로깅 가이드
기본 원칙
System.out.println 사용 금지 → @Slf4j 사용
- 문자열
"+" 연산 금지 → {} 바인딩 포맷팅 사용
- 로그에 비밀번호, 카드번호, 개인정보 출력 금지
- 운영 환경에서
DEBUG 비활성화
로거 선언
// @Slf4j 어노테이션 사용 (권장)
@Slf4j
@Service
@RequiredArgsConstructor
public class UserService {
// log.info(), log.warn(), log.error() 바로 사용
}
// 또는 직접 선언
private static final Logger log = LoggerFactory.getLogger(UserService.class);
System.out.println 사용 금지
// 잘못된 예 — 절대 금지
System.out.println("사용자 조회: " + userId);
// 올바른 예 — @Slf4j 사용
log.info("사용자 조회: userId={}", userId);
문자열 "+" 연산 금지 → {} 바인딩 사용
// 잘못된 예 — "+" 연산 (성능 저하, DEBUG 레벨에서도 문자열 생성)
log.info("사용자 조회: userId=" + userId + ", userNm=" + userNm);
// 올바른 예 — {} 바인딩 포맷팅
log.info("사용자 조회: userId={}, userNm={}", userId, userNm);
로그 레벨 기준
| 레벨 | 사용 상황 | 예시 |
ERROR | 장애, 복구 불가능한 오류 | DB 연결 실패, 외부 API 오류 |
WARN | 주의, 비정상이지만 계속 가능 | 재시도, 예상치 못한 상태 |
INFO | 주요 비즈니스 흐름 | 로그인 성공, 배치 시작/완료 |
DEBUG | 개발용 상세 정보 | 파라미터 값, 중간 계산 |
TRACE | 아주 상세한 추적 정보 | 메서드 진입/종료 |
올바른 로깅 예시
// INFO — 주요 비즈니스 이벤트
log.info("사용자 등록 완료: userId={}", vo.getUserId());
log.info("배치 시작: batchId={}", batchId);
// WARN — 비정상이지만 계속 가능한 상황
log.warn("로그인 실패: userId={}", userId);
log.warn("외부 API 응답 지연: url={}, elapsed={}ms", url, elapsed);
// ERROR — 스택트레이스 포함
log.error("사용자 등록 실패: userId={}", vo.getUserId(), e);
log.error("DB 연결 실패", e);
// DEBUG — 개발 환경에서만
log.debug("쿼리 파라미터: keyword={}, page={}", keyword, page);
잘못된 로깅 (금지)
// 개인정보 출력 금지
log.info("사용자: email={}, phone={}", email, phone); // 금지
log.info("로그인: password={}", password); // 절대 금지
log.info("카드번호: cardNo={}", cardNo); // 금지
log.info("API 키: key={}", apiKey); // 금지
// System.out.println 금지
System.out.println("처리 완료"); // 금지
// "+" 연산 금지
log.info("결과: " + result); // 금지
application.yml 로깅 설정
logging:
level:
root: INFO
com.{회사명}.{프로젝트명}: INFO
org.springframework.web: WARN
org.mybatis: WARN
Logback 운영 설정 (logback-spring.xml)
<!-- src/main/resources/logback-spring.xml -->
<configuration>
<springProfile name="prod">
<!-- 운영 환경: 파일 출력 (rolling) -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>/var/log/{서비스명}/app.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>/var/log/{서비스명}/app.%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="FILE"/>
</root>
</springProfile>
</configuration>
체크리스트
- [ ]
System.out.println 사용 금지 → @Slf4j + log.* 사용
- [ ] 문자열
"+" 연산 금지 → {} 바인딩 사용
- [ ] 로그에 비밀번호, 카드번호, 개인정보 미포함
- [ ] 운영 환경 DEBUG 로그 비활성화
- [ ] 예외 로그:
log.error("설명", e) — 스택트레이스는 로그에만
- [ ] 로거는 클래스별로 선언 (
@Slf4j 또는 직접 선언)