그 PR은 상태 관리 구조에 대한 것이었다. 컴포넌트 트리 깊숙한 곳에서 서버 데이터를 어떻게 갱신할 것인가. 나는 전역 상태에 캐싱하는 방식을 밀었고, 같은 팀 시니어는 서버 상태와 클라이언트 상태를 분리하자는 의견이었다.
나는 확신에 차 있었다. 기존 프로젝트에서 비슷한 구조를 써본 경험이 있었고, 그때 잘 동작했다. "이미 검증된 패턴이에요"라는 말을 리뷰 코멘트에 두 번이나 썼다. 시니어가 단점을 지적하면 반론을 달았고, 반론에 재반론이 붙었다. 코멘트가 쌓이면서 PR은 점점 토론장이 됐다.
이틀째 되는 날, 퇴근길 지하철에서 시니어의 코멘트를 다시 읽었다. 감정을 빼고, 내가 반박하려는 의도 없이, 순수하게 텍스트만 읽어봤다. 솔직히, 말이 됐다. 아니, 내 방식보다 더 말이 됐다.
순간 가슴이 쿵 내려앉는 느낌이었다. 이틀 동안 내가 지켜온 게 "더 나은 방식"이 아니라 "내 자존심"이었다는 걸 깨달았다.
왜 인정이 이렇게 어려운가
프로그래밍이라는 직업의 특성상, 우리는 논리적이라고 스스로를 믿는다. 감정이 아니라 근거로 판단한다고 생각한다. 코드는 맞거나 틀리거나 둘 중 하나고, 나는 맞는 쪽을 고른다고 믿는다.
그런데 실제로 코드 리뷰에서 벌어지는 일은 그렇지 않다. 코드에 대한 의견이 곧 나의 능력에 대한 평가처럼 느껴진다. "이 방식은 비효율적이에요"라는 코멘트가 "당신의 실력이 부족하네요"로 번역된다. 머리로는 아닌 걸 아는데, 감정은 그렇게 안 움직인다.
특히 주니어 시절에는 이게 심했다. 코드 한 줄 한 줄이 나의 존재 증명 같았다. 내가 작성한 코드가 틀렸다는 건 내가 이 자리에 있을 자격이 부족하다는 뜻 같았다. 그래서 지적을 받으면 방어부터 했다. "이건 이렇게 의도한 거예요." "이 상황에서는 이게 맞아요." 근거를 찾아서 반박하는 게 배우는 것보다 먼저였다.
사실 그때 시니어가 한 번 더 강하게 밀었으면 그냥 "알겠습니다"라고 하고 고쳤을 거다. 하지만 그건 인정이 아니라 복종이다. 내가 틀렸다고 이해한 게 아니라, 힘의 논리에 따른 거다. 겉으로는 같아 보여도 완전히 다른 거다.
그래서 뭐라고 했는가
다음 날 아침, 출근하자마자 PR에 코멘트를 달았다.
"다시 생각해봤는데, 제 접근 방식에 문제가 있는 것 같습니다. 서버 상태를 전역에 캐싱하면 동기화 이슈가 생기는 건 맞고, 그 부분을 제가 과소평가했어요. 제안해주신 구조로 가는 게 장기적으로 더 낫겠습니다."
타이핑하는 데 5분이 걸렸다. 문장을 쓰고 지우고를 반복했다. "부분적으로 동의한다"고 쓸까, "절충안을 제안한다"고 쓸까 고민했다. 하지만 그건 또 다른 형태의 방어였다. 틀린 거면 틀렸다고 말하는 게 맞았다.
팀원들의 반응이 의외였다. 시니어는 "솔직하게 말해줘서 고맙다. 사실 나도 이틀 동안 내가 틀린 건 아닌지 계속 고민했다"고 했다. 다른 팀원은 슬랙으로 DM을 보내왔다. "그 코멘트 보고 놀랐다. 솔직히 나도 비슷한 상황에서 끝까지 우긴 적 있는데, 저렇게 인정하기 쉽지 않다."
예상했던 반응은 "그러니까 내 말이 맞잖아"였다. 하지만 아무도 그런 말을 하지 않았다. 오히려 나를 더 신뢰하게 됐다는 뉘앙스였다. 이상하게 들릴 수 있는데, 틀렸다고 인정하는 게 존경을 사는 방법이 될 수 있다는 걸 그때 처음 알았다.
회의실에서의 그 순간
비슷한 일이 몇 달 뒤에 또 있었다. 이번에는 코드가 아니라 기술 스택 선택에 대한 회의에서였다.
새 프로젝트의 상태 관리 라이브러리를 정하는 자리였다. 나는 이전 회의에서 특정 라이브러리를 강하게 추천했었다. 사용 경험도 있고, 번들 사이즈도 작고, 러닝커브도 낮다고 했다. 다른 팀원이 대안을 제시했는데, 나는 "그건 오버 엔지니어링이에요"라고 잘랐다.
그리고 일주일 동안 두 라이브러리를 각각 프로토타입으로 만들어보는 시간을 가졌다. 직접 써보니, 내가 추천한 쪽이 현재 프로젝트의 요구사항에 맞지 않았다. 특히 서버 컴포넌트와의 통합 부분에서 상대편이 훨씬 매끄러웠다.
회의 시간. 모두가 자리에 앉아 있었다. 나는 "프로토타입을 만들어보니까, 제가 지난번에 오버 엔지니어링이라고 한 게 사실은 더 적합한 선택이었습니다. 제가 틀렸어요"라고 말했다.
방 안이 잠깐 조용해졌다. 그 2초가 꽤 길게 느껴졌다. 그리고 프로젝트 매니저가 "그러면 그걸로 갈까요?"라고 해서 논의가 빠르게 정리됐다.
회의 후에 깨달은 거다. "틀렸다"고 말하니까 논의가 빨라졌다. 아무도 메뉴얼하게 비교 분석표를 만들 필요가 없었고, 감정적인 논쟁을 할 필요도 없었고, 정치적인 타협을 할 필요도 없었다. 사실을 말했을 뿐인데 모든 게 간결해졌다.
틀릴 수 있다는 전제로 시작하기
이후로 의식적으로 연습하는 것들이 있다.
코드 리뷰에서 강한 의견을 낼 때, 마지막에 "제가 놓치고 있는 맥락이 있으면 알려주세요"를 붙인다. 처음에는 형식적인 문장이었는데, 실제로 놓치고 있는 맥락이 있는 경우가 꽤 많았다. 내가 모르는 히스토리, 내가 고려하지 못한 제약 조건, 내가 경험하지 못한 엣지 케이스.
회의에서 내 의견을 말할 때, "확실하지 않은데"를 앞에 붙인다. 확실하지 않은 건 진짜 확실하지 않은 거니까. 이게 약해 보일 수 있다고 걱정했는데, 실제로는 반대였다. 불확실성을 인정하는 사람의 말에 사람들이 더 귀를 기울였다. 항상 확신에 차 있는 사람보다 가끔 "모르겠다"고 말하는 사람이 더 믿음직스러웠다.
동료에게 도움을 요청하는 것도 틀렸다고 말하는 것의 연장선이라고 느낀다. "이거 모르겠어요"가 "이거 틀렸어요"만큼 어렵다. 둘 다 내가 완벽하지 않다는 걸 드러내는 행위니까. 그런데 팀에서 일하면서 완벽한 사람은 한 명도 못 봤다. 완벽한 척하는 사람은 봤다. 그런 사람과 일하는 건 피곤하다.
팀 문화와의 관계
개인의 노력만으로 되는 문제는 아니다. "틀렸다"고 말했을 때 "그러니까 네가 부족한 거 아니야?"라고 돌아오는 팀이라면, 아무도 틀렸다고 말하지 않을 거다. 당연하다. 합리적인 자기 방어다.
내가 운이 좋았던 건, 팀이 실수에 관대한 편이었다는 거다. 장애가 나면 원인을 분석하지, 사람을 탓하지 않았다. 코드 리뷰에서 의견이 다르면 토론하지, 직급으로 누르지 않았다. 이런 환경이 전제되어야 "틀렸다고 말하기"가 가능하다.
반대로, 누군가가 먼저 틀렸다고 말하면 그 팀의 분위기가 바뀌기도 한다. 시니어가 "내가 이번에 판단을 잘못한 것 같아"라고 회고에서 말하는 순간, 주니어도 "저도 실은 이 부분에서 실수가 있었어요"라고 말하기 쉬워진다. 솔직함은 전염된다.
예전에 있었던 팀에서는 반대의 경험도 했다. 회고 시간에 누군가 문제를 지적하면 분위기가 싸해졌다. "그때 그렇게 결정한 건 다 이유가 있었어요"라는 방어가 먼저 나왔다. 문제를 인정하면 책임을 져야 하고, 책임을 지면 평가에 불이익이 생길 수 있다는 암묵적인 공포가 있었다. 그 팀에서는 아무도 틀렸다고 말하지 않았고, 결과적으로 같은 실수가 반복됐다. 문제를 인정하지 않으니 개선할 수도 없었던 거다.
두 팀의 차이는 개인의 성향이 아니라 구조의 차이였다. 실수를 인정했을 때 벌을 받는 구조와, 실수를 인정했을 때 배울 수 있는 구조. 같은 사람이라도 어떤 구조에 있느냐에 따라 완전히 다르게 행동한다.
틀림의 크기가 다를 때
사소한 틀림은 인정하기 쉽다. 변수명이 어색하다는 지적, CSS 속성 순서를 잘못 쓴 것, 오타. 이런 건 "아 맞네요, 감사합니다" 하고 넘어가면 된다. 자존심이 상할 일이 아니다.
어려운 건 "내가 깊이 생각하고 확신했던 것"이 틀린 경우다. 설계를 잘못 한 거, 기술 선택이 틀린 거, 팀에게 잘못된 방향을 제시한 거. 투자한 시간과 감정이 클수록 인정하기 어렵다. "여기까지 왔는데 틀렸다고 하면 지금까지 한 게 다 무의미해지잖아"라는 생각이 든다. 하지만 방향이 틀린 걸 알면서 계속 가는 게 더 큰 낭비다. 빨리 인정하고 돌아서는 게 결과적으로 시간을 아낀다.
매몰 비용의 오류라는 게 이런 거다. 이미 투자한 것에 대한 집착 때문에 잘못된 방향을 계속 가는 것. 이론으로는 다 아는데, 막상 내 상황이 되면 쉽지 않다.
여전히 어렵다
오해하지 말아야 할 게, 나는 이제 틀렸다고 잘 말하는 사람이 된 게 아니다. 여전히 어렵다. 코드 리뷰에서 지적을 받으면 아직도 첫 반응은 방어다. 0.5초 동안 "왜 이걸 지적하지"라는 생각이 스치고, 의식적으로 그걸 누르고 "잠깐, 이 코멘트를 열린 마음으로 읽어보자"로 전환한다.
0.5초의 방어 반응이 사라지진 않았다. 다만 그 뒤의 0.5초가 달라졌을 뿐이다. 자동으로 반박을 타이핑하는 대신, 한 번 더 읽고 생각한다. 이게 전부다. 화려한 성장 서사 같은 건 없다. 그냥 0.5초의 습관을 바꾸려고 매일 애쓰고 있다.
그리고 가끔은, 이틀 동안 고수한 내 의견이 정말 맞는 경우도 있다. 틀렸다고 인정하는 연습은, 무조건 양보하라는 뜻이 아니다. 내가 맞을 수도 있고 틀릴 수도 있다는 가능성을 항상 열어두라는 뜻이다. 확신이 아니라 호기심으로 토론에 임하라는 거다.
누군가에게 "틀렸다"고 말하는 건 한 문장이다. 하지만 그 한 문장에는 자존심을 내려놓는 용기, 상대방의 말을 진심으로 들었다는 증거, 팀의 결과를 나의 체면보다 우선한다는 선언이 담겨 있다. 한 문장치고는 꽤 무겁다.
그래서 연습이 필요하다. 매일, 반복적으로.
최근에 후배 개발자와 1:1을 하다가 이런 이야기를 들었다. "코드 리뷰에서 지적받으면 밤에 잠이 안 와요. 내가 부족한 건가 싶어서." 그 말을 듣고 예전의 내가 떠올랐다. 나도 그랬다고 말해줬다. 그리고 지적을 받는 건 부족해서가 아니라, 팀에서 일하고 있기 때문이라고. 혼자 일하면 아무도 지적하지 않지만, 그게 내 코드가 완벽해서는 아니라고.
틀렸다고 말하는 건 재능이 아니라 기술이다. 기술은 연습으로 는다.
