사이트픽 블로그
← 목록으로

개발일지 2026-07-17

개발일지 (2026-07-17)

개요

학원 알림 템플릿 관리 시스템을 구축하고, 카카오 알림톡(뿌리오) 연동 및 자동 알림 발송 엔진을 구현했다.


수정/생성 파일 목록

백엔드 (piano-backend)

  • migration-20260715d-notification-templates.sql (신규) — 학원 알림 템플릿 테이블 + 기본 시드 7종
  • NotificationTemplate.java (신규) — 알림 템플릿 엔티티
  • NotificationTemplateMapper.java/xml (신규) — 학원 커스텀 우선 COALESCE 조회 + UPSERT
  • NotificationTemplateController.java (신규) — 목록/자동발송토글/저장 API
  • AcademyNotificationSender.java (신규) — 자동 알림 발송기 (SMS + 카카오 알림톡 + SMS 폴백)
  • StudentBookingService.java (수정) — 예약 확정 시 LESSON_CONFIRM 자동 알림 발송
  • PpurioService.java (수정) — [*N*] 형식 변수 치환 추가
  • NotificationTemplateMapper.xml (수정) — kakao_template_code 컬럼 SELECT/UPSERT 추가

프론트 — 학원 앱 (academy)

  • api/notificationTemplates.ts (신규) — 알림 템플릿 API 클라이언트
  • pages/NotificationTemplates.tsx (신규) — 알림 관리 페이지 (규칙 테이블 + 템플릿 편집기 + 미리보기)
  • App.tsx (수정) — /notification-templates 라우트 추가

파일별 상세

1. 학원 알림 템플릿 관리

학원별 자동 알림을 관리하는 시스템을 구축했다.

DB 구조:

  • academy_notification_templates 테이블: academy_id=0은 기본값, 학원별 UPSERT로 커스텀
  • 7개 알림 유형: 레슨 확정, 리마인더, 수강권 만료, 결제 완료, 환불 완료, 상담 예약, 체험 레슨
  • kakao_template_code 컬럼으로 뿌리오 카카오 알림톡 키 저장

발송기 (AcademyNotificationSender):

  • 이벤트 발생 → 템플릿 조회(학원 커스텀 우선) → auto_send 확인 → 변수 치환 → 발송
  • 카카오 키가 있으면 알림톡 발송, 실패 시 SMS 자동 폴백
  • 발송 성패와 무관하게 도메인 트랜잭션은 정상 커밋 (예외 흡수)
  • message_logs 테이블에 발송 이력 자동 기록

2. 카카오 알림톡 연동

뿌리오 카카오 알림톡 API와 연동했다.

흐름:

  1. 예약 확정 등 이벤트 발생
  2. 템플릿에 kakao_template_code가 있으면 카카오 알림톡 발송
  3. 변수([*이름*], [*1*]~[*4*])를 뿌리오 changeWord 형태로 전달
  4. 카카오 발송 실패 시 SMS로 자동 폴백

3. 알림 관리 UI

학원 앱에 알림 관리 페이지를 만들었다.

구성:

  • 상단: 자동 알림 규칙 테이블 (유형별 ON/OFF 토글)
  • 하단: 템플릿 편집기 (좌: 목록 / 중: 본문+변수삽입+미리보기 / 우: 발송시점+카카오키)
  • 제목 편집, 뿌리오 카카오 키 입력/저장 가능

트러블슈팅 메모

  • 알림 관리 페이지 배포 누락: tar가 제대로 안 올라가서 이전 번들이 서빙됨 → 배포 후 번들 해시 비교 필수
  • kakao_template_code 조회 누락: COALESCE 쿼리에 컬럼을 빼먹어서 항상 null 반환 → SELECT에 추가

결론 / 배운 점

  • 알림 발송은 도메인과 분리해야 한다. 알림 실패로 예약/결제가 롤백되면 안 된다. 예외를 흡수하고 이력만 남기는 패턴이 안전하다.
  • 카카오 알림톡 심사는 까다롭다. 변수 형식([*N*]), 수신자 액션 명시, 광고성 문구 제한 등 규격을 미리 파악해야 한다.

댓글 0

  • 첫 번째 댓글을 남겨보세요.