Spring Boot 기반의 애플리케이션에서 주로 사용되는 Java 패키지 구조는 기능 기반 패키지 구조(package-by-feature)와 계층 기반 패키지 구조(package-by-layer)가 있다.
기능 기반 패키지 구조란 말 그대로 애플리케이션의 패키지를 애플리케이션에서 구현해야 하는 기능을 기준으로 패키지를 구성하는 것이다.
이렇게 나누어진 패키지 안에는 하나의 기능을 완성하기 위한 계층별(API 계층, 서비스 계층, 데이터 액세스 계층)클래스들이 모여있다.
회원을 관리하기 위한 회원 기능
과 커피를 관리하기 위한 커피 기능
을 각각 coffee
와 member
라는 패키지로 나누었으며, 각각의 패키지 안에 레이어 별 클래스들이 존재한다.
계층 기반 패키지 구조란 패키지를 하나의 계층(Layer)으로 보고 클래스들을 계층별로 묶어서 관리하는 구조를 말한다.
계층(Layer)을 기반으로 패키지를 구성한 예다. ‘controller, dto’ 패키지는 API 계층에 해당되고, ‘model, service’ 패키지는 비즈니스 계층에 해당되며, repository는 데이터 액세스 계층에 해당된다.
Spring Boot 팀에서는 테스트와 리팩토링이 용이하고, 향후에 마이크로 서비스 시스템으로의 분리가 상대적으로 용이한 기능 기반 패키지 구조 사용을 권장하고 있다.
(1) @SpringBootApplication
@SpringBootApplication
은 코드 상에서는 보이지 않지만 내부적으로 세가지 일을 해준다.
자동 구성을 활성화한다.
애플리케이션 패키지 내에서 @Component
가 붙은 클래스를 검색한 후(scan), Spring Bean으로 등록하는 기능을 활성화한다.
@Configuration
이 붙은 클래스를 자동으로 찾아주고, 추가적으로 Spring Bean을 등록하는 기능을 활성화한다.
(2) SpringApplication.run( 클래스명 Application.class, args);
Spring 애플리케이션을 부트스트랩하고, 실행하는 역할을 한다.
부트스트랩(Bootstrap)이란?
애플리케이션이 실행되기 전에 여러가지 설정 작업을 수행하여 실행 가능한 애플리케이션으로 만드는 단계를 의미한다.
(3) @RestController
Spring MVC에서는 특정 클래스에 @RestController 를 추가하면 해당 클래스가 REST API의 리소스(자원, Resource)를 처리하기 위한 API 엔드포인트로 동작함을 정의한다.
또한 @RestController
가 추가된 클래스는 애플리케이션 로딩 시, Spring Bean으로 등록해준다.
(4) @RequestMapping
@RequestMapping("/v1/members")
@RequestMapping
은 클라이언트의 요청과 클라이언트 요청을 처리하는 핸들러 메서드(Handler Method)를 매핑해주는 역할을 한다.
@RequestMapping(value = "/v1/members",
produces = {MediaType.APPLICATION_JSON_VALUE})
public class MemberController {
produces
produces
애트리뷰트(Attribute)는 응답 데이터를 어떤 미디어 타입으로 클라이언트에게 전송할 지를 설정한다. 여기서는 JSON 형식의 데이터를 응답 데이터로 전송하겠다는 의미로 MediaType.APPLICATION_JSON_VALUE
값을 설정했다. 이 값을 설정하지 않으면 현재 코드에서는 JSON 형식의 데이터를 응답으로 전송하지 않고, 문자열 자체를 전송한다.
@PostMapping
public String postMember(@RequestParam("email") String email,
@RequestParam("name") String name,
@RequestParam("phone") String phone) {
System.out.println("# email: " + email);
System.out.println("# name: " + name);
System.out.println("# phone: " + phone);
@PostMapping
@PostMapping
은 클라이언트의 요청 데이터(request body)를 서버에 생성할 때 사용하는 애너테이션이며, 클라이언트 쪽에서 요청 전송 시, HTTP Method 타입을 동일하게 맞춰주어야 한다.
@RequestParam
@RequestParam
은 핸들러 메서드의 파라미터 종류 중 하나다.
주로 클라이언트 쪽에서 전송하는 요청 데이터를 쿼리 파라미터(Query Parmeter 또는 Query String), 폼 데이터(form-data), x-www-form-urlencoded 형식으로 전송하면 이를 서버 쪽에서 전달 받을 때 사용하는 애너테이션이다.
@GetMapping("/{member-id}")
public String getMember(@PathVariable("member-id")long memberId) {
System.out.println("# memberId: " + memberId);
// not implementation
return null;
@GetMapping
@GetMapping
은 클라이언트가 서버에 리소스를 조회할 때 사용하는 애너테이션이다.
@GetMapping
애너테이션의 괄호 안에는 몇 가지 애트리뷰트(Attribute)를 사용할 수 있지만 여기서는 전체 HTTP URI의 일부를 지정했다.
클라이언트 쪽에서 getMember() 핸들러 메서드에 요청을 보낼 경우, 최종 URI는 형태는 아래와 같습니다.
”/v1/members/{member-id}”
즉, 이 URI는 클래스 레벨의 @RequestMapping에 설정된 URI와 @GetMapping에 설정한 URI가 합쳐진 형태다.
{member-id}
는 회원 식별자를 의미하며 클라이언트가 요청을 보낼 때 URI로 어떤 값을 지정하느냐에 따라서 동적으로 바뀌는 값이다.
@PathVariable
@PathVariable
핸들러 메서드의 파라미터 종류 중 하나다.
@PathVariable
의 괄호 안에 입력한 문자열 값은 @GetMapping("/{member-id}")
처럼 중괄호({ }) 안의 문자열과 동일해야 한다. 여기서는 두 문자열 모두 “member-id” 로 동일하게 지정해주었다.
만약 두 문자열이 다르다면 MissingPathVariableException
이 발생한다.