보안
환경 분리
배포 유연성
협업과 유지보수
| 환경 | 설명 | 예시 |
|---|---|---|
| Local | 개발자 개인 PC 환경 | localhost |
| Development | 개발 서버 환경 | dev.example.com |
| Staging | 운영 배포 전 검증 환경 | staging.example.com |
| Production | 실제 사용자 서비스 환경 | www.example.com |
로컬 환경 API 주소:
http://localhost:3000
운영 환경 API 주소:
https://api.example.com
.env 파일은 환경변수를 파일 형태로 관리하는 방식입니다.NODE_ENV=development
PORT=3000
DATABASE_URL=postgresql://user:password@localhost:5432/app_db
JWT_SECRET=my-local-secret
JWT_ACCESS_EXPIRES_IN=30m
JWT_REFRESH_EXPIRES_IN=14d
AWS_REGION=ap-northeast-2
AWS_S3_BUCKET=my-dev-bucket
CORS_ORIGIN=http://localhost:5173
.env는 편리하지만 민감정보가 들어갈 수 있으므로 Git에 올리면 안 됩니다..env
.env.local
.env.development
.env.production
.env.example은 실제 비밀값 없이 필요한 환경변수 목록만 공유하는 파일입니다.NODE_ENV=
PORT=
DATABASE_URL=
JWT_SECRET=
JWT_ACCESS_EXPIRES_IN=
JWT_REFRESH_EXPIRES_IN=
AWS_REGION=
AWS_S3_BUCKET=
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
CORS_ORIGIN=
# 서버 실행 포트
PORT=3000
# PostgreSQL 연결 문자열
DATABASE_URL=
# 프론트엔드 허용 Origin
CORS_ORIGIN=
VITE_로 시작해야 합니다.VITE_API_BASE_URL=https://api.example.com
VITE_GA_MEASUREMENT_ID=G-XXXXXXXXXX
VITE_CHANNEL_TALK_PLUGIN_KEY=xxxxxxxx
const apiBaseUrl = import.meta.env.VITE_API_BASE_URL;
주의할 점
VITE_가 붙은 값은 브라우저에서 확인될 수 있습니다.NEXT_PUBLIC_ prefix를 붙입니다.NEXT_PUBLIC_API_BASE_URL=https://api.example.com
NEXT_PUBLIC_GA_ID=G-XXXXXXXXXX
const apiBaseUrl = process.env.NEXT_PUBLIC_API_BASE_URL;
NEXT_PUBLIC_이 붙은 값은 클라이언트 번들에 포함될 수 있습니다.@nestjs/config 패키지를 사용합니다.import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
@Module({
imports: [
ConfigModule.forRoot({
isGlobal: true,
envFilePath: '.env',
}),
],
})
export class AppModule {}
import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
@Injectable()
export class AuthService {
constructor(private readonly configService: ConfigService) {}
createToken() {
const jwtSecret = this.configService.get<string>('JWT_SECRET');
return jwtSecret;
}
}
process.env.JWT_SECRET를 직접 여러 곳에서 사용하는 것보다 ConfigService를 통해 관리하면 구조가 깔끔해집니다.DATABASE_URL 누락JWT_SECRET 누락Error: Environment variable not found: DATABASE_URL
joi 같은 라이브러리를 사용해 환경변수를 검증할 수 있습니다.import * as Joi from 'joi';
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
@Module({
imports: [
ConfigModule.forRoot({
isGlobal: true,
validationSchema: Joi.object({
NODE_ENV: Joi.string()
.valid('development', 'production', 'test')
.required(),
PORT: Joi.number().default(3000),
DATABASE_URL: Joi.string().required(),
JWT_SECRET: Joi.string().required(),
CORS_ORIGIN: Joi.string().required(),
}),
}),
],
})
export class AppModule {}
DATABASE_URL 환경변수를 사용합니다.DATABASE_URL="postgresql://user:password@localhost:5432/app_db?schema=public"
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
| 항목 | 예시 |
|---|---|
| DB 종류 | postgresql, mysql |
| 사용자명 | user |
| 비밀번호 | password |
| 호스트 | localhost, db.example.com |
| 포트 | 5432, 3306 |
| DB 이름 | app_db |
| 옵션 | schema=public |
localhost, Docker 내부에서는 서비스명 사용 필요.env에 잘못 넣음.env 수정 후 서버를 재시작하지 않음docker-compose.yml에서 env_file 또는 environment를 사용할 수 있습니다.services:
api:
build: .
env_file:
- .env
ports:
- "3000:3000"
.env 파일의 값을 컨테이너에 주입합니다.services:
api:
build: .
environment:
NODE_ENV: production
PORT: 3000
DATABASE_URL: postgresql://user:password@db:5432/app_db
docker-compose.yml에 그대로 들어가지 않도록 주의해야 합니다.AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEYDATABASE_URLJWT_SECRETSSH_HOSTSSH_USERSSH_PRIVATE_KEYS3_BUCKET_NAMEname: Deploy
on:
push:
branches:
- main
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Use secret
run: echo "Deploying..."
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
echo $JWT_SECRET 같은 명령어는 절대 사용하지 않는 것이 좋습니다..env 파일을 직접 서버에 두거나, 클라우드 Secret Manager를 사용할 수 있습니다..env 파일 권한을 제한한다..env를 Git에 올리지 않는다.# .env 파일 권한 예시
chmod 600 .env
.env 파일만으로는 관리가 어려워질 수 있습니다.| 도구 | 설명 |
|---|---|
| AWS Secrets Manager | AWS에서 제공하는 비밀정보 관리 서비스 |
| AWS Systems Manager Parameter Store | 설정값과 비밀정보를 저장할 수 있는 AWS 서비스 |
| Doppler | 환경변수와 Secret 관리 SaaS |
| Vault | HashiCorp에서 제공하는 Secret 관리 도구 |
| GitHub Actions Secrets | GitHub Actions용 비밀정보 저장소 |
.env + GitHub Secrets만으로도 충분한 경우가 많습니다..env를 GitHub에 올림.gitignore에 .env 포함프론트엔드에 들어가도 되는 값:
“이 값이 사용자에게 보여도 서비스가 망가지지 않는 값”
프론트엔드에 들어가면 안 되는 값:
“이 값이 노출되면 서버 권한이나 외부 서비스 권한을 탈취당하는 값”
.env 수정 후 서버 재시작 필요pm2 restart 또는 pm2 reload 필요pm2 restart api
.env 수정 후 재빌드가 필요할 수 있습니다.npm run build
.env.example을 만들었는가?.env가 .gitignore에 포함되어 있는가?.env 수정 후 서버를 재시작했는가?NestJS + Prisma 프로젝트에서 DB 연결 오류가 발생해.
상황:
- 로컬 개발 환경
- PostgreSQL은 Docker로 실행 중
- 백엔드 서버는 로컬에서 npm run start:dev로 실행 중
- Prisma 사용
- 오류 메시지: Can't reach database server at localhost:5432
.env 구조:
DATABASE_URL="postgresql://USER:PASSWORD@localhost:5432/DB_NAME?schema=public"
docker-compose.yml에서 PostgreSQL 포트:
5432:5432
실제 비밀번호와 DB명은 가렸어.
확인해야 할 순서를 알려줘.
.env 수정 후 서버 재시작을 안내하는가?.env에는 실제 값이 들어가고, .env.example에는 필요한 변수 목록만 정리합니다.@nestjs/config 같은 도구로 환경변수를 관리하고, 필수값 검증을 적용하는 것이 좋습니다.DATABASE_URL 환경변수를 통해 DB에 연결하며, DB 주소, 포트, 계정, Docker 실행 위치를 정확히 확인해야 합니다.