Skip to content

[FEAT] 라이브 코테#359

Merged
unifolio0 merged 2 commits into
developfrom
feat/live-coding
Jun 14, 2026
Merged

[FEAT] 라이브 코테#359
unifolio0 merged 2 commits into
developfrom
feat/live-coding

Conversation

@unifolio0

Copy link
Copy Markdown
Contributor

closed #

작업 내용

스크린샷

참고 사항

@unifolio0 unifolio0 self-assigned this Jun 14, 2026
@coderabbitai

coderabbitai Bot commented Jun 14, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@unifolio0, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 39 minutes and 37 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 059342a7-af6f-4de1-b9e9-fb6ada524823

📥 Commits

Reviewing files that changed from the base of the PR and between e7bcf85 and 50cafba.

📒 Files selected for processing (5)
  • src/main/java/com/samhap/kokomen/interview/domain/RootQuestion.java
  • src/main/java/com/samhap/kokomen/interview/service/InterviewStartFacadeService.java
  • src/test/java/com/samhap/kokomen/interview/domain/RootQuestionTest.java
  • src/test/java/com/samhap/kokomen/interview/repository/RootQuestionRepositoryTest.java
  • src/test/java/com/samhap/kokomen/interview/service/LiveCodingInterviewServiceTest.java

Walkthrough

RootQuestionType (GENERAL/CODE) 및 InterviewType.LIVE_CODING 열거형을 추가하고, RootQuestion에 코딩 문제용 필드(questionType, title)와 팩토리/헬퍼 메서드를 추가합니다. DB 스키마, 리포지토리 쿼리, 서비스 로직, Bedrock/GPT AI 프롬프트 상수를 모두 라이브 코딩 인터뷰 타입을 지원하도록 확장하며, 컨텐츠 길이 제한을 상향하고 관련 테스트를 추가합니다.

Changes

Live Coding Interview Feature

Layer / File(s) Summary
도메인 타입 및 엔티티 필드 확장
src/main/java/com/samhap/kokomen/interview/domain/RootQuestionType.java, src/main/java/com/samhap/kokomen/interview/domain/InterviewType.java, src/main/java/com/samhap/kokomen/interview/domain/RootQuestion.java, src/main/java/com/samhap/kokomen/interview/domain/Interview.java, src/main/java/com/samhap/kokomen/interview/domain/Question.java, src/main/java/com/samhap/kokomen/answer/domain/Answer.java, src/main/java/com/samhap/kokomen/interview/service/dto/AnswerRequestV2.java
RootQuestionType enum 신규 추가, InterviewType.LIVE_CODING 상수 추가, RootQuestionquestionType/title 필드와 forCode 팩토리·isCode·createInitialQuestionContent 메서드 추가, InterviewInterviewType 오버로드 생성자 및 isLiveCoding 추가, Question/Answer content 컬럼 길이 제한 해제.
DB 스키마 마이그레이션
src/main/resources/db/migration/V49__add_live_coding_question_type_and_widen_content.sql
root_questionquestion_type ENUM(기본값 GENERAL) 및 title VARCHAR(255) 컬럼 추가, root_question/question content를 TEXT NOT NULL로, answer content를 VARCHAR(10000) NOT NULL로 변경.
API DTO 계약 확장
src/main/java/com/samhap/kokomen/interview/service/dto/InterviewRequest.java, src/main/java/com/samhap/kokomen/interview/service/dto/RootQuestionResponse.java
InterviewRequestincludeLiveCoding Boolean 필드 추가(null이면 false), RootQuestionResponsequestionType/title 필드 추가 및 from() 팩토리 갱신.
RootQuestionRepository questionType 필터 확장
src/main/java/com/samhap/kokomen/interview/repository/RootQuestionRepository.java
findFirst/findLast JPQL 쿼리에 r.questionType = :questionType 조건 추가, findAllByStateAndQuestionType 메서드 신규 추가.
인터뷰 시작 서비스 분기 처리
src/main/java/com/samhap/kokomen/interview/service/InterviewStartFacadeService.java
CODE 루트 질문 + VOICE 모드 조합 유효성 검증, resolveInterviewType 헬퍼로 InterviewType 결정 후 Interview 생성, 첫 Question 내용을 createInitialQuestionContent()로 초기화.
RootQuestionService 랜덤 조회 분기
src/main/java/com/samhap/kokomen/interview/service/question/RootQuestionService.java
게스트 랜덤 조회에 GENERAL 필터 적용, includeLiveCoding=true 시 CODE 타입 포함 랜덤 선택 분기, private getRandomGeneralActiveRootQuestion 헬퍼 추가.
라이브 코딩 전용 AI 프롬프트 상수
src/main/java/com/samhap/kokomen/interview/tool/CodingInterviewPromptFragments.java, src/main/java/com/samhap/kokomen/interview/tool/CodingInterviewBedrockSystemMessageConstant.java, src/main/java/com/samhap/kokomen/interview/tool/GptSystemMessageConstant.java
CodingInterviewPromptFragments에 페르소나/루브릭 등 조각 상수, CodingInterviewBedrockSystemMessageConstant에 진행/종료/피드백 프롬프트, GptSystemMessageConstantCODING_PROCEED/END_SYSTEM_MESSAGE 추가.
Bedrock/GPT 클라이언트 InterviewType 전달
src/main/java/com/samhap/kokomen/interview/external/dto/request/InterviewBedrockRequestFactory.java, src/main/java/com/samhap/kokomen/interview/external/AnswerFeedbackBedrockClient.java, src/main/java/com/samhap/kokomen/interview/external/InterviewProceedBedrockClient.java, src/main/java/com/samhap/kokomen/interview/tool/InterviewMessagesFactory.java
InterviewBedrockRequestFactory 3개 메서드에 InterviewType 파라미터 추가 및 LIVE_CODING 분기, Bedrock/GPT 클라이언트에서 interviewType 전달, InterviewMessagesFactoryisLiveCoding 헬퍼로 CODING_* 상수 조건부 선택.
참조 답변 노출 차단 및 테스트 전체
src/main/java/com/samhap/kokomen/interview/service/core/InterviewService.java, src/test/java/com/samhap/kokomen/...
getReferenceAnswersisLiveCoding() 조건 추가, 픽스처 빌더 확장, 도메인/리포지토리/서비스/컨트롤러/프롬프트 테스트 전반에 라이브 코딩 시나리오 검증 추가.

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant InterviewStartFacadeService
  participant RootQuestionService
  participant RootQuestion
  participant InterviewProceedBedrockClient
  participant InterviewBedrockRequestFactory

  Client->>InterviewStartFacadeService: startInterview(InterviewRequest includeLiveCoding=true)
  InterviewStartFacadeService->>RootQuestionService: findNextRootQuestion(includeLiveCoding=true)
  RootQuestionService-->>InterviewStartFacadeService: RootQuestion(CODE type)
  InterviewStartFacadeService->>RootQuestion: isCode()
  InterviewStartFacadeService->>InterviewStartFacadeService: validateModeSupportedForRootQuestion()
  InterviewStartFacadeService->>InterviewStartFacadeService: resolveInterviewType() → LIVE_CODING
  InterviewStartFacadeService->>RootQuestion: createInitialQuestionContent() → title+"\n\n"+content
  InterviewStartFacadeService-->>Client: Interview(LIVE_CODING), Question(합성된 content)

  Note over Client,InterviewBedrockRequestFactory: 이후 답변 제출 시
  Client->>InterviewProceedBedrockClient: requestProceed(questionAndAnswers)
  InterviewProceedBedrockClient->>InterviewBedrockRequestFactory: createProceedSystem(LIVE_CODING)
  InterviewBedrockRequestFactory-->>InterviewProceedBedrockClient: CodingInterviewBedrockSystemMessageConstant 프롬프트
  InterviewProceedBedrockClient-->>Client: BedrockConverseResponse
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • samhap-soft/kokomen-backend#316: InterviewService#getReferenceAnswers(Interview) 메서드를 직접 수정하는 PR로, 이번 PR에서 동일 메서드에 isLiveCoding() 조건을 추가하는 변경과 코드 수준에서 직접 연관됩니다.

Suggested reviewers

  • nak-honest
  • kargowild

Poem

🐰 코드 테스트 시작! 토끼가 뛰어올라~
LIVE_CODING 타입, 새로운 문이 열렸네
제목과 내용, \n\n으로 합치고
Bedrock에게 코딩 프롬프트 보내며
참조 답변은 살짝 숨겨두었지 🎉
10000자의 답변, 이제 거뜬해!
당근 한 입 먹고 리뷰 시작합시다 🥕

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 2.20% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ❓ Inconclusive PR 설명이 빈 템플릿만 포함되어 있어 변경 사항에 대한 의미 있는 정보를 전혀 제공하지 않습니다. PR 설명에 작업 내용, 스크린샷, 참고 사항을 구체적으로 작성하여 변경 사항의 의도와 범위를 명확히 해주세요.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed PR 제목이 주요 변경 사항인 라이브 코테 기능 추가를 명확하게 요약하고 있습니다.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/live-coding

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@gemini-code-assist

Copy link
Copy Markdown

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

본 PR은 라이브 코딩 테스트 기능을 구현하기 위한 백엔드 인프라와 로직을 추가합니다. 기존의 카테고리 기반 면접과 병행하여 코딩 문제 타입(CODE)을 지원하도록 도메인 모델을 확장하고, AI 면접관이 코딩 테스트에 적합한 방식으로 피드백을 생성하도록 프롬프트 전략을 분리했습니다. 또한, 긴 코드 답변 저장을 위해 데이터베이스 필드 크기를 조정하고, 관련 테스트 코드를 추가하여 안정성을 확보했습니다.

Highlights

  • 라이브 코딩 테스트 기능 추가: 라이브 코딩 테스트(LIVE_CODING) 타입을 도입하여 기존의 일반 면접 질문과 구분하고, 전용 시스템 프롬프트와 평가 로직을 적용했습니다.
  • 데이터베이스 스키마 확장: RootQuestion에 question_type과 title 컬럼을 추가하고, content 필드와 Answer의 content 길이를 대폭 확장하여 마크다운 기반의 코딩 문제와 긴 코드 답변을 수용할 수 있도록 했습니다.
  • 인터뷰 시작 로직 개선: 사용자가 라이브 코딩 테스트 포함 여부를 선택할 수 있도록 API를 수정하고, 코드 타입 질문에 대해서는 제목과 본문을 결합하여 초기 질문을 생성하도록 변경했습니다.
  • AI 피드백 프롬프트 분리: 일반 면접과 코딩 테스트의 평가 기준이 다르므로, Bedrock 및 GPT 시스템 메시지를 각각 분리하여 코딩 테스트에 최적화된 피드백을 제공하도록 했습니다.
New Features

🧠 You can now enable Memory (public preview) to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize the Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counterproductive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.


코드의 바다를 헤엄치며, 질문의 꼬리를 물고 답하네. 라이브 코테의 긴장 속에서, 우리의 로직은 빛을 발하리.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a live coding test feature to the interview system. It adds a new LIVE_CODING interview type, supports code-type root questions with titles, and expands the content length limits for questions and answers. Additionally, it integrates specific system prompts and evaluation rubrics for coding interviews with Bedrock and GPT clients. The review feedback suggests adding validation to ensure that title is not null or blank when creating a code-type root question, and defensively checking the title in createInitialQuestionContent to avoid prepending a null string to the content.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +61 to +69
public static RootQuestion forCode(Category category, String title, String content) {
RootQuestion rootQuestion = new RootQuestion();
rootQuestion.category = category;
rootQuestion.state = RootQuestionState.ACTIVE;
rootQuestion.questionType = RootQuestionType.CODE;
rootQuestion.title = title;
rootQuestion.content = content;
return rootQuestion;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

CODE 타입의 루트 질문은 반드시 제목(title)이 존재해야 합니다. forCode 팩토리 메서드 호출 시 titlenull이거나 빈 값인지 검증하는 로직을 추가하여 올바르지 않은 상태의 객체가 생성되는 것을 방지하는 것이 좋습니다.

    public static RootQuestion forCode(Category category, String title, String content) {
        if (title == null || title.isBlank()) {
            throw new IllegalArgumentException("코드 타입 질문은 제목(title)이 필수입니다.");
        }
        RootQuestion rootQuestion = new RootQuestion();
        rootQuestion.category = category;
        rootQuestion.state = RootQuestionState.ACTIVE;
        rootQuestion.questionType = RootQuestionType.CODE;
        rootQuestion.title = title;
        rootQuestion.content = content;
        return rootQuestion;
    }

Comment on lines +71 to +76
public String createInitialQuestionContent() {
if (questionType == RootQuestionType.CODE) {
return title + "\n\n" + content;
}
return content;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

questionTypeCODE일 때 titlenull이거나 빈 문자열(blank)인 경우, title + "\n\n" + content 연산으로 인해 "null\n\n..."과 같이 비정상적인 문자열이 생성될 수 있습니다.

title이 유효한 경우에만 제목을 본문 앞에 추가하도록 방어적으로 코드를 개선하는 것이 좋습니다.

Suggested change
public String createInitialQuestionContent() {
if (questionType == RootQuestionType.CODE) {
return title + "\n\n" + content;
}
return content;
}
public String createInitialQuestionContent() {
if (questionType == RootQuestionType.CODE && title != null && !title.isBlank()) {
return title + "\n\n" + content;
}
return content;
}

@github-actions

Copy link
Copy Markdown

Test Results

 54 files   54 suites   1m 26s ⏱️
315 tests 314 ✅ 1 💤 0 ❌
317 runs  316 ✅ 1 💤 0 ❌

Results for commit e7bcf85.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/main/java/com/samhap/kokomen/interview/domain/RootQuestion.java`:
- Around line 61-68: The forCode factory method does not validate that the title
and content parameters are non-null and non-blank before assigning them to the
RootQuestion entity, which violates entity-level validation requirements. Add
validation checks in the forCode method to ensure both title and content
parameters are not null and not blank, throwing an appropriate exception (such
as IllegalArgumentException) if either validation fails. This will prevent the
creation of CODE type RootQuestion instances with invalid or empty title and
content fields.

In
`@src/main/java/com/samhap/kokomen/interview/service/InterviewStartFacadeService.java`:
- Around line 64-65: The issue is that VOICE interview mode combined with
includeLiveCoding=true produces non-deterministic results because the root
question is randomly selected, and validation fails only when CODE type is
selected. Add proactive validation before calling findNextRootQuestionForMember
in InterviewStartFacadeService to block the problematic VOICE +
includeLiveCoding=true combination at the request level, or ensure that when
interviewMode is VOICE, only GENERAL type root questions are selected. This will
make the result deterministic by preventing the scenario where
validateModeSupportedForRootQuestion fails due to incompatible mode and root
question type combinations.

In
`@src/test/java/com/samhap/kokomen/interview/repository/RootQuestionRepositoryTest.java`:
- Around line 47-48: The current test cases for the repository methods only
validate RootQuestionType.GENERAL filtering, leaving the CODE type path untested
and vulnerable to regressions. Add new test cases for both
findFirstRootQuestionMemberNotReceivedByCategory and its corresponding findLast
method (likely findLastRootQuestionMemberNotReceivedByCategory) that filter by
RootQuestionType.CODE instead of GENERAL. Each test should verify that when CODE
type is used as the filter, only CODE type data is returned in the results. This
provides coverage for the newly added CODE path in the repository filter logic.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 3ac1054d-3697-473d-a312-caaa91f4f4e1

📥 Commits

Reviewing files that changed from the base of the PR and between c10f3d6 and e7bcf85.

📒 Files selected for processing (33)
  • src/main/java/com/samhap/kokomen/answer/domain/Answer.java
  • src/main/java/com/samhap/kokomen/interview/domain/Interview.java
  • src/main/java/com/samhap/kokomen/interview/domain/InterviewType.java
  • src/main/java/com/samhap/kokomen/interview/domain/Question.java
  • src/main/java/com/samhap/kokomen/interview/domain/RootQuestion.java
  • src/main/java/com/samhap/kokomen/interview/domain/RootQuestionType.java
  • src/main/java/com/samhap/kokomen/interview/external/AnswerFeedbackBedrockClient.java
  • src/main/java/com/samhap/kokomen/interview/external/InterviewProceedBedrockClient.java
  • src/main/java/com/samhap/kokomen/interview/external/dto/request/InterviewBedrockRequestFactory.java
  • src/main/java/com/samhap/kokomen/interview/repository/RootQuestionRepository.java
  • src/main/java/com/samhap/kokomen/interview/service/InterviewStartFacadeService.java
  • src/main/java/com/samhap/kokomen/interview/service/core/InterviewService.java
  • src/main/java/com/samhap/kokomen/interview/service/dto/AnswerRequestV2.java
  • src/main/java/com/samhap/kokomen/interview/service/dto/InterviewRequest.java
  • src/main/java/com/samhap/kokomen/interview/service/dto/RootQuestionResponse.java
  • src/main/java/com/samhap/kokomen/interview/service/question/RootQuestionService.java
  • src/main/java/com/samhap/kokomen/interview/tool/CodingInterviewBedrockSystemMessageConstant.java
  • src/main/java/com/samhap/kokomen/interview/tool/CodingInterviewPromptFragments.java
  • src/main/java/com/samhap/kokomen/interview/tool/GptSystemMessageConstant.java
  • src/main/java/com/samhap/kokomen/interview/tool/InterviewMessagesFactory.java
  • src/main/resources/db/migration/V49__add_live_coding_question_type_and_widen_content.sql
  • src/test/java/com/samhap/kokomen/global/fixture/interview/RootQuestionFixtureBuilder.java
  • src/test/java/com/samhap/kokomen/interview/controller/InterviewControllerTest.java
  • src/test/java/com/samhap/kokomen/interview/controller/InterviewControllerV3Test.java
  • src/test/java/com/samhap/kokomen/interview/docs/InterviewDocsTest.java
  • src/test/java/com/samhap/kokomen/interview/domain/RootQuestionTest.java
  • src/test/java/com/samhap/kokomen/interview/external/dto/request/InterviewBedrockRequestFactoryTest.java
  • src/test/java/com/samhap/kokomen/interview/repository/AnswerRepositoryTest.java
  • src/test/java/com/samhap/kokomen/interview/repository/RootQuestionRepositoryTest.java
  • src/test/java/com/samhap/kokomen/interview/service/LiveCodingInterviewServiceTest.java
  • src/test/java/com/samhap/kokomen/interview/service/core/InterviewServiceTest.java
  • src/test/java/com/samhap/kokomen/interview/service/question/RootQuestionServiceTest.java
  • src/test/java/com/samhap/kokomen/interview/tool/InterviewMessagesFactoryTest.java

Comment on lines +61 to +68
public static RootQuestion forCode(Category category, String title, String content) {
RootQuestion rootQuestion = new RootQuestion();
rootQuestion.category = category;
rootQuestion.state = RootQuestionState.ACTIVE;
rootQuestion.questionType = RootQuestionType.CODE;
rootQuestion.title = title;
rootQuestion.content = content;
return rootQuestion;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

CODE 루트 질문 생성 시 제목/본문 유효성 검증이 필요합니다.

forCode(...)title/content의 null·blank를 허용해서 CODE 질문의 필수 의미가 깨질 수 있고, 이후 초기 질문 생성 시 비정상 문자열이 생성될 수 있습니다.

수정 제안
+import com.samhap.kokomen.global.exception.BadRequestException;
@@
     public static RootQuestion forCode(Category category, String title, String content) {
+        validateCodeQuestion(title, content);
         RootQuestion rootQuestion = new RootQuestion();
         rootQuestion.category = category;
         rootQuestion.state = RootQuestionState.ACTIVE;
         rootQuestion.questionType = RootQuestionType.CODE;
         rootQuestion.title = title;
         rootQuestion.content = content;
         return rootQuestion;
     }
+
+    private static void validateCodeQuestion(String title, String content) {
+        if (title == null || title.isBlank()) {
+            throw new BadRequestException("코딩 문제 제목은 비어 있을 수 없습니다.");
+        }
+        if (content == null || content.isBlank()) {
+            throw new BadRequestException("코딩 문제 본문은 비어 있을 수 없습니다.");
+        }
+    }

As per coding guidelines, "Use @Valid annotation in DTOs for validation, entity-level validation in constructors, business validation in service layer".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/java/com/samhap/kokomen/interview/domain/RootQuestion.java` around
lines 61 - 68, The forCode factory method does not validate that the title and
content parameters are non-null and non-blank before assigning them to the
RootQuestion entity, which violates entity-level validation requirements. Add
validation checks in the forCode method to ensure both title and content
parameters are not null and not blank, throwing an appropriate exception (such
as IllegalArgumentException) if either validation fails. This will prevent the
creation of CODE type RootQuestion instances with invalid or empty title and
content fields.

Source: Coding guidelines

@unifolio0 unifolio0 merged commit 163f142 into develop Jun 14, 2026
2 checks passed
@unifolio0 unifolio0 deleted the feat/live-coding branch June 14, 2026 08:59
unifolio0 added a commit that referenced this pull request Jun 14, 2026
@coderabbitai coderabbitai Bot mentioned this pull request Jun 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant