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) 테스트 코드를 수행하면 다음과 같은 로그가 발생한다.

이는 현재, 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;

 

(2) 스프링 세션 테이블

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

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문을 입력한다.

  • 명령문 각각 드래그 한 후 실행하면 된다.

 

  • RDS에 필요한 테이블은 모두 생성했다.

 

💡 참고

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

 

📖 B. 프로젝트 설정

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

implementation 'org.springframework.boot:spring-boot-starter-jdbc'  
implementation 'mysql:mysql-connector-java' // mysql

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

 

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

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 주소는

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

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

 

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

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 파일을 열어

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

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

 

 

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

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

📖 A. AWS 보안 그룹 변경

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

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

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

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

 

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

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

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

✔️ 구글에 EC2 주소 등록

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

 

  • OAuth 동의 화면 탭을 선택하고 아래에서 승인된 도메인에 http:// 없이 EC2의 퍼블릭 DNS를 등록한다.

 

  • 사용자 인증 정보 탭을 클릭해서 본인이 등록한 서비스의 이름을 클릭한다.

 

  • 퍼블릭 DNS 주소에 :8080/login/oauth2/code/google 주소를 추가하여 승인된 리디렉션 URL에 등록한다.

 

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

 

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

 

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

  • 서비스 URL

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

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

 

💡 참고

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

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

성공!

 

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

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

 

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

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

 

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

 

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

0개의 댓글