본문 바로가기
> 메모/Next.js

[Next.js] 상세 페이지 만드는 방법

by 자몽주스 2024. 11. 13.
728x90
상세 페이지 (detail) 만들기
- 리스트 페이지에서 글 클릭하면 나오는 상세페이지 구현하기
1. 글 제목을 누르면 
2. 상세페이지로 이동하고 
3. 그 페이지에선 DB에서 그 게시물을 가져와서 보여줌 

 Dynamic route 사용
폴더 하나로 수많은 URL 생성
/detail/1로 접속시 1번글 내용
/detail/2로 접속시 2번글 내용
/detail/3로 접속시 3번글 내용

이렇게 보여줘야 함.

 

1) detail (상세페이지 URL) 폴더 하나 생성. 
그리고 detail 폴더 안에 [작명] 해서 또 폴더 생성하기.

detail 폴더 안에 - [id] 폴더

- id 라고 작명했다. 

- 대괄호 써줘야 함. 

- URL 주소창 에다가 /detail/아무거나 입력했을 때 뜬다는 의미. 

2) 그 다음 또 [작명] 폴더 안에다가 page.js 파일을 생성해줌 

- URL 주소창 에다가 /detail/아무거나 입력했을 때

page.js 에 있는 페이지 내용 보여짐.

 

3) 생성한 page.js 에다가 컴포넌트를 만들어줘서 접속 시 보여지게끔 만들기. 
export default async function Detail() {
  return (
    <div>
      <h4>상세페이지임</h4>
      <h4>글제목</h4>
      <p>글내용</p>
    </div>
  )
}}

컴포넌트 생성해줌

 

4) 게시물 하나씩만 MongoDB에서 찾아서 갖고와서 보여주려면
= 저번시간에 한 몽고DB 코드갖고오는 코드 갖고오기. 
const db = (await connectDB).db("forum");
let result = await db.collection("post").find().toArray();

DB 갖고 오는 코드를 갖고온다. 

= post 컬렉션 안에 있는 모든 document(파일) 을 갖고오라는 코드. 

import { connectDB } from "@/util/database"

export default async function Detail() {
  const db = (await connectDB).db("forum");
  let result = await db.collection("post").find().toArray();
  
  return (
    <div>
      <h4>상세페이지임</h4>
      <h4>글제목</h4>
      <p>글내용</p>
    </div>
  )
}}

- connectDB 임포트 필수

- await 쓸 거니까  export default 옆에 에다가 async 써주기.

5) 게시물 하나만 갖고오도록 하기
= findOne() 사용
= id를 갖고오게 하기. (ObjectId)
const db = (await connectDB).db("forum");
let result = await db.collection("post").findOne({})

중괄호 열어줘서 

갖고 올 document 의 내용 일부를 적어줌

db.collection(컬렉션명).findOne(찾을document내용)

 

console.log(result) 로 몽고DB 에서 뭘 갖고오는 지 확인 가능. 

ObjectId 를 갖고오도록 하기.

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

export default async function Detail() {
  let db = (await connectDB).db('forum')
  let result = await db.collection('post').findOne({_id : new ObjectId('63ce8d2b10e3e9fd2d7e0c0b')});
  console.log(result)

  return (
    <div>
      <h4>상세페이지임</h4>
      <h4>{result.title}</h4>
      <p>{result.content}</p>
    </div>
  )
}}

ObjectId 사용하려면 상단에 import 필수

※그리고 ObjectId 옆에 new 라는 거 써야함.

6) 유저가 URL 에 입력한 값 넣어줘서 유동적으로 페이지 보여주기 
= props 활용
/detail/1 접속하면 1번게시물
/detail/2 접속하면 2번게시물 
가져오라고 코드 수정

 

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

export default async function Detail(props) {
  let db = (await connectDB).db('forum')
  let result = await db.collection('post').findOne({_id : new ObjectId('63ce8d2b10e3e9fd2d7e0c0b')});
  console.log(props)

  return (
    <div>
      <h4>상세페이지임</h4>
      <h4>{result.title}</h4>
      <p>{result.content}</p>
    </div>
  )
}}

- Detail 옆 소괄호에 props 를 파라미터로 입력.

- 그리고 props 를 출력하면 URL 경로 자리에 입력한 값들이 터미널에 뜬다.

- [id] 로 작명해줬는데 대괄호 자리에 입력한 값을 출력해주는 것. 

/detail/[id]

let result = await db
    .collection("post")
    .findOne({ _id: new ObjectId(props.params.id) });

- 유저가 입력한 값만 꺼내고 싶은경우엔

.params.id 라고 쓰면 bbb가 출력.

= 오브젝트 자료형 {} 안에 또 오브젝트 자료형 {}이 있는 형태이기 때문.

= props.params.id 이렇게 넣어줌.


list 페이지의 글 제목에 상세페이지 이동링크 생성하기
/detail/게시물의_id 이렇게 이동시켜주는 이동링크 생성
= Link 컴포넌트 사용

 

글 누르면 상세페이지로 이동시켜주는

= (/detail/게시물의_id ) 이 URL 로 이동시켜주는 링크 만들어주기.

 

1) Link 태그 사용하기
- import 필수
- list / page.js 에다가 해줌. 
import { connectDB} from "@/util/database"
import Link from "next/link" //Link 태그 임포트

export default async function List(){

 const db = (await connectDB).db("forum");
  let result = await db.collection("post").find().toArray();

  return (
    <div className="list-bg">
      { result.map((a, i)=>
        <div className="list-item" key={i}>
          <h4>{result[i].title}</h4>
          <Link href={"경로"}>링크</Link>
          <p>1월 1일</p>
        </div>
      ) }
    </div>
  )
}

<Link href = {"경로"}> 링크 </Link>

= /detail 하고 /글 id 를 경로로 작성.

 

2) /detail 하고 /글 id
글 id 경로 찾기
= result 변수 활용
const result = await db.collection('post').find().toArray();

여기 result 에 글 id 경로가 있음.

 <h4>{result[i]._id}</h4>

h4 를 통해서 출력해보면 

이렇게 글의 id 가 뜨는 거 확인.

 = result[0].title 이렇게 써서 title 속성 빼오듯이 _id 속성을 빼오는 것

즉, result[i]._id는 i번째 게시물 객체에서 _id라는 속성의 값을 가져오는 코드​
[
  { _id: "123", title: "첫 번째 게시물", content: "..." },
  { _id: "456", title: "두 번째 게시물", content: "..." },
  { _id: "789", title: "세 번째 게시물", content: "..." }
]

result의 생김새 

3) 글의 id 를 찾았으면 Link 태그의 경로를 지정해주기 
- 변수 사용 시 + 써서 연결
 <Link href={"경로"}>링크</Link>

경로 넣는 곳에

 <Link href={"/detail/result[i]._id"}>링크</Link>

이렇게 찾은 글의 id 를 넣어주면 될 것 같지만

result 는 변수니까 저런 식으로 쓰면 안된다.

 <Link href={'/detail/' + result[i]._id}>링크</Link>

+ 써서 변수와 연결시켜줌. 

4) 링크 경로 연결을 다 해줬으면 제목과 합쳐서 
제목을 누르면 저 페이지로 이동하게끔 만들기. 

제목인 h4 태그

<Link href={'/detail/' + result[i]._id}><h4>{a.title}</h4></Link>

Link 태그와 합쳐주기.

5)  Link 태그 사용시
prefetch 기능 끄고 싶은 경우,  false 로 사용해준다. 
<Link href={'/어쩌구'} prefetch={false}>링크</Link>

Link 태그는 prefetch 기능이 default 로 들어가있음


Link 태그 외에 UseRouter 쓰는 방법도 존재
= client component 에서만 가능
= 자바스크립트 코드로 페이지이동

 

상단에

'use client' 써서 UseRouter 사용 가능

다양한 기능 존재.

서버 컴포넌트에서도 사용하려면
클라이언트 컴포넌트를 하나 만든 다음,
useRouter 기능을 넣고,
이 컴포넌트를 서버 컴포넌트에 집어넣는 식으로 하기. 

 

728x90