NextJS 독학 3차시

Donghyun Hwang·2024년 1월 12일

NextJS 독학

목록 보기
4/6
post-thumbnail

수강중인 강의 : 코딩애플 NextJS

가보자


새로 알게 된 내용은 몇 없었다(MongoDB 업데이트, 수정 등).
알던 지식을 다시 정리해보자.

✅ MongoDB 데이터 수정, 삭제

클라이언트 페이지는 다음과 같이 만들었다.

// edit/[id]/page.tsx
import { connectDB } from '@/util/db';
import { ObjectId } from 'mongodb';
import React from 'react';

const Edit = async (props: any) => {
  const db = (await connectDB).db("board");
  let result = await db.collection("post").findOne({ _id: new ObjectId(props.params.id) });

  if (!result) {
    alert('잘못된 접근입니다.');
    window.location.href = '/list';
    return;
  }
  return (
    <div className>
      <h4>수정 페이지</h4>
      <form action="/api/post/edit" method="POST">
        <label htmlFor="title">제목</label>
        <input type="hidden" name="id" value={props.params.id} />
		// id를 전송하기 위한 input, 유저에게 보여서는 안됨
        <textarea name='title' defaultValue={result.title}></textarea>
        <label htmlFor="content">내용</label>
        <textarea name='content' defaultValue={result.content}></textarea>
        <button type="submit">수정</button>
      </form>

    </div>
  );
};

export default Edit;

여기서 눈여겨 볼 점은 글의 id를 담기 위한 input을 하나 더 만들어준다는 것이다. id 정보를 가지고 있어야 DB에서 올바르게 데이터를 수정할 수 있다.
<input type="hidden"> 또는 style={{display:'none'}}을 통해 사용자에게 보이지 않도록 주의하자.

다음은 서버 페이지다.

// pages/api/post/edit.tsx
import { connectDB } from "@/util/db";
import { ObjectId } from "mongodb";
import { NextApiRequest, NextApiResponse } from "next";

const edit = async (request: NextApiRequest, response: NextApiResponse) => {
  if (request.method == "POST"){
  const db = (await connectDB).db("board");

  let result = await db.collection("post").updateOne(
    {
      _id: new ObjectId(request.body.id),
    },
    {
      $set: {
        title: request.body.title,
        content: request.body.content,
      },
    },
    { writeConcern: { w: "majority" } }
  );

  response.status(302).redirect("/list");
  } else {
    response.status(400).json("잘못된 접근입니다.");
  }

};

export default edit;

MongoDB에서 하나의 데이터를 수정할 때는 updateOne() 메소드를 사용한다.

기본 형식은 다음과 같다.

db.collection("테이블 이름").updateOne(
    {
      // 업데이트 시에 데이터를 식별할 값
    },
    {
      $set: {
        // 수정할 값과 내용
      },
    });

$set뿐만 아니라 $inc를 통해 값의 변경이 아닌 증가/감소 처리 또한 가능하다.

삭제 또한 비슷한 형식인데, 클라이언트에서 삭제 버튼을 누를 시, /api/post/delete로 글의 id를 담아 DELETE 요청을 보낸다고 가정해보자.

이 때 서버에서는 다음과 deleteOne 메소드를 통해 처리한다.

// api/post/delete.tsx
const Delete = async (request: NextApiRequest, response: NextApiResponse) => {
  if (request.method == "DELETE"){
  const db = (await connectDB).db("board");

  let result = await db.collection("post").deleteOne(
    {
      _id: new ObjectId(request.body.id),
    }
  );

  response.status(302).redirect("/list");
  } else {
    response.status(400).json("잘못된 접근입니다.");
  }

};

export default Delete;

수정할 값을 담았던 updateOne과 달리, 데이터를 식별할 수 있는 값을 담아 보내면 데이터 삭제가 이루어진다.

✅ Client 컴포넌트에서의 데이터 접근

1. props를 통한 접근

클라이언트 컴포넌트가 서버 컴포넌트의 자식 요소로 존재할 때, 데이터 접근은 서버 컴포넌트에서 처리한 뒤, 클라이언트 컴포넌트에 props로 이를 넘겨주는 방식이다.

// 서버 컴포넌트
import { connectDB } from "@/util/db";
import Link from "next/link";
import ListItem from "./ListItem";

export default async function List() {

  const db = (await connectDB).db('board');
  let result = await db.collection('post').find().toArray();

  return (
    <div className="list-bg">
      <ListItem result={result} />
 	  // 클라이언트 컴포넌트 ListItem에 result를 넘겨줌
    </div>
  )
}
// ListItem.tsx, 클라이언트 컴포넌트
"use client";

const ListItem = (props: any) => {

  const result = props.result;
  return (
    <div>
      {result.map(
      // ... 
      )}
	</div>
  );
};

2. useEffect를 통한 접근

"use client";

import { useEffect } from "react";

const ListItem = () => {

  useEffect(() => {
    // 서버에 부탁해서 DB 게시물 가져오는 코드 작성
    // result에 저장
  }, []);

  return (
    // ...
  );
};

export default ListItem;

유의할 점은 DB에 직접 접근하는 것이 아닌, 서버에게 DB 데이터를 달라는 요청을 보낸다는 점이다. 클라이언트 컴포넌트는 클라이언트에게 노출되기 때문에, DB 접근과 같은 민감한 행위들은 금지된다.
더 궁금하다면 NextJS 독학 2차시를 참고해보자.

3. 각 방식의 장단점

props를 통한 접근은 SEO에 더욱 유리하다.
useEffect가 호출되는 시점은 html이 모두 렌더링된 이후이기 때문에, 검색 엔진 봇에게 제대로 된 결과를 제공할 수 없다.

그러나 컴포넌트 구조가 복잡해질수록, props를 통해 데이터를 주고 받는 것은 Props Drilling과 같은 문제를 낳을 수 있다.

💎느낀 점

NextJS에서는 Redux와 같은 전역 상태 관리 툴이 따로 존재하는지 궁금해졌다.
또한 백엔드 지식이 없다시피 하다보니 더 상세한 서버의 데이터, 예외 처리 등에 대해 알아봐야겠다고 생각했다.

profile
앞만 보고 가

0개의 댓글