초기에는 배포까지는 고려하지 않고 CI만 구현한 상태로, 빌드는 잘 작동하고 있었다.
하지만 기능이 하나둘 늘어나며 EC2에 직접 배포가 필요해졌고, 기존 CI는 그대로 두고 CD workflow만 별도로 새로 작성했다.
그러나 .jar
파일을 전송하고 EC2에서 실행하는 과정에서 여러 문제가 발생했다. 특히 GitHub Actions가 EC2에 SSH로 접속한 뒤 애플리케이션을 실행시키면, 세션 종료와 동시에 Spring Boot 앱도 같이 종료되는 문제가 있었다.
이 문제를 해결하기 위해 CI와 CD를 하나의 workflow로 통합했고, GitHub Actions는 단순히 실행 명령만 전달하고, 실행 책임은 EC2 내부의 start.sh
스크립트로 위임하는 방식으로 구조를 안정화시켰다.
scp
전송 시 호스트 인증 문제처음 scp
명령어로 .jar
파일을 EC2에 전송할 때,
다음과 같은 메시지와 함께 GitHub Actions가 멈추거나 실패하는 문제가 발생했다.
Host key verification failed.
이는 GitHub Actions가 EC2에 처음 접속할 때 ~/.ssh/known_hosts
에 등록된 호스트 키가 없어서 인증을 거부한 것이다.
이를 해결하기 위해 scp 명령에 다음 옵션을 추가했다
-o StrictHostKeyChecking=no
이 옵션은 처음 연결 시 자동으로 호스트 키를 수락하고 진행하도록 설정하는 것으로, CI/CD 환경처럼 자동화된 환경에서는 보안 리스크를 감수하고라도 실용적인 해결책이 된다.
이 설정을 통해 GitHub Actions에서 scp가 매번 사용자 확인 없이 EC2로 파일을 안전하게 전송할 수 있게 되었다.
GitHub Actions에서 EC2로 SSH 접속 후 아래처럼 앱을 백그라운드로 실행시켰다.
script: |
nohup java -jar ... > app.log 2>&1 &
하지만 결과는 다음과 같이 세션 종료와 함께 프로세스도 죽었다.
Process exited with status 143 from signal TERM
이 문제는 단순히 nohup
, disown
, setsid
로는 해결되지 않았다. 결국 실행을 EC2 내부에서 처리하도록 구조 자체를 바꿨다.
/home/ec2-user/start.sh
스크립트를 작성pkill
로 먼저 종료 처리nohup + java -jar + application.yml
실행을 EC2에서 수행start.sh
만 호출
start.sh
생성
nano /home/ec2-user/start.sh 후 작성
Ctrl + O 저장, Ctrl + W 종료
#!/bin/bash
pkill -f 'java -jar' || echo "No app running"
nohup java -jar /home/ec2-user/coupangclone-0.0.1-SNAPSHOT.jar \
--spring.config.location=file:/home/ec2-user/application.yml > /home/ec2-user/app.log 2>&1 &
Spring Boot에서 MySQL에 연결은 되었지만, 테이블 생성이나 쿼리 실행 시 다음과 같은 에러가 발생했다.
Access denied; you need (at least one of) the RELOAD privilege(s)
이는 Spring Boot 앱에서 사용하는 DB 계정에 권한이 부족한 것이 원인이었다.
MySQL root 계정으로 접속 후, 해당 사용자에게 필요한 권한을 부여했다.
mysql -u root -p
비밀번호를 입력하고 mysql>
프롬프트가 나타나면 정상 접속된 것이다.
GRANT ALL PRIVILEGES ON <schema>.* TO '사용자'@'%' IDENTIFIED BY '비밀번호';
FLUSH PRIVILEGES;
이후 아래 명령어로 권한이 정상적으로 부여되었는지 확인한다.
SHOW GRANTS FOR '사용자'@'%';
또한 JDBC URL에 아래 옵션을 추가해 인증 에러도 함께 해결했다.
spring:
datasource:
url: jdbc:mysql://<host>:3306/<schema>?allowPublicKeyRetrieval=true&useSSL=false
※ allowPublicKeyRetrieval=true
와 useSSL=false
는 MySQL 8 이상에서 인증 오류를 방지하는 옵션이다.
ci-cd.yml
코드tail
, ps
, scp -v
, 로그 추적 등 디버깅 습관이 핵심이다application.yml
같은 민감 정보는 GitHub Secrets + Base64 인코딩 방식으로 안전하게 처리 가능