[Spring Boot] #20. 서비스 계층과 트랜잭션

gogori6565·2024년 7월 30일
0

스프링 부트 공부

목록 보기
18/20

👉 Mission. 기존 Article의 Rest API 구현에 Service 계층을 추가하시오.


Service

: Controller와 Repository 사이에 위치하는 계층으로서 처리 업무의 순서를 총괄

  • (예를 들어) 웨이터 = Controller / 주방장 = Service / 주방보조(재료가져오는) = Repository
  • 즉, Service 가 있음으로써, Controller는 클라이언트로 요청을 받고 응답을 처리(반환)하는 것만 수행함 (내부 업무는 Service 담당)

트랜잭션과 롤백

트랜잭션(Transaction) : 모두 성공되어야 하는 일련의 과정
롤백(Rollback) : 실패 시, 진행 초기 단계로 돌리는 것

그리고 이러한 트랜잭션은 Service 가 관리한다!

실습에 사용되는 어노테이션 설명 👇

  • @Service : 해당 클래스를 서비스로 인식하여 스프링 부트에 객체를 생성(등록)
  • @Transactional : 해당 메서드를 트랜잭션으로 묶는다!
    • 해당 메서드가 수행되다 실패하면 메서드 수행 이전 상태로 롤백한다!

💻 실습 - Service 계층 구현

Controller 는 클라이언트에게 요청을 받고 응답 처리만 하게끔 Service 를 추가해 코드 변경을 해보자!

파일명 : api/ArticleApiController.java

@Autowired
private ArticleService articleService; //Service 연결

//GET - 전체 article
@GetMapping("/api/articles")
public List<Article> index(){
    return articleService.index();
}

//GET - 단일 article
@GetMapping("/api/articles/{id}")
public Article show(@PathVariable Long id){
    return articleService.show(id);
}

//POST - 생성
@PostMapping("/api/articles")
public ResponseEntity<Article> create(@RequestBody ArticleForm dto) {
    Article created = articleService.create(dto);
    return (created != null) ?
            ResponseEntity.status(HttpStatus.CREATED).body(created) :
            ResponseEntity.status(HttpStatus.BAD_REQUEST).build();
}

//PATCH
@PatchMapping("/api/articles/{id}")
public ResponseEntity<Article> update(@RequestBody ArticleForm dto,
                                     @PathVariable Long id){
    Article updated = articleService.update(dto, id);
    return (updated != null) ?
            ResponseEntity.status(HttpStatus.OK).body(updated):
            ResponseEntity.status(HttpStatus.BAD_REQUEST).build(); //OK = 200
}

//DELETE - 삭제
@DeleteMapping("/api/articles/{id}")
public ResponseEntity<Void> delete(@PathVariable Long id){
    Article deleted = articleService.delete(id);
    return (deleted != null) ?
            ResponseEntity.status(HttpStatus.NO_CONTENT).build():
            ResponseEntity.status(HttpStatus.BAD_REQUEST).build();
}

Service 구현을 위해 Service 패키지를 생성해주자.

파일명 : Service/ArticleService.java

@Service //서비스 선언! (서비스 객체를 스프링 객체에 생성)
public class ArticleService {

    @Autowired
    private ArticleRepository articleRepository;
    
    public List<Article> index() {
        return articleRepository.findAll();
    }
    
    public Article show(Long id) {
        return articleRepository.findById(id).orElse(null);
    }
    
    public Article create(ArticleForm dto) {
        Article article = dto.toEntity();
    
        //POST 요청으로 기존 articlel이 수정되는 것 방지
        if(article.getId() != null){
            return null;
        }
        return articleRepository.save(article);
    }
    
    public Article update(ArticleForm dto, Long id) {
        Article article = dto.toEntity();
        Article target = articleRepository.findById(id).orElse(null);
    
        if(target == null || id != article.getId()){
            return null;
        }
    
        target.patch(article);
        return articleRepository.save(target);
    }
    
    public Article delete(Long id) {
        Article target = articleRepository.findById(id).orElse(null);
    
        if(target == null){
            return null;
        }
    
        articleRepository.delete(target);
        return target;
    }
}

📚정리

1) Service 계층

여태까지는 Controller 에 클라이언트로부터 요청을 받아 모든 처리까지 담당하게 하였으나, Service 계층을 생성하여 역할을 확실하게 배분한다.

  • Controller -> 클라이언트로 요청을 받고 응답을 처리(반환)하는 것만
  • Service -> 내부 업무를 처리

2) 트랜잭션과 롤백

어떤 코드를 수행할 때, 해당 메서드가 실행되다가 중간에 에러가 나서 취소가 된다면, 여태까지 수행되는 코드가 다시 전부 취소 즉, '이전 상태로 되돌아가야 (=롤백)' 하지 않겠는가?
그럴 때 사용하는 것이 바로 '트랜잭션' 과 '롤백'이다.

  • 트랜잭션(Transaction) : 모두 성공되어야 하는 일련의 과정
  • 롤백(Rollback) : 실패 시, 진행 초기 단계로 돌리는 것

트랜잭션은 원하는 메서드에 @Transactional 어노테이션을 붙여 사용 가능하다.


강의 출처 : https://www.youtube.com/watch?v=_vDACE13Ubc&list=PLyebPLlVYXCiYdYaWRKgCqvnCFrLEANXt&index=1 [스프링 부트 입문 - 홍팍]

profile
p(´∇`)q

0개의 댓글