-
8장) EC2 서버에 프로젝트를 배포해 보자Java & Spring/스프링 부트와 AWS로 혼자 구현하는 웹 서비스 2020. 7. 14. 23:55반응형
EC2에 프로젝트 Clone 받기
git 설치
- sudo yum install git으로 git 설치
- git --version으로 설치 상태 체크
프로젝트 저장할 디렉토리 만들기
- mkdir ~/app && ~app/step1 생성
- cd ~/app/step1 이동
git clone하기
- git clone 깃헙주소
테스트로 코드 검증하기
- ./gradlew test
- 성공했다면, BUILD SUCCESSFUL이 뜬다.
- 여기서 한 번 실패가 떴는데, 실행권한이 없다는 표시가 떴다.
- chmod +x ./gradlew로 권한을 부여해줘서 해결
배포 스크립트 만들기
배포할 때마다 개발자가 하나하나 명령어를 실행하는 것은 비효율적
쉘 스크립트로 작성해서 스크립트만 실행하면, 위의 과정이 진행되도록 생성
쉘 스크립트
- .sh라는 파일 확장자를 가진 파일
- 노드JS가 .js라는 파일을 통해 서버에서 작동하듯, 쉘 스크립트는 리눅스에서 기본적으로 사용 가능한 스크립트 파일의 한 종류
- Vim은 편집도구
~/app/step1/에 deploy.sh 파일 생성
vim ~app/step1/deploy.sh
#!/bin/bashREPOSITORY=/home/ec2-user/app/step2
PROJECT_NAME=springboot-webservicecd $REPOSITORY/$PROJECT_NAME/
echo "> Git pull"
git pull
echo "> 프로젝트 Build 시작"
./gradlew build
echo "> step1 디렉토리로 이동"
cd $REPOSITORY
echo "> Build 파일 복사"
cp $REPOSITORY/PROJECT_NAME/build/libs/*.jar $REPOSITORY/
echo "> 현재 구동중인 애플리케이션 pid 확인"
CURRENT_PID=$(pgrep -f ${PROJECT_NAME}.*.jar)
echo "현재 구동중인 어플리케이션 pid: $CURRENT_PID"
if [ -z "$CURRENT_PID" ]; then
echo "> 현재 구동중인 애플리케이션이 없으므로 종료하지 않습니다."
else
echo "> kill -15 $CURRENT_PID" kill -15 $CURRENT_PID sleep 5
fi
echo "> 새 어플리케이션 배포"
JAR_NAME=$(ls -tr $REPOSITORY/ | grep jar | tail -n 1)
echo "> JAR Name: $JAR_NAME"
nohup java -jar $JAR_NAME > $REPOSITORY/nohup.out 2>&1 &
REPOSITORY=/home/ec2-user/app/step2
- 프로젝트 디렉토리 주소는 스크립트 내에서 자주 사용 ~> 변수로 저장
- PROJECT_NAME 도 마찬가지
- 쉘에서는 타입 없이 선언해서 저장
- $ 변수명으로 변수 사용
cd $REPOSITORY/$PROJECT_NAME/
- git clone을 받았던 디렉토리로 이동
git pull
- 디렉토리 이동 후, master 브랜치에서 최신 내용을 pull
./gradlew build
- 프로젝트 내부의 gradlew로 build 수행
cp $REPOSITORY/PROJECT_NAME/build/libs/*.jar $REPOSITORY/
- build의 결과물인 jar 파일을 복사해 jar 파일을 모아둔 위치로 복사함
CURRENT_PID=$(pgrep -f ${PROJECT_NAME}.*.jar)
- 기존에 수행 중이던 스프링 부트 애플리케이션 종료
- pgrep => process id만 추출하는 명령어
- -f 옵션 => 프로세스 이름으로 찾음
JAR_NAME=$(ls -tr $REPOSITORY/ | grep jar | tail -n 1)
- 새로 실행할 jar 파일명을 찾는다.
- 여러 jar파일이 생겨서, tail -n으로 가장 나중의 jar 파일(최신)을 변수에 저장
nohup java -jar $JAR_NAME > $REPOSITORY/nohup.out 2>&1 &
- 찾은 jar파일명으로 해당 jar 파일을 nohup으로 실행
- 일반적으로 자바를 실행할 때는 java -jar라는 명령어를 사용 ~> 사용자가 터미널 접속을 끊을 때 어플리케이션도 종료됨
- 애플리케이션 실행자가 터미널을 종료해도 애플리케이션은 계속 구동될 수 있도록 nohup 명령어를 사용
쉘 스크립트에 권한 추가
- chmod +x ./deploy.sh
쉘 스크립트 실행
- ./deploy.sh
- 여기서 오류가 한 번 발생했었는데, 쉘 스크립트 내부에서 변수를 선언하고 저장할 때 띄어쓰기를 하면 안된다. (a=1 (O) <------> a = 1 (X) 이걸로 시간을 조금 낭비했다)
- 성공적으로 실행이 되면 BUILD SUCCESSFUL이 나온다.
실행되는 애플리케이션에서 출력되는 내용 확인
- vim nohup.out
- nohup으로 실행하면, 기본적으로 로그가 nohup.out에 저장된다.
- 위의 실행결과로 Fail이 뜨는데, Security 파일인(application-oauth.properties가 없기 때문)
외부 Security 파일 등록하기
- 위에서 ClientRegistrationRepository 생성 하려고 할 때, clientId와 clientSecret이 없었다. (생성 시 필수) ~> application-oauth.properties가 .gitignore에 포함됐기 때문 ( 민감정보 보호 )
- step1이 아닌, app 디렉토리에 properties 파일을 생성 (다른 디렉토리에서도 사용하기 위해)
- vim /home/ec2-user/app/application-oauth.properties
- 로컬에 있는 application-oauth.properties를 그대로 복붙하기
- putty에서는 로컬에서 저장한 클립보드를 오른쪽 마우스 클릭으로 붙여넣기 가능
- 로컬에 있는 application-oauth.properties를 그대로 복붙하기
- vim /home/ec2-user/app/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
- 스프링 설정 파일 위치를 지정
- classpath가 붙으면 jar 안에 있는 resources 디렉토리를 기준으로 경로가 생성
- application-oauth.properties은 절대경로로 사용 ~> 외부에 파일이 있기 때문에
- 여기에서도 에러가 한 번 발생했었다. 띄어쓰기에 주의해야함
- -Dspring.config.location
스프링 부트 프로젝트로 RDS 접근하기
- RDS는 MariaDB 사용, 다음 세 작업이 필요
- 테이블 생성 : H2에서 자동으로 생성해주던 테이블들을 MariaDB에선 직접 쿼리로 생성
- 프로젝트 설정 : 자바 프로젝트가 MariaDB에 접근하려면 데이터베이스 드라이버가 필요
~> MariaDB에서 사용 가능한 드라이버를 프로젝트에 추가 - EC2(리눅스 서버) 설정 : DB 접속 정보는 중요하게 보호해야할 정보 ~> EC2 서버 내부에서 접속 정보를 관리하도록 설정
- RDS 테이블 생성
- JPA가 사용될 엔티티 테이블과 스프링 세션이 사용될 테이블 2 종류를 생성
- JPA가 사용될 엔티티 테이블
- 테스트 코드 수행 시 로그로 생성되는 쿼리 사용
- Hibernate: create table posts
, Hibernate: create table user ~
- 스프링 세션 테이블
- schema-mysql.sql 파일에서 복붙
- Shift + ctrl + N에서 위의 파일 검색
- JPA가 사용될 엔티티 테이블
- JPA가 사용될 엔티티 테이블과 스프링 세션이 사용될 테이블 2 종류를 생성
- 프로젝트 설정
- MariaDB 드라이버 build.gradle에 등록하기
- compile("org.mariadb.jdbc:mariadb-java-client")
- 서버에 구동될 환경 구성하기
- 로컬 src/main/resources/에 application-real.properties 파일 추가
- profile=real인 환경이 구성된다고 생각하면 된다.
spring.profiles.include=oauth,real-db
spring.jpa.properties.hibernate.dialect=org.hibernate.spring.session.store-type=jdbc - 이후 커밋 ~> 푸시 ~> 서버에서 ./deploy.sh 실행 (쉘 스크립트에 풀 명령 존재)
- profile=real인 환경이 구성된다고 생각하면 된다.
- 로컬 src/main/resources/에 application-real.properties 파일 추가
- MariaDB 드라이버 build.gradle에 등록하기
EC2 설정
app 디렉토리에 application-real-db.properties 파일 생성
vim ~/app/application-real-db.properties
spring.jpa.hibernate.ddl-auto=none spring.datasource.url=jdbc:mariadb://rds주소:포트명(기본은 3306)/database명 spring.datasource.username=db계정 spring.datasource.password=db계정 비밀번호 spring.datasource.driver-class-name=org.mariadb.jdbc.Driver
- spring.jpa.hibernate.ddl-auto=none
- JPA로 테이블이 자동 생성되는 옵션을 None(생성하지 않음)으로 지정
- RDS에는 실제 운영으로 사용될 테이블 ~> 절대 스프링 부트에서 새로 만들지 않도록 설정
- 매우매우매우 중요한 옵션 ~> 이 옵션을 안하면 테이블이 모두 새로 생성될 수 있음
- spring.jpa.hibernate.ddl-auto=none
deploy.sh 개선
... nohup java -jar \ -Dspring.config.location=classpath:/application.properties,classpath:/application-real.properties,/home/ec2-user/app/application-oauth.properties,/home/ec2-user/app/application-real-db.properties \ -Dspring.profiles.active=real \ $JAR_NAME > $REPOSITORY/nohup.out 2>&1 &
- -Dspring.profiles.active=real
- application-real.properties를 활성화
- application-real.properties의 spring.profiles.include=oauth,real-db 옵션 때문에 real-db 역시 함께 활성화 대상에 포함된다.
- -Dspring.profiles.active=real
curl 명령어로 확인하기
- curl localhost:8088(포트번호)
- html 코드가 보이면 성공
- curl localhost:8088(포트번호)
EC2에서 소셜 로그인하기
- AWS 보안 그룹 변경
- EC2 보안그룹의 인바운드에 해당 포트가 열려있는지 확인
- 안돼있다면, 포트 열어주기
- AWS EC2 도메인으로 접속
- 퍼블릭 DNS 확인하기 => EC2에 할당된 도메인
- 퍼블릭 DNS 주소:8088(포트번호) 로 서버에 접근
- google login과 naver login을 누르면, 작동하지 않음 ~> google, naver 서비스 등록해야함
- 구글에 EC2 주소 등록
- API 및 서비스 ~> Ouath 동의 화면 ~> 승인된 도메인에 EC2 퍼블릭 DNS 추가하기
(이 때, http://는 제거해줘야한다.) - 사용자 인증 정보 ~> 승인된 리디렉션 URI
- http://퍼블릭 DNS:8088/login/oauth2/code/google 추가
- 이 과정에서 500에러가 떠서 몇 시간을 고생했다.
- 첫번째, db에 접근할 수 없다고 나왔다.
- 위의 경우, 서버 용량 초과 or 서버 과부화(?) 문제라는 검색 결과가 있었다.
- ~> 재부팅하니까 해결 ( 불필요한 데몬 등이 돌아가고 있어서 과부화 가능성 )
- 두번째, line9 에서 username을 찾을 수 없다고 나왔다.
- 삭제하고 다시 해보고, 이번 장에서 진행한 코드들을 다 확인해봐도 이상이 없었다. 구글 설정이 잘못됐나 확인했는데도 아니었다. 그래서 nohup 로그를 뒤져보니까 mustache에서 에러가 뜬 것을 확인했다. index 파일에서 문제가 생겼음을 직감했고, 클래스 파일과 머스태치 파일을 확인했다. 그 결과, index.mustache의 9번째 줄에 userName을 출력하는 과정에서, 변수 명을 userName이 아닌 username으로 작성한 것을 발견했다... ~> 해결 (근데, username으로 해도 로컬에서는 id가 떴고 에러가 없었다.. 그래서 나는 내가 설정한 이름이 그건줄... 이상하다... ㅠ)
- 첫번째, db에 접근할 수 없다고 나왔다.
- 구글 등록이 정상적으로 완료되면, 이름이 뜬다.
- API 및 서비스 ~> Ouath 동의 화면 ~> 승인된 도메인에 EC2 퍼블릭 DNS 추가하기
- 네이버에 EC2 주소 등록
- 서비스 URL에 EC2 퍼블릭 DNS 주소 입력
- http://퍼블릭DNS주소/ 입력
- 로그인을 시도하는 서비스가 네이버에 등록된 서비스인지 판단
- 포트번호는 제외하고 실제 도메인 주소만 입력
- 네이버 서비스는 한번에 하나의 서비스 URL만 지원하기 때문에, 로컬에서도 이용하고 싶으면, 서비스 하나를 더 만들어서 키 하나 더 발급받기
- Callback URL에 redirect 받을 서버 주소 입력
- http://퍼블릭DNS주소:8088/login/oauth2/code/naver 입력
- 서비스 URL에 EC2 퍼블릭 DNS 주소 입력
반응형'Java & Spring > 스프링 부트와 AWS로 혼자 구현하는 웹 서비스' 카테고리의 다른 글
10장) 24시간 365일 중단 없는 서비스를 만들자 (0) 2020.07.18 9장) 코드가 푸시되면 자동으로 배포해 보자 - Travis CI 배포 자동화 (0) 2020.07.15 7장) AWS에 데이터베이스 환경을 만들어보자 - AWS RDS (0) 2020.07.08 6장) AWS 서버 환경을 만들어보자 - AWS EC2 (0) 2020.07.07 5장) 스프링 시큐리티와 OAuth2.0으로 로그인 기능 구현하기 (0) 2020.07.05