[Spring Study] Controller 와 Service

Controller

Controller는 웹 요청을 처리하고, 사용자와 상호 작용하는 역할을 합니다. 주로 HTTP 요청을 받고, 적절한 서비스 메서드를 호출하며, 최종적으로 HTTP 응답을 반환합니다. SpringBoot에서는 @RestController@Controller 어노테이션을 사용하여 컨트롤러 클래스를 정의합니다.

@RestController 애노테이션

@RestController 애노테이션은 Spring Boot에서 RESTful 웹 서비스를 개발할 때 사용되는 편리한 애노테이션입니다. 이 애노테이션은 @Controller@ResponseBody를 결합한 것과 같은 역할을 합니다. 아래에 @RestController 애노테이션의 주요 기능과 사용 방법을 설명하겠습니다.

자동 JSON 변환

@RestController를 사용하면 메서드의 반환값이 자동으로 JSON 형식으로 변환됩니다. 별도의 변환 작업 없이 객체를 반환하면 Jackson 라이브러리를 통해 JSON으로 변환됩니다.

코드 간소화

@ResponseBody 애노테이션을 메서드마다 반복해서 붙일 필요가 없습니다. 클래스 레벨에 @RestController를 선언하면, 해당 클래스의 모든 메서드에 자동으로 @ResponseBody가 적용됩니다.

RESTful API 개발

RESTful 웹 서비스의 개발을 쉽게 해줍니다. 각종 HTTP 메서드(GET, POST, PUT, DELETE 등)를 활용한 API 엔드포인트를 간편하게 정의할 수 있습니다.

RestController 사용방법

클래스 레벨에 @RestController 을 선언합니다.

import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.GetMapping;

@RestController
@RequestMapping("/api")
public class MyRestController {

    @GetMapping("/hello")
    public String sayHello() {
        return "Hello, World!";
    }
}

위의 예제에서 @RestController는 클래스 레벨에 선언되며, @GetMapping 애노테이션을 사용하여 /api/hello 엔드포인트를 정의합니다. 이 메서드는 문자열 “Hello, World!”를 반환하고 클라이언트에게는 JSON 형식으로 전달됩니다.

Controller 주요 역할

요청 매핑

HTTP 요청 URL과 메서드를 매핑합니다. 예를 들어, @GetMapping, @PostMapping, @PutMapping, @DeleteMapping 등을 사용합니다.

요청 파라미터 처리

요청과 함께 전달된 파라미터를 처리합니다. @RequestParam, @PathVariable, @RequestBody 등을 사용하여 파라미터를 받아옵니다.

서비스 호출

비즈니스 로직 처리를 위해 Service 클래스의 메서드를 호출합니다.

응답 생성

적절한 형식으로 응답을 생성하여 반환합니다. 보통 JSON 형식의 응답을 많이 사용하며, SpringBoot에서는 자동으로 JSON 변환을 처리해줍니다.

RestController와 Controller 차이점

@RestController: 주로 RESTful 웹 서비스의 엔드포인트를 정의할 때 사용됩니다. 메서드의 반환값은 자동으로 JSON 형식으로 변환됩니다.

@Controller: 전통적인 Spring MVC 컨트롤러로 사용됩니다. 주로 뷰(View)를 반환하거나 템플릿 엔진(예: Thymeleaf)과 함께 사용됩니다. 메서드마다 @ResponseBody 애노테이션을 사용하여 JSON 형식의 응답을 생성할 수 있습니다.

Service

Service는 비즈니스 로직을 처리하는 계층입니다. 주로 데이터 처리, 트랜잭션 관리, 기타 비즈니스 규칙을 구현합니다. Service 클래스는 @Service 어노테이션을 사용하여 정의합니다.

Service의 주요 역할

비즈니스 로직 구현

애플리케이션의 핵심 비즈니스 로직을 처리합니다.

데이터 처리

데이터베이스 접근을 위한 DAO (Data Access Object) 혹은 Repository와 연동합니다.

트랜잭션 관리

여러 데이터베이스 연산을 하나의 트랜잭션으로 묶어 원자성을 보장합니다.

추상화

컨트롤러와 데이터 접근 로직 사이의 중간 계층으로 작동하여, 컨트롤러가 비즈니스 로직에 대해 알 필요 없도록 합니다.

서비스 구현하기

@Service
@Log4j2
@RequiredArgsConstructor
public class TodoServiceImpl implements TodoService {

    private final TodoRepository todoRepository;

    @Override
    public TodoDTO get(Long id) {
        Optional<Todo> result = todoRepository.findById(id);

        Todo todo = result.orElseThrow();

        return entityToDTO(todo);
    }

    @Override
    public Long register(TodoDTO todoDTO) {
        Todo todo = dtoToEntity(todoDTO);
        Todo result = todoRepository.save(todo);

        return result.getId();
    }

    @Override
    public void modify(TodoDTO todoDTO) {
        Optional<Todo> result = todoRepository.findById(todoDTO.getId());

        Todo todo = result.orElseThrow();

        todo.changeTitle(todoDTO.getTitle());
        todo.changeContent(todoDTO.getContent());
        todo.changeDueDate(todoDTO.getDueDate());
        todo.changeDone(todoDTO.isDone());

        todoRepository.save(todo);
    }

    @Override
    public void remove(Long id) {
        todoRepository.deleteById(id);
    }
}

실습에 사용한 코드로 사용 예제를 설명해보도록 하겠습니다. Spring Boot 프로젝트에서 TodoService 인터페이스를 구현한 TodoServiceImpl 클래스입니다. 이 클래스는 할 일(Todo) 항목을 관리하는 비즈니스 로직을 포함하고 있습니다. 여기에는 @Service, @Log4j2, @RequiredArgsConstructor와 같은 여러 애노테이션이 사용됩니다. 각 메서드와 구성 요소의 역할을 설명하겠습니다.

@Service: 이 애노테이션은 해당 클래스가 서비스 계층의 역할을 한다고 Spring에게 알려줍니다. 주로 비즈니스 로직을 처리하는 데 사용됩니다.

@Log4j2: 로깅을 위한 애노테이션입니다. Apache Log4j2를 사용하여 로깅 기능을 제공합니다. log.info(), log.debug(), log.error() 등의 메서드를 통해 로그를 기록할 수 있습니다.

@RequiredArgsConstructor: Lombok 라이브러리의 애노테이션으로, final 또는 @NonNull이 붙은 필드에 대해 생성자를 자동으로 생성해줍니다. 이 경우, todoRepository 필드에 대해 생성자가 자동으로 생성됩니다.

조회 메서드 get(Long id)

주어진 ID로 할 일 항목을 조회할 수 있는 get 메서드입니다.todoRepository.findById(id)를 사용하여 Optional<Todo>를 반환받습니다.orElseThrow()를 호출하여 값이 존재하지 않으면 예외를 던집니다.조회된 Todo 객체를 TodoDTO로 변환하여 반환합니다.

등록 메서드 register(TodoDTO todoDTO)

새로운 할 일 항목을 등록합니다.dtoToEntity(todoDTO)를 호출하여 TodoDTOTodo 엔티티로 변환합니다.todoRepository.save(todo)를 호출하여 데이터베이스에 저장하고, 저장된 엔티티를 반환받습니다.저장된 엔티티의 ID를 반환합니다.

수정 메서드 modify (TodoDTO todoDTO)

기존 할 일 항목을 수정합니다.todoDTO.getId()로 할 일 항목을 조회하여 Optional<Todo>를 반환받습니다.orElseThrow()를 호출하여 값이 존재하지 않으면 예외를 던집니다.Todo 객체의 속성을 todoDTO의 값으로 변경합니다.변경된 Todo 객체를 다시 저장합니다.

삭제 메서드 remove (Long id)

주어진 ID로 할 일 항목을 삭제합니다.todoRepository.deleteById(id)를 호출하여 데이터베이스에서 해당 ID의 할 일 항목을 삭제합니다.

다시 한번 정리해보자면 @RestController@Controller@ResponseBody를 결합한 애노테이션으로, RESTful 웹 서비스를 쉽게 개발할 수 있도록 도와줍니다. 클래스 레벨에 선언하면 해당 클래스의 모든 메서드가 자동으로 JSON 형식의 응답을 반환합니다.다양한 HTTP 메서드를 사용하여 CRUD 기능을 간편하게 구현할 수 있습니다. 이렇게 구현한 서비스를 Controller 단계에서 필요 시 호출하여 사용할 수 있습니다.