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
'💻 하나씩 차곡차곡 > Back-end' 카테고리의 다른 글
프로젝트 패키지 구조 : 레이어 중심 VS 도메인 중심 (0) | 2025.04.18 |
---|---|
[Spring] @Builder란? (Feat. 정적 생성 메서드) (0) | 2025.04.18 |
인텔리제이(IntelliJ)에서 롬복(Lombok) 활성화 하는 방법 (0) | 2025.04.04 |
"나도 드디어...성능 최적화를...?" - 대용량 INSERT 성능 개선: SQL Session 배치 처리로 최적화하기 (0) | 2025.02.07 |
[Java] IllegalArgumentException VS IllegalStateException : 어떨 때 뭘 써야 하지? (0) | 2025.01.17 |