본문 바로가기
Spring/study

spring 3강 로깅, 데이터베이스 연결 테스트

by avvin 2019. 5. 28.


spring 3강 로깅, 데이터베이스(Oracle) 연결 테스트


영상에서 생략된 소스코드는 

http://mannaedu.com/bbs/board.php?bo_table=pds&wr_id=89&sfl=wr_subject&stx=spring&sop=and   << 참고



spring과 mybatis 


로깅툴


1) 로깅툴을 사용하는 이유

- System.out.println()은 IO리소스를 많이 사용하여 시스템이 느려질 수 있음

- 로그를 파일로 저장하여 분석할 필요가 있음


2) 로깅툴의 종류


- commons-logging : 스프링3에서 사용하던 로깅툴


- log4j : 효율적인 메모리 관리로 그동안 많이 사용되었음


- logback : log4j보다 성능이 우수하여 최근에 많이 사용되고 있음


  SLF4J : logback 사용을 위한 인터페이스




SLF4J 설정 방법 //sample 프로젝트에 이미 설정돼있음


1. pom.xml 의 slf4j-version을 1.7.25로 설정

2. pom.xml 에 라이브러리 추가

3. src/main/resouces에 있는 logback.xml 파일 작

4. 로그를 수집할 클래스에 변수 선언

5. 로그를 수집할 method에서 로그 수집 명령어 호출



1. pom.xml 의 slf4j-version을 1.7.25로 설정


1
2
3
4
5
        <java-version>1.8</java-version>
        <!-- 2019년 1월 현재 최신 버전 5.1.4, 에러가 날 경우 호환성을 위해 버전을 내려야 함 -->
        <org.springframework-version>5.1.4.RELEASE</org.springframework-version>
        <org.aspectj-version>1.9.2</org.aspectj-version>
        <org.slf4j-version>1.7.25</org.slf4j-version>
cs



2. pom.xml 에 라이브러리 추가


http://mvnrepository.com (메이븐 저장소 서버)


메이븐 저장소 서버에서 SLR4J 코드 찾아서 pom.xml에 추가한다 (sample파일에는 이미 있으므로 추가할 필요 X)


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
        <!-- Logging -->
        <!-- logback 로깅 관련 -->
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.3</version>
        </dependency>
 
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>${org.slf4j-version}</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>jcl-over-slf4j</artifactId>
            <version>${org.slf4j-version}</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>${org.slf4j-version}</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>  
            <exclusions>
                <exclusion>
                    <groupId>javax.mail</groupId>
                    <artifactId>mail</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>javax.jms</groupId>
                    <artifactId>jms</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>com.sun.jdmk</groupId>
                    <artifactId>jmxtools</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>com.sun.jmx</groupId>
                    <artifactId>jmxri</artifactId>
                </exclusion>
            </exclusions>
            <scope>runtime</scope>
        </dependency>
cs




3. src/main/resouces에 있는 logback.xml 파일 작성 // sample 프로젝트에 이미 작성돼있다.


logback.xml : 로그를 어떻게 수집할건지 설정돼있다. 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <!-- log4jdbc-log4j2 -->
    <logger name="jdbc.sqlonly"        level="DEBUG"/>
    <logger name="jdbc.sqltiming"      level="INFO"/>
    <logger name="jdbc.audit"          level="WARN"/>
    <logger name="jdbc.resultset"      level="ERROR"/>
    <logger name="jdbc.resultsettable" level="ERROR"/>
    <logger name="jdbc.connection"     level="INFO"/>
    
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <layout class="ch.qos.logback.classic.PatternLayout">
            <pattern>%d{HH:mm:ss.SSS} [%thread] %-4level [%logger.%method:%line]-
                %msg%n</pattern>
        </layout>
    </appender>
 
    <appender name="LOGFILE"
        class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>/WEB-INF/logback.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>logback.%d{yyyy-MM-dd}.log</fileNamePattern>
            <!-- 30일 지난 파일은 삭제한다. -->
            <maxHistory>30</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-4level [%logger.%method:%line]
                - %msg %n</pattern>
        </encoder>
    </appender>
 
    <!-- 로그의 레벨( 지정된 로그 레벨 이상만 수집 ) : DEBUG < INFO < WARN < ERROR < FATAL -->
    <logger name="myweb" additivity="false">
        <level value="INFO" />
        <appender-ref ref="LOGFILE" />
        <appender-ref ref="CONSOLE" />
    </logger>
 
    <root>
        <level value="INFO" />
        <appender-ref ref="CONSOLE" />
    </root>
 
</configuration>
 
cs


4. 로그를 수집할 클래스에 변수 선언


1
2
3
4
5
@Controller
public class HomeController {
    
    private static final Logger logger = LoggerFactory.getLogger(HomeController.class);
    
cs


private : 외부엣 로그를 가로채지 못하도록 보호


static final : 로그 내용은 바뀌지 않으므로 상수와 같이 설정


private static final Logger logger = LoggerFactory.getLogger( 로그를 수집하는 클래스 이름 )


: HomeController 클래스의 로그를 수집하겠다는 의미


5. 로그를 수집할 메서드에서 로그 수집 명령어 호출


logger.info("로그 타이틀", 출력할 값);


1
2
3
@RequestMapping(value = "/", method = RequestMethod.GET)
    public String home(Locale locale, Model model) {
        logger.info("Welcome home! The client locale is {}.", locale);
cs


로그의 level // 로그에 출력, 저장하는 level


1. Debug : Debug, Info, Warn, Error 포함 // logger.debug

2. Info : Info, Warn, Error 포함        // logger.info

3. Warn : Warn, Error 포함       // logger.warn

4. Error : Error만 포함       // logger.error




데이터베이스 연결 설정 및 테스트


1) 오라클 테이블 스페이스 생성


cmd(관리자권한으로 실행)에서 작업


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
Microsoft Windows [Version 10.0.17134.765]
(c) 2018 Microsoft Corporation. All rights reserved.
 
//관리자 계정으로 접속
 
C:\WINDOWS\system32>sqlplus
 
SQL*Plus: Release 11.2.0.2.0 Production on 화 5월 28 16:08:34 2019
 
Copyright (c) 19822014, Oracle.  All rights reserved.
 
Enter user-name: system
Enter password: //123456
 
 
//오라클 12c버전의 경우에는 11g와 호환하기 위해 alter session set "_ORACLE_SCRIPT"=true; 입력
//사용중인 버전은 11.2.0.2.0 이기때문에 할 필요 X
 
Connected to:
Oracle Database 11g Express Edition Release 11.2.0.2.0 - 64bit Production
 
//테이블 스페이스 생성
 
SQL> create tablespace spring
  2  datafile 'e:/spring.dbf' size 50m // 복붙하지 말고 경로 제대로 입력하기!! d드라이브면 d:/로
  3  autoextend on
  4  next 10m
  5  maxsize unlimited;
 
Tablespace created.
 
//사용자 계정 만들기
//user name : spring / password : 123456
// 디폴트 테이블스페이스는 위에서 만든 spring
 
SQL> create user spring identified by 123456
  2  default tablespace spring;
 
User created.
 
// 사용 권한 부여
// 접속, 리소스 사용, 관리 권한 
 
SQL> grant connect,resource,dba to spring;
 
Grant succeeded.
 
SQL>
cs



생성한 사용자 계정(spring)으로 접속

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 
SQL> exit;
Disconnected from Oracle Database 11g Express Edition Release 11.2.0.2.0 - 64bit Production
 
C:\WINDOWS\system32>sqlplus spring/123456
 
SQL*Plus: Release 11.2.0.2.0 Production on 화 5월 28 16:20:34 2019
 
Copyright (c) 1982, 2014, Oracle.  All rights reserved.
 
 
Connected to:
Oracle Database 11g Express Edition Release 11.2.0.2.0 - 64bit Production
 
SQL>
cs




sql Developer에서도 테스트



테스트(T), 저장(S), 접속(O)



데이터베이스 연결을 테스트하기 위한 테스트 케이스 작성


@Test 어노테이션 코드에서 에러가 발생할 경우 Add JUnit 4 library to the build path를 클릭하여 라이브러리를 추가해야함

//앞서 언급한 테스트 자동화 기능 라이브러리 JUnit


클래스 이름 + Test 클래스는 해당 클래스를 테스트하는 클래스



▷src/main/java 

▷src/main/resources

▶src/test/java >  com.example.spring01 패키지에 클래스 생성


OracleConnectionTest.java 생성 후


▷src/main/java > HomeController.java에서 우클릭 > New > JUnit Test Case




자동으로 해당 클래스 이름에 Test가 붙은 이름으로 설정됨



해당 클래스의 어떤 메서드를 테스트 할건지 선택




생성된 Test 클래스는 src/test/java에 위치해있다.


src/test/java>

HomeControllerTest.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.example.spring01;
 
import static org.junit.Assert.*;
 
import org.junit.Test;
 
public class HomeControllerTest {
 
    @Test
    public void testHome() {
        fail("Not yet implemented");
    }
 
}
cs



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.example.spring01;
 
import static org.junit.Assert.*;
 
import org.junit.Test;
 
public class HomeControllerTest {
 
    @Test
    public void testHome() {
        System.out.println("home test");
        //메인메서드도 없고 원래 실행이 안되는데
        //@Test 어노테이션이 불어있으면
        //JUnit 프로그램(테스트 자동화 툴. 이클립스에 내장돼있음)이
        //메서드 테스트를 실행시킴
    }
 
}
 
cs



JUnit Test 로 실행





Runs : 1/1 

메서드 한 개 테스트해서 한 개 성공



================================정리 제대로 안됨================================



메이븐 저장소에는 무료소스만 올라와있는데 오라클은 유료소스이기 때문에 거의 안올라와있다.

spring01/pom.xml에 <repositories>를 메이븐 저장소 말고 하나 더 추가해준다.


간혹 JUnit이 import도 되어있는데 @Test 어노테이션이 읽히지 않으면 


프로젝트 properties에서 Add Library > JUnit > JUnit4(현재 쓰고있는 버전 선택)


//try ~ with (자바 버전 1.7부터 지원)


//자동 close()기능 있는 try catch 구문 //AutoClosable 인터페이스 구현하는 클래스여야한다.


일반적으로 (보안을 위해) 접속 정보는 별도의 파일에 데이터베이스 연결 정보를 넣고 그 파일을 사용하여 접속하는 식


(이어서..)



new를 통해 객체를 생성하지 않아도 xml 태그로 아래와같이표현하면 스프링프레임워크가 알아서 객체를 생성해준다.


1
2
3
4
5
6
7
8
9
10
    <bean id="dataSource"
        class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <!-- 드라이버 클래스 이름이 변경됨 -->
        <property name="driverClassName" value="net.sf.log4jdbc.sql.jdbcapi.DriverSpy"></property>
        <!-- 연결문자열에 log4jdbc가 추가됨 -->
        <property name="url"
            value="jdbc:log4jdbc:oracle:thin:@localhost:1521:xe" />
        <property name="username" value="hr" />
        <property name="password" value="hr" />
    </bean>
cs



mybatis 관련 bean


SqlSessionTemplate : SqlSession 객체 생성


SqlSessionFactoryBean : SqlSessionTemplate 객체 생성


DriverManagerDataSource : DB연동 클래스


main/test/java >

Mybatis.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
package com.example.spring01;
 
import javax.inject.Inject;
 
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
 
// JUnit 4.0으로 현재 클래스를 실행시킴 
// @Test로만 하는게 아니었나?
// 클래스 상단에 RunWith 어노테이션으로 테스트 클래스임을 명시해두고 테스트할 메서드 위에만 @Test 
@RunWith(SpringJUnit4ClassRunner.class)
 
// mybatis에서 참조하는 설정파일의 위치를 알려줌 
//DB설정파일은 root-context.xml에 위치
@ContextConfiguration(locations = { 
        "file:src/main/webapp/WEB-INF/spring/root-context.xml" })
 
public class MybatisTest {
 
    // 로깅 처리를 위한 코드
    private static final Logger logger = 
            LoggerFactory.getLogger(MybatisTest.class);
 
    //@Autowired (자동연결) //@inject(주입) 와 동일한 기능을 하는 어노테이션
    @Inject // 의존관계 주입(스프링에서 이미 만든 객체를 생성하여 전달)
    //SqlSessionFactory 객체를 만드는 코드는 
    //이미 root-context.xml에 태그형태로 먼저 생성돼있다
    //@inject로 끌어다 쓰는것
    private SqlSessionFactory sqlFactory;
 
    // JUnit이 테스트하는 코드
    @Test
    public void testFactory() {
        // System.out.println("sqlFactory:" + sqlFactory);
        logger.info("sqlFactory:" + sqlFactory);
    }
 
    @Test
    public void testSession() {
        // mybatis 실행을 위한 SqlSession 객체 생성
        //try-with문이라 자동 close()
        try (SqlSession sqlSession = sqlFactory.openSession()) {
            // System.out.println("sqlSession:" + sqlSession);
            // System.out.println("mybatis 연결 성공");
            logger.info("sqlSession:" + sqlSession);
            logger.info("mybatis 연결 성공");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
 
cs