8000 feat: DRAFT 상태 질문 수정 API 구현 by Jinyshin · Pull Request #59 · If-u-Lab/If-u-server · GitHub
[go: up one dir, main page]

Skip to content

feat: DRAFT 상태 질문 수정 API 구현 - #59

Closed
Jinyshin wants to merge 5 commits into
devfrom
feature/admin-update-draft-question
Closed

Jinyshin wants to merge 5 commits into
devfrom
feature/admin-update-draft-question

Conversation

@Jinyshin
@Jinyshin Jinyshin commented Jan 3, 2026 •
Copy link
Copy Markdown
Member

Summary

  • DRAFT 상태의 질문을 수정할 수 있는 어드민 API 추가
  • Question 엔티티에 category, publishAt, closeAt 수정 메서드 추가
  • 부분 업데이트 지원 (null이 아닌 필드만 수정)

Test plan

  • DRAFT 상태 질문 수정 시 정상 동작 확인
  • PUBLISHED/CLOSED 상태 질문 수정 시 에러 반환 확인
  • 부분 업데이트 (일부 필드만 전송) 정상 동작 확인
  • Swagger 문서에서 API 스펙 확인

- Question 엔티티에 updateCategory() 메서드 추가
- Question 엔티티에 updatePublishAt() 메서드 추가
- Question 엔티티에 updateCloseAt() 메서드 추가
- QUESTION_UPDATE_NOT_ALLOWED 에러 코드 추가
  (DRAFT 상태가 아닌 질문 수정 시도 시 사용)
- UpdateQuestionRequest 레코드 추가
  (title, description, choice1, choice2, category, publishAt, closeAt)
- UpdateQuestionResponse 레코드 추가
  (id, status, content, options, plannedPublishAt, createdAt)
- @SiZe validation으로 필드 길이 제한 적용
- AdminQuestionService에 updateQuestion() 메서드 추가
  - DRAFT 상태 검증 후 부분 업데이트 수행
  - null이 아닌 필드만 선택적으로 업데이트
- AdminQuestionController에 PATCH /{id} 엔드포인트 추가
- @ApiErrorExamples 어노테이션으로 에러 케이스 문서화
@gemini-code-assist
Copy link
Copy Markdown

Summary of Changes

Hello @Jinyshin, 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은 관리자가 DRAFT 상태의 질문을 유연하게 수정할 수 있도록 새로운 기능을 도입합니다. 이를 통해 질문이 게시되기 전에 세부 사항을 조정할 수 있는 관리 효율성이 향상됩니다. 구현은 부분 업데이트를 지원하며, DRAFT 상태의 질문만 수정할 수 있도록 엄격한 검증 로직을 포함하여 데이터 무결성을 보장합니다.

Highlights

  • DRAFT 상태 질문 수정 API 추가: DRAFT 상태의 질문을 수정할 수 있는 새로운 어드민 API가 추가되었습니다. 이 API는 질문의 제목, 내용, 선택지, 카테고리, 공개 및 종료 시간 등을 변경할 수 있습니다.
  • Question 엔티티 수정 메서드 추가: Question 엔티티에 카테고리, 공개 예정 시간(publishAt), 종료 예정 시간(closeAt)을 업데이트하는 새로운 메서드들이 추가되었습니다.
  • 부분 업데이트 지원: 질문 수정 시 요청 본문에서 null이 아닌 필드만 수정되는 부분 업데이트(partial update)가 지원됩니다.
  • 수정 권한 검증 로직 추가: 질문 수정 시 해당 질문의 상태가 DRAFT인 경우에만 수정이 허용되며, 그렇지 않은 경우 에러가 반환됩니다.

🧠 New Feature in Public Preview: You can now enable Memory 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 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 counter productive. 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.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

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. ↩

@claude
claude Bot commented Jan 3, 2026
Copy link
Copy Markdown

PR 리뷰

전반적으로 DRAFT 질문 수정 API가 잘 구현되었습니다. 부분 업데이트 로직과 DRAFT 상태 검증이 적절하게 처리되었네요.

P2 (적극적으로 고려해주세요)

  • AdminQuestionService.java:126-129 - choice1/choice2 부분 업데이트 로직에 문제가 있습니다. 한쪽만 null로 전송하면 기존 값을 유지하는데, 사용자가 의도적으로 한쪽만 변경하려 해도 양쪽 모두 보내야 합니다. 이는 직관적이지 않으며, choice1만 수정 시 choice2도 함께 전송해야 하는 불편함이 있습니다.

  • UpdateQuestionResponse.java:18,34 - 응답 필드명이 일관성이 없습니다. 필드명이 content인데 실제로는 description을 반환합니다. AdminQuestionResponse는 title/description을 분리해서 반환하는데, UpdateQuestionResponse는 description만 content라는 이름으로 반환하고 title은 누락되어 있습니다.

  • UpdateQuestionResponse.java:20-21,35 - options 필드를 List로 반환하면서 category와 title 정보가 누락되었습니다. AdminQuestionResponse는 모든 필드를 개별적으로 반환하는데, UpdateQuestionResponse는 일부만 반환하여 일관성이 떨어집니다. 수정 후 전체 정보를 확인하기 어렵습니다.

P3 (웬만하면 반영해주세요)

  • AdminQuestionService.java:112-144 - updateQuestion 메서드에 대한 단위 테스트가 누락되었습니다. DRAFT 검증, 부분 업데이트, 에러 케이스 등을 테스트하는 코드 추가를 권장합니다.

  • AdminQuestionService.java:126-129 - choice 업데이트 로직이 복잡합니다. 두 필드를 항상 함께 업데이트해야 한다면, Request에서 ChoicesPair 같은 래퍼 객체로 묶는 것을 고려해보세요.

  • UpdateQuestionResponse.java:24 - 필드명이 plannedPublishAt인데 AdminQuestionResponse는 publishAt을 사용합니다. 같은 도메인 내에서 필드명 컨벤션을 통일하는 것이 좋습니다.

P4 (반영해도 좋고 넘어가도 좋습니다)

  • UpdateQuestionResponse.java:27 - updatedAt 필드가 누락되었습니다. 수정 API 응답에서 수정 시간 정보가 있으면 유용할 수 있습니다.

@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

DRAFT 상태의 질문을 수정하는 API를 구현하신 것을 확인했습니다. 전반적으로 기능 구현은 잘 되었으나, 코드의 일관성과 유지보수성을 높이기 위한 몇 가지 제안 사항을 리뷰에 남겼습니다. 특히, 서비스 레이어의 선택지 업데이트 로직과 응답 DTO의 필드명에 대한 부분을 확인해주시면 좋겠습니다.

- UpdateQuestionResponse 필드명 변경
  - content → description (Request DTO와 일관성)
  - plannedPublishAt → publishAt (엔티티와 일관성)
  - options 배열 → choice1, choice2 개별 필드로 변경
- Question 엔티티에 updateChoice1(), updateChoice2() 메서드 추가
- AdminQuestionService 선택지 업데이트 로직 간소화
  - 다른 필드들과 동일한 패턴으로 통일
@claude
claude Bot commented Jan 3, 2026
Copy link
Copy Markdown

코드 리뷰

DRAFT 상태 질문 수정 API 구현이 전반적으로 잘 되어 있습니다. 부분 업데이트 패턴도 적절하게 적용되었고, 상태 검증 로직도 명확합니다.

P2 (적극적으로 고려해주세요)

  • AdminQuestionService.java:135-139 - publishAt/closeAt 시간 검증이 누락되었습니다. closeAt이 publishAt보다 이전 시간이거나, 과거 시간으로 설정되는 경우를 검증해야 합니다.
if (request.publishAt() != null && request.closeAt() != null) {
  if (request.closeAt().isBefore(request.publishAt())) {
    throw new BusinessException(ErrorCode.INVALID_TIME_RANGE);
  }
}
  • Question.java:111-129 - update 메서드들에 null 체크 및 유효성 검증이 없습니다. 빈 문자열이나 공백만 있는 값이 들어올 수 있습니다. 특히 choice1/choice2는 nullable=false인 필드이므로 검증이 필요합니다.

P3 (웬만하면 반영해주세요)

  • UpdateQuestionResponse.java:16 - title 필드가 응답에 누락되어 있습니다. 요청에는 title 수정이 가능하지만 응답에는 포함되지 않아 일관성이 떨어집니다.

  • AdminQuestionService.java:120-140 - 수정된 필드가 없는 경우(모든 필드가 null)에도 로그가 기록되고 응답이 반환됩니다. 최소 1개 이상의 필드 수정을 요구하거나 명시적으로 처리하는 것을 권장합니다.

  • Question.java:106-109 - updateChoices() 메서드가 있는데 개별 updateChoice1/updateChoice2 메서드를 추가로 만들었습니다. updateChoices를 deprecated 처리하거나, 둘 다 사용할 명확한 이유가 있는지 확인이 필요합니다.

P4 (반영해도 좋고 넘어가도 좋습니다)

  • UpdateQuestionResponse.java:16 - category 필드도 응답에 포함하면 수정 후 전체 상태를 명확히 확인할 수 있습니다.

  • AdminQuestionController.java:68 - import 순서가 일부 뒤섞여 있습니다. 알파벳 순으로 정리하면 가독성이 좋아집니다.

- P2-1: publishAt/closeAt 시간 검증 추가
  - closeAt이 publishAt 이후인지 검증
  - QUESTION_INVALID_TIME_RANGE 에러 코드 추가
- P2-2: 빈 문자열 검증 추가
  - title, description, choice1, choice2에 @SiZe(min=1) 적용
- P3-1, P4-1: UpdateQuestionResponse에 title, category 필드 추가
- P3-3: 미사용 updateChoices() 메서드 제거
@claude
claude Bot commented Jan 3, 2026
Copy link
Copy Markdown

PR 리뷰

DRAFT 질문 수정 API 구현이 잘 되었습니다. 부분 업데이트와 유효성 검증 로직도 적절하게 처리되었네요.

P2 (적극적으로 고려해주세요)

  • AdminQuestionService.java:120-140 - 7개의 if 분기가 반복됩니다. 리플렉션이나 함수형 접근으로 중복을 제거할 수 있습니다:
Map.of(
  request.title(), question::updateTitle,
  request.description(), question::updateDescription,
  // ...
).forEach((value, updater) -> {
  if (value != null) updater.accept(value);
});
  • AdminQuestionService.java:143 - 시간 검증이 수정 후에만 수행됩니다. publishAt만 수정하면 이전 closeAt과의 관계가 검증되지 않습니다. 둘 다 null이 아닐 때만 검증하므로, 한쪽만 수정해도 검증이 필요합니다.

P3 (웬만하면 반영해주세요)

  • Question.java:106-124 - update 메서드들이 상태 검증 없이 직접 수정합니다. Service에서 검증하지만, 엔티티 레벨에서도 불변성을 보장하는 것이 안전합니다. 예를 들어 updateTitle 등에서 현재 상태가 DRAFT인지 확인하면 도메인 규칙을 엔티티가 직접 보호할 수 있습니다.

  • UpdateQuestionRequest.java:11-24 - @SiZe 검증이 null을 허용하지만, 빈 문자열("")이나 공백만 있는 경우는 통과합니다. @notblank를 함께 사용하거나, Service에서 추가 검증이 필요합니다.

  • 단위 테스트 추가를 권장합니다:

    • DRAFT 상태 질문 부분 수정 성공
    • PUBLISHED/CLOSED 상태 수정 시 에러 발생
    • publishAt > closeAt 검증 실패
    • null 필드는 업데이트하지 않음

P4 (반영해도 좋고 넘어가도 좋습니다)

  • UpdateQuestionResponse.java:52 - 파일 끝 줄바꿈 추가
  • AdminQuestionController.java:86 - 파일 끝 줄바꿈 추가

@Jinyshin Jinyshin closed this Jan 25, 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

0