Skip to content

feat: AI 이미지 생성권 남은 횟수 조회 API 구현 (#157)#158

Merged
yooooonshine merged 2 commits intodevelopfrom
feature/157-implement-remaining-generations-api
Aug 27, 2025
Merged

feat: AI 이미지 생성권 남은 횟수 조회 API 구현 (#157)#158
yooooonshine merged 2 commits intodevelopfrom
feature/157-implement-remaining-generations-api

Conversation

@yooooonshine
Copy link
Contributor

@yooooonshine yooooonshine commented Aug 27, 2025

개요

특정 포스트에 대한 사용자의 AI 이미지 생성권 남은 횟수를 조회할 수 있는 API를 구현했습니다.

구현 내용

API 추가

  • 엔드포인트: GET /api/ai/image-permissions/remaining-generations
  • 파라미터: postId (쿼리 파라미터)
  • 인증: @CurrentUser 사용하여 현재 로그인한 유저의 권한 조회
  • 응답: GetRemainingGenerationsResponse (aiImagePermissionId, remainingGenerations)

Service Layer

  • AiImagePermissionService.getRemainingGenerations() 메서드 추가
  • @Transactional(readOnly = true) 적용으로 읽기 전용 트랜잭션 처리
  • 권한이 없을 경우 AI_IMAGE_PERMISSION_NOT_FOUND 예외 발생

Swagger 문서화

  • API 문서 추가 (요약, 설명, 예외 응답 명시)
  • 구매한 이력이 없을 경우 AI-004 에러 발생 안내

테스트 내용

통합 테스트 추가 (AiImagePermissionControllerIntegrationTest)

  1. 정상 조회 테스트 (getRemainingGenerations_Success)

    • 권한이 있는 경우 정상적으로 남은 생성 횟수 반환
  2. 권한 없음 테스트 (getRemainingGenerations_PermissionNotFound)

    • 구매한 이력이 없을 경우 404 에러와 적절한 에러 코드 반환
  3. 존재하지 않는 포스트 테스트 (getRemainingGenerations_PostNotExist)

    • 존재하지 않는 포스트 ID로 조회 시 404 에러 반환

테스트 결과

  • 모든 기존 테스트 및 새로운 테스트 통과
  • 전체 빌드 성공

관련 이슈

Closes #157

🤖 Generated with Claude Code

Summary by CodeRabbit

  • 신기능
    • 남은 이미지 생성 횟수 조회 엔드포인트 추가: GET /api/ai/image-permissions/remaining-generations?postId=... (현재 사용자 기준)
    • 응답 스키마 단순화: aiImagePermissionId, remainingGenerations만 반환
  • 문서
    • OpenAPI에 404 오류 사례(사용자/권한 없음)와 새로운 응답 스키마 반영
  • 테스트
    • 성공 / 권한 없음 / 게시물 없음 시나리오에 대한 통합 테스트 추가
  • 제거
    • 목록 응답 타입(AiImagePermissionListResponse) 삭제 (관련 API 형식 변경)

@yooooonshine yooooonshine linked an issue Aug 27, 2025 that may be closed by this pull request
@coderabbitai
Copy link

coderabbitai bot commented Aug 27, 2025

Caution

Review failed

The pull request is closed.

Walkthrough

AI 이미지 사용권의 남은 생성 횟수를 조회하는 API가 추가되었습니다. 서비스에 읽기 전용 조회 메서드가 도입되고 컨트롤러에 GET 엔드포인트가 추가되었으며, 관련 응답 DTO 추가/변경 및 해당 기능을 검증하는 통합 테스트가 포함되었습니다.

Changes

Cohort / File(s) Change Summary
Service: 남은 횟수 조회 로직 추가
src/main/java/hanium/modic/backend/domain/ai/service/AiImagePermissionService.java
읽기 전용 메서드 getRemainingGenerations(userId, postId) 추가. 레포지토리에서 조회 후 미존재 시 AI_IMAGE_PERMISSION_NOT_FOUND 예외 발생, 조회결과로 GetRemainingGenerationsResponse 반환.
Controller: 조회 엔드포인트 추가
src/main/java/hanium/modic/backend/web/ai/controller/AiImagePermissionController.java
GET /api/ai/image-permissions/remaining-generations 엔드포인트 추가. @CurrentUser@RequestParam postId 수신, 서비스 호출, 200 응답 반환 및 OpenAPI 주석(404 문서화) 추가.
DTOs: 응답 DTO 추가 및 기존 DTO 축소/삭제
src/main/java/hanium/modic/backend/web/ai/dto/response/GetRemainingGenerationsResponse.java, src/main/java/hanium/modic/backend/web/ai/dto/response/AiImagePermissionResponse.java, src/main/java/hanium/modic/backend/web/ai/dto/response/AiImagePermissionListResponse.java
GetRemainingGenerationsResponse(Long aiImagePermissionId, Integer remainingGenerations) 추가. AiImagePermissionResponse 레코드 시그니처를 (Long aiImagePermissionId, Integer remainingGenerations)로 축소. AiImagePermissionListResponse 파일 삭제.
Tests: 통합 테스트 추가
src/test/java/hanium/modic/backend/web/ai/controller/AiImagePermissionControllerIntegrationTest.java
남은 횟수 조회 성공/권한 미존재/게시물 미존재 시나리오 3건 추가. 응답 JSON 및 404 에러 코드/메시지 검증.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    actor U as 사용자
    participant C as AiImagePermissionController
    participant S as AiImagePermissionService
    participant R as AiImagePermissionRepository

    U->>C: GET /api/ai/image-permissions/remaining-generations?postId
    C->>S: getRemainingGenerations(userId, postId)
    S->>R: findByUserIdAndPostId(userId, postId)
    alt 권한 존재
        R-->>S: AiImagePermissionEntity
        S-->>C: GetRemainingGenerationsResponse(aiImagePermissionId, remainingGenerations)
        C-->>U: 200 OK + JSON
    else 권한 없음
        R-->>S: 없음
        S-->>C: throw AI_IMAGE_PERMISSION_NOT_FOUND
        C-->>U: 404 Not Found + error payload
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Assessment against linked issues

Objective Addressed Explanation
결제 사용권 횟수 조회 API 구현 (#157)

Assessment against linked issues: Out-of-scope changes

Code Change Explanation
AiImagePermissionListResponse 삭제 (src/main/java/hanium/modic/backend/web/ai/dto/response/AiImagePermissionListResponse.java) 삭제는 #157의 "조회 API 구현" 목적과 직접적인 관련이 없으므로 범위를 벗어나는 변경으로 보입니다.

Possibly related PRs

Poem

깡총깡총 코드 밭을 뛰어든 토끼가 말하네 🐇
"남은 횟수 한 번에 콕, JSON에 빛나네"
아이디랑 숫자, 깔끔히 도착했네
버그는 숨바꼭질, 우리는 테스트로 찾아요
당근 한 조각은 배포 후에 먹을게요 🥕

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.


📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 4a90d7f and c480423.

📒 Files selected for processing (4)
  • src/main/java/hanium/modic/backend/domain/ai/service/AiImagePermissionService.java (2 hunks)
  • src/main/java/hanium/modic/backend/web/ai/controller/AiImagePermissionController.java (2 hunks)
  • src/main/java/hanium/modic/backend/web/ai/dto/response/AiImagePermissionListResponse.java (0 hunks)
  • src/main/java/hanium/modic/backend/web/ai/dto/response/GetRemainingGenerationsResponse.java (1 hunks)
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/157-implement-remaining-generations-api

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/main/java/hanium/modic/backend/domain/ai/service/AiImagePermissionService.java (1)

29-33: 문서와 기본 생성 횟수(20 vs 3) 불일치

서비스 기본값은 20인데, 컨트롤러의 API 설명은 “기본 3회”로 표기되어 있습니다. 대외 문서 불일치로 혼선 유발 소지 큽니다. 한 곳으로 상수화하거나 설정값으로 분리해 단일 진실 공급원을 두세요.

src/main/java/hanium/modic/backend/web/ai/controller/AiImagePermissionController.java (1)

34-35: API 문서의 기본 생성 횟수 표기 수정 필요

설명 문자열의 “기본 3회”가 실제 기본값(20회)과 다릅니다. 외부 문서 불일치이므로 즉시 수정 권장합니다.

적용 예:

- description = "코인을 사용하여 AI 이미지 생성권을 구매합니다. 기본 3회 생성 가능합니다.",
+ description = "코인을 사용하여 AI 이미지 생성권을 구매합니다. 기본 20회 생성 가능합니다.",
- description = "티켓을 사용하여 AI 이미지 생성권을 구매합니다. 기본 3회 생성 가능합니다.",
+ description = "티켓을 사용하여 AI 이미지 생성권을 구매합니다. 기본 20회 생성 가능합니다.",

Also applies to: 55-56

🧹 Nitpick comments (5)
src/main/java/hanium/modic/backend/web/ai/dto/response/AiImagePermissionResponse.java (2)

3-3: 불필요한 import 제거

LocalDateTime을 사용하지 않습니다. 정리해주세요.

-import java.time.LocalDateTime;

5-8: DTO 축소 적절함 + null 안정성 검토

응답 축소는 적절합니다. remainingGenerations가 DB에서 null이 될 가능성이 없다면 int로 고정해 NPE 여지를 없애는 것도 고려해 보세요.

src/main/java/hanium/modic/backend/web/ai/controller/AiImagePermissionController.java (2)

74-90: 요청 파라미터 제약 추가(+ 스웨거 명확화) 제안

postId에 음수/0이 들어오는 것을 사전에 차단하면 좋습니다. 또한 파라미터 설명을 추가하면 문서 가독성이 높아집니다.

다음 변경을 제안합니다:

 import org.springframework.web.bind.annotation.RequestParam;
+import io.swagger.v3.oas.annotations.Parameter;
+import jakarta.validation.constraints.Positive;

 ...

- public ResponseEntity<AiImagePermissionResponse> getRemainingGenerations(
-     @CurrentUser UserEntity user,
-     @RequestParam Long postId
- ) {
+ public ResponseEntity<AiImagePermissionResponse> getRemainingGenerations(
+     @CurrentUser UserEntity user,
+     @Parameter(description = "조회할 포스트 ID", required = true, example = "1")
+     @RequestParam @Positive Long postId
+ ) {

74-90: 200 응답 스키마 문서화(선택)

성공(200) 응답의 스키마를 명시하면 API 문서 완성도가 올라갑니다. @ApiResponsecontent/schema 추가를 고려하세요.

src/test/java/hanium/modic/backend/web/ai/controller/AiImagePermissionControllerIntegrationTest.java (1)

316-331: 존재하지 않는 포스트도 동일 404로 매핑 확인 OK

요구사항과 일치합니다. 추가로 파라미터 누락 400 케이스도 있으면 방어력이 더 좋아집니다.

아래 테스트 추가 제안:

@@
 class AiImagePermissionControllerIntegrationTest extends BaseIntegrationTest {
@@
+    @Test
+    @WithCustomUser(email = "test@test.com")
+    @DisplayName("AI 이미지 생성권 남은 횟수 조회 - postId 미지정 시 400")
+    void getRemainingGenerations_MissingPostId_BadRequest() throws Exception {
+        mockMvc.perform(get("/api/ai/image-permissions/remaining-generations"))
+            .andExpect(status().isBadRequest());
+    }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 754f163 and 4a90d7f.

📒 Files selected for processing (4)
  • src/main/java/hanium/modic/backend/domain/ai/service/AiImagePermissionService.java (2 hunks)
  • src/main/java/hanium/modic/backend/web/ai/controller/AiImagePermissionController.java (2 hunks)
  • src/main/java/hanium/modic/backend/web/ai/dto/response/AiImagePermissionResponse.java (1 hunks)
  • src/test/java/hanium/modic/backend/web/ai/controller/AiImagePermissionControllerIntegrationTest.java (1 hunks)
🔇 Additional comments (3)
src/main/java/hanium/modic/backend/domain/ai/service/AiImagePermissionService.java (1)

76-88: 조회 로직 간결·안정적 (읽기 전용 트랜잭션 OK)

권한 없을 때 AI_IMAGE_PERMISSION_NOT_FOUND로 일관되게 처리하는 부분 좋습니다. 현재 요구사항과 테스트 기대와도 일치합니다.

src/test/java/hanium/modic/backend/web/ai/controller/AiImagePermissionControllerIntegrationTest.java (2)

272-296: 성공 케이스 테스트 적절

상태 코드 및 페이로드 필드 검증이 명확합니다.


298-315: 권한 없음(404) 케이스 적절

에러 코드/메시지까지 검증한 점 좋습니다.

@yooooonshine yooooonshine merged commit 8db913b into develop Aug 27, 2025
1 check was pending
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.

결제 사용권 횟수 조회 API 구현

1 participant