안녕하세요! 오늘은 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
이에요. 여기서 어떤 로그를 어디에, 어떤 형식으로 남길지를 정해줘요. 오늘은 두 가지 로그 방식으로 구성해볼게요:

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

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. TimeBasedRollingPolicy
에 maxHistory
옵션을 추가하면 자동 삭제할 수 있어요. 예: <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
로 넘어가는 이야기도 준비해볼게요. 혹시 궁금한 점 있으시면 댓글로 남겨주세요! 🙂