Express로 서버 실행하기

소스코드

이 게시물에는 코드작성이 포함되어 있습니다. 소스코드를 받으신 후 진행해 주세요. MEAN Stack/개발 환경 구축에서 설명된 프로그램들(git, npm, atom editor)이 있어야 아래의 명령어들을 실행할 수 있습니다.

git clone https://github.com/a-mean-blogger/hello-world.git
cd hello-world
git reset --hard dead37f
npm install
atom .

- Github에서 소스코드 보기: https://github.com/a-mean-blogger/hello-world/tree/dead37f01c561fae8cc0359cd600449a394e1680


Express는 node.js로 서버를 만드는 framework입니다. node.js와 Express를 사용해서 초간단 웹서버를 만들어 봅시다.
git, node js/NPM, atom 에디터는 모두 설치되어 있겠지요?

git bash를 실행한 후 프로젝트 폴더(저는 hello-world 라고 이름을 지어주었습니다)를 생성하고 git init 명령어로 git 저장소를 생성합니다.

다음으로 npm init 명령어로 현재 폴더에 node 프로젝트를 생성합니다. 이 명령어를 실행하면 프로젝트에 대한 질의 응답이 아래와 같이 나오는데, 일단 아무것도 입력하지 않고 계속 엔터를 쳐서 넘깁시다. 이 질문들을 바탕으로 package.json 파일을 생성하게 되는데, 그냥 엔터를 쳐서 넘기게 되면 해당 질문에 해당하는 항목이 생성되지 않거나, 질문의 기본값(괄호안의 값)이 있는 경우 해당값이 입력됩니다.

**혹시 Is this ok? (yes)에서 엔터를 친 후에 다음으로 넘어가지 않는 경우에는 Ctrl+C를 눌러서 종료시켜줍니다. git bash 버그인지 NPM 버그인지는 모르겠는데 가끔 이럽니다.

생성된 package.json파일은 아래와 같은 텍스트를 담고 있습니다.

{
  "name": "hello-world",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}

npm init 명령어는 사실 이 파일을 생성하는 것이 전부입니다. 여기 눈여겨 봐야 할 부분은

  "main": "index.js", 

바로 이부분인데요, node.js 프로젝트의 메인 코드 파일명이 기록되어 있는 부분입니다. index.js가 기본값으로 입력이 되어 있으니 이 파일을 생성해 봅시다.

다음으로 Express를 설치합니다. Express는 node.js package 이며 NPM을 통해 설치할 수 있습니다.

NPM 명령어를 통해 설치된 package들은 현재_폴더/node_modules 폴더에 저장됩니다.

지금까지의 과정이 잘 이해가 되지 않으시면 Node JS 첫걸음/개발 환경 구축을 다시 읽어 주세요. 자세히 읽어보면 다 설명된 내용입니다.

아래 명령어로 현재폴더를 atom 에디터로 엽니다.

왼쪽 패널의 파일 시스템 창을 보면 modules 폴더의 하위 폴더로 Express가 설치된 것을 확인할 수 있습니다. package.json에 dependencies에도 express가 올라가 있는 것을 볼 수 있습니다.

참고로 파일및 폴더의 생성, 삭제, 이동, 복사, 이름 변경 등은 atom에서도 가능합니다. 파일 시스템 창에서 마우스 오른쪽 버튼을 눌러서 확인해 보세요.

서버를 생성하기 위해 index.js에 다음 코드를 입력해 줍니다.

//index.js

var express = require('express'); // 설치한 express module을 불러와서 변수(express)에 담습니다.
var app = express(); //express를 실행하여 app object를 초기화 합니다.

app.get('/', function(req, res) { // '/' 위치에 'get'요청을 받는 경우,
  res.send('Hello World!'); // "Hello World!"를 보냅니다.
});

app.listen(3000, function(){ //3000번 포트를 사용합니다.
  console.log('Server On!'); //서버가 실행되면 콘솔창에 표시될 메세지입니다.
});

require(모듈_이름) 함수는 node.js에서 기본적으로 주어지는 함수로, modules폴더 안에 설치된 모듈을 불러오는 함수입니다. express 모듈을 express 변수에 담고, express()로 app object를 초기화 하는 것은 Express framework에서 항상 가장 처음하는 것이므로 따라해 줍니다.

app.get, app.listen은 해당부분의 코드가 index.js 실행시 바로 실행되는 것이 아니라, app.get 부분은 서버에 get요청이 있는경우, app.listen은 서버가 실행되는 경우에 각각 실행이 됩니다. 이렇게 어떠한 조건이 갖춰지면 실행되는 코드를 가지는 함수를 event listener(이벤트 리스너)라고 합니다.

app.get 부분을 다시 살펴봅시다. 이번 포스팅에서 가장 중요한 부분입니다.

app.get('/', function(req, res) { // '/' 위치에 'get'요청을 받는 경우,
  res.send('Hello World!'); // "Hello World!"를 보냅니다.
});
app.HTTP_Method_중_하나('Route_주소', 콜백_함수, 콜백_함수, 콜백_함수...)

의 구조를 하고 있습니다. 위에서는 콜백 함수를 하나만 사용했지만 함수사이에 ","를 넣어서 여러개의 함수를 넣을 수도 있습니다.

콜백 함수에는 req, res, next의 parameter들(이 순서만 중요할 뿐 이름은 바꿔도 상관없습니다)이 자동으로 전달됩니다. 다음으로 이 parameter들에 대해 살펴봅시다.

req

request에 관련된 값들과 함수들이 저장되어 있는 object. HTTP request header, 요청 url, cookies, query, body 등의 정보가 저장되어 있습니다.

이 object의 전체 구조를 확인하고 싶을땐 콜백 함수에 console.log(req) 코드를 넣으면 안을 확인할 수 있습니다.(req 뿐만 아니라 나머지 res, next 등도 console.log를 통해 값을 확인해 봅시다!)

res

response에 관련된 값들과 함수들이 저장되어 있는 object. HTTP response header, cookies, HTTP code 등의 정보를 확인하고 값을 변경할 수도 있습니다.

또한 어떠한 방식으로 response할지도 정할 수 있습니다. 위 예제에서는 res.send를 사용해서 텍스트를 response하였습니다.

next

만약 여러개의 콜백 함수를 사용한다면 이 함수를 호출하여 다음번 콜백 함수로 넘어갈 수 있습니다. 위 예제에서는 함수가 하나뿐이므로 parameter에 적지도 않았습니다.

위 코드에서 주석을 빼고 입력하면 atom에서 이렇게 보이겠죠.

hello world강좌라 정말 한 스텝 한 스텝 마다 스크린샷을 찍었습니다.

이제 서버를 실행시킬 차례입니다.

$ node index.js

위 명령어를 입력하면 우리가 코딩한 대로 'Server On!'이라는 메세지가 뜨면서 서버가 실행됩니다.

웹 브라우저를 열고 http://localhost:3000 에 접속해 봅시다. localhost는 http프로토콜에서 자기 자신의 서버에 접속할 때 사용되는 주소이고, 3000은 서버에 접속하는 포트 번호로, app.listen에서 3000으로 설정했기 때문에 3000을 사용합니다. 한 서버에 여러가지 서버 프로그램이 작동하는 경우 포트 번호를 달리해서 구별하게 됩니다. 혹시나 자신의 컴퓨터가 이미 3000번 포트를 사용하고 있다면, 다른 값으로 바꾸어서 실행해 보세요.

웹 브라우저에 주소를 입력하는 것은 서버에 HTTP method 중 GET으로 요청됩니다. 그러므로 위 코드의 app.get콜백_함수가 실행되어 res.send를 통해 우리가 입력한 Hello World!라는 텍스트가 출력이 되는 것입니다.

댓글

j
jungbin lee 2016.12.27
이 블로그를 이제야 알다니! 멋집니다.
I
Ian H 2016.12.28
@jungbin lee,
감사합니다^^;
김태현 2017.01.28
events.js:160       throw er; // Unhandled 'error' event       ^
Error: listen EADDRINUSE :::3000     at Object.exports._errnoException (util.js:1022:11)     at exports._exceptionWithHostPort (util.js:1045:20)     at Server._listen2 (net.js:1262:14)     at listen (net.js:1298:10)     at Server.listen (net.js:1376:9)     at Function.listen (C:\Users\admin\Desktop\MyProject\Web\myapp\node_modules\express\lib\application.js:617:24)     at Object.<anonymous> (C:\Users\admin\Desktop\MyProject\Web\myapp\app.js:15:5)     at Module._compile (module.js:571:32)     at Object.Module._extensions..js (module.js:580:10)     at Module.load (module.js:488:32) [nodemon] app crashed - waiting for file changes before starting...
nodemon 을 치면 이런게 나오는데 왜이러는 걸까요
I
Ian H 2017.01.28
@김태현,
3000을 다른 숫자로 바꿔서 실행해 보세요~
J
Jason 2017.02.13
Is this ok? (yes) 여기에서 엔터 말고 yes 를 입력해야 정상적으로 종료가 되더라고요. 블로그 잘 보고 있습니다^^
I
Ian H 2017.02.17
@Jason,
앗. 그런 방법이 있었네요. 맥에서는 그냥 엔터쳐도 종료가 되거든요.
김동권 2017.05.17
감사합니다 잘배우고 있습니다~
김성환 2017.10.04
현재 폴더를 아톰으로 열기 >> atom . 을 실행하면 command not found가 나오는 데 어떻게 해야 할까요?
$ atom . bash: atom: command not found
I
Ian H 2017.10.04
@김성환,
환경변수가 업데이트 되지 않아서 그렇습니다. 컴퓨터를 재부팅해보세요
김성환 2017.10.04
@Ian H,
PATH 없는것 같아 해결했는데 댓글 달아주셔서 글 안지우겠습니다. 빠른 댓글 감사 드립니다. 
I
Ian H 2017.10.04
@김성환,
해결하셨다니 다행이네요^^
김종하 2017.12.08
"현재폴더를 atom 에디터로 엽니다. "
여기서 "atom 에디터" 링크 404 에러 뜹니다
I
Ian H 2017.12.08
@김종하,
수정하였습니다. 알려주셔서 감사합니다^^
J
Jaehong Ahn 2018.02.06
와....감사합니다.. 진짜 엄청나게 친절하고 세세하게, 또 알기 쉽게 쓰여진 강좌/가이드인거 같습니다. 구글링의 구글링을 거쳐 어쩌다 정말 우연히 여기까지 왔는데 정말 도움이 됩니다. 잘 보고 가요!
I
Ian H 2018.02.13
@Jaehong Ahn,
격려의 말씀 감사합니다^^
반팔 2018.09.19
한 단계 한 단계 따라해보고 있어요. 감사합니다!
I
Ian H 2018.09.19
@반팔,
^^ 화이팅!
컴신 2018.11.08
너무 깔끔하니, 설명이 잘되어있어서 한번 읽었을뿐인데 전부 다 쏙쏙 들어오네요. lan H님 atom에서 에디터 theme  설정 어떤걸로 하셨는지 알려 주실 수 있을까요 ?!  lan H님 에디터가 눈에 확 잘들어오네요!!
I
Ian H 2018.11.08
@컴신,
감사합니다^^ 기본 theme인데.. 아마 저때랑 지금이랑 기본 theme 색깔이 조금 달라진 것 같아요.
j
js lee 2019.03.12
이 게시 글은 2016년도에 작성 되어진건데.... 2019년 이제야 이 블로그를 알다니.... 알기 쉽게 내용을 잘 정리 해주셔서 열심히 공부하겠습니다. 감사합니다.
I
Ian H 2019.03.12
@js lee,
반갑습니다^^ 궁금하신 점 있으시면 질문도 해주세요!
캡틴제라드 2019.06.07
app.get('/',function(req,res){   res.send('Hello World'); });
이 부분에서요, function(req,res) 이 부분이 정확히 어떤 역할을 하는건지 알 수 있을까요?ㅎㅎㅎ function이 무슨 일을 하는지도 궁금합니다!! ㅎㅎ
I
Ian H 2019.06.07
@캡틴제라드,
본문에도 써있듯이 app.get은 event listener 역할을 하는 함수 입니다. 
node index.js로 코드를 실행하면 index.js의 코드들이 위에서 아래로 순서대로 실행되는데, app.get 함수는 두가지 파라메터를 가지고 있죠. 첫번째는 route이고, 두번째는 콜백 함수요.
이처럼 함수(app.get)의 파라메터로 함수(function(req,res){...})를 전달하는 것을 콜백 함수 전달이라고 하고, 전달된 콜백 함수는 원래 함수의 알고리즘에 따라 알맞은 시점에 해당 콜백함수가 호출이 됩니다. 그리고 콜백함수의 파라메터 역시 원래 함수의 알고리즘에 따라 어떠한 값이 들어갈지가 정해집니다.
다시 index.js로 돌아가서, index.js의 코드들이 처음 읽어 내려갈 때는 이 콜백 함수 속의 코드가 실행되지 않습니다.
app.get함수에 의해 이 콜백 함수가 언제 실행될지가 정해집니다. 여기서는 HTTP GET method로 첫번째 파라메터인 '/'에 요청이 오면 콜백 함수의 코드가 실행됩니다. 이름이 콜백 함수인 이유도 함수가 다시 호출(call back)하기 때문에 이런 이름이 붙여졌습니다.
서론이 길었는데, function(req,res){...}은 위 코드에서 원래 함수(app.get)의 파라메터 자리에 위치하고 있죠. 파라메터자리에서 함수를 선언하고 파라메터로서 함수에 전달되는 역할을 합니다.
보통 함수의 선언은 function 함수_이름(파라메터들){함수_코드} 로 하잖아요? 근데 저렇게 함수이름없이 선언되는 함수를 anonymous(어나니머스, 이름이없는) 함수라고 합니다.
function(req,res)는 app.get의 콜백 함수이며, app.get의 알고리즘에 의해 req(오브젝트), res(오브젝트), next(함수) 세 개의 파라메터를 전달받습니다. 위 코드에서 마지막 next는 콜백 함수 코드에서 사용되지 않으므로 삭제를 하여 function(req,res,next)가 아닌 function(req,res)로 사용되었습니다.
혹시 더 이해가 안되시는 부분이 있으면 알려주세요^^
댓글쓰기

이 글에 댓글을 다시려면 SNS 계정으로 로그인하세요. 자세히 알아보기

UP