게시판 내용 목록 불러오기
먼저 /list 로 라우팅 처리를 해준다.
폴더 list 를 app 폴더 안에 만들고
-> list 폴더 안에 page.js 를 만들어준다.
해당 page.js 안에 몽고DB를 연동하고 게시글 목록을 불러와준다.
import {connectDB} from '@/utils/database'
const client = await connectDB;
const result = await client.db('forum').collection('post').find().toArray();
MongoDB를 connect 시켜둔 코드를 import 하고 client 에 db, collection 에 접근해준다.
잘 불러와진다.
그 다음으론 게시글의 상세페이지 이동을 처리 -> Dynamic Route
우선 [폴더명] 형태로 폴더를 만들어준다. -> page.js 를 만들어준다.
해당 의미는 폴더명으로 접근하는 url은 어떠한 다른 url로 들어와도 접근이 가능하게 해달라고 하는 약속이다.
예를 들어 위와같은 계층구조라면, detail/1 이든 detail/2든.... 모두 page.js 로 접근이 가능하다.
상세페이지마다 다른 내용 보여주기
위의 경우 다른 url 로 접근하더라도 별다른 처리가 없다면 모두 같은 내용이 뜨게된다.
이때는 위에서 작성해줬던 find() 메서드 대신 디비의 특정 object를 찾아올 수 있는 findOne() 메서드를 사용하여 찾아와준다.
const client = await connectDB;
const result = await client.db('forum').collection('post').findOne({ title : '안녕'});
이때 findOne() 의 매개변수로 위와 같이 중복될 수 있는 조건이 아닌, 객체를 한정 지을 수 있는 내용이 들어가는 게 맞기때문에
import { ObjectId } from 'mongodb'
const client = await connectDB;
const result = await client.db('forum').collection('post').findOne({ _id : new ObjectId('') });
몽고디비에서 기본적으로 주어지는 _id 값을 이용하여 접근하도록 한다.
이때 new ObjectId() 로 접근해줘야 한다.
그렇다면 게시글마다 다른 상세페이지를 불러오려면?
해당 Detail 컴포넌트 안에 props 속성을 넣어줘서 내용을 확인해본다.
params 안에 객체로 폴더명 : '접근한 url' 으로 확인해줄 수 있다.
export default async function Detail(props) {
const client = await connectDB;
const result = await client.db('forum').collection('post').findOne({ _id : new ObjectId(props.params.id)});
console.log(props);
return (
<div>
<h4>{result.title}</h4>
<p>{result.content}</p>
</div>
)
}
props.params.폴더명 으로 접근해서 findOne() 처리를 해주면 각 페이지마다 몽고DB에 존재하는 게시글 내용을 확인 가능하다.
이때 없는 id값으로 접근하면 에러가 발생한다.
그리고 /list 페이지에서 해당 글과 글의 내용을 Link 로 연동시켜주면 게시글을 클릭했을 때 해당 게시글의 상세페이지로 넘어갈 수 있게 된다.
export default async function List() {
const client = await connectDB;
const boardList = await client.db('forum').collection('post').find().toArray();
return (
<div className="list-bg">
{boardList.map((el, idx) => {
return (
<div className="list-item" key={idx}>
<Link href={'detail/' + el._id}>
<h4>{el.title}</h4>
<p>{el.content}</p>
</Link>
</div>
)
})}
</div>
)
}
Link 태그 말고 페이지를 이동시키는 다른 방법
먼저 use client 로 새로운 컴포넌트를 만들어준다.
import { useRouter } from 'next/navigation'
-> useRouter() 훅을 사용해준다. 해당 훅은 클라이언트 컴포넌트 안에서만 사용이 가능하므로 서버 컴포넌트에선 사용불가함
-> 해당 훅을 변수에 저장해두고 메서드를 불러와서 사용해준다.
단순히 페이지 이동을 위해선 push() 메서드를,
export default function DetailLink(props) {
const router = useRouter();
return (
<button onClick={() => {
router.push(props.link);
}}>이동</button>
)
}
- back() 메서드는 바로 이전 페이지로
- forward() 메서드는 앞으로 가기
- refresh() 는 바뀐 내용만 새로고침해주기 (전부 새로고침X)
- prefectch() 메서드는 페이지 미리 로드를 해줘서 사용자경험이 좋아질 수 있음
Link 태그는 이미 prefectch 기능이 내장되어 있으므로 페이지 로드가 미리 되어 있는 상태이다.
그렇기에 해당 태그를 남용하면 쓸데없이 페이지 로드가 되는 부분이 생기기 때문에
속성 prefetch 로 해당 기능을 on/off 가능하다.
<Link href={'detail/' + el._id} prefetch={false} > //...
그밖에도... usePathname() 과 useSearchParams(), useParams() 훅을 next/navigation 에서 불러와서 사용할 수 있음
- usePathname() 은 현재 url 을 출력해주는 훅
- useSearchParams() 은 쿼리스트링 내용을 출력해주는 훅
- useParams() 는 dynamic route 입력한 내용을 출력해주는 훅
Link 태그 대신 이렇게 새로 클라이언트 컴포넌트를 만들어주면 위의 메서드처럼 여러 기능을 추가해줄 수 있는 이점이 존재한다.
3-tier architecture (3계층 구조) ?
플랫폼을 3계층으로 나눠서 별도의 논리적/물리적인 장치에 구축 및 운영하는 형태
데이터 입력/표현 계층(사용자 인터페이스) - 프론트엔드 / GUI |
데이터 처리하는 어플리케이션 계층 비즈니스 로직 계층 혹은 트랜잭션 계층 - 미들웨어 / 백엔드 / 서버 |
데이터를 저장하고 읽는 계층(DB) - DBMS |
글쓰기를 구현하려면 해당 원리에 맞게 해주는 것이 좋다.
기본적으로 서버 개발은?
XX 요청이 오면 ZZ 코드를 실행하게
/url
method -> Get/Post/Put/Delete/Patch
- Method
- Get : 유저에게 데이터 전송 시
- Post : 새로운 데이터 추가 시
- Put / Patch : 데이터 수정 시
- Delete : 데이터 삭제 시
Nextjs 에서 서버 기능을 구현하려면,
- app 폴더 하위에 api 폴더를 만들어 주기 (강의 내용 상 이게 더 신버전이지만 아직 불안정하다고 함)
- app 폴더와 동등한 계층(최상위)에 pages 폴더를 만들고 그 하위에 api 폴더 만들어 주기
Nextjs 의 자동 라우팅 기능
이러한 계층 구조일 때, /api/test 로 요청을 하면 test.js 코드가 실행되게끔 자동 라우팅 기능이 존재한다.
// test.js
export default function handler(request, response) {
console.log('Test!');
// 서버는 기능 실행 후 유저에게 기본적으로 응답해줘야 하므로 아래처럼 response 파라미터로 return 해줘야한다.
// 만약 return 해주지 않으면 로딩이 지속된다.
return response.status(200).json('처리완료');
}
Get 요청하기
기본적으로 주소창에 url 을 입력하는 행위가 Get 요청이다.
Post 요청하기
가장 쉬운 방법은 form 태그를 사용하여 action 에는 url 주소를, method 에는 요청 메서드 post 를 입력해주는 것이다 (form 을 사용한 method 는 post와 get 밖에 안됨)
<form action="/api/test" method="POST">
<button type="submit">버튼</button>
</form>
게시글 작성하는 기능 구현
기본적으로 몽고디비에 데이터를 삽입하는 명령어는 insertOne() 메서드이다. (객체 형태로 보내는 것을 추천)
그럼 특정 url 에서 정보를 post 한 request(요청)의 body에 접근하여 그 내용을 insertOne() 해주면 된다는 것이다.
<form action="/api/test" method="POST">
<input placeholder='제목' name='title' />
<input placeholder='내용' name='content' />
<button type="submit">버튼</button>
</form>
form 태그 안에 input 태그로 써준 내용은 name 속성이 키값이 되어 request.body 에 담겨서 정보가 온다.
import { connectDB } from "@/utils/database";
export default async function handler(request, response) {
const client = await connectDB;
if(request.method == 'GET') {
return response.status(200).json(new Date());
} else if(request.method == 'POST') {
await client.db('forum').collection('post').insertOne(request.body);
return response.status(200).json('처리 완료');
}
}
이러면 서버에 보내진 요청.body 안에 객체 형태로 제목과 내용이 삽입될 것이다.
response 에 redirect(statusCode, 'url') 형태로 써주면 강제 이동이 가능하다.
'Web Study > Next.js' 카테고리의 다른 글
코딩애플 - 배포와 최적화에 대해, 회원가입에 대한 기초 (0) | 2023.06.28 |
---|---|
코딩애플 - Next.js 로 게시판 수정/삭제 구현 (0) | 2023.06.27 |
코딩애플 - Next.js 에서 MongoDB 연결하기 (0) | 2023.06.24 |
Next.js 시작! (0) | 2023.06.23 |
코딩애플 Next.js, 개발 환경 세팅하기 (0) | 2023.06.22 |