Figma 퍼블리싱 파이프라인 09. 세션 재개와 스코프 고정
비교를 기계에 넘기고 나서 정확도는 올라갔는데, 실제로 며칠 쓰다 보니 다른 게 걸리기 시작했다.
Phase 7까지 잘 돌다가 Phase 8에서 실패하면 Phase 0부터 다시 돌려야 했다. Figma API 타임아웃 한 번에 몇 분이 날아갔다.
Figma 파일이 크면 API 응답이 수십 MB짜리 JSON이 된다. 사용자는 섹션 하나만 퍼블리싱해달라고 했는데 파이프라인은 파일 전체를 들고 다니고 있었다.
LLM을 쓰는 단계가 셋이라 토큰이 3,500쯤 나왔다.
선택한 범위를 계약으로 못 박았다
Phase 0.5에서 사용자가 섹션을 고르면, 그 뒤 모든 단계는 그 범위 밖으로 나가지 않는다. 스코프 밖 노드를 처리하려 하면 즉시 에러를 낸다.
{
"scope": {
"selected_root_node_ids": ["20530:86930"],
"mode": "strict_subtree_only"
}
}전에는 사용자가 이 섹션을 골랐으니 이 섹션 위주로 보면 되겠지 하는 암묵적인 규칙이었다. 명시적인 계약으로 만드니까 각 단계 스크립트가 훨씬 단순해졌다. 내 입력의 scope에 없는 노드는 처리하지 않는다는 규칙 하나만 지키면 된다.
TypeScript로 치면 주석으로 "여기엔 이 값만 온다"고 적어두는 것과 타입으로 좁혀두는 것의 차이에 가깝다. 규칙을 지키는 책임이 사람에서 코드로 넘어간다.
중간 결과를 세션 디렉토리에 남겼다
모든 단계 결과를 파일로 저장한다.
/tmp/figma_publish_sessions/
└── pub_20260409_143022_abc12345/
├── scope.json
└── phase_outputs/
├── phase0.json
├── phase05.json
├── phase06.jsonPhase 3까지 끝난 상태에서 실패하면 --session pub_20260409_143022_abc12345로 재개한다. Phase 3 결과가 이미 있으니 Phase 4부터 시작한다.
체감이 컸다. Figma API가 한 번 타임아웃 나도 처음부터 안 해도 된다.
고른 섹션만 잘라내 4.8MB로 줄였다
Phase 0.5 직후에 선택된 섹션의 하위 트리만 추출해 별도 스펙을 만든다. 원본 11MB가 4.8MB로 줄었고, 이후 단계는 이 작은 JSON만 본다.
데이터를 줄인 게 속도만의 문제는 아니었다. 관계없는 노드가 섞여 있으면 매칭 단계에서 엉뚱한 후보가 잡힌다. 볼 필요 없는 걸 아예 안 보이게 하는 쪽이 정확도에도 도움이 됐다.
Props를 대충 보던 걸 별도 단계로 분리했다
기존에 자주 틀리던 게 컴포넌트 props였다. Badge의 colorPalette가 green인지 grey인지를 놓치는 식이다. 전체 노드를 훑는 김에 같이 보다 보니 빠뜨렸다.
Phase 0.6을 따로 두고 선택된 섹션의 자식 노드를 하나씩 개별 분석하게 했다. componentPropertyValues에서 variant, colorPalette, size 같은 열거형 props를 명시적으로 뽑는다.
디자이너 메모는 참고만 하게 했다
Figma에 디자이너가 남긴 annotation이나 description이 있을 때 이걸 어디에 둘지가 애매했다. IR에 섞으면 코드에는 없는 정보가 diff로 잡혀서 비교 정확도가 떨어진다. 그렇다고 버리면 디자이너 의도를 놓친다.
annotationGuidance라는 별도 필드에 담고 참고 전용으로 정했다. LLM이 코드를 만들 때 읽기는 하되 Design IR이나 diff 계산에는 절대 섞지 않는다.
비교에 쓰는 데이터와 판단에 참고하는 데이터를 같은 그릇에 담지 않는 게 요점이었다.
막힌 지점과 원인
| 문제 | 원인 | 해결 |
|---|---|---|
| 중간 실패 시 처음부터 재실행 | 단계 결과가 메모리에만 있고 남지 않음 | 세션 디렉토리에 단계별 출력 저장 후 --session으로 재개 |
| 선택하지 않은 영역까지 분석 | 전체 Figma 데이터를 그대로 들고 다님 | 선택 섹션 하위 트리만 추출해 11MB에서 4.8MB로 축소 |
| 스코프 밖 노드가 섞여 들어옴 | 범위가 암묵적 규칙이라 강제되지 않음 | strict_subtree_only 계약으로 명시하고 위반 시 에러 |
| 컴포넌트 props를 자주 놓침 | 전체 노드를 훑으며 함께 처리 | Phase 0.6에서 자식 노드를 개별 분석 |
| LLM 토큰 3,500 | LLM 단계가 셋 | 설계서와 코드 생성 둘로 줄여 2,200 |
안정성과 효율은 확실히 올라갔다. 대신 비교 엔진을 새로 만들면서 이전의 정밀한 매칭 단계와 여덟 가지 diff 타입을 버리고 더 단순한 방식으로 갈아탔다. 지금 상태는 정확도는 이전이 낫고 안정성은 지금이 나은, 어느 쪽도 완전하지 않은 자리다.