[SpringBoot] 로깅 처리

1. SpringBoot Logging

스프링부트는 Commons Logging을 사용한다. Java Util Logging, Log4J, Log4J2 and Logback에 대한 기본설정을 제공한다.

2. 로그 출력형태

스프링부트에서 출력하는 기본로그 형태
2014-03-05 10:57:51.112  INFO 45469 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet Engine: Apache Tomcat/7.0.52
2014-03-05 10:57:51.253  INFO 45469 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2014-03-05 10:57:51.253  INFO 45469 --- [ost-startStop-1] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 1358 ms
2014-03-05 10:57:51.698  INFO 45469 --- [ost-startStop-1] o.s.b.c.e.ServletRegistrationBean        : Mapping servlet: 'dispatcherServlet' to [/]
2014-03-05 10:57:51.702  INFO 45469 --- [ost-startStop-1] o.s.b.c.embedded.FilterRegistrationBean  : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]

출력되는 내용은 다음과 같다. * 날짜와 시간: 밀리세컨드단위로 되어 정렬가능 * 로그레벨: ERROR,WARN, INFO, DEBUG or TRACE * 프로세스ID * ---: 를 통해서 실제 로그 메시지와 구분 * 스레드 네임 * 로거 네임: 로그가 찍히는 위치 * 로그 메시지


로그백Logback에서는 FATAL 레벨이 없다(ERROR로 매핑됨)

3. logback.xml 설정

스프링부트에서는 클래스패스classpath 상에서 루트에 logback.xml이 존재하면 해당설정파일을 로깅설정에 적용한다. 그래서 스프링부트에서는 logback-spring.xml으로 설정하는 것을 권장한다. 이렇게 해두고 설정파일에서 logging.config: classpath:logback-spring.xml과 같은 형태로 설정하면 로그설정을 추가등록한다.

스프링부트에서 생성하는 로그 설정은 대략 다음과 같다.

스프링 환경시스템 속성설명
logging.exception-conversion-wordLOG_EXCEPTION_CONVERSION_WORD로깅 예외발생시 사용할 관례적인 단어
logging.fileLOG_FILE정의되어 있다면 기본로그 설정에 사용됨
logging.pathLOG_PATH정의되어 있다면 기본로그 설정에 사용됨
logging.pattern.consoleCONSOLE_LOG_PATTERN콘솔에 출력되는 로그 패턴(stdout). (JDK 로거는 지원하지 않음)
logging.pattern.fileFILE_LOG_PATTERN파일에 사용될 로그 패턴(LOG_FILE 활성화된 경우). (JDK 로거는 지원하지 않음)
logging.pattern.levelLOG_LEVEL_PATTERN출력 로그레벨 형태 사용(기본%5p). (logging.pattern.level형태는 로그백에서만 지원)
PIDPID현재 프로세스 ID(OS 환경 변수로 정의되지 않은 경우에는 발견)

4. 로그백Logback 확장

스프링부트에서는 logback-spring.xml을 설정하길 권장한다. logback.xml로 설정하면 스프링부트가 설정하기 전에 로그백 관련한 설정을 하기 때문에 제어할 수가 없게 된다.

5. 스프링부트의 로그 설정을 유지하면서 로그백을 통해서 일일 로그파일 남기기

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<include resource="org/springframework/boot/logging/logback/base.xml"/>
 
<appender name="dailyRollingFileAppender"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<prudent>true</prudent>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>applicatoin.%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>30</maxHistory>
</rollingPolicy>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>INFO</level>
</filter>
 
<encoder>
<pattern>%d{yyyy:MM:dd HH:mm:ss.SSS} %-5level --- [%thread] %logger{35} : %msg %n</pattern>
</encoder>
</appender>
 
<logger name="org.springframework.web" level="INFO"/>
<logger name="org.thymeleaf" level="INFO"/>
<logger name="org.hibernate.SQL" level="INFO"/>
<logger name="org.quartz.core" level="INFO"/>
<logger name="org.h2.server.web" level="INFO"/>
 
<root level="INFO">
<appender-ref ref="dailyRollingFileAppender" />
</root>
</configuration>

위의 형태로 logback-spring.xml을 만들어서 ${project}/src/main/resources 에 위치시키고 application.properties 혹은 application.yml에 다음과 같이 설정한다.

  1. 애플리케이션 내 로그레벨 설정

spring.profiles: logging-info
logging:
  file: logs/application.log
  level:
    org.thymeleaf: INFO
    org.springframework.web: INFO
    org.hibernate.SQL: INFO
    org.quartz.core: INFO
    org.h2.server.web: INFO
 
---
spring.profiles: logging-debug
logging:
  file: logs/application.log
  level:
    org.thymeleaf: DEBUG
    org.springframework.web: DEBUG
    org.hibernate.SQL: DEBUG
    org.quartz.core: DEBUG
    org.h2.server.web: DEBUG
 
---
spring.profiles: logging-daily
logging:
  config: classpath:logback-spring.xml

6. 로그파일 실행

$ java -jar application.jar --spring.profiles.active=logging-debug,logging-daily

위의 형태로 실행하면, 실행한 위치에는 logback-spring.xml 설정에 의해 생성된 로그는application.2015-11-03.log 파일이 생성되고, application.yml에 설정한 logging.* 관련한 로그는 logs/application.log이 생성된다.



Spring application development and analysis process


최근 스프링개발환경은 많은 변화가 있었다. 고전적인 XML 설정방식외에도 JavaConfig 방식이 가능해졌고, 기존에 설정의 복잡함을 줄이기 위한 관례적인 설정을 자동으로 제공하는 자동설정Auto-configuration을 제공하는 스프링부트(http://projects.spring.io/spring-boot/) 프로젝트를 기반으로 한 애플리케이션 개발환경이 제공되고 있다.


1. 스프링애플리케이션 개발순서

  1. 스프링애플리케이션 기능설계

  2. 스프링 프로젝트 빌드

  3. web.xml 설정

    1. servlet 3.0+ 이상을 적용하는 경우에는 ServletInitializer를 통해서 web.xml 설정 대체가능

  4. 스프링 애플리케이션 컨텍스트ApplicationContext 설정

    1. application-context.xml(DAO, 서비스 영역)

      1. datasource 설정

      2. AOP 설정

    2. web-application-context.xml(웹 영영)

    3. security-context.xml(웹접근 인증 설정)

      1. URL과 사용자 권한을 기준으로 접근제어

  5. 애플리케이션 컨텍스트 정상설정 테스트

  6. MyBatis 를 사용하느냐, 하이버네이트등의 ORM 을 사용하느냐에 따라 DB 사용방식 달라짐

    1. MyBatis 인 경우에는 Database 에 스키마와 테이블들이 생성되어 있어야 함

      1. Mapper 클래스 및 SQL 을 설정해줘야 함

      2. iBatis 말고 MyBatis 사용을 권장: iBatis는 개발지원이 끝난지 꽤 되었음

      3. MyBatis와 관련된 부분은 MyBatis를 참고

    2. ORM인 경우에는 개발단계에서 ddl-auto 의 설정을 통해서 테이블 및 컬럼의 자동생성처리가 가능

      1. Spring Data JPA를 사용할 경우 기본적인 CRUD 처리를 JPARepository를 통해서 처리가 가능함

      2. 이와 관련된 자세한 내용은 자바 ORM 표준 JPA 프로그래밍 을 살펴보기

  7. 이후 애플리케이션의 패키지를 구성하고 기능별로 계층을 나눠 개발

io.honeymon.spring
  configuration
    - WebConfiguration.java
  domain
    - Member.java
    - Project.java
  repository
    - MemberRepository.java
    - ProjectRepository.java
  service
    - MemberService.java
    - DefaultMemberService.java
    - ProjectService.java
    - DefaultMProjectService.java
  web
    - MemberController.java
    - ProjectController.java
  common
    - FileUtils.java
    - DateUtils.java

위와 같은 형태로 기능별로 계층을 나눠 개발하기도 하고

io.honeymon.spring
  configuration
    - WebConfiguration.java
  member
    - Member.java
    - MemberRepository.java
    - MemberService.java
    - DefaultMemberService.java
    - MemberController.java
  project
    - Project.java
    - ProjectRepository.java
    - ProjectService.java
    - DefaultProjectService.java
    - ProjectController.java

와 같은 기능별 패키지로 나눠 개발하는 방식도 있습니다. 저도 최근에 이 방식으로 변환을 시도하고 있다.

위와 같은 형태로 개발을 진행합니다.

  1. 애플리케이션 개발에 있어서 MyBatis 보다는 JPA 사용을 선호함. MyBatis 는 4년전 이후로 사용해본 경험없음

  2. ORM을 기반으로 개발하면 엔티티 객체를 기반으로 해서 DB와의 매핑처리도 쉽고 기능구현도 쉬움.


스프링부트를 기반으로 개발하게 될 경우, 스프링과 관련된 설정의 부담감이 줄고 개발에 필요한 라이브러리들을 `Starter-POM`s 를 통해서 쉽게 처리가 가능하기 때문에 스프링 프레임워크에 대한 이해가 어느정도 있는 개발자에게는 스프링부트 사용을 권함

1.1. 화면개발

  1. 기본설정이 완료된 후에는 개발하는 화면에 따라 기능 구현 시작

  2. JSP 페이지 등의 템플릿 파일 작성

  3. Controller ModelAndView 에 템플릿 페이지 등록

    1. ajax 를 활용할 경우 화면처리를 담당할 컨트롤러와 데이터를 JSON으로 처리해줄 컨트롤러를 분리하면 좋음

    2. Spring 4.0 이후 @RestController 애노테이션이 생겨서 요청한 컨텐트타입으로 반환해주는 컨트롤러를 만들 수 있음

  4. 화면에 필요한 데이터를 담을 데이터들을 ModelAndView 혹은 템플릿엔진을 사용하는 경우에는 Model에 담아주면 ViewResolver에 의해서 처리됨

  5. 화면에 필요한 데이터에 따라서 Controller에서 Model에 담아주는 데이터가 달라지고 이는Service의 구현이 필요해짐

    1. 화면데이터에 따라 데이터, 서비스 가 달라짐

2. 스프링 애플리케이션 분석

2.1. 고전적인 XML 설정을 기반으로 한 경우

  1. web.xml 찾아서 애플리케이션 필터 설정들을 확인

  2. application-context.xml 혹은 *-context.xml 파일 분석

    1. application-context.xml: 파일은 보통 src/main/resource/META-INF에 위치

    2. web-application-context.xml: 파일은 보통 WEB-INF 에 위치

    3. 프로젝트를 설정한 사람에 따라 파일명이나 위치는 다를 수 있으므로 파일찾기를 통해서 찾아보기 바람

  3. DB 설정 확인

  4. 애플리케이션 패키지 구성 확인

  5. 애플리케이션을 구동하면서 찍히는 로그를 통해서 동작순서 확인

  6. 관련한 설정 확인

2.2. JavaConfig 인 경우

  1. @Configuration 애노테이션을 사용한 클래스 탐색

  2. 나머지 항목들은 고전적인 XML 설정을 기반으로 한 경우 와 동일

2.3. STS를 이용한 경우


STS: Spring Tool Suite http://spring.io/tools/sts
  1. spring explorer view 를 활용해서 각 설정빈을 확인 가능함

3. 참고자료


텍스트 기반으로 작성된 문서를 asciidoc 이라고 하는 도구를 이용하여 다양한 형태의 문서로 변환할 수 있는 도구가 있다.

간단간단하게 작성해서 볼 요량이면 마크다운으로도 충분하지만,

스프링부트 레퍼런스문서를 아무런 생각없이 마크다운으로 번역하다보니 스프링부트 레퍼런스문서와 차이가 너무 컸다.

초반에 틀도 제대로 잡지 않고 주먹구구식으로 시작하다보니 아쉬움이 많다. 목차와 섹션 연결도 제대로 안되고...

그래서 다음 스프링부트 1.3.0. 번역은 asciidoc  을 기반으로 하여 각 파트를 나눠서 진행하려고 한다.

스프링에서는 진즉에 asciidoc을 이용해서 레퍼런스문서를 생성해주고 있다.

https://github.com/spring-projects/spring-boot/tree/master/spring-boot-docs

보면서 진즉에 이렇게 했어야 했어! 라는 생각을 하게 된다.


ATOM 에서 asciidoc 형식 문서작성을 도와주지 않을까하고 찾아보니 아니나 다를까 asciidoc-preview라고 하는 패키지가 존재했다. 이 패키지를 이용해서 작성하려고보니 한글...이 안나온다.

정확하게는 사용하는 폰트가 영문폰트니 한글이 지원안된다.

그래서 한글을 나오도록 만들만드는 작업을 했다.

PREFERENCE - PACKAGE - asciidoc-preview - View Code

ATOM  홈디렉토리에 bundle 에 'nanum' 이라는 디렉토리를 생성하고 그 안에 파일들을 복사해 넣었다.

USER_HOME/.atom/packages/asciidoc-preview/bundle/nanum

asciidoc-preview.less 를 열고 아래 폰트항목을 추가했다.

// Nanum 
@font-face {
  font-family: "NanumBarunGothic";
  font-weight: normal;
  font-style: normal;
  src: url("@{nanum-font-path}/NanumBarunGothic.ttf");
}
@font-face {
  font-family: "NanumBarunGothic";
  font-weight: normal;
  font-style: bold;
  src: url("@{nanum-font-path}/NanumBarunGothicBold.ttf");
}
@font-face {
  font-family: "D2Coding";
  font-weight: normal;
  font-style: normal;
  src: url("@{nanum-font-path}/D2Coding.ttc");
}

그리고는 아래 폰트적용 코드들에다가 죄다 위에서 생성한 폰트를 넣어줬다.

pre, code, samp 항목들을 찾아서...

code,
kbd,
pre,
samp {
  font-family: D2Coding, monospace;
  font-size: 1em;
}

그리고나서 리로드Reload 를 수행하면 다음처럼 쫘안~

이제 asciidoc 의 문법을 익혀서 잘 사용하면 되겠다.

아참... 내가 마크다운을 사용하지 않게 된 것이...

ㅡ_-) atom 의 마크다운 프리뷰에서 소스코드 복사가 본문과 함께 되지 않아서다.


'Tools' 카테고리의 다른 글

[log] 싱크패드 울트라나브(블루투스)  (3) 2018.10.25
ZSH - The Z Shell  (0) 2016.05.14


지난 10월 24일(토요일), 을지로 페럼홀에서 발표를 했습니다.


세미나 컨셉은

‘Modern java web application with spring’
시대적 흐름에 맞추어 스프링진영에서도 웹과 관련된 다양한 기술들을 선보이는 기술들을 살펴볼 수 있는 자리.

  • Spring 4.x web application
  • Javascript templating
  • Spring REST docs
  • Vaddin



발표영상은 한달쯔음 뒤에…

발표하면서 긴장해가지고는 말이 빨라져서 40분만에 발표내용 전달 모두 끝나고...

5분간 주저리주저리 이야기 하고...

이야기 하려고 했던 건 빼먹고...

발표는 쉬운게 아니라는 걸 새삼 느꼈습니다. ㅋㅋ

* 도서정보: http://www.yes24.com/24/Goods/19040233?Acode=101

내가 JPA를 처음 접한 것은 대략 4년전, apache의 OpenJPA(http://openjpa.apache.org/) 였다.

그전까지는 iBatis를 조금 사용했을 무렵이다. 지금도 쿼리에는 취약하지만, 그 당시에는 프로젝트에서 사용하는 기술을 따라잡는데도 버거웠던 시절이다.

프로젝트 매니저께서 스트럿츠2, 오픈JPA를 기반으로 프로젝트를 진행하기로 하면서 나의 지옥은 시작되었다.
스프링 3.X를 사용하다가 스트럿츠2+오픈JPA를 쓸려니 어디서부터 어떻게 시작해야할지 막막한 상황에서 초강력의 학습강제력까지 쏟아지면서 난감하기만 했다.
그나마 쿼리 압박을 당하지 않았기에 다행이랄까??

우여곡절 끝에... 프로젝트 두 개를 동시에 마무리 짓고 회사에서 진행하는 새로운 솔루션 개발프로젝트에 합류했다.
다행히(?!) 그 프로젝트에서는 스프링+스프링데이타 JPA+QueryDSL을 사용하고 있었다.
우선은 하이버네이트 프로그래밍(http://m.yes24.com/Goods/Detail/3892382) 책을 통해서 개념을 다잡아가기를 시작했다.

하지만.... 여전히 배워야할 게 많다.

그 후로, 나는 쿼리를 직접적으로 다루는 경우가 거의 없었다. 내가 했던 대부분의 작업이 웹기반의 CRUD작업이었고, 엔티티 객체들을 조작하는 것으로 대부분의 데이터 관련 작업들을 처리하는데 무리가 없었기 때문이었다.

각 개발자들의 로컬에서는,
- H2Database
기능테스트는 개발서버의
- MariaDB
그 밖의 상황에 따라 적절하게 교체할 수 있기 때문이다.

지금도 개발할 때는 스프링의 'Profile' 기능을 이용해서 개발하고 있다.
그 간단한 예제로는...
https://github.com/ihoneymon/honeymon-blog

요즘은 테스트할 때 DB 저장과 관련된 부분은 목객체를 사용하기보다는 h2Database를 인메모리in-memory 로 설정하여 구동시키는 편이다. ㅡ_-);; 목객체 만들기 귀찮...

2년 전에 깃헙에 만들어둔 메이븐으로 만든 프로젝트도 보면 Spring Data JPA가 붙어 있다.


이는 하이버네이트에서 제공하는 방언Dialect 덕분이라고 할 수 있다. 각 DB에 맞춰 처리해줬기 때문에 초반에 환경설정만 하고나면 이후에는 개발에만 집중하면 됐다.

그렇게 주먹구구식으로 JPA 기술을 체득하며 사용하던 내게 좋은 참고서가 생겼다.

김영한님이 2년간 심혈을 기울여 세상에 선보인, 이 책!

바로 예약구매를 걸어놓고 기다리다가 받자마자 읽어내려갔다.

많은 분들의 검수를 받으며 잘 다듬어진 문장은 술술 읽어내려갈 수 있었다. 3일 만에 쭈욱 읽어내렸다.

그리고 때마침 회사에서 SAP의 e-commerce 솔루션 hybris를 기반으로 프로젝트를 진행하고 있는 것들이 있어 사내에 '책읽기 모임'을 주선한다. 오랜 만에 사내 스터디인 덕분에 회사에서 도서구매비를 지원해주었다.


다른 구현체이기는 하지만, JPA를 공부하면서 사람들이 ORM에 대한 개념을 이해하는데 큰 도움이 되었다. 자신들이 사용하던 기술들에 대한 궁긍증을 해소하는 순간 그 기술들에 대한 이해도가 급상승하는 효과가 있다는 것은 다들 알고 있을 것이다.


대략 한달 반(매주 화요일 역삼 본사에 모였다)이 걸려서 모두 읽어냈다. 모두가 함께 마쳤다는 것이 참 만족스러움을 준다.
읽으면서 줄치고 기억해둬야하는 개념이 정의되어 있는 곳은 태그를 붙여놨다. 언제든지 궁금증이 생기면 찾아볼 수 있도록.


이 책의 저자 영한님이 최근 개인방송도 시작했다.

다음에 기회가 닿으면 쐬주나 한잔 하자고 해야겠다. ㅋㅋㅋ
서울말을 구수한 부산억양으로 구사하는 김영한님이 앞으로도 좋은 책을 내어주길 기대하며.


+ Recent posts