최근 이펙티브 자바, 그리고 Sonarqube를 이용한 코드 품질 분석에 대해 공부하며
제 예전 코드를 리팩토링 하고 있습니다. 예전 코드를 이런 공개된 공간에 올린다는게 부끄럽지만 그 과정을 게시글에 담아보려고 합니다.
첫 백엔드 프로젝트에서 저는 지금 보면 부끄러운 코드를 작성했습니다. 🙈
아래 코드는 그 당시 Controller가 거의 모든 책임을 떠안고 있던 코드입니다.
@GetMapping
public ResponseEntity<?> getAuctions(
@RequestParam(value = "gender", required = false) Gender gender,
@RequestParam(value = "size", required = false) String size,
@RequestParam(value = "price", required = false) String price,
@RequestParam(value = "progress", required = false) AuctionProgress progress,
@RequestParam(value = "page", defaultValue = "0") int page
) {
// 파라미터 직접 파싱
...
return auctionService.getFilteredAuctions(...);
}
컨트롤러는 단지 요청을 받고, 적절한 서비스 메서드를 호출하는 역할을 해야 합니다. 그러나
- 요청 파라미터 직접 파싱
- 예외 처리
- 로깅 및 조건 분기
등의 책임을 모두 컨트롤러에 몰아넣었습니다. 이는 응집도가 낮고, 확장성과 유지보수가 어려운 코드라는 것을 금방 깨닫게 되었습니다.
@GetMapping
public ApiResponse<AuctionFilterResultDto> getAuctions(@ModelAttribute @Valid AuctionQueryParamsDto filter) {
return ApiResponse.success(HttpStatus.OK, auctionService.getFilteredAuctions(filter), "경매 조회에 성공했습니다.");
}
🔨 개선한 주요 내용
1. Controller의 책임 분리
- 파라미터 파싱, 유효성 검증, 예외 처리를 DTO와 글로벌 예외 처리 로직으로 위임
- 컨트롤러는 오직 요청 수신 → 서비스 호출 → 응답 반환이라는 흐름만 담당
2. 표준 응답 포맷 적용
- 커스텀 ApiResponse 객체를 활용해 응답 형식 일관성 유지
- 코드 가독성 향상
3. @ModelAttribute로 파라미터 바인딩
- @RequestParam을 줄줄이 나열하던 방식 대신, 필터 조건을 하나의 DTO로 캡슐화
- 유지보수성과 테스트 용이성 대폭 향상
4. @Valid를 통한 입력값 검증
- 컨트롤러에서 직접 검증하던 로직을 DTO에 정의된 유효성 어노테이션으로 위임
- 코드 중복 최소화 및 관심사 분리
마무리하며
컨트롤러는 경량화된 중간 관리자여야 합니다.
핵심 로직은 서비스에, 검증은 DTO에, 예외 처리는 전역 핸들러에 맡기는 것이 건강한 구조입니다.
728x90