[개드립 소설] 1. 엑셀팡션과 손 씻기
# 1. 엑셀팡션과 손 씻기
---
스타트업 '유니콘-X'의 백엔드 팀은 업계에서 가장 기민하고 스마트한 조직으로 손꼽혔다. 그들은 단순히 기술을 소비하는 것이 아니라, 코드의 무결성과 시스템의 고도화를 위해 매주 스터디를 열고 아키텍처 토론을 즐겼다. 그들에게 소프트웨어 설계란 단순한 노동이 아닌, 미래를 대비하는 정교한 엔지니어링이었다.
어느 날, 팀의 핵심 인재이자 유능한 개발자인 정우진이 해외 콘퍼런스에서 돌아와 팀 회의를 소집했다. 그의 목소리에는 확신과 전문성이 가득 차 있었다.
"여러분, 우리 시스템은 이제 변곡점에 서 있습니다. 대기업 D사가 채택한 '클린 아키텍처'라는 원칙은 이제 성장을 위한 필수적인 표준입니다. 계층 간의 철저한 격리를 통해 인프라의 변화에 휘둘리지 않는 코어를 구축해야 합니다. 지금 이 설계를 도입하는 것이야말로 진정한 시스템 고도화의 시작입니다."
우진의 논리는 완벽했고 제안은 프로페셔널했다. 그때, 구석에서 코드를 짜고 있던 성치훈이 귀찮은 듯 한마디를 던졌다.
"아이고, 우진 씨. 그거 우리랑은 좀 안 맞는 거 같은데. 케바케(Case by Case) 아니겠어? 굳이 그렇게까지 할 필요가 있나. 그냥 파일 하나면 될 일을 왜 여덟 개로 쪼개나."
우진은 예의를 갖춰 미소 지었지만 속으로는 한탄했다. 치훈은 회사 창업 초기, 자본금도 없이 원룸에서 라면으로 끼니를 때우며 대표와 동고동락했던 친구였다. 하지만 우진의 눈에 그는 이제 새로운 기술을 배우기 귀찮아하고 변화를 거부하는, 과거의 영광에 안주하는 '고인 물'일 뿐이었다. 우진은 결단을 내렸다. 그것이 대표의 친구가 망쳐놓은 '구식 시스템'을 정상화하는 길이라 믿었기 때문이다.
이 논의에 박종수 팀장은 '채용 브랜딩'을 위해, 최윤석 재무 팀장은 '장부상 ROI'를 위해 열렬히 찬성했다. 그렇게 유니콘-X의 아키텍처 개편이 시작되었다.
---
1-1장: 하얀 셔츠의 계절
우진의 모니터에는 젠킨스(Jenkins)의 녹색 등이 사흘째 꺼지지 않고 켜져 있었다. 921개의 유닛 테스트가 0.8초 만에 통과했다는 로그가 마지막으로 기록되어 있었다. 주니어들은 우진이 공유한 아키텍처 다이어그램을 인쇄해 파티션에 붙여두었다. 점심시간이면 그 다이어그램 앞에 서너 명이 모여 계층 구조를 손가락으로 짚어가며 이야기를 나눴다. 코드 리뷰는 매주 수요일 오전에 진행되었고, 리뷰어는 항상 우진이었다.
어느 수요일 오전, 리뷰 중에 주니어 한 명이 물었다.
"우진 님, 이 DTO 변환 과정이 왜 이렇게 많아야 하는 걸까요? 컨트롤러에서 바로 엔티티로 보내면 파일 수가 절반으로 줄잖아요."
우진이 화이트보드 앞으로 걸어갔다.
"좋은 질문이에요. 의사가 수술 전에 손을 씻는 이유를 생각해 보세요. 귀찮고 시간이 걸리죠. 하지만 씻지 않으면 환자가 감염됩니다. 이 변환 과정이 그 손 씻기예요. 화면에서 들어온 데이터가 비즈니스 규칙을 오염시키지 않도록, DB의 구조가 도메인 로직에 침투하지 않도록 각 계층에서 정제하는 겁니다. 엉클밥도 말씀하셨죠, '빨리 가는 유일한 방법은 제대로 가는 것이다.' 지금 이 구조가 나중에 우리를 지켜줄 겁니다."
주니어들이 고개를 끄덕였다. 리뷰가 끝나면 그들은 우진의 코멘트를 노션에 정리해 '제대로 가는 길 스타일 가이드'라는 이름으로 공유했다.
사무실 대각선 끝, 성치훈 차장은 낡은 모니터의 조도를 낮춘 채 검은색 SQL 창으로 커서를 옮기고 있었다. 그의 책상에는 ERD가 빽빽하게 인쇄된 A3 용지 묶음과 형광펜으로 밑줄 그어진 엑셀 명세서가 쌓여 있었다. 화이트보드 쪽에서 들려오는 우진의 목소리에 치훈은 고개를 돌리지 않았다.
그 무렵, 마케팅팀에서 요청이 두 건 들어왔다. 이벤트 배너에 새 이미지를 적용하는 건은 치훈이 SQL 클라이언트를 열어 30분 만에 끝냈다. 요청 완료 메신저 알림이 짧게 떴다가 사라졌고, 아무도 그 과정에 관심을 두지 않았다. 회원 프로필에 '가입 경로' 항목을 추가하는 건은 우진에게 넘어왔다. 우진은 평소처럼 8개의 파일을 열어 계층별로 수정했다. 5시간이 걸렸다. 마케팅 이현주 대리가 메신저로 "아직인가요?"를 두 번 보내왔지만, 우진은 당연한 절차라고 생각했다. 손 씻기에 시간이 걸리는 건 당연한 것이니까.
우진은 그날 퇴근 시간을 조금 넘겨 작업을 마무리했다. 당연한 절차에 드는 당연한 시간이었다.
---
1-2장: 8개의 탭
어느 순간부터 마케팅팀의 재촉이 잦아지기 시작했다. 필드 하나를 추가하는 데 반나절, 팝업 문구를 고치는 데 이틀. 마케팅팀의 요청은 매주 서너 건씩 밀려들었고, 우진은 매번 8개의 파일 탭을 열어 같은 순서로 같은 작업을 반복했다.
그날도 마찬가지였다.
"우진님, 사용자 프로필에 'VIP 등급 갱신일' 필드 하나만 추가해 주세요. 오늘 점심 전까지 반드시 배포되어야 합니다!"
마케팅팀 이현주 대리의 메시지가 우진의 노치 모니터 한구석에 띄워졌다. 오전 11시 10분이었다.
우진은 8개의 소스 파일 탭을 열었다. 6개월 전 작성된 계층별 인터페이스와 데이터 변환 매퍼들이었다. 필드 하나를 추가하기 위해 우진은 탭을 옮겨가며 8개의 파일을 수정했다. 타입을 맞추고 인터페이스 선언부를 갱신할 때마다 하단 로그창에 컴파일 에러가 순차적으로 밀려 올라왔다.
11시 35분. 이현주 대리가 우진의 자리 앞에 서 있었다.
"우진님, 아까 성 차장님은 저번주에 요청드린 이벤트 배너도, 오늘 추가로 부탁드린 할인 팝업도 벌써 다 끝내셨거든요. 이거 필드 하나 추가하는 건데 왜 이렇게 오래 걸리는 거예요? 이것 때문에 이벤트 페이지 오픈이 계속 밀려요."
우진은 모니터에서 시선을 떼지 않은 채 대답했다.
"이 대리님, 응급 환자가 실려 와도 의사한테 손 씻지 말고 바로 집도하라고 하시겠어요?"
우진은 모니터에서 시선을 떼지 않은 채 말을 이었다.
"지금 제가 하는 게 그 손 씻기입니다. 이 8개 파일이 각각 역할이 다 다릅니다. 화면에서 받는 데이터, 비즈니스 규칙을 처리하는 데이터, DB에 저장하는 데이터가 전부 다른 형태로 존재해요. 이걸 한 파일에 때려 넣으면 당장은 빠르겠지만, 다음에 결제 로직이 바뀌거나 정산 기준이 달라지면 어디서 뭐가 깨지는지 아무도 모르게 됩니다. 한 단계라도 건너뛰면 다른 데이터가 오염되고, 그때 가서 고치려면 지금보다 열 배는 더 걸려요. 클린 아키텍처를 만든 엉클밥도 말씀하셨죠. '빨리 가는 유일한 방법은 제대로 가는 것이다.'"
이현주는 잠시 말을 멈추었다가 입술을 한 번 깨물었다.
"...네, 알겠습니다. 이건 저희 팀장님께 한번 얘기해볼게요."
돌아서는 그녀의 어깨가 한 번 짧게 떨어졌다.
우진은 다시 첫 번째 탭으로 돌아갔다. 탭을 횡단하며 코드를 고치는 25분 동안 마우스 클릭 소리만이 사무실의 정적을 뚫고 들렸다.
옆자리의 성치훈 차장이 일어섰다. 그는 아까 같은 마케팅팀에서 요청받은 '블랙프라이데이 할인 배너 교체'와 '할인 팝업 문구 수정'을 모두 마친 뒤였다. 그는 우진의 화면에 가득 띄워진 8개의 탭을 한 번 훑고는 자신의 모니터 전원을 껐다.
"나는 아까 운영 DB로 직접 들어가서 쿼리 한 줄 날리고 끝냈다. 대표가 삼겹살 집 예약해놨다고 같이 가자네."
치훈이 자기 모니터를 손가락으로 가리켰다. SQL 클라이언트 창에는 방금 실행한 쿼리 이력이 남아 있었다. 배너 이미지 경로를 바꾸는 UPDATE 문 한 줄, 팝업 문구를 수정하는 UPDATE 문 한 줄. 두 줄이 전부였다.
"이 대리한테 받은 거 두 건 다 끝냈어. 쿼리 두 줄이면 되는 걸 뭘 그렇게 복잡하게 해. 우진 씨도 빨리 끝내고 같이 가자고."
우진이 의자를 돌렸다.
"아니 차장님, 그걸 그렇게 처리하시면 안 되죠! 운영 DB를 직접 수정하시면 git에 이력이 안 남잖아요. 나중에 누가 뭘 바꿨는지 추적이 안 됩니다. 롤백도 못 해요. 만약에 그 쿼리가 다른 테이블이랑 엮여 있으면 어떡하시려고요?"
치훈은 외투 단추를 잠그며 고개를 돌렸다.
"알았어, 알았어. 그건 내일 얘기해. 일단 이 대리한테 된다고 해놨으니까. 오늘 안 되면 대표한테 나 욕먹어. 우진 씨, 밥이나 먹고 해."
치훈의 슬리퍼 소리가 복도 너머로 멀어졌다. 우진은 이해할 수 없었다. 이력도 남기지 않고 운영 DB를 직접 건드리는 저 방식이 어째서 칭찬받는 일이 되는 건지. 저렇게 쌓인 것들이 언젠가 한꺼번에 터지면, 그때는 아무도 원인을 추적할 수 없을 것이다. 저건 미래를 팔아 오늘을 사는 거다.
---
1-3장: 반복되는 일상
오전 11시 59분.
우진의 모니터에는 UserMapper.java의 142행이 단독으로 띄워져 있다. 잘못 기입된 필드명 밑에 붉은 밑줄이 선명하다. 우진의 검지 손가락은 엔터 키 위에 멈춘 채 미세하게 떨린다.
치훈의 책상 위에는 전원이 꺼진 본체와 식어버린 커피 종이컵만이 남았다. 복도 끝 사장실 문이 열리며, 일찍 퇴근길에 나서는 치훈과 대표의 목소리가 들려왔다.
"치훈아, 너 어제 입고수량 터미널에서 수정하다가 당일치 수량 일괄 수정해버려서 복원하느라 진짜 식겁했다. 사고 좀 그만 쳐."
"에이, 형님. 그래도 저니까 10분 만에 수습해서 살려놨잖아요. 다른 애들이었으면 오늘까지 회사 마비됐을걸요?"
"그건 그래. 우리 회사에서 사고도 네가 제일 크게 치는데, 불 끄는 것도 네가 제일 빠르다. 가자, 삼겹살이나 먹자. 하하하!"
대표의 호탕한 웃음소리가 사무실의 정적을 갈랐다.
점심을 먹으러 나가는 직원들의 긴 그림자가 우진의 발등을 스치고 지나간다. 우진은 젖은 손바닥을 바지에 닦고 다시 마우스를 움켜쥔다. 8개의 탭 사이를 방황하는 커서는 더 이상 길을 찾지 못한 채 제자리에서 깜빡일 뿐이다.
이것은 유니콘-X 백엔드 팀의 평범한 일상이 되었다.
매일 저녁 6시 정각이 되면, 성치훈 차장은 컴퓨터 전원을 끄고 슬리퍼를 구두로 갈아 신었다. 그는 그날 마케팅팀이 요청한 할인율 변경, 이벤트 배너 교체, 임시 쿠폰 발급 쿼리들을 모두 운영 DB에 직접 날려 완료한 상태였다. 가끔은 대표와 저녁을 먹으러 가거나, 그대로 퇴근 인사를 던지며 엘리베이터를 탔다. 치훈의 모니터는 일찍부터 검은색 화면을 유지했다.
같은 시각, 정우진은 여전히 자리를 지켰다. 저녁 식사를 대충 샌드위치로 때운 그는, 모니터에 8개의 탭을 열어둔 채 DTO와 엔티티 간의 매핑 구조를 들여다보았다. 컴파일 에러를 하나 잡으면 다른 계층의 의존성도 따라서 수정했다. 우진의 층 끄트머리 자리 모니터 불빛은 자정이 가까워지도록 꺼지지 않았다.
하루, 이틀, 한 달.
치훈은 매일 제시간에 일을 끝내고 문을 나섰고, 우진은 매일 밤 남아 '제대로 가는 길'을 다듬었다. 보이스카웃이 캠프장을 떠날 때보다 더 깨끗하게 정리하듯, 그는 퇴근 전 반드시 코드를 한 번 더 정돈했다.
우진이 저녁을 사러 엘리베이터를 탈 때면, 퇴근하는 치훈과 마주쳤다. 둘은 고개만 살짝 숙이고 지나갔다.