๐คทโ๏ธ ๋ณธ๋ก ์ ์์
์ด์ ๊ธ์์ AWS Parameter Store ์์ฑํ๊ณ ๋งค๊ฐ๋ณ์, ๋ฌธ์์ด ์ํธํ ํ๋ ๋ฐฉ๋ฒ์ ๋ํด์ ์์๋ดค์ต๋๋ค.
์ด๋ฒ๊ธ์์๋ AWS-SDK๋ฅผ ์ฌ์ฉํด์ Nest.js ํ๋ก์ ํธ์ Parameter Store ์ ๊ทผํ๋ ๋ฐฉ๋ฒ์ ์์๋ณด๊ฒ ์ต๋๋ค.
[NestJS] AWS Parameter Store AWS-SDK ํ๋ก์ ํธ 2ํ
2024.09.05 - [Nest.js] - [NestJS] AWS Parameter Store ํ๋ก์ ํธ 2ํ
[NestJS] AWS Parameter Store ํ๋ก์ ํธ 2ํ
๐คทโ๏ธ ๋ณธ๋ก ์ ์์์ด์ ๊ธ์์ ํ๊ฒฝ๋ณ์๋ฅผ ์ค์ ๊ด๋ฆฌ ํ๋ ์ด์ ์ AWS Parameter Store ๊ฐ๋ ๊ณผ ์ฅ์ ์ ๋ํด์ ์์๋ดค์ต๋๋ค.์ด๋ฒ ๊ธ์์๋ ์ค๋ฌด์์ Parameter Store ํ๋ผ๋ฏธํฐ ๊ฐ๋ค์ ์์ฑํ๋ ๋ฐฉ๋ฒ
cometruedream.tistory.com
[NestJS] AWS Parameter Store AWS-SDK ํ๋ก์ ํธ 1ํ
2024.09.04 - [Nest.js] - [NestJS] AWS Parameter Store ํ๋ก์ ํธ 1ํ
[NestJS] AWS Parameter Store ํ๋ก์ ํธ 1ํ
๐คทโ๏ธ ๋ณธ๋ก ์ ์์ํ๋ก์ ํธ๋ฅผ ์งํํ๋ค ๋ณด๋ฉด ํ๊ฒฝ๋ณ์ ๊ด๋ฆฌ๊ฐ ์ด๋ ค์์ง๋๋ค.ํ๋ก์ ํธ ์ฌ์ด์ฆ๊ฐ ์ปค์ง๋ฉด ๋์ฑ๋ ํ๊ฒฝ๋ณ์ ๊ด๋ฆฌ๊ฐ ์ด๋ ค์์ง๊ธฐ ๋๋ฌธ์ ์ด๋ฒ ๋ฒ ํ์๋น์ค๊น์ง ๊ฐ๋ฐ์ ์๋ฃํ๊ณ A
cometruedream.tistory.com
๐คทโ๏ธ AWS-SDK ์ธํ ๋ฐ Parameter Store ์ ๊ทผ ๋ฐฉ๋ฒ
Nest.js ํ๋ก์ ํธ์์ ์ฝ๋๋ก Parameter Store ์ ๊ทผํ๊ธฐ ์ํด์๋ ๋จผ์ AWS-SDK๋ฅผ ์ค์นํด์ผํฉ๋๋ค.
1. AWS SDK ์ค์น
npm install --save @aws-sdk/client-ssm
2. Nest.js config ๊ตฌ์กฐ ์ธํ
config.module.ts ์์ฑ
ConfigModule๋ฅผ ์ ์ญ์์ ์ฌ์ฉํ ์ ์๋๋ก ์๋น์ค์ ๋ฑ๋กํฉ๋๋ค.
// config.module.ts
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import EnvConfig from './env.config';
@Module({
imports: [
ConfigModule.forRoot({
isGlobal: true,
envFilePath: `.env`,
load: [EnvConfig],
}),
],
})
export class AppConfigModule {}
env.config.ts ์์ฑ
import { AwsConfigService } from './aws-config.service';
export default async () => {
const awsConfigService = new AwsConfigService();
await awsConfigService.loadConfig();
return awsConfigService.getConfig();
};
export default async () => {}๋ ์ต๋ช ํจ์๋ฅผ ์ ์ธํ๊ณ ๋ค๋ฅธ ํ์ผ์์ ํจ์๋ฅผ import ์ ๋ฐ๋ก ํจ์๊ฐ ๋น๋๊ธฐ์ ์ผ๋ก ์คํ๋๋๋ก ํฉ๋๋ค.
ConfigModule์ load ์ต์ ์์ env.config.ts ํจ์๊ฐ ๋น๋๊ธฐ์ ์ผ๋ก ์ฆ์ ์คํํด์ ์ค์ ๊ฐ์ ์ธํ ํด์ฃผ๋ ๋ก์ง์ ๋๋ค.
aws-config.service.ts ์์ฑ
import { GetParametersByPathCommand, SSMClient } from '@aws-sdk/client-ssm';
import { Logger } from '@nestjs/common';
export class AwsConfigService {
private readonly ssmClient: SSMClient;
private config: Record<string, string> = {};
private logger = new Logger(AwsConfigService.name);
constructor() {
this.ssmClient = new SSMClient({
region: process.env.AWS_REGION,
credentials: {
accessKeyId: process.env.AWS_ENV_ACCESS_KEY,
secretAccessKey: process.env.AWS_ENV_SECRET_ACCESS_KEY,
},
});
}
// ๋ก์ปฌ ENV / AWS ๋ฐ์ดํฐ ๊ฐ์ ธ์ฌ ์ ์๋๋ก ๊ตฌ์ฑ
public async loadConfig() {
try {
const env = process.env.NODE_ENV || 'development';
const path = `/YOUR PATH/${env}/`;
const getAllParameters = async (path: string) => {
let parameters = [];
let nextToken: string | undefined;
do {
const command = new GetParametersByPathCommand({
Path: path,
Recursive: true,
WithDecryption: true,
NextToken: nextToken, // NextToken์ ์ฌ์ฉํ์ฌ ํ์ด์ง๋ค์ด์
์ฒ๋ฆฌ
});
const response = await this.ssmClient.send(command);
if (response.Parameters) {
parameters = parameters.concat(response.Parameters);
}
nextToken = response.NextToken; // ๋ค์ ํ์ด์ง๊ฐ ์์ผ๋ฉด NextToken์ด ์ค์ ๋จ
} while (nextToken);
return parameters;
};
const result = await getAllParameters(path);
if (result) {
for (const param of result) {
if (param.Name && param.Value) {
const key = param.Name.replace(path, '');
this.config[key] = param.Value.replace(/\\\\n/g, '\\n');
}
}
}
} catch (error) {
this.logger.error('AWS SSM ์ ๊ทผ ์คํจ', error);
}
}
get(key: string): string {
// ๋ก์ปฌ์์ ์คํํ ๊ฒฝ์ฐ
if (process.env.ENV_LOCAL === 'true') {
return process.env[key] || '';
}
return this.config[key] || process.env[key] || '';
}
getConfig() {
return {
redis: {
url: `redis://${this.get('REDIS_URL')}:${this.get('REDIS_PORT')}`,
},
AWS_REGION: this.get('AWS_REGION'),
AWS_S3_ACCESS_KEY: this.get('S3_ACCESS_KEY_ID'),
AWS_S3_SECRET_ACCESS_KEY: this.get('S3_SECRET_ACCESS_KEY'),
AWS_S3_BUCKET_NAME: this.get('AWS_S3_BUCKET_NAME'),
NICE_API_KEY: this.get('NICE_API_KEY'),
firebase: {
type: this.get('FIREBASE_TYPE'),
project_id: this.get('FIREBASE_PROJECT_ID'),
private_key_id: this.get('FIREBASE_PRIVATE_KEY_ID'),
private_key: this.get('FIREBASE_PRIVATE_KEY'),
client_email: this.get('FIREBASE_CLIENT_EMAIL'),
client_id: this.get('FIREBASE_CLIENT_ID'),
auth_uri: this.get('FIREBASE_AUTH_URI'),
token_uri: this.get('FIREBASE_TOKEN_URI'),
auth_provider_x509_cert_url: this.get('FIREBASE_AUTH_PROVIDER_X509_CERT_URL'),
client_x509_cert_url: this.get('FIREBASE_CLIENT_x509_CERT_URL'),
universe_domain: this.get('FIREBASE_UNIVERSE_DOMAIN'),
},
};
}
}
SSMClient ์ด๊ธฐ ์ ํ
constructor() {
this.ssmClient = new SSMClient({
region: process.env.AWS_REGION,
credentials: {
accessKeyId: process.env.AWS_ENV_ACCESS_KEY,
secretAccessKey: process.env.AWS_ENV_SECRET_ACCESS_KEY,
},
});
}
- SSMClient ์ธ์คํด์ค๋ฅผ ์ค์ ํฉ๋๋ค.
- ์๋น์ค ์์ฑ์ง์ญ region๊ณผ ๋ฐ๊ธ๋ฐ์ accessKeyId, secretAccessKey๋ฅผ ์์ฑํฉ๋๋ค.
- accessKeyId, secretAccessKey ํ๋ก์ ํธ .env ํ์ผ์ ์ถ๊ฐํฉ๋๋ค.
GetParametersByPathCommand API ํ์ฉ
const command = new GetParametersByPathCommand({
Path: path,
Recursive: true,
WithDecryption: true, //์ํธํ๋ ํ๋ผ๋ฏธํฐ์ธ ๊ฒฝ์ฐ true๋ก ์ค์
NextToken: nextToken, // NextToken์ ์ฌ์ฉํ์ฌ ํ์ด์ง๋ค์ด์
์ฒ๋ฆฌ
});
- GetParametersByPathCommand API ํ์ฉํด์ Parameter Store์ ๊ฐ๋ค์ ๋ถ๋ฌ์ต๋๋ค.
- GetParameterCommand ๋ง๊ณ GetParametersByPathCommand ์ฌ์ฉํ ์ด์ ๋ Path ๋ณ๋ก Parameter Store ๊ฐ๋ค์ ์ ๊ทผํ๊ธฐ ์ํด์์ ๋๋ค.
- IAM ๊ถํ์ ๋ฐ๋ผ์ Parameter Store ์ ๊ทผ API ์ฌ์ฉ์ด ๊ฐ๋ฅํฉ๋๋ค.
GetParametersByPath ์ค๋ฌด์์ ์ฌ์ฉ๋ฒ
const getAllParameters = async (path: string) => {
let parameters = [];
let nextToken: string | undefined;
do {
const command = new GetParametersByPathCommand({
Path: path,
Recursive: true,
WithDecryption: true,
NextToken: nextToken, // NextToken์ ์ฌ์ฉํ์ฌ ํ์ด์ง๋ค์ด์
์ฒ๋ฆฌ
});
const response = await this.ssmClient.send(command);
if (response.Parameters) {
parameters = parameters.concat(response.Parameters);
}
nextToken = response.NextToken; // ๋ค์ ํ์ด์ง๊ฐ ์์ผ๋ฉด NextToken์ด ์ค์ ๋จ
} while (nextToken);
return parameters;
};
GetParametersByPath API ์ฌ์ฉ ์ ์ ์์ฌํญ
- ๋ฐํํ ํ๊ฒฝ๋ณ์ ํญ๋ชฉ ์: ์ด API๋ ํ ๋ฒ์ ์์ฒญ์ผ๋ก ์ต๋ 10๊ฐ์ ํ๊ฒฝ๋ณ์ ํญ๋ชฉ์ ๋ฐํํฉ๋๋ค. (์ต์ 1๊ฐ, ์ต๋ 10๊ฐ)
- NextToken ํ์ฉ: ๋ง์ฝ ์์ฒญ ๊ฒฝ๋ก์ 10๊ฐ ์ด์์ ํ๊ฒฝ๋ณ์๊ฐ ์กด์ฌํ๋ ๊ฒฝ์ฐ, ๋ฐํ๋ ์๋ต์ NextToken์ด ํฌํจ๋ฉ๋๋ค. ์ด NextToken์ ์ด์ฉํด ์ถ๊ฐ ์์ฒญ์ ๋ณด๋ด๋ฉด, 10๊ฐ ์ด์์ ํ๊ฒฝ๋ณ์๋ฅผ ์์ฐจ์ ์ผ๋ก ๊ฐ์ ธ์ฌ ์ ์์ต๋๋ค.
GetParametersByPathCommand ๊ณต์๋ฌธ์
GetParametersByPath - AWS Systems Manager
If a user has access to a path, then the user can access all levels of that path. For example, if a user has permission to access path /a, then the user can also access /a/b. Even if a user has explicitly been denied access in IAM for parameter /a/b, they
docs.aws.amazon.com
๐คทโ๏ธ ๋ง์ง๋ง์ผ๋ก
ํ๊ฒฝ ๋ณ์๋ฅผ ์ค์์์ ๊ด๋ฆฌํ๋ ๊ณผ์ ๊ณผ AWS์ Parameter Store ๊ธฐ๋ฅ, AWS SDK ์ฌ์ฉ ๋ฐฉ๋ฒ์ ๋ํด ๋ค๋ค์ต๋๋ค.
.env ํ์ผ ๊ด๋ฆฌ์ ์ค์ ์ง์ค์ ํ๊ฒฝ ๋ณ์ ๊ด๋ฆฌ ์ค ์ด๋ ๊ฒ์ด ๋ ์ข์์ง๋ ์ ๋ต์ด ์์ต๋๋ค.
๊ฐ๊ฐ์ ๋ฐฉ๋ฒ์๋ ์ฅ๋จ์ ์ด ์์ผ๋ฉฐ, ํ ๋ฌธํ์ ํ๋ก์ ํธ ์ด์ ๋ฐฉ์์ ๋ง์ถฐ ์ ํํ๋ ๊ฒ์ด ์ต์ ์ ๋๋ค.
์ ๋ Parameter Store์ ์์ ์ฑ, ์ค์ ๊ด๋ฆฌ, ์๋ํ ๊ฐ๋ฅ์ฑ์ ๋ํด ๊ธ์ ์ ์ผ๋ก ํ๊ฐํ๋ฉฐ ์์ผ๋ก๋ ํ๋ก์ ํธ์ ์ ๊ทน ํ์ฉํ ๊ณํ์ ๋๋ค.
์ฌ๋ฐ๋ ์ค๋์ ๋ ๋ณ ์ด์ธ ๋ณด๊ณ ๊ฐ์ธ์!
https://cometruedream.tistory.com/247
[React] Tailwind ํ์ค, ๋์ค, ์ธ์ค ํจ๊ณผ className ์ปค์คํ
๐คทโ๏ธ Tailwind ํ์ค, ๋์ค, ์ธ์ค ํจ๊ณผํ๋ก์ ํธ ์งํ์ค ๋ฐฐ๋ ๋งํฌ์ URL ๊ธธ์ด๊ฐ ๋๋ฌด ๊ธธ์ด์ 3์ค ํจ๊ณผ ์ฒ๋ฆฌ๋ฅผ ํด์ผ ํ์ต๋๋ค. React + Tailwind CSS ์ ํ ๋ ํ๋ก์ ํธ ์ฌ์ CSS ํ์ผ & style ํ๊ทธ๋ฅผ ์ฌ์ฉํ
cometruedream.tistory.com
https://cometruedream.tistory.com/243
NestJS Lifecycle (์๋ช ์ฃผ๊ธฐ) ๊ฐ๋
๐คทโ๏ธ ๋ณธ๋ก ์ ์์ Nest JS ๊ฐ๋ ?Nest JS๋ Node JS ๊ธฐ๋ฐ์ผ๋ก ํ ์๋ฒ ์ดํ๋ฆฌ์ผ์ด์ ํ๋ ์์ํฌ ์ ๋๋ค. ์๋ฐ์คํฌ๋ฆฝํธ๋ ์๋นํ ์ค๋ซ๋์ Express ๊ธฐ๋ฐ์ผ๋ก ์๋ฒ ์ดํ๋ฆฌ์ผ์ด์ ๊ฐ๋ฐ์์ ์๋์ ์ธ ์
cometruedream.tistory.com
https://cometruedream.tistory.com/242
๋ฆฌ์กํธ Vite Proxy ํ์ฉํ CORS ์ค๋ฅ ํด๊ฒฐ
๐คทโ๏ธ ๋ณธ๋ก ์ ์์ํ๋ก ํธ์๋ ๋ฒ๋ค๋ฌ ๊ฐ๋ ๊ณผ webpack vs vite ๋น๊ต์ ๋ํด์ ๊ณต๋ถ๋ฅผ ํ๊ณ ๊ธ์ ๋ณด์๋ฉด ๋ ๋ง์ ๋์์ด ๋ฉ๋๋ค^^ํ๋ก ํธ์๋ ๊ฐ๋ฐ์ ์ํ ๋ฒ๋ค๋ฌ ๊ฐ๋ ๊ณผ webpack vs vite ๋น๊ตhttps://comet
cometruedream.tistory.com
https://cometruedream.tistory.com/241
React ํด๋๊ตฌ์กฐ FSD ๊ธฐ๋ฅ ๋ถํ ์ค๊ณ ์ํคํ ์ฒ
๐คทโ๏ธ ๋ณธ๋ก ์ ์์ํ๋ก์ ํธ๋ฅผ ์์ํ๊ธฐ์ ์์ ํด๋ ๊ตฌ์กฐ, ์ค๊ณ์ ๋ํ ์ํคํ ์ฒ๋ฅผ ๋ง๋๋ ๊ฒ์ ์๋นํ ์ด๋ ต๋ค. ์ด๋ฒ ํ๋ก์ ํธ์ React FSD ํด๋๊ตฌ์กฐ ์ํคํ ์ฒ๋ฅผ ์ค๊ณํ ์์ ์ด๋ผ์ FSD ์ํคํ
cometruedream.tistory.com
https://cometruedream.tistory.com/244
์ฝ๊ฒ ์ดํดํ๊ณ ์ฌ์ฉํ ์ ์๋ Prisma ๋ช ๋ น์ด ์ ๋ฆฌ
๐คทโ๏ธ Prisma ๋ช ๋ น์ด ๋ณธ๋ก ์ ์์ Prisma๋?Nest JS ํ๋ ์์ํฌ์ Prisma ORM์ ํ์ฉํด์ ํ๋ก์ ํธ๋ฅผ ์งํํ๋ฉด์ Prisma๋ Node JS ๊ธฐ๋ฐ์ ํ๋ ์์ํฌ/๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์ํธ์์ฉ์ด ์๋๋ฉฐ Prisma + DB ์ฐ๋์ผ
cometruedream.tistory.com
[๋์ปค ์ ๋ฌธ ์๋ฆฌ์ฆ] Dockerfile ๊ฐ๋ ๋ฐ ์ฌ์ฉ๋ฒ
์ด ๊ธ์์๋ ์ ๋ฌธ์๋ฅผ ์ํ ๋์ปค ์๋ฆฌ์ฆ๋ก ๋์ปค ์ ๋ฌธ ์๋ฆฌ์ฆ - Dockerfile ๊ฐ๋ ๋ฐ ์ฌ์ฉ๋ฒ์ ๋ํด์ ์๊ฐํฉ๋๋ค. ์๋ ํ์ธ์! ITibiza ์ ๋๋ค. ์ด์ ๊ธ์์ ๋์ปค ์ด๋ฏธ์ง, ์ปจํ ์ด๋์ ๊ฐ๋ ๊ณผ ๋์ปค
itibiza.tistory.com
'Nest.js' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[NestJS] AWS Parameter Store ํ๋ก์ ํธ 2ํ (0) | 2024.09.05 |
---|---|
[NestJS] AWS Parameter Store ํ๋ก์ ํธ 1ํ (2) | 2024.09.04 |
NestJS Lifecycle (์๋ช ์ฃผ๊ธฐ) ๊ฐ๋ (1) | 2024.05.07 |
Nest.js - ํํ ์ค ์ข ํฉ์๋์ธ API ํ์ฑ (25) | 2023.05.15 |
Nest.js Middleware logger (15) | 2022.12.05 |