요구사항
- ✅ 서비스 완성
- 1) 서비스 완성, 2) Directory Structure, 3) AWS 배포 세 가지를 모두 완수해야 합니다.</aside>
- 전체 게시글 목록 조회 API
- 제목, 작성자명, 작성 날짜를 조회하기
- 작성 날짜 기준으로 내림차순 정렬하기
- 게시글 작성 API
- 제목, 작성자명, 비밀번호, 작성 내용을 입력하기
- 게시글 조회 API
- 제목, 작성자명, 작성 날짜, 작성 내용을 조회하기 (검색 기능이 아닙니다. 간단한 게시글 조회만 구현해주세요.)
- 게시글 수정 API
- API를 호출할 때 입력된 비밀번호를 비교하여 동일할 때만 글이 수정되게 하기
- 게시글 삭제 API
- API를 호출할 때 입력된 비밀번호를 비교하여 동일할 때만 글이 삭제되게 하기
- 댓글 목록 조회
- 조회하는 게시글에 작성된 모든 댓글을 목록 형식으로 볼 수 있도록 하기
- 작성 날짜 기준으로 내림차순 정렬하기
- 댓글 작성
- 댓글 내용을 비워둔 채 댓글 작성 API를 호출하면 "댓글 내용을 입력해주세요" 라는 메세지를 return하기
- 댓글 내용을 입력하고 댓글 작성 API를 호출한 경우 작성한 댓글을 추가하기
- 댓글 수정
- 댓글 내용을 비워둔 채 댓글 수정 API를 호출하면 "댓글 내용을 입력해주세요" 라는 메세지를 return하기
- 댓글 내용을 입력하고 댓글 수정 API를 호출한 경우 작성한 댓글을 수정하기
- 댓글 삭제
- 원하는 댓글을 삭제하기
- 전체 게시글 목록 조회 API
Directory Structure
.
├── app.js
├── routes
│ ├── index.js
│ ├── comments.js
│ └── posts.js
└── schemas
├── index.js
├── comment.js
└── post.js
AWS 배포
EC2 배포
- Ubuntu EC2 를 구매한 뒤, Node.js의 포트(3000)를 80번 포트로 포워딩해서 포트 번호 없이도 서비스에 접속 가능하도록 하기
- → iptable을 사용하기
- mongoDB를 EC2 내부에 설치해서 연결하기
app.js 기본 템플릿
import express from 'express';
const app = express();
const PORT = 3000;
// Express에서 req.body에 접근하여 body 데이터를 사용할 수 있도록 설정합니다.
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
const router = express.Router();
router.get('/', (req, res) => {
return res.json({ message: 'Hi!' });
});
app.use('/api', router);
app.listen(PORT, () => {
console.log(PORT, '포트로 서버가 열렸어요!');
});
스키마 설계하기 schema/index.js
// schemas/index.js
import mongoose from 'mongoose';
const connect = () => {
mongoose
.connect(
// 빨간색으로 표시된 부분은 대여한 ID, Password, 주소에 맞게끔 수정해주세요!
'몽고디비 URL 입력 ,
{
dbName: 'notice_board', // todo_memo 데이터베이스명을 사용합니다.
},
)
.then(() => console.log('MongoDB 연결에 성공하였습니다.'))
.catch((err) => console.log(`MongoDB 연결에 실패하였습니다. ${err}`));
};
mongoose.connection.on('error', (err) => {
console.error('MongoDB 연결 에러', err);
});
export default connect;
app.js 파일에서 schema/index.js 가져오기
추가한 내용
import connect from './schmas/index.js'
connect();
import express from 'express';
import connect from './schmas/index.js'
const app = express();
const PORT = 3000;
connect();
// Express에서 req.body에 접근하여 body 데이터를 사용할 수 있도록 설정합니다.
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
const router = express.Router();
router.get('/', (req, res) => {
return res.json({ message: 'Hi!' });
});
app.use('/api', router);
app.listen(PORT, () => {
console.log(PORT, '포트로 서버가 열렸어요!');
});
schema/post.js 만들기
// schemas/post.schema.js
import mongoose from "mongoose";
const postSchema = new mongoose.Schema({
user: {
type: String,
required: true, // 필수요소
},
password: {
type: String,
required: true, // 필수요소
},
title: {
type : String,
required : true, // 필수요소
},
content: {
type : String,
required : true, // 필수요소
},
createAt: {
type: Date, // createAt 필드는 Date 타입을 가집니다.
required: true,
},
});
/*
// 프론트엔드 서빙을 위한 코드입니다. 모르셔도 괜찮아요!
postSchema.virtual("postId").get(function () {
return this._id.toHexString();
});
postSchema.set("toJSON", {
virtuals: true,
});
*/
// postSchema를 바탕으로 post모델을 생성하여, 외부로 내보냅니다.
export default mongoose.model("Schemapost", postSchema);
/routes/post.js 기본 템플릿
// /routes/post.router.js
import express from 'express';
const router = express.Router();
export default router;
app.js 파일에 라우터를 연결
import postRouter from './routes/post.router.js'
app.use('/api', [router, postRouter]);
import express from 'express';
import connect from './schmas/index.js'
import postRouter from './routes/post.router.js'
const app = express();
const PORT = 3000;
connect();
// Express에서 req.body에 접근하여 body 데이터를 사용할 수 있도록 설정합니다.
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
const router = express.Router();
router.get('/', (req, res) => {
return res.json({ message: 'Hi!' });
});
app.use('/api', [router, postRouter]);
app.listen(PORT, () => {
console.log(PORT, '포트로 서버가 열렸어요!');
});
게시판 등록
/* 게시판 등록 API*/
router.post('/posts', async(req,res, next) =>{
// 1. 클라이언트로 받아온 데이터를 가져온다
const {title, user, password , content } = req.body
//1.5 클라이언트가 유저 데이터를 전달하지 않았을때 , 클라아인트에게 에러를 반환
if(!user || !password || !title || !content){
return res.status(400).json({ Message : '데이터 형식이 올바르지 않습니다.'})
}
// newPost 라는 새로운 Schemapost 를 만든다. / post 등록
const newPost = new Schemapost({
user,
password,
title,
content,
createdAt : new Date()
})
// newPost 를 저장한다.
await newPost.save();
// 클라이언트에게 반환한다.
res.status(201).json({message:'개시글을 생성하였습니다'})
//res.status(201).json(newPost);
})
게시판 조회
게시판 을 조회하면 _id 값과 postId 값 _v 값등 안보여야 할 내용들이 보여서
map 을 이용해서 보여줘야할 내용만 보여주도록 수정
/* 게시판 목록 조회 */
router.get('/posts', async(req, res, next) => {
// 게시판 목록 조회 진행
// 게시판 목록에서 createdAt 으로 내림차순해서 정렬한다.
// mongoose 모델 목록조회 . createAt 내림차순
const cheakpost = await Schemapost.find().sort({createdAt : -1}).exec();
//'-createAt'
// 2 해야할 일 목록 조회 결과를 클라이언트에게 반환한다.
// 맵 함수로 postId 로 id 값을 이름바꾸고 보여줘야 할 값만 보여줌
const mapCheakpost = cheakpost.map(post =>({
postId :post._id, // _id 를 postId로 변경
user: post.user,
title : post.title,
createdAt: post.createdAt
}));
return res.status(200).json({ mapCheakpost });
// 오류 수정
// 맵을 돌려서 가공해서 만듬
// 맵으로 _id 를 postId 로 바꿔서 출력
//var widgetSchema = new Schema({ ... attributes ... }, { versionKey: false });
// 언더바 v값을 안보여준다.
});
게시판 상세 조회
게시판 상세조회에서도 마찬가지로 map 함수를 사용해서 수정하려고 했지만. 상세조회는 가지고있는 오브젝트가 하나라서 맵 함수가 작동을 안했다.. 그래서 map 함수를 빼고 그냥 새로운 변수를 만들어 넣어
/* 게시글 상세 조회 */
router.get('/posts/:postId', async(req, res, next) => {
// post 아이디를 찾는다
const {postId} = req.params;
// findById 로 포스트아이디를 가지고 와서 조회
const cheak1post = await Schemapost.findById(postId).exec();
if(!cheak1post){
return res.status(400).json({Massage : '데이터 형식이 올바르지 않습니다.'})
}
const mapCheak1post = {
postId :cheak1post._id,
user: cheak1post.user,
content : cheak1post.content,
createdAt: cheak1post.createdAt
}
return res.status(201).json({mapCheak1post});
})
게시판 수정
/* 게시글 수정 */
router.put('/posts/:postId', async(req, res, next) => {
const {postId} = req.params;
const {password , title, content} = req.body;
// 변수 post = 게시글을 조회해 postId 인 값을 찾음
const post = await Schemapost.findById(postId);
/* 에러 */
// postId 값이 없으면 게시글 조회 실패
if(!post) {
return res.status(404).json({message : '게시글 조회에 실패하였습니다.'})
}
// 비밀번호가 틀리면 데이터 형식이 올바르지 않습니다.
if(post.password !== password){
return res.status(400).json({message : '데이터 형식이 올바르지 않습니다.'})
}
// 변수 post 에 저장된 postId 게시물 의 제목과 컨텐츠
post.title = title;
post.content = content;
// 수정 내용 저장
await post.save();
// 수정이 성공 했을 때 메세지
return res.status(200).json({massege: '게시글이 수정되었습니다.'})
});
게시글 삭제
/* 게시글 삭제 */
router.delete('/posts/:postId', async(req,res,next)=>{
const {postId} = req.params;
const {password} = req.body;
// 개시글을 조회해서 패스워드 값을 찾음
const deletepost = await Schemapost.findById(postId).exec();
/* 에러 */
if(!deletepost){
return res.status(404).json({message : '게시글 조회에 실패하였습니다.'})
}
if(deletepost.password !== password){
return res.status(400).json({message : '데이터 형식이 올바르지 않습니다.'})
}
//실제 삭제
await deletepost.deleteOne({password: postId});
// 삭제되고 난후 서버에 메세지 출력
return res.status(200).json({message : '게시글을 삭제하였습니다.'});
});
마지막으로
댓글을 만드는 것까지 있지만 아직 작성이 안되어 내일 작성 후 최종 으로 완성된 게시판 + 댓글 작성 및 수정 삭제 를 올릴 예정
'node.js' 카테고리의 다른 글
| 게시판 만들기 (완성버전) (0) | 2023.08.29 |
|---|---|
| 게시판만들기 (2) 댓글창 만들기 (0) | 2023.08.29 |
| 비즈니스 로직이란? (0) | 2023.08.27 |
| REST API 개발하기 (0) | 2023.08.27 |
| 2. HTTP Method (GET, POST, PUT, DELETE) (0) | 2023.08.27 |