우리는 코드 리뷰를 잘하고 있을까요?

안녕하세요, 스타일쉐어에서 안드로이드 개발을 맡고 있는 이길현 개발자라고 합니다.
여러분들은 코드 리뷰에 대해서 어떻게 생각하시나요? 현재 코드 리뷰를 잘하고 계신가요?

제가 거쳐온 회사들은 코드 리뷰 정책이나 문화가 모두 달랐어요. 첫 회사는 PR이란 개념이 아예 없었는데 신뢰라는 변명 아래 일단 머지하고 보는 식이었죠. 충돌이 발생하거나 궁금한 것이 생기면 메신저나 오프라인으로 찾아가서 물어보는 방식이었어요.

한 회사에서는 제가 작성한 코드를 배포하기 위해 리뷰를 필수로 거쳐야 했지만, 코드에 대한 피드백 없이 단순히 코드 베이스의 변경을 확인하는 정도에 그쳤어요.

이전 회사에서의 경험과 달리 스타일쉐어에서는 PR을 작성하고 코드 리뷰를 하는 데 매우 공을 들이고 있어요. 때로는 동료분이 작성한 코드를 리뷰하느라 하루를 보낸 적도 있었고, “이런 작은 것까지 수정 요청을 주고받는 게 맞는 걸까?”라는 생각이 들 때도 종종 있었고요. 코드 리뷰에 대한 고민이 많은 팀이기에 코드 리뷰를 잘하는 다른 조직의 이야기가 궁금하더라고요.


 

[백명석님의 초청 강연]

그러던 중 코드 리뷰에 대한 이야기를 들을 기회가 생겼어요. 사내에서 스타일쉐어와 29CM 개발팀을 위해 종종 연사를 초청해 강연을 부탁드리는데요, 이번엔 CTO님 찬스로 11번가에 계신 백명석님을 초청해 코드 리뷰를 주제로 많은 이야기를 들을 수 있었어요.

백명석님은 이전부터 브런치, 유튜브 등 미디어에서 소프트웨어 공학을 주제로 다양한 글과 영상을 작성해오셨는데요, 11번가라는 큰 조직에서 풍부한 경험을 토대로 어떻게 코드 리뷰 문화를 리드하고 있으신지 들을 수 있는 강연이었습니다.

제 주관적인 입장에서 기억에 남았던 몇 가지 이야기들을 요약했습니다.

 

[왜 코드 리뷰를 해야 할까요?]

강연 도입부에서 코드 리뷰를 왜 해야 하는지에 대한 이야기를 들을 수 있었어요. 시장은 항상 변하기 마련이라 비즈니스는 복잡하고 불확실하며 예측할 수 없는데요, 변화하는 시장에 맞춰 더 빨리 비즈니스를 전개해야만 한다고 해요. 그러기 위해 소프트웨어는 더 자주, 신속하게, 신뢰성 있게 전달되어야 하죠. 결국 비즈니스는 소프트웨어의 생산성과 직결되어 있습니다.

개발자들이 많아진다고 생산성이 선형적으로 증가하지 않는다는 것은 많은 분이 알고 계실 거예요. 사람이 많아질수록 커뮤니케이션에 점점 더 큰 비용을 사용하기 때문이지요. 비슷하게, 릴리즈하면 할수록 개발 비용은 점점 증대하게 되고 생산성은 점점 저하되는 현상이 나타납니다. 릴리즈를 거듭할수록 소프트웨어가 점점 거대해지거든요.

출처: 클린 아키텍처

소프트웨어가 거대해지더라도 생산성을 유지하기 위해서는 좋은 아키텍처, 좋은 코드, 좋은 설계가 동반되어야 해요. 코드 리뷰는 이를 위한 일종의 검수 과정인데요, 새로 작성되는 기능이 버그가 없고 의도대로 동작하는 것을 확인하는 것은 물론이고 약속한 아키텍처를 잘 따르고 있는지, 다른 사람이 읽는 데 문제가 없는 코드인지, 올바르게 설계되었는지 확인하는 과정이기도 해요.

코드 리뷰는 소프트웨어 공학 관점에서 볼 때 이처럼 코드의 품질과 생산성을 유지하기 위해서도 필요하지만 다른 부수적인 효과도 있다고 해요. 리뷰를 통해 코드에 대한 피드백을 주고받으면서 팀 전체가 성장할 기회가 되기도 하는데, 가령 누군가 잠재적인 위험이 있는 코드를 작성한다면 리뷰어는 해당 코드에 대한 문제점과 해결책을 제시하고 작성자는 자신이 몰랐던 새로운 사실에 대해 알게 되겠죠.

또한 리뷰 과정을 통해 코드가 작성자 한 사람에게 의존되거나 혼자만 책임지는 것이 아닌 팀 전체가 기여하고 오너십을 발휘하는 기반이 되기도 해요.

[코드 리뷰가 잘 안 돼요. 왜죠?]

강연에서 코드 리뷰가 어려운 이유를 들을 수 있었는데요. 강연을 들으면서 예전의 제 모습이 떠올라 많이 공감되고 웃을 수 있던 시간이었어요.

코드 리뷰는 작성자와 리뷰어가 지식과 경험을 공유하고 토의하며 상호 학습을 통해 성장할 좋은 기회이지만, 이 과정에서 피드백의 방향에 따라 작성자가 개인에 대한 공격으로 받아들이게 되면 토의가 이루어질 수 없게 돼요.

예를 들어 일반적으로 작성자는 본인 생각에 멋지다고 생각하는 코드를 작성하지만, 정작 리뷰어는 멋지지 않다고 생각할 수 있죠. 그런 경우 리뷰어가 혹여라도 피드백을 잘못하게 되면 그 과정에서 작성자는 코드에 대한 비판을 자신에 대판 비판으로 받아들이는 경우가 있을 수 있다고 해요.

생각을 글로 전달하는 것도 어려운 요소 중 하나에요. 직접 얼굴을 맞대어 대화하는 것과 달리 상대방의 음성 톤과 표정을 알 수 없기 때문에 오해의 위험이 크기 때문인데요, 그래서 피드백을 주고받을 땐 상대방이 오해하지 않도록 조심스럽게 표현하는 것이 중요하다고 합니다.

예를 들어, “File 객체의 close() 메소드 호출을 빠뜨렸어”라고 피드백을 하면 “어떻게 File 객체를 쓰는데 close() 호출을 깜빡할 수가 있어?” 라고 받아들일 수도 있다고 하네요.

[코드 리뷰를 잘하기 위한 기법들]

코드 리뷰가 잘 자리 잡고 진행되기 위해서는 방해되는 요소는 제거하고 자연스럽게 리뷰를 진행할 수 있는 환경을 만드는 것이 중요한데요. 강연에서는 이런 환경을 만들기 위한 기법들 몇 가지를 소개했어요. 그중에서도 기억에 남는 몇 가지를 정리했습니다.

지루한 작업은 자동화

가장 먼저 소개한 것은 공백이나 들여쓰기 같은 지루한 작업은 직접 하지 말고 자동화된 도구를 사용하자는 것이었어요. 이런 지루한 작업은 기계가 더 잘하고 다른 사람이 작성한 코드를 읽는 것 자체가 높은 집중력이 요구되는 작업이기 때문에 노력을 낭비하지 말고 정말로 필요한 문제에만 집중해야 한다는 이야기였어요.

스타일 가이드 정립

스타일은 가이드를 정해서 따르고 PR에서 논쟁하지 말자는 것이었어요. 코드 리뷰에서 스타일에 대한 논쟁은 시간 낭비이기 때문인데요, 일반적으로 스타일 가이드를 정하는 방법은 아래 세 가지 중 한 가지를 선택한다고 해요.

  • 이미 존재하는 잘 정의된 스타일 가이드를 적용하기
  • 점진적으로 스타일 가이드를 만들기
  • 위 두 가지를 혼합하기

즉시 리뷰

작성자는 리뷰가 완료될 때까지 다음 작업에 온전히 집중할 수가 없는 상태가 되는데요, 리뷰를 기다리거나 컨텍스트 스위칭을 감당하며 다른 작업을 하게 되는데 결과적으로 리뷰가 늦어질수록 PR 작성자의 생산성에 큰 영향을 받게 됩니다. 이는 팀의 생산성에도 영향을 주기에 코드 리뷰는 가능한 한 빨리 완료되어야 해요.
빠른 리뷰를 위해 PR의 범위가 작고 단순하게 만들고, 이를 통해 개발자가 효율적으로 일할 수 있는 선순환 구조를 만드는 것이 중요하다고 해요.

일반적으로 리뷰를 주고받는 시간이 하루가 넘어가면 안 된다고 합니다. 리뷰가 지체되면 다른 리뷰어를 지정하는 등 빠르게 리뷰가 이루어질 수 있도록 조치해야 하고, 리뷰어가 빈번하게 변경되지 않도록 건강한 개발 사이클을 유지할 수 있도록 해야 합니다.

고수준으로 시작해서 저수준으로 진행

한 번에 너무 많은 의견을 남기면 PR 작성자는 당황할 가능성이 커집니다. 그래서 처음엔 인터페이스 설계나 복잡한 함수 분리 등 고수준의 피드백을 먼저 남기고, 이후에 변수 이름이나 주석 등 낮은 수준의 피드백을 남기는 것이 좋다고 해요.

피드백은 명령이 아닌 요청으로

현실에서 동료에게 명령하는 사람은 없을 거예요. 다만 리뷰 과정에서 글로 남겨지는 코멘트는 종종 명령처럼 보이기도 하는데요, 작성자가 명령이 아닌 권유나 요청으로 느껴질 수 있도록 표현해야 해요. (한국말은 다르고 다르다고 하잖아요) 예를 들어 “Foo 클래스를 분리하세요”보다는 “Foo 클래스를 분리하는 건 어떨까요?”나 “Foo 클래스를 분리할 수 있을까요?” 처럼 부드러운 표현을 사용하는 것이 좋다고 하더라고요.

원칙에 기반한 피드백

변경을 요청할 때에는 반드시 제안과 근거가 있어야 해요. 어떻게 바뀌길 바라는지, 왜 그렇게 바꿔야 하는지 객관적인 사실과 원칙에 기반해 피드백을 해야 작성자도 설득이 되고 요청을 받아들일 수 있겠죠. 앞뒤 잘라서 “Foo 클래스의 일부를 Bar 클래스로 분리해야 해요.” 보다는 “Foo 클래스는 읽기와 파싱 두 가지 책임을 갖고 있으니 두 클래스로 분리해 SRP 원칙을 준수해야 해요.”라고 제시하는 것이 훨씬 더 작성자를 설득하기 수월할 거예요.

재미있는 건 소프트웨어는 공학이면서도 예술에 가까워서 항상 원칙에 기반해 정확히 무엇이 잘못되었는지 언급할 수 있는 건 아니라고 하더라고요. 단순히 그냥 보기 싫거나 눈에 보이지 않는 코드가 있을 수도 있는데 객관적으로 단순히 이해하기 어렵다고 이야기하면 충분하다고 합니다.

조금씩 좋아지기를 기대

엉클 밥으로 유명한 마틴 파울러조차도 “나는 처음부터 깨끗하게 작성한 것이 아니다. “누구도 처음부터 깨끗한 코드를 작성할 수 없다고 생각한다”라고 말했어요. 한 번에 완벽한 코드를 만들 수 있는 사람은 없다는 거죠. 그러므로 리뷰를 하는 코드가 D등급이라면 리뷰 후 A등급의 코드가 되기를 기대하기보다는 C, B등급의 코드가 되도록 기대하고 도와야 한다고 해요.

작성자와 리뷰어가 여러 차례 피드백을 주고받으면서도 코드의 승인이 보류되는 유일한 이유는 기능적인 문제나 동작의 정합성을 보장할 수 없을 때가 유일하고, 그 외에는 완벽하진 않아도 더 좋은 코드가 되도록 하는 것이면 충분하다고 합니다.

리뷰 범위 지키기

의외로 자주 저지르는 실수 중 하나가 변경된 코드 근처의 코드를 작성자에게 수정 요청하는 경우라고 해요. PR과 전혀 무관한 코드지만 변경된 코드를 비교해 표시되기 때문에 무의식적으로 작성자가 작성하지 않은 코드에 대한 수정을 요청하는 경우가 많아요.

단, 만약 변경하지 않은 코드가 PR에서 변경한 코드에 영향을 미치는 경우에는 예외적으로 리뷰어가 작성자에게 수정을 요청할 수 있어야 한다고 합니다.

칭찬하기

대부분이 코드 리뷰할 때 코드의 좋은 점보다는 잘못된 부분을 찾는 것에만 집중합니다. 리뷰 대상이 되는 코드에서 더 좋은 코드로 개선하거나 잘못된 것을 찾겠다는 생각에 휩싸여 놓치는 것 중의 하나인데요. 분명 다른 사람의 코드를 보면서 몰랐던 것을 알게 되거나 새로운 사실을 배우게 되는 경우도 많을 거예요. 예를 들면 새로운 API를 알게 되었다거나, 어려운 문제를 쉽게 만들어 해결한다거나, 훨씬 좋은 구조를 만들어낸다거나 하는 것들이요.

이런 따뜻한 피드백은 리뷰어가 코드를 검사하는 감시자나 허락을 구해야 하는 존재가 아니라 진심으로 도와주려는 팀 동료라는 인식을 하게 해 줄 수 있습니다.

교착 상태 해결하기

코드 리뷰에서 최악의 결과는 교착 상태인데요. 여기서 교착 상태는 작성자는 리뷰어의 의견을 반영하기를 거부하고, 리뷰어는 의견이 반영되지 않았으니 승인하지 않는 상황을 말합니다.

교착 상태가 발생하면 우선 만나서 이야기를 하는 게 좋다고 해요. 텍스트에 기반한 커뮤니케이션은 서로가 인간이라는 것을 잊게 만들고 오해로 인해 잘못된 커뮤니케이션을 만들 가능성이 높거든요.

교착 상태가 길어지면 리뷰어와 작성자의 사이가 점점 나빠지게 되는데, 수준 낮은 코드를 승인함으로 발생하는 품질 손해보다 동료와 다퉈서 발생하는 품질 손해가 더 크다고 해요. 가능하다면 어느 한 사람이 인정해 교착을 해결하고 그럴 수 없다면 리더에게 문제를 전달해 다른 리뷰어가 리뷰를 진행할 수 있게끔 만들어야 합니다.

교착이 발생한 경우엔 매니저, 또는 리더와 상의하고 휴식을 가지는 게 좋다고 해요. 특히 교착을 만들어낸 두 사람이 관계가 회복될 때까지는 서로 코드 리뷰를 요청하지 않도록 해야 한다고 합니다.

[돌아보며]

강연에서 소개하신 많은 기법 중에서 우리가 이미 잘하고 있던 것들이 있었어요.

우리 팀이 정말 잘해왔던 것 중 하나가 리뷰어를 위해 PR 작성자가 최선을 다한다는 것인데요, 우리 팀은 PR 템플릿을 정해 그에 맞도록 최대한 상세히 PR을 작성하고 있습니다.

  • 작성 배경
  • 주고받았던 논의
  • 구현 방법
  • 주의 깊게 봐야 하는 내용
  • 테스트 방법

등을 포함하고 가능하다면 한눈에 변경사항을 파악할 수 있는 이미지를 생성해 다음과 같이 PR 본문을 작성하곤 합니다.

이 아름다운 PR 템플릿을 보라 (#늘이렇진않아요)

다음으로는 오늘 강연에서도 나왔던 부분인데 ‘기계가 할 수 있는 리뷰를 사람이 하지 말자’는 부분입니다. 이를 개선하기 전 오랜 기간 동안 코드 포맷 규칙을 작성자가 한땀 한땀 맞춰야 했고 리뷰어도 이를 숙지해야만 했었어요.

포매팅 때문에 피드백을 주고받는 횟수도 많아지고 리뷰가 길어져 에너지 소모가 심하다는 토로가 있었고, 논의를 통해 자동 포매팅 규칙에 ktlint를 적용한 뒤 포매팅과 관련된 리뷰는 하지 않기로 했어요.

이후엔 설계, 버그 검출, 좋은 코드에 더 집중해 리뷰할 수 있었고, 오랜 대화를 통해 팀 자체적으로 해결책을 찾았던 터라 강연에서 언급되었던 것이 너무 와닿았어요.

힘들었던 그때 그 순간

스타일 가이드와 관련된 부분도 있습니다. 팀 내에선 스타일 가이드를 정해서 따르고 있는데요, 간혹 스타일 가이드에 명시되지 않은 부분을 리뷰할 경우 우선 작성자의 의견을 따르고 별도의 논의를 거쳐 가이드를 업데이트하고 있어요.

코드에 대한 피드백을 전달할 때에 종종 예제 코드를 보여주기도 합니다. 때로는 문장보다 코드로 설명하는 것이 쉽거든요.

따뜻한 코멘트는 기본입니다

반면, 우리가 잘하지 못했던 것 중 하나가 바로 칭찬하기 아닐까 해요. 코드 리뷰 과정에서 긍정적인 경험을 주는 것이 굉장히 중요한데, 가장 직접적이면서도 쉬운 방법 중인데 왜 이걸 하지 못했을까 하는 생각이 들더라고요.

#그래서해봤습니다 #해보니까좋네요 #조작아님

최근에는 즉시 리뷰 하지 못하고 PR이 점점 쌓여서 팀의 개발 사이클이 좋지 못한 것이 고민이었습니다. 팀 회고를 통해 이를 어떻게 개선할지 논의했고, 일정 수 이상의 PR이 쌓이면 팀원 모두가 하던 것을 즉시 멈추고 리뷰를 우선 하자는 규칙을 정했어요. 강연 막바지 Q&A 시간에 이런 극단적인 규칙이 팀에 도움이 될지 피드백을 부탁드렸는데 굉장히 좋은 방법이라고 하시더라고요.

강의 이후에 적극적으로 이를 실행하고 있습니다. 리뷰 하지 않은 PR이 10개가 되면 누군가 넛지를 주고 팀 모두가 즉시 리뷰를 진행하고 있어요.

리.. 리뷰 할게요

덕분에 아무리 늦더라도 이틀 이내에는 머지가 가능해졌습니다. PR 반장님을 자주 뵙는게 부담이었는지 빠른 개발 싸이클을 경험한 이후부터는 PR이 머지될 때까지 걸리는 시간도 이전보다 눈에 띄게 짧아졌어요.

마치며

저는 어느 순간부터 애자일, 페어 프로그래밍, 코드 리뷰라는 단어들을 숨 쉬듯 자연스럽게 접하고 사용했는데 많은 글과 이야기를 들으면서 그저 “좋은 거니까 나도 해야겠네”하고 당연하게 받아들이기만 하고 그걸 왜 해야 하는지는, 하면 뭐가 더 좋아지는지에 대해서는 별로 고민하지 않았더라고요.

저는 여러 회사에서의 경험으로 “코드 리뷰는 시스템보다는 문화다”라는 생각을 하고 있는데요. 아무리 시스템적으로 코드 리뷰라는 과정이 존재하더라도 실제로 구성원이 적극적으로 참여하지 않으면 그저 불필요한 업무 단계가 하나 더 있는 것으로 인식되는 것을 경험했거든요. 그래서 과거에는 코드 리뷰를 안 하는 사람들을 어떻게 리뷰에 참여하게 할 수 있을까 생각해봤지만 이렇다 할 답을 찾지 못했었어요.

오늘 들었던 강연에서, 대부분의 개발자가 코드 리뷰가 중요하고 필요하다는 것을 이미 잘 인지하고 있기에 굳이 설득을 하기보다 스스로 하고 싶게 만들어야 한다는 이야기가 인상 깊었어요. 코드 리뷰라는 행위가 하는 사람과 받는 사람 모두에게 이득이 되고 리뷰를 주고받는 행위가 멋지게 느껴진다면 자연스럽게 하고 싶어질 거라고 하시더라고요.

과거의 저는 같이 일하는 동료들에게 이런 동기를 유발하지 못했고, 저조차도 코드 리뷰를 해야 한다는 강박만 있을 뿐 행동하게 만드는 동기가 없었더라고요. 게다가 스스로 코드 리뷰가 시스템이 아닌 문화라고 정의했으면서도 사람에 대해서 충분히 고려하지 못한 채 규칙, 시스템, 환경 같은 것들만 생각했었어요.

스타일쉐어에서 일하면서 어느 정도 팀이 이미 코드 리뷰를 잘하고 있었다 생각했지만, 오늘 강연을 통해 코드 리뷰에 대한 추가적인 시각을 접하면서 제가 지금까지 코드 리뷰에 대해 놓치고 있었던 부분, 우리 팀이 잘하고 있거나 부족한 것들이 정리되어 참석하길 잘했다는 생각이 들었습니다.

by. 이길현 스타일쉐어 개발자(develog@styleshare.kr)