brunch

You can make anything
by writing

C.S.Lewis

by 권순목 Sep 14. 2024

코드 리뷰, 9가지 이야기

소프트웨어 개발 노트

개발자들 누구나 이 주제에 대해 할 말이 있을 것이다. 나 역시 오래된 개발자로서 이 주제에 할 말이 있지만 딱히 나서 본 적은 없었는데, 최근 회사에서 이 주제로 강연 비슷한 것을 하면서 생각을 정리할 기회가 있었다. 그 내용을 여기에 글로 풀어 써 보고자 한다.


이 글에서 코드 리뷰에 관해 9가지 이야기를 할 것이다. 처음 3개는 What, 다음 3개는 How, 마지막 3개는 Why를 다룬다.




개발자가 가장 하기 싫은것


대부분의 개발자는 직접 코딩하는 일과, 기존 코드를 읽는 일 중 하나를 선택하라고 하면 직접 개발를 선택할 것이다. 더구나 코드 리뷰는 남의 코드를 그냥 이해 하면 되는 일이 아니다. 틀린 부분을 고쳐주고, 잘못되면 책임도 져야한다. 또한 그 읽어야 할 코드가 읽기만 해도 안구가 정화되는 모범적인 코드인 경우는 거의 없다.


코드 리뷰 외에도 개발자가 하기 싫어할 만한 일은 더 있다. 주로 개발과 무관한 관리 업무들이 그 범주에 들어간다. 그러나, 그런 일들은 피하려면 피할 수 있다. 오픈 소스 스타일의 개발 문화가 정착된 회사로 이직할 수도 있고, 경력이 쌓여도 관리자가 아닌 개인 개발자(individual contributor)의 길을 갈 수도 있다. 그러나, 코드 리뷰라는 업무는 회사에 소속된 개발자로서 피할 수 있는 것이 아니다. 코드 리뷰가 개발자가 가장 하기 싫어하는 일이라는 말은 그런 측면을 고려했을때 통계적 진실에 가깝다.



개발자 삶의 반대쪽 절반


코드 리뷰가 개발자로서 피할 수 없는 일이라는 것은 무슨 말일까? 영화 감독의 경우를 생각해 보자. 영화 감독과 영화 평론가는 동전의 양면과 같은 직업이라고 말한다. 둘은 서로를 미워하지만 동시에 서로를 필요로 한다. 감독과 비평가는 영화라는 실체를 사이에 두고, 반대편에 서서 한쪽은 그것을 만들고 다른쪽은 논평하게 된다. 어떤 관점에서 보면 이 둘은 영화를 만들기 위해 협력하는 관계이며, 이 둘이 가지고 있는 경험과 기술은 좋은 영화를 만드는데 반드시 둘 다 필요한 것이다. 그래서 많은 감독들이 비평가 출신이기도 하다.


Director and critic - image created by AI


코더와 리뷰어의 관계도 감독과 비평가의 관계와 비슷하다. 둘은 협력 관계이다. 다른점이 있다면, 코더와 리뷰어 쪽은 훨씬 더 직접적으로 협업을 수행한다는 것이다. 코더와 리뷰어로서의 기술은 개발자 한 사람 안에 공존하며 같이 발전해 가야한다. 좋은 코드를 작성하는 방법을 안다는 것은 곧 좋은 코드를 알아보는 눈도 의미한다. 개발자에게 있어서 좋은 리뷰어가 되는 것은 좋은 코더가 되는 것 만큼 중요한 일이다. 코드 리뷰는 개발자 삶의 반대쪽 절반이라 할 수 있다.



아무나 할 수 없는 것


커리어를 막 시작한 주니어 개발자의 경우를 생각해보자. 담당 업무는 피쳐 프로그래밍(feature programming)에 가깝다. 어떤 것을 개발해야 하는지는 자세한 설명과 함께 이슈 티켓으로 주어진다. 자신이 개발한 코드가 잘 돌아가도록 만드는 것만 해도 쉽지 않은 일이며, 이것만 해도 충분히 한 몫을 하는 것으로 인정 받는다. 다른 사람의 코드를 살펴보고, 시스템 전체가 잘 돌아가도록 살피는 일까지 하도록 요구받는 경우는 거의 없다. 코드 리뷰 업무는 가끔 할당되었을 때 별 생각없이 승인(approval)을 보내고, 개발자 간에 친목을 증진시키는 일종의 요식 행위처럼 느껴진다.


스타트업에서 프로덕트의 한 부분을 책임지는 10년차 개발 팀장의 경우를 생각해보자. 그를 포함해 4명으로 구성된 팀인데, 팀의 나머지 3명은 커리어를 막 시작한 주니어 개발자들이다. 팀장의 업무는 개발 이슈를 셋팅하여 팀원들이 개발을 수행하게 하고, 그들이 만든 모든 것들을 배포해서 시스템을 운영하는 것이다. 주니어 개발자들의 코드는 얼핏 괜찮아 보여도 그대로 배포했을 때 문제 없이 돌아가는 경우가 거의 없기 때문에, 수 많은 테스트 코드로도 이 문제가 전부 잡히지는 않기 때문에, 팀장은 코드 리뷰 단계에서 나중에 발생할 만한 문제를 모두 체크하기 위해 많은 시간을 들인다. 시스템에 장애가 나면 아무도 주니어 개발자들에게 책임을 묻지 않는다. 그에게 있어 코드 리뷰의 승인(approval)은 이 그 코드에서 장애가 나면 자신이 고치겠다는 의미이다.


코드 리뷰는 아무나 할 수 있는 것이 아니다. 경험 많은 개발자 만이 제대로 된 코드 리뷰를 할 수 있다. 개발자의 업무 시간에서 코드 리뷰는 경력이 올라갈수록 많은 비중을 차지하게 된다. 회사마다 차이가 나겠지만, 주니어급 개발자의 경우 개발 시간의 10 % 내외, 시니어급 개발자의 경우 개발 시간의 70 % 까지 코드 리뷰에 투입될 수 있다.

개발자의 경력과 업무 내용 변화


이 차트는 직접 개발 업무, 코드 리뷰 업무, 그리고 개발 관리 업무가 개발자의 업무 시간을 얼마나 차지하는지, 그것이 경력에 따라 어떻게 변화하는지 나타내 본 것이다. 여기서 개발 관리 업무란 개발 이슈 스펙을 작성하거나, 타 팀과의 커뮤니케이션을 수행하거나, 경영진에 개발 결과를 보고하는 등의 일을 말한다. 어쩌면 이 차트가 평균적인 한국 개발자의 커리어를 보여줄 지도 모르겠다.



로직 검증 >> 가독성, 컨벤션 > 최적화


그러면 코드 리뷰는 어떻게 하는 것이 좋은가? 가장 중요한 것은 로직 검증이다. 동작 요구사항 대로 구현되지 않은 코드, 동작 과정에 오류가 있는 코드, 또는 대부분 잘 돌지만 특정 Edge Case에 대비가 되어있지 않은 코드. 이런 코드가 배포되지 않도록 하는 것이 코드리뷰의 첫번째다. 이것은 당장 회사 비즈니스에 문제를 일으킬 수 있기 때문에, 아무리 배포가 급하더라도 이것을 생략할 수는 없다.


가독성컨벤션 검증이 그 다음으로 중요하다. 코드가 읽기에 좋도록 잘 구조화되어 있는지, 적절한 코멘트가 달려 있는지, 변수, 함수, 파일, 디렉토리 등이 역시 직관적으로 내용이 파악되도록 잘 네이밍 되어 있는지 확인해야 한다. 그리고 팀내에서 공통적으로 따르기로한 여러가지 컨벤션/규칙들을 잘 따르고 있는지 확인해야 한다. 컨벤션에는 여러가지 네이밍 규칙, 인덴테이션(indentation) 규칙, 공통 유틸리 활용 규칙 등 다양한 것들이 있을수 있는데, 이 것들의 목적은 대부분 코드의 가독성과 효율성을 높이는데 있다. 그러니까, 가독성과 컨벤션 준수 여부는 어느 정도 연결되어 있다고 할 수 있다.


코드의 최적화가 마지막이다. 코드가 일단 오류가 없고, 가독성이 높으며, 컨벤션을 준수하도록 하고 나서, 최적화 문제를 다루면, 열심히 최적화 시키고 나서보니 구조적 변경이 필요해서 그 코드가 불필요해지는 경우가 없어진다. 구조가 바뀌면 소프트웨어적으로 풀어야 할 문제가 바뀌기 때문이다. 예를들어 아주 어려운 문제가 나타나 복잡한 알고리즘의 도입이 필요한데, 구조를 바꿔서 몇 개의 심플한 문제로 나누면 복잡한 구현이 불필요해지는 경우가 있다. 이런 경우는 개발에서 자주 나온다. 한편, 머신 러닝 코드들은 알고리즘 측면에서 최적화 할 수 있는 여지가 끝도 없기 때문에, 구조나 가독성을 다루는 리뷰와 최적화 리뷰는 아예 별도의 이슈 태스크로 진행하는 것이 바람직한 경우도 많다.


여기에 로직 검증, 가독성, 컨벤션 검증, 최척화라는 코드 리뷰 작업 내용 중 어느 것이 중요한지 설명했는데, 실제 상황에서는 반대로 이루어지는 경우도 많다. 리뷰어는 우선 자기가 알고 있는 최적화 기법을 열심히 적용시키려고 한다. 그리고 가독성을 조금 다루다가 로직 검증에 대해서는 그냥 믿고 승인(approval)을 내주는 것이다. 이런 식의 리뷰도 리뷰가 없는 것 보다는 낫다. 또한 회사 상황에 따라서는 꽤 오랜 기간 잘 동작할 수도 있다. 그러나, 뒤에서 설명할 코드 리뷰의 진정한 목적 중 하나인 코드 오너십(ownership) 분산에는 도움이 되지 않는다.


여기 언급된 중요도 순서는 작업 순서를 의미하는 것이 절대 아니다. 우선 로직 검증 리뷰를 하고, 그 다음 컨벤션 검증 리뷰를 하고... 코드 리뷰는 이런식으로 진행되지 않는다. 코드 리뷰어는 리뷰 의견을 내기 전에 우선 코드를 끝까지 읽어야 한다. 그러고 나서 바람직한 코드의 전체적인 최종 형태를 머리 속에 그린 다음, 어떤 식으로 리뷰어에게 코멘트를 줘야 코드 변경 작업이 수월할 지 생각해야 한다. 그러다 보면 로직 검증에 관한 코멘트가 필요하지만, 가독성이나 컨벤션 관련 작업 요청이 우선 이루어질 수도 있다. 이렇게 진행되는 것은 아무 문제가 없다. 중요한 것은 로직 검증이 최종적으로는 꼭 이루어져야 한다는 점이다.



코드를 직접 짤 때처럼 집중


코드 리뷰를 어떻게 해야하는지에 대해서 딱 한줄로만 말하라고 하면, "본인 코드를 짤 때처럼 집중해서 해라."라고 할 수 있다. 너무나 당연하게도 개발자는 본인이 코드를 짜는 능력 이상으로 코드 리뷰를 할 수 없다. 그런데 많은 경우 코드 리뷰를 할 때는 본인이 코드를 짤 때처럼 집중하여 몰입하지 않는다. 그러면 본인이 가진 역량보다 낮은 수준의 리뷰가 나올 수밖에 없다. 특히 로직 검증이 필요한 코드에서 미세한 버그나 Edge Case를 찾아내는 것은 웬만한 집중력이 아니면 어렵다.


코드 리뷰를 본인 코드를 짤 때처럼 집중해서 하면 가장 먼저 거슬리는 것이 가독성이다. 여기서 가독성과 컨벤션 준수에 대한 리뷰 코멘트가 자연스럽게 나올 수 있다. 그리고 코드의 동작 과정을 세세히 따라가다보면 자연스럽게 로직 검증에 대한 코멘트가 이어질 수 있다. 무엇보다, 집중하면 코드 리뷰 작업 자체가 개발자 본인에게 성취감을 주고, 코드 리뷰란 남의 코드를 보는 피곤한 일이라는 관념에서 벗어날 수도 있다.



Ego에 스크래치가 날 만큼


코드 리뷰가 개발자들에게 피곤한 업무로 인식되는 이유 중 하나는 코드 리뷰 과정에서 일어날 수 있는 리뷰어(Reviewer)와 리뷰이(Reviewee) 사이 감정적 대립이다. 이런 일은 개발팀에서 흔하게 일어난다. 경력이 길거나 짧거나 상관 없다. 나이 지긋한 개발자들끼리도 이런 일로 쉽게 다툰다. 이러한 감정적 대립을 막기 위해서는, 아무리 코드 리뷰라도 인간으로서 기본적인 예의는 지켜가면서 이루어져야 한다. 그러나 더 큰 문제는 이러한 감정적 대립을 두려워한 나머지 리뷰어가 하고 싶은 말을 충분히 못 하고 제대로 된 리뷰가 이루어지지 않는 것이다.


개발은 회사일이지만, 개발자들에게는 어느 정도 사적인 일이기도 하다. 회사 소속의 영화 감독이라도 독자적인 작품 세계까지 간섭 받기를 원치 않는 것처럼, 개발자에게도 어느 정도의 개인적 영역이 있다. 그러나 이 정도가 지나쳐서 에고(ego) 수준에 이르러서는 곤란하다. 나의 아름다운 코드는 누구도 터치할 수 없다는 식의 태도는 리뷰어를 피곤하게 만들고 코드 리뷰가 제대로 이루어지지 못하게 하여 결국 회사 전체에 악영향을 끼친다.


리뷰이는 리뷰어가 지금 개발자들이 가장 힘들어하고 싫어하는 일을 하고 있다는 사실을 인식해야 한다. 그리고 자신의 Ego는 철저히 내려 놓아야 한다. 리뷰어가 요청하는 것들과 자신이 추구하는 방향이 다르더라도, 그 차이가 코드의 품질에 큰 영향을 줄 만한 것이 아니라면, 웬만하면 받아들일 준비가 되어 있어야 한다. 그래서 리뷰어가 감정적 문제까지 걱정하지 않고, 오롯이 코드에 집중할 수 있도록 해 주어야 한다. 안그래도 피곤한 리뷰어는 기본적인 예의를 지키는 선 이상의 감정적 노동을 해서는 안된다. 회사일에 Ego는 불필요하므로, 리뷰어는 필요한 경우 Ego에 스크래치를 내는 것을 두려워 해서는 안된다.


나는 언젠가 리뷰이의 자세에 대한 짦은 시를 지은 적이 있다.


제목: Reviewee's Creed

내 코드는 쓰레기다
리뷰어는 불쌍한 사람을 구제하기 위해 귀한 시간을 냈다
나는 그가 시키는 일은 무엇이든 할 것이다


웃자고 지은 시지만, 쓸모없는 Ego를 내려놓는데 도움이 될 지도 모른다.



Code Ownership Count > 1.5


앞에서 스타트업 개발 팀장이 코드 리뷰를 대하는 자세에 대해서 말했는데, 그가 코드 품질 외에 걱정해야 할 것이 하나 더 있다. 스타트업은 인력 이동이 잦다는 것이다. 입사 1년 안에 이직하는 사례가 허다하다. 그런 상황에서 이직한 사람의 코드에 수정이 필요한 경우 또한 자주 일어난다. 그래서 중요한 것이 코드를 유지 보수 할 수 있는 인원을 여럿으로 늘리는 것이다. 특정 코드를 수정 할 수 있는 인원이 딱 한 명 밖에 없는 상황은 비단 이직이라는 특수 상황이 아니더라도 개발팀에게 좋지 않다.


회사에 존재하는 모든 코드들에 그 코드를 유지 보수 할 수 있는 인원이 몇 명인가를 조사해서 기록한 다음 평균을 낸다고 생각해보자. 이 가상의 지표를 코드 오너십 카운트(code ownership count)라고 해보자. 이 코드 오너십 카운트는 회사의 코드 유지 보수 상황이 얼마나 안정적인가를 나타내는 지표가 될 수 있다.


노파심에서 말하자면, 이 지표를 실제로 측정해 보겠다는 생각은 버리는게 좋다. 그냥 리더급 개발자에게 추정해 보라고 하라. 그거면 충분하다. 그러니까, 여기서 지금 이야기 할 숫자들도 그냥 다 추정치라는 것을 미리 일러둔다. 스타트업은 이 수치를 1.5 정도로 유지하기 위해 애쓴다. 이 정도면 그래도 이직과 다양한 프로덕트 변화에 대응하면서도 어느 정도 코드 품질을 유지해 나갈 수 있다. 잘 활성화된 오픈 소스 프로젝트에서는 이 수치가 3.0은 넘을 것으로 추정된다. 이것은 코드 리뷰 과정에 개입하는 수 많은 리뷰어들과 커미터 들의 활동을 보면 알 수 있다. 소위 레거시 코드라 불리는 것들은 이 수치가 1.0 보다 낮은 0에 가까운 것들이다. 한국의 큰 기업들 중에 이 수치가 1.2를 넘는다고 자신할 만한 곳이 얼마나 될 지 잘 모르겠다. 레거시 코드들을 제외하고 나서도 아마 그럴 것이다.

 Imagnary Code Ownership Count Box-plot


코드 리뷰는 코드 오너십 카운트를 올리는 핵심 프로세스이다. 누군가 이직할 때 일어나는 흔히 일어나는 소위 코드 인수 인계라 불리는 업무는 사실 해당 코드의 오너십 분산에 큰 도움이 되지 못한다. 짧은 시간에 급하게 진행되는 이 업무를 통해서는 그저 책임만 넘어갈 뿐이고, 결국에는 레거시 코드를 늘리는 결과 밖에 남지 않는다. 평소에 철저한 코드 리뷰를 통해 해당 코드에 대한 이해가 높은 개발자들을 늘려가는 것이 정석이며, 이런 상황이라면 누군가 이직하거나, 장기 휴가를 떠나거나 하는 일이 일어나도 코드 인수 인계 같은 업무는 불필요하다.


코드 오너십의 분산은 개발자 개인의 입장에서는, 내 코드가 내 손을 떠나서 팀 코드로 이관되는 과정이라고 할 수 있다. 개발자는 자기 손 때 묻은 코드를 아끼기 마련이다. 자기 코드에 애정이 없는 개발자는 제대로 된 개발자라고 할 수 없다. 그러나 그 애정이 지나쳐서 '자신만의 코드'에 집착한다면 팀에 해를 끼치게 된다. 코드 리뷰는 개발자가 다른 사람이 자신의 코드를 자유롭게 수정하는 것을 허용하면서, 집착을 내려놓고 소유권을 공유하는 과정으로 해석 될 수도 있다.



도제식 기술 전수


오픈 소스 세계에서는 가끔 사람을 깜짝 놀라게 하는 리뷰어 코멘트가 나타난다. 나이 지긋한 리뷰어 두 세명이 나타나서 현재 진행 중인 커밋의 구조적 의미에 대해서 논하면서, 그와 관련된 개발 원칙들에 대해서 논의를 시작한다. 그 원칙들에 대해서 옛 교과서와 웹 자료들을 뒤져서 공부해야 그들이 뭘 말하는지 이해 할 수 있다. 사소한 커밋에 대해서까지 이런식의 토론을 벌이는 것이 어떨때는 너무 지나친 처사로 보이기도 하고, 일의 진행 속도를 늦추는 것처럼 보이기도 한다. 그러나 이런 기회를 통해 소프트웨어 구조에 대한 깊은 성찰을 함으로써, 개인은 기술적 성장을 이룰 수 있다.


회사에서 이루어지는 코드 리뷰는 웬만해서는 이런 수준까지는 가지 않는다. 그래도 코드 리뷰는 리뷰어가 리뷰이에게 수 많은 기술을 도제식으로 전수해 주는 통로가 된다. 이때 전수되는 기술들은 회사 내부의 여러 가이드 문서에서 커버하지 못하는 것들이며, 교과서와 실제 세계를 연결해주는 아주 실용적인 것들이다. 종류는 아주 많다.


코드 가독성을 적당한 수준으로 높이는 방법

적당히 실용적인 알고리즘 코드

각종 유틸리티를 어느 정도 수준까지 쓸 것인가

소프트웨어 개발 원칙의 적당한 적용

팀 내 각종 컨벤션이 수립된 구조적 이유

...


뭐든지 '적당히'가 가장 어렵다. 코드 리뷰 단계에서 전수되는 지식의 상당 부분이 바로 그 적당히를 어떻게 하느냐이다.


리뷰어가 꼭 상급자나 회사 생활을 오래 한 사람이 아닌 경우에도 배울 것은 많다. 특히 머신 러닝 영역은 수평적 리뷰(peer review)를 통해서 다양한 새로운 기술의 활용 방법을 코칭 받을 수 있다.


회사에서 리더십을 가지고 있는 개발자라면, 코드 리뷰를 이러한 기술 전수의 시간으로 활용할 줄 알아야 한다. 그리고 되도록 많은 사람들이 코드 리뷰를 기술 전수의 시간으로 활용하도록 참여를 확대할 필요가 있다.



코드 품질 향상 또는 회사의 생존


이 모든 과정을 통한 코드 리뷰의 궁극적 목적은 코드 품질을 상향 평준화 하는 것이다. 그리고 이것을 안정적으로 유지 보수 하는 것이다. 이것은 많은 회사들 특히 스타트업 회사에서 회사의 생존과 직결되는 문제이다.


코드 리뷰는 개발 문화의 핵심이다. 개발이 어떤 관리 형태를 통해 이루어지든, 즉, 칸반을 사용하든, 스프린트를 중심으로 운용하든, 배포 도구를 뭘 사용하든 상관 없다. 문제는 코드 리뷰가 잘 이루어지느냐라고 할 수 있다. 코드 리뷰가 잘 이루어지는지 PR(pull request) 이력을 살펴보는 것, 그리고 앞서 언급된 코드 오너십 카운트를 추정해 보는 것, 이것 두 가지면 어떤 회사의 개발 문화가 건강한지는 상당한 정확도로 추정 가능하다.




What

개발자가 가장 하기 싫은 것

개발자 삶의 반대쪽 절반

아무나 할 수 없는 것

How

로직 검증 >> 가독성, 컨벤션 > 최적화

직접 짤 때처럼 집중

Ego에 스크래치가 날 만큼

Why

Code Ownership Count > 1.5

도제식 기술 전수

코드 품질 향상 또는 회사의 생존


오늘의 이야기는 이렇게 9가지로 정리된다. 앞서도 말했지만, 코드 리뷰라는 것은 개발자 100명이 있으면 100가지 다른 의견이 나오는 주제이며, 그것들은 나름 다 옳은 것들이다. 여기 정리한 것도 절대적인 규정이 될 수는 없다. 그러나 누군가에겐 도움이 될 수도 있을 것이다.




p.s. 코드 리뷰에 대해서 여러 가지를 찾아서 읽어볼 것을 권한다. 특히 anti-pattern 이라는 주제로 검색해보면 재미있는 것들을 많이 배울 수 있다.


[1] Anti-patterns for code review, AWS DevOps Guidance [Link]

[2] Code review antipatterns, Simon Tatham [Link]


작가의 이전글 개발 팀 성과 도식화
브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari