App Runner에서 앱이 뜨질 않는다 — 로그도 없이
Docker 이미지 pull은 성공했다. App Runner 콘솔엔 ROLLBACK_SUCCEEDED만 뜬다. 로그를 보니 Failed to configure a DataSource. 이상하다. 로컬에서는 잘 됐는데.
Failed to configure a DataSource: 'url' attribute is not specified
원인을 찾기까지 꽤 많이 돌아갔다. 겪은 순서대로 기록한다.
디버깅 타임라인
apprunner:ListServices 권한 거부
CD 워크플로우에서 aws apprunner list-services 호출 시 AccessDeniedException.
ListServices는 특정 ARN으로 제한 불가 — Resource: "*" 필요ListServices를 별도 Statement로 분리
{ "Sid": "AppRunnerList", "Action": ["apprunner:ListServices"], "Resource": "*" }
Terraform state S3 접근 불가
Infrastructure 워크플로우에서 s3:GetObject 권한 거부.
로컬에서 terraform apply로 bootstrap
S3, DynamoDB(state lock) 권한을 로컬에서 직접 적용. 이후 CI에서 정상 동작.
IAM 인라인 정책 2KB 제한 초과
LimitExceeded: Maximum policy size of 2048 bytes exceeded for user
인라인 정책 → Managed Policy 전환
aws_iam_user_policy(2KB 한도) → aws_iam_policy + aws_iam_user_policy_attachment(6KB)
ssm:DescribeParameters 권한 거부
Terraform이 SSM Parameter metadata 조회 시 권한 누락. 이것도 Resource: "*" 필요.
App Runner 앱 시작 실패 — DataSource 설정 오류
여기까지 해결하고 배포했는데, 앱이 뜨질 않는다. ParameterStorePropertySource의 로그가 전혀 없다.
의심 1: AWS_REGION 누락 → 추가해봤지만 해결 안 됨
의심 2: VPC Endpoint 필요? → NAT Instance 경유로 SSM 접근 가능해야 함
EnvironmentPostProcessor 자체가 호출되지 않는다
로그 코드를 추가했지만 "Loading SSM parameters..." 한 줄도 없었다. 클래스 로딩 자체가 실패하고 있었다.
bootJar 안에 AWS SDK JAR이 없다
$ unzip -l *.jar | grep "aws.*ssm"
(결과 없음!)
$ unzip -l *.jar | grep "SClass-Infrastructure"
BOOT-INF/lib/SClass-Infrastructure-0.0.1-SNAPSHOT-plain.jar
Infrastructure JAR은 있는데 AWS SSM SDK JAR이 bootJar에 포함되지 않고 있었다.
implementation → api 스코프 변경
// Before — 전이 의존성 전파 안 됨
implementation("software.amazon.awssdk:ssm")
// After — bootJar에 포함됨
api("software.amazon.awssdk:ssm")
근본 원인
implementation은 전이 의존성을 전파하지 않는다.SClass-Infrastructure가 implementation으로 AWS SDK를 선언하면, 이를 의존하는 SClass-Api-Supporters의 bootJar에 AWS SDK JAR이 포함되지 않는다.결과:
ParameterStorePropertySource가 SsmClient 클래스를 못 찾아 조용히 실패 → SSM 값 미주입 → DataSource 설정 없음 → 앱 시작 실패
교훈
| 주제 | 배운 것 |
|---|---|
implementation vs api | 런타임에 다른 모듈이 사용해야 하는 의존성은 api로 선언 |
EnvironmentPostProcessor | 클래스 로딩 실패 시 로그 없이 무시됨. 디버깅이 매우 어려움 |
| IAM List/Describe API | ListServices, DescribeParameters 등은 Resource: "*"로만 동작 |
| IAM 인라인 정책 | 2048바이트 제한 — 권한이 많으면 Managed Policy 사용 |
| Terraform IAM bootstrap | deployer 권한 추가는 닭과 달걀 — 로컬에서 직접 적용 필요 |
| bootJar 디버깅 | unzip -l *.jar | grep "라이브러리"로 의존성 포함 여부 확인 |