본문 바로가기
💻 하나씩 차곡차곡/Back-end

[Spring] SQL 로그 출력 방법 총정리 (feat. show-sql, format_sql, log4jdbc,p6spy)

by 뚜루리 2025. 4. 16.
728x90
320x100
스프링에서 SQL을 로깅하는 것은 디버깅과 성능 분석에서 아주 중요한 것중에 하나인데,
스프링에서는 어떤 SQL 로깅 방법 들이 있고, 어떻게 사용하며 어떨 때 사용하는지 총정리 해보자

 


1. show_sql

 

 

📌 특징

  • Hibernate가 System.out으로 SQL 출력
  • 로그 시스템(SLF4J)과 무관
  • 가장 단순하고 빠르게 볼 수 있는 방법

✅ 장점

  • 설정이 매우 간단함
  • JPA 테스트할 때 빠르게 확인 가능

❌ 단점

  • 바인딩값 출력 안 됨 (→ ?)
  • 로그레벨 조절 안 됨
  • 로그 파일 등으로 남기기 힘듦

⚙️ 적용법 (application.yml)

spring:
  jpa:
    show-sql: true

 

[로그 출력 예시]

select user0_.id as id1_0_0_, user0_.name as name2_0_0_ from user user0_ where user0_.id=?

 


✅ 2. format_sql

📌 특징

  • Hibernate가 출력할 SQL에 줄바꿈, 들여쓰기 등 포맷 적용
  • show_sql: true 또는 SLF4J 로깅과 함께 사용됨

✅ 장점

  • SQL 보기 편함
  • JPA 자동 생성 쿼리 구조 파악에 도움 됨

❌ 단점

  • 출력 자체를 담당하진 않음 → show_sql 또는 SLF4J가 있어야 효과 발휘

⚙️ 적용법 (application.yml)

spring:
  jpa:
    properties:
      hibernate:
        format_sql: true

 

[로그 출력 예시]

 

select
    user0_.id as id1_0_0_,
    user0_.name as name2_0_0_
from
    user user0_
where
    user0_.id=?

 

 


 

3. SLF4J 로깅 (with Logback or Log4j2)

📌 특징

  • Hibernate가 SLF4J 인터페이스로 로그를 전달
  • Spring Boot의 logging.level 설정으로 출력 제어

✅ 장점

  • 로그레벨 제어 가능 (debug, trace)
  • 로그 파일 저장, 필터링 등 자유로움
  • ? 바인딩값도 출력 가능

❌ 단점

  • 바인딩값은 trace 레벨이라 너무 많은 로그가 나올 수 있음

⚙️ 적용법 (application.yml)

spring:
  jpa:
    show-sql: false  # 꼭 꺼야 함
    properties:
      hibernate:
        format_sql: true  # SQL 포맷팅 (선택)

logging:
  level:
    org.hibernate.SQL: debug                # SQL 쿼리 로그
    org.hibernate.orm.jdbc.bind: trace      # 바인딩값 로그

 

[로그 출력 예시]

2025-04-18 14:15:30 DEBUG org.hibernate.SQL:
    select
        user0_.id as id1_0_,
        user0_.email as email2_0_
    from
        user user0_
    where
        user0_.email=?
2025-04-18 14:15:30 TRACE org.hibernate.orm.jdbc.bind:
    binding parameter [1] as [VARCHAR] - [test@example.com]

✅ 바인딩 값까지 trace에서 보여줌
🔸 SELECT 결과는 안 나옴


4. log4jdbc

📌 특징

  • JDBC 드라이버를 프록시하여 SQL 실행을 감시
  • 바인딩된 값 + 결과 테이블 출력까지 지원

✅ 장점

  • 바인딩된 값 출력
  • SELECT 결과를 테이블 형태로 보여줌
  • SLF4J 로그 시스템과 통합됨

❌ 단점

  • SQL 들여쓰기는 안 됨 (한 줄)
  • 결과가 많으면 로그 과다

 

⚙️ 설정 방법

1. build.gradle

implementation 'org.bgee.log4jdbc-log4j2:log4jdbc-log4j2-jdbc4.1:1.16'

혹은

runtimeOnly 'org.bgee.log4jdbc-log4j2:log4jdbc-log4j2-jdbc4.1:1.16'

 

2. application.yml

spring:
  datasource:
    url: jdbc:log4jdbc:mysql://localhost:3306/bookbookclub
    driver-class-name: net.sf.log4jdbc.sql.jdbcapi.DriverSpy

  jpa:
    show-sql: false
    properties:
      hibernate:
        format_sql: false

*** url에 log5jdbc, 그리고 driver-class-name 이 추가된 것.

 

3. log4jdbc.log4j2.properties

log4jdbc.dump.sql.select=true
log4jdbc.dump.sql.bind=true
log4jdbc.dump.sql.maxlinelength=-1
log4jdbc.trim.sql=false

 

[로그 출력 예시]

1. select u1_0.id from user u1_0 where u1_0.email=?
1. PreparedStatement.setString(1, "test@example.com")

ResultSet:
|----|
| id |
|----|
| 1  |
|----|

✅ 바인딩 값 출력됨
결과 테이블까지 출력됨
❌ 쿼리 들여쓰기는 없음

 


 

6. P6Spy

📌 특징

  • JDBC 드라이버 프록시 방식
  • 쿼리 포맷팅 + 바인딩값 출력 모두 지원
  • SLF4J 기반 로그 출력

✅ 장점

  • SQL 들여쓰기 (MultiLineFormat)
  • 바인딩된 쿼리 확인 가능
  • 로그백, 로그포제이와 자연스럽게 통합

❌ 단점

  • SELECT 결과 테이블 형태 출력 불가

 

[설정 방법]

1. 의존성 추가 (Gradle)

implementation 'p6spy:p6spy:3.9.1'

2. application.yml

spring:
  datasource:
    url: jdbc:p6spy:mysql://localhost:3306/bookbookclub
    username: root
    password: ...
    driver-class-name: com.p6spy.engine.spy.P6SpyDriver

3. p6spy.properties

module.log=com.p6spy.engine.logging.P6LogFactory
logMessageFormat=com.p6spy.engine.spy.appender.MultiLineFormat
appender=com.p6spy.engine.spy.appender.Slf4JLogger

 

📍 spy.properties는 YAML로 만들면 안되나요?

안됨. 반드시 .properties 형식의 파일이어야 함.

  • p6spy는 스프링의 설정 시스템이 아니라, 자체적으로 spy.properties라는 파일을 읽어서 동작함.
  • 이 파일은 Java의 표준 Properties 방식 (key=value)만 이해함.
  • application.yml, application.properties처럼 Spring Boot 설정과는 별도로 동작.

 

[로그 출력 예시]

# Time: 2025-04-18 16:20:01
# Duration: 3 ms
# SQL:
select
    u1_0.id,
    u1_0.email
from
    user u1_0
where
    u1_0.email = 'test@example.com';

✅ 쿼리 예쁘게 포맷됨
✅ 바인딩된 실제 값 출력됨
❌ SELECT 결과는 안 보임

 


🧭 정리

항목 Hibernate 기본 SLF4J 방식 log4jdbc P6Spy
로그 출력 위치 System.out SLF4J 로그 SLF4J 로그 SLF4J 로그
포맷팅 (format_sql) O O ✅ (포맷터로 처리)
바인딩된 값 출력 ✅ (trace)
SELECT 결과 테이블
로그레벨 제어

 

 


[로깅 방법 별 구조]

[Hibernate]
  ├─ show_sql + format_sql → System.out 출력 (포맷만 O)
  ├─ SLF4J 로거 사용 → debug/trace 레벨로 로그 전송
        ↓
     [SLF4J]
        ↓
     [Logback or Log4j2] → 로그 찍힘

[log4jdbc] or [P6Spy]
  ← JDBC 호출을 가로채서
     쿼리 + 바인딩 + (결과 or 포맷) → SLF4J로 로그 전송

 

 

  • 실행순서는 Hibernate(Hibernate가 SQL 생성) → JDBC(JDBC 드라이버에 전달 (이때 log4jdbc가 개입)) → DB(실제 DB 실행) 로 흘러가지만 
  • Hibernate는 SQL을 만든 후 JDBC에 넘긴 다음에야 System.out.println(SQL)을 실행해서 출력하는데  근데 log4jdbc는 JDBC에 SQL이 넘어오는 순간 가로채서 즉시 로그로 출력해버려서

굳이 출력 순서를 따지자면

  • [log4jdbc] or [P6Spy]는 JDBC 순서를 가로채기 때문에 [log4jdbc] or [P6Spy]가 먼저 찍히고, 그담에 Hibernate의 show_sql이 콘솔에 찍힘.

 


📍로그레벨은 뭔가요?

  • logLevel 설정은 로그를 어느 수준까지 출력할지를 결정하는 설정

[로그 레벨 종류]

레벨 설명 로그 출력 여부
TRACE 가장 상세한 정보 (디버깅용, 미세한 로직 추적)
DEBUG 개발 중 필요한 주요 흐름 확인
INFO 일반적인 실행 흐름 기록
WARN 경고 (예외 발생 가능성 등)
ERROR 에러 로그
OFF 아무것도 출력 안 함 ❌❌❌

👉 SQL 로그를 보기 위해선 보통 DEBUG 또는 TRACE로 유지

728x90
320x100