인프런 커뮤니티 질문&답변

일어나서코딩해야지님의 프로필 이미지
일어나서코딩해야지

작성한 질문수

Next + React Query로 SNS 서비스 만들기

로그아웃 & 로그인 여부에 따라 화면 다르게 하기

로그인을 할 시에 useSession에서 me data를 받아오지를 못하는 것 같습니다

해결된 질문

작성

·

528

0

관련된 질문이 있나 찾아보고 혼자 코드 비교해보며 고군분투했지만 이유를 알 수가 없어 질문을 남깁니다!

 

질문

(afterLogin) > _component > LogoutButton.tsx 파일에서 useSession() 훅을 통하여 받아오는 data가 없어
if(!me?.user) 문에서 return 처리가 되어 로그아웃 버튼이 렌더링 되지 않습니다 -> 로그인이 제대로 되지 않는 것 같습니다

 

관련되서 추적을 해보니 터미널 창에 아래와 같은 에러가 뜹니다

스크린샷 2024-02-15 오후 11.20.46.png

네트워크 탭에서 session의 경우 response가 null로 넘어옵니다

스크린샷 2024-02-15 오후 11.20.20.png

application의 cookie또한 담기지 않습니다

스크린샷 2024-02-15 오후 11.21.28.png

 

아래는 관련된 파일들의 코드입니다..

 

mocks > handlers.ts

스크린샷 2024-02-15 오후 11.24.37.png

auth.ts

스크린샷 2024-02-15 오후 11.24.26.png

middleware.ts

스크린샷 2024-02-15 오후 11.24.48.png

[...nextauth] > route.ts

스크린샷 2024-02-15 오후 11.24.56.png

package.json

스크린샷 2024-02-15 오후 11.26.21.png

 

혹시나 다른분들도 저 같은 경우가 있으신 분들은 답변 한번 부탁드리겠습니다

 

답변 3

2

제로초(조현영)님의 프로필 이미지
제로초(조현영)
지식공유자

이건 로그인부터 다시 보셔야 합니다. 로그인 시 응답 헤더에 Set-Cookie 있나요?

네 위에 이미지 올려드린 것 처럼

응답헤더에 Set-Cookie 넣어놓고 있습니다!

 

스크린샷 2024-02-15 오후 11.56.04.png

제로초(조현영)님의 프로필 이미지
제로초(조현영)
지식공유자

아뇨 여기 말고 signin 함수 호출할 때의 네트워크탭을 봐야합니다. 거기가 프론트 next-auth.session-token 쿠키 넣는 곳입니다. 그게 없어서 로그인 유지가 안 되는 겁니다.

제로초(조현영)님의 프로필 이미지
제로초(조현영)
지식공유자

http.post('/api/login' 안에서는 console.log찍어서 로그인 시 출력되는지 확인해보시고, authorize 함수에서는 process.env.AUTH_URL 콘솔로그 찍어보세요.

/api/login 안에 console.log 찍을시에 정상출력되구요
authorize 함수에서 process url 경로 정상적으로 나옵니다

 

방금 이것저것 수정하다가 해결한 것 같아요

근데 해결하게 된 원인이 user 데이터에 nickname을 한글로 할 경우 next-auth.session-token 쿠키가 안쌓입니다..

하지만 영어로 할 경우는 쌓이네요 ..

스크린샷 2024-02-16 오전 12.40.24.png

 

0

제로초(조현영)님의 프로필 이미지
제로초(조현영)
지식공유자

npm i @auth/core@0.27 next-auth@5.0.0-beta.11 msw@2.1
이렇게 설치하고 .env에서 AUTH_URL을 지웁니다. 그리고 auth.ts에서 NEXT_PUBLIC_BASE_URL을 대신 씁니다. .env에 AUTH_URL을 쓰지 않는 게 핵심입니다.

const authResponse = await fetch(`${process.env.NEXT_PUBLIC_BASE_URL}/api/login`, {

아직 msw@2.2의 버그는 해결하지 못했습니다.
https://github.com/mswjs/msw/issues/1658#issuecomment-1953599080
이런 식으로 버그 제기를 하고는 있으나 언제 고쳐질 지는 모르겠습니다. 해결되는대로 다시 공유드리겠습니다.

0

npm run mock 안하신거 같은데요?

답변 감사합니다 npm run mock 되어 있는 상태입니다

스크린샷 2024-02-15 오후 11.38.22.png

혹시 User[0] 데이터랑 signIn 호출하는 곳 import 는 뭐로 되어있나요?
session null 로 되는거 얼마전에 많이 경험했었는데 ,, 기억이 잘 안나네요

AUTH_URL이랑 auth.ts 부분도 전체 코드 올려주시면 좋을 것 같아요

답변 감사합니다 대원님

auth.ts 파일 전체 코드입니다

//==============================

import NextAuth from 'next-auth';
import CredentialsProvider from 'next-auth/providers/credentials';
import KakaoProvider from 'next-auth/providers/kakao';

export const {
  handlers: { GET, POST } /** API 라우트 */,
  auth /** 내가 로그인을 했는지 안했는지 알아내는 함수 */,
  signIn /** 로그인하는 함수 */,
} = NextAuth({
  pages: {
    //회원가입과 로그인시에 어떤 페이지 경로인지 삽입
    signIn: '/i/flow/login',
    newUser: '/i/flow/signup',
  },
  providers: [
    CredentialsProvider({
      async authorize(credentials) {
        //로그인 수행할때에 아래 부분 호출
        const authResponse = await fetch(`${process.env.AUTH_URL}/api/login`, {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
          },
          body: JSON.stringify({
            id: credentials.username,
            password: credentials.password,
          }),
        });

        if (!authResponse.ok) {
          return null;
        }

        const user = await authResponse.json();

        return {
          id: user.id,
          name: user.nickname,
          image: user.image,
          ...user,
        };
      },
    }),
    // KakaoProvider({...})
  ],
});

//==============================

 

handlers.ts User[0] 넣는 곳 입니다

import { http, HttpResponse } from 'msw';
import ECOM from '/public/images/ecom.png';

const User = [
  {
    userId: 1,
    nickname: 'eden',
    id: 'eden',
    image: '/public/images/ecom.png',
  },
];

export const handlers = [
  http.post('/api/login', () => {
    return HttpResponse.json(User[0], {
      headers: {
        'Set-Cookie': 'connect.sid=msw-cookie;HttpOnly;Path=/',
      },
    });
  }),
  http.post('/api/logout', () => {
    return new HttpResponse(null, {
      headers: {
        'Set-Cookie': 'connect.sid=;HttpOnly;Path=/;Max-Age=0',
      },
    });
  }),
  http.post('/api/users', async ({ request }) => {
    console.log('회원가입');
    // return HttpResponse.text(JSON.stringify('user_exists'), {
    //   status: 403,
    // })
    return HttpResponse.text(JSON.stringify('ok'), {
      headers: {
        'Set-Cookie': 'connect.sid=msw-cookie;HttpOnly;Path=/;Max-Age=0',
      },
    });
  }),
];

 

signIn 호출하는 곳은 글 내용에 코드 캡쳐있습니다

클라이언트 컴포넌트라 next-auth/react 로 import 했습니다

authReponse 콘솔찍으면 { userId: 1, nickname: 'eden', id: 'eden', image: '/public/images/ecom.png', },

잘 들어가 있나요? signIn 호출하는 곳도 보여주세요! 글 내용에 없습니당

signIn 호출하는 LoginModal.tsx 파일 코드입니다

 

'use client';

import style from '@/app/(beforeLogin)/_component/login.module.css';
import { ChangeEventHandler, FormEventHandler, useState } from 'react';
import { useRouter } from 'next/navigation';
import { signIn } from 'next-auth/react';

export default function LoginModal() {
  const [id, setId] = useState('');
  const [password, setPassword] = useState('');
  const [message, setMessage] = useState('');
  const router = useRouter();

  const onSubmit: FormEventHandler<HTMLFormElement> = async (e) => {
    e.preventDefault();
    setMessage('');
    try {
      await signIn('credentials', {
        username: id,
        password,
        redirect: false,
      });
      router.replace('/home');
    } catch (err) {
      setMessage('아이디와 비밀번호가 일치하지 않습니다.');
    }
  };
  const onClickClose = () => {
    router.back();
  };

  const onChangeId: ChangeEventHandler<HTMLInputElement> = (e) => {
    setId(e.target.value);
  };

  const onChangePassword: ChangeEventHandler<HTMLInputElement> = (e) => {
    setPassword(e.target.value);
  };

  return (
    <div className={style.modalBackground}>
      <div className={style.modal}>
        <div className={style.modalHeader}>
          <button className={style.closeButton} onClick={onClickClose}>
            <svg
              width={24}
              viewBox="0 0 24 24"
              aria-hidden="true"
              className="r-18jsvk2 r-4qtqp9 r-yyyyoo r-z80fyv r-dnmrzs r-bnwqim r-1plcrui r-lrvibr r-19wmn03"
            >
              <g>
                <path d="M10.59 12L4.54 5.96l1.42-1.42L12 10.59l6.04-6.05 1.42 1.42L13.41 12l6.05 6.04-1.42 1.42L12 13.41l-6.04 6.05-1.42-1.42L10.59 12z"></path>
              </g>
            </svg>
          </button>
          <div>로그인하세요.</div>
        </div>
        <form onSubmit={onSubmit}>
          <div className={style.modalBody}>
            <div className={style.inputDiv}>
              <label className={style.inputLabel} htmlFor="id">
                아이디
              </label>
              <input id="id" className={style.input} value={id} onChange={onChangeId} type="text" placeholder="" />
            </div>
            <div className={style.inputDiv}>
              <label className={style.inputLabel} htmlFor="password">
                비밀번호
              </label>
              <input
                id="password"
                className={style.input}
                value={password}
                onChange={onChangePassword}
                type="password"
                placeholder=""
              />
            </div>
          </div>
          <div className={style.message}>{message}</div>
          <div className={style.modalFooter}>
            <button className={style.actionButton} disabled={!id && !password}>
              로그인하기
            </button>
          </div>
        </form>
      </div>
    </div>
  );
}

 

authReponse 콘솔 찍으면 데이터가 user의 데이터가 안담겨있습니다,, ㅎㅎ

대원님 답변 감사했습니다

해결했어요

User 데이터에 한글을 넣어 handler.ts에 있는 HttpResponse 에 들어가면 원인은 모르지만 로그인이 정상적으로 쿠키가 생성이 되지 않더라구요...
위에 제로초님에게도 답변은 따로 드렸으나 찾아봐도 정확한 원인은 모르겠네요,, 감사했습니다

일어나서코딩해야지님의 프로필 이미지
일어나서코딩해야지

작성한 질문수

질문하기