티스토리 뷰

어떻게 해야할까?

  • Page가 필요하겠네? 여러 input들을 받을 수 있는...
  • API도 필요하겠네? file에 저장할 input을 전달받을...
  • 서버에서 실제로 파일을 저장할 writePost 함수도 필요하겠네?
  • 작성이 성공하면 해당 page로 가는 Link도 제공하면 좋겠군...

 

우선 필요한 파일들을 생성해 봅시다

  • pages/post/write.js Page 추가
  • pages/api/post/write.js API 추가
  • lib/posts.js 안에 writePost 함수 추가

 

먼저 글을 쓸 수 있는 페이지를 구성해 봅시다

글을 쓸 수 있는 form이 있는 페이지를 만들어보겠습니다.

 

📜 pages/post/write.js

import { useRef } from 'react'
import Layout from '../../components/Layout'

export default function Write() {
  const idRef = useRef(undefined)
  const titleRef = useRef(undefined)
  const contentRef = useRef(undefined)

  const handleSubmit = (event) => {
    event.preventDefault()
  }

  return (
    <Layout>
      <h1>Write a post</h1>
      <form onSubmit={handleSubmit}>
        <input type="text" name="id" placeholder="id" required ref={idRef} />
        <br />
        <input
          type="text"
          name="title"
          placeholder="title"
          required
          ref={titleRef}
        />
        <br />
        <textarea
          type="text"
          name="content"
          placeholder="content"
          required
          ref={contentRef}
        />
        <br />
        <input type="submit" value="Create" />
      </form>
    </Layout>
  )
}

우선 위와 같이 간단한 ref 연결과 submit 함수 틀만 선언해 두었습니다.

 

그 다음으로, 기존 post + 새 post를 합치는 기능 함수를 만들어 봅시다

📜 lib/posts.js

export async function createPost({ id, title, date, content }) {
  const fullPath = path.join(postsDirectory, `${id}.md`)
  const data = `---
title: '${title}'
date: '${date}'
---

${content}`

  fs.writeFileSync(fullPath, data)
}

 

그 다음은, 요청을 보낼 API Routes를 구성해 봅시다

우리는 지금 만든 API Routes에 id와 title과 content를 보내서 Server는 기존 글 + 새로운 글을 합치는 역할을 수행해야 한다는 점을 집중해봅시다.

 

📜 pages/api/post/write.js

import { createPost } from '../../../lib/posts'
import { format } from 'date-fns'

export default async function handler(req, res) {
  const { id, title, content } = req.body

  try {
    await createPost({
      id,
      title,
      date: format(new Date(), 'yyyy-MM-dd'),
      content,
    })
    res.status(200).json({ message: 'create success' })
  } catch (error) {
    res.status(500).json({ error: `create failed ${error}` })
  }
}

req.body에서 id와 title과 content를 가져와서, 좀 전에 만든 createPost로 요청을 보냈을 때 성공/실패 response 로직을 작성해줍니다.

 

이제 다시 form의 submit 함수로 돌아옵시다

📜 pages/post/write.js

  const handleSubmit = (event) => {
    event.preventDefault()

    const id = idRef.current.value
    const title = titleRef.current.value
    const content = contentRef.current.value

    if (id && title && content) {
      fetch('/api/post/write', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({
          id,
          title,
          content,
        }),
      })
        .then((response) => {
          if (response.ok) {
            return response.json()
          }
          throw new Error('Fetch Error')
        })
        .then((data) => alert(data.message))
        .catch((error) => alert(`request error: ${error}`))
    }
  }

간단하게 유효성 검사를 해주고 모든 내용이 존재한다면 fetch를 보낸다는 내용이 포함되어 있습니다.

then/catch 부분을 보면, 성공 응답이 왔을 때만 response를 json으로 바꾸고 그 이외에는 error를 throw하고 있습니다. 그렇다면 아래에 있는 catch에서 에러를 잡아 alert를 띄울 것입니다.

실행 화면

파일이 잘 생성된 것을 확인할 수 있습니다.

 

Create한 후에 Link를 보여줘서 작성된 Post로 이동하는 것도 해봅시다

먼저 Link 태그를 보여줄지 보여주지 말지를 경우에 따라 렌더링하기 위해 boolean타입의 state를 하나 선언해줍니다.

 

📜 pages/post/write.js

  const [showLink, setShowLink] = useState(false)

그 후 form 바로 아래에 showLink가 true일 때만 보여줄 Link 태그도 추가해줍니다.

<form>
</form>
{showLink && (
	<Link href={`/post/${idRef.current.value}`}>Created Post</Link>
)}

이때 showLink는 response가 성공적일 때 업데이트해주도록 코드를 추가합니다.

const handleSubmit = (event) => {
    event.preventDefault()

    const id = idRef.current.value
    const title = titleRef.current.value
    const content = contentRef.current.value

    if (id && title && content) {
      fetch('/api/post/write', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({
          id,
          title,
          content,
        }),
      })
        .then((response) => {
          if (response.ok) {
            return response.json()
          }
          throw new Error('Fetch Error')
        })
        .then((data) => {
          setShowLink(true) ******
          alert(data.message)
        })
        .catch((error) => alert(`request error: ${error}`))
    }
  }

실행 화면

 


이번 글에서는 write 페이지를 만들고 API Route까지 해서 새로운 글을 쓸 수 있도록 해보았습니다 :)

 

1. API Routes

요청하는 코드는 Client Side에만 두자

 

2. POST 요청

Post를 직접 write하고 POST 해봄

728x90
LIST
250x250
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/04   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30
글 보관함