애플리케이션 키 관리자
애플리케이션 키 관리자는 reCAPTCHA, AI API Key, 결제 키, Webhook Secret, Public Site Key 등 외부 서비스 연동에 필요한 키를 안전하게 저장하고 관리하는 기능입니다.
외부 서비스 키를 페이지, JavaScript, 컨트롤러, 설정 파일에 직접 하드코딩하지 않고 중앙에서 안전하게 관리해야 할 때 사용하는 기능입니다.
화면 개요
Application Key Manager는 애플리케이션 수준의 Secret 값과 Public Key를 관리하는 보안 키 저장소입니다. 그룹, Provider, Environment, Key Type, 암호화 저장, Public Key 조회, 서버 코드 사용, HTML Token Replacement 기능을 지원합니다.
| 영역 | 설명 |
|---|---|
| Search Filters | Keyword, Group, Provider, Environment, Status 조건으로 키를 검색합니다. |
| Summary Cards | Total Keys, Active, Secret Type 개수를 요약해서 보여줍니다. |
| Key List | 등록된 애플리케이션 키 목록과 작업 버튼을 표시합니다. |
| Create Key | 새 애플리케이션 키를 생성하고 값을 암호화하여 저장합니다. |
| Usage Guide | 기본 사용법, 서버 사용법, Public Key 브라우저 사용법, reCAPTCHA 예제, 보안 규칙, Token Replacement를 설명합니다. |
Search Filters
Search Filters 영역은 저장된 키를 빠르게 찾기 위한 검색 조건입니다.
| 필터 | 설명 |
|---|---|
| Keyword | Key Code, Key Name, Provider 또는 관련 텍스트로 검색합니다. |
| Group | SECURITY, AI, PAYMENT, WEBHOOK, SITE 같은 논리 그룹으로 필터링합니다. |
| Provider | GOOGLE, OPENAI, STRIPE, SENDGRID 또는 사용자 정의 Provider 이름으로 필터링합니다. |
| Environment | PROD, DEV, TEST, STAGING 같은 환경 기준으로 필터링합니다. |
| Status | 활성 또는 비활성 상태로 필터링합니다. |
| Search | 선택한 검색 조건을 적용합니다. |
Summary Cards
Summary Cards는 현재 키 저장소의 상태를 빠르게 확인할 수 있게 해줍니다.
| 카드 | 설명 |
|---|---|
| Total Keys | 등록된 전체 애플리케이션 키 개수입니다. |
| Active | 시스템에서 사용할 수 있는 활성 키 개수입니다. |
| Secret Type | Secret Type으로 등록된 키 개수입니다. |
Key List
Key List 테이블에는 저장된 애플리케이션 키가 표시됩니다. 등록된 키가 없으면 No application keys found. 메시지가 표시됩니다.
| 컬럼 | 설명 |
|---|---|
| ID | 내부 키 레코드 ID입니다. |
| Code | 애플리케이션에서 사용하는 고유 키 코드입니다. |
| Name | 관리자 화면에 표시되는 알아보기 쉬운 키 이름입니다. |
| Group | 검색과 관리를 위한 논리 그룹입니다. |
| Provider | 외부 서비스 제공자 이름입니다. |
| Environment | PROD, DEV, TEST, STAGING 같은 환경 코드입니다. |
| Type | SECRET, PUBLIC, TOKEN, CONFIG 같은 키 타입입니다. |
| Value | 저장된 키 값입니다. Secret 값은 마스킹되고 암호화되어 저장됩니다. |
| Status | 키의 활성 또는 비활성 상태를 표시합니다. |
| Sort | 목록 표시 순서를 제어합니다. |
| Action | 시스템 설정에 따라 수정, 삭제, 테스트 등의 작업을 제공합니다. |
Create Application Key
Create Application Key 화면은 외부 서비스 키를 안전하게 저장하는 화면입니다. Secret 값은 저장 전에 암호화됩니다.
Basic Settings
| 항목 | 예시 | 설명 |
|---|---|---|
| Key Code | GOOGLE_RECAPTCHA_SITE_KEY |
애플리케이션에서 사용하는 고유 코드입니다. 서버 코드 또는 Token Replacement에서 주로 사용합니다. |
| Key Name | Google reCAPTCHA Site Key |
관리자 화면에 표시되는 이름입니다. |
| Group | SECURITY, AI, PAYMENT |
검색과 관리를 위한 논리 그룹입니다. |
| Provider | GOOGLE, OPENAI, STRIPE |
외부 서비스 제공자 이름입니다. |
| Environment | PROD, DEV, TEST |
환경별 키를 분리하기 위한 값입니다. |
| Key Type | SECRET, PUBLIC, TOKEN, CONFIG |
키의 사용 방식과 브라우저 노출 가능 여부를 결정합니다. |
| Key Value | actual key value |
실제 키 값입니다. 저장 전에 암호화되며 이후에는 마스킹된 값으로만 표시됩니다. |
| Description | 설명 입력 | 이 키가 어디에 사용되는지 설명합니다. |
| Sort Order | 100 |
목록 표시 순서를 제어합니다. |
| Active | 체크 | 키를 시스템에서 사용할 수 있는지 설정합니다. |
기존 키를 수정할 때 현재 저장된 값을 유지하려면 Key Value를 비워 둔 상태로 저장하세요.
Key Types
| Key Type | 용도 | 브라우저 노출 |
|---|---|---|
| PUBLIC | reCAPTCHA Site Key처럼 공개 가능한 키입니다. | 필요한 경우 JavaScript 또는 HTML에서 사용할 수 있습니다. |
| SECRET | 비공개 서비스 키, API Key, Webhook Secret, 결제 Secret, 서버 전용 인증 정보입니다. | 절대 브라우저에 노출하면 안 됩니다. |
| TOKEN | 백엔드 서비스에서 사용하는 Access Token 또는 Bearer Token입니다. | 공개용으로 설계된 경우가 아니라면 서버에서만 사용해야 합니다. |
| CONFIG | Project ID, Tenant ID 같은 비밀이 아닌 설정 값입니다. | 민감 정보가 아닌 경우에만 노출할 수 있습니다. |
Usage Guide
Usage Guide는 애플리케이션 키를 생성하고 서버 코드, 브라우저 코드, reCAPTCHA 연동, 보안 규칙, Token Replacement에서 사용하는 방법을 설명합니다.
기본 사용법
- 필터를 사용해 저장된 키를 검색합니다.
- Create Key를 클릭해 새 키를 추가합니다.
- 기존 키는 Edit로 수정합니다.
- Test 기능이 있다면 암호화된 키가 정상적으로 복호화되는지 확인합니다.
Server Usage
내부 서비스나 컨트롤러에서 키 값을 읽어야 할 때는 IAppKeyProvider를 사용합니다.
IAppKeyProvider 주입
private readonly IAppKeyProvider _appKeyProvider;
public MyService(IAppKeyProvider appKeyProvider)
{
_appKeyProvider = appKeyProvider;
}
일반 키 값 가져오기
string apiKey = await _appKeyProvider.GetValueAsync("OPENAI_API_KEY", "PROD");
Google reCAPTCHA Site Key 가져오기
string siteKey = await _appKeyProvider.GetGoogleRecaptchaSiteKeyAsync("PROD");
Google reCAPTCHA Secret Key 가져오기
string secretKey = await _appKeyProvider.GetGoogleRecaptchaSecretKeyAsync("PROD");
Public Key Usage
Public Key 사용은 브라우저에 노출해도 되는 키에만 사용해야 합니다. Public Key 전용 Endpoint는 SECRET 키를 차단하고 Key Type이 PUBLIC인 키만 반환합니다.
Controller Endpoint
/Admin/AppKeys/GetSiteKey?keyCode=GOOGLE_RECAPTCHA_SITE_KEY&environmentCode=PROD
JavaScript 예제
async function loadSiteKey() {
const response = await fetch("/Admin/AppKeys/GetSiteKey?keyCode=GOOGLE_RECAPTCHA_SITE_KEY&environmentCode=PROD");
const result = await response.json();
if (!result.success) {
throw new Error(result.message || "Failed to load site key.");
}
return result.value;
}
SECRET, TOKEN, 결제 Secret, Webhook Secret, AI API Key를 JavaScript에 노출하지 마세요.
reCAPTCHA Enterprise v3 예제
점수 기반 reCAPTCHA Enterprise에서는 브라우저가 grecaptcha.enterprise.execute로 토큰을 받은 뒤,
서버가 Google Cloud Assessment API로 토큰을 검증합니다.
필요한 키
GOOGLE_RECAPTCHA_SITE_KEY- Key Type: PUBLICGOOGLE_RECAPTCHA_PROJECT_ID- Key Type: CONFIGGOOGLE_RECAPTCHA_API_KEY- Key Type: SECRET
Client Script 예제
<script src="https://www.google.com/recaptcha/enterprise.js?render=SITE_KEY"></script>
const token = await grecaptcha.enterprise.execute(SITE_KEY, {
action: "newsletter_subscribe"
});
Server Validation 개념
if (!tokenProperties.Valid) return false;
if (tokenProperties.Action != "newsletter_subscribe") return false;
if (riskAnalysis.Score < 0.5m) return false;
Security Notes
| 보안 규칙 | 설명 |
|---|---|
| Secret 값을 표시하지 않기 | SECRET 값은 암호화되며 브라우저에 렌더링되면 안 됩니다. |
| 브라우저 키는 PUBLIC 사용 | JavaScript 또는 HTML에서는 PUBLIC으로 표시된 키만 사용해야 합니다. |
| 환경 분리 | DEV, TEST, PROD를 사용해 로컬 키와 운영 키가 섞이지 않도록 합니다. |
| 키 교체 | 유출되었거나 오래된 키는 즉시 교체하고 저장 후 캐시를 비웁니다. |
| Token Replacement 제한 | Token Replacement는 PUBLIC 또는 안전한 CONFIG 값에만 사용합니다. |
저장, 삭제, 상태 변경 후 컨트롤러가 캐시된 키 값을 비워 최신 키를 바로 사용할 수 있도록 합니다.
Token Replacement
Token Replacement는 저장된 HTML, 스킨 파일, 페이지 빌더 콘텐츠, DB 관리 템플릿을 렌더링할 때 유용합니다.
기본 개념
실제 키 값을 HTML에 직접 쓰지 않고 ##{GOOGLE_RECAPTCHA_SITE_KEY}## 같은 토큰 패턴을 작성합니다.
렌더링 시 서버가 해당 토큰을 키 관리자에 저장된 실제 값으로 교체합니다.
HTML Template 예제
<input type="hidden"
id="NewsletterRecaptchaSiteKey"
value="##{GOOGLE_RECAPTCHA_SITE_KEY}##" />
Rendered HTML 결과
<input type="hidden"
id="NewsletterRecaptchaSiteKey"
value="actual-google-recaptcha-site-key" />
Server Replacement 예제
string googleRecaptchaSiteKey =
await _appKeyProvider.GetGoogleRecaptchaSiteKeyAsync("PROD");
result = result.Replace(
"##{GOOGLE_RECAPTCHA_SITE_KEY}##",
googleRecaptchaSiteKey ?? string.Empty
);
General Replacement Helper 예제
private async Task<string> ReplaceAppKeyTokensAsync(string html)
{
if (string.IsNullOrWhiteSpace(html))
{
return string.Empty;
}
string googleRecaptchaSiteKey =
await _appKeyProvider.GetValueAsync("GOOGLE_RECAPTCHA_SITE_KEY", "PROD");
string googleProjectId =
await _appKeyProvider.GetValueAsync("GOOGLE_RECAPTCHA_PROJECT_ID", "PROD");
html = html.Replace("##{GOOGLE_RECAPTCHA_SITE_KEY}##", googleRecaptchaSiteKey ?? string.Empty);
html = html.Replace("##{GOOGLE_RECAPTCHA_PROJECT_ID}##", googleProjectId ?? string.Empty);
return html;
}
권장 작업 순서
- Admin > Site > AppKeys 메뉴로 이동합니다.
- Create Key를 클릭합니다.
- 고유한 Key Code를 입력합니다.
- 관리자가 알아보기 쉬운 Key Name을 입력합니다.
- Group, Provider, Environment, Key Type을 선택합니다.
- Key Value를 입력합니다.
- 이 키가 어디에 사용되는지 Description에 작성합니다.
- 사용 가능한 키라면 Active를 체크합니다.
- Save Key를 클릭합니다.
- 키 타입에 따라 서버 코드, Public Endpoint, Token Replacement에서 사용합니다.
자주 사용하는 작업
| 사용 사례 | 권장 Key Type | 권장 사용 방법 |
|---|---|---|
| Google reCAPTCHA Site Key | PUBLIC | 브라우저 또는 Token Replacement에서 사용합니다. |
| Google reCAPTCHA API Key | SECRET | 서버 코드에서만 사용합니다. |
| OpenAI API Key | SECRET | 서버 측 서비스에서만 사용합니다. |
| Stripe Secret Key | SECRET | 결제 서버 로직에서만 사용합니다. |
| Stripe Publishable Key | PUBLIC | 브라우저 결제 UI에서 사용할 수 있습니다. |
| Webhook Signing Secret | SECRET | 서버 측 서명 검증에만 사용합니다. |
| Project ID 또는 Tenant ID | CONFIG | 민감 정보가 아닌 경우 서버 또는 브라우저에서 사용할 수 있습니다. |
주의사항
- SECRET 값은 저장 전에 암호화됩니다.
- 기존 SECRET 값은 평문으로 표시되지 않습니다.
- 기존 저장 값을 유지하려면 수정 시 Key Value를 비워 두세요.
- 브라우저에 노출해도 되는 값에만 PUBLIC을 사용하세요.
- SECRET, TOKEN, 결제 Secret, Webhook Secret, AI API Key를 JavaScript나 HTML에 노출하지 마세요.
- DEV, TEST, PROD처럼 환경을 분리해서 사용하세요.
- 유출되었거나 오래된 키는 즉시 교체하세요.
문제 해결
| 문제 | 가능한 원인 | 해결 방법 |
|---|---|---|
| 목록에 키가 보이지 않음 | 검색 필터가 적용되어 있거나 키가 저장되지 않았을 수 있습니다. | 필터를 초기화하고 키가 정상 저장되었는지 확인합니다. |
| 서버 코드에서 빈 값이 반환됨 | Key Code 또는 Environment가 잘못되었거나 키가 비활성 상태일 수 있습니다. | Key Code, Environment, Active 상태를 확인합니다. |
| Public Endpoint에서 키가 반환되지 않음 | 키 타입이 PUBLIC이 아닐 수 있습니다. | Key Type이 PUBLIC인지 확인합니다. |
| 저장 후 Secret 값이 보이지 않음 | 정상 동작입니다. Secret 값은 암호화되고 마스킹됩니다. | 기존 Secret을 교체할 때만 새 값을 입력합니다. |
| Token Replacement가 동작하지 않음 | 토큰 패턴 또는 Key Code가 잘못되었을 수 있습니다. | 토큰 형식과 Key Code 철자를 확인합니다. |
| 수정한 키가 반영되지 않음 | 애플리케이션 캐시에 이전 값이 남아 있을 수 있습니다. | 키를 다시 저장하거나 시스템에서 필요한 경우 캐시를 비웁니다. |
관리 권장 사항
GOOGLE_RECAPTCHA_SITE_KEY,OPENAI_API_KEY처럼 명확한 Key Code를 사용하세요.- Provider 이름은
GOOGLE,OPENAI,STRIPE,SENDGRID처럼 일관되게 관리하세요. - 운영 키와 개발 키는 Environment로 분리하세요.
- 비공개 인증 정보는 SECRET으로 저장하고, 브라우저 안전 값에만 PUBLIC을 사용하세요.
- Description에 각 키가 어디에 사용되는지 기록하세요.
- 민감한 키는 주기적으로 교체하세요.
- 이 화면은 신뢰할 수 있는 관리자에게만 접근 권한을 부여하세요.
애플리케이션 키는 외부 서비스 접근 권한과 직접 연결되는 경우가 많습니다. Secret 값을 보호하고, 비공개 인증 정보가 브라우저에 노출되지 않도록 신중하게 관리하세요.