파트너 전용 공지사항 보드 신규 분리
목차
파트너 전용 공지사항을 별도 보드로 분리했다. board_type=PARTNER_NOTICE 를 신설하고 내부 클래스 3개, SQL 매퍼 2개, 뷰+스타일 파일 1개를 건드렸다. 변경 규모 자체는 크지 않은데, 작업 과정에서 결정해야 할 지점이 생각보다 많았다.
왜 분리했나
기존 공지사항 보드는 단일 board_type 값으로 여러 카테고리를 구분하는 구조였다. 일반 공지, 이벤트, 업데이트 노트가 같은 테이블에 섞여 있고 화면마다 필터 조건만 달리 달았다. 초기에는 단순하고 편한데, 파트너처럼 "완전히 다른 대상"을 위한 콘텐츠가 끼어들면 문제가 생기기 시작함.
가장 직접적인 이유는 접근 제어다. 파트너 전용 공지는 일반 사용자에게 노출되면 안 된다. 기존 필터링으로도 구현은 가능하지만, 새 API 엔드포인트를 추가할 때 조건을 빠뜨리거나 복붙 실수 하나로 구멍이 생긴다. 타입 자체를 PARTNER_NOTICE 로 분리하면 쿼리 레벨에서 격리되니까 실수로 섞일 가능성이 낮아진다.
두 번째 이유는 이후 확장성이다. 파트너 공지가 생기면 전용 첨부파일, 읽음 여부 추적, 노출 기간 설정 같은 요구사항이 따라오는 경우가 많다. 타입을 처음부터 분리해두면 추가 컬럼이나 로직을 붙일 때 기존 일반 공지에 영향을 주지 않고 독립적으로 확장할 수 있다.
구현과 설계 결정
변경 순서는 DB 쿼리부터 잡고, 클래스 메서드 추가, 화면 연동 순으로 진행했다. 위에서 아래로 내려가는 게 아니라 데이터 레이어부터 올라오는 방식. 화면부터 만들고 쿼리를 맞추려 하면 나중에 렌더링 데이터 구조가 바뀔 때 두 번 뜯게 된다.
SQL 매퍼 두 개는 목록 조회와 단건 조회 쪽이었다. 두 쿼리 모두 board_type = 'PARTNER_NOTICE' 조건을 파라미터로 받지 않고 명시적으로 고정했다. 파라미터로 넘기면 호출부에서 타입 값을 직접 관리해야 하는데, 오타 하나로 잘못된 타입이 들어올 수 있어서 매퍼 자체가 "파트너 공지 전용"이라는 의미를 가지도록 했다.
내부 클래스 3개에는 서비스 메서드, 레포지토리 메서드, DTO 변환 로직이 각각 들어갔다. 기존 일반 공지 흐름을 복사해서 타입만 바꾸는 식이 아니라, 공통 처리 로직은 기존 메서드를 재사용하고 파트너 전용 조건만 서비스 레이어에서 강제했다.
// 파트너 공지 전용 진입점 - 호출부에서 타입을 직접 주입하지 않음
public List<NoticeDto> getPartnerNotices(PartnerNoticeSearchDto search) {
search.setBoardType(BoardType.PARTNER_NOTICE);
return noticeMapper.selectNoticeList(search);
}
설계 결정 중 자주 논의되는 항목들을 정리하면 이렇다.
| 항목 | 결정 | 이유 |
|---|---|---|
| 실시간 갱신 | 기본 조회 방식 | 등록 주기가 길고 즉시성 요구 없음 |
| 권한 체크 위치 | API + 서비스 레이어 이중 | 내부 직접 호출 우회 방지 |
| 쿼리 타입 고정 | 서비스 레이어에서 강제 | 호출부 실수로 인한 타입 오염 방지 |
| 빈 데이터 처리 | 빈 리스트 반환 보장 | null 전파 차단 |
권한 체크는 API 단에서 막는다고 서비스 레이어에서 생략하면 나중에 내부 서비스 간 직접 호출이 생겼을 때 우회가 가능해진다. 실제로 그런 케이스가 생기는 건 몇 달 뒤인데, 그때 가서 수정하면 이미 다른 코드가 그 위에 쌓여 있다.
폴링 vs 이벤트 기반 갱신 결정도 미리 해두는 게 좋다. 나중에 "왜 새 공지가 바로 안 뜨나요" 피드백이 오기 전에 명시적으로 결정하고, 그 근거를 코드 주석이나 커밋 메시지에 남기면 이후 유지보수하는 사람이 같은 결정을 다시 고민하지 않아도 된다.
검증과 작업 습관
구현 후 화면에서 직접 확인했다. 파트너 계정으로 접근했을 때 공지가 정상 노출되는지, 일반 계정으로 접근했을 때 노출되지 않는지 양쪽 다 확인했다. 카운트 값이 목록 건수와 맞는지도 봤는데, 합산이 어긋나면 쿼리 조건이 어딘가 다르게 걸려 있다는 신호라서 이건 금융/결제 영역에서 특히 빠뜨리면 안 되는 체크다.
커밋은 논리 단위로 쪼갰다. SQL 매퍼 수정, 서비스 레이어 추가, 화면 연동을 각각 별도 커밋으로 남겼다. 특정 변경에서 문제가 생겼을 때 git bisect 나 git blame 으로 추적하기 훨씬 쉬워진다. 커밋 메시지는 "무엇을"보다 "왜"를 담으려 한다. 파트너 공지 목록 쿼리 추가보다 파트너 공지 타입 분리 - 일반 공지와 접근 제어 격리 목적 쪽이 3개월 뒤에 읽어도 맥락이 살아 있다.
사내 서비스를 만들다 보면 기능 하나가 단순히 화면에 버튼 하나 추가하는 걸로 끝나지 않는다는 걸 계속 체감한다. SQL 집계, 권한 상태, 예외 처리, 화면 렌더링이 모두 엮여 있어서 어느 하나만 빠뜨려도 숫자가 맞지 않거나 특정 사용자에게 이상한 화면이 나온다. 금융/결제 도메인은 숫자 하나가 틀리면 신뢰가 무너질 수 있어서, "대충 맞는 것 같다"로 넘기면 반드시 다시 돌아온다. 꼼꼼함이 디폴트가 되어야 뒷수습 비용이 줄어든다.
댓글 0
첫 댓글 달아줘.