제가 공부한 내용을 정리하는 블로그입니다.
아직 많이 부족하고 배울게 너무나도 많습니다. 틀린내용이 있으면 언제나 가감없이 말씀해주시면 감사하겠습니다😁

스프링 정리를 위한 포스팅입니다.
해당 포스팅은 @Controller, @Service, @Repository의 역할과 특징 정리입니다.

 

도입

Spring 프레임워크는 계층구조로 코드를 나누어 각 계층마다 역할을 분리하였습니다.(객체 지향적 특징)
이와 같은 계층 구조는 코드의 역할 분리를 명확히 하고 유지보수성을 높이는 데 중요한 역할을 합니다.

  • Presentation Layer: 클라이언트의 요청 처리
  • Business Layer: 비즈니스 로직 처리
  • Persistence Layer: 데이터 접근 처리

클라이언트와의 요청 처리는 @Controller, 비즈니스 로직 처리는 @Service, 데이터베이스와의 통신은 @Repository를 통해 코드를 구성합니다. 

 

이번 포스팅에서는 @Controller, @Service, @Repository의 역할과 특징을 살펴보겠습니다.

 

@Controller

@Controller는 Spring MVC에서 컨트롤러 클래스를 정의할 때 사용되는 어노테이션입니다. 일반적으로 뷰 템플릿을 반환하는 방식으로 클라이언트의 요청을 처리합니다. 이 어노테이션이 있는 클래스는 HTTP 요청을 처리하고, Model 객체를 사용하여 데이터를 뷰에 전달합니다. @Controller는 주로 웹 애플리케이션에서 서버 사이드 렌더링을 위한 컨트롤러로 사용됩니다.

@Controller 구조

  1. 클라이언트로부터 받은 요청을 통해 Handler 어댑터를 통해 해당 요청을 처리할 수 있는 controller를 찾습니다.
  2. controller는 service와 repository의 비즈니스 로직을 처리한 후 뷰 이름을 handlerAdapter에게 전달합니다.
  3. Dispatcher Servlet은 해당 뷰 네임에 해당하는 뷰를 ViewResolver를 통해서 뷰를 반환합니다.
@Controller
@RequiredArgsConstructor
public class UserController {
    private final UserService userService;

    @GetMapping("/users")
    public String getUsers(Model model) {
        model.addAttribute("users", userService.findAll());
        return "userList"; // "userList" 뷰 반환
    }
}

userList.html

 

@Controller + @RequestBody

@RequestBody는 HTTP 요청 본문을 자바 객체로 변환하여 매핑해주는 어노테이션입니다. 이 어노테이션을 @Controller와 함께 사용하면, 클라이언트에서 전달한 JSON, XML 등의 데이터를 객체로 받을 수 있습니다. @Controller는 뷰를 반환하는 역할을 계속하고, @RequestBody는 데이터를 뷰에 매핑하는 역할을 합니다.

@Controller + @RequestBody 구조

  1. 클라이언트로부터 받은 요청을 통해 Handler 어댑터를 통해 해당 요청을 처리할 수 있는 controller를 찾습니다.
  2. controller는 service와 repository의 비즈니스 로직을 처리한 후 뷰 이름을 handlerAdapter에게 전달합니다.
  3. 반환되는 객체는 Json으로 Serialize되어 사용자에게 반환됩니다. 이는 @ResponseBody 어노테이션으로 개발됩니다.
@Controller
@RequiredArgsConstructor
public class UserController {
    private final UserService userService;

    /**
     * Handles POST requests to create a new user from JSON data and renders the "userDetail" view.
     *
     * @param user the user data from the request body
     * @param model the model to hold attributes for the view
     * @return the name of the view to be rendered
     */
    @PostMapping("/users")
    public String createUser(@RequestBody User user, Model model) {
        User savedUser = userService.save(user);
        model.addAttribute("user", savedUser);
        return "userDetail"; // Return the name of the view
    }
}

성공적인 response

 

@RestController

@RestController는 @Controller와 @ResponseBody를 결합한 어노테이션입니다. @RestController가 적용된 클래스는 RESTful 웹 서비스를 제공하며, 메서드의 반환 값이 바로 HTTP 응답 본문으로 전송됩니다. 따라서 @RestController는 일반적으로 JSON, XML과 같은 데이터를 직접 반환하는 데 사용됩니다. 뷰를 반환하지 않으며, 주로 API 서버에서 사용됩니다.

@RestController

  1. 클라이언트로부터 받은 요청을 통해 Handler 어댑터를 통해 해당 요청을 처리할 수 있는 controller를 찾습니다.
  2. controller는 service와 repository의 비즈니스 로직을 처리한 후 뷰 이름을 handlerAdapter에게 전달합니다.
  3. 반환되는 객체는 Json으로 Serialize되어 사용자에게 반환됩니다. 이는 @RestController 어노테이션으로 개발됩니다.
@RestController
@RequiredArgsConstructor
public class UserController {
    private final UserService userService;

    /**
     * Handles GET requests to retrieve the list of users as JSON.
     *
     * @return a list of users
     */
    @GetMapping("/json-users")
    public List<User> getUsers() {
        return userService.findAll();
    }
}

 

@Service

@Service 어노테이션은 서비스 계층에 사용됩니다. 서비스 계층은 비즈니스 로직을 처리하는 곳으로, 일반적으로 데이터베이스에서 데이터를 조회하고, 가공하여 컨트롤러로 전달하는 역할을 합니다. @Service는 주로 서비스 클래스를 나타내며, @Component의 특성을 그대로 가지고 있어 Spring 컨테이너에 의해 관리됩니다.

@Service
@RequiredArgsConstructor
public class UserService {
    private final UserRepository userRepository;

    public List<User> findAll() {
        return userRepository.findAll();
    }
}

 

 

@Repository

@Repository는 데이터 접근 계층에 사용됩니다. 이 어노테이션은 주로 데이터베이스와 상호작용하는 클래스를 나타냅니다. @Repository 어노테이션을 사용하면 Spring이 해당 클래스를 자동으로 데이터 접근 객체(DAO)로 인식하고, 예외 변환 기능을 제공합니다. @Repository는 @Service와 동일하게 @Component의 특성을 그대로 가지고 있어 Spring 컨테이너에 의해 관리되며, 데이터베이스와의 상호작용을 담당합니다.

// In-memory Database
@Repository
public class ItemRepository {

    private static final Map<Long, Item> store = new HashMap<>(); //static
    private static long sequence = 0L; //static

    public Item save(Item item) {
        item.setId(++sequence);
        store.put(item.getId(), item);
        return item;
    }
}


// JPA
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
    List<User> findAll();
}

 

 

코드

+ Recent posts