-
Notifications
You must be signed in to change notification settings - Fork 76
[그리디] 황혜림 Spring Core (배포) 7,8,9 단계 제출합니다. #176
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
base: hyerimh
Are you sure you want to change the base?
Changes from 2 commits
0c86c37
8e38013
7867422
67b83a5
c8df088
39dbc46
06d9632
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| package jwt; | ||
|
|
||
| import org.springframework.beans.factory.annotation.Value; | ||
| import org.springframework.context.annotation.Bean; | ||
| import org.springframework.context.annotation.Configuration; | ||
|
|
||
| @Configuration | ||
| public class AuthConfig { | ||
|
|
||
| @Bean | ||
| public JwtUtils jwtUtils( | ||
| @Value("${roomescape.auth.jwt.secret}") String secretKey, | ||
| @Value("${roomescape.auth.jwt.expiration}") long expirationTime) { | ||
| return new JwtUtils(secretKey, expirationTime); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| package roomescape; | ||
|
|
||
| import lombok.RequiredArgsConstructor; | ||
| import org.springframework.boot.CommandLineRunner; | ||
| import org.springframework.context.annotation.Profile; | ||
| import org.springframework.stereotype.Component; | ||
| import roomescape.domain.member.Member; | ||
| import roomescape.domain.member.MemberRepository; | ||
|
|
||
| @Component | ||
| @Profile("prod") | ||
| @RequiredArgsConstructor | ||
| public class DataLoader implements CommandLineRunner { | ||
|
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. 👀 Comment혜림이 이번 미션에선 실제 서비스하는 환경이라면, 매번 빌드를 할 때마다 이런 데이터로더가 실행되면 안되지 않을까요?
Author
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. 말씀하신대로 prod는 실제 서비스 환경이라서 이렇게 매 빌드마다 데이터를 삽입하면 안되겠네요!! dev로 수정하였습니다. 추가로 properties를 yml로 바꿨고 prod, dev, test 환경별로 만들었습니다 |
||
|
|
||
| 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")); | ||
| } | ||
| } | ||
|
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. 🤔 Request Change테스트 관련된 코드는 test 패키지로 옮겨주세요. 이번 미션에서 profile을 분리하면서 application 설정을 하는 연습을 하셨을텐데요. 아마 이 코드를 test영역으로 내리면, 의도와는 다르게 동작할 수도 있을 것 같은데요.
Author
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.
우선 TestDataLoader를 test패키지 하위로 이동하였습니다! 의도와 다르게 작동한다는 걸 제대로 이해하지 못한 것 같아요..! |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| package roomescape; | ||
|
|
||
| import lombok.RequiredArgsConstructor; | ||
| import org.springframework.boot.CommandLineRunner; | ||
| import org.springframework.context.annotation.Profile; | ||
| import org.springframework.stereotype.Component; | ||
| import roomescape.domain.member.MemberRepository; | ||
| import roomescape.domain.reservation.Reservation; | ||
| import roomescape.domain.reservation.ReservationRepository; | ||
| import roomescape.domain.theme.ThemeRepository; | ||
| import roomescape.domain.time.Time; | ||
| import roomescape.domain.member.Member; | ||
| import roomescape.domain.theme.Theme; | ||
| import roomescape.domain.time.TimeRepository; | ||
|
|
||
|
|
||
| @Component | ||
| @Profile("test") | ||
| @RequiredArgsConstructor | ||
| public class TestDataLoader implements CommandLineRunner { | ||
|
|
||
| private final MemberRepository memberRepository; | ||
| private final ThemeRepository themeRepository; | ||
| private final TimeRepository timeRepository; | ||
| private final ReservationRepository reservationRepository; | ||
|
|
||
| @Override | ||
| public void run(String... args) throws Exception { | ||
| Member admin = memberRepository.save(new Member("어드민", "[email protected]", "password", "ADMIN")); | ||
| Member user = memberRepository.save(new Member("브라운", "[email protected]", "password", "USER")); | ||
|
|
||
| Theme theme1 = themeRepository.save(new Theme("테마1", "테마1입니다.")); | ||
| Theme theme2 = themeRepository.save(new Theme("테마2", "테마2입니다.")); | ||
| Theme theme3 = themeRepository.save(new Theme("테마3", "테마3입니다.")); | ||
|
|
||
| Time time1 = timeRepository.save(new Time("10:00")); | ||
| Time time2 = timeRepository.save(new Time("12:00")); | ||
| Time time3 = timeRepository.save(new Time("14:00")); | ||
| Time time4 = timeRepository.save(new Time("16:00")); | ||
| Time time5 = timeRepository.save(new Time("18:00")); | ||
| Time time6 = timeRepository.save(new Time("20:00")); | ||
|
|
||
| reservationRepository.save(new Reservation("", "2024-03-01", time1, theme1, admin)); | ||
| reservationRepository.save(new Reservation("", "2024-03-01", time2, theme2, admin)); | ||
| reservationRepository.save(new Reservation("", "2024-03-01", time3, theme3, admin)); | ||
| reservationRepository.save(new Reservation("브라운", "2024-03-01", time1, theme2)); | ||
| } | ||
| } |
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6,25 +6,33 @@ | |
| import io.restassured.response.Response; | ||
| import jakarta.transaction.Transactional; | ||
| import java.util.List; | ||
| import jwt.JwtUtils; | ||
| import org.junit.jupiter.api.DisplayName; | ||
| import org.junit.jupiter.api.Test; | ||
| import org.springframework.beans.factory.annotation.Value; | ||
| import org.springframework.boot.test.context.SpringBootTest; | ||
| import org.springframework.stereotype.Component; | ||
| import org.springframework.test.annotation.DirtiesContext; | ||
|
|
||
| import java.util.HashMap; | ||
| import java.util.Map; | ||
| import org.springframework.test.context.ActiveProfiles; | ||
| import roomescape.domain.reservation.dto.MyReservationResponse; | ||
| import roomescape.domain.waiting.dto.WaitingResponse; | ||
| import roomescape.auth.LoginRequest; | ||
| import roomescape.domain.reservation.dto.ReservationResponse; | ||
|
|
||
| import static org.assertj.core.api.Assertions.assertThat; | ||
|
|
||
| @ActiveProfiles("test") | ||
| @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) | ||
| @DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) | ||
| @Transactional | ||
| public class MissionStepTest { | ||
|
|
||
| @Value("${roomescape.auth.jwt.secret}") | ||
| private String secretKey; | ||
|
|
||
| @Test | ||
| @DisplayName("로그인 성공 시 토큰이 포함된 쿠키를 반환한다") | ||
| void 일단계() { | ||
|
|
@@ -60,12 +68,17 @@ public class MissionStepTest { | |
| String token = createToken("[email protected]", "password"); // 일단계에서 토큰을 추출하는 로직을 메서드로 따로 만들어서 활용하세요. | ||
|
|
||
| Map<String, String> params = new HashMap<>(); | ||
| params.put("date", "2024-03-01"); | ||
| params.put("date", "2024-01-01"); | ||
| params.put("time", "1"); | ||
| params.put("theme", "1"); | ||
|
|
||
| params.put("name", "어드민"); | ||
|
|
||
| Map<String, String> params2 = new HashMap<>(); | ||
| params2.put("date", "2024-02-01"); | ||
| params2.put("time", "1"); | ||
| params2.put("theme", "1"); | ||
| params2.put("name", "브라운"); | ||
|
|
||
| ExtractableResponse<Response> response = RestAssured.given().log().all() | ||
| .body(params) | ||
| .cookie("token", token) | ||
|
|
@@ -77,10 +90,8 @@ public class MissionStepTest { | |
| assertThat(response.statusCode()).isEqualTo(201); | ||
| assertThat(response.as(ReservationResponse.class).name()).isEqualTo("어드민"); | ||
|
|
||
| params.put("name", "브라운"); | ||
|
|
||
| ExtractableResponse<Response> adminResponse = RestAssured.given().log().all() | ||
| .body(params) | ||
| .body(params2) | ||
| .cookie("token", token) | ||
| .contentType(ContentType.JSON) | ||
| .post("/reservations") | ||
|
|
@@ -178,6 +189,18 @@ private String createToken(String email, String password) { | |
|
|
||
| assertThat(status).isEqualTo("1번째 예약대기"); | ||
| } | ||
|
|
||
| @Test | ||
| @DisplayName("@Component 없이 JwtUtils가 빈으로 등록되는지 확인한다.") | ||
| void 칠단계() { | ||
| Component componentAnnotation = JwtUtils.class.getAnnotation(Component.class); | ||
| assertThat(componentAnnotation).isNull(); | ||
| } | ||
|
|
||
| @Test | ||
| void 팔단계() { | ||
| assertThat(secretKey).isNotBlank(); | ||
| } | ||
| } | ||
|
|
||
|
|
||
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.
👀 Comment
@ConfigurationProperties라는 주입방식을 한번 살펴보고 어떤것이 더 적절한지 생각해보시면 좋겠습니다.
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.
👀 Comment
저는 이 configuration 이 약간 이질적으로 느껴지는데요.
일단 저는 여러모로 이 jwt 패키지 존재 자체가 공감이 잘 안됩니다.
이를 삭제하고 합쳐라 라는 의미의 리뷰는 아닙니다.
혜림이 질문 주신 것 처럼 이를 분리하는 이유를 조금 더 같이 찾아봐야될 것 같은데요.
일단 패키지를 분리하는 것은 생각보다 큰 의미입니다.
설정을 패키지 별로 옵션을 다르게 줄 수도 있겠죠.
사실 저도 현재로선 어떤 활용 방법 자체가 떠오르진 않는데요.
혜림님이 Auth 관련된 영역을 이쪽으로 많이 옮기고, prod, dev, test, ... 환경 별로 auth 설정을 달리하면서 어떤일이 벌어지는지 경험적으로 느끼셨으면 좋겠습니다.
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.
현재 값이 두개이긴 하지만 더 깔끔하고 관련 설정이 한눈에 보이는 것 같아서 @ConfiguationProperties를 사용해서 수정해보았습니다!
@Value:단일 값을 주입받기 위해 사용
RelaxedBinding 사용 불가
@ConfigurationProperties:클래스로 N개의 값을 바인딩하기 위해 사용
RelaxedBinding 사용 가능
주의사항
+) RelaxedBinding이란