# 로깅(logging)

Spring Boot는 기본적으로 **SLF4J**(Simple Logging Facade for Java)와 **Logback**을 로깅 프레임워크로 사용합니다. 별도 설정 없이도 동작하지만, 실무에서는 로그 레벨, 출력 형식, 파일 저장 등을 커스터마이징해야 하죠.

Spring Boot Starter에 SLF4J와 Logback이 포함되어 있습니다.

```kotlin
// build.gradle.kts
dependencies {
    implementation("org.springframework.boot:spring-boot-starter")
}
```

## `application.yaml`

```yaml
# 공통 로깅 설정
logging:
  level:
    root: INFO              # 기본 로깅 레벨
    com.example.myapp: DEBUG  # 특정 패키지의 로깅 레벨
  pattern:
    console: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"  # 콘솔 출력 형식
    file: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"     # 파일 출력 형식

# 개발 환경
---
spring:
  config:
    activate:
      on-profile: dev
logging:
  level:
    root: DEBUG             # 개발 환경에서 더 상세한 로그
  file:
    name: logs/myapp-dev.log  # 로그 파일 경로 및 이름

# 프로덕션 환경
---
spring:
  config:
    activate:
      on-profile: prod
logging:
  level:
    root: WARN              # 프로덕션에서는 경고 이상만 출력
  file:
    name: /var/log/myapp.log  # 프로덕션 로그 파일 경로
  logback:
    rollingpolicy:
      max-file-size: 10MB     # 파일 크기 제한
      max-history: 30         # 최대 보관 기간 (일)
      file-name-pattern: myapp-%d{yyyy-MM-dd}.%i.log  # 롤링 파일 이름 패턴
```

### 로깅 설정 옵션

| **옵션**                          | **설명**                                                                                   | **예시 값**                          |
|----------------------------------|-------------------------------------------------------------------------------------------|-------------------------------------|
| `logging.level.root`             | 루트 로거의 기본 로깅 레벨 설정 (`TRACE`, `DEBUG`, `INFO`, `WARN`, `ERROR`, `OFF`)         | `INFO`                             |
| `logging.level.{패키지명}`       | 특정 패키지나 클래스에 대한 로깅 레벨 설정                                                 | `com.example.myapp: DEBUG`         |
| `logging.pattern.console`        | 콘솔에 출력되는 로그 형식 정의                                                              | `%d{yyyy-MM-dd HH:mm:ss} %-5level %msg%n` |
| `logging.pattern.file`           | 파일에 기록되는 로그 형식 정의                                                              | `%d{yyyy-MM-dd HH:mm:ss} %-5level %msg%n` |
| `logging.file.name`              | 로그 파일의 경로와 이름 설정 (절대 경로 또는 상대 경로)                                      | `logs/myapp.log`                   |
| `logging.file.path`              | 로그 파일이 저장될 디렉토리 설정 (파일 이름은 기본값 사용)                                   | `/var/log`                         |
| `logging.logback.rollingpolicy.max-file-size` | 로그 파일의 최대 크기 (크기 초과 시 롤링)                                     | `10MB`                             |
| `logging.logback.rollingpolicy.max-history` | 롤링된 로그 파일의 최대 보관 기간 (일 단위)                                  | `30`                               |
| `logging.logback.rollingpolicy.file-name-pattern` | 롤링된 로그 파일의 이름 패턴 정의                                       | `myapp-%d{yyyy-MM-dd}.%i.log`      |
| `logging.exception-conversion-word` | 예외 스택 트레이스를 변환하는 패턴 설정                                              | `%ex`                              |
| `logging.charset.console`        | 콘솔 로그의 문자 인코딩 설정                                                               | `UTF-8`                            |
| `logging.charset.file`           | 파일 로그의 문자 인코딩 설정                                                               | `UTF-8`                            |


1. **`logging.level`**
   - **설명**: 로깅 레벨은 로그의 상세도를 결정합니다. `DEBUG`는 개발 중 디버깅에 유용하고, `WARN`이나 `ERROR`는 프로덕션에서 주로 사용됩니다.
   - **예시**: `com.example.myapp: DEBUG`로 설정하면 해당 패키지의 로그만 상세히 출력됩니다.

2. **`logging.pattern`**
   - **설명**: 로그 메시지의 형식을 정의합니다. `%d` (날짜), `%-5level` (레벨), `%msg` (메시지), `%n` (줄바꿈) 등 패턴을 조합할 수 있습니다.
   - **팁**: 콘솔과 파일 형식을 다르게 설정해 환경별로 최적화 가능.

3. **`logging.file`**
   - **설명**: `name`은 파일 경로를 직접 지정하며, `path`는 디렉토리만 지정할 때 사용됩니다. 두 옵션을 함께 사용할 경우 `name`이 우선합니다.
   - **예시**: `logs/myapp-dev.log`는 프로젝트 루트 기준 상대 경로로 파일 생성.

4. **`logging.logback.rollingpolicy`**
   - **설명**: 로그 파일이 커질 경우 롤링(새 파일 생성)을 설정합니다. `max-file-size`로 크기 제한, `max-history`로 보관 기간을 지정합니다.
   - **예시**: `file-name-pattern`에서 `%i`는 파일 인덱스를 의미하며, `myapp-2025-03-16.0.log` 같은 이름으로 생성됩니다.



## 커스텀 Logback 설정
복잡한 설정은 `src/main/resources/logback-spring.xml`로 관리합니다.

```xml
<configuration>
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>

    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>logs/my-app.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>logs/my-app-%d{yyyy-MM-dd}.log</fileNamePattern>
            <maxHistory>30</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>

    <root level="INFO">
        <appender-ref ref="CONSOLE" />
        <appender-ref ref="FILE" />
    </root>

    <logger name="com.example" level="DEBUG" additivity="false">
        <appender-ref ref="CONSOLE" />
        <appender-ref ref="FILE" />
    </logger>
</configuration>
```

- **ConsoleAppender**: 콘솔에 로그 출력.  
- **RollingFileAppender**: 날짜별로 로그 파일 저장 (30일 보관).  
- **logger**: 특정 패키지에 다른 레벨 적용.

## 코드에서 SLF4J 사용
Lombok의 `@Slf4j`로 쉽게 로깅을 추가할 수 있습니다.

```java
@Slf4j
@RestController
@RequestMapping("/api")
public class ExampleController {
    @GetMapping("/test")
    public String test() {
        log.debug("디버그 로그 테스트");
        log.info("정보 로그 테스트");
        log.error("에러 로그 테스트");
        return "Log Test";
    }
}
```

## 설정 우선순위
환경 변수 > `application.yaml` > 기본값 순으로 적용. 