원글 페이지 : 바로가기

➡️ 스프링 프레임워크의 구조와 동작원리 생각하기에 따라 각 요소의 종류에 따라 포함관계, 순서, 설명이 일부 달라질 수 있는 점 양해 바랍니다. 각 구성요소에 대한 설명은 여기를 참고해주세요. 아래 글에서도 주요 구성요소마다 같은 링크가 첨부되어 있습니다. 1~2. 클라이언트(사용자, 웹 브라우저 등)가 애플리케이션으로 HTTP 요청(HttpServletRequest)을 보내면 가장 먼저 View에 전달이 되게 되고, Apache Tomcat과 같은 WAS/Servlet Container에서 요청에 대한 처리가 이루어진다. 3~4. Servlet Container는 웹 설정(web.xml, application.properties, application.yml)에 따라 Spring Framework가 처리하겠다는 설정이 있는 경우 이를 읽어들여, DispatcherServlet에게 HttpServletRequest를 전달한다. 이제부터 Apache Tomcat 위에서 요청이 처리되어 최종적으로 클라이언트에게 반환될 것이다. 1) DispatcherServlet은 HandlerMapping 인터페이스에게 HttpServletRequest에 대한 처리를 요청한다. 2) HandlerMapping은 HttpServletRequest에서 URL과 메서드 등을 확인하여 매핑할 Controller(핸들러)가 있는지 먼저 확인한다. 실제로는 HandelrMapping는 인터페이스로, 직접 작업을 수행하는 것이 아니라 HandlerMapping의 구현체들이 요청을 처리한다. HandlerMapping의 구현체로는 RequestMappingHandlerMapping, SimpleUrlHandlerMapping, BeanNameUrlHandlerMapping가 있다. 3~4) 매핑할 Controller가 있을 경우 HandlerAdaptor가 핸들러 실행을 위한 메커니즘은 제공해준다. HandlerAdaptor는 매핑된 컨트롤러와 @RequestMapping을 통해, 해당 요청을 처리할 메서드를 인식하고 매핑 Controller를 호출한다. 5) 호출된 Controller는 코드에 따라 Service에게 비지니스 로직 처리를 요청한다. 6) Service는 DAO(EX. Spring JPA, JDBC, MyBatis)에게 데이터 처리 요청을 한다. 이때, 요청 및 응답 데이터 형식은 특수한 목적을 이루기 위해 간~혹 DTO를 사용하는 경우도 있지만, 대부분의 경우에 Entity을 사용한다. 참고로 Spring MVC에서 Service와 DAO를 묶어 Model라고 부른다. 7) DAO는 데이터베이스에 접근하여 쿼리를 수행한다. 이때 요청 및 응답 데이터 형식은 DAO에 따라 Entity일수도 DTO일수도 있다. 8) Controller는 ModelAndView 객체를 반환한다. 9) ViewResolver는 ModelAndView 객체에서 Viewname을 추출해, 이를 기반으로 View로 변환하고 DispatcherServlet에게 전달한다. 10) DispatcherServlet은 전달받은 View를 HttpServletResponse 객체에 담아 클라이언트에게 응답한다. 그러면 클라이언트에서 텍스트 형식인 HttpServletResponse를 받아서 파싱하는 등의 처리를 진행한다. 최종적으로 화면에 View가 렌더링된다. ✅ Controller와 Service 사이에서 주고받는 데이터의 형태 : DTO를 사용한다. 애플리케이션의 계층 간 데이터 전달을 간소화하고 관리하기 위해 사용되며, 특히 사용자 요청을 처리하거나 응답을 반환할 때 사용된다. import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping(“/users”)
public class UserController {
@Autowired
private UserService userService;
@PostMapping
public void createUser(@RequestBody UserDTO userDTO) {
userService.createUser(userDTO);
}
@GetMapping(“/{id}”)
public UserDTO getUser(@PathVariable Long id) {
return userService.getUser(id);
}
} ✅ Service와 DAO 사이에 주고 받는 데이터의 형태 : 일반적으로 Entity를 사용하지만 경우에 따라 DTO를 사용하기도 한다. JPA의 경우에도 마찬가지로 보통은 Entity를 사용하지만 특수한 경우에는 Dto를 사용하기도 하니 아래의 예시를 참고하자. Entity를 사용하는 경우 @Service
public class UserService {
@Autowired
private UserDAO userDAO;
public void createUser(String username, String email) {
User user = new User();
user.setUsername(username);
user.setEmail(email);
userDAO.save(user);
}
public User getUser(Long id) {
return userDAO.findById(id);
}
} DTO를 사용하는 경우 서비스와 DAO 간 데이터 변환 복잡한 변환 필요 : 비즈니스 로직에 필요한 데이터가 복잡하거나, 엔티티와 데이터베이스 스키마 간의 차이로 인해 DTO를 사용하여 필요한 데이터만 필터링하거나 변환할 때 유용하다. 쿼리 결과 : 특정 데이터베이스 쿼리의 결과를 DTO로 반환하여 필요한 데이터만 포함시킬 수 있다. 이는 특히 복잡한 쿼리나 집계 쿼리에서 유용하다. 필터링 및 데이터 축소 필터링 : 데이터베이스에서 많은 양의 데이터를 조회하고, 서비스 계층에서 필요한 부분만 DTO로 가공하여 사용하는 경우에 새용한다. 비즈니스 요구사항 : 비즈니스 로직에서 필요한 특정 데이터만 DTO로 반환하여 클라이언트에 전달하거나, 필요한 데이터를 기반으로 DTO를 구성한다. 스프링 데이터 JPA의 Projections JPA에서는 인터페이스 기반의 프로젝션을 사용하여 DTO를 반환할 수 있다. 이는 쿼리 결과를 DTO로 직접 매핑할 수 있게 해wns다. //필터링 및 데이터 축소
@Service
public class UserService {
@Autowired
private UserDAO userDAO;
public UserDTO getUser(Long id) {
User user = userDAO.findById(id);
return new UserDTO(user.getId(), user.getUsername(), user.getEmail());
}
public UserDTO findUserByCustomQuery(Long id) {
return userDAO.findUserDTOById(id);
}
} //스프링 데이터 JPA의 Projections
@Repository
//UserDAO를 보통 UserRepository로 명명한다.
public interface UserDAO extends JpaRepository
@Query(“SELECT u.id AS id, u.username AS username, u.email AS email FROM User u WHERE u.id = :id”)
UserDTO findUserDTOById(@Param(“id”) Long id);
} ✅ DAO와 Database 사이에서 주고받는 데이터의 형태 : 목적에 따라 DTO 또는 Entity를 사용한다. Entity를 사용하는 경우 : JPA (Java Persistence API)와 같은 ORM (Object-Relational Mapping) 프레임워크 개념과 목적 : 데이터베이스와의 데이터 매핑 및 상호작용을 목적으로, 데이터베이스 테이블의 구조와 매핑되는 자바 객체로 Entity는 데이터베이스와의 직접적인 상호작용을 처리한다. 역할 : 데이터베이스 테이블의 각 행을 자바 객체로 표현한다. 예를 들어, User라는 Entity 클래스는 users라는 테이블의 구조와 일치한다. 특징 : 주로 @Entity, @Table, @Id 등의 JPA 어노테이션을 사용하여 정의된다. 데이터베이스에 저장된 정보와 직접적인 매핑을 제공하며, CRUD (Create, Read, Update, Delete) 작업에 주로 사용된다. DAO와의 관계 : DAO는 Entity 객체를 사용하여 데이터베이스와 상호작용하며, Entity를 매개로 데이터베이스의 데이터를 CRUD 작업을 수행한다. 예를 들어, DAO는 Entity를 save(), findById(), update(), delete() 메서드를 통해 조작한다. DTO를 사용하는 경우 개념과 목적 : 애플리케이션 계층 간의 데이터 전송을 목적으로 하며, 데이터베이스와의 직접적인 상호작용을 다루지 않는 데이터 전송을 위해 간단히 구조화된 자바 객체이다. 특징 : 일반적으로 단순한 데이터 필드와 getter/setter 메서드를 가진 POJO (Plain Old Java Object)이다. Entity 객체의 일부 필드만을 포함하거나, 복잡한 객체 구조를 단순화하여 필요한 데이터만 전송해 성능 향상을 목적으로 사용하기도 한다. 데이터 전송과 관련된 추가적인 로직이 없으며 주로 데이터만 포함한다. DAO의 관계 : DTO는 DAO와 직접적인 상호작용을 하지는 않지만, 비즈니스 로직과 웹 레이어 또는 서비스 레이어 간의 데이터 전달에 사용된다. ➡️ 참고자료 [블로그] https://devscb.tistory.com/119 https://velog.io/@dyunge_100/Spring-%EC%8A%A4%ED%94%84%EB%A7%81-%ED%94%84%EB%A0%88%EC%9E%84%EC%9B%8C%ED%81%ACSpring-Framework%EC%9D%98-%ED%8A%B9%EC%A7%95%EA%B3%BC-%EA%B5%AC%EC%A1%B0