diff --git a/backend/src/main/java/com/dazz/again/global/auth/OAuth2LoginSuccessHandler.java b/backend/src/main/java/com/dazz/again/global/auth/OAuth2LoginSuccessHandler.java index 8fa3066..6f71564 100644 --- a/backend/src/main/java/com/dazz/again/global/auth/OAuth2LoginSuccessHandler.java +++ b/backend/src/main/java/com/dazz/again/global/auth/OAuth2LoginSuccessHandler.java @@ -6,6 +6,7 @@ import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Value; // application.yaml의 설정값을 필드에 주입하는 어노테이션 import org.springframework.security.core.Authentication; import org.springframework.security.oauth2.core.user.OAuth2User; import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler; // 로그인 성공 핸들러 기반 클래스 @@ -22,6 +23,11 @@ public class OAuth2LoginSuccessHandler extends SimpleUrlAuthenticationSuccessHan private final JwtProvider jwtProvider; private final UserRepository userRepository; + // application.yaml의 frontend.url 값 주입 (환경변수 FRONTEND_URL 또는 기본값 localhost:5173) + // SecurityConfig의 CORS와 달리 여기는 "돌아갈 곳" 하나만 필요하므로 목록이 아닌 단일 값 + @Value("${frontend.url}") + private String frontendUrl; + // 카카오 로그인이 성공하면 Spring Security가 이 메서드를 자동으로 호출함 @Override public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, @@ -40,7 +46,8 @@ public void onAuthenticationSuccess(HttpServletRequest request, HttpServletRespo // 발급한 토큰을 URL 파라미터에 담아 프론트엔드로 리다이렉트 // 브라우저가 응답 헤더를 직접 읽을 수 없으므로, URL로 전달하는 것이 표준적인 방법 - // 프론트엔드: http://localhost:5173?token=eyJ... 에서 token 파라미터를 읽어 저장 - response.sendRedirect("http://localhost:5173?token=" + token); + // 프론트엔드: {frontendUrl}?token=eyJ... 에서 token 파라미터를 읽어 저장 + // 주소를 하드코딩하지 않고 환경변수 기반 frontendUrl 사용 → 로컬/배포 환경 모두 대응 + response.sendRedirect(frontendUrl + "?token=" + token); } } \ No newline at end of file diff --git a/backend/src/main/java/com/dazz/again/global/config/SecurityConfig.java b/backend/src/main/java/com/dazz/again/global/config/SecurityConfig.java index 6f905b0..93f04ba 100644 --- a/backend/src/main/java/com/dazz/again/global/config/SecurityConfig.java +++ b/backend/src/main/java/com/dazz/again/global/config/SecurityConfig.java @@ -5,6 +5,7 @@ import com.dazz.again.global.auth.JwtFilter; import com.dazz.again.global.auth.OAuth2LoginSuccessHandler; import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Value; // application.yaml의 설정값을 필드에 주입하는 어노테이션 import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpMethod; // HTTP 메서드(GET, PUT 등)를 상수로 제공하는 클래스 @@ -31,6 +32,11 @@ public class SecurityConfig { private final OAuth2LoginSuccessHandler oAuth2LoginSuccessHandler; private final JwtFilter jwtFilter; + // application.yaml의 frontend.url 값을 주입받음 (환경변수 FRONTEND_URL 또는 기본값 localhost:5173) + // @Value("${...}") : yaml의 설정 경로를 적으면 Spring이 그 값을 이 필드에 넣어줌 + @Value("${frontend.url}") + private String frontendUrl; + @Bean // Spring은 객체를 직접 new로 안만들고, Spring Container가 대신 만들고 관리하는데, `Spring이 관리하는 객체`를 Bean이라고 부름."이 메서드가 반환하는 객체를 Spring이 빈으로 등록해서 관리해줘" 라는 뜻의 어노테이션 public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http @@ -81,7 +87,9 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { public CorsConfigurationSource corsConfigurationSource() { CorsConfiguration config = new CorsConfiguration(); // 어떤 출처를 허용할지 - config.setAllowedOrigins(List.of("http://localhost:5173")); + // localhost:5173 : 로컬 개발 중인 프론트 (항상 허용 — 배포 후에도 로컬에서 개발·테스트하기 위해) + // frontendUrl : 배포된 프론트 주소 (환경변수로 주입. 로컬에선 기본값이 localhost:5173이라 중복돼도 문제없음) + config.setAllowedOrigins(List.of("http://localhost:5173", frontendUrl)); // 어떤 HTTP메서드를 허용할지 config.setAllowedMethods(List.of("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS")); // 어떤 요청헤더를 허용할지 (* = 전부) diff --git a/backend/src/main/resources/application.yaml b/backend/src/main/resources/application.yaml index 48876d1..ec684be 100644 --- a/backend/src/main/resources/application.yaml +++ b/backend/src/main/resources/application.yaml @@ -50,4 +50,13 @@ server: # JWT 설정 jwt: secret: ${JWT_SECRET} # JWT 서명용 비밀 키 (64자 이상 권장, HS512 자동 적용) - expiration-ms: ${JWT_EXPIRATION_MS} # 토큰 유효시간 (밀리초 단위, 예: 3600000 = 1시간) \ No newline at end of file + expiration-ms: ${JWT_EXPIRATION_MS} # 토큰 유효시간 (밀리초 단위, 예: 3600000 = 1시간) + +# 프론트엔드 주소 설정 +# DB 접속정보와 같은 패턴: 환경변수가 있으면 그 값, 없으면 로컬 개발용 기본값 +frontend: + # 로컬 개발 땐 FRONTEND_URL을 안 정해놨으니 localhost:5173(Vite 개발서버) 사용 + # Render 배포 환경에선 FRONTEND_URL=배포된 프론트 주소로 설정하면 그대로 적용됨 + # 사용처 2곳: ① CORS 허용 목록(SecurityConfig) ② 카카오 로그인 성공 후 돌아갈 주소(OAuth2LoginSuccessHandler) +# 프론트 배포 후 주소가 생김 그때 백엔드서버(dazz-backend-server)>Environment탭에 FRONTEND_URL=https://dazz-frontend-xxx.onrender.com 추가 -> 저장하면 백엔드가 자동재시작하면서 그 값을 읽음. => 저장위치는 Render 백엔드서비스의 Environment설정 속. + url: ${FRONTEND_URL:http://localhost:5173} \ No newline at end of file