1. EC2 인스턴스 생성
1. EC2 선택
2. [인스턴스] 클릭 > 오른쪽 상단 지역 [서울]로 선택된 것 확인 > [인스턴스 시작] 클릭
3. 이름은 원하는 걸로 지음(나는 ServerTest로 함) > Ubuntu 선택 > Amazon Machine Image(AMI)는 [프리티어 사용 가능]이라고 되어 있는 거 선택
4. 인스턴스 유형 : t2.micro 선택 > 키 페어 선택 (이미 있으면 그대로 선택, 없으면 [새 키페어 생성]으로 만들기)
5. 네트워크 설정 (옆에 [편집] 버튼 클릭) > VPC : 기본으로 냅두기 > 퍼블릭 자동 할당 : 활성화 > 보안그룹 이름 입력
6. 스토리지 구성 : 16GB (최대 30GB까지 무료)
7. [인스턴스 시작] 클릭
2. 보안그룹 설정
1. 네트워크 밀 보안 > 보안그룹 이동
2. 아까 작성한 보안그룹 이름의 보안 그룹 ID 클릭
3. 인바운드 규칙 탭 > 인바운드 규칙 편집
4. 다음과 같이 설정 (Anywhrere-IPv4 선택. 상위 3개만 해도 됨. 아래 2개는 사용할 경우 넣기)
3. 탄력적 IP 설정 (선택)
* IP주소가 계속 바뀌지 않게 하기 위한 것
1. 네트워크 및 보안 > 탄력적IP 선택
2. [탄력적 IP 주소 할당] 클릭
3. 아무것도 하지 않고 [할당] 누르기
4-1. 상단에 뜬 [이 탄력적 IP 주소 연결] 클릭
4-2. 아니면 [작업] > [탄력적 IP 주소 연결]로도 가능
5. 아까 만든 인스턴스 이름 선택 > 연결
4. EC2에 IntelliJ로 원격 접속
1. Tools > Deployment > Configuration으로 이동
2. [+] > [SFTP]로 이동
3. 이름 입력
4. [...] 클릭
5. 다음과 같이 설정 후 [Test Connection] 클릭 > 'Successfully connected!'라고 뜨면 [Ok] > [Ok] 클릭
- Host : EC2 인스턴스의 퍼블릭 IP 주소
- Port : 22
- Username : ubuntu
- Authentication type: Key pair > 위에서 선택했던 키페어 선택
6. 터미널창에 서버 추가
7. 자바 설치
sudo apt update
sudo apt install openjdk-17-jdk
8. 자바 버전 확인
# Java 버전 확인
java -version
9. MySQL 설치 (서버 DB를 여기서 사용 - 별도 DB 있으면 생략 가능)
sudo apt install mysql-server
10. MySQL 시작 (서버 DB를 여기서 사용 - 별도 DB 있으면 생략 가능)
sudo systemctl start mysql
11. MySQL root으로 접속 (서버 DB를 여기서 사용 - 별도 DB 있으면 생략 가능)
sudo mysql -u root
12. MySQL 비밀번호 설정 (서버 DB를 여기서 사용 - 별도 DB 있으면 생략 가능)
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '원하는비밀번호';
CREATE DATABASE your_database_name;
13. MySQL 종료 (서버 DB를 여기서 사용 - 별도 DB 있으면 생략 가능)
exit
14. 스왑 메모리 설정
sudo fallocate -l 2G /swapfile # 2GB 크기의 스왑 파일을 생성
sudo chmod 600 /swapfile # 스왑 파일의 권한을 설정(root 사용자만 읽고 쓰는게 가능)
sudo mkswap /swapfile # 생성한 파일을 스왑 영역으로 초기화
sudo swapon /swapfile # 스왑 파일을 활성화하여 실제로 사용
15. 아래 명령어로 설정 확인
sudo swapon --show
free -h
5. Github Secrets 설정
1. Settings로 이동
2. [Secrets and variables] > [Actions] 선택 > [New repository secret] 버튼 클릭
3. name : EC2_HOST sercret : 퍼블릭IP주소
4. (위처럼) name : EC2_SSH_KEY sercret : 아까 선택한 키페어 내용 (메모장으로 열고 복사하기)
(여기부터)
-----BEGIN RSA PRIVATE KEY-----
(키 내용)
-----END RSA PRIVATE KEY-----
(여기까지 전부 복사)
5. (위처럼) name : EC2_USERNAME sercret : ubuntu
6. (위처럼) name : APPLICATION_YML secret : (아래처럼 적용)
spring:
datasource:
url: jdbc:mysql://localhost:3306/{ec2 DB 명}?serverTimezone=Asia/Seoul
username: root
password: {ec2비번}
driver-class-name: com.mysql.cj.jdbc.Driver
sql:
init:
mode: never
jpa:
properties:
hibernate:
dialect: org.hibernate.dialect.MySQL8Dialect
show_sql: true
format_sql: true
use_sql_comments: true
hbm2ddl:
auto: create
default_batch_fetch_size: 1000
6. GitHub Actions 설정
1. 프로젝트 root 위치(최상단)에 .github 폴더 생성
2. .github 아래에 workflows 폴더 생성
3. workflows 안에 dev_deploy.yml 생성
3. dev_deploy.yml 안을 아래 내용으로 채우기
name: CI/CD Test # 알맞은 이름으로 변경
on:
push:
branches: [ main ] # main 브랜치에 push가 일어날 때 실행
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4 # 저장소 코드 체크아웃
- name: Set up JDK 17 # Java 개발 킷 설정
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '17'
- name: Make application.yml # application.yml 파일 생성
run: |
cd ./src/main/resources
echo "${{ secrets.APPLICATION_YML }}" > ./application.yml
shell: bash
- name: Grant execute permission for gradlew # gradlew 실행 권한 부여
run: chmod +x gradlew
- name: Build with Gradle # Gradle을 사용하여 프로젝트 빌드
uses: gradle/gradle-build-action@v3
with:
arguments: clean build -x test
- name: Upload build artifact # 빌드된 아티팩트 업로드
uses: actions/upload-artifact@v4
with:
name: serverTest
path: build/libs/*.jar
deploy:
needs: build # build 작업이 성공적으로 완료된 후 실행
runs-on: ubuntu-22.04
steps:
- name: Download build artifact # 이전 단계에서 업로드한 아티팩트 다운로드
uses: actions/download-artifact@v4
with:
name: serverTest
path: build/libs/
- name: Deploy to EC2 # EC2에 배포
env:
EC2_SSH_KEY: ${{ secrets.EC2_SSH_KEY }}
EC2_USERNAME: ${{ secrets.EC2_USERNAME }}
EC2_HOST: ${{ secrets.EC2_HOST }}
run: |
echo "$EC2_SSH_KEY" > private_key.pem
chmod 600 private_key.pem
jar_file=$(find build/libs -name '*.jar' ! -name '*plain.jar' | head -n 1)
scp -i private_key.pem -o StrictHostKeyChecking=no "$jar_file" $EC2_USERNAME@$EC2_HOST:/home/$EC2_USERNAME/serverTest.jar
ssh -i private_key.pem -o StrictHostKeyChecking=no $EC2_USERNAME@$EC2_HOST "
pgrep java | xargs -r kill -15 # 기존에 실행 중인 Java 프로세스 종료
sleep 10
nohup java -jar /home/$EC2_USERNAME/serverTest.jar > app.log 2>&1 & # 새 버전 애플리케이션 실행
"
rm -f private_key.pem # 민감한 정보 삭제
4. build.gradle 수정
plugins {
id 'java'
id 'org.springframework.boot' version '3.4.1'
id 'io.spring.dependency-management' version '1.1.7'
}
group = 'com.example'
version = '0.0.1-SNAPSHOT'
java {
toolchain {
languageVersion = JavaLanguageVersion.of(17)
}
}
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-web'
compileOnly 'org.projectlombok:lombok'
runtimeOnly 'com.mysql:mysql-connector-j'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
//검증 어노테이션
implementation 'org.springframework.boot:spring-boot-starter-validation'
//Swagger 세팅
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.7.0'
implementation 'org.springframework.boot:spring-boot-starter-security'
testImplementation 'org.springframework.security:spring-security-test'
}
tasks.named('test') {
useJUnitPlatform()
}
5. 커밋 후 main 브랜치로 merge
7. 결과
1. action보면 성공이 뜸
2. {내 IP}:8080/ 으로 접속하면 잘 됨
(내 프로젝트에는 '/' api 따로 만든게 없어서 아래처럼 뜸 - 정상적으로 뜬거 맞음. 루트 api 만든거 있으면 설정한 응답으로 오는게 정상임)