Search
▪️

Express.js를 이용한 Web Server 만들기

express-generator, npm scripts, bin/www

기본 http Module만으로 Server를 구현하게 되면, Refactoring을 했다고 하더라도 Cookie나 Session에 대한 적용을 하게 되면 해야할 작업들도 많고 Code가 매우 지저분해진다. 이에 따라 Express.js라는 Framework를 사용하게 된다. Express.js가 상당히 Code를 깔끔하게 만들어 준다.
Express.js를 이용하게 되면, 기존 http Module을 이용한 Server에 비해서 Cookie, Session, 데이터베이스에 대한 연동이 비교적 쉽다.
Express.js는 굉장히 강력하다. 여러 Framework 들 중 가장 보편성 있고, 가장 실무에서 이용할 법한 Framework이다.
Express.js라는 Package를 직접 설치하여 모든 File과 폴더에 대해서 직접 Setting을 해줘도 되지만, express-generator를 통해서 비교적 쉽게 초기 Setting을 마칠 수 있다. 아래 명령어를 이용하면 된다.
npm install -g express-generator express $directoryName —view=$viewEngineName
start Script를 제외한 나머지 Script들은 npm run을 통해서 Script를 실행한다. start Script는 npm start만으로 실행이 가능하다.

Middleware 이해하기

app.set() → Express.js 설정 또는 값 저장
app.use() → Middleware 설정
app.options()는 CORS에서 주로 쓴다.
mogan Package의 logger()는 Http Request가 Router 들어왔을 때, Method와 Path, Response의 일부를 기록해둔다. 즉, Response의 일부를 기록하기 때문에 Route

유명한 Middlewares (morgan, body-parser, cookie-parser, express-session, flash)

원래 Body Parser를 쓰지 않으면, req.on('data'), req.on('end') Event에 대해서 사용자가 직접 Parsing을 수행해야 했었다. 그렇지 않으면 Request의 내용에 대해서 정확히 Catch할 수 없었다. 시간이 지나 Body Parser Package를 쓰지 않아도, Express.js에서 자체적으로 지원할 수 있도록 Method가 생겼다. (Express.js 4.16부터)
Exprss.js의 static같은 경우, static으로 지정한 폴더 내에 원하는 File이 존재하지 않으면 next()를 호출하고 그렇지 않으면 해당 File을 Return하는 방식이다. 따라서 일반적으로 불필요한 Server 작업을 줄이기 위해서 logger()를 최상단, static()을 그 다음에 이용한다.
session에서 Option값으로 주는 secret의 경우, 여기에 할당한 값을 cookieParser() Method의 인자로 동일하게 주어야 한다. 이 secret이라고 하는 Key 값은 Server로 부터 받은 Cookie가 맞는지 혹은 위조된 Cookie인지 확인할 때 사용한다. 따라서 Server는 Client로 부터 Cookie의 값을 이용하여 Request를 보내게 되면, Server는 Cookie Parser로 Parsing할 때 이 secret을 이용하여 Parsing하게 된다. secret 값이 다르면, Cookie를 Abort한다.
secret외의 session의 Option들 중에서, saveUninitialized는 처음의 빈 Session 객체도 저장을 할지, resave는 Session 객체에 수정사항이 없더라도 저장을 할지를 정하게 된다.
connect-flash의 flash() 일회성 Message를 띄울 수 있도록 돕는 Method이다.

Routing Middleware

실제로 Express.js를 이용할 때, next() Method도 없고 response에 대한 Method도 없다면 Client는 Timeout이 걸릴 때까지 무한 로딩하게 된다.

404 Handling Middleware & Error Handling Middleware

없는 Route Path에 대해서는 next()도 Response Method도 존재하지 않기 떄문에 무한 로딩이 걸릴 수 있으므로 이런 Path에 대해서도 처리를 해줘야 한다.
따라서 존재하지 않는 Path에 대해서는 404 Error Page로 Handling하게 된다.

Pug 기본 문법

- 뒤에 변수를 선언할 수 있고, = 뒤에 선언한 변수를 이용할 수 있다.
속성은 명시는 () 안에 작성하게 된다.
div는 생략이 가능하다
ID는 #, Class는 .으로 표현할 수 있다.
태그가 갖는 내용은 태그에서 한 칸 띄우고 작성한다.
|를 이용하여 Multi Line으로 작성이 가능하다. (Script 내에 JavaScript를 작성하려고 Multi Line을 허용해야 할 경우, script.으로 이용이 가능하다.)

Pug 심화 (조건, 반복, include, layout)

부분 별로 반복되는 것들은 include, 전체가 반복되는 것들은 layout으로 빼두어 사용한다.
layout을 이용하게 되면, 바뀌는 부분들은 block으로 빼둘 수 있는데, block의 경우 기본 값을 지정할 수 있다.

Middleware Tips (res.locals, req.app.get(), express.json())

res.locals는 views에서 이용할 수 있는 변수들을 둘 수 있다. 즉, render() Method안에 변수를 두지 않아도 views에서 이용할 수 있다는 것이다.
res.locals의 장점은 Middlewares를 여럿 두었을 때, 꼭 render()가 호출되는 Middleware에서 res.locals를 하지 않아도 된다는 것이다. 다른 Middleware에서 res.locals로 변수를 할당할 수도 있다는 것이다.
req.app.get() Method도 중요한데, app.get($arg) Method의 경우 app.set($arg)으로 지정한 것을 불러올 수 있는 Method이다. 그렇다면 app.get()은 이와 같은데, req.app.get()을 하는 이유는 무엇인가? → req에 담아서 Router에서 이를 사용할 수 있도록 하여 Handling 하기 위해서이다. 즉, req가 끝나기 전까지 req의 app.get()로 얻은 값에 대해서 접근할 수 있는 것이다. (일종의 객체 속성을 이용한 원리이다.)
app.use(express.json())과 같이 Json Parser를 두는 Middleware의 설정을, app.use((req, res, next) ⇒ { express.json()(req, res, next);}) 과 같이 바꿔서 표현할 수 있다. 이렇게 바꿔서 표현하는 이유는, 이전 구문과 달리 Middleware를 표시하고 끝이 아니라, express.json() Middleware 위에 로직을 처리할 수 있도록 Code를 작성할 수 있기 때문이다.
** req.app.get()이 아닌, req.app.set()을 하지 않도록 주의해야 한다. 설정된 Key와 Value를 Req가 날아가는 동안 확인이 가능할 뿐 아니라, 매 req마다 이렇게 되면 원하지 않는 값이 계속 설정될 수도 있기 때문이다.