inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

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

next-auth로 로그인하기

로그인을 서버액션으로 구현해봤는데 궁금한게 있습니다.

해결된 질문

398

강주호

작성한 질문수 7

0

로그인을 클라이언트 컴포넌트에서 서버액션을 통해 구현해봤는데, 궁금한게 생겨서 질문 드립니다.

로그인 모달의 코드입니다.

 

"use client";

import style from "@/app/(beforelogin)/_component/login.module.css";
import { ChangeEventHandler, FormEventHandler, useState } from "react";
import { redirect, useRouter } from "next/navigation";
import { signIn } from "next-auth/react";
import { useFormState, useFormStatus } from "react-dom";
import onSubmit from "../_lib/signin";
import BackButton from "./BackButton";

function showMessage(messasge: string | null | undefined) {
  if (messasge === "no_id") {
    return "아이디를 입력하세요.";
  }
  if (messasge === "no_password") {
    return "비밀번호를 입력하세요.";
  }
  return "";
}

export default function LoginModal() {
  const [state, formAction] = useFormState(onSubmit, { message: null });
  const { pending } = useFormStatus();

  return (
    <div className={style.modalBackground}>
      <div className={style.modal}>
        <div className={style.modalHeader}>
          <BackButton />
          <div>로그인하세요.</div>
        </div>
        <form action={formAction}>
          <div className={style.modalBody}>
            <div className={style.inputDiv}>
              <label className={style.inputLabel} htmlFor="id">
                아이디
              </label>
              <input
                id="id"
                name="id"
                className={style.input}
                type="text"
                placeholder=""
              />
            </div>
            <div className={style.inputDiv}>
              <label className={style.inputLabel} htmlFor="password">
                비밀번호
              </label>
              <input
                id="password"
                name="password"
                className={style.input}
                type="password"
                placeholder=""
              />
            </div>
          </div>
          <div className={style.message}>{showMessage(state?.message)}</div>
          <div className={style.modalFooter}>
            <button className={style.actionButton} disabled={pending}>
              로그인하기
            </button>
          </div>
        </form>
      </div>
    </div>
  );
}

아래는 signin.ts 의 코드입니다.

"use server";

import { redirect } from "next/navigation";
import { signIn } from "@/auth";

const onSubmit = async (prevState: any, formData: FormData) => {
  if (!formData.get("id") || !(formData.get("id") as string)?.trim()) {
    return { message: "no_id" };
  }
  if (
    !formData.get("password") ||
    !(formData.get("password") as string)?.trim()
  ) {
    return { message: "no_password" };
  }

  let shouldRedirect = false;
  try {
    const response = await signIn("credentials", {
      username: formData.get("id"),
      password: formData.get("password"),
      redirect: false,
    });

    console.log(response.status, "1");
    console.log(response, "2");
    shouldRedirect = true;
  } catch (err) {
    console.error(err);
    return { message: null };
  }

  if (shouldRedirect) {
    redirect("/home"); // try/catch문 안에서 X
  }
};

export default onSubmit;

이렇게 했을 때에, 콘솔이

이렇게 찍힙니다.
1. response가 http://localhost:3000/i/flow/login

이렇게 날라오고, status는 그에 따라 undefined 입니다.

응답이 이렇게 오면 response에 따른 status를 모르는데 에러처리를 어떻게 해야하나요 ??

 

  1. 아래는 회원가입을 똑같이 서버액션으로 구현했을때에,

signup.ts의 코드입니다.

"use server";

import { redirect } from "next/navigation";
import { signIn } from "@/auth";

const onSubmit = async (prevState: any, formData: FormData) => {
  if (!formData.get("id") || !(formData.get("id") as string)?.trim()) {
    return { message: "no_id" };
  }
  if (!formData.get("name") || !(formData.get("name") as string)?.trim()) {
    return { message: "no_name" };
  }
  if (
    !formData.get("password") ||
    !(formData.get("password") as string)?.trim()
  ) {
    return { message: "no_password" };
  }
  if (!formData.get("image")) {
    return { message: "no_image" };
  }
  let shouldRedirect = false;
  try {
    const response = await fetch(
      `${process.env.NEXT_PUBLIC_BASE_URL}/api/users`,
      {
        method: "post",
        body: formData,
        credentials: "include",
      }
    );
    console.log(response.status, "1");
    if (response.status === 403) {
      return { message: "user_exists" };
    }
    console.log(await response.json(), "2");
    console.log(response, "3");
    shouldRedirect = true;
    /*await signIn("credentials", {
      username: formData.get("id"),
      password: formData.get("password"),
      redirect: false,
    });*/
  } catch (err) {
    console.error(err);
    return { message: null };
  }

  if (shouldRedirect) {
    redirect("/home"); // try/catch문 안에서 X
  }
};

export default onSubmit;

이 때에, console.log 의 결과입니다.
response 응답 객체에서 await response.json()을 취했는데, OK로 나오는 이유가 궁금합니다.

 

  1. 로그인 구현에서

    redirect를 false로 하면 client측에서 라우팅하는 것이고, true로 하면 서버쪽에서 리다이렉트 하는 것이라고 알고 있습니다.
    그런데 서버 액션으로 api 호출을 하는 것인데,
    redirect를 false로 하고 아래 redirect를 해주어도 redirect가 되는 것인지 궁금합니다.
    그리고 redirect를 true로 하면
    이렇게 에러가 떠버립니다.
    서버액션으로 리다이렉트 시켜주는 것이라 생각해서 true옵션을 주었는데 에러가 왜 뜨는지 궁금합니다.
    바쁘실텐데 많은 질문 죄송합니다 ㅜㅜ

react next.js react-query next-auth msw

답변 1

0

제로초(조현영)

https://next-auth.js.org/getting-started/client#using-the-redirect-false-option

에러는 response 객체 안에 들어있습니다.

redirect: true 옵션은 NextAuth 설정 시에 적은 주소로 리다이렉트하는 옵션입니다. 저희는 그걸 사용하지 않고 리다이렉트를 수동으로 진행하고 있는 것입니다.

캡처링부분 질문있습니다.

0

74

2

깃에 소스코드를 찾을 수 없습니다.

0

113

2

useInfiniteQuery promise와 react use 사용시 페이지 무한 로딩

0

98

1

import 파일 경로를 찾지 못 해서 에러가 발생합니다.

0

109

2

css 라이브러리 추천 부탁드립니다

0

140

2

팔로우 추천 목록이 빈 배열로 들어옵니다.

0

130

1

게시물 업로드 시 userId가 undefined로 들어가는 오류

0

119

1

useSuspenseQuery 사용 시 SSR 401 이슈 관련

0

172

1

리액트 쿼리 useinfinitequery 무한스크롤 구현 시 페이지가 이동할 경우 데이터가 보존되게 할 수 있나요??

0

184

3

폴링이 필요없는 이유

0

93

2

next Request Memoization과 react cache

0

108

2

seo 최적화 기준은 데이터 fetching인가요 아님 데이터 렌더링인가요?

0

84

2

next.js 서버fetch 에러 fallback ui 구현 방법

0

173

2

프레임워크 여론 파악법

0

125

2

필터옵션이 많은 페이지에서 서버 fetch를 하는게 맞는걸까요??

0

103

2

서버 fetch suspense 로 감싸고 새로고침 시 잠시 빈 화면이 노출된 후 fallback ui가 노출됩니다.

0

102

2

template.tsx 내 서버fetch 응답값과 클라이언트 컴포넌트 상태값 싱크가 맞지 않는 이슈

0

66

2

Auth.js 사용 시 authorize 함수가 호출되지 않습니다

0

131

2

next.js 에서 로그인에 관하여

0

138

1

Next의 route handler에 대한 질문이 있습니다.

0

101

2

게시판 리스트 만들때 use client를 어디서부터 집어넣어야할지 모르겠습니다

0

98

2

프라이빗 폴더를 해야 하는 이유가 모호한 것 같아요.

0

85

2

vanilla-extract 못찾는 문제

0

230

2

fetch 캐싱과 revalidate 관련

0

84

2