API를 만들기 위한 3개의 클래스
1. Request 데이터를 받을 Dto
2. API 요청을 받을 Controller
3. 트랜잭션, 도메인 기능 간의 순서를 보장하는 Service
스프링 웹 계층은 다음과 같다.
비즈니스 처리를 담당하는 부분은 Domain이다. 모든 로직이 서비스 클래스 내부에서 처리가 된다면 서비스 계층이 무의미하고, 객체란 단순히 데이터 덩어리 역할을 하게 된다. (자세한 내용은 책 참고해주세요!)
그렇기 때문에 이 실습에서는 도메인 모델을 다루고 코드를 작성한다.
각각의 클래스 생성 (경로는 패키지명 참고)
<PostsSaveRequestDto>
package com.jojoldu.book.springboot.web.dto;
import com.jojoldu.book.springboot.domain.posts.Posts;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
@Getter
@NoArgsConstructor
public class PostsSaveRequestDto {
private String title;
private String content;
private String author;
@Builder
public PostsSaveRequestDto(String title, String content, String author){
this.title = title;
this.content = content;
this.author = author;
}
public Posts toEntity(){
return Posts.builder()
.title(title)
.content(content)
.author(author)
.build();
}
}
<PostApiController>
package com.jojoldu.book.springboot.web;
import com.jojoldu.book.springboot.service.posts.PostsService;
import com.jojoldu.book.springboot.web.dto.PostsSaveRequestDto;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
@RequiredArgsConstructor
@RestController
public class PostApiController {
private final PostsService postsService;
@PostMapping("/api/v1/posts")
public Long save(@RequestBody PostsSaveRequestDto requestDto){
return postsService.save(requestDto);
}
}
<PostsService>
package com.jojoldu.book.springboot.service.posts;
import com.jojoldu.book.springboot.domain.posts.PostsRepository;
import com.jojoldu.book.springboot.web.dto.PostsSaveRequestDto;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import javax.transaction.Transactional;
@RequiredArgsConstructor
@Service
public class PostsService {
private final PostsRepository postsRepository;
@Transactional
public Long save(PostsSaveRequestDto requestDto){
return postsRepository.save(requestDto.toEntity()).getId();
}
}
스프링에서는 Bean을 주입받는 방식은 다음과 같다.
1. @Autowired (권장 안함)
2. setter
3. 생성자 (권장)
생성자로 Bean 객체를 받으면 @Autowired와 동일한 효과를 볼 수 있다. 그리고 @ReauiredArgsConstructor에서 final이 선언된 모든 필드를 인자값으로 하는 생성자를 생성해준다.
생성자 대신 롬복 어노테이션을 사용하는 이유?
클래스의 의존성 관계가 변경될 때마다 생성자 코드를 계속해서 수정하는 번거로움을 해결하기 위해
PostsSaveRequestDto는 Entity 클래스(posts) 와 거의 유사하다. 하지만 절대로 Entity클래스를 Request/Response클래스로 사용하면 안된다. Entity 클래스는 DB와 맞닿은 핵심 클래스이기 때문에 이를 기준으로 테이블 생성 및 스키마가 변경된다. 그렇기 때문에 이를 변경하는 것은 좋지 않은데, Req/Res 용 Dto는 View를 위한 클래스이기 때문에 자주 변경이 된다.
Entity클래스와 Controller에서 쓸 Dto는 분리해서 사용하기 !
테스트 코드 작성하기
==진행 중단==
테스트 코드를 작성하는 과정에서 오류가 발생했다. 같은 패키지 내에 있는 클래스를 불러오지 못하는 현상이 나타났고, 그 현상으로 고치려고 했으나 책이 19년도에 발행한 책이기 때문에 현재 기술이 너무 빠르게 발전을 해서 버전이 안맞거나 오류가 종종 났었다. 그래도 잘 작동이 되길래 문제 없이 진행했고, 오류가 발생해도 그때마다 구글링을 통해서 해결하고 진행을 했으나 진행을 더이상 할 수가 없었다.. 그래서 우선 이 책에 대한 실습은 더 이상 진행하지 못할 것 같다ㅠㅠ
그래서 아마 김영한님의 강의를 실습하는 단계로 넘어가지 않을까 싶다.
-> 원래는 김영한님의 스프링 기초 강의도 글을 올렸는데 그렇게 하면 너무 시간이 오래걸리고 루즈해져서 일단 강의먼저 완강하려고 한다.
참고
http://www.yes24.com/Product/Goods/83849117
'개발 공부 > Spring' 카테고리의 다른 글
[Spring+MySql] Spring에 AWS RDS(MySQL) 연결하기 / driver 에러 해결 (0) | 2023.03.06 |
---|---|
[SpringBoot] JPA로 데이터베이스 다루기 (0) | 2023.01.28 |
[SpringBoot] 롬복 소개 및 설치 (0) | 2023.01.27 |
[Springboot] 스프링 부트에서의 테스트 코드 (0) | 2023.01.26 |
[SpringBoot] 스프링부트 프로젝트 세팅하기 (0) | 2023.01.25 |