개발 slecs

Daily Bible 어드민에 캘린더·검색·통계·푸시 페이지 신설

목차

Daily Bible 어드민 메뉴를 새로 파고, 캘린더 / 검색 / 통계 / 푸시 4개 페이지를 한 커밋에 올렸다.


왜 이 메뉴가 필요했나

콘텐츠 기반 서비스에서 "오늘의 말씀" 같은 데일리 콘텐츠는 단순히 DB에 넣고 끝나는 게 아니다. 언제 보낼지, 누가 받았는지, 얼마나 소비됐는지를 운영자가 직접 확인하고 컨트롤할 수 있어야 서비스가 제대로 돌아간다. 기존에는 이 흐름이 흩어져 있거나 아예 어드민에 노출이 안 된 상태였다. 팀 안에서 "운영자가 푸시를 수동으로 쏘거나, 특정 날짜 말씀을 확인하려면 DB를 직접 뒤져야 한다"는 불편이 쌓이다 보니 결국 이번에 통째로 만들기로 했다.

이런 류의 작업은 보통 "급하지 않다"는 이유로 미뤄지다가, 실제로 운영 이슈가 터지면 그제야 "왜 어드민이 없냐"는 말이 나온다. 이번엔 그 타이밍 전에 선제적으로 만든 셈.


4페이지 구조와 각 파일의 역할

페이지 파일 역할
캘린더 daily-bible/calendar/ 날짜별 말씀 등록 현황 시각화
푸시 daily-bible/push/ 푸시 발송 대상/시간 설정 및 실행
(검색, 통계) daily-bible.ts (actions) 서버 액션으로 검색·집계 로직 처리

Next.js App Router 구조에서 page.tsx + *Client.tsx 패턴을 쓰는 건 이 프로젝트에서 일관되게 가져가는 규칙이다. page.tsx는 서버 컴포넌트로 초기 데이터 패칭만 담당하고, 인터랙션이 있는 UI는 전부 *Client.tsx로 분리한다. 덕분에 코드리뷰할 때 "이 로직이 서버에서 도는 건지 클라이언트에서 도는 건지" 헷갈리는 일이 줄어든다. 팀원들한테 이 패턴을 처음 설명할 때는 저항이 좀 있었는데, 막상 써보니 디버깅 지점이 명확해진다는 피드백을 꽤 받았다.

src/actions/daily-bible.ts에 검색과 통계 로직을 모아넣은 건 의도적인 선택이다. 각 페이지마다 fetch나 직접 DB 호출을 흩뿌리면 나중에 로직 변경할 때 어디를 건드려야 하는지 파악이 힘들어진다. Server Action 파일을 도메인 단위로 모아두면 "Daily Bible 관련 데이터 흐름은 여기 보면 된다"는 암묵적 약속이 생긴다.


.env.example 변경의 의미

.env.example이 변경된 건 작아 보여도 팀 입장에서는 꽤 중요한 신호다. 새로운 환경 변수가 추가됐다는 뜻이고, 이게 누락되면 로컬이나 스테이징에서 푸시 기능이 조용히 실패한다. 푸시 발송처럼 외부 서비스(FCM 등)와 연동되는 기능은 특히 그렇다.

# .env.example에 추가된 키 예시 (실제값 아님)
DAILY_BIBLE_PUSH_KEY=
DAILY_BIBLE_PUSH_TOPIC=

신규 입사자나 다른 팀원이 브랜치 받아서 띄울 때 .env.example 보고 세팅하는 게 관례인 만큼, 여기 누락되면 "푸시가 안 된다"는 이슈가 슬랙에 올라오는 건 시간문제다. 커밋에 함께 포함시킨 건 당연한 거지만, 생각보다 이걸 빠뜨리는 경우가 많다. 코드리뷰 체크리스트에 "새 env 추가 시 .env.example 갱신"을 넣어두면 좋다.


캘린더 UI와 푸시 페이지, 각각의 고민

캘린더 페이지(CalendarClient.tsx)는 어드민에서 날짜 기반 콘텐츠를 다룰 때 가장 직관적인 UI다. "이번 달에 빠진 날짜가 어디냐"를 한눈에 파악할 수 있어서 운영자 입장에서는 리스트 뷰보다 훨씬 쓰기 편하다. 다만 캘린더 컴포넌트는 상태 관리가 은근히 복잡해진다. 선택 날짜, 현재 월, 로딩 상태, 모달 오픈 여부까지 얽히면 useState만으로 버티다가 결국 useReducer로 리팩터링하는 경우가 많다. 이번에 어떻게 잡았는지는 다음 리뷰 때 같이 볼 예정.

푸시 페이지(PushClient.tsx)는 기능 자체는 단순해 보여도 "한 번 쏘면 되돌릴 수 없다" 는 특성 때문에 UI에 안전장치를 얼마나 넣느냐가 포인트다. 실수 발송을 막기 위한 확인 다이얼로그, 발송 대상 미리보기, 중복 제출 방지 처리 등이 실제로는 꽤 많은 코드를 차지한다. 이런 건 기획서에 안 나오는 부분인데, 운영자가 한 번 실수를 경험하고 나서야 "확인 버튼 좀 더 강하게 만들어달라"고 요청이 들어온다.


회고

4개 페이지를 한 커밋에 올린 건 개인적으로 좀 아쉬운 부분이다. 작업 단위가 크다 보니 리뷰어 입장에서 컨텍스트 전환이 많다. 이상적으로는 액션 레이어 → 캘린더 → 검색/통계 → 푸시 순으로 나눠서 올렸으면 리뷰 코멘트가 더 정확하게 붙었을 것이다. 다만 이 4페이지가 서로 같은 액션 파일을 공유하다 보니 중간에 끊기가 애매했다는 현실적인 이유도 있다.

어드민 기능은 "만들고 끝"이 아니라 실제로 운영자가 써봐야 결함이 나온다. 배포 후 운영팀에서 직접 써보고 피드백 주는 루프를 빠르게 돌리는 게 다음 스텝.


끝.


🛒 이 글과 어울리는 추천 상품

*위 링크는 쿠팡파트너스 활동의 일환이며, 일정액의 수수료를 제공받을 수 있습니다.

댓글 0

첫 댓글 달아줘.