Node.js에는 아주 간편하게 http
서버를 만들 수 있는 모듈이 기본적으로 탑재되어있다.
아래와 같은 코드만 작성한 뒤, 실행하면 웹서버가 작동하게 된다.
const http = require('http');
http.createServer((req, res) => {
res.write('<h1>Hello, World!</h1>');
res.end();
}).listen(3000);
브라우저에서 http://localhost:3000
으로 접속하면 Hello, World!가 보이며 정상 동작한다는 것을 알 수 있다.
기본적으로 http
서버는 80번 포트를, https
서버는 443번 포트를 사용하는데, 이렇게 자주 사용되는 기본 포트들은 브라우저에서 접속할 때 생략이 가능하다.
https://naver.com
에 접속하면 https://naver.com:443
으로 접속하는 것과 같은 의미인 것이다.
그러나 3000
같은 임의의 포트를 사용하게 되면 반드시 포트 번호를 명시해줘야 정상적으로 동작한다.
이번에는 단순 문자열이 아닌, html
파일을 전달해보자.
const http = require('http');
const fs = require('fs').promises;
http.createServer((req, res) => {
fs.readFile('./index.html').then(data => {
res.end(data)
}).catch(err => {
console.err(err)
res.writeHead(400);
res.end(err.message);
})
}).listen(3000);
우선 파일을 읽기 위해 fs
내장 모듈을 불러온다.
원래 readFile()
은 콜백 함수를 인자로 받아 읽기 성공/실패 이후의 동작을 비동기적으로 핸들링하게 되는데, require('fs').promises
로 가져오게 되면 Promise로 사용할 수 있기 때문에 콜백 지옥을 피하면서 보다 편리하게 사용할 수 있다.
<!DOCTYPE html>
<html lang="en">
<head>
<title>HOME</title>
</head>
<body>
Home Page
</body>
</html>
어쨌든 위와 같은 index.html
파일을 읽어 와서 성공시 파일의 내용을 그대로 반환하고, 실패 시 400번 StatusCode와 함께 오류 메세지를 전달한다.
이번에도 아주 잘 작동하는 것을 볼 수 있다.
처음에 작성했던 코드를 다시 실행해보자.
const http = require('http');
http.createServer((req, res) => {
res.write('<h1>Hello, World!</h1>');
res.end();
}).listen(3000);
그리고 이번엔 크롬이 아닌 사파리에서 http://localhost:3000
에 접속해보자
크롬은 <h1>
태그가 텍스트가 아닌 html 태그임을 인식하고 bold체로 렌더링해줬지만, 사파리는 <h1>
태그조차 텍스트로 렌더링해주는 것을 볼 수 있다.
이렇게 브라우저마다 동작이 다를 수 있기 때문에 정확하고 일관적인 동작을 위해 좀 더 많은 정보를 전달해줘야 한다.
const http = require('http');
http.createServer((req, res) => {
res.writeHead(200,
{ 'Content-Type': 'text/html' });
res.write('<h1>Hello World!</h1>');
res.end();
}).listen(3000);
res.writeHead()
메소드에 200
, { 'Content-Type': 'text/html' }
를 인자로 전달해준다.
이렇게 하면 어떤 브라우저라도 현재 서버에서 보내주는 텍스트가 html
임을 알 수 있게 된다.
이제 사파리에서도 정상적으로 html
태그를 인식하고 렌더링하는 것을 볼 수 있다.
200
은 Status Code라고 부르며, 각 숫자 코드에 따라 의미가 다르기 때문에 상황에 따라 다른 코드를 보내줘야 한다.
200
은 요청이 정상적으로 처리되었음을 암시하는 상태 코드다.
이렇게 작성된 Header는 네트워크 탭에 들어가면 확인할 수 있다.
Status Code 200, Content-Type text/html로 잘 설정된 것을 볼 수 있다.
참고로 res.writeHead()
없이 작성된 첫번째 코드의 실행 결과는 다음과 같다.
크롬이 html
태그를 인식해서 잘 렌더링 해주기는 했지만, Content-Type을 자동으로 넣어주지 않고 누락되어 있는 것을 볼 수 있다.
서버에서 보내주는 텍스트에 한글 등이 포함되어 있다면 다음과 같이 텍스트가 깨지게 된다.
그럴 때는 아래와 같이 charset=utf-8
을 추가해주면 정상 동작한다.
const http = require('http');
http.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
res.write('<h1>안녕, 세계!</h1>');
res.end();
}).listen(3000);
Response Header에도 charset=utf-8
이 잘 추가되었음을 확인할 수 있다.