router를 설정하는 방식이 express보다 좀 더 간결하고 알아보기 쉽다.
최상단의 index.js (express의 app.js와 같은 중앙 통제실 같은 개념)
const Koa = require('koa')
const Logger = require('koa-logger')
const bodyParser = require('koa-bodyparser')
const Router = require('koa-router')
const helmet = require('koa-helmet')
const api = require('./api')
router
.use(helmet())
.use(Logger())
.use(bodyParser())
.use('/api', api.routes())
app
.use(router.routes())
.use(router.allowedMethods())
라우트 폴더 최상단.
여기서는 세부적인 라우트를 한번에 모아서 관리하고, 세부적인 라우트는 폴더 내부에 또 다른 폴더를 만들어 관리한다.
/api 에서 /auth와 /board 관련 코드를 다 모으면 된다.
/api
/api/auth/...
/api/board/....
이런 식으로 관리하면 된다. express에 비해 정돈된 모습을 보인다.
const Router = require('koa-router')
const auth = require('./auth')
const VERSION = 15
const app = new Router()
app.get('/version', ctx => ctx.body = {
version: VERSION,
status: 'ok'
})
app.use('/auth', auth.routes())
module.exports = app
세부 폴더에 들어가면 다음과 같이 구성되어 있다.
당연히 경로와 컨트롤러를 따로 분리할 수 있다.
const Router = require('koa-router')
const Controller = require('./controller')
const app = new Router()
app.post('/signin', Controller.getAuth)
app.post('/signup', Controller.createUser)
module.exports = app
const fs = require('fs')
const jwt = require('jsonwebtoken')
const bkfd2Password = require('pbkdf2-password')
const User = require('../../lib/user')
const Crypto = require('../../lib/crypto')
const SendMail = require('../../lib/email')
const Recaptcha = require('../../lib/recaptcha')
const createUser = require('../../database/user/createUser')
const readUser = require('../../database/user/readUser')
const updateUser = require('../../database/user/updateUser')
const hasher = bkfd2Password()
exports.getAuth = async ctx => {
const { username, password } = ctx.request.body
if (username === '' || password === '')
return
const user = await readUser.auth(username)
if (!user)
return ctx.body = {
message: '존재하지 않는 계정입니다.',
status: 'fail'
}
try {
const result = await new Promise((resolve, reject) => {
hasher({
password,
salt: user.salt
}, (err, pass, salt, hash) => {
if (err)
return reject({ message: err, status: 'fail' })
if (user.password !== hash)
return reject({ message: '비밀번호가 올바르지 않습니다.', status: 'fail' })
// if (user.isVerified < 1) return reject({ redirect: 'accept', message: '이메일을
// 인증하지 않았습니다.', status: 'fail' })
const token = jwt.sign({
jti: user.id
}, process.env.JWT_SECRET, { expiresIn: '30d' })
resolve({ token, status: 'ok' })
})
})
ctx.body = result
} catch (e) {
ctx.body = e
}
}
exports.createUser = async ctx => {
const { username, nickname, email, authCode, password } = ctx.request.body
if (username === '' || nickname === '' || email === '' || password === '')
return //auth 제거
const getUsername = await readUser.username(username)
if (getUsername)
return ctx.body = {
message: '이미 존재하는 아이디입니다.',
status: 'fail'
}
const getNickname = await readUser.nickname(nickname)
if (getNickname)
return ctx.body = {
message: '이미 존재하는 닉네임입니다.',
status: 'fail'
}
const getEmail = await readUser.email(email)
if (getEmail)
return ctx.body = {
message: '이미 존재하는 이메일입니다.',
status: 'fail'
}
try {
const result = await new Promise((resolve, reject) => {
hasher({
password
}, async (err, pass, salt, hash) => {
if (err)
return reject({ message: err, status: 'fail' })
await createUser({ username, nickname, email, password: hash, salt })
resolve({ status: 'ok' })
})
})
ctx.body = result
} catch (e) {
ctx.body = e
}
}
'Node, Nest, Deno > 🚀 Node.js (+ Express)' 카테고리의 다른 글
pm2 이용 및 로그 기록 살피기 (0) | 2020.08.06 |
---|---|
노드 내장 모듈 util의 util.pomisify 사용하기 (0) | 2020.07.30 |
[koa] koa 살펴보기 (0) | 2020.07.29 |
chained route handlers (0) | 2020.07.02 |
sharp를 활용한 image resizing + buffer 이해하기 (0) | 2020.06.29 |