Chapter 08 EC2 서버에 프로젝트를 배포해 보자 2

LeeKyoungChang·2022년 6월 8일
3
post-thumbnail

스프링 부트와 AWS로 혼자 구현하는 웹 서비스 를 공부하고 정리한 내용입니다.

 

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

RDS는 MYSQL을 사용 중이다.
이 MYSQL에서 스프링부트 프로젝트를 실행하기 위해선 몇 가지 작업이 필요하다.

🔔 진행할 작업

  • 테이블 생성 : H2에서 자동 생성해주던 테이블들을 MYSQL에선 직접 쿼리를 이용해 생성한다.
  • 프로젝트 설정 : 자바 프로젝트가 MYSQL에 접근하려면 데이터베이스 드라이버가 필요하다. MYSQL에서 사용 가능한 드라이버를 프로젝트에 추가한다.
  • EC2 (리눅스 서버) 설정 : 데이터베이스의 접속 정보는 중요하게 보호해야 할 정보이다. 공개되면 외부에서 데이터를 모두 가져갈 수 있기 때문이다. 프로젝트 안에 접속 정보를 갖고 있다면 깃허브와 같이 오픈된 공간에선 누구나 해킹할 위험이 있다. EC2 서버 내부에서 접속 정보를 관리하도록 설정한다. (application-real-db.yml)

 

📖 A. RDS 테이블 생성

여기선 JPA가 사용될 엔티티 테이블과 스프링 세션이 사용될 테이블 2가지 종류를 생성한다.
JPA가 사용할 테이블은 테스트 코드 수행 시 로그로 생성되는 쿼리를 사용하면 된다.

(1) 테스트 코드를 수행하면 다음과 같은 로그가 발생한다.

스크린샷 2022-06-07 오후 12 30 16

이는 현재, postsuser 테이블을 생성하지 않아 발생한 오류다.

DB Brower에 접근하여 posts, user 테이블을 생성한다.

create table posts (  
   id bigint not null auto_increment,   
   created_date datetime, modified_date datetime,  
   author varchar(255), content TEXT not null,   
   title varchar(500) not null, primary key (id)  
) engine=InnoDB;


create table user (  
   id bigint not null auto_increment,   
   created_date datetime,   
   modified_date datetime,   
   email varchar(255) not null,  
   name varchar(255) not null,   
   picture varchar(255),   
   role varchar(255) not null,   
   primary key (id)  
) engine=InnoDB;
스크린샷 2022-06-07 오후 12 20 08 스크린샷 2022-06-07 오후 12 20 36

 

(2) 스프링 세션 테이블

스프링 세션 테이블은 schema-mysql.sql 파일에서 확인할 수 있다.

스크린샷 2022-06-06 오후 12 38 17 스크린샷 2022-06-06 오후 12 38 24
CREATE TABLE SPRING_SESSION (  
   PRIMARY_ID CHAR(36) NOT NULL,  
   SESSION_ID CHAR(36) NOT NULL,  
   CREATION_TIME BIGINT NOT NULL,  
   LAST_ACCESS_TIME BIGINT NOT NULL,  
   MAX_INACTIVE_INTERVAL INT NOT NULL,  
   EXPIRY_TIME BIGINT NOT NULL,  
   PRINCIPAL_NAME VARCHAR(100),  
   CONSTRAINT SPRING_SESSION_PK PRIMARY KEY (PRIMARY_ID)  
) ENGINE=InnoDB ROW_FORMAT=DYNAMIC;  
  
CREATE UNIQUE INDEX SPRING_SESSION_IX1 ON SPRING_SESSION (SESSION_ID);  
CREATE INDEX SPRING_SESSION_IX2 ON SPRING_SESSION (EXPIRY_TIME);  
CREATE INDEX SPRING_SESSION_IX3 ON SPRING_SESSION (PRINCIPAL_NAME);  
  
CREATE TABLE SPRING_SESSION_ATTRIBUTES (  
   SESSION_PRIMARY_ID CHAR(36) NOT NULL,  
   ATTRIBUTE_NAME VARCHAR(200) NOT NULL,  
   ATTRIBUTE_BYTES BLOB NOT NULL,  
   CONSTRAINT SPRING_SESSION_ATTRIBUTES_PK PRIMARY KEY (SESSION_PRIMARY_ID, ATTRIBUTE_NAME),  
   CONSTRAINT SPRING_SESSION_ATTRIBUTES_FK FOREIGN KEY (SESSION_PRIMARY_ID) REFERENCES SPRING_SESSION(PRIMARY_ID) ON DELETE CASCADE  
) ENGINE=InnoDB ROW_FORMAT=DYNAMIC;

이것을 복사하여 RDS에 반영한다.

DB Brower에 접근하여 sql문을 입력한다.

스크린샷 2022-06-06 오후 12 33 27
  • 명령문 각각 드래그 한 후 실행하면 된다.

 

스크린샷 2022-06-06 오후 12 36 09
  • RDS에 필요한 테이블은 모두 생성했다.

 

💡 참고
스크린샷 2022-06-07 오후 12 22 57

  • SQLGrammarException, SQLSyntaxErrorException 발생
  • spring_rds.posts 테이블이 존재하지 않아 발생했다고 한다.
  • RDS에 posts 테이블을 반영하지 않은 상태에서 스프링 세션 테이블을 RDS에 반영할 시 이와 같은 오류가 발생한다.
  • 위에서(1) posts 테이블을 RDS에 적용하는 방법을 실행하면 해결된다!

 

📖 B. 프로젝트 설정

MYSQL 드라이버를 build.gradle에 등록한다.

스크린샷 2022-06-07 오후 12 55 36
implementation 'org.springframework.boot:spring-boot-starter-jdbc'  
implementation 'mysql:mysql-connector-java' // mysql

spring-boot-starter-jdbc를 넣지 않아도 된다.

 

그리고 서버에서 구동될 환경을 하나 구성한다.
src/main/resourceapplication-yml파일을 추가한다.

스크린샷 2022-06-07 오후 12 59 09
spring:  
  profiles:  
    include: oauth, real-db  
  jpa:  
    database-platform: org.hibernate.dialect.MySQL5InnoDBDialect  
  session:  
    store-type: jdbc
  • application-real.yml로 파일을 만들면 profile=real인 환경이 구성된다고 보면 된다.
  • 실제 운영될 환경이기 때문에 보안/로그상 이슈가 될 만한 설정들을 모두 제거하며 RDS 환경 profile 설정이 추가된다.

모든 설정이 되었다면 github에 push한다.

 

📖 C. EC2 설정

OAuth와 마찬가지고 RDS 접속 정보도 보호해야 할 정보이니 EC2 서버에 직접 설정 파일을 둔다.
app디렉토리에 application-real-db.yml파일을 생성한다.

vim ~/app/application-real-db.yml

그리고 다음 내용을 추가한다.

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://rds주소:3306/데이터베이스이름
    username: db계정명
    password: db계정 비밀번호
  jpa:
    hibernate:
      ddl-auto: none

여기서 조심할 것이 있다. 구글링하니 rds 주소에 localhost를 적어놓길래 나도 따라하다 3시간동안 오류를 해결하지 못했다.
rds 주소는

스크린샷 2022-06-07 오후 1 08 42

RDS 데이터베이스의 엔드포인트이다!!!

스크린샷 2022-06-07 오후 1 11 13
  • spring.jpa.hibernate.ddl-auto=none (application)
    • JPA로 테이블이 자동 생성되는 옵션을 None(생성하지 않음)으로 지정한다.
    • RDS에는 실제 운영으로 사용될 테이블이니 절대 스프링 부트에서 새로 만들지 않도록 해야 한다.
    • 이 옵션을 하지 않으면 자칫 테이블이 모두 새로 생성될 수 있다.
    • 주의해야 하는 옵션

 

마지막으로 deploy.sh에 real profile을 쓸 수 있도록 다음과 같이 개선한다.

스크린샷 2022-06-07 오후 1 19 11
nohup java -jar \
        -Dspring.config.location=classpath:/application.yml,/home/ec2-user/app/application-oauth.yml,/home/ec2-user/app/application-real-db.yml,classpath:/application-real.yml \
        -Dspring.profiles.active=real \
        $REPOSITORY/$JAR_NAME 2>&1 &
  • Dspring.profiles.active=real
    • application-real.yml를 활성화
    • application-real.ymlspring.profiles.include=oauth,real-db 옵션 때문에 real-db 역시 함께 활성화 대상에 포함된다.

 

이제 이렇게 설정한 후 deploy.sh를 실행한 후, nohup.out 파일을 열어

스크린샷 2022-06-07 오후 1 23 40 스크린샷 2022-06-07 오후 1 28 41 스크린샷 2022-06-07 오후 1 32 04

이와 같은 로그가 보인다면 성공적으로 수행된 것이다.

curl 명령어로 html 코드가 정상적으로 보인다면 성공한 것이다.

스크린샷 2022-06-07 오후 1 29 57

 

 

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

이제 브라우저에서 확인해볼 것이다.
그 전에 다음과 같은 몇 가지 작업을 하겠다.

📖 A. AWS 보안 그룹 변경

EC2에 스프링 부트 프로젝트가 8080 포트로 배포되었으니, 8080 포트가 보안 그룹에 열려 있는지 확인한다.

스크린샷 2022-06-08 오전 11 04 38

인스턴스 메뉴에서 생성한 EC2 인스턴스를 선택하면 퍼블릭 DNS를 확인할 수 있다.

스크린샷 2022-06-08 오전 11 20 34

이 주소가 EC2에 자동으로 할당된 도메인이다. 인터넷이 되는 장소 어디나 이 주소를 입력하면 우리의 EC2 서버에 접근할 수 있다.
도메인 주소에 8080 포트를 붙여 브라우저에 입력하면

스크린샷 2022-06-08 오전 11 23 39

만든 서비스가 이제 도메인을 가진 서비스가 되었다!

 

📖 B. 서비스에 EC2의 도메인을 등록

현재는 구글과 네이버 로그인이 작동하지 않는다.

스크린샷 2022-06-08 오전 11 25 27

차례로 서비스에 등록해보자!

✔️ 구글에 EC2 주소 등록

구글 웹 콘솔(https://console.cloud.google.com/home/dashboard)로 접속하여 프로젝트로 이동한 다음 API 및 서비스 → 사용자 인증 정보로 이동한다.

스크린샷 2022-06-08 오전 11 29 51

 

스크린샷 2022-06-08 오전 11 31 55
  • OAuth 동의 화면 탭을 선택하고 아래에서 승인된 도메인에 http:// 없이 EC2의 퍼블릭 DNS를 등록한다.

 

스크린샷 2022-06-08 오전 11 32 43
  • 사용자 인증 정보 탭을 클릭해서 본인이 등록한 서비스의 이름을 클릭한다.

 

스크린샷 2022-06-08 오전 11 34 40
  • 퍼블릭 DNS 주소에 :8080/login/oauth2/code/google 주소를 추가하여 승인된 리디렉션 URL에 등록한다.

 

모든 작업이 끝났다!
EC2 DNS 주소로 이동해서 다시 구글 로그인을 시도해 보면 다음과 같이 로그인이 정상적으로 수행되는 것을 확인할 수 있다.

스크린샷 2022-06-08 오전 11 35 29

 

✔️ 네이버에 EC2 주소 등록
네이버 개발자 센터(https://developers.naver.com/apps/#/myapps)로 접속해서 본인의 프로젝트로 이동한다.

스크린샷 2022-06-08 오전 11 48 31

 

아래로 내려가 보면 PC 웹 항목이 있는데 여기서 서비스 URL와 Callback URL 2개를 수정한다.

스크린샷 2022-06-08 오전 11 50 41
  • 서비스 URL

    • 로그인을 시도하는 서비스가 네이버에 등록된 서비스인지 판단하기 위한 항목이다.
    • 8080 포트는 제외하고 실제 도메인 주소만 입력한다.
    • 네이버에서 아직 지원되지 않아 하나만 등록 가능하다.
    • 즉, EC2의 주소를 등록하면 localhost가 안된다.
    • 개발 단계에서는 등록하지 않는 것을 추천한다.
    • localhost도 테스트하고 싶으면 네이버 서비스를 하나 더 생성해서 키를 발급받으면 된다.
  • Callback URL

    • 전체 주소를 등록한다. (EC2 퍼블릭 : DNS:8080/login/oauth2/code/naver)

 

💡 참고

스크린샷 2022-06-08 오후 12 39 04

이와 같은 오류가 발생한다면, application-oauth.yml에서 네이버 API에 등록한 Callback URL을 입력하는 redirect-url 을 확인한다.

스크린샷 2022-06-08 오후 12 37 23

aws 연동하기 전까지는 로컬 컴퓨터에서 사용했기 때문에 localhost:8080을 사용했을 것이다.
localhost퍼블릭 DNS 주소로 변경해주면 잘 실행된다.

스크린샷 2022-06-08 오후 12 47 03

성공!
스크린샷 2022-06-08 오후 12 20 26

 

2개의 항목을 모두 수정/추가 했다면 구글과 마찬가지로 네이버 로그인을 시도한다.
그러면 다음과 같이 로그인이 정상적으로 수행되는 것을 확인할 수 있다.

스크린샷 2022-06-08 오후 12 20 42 스크린샷 2022-06-08 오후 12 20 47

구글과 네이버 로그인도 EC2와 연동 완료되었다!
간단하게나마 스프링 부트 프로젝트를 EC2에 배포해 보았다.

 

✏️ 현재 방식 몇 가지 문제점

  • 수동 실행되는 Test
    • 본인이 짠 코드가 다른 개발자의 코드에 영향을 끼치지 않는지 확인하기 위해 전체 테스트를 수행해야만 한다.
    • 현재 상태에선 항상 개발자가 작업을 진행할 때마다 수동으로 전체 테스트를 수행해야만 한다.
  • 수동 Build
    • 다른 사람이 작성한 브랜치와 본인이 작성한 브랜치가 합쳐졌을 때(Merge) 이상이 없는지는 Build를 수행해야만 알 수 있다.
    • 이를 매번 개발자가 직접 실행해봐야만 한다.

 

그래서 다음 장에서는 이런 수동 Test & Build를 자동화시키는 작업을 진행해보겠다.
깃허브에서 푸시를 하면 자동으로 Test & Build & Deploy가 진행되도록 개선하는 작업이다!

 

profile
"야, (오류 만났어?) 너두 (해결) 할 수 있어"

0개의 댓글