본 콘텐츠의 이미지 및 내용은 AI로 생성되었습니다.
본 콘텐츠의 이미지 및 내용을 무단으로 복제, 배포, 수정하여 사용할 경우 저작권법에 의해 법적 제재를 받을 수 있습니다.
이미지 로딩 중...
AI Generated
2025. 12. 20. · 6 Views
AWS Secrets Manager 완벽 가이드
AWS에서 데이터베이스 비밀번호, API 키 등 민감한 정보를 안전하게 관리하는 Secrets Manager의 핵심 개념과 실무 활용법을 배워봅니다. 초급 개발자도 쉽게 따라할 수 있도록 실전 예제와 함께 설명합니다.
목차
1. Secrets Manager란?
어느 날 신입 개발자 김개발 씨가 코드를 GitHub에 푸시했습니다. 그런데 10분 후, 팀장님께서 급하게 달려오셨습니다.
"김 개발님! 방금 올린 코드에 데이터베이스 비밀번호가 그대로 노출되어 있어요!"
AWS Secrets Manager는 데이터베이스 자격 증명, API 키, 비밀번호 같은 민감한 정보를 안전하게 저장하고 관리하는 서비스입니다. 마치 은행의 금고처럼 중요한 정보를 암호화하여 보관하고, 필요한 사람만 접근할 수 있도록 합니다.
코드에 하드코딩하지 않고도 애플리케이션에서 안전하게 비밀 정보를 사용할 수 있습니다.
다음 코드를 살펴봅시다.
import boto3
import json
# Secrets Manager 클라이언트 생성
client = boto3.client('secretsmanager', region_name='ap-northeast-2')
# 시크릿 값 조회
response = client.get_secret_value(SecretId='prod/db/credentials')
# JSON 형태의 시크릿 파싱
secret = json.loads(response['SecretString'])
db_password = secret['password']
db_username = secret['username']
# 이제 안전하게 DB 연결 가능
print(f"사용자: {db_username}")
김개발 씨는 입사 2주 차 신입 개발자입니다. 오늘 처음으로 회사의 실제 운영 데이터베이스에 연결하는 코드를 작성하게 되었습니다.
평소 공부할 때처럼 데이터베이스 비밀번호를 코드에 직접 작성했습니다. 그런데 코드 리뷰를 하던 선배 박시니어 씨가 심각한 표정으로 말했습니다.
"김 개발님, 이렇게 하면 안 돼요. 누구나 우리 데이터베이스에 접근할 수 있게 돼요." 그렇다면 비밀번호는 어디에 저장해야 할까요?
바로 이런 문제를 해결하기 위해 AWS Secrets Manager가 존재합니다. 쉽게 비유하자면, Secrets Manager는 마치 은행의 대여 금고와 같습니다.
중요한 문서나 귀중품을 집에 두지 않고 은행 금고에 보관하듯이, 민감한 정보를 코드에 직접 쓰지 않고 안전한 곳에 보관하는 것입니다. Secrets Manager를 사용하기 전에는 어땠을까요?
개발자들은 비밀번호를 환경변수에 저장하거나, 설정 파일에 넣어두었습니다. 하지만 이런 방법은 여러 문제가 있었습니다.
환경변수는 서버에 접속할 수 있는 사람이라면 누구나 볼 수 있었고, 설정 파일은 실수로 Git에 올라가는 경우가 빈번했습니다. 더 큰 문제는 비밀번호를 변경할 때였습니다.
데이터베이스 비밀번호를 바꾸면 모든 서버에 접속해서 환경변수를 하나하나 수정해야 했습니다. 서버가 100대라면?
생각만 해도 끔찍합니다. 바로 이런 문제를 해결하기 위해 Secrets Manager가 등장했습니다.
Secrets Manager를 사용하면 몇 가지 큰 장점을 얻을 수 있습니다. 첫째, 모든 비밀 정보가 암호화되어 저장됩니다.
AWS의 강력한 암호화 기술로 보호되기 때문에 누군가 물리적으로 서버에 접근해도 원본 값을 볼 수 없습니다. 둘째, 접근 권한을 세밀하게 관리할 수 있습니다.
IAM 정책을 통해 누가, 어떤 시크릿에, 어떤 작업을 할 수 있는지 정확하게 제어할 수 있습니다. 개발팀은 개발용 데이터베이스 비밀번호만, 운영팀은 운영용 비밀번호만 볼 수 있게 설정하는 식입니다.
셋째, 비밀번호 변경이 훨씬 쉬워집니다. Secrets Manager에서 한 번만 값을 업데이트하면, 모든 애플리케이션이 자동으로 새로운 값을 사용합니다.
각 서버마다 일일이 수정할 필요가 없습니다. 위의 코드를 한 줄씩 살펴보겠습니다.
먼저 boto3 라이브러리를 사용해서 Secrets Manager 클라이언트를 생성합니다. region_name은 시크릿이 저장된 AWS 리전을 지정합니다.
다음으로 get_secret_value 메서드로 시크릿을 조회합니다. SecretId는 시크릿의 이름 또는 ARN을 의미합니다.
반환된 응답에서 SecretString을 추출하면 JSON 형태의 문자열이 나옵니다. 이것을 파싱하면 실제 사용자 이름과 비밀번호를 얻을 수 있습니다.
이제 이 값으로 데이터베이스에 안전하게 연결할 수 있습니다. 실제 현업에서는 어떻게 활용할까요?
예를 들어 전자상거래 사이트를 운영한다고 가정해봅시다. 주문 정보를 저장하는 RDS 데이터베이스, 결제 API 키, 이메일 발송 서비스의 비밀번호 등 수십 개의 민감한 정보를 관리해야 합니다.
Secrets Manager를 사용하면 이 모든 것을 한곳에서 안전하게 관리할 수 있습니다. Netflix, Airbnb 같은 글로벌 기업들도 AWS Secrets Manager를 적극적으로 활용하고 있습니다.
보안은 선택이 아니라 필수이기 때문입니다. 하지만 주의할 점도 있습니다.
초보 개발자들이 흔히 하는 실수는 시크릿 값을 조회한 후 로그에 출력하는 것입니다. 디버깅을 위해 print문으로 비밀번호를 찍으면, 결국 로그 파일에 평문으로 남게 됩니다.
이렇게 하면 Secrets Manager를 사용하는 의미가 없어집니다. 또 다른 실수는 시크릿 이름을 너무 단순하게 짓는 것입니다.
예를 들어 "password"나 "key" 같은 이름은 나중에 시크릿이 많아지면 관리하기 어렵습니다. "환경/서비스/용도" 형식으로 명확하게 작성하는 것이 좋습니다.
다시 김개발 씨의 이야기로 돌아가 봅시다. 박시니어 씨의 설명을 들은 김개발 씨는 곧바로 코드를 수정했습니다.
하드코딩된 비밀번호를 삭제하고, Secrets Manager에서 조회하도록 변경했습니다. Secrets Manager를 제대로 이해하면 보안 사고를 미연에 방지하고, 안심하고 코드를 관리할 수 있습니다.
여러분도 오늘 배운 내용을 실제 프로젝트에 적용해 보세요.
실전 팁
💡 - 시크릿 이름은 "환경/서비스/용도" 패턴으로 작성하세요 (예: prod/rds/master-password)
- 절대 시크릿 값을 로그에 출력하지 마세요
- IAM 정책으로 최소 권한 원칙을 적용하세요
2. 시크릿 생성하기
박시니어 씨가 김개발 씨에게 말했습니다. "그럼 이제 직접 시크릿을 만들어 볼까요?" 김개발 씨는 AWS 콘솔을 열었지만, 어디서부터 시작해야 할지 막막했습니다.
시크릿 생성은 민감한 정보를 Secrets Manager에 저장하는 첫 단계입니다. AWS 콘솔이나 CLI, SDK를 통해 시크릿을 만들 수 있으며, 키-값 쌍으로 저장하거나 일반 텍스트로 저장할 수 있습니다.
한 번 생성하면 암호화되어 안전하게 보관되며, 버전 관리도 자동으로 이루어집니다.
다음 코드를 살펴봅시다.
import boto3
import json
client = boto3.client('secretsmanager', region_name='ap-northeast-2')
# 데이터베이스 자격 증명을 JSON 형태로 준비
secret_value = {
'username': 'admin',
'password': 'MySecurePassword123!',
'host': 'mydb.ap-northeast-2.rds.amazonaws.com',
'port': 3306
}
# 시크릿 생성
response = client.create_secret(
Name='prod/rds/mysql-credentials',
Description='MySQL 운영 DB 자격 증명',
SecretString=json.dumps(secret_value)
)
print(f"시크릿 ARN: {response['ARN']}")
김개발 씨는 화면을 뚫어지게 바라봤습니다. AWS 콘솔의 메뉴가 너무 많아서 어디로 가야 할지 모르겠습니다.
박시니어 씨가 친절하게 안내를 시작했습니다. "먼저 AWS 콘솔에서 Secrets Manager 서비스를 찾아보세요.
검색창에 'Secrets'라고 치면 바로 나올 거예요." 시크릿을 생성하는 방법은 크게 세 가지입니다. 첫 번째는 AWS 콘솔을 사용하는 방법입니다.
웹 브라우저에서 클릭 몇 번으로 시크릿을 만들 수 있어서 가장 직관적입니다. "Store a new secret" 버튼을 누르면 마법사가 단계별로 안내해줍니다.
두 번째는 AWS CLI를 사용하는 방법입니다. 터미널에서 명령어 한 줄로 시크릿을 생성할 수 있어서, 자동화 스크립트를 작성할 때 유용합니다.
개발 환경을 자동으로 세팅하는 스크립트에 포함시키면 매우 편리합니다. 세 번째는 위 코드처럼 SDK를 사용하는 방법입니다.
애플리케이션 코드 내에서 동적으로 시크릿을 생성해야 할 때 사용합니다. 예를 들어 새로운 고객이 가입할 때마다 전용 데이터베이스를 만들고 그 자격 증명을 저장하는 경우입니다.
시크릿을 생성할 때 중요한 점이 몇 가지 있습니다. 먼저 시크릿 이름을 신중하게 정해야 합니다.
나중에 수십, 수백 개의 시크릿을 관리하게 되면 이름만 보고도 용도를 알 수 있어야 합니다. 슬래시(/)를 사용해서 계층 구조로 만드는 것이 좋습니다.
예를 들어 "prod/rds/mysql-credentials"라는 이름을 보면, 이것이 운영 환경의 RDS MySQL 자격 증명이라는 것을 바로 알 수 있습니다. 반면 "mypassword"라는 이름은 나중에 혼란을 초래합니다.
다음으로 저장 형식을 결정해야 합니다. 단순히 API 키 하나만 저장한다면 일반 텍스트로 충분합니다.
하지만 데이터베이스 연결 정보처럼 여러 값을 함께 저장해야 한다면 JSON 형태가 훨씬 편리합니다. 위의 코드를 자세히 살펴보겠습니다.
secret_value 딕셔너리에는 데이터베이스 연결에 필요한 모든 정보가 들어있습니다. 사용자 이름, 비밀번호뿐만 아니라 호스트 주소와 포트까지 함께 저장합니다.
이렇게 하면 나중에 시크릿을 조회할 때 한 번에 모든 정보를 얻을 수 있습니다. create_secret 메서드의 Name 파라미터는 시크릿의 고유 식별자입니다.
같은 리전 내에서 중복될 수 없습니다. Description은 선택 사항이지만 꼭 작성하는 것이 좋습니다.
6개월 후에 이 시크릿이 무엇인지 기억하기 어려울 수 있기 때문입니다. SecretString에는 json.dumps로 변환한 JSON 문자열을 전달합니다.
이렇게 하면 Secrets Manager가 자동으로 암호화해서 저장합니다. 응답으로는 시크릿의 ARN(Amazon Resource Name)이 반환되는데, 이것이 시크릿의 고유 주소입니다.
실제 프로젝트에서는 어떻게 활용할까요? 스타트업에서 새로운 마이크로서비스를 배포한다고 가정해봅시다.
각 서비스마다 전용 데이터베이스, 외부 API 키, 암호화 키 등이 필요합니다. 배포 스크립트에 시크릿 생성 코드를 포함시키면, 서비스가 배포될 때 자동으로 필요한 시크릿이 만들어집니다.
또 다른 예로, 고객사별로 다른 데이터베이스를 사용하는 SaaS 서비스를 생각해보세요. 새 고객이 가입하면 전용 스키마를 생성하고, 그 자격 증명을 Secrets Manager에 저장합니다.
이후 해당 고객의 요청이 들어오면 저장된 시크릿으로 데이터베이스에 접근합니다. 하지만 주의할 점도 있습니다.
초보자들이 자주 하는 실수는 같은 이름으로 시크릿을 중복 생성하려는 것입니다. Secrets Manager는 같은 이름의 시크릿을 허용하지 않기 때문에 에러가 발생합니다.
시크릿을 업데이트하려면 create_secret이 아니라 update_secret을 사용해야 합니다. 또 다른 실수는 시크릿에 너무 많은 정보를 담는 것입니다.
한 시크릿에 10개 이상의 값을 저장하면 나중에 일부만 필요할 때도 전체를 조회해야 합니다. 논리적으로 관련된 정보끼리만 묶는 것이 좋습니다.
김개발 씨는 박시니어 씨의 설명을 들으며 직접 시크릿을 생성해봤습니다. 첫 번째 시도에서는 이름을 잘못 지어서 다시 만들었지만, 두 번째에는 성공했습니다.
"생각보다 간단하네요!" 시크릿 생성은 Secrets Manager 활용의 시작점입니다. 제대로 된 이름과 구조로 시크릿을 만들어두면, 나중에 관리가 훨씬 수월해집니다.
실전 팁
💡 - 시크릿 이름은 슬래시(/)로 계층화하여 관리하기 쉽게 만드세요
- Description을 반드시 작성해서 나중에 용도를 쉽게 파악하세요
- 관련된 정보끼리만 JSON으로 묶어서 저장하세요
3. 자동 로테이션
며칠 후, 보안팀에서 전사 공지가 내려왔습니다. "모든 데이터베이스 비밀번호는 90일마다 변경해야 합니다." 김개발 씨는 한숨을 쉬었습니다.
서비스 중단 없이 비밀번호를 바꾸려면 새벽에 작업해야 할 텐데요.
자동 로테이션은 시크릿의 값을 주기적으로 자동으로 변경하는 기능입니다. Lambda 함수를 사용해서 비밀번호를 새로 생성하고, 데이터베이스나 서비스에 적용한 후, Secrets Manager에 저장합니다.
사람이 직접 개입하지 않아도 보안 정책을 준수할 수 있어서 운영 부담이 크게 줄어듭니다.
다음 코드를 살펴봅시다.
import boto3
client = boto3.client('secretsmanager', region_name='ap-northeast-2')
# 자동 로테이션 설정
response = client.rotate_secret(
SecretId='prod/rds/mysql-credentials',
RotationLambdaARN='arn:aws:lambda:ap-northeast-2:123456789012:function:SecretsManagerRotation',
RotationRules={
'AutomaticallyAfterDays': 30 # 30일마다 자동 로테이션
}
)
# 로테이션 즉시 실행 (테스트용)
response = client.rotate_secret(
SecretId='prod/rds/mysql-credentials',
RotationLambdaARN='arn:aws:lambda:ap-northeast-2:123456789012:function:SecretsManagerRotation'
)
print("로테이션이 시작되었습니다.")
김개발 씨는 박시니어 씨에게 하소연했습니다. "90일마다 비밀번호를 바꾸라고 하는데, 어떻게 해야 할까요?
서비스 중단 없이 가능할까요?" 박시니어 씨는 미소를 지으며 대답했습니다. "걱정 마세요.
Secrets Manager의 자동 로테이션 기능을 사용하면 돼요. 한 번 설정해두면 알아서 바꿔줍니다." 자동 로테이션은 마치 자동차의 자동 변속기와 같습니다.
수동 변속기는 운전자가 직접 기어를 바꿔야 하지만, 자동 변속기는 상황에 맞게 알아서 변속합니다. 마찬가지로 자동 로테이션을 설정하면 지정한 주기마다 알아서 비밀번호가 변경됩니다.
비밀번호를 수동으로 변경하던 시절에는 어땠을까요? 먼저 새벽 시간을 잡아서 공지를 올립니다.
"오전 2시부터 4시까지 정기 점검이 있습니다." 그리고 야근을 시작합니다. 데이터베이스에 접속해서 비밀번호를 변경하고, 모든 애플리케이션 서버의 설정 파일을 수정한 후, 하나씩 재시작합니다.
문제는 이 과정에서 실수가 자주 발생한다는 것입니다. 한 서버를 빠뜨리면 그 서버만 데이터베이스에 접속할 수 없게 됩니다.
고객들은 에러를 경험하고, 개발팀은 긴급 복구에 나섭니다. 밤새 고생한 끝에 해가 뜨면 모두가 지쳐있습니다.
바로 이런 악몽을 끝내기 위해 자동 로테이션이 존재합니다. 자동 로테이션의 동작 원리는 다음과 같습니다.
먼저 지정된 주기가 되면 Secrets Manager가 Lambda 함수를 호출합니다. Lambda 함수는 네 단계로 로테이션을 수행합니다.
첫 번째는 createSecret 단계입니다. 새로운 비밀번호를 생성하고 Secrets Manager에 pending 버전으로 저장합니다.
아직 실제 데이터베이스에는 적용하지 않습니다. 두 번째는 setSecret 단계입니다.
생성한 새 비밀번호를 실제 데이터베이스에 적용합니다. RDS의 경우 ALTER USER 명령으로 비밀번호를 변경합니다.
세 번째는 testSecret 단계입니다. 새 비밀번호로 실제로 데이터베이스에 접속해봅니다.
정상적으로 연결되는지 확인하는 단계입니다. 네 번째는 finishSecret 단계입니다.
테스트가 성공하면 pending 버전을 current 버전으로 승격시킵니다. 이제 모든 애플리케이션이 새 비밀번호를 사용하게 됩니다.
위의 코드를 살펴보겠습니다. rotate_secret 메서드로 로테이션을 설정합니다.
RotationLambdaARN은 로테이션을 수행할 Lambda 함수의 ARN입니다. AWS는 RDS용 로테이션 함수 템플릿을 제공하므로, 대부분의 경우 직접 작성할 필요가 없습니다.
RotationRules의 AutomaticallyAfterDays는 로테이션 주기를 의미합니다. 30을 지정하면 30일마다 자동으로 비밀번호가 변경됩니다.
보안 정책에 따라 30일, 60일, 90일 등으로 설정할 수 있습니다. 실무에서는 어떻게 활용할까요?
금융권 서비스를 개발한다고 가정해봅시다. 금융감독원의 규정에 따라 모든 계정의 비밀번호를 60일마다 변경해야 합니다.
수십 개의 데이터베이스와 수백 개의 API 키가 있다면 수동으로 관리하는 것은 불가능합니다. 자동 로테이션을 설정해두면 모든 것이 자동으로 처리됩니다.
담당자는 로테이션 실패 알림만 모니터링하면 됩니다. 대부분의 경우 성공하므로, 업무 부담이 95% 이상 줄어듭니다.
Netflix의 경우 수천 개의 시크릿을 자동 로테이션으로 관리한다고 알려져 있습니다. 사람의 개입 없이 보안을 유지하는 것이 핵심입니다.
하지만 주의할 점이 있습니다. 로테이션 Lambda 함수에는 데이터베이스를 수정할 수 있는 권한이 필요합니다.
RDS의 마스터 계정처럼 비밀번호를 변경할 수 있는 권한이 있어야 합니다. 권한이 없으면 로테이션이 실패합니다.
또한 애플리케이션은 항상 Secrets Manager에서 최신 시크릿을 조회해야 합니다. 시작할 때 한 번만 조회하고 메모리에 캐싱하면, 로테이션 후에도 옛날 비밀번호를 계속 사용하게 됩니다.
캐싱하더라도 일정 시간 후에는 다시 조회하도록 구현해야 합니다. 김개발 씨는 자동 로테이션을 설정한 후 테스트해봤습니다.
30분 후 새 비밀번호로 바뀌었고, 애플리케이션은 아무 문제 없이 작동했습니다. "새벽 작업을 안 해도 되겠네요!" 자동 로테이션은 보안과 편의성을 동시에 잡는 강력한 기능입니다.
한 번 설정해두면 평생 편안합니다.
실전 팁
💡 - RDS 시크릿은 AWS 제공 Lambda 템플릿을 사용하면 간편합니다
- 애플리케이션에서 시크릿을 캐싱할 때는 TTL을 짧게 설정하세요
- 로테이션 실패 알림을 CloudWatch로 모니터링하세요
4. Lambda에서 시크릿 사용
김개발 씨는 이번에 Lambda 함수를 작성하게 되었습니다. 외부 API를 호출하는데 API 키가 필요합니다.
환경변수에 넣을까 고민하다가, 박시니어 씨의 조언이 떠올랐습니다. "Secrets Manager를 쓰세요."
Lambda에서 시크릿 사용은 서버리스 환경에서 안전하게 민감 정보를 다루는 방법입니다. Lambda 함수가 실행될 때 Secrets Manager에서 시크릿을 조회하고, 그 값으로 외부 서비스에 접근합니다.
환경변수보다 안전하고, 로테이션과 연동하면 자동으로 최신 값을 사용할 수 있습니다.
다음 코드를 살펴봅시다.
import boto3
import json
import requests
# Lambda 핸들러 외부에서 클라이언트 생성 (재사용 가능)
secrets_client = boto3.client('secretsmanager', region_name='ap-northeast-2')
def lambda_handler(event, context):
# 시크릿 조회
response = secrets_client.get_secret_value(
SecretId='prod/external-api/key'
)
# API 키 추출
secret = json.loads(response['SecretString'])
api_key = secret['api_key']
# 외부 API 호출
headers = {'Authorization': f'Bearer {api_key}'}
result = requests.get('https://api.example.com/data', headers=headers)
return {
'statusCode': 200,
'body': json.dumps(result.json())
}
김개발 씨는 Lambda 함수를 처음 작성해봅니다. 외부 날씨 API를 호출해서 데이터를 가져오는 간단한 함수입니다.
그런데 API 키를 어디에 저장해야 할지 고민입니다. "환경변수에 넣으면 되지 않을까?"라고 생각했지만, 박시니어 씨의 말이 떠올랐습니다.
"Lambda 환경변수는 암호화되긴 하지만, 콘솔에서 누구나 볼 수 있어요. Secrets Manager를 쓰는 게 훨씬 안전합니다." Lambda에서 시크릿을 사용하는 것은 마치 호텔에서 금고를 여는 것과 같습니다.
프론트에서 열쇠를 받아서 방으로 올라간 후 금고를 열고 귀중품을 꺼내는 것처럼, Lambda도 실행될 때마다 Secrets Manager에서 필요한 값을 꺼내 씁니다. Lambda 환경변수만 사용하던 시절에는 어땠을까요?
개발자는 Lambda 콘솔에 들어가서 환경변수에 API 키를 직접 입력했습니다. 간단하긴 하지만 문제가 많았습니다.
콘솔에 접근 권한이 있는 사람은 누구나 API 키를 볼 수 있었고, CloudTrail 로그에도 기록되었습니다. 더 큰 문제는 API 키를 변경할 때였습니다.
API 키가 유출되어 급하게 바꿔야 하는 상황이라면? Lambda 함수를 하나하나 찾아서 환경변수를 업데이트하고 재배포해야 했습니다.
함수가 50개라면 50번 반복입니다. Secrets Manager를 사용하면 이런 문제가 모두 해결됩니다.
첫째, 접근 권한을 정밀하게 통제할 수 있습니다. Lambda 실행 역할에만 시크릿 조회 권한을 부여하고, 사람에게는 권한을 주지 않으면 됩니다.
개발자도 콘솔에서 API 키를 볼 수 없게 만들 수 있습니다. 둘째, 키 변경이 즉시 반영됩니다.
Secrets Manager에서 값을 업데이트하면, 모든 Lambda 함수가 다음 실행부터 새 값을 사용합니다. Lambda 코드를 재배포할 필요가 없습니다.
셋째, 감사 로그가 상세하게 남습니다. 누가 언제 어떤 시크릿을 조회했는지 CloudTrail에 모두 기록됩니다.
보안 감사나 컴플라이언스 준수에 유리합니다. 위의 코드를 자세히 분석해보겠습니다.
먼저 주목할 점은 secrets_client를 lambda_handler 함수 밖에서 생성한다는 것입니다. Lambda는 같은 실행 환경을 재사용하기 때문에, 한 번 생성한 클라이언트를 여러 번 사용할 수 있습니다.
이렇게 하면 성능이 향상됩니다. lambda_handler 함수 안에서는 get_secret_value로 시크릿을 조회합니다.
반환된 값은 JSON 문자열이므로 json.loads로 파싱합니다. 여기서 api_key를 추출하여 외부 API 호출에 사용합니다.
requests 라이브러리로 외부 API를 호출할 때 Authorization 헤더에 API 키를 넣습니다. 이제 코드 어디에도 실제 API 키가 하드코딩되지 않았습니다.
모든 것이 안전합니다. 실무에서는 어떻게 활용할까요?
대규모 이커머스 플랫폼을 운영한다고 가정해봅시다. 주문이 들어오면 Lambda 함수가 결제 게이트웨이 API를 호출합니다.
결제 API 키는 절대 유출되어서는 안 되는 정보입니다. Secrets Manager에 결제 API 키를 저장하고, Lambda에서는 매번 조회해서 사용합니다.
만약 API 키가 유출되어 긴급하게 변경해야 한다면? Secrets Manager에서 값만 업데이트하면 모든 Lambda 함수가 즉시 새 키를 사용합니다.
실제로 Slack, Stripe 같은 서비스들이 이런 패턴을 권장하고 있습니다. 서버리스 환경에서 보안을 유지하는 표준 방법입니다.
하지만 주의할 점도 있습니다. Lambda 함수가 실행될 때마다 Secrets Manager를 호출하면 비용과 지연 시간이 증가합니다.
Secrets Manager API 호출은 10,000건당 0.05 USD입니다. Lambda가 초당 100번 실행된다면 비용이 만만치 않습니다.
이를 해결하려면 시크릿을 캐싱해야 합니다. AWS는 aws-secretsmanager-caching-python 같은 캐싱 라이브러리를 제공합니다.
한 번 조회한 시크릿을 일정 시간(예: 5분) 동안 메모리에 캐싱하여 재사용합니다. 또 다른 주의점은 Lambda 실행 역할에 올바른 권한을 부여해야 한다는 것입니다.
secretsmanager:GetSecretValue 권한이 없으면 시크릿을 조회할 수 없습니다. IAM 정책을 꼼꼼히 확인하세요.
김개발 씨는 Lambda 함수를 작성하고 테스트했습니다. 첫 실행에서는 권한 에러가 났지만, IAM 역할을 수정한 후에는 완벽하게 작동했습니다.
"이제 API 키가 유출될 걱정이 없겠네요!" Lambda와 Secrets Manager의 조합은 서버리스 보안의 모범 사례입니다. 안전하면서도 운영이 편리합니다.
실전 팁
💡 - aws-secretsmanager-caching 라이브러리로 비용을 절감하세요
- Lambda 실행 역할에 최소 권한만 부여하세요
- 시크릿 조회 실패 시 재시도 로직을 구현하세요
5. RDS 자격 증명 관리
어느 날 김개발 씨가 출근하니 팀장님이 심각한 표정으로 기다리고 있었습니다. "어제 누군가 개발 DB 비밀번호를 사내 위키에 올렸어요.
당장 비밀번호를 바꿔야 합니다." 김개발 씨는 머릿속이 하얘졌습니다.
RDS 자격 증명 관리는 데이터베이스의 마스터 비밀번호와 사용자 계정 정보를 Secrets Manager로 안전하게 관리하는 방법입니다. RDS와 Secrets Manager는 긴밀하게 통합되어 있어서, 자동 로테이션 설정이 매우 간단합니다.
한 번 설정하면 수동 개입 없이 주기적으로 비밀번호가 변경됩니다.
다음 코드를 살펴봅시다.
import boto3
import json
import pymysql
# Secrets Manager에서 RDS 자격 증명 조회
def get_db_credentials():
client = boto3.client('secretsmanager', region_name='ap-northeast-2')
response = client.get_secret_value(SecretId='prod/rds/mysql')
secret = json.loads(response['SecretString'])
return secret
# 데이터베이스 연결
def connect_to_database():
creds = get_db_credentials()
connection = pymysql.connect(
host=creds['host'],
user=creds['username'],
password=creds['password'],
database=creds['dbname'],
port=creds['port']
)
return connection
# 실제 사용
conn = connect_to_database()
cursor = conn.cursor()
cursor.execute("SELECT * FROM users LIMIT 10")
results = cursor.fetchall()
김개발 씨는 당황했습니다. 데이터베이스 비밀번호를 바꾸면 모든 서버에서 연결이 끊어집니다.
사용자들은 에러를 보게 되고, 서비스 장애가 발생합니다. 어떻게 해야 할까요?
박시니어 씨가 진정시켰습니다. "괜찮아요.
우리는 Secrets Manager로 RDS를 관리하고 있으니까요. 무중단으로 비밀번호를 변경할 수 있어요." RDS 자격 증명을 관리하는 것은 마치 집의 열쇠를 관리하는 것과 같습니다.
옛날에는 열쇠를 현관 화분 아래 숨겨두었지만, 이제는 디지털 도어락으로 안전하게 관리합니다. Secrets Manager도 마찬가지로 데이터베이스의 열쇠를 안전하게 보관합니다.
Secrets Manager를 사용하기 전에는 어땠을까요? 개발자들은 데이터베이스 비밀번호를 코드에 직접 작성하거나, 설정 파일에 넣어두었습니다.
새로운 팀원이 합류하면 Slack으로 비밀번호를 보내주었습니다. 퇴사자가 생기면 비밀번호를 바꿔야 하는데, 그러면 모든 서버를 재시작해야 했습니다.
더 큰 문제는 감사였습니다. "이 데이터베이스에 누가 접근할 수 있나요?"라는 질문에 명확히 답하기 어려웠습니다.
비밀번호를 알고 있는 사람이 누구인지 추적할 방법이 없었기 때문입니다. Secrets Manager로 RDS를 관리하면 모든 것이 달라집니다.
첫째, AWS 콘솔에서 클릭 몇 번으로 통합할 수 있습니다. RDS 데이터베이스를 생성할 때 "Manage master credentials in Secrets Manager" 옵션을 선택하면, AWS가 자동으로 시크릿을 만들고 연결해줍니다.
둘째, 자동 로테이션이 기본 제공됩니다. RDS 전용 Lambda 함수 템플릿이 있어서, 복잡한 코드를 작성할 필요가 없습니다.
로테이션 주기만 설정하면 끝입니다. 셋째, 무중단 로테이션이 가능합니다.
Secrets Manager는 이전 버전과 현재 버전을 동시에 유지합니다. 로테이션 중에도 애플리케이션은 이전 비밀번호로 계속 연결할 수 있어서 서비스 중단이 없습니다.
위의 코드를 살펴보겠습니다. get_db_credentials 함수는 Secrets Manager에서 RDS 자격 증명을 조회합니다.
반환된 JSON에는 host, username, password, dbname, port가 모두 포함되어 있습니다. AWS가 RDS 시크릿을 생성할 때 자동으로 이런 구조로 만들어줍니다.
connect_to_database 함수는 조회한 자격 증명으로 데이터베이스에 연결합니다. pymysql 라이브러리를 사용하지만, psycopg2(PostgreSQL)나 다른 드라이버도 동일한 방식으로 작동합니다.
중요한 점은 비밀번호가 코드 어디에도 하드코딩되지 않았다는 것입니다. 모든 것이 런타임에 동적으로 조회됩니다.
비밀번호가 바뀌어도 코드를 수정하거나 재배포할 필요가 없습니다. 실무에서는 어떻게 활용할까요?
대규모 SaaS 플랫폼을 운영한다고 가정해봅시다. 서비스별로 전용 RDS 인스턴스가 있고, 각각 다른 비밀번호를 사용합니다.
총 30개의 데이터베이스가 있습니다. 보안 정책상 모든 비밀번호를 60일마다 변경해야 합니다.
Secrets Manager 없이 이것을 수동으로 관리한다면? 매달 15개 데이터베이스의 비밀번호를 바꾸는 작업을 해야 합니다.
1년이면 180번입니다. Secrets Manager로 자동화하면 사람의 개입이 전혀 필요 없습니다.
실패 알림만 모니터링하면 됩니다. 운영 부담이 99% 사라집니다.
Amazon 내부에서도 수만 개의 RDS 인스턴스를 Secrets Manager로 관리한다고 알려져 있습니다. 규모가 커질수록 자동화의 가치는 더욱 커집니다.
하지만 주의할 점이 있습니다. 연결 풀을 사용하는 애플리케이션은 특별히 신경 써야 합니다.
애플리케이션 시작 시 한 번만 연결 풀을 만들고 계속 재사용한다면, 비밀번호가 로테이션되어도 옛날 연결을 계속 사용하게 됩니다. 해결 방법은 연결이 끊어졌을 때 새로 시크릿을 조회해서 재연결하는 것입니다.
또는 연결 풀의 최대 수명을 짧게 설정하여(예: 30분), 주기적으로 새 연결을 만들도록 합니다. 또 다른 주의점은 로테이션 Lambda 함수가 데이터베이스에 접근할 수 있어야 한다는 것입니다.
VPC 내부에 있는 RDS라면, Lambda도 같은 VPC에 있어야 합니다. 네트워크 설정을 꼼꼼히 확인하세요.
김개발 씨는 팀장님과 함께 RDS 비밀번호를 Secrets Manager로 변경했습니다. 자동 로테이션도 설정했습니다.
"이제 사람 실수로 비밀번호가 유출되어도 걱정 없겠네요." RDS와 Secrets Manager의 조합은 데이터베이스 보안의 필수 요소입니다. 설정은 한 번, 혜택은 영원히 누립니다.
실전 팁
💡 - RDS 생성 시 "Manage in Secrets Manager" 옵션을 활성화하세요
- 연결 풀 사용 시 재연결 로직을 구현하세요
- Lambda 로테이션 함수는 VPC 설정을 정확히 맞추세요
6. SDK로 시크릿 조회
김개발 씨는 이제 Secrets Manager를 자유자 재로 사용할 수 있게 되었습니다. 하지만 Python만 알고 있습니다.
"다른 언어로도 똑같이 할 수 있을까요?" 박시니어 씨가 답했습니다. "물론이죠.
AWS SDK는 모든 주요 언어를 지원해요."
SDK로 시크릿 조회는 다양한 프로그래밍 언어에서 Secrets Manager를 사용하는 방법입니다. Python, Java, Node.js, Go, .NET 등 모든 주요 언어용 SDK가 제공되며, 사용 패턴은 거의 동일합니다.
언어와 상관없이 안전하게 시크릿을 조회하고 활용할 수 있습니다.
다음 코드를 살펴봅시다.
# Python SDK (boto3)
import boto3
import json
client = boto3.client('secretsmanager', region_name='ap-northeast-2')
response = client.get_secret_value(SecretId='my-secret')
secret = json.loads(response['SecretString'])
# Node.js SDK (AWS SDK v3)
# const { SecretsManagerClient, GetSecretValueCommand } = require("@aws-sdk/client-secrets-manager");
# const client = new SecretsManagerClient({ region: "ap-northeast-2" });
# const response = await client.send(new GetSecretValueCommand({ SecretId: "my-secret" }));
# const secret = JSON.parse(response.SecretString);
# Java SDK
# SecretsManagerClient client = SecretsManagerClient.builder().region(Region.AP_NORTHEAST_2).build();
# GetSecretValueRequest request = GetSecretValueRequest.builder().secretId("my-secret").build();
# GetSecretValueResponse response = client.getSecretValue(request);
# String secretString = response.secretString();
김개발 씨는 궁금했습니다. 회사에서는 Python을 주로 쓰지만, 새 프로젝트는 Node.js로 개발하기로 했습니다.
Secrets Manager를 계속 사용할 수 있을까요? 박시니어 씨는 자신 있게 대답했습니다.
"AWS SDK는 거의 모든 프로그래밍 언어를 지원해요. 사용 방법도 비슷해서 금방 익힐 수 있어요." SDK로 시크릿을 조회하는 것은 마치 국제 표준 플러그를 사용하는 것과 같습니다.
나라마다 콘센트 모양은 다르지만, 어댑터만 있으면 어디서든 전자기기를 사용할 수 있습니다. 마찬가지로 언어만 다를 뿐, 시크릿 조회의 본질은 동일합니다.
AWS SDK를 사용하기 전에는 어땠을까요? 개발자들은 HTTP API를 직접 호출해야 했습니다.
AWS 서명 버전 4로 요청을 서명하고, 복잡한 헤더를 구성하고, 에러를 파싱해야 했습니다. 코드가 길어지고 실수하기 쉬웠습니다.
각 언어마다 다른 방식으로 구현해야 했기 때문에, 다국어 프로젝트에서는 일관성을 유지하기 어려웠습니다. Python 팀과 Java 팀이 각자 다른 방식으로 시크릿을 조회하면 유지보수가 복잡해졌습니다.
AWS SDK를 사용하면 이런 문제가 모두 해결됩니다. 첫째, 모든 복잡한 작업이 추상화되어 있습니다.
AWS 인증, 서명, 재시도 로직 등을 SDK가 알아서 처리합니다. 개발자는 get_secret_value 같은 간단한 메서드만 호출하면 됩니다.
둘째, 언어별 관습을 따릅니다. Python에서는 딕셔너리와 snake_case를, Java에서는 객체와 camelCase를 사용합니다.
각 언어의 네이티브 개발자가 자연스럽게 느낄 수 있도록 설계되었습니다. 셋째, 에러 처리가 표준화되어 있습니다.
모든 SDK가 동일한 예외 구조를 사용하므로, 한 언어에서 배운 에러 처리 지식을 다른 언어에서도 활용할 수 있습니다. 위의 코드를 비교해보겠습니다.
Python 버전은 boto3 라이브러리를 사용합니다. client.get_secret_value로 시크릿을 조회하고, json.loads로 파싱합니다.
매우 간결하고 읽기 쉽습니다. Node.js 버전은 AWS SDK v3을 사용합니다.
모듈식 구조로 바뀌어서 필요한 클라이언트와 명령만 임포트합니다. async/await 패턴을 사용하여 비동기 처리를 자연스럽게 합니다.
Java 버전은 빌더 패턴을 사용합니다. SecretsManagerClient를 빌드하고, GetSecretValueRequest를 만들어서 전달합니다.
타입 안전성이 보장되어 컴파일 시점에 오류를 잡을 수 있습니다. 문법은 다르지만 본질은 같습니다.
클라이언트를 만들고, 요청을 보내고, 응답을 파싱하는 패턴이 일관되게 유지됩니다. 실무에서는 어떻게 활용할까요?
마이크로서비스 아키텍처를 채택한 회사를 생각해봅시다. 사용자 서비스는 Java로, 결제 서비스는 Node.js로, 데이터 분석 파이프라인은 Python으로 개발되었습니다.
각 서비스가 다른 언어를 사용하지만, 모두 Secrets Manager로 시크릿을 관리합니다. 새로운 개발자가 팀에 합류하면 "Secrets Manager 사용법"이라는 문서 하나만 읽으면 됩니다.
언어만 바꿔서 동일한 패턴을 적용하면 되기 때문입니다. 학습 비용이 크게 줄어듭니다.
Spotify, Netflix 같은 대규모 서비스들도 다양한 언어로 개발하면서 Secrets Manager를 공통으로 사용합니다. 일관된 보안 정책을 유지하면서도 각 팀이 선호하는 언어를 쓸 수 있습니다.
하지만 주의할 점이 있습니다. SDK 버전에 따라 사용법이 다를 수 있습니다.
특히 Node.js는 AWS SDK v2와 v3가 완전히 다른 구조를 가집니다. 최신 문서를 참고하여 올바른 버전을 사용하세요.
또한 각 언어의 비동기 처리 방식을 이해해야 합니다. Python은 기본적으로 동기이지만 asyncio를 사용할 수 있고, Node.js는 기본이 비동기입니다.
언어의 특성에 맞게 코드를 작성해야 합니다. 캐싱 라이브러리도 언어별로 다릅니다.
Python은 aws-secretsmanager-caching, Java는 aws-secretsmanager-caching-java를 사용합니다. 공식 라이브러리를 사용하면 검증된 캐싱 전략을 적용할 수 있습니다.
김개발 씨는 Node.js로 동일한 기능을 구현해봤습니다. Python에서 배운 개념을 그대로 적용하니 금방 완성되었습니다.
"언어가 달라도 원리는 같네요!" SDK를 활용하면 어떤 언어를 사용하든 Secrets Manager의 강력한 기능을 누릴 수 있습니다. 한 번 배우면 평생 쓸 수 있는 지식입니다.
실전 팁
💡 - 사용하는 언어의 최신 SDK 버전과 문서를 확인하세요
- 공식 캐싱 라이브러리를 사용하여 성능을 최적화하세요
- 에러 처리를 빠뜨리지 말고 재시도 로직을 구현하세요
이상으로 학습을 마칩니다. 위 내용을 직접 코드로 작성해보면서 익혀보세요!
댓글 (0)
함께 보면 좋은 카드 뉴스
Helm 마이크로서비스 패키징 완벽 가이드
Kubernetes 환경에서 마이크로서비스를 효율적으로 패키징하고 배포하는 Helm의 핵심 기능을 실무 중심으로 학습합니다. Chart 생성부터 릴리스 관리까지 체계적으로 다룹니다.
보안 아키텍처 구성 완벽 가이드
프로젝트의 보안을 처음부터 설계하는 방법을 배웁니다. AWS 환경에서 VPC부터 WAF, 암호화, 접근 제어까지 실무에서 바로 적용할 수 있는 보안 아키텍처를 단계별로 구성해봅니다.
AWS Organizations 완벽 가이드
여러 AWS 계정을 체계적으로 관리하고 통합 결제와 보안 정책을 적용하는 방법을 실무 스토리로 쉽게 배워봅니다. 초보 개발자도 바로 이해할 수 있는 친절한 설명과 실전 예제를 제공합니다.
AWS KMS 암호화 완벽 가이드
AWS KMS(Key Management Service)를 활용한 클라우드 데이터 암호화 방법을 초급 개발자를 위해 쉽게 설명합니다. CMK 생성부터 S3, EBS 암호화, 봉투 암호화까지 실무에 필요한 모든 내용을 담았습니다.
AWS WAF 웹 방화벽 완벽 가이드
웹 애플리케이션을 악의적인 공격으로부터 보호하는 AWS WAF의 핵심 개념과 실무 활용법을 초급 개발자도 쉽게 이해할 수 있도록 풀어낸 가이드입니다. SQL Injection, XSS 공격 방어부터 속도 제한까지 실전 예제로 배웁니다.