본문 바로가기

Next

게시판 글 수정 방법.

          <Link href={`/edit/${item._id}`}>수정✏️</Link>

게시판 리스트에서 수정 버튼을 링크로 만들어준다. 

/edit/${item._id} 는 게시물의 아이디를 페이지 주소로 보내준다는것 / 라우터 페이지 주소로 생성

라우터 [] 방법으로 수정페이지를 하나 만들어준다.

import { connectDB } from '@/util/database';
import { ObjectId } from 'mongodb';
const page = async(props:any) => {
    let result = await (await connectDB).db("forum").collection('post').findOne({_id:new ObjectId(props.params.id)}) // 여기 id 는 [라우터 제목]
    console.log(result, "여기")
    //위는 게시글 데이터를 가져와서 input 에 뿌려주기 위해서 가져옴
    return (
        <div className='p-20'>
            <h4>글수정 페이지</h4>
            <form action="/api/post/new" method="POST">
                <input name="title" placeholder='제목' defaultValue={result.title}></input>
                <input name="content" placeholder='내용' defaultValue={result.content}></input>
                    <button type="submit">Post 버튼</button>
            </form>
        </div>
    );
};

export default page;

데이터를 불러와서 인풋에 넣고싶으면 인풋 가운데 {} 이거롤 넣는게 아니라 value= {이안에 넣는것이다.}

value 가 안될경우 defaultValue={이걸 사용해도 된다 용도는 같음} 넥스트에서는 디폴트벨류를 쓰는게 더잘들어갈때가 있다.

차이. value 는 수정이 안되고 고정이된다. 아무래도 벨류 자체 그렇기때문

defaultValue 는 수정이 가능. 처음상태만 디폴트 값으로 넣어주기 때문인듯.

 

수정하는방법 위 코드사이에

    await (await connectDB).db("forum").collection('post').updateOne({수정할 게시물정보},
        {$set:{title:'바보',content:'바보2'}}
        )

넣어주면된다. set는 수정할 항목이다. 위에는 예시다.

 

바로위에것을 api 폴더안에 포스트 폴더안에 edit.tsx 파일을 만들어서 그안에서 작성한다

Tip. edit 폴더에서 요청.body 를 콘솔로 출력하면 인풋에 수정한걸 요청.body 로 받는다.

참고로 요청.body 자체가 오브젝트 스코프 자료형 이기때문에 따로 위처럼 title / content 나눠서 안해줘도된다. 포괄적으로 수정한다.

 

전체 코드 완성

psge.tsx     [라우터 페이지다.]

import { connectDB } from '@/util/database';
import { ObjectId } from 'mongodb';

const page = async(props:any) => {
    let result = await (await connectDB).db("forum").collection('post').findOne({_id:new ObjectId(props.params.id)}) // 여기 id 는 [라우터 제목]
    console.log(result, "여기")

    return (
        <div className='p-20'>
            <h4>글수정 페이지</h4>
            <form action="/api/post/edit" method="POST">
                <input name="title" placeholder='제목' defaultValue={result.title}/>
                <input name="content" placeholder='내용' defaultValue={result.content}/>
                <input style={{display:'none'}} name="_id" defaultValue={result._id.toString()}></input>
                    <button type="submit">전송버튼 버튼</button>
            </form>
        </div>
    );
};

export default page;

위코드 설명 input 중에 display:'none' 건 api edit.tsx 에 _id 값을  =>  요청.body 넣기위해서 input 에 넣어서 보낸것이다.

개인적인 의견은 그냥 수정안되게 인풋설정해서 보여도 상관없지 않을까? 

 

api 폴더의 edit.tsx

import { connectDB } from '@/util/database';
import { ObjectId } from 'mongodb';

const edit = async(요청:any,응답:any) => {
    if (요청.method == 'POST'){
        const 바꿀거 = {
            title:요청.body.title,
            content:요청.body.content
        }  // 위는 바꿀데이터 골라서 변수에 넣어주기 $set 에 들어간다.
        await (await connectDB).db("forum").collection('post').updateOne({_id: new ObjectId(요청.body._id)},
        {$set:바꿀거}
        )
        응답.status(200).redirect(302,'/list')
        // 위는 전부 처리 완료후 할행동을 넣은것이다 302가 들어가야 작동할때도 있고 안들어가도 될때가있다.
    }
};

export default edit;

바꿀거를 만든이유는 위에서도 말했지만.

요청.body 필요한 데이터 말고 아이디값도 있어서 따로 빼줘서 넣은것이다.

updateOne는 업데이트 덮어쓰기할 데이터 id 값이나 위치값을 넣어주면된다.

new ObjectId 를 쓴이유는 아이디값 데이터 구조가 저렇기때문

{
    _id: new ObjectId("6488715e894603854694cb12"),
    title: '수정했다 1',
    content: '수정했다 2'
    }

저게없다면 그냥 코드만 요청.body._id 만 넣으면되었다.

중요

$set: 바꿀꺼 

$set 가 데이터 에 덮어씌울 새로운 데이터 이다.

그래서 요청.body 로 인풋에 새롲거은걸 받아서 $set 안에 넣어주면 새로운 데이터로 덮어싀워준다.

 

그외에 $inc:1

같은경우는 조회수에 쓰일때쓰는거같다 숫자를 증감시켜주는 기능.

 

더보기

서버기능 만들기

 

서버에 DB수정하는 기능 만들고 

유저가 버튼누르면 그걸 실행하라고 부탁하는 식으로 코드짜면 됩니다.

 

 

 

<div className="write">
  <form action="/api/post/edit" method="POST">
    <input name="title" defaultValue={result.title}/>
    <input name="content" defaultValue={result.content}/>
    <button type="submit">전송</button>
  </form>
</div> 

action 속성에 이렇게 적으면 /api/post/edit.js 파일 안에 있는 코드가 실행되니까

그 파일 만들어서 기능만들면 되겠군요.

그래서 서버기능 만들러 api 폴더로 이동해봅시다. 

 

 

 

 

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

export default async function handler(요청, 응답) {
  if (요청.method == 'POST'){
    console.log(요청.body)
    let db = (await connectDB).db('forum')
    let result = await db.collection('post').updateOne({게시물정보}, { $set : {바꿀데이터}} );
    응답.redirect(302, '/list')
  }
}

pages/api/post/edit.js 파일 만들고 이렇게 코드를 짰습니다. 

유저가 폼으로 보낸 데이터는 요청.body 출력하면 있으니까 거기서 

바꿀데이터와 게시물정보도 꺼내서 저기에 잘 채워넣으면 될 것 같은데 

하지만 요청.body 출력해보면 유저로부터 전달되는 데이터가 {title : 어쩌구, body : 어쩌구} 밖에 없습니다.

바꿀데이터는 있는데 게시물정보는 없는데유 

 

 

 

<div className="write">
  <form action="/api/post/edit" method="POST">
    <input name="title" defaultValue={result.title}/>
    <input name="content" defaultValue={result.content}/>
    <input name="_id" defaultValue={result._id.toString()}/>
    <button type="submit">전송</button>
  </form>
</div> 

그럼 유저에게 보내라고 하면 되는거 아니겠습니까. 

서버에서 코드짜다가 데이터같은게 없으면 유저에게 보내라고 하거나 DB에서 꺼내보면 됩니다. 

수정페이지에 <input>을 하나 더 만들고 _id를 집어넣어둡니다. 

그럼 서버로 _id 이름으로 ObjectId('어쩌구') 에서 '어쩌구' 내용부분만 전달됩니다.

 

Q. 왜 .toString() 쓰냐고요? 

서버와 데이터 주고받을 때 문자, 숫자, JSON 이런 것만 주고받을 수 있습니다. 

저런 이상한 데이터들은 문자로 치환하는 방법을 찾아서 쓰면 되겠습니다. 

 

Q. _id 같은건 유저에게 안보여주는게 좋지않나요?

넴 display : none 같은 스타일 줘서 숨기면 됩니다. 

 

 

 

 

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

export default async function handler(요청, 응답) {
  if (요청.method == 'POST'){

    let 바꿀거 = {title : 요청.body.title, content : 요청.body.content}
    let db = (await connectDB).db('forum')
    let result = await db.collection('post').updateOne(
      {_id : new ObjectId(요청.body._id)}, 
      { $set : 바꿀거} 
    );
    console.log(result)

    응답.redirect(302, '/list')
  }
}

1. 요청.body에서 이것저것 꺼내서 바꿀데이터를 만들어서 updateOne() 안에 집어넣었습니다. 

2. 요청.body._id 꺼내서 게시물정보를 만들어서 updateOne() 안에 집어넣었습니다. 

{ } 자료같은게 어렵고 어색하면 자바스크립트 기초강의 들을 시점입니다. 

 

 

 

 

(참고) 실은 GET, POST 말고도 PUT, DELETE 요청으로 서버와 통신할 수도 있습니다.

PUT은 수정, DELETE는 삭제할 때 쓰면 좋은데 서버 api들 끼리 이쁘게 구분하기 위함이고 필수는 아닙니다. 

단점은 <form>으로 데이터 전송시 PUT, DELETE는 사용할 수 없어서 굳이 쓰고 싶으면 외부 라이브러리 설치하거나 해야합니다.

그래서 코드가 너무 길거나 그런게 아니면 <form>으로 데이터 전송시엔 일단 POST 요청 쓰는게 낫습니다. 

 

 

 

오늘의 결론은 

- document 수정하려면 updateOne 쓰면 됩니다. 값 변경말고 증가/감소도 가능함 

- 서버에서 코드짜다가 필요한 데이터가 없으면 1. 유저에게 보내라고 하거나 2. DB에서 꺼내써도 됩니다.