안녕하세요 이번 시간에는 Node.js에서 제일 유명한 Express 프레임워크에 대해 알아보겠습니다!
Express
Express 프레임워크 외에도 Koa나 Hapi같은 프레임워크가 더 있는데요. 다른 두 개는 제가 안 써봐서 잘 모르겠습니다. Express는 대다수가 사용할 정도로 대중적이고 인기가 가장 많습니다.
전 시간처럼 서버의 페이지 개수가 늘어나고 사이트가 커지면 코드가 복잡해지는데요. Express 프레임워크는 코드의 양도 줄여주고 추후 유지보수가 쉽도록 만들어주기 때문에 사용합니다. 하지만 성능은 이전 시간의 생 코드보다는 떨어집니다. 하지만 크게 영향은 없기 때문에 사용해도 됩니다. 드디어 npm을 사용할 때가 왔네요. 이전의 http, path, fs, url 등의 모듈은 Node.js에서 기본 제공하는 패키지였기 때문에 설치할 필요가 없지만 Express는 Node.js가 아닌 다른 개인이나 단체가 만든 패키지이기 때문에 npm에서 다운로드받아야 합니다. cmd에서 프로젝트 폴더로 간 후
npm install express
로 설치해줍니다. 설치한 express는 node_modules라는 폴더 안에 저장됩니다. 또한 package.json에 express가 설치되었음이 기록됩니다. 앞으로는 package.json 파일만 있으면 node_modules 폴더가 지워졌더라도 복구할 수 있습니다. npm install 하면 자동으로 package.json안에 기록된 모든 패키지들을 설치합니다. server.js를 다음과 같이 바꿉니다.
server.js
const express = require('express');
const app = express();
app.get('/', (req, res) => {
res.send('Hello World!');
});
app.listen(8080, () => {
console.log('Express App on port 8080!');
});
http 모듈은 Express에서 내부적으로 처리하기 때문에 더 이상 사용하지 않아도 됩니다. const app = express();
을 사용해서 만든 Express app 객체로 모든 서버의 일을 처리합니다. 위의 코드는 간단한 Hello World! 문자열을 전송합니다. 마지막에 app.listen
메소드로 http.listen
과 같이 8080포트에서 요청을 대기하고 있죠.
단순한 문자열을 전송하는 것 대신 이전 강좌처럼 about과 main 페이지로 나누어서 응답받을 수 있게 해볼까요?
Routing
const express = require('express');
const path = require('path');
const app = express();
app.use(express.static(path.join(__dirname, 'html')));
app.get('/', (req, res) => {
res.sendFile(path.join(__dirname, 'html', 'main.html'));
});
app.get('/about', (req, res) => {
res.sendFile(path.join(__dirname, 'html', 'about.html'));
});
app.listen(8080, () => {
console.log('Express App on port 8080!');
});
확실히 깔끔해졌음을 느끼시나요? server.js를 위와 같이 바꾸고, html 폴더를 server.js와 같은 위치로 새로 만든 뒤 main.html, about.html, turn.js를 html 폴더 안으로 옮깁니다.
server.js
html
--main.html
--about.html
--turn.js
node_modules
package.json
이런 구조가 되게요. app.use(express.static(path.join(__dirname, 'html')));
이 코드가 추가되었는데요. app.use
는 미들웨어를 쓰는 부분이고, express.static
은 정적 파일들이 있는 위치를 지정하는 부분입니다. 미들웨어는 다음 강좌에서 설명하겠습니다! 지금은 그냥 정적 파일을 제공하기 위해 코드를 넣었다고만 이해하고 넘어가주세요. 정적 파일이란 나중에 배울 ejs나 pug 같은 템플릿이 아닌 그냥 파일이라고 생각하시면 됩니다. 이미지, 동영상, HTML, CSS, JS 파일, 폰트 등이 모두 정적 파일입니다.
__dirname은 바로 현재 위치를 가리키는 Node.js의 전역 변수입니다. 비슷한 것으로 현재 파일 이름을 가리키는 __filename 변수가 있습니다. 아, Node.js 환경에서 디렉토리 주소를 다룰 때는 항상 path 모듈을 사용하세요! path.join
메소드를 사용하면 디렉토리 주소 구분자가 /인지 \인지 상관없이 환경에 맞게 주소를 완성해줍니다. (\와 /는 맥, 리눅스, 윈도우 OS에 따라 다릅니다) 그리고 .(현재 폴더)과 ..(상위 폴더)도 알아서 계산해서 해당 주소를 표시해주기 때문에 주소를 어떻게 써야할 지 헷갈릴 때 사용하세요.
const path = require('path');
path.join('example', 'children', 'file1.js'); // 'example/children/file1.js'
path.join('example', 'children', '..', 'file2.js'); // 'example/file2.js'
path.join('example', 'children', 'grandson', '..', '..', 'file3.js'); // 'example/file3.js'
위와 같이 ..이 있을 경우 상위 폴더로 한 단계 올라갑니다.
정적 파일의 위치를 html 폴더로 정해주면(폴더의 이름은 상관없습니다), 클라이언트에서 접근할 때 html/[파일 이름] 으로 접근하는 게 아니라, 그냥 [파일 이름]으로 접근할 수 있습니다. 예를 들면 사용자가 html 폴더 안의 turn.js 파일을 보고 싶으면 주소창에 localhost:8080/html/turn.js를 입력하는 게 아니라, localhost:8080/turn.js 이렇게 입력해야 합니다. 정작 /html/turn.js를 하면 아무것에도 접근할 수 없습니다. 사용자에게 보여주고 싶은 파일들만 html 폴더에 넣고, 나머지는 폴더 밖에 놓으면 public 폴더와 private 폴더를 구분할 수 있는거죠. 서버 코드같은 민감한 것들은 감출 수 있습니다.
app.use('/static', express.static(path.join(__dirname, 'html')));
위와 같이 /static을 넣어주면 localhost:8080/static/turn.js 이렇게 접근해야 합니다. 실제 경로와 브라우저의 경로를 달리 해서 쉽게 서버 파일에 접근하지 못하도록 하는 겁니다.
중간 app.get('/', 콜백)
, app.get('/about', 콜백)
이 REST API로써 라우팅을 처리하는 부분입니다. '/'이라는 get 요청이 들어왔을 때와 '/about'이라는 get 요청이 들어왔을 때 어떻게 응답할 것인지 콜백 함수로 정의할 수 있습니다.
앞으로는 콜백의 매개변수로 request와 response 대신 req와 res를 쓸겁니다. response와 request는 단어가 너무 길거든요. 마지막엔 지금까지 썼던 fs.readFile
과 res.end
대신 res.sendFile
메소드로 각각 해당하는 html 파일을 주면 됩니다. html 파일을 읽어서 브라우저로 보내는 복잡했던 코드가 한 줄로 줄어들었습니다.
다음 시간에는 Express 미들웨어와 고급 라우팅에 대해 알아보겠습니다!
const app2 = (function(){
return function(){}; )()