개발 slecs

결제 바코드 이용안내를 링크+상세패널 구조로 개선

목차

relay-pay 바코드 화면 작업을 했다. 바코드 하단에 붙어 있던 이용안내 인라인 블록을 링크+상세패널 구조로 바꾸는 리팩토링이다. 변경 파일은 뷰/스타일 합쳐서 딱 1개.

기능은 원래 잘 돌아가고 있었다. 그래서 "굳이 손대야 하나"라는 생각이 잠깐 들기도 했는데, 실제로 코드를 열어 보면 이야기가 달라진다.

인라인 블록에서 링크+패널로 - 왜 바꿨나

기존 구조는 이용안내 내용이 바코드 아래에 고정으로 펼쳐져 있었다. 처음 보는 사람한테는 정보가 거기 있다는 걸 알 수 있어서 나쁘지 않다. 문제는 이용안내를 읽을 필요가 없는 사람에게도 무조건 노출된다는 거다. 결제 바코드를 쓰는 사람은 대부분 흐름을 이미 알고 있고, 안내 텍스트 몇 줄이 스크롤을 잡아먹고 있으면 핵심 UI인 바코드 자체가 묻힌다.

링크+상세패널 구조는 이른바 점진적 공개(progressive disclosure) 패턴이다. 기본 상태에서는 "이용안내 보기" 같은 링크만 보이고, 필요한 사람이 탭하거나 클릭하면 패널이 열리는 방식. 화면이 간결해지고, 안내가 필요한 순간에만 나타나니 오히려 읽힐 가능성도 높아진다.

UI 변경이라는 면에서는 작은 변화지만, 뷰 파일 내부에서는 꽤 정리가 됐다.

<!-- before: 항상 펼쳐진 인라인 블록 -->
<div class="barcode-notice">
  <ul>
    <li>바코드는 1회용입니다.</li>
    <li>유효시간이 지나면 재발급이 필요합니다.</li>
    <!-- ... -->
  </ul>
</div>

<!-- after: 링크 + 토글 패널 -->
<a class="notice-toggle" data-target="barcode-notice-panel">이용안내</a>
<div id="barcode-notice-panel" class="notice-panel" hidden>
  <ul>
    <li>바코드는 1회용입니다.</li>
    <li>유효시간이 지나면 재발급이 필요합니다.</li>
    <!-- ... -->
  </ul>
</div>

눈에 띄는 변화는 hidden 속성 하나지만, 이게 상태 관리 책임이 CSS/HTML 쪽으로 내려온다는 의미다. JS는 토글만 담당하면 되고, 뷰 로직이 더 단순해진다.

이번 리팩토링에서 실제로 바꾼 것들

  • 인라인 JS를 외부 파일로 분리해 브라우저 캐시를 활용하게 했다. 인라인 스크립트는 매 요청마다 HTML 안에서 파싱되는데, 외부 파일로 빼면 첫 방문 이후 캐시에서 읽는다. 바코드 화면 특성상 짧은 시간 안에 같은 사용자가 여러 번 들어올 수 있어서 효과가 있다.
  • 중복 함수 통합. 패널 열기/닫기 처리가 두 군데 흩어져 있었다.
  • 변수명 명확화. el, t, v 같은 단타 변수들을 의미 있는 이름으로.
  • 의존성 로딩 순서 정리. 스크립트 실행 시점이 DOM 준비 전이라 간헐적으로 null 참조가 날 수 있는 구조였음.

이 중에서 의존성 로딩 순서는 "당장 터지는 버그"는 아닌데, 조건이 맞으면 터진다. 특정 브라우저나 느린 디바이스에서 먼저 맞닥뜨리는 류의 문제다. 눈에 안 보인다고 그냥 두면 결국 사용자가 먼저 발견한다.

리팩토링할 때 내가 신경 쓰는 원칙은 몇 가지 있다.

원칙 핵심
동작 불변 리팩토링 전후 결과가 동일해야 한다
단일 책임(SRP) 파일/함수 하나가 하나의 일만
DRY 같은 코드가 두 곳에 있으면 하나가 버그 수정에서 빠진다
최소 변경 필요한 범위만 건드린다, 범위를 늘리지 않는다

"동작 불변"이 제일 중요하다. 리팩토링이라고 해서 동작이 달라지면 그건 기능 변경이고, 리뷰도 더 꼼꼼하게 받아야 한다. 이 둘을 같은 커밋에 섞지 않는 게 좋다.

금융 도메인 작업에서 꼼꼼함이 기본값인 이유

결제 바코드는 숫자 하나, 상태 하나가 틀리면 바로 체감된다. 금액이 안 맞거나, 유효한 바코드가 만료됐다고 뜨거나, 재발급이 안 되거나. 사내 서비스라도 금융 흐름을 다루면 "대충 맞는 것 같다"로 넘기면 반드시 다시 돌아온다. 이번 작업은 UI 구조 변경이라 숫자 로직엔 손을 안 댔지만, 그래도 검증은 한다.

  • 변경 전 화면 동작 확인 후 메모
  • 수정 후 같은 케이스로 재확인
  • 관련 화면 있으면 크로스체크
  • 커밋 메시지는 "무엇을"보다 "왜"를 담으려고 노력

커밋을 잘게 쪼개는 습관도 이 맥락이다. 논리적으로 독립된 단위로 커밋을 분리해 두면, 나중에 문제가 생겼을 때 어느 변경에서 깨졌는지 git bisect 한 번으로 찾을 수 있다. 하나의 거대한 커밋에 모든 게 뭉쳐 있으면 롤백도 부분 롤백이 안 된다.

사내 서비스를 계속 만들다 보면 기능 하나가 버튼 하나 추가로 끝나는 경우가 없다는 걸 반복해서 체감한다. SQL 집계, 상태 머신, 예외 처리, 화면 렌더링, 권한 체크가 모두 연결돼 있어서 어느 하나 빠뜨리면 특정 사용자에게 이상한 화면이 나타난다. 그래서 변경 범위가 "파일 1개"라도 맥락은 넓게 보는 편이다.

이번 작업은 변경 자체는 작았지만, 정리하고 나면 다음에 이 화면 건드릴 때 훨씬 편할 거라는 확신이 있어서 했다. 그 확신이 리팩토링의 타당성이라고 생각한다.

댓글 0

첫 댓글 달아줘.