피그마 폰트 누락 디버깅 회고: AI는 내가 정의한 문제만큼만 똑똑했다

thumb1.png

이 글은 웹셀러(디.패밀리)가 실제로 겪은 피그마 로컬 폰트 누락 버그를 AI와 함께 추적한 디버깅 회고다. 막혀 있던 며칠을 푼 건 더 좋은 프롬프트가 아니라 문제를 정확히 짚은 한 번의 질문 전환이었다. 시점은 2026년 5월 31일~6월 1일 기준이다.

증상 — 로컬 폰트만 전부 "누락"으로 떴다

2026년 5월 31일 아침, 맥에서 피그마 데스크톱을 켜자 직접 설치해둔 로컬 폰트가 일제히 누락(missing)으로 표시됐다. 이상한 건 폰트 목록에 이름은 멀쩡히 보였다는 점이다. 프리텐다드, 지마켓 산스 같은 폰트를 골라 적용해도 글자는 바뀌지 않고, 다시 보면 누락 표시가 붙었다. 그런데 맥 시스템 폰트는 정상 적용됐다. 로컬 폰트는 다 죽고 시스템 폰트만 살아 있는 비대칭이 첫 단서였지만, 그때는 그 의미를 읽지 못했다.

1단계 — 증상만 보고 표준 해법을 쏟아부었다

증상이 "폰트 누락"이었으니 자연스럽게 폰트와 그 주변을 의심했다. AI에게 상황을 던지고 함께 시도한 목록은 이렇다.

  • 피그마 재설치
  • 맥 quarantine(격리) 속성 제거
  • 폰트 캐시 삭제
  • LaunchServices 데이터베이스 재구축
  • 재부팅(두 번)
  • 남아 있던 헬퍼 상태 초기화
  • 메뉴 막대 설정 토글

하나하나 "이게 원인일 수 있다"는 가설이 붙어 있었고, AI도 막힘없이 다음 시도를 제안했다. 한 번은 캐시를 지우고 재부팅한 직후 AI가 "이제 해결됐을 겁니다"라고 단언하기까지 했지만, 다시 켜보니 그대로 누락이었다. 이때 세운 가설 중 하나가 "5월 31일 맥 보안 자산 갱신이 앱 실행 환경을 조였다"였는데, 결과적으로 틀린 추측이었다. 시도 목록만 길어지고 한 발짝도 못 나갔다. 지금 보면 문제는 분명하다. 우리는 표면 증상만 쫓았을 뿐, 피그마가 로컬 폰트를 실제로 어떻게 불러오는지 그 동작 원리를 몰랐다.

2단계 — 증상 대신 동작 원리를 봤다

질문을 바꿨다. "피그마는 대체 내 로컬 폰트 폴더의 파일을 어떻게 읽어오는가?" 구조는 이랬다. 피그마 렌더러는 샌드박스 안에서 돌기 때문에 로컬 폰트 폴더를 직접 읽지 못한다. 그래서 피그마는 별도의 작은 헬퍼 프로세스(FigmaAgent)를 띄워, 폰트 파일을 읽어 그 실제 바이트를 로컬 웹 서버로 넘겨준다. 그것도 하나가 아니라 둘이다. http는 127.0.0.1:44950, https는 :44960으로 동시에 띄운다. 데스크톱 앱이든 브라우저판이든 둘 다 이 헬퍼에 의존한다.

여기서 첫 단서가 풀렸다. 시스템 폰트가 멀쩡했던 건 헬퍼를 거치지 않고 OS가 직접 로드하기 때문이다. 헬퍼를 안 타는 경로만 정상이었던 것이다. "헬퍼를 타는 폰트는 다 죽고 안 타는 폰트만 산다"는 건 폰트 파일도 캐시도 아니라 헬퍼-서버 경로 자체가 끊겼다는 신호였다. 그제서야 질문이 분명해졌다. "폰트 바이트를 넘겨주는 그 포트가 지금 열려 있긴 한가?"

3단계 — 데이터가 흐르는 경로를 직접 찔러봤다

추측을 멈추고 실제 경로를 확인했다. 헬퍼가 쓴다는 포트가 떠 있는지부터 봤다.

lsof -iTCP:44950 -sTCP:LISTEN
curl http://127.0.0.1:44950/

포트가 닫혀 있었다. 아무도 44950을 듣고 있지 않았다. 폰트 이름 목록은 캐시에서 읽어와 보이는데, 정작 바이트를 줄 서버가 없으니 적용이 전부 누락으로 떨어진 것이다. 그런데 헬퍼 로그에는 "listening on 44950"이 분명히 찍혀 있었다. 로그는 떴다는데 포트는 닫혀 있다 — 이 모순이 진짜 단서였다. 로그를 끝까지 읽자 답이 나왔다. 워커 스레드들이 "Too many open files"(EMFILE, errno 24)로 줄줄이 패닉하면서 방금 만든 리슨 소켓까지 같이 무너뜨리고 있었다. 로그의 "listening"은 소켓이 잠깐 떴다 곧장 닫혔다는 뜻이었다.

왜 파일 디스크립터가 부족했나. 헬퍼는 http·https 두 서버를 띄우고, 각 서버가 CPU 코어 수만큼 워커 스레드를 만든다. 이 기기는 36코어 iMac Pro라 워커가 약 72개, 이들이 함께 필요로 하는 열린 파일 수가 약 328개였다. 그런데 피그마 앱이 자식으로 헬퍼를 띄우면 맥의 기본 소프트 한도인 256개를 물려받는다. 328은 256을 넘으니 워커가 EMFILE로 죽고, 소켓이 무너진 것이다.

진짜 원인 — 바이너리가 아니라 파일 디스크립터 한도

가설을 깨끗하게 검증했다. 같은 헬퍼 바이너리를 터미널 셸에서 직접 띄우면 44950을 곧바로 물고 올라왔고, curl을 날리면 폰트 바이트를 HTTP 200으로 정상 응답했다. 셸이 물려주는 한도는 약 1,048,576개라 워커 72개가 전부 무사히 떴기 때문이다. 바이너리는 멀쩡했다. 차이는 오직 실행 환경이 물려준 파일 디스크립터 한도뿐이었다. 한 터미널에서 ulimit -Sn 256으로 한도를 낮추니 EMFILE 패닉이 그대로 재현됐고, ulimit -Sn 8192로 올리니 정상 바인딩됐다. 원인이 못 박혔다.

그럼 왜 하필 5월 31일이었나. 그날 맥의 보안·신뢰 데이터베이스가 갱신된 건 맞지만, 그건 파일 디스크립터 한도와 무관한 우연한 시점 일치였다. 진짜 방아쇠는 (추정컨대) 피그마 업데이트가 헬퍼 워커 수를 CPU 코어 수에 비례하도록 바꾸고 https 서버를 하나 더 띄우면서, fd 수요가 36코어 같은 고코어 머신에서만 256을 넘긴 것이다. 코어 수가 적은 맥은 256 아래에 머물러 멀쩡했다 — 이 비대칭이 "맥 업데이트 탓"이라는 추측을 더 그럴듯하게 만들었던 함정이었다.

해결은 헬퍼의 실행 환경에 파일 디스크립터 한도를 넉넉히 주는 것이다. 사용자별 LaunchAgent로 소프트 리소스 한도(NumberOfFiles)를 16384로 올려두면, 워커 72개가 한도를 다 써버리지 않으니 포트가 정상 바인딩되고 폰트가 살아난다. LaunchAgent 방식이라 재부팅 뒤에도 유지된다.

<key>SoftResourceLimits</key>
<dict>
  <key>NumberOfFiles</key>
  <integer>16384</integer>
</dict>

케이스가 남긴 것 — AI 디버깅은 문제 정의 품질을 증폭한다

웹셀러가 이 사례에서 가장 크게 가져간 건 기술 디테일이 아니라 일하는 방식이다. AI 디버깅은 사용자가 정의한 문제의 품질을 그대로 증폭할 뿐이다. "폰트가 누락된다"고만 던지니 AI는 폰트·캐시·권한 주변을 그럴듯하게 빙빙 돌았다. 재설치, 캐시 삭제, 격리 해제, LaunchServices 재구축은 다 표면 증상에 붙는 표준 해법이라, 문제를 잘못 잡은 채로는 정답 근처에 못 갔다. "5월 31일 보안 갱신 탓"이라는 추측도 같은 함정이었다. 그럴듯한 외부 원인을 만들어 붙였을 뿐, 실제 데이터 경로를 확인하지 않은 가설이었다.

전환점은 더 좋은 프롬프트가 아니었다. 증상 쫓기를 멈추고 "데이터가 어디로 흐르나, 그 포트가 열려 있나"라는 진짜 메커니즘으로 시선을 옮긴 순간, 그리고 헬퍼 로그에서 EMFILE 패닉이라는 실제 에러를 직접 잡아낸 순간이었다. 추측한 원인이 아니라 포착한 에러가 문제를 못 박았다. 도구가 좋아질수록 "문제를 정확히 정의하고 진짜 에러를 포착하는 사람의 몫"이 오히려 커진다는 게 이 한 건의 결론이다.

이런 진단 감각은 웹사이트·앱을 만들고 운영하는 일과 직결된다. 헬퍼-로컬서버 구조 위에서 도는 도구를 디버깅하거나, 배포 후 환경 차이로 생기는 문제를 잡아야 하는 상황이라면 증상이 아니라 데이터가 흐르는 경로부터 의심하는 편이 빠르다. 웹셀러는 이런 관점으로 어플리케이션 제작유지보수를 다루고, 검색·AI 노출까지 보는 SEO·AEO·GEO 최적화도 같은 결로 접근한다. 진단부터 같이 정리하고 싶다면 무료 상담이 출발점이 될 수 있다.

자주 묻는 질문

피그마에서 로컬 폰트가 전부 누락으로 뜨는데 폰트 파일 문제인가요?

꼭 그렇지 않다. 폰트 목록에 이름은 보이는데 적용만 안 되고, 동시에 맥 시스템 폰트는 정상이라면 폰트 파일이나 캐시 문제보다 폰트 전달 경로가 끊겼을 가능성이 크다. 피그마는 로컬 폰트의 실제 바이트를 헬퍼 프로세스(FigmaAgent)가 띄우는 로컬 서버로 받아 오는데, 이 서버가 못 떠서 막히면 이름만 보이고 적용은 누락으로 떨어진다.

피그마는 로컬 폰트를 어떻게 불러오나요?

피그마 렌더러는 샌드박스 안에서 돌아 로컬 폰트 폴더를 직접 읽지 못한다. 대신 별도의 헬퍼 프로세스(FigmaAgent)가 폰트 파일을 읽어 그 바이트를 로컬 웹 서버로 넘겨준다. http는 127.0.0.1:44950, https는 :44960으로 둘을 동시에 띄우고, 피그마는 그 서버에서 폰트 데이터를 받아 적용한다. 데스크톱 앱과 브라우저판 모두 이 헬퍼에 의존한다.

시스템 폰트는 되는데 로컬 폰트만 안 되는 이유는 뭔가요?

시스템 폰트는 헬퍼-로컬서버 경로를 거치지 않고 OS가 직접 로드하기 때문이다. 그래서 헬퍼가 띄우는 포트가 닫혀 있으면 그 경로를 타는 로컬 폰트만 누락되고, 경로를 안 타는 시스템 폰트는 정상으로 보인다. 이 비대칭 자체가 폰트 전달 포트를 의심해야 한다는 신호다.

피그마 로컬 폰트 누락의 진짜 원인은 무엇이었나요?

헬퍼의 파일 디스크립터(열린 파일) 한도 부족이었다. 헬퍼는 http·https 두 서버를 띄우고 각 서버가 CPU 코어 수만큼 워커 스레드를 만든다. 36코어 맥에서는 워커가 약 72개로 불어나 열린 파일 약 328개가 필요한데, 피그마 앱이 자식으로 헬퍼를 띄우면 맥 기본 소프트 한도 256개를 물려받는다. 그래서 워커가 EMFILE("Too many open files")로 패닉하며 리슨 소켓이 무너진다. 한도를 16384로 올려주는 LaunchAgent를 두면 포트가 정상 바인딩되고 폰트가 살아난다. 5월 31일이라는 시점은 맥 보안 갱신과 무관한 우연한 일치였다.

AI에게 버그를 맡길 때 왜 잘 안 풀릴 때가 있나요?

AI 디버깅의 품질은 사용자가 정의한 문제의 품질을 증폭하는 쪽으로 작동하기 때문이다. 표면 증상만 던지면 AI는 그 증상에 붙는 표준 해법을 빠르고 그럴듯하게 제안하지만, 문제를 잘못 잡았다면 정답에 닿기 어렵다. 이번 사례에서도 "맥 보안 갱신 탓"이라는 그럴듯한 추측이 한참 발목을 잡았다. 데이터가 흐르는 경로를 직접 확인하고 로그에서 실제 에러(EMFILE 패닉)를 포착해 진짜 메커니즘을 짚어주자, 그때부터 AI가 그 지점을 깊게 파기 시작했다.

견적 문의