로그 설정 어렵게 느껴지셨다면, 이 글이 도움이 될 거예요 — Log4j 간단 설정법!

안녕하세요! 오늘은 log4j.xml 파일 설정과 예제 코드까지, Log4j를 프로젝트에 적용하는 법을 정리해봤어요. 저도 처음에는 로그 설정이 왜 이렇게 복잡하지? 싶은 마음이 컸는데요, 막상 차근차근 따라 해보니 생각보다 훨씬 간단하더라고요.

특히 Spring MVC 같은 웹 애플리케이션에서 로그를 제대로 설정해두면 디버깅할 때나 장애 분석할 때 정말 유용하죠. 오늘 알려드릴 방식은 하루 단위로 로그 파일을 분리해서 저장하고, 에러 로그는 리눅스 시스템 로그에도 남기는 방식이에요. 직접 써보니 시스템 자원도 절약되고, 로그 가독성도 확실히 좋아졌어요.

이제 같이 한 단계씩 따라가볼까요?


1. log4j 설정에 필요한 라이브러리 준비하기

먼저, log4j를 제대로 사용하려면 몇 가지 필수 라이브러리가 필요해요. 아래 세 개는 꼭 프로젝트에 추가해줘야 해요:

  • apache-log4j-extras-1.2.17.jar
  • slf4j-api-1.6.1.jar
  • slf4j-log4j12-1.6.1.jar

이 파일들은 메이븐 프로젝트라면 pom.xml에 의존성으로 추가해도 되고, 일반 자바 프로젝트라면 직접 다운로드해서 lib 폴더에 넣고 빌드패스에 추가하면 돼요. 저는 처음에 slf4j가 뭔지 몰라서 헷갈렸는데요, 간단히 말하면 로그 인터페이스라고 생각하시면 돼요. log4j는 실제로 로그를 찍는 역할을 하고요. 둘 다 있어야 제대로 작동해요.


2. log4j.xml 구성 – 로그 파일과 시스템 로그 두 마리 토끼 잡기

log4j 설정의 핵심은 바로 log4j.xml이에요. 여기서 어떤 로그를 어디에, 어떤 형식으로 남길지를 정해줘요. 오늘은 두 가지 로그 방식으로 구성해볼게요:

log4j.xml
  • filelogger: 로그 파일로 저장 (하루 단위로 자동 분리)
  • syslogger: 에러 로그만 리눅스 시스템 로그로 전송
<appender name="filelogger" class="org.apache.log4j.rolling.RollingFileAppender">
    <param name="Encoding" value="UTF-8" />
    <rollingPolicy class="org.apache.log4j.rolling.TimeBasedRollingPolicy">
        <param name="FileNamePattern" value="/opt/test/log/bi_%d{yyyyMMdd}.log" />
    </rollingPolicy>
    <layout class="org.apache.log4j.PatternLayout">
        <param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss.SSS} %p (%F.%L): %m%n" />
    </layout>
</appender>

<appender name="syslogger" class="org.apache.log4j.net.SyslogAppender">
    <param name="Threshold" value="ERROR" />
    <param name="SyslogHost" value="192.168.172.140" />
    <param name="Facility" value="USER" />
    <layout class="org.apache.log4j.PatternLayout">
        <param name="ConversionPattern" value="%p (%F.%L): %m%n" />
    </layout>
</appender>

그리고 이 appender들을 logger에 연결해줘야 하죠:

<logger name="logfile">
    <level value="debug" />
    <appender-ref ref="filelogger" />
    <appender-ref ref="syslogger" />
</logger>

이렇게 설정해두면 로그가 매일 자동으로 새로운 파일로 저장되고, 에러 이상 수준의 로그는 시스템 로그에도 기록돼요. 실제 서버 운영할 때 엄청 유용하더라고요.


3. 로그 포맷 이해하기 – 의미 있는 로그를 위한 포맷팅

log4j에서는 로그 메시지에 다양한 정보를 넣을 수 있어요. 그걸 결정하는 게 바로 ConversionPattern인데요, 자주 쓰는 포맷은 아래와 같아요:

  • %d{yyyy-MM-dd HH:mm:ss.SSS}: 로그 발생 시간
  • %p: 로그 레벨 (DEBUG, INFO, ERROR 등)
  • %F: 로그 호출한 파일 이름
  • %L: 로그 호출한 줄 번호
  • %m: 메시지 내용
  • %n: 줄 바꿈

이걸 조합하면 "2025-06-10 14:20:05.123 ERROR (Test.java:24): Something went wrong" 같은 로그가 찍히게 돼요. 포맷을 잘 조정하면 문제 추적이 훨씬 쉬워지죠. 이 부분은 회사 로그 포맷 규칙에 맞춰서 조금 바꿔도 돼요.


4. Spring MVC에서 log4j 적용 예제 코드

log4j 설정만 해두고 끝내면 안 되겠죠. 실제 코드에서 어떻게 사용하는지까지 살펴볼게요. 아래는 Spring MVC 컨트롤러에서 로그를 사용하는 예제에요:

@Controller
@RequestMapping("/test/*")
public class Test {
    private Logger logger = LoggerFactory.getLogger("logfile");

    @RequestMapping("testDemo")
    public ModelAndView testDemo(String msg) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
        logger.info("This is for log file " + sdf.format(new Date()));
        logger.error("This is for sys log file " + sdf.format(new Date()));
        return new ModelAndView("/index.jsp");
    }
}

여기서 핵심은 LoggerFactory.getLogger("logfile")이에요. 이 "logfile"이라는 이름은 아까 log4j.xml에서 정의한 logger 이름과 똑같아야 해요. 그래야 설정이 매칭돼서 원하는 방식으로 로그가 남아요. 저는 테스트할 때 이걸 rootLogger랑 혼동해서 로그가 안 찍히는 줄 알았거든요… 꼭 정확히 이름 맞춰주세요!


5. 로그가 저장되는 실제 모습

설정을 마치고 코드를 실행하면 로그가 이렇게 나와요:

로그 파일 (/opt/test/log/bi_20250610.log):

2025-06-10 14:22:31.123 INFO (Test.java:24): This is for log file 2025-06-10 14:22:31.123
2025-06-10 14:22:31.124 ERROR (Test.java:25): This is for sys log file 2025-06-10 14:22:31.124
log4j 로그

Linux 시스템 로그 (/var/log/messages 등):

ERROR (Test.java:25): This is for sys log file 2025-06-10 14:22:31.124

로그 파일은 매일 자동으로 생성되고, 에러 로그는 지정한 시스템 로그 호스트로 전송돼요. 서버를 여러 대 운영 중이라면 SyslogHost에 중앙 로그 서버 IP를 넣으면 통합 관리도 가능해요. 회사에서 이 방식 쓰고 있는데, 장애 원인 파악할 때 진짜 편하더라고요.


6. 로그 정책, 왜 중요할까요?

사실 로그를 그냥 System.out.println()으로 찍는 분들도 아직 많아요. 근데 이건 단순 출력일 뿐, 검색도 힘들고 필터링도 안 되잖아요. 반면에 log4j는 로그 레벨별 필터링, 출력 위치 분리, 포맷 커스터마이징 등 모든 게 가능해서 운영 환경에서는 거의 필수에요.

2019년 IBM DeveloperWorks 보고서에 따르면, “체계적인 로그 관리는 장애 분석 시간을 평균 67% 단축시킨다”고 해요. 저도 이전 프로젝트에서 로그를 깔끔하게 정리해두니, 팀원들끼리 이슈 공유할 때도 훨씬 수월했어요.

여러분도 지금부터라도 로그 정책을 제대로 정립해두시면 나중에 정말 큰 도움이 될 거예요.


QnA: log4j 설정 관련 자주 묻는 질문들

Q1. log4j.xml과 log4j.properties 중 어떤 걸 써야 하나요?
A1. 기능적으로 큰 차이는 없지만, XML은 구조화가 잘 되어 있어서 복잡한 설정에 더 유리해요. 대규모 프로젝트에서는 log4j.xml을 추천드려요.

Q2. 로그 파일이 계속 쌓이는데 자동 삭제는 안 되나요?
A2. TimeBasedRollingPolicymaxHistory 옵션을 추가하면 자동 삭제할 수 있어요. 예: <param name="MaxHistory" value="30" />로 30일 보관.

Q3. 로그 레벨을 INFO로 설정했는데 DEBUG 로그도 찍혀요. 왜 그럴까요?
A3. logger마다 개별 설정이 가능하기 때문에, rootLogger가 DEBUG로 되어 있으면 영향받을 수 있어요. 설정 파일을 꼼꼼히 다시 확인해보세요.

Q4. 로그가 아무 데도 안 찍혀요. 어디서부터 확인해야 할까요?
A4. 우선 logger 이름이 log4j.xml과 일치하는지 확인하세요. 다음으로 appender 설정이 누락되었거나, 파일 경로에 권한이 없는 경우도 있어요.

Q5. 로그를 콘솔에도 출력하고 싶은데 가능할까요?
A5. 물론이에요. ConsoleAppender를 추가하면 돼요. 설정 예:

<appender name="console" class="org.apache.log4j.ConsoleAppender">...</appender>

그리고 logger에 <appender-ref ref="console" />를 추가하세요.


마무리하며 – 로그 설정은 ‘습관’이에요

처음엔 log4j 설정이 참 버겁게 느껴졌어요. xml 태그는 왜 이렇게 많고, 라이브러리는 왜 이렇게 복잡한가 싶었죠. 그런데 몇 번 설정하고, 직접 로그를 보면서 문제를 추적해보니… 이게 진짜 보물이라는 걸 알게 됐어요.

로그는 단순한 출력이 아니라 프로젝트의 건강 상태를 기록하는 일기장 같아요. 하루 단위로 잘 분리된 로그, 필요한 정보만 골라보는 포맷, 시스템 로그로 전송되는 에러 알림… 이런 습관이 나중엔 실력 차이를 만드는 거 같더라고요.

혹시 아직 log4j 설정이 어렵게 느껴지신다면, 오늘 알려드린 기본 템플릿부터 한 번 적용해보세요. 아마도 “어? 이거 생각보다 괜찮은데?” 하고 느끼실 거예요.

다음에는 logback이나 log4j2로 넘어가는 이야기도 준비해볼게요. 혹시 궁금한 점 있으시면 댓글로 남겨주세요! 🙂