본문 바로가기

카테고리 없음

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

현재 융합프로젝트를 진행중으로 이제 백엔드 개발이 거의 끝나 프론트엔드와 작업을 함께 하며

디버그 하고 api 수정을 하고 있다.

현재 내가 구현한 기능 바탕으로 나온 화면들

 

아웃바운드 일때 AI분석결과

인바운드이면서 해지관련 카테고리가 아닐때

해지관련 카테고리일때 나오는 AI 결과 페이지

우수상담 관련 점수 추출 및 선정 사유 페이지

 

관련 내가 개발한 코드 내용

🛠️ AI 분석 시스템 핵심 로직 가이드

1. 중복 실행을 방지하는 '원자적 문지기' (Scheduler)

배치 시스템에서 가장 무서운 건 이전 작업이 안 끝났는데 다음 작업이 또 돌아가는 것이죠. 🥊

Java
 
// IntegratedAnalysisScheduler.java
if (!isProcessing.compareAndSet(false, true)) {
    log.warn("[Batch] 이전 통합 분석 작업이 아직 진행 중입니다. 건너뜁니다.");
    return;
}
  • 코드 포인트: AtomicBoolean의 compareAndSet을 사용하여 Thread-safe하게 실행 상태를 체크합니다. 🥊
  • 설명: synchronized보다 가볍게 동작하며, 분산 환경이 아닌 단일 인스턴스 배치 환경에서 가장 효율적으로 중복 실행을 차단하는 기법입니다.

2. 성능을 극대화하는 '비동기 병렬 처리' (Manager)

상담 요약과 품질 채점은 서로 의존성이 없는 독립적인 작업입니다. 이걸 순서대로 하면 시간이 두 배로 걸리죠. 🥊

Java
 
// ConsultationAnalysisManager.java
CompletableFuture<List<AiExtractionResponse>> extractionFuture = CompletableFuture.supplyAsync(() ->
    geminiExtractor.extractBatch(processedRawTexts, groupType, validCodes), geminiTaskExecutor
);

List<CompletableFuture<QualityScoringResponse>> scoringFutures = processedRawTexts.stream()
    .map(text -> CompletableFuture.supplyAsync(() -> geminiQualityScorer.evaluate(text, manualContent), geminiTaskExecutor))
    .toList();
  • 코드 포인트: CompletableFuture.supplyAsync와 커스텀 Executor를 활용했습니다. 🥊
  • 설명: 요약(Batch 호출)과 채점(Individual 호출)을 동시에 날려 전체 처리 시간을 I/O 대기 시간 수준으로 단축시켰습니다. 🥊 join()을 통해 모든 결과가 올 때까지 기다린 후 트랜잭션을 마무리하는 정교한 설계입니다.

3. 비용과 효율을 잡는 '프롬프트 번들링' (Extractor)

AI API 비용은 호출 횟수당 기본 요금이 붙는 경우가 많습니다. 🥊

Java
 
// GeminiExtractor.java
private String buildChnBatchPrompt(List<String> issues, String compCodes, String defCodes) {
    sb.append(String.format("... 아래 %d건의 리스트를 분석하여 JSON 배열로 응답하세요.", issues.size()));
    for (int i = 0; i < issues.size(); i++) {
        sb.append(String.format("\n[%d] 원문: \"%s\"\n", i, issues.get(i)));
    }
}
  • 코드 포인트: 여러 건의 상담 원문을 StringBuilder로 묶어 하나의 요청(Prompt)으로 구성했습니다. 🥊
  • 설명: 10번 부를 걸 1번만 불러도 되니 API 비용은 절감되고, 한 번의 컨텍스트 안에서 AI가 일관된 기준으로 여러 건을 비교 분석하게 유도했습니다. 🥊

4. 시스템의 자생력, '좀비 데이터 구출' (Recovery)

네트워크 순단이나 예상치 못한 종료로 PROCESSING 상태에 영원히 갇힌 데이터를 처리해야 합니다. 🥊

Java
 
// IntegratedRetryScheduler.java
LocalDateTime threshold = LocalDateTime.now().minusMinutes(30);
int cleanedResult = resultEventRepository.cleanupStaleProcessingTasks(threshold);
  • 코드 포인트: 현재 시각 기준 30분 전 데이터를 조회해 상태를 강제로 리셋하는 cleanup 로직입니다. 🥊
  • 설명: 일시적인 장애로 멈춘 데이터를 수동 개입 없이 시스템이 스스로 복구하게 만듭니다. 안정적인 운영을 위한 '최후의 보루' 같은 코드죠. 🥊

 

 

우수 상담 관련 api 개발후 나온 화면들


💎 AI 우수 상담 선정 및 게시판 운영 시스템

이 시스템은 AI가 1차로 선별한 우수 상담 후보(ConsultationEvaluation)를 관리자가 검토하고, 최종 선정된 건들을 주간 베스트 게시판(WeeklyExcellentCase)에 박제하여 모든 상담사가 학습할 수 있게 돕는 선순환 품질 관리 시스템입니다. 🥊


🛠️ 주요 컴포넌트별 역할 분석 (Code-Level)

1. 관리자의 검토와 결정: ExcellentCaseAdminController

관리자가 후보군을 훑어보고 "이건 진짜 베스트다!" 혹은 "이건 좀 부족하다"를 결정하는 입구입니다. 🥊

  • getCandidates (후보군 리스트 조회):
    • 역할: AI 점수가 높은 후보들을 페이징 처리하여 보여줍니다.
    • 특징: @ParameterObject를 통해 검색 조건(상태, 연도, 주차)을 깔끔하게 넘겨받아 복잡한 필터링 조회를 수행합니다. 🥊
  • selectExcellentCase & rejectExcellentCase:
    • 역할: 후보를 최종 확정하거나 제외합니다.
    • 포인트: 단순한 상태 변경을 넘어, 실제 게시판 데이터 생성/삭제로 이어지는 트리거 역할을 합니다. 🥊

2. 비즈니스 로직의 핵심: ExcellentCaseAdminService

상태 변화에 따른 데이터 정합성을 책임지는 '집행관'입니다. 🥊

  • registerExcellentCase (최종 선정 로직):
    • 코드 포인트: AI 평가 테이블의 상태만 바꾸는 게 아니라, WeeklyExcellentCase라는 별도의 스냅샷 테이블에 데이터를 복사하여 게시판용 데이터를 독립적으로 관리합니다. 🥊
  • Java
     
    // 엔티티 조회 및 후보 자격 검증
    if (!evaluation.isCandidate()) throw new BusinessException(ErrorCode.NOT_A_CANDIDATE);
    
    // 상태 업데이트 및 주간 베스트 테이블 저장 (이력 관리)
    evaluation.updateSelectionStatus(SelectionStatus.SELECTED);
    WeeklyExcellentCase weeklyCase = WeeklyExcellentCase.builder()...build();
    weeklyRepository.save(weeklyCase);
    
  • rejectExcellentCase (제외 로직):
    • 특징: 이미 선정된 건을 나중에 취소(Reject)할 경우, 게시판 테이블에서도 해당 데이터를 함께 삭제(deleteByConsultId)하여 데이터 싱크를 맞춥니다. 🥊

3. 상담사들의 배움터: WeeklyExcellentCaseController

선정된 베스트 상담 사례를 모든 상담사가 볼 수 있는 '명예의 전당' API입니다. 🥊

  • getWeeklyBoard:
    • 역할: 연도와 주차별로 필터링된 "검증된 우수 사례" 리스트를 반환합니다.
    • 포인트: 관리자가 입력한 **'선정 사유(adminReason)'**를 함께 보여주어, 상담사들이 어떤 점을 배워야 하는지 가이드라인을 제시합니다. 🥊

💡 기술 블로그를 위한 '인사이트' 섹션 (Blog Summary)

  1. 데이터 무결성과 멱등성: registerExcellentCase에서 이미 선정된 건인지 체크하는 로직을 통해, 관리자의 중복 클릭이나 시스템 오류에도 게시판에 동일 데이터가 중복 생성되지 않도록 설계했습니다. 🥊
  2. 시간 축 기반의 필터링: r.createdAt(상담 일시)을 기준으로 연도와 주차를 계산하여 조회함으로써, "평가된 시점"이 아닌 "고객과 실제 상담한 시점" 중심의 통계를 제공합니다. 🥊
  3. 관리자-상담사 협업 구조: AI는 후보만 추천하고 최종 결정은 사람이 함으로써, 인공지능의 효율성과 인간의 전문성을 결합한 Human-in-the-loop 모델을 구현했습니다. 🥊

 

그 외에 나온 화면들

 

추후 개발해야되는 화면들

-> 내가 매뉴얼 api 바탕 crud되는 화면 및 결과서 작성시 오른쪽에 메뉴얼 관련 띄어주기

분석관련 화면들

 

이번주 느낀점

 

확실히 프론트엔드랑 협업을 하면서 진행하다보니깐 협업이라는 것이 얼마나 섬세한 작업인지 느끼는 한 주가 된 것 같다.