간단한 웹 서버 만들기
- 기본적으로 내장된
http
모듈을 사용하여 웹 서버 기능을 담당하는 서버 객체를 만들 수 있음 require("http")
const http = require("http")
const server = http.createServer()
const port = 3000
server.listen(port, function() {
console.log("시작됨 %d", port)
})
createServer()
: 웹 서버 객체 생성, 매개변수로 요청 / 응답에 대한 콜백 함수 등록
const server = http.createServer(function(req, res) {
res.write("asdf")
res.end()
})
listen()
: 서버 실행, 대기close()
: 서버 종료
클라이언트가 웹 서버에 접속한 후 데이터를 요청하면 그 때마다 적절한 이벤트가 발생하므로 다양한 상황에 맞추어 콜백 함수를 등록해야 한다.
- connection : 클라이언트가 접속하여 연결이 만들어질 때 발생하는 이벤트
- request : 클라이언트가 요청할 때 발생하는 이벤트
- close : 서버를 종료할 때 발생하는 이벤트
const http = require("http")
const server = http.createServer()
const port = 3000
server.listen(port, function() {
console.log("웹 서버가 %d 포트에서 시작됨", port)
})
server.on("connection", function(socket) {
//socket 객체는 클라이언트 연결 정보를 담고 있음
var address = socket.address()
console.log("클라이언트 접속 : %s %d", address.address, address.port)
})
server.on("request", function(req, res) {
console.log("클라이언트 요청 들어옴")
res.writeHead(200, {"Content-Type": "text/html; charset=utf-8"})
res.write("<p>hahaha</p>")
res.end()
})
server.on("close", function() {
console.log("서버 종료")
})
connection 이벤트에서
socket
객체는 클라이언트의 연결 정보를 담고 있음request 이벤트에서
res
객체의 메소드를 사용하여 클라이언트에 응답을 보낼 수 있음writeHead()
: 응답으로 보낼 헤더를 만듦write()
: 응답 본문 데이터 만듦, 여러 번 호출 가능end()
: 클라이언트에 응답 전송. 콜백 함수가 지정되면 응답이 전송된 후 콜백 함수가 호출됨
파일을 읽어서 클라이언트에 보내주기
const http = require("http")
const fs = require("fs")
const server = http.createServer((req, res) => {
console.log("클라이언트 요청 들어옴")
fs.readFile("a.png", (err, data) => {
if(err) throw err
res.writeHead(200, {"Content-Type": "image/png"})
res.write(data)
res.end()
})
})
const port = 3000
server.listen(port, () => {
console.log("서버 시작")
})
- 적절한 Content-Type 헤더 값 사용하기 (적절한
MIME (Multipurpose Internet Mail Extension)
Type 설정하기)
Content-Type | 설명 |
---|---|
text/plain | 일반 텍스트 문서 |
text/html | HTML 문서 |
text/css | CSS 문서 |
text/xml | XML 문서 |
image/jpeg, imag/png | JPEG, PNG 이미지 파일 |
video/mpeg, audio/mp3 | MPEG 비디오 파일, MP3 음악 파일 |
application/zip | ZIP 압축 파이 |
application/json | JSON 형식 파일 |
서버에서 다른 웹 사이트의 데이터를 가져와 응답하기
http
모듈은 서버 뿐만 아니라 클라이언트의 기능도 제공HTTP 클라이언트가 GET이나 POST 방식으로 다른 웹 서버에 데이터를 요청할 수 있음
웹 서버에 요청을 보내는 방식 (메소드)
- HTTP 요청 포맷은 크게 헤더(Header)와 본문(Body)으로 나뉨
메소드 | 설명 |
---|---|
GET | 헤더 부분에 요청 정보들을 넣어 보냄 |
POST | 본문 부분에 요청 정보들을 넣어 보냄 |
PUT | |
DELETE |
익스프레스로 웹 서버 만들기
express
모듈을 사용하여 간단한 코드로 웹 서버의 기능을 구현할 수 있음- 익스프레스에서 제공하는 미들웨어와 라우터를 사용하여 기능을 편리하게 구성할 수 있음
sudo npm install express --save
익스프레스의 시작점 app.js
파일
const express = require("express")
const http = require("http")
var app = express()
app.set("port", process.env.PORT || 3000)
http.createServer(app).listen(app.get("port"), () => {
console.log("익스프레스 시작" + app.get("port"))
})
[참고] express
모듈과 http
모듈을 모두 불러와서 http 서버를 만드는 이유는, express
모듈을 사용해서는 https 서버를 만들 수 없기 때문이라고 한다. express
모듈의 listen
메소드 구현부를 보면 http 서버를 만드는 것을 알 수 있다.
길게 봤을 때 서버를 만들게 된다면 https 서버를 만들게 될 것이므로 일단은 책에서 하라는 대로 따라가자...
app
객체는 익스프레스 서버 객체. 이것을http.createServer()
매개변수로 전달해준다.app
객체에 서버 설정을 위한 속성을 지정하는 등의 역할을 하게 할 수 잇음set()
: 서버 설정을 위한 속성 지정env
: 서버 모드 설정view
: 뷰들이 들어 있는 폴더 또는 폴더 배열 설정view engine
: 디폴트로 사용할 뷰 엔진 설정
get()
: 지정한 속성에 접근use()
: 미들웨어 함수 사용
const express = require("express")
const http = require("http")
const app = express()
app.use((req, res, next) => {
console.log("첫 번째 미들웨어에서 요청 처리")
req.user = "Mike"
next()
})
app.use("/", (req, res, next) => {
console.log("두 번째 미들웨어에서 요청 처리")
res.writeHead(200, {"Content-Type": "text/html; charset=utf-8"})
res.end("<h1>익스프레스 서버에서 " + req.user + "가 응답한 결과</h1>")
})
http.createServer(app).listen(3000, () => {
console.log("익스프레스 서버가 3000번 포트에서 시작됨")
})
미들웨어를 사용하여 필요한 기능을 순차적으로 실행할 수 있음
use()
메소드를 사용하여 어떠한 기능을 미들웨어로 등록하면 모든 클라이언트 요청이 이 미들웨어를 거치면서 기능을 수행하게 할 수 있음next()
메소드를 호출하여 그 다음 미들웨어가 처리할 수 있도록 순서를 넘길 수 있음
라우터는 클라이언트의 요청 경로를 보고 이 요청 정보를 처리할 수 있는 곳으로 기능을 전달해 줌
get()
메소드를 호출하여 라우터로 등록할 수 있음
클라이언트 요청 > 등록된 미들웨어 순서대로 거침 > 라우팅 > 클라이언트 응답
app.use()
로 미들웨어 설정,app.get()
으로 라우터 설정
req
객체의 속성에app
객체가 들어 있어req.app
으로app
객체를 참조할 수 있음익스프레스에서 추가로 사용할 수 있는 응답 객체 메소드
send()
: 클라이언트에 응답 데이터 보냄. HTML 문자열 / Buffer 객체 / JSON 객체 / JSON 배열status()
: HTTP 상태 코드 반환.end()
나send()
같은 전송 메소드를 호출해야 전송 가능sendStatus()
: HTTP 상태 코드 반환. 상태 메세지와 함께 전송됨redirect()
: 웹 페이지 경로를 강제로 이동시킴render()
: 뷰 엔진을 사용하여 문서를 만든 후 전송
익스프레스에서 요청 객체에 추가한 헤더와 파라미터
query
: 클라이언트에서 GET 방식으로 전송한 요청 파라미터 접근body
: 클라이언트에서 POST 방식으로 전송한 요청 파라미터 접근 (body-parser
외장모듈 필요)
미들웨어 사용하기
server-static
- 특정 폴더의 파일을 특정 경로로 접근할 수 있도록 해줌
- 기본 디렉토리 이름은
public
body-parser
- POST 메소드로 요청시 본문 영역에 들어 있는 요청 파라미터를 파싱하여 요청 객체의
body
속성에 넣어줌
- POST 메소드로 요청시 본문 영역에 들어 있는 요청 파라미터를 파싱하여 요청 객체의
요청 라우팅하기
- 경로를 기준으로 사용자가 요청한 기능을 구별
- 익스프레스 객체에서 라우터 객체를 참조하여 사용
- 라우팅 함수 등록
- 라우터 객체를
app
객체에 등록 - 요청 경로를 라우터 객체에 등록할 때 사용하는 메소드는 요청 메소드 이름과 같음
URL 파라미터는 URL 뒤
?
기호 뒤에 오는 요청 파라미터와 달리 URL 주소의 일부에 들어감요청 객체의
params
객체로 접근라우터에서 경로를 지정해줄 때 해당 부분은
:(파라미터명)
과 같은 방식으로 작성됨- 예)
router.route("/process/login/:name")
- 예)
Semantic URL
쿠키와 세션 관리하기
쿠키 : 클라이언트(웹 브라우저)에 저장되는 정보. 일정 기간 클라이언트에 정보를 저장할 때 사용
세션 : 웹 서버에 저장되는 정보. 로그인 여부에 따른 페이지 접근 권한 검증 등에 활용
쿠키 처리하기
cookie-parser
외장 모듈 사용res.cookie()
메소드로 쿠키 설정req.cookies
로 쿠키 객체 접근, 각 속성에 접근
세션 처리하기
express-session
외장 모듈 사용- 세션이 만들어지면
connect.sid
쿠키가 브라우저에 저장됨. 이것은 웹 브라우저에서 세션 정보를 저장할 때 만들어진 것
파일 업로드 기능 만들기
multer
외장 모듈 사용- 파일 업로드 시 POST 방식을 사용하므로
body-parser
미들웨어를 함께 사용 - 멀티 파트 포맷 : 음악이나 이미지 파일 등을 일반 데이터와 함께 웹 서버로 보내기 위해 만든 표준. 일반적으로 웹 서버에서 파일을 업로드할 때 멀티 파트 포맷을 사용
내장모듈 정리
http
: http 서버 구축을 위해 사용path
: 인자로 들어온 문자열을 합쳐 경로 형식의 문자열을 만들어줌fs
: 파일 입출력을 위해 사용
외장모듈 정리
express
: 웹 서버를 쉽게 구축하기 위해 사용body-parser
: POST 메소드로 온 파라미터를 파싱하기 위해 사용cookie-parser
: 쿠키 기능을 사용하기 위해 사용express-session
: 세션 기능을 사용하기 위해 사용serve-static
: 정적 파일을 제공하기 위해 사용. 기본 경로를 지정할 수 있음express-error-handler
: 에러 페이지를 보여주기 위해 사용multer
: 파일 업로드 기능을 사용하기 위해 사용