{{위키데이터 속성 추적}}
{{다른 뜻|Log4Shell|자바 로깅 프레임워크|Log4j에 영향을 준 2021년 취약점}}
{{소프트웨어 정보
| 이름 = 아파치 Log4j
| 로고 = Apache Log4j Logo.png
| 개발자 = [[아파치 소프트웨어 재단]]
| released = {{시작 날짜와 나이|2001|01|08}}<ref>{{웹 인용|url=https://logging.apache.org/log4j/1.2/changes-report.html |title=Apache Log4j 1.2 Release History |author=<!--Staff writer(s); no by-line.--> |website=apache.org |publisher=Apache Software Foundation |access-date=2014-09-02}}</ref>
| 최근 버전 = {{wikidata|property|edit|reference|P348}}
| 최근 버전 출시일 = {{시작 날짜와 나이|{{wikidata|qualifier|P348|P577}}}}<ref>{{웹 인용|url=http://logging.apache.org/log4j/2.x/changes-report.html|title=Log4j – Changes - Apache Log4j 2|website=apache.org|publisher=Apache Software Foundation|access-date=2021-12-10|archive-date=2022-04-25|archive-url=https://web.archive.org/web/20220425010026/https://logging.apache.org/log4j/2.x/changes-report.html|url-status=}}</ref>
| 운영체제 = [[크로스 플랫폼]]
| 종류 = [[로깅 도구]]
| programming language = [[자바 (프로그래밍 언어)|자바]]
| 라이선스 = [[아파치 라이선스|아파치 2.0 라이선스]]
| 웹사이트 = {{url|https://logging.apache.org/log4j/2.x/}}
}}

'''Log4j'''는 Ceki Gülcü가 처음 개발한 [[자바 (프로그래밍 언어)|자바]] 기반 [[데이터 로깅|로깅]] 유틸리티이다. [[아파치 소프트웨어 재단]]의 프로젝트 아파치 로깅 서비스(Apache Logging Services)의 일부이다. 또, Log4j는 여러 자바 로깅 프레임워크들 가운데 하나이다. 최종 사용자가 제품의 문제나 정보를 식별하기 위해, 그리고 소프트웨어 개발자가 프로그램을 개발하는 도중에 [[디버깅]] 등을 위해 타임스탬프 등 정해진 양식에 맞추어 화면 상이나 파일로 로그를 남길 목적으로 사용된다.

그 뒤로 Gülcü는 Log4j의 뒤를 잇는 유틸리티를 제공할 목적으로 [[SLF4J]]와 로그백(Logback)<ref>{{웹 인용|url=http://logback.qos.ch/ |title=Logback Home |publisher=Logback.qos.ch |access-date=2014-07-24}}</ref> 프로젝트를 시작했다.

아파치 Log4j 팀은 Log4j 1의 후속 해당 프레임워크에서 나타난 여러 문제들을 해결한다.<ref>{{웹 인용|title=Why was Log4j 2 created? |last=Goers |first=Ralph |website=Ralph Goers |date=15 December 2019 |url= https://www.ralphgoers.com/post/why-was-log4j-2-created}}</ref> 게다가 Log4j 2는 전작에 비해 더 확장성을 높이기 위한 플러그인 아키텍처를 채택하고 있다. Log4j 2는 1.x 버전들과 하위 호환이 되지는 않으나<ref>{{웹 인용|url=http://logging.apache.org/log4j/2.x/index.html#News |title=Log4j 2 Guide - Apache Log4j 2: News |publisher=Logging.apache.org |date=2014-07-12 |access-date=2014-07-24}}</ref> 어댑터(adapter)의 이용은 가능하다. 2015년 8월 5일, 아파치 로깅 서비스 프로젝트 관리 위원회는 Log4j 1이 수명 만기에 도달했으며 Log4j 1 사용자들은 아파치 Log4j 2로 업그레이드할 것을 권고한다고 발표하였다.<ref>{{웹 인용|url=https://blogs.apache.org/foundation/entry/apache_logging_services_project_announces |title=Apache Logging Services Project Announces Log4j 1 End-Of-Life; Recommends Upgrade to Log4j 2 |publisher=blogs.apache.org |date=2015-08-05 |access-date=2016-07-03}}</ref>

2021년 12월 9일, [[제로 데이 공격|제로 데이]] [[임의 코드 실행]] 취약점이 Log4j 2에서 보고되었다.<ref name="lawfare">{{웹 인용|url=https://www.lawfareblog.com/whats-deal-log4shell-security-nightmare|title=What's the Deal with the Log4Shell Security Nightmare?|date=December 10, 2021|website=Lawfare}}</ref> 지난 10년 내의 가장 크고 가장 심각한 취약점이다.<ref name="guardian">{{웹 인용|url=https://www.theguardian.com/technology/2021/dec/10/software-flaw-most-critical-vulnerability-log-4-shell|title=Recently uncovered software flaw 'most critical vulnerability of the last decade'|first=Associated|last=Press|date=December 11, 2021|website=the Guardian}}</ref>

== 아파치 Log4j 2 ==
아파치 Log4j 2는 Log4j 1의 뒤를 잇는다. 이 프레임워크는 처음부터 재개발되었으며 Log4j 1, java.util.logging을 포함한 기존 로깅 솔루션들의 영향을 받아 만들어졌다. Log4j 1 대비 주된 차이점<ref>{{웹 인용|url=http://www.grobmeier.de/the-new-log4j-2-0-05122012.html |title=The new log4j 2.0 |publisher=Grobmeier.de |date=2012-12-05 |access-date=2014-07-24}}</ref><ref>{{웹 인용|url=http://logging.apache.org/log4j/2.x/manual/index.html |title=Log4j – Overview - Apache Log4j 2 |publisher=logging.apache.org |date=2016-06-05 |access-date=2016-07-03}}</ref>은 다음과 같다:
* 개선된 가독성. Log4j 1이나 로그백과 같은 프레임워크를 재구성하는 동안 메시지는 소실되지 않음.
* 확장성. Log4j 2는 플러그인 시스템을 지원하므로 사용자들이 사용자 지정 구성 요소를 정의하고 구성할 수 있음.
* 단순화된 구성 문법
* xml, json, yaml, properties 구성 지원
* 개선된 필터
* 구성 파일, 시스템 속성, 환경 변수, ThreadContext Map, 이벤트 내 데이터에 정의된 값의 속성 찾기 지원
* 여러 API 지원: Log4j 2는 Log4j 2, Log4j 1.2, SLF4J, Commons Logging, java.util.logging (JUL) API를 사용하여 응용 프로그램과 함께 사용할 수 있음.
* 사용자 지정 로그 레벨
* 레이지 로깅(lazy logging)을 위한 자바 8 스타일의 람다 지원
* 마커
* 사용자 지정 메시지 오브젝트 지원
* 공통 구성에서 가비지가 거의 없거나 아예 없음
* 개선된 속도

Log4j 2의 가장 눈에 띄는 기능들 가운데 하나는 비동기 Loggers의 성능이다.<ref>{{웹 인용|url=http://logging.apache.org/log4j/2.x/manual/async.html#Performance |title=Log4j 2 Asynchronous Loggers for Low-Latency Logging - Apache Log4j 2 |publisher=Logging.apache.org |date=2014-07-12 |access-date=2014-07-24}}</ref> Log4j 2는 [[디스럽터|LMAX 디스럽터]]를 활용한다.<ref>{{웹 인용|url=https://lmax-exchange.github.io/disruptor/ |title=Disruptor by LMAX-Exchange |publisher=Lmax-exchange.github.io |access-date=2014-07-24}}</ref> 이 라이브러리는 커널 락의 필요성을 줄이며 12배만큼 로깅 성능을 제고한다. 이를테면 동일 환경에서 Log4j 2는 1초에 18,000,000개 이상의 메시지를 기록할 수 있는 반면 로그백과 Log4j 1 등의다른 프레임워크들은 초당 2,000,000개 미만의 메시지를 기록할 수 있다.

== 기능 ==
=== 로그 레벨 ===
log4j의 최근 버전에 의하면 높은 등급에서 낮은 등급으로의 7개 로그 레벨을 가지고 있다. 설정 파일에 대상별(자바에서는 패키지)로 레벨을 지정이 가능하고 그 등급 이상의 로그만 저장하는 방식이다.
{| class="wikitable"
|-
!'''레벨'''
!'''설명'''
|-
| '''OFF'''
| 가능성이 가장 높은 순위. 로그를 끄기 위해 사용한다.
|-
| '''FATAL'''
| 이른 종료를 일으키는 심각한 오류. 상태 콘솔에 바로 표시될 것으로 예측.
|-
| '''ERROR'''
| 다른 런타임 오류 또는 예기치 못한 조건. 상태 콘솔에 바로 표시될 것으로 예측.
|-
| '''WARN'''
| 구식 API의 사용, 잘 활용하지 못한 API 사용, 오류에 '가까운' 것, 그 밖에 꼭 잘못된 것은 아니지만 만족을 하지 못하거나 예기치 않은 런타임 상황. 상태 콘솔에 바로 표시될 것으로 예측.
|-
| '''INFO'''
| 흥미로운 런타임 이벤트(시작/종료). 콘솔에 바로 표시될 것으로 예측되므로 가능한 보수적으로 최소한으로 사용.
|-
| '''DEBUG'''
| 시스템 전반의 흐름에 관한 자세한 정보. 로그에만 기록될 것으로 예측. 일반적으로 응용 프로그램이 기록하는 대부분의 줄은 DEBUG로 작성하는 것이 좋다.
|-
| '''TRACE'''
| 가장 세세한 정보. 로그에만 기록될 것으로 예측. 버전 1.2.12부터 지원.<ref>{{웹 인용|url=http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/Level.html#TRACE |title=Level (Apache Log4j 1.2.17 API) |publisher=Logging.apache.org |date=2012-06-09 |access-date=2014-07-24}}</ref>
|}

==== 사용자 지정 로그 레벨 ====
Log4j 2는 사용자가 자신만의 로그 레벨을 정의할 수 있게 허용한다.<ref>{{웹 인용|url=https://logging.apache.org/log4j/2.x/manual/customloglevels.html |title=Custom Log Levels |publisher=Logging.apache.org |date=2014-07-12 |access-date=2016-07-16}}</ref> 내장된 로그 레벨과 동일한 사용자 지정 로그 레벨을 지원하는 Loggers를 만들기 위해 소스 코드 생성기 도구를 제공한다.

=== Log4j 구성 ===
Log4j는 구성 파일 또는 자바 코드를 통해 구성할 수 있다.<ref>{{웹 인용|url=https://logging.apache.org/log4j/2.x/manual/configuration.html |title=Configuration |publisher=Logging.apache.org |date=2016-07-05 |access-date=2016-07-16}}</ref> [[XML]], [[JSON]], [[YAML]] 또는 [[.properties|properties 파일]] 포맷으로 작성이 가능하다. 구성 내에서 사용자는 3개의 주요 구성 요소를 정의할 수 있다: Loggers, Appenders, Layouts. 파일을 통해 로깅을 구성할 경우 Log4j를 사용하는 응용 프로그램을 수정하지 않더라도 로깅을 켜고 끌 수 있다는 장점이 있다. 응용 프로그램은 문제가 생길 때까지 로그를 끄도록 허용하는 것이 가능한데, 예를 들어 로깅을 되돌리거나 단순히 구성 파일을 수정하는 것만으로 가능하다.

* '''Loggers'''는 로그 메시지 도착지 이름이다.<ref>{{웹 인용|url=https://logging.apache.org/log4j/2.x/manual/architecture.html |title=Architecture|publisher=Logging.apache.org |date=2016-07-05 |access-date=2016-07-16}}</ref>
* '''Appenders'''는 실제 출력을 수행하는 실체이다.<ref>{{웹 인용|url=https://logging.apache.org/log4j/2.x/manual/appenders.html |title=Appenders|publisher=Logging.apache.org |date=2016-07-05 |access-date=2016-07-16}}</ref>
* '''Layouts'''는 Appenders가 로그 항목의 서식을 지정하기 위해 사용한다.<ref>{{웹 인용|url=https://logging.apache.org/log4j/2.x/manual/layouts.html |title=Layouts|publisher=Logging.apache.org |date=2016-07-05 |access-date=2016-07-16}}</ref>
* '''Filters'''는 Log4j 2의 기능으로, 어느 로그 항목이 어느 Loggers와 Appenders에 의해 처리되어야 하는지를 세밀히 조절하기 위한 것이다.<ref>{{웹 인용|url=https://logging.apache.org/log4j/2.x/manual/filters.html |title=Filters|publisher=Logging.apache.org |date=2016-07-05 |access-date=2016-07-16}}</ref>

==== Log4j 2의 예시 ====
<syntaxhighlight lang="xml">
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="trace" monitorInterval="60">
  <Properties>
    <Property name="filename">target/test.log</Property>
  </Properties>

  <Appenders>
    <Console name="STDOUT">
      <PatternLayout pattern="%d %p %c{1.} [%t] %m%n"/>
    </Console>

    <File name="file" fileName="${filename}">
      <PatternLayout>
        <pattern>%d %p %c{1.} [%t] %m%n</pattern>
      </PatternLayout>
    </File>
  </Appenders>

  <Loggers>
    <!-- 
         loggers whose name starts with 'org.springframework' will only log messages of level "info" or higher;
         if you retrieve Loggers by using the class name (e.g. Logger.getLogger(AClass.class))
         and if AClass is part of the org.springframework package, it will belong to this category
    -->
    <Logger name="org.springframework" level="info" additivity="false" />

    <!--
        Filter example: for loggers whose name starts with 'com.mycompany.myproduct',
        log entries of level "debug" or higher whose ThreadContextMap data contains
        the key-value pair "test=123", also send these log entries to the "STDOUT" appender.
    -->
    <Logger name="com.mycompany.myproduct" level="debug" additivity="true">
      <ThreadContextMapFilter>
        <KeyValuePair key="test" value="123"/>
      </ThreadContextMapFilter>
      <AppenderRef ref="STDOUT"/>
    </Logger>

    <!--
        By default, all log messages of level "trace" or higher will be logged.
        Log messages are sent to the "file" appender and
        log messages of level "error" and higher will be sent to the "STDOUT" appender.
    -->
    <Root level="trace">
      <AppenderRef ref="file"/>
      <AppenderRef ref="STDOUT" level="error"/>
    </Root>
  </Loggers>

</Configuration>
</syntaxhighlight>

==== Log4j 1.2의 예시 ====
<syntaxhighlight lang="xml">
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration PUBLIC "-//LOGGER" "http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/xml/doc-files/log4j.dtd">
<log4j:configuration>
    <!-- 
         an appender is an output destination, such as the console or a file;
         names of appenders are arbitrarily chosen.
    -->
    <appender name="stdout" class="org.apache.log4j.ConsoleAppender">
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern"
                value="%d{ABSOLUTE} %5p %c{1}:%L - %m%n" />
        </layout>
    </appender>

    <!-- 
         loggers of category 'org.springframework' will only log messages of level "info" or higher;
         if you retrieve Loggers by using the class name (e.g. Logger.getLogger(AClass.class))
         and if AClass is part of the org.springframework package, it will belong to this category
    -->
    <logger name="org.springframework">
        <level value="info"/>
    </logger>

    <!-- 
         everything of spring was set to "info" but for class
         PropertyEditorRegistrySupport we want "debug" logging
    -->
    <logger name="org.springframework.beans.PropertyEditorRegistrySupport">
        <level value="debug"/>
    </logger>

    <logger name="org.acegisecurity">
        <level value="info"/>
    </logger>


    <root>
        <!-- 
            all log messages of level "debug" or higher will be logged, unless defined otherwise
            all log messages will be logged to the appender "stdout", unless defined otherwise
        -->
        <level value="debug" />
        <appender-ref ref="stdout" />
    </root>
</log4j:configuration>
</syntaxhighlight>

=== TTCC ===
TTCC는 Log4j가 사용하는 메시지 서식이다.<ref>{{웹 인용|url=http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/TTCCLayout.html |title=TTCCLayout (Apache Log4j 1.2.17 API) |publisher=Logging.apache.org |date=2012-06-09 |access-date=2014-07-24}}</ref>  TTCC는 "Time Thread Category Component"를 가리킨다. 다음의 패턴을 사용한다:

  %r [%t] %-5p %c %x - %m%n

여기서
{| class="wikitable"
|-
! 표현
! 설명
|-
| %r
| 로깅 이벤트가 발생하기 전까지 레이아웃 구성에 소요된 밀리초를 출력하기 위해 사용한다.
|-
| %t
| 로깅 이벤트를 생성한 스레드의 이름을 출력하기 위해 사용한다.
|-
| %p
| 로깅 이벤트의 우선 순위를 출력하기 위해 사용한다.
|-
| %c
| 로깅 이벤트의 범주를 출력하기 위해 사용한다.
|-
| %x
| 로깅 이벤트를 발생시킨 스레드와 관련된 NDC(nested diagnostic context)를 출력하기 위해 사용한다.<ref>{{웹 인용|url=http://people.apache.org/~carnold/log4j/docs/org/apache/log4j/NDC.html |title=Class NDC
|archive-url=https://web.archive.org/web/20070820182511/http://logging.apache.org/log4j/docs/api/org/apache/log4j/NDC.html |archive-date=2007-08-20 |url-status=live|access-date=2021-12-11}}</ref>
|-
| %X{key}
| 특정 키에 대한 로깅 이벤트를 생성한 스레드와 관련된 MDC(mapped diagnostic context)를 출력하기 위해 사용한다.<ref>{{웹 인용|url=http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/MDC.html |title=MDC (Apache Log4j 1.2.17 API) |publisher=Logging.apache.org |date=2012-06-09 |access-date=2014-07-24}}</ref>
|-
| %m
| 로깅 이벤트에 관련된 응용 프로그램이 제공한 메시지를 출력하기 위해 사용한다.
|-
| %n
| 하나 이상의 플랫폼 특화 [[새줄문자]]를 출력하기 위해 사용한다.
|}

'''출력 예시'''<br />
467 [main] INFO  org.apache.log4j.examples.Sort - Exiting main method.

== 포팅 ==
* [https://web.archive.org/web/20070820061743/http://logging.apache.org/log4cxx/ Log4cxx 홈페이지] - [[C++]]용 이식
* [http://log4cplus.sourceforge.net/ Log4cplus 홈페이지] - C++용으로 이식된 또 다른 것
* [http://dclib.sourceforge.net/ dlib C++ library 홈페이지] - C++용 이식을 아직 담고있는 것
* [http://log4c.sourceforge.net/ Log4c] - [[C (프로그래밍 언어)|C]]용 이식
* [http://log4perl.sourceforge.net/ Log4perl] - [[펄]]용 이식
* [https://web.archive.org/web/20130907201220/http://log4js.berlios.de/ Log4js] - [[자바스크립트]]용 이식
* [https://web.archive.org/web/20080924223430/http://docs.python.org/lib/module-logging.html logging] - log4j의 영향을 받은 [[파이썬]]용 공식 로깅 모듈.
* [http://log4r.sourceforge.net Log4r] - log4j의 영향을 받은 [[루비 (프로그래밍 언어)|루비]]용 로깅 모듈
* [https://web.archive.org/web/20070301084859/http://logging.apache.org/log4net/ Log4net] - 마이크로소프트 [[닷넷 프레임워크]]로 이식
* [http://logging.apache.org/log4php/ log4php] [[PHP]]용 이식
* [http://log4d.sourceforge.net/ log4d] [[델파이]]용 이식

== Log4Shell 취약점 ==
{{본문|Log4Shell}}

Log4j 2에서 [[임의 코드 실행|원격 코드 실행]]을 수반하는 [[제로 데이 공격|제로 데이]] 공격, 즉 서술자 Log4Shell(CVE-2021-44228)이 [[알리바바그룹]]에 의해 2021년 11월 24일 발견되어 아파치에 보고되었으며 2021년 12월 9일 [[트위터]]를 통해 일반에 공개되었다.<ref name="lawfare"/> 영향을 받는 서비스에는 [[클라우드플레어]], [[아이클라우드]], [[마인크래프트: 자바 에디션]],<ref>{{웹 인용|date=10 December 2021|title=Security Vulnerability in Minecraft: Java Edition|url=https://help.minecraft.net/hc/en-us/articles/4416199399693-Security-Vulnerability-in-Minecraft-Java-Edition|url-status=live|website=[[Minecraft]]}}</ref> [[스팀]], [[텐센트 QQ]], [[트위터]]가 포함된다.<ref>{{웹 인용|url=https://arstechnica.com/information-technology/2021/12/minecraft-and-other-apps-face-serious-threat-from-new-code-execution-bug/ |title=Zeroday in ubiquitous Log4j tool poses a grave threat to the Internet |last=Goodin |first=Dan |date=December 9, 2021 |website=[[Ars Technica]] |access-date=December 10, 2021 |quote=}}</ref><ref>{{웹 인용|url=https://www.cyberkendra.com/2021/12/worst-log4j-rce-zeroday-dropped-on.html |title=Worst Apache Log4j RCE Zero day Dropped on Internet  |author=<!--Not stated--> |date=December 9, 2021 |website=Cyber Kendra |access-date=December 10, 2021 |quote=}}</ref><ref name="pcmag">{{웹 인용|url=https://www.pcmag.com/news/countless-serves-are-vulnerable-to-apache-log4j-zero-day-exploit |title=Countless Servers Are Vulnerable to Apache Log4j Zero-Day Exploit |last=Mott |first=Nathaniel |date=December 10, 2021 |website=[[PC Magazine]] |access-date=December 10, 2021 |quote=}}</ref>

== 각주 ==
{{각주}}

== 외부 링크 ==
* {{공식 웹사이트}}

{{아파치 소프트웨어}}

[[분류:아파치 소프트웨어 재단 프로젝트|Log4j]]
[[분류:자바로 작성된 자유 소프트웨어]]
[[분류:아파치 라이선스 소프트웨어]]