본문으로 건너뛰기

Figma 퍼블리싱 파이프라인 12. 전면 재구현과 부분 패치의 용도 분리

·9 min read·12 / 12

publish는 처음부터 새로 만드는 상황에 맞춰져 있다. 그런데 내가 실제로 맡는 작업은 대부분 이미 구현된 페이지에 시안 변경분만 반영하는 일이었다. publish-v4를 따로 설계했고, 오늘 둘을 나란히 놓고 실무 기본값을 v4로 바꿨다.

같은 작업인데 접근이 정반대였다

publish는 전면 재구현이고 publish-v4는 지금 코드와 Figma가 뭐가 다른지 비교한 뒤 그 차이만 패치한다.

항목publishpublish-v4
모드전면 재구현비교 후 수정
입력Design IR만Design IR + Code IR
출력전체 구현 지시HIGH/MED/LOW 등급의 diff 항목만
용도새 페이지 첫 구현기존 페이지에 시안 변경분 반영

여기서 IR(Intermediate Representation, 중간 표현)은 Figma 디자인이나 소스 코드를 파이프라인이 다루기 쉬운 구조로 바꾼 데이터다. Design IR은 Figma 노드 트리를, Code IR은 실제 소스 코드를 같은 모양으로 추상화한 결과물이다.

Phase 번호는 그대로 두고 v4에 비교와 진단 단계를 끼워 넣었다.

v4가 추가한 건 코드를 IR로 파싱하는 Phase 5, Design IR 노드와 Code IR 노드를 텍스트·역할·위치 등 7단계 기준으로 잇는 Phase 7, 매칭된 짝을 비교해 등급을 매기는 Phase 8, 사람이 읽는 리포트를 만드는 Phase 9다. 반대로 Figma 스크린샷을 뽑던 Phase 4.7은 뺐다.

옵션값과 검증 방식도 같이 바꿨다

항목publishv4
Design IR snippet max_chars30,00010,000
snippet의 빈 container그대로 포함필터링
Phase 4.7 Figma 스크린샷포함제거
Phase 5~9 비교 분석없음필수
Phase 6.5 체크리스트0개 섹션도 포함0개 섹션 건너뜀
Phase 6.5 검증Claude가 수백 행 1:1 대조Python 자동 검증 후 불일치만 전달

max_chars를 30K에서 10K로 줄인 건 snippet에 담는 정보를 추렸다는 뜻이다. 자식이 없거나 의미 없는 레이아웃 래퍼인 빈 container를 걸러내니 같은 페이지를 더 적은 토큰으로 표현할 수 있었다.

토큰이 40% 줄었다

publishpublish-v4
입력70~90K40~55K
출력15~20K12~16K

snippet 축소, Phase 4.7 제거, 0개 섹션 건너뛰기, Python 자동 검증 넷이 겹친 결과다.

Phase 4.7의 Figma 스크린샷은 원래 검증용으로 붙였는데, 추가 API 호출이 불안정해서 실패하면 파이프라인 전체가 막혔다. 토큰도 크게 먹었다. 검증에 쓰려던 장치가 실행을 방해하고 있어서 잘라냈다.

맞게 구현된 부분까지 다시 만들라고 시키고 있었다

fresh 모드는 전체를 missing_in_code HIGH로 취급한다. 이미 시안대로 잘 돼 있는 부분까지 빠졌으니 다시 만들라는 지시가 나간다. 멀쩡히 돌던 코드가 재작성 과정에서 망가지는 회귀가 여기서 나왔다.

v4는 Diff Engine이 실제로 다른 항목만 등급을 매긴다. Claude가 받는 지시가 이 부분만 바꾸라로 좁혀지니 불필요한 변경이 줄었다.

검증도 사람이 하던 방식에서 스크립트로 옮겼다. 이전에는 Claude가 체크리스트를 쭉 읽으면서 각 항목이 코드에 반영됐는지 하나씩 대조했다. 수백 행이 넘어가면 실수가 섞이고 느리고 토큰도 많이 먹었다. phase6_5_auto_check.py가 체크리스트를 파싱해 실제 코드와 비교하고, 불일치만 markdown으로 내보낸다. Claude는 그 요약만 읽는다.

기계가 확실히 판정할 수 있는 건 기계에 넘기고 판단이 필요한 것만 모델에 남기는 방향이 여기서도 통했다.

터미널이 아니면 전체 섹션이 자동 선택됐다

이전 버전에 버그가 하나 있었다. Claude Code 서브프로세스처럼 터미널이 아닌 환경에서는 섹션 선택 프롬프트가 건너뛰어지면서 전체 섹션이 자동 선택됐다. 사용자가 이 섹션만 바꿔달라고 해도 전체가 돌아갔다.

터미널이 아닐 때 exit code 10을 반환하게 바꿨다. Claude Code가 이 코드를 보고 실패로 감지해서, 사용자에게 어떤 섹션을 고를지 반드시 묻게 된다. 조용히 기본값으로 넘어가는 것보다 멈추고 물어보는 쪽이 맞았다.

--page-path /my/setting/user-info 옵션도 붙였다. Code IR 범위를 해당 _source/components 하위로 제한하니 관련 없는 컴포넌트가 비교 대상에서 빠져 diff 노이즈가 줄었다. 예전에 경로와 폴더를 손으로 매핑해 관리하던 테이블도 필요 없어졌다.

막힌 지점과 원인

문제원인해결
맞게 구현된 부분까지 재작성해 회귀 발생fresh 모드가 전체를 누락 항목으로 취급Diff Engine으로 실제 차이만 등급화
입력 토큰 70~90Ksnippet 30K, 스크린샷 단계, 전량 체크리스트snippet 10K, Phase 4.7 제거, 자동 검증으로 40% 절감
체크리스트 대조가 느리고 부정확Claude가 수백 행을 1:1로 확인phase6_5_auto_check.py가 판정하고 불일치만 전달
비터미널 환경에서 전체 섹션 자동 선택프롬프트를 건너뛰고 기본값으로 진행exit code 10 반환해 사용자에게 되묻게 함
관련 없는 컴포넌트가 diff에 포함Code IR 범위를 좁힐 수단이 없음--page-path로 대상 폴더 제한

publish를 버린 건 아니다. 새 페이지를 처음 만들 때는 여전히 fresh가 낫고, 그 뒤 반복되는 유지보수에는 v4가 낫다. 하나로 다 하려던 걸 두 개로 나눈 셈이다.