사용자 정보·위젯 관리 코드 품질 개선
목차
사용자 정보와 위젯 관련 코드를 훑으면서 품질을 끌어올리는 작업을 했다. 기능 추가가 아니라 기존 코드를 다듬는 작업이라 커밋 메시지에 뭘 써야 하나 잠깐 고민하기도 했는데, 막상 해보니 생각보다 손댈 게 많았음.
왜 이런 작업이 계속 필요한가
서비스를 운영하다 보면 기능 개발 속도에 밀려서 코드 품질 문제가 조금씩 쌓인다. 특히 여러 개발자가 오가면서 작업한 코드일수록 각자의 스타일이 섞여 있고, 비슷한 로직이 여러 곳에 흩어져 있는 경우가 많음. 이번 작업도 그런 맥락이었다.
변경 범위가 백엔드 로직부터 JSP 화면, XML 쿼리, CSS까지 여러 레이어에 걸쳐 있었는데, 레이어마다 문제의 양상이 조금씩 달랐다:
- 백엔드: 유사한 처리 로직이 서비스 메서드별로 제각각 구현돼 있음
- JSP: 같은 UI 패턴인데 각 페이지가 다른 방식으로 구현
- XML 쿼리: 조건 처리 방식이 일관되지 않아서 읽기 어렵고 실수 여지가 있음
- CSS: 안 쓰는 클래스가 남아 있거나 인라인 스타일이 산발적으로 섞임
어느 것 하나 당장 장애를 만들 건 아니지만, 이런 게 쌓이면 나중에 수정할 때 영향 범위 파악에 시간이 배로 걸린다.
실제로 어떻게 접근했나
운영 중인 서비스 코드를 건드릴 때 가장 조심해야 하는 건 기존 동작을 깨는 것이다. 기능 개선이 아니라 정리 작업일수록 오히려 더 조심스럽다. "원래 잘 되던 게 왜 갑자기 안 되냐"는 상황이 제일 당황스러우니까.
내가 쓰는 접근법은 대략 이렇다:
- 변경 전에 현재 동작을 직접 눈으로 확인 - 어떤 케이스에서 어떻게 동작하는지
- 변경 단위를 가능한 작게 - 한 커밋에 너무 많이 담으면 리뷰도 어렵고 롤백 단위도 커짐
- 엣지 케이스 먼저 처리 - null 체크, 빈 값 처리, 예외 흐름이 명확해야 happy path도 믿을 수 있음
- 배포 후 로그/모니터링 확인 - 정리 작업이라도 사이드 이펙트가 있을 수 있음
중복 코드를 공통화할 때 자주 실수하는 지점이 있는데, "비슷해 보이는" 코드를 섣불리 묶는 거다. 지금 당장은 동일해 보여도 사실은 다른 맥락이어서, 나중에 분기가 생기면 공통 함수가 오히려 더 복잡해지는 경우가 있음. 아래 같은 상황이 전형적인 예다:
// 억지로 합친 케이스 - isAdmin 플래그로 내부 분기가 점점 늘어남
private UserInfo buildUserInfo(Map<String, Object> data, boolean isAdmin) {
UserInfo info = new UserInfo();
info.setId((String) data.get("userId"));
if (isAdmin) {
info.setRole("ADMIN");
info.setPermissions(parseAdminPermissions(data));
} else {
info.setRole("USER");
// 다른 파싱 로직...
}
return info;
}
// 더 나은 접근 - 진짜 공통 부분만 추출하고 나머지는 분리
private UserInfo buildBaseUserInfo(Map<String, Object> data) {
UserInfo info = new UserInfo();
info.setId((String) data.get("userId"));
return info;
}
"지금 이걸 묶는 게 맞나?" 를 한 번 더 생각하는 습관이 필요하다는 걸 이번에도 다시 느꼈음.
에러 메시지 개선도 이번에 신경 쓴 부분이다. 에러 로그가 "처리 중 오류 발생" 수준으로만 남아 있으면 장애 대응할 때 아무 도움이 안 된다. 어떤 사용자 요청이었는지, 어떤 데이터가 문제였는지가 로그에 찍혀야 새벽에 호출받았을 때 상황 파악이 빨라짐.
// 개선 전 - 아무것도 모르는 채로 로그 뒤져야 함
log.error("사용자 정보 처리 실패");
// 개선 후 - 로그만 봐도 어디서 뭐가 터졌는지 바로 보임
log.error("사용자 정보 처리 실패. userId={}, widgetType={}, errorMsg={}",
userId, widgetType, e.getMessage());
이런 변경 하나가 나중에 대응 시간을 10분씩 아껴준다. 여러 번 경험하고 나서야 에러 메시지를 얼마나 공들여 써야 하는지 실감했음.
이런 작업이 쌓이면
당장 눈에 보이는 성과가 없어서 우선순위를 밀리기 쉬운 작업이다. 기획자한테 설명하기도 애매하고, 배포 공지에 딱히 쓸 내용도 없음. 그런데 이런 작업들이 수개월치 쌓이면 느껴지는 차이가 있다. 새 기능 추가할 때 건드려야 하는 범위가 줄어들고, 버그 잡을 때 어디를 봐야 하는지 빠르게 좁혀진다. 무엇보다 코드를 읽을 때 "이게 왜 이렇게 돼 있지?" 하는 순간이 줄어든다.
코드를 쓸 때 항상 세 가지 관점을 같이 둔다:
| 관점 | 질문 |
|---|---|
| 미래의 나 | 6개월 후에 다시 봤을 때 맥락 설명 없이 이해되는가 |
| 다음 개발자 | 이 코드를 처음 보는 사람이 의도를 파악할 수 있는가 |
| 운영 상황 | 새벽에 장애 나면 원인을 몇 분 안에 찾을 수 있는가 |
세 번째가 제일 냉정한 기준이다. 평소에 잘 돌아갈 때는 모든 코드가 괜찮아 보이거든. 장애 상황에서 압박받으면서 로그 뒤질 때 코드 품질이 진짜로 드러남.
| 좋은 코드 | 나쁜 코드 신호 |
|---|---|
| 읽으면 의도가 바로 보임 | 주석 없으면 이해 불가 |
| 변경이 한 곳에만 영향 | 한 곳 바꾸면 여러 곳 수정 필요 |
| 테스트 작성이 자연스러움 | 테스트하려면 구조부터 바꿔야 함 |
| 함수/클래스명이 역할을 설명함 | 이름이 구현 방식을 설명함 |
단일 책임 원칙이나 명시적 코드 같은 건 익숙한 얘기지만, 막상 시간 압박 받으면서 구현하다 보면 놓치기 쉽다. 이런 정리 작업을 주기적으로 하는 게 그 기술 부채를 갚는 시간인 셈이다. 티가 안 나는 작업이지만, 이게 쌓여야 나중에 디버깅 시간이 줄어들고 팀 전체의 속도가 유지된다는 걸 총괄 입장에서 더 체감하게 되는 것 같음.
댓글 0
첫 댓글 달아줘.