티스토리 뷰
Spring MVC - Controller + Service
[Spring]Spring MVC - Controller 클래스 구조 생성 및 설계
[Spring]Spring MVC - Controller 클래스에 핸들러 메서드(Handler Method) 구현
[Spring]Spring MVC - Controller 클래스에 ResponseEntity 적용
[Spring]Spring MVC - Controller 클래스에 DTO 적용
[Spring]Spring MVC - DTO 유효성 검증(Validation)
[Spring]Spring MVC - DI를 통한 API 계층 ↔ 서비스 계층 연동
[Spring]Spring MVC - 매퍼(Mapper)를 이용한 DTO 클래스 ↔ 엔티티(Entity) 클래스 매핑
[Spring]Spring MVC - @ExceptionHandler를 이용한 예외처리
[Spring]Spring MVC - @RestControllerAdvice를 이용한 예외처리
Spring Data JDBC
[Spring]JDBC(Java DataBase Connectivity)
[Spring]Spring Data JDBC, Spring Data JDBC 사용법
[Spring]Spring Data JDBC - 도메인 엔티티&테이블 설계
Spring Data JPA
[Spring]JPA(Java Persistence API)
[Spring]JPA - Entity ↔ DB Table Mapping
[Spring]JPA - Entity ↔ Entity Mapping
[Spring]Spring Data JPA - 데이터 액세스 계층 구현
지난 글에서 스프링 MVC(Model - View - Controller)의 구성요소와 작동방식에 대해 알아봤다.
https://gnidinger.tistory.com/464
간단하게 요약하자면 스프링 MVC는 위 아키텍처에서 클라이언트의 요청을 받아들이는 계층,
즉 Presentation Layer(=API Layer) 영역을 세분화한 것이며
출처: https://docs.spring.io/spring-framework/docs/4.0.x/spring-framework-reference/html/overview.html
스프링 프레임워크의 웹(Web) 계층을 담당하는 모듈 중 서블릿(Servlet) API를 기반으로 클라이언트의 요청을 처리하는
spring-webmvc모듈이기도 하며
DispatcherServlet 객체를 프론트 컨트롤러로 둔 프론트 컨트롤러 패턴으로 동작한다.
지금부터 이어지는 글에선 커피 판매 앱에 대한 Presentation Layer(=API Layer) 영역을 실제로 구현해볼 것이며,
이를 위해 알아야 할 키워드는 Controller와 DTO(Data Transfer Object)이다.
참고로 각 영역에 해당하는 컴포넌트 자동 등록 애너테이션은 아래와 같다.
- @Controller - Presentation Layer(=API Layer)
- @Service - Application Layer(=Service Layer, Business Layer)
- @Repsitory - Data Access Layer
이 글에서는 먼저 Controller 클래스의 구조 생성 및 설계에 대해 알아본다.
구조 생성
가장 먼저 해야할 일은 생성한 프로젝트에 자바 패키지 구조를 잡는 것이다.
스프링 부트 기반의 앱에서 주로 사용되는 패키지 구조는 두 가지가 있는데,
- 기능 기반 패키지 구조(package-by-feature)
- 계층 기반 패키지 구조(package-by-layer)
가 그것이다.
- 기능 기반 패키지 구조(package-by-feature)
먼저 기능 기반 패키지 구조는 말 그대로 패키지를 기능에 따라 나누는 것을 말한다.
따라서 한 패키지 안에 하나의 기능을 완성하기 위한 계층별 클래스가 모여있다.
위 그림에선 패키지를 커피 기능과 멤버 기능으로 나눈 것을 확인할 수 있다.
위에서 짧게 언급 했듯이 ‘Controller, DTO’ 클래스는 API 계층에, ‘Coffee, Member, Service’ 는 비즈니스 계층에 해당되며
Repository 클래스는 데이터 액세스 계층에 해당된다.
- 계층 기반 패키지 구조(package-by-layer)
계층 기반 패키지 구조는 패키지를 하나의 계층(Layer)에 따라 나눠 관리하는 구조를 말한다.
각 계층에 따라 패키지를 구성해 클래스를 위치시킨 것을 확인할 수 있다.
위 두가지 패키지 구조는 애플리케이션의 요구 사항이나 특성에 따라서 상황에 맞게 적절하게 사용되지만,
Spring Boot에서는 기능 기반 패키지 구조 사용을 권장하고 있다.
그 이유는 테스트와 리팩터링이 용이하고, 마이크로 서비스 시스템으로의 분리가 상대적으로 용이하기 때문이라고 한다.
Controller 클래스의 설계
지난 번 글에서도 살펴봤지만 컨트롤러는 요청을 처리하는 로직을 담고 있으며 필요한 로직을 호출하는 역할을 한다.
따라서 이런 역할을 하는 컨트롤러를 설계에는 당연히 클라이언트의 요청과 그 처리 기능에 대한 고민이 담겨야 한다.
그렇다면 커피 주문 애플리케이션의 기능 요구 사항은 어떤 것들이 있을까? 대략적으로 아래와 같을 것이다.
- 주인이 커피 정보를 관리하는 기능
- 커피 정보 등록 기능
- 등록한 커피 정보 수정 기능
- 등록한 커피 정보 삭제 기능
- 등록한 커피 정보 조회 기능
- 고객이 커피 정보를 조회하는 기능
- 고객이 커피를 주문하는 기능
- 커피 주문 등록 기능
- 커피 주문 취소 기능
- 커피 주문 조회 기능
- 고객이 주문한 커피를 주인이 조회하는 기능
- 주문 조회 기능
- 고객에게 전달 완료한 커피에 대한 주문 완료 처리 기능
그렇다면 이 기능을 구현하기 위해선 몇 개의 컨트롤러 객체가 필요할까?
REST API 기반의 애플리케이션에서는 애플리케이션이 제공해야 될 기능을 리소스(Resource)로 분류한다.
위 기능을 구현하기 위한 리소스는 아래와 같은 구성이 될 것이다.
따라서 총 세 개의 컨트롤러 클래스를 작성하면 된다.
특이한 점은 고객과 주인의 기능을 따로 분리하지 않고 회원으로 묶었다는 것인데
둘을 완전히 분리한다면 인증 프로세스가 복잡해질 수 있기 때문이다.
따라서 고객과 주인을 회원 리소스에 포함시키고, 둘 사이의 ROLE을 통해 기능을 구분하는 것이 편하다고 한다.
- 엔트리 포인트(Entrypoint) 클래스
엔트리 포인트(Entrypoint) 클래스란 Spring Boot 기반의 애플리케이션이 정상적으로 실행되기 위해 필요한
main() 메서드가 포함된 클래스를 말한다.
https://start.spring.io/를 통해 생성한 프로젝트엔 이미 엔트리 포인트 클래스가 작성되어 있으며,
그 모양은 아래와 같다.
package com.gnidinger;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication // (1)
public class SpringMVCPractice {
public static void main(String[] args) {
SpringApplication.run(SpringMVCPractice.class, args); // (2)
}
}
(1) @SpringBootApplication
- 자동 구성 활성화
- @Component가 붙은 클래스를 찾아 스프링 빈으로 등록(@ComponentScan)
- @Configuration이 붙은 클래스를 찾아 @Bean이 붙은 메서드의 리턴 클래스와 함께 스프링 빈으로 등록
(2) SpringApplication.run(SpringMVCPractice.class, args);
Spring 애플리케이션을 부트스트랩(Bootstrap)*하고, 실행하는 역할을 한다.
*부트스트랩(Bootstrap) - 애플리케이션 실행 전 설정 작업을 수행하여 실행 가능한 애플리케이션으로 만드는 단계
- Controller 구조 작성
Member, Coffee, Order에 대한 컨트롤러 구조를 작성한다.
아래에 작성되는 컨트롤러는 아직 미완성이며, 다음 글에서 핸들러 메서드를 채워주어야 한다.
- MemberController
package com.gnidinger.member;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RequestMapping;
@RestController // (1)
@RequestMapping("/v1/members") // (2)
public class MemberController {
}
(1) @RestController
- 해당 클래스가 REST API의 리소스(Resource)를 처리하기 위한 API 엔드포인트로 동작함을 선언
- @RestController 가 추가된 클래스는 애플리케이션 로딩 시, Spring Bean으로 등록됨
(2) @RequestMapping
- 클라이언트의 요청과 요청을 처리하는 핸들러 메서드(Handler Method)를 매핑
- ("/v1/members")와 같이 클래스 전체에 사용되는 공통 URL을 설정
나머지 두 개의 컨트롤러도 같은 방식으로 만들어주면 된다.
- CoffeeController
package com.gnidinger.coffee;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RequestMapping;
@RestController
@RequestMapping("/v1/coffees")
public class CoffeeController {
}
- OrderController
package com.gnidinger.order;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RequestMapping;
@RestController
@RequestMapping("/v1/orders")
public class OrderController {
}
'Java+Spring > Spring' 카테고리의 다른 글
[Spring]Spring MVC - Controller 클래스에 DTO 적용 (0) | 2022.08.22 |
---|---|
[Spring]Spring MVC - Controller 클래스에 ResponseEntity 적용 (0) | 2022.08.22 |
[Spring]Spring MVC - Controller 클래스에 핸들러 메서드(Handler Method) 구현 (0) | 2022.08.22 |
[Spring]Spring MVC (4) | 2022.08.20 |
[Spring]AOP - JDK Dynamic Proxy, CGLib (2) | 2022.08.18 |
[Spring]AOP - AspectJ, Pointcut Expression, Join Point (2) | 2022.08.17 |
- Total
- Today
- Yesterday
- 스트림
- spring
- Backjoon
- 세계일주
- 유럽여행
- 칼이사
- 백준
- 중남미
- 자바
- 지지
- BOJ
- java
- 유럽
- 리스트
- 파이썬
- Algorithm
- 스프링
- 여행
- Python
- 세모
- 동적계획법
- 맛집
- 남미
- 면접 준비
- 야경
- 세계여행
- a6000
- RX100M5
- 알고리즘
- 기술면접
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |