• [ 배경 ]
    • 중고거래 프로젝트 환경인 Spring-boot 환경에서 로깅을 하기 위한 방법에 대해 고민하였습니다.
    • 구글링 중 로깅 라이브러리인 Log4j2 Logback Log4j slf4j 등의 존재를 알았습니다.
      각각의 특징에 대해 알아보겠습니다.
    • slf4j
      • Logger 추상체로 slf4j는 logback이나 log4j2와 같은 프레임워크의 인터페이스의 역할을 해주기 때문에  로깅 구현체가 바뀌더라도 생각보다 어렵지않게 변경할 수 있습니다. 기능이 너무 단순하여 실제로는 사용할 필요가 없긴합니다. 
    • Log4j Logback Log4j2 순서로 등장했습니다.
      • log4j
        • 콘솔로 출력하는 stdout 외에도 파일 출력도 제공합니다. 
          하지만 2015년에 개발이 중단되었기 때문에 기존 시스템이 아니라면 사용할 이유가 없습니다.
      • logback
        • log4j2 전에 개발된 로깅프로그램으로 log4j에서 향상된 성능과 필터링 옵션을 제공합니다. 
          slf4j
          도 지원합니다. 그리고 자동 리로드도 가능합니다.
      • log4j2
        • logback과 동일하게 자동 리로드 기능과 필터리 기능을 제공합니다. logback과 차이점은 Apache에 따르면 멀티 쓰레드 환경에서 비동기 로거(Async Logger)의 경우 Log4j 1.x 및 Logback보다 처리량이 18배 더 높고 대기 시간이 훨씬 더 짧다. 아래 그래프에서 성능 차이를 확인 해볼수 있다. 그리고 람다 표현식과 사용자 정의 로그 레벨도 지원합니다.

 

https://logging.apache.org/log4j/2.x/performance.html

  • 중고거래 프로젝트는 대용량 트래픽을 처리해야하는 다중서버 환경이어서 멀티 쓰레드 환경에서 처리량이 월등한 Log4j2 로깅 의존성을 사용하기로 정하였습니다.

  • [ 과정 ] 
    • 로깅을 위해 log4j2 의존성을 pom.xml에 추가하였습니다.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
view raw gistfile1.txt hosted with ❤ by GitHub
  • log4j2.xml 파일에 console 및 파일 설정 관련 appender를 추가하였습니다.
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="info" monitorInterval="30">
<Properties>
<Property name="LOG_FORMAT">%d{yyyy-MM-dd HH:mm:ss} %p %m%n</Property>
</Properties>
<Appenders>
<Console name="Console" target="SYSTEM_OUT" follow="true">
<PatternLayout pattern="${LOG_FORMAT}"/>
</Console>
<File name="file" fileName="./logs/file/test.log">
<PatternLayout pattern="%d %5p [%c] %m%n" />
</File>
</Appenders>
<Loggers>
<Root level="info">
<AppenderRef ref="Console"/>
<AppenderRef ref="file" />
</Root>
<logger name="com.market.server" level="trace" additivity="false" >
<AppenderRef ref="file" />
</logger>
</Loggers>
</Configuration>
view raw log4j2.xml hosted with ❤ by GitHub
  • @Log4j2 어노테이션이 있는 UserServiceImpl class 에서 에서 회원가입시 id값이 중복일 경우 log.error("insertMember ERROR! {}", userDTO);
    구문에 의해서 .log 파일에 로그인 insert 관련 error를 기록합니다.
@Service
@Log4j2
public class UserServiceImpl implements UserService {
/**
* 회원 가입 메서드.
*
* @param userDTO 저장할 회원의 정보
* @return - 고객 회원가입 메서드 비밀번호를 암호화하여 세팅한다. MyBatis에서 insert return값은 성공시 1이 리턴된다. return값은 검사하여 null값이면
* true, null이 아닐시 insert에 실패한 것이니 false를 반환한다
*/
@Override
public void register(UserDTO userDTO) {
// id 중복체크
boolean duplIdResult = isDuplicatedId(userDTO.getId());
if (duplIdResult) {
throw new DuplicateIdException("중복된 아이디입니다.");
}
userDTO.setCreatetime(new Date());
userDTO.setPassword(SHA256Util.encryptSHA256(userDTO.getPassword()));
int insertCount = userProfileMapper.register(userDTO);
if (insertCount != 1) {
log.error("insertMember ERROR! {}", userDTO);
throw new RuntimeException(
"insertUser ERROR! 회원가입 메서드를 확인해주세요\n" + "Params : " + userDTO);
}
}
...생략...
}
  • 아래 파일은 Log4j2의 appender 중 file설정에 의해 만들어진 로그입니다.
    실제 로그인 실패시 insert 에러가 있습니다.


  • [ 결과 ]
    • 로깅을 위해 log4j2 의존성을 추가하였습니다.
    • log4j2.xml 파일에 console 및 파일 설정 관련 appender를 추가하였습니다.
    • @Log4j2 를 class에 주입 후 log.info , log.error 파일을 상황에 맞게 추가하였습니다.

  • [ 성과]
    • Log4j2를 이용해 적절한 Exception 내용을 에러 로그 파일로 남김으로써 에러 발생 시 디버깅 시간을 단축하고 유지보 수 비용을 줄였습니다.

 

junshock5/used-market-server

중고거래 프로젝트. Contribute to junshock5/used-market-server development by creating an account on GitHub.

github.com

+ Recent posts