1️⃣ Server와 Router의 역할

2️⃣ Node.js에서의 라우팅이란?
3️⃣ 서버를 담당하는 app.js 만들기
// 서버역할을 담당함
const express = require('express')
const app = express()
app.listen(1234)
const userRouter = require('./routes/user-demo') // 모듈화된 user-demo 소환하기
app.use("/", userRouter) // app.use를 사용하여 매개변수에 내가 만든 모듈을 추가해줌, "/"는 ?
4️⃣ user-demo.js를 모듈화하기

const express = require('express')
// 모듈화를 위해 서버를 불러오는 건 app.js로 넘김
const router = express.Router() // express에 Router로 사용할 수 있도록 만들어 줌
// app이라는 서버에 직접 연결 해주던 것을 app,js에 넘기게 되어
// app이 사용된 모든 곳을 router로 변경 해줌
router.use(express.json()) // http 외 모듈 사용 'json 모듈' -> app.을 router.로 수정
let db = new Map()
var id = 1
function isExist(obj){
if (Object.keys(obj).length === 0) {
return true
} else {
return false
}
}
// 로그인
router.post('/login', (req, res) => {
console.log(req.body) // userid, pwd
const {userId, password} = req.body
let loginUser = {}
db.forEach((user, id) => {
if (user.userId === userId){
loginUser = user
}
})
if(isExist(loginUser)) {
console.log("아이디 같음!!")
if (loginUser.password === password) {
console.log("비번 같아")
} else {
console.log("비번 틀려")
}
} else {
console.log('입력한 아이디를 다시 확인해 주세요')
}
})
// 회원가입
router.post('/join', (req, res) => {
console.log(req.body)
if (req.body == {}) {
res.status(400).json({
message : `입력 값을 확인해주세여`
})
} else {
db.set(id++, req.body)
res.status(201).json({
message : `${db.get(id-1).name}님 환영합니당`
})
}
})
router
.route('/users/:id')
// 회원 개별 조회
.get((req, res) => {
let {id} = req.params // {}는 비구조화, id 값을 따로 빼서 사용
id = parseInt(id)
const user = db.get(id)
if (user == undefined) {
res.status(404).json({
message : '회원정보가 없어요'
})
} else {
res.json({
userId : user.userId,
name : user,name
})
}
})
// 회원 개별 탈퇴
.delete((req, res) => {
let {id} = req.params
id = parseInt(id)
const user = db.get(id)
if (user == undefined) {
res.status(404).json({
message : '회원정보가 없어요'
})
} else {
db.delete(id)
res.status(200).json({
message : `${user.name}님 다음에 볼께요`
})
}
})
module.exports = router // 모듈화를 해주기 위해 router를 반환함 -> 외부모듈로 사용 가능
1️⃣ 코드 편집이 쉽도록 명령어를 한번에 다 바뀌보자




2️⃣ channel-demo도 모듈화하여 연결
const express = require('express')
// 모듈화를 위해 서버를 불러오는 건 app.js로 넘김
const router = express.Router() // express에 Router로 사용할 수 있도록 만들어 줌
// app이라는 서버에 직접 연결 해주던 것을 app,js에 넘기게 되어
// app이 사용된 모든 곳을 router로 변경 해줌
router.use(express.json()) //http 외 모듈 사용 'json 모듈'
let db = new Map()
let id = 1
router
.route('/channels') // route로 URL 묶어주기
// 채널 개별 생성
.post((req, res) => {
if (req.body.channelTitle){
db.set(id++, req.body) // db에 값을 줄 때 id+1씩 적용
res.status(201).json({
message : `${db.get(id-1).channelTitle}채널을 응원합니다.₩`
})
} else {
res.status(400).json({
message : '요청 값을 제대로 보내주세요'
})
}
})
// 채널 전체 조회
.get((req, res) => {
let channels = [] // json array(배열 또는 리스트라 부름)를 만들어줌
if(db.size){ // db에 무엇이라도 있다면
db.forEach((value, key) => {// Map에서 하나씩 꺼내서 channels에 더해 줌
// channels[key] = value channels에 키값을 전달하면서 value를 추가
channels.push(value) // 리스트에 value를 하나씩 추가(push)해줌
})
// console.log(channels[0]) 배열의 인덱스를 활용해서 선택하여 가져올 수 있음
// console.log(channels[1])
// console.log(channels[2])
res.status(200).json(channels) // 여기서 이렇게 보내면 배열 안에 json형태로 잘 보내줌
} else {
res.status(404).json({
message : '아무것도 없는 걸요'
})
}
})
router
.route('/channels/:id')
// 채널 개별 조회
.get((req, res) => {
let {id} = req.params // req.params 객체에서 URL 경로에 포함된 id 값을 추출하여 id 변수에 저장
id = parseInt(id) // URL에서 문자열로 추출된 id를 정수로 변환
let channel = db.get(id) // 해당 id를 키로 하는 채널 정보를 channel 변수에 저장
if(channel){
res.status(200).json(channel)
} else {
res.status(404).json({
message : `채널정보를 찾을 수 없습니다.`
})
}
})
// 채널 개별 수정
.put((req, res) => {
let {id} = req.params
id = parseInt(id)
let channel = db.get(id)
let oldTitle = channel.channelTitle // 올드 타이틀을 만들어줘야 차별화가 가능함
if(channel){
let newTitle = req.body.channelTitle // 뉴타이틀을 req.body의 channelTitle에서 가져옴
channel.channelTitle = newTitle // 가져온 것을 newTitle로 바꿔줌
db.set(id, channel) // 바꾼 것을 같은 id값에 channel을 덮어쓰기 해줌
res.status(200).json({
message : `${oldTitle}님이 ${newTitle}로 수정 되었습니다.` // 삭제되기 전 객체에서 꺼내와야 함
})
} else {
res.status(404).json({
message : `채널정보를 찾을 수 없습니다.`
})
}
})
// 채널 개별 삭제
.delete((req, res) => {
let {id} = req.params
id = parseInt(id)
let channel = db.get(id) // 해당 id를 키로 하는 채널 정보를 channel 변수에 저장
if(channel){
db.delete(id) // db에서 id를 삭제
res.status(200).json({
message : `${channel.channelTitle}님 정상적으로 삭제 되었습니다.` // 삭제되기 전 객체에서 꺼내와야 함
})
} else {
res.status(404).json({
message : `채널정보를 찾을 수 없습니다.`
})
}
})
module.exports = router // 모듈화를 해주기 위해 router를 반환함
3️⃣ 모듈 이름 변경하기

const express = require('express')
const app = express()
app.listen(1234)
const userRouter = require('./routes/users')// users(자동으로 이름이 변경됨) 소환하기
app.use("/", userRouter) // app.use를 사용하여 매개변수에 내가 만든 모듈을 추가해줌
const channelRouter = require('./routes/channel-demo')// channels(자동으로 이름이 변경됨) 소환하기
app.use("/", channelRouter) // "/"는 URL을 정해줄 수 있음!
4️⃣ use URL을 이용하여 공통 URL 골라주기
const express = require('express')
const app = express()
app.listen(1234)
const userRouter = require('./routes/users')// users 소환하기
app.use("/", userRouter) // app.use를 사용하여 매개변수에 내가 만든 모듈을 추가해줌
const channelRouter = require('./routes/channels')// channels 소환하기
app.use("/channels", channelRouter) // 공통되는 URL을 여기서 설정해주면 불필요한 코드를 생략해줄 수 있음(통일된 URL이 있을 때 유용함)


1️⃣ 웹페이지 보고 ERD 생각해보기
2️⃣ 간단하게 ERD 고려해보기
회원에서 index id가 없어도 user_id로도 raw를 구별할 수 있으니 굳이 고려하지 않아도 됨

채널은 한 유저가 여러개를 만들 수 있으므로 아래와 같이 설계해 볼 수 있음

위와 같이 ERD를 설계한다면 API 수정이 필요해짐

1️⃣ 채널 API 설계 수정


// 채널 개별 생성
.post((req, res) => {
if (req.body.channelTitle){
let channel = req.body // 1. json 형태인 req.body의 형태를 바꾸기 위해 변수 선언
// 2. 생각해보니 body에 userId를 추가만 해주면 되는 것인데 이건 코드를 바꿀 것이 아니라 body에서 추가해야 하는 것임
db.set(id++, channel) // db에 값을 줄 때 id+1씩 적용
res.status(201).json({
message : `${db.get(id-1).channelTitle}채널을 응원합니다.₩`
})
} else {
res.status(400).json({
message : '요청 값을 제대로 보내주세요'
})
}
})
2️⃣ 채널 생성 테스트


1️⃣ 채널 전체 조회를 수정해보자
// 채널 전체 조회
.get((req, res) => {
if(db.size){ // db에 무엇이라도 있다면
let {userId} = req.body // 1. req.body에 있는 userId를 뽑아옴
let channels = [] // json array(배열 또는 리스트라 부름)를 만들어줌
if (userId == undefined) { // 6. 5-1 예외처리를 이렇게 만들어 줌
res.status(404).json({
message : "로그인이 필요합니다."
})
} else {
db.forEach((value, key) => {// Map에서 하나씩 꺼내서 channels에 더해 줌
// channels[key] = value channels에 키값을 전달하면서 value를 추가
if(value.userId === userId) // 2. value의 userId와 req.body에서 가져온 userId와 비교해서 같다면
channels.push(value) // 3. 리스트에 value를 하나씩 추가(push)해줌, 같지 않다면 push 안하면 됨
// 4. channels에 push가 아무것도 안되어 있을 수 있는데 예외없이 res를 해주면 안됨
})
if (channels.length == 0) { // 7. 5-2 예외처리 는 이렇게 만들어 줌
res.status(404).json({
message : "조회할 채널이 없습니다."
})
} else (
res.status(200).json(channels) // 여기서 이렇게 보내면 배열 안에 json형태로 잘 보내줌
)
}
// 5. 예외처리 2가지
// 1) userId가 body에 없으면 -> 6로 이동 / 이 경우는 포인트를 돌릴필요도 없음, 그치만 채널 관리페이지를 들어가기 위해선 마이페이지에서 들어가기 때문에 필요없지만, URL로 접속할 경우를 대비해 로그인하라는 알림을 띄워주자
// 2) userId가 가진 채널이 없으면 -> 7로 이동
} else {
res.status(404).json({
message : "조회할 채널이 없습니다."
})
}
})
"조회할 채널이 없습니다." 메시지가 잘못나온다. 어떤 문제가 있을까?2️⃣ id없으면 예외 처리 if문 고도화
.get((req, res) => {
if(db.size){ // db에 무엇이라도 있다면
let {userId} = req.body
let channels = [] // json array(배열 또는 리스트라 부름)를 만들어줌
if (userId) {
db.forEach((value, key) => {// Map에서 하나씩 꺼내서 channels에 더해 줌
if(value.userId === userId)
channels.push(value)
})
if (channels.length) {
res.status(200).json(channels)
} else {
res.status(404).json({
message : "조회할 채널이 없습니다."
})
}
} else {
res.status(404).json({
message : "로그인이 필요합니다."
})
}
} else {
res.status(404).json({
message : "조회할 채널이 없습니다."
})
}
})
.get((req, res) => {
let {userId} = req.body
let channels = [] // json array(배열 또는 리스트라 부름)를 만들어줌
if(db.size && userId){ // db에 무엇이라도 있고 userId가 있으면 으로 합칠 수 있음
db.forEach((value, key) => {// Map에서 하나씩 꺼내서 channels에 더해 줌
if(value.userId === userId)
channels.push(value)
})
if (channels.length) {
res.status(200).json(channels)
} else {
res.status(404).json({
message : "조회할 채널이 없습니다."
})
}
// } else { -> 위 if문을 하나 줄였기 때문에 여기도 줄여줌
// res.status(404).json({message : "로그인이 필요합니다."})
// }
} else {
res.status(404).json({
message : "조회할 채널이 없습니다."
})
}
})
.get((req, res) => {
let {userId} = req.body
let channels = [] // json array(배열 또는 리스트라 부름)를 만들어줌
if(db.size && userId){ // db에 무엇이라도 있고 userId가 있으면 으로 합칠 수 있음
db.forEach((value, key) => {// Map에서 하나씩 꺼내서 channels에 더해 줌
if(value.userId === userId)
channels.push(value)
})
if (channels.length) {
res.status(200).json(channels)
} else {
notFoundChannel()
}
} else {
notFoundChannel()
}
})
function notFoundChannel() {
res.status(404).json({
message : "조회할 채널이 없습니다."
})
}
1️⃣ API 설계 다듬어 보기
ERD대로 회원 API가 잘 작동할 수 있도록 수정해보자

이전 설계에서 수정할 점

2️⃣ 변경 사항을 코드에 적용해보자
✅ 서버
const express = require('express')
const app = express()
app.listen(7777)
const userRouter = require('./routes/users')// users 소환하기
app.use("/", userRouter) // app.use를 사용하여 매개변수에 내가 만든 모듈을 추가해줌
const channelRouter = require('./routes/channels')// channels 소환하기
app.use("/channels", channelRouter) //
✅ 유저 API
const express = require('express')
// 모듈화를 위해 서버를 불러오는 건 app.js로 넘김
const router = express.Router() // express에 Router로 사용할 수 있도록 만들어 줌
// app이라는 서버에 직접 연결 해주던 것을 app,js에 넘기게 되어
// app이 사용된 모든 곳을 router로 변경 해줌
router.use(express.json()) //http 외 모듈 사용 'json 모듈'
let db = new Map()
function isExist(obj){
if (Object.keys(obj).length === 0) {
return true
} else {
return false
}
}
// 로그인
router.post('/login', (req, res) => {
console.log(req.body) // userid, pwd
const {userId, password} = req.body
let loginUser = {}
db.forEach((user, id) => {
if (user.userId === userId){
loginUser = user // user가 있다면 userfmf loginUser에 user를 담음
}
})
// 위 코드에서 userId 값을 못 찾았다면
if(isExist(loginUser)) { // loginuser로도 user의 존재 여부를 알 수 있게 됨
if (loginUser.password === password) {
res.status(200).json({
message : `${loginUser.name}님 로그인 되었습니다.`
})
} else {
res.status(400).json({
message : `비밀번호가 틀렸습니다.`
})
}
} else {
res.status(404).json({
message : `회원정보가 없습니다.`
})
}
})
// 회원가입
router.post('/join', (req, res) => {
console.log(req.body)
if (req.body == {}) {
res.status(400).json({
message : `입력 값을 확인해주세여`
})
} else {
const {userId} = req.body
db.set(userId, req.body)
res.status(201).json({
message : `${db.get(userId).name}님 환영합니당`
})
}
})
router
.route('/users')
// 회원 개별 조회
.get((req, res) => {
let {userId} = req.body // {}는 비구조화, id 값을 따로 빼서 사용
const user = db.get(userId)
if (user) {
res.json({
userId : user.userId,
name : user.name
})
} else {
res.status(404).json({
message : '회원정보가 없어요'
})
}
})
// 회원 개별 탈퇴
.delete((req, res) => {
let {userId} = req.body // {}는 비구조화, id 값을 따로 빼서 사용
const user = db.get(userId)
if (user) {
db.delete(userId)
res.status(200).json({
message : `${user.name}님 다음에 볼께요`
})
} else {
res.status(404).json({
message : '회원정보가 없어요'
})
}
})
module.exports = router
✅ 채널 API
const express = require('express')
// 모듈화를 위해 서버를 불러오는 건 app.js로 넘김
const router = express.Router() // express에 Router로 사용할 수 있도록 만들어 줌
// app이라는 서버에 직접 연결 해주던 것을 app,js에 넘기게 되어
// app이 사용된 모든 곳을 router로 변경 해줌
router.use(express.json()) //http 외 모듈 사용 'json 모듈'
let db = new Map()
let id = 1
router
.route('/') // route로 URL 묶어주기
// 채널 개별 생성
.post((req, res) => {
if (req.body.channelTitle){
let channel = req.body
db.set(id++, channel) // db에 값을 줄 때 id+1씩 적용
res.status(201).json({
message : `${db.get(id-1).channelTitle}채널을 응원합니다.`
})
} else {
res.status(400).json({
message : '요청 값을 제대로 보내주세요'
})
}
})
// 채널 전체 조회
.get((req, res) => {
let {userId} = req.body
let channels = [] // json array(배열 또는 리스트라 부름)를 만들어줌
if(db.size && userId){ // db에 무엇이라도 있고 userId가 있으면 으로 합칠 수 있음
db.forEach((value, key) => {// Map에서 하나씩 꺼내서 channels에 더해 줌
if(value.userId === userId)
channels.push(value)
})
if (channels.length) {
res.status(200).json(channels)
} else {
notFoundChannel()
}
} else {
notFoundChannel()
}
})
function notFoundChannel() {
res.status(404).json({
message : "조회할 채널이 없습니다."
})
}
router
.route('/:id')
// 채널 개별 조회
.get((req, res) => {
let {id} = req.params // req.params 객체에서 URL 경로에 포함된 id 값을 추출하여 id 변수에 저장
id = parseInt(id) // URL에서 문자열로 추출된 id를 정수로 변환
let channel = db.get(id) // 해당 id를 키로 하는 채널 정보를 channel 변수에 저장
if(channel){
res.status(200).json(channel)
} else {
res.status(404).json({
message : `채널정보를 찾을 수 없습니다.`
})
}
})
// 채널 개별 수정
.put((req, res) => {
let {id} = req.params
id = parseInt(id)
let channel = db.get(id)
let oldTitle = channel.channelTitle // 올드 타이틀을 만들어줘야 차별화가 가능함
if(channel){
let newTitle = req.body.channelTitle // 뉴타이틀을 req.body의 channelTitle에서 가져옴
channel.channelTitle = newTitle // 가져온 것을 newTitle로 바꿔줌
db.set(id, channel) // 바꾼 것을 같은 id값에 channel을 덮어쓰기 해줌
res.status(200).json({
message : `${oldTitle}님이 ${newTitle}로 수정 되었습니다.` // 삭제되기 전 객체에서 꺼내와야 함
})
} else {
res.status(404).json({
message : `채널정보를 찾을 수 없습니다.`
})
}
})
// 채널 개별 삭제
.delete((req, res) => {
let {id} = req.params
id = parseInt(id)
let channel = db.get(id) // 해당 id를 키로 하는 채널 정보를 channel 변수에 저장
if(channel){
db.delete(id) // db에서 id를 삭제
res.status(200).json({
message : `${channel.channelTitle}님 정상적으로 삭제 되었습니다.` // 삭제되기 전 객체에서 꺼내와야 함
})
} else {
res.status(404).json({
message : `채널정보를 찾을 수 없습니다.`
})
}
})
module.exports = router // 모듈화를 해주기 위해 router를 반환함