File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
대시보드 → 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 Kitsection블록으로 구성. - 토큰은 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 허용목록 제외) ✅
- 지표: 매출(일/월) / 회원 현황 / 문자 발송 현황 ✅