반응형

1. 개요

 quartz 를 사용하여 1초마다 로그 클래스를 실행시키고, 발생하는 로그를 1분마다 Rolling 하여 파일로 남겨보자!


2. 환경

 1) maven

 2) JDK 1.8

 3) Tomcat 8.0


3. 준비

 3.1) Maven 라이브러리 추가

  스프링 라이브러리와 quartz 라이브러리를 추가해주자

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
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.2.8.RELEASE</version>
    </dependency>
    
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
        <version>5.2.8.RELEASE</version>
    </dependency>
    
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>5.2.8.RELEASE</version>
    </dependency>
    
    <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
    <!-- dispatcherServlet 지원 -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>5.2.8.RELEASE</version>
    </dependency>
        
    <!-- https://mvnrepository.com/artifact/org.quartz-scheduler/quartz -->
    <dependency>
        <groupId>org.quartz-scheduler</groupId>
        <artifactId>quartz</artifactId>
        <version>2.3.0</version>
    </dependency>
cs

 

 3.2) web.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
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
  
      <!-- Controller가 공유하는 Bean들을 포함하는 Spring Container를 생성한다. 
             공통 설정파일은 여기에 생성한다. 즉 quartz 또한 이곳에 생성하는 것이 좋다.
      -->
      
      <context-param>
          <param-name>contextConfigLocation</param-name>
          <param-value>
              /WEB-INF/spring/quartz-context.xml
          </param-value>
      </context-param>
      
      <listener>
          <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
      </listener>
      
      
     <filter>
        <filter-name>encodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    
    <!-- /의 형식으로 시작하는 url에 대하여 UTF-8로 인코딩 -->
    <filter-mapping>
        <filter-name>encodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
 
</web-app>
cs

 contextConfigLocation을 /WEB-INF/spring/quartz-context.xml 로 설정하고, UTF-8 인코딩 설정한다(인코딩 부분은 딱히 필요없지만 넣었다.)

 

 3.3) quartz-context.xml 파일 생성

 WEB-INF에 spring 폴더를 생성하고 내부에 quartz-context.xml 파일을 생성하자.

요로코롬.

이제 기본적인 준비가 끝났다. 실제 동작을 위한 코드를 삽입하자.


4. 클래스 생성 및 코딩

 - TestJob.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package quartz;
 
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
 
public class TestJob implements Job{
    
    private Logger logger = LogManager.getLogger(TestJob.class);
    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        // TODO Auto-generated method stub
        logger.debug("this is log and for you");
        logger.trace("this is log and for you");
        logger.info("this is log and for you");
        logger.warn("this is log and for you");
        logger.error("this is log and for you");
    }
}
 
cs

quartz를 적용시키려면 반드시 Job 인터페이스를 상속받아야 한다.

그리고 execute에 실행시킬 로직을 삽입한다.

보는것과 같이 log를 level 별로 찍고있다.

 

 - CronTrigger.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
package quartz;
 
import static org.quartz.CronScheduleBuilder.cronSchedule;
import static org.quartz.JobBuilder.newJob;
import static org.quartz.TriggerBuilder.newTrigger;
 
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerFactory;
import org.quartz.Trigger;
import org.quartz.impl.StdSchedulerFactory;
 
public class CronTrigger {
    
    public CronTrigger() {
        SchedulerFactory schedulerFactory = new StdSchedulerFactory();
        try {
            Scheduler scheduler = schedulerFactory.getScheduler();
            
            JobDetail job = newJob(TestJob.class)
                    .withIdentity("jobName""jobGroup")
                    .build();
            
            Trigger trigger = newTrigger()
                    .withIdentity("triggerName1""triggerGroup1")
                    .withSchedule(cronSchedule("0/1 * * * * ?"))
                    .build();
 
            scheduler.scheduleJob(job, trigger);
            
            scheduler.start();
        }catch(Exception e){
            System.out.println(e.getMessage());
        }
        
    }
}
cs

 

JobDetail 에는 스케줄링 하려는 클래스 정보를, Trigger에는 cron 설정을 통해 스케줄링 시간을 설정한다.

* "0/1 * * * * ?" : 1초마다 실행

 

29번 줄을 통해 스케줄러 잡에 job, trigger를 등록시키고, 31번줄에서 start 시킨다.

결과적으로 1초마다 TestJob의 execute 메서드가 실행된다.


5. quartz-context

 앞서 생성한 quartz-context 설정을 통해 CronTrigger 객체를 bean으로 등록하도록 한다.

 bean으로 등록하는 과정에서 기본생성자인 CronTrigger()를 호출하고, 이 생성자를 통해 설정이 세팅 된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:beans="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">
 
    <!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
    
    <beans:bean id = "cronTrigger" class = "quartz.CronTrigger"/>
    
</beans:beans>
cs

quartz.CronTrigger 객체를 bean으로 등록한다.

 

그 후 서버 tomcat 서버를 실행시키면 아래와 같은 라이프 사이클을 통해 quartz가 시작된다!

 

web.xml load -> quartz-context load -> CronTrigger bean 객체 생성 -> 기본생성자 호출 -> quartz 세팅 및 start!

 

실행 결과 아래와 같은 화면이 출력된다면 quartz 구현에 성공한 것이다.

console 로그

 

추가적으로! 앞의 게시글에서 설정했던 Rolling 파일을 확인해보자.

생성된 Rolling 폴더 및 log 파일
Rolling 파일

매 분마다 폴더가 생성되고, 그 시간동안 쌓였던 로그데이터가 해당 폴더로 들어가 zip 파일로 남게되는 것을 확인할 수 있을 것이다!

 

만약 이를 1일단위로 설정한다면 1일마다 쌓인 로그들이 압축파일 형태로 저장되기 때문에 로그로 인한 저장공간 사용량을 줄일 수 있고, 필요할 때마다 해당 일자의 로그를 살펴볼 수 있기 때문에 로그 관리의 효율성이 높아진다!

 

 

------끄읕------

반응형
반응형

1. 개요

 로그는 시스템의 오류 파악이나 로직 분석을 위해 꼭 필요하다.

 실무를 접하면서 로그가 얼마나 중요한지를 많이 느끼고 있기 때문에 로그 개념을 다시 정리해보고자 글을 쓴다.

 그리고! 그냥 남기면 기억에 오래 남지 않으므로, 좀 특이한? 방식으로 로그를 남겨보았다.


2. 환경

  1) maven

  2) JDK 1.8

  3) Tomcat 8.0 


3. 준비

 1) Maven 라이브러리 추가

 log4j2 관련 라이브러리는 다음과 같다. pom.xml에 추가해주자!

1
2
3
4
5
6
7
8
9
10
11
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-api</artifactId>
        <version>2.13.0</version>
      </dependency>
      <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-core</artifactId>
        <version>2.13.0</version>
      </dependency>
     </dependencies>
cs

 2) log4j2.xml 파일 생성

 class 경로인 src/main/resources 경로에 log4j2.xml 파일을 생성한다.

log4j2.xml 파일 생성

 이로써 아~주 기본 환경설정이 벌써 끝나버렸다. @_@;


4. console log

 4.1) 필요 패키지, 클래스 생성

  콘솔에 로그를 찍어보자. 일단, 동작에 필요한 패키지와 클래스를 아래와 다음과 같이 생성한다.

 

패키지, 클래스 생성

   - Main, test 패키지 생성

   - test 패키지에 LogTest 클래스 생성

   - Main 패키지에 MainClass 객체를 생성

   - quartz 패키지도 일단 생성 (활용 부분에서 quartz를 사용해 로그를 예정이며, console 로그를 출력할 때는 사용 X)

 

  4.2) log4j2.xml 파일 코드

   console에 로그를 찍기 위해 아래 코드를 삽입한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?xml version="1.0" encoding="UTF-8"?>
 
<configuration status="debug">
 
    <Appenders>
        <!-- 콜솔 -->
        <Console name="console" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{yyyy-MM-dd hh:mm:ss} %5p [%c] %m%n"/>
        </Console>
    </Appenders>
    
    <loggers>
        <root level="debug" additivity="true">
            <AppenderRef ref="console"/>
        </root>
    </loggers>
 
</configuration>
cs

 

 3번 줄의 configuration status 구문은 이 설정파일이 로드될 때 발생하는 로그에 대한 레벨을 설정하는 부분이다.

 말이 어렵지 실행화면을 보면 이해가 갈것이다. 

 

configuration status = "DEBUG"

log4j2.xml 의 내부 설정을 로드하면서 발생하는 DEBUG 이상의 로그들을 출력중이다.

status를 info로 설정하면 아~~~무 로그도 출력되지 않는다.

그 이유는 log4j2.xml 설정파일을 로드할 때의 정보는 내부적으로 DEBUG레벨로 찍고 있기 때문이다.

INFO 레벨은 DEBUG레벨보다 상위의 레벨이기 때문에 로그가 찍히지 않게 된다.

 

그렇다면 log4j2.xml 파일을 로드할 때 문제가 생기도록 코드를 바꾼 후 status를 info로 설정한다면?

내부적으로 error 로그가 발생할 것이고, 이는 info 레벨보다 높기 때문에 로그가 찍힐 것이다.

테스트로 5번줄의 Appenders 태그 명을 Appenderss로 바꾼 후 실행시켰다.

제일 아랫줄의 ERROR test.LogTest 부분이 log4j2.xml 을 로드하면서 생긴에러이다.

configuration status ="info" And Appenders -> Appenderss

 

* configuration 부분을 설명하기 위해 먼저 MainClass와 LogTest를 구현하였다. 현재 MainClass와 LogTest 를 생성만 한 상태에서는 위처럼 테스트가 불가능하다. 이런 설정이구나 라고만 이해하고 넘어가자. 

 

Appenders 태그 안에 실질적인 로그 설정 코드를 삽입한다.

현재 콘솔에 로그를 출력시키기 위해 <Console> 태그 관련 코드를 삽입하고 로그로 찍히는 패턴을 PatternLayout 태그를 통해 설정한다.

%d는 로그 시간에 관한 설정을 나타내는데 괄호 안의 형태로 포멧시킬 수 있다.

%p는 로그 레벨, %c는 로그가 발생한 클래스 경로, %m은 로그 메시지, %n은 개행이다. 

%5p는 로그 레벨이 출력되는 기본 문자열 길이를 5로 설정한다는 의미이다.

WARN 앞에 공백 보이시죠?

 

12번 줄의 loggers 는 설정한 로그 코드를 적용하는 부분이다.

root 태그를 사용하면 현재 시스템에서 발생하는 모든 로그를 찍어낼 수 있고, level을 debug로 설정하여 debug 이상의 로그만 출력되도록 한다. Appender를 이용해서 앞서 설정한 console을 적용시키면, 결과적으로 기동하는 시스템내에서 발생하는 모든 로그 중 debug레벨 이상은 모두 찍히게 된다.

 

4.3) 클래스 파일 코드 작성

 - LogTest.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package test;
 
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
 
 
public class LogTest {
    
    private Logger logger = LogManager.getLogger(LogTest.class);
    
    public void printLog() {
        logger.debug("[debug] log!");
        logger.info("[info] log!");
        logger.warn("[warn] log!");
        logger.error("[error] log!");
    }
}
 
cs

로그 객체를 설정하고, printLog() 메서드에 debug, info, warn, error로그를 출력하는 코드를 삽입한다.

 

 - MainClass.java

1
2
3
4
5
6
7
8
9
10
11
12
13
package Main;
 
import test.LogTest;
 
public class MainClass {
 
    public static void main(String[] args) {
        
        LogTest logTest = new LogTest();
        logTest.printLog();
    }
}
 
cs

앞서 만든 LogTest 객체 생성 후 printLog() 메서드를 호출하는 코드를 삽입한다.

 

이제 MainClass를 실행시켜보자!

이러한 로그가 출력되면 성공!

만약 에러 로그만 출력하고 싶다면 log4j2.xml 의 root level을 error로 설정하면 된다.

 

5. RollingFile log

로그를 파일로 남기는 방법 중 하나로, 날짜, 시간 등에 따라 로그파일을 생성하여 보관하고 싶거나, 로그파일의 용량이 너무 커 압축파일 형태로 로그를 남기고싶다면 이 설정을 사용하면 된다.

 

5.1) log4j2.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
<?xml version="1.0" encoding="UTF-8"?>
 
<configuration status="DEBUG">
 
    <Appenders>
        <!-- 콜솔 -->
        <Console name="console" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{yyyy-MM-dd hh:mm:ss} %5p [%c] %m%n"/>
        </Console>
        
        <!-- 파일  -->
        <RollingFile name ="RollingFile">
            <FileName>C:/log/mylog.txt</FileName>
            <FilePattern>C:/log/%d{yyyy-MM-dd-hh-mm}/mylog.zip</FilePattern>
            <PatternLayout>
                <Pattern>%d{yyyy-MM-dd HH:mm:ss} %5p [%c] %m%n</Pattern>
            </PatternLayout>
            <Policies>
                <TimeBasedTriggeringPolicy interval = "1" modulate = "true"/>
            </Policies>
        </RollingFile>
        
        <RollingFile name ="RollingFileError">
            <FileName>C:/log/mylog_error.txt</FileName>
            <FilePattern>C:/log/%d{yyyy-MM-dd-hh-mm}/mylog_error.zip</FilePattern>
            <PatternLayout>
                <Pattern>%d{yyyy-MM-dd HH:mm:ss} %5p [%c] %m%n</Pattern>
            </PatternLayout>
            <Policies>
                <TimeBasedTriggeringPolicy interval = "1" modulate = "true"/>
            </Policies>
        </RollingFile>
        
    </Appenders>
    
    <loggers>
        <root level="debug" additivity="true">
            <AppenderRef ref="console"/>
            <AppenderRef ref="RollingFile"/>
            <AppenderRef ref="RollingFileError" level = "ERROR"/>
        </root>
    </loggers>
    
</configuration> 
cs

코드가 갑자기 늘어났는데, 천천히 파악해보자.

일단 이 코드의 기능목표는 다음과 같다.

 가) 모든 로그가 찍히는 mylog.txt 파일 생성

 나) 에러 로그만 찍히는 mylog_error.txt 파일 생성

 다) 1분마다 찍힌 로그파일을 압축파일로 저장

 

 5.2) 코드 설명

 RollingFile 태그를 사용해야한다.

 FileName은 로그가 찍히게 될 파일경로,

 FilePattern은 파일이 Rolling 될때, 즉 조건에 의해 파일이 말릴 때의 파일 패턴. >> 날짜폴더/mylog.zip 형태

 Pattern은 찍히는 로그 형태

 TimeBasedTriggeringPolicy는 Rolling 조건을 시간으로 설정하고, interval은 1분 간격으로 Rolling한다는 의미.

 

 * interval은 앞서 설정한 FilePattern에 따라 1분이 될수도, 1시간이 될수도, 1일이 될수도 있다.

%d{yyyy-MM-dd-hh-mm}.log.zip interval = 1  1분마다 롤링
%d{yyyy-MM-dd-hh}.log.zip interval = 1  1시간마다 롤링
%d{yyyy-MM-dd}.log.zip interval = 1  1일마다 롤링

 

일반적으로 1일마다 롤링을 하지만, 로그 파일이 롤링되는 테스트 결과를 내일 확인할 수 없으니.. 1분마다 생성되도록 설정하였다.

 

위와 같이 일반 로그, 에러 로그에 대한 Rolling 로그 설정을 만들고, 

39 ~ 40번 줄처럼 RollingFile, RollingFileError 를 AppenderRef 태그를 통해 실제로 적용시켜보자.

단, RolingFileError는 ERROR 레벨 이상의 로그만 찍혀야 하기 때문에 level을 따로 ERROR로 설정한다.

 

이제 MainClass를 실행 시켰을 때 설정한 경로로 파일이 생성되어 로그가 찍히고 1분마다 zip파일로 남을까??

 

안남는다. 파일은 생성되고 순간의 로그는 파일에 찍히겠지만, 그게끝이야! 로그가 계속 찍히지 않으니까!

 

때문에 날짜 형식으로 폴더 하나가 생성되고, mylog, mylog_error 코드 안에 각각의 로그가 들어가면 성공이다.

 

"그럼 로그를 계속 찍어주려면 어떻게할까?? 반복문 돌려도 된다! while!

하지만 좀 더 의미있게 해보자...! 1초마다 찍히게 하는거야! 반복문을 통해서가 아닌 잡 스케줄러를 이용해서!!"

 

해서 활용편으로 quartz라는 스케줄러를 사용하여 1초마다 로그를 찍도록 해보겠다. @_@;

 

이 부분은 스프링에 대한 조금의 지식을 갖고 있다면 어렵지 않게 구현할 수 있다.

 

다음 글에서 진행하도록 하겠다.

 

 

반응형
반응형
반응형

목차

1. 개요

2. 환경

3. 라이브러리

4. 예제

5. 실행결과


1. 개요

 log4j2 = log lib

 log를 남기는 이유는 여러 가지가 있는데 대표적으로 [에러 추적, 디버깅] 또는 [통계]나 [기록]을 목적으로 해!

 어쨌든간에 어렵지 않은 내용이니 한번 따라 해 보자고~

 So~~~~~~~ Ez.


2. 환경

이클립스 MARS
JDK 1.7
comcat 7 (그저갓)

3. 라이브러리

 이거 다 받아서 프로젝트의 lib폴더에 넣자. 프로젝트를 컴파일하면 lib폴더에 있는 jar파일을 class파일로 만들어 사용하기 때문에 여기다 넣어도 된단다! 예외가 몇 개 있지만 요 녀석들은 해당되지 않아! 어서 다운로드하으렴

log4j-api-2.0.2.jar
0.12MB
log4j-core-2.0.2.jar
0.75MB
log4j-over-slf4j-1.7.7.jar
0.02MB
log4j-slf4j-impl-2.0.2.jar
0.02MB
log4j-web-2.0.2.jar
0.02MB
slf4j-api-1.7.7.jar
0.03MB
slf4j-ext-1.7.7.jar
0.04MB


4. 예제

 다운로드한 파일을 프로젝트 폴더의 lib(경로는 WEB-INF/lib) 폴더에 넣었다면 본격적인 예제를 작성해볼 건데, 그냥 로그를 뿌리는 것보다 뭔가 상황이 주어지면 맛깔날 것 같아서 대충 시나리오를 준비했어.

 ※ 시나리오

  1) 나는 서버 개발자

  2) x초보 서버 개발자

  3) controller가 아닌! Servlet을 이용.

  4) 클라이언트가 Servlet에 설정된 Url로 요청

  5) log출력.

 

웹 프로젝트는 생성했다고 가정하고 post, get 통신을 받는 서블릿 패키지 및 클래스를 만들어보자.

 

  4.1) 서블릿 생성

  File -> New -> Servlet 클릭

  나는 패키지 이름을 one, 클래스 이름을 andTwo로 설정했어.

서블릿 패키지 및 클래스 생성

   4.2) andTwo.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
package one;
 
import java.io.IOException;
 
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
 
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
 
/**
 * Servlet implementation class andTwo
 */
@WebServlet("/andTwo")
public class andTwo extends HttpServlet {
    private static final long serialVersionUID = 1L;
    private Logger logger = LogManager.getLogger(andTwo.class);
    /**
     * Default constructor. 
     */
    public andTwo() {
        // TODO Auto-generated constructor stub
    }
 
    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        response.getWriter().append("Served at: ").append(request.getContextPath());
        logger.error("error message");
        logger.warn("warn message");
        logger.info("info message");
        logger.debug("debug message");
        logger.trace("trace message");
    }
 
    /**
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        response.getWriter().append("Served at: ").append(request.getContextPath());
        logger.error("error message");
        logger.warn("warn message");
        logger.info("info message");
        logger.debug("debug message");
        logger.trace("trace message");
    }
 
}
 
 

코드 설명 대충 하자면 

18번째 줄은 요청 url이야. 그림으로 설명해줄게

포트정보
context path

서버 탭을 자세히 살펴보면 자신의 포트와 contextPath 정보를 확인할 수 있어.

서버를 기동시 키면 http://localhost:port/contextPath 가 루트 url이 되는 거야.

요청 url인 '/andTwo'는 루트 url을 포함한 형태라고 생각해.

정리하면 http://localhost:8080/log/andTwo 경로로 요청이 들어오면 해당 경로와 mapping 된 서블릿에 정의된 코드를 처리한다는 뜻이야.

 

21번째 줄에 logger 객체 LogManger.getLogger() 메서드를 통해 생성해주었어. getLogger의 파라미터 값에 현재 클래스명. class를 넣어줘

 

32번째 줄은 Get방식으로 온 요청에 대한 처리.

 

45번째 줄은 Post방식으로 온 요청에 대한 처리이고, 각각 error, warn, info, debug, trace 로그를 남기게 돼. 이들을 로그 레벨이라고 하고 자세한 건 구글링을 통해 알아보면 좋을 것 같아.

 

간단하게 몇 개만 설명하면

 error는 시스템에 문제를 발생시킬만한 로그정보

 warn는 시스템에 문제가 생기진 않지만 에러를 야기할 수 로그정보

 debug는 디버깅을 위해 남기는 로그정보

 

 상황에 맞게 이 로그들을 사용해야 한다는데.. 나는 아직도 어려워..

 어쨌든 이 서블릿으로 요청이 들어오면 무조건 error ~ tarce까지 로그를 출력하도록 했어.

 이제 log4j2의 설정 파일을 생성해야하는데 생성하기 전에 log4j2의 설정파일 경로를 지정해놓자. 이 작업은 web.xml파일에서 해.

 

 4.3) web.xml 파일 설정

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
  <display-name>log</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
  <context-param>
    <param-name>log4j2ConfigLocation</param-name>
    <param-value>/WEB-INF/log4j2.xml</param-value>
  </context-param>
</web-app>
 

display-name은 프로젝트명.

welcome-file-list는 프로젝트가 컴파일되면 최초로 보이는 파일 list.

만약 WEB-INF에 이 파일이 없다면? 404 에러가 뜰 거야. 하지만 우리는 저런 html 파일이 필요 없기 때문에 만들지 않아도 돼

 

context-param은 서버의 parameter를 설정해주는 부분이야.

log4 jConfigLocation이라는 변수에 /WEB-INF/log4j2.xml이라는 값을 넣었다고 생각하면 편해.

 

log4j2는 기본적으로 로그에 대한 설정 파일인 log4j2.xml이 필요한데 이 녀석의 경로야.

 

(사실 이 부분이 없어도 되는데 이유는 log4j2는 로드가 될때 설정 파일인 log4j2.xml을 classpath: 경로에서 알아서 찾는다고 하네..)

 

이제 log4j2 설정파일 세팅을 해보자.

 

 4.4) log4j2.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
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
    <!-- 로그 출력 방식 -->
    <Appenders>
        <!-- 콘솔 출력 방식 -->
        <Console name="STDOUT" target="SYSTEM_OUT">
            <PatternLayout pattern="%d %-5p [%t] %C{2} (%F:%L) - %m%n" />
        </Console>
        
        <!-- 파일 저장 방식 -->
        <File name="file" fileName="C:/Users/mcnc/Desktop/20191203.log">
              <PatternLayout pattern="%d %-5p [%t] %C{2} (%F:%L) - %m%n"/>
        </File>
    </Appenders>
    
    <Loggers>
        <!-- one 패키지의 'andTwo 클래스의 로그 레벨은 info로 올리고', file로 저장할래 -->
        <!-- additivity는 같은 로그가 있다면 additivity가 설정되어있는 로거에서만 출력하도로 설정하는거야.
        참고로 모든 로거에는 기본 로그가 남는데 아래처럼 따로 설정한 로그 방식을 AppenderRef 해준다면 기본 로그+Append 로그. 총 2개의 로그가 남아.
        기본로그는 최소의 정보만 들어있기때문에 이를 막아야겠지? 로그 자체는 동일하기때문에 additivity를 false로 해 주면 기본로그는 뜨지 않을거야. -->
        <Logger name = "one.andTwo"  level="info" additivity = 'false'>
            <AppenderRef ref="STDOUT"/>
            <AppenderRef ref="file"/>
        </Logger>
    </Loggers>
</Configuration>
 

3번째 줄의 Appenders는 로그 방식에 대한 정의 부분이야.

 

6번째 줄은 Console로 출력하기 위한 설정으로 target="SYSTEM_OUT"으로 설정했어.  name은 이 방식에 대한 이름이야. 맘대로 정해.

 

7번째 줄은 로그 내용에 대한 형식이야. 날짜, 시간, 클래스.. 대충 요런 형식으로 로그 정보가 남는다는 뜻이야. 자세한 건 구글링..

 

11번째 줄부터는 로그를 파일에 저장시키는 방식을 정의한 부분이야.

 

16번째 줄부터는 Appenders에 정의해놓은 로그 방식을 사용하는 부분이야.

 

21번째 줄의 name은 패키지 경로를 포함한 클래스 이름이야. andTwo 클래스에서 발생되는 로그를 콘솔과 파일로 남기겠다는 뜻인데, level이 info로 설정되어 있으니 info레벨 이상의 로그만 남긴다는 의미야.

현재 andTwo 클래스에는 상위부터 error ~ trace까지의 로그를 남긴다고 되어있는데 level속성에 의해 trace와 debug를 제외한 로그만이 console과 파일에 저장되게 되지!

 

이제 서버를 켜고 크롬 창에서 요청 url을 입력해봐. 만약 아래와 같은 화면이 출력된다면 Servlet 호출에 성공한 거고, 콘솔 창, 파일에 로그까지 남는다면 log4j2를 이용한 로그 남기기도 성공한 거야!


5. 실행결과

 

이클립스 콘솔

 

 

파일

 

 

설명이 너무 장황하고 두서없어서 이해하긴 어려울 거야... 공부한다고 생각하고 나 자신과 대화를 한다는 컨셉으로 쓴 거니까 이해해주길..

반응형

+ Recent posts