결제 모니터 뷰 레이어 알림 중복 제거
목차
pay-monitor에서 오래 묵혀둔 알림 중복 문제를 드디어 정리했다. 커밋 하나치고 건드린 파일이 6개였는데, 막상 뚜껑 열어보니 왜 이게 이렇게 됐는지 이해가 가서 오히려 속이 시원했던 작업이다.
왜 알림 코드가 이렇게 흩어지나
JSP 뷰가 많은 레거시 프로젝트에서 흔히 생기는 현상이다. 처음엔 alert('에러가 발생했습니다') 한 줄짜리로 시작한다. 그다음엔 외부 Toast 라이브러리가 붙으면서 toastr.error() 계열이 섞이고, 나중에 사내 디자인 가이드가 생기면 공통 컴포넌트인 SLECS.Modal.alert()가 추가된다. 기능은 동일한데 구현체가 세 가지가 되는 것이다.
문제는 이게 서서히 진행되다 보니 어느 순간까지는 아무도 "정리해야 한다"는 인식을 못 한다는 거다. 파일마다 알림 스타일이 달라서 사용자 경험이 들쭉날쭉하고, 나중에 알림 문구나 공통 동작을 바꾸려면 패턴을 전부 찾아서 각각 수정해야 한다. 결제 모니터처럼 금융 도메인이 얽혀있는 화면이라면 "이 부분은 잘못 건드리면 큰일 나니까 그냥 두자"는 관성이 더 강하게 작동한다. 그 관성이 쌓이면 파일 하나를 고치려다 여섯 개를 봐야 하는 상황이 된다.
이번에 정리 대상이 된 건 총 6개 파일 - MyBatis SQL 매퍼 설정 하나, 뷰 템플릿(JSP) 다섯이었다.
| 레이어 | 파일 | 주요 변경 |
|---|---|---|
| 퍼시스턴스 | MyBatis 매퍼 / 설정 | 미사용 resultMap, 불명확한 alias 정리 |
| 뷰 | 상품-공급.jsp | Toast → SLECS.Modal.alert 교체 |
| 뷰 | 내부 JSP 3종 | 중복 스크립트 블록 제거, 공통 함수로 위임 |
| 뷰 | kyc 내부 JSP | 인라인 알림 로직 → 공통 패턴으로 통합 |
무엇을 어떻게 바꿨나
핵심 작업은 SLECS.Modal.alert로의 단일화였다. 기존에 혼재하던 패턴은 대략 이렇다:
// 패턴 1 - 네이티브 브라우저 alert (블로킹)
alert('조회 결과가 없습니다.');
// 패턴 2 - Toastr 외부 라이브러리
toastr.warning('저장에 실패했습니다.');
toastr.success('처리가 완료되었습니다.');
// 패턴 3 - 사내 공통 컴포넌트 (일부 파일에만 도입된 상태)
SLECS.Modal.alert({ type: 'error', message: '오류가 발생했습니다.' });
셋 다 알림을 띄우는 건 같지만 스타일은 제각각이었다. 특히 네이티브 alert()는 브라우저가 블로킹 다이얼로그를 띄우기 때문에, 뒤에 오는 콜백 로직과의 타이밍이 모달 방식과 미묘하게 다르다. 모달로 교체하면서 이 타이밍을 확인하는 게 이번 작업에서 가장 신경 쓴 부분이다.
메서드 분리도 함께 진행했다. Submit 핸들러가 유효성 검사, 알림 처리, Ajax 요청을 한 함수 안에 전부 담고 있는 경우가 많았는데, 이를 책임 단위로 쪼갰다.
// 변경 전 - 하나의 긴 핸들러
function onSubmit() {
// 유효성 검사 ~15줄
// 조건별 알림 분기 ~10줄
// Ajax 요청 + 성공/실패 콜백 ~25줄
}
// 변경 후 - 책임 분리
function validatePaymentForm() { /* 검사 로직만 */ }
function notifyUser(type, msg) {
SLECS.Modal.alert({ type: type, message: msg });
}
function requestPayment(params) { /* Ajax + 콜백만 */ }
function onSubmit() {
if (!validatePaymentForm()) return;
requestPayment(buildParams());
}
이렇게 나눠두면 다음에 유효성 규칙 하나를 추가할 때 Ajax 콜백 코드를 읽을 필요가 없다. 반대로 알림 문구를 바꿀 때도 notifyUser만 보면 된다. 당장은 "분리만 했다"는 느낌이 크지만, 이런 구조가 쌓여야 나중에 기능 추가가 덜 무서워진다.
네이밍도 손봤다. 결제 관련 JSP에서 tmp, flag, chk처럼 의미가 불분명한 변수가 꽤 남아있었다. 맥락을 보고 isSubmitting, selectedPaymentType, hasValidationError 식으로 바꿨다. 짧아도 의미 있는 이름이 훨씬 낫다.
금융 로직 주변에서 리팩토링을 다루는 방식
"기능 변경 없는 리팩토링"이라도 결제 흐름 근처는 다르게 다룬다. 알림 타이밍이 달라지면 사용자 입장에서 "결제가 된 건지 안 된 건지" 불확실한 상태가 만들어질 수 있기 때문이다. 네이티브 alert()에서 SLECS.Modal.alert()로 교체할 때는 UI 블로킹 방식이 달라지기 때문에, 콜백 순서가 의도한 대로 유지되는지를 직접 눌러보면서 확인했다.
확인한 시나리오:
- 정상 결제 완료 후 모달 노출 → 확인 클릭 후 목록 갱신 순서가 유지되는지
- 서버 오류 응답 시 알림이 뜨고 폼 상태가 유지되는지 (재시도 가능 상태)
- 중복 클릭 방지 로직이 모달이 열린 상태에서도 제대로 작동하는지
- KYC 화면에서 상태 변경 알림이 누락 없이 노출되는지
회귀는 없었다. 다만 이런 검증을 매번 수동으로 하는 건 한계가 있어서, 공통 알림 함수 쪽에 자동화 테스트 케이스가 있었다면 훨씬 편했을 것 같다는 생각이 남았다. 리팩토링이 잦은 레이어는 테스트 커버리지가 받쳐줘야 "괜히 손 댔다가 망하면"이라는 심리적 허들이 낮아진다.
MyBatis 매퍼 쪽은 상대적으로 단순했다. 어느 시점에 사용하지 않게 된 resultMap 정의가 파일 안에 남아있었고, 의미를 파악하기 어려운 파라미터 alias 몇 개를 실제 컬럼 의미에 맞게 수정했다. SQL 로직 자체는 건드리지 않았다. 매퍼 정리는 심리적으로 가장 부담이 없는 작업이었는데, 쿼리 결과가 달라지지 않는 한 영향 범위가 명확하기 때문이다.
작업이 끝나고 같은 도메인 파일을 다시 열어봤는데, 읽는 속도가 체감상 달라졌다. 이 종류의 리팩토링은 당장 눈에 보이는 산출물이 없어서 미루기 쉽다. 하지만 효과는 다음 기능 추가나 버그 대응 때 드러난다. 코드를 파악하는 데 걸리는 시간이 짧아지면 실제 문제에 더 빨리 집중할 수 있고, 유사한 패턴의 화면을 만들 때 참고할 수 있는 예시가 생긴다. 쌓이면 쌓일수록 이후 작업의 바닥이 달라진다.
댓글 0
첫 댓글 달아줘.