← 블로그

브라우저도 API 키도 없이 중국어 여행 지도를 한 묶음 만든 이야기

AI/LLM 엔지니어링 여행

나흘간의 홍콩 여행을 준비하면서, 원한 건 단순했습니다. 들르는 곳마다, 영어가 아니라 간체 중국어로 라벨이 붙은 또렷한 지도 한 장씩. 핀만 하나 찍은 영어 지도도, 링크 더미도 아니라. 열두 곳 — 호텔, 박물관, 오션파크, 피크 트램, 공항 — 각각을, 인쇄해서 책자에 끼워 넣을 한 장의 깔끔한 스크린샷으로.

그래서 샌드박스 웹 세션에서 도는 Claude Code에 만들어 달라고 했습니다. 5분이면 끝날 심부름인 줄 알았는데, "중국어로 된 홍콩 지도"가 왜 생각보다 어려운지를 둘러보는 작은 여정이 됐습니다 — 그 안에는 바로 이런 종류의 작업을 더 어렵게 만들려고 존재하는 좌표계까지 있었습니다.

브라우저 없이, API 키 없이

가장 무난한 방법 — 지도 사이트를 열고, 언어를 중국어로 바꾸고, 각 지점을 스크린샷하는 것 — 은 두 번 막혔습니다. 이 세션에는 조작할 브라우저가 없었고, 깔끔한 정적 지도 API는 하나같이 과금되는 키를 요구합니다. 이 우회는 오히려 단점이 아니라 장점이었습니다. Google과 OpenStreetMap은 홍콩을 이중 언어 또는 영어 우선으로 라벨링합니다. 진짜 중국어 라벨을 원하면 중국 지도 제공자가 필요합니다. 답은 AutoNavi(高德) 지도 타일이었습니다. 홍콩을 간체 중국어 지명 — 海洋公园, 太平山顶, 尖沙咀 — 으로 렌더링해 줍니다. 현지에 도착해 표지판과 앱에서 보게 될 바로 그 이름들입니다. 계획은 이렇습니다. 원시 256×256 지도 타일을 받아, 파이썬의 Pillow로 한 장씩 손으로 이어 붙인다.

아무도 알려주지 않는 좌표계

여기 한 시간을 잡아먹은 함정이 있습니다. 중국 지도 제공자는 법적으로 GCJ-02 — 흔히 "화성 좌표"라 불리는 난독화된 좌표계 — 를 써야 합니다. 이것은 실제 WGS-84 위경도에 의도적이고 비선형적인 오프셋을 더합니다. 실제 GPS 좌표를 중국 지도에 그대로 얹으면, 핀은 수백 미터 떨어진 곳 — 길 건너 건물 안이나, 아예 항구 한가운데 — 에 떨어집니다. 이 오프셋 자체가 목적입니다. 정밀한 지리 데이터에 국가가 깔아 둔 과속방지턱인 셈입니다.

그래서 모든 좌표는 타일 계산에 들어가기 전에 표준 WGS-84 → GCJ-02 변환을 한 번 거쳐야 했습니다. 중심점을 화성 좌표로 옮기고, 그 옮긴 점 둘레에서 타일을 받고, 마커를 정중앙에 놓아 어긋난 지도와 맞춥니다. 틀리면 모든 지도가 시치미를 뗀 채 자신만만하게 틀립니다. 제대로 하면 아무도 알아채지 못합니다 — 그게 바로 지도가 하는 일의 전부입니다.

지도를 그리다

좌표 문제가 풀리면 나머지는 이미지 배관 작업입니다. 각 지점에 대해, 어떤 타일이 그 영역을 덮는지 계산하고, 받아서 760픽셀 폭 카드에 이어 붙이고, 한가운데에 물방울 모양 핀을 떨어뜨리고, 그 위에 중국어 지명과 일련번호, 여행 며칠째인지를 담은 헤더 띠를 얹습니다. 중국어 텍스트에는 CJK 지원 폰트가 필요한데, 샌드박스에 마침 WenQuanYi Zen Hei가 들어 있어 충분했습니다.

가장 마음에 든 건 검증 단계였습니다. 손으로 입력한 좌표는 딱 "맞는 것 같지만 사실은 애매한" 부류라, 렌더링 후 Claude Code는 자기 출력 이미지를 다시 읽어, 각 핀을 그 아래 라벨이 붙은 지형지물과 대조했습니다 — 과학관 핀이 정말 香港科学馆 위에 있나, 아니면 한 블록 북쪽으로 어긋났나? 핀 몇 개는 조금씩 옮겨졌고, 스타페리, 피크 트램 역, 공항은 모두 정확히 자리를 잡았습니다. 만들고 나서 들여다보는 루프 — 들여다보는 쪽과 만든 쪽이 같은 존재일 때는, 지금도 조금 새롭습니다.

현지화는 번역이 아니다

지도는 쉬운 쪽이었습니다. 그 주변의 말이야말로 사람 냄새 나는 부분이었습니다. 독자는 본토 표준 중국어를 읽는 사람들인데, 여행 책자는 어느새 홍콩 광둥어 말투로 미끄러져 있었습니다. 저는 호텔을 "地铁站上盖"라고 적었었는데 — "上盖"는 "역 바로 위에 지었다"는 뜻의, 흠잡을 데 없이 홍콩스러운 부동산 용어지만 본토 독자에게는 거의 통하지 않습니다. 이건 "就在地铁站楼上"가 됐습니다. 이어서 "离港"→"返程", "手信"→"伴手礼", 그리고 "有得逛"(광둥어 문법 구조)→"能逛".

음식은 반대 처리가 필요했습니다. "烧味饭", "炖奶", "滑蛋"은 광둥어 음식 이름이지만, 실제 메뉴에 적힌 실제 이름이라 "고치면" 오히려 틀리게 됩니다. 그래서 이름은 그대로 두고 표준 중국어 주석을 달았습니다 — 烧味饭(即烧腊饭:叉烧、烧鹅、烧肉饭). 식당 자체는 한 차례 피드백을 거쳐 개별 지도 페이지를 통째로 없앴습니다. 오션파크로 가듯 저녁을 먹으러 내비게이션하지는 않으니까요. 그래서 각 날짜 일정에 텍스트로 남기고, 지도 색인에서는 물러났습니다. 이 가운데 어느 것도 사전적 의미의 번역이 아닙니다. 말투이고, 방언이며, 어떤 단어가 언제 고쳐야 할 지역어이고 언제 남겨 둘 고유명사인지를 가려내는 일입니다.

여기서 얻은 것

이건 제가 거듭 도달하는 자리로 떨어집니다 — 유한하고 검증 가능한 작업일수록 일이 가장 빨리 나아갑니다. 타일을 이어 붙이고, 알려진 좌표 변환을 적용하고, 핀이 라벨 위에 놓였는지 확인하고 — 각 단계마다 눈으로 확인할 수 있는 정답이 있습니다. 이는 보안 점검과 컴플라이언스 도구 작업에서 느끼는 바와 운율이 맞습니다. GCJ-02로의 우회는 "찾아내긴 번거롭지만 일단 알면 사소한" 종류의 도메인 지식 — 바로 떠넘길 가치가 있는 것입니다.

판단은 제 몫으로 남았습니다. 어느 열두 곳을 "주요" 지점으로 칠지, 식당에는 지도가 필요 없다는 것, 본토 표준 중국어 독자가 "上盖"를 해독하게 해선 안 된다는 것. 완성된 책자 — 열두 장의 중국어 지도, 날짜별 일정, 그리고 인쇄할 수 있는 PDF 하나 — 는 브라우저도 API 키도 없는 샌드박스에서 나왔습니다. 1년 전이라면 이게 더 쉬운 쪽 버전이라고는 짐작도 못 했을 겁니다.

esc