728x90
서버 API 구현
프로젝트 구조 생성
app 폴더 내에 api 폴더를 생성하고 path로 사용할 폴더를 하나 생성한 다음 route.ts 파일을 생성한다.
프로젝트의 구조는 다음과 같다.
route.ts
1. 함수 생성 및 Method 지정
먼저 호출할 함수의 HTTP Method의 이름으로 함수를 생성해준다.
필자는 POST로 테스트를 진행하기 위해서 POST로 작성해줬다.
export async function POST() {}
만약 POST Method가 아닌 다른 Method로 호출하게 되면 405 에러가 발생하게 된다.
2. Request 객체 사용하기
API 호출 시 NextRequest 타입의 객체에 사용자가 보낸 json 데이터를 받아와서 사용할 수 있다.
사용자가 입력한 id와 password 값을 받아오기 위해서 매개변수에 NextRequest 타입의 객체를 생성해주면 된다.
받아온 객체는 json() 함수를 사용해 json 객체로 파싱한 후 변수 안에 넣어준다.
변수에 저장된 json의 key 값으로 value를 가져와서 사용할 수 있다.
import { NextRequest } from "next/server";
export async function POST( req: NextRequest ) {
const body = await req.json();
const { id, password } = body;
if (id === "123" && password === "123") {
...
} else {
...
}
}
3. 사용자의 요청에 응답 주기
사용자가 요청한 API에 응답을 주기 위해서 NextResponse 객체를 리턴해준다.
사용자 응답을 json 객체를 생성한 후 아래의 코드처럼 리턴해주면 된다.
import { NextRequest, NextResponse } from "next/server";
interface LoginResponseProps {
code: string;
msg: string;
name?: string;
}
export async function POST( req: NextRequest ) {
const body = await req.json();
const { id, password } = body;
let json: LoginResponseProps = { code: "", msg: "", name: "" };
if (id === "123" && password === "123") {
json = { code: "00", msg: "정상", name: "신대범" };
} else {
json = { code: "23", msg: "아이디 또는 비밀번호가 다릅니다" };
}
return new NextResponse(JSON.stringify(json));
}
클라이언트 구현
다음으로 서버 API를 호출하기 위한 클라이언트를 구현한다.
fetch 함수를 사용해서 로그인 기능을 구현한 후 로그인 성공 시 home 화면으로 이동하는 함수를 아래와 같이 작성했다.
"use client";
import { useCallback, useRef, useState } from "react";
import { useRouter } from "next/navigation";
interface LoginProps {
id: string;
password: string;
}
const defaultLoginInfo: LoginProps = {
id: "",
password: "",
};
const Login = () => {
const [ userInfo, setUserInfo ] = useState(defaultLoginInfo);
const idRef = useRef<HTMLInputElement>(null);
const passwordRef = useRef<HTMLInputElement>(null);
const router = useRouter();
const onClickLogin = useCallback(async () => {
try {
if (!userInfo.id) {
idRef.current.focus();
return alert("아이디를 입력해 주세요");
}
if (!userInfo.password) {
passwordRef.current.focus();
return alert("비밀번호를 입력해 주세요");
}
const res = await fetch(
"/api/login",
{
method: "POST",
body: JSON.stringify({
id: userInfo.id,
password: userInfo.password,
}),
}
);
if (res.status === 200) {
const data = await res.json();
if (data.code === "23") {
return alert("아이디 또는 비밀번호가 다릅니다");
}
router.push("/home");
return alert(`${data.name}님, 환영합니다 🎉`);
}
} catch (err) {
console.error(err);
}
}, [userInfo]);
return (
<div>
<input
ref={idRef}
type="text"
value={userInfo.id}
onChange={(e) => setUserInfo({ ...userInfo, id: e.target.value })}
placeholder="아이디"
/>
<input
ref={passwordRef}
type="text"
value={userInfo.password}
onChange={(e) => setUserInfo({ ...userInfo, password: e.target.value })}
placeholder="비밀번호"
/>
<button onClick={onClickLogin}>로그인</button>
</div>
);
};
export default Login;
728x90
'🖥️Frontend > Next' 카테고리의 다른 글
[Next] 데이터 베이스 연결하기 (feat. MySQL) (0) | 2025.04.28 |
---|---|
[Next] Next에서 라우팅 구현하기 (0) | 2024.08.21 |
[Next] 프로젝트 수동 설치하기 (0) | 2024.08.20 |
댓글