서비스 계층 만들기

1. 게시글 조회 요청 개선하기 (좌 → 우)

// GET
    @GetMapping("/api/articles")
    public List<Article> index() {
        return articleService.index();
    }
// GET
    @GetMapping("/api/articles")
    public List<Article> index() {
        return articleRepository.findAll();
    }
@GetMapping("/api/articles/{id}")
public Article show(@PathVariable Long id) {
	return articleService.show(id);
}
@GetMapping("/api/articles/{id}")
public Article show(@PathVariable Long id) {
	:eturn articleRepository.findById(id).orElse(null);
}

2. 게시글 생성 요청 개선하기

// POST
@PostMapping("/api/articles")
public ResponseEntity<Article> create(@RequestBody ArticleForm dto) { // 1. 서비스로 게시글 생성
	Article created = articleService.create(dto); // 객체 이름 created로 변경
	return articleRepository.save(created);
}
       // 2. 반환형 수정
public ResponseEntity<Article> create(@RequestBody ArticleForm dto) {
	Article created = articleService.create(dto);
	return (created != null) ? // 1. 생성하면 정상, 실패하면 오류 응답
		ResponseEntity.status(HttpStatus.OK).body(created) :
		ResponseEntity.status(HttpStatus.BAD_REQUEST).build();
}
public Article create(ArticleForm dto) {
	Article article = dto.toEntity(); // 1. dto-> 엔티티로 변환하고 article에 저장
	return articleRepository.save(article); // 2. article을 DB에 저장
public Article create(ArticleForm dto) {
        Article article = dto.toEntity();
        if (article.getId() != null) {
            return null;
        }
        return articleRepository.save(article);
    }

3. 게시글 수정 요청 개선하기

public ResponseEntity<Article> update(@PathVariable Long id,
                                      @RequestBody ArticleForm dto) {
        Article updated = articleService.update(id, dto);
        return (updated != null) ?
                ResponseEntity.status(HttpStatus.OK).body(updated):
                ResponseEntity.status(HttpStatus.BAD_REQUEST).build();
    }
@Slf4j // 1. 로깅할 수 있게 어노테이션 추가
@Service
public class ArticleService {
	(중략)
	public Article update(Long id, ArticleForm dto) {
        // 1. DTO -> 엔티티 변환하기
        Article article = dto.toEntity();
        log.info("id: {}, article: {}", id, article.toString());

        // 2. 타겟 조회하기
        Article target = articleRepository.findById(id).orElse(null);

        // 3. 잘못된 요청 처리하기
        if (target == null || id != article.getId()) {
            // 400번, 잘못된 요청 응답!
            log.info("잘못된 요청! id: {}, article: {}", id, article.toString());
            return null; // 2. 응답은 컨트롤러가 하므로 여기서는 null 반환
        }

        // 4. 업데이트 및 정상 응답(200)하기
        target.patch(article);
        Article updated = articleRepository.save(target);
        return updated; // 3. 응답은 컨트롤러가 하므로 여기서는 수정 데이터만 반환
    }

4. 게시글 삭제 요청 개선하기

public ResponseEntity<Article> delete(@PathVariable Long id) {
        Article deleted = articleService.delete(id); // 1. 서비스를 통해 게시글 삭제
        return (deleted != null) ? // 2. 삭제 결과에 따라 응답 처리
                ResponseEntity.status(HttpStatus.NO_CONTENT).build() :
                ResponseEntity.status(HttpStatus.BAD_REQUEST).build();
    }
public Article delete(Long id) {
        // 1. 대상 찾기
        Article target = articleRepository.findById(id).orElse(null);

        // 2. 잘못된 요청 처리하기
        if (target == null) {
            return null; // 1. 응답은 컨트롤러가 하므로 여기서는 null 반환
        }

        // 3. 대상 삭제하기
        articleRepository.delete(target);
        return target; // 2. DB에서 삭제한 대상을 컨트롤러에 반환
    }

트랜잭션 맛보기