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

강주호님의 프로필 이미지

작성한 질문수

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

서버 컴포넌트에서 Server Actions 사용하기

서버 컴포넌트에서 server action 사용 질문이 있습니다.

해결된 질문

24.05.04 14:13 작성

·

295

0

서버 컴포넌트에서 server actions 사용 중 네트워크 탭에서 응답이 안담기는 문제가 있어서 질문 드립니다.

강의에 나와있는대로 코드를 따라했는데 뭐가 문제인지 잘 모르겠습니다.


아래는 signupModal의 코드입니다.

import style from "./signup.module.css";
import onSubmit from "../_lib/signup";
import BackButton from "@/app/(beforelogin)/_component/BackButton";
import { useFormState, useFormStatus } from "react-dom";
import { redirect } from "next/navigation";

function showMessage(messasge: string | null | undefined) {
  if (messasge === "no_id") {
    return "아이디를 입력하세요.";
  }
  if (messasge === "no_name") {
    return "닉네임을 입력하세요.";
  }
  if (messasge === "no_password") {
    return "비밀번호를 입력하세요.";
  }
  if (messasge === "no_image") {
    return "이미지를 업로드하세요.";
  }
  if (messasge === "user_exists") {
    return "이미 사용 중인 아이디입니다.";
  }
  return "";
}

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

  const formAction = async (formData: any) => {
    "use server";

    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);
      console.log(await response.json(), "abc");
      if (response.status === 403) {
        console.log("???");
        return { message: "user_exists" };
      }
      shouldRedirect = true;
    } catch (err) {
      console.log(err);
    }
    if (shouldRedirect) {
      redirect("/home"); // try/catch문 안에서 X
    }
  };

  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=""
                  required
                />
              </div>
              <div className={style.inputDiv}>
                <label className={style.inputLabel} htmlFor="name">
                  닉네임
                </label>
                <input
                  id="name"
                  name="name"
                  className={style.input}
                  type="text"
                  placeholder=""
                  required
                />
              </div>
              <div className={style.inputDiv}>
                <label className={style.inputLabel} htmlFor="password">
                  비밀번호
                </label>
                <input
                  id="password"
                  name="password"
                  className={style.input}
                  type="password"
                  placeholder=""
                  required
                />
              </div>
              <div className={style.inputDiv}>
                <label className={style.inputLabel} htmlFor="image">
                  프로필
                </label>
                <input
                  id="image"
                  name="image"
                  required
                  className={style.input}
                  type="file"
                  accept="image/*"
                />
              </div>
            </div>
            <div className={style.modalFooter}>
              <button type="submit" className={style.actionButton}>
                가입하기
              </button>
            </div>
          </form>
        </div>
      </div>
    </>
  );
}

아래는 핸들러 세팅입니다.

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",
    //   },
    // });
  }),

여기서 회원가입을 누를시에

console.log() 처리한 부분은 잘 찍히고

서버쪽에서 찍은 회원가입 콘솔도 잘 찍히는 모습입니다.

네트워크탭에서 페이로드는 잘 담겼는데, 응답이 없습니다.

회원가입 누를 때 콘솔이 찍히는 것으로 보아서 포트도 9090으로 제대로 열려있고, 403응답이 오는 것으로 보아 핸들러 쪽은 제대로 작동하는 것 같습니다.

그리고 서버액션 쪽 콘솔 "???"가 찍히는 것으로 보아서 status도 403으로 잘 오는 것 같은데 리턴 메시지가 제대로 안되는 것인지 응답이 왜 없는 것인지 궁금합니다.

 

 

답변 1

0

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

2024. 05. 04. 14:59

서버액션은 원래 응답이 안 뜹니다. msw 서버에 대한 응답은 넥스트 서버가 대신 받았습니다.

강주호님의 프로필 이미지
강주호
질문자

2024. 05. 04. 15:34

제로초님 답변 감사합니다.

또 궁금한게 있습니다.

강의에서는 응답 messge가 있는데, 이것은 무슨 차이인가요 ??
그리고, 저 또한 응답에 message가 담겼다가 안담겼다가 하는데 담겼을 때 안담겼을 때 차이를 모르겠습니다.
응답에 message가 담겼다가, 바로 똑같은 요청을 보내니 응답이 없게 날라옵니다.
(동작은 동일하게 되어 문제는 없습니다. 그냥 차이가 무엇인지 궁금해서 여쭈어봅니다.)
넥스트에서 응답이 캐싱이 되는 것(?)

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

2024. 05. 05. 13:53

응답이 담겨있고 안 담겨있고는 전부 Next가 자체적으로 처리하기 위해서 편의상 넣거나 안 넣는 것입니다. 서버액션은 넥스트가 전적으로 컨트롤하는 것이라서요. 예를 들어 어디로 리다이렉트하라, 에러메시지가 이것이다 등등의 정보가 담겨있을 수 있는데 저희가 접근할 수는 없습니다.