프론트(리액트)와 백엔드(스프링부트)연결

Yeeun·2025년 6월 4일
0

SpringBoot

목록 보기
45/46
post-thumbnail

시험하는법

프론트엔드서버 켜고(securityoauth2jwtreact) npm start

백엔드서버 켜고 (SpringBootSecurityJWTOAuth2)

http://localhost:8080/login 들어가서 oauth 로그인 ( 구글로그인이나)

OAuth2SuccessHandler 보면 마지막에

response.sendRedirect("http://localhost:3000/oauth2/callback");
System.out.println("jwtToken:" + jwtToken);
response.setHeader(HttpHeaders.AUTHORIZATION, jwtToken);
라 되어있음. 즉, 이쪽으로 리다이렉트 해라고 되어있음.

그럼 3000번대 포트 App.js가 실행되고 여기에 있는 코드인 <Route path="/oauth2/callback" element={} /> 이거 실행.

프론트에 JwtCallback.js 보면 const res = await fetch("http://localhost:8080/api/jwtcallback", { 라 되어있으니

이때 백엔드 SecurityController 클래스의 이 메소드가 실행되어서 쿠키랑 토큰이랑 헤더에 다 담김
@PostMapping("/api/jwtcallback")
public ResponseEntity<?> jwtCallBack(HttpServletRequest request){
String jwtToken = null;
Cookie[] cookies = request.getCookies();
for(Cookie cookie : cookies) {
if(!cookie.getName().equals("jwtToken")) continue;
try {
jwtToken = URLDecoder.decode(cookie.getValue(),"utf-8");
}catch(Exception e) {
System.out.println(e.getMessage());
}
break;
}
return ResponseEntity.ok().header(HttpHeaders.AUTHORIZATION, jwtToken).build();
}

네비게이트 홈으로 가라 적혀있어 홈페이지뜸

네, 설명하신 흐름(백엔드 OAuth 로그인 → 3000번 포트로 리다이렉트 → /oauth2/callback에서 JWT 받기)은 전체적으로 맞습니다.
하지만 "로그인 처리중입니다..."가 안 뜨고 바로 홈페이지 글자가 뜨는 이유는 React 라우팅/렌더링 구조 또는 리다이렉트 타이밍 문제 때문일 가능성이 높습니다.


1. 설명하신 흐름 요약

  • 백엔드에서 OAuth 로그인 성공
    • response.sendRedirect("http://localhost:3000/oauth2/callback");
    • response.setHeader(HttpHeaders.AUTHORIZATION, jwtToken);
  • 프론트엔드(React)
    • /oauth2/callback 경로에 `` 컴포넌트가 매핑됨
    • JwtCallback.js에서 백엔드에 토큰 요청 → 토큰 저장 → navigate('/')로 홈으로 이동

2. "로그인 처리중입니다..."가 안 뜨는 이유

A. 리다이렉트가 너무 빨라서

  • JwtCallback 컴포넌트가 마운트되자마자 useEffect에서 토큰 요청 후
    바로 navigate('/')로 홈으로 이동합니다.
  • 이 과정이 매우 빠르게 일어나기 때문에
    로그인 처리 중입니다...가 화면에 거의 보이지 않고
    바로 홈페이지로 이동하게 됩니다.

B. 라우팅 구조 문제

  • 만약 App.js에서 / 경로에 바로 `같은 컴포넌트를 매핑해두었다면 navigate('/')`가 실행되면서 즉시 홈 컴포넌트가 렌더링됩니다.
  • 이때, "로그인 처리중입니다..."는 아주 잠깐 렌더링되거나,
    React의 렌더링 최적화 때문에 아예 보이지 않을 수도 있습니다.

C. 추가 가능성: 라우팅/컴포넌트 등록 문제

  • 만약 } />
    제대로 등록되어 있지 않거나,
    `` 내부에서 에러가 발생해 곧바로 navigate가 실행되지 않는 경우
    해당 경로에서 원하는 컴포넌트가 보이지 않을 수도 있습니다.
  • 하지만, 콘솔에 "JWT 저장됨" 로그가 뜬다면 useEffect는 정상 동작한 것입니다.

3. 실제로 어떤 현상인가?

  • 이미지를 보면 홈페이지 글자만 보이고,
    콘솔에는 "JWT 저장됨: ..." 로그가 찍혀 있습니다.
  • 즉, /oauth2/callback에 잠깐 들어왔다가
    바로 /(홈)으로 이동한 상태입니다.

4. 만약 "로그인 처리중입니다..."를 보이게 하고 싶다면?

  • navigate('/')를 토큰 저장 후에 바로 실행하지 말고,
    setTimeout 등으로 1초 정도 딜레이를 주면
    "로그인 처리중입니다..."가 잠깐이라도 보입니다.

예시:

if (jwtToken) {
    localStorage.setItem('jwtToken', jwtToken);
    console.log('JWT 저장됨:', jwtToken);
    setTimeout(() => {
        navigate('/');
    }, 1000); // 1초 후 홈으로 이동
}

5. 결론

  • 설명하신 백엔드-프론트 흐름은 맞습니다.
  • "로그인 처리중입니다..."가 안 보이는 것은
    토큰 저장 후 즉시 navigate('/')로 홈으로 이동하기 때문입니다.
  • 이게 정상 동작이며, 만약 메시지를 잠깐이라도 보고 싶으면
    navigate에 딜레이를 주면 됩니다.

참고:
이 현상은 React에서 useEffect로 비동기 작업 후 바로 라우트 이동을 할 때
매우 흔하게 발생하는 패턴입니다[7][8].

[1] https://pplx-res.cloudinary.com/image/private/user_uploads/54916126/9b5ef289-2584-4a3e-b7bc-0a1f55b30488/image.jpg
[2] https://www.reddit.com/r/Frontend/comments/1afmh71/why_is_the_url_changing_but_the_component_is_not/
[3] https://trio.dev/guide-to-react-router-v6/
[4] https://stackoverflow.com/questions/67855074/react-useeffect-doesnt-trigger-fetch-when-rendering-component
[5] https://stackoverflow.com/questions/60156663/how-to-include-authorization-header-in-get-request-to-secured-endpoint-in-spring
[6] https://stackoverflow.com/questions/72144689/how-to-fix-loading-spinner-when-using-useeffect-hooks-with-dependency-list
[7] https://www.geeksforgeeks.org/how-to-prevent-page-from-rendering-before-redirect-in-reactjs/
[8] https://www.robinwieruch.de/react-router-redirect/
[9] https://www.youtube.com/watch?v=OfJGNonUUM0
[10] https://stackoverflow.com/questions/43884204/react-router-is-not-rendering-anything
[11] https://github.com/reach/router/issues/504
[12] https://www.reddit.com/r/react/comments/rew2yd/react_router_not_rendering_pages_but_link_changes/
[13] https://reactrouter.com/v6/start/tutorial
[14] https://stackoverflow.com/questions/77959977/how-to-create-custom-route-childrens-of-react-router-v6
[15] https://gist.github.com/mjackson/d54b40a094277b7afdd6b81f51a0393f
[16] https://react.dev/reference/react/useEffect
[17] https://stackoverflow.com/questions/73012126/react-async-data-fetch-in-useeffect
[18] https://velog.io/@ghwns9991/Spring-Boot-JWT-Tutorial
[19] https://docs.spring.io/spring-security/reference/servlet/oauth2/resource-server/jwt.html
[20] https://blog.nashtechglobal.com/spring-boot-rest-authentication-with-jwt/
[21] https://wonyong-jang.github.io/spring/2020/08/17/Spring-Security-JWT.html
[22] https://dev.to/abhay_yt_52a8e72b213be229/handling-redirects-in-react-router-v6-methods-and-best-practices-2ocp
[23] https://kinsta.com/knowledgebase/react-hook-useeffect-has-a-missing-dependency/
[24] https://community.palantir.com/t/react-router-error-no-route-matches-url-multipass-login-in-oauth2-flow/2012
[25] https://www.youtube.com/watch?v=w16q1Wr5ZV4
[26] https://stackoverflow.com/questions/76387513/why-is-my-react-component-not-updating-with-useeffect-hook
[27] https://community.auth0.com/t/deployed-react-app-unable-to-issue-redirect-for-oauth-2-0-transaction/99929
[28] https://dev.to/salehmubashar/conditional-routing-with-react-router-v6-229g
[29] https://stackoverflow.com/questions/16864199/how-to-configure-route-for-oauth-callback
[30] https://stackoverflow.com/questions/71924362/how-to-add-elements-in-react-router-v6-with-props
[31] https://reactrouter.com/6.30.0/start/concepts
[32] https://github.com/tasoskakour/react-use-oauth2
[33] https://www.reddit.com/r/reactjs/comments/17k02bo/react_router_v6_using_the_element_prop/
[34] https://www.reddit.com/r/reactjs/comments/1fg31qs/if_i_shouldnt_fetch_in_useeffect_where_should_i/
[35] https://www.dhiwise.com/post/how-to-fix-useeffect-not-triggering-in-your-react-project
[36] https://github.com/vercel/next.js/discussions/63996
[37] https://react.dev/learn/you-might-not-need-an-effect
[38] https://www.reddit.com/r/reactjs/comments/x9rlzw/loading_state_on_api_call_with_useeffect/
[39] https://devtrium.com/posts/async-functions-useeffect
[40] https://stackoverflow.com/questions/57263525/useeffect-not-being-called-and-not-updating-state-when-api-is-fetched
[41] https://www.youtube.com/watch?v=X80nJ5T7YpE
[42] https://stackoverflow.com/questions/45152484/how-to-set-respond-header-values-in-spring-boot-rest-service-method/45152670
[43] https://stackoverflow.com/questions/76619918/spring-boot-security-use-token-from-cookies-instead-of-authorization-header
[44] https://www.baeldung.com/spring-response-entity
[45] https://99milestoempty.com/2021/03/22/moving-jwt-from-headers-to-cookies/
[46] https://github.com/facebook/react/issues/17219
[47] https://www.reddit.com/r/reactjs/comments/10lets1/how_to_make_a_component_render_only_after_a/
[48] https://www.dhiwise.com/post/enhancing-user-experience-with-the-loading-component-in-react
[49] https://react.dev/learn/synchronizing-with-effects
[50] https://www.dhiwise.com/post/enhancing-navigation-with-redirects-in-react-route

0개의 댓글