본문 바로가기
> 코딩애플 (부분공개)/Next.js로 웹서비스 만들기

수정기능 만들기 1

by 자몽주스 2024. 11. 8.
728x90

글 수정기능은 어떻게 만들죠?

직접 글 수정기능이 어떻게 동작하는지 자세히 한글로 정의하고

그거 그대로 코드로 옮기면 된다고 했습니다. 그럼 혼자서도 코딩가능

그 기능이 어떻게 동작하는지 모르면 언제나 유사한 다른 사이트 참고하면 됩니다. 

다른 사이트 게시판들은  

1. 글마다 있는 수정버튼누르면 수정페이지로 이동함 (수정페이지 URL도 정해야할듯)

2. 수정페이지는 글작성페이지랑 비슷하게 생겼는데 기존 글을 DB에서 불러와서 넣어줘야함 

3. 전송버튼 누르면 DB에 있던 document를 작성내용으로 수정하면 됩니다.

근데 유저가 DB 데이터를 직접 수정하면 큰일나니 서버에 수정을 부탁하는 식으로 코드짭시다. 

이거 그대로 코드로 옮기면 되겠군요. 

다 배운거라 MongoDB 안에 있는 데이터 수정하는 법만 찾아보면 알아서 해볼 수 있을 것 같은데

자신있으면 강의 보기 전에 직접 구현해봅시다. 

겁쟁이들은 저랑 같이 1번 2번이나 해봅시다. 


1. 수정페이지로 이동하는 버튼만들기

 

 

수정버튼은 /list 목록페이지의 글제목마다 넣는게 좋겠군요. 

 

그리고 이거 누르면 이동할 글 수정페이지 URL은 어떻게 만들까요?

우선, list/page.js 로 들어가기.

import { connectDB } from "@/util/database";
import Link from "next/link";

export default async function List() {
  const db = (await connectDB).db("forum");
  let result = await db.collection("post").find().toArray();
  console.log(result);

  return (
    <div className="list-bg">
      {result.map((a, i) => {
        return (
          <div className="list-item" key={i}>
            <Link href={"/detail/" + result[i]._id}>
              <h4>{a.title}</h4>
            </Link>

            <p>1월 1일</p>
          </div>
        );
      })}
    </div>
  );
}

저기다가 Link를 하나 더 생성해보기. 

수정링크인데 글씨만 쓰기보단 이모지를 써서 만들어줌. 

href 를 써서 경로 적어주기. 

 

저거 누르면 이동할 URL 도 알아서 생성해주기

(폴더 생성해주면 될듯)

링크를 생성하면 저런 식으로 언더바 (밑줄) 이 생기는 경우가 있음.

= css 로 꾸며주기 ( a 태그 ) 

색상도 변경해줌. 

글 수정 페이지의 URL 을 결정해주기. 

= 첫 번째 글의 수정 버튼을 누르면 저 URL 로 이동되게끔 하구시픔. 

/edit/게시물id

▲ 저는 이렇게 접속하면 해당 게시물 수정페이지를 보여주도록 만들고 싶습니다. 

상세페이지 만들던거랑 비슷하게요. 

 

URL 을 각각 다르게 만드는 이유: 

글 수정 버튼을 누르면 각각 다른 페이지가 보여야 함. 

그래서 URL 을 각각 다르게 만듦.

이런식으로 수정해줌. 

/ edit/

import { connectDB } from "@/util/database";
import Link from "next/link";

export default async function List() {
  const db = (await connectDB).db("forum");
  let result = await db.collection("post").find().toArray();
  console.log(result);

  return (
    <div className="list-bg">
      {result.map((a, i) => {
        return (
          <div className="list-item" key={i}>
            <Link href={"/detail/" + result[i]._id}>
              <h4>{a.title}</h4>
            </Link>
            <Link href={"/edit/" + result[i]._id}>✏️</Link>
            <p>1월 1일</p>
          </div>
        );
      })}
    </div>
  );
}

첫 번째 글의 수정 버튼을 누르게되면

/ 그다음에 첫 번째  글의 아이디가 뜨게됨. 

두 번째 글의 수정버튼을 누르면

두 번째 글의 아이디도 확인 가능 

이제 404 뜨지 않게 페이지를 만들어보자

그럼 글이 100개 있으면 수정페이지도 100개 만들까요?

그래도 되겠지만 싫으면 [dynamic route] 문법을 사용합시다. 

detail 페이지 만들때 저렇게 한 것 처럼

= detail (폴더) [id] 폴더 생성


result.map((a,i)=>
  <div className="list-item" key={i}>
    <Link href={'/detail/' + result[i]._id}>{result[i].title}</Link>
    <Link href={'/edit/' + result[i]._id} className="list-btn">✏️</Link>
    <p>1월 1일</p>
  </div>
)

▲ 그래서 /list/page.js 페이지에 있던 글제목 옆에 수정버튼도 집어넣어봤습니다. 

그럼 누르는 순간 /edit/게시물id로 이동해주는군요. 

a {
  text-decoration: none;
  color : black;
} 

▲ css 파일에 디자인도 대충 넣어봄


2. 글 수정페이지 만들기 

에딧 (수정) 페이지 생성해주기 

= 수정 폴더 만들기

= app 폴더 안에 생성

이렇게 edit 폴더 하나 생성

그 다음에 [id] 를 써서

다이나믹 라우트를 사용해준다. 

그리고 그 안에 page.js 파일 생성

그러면 저렇게 주소로 접속했을 시 

page.js 파일 안에 있는 내용 보여줌. 

 

생성한 edit\[id]\page.js 에다가

레이아웃 하나 만들어주기. 

글 수정페이지는 어떻게 생겼죠? 

 

블로그나 게시판 서비스 아무데나 들어가보면 글 수정페이지는 작성페이지와 유사하지않습니까?

= 글 작성페이지에 있던거 그대로 갖다 써보기 

그리고 그 페이지에 있는 <input>들엔 게시물 내용이 들어있을 뿐이고요. 

export default async function Edit() {
  return (
    <div className="p-20">
      <h4>수정페이지</h4>
      <form action="어쩌구" method="POST">
        <input name="title" />
        <input name="content" />
        <button type="submit">전송</button>
      </form>
    </div>
  )
}

그래서 /edit/[id]/page.js 파일 만들어서 레이아웃 만들어봤는데 /write 페이지 그대로 베낌 

그리고 이 페이지에 DB에서 가져온 게시물을 집어넣어봅시다.

레이아웃 만들고 확인해줌. 

레이아웃 - 수정페이지 


수정페이지에 DB에 있던 게시물을 넣어줘야겠는데요 

/edit/게시물id 입력해서 수정페이지 방문하면 지금은 텅 비어있는데 

해당 게시물id를 가진 글을 DB에서 가져와서 수정페이지 안에 보여주도록 합시다.

detail 페이지에서 썻던 코드 옮겨줌.

connectDB 이런거 상단에서 import .

그리고 await 갖다 쓰려면 async 꼭 추가

도큐먼트하나 갖고오늘 코드

어떤 게시물을 찾아와서 보여줄 건지 ??

= 첫째 게시물을 찾아서 보여주고싶으면 

첫 째 게시물의 아이디를 넣어주면 될 것 같음.

만약 첫 째 게시물의 아이디를 입력하면 

첫째 게시물의 제목과 내용을 찾아와서 보여줘야 함. 

이걸 갖고와줘야 함

= 현재 URL 에 입력한 id

= props 갖다 쓰기. 

= props 에 다이나믹 라우트 자리에 입력한 것들이 들어있음. 

출력해보면 현재 URL 에 입력한 데이터들이 나옴

이렇게 URL 에 입력한 내용이 나오고 있는 거 확인됨

저걸 꺼내서 입력해주면 될 것 같다

props.params.id 라고 써주면 될듯. 

저 출력된 모양이 오브젝트 모양이니까 

. 을 써서 꺼내줌.

 

그럼 이제 저 id 를 가진 게시물은

DB에서 찾아줄 것. 

근데 몽고DB 에는 도큐먼트(파일)를 잘 보면 

저런식으로 id 들이 기록돼있음.

 

저거랑 똑같이 맞춰 줘야지 잘 찾아올 수 이씀.

그럼 저걸 이런 식으로 바꿔줘야함.

도큐먼트에는 저런 식으로 써져 있으므로. 

근데 ObjectId 함수 갖다 쓰려면 상단에 import 필수

import { ObjectId } from "mongodb";
import { connectDB } from "@/util/database.js";

export default async function Edit(props) {
  let db = (await connectDB).db("forum");
  let result = await db
    .collection("post")
    .findOne({ _id: new ObjectId(props.params.id) });
  return (
    <div className="p-20">
      <h4>수정페이지</h4>
      <form action="" method="POST">
        <input name="title" />
        <input name="content" />
        <button type="submit">전송</button>
      </form>
    </div>
  );
}

console 써서 잘 담아오는 지 확인해보기. 

터미널에 갖고온 데이터 잘 뜨는 거 확인됨.

result 안에 있는 title 하고 content 를 집어넣고 싶은 경우 (수정해야하니까 보여야함)

value 속성 사용. 

 

value 속성

= 인풋에 미리 입력된 값을 뜻함. 

만일, 에러가 뜰 경우 

defaultValue 쓰면 됨. 

페이지 들어가서 확인해보기

= 글이 잘 채워져 있는거 확인완료 


알아서 해봅시다
import { ObjectId } from "mongodb";
import { connectDB } from "@/util/database.js"

export default async function Edit(props) {
  let db = (await connectDB).db('forum')
  let result = await db.collection('post').findOne({_id : ObjectId(props.params.id)});
  return (
    <div className="write">
      <form action="어쩌구" method="POST">
        <input name="title" defaultValue={result.title} />
        <input name="content" defaultValue={result.content} />
        <button type="submit">전송</button>
      </form>
    </div>
  )
}

 

<input> 안에 미리 채워질 내용을 적고 싶으면 value="채울내용" 속성을 추가하면 되는데

Next.js의 server component에선 value를 그냥 쓰면 뭐라고 하는 경우가 있습니다.

그럴 땐 defaultValue=" " 사용합시다. 기능은 value=" " 와 같습니다. 

 

수정페이지 완성

 

[collapse]

MongoDB 데이터 수정하는 법

 

MongoDB에 있던 document 수정하는 방법을 알려드릴테니

기능 마무리는 여러분이 집에가서 해보도록 합시다.

 

DB에 있는 하나의 글을 갖고오고 싶은 경우 

저렇게 써서 갖고와줌. 

근데 DB 에 있던 하나의 글을 수정하고 싶은 경우

await 붙인다음 updateOne 갖다 쓰면 됨. 

그리고 중괄호 사용해서 채워주면 됨. 

저런 식으로 큰 틀잡고 코드를 짬. 

첫번째 중괄호에는 수정할 게시물 정보 담기

ex) id 가 1인 도큐먼트(파일) 수정 

그리고 set 안에는 수정할 내용을 넣어주면 됨. 

ex) title 을 바보로 수정해라 

content 부분도 동시에 수정해주고 싶은 경우

추가해주면 됨. 


DB에 있던 document 수정문법은 쉬운데 

await db.collection(컬렉션명).updateOne({수정할게시물정보}, { $set : {수정할내용} } ); 

updateOne() 쓰면 되는데 안에 2개 정보들을 넣어주면 되는데 

왼쪽엔 수정할 게시물을 일단 찾아야하기 때문에 수정할 게시물에 들어있던 내용을 { } 자료로 넣어주면 됩니다.

보통 {_id : 어쩌구} 넣는 경우가 많습니다. 

 

오른쪽엔 수정할 내용을 { } 자료로 넣으면 됩니다. 

예를 들어 title 항목을 '바보'로 수정하고 싶으면 { title : '바보' } 넣으면 됩니다. 

 

(참고) $set 말고 여러가지 연산자가 있습니다. 

$set 연산자는 기존 값을 바꿔줍니다. 만약에 없으면 추가해줌

$unset 연산자는 기존에 있던 키값을 제거해줍니다. 

$inc 연산자는 기존 값이 숫자면 거기에 숫자를 더하거나 뺄 때 사용합니다. 

필요할 때 찾아서 사용합시다. 


오늘의 숙제 : 

3번 기능을 완성해옵시다. 

수정 페이지에서 전송버튼 누르면 DB에 있던 해당 글이 수정되어야합니다. 

 

(힌트) 유저는 서버에게 게시물을 수정해달라고 요청보낼 때

수많은 게시물 중에 어떤 게시물을 수정할지 그 정보도 보내줘야 잘 수정할 수 있지않을까요?

게시물 id 같은거요 

 

728x90