부제: 코드 Reviewer, Reviewee의 마인드셋 장착하기
한빛N MSA(Micro Seminar Assemble)는 한빛미디어 디지털콘텐츠개발연구소에서 준비한 세미나 시리즈다. 학교와, 학원 등에서 다루지는 않지만, 현업에서 일을 할 때 필요한 지식, 기술, 정보 등을 전달하는 걸 목표로 진행되는 세미나다. 각 세미나는 격주 목요일마다 진행되며(공휴일 제외), 홍대에서 세미나가 열려 접근성도 좋았다.
저번 주제가 TDD였다면 이번 주제는 Code Review.
홍승환님의 "우리 팀의 코드 품질 향상을 위한 Code Review" 세션을 듣고 일부 정리했다.
게시글에 사용된 강의 자료는 한빛미디어의 지원을 받았습니다.
코드리뷰 자체는 어느 개발팀을 가도 '꼭 필요한 과정이고, 꼭 해야된다'고 얘기하지만 처음 팀에 도입하려하면 굉장히 어렵다. 실무를 경험했던 사람들이라면 팀원들을 설득하는게 꽤 어렵다는 것을 공감할 내용이다. 학생들의 입장에서도 서로 팀 프로젝트를 할 때 어떻게 해야 더 좋은 의견을 주고 받을 수 있을까 궁금해하는 경우가 많아 이번 세션을 준비했다고 한다.
우리가 어떻게 팀에 올바른 코드 리뷰 문화를 정착시킬 수 있는지 다뤄보고, 특히 코드 리뷰를 하는 팀원과 코드 리뷰를 받는 팀원의 입장을 나눠 어떤 입장을 취해야 할 지 알아보자.
코드 리뷰를 실제로 도입했지만 허들을 만나 좌절하는 케이스가 굉장히 많다.
왜일까? 코드 리뷰의 도입이 실무적으로 힘든 이유들을 먼저 알아보자.
"그거 하고 있을 시간이 어딨어?"
먼저 코드 리뷰를 하는 과정 자체가 개발 과정에 병목이 된다는 주장. "코드리뷰 하면 좋을 것 같은데?" 하는 말을 듣고, 팀에 도입하려 할때 제일 많이 듣는 말이다. 그것도 아주 완곡하게.
"코드 리뷰 하는거 어때요?" 하고 제안하면 돌아오는 답은,,
"리뷰 하나씩 다 보고 있으면 처리할 티켓 많은데, 엄청 느려질거 같으니 지금 상황에서는 조금 과하고 나중에 문제 있으면 수정하면 될 것 같아요! 다음 프로젝트 정도에서 도입해봅시다."
발표자분이 직접 본 경우의 60~70%를 차지할 만큼 이렇게 계속 질질 끌리는 케이스가 많다. 이건 영원히 도입되지 않는다. 내가 지금 코딩할 것도 있고 남의 코드도 봐줄 것이 있다 보니 '코드 리뷰' 자체가 내 업무 시간을 침범하는 추가적인 일이라고 받아들이는 분들이 많기 때문일까.
40% 정도는 '그래도 어떻게든 도입해보자!' 해서 팀 설득을 성공하지만,
그들은 두 번째 허들인 "나 하나 쯤이야" 문제에 봉착한다.
Example. PR을 3분에게 요청한 상황
결국 서로 용인되면 안되는 이유들이 하나씩 용인되서 3명의 approve를 받게 된다.
이 경우 나중에 가서 "우리 코드 리뷰를 코드 품질 올리자고 했던거 아닌가? 근데 품질이 올라간 사례가 한번도 없지?" 라고 하면 다들 꿀먹은 벙어리가 된다. 이미 자신들도 거기에 녹아들었기 때문에 별다른 이유를 생각하지 못하는 것이다. 이렇게 실패하는 케이스가 있다.
마지막으로 리뷰 코멘트를 달때 상대방에 대한 비난이나 공격이 은연중에 포함되는 케이스.
"OO님 습관적으로 이렇게 하시더라고요."
이건 코드가 아니라 사람을 욕하는거다. 이정도면 서로 얼굴을 붉히고도 남을 수 있다.
해당 코멘트를 받는 사람은 이제 방어기제가 작용한다.
"그건 사람에 따라 다른거 아닌가요? 그렇게 짚어내도 되는건가요?"
"우리가 그런 문제에 대해 합의한 적이 있나요? 합의한 적이 없다면 제안할 수 있는거 아닌가요?"
"이건 취향차이의 문제인데... 이걸 왜 옳고 그름의 문제로 몰아가시죠?"
이 문제가 발생한 즉시 조직장은 쓸데없이 분란만 만드는 이 프로세스(코드 리뷰)를 유예기간도 없이 곧장 끝내버린다. 이렇게 3가지가 대표적으로 실무 케이스에서 코드리뷰를 도입하려다 실패하는 케이스다.
이런 허들을 다 넘어가면서 도대체 우리는 뭘 얻고 싶길래 코드 리뷰를 하는걸까?
코드리뷰를 하면서 가장 달성하고자 하는 목표 3가지를 알아보자.
제품 품질의 전반적인 상승과 보존
개발자가 과연 코드만 짜는가? 시스템이 어떻게 생겼는지 설계도 하고, 설계 내용에 따라 분배를 하고, 각자 코드를 짜는 구현 스텝이 있고, 구현된걸 보며 프로덕션 환경에선 어떤 오류가 있을지 잠재성을 보기도 한다. 각 케이스에서 항상 문제는 발생할 수 있다. 이를 사전에 발견하고 제거할 수 있다는게 가장 큰 장점이다.
온콜(on Call)상황에서 연락받은 개발자는 해당 코드를 짠 개발자가 아닐 확률이 높다. 특히 조직이 커지면 커질수록 그 가능성은 높아진다. 하지만 코드 리뷰를 했다면 서로가 이 코드가 어떻게 돌아가는지 보았기 때문에, MTTR (Mean time to recovery, 장애가 난 시점으로부터 복구 까지의 시점)이 줄어드는 이점이 있다.
버스 팩터(Bus Factor)의 최소화
'Bus Factor', 팀원이 출근하다 버스에 치여 죽거나 큰 부상을 당했을때 프로젝트가 망할 확률을 나타내는 단어다. 다시 말해 '프로젝트가 잘 진행되기 위해 꼭 필요한 사람의 수'를 나타낸다.
이는 개발팀의 가장 중요한 요소 중 하나인 Context Sharing의 문제다. 이런 점에서 코드 리뷰는 엔지니어들이 적극적으로 가담해 문제를 해결할 가능성을 올리는데 도움이 된다.
엔지니어링 업무의 효율화
각자 개인별로 취향이 다르고 방식이 다르다. 똑같은 코드를 짜더라도 서로의 코드를 보면 굉장히 다른 형태를 지닐 수 밖에 없다. 그러니 각자 다르게 가지고 있는 개인의 방식을 하나의 합일된 방식으로 합의하는 과정으로 코드리뷰를 쓸 수 있다.
이 과정에서 코딩 컨벤션을 넘어 전반적인 설계 원칙까지 결정될 수 있다. 학생의 경우 지금까지 다뤘던 프로젝트들이 어느정도 정답이 있다. 그러나 실무에 올라와 점점 경력을 쌓다보면 문제가 어려워질수록 아키텍처라는 것이 크게 정답이 없다는 것을 경험하게 된다.
'이렇게 하면 이정도의 트래픽을 감당할 수 있는 서버 아키텍처일거야'
위처럼 현재 상황을 정확히 고려해 실행하는 케이스가 많다. 이건 많은 경험을 갖고 있는 시니어 개발자분들이 모여 검토 후 특정방향으로 몰고 간 것이지, 이게 정답이라 그렇게 간게 아니다. 이런 원칙들도 싱크를 맞춰야 할 상황이 분명히 존재한다. 이런 것들도 점진적으로 싱크해 나가는 과정으로써 코드리뷰를 사용할 수 있다.
코드 리뷰는 커멘트를 남기는 행위기 때문에 대부분은 그 행위를 잘하는 방법을 설명한다.
이와 반대로 강연자 분은 직접 조직에 코드리뷰 문화를 도입해보며 코드리뷰를 받는 사람의 노력이 더 중요하다는 사실을 깨우쳤다고 한다.
코드리뷰를 잘하기 위해선 받는 사람과, 하는 사람 모두 함께 노력해야 한다.
아무리 코드 리뷰를 하는 사람이 열심히 노력해도, 코드 리뷰를 받을 준비가 제대로 안됐다면 똑바로 코드리뷰가 되지 않는다. 큰 저항없이 팀원들과 코드리뷰를 하기 위해서는 각각의 입장에서 어떤 스탠스를 취해야 하는지 알아보자.
'이게 무슨 코드고 어떤 코드지?!'
'이게 어떤 feature를 만들어서 올리는거지?'
'어떤 기능을 내가 기여할려고 이 PR을 보고 있는거지?'
이런 생각이 드는 리뷰를 한번쯤은 봤을 것이다. 이 경우 리뷰어가 코드를 여러번 읽어야 될 수 있고, 결과적으로 이해 수준이 낮은 리뷰일 수 밖에 없다. 그래서 리뷰어의 이해수준을 올려주자는 취지에서 리뷰받을 준비를 잘 하는 것이 리뷰 자체보다 훨씬 더 중요하다.
잘 준비된 리뷰는 리뷰어에게 "내가 이런 부분에 대해 리뷰 해야겠구나" 하는 마인드셋을 잡아준다. 이 경우 리뷰 시간에 대한 부담을 감소시킬 수 있고 효율성도 높이는 효과를 전부 잡을 수 있다.
'잘 준비된 리뷰'를 준비하기 위해 아래에 소개한 방법들을 잘 알아두자.
핵심은 같이 작업하는 Git repo의 사용법을 조직적으로 약속하고 관리하자는 것이다.
무조건적인 정답은 없겠지만, 적어도 같은 방법을 일하는 사람들끼리는 싱크가 맞아야 한다.
'이게 좋은데?', '저게 좋은데?' 하면서 서로 다른 방법으로 일을 해버린다면 이 노력이 수포로 돌아가버리기에, 이 합의가 가장 중요하다. 이 합의로 얻고자 하는건 다음과 같다.
리뷰어가 Context를 빠르게 이해하고 준비하도록 돕는 것
'지금 무슨 일을 하다 이걸 올린거지?'
'이 일은 어떤 설계에 들어가 있는거지?'
'언제 배포하는 버전에 대해서 어떤 기능을 하는거지?'
모든 것들에 대해 완전히 이해한 상태에서 리뷰하는 것과 아닌 것은 분명히 다르다. 그렇기에 이해를 완전히 시킨 상태에서 이 코드를 보게끔 유도하자는 것이다.
이 세미나에선 Git을 똑바로 사용하기 위한 방법으로 '팀 내 브랜치 관리전략 준수', 'Commit Convention'을 소개했다. branch 전략 물론 중요하지만, 나는 commit convention 위주로 얻어간게 더 많았기에 해당 내용을 정리해봤다.
작업 하나의 단위를 commit이라 하고, 이게 어떤 작업인지를 설명하는걸 commit message라 한다. 내가 한 작업을 대표하는 문구인 커밋 메시지만 보고도, 어떤 작업을 했는지 남들이 바로 알 수 있다면 코드리뷰를 할때 직관성이 확보된다. 그렇기에 커밋 메시지의 중요성은 높다.
예를 들어, 다음과 같은 커밋 리스트가 있다고 하자.
feat: 회원가입 기능 추가
perf: 회원가입 과정에서 DB에 데이터를 넣는 속도 최적화
perf: 회원가입 과정에서 ...
위 예시에서 커밋 타입(feat perf perf
)만 보고도 기능 하나를 추가했고 성능이 마음에 안들어 2번 개선했다는 것을 알 수 있다. 이걸 본 리뷰어는 '이 기능은 어떤 로직인지, 코드가 잘 짜여졌는지 검사함과 동시에 효율적인 코드인지, 좀 더 빨라질 수 없는지를 봐줘야 겠다'는 생각이 절로 들게된다.
이렇게 직관적으로 어떤 작업을 했는지 보여줌으로써 리뷰어가 어떤 부분을 중심으로 리뷰해야되는지 마인드셋을 잡아 주는 것이 커밋 컨벤션의 핵심이다. 이런 중요성을 알고 나니 가끔 커밋 메시지를 적는게 귀찮다며 아무 생각없이 test로 올렸던 과거가 부끄러워졌다...
💡 '이렇게만 하면 기본으로 커밋 컨벤션 반은 먹고 들어간다!
https://www.conventionalcommits.org/en/v1.0.0/
처음 컨벤션을 세팅하는데 있어 좋은 샘플을 가진 사이트다. 강연자분 말씀으로는 큰 규모의 스타트업 회사들이 코드 리뷰를 도입할때 이 사이트를 참고한 경우가 많아, 여기에 익숙해진다면 여러모로 도움이 될 수 있다고 했다.
리뷰를 잘 받기 위한 두번째 조건은 '리뷰받을 준비가 된 PR을 만들자'는 것이다.
리뷰어의 시간은 내 시간만큼 소중하기에 당연하게 여기면 안된다.
리뷰어가 보기 전에 내가 날린 PR이 최소한의 조건을 만족하는지 다시 살펴보는게 굉장히 중요하다. 세미나에서 언급한 '최소한의 조건'으로 4개가 제시됐다.
CI 파이프라인이 통과되었는가?
- 개인의 코드가 팀의 코드로 인정받기 위한 최소한의 조건을 충족했는가?
- Formatter, Type Checker, Unit Test...
PR이 가능한 리뷰 크기인가?
- 보라고 올린건지 말라는건지 모르겠는 PR이 가끔 발생한다. 이 경우 어떻게 해야할까?
적절한 리뷰어를 설정하였는가?
- 개인, 팀별 Reviewer 설정, Branch Protection Rule, Code Owner등
Self-Review를 마쳤는가?
- 리뷰는 리뷰어가 아니라, 나 자신도 해야한다.
이 내용들을 다 적고 싶지만 분량이 길어 간략히 작성했으니, 각 파트별로 자세한 내용이 궁금하다면 아래 링크로 들어가 한빛미디어에서 공개한 세미나 영상을 확인하자.
https://www.hanbitn.com/product/msa2023-code-review-culture/
코드 리뷰는 이름이 코드 리뷰지만, 코드만 리뷰하는 일은 아니다.
코드 리뷰의 진정한 가치를 끌어올리려면 다음 3가지 제언을 꼭 염두에 두자.
코드 리뷰에서 전반적인 로직 구성과 대안 검토는 당연하다. 여기서 한발 더 나아가 코딩을 잘 하는게 문제가 아니고 일을 잘 해야하는 범주에서 '풀고자 하는 문제를 올바르게 해결했는가?'를 봐야한다. 그래서 이건 비즈니스 문제와 동일하다. '어떤 비즈니스 문제를 풀려고 이 코드를 짰는가?', '어떤 상황이 미래에 올 수 있는가?'에 대한 고민을 같이 해야되는 것이다.
💡 Example
어떤 코드가 금방 엎어질 코드인데 꼼꼼하게 추상화 한 경우, 나중에 빨리 수정할 일이 있을때 전체 상속구조를 다 지켜가며 코딩해야하기 때문에 병목이 발생할 수 있다.
이런 경우 미래 상황을 고려해 피드백을 줄 수 있다.
또한 내 지식을 효과적으로 공유하고, 코드를 짠 사람의 책임을 서로 나누는 용도로 코드리뷰를 사용하는게 중요하다. 이 코드를 가장 잘 짤 수 있는 방법을 그 사람 말고 내가 알 수도 있기 때문에, 알고 있는 것들을 전부 전달하겠다는 일념으로 코멘트를 굉장히 성실하게 달아줘야 한다.
“이거 너무 복잡해요. 수정해주세요.”, “이거 복잡해요. 이렇게 수정하면 좋을것 같아요.”
→ 막말로 이 경우 "그걸 왜 님이 판단하시죠?"라고 올 수 있다.“제 생각에는 이런 상황에선 이렇게 짜는게 맞는거 같은데, 그렇게 짜면 이런 문제가 발생할 것 같아요. 그래서 이렇게 짰으면 좋겠어요.”
→ 그렇기에 이 3박자가 다 맞아 떨어지도록 올바른 문제제기를 하자.
위처럼 다각도에서 살펴보고 원인을 충분히 제공하며 의견을 공유하자. 그리고 이 코드를 같이 봤기에 코드에 대한 Ownership은 서로 공유한다는 점도 중요하다. '이제부터는 항상 내가 짠거와 다름이 없다'라는 수준으로 싱크를 할 수 있게끔 상세하게 볼 수 있어야 한다.
처음 개발팀에 들어오면 '예의바르게 대해야지!' 라는 생각으로 접근해 이런 피드백에 소극적일 수 밖에 없다고 한다. 근데 예의를 잘 지키는 것과 피드백을 똑바로 하는건 다른 개념이다. 예의를 지키면서 할말은 다 해야한다. 그렇기 때문에 서로가 코드, 설계, 제품을 더 좋게 만들기 위한 의지가 있다는 믿음을 바탕으로 솔직하게 이야기 할 수 있어야 하고, 건강하게 충돌하자.
물론 이 과정에서 지식의 한계를 맛볼 수 있다. 솔직하게 얘기했지만 틀린 답안일 수 있고, 이때 들어오는 지적은 굉장히 좋은 성장의 밑거름이 된다. 시니어의 노하우와 지식을 흡수하며 빠르게 성장할 수 있는 좋은 발판이 되는 셈이다. 그래서 적극적으로 피드백 할 수 있어야 한다.
"얜 나한테 왜이러지..."
"나 왜 이것밖에 못짠거지..."
솔직하게 얘기했을때 리뷰를 받는 사람 입장에서 이 리뷰가 나에게 하는 인신공격이나 비난이 아님을 이해하고 상처받지 않는 연습을 해야한다. 처음에는 실제로 상처받는 경우가 많다. 어떤 경우에는 자책과 자괴감이 들지만 너무 당연한 경험이다. 내 성장을 위해서 내 동료, 사수가 주는 솔직한 피드백이자 성장을 위한 좋은 믿거름이란 생각을 가지고 곧이 곧대로 수용하자.
코드가 깔끔하더라도 지적사항을 안쓰면 대충 리뷰한 느낌이 들 수 있다. 그렇다고 괜히 지적사항을 괜히 찾아서 쓰진 말고, 간단한 칭찬을 적어주자. 양성 피드백은 의지를 북돋아 더 나은 퍼포먼스를 내게 해주며, 엔지니어링 팀에 큰 효용을 가져다준다. 무엇보다도 건강하게 충돌하기 쉬운 환경이 조성된다. 그러니 칭찬에 인색해지지 말자.
‘쟤네는 저렇게 좋은거 하는데 우리는 왜 안해?’
각 팀은, 서로 다른 문화를 지닌다. 팀마다 다른 문화를 가지고 있다해서 잘하고 못함을 나누지 말고, 우리 팀에 가장 좋은 문화의 도입방식은 무엇인지 살펴보자.
우리 팀에 좋은 방법을 잘 짜서 제안해야 하는 책임은 나 자신에게 있다. 우리팀에 잘 맞는 방법은 내가 제일 잘 아니까. 팀에 맞게 잘 정리해서 제안하고, 적극적으로 퍼뜨려보자! 소음이 발생하더라도 일단 밀어 붙이고, 한 분기 정도 운영한 뒤에 적용한 방법에 대해 피드백이 있다면 모아서 개선하고 또 돌고… 돌다보면 우리팀만이 가지고 있는 진짜 자랑스러운 문화로 자리잡게 될 것이다.
코드리뷰, 굉장히 도입이 힘든게 사실이다. 팀/회사 입장에서는 효용보다 비용이 먼저 보이기에 더욱 더 비용에 많은 신경을 쓰게 되지만, 다 자양분이 되서 팀의 가치를 쌓는 방법이 된다는 것을 분명히 인지하자. 그리고 어떤 코드 리뷰 문화를 도입할 수 있을지 생각한 뒤에 팀에 도입해보자.
코드 리뷰는 행위가 아닌 문화입니다.
반려동물을 키움으로써 얻는 행복은 이루 말할 수 없다. 이 글을 보는 '집사', '주인'들이라면 공감하겠지만 초기 비용이 정말 많이 들어간다. 무엇보다 가장 중요한 문제는 같이 키우는 구성원들의 책임감이다. 혼자 책임진다고 될 일도 아니고, 분명히 모두가 노력해야 하는 부분이다.
이런 부분에서 어쩌면 '반려동물을 키울때 구성원들이 가져야 할 책임감'은 '팀 전체가 코드리뷰를 하는 이유를 명확히 이해하는 것'과 일맥상통하는게 아닐까 싶었다. 나 혼자 한다고 문화가 되는게 아니기에, 팀 전체가 이해하고 움직여야만 코드 리뷰가 반려 동물의 행복에 맞먹는 장점을 가져다 주는게 아닐까. 적어도 이번 세미나를 들으며 그렇게 생각했다.
예의를 잘 지키는 것과 피드백을 똑바로 하는건 다른 문제이니 솔직하게 이야기 하기
이번 리뷰글을 작성하며 내가 작성한 피드백들을 찾아봤다. 크게 지적할만한 부분이 아니라면 기본적으로 상대방의 기분을 우선시한 경향이 있었는데, '사람 좋은게 좋은거지~'란 마인드로 작성한 느낌이다. 그렇지만 이제는 위 문장을 추진력으로 삼아 거리낌 없이 건강한 충돌을 시도해볼 수 있지 않을까?
그리고 강연의 절반 정도는 Git의 활용법을 언급하셨던 것 만큼 Commit Message나, 브랜치 관리전략 외에도 PR에 도움을 줄 수 있는 다양한 팁들로 코드 리뷰를 진행하며, 향후 원하는 만큼의 결과물을 얻어보고 싶다.
'조직 전체가 어떻게 효율적으로 소통하고, 생산적으로 일할 수 있을까'
이 약속을 했기 때문에 서로 솔직하게 얘기하고 충돌이 가능했다는 내용은 유독 단순한 피드백에도 자책을 깊게 하는 사람들이 분명히 배워야 할 부분이라고 본다. (특히 내가 배워야 할 부분이었다.)
해당 게시글을 작성하며 미처 언급하지 못한 Reviewer, Reviewee가 갖춰야 할 부분이 있다. 이 부분의 자세한 내용을 확인하거나, 본인의 팀에 코드 리뷰를 도입하고 싶다면 아래 링크로 들어가 한빛미디어에서 공개한 VOD, 세미나 자료를 확인해보도록 하자.
https://www.hanbitn.com/product/msa2023-code-review-culture/
추가로 이 글을 작성하는 시점에서 다음 세미나는 Copilot을 주제로 09.14에 진행되는데,
아래 링크에서 참가 신청이 가능하다!