Joyuno's Dev Blog

2026-07-16 (목) 개발일지

dev-blog

오늘의 회고: 편견을 깨는 순간

오늘은 세 가지 트러블슈팅을 진행했다. Figma MCP가 read-only라는 편견을 직접 확인하고 깨는 조사, Git push 충돌 디버깅, 그리고 Flutter 리플레이 위젯트리가 빈 화면만 보이던 문제를 잡아내는 흐름이었다. 각각의 사고 전환점이 뚜렷했던 하루였다.


Figma MCP 쓰기 기능 — “read-only”라는 첫 가설이 깨진 과정

IR 피치덱 제작을 앞두고, Figma MCP가 슬라이드를 직접 생성할 수 있는지가 핵심이었다. 공식 문서상 Dev Mode는 read-only로 명시되어 있었기 때문에, 나는 처음에 “Figma MCP는 읽기 전용이다”로 가설을 세웠다.

단서 수집을 위해 Exa 검색으로 40개 결과를 분석하고, 추가로 3회 보강 검색을 더했다. 그런데 결과가 흥미로웠다. 실무자 블로그 5건이 모두 “write 가능하다”고 증언하고 있었다. 공식 문서와 실무 경험 사이의 괴리가 생겼다. 첫 가설이 흔들리기 시작했다.

진짜 원인을 잡기 위해, 공식 Figma MCP 원격 서버(https://mcp.figma.com/mcp)의 도구 목록을 직접 호출해봤다. get_design_context, get_screenshot 같은 read 도구 외에도, use_figma 라는 write 도구가 존재했다. 이 도구로 캔버스 수정, 컴포넌트 생성, 변수 편집이 가능했다. Dev Mode는 read-only지만, MCP 원격 서버는 별도의 write 채널을 가지고 있던 것이다.

결론적으로, Figma MCP는 write 가능했고, IR 피치덱 제작에 활용할 수 있었다. 다만 Figma Slides API의 학습 곡선을 고려해, 더 빠른 피드백을 위해 직접 HTML 16:9 슬라이드로 제작하는 쪽으로 방향을 틀었다. 검증으로, 생성된 ir_deck.html을 브라우저에서 열어 8페이지 슬라이드가 정상 렌더링되는 것을 확인했다.

가설 상태 근거
Figma MCP = read-only ❌ 기각 공식 원격 서버에 write 도구 존재
Dev Mode = MCP와 동일 ❌ 부분 기각 Dev Mode는 read-only지만 MCP는 별도
IR 피치덱 = Figma Slides로 제작 ⏳ 보류 HTML 직접 제작이 더 빠름

Git push 충돌 — “Everything up-to-date”가 거짓말한 이유

IR 문서를 커밋한 후 git push origin main을 실행했더니, “Everything up-to-date” 가 떴다. 그런데 원격 저장소를 확인해보니 커밋이 반영되지 않았다. 첫 반응은 “캐시가 꼬였나?”였다. git status를 확인했지만 clean. 로컬 main 브랜치를 찍어보니, 실제 작업은 tr-test 브랜치에서 하고 있었고 로컬 main은 원격보다 뒤처져 있었다.

가설의 전환: “push origin main”은 현재 브랜치가 아니라 로컬 main 브랜치를 푸시한다. 즉, tr-test에서 작업한 커밋은 전혀 포함되지 않았던 것. git branch로 현재 브랜치를 확인하고 나서야 원인을 깨달았다.

해결은 단순했다. git push origin HEAD:main으로 현재 HEAD를 원격 main에 직접 밀어주는 방식으로 변경했다. 그 후 git log origin/main에서 커밋(2fcb728)이 정상 반영된 것을 확인했다.

“Everything up-to-date”는 거짓말하지 않는다 — 대신, 내가 밀고 있는 브랜치가 무엇인지 확인하라.


Flutter 리플레이 위젯트리 — “보이지 않는 화면”이 보이기까지

iOS 시뮬레이터에서 리플레이 플레이어를 실행하면 홈 화면이 빈 화면으로 나왔다. 이전 mode A(단순 스크린샷 기반)에서는 위젯트리 렌더링이 전혀 안 되던 상태였다. 처음엔 “Flutter DevTools의 위젯트리 덤프가 제대로 안 올라오나?” 하고 flutter devtools로 직접 인스펙터를 열었다.

인스펙터 결과, 실제 위젯트리는 비어 있지 않았다. 문제는 Omnitrace 플러그인이 위젯트리 스냅샷을 제대로 포착하지 못하는 것이었다. mergesDescendants가 SemanticsFlag인지 노드 프로퍼티인지 헷갈려서, 초기 코드는 잘못된 경로로 데이터를 가져오고 있었다.

진단을 위해 WireframeBindingObserver의 콜백 로그를 찍어보니, “mergesDescendants is not a SemanticsFlag” 라는 예외가 숨어 있었다. 공식 Flutter API 문서를 다시 확인하고, 해당 프로퍼티가 RenderObject의 노드 프로퍼티임을 확인했다. 코드를 수정했다.

해결 후, 리플레이 플레이어에서 홈 화면의 “오연 / 오늘의 인연”, 오행 라벨, “준혁” 매칭 리스트, 하단 탭바 버튼 5개가 정확한 위치에 렌더링되었다. 앱 코드는 한 줄도 수정하지 않고, 플러그인 레벨에서만 처리했다.

항목 이전 (mode A) 이번 (mode B)
iOS /home 위젯트리 빈 화면 위젯 12개 정확한 위치
위젯 인식 미지원 텍스트·버튼·이미지 구분
앱 코드 수정 필요 0줄 유지

오늘의 한줄

“공식 문서와 실무 현장의 차이는 직접 까보기 전엔 알 수 없다 — MCP의 write 권한도, Git 충돌의 진짜 원인도, 위젯트리의 숨은 예외도 모두 직접 확인해야 열린다.”