작년 하반기에 Nextstep 의 클린코드 교육과정을 참여하며 배웠던 내용을 바탕으로 많은 성장을 할 수 있었다. 좋은 수업이라며 주위에 열심히 홍보를 하던 찰나, 과정을 직접 운영하고 계시는 박재성님으로부터 코드 리뷰어 활동을 제안 받게 되었다.
코드 리뷰어로 활동할 수 있는 실력이 안될 것 같아 고민이 되었지만, 재성님의 격려와 좋은 경험을 쌓을 수 있는 기회라고 생각이 되어 제안을 수락하였다.
리뷰어 활동은 약 한달간 진행되었고 그 과정속에서 깨달은 것이 많아 개인적인 정리 및 기록 차원에서 글을 남긴다.
코드 리뷰를 진행하며
처음 리뷰를 진행할 때는 생각 이상으로 많은 시간과 에너지가 소모되었다. 회사 업무를 마치고 또 코드를 봐야하는 압박감도 있었고, 각자 다른 스타일의 코드를 꼼꼼히 확인 하고 적절한 피드백이 무엇일지 고민하고 공부해야했기 때문이다. 또한 리뷰를 마쳐야 리뷰이가 다음 단계를 진행하기 수월하기 때문에 코드가 올라오는데로 최대한 빠르게 피드백을 줄 수 있도록 신경을 써야했다. 따라서 초반에는 시간적 여유가 별로 없다보니 특별한 체계없이 정해진 리뷰의 양을 채워나갔던 것 같다. 점점 시간이 흐를 수록 나름의 체계가 생기고 속도가 붙어 초반보단 여유가 생겼다. 이때 나 스스로의 리뷰 방식/관점에 대해 점검해보며 아래과 같은 기준을 세우고 리뷰를 진행했다.
1. 모호한 지식은 모호한 답변을 남긴다.
특정 내용에 대하여 피드백을 할 때마다 굉장히 모호하게 답변을 남기고 있는 것을 깨달았다. 해당 내용에 대한 정확한 지식이 없다는 신호라고 느꼈다. 이런 수준에서는 좋은 피드백을 줄 수 없을 것 같아 잠시 리뷰를 중단했다. 이후 책과 검색을 통해 좀 더 깊게 공부하고 부족해 보이는 부분을 채워나갔다. 내가 어떤 주제에 대하여 막연히만 알고 있었는지 깨닫는 좋은 순간이었다. 어느정도 정리 및 공부가 끝났다고 생각되면 다시 리뷰를 진행했고 이후에도 비슷한 주제가 나올 경우 위와 같은 과정을 반복하였다.
2. 모든 코드에는 근거가 있어야한다.
리뷰를 진행하다보면 특정 상황에서 관습적으로 굳어진듯한 구현을 발견할때가 있다. 이러한 코드를 발견하면 피드백을 남길 때 집요하게😈어떤 구현 의도를 가지고 작성했는지 물어보곤 했다. 관습적인 구현은 대게 큰 고민 없이 이루어지는 경우가 많다. 하지만 모든 코드는 명확한 근거가 있어야한다고 생각한다. 만약 스스로 세운 근거가 틀리더라도 큰 상관이 없다. 나중에 잘못된 방향임을 깨닫더라도 어떤 부분을 놓쳤는지 비교가 가능하기 때문이다. 특히 나같은 경우 스스로 세운 근거가 틀렸음을 깨달았을 때 더 많이 성장하는 것을 경험했기 때문에 이 부분을 특히 집중했다.
3. 나의 피드백보다 더 좋은 방향은 항상 있을 수 있다.
미션의 요구사항이 간단할 때는 리뷰이의 구현 방향이 대부분 비슷하게 수렴하고 이에 대한 베스트 케이스도 어느정도 정해져있다. 그래서 피드백으로 가이드를 남기는 것도 비교적 수월하다. 그러나 점점 미션의 요구사항이 복잡하고 어려워질 수록 다양한 접근 방식이 나타나기 시작한다. 이때 나 또한 결국 가지고 있는 지식과 경험 내에서 답변할 수 밖에 없는 한계점이 있기 때문에 항상 내가 남긴 피드백보다 더 좋은 방향이 있을 수 있다는 마음가짐으로 리뷰에 임했다. 실제로 다양한 방식으로 풀 수 있는 부분에 대하여 피드백을 남기면 리뷰이에게 종종 문의가 들어왔다. 이때 나는 피드백을 남긴 의도를 최대한 자세히 남겼다. 그리고 리뷰이의 의도 역시 물어본 후 각각 비교하여 장/단점을 생각해보고, 목표를 이루기 위해서 무엇을 취할 수 있을지/버려야할 지 논의했다. 이러한 과정 또한 나의 생각을 정리하고 공부하는 계기가 되어 오히려 내가 스스로 많이 배울 수 있는 좋은 거름이 되었다. 👏
(기억에 남았던 논의 과정, 지금 다시 보니 답변 내용 중 아쉬운 부분이 보인다. 😭)
코드리뷰도 결국은..
코드 리뷰도 결국은 사람과의 커뮤니케이션이다. 또한 사람은 각기 다른 커뮤니케이션 스타일을 가지고 있다. 그래서 소프트 스킬이 어렵다고 생각한다. 논의를 주고 받다보면 각 리뷰이분의 스타일을 대략적으로 파악하고, 이에 맞게 커뮤니케이션 방식을 조금씩 바꿔가며 진행해보려 노력했다. 소프트 스킬을 연습할 수 있는 기회는 흔치 않다고 생각되어 이부분에 대해 적지 않게 신경썼던 기억이 난다.
가장 많이 드렸던 피드백들
리뷰를 하다보면 공통으로 피드백을 많이 남기는 내용이 있었다. 정리를 해보니 다음과 같다.
이 객체가 알아야할 정보가 맞을까요?
→ 클래스가 존재해야할 이유는 하나이다. SRP를 잘 지켰는지 확인했다.
이 코드는 다른 객체에서 스스로 수행할 수 있지 않을까요?
→ 객체 상태를 꺼내와서 연산을 수행하지 말고 상태를 알고 있는 객체에 명령할 것, 객체의 응집도 측면에서 확인했다.
이 메소드의 네이밍을 좀 더 구체적으로 지어볼 수 있을까요? / 좀 더 구현 내용을 숨겨볼 수 있을까요?
→ 아마 리뷰이분들 입장에서는 가장 짜증나는(?) 피드백이지 않았을까.ㅎㅎ 어떤 메소드는 이름을 자세히 짓고, 어떤 메소드는 좀 더 추상적으로 지으라니..🤬🤬
나는 SRP 와 캡슐화의 관점에서 피드백을 진행했다.
(1) 좀 더 구체적으로 지어볼 수 있을까요?
메소드는 하나의 일만을 수행해야 한다. 그리고 수행하는 일을 드러낼 수 있다.
위 규칙을 지킨다면 이름이 모호한 메소드는 수행하는 일이 명확히 드러나도록 표현할 수 있다.
user.get() // (X) 수행하는 일이 명확히 나타나지 않는다.
user.getName() // (O) 무슨일을 수행하는지 알 수 있다.
(2) 좀 더 구현 내용을 숨겨볼 수 있을까요?
캡슐화란 변경 가능성이 높은 부분을 객체 내부로 숨기는 추상화 기법이다.
오브젝트에서는 변경할 수 있는 모든 것을 캡슐화하라고 이야기 한다. (관련 내용에 대하여 과거에 정리했던 글이 있다.)
winnerNumber.getRankWithAnotherNumber(number) // (X) 전달되는 파라미터에 대한 정보가 드러난다.
위와 같은 메소드의 네이밍은 전달되는 인자에 대한 정보가 메소드에 그대로 드러나 있다. 파라미터가 드러나면 어느정도 가독성은 확보할 수 있을지도 모른다. 그러나 파라미터에 대한 변경은 꽤나 빈번하게 발생하는 일이며, 그때마다 해당 메소드의 이름은 변경되어야 할 것이다. 즉, 변경에 취약하다.
그렇다면 어디까지 추상화해야 할까? 메소드에서 변경되지 않는 것이 딱 하나 있다. 바로 메소드가 수행하는 일이다. 따라서 메소드가 수행하는 일만 드러내는 것이 변경에 좀 더 유연한 네이밍이라고 생각되어 피드백을 남겼었다. (1) 번 내용과도 같이 생각해볼만한 부분이다.
winnerNumber.getRank(number) // (O) 수행하는 일만을 명시한다.
요 내용은 개인적으로 고민이 있는 부분이라 다른 의견도 들어보고 싶다. 🤔
동시에 성장하는 경험
내가 알고 있는 지식을 누군가에게 설명해줄 때 가장 공부가 많이 되는 경험을 해본적이 있을 것이다. 코드 리뷰를 진행하면서 비슷한 경험을 했다. 내가 피드백을 제시하기 위해선 근거가 있어야하고 이를 위해서는 탄탄한 지식과 좋은 레퍼런스가 있어야 하기에 엄청나게 공부를 할 수 밖에 없다. 특히 날카로운 질문이 들어올 때, 질문의 주제가 내가 막연하게 알고 있는 내용일 경우 바로 바닥이 나타났기에 더욱 열심히 찾아보고 공부했다. 그래서 과정이 점점 진행될 수록 리뷰이와 내가 동시에 성장을 하는 것을 경험을 했다.
마무리하며
엄청난 열정으로 구현을 진행하고 논의를 나눈 리뷰이분들, 자신의 리뷰과정을 공유하여 다양한 관점으로 볼 수 있게 해준 리뷰어분들, 중간중간 어려움이 있을 때마다 아낌없는 조언을 주신 재성님에게 다시 한번 감사드린다. 🙏 NextStep 에서는 클린코드 과정외에도 다양한 주제의 강의가 진행되고 있으니 관심이 있다면 클릭!