node js 서버 구축하기

lsw·2021년 8월 26일
0

서버

목록 보기
2/6
post-thumbnail

3.2. url의 구성요소

protocol: http 또는 https(강화된 보안, 별도 인증문서 필요)

domain: www.google.com / www.naver.com 등이 해당하며 hostname 혹은 ip + port 와 동치이다. : localhost:2200 / 127.0.0.1:2200. 도메인은 네트워크 상 일종의 약속이다. 선점방식이기 때문에 이미 존재하는 도메인은 사용할 수 없다.

path: 도메인의 특정 위치를 가리킵니다. (points specific location of domain)

query: ?key=value를 이용해 특정 페이지를 탐색한다.


3.3. node js로 서버 구축하기

노드는 모듈방식을 채택하고 있어 필요한 기능을 다양하게 정의된 모듈로 부터 끌어다 쓰는 것이 가능하다. 이 중 'http' 라는 내장모듈을 사용하면 서버를 직접 구축할 수 있다.

// http 모듈 가져오기
const http = require('http')
// === import http from 'http' 

// const app = http.createServer([options], [request listener])
// return type = http.Server
// options = null, listenr = function(req,res)
const app = http.createServer((req,res) => {
	const a = req. ...
  	res. ...
	}
);

반환 타입(return type)이 http.Server임을 주목합시다.

http.Server는 listen 매서드를 갖는데, 이를 통해 특정 포트와 서버를 연결할 수 있다.

// 앞선 코드의 연장
// 사용법 : app.listen([port],[hostname],[listener]);
app.listen(3000, 'localhost', () => console.log(port number 3000 is running on));

→ 이제 url : localhost:3000 은 상기 http.createServer 내 콜백함수 본문에 담긴 내용을 보여주는(로드해주는) 웹페이지의 주소가 된다. 본문에 직접 소스를 작성해 줄이 길어지거나 지저분하다면 별도 파일을 만들어서 연결해주면 됩니다. html, css, txt, javascript 등등 다양한 확장자가 대상이될 수 있다.
추가적으로 localhost라는 hostname은 본인의 컴퓨터 로컬에서만 접근 가능한 url을 만들며 타 컴퓨터에서 액세스가 불가능 하다. ip로는 127.0.0.1로 표현할 수 있다.


3.4. 파일 연결

보통 하나의 파일에 150 ~ 200 줄이 넘어가는 코드가 들어가면 보기 지저분하다고들 한다. 긴 소스를 억지로 집어넣을 필요 없이 별도로 파일에 저장한 후 가져와 사용할 수 있다. 다양한 데이터(html, css, txt, json 등)을 담아 연결해보는 것은 웹페이지 구성의 기본이 될것이다.

  • readFile / readDir

http/test.html (출처 : https://www.w3schools.com/html/html_examples.asp)

<!DOCTYPE html>
<html>
<body>

<h2>An Unordered HTML List</h2>

<ul>
  <li>Coffee</li>
  <li>Tea</li>
  <li>Milk</li>
</ul>  

<h2>An Ordered HTML List</h2>

<ol>
  <li>Coffee</li>
  <li>Tea</li>
  <li>Milk</li>
</ol> 

</body>
</html>

http/test.js

const fs = require('fs');

// readFile 사용법 : fs.readFile([file_Dir],[options],[callback])
// readDir 사용법 : fs.readDir([file_Dir],[options],[callback]) 
fs.readFile('./test.html', (err, data) => {
		if (err) throw err;
		data...	
});

fs.readDir('./test.html', (err, data) => {
		if (err) throw err;
		data...	
});

파일을 가져왔으면 그 파일의 데이터를 이용하는 것이 저희의 목적입니다. readFile, readDir매서드를 통해 인자 data를 자유롭게 사용할 수 있다.

node의 모듈사용법은 웬만하면 검색해서 나오는 도큐먼트를 보는게 낫다. (이 뿐 아니라 공식문서는 언제나 큰 도움이 됩니다.)

readFile, readDir은 모두 fs모듈의 매서드임으로 node js모듈 공식문서 를 참조하는 방식으로 말이다.


3.5. express 모듈

express 모듈은 기존 http 모듈 서버구축 방식에 라우터, 미들웨어, http req,res의 객체화 등의 개념을 추가한 것으로 http 모듈과 마찬가지 REST-API의 get / post / put / delete 매서드를 모두 사용할 수 있다.

const express = require('express');
const app = express();

app.use();
app.get();
app.post();
app.put();
app.delete();

3.6. 미들웨어

미들웨어란 중간(middle)에 거쳐가는 함수라는 뜻으로 http req, res 객체와 next 미들웨어에 대한 접근권한을 갖는 함수이다. (이벤트 리스너 혹은 콜백의 느낌이 듭니다.)

app.use((req, res, next) => {
	req. ... 
	res. ...
	next(...);	
});

app.get((req, res, next) => {
	req. ...
	res. ...
	next(...);
});

app.post('__dir', (req, res, next) => {
	req. ...
	res. ...
	next(...);
}, function(req, res, next) {
	req. ...
	res. ...
	next(...);
});

app.use는 호출 매서드(get, post, put, delete) 에 상관 없이 호출되어 미들웨어 함수가 항상 호출된다. 이를 이용하면,

const logger = require('morgan');
const express = require('express');
const app = express();

app.use(morgan([options]))
// options : 'dev', 'short', 'tiny', 'combined' ... 

npm i morgan
로그를 찍어주는, 써드파티 미들웨어인 morgan을 설치해 주고 app.use를 통해 등록해 주면

다음과 같이 클라이언트에게 요청이 올 때마다 항상 로그가 찍히게 된다.


next()함수는 호출 시 흐름을 다음 미들웨어 함수로 넘어가게 하는데, 호출되지 않으면 미들웨어의 이 흐름이 끊겨 다음 함수의 호출이 이뤄지지 않는다.

라우터 미들웨어 스택의 다른 미들웨어 함수(동일 라우터에 속한 다른 미들웨어 함수)를 건너뛰고 싶다면 next('route')를 호출해주면 된다.

app.use( middlewareFunc1 = (req, res, next) => {
	...	
	next('route'); // 호출로 인해 하단 middlewareFunc2는 호출되지 않고 건너뛰어진다.
}, middlewareFunc2(req, res, next) => {
	...	
});

3.7. 라우터 미들웨어

라우팅은 클라이언트의 다양한 요청의 처리를 위해 서버를 분기하는 작업으로 express 모듈을 도입하기 전엔 if ~ else if ~ else 등으로 처리하였으나, express 모듈의 적용으로

app.get('direction', (callbacks or middlewares));

다음과 같이 클라이언트의 요청 주소를 받을 수 있게 되었다.


아래와 같이 분기(라우팅)문을 보았을 때 어떤 기분이 드는가? 중복되는 부분이 불편하시지 않는가.
대게 코딩에서 같은내용의 코드가 반복해서 나오면 따로 정의를 내리기 마련인데, 그와 같이 중복되는 경로에 대해서도 정의를 내릴 수 있다.

app.get('./jyp/twice/TT', (callback1));
app.get('./jyp/rain/rainism', (callback2));
app.get('./sm/aespa/blackmamba', (callback3));
app.get('./sm/aespa/next-level', (callback4));

이는 express모듈의 Router 인스턴스의 생성으로 해결할 수 있다. router라는 일종의 미들웨어 파일을 만들고 이를 exports 해줄거다.

router.js

const express =require('epxress');
// Router 클래스 인스턴스 생성
const routerJyp = express.Router();
const routerSm = express.Router();

routerJyp.get('/twice/TT', (callback1));
routerJyp.get('/rain/rainism', (callback2));
routerSm.get('/blackmamba', (callback3));
routerSm.get('/next-level', (callback4));

module.exports = { routerJyp, routerSm };

app.js

const express = require('express');
const { routerJyp, routerSm } = require('./router');
const app = express();

// { routerJyp, routerSm }미들웨어의 적용
app.use('/jyp', routerJyp);
app.use('/sm/aespa', routerSm);

"routerJyp를 사용한 주소는 앞에 '/jyp'가 기본으로 붙는다" 라고 이해하면 된다.


3.8. http req, res 객체

express 모듈을 사용하게 되며 가장 크게 변한 것 중 하나는 역시 req, res의 객체화로 사용할 수 있는 매서드가 다양해졌다는 것이다. 살펴보면

const express = require('express');
const app = express();

app.get('/', (req, res, next) => {
// req객체의 매서드를 이용하여 클라이언트 요청(바디, 헤더, 파라미터, 쿼리 등등)에 접근할 수 있다.
		const body = req.**body**;
		const field1 = req.**params**.field1;
		const id = req.**query**.id;
// res객체의 매서드를 이용하여 클라이언트에게 여러가지 프라퍼티를(헤더, 쿠키, 세션, 타입, 상태코드, 바디 등등등)응답을 할 수 있다.
		res.status(200);
		res.redirect([dir]);
		res.send(anything);
		res.sendFile(file dir);
		res.json(json file);
		res.end(anything);

		res.cookie(..);
		res.set(..);
	});

결국 이를 통해 클라이언트 - 서버 간에 원활한 소통이 가능해졌다는 장점이 생겼다.
다음번엔 node js를 이용한 tdd를 살펴볼 예정~!

profile
미생 개발자

0개의 댓글