Next.js 글 삭제 기능과 애니메이션 구현 (7)

2024. 3. 5. 23:18Next.js

728x90
반응형

글 삭제 기능과 애니메이션 구현


글 삭제 버튼 만들기

글 삭제 기능을 만들기 위해 먼저 각 글마다 삭제 버튼을 만들어야 합니다. 이 때, 삭제 버튼을 누르면 해당 글이 데이터베이스(DB)에서 삭제되고, 그 과정에서 글 목록에서 해당 글이 서서히 사라지는 UI 애니메이션을 추가해보겠습니다.


Client Component에서 애니메이션 구현


먼저, '삭제 버튼'을 누르면 해당 글이 서서히 사라지는 기능은 클라이언트 컴포넌트에서만 구현할 수 있습니다. 이를 위해 클라이언트 컴포넌트를 만들어서 코드를 작성하겠습니다.
하지만 기존에 있던 '/list/page.js' 파일을 전부 클라이언트 컴포넌트로 바꾸는 것 보다는, JavaScript 기능이 필요한 부분만 클라이언트 컴포넌트로 바꾸는 것이 효율적입니다.


ListItem 컴포넌트 만들기

그래서 '/list/ListItem.js'라는 클라이언트 컴포넌트를 만들어서 글 목록 UI를 옮겼습니다.

//javascript
'use client'

export default function ListItem() {
  return (
    <div>
      { 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>
       ) }
    </div>
  )
}


그 다음으로는 이 ListItem 컴포넌트를 '/list' 페이지 안에 넣어보겠습니다.

//javascript
import ListItem from './ListItem.js'

export default async function List() {
  return (
    <div className="list-bg">
      <ListItem/>
    </div>
  )
}


그런데 이렇게 하면 "ListItem 컴포넌트 안에 result가 정의되지 않았다"는 에러가 발생합니다. 이 문제를 해결하기 위해 두 가지 방법을 사용할 수 있습니다.

1. List 컴포넌트에 있던 result 변수를 ListItem까지 props로 전송하거나
2. ListItem 컴포넌트에서 직접 DB 데이터를 가져오거나


ListItem에서 DB 데이터 가져오기

ListItem 컴포넌트에서 DB 데이터를 가져오려면 useEffect를 사용하여 서버에 요청해서 DB 데이터를 가져올 수 있습니다. 그러나 이 방법의 단점은 페이지 로드 시 유저가 먼저 빈 HTML을 보게 되고, 조금 시간이 지나야 HTML 내용이 채워진다는 것입니다. 이는 검색 엔진 봇들이 페이지를 수집할 때 단점이 될 수 있습니다.

//javascript
'use client'

export default function ListItem(){
  useEffect(()=>{
    let result = (서버에 요청해서 DB데이터 가져오는 코드)
  },[])

  return (
    <div>{result}</div>
  )
}

 

ListItem에 props 전송하기

그래서 이런 경우에는 부모 컴포넌트인 List에서 DB 데이터를 가져온 후 ListItem으로 props로 전송하는 방법이 좋습니다. 이 방법을 사용하면 클라이언트 컴포넌트도 DB 데이터를 미리 채워서 유저에게 보여줄 수 있습니다.

List 컴포넌트에서 ListItem 컴포넌트로 result 변수를 props로 전송하려면 다음과 같이 작성하면 됩니다.

//javascript
<ListItem result={result} />


그리고 이제 ListItem 컴포넌트에서는 props를 받아서 사용하면 됩니다.

javascript
'use client'

export default async function ListItem({result}) {
  return (
    <div>
      { 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>
            <button>🗑️<button>
            <p>1월 1일</p>
          </div>
       ) }
    </div>
  )
}


Ajax를 사용한 요청

서버에 요청을 보내는 방법 중 하나인 Ajax를 사용하면, 페이지를 새로 고침하지 않고도 서버로 요청을 보낼 수 있습니다. 이는 form 태그를 사용하여 요청을 보낼 때 페이지가 새로고침 되는 것을 방지할 수 있습니다.

//javascript
<button onClick={()=>{
  fetch('/URL')
}}>🗑️</button>


fetch()를 실행하면 '/URL' 경로로 GET 요청이 갑니다. 요청이 완료되었을 때 특정 코드를 실행하려면 .then()을 사용하면 됩니다.

//javascript
<button onClick={()=>{
  fetch('/URL').then(()=>{
    console.log('완료')
  })
}}>🗑️</button>


POST, PUT, DELETE 요청도 가능하며, 요청 시 서버로 데이터를 전송하려면 body 항목에 데이터를 넣으면 됩니다.

//javascript
<button onClick={()=>{
  fetch('/URL', { method : 'POST', body : '안녕' })
}}>🗑️</button>


서버로 배열이나 객체를 전송하려면 JSON.stringify() 함수를 사용하여 JSON 형식으로 변환한 후 전송하면 됩니다. 또한, JSON 형식의 데이터를 배열이나 객체로 변환하려면 JSON.parse() 함수를 사용하면 됩니다.