모든 프로그래밍 언어를 배우다보면 항상 처음에 등장하는 동시에 그 언어의 성격을 맛 볼 수 있는 문구가 존재합니다. 바로 Hello world!
라는 문장입니다. 우리는 이 포스트를 통해 노드로 처음 서버를 열어보고 헬로 월드도 출력해볼 것 입니다.
우리는 서버를 열기 위해 HTTP 모듈
을 이용할 것 입니다. 지난 포스트에서 다룬 모듈사용법에 따라서 require를 해줍니다.
const http = require('http');
다음으로 HTTP 요청에 응답하는 createServer()
메소드를 호출해줍니다. 이때 createServer
메소드의 인수로 요청에 대한 콜백을 넣어서 요청이 들어올 때 마다 콜백을 실행하게 됩니다. 대부분은 콜백 함수의 인자로 req
와 res
를 사용하게 됩니다. req
는 Request, 요청이란 의미로 요청에 대한 정보를 담은 객체이고, res
는 Response, 응답에 대한 정보들을 담은 객체입니다.
const http = require('http');
http.createServer((req, res) => {
res.writeHead(200, {'Content-type': 'text/html; charset=utf-8'});
res.write('<p>Hello world!</p>');
res.end('<p>Hello world?</p>');
}).listen(8080);
서버가 제대로 열렸을지 확인하기 전에 코드부터 설명드리겠습니다.
res.writeHead()
메소드는 응답에 대한 정보를 기록하는 메소드입니다. 첫번째 인수로는 200을 보냈는데 이 숫자는 HTTP 응답 코드 중 하나인 성공을 의미하는 숫자입니다. 그리고 두번째 인수로 응답에 대한 정보를 보내는데, 이때 응답이 html파일임과 utf-8인코딩을 사용한다는 정보를 보내고있습니다.
다음으로 등장한 write()
메소드는 클라이언트에게 보내는 데이터입니다. 이때 보내진 데이터는 body로 보내져 우리눈에 보이게 되죠. 그래서 'Hello world!' html 문자열을 write 메소드에 담았습니다또한 write 메소드는 계속해서 여러번 사용이 가능합니다.
end()
메소드는 응답 종료 메소드입니다. 비워놔도 되고, 인수로 값을 전달해도 됩니다. 만약 지금처러 인수로 어떤 값이 전달이 된다면 그 값을 클라이언트로 전송한 다음 응답을 종료하게 됩니다.
마지막으로 오는 listen()
메소드는 createServer뒤에 오는 메소드입니다. 첫번째 인수로는 클라이언트에게 공개되는 포트번호(여기서는 8080번)이 오고 두번째 인수로는 포트 연결이 성공하면 실행되는 콜백 함수가 옵니다. 위의 예제에서는 생략했지만 추가해보면 다음과 같이 만들 수 있습니다.
const http = require('http');
http.createServer((req, res) => {
res.writeHead(200, {'Content-type': 'text/html; charset=utf-8'});
res.write('<p>Hello world!</p>');
res.end('<p>Hello world?</p>');
})
.listen(8080, ()=>{
console.log('8080 port');
});
이제 제대로 서버를 여는데 성공했는지 확인해볼 차례인데 터미널에 다음과 같이 입력하고 엔터를 누릅니다. 이것은 우리가 작성한 http 요청 코드를 node로 실행하겠다. 즉, 노드를 서버로 이용해 보겠다라고 하는 것 입니다.
node 파일경로
이렇게 입력하셨으면 아무 인터넷 브라우저나 열은 다음에 주소창에 http://localhost:8080
를 입력해보시면 다음과 같이 출력될 것 입니다.우리는 이렇게 첫 번째 서버를 성공적으로 열어보았습니다. 서버 종료는 다시 터미널로 돌아와서 Ctrl+c
를 눌러주세요.
참고로 서버를 닫고 좀 전에 이용한 링크에 가면 다음과 같은 화면이 뜹니다.
조금 전에 다음 코드처럼 listen()
메소드의 두번째 인수로 콜백 함수가 올 수 있다고 했었는데, 이것을 이벤트 리스너
형식으로 처리가 가능합니다. 바로 아래의 코드를 이벤트 리스너 형식으로 처리해보겠습니다.
//변경 전
const http = require('http');
http.createServer((req, res) => {
res.writeHead(200, {'Content-type': 'text/html; charset=utf-8'});
res.write('<p>Hello world!</p>');
res.end('<p>Hello world?</p>');
})
.listen(8080, ()=>{
console.log('8080 port');
});
//이벤트 리스너형식으로 변경
const http = require('http');
const server = http.createServer((req, res) => {
res.writeHead(200, {'Content-type': 'text/html; charset=utf-8'});
res.write('<p>Hello world!</p>');
res.end('<p>Hello world?</p>');
});
server.listen(8080);
server.on('listening', ()=>{
console.log('8080 port');
});
조금전에 write()
메소드를 통해서 html을 전달해서 브라우저에 나타내었습니다. 하지만 이런 방법은 비효율적이기 때문에 다른 방식을 찾아보겠습니다.
더 좋은 방식은 html파일을 따로 만들고 파일 시스템 모듈을 이용해서 읽어서 클라이언트에게 전송하는 방식입니다. 예제에 사용될 html파일은 다음과 같습니다. 우리의 예상대로라면 화면에 'Hello world!'와 '재미있는(?) Node.js'라는 문구가 나오겠죠?
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>node-study</title>
</head>
<body>
<p>Hello world!</p>
<h4>재미있는(?) Node.js</h4>
</body>
</html>
이 html파일을 읽어서 전송하는 코드는 아래와 같습니다. 갑자기 promise가 나와서 당황하실 것 같은데, 파일 시스템은 콜백 형식의 모듈이라서 그냥 사용하면 굉장히 복잡해집니다. 그래서 비교적 사용하기 편한 콜백인 promise를 이용하고자 붙여줬습니다.
또 try~catch 예외처리도 들어가 있는데, 파일 시스템을 읽는게 오류가 하도 자주 뜨는 작업이다 보니 넣게되었습니다.
마지막에 포트번호를 8080으로 줬는데, 아까전에 실시한 실습에서 Ctrl+c 등의 방식으로 서버를 닫았다면 8080 포트를 다시 열어서 사용할 수 있지만, 닫지 않았을 경우에는 이용이 불가능하며 에러메세지가 나옵니다. 이때는 기존의 8080포트를 닫아주거나 8081 등의 번호를 사용해주세요.
const http = require('http');
const fs = require('fs').promises;
http.createServer(async (req, res) => {
try {
//경로는 사용자 환경마다 다릅니다
const data = await fs.readFile('./src/fsServer.html');
res.writeHead(200, {'Content-type': 'text/html; charset=utf-8'});
res.end(data);
}
catch (err) {
console.error(err);
res.writeHead(200, {'Content-type': 'text/html; charset=utf-8'});
res.end(err.message);
}
}).listen(8080);
코드를 이렇게 작성하고 아까처럼 실행을 하면 브라우저에 제대로 표시가 되었음을 확인할 수 있습니다.