
코드 리뷰는 소프트웨어 품질을 보장하는 핵심 프로세스다. 체계적인 체크리스트를 사용하면 중요한 이슈를 놓치지 않고 일관된 리뷰를 수행할 수 있다. 이 글은 실무에서 바로 사용할 수 있는 코드 리뷰 체크리스트를 제공한다.
1. 기능성 체크리스트
요구사항 충족
- 요구사항을 정확히 구현했는가?
- 엣지 케이스를 처리했는가?
- 에러 케이스를 적절히 처리했는가?
- 입력 검증이 충분한가?
- 출력 형식이 요구사항과 일치하는가?
로직 정확성
- 비즈니스 로직이 올바른가?
- 알고리즘이 효율적인가?
- 조건문이 모든 경우를 커버하는가?
- 반복문이 무한 루프에 빠지지 않는가?
- 예외 처리가 적절한가?
테스트
- 단위 테스트가 작성되었는가?
- 테스트 커버리지가 충분한가?
- 엣지 케이스 테스트가 있는가?
- 테스트가 실제로 통과하는가?
- 통합 테스트가 필요한가?
2. 코드 품질 체크리스트
가독성
- 변수명이 명확하고 의미 있는가?
- 함수명이 기능을 잘 설명하는가?
- 주석이 필요한가? (너무 많거나 적지 않은가?)
- 코드 구조가 명확한가?
- 매직 넘버가 상수로 정의되었는가?
나쁜 예시
function calc(a, b, c) {
return a * 1.1 + b * 0.9 - c * 0.05;
}좋은 예시
const TAX_RATE = 1.1;
const DISCOUNT_RATE = 0.9;
const SERVICE_FEE_RATE = 0.05;
function calculateTotalPrice(basePrice, discount, serviceFee) {
return basePrice * TAX_RATE + discount * DISCOUNT_RATE - serviceFee * SERVICE_FEE_RATE;
}복잡도
- 함수가 너무 길지 않은가? (일반적으로 50줄 이하)
- 순환 복잡도가 적절한가? (10 이하 권장)
- 중첩이 너무 깊지 않은가? (3-4단계 이하)
- 단일 책임 원칙을 따르는가?
중복 코드
- 중복된 코드가 있는가?
- 공통 함수로 추출할 수 있는가?
- 유사한 패턴이 반복되는가?
3. 성능 체크리스트
알고리즘 효율성
- 시간 복잡도가 적절한가?
- 불필요한 반복이 있는가?
- 캐싱을 활용할 수 있는가?
- 데이터베이스 쿼리가 최적화되었는가?
리소스 사용
- 메모리 누수가 없는가?
- 파일/스트림이 제대로 닫히는가?
- 연결 풀링을 사용하는가?
- 불필요한 리소스 로딩이 없는가?
데이터베이스
- N+1 쿼리 문제가 없는가?
- 인덱스가 적절히 사용되는가?
- 대량 데이터 처리가 효율적인가?
- 트랜잭션이 적절히 사용되는가?
N+1 쿼리 문제 예시
나쁜 예시
// N+1 쿼리 문제
const users = await getUsers();
for (const user of users) {
user.profile = await getProfile(user.id); // 각 사용자마다 쿼리 실행
}좋은 예시
// JOIN 또는 배치 쿼리 사용
const users = await getUsersWithProfiles(); // 한 번의 쿼리4. 보안 체크리스트
입력 검증
- 사용자 입력을 검증하는가?
- SQL 인젝션을 방지하는가?
- XSS 공격을 방지하는가?
- CSRF 보호가 있는가?
인증 및 권한
- 인증이 제대로 구현되었는가?
- 권한 검사가 충분한가?
- 세션 관리가 안전한가?
- 토큰이 안전하게 저장되는가?
민감한 정보
- 비밀번호가 평문으로 저장되지 않는가?
- API 키가 하드코딩되지 않는가?
- 로그에 민감한 정보가 포함되지 않는가?
- 환경 변수를 사용하는가?
나쁜 예시
const apiKey = "sk_live_1234567890"; // 하드코딩좋은 예시
const apiKey = process.env.API_KEY; // 환경 변수 사용의존성
- 사용 중인 라이브러리에 알려진 취약점이 없는가?
- 의존성이 최신 버전인가?
- 불필요한 의존성이 없는가?
5. 아키텍처 및 설계 체크리스트
설계 원칙
- SOLID 원칙을 따르는가?
- DRY (Don’t Repeat Yourself) 원칙을 따르는가?
- KISS (Keep It Simple, Stupid) 원칙을 따르는가?
- 관심사의 분리가 잘 되어 있는가?
의존성
- 모듈 간 결합도가 낮은가?
- 의존성 주입이 적절히 사용되는가?
- 순환 의존성이 없는가?
확장성
- 새로운 기능 추가가 쉬운가?
- 변경에 유연한가?
- 확장 가능한 구조인가?
6. 프론트엔드 특화 체크리스트
접근성
- 시맨틱 HTML을 사용하는가?
- ARIA 속성이 적절히 사용되는가?
- 키보드 네비게이션이 가능한가?
- 색상 대비가 충분한가?
성능
- 이미지가 최적화되었는가?
- 번들 크기가 적절한가?
- 불필요한 리렌더링이 없는가?
- 코드 스플리팅이 적용되었는가?
사용자 경험
- 로딩 상태를 표시하는가?
- 에러 메시지가 사용자 친화적인가?
- 반응형 디자인이 적용되었는가?
- 모바일에서 잘 작동하는가?
7. 백엔드 특화 체크리스트
API 설계
- RESTful 원칙을 따르는가?
- 적절한 HTTP 메서드를 사용하는가?
- 상태 코드가 올바른가?
- API 버전 관리가 되어 있는가?
에러 처리
- 일관된 에러 응답 형식을 사용하는가?
- 적절한 에러 로깅이 있는가?
- 사용자에게 노출되는 에러 메시지가 적절한가?
로깅
- 적절한 로그 레벨을 사용하는가?
- 로그에 충분한 컨텍스트가 있는가?
- 민감한 정보가 로그에 포함되지 않는가?
8. 코드 리뷰 프로세스
리뷰 전 체크
- 로컬에서 테스트했는가?
- 린터/포매터를 실행했는가?
- 테스트가 모두 통과하는가?
- 문서를 업데이트했는가?
리뷰 작성 시
- 구체적이고 명확한 피드백을 제공하는가?
- 개선 방안을 제시하는가?
- 긍정적인 피드백도 포함하는가?
- 우선순위를 명시하는가?
리뷰 후
- 피드백에 대해 논의했는가?
- 개선 사항을 적용했는가?
- 재리뷰가 필요한가?
9. 자동화 도구
정적 분석
- ESLint / TSLint 설정
- Prettier 포맷팅
- SonarQube 코드 품질 분석
테스트
- 자동화된 단위 테스트
- 통합 테스트
- E2E 테스트
보안
- Snyk 취약점 스캔
- OWASP Dependency Check
- npm audit
FAQ
Q: 모든 체크리스트를 매번 확인해야 하나요?
A: 프로젝트와 변경 사항의 중요도에 따라 우선순위를 정해 집중적으로 리뷰한다. 자동화 도구로 처리할 수 있는 항목은 CI/CD에 통합한다.
Q: 코드 리뷰에 얼마나 시간을 할애해야 하나요?
A: 변경 사항의 복잡도에 따라 다르지만, 일반적으로 30분-2시간 정도가 적절하다. 작은 변경은 빠르게, 큰 변경은 더 자세히 리뷰한다.
Q: 리뷰어가 여러 명인 경우 어떻게 하나요?
A: 각 리뷰어가 다른 관점에서 리뷰하도록 역할을 분담한다. 예를 들어, 한 명은 기능성, 다른 한 명은 보안에 집중한다.
Q: 모든 피드백을 반영해야 하나요?
A: 필수적인 이슈는 반드시 반영하고, 스타일이나 선호도 문제는 팀과 논의하여 결정한다. 리뷰어와 작성자가 대화를 통해 합의하는 것이 중요하다.
Q: 자동화 도구로 대체할 수 있나요?
A: 일부 항목(포맷팅, 린팅, 보안 스캔)은 자동화할 수 있지만, 비즈니스 로직, 설계, 사용자 경험 등은 사람이 리뷰해야 한다.
Q: 코드 리뷰가 너무 오래 걸리는 경우?
A: 큰 변경은 작은 단위로 나누어 PR을 분리한다. 점진적 리뷰가 더 효과적이다. 또한 리뷰 시간을 제한하고, 자동화 도구를 활용해 반복적인 작업을 줄인다.
코드 리뷰 역량을 프로젝트에 활용
체계적인 코드 리뷰 프로세스를 구축했다면, 다양한 프로젝트에서 그 경험을 활용해보자. 블루버튼 같은 플랫폼에서 코드 품질 개선, 레거시 코드 리팩토링, 팀 코드 리뷰 프로세스 구축 등이 필요한 프로젝트를 찾을 수 있다. 특히 대규모 프로젝트, 오픈소스 기여, 팀 협업이 중요한 프로젝트에서 이 글의 체크리스트를 바로 적용할 수 있다.