Next.js 는 ServerSide 에서 사용 가능한 Code 를 제공한다.
클라이언트 측에서는 할 수 없는 DB 와 소통하는 코드가 아주 대표적이다.
서버측코드는 일반 클라이언트측 자바스크립트 코드와는 다르게 유저들에게 노출되어있지 않다.
기본적으로 유저들에게 숨겨져있으며 따로 볼 수 없다.
사전 데이터 페칭을 제공하는
getStaticProps 나 getServerSideProps 를 통해, 코드 내에서 직접적으로 서버측 코드를 사용 할 수 있고,
pages 의 api 폴더 내에, 자신이 직접 서버측 코드를 만들어 클라이언트측에서 fetch 를 통해 서버에 요청 할 수도 있다.
기본적으로 REST API 를 하기 위해, 독립적으로 node(서버) 와 react(클라이언트) 를 운영하지만
Nextjs 는 이 모든걸 한방에! CORS Error 를 처리할 필요도 없이 사용가능하다!
그렇다면 전에 만든 DB 에서 값을 가져와보자.
0. mongodb 를 사용하기 위해 mongodb 를 설치한다.
https://www.npmjs.com/package/mongodb
1. helper 함수로 만든 DB 에 접근하자.
< src / helper / sample.ts >
import { MongoClient } from "mongodb";
export const client = new MongoClient(String(process.env.MONGODB_URL));
export const getSample = async (client: MongoClient) => {
const dbName = "personality-and-dog";
const collectionName = "user-personality-result";
const result = await client
.db(dbName)
.collection(collectionName)
.find({})
.toArray();
return result;
};
client 의 Type 을 정해주고, DB 에서 만든 DB Name 과 collection 을 가져온다.
mongodb 는 데이터를 가져올때 find({조건}) 를 사용하거나, findOne({조건}) 을 사용하여 data 를 get 할 수 있다.
2. [ 방법 1 ] getStaticProps (or getServerSideProps ) 를 통해 바로 가져오기
< pages / index.tsx >
import Head from "next/head";
import Link from "next/link";
import { getSample, client } from "../helper/sample";
import { useEffect } from "react";
export default function Home(props: { responseData: { _id: string; message: string }}) {
const { responseData } = props;
console.log(responseData);
return (
...
)
}
export async function getStaticProps() {
const response = await getSample(client);
const responseData = JSON.stringify(response);
return {
props: { responseData },
};
}
서버측 코드인 getStaticProps 를 통해, api 를 통하지 않고 직접 DB의 값에 접근하여 가져왔다.
데이터 교환은 json 데이터 교환으로 이루어지므로, JSON.stringify 를 통해 javascript Code 로 parsing 해준다.
3. [ 방법 2 ] api 를 통해 가져오기 - api 의 정의
next.js 를 사용하는 가장 큰 장점 여러가지중 하나이다.
서버측 코드를 직접 만들어서, REST API 를 구현가능하다는 것.
위치는 pages / api / 안에 서버 코드를 만들어준다.
< pages / api / getSample.ts >
import { getSample, client } from "../../helper/sample";
import type { NextApiRequest, NextApiResponse } from "next";
const sampleHandler = async (req: NextApiRequest, res: NextApiResponse) => {
if (req.method === "GET") {
const response = await getSample(client);
res.status(200).json(response);
}
};
export default sampleHandler;
next.js 의 official DOCS 를 보면 req 와 res 에 대한 Type 이 정의되어 있다. 가져오도록 하자.
https://nextjs.org/docs/api-routes/response-helpers
req.method 를 통해 어떤 요청이 들어왔는지 확인하고,
helper 에서 정의한 DB 에서의 값을 가져오는 함수를 호출하고
res 를 통해, status 코드를 만들어 json 데이터로 응답하도록 만든다.
3. [ 방법 2 ]api 를 통해 가져오기 - 클라이언트에서 서버로 요청(fetch)
< pages / index.tsx >
import Head from "next/head";
import Link from "next/link";
import { useEffect } from "react";
export default function Home() {
useEffect(() => {
const getSampleData = async (): Promise<void> => {
const result = await fetch("/api/getSample");
const resultData = await result.json();
console.log(resultData);
};
getSampleData();
}, []);
return (
...
);
}
fetch 를 통해 만든 api (서버) 로 값을 req(요청)한다.
fetch 는 기본적으로 req.method 가 GET 이기 때문에 조건에 부합할 것이다.
req.method 가 GET 인 요청에 서버(API) 에 전달되면 API 는 response 로 JSON Data 를 응답(res) 할 것이고
응답된 데이터는 result 에 들어갈 것이다.
해당 값을 json() 을 통해 자바스크립트 코드로 parsing 하고 log 하는 비동기 함수를 만들고 바로 사용한다.
useEffect(() => {
(async (): Promise<void> => {
const result = await fetch("/api/getSample");
const resultData = await result.json();
console.log(resultData);
})();
}, []);
이렇게 즉시 실행 함수로 사용해도 괜찮다. 잘 작동한다.
그래서 DB의 값을 가져오기 위해 어떤 것을 사용해야 하는가
지금 생각하기에는
getStaticProps 의 경우 사전 데이터 페칭을 통해 HTML 을 생성할때 필요한 데이터를 미리 정의한다는 것에 초점을 둔다.
데이터를 미리 정의하면 SEO 에 굉장히 유리하다. HTML 을 생성할때 이미 그 데이터가 들어가있기 때문이다.
props 로 가져온 데이터는 공개적으로 캐시(저장) 되므로 민감한 정보는 getStaticProps 로 가져오지 않는 것이 타당하다.
getStaticProps 는 여러가지 옵션을 통해, 조작이 가능하다.
서버측 코드를 이용하는 REST API 의 장점을 생각해본다면
유니폼 인터페이스를 가지고 있어 어느 기기, 어느 환경 에서도 HTTP 표준을 따른다면 데이터의 교환을 할 수 있다.
또한 Validation 은 기본적으로 서버측에서 담당하는 것이다.
클라이언트 측에서 아무리 열심히 Validation 을 한다고 한들 서버에서 보내줄때 하는 것 만 못하다.
가령 일반적인 Validation 이나
if (req.body.name === "" ||
!req.body.email.includes("@")
){
throw new Error(...)}
heper 함수로 복잡한 Validation 을 따로 정의하여 조건에 맞지 않는다면 다른 res 를 주고 error를 발생시킨다거나
if (signupValidation(email, password, name)) {
res.status(400).json({ message: "정보를 다시 확인해주세요" });
throw new Error("정보를 다시 확인해주세요");
}
서로 다른 method 에 따라 다른 res 를 준다던가
if(req.method === "GET"){
...
res.status(200).json({...})
}
if(req.method === "POST"){
...
res.status(200).json({...})
}
이런 것들을 사용하기 위해, 중요하거나 사전데이터페칭이 필요 없는 데이터들은
api 를 사용해 직접 정의한 서버로부터 값을 받는 것이 더 낫다는 생각을 한다.
추가적으로
API 를 이용하여야 DB에 값을 CRUD 할 수 있다.
그냥 api 에 더 익숙해지는 것이 낫지 않을까 생각한다.
결론
사전 데이터페칭이 필요하다면 (SEO 를 위해) getStaticProps 를 사용하자.
숨겨야 하는 정보나, 민감한 정보들은 공개적으로 캐시되는 getStaticProps 를 사용하면 안된다.
따로, 그것들이 필요하지 않는 한 api 를 이용하여 값을 가져오자.
어차피 값을 가져오는 것 이외에 DB 에 CRUD 를 하기 위해서는 api 를 이용해야 하니까 말이다.
더 찾아보고 더 생각해보고 나중에 이 글도 수정해야겠다.
'메인-프로젝트 > Next.js - 심리검사와 강아지 프로젝트' 카테고리의 다른 글
5. POST 를 이용한 데이터 가져오기, 로컬스토리지에 저장하기 (0) | 2023.02.03 |
---|---|
4. Redux-toolkit을 사용해 "비동기함수(fetch)" 를 이용한 DB 의 값 받아와서 넣기 + Thunk 생성자 + action.ts (0) | 2023.01.29 |
2. MongoDB 연결과 API 를 통한 fetch(1) - MongoDB 연결 (0) | 2023.01.28 |
1. Google OAuth 구현하기 [TypeScript + Next.js + Next-auth] (1) | 2023.01.27 |
0. 프로젝트를 시작해보자! (0) | 2023.01.27 |
댓글