개발 학습일지(TIL)

[TIL] : Nestjs 에서 express-ejs-layouts 사용하기 require() vs import()

Veams 2023. 3. 6.

작업 배경 및 문제상황

Nest.js 사용환경이다.

 

- 기존에 node.js, express에서 express-ejs-layouts 라이브러리를 잘 사용한 바가 있었다.

- nestjs를 사용하는 이번 프로젝트에서도 express-ejs-layouts 사용하고 싶었다. 그래서 메인으로 사용하고 있는 main.ts에 다음과 같이 ejs 설정 및 express-ejs-layouts작업을 해주었다.

- 참고로, express-ejs-layouts 라이브러리는 ejs를 사용하기 위한 기본 설정 이외에 app.use를 사용한 미들웨어를 통해 프로그램이 작동하도록 설정시켜줘야 한다.

import { ValidationPipe } from '@nestjs/common';
import { NestExpressApplication } from '@nestjs/platform-express';
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { join } from 'path';
import { ejslayouts } from 'express-ejs-layouts';

async function bootstrap() {
  const app = await NestFactory.create<NestExpressApplication>(
    AppModule
    );
  
  app.useGlobalPipes(new ValidationPipe({transform: true}));
  
  //express-ejs-layouts 설정
  app.use(ejslayouts);
  console.log('express');
  app.set('layout', 'layouts/main');  

  //ejs 셋팅
  app.useStaticAssets(join(__dirname, '..', 'views', 'public')); //static폴더를 현재폴더(dirname)에서 한칸 상위('..')에 있는 views폴더 내 public으로 지정
  app.setBaseViewsDir(join(__dirname, '..', 'views'));  //view폴더를 현재폴더(dirname)에서 한칸 상위('..')에 있는 views폴더로 지정
  app.setViewEngine("ejs");


  const PORT = process.env.PORT;

  await app.listen(PORT, function (){
    console.log(`서버가 ${PORT} 포트로 열렸습니다. http://localhost:${PORT}`);
  });
}
bootstrap();

 

하지만 다음의 에러 메시지를 나타내며 작동하지 않았다.

 

[Nest] 28640  - 2023. 03. 06. 오전 11:36:10   ERROR [ExceptionHandler] app.use() requires a middleware function
TypeError: app.use() requires a middleware function

 

문제 원인 분석

- 미들웨어를 사용하기 위해 모듈을 불러오는 코드에 문제가 있다.

- nestjs에서 모듈을 사용하기 위해 import() 메써드를 작성하는데, 사용법을 정확히 알지 못한 상태에서 관성적으로 코드를 작성했다.

- 그래서 오류가 발생했고, 코드의 형태를 다음과 같이 바꾸었다.

 

해법

변경전 : 

import { ejslayouts } from 'express-ejs-layouts';

 

변경후:

const ejslayouts = require('express-ejs-layouts');
 
- 혹은 import * as ejslayouts from 'express-ejs-layouts'도 가능하다.

 

수정된 전체코드

import { ValidationPipe } from '@nestjs/common';
import { NestExpressApplication } from '@nestjs/platform-express';
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { join } from 'path';
import * as ejslayouts from 'express-ejs-layouts';

async function bootstrap() {
  const app = await NestFactory.create<NestExpressApplication>(
    AppModule
    );


  app.useGlobalPipes(new ValidationPipe({transform: true}));
  
  //express-ejs-layouts 설정
  app.use(ejslayouts);
  app.set('layout', 'layouts/main');  

  //ejs 셋팅
  app.useStaticAssets(join(__dirname, '..', 'views', 'public')); //static폴더를 현재폴더(dirname)에서 한칸 상위('..')에 있는 views폴더 내 public으로 지정
  app.setBaseViewsDir(join(__dirname, '..', 'views'));  //view폴더를 현재폴더(dirname)에서 한칸 상위('..')에 있는 views폴더로 지정
  app.setViewEngine("ejs");


  const PORT = process.env.PORT;

  await app.listen(PORT, function (){
    console.log(`서버가 ${PORT} 포트로 열렸습니다. http://localhost:${PORT}`);
  });
}
bootstrap();
 

문제가 해결되어 현재는 express-ejs-layouts 라이브러리를 사용할 수 있게 되었다. 

 

 

알게 된점 

주요 차이점 중 하나는, require()는 모듈 전체를 가져오는 데만 사용할 수 있는 반면 

import()는 모듈 전체는 물론, 해당 모듈에서 개별만 가져오는 데 사용할 수 있다.

 

그리고 또 한 가지,

# import()의 사용법

import { ejslayouts } from 'express-ejs-layouts';

는 모듈에서 ejslayouts 라는 무언가만 개별 가져오기를 하려는 경우이고

import * as ejslayouts from 'express-ejs-layouts';
모듈 전체를 가져오기를 시도하면서 그것을 ejslayouts라고 명명한 한 차이가 있다.
 

문제와 해법을 정리하자면,

기존에는 모듈로부터 개별 가져오기를 하는 문법을 사용해서 문제가 됐고,

이것을 모듈로부터 전체 가져오기로 바꾸었기 때문에 작동이 되고 있는 것 같다.

 

# 여담

사실 import { ejslayouts } from 'express-ejs-layouts'; 은 사실 그 자체로 부자연스러운 코드이다. 

express-ejs-layouts 라이브러리(모듈) 안 에 ejslayouts라는 건 애초에 존재하지도 않기 때문이다. ejslayouts는 내가 임의로 지정한 변수명이니까! 별생각없이 문법을 적용하려해서 발생한 오류였다.

 

다음을 참고해보자.

https://ko.javascript.info/import-export

 

모듈 내보내고 가져오기

 

ko.javascript.info

https://inpa.tistory.com/entry/NODE-%F0%9F%93%9A-require-%E2%9A%94%EF%B8%8F-import-CommonJs%EC%99%80-ES6-%EC%B0%A8%EC%9D%B4-1

 

[NODE] 📚 require vs import 문법 비교 (CommonJS vs ES6)

require vs import 문법 자바스크립트 개발을 하다보면 모듈을 불러오는 문법 두가지 ( require / exports ) 와 ( import / export ) 키워드를 접하게 되는데, 이 둘은 비슷하면서도 달라 가끔 자바스크립트 개발

inpa.tistory.com

https://stackdiary.com/require-vs-import-in-javascript/

 

Require vs. Import in JavaScript - Stack Diary

The import keyword is used to import bindings that are exported by another module, while the require() function is used to load a module in a Node.js application. These two mechanisms are similar, but they have some important differences that you should be

stackdiary.com

 

 

댓글