Skip to content

Conversation

@kgy1008
Copy link
Member

@kgy1008 kgy1008 commented Oct 21, 2025

📣 Jira Ticket

EDMT-456

👩‍💻 작업 내용

Spring AI 의존성 제거

  • edukit-external/build.gradle에서 Spring AI 의존성 제거
  • 기존 OpenAI 관련 클래스 삭제:
    • SpringAIConfig.java
    • OpenAIServiceImpl.java
    • OpenAIProperties.java
    • WebClientConfig.java
    • OpenAiErrorCode.java
    • OpenAiException.java

AI 이벤트 처리 구조 개선

  • AIEventListener 단순화: StudentRecordAITask 의존성 제거
  • AITaskCreateEventAIResponseGenerateEvent 데이터 구조 간소화
  • AI 작업 초기화 로직 개선: createAITask 메서드에서 작업 시작
  • 이벤트 핸들링 로직 스트림라인화

변경 통계

  • 13개 파일 수정
  • 355줄 삭제, 25줄 추가
  • 영향 받은 모듈: edukit-api, edukit-core, edukit-external

📝 리뷰 요청 & 논의하고 싶은 내용

  1. AI 이벤트 구조 변경: StudentRecordAITask 의존성을 제거하고 이벤트 데이터를 단순화했습니다. 이로 인해 결합도가 낮아지고 유지보수성이 향상되었는지 확인 부탁드립니다.

  2. Spring AI 제거 영향: Spring AI 의존성 제거가 기존 AI 기능에 영향을 주지 않는지 검토 부탁드립니다.

  3. 초기화 로직: AI 작업을 생성 시점에 바로 시작하도록 변경했는데, 비즈니스 로직상 문제가 없는지 확인 부탁드립니다.

Test Plan

✅ Manual Testing Checklist

  • AI 작업 생성 시 정상적으로 초기화되는지 확인
  • AI 이벤트 발생 시 리스너가 정상적으로 응답하는지 확인
  • StudentRecord AI 기능이 정상 동작하는지 확인
  • AI 응답 생성 이벤트가 올바르게 처리되는지 확인
  • 기존 AI 관련 API 엔드포인트 정상 동작 확인

🧪 Automated Tests

  • Unit tests pass: ./gradlew test
  • Integration tests pass
  • Build succeeds: ./gradlew build
  • AI 관련 서비스 테스트 통과 확인
  • 이벤트 리스너 테스트 통과 확인

🔍 Code Quality

  • Code review completed
  • No new warnings or errors
  • Security considerations reviewed
  • 불필요한 의존성 제거로 인한 빌드 성능 개선 확인
  • 삭제된 클래스에 대한 참조가 남아있지 않은지 확인

Deployment Notes

  • Spring AI 의존성 제거로 인한 런타임 영향 없음 확인
  • 기존 AI 기능 정상 동작 확인 필요
  • 환경 변수 변경 사항 없음
  • 데이터베이스 마이그레이션 불필요

🤖 Generated with Claude Code

Summary by CodeRabbit

릴리스 노트

  • 개선사항

    • AI 작업이 생성 시 자동으로 시작됩니다.
  • 리팩터링

    • AI 작업 처리 인프라가 최적화되었습니다.
    • 내부 이벤트 처리 구조가 단순화되었습니다.

@coderabbitai
Copy link

coderabbitai bot commented Oct 21, 2025

워크스루

AI 스트리밍 및 OpenAI 통합을 제거하고, 이벤트 페이로드를 단순화하여 작업 ID 기반 비동기 처리로 리팩토링했습니다. Spring AI 의존성, 관련 설정, 서비스 인터페이스를 제거하고 직접 SQS 메시징으로 전환했습니다.

변경 사항

그룹 / 파일 변경 요약
이벤트 페이로드 단순화
edukit-api/src/main/java/com/edukit/studentrecord/event/AITaskCreateEvent.java, edukit-core/src/main/java/com/edukit/core/event/ai/AIResponseGenerateEvent.java
이벤트 필드를 StudentRecordAITask 객체에서 String taskId로 변경. task() 메서드 제거 및 taskId() 메서드 추가. 팩토리 메서드 시그니처 업데이트.
파사드 및 리스너 리팩토링
edukit-api/src/main/java/com/edukit/studentrecord/facade/StudentRecordAIFacade.java, edukit-core/src/main/java/com/edukit/core/event/ai/AIEventListener.java
StudentRecordAIFacade.createTaskId에서 이벤트 페이로드를 taskId 문자열로 전달. AIEventListener에서 복잡한 스트리밍 처리 로직을 제거하고 단순 SQS 메시징으로 변경. 중첩 레코드 AITask 추가.
작업 서비스 자동화
edukit-core/src/main/java/com/edukit/core/studentrecord/service/AITaskService.java
createAITask에서 aiTask.start() 자동 호출 추가. startTask 공개 메서드 제거.
AI 서비스 인터페이스 제거
edukit-core/src/main/java/com/edukit/core/common/service/AIService.java
AIService 인터페이스 파일 전체 삭제. getVersionedStreamingResponse(String) 메서드 및 관련 임포트 제거.
OpenAI 구현 제거
edukit-external/src/main/java/com/edukit/external/ai/service/OpenAIServiceImpl.java
스트리밍 버전 응답, MDC 컨텍스트 관리, 청크 버퍼링, 버전 감지 로직을 포함한 OpenAIServiceImpl 클래스 삭제.
Spring AI 설정 제거
edukit-external/src/main/java/com/edukit/external/ai/config/SpringAIConfig.java, edukit-external/src/main/java/com/edukit/external/ai/setting/WebClientConfig.java
SpringAIConfig 설정 클래스 및 ChatClient 빈 메서드 삭제. WebClientConfig와 관련 웹클라이언트 커스터마이저 삭제.
OpenAI 예외 및 설정 제거
edukit-external/src/main/java/com/edukit/external/ai/exception/OpenAiErrorCode.java, edukit-external/src/main/java/com/edukit/external/ai/exception/OpenAiException.java, edukit-external/src/main/java/com/edukit/external/ai/setting/OpenAIProperties.java
OpenAiErrorCode 열거형, OpenAiException 예외 클래스, OpenAIProperties 설정 레코드 파일 삭제.
의존성 제거
edukit-external/build.gradle
Spring AI 스타터 의존성(org.springframework.ai:spring-ai-starter-model-openai:1.0.0-M7) 제거.

시퀀스 다이어그램

sequenceDiagram
    participant Client
    participant Facade as StudentRecordAIFacade
    participant EventBus as Event Bus
    participant Listener as AIEventListener
    participant SQS as SQS Service
    
    Note over Client,SQS: 변경 후 흐름: 작업 ID 기반 비동기 처리
    
    Client->>Facade: createTaskId(userPrompt, requestPrompt, byteCount)
    Facade->>Facade: task = createTask(...)
    Facade->>Facade: taskId = task.getId()
    Facade->>EventBus: AITaskCreateEvent.of(taskId, userPrompt, requestPrompt, byteCount)
    Facade-->>Client: TaskResponse with taskId
    
    rect rgb(220, 240, 220)
        Note over EventBus,SQS: 이벤트 처리
        EventBus->>Listener: handleTaskCreateEvent(event)
        Listener->>Listener: taskId = event.taskId()
        Listener->>Listener: AITask(userPrompt, requestPrompt, byteCount)
        Listener->>SQS: send(AITask)
        SQS-->>Listener: ✓ Sent
    end
Loading

예상 코드 리뷰 노력

🎯 4 (복잡도 높음) | ⏱️ ~50분

분석:

  • 여러 파일에 걸친 이질적인 변경사항: 이벤트 페이로드 단순화, 서비스 인터페이스 제거, 스트리밍 로직 삭제, 설정 제거
  • OpenAIServiceImpl 삭제로 인한 복잡한 로직 영향도: MDC 관리, 청크 버퍼링, 버전 감지 등
  • AIEventListener 대폭 리팩토링: 조건부 빈 와이어링 변경, 복잡한 처리 단순화
  • 여러 설정 파일 및 예외 클래스 제거로 인한 의존성 체인 검증 필요
  • 자동 작업 시작 로직 추가로 인한 라이프사이클 변경 영향 검토 필요

관련 PR

추천 라벨

✏️ refactoring

추천 리뷰어

  • TaegeunYou

🐰 스트리밍 흐름은 가고, 단순함이 남아있고,
작업 ID로 가볍게 날아가는 메시지들,
OpenAI 설정 모두 치워지고 난 후,
깔끔한 비동기 파이프라인 완성!
SQS로 향하는 길, 이제 더 빠르네 🚀

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title Check ✅ Passed 제목 "EDMT-456 Spring AI 의존성 제거 및 AI 이벤트 처리 구조 개선"은 changeset의 주요 변경사항을 정확하게 반영하고 있습니다. 실제 변경 내용을 보면 Spring AI 의존성 제거와 6개의 OpenAI 관련 클래스 삭제, 그리고 AI 이벤트 처리 로직의 단순화가 이루어졌으며, 제목에서 이 두 가지 핵심 내용을 명확하게 전달하고 있습니다. 또한 이슈 번호(EDMT-456)도 포함되어 있어 추적성이 좋습니다. 제목은 간결하면서도 구체적이어서 팀원들이 커밋 히스토리에서 주요 변경사항을 쉽게 파악할 수 있습니다.
Description Check ✅ Passed PR 설명이 제공된 template의 모든 필수 섹션을 충실하게 포함하고 있습니다. Jira 이슈 번호(EDMT-456)가 명시되었고, 작업 내용 섹션에서는 Spring AI 의존성 제거와 AI 이벤트 처리 구조 개선에 대해 구체적으로 설명되어 있으며, 변경 통계도 포함되어 있습니다. 리뷰 요청 및 논의하고 싶은 내용에서는 3가지 구체적인 검토 포인트를 제시하고 있으며, 추가로 상세한 테스트 계획과 배포 노트를 제공하여 검토자가 변경사항의 영향과 검증 항목을 명확히 이해할 수 있도록 구성되어 있습니다.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch refac/EDMT-456

Comment @coderabbitai help to get the list of available commands and usage tips.

@kgy1008 kgy1008 self-assigned this Oct 21, 2025
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
edukit-core/src/main/java/com/edukit/core/event/ai/AIEventListener.java (1)

22-32: 불필요한 String.valueOf() 호출

라인 23에서 String.valueOf(generateEvent.taskId())를 사용하고 있습니다. AIResponseGenerateEvent.taskId()는 이미 String을 반환하므로 String.valueOf() 변환이 불필요합니다.

다음과 같이 직접 사용하는 것을 권장합니다:

-    String taskId = String.valueOf(generateEvent.taskId());
+    String taskId = generateEvent.taskId();

만약 null 안전성이 필요하다면, 인터페이스 계약에서 taskId가 non-null임을 명시하거나 명시적인 null 체크를 추가하는 것이 더 명확합니다.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0015708 and 8dabcf3.

📒 Files selected for processing (13)
  • edukit-api/src/main/java/com/edukit/studentrecord/event/AITaskCreateEvent.java (1 hunks)
  • edukit-api/src/main/java/com/edukit/studentrecord/facade/StudentRecordAIFacade.java (1 hunks)
  • edukit-core/src/main/java/com/edukit/core/common/service/AIService.java (0 hunks)
  • edukit-core/src/main/java/com/edukit/core/event/ai/AIEventListener.java (1 hunks)
  • edukit-core/src/main/java/com/edukit/core/event/ai/AIResponseGenerateEvent.java (1 hunks)
  • edukit-core/src/main/java/com/edukit/core/studentrecord/service/AITaskService.java (1 hunks)
  • edukit-external/build.gradle (0 hunks)
  • edukit-external/src/main/java/com/edukit/external/ai/config/SpringAIConfig.java (0 hunks)
  • edukit-external/src/main/java/com/edukit/external/ai/exception/OpenAiErrorCode.java (0 hunks)
  • edukit-external/src/main/java/com/edukit/external/ai/exception/OpenAiException.java (0 hunks)
  • edukit-external/src/main/java/com/edukit/external/ai/service/OpenAIServiceImpl.java (0 hunks)
  • edukit-external/src/main/java/com/edukit/external/ai/setting/OpenAIProperties.java (0 hunks)
  • edukit-external/src/main/java/com/edukit/external/ai/setting/WebClientConfig.java (0 hunks)
💤 Files with no reviewable changes (8)
  • edukit-external/build.gradle
  • edukit-external/src/main/java/com/edukit/external/ai/setting/OpenAIProperties.java
  • edukit-external/src/main/java/com/edukit/external/ai/service/OpenAIServiceImpl.java
  • edukit-external/src/main/java/com/edukit/external/ai/exception/OpenAiErrorCode.java
  • edukit-external/src/main/java/com/edukit/external/ai/exception/OpenAiException.java
  • edukit-core/src/main/java/com/edukit/core/common/service/AIService.java
  • edukit-external/src/main/java/com/edukit/external/ai/setting/WebClientConfig.java
  • edukit-external/src/main/java/com/edukit/external/ai/config/SpringAIConfig.java
🔇 Additional comments (6)
edukit-core/src/main/java/com/edukit/core/event/ai/AIResponseGenerateEvent.java (1)

5-5: 좋은 개선사항입니다!

인터페이스 메서드를 task()에서 taskId()로 변경하고 반환 타입을 StudentRecordAITask에서 String으로 단순화한 것은 결합도를 낮추고 이벤트 구조를 개선하는 좋은 변경입니다. 전체 객체 대신 식별자만 전달하는 것이 이벤트 패턴의 모범 사례와 일치합니다.

edukit-api/src/main/java/com/edukit/studentrecord/event/AITaskCreateEvent.java (1)

5-15: 이벤트 구조 단순화가 잘 적용되었습니다!

레코드 필드를 StudentRecordAITask task에서 String taskId로 변경하고 팩토리 메서드 시그니처를 그에 맞게 업데이트한 것은 명확하고 일관성 있는 개선입니다. 이벤트가 도메인 엔티티 전체 대신 식별자만 전달하도록 개선되어 결합도가 감소했습니다.

edukit-core/src/main/java/com/edukit/core/event/ai/AIEventListener.java (2)

15-15: 의존성 단순화가 적절합니다!

@ConditionalOnBean에서 AIService.class를 제거하고 SqsService.class만 유지한 것은 Spring AI 의존성 제거 목표와 일치하며 적절한 변경입니다.


34-40: AITask 레코드 설계가 깔끔합니다!

SQS 페이로드를 표현하기 위한 private record AITask의 설계가 명확하고 간결합니다. 불변 데이터 구조로 필요한 정보만 담고 있으며, taskId는 메시지 속성으로 별도 전달하는 구조가 합리적입니다.

edukit-api/src/main/java/com/edukit/studentrecord/facade/StudentRecordAIFacade.java (1)

40-42: 원본 리뷰 코멘트는 부정확합니다

코드 검증 결과:

  • StudentRecordAITask@GeneratedValue(strategy = GenerationType.IDENTITY)를 사용합니다
  • IDENTITY 전략에서 JPA는 save() 호출 후 자동으로 생성된 ID를 엔티티에 설정합니다
  • createAITask() 메서드가 @Transactional이므로 반환되는 task의 ID는 항상 non-null입니다
  • String.valueOf(task.getId())는 안전합니다

원본 코멘트의 우려사항(null ID 반환 가능성)은 IDENTITY 전략의 작동 방식에 대한 오해입니다. 현재 코드는 올바르게 작동합니다.

Likely an incorrect or invalid review comment.

edukit-core/src/main/java/com/edukit/core/studentrecord/service/AITaskService.java (1)

19-24: 원본 리뷰 코멘트는 부정확합니다

StudentRecordAITask.start() 메서드의 실제 구현을 확인한 결과, 원본 리뷰 코멘트의 우려사항들이 모두 해당되지 않습니다:

public void start() {
    this.startedAt = LocalDateTime.now();
}
  • start() 메서드는 getId() 를 호출하지 않으며, 단순히 startedAt 필드에 현재 시간을 설정합니다.
  • 외부 시스템 호출이나 복잡한 로직이 없으므로 트랜잭션 안전성 문제가 없습니다.
  • save() 전에 start() 를 호출하는 순서는 안전하며, 이는 의도적인 변경입니다.

Likely an incorrect or invalid review comment.

@kgy1008 kgy1008 merged commit 3013dc7 into develop Oct 21, 2025
2 checks passed
@kgy1008 kgy1008 deleted the refac/EDMT-456 branch October 21, 2025 05:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants