본문 바로가기
Spring

Spring Framework (5) - Database MariaDB 연동

by 이도현 2021. 5. 19.

 

    MariaDB를 설치하는 과정은 운영체제가 윈도우즈인지, 리눅스인지, 맥OS인지에 따라 방법이 다르고, 이에 대해서는 구글 검색을 통해 쉽게 찾아볼 수 있으므로 여기서는 따로 작성하지 않겠다.

    다만, 만약 데이터베이스를 설치하였다면, 이후의 작업을 위해 IP주소, 포트번호, 계정명, 비밀번호를 알고 있어야 한다. 설치를 지금 사용하고 있는 컴퓨터(로컬 컴퓨터)에 하였다면, IP주소는 localhost(127.0.0.1)이며, 포트번호를 따로 바꾸지 않았다면 3306이다. 계정명은 새로 생성하지 않았다면 root일 것이고, 비밀번호는 설치시 본인이 설정한 비밀번호이다. 만약 설치한 컴퓨터가 로컬 컴퓨터가 아닌경우는 따로 주소와 포트번호를 설정하였을 것이고, 이 정보를 알고 있어야 그 데이터베이스에 접근이 가능하다. 

    먼저 Java언어를 사용하는 경우 데이터베이스와의 연동을 위해서는 JDBC(Java Database Connectivity)라는 자바 API를 사용하여야 한다. Spring 역시 Java를 기반으로 만들어진 프레임워크이므로 당연히 JDBC를 이용해야만 데이터베이스에 접근이 가능하다. 이제 Spring에서 어떤 설정을 해야 데이터베이스에 있는 데이터에 접근이 가능한지 알아보겠다.

    먼저 메이븐 리포지터리 웹페이지를 켠다. 주소는 다음과 같다. 

https://mvnrepository.com/

    메이븐 리포지터리는 간략히 말하면, 메이븐에서 의존성(dependency)을 설정하기 위한 데이터들을 보관하고 있는 저장소(repository)라고 할 수 있다. 많은 개발자, 개발단체·기관들이 개발을 위해 필요한 어떤 기능을 위해 필요한 파일들을 모아 jar(Java Archive,자바 아카이브)파일로 패키징해 공유하는데, 이를 보관하는 곳이 메이븐 리포지터리이다. 우리는 여기서 우리가 필요한 파일을 찾아서 이 파일을 우리가 작업하는 프로젝트에 집어넣어 사용하는데, 우리가 만드는 프로젝트는 리포지터리에서 받은 jar파일들에 의존하여 개발되기 때문에 이를 의존관계를 설정하여 집어 넣는다는 의미에서 DI(Dependency injection, 의존성 주입)이라고 한다. 사실 나는 의존성 주입이라는 말이 번역으로는 별로 좋지 않다고 생각한다. 의존관계설정이라는 것이 좀 더 이해하기 편하지 않을까하는 생각을 해본다. 

    먼저 스프링에서 제공하는 jdbc를 찾아보자. 메이븐 리포지터리에 접속해 검색창에 Spring JDBC를 검색하고 제일 상단에 나오는 Spring JDBC를 클릭하자. 들어가보면 스프링 버전 5.2.8.RELEASE 이 최신임을 알 수 있다. 이 버전은 현재 사용하고 있는 최신의 버전과 동일하다. 최신버전을 클릭하여 들어가면 하단에 

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>5.2.8.RELEASE</version>
</dependency>

이 나와있다. 해당 내용을 Ctrl + C를 눌러 복사하자. 그리고 이클립스로 돌아가 38번 째 줄에 <!-- AspectJ --> 위쪽에 붙여 넣기를 하자. 그리고 version 안에 ${org.springframework-version} 를 입력하자. <!-- --> 안의 주석부분도 Spring JDBC 로 바꾸자. 그러면 다음과 같아진다. 

<!-- Spring JDBC -->
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-jdbc</artifactId>
  <version>${org.springframework-version}</version>
</dependency>

    다시 메이븐 리포지터리 홈페이지로 접속해 검색창에 mariadb를 검색한다. 그러면 제일 위쪽에 "MariaDB Java Client"이라는 것이 제일 상단에 나타나텐데, 이를 클릭하여 들어가보자. 화면에 여러가지 버전들이 나올텐데, 이 중에서 제일 최근의 것을 사용해 보자. 현재 시점(2020.08.08)에는 2.6.2 버전이 가장 최신으로 나오니 해당 버전의 숫자를 클릭해보자. 그러면 화면이 바뀌면서 하단에 

<dependency>
    <groupId>org.mariadb.jdbc</groupId>
    <artifactId>mariadb-java-client</artifactId>
    <version>2.6.2</version>
</dependency>

라는 부분이 나온다. 이 내용을 Ctrl+C로 복사하자. 그리고 이제 이크립스로 돌아가서 Ctrl + Shift + R을 눌러 pom.xml을 검색하여 찾은 후 파일을 열자. 지금까지의 과정을 정상적으로 따라왔고, 다른 설정을 추가하지 않았다면 119줄 쯤에 </dependencies>이 보일 것이다(cies라는 복수형으로 끝난다는 점에 주의). 여기는 의존관계 설정이 끝나는 지점을 표시하는데, 우리는 새로 의존관계를 설정해야하므로 상단에  </dependency>으로 끝나는 지점과 </dependencies>이 시작하는 지점 사이를 클릭하고 엔터를 쳐서 한줄을 띄운 다음 아까 복사해온 내용을 Ctrl + V를 눌러 붙여 넣자. 그다음 코드 정리를 위해서 Ctrl + A를 눌러 전체 선택을 한후 Ctrl + SHIFT+ F 를 눌러 소스를 정리하자. 그 다음 파일을 저장하기 위해 Ctrl + S를 누르자. 

 

    버전을 추가하는 경우 프로퍼티로 빼서 따로 관리하는 것이 좋고, <!--  --> 사이의 주석부분도 보기좋게 수정하는 것이 좋다. 일단 이클립스의 pom.xml창의 하단에 보이는 overview 탭을 좌클릭하자. Properties 항목의 우측에 Create를 좌클릭하자. Add property 창이 뜨면, Name에는 org.mariadb.jdbc-version 을 쓰고, Value에는 방금 받은 버전 (나의 경우는 2.6.2)를 써넣고 OK를 좌클릭하자. property가 추가된 것이 확인될 것이다. 다시 pom.xml창 하단의 pom.xml탭을 클릭하여 소스코드로 돌아오자. 스크롤하여 페이지 상단으로 올라오면 

<org.mariadb.jdbc-version>2.6.2</org.mariadb.jdbc-version>

이 추가된 것을 확인할 수 있다. 다시 스크롤을 내려서 방금 추가한 항목을 적용하자. 

<dependency>
  <groupId>org.mariadb.jdbc</groupId>
  <artifactId>mariadb-java-client</artifactId>
  <version>${org.mariadb.jdbc-version}</version>
</dependency>

    해당 부분을 위와 같이 수정하였다면, 이제 주석을 수정해 보자. 

 

위와 같이 적용되어 있는 부분을 

<!-- MariaDB Java Client -->

와 같이 수정하자. 이제 소스 파일은 

<!-- MariaDB Java Client -->
<dependency>
  <groupId>org.mariadb.jdbc</groupId>
  <artifactId>mariadb-java-client</artifactId>
  <version>${org.mariadb.jdbc-version}</version>
</dependency>

이렇게 적용되어 있을 것이다. Ctrl + S로 소스파일을 저장한다. 이제 의존관계에 대한 설정을 하였으니, 이클립스 화면 좌측의 Package Explorer에서 Maven Dependencies라는 항목을 더블클릭하면 최하단에 mariadb-java-client로 시작하는 jar파일이 추가되어 있음을 확인할 수 있다. 

 

이러면 일단 우리는 JDBC를 위한 의존관계설정을 정상적으로 마쳤다고 볼 수 있다.

 

    하지만 이렇게 의존관계를 설정해 놓았다고 DB와 데이터를 주고 받을 수 있는 것은 아니다. 이제 접속을 하기 위해 아까 말한 IP주소, 포트번호, 계정명, 비밀번호을 어딘가에 적어 넣어야 할 것이다. 

 

    이제 우리는 이런 설정을 담은 파일을 하나 작성할 것이다. 예전에 web.xml에서 모든 서블렛과 필터들에 공통으로 적용되는 파일은 /WEB-INF/spring/*-context.xml 에 위치시키기로 설정했으니, 이제 그 위치를 찾아가서 파일을 생성해본다. 

 

    좌측의 패키지 익스플로러 창에서 내가 생성한 프로젝트를 더블클릭하여 내부 파일 목록을 보면 src라는 폴더가 보인다. 이후 main -> webapp -> WEB-INF -> spring 까지 더블클릭하여 들어간다. 그리고 spring 폴더를 좌클릭한 후 우클릭하여 new -> other... 을 클릭하자. 창이 하나뜨는데 xml이라고 검색하자. XML File이라는 항목이 보일 것이다. 좌클릭하고 창 하단의 Next를 클릭하자. 파일명을 입력하라고 나오는 데, 나는 database-context.xml을 사용하려 한다. 이름을 입력하고 Next를 클릭하자. Create XML file from an XML template를 클릭하고 Next를 클릭하자. 다음 화면에서는 별다른 내용을 입력하지 않고 바로 Finish를 클릭하자. 

    이렇게 파일을 생성하고 나면 아마 Problems창에 에러가 뜰 것이다. 이 xml파일에 대해서 설명한 내용이 없기 때문이다. 이제 우리가 어떤 DTD나 xml 스키마를 사용할지 기술해야 이러한 에러가 사라진다. 일단 우리가 생성해야할 것은 스프링에서 제공하는 beans라는 네임스페이스를 사용해야 한다. beans에 대해서는 추후에 설명하기로 하고, 일단 먼저 적용해보자. 

<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>

 

해당 내용을 생성한 파일의 <?xml version="1.0" encoding="UTF-8"?> 밑에 넣어주자. 

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">

</beans>

 

위와 같이 되었다면 Problems 창에 에러가 모두 사라질 것이다. 

    이제 데이터를 주고 받기 위해 DataSource에 대한 설정을 하여야 하는데 DataSource에 대한 설정은 추후 시간이 되면 다루도록 하고 여기서는 일단 설정 방법만 언급하고 넘어가겠다.

    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="org.mariadb.jdbc.Driver"></property>
        <property name="url" value="jdbc:mariadb://127.0.0.1:3306/spring"></property>
        <property name="username" value="name"></property>
        <property name="password" value="password"></property>
    </bean>

 

이 내용을 </beans> 앞에 넣어준다. 여기서 url, username,  password의 값은 처음에 알아야한다고 말했던 데이터를 위의 양식에 맞게 수정하여 적용하면 된다. 

 

    이제 아까 pom.xml에 의존관계 설정한 파일들이 어떻게 사용되고 있는지 확인해보자. 일단     <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">에서 class의 "org.springframework.jdbc.datasource.DriverManagerDataSource"값을 Ctrl을 누른 채 좌클릭 해보자. 좌측의 패키지익스플로러 창이 켜지면서 소스파일이 뜰 것이다. 만약 소스파일이 뜨지 않는다면 패키지 익스플로러 창의 탭 좌측에 있는 교차된 화살표 표시를 클릭해보자. 켜져 있는 소스파일의 위치를 패키지 익스플로러 창에서 어디에 위치하는 지 찾아주는 기능이다. 

켜져 있는 소스는 spring-jdbc jar파일 안에 위치하고 있음을 알 수 있다. 이제 다음으로 <property name="driverClassName" value="org.mariadb.jdbc.Driver"></property>의 "org.mariadb.jdbc.Driver" 값을 Ctrl을 누른 채 좌클릭 해보자. mariadb-java-client jar파일 안에 위치하고 있음을 알 수 있다. 우리가 의존성 주입(의존관계를 설정)한 것들은 이런식으로 우리 소스 안에서 활용되고 있다.

 

    이제 스프링에서 접속 테스트를 해보아야 하는데, 이를 위해서는 테스트를 위한 의존관계를 설정해주어야 한다. 메이븐 리파지터리로 가서 Spring TestContext Framework을 검색하여 pom.xml에 설정하자. 

<!-- Spring TestContext Framework -->
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-test</artifactId>
  <version>${org.springframework-version}</version>
  <scope>test</scope>
</dependency>

위와 같이 추가하면 되는데, 나중에는 pom.xml이 매우 길어지게 되므로 기존에 작성했던 Spirng관련 설정 아래에 추가하는 것이 좋다. 

 

(테스트는 관련 설정이 모두 끝난 다음 하기 위해 여기서는 그냥 넘어간다.)

    이제 테스트를 위한 파일을 생성하기 위해 좌측 패키지 익스플로러 창 에서 src/test/java 를 좌클릭하여 선택하고, 우클릭을 하여 new -> Class 를 클릭하자. New Java Class라는 창이 뜰 것이다. 여기서 Name에 DataSourceConnectionTest라는 이름을 입력하고 Finish를 좌클릭하자. 파일이 생성되어 창이 나타날 것이다. 이제 아래와 같이 소스파일을 작성하자.

 

 

import java.sql.Connection;

 

import javax.inject.Inject;

import javax.sql.DataSource;

 

import org.apache.log4j.Logger;

import org.junit.Test;

import org.junit.runner.RunWith;

import org.springframework.test.context.ContextConfiguration;

import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

 

@RunWith(SpringJUnit4ClassRunner.class)

@ContextConfiguration(locations = {"file:src/main/webapp/WEB-INF/spring/database-context.xml"})

public class DataSourceConnectionTest {

 

protected static Logger logger = Logger.getLogger(DataSourceConnectionTest.class.getName());

 

@Inject

private DataSource dataSource;

 

@Test

public void connectionTest() throws Exception{

 

try(Connection connection = dataSource.getConnection()) {

 

logger.info(connection.getCatalog());

 

} catch (Exception e) {

e.printStackTrace();

}

 

}

 

}

 

    테스트를 하기에 앞서 JUnit이라는 테스트 툴의 버전을 높여야 한다. 지금 바로 실행하면 버전문제로 에러가 나게 된다. 이처럼 최신버전을 사용하게 되면 구 버전은 정상적으로 실행되지 않는 문제가 있기 때문에 의존성 주입시에는 항상 이런 사항을 고려해야 한다. pom.xml로 가서 <!-- Test --> 라고 되어 있는 부분을 찾고 다음과 같이 수정한다.

<!-- Test -->
<dependency>
  <groupId>junit</groupId>
  <artifactId>junit</artifactId>
  <version>${junit-version}</version>
  <scope>test</scope>
</dependency>

 

    이러면 프로퍼티값이 설정되어 있지 않아 에러가 난다. 스크롤 하여 상단으로 가서 다음 소스를 마지막 프로퍼티값 다음에 입력하자.

<properties>
  <java-version>1.8</java-version>
  <org.springframework-version>5.2.8.RELEASE</org.springframework-version>
  <org.aspectj-version>1.6.10</org.aspectj-version>
  <org.slf4j-version>1.6.6</org.slf4j-version>
  <org.mariadb.jdbc-version>2.6.2</org.mariadb.jdbc-version>
  <junit-version>4.13</junit-version>
</properties>

 

 

이제 소스파일을 저장하고 DataSourceConnectionTest 파일로 돌아오자.

 

    테스트를 위해서는 이클릭스 상단의 네이게이션바의 벌레모양의 아이콘을 클릭하면 된다. 만약 창이 노출되면 JUnit을 더블클릭한다. 그러면 테스트가 실행되며 이클립스 하단의 Console 탭에 결과가 나온다. 내가 짜놓은 소스는 접속이 정상적으로 되는 경우 생성한 테이블의 이름이 반환되도록 해 놓았다.

 

INFO : org.springframework.test.context.support.DefaultTestContextBootstrapper - Loaded default TestExecutionListener class names from location [META-INF/spring.factories]: [org.springframework.test.context.web.ServletTestExecutionListener, org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener, org.springframework.test.context.support.DependencyInjectionTestExecutionListener, org.springframework.test.context.support.DirtiesContextTestExecutionListener, org.springframework.test.context.transaction.TransactionalTestExecutionListener, org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener, org.springframework.test.context.event.EventPublishingTestExecutionListener]

INFO : org.springframework.test.context.support.DefaultTestContextBootstrapper - Using TestExecutionListeners: [org.springframework.test.context.web.ServletTestExecutionListener@623a8092, org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener@a1cdc6d, org.springframework.test.context.support.DependencyInjectionTestExecutionListener@175b9425, org.springframework.test.context.support.DirtiesContextTestExecutionListener@3098cf3b, org.springframework.test.context.transaction.TransactionalTestExecutionListener@610f7aa, org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener@6a03bcb1, org.springframework.test.context.event.EventPublishingTestExecutionListener@21b2e768]

INFO : spring.DataSourceConnectionTest - spring

 

    만약 에러가 나게 되면 에러내용을 보고 구글을 검색하여 원인을 스스로 찾아보자. 

 

    이미 정상적으로 동작하는 것을 알았지만, 데이터베이스 접속을 위한 정보들은 보안성이 있게 보관되어야 하기 때문에, 소스파일 내에 접속주소나 아이디, 비밀번호를 넣어놓는 것은 좋은 방법이라 하기 어렵다. 즉, 이러한 프로퍼티값은 별로도 보관하는 것이 보안적으로도, 추후 관리의 차원에서도 용이하다. 이를 위해서 프로퍼티 값을 가진 파일은 별도로 생성하고, 그 파일을 읽어서 적용하는 방식으로 변경해본다. 네임스페이스 설정과 관련된 부분은 아래 링크를 통해서 설명과 사용법을 확인할 수 있다. 

 

https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#xsd-schemas

 

    이클릭스 좌측의 패키지 익스플로러 창에서 내 프로젝트 내의 src/main/resources 를 좌클릭한후 우클릭하여 new -> Folder로 properties라는 항목을 생성한다. 그리고 생성된 폴더를 좌클릭한 후 다시 우클릭하여 new -> File을 좌클릭 후 local.properties, dev.properties, prod.properties 라는 이름으로 각각 파일을 만든다. 

    일단 이렇게 생성된 세개의 파일에 다음과 같이 작성하자.

#Database
MariaDB.driverClassName=org.mariadb.jdbc.Driver
MariaDB.url=jdbc:mariadb://127.0.0.1:3306/spring
MariaDB.username=name
MariaDB.password=password

 

    당연히 url과 name, password 부분은 나의 데이터베이스 접속 정보로 수정하여 입력해야한다. 프로퍼티 파일은 =를 기준으로 좌측이 키(Key)가 되고 우측이 값(Value)이 된다. 엔터를 치면 다음 프로퍼티가 시작되는 부분이 된다. 그리고 스프링에서 프로퍼티 파일은 키값이 중복되는 경우 마지막으로 읽어온 키의 값이 적용되므로 중복되지 않도록 유의해야한다. 무슨 말이냐면, 만약 키 값을 MariaDB.username 대신 username를 사용하면, 이미 등록되어 있는 username이라는 프로퍼티 값이 있기 때문에 내가 적은 값이 적용되지 않는다는 뜻이다. 스프링 전체의 프로퍼티 파일은 일괄적으로 읽어서 적용되므로 앞으로도 프로퍼티의 키값이 중복되는 일이 없도록 관리해야한다. 그러므로 키값은 항상 고유한 값을 가지도록 "."으로 구분하여 중복되지 않도록 알아보기 쉽게 관리하는 것이 좋다. 사실 프로퍼티 파일은 하나로 묶어 놓는 것이 좋지만, 나는 작업시 가시성을 높이기 위해서 파일별로 정리하곤 한다.

 

    일단 이렇게 프로퍼티 파일을 작성하고 저장하고 나면 database-context.xml 파일로 돌아와서 소스 파일을 아래와 같이 수정한다. 

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd ">

<context:property-placeholder location="classpath:properties/${spring.profiles.active}.properties"/>

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
  <property name="driverClassName" value="${MariaDB.driverClassName}" />
  <property name="url" value="${MariaDB.url}"/>
  <property name="username" value="${MariaDB.username}"/>
  <property name="password" value="${MariaDB.password}"/>
</bean>

</beans>

 

    <context:property-placeholder location="classpath:properties/${spring.profiles.active}.properties"/>로 경로를 설정하고 나면, 내가 방금 작성한 프로퍼티들을 ${} 사이에 입력하여 불러올 수 있다. 이를 위해서는 context 라는 네임스페이스를 활용해야 하므로 상단에 관련 정보들을 기입하여야 한다. 개발환경에 대한 설정이 어디냐에 따라 프로퍼티를 읽어오는 파일이 다르게 구성해 놓았기 때문이다. 배포환경에 따라 web.xml에서 spring.profiles.active 값을 local/dev/prod로 바꾸면 된다. 

    이로서 스프링에서 데이터베이스와 연동하는 가장 기본적인 방식을 해보았다. 이제 추가적으로 더 작업할 내용을 다음에서 다뤄보겠다.