spring boot (3)

 

 

 

 

 

Spring MVC에서의 예외 처리

 

 

Spring MVC는 애플리케이션에서 발생할 수 예외를 효율적으로 처리하도록 몇 가지 방법을 제공한다.

 

 

 

➤ @ExceptionHandler를 이용한 Controller 레벨에서의 예외 처리

 

유효성 검증에서 실패했을 때 클라이언트가 전달 받는 Response Body는 애플리케이션에서 예외(Exception)가 발생했을 때, 내부적으로 Spring에서 전송해주는 에러 응답 메시지 중 하나이다.

 

Spring에서 예외는 유효성 검증이 실패했을 때 등 문제가 발생하면 실패를 하나의 예외로 간주하여 이 예외를 던져서 (throw) 예외 처리를 유도한다.

 

 

▶️ @Slf4J

Simple Logging Facade for Java

Logging

  • 개발 중이나 완료 후 발생할 수 있는 오류에 대해 디버깅하거나 운영중인 프로그램 상태를 모니터링 하기 위해 필요한 정보(로그)를 기록하는것

 

Logback과 같은 백엔드 Logging Framework의 facade pattern

 

https://www.slf4j.org/

 

SLF4J

Simple Logging Facade for Java (SLF4J) The Simple Logging Facade for Java (SLF4J) serves as a simple facade or abstraction for various logging frameworks (e.g. java.util.logging, logback, log4j) allowing the end user to plug in the desired logging framewor

www.slf4j.org

 

 

▶️ @ExceptionHandler

예외 처리 메서드로 선언

 

 

▶️ .getBindingResult().getFieldErrors()

에러 정보를 확인할 수 있다

 

 

➤ ErrorResponse 클래스 만들기

 

DTO 클래스 유효성 검증 실패 시

실패한 필드에 대한 Error 정보만 담아서 응답으로 전송하기 위한 클래스

 

Response Body의 JSON 응답 객체가 배열이다.

✅ 배열인 이유?

DTO 클래스에서 유효성 검증에 실패하는 멤버변수가 하나 이상이 될 수 있기 때문에 유효성 검증 실패 에러 역시 하나 이상이 될 수 있다.

-> 유효성 검증에 실패한 필드의 에러 정보를 담기 위해서 List 객체를 이용

FieldError라는 별도의 static class를 ErrorResponse 클래스의 안에 정의한다.

FieldError클래스는 ErrorResponse 클래스의 내부(Inner) 클래스라고 부르기 보다는

ErrorResponse 클래스의 static 멤버 클래스라고 부르는 것이 적절하다.

필요한 정보들만 골라서 Response body에 담을 수 있다.

 

 

 

➤ @ExceptionHandler 의 단점

 

1. 코드 중복이 발생한다.

각각의 Controller 클래스에서 @ExceptionHandler 애너테이션을 사용해서 유효성 검증 실패에 대한 에러 처리를 해야한다.

 

2. 예외 마다 에러 처리 핸들러 메서드가 늘어난다.

Controller 클래스 내에서 발생할 수 있는 예외(Exception)은 한가지만 있는게 아니다.

그러면 각각의 예외 마다 @ExceptionHandler를 추가한 에러 처리 핸들러 메서드가 늘어나게 된다.

 

 

https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#mvc-ann-exceptionhandler

 

Web on Servlet Stack

Spring Web MVC is the original web framework built on the Servlet API and has been included in the Spring Framework from the very beginning. The formal name, “Spring Web MVC,” comes from the name of its source module (spring-webmvc), but it is more com

docs.spring.io

 

 

 

 

❑ @RestControllerAdvice 를 이용한 예외 처리

 

➤ 예외 처리 공통화

 

특정 클래스에 @RestControllerAdvice 애너테이션을 추가하면 여러개의 Controller 클래스에서 @ExceptionHandler, @InitBinder, @ModelAttribute가 추가된 메서드를 공유해서 사용할 수 있다.

 

 

@RestControllerAdvice 애너테이션을 추가한 클래스

➡️ 예외 처리를 모든 Controller에 공통화 할 수 있게 된다.

 

 

▶️ @InitBinder, @ModelAttribute 애너테이션

 

JSP, Thymeleaf 같은 서버 사이드 렌더링(SSR, Server Side Rendering) 방식에서 주로 사용된다.

 

 

 

Controller 클래스에서 @ExceptionHandler 로직 제거

-> ExceptionAdvice 클래스 정의 (@RestControllerAdvice)

-> 모든 Controller의 에러를 동시에 처리할 수 있게 된다.(AOP, 공통 관심사)

 

에러를 정보를 전달하는 객체(Error Response)와 에러 정보를 추출하고 가공하는 static 멤버 클래스로 역할을 분리한다.

 

기능이 늘어남에 따라 Error Response 클래스의 구현 복잡도가 늘어나지만

에러 유형에 따른 에러 정보 생성 역할을 분리함으로써 사용자 입장에서 한층 더 편리해진다.

 

 

▶️ of() 메서드

  • 네이밍 컨벤션(Naming Convention)
  • 객체 생성시 어떤 값들의(of~) 객체를 생성한다는 의미
  • 객체.of(원하는 값)

 

ExceptionAdvice 클래스에서 ErrorResponse 클래스에 of를 사용해서 에러 객체 전달한다.

ResponseEntity 대신 ErrorResponse 객체 그대로 반환하고

@ResponseStatus 애너테이션을 이용해서 attribute로 HTTP Status 전달한다.

 

 

※ @RestControllerAdvice vs @ControllerAdvice

 

SpringMVC 4.3버전 이후부터 @RestControllerAdvice 지원

@RestControllerAdvice = @ControllerAdvice + @ResponseBody

JSON 형식의 데이터를 Response Body로 전송하기 위해서 ResponseEntity로 데이터를 래핑할 필요가 없다.

 

 

 

 

읽어주셔서 감사합니다. 좋은하루 되세요 🤩

 

 

 

 

 

 

 

❑ Service 계층

 

 

Spring MVC layer architecture

 

 

➤ DI를 통한 서비스 계층과 API 계층 연동

 

✔️ API 계층과 서비스 계층을 연동한다?

API 계층에서 구현한 Controller 클래스가 서비스 계층의 Service 클래스와 메서드 호출을 통해 서로 상호작용한다.

 

 

▶️ Service의 의미

 

애플리케이션에서 Service는 도메인 업무 영역을 구현하는 비즈니스 로직과 관련이 있다.

Serivce는 쉽게 말해 비즈니스 로직을 처리하기 위한 Service 클래스이다.

애플리케이션의 서비스 계층은 대부분 도메인 모델을 포함하고 있다.

도메인 모델은 빈약한 모델(anemic domain model)풍부한 도메인 모델(rich domain model)로 구분할 수 있다.

이러한 도메인 모델은 DDD(Domain Driven Design, 도메인 주도 설계)와 관련있다.

(DDD는 현업에서 클래스 설계 경험이 풍부해야 제대로 사용할 수 있다.)

 

 

 

➤ 도메인 엔티티(Domain Entity) 클래스

 

서비스 계층에서 데이터 엑세스 계층과 연동하면서 비즈니스 로직을 처리하기 위해 필요한 데이터를 담는 클래스

보통 리소스 이름으로 만든다. ex) Member, Coffee, Order

 

 

➤ 도메인 엔티티 클래스에 붙는 애너테이션

 

lombok 라이브러리에서 제공한다.

 

@Getter / @Setter

  • getter/setter 메서드를 일일이 작성할 필요 없도록 추가해준다.

 

@AllArgsConstructor

  • 클래스에 존재하는 모든 필드를 매개변수로 갖는 생성자를 자동으로 생성해준다.
  • 만약에 필드 중에 @NotNull 애너테이션이 붙어 있다면 해당 부분은 생성자 내에서 null-check로직을 자동으로 생성한다.

 

@NoArgsConstructor

  • 매개변수가 없는 생성자를 생성한다.
  • 필드에 final 키워드가 있을 경우 초기화 할 수 없기 때문에 에러가 발생한다.
  • 필드에 @NotNull 같은 제약조건이 설정되어 있을 경우, 생성자 내 null-check 로직이 생성되지 않는다.

 

@RequiredArgsConstructor

  • 초기화 되지 않은 모든 final 필드, @NotNull이 설정되 있는 필드들에 대한 생성자를 자동으로 생성해준다.

 

 

 

※ lombok 라이브러리의 더 많은 애너테이션

https://projectlombok.org/features/all

 

Stable

 

projectlombok.org

 

 

 

➤ DI 주입

 

Service 클래스에 @Service 애너테이션 추가해서 Spring Bean으로 등록해주고

Controller 클래스와 Service 클래스간에 느슨한 결합(Losse Coupling)을 위해 DI를 주입해준다.

(Controller는 @RestController 로 이미 Spring Container에 등록되어 있다.)

 

※ 일반적으로 생성자가 하나일 경우에는 @Autowired 를 붙이지 않아도 Spring이 알아서 DI를 적용한다.

하지만 생성자가 하나 이상일 경우, DI를 적용하기 위해선 반드시 @Autowired를 붙여야 한다!

 

 

 

 

❑ Mapper(매퍼)

 

 

➤ Mapper를 이용한 DTO 클래스와 Entity(엔티티) 클래스 매핑

 

▶️ Mapper를 사용하지 않을 경우

 

  • Controller의 핸들러 메서드가 DTO 클래스를 엔티티 클래스로 변환 하는 작업까지 하게 되어 여러 역할을 가지게 된다.
  • 서비스 계층인 엔티티(Entity) 클래스 객체를 클라이언트의 응답으로 전송(API 계층의 역할)해서 계층 간의 역할 분리가 이루어지지 않는다.

 

 

▶️ Mapper 사용법

 

  • 클래스를 Spring Bean으로 등록하기 위해 @Component 애너테이션을 추가한다.
  • 등록된 빈은 Controller에서 사용된다.

 

 

➤ MapStruct를 이용한 Mapper 자동 생성

 

Mapper를 수작업으로 작성하는 것은 비효율 적이다.

Mapper를 자동으로 만들 수 있는 MapStruct을 이용하면 편리하다.

DTO클래스 처럼 Java Bean 규약을 지키는 객체들 간의 변환 기능을 제공하는 매퍼(Mapper) 구현 클래스를 자동으로 생성해주는 코드 자동 생성기이다.

 

MapStruct를 사용하려면 먼저 의존 라이브러리를 추가 해주어야 한다.

Gradle

build.gradle파일 dependencies에 아래 코드 추가한다.

dependencies {

implementation 'org.mapstruct:mapstruct:1.4.2.Final'

annotationProcessor 'org.mapstruct:mapstruct-processor:1.4.2.Final'

}

 

 

Mapper 인터페이스 추가하고 인터페이스에 @Mapper 애너테이션 추가한다.

-> 인터페이스가 MapStruct의 매퍼 인터페이스로 정의된 것임을 알려준다.

attribute로 componentModel = “spring” 지정해서 Spring Bean으로 등록한다.

MapStruct가 Mapper 인터페이스를 기반으로 매퍼(Mapper) 구현 클래스를 자동으로 생성해준다!

Gradle에 build task를 실행하면 자동으로 생성된다.

intelliJ에서 build task 실행하기

Gradle 탭 -> 해당 프로젝트 명 -> Tasks 디렉토리 -> build 디렉토리 -> build 더블클릭

 

 

 

 

읽어주셔서 감사합니다.

오개념에 대한 지적은 늘 환영입니다. 😆

 

 

 

 

❑ Architecture (아키텍처)

 

 

➤ 아키텍처란?

 

▶️ Architecture?

아키텍처는 건축 분야에서 유래된 용어로 건축물을 짓는데 있어 청사진 같은 역할을 한다.

쉽게 생각하면 건축의 조감도이다.

 

컴퓨터 시스템에서도 시스템을 만들기 전에 이해 당사자들이 모여서 시스템의 구조를 알기 쉬운 도형이나 이미지로 만들어놓는다.

 

 

 

➤ 컴퓨터 시스템에서 아키텍처 유형

 

▶️ 시스템 아키텍처

하드웨어 + 소프트웨어를 모두 포함하는 시스템의 전체적인 구성을 큰그림으로 표현한 것

시스템의 구성 및 동작원리를 나타낸다.

시스템의 구성요소에 대해 설계 및 구현을 지원하는 수준으로 자세히 기술

구성 요소 및 시스템 외부 환경과의 관계 묘사

요구 사양과 시스템의 전체 수명 주기를 고려

시스템의 전체적인 최적화가 목표

 

 

참고 사이트

https://www.edrawsoft.com/kr/program-review/architecture-drawing-program.html

 

아키텍처 구성도 쉽게 그리는 프로그램?

아키텍처란 건축학이라는 의미 외에도 컴퓨터를 기능면에서 본 구성 방식을 의미하기도 합니다. 아키텍처 구성도를 그리는 프로그램을 사용하여 간단한 아키텍처 구성도를 직접 그려보도록 하

www.edrawsoft.com

 

 

 

▶️ 소프트웨어 아키텍처

 

하드웨어를 제외한 컴퓨터 내의 모든 프로그램을 포괄하는 소프트웨어의 구성을 큰 그림으로 표현한 것

 

소프트웨어 아키텍처의 예시

Java 플랫폼 아키텍처

 

Java SE 아키텍처 (출처: https://docs.oracle.com/javase/1.5.0/docs/index.html)

 

 

▶️ 애플리케이션 아키텍처

 

애플리케이션은 소프트웨어의 종류 중 하나이다.

데스크탑이나 스마트폰에서 사용하는 응용 프로그램이다.

넓게는 클라이언트의 요청을 처리하는 서버 애플리케이션을 의미한다.

 

애플리케이션 아키텍처 중에 앞으로 자주 볼 웹 애플리케이션 아키텍처인 계층형 아키텍처(N-Tier) 정도는 기억해두자.

 

계층형 아키텍처

 

API 계층(API Layer)

클라이언트의 요청을 받아들이고 응답하는 계층

일반적으로 표현 계층(Presentation Layer)라고 불림

REST API를 제공하는 애플리케이션의 경우엔 API 계층이라고 표현한다.

 

 

서비스 계층(Service Layer)

API 계층에서 전달받은 요청을 업무 도메인의 요구 사항에 맞게 처리하는 계층

Domain(Business) 계층이라고도 불림

서비스의 핵심 로직이 포함되어 있음

API 계층에서 전달받은 데이터의 유효성(Validation) 검사

어떤 Data Access를 선택할지 결정

 

※ 도메인(Domain)이란?

애플리케이션 개발에서의 도메인은 비즈니스적인 어떤 업무 영역과 관련이 있다.

예를 들어 배달 주문 앱을 만들어야 할때 고객과, 음식점, 배달원, 카드사 또는 은행 등 배달 주문 앱을 구현하기 위해 필요한 업무들을 자세히 알아야 높은 퀄리티의 애플리케이션을 만들 수 있다.

도메인 지식(Domain Knowledge) 들을 서비스 계층에서 비즈니스 로직으로 구현해야 한다.

예시) 고객이 주문을 하는 과정, 주문 받은 음식을 음식점에 전달하는 과정, 배달 기사를 매칭하는 과정 등

 

 

데이터 액세스 계층(Data Access Layer)

서비스 계층에서 처리된 데이터를 데이터베이스같은 데이터 저장소에 저장하기 위한 계층

 

 

 

➤ 아키텍처로 보는 Spring Framework 모듈(Module) 구성

 

아래는 스프링에서 제공하는 기능들을 나타낸 그림이다.

 

Spring Framework 모듈 아키텍처 (출처: Spring Framework Reference)

 

Spring Framework에서는 약 20개의 모듈을 통해 다양한 기능을 제공

 

▶️ 모듈(Module) 이란?

Java에서 일반적으로 지원되는 여러가지 기능들을 목적에 맞게 그룹화하여 묶어 놓은 것

모듈은 Java의 패키지 단위로 묶여 있고, 이 패키지 안에는 관련 기능을 제공하기 위한 클래스들이 포함되어 있다.

일반적인 모듈은 재사용이 가능하도록 라이브러리 형태로 제공되는 경우가 많다.

 

 

 

❑ Spring Boot 란?

 

➤ Spring Boot 란 무엇일까?

 

Spring Framework는 enterprise 애플리케이션을 개발하기 위한 핵심 기능을 제공하는 Spring Project중 하나이다.

Spring의 복잡한 설정을 해결하기 위해 나온 것이 Spring Boot이다.

 

 

➤ Spring Boot를 사용해야하는 이유?

 

1. XML 기반의 복잡한 설계 방식 지양

2. 의존 라이브러리의 자동 관리

3. 애플리케이션 설정의 자동 구성

4. 프로덕션급 애플리케이션의 손쉬운 빌드

5. 내장된 WAS를 통한 손쉬운 배포

 

지금은 아직 의미가 와닿게 이해되진 않지만 Spring을 계속 공부하다보면 언젠가 의미를 깨닫는 날이 오겠지..?

 

 

 

※ 심화학습

 

아파치 톰캣(Apache Tomcat) 이외에 Spring Boot에서 사용할 수 있는 서블릿 컨테이너(WAS)에는 어떤 것들이 있을까?

 

▶️ Tomcat

자바에서 가장 널리 사용되는 WAS

Spring Boot에서 기본 내장된 WAS

 

▶️ Jetty (추억의 제티 음료가 생각난다..)

경량 WAS이다.

적은 메모리를 사용하고 속도도 빠르지만

그만큼 대규모 트래픽엔 취약하다.

 

▶️ Undertow

유연한 고성능 웹서버

대규모 트래픽으로부터 톰캣보다 안정적

 

▶️ Netty (얘는 뭘까 Jetty 친구인가..?)

 

 

 

 

읽어주셔서 감사합니다 🤗

스프링 어려운데.. 동기분들 모두 힘내세요..!

오개념에 대한 지적은 언제나 환영입니다~

 

1