코드 리뷰에서 '이건 안 됩니다'라고 말하기의 어려움

코드 리뷰에서 '이건 안 됩니다'라고 말하기의 어려움

코드 리뷰에서 ‘이건 안 됩니다’라고 말하기의 어려움

시작은 슬랙 알림

아침 10시. 슬랙 알림이 울렸다.

“김 개발님, PR 올렸습니다~ 확인 부탁드려요!”

이모티콘까지 붙어있다. 귀엽다. 하지만 나는 안다. 저 PR을 열면 내 30분이 사라진다는 걸.

커피 한 모금 마시고 깃허브를 켰다.

파일 하나에 500줄

첫 줄부터 한숨이 나왔다.

public class UserService {
    // 500줄의 메서드들...
}

500줄이 한 파일에 있다. 메서드 하나가 100줄이다. if문이 5단 중첩이다.

작동은 한다. 테스트도 통과한다. 효율적이기까지 하다.

하지만 읽을 수가 없다.

나는 스크롤을 내리며 생각했다. “이거 어떻게 말하지?”

후배는 2년차다. 나름 열심히 한다. 야근도 마다 않는다. 근데 코드가 이렇다.

직책이 있으면 쉽다. “팀장 지시사항입니다” 하면 끝이다.

근데 나는 그냥 선임이다. 사실상 테크 리드인데 직책이 없다. 연봉도 별로 안 높다.

“이건 안 됩니다” 라고 말할 권한이 애매하다.

댓글 창 앞에서 10분

커서가 댓글 입력창에서 깜빡인다.

뭐라고 쓸까.

“이 코드는 가독성이 떨어집니다” - 너무 딱딱하다. “메서드를 좀 더 나눠주시면…” - 너무 약하다. “이렇게 하면 나중에 유지보수가…” - 잔소리 같다.

결국 이렇게 썼다.

“수고하셨습니다. 몇 가지 제안 드립니다.”

제안. 안전한 단어다. 명령이 아니다. 거절 가능하다.

그리고 댓글을 달기 시작했다.

“이 메서드가 100줄이 넘어서 한눈에 파악하기 어려울 것 같습니다. 책임별로 나눠보면 어떨까요?”

“if 중첩이 깊어서 읽기 어렵습니다. Early return 패턴을 고려해보시면…”

“변수명이 a, b, c로 되어있어서 의도를 파악하기 어렵습니다.”

댓글 7개를 달았다. 20분이 걸렸다.

말투를 신경 썼다. “~하세요” 대신 “~하면 어떨까요”. “틀렸습니다” 대신 “어려울 것 같습니다”.

제출 버튼을 누르기 전에 다시 읽었다. 기분 나쁘게 들리지 않나. 너무 약하게 들리지 않나.

5분 더 고민했다. 그리고 제출을 눌렀다.

30분 뒤의 답장

“아 그렇군요! 그럼 이렇게 수정하면 될까요?”

답장이 빨랐다. 기분 나쁘지 않은 것 같다. 다행이다.

근데 수정본을 보니 별로 안 바뀌었다.

메서드 이름만 바꿨다. 구조는 그대로다. 여전히 100줄이다.

“음… 제가 말씀드린 건 구조를 나누는 거였는데요.”

이렇게 쓰려다 지웠다. 너무 직접적이다.

“좋습니다! 다만 메서드 길이도 함께 조정하면 더 좋을 것 같아요.”

또 제안이다. 명령이 아니다.

“아 네! 그럼 어떻게 나누는 게 좋을까요?”

질문이 왔다. 이제 내가 예시를 보여줘야 한다.

브랜치를 따서 직접 수정했다. 30분이 걸렸다.

500줄을 5개 클래스로 나눴다. 메서드는 20줄 이내로 줄였다. 변수명을 의미 있게 바꿨다.

“이런 식으로 나누면 각 클래스의 책임이 명확해집니다.”

커밋을 푸시하고 링크를 보냈다.

“오 이해했습니다! 감사합니다!”

이모티콘 3개가 붙었다.

1시간이 지났다. 내 일은 못 했다.

직책 없는 테크 리드의 딜레마

팀장이 있긴 하다.

근데 팀장은 코드를 안 본다. 관리만 한다. 회의만 한다.

실제 기술 결정은 내가 한다. 아키텍처도 내가 짠다. 코드 리뷰도 내가 한다.

근데 직책은 없다.

명함에 “선임 연구원”이라고 적혀있다. 연구는 안 하는데.

월급은 6500이다. 동기들은 7천 넘게 받는다고 한다.

“직책 주면 안 되냐”고 팀장한테 물었다.

“위에서 아직 승인이 안 났어요. 조금만 기다리세요.”

1년째 기다리는 중이다.

직책이 없으니까 말하기가 애매하다.

“이건 안 됩니다”라고 딱 잘라 말할 수 없다. 권한이 없다.

그래서 항상 “제안”한다. “부탁”한다. “의견”을 낸다.

피곤하다.

점심시간의 고민

점심은 김치찌개집에 갔다.

사장님이 이름을 안다. “개발님 오셨어요~”

단골이다. 주 3회는 온다.

김치찌개를 먹으면서 생각했다.

‘내가 너무 약하게 말하나?’

‘아니면 적당한 건가?’

‘다른 회사 시니어들은 어떻게 하지?’

스택오버플로우에 비슷한 질문이 있었다.

“How to give code review feedback without sounding harsh?”

답변들을 읽었다.

  • “Be specific and objective”
  • “Focus on the code, not the person”
  • “Suggest alternatives instead of just criticizing”

다 알고 있다. 근데 한국 회사에서는 다르다.

위계가 있다. 눈치가 있다. 분위기가 있다.

“이 코드는 SOLID 원칙을 위반합니다”라고 말하면 학술 논문이다.

“형, 이거 좀 이상한 것 같은데요”라고 말해야 먹힌다.

근데 나는 형도 아니고 팀장도 아니다. 그냥 선임이다.

밥을 다 먹고 사무실로 돌아왔다. 슬랙에 알림이 7개다.

오후 3시, 두 번째 PR

또 알림이 왔다.

“김 개발님, PR 수정했습니다!”

열어봤다.

여전히 별로다.

클래스를 나누긴 했는데 책임 분리가 안 됐다. 그냥 줄 수만 줄였다.

또 댓글을 달아야 한다.

커서가 깜빡인다.

뭐라고 쓸까.

“이건 여전히 개선이 필요할 것 같습니다” - 너무 애매하다. “제가 보여드린 예시와 조금 다른 것 같아요” - 비교하는 것 같다. “다시 한 번 수정 부탁드립니다” - 짜증난 것 같다.

5분 고민했다.

그리고 이렇게 썼다.

“방향은 좋습니다! 다만 클래스 간 의존성을 조금 더 정리하면 좋을 것 같아요. 각 클래스가 하나의 책임만 가지도록 해보시겠어요?”

또 제안이다. 칭찬 먼저 하고 제안한다.

샌드위치 피드백이다. 좋은 말 - 개선점 - 좋은 말.

근데 빵이 너무 얇다. 속이 뻔히 보인다.

회의 중에도 생각남

4시에 주간 회의가 있다.

기획자가 발표한다. “이번 기능은 간단합니다.”

간단하다는 말이 나오면 복잡한 거다.

팀장이 묻는다. “개발 기간 얼마나 걸릴까요?”

나를 본다.

“2주 정도 필요할 것 같습니다.”

“1주면 안 될까요?”

“백엔드 구조를 새로 짜야 해서…”

“기존 코드 활용하면 되지 않나요?”

기존 코드가 엉망이라서 못 쓴다. 리팩토링 필요하다.

근데 말할 수 없다. “기존 코드가 엉망입니다”라고 하면 누구 책임이냐고 물어본다.

내 책임이다. 내가 리뷰했으니까.

”…최대한 단축해보겠습니다.”

회의가 끝나고 자리로 돌아왔다.

슬랙에 또 알림이다.

“김 개발님, 이해가 잘 안 가서요. 잠깐 설명 부탁드려요.”

일어나서 후배 자리로 갔다.

설명하는 20분

“여기 이 부분이요.”

후배가 화면을 가리킨다.

“이걸 왜 나눠야 하는지 모르겠어요.”

내가 작성한 예시 코드를 보고 있다.

“지금은 UserService가 너무 많은 일을 하잖아.”

“네.”

“사용자 조회, 생성, 수정, 삭제, 권한 체크, 알림 발송까지.”

“네.”

“나중에 알림 로직만 바꾸고 싶으면?”

”…UserService를 수정하면 되는데요?”

“그럼 사용자 조회 기능도 영향받을 수 있어.”

“아…”

“그래서 책임을 나누는 거야. 알림은 NotificationService로.”

“아 그렇구나!”

이해했다는 표정이다.

20분이 걸렸다. PR 댓글로는 5분이면 쓸 내용이다.

근데 직접 설명하면 20분이다.

자리로 돌아왔다. 시간을 봤다. 5시다.

오늘 내 코드는 한 줄도 못 썼다.

퇴근길 지하철에서

6시에 퇴근했다.

지하철에 앉아서 폰을 봤다.

유튜브에 추천 영상이 떴다.

“시니어 개발자가 코드 리뷰하는 법”

봤다.

외국 개발자가 나온다. 영어로 말한다.

“Be direct but kind.”

“Explain why, not just what.”

“It’s about the code, not the coder.”

다 맞는 말이다.

근데 저 사람은 직책이 있을 거다. Senior Engineer라고 명함에 적혀있을 거다.

나는 선임 연구원이다. 연구 안 하는.

댓글을 봤다.

“우리 팀장은 그냥 ‘이거 왜 이렇게 짰어?’ 하고 끝남 ㅋㅋ”

“권한 없으면 말 안 먹힘. 그냥 포기.”

공감이 됐다.

집에 와서

7시에 집에 도착했다.

아내가 야근이다.

라면을 끓였다. 신라면에 계란 1개.

먹으면서 슬랙을 봤다. 습관이다.

“김 개발님 감사합니다! 이해했어요!”

후배가 메시지를 보냈다.

기분이 좋았다. 잠깐.

그리고 다음 메시지가 왔다.

“그런데 이 부분은 원래대로 해도 될까요? 지금 방식이 더 익숙해서요.”

한숨이 나왔다.

익숙하다는 건 핑계다. 바꾸기 귀찮다는 소리다.

댓글을 쓰려다 멈췄다.

‘또 설득해야 하나?’

‘그냥 놔둘까?’

‘나중에 문제 생기면 내가 고치면 되지.’

근데 그게 계속 쌓인다. 레거시가 된다.

결국 이렇게 답했다.

“일단 현재 방식으로 머지하시고, 다음 스프린트 때 리팩토링 태스크로 잡읍시다.”

타협이다.

읽음 표시가 떴다. 답은 없다.

아마 다음 스프린트 때도 우선순위 밀린다.

밤 10시, 침대에서

넷플릭스를 틀었다.

근데 집중이 안 된다.

‘내가 너무 약하게 말하나?’

‘직책이 있으면 다를까?’

‘다른 회사로 이직하면 나아질까?’

생각만 했다.

이직하려면 코테 준비해야 한다. 알고리즘 공부해야 한다.

피곤하다. 주말에 하자.

주말은 늦잠 자고 치킨 먹는 날이다.

폰을 내려놨다.

잠이 안 온다.

슬랙 알림이 또 울릴까봐 무음으로 해뒀다.

근데 자꾸 폰을 본다. 습관이다.

알림은 없다. 다행이다.

아내가 11시에 들어왔다.

“오늘 어땠어?”

“그냥 그랬어. 너는?”

“디자인 수정 요청 5번 받았어.”

“힘들었네.”

“너도?”

“응.”

더 말하지 않았다. 둘 다 피곤하다.

다음날 아침

9시에 출근했다.

커피를 뽑았다. 아이스 아메리카노.

자리에 앉아서 슬랙을 켰다.

알림 3개다.

첫 번째: “김 개발님, 새 PR 올렸습니다~”

두 번째: “급한데 리뷰 부탁드려요!”

세 번째: “이번엔 잘한 것 같아요 ㅎㅎ”

깃허브를 켰다.

또 500줄이다.

커피를 한 모금 마셨다.

댓글 입력창을 열었다.

커서가 깜빡인다.

“수고하셨습니다. 몇 가지 제안 드립니다.”

오늘도 제안한다. 명령이 아니다.

직책이 생길 때까지.

아니면 이직할 때까지.


직책 없는 테크 리드는 오늘도 제안한다. 조심스럽게.