이 글은 이전 포스트에 이어 Next.js의 프론트엔드에서 REST API를 사용하는 방법을 설명합니다.
다음 지식들을 안다면 문제없이 읽을 수 있습니다.
- TypeScript
- Node.js
- React 기초 문법
- Next.js 기초 문법
- Promise
- ES6
- REST API
프론트엔드에서 api
에 접근하기 위해서는 fetch
혹은 axios
를 사용합니다. 두 메소드에 대한 자세한 내용은 좋은 포스트가 있으니 확인해 보시기 바랍니다. 여기서는 axios
를 사용하겠습니다.
npm install axios
혹은 yarn add axios
를 이용해 설치합니다.
axios
는 여러 가지 방법으로 사용할 수 있습니다. axios.(요청을 보낼 메소드 명)
방식으로 사용하겠습니다. 다시 설명하자면, api/users
url에 GET
요청을 보내고 싶다면 다음과 같이 작성하면 됩니다.
axios.get("/api/users");
POST, PUT, DELETE
요청도 동일하게 작성하면 됩니다. 만약 추가 정보가 필요한 경우는 다음과 같이 두 번째 인자에 객체를 주면 됩니다.
axios.post("/api/users", {
headers: { ... },
data: { ... },
});
프론트엔드 코드를 작성하기 전에, 저번 포스트에서 작성한 내용을 바탕으로 /api
폴더의 백엔드 코드를 작성해보려 합니다. 그 전에, 각 요청을 받을때 API
가 어떤 방식으로 동작해야할 지를 정의해 봅시다.
GET
요청을 받는 경우: 모든user
정보를 가게 이름들과 함께 주면 됨POST
요청을 이름과 함께 받는 경우: 새user
를 만듦PUT
요청을id
, 이름과 함께 받는 경우: 해당id
의 유저 이름을 변경DELETE
요청을id
와 함께 받는 경우 : 해당id
의 유저를 삭제
위 네 가지 동작을 수행하는 코드를 작성하는 것은 저번에 배웠지만, 요청에서 id
혹은 이름을 어떻게 가져올까요? 보통 axios
에서는 요청의 body
의 data
에 정보를 담아 보내기 때문에, id를 가져오려면 다음 방법들 중 하나를 사용하면 됩니다.
const id = req.body.data.id;
// With ES6
const {
body: {
data: { id },
},
} = req;
GET
요청같은 경우에는 응답을 프론트엔드에 보내야 합니다. 이 경우에는 prisma client
가 반환한 값을 json
에 실어 보내면 됩니다.
const users = await client.users.findMany({});
res.json({ ok: true, users });
위와 같이 작성하면 프론트엔드에서는 수신한 데이터의 users
속성을 확인해 데이터를 확인할 수 있습니다.
이제 정보를 가져오고 응답을 보내는 방법을 알았으니 API
를 작성하면 됩니다. 저번 포스트에서 설명한 내용이라 별도로 설명하지는 않겠습니다. 이 함수는 handler
함수의 내부를 작성한 것입니다.
if (req.method === "GET") {
const users = await client.users.findMany({
include: {
shops: {
select: {
name: true,
},
},
},
});
res.json({ ok: true, users });
}
if (req.method === "POST") {
const {
body: {
data: { name },
},
} = req;
const createUser = await client.users.create({
data: {
username: name,
},
});
res.json({ ok: true });
}
if (req.method === "PUT") {
const {
body: {
data: { id, name },
},
} = req;
const updateUser = await client.users.update({
where: {
id: +id,
},
data: {
username: name,
},
});
res.json({ ok: true });
}
if (req.method === "DELETE") {
const {
body: { id },
} = req;
const deleteUser = await client.users.delete({
where: {
id: +id,
},
});
}
id
를 사용할때+id
형태로 사용하는 것은, 받은id
가 숫자인지 확실하지 않기 때문에 숫자로 변환시키기 위해 +를 붙여주는 것입니다.axios.delete
함수가body
내의data
부분이 없다는 점 대문에DELETE
메소드일땐id
를 바로body
에서 가져옵니다. (이 부분은 저도 조금 헷갈리네요...)
백엔드에서 어떻게 API
를 다루는지는 끝났습니다. 이제는 프론트엔드에서 API
에 요청을 보내는 코드를 작성해보겠습니다. 그 전에 데이터베이스에서 CRUD
작업이 잘 이루어지는지 확인하기 위해 prisma studio
를 활용하겠습니다.
우선 /pages
폴더에 users.tsx
파일을 다음과 같이 생성해 줍니다.
export default function Users() {
const onPostClick = async () => {};
const onGetClick = async () => {};
const onPutClick = async () => {};
const onDeleteClick = async () => {};
return (
<div className="flex flex-col space-y-8">
<button onClick={onPostClick}>POST</button>
<button onClick={onGetClick}>GET</button>
<button onClick={onPutClick}>PUT</button>
<button onClick={onDeleteClick}>DELETE</button>
</div>
);
}
맨 상위
div
에 작성된"flex flex-col space-y-8"
은 CSS를 적용한 것입니다. 자세한 내용은 tailwindcss 를 참고 바랍니다.
위 코드는 각각 POST, GET, PUT, DELETE
요청을 보내는 버튼들을 모아두었습니다. 각 버튼에 연결된 함수들을 구현해 보겠습니다.
const onPostClick = async () => {
await axios.post("/api/users", {
headers: { "Content-Type": "application/json" },
data: {
name: "Max Demian",
},
});
};
위 코드가 실행되면 /api/users
url로 {name: Max Demain}
데이터와 함께 POST
요청이 갑니다. 따라서 username
에 Max Demian
속성을 가지고 있는 user
가 만들어질 것입니다.
실제로 다음과 같이 데이터가 만들어진 것을 볼 수 있습니다.
GET
요청을 수행하기 전에 방금 만든 user
와 연결되는 shop
두개를 만들어 보겠습니다. prisma studio
로 만들거나 위 create 코드를 응용해 만드시면 됩니다.
const onGetClick = async () => {
const result = await axios.get("/api/users");
console.log(result);
};
위 코드와 같이 현재 GET
요청은 추가적인 정보를 필요로 하지 않습니다. 그리고 axios.get
함수의 반환값을 살펴보면 다음과 같습니다.
여기서 저희가 원하는 부분은 data
부분이므로, ES6
의 도움을 받아 다음과 같이 작성해 원하는 결과를 얻을 수 있습니다.
const { data } = await axios.get("/api/users");
console.log(data);
위와 같이 users
배열을 반환하고, 각 우리가 만든 shops
정보도 user
데이터 안에 있는 것을 확인할 수 있습니다.
const onPutClick = async () => {
await axios.put("/api/users", {
data: {
id: 2,
name: "Max Emil",
},
});
};
PUT
요청은 간단합니다. 프론트엔드에서 id:2, name: "Max Emil"
을 제공하면 위 API
에서 설계한 바와 같이 해당 id
를 가진 user
의 username
이 바뀌게 됩니다.
const onDeleteClick = async () => {
await axios.delete("/api/users", {
data: {
id: 2,
},
});
};
DELETE
요청 역시 PUT
요청과 크게 다르지 않습니다. 해당하는 id
의 user
를 삭제합니다.
데이터가 잘 삭제된 것을 확인할 수 있습니다. 또한 저번 포스트에서 shops
의 onDelete
옵션을 cascade
로 주었기 때문에 user
가 삭제됨에 따라 shop
도 같이 삭제된 것을 확인 가능합니다.
이 포스트에서는 저번에 만든 REST api
를 프론트엔드에서 어떻게 사용하는지에 대해 알아 봤습니다. 원래는 form
을 이용해 직접 데이터를 DB
에 넣고 수정하는 것 까지 하려 그랬는데 너무 복잡해져서 그만뒀습니다. react-hook-form
까지 이용한다면 쉽게 여러 페이지를 만드실 수 있을겁니다.
코드 원본은 여기를 참고해 주시면 됩니다.