Conversation
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the You can disable this status message by setting the Walkthrough이 변경 사항은 기존의 단일 모듈 구조를 제거하고, Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant ScheduleWebAdapter
participant QueryScheduleByTypeUseCase
participant ScheduleFacade
participant FindSchedulePort
participant DB
Client->>ScheduleWebAdapter: GET /schedule?type=...
ScheduleWebAdapter->>QueryScheduleByTypeUseCase: execute(type)
QueryScheduleByTypeUseCase->>ScheduleFacade: getScheduleByType(type)
ScheduleFacade->>FindSchedulePort: findByType(type)
FindSchedulePort->>DB: DB 조회
DB-->>FindSchedulePort: Schedule
FindSchedulePort-->>ScheduleFacade: Schedule
ScheduleFacade-->>QueryScheduleByTypeUseCase: Schedule
QueryScheduleByTypeUseCase-->>ScheduleWebAdapter: ScheduleDto
ScheduleWebAdapter-->>Client: ScheduleDto (JSON)
Estimated code review effort🎯 4 (Complex) | ⏱️ ~40 minutes Poem
✨ Finishing Touches🧪 Generate unit tests
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
...in/hs/kr/entrydsm/schedule/domain/schedule/application/service/QueryScheduleByTypeService.kt
Show resolved
Hide resolved
|
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain@coehgns I can help you resolve the CodeRabbit configuration issue. Let me gather information about your current configuration settings to provide specific guidance on enabling auto reviews. 🛠️ Debug Information Gathered @coehgns 이제 문제를 정확히 파악했습니다. 현재 CodeRabbit 구성에서 자동 리뷰가 비활성화되어 있습니다. 문제 원인현재 설정에서 다음과 같이 자동 리뷰가 비활성화되어 있습니다: auto_review:
enabled: false
auto_incremental_review: false해결 방법옵션 1: CodeRabbit UI에서 설정 변경
옵션 2: .coderabbit.yaml 파일 생성/수정리포지토리 루트에 reviews:
auto_review:
enabled: true
auto_incremental_review: true현재 PR에 대한 즉시 해결책지금 이 PR을 리뷰받으려면 다음 명령어를 사용하세요: 설정 변경 후 향후 PR들은 자동으로 리뷰됩니다. 추가 질문이 있으시면 언제든 말씀해 주세요! |
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
1 similar comment
✅ Actions performedReview triggered.
|
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Actionable comments posted: 25
♻️ Duplicate comments (1)
casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/domain/schedule/application/service/QueryScheduleByTypeService.kt (1)
24-27: 잘못된 타입 입력에 대한 예외 처리가 필요합니다.
Type.valueOf(type)는 유효하지 않은 타입 문자열이 전달될 경우IllegalArgumentException을 발생시킵니다. 이에 대한 적절한 예외 처리가 없어 클라이언트에게 명확한 오류 메시지를 제공할 수 없습니다.다음과 같이 예외 처리를 추가하세요:
override fun execute(type: String): ScheduleDto { - val schedule = scheduleFacade.getScheduleByType(Type.valueOf(type)) + val scheduleType = try { + Type.valueOf(type.uppercase()) + } catch (e: IllegalArgumentException) { + throw InvalidScheduleTypeException("유효하지 않은 스케줄 타입입니다: $type") + } + val schedule = scheduleFacade.getScheduleByType(scheduleType) return ScheduleDto(schedule.type, schedule.date) }
🧹 Nitpick comments (22)
detekt.yml (1)
13-15: MagicNumber 규칙 전체 비활성화는 과도합니다—선택적 억제 또는ignoreNumbers확장이 더 적절합니다.
MagicNumber를 전부 끄면 의도치 않은 매직 넘버가 코드베이스 곳곳에 퍼질 수 있어 가독성과 유지보수성이 떨어집니다.
권장 사항:
active: true로 유지하고, 실제 필요에 따라@Suppress("MagicNumber")를 해당 함수/파일 단위로 지정합니다.- 혹은
ignoreNumbers목록에 자주 쓰이는 값(예: 포트, 기본 페이지 크기 등)을 추가하여 규칙을 완화합니다.이전 커밋에서 해당 규칙이 불편을 초래한 구체적 사례가 없다면, 전역 비활성화 대신 위 두 방법을 우선 고려해 주세요.
buildSrc/build.gradle.kts (1)
1-7: 레포지토리 선언에 플러그인 저장소 추가 검토
kotlin-dsl플러그인 자체는 Gradle 배포본에 포함돼 있지만, 향후buildSrc에서 외부 플러그인을 사용할 경우를 대비해gradlePluginPortal()을 함께 선언해 두면 재사용성이 좋아집니다.repositories { + gradlePluginPortal() mavenCentral() }casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/global/error/exception/CasperException.kt (1)
9-11: 예외 메시지 노출 여부 고려현재
RuntimeException의 기본message가 null 이라 스택트레이스만으로 원인을 파악하기 어렵습니다.errorCode.message를super(message)로 전달하거나override val message를 구현해두면 로깅·모니터링 시 가독성이 향상됩니다.-abstract class CasperException( - val errorCode: ErrorCode -) : RuntimeException() +abstract class CasperException( + val errorCode: ErrorCode +) : RuntimeException(errorCode.message)build.gradle.kts (1)
80-82: BootJar 설정을 루트에 두는 경우의 부작용
tasks.withType<BootJar>설정이 루트에서 전체 서브모듈에 적용됩니다. 현 시점엔casper-schedule하나뿐이라 문제없지만, 다른 Spring Boot 모듈이 추가되면mainClass충돌 위험이 있습니다. 해당 설정을casper-schedule/build.gradle.kts로 이동하거나, 대상 프로젝트를 한정해주세요.-tasks.withType<org.springframework.boot.gradle.tasks.bundling.BootJar> { - mainClass.set("hs.kr.entrydsm.schedule.CasperScheduleApplication") -} +project(":casper-schedule") { + tasks.withType<org.springframework.boot.gradle.tasks.bundling.BootJar> { + mainClass.set("hs.kr.entrydsm.schedule.CasperScheduleApplication") + } +}casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/domain/schedule/adapter/in/dto/request/UpdateSchedulesRequest.kt (1)
11-14: 검증 어노테이션 개선을 고려해보세요.현재 구현은 기본적으로 올바르지만 다음 개선사항을 고려해보세요:
data class UpdateSchedulesRequest( - @field:NotNull + @field:NotEmpty + @field:Valid val schedules: List<ScheduleDto> )개선 이유:
@NotEmpty: 빈 리스트 방지 (비즈니스 로직상 의미가 더 적절)@Valid:ScheduleDto내부 필드들의 검증을 위한 중첩 검증 활성화casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/global/error/config/ConfigurationPropertiesConfig.kt (1)
1-12: 패키지 위치가 의도를 혼동시킬 수 있습니다.
global.error.config아래에 두면 “에러 처리 전용 설정”으로 오해하기 쉽습니다.
전역@ConfigurationPropertiesScan용도라면global.config또는 루트configuration등의 보다 일반적인 패키지로 이동하는 편이 명확합니다.buildSrc/src/main/kotlin/PluginVersion.kt (1)
1-8: 버전 업스트림 동향 주기적 점검 권장하드코딩된 버전이 장기간 고정되면 보안 패치 반영이 늦어질 수 있습니다.
dependabot등으로 주기적 업데이트를 자동화하는 방안을 고려해 주세요.casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/global/security/jwt/JwtProperties.kt (1)
15-15: JWT 비밀 키 보안 관리 고려 필요JWT 서명에 사용되는 비밀 키를 properties 파일에 직접 저장하는 것은 보안상 위험할 수 있습니다. 환경 변수나 외부 키 관리 시스템 사용을 고려해보세요.
casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/global/error/exception/ErrorCode.kt (1)
10-27: 잘 구조화된 에러 코드 정의에러 코드가 논리적으로 분류되어 있고, 적절한 HTTP 상태 코드를 사용하고 있습니다. 중앙집중식 에러 처리에 적합한 구조입니다.
일관성을 위해 다음 개선사항을 고려해보세요:
enum class ErrorCode( val status: Int, val message: String ) { - // Internal Server Error + // 5xx - Server Errors INTERNAL_SERVER_ERROR(500, "Internal Server Error"), - // UnAuthorization + // 4xx - Client Errors + // Authorization INVALID_TOKEN(401, "Invalid Token"), EXPIRED_TOKEN(401, "Expired Token"), // Schedule DATE_SEQUENCE_NOT_VALID(400, "Schedule sequence is not valid"), INVALID_SCHEDULE(400, "Schedule list is Empty."), SCHEDULE_NOT_FOUND(404, "Schedule Not Found"), - TYPE_MAPPING_ERROR(400, "Schedule Type Mapping Error") }casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/domain/schedule/application/port/in/QueryScheduleByTypeUseCase.kt (1)
17-17: 타입 안전성 개선 고려현재
String타입을 사용하고 있지만, 도메인의Typeenum을 직접 사용하면 더 타입 안전한 API를 제공할 수 있습니다.- fun execute(type: String): ScheduleDto + fun execute(type: Type): ScheduleDto단, 이 경우 웹 어댑터에서 문자열을 enum으로 변환하는 로직이 필요합니다.
casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/domain/schedule/adapter/out/persistence/repository/ScheduleRepository.kt (1)
25-25: 반환 타입 일관성을 고려해보세요.
findByType()메서드가 nullable을 반환하는 것은 적절하지만, 타입별로 하나의 스케줄만 존재한다는 비즈니스 규칙이 확실하다면Optional<ScheduleJpaEntity>를 사용하는 것을 고려해보세요.Spring Data JPA의 관례를 따라 다음과 같이 수정할 수 있습니다:
+import java.util.Optional + - fun findByType(type: Type): ScheduleJpaEntity? + fun findByType(type: Type): Optional<ScheduleJpaEntity>casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/domain/schedule/application/service/UpdateSchedulesService.kt (2)
13-13: 불필요한 import 제거 필요
kotlin.collections.ifEmpty는 코틀린 표준 라이브러리에 내장된 함수이므로 명시적으로 import할 필요가 없습니다.-import kotlin.collections.ifEmpty
40-47: 배치 처리 성능 최적화 고려 필요현재 구현은 각 스케줄을 개별적으로 조회하고 저장하므로 N+1 문제가 발생할 수 있습니다. 대량의 스케줄 업데이트 시 성능 이슈가 예상됩니다.
배치 처리를 위한 성능 최적화를 고려해보세요:
- 모든 스케줄을 한 번에 조회 후 Map으로 변환
- 배치 저장 기능 활용
casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/domain/schedule/facade/ScheduleFacade.kt (1)
18-21: @component vs @service 어노테이션 선택 검토현재
@Component를 사용하고 있지만, 이 클래스가 비즈니스 로직을 캡슐화하는 파사드 역할을 한다면@Service가 더 적절할 수 있습니다.-@Component +@Servicecasper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/global/error/GlobalExceptionFilter.kt (1)
55-64: 메서드명 오타 수정메서드명이
writerErrorCode로 되어 있는데,writeErrorCode가 더 적절합니다.- private fun writerErrorCode( + private fun writeErrorCode(그리고 호출하는 곳도 수정:
- writerErrorCode(response, e.errorCode) + writeErrorCode(response, e.errorCode) - writerErrorCode(response, ErrorCode.INTERNAL_SERVER_ERROR) + writeErrorCode(response, ErrorCode.INTERNAL_SERVER_ERROR)casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/domain/schedule/application/service/QuerySchedulesService.kt (1)
47-55: 성능 최적화 고려 필요
getCurrentStatus()메서드에서 각 타입별로 개별 조회를 수행하고 있어 N+1 문제가 발생할 수 있습니다.- val firstAnnounce: Schedule = scheduleFacade.getScheduleByType(Type.FIRST_ANNOUNCEMENT) - val interview: Schedule = scheduleFacade.getScheduleByType(Type.INTERVIEW) - val secondAnnounce: Schedule = scheduleFacade.getScheduleByType(Type.SECOND_ANNOUNCEMENT) - - val startDate = scheduleFacade.getScheduleByType(Type.START_DATE).date - val endDate = scheduleFacade.getScheduleByType(Type.END_DATE).date + // 모든 스케줄을 한 번에 조회 후 Map으로 변환하여 사용 + val scheduleMap = findSchedulePort.findAllBy().associateBy { it.type } + + val firstAnnounce = scheduleMap[Type.FIRST_ANNOUNCEMENT] ?: throw ScheduleNotFoundException + val interview = scheduleMap[Type.INTERVIEW] ?: throw ScheduleNotFoundException + val secondAnnounce = scheduleMap[Type.SECOND_ANNOUNCEMENT] ?: throw ScheduleNotFoundException + val startDate = scheduleMap[Type.START_DATE]?.date ?: throw ScheduleNotFoundException + val endDate = scheduleMap[Type.END_DATE]?.date ?: throw ScheduleNotFoundExceptioncasper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/domain/schedule/adapter/in/dto/ScheduleDto.kt (1)
17-17: 타임존 하드코딩 개선 고려사항
Asia/Seoul타임존이 하드코딩되어 있습니다. 향후 국제화나 다른 타임존 지원이 필요할 경우를 대비해 설정 파일이나 상수로 관리하는 것을 검토해보세요.+companion object { + const val DEFAULT_TIMEZONE = "Asia/Seoul" + const val DEFAULT_DATE_PATTERN = "yyyy-MM-dd'T'HH:mm:ss" +} + -@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss", timezone = "Asia/Seoul") +@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = DEFAULT_DATE_PATTERN, timezone = DEFAULT_TIMEZONE)casper-schedule/src/main/proto/schedule.proto (1)
16-18: 날짜 필드 타입 개선 고려사항
GetScheduleResponse의date필드가string타입으로 정의되어 있습니다. 타입 안전성과 표준화를 위해 Google의 Well-Known Types인google.protobuf.Timestamp를 사용하는 것을 고려해보세요.+import "google/protobuf/timestamp.proto"; + message GetScheduleResponse { Type type = 1; - string date = 2; + google.protobuf.Timestamp date = 2; }casper-schedule/build.gradle.kts (1)
60-68: gRPC 의존성 정리 제안gRPC 관련 의존성들이 잘 구성되어 있지만, 가독성을 위해 그룹화와 주석을 개선할 수 있습니다.
- //grpc + // gRPC 서버 및 클라이언트 implementation(Dependencies.GRPC_NETTY_SHADED) implementation(Dependencies.GRPC_PROTOBUF) implementation(Dependencies.GRPC_STUB) + + // Kotlin gRPC 지원 implementation(Dependencies.GRPC_KOTLIN_STUB) implementation(Dependencies.PROTOBUF_KOTLIN) - testImplementation(Dependencies.GRPC_TESTING) implementation(Dependencies.GRPC_SERVER_SPRING) implementation(Dependencies.GOOGLE_PROTOBUF) + + // gRPC 테스트 + testImplementation(Dependencies.GRPC_TESTING)casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/global/error/GlobalExceptionHandler.kt (1)
28-31: 중복된 HttpStatus 설정
ErrorResponse에 이미 status 코드를 전달하고 있는데,ResponseEntity에서 다시 HttpStatus를 설정하고 있습니다. 이는 중복이며 불일치 가능성이 있습니다.다음 중 하나의 방식을 선택하여 일관성을 유지하세요:
return ResponseEntity( ErrorResponse(code.status, code.message), - org.springframework.http.HttpStatus.valueOf(code.status) + HttpStatus.valueOf(code.status) )또는 ResponseEntity.status()를 사용하여 더 명확하게 작성할 수 있습니다:
- return ResponseEntity( - ErrorResponse(code.status, code.message), - org.springframework.http.HttpStatus.valueOf(code.status) - ) + return ResponseEntity.status(code.status) + .body(ErrorResponse(code.status, code.message))casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/domain/schedule/adapter/in/ScheduleWebAdapter.kt (2)
51-55: 반환 타입 명시 누락
updateSchedules메서드에서 반환 타입이 명시되지 않았습니다. 코드 가독성과 유지보수성을 위해 반환 타입을 명시해야 합니다.반환 타입을 명시하세요:
@PatchMapping fun updateSchedules( @RequestBody @Valid request: UpdateSchedulesRequest - ) = updateSchedulesUseCase.execute(request) + ): UpdateSchedulesResponse = updateSchedulesUseCase.execute(request)또는 use case의 반환 타입이 Unit이라면:
- ) = updateSchedulesUseCase.execute(request) + ) { + updateSchedulesUseCase.execute(request) + }
1-1: 패키지명의 백틱 사용Kotlin에서
in은 예약어이므로 백틱으로 감싸는 것이 필요하지만, 가독성을 위해 다른 패키지명 사용을 고려해볼 수 있습니다.
in대신 다음과 같은 대안을 고려해보세요:
inboundwebcontroller예시:
-package hs.kr.entrydsm.schedule.domain.schedule.adapter.`in` +package hs.kr.entrydsm.schedule.domain.schedule.adapter.inbound
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Cache: Disabled due to data retention organization setting
Knowledge Base: Disabled due to data retention organization setting
📒 Files selected for processing (54)
build-logic/build.gradle.kts(0 hunks)build-logic/settings.gradle.kts(0 hunks)build-logic/src/main/kotlin/io/casper/build/TestClass.kt(0 hunks)build.gradle.kts(2 hunks)buildSrc/build.gradle.kts(1 hunks)buildSrc/src/main/kotlin/Dependencies.kt(1 hunks)buildSrc/src/main/kotlin/DependencyVersion.kt(1 hunks)buildSrc/src/main/kotlin/Plugin.kt(1 hunks)buildSrc/src/main/kotlin/PluginVersion.kt(1 hunks)casper-schedule/build.gradle.kts(1 hunks)casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/CasperScheduleApplication.kt(1 hunks)casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/domain/schedule/adapter/in/ScheduleWebAdapter.kt(1 hunks)casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/domain/schedule/adapter/in/dto/ScheduleDto.kt(1 hunks)casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/domain/schedule/adapter/in/dto/request/UpdateSchedulesRequest.kt(1 hunks)casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/domain/schedule/adapter/in/dto/response/SchedulesResponse.kt(1 hunks)casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/domain/schedule/adapter/out/entity/ScheduleJpaEntity.kt(1 hunks)casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/domain/schedule/adapter/out/mapper/ScheduleMapper.kt(1 hunks)casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/domain/schedule/adapter/out/persistence/SchedulePersistenceAdapter.kt(1 hunks)casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/domain/schedule/adapter/out/persistence/repository/ScheduleRepository.kt(1 hunks)casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/domain/schedule/application/exception/InvalidScheduleRequestException.kt(1 hunks)casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/domain/schedule/application/exception/InvalidScheduleSequenceException.kt(1 hunks)casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/domain/schedule/application/exception/ScheduleNotFoundException.kt(1 hunks)casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/domain/schedule/application/port/in/QueryScheduleByTypeUseCase.kt(1 hunks)casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/domain/schedule/application/port/in/QuerySchedulesUseCase.kt(1 hunks)casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/domain/schedule/application/port/in/ScheduleFacadeUseCase.kt(1 hunks)casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/domain/schedule/application/port/in/UpdateSchedulesUseCase.kt(1 hunks)casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/domain/schedule/application/port/out/FindSchedulePort.kt(1 hunks)casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/domain/schedule/application/port/out/SaveSchedulePort.kt(1 hunks)casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/domain/schedule/application/service/QueryScheduleByTypeService.kt(1 hunks)casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/domain/schedule/application/service/QuerySchedulesService.kt(1 hunks)casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/domain/schedule/application/service/UpdateSchedulesService.kt(1 hunks)casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/domain/schedule/facade/ScheduleFacade.kt(1 hunks)casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/domain/schedule/model/Schedule.kt(1 hunks)casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/domain/schedule/model/type/Type.kt(1 hunks)casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/global/error/ErrorResponse.kt(1 hunks)casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/global/error/GlobalExceptionFilter.kt(1 hunks)casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/global/error/GlobalExceptionHandler.kt(1 hunks)casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/global/error/config/ConfigurationPropertiesConfig.kt(1 hunks)casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/global/error/exception/CasperException.kt(1 hunks)casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/global/error/exception/ErrorCode.kt(1 hunks)casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/global/exception/ExpiredTokenException.kt(1 hunks)casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/global/exception/InternalServerErrorException.kt(1 hunks)casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/global/exception/InvalidTokenException.kt(1 hunks)casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/global/security/FilterConfig.kt(1 hunks)casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/global/security/SecurityConfig.kt(1 hunks)casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/global/security/jwt/JwtFilter.kt(1 hunks)casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/global/security/jwt/JwtProperties.kt(1 hunks)casper-schedule/src/main/proto/schedule.proto(1 hunks)casper-schedule/src/test/kotlin/hs/kr/entrydsm/schedule/CasperScheduleApplicationTests.kt(1 hunks)detekt.yml(1 hunks)settings.gradle.kts(1 hunks)src/main/kotlin/hs/kr/entrydsm/schedule/CasperScheduleApplication.kt(0 hunks)src/main/resources/application.properties(0 hunks)src/test/kotlin/hs/kr/entrydsm/schedule/CasperScheduleApplicationTests.kt(0 hunks)
💤 Files with no reviewable changes (6)
- src/main/resources/application.properties
- build-logic/settings.gradle.kts
- build-logic/build.gradle.kts
- build-logic/src/main/kotlin/io/casper/build/TestClass.kt
- src/main/kotlin/hs/kr/entrydsm/schedule/CasperScheduleApplication.kt
- src/test/kotlin/hs/kr/entrydsm/schedule/CasperScheduleApplicationTests.kt
🧰 Additional context used
🪛 detekt (1.23.8)
casper-schedule/src/test/kotlin/hs/kr/entrydsm/schedule/CasperScheduleApplicationTests.kt
[warning] 18-19: This empty block of code can be removed.
(detekt.empty-blocks.EmptyFunctionBlock)
🪛 Buf (1.55.1)
casper-schedule/src/main/proto/schedule.proto
3-3: Files with package "schedule.proto" must be within a directory "schedule/proto" relative to root but were in directory "casper-schedule/src/main/proto".
(PACKAGE_DIRECTORY_MATCH)
🔇 Additional comments (43)
settings.gradle.kts (1)
17-17: casper-schedule 모듈 디렉터리 및 빌드 스크립트 확인 완료
casper-schedule/디렉터리 존재casper-schedule/build.gradle.kts파일 존재위 사항을 검증했으며, Gradle 구성에 문제 없습니다. 추가 작업은 필요하지 않습니다.
build.gradle.kts (1)
10-10: ktlint 버전 다운그레이드 사유 확인12.x → 11.5.1 로 버전이 하향되었습니다. 최신 버전에서 해결된 버그나 CVE 가 다시 발생할 수 있으니, 호환성 문제 때문인지 명시적인 코멘트를 남겨 두면 추후 유지보수 시 혼란을 줄일 수 있습니다.
casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/domain/schedule/application/exception/ScheduleNotFoundException.kt (1)
1-12: LGTM! 잘 구현된 도메인 예외 클래스입니다.헥사고날 아키텍처에서 도메인 예외의 올바른 구현을 보여줍니다:
object선언으로 상태가 없는 예외를 적절히 구현- 기본
CasperException을 확장하여 일관된 예외 계층 구조 유지ErrorCode열거형을 사용하여 에러 코드 중앙 집중화- 명확한 한국어 문서화로 사용 시점 설명
casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/domain/schedule/application/port/out/SaveSchedulePort.kt (1)
1-16: LGTM! 헥사고날 아키텍처의 아웃바운드 포트가 잘 설계되었습니다.포트 인터페이스의 우수한 구현:
- 단일 책임 원칙을 따라 일정 저장만 담당
- 도메인 모델(
Schedule)을 사용하여 영속성 기술과 분리- 명확한 메서드 시그니처와 한국어 문서화
- 인터페이스 분리 원칙을 준수하여 응집도 높음
casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/domain/schedule/adapter/in/dto/request/UpdateSchedulesRequest.kt (1)
1-1: 패키지명의 백틱 사용이 적절합니다.Kotlin에서
in이 예약어이므로 백틱을 사용한 것이 올바른 접근입니다.casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/domain/schedule/application/exception/InvalidScheduleSequenceException.kt (1)
1-12: LGTM! 일관성 있는 예외 설계입니다.다른 도메인 예외들과 일관된 패턴을 따라 잘 구현되었습니다:
- 특정 비즈니스 규칙(일정 순서) 위반에 대한 명확한 예외
object선언으로 상태 없는 예외를 적절히 모델링- 상세한 문서화로 사용 시나리오를 명확히 설명
casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/global/exception/InvalidTokenException.kt (1)
1-12: LGTM! 글로벌 예외의 적절한 배치입니다.보안 관련 예외의 올바른 구현:
- 도메인별 예외와 글로벌 예외를 패키지로 적절히 분리
- JWT 토큰 검증이라는 횡단 관심사에 대한 전용 예외
- 다른 예외들과 일관된 구현 패턴 유지
casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/domain/schedule/application/port/in/UpdateSchedulesUseCase.kt (2)
1-18: 헥사고날 아키텍처 패턴이 잘 적용된 유스케이스 인터페이스입니다.인바운드 포트 패턴을 올바르게 구현했으며, 단일 책임 원칙을 잘 따르고 있습니다. 한국어 문서화도 명확하고 이해하기 쉽습니다.
14-15: UpdateSchedulesUseCase 구현체 및 예외 처리 검증 요청
UpdateSchedulesUseCase인터페이스는 존재하나, 이를 구현한 클래스가 레포지토리 내에서 확인되지 않습니다.
문서에 명시된 예외가 실제 코드에서 던져지는지 아래 사항을 직접 검증해주세요:
- 인터페이스
UpdateSchedulesUseCase를 구현한 클래스 파일 경로 및 패키지 확인- 해당 구현체의 메서드 내에서
InvalidScheduleRequestExceptionInvalidScheduleSequenceException
예외가 실제로 발생(throw)되는지문서의 @throws 주석과 구현체 간 일치 여부를 재검토 부탁드립니다.
casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/domain/schedule/application/exception/InvalidScheduleRequestException.kt (2)
1-12: 잘 구현된 도메인 예외 클래스입니다.Kotlin의 object 패턴을 사용한 싱글톤 예외 구현이 적절하며, CasperException 계층구조를 올바르게 따르고 있습니다. 한국어 문서화도 명확합니다.
11-11: INVALID_SCHEDULE 에러 코드가 정의되어 있습니다
ErrorCode enum(casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/global/error/exception/ErrorCode.kt)에서
INVALID_SCHEDULE(400, "Schedule list is Empty.")가 이미 선언되어 있으므로, 참조에 문제가 없습니다.casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/domain/schedule/model/type/Type.kt (2)
1-13: 명확하고 잘 정의된 도메인 열거형입니다.입학 일정의 단계를 명확하게 표현하고 있으며, 비즈니스 도메인을 잘 반영한 명명이 되어 있습니다. 문서화도 적절합니다.
8-12: Type enum 순서 및 순서 의존성 검증 완료
casper-schedule/src/main/kotlin/…/Type.kt과casper-schedule/src/main/proto/schedule.proto의 enum 정의 순서가 완전히 일치합니다.- 비즈니스 로직(
QuerySchedulesService,QueryScheduleByTypeService등)에서Type을 조회할 때ordinal에 의존하지 않고, 명시적으로Type.START_DATE,Type.FIRST_ANNOUNCEMENT등으로만 사용하고 있어 순서 변경 리스크가 없습니다.따라서 현재 정의를 유지해도 무방합니다.
casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/global/exception/InternalServerErrorException.kt (1)
1-12: 일관성 있게 구현된 글로벌 예외 클래스입니다.다른 예외 클래스들과 동일한 패턴을 따르고 있으며, 서버 내부 오류를 위한 적절한 위치에 배치되어 있습니다. 문서화도 명확합니다.
casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/domain/schedule/application/port/in/QuerySchedulesUseCase.kt (1)
1-16: CQRS 패턴을 잘 구현한 조회 유스케이스입니다.단일 책임을 가진 명확한 조회 인터페이스이며, 문서화도 적절합니다. 헥사고날 아키텍처의 인바운드 포트 패턴을 올바르게 따르고 있습니다.
casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/global/error/ErrorResponse.kt (1)
10-13: ✅ 문제없이 잘 설계된 공통 응답 DTO입니다.필드 정의·가시성 모두 적절하며, 직렬화 라이브러리(Jackson/Kotlin-module)와도 호환됩니다.
추가 의견 없습니다.buildSrc/src/main/kotlin/Plugin.kt (1)
1-11: 플러그인 ID 상수화👍공통 플러그인 ID를 중앙 집중화해 오타·중복을 방지했습니다.
차후 멀티모듈에도 재사용 가능해 유지보수성이 크게 향상됩니다.casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/domain/schedule/application/port/in/QueryScheduleByTypeUseCase.kt (1)
1-1: 백틱 사용으로 Kotlin 예약어 처리
in키워드가 Kotlin 예약어이므로 백틱으로 올바르게 처리했습니다.casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/domain/schedule/application/port/in/ScheduleFacadeUseCase.kt (1)
9-18: Facade 패턴의 올바른 구현외부 시스템과의 인터페이스 역할을 하는 Facade 유스케이스가 잘 정의되어 있습니다.
Typeenum을 직접 사용하여 타입 안전성을 보장하고 있으며, 예외 처리 명세도 명확합니다.casper-schedule/src/test/kotlin/hs/kr/entrydsm/schedule/CasperScheduleApplicationTests.kt (2)
17-19: 컨텍스트 로딩 테스트의 올바른 구현빈 테스트 메서드는 Spring Boot 통합 테스트에서 일반적인 패턴입니다. 애플리케이션 컨텍스트가 성공적으로 로드되는지 확인하는 스모크 테스트 역할을 합니다. 정적 분석 도구의 제거 제안은 무시해도 됩니다.
10-21: Spring Boot 테스트 구조 양호
@SpringBootTest어노테이션을 사용한 통합 테스트 클래스가 적절히 구성되어 있습니다. 새로운 모듈 구조에서 애플리케이션이 정상적으로 시작되는지 확인하는 기본적인 검증을 제공합니다.buildSrc/src/main/kotlin/Dependencies.kt (1)
1-43: 의존성 중앙 관리 구조가 잘 설계되었습니다.카테고리별로 의존성을 체계적으로 그룹화하고
DependencyVersion을 통한 버전 관리가 잘 구현되어 있습니다. 프로젝트의 유지보수성이 크게 향상될 것입니다.casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/domain/schedule/application/port/out/FindSchedulePort.kt (1)
6-24: 헥사고날 아키텍처 아웃바운드 포트가 잘 구현되었습니다.인터페이스 설계가 깔끔하고 메서드 시그니처가 명확합니다. 한국어 문서화도 잘 되어 있으며, nullable 반환 타입 사용이 적절합니다. 클린 아키텍처 원칙을 잘 따르고 있습니다.
buildSrc/src/main/kotlin/DependencyVersion.kt (1)
1-17: 버전 중앙 관리 구조가 우수합니다.의존성 버전을 한 곳에서 관리하는 접근 방식이 훌륭합니다. 버전 업데이트 시 일관성 유지와 유지보수성이 크게 향상될 것입니다.
casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/CasperScheduleApplication.kt (1)
6-21: Spring Boot 애플리케이션 진입점이 올바르게 구현되었습니다.표준 Spring Boot 컨벤션을 잘 따르고 있으며, 한국어 문서화도 충실합니다. 코드가 깔끔하고 최소한의 필요한 요소만 포함되어 있어 좋습니다.
casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/domain/schedule/model/Schedule.kt (1)
6-28: 도메인 모델이 우수하게 설계되었습니다.불변성을 유지하는 데이터 클래스 설계가 훌륭하고,
updateDate메서드가 새 인스턴스를 반환하여 불변성 원칙을 잘 따르고 있습니다. 한국어 문서화가 매우 상세하며 도메인 주도 설계 원칙에 부합합니다.casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/domain/schedule/adapter/out/mapper/ScheduleMapper.kt (1)
11-28: LGTM!MapStruct 매퍼 구현이 올바르게 되어 있습니다. Spring 컴포넌트 모델 설정과 메서드 시그니처가 적절하며, 도메인 모델과 JPA 엔티티 간의 변환을 깔끔하게 처리합니다.
casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/global/security/SecurityConfig.kt (1)
50-50: FilterConfig 의존성 확인 완료
casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/global/security/FilterConfig.kt에서class FilterConfig구현 확인casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/global/security/jwt/JwtFilter.kt에서class JwtFilter구현 확인casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/global/error/GlobalExceptionFilter.kt에서class GlobalExceptionFilter구현 확인위 클래스들이 모두 정상적으로 구현되어 있으므로 추가 검토나 수정은 필요하지 않습니다.
casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/domain/schedule/application/service/UpdateSchedulesService.kt (1)
43-45: 날짜 비교 경계 조건 명확화 필요
UpdateSchedulesService.kt(43–45)에서는 오직 이전 일정의 날짜가 새 날짜보다 뒤인 경우에만 InvalidScheduleSequenceException을 던지고, 동일한 날짜는 허용하고 있습니다. 반면 QuerySchedulesService.kt에서는 isEqual을 적극 활용해 “동일 날짜”를 별도로 처리하고 있으므로, 비즈니스 요구사항에 따라 UpdateSchedulesService에서도 동일한 날짜 허용 여부를 명확히 정의해야 합니다.예시) 동일 날짜도 금지하려면:
if (index != 0 && (scheduleDtoList[index - 1].date.isAfter(scheduleDto.date) || scheduleDtoList[index - 1].date.isEqual(scheduleDto.date)) ) { throw InvalidScheduleSequenceException }검토 항목:
- UpdateSchedulesService.kt (43–45): 동일 날짜 허용 여부 검토 및 경계 조건(isEqual) 추가 여부 결정
- QuerySchedulesService.kt: 날짜 비교 로직 경계 처리와 일치하는지 확인
비즈니스 룰에 맞춰 경계 조건을 확실히 정의해주세요.
casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/domain/schedule/facade/ScheduleFacade.kt (1)
29-32: LGTM! 깔끔한 파사드 패턴 구현파사드 패턴이 올바르게 구현되어 있으며, 의존성 주입과 예외 처리도 적절합니다. Elvis 연산자를 사용한 null 처리가 코틀린답고 간결합니다.
casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/domain/schedule/adapter/out/persistence/SchedulePersistenceAdapter.kt (3)
18-22: LGTM! 헥사고날 아키텍처 원칙 준수Persistence Adapter가 올바르게 구현되어 있습니다. 도메인과 영속성 계층 간의 분리가 잘 되어 있고, 의존성 주입도 적절합니다.
29-31: Null 처리 로직 확인
let블록을 사용한 null 처리가 적절합니다. Repository에서 null을 반환할 때 적절히 처리되고 있습니다.
48-50: 저장 로직 및 반환 처리 적합 확인
ScheduleRepository가JpaRepository<…, Int>를 상속해save()호출 시 영속화된 엔티티를 반환- 반환된 엔티티를
scheduleMapper.toModel()로 도메인 모델로 변환하는 패턴이 다른 조회 메서드(findByType,findAllBy)와 일관되게 사용됨- 별도의 문제나 추가 검증 요청 사항 없습니다.
casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/domain/schedule/application/service/QuerySchedulesService.kt (2)
31-39: LGTM! 깔끔한 서비스 구현모든 스케줄을 조회하고 DTO로 변환하는 로직이 잘 구현되어 있습니다. 함수형 프로그래밍 스타일의 map 사용도 적절합니다.
66-66: InvalidScheduleSequenceException 처리 로직이 적절함 확인됨
QuerySchedulesService 와 UpdateSchedulesService 에서 모두 스케줄 순서가 유효하지 않은 상황에 대해 일관되게InvalidScheduleSequenceException을 던지고 있으며, 예외 클래스의 설명(일정의 시작일이 종료일보다 늦거나, 이전 일정과의 순서가 맞지 않는 경우 발생)도 적용 대상과 일치합니다.casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/domain/schedule/adapter/in/dto/ScheduleDto.kt (1)
14-20: 헥사고날 아키텍처 패턴 잘 적용됨DTO 설계가 우수합니다. 불변 데이터 클래스, 적절한 검증 어노테이션, 명확한 JSON 포맷팅이 잘 구현되어 있으며 헥사고날 아키텍처의 어댑터 계층에 적합한 구조입니다.
casper-schedule/src/main/proto/schedule.proto (1)
8-10: gRPC 서비스 정의 구조 우수함서비스 인터페이스가 명확하고 RESTful한 스타일로 잘 설계되었습니다. 타입별 스케줄 조회 기능이 단순하고 효과적으로 정의되어 있습니다.
casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/global/security/jwt/JwtFilter.kt (1)
65-70: UserRole 열거형 구조 적절함역할 정의가 명확하고 권한 수준이 잘 구분되어 있습니다. 각 역할의 용도가 주석으로 잘 설명되어 있어 유지보수성이 좋습니다.
casper-schedule/build.gradle.kts (2)
72-94: Protobuf 설정 구성 우수함gRPC 코드 생성을 위한 Protobuf 플러그인 설정이 잘 구성되어 있습니다. Java와 Kotlin gRPC stub 생성을 모두 지원하며, 버전 관리도 중앙화되어 있어 유지보수성이 좋습니다.
4-12: 플러그인 구성 및 중앙화된 버전 관리 우수함플러그인 ID와 버전이 중앙화되어 관리되고 있어 일관성과 유지보수성이 뛰어납니다. 헥사고날 아키텍처 구현에 필요한 모든 플러그인이 적절히 포함되어 있습니다.
casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/global/security/FilterConfig.kt (2)
34-38: 필터 체인 순서 확인
addFilterBefore의 호출 순서로 인해 최종 필터 실행 순서가 GlobalExceptionFilter -> JwtFilter -> UsernamePasswordAuthenticationFilter가 됩니다. 예외 처리가 가장 먼저 실행되는 것이 올바른 설계입니다.
18-21: Spring Security 설정 패턴 우수함
SecurityConfigurerAdapter를 적절히 확장하여 필터 체인을 구성하고 있으며, 의존성 주입도 올바르게 구현되어 있습니다. 컴포넌트 스캔을 통한 빈 등록도 적절합니다.casper-schedule/src/main/kotlin/hs/kr/entrydsm/schedule/domain/schedule/adapter/in/ScheduleWebAdapter.kt (1)
25-31: 헥사고날 아키텍처 패턴 준수 확인이 adapter는 헥사고날 아키텍처의 input adapter로서 올바른 구조를 가지고 있습니다. use case 인터페이스에만 의존하고 있어 의존성 역전 원칙을 잘 따르고 있습니다.
Summary by CodeRabbit
신규 기능
버그 수정
문서화
테스트
환경설정/빌드
기타