1. 미니미니 프로젝트 (실습)
이전 내용
[TIL] 9/6 핸들러, 예외 처리, HTTP 상태코드
1. 핸들러 (Handler)HTTP request 가 날아오면 자동으로 호출되는 메소드 노드에서는 콜백함수로, 콜백함수를 핸들러라고 생각하면 된다. (cf. 스프링에서는 컨트롤러라고 불린다)즉, HTTPMETHOD 를 사용
everydayc0ding.tistory.com
[TIL] 9/9 API 설계 - 회원 API, 채널 API
1. 미니미니 프로젝트 (실습) 지난번에 했던 미니미니 프로젝트를 이어서 해보려고 한다. 지난번에는 회원 API 의 회원가입 / 회원 개별 조회 / 회원 개별 탈퇴까지 했으니, 로그인 API 를 만들어보
everydayc0ding.tistory.com
1.1. Router
Server: 리퀘스트 받음
Router: 리퀘스트의 URL 에 따라 루트(route) 를 정해줌 (어디로 갈지 길을 정해줌)
Node.js 에서의 라우팅(Routing)이란?
리퀘스트가 날아왔을 때, 원하는 경로에 따라 적절한 방향으로 경로를 안내해주는 것
( = URL 과 method 가 날아왔을 때, 어떤 콜백 함수를 호출할 것인지 안내해주는 것)
라우팅을 사용하기 위해 기존 프로젝트 구조를 바꾸어 주었다.

그리고 users.js 파일과 channels.js 파일의 express 모듈 셋팅, 포트 번호 설정 부분을 가져와 app.js 로 옮겨 시작을 app.js 에서 할 수 있도록 만들어주었다.
app.use 안에 주소는 라우터의 공통된 주소로, 저 주소에서부터 분기하게 된다.
// express 모듈 셋팅
const express = require('express')
const app = express()
app.listen(6666) // 포트 번호 설정
// 쉽게 말해 미들웨어를 만든 것 -> use 이용해 써야겠다고 말만하면 됨
const userRouter = require('./routes/users') // users 소환
const channelRouter = require('./routes/channels') // channels 소환
app.use("/", userRouter)
app.use("/channels", channelRouter)
1.2. API 문제점1 - 채널 API 수정
문제점1.
회원 1명이 생성할 수 있는 채널의 최대 개수는 100개, 그러나 채널 db 테이블은 channelTitle 밖에 갖고 있지 않기 때문에 채널의 소유자가 누구인지 알 수 없음 -> 전체 채널 조회할 때 channelTitle 만 나오고 어떤 사용자의 채널인지 모름
수정방안 -> 채널 db 테이블에 어떤 소유자의 채널인지 알 수 있도록 userId 컬럼 추가
(수정된 사항 표시)
채널 생성 -> POST /channels
- req: body(channelTitle, userId)
- res 201: `${channelTitle} 채널을 응원합니다` 👉 다른 페이지 띄우고 싶음 (ex. 채널 관리 페이지)
회원이 소유한 채널 전체 조회 GET /channels
- req: body(userId)
- res 200: 채널 전체 데이터를 list, json array 등으로 돌려줌
예외처리
1) 리퀘스트 바디에 userId 가 없는 경우
2) 사용자가 소유하고 있는 채널이 없는 경우
1) 번의 경우 마이페이지에서 채널 관리 페이지로 들어가기 때문에 이 경우를 고려하지 않아도 된다고 생각할 수 있지만, 아래와 같은 경우에는 userId 가 리퀘스트 바디에 없을 수 있기 때문에 예외처리를 해줘야 한다.
- 마이페이지를 켜놓고 장시간 후에 로그인이 만료된 후 채널 관리 페이지에 들어가려고 하는 경우
- 브라우저에서 마이페이지 url 을 기억해 놓고 있다가 자동완성 기능을 통해 마이페이지에 접속한 경우
추가로 예외처리를 할 때 리스폰스 메세지로 '채널 정보를 찾을 수 없습니다.' 라는 문구를 돌려줘야 하는 경우가 많기 때문에 notFoundChannel 이라는 함수를 만들어 코드를 정리해주었다.
router
.route('/')
.get((req, res) => {
let channels = []
let {userId} = req.body
if (userId && db.size) {
db.forEach((channel) => {
if (channel.userId === userId) {
channels.push(channel)
}
})
if (channels.length) {
res.status(200).json(channels)
} else { // 예외처리2 - 소유하고 있는 채널이 없음
notFoundChannel()
}
} else { 예외처리 1 - userId x
notFoundChannel()
}
}) // 채널 전체 조회
.post((req, res) => {
let channel = req.body
if (channel) {
db.set(id++, channel)
res.status(200).json({
message: `${db.get(id-1).channelTitle} 채널을 응원합니다`
})
} else {
res.status(400).json({
message: '요청 값을 제대로 보내주세요'
})
}
}) // 채널 개별 생성
1.3. API 문제점2 - 회원 API 수정
문제점2. (사실 2번은 문제점보다는 개선하면 좋은 점)
회원 db 테이블은 사용자를 구별할 수 있는 값이 2개 존재 -> id (현재 키 값으로 사용 중), userId (사용자의 id)
수정방안 -> 사용자를 구별할 수 있는 값이 굳이 중복으로 존재할 필요가 없으므로 id 값 대신 userId 를 키 값으로 사용
(수정된 사항 표시)
1) 로그인 -> POST /login
- req: body(userId, pwd)
- res: `${name}님 환영합니다` 👉 메인 페이지
2) 회원 가입 -> POST /join
- req: body(userId, pwd, name)
- res: `${name}님 환영합니다` 👉 로그인 페이지
3) 회원 개별 정보 조회 -> GET /users/:id
- req: body(userId)
- res: userId, name
4) 회원 개별 탈퇴 -> DELETE /users/:id
- req: body(userId)
- res: `${name}님 다음에 또 뵙겠습니다.` or 👉 메인 페이지
// express 모듈 셋팅
const express = require('express')
const router = express.Router()
router.use(express.json())
let db = new Map()
// 로그인
router
.route('/login')
.post((req, res) => {
const {userId, pwd} = req.body
let loginUser = {}
db.forEach(user => {
if (user.userId === userId) {
loginUser = user
}
})
if (isExisted(loginUser)) {
if (loginUser.pwd === pwd) {
res.status(201).json({
message: `${loginUser.name}님 로그인 성공`
})
} else {
res.status(400).json({
message: '비밀번호가 틀립니다'
})
}
} else {
res.status(404).json({
message: '아이디가 존재하지 않습니다'
})
}
})
function isExisted(obj) {
if (Object.keys(obj).length) {
return true
} else {
return false
}
}
// 회원 가입
router
.route('/join')
.post((req, res) => {
let {userId, pwd, name} = req.body
let user = {
userId: userId,
pwd: pwd,
name: name
}
if (userId && pwd && name) {
db.set(userId, user)
res.status(201).json({
message: `${user.name}님 환영합니다.`
})
} else {
res.status(400).json({
message: '입력 값을 다시 확인해주세요'
})
}
})
// 회원 개별 조회
router
.route('/users')
.get((req, res) => {
let {userId} = req.body
let user = db.get(userId)
if (user) {
res.status(200).json({
id: userId,
name: user.name
})
} else {
res.status(404).json({
message: '회원 정보가 없습니다.'
})
}
})
// 회원 개별 탈퇴
router.delete('/users', (req, res) => {
let {userId} = req.body
let 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
'TIL with Programmers' 카테고리의 다른 글
[TIL] 9/12 데이터베이스 실습 - SELECT, ALTER, JOIN, FK, PK, AUTO_INCREMENT, NOT NULL, DEFALUT (0) | 2024.09.12 |
---|---|
[TIL] 9/11 데이터베이스, DBMS, RDBMS (0) | 2024.09.11 |
[TIL] 9/9 API 설계 - 회원 API, 채널 API (0) | 2024.09.09 |
[TIL] 9/6 핸들러, 예외 처리, HTTP 상태코드 (1) | 2024.09.08 |
[회고록] 풀 사이클 개발 데브코스 4주차 회고 (1) | 2024.09.08 |