페북 그룹에서 Express를 사용 하지 않고 API 서버 만드는 글을 보고 나도 도전 해보았다.
DB 연결은 안 하고 기타 라이브러리 없이 기본적인 구조 및 라우팅만 만들어 보기로 했다.
구조는 아래와 같이 작성 하였다.
1 2 3 4 5 6 7 8 9
| ├── app │ ├── controllers ├── user.js ├── lib ├── routes.js ├── utils.js ├── package.json ├── node_modules ├── server.js
|
파라미터 받기
Express에서는 쿼리스트링은 req.query로 받고 POST의 경우에는 body-parser를 설치하여
사용 했었는데 이번엔 직접 utils.js에 파라미터 처리 함수를 작성 해보았다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| const url = require('url');
const NONE_CHECK_PARAM_GET_URL = [ '/userAll' ];
const parseParameters = (req) => { return new Promise((resolve, reject) => { if (req.method === "GET") { const qs = url.parse(req.url, true).query; if (NONE_CHECK_PARAM_GET_URL.indexOf(req.url) < 0 && Object.keys(qs).length === 0) return reject(new Error('파라미터가 안 넙어 왔습니다')); req.body = qs; return resolve(); } const body = []; req .on("error", (err) => reject(err)) .on("data", (chuck) => body.push(chuck)) .on("end", () => { try { req.body = JSON.parse(Buffer.concat(body).toString()); resolve(); } catch(e) { if (body.length == 0) e.message = '파라미터가 안 넘어 왔습니다.'; reject(e); } }); }); };
|
METHOD의 따라 GET인 경우 내장된 URL 모듈을 이용해 쿼리스트링 데이터를 넘겼으며
POST의 경우에는 공식 문서 가이드에 따라 해봤는데 잘 넘어오는 걸 확인 할 수 있었다.
데이터 모델 작성 하기
DB를 안 쓰기로 했으므로 간단하게 글로벌 변수에 넣거나 가져오는 걸로 처리를 했다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| const create = (id, data) => { return new Promise((resolve, reject) => { if (global.user[id]) return reject(new Error('이미 존재하는 아이디')); global.user[id] = data; return resolve(global.user[id]); }); };
const findByOne = (id) => { return new Promise((resolve, reject) => { if (!global.user[id]) return reject(new Error('존재하지 않은 회원')); return resolve(global.user[id]); }); }
const findAll = () => { return new Promise((resolve, reject) => { return resolve(global.user); }); };
module.exports = { create, findByOne, findAll, };
|
컨트롤러 작성 하기
데이터 모델을 호출 하기 위한 컨트롤러를 만들어 본다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| const userModel = require('../models/user');
const createUser = async (req) => { try { return await userModel.create(req.body.id, req.body); } catch (e) { throw e; } };
const getUserByID = async (req) => { try { return await userModel.findByOne(req.body.id); } catch (e) { throw e; } };
const getAllUser = async (req) => { try { return await userModel.findAll(); } catch (e) { throw e; } };
module.exports = { createUser, getUserByID, getAllUser, };
|
라우터 작성
Express로 작성할 때 보통 따로 만들지는 않았었는데 걍 문득 레일즈였나..? 생각 나서 따로 분류를 해보았다.
1 2 3 4 5 6 7 8 9 10 11 12 13
| const user = require('../app/controllers/user');
const router = { POST: { '/userCreate': user.createUser, }, GET: { '/userByID': user.getUserByID, '/userAll': user.getAllUser, } };
module.exports = router;
|
공통 응답 처리 작성
일일이 res 하기 귀찮으므로 공통으로 만들어서 호출을 하자.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
|
const responseResult = (err, body, res) => { const results = { status: 200, message: 'SUCCESS', body, }; if (err) { results.status = 500; results.message = err.message; } else if (!results.message && typeof results.message === "object") { results.status = 403; results.message = "페이지를 찾을 수 없습니다."; } res.writeHead(results.status, { "Content-Type": "application/json" }); res.end(JSON.stringify(results)); };
exports.parseParameters = parseParameters; exports.responseResult = responseResult;
|
Server.js 작성
이제 재료를 모두 만들었으니 실제 구동 부분을 내장 http 모듈을 이용하여 만들어 본다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| const http = require("http");
const utils = require('./libs/utils'); const router = require('./libs/routes');
const PORT = process.env.PORT || 3000;
const server = http.createServer(async (req, res) => { const opt = { err: null, body: null, res, }; try { await utils.parseParameters(req); } catch (e) { return utils.responseResult(e, opt.body, opt.res); } let url = req.url; if (req.method === 'GET') url = req.url.split('?')[0]; try { opt.body = await router[req.method][url].call(null, req); } catch (e) { if (router[req.method][url]) opt.err = e; } utils.responseResult(opt.err, opt.body, opt.res); });
server.listen(PORT, () => { global.user = {}; console.log(`서버는 ${PORT}에서 동작중..`); });
|
검색 좀 해보면서 만들어보니 음 생각보다 어렵지 않았고 막상 설명 적을 것도 없다… 😰
다만 이번에 만들다가 안 건데 미들웨어 처리가 Node.js 내장이 아니고 Express 내장이였다.
검색 해보니 직접 구현 관련 글들 좀 나오던데 굳이 따라해보고 싶진 않았음..
Express는 가볍고 쓰기 쉬운 프레임워크 라고 생각하기 때문에 굳이 안 쓰고 순수하게
짤 필요성을 못 느껴서 앞으로도 Node.js 기반으로 개발 할 때는 계속 쓸 거 같다 😊
참조