Service

prana·2023년 5월 22일

SpringBoot

목록 보기
9/22
post-thumbnail

출처 : https://wikidocs.net/161220

앞서 우리는 QuestionController에서 QuestionRepository를 직접 사용하여 질문 목록 데이터를 조회했다.

  • 하지만 대부분의 규모있는 스프링부트 프로젝트는 컨트롤러에서 리포지터리를 직접 호출하지 않고
    중간에 서비스(Service)를 두어 데이터를 처리한다.

  • 서비스는 스프링에서 데이터 처리를 위해 작성하는 클래스이다.

서비스가 필요한 이유

1. 모듈화

  • 여러 개의 리포지터리를 사용하여 데이터를 조회한 후 가공하여 리턴한다고 하면, 이러한 기능을 서비스로 만들어두면 컨트롤러에서는 해당 서비스를 호출하여 사용하면 된다.

  • 하지만 서비스로 만들지 않고, 컨트롤러에서 구현하려 한다면 해당 기능을 필요로 하는 모든 컨트롤러가 동일한 기능을 중복으로 구현해야 한다.

  • 서비스는 모듈화를 위해 필요하다.

2. 보안

  • 컨트롤러는 리포지터리 없이 서비스를 통해서만 데이터베이스에 접근하도록 구현하는 것이 보안상 안전하다.
  • 이렇게 하면 어떤 해커가 해킹을 통해 컨트롤러를 제어할 수 있게 되더라도 리포지터리에 직접 접근은 할 수 없게 된다.

3. 엔티티 객체와 DTO 객체의 변환

  • 우리가 작성한 Question, Answer 클래스는 엔티티(Entity) 클래스이다.

  • 엔티티 클래스는 데이터베이스와 직접 맞닿아있는 클래스이기 때문에, 컨트롤러나 타임리프같은 템플릿 엔진에 전달하여 사용하는 것은 좋지 않다.

  • 컨트롤러나 타임리프에서 사용하는 데이터 객체는 속성을 변경하여 비즈니스적인 요구를 처리해야 하는 경우가 많은데,

    • 엔티티를 직접 사용하여 속성을 변경한다면 테이블 컬럼이 변경돼 엉망이 될 수 있기 때문이다.
  • Question, Answer 같은 엔티티 클래스는 컨트롤러에서 사용할 수 없게끔 설계하는 것이 좋다.

    • 그러기 위해서는 Question, Answer 대신 사용할 DTO(Data Transfer Object) 클래스가 필요하다.
  • Question, Answer 등의 엔티티 객체를 DTO 객체로 변환하는 작업도 필요하다. 그러면 엔티티 객체를 DTO 객체로 변환하는 일은 어디서 처리해야 할까.

    • 서비스에서 변환을 해준다.

    • 서비스는 컨트롤러와 리포지터리의 중간자적인 입장에서 엔티티 객체와 DTO 객체를 서로 변환하여 양방향에 전달하는 역할을 한다.

//QuestionService.java
package com.mysite.sbb.question;

import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.List;

@RequiredArgsConstructor
@Service
public class QuestionService {
    private final QuestionRepository questionRepository;
    public List<Question> getList(){
        return this.questionRepository.findAll();
    }
}

package com.mysite.sbb.question;

import java.util.List;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;

import lombok.RequiredArgsConstructor;

@RequiredArgsConstructor
@Controller
public class QuestionController {

    //private final QuestionRepository questionRepository;
    private final QuestionService questionService;

    @GetMapping("question/list")
    public String list(Model model) {
        List<Question> questionList = this.questionService.getList();
        model.addAttribute("questionList", questionList);
        return "question_list";
    }
}

실행시키고 http://localhost:8080/question/list 페이지에 접속하면 이전과 동일한 화면을 볼 수 있다.

앞으로 작성할 컨트롤러도 리포지터리를 직접 사용하지 않고
Controller -> Service -> Repository 구조로 데이터를 처리한다.

0개의 댓글