이전 글에서 서버를 배포하였다. 하지만, 이 방법은 코드를 변경하여 git에 올릴 때 마다 빌드를 새로 해 주어야 해서 상당히 불편하다.
이 때, GitHub Action을 사용하면 새로 빌드를 하지 않아도 자동으로 빌드가 되어 편리하다.
GitHub Actions
https://docs.github.com/ko/actions
- GitHub에서 제공하는 CI/CD 도구
- 코드 변경 시 자동으로 워크플로우를 실행할 수 있도록 함
- 코드 빌드, 테스트, 배포 등을 자동화 할 수 있음
Workflow(워크플로우)
하나 이상의 작업을 실행하는 구성 가능한 자동화된 프로세스. 디렉토리에 저장된 yaml 파일로 구성되며, 각 워크플로우는 특정 이벤트에 대하여 트리거됨
Event(이벤트)
워크플로우 실행을 트리거하는 활동. pull, push 등의 활동이 생성될 때 워크플로우를 트리거 할 수 있음
Job(잡)
워크플로우 내에서 실행되는 하나의 작업 단위. 각 job은 여러 step으로 구성되며, 각 step은 실행될 개별 명령어 / 액션임. 병렬로 실행될 수도 있고, 순차적으로 실행될 수도 있음
Step(스텝)
각 job 내에서 수행되는 개별 명령어 또는 스크립트. 복잡하지만 자주 반복되는 작업을 수행하는 GitHub Actions 플랫폼용 사용자 지정 애플리케이션. GitHub에서 Git repository를 가져오거나 클라우드 공급자에 대한 인증을 설정할 수 있음
Runner(러너)
workflow가 트리거 될 때 workflow를 실행하는 서버. 각 실행은 새로운 가상 머신에서 실행되며, GitHub에서 제공하는 호스트 러너를 사용할 수도 있고, 자체 호스팅 러너를 설정할 수 도 있음
Continuous Integration / Continuous Deployment(CI/CD)
- 지속적 통합 / 지속적 배포
- CI : 새로운 소스코드의 빌드, 테스트, 병학
- CD : 개발자의 변경 사항이 production 환경까지 릴리즈 되는 것
지속적 통합
새로운 코드 변경 사항이 정기적으로 빌드 및 테스트 되어 공유 레포지토리에 통합하는 것. 자동으로 빌드 및 테스트가 진행되므로 소스코드의 충돌을 방어하고 기능 충돌을 방어함
지속적 배포
지속적인 서비스 제공, 지속적인 배포를 의미함
GitHub Actios 적용
1. Repository secrets 설정
Repository secrets는 repository의 정보를 보호하기 위하여 사용된다. 비밀번호, API key, token 등과 같은, 유출되면 안되는 데이터를 저장하며 이것을 GitHub Actions workflow에서 사용할 수 있도록 한다.
이것을 설정하려면 깃 액션을 적용하려는 레포지토리에 들어가 setting를 눌러준다. 이후 Security>Secrets and variables>Actions에들어가 New repository secret을 눌러 추가해 주면 된다. 여기서의 Name은 추후 깃 액션 설정 시에 사용된다.

2. yml 파일 생성
레포지토리의 Actions를 누른 후 'set up a workflow yourself'를 눌러준다. 그럼 yml파일을 작성할 수 있는 화면으로 넘어간다.
이 yml 파일은 main에서 .github/workflows라는 폴더 내에 생성되며, workflow를 정의하는 파일이다.

아래의 링크를 통하여 여러 문법을 확인할 수 있고, 원하는 값에 맞게 작성해 주면 된다.
https://docs.github.com/en/actions/learn-github-actions
3. yml 파일 작성
jobs안의 steps는 위에서부터 순서대로 실행된다. 배포 과정에서 내가 직접 터미널로 해 주었던 과정들을 github actions가 해주도록 로직을 작성한 것이며, 프로세스는 다음과 같다.
- main 브랜치에 코드가 푸쉬되거나 풀 리퀘스트가 생성될 때 실행됨
- 가장 최신 버전의 우분투 환경에서 실행되도록 설정함
- JDK 11과 Maven 환경을 설정함
- 프로젝트를 clean 한 후 build
- ssh 키 설정 후 known_hosts 파일에 추가
- 기존 tomcat의 ROOT 디렉토리와 ROOT.war 파일 삭제
- 서버 종료 후 시작
on:
push:
branches:
- main
pull_request_target:
branches:
- main
types: [closed]
jobs:
build:
if: github.event.pull_request.merged == true
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up JDK 11
uses: actions/setup-java@v2
with:
java-version: '11'
distribution: 'temurin'
- name: Set up Maven
uses: actions/setup-java@v2
with:
java-version: '11'
distribution: 'temurin'
cache: maven
- name: Maven Clean and Package
run: mvn clean package
- name : SSH KEY permission
run : |
mkdir -p ~/.ssh
echo "${{ secrets.SSH_KEY }}" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
- name : Add SSH Key
uses : webfactory/ssh-agent@v0.5.3
with :
ssh-private-key: ${{ secrets.SSH_KEY }}
- name : Add known_hosts
run : |
echo "3.36.97.132 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGZFY4R3oBQp9/O62iqwR/T1zSj6i7QpIJxdRe5+Sev5" >> ~/.ssh/known_hosts
- name: clean ROOT directory
run: |
ssh -i ~/.ssh/id_rsa ubuntu@3.36.97.132 << 'EOF'
sudo rm -rf /home/ubuntu/shinhan_team2_chukahaeyo/apache-tomcat-9.0.89/webapps/ROOT
sudo rm -rf /home/ubuntu/shinhan_team2_chukahaeyo/apache-tomcat-9.0.89/webapps/ROOT.war
EOF
- name: Upload WAR file
run: |
scp -i ~/.ssh/id_rsa target/chukahaeyo-1.0.0-BUILD-SNAPSHOT.war ubuntu@3.36.97.132:/home/ubuntu/shinhan_team2_chukahaeyo/apache-tomcat-9.0.89/webapps/ROOT.war
- name: Restart Tomcat on Remote Server
run: |
ssh -i ~/.ssh/id_rsa ubuntu@3.36.97.132 << 'EOF'
kill `pgrep -f chukahaeyo`
/home/ubuntu/shinhan_team2_chukahaeyo/apache-tomcat-9.0.89/bin/startup.sh
EOF
빌드 상황도 볼 수 있다. 그러므로 name을 자세히 써 주는 것이 어디에서 에러가 발생하였는지 찾을 때 편하다.


4. tomcat 구동 시 profile 설정하기
초반에는 properties 파일을 ~/apache-tomcat-9.0.89/webapps/안에다가 저장해 둔 후, 배포 시 ~/apache-tomcat-9.0.89/webapps/ROOT/WEB-INF/classes/로 cp해 주었다. 하지만, 여기에서 복사가 되지 않는 문제점이 발생하였다.
ROOT 폴더가 있어야 cp가 가능한데, ROOT폴더를 지운 후 start 할 때 새로 생성하기 때문에 복사가 안되는 것이다. 위와 같은 방법을 쓰려면 server start -> copy -> restart를 해야 하는데, 이는 비효율적이고 서버를 재시작 하는 데에 시간이 소요되므로 좋은 방법이 아니다.
그래서 우선 문제점을 분석해 보았다. 현재 우리의 프로젝트는 배포를 진행하였기 때문에 개발 환경과 운영 환경이 다르다. 깃에 push, pull request가 올라가면 서버가 build되고, 이 때 기존 파일은 삭제하는 로직을 수행한 후 다시 war파일을 만들기 때문에 git ignore 파일인 properties는 반영되지 않아 500 에러가 발생하는 것이다.
그래서 개발이랑 운영 properties를 다르게 두었다. 실제로도 개발 property는 resource에 위치하고, 배포 property는 classes에 위치한다.

환경을 다르게 하려면 톰캣에 옵션을 지정해 주면 된다. 이 옵션은 매개변수를 사용하여 내가 만든 소스가 어디에서 돌아가게 할 것인지를 자동으로 구분하도록 해 준다.
우선, ~/apache-tomcat-9.0.89/bin에 들어가준다. 그럼 actalina.sh가 보일 것이다. 동일한 위치에 setenv.sh 파일을 생성해주고, 아래 환경 변수를 입력해 준다.
export JAVA_OPTS="-Dspring.profiles.active=aws"
이후 spring에 들어가 MvcConfig 코드에 아래 내용을 추가해준다.
String value = System.getProperty("spring.profiles.active");
if ("aws".equals(value)) {
config.setLocations(new FileSystemResource("/home/ubuntu/shinhan_team2_chukahaeyo/apache-tomcat-9.0.89/webapps/db.properties"));
} else {
config.setLocations(new ClassPathResource("db.properties"));
}
현재 시스템 속성인 spring.profiles.active 값을 가져와 value 변수에 저장하고, 이것이 aws과 같으면 설정해둔 경로의 파일을 사용하고 그렇지 않으면 클래스 경로에 있는 db.properties 파일을 사용한다는 뜻이다.
이렇게 하면 aws에서의 properties파일을 미리 저장해 둔 곳에 있는 properties 파일로 사용할 수 있게 되는 것이다.
5. 주의해야 할 점
깃 액션을 만들며, 여러 가지 에러를 마주했었다. 아래는 그 문제들을 겪고 깨달은 점들을 작성한 것이다.
- 경로 제대로 확인하기. 특히, tomcat server 경로 제대로 확인하기
- 저장하는 SSH_KEY값은 .pub이 아님(여기서의 id_rsa값임)
- ROOT 디렉토리를 삭제할 때, ROOT 폴더와 .war 파일 둘 다 삭제해야함(ROOT/*으로 삭제하지 말고, ROOT 자체를 삭제해야 함)
- 단순히 shutdown.sh -> startup.sh을 해 주었을 경우, 서버가 제대로 재실행되는지 터미널에서 확인하기(나는 재시작이 제대로 되지 않아 서버를 kill하고 재시작함)
- pull request가 open되는 경우에 actions가 돌아가게 하면 실수로 pull request를 open한 경우 main에 빌드되어 배포 서버에서 에러가 발생할 수 있으므로 merge 시에만 actons가 돌아가게 하도록 해야 함
#비추천
pull_request:
branches:
- main
#추천
pull_request_target:
branches:
- main
types: [closed]
jobs:
build:
if: github.event.pull_request.merged == true
'커스텀 축하 카드 쇼핑몰 [축하해요]' 카테고리의 다른 글
Open Graph Protocol(OGP) (0) | 2025.01.06 |
---|---|
모든 페이지에 Error Page 적용(404, 500) (1) | 2025.01.06 |
Amazon RDS(AWS RDS)를 통한 DB 배포 (1) | 2025.01.06 |
Amazon EC2(AWS EC2)를 이용한 서버 배포 (0) | 2025.01.06 |
Amazon S3(AWS S3) (1) | 2025.01.06 |