서비스에서 문제가 생기면 보통 가장 먼저 최근 Commit을 의심한다.
하지만 실제 운영에서는 코드가 하나도 바뀌지 않았는데도 장애가 발생할 수 있다.
예:
API Key 교체
환경변수 값 변경
Feature Flag ON
AWS Parameter 수정
외부 API URL 변경
Timeout 값 변경
DB Connection Pool 설정 변경
즉:
Code Change
만 변경이 아니다.
Configuration Change
도 Production의 동작을 바꾸는 중요한 변경이다.
애플리케이션 코드 밖에서 시스템 동작을 결정하는 값이다.
예:
DATABASE_URL
AWS_REGION
KAKAO_API_KEY
NOTIFICATION_TIMEOUT_MS
EXPORT_CONCURRENCY
FEATURE_SELF_CONSULT_ENABLED
AI_AUTOMATION_ENABLED
코드를 수정하지 않아도 이 값만 바꾸면 서비스 동작이 달라진다.
예를 들어:
const timeout = 5000;
처럼 코드에 박혀 있다면 값을 바꿀 때마다 배포가 필요하다.
반면:
const timeout =
config.notification.timeoutMs;
처럼 설정으로 분리하면 환경별로 조절할 수 있다.
Local
10초
Staging
5초
Production
3초
같은 운영이 가능하다.
설정이 수십 개가 되면 다음 상황이 발생할 수 있다.
이 값이 어디서 오는지 모름
Local과 Production 값이 다름
누가 언제 변경했는지 모름
사용하지 않는 설정이 남아 있음
Secret이 만료됐는지 모름
Feature Flag가 몇 달째 남아 있음
즉 Configuration도 코드처럼 관리해야 한다.
핵심은 다음 다섯 가지다.
어떤 설정이 존재하는가?
어떤 환경에서 어떤 설정을 사용하는가?
누가 언제 변경했는가?
변경 결과를 어떻게 검증하는가?
문제가 생기면 어떻게 되돌리는가?
현재 AWS Parameter Store를 사용한다면 방향 자체는 좋다.
예:
/togethermall/prod/database/url
/togethermall/prod/kakao/api-key
/togethermall/prod/notification/timeout
/togethermall/prod/feature/self-consult
환경별 Namespace를 명확하게 나눈다.
예:
/{project}/{environment}/{domain}/{key}
형태로 통일할 수 있다.
예:
/togethermall/prod/notification/provider
/togethermall/prod/notification/timeout-ms
/togethermall/prod/export/concurrency
/togethermall/staging/export/concurrency
모든 환경변수를 똑같이 취급할 필요는 없다.
LOG_LEVEL
TIMEOUT_MS
WORKER_CONCURRENCY
FEATURE_SELF_CONSULT_ENABLED
DATABASE_PASSWORD
API_KEY
JWT_SECRET
S3_BUCKET
QUEUE_NAME
AWS_REGION
종류에 따라 관리 정책이 다르다.
다음은 Secret이다.
Password
API Key
Private Key
OAuth Client Secret
JWT Signing Secret
반면:
TIMEOUT_MS=5000
AWS_REGION=ap-northeast-2
는 일반 설정이다.
둘을 같은 방식으로 로그에 출력하면 안 된다.
설정이 많아질수록 코드 시작 시 검증하는 것이 좋다.
예:
interface AppConfig {
environment: 'local' | 'staging' | 'prod';
notification: {
timeoutMs: number;
concurrency: number;
};
export: {
concurrency: number;
};
}
환경변수는 기본적으로 문자열이다.
예:
NOTIFICATION_TIMEOUT_MS="5000"
코드에서 바로 쓰지 말고 Parse + Validate한다.
const timeout =
Number(process.env.NOTIFICATION_TIMEOUT_MS);
그리고:
NaN인가?
0 이하인가?
허용 범위를 넘는가?
를 검증한다.
예:
EXPORT_CONCURRENCY=-10
인데 서버가 그대로 시작되면 런타임에 이상한 문제가 생길 수 있다.
차라리:
Configuration validation failed
로 애플리케이션 시작 자체를 막는 것이 낫다.
이런 접근을:
Fail Fast
라고 생각할 수 있다.
즉:
잘못된 설정으로
부분적으로 이상하게 동작
하는 것보다:
잘못된 설정 감지
→ 시작 차단
이 낫다.
예:
const schema = {
notificationTimeoutMs: {
min: 1000,
max: 30000,
},
exportConcurrency: {
min: 1,
max: 10,
},
};
처럼 범위를 지정할 수 있다.
예:
Local
KAKAO_API_KEY 없어도
Mock Provider 사용 가능
하지만:
Production
KAKAO_API_KEY 없으면
서버 시작 실패
처럼 환경마다 Required 조건이 달라질 수 있다.
예:
const apiKey =
process.env.KAKAO_API_KEY ?? 'test-key';
같은 코드는 Production에서 위험하다.
설정 누락을 숨길 수 있기 때문이다.
Secret에는 특히 Default를 두지 않는 편이 좋다.
안전할 수 있는 예:
LOG_LEVEL=info
TIMEOUT_MS=5000
위험한 예:
AUTH_ENABLED=false
PAYMENT_ENABLED=true
PRODUCTION_API_KEY=test-key
환경 간 설정이 원치 않게 달라지는 상태다.
예:
Staging
NOTIFICATION_TIMEOUT=5000
Production
NOTIFICATION_TIMEOUT=30000
의도된 차이라면 문제가 아니다.
하지만 이유도 모르고 다르다면 Drift다.
예:
Local DB
localhost
Production DB
RDS
는 정상적인 차이다.
반면:
Staging
FEATURE_NEW_ORDER=true
Production
FEATURE_NEW_ORDER=true
인데 원래 Production은 false여야 했다면 Drift다.
실제 Secret 값은 빼고 필요한 Key와 Metadata를 관리한다.
예:
notification:
provider:
required: true
timeoutMs:
required: true
min: 1000
max: 30000
apiKey:
required: true
secret: true
예:
prod:
notification:
provider: kakao
timeoutMs: 5000
export:
concurrency: 2
단 Secret 값은 Manifest에 넣지 않는다.
설정 변경에도 버전을 부여할 수 있다.
예:
configVersion
2026-09-28-03
그리고 Release와 연결한다.
Release
release_20260928_02
Config
config_20260928_03
장애 발생 시:
코드는 어제와 같은데
오늘 왜 장애가 났지?
라는 상황이 생긴다.
확인해보니:
14:03
Notification Timeout 변경
14:07
실패율 증가
일 수 있다.
Config 변경 이력이 있으면 쉽게 찾을 수 있다.
예:
Actor
admin_1
Action
CONFIG_UPDATE
Key
notification.timeoutMs
Before
5000
After
2000
Environment
production
단 Secret이라면 값 자체는 남기지 않는다.
Secret은:
Before
[REDACTED]
After
[REDACTED]
로 하고,
secretVersion
만 기록할 수 있다.
예:
v12 → v13
Production Config를 바꾸는 행위는 사실상:
코드 없는 배포
와 비슷하다.
따라서:
Validate
Apply
Verify
Monitor
Rollback
과정을 적용할 수 있다.
예:
DRAFT
↓
VALIDATING
↓
APPROVED
↓
APPLYING
↓
VERIFYING
↓
ACTIVE
실패하면:
ROLLED_BACK
으로 돌아간다.
예:
Notification Timeout
5000 → 2000
변경 후:
Provider Error Rate
Timeout Error
Queue Lag
를 확인한다.
설정도 이전 값을 알고 있어야 되돌릴 수 있다.
예:
Current
2000
Previous Stable
5000
문제가 생기면:
5000
으로 복구한다.
AWS Console에서 직접:
값 수정
→ 저장
하고 끝내면:
누가 변경했는지
왜 변경했는지
이전 값이 무엇인지
관련 Release가 무엇인지
추적하기 어렵다.
예:
Reason
알림톡 Provider 응답 지연으로
Timeout 3초 → 5초 조정
를 남기면 이후 이해하기 쉽다.
Feature Flag는 코드를 배포해놓고 실제 기능 활성화를 설정으로 제어하는 방식이다.
예:
if (
featureFlags.selfConsultEnabled
) {
showSelfConsult();
}
코드 배포와 기능 공개를 분리할 수 있다.
코드 배포
↓
기능 OFF
테스트
↓
내부 사용자 ON
검증
↓
일부 사용자 ON
검증
↓
전체 ON
기능이 완전히 정착했는데도:
if (featureFlags.newOrderFlow) {
...
} else {
...
}
가 몇 년씩 남으면 코드가 복잡해진다.
그래서 Flag에도 수명주기가 필요하다.
예:
CREATED
↓
TESTING
↓
ROLLOUT
↓
FULLY_ENABLED
↓
CLEANUP_PENDING
↓
REMOVED
처럼 관리할 수 있다.
Flag 생성 시 다음 정보를 둔다.
flagName
owner
createdAt
purpose
expectedRemovalDate
status
모든 Flag를 반드시 삭제해야 하는 것은 아니다.
신규 기능 배포
Migration
Canary
실험
대부분 제거 대상이다.
운영 Kill Switch
환경별 기능 On/Off
외부 Provider 선택
장기 유지할 수 있다.
예:
RELEASE
EXPERIMENT
OPS
PERMISSION
신규 기능 공개 제어.
A/B 테스트.
운영 Kill Switch.
특정 사용자/관리자 기능.
나쁜 예:
feature1
newFeature
test2
좋은 예:
self_consult_v2_enabled
notification_auto_send_enabled
admin_order_table_v2_enabled
예:
disable_notification = false
는 읽기 어렵다.
notification_enabled = true
처럼 긍정형이 이해하기 쉽다.
Flag 값을 가져오지 못했을 때:
기능 ON
으로 할지
OFF
로 할지 정해야 한다.
고위험 기능은 일반적으로 Fail Closed가 안전하다.
예:
AI Production Action Flag
를 읽지 못했다면:
false
로 처리한다.
즉 위험 기능은 기본적으로 비활성화한다.
반대로 서비스 핵심 조회 기능의 부가 설정이 실패했다고 전체 페이지까지 막을 필요는 없을 수 있다.
상황에 따라:
Fail Open
도 가능하다.
핵심은 기능별 정책을 명확히 정하는 것이다.
코드 곳곳에서 직접:
process.env.FEATURE_X === 'true'
를 쓰면 관리하기 어렵다.
대신:
featureFlagService.isEnabled(
'self_consult_v2',
);
처럼 공통 서비스를 둔다.
예:
interface FeatureFlagService {
isEnabled(
key: FeatureFlagKey,
context?: FeatureContext,
): boolean;
}
일부 사용자에게만 공개할 수 있다.
예:
adminId
userId
tenant
carrier
percentage
기준으로 평가한다.
예:
admin_order_table_v2
를:
동준 계정만 ON
으로 시작한다.
이후:
관리자 2명
전체 관리자
순서로 확대한다.
예:
5%
25%
50%
100%
로 단계적으로 공개할 수 있다.
하지만 현재 규모에서는 복잡한 사용자 비율 Rollout보다 내부 관리자/특정 조건 기반이 더 현실적일 수 있다.
5% Rollout인데 매 요청마다 랜덤이면:
이번 요청
신규 UI
다음 요청
기존 UI
가 될 수 있다.
좋지 않다.
예:
hash(userId + flagKey)
를 통해 같은 사용자는 계속 같은 그룹에 들어가게 한다.
A/B 테스트나 Percentage Rollout에서 중요하다.
예:
14:00
self_consult_v2
10% → 50%
그 이후:
14:03
Error Rate 증가
가 보이면 Flag 변경과 비교할 수 있다.
Dashboard에:
Feature Flag Changed
시점을 표시하면 Release Marker와 같은 역할을 한다.
Flag 평가 결과를 모든 로그에 넣을 필요는 없다.
하지만 장애 분석에 필요한 주요 Flag는:
flagVersion
variant
정도를 남길 수 있다.
예:
{
"event": "order.create.failed",
"orderFlowVariant": "v2"
}
모든 Flag 조합을 Metric Label로 넣으면 Cardinality가 폭증할 수 있다.
중요한 Flag 몇 개만 사용한다.
신규 기능이 완전히 안정화되고:
100% ON
상태가 충분히 유지됐다면 Temporary Flag를 제거한다.
예:
1. 100% ON
2. 일정 기간 Monitoring
3. 기존 코드 Path 삭제
4. Flag 조건 삭제
5. Flag 설정 삭제
6. 관련 테스트 정리
예:
if (flagA) {
if (flagB) {
...
} else {
...
}
} else {
...
}
Flag가 늘어날수록 가능한 상태 조합이 폭증한다.
2^5
=
32
10개면:
1024
개의 조합이 가능하다.
모든 조합을 테스트하기 어렵다.
그래서 오래된 Flag를 정리해야 한다.
삭제되지 않은 Feature Flag는:
Flag Debt
라고 생각할 수 있다.
주기적으로:
90일 이상 Flag
100% ON Flag
Owner 없는 Flag
만료일 지난 Flag
를 찾는다.
예:
interface FeatureFlagDefinition {
key: string;
type:
| 'RELEASE'
| 'EXPERIMENT'
| 'OPS'
| 'PERMISSION';
owner: string;
createdAt: Date;
expiresAt?: Date;
description: string;
}
예:
| Flag | 상태 | 유형 | 환경 | 만료 |
|---|---|---|---|---|
| self_consult_v2 | ON | RELEASE | prod | 10/30 |
| notification_auto | ON | OPS | prod | - |
| ai_prod_action | OFF | OPS | prod | - |
이런 화면이 있으면 운영이 쉬워진다.
예:
개발 관리자
READ
운영 관리자
일부 Flag 변경
Production Critical Flag
승인 필요
처럼 관리할 수 있다.
예:
AI_REPORT_ENABLED
AI_AUTO_COMMIT_ENABLED
AI_AUTO_DEPLOY_ENABLED
중:
AI_AUTO_DEPLOY_ENABLED
은 훨씬 위험하다.
AI 자동화는 단순 ON/OFF보다 권한 수준으로 나눌 수 있다.
예:
READ_ONLY
WRITE_LOCAL
CREATE_PR
DEPLOY_STAGING
DEPLOY_PRODUCTION
이 중 Production은 별도 Approval을 요구한다.
Kill Switch는:
문제가 생기면 즉시 멈추기 위한 Flag
다.
예:
NOTIFICATION_AUTO_SEND_ENABLED
AI_PROD_ACTION_ENABLED
WEBHOOK_SIDE_EFFECT_ENABLED
비상시에:
여러 설정을 찾아 바꾸고
배포까지 해야 함
이면 Kill Switch가 아니다.
가능하면:
한 설정 변경
→ 즉시 기능 중단
이어야 한다.
비상시에 처음 꺼보면 안 된다.
Staging에서:
ON
→ 기능 실행
OFF
→ Side Effect 없음
을 확인한다.
가능하면 Runtime에서 Config를 다시 읽을 수 있으면 좋다.
하지만 무조건 실시간 Config 시스템이 필요한 것은 아니다.
현재 규모에서는:
짧은 Cache TTL
정도로도 충분할 수 있다.
애플리케이션 재배포 없이 변경 가능한 설정이다.
예:
Feature Flag
Concurrency
Rate Limit
Kill Switch
앱 시작 시만 읽어도 되는 설정이다.
예:
AWS_REGION
Database Host
Application Port
Dynamic과 Static을 구분한다.
실시간 변경 기능이 많아질수록 복잡해진다.
잘못된 Runtime 변경으로 장애가 생길 수도 있다.
따라서 실제 운영 중 변경 가치가 높은 것만 Dynamic으로 둔다.
SSM을 매 요청마다 읽는 것은 비효율적이다.
예:
Request
→ SSM 조회
를 반복하면 Latency와 비용이 증가할 수 있다.
따라서 Cache를 사용한다.
예:
Feature Flag
30초
Kill Switch
5초
일반 Config
5분
처럼 중요도에 따라 다르게 둘 수 있다.
예:
AI Production Action 중단
을 했는데 Cache가 30분이면:
최대 30분 더 실행
될 수 있다.
위험하다.
SSM을 읽지 못했다고 하자.
기존 Cache 유지
Default 사용
기능 OFF
서버 실패
중 어떤 행동을 할지 Config별로 정해야 한다.
Secret을 영구적으로 같은 값으로 쓰지 않고 주기적으로 교체하는 것이다.
예:
API Key
Database Password
OAuth Secret
JWT Secret
Secret은 시간이 지날수록 노출 가능성이 누적된다.
예:
로그에 실수로 출력
개발자 로컬 저장
과거 백업
잘못된 공유
외부 서비스 유출
그래서 일정 주기로 교체하거나 사고 발생 시 즉시 교체한다.
예:
DB Password
old → new
라고 한 번에 바꾸면:
앱은 old 사용 중
DB는 new만 허용
→ 서비스 장애
가 날 수 있다.
외부 서비스가 여러 Key 동시 활성화를 지원한다면:
Old Key
ACTIVE
New Key
ACTIVE
상태를 잠깐 유지한다.
예:
1. 새 Secret 생성
2. 새 Secret 등록
3. 애플리케이션이 새 Secret 사용
4. 정상 동작 확인
5. 이전 Secret 폐기
서비스가 지원한다면:
currentSecret
previousSecret
을 잠깐 함께 유지할 수도 있다.
Auth Token 검증 같은 경우에 유용하다.
예를 들어 Signing Key를 즉시 바꾸면 기존 로그인 Token이 전부 무효화될 수 있다.
이게 의도된 보안 대응이면 괜찮지만, 일반 Rotation이라면 사용자 영향이 크다.
JWT나 서명 키는:
kid
를 활용해 어떤 Key로 서명했는지 구분할 수 있다.
예:
kid=v12
그러면:
v11
v12
를 일정 기간 함께 검증 가능하다.
DB Credential 변경 시:
새 Credential 생성
애플리케이션 반영
Connection 재생성
기존 Credential 제거
순서가 중요하다.
기존 DB Connection은 이전 Credential로 계속 살아 있을 수 있다.
재연결 시점에 문제가 드러날 수 있다.
그래서 Rotation 후:
새 Connection 생성 확인
이 필요하다.
예:
Kakao
Vercel
OpenRouter
기타 Provider
Key 교체 후:
실제 API Health Check
를 수행한다.
예:
PLANNED
↓
NEW_SECRET_CREATED
↓
DEPLOYED
↓
VERIFIED
↓
OLD_SECRET_REVOKED
↓
COMPLETED
새 Secret을 배포하자마자 바로 기존 Key를 폐기하면:
일부 Instance는 아직 old key
일 수 있다.
모든 실행 환경이 새 Key를 쓰는지 먼저 확인한다.
확인:
새 Credential로 인증 성공
관련 API 호출 정상
Error Rate 정상
이전 Credential 사용 없음
이다.
가능한 서비스라면:
old key usage
를 확인한다.
사용량이 0이 된 후 폐기한다.
새 Key가 문제라면:
이전 Key가 아직 활성
상태에서 빠르게 Rollback할 수 있어야 한다.
예:
secret
KAKAO_API_KEY
version
v12 → v13
rotatedAt
2026-09-28
actor
system/admin
oldRevokedAt
2026-09-28
실제 값은 기록하지 않는다.
일부 Provider Key는 만료일이 있을 수 있다.
예:
expiresAt
을 저장해서:
30일 전
7일 전
1일 전
알림을 만들 수 있다.
예:
90일
180일
등으로 조직 정책을 정할 수 있다.
다만 무조건 짧게 바꾼다고 보안이 좋아지는 것은 아니다.
Rotation 과정 자체가 사고 위험을 만들 수도 있다.
정기 Rotation보다 더 중요한 것은:
Secret 노출 의심
↓
즉시 폐기/교체
↓
서비스 정상화
가 가능한 구조다.
어떤 Secret이 있는지 모르면 Rotation도 못 한다.
예:
Secret Name
Purpose
Provider
Environment
Owner
CreatedAt
LastRotatedAt
ExpiresAt
를 관리한다.
예:
과거 API Key
퇴역한 OAuth App
테스트용 Production Credential
을 계속 남겨두면 공격면이 늘어난다.
Secret마다 책임 영역을 정한다.
예:
Kakao Key
Notification
AWS Key
Infrastructure
AI Key
AI Automation
1인 개발이라도 목적이 명확해진다.
CI에서:
API Key Pattern
Private Key
.env
Credential File
등을 검사할 수 있다.
Commit History에 남아 있을 수 있다.
따라서 실제 Secret이 Git에 노출되었다면:
Secret Rotation
이 우선이다.
History 제거만으로 Secret을 다시 안전하게 만들 수 있는 것은 아니다.
예:
Authorization
Cookie
API Key
Password
Token
등은 Logger에서 중앙적으로 제거하는 것이 좋다.
나쁜 구조:
logger.info({
password:
'[REDACTED]',
});
개발자가 실수할 수 있다.
공통 Logger가 Key 이름을 기준으로 자동 Redaction하게 한다.
const sensitiveKeys = [
'password',
'token',
'authorization',
'apiKey',
'secret',
];
예:
error:
"request failed Authorization: Bearer xxx"
처럼 Error Message 자체에 들어갈 수도 있다.
따라서 외부 Library Error를 그대로 전체 출력하지 않는 것이 좋다.
Incident 분석을 위해 당시 Config 상태를 알고 싶을 수 있다.
하지만 Secret 전체를 저장하면 안 된다.
대신:
{
"notificationTimeoutMs": 5000,
"exportConcurrency": 2,
"featureFlagsVersion": "v31",
"secretVersions": {
"kakao": "v13"
}
}
처럼 안전한 Snapshot을 남긴다.
예:
Release
release_20260928_02
Config Version
config_44
Flag Version
flag_31
Secret Version
secret_13
이면 당시 실행 환경을 훨씬 잘 재현할 수 있다.
예:
코드
변화 없음
Release
동일
Config
v43 → v44
장애 발생
이라면 Config 변경을 우선 확인할 수 있다.
Config 변경 시 이벤트를 남긴다.
예:
config.changed
{
"key": "notification.timeoutMs",
"environment": "production",
"version": "v44"
}
Secret 값은 제외한다.
feature_flag.changed
예:
{
"flag": "self_consult_v2",
"before": 25,
"after": 100
}
secret.rotated
예:
{
"secret": "kakao_api_key",
"oldVersion": "v12",
"newVersion": "v13"
}
설정 문제도 Error Code를 만들 수 있다.
예:
CONFIG_MISSING
CONFIG_INVALID
CONFIG_OUT_OF_RANGE
SECRET_UNAVAILABLE
FEATURE_FLAG_FETCH_FAILED
만약 외부 Feature Flag 서비스를 쓴다면 그 서비스 장애 자체도 고려해야 한다.
현재는 굳이 별도 SaaS를 쓸 필요는 없다.
SSM이나 DB 수준으로도 충분할 수 있다.
처음에는:
DB 또는 SSM
+
FeatureFlagService
정도면 충분하다.
굳이 대형 Flag Platform을 도입할 필요는 없다.
관리자 UI 구축 쉬움
변경 이력 관리 가능
사용자별 Flag 가능
DB 장애 시 Flag 조회도 실패할 수 있다.
그래서:
Cache
+
Safe Default
가 필요하다.
이미 AWS를 쓰고 있다면 Infrastructure가 단순하다.
다만 사용자별 복잡한 Rollout이나 관리자 UI는 별도 구현이 필요하다.
예:
Static Config / Secret
→ SSM
Operational Feature Flag
→ DB
처럼 역할을 나눌 수 있다.
예:
Default
↓
Environment
↓
SSM
↓
Runtime Override
여러 Source가 있으면 최종 값이 어디서 왔는지 알기 어려워진다.
최종 적용된 설정을:
Effective Config
라고 볼 수 있다.
운영 화면에서 Secret을 제외하고 일부를 확인할 수 있다.
예:
notification.timeoutMs
5000
export.concurrency
2
selfConsult
ON
설정 정보 자체가 공격자에게 시스템 구조를 알려줄 수 있다.
내부 관리자 권한에서만 노출한다.
예:
AI_MODEL
AI_MAX_STEPS
AI_TOOL_TIMEOUT
AI_AUTO_COMMIT
AI_PRODUCTION_ACCESS
이런 값이 생길 수 있다.
예:
AI_MAX_STEPS=20
은 Config다.
반면:
AI는 Production DB DELETE 금지
는 Policy다.
Policy를 단순 Config 하나로 쉽게 끌 수 있게 만들면 위험하다.
예:
AI_PRODUCTION_WRITE_ALLOWED
같은 Flag가 있다면 일반 Feature Flag보다 훨씬 높은 권한이 필요하다.
AI 자동화에서는 Prompt 변경도 실행 결과를 크게 바꾼다.
즉:
Code Version
Model Version
Prompt Version
Policy Version
을 같이 관리해야 한다.
예:
{
"model": "shn-coder",
"promptVersion": "v18",
"policyVersion": "v7",
"configVersion": "v44"
}
를 Run에 저장한다.
예:
Code
동일
Prompt Version
v17 → v18
결과 품질 하락
같은 변화도 추적할 수 있다.
예:
qwen model A
→ model B
는 단순 설정 변경 같지만 AI Workflow 동작을 크게 바꿀 수 있다.
따라서:
Canary
Evaluation
Rollback
과정이 필요할 수 있다.
예:
새 Prompt Version
내부 Test Run 10개
↓
성공
↓
일부 Report Workflow
↓
전체 적용
형태다.
예:
ai_auto_report_enabled
ai_auto_commit_enabled
ai_tool_write_enabled
을 별도로 제어한다.
문제가 생기면 AI 전체를 끄는 것보다 특정 Capability만 막을 수 있다.
정기적으로:
Expected Config
vs
Actual Config
를 비교할 수 있다.
단 Secret은 값 비교가 아니라 Version이나 존재 여부만 비교한다.
Production Config Drift
notification.timeoutMs
Expected
5000
Actual
3000
Status
DRIFT
실제로 운영자가 긴급 대응으로 설정을 바꿨을 수도 있다.
자동으로 원래 값으로 돌리면 장애를 악화시킬 수 있다.
초기에는:
Detect
→ Alert
→ Human Review
정도가 안전하다.
Reconciliation 개념과 같다.
Desired State
설정 저장소
Actual State
실제 Running Application
두 값을 비교할 수 있다.
SSM 값만 바뀌었다고 앱이 새 값을 읽었다는 보장은 없다.
예:
SSM
timeout=5000
App Cache
timeout=3000
이면 실제 동작은 3000이다.
예:
GET /internal/config/version
응답:
{
"configVersion": "v44",
"flagVersion": "v31"
}
값 전체를 노출할 필요는 없다.
예:
Desired
config v44
Actual
config v43
이면:
CONFIG_DRIFT
Alert를 낸다.
자동 Restart까지는 운영 정책에 따라 판단한다.
일부 설정은:
Reload
할 수 있다.
예:
Feature Flag
Rate Limit
Concurrency
반면 DB Host나 Runtime과 밀접한 설정은 재시작이 더 안전할 수 있다.
Config 여러 개를 동시에 변경하는데 중간 상태가 노출되면 이상할 수 있다.
예:
provider=new
apiKey=old
상태가 잠깐 생기면 실패한다.
관련 설정 여러 개를 하나의 Bundle로 묶을 수 있다.
예:
notificationConfig v12
provider
timeout
apiKeyVersion
rateLimit
전체 Bundle을 한 번에 교체한다.
같은:
configVersion=v44
적용 요청이 두 번 와도 최종 상태가 같아야 한다.
관리자 A와 B가 동시에 같은 Flag를 바꾸면:
Lost Update
가 발생할 수 있다.
Version을 이용한 Optimistic Lock을 적용할 수 있다.
현재:
version=12
인 Flag를 수정할 때:
UPDATE feature_flags
SET ...
WHERE id = ?
AND version = 12
로 처리한다.
다른 사람이 먼저 수정했다면 실패한다.
위험한 설정은:
Draft
→ Approval
→ Apply
과정을 둘 수 있다.
예:
DB Connection Pool
AI Production Action
Notification Kill Switch
Payment Provider
위험도에 따라 나눈다.
UI Flag
즉시 변경.
Worker Concurrency
변경 후 Monitoring.
Production AI Write
Auth
DB Credential
Approval 필요.
예:
LOW
MEDIUM
HIGH
CRITICAL
을 설정 Definition에 둘 수 있다.
고위험 설정 변경도 가능하면:
문제 발생 시 대응 가능한 시간
에 한다.
퇴근 직전 DB Credential Rotation은 피한다.
예:
1. 변경 이유 확인
2. 현재 값/Version 확인
3. Previous Stable 기록
4. Validation
5. Apply
6. Health 확인
7. Metric 확인
8. Stable 선언
1. 새 Secret 생성
2. 새 Version 저장
3. 앱에 새 Secret 반영
4. 새 Connection/API 호출 확인
5. Error Metric 확인
6. Old Secret 사용 여부 확인
7. Old Secret 폐기
8. Audit 기록
1. 100% ON 여부 확인
2. 일정 기간 장애 없음 확인
3. 기존 Code Path 사용 여부 확인
4. Legacy Branch 삭제
5. Flag Condition 삭제
6. Flag Registry 제거
7. 관련 테스트 단순화
예:
Incident
알림톡 Timeout 급증
원인:
notification.timeoutMs
5000
→
500
오타였다.
Postmortem:
운영자가 5000 대신 500 입력
보다:
Config Range Validation이 없었음
Production 변경 Approval 없음
변경 후 Metric 확인 절차 없음
이 구조적 원인이다.
Timeout 최소값 1000 Validation
Production Config 변경 Audit
Change Marker
5분 Monitoring
을 추가한다.
예:
Before
timeout
5000
failureRate
0.2%
After
timeout
2000
failureRate
4.1%
처럼 자동 비교할 수 있다.
변경 후 일정 시간 뒤:
Error Rate
Latency
Queue Lag
Business Metric
을 요약한다.
AI에게:
최근 24시간 Config 변경과
Metric 변화를 비교해줘.
라고 할 수 있다.
Read-Only 분석은 안전하다.
Drift 발견
위험 설정 식별
Flag Cleanup 후보
등은 AI가 할 수 있다.
하지만:
Production Config 자동 수정
은 별도 승인 구조가 필요하다.
Change
export.concurrency
2 → 10
Risk
HIGH
Reason
DB Connection 사용량 증가 가능
Recommended Checks
- DB Connection Pool
- RDS CPU
- Export Queue
예:
Flag
admin_order_table_v2
Created
120 days ago
Current
100% ON
Legacy Path Traffic
0%
Recommendation
Cleanup candidate
형태로 정리할 수 있다.
코드 Branch 삭제까지 자동으로 하는 것은 위험하다.
AI가 후보를 제시하고 사람이 확인하는 방식이 낫다.
관리자 내부 화면에:
Environment
Config Version
Feature Flag Version
Last Config Change
Secret Rotation Status
Drift Count
를 표시할 수 있다.
예:
KAKAO_API_KEY
Status
Configured
Version
v13
Last Rotated
2026-09-28
정도만 보여준다.
예:
self_consult_v2
Environment
Production
Status
50%
Type
RELEASE
Owner
web
Expires
2026-10-15
Production Critical Flag라면:
AI Production Action을
활성화하시겠습니까?
같은 별도 확인을 둘 수 있다.
Production 설정 변경 시:
reason
을 필수로 받아도 좋다.
나중에 Audit가 훨씬 이해하기 쉬워진다.
현재 NestJS + Prisma + AWS SSM 기반 프로젝트에
Configuration Management 구조를 정리해줘.
목표는 복잡한 Configuration Platform을 만드는 것이 아니라,
Production에서 사용하는 설정, Feature Flag, Secret의
변경을 안전하게 검증하고 추적할 수 있게 하는 것이다.
현재 사용 중인 AWS SSM Parameter Store 구조를 우선 활용하고,
필요하지 않은 외부 SaaS는 새로 도입하지 않는다.
1. Configuration을 다음 유형으로 구분한다.
- STATIC_CONFIG
- DYNAMIC_CONFIG
- FEATURE_FLAG
- SECRET
2. 애플리케이션 시작 시 Config Validation을 수행한다.
다음 항목을 검증한다.
- 필수 설정 존재 여부
- 숫자 Parsing
- 최소/최대 범위
- Production에서 필수 Secret 존재 여부
잘못된 필수 설정이 있으면 Fail Fast한다.
3. Secret에는 안전하지 않은 Default 값을 두지 않는다.
4. Config 값 접근을 중앙화한다.
각 Service에서
process.env를 직접 읽지 않도록 하고
ConfigService를 통해 접근한다.
5. AWS SSM Parameter naming convention을 정리한다.
예:
/{project}/{environment}/{domain}/{key}
6. Secret 값은 Log, Audit Log,
Error Message에 노출하지 않는다.
7. 공통 Logger에 Secret Redaction 구조를 추가한다.
최소 대상:
- password
- token
- authorization
- apiKey
- secret
- cookie
8. FeatureFlag 모델 또는 적절한 저장 구조를 만든다.
필드 예:
- key
- type
- status
- environment
- owner
- description
- createdAt
- expiresAt
- version
9. Feature Flag Type은 다음을 지원한다.
- RELEASE
- EXPERIMENT
- OPS
- PERMISSION
10. FeatureFlagService를 통해서만 Flag를 평가하게 한다.
예:
isEnabled(key, context)
11. Production에서 위험한 Flag는
값 조회 실패 시 Fail Closed하도록 할 수 있게 한다.
12. Flag 변경 이력을 Audit Log에 기록한다.
- before
- after
- actor
- reason
- environment
- version
13. Feature Flag version에
Optimistic Lock을 적용할 수 있게 한다.
동시에 두 명이 변경했을 때
마지막 저장이 이전 변경을 덮어쓰지 않게 한다.
14. Temporary Flag Cleanup을 위한 정보를 관리한다.
- createdAt
- expiresAt
- owner
- fullyEnabledAt
15. 다음 Flag를 Cleanup Candidate로 조회할 수 있게 한다.
- 만료일 초과
- 장기간 100% ON
- Owner 없음
자동 삭제는 하지 않는다.
16. Static Config와 Dynamic Config를 구분한다.
Dynamic Config 예:
- Feature Flag
- Worker Concurrency
- Kill Switch
- Rate Limit
17. Dynamic Config는 Cache를 사용할 수 있게 한다.
Config 유형별 TTL을 다르게 설정할 수 있게 한다.
18. Kill Switch는 짧은 TTL을 사용할 수 있게 한다.
19. Dynamic Config 조회 실패 시
Config별 Fallback Policy를 정의할 수 있게 한다.
예:
- KEEP_LAST_VALUE
- FAIL_CLOSED
- DEFAULT
- FAIL_STARTUP
20. Config Version 개념을 추가한다.
실제 Secret 값이 아닌
현재 Config Version을 확인할 수 있게 한다.
21. Health/Internal Endpoint에서
민감 값을 노출하지 않고 다음만 확인할 수 있게 한다.
- configVersion
- featureFlagVersion
22. Secret Rotation 기록 구조를 만든다.
필드 예:
- secretName
- environment
- previousVersion
- newVersion
- rotatedAt
- oldSecretRevokedAt
- status
실제 Secret 값은 DB에 저장하지 않는다.
23. Rotation 상태는 다음을 고려한다.
- PLANNED
- NEW_SECRET_CREATED
- DEPLOYED
- VERIFIED
- OLD_SECRET_REVOKED
- COMPLETED
- FAILED
24. Secret Rotation은
새 Secret 검증 전 Old Secret을 자동 폐기하지 않는다.
25. Config 변경 이벤트를 Structured Log로 남긴다.
예:
- config.changed
- feature_flag.changed
- secret.rotated
26. Production Config 변경 후
일정 시간 Monitoring할 수 있는 구조를 고려한다.
27. 테스트를 작성한다.
- Required Config 누락 시 실패
- 잘못된 숫자 Config 실패
- Secret 로그 Redaction
- Feature Flag 기본값
- Fail Closed
- Optimistic Lock 충돌
- Flag Audit Log
- Secret 값 Audit 미노출
- Config Version 확인
기존 구조를 먼저 분석하고,
이미 존재하는 ConfigService 또는 SSM 로직이 있다면
중복 구현하지 말고 현재 구조를 확장해줘.
현재 코드베이스에서 사용 중인 Feature Flag를 전부 찾아서
Flag Cleanup Report를 작성해줘.
코드를 직접 삭제하지 말고 분석만 수행한다.
각 Flag에 대해 다음을 정리한다.
- Flag 이름
- 사용 위치
- 활성/비활성 Branch
- Flag Type 추정
- Legacy Path 존재 여부
- 제거 시 영향 범위
- 관련 Test
- Cleanup 난이도
다음 조건이면 Cleanup Candidate로 표시한다.
1. 항상 true로 사용되고 있는 Flag
2. 항상 false로 사용되고 있는 Flag
3. 설정 정의는 있지만 코드에서 사용하지 않는 Flag
4. 신규 경로가 이미 기본 경로가 된 Flag
5. Legacy Branch가 장기간 사용되지 않은 Flag
결과는 다음 Priority로 구분한다.
HIGH
즉시 정리 가능하고 위험 낮음
MEDIUM
테스트 후 정리 필요
LOW
운영상 유지 필요 가능성 있음
실제 사용 여부를 확인할 수 없는 경우
추정으로 삭제 가능하다고 단정하지 않는다.
# Secret Rotation
Secret:
Environment:
Provider:
Current Version:
New Version:
## 1. 사전 확인
- 관련 서비스 확인
- 사용 Instance 확인
- Rollback 방법 확인
- Provider가 Key Overlap을 지원하는지 확인
## 2. 새 Secret 생성
## 3. SSM 등록
## 4. 애플리케이션 반영
## 5. Verification
- 인증 성공
- API 호출 정상
- Error Rate 정상
- 새 Connection 정상
## 6. Old Secret Usage 확인
## 7. Old Secret 폐기
## 8. Monitoring
## 9. Audit
- Rotation 완료 시각
- Version 변경
- 이상 여부
운영 시스템에서 변경은 코드만 의미하지 않는다.
실제로는:
Code
Configuration
Feature Flag
Secret
Prompt
Model
모두 서비스 동작을 바꾸는 변경사항이다.
그래서 Configuration도 코드처럼:
Validate
↓
Version
↓
Apply
↓
Verify
↓
Monitor
↓
Rollback
해야 한다.
가장 먼저 중요한 것은 Config Validation이다.
잘못된 값으로 서버가 실행
되는 것보다:
시작 단계에서 오류 감지
→ Fail Fast
하는 편이 안전하다.
또한 환경별 설정 차이는 모두 문제가 아니라:
의도하지 않은 차이
가 Config Drift다.
따라서:
Expected Config
vs
Actual Config
를 비교할 수 있어야 한다.
Feature Flag는 안전한 배포에 매우 유용하지만 Flag 자체도 수명주기가 필요하다.
CREATED
↓
TESTING
↓
ROLLOUT
↓
FULLY_ENABLED
↓
CLEANUP
↓
REMOVED
기능이 안정화됐는데도 Flag를 계속 남기면:
Legacy Code
Branch 증가
Test 조합 증가
라는 새로운 기술 부채가 된다.
특히 운영 Kill Switch는 일반 Flag와 다르다.
문제가 발생했을 때
배포 없이
즉시 Side Effect를 멈출 수 있어야 한다.
그래서:
Notification Auto Send
Webhook Side Effect
AI Production Action
같은 기능은 Kill Switch를 두는 가치가 크다.
Secret 관리에서는 가장 중요한 것이:
값을 숨기는 것
뿐만 아니라:
언제든 교체할 수 있는 구조
를 만드는 것이다.
안전한 Rotation은:
새 Secret 생성
↓
애플리케이션 적용
↓
검증
↓
기존 Secret 사용 없음 확인
↓
기존 Secret 폐기
순서로 진행한다.
새 Secret이 제대로 동작하는지도 확인하지 않고 이전 Secret부터 폐기하면 Rotation 자체가 장애를 만들 수 있다.
또한 AI 자동화에서는 일반 코드보다 관리해야 할 Version이 더 많다.
Code Version
Config Version
Prompt Version
Policy Version
Model Version
이 정보가 Run에 남아야:
같은 코드인데
왜 AI 결과가 달라졌는가?
도 추적할 수 있다.
현재 투게더몰 규모에서는 거대한 Configuration Platform이 필요한 것은 아니다.
우선:
SSM 구조 정리
Config Validation
FeatureFlagService
Kill Switch
Config Audit Log
Secret Rotation 기록
정도부터 갖추는 것이 현실적이다.
지금까지의 운영 자동화 흐름에 Configuration까지 연결하면:
Change
↓
Validate
↓
Version
↓
Release / Config Apply
↓
Observe
↓
Detect Drift
↓
Rollback / Reconcile
↓
Audit
↓
Cleanup
이 된다.
결국 Configuration Management의 핵심은
“설정은 코드보다 덜 중요해서 관리하는 것이 아니라, 코드처럼 리뷰되지 않고 바로 운영 동작을 바꿀 수 있기 때문에 오히려 더 조심해서 관리해야 한다.”
는 것이다.