Skip to content

Conversation

@sjk4618
Copy link
Member

@sjk4618 sjk4618 commented Dec 31, 2025

🔥Pull requests

⛳️ 작업한 브랜치

👷 작업한 내용

🚨 참고 사항

@sjk4618 sjk4618 self-assigned this Dec 31, 2025
@coderabbitai
Copy link

coderabbitai bot commented Dec 31, 2025

📝 Walkthrough

Summary by CodeRabbit

릴리스 노트

  • 새로운 기능

    • 각 티켓 타입별 품절 상태 표시 기능이 추가되었습니다.
    • 실시간 재고 현황 확인으로 사용자 경험이 개선되었습니다.
  • 버그 수정

    • 재고 데이터 불일치 발생 시 안정적인 오류 처리 메커니즘이 추가되었습니다.

✏️ Tip: You can customize this high-level summary in your review settings.

Walkthrough

티켓 판매 완료 상태를 Redis 기반으로 관리하기 위한 기능을 추가합니다. TicketType 응답 DTO에 isTicketSoldOut 필드를 추가하고, TicketService에서 Redis를 통해 판매 완료 상태를 조회한 후 DTO에 전달하며, RedisManager에 배치 조회 메서드를 추가하고 새로운 오류 코드를 정의합니다.

Changes

Cohort / File(s) 변경 사항
응답 DTO 확장
src/main/java/com/permitseoul/permitserver/domain/ticket/api/dto/res/EventTicketInfoResponse.java
TicketType 레코드에 boolean isTicketSoldOut 필드 추가; 티켓 타입별 판매 완료 상태 표시 기능 추가
서비스 로직 통합
src/main/java/com/permitseoul/permitserver/domain/ticket/api/service/TicketService.java
Redis 기반 판매 완료 상태 조회 로직 구현; Redis 실패 시 DB 여유 개수로 폴백; 오류 처리 및 로깅 추가; 레코드 DTO 생성 시 판매 완료 상태 전달
인프라 계층 확장
src/main/java/com/permitseoul/permitserver/global/redis/RedisManager.java
다중 Redis 키 조회를 위한 mGet(List<String> keys) 메서드 추가
오류 코드 정의
src/main/java/com/permitseoul/permitserver/global/response/code/ErrorCode.java
새 에러 코드 BAD_REQUEST_REDIS_TICKET_TYPE_MISMATCH (상태 400, 코드 40018) 추가

Sequence Diagram

sequenceDiagram
    actor Client
    participant TicketService
    participant RedisManager
    participant Database
    
    Client->>TicketService: 행사 티켓 정보 조회 요청
    
    rect rgb(200, 220, 240)
    Note over TicketService,RedisManager: Redis 판매 완료 상태 조회
    TicketService->>TicketService: 조회할 티켓 타입 ID 수집
    TicketService->>RedisManager: mGet(ticketTypeIds)
    RedisManager-->>TicketService: Redis 판매 완료 상태 맵
    end
    
    alt Redis 조회 성공
        TicketService->>TicketService: 판매 완료 상태 맵 구성
    else Redis 실패/오류
        rect rgb(255, 240, 220)
        Note over TicketService,Database: 폴백: DB에서 여유 개수 조회
        TicketService->>Database: 티켓 여유 개수 조회
        Database-->>TicketService: 여유 개수 데이터
        TicketService->>TicketService: 여유 개수 0 여부로 판매 완료 판단
        end
    end
    
    TicketService->>TicketService: TicketType DTO 생성<br/>(isTicketSoldOut 포함)
    TicketService->>TicketService: 행사 정보 응답 구성
    TicketService-->>Client: EventTicketInfoResponse 반환
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 분

Possibly related PRs

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed 제목이 변경 사항의 주요 내용을 명확하게 설명하고 있습니다. 행사 티켓 정보 조회 API에 티켓 필드를 추가하는 것이 이슈 #203과 관련되어 있습니다.
Description check ✅ Passed 설명에는 구체적인 작업 내용이 명시되지 않았으나, 이슈 #203 참조를 통해 변경 사항이 티켓 정보 조회 API와 관련 있음을 알 수 있습니다.
Linked Issues check ✅ Passed 이슈 #203은 행사 티켓 정보 조회 API에 티켓 개수/판매 완료 필드를 추가하는 것이 목표이며, 변경 사항이 이를 충족합니다.
Out of Scope Changes check ✅ Passed 모든 변경 사항이 티켓 정보 조회 API의 판매 완료 여부 필드 추가라는 이슈 #203의 목표와 관련이 있습니다.
✨ Finishing touches
  • 📝 Generate docstrings

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.

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: 3

🧹 Nitpick comments (1)
src/main/java/com/permitseoul/permitserver/domain/ticket/api/service/TicketService.java (1)

173-179: 불필요한 연산 가능성이 있습니다.

dbRemainMap은 Redis 장애 시 fallback용으로만 사용되지만, 매번 빌드됩니다. Redis가 정상인 경우(대부분의 경우)에는 불필요한 연산입니다.

🔎 지연 초기화 방식 제안

Redis 호출 실패 시에만 dbRemainMap을 생성하도록 수정하면 성능을 최적화할 수 있습니다:

-        //장애 fallback 시 사용할 DB remain 맵
-        final Map<Long, Integer> dbRemainMap = ticketTypeList.stream()
-                .collect(Collectors.toMap(
-                        TicketType::getTicketTypeId,
-                        TicketType::getRemainTicketCount,
-                        (a, b) -> a // 중복이면 앞 값 유지
-                ));
-
         final List<Long> ticketTypeIds = ticketTypeList.stream()
                 .map(TicketType::getTicketTypeId)
                 .distinct()
                 .toList();

그리고 catch 블록 내에서:

         } catch (RedisConnectionFailureException | RedisSystemException | QueryTimeoutException e) {
             // Redis 장애일 때만 fallback
             log.error("[TicketType 개수 정보 조회] Redis 장애로 DB remainTicketCount fallback 처리. ticketType={}, err={}",
                     ticketTypeIds, e.getClass().getSimpleName());

+            final Map<Long, Integer> dbRemainMap = ticketTypeList.stream()
+                    .collect(Collectors.toMap(
+                            TicketType::getTicketTypeId,
+                            TicketType::getRemainTicketCount,
+                            (a, b) -> a
+                    ));
+
             final Map<Long, Boolean> fallback = new HashMap<>();
📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a5653ee and c30dd9e.

📒 Files selected for processing (4)
  • src/main/java/com/permitseoul/permitserver/domain/ticket/api/dto/res/EventTicketInfoResponse.java
  • src/main/java/com/permitseoul/permitserver/domain/ticket/api/service/TicketService.java
  • src/main/java/com/permitseoul/permitserver/global/redis/RedisManager.java
  • src/main/java/com/permitseoul/permitserver/global/response/code/ErrorCode.java
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: sjk4618
Repo: PERMIT-SEOUL/permit-server PR: 48
File: src/main/java/com/permitseoul/permitserver/domain/guest/core/domain/entity/GuestEntity.java:31-37
Timestamp: 2025-07-15T09:37:32.765Z
Learning: sjk4618 prefers to implement factory methods or public constructors for entities when they are actually needed, rather than creating them proactively.
🔇 Additional comments (6)
src/main/java/com/permitseoul/permitserver/global/redis/RedisManager.java (1)

80-88: LGTM!

mGet 메서드 구현이 깔끔합니다. null/empty 입력과 multiGet 반환값 null 케이스를 적절히 처리하고 있습니다.

src/main/java/com/permitseoul/permitserver/domain/ticket/api/dto/res/EventTicketInfoResponse.java (1)

16-23: LGTM!

isTicketSoldOut 필드가 적절하게 추가되었습니다. 다만, 이 API를 사용하는 클라이언트가 있다면 새 필드 추가에 대한 호환성을 확인해 주세요.

src/main/java/com/permitseoul/permitserver/domain/ticket/api/service/TicketService.java (4)

84-89: LGTM!

Redis 기반 soldOut 상태 조회 로직이 기존 플로우에 잘 통합되었습니다.


364-380: LGTM!

soldOutByTicketTypeId 파라미터가 적절히 전달되고 있습니다.


417-436: LGTM!

getOrDefault(ticketType.getTicketTypeId(), false)를 사용하여 맵에 없는 경우 안전하게 false를 반환합니다.


239-241: LGTM!

상수를 사용하여 Redis 키를 구성하는 것은 좋은 방식입니다.

Comment on lines +206 to +210
if (redisTicketTypeCountValues == null || redisTicketTypeCountValues.size() != ticketTypeKeys.size()) {
log.error("[TicketInfo] Redis mGet 결과 크기 불일치. keysSize={}, valuesSize={}",
ticketTypeKeys.size(), redisTicketTypeCountValues == null ? -1 : redisTicketTypeCountValues.size());
throw new PaymentBadRequestException(ErrorCode.INTERNAL_TICKET_TYPE_REDIS_ERROR);
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Exception 타입과 ErrorCode가 일치하지 않습니다.

PaymentBadRequestException을 사용하고 있지만, INTERNAL_TICKET_TYPE_REDIS_ERROR는 500 에러 코드입니다. 또한, Payment 관련 예외를 Ticket 서비스에서 사용하는 것은 의미적으로 맞지 않습니다.

🔎 개선 방안

Ticket 도메인에 적합한 내부 서버 에러 예외 클래스를 사용하거나, 새로운 예외 타입을 정의하는 것이 좋습니다:

-            throw new PaymentBadRequestException(ErrorCode.INTERNAL_TICKET_TYPE_REDIS_ERROR);
+            throw new InternalServerErrorException(ErrorCode.INTERNAL_TICKET_TYPE_REDIS_ERROR);

또는 TicketService 전용 예외 클래스가 있다면 해당 클래스를 사용해 주세요.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In
src/main/java/com/permitseoul/permitserver/domain/ticket/api/service/TicketService.java
around lines 206 to 210, the code throws PaymentBadRequestException while using
ErrorCode.INTERNAL_TICKET_TYPE_REDIS_ERROR (a 500-level internal error) and
using a Payment-specific exception in the Ticket domain; replace the thrown
exception with a ticket-appropriate internal server error exception (e.g., a
TicketInternalServerException or a generic InternalServerException) that maps to
ErrorCode.INTERNAL_TICKET_TYPE_REDIS_ERROR, or create/use an existing
TicketService-specific exception class so the exception type semantically
matches the 500 error code and domain.

BAD_REQUEST_CANCELED_TICKET(HttpStatus.BAD_REQUEST, 40015, "취소된 ticket 입니다."),
BAD_REQUEST_MISMATCH_TICKET_TYPE_ROUND(HttpStatus.BAD_REQUEST, 40016, "ticketType의 roundId와 다른 ticketRoundId 입니다."),
BAD_REQUEST_MISMATCH_LIST_SIZE(HttpStatus.BAD_REQUEST, 40017, "list의 길이가 다릅니다."),
BAD_REQUEST_REDIS_TICKET_TYPE_MISMATCH(HttpStatus.BAD_REQUEST, 40018, "redis ticket tpye mismatch 에러입니다. "),
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

에러 메시지에 오타가 있습니다.

"tpye""type"으로 수정이 필요합니다. 또한, 메시지 끝의 불필요한 공백도 제거해 주세요.

🔎 수정 제안
-    BAD_REQUEST_REDIS_TICKET_TYPE_MISMATCH(HttpStatus.BAD_REQUEST, 40018, "redis ticket tpye mismatch 에러입니다. "),
+    BAD_REQUEST_REDIS_TICKET_TYPE_MISMATCH(HttpStatus.BAD_REQUEST, 40018, "redis ticket type mismatch 에러입니다."),
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
BAD_REQUEST_REDIS_TICKET_TYPE_MISMATCH(HttpStatus.BAD_REQUEST, 40018, "redis ticket tpye mismatch 에러입니다. "),
BAD_REQUEST_REDIS_TICKET_TYPE_MISMATCH(HttpStatus.BAD_REQUEST, 40018, "redis ticket type mismatch 에러입니다."),
🤖 Prompt for AI Agents
In
src/main/java/com/permitseoul/permitserver/global/response/code/ErrorCode.java
around line 32, fix the typo and trailing space in the enum message: change
"redis ticket tpye mismatch 에러입니다. " to "redis ticket type mismatch 에러입니다." by
correcting "tpye" to "type" and removing the extra space at the end so the
string is clean.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Search for BAD_REQUEST_REDIS_TICKET_TYPE_MISMATCH usage
echo "=== Searching for BAD_REQUEST_REDIS_TICKET_TYPE_MISMATCH usage ==="
rg -n "BAD_REQUEST_REDIS_TICKET_TYPE_MISMATCH" --type java

echo ""
echo "=== Searching for INTERNAL_TICKET_TYPE_REDIS_ERROR usage ==="
rg -n "INTERNAL_TICKET_TYPE_REDIS_ERROR" --type java

echo ""
echo "=== Searching for all references to the error code ==="
rg -n "40018" --type java

Repository: PERMIT-SEOUL/permit-server

Length of output: 1970


정의된 에러 코드가 사용되지 않습니다. 제거해 주세요.

BAD_REQUEST_REDIS_TICKET_TYPE_MISMATCH는 정의되었으나 코드베이스 어디에서도 사용되지 않습니다. 실제로는 INTERNAL_TICKET_TYPE_REDIS_ERROR(50015)가 TicketService, AdminTicketService, AdminEventService에서 사용 중입니다. 불필요한 에러 코드 정의이므로 제거하거나, 실제 용도가 있다면 구현을 완료해 주세요.

또한 에러 메시지의 "tpye"은 "type"의 오타입니다.

🤖 Prompt for AI Agents
In
src/main/java/com/permitseoul/permitserver/global/response/code/ErrorCode.java
around line 32, the enum constant BAD_REQUEST_REDIS_TICKET_TYPE_MISMATCH is
unused and contains a typo ("tpye"); either delete this constant from the enum,
or if it was intended to be used, replace the current usages of
INTERNAL_TICKET_TYPE_REDIS_ERROR (50015) in TicketService, AdminTicketService,
and AdminEventService with this constant and correct its message to "redis
ticket type mismatch 에러입니다."; ensure imports/compilation are updated after
removal or replacement.

@sjk4618 sjk4618 merged commit 8183706 into dev Dec 31, 2025
2 checks passed
@sjk4618 sjk4618 deleted the feat/#203 branch December 31, 2025 07:53
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.

feat: 행사 티켓 정보 조회 api 티켓 개수 필드 추가

2 participants