[개드립 소설] 9. 황금 소
9-1장: 우상숭배
세진은 결제에서 직접 체감한 그 기적을 자신의 손으로 재현하기로 마음먹었다. 도메인 격리, 1초 만에 통과하는 테스트, 천만 원짜리 장애를 사전에 잡아낸 픽스쳐. 그것은 책에서 읽은 이론이 아니라 자신이 직접 만들어낸 결과였다.
세진은 먼저 선지자가 남긴 묵시록을 펼쳤다. 결제 코드였다. 자신이 직접 작업했던 그 코드. 계층은 엄격히 분리되어 있었고, 인터페이스는 율법처럼 경계를 지키고 있었다.
태초에 테스트가 있었다. 자신이 직접 짠 픽스쳐, 자신이 직접 잡아낸 가드 조건 누락. 그 테스트가 실서비스 장애를 막은 순간, 세진은 회심했다.
선지자가 남긴 거룩한 구절의 흔적을 어느 것 하나 빠뜨리지 않았던 세진은 테스트 커버리지와 테스트 케이스를 자신의 양피지에 필사했다. 기록한 커뮤니티의 테스트 케이스는 예상보다 단순했다. 아니, 진리는 단순한 법이다.
진리의 말씀을 귀히 여기지 않고 테스트를 게을리하는 것은 율법을 저버리는 것과 다름없었다. 결제 도메인에서 자신이 직접 행하였던 그 거룩한 검증의 의식을, 댓글 수정이라는 자신의 제단 위에서도 빠짐없이 재현하리라.
특히 세진은 레이어 간의 경계를 종단할 때마다 엄격한 DTO로 그 경계를 수호하는 것을 기술적 정결을 지키는 예식으로 받아들였다. ORM과 도메인을 분리하고, 엔티티를 인프라로 구분하는 것. 결제에서 체험한 거룩함을 댓글에도 증거했다.
부정한 웹 요청(Web Request)과 사단과도 같은 이상 데이터로 타락한 데이터베이스(Database)의 그림자가 거룩한 도메인의 성역을 침범하지 못하도록, 세진은 경계를 넘나드는 데이터를 DTO라는 성수로 정화하여 마귀들린 데이터가 감히 넘나들 수 없게 만드는 고결한 세례의식에 매달렸다.
세진에게 야근은 철야기도였다. 새벽 2시, 텅 빈 사무실에서 종이컵에 들이붓는 카페인을 '현현할 기적을 탄생시키기 위한 고행 의식'이라 명하며 스스로를 고조시켰다.
묵시록 속에 선지자가 묵과한 진실을 엿보았다.
도메인의 말씀이 선포될 때, 그에 경배하는 신도들이 없었다. 세진은 옵저버 패턴을 제단에 올렸다. 도메인 이벤트가 선포되면, 이 땅에 역사함을 기록 서비스가 행하고, 알림 서비스가 회중에게 전파하라.
선지자의 탄로난 흠결을 내가 메우리라.
성전을 지어 올리는 공정은 한 치의 타협도 허용하지 않는 처절한 고행이자 집요한 봉헌의 시간이었다.
매 순간마다 자신의 기술적 정조를 제단 위에 바친 끝에, 마침내 일주일의 고행을 갈아 넣어 지어 올린 '댓글 수정' 모듈이 로컬 환경에서 구동되는 순간, 세진은 감격했다.
코드는 제단 위에 세워진 거대한 황금소의 광채를 내뿜으며 영광을 드러냈다. 이교도는 감히 범접할 수 없는 성수로 도포된 DTO 덕분에 데이터는 단 한 방울의 오염도 없이 순수한 상태로 흘렀고, 인터페이스라는 성소 뒤에 기거하는 율법학자들은 말씀(Message) 속 계시(DTO)를 해독하였다.
배포 첫날, 기능은 매끄럽게 작동했다.
세진의 코드를 본 동기가 말했다. "어, 이거 문 수석님 결제 쪽이랑 구조가 비슷한데?"
동기들은 세진에게 계시 앞에 무릎 꿇은 어린 양이었다. 자신은 문 수석이라는 메시아의 도래를 예비하며 그 계시를 이 땅에 전파하는 세례 요한이자 광야의 예언자였다.
세진은 자신이 드디어 '기적의 대리자'가 되었다고 확신했다. 황금 소의 광채는 더욱 빛났다.
---
9-2장: 세 번의 순례
첫 번째 요청은 배포 이틀 뒤에 왔다. "댓글 옆에 수정 시간을 표시해달라."
성 부장이라면 세속의 유혹에 눈이 멀어 부정한 방식으로 DB를 더듬었을 것이다.
세진은 경건한 발걸음으로 다시 성전에 들어섰다.
성전의 가장 바깥 회랑인 Endpoint DTO에 필드를 새기는 것으로 순례가 시작되었다. 그것을 거룩한 언어로 번역하는 Controller Mapper의 번역실을 거쳐, 비즈니스의 뜻을 담은 UseCase Command라는 언약궤의 석판에 필드 하나를 계명으로 새겼다. 새로운 계명을 UseCase Interface라는 석판에 새겼다.
예배는 이제 시작이었다.
성전의 심장부인 Service Logic을 관통해 지성소에 안치된 Domain Model의 상태를 바꾸고, Persistence Mapper라는 하산 의식을 거쳐, 최종적으로 가장 낮은 곳—DB와 맞닿은 JPA Entity라는 육신에 수육했다.
귀환의 순례는 더 깊은 헌신을 요구했다. DB에서 끌어올린 수정 시간 데이터는 다시 반대 방향의 정화 의식을 타고 올라가며 수많은 Response DTO 파편들로 쪼개져야만 했다.
3일이 걸렸다.
세진은 이 고통을 기꺼이 받아들였다. 그것은 거룩한 설계를 유지하기 위해 짊어져야 할 마땅한 십자가였다. 기획팀이 원성을 높였지만, 세진은 개의치 않았다. '효율'이라는 이름의 세속의 유혹에 굴복하지 않는 순교자의 길이었다.
두 번째 요청은 일주일 뒤에 왔다. "댓글에 좋아요 수를 표시해달라."
세진은 또다시 12개의 파일 탭을 열었다. 테스트 제단에 엎드려 세 번 절하고 순례를 반복했다. 회랑에서 번역실로, 기도문에서 율법으로, 지성소를 오르내렸다.
이번에도 3일이 걸렸다.
카페인으로 충혈된 눈으로 추상화의 계단을 한 층씩 오르내릴 때마다, 세진은 자신이 기술적 진리의 정점에 한 걸음 더 다가서고 있다고 믿었다. 세진은 자신을 기꺼이 번제했다.
같은 의식을 두 번째 치르자, 제단 앞에 선 자만이 느끼는 현기증이 밀려왔다.
세 번째 요청이 왔다. "댓글 작성자 프로필 사진을 옆에 붙여달라."
세진은 엎드려 세 번 절하듯 파일 탭을 열었다. 12개. 같은 순서. 같은 계단. 같은 의식.
기획팀 담당자가 박종수 팀장을 찾아왔다.
"팀장님, 이번에도 3일이래요. 프로필 사진 하나 붙이는 건데."
박 팀장은 한숨을 쉬며 기획팀 담당자를 돌려보냈다.
점심시간, 복도에서 기획팀 직원 둘이 이야기하는 소리가 세진의 귀에 닿았다.
"세진 씨한테 요청하면 무조건 3일이야. 뭘 해도 3일."
"치훈 부장님한테 가면 안 되나?"
"몰라, 커뮤니티는 세진 씨가 하기로 했대."
오후 회의에서 박 팀장이 진행 상황을 물었다.
세진이 12개 파일의 수정 범위를 설명하려 하자, 옆에 앉아 있던 동기가 끼어들었다.
"그거 그냥 쿼리에 조인 하나 추가하면 되는 거 아냐?"
세진은 속으로 한탄했다. 성 부장의 방식에 오염된 자들에게는 정화의 세례가 필요했다.
퇴근 시간, 치훈이 자기 모니터를 끄며 지나가듯 던졌다.
"세진 씨, 그 프로필 사진 건 DB에 이미 있어. 조인 한 줄이면 되는 건데 뭘 그렇게 오래 붙들고 있어."
고객의 고함 한마디에 무너져 내리는 여리고 성벽의 병사. 조인 한 줄로 쌓고, 조인 한 줄로 무너지는 자.
이교도의 핍박은 세진을 오히려 성령으로 충만케 했다.
자리로 돌아가 다시 12개의 파일 탭을 열었다. 박해받은 순례자는 더욱 빠져들었다.
---
9-3장: 새벽닭의 울음
어느 새벽, 모니터의 푸른 빛 앞에서 세진은 멈췄다.
12개의 파일 탭이 열려 있었다. 경전의 어느 구절을 읊어야 하는지 기억나지 않았다. 손가락이 키보드 위에서 멈춰 있었다. 성수를 부어야 할 그릇이 어디에 있는지 보이지 않았다.
"왜... 무엇을 위해 이 짓을 하고 있는 거지?"
목소리가 새어 나왔다.
그때 책상 위 휴대폰이 울렸다. 기상 알람이었다. 꼬끼오— 닭 울음소리 벨이 텅 빈 사무실을 갈랐다.
새벽 6시. 사무실에는 아무도 없었다.
광야의 예언자가 아니었다. 거룩한 순교자도 아니었다. 밤새도록 댓글 수정 시간 하나를 화면에 띄우지 못하는 4년 차 개발자가 있을 뿐이었다.
십자가라 믿었던 것은 고철이었다. 보혈이라 마셨던 것은 편의점 캔커피였다. 성전이라 지어 올린 것은 기획팀의 실적을 조르는 병목이었다.
제단 위의 황금 소는 온데간데없이 사라져 있었다.
세진은 모니터를 껐다.
어둠이 내려앉은 화면에 자기 얼굴이 비쳤다. 결제에서 목격한 기적이 여기서도 일어날 거라 믿었다. 기적은 일어나지 않았다. 결제와 댓글은 다른 세계였고, 자신은 그 경계를 보지 못했다.
다음 날 아침, 우진은 머리를 감싸 쥐고 자리에 앉아 있는 세진을 보았다. 그리고 세진의 모니터에 열려 있는 12개의 파일 탭을 보았다.
기획팀에서 박종수 팀장에게 연락이 왔다.
박 팀장은 우진을 불렀다.
"우진 씨, 세진 씨가 맡은 댓글 수정 건 좀 확인해줘. 기획팀에서 또 3일 더 걸린다고 난리야."
우진은 세진의 자리로 갔다. 세진이 충혈된 눈으로 고개를 들었다.
우진은 세진의 모니터를 들여다보았다. Endpoint DTO, Controller Mapper, UseCase Interface, Domain Model, Persistence Mapper, JPA Entity. 그리고 테스트.
12개의 탭. 1년 전 자기 화면이었다.
세진이 충혈된 눈으로 말을 쏟아냈다.
"우진 책임님, 이건 단순한 필드 추가가 아닙니다. 엉클밥도 말했잖아요, 빨리 가는 유일한 방법은 제대로 가는 거라고."
숨을 몰아쉬며 말을 이었다.
"다른 레이어의 데이터가 도메인에 침투하려면 반드시 DTO로 변환해야 하고, 계층을 넘을 때마다 새 DTO가 필요하거든요. 유스케이스 계약 갱신하고, 영속성 매퍼까지 왕복으로 다 고쳐야 해요."
세진의 손가락이 모니터를 가리켰다.
"아, 그리고 옵저버 패턴도 제가 추가했거든요. 문 수석님 코드에는 없었는데, 댓글 수정 이벤트가 발생하면 알림이랑 로그가 자동으로 반응하게요. 인터페이스로 된 계약이라 구현체를 쉽게 교체할 수도 있어요. 이건 제가 직접 설계한 겁니다."
빠르게 말을 이었다.
"결제에서 가드 조건 하나 빠진 걸 테스트가 잡았잖아요. 그때 실서비스 나갔으면 장애였어요. 이게 나중에 열 배로 돌아옵니다."
우진이 낮은 목소리로 되물었다.
"게시물 옵저버의 구현체를 교체할 일이 있어?"
세진이 멈칫했다. 그리고 숨을 고르더니 덧붙였다.
"아, 책임님이 전에 말씀하셨잖아요. 의사가 수술 전에 손 씻는 거랑 같은 원리라고."
우진은 한참을 말없이 서 있었다. 저 말들은 자기가 했던 말이었다. 변명으로 쓰이고 있었다.
"세진 씨." 우진의 목소리가 올라갔다. "이거 댓글이야. 하... 댓글 수정 시간 하나 표시하는 건데 소 잡는 칼로 닭을 잡고 있는 거 아냐?"
말이 입 밖으로 나온 뒤 우진은 자기가 무슨 말을 했는지 알아챘다.
치훈이 했던 말이었다.
우진은 말을 잇지 않았다.
자리로 돌아가는 발걸음이 무거웠다.
문 수석은 결제에 소 잡는 칼을 썼다.
세진은 댓글에 소 잡는 칼을 썼다.
그렇다. 나 역시도 마찬가지였다.