스프링 전체흐름
1. Server Startup:
- When you start your Spring Boot application (or deploy it to a servlet container like Tomcat), the server begins its initialization process.
2. Spring Boot Application Initialization:
- SpringApplication.run(): This method is called in your main() method, which starts the entire Spring application.
- Spring Boot Auto-Configuration: Spring Boot auto-configures the application context based on the classpath settings, other beans, and various property settings.
3. WebApplicationContext Initialization:
- WebApplicationContext Creation: A specialized version of ApplicationContext, the WebApplicationContext is created if your application is a web application.
- All configurations, whether they pertain to security, MVC, data, or any other aspect, are ultimately registered within this WebApplicationContext.
- Bean Definitions Loading: During this phase, Spring scans your application for bean definitions (components, services, repositories, controllers, and configuration classes).
- Security Configuration: As part of the bean initialization process, security configurations defined in classes annotated with @EnableWebSecurity or @Configuration are also loaded and processed.
- Filter Chain Setup: As part of the Security Configuration, Spring sets up a chain of security filters
4. DispatcherServlet Initialization:
- DispatcherServlet Bean Creation: The DispatcherServlet is a special Servlet in Spring that acts as the front controller, handling all incoming HTTP requests.
- Mapping to URL Patterns: The DispatcherServlet is typically mapped to the "/" URL pattern, meaning it handles all requests coming to the application.
- Loading Handler Mappings and Other Beans: The DispatcherServlet loads handler mappings, view resolvers, and other necessary components from the WebApplicationContext.
5. Request Handling:
- Server Receives HTTP Request: When a client sends an HTTP request, the server receives it and passes it to the DispatcherServlet.
- Filter Chain Execution: Before the request reaches the DispatcherServlet, it passes through the filter chain configured during the Security Configuration phase.
- DispatcherServlet Processing: After passing through the filters, the request reaches the DispatcherServlet.
스프링 MVC - 필터, 인터셉트
개념설명
웹상에서 흐르는 데이터에 공통적인 처리를 할때 필요한 것이 필터와 인터셉트이다.
필터
- 스프링 외부의 서블릿에서 제공하는 공통처리기능, dispatcher로 가기전의 client의 불필요한 request(해킹 등)를 걸러주는 역할
- 스프링 내 요청이 들어오기 전과 스프링 요청이 나갈때 처리가능
- 조금더 low-level 처리가 가능
인터셉터
- 스프링에서 제공하는 공통처리 기능
- dispatcher에서 handler mapping이 완료된 후 controller로 향하는 데이터와 controller로부터 나오는 데이터가 특정조건에 만족한다면, 특정처리가 가능하다. 하여, 실제 매핑된 Handler 정보 확인가능(어떤 것이 실제 내 요청을 처리하는지도 확인 가능)
- 조금 더 상세한 조건식과 세부적인 스펙(pre, post, after)를 통해서 구체적인 시점에 구체적인 동작가능
- AOP와 비교한다면 AOP는 좀더 java code( 패키지, annotation, method명 등)에 대한 처리를, 인터셉터와 필터는 web관련 조건에 따라(url주소 protocol 등)처리를 한다는 점에서 차이가 있다.
- AOP는 인터셉터보다 더 구체적인 조건 (애노테이션, 파라미터, 주소 등)과 동작위치 (afterThrowing 등)을 갖음
사용설명
필터사용 - filter은 서블릿 기능으로 스프링과 무관하게 동작할 수도 있지만 스프링 빈으로 등록할시 여러가지 이점이 있음. 그러므로 component로 등록한다. filter라는 인터페이스를 구현하여 자체적으로 클래스를 만들고 dofilter를 정의하여 필터링 기능을 생성한다.
필터셋등록 - 그리고 filter는 보통 복수의 필터가 있기에 , configuration이라는 별도의 class를 만들고 registerfilter라는 메소드를 생성 하고 반환타입으로 filterregisterationbean이라는 set형식으로 filter들을 set에 등록하게 끔 한다. filterregisterationbean으로 필터가 동작할 url이나 필터의 순서를 지정가능함.
인터셉트는 handlerintercept라는 인터페이스를 구현하여 만들고 prehandle(handler처리전) posthandle(hadler응답성공후) aftercompletion( handler응답성공무관,항상). 각 메소드 들은 parameter로 request, response, handler, modelandview 등을 갖는다. 각각 return true를 해주면 method들이 순서대로 실행된다. 인터셉터는 조금더 다양한 정보로, 구체적인 정보로 동작은 해줄 수 있음. filter은 요즘 잘 안쓰면서 인터셉트가 더 잘쓰이는 추세인것같음.
인터셉트를 등록하기 위해서는 WebMvcConfigurer라는 인터페이스를 구현하면 편리하게 등록할 수 있다. filter를 담고있는 configuration클래스를 구현체로 사용해서 addinterceptors 메소드를 구현하여 인터셉터의 순서, 포함할 url, 제외할 url등을 설정하면된다. WebMvcConfigurer의 메소드들은 자동적으로 bean으로 등록되도록 구현되어있다. ( 필터의 경우 spring mvc가아닌 서블릿의 개체이기때문에 별도로 서블릿으로부터 filterregisterationbean을 끌어와서 구현한 것임. )
CleanArchitecture : Division of Layer
Client:
- 프론트엔드 모듈을 의미하며, 사용자 인터페이스를 통해 서버와 상호작용합니다.
- 사용자가 입력한 데이터를 서버로 보내고, 서버로부터 받은 데이터를 화면에 표시합니다.
DTO (Data Transfer Object):
- 계층 간 데이터 교환을 위한 객체입니다.
- 주로 클라이언트에서 서버까지 데이터를 전달할 때 사용됩니다.
- DTO는 범용으로 쓰지 않고 개별적인 용도로 써야 오류가 나지 않는다. 메소드의 필요에 따라 1:1로 만들것. (Controller DTO는 Controller에서만, Service DTO는 Service에서만)
- Service DTO는 Entity에서 일부 데이터를 추출하여 Web Layer에서 필요로 할만한 데이터 전송에 최적화된 형태로 설계된다.
- 반면 Request DTO는 Web의 요구에 따라서 변경이 잦으므로, Service Layer에 침투되지 않도록 분리한다. 필요시에 Service DTO로 변환하여 전달한다.
Controller:
- 클라이언트로부터 HTTP 요청을 받아들이는 역할을 합니다.
- 요청을 적절한 서비스 계층으로 전달하고, 서비스로부터 받은 결과를 클라이언트에 반환합니다.
- 주로 @Controller나 @RestController 애노테이션을 사용하여 정의합니다.
- 예외처리 : 우선, Contoller별로 custon excpetion Handler로 1차 처리 후, Global Handler을 통해서 전체 예외처리
Service:
- 비즈니스 로직을 처리하는 계층입니다.
- Controller로부터 받은 DTO를 사용하여 필요한 로직을 수행하고, 이를 사용하여 Entity를 생성하거나 업데이트합니다. 로직이 다 수행되었다면 Controller에 응답을 위해서 return값을 설정하고 주로 동일한 DTO를 쓴다.
- 주로 @Service 애노테이션을 사용하여 정의합니다.
- 예외처리 : 비즈니스 로직은 예외처리까지 포함하는 범위이며 로직의 원자성을 위해서 excpetion은 Service 내에서만 발생하도록 하는 것이 best practice.
Entity (Domain):
- DB의 테이블과 1:1로 대응되는 객체입니다.
- 테이블의 컬럼과 엔티티의 필드가 매핑되며, 여러 엔티티 간의 연관관계(관계형 데이터베이스의 외래키 등)를 정의합니다.
- 주로 @Entity 애노테이션을 사용하여 정의합니다.
Repository:
- DB와 직접 연결되어 CRUD(Create, Read, Update, Delete) 작업을 수행하는 계층입니다.
- Entity에 접근하기 위한 메서드들을 정의하며, Spring Data JPA의 경우 JpaRepository 인터페이스를 상속받아 구현합니다.
- 주로 @Repository 애노테이션을 사용하여 정의합니다.
DAO (Data Access Object):
- 데이터베이스에 접근하는 객체로, 퍼시스턴스 계층이라고도 불립니다.
- 서비스 계층이 DB와 통신할 수 있도록 도와줍니다.
- Spring Data JPA를 사용할 경우, Repository가 DAO의 역할을 합니다.
ServiceImpl, DAOImpl:
- 서비스와 DAO는 인터페이스로 정의되며, 실제 구현 클래스는 Impl 접미사를 붙여서 구현합니다.
- 인터페이스를 통해 의존성을 주입받아 테스트 용이성과 코드의 유연성을 높입니다.
Design Concern
- Seperation between the database architecture(Db Interaction,Entity) from the API(User Interaction, DTO)
- 1. Performance Concerns :
- lazy-loaded
- 2. Transactional Concerns :
- where lazy loading triggers outside of transactional boundaries, causing exceptions like LazyInitializationException.
- 3. Data Safety :
- If entities are exposed directly, any modifications made to the returned entities could inadvertently affect the database once the transaction commits.
- + sensitive info in Entity
- 4. Division of work
- API와 DB에서 요구하는 데이터가 상이할 수 있다. API의 요구에 따라서 ENtity를 수정하는 것은, DB에 영향을 주기에 불가능하고 API요구에 맞도록 DTO를 별도로 만들어주는 것이 올바른 접근이다. 혹시 API의 요구사항 변경이 생겼을때 더욱 유연하게 대응할 수 있음.
- API Stability vs. Database Changes: . Using DTOs allows the database model to evolve without necessarily impacting the API.
- Entity에서 DTO로 넘겨보내기 위해서 DTO 내부구조를 아래와 같이 entity에서 정보를 뽑아서 DTO를 생성하도록 주로함.
- 1. Performance Concerns :
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class AccountDto {
private Long userId;
private String accountNumber;
private Long balance;
private LocalDateTime registeredAt;
private LocalDateTime unregisteredAt;
public static AccountDto fromEntity(Account account) {
return AccountDto.builder().
userId(account.getAccountUser().getId())
.accountNumber(account.getAccountNumber())
.balance(account.getBalance())
.registeredAt(account.getRegisteredAt())
.unregisteredAt(account.getUnregisteredAt()).
build();
'개발기술 > Spring' 카테고리의 다른 글
Spring Security - JWT 인증방식 구현 (0) | 2024.09.03 |
---|---|
Spring 동시성이슈 해결 (0) | 2024.07.30 |
스프링 MVC (0) | 2024.07.18 |
스프링 부가기능 (Resource, AOP, 유효성검증, 데이터바인딩,spel) (0) | 2024.07.17 |
스프링 도입배경 - 객체지향적 코드개선 (0) | 2024.05.17 |