안녕하세요! 이번 시간에는 서버를 만들어보겠습니다!
서버를 직접 만든다니 새롭지 않나요? 다른 서버들은 서버를 다운로드받은 후 설정... 설정... 설정... 끝에야 돌릴 수 있잖아요. Node.js는 코드를 통해 서버를 만들고 실행할 수 있습니다. (물론 설정하는 것은 자신의 몫입니다.) 웹서버가 안에 내장되어 있기 때문에 가능합니다.
서버
우선 server.js 파일을 만들고, 그 안에 다음과 같이 써줍니다.
server.js
const http = require('http'); // 서버를 만드는 모듈 불러옴
http.createServer((request, response) => { // 서버 만드는 메소드
console.log('server start!');
}).listen(8080);
잠깐 코드를 볼까요? Node.js는 모듈 시스템을 구축하고 있습니다. 모듈이란, 필요한 것만 불러오는 것이라고 생각하면 됩니다. http 서버가 필요하니 http 모듈을 require 메소드를 통해서 불러와 http 변수에 저장하였습니다. 전 시간에 말했던 npm의 패키지가 이와 비슷한 개념입니다. 단, http 패키지는 Node.js 자체에서 기본적으로 제공하는 패키지이기 때문에 npm install http로 따로 설치할 필요가 없습니다. 서버가 실행된 후의 동작을 콜백 함수로 등록합니다. 콜백 함수 안의 request와 response는 조금 이따 알아볼 예정입니다. http 패키지의 createServer 메소드의 인자로 넣어주면 됩니다. 그리고 8080번 포트에 연결(listen)합니다.
그런 후 cmd를 실행하고 server.js를 만든 곳으로 이동합니다. 이동하는 방법은 cd라는 명령어로 합니다.
위의 사진을 보세요. cd [폴더이름] 으로 원하는 폴더로 이동할 수 있습니다. 상위 폴더로 가는 것은 cd ..하면 됩니다. 사진에서는 상위 폴더로 두 번 이동하고 users폴더, zerocho폴더 순으로 들어갔습니다. 이렇게 각자 server.js를 만든 폴더로 들어가면 됩니다.
그 폴더까지 갔다면 node server.js를 쳐보세요. server.js 파일을 구동하는 명령어입니다. 그리고 웹 브라우저로 http://localhost:8080에 들어가면, cmd에 'server start!' 라고 아래와 같이 뜰겁니다. 콘솔 명령어만 사용했고, 아직 브라우저에는 아무것도 보내지 않았기 때문에 브라우저에는 아무것도 뜨지 않습니다.
만약 8080번 포트 대신에 그냥 일반 주소로 하고 싶다면, 80번 포트로 listen하게 하면 됩니다. 80번 포트는 기본이라 :80을 쓰지 않아도 됩니다. 네이버같은 사이트도 다 80번 포트를 이용하고 있기 때문에 www.naver.com:8080 이렇게 입력하지 않아도 되는 겁니다. 대신 80포트는 이미 다른 프로그램에서 사용하고 있는 경우가 많아 충돌이 자주 발생합니다. 자기 컴퓨터로 할 때는 80포트 대신 다른 포트를 쓰고, 서버에 올릴 때는 80포트로 올리는 게 좋습니다.
Request, Response
이제 createServer 메소드 콜백의 매개변수인 request와 response에 대해서 알아보죠. request는 요청을 담당합니다. 즉 서버로 보내는 요청에 대한 정보가 들어있습니다. 방금 우리가 주소창에 localhost:8080이라고 친 행위도 서버에 그 주소에 해당하는 정보를 달라고 요청한 겁니다. 서버는 항상 대기중이다가 request가 들어올 때 반응하면 됩니다. 그리고 request에 대한 처리를 한 후 결과를 response 객체로 돌려주는 겁니다.
response는 이제 클라이언트(브라우저)로 돌려줄 응답을 담당합니다. 만약 어떤 정보를 보내고 싶다면 response 객체를 활용하면 됩니다. 지금까지 브라우저에 아무것도 안 뜬 이유는 response를 설정하지 않았기 때문입니다. response가 없다면 브라우저에는 아무 것도 전달되지 않습니다. response는 대부분 페이지를 보내지만, 꼭 페이지만을 보낼 필요는 없습니다. JSON, AJAX나 이미지같은 것도 모두 정보입니다.
request -> 서버 처리 -> response로 이어지는 흐름을 기억하세요. 한 가지 더 알아둘 점은 request와 response에는 header과 body가 있습니다. header는 request, response에 대한 정보(종류, 크기, 캐시 여부 등등)가 들어있고, body는 진짜 주고받고자 하는 내용이 들어있습니다. 제 홈페이지 주소를 주소창에 입력했을 때의 request와 response의 header 내용입니다. F12(개발자도구)를 누르고 Network 탭에 가면 볼 수 있습니다.
온갖 정보들이 나오는 데 이것은 사용하기 나름입니다. 나중에 차차 알아가도록 하죠.
server.js 내용을 다음과 같이 바꿔보겠습니다.
const http = require('http');
http.createServer((request, response) => {
return request
.on('error', (err) => { // 요청에 에러가 있으면
console.error(err);
})
.on('data', (data) => { // 요청에 데이터가 있으면
console.log(data);
})
.on('end', () => { // 요청의 데이터가 모두 받아졌으면
response.on('error', (err) => { // 응답에 에러가 있으면
console.error(err);
});
response.statusCode = 200; // 성공 상태 코드
response.setHeader('Content-Type', 'text/plain'); // header 설정
response.write('hi\n'); // body에 정보 탑재
response.end('the end!'); // 정보 탑재 후 브라우저로 전송
});
}).listen(8080);
createServer 메소드의 인자인 response와 request를 사용하기 시작했습니다. 순서대로 살펴보면, 맨 처음은 request.on('error', 콜백)
입니다. 일단 요청에 에러가 있을 수도 있으니 처리하고 보는거죠. 에러가 생기면 서버가 멈춰버리기(죽어버린다고 표현합니다) 때문에 에러는 반드시 처리해줘야합니다.
사소한 에러 하나가 발생해서 서버가 죽었는데 그 사실을 모르고 있다면, 사용자들은 여러분의 서비스를 사용하지 못합니다. 그리고 대체 서비스를 찾겠죠. 이렇게 멀어진 관심은 다시 되돌리기 힘듭니다. (제가 예전에 이 홈페이지에 에러가 난 것을 모르고 자버렸습니다)
다음은 request.on('data', 콜백)
, request.on('end', 콜백);
인데요. 각각 request에 data가 있을 경우 처리하는 부분과, data 처리가 다 끝났음을 알려주는 부분입니다. request에 data가 있는 경우는 HTML 폼 전송같이 폼의 내용을 전송하는 경우 데이터가 request의 data에 실려 서버로 전송됩니다.
요청이 끝났으니까 응답을 해줘야겠죠? end의 콜백에 response해줍니다. 일단 response에도 에러가 생길 수 있으니, response.on('error', 콜백)
로 에러를 처리해줍시다. response.statusCode
는 여러 개가 있는데 지금은 성공적으로 데이터를 전송했다는 것을 알려야하니까 성공의 의미인 200을 설정합니다. statusCode에 대한 강좌 그리고 response의 정보를 가진 header를 설정하는 setHeader 메소드를 사용해서 지금 보내는 컨텐츠의 유형을 평문 텍스트(text/plain)로 설정합니다. 만약 html을 전송하고 싶다면 text/html하면 됩니다. html 전송은 다음 시간에 알아봅니다.
이제 response의 body를 설정해 정보를 보내주어야겠죠? 위의 예시에는 두 메소드가 있는데요. write와 end입니다. end 메소드는 write함과 동시에 response를 종료하는 겁니다. 종료하는 순간 클라이언트로 전송됩니다. write와 end 메소드로 hi\n, the end! 문자열을 전송했습니다. 이제 브라우저에는
라는 짧은 결과가 표시됩니다. 아직은 서버가 좀 허접하죠? 다음 시간에는 html 파일을 만들어서 통째로 전송해봅시다!