Configuration
Configuration
์์ฉ ํ๋ก๊ทธ๋จ์ ๋ค๋ฅธ ํ๊ฒฝ์์ ์คํ๋๋ ๋ฐ ์ฌ์ฉ๋๊ณค ํฉ๋๋ค. ํ๊ฒฝ์ ๋ฐ๋ผ ๋ค์ํ ๊ตฌ์ฑ ๋ณ์ ์ธํธ๋ฅผ ์ฌ์ฉํด์ผ ํฉ๋๋ค. ์๋ฅผ ๋ค์ด, ๋ก์ปฌ ํ๊ฒฝ์ ํน์ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์๊ฒฉ ์ฆ๋ช
์ ์์กดํ ๊ฐ๋ฅ์ฑ์ด ๋งค์ฐ ๋์ผ๋ฉฐ ๋ก์ปฌ DB ์ธ์คํด์ค์๋ง ์ ํจํฉ๋๋ค. ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ํค-๊ฐ ์์ ๋ณด์ ํ๋.env
ํ์ผ์ ํ์ฉํ์ต๋๋ค. ์ด ๋ฐฉ๋ฒ์ ๋งค์ฐ ํธ๋ฆฌํ๋ฏ๋ก ๊ฐ ํค๋ ํน์ ๊ฐ์ ๋ํ๋
๋๋ค.
๊ทธ๋ฌ๋ ํ๋ก์ธ์ค
์ ์ญ ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ ํ
์คํธ๋ ํด๋์ค๊ฐ ์ง์ ์ฌ์ฉํ ์ ์์ผ๋ฏ๋ก ํ
์คํธ๋ฅผ ๊นจ๋ํ๊ฒ ์ ์งํ๊ธฐ๊ฐ ์ด๋ ต์ต๋๋ค. ๋ ๋ค๋ฅธ ๋ฐฉ๋ฒ์ ๋ก๋๋ ๊ตฌ์ฑ ๋ณ์๋ก ConfigService
๋ฅผ ๋
ธ์ถํ๋ ์ถ์ํ ๊ณ์ธต ์ธ ConfigModule
์ ์์ฑํ๋ ๊ฒ์
๋๋ค.
Installation
ํน์ ํ๋ซํผ์ ํ๊ฒฝ ๋ณ์๋ฅผprocess.env
์ ์ญ์ ์๋์ผ๋ก ์ฐ๊ฒฐํฉ๋๋ค. ๊ทธ๋ฌ๋ ๋ก์ปฌ ํ๊ฒฝ์์๋ ์๋์ผ๋ก ๊ด๋ฆฌํด์ผ ํฉ๋๋ค. ํ๊ฒฝ ํ์ผ์ ๊ตฌ๋ฌธ ๋ถ์ํ๊ธฐ ์ํด dotenv ํจํค์ง๋ฅผ ์ฌ์ฉํฉ๋๋ค.
$ npm i --save dotenv
$ npm i --save-dev @types/dotenv
Service
๋จผ์ ConfigService
ํด๋์ค๋ฅผ ๋ง๋ค์ด ๋ด
์๋ค.
@@filename()
import * as dotenv from 'dotenv';
import * as fs from 'fs';
export class ConfigService {
private readonly envConfig: { [key: string]: string };
constructor(filePath: string) {
this.envConfig = dotenv.parse(fs.readFileSync(filePath))
}
get(key: string): string {
return this.envConfig[key];
}
}
@@switch
import * as dotenv from 'dotenv';
import * as fs from 'fs';
export class ConfigService {
constructor(filePath) {
this.envConfig = dotenv.parse(fs.readFileSync(filePath))
}
get(key) {
return this.envConfig[key];
}
}
์ด ํด๋์ค๋.env
ํ์ผ์ ๊ฒฝ๋ก ์ธ filePath
๋ผ๋ ๋จ์ผ ์ธ์๋ฅผ ์ทจํฉ๋๋ค. get()
๋ฉ์๋๋ ํ๊ฒฝ ํ์ผ ๋ด์ ์ ์๋ ๊ฐ ์์ฑ์ ๋ณด์ ํ๋ ๊ฐ์ธ envConfig
์ค๋ธ์ ํธ์ ์ก์ธ์คํ ์ ์๋๋ก ์ ๊ณต๋ฉ๋๋ค.
๋ง์ง๋ง ๋จ๊ณ๋ ConfigModule
์ ๋ง๋๋ ๊ฒ์
๋๋ค.
@@filename()
import { Module } from '@nestjs/common';
import { ConfigService } from './config.service';
@Module({
providers: [
{
provide: ConfigService,
useValue: new ConfigService(`${process.env.NODE_ENV}.env`),
},
],
exports: [ConfigService],
})
export class ConfigModule {}
ConfigModule
์ ConfigService
๋ฅผ ๋ฑ๋กํ๊ณ ์ด๋ฅผ ๋ด ๋ณด๋
๋๋ค. ๋ํ .env
ํ์ผ์ ๊ฒฝ๋ก๋ฅผ ์ ๋ฌํ์ต๋๋ค. ์ด ๊ฒฝ๋ก๋ ์ค์ ์คํ ํ๊ฒฝ์ ๋ฐ๋ผ ๋ค๋ฆ
๋๋ค. ์ด์ ์ด๋์๋ ConfigService
๋ฅผ ์ฃผ์
ํ๊ณ ์ ๋ฌ๋ ํค๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํน์ ๊ฐ์ ๊ฐ์ ธ์ฌ ์ ์์ต๋๋ค. ์ํ .env
ํ์ผ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
DATABASE_USER = test
DATABASE_PASSWORD = test
Using the ConfigService
ConfigService
์์ ํ๊ฒฝ ๋ณ์์ ์ก์ธ์คํ๋ ค๋ฉด ๋ณ์๋ฅผ ์ฃผ์
ํด์ผํฉ๋๋ค. ๋ฐ๋ผ์ ๋จผ์ ๋ชจ๋์ ๊ฐ์ ธ์์ผํฉ๋๋ค.
@@filename(app.module)
@Module({
imports: [ConfigModule],
...
})
๊ทธ๋ฐ ๋ค์ ์ฃผ์
ํ ํฐ์ ์ฌ์ฉํ์ฌ ์ฃผ์
ํ ์ ์์ต๋๋ค. ๊ธฐ๋ณธ์ ์ผ๋ก ํ ํฐ์ ํด๋์ค ์ด๋ฆ๊ณผ ๊ฐ์ต๋๋ค (์: ConfigService
).
@@filename(app.service)
@Injectable()
export class AppService {
private isAuthEnabled: boolean;
constructor(config: ConfigService) {
// Please take note that this check is case sensitive!
this.isAuthEnabled = config.get('IS_AUTH_ENABLED') === 'true';
}
}
info ํํธ ๋ชจ๋ ๋ชจ๋์์
ConfigModule
์ ๊ฐ์ ธ ์ค๋ ๋์ConfigModule
์ ์ ์ญ ๋ชจ๋๋ก ์ ์ธํ ์๋ ์์ต๋๋ค.
Advanced configuration
๋ฐฉ๊ธ ๊ธฐ๋ณธ ConfigService
๋ฅผ ๊ตฌํํ์ต๋๋ค. ๊ทธ๋ฌ๋ ์ด ์ ๊ทผ ๋ฐฉ์์๋ ๋ช ๊ฐ์ง ๋จ์ ์ด ์์ต๋๋ค.
ํ๊ฒฝ ๋ณ์์ ๋ํ ์ด๋ฆ ๋ฐ ์ ํ ๋๋ฝ (IntelliSense ์์)
์ ๊ณต๋
.env
ํ์ผ์ ํ์ธ ๋ถ์กฑenv ํ์ผ์ ๋ถ์ธ์ ๋ฌธ์์ด (
'true'
)๋ก ์ ๊ณตํ๋ฏ๋ก ๋งค๋ฒ ๋ถ์ธ๋ก ์บ์คํธํด์ผํฉ๋๋ค.
Validation
์ ๊ณต๋ ํ๊ฒฝ ๋ณ์์ ์ ํจ์ฑ ๊ฒ์ฆ๋ถํฐ ์์ํ๊ฒ ์ต๋๋ค. ํ์ํ ํ๊ฒฝ ๋ณ์๊ฐ ์ ๊ณต๋์ง ์์๊ฑฐ๋ ์ฌ์ ์ ์๋ ์๊ตฌ ์ฌํญ์ ์ถฉ์กฑํ์ง ์์ผ๋ฉด ์ค๋ฅ๊ฐ ๋ฐ์ํ ์ ์์ต๋๋ค. ์ด๋ฅผ ์ํด npm ํจํค์ง Joi๋ฅผ ์ฌ์ฉํฉ๋๋ค. Joi๋ฅผ ์ฌ์ฉํ๋ฉด ๊ฐ์ฒด ์คํค๋ง๋ฅผ ์ ์ํ๊ณ ์ด์ ๋ํด JavaScript ๊ฐ์ฒด์ ์ ํจ์ฑ์ ๊ฒ์ฌํฉ๋๋ค.
Joi ์ค์น ๋ฐ ์ ํ (TypeScript ์ฌ์ฉ์์ ๊ฒฝ์ฐ) :
$ npm install --save @hapi/joi
$ npm install --save-dev @types/hapi__joi
ํจํค์ง๊ฐ ์ค์น๋๋ฉด ConfigService
๋ก ์ด๋ํ ์ ์์ต๋๋ค.
@@filename(config.service)
import * as dotenv from 'dotenv';
import * as Joi from '@hapi/joi';
import * as fs from 'fs';
export interface EnvConfig {
}
export class ConfigService {
private readonly envConfig: EnvConfig;
constructor(filePath: string) {
const config = dotenv.parse(fs.readFileSync(filePath));
this.envConfig = this.validateInput(config);
}
/**
* Ensures all needed variables are set, and returns the validated JavaScript object
* including the applied default values.
*/
private validateInput(envConfig: EnvConfig): EnvConfig {
const envVarsSchema: Joi.ObjectSchema = Joi.object({
NODE_ENV: Joi.string()
.valid(['development', 'production', 'test', 'provision'])
.default('development'),
PORT: Joi.number().default(3000),
API_AUTH_ENABLED: Joi.boolean().required(),
});
const { error, value: validatedEnvConfig } = Joi.validate(
envConfig,
envVarsSchema,
);
if (error) {
throw new Error(`Config validation error: ${error.message}`);
}
return validatedEnvConfig;
}
}
NODE_ENV
์ PORT
์ ๊ธฐ๋ณธ๊ฐ์ ์ค์ ํ์ผ๋ฏ๋ก ํ๊ฒฝ ํ์ผ์ ์ด๋ฌํ ๋ณ์๋ฅผ ์ ๊ณตํ์ง ์์ผ๋ฉด ์ ํจ์ฑ ๊ฒ์ฌ๊ฐ ์คํจํ์ง ์์ต๋๋ค. ๊ทธ๋ผ์๋ ๋ถ๊ตฌํ๊ณ ๋ช
์์ ์ผ๋ก API_AUTH_ENABLED
๋ฅผ ์ ๊ณตํด์ผ ํฉ๋๋ค. ์คํค๋ง์ ์ผ๋ถ๊ฐ ์๋ .env ํ์ผ์ ๋ณ์๊ฐ ์๋ ๊ฒฝ์ฐ ์ ํจ์ฑ ๊ฒ์ฌ์์๋ ์ค๋ฅ๊ฐ ๋ฐ์ํฉ๋๋ค. ๋ํ Joi๋ env ๋ฌธ์์ด์ ์ฌ๋ฐ๋ฅธ ์ ํ์ผ๋ก ๋ณํํ๋ ค๊ณ ์๋ํฉ๋๋ค.
Class properties
๊ฐ ๊ตฌ์ฑ ์์ฑ๋ง๋ค getter ํจ์๋ฅผ ์ถ๊ฐํด์ผํฉ๋๋ค.
@@filename(config.service)
get isApiAuthEnabled(): boolean {
return Boolean(this.envConfig.API_AUTH_ENABLED);
}
Usage example
์ด์ ํด๋์ค ์์ฑ์ ์ง์ ์ก์ธ์ค ํ ์ ์์ต๋๋ค.
@@filename(app.service)
@Injectable()
export class AppService {
constructor(config: ConfigService) {
if (config.isApiAuthEnabled) {
// Authorization is enabled
}
}
}
Last updated
Was this helpful?