정리 목적

이번에 AWS에 배포 테스트를 하며 UI가 변경된 부분도 좀 있었고 이전에는 도메인 구매 후 접근 테스트만 해본 반면 이번에는 여러 환경을 설정하고 처리했기 때문에 이전 정리 내용을 지우고 새로 다시 정리.

 

처리 환경 정리

Project

  • BackEnd - Spring Boot 3
  • FrontEnd - React
  • 빌드 방식 - 통합빌드

AWS

  • EC2 t2.micro
    • ubuntu 22.0.4
  • Application Load Balancer
  • AWS Certificate Manager(ACM)
  • Route53
  • S3
  • RDS(MySQL)
  • ElastiCache(Redis)

CI / CD

  • Jenkins
  • Git Webhook

WebServer

  • Nginx

Domain Register

  • Gabia

 

정리 순서

  1. S3 Bucket 생성 후 Local에서 테스트
  2. RDS MySQL Database Instance 생성 후 Local Workbench와 연결 테스트 및 프로젝트 연결 테스트
  3. EC2 Instance 생성 후 설정
    1. swap 메모리 설정
    2. JDK 17 설치
    3. nvm 설치 및 node 21.7.1 설치
    4. Nginx 설치 및 설정
    5. Jenkins 설치 및 빌드 Job 설정을 제외한 나머지 처리
    6. ElasiCache Redis OSS Cache 생성 및 Redis 설치
  4. Gabia 도메인 구매 후 Route53, ACM 처리
  5. Load Balancer 대상 그룹 생성 및 ALB 생성 후 대상 그룹 설정
  6. A레코드 생성 및 도메인 접근 테스트
  7. git clone을 통해 사전 테스트 이후 Jenkins Job 설정과 Build 테스트
  8. Git Webhook 연동 및 테스트

Git webhook 연동

이제 배포 테스트 과정 중 마지막이다.

webhook을 연동해두면 로컬에서 git에 push 했을 때 이 push 이벤트를 Jenkins에 전달하고 이벤트를 전달받은 Jenkins가 자동으로 해당 Job 설정대로 빌드와 배포를 처리해준다.

 

이 연동을 위해 github에서 personal access token을 발급 받아야 한다.

github 페이지에서 오른쪽 상단에 있는 자신의 프로필을 눌러 Settings로 이동한다.

 

그리고 최하단의 Developer settings로 이동

 

Personal access tokens 하위의 Tokens(classic)을 클릭

 

Generate new token을 눌러 새 토큰을 생성한다.

 

Note에는 토큰명을 입력해주면 되고 아래 이미지와 같이 체크해준다.

webhook에 필요한 포인트는 가장 위의 repo 하위 선택지와 admin:repo_hook의 하위 선택지이다.

다 체크했다면 토큰 생성!

토큰을 생성하게 되면 토큰 값이 바로 나오는데 이건 이때 아니면 확인할 수 없기 때문에 바로 복사해서 어딘가에 저장해둬야 한다.

 

webhook을 연동하기 위해 연동할 프로젝트 repository 페이지로 이동해서 상단의 Settings로 이동한다.

 

그리고 왼쪽 탭에서 webhooks로 이동

 

Add webhook 버튼을 클릭해준다.

 

Payload URL에는 자신의 jenkins접속 IP와 포트 번호 /github-webhook/을 입력해준다.

이때 꼭 끝에 / 가 붙어있어야 한다.

Content type은 application/json으로 변경하고 Add webhook 버튼을 클릭한다.

 

그럼 이제 jenkins 페이지로 이동한다.

jenkins 관리 탭에서 Security 하위의 Credentials로 이동한다.

 

Stores scoped to Jenkins에서 system의 Domains인 global을 클릭한다.

Add Credentials를 클릭

Kind에는 Username with password를 선택.

Username은 git username을 적어주고 password에는 생성한 personal access token을 입력해준다.

그리고 create!

 

다시 Jenkins로 돌아와 system으로 이동한다.

 

GitHub 탭에서 Add GitHub Server를 눌러 추가해준다.

Name은 임의로 입력해도 되고, Credentials는 방금 생성한 Credential을 선택해주면 된다.

Manage hook를 체크해주고 Apply 이후 저장하면 된다.

저장 이전 Test connection으로 연결 상태를 체크할 수 있다.

 

Jenkins Job에서 설정해야 하는 것은 이전 포스팅에서 끝났기 때문에 모든 설정이 끝났다.

이제 프로젝트에서 README 같은것을 조금 수정하고 push 했을 때 Jenkins 페이지에서 Build History에 빌드가 추가된다면 연동은 성공이다!

빌드 시작까지 확인했다면 처리 이후 브라우저에서 도메인 접근까지 체크한다면 모든 배포 테스트 끝!!

정리 목적

이번에 AWS에 배포 테스트를 하며 UI가 변경된 부분도 좀 있었고 이전에는 도메인 구매 후 접근 테스트만 해본 반면 이번에는 여러 환경을 설정하고 처리했기 때문에 이전 정리 내용을 지우고 새로 다시 정리.

 

처리 환경 정리

Project

  • BackEnd - Spring Boot 3
  • FrontEnd - React
  • 빌드 방식 - 통합빌드

AWS

  • EC2 t2.micro
    • ubuntu 22.0.4
  • Application Load Balancer
  • AWS Certificate Manager(ACM)
  • Route53
  • S3
  • RDS(MySQL)
  • ElastiCache(Redis)

CI / CD

  • Jenkins
  • Git Webhook

WebServer

  • Nginx

Domain Register

  • Gabia

 

정리 순서

  1. S3 Bucket 생성 후 Local에서 테스트
  2. RDS MySQL Database Instance 생성 후 Local Workbench와 연결 테스트 및 프로젝트 연결 테스트
  3. EC2 Instance 생성 후 설정
    1. swap 메모리 설정
    2. JDK 17 설치
    3. nvm 설치 및 node 21.7.1 설치
    4. Nginx 설치 및 설정
    5. Jenkins 설치 및 빌드 Job 설정을 제외한 나머지 처리
    6. ElasiCache Redis OSS Cache 생성 및 Redis 설치
  4. Gabia 도메인 구매 후 Route53, ACM 처리
  5. Load Balancer 대상 그룹 생성 및 ALB 생성 후 대상 그룹 설정
  6. A레코드 생성 및 도메인 접근 테스트
  7. git clone을 통해 사전 테스트 이후 Jenkins Job 설정과 Build 테스트
  8. Git Webhook 연동 및 테스트

git clone 후 서버 실행 및 테스트

Jenkins를 통해 CI / CD 를 수행하기 전에 프로젝트가 정상적으로 배포되는지 확인하기 위해 테스트했다.

 

EC2에서 프로젝트를 clone 받았다.

# root 위치에서 디렉토리 생성
sudo mkdir testBuild

# 이동
cd testBuild

# git clone
git clone https://github.com/~

 

그리고 바로 프로젝트 빌드 후 실행했다.

# 프로젝트 경로에서 명령어 실행
./gradlew build

# jar 파일 실행
java -jar build/libs/project.jar

 

이렇게 실행 후 도메인으로 접근했을 때 정상적인 결과를 얻을 수 있었다.

 

Jenkins Provide Configuration files 사용을 위한 처리

이걸 뭐라고 불러야 할지 몰라서 부제를 이렇게 정하긴 했다.

이후 Jenkins Job 설정을 하면서 Provide Configuration files라는 기능을 체크해 사용할 것이다.

이 기능은 빌드 환경에서 선택할 수 있는데 Spring을 기준으로 application.yml 같은 설정 파일은 공개가 되면 안되는 내용들이 작성되기도 하므로 git에 올라가지 않도록 ignore에 걸어둔다.

그럼 단순하게 application.yml 하나만 ignore에 걸어두었다고 가정하고 이걸 처리하기 위해서는 두가지 방법이 있었다.

첫번째 방법은 EC2에 shell script를 작성해두고 Jenkins Job 설정 시 빌드 과정에 해당 스크립트를 실행하도록 해 application.yml 파일을 추가하는 방법.

두번째 방법은 Provide Configuration files를 체크해 Jenkins에서 작성해둔 application.yml 파일을 생성하도록 하는 방법.

 

두 방법 모두 사용해봤는데 개인적으로는 Provide Configuration files를 통해 처리하는게 더 쉬웠던 것 같다.

하지만 이것도 Job 설정 시 어떻게 처리하느냐에 따라 장단점이 존재할 것 같다.

 

일단 shell script 를 통해 처리하는 방법.

echo "application.yml 내용" > /var/lib/jenkins/project/src/main/resources/application.yml

 

이런식의 내용을 EC2 내부에서 000.sh 이런 식의 파일을 생성해준다.

그리고 Job 설정 중 Build Step에서 빌드 과정에 대한 스크립트를 작성하면서 해당 스크립트를 실행하는 명령어를 사용해주면 된다.

 

Provide Configuration Files를 처리하는 방법.

이 방법을 사용하기 위해서는 어떤 내용의 파일을 생성할 것인지 Jenkins에 설정해 둬야 한다.

 

Jenkins 관리 탭으로 이동해 System Configuration 하위의 Managed files를 클릭한다.

 

그럼 아래와 같은 페이지로 접근하게 되는데 Add a new Config를 눌러 추가해준다.

아래 이미지는 이미 추가해둔 파일들이고 아마 최초 접근 시에는 아무것도 없을 것이다.

 

여기서 생성할 타입을 선택하고 next로 넘어간다.

yml 또는 properties는 Properties file을 선택하면 되고 React의 .env같은 파일은 Custom file을 선택하면 된다.

ID는 자동 생성이기 때문에 그냥 Next!

 

여기에서는 Name과 Comment, Content를 작성한다.

Name은 파일의 이름을 작성해주면 된다. 이 Name이 그대로 파일명이 되는 것은 아니다.

Comment는 설명 정도.

Content에는 파일의 내용을 작성해주면 된다.

 

이렇게 필요한 Configuration file 들을 작성해 생성해주면 된다.

이걸 적용하는건 아래 Job 설정에서 마저 정리한다.

Jenkins Job 설정 및 Build 테스트

git clone을 통한 사전 배포 테스트가 정상적으로 수행되었기 때문에 Jenkins를 마저 설정하고 build 테스트까지 정리한다.

Jenkins 페이지에서 Job 을 새로 작성하기 위해 새로운 Item 버튼을 눌러 생성한다.

 

그럼 아래와 같은 페이지가 나온다.

Item name을 원하는 이름으로 작성해주고 Freestyle project를 선택한 뒤 OK 버튼을 클릭.

이때 Item name은 EC2 내에서 프로젝트 경로명이 되므로 너무 복잡하게 설정하면 나중에 피곤할 것 같다.

 

소스 코드 관리 탭에서는 Git에 올라가있는 프로젝트를 대상으로 할 것이기 때문에 GIt을 선택해준다.

Repository URL은 해당 프로젝트의 git url을 적어준다.

그리고 Credentials는 git 계정에 대한 정보인데 처음 생성하면 없을 것이므로 + Add 버튼을 눌러 생성해준다.

 

Add 버튼을 눌렀을 때 아래와 같은 창이 뜰 것이다.

git username과 비밀번호를 입력하고 Add 버튼을 눌러준다.

git에서는 personal Token을 사용하고 있어 해당 토큰 값을 비밀번호로 넣어줬다.

그러고보니 웹에서 로그인할 때 사용하는 비밀번호로는 테스트를 안해봤는데..

이후 webhook 연동할 때도 personal Token을 사용하기 때문에 없다면 다음 포스팅에서 git personal token 생성하는 부분을 먼저 보고 생성한 뒤 사용하시는 것이 좋을 것 같습니다.

 

Add 버튼을 눌러 Credentials를 생성하고 나면 생성된 Credentials를 선택할 수 있으니 선택해준다.

 

빌드 유발탭에서는 GitHub hook trigger for GITScm polling을 선택해준다.

다음 포스팅에서 git webhook과 연동할때 사용되는 건데 그때 수정하지 않기 위해 미리 체크한다.

git webhook 연동까지 처리하지 않을 것이라면 체크하지 않아도 된다.

 

빌드 환경 탭에서는 Provide Configuration files와 Provide Node & npm bin/folder to PATH를 체크한다.

Provide Node & npm bin/ folder to PATH의 경우 NodeJS가 필요하다면 체크하는 것이므로 자신의 환경에 NodeJS가 사용되지 않는다면 체크할 필요가 없다.

체크한다면 초반 Jenkins plugin 설치 이후 Tools의 NodeJS Installation에서 설정해뒀던 정보가 알아서 설정되어있기 때문에 따로 건드릴건 없다.

 

Configuration file에 대한 설정을 해두었다면 체크했을 때 아래와 같은 탭이 생성될 것이고 File에서는 생성한 파일들의 목록이 나올 것이다.

Target에는 경로를 설정해준다.

기본 시작 경로는 프로젝트 루트 경로이다.

그렇기 때문에 프로젝트 내부에서 src/main/resources 안에 위치하는 application.yml은 아래 이미지 처럼 작성해준다.

이때 파일명까지 작성해줘야 한다.

이 처리를 필요한 파일의 개수만큼 처리해주면 된다.

 

 

다음으로는 BuildSteps다.

Add build step 버튼을 누르면 여러 설정 중 선택해 처리할 수 있다.

여기에서도 두가지 선택지로 간단하게 처리할 수 있다.

가장 먼저 매우 간단한 Invoke Gradle script다.

빌드 과정에서 별다른 스크립트가 필요하지 않고 빌드만 하는 것으로 처리가 된다면 Invode Gradle script를 선택하는 것이 편하다.

 

아래와 같은 탭이 생길텐데 Use Gradle Wrapper를 선택하고 Make gradlew executable을 체크.

Wrapper location 에는 ${workspace}라고 작성하면 알아서 프로젝트 경로를 잡아준다.

Tasks에는 build 라고 작성해주는 것만으로 ./gradlew build 까지 수행하게 된다.

 

하지만 스크립트를 작성해 처리해야 할 것이 필요하다면 Execute shell을 선택해 처리한다.

이전에는 Spring, thymeleaf로 작성된 프로젝트를 배포해 Invoke Gradle script를 통해 간단히 처리할 수 있었으나 오류가 발생했기 때문에 Execute shell을 통해 처리했다.

 

프로젝트는 Spring Boot와 React의 통합 빌드를 처리하기 위해 build.gradle에 스크립트가 작성되어있다.

그래서 Invoke Gradle script 설정으로 간단하게 처리될 줄 알았는데 오산이었다.

install React FAILED 오류가 대체적으로 발생하였고 이 오류에 대한 해결방안으로 npm cache 초기화와 node_modules를 삭제하는 방법이 있었다.

 

그래서 빌드 수행 이전 해당 처리를 위해 아래 이미지처럼 스크립트를 작성했고 빌드를 수행하도록 처리했다.

 

추가적으로 통합 빌드 기준 이렇게 수행하더라도 Jenkins에서 React 경고를 오류로 인식해 빌드에 실패하는 경우가 있다.

그런 경우 npm run build 앞에 CI=false를 추가해 주면 되는데 이 문제에 대해서는 execute shell에 작성하는 것이 아닌 build.gradle에 작성해 문제를 해결했다.

 

마지막 Job 설정으로는 빌드 후 조치에 대한 설정을 해주면 끝난다.

빌드 후 조치로는 Post build task를 선택해준다.

빌드가 성공했다면 BUILD SUCCESSFUL이 찍히기 때문에 해당 로그가 찍혔을 때 스크립트가 동작하게 된다.

그래서 스크립트에는 jar 파일을 실행하도록 작성해둔다면 빌드에 성공했을 때 jar 파일을 실행해 서버가 배포된다.

 

여기까지 체크가 끝났다면 Apply 이후 저장!

 

그럼 Jenkins 페이지에서 해당 job으로 이동하고 지금 빌드 버튼을 눌렀을 때 Build History에 추가가 될 것이다.

성공한 경우 초록색 체크 표시가 뜨는데 jar 파일 실행까지 모두 작성한 경우에는 종료되지 않고 계속 돌아가고 있기 때문에 상태바가 거의 다 채워진 것 처럼 보일 때 도메인으로 접근해 서버가 동작하고 있는지 확인할 수 있다.

중단하기 위해서는 해당 히스토리의 오른쪽 상단 x 버튼을 누르면 서버가 중단된다.

정리 목적

이번에 AWS에 배포 테스트를 하며 UI가 변경된 부분도 좀 있었고 이전에는 도메인 구매 후 접근 테스트만 해본 반면 이번에는 여러 환경을 설정하고 처리했기 때문에 이전 정리 내용을 지우고 새로 다시 정리.

 

처리 환경 정리

Project

  • BackEnd - Spring Boot 3
  • FrontEnd - React
  • 빌드 방식 - 통합빌드

AWS

  • EC2 t2.micro
    • ubuntu 22.0.4
  • Application Load Balancer
  • AWS Certificate Manager(ACM)
  • Route53
  • S3
  • RDS(MySQL)
  • ElastiCache(Redis)

CI / CD

  • Jenkins
  • Git Webhook

WebServer

  • Nginx

Domain Register

  • Gabia

 

정리 순서

  1. S3 Bucket 생성 후 Local에서 테스트
  2. RDS MySQL Database Instance 생성 후 Local Workbench와 연결 테스트 및 프로젝트 연결 테스트
  3. EC2 Instance 생성 후 설정
    1. swap 메모리 설정
    2. JDK 17 설치
    3. nvm 설치 및 node 21.7.1 설치
    4. Nginx 설치 및 설정
    5. Jenkins 설치 및 빌드 Job 설정을 제외한 나머지 처리
    6. ElasiCache Redis OSS Cache 생성 및 Redis 설치
  4. Gabia 도메인 구매 후 Route53, ACM 처리
  5. Load Balancer 대상 그룹 생성 및 ALB 생성 후 대상 그룹 설정
  6. A레코드 생성 및 도메인 접근 테스트
  7. git clone을 통해 사전 테스트 이후 Jenkins Job 설정과 Build 테스트
  8. Git Webhook 연동 및 테스트

A 레코드 생성

도메인 테스트를 하기 전 Route 53에서 A 레코드를 생성해야 한다.

Route 53으로 이동해 호스팅 영역으로 이동한뒤 레코드 생성 버튼을 클릭한다.

 

혹시 아래 이미지 같은 페이지가 뜬다면 빠른 생성으로 전환 버튼을 클릭해 화면 전환을 할 수 있다.

개인적으로는 빠른 생성으로 처리하는게 더 편했어서 그 방법으로 정리한다.

 

 

이런 페이지가 출력될건데 아래 이미지에서 우측 하단의 다른 레코드 추가 버튼을 누르면 하나씩 추가가 가능하다.

레코드 1의 레코드 이름은 비워둔다. 그리고 레코드 2의 레코드 이름에는 www 를 작성해준다.

이렇게 처리한다면 도메인에 접근했을 때 test-domain.shop과  www.test-domain.shop 두 가지 설정이 되는 것이다.

 

나머지는 레코드 1, 2가 공통이다.

레코드 유형은 A - IPv4 주소 및 일부 AWS 리소스로 트래픽 라우팅 을 선택한다.

별칭 탭을 열어주면 트래픽 라우팅 대상을 선택할 수 있을 것이다.

이미지처럼 Application/Classic Load Balancer에 대한 별칭 -> 자신의 리전 -> 생성한 로드밸런서 선택 순서로 처리한다.

모두 작성했다면 레코드 생성 버튼 클릭!

 

그럼 A 레코드가 생성되었을 것이고 연결은 끝이다!

 

도메인 접근 테스트

Nginx를  설정해뒀기 때문에 프로젝트를 배포하지 않아도 도메인 접근이 정상적으로 이루어지는지는 확인할 수 있다.

브라우저에서 도메인으로 접근했을 때 아래와 같은 페이지가 출력된다면 정상적으로 도메인이 연결된 것이다.

하나 더 체크해야 할 사항으로 http 로 접근했을 때 https로 redirect가 정상적으로 수행되는지 체크해야 한다.

정리 목적

이번에 AWS에 배포 테스트를 하며 UI가 변경된 부분도 좀 있었고 이전에는 도메인 구매 후 접근 테스트만 해본 반면 이번에는 여러 환경을 설정하고 처리했기 때문에 이전 정리 내용을 지우고 새로 다시 정리.

 

처리 환경 정리

Project

  • BackEnd - Spring Boot 3
  • FrontEnd - React
  • 빌드 방식 - 통합빌드

AWS

  • EC2 t2.micro
    • ubuntu 22.0.4
  • Application Load Balancer
  • AWS Certificate Manager(ACM)
  • Route53
  • S3
  • RDS(MySQL)
  • ElastiCache(Redis)

CI / CD

  • Jenkins
  • Git Webhook

WebServer

  • Nginx

Domain Register

  • Gabia

 

정리 순서

  1. S3 Bucket 생성 후 Local에서 테스트
  2. RDS MySQL Database Instance 생성 후 Local Workbench와 연결 테스트 및 프로젝트 연결 테스트
  3. EC2 Instance 생성 후 설정
    1. swap 메모리 설정
    2. JDK 17 설치
    3. nvm 설치 및 node 21.7.1 설치
    4. Nginx 설치 및 설정
    5. Jenkins 설치 및 빌드 Job 설정을 제외한 나머지 처리
    6. ElasiCache Redis OSS Cache 생성 및 Redis 설치
  4. Gabia 도메인 구매 후 Route53, ACM 처리
  5. Load Balancer 대상 그룹 생성 및 ALB 생성 후 대상 그룹 설정
  6. A레코드 생성 및 도메인 접근 테스트
  7. git clone을 통해 사전 테스트 이후 Jenkins Job 설정과 Build 테스트
  8. Git Webhook 연동 및 테스트

Application Load Balancer(ALB) 대상그룹 생성

이번에는 ALB와 그 대상 그룹 생성에 대해 정리한다.

먼저 대상그룹을 생성한다.

 

EC2 페이지에서 로드밸런싱 하위의 대상그룹으로 이동.

대상그룹 생성 버튼을 클릭한다.

 

대상 유형은 인스턴스로 선택하고 대상 그룹 이름을 작성해준다.

이후 다른건 건드리지 않는다.

 

아래 이미지에서 상태검사 경로를 /health로 작성했다.

기본 경로는 / 로 설정해도 된다.

하지만 이번 테스트 과정에서 / 로 처리하는 경우 대상 그룹의 health check가 정상적으로 처리되지 않아 불가피하게 nginx 설정에 /health 경로로 응답을 200으로 처리하도록 작성했다.

그렇기 때문에 안되는 경우 이렇게 처리하는 방법이 있다~ 라고 생각하면 된다.

 

여기까지 처리했다면 다음 클릭!

 

다음 페이지에서는 라우팅 대상을 등록해야 한다.

적용할 인스턴스의 체크박스를 체크하고 아래에 보류 중인 것으로 포함 버튼을 누르면 대상으로 해당 인스턴스가 추가될 것이다.

그럼 대상 그룹 생성 버튼 클릭

 

대상 그룹 생성이 완료되었다면 상태 검사를 수행하게 된다.

대상 그룹을 선택하고 하단 탭에서 대상 탭으로 이동하면 상태검사를 확인할 수 있다.

아래 이미지처럼 Healthy로 나와야 정상이다.

UnHealthy로 나온다면 nginx 설정 또는 네트워크 문제일 가능성이 있다.

혹은 경로를 잘못 설정한 경우에도 문제가 발생한다.

 

뭘 해도 안된다면 이 테스트 과정 포스팅 3번째 단계인 EC2 인스턴스에 대한 정리 중에 nginx 정리한 부분을 확인해 /health 요청에 대한 설정을 처리하도록 하고 대상 그룹 상태검사 경로도 /health로 바꾼 뒤 다시 확인하는 방법도 있다.

 

대상 그룹의 상태 검사까지 모두 완료 했다면 Load Balancer를 생성한다.

로드밸런싱 하위의 로드밸런서로 이동해 오른쪽 상단의 로드밸런서 생성 버튼을 클릭해준다.

그럼 아래 이미지와 같은 페이지가 나올텐데 Application Load Balancer를 선택해준다.

 

로드밸런서 이름을 입력해주고 네트워크 매핑에 자신의 리전이 몇가지 나올텐데 선택해준다.

이때, 리전은 2개 이상을 선택해야 한다.

선택하게 되면 서브넷이 나오게 될텐데 알아서 설정되므로 그대로 두면 된다.

 

다음으로는 보안그룹을 선택하게 되는데 최초 생성해두었던 보안그룹을 그대로 선택해준다.

리스너 및 라우팅 탭에서는 기본적으로 80 포트가 추가된 상태일 것이다.

기본 작업에서는 좀전에 만들었던 대상그룹을 선택해주면 된다.

이후 리스터 추가 버튼을 눌러 HTTPS 443 포트를 추가해주고 대상그룹은 동일하게 방금 생성한 대상 그룹을 선택해준다.

 

보안 리스터 설정에서의 보안 정책은 기본적으로 ELBSecurityPolisy가 선택되어 있다.

권장사항이기 때문에 따로 건드리지 않고 넘겼다.

기본 SSL/TLS 서버 인증서는 ACM에서 인증서를 요청해 발급 받았으므로 ACM을 선택하고 인증서 선택을 누르면 발급받은 인증서가 존재할 것이다. 선택!

만약 ACM이 아닌 다른 방식으로 인증서를 받았다면 인증서 가져오기를 선택해서 처리할 수 있다.

 

그럼 모든 처리가 끝났으므로 하단의 로드밸런서 생성 버튼을 클릭해 생성해준다.

 

생성된 ALB는 프로비저닝이 모두 끝나고 상태가 활성으로 변하게 될 것이다.

이 과정을 조금 기다려주고 이후 설정해 줄 것이 하나 있다.

HTTP 포트인 80 포트로 접근했을 때 443으로 Redirect 시켜주도록 처리할 것이다.

 

ALB 세부 정보 하단의 리스너 및 규칙 탭에서 HTTP 규칙을 선택한다.

이미지에서는 이미 수정한 상태이기 때문에 리디렉션 대상 이라고 뜨지만 정상적으로 처리했다면 HTTPS와 동일하게 기본 작업이 출력되는게 정상이다.

 

HTTP:80 을 클릭하고 나면 나오는 페이지에서 오른쪽 상단의 작업 탭을 클릭하고 리스터 편집을 클릭!

 

기본 작업탭에서의 라우팅 액션에서 URL로 리디렉션을 선택해준다.

그리고 URI 부분을 선택하고 프로토콜을 HTTPS로 바꿔준 뒤 443 포트로 수정해준다.

상태코드는 기본 설정인 301을 유지. 변경 내용 저장 버튼을 클릭해 수정해준다.

 

 

그럼 ALB 생성까지 끝!

정리 목적

이번에 AWS에 배포 테스트를 하며 UI가 변경된 부분도 좀 있었고 이전에는 도메인 구매 후 접근 테스트만 해본 반면 이번에는 여러 환경을 설정하고 처리했기 때문에 이전 정리 내용을 지우고 새로 다시 정리.

 

처리 환경 정리

Project

  • BackEnd - Spring Boot 3
  • FrontEnd - React
  • 빌드 방식 - 통합빌드

AWS

  • EC2 t2.micro
    • ubuntu 22.0.4
  • Application Load Balancer
  • AWS Certificate Manager(ACM)
  • Route53
  • S3
  • RDS(MySQL)
  • ElastiCache(Redis)

CI / CD

  • Jenkins
  • Git Webhook

WebServer

  • Nginx

Domain Register

  • Gabia

 

정리 순서

  1. S3 Bucket 생성 후 Local에서 테스트
  2. RDS MySQL Database Instance 생성 후 Local Workbench와 연결 테스트 및 프로젝트 연결 테스트
  3. EC2 Instance 생성 후 설정
    1. swap 메모리 설정
    2. JDK 17 설치
    3. nvm 설치 및 node 21.7.1 설치
    4. Nginx 설치 및 설정
    5. Jenkins 설치 및 빌드 Job 설정을 제외한 나머지 처리
    6. ElasiCache Redis OSS Cache 생성 및 Redis 설치
  4. Gabia 도메인 구매 후 Route53, ACM 처리
  5. Load Balancer 대상 그룹 생성 및 ALB 생성 후 대상 그룹 설정
  6. A레코드 생성 및 도메인 접근 테스트
  7. git clone을 통해 사전 테스트 이후 Jenkins Job 설정과 Build 테스트
  8. Git Webhook 연동 및 테스트

Gabia를 통한 도메인 구매

이번 배포 테스트에서 사용할 도메인은 Gabia에서 구매했다.

이전 테스트때는 freenom에서 무료 도메인을 구매해 사용했었는데 안되길래 알아봤더니 막혔다고 했다.

가비아에서 1년으로 끊으면 그래도 저렴하길래 가비아를 통해 구매했다.

 

가비아에 회원가입을 하고 메인 페이지에서 원하는 도메인을 입력 후 검색할 수 있다.

 

그럼 구매할 수 있는 도메인들이 나오게 되는데 원하는 도메인을 선택하고 우측에 위치한 신청하기 버튼을 통해 구매할 수 있다.

 

구매는 화면만 보고 그냥 할 수 있기 때문에 정리는 패스.

한가지 주의사항으로는 가비아에서 도메인 구매 시 기본 기간이 3년으로 설정되어있기 때문에 검색했을 때의 가격과 다를 수 있다.

그렇기 때문에 기간을 1년으로 선택해야 리스트에서 본 가격대로 구매할 수 있다.

 

아 그리고 500원짜리 고르면 카드 결제 안된다..ㅎ

 

도메인을 구매하고 나면 페이지 우측 상단에 위치한 My가비아에서 구매한 도메인을 확인할 수 있다.

따로 뭘 설정할만한 것이 없기 때문에 미뤄두고 구매가 정상적으로 처리되었는지만 확인하고 도메인을 배포할 서비스와 연결해주기 위한 준비를 한다.

 

Route 53 호스팅 영역 생성

AWS에서 Route 53을 검색하고 호스팅 영역으로 이동해 호스팅 영역 생성 버튼을 클릭한다.

생성 페이지에서는 구매한 도메인을 입력하고 태그가 필요하다면 작성 한 뒤 호스팅 영역 버튼을 클릭해 생성해준다.

도메인 이름에는 구매한 도메인을 넣어주면 된다. 예를 들어 test-project.shop 이런 도메인을 검색하고 구매했다면 그대로 작성해주면 됨.

 

그럼 호스팅 영역이 생성되고 레코드로 NS, SOA 두가지가 있는 것을 확인할 수 있다.

 

 

AWS Certificate Manager(ACM) 인증서 요청

AWS에서 ACM이라고 검색하면 Certificate Manager라고 나온다.

페이지로 이동해 왼쪽에 위치한 인증서 요청을 클릭한다.

 

가장 첫 페이지에서는 퍼블릭 인증서 요청이 선택된 상태일 것이고 다음 버튼을 클릭한다.

 

도메인 이름 탭에서는 도메인을 작성해주고 이후 이 인증서에 다른 이름 추가 버튼을 눌러 도메인 앞에 *. 를 붙여 하나 추가해준다.

www 이나 앞에 다른 것이 붙게 하고자 하는 경우에 사용된다.

다른 설정들은 건드리지 않고 인증서를 요청한다.

 

그럼 인증서가 생성되고 상태가 검증 대기중으로 뜰 것이다.

아래 이미지는 이미 생성해둔 인증서를 캡쳐한 것이기 때문에 상태가 성공으로 뜨지만 검증 대기중으로 뜨는 것이 정상이다.

아래 이미지처럼 도메인 탭에서 Route 53에서 레코드 생성 버튼을 클릭한다.

 

그럼 아래 이미지 같은 페이지가 나오게 되는데 캡쳐할 때는 이미 처리가 된 상태라 없지만 새로 처리하는 경우라면 인증서 요청 시 추가한 도메인의 개수만큼 CNAME 데이터가 존재할 것이다.

그 데이터들을 모두 체크해주고 오른쪽 하단의 레코드 생성 버튼을 눌러주면 Route 53 호스팅 영역에 CNAME이 추가된다.

 

여기까지 해도 아마 성공으로 바뀌지 않을 것이다.

기다리면 성공으로 바뀐다는 글도 많이 봤는데 한번도 그랬던 적이 없기도 하고 보통 그런 경우 빠르면 30분 길면 다음날 이라는 얘기도 있어서 빠르게 처리할 수 있는 방법으로 해결한다.

모든 도메인과 환경에 대해 이 방법이 먹히는지는 모르겠지만 이렇게 처리하면 5분 내로 성공 상태로 바뀌게 된다.

 

가비아 페이지로 이동해 상단 메뉴중 서비스 관리 탭의 서비스 관리로 이동한다.

 

그럼 아래 이미지와 같이 구매한 도메인과 오른쪽에 관리 버튼이 있다.

관리 버튼을 눌러 이동.

 

그럼 아래와 같은 페이지가 나올 것이다.

이미지는 이미 다 처리해둔 상태이기 때문에 네임서버에 데이터가 들어가있지만 최초 설정의 경우 모든 데이터가 데이터 없음으로 나올 것이다.

네임 서버 옆의 설정 버튼을 눌러 설정 페이지로 이동한다.

네임 서버 설정 페이지에서는 Route 53에 있는 NS 레코드를 가져와 복사해서 붙여넣기 해주면 된다.

 

아래와 이미지와 같은 페이지에서 추가 버튼을통해 데이터를 추가할 수 있으며 Route 53에 있는 NS 레코드 데이터 4개를 모두 작성해주면 된다.

가비아에서는 도메인 정보 변경 시 마다 소유자 인증을 해야 하기 때문에 소유자 인증 후 적용 버튼을 눌러 수정해준다.

다음으로 도메인에 CNAME을 설정해준다.

마찬가지로 Route 53에 인증서 요청 후 생성된 CNAME값을 복사해서 붙여넣기 할 것이다.

 

가비아 페이지에서 DNS 정보 탭으로 이동한다.

CNAME 설정을 최초로 하는 도메인이라면 데이터가 없을 것이다.

DNS 관리 버튼을 누르면 'DNS 관리 툴로 이동합니다. 계속 진행하시겠습니까?' 라는 창이 뜨는데 당연히 확인!

 

첫 페이지에서 설정 버튼을 눌러준다.

 

레코드 수정 버튼 클릭!

데이터도 당연히 없는게 정상이다.

 

그럼 아래 이미지와 같은 창이 뜬다.

여기서도 데이터는 당연히 없을 것이고, 추가 버튼을 누르면 두번째 이미지처럼 아래 탭이 추가 된다.

타입을 CNAME으로 선택하고 호스트에는 CNAME의 레코드 이름을, 값/위치에는 레코드 의 값을 넣어준다.

 

호스트에는 input 창 이후 자신의 도메인이 붙어있는 것을 볼 수 있다.

그리고 CNAME 레코드의 이름에도 동일하게 끝에 도메인이 붙어있는 것을 볼 수 있다.

그렇기 때문에 CNAME 레코드 이름에서 뒤에 위치한 도메인을 제외한 나머지만 복사해 붙여넣기 해주면 된다.

값/위치에 대해서는 레코드의 값을 가져와 붙여넣기 해주되 끝에 붙어있는 . 은 제거해줘야 한다.

그리고 확인 버튼을 누르면 정상적으로 추가가 되는 것을 확인할 수 있다.

 

그리고 한번 더 레코드 추가를 눌러 타입을 A로 선택하고 호스트에는 www 를, 값 / 위치에는 EC2 인스턴스의 public IP를 적어준다.

모두 입력했다면 저장!

 

그리고 ACM 페이지로 이동해 조금 기다리면서 새로고침 한번씩 해보면 금방 상태가 발급 됨으로 바뀌는 것을 확인 할 수 있다.

 

가비아에서는 A 레코드를 설정했지만 Route 53에는 A 레코드가 아직 없는데 상관없다.

어차피 이후에 Route 53에도 A 레코드를 설정할 것이고 그때 다시 설정하지 않기 위해 미리 설정한 것이기 때문에!

정리 목적

이번에 AWS에 배포 테스트를 하며 UI가 변경된 부분도 좀 있었고 이전에는 도메인 구매 후 접근 테스트만 해본 반면 이번에는 여러 환경을 설정하고 처리했기 때문에 이전 정리 내용을 지우고 새로 다시 정리.

 

처리 환경 정리

Project

  • BackEnd - Spring Boot 3
  • FrontEnd - React
  • 빌드 방식 - 통합빌드

AWS

  • EC2 t2.micro
    • ubuntu 22.0.4
  • Application Load Balancer
  • AWS Certificate Manager(ACM)
  • Route53
  • S3
  • RDS(MySQL)
  • ElastiCache(Redis)

CI / CD

  • Jenkins
  • Git Webhook

WebServer

  • Nginx

Domain Register

  • Gabia

 

정리 순서

  1. S3 Bucket 생성 후 Local에서 테스트
  2. RDS MySQL Database Instance 생성 후 Local Workbench와 연결 테스트 및 프로젝트 연결 테스트
  3. EC2 Instance 생성 후 설정
    1. swap 메모리 설정
    2. JDK 17 설치
    3. nvm 설치 및 node 21.7.1 설치
    4. Nginx 설치 및 설정
    5. Jenkins 설치 및 빌드 Job 설정을 제외한 나머지 처리
    6. ElasiCache Redis OSS Cache 생성 및 Redis 설치
  4. Gabia 도메인 구매 후 Route53, ACM 처리
  5. Load Balancer 대상 그룹 생성 및 ALB 생성 후 대상 그룹 설정
  6. A레코드 생성 및 도메인 접근 테스트
  7. git clone을 통해 사전 테스트 이후 Jenkins Job 설정과 Build 테스트
  8. Git Webhook 연동 및 테스트

EC2 Instance 생성

AWS에서 EC2 페이지에 접근한다.

인스턴스 탭으로 이동하면 오른쪽 상단에 인스턴스 시작 버튼이 존재하니 클릭!

아래와 같은 페이지가 출력된다.

이름은 EC2 Instance 이름이다.

애플리케이션 및 OS 이미지는 ubuntu 22.04를 사용했기 때문에 Ubuntu를 선택하고 22.04를 선택했다.

아마 ubuntu 선택하고 나면 24년 7월 기준 24.04 가 기본 설정일텐데 22.04로 바꾸게 되면 하단의 이미지처럼 안내창이 뜰 것이다.

그냥 설정 중에 일부가 변경될 것이라는 안내이기 때문에 변경 확인 눌러주면 된다.

 

인스턴스 유형은 프로젝트가 크지 않기 때문에 t2.micro를 선택한다.

프리티어 계정이라면 micro를 사용해야 요금이 발생하지 않는다.

만료되었더라도 nano는 너무 작고 Micro가 그래도 싸니까 선택!

다음은 키페어를 생성한다.

이미 키페어가 존재한다면 해당 키페어를 선택할 수 있을 것이고 없다면 새 키페어 생성을 눌러 생성해준다.

 

새 키 페어 생성을 누르면 아래와 같은 창이 뜬다.

키페어의 이름을 입력하고 유형은 RSA 그대로 유지.

파일형식은 .pem으로 선택한다. ppk는 예전에 못봤는데 window 환경이라면 Putty를 통해 접근할 때는 ppk를 사용해야 될지는 알아봐야함..... 전에는 윈도우에서 Putty로 접근해도 pem 쓰긴했는데..

mac 환경이라 .pem으로 선택!

키페어 생성을 해준다.

생성하고 나면 키페어 탭에서 생성한 키페어가 들어가있을 것이기 때문에 선택해준다.

 

다음은 네트워크 설정이다.

방화벽(보안그룹)에서는 기존 보안그룹을 선택하고 RDS 생성 전 만들어두었던 보안그룹을 선택해준다.

 

스토리지 구성은 무조건 최대치 30!!

기본 설정인 8GB로 했다가 한참 모자라서 다시 생성했슴다..

딱 EC2 생성해서 git에서 프로젝트 clone 받고 서버 실행만 할거라면 8GB도 괜찮을지 모르겠지만 이것저것 설치하고 뭐하고 하면 한참 모자라기도 해서 30이 좋다.

 

그럼 이제 오른쪽의 인스턴스 시작 버튼을 누르면 인스턴스 생성이 시작된다.

완전히 완료되기까지는 시간이 쪼금 걸리니 기다려줬다가 상태가 실행중으로 변경되고 상태 검사에 검사 통과가 뜬다면 모두 마무리 된 것이므로 정상적으로 생성되어 실행되고 있다고 볼 수 있다.

 

탄력적 IP 생성 및 EC2 Instance에 연결

그럼 이제 다음으로 탄력적 IP를 생성하고 연결해준다.

생성 전에 유의사항으로 탄력적 IP는 인스턴스에 연결하지 않는 경우 요금이 발생하므로 바로바로 연결해주도록 해야하고 인스턴스를 삭제한다면 탄력적 IP도 바로바로 삭제하는게 좋다.

 

왼쪽 탭에서 네트워크 및 보안 -> 탄력적 IP로 이동한 뒤 오른쪽 상단의 탄력적 IP 주소 할당 클릭!

따로 설정하거나 작성해야 하는 부분은 없기 때문에 캡쳐는 따로 하지 않았다.

태그 작성이 있긴한데 선택사항이므로 태그가 필요하다면 작성 후 할당 버튼을 클릭해 생성해주면 된다.

 

리스트에 탄력적 IP가 추가된 것을 볼 수 있을 것이고, 해당 IP에서 마우스 오른쪽 버튼을 클릭해 탄력적 IP 주소 연결을 선택한다.

그럼 아래 이미지와 같은 창으로 이동하게 될건데 인스턴스 선택을 누르면 생성한 인스턴스가 나올 것이다.

해당 인스턴스를 선택해주고 프라이빗 IP 주소를 누르면 알아서 선택한 EC2 인스턴스의 프라이빗 IP가 나오니 선택해준다.

그리고 연결 버튼 클릭!

 

 

 

EC2에 접속

접속 환경은 mac 기준입니다.

window는 putty를 통한 접근이 가능할텐데 예전에 정리해둔게 있긴 하지만 바뀌었을 수도 있긴 합니다.

이전에 정리해둔 내용은 아래 링크에서 확인.

https://myyoun.tistory.com/156

 

 

mac에서는 터미널을 열고 아래 명령어를 통해 EC2에 접속할 수 있다.

ssh -i .pem파일 경로/000.pem ubuntu@EC2 public IP주소

 

EC2 public IP 주소는 EC2에서 해당 인스턴스를 선택해보면 하단에 나오는 정보를 통해 확인할 수 있다.

위 링크에도 정리해뒀는데 ubuntu가 아닌 다른 환경은 ubuntu 대신 다른 명령어가 들어간다.

 

 

배포를 위한 EC2 기본 설정 및 설치

처리할 내용들은 아래와 같다.

  1. swap 메모리 설정
  2. JDK 17 설치
  3. nvm 설치 및 node 21.7.1 설치
  4. Nginx 설치 및 설정
  5. Jenkins 설치 및 빌드 Job 설정을 제외한 나머지 처리
  6. ElastiCache Redis OSS 캐시 생성 및 Redis 설치

 

1. swap 메모리 설정

swap이 뭔지 먼저 이해해야 한다.

swap이란 Linux 기반 운영체제에서 가상 메모리로 작동하는 저장장치의 전용 공간이다.

시스템의 사용 가능한 메모리가 부족할 때 물리적 RAM을 보충하는데 사용된다.

swap 공간을 통해 운영체제는 자주 사용되지 않는 데이터를 RAM에서 swap 영역으로 이동시켜 더 중요하거나 자주 사용되는 데이터를 위해 RAM 공간을 확보할 수 있다.

 

swap 공간은 linux 커널 메모리 관리 하위 시스템에서 제어하는 디스크 영역이다.

커널은 메모리에 비활성 페이지를 보관하여 시스템 RAM을 보완하기 위해 swap 공간을 사용한다.

시스템의 가상 메모리에는 결합된 시스템 RAM과 swap 공간이 포함된다.

 

swap 영역이 디스크에 상주하기 때문에 swap은 RAM에 비해 속도가 느리다.

swap 공간은 시스템 RAM을 늘리는데 사용되지만 Work Load에 비해 RAM이 부족한 경우 swap 공간을 지속 가능한 해결책으로 간주해서는 안되며, 물리적 메모리를 늘리는 것이 좋다.

 

참고

https://easyitwanner.tistory.com/149

 

[Linux 명령어] swap이란? (+ swap 관련 명령어)

SWAP 스왑은 Linux 기반 운영 체제에서 가상 메모리로 작동하는 저장 장치(예: HHD, SSD, 가상 저장 장치)의 전용 공간이다. 시스템의 사용 가능한 메모리가 부족할 때 물리적 RAM(Random Access Memory)을 보

easyitwanner.tistory.com

 

 

아주아주 간단하고 단순하게 정리하면 t2.micro의 램은 1GB 밖에 안돼서 이걸 확장하고자 swap을 사용한다.

확장이라는게 정말 RAM의 공간이 늘어나는 것은 아니고 자주 사용하지 않는 것을 swap 영역으로 빼고 새로운 프로세스가 RAM에 할당되도록 하는 것!

 

swap 영역을 설정한 이유는 Jenkins 때문이다.

기본 설치만 하고 Jenkins 잘 연결 됐나~ 테스트 했더니 메모리 부족으로 인해 서버가 멈추는 상황이 발생했고, 그로 인해 swap 영역을 설정해봤더니 이정도로 가능했다.

만약! swap 영역을 설정했는데도 서버가 멈춘다면 인스턴스 유형을 t2.micro가 아닌 상위 성능의 유형을 선택해야 한다.

 

swap 공간의 크기는 권장사항이 어느정도 설정되어있다. 무조건 따라야 하는 정도의 사항은 아니라고 하지만 어느정도는 맞춰주는 것이 좋다고 생각한다.

이 권장 사항에 대해서는 위 링크에서 잘 정리해주셨다.

 

그럼 이제 설정 시작!

권장 사항에 따라 swap 공간의 크기를 RAM의 2배로 설정한다.

t2.micro는 1GB의 메모리를 갖기 때문에 2GB로 설정해준다.

sudo dd if=/dev/zero of=/swapfile bs=128MB count=16

 

dd 명령어를 통해 root File System에 swap file을 생성하게 된다.

bs의 경우 블록의 크기를 의미하고 count는 블록의 수를 의미한다.

그래서 128 * 16으로 2048MB를 설정하게 된다.

이때 지정한 블록 크기는 인스턴스에서 사용가능한 메모리보다 작아야 한다.

그렇지 않다면 memory exhausted 오류가 발생한다.

 

 

다음으로 swap file에 대해 읽기 및 쓰기 권한을 수정하고 Linux swap 영역을 설정한다.

이후 swap 공간에 swap file을 추가해 swap file을 즉시 사용할 수 있도록 만들어준다.

sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile

# 모두 성공했는지 확인
sudo swapon -s

 

swapon -s 명령어를 입력했을 때 Filename에 /swapfile이 나와야 한다.

 

이제 /etc/fastb 파일을 편집해 부팅 시 swap file이 활성화 되도록 해준다.

아래 명령어로 fstab 파일을 열어주고

/swapfile swap swap defaults 0 0 을 가장 마지막 줄에 추가해준 뒤 저장하고 종료하면 된다.

sudo vi /etc/fstab

 

그리고 아래처럼 free -h 를 입력했을 때 이미지와 같이 swap total이 2.0Gi가 되었다면 성공이다!

 

 

2. JDK17 설치

프로젝트 환경과 일치하는 JDK 17을 설치한다.

어려운 것은 없기 때문에 짧게 정리.

sudo apt-get update
sudo apt-get install openjdk-17-jdk

# openjdk version "17.0.11" 이런식으로 출력되어야 한다. 설치기간에따라 조금 차이는 있을 수 있다.
java -version

# 환경변수 설정
sudo vi /etc/profile

# /etc/profile 최하단에 아래 코드를 추가한 뒤 저장한다.
export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64
export PATH=$PATH:$JAVA_HOME/bin
export CLASSPATH=$JAVA_HOME/jre/lib:$JAVA_HOME/lib/tools.jar

#EC2 Instance reboot
sudo reboot now

#적용 확인
echo $JAVA_HOME
echo $PATH
echo $CLASSPATH

 

혹시 apt-get update 명령어를 수행했을 때 Some index files failed to download. They have been ignored, or old ones used instead. 라는 오류가 발생한다면 보안그룹의 아웃바운드 규칙을 확인한다.

아웃바운드 규칙이 모든 트래픽을 허용하고 있지 않다면 오류가 발생한다.

 

아웃바운드 규칙을 허용하는 것 만으로 문제를 해결했지만 그렇지 않은 경우도 있다고 해 그 방법들도 정리한다.

 

가장 먼저 DNS가 제대로 잡히지 않아 발생하는 경우가 있다고 한다.

이런경우 /etc/resolvl.conf에서 nameserver를 8.8.8.8로 수정해준다.

 

다음 방법은 /etc/apt/sources.list를 수정하는 방법이다.

오류를 검색했을 때 가장 많이 나오는 해결 방안이다.

기본 구조는 리전.ec2.archive.ubuntu.com/ubuntu/jammy main restricted ~~~ 이런 구조일 것이다.

이게 몇줄에 걸쳐서 조금씩 차이가 있는 구조로 작성되어 있을 텐데 이 주소를 모두 수정해주면 된다.

 

일단 수정할 값의 선택지는 몇개를 확인할 수 있었다.

  1. ftp.daumkakao.com/ubuntu
  2. ftp.daum.net/ubuntu
  3. kr.archive.ubuntu.com/ubuntu

이 세개의 주소를 하나씩 넣어보면서 확인해야 할 것 같다.

이 오류가 발생하는 이유에 대해 보통 서버측 오류일 가능성이 크다고 많이들 판단하시는 것 같다.

 

그럼 이걸 하나하나 바꾸기는 어려우니 vim 명령어를 통해 한번에 수정해준다.

/etc/apt/sources.list 에 vim으로 접근하고 하단에 아래와 같은 명령어를 입력하면 한번에 바꿔줄 수 있다.

예시는 3번 주소로 바꾸는 예시다.

:%s /archive.ubuntu.com/ubuntu /kr.archive.ubuntu.com/ubuntu

 

근데 뭐가됐던 일단 아웃바운드가 열려있어야 한다!!!!

 

 

3. nvm 설치 및 node 21.7.1 설치

다음은 React 환경과 동일한 node 21.7.1 버전을 설치한다.

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.4/install.sh | bash

source ~/.bashrc

nvm install 21.7.1

# 21.7.1을 사용하겠다는 명령어
nvm use 21.7.1

# 21.7.1을 default 버전으로 설정
nvm alias default 21.7.1

# node 버전 확인
node -v

 

이것도 딱히 정리할 내용은 없어서 패스!

 

4. Nginx 설치

Nginx의 설치는 아래 명령어로 처리한다.

그리고 알아서 실행된다고 하지만 확실하게 명령어를 통해 실행시켰다.

sudo apt-get install nginx

sudo service nginx start

 

Nginx 설정 파일을 생성하고 적용해야 한다.

Nginx 설치 이후 /etc/nginx/sites-available에 접근하면 default라는 파일이 존재한다.

이 파일을 수정하는 케이스도 봤지만 파일을 만들어서 처리하는 경우가 더 많이 보였기 때문에 해당 방법으로 처리했다.

 

새로운 파일로 test.conf라는 파일을 만들어주고 이 파일을 sites-enabled에 심볼릭 링크를 만들어 이 설정파일을 통해 처리하도록 하는 과정이다.

예시로 도메인은 nvaer.com이라고 가정했고, EC2 public IP는 11.111.111.111로 가정했다.

만약 이 포스팅들을 처음부터 보고 있다면 도메인은 없을테니 public IP만 알고 있으면 된다.

 

cd /etc/nginx/sites-available

# 이 명령어를 수행했을 때 default가 존재해야 한다.
ls -al

# test.conf 파일을 생성한다. 이름은 상관없고 .conf로만 만들어주면 된다.
sudo vi test.conf

# test.conf의 내용
server {
    listen 80; # IPv4
    listen [::]:80; # IPv6
    
    # 도메인 연결이 안되었다면 임시로 EC2 public IP를 적는다. 도메인 연결후 수정하면 됨.
    server_name naver.com
    
    # 배포할 프로젝트의 메인 경로로 설정. 만약 localhost:8080/main이 메인 경로라면 / 가 아닌 /main으로.
    location / {
        proxy_pass http://11.111.111.111:8080; #EC2 public IP와 프로젝트 서버 포트 작성
        proxy_set_header X-Real-IP $remote_addr;
		proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
		proxy_set_header Host $http_host;
		proxy_set_header X-Forwarded-Proto $scheme;
    }
    
    # ALB 대상그룹 Health check에 활용
    # 원래라면 상단의 메인 경로를 통해 체크되는데 뭘해도 저 경로로 잡히지가 않아서 불가피하게 추가
    # 메인 경로로 health check가 되지 않는다면 아래 코드를 작성.
    location /health {
        return 200 'healthy';
        add_header Content-Type text/plain;
    }
}

# sites-enabled에 심볼릭 링크 생성
sudo ln -s /etc/nginx/sites-available/test.conf /etc/nginx/sites-enabled

# site-enabled에 default가 존재한다면 default만 적용되기 때문에 제거해준다.
# 제거하더라도 site-available에는 존재하기 때문에 백업을 따로 할 필요는 없다.
# 주의 해야할 사항은 site-enabled에 존재하는 default만 제거해야 한다.
sudo rm default

# nginx 재구동
sudo service nginx reload
# or
sudo service nginx restart
# or
sudo systemctl restart nginx

 

여기에 추후 추가되는 사항도 있다.

만약 ACM을 통해서 인증서를 받지 않는 경우에는 80포트 아래에 443 포트도 추가해줘야 하고 그렇게 되면 인증서 정보가 꼭 들어가줘야 한다.

테스트는 ACM을 통해 인증서를 발급 받았기 때문에 위 내용으로 처리가 가능하지만 그렇지 않은 경우는 아래와 같이 작성해준다.

 

# test.conf
server {
	listen 80; # IPv4
	listen [::]:80; #IPv6
	listen 443; # https 포트 추가.
	listen [::]:443;
	
	server_name naver.com # 도메인명 혹은 public IP
	
    # 인증서 설정 추가
	ssl_certificate /certificate 경로/certificate.crt;
	ssl_certificate_key /cerficiate key 경로/private.key;
	
	location / {
		proxy_pass http://11.111.111.111:8080; # public IP
		proxy_set_header X-Real-IP $remote_addr;
		proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
		proxy_set_header Host $http_host;
		proxy_set_header X-Forwarded-Proto $scheme;
	}
	
	# AWS 대상그룹 Health check를 위해 필요
	location /health {
		return 200 'healthy';
		add_header Content-Type text/plain;
	}
}

 

443 포트까지 설정했는데 인증서 정보가 없다면 오류가 발생한다.

가장 아래에 /health는 이후 ALB 대상 그룹 생성의 health check에 사용되는데 원래는 그냥 기본 메인 경로를 통해 체크가 되었었는데 뭘 해도 안되길래 추가해서 200을 반환하도록 처리했더니 정상적으로 동작했다.

처음부터 추가할 필요는 없고 만약 대상 그룹에서 health check가 되지 않는다면 그때 작성해서 시도해보는 것도 좋을듯!

 

5. Jenkins 설치 및 빌드 Job 설정을 제외한 나머지 처리

 

Jenkins 설치와 페이지 접근, Jenkins의 계정 생성까지 정리.

Jenkins도 이전과 설치 방법이 좀 바뀌엇다.

# Jenkins 공개키 다운로드 및 저장
curl -fsSL https://pkg.jenkins.io/debian-stable/jenkins.io-2023.key | sudo tee \ /usr/share/keyrings/jenkins-keyring.asc > /dev/null

# Jenkins Repository 추가
echo deb [signed-by=/usr/share/keyrings/jenkins-keyring.asc] \ 
https://pkg.jenkins.io/debian-stable binary/ | sudo tee \
/etc/apt/sources.list.d/jenkins.list > /dev/null

# 패키지 목록 업데이트 후 Jenkins 설치
sudo apt update
sudo apt install jenkins

# 상태 확인
sudo systemctl status jenkins

# 초기 비밀번호 ( 따로 메모 )
sudo cat /var/lib/jenkins/secrets/initialAdminPassword

# 포트 변경전 권한 수정
sudo chmod 777 /usr/lib/systemd/system/jenkins.service
# 포트 번호 원하는 번호로 수정 후 저장
sudo vi /usr/lib/systemd/system/jenkins.service
# 꼭 권한을 다시 원래대로 수정한다
sudo chmod 444 /usr/lib/systemd/system/jenkins.service

# jenkins 재시작
sudo systemctl daemon-reload
sudo serivce jenkins restart


# 만약 그래도 변경되지 않았다면 아래 파일에서도 포트 변경 후 재시작
sudo vi /etc/default/jenkins

 

설치는 위 과정을 따라가기만 하면 무리없이 처리된다.

상태 확인 명령어를 수행했을 때 active가 정상적으로 나와야 하고 초기비밀번호의 경우 Jenkins 페이지 접근했을 때 필요하므로 저장해두도록 한다.

 

Jenkins 설치 이후에는 8080이 기본 포트로 설정되는데 프로젝트에서 8080 포트를 사용하기 때문에 9095 포트로 변경해줄 필요가 있어 포트 번호를 수정해준다.

 

마지막 재시작까지 수행하고 나면 EC2 public IP:jenkinsport 를 통해 페이지에 접근할 수 있다.

그럼 가장 먼저 비밀번호를 입력하라고 하는데 중간에 조회했던 초기 비밀번호를 붙여넣기 해준다.

 

그럼 이제 아래와 같은 페이지가 나오게 되는데 설정에 따라 다르겠지만 Install suggested plugins를 선택해 기본 플러그인들을 설치하도록 한다.

 

플러그인 설치가 완료된 이후에는 아래처럼 계정 생성 페이지가 나오는데 스킵해도 되지만 계정을 생성해줬다.

 

그럼 아래처럼 접근 URL이 나온다.

보통 접근한 URL이 그대로 나오기 때문에 딱히 건드릴 필요는 없을 것 같다.

 

이후 Jenkins 메인 페이지에서 Jenkins 관리 탭으로 이동한다.

System Configuration의 Plugins 로 이동.

Available plugins 탭으로 이동해 설치할 플러그인들을 설치해야 한다.

설치할 플러그인은 아래와 같다.

  1. Post build task
  2. NodeJS
  3. GitHub Integration

 

플러그인을 하나 설치할때마다 재부팅 선택지가 있는데 이건 따로 언급되는 것을 본적이 없다.

그래도 그냥 있는 기능이니까 재부팅을 해줬다.

 

Post build task는 빌드를 처리할 때 사용할 것이고, NodeJS는 React 빌드를 위해 설치했다.

GitHub Integration은 git webhook 연동에 사용된다.

 

모든 플러그인을 설치했다면 Node에 대해 설정해줘야 할 것이 있다.

다시 Jenkins 관리 탭으로 이동해 이번에는 System Configuration의 Tools로 이동한다.

 

그리고 하단으로 쭉 내려보면 NodeJS Installiations가 존재한다.

이미지는 이미 설정해둔 상태라 그렇지만 Add NodeJS라는 버튼이 빨간 박스 위치에 있을 것.클릭!!

EC2 인스턴스에 설치한 것과 동일한 21.7.1 버전을 사용하도록 하는 과정이다.

Install automatically를 체크해 자동으로 설치하도록 한다.

다 처리했다면 Apply 누른뒤 Save!

 

그럼 이제 Jenkins에서 빌드를 제외한 기본적인 설정은 끝이다.

 

 

6. ElastiCache Redis OSS 캐시 생성 및 Redis 설치

EC2에 Redis를 설치하기 전 ElastiCache에서 Redis OSS 캐시를 생성한다.

AWS에서 ElastiCache로 접근하고 리소스 하위에 있는 Redis OSS 캐시 탭으로 이동해 Redis OSS 캐시 생성 버튼을 클릭한다.

 

아래 이미지처럼 배포 옵션에서는 자체 캐시 설계를 선택하고 생성 방법은 클러스터 캐시로 선택한다.

클러스터 모드는 비활성화를 선택한다.

테스트이기 때문에 굳이 사용할 것 같지 않은데다가 활성화 하면 추가적인 요금도 발생한다.

 

클러스터 정보에는 이름을 작성해주면 된다.

 

위치 탭에서는 위치에 대해 AWS 클라우드를 선택하고 클러스터 설정에서 포트는 기본값 그대로 유지했다.

위치 탭의 다중 AZ는 이미지와 다르게 활성화된 상태일텐데 클러스터 설정 하단의 복제본 개수를 0으로 바꿔주면 비활성화 된다.

이것도 테스트에 필요하진 않아서 0으로 수정했다.

노드 유형의 경우 24년 7월 기준으로 기본 값이 cache.r7g.large로 되어있다.

이렇게 큰게 필요없기도 하고 이것도 유형 선택에 따라 요금이 달라지기 때문에 프리티어에 해당하는 t3.micro를 선택했다.

 

연결 탭에서는 새 서브넷 그룹 생성을 선택하고 서브넷명을 작성해준다.

그리고 서브넷 선택됨 탭의 관리 버튼을 눌러 자신의 리전에 해당하는 서브넷을 선택해주면 되는데 여러개를 선택할 수 있다.

 

가용영역 배치는 따로 건드릴 것은 없어서 그대로 두고 다음 버튼을 클릭!

 

다음 페이지인 고급 설정에서는 보안 그룹만 선택해주고 나머지는 건드리지 않았다.

보안 그룹 역시 기존에 생성한 모든 환경에 대해 열어준 그 보안 그룹을 선택했다.

여기서 다시 한번 생각해보면 왜 보안그룹을 하나로 처리하지 말아야 하는지 알 수 있다.

열어줘야 하는 인바운드 규칙은 6379 포트 하난데 하나의 보안그룹을 사용하면 괜히 Redis cache에 80, 443, 8080 등등 규칙이 들어가 있게 된다.

뭐.. 일단은 테스트니까~

 

하단의 다음 버튼을 누르면 생성이 완료되고 이제 EC2에서 Redis를 설치한다.

 

sudo apt-get update

# build-essential과 wget 설치
sudo apt-get install build-essential wget

# Redis의 최신 버전을 포함하는 tar.gz 다운로드
wget http://download.redis.io/redis-stable.tar.gz

# 다운로드 받은 파일 조작
tar xvzf redis-stable.tar.gz

cd redis-stable
make distclean
make

# redis 접속
# -h 이후에는 ElasticCache 엔드 포인트를 적는다. com 뒤에 포트는 ' : '가 아닌 -p로 수정해준다.
src/redis-cli -c -h RedisOSS 캐시 기본 엔드포인트 -p 6379

 

여기서는 조금 생소했던 tar xvzf ~~~ 코드에 대해 조금 정리를 한다.

tar는 tar 아카이브 조작을 위한 유틸리티이다.

xvzf는 각각 의미가 있는데 아래와 같은 의미를 갖는다.

  • x - 파일 추출
  • v - 자세한 모드(추출 과정을 보여준다)
  • z - gzip 압축 해제
  • f - 파일 지정

 

make distclean도 정리.

make는 Makefile을 읽고 소프트웨어를 빌드하는 명령어다.

distclean은 모든 빌드 아티팩트와 설정 파일을 제거하여 소스트리를 초기 상태로 되돌리는 make 타겟이다.

주로 이전 필드의 잔여물을 제거하기 위해 사용한다.

이후 make 명령어는 Makefile에 정의된대로 소스코드를 빌드한다. 여기서는 Redis 서버와 클라이언트 프로그램이 컴파일 된다.

 

그럼 이제 마지막 라인에 작성된 명령어를 통해 redis에 접속할 수 있다.

이때 명령어 입력 위치는 redis-stable이다.

명령어를 입력할 때 엔드포인트는 포트를 제외한 com 까지만 작성해주면 된다.

 

Redis 접속 이후 정상 동작하는지 명령어를 통해 체크하면 된다

 

프로젝트의 application.yml에서도 redis 관련 정보 host에 엔드포인트를 작성하면 되는데 접속 명령어때와 마찬가지로 com 까지만 작성해주면 된다!

정리 목적

이번에 AWS에 배포 테스트를 하며 UI가 변경된 부분도 좀 있었고 이전에는 도메인 구매 후 접근 테스트만 해본 반면 이번에는 여러 환경을 설정하고 처리했기 때문에 이전 정리 내용을 지우고 새로 다시 정리.

 

처리 환경 정리

Project

  • BackEnd - Spring Boot 3
  • FrontEnd - React
  • 빌드 방식 - 통합빌드

AWS

  • EC2 t2.micro
    • ubuntu 22.0.4
  • Application Load Balancer
  • AWS Certificate Manager(ACM)
  • Route53
  • S3
  • RDS(MySQL)
  • ElastiCache(Redis)

CI / CD

  • Jenkins
  • Git Webhook

WebServer

  • Nginx

Domain Register

  • Gabia

 

정리 순서

  1. S3 Bucket 생성 후 Local에서 테스트
  2. RDS MySQL Database Instance 생성 후 Local Workbench와 연결 테스트 및 프로젝트 연결 테스트
  3. EC2 Instance 생성 후 설정
    1. swap 메모리 설정
    2. JDK 17 설치
    3. nvm 설치 및 node 21.7.1 설치
    4. Nginx 설치 및 설정
    5. Jenkins 설치 및 빌드 Job 설정을 제외한 나머지 처리
    6. ElasiCache Redis OSS Cache 생성 및 Redis 설치
  4. Gabia 도메인 구매 후 Route53, ACM 처리
  5. Load Balancer 대상 그룹 생성 및 ALB 생성 후 대상 그룹 설정
  6. A레코드 생성 및 도메인 접근 테스트
  7. git clone을 통해 사전 테스트 이후 Jenkins Job 설정과 Build 테스트
  8. Git Webhook 연동 및 테스트

RDS MySQL Database Instance 생성

RDS instance를 생성하기 전 보안그룹을 먼저 생성하는게 편하다.

테스트이기 때문에 하나의 보안그룹을 통해 모든 환경에서 사용하도록 했으나 각 환경에 따라 분리하는 것이 더 좋을 수 있다.

 

생성하는 보안그룹은 모든 AWS 환경에 적용할 것이다.

AWS EC2로 이동해 네트워크 및 보안 -> 보안 그룹으로 이동해 보안 그룹 생성 버튼을 눌러 생성해준다.

인바운드 규칙과 아웃바운드 규칙을 설정해준다.

아래 이미지를 보면 두개씩 설정된 유형이 있는데 각각 IPv4와 IPv6에 대한 설정이기 때문.

그리고 아래 이미지와 동일하게 설정한다면 모든 포트 접근에 대해 누구나 접근할 수 있는 설정을 해주는 것이다.

즉, 테스트니까 이렇게 해도 되는거지 이 방법이 맞는 방법은 아니다.

HTTP, HTTPS의 경우 사용자의 아이피를 특정해 모두 작성할 수 없기 때문에 아무나 접근할 수 있어야 하지만 EC2 인스턴스에 접근 할 수 있는 SSH 같은 경우는 자신의 아이피만 설정해준다거나 하는 처리가 필요하다.

열어준 인바운드 규칙을 보면 유형으로 유추 할 수 있는 규칙을 제외하고 8080과 9095 두개가 더 있다.

8080은 프로젝트 서버 포트고 9095는 추후 Jenkins 포트로 사용한다.

아웃 바운드 규칙에 대해서는 모든 트래픽에 대해 허용하는 설정 그대로 둔다.

이전에 테스트했을 때는 아웃바운드 규칙이 따로 분리가 안되어있어서 처음에 설정 안하고 삭제했더니 EC2에서 뭐 설치할 때 막힌다..

아웃바운드 규칙 다 삭제하고 막아두었다가 EC2 인스턴스 한 5번은 재생성 한 것 같으니 절대 열어준다!!!!

인바운드 규칙은 해당 포트로 접근하는 것에 대한 보안 설정이라면 아웃바운드는 서버에서 외부로 요청하는 것에 대한 설정이기 때문에 완전히 폐쇄적으로 외부 요청을 차단하는 경우가 아니라면 설정해줘야 하며, 내부에서 관리가 잘 되어야 한다.

 

 

그럼 이제 RDS를 생성한다.

RDS로 이동해 대시보드에서 데이터베이스 생성 버튼을 클릭

 

데이터베이스 생성 방식은 표준 생성을 통해 생성했다.

엔진 옵션으로는 MySQL을 선택.

 

엔진 버전에서는 사용할 MySQL 버전을 선택한다.

템플릿은 기본으로 프로덕션에 선택이 되어있는데 테스트이기 때문에 프리티어를 선택해준다.

프리티어 계정이라면 프리티어를 사용해야만 요금이 발생하지 않는다.

그리고 프리티어가 끝난 계정이더라도 프리티어로 생성하는게 싸다.

프리티어를 선택하는 경우 가용성 및 내구성에 대한 설정은 할 수 없게 된다.

 

 

설정 탭에서는 필수 입력으로 DB 인스턴스 식별자와 마스터 사용자 이름, 암호 및 확인이 필요하다.

입력해주고 자격증명 관리는 자체 관리를 선택했다.

마스터 암호는 프로젝트 서버의 설정 파일에도 필요하고 로컬에서 Workbench에 연결할때도 필요하다.

마스터 사용자 이름과 암호는 그냥 흔히 로컬에서 root 계정과 암호라고 보면 된다.

인스턴스 구성 탭에서는 프리티어를 선택하는 경우 버스터블 클래스로 고정되기 때문에 그대로 두면 된다.

 

 

스토리지는 테스트 용도이기 때문에 따로 손대지 않았고 기본값으로 유지.

 

연결 탭에서는 EC2 컴퓨팅 리소스에 연결 안함을 택했다.

네트워크 유형의 경우 IPv6까지 해줄 필요는 없었기 때문에 IPv4를 선택.

퍼블릭 액세스를 ' 예 ' 로 체크해줬다.

 

보안 그룹에서는 기존 보안 그룹을 선택하는데 인스턴스 생성 전 만들었던 보안그룹을 선택한다.

보안그룹 하단의 추가 구성을 누르면 포트 설정이 나오고 변경할 수 있는데 기본 포트를 사용할 것이라면 그대로 두고 수정할 계획이라면 수정. 대신 수정하는 경우 보안 그룹에서 3306 포트가 아닌 수정한 포트 설정으로 인바운드 규칙을 설정해줘야 한다.

데이터베이스 인증은 암호 인증으로 선택해 마스터 암호로 접근할 수 있도록 해ㅑㅆ다.

 

테스트기 때문에 모니터링도 따로 활성화 하진 않았다.

모니터링 탭 하단의 추가 구성은 닫혀있을 건데 열어서 초기 데이터베이스 이름을 작성해준다.

필수까지는 아니지만 작성하지 않는다면 RDS에서 데이터베이스를 생성하지 않기 때문에 미리 작성하는게 편하다.

배포할 프로젝트에 연결할 데이터베이스 이름을 작성해준다.

백업도 따로 필요하진 않았지만 체크된 상태로 유지했다.

그럼 모든 설정이 끝났다.

최하단에는 요금에 대한 설명이 나오니 한번 확인하고 데이터베이스 생성 버튼을 클릭해 생성한다.

 

 

생성이 완료되었다면 데이터베이스명을 클릭해 정보로 들어가 연결 및 보안 탭에서 엔드포인트를 복사한다.

 

 

RDS를 프로젝트와 Local Workbench에 연결

 

RDS 엔드포인트는 두군데서 사용한다.

  1. 프로젝트 application.yml
  2. Workbench

 

설정에 따라 조금씩 차이가 있을 수 있지만 아래와 같은 구조일텐데 localhost 부분에 엔드포인트를 붙여넣기 해주면 된다.

datasource:
  url: mysql://localhost:3306/database_name?....
  username: RDS 마스터 사용자 이름
  password: RDS 마스터 사용자 암호

 

그럼 프로젝트와 연결을 끝!!

 

다음은 Workbench와 연결한다.

Workbench를 열어주고 MySQL Connections 옆에 보면 + 버튼이 있다.

클릭!

 

버튼을 눌러 열리는 창에서 Connection Name은 원하는 이름으로 작성해주고 Hostname에는 RDS 엔드포인트, Username에는 RDS 마스터 사용자 이름을 넣어준다.

그리고 Store in Keychain을 눌러 RDS 마스터 사용자 암호를 입력한다.

다 설정했다면 하단의 Test Connection을 눌러 연결상태를 확인한다.

결과 창에 Successfully made the MYSQL connection이 나온다면 연결이 성공한 것이다.

들어가서 데이터베이스까지 체크하면 연동 끝~

정리 목적

이번에 AWS에 배포 테스트를 하며 UI가 변경된 부분도 좀 있었고 이전에는 도메인 구매 후 접근 테스트만 해본 반면 이번에는 여러 환경을 설정하고 처리했기 때문에 이전 정리 내용을 지우고 새로 다시 정리.

 

처리 환경 정리

Project

  • BackEnd - Spring Boot 3
  • FrontEnd - React
  • 빌드 방식 - 통합빌드

AWS

  • EC2 t2.micro
    • ubuntu 22.0.4
  • Application Load Balancer
  • AWS Certificate Manager(ACM)
  • Route53
  • S3
  • RDS(MySQL)
  • ElastiCache(Redis)

CI / CD

  • Jenkins
  • Git Webhook

WebServer

  • Nginx

Domain Register

  • Gabia

 

정리 순서

  1. S3 Bucket 생성 후 Local에서 테스트
  2. RDS MySQL Database Instance 생성 후 Local Workbench와 연결 테스트 및 프로젝트 연결 테스트
  3. EC2 Instance 생성 후 설정
    1. swap 메모리 설정
    2. JDK 17 설치
    3. nvm 설치 및 node 21.7.1 설치
    4. Nginx 설치 및 설정
    5. Jenkins 설치 및 빌드 Job 설정을 제외한 나머지 처리
    6. ElasiCache Redis OSS Cache 생성 및 Redis 설치
  4. Gabia 도메인 구매 후 Route53, ACM 처리
  5. Load Balancer 대상 그룹 생성 및 ALB 생성 후 대상 그룹 설정
  6. A레코드 생성 및 도메인 접근 테스트
  7. git clone을 통해 사전 테스트 이후 Jenkins Job 설정과 Build 테스트
  8. Git Webhook 연동 및 테스트

 

S3 Bucket 생성 후 Local 연결 테스트

 

AWS IAM 계정 생성

S3 Bucket을 생성하기 전에 IAM에 계정을 생성한다.

AWS에서 IAM에 접근해 액세스 관리 -> 사용자 탭을 눌러 접근한다.

 

 

사용자 이름을 작성하고 다음으로 넘어간다.

이 계정은 단지 S3 계정에 접근하기 위해 생성하는 것이므로 AWS Management Console에 대한 사용자 액세스 권한 제공은 체크하지 않는다.

 

 

권한 옵션에서 직접 정책 연결을 선택하면 아래에 권한 정책이 나온다.

여기서 S3를 검색하고 AmazonS3FullAccess 체크박스를 체크해주고 다음으로 넘어간다.

 

다음 페이지에 나오는 검토 및 생성에서는 태그를 추가할 수 있는데 선택사항이기 때문에 필요하다면 태그를 추가하고 사용자 생성을 눌러 계정 생성을 마무리한다.

계정이 처음 생성되고 나서 리스트에 있는 계정을 클릭해서 접근하고 아래 이미지의 탭들 중 보안 자격 증명 탭으로 이동한다.

그리고 하단의 액세스 키 만들기를 눌러 액세스 키를 생성해준다.

 

그럼 가장 먼저 액세스 키 모범 사례 및 대안이라는 페이지가 나오는데 여기서는 말 그대로 모범 사례와 그 설정 대안에 대해서만 알려주는 정도이기 때문에 뭘 선택해도 상관없다.

이번에는 로컬 연결에서 먼저 테스트 해 볼것이기 때문에 로컬 코드를 선택했고 하단의 권장되는 대안에서 자세히 알아보기를 눌러 링크로 이동하면 어느 환경에서는 어떻게 설정하는지에 대한 문서를 확인할 수 있다.

다음!

 

 

다음 페이지는 설명 태그 설정 탭인데 여기서는 원하는 태그값을 작성해준다.

설명에 있는 내용 그대로 키의 용도와 사용 위치를 명시하는 태그다.

 

액세스 키 만들기 버튼을 눌러 다음으로 넘어오면 아래 이미지와 같은 페이지를 볼 수 있다.

액세스키와 비밀 액세스키가 나오게 되며 표시 버튼을 눌러 확인할 수 있다.

여기서 비밀 액세스 키는 이 페이지가 아니라면 더이상 확인 할 방법이 없기 때문에 꼭 저장해둬야 한다.

복사해서 어디 메모해두거나 .csv 파일 다운로드 버튼을 통해 다운받아 저장해둔다.

 

그럼 이제 계정 생성은 마무리.

다음은 S3 bucket을 생성해준다.

S3로 이동해 버킷 탭으로 들어가 버킷 만들기 버튼을 클릭

 

가장 먼저 일반 구성 탭에서 버킷의 이름을 작성한다.

기존에 사용하고 있는 버킷이 있고 그 설정과 동일하게 처리하고자 한다면 버킷 선택을 통해 처리할 수 있는 것 같다.

객체 소유권의 경우 ACL 활성화를 선택하고 소유권은 객체 라이터를 선택한다.

 

퍼블릭 액세스 차단 설정의 경우 모든 퍼블릭 액세스 차단 체크박스를 해제해준다.

지금은 테스트이기 때문에 모드 해제해주지만 그렇지 않다면 당연히 환경 또는 상황에 맞춰 체크해주고 설정해야 한다.

그리고 모두 해제하게 되면 아래 안내 창이 뜨는데 현재 설정으로 인해 객체가 퍼블릭 상태가 될 수 있음을 알고 있습니다에 체크해준다.

버전 관리 역시 필요에 따라 선택. 테스트이기 때문에 비활성화했다.

 

기본암호화 설정은 SSE-S3가 선택된 그대로 유지한다.

SSE-KMS를 선택하는 경우 추가적인 요금이 발생할 수 있다.

고급 설정도 따로 건드리지 않고 비활성화 상태로 버킷 만들기 버튼을 눌러 버킷 생성!

 

다음은 버킷 정책을 설정해야 한다.

테스트에서는 버킷에 업로드, 조회, 삭제에 대한 정책만 설정해준다.

자세한 정책 예시는 아래 링크에서 자세하게 알아볼 수 있다.

https://docs.aws.amazon.com/ko_kr/AmazonS3/latest/userguide/example-bucket-policies.html

 

Amazon S3 버킷 정책 예시 - Amazon Simple Storage Service

특정 IP 주소에 대한 액세스를 제한할 때는 S3 버킷에 액세스할 수 있는 VPC 엔드포인트, VPC 소스 IP 주소 또는 외부 IP 주소도 지정해야 합니다. 그렇지 않으면 적절한 권한이 이미 갖춰지지 않은

docs.aws.amazon.com

이것도 제대로 이해하고 자유자재로 사용하기 위해서는 좀 더 알아봐야 할 것 같다.

 

생성한 버킷 명을 눌러 들어가고, 하단의 탭 중 권한 탭으로 이동하면 버킷 정책 탭을 볼 수 있다.

여기서 편집 버튼을 눌러준다.

 

 

 

그럼 아래 이미지와 같은 페이지가 나오는데 버킷 ARN을 복사해준뒤에 정책 생성기 버튼을 클릭.

 

그럼 여기서 아래와 같이 설정해준다.

Select type of Policy -> S3 Bucket Policy

Principal -> *

Actions -> DeleteObject, GetObject, PutObject 체크박스 선택

Amazon Resource Name (ARN) -> 이전 페이지에서 복사했던 버킷 ARN 붙여넣기

 

모두 설정하고 나면 AddStatement 버튼이 활성화 될 것이고 버튼을 클릭!

 

Add Statement 버튼을 클릭하고 나면 입력한 정보가 출력되며 Generate Policy 버튼이 생성된 것을 볼 수 있다.

클릭!

 

그럼 아래와 같은 모달창이 출력된다.

이 내용을 모두 복사해준 뒤 닫아주고 버킷 정책 설정 페이지로 이동해 버킷 정책 탭 내부의 정책에 붙여넣기를 해주면 된다.

그리고 추가적인 설정으로 Resource 부분에 ARN이 작성되어있을텐데 ARN 끝에 /* 를 꼭 붙여줘야 한다.

"arn:aws:::버킷명" -> "arn:aws:::버킷명/*" 이렇게!

 

 

그럼 이제 로컬에 연결을 한다.

가장 먼저 build.gradle에 aws 의존성 추가를 해준다.

implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE'

 

그리고 application.yml에 아래와 같이 추가해준다.

cloud:
  aws:
    credentials:
      access-key: IAM 액세스 키
      secret-key: IAM 비밀 액세스 키
    region:
      static: 자신의 리전
    s3:
      bucket: 버킷명
    stack:
      auto: false

 

다음으로 설정 클래스를 생성한다.

import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
//...

@Configuration
public class AwsS3Config {
    
    @Value("${cloud.aws.credentials.access-key}")
	private String accessKey;
	
	@Value("${cloud.aws.credentials.secret-key}")
	private String secretKey;
	
	@Value("${cloud.aws.region.static}")
	private String region;
    
    @Bean
    public AmazonS3Client amazonS3Client() {
        BasicAWSCredentials awsCredentials = 
            new BasicAWSCredentials(accessKey, secretKey);
        
        return (AmazonS3Client) AmazonS3ClientBuilder.standard()
                    .withRegion(region)
                    .withCredentials(
                        new AWSStaticCredentialsProvider(awsCredentials)
                    )
                    .build();
    }
}

 

그럼 이제 저장하는 코드와 삭제하는 코드를 정리.

import com.amazonaws.services.s3.AmazonS3;  
import com.amazonaws.services.s3.AmazonS3Client;  
import com.amazonaws.services.s3.model.CannedAccessControlList;  
import com.amazonaws.services.s3.model.DeleteObjectRequest;  
import com.amazonaws.services.s3.model.ObjectMetadata;  
import com.amazonaws.services.s3.model.PutObjectRequest;
//...

@Service
public class TestServiceImpl implements TestService {
    
    @Value("${cloud.aws.s3.bucket}")
    private String bucket;
    
    private final AmazonS3 amazonS3;
    
    private final AmazonS3Client amazonS3Client;
    
    //파일 객체 저장
    public String imageInsert(MultipartFile image) {
        StringBuffer sb = new StringBuffer();
		String saveName = sb.append(new SimpleDateFormat("yyyyMMddHHmmss")  
                            .format(System.currentTimeMillis()))
                            .append(UUID.randomUUID().toString())
                            .append(
                                image
                                .getOriginalFilename()
                                .substring(
                                    image
                                    .getOriginalFilename()
                                    .lastIndexOf(".")
                                )
                            )
                            .toString();
		
        ObjectMetadata objectMetadata = new ObjectMetadata();
        objectMetadata.setContentLength(image.getSize());
        objectMetadata.setContentType(image.getContentType());
        
        try{
            amazonS3.putObject(
                new PutObjectRequest(
                    bucket
                    , saveName
                    , image.getInputStream()
                    , objectMetadata
                )
                .withCannedAcl(CannedAccessControlList.PublicRead)
            );
        }catch (Exception e) {
            throw new CustomIOException();
        }
        
        //접근 url이 바로 필요하다면 아래 코드처럼 조회가 가능하다.
        //String.valueOf(amazonS3Client.getUrl(bucket, saveName))
        
        return saveName;
    }
    
    //S3 파일 객체 삭제
    public void deleteImage(String imageName) {
        amazonS3.deleteObject(
            new DeleteObjectRequest(bucket, imageName)
        );
    }
}

 

조회에 대한 처리는 따로 정리했다.

 

https://myyoun.tistory.com/230

 

S3 이미지 파일 처리

이번에 프로젝트를 마무리하고 AWS를 통해 배포하면서 S3를 같이 사용해보게 되었는데 솔직히 시작할때는 S3 Bucket 생성과 보안 같은 설정 말고는 별거 있겠나 했는데 역시 사용해봐야 한다는 것

myyoun.tistory.com

 

 

 

 

참고 블로그

https://skatpdnjs.tistory.com/70

 

AWS에서 제공하는 S3에 이미지 업로드 해보기

저번시간에 간단하게 내 컴퓨터에다가 이미지를 저장하고, 현재 진행하고 있는 프로젝트에 적용해보았다. 이번포스팅에서는 s3에 이미지를 업로드하는 방법을 알아보겠다. 내 로컬에다 이미지

skatpdnjs.tistory.com

 

+ Recent posts