스프링 부트와 AWS로 혼자 구현하는 웹 서비스 를 공부하고 정리한 내용입니다.
RDS는 MYSQL을 사용 중이다.
이 MYSQL에서 스프링부트 프로젝트를 실행하기 위해선 몇 가지 작업이 필요하다.
🔔 진행할 작업
- 테이블 생성 : H2에서 자동 생성해주던 테이블들을 MYSQL에선 직접 쿼리를 이용해 생성한다.
- 프로젝트 설정 : 자바 프로젝트가 MYSQL에 접근하려면 데이터베이스 드라이버가 필요하다. MYSQL에서 사용 가능한 드라이버를 프로젝트에 추가한다.
- EC2 (리눅스 서버) 설정 : 데이터베이스의 접속 정보는 중요하게 보호해야 할 정보이다. 공개되면 외부에서 데이터를 모두 가져갈 수 있기 때문이다. 프로젝트 안에 접속 정보를 갖고 있다면 깃허브와 같이 오픈된 공간에선 누구나 해킹할 위험이 있다. EC2 서버 내부에서 접속 정보를 관리하도록 설정한다. (
application-real-db.yml
)
여기선 JPA가 사용될 엔티티 테이블과 스프링 세션이 사용될 테이블 2가지 종류를 생성한다.
JPA가 사용할 테이블은 테스트 코드 수행 시 로그로 생성되는 쿼리를 사용하면 된다.
(1) 테스트 코드를 수행하면 다음과 같은 로그가 발생한다.
이는 현재, posts
와 user
테이블을 생성하지 않아 발생한 오류다.
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문을 입력한다.
💡 참고
- SQLGrammarException, SQLSyntaxErrorException 발생
- spring_rds.posts 테이블이 존재하지 않아 발생했다고 한다.
- RDS에 posts 테이블을 반영하지 않은 상태에서 스프링 세션 테이블을 RDS에 반영할 시 이와 같은 오류가 발생한다.
- 위에서(1) posts 테이블을 RDS에 적용하는 방법을 실행하면 해결된다!
MYSQL 드라이버를 build.gradle
에 등록한다.
implementation 'org.springframework.boot:spring-boot-starter-jdbc'
implementation 'mysql:mysql-connector-java' // mysql
spring-boot-starter-jdbc
를 넣지 않아도 된다.
그리고 서버에서 구동될 환경을 하나 구성한다.
src/main/resource
에 application-yml
파일을 추가한다.
spring:
profiles:
include: oauth, real-db
jpa:
database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
session:
store-type: jdbc
application-real.yml
로 파일을 만들면 profile=real
인 환경이 구성된다고 보면 된다.모든 설정이 되었다면 github에 push한다.
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)
마지막으로 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.yml
의 spring.profiles.include=oauth,real-db
옵션 때문에 real-db
역시 함께 활성화 대상에 포함된다.
이제 이렇게 설정한 후 deploy.sh를 실행한 후, nohup.out 파일을 열어
이와 같은 로그가 보인다면 성공적으로 수행된 것이다.
curl 명령어로 html 코드가 정상적으로 보인다면 성공한 것이다.
이제 브라우저에서 확인해볼 것이다.
그 전에 다음과 같은 몇 가지 작업을 하겠다.
EC2에 스프링 부트 프로젝트가 8080 포트로 배포되었으니, 8080 포트가 보안 그룹에 열려 있는지 확인한다.
인스턴스 메뉴에서 생성한 EC2 인스턴스를 선택하면 퍼블릭 DNS를 확인할 수 있다.
이 주소가 EC2에 자동으로 할당된 도메인이다. 인터넷이 되는 장소 어디나 이 주소를 입력하면 우리의 EC2 서버에 접근할 수 있다.
도메인 주소에 8080 포트를 붙여 브라우저에 입력하면
만든 서비스가 이제 도메인을 가진 서비스가 되었다!
현재는 구글과 네이버 로그인이 작동하지 않는다.
차례로 서비스에 등록해보자!
✔️ 구글에 EC2 주소 등록
구글 웹 콘솔(https://console.cloud.google.com/home/dashboard)로 접속하여 프로젝트로 이동한 다음 API 및 서비스 → 사용자 인증 정보로 이동한다.
http://
없이 EC2의 퍼블릭 DNS를 등록한다.
:8080/login/oauth2/code/google
주소를 추가하여 승인된 리디렉션 URL에 등록한다.
모든 작업이 끝났다!
EC2 DNS 주소로 이동해서 다시 구글 로그인을 시도해 보면 다음과 같이 로그인이 정상적으로 수행되는 것을 확인할 수 있다.
✔️ 네이버에 EC2 주소 등록
네이버 개발자 센터(https://developers.naver.com/apps/#/myapps
)로 접속해서 본인의 프로젝트로 이동한다.
아래로 내려가 보면 PC 웹 항목이 있는데 여기서 서비스 URL와 Callback URL 2개를 수정한다.
서비스 URL
Callback URL
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
가 진행되도록 개선하는 작업이다!