refactor: 인증 도메인에서의 예외 세분화

- 현재는 회원 도메인의 예외를 그대로 던지는데, 이를 인증 예외로 처리
This commit is contained in:
이상진 2025-07-23 16:00:10 +09:00
parent f1ebc0f57d
commit 9683ed946e
4 changed files with 37 additions and 19 deletions

View File

@ -7,9 +7,11 @@ enum class AuthErrorCode(
override val httpStatus: HttpStatus,
override val errorCode: String,
override val message: String,
): ErrorCode {
) : ErrorCode {
TOKEN_NOT_FOUND(HttpStatus.UNAUTHORIZED, "A001", "인증 토큰이 없어요."),
INVALID_TOKEN(HttpStatus.UNAUTHORIZED, "A002", "유효하지 않은 토큰이에요."),
EXPIRED_TOKEN(HttpStatus.UNAUTHORIZED, "A003", "토큰이 만료됐어요."),
ACCESS_DENIED(HttpStatus.FORBIDDEN, "A004", "접근 권한이 없어요."),
LOGIN_FAILED(HttpStatus.UNAUTHORIZED, "A005", "이메일과 비밀번호를 확인해주세요."),
UNIDENTIFIABLE_MEMBER(HttpStatus.UNAUTHORIZED, "A006", "회원 정보를 찾을 수 없어요."),
}

View File

@ -1,6 +1,8 @@
package roomescape.auth.service
import org.springframework.stereotype.Service
import roomescape.auth.exception.AuthErrorCode
import roomescape.auth.exception.AuthException
import roomescape.auth.infrastructure.jwt.JwtHandler
import roomescape.auth.web.LoginCheckResponse
import roomescape.auth.web.LoginRequest
@ -14,10 +16,9 @@ class AuthService(
private val jwtHandler: JwtHandler
) {
fun login(request: LoginRequest): LoginResponse {
val member: MemberEntity = memberService.findByEmailAndPassword(
request.email,
request.password
)
val member: MemberEntity = fetchMemberOrThrow(AuthErrorCode.LOGIN_FAILED) {
memberService.findByEmailAndPassword(request.email, request.password)
}
val accessToken: String = jwtHandler.createToken(member.id!!)
@ -25,8 +26,21 @@ class AuthService(
}
fun checkLogin(memberId: Long): LoginCheckResponse {
val member = memberService.findById(memberId)
val member: MemberEntity = fetchMemberOrThrow(AuthErrorCode.UNIDENTIFIABLE_MEMBER) {
memberService.findById(memberId)
}
return LoginCheckResponse(member.name)
}
private fun fetchMemberOrThrow(
errorCode: AuthErrorCode,
block: () -> MemberEntity
): MemberEntity {
try {
return block()
} catch (_: Exception) {
throw AuthException(errorCode)
}
}
}

View File

@ -7,10 +7,10 @@ import io.kotest.matchers.shouldBe
import io.mockk.every
import io.mockk.mockk
import org.springframework.data.repository.findByIdOrNull
import roomescape.auth.exception.AuthErrorCode
import roomescape.auth.exception.AuthException
import roomescape.auth.infrastructure.jwt.JwtHandler
import roomescape.auth.service.AuthService
import roomescape.common.exception.ErrorType
import roomescape.common.exception.RoomescapeException
import roomescape.member.business.MemberService
import roomescape.member.infrastructure.persistence.MemberEntity
import roomescape.member.infrastructure.persistence.MemberRepository
@ -45,11 +45,11 @@ class AuthServiceTest : BehaviorSpec({
memberRepository.findByEmailAndPassword(request.email, request.password)
} returns null
val exception = shouldThrow<RoomescapeException> {
val exception = shouldThrow<AuthException> {
authService.login(request)
}
exception.errorType shouldBe ErrorType.MEMBER_NOT_FOUND
exception.errorCode shouldBe AuthErrorCode.LOGIN_FAILED
}
}
}
@ -71,11 +71,11 @@ class AuthServiceTest : BehaviorSpec({
Then("회원이 없다면 예외를 던진다.") {
every { memberRepository.findByIdOrNull(userId) } returns null
val exception = shouldThrow<RoomescapeException> {
val exception = shouldThrow<AuthException> {
authService.checkLogin(userId)
}
exception.errorType shouldBe ErrorType.MEMBER_NOT_FOUND
exception.errorCode shouldBe AuthErrorCode.UNIDENTIFIABLE_MEMBER
}
}
}

View File

@ -7,10 +7,10 @@ import org.hamcrest.Matchers.equalTo
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest
import org.springframework.data.repository.findByIdOrNull
import org.springframework.test.web.servlet.MockMvc
import roomescape.auth.exception.AuthErrorCode
import roomescape.auth.service.AuthService
import roomescape.common.exception.CommonErrorCode
import roomescape.common.exception.ErrorCode
import roomescape.common.exception.ErrorType
import roomescape.util.MemberFixture
import roomescape.util.RoomescapeApiTest
@ -61,14 +61,15 @@ class AuthControllerTest(
memberRepository.findByEmailAndPassword(userRequest.email, userRequest.password)
} returns null
Then("400 에러를 응답한다") {
Then("에러 응답") {
val expectedError = AuthErrorCode.LOGIN_FAILED
runPostTest(
mockMvc = mockMvc,
endpoint = endpoint,
body = userRequest,
) {
status { isBadRequest() }
jsonPath("$.errorType", equalTo(ErrorType.MEMBER_NOT_FOUND.name))
status { isEqualTo(expectedError.httpStatus.value()) }
jsonPath("$.code", equalTo(expectedError.errorCode))
}
}
}
@ -117,13 +118,14 @@ class AuthControllerTest(
every { jwtHandler.getMemberIdFromToken(any()) } returns invalidMemberId
every { memberRepository.findByIdOrNull(invalidMemberId) } returns null
Then("400 에러를 응답한다.") {
Then("에러 응답.") {
val expectedError = AuthErrorCode.UNIDENTIFIABLE_MEMBER
runGetTest(
mockMvc = mockMvc,
endpoint = endpoint,
) {
status { isBadRequest() }
jsonPath("$.errorType", equalTo(ErrorType.MEMBER_NOT_FOUND.name))
status { isEqualTo(expectedError.httpStatus.value()) }
jsonPath("$.code", equalTo(expectedError.errorCode))
}
}
}