Skip to content

Commit 2d4064e

Browse files
authored
chore/#147 -> staging merge commit
* chore: archunit 의존성 추가 * test: 계층간 의존 관계 설정 * chore: claude code spotless, test hook 추가 * chore: infra 계층 dto 네이밍을 payload로 통일 * ref: 중복되는 테스트 parameterized test로 통합
1 parent c9bb419 commit 2d4064e

File tree

17 files changed

+322
-61
lines changed

17 files changed

+322
-61
lines changed

.claude/settings.json

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"hooks": {
3+
"Stop": [
4+
{
5+
"hooks": [
6+
{
7+
"type": "command",
8+
"command": "cd \"$CLAUDE_PROJECT_DIR\" && ./gradlew spotlessApply",
9+
"timeout": 120
10+
},
11+
{
12+
"type": "command",
13+
"command": "cd \"$CLAUDE_PROJECT_DIR\" && ./gradlew test",
14+
"timeout": 300
15+
}
16+
]
17+
}
18+
]
19+
}
20+
}

build.gradle.kts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ val kotestVersion = "5.9.1"
2828
val kotestExtensionsVersion = "1.3.0"
2929
val mockkVersion = "1.13.10"
3030
val ktlintVersion = "1.5.0"
31+
val archunitVersion = "1.3.0"
3132

3233
group = "com.neki"
3334
version = "1.0.0"
@@ -111,6 +112,7 @@ dependencies {
111112
testImplementation("io.mockk:mockk:$mockkVersion")
112113
testRuntimeOnly("com.h2database:h2")
113114
testImplementation("io.rest-assured:rest-assured")
115+
testImplementation("com.tngtech.archunit:archunit-junit5:$archunitVersion")
114116
}
115117

116118
spotless {

src/main/kotlin/com/neki/auth/application/contract/KakaoClientResponse.kt renamed to src/main/kotlin/com/neki/auth/application/contract/KakaoClientPayload.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,15 @@ import com.neki.user.domain.enums.ProviderType
55
/**
66
* 카카오 사용자정보 추출 DTO
77
*/
8-
data class OauthInfoResponse(
8+
data class OauthInfoPayload(
99
val providerType: ProviderType,
1010
val oid: String,
1111
val email: String?,
1212
val name: String?,
1313
val imageUrl: String?,
1414
)
1515

16-
data class OIDCDecodePayloadResponse(
16+
data class OIDCDecodePayload(
1717
/** issuer ex https://kauth.kakao.com */
1818
val iss: String,
1919
/** client id */
@@ -28,7 +28,7 @@ data class OIDCDecodePayloadResponse(
2828
val imageUrl: String?,
2929
)
3030

31-
data class OIDCPublicKeysResponse(val keys: MutableList<OIDCPublicKeyDto>)
31+
data class OIDCPublicKeysPayload(val keys: MutableList<OIDCPublicKeyDto>)
3232

3333
data class OIDCPublicKeyDto(val kid: String, val alg: String, val use: String, val n: String, val e: String)
3434

@@ -38,7 +38,7 @@ data class OIDCPublicKeyDto(val kid: String, val alg: String, val use: String, v
3838
* date : 2025. 12. 26. 18:20
3939
* description : Auth usercase 관련 result idToken을 얻기 위한 테스트 DTO
4040
*/
41-
data class GetKakaoTokenResponse(
41+
data class KakaoTokenPayload(
4242
val accessToken: String,
4343
val tokenType: String,
4444
val refreshToken: String,
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package com.neki.auth.application.port
22

3-
import com.neki.auth.application.contract.OIDCPublicKeysResponse
3+
import com.neki.auth.application.contract.OIDCPublicKeysPayload
44
import java.time.Duration
55

66
/**
@@ -10,9 +10,9 @@ import java.time.Duration
1010
* description : 캐시사용을 위한 Port 인터페이스
1111
*/
1212
interface AuthCachePort {
13-
fun setPublicKeys(key: String, value: OIDCPublicKeysResponse, ttl: Duration)
13+
fun setPublicKeys(key: String, value: OIDCPublicKeysPayload, ttl: Duration)
1414

15-
fun getPublicKeys(key: String): OIDCPublicKeysResponse?
15+
fun getPublicKeys(key: String): OIDCPublicKeysPayload?
1616

1717
fun clearPublicKeys(key: String)
1818
}

src/main/kotlin/com/neki/auth/application/port/OidcTokenValidatorPort.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package com.neki.auth.application.port
22

3-
import com.neki.auth.application.contract.OauthInfoResponse
3+
import com.neki.auth.application.contract.OauthInfoPayload
44
import com.neki.auth.domain.Platform
55
import com.neki.user.domain.enums.ProviderType
66

@@ -11,5 +11,5 @@ import com.neki.user.domain.enums.ProviderType
1111
* description :
1212
*/
1313
interface OidcTokenValidatorPort {
14-
fun validateIdToken(idToken: String, providerType: ProviderType, platform: Platform): OauthInfoResponse
14+
fun validateIdToken(idToken: String, providerType: ProviderType, platform: Platform): OauthInfoPayload
1515
}

src/main/kotlin/com/neki/auth/application/usecase/OauthLoginUseCase.kt

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ package com.neki.auth.application.usecase
22

33
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
44
import com.neki.auth.application.command.RegisterOauthUserCommand
5-
import com.neki.auth.application.contract.GetKakaoTokenResponse
6-
import com.neki.auth.application.contract.OauthInfoResponse
5+
import com.neki.auth.application.contract.KakaoTokenPayload
6+
import com.neki.auth.application.contract.OauthInfoPayload
77
import com.neki.auth.application.port.AuthTokenProviderPort
88
import com.neki.auth.application.port.NicknameGeneratorPort
99
import com.neki.auth.application.port.OidcTokenValidatorPort
@@ -45,14 +45,14 @@ class OauthLoginUseCase(
4545
* 4. oauthInfoResult 값 여부에 따라 회원가입 처리
4646
*/
4747
fun execute(command: RegisterOauthUserCommand): GetAuthResult {
48-
val oauthInfoResponse = oidcTokenValidatorPort.validateIdToken(
48+
val oauthInfoPayload = oidcTokenValidatorPort.validateIdToken(
4949
command.idToken,
5050
command.providerType,
5151
command.platform,
5252
)
5353

5454
// 신규 사용자 추가
55-
val (user, _) = transactionRunner.run { registerOauthUserIfEmpty(oauthInfoResponse) }
55+
val (user, _) = transactionRunner.run { registerOauthUserIfEmpty(oauthInfoPayload) }
5656

5757
// 토큰 생성
5858
val accessToken = tokenProviderPort.createAccessToken(
@@ -75,10 +75,10 @@ class OauthLoginUseCase(
7575
)
7676
}
7777

78-
private fun registerOauthUserIfEmpty(oauthInfoResponse: OauthInfoResponse): Pair<User, Boolean> {
78+
private fun registerOauthUserIfEmpty(oauthInfoPayload: OauthInfoPayload): Pair<User, Boolean> {
7979
val existingUser = userRepositoryPort.findByOid(
80-
oid = oauthInfoResponse.oid,
81-
provider = oauthInfoResponse.providerType,
80+
oid = oauthInfoPayload.oid,
81+
provider = oauthInfoPayload.providerType,
8282
)
8383

8484
return if (existingUser != null) {
@@ -87,11 +87,11 @@ class OauthLoginUseCase(
8787
val nickname = nicknameGenerator.generateUniqueNickname()
8888
val newUser = userRepositoryPort.save(
8989
User(
90-
email = oauthInfoResponse.email,
91-
oid = oauthInfoResponse.oid,
90+
email = oauthInfoPayload.email,
91+
oid = oauthInfoPayload.oid,
9292
name = nickname,
9393
roles = RoleType.USER.role,
94-
providerType = oauthInfoResponse.providerType,
94+
providerType = oauthInfoPayload.providerType,
9595
profileImageId = null,
9696
),
9797
)
@@ -108,7 +108,7 @@ class OauthLoginUseCase(
108108
* @return KakaoTokenResponse 카카오 토큰 정보
109109
* @throws Exception 토큰 획득 실패 시
110110
*/
111-
fun getAccessTokenByCode(code: String): GetKakaoTokenResponse {
111+
fun getAccessTokenByCode(code: String): KakaoTokenPayload {
112112
val clientId = oauthProperties.kakao.androidClientId
113113
val clientSecret = oauthProperties.kakao.clientSecret
114114

@@ -133,7 +133,7 @@ class OauthLoginUseCase(
133133
val objectMapper = jacksonObjectMapper()
134134
val jsonNode = objectMapper.readTree(response)
135135

136-
return GetKakaoTokenResponse(
136+
return KakaoTokenPayload(
137137
accessToken = jsonNode.get("access_token").asText(),
138138
tokenType = jsonNode.get("token_type").asText(),
139139
refreshToken = jsonNode.get("refresh_token").asText(),

src/main/kotlin/com/neki/auth/infra/oauth/OidcTokenValidator.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package com.neki.auth.infra.oauth
22

33
import com.neki.auth.application.contract.AuthCacheKeys
4-
import com.neki.auth.application.contract.OauthInfoResponse
4+
import com.neki.auth.application.contract.OauthInfoPayload
55
import com.neki.auth.application.port.OidcTokenValidatorPort
66
import com.neki.auth.domain.Platform
77
import com.neki.auth.infra.oauth.helper.OauthHelper
@@ -34,7 +34,7 @@ class OidcTokenValidator(
3434
* - 1차 시도: 캐시된 공개키로 토큰 검증
3535
* - BusinessException 발생 시: 캐시 무효화 후 재시도 (공개키 로테이션 대응)
3636
*/
37-
override fun validateIdToken(idToken: String, providerType: ProviderType, platform: Platform): OauthInfoResponse {
37+
override fun validateIdToken(idToken: String, providerType: ProviderType, platform: Platform): OauthInfoPayload {
3838
val oidcAdapter = oidcRegistry.getAdapter(providerType)
3939
val oauthHelperAdapter = oauthHelperRegistry.getAdapter(providerType)
4040

@@ -60,7 +60,7 @@ class OidcTokenValidator(
6060
oidc: Oidc,
6161
oauthHelper: OauthHelper,
6262
platform: Platform,
63-
): OauthInfoResponse {
63+
): OauthInfoPayload {
6464
val publicKeys = oidc.getOIDCPublicKey()
6565
return oauthHelper.getOauthInfoByIdToken(
6666
idToken = idToken,

src/main/kotlin/com/neki/auth/infra/oauth/helper/AppleOauthHelper.kt

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
package com.neki.auth.infra.oauth.helper
22

33
import com.fasterxml.jackson.databind.ObjectMapper
4-
import com.neki.auth.application.contract.OIDCDecodePayloadResponse
4+
import com.neki.auth.application.contract.OIDCDecodePayload
55
import com.neki.auth.application.contract.OIDCPublicKeyDto
6-
import com.neki.auth.application.contract.OIDCPublicKeysResponse
7-
import com.neki.auth.application.contract.OauthInfoResponse
6+
import com.neki.auth.application.contract.OIDCPublicKeysPayload
7+
import com.neki.auth.application.contract.OauthInfoPayload
88
import com.neki.auth.domain.Platform
99
import com.neki.auth.infra.security.properties.OauthProperties
1010
import com.neki.common.api.dto.ResultCode
@@ -61,9 +61,9 @@ class AppleOauthHelper(private val oauthProperties: OauthProperties, private val
6161
*/
6262
override fun getOauthInfoByIdToken(
6363
idToken: String,
64-
publicKeys: OIDCPublicKeysResponse,
64+
publicKeys: OIDCPublicKeysPayload,
6565
platform: Platform,
66-
): OauthInfoResponse {
66+
): OauthInfoPayload {
6767
// Step 1: 헤더에서 kid 추출
6868
val kid = extractKidFromTokenHeader(idToken)
6969

@@ -79,7 +79,7 @@ class AppleOauthHelper(private val oauthProperties: OauthProperties, private val
7979
expectedAudience = oauthProperties.apple.clientId,
8080
)
8181

82-
return OauthInfoResponse(
82+
return OauthInfoPayload(
8383
providerType = ProviderType.APPLE,
8484
oid = payload.sub, // String 그대로 사용 (UUID)
8585
email = payload.email,
@@ -122,11 +122,11 @@ class AppleOauthHelper(private val oauthProperties: OauthProperties, private val
122122
publicKey: OIDCPublicKeyDto,
123123
expectedIssuer: String,
124124
expectedAudience: String,
125-
): OIDCDecodePayloadResponse {
125+
): OIDCDecodePayload {
126126
val rsaPublicKey = convertToRSAPublicKey(publicKey.n, publicKey.e)
127127
val claims = verifyTokenSignatureAndClaims(token, rsaPublicKey, expectedIssuer, expectedAudience)
128128

129-
return OIDCDecodePayloadResponse(
129+
return OIDCDecodePayload(
130130
iss = claims.issuer,
131131
aud = claims.audience.toString(),
132132
sub = claims.subject, // String 그대로 사용 (Apple UUID)

src/main/kotlin/com/neki/auth/infra/oauth/helper/KakaoOauthHelper.kt

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
package com.neki.auth.infra.oauth.helper
22

33
import com.fasterxml.jackson.databind.ObjectMapper
4-
import com.neki.auth.application.contract.OIDCDecodePayloadResponse
4+
import com.neki.auth.application.contract.OIDCDecodePayload
55
import com.neki.auth.application.contract.OIDCPublicKeyDto
6-
import com.neki.auth.application.contract.OIDCPublicKeysResponse
7-
import com.neki.auth.application.contract.OauthInfoResponse
6+
import com.neki.auth.application.contract.OIDCPublicKeysPayload
7+
import com.neki.auth.application.contract.OauthInfoPayload
88
import com.neki.auth.domain.Platform
99
import com.neki.auth.infra.security.properties.OauthProperties
1010
import com.neki.common.api.dto.ResultCode
@@ -59,9 +59,9 @@ class KakaoOauthHelper(private val oauthProperties: OauthProperties, private val
5959
*/
6060
override fun getOauthInfoByIdToken(
6161
idToken: String,
62-
publicKeys: OIDCPublicKeysResponse,
62+
publicKeys: OIDCPublicKeysPayload,
6363
platform: Platform,
64-
): OauthInfoResponse {
64+
): OauthInfoPayload {
6565
// Step 1: 헤더에서 kid 추출 (토큰 분리 및 Base64 디코딩)
6666
val kid = extractKidFromTokenHeader(idToken)
6767

@@ -82,7 +82,7 @@ class KakaoOauthHelper(private val oauthProperties: OauthProperties, private val
8282
expectedAudience = expectedAudience,
8383
)
8484

85-
return OauthInfoResponse(
85+
return OauthInfoPayload(
8686
providerType = ProviderType.KAKAO,
8787
oid = payload.sub,
8888
email = payload.email,
@@ -133,11 +133,11 @@ class KakaoOauthHelper(private val oauthProperties: OauthProperties, private val
133133
publicKey: OIDCPublicKeyDto,
134134
expectedIssuer: String,
135135
expectedAudience: String,
136-
): OIDCDecodePayloadResponse {
136+
): OIDCDecodePayload {
137137
val rsaPublicKey = convertToRSAPublicKey(publicKey.n, publicKey.e)
138138
val claims = verifyTokenSignatureAndClaims(token, rsaPublicKey, expectedIssuer, expectedAudience)
139139

140-
return OIDCDecodePayloadResponse(
140+
return OIDCDecodePayload(
141141
iss = claims.issuer,
142142
aud = claims.audience.toString(),
143143
sub = claims.subject,
Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package com.neki.auth.infra.oauth.helper
22

3-
import com.neki.auth.application.contract.OIDCPublicKeysResponse
4-
import com.neki.auth.application.contract.OauthInfoResponse
3+
import com.neki.auth.application.contract.OIDCPublicKeysPayload
4+
import com.neki.auth.application.contract.OauthInfoPayload
55
import com.neki.auth.domain.Platform
66

77
/**
@@ -11,9 +11,5 @@ import com.neki.auth.domain.Platform
1111
* description : OAuth OIDC 검증을 위한 Port
1212
*/
1313
interface OauthHelper {
14-
fun getOauthInfoByIdToken(
15-
idToken: String,
16-
publicKeys: OIDCPublicKeysResponse,
17-
platform: Platform,
18-
): OauthInfoResponse
14+
fun getOauthInfoByIdToken(idToken: String, publicKeys: OIDCPublicKeysPayload, platform: Platform): OauthInfoPayload
1915
}

0 commit comments

Comments
 (0)