요약정리
백엔드에서 함수 작성(이해를 많이 하고 넘어갈 부분이 많음.)
다음글, 이전글, 게시물 수정, 게시글 삭제, 조회수 증가
포스트맨에서 확인(날릴때 쿼리로 날리는지, 바디로 날리는지, 폼인지 확인)
BoardSelect.vue(ui, 조회수 증가 이동, 글쓰기, 검색어)
BoardSelectOne.vue(ui, row1참조, row2활용 수정시 유용하게 활용, 삭제, 수정, 이전글, 다음글, 목록)
수정시 해당 화면에서 바로 바꾸고 put함. row1과 row2활용 이전글, 다음글 v-if문 사용 버튼 없애기
게시물 상세페이지로 이동시 쿼리로 넘버만 보내주고 해당 페이지에서 핸들 데이터를 이용하여 정보를 받아옴.
(나는 정보 미리 받고 넘어가게 만들었다가 고침)
오전
exp
조회수 증감
쿼리로 날린다 127.0.0.1:3000/board/updatehit.json?no=34
바디로 날린다 사진 참고 { "no" : 20 } (포스트맨에서 body raw json)
// 조회수 증가
// 127.0.0.1:3000/board/updatehit.json?no=34
// 쿼리나, 바디로 받아와서 증감
// req.query.no로 증가할 게시물 번호를 전달받음.
router.put('/updatehit.json', async function(req, res, next) {
try{
// 1. 전달되는 값을 받음
const no = Number(req.query.no);
// 2. DB변경을 위한 조건 설정
const query = {_id:no} // 언더바 아이디와 일치하는 것 가져와라
// 3. DB변경 할 내용 설정 $inc 증가 명령어(몽고디비언어)
const update = { $inc : {hit : 11} } // 조회수를 11씩 증가시켜라
// 4. DB적용
const result = await Board.updateOne(query, update);
// 5. 결과확인
console.log(result);
// 6. 결과값에 따른 전달값 설정
if(result.modifiedCount === 1){ // 임의로 하는게 아님 키를 확인하고 하는 것.
//포스트맨으로 서버에 날려보면 바뀐 것이 있으면 modifiedCount:1이뜸
return res.send({status:200});
}
return res.send({status:0});
}
catch(e){
// 1~6까지 수행시 오류가 발생한 경우 수행됨.
console.error(e);
return res.send({status:-1, result:e});
}
});
https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=ahnkhoon&logNo=220724030735
ModifiedCount() 조회수가 바뀌었는지 확인 해봄 1이면 바뀐거고 0이면 바뀐 것이 없다는 것.
쿼리로했음.(?no=)
항상 테스트를 해야함 result가 어떻게 나오는지
그리고 if문을 사용하여 조건문 작성
// 6. 결과값에 따른 전달값 설정
if(result.modifiedCount === 1){ // 임의로 하는게 아님 키를 확인하고 하는 것.
//포스트맨으로 서버에 날려보면 바뀐 것이 있으면 modifiedCount:1이뜸
return res.send({status:200});
}
return res.send({status:0});
delete
// 게시물 삭제
// 127.0.0.1:3000/board/delete.json
// {"no" : 33}
router.delete('/delete.json', async function(req, res, next) {
try{
// 1. 전달되는 값을 받음
const no = Number(req.body.no);
// 2. 삭제 조건
const query = {_id:no}; // 언더바 아이디와 일치하는 것 가져와라
// 3. DB에 삭제 수행
const result = await Board.deleteOne(query);
//4. 수행결과 확인 { acknowledged: true, deletedCount: 1 }
console.log(result);
// 5. 수행결과에 따른 결과값 리턴
if(result.deletedCount === 1){
// 성공시 cmd 백엔드에 deletedCount가 1이 뜸
// return 있으면 종료
return res.send({status:200});
}
return res.send({status:0});
}
catch(e){
// 1~6까지 수행시 오류가 발생한 경우 수행됨.
console.error(e);
return res.send({status:-1, result:e});
}
});
DeletedCount() 이게 1이상으로 와야 삭제되었다는 것임.
바디로함
const result = await Board.deleteOne(query);
deletemany는 여러개 삭제할때
삭제는 바디로 주소에 안보이게 보내는 경우가 대다수
수정
update
보내주는 데이터 형태 주목 body raw json
// 게시물 수정(selectone을 가져오면 쉽다)
// 127.0.0.1:3000/board/update.json
// 포스트맨 => {"no":3, "title":"변경1", "content":"변경2", "writer":"변경3"}
// vue3 => {no:3, title:"변경1", content:"변경2", writer:"변경3"}
router.put('/update.json', async function(req, res, next) {
try{
// 1. 전달값 받기(4개)
const no = Number(req.body.no);
const ti = req.body.title;
const co = req.body.content;
const wr = req.body.writer;
// 2. DB 변경할 항목에 대한 조건
const query = {_id : no};
// 3. DB에서 기존 데이터 가져오기
const obj = await Board.findOne(query);
// 4. 가져온 데이터에서 수정항목 변경
obj.title = ti;
obj.content = co;
obj.writer = wr;
// 5. obj값을 다시 저장(_id항목은 변경하지 않았기 때문에 수정이 되는 것임. 넘버는 그대로 내용을 덮어쓰는 것.)
const result = await obj.save();
// 6. 결과값 확인
console.log(result);
// 7. 리턴결과
if(result !== null) {
return res.send( {status:200} );
}
return res.send( {status:0} );
}
catch(e){
// 수행시 오류가 발생한 경우 수행됨.
console.error(e);
return res.send({status:-1, result:e});
}
});
해당 넘버의 req.body(새로운 정보바디)를 들고와서 obj(기존 글 정보)에 넣고 세이브
결과에 따른 status 200 출력이 다른 것들과 다름
이전글
// 이전글
// 127.0.0.1:3000/board/prevno.json?no=5
// 현재번호가 중심이기 때문에 쿼리가 있어야함
router.get('/prevno.json', async function(req, res, next) {
try{
// 1. 현재 글번호 받기
const no =Number(req.query.no);
// 2. 조회 조건
// 비교연산자로 작다는 것을 못넣음. 그래서 만들어진 명령어 사용
// $lt 작다. 미만
// $lte 작거나 같다. 이하
// $gt 크다. 초과
// $gte 크거나 같다. 이상
const query = { _id : { $lt : no}};
// 3. 조건에 의한 조회
// 내림차수 정렬하고 아래 것들 중에서 1개만 가져와라
// 필요한 것만 꺼내는 것 projection 프로젝션
const projection = {_id : 1}
const result = await Board.find(query, projection).sort({_id:-1}).limit(1);
// 4. 결과확인
// 있으면 [ { _id: 4 } ]
// 없으면(0번째 글) []
// const arr = [{id:'a', name:'b'}, {id:"c", name:"d"}]
// d꺼낼려면 console.log(arr[1].name)
console.log(result);
if(result.length > 0){
return res.send({status:200, prevno: result[0]._id})
}
return res.send({status:0});
}
catch(e){
console.error(e);
return res.send({status:-1, result:e});
}
});
findOne을 쓰면 안됨
전체 다 들고 와야해서 find
내림차수 정렬하고 아래 것들 중에서 1개만 가져와라
const projection = {_id : 1}
const result = await Board.find(query, projection).sort({_id:-1}).limit(1);
이전글 코드에 메모 중요
다음글(실습 직접 만든 것)
// 다음글
// 127.0.0.1:3000/board/nextno.json?no=5
router.get('/nextno.json', async function(req, res, next) {
try{
// 1. 현재 글번호 받기
const no =Number(req.query.no);
// 2. 조회 조건
const query = { _id : { $gt : no}};
// 3. 조건에 의한 조회
const projection = {_id : 1}
const result = await Board.find(query, projection).sort({_id:1}).limit(1);
// 4. 결과확인
console.log(result);
if(result.length > 0){
return res.send({status:200, nextno: result[0]._id})
}
return res.send({status:0});
}
catch(e){
console.error(e);
return res.send({status:-1, result:e});
}
});
\\\\\\\\\\\\\\\\\\\\\\
vue_20220711
boardselect
컨텐츠로 넘어갈때 쿼리로 넘버만 보내준걸로 수정함.(나는 정보를 받고 넘어가는 걸로 만들었었음.)
조회수 증가이후 이동
const handleContent = async( tmp ) =>{
// 조회수 증가후에 이동
const url=`/board/updatehit.json?no=${tmp}`;
const headers={"Content-Type":"application/json"};
const body = {};
const {data} = await axios.put(url, body, {headers});
if(data.status === 200){
// /boardselectone?no=23
console.log('handleContent => ', tmp);
router.push({path:'/boardselectone', query:{ no : tmp }});
}
};
BoardSelectOne.vue
<template>
<div>
<div v-show="state.isUpdate === false">
<h3>게시물 상세</h3>
{{ state }} <!-- 처음에 해놓는게 좋음 -->
<div v-if="state.row">
글번호 : {{state.row._id}} <br/>
제목 : {{state.row.title}} <br/>
제목 : {{state.row.content}} <br/>
작성자 : {{state.row.writer}} <br/>
조회수 : {{state.row.hit}} <br/>
등록일 : {{state.row.regdate}} <br/>
<img :src="state.imageurl" style="width:150px"/> <br/>
<hr />
<button @click="handleDelete">삭제</button>
<button @click="state.isUpdate = true">수정</button>
<button @click="handlePrevAction" v-if="state.prevno > 0">이전글</button>
<button @click="handleNextAction" v-if="state.nextno > 0">다음글</button>
<router-link to ="/boardselect">
<button>목록</button>
</router-link>
</div>
</div>
<div v-show="state.isUpdate === true">
<h3>게시물 수정</h3>
<div>
<label class="lbl">제목</label>
<input type="text" v-model="state.row1.title" />
</div>
<div>
<label class="lbl">내용</label>
<textarea rows="6" v-model="state.row1.content"></textarea>
</div>
<div>
<label class="lbl">작성자</label>
<input type="text" v-model="state.row1.writer"/>
</div>
<div>
<label class="lbl">이미지</label>
<img :src="state.img" style="width:150px"/>
<input type="file" @change="handleImage($event)"/>
</div>
<hr/>
<button @click="handleUpdate">수정하기</button>
<button @click="state.isUpdate = false">취소</button>
</div>
</div>
</template>
<script>
import { reactive } from '@vue/reactivity'
import { useRoute, useRouter } from 'vue-router'
import { onMounted } from '@vue/runtime-core';
import axios from 'axios';
export default {
setup () {
const route = useRoute();
const router = useRouter();
const state = reactive({
no : Number( route.query.no ),
row : '', // 상세 내용에 씀
row1 : '', // 수정 내용에 씀
imageurl : '',
isUpdate: false,
prevno: 0,
nextno: 0,
});
onMounted(() => {
handleData();
handlePrev();
handleNext();
});
const handleData = async() => {
const url = `/board/selectone.json?no=${state.no}`;
const headers = {"Content-Type":"application/json"};
const { data } = await axios.get(url, {headers});
console.log(data);
if(data.status === 200){
// 참조
// data.result === state.row가 참조
state.row = data.result; //내용 표시용
// state.row1 = data.result; //내용 표시용
// 내용복사
state.row1 = { ...data.result }; // 수정시 사용
state.imageurl = data.image;
}
};
const handleUpdate = async() => {
const url = `board/update.json`;
const headers = {"Content-Type":"application/json"};
const body = {
no : state.no,
title : state.row1.title,
content : state.row1.content,
writer : state.row1.writer
};
const {data} = await axios.put(url, body, {headers});
console.log(data);
if(data.status === 200){
alert('게시물 수정 완료')
state.isUpdate = false;
handleData();
handlePrev();
handleNext();
}
};
const handleDelete = async() => {
if(confirm('삭제할까요?')){
const url = `board/delete.json`;
const body = {
no : state.no
}
const headers = {"Content-Type":"application/json"};
const response = await axios.delete(url, {headers:headers, data:body});
if(response.data.status === 200){
alert('삭제되었습니다.')
router.push({path:'boardselect'});
}
}
};
const handlePrev = async() => {
const url = `/board/prevno.json?no=${state.no}`;
const headers = {"Content-Type":"application/json"};
const { data } = await axios.get(url, {headers});
console.log(data);
if(data.status === 200){
state.prevno = data.prevno;
}
// handleData();
// router.push({path:"/boardselectone", query:{no:state.no}})
else if(data.status === 0){
state.prevno = 0;
}
};
const handleNext = async() => {
const url = `/board/nextno.json?no=${state.no}`;
const headers = {"Content-Type":"application/json"};
const { data } = await axios.get(url, {headers});
console.log(data);
if(data.status === 200){
state.nextno = data.nextno;
// handleData();
// router.push({path:"/boardselectone", query:{no:state.no}})
}
else if(data.status === 0){
state.nextno = 0;
}
};
const handlePrevAction = () => {
state.no = state.prevno; //이전글번호를 현재번호로 변경
handlePrev();
handleNext();
handleData();
router.push({path:"/boardselectone", query:{no:state.no}});
};
const handleNextAction = () => {
state.no = state.nextno; //이전글번호를 현재번호로 변경
handlePrev();
handleNext();
handleData();
router.push({path:"/boardselectone", query:{no:state.no}});
};
return {state, handleUpdate, handleDelete, handlePrev, handleNext, handlePrevAction, handleNextAction}
}
}
</script>
<style lang="css" scoped>
.container {
width: 600px;
border: 1px solid #cccccc;
padding:20px;
}
.lbl {
display: inline-block;
width: 90px;
}
</style>
시험인데 미리 만들어봄
----------------------------------------------------------
exp_20220711>routes>board.js
var express = require('express');
var router = express.Router();
// npm i multer --save
const multer = require('multer')
// 첨부되어 오는 파일을 저장하는 방식 ex)파일로 저장, 메모리로 저장
// 여기서는 데이터 베이스에 저장해야하기 때문에 메모리로 저장
const upload = multer({storage : multer.memoryStorage()});
// npm i moment
// npm i moment-timezone --save
require('moment-timezone');
var moment = require('moment');
moment.tz.setDefault('Asia/Seoul'); // 표준시 UTC 시간, 아시아.서울로 설정
//db연동을 위한 모델 ORM
var Board = require('../models/boardmodel');
// 다음글
// 127.0.0.1:3000/board/nextno.json?no=5
router.get('/nextno.json', async function(req, res, next) {
try{
// 1. 현재 글번호 받기
const no =Number(req.query.no);
// 2. 조회 조건
const query = { _id : { $gt : no}};
// 3. 조건에 의한 조회
const projection = {_id : 1}
const result = await Board.find(query, projection).sort({_id:1}).limit(1);
// 4. 결과확인
console.log(result);
if(result.length > 0){
return res.send({status:200, nextno: result[0]._id})
}
return res.send({status:0});
}
catch(e){
console.error(e);
return res.send({status:-1, result:e});
}
});
// 이전글
// 127.0.0.1:3000/board/prevno.json?no=5
// 현재번호가 중심이기 때문에 쿼리가 있어야함
router.get('/prevno.json', async function(req, res, next) {
try{
// 1. 현재 글번호 받기
const no =Number(req.query.no);
// 2. 조회 조건
// 비교연산자로 작다는 것을 못넣음. 그래서 만들어진 명령어 사용
// $lt 작다. 미만
// $lte 작거나 같다. 이하
// $gt 크다. 초과
// $gte 크거나 같다. 이상
const query = { _id : { $lt : no}};
// 3. 조건에 의한 조회
// 내림차수 정렬하고 아래 것들 중에서 1개만 가져와라
// 필요한 것만 꺼내는 것 projection 프로젝션
const projection = {_id : 1}
const result = await Board.find(query, projection).sort({_id:-1}).limit(1);
// 4. 결과확인
// 있으면 [ { _id: 4 } ]
// 없으면(0번째 글) []
// const arr = [{id:'a', name:'b'}, {id:"c", name:"d"}]
// d꺼낼려면 console.log(arr[1].name)
console.log(result);
if(result.length > 0){
return res.send({status:200, prevno: result[0]._id})
}
return res.send({status:0});
}
catch(e){
console.error(e);
return res.send({status:-1, result:e});
}
});
// 게시물 수정(selectone을 가져오면 쉽다)
// 127.0.0.1:3000/board/update.json
// 포스트맨 => {"no":3, "title":"변경1", "content":"변경2", "writer":"변경3"}
// vue3 => {no:3, title:"변경1", content:"변경2", writer:"변경3"}
router.put('/update.json', async function(req, res, next) {
try{
// 1. 전달값 받기(4개)
const no = Number(req.body.no);
const ti = req.body.title;
const co = req.body.content;
const wr = req.body.writer;
// 2. DB 변경할 항목에 대한 조건
const query = {_id : no};
// 3. DB에서 기존 데이터 가져오기
const obj = await Board.findOne(query);
// 4. 가져온 데이터에서 수정항목 변경
obj.title = ti;
obj.content = co;
obj.writer = wr;
// 5. obj값을 다시 저장(_id항목은 변경하지 않았기 때문에 수정이 되는 것임. 넘버는 그대로 내용을 덮어쓰는 것.)
const result = await obj.save();
// 6. 결과값 확인
console.log(result);
// 7. 리턴결과
if(result !== null) {
return res.send( {status:200} );
}
return res.send( {status:0} );
}
catch(e){
// 수행시 오류가 발생한 경우 수행됨.
console.error(e);
return res.send({status:-1, result:e});
}
});
// 게시물 삭제
// 127.0.0.1:3000/board/delete.json
// {"no" : 33}
router.delete('/delete.json', async function(req, res, next) {
try{
// 1. 전달되는 값을 받음
const no = Number(req.body.no);
// 2. 삭제 조건
const query = {_id:no}; // 언더바 아이디와 일치하는 것 가져와라
// 3. DB에 삭제 수행
const result = await Board.deleteOne(query);
//4. 수행결과 확인 { acknowledged: true, deletedCount: 1 }
console.log(result);
// 5. 수행결과에 따른 결과값 리턴
if(result.deletedCount === 1){
// 성공시 cmd 백엔드에 deletedCount가 1이 뜸
// return 있으면 종료
return res.send({status:200});
}
return res.send({status:0});
}
catch(e){
// 1~6까지 수행시 오류가 발생한 경우 수행됨.
console.error(e);
return res.send({status:-1, result:e});
}
});
// 조회수 증가
// 127.0.0.1:3000/board/updatehit.json?no=34
// 쿼리나, 바디로 받아와서 증감
// req.query.no로 증가할 게시물 번호를 전달받음.
router.put('/updatehit.json', async function(req, res, next) {
try{
// 1. 전달되는 값을 받음
const no = Number(req.query.no);
// 2. DB변경을 위한 조건 설정
const query = {_id:no} // 언더바 아이디와 일치하는 것 가져와라
// 3. DB변경 할 내용 설정 $inc 증가 명령어(몽고디비언어)
const update = { $inc : {hit : 11} } // 조회수를 11씩 증가시켜라
// 4. DB적용
const result = await Board.updateOne(query, update);
// 5. 결과확인
console.log(result);
// 6. 결과값에 따른 전달값 설정
if(result.modifiedCount === 1){ // 임의로 하는게 아님 키를 확인하고 하는 것.
//포스트맨으로 서버에 날려보면 바뀐 것이 있으면 modifiedCount:1이뜸
return res.send({status:200});
}
return res.send({status:0});
}
catch(e){
// 1~6까지 수행시 오류가 발생한 경우 수행됨.
console.error(e);
return res.send({status:-1, result:e});
}
});
//127.0.0.1:3000/board/image?no=4
//<img src="/board/image?no=4" style"width:50px" /> 뷰에서는 이렇게 쓸 예정
router.get('/image', async function(req, res, next) {
try{
const no = Number(req.query.no);
const query = {_id:no};
const projection = { filedata:1, filesize:1, filetype:1, filename:1};
const result = await Board.findOne(query).select(projection);
console.log(result);
res.contentType(result.filetype); // contentType변경
return res.send(result.filedata); // 파일데이터
}
catch(e){
console.error(e);
return res.send({status:-1, result:e});
}
});
// 127.0.0.1:3000/board/selectone.json?no=5
router.get('/selectone.json', async function(req, res, next) {
try{
const no =Number(req.query.no); //5
const query = {_id:no};
const projection = {filedata:0, filesize:0, filetype:0, filename:0};
const result = await Board.findOne(query).select(projection)
if(result !== null){
return res.send({status:200, result:result, image:'/board/image?no='+no});
}
return res.send({status:0})
}
catch(e){
console.error(e);
return res.send({status:-1, result:e});
}
});
// 127.0.0.1:3000/board/select.json?page=5&text=a
router.get('/select.json', async function(req, res, next) {
try{
const page =Number(req.query.page); //5
const text = req.query.text; //a
//1페이지이면 점프 10개
//2페이지이면 점프 20개
const query = {title: new RegExp(text,'i')};
const projection = {_id:1, title:1, writer:1, hit:1, regdate:1}
const sort = {_id:-1}; //오름차수는 1 내림은 -1
const result = await Board.find(query,projection)
.sort(sort).skip((page-1)*10).limit(10); // 조건이 들어와야함, 가져올 항목 중요
const total = await Board.countDocuments(query);
if(result !== null){
return res.send({status:200, result:result, total:total});
}
return res.send({status:0})
}
catch(e){
console.error(e);
return res.send({status:-1, result:e});
}
});
// 크롬에서 127.0.0.1:3000/board/insert.json
//{"title":"aaa", "content":"bbb", "wirter":"ccc", "flile":첨부파일}
//파일 넣을꺼면 upload.sing("") 넣어줘야함
router.post('/insert.json', upload.single("file"), async function(req, res, next) {
try{
console.log(req.body); //db cmd보고 body로 전달 되는 것을 확인함
console.log(req.file); //마찬가지 flile로 오는 것을 확인함
var obj = new Board(); // 빈 객체를 생성
obj.title = req.body.title;
obj.content = req.body.content;
obj.writer = req.body.writer;
obj.regdate = moment().format('YYYY-MM-DD HH:mm:ss');
obj.filedata = req.file.buffer;
obj.filename = req.file.originalname;
obj.filetype = req.file.mimetype;
obj.filesize = req.file.size;
const result = await obj.save();
if(result !== null){
return res.send({status:200})
}
return res.send({status:0})
}
catch(e){
console.error(e);
return res.send({status:-1, result:e});
}
});
module.exports = router;
BoardSelect.vue
<template>
<div>
<h3>게시판 목록</h3>
<router-link :to="{path:'/boardinsert'}">글쓰기</router-link>
<input type="text" placeholder="검색어"
v-model="state.text" @keyup.enter="handleText()" />
<table border="1">
<tr>
<th>번호</th>
<th>제목</th>
<th>작성자</th>
<th>조회수</th>
<th>날짜</th>
</tr>
<tr v-for="tmp of state.rows" :key="tmp">
<td v-text="tmp._id"></td>
<td v-text="tmp.title"
style="cursor: pointer;"
@click="handleContent( tmp._id )"></td>
<td v-text="tmp.writer"></td>
<td v-text="tmp.hit"></td>
<td v-text="tmp.regdate"></td>
</tr>
</table>
<div v-for="tmp of state.pages" :key="tmp"
style="display:inline-block">
<button v-text="tmp" @click="handlePage(tmp)"></button>
</div>
</div>
</template>
<script>
import { reactive } from '@vue/reactivity'
import { onMounted } from '@vue/runtime-core';
import axios from 'axios';
import { useRouter } from 'vue-router';
export default {
setup () {
const router = useRouter();
const state = reactive({
page : 1,
text : '',
rows : [],
total : 0,
pages : 0,
});
const handleData = async() => {
const url = `/board/select.json?page=${state.page}&text=${state.text}`;
const headers={"Content-Type":"application/json"};
const { data } = await axios.get(url, {headers});
console.log(data);
if(data.status === 200){
state.rows = data.result; // 게시물 내용
state.total = data.total; // 개시물 개수
//21 => (21-1)/10 + 1 => 3 // 페이지수 계산
state.pages = Math.floor((data.total-1)/10) +1;
}
};
const handlePage = (tmp) =>{
state.page = tmp;
handleData();
};
const handleText = () => {
state.page = 1;
handleData();
};
onMounted(() => {
handleData();
});
const handleContent = async( tmp ) =>{
// 조회수 증가후에 이동
const url=`/board/updatehit.json?no=${tmp}`;
const headers={"Content-Type":"application/json"};
const body = {};
const {data} = await axios.put(url, body, {headers});
if(data.status === 200){
// /boardselectone?no=23
console.log('handleContent => ', tmp);
router.push({path:'/boardselectone', query:{ no : tmp }});
}
};
return {state, handlePage, handleText, handleContent}
}
}
</script>
<style lang="css" scoped>
</style>
배열
// const arr = [{id:'a', name:'b'}, {id:"c", name:"d"}]
// d꺼낼려면 console.log(arr[1].name)
'mongoDB + Postman + vue' 카테고리의 다른 글
국비 코딩 풀스택 수업 20일차(백엔드 for문 질문했음) (0) | 2022.07.19 |
---|---|
국비 코딩 풀스택 수업 19일차 (0) | 2022.07.18 |
국비 코딩 풀스택 수업 18일차 (0) | 2022.07.15 |
국비 코딩 풀스택 수업 17일차 (0) | 2022.07.14 |
국비 코딩 풀스택 수업 14일차 (0) | 2022.07.11 |