2026-07-31 (금) 개발일지
오늘은 옵시디언 수동 동기화 프로세스를 정리했다. 6월에 죽어있던 collector 파이프라인이 지금은 살아서 돌고 있었는데, 유니코드 정규화 문제로 일부 폴더가 제대로 매칭되지 않고 있었다. 그걸 발견하고 고치는 과정에서 macOS 파일시스템의 NFD 자모 분해 동작을 처음 이해했다.
옵시디언 collector 파이프라인 — macOS 유니코드 정규화 불일치로 폴더명 매칭 실패
collect.py 가 매주 돌면서 다운로드 폴더의 파일들을 옵시디언으로 옮기는 작업인데, 지난 6월 말에는 exit 127로 완전히 죽어있었다. 지금 상태를 직접 확인해봤더니 현재는 살아서 돌고 있다. 하지만 일부 폴더만 자꾸 매칭이 안 되고 있었다.
처음엔 단순히 매칭 로직이 깨진 줄 알았다. live_map.json 에 등록된 폴더명과 실제 로컬 폴더명을 비교하는 딕셔너리 키 검사를 돌려봤는데, “사주”와 “투자보고서” 두 폴더만 계속 안 맞았다. 리스트 출력해보니:
live_map.json 에 등록된 폴더:
- 사주 (NFC, 조합형 한글)
- 투자보고서 (NFC)
실제 로컬 폴더 (macOS 반환):
- 사주 (NFD, 자모 분해됨)
- 투자보고서 (NFD)
macOS 파일시스템(HFS+)이 반환하는 경로는 NFD(Normalization Form Decomposed) 형태라서, 한글 문자가 초성·중성·종성으로 분해되어 있다. 반면
live_map.json은 사용자가 직접 입력한 NFC(조합형)로 저장되어 있었다.
GitHub 저장소에 commit 할 때는 NFC로 정규화되기 때문에 ASCII 파일명이나 영문 폴더는 아무 문제가 없었다. 한글만 깨졌다.
처음 시도는 모든 게시글의 OG 이미지를 미리 다 self-host 하는 backfill 스크립트 를 만드는 것이었다. 94개 글 중 80개는 잘 받았지만, 14개가 여전히 429였고 — 무엇보다 저장소를 이미지로 채우고 싶지 않다 는 제약이 더 컸다. 방향을 틀었다.
진짜 원인을 찾기 위해 collect.py 의 폴더 매칭 로직을 한 줄씩 따라가봤다. 딕셔너리 lookup 직전에 두 문자열을 유니코드 정규화 함수로 비교 해봤다:
import unicodedata
live_map_key = "사주" # NFC
local_folder = "사주" # NFD (macOS 반환)
print(unicodedata.normalize('NFC', local_folder) == live_map_key) # True
이 한 줄이 모든 걸 바꿨다. 문제를 정확히 찾았으니, 해결책은 간단했다.
collect.py 의 폴더 매칭 부분에 NFC 정규화를 박아 넣었다:
def normalize_path(path):
return unicodedata.normalize('NFC', path)
# 매칭 로직
for local_folder in os.listdir(downloads_path):
normalized = normalize_path(local_folder)
if normalized in live_map:
# 매칭 성공
다시 돌려봤더니 17/18 폴더가 정확히 매칭 됐다 (드롭쉬핑 폴더는 git 추적 대상이 아니라 정상). 사주 7/16개, 투자보고서 3/24개가 새로 주입되는 걸 확인했다.
바뀐 점
- 모든 폴더명을 NFC로 정규화한 뒤 매칭 시도
- 한글 폴더 인식률 17/18 → 18/18 (100%)
- 매주 자동 동기화 정상 작동 재개
검증: 다음 주 스케줄 돌았을 때 새로 추가된 폴더 3개가 모두 제대로 sync 되는 걸 로그로 확인했다.
남은 과제: GitHub Actions 의 weekly-papers.yml 에 등록된 GeekNews 주간 논문 요약 루틴이 따로 있는데, 그쪽도 한 번 정리할 예정.
오늘의 한줄
파일시스템 수준의 유니코드 동작을 모르면 국제화 버그는 영원히 찾을 수 없다 — 로그만 봐서는 절대 안 보인다.