본문 바로가기

카테고리 없음

[TIL] 유레카 sw교육과정 백엔드 25주차 내용 정리

25주차는 개발 시작

JIRA로 스프린트 진행

이렇게 8개의 기능 개발 완료

일반 로그인

토큰 발급

 

구글 이메일 중복 확인

내 정보 및 메뉴 권한 조회

토큰 바탕으로 로그인한 계정의 정보 출력

 

직원 계정 정보 상세 조회

 

직원 empId 바탕으로 해당 직원 정보 조회

 

직원 계정 정보 목록 조회

 

페이지 수와 사이즈, 부서 및 역할에 따라 조회 가능

 

저번주에 진행한 내용

1. 계정 보안 및 유효성 검증

신규 직원이 등록될 때 데이터의 무결성을 보장하기 위한 로직을 구축했습니다.

  • Google 이메일 중복 확인: Google SSO(Single Sign-On) 연동을 고려하여, 가입 전 해당 이메일이 DB에 이미 존재하는지 검증하는 API를 구현했습니다. 이는 계정 충돌을 방지하는 첫 번째 방어선입니다.
  • 직원 계정 정보 조회 (목록/상세): * 목록 조회: 전체 직원 리스트를 페이징 처리하여 효율적으로 출력합니다.
    • 상세 조회: 특정 직원의 기본 인적 사항뿐만 아니라 현재 할당된 직무와 권한 상태를 한눈에 확인할 수 있는 상세 페이지 API를 완성했습니다.

2. 사용자 중심의 권한 컨텍스트(Context) 구현

로그인한 사용자가 자신의 상태와 권한을 실시간으로 파악할 수 있도록 돕는 기능입니다.

  • 로그인 계정 정보 조회: 현재 세션에 유지되고 있는 사용자의 고유 ID, 이름, 소속 등의 프로필 정보를 반환하여 프론트엔드 UI의 개인화를 지원합니다.
  • 개별 권한 목록 조회: 사용자가 가진 모든 세부 권한(예: READ_CONSULT, DELETE_USER 등)을 리스트 형태로 응답합니다. 이를 통해 프론트엔드에서 버튼 노출 여부를 동적으로 제어(UI Masking)할 수 있습니다.

3. 직무(Job-Role) 기반 동적 메뉴 시스템 설계

오늘 작업 중 가장 난도가 높았던 부분으로, 직무에 따라 메뉴 노출을 제어하는 유연한 구조를 설계했습니다.

  • 메뉴 관련 테이블 설계 및 생성:
    • menu: 전체 메뉴 트리 구조(ID, URL, 순서 등)를 관리합니다.
    • job_role_menu: 특정 직무(상담원, 관리자 등)가 접근 가능한 메뉴를 연결하는 매핑 테이블입니다.
  • 기능 구현: 사용자가 로그인할 때 소속된 Job-Role을 확인하고, 그에 매핑된 메뉴들만 쿼리하여 사이드바에 동적으로 렌더링하는 로직을 완성했습니다.

4. 권한 관련 DB 및 코드 리팩토링

시스템의 확장성을 위해 기존의 파편화된 권한 구조를 정리했습니다.

  • DB 수정 및 삭제에 따른 코드 싱크: 불필요해진 권한 테이블을 삭제하고, 관련 엔티티와 레포지토리 코드를 최신 스키마에 맞춰 전면 수정했습니다.
  • 영향도 관리: DB 컬럼이 바뀌거나 삭제될 때 발생할 수 있는 런타임 에러를 방지하기 위해, 해당 테이블을 참조하던 모든 비즈니스 로직(Service 단)을 찾아내어 동기화했습니다.

 

저번주 프로젝트에서 정해진 프로젝트의 전체적인 구조

 

 

✅ v5 — 상담사 + 관리자 전체 기능 명세 (RBAC)
외부 콜센터 시스템 없음. 상담사 화면이 콜센터 역할을 직접 대행합니다. v5에서는 상담사(ROLE_AGENT) 관리자(ROLE_ADMIN) 두 역할의 모든 기능이 명세됩니다. 세부 기능은 섹션 05B(상담사 전체 기능) 섹션 05C(관리자 전체 기능)를 참고하세요.
👤 상담사 (ROLE_AGENT) — 주요 기능
 결과서 전송 (콜센터 대행) CSL_SEND_01
 상담내역 + AI 결과 조회 CSL_RES_01
 전문검색 (ES) SMR_DOC_01
 개인 리포트 ANL_AGT_01
 운영정책 / 우수사례 / 공지 열람
🔐 관리자 (ROLE_ADMIN) — 추가 기능
 전체 분석 리포트 ANL_ALL_01
 직원 계정 관리 MNG_EMP_01~04
 우수사례 등록·심사 DSH_BP_02
 공지 작성·삭제·핀 DSH_NTC_02~03
 운영정책 CRUD DSH_POL_01
02 핵심 기능 데이터 흐름도
👤 상담사 화면 콜센터 대행 → 결과서 전송 → AI 선별 처리 흐름
외부 콜센터 시스템은 없습니다. 우리 시스템의 상담사 화면이 콜센터 역할을 직접 대행합니다. 상담사는 더미 DB에서 랜덤 결과서를 불러와 화면에서 확인 후 [📤 송신] 버튼으로 전송합니다. 또한 상담사는 AI 분석 결과를 활용하는 페이지들(상담내역 조회, AI 분석요약, 검색, 개인 리포트)도 사용합니다.
0
상담사 화면 → 더미 DB에서 랜덤 결과서 불러오기
상담사가 [결과서 전송 화면]에 접근하면, 시스템은 더미 DB(consultation_results)에 미리 저장된 결과서 중 하나를 랜덤으로 조회하여 화면에 표시합니다. 화면에는 고객 기본정보, 상담기본정보, IAM(Issue/Action/Memo), 첨부파일 정보, 대화원문이 노출됩니다. 상담사는 화면에 표시된 내용을 확인한 후 [📤 송신] 버튼을 클릭하여 AI 분석 파이프라인을 트리거합니다.
상담사 화면 (React)GET /api/consultations/random/dummy더미 DB 랜덤 조회REST
💡 포인트: 상담사 화면이 콜센터 역할을 대행합니다. 외부 콜센터 시스템은 없습니다. 더미 데이터는 MySQL에 미리 시딩(seed)된 상태입니다.
1
상담사 [📤 송신] → API 결과서 전송 (콜센터 역할 대행)
상담사가 [📤 송신] 버튼을 클릭하면 화면에 노출된 결과서 데이터가 API Server로 POST 전송됩니다. 전송 데이터에는 고객 기본정보, 상담기본정보, IAM, 첨부파일 정보, 대화원문, category_code가 포함됩니다. 이것이 실제 콜센터 시스템이 자동으로 수행하는 역할을 우리 상담사 화면이 대신하는 것입니다.
상담사 화면 (React)POST /api/consultations/receiveREST📤 송신 버튼 클릭
2
API Server → MySQL 저장 + 비동기 이벤트 발행
API Server가 수신한 결과서를 MySQL의 consultation_results에 저장합니다. 저장 완료 후 Spring Application Event(@EventListener)를 발행하여 Async Worker에게 비동기 처리를 위임합니다. API는 즉시 콜센터에 200 OK를 반환합니다.
API ServerMySQL: consultation_results 저장@Event 발행ASYNC
3
Async Worker: DB 카테고리 코드 확인 → AI 호출 분기
Async Worker가 이벤트를 수신 후 consultation_results의 category_code를 확인합니다. 카테고리는 DB에 하드코딩된 더미 데이터 형식으로 정의되어 있으며 별도의 동적 필터링이 필요 없습니다. 카테고리 코드가 해지방어 대분류(예: CAT_CHURN_*)에 해당하면 AI 호출 대상으로 분류합니다.
Async Workercategory_code 조회IF 해지방어
4A
해지방어 카테고리 → AI API 호출 (비용 발생)
category_code가 해지방어 대분류인 경우 AI API를 호출합니다. 대화원문·IAM을 AI에게 전달하고 요약문 + 추출 키워드 + complaint_reason(불만사유) + 방어성공여부를 one-shot으로 수신합니다. 결과를 consultation_summary(MongoDB)에 저장하고 retention_analysis(MySQL)에 기록합니다. 이후 ES 색인을 트리거합니다.
Async WorkerAI APIMongoDB: consultation_summaryMySQL: retention_analysis⚡ 비용 발생
4B
그 외 카테고리 → AI 미호출, IAM 그대로 저장
해지방어 외의 카테고리(일반문의, 상품안내, 서비스 등)는 AI를 호출하지 않습니다. 수신된 IAM 텍스트와 category_code를 그대로 consultation_summary(MongoDB)에 저장합니다. ES 색인은 IAM 원문 기준으로 처리되며, Nori 형태소 분석으로 키워드 검색이 가능합니다.
Async WorkerMongoDB: IAM 원문 저장ES 색인 (Nori)✓ AI 비용 없음
5
상담사 → 분석 결과 활용 페이지들 (조회·분석 기능)
상담사는 AI가 분석한 결과를 여러 화면에서 활용합니다. ① 상담내역(CSL_RES_01): 수신된 결과서와 AI 분석 결과 조회. ② AI 분석요약(SMR_DOC_01): 해지방어 상담의 요약·키워드·불만사유·방어성공여부 확인. ③ 상담 검색(SMR_SRCH_01): ES 기반 전문검색. ④ 내 상담현황(RPT_AGT_01): 개인 리포트 조회.
ReactGET /api/consultations/random조회 전용
6
Batch 집계 → 리포트 스냅샷 → AI 인사이트 1줄
매일 새벽 Batch가 MySQL과 MongoDB를 집계하여 스냅샷을 생성합니다. AI는 집계된 숫자만 입력받아 인사이트 문장 1줄을 생성합니다.
BatchMySQL 집계AI (숫자→1줄)Snapshot 저장
⚖️ AI 호출 조건 — DB 카테고리 코드 기준 (하드코딩)
ES 키워드 필터링 없이, 수신된 결과서의 category_code만으로 AI 호출 여부를 판단합니다. 카테고리 정의는 DB에 더미 데이터로 고정되어 있으며 런타임에 변경되지 않습니다.
🔴 AI 호출 O — 해지방어 카테고리
  • CAT_CHURN_PREVENT (해지방어 일반)
  • CAT_CHURN_FEE (요금 불만 → 해지 시도)
  • CAT_CHURN_SERVICE (서비스 불만 → 해지 시도)
  • CAT_CHURN_COMPETE (경쟁사 이탈 방어)
  • 해지방어 대분류로 DB에 정의된 모든 코드
🟢 AI 호출 X — 일반 카테고리
  • CAT_INQUIRY (일반 문의)
  • CAT_PRODUCT (상품 안내)
  • CAT_SERVICE (서비스 이용 안내)
  • CAT_BILLING (요금 조회/변경 — 해지 미포함)
  • 그 외 DB에 정의된 비해지방어 카테고리 코드
03 컴포넌트별 역할 및 쓰임새
⚛️
React SPA
React 18 · TypeScript · Zustand · React Query
전체 UI 단일 진입점. RBAC(ROLE_AGENT / ROLE_ADMIN) 기반 메뉴 동적 렌더링. 상담사 화면이 콜센터 역할 대행. 상담결과서 직접 작성·등록 기능 없음.
  • 👤 상담사 전용:결과서 전송(CSL_SEND_01) · 개인 리포트(ANL_AGT_01) — 관리자 접근 시 차단
  • 🔐 관리자 전용:전체 리포트(ANL_ALL_01) · 직원 관리(MNG_EMP_01~04) — 상담사 접근 시 403
  • 공통:상담내역(CSL_RES_01) · 상담요약 검색(SMR_DOC_01) · 운영정책 · 우수사례 열람 · 공지사항
  • 관리자 추가: 우수사례 등록·심사(DSH_BP_02) · 공지 작성·삭제(DSH_NTC_02~03) · 운영정책 CRUD
  • React 사이드바: 역할 기반 메뉴 auto show/hide (admin-only / agent-only CSS class)
  • 역할 전환 토글 (UI 시연용) — 실제 권한은 JWT ROLE_* claim 기준
🔧
API Server
Spring Boot 3 · Spring Security · JPA
콜센터로부터 결과서를 수신하여 저장하고, 화면 조회 API를 제공합니다. 수신 즉시 비동기 이벤트를 발행하여 AI 처리를 위임합니다.
  • JWT 인증 + job_roles 기반 RBAC (Spring Security)
  • POST /api/consultations/receive — 콜센터 결과서 수신 저장
  • GET /api/consultations/random — 랜덤 결과서 조회 (시연용)
  • 저장 후 @ApplicationEvent 발행 → Async Worker에게 위임
  • 리포트 조회 API: MongoDB 스냅샷 읽기 (실시간 집계 없음)
⚙️
Async Worker
Spring @Async · @EventListener
AI 선별 호출의 핵심. API 이벤트를 비동기로 수신하여 DB 카테고리 코드를 확인하고 AI 호출 여부를 결정합니다.
  • @EventListener로 consultation_results 저장 이벤트 수신
  • category_code 확인: 해지방어 코드면 AI 호출, 아니면 IAM 저장
  • AI 호출 시: 요약+키워드+불만사유+방어성공 one-shot 요청
  • 결과 → MongoDB: consultation_summary + ES 색인 트리거
  • AI 호출 결과 → MySQL: retention_analysis 기록
  • consultation_analysis_status 상태 관리 (retry_count 포함)
🕑
Batch Server
Spring Batch · Quartz Scheduler
리포트의 핵심 데이터 생산자. 새벽 스케줄에 MySQL·MongoDB를 집계해 스냅샷을 미리 생성.
  • 매일 02:00: MySQL GROUP BY 집계 → daily_report_snapshot
  • 매주 월 03:00: 상담사 순위·상품 선호도 → weekly_report_snapshot
  • 매월 1일 04:00: 해지방어 패턴 → monthly_report_snapshot + AI 인사이트
  • 품질 분석: 인사말·공감·마무리 멘트 패턴 매칭 (regex, AI 불필요)
  • 우수사례 후보 자동 필터링 (만족도점수 + 방어성공 기준)
🗄️
MySQL
39개 테이블 · RDB 트랜잭션
모든 마스터 데이터와 트랜잭션 데이터의 원천. 카테고리 코드가 DB에 하드코딩되어 런타임 분기 기준이 됩니다.
  • consultation_results: 콜센터 수신 결과서 (고객정보, IAM, 대화원문)
  • category_master: 해지방어/일반 카테고리 코드 (하드코딩)
  • retention_analysis: 해지방어 상담 AI 분석 결과 (월별 리포트 원천)
  • customer_risk_logs: 위험 고객 이력 관리
  • consultation_analysis_status: Worker 처리 상태 추적
  • best_practices, manuals, notice 등 마스터 테이블
🍃
MongoDB
9개 컬렉션 · Document Store
AI 분석 결과와 리포트 스냅샷 저장소. 리포트 조회 시 이미 계산된 스냅샷을 읽어 실시간 집계 부하 없음.
  • consultation_summary: AI 요약·키워드·ai_category 저장 + ES 색인 원천
  • daily/weekly/monthly_report_snapshot: Batch 사전 계산본
  • daily/weekly/monthly_agent_report_snapshot: 상담사 개인 성과
  • keyword_dictionary: AI 추출 키워드의 표준 집합 (검색 정확도 향상용)
  • synonym_dictionary: ES synonym.txt 원천 (동의어 처리)
🔍
Elasticsearch
Nori Analyzer · synonym filter
상담 요약 전문검색 전용. AI 호출 분기에는 관여하지 않습니다. 카테고리 기반 분기가 ES를 대체합니다.
  • consultation_summary 색인: IAM 텍스트 + AI 요약문 검색 지원
  • Nori 형태소 분석: 텍스트 토큰화 → 역색인 생성 (검색 정확도)
  • synonym_dictionary 기반 동의어 처리 (해지=해약=탈퇴)
  • SMR_DOC_01: 키워드·기간·카테고리·상담사 복합 전문검색
  • AI 호출 분기와 무관 — 색인/검색 역할만 담당
🤖
AI 엔진 (선별 호출)
GPT-4o / Claude / Gemini · 비용 최적화
해지방어 카테고리 결과서에만 호출됩니다. 한 번의 요청으로 필요한 모든 결과를 one-shot으로 수신하여 API 비용 최소화.
  • 해지방어 상담: 요약 + 키워드 + complaint_reason + 방어성공 one-shot
  • 리포트 인사이트: 숫자 집계값 → 1줄 해석 문장 (토큰 최소)
  • 우수사례(DSH_BP_02) 후보 요약문 생성
  • 카테고리는 수신된 category_code 그대로 유지 (AI가 변경하지 않음)
  • AI 결과를 consultation_summary의 별도 ai_* 필드에 저장
04 주요 데이터 흐름 연계 테이블
흐름출발→도착방식설명
결과서 수신 콜센터 MySQL: consultation_results 저장 REST POST /api/consultations/receive. 고객정보+IAM+대화원문 수신 저장.
비동기 위임 API Server Async Worker @Event 저장 완료 후 ApplicationEvent 발행 → Worker 비동기 처리 시작.
카테고리 분기 Async Worker category_master 조회 IF/ELSE DB 하드코딩 카테고리 확인. 해지방어 코드 → AI 호출, 그 외 → Skip.
AI 처리 (해지) Async Worker AI Engine COND 해지방어 카테고리만 호출. 요약+키워드+불만사유+방어성공 one-shot.
요약 저장 Worker (AI/IAM) MongoDB: consultation_summary EVENT AI 결과 또는 IAM 원문을 저장. ES 색인 트리거.
ES 색인 consultation_summary ES: 색인 INDEX Nori 형태소 분석으로 토큰화. IAM·AI요약 모두 검색 가능.
해지방어 기록 Worker (AI) MySQL: retention_analysis EVENT AI 처리된 해지방어 상담의 complaint_reason·방어성공여부 기록.
결과서 조회 React GET /consultations/random REST CSL_RES_01. 수신된 결과서 랜덤 조회. 고객정보·IAM·대화원문 표시.
일별 집계 Batch 02:00 MongoDB: daily_report_snapshot CRON MySQL GROUP BY + ES Aggregation → 스냅샷. 조회 시 실시간 집계 없음.
월별 집계+AI Batch 1일 04:00 AI (숫자→문장)
monthly_report_snapshot
CRON retention_analysis 집계 후 AI에 숫자만 전달 → 인사이트 1줄. 토큰 최소.
리포트 조회 React MongoDB: Snapshot 읽기 REST 스냅샷 읽기만 → 빠른 응답. ANL_ALL_01·ANL_AGT_01.
요약 검색 React ES: Full-text Search REST SMR_DOC_01. 키워드·기간·카테고리·상담사 복합 검색.
05 기능 코드 × 아키텍처 매칭
기능 정의서의 각 기능 코드가 어느 컴포넌트를 경유하고, AI/ES/Batch 중 어떤 처리를 필요로 하는지 명시합니다.
기능코드카테고리기능명권한처리 방식연관 컴포넌트
AUTH 권한 권한 분기 전체 Spring Security API Server → job_roles → Redis 세션
MENU_01 메뉴 메뉴 목록 조회 전체 MySQL 조회 API → MySQL: job_role_menus → React
MNG_EMP_01~04 관리 직원 계정 관리 관리자 MySQL CRUD React → API → MySQL: employees, employee_details
MNG_ACC_01 관리 내 계정 관리 전체 MySQL CRUD React → API → MySQL: employees
DSH_POL_01 대시보드 운영정책 매뉴얼 조회 전체 MySQL 조회 React → API → MySQL: manuals
DSH_BMK_01~02 대시보드 매뉴얼 북마크 상담사 MySQL CRUD React → API → MySQL: manuals (bookmark 연관)
DSH_CUS_01 대시보드 고객우대/제약 조회 전체 MySQL 조회 React → API → MySQL: customer_policy, customer_grade
DSH_BP_01~02 대시보드 우수상담 사례 전체/관리자 AI (요약) Batch (후보) Batch 후보필터 → 관리자 선택 → AI 요약 → MySQL: best_practices
DSH_NTC_01~03 대시보드 공지사항 관리 전체/관리자 MySQL CRUD React → API → MySQL: notice (pin 우선 정렬)
CSL_RES_01 상담내역 상담 결과서 조회 전체 MySQL 조회 AI 요약 표시 React → API → MySQL: consultation_results + MongoDB: consultation_summary. 랜덤 조회.
CSL_SEND_01 결과서 전송 더미 결과서 랜덤 조회 → 화면 노출 → 송신 React (상담사) → API Server → @Event 📤 상담사 화면 (콜센터 대행) 상담사 화면에서 GET /random/dummy로 더미 결과서 불러오기 → 화면 확인 → POST /receive 송신. 콜센터 시스템 역할 대행.
SMR_DOC_01 상담요약 상담 요약 검색·조회 전체 ES 검색 React → API → ES: consultation_summary 색인 full-text 검색
SMR_FLT_01~02 상담요약 검색 조건 저장 전체 MySQL CRUD React → API → MySQL: filter, filter_groups, filter_custom
ANL_AGT_01 분석 상담사 개인 리포트 전체 On-demand 경량집계 React → API → MySQL 경량 집계 (한 명 범위, 스냅샷 없이)
ANL_ALL_01 분석 전체 리포트 조회 관리자 Batch 스냅샷 AI 인사이트 React → API → MongoDB: daily/weekly/monthly_report_snapshot (읽기)
ANL_BATCH 분석 분석 데이터 생성 - Batch CRON AI 인사이트 Batch → MySQL집계 + MongoDB집계 → Snapshot + AI 1줄
SMR_BATCH 상담요약 요약 데이터 생성 - AI (해지방어) ES 색인 수신 이벤트 → 카테고리 분기 → AI(조건부) → MongoDB: consultation_summary → ES 색인
05B 상담사 전체 기능 — 화면별 상세
권한: ROLE_AGENT — 상담사 전용 기능과 공통 열람 기능을 모두 사용합니다. 결과서 전송(CSL_SEND_01)은 상담사 전용이며, 대시보드·공지·정책 등은 관리자와 공유합니다.
📤 결과서 전송 (콜센터 역할 대행)
상담사 전용
CSL_SEND_01
  • 더미 DB에서 랜덤 결과서 불러오기 — GET /api/consultations/random/dummy
  • 화면 표시: 고객정보 / 상담정보 / IAM / 첨부파일 / 대화 원문
  • [📤 시스템에 전송] → POST /api/consultations/receive
  • 전송 후 백엔드 파이프라인 시각화 (5단계 실시간 애니메이션)
  • 해지방어 카테고리 → AI 분석 결과 우측 패널 즉시 표시
📋 상담내역 조회
공통
CSL_RES_01
  • 수신된 결과서 + AI 분석 결과 통합 조회 (조회 전용, 수정 불가)
  • 필터: 처리상태 / 유형 / 채널 / 기간
  • 상세 모달: 기본정보 / IAM내용 / 원문대화 / AI 분석결과 탭
  • AI 분석탭: 요약·키워드·불만사유·방어성공 여부 표시
  • 일반 카테고리: IAM 원문 저장 확인 (AI 미호출 명시)
🔍 상담 검색 (AI 요약문 전문검색)
공통
SMR_DOC_01 · SMR_SRCH_01
  • Elasticsearch 기반 전문검색 — Nori 형태소 분석·동의어 처리
  • 저장된 검색 조건 저장/불러오기 — SMR_FLT_01~02
  • 상세 검색: 카테고리 / 상담사 / 방어성공여부 / 기간 필터
  • 요약문 상세 모달: AI 요약·키워드·불만사유 확인
  • 결과 하이라이팅: 검색어 일치 구간 강조 표시
📊 내 상담현황 (개인 리포트)
상담사 전용
ANL_AGT_01
  • On-demand 조회 (Batch 없음) — 개인 데이터 범위 한정이라 실시간 가능
  • 일/주/월 기간 선택 탭
  • 지표: 총 상담건수·해지방어 성공률·AI처리건수·평균만족도
  • Chart.js 시각화: 기간별 추이 그래프
  • 관리자 전체 리포트(ANL_ALL_01)와 데이터 원천 공유
📖 운영정책 & 우수사례 열람
공통 (열람)
DSH_POL_01 · DSH_BP_01
  • 전체 매뉴얼 조회 — 카테고리·유형별 필터, 즐겨찾기 북마크
  • 고객유형별 대응 가이드 — VIP·민원·위협 고객 스크립트
  • 우수사례 카드 갤러리 — 카테고리 칩 필터, 좋아요·조회수
  • 우수사례 상세 모달: 핵심 포인트·Q&A 스크립트·AI 인사이트
  • 관리자는 추가로 등록·심사·공개 권한 보유 (→ 05C)
🔔 공지사항 & 내 계정
공통
DSH_NTC_01 · MNG_ACC_01
  • 공지사항 목록 조회 — 핀 고정·NEW 배지·알림 배너
  • 공지 상세 모달: 첨부파일 다운로드, 카테고리 분류
  • 내 계정: 이름·비밀번호·알림 설정 변경
  • 로그인 이력, 접속 기기 확인
  • 관리자는 공지 작성·수정·삭제 권한 추가 (→ 05C)
👤 상담사 기능 권한 요약
기능코드화면명권한데이터 원천비고
CSL_SEND_01 결과서 전송 상담사 전용 더미 DB (랜덤) 콜센터 역할 대행
CSL_RES_01 상담내역 조회 공통 MySQL + MongoDB 조회 전용·수정 불가
SMR_DOC_01 상담요약 검색 공통 Elasticsearch Nori 형태소 분석
SMR_SRCH_01 상담 검색 공통 Elasticsearch 전문검색
SMR_FLT_01~02 검색조건 저장 개인 MySQL (개인) 저장/불러오기
ANL_AGT_01 내 상담현황 상담사 전용 MySQL + MongoDB On-demand, 개인만
DSH_POL_01 운영정책 열람 공통 MySQL 북마크·검색 지원
DSH_BP_01 우수사례 열람 공통 MySQL + MongoDB 좋아요·필터
DSH_NTC_01 공지사항 열람 공통 MySQL NEW 배지·핀
MNG_ACC_01 내 계정 관리 개인 MySQL 비밀번호·알림
05C 관리자 전체 기능 — 화면별 상세
권한: ROLE_ADMIN — 관리자는 상담사의 모든 열람 기능을 포함하며, 추가로 CRUD 관리 권한을 가집니다. 결과서 전송(CSL_SEND_01)은 관리자 접근 불가입니다.
📊 전체 분석 리포트 (대시보드)
관리자 전용
ANL_ALL_01
  • 일/주/월 기간 선택 탭 — Batch 스냅샷 기반 즉시 응답
  • 전체 KPI: 총 상담건수·해지방어 성공률·AI처리 비율·평균만족도
  • 채널별·카테고리별 분포 Chart.js 시각화
  • 상담사별 성과 비교 테이블 (이름·건수·성공률·만족도 정렬)
  • AI 인사이트 1줄: Batch가 GPT-4o에 요청한 집계 해석 문장
  • 상담사 개인 리포트(ANL_AGT_01)와 동일 데이터 원천 공유
👥 직원 계정 관리
관리자 전용
MNG_EMP_01~04
  • MNG_EMP_01 직원 등록 — 사번·로그인ID·부서·직급·권한 설정
  • MNG_EMP_02 직원 목록 조회 — 이름·사번·부서·직급·상태 필터
  • MNG_EMP_03 직원 상세 조회 — 개인정보·상담 실적·접속 이력
  • MNG_EMP_04 직원 수정/삭제 — 정보 수정, 재직→퇴사 상태 변경
  • 검색: 이름·사번·로그인ID 검색, 부서·직급·상태 필터
🌟 우수사례 관리 (등록·심사·공개)
관리자 전용
DSH_BP_01~02 (Admin CRUD)
  • 우수사례 CRUD 관리 뷰 — 상태별 통계 (전체·활성·임시저장·추천)
  • 목록 관리 테이블: 상태 필터·카테고리 필터·검색
  • 등록 위저드 3단계: ① 상담 선택 → ② 핵심 포인트 작성 → ③ 미리보기·저장
  • 상태 변경: DRAFT → ACTIVE → HIDDEN (공개·비공개 전환)
  • Batch가 자동 추출한 우수사례 후보를 관리자가 심사하여 공개
  • 추천(FEATURED) 설정 — 상담사 화면에서 특별 배지 표시
📢 공지사항 관리 (작성·핀·삭제)
관리자 전용
DSH_NTC_01~03
  • DSH_NTC_01 목록 조회 — 상담사와 동일하나 관리 컬럼 추가
  • DSH_NTC_02 공지 작성·수정 — 제목·내용·카테고리·파일 첨부
  • DSH_NTC_03 공지 삭제·핀 고정 — 핀 설정 시 목록 최상단 고정
  • 알림 배너 설정 — 긴급 공지 시 모든 페이지 상단 배너 표시
  • NEW 배지 자동 관리 — 등록일 기준 7일 이내 자동 표시
📖 운영정책 관리
관리자 전용
DSH_POL_01 (Admin CRUD)
  • 매뉴얼 등록·수정·삭제 — 카테고리·유형·중요도 분류
  • 고객유형별 대응 가이드 관리 — VIP·민원·위협·성희롱 고객 스크립트
  • 버전 관리 — v1.0 → v2.0 이력 보존
  • 배포 상태 관리 — 초안·검토중·배포완료
  • 상담사에게는 열람 전용으로 제공 (CRUD 권한 없음)
🔐 RBAC 권한 체계
시스템 공통
JWT + Spring Security RBAC
  • ROLE_ADMIN: 모든 기능 접근 + CRUD 권한
  • ROLE_AGENT: 열람·검색·개인 기능만 접근, 결과서 전송 포함
  • 관리자 전용 페이지: 직원관리 / 전체리포트 — 상담사 접근 시 403
  • 상담사 전용 기능: CSL_SEND_01 / ANL_AGT_01 — 관리자 접근 시 토스트 경고
  • 공통 페이지: 상담내역·검색·운영정책·우수사례·공지 (열람)
  • React 사이드바: 역할 기반 메뉴 자동 show/hide
🔐 관리자 기능 권한 요약
기능코드화면명권한데이터 원천비고
ANL_ALL_01 전체 분석 리포트 관리자 전용 MongoDB 스냅샷 Batch 집계 기반
MNG_EMP_01 직원 등록 관리자 전용 MySQL 권한 설정 포함
MNG_EMP_02 직원 목록 조회 관리자 전용 MySQL 검색·필터
MNG_EMP_03 직원 상세 조회 관리자 전용 MySQL 실적 포함
MNG_EMP_04 직원 수정·삭제 관리자 전용 MySQL 상태 변경
DSH_BP_02 우수사례 등록·관리 관리자 전용 MySQL + MongoDB 3단계 위저드
DSH_NTC_02 공지 작성·수정 관리자 전용 MySQL 파일 첨부
DSH_NTC_03 공지 삭제·핀 관리자 전용 MySQL 배너 설정
DSH_POL_01 운영정책 CRUD 관리자 전용 MySQL 버전 관리
↓ 아래는 관리자도 사용하는 공통 기능 (상담사와 동일 화면, 동일 데이터)
CSL_RES_01 상담내역 조회 공통 MySQL + MongoDB 전체 데이터 조회
SMR_DOC_01 상담요약 검색 공통 Elasticsearch
DSH_BP_01 우수사례 열람 공통 MySQL + MongoDB +관리 뷰 추가
DSH_NTC_01 공지사항 열람 공통 MySQL +관리 컬럼 추가
MNG_ACC_01 내 계정 관리 개인 MySQL
🔐 React 사이드바 RBAC 렌더링 규칙
👤 상담사 (ROLE_AGENT) 메뉴
── 상담 업무 ──
📋 상담내역 CSL_RES_01
📤 결과서 전송 CSL_SEND_01 
🔍 상담요약 SMR_DOC_01
📊 내 상담현황 ANL_AGT_01 
── 대시보드 ──
📖 운영정책 / 🌟 우수사례 / 🔔 공지
── 관리 ──
👤 내 계정
👥 직원관리 (접근 불가)
🔐 관리자 (ROLE_ADMIN) 메뉴
── 상담 업무 ──
📋 상담내역 CSL_RES_01
📤 결과서 전송 (접근 불가)
🔍 상담요약 SMR_DOC_01
📊 상담 분석 ANL_ALL_01 
── 대시보드 ──
📖 운영정책 / 🌟 우수사례 / 🔔 공지 (+ 관리)
── 관리 ──
👥 직원 계정 관리 MNG_EMP 
👤 내 계정
★ = 해당 역할 전용 항목 / 공통 항목은 양측 모두 표시
06 배치 & 이벤트 드리븐 설계
⚙️ Spring Application Event 패턴 — 결과서 수신 비동기 처리
상담사가 [📤 송신] 버튼을 클릭하면 API Server가 결과서를 MySQL에 저장한 즉시 200 OK를 반환합니다. AI 처리나 ES 색인 같은 무거운 작업은 비동기 이벤트로 분리하여 상담사 화면이 응답을 기다리지 않도록 합니다. 이를 통해 송신 API의 응답속도를 일정하게 유지합니다.
상담사 화면
📤 [송신] 버튼 클릭
STEP 1
API Server
MySQL 저장 완료
→ 200 OK 즉시 반환
STEP 2 · 동기
@ApplicationEvent
ConsultationReceived
Event 발행
STEP 3 · 비동기
Async Worker
카테고리 코드 확인
AI 호출 분기 판단
STEP 4
AI / IAM 저장
해지방어: AI 호출
그 외: IAM 저장
STEP 5
ES 색인
MongoDB 저장 완료
→ ES 색인 트리거
STEP 6
AI 호출 실패 시 consultation_analysis_status의 status를 AI_FAILED로 업데이트하고 retry_count를 증가시킵니다. 최대 재시도 초과 시 IAM 텍스트로 fallback 저장합니다. API 응답과 비동기 처리가 분리되어 있으므로 AI 실패가 콜센터 수신에 영향을 주지 않습니다.
📅 Batch 스케줄 설계
CRON: 0 0 2 * * * (매일 02:00)
📊 일별 리포트 Batch
  • consultation_results GROUP BY hour → 시간대별 상담량
  • customer_risk_logs → 당일 위험 고객 집계
  • ES Terms Aggregation → 당일 키워드 순위
  • IAM 텍스트 패턴 매칭 → 인사말/공감/마무리 비율 (regex)
  • → MongoDB: daily_report_snapshot 저장
  • → Redis: 스냅샷 캐시 갱신
CRON: 0 0 3 * * MON (매주 월 03:00)
📈 주별 리포트 Batch
  • 상담사별 상담건수·처리율 집계 → 순위 계산
  • consult_product_logs → 상품 선호도 분석
  • consultation_summary 키워드 ES 집계 → 주간 키워드
  • client_review → 상담사 만족도 집계
  • → MongoDB: weekly_report_snapshot 저장
  • → MongoDB: weekly_agent_report_snapshot 저장
CRON: 0 0 4 1 * * (매월 1일 04:00)
📆 월별 리포트 Batch + AI 인사이트
  • retention_analysis GROUP BY complaint_reason → 해지방어 패턴
  • customer_risk_logs 이상징후 고객 분류
  • 집계 숫자 → AI에 전달 (원문 없음, 최소 토큰)
  • AI → 인사이트 문장 1줄 ("해지 18% 증가, 요금 불만 주요원인...")
  • → MongoDB: monthly_report_snapshot 저장
  • Batch 후보 필터: 만족도+방어성공 기준 우수사례 후보 추출
On-demand (접근 시 즉시 경량 집계)
👤 상담사 개인 리포트 (ANL_AGT_01)
  • 해당 상담사의 consultation_results만 조회 (범위 한정)
  • 개인 건수·처리율·카테고리 분포 계산
  • consultation_summary에서 개인 키워드 집계
  • client_review 개인 만족도 평균
  • 전체 Batch 불필요 → DB 부하 거의 없음
  • 결과는 Redis 캐시 (TTL 1시간)
⚡ 이벤트 드리븐 처리 상태 흐름
상태값테이블전환 조건처리 주체설명
RECEIVED consultation_analysis_status API 결과서 수신 직후 API Server 결과서 수신 저장 완료. 비동기 이벤트 발행 대기.
PROCESSING consultation_analysis_status Worker 이벤트 수신 시작 Async Worker 카테고리 확인 및 처리 진행 중.
SKIP_AI consultation_analysis_status 비해지방어 카테고리 Async Worker AI 미호출. IAM 그대로 MongoDB 저장 완료.
PENDING_AI consultation_analysis_status 해지방어 카테고리 확인 Async Worker AI 호출 준비 완료. AI 응답 대기 중.
COMPLETED consultation_analysis_status AI 응답 수신 및 저장 완료 Async Worker MongoDB 저장 + ES 색인 완료. 전체 처리 완료.
AI_FAILED consultation_analysis_status AI 호출 실패 (retry_count 초과) Async Worker IAM 텍스트로 fallback 저장. AI 재처리 가능하도록 플래그 유지.
07 카테고리 분기 플로우
💡 핵심 원칙: AI 호출 여부는 DB 카테고리 코드로만 결정
ES 키워드 필터링이나 별도의 규칙 엔진 없이, 콜센터가 송신 시 함께 전달한 category_code와 DB에 하드코딩된 카테고리 정의만으로 AI 호출 여부를 판단합니다. 카테고리는 더미 데이터 형식으로 사전 정의되어 있어 런타임에 변경되지 않습니다.
STEP 1
📞
콜센터 송신
결과서 전송
category_code 포함
IAM + 대화원문
POST /receive
STEP 2
🗄️
MySQL 저장
consultation_results
category_code 그대로
저장
@Event 발행
STEP 3
🔀
카테고리 분기
DB 카테고리
코드 조회
해지방어 여부
IF/ELSE 판단
STEP 4A
🤖
AI 호출
해지방어 카테고리
대화원문 + IAM
one-shot 요청
비용 발생
STEP 4B
📄
IAM 저장
일반 카테고리
AI 호출 없음
IAM 텍스트 원문
그대로 저장
STEP 5
🍃
MongoDB 저장
consultation_summary
AI경로: summary,
keywords[] 포함
IAM경로: summary=IAM
STEP 6
🔍
ES 색인
Nori 형태소 분석
→ 토큰 분해
역색인 생성
전문검색 지원
📋 상담 결과서 화면 구성 (CSL_RES_01 — 조회 전용)
👤 고객 기본정보

고객명, 고객번호, 연락처, 가입 상품, 고객 등급, 계약 정보 등. 콜센터 시스템에서 수신된 그대로 표시.

📋 상담 기본정보

상담 일시, 담당 상담사, 카테고리(category_code), 처리상태, 상담시간, 채널(전화/채팅) 등.

📝 IAM (상담내용)

Issue: 고객 문의 요지. Action: 상담사 처리 내역. Memo: 특이사항 메모. 콜센터 상담사 작성본.

📎 첨부파일

콜센터에서 첨부한 관련 파일 목록. 파일명·유형·업로드 시각 표시. 다운로드 링크 제공.

💬 대화 원문

상담사-고객 간 전체 대화 텍스트. 시간 순 정렬. 발화자 구분(상담사/고객)하여 표시.

🤖 AI 분석결과 (해지방어만)

해지방어 카테고리인 경우에만 표시. AI 요약문, 추출 키워드, 불만사유, 방어성공여부.

🏷️ 카테고리 DB 하드코딩 방식

카테고리는 category_master 테이블에 더미 데이터 형식으로 사전 정의됩니다. 런타임에 변경되지 않으므로 Async Worker가 단순 IF/ELSE 분기만으로 처리합니다.

해지방어 여부를 나타내는 is_churn_defense 컬럼(Boolean)으로 분기합니다. WHERE is_churn_defense = true인 카테고리에 대해 AI를 호출합니다.

🔍 ES의 역할 재정리 (오해 방지)

ES는 AI 호출 분기와 무관합니다. AI 호출 여부는 오직 DB 카테고리 코드만으로 결정됩니다.

ES의 역할은 단 하나입니다: consultation_summary를 색인하여 SMR_DOC_01 전문검색을 지원하는 것. 키워드 검색 시 Nori 형태소 분석과 동의어 처리로 검색 정확도를 높입니다.

08 분석·요약 집계 시스템 상세 — 팀원 참고용
이 섹션은 분석·요약·리포트 기능의 설계 맥락을 팀원들이 이해할 수 있도록 작성되었습니다. "왜 이렇게 설계했는가"와 "어떤 데이터가 어디서 오는가"를 중심으로 설명합니다.
💰 AI 비용 최적화 구조
20~30%
AI 호출 대상 상담
해지·위험·우수사례 후보 상담만 AI 처리. 나머지 70~80%는 IAM 그대로 저장.
1회
상담당 AI 호출 횟수
요약+키워드+카테고리+불만사유를 한 번의 요청에 처리. 분리 호출 금지.
1줄
리포트 AI 결과물
집계된 숫자를 AI에 전달 → 인사이트 문장 1줄만 생성. 원문 없이 최소 토큰.
🎯 이 시스템은 무엇인가 — 팀원 공통 인식 확립

이 시스템은 콜센터가 아닙니다. 콜센터에서 상담이 완료된 결과서를 수신하여 분석하는 콜센터 분석 플랫폼입니다.

따라서 상담결과서를 작성하거나 등록하는 기능이 없습니다. React 화면에서 결과서를 조회할 수 있지만, 이는 콜센터에서 수신한 결과서를 랜덤 API로 불러와 표시하는 조회 전용입니다.

[송신] 버튼이 있는 페이지는 시연 목적의 콜센터 화면입니다. 실제 운영에서는 콜센터 시스템이 자동으로 POST /api/consultations/receive를 호출합니다. 이 페이지는 "콜센터 → 우리 시스템으로 어떻게 전달되는가"를 시각적으로 보여주기 위한 것입니다.

📊 리포트 각 항목의 데이터 원천

시간대별 상담량 → consultation_results.started_at, created_at GROUP BY hour (MySQL). Batch가 집계 → daily_report_snapshot.hourlyConsultCount.

키워드 순위 → ES의 consultation_summary 인덱스에 Terms Aggregation. AI 추출 키워드(해지상담)와 IAM Nori 토큰(일반상담)을 함께 집계. Batch가 실행 → snapshot 저장.

해지방어 분석 → retention_analysis 테이블 (MySQL). complaint_reason별 GROUP BY, 방어성공 비율 계산. AI가 원문에서 추출한 complaint_reason 값이 원천. Batch → monthly_report_snapshot.churnDefenseAnalysis.

상담사 순위·IAM 일치율 → consultation_results(MySQL)의 상담사별 건수·카테고리 + consultation_summary(MongoDB)의 ai_category와 비교. Batch → weekly_agent_report_snapshot.

고객 만족도 → client_review 테이블 (MySQL). 상담사별 평균 점수. Batch → monthly_agent_report_snapshot.customerSatisfactionAnalysis.

응대 품질 분석 (인사말·공감표현·마무리 비율) → consultation_raw_texts 원문에 정규식 패턴 매칭. AI 불필요. "안녕하세요", "죄송합니다", "감사합니다", "도움이 되셨나요" 등 사전 패턴으로 처리.

AI 인사이트 문장 → Batch가 위 숫자들을 모두 계산한 뒤, 숫자 요약(JSON 형태)만 AI에 전달. AI는 해석 문장 1개만 반환. 예: "이번 달 해지 시도 전월 대비 18% 증가, 요금 불만이 주요 원인으로 분석됩니다."

🎯 왜 리포트를 실시간으로 만들지 않는가

리포트 화면에서 "전체 분석" 버튼을 누를 때마다 MySQL과 MongoDB에 GROUP BY 집계 쿼리를 실행하면, 동시 사용자가 많은 시간대에 DB 부하가 급증합니다. 특히 월별 리포트처럼 수십만 건을 집계하는 쿼리는 수 초~수십 초가 걸릴 수 있습니다.

Batch 스냅샷 방식은 조회 시점에 DB 부하가 없습니다. 이미 계산된 Document를 MongoDB에서 읽는 것이기 때문에 응답 시간이 수십 ms 수준입니다. Redis 캐시를 추가하면 더 빠릅니다.

단점은 데이터 최신성입니다. 일별 리포트는 전날 데이터까지만 반영됩니다. 당일 데이터는 포함되지 않습니다. 이는 비즈니스 요구사항과 타협한 결과입니다. 실시간 대시보드가 필요한 항목(현재 처리 중 상담 수 등)은 별도 경량 API로 분리하는 것을 권장합니다.

👤 개인 리포트(ANL_AGT_01)가 Batch 없이 On-demand인 이유

전체 리포트는 모든 상담사의 데이터를 집계하므로 데이터 범위가 매우 넓습니다. 반면 개인 리포트는 한 명의 데이터만 조회하기 때문에 쿼리 범위가 극히 제한됩니다.

예를 들어 상담사 A의 이번 주 상담 건수·카테고리 분포·만족도 평균을 조회하는 쿼리는 consultation_results에서 emp_id = A인 데이터만 필터링하면 됩니다. 이는 인덱스로 충분히 빠르게 처리됩니다.

Batch로 미리 만들어두면 N명의 상담사 × 일/주/월 = 매우 많은 스냅샷이 생성되어 MongoDB 용량 낭비가 발생합니다. On-demand 방식이 훨씬 효율적입니다. 결과는 Redis에 1시간 TTL로 캐시합니다.

⭐ 우수상담 사례(DSH_BP) 생성 프로세스

우수사례는 AI가 자동으로 등록하지 않습니다. Batch → 관리자 → AI → 등록의 3단계를 거칩니다.

1단계 Batch 필터링: 매월 1일 Batch가 전월 AI 처리 상담(해지방어 성공 + client_review 점수 상위 10%)을 자동 필터링하여 "후보 목록"을 생성합니다. 이 목록은 관리자 화면에 노출됩니다.

2단계 관리자 선택 (DSH_BP_02): 관리자가 후보 목록을 검토하고 최종 우수사례로 등록할 상담을 선택합니다. 관리자의 판단이 개입하므로 AI 오판을 방지합니다.

3단계 AI 요약 생성: 관리자가 선택한 상담에 대해서만 AI를 호출하여 best_practices 테이블의 summary·title을 생성합니다. 이미 AI 처리된 상담이라면 consultation_summary의 summary를 재사용하여 AI 호출을 생략할 수 있습니다.

🔍 ES와 AI의 역할 구분 (팀원 오해 방지)

ES는 AI 호출 분기와 전혀 무관합니다. v2 구조에서는 ES 1차 키워드 필터링이 AI 호출 여부를 결정하는 역할을 했지만, 현재(v3) 구조에서 이 역할은 DB 카테고리 코드로 대체되었습니다.

ES의 유일한 역할은 SMR_DOC_01 전문검색 지원입니다. consultation_summary가 MongoDB에 저장될 때 ES에 동시 색인하며, 상담사가 키워드·기간·카테고리로 검색할 때 ES가 Nori 형태소 분석과 동의어 처리로 정확한 검색 결과를 제공합니다.

AI 호출 여부는 오직 category_code 하나로 결정됩니다. Async Worker가 category_master 테이블의 is_churn_defense 컬럼을 조회하여 true이면 AI를 호출하고, false이면 IAM을 그대로 저장합니다. ES 질의 없음, 키워드 매칭 없음.

🔮 향후 확장 고려사항
현재 카테고리 코드는 DB 하드코딩(더미 데이터)이므로 category_master 테이블의 is_churn_defense 값만 변경하면 AI 호출 범위를 즉시 조정할 수 있습니다. 별도 배포 없이 DB 업데이트만으로 운영 중 조정 가능합니다. 또한 콜센터 시스템이 다수로 확장되는 경우에도 /api/consultations/receive 엔드포인트가 단일 수신 창구이므로 API 인증 키만 추가 발급하면 됩니다. AI 엔진 교체(GPT-4o → Claude 등)도 Async Worker 내부 구현만 변경하면 되며 React·API·Batch에는 영향이 없습니다.

 

이상으로 마치겠습니다.