Showing preview only (1,064K chars total). Download the full file or copy to clipboard to get everything.
Repository: nestjskr/docs.nestjs.kr
Branch: main
Commit: 7ad5edd439f4
Files: 126
Total size: 949.3 KB
Directory structure:
gitextract__5bt60q5/
├── .gitignore
├── README.md
└── content/
├── application-context.md
├── cli/
│ ├── libraries.md
│ ├── overview.md
│ ├── scripts.md
│ ├── usages.md
│ └── workspaces.md
├── components.md
├── controllers.md
├── custom-decorators.md
├── discover/
│ ├── who-uses.json
│ └── who-uses.md
├── enterprise.md
├── exception-filters.md
├── faq/
│ ├── errors.md
│ ├── global-prefix.md
│ ├── http-adapter.md
│ ├── hybrid-application.md
│ ├── multiple-servers.md
│ ├── request-lifecycle.md
│ └── serverless.md
├── first-steps.md
├── fundamentals/
│ ├── async-components.md
│ ├── circular-dependency.md
│ ├── dependency-injection.md
│ ├── dynamic-modules.md
│ ├── execution-context.md
│ ├── lazy-loading-modules.md
│ ├── lifecycle-events.md
│ ├── module-reference.md
│ ├── platform-agnosticism.md
│ ├── provider-scopes.md
│ └── unit-testing.md
├── graphql/
│ ├── cli-plugin.md
│ ├── complexity.md
│ ├── directives.md
│ ├── extensions.md
│ ├── federation.md
│ ├── field-middleware.md
│ ├── guards-interceptors.md
│ ├── interfaces.md
│ ├── mapped-types.md
│ ├── mutations.md
│ ├── plugins.md
│ ├── quick-start.md
│ ├── resolvers-map.md
│ ├── scalars.md
│ ├── schema-generator.md
│ ├── subscriptions.md
│ └── unions-and-enums.md
├── guards.md
├── interceptors.md
├── introduction.md
├── microservices/
│ ├── basics.md
│ ├── custom-transport.md
│ ├── exception-filters.md
│ ├── grpc.md
│ ├── guards.md
│ ├── interceptors.md
│ ├── kafka.md
│ ├── mqtt.md
│ ├── nats.md
│ ├── pipes.md
│ ├── rabbitmq.md
│ └── redis.md
├── middlewares.md
├── migration.md
├── modules.md
├── openapi/
│ ├── cli-plugin.md
│ ├── decorators.md
│ ├── introduction.md
│ ├── mapped-types.md
│ ├── migration-guide.md
│ ├── operations.md
│ ├── other-features.md
│ ├── security.md
│ └── types-and-parameters.md
├── pipes.md
├── recipes/
│ ├── cqrs.md
│ ├── crud-generator.md
│ ├── documentation.md
│ ├── hot-reload.md
│ ├── mikroorm.md
│ ├── mongodb.md
│ ├── nest-commander.md
│ ├── prisma.md
│ ├── router-module.md
│ ├── serve-static.md
│ ├── sql-sequelize.md
│ ├── sql-typeorm.md
│ └── terminus.md
├── security/
│ ├── authentication.md
│ ├── authorization.md
│ ├── cors.md
│ ├── csrf.md
│ ├── encryption-hashing.md
│ ├── helmet.md
│ └── rate-limiting.md
├── support.md
├── techniques/
│ ├── caching.md
│ ├── compression.md
│ ├── configuration.md
│ ├── cookies.md
│ ├── events.md
│ ├── file-upload.md
│ ├── http-module.md
│ ├── logger.md
│ ├── mongo.md
│ ├── mvc.md
│ ├── performance.md
│ ├── queues.md
│ ├── serialization.md
│ ├── server-sent-events.md
│ ├── sessions.md
│ ├── sql.md
│ ├── streaming-files.md
│ ├── task-scheduling.md
│ ├── validation.md
│ └── versioning.md
└── websockets/
├── adapter.md
├── exception-filters.md
├── gateways.md
├── guards.md
├── interceptors.md
└── pipes.md
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
.idea
================================================
FILE: README.md
================================================
# NestJS 한국어 메뉴얼
## NestJS 프레임워크
NestJS는 Typescript 에서 사용할 수 있는 가장 모던하고 세련된 프레임워크이며, 유연하고 세련된 기능을 제공합니다. NestJS는 Typescript개발이 즐겁고 좀더 창의적일 수 있도록 하기 위해서 만들어졌습니다. NestJS를 사용하면 Typescript를 사용한 웹 개발에 있어서, 보다 중요한 비지니스 로직을 구현하는데 집중할 수 있습니다.
## 기여방법
NestJS의 한글 매뉴얼은 많은 분들의 기여를 필요로합니다. 계속해서 업데이트를 해나갈 예정이며, 자유로운 번역을 통해 한국어 메뉴얼을 더욱 완성도 있는 형태로 만들어 나갈것입니다.
* 오타나 수정사항에 대해서는 `Pull Request`를 보내주시면 리뷰를 통해 반영됩니다.
* 새로운 번역도 자유롭게 `Pull Request`를 보내주시면 리뷰를 통해 반영됩니다.
### 1. Issue
이 레포지토리 `Issue` 에 수정 요청사항을 등록해주시면 됩니다.
### 2. Pull Request
`Pull Request`의 경우 규칙에 따라 등록을 해주셔야 합니다. 자세한 사항은 [Discussions](https://github.com/nestjskr/docs.nestjs.kr/discussions) 를 참조해 주시기 바랍니다.
## 기여자 보상
* 매뉴얼 레포지터리의 `README.md` 하단에 기여자 리스트를 표시할 예정입니다.
## 라이센스
NestJS 한국어 매뉴얼은 영문 매뉴얼과 동일하게 `MIT 라이센스`를 따릅니다.
## 커뮤니티
NestJS 번역에 관련된 커뮤니티는 이 레포지토리의 [Discussions](https://github.com/nestjskr/docs.nestjs.kr/discussions) 을 활용합니다.
* [NestJS Korea 슬랙 참여하기](https://join.slack.com/t/nestjskorea/shared_invite/zt-1i1rac8s3-EOHU_8SKjNsgtoeHtnS1Hg)
* [NestJS Korea 카카오톡 오픈 채팅방](https://open.kakao.com/o/ggLiN79c)
* [NestJS 한국어 메뉴얼 번역 Discussions](https://github.com/nestjskr/docs.nestjs.kr/discussions)
================================================
FILE: content/application-context.md
================================================
### Standalone applications
There are several ways of mounting a Nest application. You can create a web app, a microservice or just a bare Nest **standalone application** (without any network listeners). The Nest standalone application is a wrapper around the Nest **IoC container**, which holds all instantiated classes. We can obtain a reference to any existing instance from within any imported module directly using the standalone application object. Thus, you can take advantage of the Nest framework anywhere, including, for example, scripted **CRON** jobs. You can even build a **CLI** on top of it.
#### Getting started
To create a Nest standalone application, use the following construction:
```typescript
@@filename()
async function bootstrap() {
const app = await NestFactory.createApplicationContext(AppModule);
// application logic...
}
bootstrap();
```
The standalone application object allows you to obtain a reference to any instance registered within the Nest application. Let's imagine that we have a `TasksService` in the `TasksModule`. This class provides a set of methods that we want to call from within a CRON job.
```typescript
@@filename()
const app = await NestFactory.createApplicationContext(AppModule);
const tasksService = app.get(TasksService);
```
To access the `TasksService` instance we use the `get()` method. The `get()` method acts like a **query** that searches for an instance in each registered module. Alternatively, for strict context checking, pass an options object with the `strict: true` property. With this option in effect, you have to navigate through specific modules to obtain a particular instance from the selected context.
```typescript
@@filename()
const app = await NestFactory.createApplicationContext(AppModule);
const tasksService = app.select(TasksModule).get(TasksService, { strict: true });
```
Following is a summary of the methods available for retrieving instance references from the standalone application object.
<table>
<tr>
<td>
<code>get()</code>
</td>
<td>
Retrieves an instance of a controller or provider (including guards, filters, and so on) available in the application context.
</td>
</tr>
<tr>
<td>
<code>select()</code>
</td>
<td>
Navigates through the modules graph to pull out a specific instance from the selected module (used together with strict mode as described above).
</td>
</tr>
</table>
> info **Hint** In non-strict mode, the root module is selected by default. To select any other module, you need to navigate the modules graph manually, step by step.
If you want the node application to close after the script finishes (e.g., for a script running CRON jobs), add `await app.close()` to the end of your `bootstrap` function:
```typescript
@@filename()
async function bootstrap() {
const app = await NestFactory.createApplicationContext(AppModule);
// application logic...
await app.close();
}
bootstrap();
```
#### Example
A working example is available [here](https://github.com/nestjs/nest/tree/master/sample/18-context).
================================================
FILE: content/cli/libraries.md
================================================
### Libraries
많은 애플리케이션들은 동일한 일반적인 문제들을 해결하거나, 몇몇 다른 컨텍스트에서 모듈러 컴포넌트들을 재사용할 필요가 있습니다. Nest는 이러한 문제를 해결하는 몇 가지 방법이 있지만, 각 방법들은 다른 구조적, 조직적 목표를 충족시키는데 도움을 주는 방식으로 해당 문제를 해결하기 위해 서로 다른 수준에서 동작합니다.
Nest [모듈](/modules)들은 하나의 애플리케이션 내에서 컴포넌트들을 공유를 가능하게하는 실행 컨텍스트를 제공하는데 유용합니다. 모듈들은 또한 다른 프로젝트에 설치할 수 있는 재사용가능한 라이브러리를 생성하기 위해 [npm](https://npmjs.com)으로 패키징될 수 있습니다. 이것은 서로 다르거나, 느슨하게 연결되거나 독립적인 조직에서 사용되는 설정가능하고, 재사용가능한 라이브러리를 배포하는데 효과적인 방법이 될 수 있습니다 (예: 서드파티 라이브러리 배포/설치).
밀접하게 조직된 그룹들 사이에서(예: 회사/프로젝트 경계 내에서) 코드를 공유하기 위해서, 컴포넌트 공유에 대해 더 가볍게 접근하는 것은 유용할 수 있습니다. Monorepos는 이것을 가능하게 하는 구조로 생겨났고, Monorepo 내에서 **라이브러리**는 코드를 쉽고, 가벼운 방식으로 공유하는 방법을 제공합니다. Nest monorepo에서, 라이브러리를 사용하는 것은 컴포넌트를 공유하는 애플리케이션의 쉬운 조립을 가능하게 합니다. 실제로, 이것은 모듈러 컴포넌트들을 구축하고 구성하는데 초점을 맞추기 위해 모놀리식 애플리케이션과 개발 프로세스의 분해를 권장합니다.
#### Nest libraries
A Nest library is a Nest project that differs from an application in that it cannot run on its own. A library must be imported into a containing application in order for its code to execute. The built-in support for libraries described in this section is only available for **monorepos** (standard mode projects can achieve similar functionality using npm packages).
For example, an organization may develop an `AuthModule` that manages authentication by implementing company policies that govern all internal applications. Rather than build that module separately for each application, or physically packaging the code with npm and requiring each project to install it, a monorepo can define this module as a library. When organized this way, all consumers of the library module can see an up-to-date version of the `AuthModule` as it is committed. This can have significant benefits for coordinating component development and assembly, and simplifying end-to-end testing.
#### Creating libraries
Any functionality that is suitable for re-use is a candidate for being managed as a library. Deciding what should be a library, and what should be part of an application, is an architectural design decision. Creating libraries involves more than simply copying code from an existing application to a new library. When packaged as a library, the library code must be decoupled from the application. This may require **more** time up front and force some design decisions that you may not face with more tightly coupled code. But this additional effort can pay off when the library can be used to enable more rapid application assembly across multiple applications.
To get started with creating a library, run the following command:
```bash
nest g library my-library
```
When you run the command, the `library` schematic prompts you for a prefix (AKA alias) for the library:
```bash
What prefix would you like to use for the library (default: @app)?
```
This creates a new project in your workspace called `my-library`.
A library-type project, like an application-type project, is generated into a named folder using a schematic. Libraries are managed under the `libs` folder of the monorepo root. Nest creates the `libs` folder the first time a library is created.
The files generated for a library are slightly different from those generated for an application. Here is the contents of the `libs` folder after executing the command above:
<div class="file-tree">
<div class="item">libs</div>
<div class="children">
<div class="item">my-library</div>
<div class="children">
<div class="item">src</div>
<div class="children">
<div class="item">index.ts</div>
<div class="item">my-library.module.ts</div>
<div class="item">my-library.service.ts</div>
</div>
<div class="item">tsconfig.lib.json</div>
</div>
</div>
</div>
The `nest-cli.json` file will have a new entry for the library under the `"projects"` key:
```javascript
...
{
"my-library": {
"type": "library",
"root": "libs/my-library",
"entryFile": "index",
"sourceRoot": "libs/my-library/src",
"compilerOptions": {
"tsConfigPath": "libs/my-library/tsconfig.lib.json"
}
}
...
```
There are two differences in `nest-cli.json` metadata between libraries and applications:
- the `"type"` property is set to `"library"` instead of `"application"`
- the `"entryFile"` property is set to `"index"` instead of `"main"`
These differences key the build process to handle libraries appropriately. For example, a library exports its functions through the `index.js` file.
As with application-type projects, libraries each have their own `tsconfig.lib.json` file that extends the root (monorepo-wide) `tsconfig.json` file. You can modify this file, if necessary, to provide library-specific compiler options.
You can build the library with the CLI command:
```bash
nest build my-library
```
#### Using libraries
With the automatically generated configuration files in place, using libraries is straightforward. How would we import `MyLibraryService` from the `my-library` library into the `my-project` application?
First, note that using library modules is the same as using any other Nest module. What the monorepo does is manage paths in a way that importing libraries and generating builds is now transparent. To use `MyLibraryService`, we need to import its declaring module. We can modify `my-project/src/app.module.ts` as follows to import `MyLibraryModule`.
```typescript
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { MyLibraryModule } from '@app/my-library';
@Module({
imports: [MyLibraryModule],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
```
Notice above that we've used a path alias of `@app` in the ES module `import` line, which was the `prefix` we supplied with the `nest g library` command above. Under the covers, Nest handles this through tsconfig path mapping. When adding a library, Nest updates the global (monorepo) `tsconfig.json` file's `"paths"` key like this:
```javascript
"paths": {
"@app/my-library": [
"libs/my-library/src"
],
"@app/my-library/*": [
"libs/my-library/src/*"
]
}
```
So, in a nutshell, the combination of the monorepo and library features has made it easy and intuitive to include library modules into applications.
This same mechanism enables building and deploying applications that compose libraries. Once you've imported the `MyLibraryModule`, running `nest build` handles all the module resolution automatically and bundles the app along with any library dependencies, for deployment. The default compiler for a monorepo is **webpack**, so the resulting distribution file is a single file that bundles all of the transpiled JavaScript files into a single file. You can also switch to `tsc` as described <a href="https://docs.nestjs.com/cli/monorepo#global-compiler-options">here</a>.
================================================
FILE: content/cli/overview.md
================================================
### 시작하기
[Nest CLI](https://github.com/nestjs/nest-cli) 는 Nest application 초기화, 개발 및 유지보수 하는데 도움이 되는 명령줄-인터페이스 도구입니다. 프로젝트 스케폴딩, 개발모드 제공, 빌드 및 번들링 도구 등 다양한 방법을 지원 합니다. 이 도구는 잘 구성된 아키텍쳐 패턴들을 구현하여 여러분의 애플리케이션이 견고한 구조를 가질 수 있도록 합니다.
#### 설치
**참고**: 이 가이드에서는 [npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm) 을 사용하여 Nest CLI를 포함한 패키지를 설치하는 방법에 대해 설명합니다. 선호하는 다른 패키지 매니저를 사용해도 좋습니다. npm 을 사용하면 OS 명령줄에서 `nest` CLI 바이너리 파일의 위치를 찾는 데 몇 가지 옵션을 사용할 수 있습니다. 여기서는 `-g`옵션을 사용하여 `nest` 바이너리를 전역으로 설치하는 방법을 설명합니다. 이는 어느정도의 편의성을 제공하며, 해당 설치 방법을 전제로 문서를 작성 하였습니다. **어떠한** `npm` 패키지를 전역으로 설치하면 올바른 버전이 실행되고 있는지 확인하는 책임은 사용자에게 있습니다. 또한 다른 프로젝트 이더라도 **같은** 버전의 CLI 를 실행 한다는 걸 의미합니다. 합리적인 대안은 [npx](https://github.com/npm/npx) 프로그램(또는 다른 패키지 매니저와 유사한 기능)을 사용하여 Nest CLI의 **managed version**을(를) 실행하는 것입니다. 자세한 내용은 [npx 설명서](https://github.com/npm/npx) 및/또는 DevOps 지원 담당자에게 문의하세요.
`npm install -g` 명령을 사용하여 CLI를 전역으로 설치합니다. (전역 설치에 대한 자세한 내용은 위의 **참고** 항목을 참조하세요).
```bash
$ npm install -g @nestjs/cli
```
#### 기본 흐름
설치되면 `nest` 실행 파일을 통해 OS 명령줄에서 직접 CLI 명령을 호출할 수 있습니다. 다음을 입력하여 사용 가능한 `nest` 명령을 확인해 보세요
```bash
$ nest --help
```
다음과 같은 구문을 사용하여 개별적인 명령어에 대한 도움말을 볼 수 있습니다. `new`, `add`등과 같은 명령어에 대한 자세한 도움말을 보려면 아래의 예에서 `generate` 자리에 명령어를 입력하면 됩니다.
```bash
$ nest generate --help
```
개발 모드에서 새로운 Nest 프로젝트를 생성하거나 빌드, 실행 시키려면 프로젝트의 상위 폴더로 이동한 후 다음 명령어를 실행합니다.
```bash
$ nest new my-nest-project
$ cd my-nest-project
$ npm run start:dev
```
브라우저에서 [http://localhost:3000](http://localhost:3000)을 열어 실행 중인 애플리케션을 확인합니다. 소스 파일을 변경하면 앱이 자동으로 다시 컴파일하고 로드합니다.
#### 프로젝트 구조
`nest new` 를 실행하면 Nest는 새 폴더를 만들고 초기 설정파일들을 만들어 boilerplate 애플리케이션 구조를 생성합니다. 이 문서의 설명에 따라 기본 구조에서 새 컴포넌트를 추가하면서 작업을 이어나가면 됩니다. 우리는 `nest new` 로 생성한 프로젝트의 구조를 **standard mode** 라고 부릅니다. 또한 Nest는 **monorepo mode** 라고 하는 여러 프로젝트 및 라이브러리를 관리하기위한 대체 구조를 지원합니다.
**build** 프로세스가 작동하는 방식과 내장 [라이브러리](/cli/library) 지원에 대한 몇 가지 구체적인 고려 사항 외에도(기본적으로 monorepo mode 는 monorepo-style의 프로젝트 구조에서 발생할 수 있는 빌드 복잡성을 단순화합니다), 나머지 Nest 기능 과 이 문서는 standard mode 및 monorepo mode 프로젝트 구조 모두에 동일하게 적용됩니다. 나중에 언제든지 standard mode에서 monorepo mode로 쉽게 전환할 수 있으므로 Nest에 대해 배우는 동안 이 결정을 하지 않아도 괜찮습니다.
두 모드 중 하나를 사용하여 여러 프로젝트를 관리할 수 있습니다. 다음은 각 모드의 차이점을 간단히 요약한 것입니다.
| Feature | Standard Mode | Monorepo Mode |
| ----------------------------------------------------- | ------------------------------------------------------------------ | ---------------------------------------------------------- |
| Multiple projects | Separate file system structure | Single file system structure |
| `node_modules` & `package.json` | Separate instances | Shared across monorepo |
| Default compiler | `tsc` | webpack |
| Compiler settings | Specified separately | Monorepo defaults that can be overridden per project |
| Config files like `.eslintrc.js`, `.prettierrc`, etc. | Specified separately | Shared across monorepo |
| `nest build` and `nest start` commands | Target defaults automatically to the (only) project in the context | Target defaults to the **default project** in the monorepo |
| Libraries | Managed manually, usually via npm packaging | Built-in support, including path management and bundling |
가장 적합한 모드를 결정하는 데 도움이 되는 자세한 내용은 [Workspaces](/cli/monorepo) 및 [Libraries](/cli/libraries) 섹션을 참조하세요.
<app-banner-courses></app-banner-courses>
#### CLI 명령어 문법
모든 `nest` 명령어들은 동일한 형식을 따릅니다
```bash
nest commandOrAlias requiredArg [optionalArg] [options]
```
예시:
```bash
$ nest new my-nest-project --dry-run
```
여기서 `new` 는 _commandOrAlias_ 입니다.`new` 의 별칭은 `n` 입니다. `my-nest-project` 는 _requiredArg_ 입니다. _requiredArg_ 가 입력되지 않은 경우, `nest` 에서 이를 입력하라고 합니다. 또한, `--dry-run` 의 약식 표현은 `-d` 입니다. 이 점을 참고하면, 다음 명령은 위의 명령과 동일합니다.
```bash
$ nest n my-nest-project -d
```
대부분의 명령과 일부 옵션에는 별칭이 있습니다. `nest new --help` 를 실행하여 이러한 옵션과 별칭들을 보고 위의 구조에 대해 이해했는지 확인하세요.
#### 명령어 정리
명령별 옵션을 보려면 다음 명령어들 중 하나에 대해 `nest <command> --help` 를 실행하세요.
각 명령에 대한 자세한 내용은 [usage](/cli/uses)를 참조하세요.
| Command | Alias | Description |
| ---------- | ----- | ----------------------------------------------------------------------------------------------------- |
| `new` | `n` | Scaffolds a new _standard mode_ application with all boilerplate files needed to run. |
| `generate` | `g` | Generates and/or modifies files based on a schematic. |
| `build` | | Compiles an application or workspace into an output folder. |
| `start` | | Compiles and runs an application (or default project in a workspace). |
| `add` | | Imports a library that has been packaged as a **nest library**, running its install schematic. |
| `update` | `u` | Update `@nestjs` dependencies in the `package.json` `"dependencies"` list to their `@latest` version. |
| `info` | `i` | Displays information about installed nest packages and other helpful system info. |
================================================
FILE: content/cli/scripts.md
================================================
### Nest CLI and scripts
This section provides additional background on how the `nest` command interacts with compilers and scripts to help DevOps personnel manage the development environment.
A Nest application is a **standard** TypeScript application that needs to be compiled to JavaScript before it can be executed. There are various ways to accomplish the compilation step, and developers/teams are free to choose a way that works best for them. With that in mind, Nest provides a set of tools out-of-the-box that seek to do the following:
- Provide a standard build/execute process, available at the command line, that "just works" with reasonable defaults.
- Ensure that the build/execute process is **open**, so developers can directly access the underlying tools to customize them using native features and options.
- Remain a completely standard TypeScript/Node.js framework, so that the entire compile/deploy/execute pipeline can be managed by any external tools that the development team chooses to use.
This goal is accomplished through a combination of the `nest` command, a locally installed TypeScript compiler, and `package.json` scripts. We describe how these technologies work together below. This should help you understand what's happening at each step of the build/execute process, and how to customize that behavior if necessary.
#### The nest binary
The `nest` command is an OS level binary (i.e., runs from the OS command line). This command actually encompasses 3 distinct areas, described below. We recommend that you run the build (`nest build`) and execution (`nest start`) sub-commands via the `package.json` scripts provided automatically when a project is scaffolded (see [typescript starter](https://github.com/nestjs/typescript-starter) if you wish to start by cloning a repo, instead of running `nest new`).
#### Build
`nest build` is a wrapper on top of the standard `tsc` compiler (for [standard projects](https://docs.nestjs.com/cli/overview#project-structure)) or the webpack compiler (for [monorepos](https://docs.nestjs.com/cli/overview#project-structure)). It does not add any other compilation features or steps except for handling `tsconfig-paths` out of the box. The reason it exists is that most developers, especially when starting out with Nest, do not need to adjust compiler options (e.g., `tsconfig.json` file) which can sometimes be tricky.
See the [nest build](https://docs.nestjs.com/cli/usages#nest-build) documentation for more details.
#### Execution
`nest start` simply ensures the project has been built (same as `nest build`), then invokes the `node` command in a portable, easy way to execute the compiled application. As with builds, you are free to customize this process as needed, either using the `nest start` command and its options, or completely replacing it. The entire process is a standard TypeScript application build and execute pipeline, and you are free to manage the process as such.
See the [nest start](https://docs.nestjs.com/cli/usages#nest-start) documentation for more details.
#### Generation
The `nest generate` commands, as the name implies, generate new Nest projects, or components within them.
#### Package scripts
Running the `nest` commands at the OS command level requires that the `nest` binary be installed globally. This is a standard feature of npm, and outside of Nest's direct control. One consequence of this is that the globally installed `nest` binary is **not** managed as a project dependency in `package.json`. For example, two different developers can be running two different versions of the `nest` binary. The standard solution for this is to use package scripts so that you can treat the tools used in the build and execute steps as development dependencies.
When you run `nest new`, or clone the [typescript starter](https://github.com/nestjs/typescript-starter), Nest populates the new project's `package.json` scripts with commands like `build` and `start`. It also installs the underlying compiler tools (such as `typescript`) as **dev dependencies**.
You run the build and execute scripts with commands like:
```bash
$ npm run build
```
and
```bash
$ npm run start
```
These commands use npm's script running capabilities to execute `nest build` or `nest start` using the **locally installed** `nest` binary. By using these built-in package scripts, you have full dependency management over the Nest CLI commands\*. This means that, by following this **recommended** usage, all members of your organization can be assured of running the same version of the commands.
\*This applies to the `build` and `start` commands. The `nest new` and `nest generate` commands aren't part of the build/execute pipeline, so they operate in a different context, and do not come with built-in `package.json` scripts.
For most developers/teams, it is recommended to utilize the package scripts for building and executing their Nest projects. You can fully customize the behavior of these scripts via their options (`--path`, `--webpack`, `--webpackPath`) and/or customize the `tsc` or webpack compiler options files (e.g., `tsconfig.json`) as needed. You are also free to run a completely custom build process to compile the TypeScript (or even to execute TypeScript directly with `ts-node`).
#### Backward compatibility
Because Nest applications are pure TypeScript applications, previous versions of the Nest build/execute scripts will continue to operate. You are not required to upgrade them. You can choose to take advantage of the new `nest build` and `nest start` commands when you are ready, or continue running previous or customized scripts.
#### Migration
While you are not required to make any changes, you may want to migrate to using the new CLI commands instead of using tools such as `tsc-watch` or `ts-node`. In this case, simply install the latest version of the `@nestjs/cli`, both globally and locally:
```bash
$ npm install -g @nestjs/cli
$ cd /some/project/root/folder
$ npm install -D @nestjs/cli
```
You can then replace the `scripts` defined in `package.json` with the following ones:
```typescript
"build": "nest build",
"start": "nest start",
"start:dev": "nest start --watch",
"start:debug": "nest start --debug --watch",
```
================================================
FILE: content/cli/usages.md
================================================
### CLI command reference
#### nest new
Creates a new (standard mode) Nest project.
```bash
$ nest new <name> [options]
$ nest n <name> [options]
```
##### Description
Creates and initializes a new Nest project. Prompts for package manager.
- Creates a folder with the given `<name>`
- Populates the folder with configuration files
- Creates sub-folders for source code (`/src`) and end-to-end tests (`/test`)
- Populates the sub-folders with default files for app components and tests
##### Arguments
| Argument | Description |
| -------- | --------------------------- |
| `<name>` | The name of the new project |
##### Options
| Option | Description |
| ------------------------------------- | --------------------------------------------------------------------------------------------------------------- |
| `--dry-run` | Reports changes that would be made, but does not change the filesystem.<br/> Alias: `-d` |
| `--skip-git` | Skip git repository initialization.<br/> Alias: `-g` |
| `--skip-install` | Skip package installation.<br/> Alias: `-s` |
| `--package-manager [package-manager]` | Specify package manager. Use `npm`, `yarn`, or `pnpm`. Package manager must be installed globally.<br/> Alias: `-p` |
| `--language [language]` | Specify programming language (`TS` or `JS`).<br/> Alias: `-l` |
| `--collection [collectionName]` | Specify schematics collection. Use package name of installed npm package containing schematic.<br/> Alias: `-c` |
#### nest generate
Generates and/or modifies files based on a schematic
```bash
$ nest generate <schematic> <name> [options]
$ nest g <schematic> <name> [options]
```
##### Arguments
| Argument | Description |
| ------------- | -------------------------------------------------------------------------------------------------------- |
| `<schematic>` | The `schematic` or `collection:schematic` to generate. See the table below for the available schematics. |
| `<name>` | The name of the generated component. |
##### Schematics
| Name | Alias | Description |
| ------------- | ----- | --------------------------------------------------------------------------------------------------- |
| `app` | | Generate a new application within a monorepo (converting to monorepo if it's a standard structure). |
| `library` | `lib` | Generate a new library within a monorepo (converting to monorepo if it's a standard structure). |
| `class` | `cl` | Generate a new class. |
| `controller` | `co` | Generate a controller declaration. |
| `decorator` | `d` | Generate a custom decorator. |
| `filter` | `f` | Generate a filter declaration. |
| `gateway` | `ga` | Generate a gateway declaration. |
| `guard` | `gu` | Generate a guard declaration. |
| `interface` | | Generate an interface. |
| `interceptor` | `in` | Generate an interceptor declaration. |
| `middleware` | `mi` | Generate a middleware declaration. |
| `module` | `mo` | Generate a module declaration. |
| `pipe` | `pi` | Generate a pipe declaration. |
| `provider` | `pr` | Generate a provider declaration. |
| `resolver` | `r` | Generate a resolver declaration.
| `resource` | `res` | Generate a new CRUD resource. See the [CRUD (resource) generator](/recipes/crud-generator) for more details. |
| `service` | `s` | Generate a service declaration. |
##### Options
| Option | Description |
| ------------------------------- | --------------------------------------------------------------------------------------------------------------- |
| `--dry-run` | Reports changes that would be made, but does not change the filesystem.<br/> Alias: `-d` |
| `--project [project]` | Project that element should be added to.<br/> Alias: `-p` |
| `--flat` | Do not generate a folder for the element. |
| `--collection [collectionName]` | Specify schematics collection. Use package name of installed npm package containing schematic.<br/> Alias: `-c` |
| `--spec` | Enforce spec files generation (default) |
| `--no-spec` | Disable spec files generation |
#### nest build
Compiles an application or workspace into an output folder.
```bash
$ nest build <name> [options]
```
##### Arguments
| Argument | Description |
| -------- | --------------------------------- |
| `<name>` | The name of the project to build. |
##### Options
| Option | Description |
| ----------------- | ------------------------------------------------------ |
| `--path [path]` | Path to `tsconfig` file. <br/>Alias `-p` |
| `--config [path]` | Path to `nest-cli` configuration file. <br/>Alias `-c` |
| `--watch` | Run in watch mode (live-reload) <br/>Alias `-w` |
| `--webpack` | Use webpack for compilation. |
| `--webpackPath` | Path to webpack configuration. |
| `--tsc` | Force use `tsc` for compilation. |
#### nest start
Compiles and runs an application (or default project in a workspace).
```bash
$ nest start <name> [options]
```
##### Arguments
| Argument | Description |
| -------- | ------------------------------- |
| `<name>` | The name of the project to run. |
##### Options
| Option | Description |
| ----------------------- | -------------------------------------------------------------------------------------------------------------------- |
| `--path [path]` | Path to `tsconfig` file. <br/>Alias `-p` |
| `--config [path]` | Path to `nest-cli` configuration file. <br/>Alias `-c` |
| `--watch` | Run in watch mode (live-reload) <br/>Alias `-w` |
| `--preserveWatchOutput` | Keep outdated console output in watch mode instead of clearing the screen. (`tsc` watch mode only) |
| `--watchAssets` | Run in watch mode (live-reload), watching non-TS files (assets). See [Assets](cli/monorepo#assets) for more details. |
| `--debug [hostport]` | Run in debug mode (with --inspect flag) <br/>Alias `-d` |
| `--webpack` | Use webpack for compilation. |
| `--webpackPath` | Path to webpack configuration. |
| `--tsc` | Force use `tsc` for compilation. |
| `--exec [binary]` | Binary to run (default: `node`). <br/>Alias `-e` |
#### nest add
Imports a library that has been packaged as a **nest library**, running its install schematic.
```bash
$ nest add <name> [options]
```
##### Arguments
| Argument | Description |
| -------- | ---------------------------------- |
| `<name>` | The name of the library to import. |
#### nest update
Updates `@nestjs` dependencies in the `package.json` `"dependencies"` list to their `@latest` version.
##### Options
| Option | Description |
| --------- | ------------------------------------------------------------------------ |
| `--force` | Do **upgrade** instead of update <br/>Alias `-f` |
| `--tag` | Update to tagged version (use `@latest`, `@<tag>`, etc) <br/>Alias `-t` | |
#### nest info
Displays information about installed nest packages and other helpful system info. For example:
```bash
$ nest info
```
```bash
_ _ _ ___ _____ _____ _ _____
| \ | | | | |_ |/ ___|/ __ \| | |_ _|
| \| | ___ ___ | |_ | |\ `--. | / \/| | | |
| . ` | / _ \/ __|| __| | | `--. \| | | | | |
| |\ || __/\__ \| |_ /\__/ //\__/ /| \__/\| |_____| |_
\_| \_/ \___||___/ \__|\____/ \____/ \____/\_____/\___/
[System Information]
OS Version : macOS High Sierra
NodeJS Version : v8.9.0
YARN Version : 1.5.1
[Nest Information]
microservices version : 6.0.0
websockets version : 6.0.0
testing version : 6.0.0
common version : 6.0.0
core version : 6.0.0
```
================================================
FILE: content/cli/workspaces.md
================================================
### Workspaces
Nest has two modes for organizing code:
- **standard mode**: useful for building individual project-focused applications that have their own dependencies and settings, and don't need to optimize for sharing modules, or optimizing complex builds. This is the default mode.
- **monorepo mode**: this mode treats code artifacts as part of a lightweight **monorepo**, and may be more appropriate for teams of developers and/or multi-project environments. It automates parts of the build process to make it easy to create and compose modular components, promotes code re-use, makes integration testing easier, makes it easy to share project-wide artifacts like `eslint` rules and other configuration policies, and is easier to use than alternatives like github submodules. Monorepo mode employs the concept of a **workspace**, represented in the `nest-cli.json` file, to coordinate the relationship between the components of the monorepo.
It's important to note that virtually all of Nest's features are independent of your code organization mode. The **only** affect of this choice is how your projects are composed and how build artifacts are generated. All other functionality, from the CLI to core modules to add-on modules work the same in either mode.
Also, you can easily switch from **standard mode** to **monorepo mode** at any time, so you can delay this decision until the benefits of one or the other approach become more clear.
#### Standard mode
When you run `nest new`, a new **project** is created for you using a built-in schematic. Nest does the following:
1. Create a new folder, corresponding to the `name` argument you provide to `nest new`
2. Populate that folder with default files corresponding to a minimal base-level Nest application. You can examine these files at the [typescript-starter](https://github.com/nestjs/typescript-starter) repository.
3. Provide additional files such as `nest-cli.json`, `package.json` and `tsconfig.json` that configure and enable various tools for compiling, testing and serving your application.
From there, you can modify the starter files, add new components, add dependencies (e.g., `npm install`), and otherwise develop your application as covered in the rest of this documentation.
#### Monorepo mode
To enable monorepo mode, you start with a _standard mode_ structure, and add **projects**. A project can be a full **application** (which you add to the workspace with the command `nest generate app`) or a **library** (which you add to the workspace with the command `nest generate library`). We'll discuss the details of these specific types of project components below. The key point to note now is that it is the **act of adding a project** to an existing standard mode structure that **converts it** to monorepo mode. Let's look at an example.
If we run:
```bash
nest new my-project
```
We've constructed a _standard mode_ structure, with a folder structure that looks like this:
<div class="file-tree">
<div class="item">node_modules</div>
<div class="item">src</div>
<div class="children">
<div class="item">app.controller.ts</div>
<div class="item">app.module.ts</div>
<div class="item">app.service.ts</div>
<div class="item">main.ts</div>
</div>
<div class="item">nest-cli.json</div>
<div class="item">package.json</div>
<div class="item">tsconfig.json</div>
<div class="item">.eslintrc.js</div>
</div>
We can convert this to a monorepo mode structure as follows:
```bash
cd my-project
nest generate app my-app
```
At this point, `nest` converts the existing structure to a **monorepo mode** structure. This results in a few important changes. The folder structure now looks like this:
<div class="file-tree">
<div class="item">apps</div>
<div class="children">
<div class="item">my-app</div>
<div class="children">
<div class="item">src</div>
<div class="children">
<div class="item">app.controller.ts</div>
<div class="item">app.module.ts</div>
<div class="item">app.service.ts</div>
<div class="item">main.ts</div>
</div>
<div class="item">tsconfig.app.json</div>
</div>
<div class="item">my-project</div>
<div class="children">
<div class="item">src</div>
<div class="children">
<div class="item">app.controller.ts</div>
<div class="item">app.module.ts</div>
<div class="item">app.service.ts</div>
<div class="item">main.ts</div>
</div>
<div class="item">tsconfig.app.json</div>
</div>
</div>
<div class="item">nest-cli.json</div>
<div class="item">package.json</div>
<div class="item">tsconfig.json</div>
<div class="item">.eslintrc.js</div>
</div>
The `generate app` schematic has reorganized the code - moving each **application** project under the `apps` folder, and adding a project-specific `tsconfig.app.json` file in each project's root folder. Our original `my-project` app has become the **default project** for the monorepo, and is now a peer with the just-added `my-app`, located under the `apps` folder. We'll cover default projects below.
> error **Warning** The conversion of a standard mode structure to monorepo only works for projects that have followed the canonical Nest project structure. Specifically, during conversion, the schematic attempts to relocate the `src` and `test` folders in a project folder beneath the `apps` folder in the root. If a project does not use this structure, the conversion will fail or produce unreliable results.
#### Workspace projects
A monorepo uses the concept of a workspace to manage its member entities. Workspaces are composed of **projects**. A project may be either:
- an **application**: a full Nest application including a `main.ts` file to bootstrap the application. Aside from compile and build considerations, an application-type project within a workspace is functionally identical to an application within a _standard mode_ structure.
- a **library**: a library is a way of packaging a general purpose set of features (modules, providers, controllers, etc.) that can be used within other projects. A library cannot run on its own, and has no `main.ts` file. Read more about libraries [here](/cli/libraries).
All workspaces have a **default project** (which should be an application-type project). This is defined by the top-level `"root"` property in the `nest-cli.json` file, which points at the root of the default project (see [CLI properties](/cli/monorepo#cli-properties) below for more details). Usually, this is the **standard mode** application you started with, and later converted to a monorepo using `nest generate app`. When you follow these steps, this property is populated automatically.
Default projects are used by `nest` commands like `nest build` and `nest start` when a project name is not supplied.
For example, in the above monorepo structure, running
```bash
$ nest start
```
will start up the `my-project` app. To start `my-app`, we'd use:
```bash
$ nest start my-app
```
#### Applications
Application-type projects, or what we might informally refer to as just "applications", are complete Nest applications that you can run and deploy. You generate an application-type project with `nest generate app`.
This command automatically generates a project skeleton, including the standard `src` and `test` folders from the [typescript starter](https://github.com/nestjs/typescript-starter). Unlike standard mode, an application project in a monorepo does not have any of the package dependency (`package.json`) or other project configuration artifacts like `.prettierrc` and `.eslintrc.js`. Instead, the monorepo-wide dependencies and config files are used.
However, the schematic does generate a project-specific `tsconfig.app.json` file in the root folder of the project. This config file automatically sets appropriate build options, including setting the compilation output folder properly. The file extends the top-level (monorepo) `tsconfig.json` file, so you can manage global settings monorepo-wide, but override them if needed at the project level.
#### Libraries
As mentioned, library-type projects, or simply "libraries", are packages of Nest components that need to be composed into applications in order to run. You generate a library-type project with `nest generate library`. Deciding what belongs in a library is an architectural design decision. We discuss libraries in depth in the [libraries](/cli/libraries) chapter.
#### CLI properties
Nest keeps the metadata needed to organize, build and deploy both standard and monorepo structured projects in the `nest-cli.json` file. Nest automatically adds to and updates this file as you add projects, so you usually do not have to think about it or edit its contents. However, there are some settings you may want to change manually, so it's helpful to have an overview understanding of the file.
After running the steps above to create a monorepo, our `nest-cli.json` file looks like this:
```javascript
{
"collection": "@nestjs/schematics",
"sourceRoot": "apps/my-project/src",
"monorepo": true,
"root": "apps/my-project",
"compilerOptions": {
"webpack": true,
"tsConfigPath": "apps/my-project/tsconfig.app.json"
},
"projects": {
"my-project": {
"type": "application",
"root": "apps/my-project",
"entryFile": "main",
"sourceRoot": "apps/my-project/src",
"compilerOptions": {
"tsConfigPath": "apps/my-project/tsconfig.app.json"
}
},
"my-app": {
"type": "application",
"root": "apps/my-app",
"entryFile": "main",
"sourceRoot": "apps/my-app/src",
"compilerOptions": {
"tsConfigPath": "apps/my-app/tsconfig.app.json"
}
}
}
}
```
The file is divided into sections:
- a global section with top-level properties controlling standard and monorepo-wide settings
- a top level property (`"projects"`) with metadata about each project. This section is present only for monorepo-mode structures.
The top-level properties are as follows:
- `"collection"`: points at the collection of schematics used to generate components; you generally should not change this value
- `"sourceRoot"`: points at the root of the source code for the single project in standard mode structures, or the _default project_ in monorepo mode structures
- `"compilerOptions"`: a map with keys specifying compiler options and values specifying the option setting; see details below
- `"generateOptions"`: a map with keys specifying global generate options and values specifying the option setting; see details below
- `"monorepo"`: (monorepo only) for a monorepo mode structure, this value is always `true`
- `"root"`: (monorepo only) points at the project root of the _default project_
#### Global compiler options
These properties specify the compiler to use as well as various options that affect **any** compilation step, whether as part of `nest build` or `nest start`, and regardless of the compiler, whether `tsc` or webpack.
| Property Name | Property Value Type | Description |
| ------------------- | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `webpack` | boolean | If `true`, use [webpack compiler](https://webpack.js.org/). If `false` or not present, use `tsc`. In monorepo mode, the default is `true` (use webpack), in standard mode, the default is `false` (use `tsc`). See below for details. |
| `tsConfigPath` | string | (**monorepo only**) Points at the file containing the `tsconfig.json` settings that will be used when `nest build` or `nest start` is called without a `project` option (e.g., when the default project is built or started). |
| `webpackConfigPath` | string | Points at a webpack options file. If not specified, Nest looks for the file `webpack.config.js`. See below for more details. |
| `deleteOutDir` | boolean | If `true`, whenever the compiler is invoked, it will first remove the compilation output directory (as configured in `tsconfig.json`, where the default is `./dist`). |
| `assets` | array | Enables automatically distributing non-TypeScript assets whenever a compilation step begins (asset distribution does **not** happen on incremental compiles in `--watch` mode). See below for details. |
| `watchAssets` | boolean | If `true`, run in watch-mode, watching **all** non-TypeScript assets. (For more fine-grained control of the assets to watch, see [Assets](cli/monorepo#assets) section below). |
#### Global generate options
These properties specify the default generate options to be used by the `nest generate` command.
| Property Name | Property Value Type | Description |
| ------------- | ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `spec` | boolean _or_ object | If the value is boolean, a value of `true` enables `spec` generation by default and a value of `false` disables it. A flag passed on the CLI command line overrides this setting, as does a project-specific `generateOptions` setting (more below). If the value is an object, each key represents a schematic name, and the boolean value determines whether the default spec generation is enabled / disabled for that specific schematic. |
The following example uses a boolean value to specify that spec file generation should be disabled by default for all projects:
```javascript
{
"generateOptions": {
"spec": false
},
...
}
```
In the following example, `spec` file generation is disabled only for `service` schematics (e.g., `nest generate service...`):
```javascript
{
"generateOptions": {
"spec": {
"service": false
}
},
...
}
```
> warning **Warning** When specifying the `spec` as an object, the key for the generation schematic does not currently support automatic alias handling. This means that specifying a key as for example `service: false` and trying to generate a service via the alias `s`, the spec would still be generated. To make sure both the normal schematic name and the alias work as intended, specify both the normal command name as well as the alias, as seen below.
>
> ```javascript
> {
> "generateOptions": {
> "spec": {
> "service": false,
> "s": false
> }
> },
> ...
> }
> ```
#### Project-specific generate options
In addition to providing global generate options, you may also specify project-specific generate options. The project specific generate options follow the exact same format as the global generate options, but are specified directly on each project.
Project-specific generate options override global generate options.
```javascript
{
"projects": {
"cats-project": {
"generateOptions": {
"spec": {
"service": false
}
},
...
}
},
...
}
```
> warning **Warning** The order of precedence for generate options is as follows. Options specified on the CLI command line take precedence over project-specific options. Project-specific options override global options.
#### Specified compiler
The reason for the different default compilers is that for larger projects (e.g., more typical in a monorepo) webpack can have significant advantages in build times and in producing a single file bundling all project components together. If you wish to generate individual files, set `"webpack"` to `false`, which will cause the build process to use `tsc`.
#### Webpack options
The webpack options file can contain standard [webpack configuration options](https://webpack.js.org/configuration/). For example, to tell webpack to bundle `node_modules` (which are excluded by default), add the following to `webpack.config.js`:
```javascript
module.exports = {
externals: [],
};
```
Since the webpack config file is a JavaScript file, you can even expose a function that takes default options and returns a modified object:
```javascript
module.exports = function(options) {
return {
...options,
externals: [],
};
};
```
#### Assets
TypeScript compilation automatically distributes compiler output (`.js` and `.d.ts` files) to the specified output directory. It can also be convenient to distribute non-TypeScript files, such as `.graphql` files, `images`, `.html` files and other assets. This allows you to treat `nest build` (and any initial compilation step) as a lightweight **development build** step, where you may be editing non-TypeScript files and iteratively compiling and testing.
The assets should be located in the `src` folder otherwise they will not be copied.
The value of the `assets` key should be an array of elements specifying the files to be distributed. The elements can be simple strings with `glob`-like file specs, for example:
```typescript
"assets": ["**/*.graphql"],
"watchAssets": true,
```
For finer control, the elements can be objects with the following keys:
- `"include"`: `glob`-like file specifications for the assets to be distributed
- `"exclude"`: `glob`-like file specifications for assets to be **excluded** from the `include` list
- `"outDir"`: a string specifying the path (relative to the root folder) where the assets should be distributed. Defaults to the same output directory configured for compiler output.
- `"watchAssets"`: boolean; if `true`, run in watch mode watching specified assets
For example:
```typescript
"assets": [
{ "include": "**/*.graphql", "exclude": "**/omitted.graphql", "watchAssets": true },
]
```
> warning **Warning** Setting `watchAssets` in a top-level `compilerOptions` property overrides any `watchAssets` settings within the `assets` property.
#### Project properties
This element exists only for monorepo-mode structures. You generally should not edit these properties, as they are used by Nest to locate projects and their configuration options within the monorepo.
================================================
FILE: content/components.md
================================================
### Providers
프로바이더는 Nest의 기본 개념입니다. 기본 Nest 클래스의 대부분은 서비스, 리포지토리, 팩토리, 헬퍼 등 프로바이더로 취급될 수 있습니다. 프로바이더의 주요 아이디어는 종속성으로 **주입**할 수 있다는 것입니다. 즉, 객체는 서로 다양한 관계를 생성할 수 있으며 객체의 인스턴스를 "연결"하는 기능은 대부분 Nest 런타임 시스템에 위임될 수 있습니다.
<figure><img src="/assets/Components_1.png" /></figure>
이전 장에서 우리는 간단한 `CatsController`를 만들었습니다. 컨트롤러는 HTTP 요청을 처리하고 더 복잡한 작업을 **프로바이더**에 위임해야 합니다. 공급자는 [모듈](/modules)에서 `프로바이더'로 선언된 일반 자바스크립트 클래스입니다.
> 정보 **힌트** Nest를 사용하면 종속성을 보다 OO-방식으로 설계하고 구성할 수 있으므로 [SOLID](https://en.wikipedia.org/wiki/SOLID) 원칙을 따르는 것이 좋습니다.
#### Services
간단한 'CatsService'를 만드는 것으로 시작하겠습니다. 이 서비스는 데이터 저장 및 검색을 담당하며 `CatsController`에서 사용하도록 설계되었으므로 프로바이더로 정의하기에 좋은 후보입니다.
```typescript
@@filename(cats.service)
import { Injectable } from '@nestjs/common';
import { Cat } from './interfaces/cat.interface';
@Injectable()
export class CatsService {
private readonly cats: Cat[] = [];
create(cat: Cat) {
this.cats.push(cat);
}
findAll(): Cat[] {
return this.cats;
}
}
@@switch
import { Injectable } from '@nestjs/common';
@Injectable()
export class CatsService {
constructor() {
this.cats = [];
}
create(cat) {
this.cats.push(cat);
}
findAll() {
return this.cats;
}
}
```
> 정보 **힌트** CLI를 사용하여 서비스를 생성하려면 `$ nest g service cats` 명령을 실행하면 됩니다.
우리의 `CatsService`는 하나의 속성과 두 개의 메소드가 있는 기본 클래스입니다. 유일한 새로운 기능은 `@Injectable()` 데코레이터를 사용한다는 것입니다. `@Injectable()` 데코레이터는 `CatsService`가 Nest IoC 컨테이너에서 관리할 수 있는 클래스임을 선언하는 메타데이터를 첨부합니다. 그런데 이 예제는 'Cat' 인터페이스도 사용됩니다:
```typescript
@@filename(interfaces/cat.interface)
export interface Cat {
name: string;
age: number;
breed: string;
}
```
이제 고양이를 검색하는 서비스 클래스가 있으므로 `CatsController` 내부에서 사용하겠습니다.
```typescript
@@filename(cats.controller)
import { Controller, Get, Post, Body } from '@nestjs/common';
import { CreateCatDto } from './dto/create-cat.dto';
import { CatsService } from './cats.service';
import { Cat } from './interfaces/cat.interface';
@Controller('cats')
export class CatsController {
constructor(private catsService: CatsService) {}
@Post()
async create(@Body() createCatDto: CreateCatDto) {
this.catsService.create(createCatDto);
}
@Get()
async findAll(): Promise<Cat[]> {
return this.catsService.findAll();
}
}
@@switch
import { Controller, Get, Post, Body, Bind, Dependencies } from '@nestjs/common';
import { CatsService } from './cats.service';
@Controller('cats')
@Dependencies(CatsService)
export class CatsController {
constructor(catsService) {
this.catsService = catsService;
}
@Post()
@Bind(Body())
async create(createCatDto) {
this.catsService.create(createCatDto);
}
@Get()
async findAll() {
return this.catsService.findAll();
}
}
```
`CatsService`는 클래스 생성자를 통해 **주입**됩니다. `private` 클래스 필드를 사용하는 것에 주목해야합니다. 이 약식을 사용하면 같은 위치에서 즉시 `catsService` 멤버를 선언하고 초기화할 수 있습니다.
#### Dependency injection
Nest is built around the strong design pattern commonly known as **Dependency injection**. We recommend reading a great article about this concept in the official [Angular](https://angular.io/guide/dependency-injection) documentation.
In Nest, thanks to TypeScript capabilities, it's extremely easy to manage dependencies because they are resolved just by type. In the example below, Nest will resolve the `catsService` by creating and returning an instance of `CatsService` (or, in the normal case of a singleton, returning the existing instance if it has already been requested elsewhere). This dependency is resolved and passed to your controller's constructor (or assigned to the indicated property):
```typescript
constructor(private catsService: CatsService) {}
```
#### Scopes
Providers normally have a lifetime ("scope") synchronized with the application lifecycle. When the application is bootstrapped, every dependency must be resolved, and therefore every provider has to be instantiated. Similarly, when the application shuts down, each provider will be destroyed. However, there are ways to make your provider lifetime **request-scoped** as well. You can read more about these techniques [here](/fundamentals/injection-scopes).
<app-banner-courses></app-banner-courses>
#### Custom providers
Nest has a built-in inversion of control ("IoC") container that resolves relationships between providers. This feature underlies the dependency injection feature described above, but is in fact far more powerful than what we've described so far. There are several ways to define a provider: you can use plain values, classes, and either asynchronous or synchronous factories. More examples are provided [here](/fundamentals/dependency-injection).
#### Optional providers
Occasionally, you might have dependencies which do not necessarily have to be resolved. For instance, your class may depend on a **configuration object**, but if none is passed, the default values should be used. In such a case, the dependency becomes optional, because lack of the configuration provider wouldn't lead to errors.
To indicate a provider is optional, use the `@Optional()` decorator in the constructor's signature.
```typescript
import { Injectable, Optional, Inject } from '@nestjs/common';
@Injectable()
export class HttpService<T> {
constructor(@Optional() @Inject('HTTP_OPTIONS') private httpClient: T) {}
}
```
Note that in the example above we are using a custom provider, which is the reason we include the `HTTP_OPTIONS` custom **token**. Previous examples showed constructor-based injection indicating a dependency through a class in the constructor. Read more about custom providers and their associated tokens [here](/fundamentals/custom-providers).
#### Property-based injection
The technique we've used so far is called constructor-based injection, as providers are injected via the constructor method. In some very specific cases, **property-based injection** might be useful. For instance, if your top-level class depends on either one or multiple providers, passing them all the way up by calling `super()` in sub-classes from the constructor can be very tedious. In order to avoid this, you can use the `@Inject()` decorator at the property level.
```typescript
import { Injectable, Inject } from '@nestjs/common';
@Injectable()
export class HttpService<T> {
@Inject('HTTP_OPTIONS')
private readonly httpClient: T;
}
```
> warning **Warning** If your class doesn't extend another provider, you should always prefer using **constructor-based** injection.
#### Provider registration
Now that we have defined a provider (`CatsService`), and we have a consumer of that service (`CatsController`), we need to register the service with Nest so that it can perform the injection. We do this by editing our module file (`app.module.ts`) and adding the service to the `providers` array of the `@Module()` decorator.
```typescript
@@filename(app.module)
import { Module } from '@nestjs/common';
import { CatsController } from './cats/cats.controller';
import { CatsService } from './cats/cats.service';
@Module({
controllers: [CatsController],
providers: [CatsService],
})
export class AppModule {}
```
Nest will now be able to resolve the dependencies of the `CatsController` class.
This is how our directory structure should look now:
<div class="file-tree">
<div class="item">src</div>
<div class="children">
<div class="item">cats</div>
<div class="children">
<div class="item">dto</div>
<div class="children">
<div class="item">create-cat.dto.ts</div>
</div>
<div class="item">interfaces</div>
<div class="children">
<div class="item">cat.interface.ts</div>
</div>
<div class="item">cats.controller.ts</div>
<div class="item">cats.service.ts</div>
</div>
<div class="item">app.module.ts</div>
<div class="item">main.ts</div>
</div>
</div>
#### Manual instantiation
Thus far, we've discussed how Nest automatically handles most of the details of resolving dependencies. In certain circumstances, you may need to step outside of the built-in Dependency Injection system and manually retrieve or instantiate providers. We briefly discuss two such topics below.
To get existing instances, or instantiate providers dynamically, you can use [Module reference](https://docs.nestjs.com/fundamentals/module-ref).
To get providers within the `bootstrap()` function (for example for standalone applications without controllers, or to utilize a configuration service during bootstrapping) see [Standalone applications](https://docs.nestjs.com/standalone-applications).
================================================
FILE: content/controllers.md
================================================
### Controllers
컨트롤러는 들어오는 **요청**을 적절히 핸들링하고 **응답**을 클라이언트로 리턴해주는 책임을 지니고 있습니다.
<figure><img src="/assets/Controllers_1.png" /></figure>
컨트롤러의 목적은 application을 위한 요청을 받아오는 데 있습니다. **routing** 메커니즘은 어떤 컨트롤러가 어떤 요청을 받아오는지를 제어합니다.
많은 경우, 각각의 컨트롤러는 하나 이상의 라우트를 가지고, 각각의 라우트는 고유한 목적을 가지고 동작합니다.
기본적 형태의 컨트롤러를 만들기 위해, 클래스와 데코레이터를 사용합니다. 데코레이터는 클래스와 클래스가 필요한 메타데이터를 연결시키고, 네스트가 라우팅 맵을 만들 수 있도록 합니다(요청과 적절한 컨트롤러를 연결시켜줍니다).
> info **힌트** [밸리데이션](https://docs.nestjs.kr/techniques/validation)이 포함된 CRUD 컨트롤러를 간편하게 만들기 위해 CLI의 [CRUD generator](https://docs.nestjs.kr/recipes/crud-generator#crud-generator): `nest g resource [이름]`을 사용할 수 있습니다.
#### 라우팅
다음의 예제에서 기본적인 컨트롤러를 정의하기 위해 필요한 `@Controller()` 데코레이터를 사용해봅니다. 우리는 앞으로 `cats`라는 이름의 접두사를 가진 라우트를 만들 것입니다. `@Controller()` 데코레이터에서 접두사를 이용하는 것은 연관된 라우트들을 그룹화하기 쉽게 만들어주고 코드의 중복을 최소화할 수 있습니다. 예를 들어, `/customers`라는 이름의 접두사 하에서 고객 엔티티와 상호작용하는 라우트 그룹을 다룰 것이라 생각할 수 있습니다. 이런 경우, 한 파일 안에서 각각의 라우트마다 반복하여 접두사를 기입할 필요가 없도록 `@Controller()` 데코레이터에 `customers`를 명시해놓을 수 있습니다.
```typescript
@@filename(cats.controller)
import { Controller, Get } from '@nestjs/common';
@Controller('cats')
export class CatsController {
@Get()
findAll(): string {
return 'This action returns all cats';
}
}
@@switch
import { Controller, Get } from '@nestjs/common';
@Controller('cats')
export class CatsController {
@Get()
findAll() {
return 'This action returns all cats';
}
}
```
> info **힌트** CLI를 이용해 컨트롤러를 만들기 위해서는 `$ nest g controller cats` 명령어를 입력하세요.
The `@Get()` HTTP request method decorator before the `findAll()` method tells Nest to create a handler for a specific endpoint for HTTP requests. The endpoint corresponds to the HTTP request method (GET in this case) and the route path. What is the route path? The route path for a handler is determined by concatenating the (optional) prefix declared for the controller, and any path specified in the method's decorator. Since we've declared a prefix for every route ( `cats`), and haven't added any path information in the decorator, Nest will map `GET /cats` requests to this handler. As mentioned, the path includes both the optional controller path prefix **and** any path string declared in the request method decorator. For example, a path prefix of `customers` combined with the decorator `@Get('profile')` would produce a route mapping for requests like `GET /customers/profile`.
In our example above, when a GET request is made to this endpoint, Nest routes the request to our user-defined `findAll()` method. Note that the method name we choose here is completely arbitrary. We obviously must declare a method to bind the route to, but Nest doesn't attach any significance to the method name chosen.
This method will return a 200 status code and the associated response, which in this case is just a string. Why does that happen? To explain, we'll first introduce the concept that Nest employs two **different** options for manipulating responses:
<table>
<tr>
<td>Standard (recommended)</td>
<td>
Using this built-in method, when a request handler returns a JavaScript object or array, it will <strong>automatically</strong>
be serialized to JSON. When it returns a JavaScript primitive type (e.g., <code>string</code>, <code>number</code>, <code>boolean</code>), however, Nest will send just the value without attempting to serialize it. This makes response handling simple: just return the value, and Nest takes care of the rest.
<br />
<br /> Furthermore, the response's <strong>status code</strong> is always 200 by default, except for POST
requests which use 201. We can easily change this behavior by adding the <code>@HttpCode(...)</code>
decorator at a handler-level (see <a href='controllers#status-code'>Status codes</a>).
</td>
</tr>
<tr>
<td>Library-specific</td>
<td>
We can use the library-specific (e.g., Express) <a href="https://expressjs.com/en/api.html#res" rel="nofollow" target="_blank">response object</a>, which can be injected using the <code>@Res()</code> decorator in the method handler signature (e.g., <code>findAll(@Res() response)</code>). With this approach, you have the ability to use the native response handling methods exposed by that object. For example, with Express, you can construct responses using code like <code>response.status(200).send()</code>.
</td>
</tr>
</table>
> warning **Warning** Nest detects when the handler is using either `@Res()` or `@Next()`, indicating you have chosen the library-specific option. If both approaches are used at the same time, the Standard approach is **automatically disabled** for this single route and will no longer work as expected. To use both approaches at the same time (for example, by injecting the response object to only set cookies/headers but still leave the rest to the framework), you must set the `passthrough` option to `true` in the `@Res({{ '{' }} passthrough: true {{ '}' }})` decorator.
<app-banner-enterprise></app-banner-enterprise>
#### Request object
Handlers often need access to the client **request** details. Nest provides access to the [request object](https://expressjs.com/en/api.html#req) of the underlying platform (Express by default). We can access the request object by instructing Nest to inject it by adding the `@Req()` decorator to the handler's signature.
```typescript
@@filename(cats.controller)
import { Controller, Get, Req } from '@nestjs/common';
import { Request } from 'express';
@Controller('cats')
export class CatsController {
@Get()
findAll(@Req() request: Request): string {
return 'This action returns all cats';
}
}
@@switch
import { Controller, Bind, Get, Req } from '@nestjs/common';
@Controller('cats')
export class CatsController {
@Get()
@Bind(Req())
findAll(request) {
return 'This action returns all cats';
}
}
```
> info **Hint** In order to take advantage of `express` typings (as in the `request: Request` parameter example above), install `@types/express` package.
The request object represents the HTTP request and has properties for the request query string, parameters, HTTP headers, and body (read more [here](https://expressjs.com/en/api.html#req)). In most cases, it's not necessary to grab these properties manually. We can use dedicated decorators instead, such as `@Body()` or `@Query()`, which are available out of the box. Below is a list of the provided decorators and the plain platform-specific objects they represent.
<table>
<tbody>
<tr>
<td><code>@Request(), @Req()</code></td>
<td><code>req</code></td></tr>
<tr>
<td><code>@Response(), @Res()</code><span class="table-code-asterisk">*</span></td>
<td><code>res</code></td>
</tr>
<tr>
<td><code>@Next()</code></td>
<td><code>next</code></td>
</tr>
<tr>
<td><code>@Session()</code></td>
<td><code>req.session</code></td>
</tr>
<tr>
<td><code>@Param(key?: string)</code></td>
<td><code>req.params</code> / <code>req.params[key]</code></td>
</tr>
<tr>
<td><code>@Body(key?: string)</code></td>
<td><code>req.body</code> / <code>req.body[key]</code></td>
</tr>
<tr>
<td><code>@Query(key?: string)</code></td>
<td><code>req.query</code> / <code>req.query[key]</code></td>
</tr>
<tr>
<td><code>@Headers(name?: string)</code></td>
<td><code>req.headers</code> / <code>req.headers[name]</code></td>
</tr>
<tr>
<td><code>@Ip()</code></td>
<td><code>req.ip</code></td>
</tr>
<tr>
<td><code>@HostParam()</code></td>
<td><code>req.hosts</code></td>
</tr>
</tbody>
</table>
<sup>\* </sup>For compatibility with typings across underlying HTTP platforms (e.g., Express and Fastify), Nest provides `@Res()` and `@Response()` decorators. `@Res()` is simply an alias for `@Response()`. Both directly expose the underlying native platform `response` object interface. When using them, you should also import the typings for the underlying library (e.g., `@types/express`) to take full advantage. Note that when you inject either `@Res()` or `@Response()` in a method handler, you put Nest into **Library-specific mode** for that handler, and you become responsible for managing the response. When doing so, you must issue some kind of response by making a call on the `response` object (e.g., `res.json(...)` or `res.send(...)`), or the HTTP server will hang.
> info **Hint** To learn how to create your own custom decorators, visit [this](/custom-decorators) chapter.
#### Resources
Earlier, we defined an endpoint to fetch the cats resource (**GET** route). We'll typically also want to provide an endpoint that creates new records. For this, let's create the **POST** handler:
```typescript
@@filename(cats.controller)
import { Controller, Get, Post } from '@nestjs/common';
@Controller('cats')
export class CatsController {
@Post()
create(): string {
return 'This action adds a new cat';
}
@Get()
findAll(): string {
return 'This action returns all cats';
}
}
@@switch
import { Controller, Get, Post } from '@nestjs/common';
@Controller('cats')
export class CatsController {
@Post()
create() {
return 'This action adds a new cat';
}
@Get()
findAll() {
return 'This action returns all cats';
}
}
```
It's that simple. Nest provides decorators for all of the standard HTTP methods: `@Get()`, `@Post()`, `@Put()`, `@Delete()`, `@Patch()`, `@Options()`, and `@Head()`. In addition, `@All()` defines an endpoint that handles all of them.
#### Route wildcards
Pattern based routes are supported as well. For instance, the asterisk is used as a wildcard, and will match any combination of characters.
```typescript
@Get('ab*cd')
findAll() {
return 'This route uses a wildcard';
}
```
The `'ab*cd'` route path will match `abcd`, `ab_cd`, `abecd`, and so on. The characters `?`, `+`, `*`, and `()` may be used in a route path, and are subsets of their regular expression counterparts. The hyphen ( `-`) and the dot (`.`) are interpreted literally by string-based paths.
#### Status code
As mentioned, the response **status code** is always **200** by default, except for POST requests which are **201**. We can easily change this behavior by adding the `@HttpCode(...)` decorator at a handler level.
```typescript
@Post()
@HttpCode(204)
create() {
return 'This action adds a new cat';
}
```
> info **Hint** Import `HttpCode` from the `@nestjs/common` package.
Often, your status code isn't static but depends on various factors. In that case, you can use a library-specific **response** (inject using `@Res()`) object (or, in case of an error, throw an exception).
#### Headers
To specify a custom response header, you can either use a `@Header()` decorator or a library-specific response object (and call `res.header()` directly).
```typescript
@Post()
@Header('Cache-Control', 'none')
create() {
return 'This action adds a new cat';
}
```
> info **Hint** Import `Header` from the `@nestjs/common` package.
#### Redirection
To redirect a response to a specific URL, you can either use a `@Redirect()` decorator or a library-specific response object (and call `res.redirect()` directly).
`@Redirect()` takes two arguments, `url` and `statusCode`, both are optional. The default value of `statusCode` is `302` (`Found`) if omitted.
```typescript
@Get()
@Redirect('https://nestjs.com', 301)
```
Sometimes you may want to determine the HTTP status code or the redirect URL dynamically. Do this by returning an object from the route handler method with the shape:
```json
{
"url": string,
"statusCode": number
}
```
Returned values will override any arguments passed to the `@Redirect()` decorator. For example:
```typescript
@Get('docs')
@Redirect('https://docs.nestjs.com', 302)
getDocs(@Query('version') version) {
if (version && version === '5') {
return { url: 'https://docs.nestjs.com/v5/' };
}
}
```
#### Route parameters
Routes with static paths won't work when you need to accept **dynamic data** as part of the request (e.g., `GET /cats/1` to get cat with id `1`). In order to define routes with parameters, we can add route parameter **tokens** in the path of the route to capture the dynamic value at that position in the request URL. The route parameter token in the `@Get()` decorator example below demonstrates this usage. Route parameters declared in this way can be accessed using the `@Param()` decorator, which should be added to the method signature.
```typescript
@@filename()
@Get(':id')
findOne(@Param() params): string {
console.log(params.id);
return `This action returns a #${params.id} cat`;
}
@@switch
@Get(':id')
@Bind(Param())
findOne(params) {
console.log(params.id);
return `This action returns a #${params.id} cat`;
}
```
`@Param()` is used to decorate a method parameter (`params` in the example above), and makes the **route** parameters available as properties of that decorated method parameter inside the body of the method. As seen in the code above, we can access the `id` parameter by referencing `params.id`. You can also pass in a particular parameter token to the decorator, and then reference the route parameter directly by name in the method body.
> info **Hint** Import `Param` from the `@nestjs/common` package.
```typescript
@@filename()
@Get(':id')
findOne(@Param('id') id: string): string {
return `This action returns a #${id} cat`;
}
@@switch
@Get(':id')
@Bind(Param('id'))
findOne(id) {
return `This action returns a #${id} cat`;
}
```
#### Sub-Domain Routing
The `@Controller` decorator can take a `host` option to require that the HTTP host of the incoming requests matches some specific value.
```typescript
@Controller({ host: 'admin.example.com' })
export class AdminController {
@Get()
index(): string {
return 'Admin page';
}
}
```
> **Warning** Since **Fastify** lacks support for nested routers, when using sub-domain routing, the (default) Express adapter should be used instead.
Similar to a route `path`, the `hosts` option can use tokens to capture the dynamic value at that position in the host name. The host parameter token in the `@Controller()` decorator example below demonstrates this usage. Host parameters declared in this way can be accessed using the `@HostParam()` decorator, which should be added to the method signature.
```typescript
@Controller({ host: ':account.example.com' })
export class AccountController {
@Get()
getInfo(@HostParam('account') account: string) {
return account;
}
}
```
#### Scopes
For people coming from different programming language backgrounds, it might be unexpected to learn that in Nest, almost everything is shared across incoming requests. We have a connection pool to the database, singleton services with global state, etc. Remember that Node.js doesn't follow the request/response Multi-Threaded Stateless Model in which every request is processed by a separate thread. Hence, using singleton instances is fully **safe** for our applications.
However, there are edge-cases when request-based lifetime of the controller may be the desired behavior, for instance per-request caching in GraphQL applications, request tracking or multi-tenancy. Learn how to control scopes [here](/fundamentals/injection-scopes).
#### Asynchronicity
We love modern JavaScript and we know that data extraction is mostly **asynchronous**. That's why Nest supports and works well with `async` functions.
> info **Hint** Learn more about `async / await` feature [here](https://kamilmysliwiec.com/typescript-2-1-introduction-async-await)
Every async function has to return a `Promise`. This means that you can return a deferred value that Nest will be able to resolve by itself. Let's see an example of this:
```typescript
@@filename(cats.controller)
@Get()
async findAll(): Promise<any[]> {
return [];
}
@@switch
@Get()
async findAll() {
return [];
}
```
The above code is fully valid. Furthermore, Nest route handlers are even more powerful by being able to return RxJS [observable streams](http://reactivex.io/rxjs/class/es6/Observable.js~Observable.html). Nest will automatically subscribe to the source underneath and take the last emitted value (once the stream is completed).
```typescript
@@filename(cats.controller)
@Get()
findAll(): Observable<any[]> {
return of([]);
}
@@switch
@Get()
findAll() {
return of([]);
}
```
Both of the above approaches work and you can use whatever fits your requirements.
#### Request payloads
Our previous example of the POST route handler didn't accept any client params. Let's fix this by adding the `@Body()` decorator here.
But first (if you use TypeScript), we need to determine the **DTO** (Data Transfer Object) schema. A DTO is an object that defines how the data will be sent over the network. We could determine the DTO schema by using **TypeScript** interfaces, or by simple classes. Interestingly, we recommend using **classes** here. Why? Classes are part of the JavaScript ES6 standard, and therefore they are preserved as real entities in the compiled JavaScript. On the other hand, since TypeScript interfaces are removed during the transpilation, Nest can't refer to them at runtime. This is important because features such as **Pipes** enable additional possibilities when they have access to the metatype of the variable at runtime.
Let's create the `CreateCatDto` class:
```typescript
@@filename(create-cat.dto)
export class CreateCatDto {
name: string;
age: number;
breed: string;
}
```
It has only three basic properties. Thereafter we can use the newly created DTO inside the `CatsController`:
```typescript
@@filename(cats.controller)
@Post()
async create(@Body() createCatDto: CreateCatDto) {
return 'This action adds a new cat';
}
@@switch
@Post()
@Bind(Body())
async create(createCatDto) {
return 'This action adds a new cat';
}
```
> info **Hint** Our `ValidationPipe` can filter out properties that should not be received by the method handler. In this case, we can whitelist the acceptable properties, and any property not included in the whitelist is automatically stripped from the resulting object. In the `CreateCatDto` example, our whitelist is the `name`, `age`, and `breed` properties. Learn more [here](https://docs.nestjs.com/techniques/validation#stripping-properties).
#### Handling errors
There's a separate chapter about handling errors (i.e., working with exceptions) [here](/exception-filters).
#### Full resource sample
Below is an example that makes use of several of the available decorators to create a basic controller. This controller exposes a couple of methods to access and manipulate internal data.
```typescript
@@filename(cats.controller)
import { Controller, Get, Query, Post, Body, Put, Param, Delete } from '@nestjs/common';
import { CreateCatDto, UpdateCatDto, ListAllEntities } from './dto';
@Controller('cats')
export class CatsController {
@Post()
create(@Body() createCatDto: CreateCatDto) {
return 'This action adds a new cat';
}
@Get()
findAll(@Query() query: ListAllEntities) {
return `This action returns all cats (limit: ${query.limit} items)`;
}
@Get(':id')
findOne(@Param('id') id: string) {
return `This action returns a #${id} cat`;
}
@Put(':id')
update(@Param('id') id: string, @Body() updateCatDto: UpdateCatDto) {
return `This action updates a #${id} cat`;
}
@Delete(':id')
remove(@Param('id') id: string) {
return `This action removes a #${id} cat`;
}
}
@@switch
import { Controller, Get, Query, Post, Body, Put, Param, Delete, Bind } from '@nestjs/common';
@Controller('cats')
export class CatsController {
@Post()
@Bind(Body())
create(createCatDto) {
return 'This action adds a new cat';
}
@Get()
@Bind(Query())
findAll(query) {
console.log(query);
return `This action returns all cats (limit: ${query.limit} items)`;
}
@Get(':id')
@Bind(Param('id'))
findOne(id) {
return `This action returns a #${id} cat`;
}
@Put(':id')
@Bind(Param('id'), Body())
update(id, updateCatDto) {
return `This action updates a #${id} cat`;
}
@Delete(':id')
@Bind(Param('id'))
remove(id) {
return `This action removes a #${id} cat`;
}
}
```
> info **Hint** Nest CLI provides a generator (schematic) that automatically generates **all the boilerplate code** to help us avoid doing all of this, and make the developer experience much simpler. Read more about this feature [here](/recipes/crud-generator).
#### Getting up and running
With the above controller fully defined, Nest still doesn't know that `CatsController` exists and as a result won't create an instance of this class.
Controllers always belong to a module, which is why we include the `controllers` array within the `@Module()` decorator. Since we haven't yet defined any other modules except the root `AppModule`, we'll use that to introduce the `CatsController`:
```typescript
@@filename(app.module)
import { Module } from '@nestjs/common';
import { CatsController } from './cats/cats.controller';
@Module({
controllers: [CatsController],
})
export class AppModule {}
```
We attached the metadata to the module class using the `@Module()` decorator, and Nest can now easily reflect which controllers have to be mounted.
<app-banner-shop></app-banner-shop>
#### Library-specific approach
So far we've discussed the Nest standard way of manipulating responses. The second way of manipulating the response is to use a library-specific [response object](https://expressjs.com/en/api.html#res). In order to inject a particular response object, we need to use the `@Res()` decorator. To show the differences, let's rewrite the `CatsController` to the following:
```typescript
@@filename()
import { Controller, Get, Post, Res, HttpStatus } from '@nestjs/common';
import { Response } from 'express';
@Controller('cats')
export class CatsController {
@Post()
create(@Res() res: Response) {
res.status(HttpStatus.CREATED).send();
}
@Get()
findAll(@Res() res: Response) {
res.status(HttpStatus.OK).json([]);
}
}
@@switch
import { Controller, Get, Post, Bind, Res, Body, HttpStatus } from '@nestjs/common';
@Controller('cats')
export class CatsController {
@Post()
@Bind(Res(), Body())
create(res, createCatDto) {
res.status(HttpStatus.CREATED).send();
}
@Get()
@Bind(Res())
findAll(res) {
res.status(HttpStatus.OK).json([]);
}
}
```
Though this approach works, and does in fact allow for more flexibility in some ways by providing full control of the response object (headers manipulation, library-specific features, and so on), it should be used with care. In general, the approach is much less clear and does have some disadvantages. The main disadvantage is that your code becomes platform-dependent (as underlying libraries may have different APIs on the response object), and harder to test (you'll have to mock the response object, etc.).
Also, in the example above, you lose compatibility with Nest features that depend on Nest standard response handling, such as Interceptors and `@HttpCode()` / `@Header()` decorators. To fix this, you can set the `passthrough` option to `true`, as follows:
```typescript
@@filename()
@Get()
findAll(@Res({ passthrough: true }) res: Response) {
res.status(HttpStatus.OK);
return [];
}
@@switch
@Get()
@Bind(Res({ passthrough: true }))
findAll(res) {
res.status(HttpStatus.OK);
return [];
}
```
Now you can interact with the native response object (for example, set cookies or headers depending on certain conditions), but leave the rest to the framework.
================================================
FILE: content/custom-decorators.md
================================================
### 사용자 정의 라우트 데코레이터
Nest는 **데코레이터**라는 언어 기능을 활용하여 구축됩니다. 데코레이터는 많은 프로그래밍 언어들에서는 잘 알려진 개념이지만, 자바스크립트 세계에서는 아직까지는 상대적으로 신기능입니다. 데코레이터가 어떻게 동작하는지 더 잘 이해하고 싶다면, [이 자료](https://medium.com/google-developers/exploring-es7-decorators-76ecb65fb841)를 읽어보기를 추천합니다. 데코레이터에 대해 간단하게 정의하자면 이렇습니다.
<blockquote class="external">
ES2016 데코레이터는 특정 대상이나 이름, 프로퍼티 설명자를 인자로 받으며 함수를 반환하는 표현식입니다. 데코레이터를 적용할 때는 <code>@</code>문자를 데코레이터의 접두사로 붙이고, 적용할 대상의 바로 위에 위치시킵니다. 데코레이터는 클래스나 메서드, 프로퍼티를 적용 대상으로 삼을 수 있습니다.
</blockquote>
#### 매개변수 데코레이터
Nest는 HTTP 라우트 핸들러와 함께 유용하게 사용할 수 있는 유용한 **매개변수 데코레이터**들을 제공합니다. 다음은 제공되는 데코레이터들의 종류와 각 데코레이터들이 나타내는 Express(또는 Fastify) 객체입니다.
<table>
<tbody>
<tr>
<td><code>@Request(), @Req()</code></td>
<td><code>req</code></td>
</tr>
<tr>
<td><code>@Response(), @Res()</code></td>
<td><code>res</code></td>
</tr>
<tr>
<td><code>@Next()</code></td>
<td><code>next</code></td>
</tr>
<tr>
<td><code>@Session()</code></td>
<td><code>req.session</code></td>
</tr>
<tr>
<td><code>@Param(param?: string)</code></td>
<td><code>req.params</code> / <code>req.params[param]</code></td>
</tr>
<tr>
<td><code>@Body(param?: string)</code></td>
<td><code>req.body</code> / <code>req.body[param]</code></td>
</tr>
<tr>
<td><code>@Query(param?: string)</code></td>
<td><code>req.query</code> / <code>req.query[param]</code></td>
</tr>
<tr>
<td><code>@Headers(param?: string)</code></td>
<td><code>req.headers</code> / <code>req.headers[param]</code></td>
</tr>
<tr>
<td><code>@Ip()</code></td>
<td><code>req.ip</code></td>
</tr>
<tr>
<td><code>@HostParam()</code></td>
<td><code>req.hosts</code></td>
</tr>
</tbody>
</table>
추가적으로, **사용자 정의 데코레이터**를 작성할 수도 있습니다. 이게 왜 유용할까요?
node.js 세계에서는 **요청**객체에 프로퍼티들을 붙이는 경험을 흔하게 합니다. 그러고는 아래처럼 각 라우트 핸들러에서 코드를 통해 해당 프로퍼티들을 추출할 수 있습니다.
```typescript
const user = req.user;
```
코드의 가독성을 높이고 더욱 투명하게 만들기 위해, `@User()` 데코레이터를 작성하여 모든 컨트롤러에서 재사용할 수 있습니다.
```typescript
@@filename(user.decorator)
import { createParamDecorator, ExecutionContext } from '@nestjs/common';
export const User = createParamDecorator(
(data: unknown, ctx: ExecutionContext) => {
const request = ctx.switchToHttp().getRequest();
return request.user;
},
);
```
그러고나서 필요하다면 어디서든 간단하게 이 데코레이터를 사용할 수 있습니다.
```typescript
@@filename()
@Get()
async findOne(@User() user: UserEntity) {
console.log(user);
}
@@switch
@Get()
@Bind(User())
async findOne(user) {
console.log(user);
}
```
#### 데이터 넘겨주기
작성한 데코레이터가 특정 조건에 의존하여 동작해야 한다면, 데코레이터를 만드는 팩토리 함수에 넘겨주기 위한 `data` 매개변수를 사용할 수 있습니다. 사용 사례로는 요청 객체에서 특정 키로 프로퍼티를 가져오는 사용자 정의 데코레이터가 있습니다. 예를 들어, <a href="techniques/authentication#implementing-passport-strategies">인증 계층</a>에서는 요청 내용에 대해 유효성 검사를 실시한 후에 요청 객체 속에 사용자 정의 정보를 붙입니다. 인증에 성공한 사용자 정의 정보는 다음과 같을 것입니다:
```json
{
"id": 101,
"firstName": "Alan",
"lastName": "Turing",
"email": "alan@email.com",
"roles": ["admin"]
}
```
이제 키를 통해 이 프로퍼티를 가져와서 값이 있다면 그 값을 반환하는 데코레이터를 작성해 봅시다. (`user`객체가 없거나 객체에 값이 없다면 undefined를 반환합니다.)
```typescript
@@filename(user.decorator)
import { createParamDecorator, ExecutionContext } from '@nestjs/common';
export const User = createParamDecorator(
(data: string, ctx: ExecutionContext) => {
const request = ctx.switchToHttp().getRequest();
const user = request.user;
return data ? user?.[data] : user;
},
);
@@switch
import { createParamDecorator } from '@nestjs/common';
export const User = createParamDecorator((data, ctx) => {
const request = ctx.switchToHttp().getRequest();
const user = request.user;
return data ? user && user[data] : user;
});
```
이제 컨트롤러에서 `@User()`데코레이터를 통해 특정 프로퍼티에 접근할 수 있습니다.
```typescript
@@filename()
@Get()
async findOne(@User('firstName') firstName: string) {
console.log(`Hello ${firstName}`);
}
@@switch
@Get()
@Bind(User('firstName'))
async findOne(firstName) {
console.log(`Hello ${firstName}`);
}
```
다른 프로퍼티에 접근하기 위해서는 똑같은 데코레이터에 다른 키를 사용하면 됩니다. 만약 `user`객체의 깊이가 깊거나 복잡하다면, 이 방법은 요청 핸들러를 더욱 쉽고 가독성 높게 구현하도록 만들어줄 수 있습니다.
> info **힌트** 타입스크립트 사용자 정의들은 `createParamDecorator<T>()`함수가 제네릭 타입을 취한다는 것을 염두해 두시길 바랍니다. 예를 들어 `createParamDecorator<string>((data, ctx) => ...)`와 같이 사용하여 명시적으로 Type Safety를 강제할 수 있습니다. 또한 `createParamDecorator((data: string, ctx) => ...)`와 같이 팩토리 함수의 매개변수 타입을 정할 수도 있습니다. 두 군데 모두 타입을 명시하지 않으면 `data`의 타입은 `any`가 됩니다.
#### 파이프와 함께 사용
Nest는 사용자 정의 파라미터 데코레이터를 이미 구현되어 있는 파라미터 데코레이터들(`@Body()`와 `@Param()`, `@Query()`)과 똑같은 방식으로 처리합니다. 즉, 파이프는 사용자 정의 데코레이터가 붙은 인자(아래 예제에서는 `user`)에 대해서도 실행됩니다. 게다가 사용자 정의 데코레이터에 직접적으로 파이프를 적용시킬 수도 있습니다:
```typescript
@@filename()
@Get()
async findOne(
@User(new ValidationPipe({ validateCustomDecorators: true }))
user: UserEntity,
) {
console.log(user);
}
@@switch
@Get()
@Bind(User(new ValidationPipe({ validateCustomDecorators: true })))
async findOne(user) {
console.log(user);
}
```
> info **힌트** `validateCustomDecorators` 옵션을 꼭 true로 지정해야 합니다. `ValidationPipe`는 기본적으로 사용자 정의 데코레이터가 붙은 인자에 대해 유효성 검사를 수행하지 않습니다.
#### 데코레이터 조합
Nest는 여러 데코레이터를 조합하는 헬퍼 메서드를 제공합니다. 예를 들어, 인증과 관련된 모든 데코레이터들을 모아 하나의 데코레이터로 사용하고 싶다면 다음과 같이 구성할 수 있습니다:
```typescript
@@filename(auth.decorator)
import { applyDecorators } from '@nestjs/common';
export function Auth(...roles: Role[]) {
return applyDecorators(
SetMetadata('roles', roles),
UseGuards(AuthGuard, RolesGuard),
ApiBearerAuth(),
ApiUnauthorizedResponse({ description: 'Unauthorized' }),
);
}
@@switch
import { applyDecorators } from '@nestjs/common';
export function Auth(...roles) {
return applyDecorators(
SetMetadata('roles', roles),
UseGuards(AuthGuard, RolesGuard),
ApiBearerAuth(),
ApiUnauthorizedResponse({ description: 'Unauthorized' }),
);
}
```
그 다음엔 아래와 같이 `@Auth()`라는 사용자 정의 데코레이터를 사용합니다:
```typescript
@Get('users')
@Auth('admin')
findAllUsers() {}
```
이렇게 하면 하나의 데코레이터로 네 개의 데코레이터를 모두 적용시킬 수 있는 효과를 얻을 수 있습니다.
> warning **주의** `@nestjs/swagger` 패키지의 `@ApiHideProperty()` 데코레이터는 조합할 수 없으며 `applyDecorators` 함수와 함께 사용하면 제대로 동작하지 않습니다.
================================================
FILE: content/discover/who-uses.json
================================================
{
"Header": [
{
"logo": "/assets/logo/roche-logo.png",
"url": "https://roche.com",
"width": "90px"
},
{
"logo": "/assets/logo/adidas.svg",
"url": "https://adidas.com",
"width": "80px"
},
{
"logo": "/assets/logo/capgemini.svg",
"url": "https://capgemini.com"
},
{
"logo": "/assets/logo/societe-generale-logo.png",
"url": "https://www.societegenerale.fr/"
},
{
"logo": "/assets/logo/rewe.svg",
"url": "https://rewe-digital.com/",
"width": "180px"
},
{
"logo": "/assets/logo/decathlon.png",
"url": "https://www.decathlon.com/"
},
{
"logo": "/assets/logo/autodesk.png",
"url": "https://www.autodesk.com/"
},
{
"logo": "/assets/logo/neo4j.png",
"url": "https://www.neo4j.com/"
},
{
"logo": "/assets/logo/shipt.png",
"url": "https://www.shipt.com/"
},
{
"logo": "/assets/logo/sanofi.png",
"url": "https://github.com/Sanofi-IADC"
},
{
"logo": "https://nestjs.com/img/valor-software.png",
"url": "https://valor-software.com/"
},
{
"logo": "/assets/logo/sitepen.svg",
"url": "https://sitepen.com"
},
{
"logo": "https://nestjs.com/img/gojob-logo.png",
"url": "https://gojob.com/",
"width": "100px"
},
{
"logo": "https://nestjs.com/img/neoteric.png",
"url": "https://neoteric.eu/"
},
{
"logo": "/assets/logo/trellis.png",
"url": "https://trellis.org/",
"width": "70px"
},
{
"logo": "https://nestjs.com/img/scalio-logo.svg",
"url": "https://scal.io",
"width": "120px"
},
{
"logo": "https://nestjs.com/img/swingdev-logo.svg",
"url": "https://swingdev.io/"
},
{
"logo": "/assets/logo/cultura-colectiva.png",
"url": "https://culturacolectiva.com",
"width": "90px"
},
{
"logo": "https://nestjs.com/img/trilon.png",
"url": "https://trilon.io"
},
{
"logo": "/assets/logo/architectnow.png",
"url": "http://architectnow.net",
"width": "150px"
},
{
"logo": "/assets/logo/iflix.svg",
"url": "https://www.iflix.com",
"width": "70px"
},
{
"logo": "https://nestjs.com/img/genuinebee.svg",
"url": "https://genuinebee.com/"
},
{
"logo": "/assets/logo/run-players-league.png",
"url": "https://runplayersleague.com",
"width": "80px"
},
{
"logo": "/assets/logo/yanrongyun.svg",
"url": "http://www.yanrongyun.com",
"width": "120px"
},
{
"logo": "/assets/logo/sclable.svg",
"url": "https://sclable.com",
"width": "120px"
},
{
"logo": "/assets/logo/dozto.png",
"url": "https://www.dozto.com",
"width": "117px"
},
{
"logo": "/assets/logo/qingtui.png",
"url": "https://www.qingtui.cn/",
"width": "90px"
},
{
"logo": "/assets/logo/crowdlinker.svg",
"url": "https://crowdlinker.com/",
"width": "110px"
},
{
"logo": "/assets/logo/nothing.svg",
"url": "https://nothing.ch/",
"width": "110px"
},
{
"logo": "/assets/logo/swissdevjobs-devops-logo.png",
"url": "https://swissdevjobs.ch/jobs/Dev-Ops/All",
"width": "65px"
},
{
"logo": "/assets/logo/zeoagency.svg",
"url": "https://zeo.org/tr/",
"width": "80px"
},
{
"logo": "/assets/logo/valueadd.png",
"url": "https://valueadd.pl/",
"width": "120px"
},
{
"logo": "/assets/logo/bedu.svg",
"url": "https://bedu.org",
"width": "100px"
},
{
"logo": "/assets/logo/shopback.png",
"url": "https://shopback.com",
"width": "100px"
},
{
"logo": "/assets/logo/facile.png",
"url": "https://www.facile.it",
"width": "100px"
},
{
"logo": "/assets/logo/interfacewerk.png",
"url": "https://interfacewerk.de",
"width": "130px"
},
{
"logo": "/assets/logo/ottonova.png",
"url": "https://www.ottonova.de",
"width": "130px"
},
{
"logo": "/assets/logo/radity.png",
"url": "https://radity.com",
"width": "120px"
},
{
"logo": "/assets/logo/global-cto-forum.png",
"url": "https://globalctoforum.org/",
"width": "120px"
},
{
"logo": "/assets/logo/rivvy.png",
"url": "https://rivvy.app",
"width": "120px"
},
{
"logo": "/assets/logo/vue-storefront.png",
"url": "https://www.vuestorefront.io/"
}
],
"Body": [
"https://gorrion.io/",
"http://balticdatascience.com/",
"https://prohabits.com/",
"https://komed-health.com/",
"https://kerberus.com.co/",
"http://xtremis.com/",
"https://notadd.com/",
"http://jsdaddy.io/",
"https://yumpingo.com/",
"https://analytics-importer.cz/",
"https://dayzim.com/",
"https://wizkids.co.uk/",
"https://pilvia.com/",
"https://wi-q.com/",
"http://agrofel.com.br",
"https://societegenerale.com/",
"https://trashpanda.hulan.nl/",
"https://bytedance.com/",
"https://votercircle.com",
"https://erento.com",
"https://ideas.manticore-labs.com/",
"https://smartexlab.com/",
"https://automama.ru/",
"https://iflix.com/",
"https://frontendwatch.com/",
"https://mobilejazz.com/",
"https://cgiandi.com/",
"https://www.titlex.com.au/",
"https://codengage.com/",
"https://budacode.com/",
"https://blueanchor.io/",
"https://www.easymetrics.com/",
"https://getapollo.io/",
"https://big-bench.com/",
"https://www.qingtui.cn/",
"https://www.rosebayconsult.com/",
"https://www.patrocinium.com/",
"https://creatorsdaily.com",
"https://autoscar.com.br",
"https://www.mediktiv.com",
"https://harmonize.health",
"https://accerlery.be",
"https://www.facile.it",
"https://shopback.com",
"https://www.ottonova.de",
"https://www.radity.com",
"https://globalctoforum.org",
"https://halojasa.com",
"https://hexito.com",
"https://rivvy.app",
"https://padfever.com/",
"https://datenlotse.org",
"https://bemum.co",
"https://weoptimeye.ai",
"https://nemovote.com",
"https://selleo.com",
"https://pchas.ir",
"https://tayeh.ir",
"https://forwardigital.co.uk",
"https://rozetka.com.ua",
"https://www.itrio.net",
"https://dyrector.io",
"https://stijlbreuk.nl"
]
}
================================================
FILE: content/discover/who-uses.md
================================================
### Who is using Nest?
We are proudly helping various companies building their products at scale.
If you are using Nest and would you like to be listed here, see this [thread](https://github.com/nestjs/nest/issues/1006).
We are willing to put your logo here!
#### Companies
According to our knowledge, all the following companies have built awesome projects on top of our framework:
================================================
FILE: content/enterprise.md
================================================
### Official NestJS Consulting
Our goal is to ensure that your developers are successful and productive with NestJS as well as other modern technologies in today's ever-changing tech world.
### Official Support
With official support, get expert help directly from the NestJS core team. We tackle your toughest challenges, and collaborate with your team on many levels such as:
- Providing technical guidance & architectural reviews
- **Mentoring** team members
- Advising best practices
- Solving design decisions
- Addressing security & performance concerns
- Performing **in-depth** code reviews
<div class="row">
<div class="content">
<h4>Team Augmentation & Development</h4>
<p>
With team augmentation, NestJS core team members can work directly with your team on a daily basis to help take your project to the next-level. Consider us “part of your team”, tackling the most ambitious projects - right by your side.
</p>
</div>
<div class="thumbnail p-l-30">
<img src="/assets/enterprise/help.svg" />
</div>
</div>
<div class="row">
<div class="thumbnail p-r-30">
<img src="/assets/enterprise/contact.svg" />
</div>
<div class="content">
<h4>NestJS Best Practices</h4>
<p>
Frequent code reviews can eliminate potentially hazardous bugs & issues at an early stage and help enforce best practices. Let us perform PR reviews & audits to ensure your code quality, performance, and security.
</p>
</div>
</div>
#### First-hand access
Direct communication channel will boost team velocity, giving a quick access to discuss and solve problems.
#### NestJS Workshops and Trainings
We provide solid kick-off training as well as more advanced ones that give teams an in-depth understanding of NestJS. We offer on-site workshops and remote intensive sessions which help get you up and running _quickly_ within the NestJS ecosystem.
<div class="contact-us">
<div class="column column-text">
<h5>Contact us!</h5>
<p>
Let's talk how we can help you become successful with NestJS.
</p>
</div>
<div class="column column-action">
<a href="mailto:support@nestjs.com">CONTACT US</a>
</div>
</div>
Reach out to us at [support@nestjs.com](mailto:support@nestjs.com), and let’s talk about your project & teams needs!
================================================
FILE: content/exception-filters.md
================================================
### Exception filters
Nest comes with a built-in **exceptions layer** which is responsible for processing all unhandled exceptions across an application. When an exception is not handled by your application code, it is caught by this layer, which then automatically sends an appropriate user-friendly response.
<figure>
<img src="/assets/Filter_1.png" />
</figure>
Out of the box, this action is performed by a built-in **global exception filter**, which handles exceptions of type `HttpException` (and subclasses of it). When an exception is **unrecognized** (is neither `HttpException` nor a class that inherits from `HttpException`), the built-in exception filter generates the following default JSON response:
```json
{
"statusCode": 500,
"message": "Internal server error"
}
```
> info **Hint** The global exception filter partially supports the `http-errors` library. Basically, any thrown exception containing the `statusCode` and `message` property will be properly populated and send back as a response (instead of the default `InternalServerErrorException` for unrecognized exceptions).
#### Throwing standard exceptions
Nest provides a built-in `HttpException` class, exposed from the `@nestjs/common` package. For typical HTTP REST/GraphQL API based applications, it's best practice to send standard HTTP response objects when certain error conditions occur.
For example, in the `CatsController`, we have a `findAll()` method (a `GET` route handler). Let's assume that this route handler throws an exception for some reason. To demonstrate this, we'll hard-code it as follows:
```typescript
@@filename(cats.controller)
@Get()
async findAll() {
throw new HttpException('Forbidden', HttpStatus.FORBIDDEN);
}
```
> info **Hint** We used the `HttpStatus` here. This is a helper enum imported from the `@nestjs/common` package.
When the client calls this endpoint, the response looks like this:
```json
{
"statusCode": 403,
"message": "Forbidden"
}
```
The `HttpException` constructor takes two required arguments which determine the
response:
- The `response` argument defines the JSON response body. It can be a `string`
or an `object` as described below.
- The `status` argument defines the [HTTP status code](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status).
By default, the JSON response body contains two properties:
- `statusCode`: defaults to the HTTP status code provided in the `status` argument
- `message`: a short description of the HTTP error based on the `status`
To override just the message portion of the JSON response body, supply a string
in the `response` argument. To override the entire JSON response body, pass an object in the `response` argument. Nest will serialize the object and return it as the JSON response body.
The second constructor argument - `status` - should be a valid HTTP status code.
Best practice is to use the `HttpStatus` enum imported from `@nestjs/common`.
Here's an example overriding the entire response body:
```typescript
@@filename(cats.controller)
@Get()
async findAll() {
throw new HttpException({
status: HttpStatus.FORBIDDEN,
error: 'This is a custom message',
}, HttpStatus.FORBIDDEN);
}
```
Using the above, this is how the response would look:
```json
{
"status": 403,
"error": "This is a custom message"
}
```
#### Custom exceptions
In many cases, you will not need to write custom exceptions, and can use the built-in Nest HTTP exception, as described in the next section. If you do need to create customized exceptions, it's good practice to create your own **exceptions hierarchy**, where your custom exceptions inherit from the base `HttpException` class. With this approach, Nest will recognize your exceptions, and automatically take care of the error responses. Let's implement such a custom exception:
```typescript
@@filename(forbidden.exception)
export class ForbiddenException extends HttpException {
constructor() {
super('Forbidden', HttpStatus.FORBIDDEN);
}
}
```
Since `ForbiddenException` extends the base `HttpException`, it will work seamlessly with the built-in exception handler, and therefore we can use it inside the `findAll()` method.
```typescript
@@filename(cats.controller)
@Get()
async findAll() {
throw new ForbiddenException();
}
```
#### Built-in HTTP exceptions
Nest provides a set of standard exceptions that inherit from the base `HttpException`. These are exposed from the `@nestjs/common` package, and represent many of the most common HTTP exceptions:
- `BadRequestException`
- `UnauthorizedException`
- `NotFoundException`
- `ForbiddenException`
- `NotAcceptableException`
- `RequestTimeoutException`
- `ConflictException`
- `GoneException`
- `HttpVersionNotSupportedException`
- `PayloadTooLargeException`
- `UnsupportedMediaTypeException`
- `UnprocessableEntityException`
- `InternalServerErrorException`
- `NotImplementedException`
- `ImATeapotException`
- `MethodNotAllowedException`
- `BadGatewayException`
- `ServiceUnavailableException`
- `GatewayTimeoutException`
- `PreconditionFailedException`
#### Exception filters
While the base (built-in) exception filter can automatically handle many cases for you, you may want **full control** over the exceptions layer. For example, you may want to add logging or use a different JSON schema based on some dynamic factors. **Exception filters** are designed for exactly this purpose. They let you control the exact flow of control and the content of the response sent back to the client.
Let's create an exception filter that is responsible for catching exceptions which are an instance of the `HttpException` class, and implementing custom response logic for them. To do this, we'll need to access the underlying platform `Request` and `Response` objects. We'll access the `Request` object so we can pull out the original `url` and include that in the logging information. We'll use the `Response` object to take direct control of the response that is sent, using the `response.json()` method.
```typescript
@@filename(http-exception.filter)
import { ExceptionFilter, Catch, ArgumentsHost, HttpException } from '@nestjs/common';
import { Request, Response } from 'express';
@Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter {
catch(exception: HttpException, host: ArgumentsHost) {
const ctx = host.switchToHttp();
const response = ctx.getResponse<Response>();
const request = ctx.getRequest<Request>();
const status = exception.getStatus();
response
.status(status)
.json({
statusCode: status,
timestamp: new Date().toISOString(),
path: request.url,
});
}
}
@@switch
import { Catch, HttpException } from '@nestjs/common';
@Catch(HttpException)
export class HttpExceptionFilter {
catch(exception, host) {
const ctx = host.switchToHttp();
const response = ctx.getResponse();
const request = ctx.getRequest();
const status = exception.getStatus();
response
.status(status)
.json({
statusCode: status,
timestamp: new Date().toISOString(),
path: request.url,
});
}
}
```
> info **Hint** All exception filters should implement the generic `ExceptionFilter<T>` interface. This requires you to provide the `catch(exception: T, host: ArgumentsHost)` method with its indicated signature. `T` indicates the type of the exception.
The `@Catch(HttpException)` decorator binds the required metadata to the exception filter, telling Nest that this particular filter is looking for exceptions of type `HttpException` and nothing else. The `@Catch()` decorator may take a single parameter, or a comma-separated list. This lets you set up the filter for several types of exceptions at once.
#### Arguments host
Let's look at the parameters of the `catch()` method. The `exception` parameter is the exception object currently being processed. The `host` parameter is an `ArgumentsHost` object. `ArgumentsHost` is a powerful utility object that we'll examine further in the [execution context chapter](/fundamentals/execution-context)\*. In this code sample, we use it to obtain a reference to the `Request` and `Response` objects that are being passed to the original request handler (in the controller where the exception originates). In this code sample, we've used some helper methods on `ArgumentsHost` to get the desired `Request` and `Response` objects. Learn more about `ArgumentsHost` [here](/fundamentals/execution-context).
\*The reason for this level of abstraction is that `ArgumentsHost` functions in all contexts (e.g., the HTTP server context we're working with now, but also Microservices and WebSockets). In the execution context chapter we'll see how we can access the appropriate <a href="https://docs.nestjs.com/fundamentals/execution-context#host-methods">underlying arguments</a> for **any** execution context with the power of `ArgumentsHost` and its helper functions. This will allow us to write generic exception filters that operate across all contexts.
<app-banner-courses></app-banner-courses>
#### Binding filters
Let's tie our new `HttpExceptionFilter` to the `CatsController`'s `create()` method.
```typescript
@@filename(cats.controller)
@Post()
@UseFilters(new HttpExceptionFilter())
async create(@Body() createCatDto: CreateCatDto) {
throw new ForbiddenException();
}
@@switch
@Post()
@UseFilters(new HttpExceptionFilter())
@Bind(Body())
async create(createCatDto) {
throw new ForbiddenException();
}
```
> info **Hint** The `@UseFilters()` decorator is imported from the `@nestjs/common` package.
We have used the `@UseFilters()` decorator here. Similar to the `@Catch()` decorator, it can take a single filter instance, or a comma-separated list of filter instances. Here, we created the instance of `HttpExceptionFilter` in place. Alternatively, you may pass the class (instead of an instance), leaving responsibility for instantiation to the framework, and enabling **dependency injection**.
```typescript
@@filename(cats.controller)
@Post()
@UseFilters(HttpExceptionFilter)
async create(@Body() createCatDto: CreateCatDto) {
throw new ForbiddenException();
}
@@switch
@Post()
@UseFilters(HttpExceptionFilter)
@Bind(Body())
async create(createCatDto) {
throw new ForbiddenException();
}
```
> info **Hint** Prefer applying filters by using classes instead of instances when possible. It reduces **memory usage** since Nest can easily reuse instances of the same class across your entire module.
In the example above, the `HttpExceptionFilter` is applied only to the single `create()` route handler, making it method-scoped. Exception filters can be scoped at different levels: method-scoped, controller-scoped, or global-scoped. For example, to set up a filter as controller-scoped, you would do the following:
```typescript
@@filename(cats.controller)
@UseFilters(new HttpExceptionFilter())
export class CatsController {}
```
This construction sets up the `HttpExceptionFilter` for every route handler defined inside the `CatsController`.
To create a global-scoped filter, you would do the following:
```typescript
@@filename(main)
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.useGlobalFilters(new HttpExceptionFilter());
await app.listen(3000);
}
bootstrap();
```
> warning **Warning** The `useGlobalFilters()` method does not set up filters for gateways or hybrid applications.
Global-scoped filters are used across the whole application, for every controller and every route handler. In terms of dependency injection, global filters registered from outside of any module (with `useGlobalFilters()` as in the example above) cannot inject dependencies since this is done outside the context of any module. In order to solve this issue, you can register a global-scoped filter **directly from any module** using the following construction:
```typescript
@@filename(app.module)
import { Module } from '@nestjs/common';
import { APP_FILTER } from '@nestjs/core';
@Module({
providers: [
{
provide: APP_FILTER,
useClass: HttpExceptionFilter,
},
],
})
export class AppModule {}
```
> info **Hint** When using this approach to perform dependency injection for the filter, note that regardless of the module where this construction is employed, the filter is, in fact, global. Where should this be done? Choose the module where the filter (`HttpExceptionFilter` in the example above) is defined. Also, `useClass` is not the only way of dealing with custom provider registration. Learn more [here](/fundamentals/custom-providers).
You can add as many filters with this technique as needed; simply add each to the providers array.
#### Catch everything
In order to catch **every** unhandled exception (regardless of the exception type), leave the `@Catch()` decorator's parameter list empty, e.g., `@Catch()`.
In the example below we have a code that is platform-agnostic because it uses the [HTTP adapter](./faq/http-adapter) to deliver the response, and doesn't use any of the platform-specific objects (`Request` and `Response`) directly:
```typescript
import {
ExceptionFilter,
Catch,
ArgumentsHost,
HttpException,
HttpStatus,
} from '@nestjs/common';
import { HttpAdapterHost } from '@nestjs/core';
@Catch()
export class AllExceptionsFilter implements ExceptionFilter {
constructor(private readonly httpAdapterHost: HttpAdapterHost) {}
catch(exception: unknown, host: ArgumentsHost): void {
// In certain situations `httpAdapter` might not be available in the
// constructor method, thus we should resolve it here.
const { httpAdapter } = this.httpAdapterHost;
const ctx = host.switchToHttp();
const httpStatus =
exception instanceof HttpException
? exception.getStatus()
: HttpStatus.INTERNAL_SERVER_ERROR;
const responseBody = {
statusCode: httpStatus,
timestamp: new Date().toISOString(),
path: httpAdapter.getRequestUrl(ctx.getRequest()),
};
httpAdapter.reply(ctx.getResponse(), responseBody, httpStatus);
}
}
```
#### Inheritance
Typically, you'll create fully customized exception filters crafted to fulfill your application requirements. However, there might be use-cases when you would like to simply extend the built-in default **global exception filter**, and override the behavior based on certain factors.
In order to delegate exception processing to the base filter, you need to extend `BaseExceptionFilter` and call the inherited `catch()` method.
```typescript
@@filename(all-exceptions.filter)
import { Catch, ArgumentsHost } from '@nestjs/common';
import { BaseExceptionFilter } from '@nestjs/core';
@Catch()
export class AllExceptionsFilter extends BaseExceptionFilter {
catch(exception: unknown, host: ArgumentsHost) {
super.catch(exception, host);
}
}
@@switch
import { Catch } from '@nestjs/common';
import { BaseExceptionFilter } from '@nestjs/core';
@Catch()
export class AllExceptionsFilter extends BaseExceptionFilter {
catch(exception, host) {
super.catch(exception, host);
}
}
```
> warning **Warning** Method-scoped and Controller-scoped filters that extend the `BaseExceptionFilter` should not be instantiated with `new`. Instead, let the framework instantiate them automatically.
The above implementation is just a shell demonstrating the approach. Your implementation of the extended exception filter would include your tailored **business** logic (e.g., handling various conditions).
Global filters **can** extend the base filter. This can be done in either of two ways.
The first method is to inject the `HttpServer` reference when instantiating the custom global filter:
```typescript
async function bootstrap() {
const app = await NestFactory.create(AppModule);
const { httpAdapter } = app.get(HttpAdapterHost);
app.useGlobalFilters(new AllExceptionsFilter(httpAdapter));
await app.listen(3000);
}
bootstrap();
```
The second method is to use the `APP_FILTER` token <a href="exception-filters#binding-filters">as shown here</a>.
================================================
FILE: content/faq/errors.md
================================================
### Common errors
During your development with NestJS, you may encounter various errors as you learn the framework.
#### "Cannot resolve dependency" error
Probably the most common error message is about Nest not being able to resolve dependencies of a provider. The error message usually looks something like this:
```bash
Nest can't resolve dependencies of the <provider> (?). Please make sure that the argument <unknown_token> at index [<index>] is available in the <module> context.
Potential solutions:
- If <unknown_token> is a provider, is it part of the current <module>?
- If <unknown_token> is exported from a separate @Module, is that module imported within <module>?
@Module({
imports: [ /* the Module containing <unknown_token> */ ]
})
```
The most common culprit of the error, is not having the `provider` in the module's `providers` array. Please make sure that the provider is indeed in the `providers` array and following [standard NestJS provider practices](/fundamentals/custom-providers#di-fundamentals).
There are a few gotchas, that are common. One is putting a provider in an `imports` array. If this is the case, the error will have the provider's name where `<module>` should be.
If you run across this error while developing, take a look at the module mentioned in the error message and look at its `providers`. For each provider in the `providers` array, make sure the module has access to all of the dependencies. Often times, `providers` are duplicated in a "Feature Module" and a "Root Module" which means Nest will try to instantiate the provider twice. More than likely, the module containing the `provider` being duplicated should be added in the "Root Module"'s `imports` array instead.
If the `unknown_token` above is the string `dependency`, you might have a circular file import. This is different from the [circular dependency](./errors.md#circular-dependency-error) below because instead of having providers depend on each other in their constructors, it just means that two files end up importing each other. A common case would be a module file declaring a token and importing a provider, and the provider import the token constant from the module file. If you are using barrel files, ensure that your barrel imports do not end up creating these circular imports as well.
#### "Circular dependency" error
Occasionally you'll find it difficult to avoid [circular dependencies](/fundamentals/circular-dependency) in your application. You'll need to take some steps to help Nest resolve these. Errors that arise from circular dependencies look like this:
```bash
Nest cannot create the <module> instance.
The module at index [<index>] of the <module> "imports" array is undefined.
Potential causes:
- A circular dependency between modules. Use forwardRef() to avoid it. Read more: https://docs.nestjs.com/fundamentals/circular-dependency
- The module at index [<index>] is of type "undefined". Check your import statements and the type of the module.
Scope [<module_import_chain>]
# example chain AppModule -> FooModule
```
Circular dependencies can arise from both providers depending on each other, or typescript files depending on each other for constants, such as exporting constants from a module file and importing them in a service file. In the latter case, it is advised to create a separate file for your constants. In the former case, please follow the guide on circular dependencies and make sure that both the modules **and** the providers are marked with `forwardRef`.
#### Debugging dependency errors
Along with just manually verifying your dependencies are correct, as of Nest 8.1.0 you can set the `NEST_DEBUG` environment variable to a string that resolves as truthy, and get extra logging information while Nest is resolving all of the dependencies for the application.
<figure><img src="/assets/injector_logs.png" /></figure>
In the above image, the string in yellow is the host class of the dependency being injected, the string in blue is the name of the injected dependency, or its injection token, and the string in purple is the module in which the dependency is being searched for. Using this, you can usually trace back the dependency resolution for what's happening and why you're getting dependency injection problems.
================================================
FILE: content/faq/global-prefix.md
================================================
### Global prefix
HTTP 어플리케이션에 등록된 **모든 경로에** 접두사(prefix)를 붙이기 위해서는, `INestApplication` 인스턴스의 `setGlobalPrefix()` 메서드를 사용합니다.
```typescript
const app = await NestFactory.create(AppModule);
app.setGlobalPrefix('v1');
```
다음 구성을 사용해 전역 접두사(prefix)에서 경로를 제외할 수 있습니다.
```typescript
app.setGlobalPrefix('v1', {
exclude: [{ path: 'health', method: RequestMethod.GET }],
});
```
대안으로, 경로를 문자열로 지정할 수도 있습니다 (모든 요청 메서드에 적용됩니다).
```typescript
app.setGlobalPrefix('v1', { exclude: ['cats'] });
```
================================================
FILE: content/faq/http-adapter.md
================================================
### HTTP adapter
Occasionally, you may want to access the underlying HTTP server, either within the Nest application context or from the outside.
Every native (platform-specific) HTTP server/library (e.g., Express and Fastify) instance is wrapped in an **adapter**. The adapter is registered as a globally available provider that can be retrieved from the application context, as well as injected into other providers.
#### Outside application context strategy
To get a reference to the `HttpAdapter` from outside of the application context, call the `getHttpAdapter()` method.
```typescript
@@filename()
const app = await NestFactory.create(AppModule);
const httpAdapter = app.getHttpAdapter();
```
#### In-context strategy
To get a reference to the `HttpAdapterHost` from within the application context, inject it using the same technique as any other existing provider (e.g., using constructor injection).
```typescript
@@filename()
export class CatsService {
constructor(private adapterHost: HttpAdapterHost) {}
}
@@switch
@Dependencies(HttpAdapterHost)
export class CatsService {
constructor(adapterHost) {
this.adapterHost = adapterHost;
}
}
```
> info **Hint** The `HttpAdapterHost` is imported from the `@nestjs/core` package.
The `HttpAdapterHost` is **not** an actual `HttpAdapter`. To get the actual `HttpAdapter` instance, simply access the `httpAdapter` property.
```typescript
const adapterHost = app.get(HttpAdapterHost);
const httpAdapter = adapterHost.httpAdapter;
```
The `httpAdapter` is the actual instance of the HTTP adapter used by the underlying framework. It is an instance of either `ExpressAdapter` or `FastifyAdapter` (both classes extend `AbstractHttpAdapter`).
The adapter object exposes several useful methods to interact with the HTTP server. However, if you want to access the library instance (e.g., the Express instance) directly, call the `getInstance()` method.
```typescript
const instance = httpAdapter.getInstance();
```
================================================
FILE: content/faq/hybrid-application.md
================================================
### Hybrid application
A hybrid application is one that both listens for HTTP requests, as well as makes use of connected microservices. The `INestApplication` instance can be connected with `INestMicroservice` instances through the `connectMicroservice()` method.
```typescript
const app = await NestFactory.create(AppModule);
const microservice = app.connectMicroservice({
transport: Transport.TCP,
});
await app.startAllMicroservices();
await app.listen(3001);
```
To connect multiple microservice instances, issue the call to `connectMicroservice()` for each microservice:
```typescript
const app = await NestFactory.create(AppModule);
// microservice #1
const microserviceTcp = app.connectMicroservice<MicroserviceOptions>({
transport: Transport.TCP,
options: {
port: 3001,
},
});
// microservice #2
const microserviceRedis = app.connectMicroservice<MicroserviceOptions>({
transport: Transport.REDIS,
options: {
url: 'redis://localhost:6379',
},
});
await app.startAllMicroservices();
await app.listen(3001);
```
To bind `@MessagePattern()` to only one transport strategy (for example, MQTT) in a hybrid application with multiple microservices, we can pass the second argument of type `Transport` which is an enum with all the built-in transport strategies defined.
```typescript
@@filename()
@MessagePattern('time.us.*', Transport.NATS)
getDate(@Payload() data: number[], @Ctx() context: NatsContext) {
console.log(`Subject: ${context.getSubject()}`); // e.g. "time.us.east"
return new Date().toLocaleTimeString(...);
}
@MessagePattern({ cmd: 'time.us' }, Transport.TCP)
getTCPDate(@Payload() data: number[]) {
return new Date().toLocaleTimeString(...);
}
@@switch
@Bind(Payload(), Ctx())
@MessagePattern('time.us.*', Transport.NATS)
getDate(data, context) {
console.log(`Subject: ${context.getSubject()}`); // e.g. "time.us.east"
return new Date().toLocaleTimeString(...);
}
@Bind(Payload(), Ctx())
@MessagePattern({ cmd: 'time.us' }, Transport.TCP)
getTCPDate(data, context) {
return new Date().toLocaleTimeString(...);
}
```
> info **Hint** `@Payload()`, `@Ctx()`, `Transport` and `NatsContext` are imported from `@nestjs/microservices`.
#### Sharing configuration
By default a hybrid application will not inherit global pipes, interceptors, guards and filters configured for the main (HTTP-based) application.
To inherit these configuration properties from the main application, set the `inheritAppConfig` property in the second argument (an optional options object) of the `connectMicroservice()` call, as follow:
```typescript
const microservice = app.connectMicroservice({
transport: Transport.TCP
}, { inheritAppConfig: true });
```
================================================
FILE: content/faq/multiple-servers.md
================================================
### HTTPS
To create an application that uses the HTTPS protocol, set the `httpsOptions` property in the options object passed to the `create()` method of the `NestFactory` class:
```typescript
const httpsOptions = {
key: fs.readFileSync('./secrets/private-key.pem'),
cert: fs.readFileSync('./secrets/public-certificate.pem'),
};
const app = await NestFactory.create(AppModule, {
httpsOptions,
});
await app.listen(3000);
```
If you use the `FastifyAdapter`, create the application as follows:
```typescript
const app = await NestFactory.create<NestFastifyApplication>(
AppModule,
new FastifyAdapter({ https: httpsOptions }),
);
```
#### Multiple simultaneous servers
The following recipe shows how to instantiate a Nest application that listens on multiple ports (for example, on a non-HTTPS port and an HTTPS port) simultaneously.
```typescript
const httpsOptions = {
key: fs.readFileSync('./secrets/private-key.pem'),
cert: fs.readFileSync('./secrets/public-certificate.pem'),
};
const server = express();
const app = await NestFactory.create(
AppModule,
new ExpressAdapter(server),
);
await app.init();
http.createServer(server).listen(3000);
https.createServer(httpsOptions, server).listen(443);
```
> info **Hint** The `ExpressAdapter` is imported from the `@nestjs/platform-express` package. The `http` and `https` packages are native Node.js packages.
> **Warning** This recipe does not work with [GraphQL Subscriptions](/graphql/subscriptions).
================================================
FILE: content/faq/request-lifecycle.md
================================================
### Request lifecycle
Nest applications handle requests and produce responses in a sequence we refer to as the **request lifecycle**. With the use of middleware, pipes, guards, and interceptors, it can be challenging to track down where a particular piece of code executes during the request lifecycle, especially as global, controller level, and route level components come into play. In general, a request flows through middleware to guards, then to interceptors, then to pipes and finally back to interceptors on the return path (as the response is generated).
#### Middleware
Middleware is executed in a particular sequence. First, Nest runs globally bound middleware (such as middleware bound with `app.use`) and then it runs [module bound middleware](/middleware), which are determined on paths. Middleware are run sequentially in the order they are bound, similar to the way middleware in Express works. In the case of middleware bound across different modules, the middleware bound to the root module will run first, and then middleware will run in the order that the modules are added to the imports array.
#### Guards
Guard execution starts with global guards, then proceeds to controller guards, and finally to route guards. As with middleware, guards run in the order in which they are bound. For example:
```typescript
@UseGuards(Guard1, Guard2)
@Controller('cats')
export class CatsController {
constructor(private catsService: CatsService) {}
@UseGuards(Guard3)
@Get()
getCats(): Cats[] {
return this.catsService.getCats();
}
}
```
`Guard1` will execute before `Guard2` and both will execute before `Guard3`.
> info **Hint** When speaking about globally bound vs controller or locally bound, the difference is where the guard (or other component is bound). If you are using `app.useGlobalGuard()` or providing the component via a module, it is globally bound. Otherwise, it is bound to a controller if the decorator precedes a controller class, or to a route if the decorator proceeds a route declaration.
#### Interceptors
Interceptors, for the most part, follow the same pattern as guards, with one catch: as interceptors return [RxJS Observables](https://github.com/ReactiveX/rxjs), the observables will be resolved in a first in last out manner. So inbound requests will go through the standard global, controller, route level resolution, but the response side of the request (i.e., after returning from the controller method handler) will be resolved from route to controller to global. Also, any errors thrown by pipes, controllers, or services can be read in the `catchError` operator of an interceptor.
#### Pipes
Pipes follow the standard global to controller to route bound sequence, with the same first in first out in regards to the `@usePipes()` parameters. However, at a route parameter level, if you have multiple pipes running, they will run in the order of the last parameter with a pipe to the first. This also applies to the route level and controller level pipes. For example, if we have the following controller:
```typescript
@UsePipes(GeneralValidationPipe)
@Controller('cats')
export class CatsController {
constructor(private catsService: CatsService) {}
@UsePipes(RouteSpecificPipe)
@Patch(':id')
updateCat(
@Body() body: UpdateCatDTO,
@Param() params: UpdateCatParams,
@Query() query: UpdateCatQuery,
) {
return this.catsService.updateCat(body, params, query);
}
}
```
then the `GeneralValidationPipe` will run for the `query`, then the `params`, and then the `body` objects before moving on to the `RouteSpecificPipe`, which follows the same order. If any parameter-specific pipes were in place, they would run (again, from the last to first parameter) after the controller and route level pipes.
#### Filters
Filters are the only component that do not resolve global first. Instead, filters resolve from the lowest level possible, meaning execution starts with any route bound filters and proceeding next to controller level, and finally to global filters. Note that exceptions cannot be passed from filter to filter; if a route level filter catches the exception, a controller or global level filter cannot catch the same exception. The only way to achieve an effect like this is to use inheritance between the filters.
> info **Hint** Filters are only executed if any uncaught exception occurs during the request process. Caught exceptions, such as those caught with a `try/catch` will not trigger Exception Filters to fire. As soon as an uncaught exception is encountered, the rest of the lifecycle is ignored and the request skips straight to the filter.
#### Summary
In general, the request lifecycle looks like the following:
1. Incoming request
2. Globally bound middleware
3. Module bound middleware
4. Global guards
5. Controller guards
6. Route guards
7. Global interceptors (pre-controller)
8. Controller interceptors (pre-controller)
9. Route interceptors (pre-controller)
10. Global pipes
11. Controller pipes
12. Route pipes
13. Route parameter pipes
14. Controller (method handler)
15. Service (if exists)
16. Route interceptor (post-request)
17. Controller interceptor (post-request)
18. Global interceptor (post-request)
19. Exception filters (route, then controller, then global)
20. Server response
================================================
FILE: content/faq/serverless.md
================================================
### Serverless
Serverless computing is a cloud computing execution model in which the cloud provider allocates machine resources on-demand, taking care of the servers on behalf of their customers. When an app is not in use, there are no computing resources allocated to the app. Pricing is based on the actual amount of resources consumed by an application ([source](https://en.wikipedia.org/wiki/Serverless_computing)).
With a **serverless architecture**, you focus purely on the individual functions in your application code. Services such as AWS Lambda, Google Cloud Functions, and Microsoft Azure Functions take care of all the physical hardware, virtual machine operating system, and web server software management.
> info **Hint** This chapter does not cover the pros and cons of serverless functions nor dives into the specifics of any cloud providers.
#### Cold start
A cold start is the first time your code has been executed in a while. Depending on a cloud provider you use, it may span several different operations, from downloading the code and bootstrapping the runtime to eventually running your code.
This process adds **significant latency** depending on several factors, the language, the number of packages your application require, etc.
The cold start is important and although there are things which are beyond our control, there's still a lot of things we can do on our side to make it as short as possible.
While you can think of Nest as a fully-fledged framework designed to be used in complex, enterprise applications,
it is also **suitable for much "simpler" applications** (or scripts). For example, with the use of [Standalone applications](/standalone-applications) feature, you can take advantage of Nest's DI system in simple workers, CRON jobs, CLIs, or serverless functions.
#### Benchmarks
To better understand what's the cost of using Nest or other, well-known libraries (like `express`) in the context of serverless functions, let's compare how much time Node runtime needs to run the following scripts:
```typescript
// #1 Express
import * as express from 'express';
async function bootstrap() {
const app = express();
app.get('/', (req, res) => res.send('Hello world!'));
await new Promise<void>((resolve) => app.listen(3000, resolve));
}
bootstrap();
// #2 Nest (with @nestjs/platform-express)
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule, { logger: ['error'] });
await app.listen(3000);
}
bootstrap();
// #3 Nest as a Standalone application (no HTTP server)
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { AppService } from './app.service';
async function bootstrap() {
const app = await NestFactory.createApplicationContext(AppModule, {
logger: ['error'],
});
console.log(app.get(AppService).getHello());
}
bootstrap();
// #4 Raw Node.js script
async function bootstrap() {
console.log('Hello world!');
}
bootstrap();
```
For all these scripts, we used the `tsc` (TypeScript) compiler and so the code remains unbundled (`webpack` isn't used).
| | |
| ------------------------------------ | ----------------- |
| Express | 0.0079s (7.9ms) |
| Nest with `@nestjs/platform-express` | 0.1974s (197.4ms) |
| Nest (standalone application) | 0.1117s (111.7ms) |
| Raw Node.js script | 0.0071s (7.1ms) |
> info **Note** Machine: MacBook Pro Mid 2014, 2.5 GHz Quad-Core Intel Core i7, 16 GB 1600 MHz DDR3, SSD.
Now, let's repeat all benchmarks but this time, using `webpack` (if you have [Nest CLI](/cli/overview) installed, you can run `nest build --webpack`) to bundle our application into a single executable JavaScript file.
However, instead of using the default `webpack` configuration that Nest CLI ships with, we'll make sure to bundle all dependencies (`node_modules`) together, as follows:
```javascript
module.exports = (options, webpack) => {
const lazyImports = [
'@nestjs/microservices/microservices-module',
'@nestjs/websockets/socket-module',
];
return {
...options,
externals: [],
plugins: [
...options.plugins,
new webpack.IgnorePlugin({
checkResource(resource) {
if (lazyImports.includes(resource)) {
try {
require.resolve(resource);
} catch (err) {
return true;
}
}
return false;
},
}),
],
};
};
```
> info **Hint** To instruct Nest CLI to use this configuration, create a new `webpack.config.js` file in the root directory of your project.
With this configuration, we received the following results:
| | |
| ------------------------------------ | ---------------- |
| Express | 0.0068s (6.8ms) |
| Nest with `@nestjs/platform-express` | 0.0815s (81.5ms) |
| Nest (standalone application) | 0.0319s (31.9ms) |
| Raw Node.js script | 0.0066s (6.6ms) |
> info **Note** Machine: MacBook Pro Mid 2014, 2.5 GHz Quad-Core Intel Core i7, 16 GB 1600 MHz DDR3, SSD.
> info **Hint** You could optimize it even further by applying additional code minification & optimization techniques (using `webpack` plugins, etc.).
As you can see, the way you compile (and whether you bundle your code) is crucial and has a significant impact on the overall startup time. With `webpack`, you can get the bootstrap time of a standalone Nest application (starter project with one module, controller, and service) down to ~32ms on average, and down to ~81.5ms for a regular HTTP, express-based NestJS app.
For more complicated Nest applications, for example, with 10 resources (generated through `$ nest g resource` schematic = 10 modules, 10 controllers, 10 services, 20 DTO classes, 50 HTTP endpoints + `AppModule`), the overall startup on MacBook Pro Mid 2014, 2.5 GHz Quad-Core Intel Core i7, 16 GB 1600 MHz DDR3, SSD is approximately 0.1298s (129.8ms). Running a monolithic application as a serverless function typically doesn't make too much sense anyway, so think of this benchmark more as an example of how the bootstrap time may potentially increase as your application grows.
#### Runtime optimizations
Thus far we covered compile-time optimizations. These are unrelated to the way you define providers and load Nest modules in your application, and that plays an essential role as your application gets bigger.
For example, imagine having a database connection defined as an [asynchronous provider](/fundamentals/async-providers). Async providers are designed to delay the application start until one or more asynchronous tasks are completed.
That means, if your serverless function on average requires 2s to connect to the database (on bootstrap), your endpoint will need at least two extra seconds (because it must wait till the connection is established) to send a response back (when it's a cold start and your application wasn't running already).
As you can see, the way you structure your providers is somewhat different in a **serverless environment** where bootstrap time is important.
Another good example is if you use Redis for caching, but only in certain scenarios. Perhaps, in this case, you should not define a Redis connection as an async provider, as it would slow down the bootstrap time, even if it's not required for this specific function invocation.
Also, sometimes you could lazy-load entire modules, using the `LazyModuleLoader` class, as described in [this chapter](/fundamentals/lazy-loading-modules). Caching is a great example here too.
Imagine that your application has, let's say, `CacheModule` which internally connects to Redis and also, exports the `CacheService` to interact with the Redis storage. If you don't need it for all potential function invocations,
you can just load it on-demand, lazily. This way you'll get a faster startup time (when a cold start occurs) for all invocations that don't require caching.
```typescript
if (request.method === RequestMethod[RequestMethod.GET]) {
const { CacheModule } = await import('./cache.module');
const moduleRef = await this.lazyModuleLoader.load(() => CacheModule);
const { CacheService } = await import('./cache.service');
const cacheService = moduleRef.get(CacheService);
return cacheService.get(ENDPOINT_KEY);
}
```
Another great example is a webhook or worker, which depending on some specific conditions (e.g., input arguments), may perform different operations.
In such a case, you could specify a condition inside your route handler that lazily loads an appropriate module for the specific function invocation, and just load every other module lazily.
```typescript
if (workerType === WorkerType.A) {
const { WorkerAModule } = await import('./worker-a.module');
const moduleRef = await this.lazyModuleLoader.load(() => WorkerAModule);
// ...
} else if (workerType === WorkerType.B) {
const { WorkerBModule } = await import('./worker-b.module');
const moduleRef = await this.lazyModuleLoader.load(() => WorkerBModule);
// ...
}
```
#### Example integration
The way your application's entry file (typically `main.ts` file) is supposed to look like **depends on several factors** and so **there's no single template** that just works for every scenario.
For example, the initialization file required to spin up your serverless function varies by cloud providers (AWS, Azure, GCP, etc.).
Also, depending on whether you want to run a typical HTTP application with multiple routes/endpoints or just provide a single route (or execute a specific portion of code),
your application's code will look different (for example, for the endpoint-per-function approach you could use the `NestFactory.createApplicationContext` instead of booting the HTTP server, setting up middleware, etc.).
Just for illustration purposes, we'll integrate Nest (using `@nestjs/platform-express` and so spinning up the whole, fully functional HTTP router)
with the [Serverless](https://www.serverless.com/) framework (in this case, targetting AWS Lambda). As we've mentioned earlier, your code will differ depending on the cloud provider you choose, and many other factors.
First, let's install the required packages:
```bash
$ npm i @vendia/serverless-express aws-lambda
$ npm i -D @types/aws-lambda serverless-offline
```
> info **Hint** To speed up development cycles, we install the `serverless-offline` plugin which emulates AWS λ and API Gateway.
Once the installation process is complete, let's create the `serverless.yml` file to configure the Serverless framework:
```yaml
service:
name: serverless-example
plugins:
- serverless-offline
provider:
name: aws
runtime: nodejs12.x
functions:
main:
handler: dist/main.handler
events:
- http:
method: ANY
path: /
- http:
method: ANY
path: '{proxy+}'
```
> info **Hint** To learn more about the Serverless framework, visit the [official documentation](https://www.serverless.com/framework/docs/).
With this place, we can now navigate to the `main.ts` file and update our bootstrap code with the required boilerplate:
```typescript
import { NestFactory } from '@nestjs/core';
import serverlessExpress from '@vendia/serverless-express';
import { Callback, Context, Handler } from 'aws-lambda';
import { AppModule } from './app.module';
let server: Handler;
async function bootstrap(): Promise<Handler> {
const app = await NestFactory.create(AppModule);
await app.init();
const expressApp = app.getHttpAdapter().getInstance();
return serverlessExpress({ app: expressApp });
}
export const handler: Handler = async (
event: any,
context: Context,
callback: Callback,
) => {
server = server ?? (await bootstrap());
return server(event, context, callback);
};
```
> info **Hint** For creating multiple serverless functions and sharing common modules between them, we recommend using the [CLI Monorepo mode](/cli/monorepo#monorepo-mode).
> warning **Warning** If you use `@nestjs/swagger` package, there are a few additional steps required to make it work properly in the context of serverless function. Check out this [article](https://javascript.plainenglish.io/serverless-nestjs-document-your-api-with-swagger-and-aws-api-gateway-64a53962e8a2) for more information.
Next, open up the `tsconfig.json` file and make sure to enable the `esModuleInterop` option to make the `@vendia/serverless-express` package load properly.
```json
{
"compilerOptions": {
...
"esModuleInterop": true
}
}
```
Now we can build our application (with `nest build` or `tsc`) and use the `serverless` CLI to start our lambda function locally:
```bash
$ npm run build
$ npx serverless offline
```
Once the application is running, open your browser and navigate to `http://localhost:3000/dev/[ANY_ROUTE]` (where `[ANY_ROUTE]` is any endpoint registered in your application).
In the sections above, we've shown that using `webpack` and bundling your app can have significant impact on the overall bootstrap time.
However, to make it work with our example, there are a few additional configurations you must add in your `webpack.config.js` file. Generally,
to make sure our `handler` function will be picked up, we must change the `output.libraryTarget` property to `commonjs2`.
```javascript
return {
...options,
externals: [],
output: {
...options.output,
libraryTarget: 'commonjs2',
},
// ... the rest of the configuration
};
```
With this in place, you can now use `$ nest build --webpack` to compile your function's code (and then `$ npx serverless offline` to test it).
It's also recommended (but **not required** as it will slow down your build process) to install the `terser-webpack-plugin` package and override its configuration to keep classnames intact when minifying your production build. Not doing so can result in incorrect behavior when using `class-validator` within your application.
```javascript
const TerserPlugin = require('terser-webpack-plugin');
return {
...options,
externals: [],
optimization: {
minimizer: [
new TerserPlugin({
terserOptions: {
keep_classnames: true,
},
}),
],
},
output: {
...options.output,
libraryTarget: 'commonjs2',
},
// ... the rest of the configuration
};
```
#### Using standalone application feature
Alternatively, if you want to keep your function very lightweight and you don't need any HTTP-related features (routing, but also guards, interceptors, pipes, etc.),
you can just use `NestFactory.createApplicationContext` (as mentioned earlier) instead of running the entire HTTP server (and `express` under the hood), as follows:
```typescript
@@filename(main)
import { HttpStatus } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import { Callback, Context, Handler } from 'aws-lambda';
import { AppModule } from './app.module';
import { AppService } from './app.service';
export const handler: Handler = async (
event: any,
context: Context,
callback: Callback,
) => {
const appContext = await NestFactory.createApplicationContext(AppModule);
const appService = appContext.get(AppService);
return {
body: appService.getHello(),
statusCode: HttpStatus.OK,
};
};
```
> info **Hint** Be aware that `NestFactory.createApplicationContext` does not wrap controller methods with enhancers (guard, interceptors, etc.). For this, you must use the `NestFactory.create` method.
You could also pass the `event` object down to, let's say, `EventsService` provider that could process it and return a corresponding value (depending on the input value and your business logic).
```typescript
export const handler: Handler = async (
event: any,
context: Context,
callback: Callback,
) => {
const appContext = await NestFactory.createApplicationContext(AppModule);
const eventsService = appContext.get(EventsService);
return eventsService.process(event);
};
```
================================================
FILE: content/first-steps.md
================================================
### 시작하기
이 문서에서는 Nest의 **핵심 원리** 에 대해 알아봅니다. Nest 애플리케이션의 필수 구성 요소를 숙지하려면,
기초적인 수준에서 많은 분야를 다루며 기본적인 CRUD 애플리케이션을 구축해 봐야 합니다.
#### 언어
우리는 [TypeScript](https://www.typescriptlang.org/)와 사랑에 빠졌지만, 무엇보다도 [Node.js](https://nodejs.org/en/)를 사랑합니다. 이것이 Nest가 TypeScript, **pure JavaScript** 모두와 호환되는 이유입니다. Nest는 최신 언어 기능을 활용하기 때문에 바닐라 자바스크립트와 함께 사용하려면 [Babel](https://babeljs.io/) 컴파일러가 필요합니다.
우리가 제공하는 예제 에서는 대부분 타입스크립트를 사용하겠지만, 언제든 바닐라 자바스크립트로 **코드 스니펫을 전환** 할 수 있습니다 (각 스니펫의 오른쪽 상단 모서리에 있는 언어 버튼을 클릭하여 전환).
#### 전제조건
운영 체제에 [Node.js](https://nodejs.org/)(>= 10.13.0, v13 제외)가 설치되어 있는지 확인하세요.
#### 설정하기
[Nest CLI](/cli/overview) 로 새 프로젝트를 설정하는 것은 매우 간단합니다. [npm](https://www.npmjs.com/)이 설치되어 있다면, OS 터미널에서 다음 명령을 사용해 새 Nest 프로젝트를 생성할 수 있습니다.
```bash
$ npm i -g @nestjs/cli
$ nest new project-name
```
`project-name` 디렉토리가 생성되고, node modules 와 몇가지 boilerplate 파일들이 생성되며, `src/` 디렉토리와 함께 여러개의 코어 파일들로 채워집니다.
<div class="file-tree">
<div class="item">src</div>
<div class="children">
<div class="item">app.controller.spec.ts</div>
<div class="item">app.controller.ts</div>
<div class="item">app.module.ts</div>
<div class="item">app.service.ts</div>
<div class="item">main.ts</div>
</div>
</div>
다음은 코어 파일들의 간략한 설명 입니다.
| | |
| ------------------------ | ------------------------------------------------------------------------------------------------------------------- |
| `app.controller.ts` | A basic controller with a single route. |
| `app.controller.spec.ts` | The unit tests for the controller. |
| `app.module.ts` | The root module of the application. |
| `app.service.ts` | A basic service with a single method. |
| `main.ts` | The entry file of the application which uses the core function `NestFactory` to create a Nest application instance. |
`main.ts`는 우리의 어플리케이션의 **시작점**이 되는 비동기 함수를 포함하고 있습니다.
```typescript
@@filename(main)
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
await app.listen(3000);
}
bootstrap();
@@switch
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
await app.listen(3000);
}
bootstrap();
```
Nest 애플리케이션 인스턴스를 생성하기 위해 우리는 `NestFactory` 클래스를 사용합니다. `NestFactory` 는 애플리케이션 인스턴스를 만들 수 있는 몇가지 정적 메소드를 제공합니다. `create()` 메소드는 `INestApplication` 인터페이스를 따르는 애플리케이션 객체를 반환합니다. 이 객체는 다음 장에서 설명하는 메소드 집합을 제공합니다. 우리는 위의 `main.ts` 예제에서 HTTP 요청을 받을 수 있도록 HTTP 리스너를 실행 했습니다.
Nest CLI로 생성된 프로젝트는 개발자가 각 모듈을 독립된 디렉토리에 작성하는 관례를 따르도록 권장하기 위해 초기 프로젝트 구조를 생성합니다.
<app-banner-courses></app-banner-courses>
#### 플랫폼
Nest는 플랫폼에 구애받지 않는 프레임워크가 되는 것을 목표로 합니다. 플랫폼 독립성을 통해 개발자가 여러 유형의 애플리케이션에 걸쳐 활용할 수 있는 재사용 가능한 논리적 모듈을 만들 수 있습니다. 기술적으로 Nest는 어댑터가 만들어지면 어떤 Node HTTP 프레임워크에서도 동작 합니다. 기본적으로 지원되는 HTTP 플랫폼은 [express](https://expressjs.com/)와 [fastify](https://www.fastify.io) 두 가지가 있습니다. 요구사항에 맞는 적합한 프레임워크를 선택하여 사용하면 됩니다.
| | |
| ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `platform-express` | [Express](https://expressjs.com/) is a well-known minimalist web framework for node. It's a battle tested, production-ready library with lots of resources implemented by the community. The `@nestjs/platform-express` package is used by default. Many users are well served with Express, and need take no action to enable it. |
| `platform-fastify` | [Fastify](https://www.fastify.io/) is a high performance and low overhead framework highly focused on providing maximum efficiency and speed. Read how to use it [here](/techniques/performance). |
어떤 플랫폼을 사용하더라도 자체적인 애플리케이션 인터페이스를 제공합니다. 각각 `NestExpressApplication` 과 `NestFastifyApplication` 입니다.
아래 예제와 같이 타입을 `NestFactory.create()` 메소드에 전달하면 `app` 객체는 해당 특정 플랫폼에서만 사용할 수있는 메소드를 갖게 됩니다. 하지만 참고로, 실제로 기본 플랫폼 API에 액세스하려는 경우가 **아니라면** 타입을 지정할 **필요**가 없습니다.
```typescript
const app = await NestFactory.create<NestExpressApplication>(AppModule);
```
#### 애플리케이션 실행
설치가 끝났다면 OS 명령 프롬프트에서 다음 명령을 실행하여 HTTP 요청을 기다리는 애플리케이션을 시작할 수 있습니다.
```bash
$ npm run start
```
이 명령은 `src/main.ts` 파일에 정의된 포트에서 HTTP 서버 앱을 시작합니다. 애플리케이션이 실행되면 브라우저를 열고 `http://localhost:3000/`로 이동하세요. `Hello World!` 라는 메시지를 볼 수 있습니다.
================================================
FILE: content/fundamentals/async-components.md
================================================
### Asynchronous providers
At times, the application start should be delayed until one or more **asynchronous tasks** are completed. For example, you may not want to start accepting requests until the connection with the database has been established. You can achieve this using asynchronous providers.
The syntax for this is to use `async/await` with the `useFactory` syntax. The factory returns a `Promise`, and the factory function can `await` asynchronous tasks. Nest will await resolution of the promise before instantiating any class that depends on (injects) such a provider.
```typescript
{
provide: 'ASYNC_CONNECTION',
useFactory: async () => {
const connection = await createConnection(options);
return connection;
},
}
```
> info **Hint** Learn more about custom provider syntax [here](/fundamentals/custom-providers).
#### Injection
Asynchronous providers are injected to other components by their tokens, like any other provider. In the example above, you would use the construct `@Inject('ASYNC_CONNECTION')`.
#### Example
[The TypeORM recipe](/recipes/sql-typeorm) has a more substantial example of an asynchronous provider.
================================================
FILE: content/fundamentals/circular-dependency.md
================================================
### Circular dependency
A circular dependency occurs when two classes depend on each other. For example, class A needs class B, and class B also needs class A. Circular dependencies can arise in Nest between modules and between providers.
While circular dependencies should be avoided where possible, you can't always do so. In such cases, Nest enables resolving circular dependencies between providers in two ways. In this chapter, we describe using **forward referencing** as one technique, and using the **ModuleRef** class to retrieve a provider instance from the DI container as another.
We also describe resolving circular dependencies between modules.
> warning **Warning** A circular dependency might also be caused when using "barrel files"/index.ts files to group imports. Barrel files should be omitted when it comes to module/provider classes. For example, barrel files should not be used when importing files within the same directory as the barrel file, i.e. `cats/cats.controller` should not import `cats` to import the `cats/cats.service` file. For more details please also see [this github issue](https://github.com/nestjs/nest/issues/1181#issuecomment-430197191).
#### Forward reference
A **forward reference** allows Nest to reference classes which aren't yet defined using the `forwardRef()` utility function. For example, if `CatsService` and `CommonService` depend on each other, both sides of the relationship can use `@Inject()` and the `forwardRef()` utility to resolve the circular dependency. Otherwise Nest won't instantiate them because all of the essential metadata won't be available. Here's an example:
```typescript
@@filename(cats.service)
@Injectable()
export class CatsService {
constructor(
@Inject(forwardRef(() => CommonService))
private commonService: CommonService,
) {}
}
@@switch
@Injectable()
@Dependencies(forwardRef(() => CommonService))
export class CatsService {
constructor(commonService) {
this.commonService = commonService;
}
}
```
> info **Hint** The `forwardRef()` function is imported from the `@nestjs/common` package.
That covers one side of the relationship. Now let's do the same with `CommonService`:
```typescript
@@filename(common.service)
@Injectable()
export class CommonService {
constructor(
@Inject(forwardRef(() => CatsService))
private catsService: CatsService,
) {}
}
@@switch
@Injectable()
@Dependencies(forwardRef(() => CatsService))
export class CommonService {
constructor(catsService) {
this.catsService = catsService;
}
}
```
> warning **Warning** The order of instantiation is indeterminate. Make sure your code does not depend on which constructor is called first.
#### ModuleRef class alternative
An alternative to using `forwardRef()` is to refactor your code and use the `ModuleRef` class to retrieve a provider on one side of the (otherwise) circular relationship. Learn more about the `ModuleRef` utility class [here](/fundamentals/module-ref).
#### Module forward reference
In order to resolve circular dependencies between modules, use the same `forwardRef()` utility function on both sides of the modules association. For example:
```typescript
@@filename(common.module)
@Module({
imports: [forwardRef(() => CatsModule)],
})
export class CommonModule {}
```
================================================
FILE: content/fundamentals/dependency-injection.md
================================================
### Custom providers
In earlier chapters, we touched on various aspects of **Dependency Injection (DI)** and how it is used in Nest. One example of this is the [constructor based](https://docs.nestjs.com/providers#dependency-injection) dependency injection used to inject instances (often service providers) into classes. You won't be surprised to learn that Dependency Injection is built into the Nest core in a fundamental way. So far, we've only explored one main pattern. As your application grows more complex, you may need to take advantage of the full features of the DI system, so let's explore them in more detail.
#### DI fundamentals
Dependency injection is an [inversion of control (IoC)](https://en.wikipedia.org/wiki/Inversion_of_control) technique wherein you delegate instantiation of dependencies to the IoC container (in our case, the NestJS runtime system), instead of doing it in your own code imperatively. Let's examine what's happening in this example from the [Providers chapter](https://docs.nestjs.com/providers).
First, we define a provider. The `@Injectable()` decorator marks the `CatsService` class as a provider.
```typescript
@@filename(cats.service)
import { Injectable } from '@nestjs/common';
import { Cat } from './interfaces/cat.interface';
@Injectable()
export class CatsService {
private readonly cats: Cat[] = [];
findAll(): Cat[] {
return this.cats;
}
}
@@switch
import { Injectable } from '@nestjs/common';
@Injectable()
export class CatsService {
constructor() {
this.cats = [];
}
findAll() {
return this.cats;
}
}
```
Then we request that Nest inject the provider into our controller class:
```typescript
@@filename(cats.controller)
import { Controller, Get } from '@nestjs/common';
import { CatsService } from './cats.service';
import { Cat } from './interfaces/cat.interface';
@Controller('cats')
export class CatsController {
constructor(private catsService: CatsService) {}
@Get()
async findAll(): Promise<Cat[]> {
return this.catsService.findAll();
}
}
@@switch
import { Controller, Get, Bind, Dependencies } from '@nestjs/common';
import { CatsService } from './cats.service';
@Controller('cats')
@Dependencies(CatsService)
export class CatsController {
constructor(catsService) {
this.catsService = catsService;
}
@Get()
async findAll() {
return this.catsService.findAll();
}
}
```
Finally, we register the provider with the Nest IoC container:
```typescript
@@filename(app.module)
import { Module } from '@nestjs/common';
import { CatsController } from './cats/cats.controller';
import { CatsService } from './cats/cats.service';
@Module({
controllers: [CatsController],
providers: [CatsService],
})
export class AppModule {}
```
What exactly is happening under the covers to make this work? There are three key steps in the process:
1. In `cats.service.ts`, the `@Injectable()` decorator declares the `CatsService` class as a class that can be managed by the Nest IoC container.
2. In `cats.controller.ts`, `CatsController` declares a dependency on the `CatsService` token with constructor injection:
```typescript
constructor(private catsService: CatsService)
```
3. In `app.module.ts`, we associate the token `CatsService` with the class `CatsService` from the `cats.service.ts` file. We'll <a href="/fundamentals/custom-providers#standard-providers">see below</a> exactly how this association (also called _registration_) occurs.
When the Nest IoC container instantiates a `CatsController`, it first looks for any dependencies\*. When it finds the `CatsService` dependency, it performs a lookup on the `CatsService` token, which returns the `CatsService` class, per the registration step (#3 above). Assuming `SINGLETON` scope (the default behavior), Nest will then either create an instance of `CatsService`, cache it, and return it, or if one is already cached, return the existing instance.
\*This explanation is a bit simplified to illustrate the point. One important area we glossed over is that the process of analyzing the code for dependencies is very sophisticated, and happens during application bootstrapping. One key feature is that dependency analysis (or "creating the dependency graph"), is **transitive**. In the above example, if the `CatsService` itself had dependencies, those too would be resolved. The dependency graph ensures that dependencies are resolved in the correct order - essentially "bottom up". This mechanism relieves the developer from having to manage such complex dependency graphs.
<app-banner-courses></app-banner-courses>
#### Standard providers
Let's take a closer look at the `@Module()` decorator. In `app.module`, we declare:
```typescript
@Module({
controllers: [CatsController],
providers: [CatsService],
})
```
The `providers` property takes an array of `providers`. So far, we've supplied those providers via a list of class names. In fact, the syntax `providers: [CatsService]` is short-hand for the more complete syntax:
```typescript
providers: [
{
provide: CatsService,
useClass: CatsService,
},
];
```
Now that we see this explicit construction, we can understand the registration process. Here, we are clearly associating the token `CatsService` with the class `CatsService`. The short-hand notation is merely a convenience to simplify the most common use-case, where the token is used to request an instance of a class by the same name.
#### Custom providers
What happens when your requirements go beyond those offered by _Standard providers_? Here are a few examples:
- You want to create a custom instance instead of having Nest instantiate (or return a cached instance of) a class
- You want to re-use an existing class in a second dependency
- You want to override a class with a mock version for testing
Nest allows you to define Custom providers to handle these cases. It provides several ways to define custom providers. Let's walk through them.
> info **Hint** If you are having problems with dependency resolution you can set the `NEST_DEBUG` environment variable and get extra dependency resolution logs during startup.
#### Value providers: `useValue`
The `useValue` syntax is useful for injecting a constant value, putting an external library into the Nest container, or replacing a real implementation with a mock object. Let's say you'd like to force Nest to use a mock `CatsService` for testing purposes.
```typescript
import { CatsService } from './cats.service';
const mockCatsService = {
/* mock implementation
...
*/
};
@Module({
imports: [CatsModule],
providers: [
{
provide: CatsService,
useValue: mockCatsService,
},
],
})
export class AppModule {}
```
In this example, the `CatsService` token will resolve to the `mockCatsService` mock object. `useValue` requires a value - in this case a literal object that has the same interface as the `CatsService` class it is replacing. Because of TypeScript's [structural typing](https://www.typescriptlang.org/docs/handbook/type-compatibility.html), you can use any object that has a compatible interface, including a literal object or a class instance instantiated with `new`.
#### Non-class-based provider tokens
So far, we've used class names as our provider tokens (the value of the `provide` property in a provider listed in the `providers` array). This is matched by the standard pattern used with [constructor based injection](https://docs.nestjs.com/providers#dependency-injection), where the token is also a class name. (Refer back to <a href="/fundamentals/custom-providers#di-fundamentals">DI Fundamentals</a> for a refresher on tokens if this concept isn't entirely clear). Sometimes, we may want the flexibility to use strings or symbols as the DI token. For example:
```typescript
import { connection } from './connection';
@Module({
providers: [
{
provide: 'CONNECTION',
useValue: connection,
},
],
})
export class AppModule {}
```
In this example, we are associating a string-valued token (`'CONNECTION'`) with a pre-existing `connection` object we've imported from an external file.
> warning **Notice** In addition to using strings as token values, you can also use JavaScript [symbols](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol) or TypeScript [enums](https://www.typescriptlang.org/docs/handbook/enums.html).
We've previously seen how to inject a provider using the standard [constructor based injection](https://docs.nestjs.com/providers#dependency-injection) pattern. This pattern **requires** that the dependency be declared with a class name. The `'CONNECTION'` custom provider uses a string-valued token. Let's see how to inject such a provider. To do so, we use the `@Inject()` decorator. This decorator takes a single argument - the token.
```typescript
@@filename()
@Injectable()
export class CatsRepository {
constructor(@Inject('CONNECTION') connection: Connection) {}
}
@@switch
@Injectable()
@Dependencies('CONNECTION')
export class CatsRepository {
constructor(connection) {}
}
```
> info **Hint** The `@Inject()` decorator is imported from `@nestjs/common` package.
While we directly use the string `'CONNECTION'` in the above examples for illustration purposes, for clean code organization, it's best practice to define tokens in a separate file, such as `constants.ts`. Treat them much as you would symbols or enums that are defined in their own file and imported where needed.
#### Class providers: `useClass`
The `useClass` syntax allows you to dynamically determine a class that a token should resolve to. For example, suppose we have an abstract (or default) `ConfigService` class. Depending on the current environment, we want Nest to provide a different implementation of the configuration service. The following code implements such a strategy.
```typescript
const configServiceProvider = {
provide: ConfigService,
useClass:
process.env.NODE_ENV === 'development'
? DevelopmentConfigService
: ProductionConfigService,
};
@Module({
providers: [configServiceProvider],
})
export class AppModule {}
```
Let's look at a couple of details in this code sample. You'll notice that we define `configServiceProvider` with a literal object first, then pass it in the module decorator's `providers` property. This is just a bit of code organization, but is functionally equivalent to the examples we've used thus far in this chapter.
Also, we have used the `ConfigService` class name as our token. For any class that depends on `ConfigService`, Nest will inject an instance of the provided class (`DevelopmentConfigService` or `ProductionConfigService`) overriding any default implementation that may have been declared elsewhere (e.g., a `ConfigService` declared with an `@Injectable()` decorator).
#### Factory providers: `useFactory`
The `useFactory` syntax allows for creating providers **dynamically**. The actual provider will be supplied by the value returned from a factory function. The factory function can be as simple or complex as needed. A simple factory may not depend on any other providers. A more complex factory can itself inject other providers it needs to compute its result. For the latter case, the factory provider syntax has a pair of related mechanisms:
1. The factory function can accept (optional) arguments.
2. The (optional) `inject` property accepts an array of providers that Nest will resolve and pass as arguments to the factory function during the instantiation process. The two lists should be correlated: Nest will pass instances from the `inject` list as arguments to the factory function in the same order.
The example below demonstrates this.
```typescript
@@filename()
const connectionFactory = {
provide: 'CONNECTION',
useFactory: (optionsProvider: OptionsProvider) => {
const options = optionsProvider.get();
return new DatabaseConnection(options);
},
inject: [OptionsProvider],
};
@Module({
providers: [connectionFactory],
})
export class AppModule {}
@@switch
const connectionFactory = {
provide: 'CONNECTION',
useFactory: (optionsProvider) => {
const options = optionsProvider.get();
return new DatabaseConnection(options);
},
inject: [OptionsProvider],
};
@Module({
providers: [connectionFactory],
})
export class AppModule {}
```
#### Alias providers: `useExisting`
The `useExisting` syntax allows you to create aliases for existing providers. This creates two ways to access the same provider. In the example below, the (string-based) token `'AliasedLoggerService'` is an alias for the (class-based) token `LoggerService`. Assume we have two different dependencies, one for `'AliasedLoggerService'` and one for `LoggerService`. If both dependencies are specified with `SINGLETON` scope, they'll both resolve to the same instance.
```typescript
@Injectable()
class LoggerService {
/* implementation details */
}
const loggerAliasProvider = {
provide: 'AliasedLoggerService',
useExisting: LoggerService,
};
@Module({
providers: [LoggerService, loggerAliasProvider],
})
export class AppModule {}
```
#### Non-service based providers
While providers often supply services, they are not limited to that usage. A provider can supply **any** value. For example, a provider may supply an array of configuration objects based on the current environment, as shown below:
```typescript
const configFactory = {
provide: 'CONFIG',
useFactory: () => {
return process.env.NODE_ENV === 'development' ? devConfig : prodConfig;
},
};
@Module({
providers: [configFactory],
})
export class AppModule {}
```
#### Export custom provider
Like any provider, a custom provider is scoped to its declaring module. To make it visible to other modules, it must be exported. To export a custom provider, we can either use its token or the full provider object.
The following example shows exporting using the token:
```typescript
@@filename()
const connectionFactory = {
provide: 'CONNECTION',
useFactory: (optionsProvider: OptionsProvider) => {
const options = optionsProvider.get();
return new DatabaseConnection(options);
},
inject: [OptionsProvider],
};
@Module({
providers: [connectionFactory],
exports: ['CONNECTION'],
})
export class AppModule {}
@@switch
const connectionFactory = {
provide: 'CONNECTION',
useFactory: (optionsProvider) => {
const options = optionsProvider.get();
return new DatabaseConnection(options);
},
inject: [OptionsProvider],
};
@Module({
providers: [connectionFactory],
exports: ['CONNECTION'],
})
export class AppModule {}
```
Alternatively, export with the full provider object:
```typescript
@@filename()
const connectionFactory = {
provide: 'CONNECTION',
useFactory: (optionsProvider: OptionsProvider) => {
const options = optionsProvider.get();
return new DatabaseConnection(options);
},
inject: [OptionsProvider],
};
@Module({
providers: [connectionFactory],
exports: [connectionFactory],
})
export class AppModule {}
@@switch
const connectionFactory = {
provide: 'CONNECTION',
useFactory: (optionsProvider) => {
const options = optionsProvider.get();
return new DatabaseConnection(options);
},
inject: [OptionsProvider],
};
@Module({
providers: [connectionFactory],
exports: [connectionFactory],
})
export class AppModule {}
```
================================================
FILE: content/fundamentals/dynamic-modules.md
================================================
### 동적 모듈
[모듈 챕터](/modules)에서 모듈에 대한 기본적인 내용을 다루면서 [동적 모듈](https://docs.nestjs.com/modules#dynamic-modules)에 대해 간단히 소개하기도 했습니다. 이번 챕터에서는 동적 모듈에 대해 더 자세히 다룹니다. 이번 챕터를 마치고 나면 그것들이 무엇이며 언제 어떻게 사용하는지 제대로 파악할 수 있을 것입니다.
#### 소개
본 문서의 **개요** 섹션에 있는 대부분의 예제 코드에서는 일반 모듈이나 정적 모듈을 사용합니다. 모듈은 [프로바이더](/providers)와 [컨트롤러](/controllers)같이 전체 어플리케이션의 모듈적인 부분이 되어 함께 어울리는 컴포넌트들의 그룹을 나타냅니다. 모듈은 이러한 컴포넌트들에게 실행 컨텍스트나 스코프 등을 주입해 줍니다. 예를 들어, 어떤 모듈 안에 정의된 프로바이더를 따로 내보내지 않아도 해당 모듈의 다른 다른 멤버들이 그 프로바이더를 찾을 수 있습니다. 프로바이더가 모듈 바깥에 노출될 필요가 있다면, 우선 해당 프로바이더의 호스트 모듈로부터 내보낸 다음, 사용하고자 하는 모듈에 import 되어야 합니다.
익숙한 예시를 통해 다시 들여다 봅시다.
우선, `UsersModule`에서 `UsersService`를 공급받고 내보냅니다. `UsersModule`은 `UsersService`의 **호스트** 모듈입니다.
```typescript
import { Module } from "@nestjs/common";
import { UsersService } from "./users.service";
@Module({
providers: [UsersService],
exports: [UsersService],
})
export class UsersModule {}
```
그 다음, `UsersModule`을 import하는 `AuthModule`을 정의하고, `UsersModule`에서 내보낸 프로바이더를 `AuthModule` 내부에서 사용할 수 있게 만듭니다:
```typescript
import { Module } from "@nestjs/common";
import { AuthService } from "./auth.service";
import { UsersModule } from "../users/users.module";
@Module({
imports: [UsersModule],
providers: [AuthService],
exports: [AuthService],
})
export class AuthModule {}
```
이렇게 작성하면 `AuthModule`을 호스트로 두는 가령 `AuthService`같은 곳에 `UsersService`를 주입할 수 있게 됩니다:
```typescript
import { Injectable } from "@nestjs/common";
import { UsersService } from "../users/users.service";
@Injectable()
export class AuthService {
constructor(private usersService: UsersService) {}
/*
Implementation that makes use of this.usersService
*/
}
```
이와 같은 일을 **정적** 모듈 바인딩이라고 합니다. Nest가 엮어야 할 모듈에 대한 정보는 호스트 모듈과 그 모듈을 사용하는 모듈에 이미 정의되어 있습니다. 이러한 작업이 내부적으로 어떻게 이루어지는지 살펴봅시다. Nest는 아래의 과정들을 통해 `AuthModule` 내부에서 `UsersService`를 사용할 수 있게 만듭니다:
1. `UsersModule`을 인스턴스화 하는데, 이 때 이 모듈이 사용하는 다른 모듈들을 가져오면서 의존성을 해소합니다. ([사용자 정의 프로바이더](/fundamentals/custom-providers)를 참조해 주세요)
2. `AuthModule`을 인스턴스화 하면서, `UsersModule`에서 내보낸 프로바이더들을 `AuthModule` 속 컴포넌트들이 사용할 수 있게 만듭니다. (마치 그 프로바이더들이 `AuthModule` 안에 선언되듯이)
3. `AuthService`에 `UsersService` 인스턴스를 주입합니다.
#### 동적 모듈 사용 사례
정적 모듈 바인딩을 할 때, 사용하는 모듈 쪽에서는 호스트 모듈에서 제공하는 프로바이더를 설정할 수 있도록 영향을 미칠 기회가 없습니다. 그게 왜 문제가 될까요? 다양한 유스케이스에서 다르게 동작할 필요가 있도록 범용적으로 사용하는 모듈이 있다고 가정해 봅시다. 이것은 많은 시스템에서 "플러그인" 이라 칭하는 컨셉과 유사할 테고, 사용자가 이를 사용하기 전에 몇가지 설정을 해야 합니다.
Nest에서 이와 관련한 좋은 예시가 바로 **환경설정 모듈**입니다. 많은 애플리케이션들이 세부설정을 외부로 빼기 위해 환경설정 모듈을 유용하게 사용합니다. 이것은 다양한 배포환경에서 동적으로 애플리케이션 설정을 쉽게 바꿀 수 있게 해줍니다: 예를 들면, 개발자가 사용하는 개발용 데이터베이스, 스테이징과 테스팅 환경에서 쓰이는 스테이징 데이터베이스 등이 있습니다. 설정값들의 관리를 환경설정 모듈에게 위임함으로써, 애플리케이션의 소스코드를 설정값으로부터 독립적으로 유지할 수 있습니다.
해야 할 일은, 환경설정 모듈 자체는 "플러그인과"처럼 범용적이기 때문에 이를 사용하는 모듈에서 커스터마이징 하는 것입니다. 이곳이 바로 *동적 모듈*이 동작하는 곳입니다. 동적 모듈의 기능으로 환경설정 모듈을 **동적**으로 만들었기 때문에 사용하는 모듈에서는 환경설정 모듈을 import할 때 API를 호출할 수 있게 되며, 해당 API를 통해 환경설정 모듈이 어떻게 커스터마이징될지를 제어합니다.
달리 말하면, 동적 모듈은 어떤 모듈을 다른 여러 모듈에서 import한다거나 해당 모듈을 import할 때 그 모듈의 프로퍼티와 동작을 커스터마이징할 수 있도록 API를 제공합니다. 이는 이제껏 보았던 정적 바인딩과 아주 대조적입니다.
<app-banner-shop></app-banner-shop>
#### 설정 모듈 예제
이번 섹션에서는 [환경설정 챕터](https://docs.nestjs.com/techniques/configuration#service)의 예제 코드를 기반으로 설명하겠습니다. 이번 챕터를 통해 완성된 코드는 [이 예제](https://github.com/nestjs/nest/tree/master/sample/25-dynamic-modules)에서 동작을 확인할 수 있습니다.
우리의 요구사항은 `ConfigModule`을 만들고 이를 커스터마이징 하기 위해 `options` 객체를 사용하는 것입니다. 제공하려는 기능에 대해 말씀 드리겠습니다. 기본 예제에서는 `.env`파일의 위치가 프로젝트 폴더 최상단으로 하드코딩 되어 있습니다. 이것을 `.env` 파일들이 어느 폴더에 있든 관리할 수 있게끔 설정 가능하게 만든다고 가정해 봅시다. 예를 들어, 프로젝트 최상단의 `config`폴더(`src`폴더의 형제 위치) 안에 다양한 `.env` 파일들을 저장해 두었다고 한다면, 다른 프로젝트들에서는 `ConfigModule`을 사용할 때 다른 폴더를 지정하고 싶어집니다.
동적 모듈은 해당 모듈을 import할 때 인자를 전달할 수 있게 해주어 우리가 그 동작을 변경할 수 있게 됩니다. 이것이 어떻게 동작하는지 살펴봅시다. 사용하는 모듈의 관점에서 어떻게 보이는지부터 시작해서 거꾸로 파악해 나가면 더 이해하기 쉽습니다. 우선, `ConfigModule`을 _정적으로_ import하던 예제(모듈을 import할 때 그 모듈의 동작에 영향을 줄 수 없던 접근방식이었습니다)를 다시금 빠르게 살펴보고 지나갑시다. `@Module()` 데코레이터의 `imports` 배열을 집중적으로 봐주세요:
```typescript
import { Module } from "@nestjs/common";
import { AppController } from "./app.controller";
import { AppService } from "./app.service";
import { ConfigModule } from "./config/config.module";
@Module({
imports: [ConfigModule],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
```
우리가 설정 객체를 전달할 *동적 모듈*을 import하는 모습은 어떨지 생각해 봅시다. 위와 아래 두 예제의 `import` 배열에 어떤 차이가 있는지 비교해 보세요:
```typescript
import { Module } from "@nestjs/common";
import { AppController } from "./app.controller";
import { AppService } from "./app.service";
import { ConfigModule } from "./config/config.module";
@Module({
imports: [ConfigModule.register({ folder: "./config" })],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
```
위의 동적 모듈 예제에 무슨 일이 일어나는지 봅시다. 어떤 부분이 달라졌나요?
1. `ConfigModule`은 평범한 클래스이므로, `register()`이라는 **정적 메서드**를 가진다고 짐작할 수 있습니다. 이 메서드는 클래스의 **인스턴스**가 아니라 `ConfigModule` 클래스 자체에서 불러오기 때문에 정적입니다. 곧 구현할 이 메서드는 임의의 이름을 가질 수 있지만, 관례적으로 `forRoot()`나 `register()`라고 부릅니다.
2. `register()` 메서드는 우리가 만들 것이기 때문에 원하는 인자를 넣을 수 있습니다. 이번에는, 일반적인 경우에 적합한 프로퍼티들을 가지는 `options` 객체를 받도록 하겠습니다.
3. `register()` 메서드는 `module`같은 무언가를 반환해야 한다고 짐작할 수 있습니다. 왜냐면 그 반환 값이 `imports` 리스트에 들어가고 있고, 지금까지 이 리스트에 모듈들이 들어가는 것을 보았기 때문입니다.
사실, `register()`메서드는 `DynamicModule`을 반환합니다. 동적 모듈은 런타임에서 만들어진다는 것 말고는 아무것도 없습니다. 정적 모듈이 가지는 모든 프로퍼티를 동일하게 가지고, 거기에 `module`이라는 프로퍼티만 추가로 가집니다. 정적 모듈을 선언할 때 데코레이터에 전달되는 모듈 옵션을 다시금 빠르게 살펴봅시다:
```typescript
@Module({
imports: [DogsModule],
controllers: [CatsController],
providers: [CatsService],
exports: [CatsService]
})
```
동적 모듈은 인터페이스와 동일한 객체에 `module`이라는 프로퍼티를 추가하여 반환해야 합니다. `module` 프로퍼티는 모듈의 이름을 제공하며 아래 예시에서 볼 수 있듯 모듈의 클래스 이름과 같아야 합니다.
> info **힌트** 동적 모듈에서는 `module`프로퍼티를 **제외**하고 모듈 옵션 객체의 모든 프로퍼티를 선택적으로 가집니다.
`register()`라는 정적 메서드는 무엇일까요? 우리는 이제 이 메서드가 하는 일이 `DynamicModule` 인터페이스를 가지는 객체를 반환하는 것이라는 걸 압니다. 이 메서드를 호출함으로써, `imports` 리스트에 정적으로 모듈 클래스 이름을 적어주었던 것과 유사한 방법으로 모듈을 효과적으로 제공합니다. 달리 말하면, 동적 모듈의 API는 단순하게 어떤 모듈을 반환하되, `@Module` 데코레이터의 프로퍼티들을 고정시키지 않고 프로그래밍적으로 명시합니다.
그림을 완성하려면 몇 가지 세부사항들이 더 필요합니다:
1. 이제는 `@Module()` 데코레이터의 `imports` 프로퍼티에는 모듈 클래스 이름(예: `imports: [UsersModule]`)뿐만 아니라 동적 모듈을 반환하는 함수(예: `imports: [ConfigModule.register(...)]`)도 사용할 수 있다고 말할 수 있습니다.
2. 동적 모듈은 스스로 다른 모듈들을 import할 수 있습니다. 이번 예제에서는 그러지 않았지만 만약 동적 모듈이 다른 모듈의 프로바이더에 의존한다면, `imports` 프로퍼티를 사용하여 그 모듈들을 import하면 됩니다. 다시 말씀 드리지만, 정적 모듈에서 `@Module()` 데코레이터를 사용하여 메타데이터를 선언하던 방식과 완전히 동일합니다.
이러한 이해를 바탕으로, 이제 우리의 동적 모듈인 `ConfigModule`의 선언이 어떻게 생겼는지 확인할 수 있습니다. 다음과 같이 시도해 봅시다.
```typescript
import { DynamicModule, Module } from "@nestjs/common";
import { ConfigService } from "./config.service";
@Module({})
export class ConfigModule {
static register(): DynamicModule {
return {
module: ConfigModule,
providers: [ConfigService],
exports: [ConfigService],
};
}
}
```
이제는 지금까지 다룬 조각들이 서로 어떻게 연결되는지 명확히 이해할 차례입니다. `ConfigModule.register(...)`을 호출하면, 지금까지 `@Module()` 데코레이터를 통해 메타데이터를 제공했던 것과 본질적으로 동일한 프로퍼티를 가지는 `DynamicModule` 객체를 반환합니다.
> info **힌트** `DynamicModule`는 `@nestjs/common`에서 import합니다.
우리의 동적 모듈은 아직까지는 그다지 흥미롭지 않은데, 이는 우리가 하고 싶다고 말했던 그 **설정** 기능을 아직 다루지 않았기 때문입니다. 이는 다음 섹션에서 다루도록 하겠습니다.
#### 모듈 설정
위에서 추측한 대로, `ConfigModule`의 동작을 커스터마이징하는 분명한 방법은 정적 메서드인 `register()`에 `options` 객체를 넘기는 것입니다. 사용하는 모듈의 `imports` 프로퍼티를 다시 한 번 봅시다:
```typescript
import { Module } from "@nestjs/common";
import { AppController } from "./app.controller";
import { AppService } from "./app.service";
import { ConfigModule } from "./config/config.module";
@Module({
imports: [ConfigModule.register({ folder: "./config" })],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
```
동적 모듈에 `options` 객체를 넘기는 것이 좋은 조작입니다. 이후에 그 `options` 객체를 `ConfigModule`에서 어떻게 사용할 수 있을까요? 잠시 스스로 생각해 봅시다. `ConfigModule`은 기본적으로 다른 프로바이더에 주입할 수 있는 서비스(`ConfigService`)를 포함하고 내보내는 호스트 모듈입니다. 실제로 `options` 객체를 읽어서 동작을 커스터마이징 해야 하는 건 `ConfigService`입니다. 이러한 가정을 바탕으로, `options` 객체의 프로퍼티들을 기반으로 서비스의 동작을 커스터마이징 하기 위해 서비스를 약간 수정할 수 있습니다. (**참고**: 실제로 어떻게 전달하는지는 아직 다루지 않았기 때문에, 당분간은 `options`를 하드코딩하겠습니다. 이는 잠시 후에 해결하겠습니다.)
```typescript
import { Injectable } from "@nestjs/common";
import * as dotenv from "dotenv";
import * as fs from "fs";
import { EnvConfig } from "./interfaces";
@Injectable()
export class ConfigService {
private readonly envConfig: EnvConfig;
constructor() {
const options = { folder: "./config" };
const filePath = `${process.env.NODE_ENV || "development"}.env`;
const envFile = path.resolve(__dirname, "../../", options.folder, filePath);
this.envConfig = dotenv.parse(fs.readFileSync(envFile));
}
get(key: string): string {
return this.envConfig[key];
}
}
```
이제 `ConfigService`는 `options`에 명시한 폴더에서 `.env`파일을 찾습니다.
이제 남은 작업은 어떻게든 `options` 객체를 `register()`를 통해 `ConfigService`에 주입하는 것입니다. 이번에도 당연히 *의존성 주입*을 사용합니다. 이것이 중요한 포인트이니 꼭 숙지하시길 바랍니다. `ConfigModule`은 `ConfigService`를 제공합니다. `ConfigService`는 `options` 객체에 의존하며 이는 오직 런타임 환경에서만 제공됩니다. 따라서 런타임에서는, 우선 `options` 객체를 Nest의 IoC 컨테이너에 바인딩하고, Nest가 이를 `ConfigService`에 주입해야 합니다. **사용자 정의 프로바이더** 챕터에서 말씀 드렸듯 프로바이더는 [어떤 값이든 포함할 수 있다](https://docs.nestjs.com/fundamentals/custom-providers#non-service-based-providers)는 점을 기억하시길 바라며, 이는 단순히 서비스만 해당되는 내용이 아닙니다. 따라서 우리는 `options` 객체를 쉽게 다루기 위해 의존성 주입을 사용하기만 하면 됩니다.
options 객체를 IoC 컨테이너에 바인딩하는 문제부터 해결해 봅시다. 이 작업은 우리의 정적 메서드인 `register()`에서 이루어집니다. 우리는 지금 모듈을 동적으로 구성하고 있고, 모듈의 프로퍼티 중 하나는 프로바이더 리스트라는 점을 기억해 보세요. 그렇다면 우리가 해야 할 일은 우리의 options 객체를 프로바이더라고 정의하는 것입니다. 이렇게 하면 다음 단계에서 활용할 `ConfigModule`에 options 객체를 주입할 수 있게 됩니다. 아래 코드에서 `providers` 배열을 집중적으로 살펴보세요:
```typescript
import { DynamicModule, Module } from "@nestjs/common";
import { ConfigService } from "./config.service";
@Module({})
export class ConfigModule {
static register(options): DynamicModule {
return {
module: ConfigModule,
providers: [
{
provide: "CONFIG_OPTIONS",
useValue: options,
},
ConfigService,
],
exports: [ConfigService],
};
}
}
```
이제 `ConfigService`에 `'CONFIG_OPIONS'` 프로바이더를 주입하면 완성입니다. 클래스가 아닌 토큰을 사용하는 프로바이더를 정의하려면 `@Inject()` 데코레이터를 사용해야 하며, 이에 대한 내용은 [여기에서 설명하고 있습니다](https://docs.nestjs.com/fundamentals/custom-providers#non-class-based-provider-tokens).
```typescript
import * as dotenv from "dotenv";
import * as fs from "fs";
import { Injectable, Inject } from "@nestjs/common";
import { EnvConfig } from "./interfaces";
@Injectable()
export class ConfigService {
private readonly envConfig: EnvConfig;
constructor(@Inject("CONFIG_OPTIONS") private options) {
const filePath = `${process.env.NODE_ENV || "development"}.env`;
const envFile = path.resolve(__dirname, "../../", options.folder, filePath);
this.envConfig = dotenv.parse(fs.readFileSync(envFile));
}
get(key: string): string {
return this.envConfig[key];
}
}
```
마지막으로 기억해야 할 것이 있습니다. 위에서는 단순하게 문자열 기반의 주입 토큰(`'CONFIG_OPTIONS'`)을 사용했지만, 이러한 토큰을 정의하는 가장 좋은 방법은 별도의 파일에 상수(또는 `Symbol`)로 정의해 두고 다른 파일에서 가져다 사용하는 것입니다. 아래는 그 예시입니다:
```typescript
export const CONFIG_OPTIONS = "CONFIG_OPTIONS";
```
### 예제
이번 챕터의 예제 코드 최종본은 [여기](https://github.com/nestjs/nest/tree/master/sample/25-dynamic-modules)에 있습니다.
================================================
FILE: content/fundamentals/execution-context.md
================================================
### 실행 컨텍스트
Nest는 여러 애플리케이션 컨텍스트들(예를 들면 Nest HTTP 서버 기반과 마이크로서비스, 웹소켓 컨텍스트)을 아울러서 작동하는 애플리케이션을 쉽게 작성할 수 있도록 몇 가지 유틸리티 클래스들을 제공합니다. 이 유틸리티들은 전반적인 컨트롤러, 메서드, 실행 컨텍스트를 아울러 동작하는 범용적인 [가드](/guards), [필터](/exception-filters), [인터셉터](/interceptors)를 만들 수 있도록 현재 실행 컨텍스트에 대한 정보를 제공합니다.
이 챕터에서는 `ArgumentsHost`, `ExecutionContext` 두 클래스를 다룹니다.
#### ArgumentsHost 클래스
`ArgumentsHost` 클래스는 핸들러에 전달 된 인자들을 찾을 수 있는 메서드들을 제공하며, 인자들을 찾을 수 있는 적절한 컨텍스트(예를 들면 HTTP, RPC(마이크로서비스), 웹소켓)를 선택할 수 있게 해줍니다. 프레임워크는 `ArgumentsHost`의 인스턴스를 제공하며, 접근하려는 곳에서는 일반적으로 `host`라는 이름의 매개변수로 참조됩니다. 예를 들어, [예외 필터](https://docs.nestjs.com/exception-filters#arguments-host)의 `catch()`메서드는 `ArgumentsHost` 인스턴스와 함께 호출됩니다.
`ArgumentsHost`는 단순하게 핸들러의 전체적인 인자에 대한 추상화 역할을 수행합니다. HTTP 서버 애플리케이션(`@nestjs/platform-express`를 사용할 때)을 예를 들면 `host`객체가 Express의 `[request, response, next]`배열을 캡슐화 합니다. 여기서 `request`는 요청 객체를, `response`는 응답 객체를, `next`는 애플리케이션의 요청-응답 사이클을 제어하는 함수입니다. 반면에 [GraphQL](/graphql/quick-start) 애플리케이션에서의 `host`객체는 `[root, args, context, info]` 배열을 포함합니다.
#### 현재 애플리케이션 컨텍스트
여러 애플리케이션 컨텍스트를 아울러 동작하는 일반적인 [가드](/guards), [필터](/exception-filters), [인터셉터](/interceptors)를 만들기 위해서는 현재 메서드가 동작하고 있는 애플리케이션 타입을 결정지어야 하며, 이는 `ArgumentsHost`의 `getType()`메서드를 통해 가능합니다:
```typescript
if (host.getType() === "http") {
// do something that is only important in the context of regular HTTP requests (REST)
} else if (host.getType() === "rpc") {
// do something that is only important in the context of Microservice requests
} else if (host.getType<GqlContextType>() === "graphql") {
// do something that is only important in the context of GraphQL requests
}
```
> info **힌트** `GqlContextType`은 `@nestjs/graphql`패키지에서 import합니다.
이처럼, 사용 가능한 애플리케이션 타입을 활용하여 보다 범용적인 컴포넌트를 작성할 수 있습니다.
#### 호스트 핸들러 매개변수
핸들러에 전달 된 인자를 찾기 위해 host 객체의 `getArgs()`메서드를 사용할 수 있습니다.
```typescript
const [req, res, next] = host.getArgs();
```
`getArgByIndex()`메서드를 사용하여 특정 인자만 찾을 수 있습니다:
```typescript
const request = host.getArgByIndex(0);
const response = host.getArgByIndex(1);
```
이 예제들에서 요청 객체 및 응답 객체를 인덱스를 통해 찾았는데, 일반적으로 이는 어플리케이션을 특정한 하나의 실행 컨텍스트에 국한시키는 것이므로 권장되지 않습니다. 대신에, `host`객체에는 적절한 어플리케이션 컨텍스트로 전환할 수 있는 유틸리티 메서드가 있으므로 이를 사용하여 더욱 안정되고 재사용가능한 코드를 작성할 수 있습니다. 아래는 컨텍스트를 전환하는 유틸리티 메서드들입니다.
```typescript
/**
* Switch context to RPC.
*/
switchToRpc(): RpcArgumentsHost;
/**
* Switch context to HTTP.
*/
switchToHttp(): HttpArgumentsHost;
/**
* Switch context to WebSockets.
*/
switchToWs(): WsArgumentsHost;
```
직전의 예제를 `switchToHttp()`메서드를 사용하여 다시 작성해 봅시다. `host.switchToHttp()`는 HTTP 애플리케이션 컨텍스트에 걸맞는 `HttpArgugentsHost`객체를 반환합니다. `HttpArgugentsHost`객체는 우리가 원하는 객체를 받아올 수 있도록 두 가지 유용한 메서드를 제공합니다. 이 경우에는 Express 본연의 타입을 가진 객체를 반환받을 수 있도록 Express의 타입을 type assertion 해줍니다:
```typescript
const ctx = host.switchToHttp();
const request = ctx.getRequest<Request>();
const response = ctx.getResponse<Response>();
```
`WsArgumentsHost`와 `RpcArgumentsHost`에도 각각 웹소켓 컨텍스트와 마이크로서비스 컨텍스트에서 적당한 객체를 반환하는 메서드들이 있습니다. 아래는 `WsArgMentsHost`의 메서드들입니다.
```typescript
export interface WsArgumentsHost {
/**
* Returns the data object.
*/
getData<T>(): T;
/**
* Returns the client object.
*/
getClient<T>(): T;
}
```
이어서 `RpcArgumentsHost`의 메서드들입니다:
```typescript
export interface RpcArgumentsHost {
/**
* Returns the data object.
*/
getData<T>(): T;
/**
* Returns the context object.
*/
getContext<T>(): T;
}
```
#### ExecutionContext 클래스
`ExecutionContext`는 `ArgumentsHost`를 상속 받으며, 현재 실행 프로세스에 대한 추가적인 세부사항을 제공합니다. `ArgumentsHost`와 같이, Nest는 우리가 원하는 곳에 `ExecutionContext` 인스턴스를 제공하며, [가드](https://docs.nestjs.com/guards#execution-context)의 `canActive()`메서드나 [인터셉터](https://docs.nestjs.com/interceptors#execution-context)의 `intercept()`메서드가 그 예시입니다. 인스턴스는 아래 메서드들을 제공합니다:
```typescript
export interface ExecutionContext extends ArgumentsHost {
/**
* Returns the type of the controller class which the current handler belongs to.
*/
getClass<T>(): Type<T>;
/**
* Returns a reference to the handler (method) that will be invoked next in the
* request pipeline.
*/
getHandler(): Function;
}
```
`getHandler()`메서드는 실행 될 핸들러의 참조를 반환합니다. `getClass()`메서드는 그 핸들러가 속한 `Controller`클래스의 타입을 반환합니다. HTTP 컨텍스트에서의 예시로, 현재 처리되는 요청이 `POST`요청이고 `CatsController`의 `create()`메서드가 실행된다면 `getHandler()`는 `create()`메서드의 참조를 반환하고 `getClass()`는 `CatsController`의 인스턴스가 아닌 **타입**을 반환합니다.
```typescript
const methodKey = ctx.getHandler().name; // "create"
const className = ctx.getClass().name; // "CatsController"
```
현재 클래스와 핸들러 메서드 둘의 참조 모두에 접근하는 기능은 굉장한 유연성을 제공합니다. 가장 중요한 건, 연관된 가드나 인터셉터에서 `@SetMetadata()`데코레이터를 통해 지정한 메타데이터에 접근할 수 있는 기회가 된다는 점입니다. 이 사례에 대해서는 아래에서 다루어 보겠습니다.
<app-banner-enterprise></app-banner-enterprise>
#### Reflection과 메타데이터
Nest는 **사용자 정의 메타데이터** 붙일 수 있는 기능을 제공하며 이는 라우트 핸들러에서 `@SetMetadata()`데코레이터를 통해 가능합니다. 이후 클래스 내에서 이 메타데이터에 접근하여 특정 결정을 내릴 수 있습니다.
```typescript
@@filename(cats.controller)
@Post()
@SetMetadata('roles', ['admin'])
async create(@Body() createCatDto: CreateCatDto) {
this.catsService.create(createCatDto);
}
@@switch
@Post()
@SetMetadata('roles', ['admin'])
@Bind(Body())
async create(createCatDto) {
this.catsService.create(createCatDto);
}
```
> info **힌트** `@SetMetadata()` 데코레이터는 `@nestjs/common` 패키지에서 import합니다.
위의 예제에서는 `roles`라는 메타데이터를 `create()`메서드에 붙였습니다(`roles`는 메타데이터 키이며 `['admin']`은 그 값입니다). 라우트에서 `@SetMetadata()`데코레이터를 직접 쓰는 것은 그다지 좋은 방법은 아닙니다. 대신에 아래와 같이 사용자 정의 데코레이터를 작성합니다:
```typescript
@@filename(roles.decorator)
import { SetMetadata } from '@nestjs/common';
export const Roles = (...roles: string[]) => SetMetadata('roles', roles);
@@switch
import { SetMetadata } from '@nestjs/common';
export const Roles = (...roles) => SetMetadata('roles', roles);
```
이러한 접근 방식이 훨씬 깔끔하고 가독성 있으며, 타입을 더욱 엄격하게 관리할 수 있습니다. 이제 `@Roles()`데코레이터를 `create()`메서드에 사용합니다.
```typescript
@@filename(cats.controller)
@Post()
@Roles('admin')
async create(@Body() createCatDto: CreateCatDto) {
this.catsService.create(createCatDto);
}
@@switch
@Post()
@Roles('admin')
@Bind(Body())
async create(createCatDto) {
this.catsService.create(createCatDto);
}
```
라우트에서 role이라는 사용자 정의 메타데이터에 접근하기 위해서는 `Reflector` 헬퍼 클래스를 사용하면 됩니다. 이 클래스는 별도의 작업 없이 그저 `@nestjs/core`에서 가져다 사용하기만 하면 됩니다. `Reflector` 일반적인 방법으로 클래스에 주입시킬 수 있습니다:
```typescript
@@filename(roles.guard)
@Injectable()
export class RolesGuard {
constructor(private reflector: Reflector) {}
}
@@switch
@Injectable()
@Dependencies(Reflector)
export class CatsService {
constructor(reflector) {
this.reflector = reflector;
}
}
```
> info **힌트** `Reflector` 클래스는 `@nestjs/core` 패키지에서 import합니다.
> Now, to read the handler metadata, use the `get()` method.
```typescript
const roles = this.reflector.get<string[]>("roles", context.getHandler());
```
메타데이터의 **키**와 메타데이터를 찾을 **컨텍스트** (데코레이터가 붙는 대상) 두 가지를 `Reflector#get` 메서드에 인자로 넘김으로써 쉽게 메타데이터에 접근할 수 있습니다. 이 예제에서는 위에서 작성한 `roles.decorator.ts`파일에서 `SetMetadata()`를 통해 만들었던 `'roles'`라는 **키**가 있습니다. 컨텍스트는 `context.getHandler()`를 호출하면 얻을 수 있고, 이 둘을 넘긴 결과로 현재 처리되는 라우트 핸들러의 메타데이터를 추출할 수 있습니다. `getHandler()`는 라우트 핸들러 함수의 **참조**를 반환한다는 점을 기억해야 합니다.
또한, 컨트롤러 레벨에 메타데이터를 적용하여 해당 컨트롤러의 모든 라우트들에 메타데이터를 적용시킬 수 있습니다.
```typescript
@@filename(cats.controller)
@Roles('admin')
@Controller('cats')
export class CatsController {}
@@switch
@Roles('admin')
@Controller('cats')
export class CatsController {}
```
이 경우에는, `context.getHandler()` 대신에 `context.getClass()`를 두 번째 인자로 넣어야 하며, 이는 메타데이터를 추출하기 위한 컨텍스트로 해당 컨트롤러 클래스를 제공하기 위함입니다.
```typescript
@@filename(roles.guard)
const roles = this.reflector.get<string[]>('roles', context.getClass());
@@switch
const roles = this.reflector.get('roles', context.getClass());
```
하나의 메타데이터를 다양한 레벨에서 동시에 지정한다면, 다수의 컨텍스트로부터 메타데이터를 추출하고 합쳐야 할 것입니다. `Reflector` 클래스는 이를 위해 두 가지의 유틸리티 메서드를 제공합니다. 이 메서드들은 컨트롤러와 메서드 **두 곳 모두**에서 메타데이터를 추출하고, 각기 다른 방법으로 조합합니다.
`'roles'`메타데이터를 두 가지 레벨에서 동시에 공급한다고 가정해 봅시다.
```typescript
@@filename(cats.controller)
@Roles('user')
@Controller('cats')
export class CatsController {
@Post()
@Roles('admin')
async create(@Body() createCatDto: CreateCatDto) {
this.catsService.create(createCatDto);
}
}
@@switch
@Roles('user')
@Controller('cats')
export class CatsController {}
@Post()
@Roles('admin')
@Bind(Body())
async create(createCatDto) {
this.catsService.create(createCatDto);
}
}
```
위 코드의 의도가 `'user'` role을 기본으로 취급하되 몇몇 메서드에서만 role을 덮어씌우고자 하는 것이라면, `getAllAndOverride()` 메서드를 사용하면 됩니다.
```typescript
const roles = this.reflector.getAllAndOverride<string[]>("roles", [
context.getHandler(),
context.getClass(),
]);
```
`created()` 메서드의 컨텍스트 속에서 동작하는 가드에서 위와 같이 코드를 작성하면 `roles`의 값은 `['admin']`가 됩니다.
두 메타데이터를 병합하려면 `getAllAndMerge()` 메서드를 사용합니다. 이 메서드는 두 배열을 하나로 병합합니다.
```typescript
const roles = this.reflector.getAllAndMerge<string[]>("roles", [
context.getHandler(),
context.getClass(),
]);
```
위와 같이 작성하면 `roles`의 값은 `['user', 'admin']`가 됩니다.
이 두 가지 메서드를 사용할 때에는 첫 번째 인자로 메타데이터 키를, 두 번재 인자로는 메타데이터 대상 컨텍스트(`getHandler()`나 `getClass()` 메서드를 호출한 결과)가 담긴 배열을 건네야 합니다.
================================================
FILE: content/fundamentals/lazy-loading-modules.md
================================================
### Lazy-loading modules
By default, modules are eagerly loaded, which means that as soon as the application loads, so do all the modules, whether or not they are immediately necessary. While this is fine for most applications, it may become a bottleneck for apps/workers running in the **serverless environment**, where the startup latency ("cold start") is crucial.
Lazy loading can help decrease bootstrap time by loading only modules required by the specific serverless function invocation. In ad
gitextract__5bt60q5/
├── .gitignore
├── README.md
└── content/
├── application-context.md
├── cli/
│ ├── libraries.md
│ ├── overview.md
│ ├── scripts.md
│ ├── usages.md
│ └── workspaces.md
├── components.md
├── controllers.md
├── custom-decorators.md
├── discover/
│ ├── who-uses.json
│ └── who-uses.md
├── enterprise.md
├── exception-filters.md
├── faq/
│ ├── errors.md
│ ├── global-prefix.md
│ ├── http-adapter.md
│ ├── hybrid-application.md
│ ├── multiple-servers.md
│ ├── request-lifecycle.md
│ └── serverless.md
├── first-steps.md
├── fundamentals/
│ ├── async-components.md
│ ├── circular-dependency.md
│ ├── dependency-injection.md
│ ├── dynamic-modules.md
│ ├── execution-context.md
│ ├── lazy-loading-modules.md
│ ├── lifecycle-events.md
│ ├── module-reference.md
│ ├── platform-agnosticism.md
│ ├── provider-scopes.md
│ └── unit-testing.md
├── graphql/
│ ├── cli-plugin.md
│ ├── complexity.md
│ ├── directives.md
│ ├── extensions.md
│ ├── federation.md
│ ├── field-middleware.md
│ ├── guards-interceptors.md
│ ├── interfaces.md
│ ├── mapped-types.md
│ ├── mutations.md
│ ├── plugins.md
│ ├── quick-start.md
│ ├── resolvers-map.md
│ ├── scalars.md
│ ├── schema-generator.md
│ ├── subscriptions.md
│ └── unions-and-enums.md
├── guards.md
├── interceptors.md
├── introduction.md
├── microservices/
│ ├── basics.md
│ ├── custom-transport.md
│ ├── exception-filters.md
│ ├── grpc.md
│ ├── guards.md
│ ├── interceptors.md
│ ├── kafka.md
│ ├── mqtt.md
│ ├── nats.md
│ ├── pipes.md
│ ├── rabbitmq.md
│ └── redis.md
├── middlewares.md
├── migration.md
├── modules.md
├── openapi/
│ ├── cli-plugin.md
│ ├── decorators.md
│ ├── introduction.md
│ ├── mapped-types.md
│ ├── migration-guide.md
│ ├── operations.md
│ ├── other-features.md
│ ├── security.md
│ └── types-and-parameters.md
├── pipes.md
├── recipes/
│ ├── cqrs.md
│ ├── crud-generator.md
│ ├── documentation.md
│ ├── hot-reload.md
│ ├── mikroorm.md
│ ├── mongodb.md
│ ├── nest-commander.md
│ ├── prisma.md
│ ├── router-module.md
│ ├── serve-static.md
│ ├── sql-sequelize.md
│ ├── sql-typeorm.md
│ └── terminus.md
├── security/
│ ├── authentication.md
│ ├── authorization.md
│ ├── cors.md
│ ├── csrf.md
│ ├── encryption-hashing.md
│ ├── helmet.md
│ └── rate-limiting.md
├── support.md
├── techniques/
│ ├── caching.md
│ ├── compression.md
│ ├── configuration.md
│ ├── cookies.md
│ ├── events.md
│ ├── file-upload.md
│ ├── http-module.md
│ ├── logger.md
│ ├── mongo.md
│ ├── mvc.md
│ ├── performance.md
│ ├── queues.md
│ ├── serialization.md
│ ├── server-sent-events.md
│ ├── sessions.md
│ ├── sql.md
│ ├── streaming-files.md
│ ├── task-scheduling.md
│ ├── validation.md
│ └── versioning.md
└── websockets/
├── adapter.md
├── exception-filters.md
├── gateways.md
├── guards.md
├── interceptors.md
└── pipes.md
Condensed preview — 126 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,076K chars).
[
{
"path": ".gitignore",
"chars": 6,
"preview": ".idea\n"
},
{
"path": "README.md",
"chars": 1170,
"preview": "# NestJS 한국어 메뉴얼\n\n## NestJS 프레임워크\n\nNestJS는 Typescript 에서 사용할 수 있는 가장 모던하고 세련된 프레임워크이며, 유연하고 세련된 기능을 제공합니다. NestJS는 Types"
},
{
"path": "content/application-context.md",
"chars": 3106,
"preview": "### Standalone applications\n\nThere are several ways of mounting a Nest application. You can create a web app, a microser"
},
{
"path": "content/cli/libraries.md",
"chars": 6906,
"preview": "### Libraries\n\n많은 애플리케이션들은 동일한 일반적인 문제들을 해결하거나, 몇몇 다른 컨텍스트에서 모듈러 컴포넌트들을 재사용할 필요가 있습니다. Nest는 이러한 문제를 해결하는 몇 가지 방법이 있지만, "
},
{
"path": "content/cli/overview.md",
"chars": 5848,
"preview": "### 시작하기\n\n[Nest CLI](https://github.com/nestjs/nest-cli) 는 Nest application 초기화, 개발 및 유지보수 하는데 도움이 되는 명령줄-인터페이스 도구입니다. 프"
},
{
"path": "content/cli/scripts.md",
"chars": 6281,
"preview": "### Nest CLI and scripts\n\nThis section provides additional background on how the `nest` command interacts with compilers"
},
{
"path": "content/cli/usages.md",
"chars": 10826,
"preview": "### CLI command reference\n\n#### nest new\n\nCreates a new (standard mode) Nest project.\n\n```bash\n$ nest new <name> [option"
},
{
"path": "content/cli/workspaces.md",
"chars": 19498,
"preview": "### Workspaces\n\nNest has two modes for organizing code:\n\n- **standard mode**: useful for building individual project-foc"
},
{
"path": "content/components.md",
"chars": 8485,
"preview": "### Providers\n\n프로바이더는 Nest의 기본 개념입니다. 기본 Nest 클래스의 대부분은 서비스, 리포지토리, 팩토리, 헬퍼 등 프로바이더로 취급될 수 있습니다. 프로바이더의 주요 아이디어는 종속성으로 *"
},
{
"path": "content/controllers.md",
"chars": 23728,
"preview": "### Controllers\n\n컨트롤러는 들어오는 **요청**을 적절히 핸들링하고 **응답**을 클라이언트로 리턴해주는 책임을 지니고 있습니다.\n\n<figure><img src=\"/assets/Controllers_"
},
{
"path": "content/custom-decorators.md",
"chars": 6150,
"preview": "### 사용자 정의 라우트 데코레이터\n\nNest는 **데코레이터**라는 언어 기능을 활용하여 구축됩니다. 데코레이터는 많은 프로그래밍 언어들에서는 잘 알려진 개념이지만, 자바스크립트 세계에서는 아직까지는 상대적으로 "
},
{
"path": "content/discover/who-uses.json",
"chars": 6577,
"preview": "{\n \"Header\": [\n {\n \"logo\": \"/assets/logo/roche-logo.png\",\n \"url\": \"https://roche.com\",\n \"width\": \"90p"
},
{
"path": "content/discover/who-uses.md",
"chars": 386,
"preview": "### Who is using Nest?\n\nWe are proudly helping various companies building their products at scale.\nIf you are using Nest"
},
{
"path": "content/enterprise.md",
"chars": 2300,
"preview": "### Official NestJS Consulting\n\nOur goal is to ensure that your developers are successful and productive with NestJS as "
},
{
"path": "content/exception-filters.md",
"chars": 16124,
"preview": "### Exception filters\n\nNest comes with a built-in **exceptions layer** which is responsible for processing all unhandled"
},
{
"path": "content/faq/errors.md",
"chars": 4314,
"preview": "### Common errors\n\nDuring your development with NestJS, you may encounter various errors as you learn the framework.\n\n##"
},
{
"path": "content/faq/global-prefix.md",
"chars": 495,
"preview": "### Global prefix\n\nHTTP 어플리케이션에 등록된 **모든 경로에** 접두사(prefix)를 붙이기 위해서는, `INestApplication` 인스턴스의 `setGlobalPrefix()` 메서드를 "
},
{
"path": "content/faq/http-adapter.md",
"chars": 1985,
"preview": "### HTTP adapter\n\nOccasionally, you may want to access the underlying HTTP server, either within the Nest application co"
},
{
"path": "content/faq/hybrid-application.md",
"chars": 2695,
"preview": "### Hybrid application\n\nA hybrid application is one that both listens for HTTP requests, as well as makes use of connect"
},
{
"path": "content/faq/multiple-servers.md",
"chars": 1482,
"preview": "### HTTPS\n\nTo create an application that uses the HTTPS protocol, set the `httpsOptions` property in the options object "
},
{
"path": "content/faq/request-lifecycle.md",
"chars": 5326,
"preview": "### Request lifecycle\n\nNest applications handle requests and produce responses in a sequence we refer to as the **reques"
},
{
"path": "content/faq/serverless.md",
"chars": 16224,
"preview": "### Serverless\n\nServerless computing is a cloud computing execution model in which the cloud provider allocates machine "
},
{
"path": "content/first-steps.md",
"chars": 5508,
"preview": "### 시작하기\n\n이 문서에서는 Nest의 **핵심 원리** 에 대해 알아봅니다. Nest 애플리케이션의 필수 구성 요소를 숙지하려면,\n기초적인 수준에서 많은 분야를 다루며 기본적인 CRUD 애플리케이션을 구축해 봐"
},
{
"path": "content/fundamentals/async-components.md",
"chars": 1162,
"preview": "### Asynchronous providers\n\nAt times, the application start should be delayed until one or more **asynchronous tasks** a"
},
{
"path": "content/fundamentals/circular-dependency.md",
"chars": 3303,
"preview": "### Circular dependency\n\nA circular dependency occurs when two classes depend on each other. For example, class A needs "
},
{
"path": "content/fundamentals/dependency-injection.md",
"chars": 15419,
"preview": "### Custom providers\n\nIn earlier chapters, we touched on various aspects of **Dependency Injection (DI)** and how it is "
},
{
"path": "content/fundamentals/dynamic-modules.md",
"chars": 11217,
"preview": "### 동적 모듈\n\n[모듈 챕터](/modules)에서 모듈에 대한 기본적인 내용을 다루면서 [동적 모듈](https://docs.nestjs.com/modules#dynamic-modules)에 대해 간단히 소개하"
},
{
"path": "content/fundamentals/execution-context.md",
"chars": 9064,
"preview": "### 실행 컨텍스트\n\nNest는 여러 애플리케이션 컨텍스트들(예를 들면 Nest HTTP 서버 기반과 마이크로서비스, 웹소켓 컨텍스트)을 아울러서 작동하는 애플리케이션을 쉽게 작성할 수 있도록 몇 가지 유틸리티 클"
},
{
"path": "content/fundamentals/lazy-loading-modules.md",
"chars": 6367,
"preview": "### Lazy-loading modules\n\nBy default, modules are eagerly loaded, which means that as soon as the application loads, so "
},
{
"path": "content/fundamentals/lifecycle-events.md",
"chars": 8513,
"preview": "### Lifecycle Events\n\nA Nest application, as well as every application element, has a lifecycle managed by Nest. Nest pr"
},
{
"path": "content/fundamentals/module-reference.md",
"chars": 6885,
"preview": "### Module reference\n\nNest는 `ModuleRef` 클래스를 제공하여 프로파이더의 내부 목록을 탐색하고 인젝션 토큰을 조회 키로 사용하는 모든 프로파이더에 대한 참조를 가져옵니다. `ModuleR"
},
{
"path": "content/fundamentals/platform-agnosticism.md",
"chars": 1368,
"preview": "### Platform agnosticism\n\nNest is a platform-agnostic framework. This means you can develop **reusable logical parts** t"
},
{
"path": "content/fundamentals/provider-scopes.md",
"chars": 3767,
"preview": "### 스코프 주입하기\n\n다른 개발 언어를 경험하고 오는 사람들은, 들어오는 모든 요청 간에 거의 모든 컴포넌트들이 공유된다는 사실을 예상하지 못할 수 있습니다. 이를테면 데이터베이스와의 연결 풀, 전역 상태를 가지"
},
{
"path": "content/fundamentals/unit-testing.md",
"chars": 16759,
"preview": "### Testing\n\n자동화된 테스트는 진지한 소프트웨어 개발의 필수적인 부분 이라 간주됩니다. 테스트 자동화는 개발하는 도중 각각의 테스트, 혹은 테스트 묶음을 쉽게 혹은 빠르게 반복할 수 있게 해줍니다. 이는 "
},
{
"path": "content/graphql/cli-plugin.md",
"chars": 6108,
"preview": "### CLI Plugin\n\n> warning **Warning** This chapter applies only to the code first approach.\n\nTypeScript's metadata refle"
},
{
"path": "content/graphql/complexity.md",
"chars": 3823,
"preview": "### Complexity\n\n> warning **Warning** This chapter applies only to the code first approach.\n\nQuery complexity allows you"
},
{
"path": "content/graphql/directives.md",
"chars": 3281,
"preview": "### Directives\n\nA directive can be attached to a field or fragment inclusion, and can affect execution of the query in a"
},
{
"path": "content/graphql/extensions.md",
"chars": 2457,
"preview": "### Extensions\n\n> warning **Warning** This chapter applies only to the code first approach.\n\nExtensions is an **advanced"
},
{
"path": "content/graphql/federation.md",
"chars": 12934,
"preview": "### Federation\n\n[Apollo Federation](https://www.apollographql.com/docs/apollo-server/federation/introduction/) offers a "
},
{
"path": "content/graphql/field-middleware.md",
"chars": 4662,
"preview": "### Field middleware\n\n> warning **Warning** This chapter applies only to the code first approach.\n\nField Middleware lets"
},
{
"path": "content/graphql/guards-interceptors.md",
"chars": 5616,
"preview": "### Other features\n\nIn the GraphQL world, there is a lot of debate about handling issues like **authentication**, or **s"
},
{
"path": "content/graphql/interfaces.md",
"chars": 2747,
"preview": "### Interfaces\n\nLike many type systems, GraphQL supports interfaces. An **Interface** is an abstract type that includes "
},
{
"path": "content/graphql/mapped-types.md",
"chars": 4717,
"preview": "### Mapped types\n\n> warning **Warning** This chapter applies only to the code first approach.\n\nAs you build out features"
},
{
"path": "content/graphql/mutations.md",
"chars": 3706,
"preview": "### Mutations\n\nMost discussions of GraphQL focus on data fetching, but any complete data platform needs a way to modify "
},
{
"path": "content/graphql/plugins.md",
"chars": 1851,
"preview": "### Plugins\n\nPlugins enable you to extend Apollo Server's core functionality by performing custom operations in response"
},
{
"path": "content/graphql/quick-start.md",
"chars": 12136,
"preview": "## TypeScript와 GraphQL의 강력한 기능 활용\n\n[GraphQL](https://graphql.org/) 은 API를 위한 강력한 쿼리 언어이며 기존 데이터로 쿼리를 수행할 수 있는 런타임입니다. Gr"
},
{
"path": "content/graphql/resolvers-map.md",
"chars": 28325,
"preview": "### Resolvers\n\nResolvers provide the instructions for turning a [GraphQL](https://graphql.org/) operation (a query, muta"
},
{
"path": "content/graphql/scalars.md",
"chars": 6663,
"preview": "### Scalars\n\nA GraphQL object type has a name and fields, but at some point those fields have to resolve to some concret"
},
{
"path": "content/graphql/schema-generator.md",
"chars": 1739,
"preview": "### Generating SDL\n\n> warning **Warning** This chapter applies only to the code first approach.\n\nTo manually generate a "
},
{
"path": "content/graphql/subscriptions.md",
"chars": 13015,
"preview": "### Subscriptions\n\nIn addition to fetching data using queries and modifying data using mutations, the GraphQL spec suppo"
},
{
"path": "content/graphql/unions-and-enums.md",
"chars": 6418,
"preview": "### Unions\n\nUnion types are very similar to interfaces, but they don't get to specify any common fields between the type"
},
{
"path": "content/guards.md",
"chars": 9710,
"preview": "### 가드\n\n가드는 `@Injectable()` 데코레이터가 붙는 클래스의 일종이며 `CanActivate` 인터페이스를 구현해야 합니다.\n\n<figure><img src=\"/assets/Guards_1.png\" "
},
{
"path": "content/interceptors.md",
"chars": 15529,
"preview": "### Interceptors\n\nAn interceptor is a class annotated with the `@Injectable()` decorator. Interceptors should implement "
},
{
"path": "content/introduction.md",
"chars": 2250,
"preview": "### Introduction\n\nNest(NestJS)는 효율적이고 확장 가능한 [Node.js](https://nodejs.org/) 서버 어플리케이션을 구축하기 위한 프레임워크입니다. 프로그레시브 자바스크립트를 "
},
{
"path": "content/microservices/basics.md",
"chars": 16629,
"preview": "### 개요\n\nNest는 모놀리식 아키텍쳐라 불리우는 전통적인 방식의 어플리케이션 아키텍쳐 방식 뿐만 아니라 마이크로서비스 아키텍쳐 방식의 개발을 기본적으로 지원합니다. 이 문서에 다루는 모든 것들 -- 예를 들어,"
},
{
"path": "content/microservices/custom-transport.md",
"chars": 11560,
"preview": "### Custom transporters\n\nNest provides a variety of **transporters** out-of-the-box, as well as an API allowing develope"
},
{
"path": "content/microservices/exception-filters.md",
"chars": 3333,
"preview": "### Exception filters\n\nThe only difference between the HTTP [exception filter](/exception-filters) layer and the corresp"
},
{
"path": "content/microservices/grpc.md",
"chars": 21395,
"preview": "### gRPC\n\n[gRPC](https://github.com/grpc/grpc-node) is a modern, open source, high performance RPC framework that can ru"
},
{
"path": "content/microservices/guards.md",
"chars": 835,
"preview": "### Guards\n\nThere is no fundamental difference between microservices guards and [regular HTTP application guards](/guard"
},
{
"path": "content/microservices/interceptors.md",
"chars": 707,
"preview": "### Interceptors\n\nThere is no difference between [regular interceptors](/interceptors) and microservices interceptors. T"
},
{
"path": "content/microservices/kafka.md",
"chars": 14561,
"preview": "### Kafka\n\n[Kafka](https://kafka.apache.org/) is an open source, distributed streaming platform which has three key capa"
},
{
"path": "content/microservices/mqtt.md",
"chars": 5885,
"preview": "### MQTT\n\n[MQTT](https://mqtt.org/) (Message Queuing Telemetry Transport) is an open source, lightweight messaging proto"
},
{
"path": "content/microservices/nats.md",
"chars": 7249,
"preview": "### NATS\n\n[NATS](https://nats.io) is a simple, secure and high performance open source messaging system for cloud native"
},
{
"path": "content/microservices/pipes.md",
"chars": 852,
"preview": "### Pipes\n\nThere is no fundamental difference between [regular pipes](/pipes) and microservices pipes. The only differen"
},
{
"path": "content/microservices/rabbitmq.md",
"chars": 6501,
"preview": "### RabbitMQ\n\n[RabbitMQ](https://www.rabbitmq.com/)는 다양한 메시징 프로토콜을 지원하는 가벼운 오픈소스 메시지 브로커이며, 대규모 또는 고가용성에 대한 요구사항을 충족시키기 "
},
{
"path": "content/microservices/redis.md",
"chars": 4039,
"preview": "### Redis\n\nThe [Redis](https://redis.io/) transporter implements the publish/subscribe messaging paradigm and leverages "
},
{
"path": "content/middlewares.md",
"chars": 9449,
"preview": "### Middleware\n\n미들웨어는 라우트 핸들러보다 **먼저** 호출되는 함수입니다. 미들웨어 함수는 [request](https://expressjs.com/en/4x/api.html#req) 및 [respo"
},
{
"path": "content/migration.md",
"chars": 4222,
"preview": "### Migration guide\n\nThis article provides a set of guidelines for migrating from Nest version 7 to version 8.\nTo learn "
},
{
"path": "content/modules.md",
"chars": 11196,
"preview": "### Modules\n\nA module is a class annotated with a `@Module()` decorator. The `@Module()` decorator provides metadata tha"
},
{
"path": "content/openapi/cli-plugin.md",
"chars": 8889,
"preview": "### CLI Plugin\n\nTypeScript's metadata reflection system has several limitations which make it impossible to, for instanc"
},
{
"path": "content/openapi/decorators.md",
"chars": 1222,
"preview": "### Decorators\n\n모든 OpenAPI 의 decorator 들은 다른 주요 decorator 들과 구별하기 위해, `Api` 라는 접두어를 앞에 붙입니다. 하단의 항목은 사용할 수 있는 전체 decorat"
},
{
"path": "content/openapi/introduction.md",
"chars": 6683,
"preview": "### Introduction\n\nThe [OpenAPI](https://swagger.io/specification/) specification is a language-agnostic definition forma"
},
{
"path": "content/openapi/mapped-types.md",
"chars": 3808,
"preview": "### Mapped types\n\nAs you build out features like **CRUD** (Create/Read/Update/Delete) it's often useful to construct var"
},
{
"path": "content/openapi/migration-guide.md",
"chars": 1142,
"preview": "### 마이그레이션 가이드\n\n`@nestjs/swagger@3.*` 를 사용하고 있다면, 버전 4.0 에서는 하단의 중요한 변화들이 있다는 점을 유념해야 합니다.\n\n#### 중요한 변화들\n\n다음의 decorator "
},
{
"path": "content/openapi/operations.md",
"chars": 8201,
"preview": "### Operations\n\nIn OpenAPI terms, paths are endpoints (resources), such as `/users` or `/reports/summary`, that your API"
},
{
"path": "content/openapi/other-features.md",
"chars": 2769,
"preview": "### Other features\n\nThis page lists all the other available features that you may find useful.\n\n#### Global prefix\n\nTo i"
},
{
"path": "content/openapi/security.md",
"chars": 1595,
"preview": "### 보안\n\n특정 작업에 사용할 보안 메커니즘을 정의하려면 `@ApiSecurity()` 데코레이터를 사용하십시오.\n\n```typescript\n@ApiSecurity('basic')\n@Controller('cats"
},
{
"path": "content/openapi/types-and-parameters.md",
"chars": 8390,
"preview": "### Types and parameters\n\nThe `SwaggerModule` searches for all `@Body()`, `@Query()`, and `@Param()` decorators in route"
},
{
"path": "content/pipes.md",
"chars": 23572,
"preview": "### Pipes\n\nA pipe is a class annotated with the `@Injectable()` decorator. Pipes should implement the `PipeTransform` in"
},
{
"path": "content/recipes/cqrs.md",
"chars": 9362,
"preview": "### CQRS\n\nThe flow of simple [CRUD](https://en.wikipedia.org/wiki/Create,_read,_update_and_delete) (Create, Read, Update"
},
{
"path": "content/recipes/crud-generator.md",
"chars": 5418,
"preview": "### CRUD generator\n\nThroughout the life span of a project, when we build new features, we often need to add new resource"
},
{
"path": "content/recipes/documentation.md",
"chars": 779,
"preview": "### 문서화\n\n**Compodoc**은 Angular 애플리케이션을 위한 문서화 도구입니다. Nest와 Angular는 유사한 프로젝트 코드 구조를 공유하므로 **Compodoc**은 Nest 애플리케이션에서도 작"
},
{
"path": "content/recipes/hot-reload.md",
"chars": 6212,
"preview": "### Hot Reload\n\nThe highest impact on your application's bootstrapping process is **TypeScript compilation**. Fortunatel"
},
{
"path": "content/recipes/mikroorm.md",
"chars": 9010,
"preview": "### MikroORM\n\nThis recipe is here to help users getting started with MikroORM in Nest. MikroORM is the TypeScript ORM fo"
},
{
"path": "content/recipes/mongodb.md",
"chars": 5494,
"preview": "### MongoDB (Mongoose)\n\n> **Warning** In this article, you'll learn how to create a `DatabaseModule` based on the **Mong"
},
{
"path": "content/recipes/nest-commander.md",
"chars": 6951,
"preview": "### Nest Commander\n\nExpanding on the [standalone application](/standalone-applications) docs there's also the [nest-comm"
},
{
"path": "content/recipes/prisma.md",
"chars": 19361,
"preview": "### Prisma\n\n[Prisma](https://www.prisma.io) is an [open-source](https://github.com/prisma/prisma) ORM for Node.js and Ty"
},
{
"path": "content/recipes/router-module.md",
"chars": 2354,
"preview": "### Router module\n\n> info **Hint** This chapter is only relevant to HTTP-based applications.\n\nIn an HTTP application (fo"
},
{
"path": "content/recipes/serve-static.md",
"chars": 2018,
"preview": "### Serve Static\n\nIn order to serve static content like a Single Page Application (SPA) we can use the `ServeStaticModul"
},
{
"path": "content/recipes/sql-sequelize.md",
"chars": 4842,
"preview": "### SQL (Sequelize)\n\n##### This chapter applies only to TypeScript\n\n> **Warning** In this article, you'll learn how to c"
},
{
"path": "content/recipes/sql-typeorm.md",
"chars": 5052,
"preview": "### SQL (TypeORM)\n\n##### This chapter applies only to TypeScript\n\n> **Warning** In this article, you'll learn how to cre"
},
{
"path": "content/recipes/terminus.md",
"chars": 12202,
"preview": "### Healthchecks (Terminus)\n\nTerminus integration provides you with **readiness/liveness** health checks. Healthchecks a"
},
{
"path": "content/security/authentication.md",
"chars": 44514,
"preview": "### Authentication\n\nAuthentication is an **essential** part of most applications. There are many different approaches an"
},
{
"path": "content/security/authorization.md",
"chars": 17888,
"preview": "### Authorization\n\n**Authorization** refers to the process that determines what a user is able to do. For example, an ad"
},
{
"path": "content/security/cors.md",
"chars": 1551,
"preview": "### CORS\n\nCross-origin resource sharing (CORS)은 다른 도메인에서 리소스를 요청하는 것을 허용하는 메커니즘입니다. Nest에서는 내부적으로 Express의 [cors](https:"
},
{
"path": "content/security/csrf.md",
"chars": 1089,
"preview": "### CSRF 보호\n\nCSRF나 XSRF로 잘 알려진 Cross-site request forgery는 웹 에플리케이션이 신뢰하는 사용자로부터 **승인되지 않은**명령이 전송되게 만들도록 웹사이트를 악용하는 수법입"
},
{
"path": "content/security/encryption-hashing.md",
"chars": 2255,
"preview": "### 암호화와 해싱\n\n**암호화**는 정보를 인코딩하는 작업입니다. 이 작업은 평문이라 불리는 정보의 원래 표현을 암호문이라 불리는 또다른 형태로 변환합니다. 이상적으로는 승인된 당사자만이 암호문을 다시 평문으로 "
},
{
"path": "content/security/helmet.md",
"chars": 2327,
"preview": "### Helmet\n\n[Helmet](https://github.com/helmetjs/helmet)은 HTTP 헤더를 적절하게 설정해 줘서 우리의 앱을 잘 알려진 웹 취약점으로부터 보호하는 데 도움을 줍니다. 일반"
},
{
"path": "content/security/rate-limiting.md",
"chars": 4934,
"preview": "### 비율 제한\n\n**비율 제한**은 브루트-포스 공격으로부터 애플리케이션을 보호하는 일반적인 방법입니다. 이를 위해 `@nestjs/throttler` 패키지를 설치해야 합니다.\n\n```bash\n$ npm i -"
},
{
"path": "content/support.md",
"chars": 1259,
"preview": "### Support\n\nNest is an MIT-licensed open source project with its ongoing development made possible thanks to the suppor"
},
{
"path": "content/techniques/caching.md",
"chars": 7947,
"preview": "### 캐싱\n\n캐싱은 앱의 성능을 향상시킬 수 있는 훌륭하면서도 간단한 **테크닉** 입니다. 캐싱은 고성능 데이터 액세스를 제공하는 임시 데이터 저장소 역할을 합니다. \n\n#### 설치\n\n먼저 캐싱을 사용하는 데"
},
{
"path": "content/techniques/compression.md",
"chars": 1869,
"preview": "### Compression\n\nCompression can greatly decrease the size of the response body, thereby increasing the speed of a web a"
},
{
"path": "content/techniques/configuration.md",
"chars": 23876,
"preview": "### Configuration\n\nApplications often run in different **environments**. Depending on the environment, different configu"
},
{
"path": "content/techniques/cookies.md",
"chars": 5054,
"preview": "### Cookies\n\nAn **HTTP cookie** is a small piece of data stored by the user's browser. Cookies were designed to be a rel"
},
{
"path": "content/techniques/events.md",
"chars": 4936,
"preview": "### Events\n\n[Event Emitter](https://www.npmjs.com/package/@nestjs/event-emitter) package (`@nestjs/event-emitter`) provi"
},
{
"path": "content/techniques/file-upload.md",
"chars": 6396,
"preview": "### 파일 업로드\n\n파일 업로드를 처리하기 위해, 네스트는 익스프레스의 미들웨어인 [multer](https://github.com/expressjs/multer) 에 기반한 빌트인 모듈을 제공합니다. Multer"
},
{
"path": "content/techniques/http-module.md",
"chars": 4221,
"preview": "### HTTP module\n\n[Axios](https://github.com/axios/axios) is richly featured HTTP client package that is widely used. Nes"
},
{
"path": "content/techniques/logger.md",
"chars": 13136,
"preview": "### Logger\n\nNest comes with a built-in text-based logger which is used during application bootstrapping and several othe"
},
{
"path": "content/techniques/mongo.md",
"chars": 18290,
"preview": "### Mongo\n\nNest supports two methods for integrating with the [MongoDB](https://www.mongodb.com/) database. You can eith"
},
{
"path": "content/techniques/mvc.md",
"chars": 6628,
"preview": "### Model-View-Controller\n\nNest, by default, makes use of the [Express](https://github.com/expressjs/express) library un"
},
{
"path": "content/techniques/performance.md",
"chars": 3570,
"preview": "### Performance (Fastify)\n\nBy default, Nest makes use of the [Express](https://expressjs.com/) framework. As mentioned e"
},
{
"path": "content/techniques/queues.md",
"chars": 16704,
"preview": "### 큐\n\n큐는 일반적인 어플리케이션 확장 및 성능 문제를 처리하는 데 도움이 되는 강력한 디자인 패턴입니다. 큐가 해결할 수 있는 문제는 다음과 같습니다:\n\n- 프로세스 피크를 완화할 수 있습니다. 예를 들어, "
},
{
"path": "content/techniques/serialization.md",
"chars": 4583,
"preview": "### Serialization\n\nSerialization is a process that happens before objects are returned in a network response. This is an"
},
{
"path": "content/techniques/server-sent-events.md",
"chars": 2566,
"preview": "### Server-Sent Events\n\nServer-Sent Events (SSE) is a server push technology enabling a client to receive automatic upda"
},
{
"path": "content/techniques/sessions.md",
"chars": 5132,
"preview": "### Session\n\n**HTTP sessions** provide a way to store information about the user across multiple requests, which is part"
},
{
"path": "content/techniques/sql.md",
"chars": 47603,
"preview": "### Database\n\nNest is database agnostic, allowing you to easily integrate with any SQL or NoSQL database. You have a num"
},
{
"path": "content/techniques/streaming-files.md",
"chars": 2656,
"preview": "### Streaming files\n\n> info **Note** This chapter shows how you can stream files from your **HTTP application**. The exa"
},
{
"path": "content/techniques/task-scheduling.md",
"chars": 15010,
"preview": "### Task Scheduling\n\nTask scheduling allows you to schedule arbitrary code (methods/functions) to execute at a fixed dat"
},
{
"path": "content/techniques/validation.md",
"chars": 17433,
"preview": "### Validation\n\nIt is best practice to validate the correctness of any data sent into a web application. To automaticall"
},
{
"path": "content/techniques/versioning.md",
"chars": 8203,
"preview": "### Versioning\n\n> info **Hint** This chapter is only relevant to HTTP-based applications.\n\nVersioning allows you to have"
},
{
"path": "content/websockets/adapter.md",
"chars": 5696,
"preview": "### Adapters\n\nThe WebSockets module is platform-agnostic, hence, you can bring your own library (or even a native implem"
},
{
"path": "content/websockets/exception-filters.md",
"chars": 2274,
"preview": "### Exception filters\n\nThe only difference between the HTTP [exception filter](/exception-filters) layer and the corresp"
},
{
"path": "content/websockets/gateways.md",
"chars": 9225,
"preview": "### Gateways\n\nMost of the concepts discussed elsewhere in this documentation, such as dependency injection, decorators, "
},
{
"path": "content/websockets/guards.md",
"chars": 862,
"preview": "### Guards\n\nThere is no fundamental difference between web sockets guards and [regular HTTP application guards](/guards)"
},
{
"path": "content/websockets/interceptors.md",
"chars": 739,
"preview": "### Interceptors\n\nThere is no difference between [regular interceptors](/interceptors) and web sockets interceptors. The"
},
{
"path": "content/websockets/pipes.md",
"chars": 1014,
"preview": "### Pipes\n\nThere is no fundamental difference between [regular pipes](/pipes) and web sockets pipes. The only difference"
}
]
About this extraction
This page contains the full source code of the nestjskr/docs.nestjs.kr GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 126 files (949.3 KB), approximately 239.4k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.