일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
- select
- join
- 카카오코테
- 안드로이드스튜디오
- 혼공단
- 코테
- Kotlin
- 자바
- SQL
- 티스토리챌린지
- MySQL
- Til
- 인프런
- 자료구조
- 안드로이드
- 코틀린
- doitandroid
- 오블완
- 스터디
- java
- 기술면접
- Android
- 프로그래머스
- CS
- 혼공챌린지
- 알고리즘
- groupby
- 혼공파
- 정보처리기사
- 정처기
- Today
- Total
Welcome! Everything is fine.
[AWS] EC2와 RDS를 연결해보자🔗(+Elastic IP, health check, security groups) 본문
이번 개인 과제 중 AWS를 실습하는 부분이 있는데, 요구사항은 다음과 같다. 먼저 EC2와 RDS를 구축하고 연결하는 과정을 기록해보려고 한다.✍🏻
✔️ EC2
- EC2 인스턴스에서 어플리케이션을 실행한다.
- 탄력적 IP를 설정해 외부에서도 접속할 수 있도록 한다.
- 서버 접속 및 Live 상태를 확인할 수 있는 health check API를 만든다.
✔️ RDS
- RDS 데이터베이스를 구축한다.
- EC2에서 실행되는 어플리케이션에 연결한다.
✔️ S3
- S3 버킷을 생성한다.
- 유저의 프로필 이미지 업로드 및 관리 API를 구현한다.
프로젝트를 EC2에 배포하기
로컬에서 프로젝트 빌드하기
인텔리제이에서 프로젝트를 빌드해보자! EC2 인스턴스는 이미 만들어놨다는 가정 하에 진행하겠다.
1) Gradle 탭에서 Task - build에서 왼쪽에 톱니바퀴 모양이 있는 build를 두 번 클릭한다.

2) BUILD SUCCESSFUL 메시지가 뜨고 빌드가 정상적으로 수행되었다면 프로젝트에서 build - libs에 생긴 파일을 확인한다.

여기서 expert-0.0.1-SNAPSHOT.jar 파일을 EC2로 보내야 한다.

🤔 .jar 파일이 뭐길래...?
- Java ARchive (자바 아카이브) 파일의 줄임말.
- Spring Boot 프로젝트 전체를 하나로 압축한 실행 파일이다.
- 내가 작성한 소스 코드, 사용하는 라이브러리, 설정 파일, 실행 메타 정보 등이 전부 들어있다.
- 따라서 이 파일만 보내면 EC2에서도 별다른 설치 없이 바로 실행할 수 있다!
⚠️ 빌드 과정에서 발생한 오류
- Error creating bean with name 'jwtAuthenticationFilter' defined in file ... 오류
- JwtAuthenticationFilter 클래스가 JwtUtil을 주입받으려고 했는데 스프링 컨테이너에 JwtUtil 빈이 등록되어 있지 않아 발생한 오류이다.
- JwtUtil을 Mock으로 주입해 해결했다.
- Spring Security 인증이 걸리는 테스트가 있어 인증 객체가 필요하다는 문제가 있었다.
- @WithMockUser을 추가해 테스트용으로 가짜 인증 객체(SecurityContext)에 넣어 해결했다.
EC2에 .jar 파일 보내고 실행하기
1) 로컬에서 .jar 파일을 EC2로 보낸다. 로컬에서 다음 명령어를 입력한다.
나는 window라서 wsl에서 입력했다.
scp -i key.pem build/libs/expert-0.0.1-SNAPSHOT.jar ubuntu@EC2_IP:/home/ubuntu/
혹시 key.pem과 빌드된 파일이 다른 곳에 있다면 각 경로를 입력해줘야 한다. 나는 각자 다른 곳에 있어서 다음과 같이 경로를 하나하나 입력했다. 만약 잘 전송됐다면 왼쪽에 파일명이 뜨고 오른쪽에 100% 라고 뜰 것이다.

2) EC2에 접속한다.
key.pem이 있는 폴더에서 다음과 같이 입력한다.
ssh -i key.pem ubuntu@EC2_IP
이렇게 Welcome to Ubuntu~라는 글자가 나오면 정상적으로 접속된 것이다.

3) EC2에서 Spring boot 서버를 백그라운드로 실행한다.
우선 ls 명령어를 통해 실제로 EC2에 .jar 파일이 있는지 확인한다. 파일이 제대로 있다면 다음 명령어를 입력한다.
nohup java -jar expert-0.0.1-SNAPSHOT.jar &
- nohup : no hang up의 줄임말로, 터미널 연결이 끊겨도 프로세스가 죽지 않고 계속 실행된다. 로그는 기본적으로 nohup.out 파일에 저장된다.
- java -jar expert-0.0.1-SNAPSHOT.jar : java 명령어로 .jar 파일을 실행한다. Tomcat이 내장되어있어 8080 포트에서 바로 실행된다.
- & : 해당 명령어를 백그라운드로 실행한다. 터미널에서 바로 다음 명령어를 입력할 수 있고, 실행된 프로세스는 PID를 부여받아 별도로 동작한다.
서버가 잘 실행된다면 다음과 같이 뜰 것이다.

- [1] : 백그라운드 작업 번호
- 16824 : 실행된 프로세스의 PID (Process ID)
- nohup: ignoring input and appending output to 'nohup.out' : 터미널 입력을 무시하고 모든 출력(로그)을 nohup.out 파일에 저장하겠다는 의미
⚠️ 배포 과정에서 발생한 오류
- MySQL 연결 실패 오류 발생
- DB URL에서 localhost로 되어 있으면 EC2가 자기 자신을 찾다가 오류가 발생한다고 한다.
- 이때는 RDS를 구축하지 않은 상태여서 일단 DB 연결 없이 서버만 실행하는 방향으로 시도했다.
- 따라서 아래와 같이 application.properties에서 DB 설정을 주석 처리한후 다시 빌드했다.
- 8080 포트를 이미 다른 프로세스가 잡고 있는 문제 발생
- 새로 빌드하고 배포 후 다시 실행하려고 하자 위와 같은메세지가 나왔다. 기존에 실행한 java -jar 프로세스가 아직 살아있거나 두 번 실행해 포트 충돌이 난 것이다.
- ps -ef | grep java 명령어를 이용해 PID를 확인 후, kill -9 [PID] 명령어로 기존 프로세스를 종료한 후, 다시 서버를 실행한다.
- 접속이 안된다면 보안 규칙에서 8080 포트가 열려 있는지 확인한다. 만약 열려있지 않다면 다음과 같이 Inbound rules에 8080 포트를 추가한다.
- nohup java -jar expert-0.0.1-SNAPSHOT.jar & 명령어 오류 : nohup: failed to run command 'java': No such file or directory 라는 오류 메세지가 나타났다. EC2 인스턴스에 Java가 설치되어 있지 않아서 발생한 오류이다. 다음과 같은 명령어를 입력해 Java를 설치 후 다시 시도한다.
sudo apt update
sudo apt install openjdk-17-jdk -y
탄력적 IP(Elastic IP) 설정하기
EC2 대시보드에서 Network & Security - Elastic IPs를 클릭한다.

Allocate Elastic IP address 클릭하고 Amazon에서 제공하는 IP를 선택 후 Allocate 한다.

생성된 Elastic IP를 선택하고 Actions - Associate Elastic IP address를 누른다.

연결할 인스턴스를 선택 후 Associate 한다.

이제 Public IP 대신 Elastic IP를 사용하면 된다. Elastic IP를 사용하면 인스턴스를 재시작해도 IP가 변하지 않고, Route53이나 외부 DNS에서 연결을 쉽게 할 수 있다. 그런데 연결이 안 된 EIP는 비용이 발생한다고 하니 꼭 인스턴스 연결 상태를 확인하자!
RDS
RDS 인스턴스를 생성 했다면, EC2와 RDS를 연결해야 한다.
보안 그룹 설정하기
기존에 EC2가 속한 보안그룹을 RDS에 추가한다. 나는 launch-wizard-2 라는 이름의 보안 그룹을 EC2에 적용했으므로 RDS에도 같은 것을 적용했다.

그리고 RDS 보안 그룹 Inbound rules에 MySQL/Aurora 포트(TCP 3306)를 추가했다. RDS 인스턴스는 AWS 내에서 격리되어 있기 때문에 외부에서 바로 접근할 수 없다. 따라서 RDS의 보안 그룹에서 MySQL/Aurora 포트(3306)를 허용해야, EC2 인스턴스의 보안 그룹 또는 특정 IP가 RDS와 연결될 수 있다.


RDS 연결 정보 작성하기
application.properties에 다음과 같이 RDS 연결 정보를 작성했다.
spring.datasource.url=jdbc:mysql://<엔드포인트>:<포트>/<DB명>
spring.datasource.username=admin
spring.datasource.password=비밀번호
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
- spring.datasource.url : RDS 엔드포인트 + 포트 + DB명
- spring.datasource.username : RDS 사용자명
- spring.datasource.password : RDS 비밀번호
- driver-class-name ; MySQL 사용 시 추가
참고로 RDS 엔드포인트는 RDS 내 데이터베이스에 들어가면 나와있다.

다시 빌드 후 배포하기
이제 위에서 EC2로 배포할 때 했던 과정을 다시 해주면 된다.
- 빌드
- EC2로 새로 빌드한 .jar 파일 전송
- EC2 접속 후 새 버전 실행
- 로그 확인 or 브라우저 테스트
health check API로 확인하기
health check를 위해 다음 의존성을 추가한다.
implementation 'org.springframework.boot:spring-boot-starter-actuator'
다음은 application.properties에 추가하는 설정으로, RDS 연결 확인을 위해 필요하다.
management.endpoint.health.show-details=always
management.health.db.enabled=true
- management.endpoint.health.show-details=always
- 기본값은 when-authorized로, 권한이 없으면 status: "UP"만 보여준다.
- DB, Disk, Custom Health 등 상세 정보까지 모두 출력한다.
- management.health.db.enabled=true
- Spring Boot Actuator에서 DataSource 연결(DB Health Check) 여부를 켜는 설정이다.
- DB 연결 상태를 확인하고 싶을 때 true로 설정한다.
health check로 확인해보면 다음과 같이 tjqjdmlDB가 정상적으로 돌아가고 있는 것을 알 수 있다.

위 결과에서 기본 경로가 /actuator/health가 아니라 그냥 /health인데, 아래 설정을 추가하면 /actuator 없이 루트 경로로 health check가 가능하다.
management.endpoints.web.base-path=/