티스토리 뷰
1. 도입
로깅이란?
- 로깅(logging)은 소프트웨어 시스템에서 발생하는 모든 행위와 이벤트 정보를 시간 순서대로 기록하는 작업을 말한다. 이러한 기록은 프로그램의 실행 상태를 모니터링하고, 문제를 진단하며, 성능을 평가하는 데 필수적인 역할을 한다.
- 쉽게 말해, 로깅은 프로그램이 어떻게 실행되고 있는지에 대한 ‘흔적’을 남기는 것이다.
- 간단히 System.out.println()을 사용해 콘솔 로그를 남기는 것도 로깅에 해당한다.
Spring에서는 일련의 로깅 라이브러리를 제공하고 있다.
로깅의 필요성
- 디버깅
- 코드가 예상대로 작동하지 않을 때, 로그는 문제의 원인을 찾는 데 도움을 준다. 예를 들어, 특정 기능이 제대로 작동하지 않는다면, 로그를 통해 어느 부분에서 문제가 발생했는지 확인할 수 있다.
- 성능 모니터링
- 로그를 통해 시스템의 성능을 모니터링하고 병목 지점을 파악할 수 있다. 예를 들어, 특정 요청이 처리되는 데 걸리는 시간을 로그에 기록하면, 성능 저하가 발생하는 부분을 쉽게 찾아낼 수 있다.
- 감사 및 추적
- 로그는 사용자의 행동을 추적하고 보안 감사의 근거 자료로 사용할 수 있다. 예를 들어, 누가 언제 어떤 데이터를 변경했는지 기록함으로써, 나중에 문제가 발생했을 때 원인을 추적할 수 있다.
- 등등.
로깅의 기본 개념 소개 (Log Level : 로그 레벨)
로깅은 다양한 수준(level)으로 분류할 수 있다.
- ERROR: 예상하지 못한 심각한 문제가 발생했을 때 사용한다. 즉시 조취를 취해야 할 수준의 로그이다.
- WARN: 로직 상 유효성 확인이나 예상 가능한 문제로 인해 예외 처리가 필요한 경우 사용한다. 당장 서비스 운영에 큰 영향을 미치지 않지만 주의해야 할 부분을 나타낸다.
- INFO: 운영에 참고할 만한 사항이나 중요한 비즈니스 프로세스가 완료되었을 때 사용한다. 일반적으로 시스템의 정상적인 동작을 기록한다.
- DEBUG: 개발 단계에서 사용하며, SQL 쿼리 로깅 등 상세한 정보를 기록한다. 시스템의 내부 동작을 이해하는 데 도움이 된다.
- TRACE: 모든 레벨에 대한 상세한 로깅을 포함하며, 주로 개발 단계에서 사용한다. 세부적인 실행 흐름을 추적하는 데 유용하다.
위로 갈수록 로그 레벨이 높으며, 중요도와 긴급도가 증가한다.
로그 레벨 사용 지침
- DEBUG 이하 레벨: 주로 개발 과정에서 사용된다. 개발자는 시스템의 내부 동작을 이해하고 디버깅하기 위해 상세한 정보를 기록한다.
- INFO 레벨과 WARN 레벨: 실제 운영 환경에서 주로 사용된다. 시스템의 정상적인 동작과 주의해야 할 사항을 기록함으로써 운영 상태를 모니터링하고, 필요한 경우 즉각적인 조치를 취할 수 있다.
2. 로깅 라이브러리
Spring에서 사용할 수 있는 대표적인 로깅 관련 라이브러리
- Logback
- Slf4j의 구현체로 Spring Boot 환경에서는 **spring-boot-starter-web**에 기본적으로 포함된 **spring-boot-starter-logging**을 통해 Logback을 사용할 수 있다. 별도의 의존성 추가 작업이 필요 없다.
- 실무에서는 Logback을 대부분 사용한다고 한다.
- Log4j2
- 최신 프레임워크로, Logback에 비해 멀티 스레드 환경에서 비동기 처리가 아주 빠르다는 장점이 있다.
- Log4j
- 2015년 경 지원이 종료되었다. 현재는 사용을 권장하지 않는다.
SLF4J 라이브러리는 이들을 통합하여 인터페이스로 제공한다.
SLF4J(Simple Logging Facade for Java)
- SLF4J(Simple Logging Facade for Java)는 다양한 로깅 라이브러리를 통합하여 인터페이스로 제공하는 추상화 라이브러리이다. 이를 통해 구현체 라이브러리 간 전환이 자유롭다는 장점이 있다.
로깅 라이브러리를 사용하는 것의 장점
**System.out.println()**을 사용하는 것과 비교했을 때, 로깅 라이브러리를 사용하는 장점
- 부가 정보 제공: 스레드 정보, 클래스 이름 등 부가 정보를 함께 볼 수 있다.
- 출력 형식 지정: 출력 형식을 자유롭게 지정할 수 있다.
- 로그 레벨 지정: 로그 레벨에 따라 남기고 싶은 로그를 별도로 지정할 수 있다.
- 다양한 로그 위치: 콘솔뿐만 아니라 파일, 데이터베이스 등 다양한 위치에 로그를 남길 수 있다.
- 성능 향상: **System.out.println()**보다 성능이 좋다. (내부 버퍼링, 멀티 스레드 처리 등)
3. 기본 로깅 구현(실습)
spring-boot-starter 에는 기본적으로 starter-logging이 포함되어 있다.
Gradle dependencies를 살펴보면 starter-logging 안에 logback, log4j, slf4j가 포함되어 있는 것을 확인할 수 있다.
1. Controller에 로그 API 작성
//LogController
@RestController
@Slf4j // spring-boot-starter-web 의존성 있다면
//@Slf4j 애노테이션으로 바로 log 사용 가능
public class LogController {
@GetMapping("/")
public void log() {
log.trace("trace message");
log.debug("debug message");
log.info("info message"); //(기본 로그 레벨)
log.warn("warn message");
log.error("error message");
}
}
• @Slf4j : logger 사용을 위한 lombok 어노테이션. 직접 LoggerFactory를 사용해서 선언해도 된다.
그런데..! 포맨으로 쏜 후 콘솔창을 보면
debug와 trace 로그는 보이지 않는다. 그 이유는 로그 레벨은 기본적으로
[trace > debug > info > warn > error] 순이며
디폴트 설정이 **info**로 되어있기 때문에 debug와 trace로그는 기록되지 않은 것이다.
따라서 이들의 로그도 보고싶다면 콘솔 로그 수준을 변경해주어야 한다.
2-1. application.yml로 설정
콘솔 로그 수준을 변경하는 가장 간단한 방법은 application.yml이나 application.properties로 설정해주는 것이다.
// application.yml
logging:
level:
root: debug
콘솔 로그 수준을 debug로 해주면,
이제 콘솔창에서 debug 로그도 확인할 수 있다!
근데 잠시만. ㅋ
yml 설정은 스프링 부트에서 간단하게 설정할 수 있는 추상화된 방식이다. 따라서 세부적인 커스텀 설정을 위해서는 스프링 부트 문서에서 제공하는 xml 설정 방식을 익히는 것이 필요하다.
특히 로그 설정을 분리하고 세밀하게 조정하려면 xml 설정이 더 적합하다.
이를 위해 logback-spring.xml 파일을 생성하고 직접 커스텀해보겠다!
2-2. Spring boot Logback 설정
- logback-spring.xml 파일을 resources 디렉토리에 만들어서 참조한다.
- 참고순서
- **classpath(resources 디렉토리)**에 logback-spring.xml 파일이 있으면 해당 설정 파일을 읽어 사용한다.
- logback-spring.xml 파일이 없으면 .yml 또는 .properties 파일의 설정을 읽어 사용한다.
- logback-spring.xml 파일과 .yml 또는 .properties 파일이 동시에 있으면 .yml 또는 .properties 설정 파일이 먼저 적용되고, 그 후에 logback-spring.xml 파일이 적용된다.
// logback-spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- 60초마다 설정 파일의 변경을 확인하여 변경 시 갱신 -->
<configuration scan="true" scanPeriod="60 seconds">
<!-- log file path -->
<property name="LOG_PATH" value="/Users/chaewonkim/Desktop/logs"/>
<!-- log file name -->
<property name="LOG_FILE_NAME" value="logging"/>
<!-- err log file name -->
<property name="ERR_LOG_FILE_NAME" value="err_logging"/>
<!-- pattern -->
<property name="LOG_PATTERN" value="%-5level %d{yy-MM-dd HH:mm:ss}[%thread] [%logger{0}:%line] - %msg%n"/>
<!-- 로그 패턴에 색상 적용 %clr(pattern){color} -->
<conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter" />
<!-- Console log pattern with colors -->
<property name="CONSOLE_LOG_PATTERN"
value="[%d{yyyy-MM-dd HH:mm:ss}:%-3relative] %clr(%-5level) %clr(${PID:-}){magenta} %clr(---){faint} %clr([%15.15thread]){faint} %clr(%-40.40logger{36}){cyan} %clr(:){faint} %msg%n"/>
<!-- Console Appender with colors -->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
</encoder>
</appender>
<!-- File Appender -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 파일경로 설정 -->
<file>${LOG_PATH}/${LOG_FILE_NAME}.log</file>
<!-- 출력패턴 설정 -->
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${LOG_PATTERN}</pattern>
</encoder>
<!-- Rolling 정책 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- .gz,.zip 등을 넣으면 자동 일자별 로그파일 압축 -->
<fileNamePattern>${LOG_PATH}/${LOG_FILE_NAME}.%d{yyyy-MM-dd}_%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<!-- 파일당 최고 용량 kb, mb, gb -->
<maxFileSize>10MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!-- 일자별 로그파일 최대 보관주기(~일), 해당 설정일 이상된 파일은 자동으로 제거 -->
<maxHistory>30</maxHistory>
</rollingPolicy>
</appender>
<!-- 에러의 경우 파일에 로그 처리 -->
<appender name="Error" class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>error</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<file>${LOG_PATH}/${ERR_LOG_FILE_NAME}.log</file>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${LOG_PATTERN}</pattern>
</encoder>
<!-- Rolling 정책 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- .gz,.zip 등을 넣으면 자동 일자별 로그파일 압축 -->
<fileNamePattern>${LOG_PATH}/${ERR_LOG_FILE_NAME}.%d{yyyy-MM-dd}_%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<!-- 파일당 최고 용량 kb, mb, gb -->
<maxFileSize>10MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!-- 일자별 로그파일 최대 보관주기(~일), 해당 설정일 이상된 파일은 자동으로 제거 -->
<maxHistory>60</maxHistory>
</rollingPolicy>
</appender>
<!-- root레벨 설정 -->
<root level="debug">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="FILE"/>
<appender-ref ref="Error"/>
</root>
<!-- 특정패키지 로깅레벨 설정 -->
<logger name="org.apache.ibatis" level="debug" additivity="false">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="FILE"/>
<appender-ref ref="Error"/>
</logger>
</configuration>
당황하셨죠? ㅋㅋ
이론설명
Logback-spring.xml은 크게 appender와 logger 두개로 구분된다.
1) appender
로그의 형태를 결정하고, 로그 메시지가 출력될 대상을 결정하는 요소 (콘솔에 출력할지, 파일로 출력할지 등의 설정)
Appender의 주요 클래스 종류
- ch.qos.logback.core.ConsoleAppender: 콘솔에 로그를 출력한다. 로그를 OutputStream에 작성하여 콘솔에 출력한다.
- ch.qos.logback.core.FileAppender: 파일에 로그를 출력한다. 최대 보관 일수 등을 설정할 수 있다.
- ch.qos.logback.core.rolling.RollingFileAppender: 여러 개의 파일로 로그를 롤링하며 출력한다. (FileAppender를 상속받으며, 지정 용량을 초과한 로그 파일을 넘버링하여 나누어 저장할 수 있다.)
- ch.qos.logback.classic.net.SMTPAppender: 로그를 이메일로 전송한다.
- ch.qos.logback.classic.db.DBAppender: 데이터베이스에 로그를 저장한다.
2) root, logger
패키지와 로그 레벨을 설정할 때, 지정된 appender를 참조한다.
root
- 전역 설정을 담당하며, 모든 로거의 기본 설정으로 사용된다.
- 특정 logger 설정이 없는 경우 이 설정이 적용된다.
logger
- 지역 설정을 담당하며, 특정 패키지나 클래스에 대한 로그 설정을 정의한다.
- additivity 값은 이 Logger가 상위 설정을 상속할지 여부를 결정하며, 기본값은 true 이다.
3) property
설정 파일에서 변수 값을 선언하여 사용할 수 있다.
이를 통해 설정 파일을 보다 유연하게 관리할 수 있다.
4) layout, encoder
Layout
로그의 출력 형식을 지정한다.
Encoder
로그 메시지를 지정된 형식으로 변환하여 appender에 전달한다.
FileAppender와 그 하위 클래스는 encoder를 필요로 하며, layout 대신 encoder를 사용한다.
5) pattern
로그 출력 패턴을 정의하는 요소들
- %Logger{length}: Logger 이름을 축약하여 출력한다. **{length}**는 최대 자리 수를 의미합니다 (예: %logger{35}).
- %-5level: 로그 레벨을 출력한다. **5**는 고정된 폭을 의미합니다 (5글자).
- %msg: 로그 메시지 (또는 %message).
- ${PID:-}: 프로세스 ID를 출력한다.
- %d: 로그 기록 시간을 출력한다.
- %p: 로깅 레벨을 출력한다.
- %F: 로깅이 발생한 파일 이름을 출력한다.
- %M: 로깅이 발생한 메서드 이름을 출력한다.
- %l: 로깅이 발생한 호출지 정보를 출력한다.
- %L: 로깅이 발생한 호출지의 라인 번호를 출력한다.
- %thread: 현재 스레드 이름을 출력한다.
- %t: 로깅이 발생한 스레드 이름을 출력한다.
- %c: 로깅이 발생한 카테고리를 출력한다.
- %C: 로깅이 발생한 클래스 이름을 출력한다.
- %m: 로그 메시지를 출력한다.
- %n: 줄 바꿈 문자를 출력한다.
- %%: **%**를 출력한다.
- %r: 애플리케이션 시작 이후 로깅이 발생한 시점까지의 시간을 밀리초 단위로 출력한다.
6) 기타..
- <file>: 기록할 파일명과 경로를 설정한다.
- <rollingPolicy class>:
- ch.qos.logback.core.rolling.TimeBasedRollingPolicy: 날짜별로 로그를 롤링한다.
- ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP: 날짜와 크기별로 로그를 롤링한다.
- <fileNamePattern>: 로그 파일의 패턴을 지정한다. .gz나 .zip으로 자동 압축할 수 있다.
- <maxFileSize>: 파일당 최대 크기를 설정한다. 로그 크기는 IO 성능에 영향을 미치므로 적절한 크기로 설정하는 것이 좋다 (최대 10MB 권장). 용량 단위는 KB, MB, GB로 지정할 수 있다.
- <maxHistory>: 최대 보관할 로그 파일의 개수를 설정한다. 예를 들어, **maxHistory**가 30이면 30일 동안 로그 파일이 보관됩니다.
- <Filter>: 특정 조건에 따라 로그를 필터링할 수 있다. 예를 들어, 레벨 필터를 추가하여 특정 레벨 이상의 로그만 기록할 수 있다.
자 이제 하나하나 뜯어 살펴보면..
1. 설정 파일의 기본 정보
<?xml version="1.0" encoding="UTF-8"?>
<!-- 60초마다 설정 파일의 변경을 확인하여 변경 시 갱신 -->
<configuration scan="true" scanPeriod="60 seconds">
- scan="true": 설정 파일의 변경을 주기적으로 확인한다.
- scanPeriod="60 seconds": 설정 파일의 변경을 확인하는 주기를 60초로 설정한다.
2. 로그 파일 경로 및 이름 설정
<!-- log file path -->
<property name="LOG_PATH" value="/Users/chaewonkim/Desktop/logs"/>
<!-- log file name -->
<property name="LOG_FILE_NAME" value="logging"/>
<!-- err log file name -->
<property name="ERR_LOG_FILE_NAME" value="err_logging"/>
<!-- pattern -->
<property name="LOG_PATTERN" value="%-5level %d{yy-MM-dd HH:mm:ss}[%thread] [%logger{0}:%line] - %msg%n"/>
- LOG_PATH: 로그 파일이 저장될 경로를 설정한다.
- LOG_FILE_NAME: 일반 로그 파일의 이름을 설정한다.
- ERR_LOG_FILE_NAME: 에러 로그 파일의 이름을 설정한다.
- LOG_PATTERN: 로그 메시지의 포맷을 설정한다.
3. 색상 적용을 위한 설정
<!-- 로그 패턴에 색상 적용 %clr(pattern){color} -->
<conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter" />
- 로그 패턴에 색상을 적용할 수 있도록 변환 규칙을 설정한다.
4. 콘솔 로그 패턴 및 Appender 설정
<!-- Console log pattern with colors -->
<property name="CONSOLE_LOG_PATTERN"
value="[%d{yyyy-MM-dd HH:mm:ss}:%-3relative] %clr(%-5level) %clr(${PID:-}){magenta} %clr(---){faint} %clr([%15.15thread]){faint} %clr(%-40.40logger{36}){cyan} %clr(:){faint} %msg%n"/>
<!-- Console Appender with colors -->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
</encoder>
</appender>
- CONSOLE_LOG_PATTERN: 콘솔에 출력될 로그 메시지의 포맷을 설정한다.
- CONSOLE Appender: 콘솔에 로그를 출력하는 Appender를 설정한다.
콘솔에 요론식으러 나오겠쬬
5. 파일 로그 Appender 설정
<!-- File Appender -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 파일경로 설정 -->
<file>${LOG_PATH}/${LOG_FILE_NAME}.log</file>
<!-- 출력패턴 설정 -->
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${LOG_PATTERN}</pattern>
</encoder>
<!-- Rolling 정책 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- .gz,.zip 등을 넣으면 자동 일자별 로그파일 압축 -->
<fileNamePattern>${LOG_PATH}/${LOG_FILE_NAME}.%d{yyyy-MM-dd}_%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<!-- 파일당 최고 용량 kb, mb, gb -->
<maxFileSize>10MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!-- 일자별 로그파일 최대 보관주기(~일), 해당 설정일 이상된 파일은 자동으로 제거 -->
<maxHistory>30</maxHistory>
</rollingPolicy>
</appender>
- FILE Appender: 파일에 로그를 기록하는 Appender를 설정한다.
- file: 로그 파일 경로 및 이름을 설정한다.
- encoder: 로그 메시지의 포맷을 설정한다.
- rollingPolicy: 로그 파일의 롤링 정책을 설정한다.
- fileNamePattern: 로그 파일의 이름 패턴을 설정한다.
- maxFileSize: 로그 파일 하나의 최대 크기를 설정한다.
- maxHistory: 보관할 로그 파일의 최대 개수를 설정한다.
6. 에러 로그 Appender 설정
<!-- 에러의 경우 파일에 로그 처리 -->
<appender name="Error" class="ch.qos.logback.core.rolling.RollingFileAppender">
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>error</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<file>${LOG_PATH}/${ERR_LOG_FILE_NAME}.log</file>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${LOG_PATTERN}</pattern>
</encoder>
<!-- Rolling 정책 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- .gz,.zip 등을 넣으면 자동 일자별 로그파일 압축 -->
<fileNamePattern>${LOG_PATH}/${ERR_LOG_FILE_NAME}.%d{yyyy-MM-dd}_%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<!-- 파일당 최고 용량 kb, mb, gb -->
<maxFileSize>10MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!-- 일자별 로그파일 최대 보관주기(~일), 해당 설정일 이상된 파일은 자동으로 제거 -->
<maxHistory>60</maxHistory>
</rollingPolicy>
</appender>
- Error Appender: 에러 로그만 기록하는 파일 Appender를 설정한다.
- filter: 로그 레벨이 **error**인 경우에만 로그를 기록하도록 필터를 설정한다.
- file: 에러 로그 파일 경로 및 이름을 설정한다.
- encoder: 로그 메시지의 포맷을 설정한다.
- rollingPolicy: 에러 로그 파일의 롤링 정책을 설정한다.
- fileNamePattern: 에러 로그 파일의 이름 패턴을 설정한다.
- maxFileSize: 에러 로그 파일 하나의 최대 크기를 설정한다.
- maxHistory: 보관할 에러 로그 파일의 최대 개수를 설정한다.
7. 루트 로거 설정
<!-- root레벨 설정 -->
<root level="debug">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="FILE"/>
<appender-ref ref="Error"/>
</root>
- root 로거: 전체 애플리케이션에 대한 기본 로거 설정이다.
- level="debug": 기본 로그 레벨을 **debug**로 설정한다.
- appender-ref: 로그를 기록할 Appender들을 지정한다.
8. 특정 패키지 로깅 레벨 설정
<!-- 특정패키지 로깅레벨 설정 -->
<logger name="org.apache.ibatis" level="debug" additivity="false">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="FILE"/>
<appender-ref ref="Error"/>
</logger>
- logger: 특정 패키지(org.apache.ibatis)에 대한 로거 설정이다.
- level="debug": 해당 패키지의 로그 레벨을 **debug**로 설정한다.
- additivity="false": 부모 로거로 로그가 전파되지 않도록 설정한다.
- appender-ref: 로그를 기록할 Appender들을 지정한다.
'Spring' 카테고리의 다른 글
[SPRING] Hibernate 지연 로딩으로 인한 JSON 직렬화 오류 해결하기 (0) | 2024.06.07 |
---|---|
[SPRING] 로깅에 AOP 적용해보기 (0) | 2024.06.01 |
스프링 키워드 모음 #4 (1) | 2024.05.07 |
스프링 키워드 모음 #3 (0) | 2024.04.26 |
[SPRING]자바 ORM 표준 JPA 프로그래밍 섹션4 (엔티티 매핑) (0) | 2024.04.25 |
- Total
- Today
- Yesterday
- 스프링 북마크
- 파이썬
- 북마크
- 스프링
- 웹MVC
- 웹 MVC
- 로그아웃
- 회원탈퇴
- 자바
- 스프링부트
- 로깅
- 프론트엔드
- SQL
- 인텔리제이
- SQLD
- 스프링 커뮤니티
- JPA
- 비영속
- 백준 파이썬
- 자바 스프링
- 준영속
- 다이나믹 프로그래밍
- elasticsearch
- 커뮤니티
- EnumType.ORDINAL
- SQL 레벨업
- 지연로딩
- 영속
- DP
- 백준
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 |