Skip to content
Open
Show file tree
Hide file tree
Changes from 85 commits
Commits
Show all changes
103 commits
Select commit Hold shift + click to select a range
37ab4da
Feat: 로그인 인증 요청 DTO 추가
haeun92e0 Jun 29, 2026
636c329
Feat: 로그인 기능 개발 및 JWT 토큰 쿠키 발급 API 구현
haeun92e0 Jun 29, 2026
aa182a6
Feat: JWT 토큰 해석 및 Member 객체 자동 주입용 ArgumentResolver 구현
haeun92e0 Jun 29, 2026
684129b
Feat: WebMvcConfigurer 설정을 통해 커스텀 아규먼트 리솔버 추가 등록
haeun92e0 Jun 29, 2026
444e69f
Refactor: 예약 이름 치환 처리를 지원하도록 예약 요청 DTO 가공 생성자 정의
haeun92e0 Jun 29, 2026
e709d8b
Refactor: 예약 생성 API에 ArgumentResolver 연동 및 이름 치환 로직 반영
haeun92e0 Jun 29, 2026
7e42eac
Test: 인증 및 예약 이름 치환 기능 확인을 위한 1, 2단계 인수 테스트 추가
haeun92e0 Jun 29, 2026
da54f46
Docs: 복습용 주석 추가
haeun92e0 Jul 1, 2026
2745e21
Feat: 인증 실패 시 401 Unauthorized 응답을 위한 ExceptionController 추가
haeun92e0 Jul 1, 2026
b3887e3
Refactor: 하드코딩된 JWT 시크릿 키를 설정 파일로 분리
haeun92e0 Jul 1, 2026
851bbb2
Refactor: JWT 생성 로직을 MemberService로 이동
haeun92e0 Jul 3, 2026
0c3ad92
Feat: 관리자 권한 검증을 위한 AdminInterceptor 추가
haeun92e0 Jul 6, 2026
e598d30
Chore: JWT secret 설정 추가
haeun92e0 Jul 6, 2026
dbaca0e
Test: 관리자 권한 검증 테스트 추가
haeun92e0 Jul 6, 2026
9ab6dd4
Docs: 테스트 오류로 인한 주석 삭제
haeun92e0 Jul 6, 2026
69c254f
Refactor: AdminInterceptor 등록
haeun92e0 Jul 6, 2026
dcac4d5
Merge branch 'haeun92e0' into main
haeun92e0 Jul 6, 2026
8ac2b26
Feat: JWT 만료 시간 추가
haeun92e0 Jul 8, 2026
c8637cb
Refactor: JWT 파싱 실패 예외 처리 추가
haeun92e0 Jul 8, 2026
0fb712b
Refactor: 관리자 권한 부족 시 응답 코드를 403 Forbidden으로 변경
haeun92e0 Jul 8, 2026
003edd0
Refactor: 토큰 생성 및 파싱 책임을 JwtTokenProvider 클래스로 추출하여 중복 제거
haeun92e0 Jul 8, 2026
c867706
Build: 의존성을 spring-boot-starter-data-jpa로 변경
haeun92e0 Jul 13, 2026
742e87c
Refactor: 로그인 회원 리졸버가 MemberRepository를 참조하도록 수정
haeun92e0 Jul 13, 2026
2b8cc3e
feat: Member 클래스를 JPA 엔티티로 매핑 및 생성자 추가
haeun92e0 Jul 13, 2026
8f542e3
feat: EntityManager 기반의 MemberRepository 구현
haeun92e0 Jul 13, 2026
e0fddd8
refactor: MemberService가 MemberDao 대신 MemberRepository를 사용하도록 변경
haeun92e0 Jul 13, 2026
8b8425e
remove: 사용하지 않는 MemberDao 클래스 삭제
haeun92e0 Jul 13, 2026
e1ed30c
feat: Theme 클래스를 JPA 엔티티로 매핑
haeun92e0 Jul 13, 2026
2acc84a
feat: EntityManager 기반의 ThemeRepository 구현
haeun92e0 Jul 13, 2026
677f89c
refactor: ThemeController가 ThemeDao 대신 ThemeRepository를 사용하도록 변경
haeun92e0 Jul 13, 2026
2718e57
remove: 사용하지 않는 ThemeDao 클래스 삭제
haeun92e0 Jul 13, 2026
1358c45
feat: Time 클래스를 JPA 엔티티로 매핑
haeun92e0 Jul 13, 2026
23d64ec
feat: EntityManager 기반의 TimeRepository 구현
haeun92e0 Jul 13, 2026
f35bcce
refactor: TimeService가 TimeDao 대신 TimeRepository를 사용하도록 변경
haeun92e0 Jul 13, 2026
d1f60ed
remove: 사용하지 않는 TimeDao 클래스 삭제
haeun92e0 Jul 13, 2026
b16169c
feat: Reservation 클래스를 JPA 엔티티로 매핑 및 Member 연관관계 추가
haeun92e0 Jul 13, 2026
67f2b5d
feat: EntityManager 기반의 ReservationRepository 구현 (내 예약 조회 JPQL 포함)
haeun92e0 Jul 13, 2026
9dee51b
feat: 내 예약 목록 조회 응답을 위한 MyReservationResponse DTO 생성
haeun92e0 Jul 13, 2026
6fe77db
feat: 내 예약 목록 조회 API 구현 및 Repository 기반으로 리팩토링
haeun92e0 Jul 13, 2026
4b66a8a
refactor: ReservationService가 ReservationDao 대신 ReservationRepository…
haeun92e0 Jul 13, 2026
83027f1
remove: 사용하지 않는 ReservationDao 클래스 삭제
haeun92e0 Jul 13, 2026
a41d855
refactor: WebMvcConfiguration에서 리졸버 등록 시 MemberRepository 의존성 주입 추가
haeun92e0 Jul 13, 2026
b8ec630
feat: 내 예약 목록 조회(listMine) API 구현
haeun92e0 Jul 13, 2026
6f933e3
refactor: 안쓰는 메서드들 정리
haeun92e0 Jul 16, 2026
a0739e4
build: Lombok 의존성 추가
haeun92e0 Jul 16, 2026
0de5f6f
refactor: 생성자와 getter를 Lombok으로 대체
haeun92e0 Jul 16, 2026
50cf9f1
refactor: dto 성격을 띄는 MyReservationResponse를 record로 구현
haeun92e0 Jul 16, 2026
8cacf2b
refactor: 하드코딩 제거
haeun92e0 Jul 16, 2026
84b8803
refactor: MemberRepository를 Spring Data JPA 인터페이스로 전환
haeun92e0 Jul 19, 2026
bcce22a
refactor: MemberRepository Optional 반환에 따른 예외 처리 추가
haeun92e0 Jul 19, 2026
4d29436
refactor: ThemeRepository를 Spring Data JPA 인터페이스로 전환
haeun92e0 Jul 19, 2026
4b65edf
fix: ThemeController 삭제 로직 오타 수정 및 소프트 딜리트 반영
haeun92e0 Jul 19, 2026
e983b1f
refactor: TimeRepository를 Spring Data JPA 인터페이스로 전환
haeun92e0 Jul 19, 2026
201e1c8
chore: 불필요해진 TimeService 클래스 제거
haeun92e0 Jul 19, 2026
fb5bc19
feat: 예약 대기 JPA 엔티티 생성
haeun92e0 Jul 19, 2026
0429594
feat: 예약 대기 순위 정보를 담기 위한 WaitingWithRank 객체 생성
haeun92e0 Jul 19, 2026
c3a64fc
feat: WaitingRepository 생성 및 대기 순위 조회 JPQL 구현
haeun92e0 Jul 19, 2026
b127cc2
feat: 예약 대기 응답을 위한 WaitingResponse 레코드 생성
haeun92e0 Jul 19, 2026
01af716
feat: 예약 대기 신청 및 취소 API 구현
haeun92e0 Jul 19, 2026
20d17b0
refactor: ReservationRepository JPA 전환 및 중복 예약 확인 메서드 추가
haeun92e0 Jul 19, 2026
0fc47d8
feat: 내 예약 목록 조회 시 예약 대기 및 순위 목록 포함하도록 수정
haeun92e0 Jul 19, 2026
9b3d82e
Merge branch 'haeun92e0' into final6
haeun92e0 Jul 19, 2026
cfcb3e8
refactor: TimeController에서 TimeService 제거 및 Repository 직접 연동
haeun92e0 Jul 25, 2026
bfc4174
fix: rebase 과정에서 누락된 MemberRepository 의존성 주입 및 빌드 오류 수정
haeun92e0 Jul 25, 2026
ddbe201
fix: 애플리케이션 환경 설정 및 인증 예외 처리 보완
haeun92e0 Jul 26, 2026
3faa466
feat: 내 예약 목록 조회 및 예약/대기 기능 구현
haeun92e0 Jul 26, 2026
e8358f3
test: 미션 테스트 코드 추가 및 검증
haeun92e0 Jul 26, 2026
cc529cb
feat: JWT 비밀키 프로퍼티 추가 및 환경 설정 분리
haeun92e0 Jul 26, 2026
e9f37b1
refactor: JwtUtils의 @Component 제거 및 구조 개선
haeun92e0 Jul 26, 2026
1200212
feat: @Configuration 기반의 JwtUtils 빈 등록 설정 추가
haeun92e0 Jul 26, 2026
01fcd88
feat: 기본 프로파일용 DataLoader 초기화 클래스 구현
haeun92e0 Jul 26, 2026
d2f7a45
feat: 테스트 프로파일용 TestDataLoader 초기 데이터 설정 구현
haeun92e0 Jul 26, 2026
5fd4511
refactor: 초기 INSERT 구문 제거 및 테이블 스키마 정돈
haeun92e0 Jul 26, 2026
019bdd4
feat: 애플리케이션 자동 배포 스크립트 추가
haeun92e0 Jul 26, 2026
f02356f
test: 8단계 비밀키 외부 분리 검증 테스트 작성
haeun92e0 Jul 26, 2026
08b0015
test: 7단계 @Configuration 미션 검증 테스트 작성
haeun92e0 Jul 26, 2026
6205791
Merge branch 'haeun92e0' into final9
haeun92e0 Jul 26, 2026
5b295d1
refactor: 미사용 JwtConfig 클래스 삭제
haeun92e0 Jul 26, 2026
a7ef5b0
refactor: JwtUtils로 일원화에 따른 JwtTokenProvider 클래스 삭제
haeun92e0 Jul 26, 2026
88cdd15
feat: (id, role) 전용 Member 생성자 추가
haeun92e0 Jul 26, 2026
722a5ea
refactor: ArgumentResolver 내 DB 조회 제거 및 JWT Claim 기반 객체 반환
haeun92e0 Jul 26, 2026
920088e
refactor: AdminInterceptor 의존성을 JwtTokenProvider에서 JwtUtils로 변경
haeun92e0 Jul 26, 2026
d6a99a4
refactor: MemberService 의존성을 JwtTokenProvider에서 JwtUtils로 변경
haeun92e0 Jul 26, 2026
be70672
feat: @Configuration 기반의 JwtUtils 빈 등록 설정 추가
haeun92e0 Jul 26, 2026
77f7d71
refactor: MemberRepository 의존성 제거 및 JwtUtils 기반 설정으로 수정
haeun92e0 Jul 26, 2026
000896a
refactor: ReservationController 내 클래스 풀 패키지 경로를 import문으로 변경
haeun92e0 Jul 29, 2026
1ef73f4
test: Waiting 도메인 검증 및 대기 생성 관련 단위 테스트 추가
haeun92e0 Jul 29, 2026
bf0aea5
style: Repository 내 @Query 문에 텍스트 블록("""") 적용하여 가독성 개선
haeun92e0 Jul 29, 2026
209a9ce
test: Waiting 도메인 검증 및 대기 생성 관련 단위 테스트 추가(잘못 삭제해서 다시 커밋)
haeun92e0 Jul 29, 2026
dd4b8c2
fix: 로그인 유저 예약 생성 실패 이슈 해결 (ArgumentResolver DB 조회 로직 복구)
haeun92e0 Jul 29, 2026
f95aa63
refactor: ArgumentResolver 등록 방식을 스프링 빈 주입으로 수정
haeun92e0 Jul 29, 2026
501779d
chore: 스터디 피드백을 반영해 deploy.sh 개선
haeun92e0 Aug 1, 2026
985e5c1
refactor: WaitingController 비즈니스 로직을 WaitingService로 위임 및 리팩토링
haeun92e0 Aug 1, 2026
2e146eb
test: WaitingService 리팩토링에 따른 WaitingTest 테스트 코드 업데이트
haeun92e0 Aug 1, 2026
4b46f91
fix: 배포 스크립트(deploy.sh) 안정성 개선
haeun92e0 Aug 1, 2026
f8521e1
refactor: 프로세스 종료 대기 로직 개선
haeun92e0 Aug 1, 2026
df8025f
feat: Service 계층 비즈니스 로직 구현
haeun92e0 Aug 1, 2026
1d863b8
test: 테스트 코드 보완
haeun92e0 Aug 1, 2026
5773213
refactor: @RequiredArgsConstructor를 활용한 생성자 주입 리팩토링
haeun92e0 Aug 4, 2026
bbaa9ba
refactor: TimeService 내 불명확한 변수명(t -> time) 수정
haeun92e0 Aug 4, 2026
58740bf
refactor: 불필요한 @Query 어노테이션 제거
haeun92e0 Aug 4, 2026
f43cbba
refactor: 쿼리 메서드 파라미터 타입 일치를 위한 메서드명 수정
haeun92e0 Aug 4, 2026
5d09da9
test: WaitingService 단위 테스트 추가 및 검증 케이스 작성
haeun92e0 Aug 4, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions deploy.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#!/bin/bash

# 1. 최신 코드 불러오기
echo ">>> Git Pull 실행"
git pull origin main

# 2. 프로젝트 빌드
echo ">>> 프로젝트 빌드 시작"
./gradlew build -x test

# 3. 기존 실행 중인 프로세스 종료
echo ">>> 기존 애플리케이션 PID 확인"
CURRENT_PID=$(pgrep -f roomescape-0.0.1-SNAPSHOT.jar)

if [ -z "$CURRENT_PID" ]; then
echo ">>> 실행 중인 애플리케이션이 없습니다."
else
echo ">>> 기존 애플리케이션 종료 (PID: $CURRENT_PID)"
kill -15 $CURRENT_PID
sleep 5
fi

# 4. 새 애플리케이션 실행
echo ">>> 새 애플리케이션 배포 및 실행"
JAR_NAME=$(ls -tr build/libs/*.jar | tail -n 1)

nohup java -jar $JAR_NAME > app.log 2>&1 &

echo ">>> 배포 완료!"
47 changes: 47 additions & 0 deletions src/main/java/roomescape/DataLoader.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package roomescape;


import org.springframework.boot.CommandLineRunner;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Component;
import roomescape.member.Member;
import roomescape.member.MemberRepository;
import roomescape.theme.Theme;
import roomescape.theme.ThemeRepository;
import roomescape.time.Time;
import roomescape.time.TimeRepository;

@Profile("!test") //테스트 환경이 아닐때 실행되게 하는 기능
@Component
public class DataLoader implements CommandLineRunner {

private final MemberRepository memberRepository;
private final ThemeRepository themeRepository;
private final TimeRepository timeRepository;

public DataLoader(MemberRepository memberRepository, ThemeRepository themeRepository, TimeRepository timeRepository) {
this.memberRepository = memberRepository;
this.themeRepository = themeRepository;
this.timeRepository = timeRepository;
}

@Override
public void run(String... args) throws Exception {
// 1. 회원 저장 (ID: 1, 2)
memberRepository.save(new Member("어드민", "admin@email.com", "password", "ADMIN"));
memberRepository.save(new Member("브라운", "brown@email.com", "password", "USER"));

// 2. 테마 저장
themeRepository.save(new Theme("테마1", "테마1입니다."));
themeRepository.save(new Theme("테마2", "테마2입니다."));
themeRepository.save(new Theme("테마3", "테마3입니다."));

// 3. 시간 저장
timeRepository.save(new Time("10:00"));
timeRepository.save(new Time("12:00"));
timeRepository.save(new Time("14:00"));
timeRepository.save(new Time("16:00"));
timeRepository.save(new Time("18:00"));
timeRepository.save(new Time("20:00"));
}
}
56 changes: 56 additions & 0 deletions src/main/java/roomescape/TestDataLoader.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package roomescape;


import org.springframework.boot.CommandLineRunner;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Component;
import roomescape.member.Member;
import roomescape.member.MemberRepository;
import roomescape.reservation.Reservation;
import roomescape.reservation.ReservationRepository;
import roomescape.theme.Theme;
import roomescape.theme.ThemeRepository;
import roomescape.time.Time;
import roomescape.time.TimeRepository;

@Profile("test") //테스트 환경에서만 동작
@Component
public class TestDataLoader implements CommandLineRunner {

private final MemberRepository memberRepository;
private final ThemeRepository themeRepository;
private final TimeRepository timeRepository;
private final ReservationRepository reservationRepository;

public TestDataLoader(MemberRepository memberRepository,
ThemeRepository themeRepository,
TimeRepository timeRepository,
ReservationRepository reservationRepository) {
this.memberRepository = memberRepository;
this.themeRepository = themeRepository;
this.timeRepository = timeRepository;
this.reservationRepository = reservationRepository;
}

@Override
public void run(String... args) throws Exception {
// 1. 회원 저장 (1L: 어드민, 2L: 브라운)
Member admin = memberRepository.save(new Member("어드민", "admin@email.com", "password", "ADMIN"));
Member brown = memberRepository.save(new Member("브라운", "brown@email.com", "password", "USER"));

// 2. 테마 저장
Theme theme1 = themeRepository.save(new Theme("테마1", "테마1입니다."));
Theme theme2 = themeRepository.save(new Theme("테마2", "테마2입니다."));
Theme theme3 = themeRepository.save(new Theme("테마3", "테마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"));

// 4. 5단계, 6단계 테스트에서 요구하는 예약 데이터 저장
reservationRepository.save(new Reservation("어드민", "2024-03-01", time1, theme1, admin));
reservationRepository.save(new Reservation("어드민", "2024-03-01", time1, theme2, admin));
reservationRepository.save(new Reservation("어드민", "2024-03-01", time3, theme3, admin));
}
}
15 changes: 6 additions & 9 deletions src/main/java/roomescape/WebMvcConfiguration.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
package roomescape;

import org.springframework.beans.factory.annotation.Value;
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 roomescape.auth.JwtUtils;
import roomescape.member.AdminInterceptor;
import roomescape.member.JwtTokenProvider;
import roomescape.member.LoginMemberArgumentResolver;
import roomescape.member.MemberRepository;

Expand All @@ -15,21 +14,19 @@
@Configuration
public class WebMvcConfiguration implements WebMvcConfigurer {

private final JwtTokenProvider jwtTokenProvider;
private final MemberRepository memberRepository;
private final JwtUtils jwtUtils;

public WebMvcConfiguration(JwtTokenProvider jwtTokenProvider, MemberRepository memberRepository){
this.jwtTokenProvider = jwtTokenProvider;
this.memberRepository = memberRepository;
public WebMvcConfiguration(JwtUtils jwtUtils){
this.jwtUtils = jwtUtils;
}
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
resolvers.add(new LoginMemberArgumentResolver(jwtTokenProvider, memberRepository));
resolvers.add(new LoginMemberArgumentResolver(jwtUtils));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Component로 관리되고 있는 LoginMemberArgumentResolver를 new로 새로 생성할 필요가 있을까요?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오마이갓 수정했습니다!! 감사합니다!!

}

@Override
public void addInterceptors(InterceptorRegistry registry){
registry.addInterceptor(new AdminInterceptor(jwtTokenProvider))
registry.addInterceptor(new AdminInterceptor(jwtUtils))
.addPathPatterns("/admin/**", "/admin");
}
}
Expand Down
18 changes: 18 additions & 0 deletions src/main/java/roomescape/auth/AuthConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package roomescape.auth;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AuthConfig {

@Value("${roomescape.auth.jwt.secret}")
private String secretKey;

@Bean
public JwtUtils jwtUtils() {
// 1시간(3600000ms) 만료 기준
return new JwtUtils(secretKey, 3600000L);
}
}
47 changes: 47 additions & 0 deletions src/main/java/roomescape/auth/JwtUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package roomescape.auth;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;

import java.nio.charset.StandardCharsets;
import java.security.Key;
import java.util.Date;

public class JwtUtils {

private final String secretKey;
private final long validityInMilliseconds;

public JwtUtils(String secretKey, long validityInMilliseconds) {
this.secretKey = secretKey;
this.validityInMilliseconds = validityInMilliseconds;
}

private Key getSigningKey() {
return Keys.hmacShaKeyFor(secretKey.getBytes(StandardCharsets.UTF_8));
}

public String createToken(String id, String role) {
Claims claims = Jwts.claims().setSubject(id);
claims.put("role", role);

Date now = new Date();
Date validity = new Date(now.getTime() + validityInMilliseconds);

return Jwts.builder()
.setClaims(claims)
.setIssuedAt(now)
.setExpiration(validity)
.signWith(getSigningKey())
.compact();
}

public Claims parseToken(String token) {
return Jwts.parserBuilder()
.setSigningKey(getSigningKey())
.build()
.parseClaimsJws(token)
.getBody();
}
}
16 changes: 0 additions & 16 deletions src/main/java/roomescape/config/JwtConfig.java

This file was deleted.

9 changes: 5 additions & 4 deletions src/main/java/roomescape/member/AdminInterceptor.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,13 @@
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import roomescape.auth.JwtUtils;

public class AdminInterceptor implements HandlerInterceptor {
private final JwtTokenProvider jwtTokenProvider;
private final JwtUtils jwtUtils;

public AdminInterceptor(JwtTokenProvider jwtTokenProvider) {
this.jwtTokenProvider = jwtTokenProvider;
public AdminInterceptor(JwtUtils jwtUtils) {
this.jwtUtils = jwtUtils;
}

@Override
Expand Down Expand Up @@ -44,7 +45,7 @@ public boolean preHandle(HttpServletRequest request, HttpServletResponse respons
}

try {
Claims claims = jwtTokenProvider.parseToken(token);
Claims claims = jwtUtils.parseToken(token);

String role = claims.get("role", String.class);

Expand Down
35 changes: 0 additions & 35 deletions src/main/java/roomescape/member/JwtTokenProvider.java

This file was deleted.

47 changes: 23 additions & 24 deletions src/main/java/roomescape/member/LoginMemberArgumentResolver.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,20 @@
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.core.MethodParameter;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
import roomescape.auth.JwtUtils;

//컨트롤러의 매개변수를 자동으로 만들어주는 클래스
@Component
public class LoginMemberArgumentResolver implements HandlerMethodArgumentResolver {
private final JwtTokenProvider jwtTokenProvider;
private final MemberRepository memberRepository;
private final JwtUtils jwtUtils;

public LoginMemberArgumentResolver(JwtTokenProvider jwtTokenProvider,MemberRepository memberRepository){
this.jwtTokenProvider = jwtTokenProvider;
this.memberRepository = memberRepository;
public LoginMemberArgumentResolver(JwtUtils jwtUtils){
this.jwtUtils = jwtUtils;
}

@Override
Expand All @@ -30,30 +31,28 @@ public boolean supportsParameter(MethodParameter parameter) {
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
HttpServletRequest request = (HttpServletRequest) webRequest.getNativeRequest(); //현재 HTTP 요청 가져오기
Cookie[] cookies = request.getCookies(); //쿠키 가져오기
String token = extractToken(request);

if (cookies == null) {
throw new IllegalArgumentException("토큰 쿠키가 존재하지 않습니다.");
if (token == null) {
throw new IllegalArgumentException("토큰이 존재하지 않습니다.");
}

String token = "";
for (Cookie cookie : cookies) {
if ("token".equals(cookie.getName())) {//이름이 token인 쿠키 찾기
token = cookie.getValue(); //JWT 문자열 저장
}
}

if(token.isBlank()){
throw new IllegalArgumentException("토큰 값이 비어있습니다.");
}

// 토큰 파싱하여 회원 정보 추출
Claims claims = jwtTokenProvider.parseToken(token);
//정보 꺼내기
Claims claims = jwtUtils.parseToken(token);
Long id = Long.parseLong(claims.getSubject());
String role = claims.get("role", String.class);
return new Member(id, role); // 필요한 id와 role만 가진 객체 반환

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

현재 로그인한 회원도 예약 생성이 되지 않습니다. 왜일까요?
해당 부분을 시작으로 한번 찾아봅시다~!

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

앗... new Member(id, role) 객체를 직접 생성했더니, name이나 email이 null 상태가 되어 예약 생성 시 에러가 발생한 것 같습니다.
LoginMemberArgumentResolver에 MemberRepository 의존성을 다시 주입받아 DB를 통해 Member 엔티티를 반환하도록 수정했습니다.
감사합니다!

}

return memberRepository.findById(id)
.orElseThrow(() -> new IllegalArgumentException("존재하지 않는 회원입니다."));
private String extractToken(HttpServletRequest request) {
Cookie[] cookies = request.getCookies();
if (cookies != null) {
for (Cookie cookie : cookies) {
if ("token".equals(cookie.getName())) {
return cookie.getValue();
}
}
}
return null;
}
}
//브라우저가 보낸 JWT 쿠키를 읽어서 그 안에 저장된 회원 정보를 Member 객체로 복원한 뒤, 컨트롤러의 Member loginMember 매개변수에 자동으로
Expand Down
Loading