6.1 익스프레스 프로젝트 시작하기
- package.json 생성: `npm init` 명령어를 실행한다. 이 과정에서 `package.json` 파일이 생성되며, 프로젝트에 대한 세부 정보(이름, 버전, 설명 등)를 입력할 수 있다.
- Express 설치: `npm i express` 여기서 i 는 install의 줄임말이다. `npm install express`와 동일한 동작을 수행한다. `npm i -D nodemon`은 nodemon을 설치한다. 여기서 `-D`는 `--save-dev`의 축약형이며, 이는 패키지를 `package.json` 파일의 `devDependencies` 섹션에 추가한다. 개발 의존성은 프로덕션 환경에서는 필요하지 않고, 개발 과정에서만 필요한 패키지들을 나타낸다. nodemon은 개발 중에 서버를 자동으로 재시작해주는 도구이다.
- 기본 서버 파일 생성: 서버의 역할을 할 app.js를 다음과 같이 만들어준다.
단순한 문자열 대신 HTML로 응답하고 싶다면 res.sendFile 메서드를 사용할 수 있다. 사용시 파일의 경로를 path 모듈을 사용해서 지정해야 한다.
6.2 자주 사용하는 미들웨어
미들웨어란?
미들웨어는 Express 애플리케이션에서 요청과 응답 사이에서 특정 작업을 수행하는 함수들이다. 각 미들웨어는 요청-응답 사이클에서 순차적으로 실행된다.
- morgan: HTTP 요청을 로그하는 미들웨어이다. 개발 중에 어떤 요청이 서버에 들어왔는지를 콘솔에 기록하여 확인할 때 유용하다. 각 요청에 대한 정보를 자동으로 로그하므로 디버깅에 도움이 된다. `tiny`, `dev`, `common`, `combined`등 다양한 로깅 포맷을 제공한다.
- static: 정적 파일(이미지, css파일, 자바스크립트 파일 등)을 제공하기 위한 미들웨어이다. 이 미들웨어를 사용하면, 지정된 디렉토리의 파일들을 웹서버에서 바로 접근할 수 있도록 설정할 수 있다.
- body-parser: 요청의 본문(body): 요청의 본문(body)을 파싱하는 미들웨어다. 이 미들웨어는 JSON 데이터, URL 인코딩 데이터, 텍스트 데이터 등 다양한 형식의 본문을 적절한 `req.body` 형태로 변환한다. Express 4.16.0 이상에서는 이 기능이 Express에 내장되어 있어 별도로 설치할 필요가 없다.
- cookie-parser: 요청 헤더에 포함된 쿠키를 파싱하여 `req.cookies`에 저장하는 미들웨어다. 이를 통해 서버는 클라이언트의 쿠키를 쉽게 읽을 수 있다. 또한, 서명된 쿠키를 지원하여 보안성을 강화할 수 있다.
- express-session: 세션 관리를 위한 미들웨어다. 이 미들웨어는 서버 측에서 사용자별 세션을 생성하고 유지할 수 있게 해준다. 이를 통해 사용자 인증 상태를 유지하거나 사용자별 정보를 저장하는 등의 기능을 구현할 수 있다. 세션 정보는 서버에 저장되며, 클라이언트는 세션을 식별할 수 있는 쿠키가 전송된다.
6.2.6 미들웨어의 특성 활용하기
미들웨어가 어떻게 순차적으로 요청을 처리하고, 에러를 핸들링하는지 알아보겠다.
- req(Request 객체): `req` 객체는 HTTP 요청에 관한 정보를 담고 있으며, 클라이언트에서 서버로 보낸 데이터에 접근할 수 있게 해준다. 예를 들어, `req.body`를 통해 POST 요청의 본문에 접근하거나, `req.params`로 URL 파라미터에 접근하고, `req.query`로 쿼리 파라미터를 얻을 수 있다.
- res(Response 객체): `res` 객체는 HTTP 응답을 다루며, 서버가 클라이언트에 데이터를 보내는 방법을 제공한다. 예를 들어, `res.send()`를 사용하여 텍스트 응답을 보내거나, `res.json()`으로 JSON 형식의 응답을 전송할 수 있다. `res.status()`를 통해 HTTP 상태 코드를 설정할 수도 있다.
- next(Next 함수): `next` 함수는 미들웨어 체인에서 다음 미들웨어로 제어를 넘기는 역할을 한다. `next()`를 호출하면 처리를 다음 미들웨어로 이동시키며, 특정 미들웨어나 라우터를 건너뛰고 싶을 때는 `next(route)`를 사용할 수 있다. 만약 에러가 발생했을 때, 이를 처리하는 에러 핸들링 미들웨어로 직접 이동하고 싶다면 `next(err)`를 호출하면 된다.
- res.locals: 한 요청의 수명 주기 동안에만 유효한 응답 로컬 변수를 포함하는 객체이다. `res.locals`에 저장된 값들은 같은 요청-응답 사이클 내에서 미들웨어와 뷰 템플릿 간에 데이터를 공유하는 데 사용된다. 즉, 한 요청에 대해 생성된 `res.locals`의 값은 그 요청에 대한 응답이 완료되면 사라진다. 이는 요청별 상태를 유지하는 데 유용하다.
- res.locals vs app.set: `app.set`은 애플리케이션 전반에 걸쳐 영구적으로 사용될 설정값을 정의한다. `app.set`으로 설정된 값은 애플리케이션의 모든 요청과 응답 사이클에서 유효하며, 애플리케이션의 전역 상태나 구성을 정의하는데 사용된다. 반면에 `res.locals`는 한 요청의 응답 객체 내에서만 유효한 임시 저장소로 사용된다. 각 요청마다 독립적인 값을 가지며, 주로 템플릿에 데이터를 전달하거나, 요청 사이클 내에서 필요한 정보를 임시로 저장하는 데 사용된다.
6.2.7 multer
`multer`는 파일 업로드를 위해 사용되는 미들웨어다. `multipart/form-data` 형식의 폼 데이터를 처리할 때 주로 사용된다. 이 형식은 주로 파일이나 이미지를 서버로 전송할 때 필요하다.
- 파일 저장: `multer`는 파일을 디스크에 저장하거나 메모리에 임시로 보관하는 기능을 제공한다.
- 구성 옵션: 파일 저장 위치, 파일명, 허용 파일 형식, 파일 크기 제한 등을 구성할 수 있다.
- 접근성: 파일은 `req.file` 또는 `req.files`를 통해 요청 처리기에서 접근할 수 있다.
multer 설정
파일을 디스크에 저장하도록 설정하는 예시다.
파일을 처리할 라우트를 설정할 수 있다.
사용 예시
- 단일 파일 업로드
- 여러 파일 업로드
6.3 Router 객체로 라우팅 분리하기
Router 객체 사용 예시: 라우팅을 분리하기 위해 각 라우트 별로 파일을 만들고, 각 파일에서 `express.Router()`를 사용하여 라우터 인스턴스를 생성한다.
메인 앱 파일(예: app.js)에서 위에서 생성한 라우터 모듈을 가져와서 사용한다. `app.use()` 메서드를 사용하여 라우터를 앱에 마운트한다.
위 코드에서 `/api` 경로를 기반으로 `userRoutes`와 `postRoutes` 라우터를 마운트했다. 이렇게 하면 사용자 목록을 조회하는 URL은 ` http://localhost:3000/api/users`가 된다.
클라이언트가 서버에 HTTP 요청을 보낼 때 URL의 일부를 동적으로 지정할 수 있다. `라우트 매개변수`를 사용해서 이것을 구현할 수 있으며, 콜른 `:`과 함께 변수 이름을 사용하여 이 매개변수를 설정한다. 이를 통해 URL의 특정 부분을 변수로써 캡처하여 요청 처리 로직에서 사용할 수 있다. 사용 예시는 아래와 같다.
이처럼 `Router` 객체를 사용하면 Express 앱의 라우트를 효율적으로 관리하고, 각 라우트를 별도의 파일로 분리하여 프로젝트의 구조를 개선할 수 있다.
6.4 req, res 객체 살펴보기
`req(Request)` 객체
- req.app: Request 객체와 연결된 express의 인스턴스를 반환한다
- req.body: 클라이언트가 보낸 데이터를 담고 있는 객체로, `body-parser` 미들웨어가 이를 파싱한다
- req.cookies: 클라이언트가 보낸 쿠키들을 담고 있는 객체다. 이를 사용하려면 `cookie-parser` 미들웨어가 필요하다
- req.ip: 요청을 보낸 클라이언트의 IP 주소를 반환한다
- req.params: 라우트 매개변수에 대한 정보를 담고 있는 객체이다
- req.query: URL 쿼리 스트링의 매개변수를 담고 있는 객체이다.
- req.signedCookies: 서명된 쿠키들을 담고 있는 객체로, 서명된 쿠키를 다룰 때 사용한다
- req.get(headers): 특정 HTTP 요청 헤더의 값을 반환한다
`res(Response)` 객체
- res.app: Response 객체와 연결된 express의 인스턴스를 반환한다
- res.cookie(name, value): 클라이언트에게 쿠키를 설정한다
- res.clearCookie(name): 클라이언트의 쿠키를 제거한다
- res.end(): 응답 프로세스를 종료한다. 이 메서드는 데이터나 응답 본문 없이 응답을 종료한다
- res.json(object): JSON 형식의 응답을 전송한다
- res.locals: 라우트 핸들러에서 뷰로 변수를 전달할 때 사용한다
- res.render(view, locals): 뷰 엔진을 사용하여 HTML 뷰를 생성하고 클라이언트에게 전송한다
- res.send(body): 다양한 유형의 응답을 전송한다. 문자열, 버퍼, 객체, 배열 등을 전송할 수 있다
- res.sendFile(path): 파일을 전송한다
- res.set(header, value): HTTP 응답 헤더를 설정한다
- res.status(code): HTTP 응답 상태 코드를 설정한다
`메서드 체이닝(Method Chaining)`은 객체의 메서드를 연속적으로 호출하는 프로그래밍 패턴이다. 이 패턴은 각 메서드가 객체를 반환함으로써 다음 메서드를 즉시 호출할 수 있도록 해준다. 이 방식은 코드를 더 읽기 쉽고 간결하게 만들어주며, 일련의 연산을 순차적으로 적용할 때 유용하다. 메서드 체이닝을 사용하기 위해서는, 각 메서드가 호출된 객체의 참조(보통 `this`)를 반환해야 한다. 이렇게 하면, 체인의 다음 링크로 작용하는 다음 메서드를 계속 호출할 수 있다.
6.5 템플릿 엔진 사용하기
템플릿 엔진은 서버에서 HTML 파일을 동적으로 생성할 때 사용하는 도구이다. 템플릿 엔진을 사용하면, 정적 HTML 파일에 서버 사이드 데이터를 삽입하고 조건부 논리, 반복, 서버 사이드 변수 등을 사용하여 페이지를 동적으로 구성할 수 있다.
6.5.1 퍼그(제이드)
pug(예전에는 jade)는 Node.js와 함께 사용되는 고성능의 템플릿 엔진이다. pug는 HTML을 작성하는 대체 문법을 제공하며, 깔끔하고 간결한 방법으로 서버 사이드 데이터를 HTML에 쉽게 통합할 수 있도록 한다. pug는 HTML 태그를 더 짧은 코드로 작성할 수 있게 해주며, 들여쓰기를 사용하여 HTML 구조를 표현한다.
- HTML 표현: pug에서는 괄호나 닫는 태그를 사용하지 않고 HTML을 작성한다. 예를 들어, HTML의 `<p> hello, jwcs</p>`는 pug에서는 단순히 `p hello, jwcs`로 표현된다.
- 변수: pug에서는 `-`로 시작하는 코드 라인으로 자바스크립트 변수를 선언할 수 있으며, `#{}` 구문을 사용하여 HTML에 변수를 삽입할 수 있다
- 반복문: `each` 또는 `while`을 사용하여 반복문을 구현할 수 있다
- 조건문: `if`, `else if`, `else` 등의 조건문을 사용할 수 있다.
- Include: 다른 pug 파일을 포함할 때 `include` 키워드를 사용한다. 이는 파일을 분할하고 코드를 재사용할 때 유용하다
- Extends와 Block: pug에서 `extends`는 한 템플릿이 다른 템플릿의 레이아웃을 상속받을 수 있도록 해준다. 이를 통해 기본 레이아웃을 정의하고, 다른 템플릿에서 이 레이아웃을 확장할 수 있다. `block`은 템플릿 상속에서 자식 템플릿이 내용을 삽입할 수 있는 영역을 정의한다
6.5.2 넌적스
넌적스(Nunjucks)는 서버사이드에서 HTML을 동적으로 생성하는 데 사용되며, 템플릿 상속, 비동기 제어, 사용자 정의 필터 등의 기능을 지원한다.
- 변수: 넌적스에서는 `{{변수명}}`구문을 사용하여 템플릿에 변수를 삽입한다
- 반복문: 넌적스는 `{% for %}` 구문을 사용하여 반복문을 구현한다
- 조건문: `{% if %}`, `{% elif %}`, `{% else %}` 구문을 사용하여 조건부 렌더링을 수행한다
- Include: `{% include %}` 구문을 사용하여 다른 템플릿 파일의 내용을 포함시킨다
- extends: `{% extends %}` 구문을 사용하여 다른 템플릿의 레이아웃을 상속받는다
- block: `{% block %}` 구문은 템플릿 상속 시 자식 템플릿이 내용을 삽입할 수 있도록 한다
6.5.3 에러 처리 미들웨어
이 코드에서 첫 번째 `app.use`는 존재하지 않는 라우트에 대한 요청이 있을 때 404 에러 객체를 생성하고, 이를 두 번째 `app.use`(에러처리 미들웨어)로 전달한다. 에러 처리 미들웨어에서는 상태 코드를 설정하고, 개발 환경 여부에 따라 에러 정보를 조정한 후, `error` 템플릿을 렌더링하여 사용자에게 에러 페이지를 보여준다.
'개발' 카테고리의 다른 글
[Node.js] 7장 (0) | 2024.02.16 |
---|---|
[Node.js] 1~6장 복습 (0) | 2024.02.15 |
[Node.js] 5장 (0) | 2024.02.07 |
[Node.js] 4장 (0) | 2024.02.04 |
[Node.js] 3장 (0) | 2024.02.04 |