- Tags:
- #Reflection
- Date:
미움받을 용기
회사를 그만뒀다. 약 1년 만이었다. 한 회사에 들어가면 으레 3년 가까이는 다니던 나로서는 이례적인 일이다.
무의식적으로 그때의 일을 곱씹는다. 계속되는 반추. 아마 나의 경우에는, 직장에 관한 가장 최근의 기억이 그곳에 멈춰 있기 때문일 것이다. 이미 떠나온 회사와 지나간 일 따위로 괴롭지는 않지만 아쉬움은 남기에. 과거에 오래 머무는 일은 사람을 조금씩 좀먹는다. 그러니 이대로 내버려둘 수는 없었다. 또 다른 종류의 고통이었다.
이 글은 가장 최근의 직장에서 겪은 일과, 그 안에서 내가 기울였던 노력에 대한 기록이다. 누군가를 비난하려는 것은 아니다. 팀에 해를 끼치고 싶은 마음도 없다. 누군가 내게 입힌 피해가 있다 해도, 그 행동에 악의가 있었다고 생각하지 않는다. 오히려 이 글이 드러내는 것은 나의 어리숙함일지도.
내가 놓여 있던 환경과 그 안에서 겪은 문제들, 어떤 사고 과정으로 그렇게 행동했는지, 더 현명하게 행동하지 못한 데 대한 반성도 여기에 적는다. 함께 일했던 동료가 읽는다면 변명으로 읽힐지도 모르겠다. 그러나 상관없다. 그저 내 마음이 편해지고자 하는 일이니까.
회사·제품·팀 이름은 언급하지 않았고, 개인을 특정할 수 있는 정보도 최대한 덜어냈다. 우연히 이 글을 마주칠 가능성을 줄이기 위해 검색 엔진에서도 숨겨두었다. 이 이야기가 입에 오르내리거나 팀과 개인에 대한 억측과 부정적인 소문으로 번지는 일은 바라지 않는다. 끝에 이르러서는 분명 문제가 해결되고 있었고, 그 기간을 내가 버티지 못했을 뿐이다.
갈증
한때 나는 어느 스타트업의 창업 멤버로 일했다. 세 번째 직장이었고, 산업기능요원을 마친 뒤 온전히 내 의지로 고른 첫 회사였다. 남들이 빅테크를 원할 때 나는 스타트업에 끌렸다. 회사가 망하면 그때 떠나도 된다는 가벼운 마음도 있었다. 그러나 그곳에서 보낸 4년은 나를 크게 바꿨고, 과분할 만큼 많은 것을 경험하고 배웠다. 오늘 하려는 이야기는 그 회사에 관한 것이 아니니 이쯤 해둔다.
갈증은 여전했다. 내가 무엇을 모르는지조차 모른다는 것. 그 미지의 영역이 궁금했다. 지금 회사가 계획하고 있는 변화는 옳은 방향인가. 그렇게 판단하는 나 자신을 믿어도 되는가. 자신은 있었지만 확신은 없었다. 그동안 나는 환경을 이유로 누군가를 곁에서 보고 배우기보다 직접 부딪히며 익혀왔다. 그러나 마주한 눈앞의 문제는 그렇게 쌓은 경험만으로 가늠하기 어려웠다. 나는 회사의 방향을 결정할 수는 없어도 리더로서 일을 벌일 수 있는 위치에는 있었는데, 여느 스타트업이 그렇듯 재정은 넉넉지 않았다. 스타트업의 파티가 끝나고 모두가 생존에 집중하던 시기였다. 실패를 경험으로 치부하기에는 치러야 할 대가가 컸고, 나보다 나은 전문가가 필요했다.
결국 모든 것을 내려놓고 본업으로 돌아가기로 했다. 이제 와 솔직히 말하자면, 더는 상황을 나아지게 할 수 없다는 무력감에 도망친 것인지도 모른다. 새로운 환경에서는 내가 해보지 못한 일을 해내는 동료들을 가까이에서 보고 배우고 싶었다. 내가 가장 잘할 수 있는 엔지니어링으로 기여하면서 말이다. 준비된 제너럴리스트가 되기 위한 선택이었다.
기대
인터뷰 과정이 인상적인 회사가 있었다. 이렇다 할 특별함은 없었지만, 내가 다시 면접관이 되면 이를 모방해야겠다는 생각이 들었던 회사. 촘촘하게 설계된 인터뷰였다. 어렵지 않은 질문들이었지만 꽤나 공을 들였겠지. 이런 회사라면 인재 밀도도 높으리라 기대했으니, 나름 신중한 선택이었다.
회사가 풀고 있는 문제도 마음에 들었다. 그중에서도 더 깊이 알고 싶은 도메인이 둘 있었다. 온보딩이 끝나기 전, 마침 그중 하나를 담당하는 스쿼드에 배치될 것이라는 이야기를 들었다. 그것이 레거시라는 말도 어디선가 주워들었지만, 내게는 아무런 문제가 되지 않았다. 그저 잘됐다는 생각뿐이었다.
온보딩은 대략 4주 동안 진행됐다. 플레이북 곳곳에는 신경 쓴 흔적이 보였다. 오랜만의 엔지니어 채용이라 오래된 정보가 더러 섞여 있었지만, 온보딩 메이트가 있어 별문제는 아니었다. 다만 엔지니어링 온보딩은 신입이나 주니어를 상정하고 쓰였는지, 내게 필요하지 않은 과정도 적지 않았다. 회사 기술 스택에 익숙해지기 위한 사이드 프로젝트 같은 것들 말이다. 메이트와 상의해 몇 가지는 건너뛰었다. 시니어 엔지니어를 몇 년 만에 채용한다고 했으니 그럴 만했다.
이때까지만 해도 모든 일이 잘 풀리는 듯했다. 앞으로의 회사 생활도 기대됐다. 절차에 따라 나는 온보딩을 마칠 때까지 어느 스쿼드에도 소속되지 않은 채 기다렸는데, 상황을 조금만 일찍 알았더라면, 혹은 다른 팀에 배정됐더라면, 나는 지금도 그곳에 남아 있었을까?
교착
온보딩을 마치고 스쿼드에 합류했다. 그곳에는 나의 매니저도 있었다. 첫인상은 좋았다. 구성원들은 밝았고 분위기도 화기애애했다. 적어도 새로 들어온 내 눈에는 아무런 문제가 없어 보였다. 낯을 꽤 가리는 나만 이 팀에 적응하면 될 일이었다.
실상은 달랐다. 내가 합류했을 때 스쿼드는 1년 가까이 이렇다 할 성과를 내지 못한 상태였다. 회사의 많은 사람이 그 사정을 알고 있었지만, 누군가 알려주지 않는 한 신규 입사자인 내가 알아차릴 방법은 없었다. 온보딩 기간에 이미 접근할 수 있는 문서 대부분을 읽었지만, 그런 갈등까지 애써 기록으로 남길 리는 없으니까. 기록을 잘 남기지 않던 팀이였으니 더욱 그랬다.
팀이 풀려던 문제는 과거의 틀린 의사결정들이 제품에 남긴 흔적을 걷어내는 일이었다. 서로 다른 고객의 요구를 모두 품을 수 있는 새로운 경험을 만들고자 했다. 그러나 오랜 시간 쌓인 문제를 며칠이나 한두 번의 스프린트 안에 해결할 방법이 나올 리 없었다. 무엇을 어떻게 나누고 무엇부터 바꾸어야 할지 계속 고민해야 했다. 흔히 스타트업 씬이나 SNS에서 떠들어대는 빠른 MVP를 통한 성공 법칙과는 달리, 오래된 서비스에서는 종종 있는 일이었다. 그리고 그 계획은 끝내 실행되지 못했다.
처음 들은 이유는 팀의 접근에 회사가 동의하지 않는다는 것이었다. 하지만 회사의 반대만이 문제는 아니었다. 정작 팀 안에서도 동의하는 사람이 거의 없었다. 정확히는, 목표로 하는 완성된 그림에는 동의하면서도 거기까지 도달하는 방법을 두고 의견이 충돌했다.
Product Owner는 급진적인 변화를 원했다. 동료들의 합의를 이끌어내기보다 자신이 옳다고 믿는 방향을 고수했다. 문제는 그 방향이 기존 고객의 경험을 완전히 파괴한다는 데 있었다. 사실상 제품을 바닥부터 다시 만드는 것인데도 데이터 마이그레이션조차 지원하지 않으려 했다. 자신이 원하는 것과 가장 가까운 합의안이었지만, 그것마저 받아들이지 않은 것이다. 이미 사용자가 있는 제품의 핵심 기능이었으니, 회사의 리더들이 반대하는 것도 무리는 아니었다.
그렇다고 이 문제를 책임지고 이끌 사람도 없었다. 그렇다면 반대를 남겨둔 채 누군가의 결정에 힘을 싣는 선택도 필요했다. ‘Disagree and Commit’. 회사의 반대는 여전했겠지만, 적어도 팀은 같은 방향으로 움직일 수 있었다. 전체 고객을 대상으로 배포하지 않고 가설을 검증할 방법을 찾아, 그 결과를 바탕으로 다음 논의를 이어갈 수도 있었다. 성공하지 못하더라도 시도하고 학습할 수 있는 기회는 있었을 것이다. 하지만 누군가에게는 화합과 만장일치가 의사결정에서 양보할 수 없는 원칙이었고, 적어도 이 문제만큼은 모두가 동의하지 않으면 누구도 움직일 수 없었다.
나 역시 의사결정에서 이상함을 느꼈다. 그러나 이 교착이 1년 가까이 이어진 갈등이라는 사실을 알지 못했던 나는, 새로 합류한 사람으로서 먼저 이 팀이 일하는 방식을 충분히 관찰하고 싶었다. 결코 소극적인 태도로 임하지는 않았지만, 문제 현상을 인지하고도 최대한 지켜보려 했다. 다른 동료보다는 자주 개입했지만, 그 빈도는 의식적으로 줄이려 했다. 제대로 된 스프린트를 돌려본 다음에야 결과로부터 학습하고 피드백할 수 있으리라 생각했으니, 결과적으로 오판이었다.
그래서 나의 시선은 코드베이스에 가 있었다. 살면서 본 레거시 가운데 세 손가락에 꼽을 만큼 심각했기 때문이다. 나는 시급한 기술 부채를 먼저 해결하겠다고 선언했고, 그동안 PO가 적어도 팀이 움직일 수 있을 만큼은 방향을 정리해 오리라 믿었다. 네 일 내 일 가리지 않고 돕는 것을 선호하지만, 직업인으로서 각자 전문성을 발휘해야 할 분야는 달랐다. 더욱이 PO가 원하는 대로 제품 부채를 청산하려면 그에 얽힌 기술 부채부터 해결해야 했다.
물론 동료들도 마냥 손을 놓고 있었던 것은 아니다. PO가 기존 문제에 묶여 있는 동안, 다른 구성원들은 자신들이 주도할 수 있는 문제를 찾기 시작했고, 그렇게 해결할 수 있는 문제라도 먼저 시도해 보기로 했다.
형식
새로운 문제를 찾으면서 스쿼드는 비로소 움직이기 시작했다. 나로서도 기다리던 순간이었다. 드디어 이 팀이 어떻게 일하는지 온전히 이해할 수 있으리라 생각했다. 앞으로 나아가는 경험을 통해 자신감이 붙으면, 그동안의 교착도 조금씩 풀릴지 모를 일이었다.
하지만 일이 시작되자 또 다른 문제가 나타났는데, 무엇을 만들지 이야기가 오고 가면 곧바로 구현부터 서둘렀다. 정확히는 근거가 없었다. 왜 이 문제를 지금 풀어야 하는지, 어떤 근거로 이 아이디어를 선택했는지, 무엇을 확인하면 성공이나 실패를 판단할 수 있는지는 충분히 다루지 않았다. 검증 계획도, 구현한 뒤 실제로 검증하는 과정도 빈약했다. 일단 빨리 만드는 것이 우선이었다. PO의 공백이 여실히 드러나는 순간이었다.
빠르게 만드는 것 자체는 잘못이 아니다. 불확실한 것을 작게 만들고 확인하는 일은 오히려 더 빨라야 한다. 다만 그 속도는 다음 판단을 위한 것이어야 했다. 가설도 검증도 없다면, 짧은 시간 안에 무언가를 완성해도 남는 것은 Feature Creep뿐이다. 오늘날의 AI Slop과도 닮았다. 결국 학습하지 못한 팀은 다음 스프린트에서 다시 처음부터 판단해야 한다.
표면적인 형식은 이미 갖추고 있었다. 스프린트라는 이름이 있었고, 그에 딸린 회의와 도구도 있었다. 그러나 정작 왜 그런 주기로 일하고, 각각의 회의에서 무엇을 얻어야 하는지는 충분히 공유되지 않은 듯했다. 이를 분명히 알게 된 계기가 있었는데, 어느 날 같은 스쿼드에 있던 한 동료가 스프린트가 무엇인지를 설명하는 자리를 마련했다. 정확한 계기는 희미하지만, 스프린트를 진행하다 어떤 문제를 겪었던 것으로 기억한다. 설명을 들은 다른 동료들은 이제야 스프린트를 왜 하는지 이해했다는 후기를 남겼다. 미팅 자체는 성공적이었던 셈이다. 그래서 더 당황스러웠다. 그렇다면 그동안 이들이 반복해 온 것은 무엇이었을까.
그제야 내 머릿속의 퍼즐이 맞춰졌다. 흩어져 있던 문제 현상들이 하나의 위험 신호로 보이기 시작했다. 합류한 지 이미 수개월이 지난 뒤였다.
나는 이 스쿼드가 지금 겪는 문제를 해결하고 자생할 수 없는 팀이라 결론 지었다.
생존
이곳은 내가 찾아다니던 환경이 아니었다. 이전 직장을 떠나 얻은 것이 단순히 연봉 하나만은 아니어야 했다. 그러나 문제가 보인다고 바로 도망칠 내가 아니었고, 무엇보다 또다시 그러고 싶지 않았다. 팀을 어떻게든 계몽시켜서라도 살아남게 해야 했다. 계몽이란 단어를 떠올렸을 때부터 내 태도는 틀렸던 것일지도 모른다.
먼저 멈추어야 한다고 주장했다. 앞서 풀리지 않는 문제로 같은 의사결정을 수십 번 되풀이했을 때도 나는 옐로카드를 꺼내 들었는데, 이번에도 다르지 않았다. 근거도 검증도 없이 기능을 더하는 일은 전진이 아니었다. 과거의 틀린 결정이 남긴 흔적을 걷어내겠다면서, 옳은지조차 확인조차 할 수 없는 기능을 그 위에 다시 쌓는 것은 모순이었다. 더 만들기 전에 무엇이 어긋났는지 돌아보고 바로잡아야 했다.
그러나 전혀 동의를 얻지 못했다. 이미 오랫동안 성과를 내지 못한 팀이었고, 구성원들은 저마다 압박을 느끼고 있었다. 그런 상황에서 멈추자는 말은 유일하게 붙들고 있던 진척마저 포기하자는 말처럼 들렸을 것이다. 나에게는 고작 몇 개월이지만 이들에게는 절박함 속에서 버텨온 긴 시간이었을 테니. 더욱이 이 회사에서는 ‘빠른 기능 구현’ 외의 일을 주장하는 것만으로도 부정적인 반응을 사기 쉬웠다. 그러니 이들의 사전에는 ‘멈추자’는 말이 없었을 것이다. 앞서 기술 부채를 해결하겠다고 나섰을 때도 마찬가지였다. 같은 직무인 매니저조차 줄곧 반대했을 정도. 분명히 하자면, 기술 부채 해결의 반대는 팀이 성과를 내지 못해 다급했기 때문만은 아니었다. 그와의 갈등은 뒤에서 다시 이야기하기로 하고, 결과적으로 나의 주장은 팀이 변화할 계기를 만들지 못했다.
다음으로 PO와 따로 이야기를 나누었다. 동료들이 PO의 의견에 생각만큼 힘을 실어주지 않는 것 같다고 말했다. 물론 그의 방향에 전부 동의해서는 아니었지만, 내 말은 진심이었다. 누구도 결정을 내리지 못하는 가운데, 적어도 한 사람은 같은 편에 설 필요가 있다고 생각했다. 예상과 달리 PO는 동료들에게 실망하지 않았다고 했는데, 어쩌면 함께한 지 얼마 되지도 않은 내가 섣불리 단정한 것인지도. 다만 PO가 너무 많은 책임과 부담을 혼자 지고 있다는 점만은 분명해 보였다. UX 디자이너도 나와 같은 생각이었다.
그리고 우리는 워크숍을 열었다. 내가 주도했다. 명목은 앞으로 나아갈 길을 찾는 것이었지만, 숨은 목적은 팀을 잠시 멈춰 지금까지 온 길을 돌아보게 하는 데 있었다. 그동안 지켜본 회고는 대개 서로를 칭찬하고 격려하는 데 그쳤는데, 지금 팀에 더 필요한 것은 무엇이 잘못됐는지 직시하는 회고였다. 그러므로 멈추자고 다시 주장하는 대신 며칠을 워크숍에 쓰자고 제안하면 거부감도 덜할 터였다. 우회는 분명 효과적이었고, 제안은 받아들여졌다. 그러나 무엇 하나 끝까지 내 뜻대로 흘러가지는 않았다.
동료들이 워크숍에서 원한 것은 아이디어 탐색(Product Discovery)이었다. 물론 그것도 일정에 포함되어 있었는데, 다만 아이디어를 탐색하는 데 모두가 참여할 필요는 없다는 말도 함께였다. 왜 하필 지금일까. 누구보다 함께하는 것을 강조하며 한 사람도 빠져서는 안 된다고 말하던 이도 있었는데. 그 방식에 피로를 느꼈는지, 동료들은 나와 있을 때만큼은 각자 할 수 있는 일을 하길 원한다며 솔직해졌다. 난감한 일이었다. 그들의 주장이 틀린 것은 아니니까. 적절한 분업이야말로 효과적인 협업이며, 모든 일에 모두가 참여해 온 기존의 방식이야말로 우직하다 못해 무식했다. 그러나 본래 워크숍은 팀 전체가 함께하는 자리였고, 이번에는 꼭 모두가 참여해야 했는데. 이미 같은 논의를 여러 차례 경험한 동료들은 자신이 더 보탤 것이 없다고 느꼈을지도 모른다.
어디서부터 설명해야 할까. 내가 너무 늦었나? 아님 반대로 성급했나? 노련한 조직이었다면. 아니, 그랬다면 처음부터 이런 일은 없었을지도. 정말 상황만이 이들을 이렇게 만든 것일까. 내가 겪은 시간은 그들에 비할 바가 아니었지만, 수개월째 진척이 없는 상황은 내게도 적지 않은 피로를 안겼다. 분명 방법이 있을 테지만, 어느덧 바닥난 인내심은 사고를 차단하기 시작했다. 전부 갈아엎고 싶었다. 목표를 위해 한 명씩 원온원하며 발품 파는 것은 어렵지 않았지만, 문제를 직설적으로 짚고 변화를 요구하기에는 함께 쌓은 신뢰가 부족했다.
그렇다고 더 지켜볼 만큼 가벼운 상황은 아니었기에, 이때만큼은 지시형 리더십이 필요했다. 차라리 내가 리더로 합류했다면 잠깐이나마 행동 양식을 강제로 정해 팀을 움직였을 텐데. 지시라는 말이 거북하게 들릴 수도 있지만, 리더십은 한 가지 유형과 태도를 고수하는 일이 아니라 상황에 맞는 방식을 선택하는 일이니까. 애초에 멈춰 있던 팀 하나의 일하는 방식을 바꾸는 일은 오히려 정당하다고 볼 수 있을 것이다. 그러나 이 팀에 그런 권한을 가진 사람은 없었다.
이제 와 제안을 무를 수도 없었다. 워크숍은 해야만 했고, 이제는 팀의 회고보다 아이디어 탐색의 결과를 만들어야 했다. 물론 PO가 혼자 들고 있던 짐을 덜어내는 것도 바라던 목적이었으니, 아쉽지만 이 일이라도 해내야 했다. 참여자는 Product Owner와 UX 디자이너, 그리고 프로덕트 엔지니어인 나까지 세 명이었다. 다른 이들은 뭘 했는지는 기억나지 않는다. 그들도 미뤄 두었던 해야 할 일이 있었을 것이다.
우선 기존 제품의 흐름을 모두 시각화했다. 그리고 PO가 붙들고 있던 큰 문제를 함께 쪼개고, 무엇부터 검증할 것인지 정리해 나갔다. PO가 원하는 그림은 한 번에 도달할 수 있는 것이 아니므로, 이를 작게 나누어 PO 자신과 동료들이 납득할 수 있는 단위로 만들어야 했다. 처음에는 잘 풀리는 듯했다. 혼자 감당하던 생각을 펼쳐 놓고 함께 고민하기 시작했다는 것만으로도 이전과는 달랐다. 그러나 시간이 갈수록 PO는 의욕을 잃어가는 듯했는데, 그 이유를 내가 단정할 수는 없었다. 워크숍은 끝까지 이어졌지만 마무리는 어딘가 개운하지 않았다. 우리가 다음으로 나아갈 발판을 만든 것인지, 끝내지 못한 일을 하나 더 남긴 것인지 알기 어려웠다.
그리고 머지않아 PO는 퇴사했다. 마지막 회식 자리에서 그는, 자신이 고집을 부렸다며 그간의 행동을 사과했다. 그것만으로도 나보다는 나았다. 그는 떠나기 전에 자신의 잘못을 인정했지만, 나는 내가 저지른 잘못에 대해 그러지 못했으니까.
나의 시도는 결실을 맺지 못한 채 멈추었다. 곧이어 조직 개편이 예고됐다. 구체적인 날짜까지 정한 것은 아니었으나, 나는 이곳을 떠나기로 마음먹었다.
균열
인내심은 어느덧 바닥나 있었고, 이 무렵부터 나는 냉소적으로 변하기 시작했다. 스쿼드만으로도 충분히 지쳐 있었는데, 동시에 나를 집요하게 괴롭혀 온 문제가 하나 더 있었기 때문이다. 때는 다시, 내가 스쿼드의 교착 상태를 인지하지 못해 기술 부채를 먼저 해결하려던 때로 돌아간다.
매니저와의 갈등은 코드 리뷰에서 먼저 모습을 드러냈다. 내가 그의 코드에 리뷰를 남기면 대화는 대개 서로의 의견을 반박하는 댓글로 이어졌다. 그 자체가 잘못은 아니다. 코드 리뷰는 서로 다른 판단을 드러내고 더 나은 결론을 찾아 상호 학습하는 자리이기도 하다. 하나의 리뷰에서 지나치게 긴 토론을 벌여 병목을 만든 일도 손에 꼽았다. 기억하기로는 세 번 정도였다. 실은 이미 구현했으니 다음에 개선하자며 내가 먼저 마무리하거나, 그가 답변 없이 PR을 병합하는 일이 대부분이었다.
그래서 문제는 길이가 아니라 반복이었다. 전에 남겼던 것과 같은 리뷰를 다시 남기고, 전에 내세웠던 것과 같은 논리로 거부했다. 같은 대화가 몇 번이고 되풀이되었지만 무엇이 좋은 코드인지에 대한 합의는 조금도 쌓이지 않았다. 토론은 끝나도 갈등은 그대로 남았다.
그러나 그가 내 코드에 유의미한 리뷰를 남기는 일은 거의 없었다. 달리 지적할 것이 없는 코드였을 수 있지만, 서로의 기준이 그토록 달랐음을 생각하면 의아했다. 바빠서 자세히 보지 못했을 수도 있지, 나도 설계와 동작 오류 외엔 자세히 안 보는 편이니까. 그러나 꺼림칙함은 계속해서 쌓이고 있었다.
갈등이 수면 위로 올라온 것은 내가 기술 부채를 해결하겠다고 선언하면서부터였다.
우리가 다루던 제품에는 오래된 결함이 있었다. 스쿼드의 이름과도 같은 핵심 개념—이 글에서는 ‘별’이라 부르겠다—하나를 보여주기 위해 고객사의 모든 별을 가져왔고, 별 하나만 수정해도 모든 별을 다시 불러왔다. 고객사에 따라 별의 수는 많게는 수만 개에 달했다. 여기서 파생된 문제 때문에 브라우저는 계속해서 멈췄고, 고객에게는 별을 여러 묶음으로 나누어 관리하라고 안내하고 있었다. 물론 모든 고객이 이에 동의하는 것은 아니었다.
처음부터 잘못된 설계였던 것은 아니다. 과거에는 고객사별로 관리할 별이 많지 않으리라 예상했다. 당시에 그렇게 판단했다면, 다음은 완성도보다 빠른 구현이 중요했을 테니 합리적인 결정이었다. 문제는 제품의 수요를 검증하고 전제가 달라진 지 수년이 지나도록 같은 구조를 유지했다는 데 있었다.
데이터 형태는 더 심각했다. 전체 별 목록을 보여주기 위해 만든 API 하나로 모든 기능을 구현하면서, 이를 사용하는 코드에는 응답값을 용도에 맞게 가공하는 수백 줄짜리 계산 함수가 여럿 생겨났다. 진작 API를 용도별로 나누고, 각 계산을 클라이언트와 API, 어느 쪽에서 맡을지 책임을 구분했어야 했다. 그러나 문제를 알리지 않았으니 다른 엔지니어들은 아무런 문제가 없는 줄 알았다더라. 훗날 조직 개편을 거치며 이 사실을 알게 된 백엔드 엔지니어들조차 왜 프론트엔드 엔지니어가 말없이 그렇게 구현했는지 납득하지 못했다. 이 함수와 타입들은 무엇을 위한 데이터인지 이름에서 유추할 수 없었고, 그동안 의도를 잃은 수백 줄의 함수가 여기저기 쓰이며 새로운 프로퍼티가 덧붙여지면서, 데이터가 어디에서 와서 어디로 흘러가는지 이해할 수 없게 되었다.
보통의 나쁜 코드는 해당 기능을 고칠 때 함께 손보면 그만이다. 문제없이 동작한다면 굳이 건드릴 이유도 없다. 하지만 이 구조는 달랐다. 이 개념은 우리 스쿼드가 맡은 도메인 그 자체였고, 이 결함은 우리가 만드는 모든 기능과 앞으로 만들 모든 기능에 심각한 영향을 주고 있었다. 간단한 기능 하나를 고쳐도 거의 모든 페이지가 영향 범위였다.
엔지니어로서 외면할 수 없는 문제다. 직업인이라면 자신이 지켜야 한다고 믿는 가치를 주장하되, 필요하면 이를 포기하고 팀에 가장 도움이 되는 방향으로 결정해야 한다. 그러니 반드시 지금 고치자는 뜻은 아니었다. 해결을 미루더라도 문제가 있다는 사실은 모두가 알아야 팀이 우선순위를 판단하고 적절한 때에 해결할 수 있으니까. 돈이 되는 것만 좇으며 모르는 척하는 것은 판단이 아니라 방관이었다. 나보다 약 한 달을 늦게 합류한 주니어 엔지니어도 같은 문제를 느끼고 있었는데, 강하게 주장하지는 못했지만 적어도 내 의견에는 동의했다.
그러나 매니저는 반대했다. 이유를 분명히 듣지는 못했다. 그에게 나는 제품보다 코드 품질에 집착하는 사람으로 보이는 듯했다. 진심으로 궁금해져 시니어 엔지니어에게 무엇을 기대하는지, 직무를 떠나 나라는 사람에게 어떤 역할을 기대하는지 물었다. 그는 잠시 고민했지만 기능을 빠르게 만드는 것 이상의 답을 내놓지 못했다.
그의 답변만 놓고 보면 미리 생각해 두지 않았던 것처럼 보이지만, 어쩌면 당시 스쿼드의 사정을 신규 입사자에게 솔직하게 말하기 어려웠을지도 모른다. 이미 무너져가는 것을 알고 있던 팀에 굳이 신규 채용으로 나를 배치한 이유가 분명 있었을 테니까. 그때의 내가 팀의 상황을 명확히 알았다면 교착을 푸는 데 먼저 힘을 썼을 것이다. 부채를 해결할 기회는 분명 다시 올 것이고, 그것이 팀의 입장에서도 더 합리적인 판단이었을 테니.
어쨌든 이번만큼은 강하게 밀어붙인 끝에 동의를 얻었다. 그래야만 했다. 나는 팀의 요구에 따라 제품을 개선했고, 그 경험을 근거로 다시 주장했으니까. 문제를 모르는 다른 직무의 동료들에게는 내가 제품을 두고 다른 일로 빠지는 사람처럼 보였겠지만, 나도 매번 충돌을 겪느라 제대로 공유할 수 없는 나름의 고충이 있었다. 그렇게 일주일을 온전히 리팩터링에 쏟았던 것으로 기억한다. 그리고 이를 마지막으로 그가 내 주장에 물러선 적은 한 번도 없었다.
단절
매니저와 충돌하던 사람은 나뿐만이 아니었다. 다른 시니어 엔지니어도 챕터 미팅과 장문의 토론 스레드에서 그와 반복해서 부딪히고 있었다. 나는 그 시니어의 행동을 본받아 이번 리팩터링의 진행 과정과 그때마다 내린 판단을 커밋 단위로 정리해 발표했다. 혼자 코드를 고치는 데서 끝내지 않고, 무엇을 왜 바꾸었는지 사고 과정을 챕터에 남기려 했다.
그러나 반응은 미지근했다. 평소의 모습대로라면 여기서도 충돌이 일어났어야 했다. 하지만 그는 그냥 듣기만 했고, 별다른 의견 없이 자리를 떠났다. 이전부터 품고 있던 의심이 확신에 가까워졌다. 어떤 이유로든 그는, 지금의 문제를 나와 같은 수준으로 보고 있지 않았다.
기술적인 문제는 우리 스쿼드에만 있지 않았다. 우리가 맡은 영역이 유독 심각한 레거시였지만, 제품 전체의 코드베이스도 좋은 상태와는 거리가 멀었다. 나쁜 코드가 있다는 사실 자체는 괜찮았다. 과거의 잘못된 판단이 남긴 부채도, 당시에는 합리적인 이유로 미뤄 둔 부채도 있을 수 있다. 역량 부족 자체도 잘못은 아니었다. 문제는 같은 현상이 반복되는데도 피드백을 거부하고, 이를 누구도 막지 못한다는 데 있었다. 어지르는 사람과 치우는 사람이 따로 있었다.
개인이 뒤따라다니며 수습하고 변화를 이끌어내는 것보다 리더가 개입하는 편이 빨랐다. 그러나 그 역할을 맡아야 할 챕터 리드이자 매니저는 애초에 이를 문제로 여기지 않았고, 개인들이 개선을 요구할 때마다 대체로 반대했다. 코드 리뷰에서도, 챕터 미팅에서도, 기술 부채를 이야기할 때도 비슷했다. 시니어라면 문제 해결을 주도하고 사람들을 이끌 수 있어야 한다고 말하는 동시에 나를 앞장서서 막던 사람이었는데, 그는 자신이 줄곧 반대해 왔다는 사실조차 인지하지 못하는 듯했다. 오히려 내게 unlearning을 요구했고, 나는 억울함을 참지 못해 원온원에서 언성을 높였다. 그와 아무리 더 이야기한들 서로에게 닿지 않으리라는 생각이 들었다.
나는 결국 그를 포기했다. 그렇다고 동료들까지 포기한 것은 아니었다. 어차피 서로가 피드백을 받아들이지 못하니, 그냥 무시하기로 했다. 상황은 전혀 나아지지 않았지만 적어도 내 정신 건강에는 그편이 이로웠다. 주기적으로 있던 그와의 원온원도 바쁘다고 미루거나 아무 문제도 없다며 말을 줄였다. 손가락 마디만 한 원형 탈모는 덤이었다.
시간이 지나 그는 갑자기 다른 스쿼드로 떠났다. PO가 퇴사한 것과 비슷한 시기였다. 그에게서 벗어난 나와 주니어 엔지니어는 비로소 스쿼드의 기술 부채를 어떻게 다룰지 함께 고민하기 시작했다. 당장 모든 것을 고치겠다는 계획은 결코 아니었다. 지금까지 쌓아온 문제들을 팀이 제어할 수 있도록 어떤 순서와 전략으로 풀어갈지를 계획하는 일이었다.
그 시도는 결과적으로 성공했지만, 그동안 나는 스쿼드와 챕터 어디에서도 소속감이나 안정감을 얻지 못했다. 나 외에 유일한 시니어 엔지니어였던 동료도 곧이어 회사를 떠났다.
전환
그 무렵 이상 신호는 회사 밖에서도 나타났다. 회사는 오랫동안 ‘빠른 기능 구현’을 좋은 성과와 같은 것으로 여겼다. 제품의 품질은 날이 갈수록 떨어지면서 결국 고객의 날 선 비판을 들어야 했는데, 구체적인 내용은 이곳에 적을 수 없지만 B2B 고객이 이토록 거친 피드백을 주는 일은 드물었다.
처음에는 그저 개인의 태도라고 생각했다. 그러나 분명 회사의 문화였다. 왜 이런 분위기가 형성됐는지는 누구도 몰랐다. 메이커의 존재 의의는 무언가를 구현하는 데 있지만, 그것이 전부는 아니어야 하는데. 안타깝게도 도입기에 통했던 성공 방식이 지금의 조직에서 철칙으로 굳어졌으리라, 그렇게 추정했다.
조직 개편 전후로 나쁜 결과가 잇따르고 나서야 회사도 태도를 바꿨다. 슬랙에는 전략 변경이 공지됐다. 앞으로 스쿼드와 메이커의 행동 양식도 달라질 것이라는 설명과 함께. 돌이킬 수 없을 만큼 늦지는 않았으나, 확실히 늦은 변화였다.
나는 전부터 비슷한 문제를 주장해 왔다. 대체로 받아들여지지 않았지만 동의하는 리더도 있었으니, 내가 모르는 곳에서 변화를 준비하는 데 시간이 필요했으리라 생각한다. 그래서 다른 사람들의 이야기를 직접 들으며 문제를 더 넓게 조사하고 있었다. 이제는 사라져버린 스쿼드의 경험에서 시작된 문제의식. 내 생각이 여전히 옳다면, 이번에는 설득을 위한 더 많은 근거가 필요했다. 수집한 현상들의 인과 관계를 연결해 악순환을 찾고, 시스템 원형과 인과 루프 다이어그램으로 시각화했다.
그러나 일은 이미 벌어졌다. 충분히 준비할 틈도 없이, 고객의 피드백에 뒤이어 공지가 올라왔다. 나는 정리 중이던 자료를 곧바로 답글에 붙였다. 예견했던 결과를 막을 수는 없었으나, 그 결정이 왜 필요했는지, 앞으로 무엇을 바꾸어야 할지 논의할 근거는 될 수 있었다. 이후 여러 미팅과 원온원이 뒤따랐고, 비로소 대화가 시작됐다.
다시 스쿼드로 돌아와서, 조직 개편이 끝났다고 모든 문제가 곧바로 풀릴 리는 없었다. 맡은 일은 여전히 같았지만 구성원의 절반 이상이 교체됐고, 우리는 처음부터 다시 합을 맞춰야 했다. 서로가 어떻게 일하는지 알아가는 데는 앞으로도 오랜 시간이 필요할 터였다. 그래도 이번 스쿼드는 상식적으로 움직일 조짐을 보였다. 나는 충분히 지쳐 있었지만, 긍정적인 신호인 건 분명했다.
재건
전략은 바뀌었고 팀 빌딩도 필요했지만, 우선 급한 불부터 꺼야 했다. 내가 합류하기 전을 포함해, 이전 스쿼드가 2년 가까이 표류하는 동안 쌓인 고객의 요구는 적지 않았다. 그 탓에 풀어야 할 고객의 문제와 접근은 이미 정해져 있었는데, 이는 내가 바라던 형태의 일이 아니었다. 그렇다고 대충 할 이유는 없었다.
이 일을 진행하며 발견된 팀의 문제는, 계획을 실행한 뒤에야 결정되지 않은 사항들이 계속 드러났다는 점이었다. 해보기 전에는 모든 것을 알 수 없기에 어쩌면 당연한 현상이지만, 그 정도가 심했다. 아무 일도 하지 못했던 팀에 있었던 나로서는 과거의 모습들이 겹쳐 보였다.
다행히도 이번에는 팀이 그 현상을 그대로 두지 않았다. 문제가 있으면 살피는 게 당연한 동료들이었고, 우리는 구현을 시작하기 전에 해결하려는 문제와 기대 효과, 다른 작업과의 의존성을 먼저 확인하기로 했다. 어디까지 만들어야 완료한 것으로 볼지 인수 기준으로 맞추고, 누가 무엇을 실행할지도 미리 정했다. 우리에게 맞는 준비의 정의(Definition of Ready)를 만들어 나갔다. 분명 내가 주도했고 없는 것보다는 나았지만, 내게는 애초에 이런 상황이 벌어진다는 사실부터 만족스럽지 않았다. 점점 그들처럼 조급해졌다.
급한 작업을 모두 끝낸 다음에야 우리는, 잠시나마 제품·기술 부채를 해결할 수 있게 되었다. 전략 변경에 따른 새로운 PO의 제안이었고, 스쿼드 구성원 모두가 동의한 채 이런 일을 하는 것은 처음이었다. 앞서 동료 엔지니어와 세운 계획은 일종의 타협이었다. Layered Architecture를 설계해 레거시와는 격리된 새로운 틀을 만들어두고, 기능을 구현하며 레거시 코드를 건드려야 할 때 개선해 옮기는 방식이었다. 그러나 지금 제품의 상태라면 이렇게 리팩터링을 위한 시간이 주어지는 것도 분명 좋은 기회였다.
조직 개편 전에 별—스쿼드의 핵심 개념—의 데이터 형태와 가공 함수를 분류하고 개선해 둔 덕분에, 이번에는 API를 용도에 맞게 나눌 수 있었다. 다음으로는 대량의 별을 처리하는 가공 함수의 알고리즘을 개선했고, 병목을 제거하여 모든 별을 보여주는 UI의 렌더링 시간을 정상 범위 안으로 단축했다. 브라우저가 멈추는 것을 피하려고 고객에게 별을 여러 묶음 단위로 나누어 사용하라는 안내는 더 이상 필요 없어졌고, 별을 한곳에서 관리하길 원하던 고객사의 계약 조건도 수용할 수 있게 됐다. 나에게는 이 회사에서 처음으로, 새 기능이 아니라 기존 기능의 기술적인 문제를 해결해 비즈니스에 영향을 준 경험이었다.
그러나 기쁘지는 않았다. 새로운 경험으로 모든 문제를 한 번에 해결하려던 고집과 기술 부채를 문제로 보지 않던 무지함이 고객을 오랫동안 불편하게 만든 것이니까. 별일도 아닌 걸 질질 끌다가 이제야 해결한다는 생각뿐이었다.
나에게는 더 이상 마음의 여유가 없었고, 이런 생각을 하는 내가 싫어 퇴사를 결정했다.
매듭
3개월 뒤를 퇴사일로 정했다. 나는 원래 퇴사일을 여유롭게 정하는 편인데, 마음의 준비를 하기에는 충분히 길고, 생각이 달라진다면 결정을 뒤집기에도 늦지 않은 시간이다. 회사에는 두 달 뒤에 알리기로 했다. 재직한 지 정확히 1년이 되던 때였다.
떠날 날짜를 정하고 나니 오히려 마음은 차분해졌다. 회사에 대한 기대는 거의 사라졌지만, 그렇다고 손 놓고 있을 생각은 없었다. 떠나기 전까지 무엇을 남겨야 회사에 도움이 될지 고민했다.
마지막으로 붙들고 있던 문제는 크게 두 가지였다. 하나는 직업인으로서, 동료들이 외부 도움 없이도 코드를 제어하고 관리할 수 있는 기반을 남기는 것. 다른 하나는 리더십으로, 회사의 구조적인 문제를 분석해 해결의 실마리를 남기는 것. 후자는 앞서 말한 그것이다. 구조적인 문제가 풀리면 스쿼드 내부, 그리고 스쿼드와 이해관계자 사이의 문제는 알아서 풀 수 있으리라 생각했다.
그래서 통합 테스트 환경을 만들었다. 내가 떠난 뒤에도 동료들은 이 낡은 코드 위에서 계속 제품을 만들어야 했는데, 나쁜 코드 탓에 변경의 영향 범위는 넓고 예측하기도 어려웠으니, 기존 동작이 망가지지 않았는지 확인할 방법이 필요했다. E2E 테스트는 있었지만 우리의 빠른 작업 흐름에는 맞지 않아 방치돼 있었고, 엔지니어들은 코드를 고치면서 결과를 즉시 확인할 수 있어야 했다. 이미 있던 단위 테스트 환경을 그대로 쓸 수 있었다면 좋았겠지만, 소스코드는 여러 페이지에 걸친 동작을 테스트할 수 있도록 작성되지 않아, 스쿼드의 업무를 끝내고 남는 시간마다 하나씩 리팩터링해야 했다.
전략 변경은 챕터에도 영향을 미쳤다. 기술 부채를 해결하라는 지시와 함께 여러 과업이 주어졌고, 나는 스쿼드에 새로운 아키텍처를 도입한 경험이 있었기에 챕터의 코드 작성 패턴과 규칙을 통일할 기준을 마련하는 TF를 맡았다. 계획에 없었고 이미 바빴지만, 무리해서라도 떠나기 전에 팀에 더 도움이 되고 싶었다. 이 과정에서 매니저는 다른 TF에 참여하려던 동료 한 명을 의사결정의 균형을 맞춘다는 이유로 우리 TF로 옮겼는데, 그 동료는 신중한 성격으로 반대를 자주 했지만, 자신이 블로커가 될까 봐 걱정하던 사람이었다. 나는 그가, 나를 믿지 못해 자신의 편이라 여기는 동료를 붙였다고 의심했다. 그건 사실이 아니었겠지만 그를 불신했던 그때의 나에게는 불쾌한 경험이었다. 의도가 무엇이었든, 우리는 아무런 문제없이 챕터가 오랫동안 합의하지 못했던 좋은 코드와 설계의 기준, 이를 적용하는 방법과 해결 사례를 문서로 남겼다.
이를 계기로 내가 스쿼드에서 진행하던 개선도 알려졌다. 사실 진작에 공유했었지만, TF의 결과물 덕분에 확실히 이목을 끌었다. 매니저는 설계 의도와 효과를 발표해 달라고 요청했다. 다른 동료들도 원하던 발표였고, 분명 기대했던 반응이었다. 그러나 반가움보다 ‘이제 와서 왜?’라는 생각이 먼저 들었다. 지금까지 반대만 했었는데. 나는 이미 그의 어떤 행동도 곧이곧대로 받아들이지 못하는 사람이 되어 있었고, 그런 나를 혐오하며 반드시 떠나야겠다고 다짐했다.
용기
그렇게 두 달이 흘렀다. 나는 예정대로 회사에 퇴사 의사를 알렸다. 그동안의 갈등과 노력을 알아준 어떤 리더는 부서 이동을 권하며 나를 회유했으나, 내 마음은 결코 변하지 않았다. 내게 지난 경험은 한 것도 배운 것도 없이 버려진 시간으로 느껴졌고, 무언가 만들고 싶다는 억제된 욕구를 회사를 떠나 1인 창업으로 풀고 싶었다. 사실은 현실 도피를 위한 자기합리화였는지도 모른다. 계획이 있다고 스스로를 속여야 떠날 수 있었으니까.
그때는 마침 인사평가 기간이었다. 퇴사까지 일주일도 남지 않았을 무렵, 한 동료에게서 내가 무섭게 말한다는 피드백을 받았다. 이미 알고 있던 사실이라 놀랍지는 않았다. 표현은 이전보다 거칠어졌고, 표정에서 냉소를 숨기지 못했다. 동료가 같은 잘못을 반복하면 필요 이상으로 날을 세웠고, 회고에서는 동료들이 감당할 이유 없는 감정을 드러냈다. 바깥의 동료들은 몰랐겠지만, 적어도 스쿼드 안에서의 나는 생각을 편하게 나누기 어려운 사람이 되어 있었다.
그런 행동을 하는 나와 이를 지켜보는 내가 분리되기 시작했다. 처음 겪는 괴로움이었다. 모든 일에 항상 진심이 필요하다고 생각하진 않지만, 결코 내 방식은 아니었다. 나는 일정 초대 메일로 장문의 편지까지 쓰던 사람이었으니까. 아마 그때의 나는 회사와 동료들로부터 존중받기는커녕 핍박받고 있다고 느꼈던 것 같다.
이미 알고 있었다는 사실은 잘못을 가볍게 하지 않는다. 나는 문제를 해결해야 한다는 조급함을 이유로, 그 문제를 만든 것이 아닌 동료들에게까지 쌓인 감정을 떠넘겼다. 문제를 함께 풀 사람을 설득의 대상이나 잘못을 통제해야 할 대상으로만 대했다. 더 이상 태도를 조절하지 못했고, 서로를 위해서라도 회사를 제 발로 떠나야 했다.
그러나 최악인 것은 피드백을 받고도 떠나기 전에 사과하지 않았다는 것이다. 애초에 깊은 관계를 맺지도 못했지만, 회복할 기회마저 놓쳤다. 퇴사가 얼마 남지 않았다는 사실 뒤에 숨은 채 도망치듯 회사를 떠났고, 먼저 자신의 잘못을 사과하고 떠난 Product Owner가 부러웠다.
그리고 매니저는 고객과 가까이서 요구사항을 빠르게 구현하는 데 강점이 있는 사람이었고, 그 지점에선 분명히 나보다 뛰어났다. 그와의 갈등은 그저 인사 배치의 실패에 불과했다. 누구도 직접 맡겨보기 전에는 그가 역할을 잘 해낼지 알 수 없으니까. 회사는 가능하면 그의 강점을 살리는 방향으로 역할을 조정해야 했고, 지금의 포지션을 그대로 유지하더라도 성장할 수 있도록 적절한 피드백을 제공해야 했다. 그랬다면 서로 좋은 동료가 되었을지도. 그러므로 결과는 실패가 맞지만, 이를 회사의 잘못이나 개인의 악의라고 말하고 싶지는 않다. 나는 이제 그를 원망하지 않는다. 지금까지 나의 매니저를 나쁘게만 적은 듯해 글을 덧붙인다.
물론 결과는 내 문제의식이 틀리지 않았음을 보여주었다. 내 주장은 고객의 반응이 되어 돌아왔고, 회사는 방향을 바꿨다. 받아들여지지 않던 문제들은 뒤늦게 회사의 과제가 됐다. 인정받지 못하는 일을 하려면 용기가 필요하다. 누구도 듣고 싶어 하지 않는 말을 하고, 반대 속에서도 해야 한다고 믿는 일을 주장해야 하니까. 그러나 내가 옳았다는 사실이 내 행동을 모두 정당화하지는 않는다.
나는 반대 속에서도 주장할 용기도 회사를 떠날 용기도 있었지만, 그 과정에서 잘못한 일을 인정하고 사과할 용기는 없었다. 내가 옳았다는 결과는 면죄부가 아니었다. 나는 필요한 일을 했고, 동시에 동료들에게 잘못했다. 둘 중 하나가 다른 하나를 지우지는 않는다. 내게 부족했던 것은 미움받을 용기보다, 용서받을 용기였나 보다.
이 글이 그때 하지 못한 사과를 대신할 수는 없다는 건 안다. 그럼에도 내가 옳았다는 기억만 남기지 않기 위해, 반성의 의미로 내가 저지른 잘못들을 비겁하게나마 이곳에 기록하며 글을 마무리한다.