[Node.js] express 모듈, ejs 템플릿 엔진

Yunhye Park·2023년 10월 15일
0
post-thumbnail

🌱 오늘의 수업 (10/12)

  1. ES6 문법으로 모듈 생성-내보내기-가져오기

  2. express 모듈

  • http 모듈과 express 모듈
  • install (package.json 확인)
  • get, listen, set
  1. ejs 템플릿 엔진
  • 정의 : 자바스크립트가 내장된 HTML 파일
  • install (package.json 확인)
  • 문법과 사용
    • <% %>
    • =, -
    • 서버(back) 측 정보를 프론트로 보내기
    • 백의 데이터이므로 script에서 해당 변수를 사용할 순 없다. ejs 문법이므로 .ejs 파일 내부(body)에서 가능
    • 미들웨어
  1. ejs 관련 extention
  • Prettier와 충돌 방지 : ejs Beautify
  • 색깔 : ejs language support
  1. JS 문법 심화
  • 객체 구조분해(배열, 디렉토리, 문자열)
  • spread 연산자(배열, 디렉토리, 문자열)
  • rest 파라미터 : 함수의 매개변수로 활용

정리할 내용

✅ 지난 시간에 배운 common JS 문법을 ES6문법과 비교해 예시 코드 복기
✅ express 모듈 설치 후 웹 서버 구동하기
✅ ejs 템플릿 엔진은 왜 쓸까?


1. node.js 시작하기

지금까지 자바스크립트를 실행하려면 html 파일을 만들어 브라우저에서 열람하고, 개발자 도구로 콘솔창을 열어서 확인해야 했다. 자바스크립트는 반드시 브라우저를 통해야만 할까? 그건 아니다. Node.js는 브라우저 외의 자바스크립트 런타임 환경을 제공해서 텍스트 에디터 내 터미널로 콘솔을 확인할 수 있다.


node.js 다운로드 페이지에서 프로그램 설치 후, NPM*으로 노드 모듈 패키지를 관리해준다. NPM(Node Package Manager)으로 손쉽게 외부 모듈을 사용할 수 있게 된다. 후술할 express 모듈이 그중 하나다.

npm init
: 문답식으로 npm 설치. npm init --yes를 입력하면 모든 답변에 기본값을 세팅해 NPM을 생성한다. 이 내용을 터미널에 입력하면 package.json 파일이 생성된다.

node.js를 설치하면 ECMAScript에서 제공하는 기본 자바스크립트 문법과 node.js의 기본 문법 모두를 사용할 수 있다. 두 문법 각각을 사용하여 모듈*을 작성해 내보내고 가져오는 작업을 해보자.

모듈(module)?
재사용할 함수는 매번 입력하기 번거롭다. 기능별로 묶어서 퍼즐 조각처럼 필요할 때마다 꺼내 쓰면 편리할 것이다. 이처럼 자주 사용하는 함수나 변수를 하나로 묶은 단위를 '모듈'이라고 한다.

모듈을 내보내고 가져오는 방법이 Common JS와 ES6가 다르다. 모듈은 노드에서 발전한 문법이고, 백엔드에서는 주로 Common JS 문법을 자주 사용한다. 그래도 두 문법을 비교해보는 게 이해하는 데에 도움이 될 것 같다.

2. Common JS와 ES6

먼저 common JS에서 모듈을 생성해 내보내는 것부터 해보자.

2.1 모듈을 Common JS로

math.js 파일을 만들어 두 개의 연산과 하나의 파이값을 변수에 입력하고, 그중 한 개의 모듈을 내보내려고 한다.

const add = (a, b) => a + b;
const minus = (a, b) => a - b;
const PI = 3.14;

module.exports = add;

파일 index.js를 생성해 위에 작성한 모듈(add 변수에 담긴 함수)을 받아오겠다. require에는 불러올 파일을 입력하는데, 상대주소로 작성한다.

// math.js 파일의 add 변수를 동명의 변수로 받아온다. 
const add = require('./math.js')

// add에 인자를 넣어 함수를 실행해 값을 확인한다.
console.log( add(4,5) ); // 9

둘 이상의 값을 내보내고 가져올 땐 어떻게 작성할까?
우선 내보내보자.

const add = (a, b) => a + b;
const minus = (a, b) => a - b;
const PI = 3.14;

module.exports = {
	add,
	minus,
	PI
}

객체라서 중괄호{}안에 묶었을 뿐 내보내는 방식에 차이는 없다.
다만 한 개의 모듈을 내보내든 여럿을 내보내든 상관 없이 변수를 선언하고 내보내는 걸 동시에 할 수 있다.

module.exports.add = (a, b) => a + b;
module.exports.minus = (a, b) => a - b;
module.exports.PI = 3.14;

차이는 가져올 때 발생한다. 객체는 전체를 가져올 수도 있고, 일부만 가져올 수도 있기 때문이다. 일부를 가져올 때엔 require로 가져온 변수만 참조할 수 있다. 전체를 가져오면 그중 어떤 메서드를 사용할지 접근해서 호출한다.

// 객체의 일부를 가져오기
// 객체 분해구조로 가져올 땐 변수명 그대로 가져와야 함
const {add, PI} = require('./math.js');
console.log( add(4, 5) ); // 9
console.log(PI); // 3.14

// 객체 그대로 가져오기
const math = require('./math.js');
console.log( math.minus(4,5) ); // -1

2.2 모듈을 ES6 문법으로

똑같은 내용을 ES6문법으로 작성해보자. 우선 다른 문법을 사용할 거니까 NPM에 이를 명시해야 한다. package.json 파일에 "type": "module"를 입력하면 된다. ES6 문법을 사용하겠다고 명시했으므로 앞서 common JS로 작성한 코드 실행 시 오류가 발생한다.

마찬가지로 하나의 모듈을 내보내고 가져오는 것부터 해본다.

const add = (a, b) => a + b;
const minus = (a, b) => a - b;
const PI = 3.14;

export default add;
// common JS의 module.exports = add;

받아올 땐 새로운 변수를 만든다.

import add2 from "./math_es6.js";

//common JS의 const add = require('./math.js')

여러 모듈을 내보내고 가져올 때 조금 달라진다. 객체 구조분해 할당* 없이 새 식별자를 만들어 가져올 땐 반드시 export default로 내보내야 한다. export만 작성하면 오류가 발생한다.

구조분해 할당(Destructuring Assignment)

  • 구조분해 할당은 '배열[val1, val2] 구조분해 할당'과 '오브젝트{key: value} 구조분해 할당'으로 나뉜다.
  • 배열은 순서가 존재하기 때문에 변수명에 의미를 담는다고 한들 의도대로 순서가 바뀌는 일은 없다. 새 배열에 기존 배열에 없는 값을 변수명과 함께 입력하면 새 값이 생겨난다.
  • 오브젝트는 객체 안의 속성을 key로 사용한다. 기존 변수명을 새로운 변수명으로 바꿀 수 있다. 자연히 기존 변수는 GC(Garbage Collector)의 대상이 된다.

🗝️ 구조분해 할당은 왜 쓸까?
자바스크립트의 대부분은 객체로 이루어져있다. 객체는 여러 속성이나 값이 하나로 묶인 형태이다. 물론 인덱싱으로 참조할 수 있지만, 각 요소에 식별자가 존재한다면 값의 의미를 파악하기 수월할 테다. 숫자로 이루어진 IP 주소 대신 문자로 특정 의미가 담긴 도메인 주소가 기억하기 쉽듯이. 그래서 객체의 값을 해체(구조분해)하여 데이터의 일부 값에 식별자를 붙여(할당) 사용한다.

// 여러 모듈 내보낼 때
const add = (a, b) => a + b;
const minus = (a, b) => a - b;
const PI = 3.14;

export {add, minus}; // default가 없어서 새 변수로 받으면 오류 발생
export default PI; // 제대로 내보냄
// 기존 변수로 모듈을 가져올 때
import {add} from "./math_es6.js";
console.log( add(2, 3) );

// 새 변수로 모듈을 가져올 때
import math from "./math_es6.js"; // 내보낼 때 export default로 했어야 함
console.log(math);

3. 웹 서버 만들기

3.1 http 모듈

이미 존재하는 모듈이라서 따로 설치하거나 불러올 필요가 없다. 객체 생성 등 http 웹 서버 생성과 관련된 기능을 담당한다.

다만 등장한 지 오래된 만큼 지원하지 않는 기능이 많다. 작성해야 하는 코드 양이 늘어나면 가독성 저하 문제 등이 생기는데, express 모듈을 대안으로 사용하면 좋다.

3.2 express 모듈

express 모듈은 http 모듈이 하는 역할(객체 생성) 등을 모두 할 수 있다. 각종 메서드와 미들웨어를 제공해서 다양한 기능을 손쉽게 처리하는 게 가능하고, jade나 ejs 같은 동적 웹 페이지 파일도 지원한다. 여러 모로 http 모듈보다 효율적이라서 웹 어플리케이션 개발은 대부분 express를 활용한다.

3.2.1 express 모듈 설치하기

NPM 설치 후 터미널에 npm install express 입력한다. install의 축약형으로 npm i express도 가능하다. package.json 파일을 보면 express가 설치된 걸 확인할 수 있다.

  "dependencies": {
    "express": "^4.18.2"
  }

설치 가능한 다른 모듈 조회

3.2.2 서버 구동하기

웹 서버 구동은 내장 모듈인 http 모듈로도 처리할 수 있다. 하지만 앞서 말한 대로 express 모듈은 간단한 입력이 가능해서 계속 이 모듈을 사용한다. 아래의 객체 개념은 http 모듈에서 나왔다는 점만 알아두면 되겠다.

서버는 클라이언트의 요청(request)을 받고, 이 요청을 처리하며 반응(response)한다. 결국 요청과 반응을 할 객체가 필요한 것이다.

  • server 객체 : 웹서버 생성 시 사용하는 객체
  • request 객체 : 응답의 첫번째 매개변수로 전달되는 객체
  • response 객체 : 응답의 두번째 매개변수로 전달되는 객체

이 개념을 가지고 아래의 코드를 입력해 서버를 구동해본다.

const express = require("express"); // express 모듈 import
// express 모듈이 export 하는 최상위 함수인 express를 호출하여
// express application을 만들고 이를 app 객체에 담았다.
const app = express();
const PORT = 8000; // 포트는 8000으로

app.get("/", function(req, res) {
  res.send("hi express");
}

app.get("/TEST", function(req, res) {
  res.send("TEST");
}

// 서버 포트 열기
// http 모듈에서는 createServer가 필요했지만
// express에서는 바로 listen을 입력하면 된다.
const server = app.listen(PORT, function() {
  console.log(`http://localhost:${PORT}로 서버 실행`);
}

localhost?
내 컴퓨터를 가리키는 호스트 이름. IP주소로는 127.0.0.1이다.
ex. http://127.0.0.1/8000

4. ejs 템플릿 엔진

웹 페이지의 구조를 담당하는 html 파일. 이는 정적 파일 중 하나이다. 하지만 웹에서의 동적인 기능들이 점점 더 강조되면서 클라이언트의 요청에 따라 웹에서 보여질 화면(결과)이 달라지게 된다. 템플릿 엔진은 동적인 결과물을 정적 파일에 효율적으로 담기 위해 사용한다.

여기서 말하는 효율은 어떤 의미인가? express 모듈은 서버 구동을 위한 객체들을 생성하고 클라이언트의 요청에 따른 결과물을 제공하는 게 본연의 역할이기에, 이 모듈로 클라이언트에 전달할 파일의 데이터를 한 줄씩 html 코드나 자바스크립트 코드로 바꾸는 건 무리일 테다.

그래서 템플릿 엔진을 활용한다. 템플릿 엔진은 문법과 설정에 따라 파일을 html 형식으로 변환한다. 특히 ejs는 Embedded JavaScript의 약자로 html 파일과 이면서 자바스크립트가 내장된 것이다. 무엇보다 html 문법과 거의 유사하기 때문에 처음 접했을 때도 적응이 용이하다.

즉 자바스크립트 코드로 연산된 결과를 변수에 담고, 그 변수를 뷰(view) 파일에서 사용하는 식으로 활용한다. 뷰 파일과 자바스크립트 코드 파일을 각각의 쓰임에 맞게 따로 작성할 수 있기에 그만큼 코드 관리가 편리해진다.

이 또한 외부 모듈 중 하나이기에 express 모듈처럼 터미널로 설치해야 한다.
npm install ejs

4.1 ejs 문법

// ejs 템플릿 설정
app.set("view engine", "ejs");

// ejs으로 렌더링
app.get("/test", (req, res) => {
	res.render("test");
});

html과 같은 방식으로 작성하되 자바스크립트 코드 앞뒤에 <% %>를 삽입한다.

단, 줄바꿈이 필요하면 마찬가지로 <% %>를 자바스크립트 코드의 시작과 끝에 달아줘야 한다.

변수를 가져올 땐 상황에 따라 두 기호(=, -) 중 하나를 추가한다.

<%= %>
다른 파일의 html을 이스케이프 해서 값을 가져올 때 쓴다.

<%- include ('다른 view 파일의 상대주소')>
다른 파일의 html 코드를 그대로 가져온다. 즉 Raw값을 사용할 수 있다.


참고

node express 모듈 사용하기
express 그리고 템플릿엔진 ejs


생각

  • 수업에서는 express 모듈에서 ejs 템플릿 엔진으로 넘어가는 흐름을 이해하지 못했었다. 왜 사용하는지 알 수 없으니 어떤 역할을 하는 건지 아리송했다.
    이번 포스팅에선 전체 흐름을 정리하기 위해 '왜?'를 풀이하는 데에 집중했다.

  • 여전히 완벽하게 이해한 거 같지는 않지만.. 적어도 윤곽이 잡힌다.

    • 모듈 : 쉽게 말해 특정 기능이 담긴 조각.
    • express 모듈 : 웹 서버 구동할 때 주로 사용하는 외부 모듈
    • ejs 템플릿 엔진 : 자바스크립트가 내장된 html 형식으로 변환해주는 템플릿. 이 또한 특정 기능 조각이므로 모듈에 해당.
profile
일단 해보는 편

0개의 댓글