2023-02-14-TIL
2023-02-14-TIL
Today I Learned
Custom Exception vs Runtime Exception
표준 예외(IllegalArgumentException, IllegalStateException)를 재사용할지, 사용자 정의 예외를 만들지는 결국 예외가 담아야 할 정보의 양으로 정한다. 메시지 하나로 충분하면 표준 예외가 더 읽기 쉽고, 같은 예외가 여러 곳에서 상세 정보(에러 코드, 관련 값)와 함께 던져진다면 사용자 정의 예외로 그 정보를 한 클래스에 모으는 편이 낫다.
- https://tecoble.techcourse.co.kr/post/2020-08-17-custom-exception/
Checked Exception vs Unchecked Exception
checked exception은 컴파일러가 처리나 선언을 강제하고, unchecked exception(RuntimeException 계열)은 강제하지 않는다. 호출자가 복구할 수 있는 상황이면 checked, 프로그래밍 오류처럼 복구할 수 없으면 unchecked로 만든다는 것이 Java Tutorial의 기준이다.
- https://bcp0109.tistory.com/303
Error Handling for REST with Spring
Baeldung의 “Error Handling for REST with Spring”은 스프링이 제공하는 방법을 순서대로 정리한다.
- 컨트롤러 안의
@ExceptionHandler: 그 컨트롤러에서 난 예외만 처리한다. @ControllerAdvice의@ExceptionHandler: 여러 컨트롤러의 예외를 전역으로 처리한다. 지금 가장 많이 쓰는 방식이다.- 예외 클래스에
@ResponseStatus: 예외를 상태 코드에 고정해서 매핑한다. ResponseStatusException: Spring 5에서 추가된RuntimeException으로, 예외 클래스를 만들지 않고 던지는 지점에서 상태 코드와 이유를 지정한다.@ResponseStatus의 프로그래밍 방식 대안이다.HandlerExceptionResolver: 위 방법들을 구현하는 하위 메커니즘이고, 직접 구현해 등록할 수도 있다.
전역 핸들러에서는 예외 타입별로 에러 코드와 메시지를 담은 공통 응답 객체를 만들고, 예상하지 못한 예외는 마지막에 Exception 핸들러로 받아 500으로 응답한다.
- https://www.baeldung.com/exception-handling-for-rest-with-spring
- https://www.baeldung.com/spring-response-status-exception
- https://naiyer.dev/post/2020/07/26/error-handling-for-a-spring-based-rest-api/
- https://cheese10yun.github.io/spring-guide-exception/
- https://mangkyu.tistory.com/204
- https://wookim789.tistory.com/62
- https://luvstudy.tistory.com/50
- https://www.digitalocean.com/community/tutorials/spring-mvc-exception-handling-controlleradvice-exceptionhandler-handlerexceptionresolver
Response Entity vs Custom Response
ResponseEntity는 HttpEntity를 확장해 상태 코드를 더한 클래스로, 상태 코드, 헤더, 본문을 모두 직접 정해 응답할 수 있다. @ResponseBody(또는 @RestController)만 쓰면 반환 객체가 HttpMessageConverter로 본문에 직렬화되고 상태 코드는 기본값이나 @ResponseStatus를 따른다.
Custom Response는 { "code": ..., "message": ..., "data": ... }처럼 모든 응답을 감싸는 공통 래퍼를 말한다. 클라이언트가 응답 형식을 하나로 처리할 수 있다는 장점이 있지만, HTTP 상태 코드가 이미 전달하는 정보를 본문에 중복해서 담게 되고 성공 응답까지 한 겹 감싸야 한다. 그래서 성공 응답은 ResponseEntity나 객체 그대로 반환하고, 에러 응답만 공통 형식으로 맞추는 절충도 흔하다.
- https://www.baeldung.com/spring-response-entity
- https://medium.com/codestorm/custom-json-response-with-responseentity-in-spring-boot-b09e87ab1f0a
- https://velog.io/@_koiil/Custom-Response%EC%9D%98-%ED%95%84%EC%9A%94%EC%84%B1
- https://tecoble.techcourse.co.kr/post/2021-05-10-response-entity/
- https://stackoverflow.com/questions/26549379/when-use-responseentityt-and-restcontroller-for-spring-restful-applications
- https://zetcode.com/springboot/responseentity/
- https://www.springcloud.io/post/2022-02/responseentity-tips/#gsc.tab=0
- https://www.javaguides.net/2019/08/spring-responseentity-using-responseentity-in-spring-application.html
- https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/http/ResponseEntity.html
- https://a1010100z.tistory.com/106
- https://devlog-wjdrbs96.tistory.com/182
Logging Thread ID
여러 개의 서버 인스턴스로 나누어져 있을 때, 통합해서 로그를 보려면 Thread ID가 유용하다. MSA 구조에서는 Span ID, Transaction ID로 엮어서 일련의 연쇄적인 요청 수행의 과정을 볼 수 있지만, MSA 구조가 아니라면 Thread ID로도 충분하다.
한 가지 주의할 점은 스레드는 요청이 끝나면 풀로 돌아가 다른 요청을 처리한다는 것이다. 같은 스레드 이름이 여러 요청에 걸쳐 반복되므로, 요청 단위로 묶으려면 요청마다 고유한 ID를 붙이는 편이 확실하다. Logback 문서는 이를 위해 SLF4J의 MDC(Mapped Diagnostic Context)를 소개한다. 클라이언트마다 로거를 따로 만드는 대신, 요청을 처리하는 동안 MDC에 요청 ID 같은 문맥 정보를 넣어 두면 그 스레드에서 남기는 모든 로그에 찍을 수 있다. 필터에서 요청 시작 시 값을 넣고 끝날 때 지우면 된다.
RestTemplate vs …
RestTemplate은 스프링에서 기본적으로 지원해주는 HTTP 요청 템플릿이다. 하지만 팀원 중 한 명은 이것이 그렇게 좋지 않다는 의견이다. 오히려 Feign Client, Retrofit 같은 것들이 더 깔끔하다고 말한다. 너무 당연하게도 아무 생각없이 RestTemplate을 사용해왔는데, 새로운 시각을 얻게 되었다.
Spring Framework 6.0 Javadoc에는 RestTemplate이 5.0부터 유지보수 모드이며 사소한 변경 요청과 버그 수정만 받는다고 적혀 있고, 동기, 비동기, 스트리밍을 모두 지원하는 WebClient를 고려하라고 안내한다. 다른 선택지는 성격이 다르다.
WebClient: Spring 5에서 추가된 논블로킹, 리액티브 클라이언트다.block()으로 동기식으로도 쓸 수 있다.- OpenFeign: 인터페이스에 애너테이션만 선언하면 구현체를 런타임에 만들어 주는 선언적 클라이언트다. 기본적으로 블로킹이고, Spring Cloud OpenFeign으로 스프링에 통합된다.
- Retrofit: Square가 만든 선언적 HTTP 클라이언트로, Feign과 비슷하게 인터페이스로 API를 정의한다.
Feign과 Retrofit이 깔끔하게 느껴지는 이유는 URL 조립과 응답 변환 코드가 사라지고, 호출하는 API가 인터페이스 한 장에 정리되기 때문이다.
- https://www.baeldung.com/spring-webclient-resttemplate
- https://digitalbourgeois.tistory.com/56
- https://www.baeldung.com/spring-boot-feignclient-vs-webclient
- https://medium.com/@MonkeyPatch/feign-vs-retrofit-1-getting-started-1298b57a254
- https://www.javacodemonk.com/retrofit-vs-feign-for-server-side-d7f199c4
- https://sylvainleroy.com/2018/04/13/rest-http-client-feign-vs-retrofit-2/
댓글
아직 댓글이 없습니다