RDS 연결 - DataGrip
General 탭
- 실제 목적지인 RDS, 즉 DB와 연결시켜주는 역할을 한다. RDS, EC2 생성 이후에 DataGrip 들어가서 하면 된다.
- 입력값
- Host: RDS > 연결 및 보안 > 엔드로인트 및 포트 > 엔드포인트 복붙하면 된다
- Authentication: User & Password
- RDS 생성 당시 사용했던 마스터 사용자 이름과 암호를 각각 User, Password에 입력해주면 된다
- Database: 이것 또한 RDS 생성 당시 정할 수 있다. 기본값은 postgres이다 (PostgreSQL을 사용할 경우).

만약에 설정 정보를 잊었다면, RDS 인스턴스 > 구성 (Configuration) 에서 찾아보면 된다.

SSH/SSL 탭
- 위와 같이 아무리 RDS 설정 정보를 넣어준다 해도 EC2가 없으면 연결할 수 없다. RDS 데이터베이스는 외부 인터넷에서 직접 접근할 수 없도록 Private Network에 격리되어 있기 때문이다.
- EC2는 그 Private Network에 접근할 수 있는 유일한 '관문' 역할을 한다 -> 외부에서 접속 가능한 Public IP 주소를 가지고 있다.
- 따라서, 먼저 외부에서 접근 가능한 EC2에 SSH로 접속해서 일단 AWS 내부망으로 진입하고, 이 SSH 연결이 바로 그 '보안 통로'가 되는 것이다.

- 우선 SSH 터널링을 통해 RDS에 연결하기 위해서 먼저 EC2의 SSH 정보를 등록줘야 한다. Datasource -> SSH/SSL 옵션을 클릭해서 Add configuration 하면 된다.
- 입력값
- Host: EC2 인스턴스의 호스트 주소/퍼블릭 IP를 사용한다.
- Authentication Type: Key Pair
- EC2 인스턴스 생성 시 다운로드 했던 pem 파일을 사용한다.
- Test Connection 버튼을 누르고 Successfully connected!라고 뜨면 된거다.
흐름 정리
- DataGrip → EC2로 SSH 터널을 만든다. (성공)
- 그 터널을 통해 EC2 → RDS 엔드포인트로 데이터베이스 연결을 전달한다.
- 연결이 성공적으로 이루어진다. (굿)
여기까지 이해한 후 조금 의아했는데, 어떻게 EC2와 RDS가 연결돼었을지 생각해봤다. 그래서 AWS 콘솔을 봤는데, 이 흐름이 가능한 이유는 EC2와 RDS는 같은 보안 그룹에 있기 때문이었다.
데이터베이스와 사용자, 테이블을 초기화
이제 DataGrip에서 초기화 시켜준다.
console [sprint8]:
-- 1. 새 유저 'discodeit_user' 생성 (비밀번호는 원하는 값으로 설정)
CREATE USER discodeit_user WITH PASSWORD 'discodeit1234';
-- 2. postgres 계정은 AWS RDS 환경 특성상 완전한 super user가 아니므로, discodeit_user에 대한 권한을 추가로 부여해야함.
GRANT discodeit_user TO postgres;
-- 3. 'discodeit' 데이터베이스 생성 (소유자는 'discodeit_user')
CREATE DATABASE discodeit OWNER discodeit_user;
-- 4. schema.sql 실행하여 테이블 생성

- schema.sql을 DataGrip에서 새로운 창으로 연다음에, 오른쪽 위에 보이는 것처럼 discodeit.public과 sprint8을 설정해주면 된다.
- 그러면 이렇게 discodeit db를 열어보면 잘 생성된걸 볼 수 있다.

여기까지 왔으면 EC2는 삭제하라고 스펙에 나와있어서 삭제를 했다.
왜 삭제해도 괜찮은지 내가 이해한 바로는... 내가 만들었던 EC2 인스턴스(rds-ssh)는 데이터베이스 초기 설정을 위한 임시 연결 통로 역할이여서다.
- 이제 RDS 연결 + DB 생성 + 테이블 생성이 다 끝났으므로 EC2는 필요없게 된것이다.
- (또 과금을 막기 위해..!)
RDS 인스턴스와 데이터베이스 이해하기
일단 방금 만들었던 discodeit DB나 postgres DB는 AWS 콘솔에서 볼 수 없고, 그게 정상이다.
- RDS: PostgreSQL 데이터베이스 소프트웨어가 실행될 가상 서버 환경을 설정하고 제어하는 역할이다
- 관리하는 것들:
- DB 인스턴스(서버)의 사양 (CPU, 메모리, 저장 공간 크기)
- 네트워크 및 방화벽 설정 (보안 그룹)
- 자동 백업 및 유지보수 일정
- 서버의 전반적인 상태 모니터링 (CPU 사용률 등)
- 한마디로, PostgreSQL이라는 소프트웨어가 잘 동작할 수 있도록 하드웨어와 환경을 제공하는 것에 집중하는게 역할이다. 즉, 데이터베이스들을 담는 서버라고 이해하면 된다.
- 관리하는 것들:
- DataGrip
- DataGrip은 데이터베이스 소프트웨어 자체를 직접 제어하고 관리하는 도구다. RDS가 제공한 서버 환경에 접속해서, 그 안에서 동작하는 PostgreSQL에 직접 명령을 내린다.
- 이미 만들어진 서버 환경 내부로 들어가서 실제 데이터와 구조를 다우는 것에 집중한다.
ECR 연결
- ECR에서 discodeit이라는 public repository를 만들어줬다.
- 이제 intellij에서 프로젝트를 빌드하고 이 discodeit repo에 올려주면 된다
- IAM 유저를 만들고 AmazonElasticContainerRegistryPublicFullAccess 권한을 주고 aws configure해준다
- AWS CLI로 터미널에서 로그인 해준다
-
aws ecr-public get-login-password --region us-east-1 | docker login --username AWS --password-stdin public.ecr.aws/q1g5n6n3
-
- AWS 콘솔에서 discodeit 리포의 URI를 가져온다
- 이 URI와 buildx를 사용해서 push하면 된다
사용하는 buildx 명령어
docker buildx build --platform linux/amd64,linux/arm64
-t <URI>/discodeit:latest
-t <URI>/discodeit:1.2-M8
--push .
내 경우는:

docker buildx build --platform linux/amd64,linux/arm64
-t public.ecr.aws/q1g5n6n3/discodeit:latest
-t public.ecr.aws/q1g5n6n3/discodeit:1.2-M8
--push .
이렇게 해주면 됐었다.
작동하는 이유
- 이미지 태그(URI) 자체는 어디로 푸시할지에 대한 완전한 주소 역할을 한다.
- 도커 이미지 형식: [레지스트리 주소]/[저장소 이름]:[태그]
- Docker Hub - username 사용
- Docker Hub에 푸시할 때는 my-username/my-repo:latest 와 같은 형식을 사용한다
- 이것은 사실 단축된 형태다 -> 도커 클라이언트는 앞에 레지스트리 주소가 없으면 기본값인 Docker Hub의 주소, docker.io를 자동으로 붙힌다!
- 그래서 my-username/my-repo의 전체 주소는 사실 docker.io/my-username/my-repo다
- ECR - URI 사용
- ECR URI는 이미지를 저장할 서버의 완전한 주소 그 자체다. 그래서 도커는 그 주소로 이미지를 바로 전송할 수 있다
- Docker Hub - username 사용
ECS
이제 ECR을 만들고 거기에 도커 이미지를 저장했으면 그 저장된 도커 이미지를 실제로 실행하고 관리하기 위해서 ECS를 만들어야한다.
- ECR은 이미지 보관창고 역할만 가지고 있고, ECS 는 그 이미지를 가져와서 실제로 어플리케이션으로 동작시키는 엔진 역할을 한다.
- 그래서 ECS는 ECR에서 이미지를 가져와 AWS의 서버(EC2 또는 Fargate) 위에서 컨테이너로 실행시켜야한다.
먼저 discodeit.env를 만들어서 이미 만들어놓은 S3 버킷에 올려뒀다:
# Spring Configuration
SPRING_PROFILES_ACTIVE=prod
# Application Configuration
STORAGE_TYPE=s3
AWS_S3_ACCESS_KEY=엑세스_키
AWS_S3_SECRET_KEY=시크릿_키
AWS_S3_REGION=ap-northeast-2
AWS_S3_BUCKET=버킷_이름
AWS_S3_PRESIGNED_URL_EXPIRATION=600
# DataSource Configuration
RDS_ENDPOINT=RDS_엔드포인트(포트 포함)
SPRING_DATASOURCE_URL=jdbc:postgresql://${RDS_ENDPOINT}/discodeit
SPRING_DATASOURCE_USERNAME=RDS_유저네임(DataGrip을 통해 생성했던 유저)
SPRING_DATASOURCE_PASSWORD=RDS_비밀번호
# JVM Configuration (프리티어 고려)
# JVM_OPTS="-Xmx384m -Xms256m -XX:MaxMetaspaceSize=64m -XX:+UseSerialGC"
JAVA_TOOL_OPTIONS=-Xmx384m -Xms256m -XX:MaxMetaspaceSize=128m -XX:+UseSerialGC
참고로 저렇게 JVM_OPTS를 사용하면 에러가 떠서 JAVA_TOOLS_OPTIONS를 사용하는 것으로 바꿔줬다.
(또한 자꾸 OutOfMemoryError이 떠서 MaxMetaspaceSize=64를 128로 늘려주었다.
그리고
- 주어진 스펙대로 AWS ECS 콘솔에서 클러스터를 생성해줬는다.
원래 스펙에는 t2.micro를 사용하라고 적혀져있었다. 하지만 t2.micro를 사용해보니까 배포가 자꾸 실패했었는데, 이런 에러가 떴었다: Launching a new EC2 instance. Status Reason: The specified instance type is not eligible for Free Tier. For a list of Free Tier instance types, run 'describe-instance-types' with the filter 'free-tier-eligible=true'. Launching EC2 instance failed.클러스터 구성 > 클러스터 이름 discodeit-cluster 인프라 > AWS Fargate(서버리스) 체크해제 과금 주의 인프라 > Amazon EC2 인스턴스 체크 인프라 > EC2 인스턴스 유형 t3.micro (원래 t2.mirco) 과금 주의 인프라 > 원하는 용량 최소 0, 최대 1 과금 주의 인프라 > SSH 키 페어 새 키 페어 생성 후 지정
그래서 찾아보니까 t2.micro는 더이상 프리티어가 아니라서 t3.micro를 써야한다는 것이였다. - 태스트 정의
discodeit 클러스터 상세 화면에서 서비스를 생성태스크 정의 구성 > 태스크 정의 패밀리 discodeit-task 인프라 요구 사항 > 시작 유형 AWS Fargate: 체크 해제, Amazon EC2 인스턴스: 체크 인프라 요구 사항 > 네트워크 모드 bridge 인프라 요구 사항 > 태스크 크기 CPU: 0.25 vCPU, 메모리: 0.5 GB 컨테이너-1 > 컨테이너 세부 정보 이름: discodeit-app, 이미지 URI: 이전에 배포한 이미지 컨테이너-1 > 포트 매핑 호스트 포트: 80, 컨테이너 포트: 80 컨테이너-1 > 리소스 할당 제한 - 조건부 CPU: 0.25 vCPU, 메모리 하드 제한: 0.5 GB, 메모리 소프트 제한: 0.25 GB 컨테이너-1 > 환경 변수 - 선택 사항 > 파일에서 추가 이전에 S3에 업로드한 discodeit.env 파일 지정
배포 구성 > 태스크 정의 패밀리 discodeit-task 배포 구성 > 서비스 이름 discodeit-service 배포 구성 > 원하는 태스크 1 기본값 배포 구성 > 상태 검사 유예 기간 30초 - 태스크의 EC2 보안 그룹의 인바운드 규칙을 설정하여 어디서든 접근할 수 있도록 변경.
- EC2 보안 그룹 인바운드 규칙을 편집: 규칙 유형으로 HTTP를 선택 + 소스로 Anywhere-IPv4를 선택하여 모든 IP를 허용
discodeit-service > 로그로 들어가보면 잘 작동하는 것을 볼 수 있다!

이제 만들어지고 실행중인 EC2 인스턴스의 퍼플릭 IP 주소에 연결해보면:

이런식으로 에러가 떴었다.......
그래서 diescodeit-service에서 로그를 읽어보니까 이런 에러가 있었다:

?? 하면서 로그 에러를 구글링하면서 찾아보고 있었는데, 알고보니까 그냥 https -> http로 바꿔서 접속해주면 되는거였다..
- 서버(Tomcat)는 현재 HTTP라는 언어로만 대화할 수 있도록 설정되어서 간단한 POST/GET 메서드로 요청이 들어올거라고 예상을 한다. 하지만 HTTPS는 http method 앞에 암호 신호를 넣어주므로 톰캣 입장에선 http method가 아니니까 IllegalArgumentException을 던지는 것이다.
이제 http로 접속해주면 잘 뜬다!

'Codeit > 스프린트 과제' 카테고리의 다른 글
| [sprint8] 심화: CI/CD 파이프라인 + 버그와 해결방법들 (2) | 2025.08.28 |
|---|---|
| [sprint8] S3 관련 코드 + S3Client와 Presigned Url (3) | 2025.08.25 |
| [sprint8] 어플리케이션 컨테이너화 - dockerfile, docker compose, docker volume (1) | 2025.08.22 |
| [sprint5] 과제에서 사용한 swagger 간단하게 정리 (0) | 2025.07.14 |
| [sprint4] IOException과 @Transactional (멘토님 피드백) (0) | 2025.07.14 |