결제 정산 화면 인라인 스크립트를 외부 파일로 분리해 유지보수성 개선
목차
merchant-balance 뷰는 한동안 건드리기 꺼려지는 파일 중 하나였다. 기능은 돌아간다. 숫자도 맞는다. 근데 열어볼 때마다 스크롤을 한참 내려야 JS가 끝난다는 감각이 쌓이다 보면, 언젠가 반드시 손대야 할 순간이 온다는 걸 알게 된다. 이번에 그 순간이 왔고, 인라인 JS 1272줄을 외부 파일로 분리하고 재무요약 탭 구조를 정리했다.
인라인 스크립트가 뷰 파일 안에 같이 있으면 처음엔 편하다. 하나의 파일 열면 화면과 동작이 다 보인다. 근데 시간이 지날수록 뷰 템플릿과 JS가 서로 얽히면서 경계가 흐려진다. 변수를 PHP에서 JS로 넘기는 방식이 onclick="doSomething({{ $id }})" 같은 형태로 굳어지고, 함수가 하나 더 필요할 때마다 <script> 블록 아래에 붙여넣는 식으로 커진다.
1272줄이 된 이유도 그렇게 쌓인 거였다. 탭별 초기화 로직, 테이블 렌더링, 날짜 필터 처리, 금액 포맷팅, 그리고 중복된 유사 함수 서너 개. 한 파일이 너무 많은 걸 알고 있는 상태.
분리 자체보다 분리 기준이 핵심이다
단순히 <script> 블록을 오려내서 .js 파일로 붙여넣는 건 5분이면 된다. 문제는 그렇게 하면 뷰에서 PHP 변수를 직접 참조하던 코드들이 깨진다는 것. 인라인 스크립트에서 흔히 보이는 패턴이다.
<script>
var initialBalance = {{ $summary['balance'] }};
var merchantId = '{{ $merchant->id }}';
// ...
</script>
외부 파일로 옮기면 템플릿 엔진이 더 이상 저 자리에서 실행되지 않는다. 이 의존성을 먼저 정리해야 한다. 방법은 크게 두 가지인데, 뷰에 별도의 작은 <script> 블록을 남겨서 초기값만 전달하거나, 아니면 data-* 어트리뷰트나 API 호출로 교체하는 것이다.
이번엔 전자로 처리했다. 뷰 파일에는 초기화 데이터만 넘기는 최소한의 인라인만 남기고, 로직 전부는 외부 파일로 이동했다.
{{-- blade 뷰 --}}
<script>
window.MerchantBalance = {
merchantId: '{{ $merchant->id }}',
currency: '{{ $merchant->currency }}',
};
</script>
<script src="{{ asset('js/merchant-balance.js') }}" defer></script>
이렇게 하면 외부 JS 파일은 순수한 JS로만 구성되고, 브라우저는 파일을 캐싱할 수 있다. 같은 페이지를 다시 방문하거나 다른 페이지로 갔다가 돌아올 때 네트워크 요청 없이 캐시에서 로드된다. 1272줄짜리 파일이 매 페이지 로드마다 서버에서 렌더링되던 것과 비교하면 체감 차이가 있다.
중복 함수 통합과 변수명 정리는 분리 과정에서 자연스럽게 따라왔다. 파일을 새 컨텍스트에서 보게 되면 "이거 위에도 있던 것 같은데"가 눈에 더 잘 띈다. 의존성 로딩 순서도 defer로 통일하면서 기존에 암묵적으로 의존하던 타이밍을 명시적으로 만들었다.
금융 도메인에서 리팩토링이 까다로운 이유
결제 정산 화면은 그냥 목록 페이지가 아니다. SQL 집계 결과, 상태 머신 기반의 거래 상태, 날짜 범위 필터, 통화 포맷팅이 화면 하나에 다 엮여 있다. 어느 하나만 살짝 바꿔도 숫자가 달라질 수 있다.
리팩토링 원칙 중 "동작은 바꾸지 않는다"는 이 도메인에서 가장 위반하기 쉬운 규칙이다. 중복 함수를 합치다가 엣지 케이스 처리 방식이 미묘하게 달랐던 걸 모르고 하나로 통합해버리면, 특정 조건에서만 틀린 숫자가 나온다. 그게 정산 금액이면 신뢰 문제가 된다.
그래서 이번에 지킨 것들:
- 리팩토링 전 주요 케이스 수치를 메모해두고, 작업 후 같은 조건으로 cross-check
- 한 번에 큰 변경 대신 논리 단위별로 커밋을 쪼갬 - 어디서 숫자가 달라졌는지 추적하기 위해
- 의심스러운 중복 함수는 통합 대신 일단 공존시키고, 동작 확인 후 정리
작은 커밋이 귀찮아 보일 때도 있지만, 문제가 생겼을 때 git bisect 한 번으로 어느 커밋이 원인인지 좁혀지는 경험을 몇 번 하면 생각이 바뀐다.
변경 범위를 의도적으로 제한한 이유
리팩토링을 시작하면 "이 부분도 고치면 좋겠다", "이 구조도 개선하면 어떨까"라는 생각이 계속 붙는다. 충동을 따라가면 범위가 커지고, PR이 커지고, 리뷰하기 어려워지고, 무엇이 바뀌었는지 추적하기 어려워진다.
이번엔 변경 파일을 뷰/스타일 1개, 스크립트 1개로 제한했다. 건드리고 싶은 부분이 없었던 게 아니라, 그 부분은 다음 작업으로 분리하기 위해 의도적으로 두었다. "지금 범위에서 벗어나는 건 TODO 코멘트로 남기고 별도 이슈로"가 이런 작업의 합리적인 선이다.
커밋 메시지에도 "무엇을 바꿨다"보다 "왜 바꿨는지"를 담으려고 했다. 외부 JS 분리로 브라우저 캐시 활용 및 뷰-스크립트 책임 분리처럼. 3개월 후에 git log를 봤을 때 그 시점의 판단을 이해할 수 있어야 한다.
기능이 잘 돌아가는 코드를 건드리는 건 항상 약간의 긴장감이 있다. 근데 그 긴장감을 미루면 나중에 더 큰 긴장감이 된다. 1272줄짜리 인라인 스크립트가 그 예다. 지금 정리해둔 구조 덕분에 다음 기능 추가나 버그 수정 때 훨씬 좁은 범위만 열어보면 된다.
댓글 0
첫 댓글 달아줘.