개발 slecs

공급사 포탈에 역할 분리와 실물상품 셀프 공급 기능 추가

목차

supplier-portal 영역에 기능 세 가지를 한 번에 밀어 넣었다. 공급사 역할 분리, 공급사 전용 포탈, 실물상품 셀프 공급. 파일 기준으로는 내부 클래스 6개가 바뀌었는데, 바뀐 줄 수 대비 고민 시간이 훨씬 길었던 작업이다.

왜 이게 필요했나

기존 화면과 API는 처음 설계 시점의 유스케이스에 맞춰져 있었다. 공급사라는 역할이 단일 덩어리로 취급되다 보니, 실물 상품을 직접 등록·관리하려는 공급사와 그걸 검토하는 담당자가 같은 메뉴를 보는 구조였음. 기능이 하나씩 붙을수록 권한 경계가 모호해지고, "이 버튼은 저한테 왜 보이나요?" 같은 문의가 들어오기 시작했다.

역할 분리는 생각보다 뒤를 많이 건드린다. 화면만 분리하는 게 아니라 권한 인터셉터, 메뉴 활성화 로직, API 엔드포인트 접근 제어, 역할별 데이터 쿼리까지 동시에 바뀌어야 한다. 어느 한 레이어만 손대면 화면에서는 메뉴가 안 보이는데 URL 직접 접근은 통과되는, 반쪽짜리 구현이 된다. 그래서 이번엔 처음부터 쿼리 레벨부터 잡고 올라갔음. 단순 UI 추가로 접근했다가 중간에 엎는 것보다 처음 설계에 시간을 더 쓰는 게 낫다는 걸 이전 작업들에서 배웠다.

실물상품 셀프 공급 쪽은 기존에 담당자가 대신 등록해주던 흐름을 공급사가 직접 할 수 있게 여는 작업이었다. 상태값은 "등록 요청 → 검토 중 → 승인/반려" 흐름으로 설계했고, 공급사는 자신이 올린 상품의 상태만 조회할 수 있도록 데이터 접근 범위도 함께 제한했음.

구현 흐름

크게 세 레이어가 동시에 움직였다.

백엔드는 공급사 전용 포탈의 API 엔드포인트를 새로 뚫었다. 기존 엔드포인트를 재활용하지 않은 이유는 역할별 응답 스펙이 달라질 수 있어서다. 공통 서비스 레이어는 그대로 두되, 컨트롤러 레벨에서 역할 분기를 가져갔음.

프론트는 JSP + AJAX 구조. 사이드바 메뉴 활성화, 신규 메뉴 진입점, 실물상품 등록 폼 세 곳을 연동했다. AJAX 응답 실패 케이스를 꼼꼼하게 잡아야 해서 에러 핸들링 분기가 조금 늘었음. 서버에서 내려오는 에러 코드에 따라 사용자에게 보여주는 메시지를 다르게 처리했다.

권한은 인터셉터에서 역할 체크를 추가했다. 패턴은 기존 인터셉터 구조에 맞게 끼워 넣는 방식으로:

// 공급사 역할 검증 - 인터셉터
String supplierRole = (String) session.getAttribute("supplierRole");
if (supplierRole == null || !ALLOWED_ROLES.contains(supplierRole)) {
    response.sendRedirect("/supplier/portal/unauthorized");
    return false;
}

단순해 보이지만 이게 빠지면 역할 분리가 화면에서만 존재하고 실제 접근 제어는 없는 상태가 된다. URL을 직접 치고 들어오는 케이스, 세션이 만료된 상태에서 접근하는 케이스 등 방어해야 할 경우의 수가 생각보다 많다.

설계 포인트와 검증

데이터 정합성은 이 도메인에서 타협이 없는 항목이다. 공급사 포탈에 나오는 집계 숫자가 다른 화면과 다르면 신뢰 문제로 직결된다. 설계 단계에서 체크한 것들을 정리하면:

항목 결정 이유
실시간 갱신 방식 폴링 없이 요청 시 조회 상태 변경 빈도가 낮아 이벤트 처리 불필요
빈 데이터 처리 공란 또는 0으로 표시 미처리 시 화면 깨짐, NPE 가능성
쿼리 실행 계획 신규 쿼리 EXPLAIN 사전 확인 테이블 크기 고려, 인덱스 활용 여부 검토
권한 없는 접근 인터셉터에서 리다이렉트 URL 직접 접근 방어
역할별 데이터 범위 본인 공급사 데이터만 조회 타 공급사 데이터 노출 차단

폴링 vs 이벤트 결정이 처음에는 좀 고민됐다. 실시간으로 상태가 바뀌는 느낌을 주려면 웹소켓이나 SSE가 낫긴 한데, 승인/반려 처리 빈도가 높지 않고 공급사가 페이지를 열어두고 계속 지켜보는 패턴이 아니라 판단해서 단순하게 갔음. 기능이 더 붙고 실시간성이 필요해지면 그때 바꾸는 게 낫다고 봤다.

구현 후에는 직접 화면에서 동작을 확인했다. 기존 데이터가 깨지지 않았는지, 관련 화면의 숫자가 일치하는지 cross-check. 변경 전 수치를 메모해두고 같은 케이스로 비교하는 게 습관이 됐는데, 사소해 보여도 이게 없으면 "원래도 이랬나?" 싶은 상황이 생긴다.


사내 서비스를 만들다 보면 기능 하나가 버튼 하나 추가로 끝나지 않는다는 걸 작업할 때마다 체감한다. SQL 집계, 상태 머신, 예외 처리, 화면 렌더링, 권한 체크가 모두 엮여 있어서 어느 하나만 빠뜨려도 특정 사용자에게 이상한 화면이 나타나거나 숫자가 어긋난다. 특히 금융/결제 도메인은 그 임계치가 낮다. "대충 맞는 것 같다"로 넘기면 나중에 반드시 다시 돌아옴.

이번 작업은 역할 분리, 엔드포인트 추가, 프론트 연동, 권한 인터셉터를 각각 별도 커밋으로 쪼갰다. 작은 커밋이 쌓이면 나중에 어느 변경에서 뭔가 깨졌는지 찾는 시간이 확실히 줄어든다. 커밋 메시지도 "무엇을" 보다 "왜"를 담으려고 했음. 지금은 그게 나중의 나한테 쓰는 메모라는 생각으로 쓴다.

댓글 0

첫 댓글 달아줘.