feat(identity): 계정 Account API와 JPA 저장소 구성 #48 - #54
Conversation
|
Important Review skippedAuto reviews are limited based on label configuration. 🏷️ Required labels (at least one) (1)
🚫 Excluded labels (none allowed) (2)
Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 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
`@systems/identity/identity-adapter-in/src/test/kotlin/hs/kr/entrydsm/identity/adapterin/web/AccountControllerTest.kt`:
- Around line 17-27: Extend AccountControllerTest beyond
getMePassesAuthorizationAndReturnsBasicInfo to cover deleteMe authorization
propagation through the account port, and add a deterministic unauthenticated
web-layer test asserting the documented 401 status and AUTH_UNAUTHORIZED
response code. Use the existing fake port and controller symbols, with
meaningful assertions for both the forwarded Authorization value and the
missing-Authorization behavior.
In
`@systems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/entity/StudentProfileJpaEntity.kt`:
- Around line 42-43: Update StudentProfileJpaEntity.birthdate from String to
LocalDate and map it to a non-nullable DATE column, keeping the existing
required-field behavior. Adjust JpaAccountRepositoryAdapter and any related
persistence mapping so the domain-facing string conversion remains correct
without calling LocalDate.parse on an already typed value.
In
`@systems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/repository/JpaAccountRepositoryAdapter.kt`:
- Around line 27-90:
systems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/repository/JpaAccountRepositoryAdapter.kt:27-90에
JPA 통합 테스트를 추가해 신규 계정·프로필 저장 및 재조회, 기존 프로필 갱신과 도메인 변환을 검증하세요.
systems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/base/BaseTimeEntity.kt:11-24의
createdAt·updatedAt 감사 시간 매핑도 검증하고,
systems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/repository/AccountJpaRepository.kt:6-8
및
systems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/repository/StudentProfileJpaRepository.kt:6-8의
로그인 ID·계정 ID 조회 쿼리 결과를 각각 확인하세요.
In
`@systems/identity/identity-application/src/main/kotlin/hs/kr/entrydsm/identity/application/service/AccountService.kt`:
- Around line 11-14: AccountService에서 Spring의 `@Service` 의존성을 제거해 애플리케이션 서비스를
프레임워크 비의존 클래스로 유지하고, bootstrap 구성에서 AccountService를 빈으로 명시 등록하세요. 실제 삭제·조회 동작을
검증하는 AccountService 테스트를 추가해 Kotlin production 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 Plus
Run ID: 614bc68a-5ec2-4085-b025-4a0cf410f371
📒 Files selected for processing (18)
systems/identity/identity-adapter-in/src/main/kotlin/hs/kr/entrydsm/identity/adapterin/web/AccountController.ktsystems/identity/identity-adapter-in/src/test/kotlin/hs/kr/entrydsm/TestMain.ktsystems/identity/identity-adapter-in/src/test/kotlin/hs/kr/entrydsm/identity/adapterin/web/AccountControllerTest.ktsystems/identity/identity-adapter-out/BUILD.bazelsystems/identity/identity-adapter-out/deps.bzlsystems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/base/BaseTimeEntity.ktsystems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/config/JpaAuditingConfig.ktsystems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/entity/AccountJpaEntity.ktsystems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/entity/StudentProfileJpaEntity.ktsystems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/repository/AccountJpaRepository.ktsystems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/repository/JpaAccountRepositoryAdapter.ktsystems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/repository/StudentProfileJpaRepository.ktsystems/identity/identity-application/src/main/kotlin/hs/kr/entrydsm/identity/application/port/in/AccountPort.ktsystems/identity/identity-application/src/main/kotlin/hs/kr/entrydsm/identity/application/port/in/command/DeleteAccountCommand.ktsystems/identity/identity-application/src/main/kotlin/hs/kr/entrydsm/identity/application/port/in/command/ReadAccountCommand.ktsystems/identity/identity-application/src/main/kotlin/hs/kr/entrydsm/identity/application/service/AccountService.ktsystems/identity/identity-domain/src/test/kotlin/hs/kr/entrydsm/TestMain.ktsystems/identity/identity-domain/src/test/kotlin/hs/kr/entrydsm/identity/domain/StudentProfileTest.kt
📜 Review details
🧰 Additional context used
📓 Path-based instructions (8)
**/*.{kt,go}
📄 CodeRabbit inference engine (Custom checks)
If production logic is changed in Kotlin or Go files, require corresponding test updates in the same subsystem unless the PR description explicitly justifies why tests are unnecessary
Files:
systems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/repository/StudentProfileJpaRepository.ktsystems/identity/identity-application/src/main/kotlin/hs/kr/entrydsm/identity/application/port/in/command/ReadAccountCommand.ktsystems/identity/identity-adapter-in/src/test/kotlin/hs/kr/entrydsm/identity/adapterin/web/AccountControllerTest.ktsystems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/config/JpaAuditingConfig.ktsystems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/base/BaseTimeEntity.ktsystems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/repository/AccountJpaRepository.ktsystems/identity/identity-application/src/main/kotlin/hs/kr/entrydsm/identity/application/port/in/command/DeleteAccountCommand.ktsystems/identity/identity-application/src/main/kotlin/hs/kr/entrydsm/identity/application/port/in/AccountPort.ktsystems/identity/identity-domain/src/test/kotlin/hs/kr/entrydsm/identity/domain/StudentProfileTest.ktsystems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/entity/AccountJpaEntity.ktsystems/identity/identity-domain/src/test/kotlin/hs/kr/entrydsm/TestMain.ktsystems/identity/identity-application/src/main/kotlin/hs/kr/entrydsm/identity/application/service/AccountService.ktsystems/identity/identity-adapter-in/src/test/kotlin/hs/kr/entrydsm/TestMain.ktsystems/identity/identity-adapter-in/src/main/kotlin/hs/kr/entrydsm/identity/adapterin/web/AccountController.ktsystems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/entity/StudentProfileJpaEntity.ktsystems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/repository/JpaAccountRepositoryAdapter.kt
**/*.{java,kt,scala,groovy,go,js,ts,tsx,jsx,py,rb,rs,cpp,c,h,hpp,cs}
📄 CodeRabbit inference engine (Custom checks)
Flag TODO/FIXME comments introduced by this PR that do not include an issue reference in the form
#123or a full tracker key like PROJ-123
Files:
systems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/repository/StudentProfileJpaRepository.ktsystems/identity/identity-application/src/main/kotlin/hs/kr/entrydsm/identity/application/port/in/command/ReadAccountCommand.ktsystems/identity/identity-adapter-in/src/test/kotlin/hs/kr/entrydsm/identity/adapterin/web/AccountControllerTest.ktsystems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/config/JpaAuditingConfig.ktsystems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/base/BaseTimeEntity.ktsystems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/repository/AccountJpaRepository.ktsystems/identity/identity-application/src/main/kotlin/hs/kr/entrydsm/identity/application/port/in/command/DeleteAccountCommand.ktsystems/identity/identity-application/src/main/kotlin/hs/kr/entrydsm/identity/application/port/in/AccountPort.ktsystems/identity/identity-domain/src/test/kotlin/hs/kr/entrydsm/identity/domain/StudentProfileTest.ktsystems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/entity/AccountJpaEntity.ktsystems/identity/identity-domain/src/test/kotlin/hs/kr/entrydsm/TestMain.ktsystems/identity/identity-application/src/main/kotlin/hs/kr/entrydsm/identity/application/service/AccountService.ktsystems/identity/identity-adapter-in/src/test/kotlin/hs/kr/entrydsm/TestMain.ktsystems/identity/identity-adapter-in/src/main/kotlin/hs/kr/entrydsm/identity/adapterin/web/AccountController.ktsystems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/entity/StudentProfileJpaEntity.ktsystems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/repository/JpaAccountRepositoryAdapter.kt
**/*.kt
⚙️ CodeRabbit configuration file
**/*.kt: Apply Kotlin Official Coding Conventions.Formatting and structure:
- Use 4 spaces for indentation; no tabs.
- Keep files focused and readable; avoid horizontal alignment for spacing.
- Place related declarations together and keep overloads adjacent.
- Keep implementation member order stable and logical for readability.
Naming:
- Package names are lowercase and do not use underscores.
- Class/object names use UpperCamelCase.
- Functions/properties/local variables use lowerCamelCase.
- Constants use UPPER_SNAKE_CASE only for true constants.
API and null-safety:
- Avoid platform type leakage in public APIs.
- Use explicit types in public APIs when inference obscures meaning.
- Prefer immutable values (
val) over mutable values (var) unless mutation is required.- Flag nullable flows that can be replaced with safer modeling.
Imports and idioms:
- Avoid wildcard imports unless justified by language/tooling conventions.
- Prefer expression bodies for short, clear functions.
- Prefer standard library idioms over custom utility wrappers when equivalent.
Architecture and tests:
- Respect module boundaries (domain/application/adapter/bootstrap layering).
- Highlight behavior-changing code that lacks corresponding unit/integration tests.
- Ask for deterministic tests and meaningful assertions, not only happy-path checks.
Files:
systems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/repository/StudentProfileJpaRepository.ktsystems/identity/identity-application/src/main/kotlin/hs/kr/entrydsm/identity/application/port/in/command/ReadAccountCommand.ktsystems/identity/identity-adapter-in/src/test/kotlin/hs/kr/entrydsm/identity/adapterin/web/AccountControllerTest.ktsystems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/config/JpaAuditingConfig.ktsystems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/base/BaseTimeEntity.ktsystems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/repository/AccountJpaRepository.ktsystems/identity/identity-application/src/main/kotlin/hs/kr/entrydsm/identity/application/port/in/command/DeleteAccountCommand.ktsystems/identity/identity-application/src/main/kotlin/hs/kr/entrydsm/identity/application/port/in/AccountPort.ktsystems/identity/identity-domain/src/test/kotlin/hs/kr/entrydsm/identity/domain/StudentProfileTest.ktsystems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/entity/AccountJpaEntity.ktsystems/identity/identity-domain/src/test/kotlin/hs/kr/entrydsm/TestMain.ktsystems/identity/identity-application/src/main/kotlin/hs/kr/entrydsm/identity/application/service/AccountService.ktsystems/identity/identity-adapter-in/src/test/kotlin/hs/kr/entrydsm/TestMain.ktsystems/identity/identity-adapter-in/src/main/kotlin/hs/kr/entrydsm/identity/adapterin/web/AccountController.ktsystems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/entity/StudentProfileJpaEntity.ktsystems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/repository/JpaAccountRepositoryAdapter.kt
**/*-application/**/*.{java,kt,scala,groovy}
📄 CodeRabbit inference engine (Custom checks)
For files under *-application modules, flag direct dependency on infrastructure-specific framework classes unless justified
Files:
systems/identity/identity-application/src/main/kotlin/hs/kr/entrydsm/identity/application/port/in/command/ReadAccountCommand.ktsystems/identity/identity-application/src/main/kotlin/hs/kr/entrydsm/identity/application/port/in/command/DeleteAccountCommand.ktsystems/identity/identity-application/src/main/kotlin/hs/kr/entrydsm/identity/application/port/in/AccountPort.ktsystems/identity/identity-application/src/main/kotlin/hs/kr/entrydsm/identity/application/service/AccountService.kt
**/*-domain/**/*.{java,kt,scala,groovy}
📄 CodeRabbit inference engine (Custom checks)
For files under *-domain modules, fail if imports reference adapter or bootstrap packages
Files:
systems/identity/identity-domain/src/test/kotlin/hs/kr/entrydsm/identity/domain/StudentProfileTest.ktsystems/identity/identity-domain/src/test/kotlin/hs/kr/entrydsm/TestMain.kt
**/{BUILD.bazel,*.bzl}
📄 CodeRabbit inference engine (Custom checks)
In BUILD.bazel and .bzl files, require buildifier-compatible formatting and stable target naming
Files:
systems/identity/identity-adapter-out/deps.bzlsystems/identity/identity-adapter-out/BUILD.bazel
**/*.bzl
⚙️ CodeRabbit configuration file
**/*.bzl: Apply Bazel Starlark (.bzl) style guidance.Readability and docs:
- Keep file/module docstrings and docstrings for public functions/macros.
- Use descriptive parameter names and document attribute intent.
API design:
- Macros should take a
nameargument and derive generated target names from it.- Prefer keyword arguments when calling macros for clarity and stability.
- Keep macro side effects predictable and visible.
Encapsulation:
- Use private visibility for helper targets created by macros unless explicitly public.
- Avoid exposing internal implementation targets unintentionally.
Tooling:
- Enforce buildifier formatting and lint compliance.
Files:
systems/identity/identity-adapter-out/deps.bzl
**/BUILD.bazel
⚙️ CodeRabbit configuration file
**/BUILD.bazel: Apply Bazel BUILD style guidance.Core rules:
- BUILD formatting must match buildifier output.
- Prefer DAMP BUILD files over over-abstracted DRY patterns.
- Keep top-level layout clear: load() first, then package/default visibility, then targets.
Target definitions:
- Keep deps explicit and close to each target's real direct dependencies.
- Avoid recursive globs unless there is a clear, documented reason.
- Avoid top-level list comprehensions for generating many targets.
- Prefer literal labels and stable naming for readability and tooling compatibility.
- Use boolean values (True/False), not numeric stand-ins.
Maintenance:
- Flag duplicated target logic that should be moved into a macro.
- Flag macro usage that hides important dependency or visibility decisions.
Files:
systems/identity/identity-adapter-out/BUILD.bazel
🔇 Additional comments (13)
systems/identity/identity-application/src/main/kotlin/hs/kr/entrydsm/identity/application/port/in/AccountPort.kt (1)
1-11: LGTM!systems/identity/identity-application/src/main/kotlin/hs/kr/entrydsm/identity/application/port/in/command/DeleteAccountCommand.kt (1)
1-5: LGTM!systems/identity/identity-application/src/main/kotlin/hs/kr/entrydsm/identity/application/port/in/command/ReadAccountCommand.kt (1)
1-5: LGTM!systems/identity/identity-application/src/main/kotlin/hs/kr/entrydsm/identity/application/service/AccountService.kt (1)
19-39: 📐 Maintainability & Code Quality
AccountService에 대응하는 애플리케이션 계층 테스트를 추가하거나 확인해 주세요.삭제 시각 주입, 인증 실패 처리,
BasicInfoResult전체 필드 매핑을 검증하는 결정적 서비스 테스트가 필요합니다. 제공된 PR 테스트 목록에는 controller/domain 테스트만 확인되므로, application 서브시스템 테스트가 이미 존재하는지 확인하고 없다면 추가해 주세요.As per coding guidelines: Kotlin production logic 변경에는 같은 서브시스템의 대응 테스트가 필요하며, 불필요한 경우 PR 설명에 명시적인 정당화가 있어야 합니다.
Source: Coding guidelines
systems/identity/identity-adapter-out/BUILD.bazel (1)
11-11: LGTM!systems/identity/identity-adapter-out/deps.bzl (1)
1-6: LGTM!systems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/config/JpaAuditingConfig.kt (1)
1-8: LGTM!systems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/entity/AccountJpaEntity.kt (1)
1-34: LGTM!systems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/entity/StudentProfileJpaEntity.kt (1)
1-41: LGTM!Also applies to: 45-58
systems/identity/identity-adapter-in/src/main/kotlin/hs/kr/entrydsm/identity/adapterin/web/AccountController.kt (1)
21-35: LGTM!systems/identity/identity-adapter-in/src/test/kotlin/hs/kr/entrydsm/TestMain.kt (1)
3-17: LGTM!systems/identity/identity-domain/src/test/kotlin/hs/kr/entrydsm/identity/domain/StudentProfileTest.kt (1)
11-29: LGTM!systems/identity/identity-domain/src/test/kotlin/hs/kr/entrydsm/TestMain.kt (1)
6-10: 🎯 Functional Correctness수정이 필요 없습니다.
TestMain.kt이hs.kr.entrydsm.identity.domain패키지 안에 있고,AccountTest,StudentProfileTest도 같은 패키지이므로 import 생략이 컴팩과 무관합니다.
| fun getMePassesAuthorizationAndReturnsBasicInfo() { | ||
| val accountPort = FakeAccountPort() | ||
| val controller = AccountController(accountPort) | ||
|
|
||
| val response = controller.getMe("Bearer access-token") | ||
|
|
||
| val command = requireNotNull(accountPort.readAccountCommand) | ||
| assertEquals("Bearer access-token", command.authorization) | ||
| assertEquals("user_123", response.data?.userId) | ||
| assertEquals(ApplicantStatus.SUBMITTED, response.data?.applicantStatus) | ||
| } |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
DELETE /me와 미인증 계약도 검증하세요.
현재 테스트는 getMe만 호출합니다. deleteMe의 Authorization 전달과, Authorization 누락 시 명세대로 401 AUTH_UNAUTHORIZED가 되는 웹 계층 경로를 추가로 검증하세요.
As per coding guidelines, “If production logic is changed in Kotlin or Go files, require corresponding test updates in the same subsystem unless the PR description explicitly justifies why tests are unnecessary.”
As per path instructions, “Ask for deterministic tests and meaningful assertions, not only happy-path checks.”
🤖 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
`@systems/identity/identity-adapter-in/src/test/kotlin/hs/kr/entrydsm/identity/adapterin/web/AccountControllerTest.kt`
around lines 17 - 27, Extend AccountControllerTest beyond
getMePassesAuthorizationAndReturnsBasicInfo to cover deleteMe authorization
propagation through the account port, and add a deterministic unauthenticated
web-layer test asserting the documented 401 status and AUTH_UNAUTHORIZED
response code. Use the existing fake port and controller symbols, with
meaningful assertions for both the forwarded Authorization value and the
missing-Authorization behavior.
Sources: Coding guidelines, Path instructions
| @Column(name = "birthdate", nullable = false, length = 255) | ||
| val birthdate: String = "", |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== candidate files =="
fd -a 'StudentProfileJpaEntity\.kt|JpaAccountRepositoryAdapter\.kt' . || true
echo "== git diff stat =="
git diff --stat HEAD || true
echo "== grep birthdate usages =="
rg -n "birthdate|birth" -S . || true
echo "== inspect StudentProfileJpaEntity =="
file=$(fd 'StudentProfileJpaEntity\.kt' . | head -n1 || true)
if [ -n "${file:-}" ]; then
wc -l "$file"
cat -n "$file"
fi
echo "== inspect adapter outline/content around toDomain =="
adapter=$(fd 'JpaAccountRepositoryAdapter\.kt' . | head -n1 || true)
if [ -n "${adapter:-}" ]; then
wc -l "$adapter"
ast-grep outline "$adapter" || true
rg -n "toDomain|birthdate|StudentProfileJpaEntity|LocalDate" -C 8 "$adapter" || true
fiRepository: EntryDSM/entrydsm-platform
Length of output: 8873
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== student profile domain/model =="
profileDomain=$(fd 'StudentProfile\.kt' systems/identity/identity-domain systems/identity 2>/dev/null | head -n5)
for f in $profileDomain; do
echo "--- $f"
wc -l "$f"
sed -n '1,220p' "$f"
done
echo "== input/profile creation sources =="
rg -n "StudentProfile\(.*birthdate|profile\.birthdate|birthdate\s*=" -S systems/identity/identity-application systems/identity/identity-adapter-in systems/identity/identity-domain -C 4 || true
echo "== focused test files =="
testFiles=$(fd 'StudentProfileTest\.kt|AccountControllerTest\.kt|.*Test\.kt' systems/identity -e kt 2>/dev/null | head -n 20)
for f in $testFiles; do
if rg -q "birthdate|StudentProfile" "$f"; then
echo "--- $f"
wc -l "$f"
sed -n '1,220p' "$f"
fi
doneRepository: EntryDSM/entrydsm-platform
Length of output: 7970
생년월일은 문자열에서 LocalDate로 매핑해 주세요.
StudentProfileJpaEntity는 birthdate: String + VARCHAR(255)로 저장하지만, JpaAccountRepositoryAdapter.kt:83에서 LocalDate.parse(birthdate)로 변환합니다. DB가 날짜 형식을 검증하지 않아 잘못된 값이 저장되면 계정 조회가 예외가 됩니다. birthdate를 LocalDate/DATE로 맞춰주고, 문자열 매핑을 유지해야 한다면 엄격한 converter 및 입력 검증으로 2009-03-15 형식을 강제해 주세요.
🤖 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
`@systems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/entity/StudentProfileJpaEntity.kt`
around lines 42 - 43, Update StudentProfileJpaEntity.birthdate from String to
LocalDate and map it to a non-nullable DATE column, keeping the existing
required-field behavior. Adjust JpaAccountRepositoryAdapter and any related
persistence mapping so the domain-facing string conversion remains correct
without calling LocalDate.parse on an already typed value.
| override fun save(account: Account): Account { | ||
| val existing = accountJpaRepository.findById(account.userId).orElse(null) | ||
| ?.takeIf { it.loginIdHash == account.loginId } | ||
| val entity = if (existing == null) { | ||
| AccountJpaEntity( | ||
| loginIdHash = account.loginId, | ||
| passwordHash = account.passwordForPersistence(), | ||
| role = account.role, | ||
| status = account.status, | ||
| ) | ||
| } else { | ||
| existing.apply { | ||
| passwordHash = account.passwordForPersistence() | ||
| status = account.status | ||
| } | ||
| } | ||
| val savedAccount = accountJpaRepository.saveAndFlush(entity) | ||
| val savedUserId = requireNotNull(savedAccount.id) | ||
| val profile = studentProfileJpaRepository.findByAccount_Id(savedUserId) | ||
| ?: StudentProfileJpaEntity( | ||
| account = savedAccount, | ||
| signupType = account.profile.signupType, | ||
| nameEncrypted = account.profile.name, | ||
| phoneEncrypted = account.profile.phone, | ||
| birthdate = account.profile.birthdate.toString(), | ||
| ) | ||
| profile.applicantStatus = account.profile.applicantStatus | ||
| profile.passStatus = account.profile.passStatus | ||
| profile.submittedAt = account.profile.submittedAt | ||
| profile.announcedAt = account.profile.announcedAt | ||
| val savedProfile = studentProfileJpaRepository.saveAndFlush(profile) | ||
| return savedAccount.toDomain(savedProfile) | ||
| } | ||
|
|
||
| private fun AccountJpaEntity.toDomain(profile: StudentProfileJpaEntity? = null): Account { | ||
| val resolvedProfile = profile ?: requireNotNull(id) { "Account ID must be present" } | ||
| .let { studentProfileJpaRepository.findByAccount_Id(it) } | ||
| ?: error("Student profile not found for account $id") | ||
| val createdAt = createdAtValue() ?: Instant.EPOCH | ||
| val updatedAt = updatedAtValue() ?: createdAt | ||
| return Account.create( | ||
| userId = requireNotNull(id), | ||
| loginId = loginIdHash, | ||
| password = passwordHash, | ||
| role = role, | ||
| status = status, | ||
| profile = resolvedProfile.toDomain(updatedAt), | ||
| createdAt = createdAt, | ||
| updatedAt = updatedAt, | ||
| ) | ||
| } | ||
|
|
||
| private fun StudentProfileJpaEntity.toDomain(accountUpdatedAt: Instant): StudentProfile = | ||
| StudentProfile( | ||
| name = nameEncrypted, | ||
| phone = phoneEncrypted, | ||
| birthdate = LocalDate.parse(birthdate), | ||
| signupType = signupType, | ||
| applicantStatus = applicantStatus, | ||
| passStatus = passStatus, | ||
| submittedAt = submittedAt, | ||
| announcedAt = announcedAt, | ||
| updatedAt = updatedAtValue() ?: accountUpdatedAt, | ||
| ) |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟠 Major | 🏗️ Heavy lift
새 JPA 영속성 경로에 adapter-out 테스트를 추가하세요.
계정/프로필 저장·재조회, 기존 프로필 갱신, 두 조회 쿼리, 감사 시간 매핑을 검증하는 동일 서브시스템의 JPA 통합 테스트가 없습니다.
systems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/repository/JpaAccountRepositoryAdapter.kt#L27-L90: 신규 저장과 기존 엔티티 갱신 후 도메인 변환 결과를 검증하세요.systems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/base/BaseTimeEntity.kt#L11-L24: 저장 시createdAt·updatedAt감사 값이 채워지는지 검증하세요.systems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/repository/AccountJpaRepository.kt#L6-L8: 로그인 ID 조회 결과를 검증하세요.systems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/repository/StudentProfileJpaRepository.kt#L6-L8: 계정 ID 기반 프로필 조회 결과를 검증하세요.
As per coding guidelines, “If production logic is changed in Kotlin or Go files, require corresponding test updates in the same subsystem unless the PR description explicitly justifies why tests are unnecessary.”
As per path instructions, “Highlight behavior-changing code that lacks corresponding unit/integration tests.”
📍 Affects 4 files
systems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/repository/JpaAccountRepositoryAdapter.kt#L27-L90(this comment)systems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/base/BaseTimeEntity.kt#L11-L24systems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/repository/AccountJpaRepository.kt#L6-L8systems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/repository/StudentProfileJpaRepository.kt#L6-L8
🤖 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
`@systems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/repository/JpaAccountRepositoryAdapter.kt`
around lines 27 - 90,
systems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/repository/JpaAccountRepositoryAdapter.kt:27-90에
JPA 통합 테스트를 추가해 신규 계정·프로필 저장 및 재조회, 기존 프로필 갱신과 도메인 변환을 검증하세요.
systems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/base/BaseTimeEntity.kt:11-24의
createdAt·updatedAt 감사 시간 매핑도 검증하고,
systems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/repository/AccountJpaRepository.kt:6-8
및
systems/identity/identity-adapter-out/src/main/kotlin/hs/kr/entrydsm/identity/adapterout/repository/StudentProfileJpaRepository.kt:6-8의
로그인 ID·계정 ID 조회 쿼리 결과를 각각 확인하세요.
Sources: Coding guidelines, Path instructions
| import org.springframework.stereotype.Service | ||
|
|
||
| @Service | ||
| class AccountService( |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟠 Major | 🏗️ Heavy lift
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== files =="
git ls-files | rg 'systems/identity|build\.kts|gradle|settings|identity-application' | head -200
echo "== AccountService =="
fd -a 'AccountService\.kt$' . | while read -r f; do
echo "--- $f"
wc -l "$f"
sed -n '1,220p' "$f"
done
echo "== Spring stereotype usages in identity-application =="
rg -n "import org\.springframework\.stereotype|`@Service`|`@Component`|`@ConfigurationProperties`|SpringBootApplication" systems/identity/identity-application || true
echo "== module build files =="
fd -a 'build\.kt*|gradle\.kts|settings\.kt*|settings\.gradle' systems/identity or fd . systems/identity | rg 'build\.kts|gradle\.kts|settings' | head -50
for f in $(fd 'build\.kts|gradle\.kts' systems/identity); do
echo "--- $f"
sed -n '1,220p' "$f"
doneRepository: EntryDSM/entrydsm-platform
Length of output: 5883
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== application module Bazel files =="
for f in systems/identity/identity-application/BUILD.bazel systems/identity/identity-dependencies.bzl systems/identity/identity-application/deps.bzl; do
if [ -f "$f" ]; then
echo "--- $f"
sed -n '1,220p' "$f"
fi
done
echo "== identity service registration/usages =="
rg -n "AccountService|ApplicationDataPort|AccountRepository|AccountPort|compose|register|bootstrap|component|koin|Dagger" systems/identity -g '*.kt' || true
echo "== test files under identity-application =="
fd . systems/identity/identity-application/src/test || true
rg -n "AccountService|deleteAccount|BasicInfoResult|ApplicationDataPort|AccountRepository" systems/identity/identity-application/src/test -g '*.kt' || trueRepository: EntryDSM/entrydsm-platform
Length of output: 4217
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== identity application test =="
sed -n '1,220p' systems/identity/identity-application/src/test/kotlin/hs/kr/entrydsm/TestMain.kt
echo "== account service logic details =="
sed -n '1,80p' systems/identity/identity-application/src/main/kotlin/hs/kr/entrydsm/identity/application/service/AccountService.kt
echo "== ports =="
for f in systems/identity/identity-application/src/main/kotlin/hs/kr/entrydsm/identity/application/port/in/AccountPort.kt systems/identity/identity-bootstrap/src/main/kotlin/hs/kr/entrydsm/ExampleApplication.kt systems/identity/bootstrap/src/main/kotlin/hs/kr/entrydsm/ExampleApplication.kt systems/identity/identity-bootstrap/BUILD.bazel systems/identity/identity-bootstrap/deps.bzl; do
[ -f "$f" ] && { echo "--- $f"; sed -n '1,260p' "$f"; }
doneRepository: EntryDSM/entrydsm-platform
Length of output: 4796
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== all Spring stereotype usages in systems ==
rg -n "import org\.springframework\.stereotype|`@Service`|`@Component`|`@Configuration`|`@ConfigurationProperties`|`@SpringBootApplication`" systems || trueRepository: EntryDSM/entrydsm-platform
Length of output: 224
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== Spring stereotype usages in systems =="
rg -n 'import org\.springframework\.stereotype|`@Service`|`@Component`|`@Configuration`|`@ConfigurationProperties`|`@SpringBootApplication`' systems || trueRepository: EntryDSM/entrydsm-platform
Length of output: 3017
Application service를 Spring stereotype에서 분리하고 이 변경에 대한 test를 추가해 주세요.
identity-application이 identity-application/src/main/kotlin/hs/kr/entrydsm/identity/application/service/AccountService.kt:11-18에서 @Service를 직접 사용하며, 실제 삭제/조회 로직이 추가되었지만 AccountService 테스트는 아직 없습니다. 서비스는 프레임워크 비의존 클래스로 두고 bootstrap에서 빈으로 등록해 모듈 경계를 지키고, Kotlin production logic 변경에 대한 동급 subsystem test도 동반해 주세요.
🤖 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
`@systems/identity/identity-application/src/main/kotlin/hs/kr/entrydsm/identity/application/service/AccountService.kt`
around lines 11 - 14, AccountService에서 Spring의 `@Service` 의존성을 제거해 애플리케이션 서비스를
프레임워크 비의존 클래스로 유지하고, bootstrap 구성에서 AccountService를 빈으로 명시 등록하세요. 실제 삭제·조회 동작을
검증하는 AccountService 테스트를 추가해 Kotlin production logic 변경을 커버하세요.
Source: Coding guidelines
Summary
develop대비 변경 파일 18개로 분리했습니다.Related Issue
Scope
GET /api/identity/v11/accounts/meDELETE /api/identity/v11/accounts/meImplementation
AccountController가AccountPort를 통해 내 정보 조회와 계정 삭제를 처리합니다.AccountService는 인증 정보를 account repository로 resolve하고, application data에서 지원 상태를 조합해 응답합니다.AccountJpaEntity와StudentProfileJpaEntity를 분리하고 Spring Data repository 및 adapter로 저장소 경계를 구성했습니다.Testing
AccountControllerTest추가StudentProfileTest추가401 AUTH_UNAUTHORIZEDDeployment Notes
accounts,student_profiles테이블 스키마 적용 필요Checklist