Projects About

빌드 로그 페이지에 언어 pair 기능 추가 — 10번 배포, 스크린샷 디버깅

“좋아. 이게 맞아!”

이 한 마디가 나오기까지 배포를 10번 넘게 했다. 스크린샷을 5장 찍어 Claude에게 보여줬다. 세션이 13개 이어졌다. 총 tool call은 약 400회.

TL;DR 포트폴리오 사이트의 빌드 로그 탭에 한국어/영어 pair 기능을 추가했다. 같은 내용의 두 글을 하나의 카드로 묶고, 언어 토글로 전환하는 방식. 생각보다 엣지 케이스가 많았고, 디자인까지 toss.tech 스타일로 정리하면서 완성됐다.

발단: 글이 두 개인데 왜 카드가 두 개야

빌드 로그 페이지에는 한국어 글과 영어 글이 따로 올라간다. 같은 내용을 두 언어로 쓰는 구조다. 파일명에 -ko, -en이 붙고, pair 필드로 서로를 참조한다.

문제는 목록 페이지에서 이 두 글이 카드 두 개로 나온다는 거다. 같은 내용인데 두 번 보이는 건 좀 이상하다. 사이트에 글이 하나 있으면 카드도 하나가 보여야 한다.

나: "build logs 탭에서 글 두 개가 같은 건데, 달라 보여. 파랑색/초록색 태그가 다른 이유는?"

이게 시작이었다.

첫 번째 접근: Language Filter 사이드바

처음엔 Language Filter를 만들었다. 사이드바에 한국어/영어 필터 버튼을 두고, 선택한 언어의 글만 보여주는 방식.

배포했다. 확인했다.

이상했다. 사이드바의 Language Filter 자체가 어색했다. 글 목록 옆에 필터가 뜨는 건 UI적으로 불필요하게 복잡했다.

나: "뭔가 좀 어색해. 어떻게 하면 좋을지 말해봐"

세 가지 안이 나왔다. 첫 번째 안이 가장 깔끔했다. Language Filter를 없애고, pair된 글을 하나로 묶어서 언어 선택 버튼을 카드 안에 넣는 방식.

나: "1번으로 해보자. 필터 없애고, 양쪽 언어 다 보여줘. pair가 있는 경우 하나로 묶어서 언어 선택을 제공해줘."

두 번째 접근: 카드 안에서 토글

이 구조의 핵심은 두 가지 데이터를 묶는 로직이다.

pair 필드가 있는 글 → 상대방 글과 묶어서 하나의 항목으로 만든다. pair 필드가 없는 글 → 그냥 단독으로 표시한다.

Astro의 Content Collections에서 전체 글 목록을 가져온 뒤, pair 기준으로 중복을 제거하는 방식으로 구현했다. pair가 있으면 주 언어를 정해서 대표 글로 쓰고, 토글 버튼으로 다른 언어로 전환하는 구조.

배포했다. 확인했다.

두 글이 여전히 따로 보였다.

나: "두 글이 아직도 따로 보여"

pair 로직이 클라이언트 사이드에서 제대로 처리되지 않고 있었다. 빌드 타임에 pair를 묶는 게 아니라, 렌더링 후에 JavaScript로 숨기는 방식이었는데 — 이게 문제였다. 언어 토글 상태에 따라 숨겨야 하는 카드가 제대로 처리되지 않았다.

세 번째 시도.

이번엔 Astro 빌드 타임에 pair를 묶어서 PairedPost 자료구조를 만들었다. 페이지에 넘기는 데이터 자체가 이미 묶인 상태. JavaScript는 토글 상태만 관리하고, 숨기기/보이기는 CSS class로 처리했다.

나: "계속 해줘"
(배포)
나: "확인해봐"
나: "화면 스크린샷 찍을게"
(이미지)
나: "좋아. 이게 맞아!"

Session 20에서만 62번의 tool call이 나갔다. 39분. 이 한 기능을 위해서.

상세 페이지도 마찬가지

목록 페이지를 고쳤더니 상세 페이지가 문제였다.

글 카드를 클릭하면 /build-logs/[slug] 페이지로 간다. 여기서도 pair 글이 있으면 언어 토글이 되어야 하는데, 상세 페이지는 완전히 별개 로직이었다.

나: "거기서도 마찬가지로 이 글에 pair 글이 있으면 언어 toggle로 언어 변환이 되어야 해"

상세 페이지 구현이 더 까다로웠다. 현재 slug에서 pair slug를 찾고, 토글 시 URL 자체를 바꿔야 한다. /build-logs/2026-03-21-portfolio-site-ko/build-logs/2026-03-21-portfolio-site-en 이런 식으로.

중간에 한 번 완전히 망가졌다.

나: "이상하게 됐어. 이전 상태로 되돌려줘"

Git에 커밋이 되어 있어서 되돌리는 건 금방이었다. 다시 접근. 이번엔 페이지 이동 방식이 아니라 콘텐츠 교체 방식으로 바꿨다. URL은 유지하고, JavaScript로 현재 페이지의 콘텐츠를 fetch해서 교체하는 구조.

Session 21에서 75번의 tool call. 1시간 13분.

엣지 케이스의 엣지 케이스

기능이 동작하기 시작하면서 예상 못한 엣지 케이스들이 연달아 나왔다.

pair 없는 글은 어떻게? pair가 있는 글은 선택한 언어로 필터링한다. 그런데 pair 없는 글은? 언어에 상관없이 항상 보여야 한다. 그렇지 않으면 영어 글만 있는 건 영어 선택 시에만 보이게 되는데, 이건 콘텐츠가 사라지는 것처럼 느껴진다.

나: "한국어로 전환할 때, pair있는 글은 한국어로, pair없는 글은 그냥 언어에 상관없이 나오게 해줘"

태그 색상이 다른 이유? 한국어 글 카드에는 초록 태그, 영어 글 카드에는 파랑 태그가 붙어 있었다. pair로 묶으면 같은 카드인데 언어에 따라 태그 색이 달라지는 이상한 현상. 스타일 로직을 통일하는 수정이 한 번 더 필요했다.

글 개수가 맞지 않는 문제. 영어 선택 시 3개만 나온다고 했다. 알고 보니 pair 없는 한국어 글이 영어 선택 시 숨겨지고 있었다. 위 수정 이전의 버그.

각각 별도 세션, 별도 배포였다.

스크린샷으로 디버깅하는 방식

이번 작업에서 특이한 점은 디버깅 방식이었다. 코드를 읽으면서 찾는 게 아니라, 배포하고 → 스크린샷 찍어서 보내고 → Claude가 보고 판단하는 방식이었다.

웹에서 실제로 어떻게 보이는지를 텍스트로 설명하는 것보다 이미지가 훨씬 정확하다. “왼쪽에 필터가 이상하게 붙어 있어”보다 이미지 한 장이 백 마디다.

단점도 있었다. 스크린샷으로는 JavaScript 에러나 서버 로그를 볼 수 없다. 클릭이 안 된다는 시각적 증상을 보고 원인을 추론해야 했는데, 그 추론이 틀리면 배포를 또 해야 했다.

나: "언어 토글 클릭이 안 돼"
(이미지)
나: "토글 클릭이 됐는데, 아직도 안 돼"

클릭 이벤트가 달리지 않은 상태로 배포됐다. 이걸 확인하려면 브라우저 콘솔이 필요한데 이미지로는 알 수 없다. 결국 WebFetch로 배포된 페이지 소스를 긁어와서 이벤트 핸들러 코드가 포함됐는지 확인하는 방식으로 해결했다.

디자인 정리

기능이 되고 나면 디자인을 정리할 차례였다.

빌드 로그 탭이 전체적으로 홈페이지와 스타일이 달랐다. 홈페이지는 toss.tech 영향을 받은 클린한 라이트 테마인데, 빌드 로그 탭은 카드 배경, 글꼴 크기, 여백이 제각각이었다.

나: "이 부분 좀 더 나이스하게 만들어줘. 느낌은 지금 포트폴리오에서 사용중인 toss.tech 스타일이야"
나: "배경색은 통일해야 할 것 같아. build logs 탭 전체 디자인을 홈페이지 레이아웃 맞춰줘"

toss.tech 스타일의 핵심은 여백이다. 카드 패딩, 섹션 간격, 텍스트 크기 모두 시원하게 잡는 게 포인트. 컬러는 최소화하고 초록 액센트 하나만 쓴다.

목록 페이지와 상세 페이지를 각각 정리했다. Session 23-25, 약 1시간 30분.

숫자로 보면

항목수치
관련 세션 수13개 (session 13~25)
총 tool calls약 400회
배포 횟수12회
스크린샷 확인5회
가장 많은 tool call 세션session 21 (75회, 1시간 13분)

기능 자체의 복잡도보다 반복 사이클이 더 많은 시간을 잡아먹었다. 배포 → 확인 → 수정 → 배포. Cloudflare Pages 배포가 1~2분이지만, 13번 반복하면 20분이다.

코드 리뷰도 한 번 돌렸다

기능 완성 후 전체 코드를 리뷰했다.

나: "이 코드 전체 리뷰 해줘. 좋지 않은 패턴이 있으면 개선해줘"

지적된 것 중에 실제로 고친 건 “localStorage 직접 접근과 상태 관리의 분리” 문제였다. 언어 토글 상태를 여러 곳에서 각각 localStorage를 읽어서 처리하고 있었는데, 한 곳에서만 읽고 나머지는 prop으로 받는 구조로 정리했다.

나머지 지적들은 현재 구조에서 오버엔지니어링이 될 것 같아서 패스했다.

결론

기능 하나가 세션 13개, 배포 12회, 400 tool call을 잡아먹었다.

엣지 케이스가 많았다. pair 없는 글 처리, 태그 스타일 통일, URL 기반 토글, 상세 페이지 콘텐츠 교체. 각각은 작은 문제였지만, 배포하고 확인해야 보이는 문제들이라 사이클이 계속 돌았다.

배포 전에 더 많은 엣지 케이스를 예측할 수 있었을까? 어느 정도는. 하지만 “실제 사이트에서 어떻게 보이는지”는 배포 전에 100% 예측하기 어렵다. 스크린샷으로 확인하는 방식이 지금으로선 가장 현실적이다.

배포가 빠를수록 피드백 루프가 짧다. Cloudflare Pages 1분 배포가 이 작업 방식의 핵심이었다.

Comments 0

0 / 1000