# Model-View-Controller

## Model-View-Controller

기본적으로 Nest는 기본적으로 [Express](https://github.com/expressjs/express) 라이브러리를 사용합니다. 따라서 Express에서 MVC (Model-View-Controller) 패턴을 사용하는 모든 기술은 Nest에도 적용됩니다.

먼저 [CLI](https://github.com/nestjs/nest-cli) 도구를 사용하여 간단한 Nest 응용 프로그램을 스캐 폴딩하십시오.

```bash
$ npm i -g @nestjs/cli
$ nest new project
```

MVC 앱을 만들려면 HTML 뷰를 렌더링하기 위해 [template engine](http://expressjs.com/en/guide/using-template-engines.html)도 필요합니다.

```bash
$ npm install --save hbs
```

우리는`hbs` ([Handlebars](https://github.com/pillarjs/hbs#readme)) 엔진을 사용했지만 요구 사항에 맞는 것을 사용할 수 있습니다. 설치 프로세스가 완료되면 다음 코드를 사용하여 Express 인스턴스를 구성해야합니다.

```typescript
@@filename(main)
import { NestFactory } from '@nestjs/core';
import { NestExpressApplication } from '@nestjs/platform-express';
import { join } from 'path';
import { AppModule } from './app.module';

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

  app.useStaticAssets(join(__dirname, '..', 'public'));
  app.setBaseViewsDir(join(__dirname, '..', 'views'));
  app.setViewEngine('hbs');

  await app.listen(3000);
}
bootstrap();
@@switch
import { NestFactory } from '@nestjs/core';
import { join } from 'path';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create(
    AppModule,
  );

  app.useStaticAssets(join(__dirname, '..', 'public'));
  app.setBaseViewsDir(join(__dirname, '..', 'views'));
  app.setViewEngine('hbs');

  await app.listen(3000);
}
bootstrap();
```

우리는 [Express](https://github.com/expressjs/express)에 `public` 디렉토리가 정적 자산을 저장하는 데 사용되고 `views` 는 템플릿을 포함하며 `hbs` 템플릿 엔진은 HTML 출력을 렌더링합니다.

## Template rendering

이제 그 안에 `views` 디렉토리와 `index.hbs` 템플릿을 만들어 봅시다. 템플릿에서 컨트롤러에서 전달 된 `message`를 인쇄합니다.

```markup
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>App</title>
  </head>
  <body>
    {{ "{{ message }\}" }}
  </body>
</html>
```

다음으로 `app.controller` 파일을 열고 `root()`메소드를 다음 코드로 바꿉니다 :

```typescript
@@filename(app.controller)
import { Get, Controller, Render } from '@nestjs/common';

@Controller()
export class AppController {
  @Get()
  @Render('index')
  root() {
    return { message: 'Hello world!' };
  }
}
```

이 코드에서는 `@Render()` 데코레이터에서 사용할 템플릿을 지정하고 있으며, 라우트 핸들러 메소드의 반환 값은 렌더링을 위해 템플릿으로 전달됩니다. 반환 값은 템플릿에서 만든 `message`자리 표시자와 일치하는 `message`속성이 있는 객체입니다.

응용 프로그램이 실행되는 동안 브라우저를 열고 `http://localhost:3000`으로 이동하십시오. `Hello world!`메시지가 나타납니다.

## Dynamic template rendering

애플리케이션 로직이 어떤 템플릿을 렌더링할지 동적으로 결정해야하는 경우에는 `@Res()` 데코레이터를 사용하고, `@Render()` 데코레이터가 아닌 경로 핸들러에 뷰 이름을 제공해야합니다.

> info **힌트** Nest는`@Res()`데코레이터를 감지하면 라이브러리 별 `response` 객체를 삽입합니다. 이 객체를 사용하여 템플릿을 동적으로 렌더링할 수 있습니다. 응답 객체 API에 대해 자세히 알아보십시오 [여기](http://expressjs.com/en/api.html).

```typescript
@@filename(app.controller)
import { Get, Controller, Render } from '@nestjs/common';
import { Response } from 'express';
import { AppService } from './app.service';

@Controller()
export class AppController {
  constructor(private readonly appService: AppService) {}

  @Get()
  root(@Res() res: Response) {
    return res.render(
      this.appService.getViewName(),
      { message: 'Hello world!' },
    );
  }
}
```

## Example

실제 사례는 [여기](https://github.com/nestjs/nest/tree/master/sample/15-mvc)에서 확인할 수 있습니다.

## Fastify

이 [챕터](https://app.gitbook.com/techniques/http-performance)에서 언급했듯이, 호환 가능한 HTTP 공급자를 Nest와 함께 사용할 수 있습니다. 그러한 라이브러리 중 하나는 [Fastify](https://github.com/fastify/fastify)입니다. Fastify로 MVC 응용 프로그램을 만들려면 다음 패키지를 설치해야합니다.

```bash
$ npm i --save fastify point-of-view handlebars
```

다음 단계는 플랫폼과 관련된 약간의 차이점을 제외하고 Express와 거의 동일한 프로세스를 다룹니다. 설치 과정이 완료되면 `main.ts` 파일을 열고 내용을 업데이트하십시오 :

```typescript
@@filename(main)
import { NestFactory } from '@nestjs/core';
import { NestFastifyApplication, FastifyAdapter } from '@nestjs/platform-fastify';
import { AppModule } from './app.module';
import { join } from 'path';

async function bootstrap() {
  const app = await NestFactory.create<NestFastifyApplication>(
    AppModule,
    new FastifyAdapter(),
  );
  app.useStaticAssets({
    root: join(__dirname, '..', 'public'),
    prefix: '/public/',
  });
  app.setViewEngine({
    engine: {
      handlebars: require('handlebars'),
    },
    templates: join(__dirname, '..', 'views'),
  });
  await app.listen(3000);
}
bootstrap();
@@switch
import { NestFactory } from '@nestjs/core';
import { FastifyAdapter } from '@nestjs/platform-fastify';
import { AppModule } from './app.module';
import { join } from 'path';

async function bootstrap() {
  const app = await NestFactory.create(AppModule, new FastifyAdapter());
  app.useStaticAssets({
    root: join(__dirname, '..', 'public'),
    prefix: '/public/',
  });
  app.setViewEngine({
    engine: {
      handlebars: require('handlebars'),
    },
    templates: join(__dirname, '..', 'views'),
  });
  await app.listen(3000);
}
bootstrap();
```

Fastify API는 약간 다르지만 이러한 메소드 호출의 최종 결과는 동일하게 유지됩니다. Fastify와의 차이점은`@Render()`데코레이터에 전달된 템플릿 이름은 파일 확장자를 포함해야 한다는 것입니다.

```typescript
@@filename(app.controller)
import { Get, Controller, Render } from '@nestjs/common';

@Controller()
export class AppController {
  @Get()
  @Render('index.hbs')
  root() {
    return { message: 'Hello world!' };
  }
}
```

응용 프로그램이 실행되는 동안 브라우저를 열고 `http://localhost:3000`으로 이동하십시오. `Hello world!`메시지가 나타납니다.

## Example

실제 사례는 [여기](https://github.com/nestjs/nest/tree/master/sample/17-mvc-fastify)에서 확인할 수 있습니다.
