Group Study (2022-2023)/Spring 입문

[spring 입문] 6주차 스터디 - EC2에서 소셜 로그인 하기 + 자바 웹 애플리케이션의 동작과 배포

박소윤15 2022. 11. 20. 22:22
더보기

목차

1. 교재 내용 실습하기
   1-1. EC2에 프로젝트 clone 하기
   1-2. 배포 스크립트 만들기
   1-3. 외부 Security 파일 등록하기
   1-4.  스프링 부트 프로젝트로 RDS 접근하기
   1-5.  EC2에서 소셜 로그인 하기
2. 실습 중 에러 해결하기
   2-1. mysql 드라이버 에러
   2-2. test 애플리케이션 빌드 에러
3. 자바 웹 애플리케이션의 동작과 배포
   3-1. 자바 웹 애플리케이션 배포
   3-2. 웹 애플리케이션이 동작하는 방법
   3-3. 지속적인 통합과 배포

1. 교재 내용 실습하기

1-1. EC2에 프로젝트 clone 하기

깃허브 프로젝트 clone 하기

 -EC2에 git 설치하기

sudo yum install git

-레포 저장할 디렉터리 생성

mkdir ~/app && mkdir ~/appstep1

-생성한 디렉터리로 이동

cd ~app/step1

-git 레포 clone 하기

git clone [레포링크]

-프로젝트 디렉터리로 이동

cd GDSC_Spring_study/박소윤/freelec-springboot2-webservice

기존의 코드 검증

-테스트 코드 실행하기

./gradlew test

1-2. 배포 스크립트 만들기

쉘 스크립트 작성하기

-프로젝트 디렉터리로 이동 후 파일 생성

cd ~/app/step1
touch ./deploy.sh

-코드 추가하기

-생성한 스크립트에 실행 권한 추가

chmod +x ./deploy.sh

-스크립트 실행

./deploy.sh

-애플리케이션 로그 살펴보기

vim nohup.out

1-3. 외부 Security 파일 등록하기

서버에 ClientId와 Client Secret 저장하기

-app 디렉터리에 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 &

-애플리케이션 로그 살펴보기

vim nohup.out

1-4. 스프링 부트 프로젝트로 RDS 접근하기

RDS 테이블 생성하기

1. schema-mysql.sql 파일에서 mysql 전체 쿼리를 복사 Database Sources 에서 실행

00

프로젝트 설정하기

1. build.gradle 파일에 다음 코드를 추가

implementation 'org.mariadb.jdbc:mariadb-java-client'

2. src/main/resourcesapplication-real.properties 파일 생성

spring.profiles.include=oauth,real-db
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
spring.session.store-type=jdbc

EC2 설정하기

1. EC2 서버에서 app 디렉터리에 application-real-db.properties 파일 생성

spring.jpa.hiberante.ddl-auto=none
spring.datasource.url=jdbc:mariadb://gdsc-db.cnghkyxhgovg.ap-northeast-2.rds.amazonaws.com:3306/gdscdb
spring.datasource.username = admin
spring.datasource.password = 123123123
spring.datasource.driver-class-name=org.mariadb.jdbc.Driver
  • spring.jpa.hiberante.ddl-auto=none
    • jpa로 테이블이 자동 생성되는 옵션을 none으로 지정한다.
    • rds에는 실제 운영으로 사영될 테이블이니 절대 스프링 부트에서 새로 만들지 않도록 해야 함

2. deploy.sh 파일이 real profile을 쓸 수 있도록 수정

nohup java -jar -Dspring.config.location=classpath:/application.properties, /home/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 &

3. application-real.properties 파일을 EC2 서버의 깃허브 프로젝트 src/main/resources 로 이동

mv application-oauth.properties ./step1/GDSC_Spring_study/박소윤/freelec-springboot2-webservice/src/main/resources

4. deploy.sh 파일 실행

~app/step1/deploy.sh

5. 포트포워딩 확인

curl localhost:8080

1-5. EC2에서 소셜 로그인 하기

AWS EC2 도메인으로 접속하기

주소 [EC2 퍼블릭 DNS]:8080으로 접속

구글에 EC2 주소 등록하기

1. 구글 웹 콘솔에 접속 후 해당 프로젝트로 이동, API 및 서비스, 사용자 인증 정보 클릭

2. OAuth 동의 화면 클릭 후 승인된 도메인에 EC2 퍼블릭 DNS를 추가

3. 사용자 인증 정보 클릭 후 OAuth 2.0 클라이언트 ID에서 해당 프로젝트 클릭

4. 승인된 리디렉션 URI에 EC2 퍼블릭 DNS에 :8080/login/oauth2/code/google 주소를 추가하여 추가

5. 구글 계정으로 로그인 하기

네이버에 EC2 주소 등록하기

1. 네이버 개발자 센터 접속 후 내 애플리케이션, API 설정 클릭

2. 로그인 오픈 API 서비스 환경의 PC 웹에서 서비스 URLhttp://EC2 퍼블릭 DNS로, Callback을 http://EC2 퍼블릭 DNS:8080/login/oauth2/code/naver 로 수정

3. 네이버 계정으로 로그인 하기

 

2. 실습 중 에러 해결하기

2-1. mysql 드라이버 에러 해결

Execution failed for task ':test'. > Could not resolve all files for configuration ':testRuntimeClasspath'. > Could not find com.mysql:mysql-connector-j:. Required by: project :

build.gradle 파일에서 기존 코드를

runtimeOnly 'com.mysql:mysql-connector-j'

다음과 같이 수정함

runtimeOnly 'mysql:mysql-connector-java'

2-2. test 애플리케이션 빌드 에러 해결

로컬에선 gradle로 빌드 성공했는데 EC2 서버에서는 에러

FAILURE: Build failed with an exception. FreelecSpringboot2WebserviceApplicationTests > contextLoads() FAILED

FreelecSpringboot2WebserviceApplicationTests 파일에서 @SpringBootTest 를 주석처리

 

3. 자바 웹 애플리케이션의 동작과 배포

3-1. 자바 웹 애플리케이션 배포

jar  애플리케이션 배포하기

Jar 자바 프로젝트의 압축 파일 포맷으로 자바 클래스 파일과 리소스, 메타 데이터를 모아 배포하기 위해 사용된다. like 실행 파일!

컴파일, 빌드, 배포

자바 프로젝트를 서버에 배포하기 위해서는 1.컴파일 2.빌드 3.배포 순서를 거친다.

1. 컴파일

  • 소스 코드를 기계가 읽을 수 있게 번역한다. (자바의 경우 바이너리 코드이다.)
  • .java가 .class로 변환된다.

+ 자바의 바이너리 코드는 JVM(Java Virtual Machine) 해석하므로 운영체제에 독립적이다! 

2. 빌드

  • 컴파일 된 코드(.class)를 실행 가능한 독립적인 소프트웨어로 변환한다.
  • 변환에는 1.클래스 파일들을 연결하고 2.클래스가 참조 가능한 위치로 리소스를 옮기고 3.메타 데이터 파일을 모으는 과정이 있다.
  • 위의 과정에서 빌드 도구인 Gradle이 사용된다.
  • 이후 JAR, WAR* 같은 실행 파일을 만들게 된다. 

3. 배포

  • JAR, WAR 같은 실행 파일을 사용자가 접근할 수 있는 환경(서버)에 배치한다.
  • ex) EC2 인스턴스에 코드를 clone해 jar 파일을 생성하고 실행한다. -> 스프링 부트 프로그램이 인스턴스의 8080 포트에서 실행된다.

JAR WAR

JAR WAR 빌드의 산출물로 소스 코드와 리소스가 압축되어 있다. JAR Java Archieve, 자바 프로그램이 동작할  있도록 하는 데에 목적을 두며 WAR Web Application Archieve,  애플리케이션 전체를 패키징하는 데에 목적을 둔다. 따라서 WAR 자바 코드(JAR, CLASS)  자원(JSP, HTML, JAVASCRIPT) 모두 포함하며 톰캣과 혹은 WAS 필요로한다. (JAR JRE만으로도 가능하다. 이는 자바 프로그램과  애플리케이션의 차이로 생긴 !)

Spring Boot Executable JAR

스프링 부트는 내장 서버(톰캣) 가지고 있기 때문에 WAR 아닌 JAR 파일로  애플리케이션을 배포할  있다. 이런 간편함 덕분에 JAR 파일을 도커이미지로 생성해 배포하기에 유리하며 개발자는 서버 구축과 배포보다 애플리케이션 개발에 집중할  있다! 

3-2. 웹 애플리케이션이 동작하는 방법

 기본적으로 클라이언트  서버 구조로, 원리는

  1. 클라이언트가 서버에 Request를 보낸다
  2. 서버는 받은 요청을 Web Server*, WAS*, DB 등을 통해 처리한다
  3. 처리가 완료되면 서버는 클라이언트에게 Response를 보낸다
  4. 클라이언트는 Response를 해석해 출력한다

 Web Server WAS 개념적 구분

Web Server 클라이언트로부터 HTTP 요청을 받고 응답한다. 요청이 정적 컨텐츠(HTML, CSS, JS, 이미지, 영상 ) 경우 해당 파일을 반환하고, 동적 컨텐츠(비즈니스 로직, DB  외부 서버 조회가 필요) 경우 WAS 요청을 넘겨 받아 동적 컨텐츠를 반환하게 된다. 그러나 WAS 내부에  서버가 존재하기 때문에 Web Server WAS 반환 컨텐츠 차이가 아닌 HTTP 프로토콜을 사용해  복잡한 작업을   있느냐 없느냐의 차이로 알고 있으면 되겠다!

Web Server 애플리케이션의 데이터 교환

HTTP 프로토콜 기반의  서버와 프로그램이 데이터를 주고받는 인터페이스를 CGI라고 한다. 많은 언어가  인터페이스를 지원하지만 자바는 예외이다. 이를 해결하기 위한 것이 Servlet이다.

Servlet 자바를 사용해  페이지를 동적으로 생성하는 서버  인터페이스이다. 스프링 이전 자바  개발에서는 서블렛 구현체 클래스를 모두 직접 xml 설정해야 했다. 이를 스프링 부트는 DispatchServelt으로 서블렛 매핑 구현체를 지원한다. 서블렛의 생명 주기는 1.초기화(init) 2.구현체의 메소드 실행(service) 3.메소드 실행  리소스 반납(destroy)으로 구성된다. 서블릿 구현체은 서버가   생성  초기화 되어 요청이 들어올 때마다 실행된다.  생명 주기를 Servlet Container 담당하며 WAS 요청을 처리할 스레드를 스레드 풀에서 꺼내 서블릿 구현체의 service() 호출하도록 컨테이너에 요청하는 것까지 맡게 된다. Servlet Container Web Container이며 이를 제공하는 실제 제품이 톰캣이다! Executable JAR 내장 톰캣을 가지고 있는 것이 서블릿 컨테이너를 제공하는 WAS 것이다!

WAS 앞에 붙이는 Web Server 역할

WAS 내에  서버가 있음에도 WAS 앞에 Web Server 붙어 있는데,  이유는

  1. 서버 부하 방지를 위한 책임 분할 : Web Server와 WAS가 컨텐츠 종류를 나눠 담당하기 때문에 WAS의 부담이 줄어든다
  2. 여러 대의 WAS를 묶어 로드밸런싱하고 헬스 체크 : 여러 대의 WAS 앞에 Web Server를 두어 클라이언트로부터 받은 요청을 WAS로 분산해 나눈다
  3. 실제 서버를 외부에 노출되지 않게 하기 : WAS는 애플리케이션 로직, DB 로직을 포함하기 때문에 클라이언트가 직접 접근하는 것은 보안적으로 좋지 않아 Web Server를 두어 외부로부터 실제 서버를 숨길 수 있다

3-3. 지속적인 통합과 배포

스프링 부트의 배포는 JAR 생성해 인스턴스에 업로드하고 실행하면 되지만 JAR 업로드하는 데에 시간이 오래 걸릴 뿐만 아니라 귀찮다는 단점이 있다. 따라서 배포를 자동화해 서버를 운영할  있도록 도입된 것이 CI/CD이다. CI VCS 시스템(Git) Push 발생하면 자동으로 테스트와 빌드를 수행해 배포 파일을 만들고, CD CI 만든 빌드 결과를 자동으로 운영 서버에 중단 없이 배포하여 서비스한다.