유튜브
회원
- 로그인
- 회원가입
- 회원정보조회
- 회원탈퇴
회원은 계정 1개당 채널 100개를 가질 수 있다.
채널
- 채널 생성
- 채널 수정
- 채널 삭제
회원 API 설계
- 로그인 POST /login
- req : body (id,pwd)
- res : 000님 환영합니다 , 메인페이지
- 회원가입 POST /join
- req : body(id, pwd, name)
- res : 000님 환영합니다 ,로그인 페이지
- 회원정보(개별)조회 GET /users/:id
- req : URL (id)
- res : id,name
- 회원 개별 탈퇴 DELETE /users/:id
- req : URL(id)
- res : 000님 다음에 또 뵙겠습니다. 메인페이지
express환경을 셋팅해준 다음 db Map객체를 선언하고 id를 전역적으로 선언해주겠습니다. app.use(express.json())을 코드 상단에 선언해주겠습니다.
// express 모듈 셋팅
const express = require('express')
const app = express()
app.listen(7777)
app.use(express.json())
let db = new Map()
var id = 1
회원가입
먼저 회원가입api입니다. set함수를 사용해 저장해주었고 201상태코드를 보내주어 생성되었다는걸 알려줍니다.
예외처리도 400상태코드를 출력해주었습니다. 즉 body에 값이 없을때 400에러를 출력합니다.
여기서 사용자가 아무런 데이터도 입력하지 않았을때 {} 값이 들어오는데 이값을 Object.keys().length(Object.keys(객체)-> 프로퍼티들을 배열에 담아 반환)를 이용해 체크해주었습니다.
app.post('/join',(req,res)=>{
console.log(req.body);
if(Object.keys(req.body).length)
{
db.set(id++, req.body)
res.status(201).json({
message:`${db.get(id-1).name}님 환영합니다.`
})
}else{
res.status(400).json({
message:`입력 값을 다시 확인해주세요`
})
}
})
회원정보조회
회원정보개별조회 api입니다. get메소드를 사용하였고 url의 id를 받아서 db 맵객체에서 꺼내주었습니다. 꺼냈을때 값이 있으면 200과 user의 id,name을 없으면 404를 리턴해주었습니다.
//회원 개별 조회
app.get('/users/:id', (req,res)=>{
let {id} = req.params;
id=parseInt(id);
let user = db.get(id);
if(user)
{
res.status(200).json({
userId : user.id,
name:user.name
})
}
else{
res.status(404).json({
message:`해당 회원이 없습니다.`
})
}
})
결과입니다. join post를 이용해 회원가입을 먼저 진행하고 get을 하였습니다.
회원탈퇴
회원개별탈퇴입니다. 마찬가지로 url에 id를 받고 db 맵객체를 get으로꺼낸후 데이터가 있으면 200을 없으면 404를 리턴해주었습니다.
//회원 개별 탈퇴
app.delete('/users/:id',(req,res)=>{
let id = Number(req.params.id);
const user = db.get(id);
if(user)
{
db.delete(id);
res.status(200).json({
message:`${user.name}님 다음에 또 뵙겠습니다. 메인페이지`
})
}
else{
res.status(404).json({
message:`삭제할 회원이 없습니다`
})
}
})
결과입니다. 먼저 join post를 사용해 회원가입을 한 후 탈퇴를 하였습니다.
router
현재 회원정보조회와 회원탈퇴 api를 보면 url이같은걸 알 수 있습니다. 여기서 router를 사용하면 효율적으로 작성할 수 있습니다.
app
.route('/users/:id')
.get((req, res) => {
let { id } = req.params;
id = parseInt(id);
let user = db.get(id);
if (user) {
res.status(200).json({
userId: user.id,
name: user.name
})
}
else {
res.status(404).json({
message: `해당 회원이 없습니다.`
})
}
})
.delete((req, res) => {
let id = Number(req.params.id);
const user = db.get(id);
if (user) {
db.delete(id);
res.status(200).json({
message: `${user.name}님 다음에 또 뵙겠습니다. 메인페이지`
})
}
else {
res.status(404).json({
message: `삭제할 회원이 없습니다`
})
}
})
로그인
빈객체확인하는방법3가지
- 객체.keys()
- for
- lodash : isEmpty
body에 아무런 값도 없는 경우를 체크하기 위해 Object.keys(객체).length를 이용해 체크해주었습니다. 클린코드를 짜기 위해 해당 부분을 함수로 따로 만들어주었습니다.
//로그인
app.post('/login', (req, res) => {
let loginUser ={}
const {id,pwd}=req.body
db.forEach((value, key) => {
if (id == value.id) {
hasUserId=true
loginUser=value;
}
})
if(isExist(loginUser)){
if(pwd===loginUser.pwd){
res.status(200).json({
message:"성공"
})
}
}
else{
res.status(404).json({
message:"실패"
})
}
})
function isExist(obj){
if(Object.keys(obj).length){
return true;
}
else{
return false;
}
}
join으로 회원가입 post를 먼저 한 후 login post를 해주었습니다.
채널
- 채널 생성 : POST /channels
- req : body(channelTitle)
- res 201 : (channelTitle)님 채널을 응원합니다.
- 채널 수정 : PUT /channels/:id
- req : URL(id) , body(channelTitle)
- res 200 : "채널명이 성공적으로 수정되었습니다. 기존 () -> 수정 () "
- 채널 삭제 : DELETE /channels/:id
- req : URL(id)
- res 200 : "삭제 되었습니다 " -> 메인페이지
- 채널 전체 조회 : GET /channels
- req : X
- res 200 : 채널 전체 데이터 list, json array
- 채널 개별 조회 : GET /channels/:id
- req : URL(id)
- res 200 : 채널 개별 데이터
먼저 express 환경셋팅을 해주겠습니다.
//express 모듈 셋팅
const express = require('express')
const app = express()
app.listen(7777)
app.use(express.json())
let db = new Map()
let id = 1
채널생성
먼저 채널생성입니다. 사용자가 Body에 값을 실어서 요청하지 않았을 경우 예외처리 해주었습니다.
Object.keys(객체).length를 이용해 Body에 값이 있는지 없는지 체크 해주었습니다.
//채널생성
app.post('/channels', (req,res)=>{
console.log('채널생성');
if(Object.keys(req.body).length)
{
db.set(id++,req.body)
res.status(201).json({
message:`${req.body.channelTitle}님 채널을 응원합니다.`
})
}
else{
res.status(400).json({
message:`채널명을 확인해주세요`
})
}
})
채널 개별조회
채널개별조회입니다. url의 id를 받아서 Map 객체에서 get으로 꺼내주었습니다. 꺼냈을때 값이 있으면 200코드와 함께 조회된 채널명을 출력해주었고 예외처리로 400코드를 출력해주었습니다.
//채널 개별 조회
app.get('/channels/:id',(req,res)=>{
console.log('전체 채널 조회')
let channel = [];
db.forEach((value, index) => {
channel.push(value);
})
console.log(channel);
if (db.size >= 1) {
res.status(200).json(channel)
}
else {
res.status(404).json({
message: `채널이 없습니다 `
})
}
})
채널 전체조회
채널전체조회입니다. 전체채널을 배열로 리턴해주고 싶었습니다. 그러기 위해서는 db 맵객체를 forEach문으로 돌면서 channel이라는 배열에 push 해주었습니다. for문을 다 돌고 db 맵객체의 사이즈가 1보다크면 즉, 유튜브채널이 존재하면 채널들을 리턴해주었고 채널이 존재하지않으면 "채널이없습니다"를 리턴해주었습니다.
//전체 채널 조회
app.get('/channels', (req,res)=>{
console.log('전체 채널 조회')
let channel = [];
db.forEach((value, index) => {
channel.push(value);
})
console.log(channel);
if (db.size >= 1) {
res.status(200).json(channel)
}
else {
res.status(404).json({
message: `채널이 없습니다 `
})
}
})
채널수정
채널수정입니다. 채널이 수정되었을때 000(이전채널명)채널명이 성공적으로 000(새로운채널명)으로 수정되었습니다 문구를 출력하고싶었습니다. 따라서 url의 id로 받은 값을 이용해 db 맵객체의 get을 할때 채널명을 beforeTitle에 저장해주었습니다. 만약 수정하고자하는 채널이 존재하면 200상태코드와 함께 문구를 출력해주었씁니다. 채널이 존재하지 않으면 400상태코드와 함께 문구를 출력하였습니다.
//채널수정
app.put((req, res) => {
console.log('채널 수정')
let { id } = req.params
id = Number(id);
let channel = db.get(id);
let beforeTitle = channel.channelTitle
if (channel) {
db.set(id, req.body);
res.status(200).json({
message: `${beforeTitle}채널명이 성공적으로 ${db.get(id).channelTitle}로 수정되었습니다`
})
}
else {
res.status(404).json({
message: `수정하고자 하는 채널을 확인해주세요`
})
}
})
채널삭제
채널삭제입니다. delete메소드를 사용하였고 삭제하고자 하는 채널이 존재하면 200상태코드와 함께 문구를 그리고 삭제하고자 하는 채널이 없으면 400상태코드와 함께 문구를 리턴해주었습니다.
//채널삭제
app.delete((req, res) => {
console.log('채널 삭제')
let { id } = req.params
id = Number(id)
let channel = db.get(id)
if (channel) {
db.delete(id)
res.status(200).json({
message: `${channel.channelTitle}이 삭제되었습니다`
})
}
else {
res.status(404).json({
message: `삭제되지않았습니다`
})
}
})
route 적용
현재 위의 채널 api url을 보면 중복된 부분이 많습니다. 따라서 url에 따라서 라우트를 설정해주겠습니다. 크게 2가지의 라우트로 설정됩니다.
- app.route('/channels') -> .get() 채널전체조회, .post() 채널 개별생성
- app.route('/channels/:id') -> .get() 채널개별조회, .delete()채널개별삭제, .put()채널개별수정
먼저 app.route('/channels;) 입니다.
app
.route('/channels')
//채널 전체 조회
.get((req, res) => {
console.log('전체 채널 조회')
let channel = [];
db.forEach((value, index) => {
channel.push(value);
})
console.log(channel);
if (db.size >= 1) {
res.status(200).json(channel)
}
else {
res.status(404).json({
message: `채널이 없습니다 `
})
}
})
//채널 개별 생성
.post((req, res) => {
console.log('채널생성');
if (Object.keys(req.body).length) {
db.set(id++, req.body)
res.status(201).json({
message: `${req.body.channelTitle}님 채널을 응원합니다.`
})
}
else {
res.status(400).json({
message: `채널명을 확인해주세요`
})
}
})
router
현재 프로젝트를 보면 user-demo.js와 channel-demo.js 이렇게 2개 파일에 각각 유저에 관한 api와 채널에관한 api로나뉘어져있습니다. 그래서 하나의 데모만 실행시켜 api를 확인할 수 있습니다. 즉 무슨말이냐면 두개의 데모를 함께 실행할 수 없다는 점입니다. 그래서 두개의 데모를 합치기 위해 router에 대해 알아보겠습니다.
Node.js에서의 라우팅이란?
- Request(요청)이 날라왔을때, 원하는 경로에 따라 적절한 방향으로 경로를 안내해주는 것
현재 각각의 데모에서 라우팅을 설정해주긴 했습니다. 2개의 파일을 합쳐서 라우팅해주겠습니다.
먼저 routes라는 폴더를 만들어주고 app.js를 만들어 코드(express 환경셋팅)를 입력합니다. 앞으로 app.js에서 서버를 셋팅해주겠습니다. 두개의 데모에서는 express서버를 셋팅할 필요가 없어졌습니다.
방금 만든 app.js에서 두개의 데모를 모듈처럼 불러올 것입니다. 그러기 위해서는 두개의 데모를 모듈로 만들어줘야합니다. 먼저 user-demo.js를 모듈로 만들어주겠습니다. const app이 아닌 const router를 사용할 것 입니다. 그래서 app부분을 모두 router로 변경해줍니다. 수정된 코드입니다.
// express 모듈 셋팅
const express = require('express')
const router = express.Router()
router.use(express.json())
let db = new Map()
var id = 1
//로그인
router.post('/login', (req, res) => {
let loginUser ={}
const {id,pwd}=req.body
db.forEach((value, key) => {
if (id == value.id) {
hasUserId=true
loginUser=value;
}
})
if(isExist(loginUser)){
if(pwd===loginUser.pwd){
res.status(200).json({
message:"성공"
})
}
}
else{
res.status(404).json({
message:"실패"
})
}
})
function isExist(obj){
if(Object.keys(obj).length){
return true;
}
else{
return false;
}
}
//회원가입
router.post('/join', (req, res) => {
console.log(req.body);
if (Object.keys(req.body).length) {
db.set(id++, req.body)
res.status(201).json({
message: `${db.get(id - 1).name}님 환영합니다.`
})
} else {
res.status(400).json({
message: `입력 값을 다시 확인해주세요`
})
}
})
router
.route('/users/:id')
.get((req, res) => {
let { id } = req.params;
id = parseInt(id);
let user = db.get(id);
if (user) {
res.status(200).json({
userId: user.id,
name: user.name
})
}
else {
res.status(404).json({
message: `해당 회원이 없습니다.`
})
}
})
.delete((req, res) => {
let id = Number(req.params.id);
const user = db.get(id);
if (user) {
db.delete(id);
res.status(200).json({
message: `${user.name}님 다음에 또 뵙겠습니다. 메인페이지`
})
}
else {
res.status(404).json({
message: `삭제할 회원이 없습니다`
})
}
})
module.exports=router
맨 아래부분에 exports 해주었습니다. 그리고 app.js에서 모듈을 require해주어서 미들웨어처럼 사용해주겠습니다.
const express = require('express')
const app = express()
app.listen(7777)
//user-demo.js 모듈 불러오기
const userRouter = require('./routes/user-demo')
app.use("/",userRouter)
postman에서 테스트 해보겠습니다. 잘 동작합니다.
이어서 channeldemo도 exports한 후 require해주겠습니다.
수정된 channeldemo.js코드입니다.
//express 모듈 셋팅
const express = require('express')
const router = express.Router()
router.use(express.json())
let db = new Map()
let id = 1
router
.route('/channels')
//채널 전체 조회
.get((req, res) => {
console.log('전체 채널 조회')
let channel = [];
db.forEach((value, index) => {
channel.push(value);
})
console.log(channel);
if (db.size >= 1) {
res.status(200).json(channel)
}
else {
res.status(404).json({
message: `채널이 없습니다 `
})
}
})
//채널 개별 생성
.post((req, res) => {
console.log('채널생성');
if (Object.keys(req.body).length) {
db.set(id++, req.body)
res.status(201).json({
message: `${req.body.channelTitle}님 채널을 응원합니다.`
})
}
else {
res.status(400).json({
message: `채널명을 확인해주세요`
})
}
})
router
.route('/channels/:id')
//채널개별조회
.get((req, res) => {
console.log('채널개별조회')
let { id } = req.params
id = Number(id)
let channel = db.get(id)
if (channel) {
res.status(200).json({
message: `${channel.channelTitle}채널조회`
})
}
else {
res.status(404).json({
message: `채널 조회가 실패하였습니다.`
})
}
})
//채널삭제
.delete((req, res) => {
console.log('채널 삭제')
let { id } = req.params
id = Number(id)
let channel = db.get(id)
if (channel) {
db.delete(id)
res.status(200).json({
message: `${channel.channelTitle}이 삭제되었습니다`
})
}
else {
res.status(404).json({
message: `삭제되지않았습니다`
})
}
})
//채널수정
.put((req, res) => {
console.log('채널 수정')
let { id } = req.params
id = Number(id);
let channel = db.get(id);
let beforeTitle = channel.channelTitle
if (channel) {
db.set(id, req.body);
res.status(200).json({
message: `${beforeTitle}채널명이 성공적으로 ${db.get(id).channelTitle}로 수정되었습니다`
})
}
else {
res.status(404).json({
message: `수정하고자 하는 채널을 확인해주세요`
})
}
})
module.exports=router
app.js에서도 require해주겠습니다.
const express = require('express')
const app = express()
app.listen(7777)
//user-demo.js 모듈 불러오기
const userRouter = require('./routes/user-demo')
const chaneelRouter = require('./routes/channel-demo')
app.use("/",userRouter)
app.use("/",chaneelRouter)
channel-demo.js를 보면 api의 url에 channels가 중복되기 때문에 app.js에서 app.use를 사용할때 channels를 붙여줍니다. 그리고 보통 파일이름은 복수형으로 작성하기에 채널데모의 이름도 channels로 바꿔줍니다.
const express = require('express')
const app = express()
app.listen(7777)
//user-demo.js 모듈 불러오기
const userRouter = require('./routes/users')
const chaneelRouter = require('./routes/channels')
app.use("/",userRouter)
app.use("/channels",chaneelRouter)
결과
postman에서 두개의 api를 동시에 실행시켜보겠습니다. channel을 먼저 하나 생성하고 user를 생성해보겠습니다.
바디에 채널이름을 Choims로 설정해서 send해줍니다.
다음으로 아래처럼 회원정보를 body에 실어서 send해주면 두개의 api가 다른 파일에 작성이 되어있음에도 정상적으로 작동합니다.
'백엔드 > node.js(express)' 카테고리의 다른 글
Docker MariaDB db생성 및 테이블생성(삽입,수정,join) (0) | 2023.12.19 |
---|---|
토이프로젝트 유튜브2(채널 API 리팩토링) (2) | 2023.12.18 |
핸들러란, 상태코드,예외처리 (1) | 2023.12.15 |
Node.js-Express(Delete,put), HTTP상태코드 (0) | 2023.12.15 |
Expess Post(Postman, app.use()함수) (0) | 2023.12.11 |