리뷰어에게 사랑받는 코드 리뷰는 어떻게 보낼 수 있을까? - Part 2


code-review-love-cover

Michael Lynch의 How to Make Your Code Reviewer Fall in Love with You을 번역한 글 입니다.

이전 내용인 Part 1에 이어지는 두번째 글 입니다.


#7. 수정사항 쪼개기

하나의 코드 리뷰 요청 안에서 수정사항의 크기를 과도하게 크게 가져가면 5. 수정사항의 범위 제한하기에서 살펴본 것과 유사한 문제가 생깁니다.

기능 X를 새로 개발하기 위해, 기존의 사용하던 두 라이브러리 A와 B의 시멘틱을 변경해야 하는 상황을 생각해볼까요. 이렇게 원래 작업의 목적과는 좀 다른, 파생된 수정사항들을 한 PR에서 다 다루려다 보면 수정사항이 끝없이 커질 수 있습니다.

리뷰어가 코드를 이해하는 데 드는 비용은 수정된 코드 라인수에 비례해서 기하급수적으로 늘어납니다. 프로덕션 코드를 400라인 이상 수정했다면 별개의 코드 리뷰 요청으로 쪼개는 것을 고려해보세요.

모든 것을 한 번에 바꾸는 것보다, 의존당하는 요소들을 먼저 바꾸고 의존하는 녀석을 나중에 바꾸는 것이 유리합니다. 라이브러리 A, B를 먼저 수정하고 나서 기능 X를 개발하는 거죠. 코드 베이스는 멀쩡한 상태를 유지하면서 수정사항을 차례로 적용하는 것이 가능할지 고민해보세요.

그 자체로도 제대로 동작하면서 동시에 의미 단위도 되도록 수정사항을 쪼개는 것이 그다지 재밌는 작업은 아닐 거예요. 하지만 배려심 있게 쪼개진 수정사항을 바탕으로, 부담이 덜어진 리뷰어로부터 더 퀄리티 있는 피드백을 받으실 수 있을 거예요.

#8. 비판에 관대하기

코드 리뷰를 망치는 가장 빠르고 효과적인 방법은 비판을 나에 대한 공격으로 받아들이는 겁니다. 전문성에 자부심을 가진 개발자는 자기 코드를 자기 존재의 연장물로 보는 경향이 있기 때문에 이 함정에 빠지기 쉽습니다. 상대 리뷰어가 공격적인 말투를 사용한다면 더더욱 그렇죠.

내가 요청한 코드 리뷰의 피드백에 어떻게 반응할지에 대한 주도권은 궁극적으로 나에게 있습니다. 리뷰어의 코멘트를 '코드에 대한' 객관적인 논의로 바라보세요. 리뷰어는 '나의 가치에 대해' 논의하고자 하는 것이 아닙니다. 방어적인 대응은 항상 상황을 악화시킬 뿐입니다.

저는 모든 코멘트는 저에게 배울 점을 줄 거라고 기대하고, 항상 이 각도에서 해석하려고 노력해요. 리뷰어가 제 민망한 실수를 찾아 알려주면 저는 본능적으로 변명이 먼저 떠오릅니다. 하지만 한 번 참아내고, 대신 꼼꼼하게 봐줘서 감사하다는 코멘트를 남깁니다.

nice-catch

그리고 리뷰어가 작은 실수를 찾아준다는 것은 의외로 긍정적인 시그널입니다. 리뷰이가 Changelist를 잘 정돈하고 있다는 증거로 볼 수 있기 때문이죠.

#9. 리뷰어가 틀렸을 때 참을성 갖기

때로는 리뷰어가 잘못된 내용의 코멘트를 남길 수도 있습니다. 우리가 코드를 작성할 때 종종 버그를 만드는 것처럼, 리뷰어도 문제없는 코드를 읽다가 실수로 오해할 수 있으니까요.

많은 개발자는 이런 상황에 방어적으로 대응합니다. 무례하게 모욕당했다고 느끼는 거죠. 심지어, 사실도 아닌 잘못된 내용으로요!

리뷰어가 순전히 실수로 오해했다고 하더라도 이것은 일종의 위험 신호입니다. 다른 사람들도 공통적으로 실수하기 쉬운 어떤 포인트가 있는 것은 아닌가요? 몇 번이고 들여다봐야만 특정 버그가 없다는 것을 겨우 확인할 수 있는 코드인 것은 아닌가요?

try-actually-reaading

코드 리팩터링이나 주석을 통해서, 버그가 있다고 오해할 만한 여지를 없애보세요. 그 모호함이 프로그래밍 언어가 제공하는 인터페이스에서 온 거라면, 그 언어의 비전문가도 이해할 수 있는 다른 인터페이스나 기능을 사용해서 구현해보는 것도 방법입니다.

#10. 주도권을 확실하게 주고받기

리뷰어로부터 받은 피드백의 일부만 적용한 뒤 아무런 코멘트도 남기지 않는 분들을 꽤 자주 봤습니다. 사실 이때 굉장히 애매한 상태가 되죠. 리뷰이가 나머지 피드백에 대해 아직 작업 중인 건지, 아니면 그냥 놓치고 지나간 건지 리뷰어의 입장에서는 알 수가 없습니다. 이 상태에서 리뷰를 하자니 작업 중인 내용을 리뷰하고 있는 건 아닌가 싶고요, 마냥 기다리자니 혹시 상대방도 나를 마냥 기다리고 있는 거 아닌가 싶은 생각이 듭니다.

모든 순간 누가 바통을 쥐고 있는지를 알 수 있도록 팀 컨벤션을 만드세요. 작성자가 피드백 반영을 진행 중인지, 리뷰어가 피드백을 작성 중인지 명확히 알 수 있도록요. 누가 뭘 하고 있는지를 서로 몰라서 코드 리뷰가 진척되지 못하는 상황이 오지 않도록 하는 겁니다. 최상위 수준의 코멘트로 진행 상황을 남기면, 주도권의 주고받음이 명확해집니다.

ptal

나의 액션이 필요한 모든 피드백에 대해서 명시적으로 응답하세요. 코멘트를 해결(resolved) 상태로 표시하는 기능을 리뷰 툴에서 제공하기도 하죠. 또는 간단한 규칙을 만드세요. "반영 완료"(Done)라고 각각 코멘트를 남기는 겁니다. 만약 동의하지 않는 제안사항이 있다면 거절의 이유를 살포시 남겨주세요.

reviewable-satisfied

피드백에 들어간 리뷰어의 노력과 시간에 상응하는 응답을 주세요. 내가 몰랐던 기술적인 지식의 설명을 포함한 자세한 코멘트에다가 그냥 "완료"라고 답하는 건 좋지 않습니다. 상대방이 공들여 작성해준 피드백에 대한 감사를 사려 깊게 표현해보세요.

#11. 빠진 정보를 똑똑하게 알아내는 요령

리뷰어의 코멘트 내용만으로는 요청하는 수정사항이 무엇인지 정확히 알 수 없는 경우가 있습니다. 예를 들어, "이 함수는 헷갈리네요"라는 코멘트를 받았다면, "헷갈린다"는 것이 무슨 말일까요? 함수의 길이가 너무 긴 것일까요? 함수의 이름이 적절하지 않은 걸까요? 혹시 추가적인 도큐먼테이션이 필요한 걸까요?

저는 오랜 시간 동안 어떻게 하면 방어적으로 군다는 느낌을 주지 않으면서도 애매한 내용을 구체화시킬 수 있을지 고민했습니다. 제 머릿속에 떠오르는 그대로 "뭐가 헷갈리는데요?"라고 말하면, 지적을 인정하지 못하고 뾰로통해하는 느낌을 준다고 생각했거든요.

제가 무심결에 저희 팀원에게 불명확한 내용의 피드백을 남긴 적이 있는데, 그 팀원의 코멘트가 저를 완전히 무장해제시켰습니다.

그러면 어떻게 수정하면 좋을까요?

이 문장은 방어적으로 굴지 않으면서 비판에 활짝 열려있다는 느낌을 준다는 점 때문에 참 좋습니다. 저에게 명확하지 않은 수정 요청이 오면, 저는 항상 "그러면 어떻게 바꿀까요?"와 비슷한 말로 대답합니다.

또 하나 팁을 드리자면, 리뷰어의 의도를 추측해서 그 가정대로 코드를 미리 수정해버리는 것도 괜찮은 전략입니다. "이 부분 헷갈리네요"라는 피드백을 받은 사람은 일단 그 부분을 다시 한번 보게 되죠. 이때 뭐가 되었든, 무언가 개선할 점이 보통은 보일 겁니다. 리뷰어가 원래 지적하려고 했던 부분이 아니더라도 괜찮습니다. 당신이 수정사항에 열려있다는 시그널은 분명하게 전달이 될 테니까요.

#12. 비등비등할 때는 리뷰어의 편을 들어주기

테니스에서는 상대방의 서브가 서비스 박스 안에 들어왔는지 확실하지 않을 때는, 서브를 성공한 것으로 쳐줍니다. 확실하지 않고 심증만 있는 상황이라면 상대에게 유리한 방향으로 일단 믿어주자(benefit of the doubt)는 거죠. 코드 리뷰도 이와 같은 사고방식을 적용하면 좋습니다.

코드 리뷰를 통해 결정을 내리는 사항들 중에는 옳고 그름보다는 취향의 문제에 가까운 것들도 있습니다. 누군가 5줄짜리 함수 두 개보다 8줄짜리 함수 하나가 더 낫다고 말해도, 이 의견을 옳다 혹은 그르다고 말하기는 힘듭니다. 어쨌거나 각자의 생각, 의견이고 결국 선호도의 문제일 뿐이죠.

리뷰어가 제안해준 것이 있을 때, 나도 그 제안과 비슷한 정도의 근거로 반대 의견을 가지고 있다면, 리뷰어의 말을 따르세요. 내 코드와 더 초면인 쪽은 리뷰어이기 때문에, 처음 읽는 사람의 관점을 더 많이 반영하고 있을 겁니다.

#13. 리뷰 사이의 지연시간을 최소화

몇 달 전, 제가 운영하는 오픈소스 프로젝트에 새로운 개발자분이 컨트리뷰션을 해주셨습니다. 몇 시간 만에 피드백을 드렸는데, 그 뒤로는 답이 없었습니다. 며칠 뒤에 다시 확인해 봤을 때도 여전히 답이 없으시더군요.

그 후로 6주가 지난 뒤에 제가 요청한 피드백이 반영된 리뷰 요청을 다시 받을 수 있었습니다. 그분의 노력에는 감사합니다만, 6주라는 시간 덕에 저는 이 리뷰에 두 배의 노력을 쏟아야 했습니다. 그분이 작성한 코드를 다시 읽어야 했을 뿐만 아니라 제가 드렸던 피드백마저도 다시 읽고 기억해내야 했죠. 6주가 아니라 하루, 이틀의 간격이었다면 저는 훨씬 시간을 덜 쓰면서 수월함을 느꼈을 겁니다.

effort

6주까지는 아니더라도, 팀원들이 불필요하게 시간을 끄는 상황을 종종 봅니다. 리뷰 요청을 보내고 피드백을 받은 다음, 다른 일을 처리하느라 일주일을 그 상태 그대로 묵혀두는 식입니다.

컨택스트를 기억해내는 데에 걸리는 시간도 큰 비용이지만, 처리하다 말았던 수정사항 목록도 복잡도를 증가시키는 데에 한몫합니다. 처리가 끝나 머지된 이슈와 아직 남아있는 이슈를 기억해서 팔로우 업하기가 점점 힘들어지죠. 이런 식의 반쯤 끝난 리뷰 요청이 많을수록, 머지 컨플릭트는 늘어나고 해결은 더욱 요원해질 겁니다.

리뷰 요청을 보내서 일단 스타트를 끊었다면, 해당 리뷰의 라이프사이클을 끝까지 완료하는 것을 높은 우선순위로 생각해야 합니다. 리뷰를 질질 끌게 될수록 리뷰어의 시간을 추가적으로 낭비하게 될 뿐만 아니라, 팀 전체의 작업까지 더 복잡하게 만들게 될 테니까요.

#결론

다음 리뷰 요청을 보낼 때는 생산적인 코드 리뷰를 위해 내가 컨트롤할 수 있는 부분들을 고민해보세요. 리뷰를 진행하는 도중에도, 시간이나 노력의 낭비로 이어지는 패턴은 없는지 점검해보세요.

이 황금률을 다시 한번 기억하세요: 리뷰어의 시간은 소중합니다. 리뷰어가 내 코드의 흥미로운 부분에만 집중해서 양질의 피드백을 만들어내도록 유도할 줄 알아야 합니다. 간단한 실수를 잡아내는 일이나, 내 스파게티 코드를 풀어내는 일을 리뷰어에게 미룬다면 결국 나와 리뷰어 둘 다 고통받을 거예요.

마지막으로, 배려와 함께 커뮤니케이션하세요. 배려 없는 코멘트는 코드 리뷰를 망치는 지름길입니다. 코드를 지적하고 지적당할 때 나도 모르게 뾰족한 말투가 되기 쉬운데, 리뷰어의 감정을 상하게 하는 일이 없도록 신경 써야 합니다.

축하합니다! 여기까지 읽으셨다면 이제 리뷰 요청에는 자신감이 생기셨죠? 앞으로 당신에게 사랑에 빠지는 리뷰어들에게 친절하게 대해주세요.