
* 스프링 예외 처리 방법 (우선 순위별로 작성)
*
* 1. 메서드에서 직접 처리하는 방법 (try-catch, throws)
*
* 2. 컨트롤러 클래스에서 클래스 단위로 모아서 처리
* (@ExceptionHandler 어노테이션을 지닌 메서드를 해당 클래스에 작성)
*
* 3. 별도 클래스를 만들어 프로젝트 단위로 모아서 처리✔️
* ( @ControllerAdvice 어노테이션을 지닌 클래스를 작성 )
@ControllerAdvice // 전역적 예외처리 활성화 어노테이션 -> 즉, 프로젝트 전체를 보겠다는 의미
// 프로젝트 전체 컨트롤러에서 발생하는 예외를 한 곳에 모아서 처리하는 역할
// 요청과 응답을 처리하는 컨트롤러임
public class ExceptionController {
// @ExceptionHandler(예외 종류) : 어떤 예외를 다룰건지 작성
// 예외 종류
// SQLException.class - SQL 관련 예외만 처리
// IOException.class - 입출력 관련 예외만 처리
// ..
// NoResourceFoundException : 404
@ExceptionHandler(NoResourceFoaundException.class)
public String notFound() { // 404 오류
return "error/404";
}
}

@ControllerAdvice
public class ExceptionController {
// 프로젝트에서 발생하는 모든 종류의 예외를 500으로 처리
@ExceptionHandler(Exception.class)
public String allExceptionHandler(Model model, Exception e) {
e.printStackTrace();
model.addAttribute("e", e);
return "error/500"; // error/500.html로 이동
}
}

⇒ @Slf4j → lombok에서 제공해주는 log 객체를 생성해주는 어노테이션
스프링은 다른 여러 모듈을 사용함에 있어 별도의 추상화 레이어를 제공하여 특정 기술에 종속되
지 않으면서 다양한 기술 스택을 쉽게 사용할 수 있음
(외부 라이브러리, API 등 외부 기술을 쉽게 이용할 수 있도록 여러 인터페이스, 추상 클래스를
제공)
⇒ 사용하려면 logback 관련 모듈들이 존재해야함

⇒ 기본적으로 내장이 되어있어서 따로 건들게 없다
<configuration scan="true" scanPeriod="60 seconds">
<!-- 1분(60초) 마다 설정 변경 사항을 파악한 후 갱신 -->
<!-- config.properties에 아래 내용 추가
log.config.path(로그 파일 저장 경로)
log.config.fileName(로그 파일 이름)
-->
<!-- 설정 값을 읽어들일 외부 파일 지정 -->
<property resource="config.properties" />
<!-- logback-spring.xml에서 사용할 변수 선언 -->
<property name="logPath" value="${log.config.path}" /> <!-- config.properties에서 얻어온 값 -->
<property name="fileName" value="${log.config.fileName}" /> <!-- config.properties에서 얻어온 값 -->
<property name="maxHistory" value="30" />
<property name="maxFileSize" value="10MB" />
<!--============================ 스프링 부트 기본 로그 설정 ============================ -->
<conversionRule conversionWord="clr"
converterClass="org.springframework.boot.logging.logback.ColorConverter" />
<conversionRule conversionWord="wex"
converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter" />
<conversionRule conversionWord="wEx"
converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter" />
<property name="CONSOLE_LOG_PATTERN"
value="${CONSOLE_LOG_PATTERN:-%clr(%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}}){green} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}" />
<property name="CONSOLE_LOG_CHARSET"
value="${CONSOLE_LOG_CHARSET:-default}" />
<property name="FILE_LOG_PATTERN"
value="${FILE_LOG_PATTERN:-%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}} ${LOG_LEVEL_PATTERN:-%5p} ${PID:- } --- [%t] %-40.40logger{39} : %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}" />
<property name="FILE_LOG_CHARSET"
value="${FILE_LOG_CHARSET:-default}" />
<appender name="CONSOLE"
class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
<charset>${CONSOLE_LOG_CHARSET}</charset>
</encoder>
</appender>
<include
resource="org/springframework/boot/logging/logback/file-appender.xml" />
<logger name="org.apache.catalina.startup.DigesterFactory"
level="ERROR" />
<logger name="org.apache.catalina.util.LifecycleBase"
level="ERROR" />
<logger name="org.apache.coyote.http11.Http11NioProtocol"
level="WARN" />
<logger name="org.apache.sshd.common.util.SecurityUtils"
level="WARN" />
<logger name="org.apache.tomcat.util.net.NioSelectorPool"
level="WARN" />
<logger
name="org.eclipse.jetty.util.component.AbstractLifeCycle"
level="ERROR" />
<logger name="org.hibernate.validator.internal.util.Version"
level="WARN" />
<logger name="org.springframework.boot.actuate.endpoint.jmx"
level="WARN" />
<!--============================ 스프링 부트 기본 로그 설정 ============================ -->
<!-- 로그를 파일로 저장 -->
<appender name="ROLLING"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- Rolling 정책 -->
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<!-- 로그 파일이 저장될 위치, 파일명 패턴 지정 -->
<fileNamePattern>${logPath}${fileName}.%d{yyyy-MM-dd}_%i.log</fileNamePattern>
<!-- 로그파일 최대 보관일 -->
<maxHistory>${maxHistory}</maxHistory>
<!-- 로그 파일당 최고 용량 kb, mb, gb -->
<maxFileSize>${maxFileSize}</maxFileSize>
</rollingPolicy>
<!-- 출력되는 로그의 패턴, 인코딩 -->
<encoder>
<pattern>${FILE_LOG_PATTERN}</pattern>
<charset>${FILE_LOG_CHARSET}</charset>
</encoder>
</appender>
<!-- * 로그 레벨 : TRACE < DEBUG < INFO < WARN < ERROR
(로그 레벨 지정 시 지정된 레벨 +
상위 레벨만 출력됨) -->
<!-- 기본 로그 출력 레벨, 로그 작성 객체(appender) 지정 -->
<root level="INFO">
<appender-ref ref="CONSOLE" />
<appender-ref ref="ROLLING" />
</root>
</configuration>

⇒ C:/log/안에 콘솔에 찍히는 모든 로그가 이어붙이기 되면서 기록이 된다.