Back-End/REST with spring boot basic

06. 데이터베이스 연동 – docker 기반

728x90

DOCKER 설치

리눅스 기반 클라우드 서버가 있다면 거기에 MariaDB를 설치하면 되지만,  가장 쉽게 데이터베이스를 설치하는 방법은 리눅스 기반에 MariaDB를 설치하고 그것을 이미지로 구워놓은걸 가져다 쓰면 제일 쉽게 설치할 수 있다. 이 개념이 docker 기반으로 docker는 컨테이너 이고 컨테이너 위에 이미지를 올리면 된다. 그러므로 먼저 docker를 설치해야 한다.

윈도우 기반에 docker를 설치를 설치해도 되고 여기서는 아마존 서버 혹은 구글 클라우드 서버 Centos7 64비트 머신위에 docker를 설치해본다.

# yum update 가 제대로 실행되지 않을 경우 아래에서 baseurl 주석을 제거한다.
vi /etc/yum.repos.d/CentOS-Base.repo

# 설치전에 패키지 정보 업데이트를 한번 실행한다.
yum update -y

# docker를 yum으로 설치
yum -y install docker docker-registry

# 서비스로 등록하고 부팅시 자동 실행 설정
systemctl enable docker.service
systemctl start docker.service

데이터베이스 설치

여기서는 MariaDB를 설치를 할것이고 docker Hub 사이트 공식 Maridb  이미지는 https://hub.docker.com/_/mariadb/ 이다. 여기가서 설명서를 읽고 설치하면 된다.

# docker 설치
docker run -d –name mariadb -v /var/maria/data/:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456  -p 3306:3306 mariadb

# docker 설치가 제대로 되었는지 확인
docker ps

docker 설치시 옵션을 설명하자면 다음과 같다.

run -d :  백그라운드로 실행하라.

–name mariadb: 이름을 mariadb로 지정한다.

-v /var/maria/data/:/var/lib/mysql: docker와 물리적 디스크를 연결한다. 이걸 하기 전에 먼저 /var/maria/data 폴더를 만들어 놓아야 한다.

-e MYSQL_ROOT_PASSWORD=123456: 환경설정을 한다. root 패스워드를 123456으로 설정하였다

-p 3306:3306 : 외부 포트 3306을 내부포트 3306과 연결한다.

mariadb: 이미지 이름이다.

데이터베이스 설정

docker 내부로 진입하여 데이터베이스를 만들고 계정정보와 패스워드를 설정하고 권한을 위임한다.

# docker 내부로 진입
docker exec -it mariadb /bin/bash

# 프람프트가 바뀜에 주의. mysql로 진입하자.
root@20cd70cb8759:/# mysql -u root -p

# eastdb라는 이름의 데이터베이스 생성
MariaDB [(none)]> create database eastdb;

# eastflag이라는 계정 생성과 패스워드 설정
MariaDB [(none)]> grant all on eastdb.* to eastflag identify by ‘********’;

# 권한 위임
MariaDB [(none)]> grant all on eastdb.* to eastflag identified by ‘********’;

# 쓰기 완료
MariaDB [(none)]> flush privileges;

한글 설정

/etc/my.cnf 화일을 아래와 같이 한글부분만 보고 수정한다.

#
# This group is read both both by the client and the server
# use it for options that affect everything
#
[client-server]
 
#
# include all files from the config directory
#
[mysql]
default-character-set = utf8
 
[mysqld]
skip-host-cache
skip-name-resolve
lower_case_table_names=1
character-set-client-handshake=FALSE
init_connect="SET collation_connection = utf8_general_ci"
init_connect="SET NAMES utf8"
character-set-server = utf8
collation-server = utf8_general_ci
max_connections = 500 
thread_pool_max_threads = 300 
innodb_file_per_table                           # innodb 테이블스페이스를 테이블별로 각각의 파일로 나누어 생성한다. 
innodb_buffer_pool_size = 2G               # 버퍼풀의 메모리 사이즈. 권장은 메인메모리의 50~70% (전용서버일때) 디폴트는 8M  
innodb_flush_log_at_trx_commit = 1 
innodb_adaptive_flushing = ON
innodb_adaptive_hash_index = ON
innodb_autoextend_increment  = 8  # 테이블스페이스를 자동으로 늘려주는 단위, MB 단위이다. 
 
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
symbolic-links=0
 
[mysqld_safe]
log-error=/var/log/mariadb/mariadb.log
pid-file=/var/run/mariadb/mariadb.pid
 
!includedir /etc/my.cnf.d

mariadb를 재기동한다.

systemctl restart mariadb

mysql 로 진입해서 아래 명령어로 utf-8로 바뀌어있는지 확인한다.

MariaDB [(none)]> show variables like 'c%';
+--------------------------+----------------------------+
| Variable_name            | Value                      |
+--------------------------+----------------------------+
| character_set_client     | utf8                       |
| character_set_connection | utf8                       |
| character_set_database   | utf8                       |
| character_set_filesystem | binary                     |
| character_set_results    | utf8                       |
| character_set_server     | utf8                       |
| character_set_system     | utf8                       |
| character_sets_dir       | /usr/share/mysql/charsets/ |
| collation_connection     | utf8_general_ci            |
| collation_database       | utf8_general_ci            |
| collation_server         | utf8_general_ci            |
| completion_type          | NO_CHAIN                   |
| concurrent_insert        | AUTO                       |
| connect_timeout          | 10                         |
+--------------------------+----------------------------+
14 rows in set (0.00 sec)

데이터베이스 연동

이제 스프링 boot에서 데이터베이스로 연동한다.  스프링에서 사용하는 ORM 솔루션은 JPA와 MyBatis 두가지가 가장 많이 사용되는데, 둘 다 장단점이 있다. 간단한 CRUD를 한다면 JPA로 하는게 편하고 복잡한 join문으로 쿼리가 복잡해지면 JPA 보다 MyBatis로 하는게 기존 쿼리를 그대로 활용할 수 있기 때문에 더 좋을수 있다. 여기서는 MyBatis를 사용하겠다. 먼저 MyBatis 관련 패키지와 MariaDB 패키지를 build.gradle에 추가한다.

dependencies {
    compile('org.springframework.boot:spring-boot-devtools')
    compile('com.microsoft.sqlserver:mssql-jdbc')
    compile("org.mybatis.spring.boot:mybatis-spring-boot-starter:1.3.1")
    compile("org.springframework.boot:spring-boot-starter-jdbc")
    implementation 'org.springframework.boot:spring-boot-starter-web'
    compileOnly 'org.projectlombok:lombok'
    annotationProcessor 'org.projectlombok:lombok'

    runtime("mysql:mysql-connector-java")

    testImplementation('org.springframework.boot:spring-boot-starter-test') {
        exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
    }
}

spring-boot-starter-jdbc는 DataSource, ConnectionFactory 등 복잡한 설정을 아주 간단하게 해준다.

이제 MariaDB와 연결하기 위한 DB 접속 정보를 src -> main ->resources 아래에 application.yml 파일을 추가하고 아래와 같이 작성한다. application.properties와 application.yml은 동일한데, yaml 파일은 tree 구조로 작성이 가능하다. 만일 dirver에서 에러가 발생한다면 위에 패키지가 아직 설치가 안된것이므로 gradle sync를 한번 해주면 된다.

spring:
  datasource:
    driver-class-name: "com.mysql.jdbc.Driver"
    url: "jdbc:mysql://www.javabrain.kr:3306/eastdb?useUnicode=true&charaterEncoding=utf-8"
    username: "eastflag"
    password: "xxxxxxxx"

이제 shift 키를 두번 누르고 database를 입력하고 선택하면 오른쪽에 database 탭이 보일것이다.

여기서 + 를 누르고 DataSource 선택후 MySql을 선택한다. 위에서 지정한 database, user, password, 를 각각 입력하고 테스트 버튼을 눌르서 success가 뜨는지 확인한다.

CORS 설정

브라우저에서 프런트서버도 호출하고 백엔드 서버도 호출하게 되면 cross domain 이슈가 발생한다. main 클래스가 있는곳에 CORS 필터를 등록한다.

//CORS 필터
@Bean
public FilterRegistrationBean corsFilter() {
  UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
  CorsConfiguration config = new CorsConfiguration();
  config.setAllowCredentials(true);
  config.addAllowedOrigin("*");
  config.addAllowedHeader("*");
  config.addAllowedMethod("*");
  source.registerCorsConfiguration("/**", config);

  FilterRegistrationBean registrationBean = new FilterRegistrationBean();
  registrationBean.setFilter(new CorsFilter(source));
  registrationBean.setOrder(0);
  return registrationBean;
}