File name
Commit message
Commit date
jykim 09-15 00e045f 전송자격인증제 migration UNIX

대시보드 → n8n → Slack 정기 리포트 연동 설계#

작성일: 2026-06-23

1. 목적 / 범위#

문자ON 관리자 대시보드(/cmm/main/mainPage.do)의 주요 운영 지표를 매일(또는 매주) 정해진 시각에 Slack 채널로 요약 발송한다.

  • 연동 방식: 앱에 신규 JSON API 엔드포인트를 추가하고, n8n이 스케줄로 호출하여 Slack으로 게시(pull 방식).
  • 포함 지표(1차): 매출(일/월), 회원 현황, 문자 발송 현황.
  • 인증: 공유 토큰(헤더) 단독. (회사 내부망 사용 전제로 IP 허용목록은 제외)
  • 비범위(추후): 발신번호/환불 대기 지표, 실시간 이벤트 알림, IP 허용목록.

2. 현황 (재사용 자산)#

itn.let.main.web.EgovMainController가 대시보드 데이터를 아래 서비스 메서드로 조회하고 있으며, 그대로 재사용한다(신규 SQL 없음).

  • 매출: MjonPayService.selectPayDayChartDashboard, selectPayMonthChartDashboard, selectPayYearChart
  • 회원: EgovConectStatsService.selectMberTotStats, selectMberCmpHstStatsDashboard, selectTodaySttCountString
  • 문자: MjonMsgService.selectAgentSmsCountStatMainList, selectMemDayChartDashboard

3. 엔드포인트 계약 (Contract)#

요청

GET /api/dashboard/summary.do
Header: X-DASHBOARD-TOKEN: <공유 토큰>   (필수)
Query : ?date=YYYY-MM-DD                 (선택, 미지정 시 오늘)

응답 — 앱은 Slack 포맷이 아닌 순수 도메인 JSON만 반환(Slack 표현은 n8n 담당, 앱-Slack 결합도 제거).

{
  "isSuccess": true,
  "msg": "",
  "baseDate": "2026-06-23",
  "sales": {                              // 매출(VAT 포함, 단위: 원, 숫자)
    "todayAmt": 1234500,                  // 당일 매출액
    "dayChart":   [ {"date":"06-20","amt":900000}, ... ],   // 최근 4일
    "monthChart": [ {"month":"6월","amt":25000000}, ... ],  // 최근 4개월
    "yearAmtSum": 310000000               // 연간 누적
  },
  "members": {                            // 회원 현황
    "userNorCnt": 0, "userComCnt": 0,     // 개인/기업 정상회원수
    "mberNorTot": 0,                      // 정상회원 합계
    "mberBlockTot": 0, "mberSecessTot": 0,// 정지/탈퇴 누적
    "cmpApply": 0, "cmpApprove": 0, "cmpReject": 0, // 기업회원 신청/승인/반려
    "todayExpireCnt": 0, "todayStopCnt": 0          // 금일 탈퇴/정지
  },
  "sms": {                                // 문자 발송 현황(전송사별)
    "agents": [
      {"agentCode":"ITN019","succCnt":12000,"failCnt":30,"succRate":99}, ...
    ],
    "todaySignupCnt": 0                   // 일 회원가입자수(참고)
  }
}
  • 원본 서비스가 문자열로 반환하는 금액/건수는 서비스 계층에서 숫자로 정규화한다.
  • 천단위 콤마/원화 표기 등 표현 포맷은 n8n에서 처리한다(앱은 raw 숫자만 제공).
  • 누락 지표는 1차 범위에서 제외하며, 향후 sales/members/sms 블록에 필드를 추가하는 식으로 확장한다.

4. 인증 / 보호#

  • globals.properties에 Globals.dashboard.api.token 추가, 환경별 globals_*.properties에서 override.
  • 신규 인터셉터 DashboardApiAuthInterceptor를 /api/dashboard/** 경로에만 매핑(egov-interceptor-servlet.xml).
    • 요청 헤더 X-DASHBOARD-TOKEN 값이 설정 토큰과 불일치/누락 → 401 JSON({"isSuccess":false,"msg":"unauthorized"})을 직접 작성하고 컨트롤러 진입 차단.
  • 엔드포인트가 *.do이므로 Spring Security의 DB 기반 URL 권한(context-security.xml)에 걸릴 수 있다 → /api/dashboard/**를 security="none"으로 예외 추가(토큰으로 자체 보호, 세션 불필요).
  • 토큰 값은 응답/로그에 노출 금지.

5. Java 컴포넌트 구성 (4종 패턴)#

신규 모듈 itn.let.mjo.dashboardapi:

파일역할
web/DashboardApiController.java@RestController. GET /api/dashboard/summary.do → getDashboardSummary(...)가 DashboardSummaryVO를 직접 반환(Jackson 직렬화, jsonView 미사용). 얇게 유지
service/DashboardSummaryService.java인터페이스
service/DashboardSummaryVO.java응답 DTO(sales/members/sms 중첩 + isSuccess/msg/baseDate). Jackson 직렬화용 getter 포함
service/impl/DashboardSummaryServiceImpl.java@Service. 기존 mjonPayService·conectStatsService·mjonMsgService를 주입해 조합·숫자 정규화
web/DashboardApiAuthInterceptor.java토큰 헤더 검증 인터셉터

설계 근거 / 규칙:

  • DAO 신규 없음 — 기존 검증된 서비스 메서드만 호출.
  • @RestController는 @Controller를 메타포함 → 디스패처 컨텍스트의 @Controller 스캔에 잡힘. Jackson 컨버터는 <mvc:annotation-driven/> + jackson-databind 의존성 + 기존 @ResponseBody 선례로 동작 검증됨.
  • 빈 스캔 분리 유지: 컨트롤러/인터셉터=디스패처 컨텍스트, 서비스=루트 컨텍스트.
  • 관리자 로그 AOP가 itn..*Controller.select*에 걸리므로, 메서드명을 getDashboardSummary로(=select* 아님) 지어 불필요한 잡로그를 피한다.
  • 지표 블록별 try/catch — 개별 지표 실패가 전체 응답을 막지 않도록 하고 실패 블록은 null/0으로 둔다(기존 대시보드 Ajax 관례).

6. n8n 워크플로우 / Slack#

[Schedule Trigger]   매일 09:00 (cron)
       ↓
[HTTP Request]       GET https://<admin-host>/api/dashboard/summary.do
                     Header X-DASHBOARD-TOKEN = {{ $env.MJON_DASH_TOKEN }}
       ↓
[Code (Function)]    도메인 JSON → Slack Block Kit 변환(콤마/원화 포맷 여기서)
       ↓
[Slack node]         지정 채널 게시(OAuth 또는 Incoming Webhook)
  • Slack 메시지: 제목(📊 문자ON 일일 리포트 — {baseDate}) + 매출/회원/문자 섹션을 Block Kit section 블록으로 구성.
  • 토큰은 n8n 환경변수 MJON_DASH_TOKEN에 보관(워크플로우 JSON에 평문 미포함).
  • 산출물: import 가능한 n8n-workflow.json 예시 + Code 노드 포맷 스니펫.

7. 에러처리 / 테스트 / 배포#

  • 앱 서비스: 지표 블록별 try/catch, 전역 실패 시 isSuccess:false + msg. 인증 실패는 인터셉터에서 401 JSON.
  • 테스트: 본 저장소는 단위테스트 인프라가 없음(surefire skipTests=true) → 수동 검증.
    • curl -H "X-DASHBOARD-TOKEN: <token>" http://localhost/api/dashboard/summary.do (토큰 유/무 케이스 모두).
    • n8n 워크플로우 Execute → Slack 채널 수신 확인.
  • 설정: globals.properties에 Globals.dashboard.api.token 추가, 환경별 override. 운영 토큰은 별도 공유.
  • 배포: WAR 재빌드 후 WAS 반영. 신규 엔드포인트는 추가 전용이라 기존 기능 영향 없음.

8. 결정 사항 요약#

  • 연동: pull(신규 JSON API + n8n 스케줄) ✅
  • 집계 위치: 신규 Service(접근안 A) ✅
  • 컨트롤러: @RestController ✅
  • 인증: 공유 토큰 단독(IP 허용목록 제외) ✅
  • 지표: 매출(일/월) / 회원 현황 / 문자 발송 현황 ✅