addylog
AI와 함께한 마이그레이션1/3

회사에서 제일 복잡한 시스템을, 도메인도 모르는 내가 물려받았다

목차

재직 2년 3개월차, 신입도 아니고 자리를 잡을 만큼은 잡았다 싶던 무렵에 마이그레이션 담당 리더가 회사를 떠났고, 그가 쥐고 있던 회사에서 제일 복잡한 시스템이 그대로 내게 넘어왔다. 인수인계 문서가 없진 않았다. 다만 큰 틀만 짚은 수준이라 세부는 받지 못했고, 그마저 도메인을 처음 보는 사람이 읽고 이해할 물건은 아니었다. 문제는 내가 그 도메인을 한 번도 다뤄본 적이 없다는 거였다. 2년을 일했어도 이 시스템 앞에서는 초심자였다.

레거시부터가 만만치 않았다. 3년 넘게 쌓여 온 시스템이라 손댄 사람도 많고 사연도 많았는데, 그중에서도 제일 당황스러웠던 건 화면에 값을 내려주기만 하면 되는 BFF가 원래 백엔드가 맡았어야 할 돈 계산까지 자기 안에서 직접 하고 있는 광경이었다. 판매 수수료를 매기고 정산 금액을 뽑아내는, 한 푼이 틀리면 안 되는 계산이 정작 화면을 그리는 계층에 얹혀 있었다. 백엔드에 손댈 여유가 없던 누군가가 급한 대로 BFF에 붙였을 테고, 그게 지워지지 않은 채 다음 사람에게, 또 그다음 사람에게 넘어오면서 로직이 있어야 할 곳과 실제로 도는 곳이 어긋나 버린 거였다. 그러니 뭐가 어디서 어떻게 도는지 파악하는 것부터가 일이었다.

거기에 이어받을 신규 프로젝트는 이미 60% 가까이 진행돼 있었고 그마저 내 손으로 짠 게 아니었으며, 이번 작업은 데이터를 새 그릇에 옮기는 데 그치지 않고 DB 스키마를 바닥부터 갈아엎어야 했다. 며칠 코드를 들여다보고 상황을 이렇게 정리했다.

레거시도 모르고, 이어받을 신규 프로젝트도 모르고, 스키마는 근본부터 바뀌고, 나는 이 도메인 전문가도 아니었다.

담당은 나까지 둘, 목표 기간은 서너 달이었다. 며칠을 씨름한 끝에 나는 결론을 하나 내렸다. 사람 손만으로는 기한 안에 끝낼 수 없고, AI를 제대로 붙이지 않으면 불가능하다는 것. 그리고 AI를 적극적으로 붙이기로 한 건 순전히 내 판단이었다. 위에서 내려온 방침은 없었다.

떠넘긴 4주

문제는 방향을 잡아야 하는 쪽도 나였다는 데 있었다. 도메인을 모르니 AI한테 뭘 시켜야 할지도 몰랐고, 결국 사실상 '그냥 해봐'에 가까운 지시를 던지는 날이 이어졌다. 시키는 사람이 목적지를 모르는데 방향이 나올 리 없었다.

결과는 예상대로였다. AI는 있지도 않은 필드명을 자신 있게 지어냈고, 어디에도 존재하지 않는 상태값을 천연덕스럽게 갖다 붙였으며, 나는 그게 진짜인지 코드를 뒤져 확인하느라 하루를 다 쓰곤 했다. 뭔가를 끊임없이 만들어내긴 했지만 그중 실제로 쓸 수 있는 건 거의 없었다. 그렇게 4주가 지나갔고, 태운 건 토큰뿐이었다.

돌아보면 원인은 분명했다. 도메인을 모르는 사람이 방향까지 AI한테 떠넘기면 둘이 나란히 헛돈다는 것을, 나는 그 4주를 다 보내고 나서야 몸으로 알았다. 큰 그림을 쥔 사람이 없으면 AI는 그 빈자리를 없는 사실로 메우고, 그렇게 만들어진 거짓을 걸러내는 일은 고스란히 다시 내 몫으로 돌아온다.

지도부터

그래서 AI를 쓰는 방식을 통째로 뒤집었다. 뭔가를 만들게 하는 대신, 먼저 이 도메인을 나한테 설명하게 시킨 것이다. 문서라고 부를 만한 게 없었으니 남은 방법은 하나뿐이었는데, 레거시 소스코드를 통째로 읽히고 그 코드가 실제로 하는 일을 사람이 읽을 수 있는 명세로 되짚어 쓰게 하는 것이었다. AI는 상품 상태가 어떤 조건에서 어디로 넘어가는지를 코드에서 역으로 뽑아 상태 전이도로 그려냈고, 저장할 때는 CSV로 쓰면서 조회할 때는 JSON으로 읽는 필드처럼 코드를 직접 열어보지 않으면 절대 만날 수 없는 함정들까지 그 과정에서 하나씩 드러났다. 수백 개의 소스 파일이 그렇게 열 몇 개의 도메인 문서로 정리되는 동안, 정작 도메인을 배우고 있던 건 AI가 아니라 나였다.

지도를 그리다 보니 이 도메인이 왜 그렇게 어려웠는지도 비로소 눈에 들어왔다. 레거시는 상품의 성격이 바뀌면, 그러니까 위탁하던 물건을 회사가 사들이는 매입으로 넘어가면, 그 상품을 아예 새 코드로 새로 만들어 두고 옛 것은 그대로 남겨 뒀다. 반면 새로 짜는 신규 쪽은 같은 상품을 그대로 둔 채 그 안의 상태만 바꿨다. 같은 사건 하나를 두 세계관이 정반대 방식으로 다룬 셈이다.

레거시 · 새로 만든다
상품 A
위탁
상품 B
매입

상품의 성격이 바뀌면 코드를 새로 발급해 새 상품을 만들고, 옛 상품은 지우지 않고 옆에 남겨 둔다. 같은 물건인데 상품이 둘이 된다.

신규 · 상태만 바꾼다
상품 A
위탁 → 매입

같은 상품을 그대로 둔 채 안의 상태만 위탁에서 매입으로 바꾼다. 물건도, 그것을 가리키는 코드도 하나로 이어진다.

같은 사건을 다루는 두 설계 — 레거시는 상품을 새로 만들고, 신규는 상태만 바꾼다.

그러니 이 마이그레이션은 데이터를 이쪽 그릇에서 저쪽 그릇으로 옮기는 일이라기보다 한 세계관의 문장을 다른 세계관의 문장으로 번역하는 일에 가까웠다. 감정, 상품, 배송, 정산, 반환으로 갈래가 나뉜 리세일 도메인 전체가 그런 식으로 얽혀 있었으니, 아무것도 모르고 들어온 사람이 이해하는 데만 한참이 걸릴 복잡도였다. 그 복잡도를 AI에게 코드로 역설계하게 하면서 내가 도메인을 익히는 속도가 붙었다. 이 무렵 AI는 나를 도메인에 태우는 온보딩 도구 노릇을 했다.

빠른 오답

방향을 다시 잡았다고 곧장 순탄해진 건 아니었다. 한 번은 AI에게 잘못된 스코프를 물려준 채 저녁에 작업을 걸어놓고 퇴근했는데, 다음 날 아침 열어 보니 천 줄이 훌쩍 넘는 코드가 새로 쌓여 있었다. 얼핏 보기엔 꽤 그럴듯했지만 방향 자체가 어긋나 있어서, 몇 시간을 들여다본 끝에 통째로 버리고 처음부터 다시 시작했다. AI는 옳은 방향으로도 빠르지만, 틀린 방향으로도 딱 그만큼 빠르다. 방향이 틀렸으면 그 속도만큼 더 멀리 가 있을 뿐이다. 하룻밤 치 노동을 아침에 버린 건, 방향키를 놓고 있던 대가였다.

4주를 태우고

이 4주가 내게 남긴 건 하나였다. 방향을 쥐어야 할 사람은 처음부터 나인데 그 몫까지 AI에게 미뤘다는 자각. 그렇다고 프로젝트마다 이렇게 4주씩 헌납할 수는 없는 노릇이라, 나는 AI가 같은 자리에서 반복해 넘어지는 걸 어떻게든 막아줄 장치를 직접 짓기 시작했다. 그 장치가 무엇을 막았는지는 2부에 이어 적었다.

댓글