spring boot의 구조를 살펴보고 각 기능별로 살펴보겠습니다.
구조
Spring boot는 목적에 따라 패키지를 따로 생성해서 프로젝트를 관리하는데 크게 나누어 보자면 다음과 같다.
- Controller
- DTO
- Service
- Repository
- Domain (Entity)
Domain
DB 테이블과 직접 맵핑되는 클래스로서 JPA 사용 시 어노테이션을 이용하여 테이블, 필드, 등을 설정한다.
또한 Domain과 Client를 직접 연동하지 않고 DTO를 통해 분리하는 이유가 있는데,
- Client 쪽과 연결된 부분은 잦은 변경사항이 있을 수 있는데 Domain과 연결되어 자주 변경되게 된다면 여러 클래스에 영향을 미치기 때문에 분리한다.
- DTO는 Domain Model을 복사한 형태로 다양한 Presentation Logic을 추가한 정도로 사용하며 Domain Model 객체는 Persistent만을 위해서 사용한다.
- View 단과 DB 단을 확실하게 분리하기 위해서
Domain의 예시를 보면 아래와 같다.
@Entity
@Table(name = "post")
public class Posts {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(length = 500, nullable = false)
private String title;
@Column(columnDefinition = "TEXT", nullable = false)
private String content;
private String author;
@Builder
public Posts(String title, String content, String author){
this.title = title;
this.content = content;
this.author = author;
}
public void update(String title, String content) {
this.title = title;
this.content = content;
}
}
Domain에서 사용하는 어노테이션에는 여러 종류가 있는데 그중 몇 가지를 보자면
- Entity - 테이블과 1:1로 맵핑되는 어노테이션 [해당 어노테이션이 붙으면 JPA가 해당 클래스를 관리함]
- Id - PK를 지정하는 어노테이션
- Column - 필드에 붙이는 어노테이션 [해당 어노테이션이 붙으면 컬럼으로 인식]
- Builder - Builder 패턴을 사용하기 위한 어노테이션
등이 있다.
Repository
repository는 DB에 접근하는 소스코드를 모아둔 Interface다.
JpaRepository interface를 상속받아서 관리하고자 하는 클래스, ID 필드 타입을 JpaRepository<Entity Class, PK type>
같이 넣어주면 자동으로 DB와 CRUD 연결을 할 수 있는 메소드를 생성해준다.
public interface MemberRepository extends JpaRepository<Member, Long> {
}
위 코드처럼 사용하면 된다.
DTO
DTO는 말 그대로 Data Transfer Object로 "데이터 전송 객체"이다.
Service나 Controller에서 DB에 접근할 때 사용하는 클래스로 Domain과 차이점이 있는데
Domain은 DB 테이블에 대한 정보를 가지고 있는 클래스이고, DTO는 해당 테이블에서 실제로
CRUD를 할 필드를 정의해둔 것이라고 보면 된다. 따라서 테이블에 대한 정보를 작성하는
Domain 클래스와 DB에 접근하는 필드에 관한 내용을 작성하는 DTO 클래스를 사용하며
Domain과 마찬가지로 Builder 패턴을 사용할 수 있습니다.
아까 위에 있던 Domain과 같은 클래스가 있다고 가정했을 때
@Getter
@NoArgsConstructor
public class PostSaveRequestDto {
private String title;
private String content;
private String author;
}
이런식으로 연결 통로를 만들어주면 된다.
Service
Repository와 DTO를 통해 DB에 접근하여 CRUD의 각각의 프로세스 관리와 예외처리 등을 담당한다.
@Service 어노테이션을 붙이면 스프링에서 관리하는 객체가 된다.
Domain과 DTO를 나눈 것과 마찬가지로 Service와 Controller를 나눈 이유가 있는데
- 중복 코드가 생기기 때문이다.
- 중복 코드가 발생하면 모듈화를 통해 나눠주어 유지 보수를 하기 편하다.
- 기능을 세분화 하여 Service에 등록하면 추후 기능을 조합하기만 해서 새로운 기능을 만들 수 있다.
- Service에서 다른 Service를 의존성 참조하는 것도 가능하다.
즉 Service를 사용하는 이유는 확장성, 재사용성, 중복 코드의 제거이다.
@Service
public class InfoService {
public Project getProjectInfo() {
Project project = new Project();
project.projectName = "preword";
project.author = "hello-bryan";
project.createdDate = new Date();
return project;
}
}
@Service 어노테이션을 통해 Spring은 beanFactory에 담게 되고, @Autowired를 사용하는 곳에 해당 bean을 찾아 주입한다.
Controller
Http 요청과 응답을 위한 클래스로서 제일 앞단이라고 볼 수 있다.
@Controller 어노테이션을 통하여 bean에 등록되고 스프링에서 관리됩니다.
@Controller
@RequestMapping("/hello")
public class hello {
@Resource(name = "userService")
private UserService userService;
@PostMapping(value = "/info")
public @ResponseBody User info(@RequestBody User user){
return userService.retrieveUserInfo(user);
}
@GetMapping(value = "/view")
public String view(Model model, @RequestParam(value = "userName", required = true) String userName){
User user = userService.retrieveUserInfo(userName);
model.addAttribute("user", user);
return "/user/userView";
}
}
위와 같은 느낌으로 Method를 설정하고 인자를 사용하여 처리한다.
MVC 패턴을 준수하며 코드를 작성하는게 절대 쉬운 일은 아니지만 최대한 생각하며 작성하고 코드 효율을 높이는
방법을 항상 생각해야겠다.
'Java > Spring Boot' 카테고리의 다른 글
Spring boot RestAPI 파일 다운로드 (0) | 2023.02.10 |
---|---|
Spring boot Controller Zip 압축 해제 (0) | 2023.01.25 |
Spring boot H2 DB 설정 (0) | 2022.11.10 |
[Spring boot + React] Rest Api 연동하기 (0) | 2022.08.16 |
Spring boot Scheduler 구현하기 (0) | 2022.06.07 |