Spring Boot 계층형 아키텍처 패턴
앞서 Spring Boot의 계층형 아키텍처 패턴에 대해서 다시 짚고 넘어가자 !
위의 그림은 아래와 같이 정리할 수 있는데
1. 표현 계층 [@Controller] : Clinet의 요청을 받아 app계층에 처리를 위임하고, 최종 결과를 Client에게 전달함
2. 애플리케이션 계층 [@Service] : 애플리케이션을 위한 다양한 비지니스 로직들이 위치하고, 데이터가 처리된다.
3. 데이터접근 계층 [@Repository] : DB에 접근하여 CURD를 수행하는 역할
Spring Service 계층은 시스템의 핵심 비지니스 로직을 구현하는 계층으로 , 데이터를 저장하고, 연산 처리, 사용자에게 표시할 내용 선택 등 실제 서비스의 수행이 이루어지는 부분이다.
이 때 Service 계층은 View & Database의 종류와 상관없이 독립적인 계층으로 , 두 설정으로 인해 영향이 생기지 않도록 설계해야 한다.
Service의 구현
- 클래스에 @Service Annotation을 매핑시킴
- 파라미터로 전달 된 데이터에 대해서 검증 작업을 수행함
- Repository 계층을 활용하여 DB에 접근함
- Service 계층의 단일 메소드가 Transaction의 단위로 작용함
- 애플리케이션의 세부 영역별로 클래스를 생성하여 구현하는게 바람직함
- 인터페이스의 사용이 권장되나, 다형성을 활용한 기능 확장의 요구사항이 없는 경우 사용하지 않는 경우도 있음
위의 그림과 같이 애플리케이션의 세부 영역별로 클래스를 생성하여 구현한다.
( Service 계층 : 다양한 @Service Annotaion이 사용된 클래스들의 묶음 )
#### Service 계층과 Controller의 연결 ####
[1]핵심 비지니스를 담당할 Service 계층의 클래스를 생성함 ( in service 패키지 )
@Service
public calss PostService {
public void getPost(Integer id) {
System.out.println("비지니스 로직 수행 중 : id 데이터 찾는중 " + id);
System.out.println("DB에 접근하고 data 검증 중");
}
}
[2] PostController에서 PostService 계층을 사용하도록 객체를 선언
그 후 객체를 사용함
[ new 키워드를 통해 다른 객체를 사용함 = DI ]
@RestController
@RequestMapping(value="/post")
public class PostController {
public PostService postService = new PostService();
@GetMapping
public PostDto getPost(@RequestParam Integer id) {
PostDto reuslt = postService.getPost(id); // Service계층 사용
return result
}
}
Spring Bean & 의존성 주입 ( Dependcy Injection )
의존성(Dependecy)이란?
하나의 모듈(클래스, 패키지 등)이 다른 모듈을 사용하는 것을 말한다. -new-
# PostController 클래스는 PostService에 의존(의존성이 있다)한다. ( PostService가 없으면 동작 못함 )
Class PostControl | <===> | Class PostService |
PostService service = new PostService(); method getPost() { service.getPostById() } |
← →← → |
method getPostById() { System.out.println( "id 출력" ); } |
Controller 클래스에서 PostService 객체를 생성해서 객체의 method에 접근하는 상황 ( 코드 상에 객체를 생성하여 compile-time 의존성이 생성 ) |
객체의 활용을 위한 의존성
- 일반적으로 다른 객체의 기능을 사용하기 위해서는 멤버 변수에 new로 사용할 기능의 객체를 생성하고 참조한다.
- 생성한 객체의 메서드를 호출하여, 다른 객체의 기능을 사용한다.
- 어떤 객체를 생성하여 사용할 것인지 코드 상에 명시한다.
- Compile-time 의존성이 생성 됨 ( 코드에 위치하니까 ! )
의존성 주입(Dependecy Injection)이란?
객체 생성을 외부에서 대신 수행하는 것을 말한다. ==> new (X)
- 활용할 객체에 대한 의존성(참조)설정을 외부에서 대신 해준다.
- 활용할 클래스(인터페이스) 타입의 멤버 변수만 선언 후 생성자를 구현한다.
- new 키워드로 객체 생성을 직접 하지 않는다 !! '
####의존성 주입을 통한 PostService 객체 생성 ######
@RestController
@RequestMapping(value = "/post")
public class PostController {
// 빈 클래스 타입의 멤버 변수만 선언
public PostService postService;
// 생성자에서 객체에 대한 초기화 수행 ?
public PostController(Post Service postService) {
this.postServilce = postService;
}
@GetMapping
public PostDto getPost(@RequestParam Integer id) {
PostDto res = postService.getPost(id);
return res;
}
}
위의 클래스에서는 클래스(인터페이스) 타입의 멤버 변수만 선언하고 객체를 할당해 주지 않았다. (참조만 가능하게)
하지만 생성자에서 멤버 변수를 인자로 받아서 할당해준다.
PostController 객체의 postService 변수는 누가 할당하는 것인가 ? 외부에서 런타임 내 생성자를 사용하는 곳에서 결정한다 !
특정 클래스가 사용하는 다른 객체를 코드상에서 명시하는 것이 아니라, 런타임 내 외부에서 결정해서 생성된 객체를 생성자로 주입시킨다.
즉 어떤 객체를 사용할 지 외부에서 결정함 !!
Spring Framework가 객체를 생성하고 관리하는 Cycle의 예시
- Spring Framework가 소스코드를 스캔
- 어노테이션을 만나면 객체를 생성함
- 만들 객체[1]의 생성자에서 다른 객체[2]가 필요하면 그 객체를 찾으러 떠난다.
- 객체[2]를 찾으러 갔는데 @Service라는 어노테이션이 있을 때, 객체를 생성해서 프레임워크가 관리한다.
- 객체[2]를 생성해서 Spring Framework가 가지고 있고 관리한다.
- 객체[2]가 있으니까 아까 못한 객체[1]의 생성자를 구동시키고 객체[1]을 만들자
- 객체[1]은 객체[2]에 의존성을 가지게 되었음 !
Spring Ioc 컨테이너
- Sping Framework에서 객체의 생성과 관리의 역할을 하는 컴포넌트
- 사용자가 framework를 사용하는 것이 아닌, framework가 사용자의 코드를 사용하면서 구동
Spring Bean
- Spring Ioc 컨테이너에 의해서 생성되어 관리되는 Java 객체
- 즉 Ioc 컨테이너가 만들고 관리하는 Java 객체
의존성 주입의 단계
[1] 객체 생성 방법
1. Spring에 의해 Bean 객체가 생성되게끔 Annotation을 설정함
(1-1) RestController , @Service 등의 어노테이션의 클래스들을 컴포넌트 스캔 단게에서 객체로 생성해줌
2. 사용할 객체를 멤버 변수와 생성자에 추가한다.
3. 객체를 사용한다.
( 객체를 멤버 변수로 선언하고 , 생성자에 추가하기만 하면 Spring Framework에 의해 생성&관리된다. )
[2] 객체 생성 방법 - 2
@Configuration
- Java 클래스에 @Configuration Annotation을 사용할 수 있다.
- Annotation에 해당하는 클래스는 Spring Framework에 의해 설정 정보를 위한 클래스로 활용된다.
@Bean Annotaion
- @Configuration 클래스 내에 @Bean을 사용한 메소드로 Bean을 생성하는 것이 가능하다.
- Bean으로 등록할 객체를 생성 후 Return하게 된다.
- Bean이란 리턴 객체가 Spring에 의해서 생성되고 관리되는 Java 객체를 의미함
- Bean들은 의존성을 가지고 서로 상호작용이 가능함
#### Configuration을 통해 미리 Bean 객체를 설정 #####
@Configuration
public class AppConfig {
@Bean
public PostService postServie() {
return new PostService();
}
}
#### Configuration을 통해서 생성되어 프레임 워크에서 관리되고 있는 Bean 객체 사용 #####
@RestController
@RequestMapping(value = "/post")
public class PostController {
// 클래스 타입의 멤버 변수만 선언
public PostService postService;
// Spring Framework의 Bean으로 등록되어 관리되고 있어서 사용이 가능함
public PostController(Post Service postService) {
this.postServilce = postService;
}
<정리> Spring Framework가 조건에 대해 객체를 생성하는 방법
1. 클래스 상단의 Annotation 정보를 활용하여 객체를 생성함 ( @Controller, @RestController, @Service 등 ) 2. @Configuration 클래스의 @Bean을 통해서 객체를 생성하고 프레임워크를 통해 관리하고 있는다. 3. XML 설정 [ 객체로 생성할 대상을 검색하는 과정을 Component Scan 이라고 한다. ] |
'FrameWork & Runtime > Spring' 카테고리의 다른 글
Spring Session & Cookie (0) | 2022.03.09 |
---|---|
MyBatis (0) | 2022.03.07 |
Spring의 Request & Response (0) | 2022.03.01 |
Spring 서비스 계층 (0) | 2022.02.28 |
<코드 프레소 웹 개발 트랙> Spring Boot 웹 개발 초급 [1] (0) | 2022.02.22 |