입사 3주 차, 생애 첫 코드 리뷰. 내 코드가 틀린 게 아니라 내 존재가 부정당하는 것 같았던 그 오후
입사 3주 차였다. 처음으로 혼자 맡은 기능을 완성하고, 두근거리는 마음으로 PR을 올렸다. 커밋 메시지도 신경 써서 썼고, 기능도 잘 돌아갔다. 잘했다, 나.
세 시간 뒤 깃허브 알림이 울리기 시작했다. 하나, 둘, 다섯, 열… 알림이 멈추지 않았다. 설레는 마음으로 PR을 열었다가, 화면을 스크롤하면서 얼굴이 굳었다. 댓글이 17개였다. 초록 체크 하나 없이, 전부 노란 동그라미와 빨간 느낌표였다.
그날 퇴근길에 이어폰을 꽂고 지하철에 앉아서 창밖을 보다가 생각했다. 내가 개발자가 맞나.

(초기 라운드)
PR을 올리던 그 순간 — 자신감이 넘쳤다
기능 자체는 단순했다. 사용자 프로필 수정 폼에 유효성 검사 로직을 추가하고, API 연동을 붙이는 작업이었다. 이틀 동안 꼼꼼하게 만들었다고 생각했다. 실제로 로컬에서 테스트도 다 돼 있었다.
PR 설명도 열심히 썼다. 어떤 기능을 추가했는지, 테스트 방법은 어떻게 되는지. 선배 개발자들의 PR을 참고해서 형식도 맞췄다. 올리고 나서 슬랙에 PR 링크를 공유하면서 내심 "잘 만들었죠?"라는 말이 목구멍까지 올라왔다.
"처음엔 코멘트 개수가 피드백의 양인 줄 알았다. 나중엔 그게 관심의 양이라는 걸 알게 됐다."
— 6개월이 지난 뒤에야 이해한 것실제 받은 코멘트들 — 재현해봤다
기억을 더듬어서 당시 받은 코멘트 유형들을 재현해봤다. 지금 보면 전부 타당한 지적이다. 그런데 당시엔 그렇게 느껴지지 않았다.
이 코멘트는 솔직히 맞는 말이었다. ==랑 === 차이를 이론으로는 알고 있었는데, 실제 코드 짤 때 무의식적으로 ==를 썼던 것이다. 당시 내 반응은 "이거 하나 가지고 이렇게까지 말해야 해?"였다. 지금 생각하면 창피하다.
console.log는 프로덕션 코드에 남기지 않아요. 디버깅용이라면 개발 끝나고 지워주시고, 에러 처리는 사용자에게 명확한 메시지를 보여줘야 합니다. catch 블록에서 그냥 log만 하면 사용자는 아무것도 모르는 채로 실패하게 돼요.useState로 관리하고 있는데, 이 경우엔 하나의 객체로 묶는 게 더 낫습니다. 상태가 늘어날수록 관리가 어려워지고, 나중에 필드 추가 시 매번 state를 추가해야 해요. react-hook-form 같은 라이브러리도 검토해보셨나요?이 마지막 코멘트가 가장 충격이었다. 이틀 동안 만든 구조 자체를 바꾸라는 말이었으니까. 당시엔 "내 설계가 틀렸다는 거야?"로 읽혔다. 지금은 "더 좋은 방법이 있어요"로 읽힌다. 같은 문장인데 해석이 완전히 달랐던 것이다.
"이 부분 수정해주세요" → "너 이것도 몰라?"
"더 나은 방법이 있어요" → "네 설계는 쓸모없어"
"린트 규칙 확인해주세요" → "기본도 안 지키네"
"라이브러리 검토해보셨나요?" → "왜 이것도 모르고 짰어?"
실제로 그 문장들에 그런 의미는 없었다.
그날 밤 — 혼자 앉아서 한 생각들
===로 바꾸고, console.log 지우고, 에러 상태를 객체로 합치고, react-hook-form도 처음 써봤다. 두 번째 PR엔 댓글이 6개였다. 그게 그나마 위안이 됐다.Before / After — 실제로 코드가 어떻게 바뀌었나
// 에러 상태 4개 따로따로
const [nameErr, setNameErr]
= useState('')
const [emailErr, setEmailErr]
= useState('')
const [phoneErr, setPhoneErr]
= useState('')
const [bioErr, setBioErr]
= useState('')
// 유효성 검사도 직접
if (name == '') {
setNameErr('필수 입력')
}
// ... 필드마다 반복
// 에러 처리
} catch(e) {
console.log(e)
}
// react-hook-form 도입
const {
register,
handleSubmit,
formState: { errors }
} = useForm<ProfileInput>()
// 유효성 규칙 선언적으로
<input
{...register('name', {
required: '필수 입력',
maxLength: 20
})}
/>
// 에러 처리 제대로
} catch(err) {
toast.error(
'저장 실패. 다시 시도해주세요'
)
}
코드가 절반으로 줄었고, 유지보수도 훨씬 쉬워졌다. 나중에 필드가 두 개 추가됐을 때 이전 방식이었으면 useState 두 개를 더 만들었을 텐데, 수정된 코드에서는 register 한 줄이면 끝이었다. 당시엔 공격으로 느꼈던 것이, 사실 선물이었다. 핵심 깨달음
코멘트 유형별로 이해하기 — 이걸 알았으면 덜 무너졌을 텐데
나중에 팀의 다른 PR들을 유심히 살펴보면서, 코드 리뷰 코멘트가 실제로 여러 유형으로 나뉜다는 걸 알게 됐다. 당시에 이걸 구분할 줄 알았다면 훨씬 덜 힘들었을 것이다.
| 유형 | 예시 표현 | 실제 의미 | 대응 방식 |
|---|---|---|---|
| 필수 수정 | "이렇게 하면 버그 납니다", "보안 이슈" | 머지 전 반드시 고쳐야 함 | 바로 수정, 이유 이해하고 넘어가기 |
| 제안 | "더 나은 방법이 있어요", "검토해보시겠어요?" | 강제 아님, 더 나은 방향 제시 | 이유 물어보고 적용 여부 판단해도 됨 |
| Nitpick | "nit:", "개인적으로는~", "취향 차이지만" | 사소한 스타일 지적, 블로커 아님 | 적용해도 되고 이유 설명해도 됨 |
| 칭찬 | "이 부분 좋네요!", "깔끔하게 잘 짜셨어요" | 배운 점 공유 / 긍정 피드백 | 그냥 받아들이기 (쑥스러워도) |
"nit: 변수명을 좀 더 명확하게"처럼 앞에
nit:이 붙은 코멘트는 Nitpick의 줄임말이다. 머지를 막지 않는 사소한 제안이라는 신호다. 이걸 모르고 필수 수정과 똑같은 무게로 받아들이면 불필요하게 소진된다.3개월 후, 내가 코드 리뷰를 주는 입장이 됐을 때
신입이 들어왔다. 첫 PR을 올렸는데, 솔직히 내 첫 PR이 떠올랐다. console.log가 다섯 개 있었고, 상태 관리가 분산돼 있었다. 나는 댓글을 쓰다가 잠깐 멈췄다.
"console.log는 프로덕션에서 지워주세요 😊 디버깅할 때 편하게 쓰다가 남은 거죠? 저도 처음엔 자주 그랬어요."
같은 지적인데, 이 한 문장이 다르게 느껴질 거라는 걸 알았다. 내 첫 리뷰어가 그렇게 써줬다면 그날 밤을 덜 힘들게 보냈을 것 같아서.
그렇다고 내 첫 리뷰어가 나쁜 사람이었다고 생각하지 않는다. 돌이켜보면 그분은 정확한 피드백을 줬다. 다만 나는 그걸 받을 준비가 안 돼 있었던 것이다. 코드 리뷰는 코드에 관한 것인데, 나는 그걸 나에 관한 것으로 받아들였다.
지금의 나에게 남은 것 — 6가지 교훈
① PR을 올리기 전에 본인이 먼저 diff를 훑어보기 — "내가 리뷰어라면 뭘 물어볼까"
② PR 크기를 줄이기 — 변경 파일 5개 이하를 목표로
③ 코멘트 유형(필수/제안/nit)을 구분해서 읽기
④ 이해 안 되면 그 자리에서 질문하기 — 혼자 해석하지 않기
⑤ 당일 멘탈 터져도 괜찮다 — 다음날 다시 읽으면 다르게 보인다
지금도 리뷰 많이 달린 PR 알림이 오면 심장이 약간 쫄깃해진다. 완전히 무감각해진 건 아니다. 다만 이제는 알림 소리가 울리면 "내가 뭘 배울 수 있지?"로 시작한다. 그날 지하철에서 창밖 보던 내가 알았으면 좋았을 것들을, 지금 비슷한 상황의 누군가에게 전하고 싶어서 이 글을 썼다.
💬 첫 코드 리뷰, 어떠셨나요?
처음 코드 리뷰를 받았을 때 가장 당황하거나 충격받은 코멘트가 뭐였는지, 혹은 반대로 리뷰를 주는 입장에서 신경 쓰는 점이 있다면 댓글로 나눠주세요. 신입 개발자분들에게도, 리뷰어로서 어떻게 피드백할지 고민하는 분들에게도 분명 도움이 될 것 같습니다. 🙏
'개발자 > 실무 개발 현장' 카테고리의 다른 글
| 배포 후 장애 터졌을 때, 그 긴박했던 밤 이야기 (0) | 2026.06.15 |
|---|---|
| 신입 개발자가 처음 맞닥뜨린 레거시 코드 — 살아남기까지의 기록 (0) | 2026.06.08 |
==대신===사용해주세요. JS에서 동등 연산자는 타입 강제 변환이 일어나서 예기치 않은 동작이 생길 수 있어요. 저희 팀 린트 규칙에도eqeqeq가 설정되어 있습니다.