사내에서 카카오 이모티콘을 하나 준비하고 있습니다. 주짓수 도복을 입은 햄스터로 32장 한 세트인데, AI가 실제 제작 공정에 어디까지 들어올 수 있는지 재보려고 시작한 일이에요.
32장을 따로따로 뽑으면 얼굴이 조금씩 다른 32마리가 나옵니다. 한 장씩 보면 괜찮은데 나란히 놓으면 세트가 아니에요. 그래서 뽑은 컷의 눈·눈썹·도복을 손으로 고쳐 인상을 맞춥니다.
여기서 걸리는 게 하나 있어요. 고치려면 부위가 따로 잡혀 있어야 합니다. 포토샵으로 치면 레이어가 나뉘어 있어야 하는데, 모델이 주는 건 통짜 PNG 한 장이거든요. 눈썹을 만지려면 눈썹이 하나의 덩어리로 인식돼 있어야 합니다.
그래서 32장을 전부 부위별로 쪼개는 도구를 만들었습니다. 처음엔 당연히 AI를 붙일 생각이었어요. 이미지에서 부위를 잘라내는 모델은 이미 널려 있으니까요.
그런데 안 썼습니다. 한 번도 안 불렀어요.
AI를 안 쓴 이유
편집기는 같은 그림을 열 때마다 같은 부위 목록이 나와야 합니다.
이게 왜 중요하냐면요. 눈이 어제는 한 덩어리로 잡혔다가 오늘은 두 덩어리로 잡히면, 사용자가 어제 저장한 편집을 어디에 붙일지 알 수 없습니다. 부위 번호가 어긋나면 저장해둔 작업이 통째로 날아가요.
AI 모델은 대체로 이걸 보장하지 않습니다. 정확도는 높은데 같은 입력에 같은 답이라는 보장이 없어요. 편집기처럼 사용자의 작업이 그 위에 쌓이는 도구에서는 정확도보다 이게 먼저입니다.
그래서 계산으로 갈랐습니다
원리는 한 문장이에요. 선을 지우면 면이 서로 끊어집니다.
이 그림은 도복도 살결도 검은 윤곽선으로 둘러싸여 있습니다. 그러니 검은 화소를 빼고 나면 도복은 도복끼리, 살결은 살결끼리 섬처럼 떨어져요. 그 섬에 번호를 붙이면 끝입니다. 파이썬 라이브러리 함수 한 줄이면 되고요.

오른쪽이 분해 결과에 부위마다 다른 색을 칠한 것입니다. 이 컷은 31개로 갈렸어요. 면 21개, 얹힌 획 9개, 실루엣 1개.
32장을 전부 돌려보니 부위 수는 적게는 13개, 많게는 54개, 평균 29.6개였습니다. 전체 1.8초, 장당 55밀리초예요. AI를 부르면 이 시간에 한 장도 못 끝냈을 겁니다.
무엇보다 몇 번을 돌려도 같은 답이 나옵니다. 편집기는 그 위에 올라가 있어요.
이름 붙이기가 훨씬 어려웠습니다
쪼개는 것보다 "이건 눈, 저건 눈썹"을 정하는 게 어려웠어요. 방법을 다섯 번 갈아엎었습니다.
| 방법 | 정확도 | 왜 실패했나 |
|---|---|---|
| 절대 높이로 자르기 | — | 표정이 납작하면 눈을 눈썹으로 읽음 |
| 위에서부터 줄 순서로 | 19% | 귀가 첫 줄을 차지해 전부 한 칸씩 밀림 |
| 몸 중심선 대칭으로 쌍 찾기 | 63% | 눕거나 기운 자세에서 11컷 탈락 |
| 얼굴 기준 대칭으로 쌍 찾기 | 75% | 엉뚱한 획이 기준점을 끌어당겨 4컷 탈락 |
| 대칭을 아예 안 봄 | 88% | 같은 높이·비슷한 크기만 봄 |
| 얼굴판을 "획을 가장 많이 품은 면"으로 | 94% | 과다 검출 0컷 |
재밌는 건 대칭을 보지 않기 시작하면서 정확도가 올랐다는 점이에요. 눈이 두 개니까 대칭으로 쌍을 찾는 게 당연해 보이잖아요. 그런데 기준점을 무엇으로 잡든 엉뚱한 획이 그 기준점을 끌어당겼습니다. 두 번 다르게 시도해서 두 번 다 실패한 뒤에 뺐어요.
남은 2컷은 06번과 18번인데, 눈이 아예 안 그려진 컷입니다. 알고리즘 문제가 아니에요.
안 될 것 같아서 막아둔 기능
이 얘기를 꼭 쓰고 싶었습니다.
면을 옮기는 기능은 처음에 아예 막아뒀어요. 이유는 그럴듯했습니다. 면을 들어내면 그 자리를 두르고 있던 게 검은 윤곽선이니까, 주변 색으로 메우면 검은 덩어리가 될 거라고 봤거든요.
나중에 실제로 해보니 아니었습니다. 맞닿은 윤곽선을 함께 떼어가고 남는 자리를 이웃한 면 색으로 메우면, 그 아래 있었을 색이 드러난 것처럼 됩니다. 소매를 옮기면 몸통이 보이는 식이에요.
테스트 없이 막아뒀던 걸 테스트해서 푼 사례입니다. "안 될 것 같다"로 기능을 막는 판단에는 비용이 안 드는 것처럼 보이죠. 그런데 그 기능이 없다는 전제로 다른 코드가 쌓이면 나중에 훨씬 비쌉니다. 한 번 해보는 게 쌉니다.
같은 버그를 세 번 냈습니다
속도가 안 나와서 세 군데를 고쳤는데, 셋 다 같은 실수였어요. 부위 하나 때문에 매번 이미지 전체를 훑고 있었습니다.
구멍 메우기, 어느 면 위에 얹혔는지 찾기, 번호로 마스크 만들기 — 전부 작은 부위 하나를 다루면서 이미지 전체 크기의 연산을 걸고 있었습니다. 눈동자 하나가 전체의 0.2%를 차지한다면 연산량도 그만큼만 들어야 하는데요.
각 덩어리가 차지하는 사각 상자를 먼저 구해서 그 안에서만 계산하도록 바꾸자 653밀리초가 50밀리초가 됐습니다. 13배예요.
새 코드를 쓸 때 이제 이것 하나를 봅니다. 부위 하나를 다루면서 전체에 연산을 걸고 있지 않은가.
남는 것
이번 작업에서 남는 건 이거예요. 입력에 규칙이 있으면 모델보다 계산이 낫습니다.
닫힌 선과 평평한 면이라는 성질 하나 덕에 세그멘테이션 모델 없이 32장이 1.8초에 갈렸어요. 무엇보다 같은 입력에 같은 답이 나옵니다.
같은 32장을 벡터로 바꾸다가 겪은 이야기는 그림을 벡터로 바꿨더니 획의 24%가 사라졌습니다에 적었습니다.
요즘은 뭐든 AI부터 붙이고 보는 분위기인데, 붙이기 전에 물어볼 게 하나 있습니다. 이 입력에 규칙이 있나? 있으면 계산이 빠르고 싸고 예측 가능합니다. 없을 때 모델을 씁니다.