| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | 7 |
| 8 | 9 | 10 | 11 | 12 | 13 | 14 |
| 15 | 16 | 17 | 18 | 19 | 20 | 21 |
| 22 | 23 | 24 | 25 | 26 | 27 | 28 |
| 29 | 30 | 31 |
- 기술부채
- 양꼬치
- 포케맛집
- 한빛미디어
- 합정맛집
- 혼공컴운
- 자료구조
- 혼공네트
- 회고
- 호치민
- 합정포케
- 혼공컴운11기
- 무이네 사막투어
- 혼공학습단12기
- OS
- 호치민여행
- 베트남여행
- 핑크성당
- Redis
- 연어포케
- 밤리단길 맛집
- 혼공학습단
- Docker
- 무이네투어
- 합정 맛집
- 니코호텔
- 호치민 무이네
- cs
- 호치민 맛집
- 호치민 여행
- Today
- Total
경험은 나의 것
뒤엉킨 레거시 청산기: 빠른 개발과 유지보수, 그 사이 본문
배경
프로젝트 초반에는 늘 그렇듯, '일정 준수'가 가장 중요했습니다. 백엔드와 화면을 동시에 개발해야 했기에, 가장 빠르고 직관적인 방법을 선택했죠. 바로 하나의 Controller에서 View와 Data를 모두 처리하는 구조였습니다.
당시에는 가장 효율적인 선택이라고 생각했지만, 프로젝트 규모가 커지고 새로운 모듈을 도입하려다 보니 이 구조가 발목을 잡기 시작했습니다.
당시의 코드
@RequestMapping("/api")
class TotalController(
private final TotalService service;
) {
@GetMapping("/form")
public String form(){ return "form"; }
// DataTables 라이브러리 스펙
@GetMapping("/detail")
public ResponseEntity<ResponseDto> getDetail(@RequestParam("id") String id){
return Result.ok(service.find(id));
}
// ...여기에 저장, 수정, 조회 로직...
}
이 코드를 보며 막막함을 느꼈습니다.
- 역할의 모호함: 화면 로직과 데이터 로직이 한 클래스에 섞여 있어, 4000 line에 달하는 소스의 길이와 하나를 수정하면 다른 쪽에 영향을 줄까 겁이 났습니다.
- 확장성 부재: 프론트엔드 라이브러리에 종속된 응답 구조 때문에, 다른 서비스와의 연동이 불가능했습니다.
- 복사-붙여넣기의 유혹: 새 기능을 만들 때, 이 구조를 그대로 복사해서 이름만 바꾸면 금방 개발할 수 있다는 점이 컷습니다.
복붙이냐, 개선이냐
새로운 모듈 개발 일정이 다가왔을 때, 저에게는 두 가지 선택지가 있었습니다.
- 선택 A (복사-붙여넣기): 기존 방식을 그대로 차용한다. (개발 기간 단축, 하지만 기술 부채 누적)
- 선택 B (리팩토링 병행): 구조를 개선하며 개발한다. (초기 개발 속도 저하, 하지만 유지보수성 확보)
현실적으로는 A가 달콤했습니다. 하지만 이번만 이렇게 하고 나중에 고치자라는 말이 얼마나 지키기 어려운 약속인지 우리 모두 잘 알고 있고 경험이 있습니다. 지금 고치지 않으면, 나중엔 더 큰 비용을 치러야 한다는 확신이 들었습니다.
그래서 조금 돌아가더라도, 수정과 개발을 동시에 진행하는 길을 선택했습니다.
리팩토링 포인트 3가지
개발과 리팩토링을 병행하며 중점적으로 개선한 부분은 다음 세 가지입니다.
View와 API의 확실한 역할 분리
가장 먼저 TotalController를 두 개의 전문화된 컨트롤러로 분리했습니다.
- PageController (@Controller): 오직 화면 네비게이션과 권한 체크만 담당합니다.
- ApiController (@RestController): 순수한 데이터(JSON) 응답만 담당합니다.
이렇게 분리하고 나니, 프론트엔드 로직이 바뀌어도 API 코드를 건드릴 필요가 없어졌습니다.
특정 라이브러리 종속성 제거 (DataTables)
기존에는 프론트엔드 그리드 라이브러리인 DataTables가 요구하는 포맷(draw, recordsTotal 등)을 서버에서 직접 만들어 반환했습니다. 백엔드가 프론트엔드 구현 상세에 의존하는 구조였습니다.
이를 RESTful한 표준 응답 구조로 변경했습니다. 서버는 표준화된 데이터(content, totalElements 등)만 내려주고, 포맷팅은 프론트엔드(JS)나 어댑터 패턴을 통해 처리하도록 위임했습니다. 덕분에 이제 어떤 프론트엔드 프레임워크가 와도 대응할 수 있는 API가 되었습니다.
리소스(Resource) 중심의 URI 설계
getDetail, saveForm 같은 행위 중심의 URI를 리소스 중심으로 재정의했습니다.
- Before: GET /api/getDetail?id=1
- After: GET /api/orders/1
사소해 보일 수 있지만, URI만 보고도 어떤 자원을 다루는지 명확히 알 수 있게 되어 협업 효율이 크게 올라갔습니다.
- 리팩토링
처음 리팩토링을 병행하며 개발할 때는 솔직히 힘들었습니다. "그냥 하던 대로 하면 벌써 끝났을 텐데"라는 생각이 들 때도 있었고요.
하지만 그 효과는 두 번째, 세 번째 모듈을 개발할 때 증명되었습니다. 잘 만들어진 공통 API 구조 덕분에, 이후 개발은 '복사-붙여넣기'보다 훨씬 빠른 속도로, 그리고 훨씬 안정적으로 진행할 수 있었습니다.
기술 부채는 피할 수 없지만, 관리할 수 있다는 점을 알았습니다.
"결국은 기반이 튼튼해야 한다는 것."
'Dev' 카테고리의 다른 글
| [Spring] Redis의 세션 Store 휩쓸기 (0) | 2025.12.26 |
|---|---|
| 토스 러너스 하이 2기 (1) | 2025.12.15 |
| 윈도우와 리눅스에서 중복 폴더 일괄 제거 방법 (0) | 2024.07.15 |
| Chart.js 사용법 + DB 연동 (1) | 2024.07.14 |
| [Kubernetes] 쿠버네티스란? (1) | 2023.11.30 |