Skip to content

feat: AI 톤 교정 준비 - 출력 토큰 수 · 회원 존재 확인 · 에러 코드 · 요청 검증 (#65 1/3) - #85

Merged
chjpooh2002 merged 3 commits into
developfrom
feat/65-tone-correction-prep
Nov 13, 2026
Merged

chjpooh2002 merged 3 commits into
developfrom
feat/65-tone-correction-prep

Conversation

@chjpooh2002

@chjpooh2002 chjpooh2002 commented Nov 10, 2026 •

Copy link
Copy Markdown
Contributor

관련 이슈

작업 내용

#65가 약 1,220줄이라 세 PR로 나눴습니다. 순서대로 병합해 주세요.
① 준비 #85 (이 PR, develop 대상) → ② 서비스 #86 (① 브랜치 대상) → ③ API·문서 #87 (② 브랜치 대상)

  • 커밋: b1ace28, 1c1e631, 1fb4056
  • 언어 모델 응답에 출력 토큰 수 추가 (global/client/llm, 디스코드 공유함)
    • LanguageModelResult(text, refused, outputTokens)
    • Anthropic 응답의 usage.output_tokens를 읽음. usage나 값이 없으면 0 (잭슨 3에서 원시 타입 누락으로 실패하지 않게 Integer로 받음)
    • FakeLanguageModelClient는 0
    • 운영에서 응답 시간과 출력 토큰 수를 로그로 확인하기 위함 ([feat] AI 톤 교정 문체 열거형 · 문체별 지시문 #64: 3000자 원문 11~16초, 20초 제한까지 여유 약 4초)
  • 회원 존재 확인 UserQueryService.validateActive(Long userId)
    • 없거나 탈퇴한 회원이면 USER404_1
    • 없는 회원 번호로 사용량을 선점하면 외래 키 위반으로 500이 나서, 선점 전에 부르기 위함
    • CLAUDE.md 도메인 사이 연결 지점 표에 한 줄 추가 (user → ai)
  • AiErrorCode에 AI400_1~3, AI422_1, AI502_1, AI504_1 추가 (문구는 명세 그대로)
  • 요청 검증 어노테이션 (domain/ai/annotation)
    • @ValidToneStyle: ToneStyle 상수 이름과 대소문자까지 같을 때만 통과. 아니면 AI400_1 (요청 필드를 열거형으로 받으면 없는 값이 JSON 변환 실패로 COMMON400_1이 되기 때문)
    • @ValidToneText: null·빈 값·공백만(TextWhitespace 기준, NBSP·BOM 포함)이면 AI400_2, String.length() 3000 초과면 AI400_3. 정규화하지 않고 받은 그대로 셈

명세와 달라진 점

없음

테스트

  • 출력 토큰 수: 응답 값을 그대로 돌려줌(거절 응답 포함), usage 없음·output_tokens 없음·usage: null이면 0이고 결과는 정상, 가짜 구현은 0
  • 회원 존재 확인: 정상 회원 통과, 없는 회원·탈퇴 회원은 USER404_1
  • 에러 코드: 7개 모두 명세의 HTTP 상태·코드·문구와 같음, 명세에 없는 코드 없음
  • @ValidToneStyle: 6개 문체 통과, null·빈 값·공백·ESSAY·소문자·앞뒤 공백·없는 값은 AI400_1
  • @ValidToneText: null·빈 값·공백만(NBSP·BOM·전각 공백·줄바꿈)은 AI400_2, 3000자 통과·3001자 AI400_3, 자모 분리형도 받은 그대로 셈

확인 체크리스트

  • ./gradlew build 통과
  • 테스트 포함
  • 변경 400줄 안팎 (+412 −19)
  • 병합된 마이그레이션 수정 안 함
  • 비밀 값·개인정보 없음
  • global 공통 코드를 바꿨다면 디스코드에 공유함 (global/client/llm 출력 토큰 수)

리뷰어에게

[중점] LanguageModelResult에 필드를 추가한 global 변경, @ValidToneStyle을 문자열로 받는 판단

@chjpooh2002 chjpooh2002 added feature 기능 개발 ai AI 톤 교정 user 내 정보·사용량·플랜 판정 global 공통 응답·예외·보안 설정 labels Nov 10, 2026
@chjpooh2002 chjpooh2002 self-assigned this Nov 11, 2026

@oTAETAEo oTAETAEo left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

리뷰가 늦었습니다 고생하셨어여 👏

if (text == null || TextWhitespace.isBlank(text)) {
return reject(context, AiErrorCode.TEXT_EMPTY);
}
if (text.length() > MAX_LENGTH) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

원문 길이를 정규화 없이 세는 건 본문에 적어 주셔서 확인했는데, 화면 톤 교정 입력창도 같은 기준으로 세는지만 프론트랑 맞춰 보면 좋을 것 같아요 !

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

서버는 String.length() 기준이라 이모지는 2자, 줄바꿈은 1자로 셉니다. 프론트에서 입력창 최대 길이 속성이나 value.length로 세면 같은 기준이라 어긋나지 않을 것 같은데, 프론트에 한번 확인해 보겠습니다!

* @param outputTokens 출력 토큰 수 (생각 토큰 포함). 응답에 없으면 0
*/
public record LanguageModelResult(String text, boolean refused) {
public record LanguageModelResult(String text, boolean refused, int outputTokens) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LanguageModelResult에 필드를 추가한 global 변경

좋은 것 같아요 ! global이 도메인을 참조하지 않고, usage나 output_tokens가 없어도 0으로 받아서 응답 처리가 깨지지 않는 것 확인했습니다 👍


/**
* 요청 객체의 문체 검증. null·빈 값·ToneStyle 상수 이름과 정확히 같지 않은 값(소문자 포함)이면 AI400_1.
* 요청 필드를 ToneStyle로 받으면 없는 값이 JSON 변환 실패(COMMON400_1)가 되므로, 문자열로 받아 이것으로 검사한다.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@ValidToneStyle을 문자열로 받는 판단

적절한 것 같아여ToneStyle로 바로 받으면 없는 값이 JSON 변환 실패로 COMMON400_1이 돼서, 명세의 "style 누락 또는 값 오류 → AI400_1"을 못 맞추는 걸로 이해했습니당 대소문자까지 정확히 비교하는 것도 명세 값과 맞습니다아

@chjpooh2002
chjpooh2002 merged commit dae1d63 into develop Nov 13, 2026
1 check passed
@chjpooh2002
chjpooh2002 deleted the feat/65-tone-correction-prep branch November 13, 2026 04:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai AI 톤 교정 feature 기능 개발 global 공통 응답·예외·보안 설정 user 내 정보·사용량·플랜 판정

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants