개발 slecs

허브 페이지 백엔드 로직 공통화

목차

허브 페이지 백엔드 로직을 정리했다. 백엔드 파일 4개 건드린 게 전부였는데, 작업 시간은 생각보다 길었다.

이유가 있다. 허브 페이지는 여러 서브 도메인의 데이터를 모아서 보여주는 구조라 백엔드 처리 경로가 여러 갈래였다. 오래된 코드였고, 기능이 추가될 때마다 비슷한 로직이 각자의 방식으로 조금씩 다르게 복사돼 있었다. 처음엔 작은 차이처럼 보이는데 막상 버그가 생기면 한 곳만 고치고 나머지를 빠뜨리는 게 반복된다. 이번 작업의 출발점은 거기서였다.

공통화 전에 먼저 한 것

코드 공통화를 바로 시작하면 안 된다. 일단 흩어진 로직들이 정말 동일한 의도를 가지고 있는지 확인해야 한다. 비슷해 보이지만 의도가 다른 코드를 억지로 묶으면 나중에 분리하는 게 훨씬 힘들다.

각 처리 경로를 따라가면서 입력값 범위, 예외 처리 흐름, 리턴 타입을 하나씩 비교했다. 그 과정에서 엣지 케이스 처리가 누락된 경로가 있었다. null 체크를 건너뛰는 곳, 에러를 로그도 안 찍고 삼켜버리는 곳. 이 부분은 공통화 전에 먼저 보강했다. 공통 메서드로 합친 다음에 엣지 케이스를 수정하면 어디서 어떻게 바뀐 건지 추적하기가 복잡해진다.

변경 범위를 정리하면 이렇다.

레이어 파일 수 주요 변경
백엔드 로직 4개 중복 처리 로직 추출, 엣지 케이스 보강, 에러 메시지 통일
화면 (JSP) 0개 -
쿼리 (XML) 0개 -
스타일 0개 -

JSP나 쿼리는 안 건드렸다. 이번 커밋 범위를 백엔드 로직으로만 제한한 게 의도적인 선택이었다. 화면이나 SQL까지 섞이면 리뷰 시 변경 의도가 흐려진다.

공통화 작업에서 지킨 것들

중복 제거 자체보다 어떤 방식으로 공통화하느냐가 더 중요하다. 잘못된 추상화는 중복보다 나쁘다. 로직을 하나로 묶었을 때 각 호출 측에서 플래그를 넘겨서 내부에서 분기하는 구조가 되면 그건 공통화가 아니라 복잡성을 숨긴 것에 가깝다.

이번엔 호출 측마다 다른 동작이 필요한 부분은 과감히 공통화 대상에서 제외했다. 추출한 공통 메서드는 단순하게 유지했다.

// Before: 각 서비스마다 같은 전처리가 흩어져 있던 상태
private SomeResult processA(Input input) {
    if (input == null) return null;
    String normalized = input.getValue().trim().toLowerCase();
    // ... 처리 로직
}

private SomeResult processB(Input input) {
    if (input == null) return null;
    String normalized = input.getValue().trim().toLowerCase();
    // ... 약간 다른 처리 로직
}

// After: 전처리만 추출, 이후 처리는 각자 유지
private String normalize(Input input) {
    if (input == null || input.getValue() == null) return "";
    return input.getValue().trim().toLowerCase();
}

에러 메시지도 정리했다. 같은 종류의 실패가 서비스마다 다른 메시지를 내고 있었다. 로그를 모아서 분석할 때 패턴을 잡기 어려운 구조였다. 메시지 포맷을 통일하고 컨텍스트 정보(어떤 파라미터로 들어왔는지)를 함께 찍도록 바꿨다.

로그 메시지 하나 제대로 못 찍은 코드 때문에 장애 대응 시간이 길어지는 걸 경험하고 나면 이게 사소한 작업이라는 생각이 없어진다.

운영 중인 코드를 건드릴 때의 기준

배포된 서비스에서 동작하는 코드를 리팩터링할 때 지키는 기준이 있다.

  • 변경 전 현재 동작을 정확히 파악하고 시작한다. 테스트가 없으면 직접 케이스를 만들어서라도 현재 동작을 기록해둔다.
  • 한 커밋에 리팩터링과 기능 변경을 섞지 않는다. 롤백할 때 분리가 안 되면 선택지가 없어진다.
  • 배포 후 일정 시간은 주요 에러 지표를 눈으로 확인한다. 자동화된 모니터링을 믿되 처음 배포 후에는 직접 보는 게 맞다.
좋은 코드의 기준 나쁜 코드의 신호
읽으면 의도가 바로 보임 주석 없으면 이해 불가
변경이 한 곳에만 영향 한 곳 바꾸면 여러 곳 수정 필요
테스트 작성이 자연스러움 테스트하려면 구조 바꿔야 함
에러가 어디서 왔는지 로그로 파악됨 스택 트레이스 없이는 원인 불명

코드를 쓸 때 항상 세 가지 시점을 기준으로 생각한다. 6개월 뒤의 나, 이 코드를 처음 보는 다른 개발자, 새벽에 장애 대응 중인 사람. 그 세 사람이 이 코드를 보고 빠르게 상황을 파악할 수 있는가.

이번 작업은 기능 추가가 아니어서 PR 설명이 짧아 보일 수 있다. 하지만 이런 작업이 쌓이지 않으면 새로운 기능을 안전하게 얹을 수 있는 토대가 없다. 지금 당장 눈에 보이는 결과물은 없어도, 다음 기능 작업할 때 이번에 정리된 코드 위에서 시작하는 게 체감상 다르다.

댓글 0

첫 댓글 달아줘.