빠른 프론트 개발을 위한 셀프 리뷰

빠른 프론트 개발을 위한 셀프 리뷰

배경

신입 개발자 시절, 운 좋게도 코드 리뷰를 받을 수 있는 환경에서 개발을 시작했습니다. 처음에는 리뷰의 기준이 무엇인지도 잘 몰랐습니다. 단순히 기능이 정상적으로 동작하면 개발이 끝났다고 생각했고, 리뷰에서 지적받는 내용도 처음에는 사소하게 느껴졌습니다.

import 순서나 변수명처럼 기능과 직접적인 관련이 없어 보이는 부분부터, 이런 질문들을 받곤 했습니다.

  • "이 상태값이 정말 필요한가요?"

  • "watch로 처리했는데 이벤트로 처리하는 것이 더 적절하지 않은가요?"

  • "이 컴포넌트가 너무 많은 책임을 가지고 있지 않은가요?"

  • "null, undefined, 빈 배열을 제대로 처리하고 있나요?"

처음에는 하나하나 수정하는 것이 번거롭기도 했습니다. 하지만 팀 단위 개발과 운영 중인 서비스를 직접 경험하면서 조금씩 생각이 바뀌었습니다. '지금 기능이 동작하는가?'에서 끝나는 것이 아니라, '이 코드를 다른 사람이 다시 수정해야 한다면 쉽게 이해할 수 있을까?'를 생각하게 되었습니다.

운영 환경에서는 "나중에 문제가 생기면 다른 개발자가 고치겠지"라는 생각으로 작업하기가 어렵습니다. 팀으로 개발하더라도 내가 작성한 코드를 다른 사람이 다시 수정할 수도 있고, 몇 달 뒤 내가 다시 해당 코드를 보게 될 수 있기 때문입니다.

이런 경험을 반복하면서 자연스럽게 과거 코드 리뷰에서 확인하던 항목들을 개발 과정에서도 한 번씩 점검하기 시작했습니다.

물론 지금도 모든 코드를 꼼꼼하게 검토하는 것은 현실적으로 어렵습니다. 특히 개발 일정이 빠듯한 상황에서는 더욱 그렇습니다. 그래서 제가 말하는 '셀프 코드 리뷰'는 정밀한 분석보다는 빠르게 개발하면서도 놓치기 쉬운 문제를 한 번 더 확인하는 최소한의 검증 과정에 가깝습니다.

1. 셀프 코드 리뷰가 필요한 이유

빠르게 개발하는 상황에서는 기능을 만들고 정상적으로 동작하는 것을 확인한 뒤 다음 작업으로 넘어가기 쉽습니다. 개발 속도만 생각하면 효율적인 방법일 수 있습니다. 하지만 빠르게 개발할수록 코드를 객관적으로 바라볼 기회가 줄어듭니다. 코드를 작성할 당시에는 전체 맥락을 알고 있기 때문에 불필요한 코드나 애매한 구조를 자연스럽게 넘어가기 쉽습니다.

2. 기능이 동작한다고 리뷰가 끝난 게 아니다

화면이 정상적으로 나오고 버튼을 눌렀을 때 원하는 결과가 나오면 개발이 완료된 것처럼 보입니다. 하지만 실제 서비스에서는 정상적인 상황(Happy Path)만 존재하지 않습니다. API 요청 하나만 보더라도 다양한 상황을 고려해야 합니다.

  • 정상 응답 → 데이터 표시

  • API 실패 → 에러 처리

  • 응답 데이터 없음 → Empty 상태

  • undefined / null → 데이터 존재 여부 확인 및 안전한 처리

  • 연속 클릭 → 중복 요청 또는 상태 꼬임 방지

셀프 리뷰에서는 단순히 "정상적으로 동작하는가?"에서 끝내지 않고, "비정상적인 상황에서도 화면이 깨지지 않는가?"를 확인해야 합니다.

3. 첫 번째 리뷰: 불필요한 코드 찾기

가장 먼저 보는 부분은 의외로 간단합니다. "이 코드가 정말 필요한가?"

① 사용하지 않는 변수와 import

테스트를 위해 남겨둔 console.log()나 더 이상 쓰지 않는 변수, import된 모듈이 없는지 확인합니다. 이런 부분은 ESLint 같은 정적 분석 도구의 도움을 받아 자동화하는 것이 좋습니다.

② 중복 코드

여러 화면에서 동일한 API 호출과 에러 처리를 반복하고 있다면 공통화할 필요가 없는지 검토합니다. 다만 무조건적인 공통화가 정답은 아닙니다. "이 코드를 공통화했을 때 실제로 유지보수가 쉬워지는가?"를 기준으로 판단합니다.

③ 과도한 상태값

// ❌ AS-IS
const dataList = ref([]);
const isEmpty = ref(false);
const hasData = ref(false);
// ⭕ TO-BE
const dataList = ref([]);
const isEmpty = computed(() => dataList.value.length === 0);한 상태값

위처럼 dataList만 있으면 계산해낼 수 있는 isEmpty나 hasData 같은 값을 별도의 상태(ref)로 관리할 필요가 없는지 먼저 검토할 수 있습니다.

상태를 따로 관리하게 되면, 데이터를 업데이트할 때마다 isEmpty나 hasData의 값도 수동으로 같이 업데이트해 줘야 합니다. 상태 업데이트 로직 중 하나라도 누락하면, 실제 데이터는 존재하는데 화면에는 '데이터가 없습니다'라고 뜨는 버그가 발생합니다. computed를 활용해 원본 데이터에 의존적으로 동작하게 만들면 상태값을 수동으로 동기화해야 하는 부분을 줄이고, 개발자가 상태 업데이트를 누락할 가능성도 낮출 수 있습니다.

4. 두 번째 리뷰: 컴포넌트의 책임 확인하기

처음엔 단순했던 컴포넌트도 개발이 진행되면서 사용자 조회, 인증, 폼 검증, 모달, 페이징 등 수많은 책임을 떠안게 됩니다.

큰 컴포넌트를 보면 기능별로 영역을 나누어 보고, 독립적으로 분리할 수 있는지 검토합니다. 단, 코드가 길다는 이유만으로 무작정 쪼개면 파일 탐색 비용만 높아집니다. 중요한 것은 '작게 만드는 것'이 아니라 '책임을 명확하게 만드는 것'입니다.

Props와 Emits: 부모가 너무 많은 상태를 직접 제어하고 있지는 않은지, 이벤트 이름만 보고도 어떤 동작인지 유추할 수 있는지 확인합니다.

5. 세 번째 리뷰: 상태와 예외 상황 확인하기

개인적으로 셀프 리뷰에서 가장 중요하게 봅니다. 화면은 정상적인 상황보다 예외 상황에서 훨씬 쉽게 깨집니다.

① Loading과 Error 상태

데이터를 불러오는 동안 사용자가 피드백을 받고 있는가? (중복 클릭 방지)

API가 실패했을 때 화면이 어떻게 처리되는가? (사용자가 빈 화면에 갇히지 않는가?)

실제로 한 프로젝트의 코드 리뷰를 진행하면서, 인증 과정에서 특정 오류가 발생했을 때 예외 처리가 누락되어 화면 전체가 하얗게 변하고 이후 절차를 진행할 수 없는 문제를 발견한 적이 있습니다. 정상적인 인증 흐름에서는 문제가 없었기 때문에, 정상 케이스만 확인했다면 놓치기 쉬운 오류였습니다. 이 경험 이후 API 호출 코드를 볼 때는 성공했을 때의 결과뿐만 아니라, "여기서 실패하면 사용자는 어떤 화면을 보게 되는가?"를 함께 확인하게 되었습니다.

② Empty와 Null / Undefined

데이터가 빈 배열([])인 상황(Empty State)과 API가 실패한 상황은 다릅니다. 또한 user.profile.name 같은 참조에서 profile이 존재하지 않을 가능성을 고려하지 않으면 런타임 오류로 화면이 정상적으로 렌더링되지 않을 수 있습니다.

6. 네 번째 리뷰: 비동기와 API 호출 확인하기

중복 호출: 페이지 진입 시, watch 동작 시, 사용자 이벤트 발생 시 동일한 API를 불필요하게 호출하고 있지 않은지 확인합니다.

비동기 처리 순서(Race Condition): 사용자가 빠르게 두 번 액션을 취했을 때, 나중에 요청한 데이터가 먼저 도착하고 이전 요청의 데이터가 늦게 도착하면서 최신 상태를 덮어쓸 가능성이 없는지 확인합니다.

7. 다섯 번째 리뷰: 유지보수 관점에서 다시 보기

마지막으로 처음 코드를 보는 사람의 관점에서 정리합니다.

네이밍과 HTML 시맨틱: const temp 대신 역할을 알 수 있는 이름으로 짓고, 클릭 이벤트가 필요한 버튼에 <div> 대신 <button>을 사용했는지 확인합니다.

주석과 죽은 코드: 더 이상 쓰지 않는 코드를 한 바닥씩 주석 처리해 두지 마세요. 과거 이력은 Git이 기억합니다. 주석은 '무엇을' 하는지가 아니라 '왜' 이렇게 짰는지를 설명해야 합니다.

구조적 일관성: 파일 내에서 import, props, state, methods 등의 배치가 프로젝트의 기존 작성 방식과 일관적인지 확인합니다.

프로젝트에 이미 공통 API 처리 방식이나 유틸리티, UI 컴포넌트가 있다면 새로운 방식을 만들기 전에 기존 구현을 먼저 확인합니다.

새롭게 작성한 코드가 기술적으로 더 좋아 보이더라도 프로젝트의 기존 패턴과 달라지면 오히려 유지보수 비용이 증가할 수 있습니다. 따라서 새로운 방식을 적용할 때는 “이 방법이 더 좋아 보이는데?”라는 이유로 기존 방식을 쉽게 바꾸기보다는, 프로젝트 전체에서 일관된 방식으로 동작하는지를 먼저 확인하는 편이 안전합니다.

예를 들어 API 호출과 에러 처리가 이미 공통화되어 있다면, 특정 화면에서만 별도의 방식으로 처리하고 있지는 않은지 확인합니다.

8. 실제 변경 사항을 기준으로 셀프 리뷰하기

코드를 작성하는 중간에 이 모든 것을 체크하면 오히려 개발 속도가 느려집니다. 저는 기능 구현을 우선 끝낸 뒤, Git Diff나 PR의 변경 사항처럼 실제로 수정된 코드만 확인할 수 있는 화면에서 다시 보는 방식을 선호합니다.

작성할 때는 "어떻게 구현하지?"에 집중했다면, 리뷰할 때는 "내가 처음 보는 코드라면 이해할 수 있을까?"로 관점을 바꿉니다.

[최소한의 셀프 리뷰 체크리스트]

  • 기능

  • 정상적인 입력에서 의도대로 동작하는가?

  • Loading / Error / Empty 상태를 처리했는가?

  • null / undefined 가능성을 확인했는가?

  • 기존 기능에 영향을 주지 않는가?

  • 코드

  • 사용하지 않는 변수 / import / console.log가 없는가?

  • 불필요한 상태값을 만들지 않았는가?

  • 중복 로직을 확인했는가?

  • 컴포넌트의 책임이 지나치게 크지 않은가?

  • API / 비동기

  • 동일 API가 불필요하게 중복 호출되지 않는가?

  • API 에러 처리가 일관적인가?

  • 연속 요청으로 상태가 꼬일 가능성은 없는가?

  • 유지보수

  • 변수와 함수 이름만 보고 역할을 이해할 수 있는가?

  • 죽은 코드나 오래된 주석이 없는가?

  • 프로젝트의 기존 패턴과 일관적인가?

  • 처음 보는 개발자가 코드를 따라갈 수 있는가?

9. 실무 리뷰 경험과 현실적인 타협

신입 시절 리뷰를 받으며 익혔던 것들은, 이후 운영 중인 서비스를 개선하는 프로젝트에서 코드 리뷰를 맡았을 때도 도움이 되었습니다. 단순히 코드의 문제를 찾는 것보다, 이후 수정이나 유지보수에 어떤 영향을 줄지도 함께 보게 되었습니다. 실제로 이 과정을 통해 이전 프로젝트에서 발생할 수 있었던 오류를 사전에 발견하고 수정할 수 있었습니다.

하지만 모든 프로젝트에서 완벽한 잣대를 들이댈 수는 없습니다. 일정이 빠듯한 프로젝트를 지원했을 때의 일입니다. 저 역시 기능 개발을 함께 담당하고 있었기 때문에 기존 코드를 전부 정리할 현실적인 여유가 없었습니다. 이때는 우선순위를 정해 필요한 부분부터 개선했습니다.

  1. 기능에 영향을 주는 크리티컬한 문제

  2. 유지보수에 직접적인 방해가 되는 부분

  3. 공통화했을 때 이점이 확실한 부분

  4. 단순 코드 스타일 정리 (console 제거, 주석 정리 등 최소화)

일정이 급하다는 이유로 모든 문제를 무시하면 기술 부채가 되어 돌아오지만, 한 번에 완벽을 기하려다 일정을 놓치는 것도 문제입니다. 그래서 상황에 따라 우선순위를 정하고, 필요한 부분부터 개선하려고 합니다.

마무리

셀프 코드 리뷰라고 해서 거창한 아키텍처 리뷰를 할 필요는 없습니다. 특히 빠른 개발이 필요한 상황이라면 더욱 그렇습니다. 제가 생각하는 셀프 코드 리뷰는 결국 ”기능 구현이 끝난 코드를 한 번 더 의심해 보는 것”입니다.

신입 시절에는 코드 리뷰에서 지적받은 내용을 하나씩 수정하면서 배웠습니다. 지금도 그때 리뷰에서 받았던 질문들을 비슷한 상황에서 한 번씩 떠올려 보려고 합니다.

빠르게 개발해야 하는 상황이라면, 모든 부분을 완벽하게 검토하기보다 5분이라도 놓친 부분이 없는지 한 번 더 확인해보는 것부터 시작해도 좋습니다.

Code_Latte

Site footer