-
Notifications
You must be signed in to change notification settings - Fork 56
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Spring Core] (배포) 정상희 미션 제출합니다. #116
Open
SANGHEEJEONG
wants to merge
40
commits into
next-step:sangheejeong
Choose a base branch
from
SANGHEEJEONG:sanghee-core
base: sangheejeong
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 37 commits
Commits
Show all changes
40 commits
Select commit
Hold shift + click to select a range
eac6692
[FEAT] 리드미 작성
SANGHEEJEONG e1b4ce3
[FEAT] 로그인, 인증 정보 조회 (1단계)
SANGHEEJEONG 0186fcf
[FEAT] 리드미 작성 (2단계)
SANGHEEJEONG 769b6bf
[FEAT] ArgumentResolver 구현 + 예약 리팩터링 (2단계)
SANGHEEJEONG 9b180fb
[FEAT] 리드미 작성 (3단계)
SANGHEEJEONG 2ebef37
[FEAT] 어드민 페이지 권한 (3단계)
SANGHEEJEONG f9c1a7d
[REFACTOR] 클래스명 변경 및 코드 정리
SANGHEEJEONG c83b84b
[FEAT] 리드미 작성 (4단계)
SANGHEEJEONG 36b7dd3
[FEAT] Dao -> Repository (4단계)
SANGHEEJEONG 9cfe2f7
[FEAT] 리드미 작성 (5단계)
SANGHEEJEONG 112420c
[FEAT] 내 예약 목록 조회 (5단계)
SANGHEEJEONG 2b497bf
[FEAT] 중복 예약 방지 및 예약 대기 기능 (6단계)
SANGHEEJEONG 2e0884e
[REFACTOR] AuthClaims 와 LoginResponse 분리
SANGHEEJEONG 0cfc7eb
[REFACTOR] 토큰 추출 메서드 중복 제거
SANGHEEJEONG ff3ad6a
[REFACTOR] Role enum 타입으로 변경
SANGHEEJEONG 75132bc
[REFACTOR] 예외처리 핸들러 작성
SANGHEEJEONG fde3d1d
[REFACTOR] 커스텀 어노테이션 적용
SANGHEEJEONG 1f2e385
[REBASE] mvc 리베이스 후 충돌 해결
SANGHEEJEONG 1d62e9a
[REBASE] mvc 리베이스 충돌 해결 2
SANGHEEJEONG d5e2ad0
[FEAT] 리드미 작성 (5단계)
SANGHEEJEONG ae765ec
[REBASE] mvc 리베이스 충돌 해결 3
SANGHEEJEONG 71cd274
[REBASE] mvc 리베이스 충돌 해결 4
SANGHEEJEONG 9bcfcbf
[REFACTOR] service 웹 기술 제거
SANGHEEJEONG ec05e2c
[REFACTOR] DTO 변환 로직 분리
SANGHEEJEONG 4b0e950
[REFACTOR] jpa를 위한 생성자 오용 방지
SANGHEEJEONG d47ce84
[REFACTOR] name -> id 조회로 변경 및 권한 추가
SANGHEEJEONG 43f3c71
[REFACTOR] joinColumn 추가
SANGHEEJEONG b8b073f
[REFACTOR] joinColumn 추가 (Waiting 엔티티)
SANGHEEJEONG ebfb5d9
[REFACTOR] WaitingService 조회 수정
SANGHEEJEONG a89b961
[REFACTOR] 코드 정렬
SANGHEEJEONG 0b1819c
Merge branch 'sanghee-jpa' of https://github.com/SANGHEEJEONG/spring-…
SANGHEEJEONG 64d65be
[FEAT] 리드미 작성
SANGHEEJEONG 4841c67
[FEAT&FIX] auth 패키지 외부 이동 및 오류 수정
SANGHEEJEONG 43cb26c
[FIX] id 추출 및 에러 코드 오류 수정
SANGHEEJEONG b6fadf3
[FIX] 예약 & 대기 생성 로직 수정
SANGHEEJEONG 9e3b738
[FIX] @AuthCustomAnnotation 어노테이션 추가
SANGHEEJEONG 14a1bc0
[FEAT] 데이터 로더 클래스 생성
SANGHEEJEONG 3b804b4
[REFACTOR] 안 쓰는 코드 제거
SANGHEEJEONG 001cd99
[REFACTOR] jwt 관련 로직 분리
SANGHEEJEONG 3f3af8a
[FIX] 이단계 테스트 업데이트
SANGHEEJEONG File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
# 🌀 Spring MVC (인증) | ||
|
||
# 1단계 | ||
___ | ||
## 로그인 페이지 | ||
+ 이메일, 비밀번호 입력 | ||
## 로그인 요청 | ||
+ 이메일, 비밀번호 -> 멤버 조회 | ||
+ 조회한 멤버로 토큰 발급 | ||
+ Cookie를 만들어 응답 | ||
## 인증 정보 조회 | ||
+ Cookie -> 토큰 정보 추출 | ||
+ 멤버를 찾아서 응답 | ||
## API | ||
+ GET/login : 로그인 페이지 호출 | ||
+ POST/login : 로그인 요청 | ||
+ GET/login/check : 인증 정보 조회 | ||
|
||
# 2단계 | ||
___ | ||
## 로그인 리팩터링 | ||
#### HandlerMethodArgumentResolver | ||
+ 컨트롤러 메서드 파라미터로 자동 주입 | ||
|
||
## 예약 생성 기능 변경 | ||
+ 예약 : ReservationRequest(요청 DTO) | ||
-> name이 있으면 name으로 Member 찾기 | ||
-> name이 없으면 Cookie에 담긴 정보 활용 | ||
|
||
# 3단계 | ||
___ | ||
## 관리자 기능 | ||
+ admin 페이지 진입 (HandlerInterceptor 이용) | ||
-> 관리자 : 진입 가능 | ||
-> 관리자 X : 401 코드 응답 | ||
|
||
# 🌀 Spring JPA (인증) | ||
|
||
# 4단계 | ||
___ | ||
## JPA 전환 | ||
+ 엔티티 & 연관 관계 매핑 | ||
+ DAO -> JpaRepository를 상속받는 Repository로 대체 | ||
|
||
# 5단계 | ||
___ | ||
## 내 예약 목록 조회 | ||
+ 응답 DTO -> 예약 아이디, 테마, 날짜, 시간, 상태를 포함 | ||
## 예약 테이블 수정 | ||
+ 관리자 예약 (어드민 화면) : name을 string으로 전달 | ||
+ 사용자 예약 (예약 화면) : 로그인 정보를 이용해 Member ID 저장 | ||
## API | ||
+ GET/reservation-mine : reservation-mine 페이지 응답 | ||
+ GET/reservations-mine : 내 예약 목록 조회 | ||
|
||
# 6단계 | ||
___ | ||
## 예약 대기 | ||
+ 요청 | ||
+ 취소 | ||
+ 조회 : N번 째 예약 대기인지 표시 | ||
## API | ||
+ POST/waitings : 예약 대기 생성 | ||
+ DELETE/waitings/{id} : 예약 삭제 | ||
|
||
# 7단계 | ||
___ | ||
## @Configuration | ||
+ JWT 관련 로직 auth 패키지(roomescape 외부 패키지)로 분리 | ||
|
||
# 8단계 | ||
___ | ||
## Profile과 Resource | ||
### 1. schema.sql 대신 데이터베이스 초기화 클래스 만들기 | ||
#### < DataLoader > | ||
+ DataLoader : 사용자 정보 초기화 | ||
+ TestDataLoader : 테스트에 필요한 사전 값 초기화 | ||
|
||
### 2. secret key 값을 properties 파일로 이동 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package auth; | ||
|
||
public record AuthClaims( | ||
Long id, | ||
String name, | ||
String role | ||
) { | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
package auth; | ||
|
||
import jakarta.servlet.http.HttpServletRequest; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.core.MethodParameter; | ||
import org.springframework.web.bind.support.WebDataBinderFactory; | ||
import org.springframework.web.context.request.NativeWebRequest; | ||
import org.springframework.web.context.request.ServletWebRequest; | ||
import org.springframework.web.method.support.HandlerMethodArgumentResolver; | ||
import org.springframework.web.method.support.ModelAndViewContainer; | ||
|
||
// @Component | ||
@RequiredArgsConstructor | ||
public class AuthClaimsArgumentResolver implements HandlerMethodArgumentResolver { | ||
|
||
private final JWTUtils jwtUtils; | ||
|
||
@Override | ||
public boolean supportsParameter(MethodParameter parameter) { | ||
return parameter.hasParameterAnnotation(AuthCustomAnnotation.class) && | ||
parameter.getParameterType().equals(AuthClaims.class); | ||
} | ||
|
||
@Override | ||
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception { | ||
HttpServletRequest request = ((ServletWebRequest) webRequest).getRequest(); | ||
String token = jwtUtils.extractToken(request).token(); | ||
|
||
return jwtUtils.getClaimsFromToken(token); | ||
} | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package auth; | ||
|
||
import org.springframework.context.annotation.Bean; | ||
import org.springframework.context.annotation.Configuration; | ||
|
||
@Configuration | ||
public class AuthConfig { | ||
|
||
@Bean | ||
public JWTUtils jwtUtils() { | ||
return new JWTUtils(); | ||
} | ||
|
||
@Bean | ||
public AuthClaimsArgumentResolver authClaimsArgumentResolver(JWTUtils jwtUtils) { | ||
return new AuthClaimsArgumentResolver(jwtUtils); | ||
} | ||
|
||
@Bean | ||
public AuthRoleInterceptor authRoleInterceptor(JWTUtils jwtUtils) { | ||
return new AuthRoleInterceptor(jwtUtils); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package auth; | ||
|
||
import java.lang.annotation.Documented; | ||
import java.lang.annotation.ElementType; | ||
import java.lang.annotation.Retention; | ||
import java.lang.annotation.RetentionPolicy; | ||
import java.lang.annotation.Target; | ||
|
||
@Target(ElementType.PARAMETER) | ||
@Retention(RetentionPolicy.RUNTIME) | ||
@Documented | ||
public @interface AuthCustomAnnotation { | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
package auth; | ||
|
||
import jakarta.servlet.http.HttpServletRequest; | ||
import jakarta.servlet.http.HttpServletResponse; | ||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.web.servlet.HandlerInterceptor; | ||
|
||
// @Component | ||
@RequiredArgsConstructor | ||
public class AuthRoleInterceptor implements HandlerInterceptor { | ||
|
||
private final JWTUtils jwtUtils; | ||
|
||
@Override | ||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { | ||
String token = jwtUtils.extractToken(request).token(); | ||
|
||
if (!jwtUtils.getClaimsFromToken(token).role().equals("ADMIN")) { | ||
response.setStatus(401); | ||
return false; | ||
} | ||
|
||
return true; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
package auth; | ||
|
||
public record AuthToken( | ||
String token | ||
) { | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
package auth; | ||
|
||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.context.annotation.Configuration; | ||
import org.springframework.web.method.support.HandlerMethodArgumentResolver; | ||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry; | ||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; | ||
|
||
import java.util.List; | ||
|
||
@Configuration | ||
@RequiredArgsConstructor | ||
public class AuthWebConfig implements WebMvcConfigurer { | ||
|
||
private final AuthClaimsArgumentResolver authClaimsArgumentResolver; | ||
private final AuthRoleInterceptor authRoleInterceptor; | ||
|
||
@Override | ||
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) { | ||
resolvers.add(authClaimsArgumentResolver); | ||
} | ||
|
||
@Override | ||
public void addInterceptors(InterceptorRegistry registry) { | ||
registry.addInterceptor(authRoleInterceptor).addPathPatterns("/admin/**"); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
package auth; | ||
|
||
import io.jsonwebtoken.Claims; | ||
import io.jsonwebtoken.JwtException; | ||
import io.jsonwebtoken.Jwts; | ||
import io.jsonwebtoken.security.Keys; | ||
import jakarta.servlet.http.Cookie; | ||
import jakarta.servlet.http.HttpServletRequest; | ||
import org.springframework.beans.factory.annotation.Value; | ||
import roomescape.exception.InvalidTokenException; | ||
import roomescape.exception.MissingTokenException; | ||
import roomescape.member.Member; | ||
|
||
import java.util.Arrays; | ||
|
||
// @Component | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 사용하지 않는 코드는 주석 처리를 하기 보단, 삭제를 하는 것이 좋을 것 같아요! |
||
public class JWTUtils { | ||
|
||
@Value("${roomescape.auth.jwt.secret}") | ||
private String secretKey; | ||
|
||
public AuthToken createToken(Member member) { | ||
String accessToken = Jwts.builder() | ||
.setSubject(member.getId().toString()) | ||
.claim("name", member.getName()) | ||
.claim("role", member.getRole()) | ||
.signWith(Keys.hmacShaKeyFor(secretKey.getBytes())) | ||
.compact(); | ||
|
||
return new AuthToken(accessToken); | ||
} | ||
|
||
public AuthToken extractToken(HttpServletRequest request){ | ||
String token = Arrays.stream(request.getCookies()) | ||
.filter(cookie -> "token".equals(cookie.getName())) | ||
.findFirst() | ||
.map(Cookie::getValue) | ||
.orElseThrow(() -> new MissingTokenException("토큰을 찾을 수 없습니다.")); | ||
|
||
return new AuthToken(token); | ||
} | ||
|
||
public AuthClaims getClaimsFromToken(String token) { | ||
if (token == null || token.isBlank()) { | ||
throw new MissingTokenException("토큰이 비어있습니다."); | ||
} | ||
|
||
try { | ||
Claims claims = Jwts.parserBuilder() | ||
.setSigningKey(Keys.hmacShaKeyFor(secretKey.getBytes())) | ||
.build() | ||
.parseClaimsJws(token) | ||
.getBody(); | ||
|
||
Long id = Long.parseLong(claims.getSubject()); | ||
String name = claims.get("name", String.class); | ||
String role = claims.get("role", String.class); | ||
|
||
if (id == null || name == null || role == null) { | ||
throw new InvalidTokenException("필수 클레임이 누락되었습니다."); | ||
} | ||
|
||
return new AuthClaims(id, name, role); | ||
|
||
} catch (JwtException e) { | ||
throw new InvalidTokenException("유효하지 않은 토큰입니다."); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package roomescape; | ||
|
||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.boot.CommandLineRunner; | ||
import org.springframework.context.annotation.Profile; | ||
import org.springframework.stereotype.Component; | ||
import roomescape.member.Member; | ||
import roomescape.member.MemberRepository; | ||
|
||
@Profile("prod") | ||
@Component | ||
@RequiredArgsConstructor | ||
public class DataLoader implements CommandLineRunner { | ||
|
||
private final MemberRepository memberRepository; | ||
|
||
@Override | ||
public void run(String... args) throws Exception { | ||
memberRepository.save(new Member("어드민", "[email protected]", "password", "ADMIN")); | ||
memberRepository.save(new Member("브라운", "[email protected]", "password", "USER")); | ||
} | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Auth 라고 이름 붙은 클래스를 모두 auth 패키지로 옮겨주신 것 같아요.
이건 아마 7단계 중 아래의 요구사항 때문이겠죠?!
여기서 두 가지 정도의 리뷰 포인트가 존재할 것 같아요.
1.
JWT 관련 로직
은 어디까지를 관련된 로직으로 봐야 하는가?상희님도 이에 대해 고민을 해보셨을 것 같아요. 그리고 이에 대한 결론으로, JWTUtils 와 Auth 가 붙은 모든 클래스를 그 대상으로 보신 것 같습니다.
다만 저는 생각이 조금 달라요. 아래는 요구사항 해결 방향성에서 가져온 문장인데요!
Auth 가 붙은 클래스들에는, 토큰 생성과 토큰 값 조회에 대한 기능을 포함하고 있지 않는 것 같아요. 이는 모두 JWTUtils 라는 클래스의 책임으로 보여요.
즉, JWT 관련 로직이라는 범위에는
Auth~
클래스가 포함되지 않을 것 같다는 생각이에요.예를 들어, 상희님의 코드에서는
AuthClaimsArgumentResolver
가JWTUtils
를 의존하고 있는데, 이는 JWTUtils의 기능을 이용하여 AuthClaims 객체 조립을 도울 뿐, JWTUtils에 관련된 로직이라고 보긴 어렵지 않을까 하는 생각입니다.2. 왜 auth 패키지로 분리해야 하는가? (= 미션의 의도가 무엇인가?)
이번 리뷰가 좀 어려웠는데, 이 포인트 때문이었던 것 같아요. 이 이야기는 상희님이 PR 본문에 남겨주신 아래의 질문들에 도움이 될 것 같네요.
아래는 7단계 요구사항 테스트 코드인데요,
상희님이 만드신 JWTUtils 클래스에
@Component
어노테이션이 없어야 한다는 의도를 담은 테스트 코드예요.이 테스트의 의도와, 7단계 미션의 맥락을 봤을 때, JWTUtils 및 auth 패키지를
스프링으로부터 완벽히 격리되어 있는 하나의 모듈
로 바라보는 걸 원하지 않았을까? 라는 생각이 듭니다.이렇게 생각해 봅시다. 상희님은 당장 JWT 관련 로직이 필요한데, 직접 구현하기에는 난이도가 너무 높다고 가정해 볼게요.
그렇다면 대안은, 이미 잘 만들어져있는 JWT 관련 라이브러리를 외부에서 끌어오는 방법이 있을 것 같아요. 이때 이 라이브러리의 패키지 명은 auth 이고, 클래스는 JWTUtils 라는 이름을 가진 거죠.
문제는, JWT 라이브러리를 만든 개발자가 스프링 기술을 전혀 고려하지 않고, 범용적으로 사용할 수 있는 POJO 형태의 코드를 작성했다는 점입니다.
즉, JWTUtils 클래스에는
@Component
와 같은 코드가 전혀 작성이 되어있지 않을 거예요. 스프링 기술을 전혀 고려하지 않았으니까요. 이 클래스가 스프링 빈으로 사용될 건지, 순수 자바 객체로 사용될 건지는, 이 라이브러리를 가져다 쓰는 개발자의 몫으로 남겨둔 거죠.그러면 이제 다시 우리의 상황으로 돌아와서 생각해 봅시다!
우리는 스프링 기술을 사용하고 있고, 당장 JWTUtils 클래스를 스프링 빈으로 등록해서 사용해야 하는 상황입니다.
문제는, JWTUtils 클래스가 외부 라이브러리 코드이기 때문에, 우리가 수정할 수가 없다는 점이에요. 즉,
@Component
어노테이션을 붙이고 싶어도 방법이 없어요.이럴 때 어떻게 해볼 수 있을까요?
외부 모듈 코드라서, 해당 코드의 제어권이 우리에게 없을 때,
@Configuration
을 통해서 수동으로 빈 등록을 할 수 있어요. 이렇게 하면 외부 모듈 코드더라도, 우리가 사용하고 있는 스프링 세계로 끌어들일 수 있겠죠.또 다른 관점에서 볼 수도 있는데, 만약 상희님이 도메인 설계를 하고 있는데, 스프링 이라는 특정 기술에 종속적인 코드를 작성하고 싶지 않다고 가정해볼게요. 즉, 그 도메인 클래스의 import문에는 스프링 기술이 존재하면 안되는 상황입니다.
그렇게 도메인 코드를 POJO 형식으로 잘 작성했는데, 개발을 하다보니 그 도메인 객체를 스프링 빈으로 등록해서 조금 더 간편하게 사용하고 싶을 때가 있을 거예요.
이럴 때 사용해볼 수 있는게
@Configuration
이기도 합니다. 상희님이 만든 도메인 객체를 Configuration 클래스에서 스프링 빈으로 수동 등록하는 거죠. 이렇게 되면, 도메인 코드에서는 스프링 기술 종속성을 제거할 수 있으면서도, 동시에 스프링 빈 객체로서 사용할 수 있습니다.그래서 이 미션을 진행하실 때 상희님이 가져야 할 관점을 정리해보자면,
auth 패키지 및 JWTUtils 클래스를 스프링 기술과 별개로 존재하는 외부의 모듈(라이브러리)로서 바라보는 것
일 거 같아요.상희님이 JWTUtils 라는 코드를 외부에서 끌고 왔다고 가정하고, 코드를 다시 작성해보시면, 왜
@Configuration
을 사용해야 하는지 감이 오실 것 같아요.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
어떻게 이런 리뷰를 달 수 있죠.. 코코닥의 리뷰로 하나 배우고 갑니다 🏃🏃♂️
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
JWT 관련 로직이 JWT에 직접적인 연관성을 가지는 클래스만 포함하는 것이 이 요구사항의 의도였군요!
저는 JWT를 활용하여 인증하는 흐름까지 포함하는 건 줄 알고 다 같이 옮겨버렸던 것 같습니다..!
리뷰어님 말씀대로 토큰 생성과 조회에 대한 책임은 JWTUtils가 가진다고 생각합니다.
리뷰어님의 리뷰를 보고 미션의 의도를 정리해봤는데요,
이렇게 정리할 수 있을 것 같습니다.
미션의 의도대로 했을 때 얻는 이점
리뷰어님 덕분에 미션에서 왜 이런 요구사항을 제시했는지 얼추 이해가 된 것 같아요~ 감사합니다.
혹시 조금이라도 틀린 내용이 있거나 잘못 이해한 부분이 있다면 알려주세요!