본문 바로가기
Web/SpringBoot

8. EC2 서버에 프로젝트 배포

by SeleniumBindingProtein 2022. 3. 7.
728x90
반응형

1. EC2에 프로젝트 Clone 받기

  • 깃허브에서 코드를 받아올 수 있게 EC2에 깃을 설치
    • sudo yum install git
  • 설치 완료 후, 설치 상태 확인
    • git --version

 

  • git clone으로 프로젝트를 저장할 디렉토리 생성
    • mkdir ~/app && mkdir ~/app/step1
  • 생성된 디렉토리 이동
    • cd ~/app/step1
  • 본인의 깃허브 웹페이지에서 https 주소 복사
  • 복사한 http 주소를 통해 git clone 진행
    • git clone 복사한 주소
  • git clone 끝났으면, 클론된 프로젝트로 이동해서 파일들이 복사되었는지 확인함
    • cd 프로젝트명
    • ls -ll
  • 코드들이 잘 수행되는지 테스트로 검증
    • ./gradlew test
  • gradle 버전 최신으로 업그레이드
 

(2020.12.16) 스프링 부트와 AWS로 혼자 구현하는 웹 서비스 최신 코드로 변경하기

작년 11월 말에 스프링 부트와 AWS로 혼자 구현하는 웹 서비스를 출판 하였습니다. Spring Boot가 2.1 -> 2.4로, IntelliJ IDEA가 2019 -> 2020으로 오면서 너무 많은 변화가 있다보니, 집필할 때와 비교해 실습

jojoldu.tistory.com

    • 터미널 내에서 git 충돌이 일어나서 인텔리제이에서 test 실행이 문제 없음에도 불구하고, 에러가 자꾸 발생하였음
      • 이를 해결하기 위해,
      • git stash && git pull origin master && git stash pop 를 통해 깃 충돌 문제 해결하였음
      • 이후, git pull을 받고, ./gradlew test를 통해 문제 없음을 확인하였음
        • 현재 디렉토리의 파일을 임시로 백업하고 깨끗한 상태로 돌림
        •  버전관리 되는 대상 파일들을 임시저장 해둔다고 보면 됨 
          • 해당 명령어를 통해 현재 Staging 영역에 있는 파일의 변경사항을 스택에 넣어 둠
          • master에서 pull하거나, git checkout 등 원격 저장소에서 내 로컬 브랜치로 변경사항을 적용함
          • 변경 사항을 적용하고, 스택에서 제거 

 

2. 배포 스크립트 만들기

  • 배포의 의미
    • git clone 혹은 git pull을 통해 새 버전의 프로젝트 받음
    • Gradle이나 Maven을 통해 프로젝트 테스트와 빌드
    • EC2 서버에서 해당 프로젝트 실행 및 재실행 
  • 배포할 때마다 개발자가 하나하나 명령어를 실행함에 있어 불편하기 때문에 쉘 스크립트로 작성해 스크립트만 실행
    • 쉘 스크립트 : .sh라는 파일 확장자를 가진 파일 
    • 빔 : 리눅스 환경과 같이 GUI가 아닌 환경에서 사용할 수 있는 편집 도구
    • vim ~/app/step1/deploy.sh
  • 빔의 사용법
    • #!/bin/bash
      • REPOSITORY=/home/ec2-user/app/step1, PROJECT_NAME=freelec-springboot2-webservice
        • 프로젝트 디렉토리 주소, 프로젝트 이름은 스크립트 내에서 자주 사용하는 값이기 때문에 변수로 저장
        • 쉘에서는 타입없이 선언하여 변수를 저장함
        • 쉘에서는 $변수명으로 변수를 사용할 수 있음
      • cd $REPOSITORY/$PROJECT_NAME/
        • 제일 처음 git clone 받았던 디렉토리로 이동
        • 위에서 선언한 쉘 변수 설명을 따라 이동
      • echo "> Git Pull"
        • 디렉토리 이동 후, master 브랜치 최신 내용을 받음
      • git pull
      • echo "> 프로젝트 Build 시작"
      • ./gradlew build
        • 프로젝트 내부의 gradlew로 build를 수행
      • echo "> step1 디렉토리로 이동"
      • cd $REPOSITORY
      • echo "> Build 파일 복사"
      • cp $REPOSITORY/$PROJECT_NAME/build/libs/*.jar $REPOSITORY/
        • build 결과물인 jar 파일을 복사해 jar 파일을 모아둔 위치로 복사
      • echo "> 현재 구동 중인 애플리케이션 pid 확인"
      • CURRENT_PID=$(pgrep -f ${PROJECT_NAME}.*.jar)
        • 기존 수행 중이던 애플리케이션 종료
        • pgrep : process id만 추출하는 명령
        • -f : 프로세스 이름으로 찾는 옵션
      • echo "현재 구동 중인 애플리케이션 pid: $CURRENT_PID"
      • if [ -z "$CURRENT_PID" ]; then
        • echo "> 현재 구동 중인 애플리케이션이 없으므로 종료하지 않습니다."
        •  else
        • echo "> kill -15 $CURRENT_PID"
        • kill -15 $CURRENT_PID
        • sleep 5
        • fi
          • 현재 구동 중인 프로세스가 있는지 없는지를 판단해서 기능을 수행
          • process id 값을 보고 프로세스가 있으면 해당 프로세스를 종료함
      • echo "> 새 애플리케이션 배포"
      • JAR_NAME=$(ls -tr $REPOSITORY/ | grep jar | tail -n 1)
        • 새로 실행할 jar 파일명 찾고, 여러 jar 파일이 생기기 때문에 tail -n로 가장 나중의 jar 파일을 변수에 저장
      • echo "> JAR Name: $JAR_NAME"
      • nohup java -jar $REPOSITORY/$JAR_NAME 2>&1 &
        • 찾은 jar 파일명으로 해당 jar 파일을 nohup으로 실행
        • 스프링 부트의 장점으로 특별히 외장 톰캣 설치가 필요 없으며, 내장 톰캣을 사용해서 jar 파일만 있으면 바로 웹 애플리케이션 서버 실행 가능
        • 애플리케이션 실행자가 터미널을 종료해도 애플리케이션은 계속 구동될 수 있도록 nohup 명령어 사용

 

  • 스크립트 실행 권한
    • chmod +x ./deploy.sh
    • ll 로 x 권한이 추가된 것을 확인
    • ./deploy.sh 명령어를 통해 스크립트 실행
      • 로그가 출력되며 애플리케이션 실행됨
    • vim nohup.out 실행하여 파일을 열어 로그를 확인
      • ClientRegistrationRepository를 찾을 수 없다는 에러가 발생하면서 애플리케이션 실행에 실패 했다는 것을 확인
  • 외부 Security 파일 등록
    • ClientRegistrationRepository를 생성하려면 clientId와 clientSecret이 필수이며, 이 파일은 .gitignore로 git에서 제외대상이라 깃허브에는 올라가 있지 않으므로, 서버에서 직접 이 설정들을 가지고 있게 하겠음
      • app 디렉토리에 properties 파일을 생성
        • vim /home/ec2-user/app/application-oauth.properties
      • 로컬에 있는 application-oauth.properties 파일 내용을 그대로 붙여 넣기하고, 해당 파일을 저장하고 종료
      • 방금 생성한 application-oauth.properties을 쓰도록 deploy.sh 파일 수정
        • nohup java -jar \ -Dspring.config.location=classpath:/application.properties,/home/ec2-user/app/application-oauth.properties\$REPOSITORY/$JAR_NAME 2>&1 &
          • Dspring.config.location
            • 스프링 설정 파일 위치를 지정함
            • 기본 옵션들을 담고 있는 application.properties와 OAuth 설정들을 담고 있는 application-oauth.properties의 위치를 지정
            • classpath가 붙으면 jar 안에 있는 resources 디렉토리를 기준으로 경로가 생성됨
            • application-oauth.properties는 절대 경로로 사용함 
        • 수정아 다 되었다면 deploy.sh 다시 실행하여 정상적인 실행을 확인

 

 

3. 스프링 부트 프로젝트로 RDS 접근

    • RDS는 MariaDB 사용 중이며, MariaDB에서 스프링부트 프로젝트를 실행하기 위해선 몇 가지 작업이 필요함
      • 테이블 생성 : H2에서 자동 생성해주던 테이블들을 MariaDB에선 직접 쿼리를 이용해 생성함
      • 프로젝트 설정 : 자바 프로젝트가 MariaDB에 접근하려면 데이터베이스 드라이버가 필요하며, MariaDB에서 사용 가능한 드라이버를 프로젝트에 추가함
      • EC2(리눅스 서버) 설정 : 데이터베이스의 접속 정보는 중요하게 보호해야 할 정보이며, 공개되면 외부에서 데이터를 모두 가져갈 수 있기 때문임. 프로젝트 안에 접속 정보를 갖고 있다면 깃허브와 같이 오픈된 공간에서 누구나 해킹할 위험이 있고, EC2 서버 내부에서 접속 정보를 관리하도록 설정함
    • RDS 테이블 생성
      • JPA가 사용될 엔티티 테이블과 스프링 세션이 사용될 테이블 2가지 종류 생성함
      • JPA가 사용할 테이블은 테스트코드 수행 시 로그로 생성되는 쿼리를 사용하면 됨\
        • Hibernate: create table user (id bigint not null auto_increment, created_date datetime(6), modified_date datetime(6), email varchar(255) not null, name varchar(255) not null, picture varchar(255), role varchar(255) not null, primary key (id)) engine=InnoDB;
        • Hibernate: create table posts (id bigint not null auto_increment, created_date datetime(6), modified_date datetime(6), author varchar(255), content TEXT not null, title varchar(500) not null, primary key (id)) engine=InnoDB;
        • Command+Shitf+O 검색을 통해 schema-mysql.sql 파일 확인
        • RDS mysql 접속해서 실행 해야 함
          •  mysql -u username -p  -h hostname
          • MariaDB [(none)]> use freelec_springboot2_webservice; 를 통해 테이블 지정하고, sql 실행하여 저장

 

 

  • 프로젝트 설정
    • MariaDB 드라이버를 build.gradle에 등록
    implementation("org.mariadb.jdbc:mariadb-java-client")
  • 서버에서 구동될 환경 하나 구성함
    • src/main/resources/application-real.properties로 파일을 만들면 profile=real 환경이 구성됨
    • 실제 운영될 환경이기 때문에 보안/로그상 이슈가 될만한 설정들을 모두 제거하며 RDS 환경 profile 설정 추가됨
spring.profiles.include=oauth,real-db
spring.jpa.properties.hibernate.dialect=rg.hibernate.dialect.MySQL57Dialect
spring.session.store-type=jdbc
  • EC2 설정
    • OAuth와 마찬가지로 RDS 접속 정보도 보호해야 할 정보이니 EC2 서버에 직접 설정 파일을 둠
    • app 디렉토리에 application-real-db.properties 파일 생성
      • vim ~/app/application-real-db.properties
        • spring.jpa.hibernate.ddl-auto=none : 
          • JPA로 테이블이 자동 생성되는 옵션을 None으로 지정하며, RDS에는 실제 운영으로 사용될 테이블이니 절대 스프링 부트에서 새로 만들지 않도록 해야 함. 이 옵션을 하지 않으면 자칫 테이블이 모두 새로 생성될 수 있으므로, 주의해야 하는 옵션임
spring.jpa.hibernate.ddl-auto=none
spring.jpa.show_sql=false

spring.datasource.hikari.jdbc-url=jdbc:mariadb://rds주소:포트명(기본은 3306)/database명
spring.datasource.hikari.username=db계정
spring.datasource.hikari.password=db계정 비밀번호
spring.datasource.hikari.driver-class-name=org.mariadb.jdbc.Driver
  • deploy.sh가 real profile을 쓸 수 있도록 다음과 같이 개선함
    • vim /home/ec2-user/app/application-oauth.properties
      • -Dspring.profiles.active=real : application-real.properties를 활성화시킴. application-real.properties의 spring.profiles.include=oauth,real-db 옵션 때문에 real-db 역시 함께 활성화 대상에 포함됨

 

 

nohup java -jar \
	-Dspring.config.location=classpath:/application.properties, /hoome/ec2-user/app/application-oauth.properties,/ home/ec2-user/app/application-real-db.properties, classpath:/application-real.properties\
    -Dspring.profiles.active=real\
    $REPOSITORY/$JAR_NAME 2>&1 &
  • ./deploy.sh 실행

  • vim nohup.out 실행하여 파일 열어 로그 확인curl localhost:8080 명령어로 html코드가 정상적으로 보인다면 성공

 

4. EC2에서 소셜 로그인 

    • 8080포트가 보안 그룹에 열려 있는지 확인

  • AWS EC2 도메인으로 접속
    • 왼쪽 사이드바의 인스턴스 메뉴를 클릭. 본인이 생성한 EC2 인스턴스를 선택하면, 상세정보에서 퍼블릭 DNS를 확인할 수 있음
    • 이 주소가 EC2에 자동으로 할당된 도메인이고, 인터넷이 되는 장소 어디나 이 주소를 입력하면 우리의 EC2 서버에 접근할 수 있음
  • 현재 상태에서 해당 서비스에 EC2의 도메인을 등록하지 않았기 때문에 구글과 네이버 로그인이 작동하지 않음

  • 구글에 EC2 주소 등록
    • 구글 웹 콘솔에 접속하여 본인의 프로젝트로 이동한 다음 "API 및 서비스" => "사용자 인증 정보" 이동
    • "OAuth 동의 화면" 탭을 선택하고, 아래에서 승인된 도메인에 'http://' 없이 EC2의 퍼블릭 DNS를 등록함
  • 네이버에 EC2 주소 등록
    • 네이버 개발자 센터로 접속해서 본인의 프로젝트 이동
    • PC웹 항목이 있는데, 서비스 URL과 Callback URL 2개 수정
      • 서비스 URL
        • : 로그인을 시도하는 서비스가 네이버에 등록된 서비스인지 판단하기 위한 항목. 
        • 8080포트는 제외하고 실제 도메인 주소만 입력
        • 네이버에서 아직 지원되지 않아 하나만 등록 가능함
        • EC2의 주소를 등록하면 localhost가 안됨
        • 개발 단계에서는 등록하지 않는 것을 추천함
        • localhost도 테스트하고 싶으면 네이버 서비스를 하나 더 생성해서 키를 발급 받으면 됨
      • Callback URL
        • 전체 주소를 등록함
728x90
반응형

댓글