클라이언트가 서버에 요청한 내용을 하나의 클래스에서 모두 처리한다고 생각해보자.
어떤 HTTP 요청이 들어왔는지 확인해서, DB에서 어떻게 가져와야할지, 가져온 데이터를 어떻게 처리할지, 그리고 어떻게 보내줄지를 모두 한 클래스에서 작성하게 된다면...
간단한 메서드 정도는 문제 없을지 몰라도
메서드 로직이 복잡해지고, 유지보수 시 수정해야할 코드가 생기게 되면 막막할것이다.
따라서 클래스별로 역할을 구분할 필요가 있다.
그럼 어떻게 역할 구분을 해야할까?
- 사용자 요청: 사용자가 웹 애플리케이션에 요청을 보냅니다.
- Controller:
요청을 받아 해당 메서드를 호출합니다.
필요한 데이터를 DTO 형태로 Service에 전달합니다. - Service:
Controller로부터 받은 DTO를 기반으로 비즈니스 로직을 실행합니다.
필요한 경우 DAO를 호출하여 데이터베이스에서 정보를 가져옵니다. - DAO:
데이터베이스와 연결되어 CRUD 작업을 수행합니다.
결과를 Service에 반환합니다. - Service:
DAO로부터 받은 데이터를 가공하여 다시 DTO 형태로 Controller에 전달합니다. - Controller:
최종적으로 가공된 DTO를 클라이언트에게 응답으로 반환합니다.
컨트롤러 클래스란?
- 요청 처리:
클라이언트로부터 들어오는 HTTP 요청을 수신하고, 해당 요청에 대한 적절한 처리를 수행합니다. - 응답 생성:
요청 처리 결과를 바탕으로 클라이언트에게 반환할 응답을 생성합니다.(예 - 성공적인 요청에 대해 200 OK를 반환) 이 과정에서 데이터 포맷(JSON, XML 등)을 설정할 수 있습니다. - URL 매핑:
리퀘스트된 HTTP 메서드(GET-리소스 조회, POST-리소스 생성, PUT-리소스 업데이트, DELETE-리소스 삭제 등)에 따라 적절한 메서드를 호출하도록 매핑합니다. 이를 통해 RESTful API를 구현할 수 있습니다. - 데이터 검증:
클라이언트가 보낸 데이터의 유효성을 검사하고, 필요한 경우 오류 메시지를 반환(예-오류 발생 시 400 등 적절한 에러 코드를 반환)합니다. - 서비스 호출:
비즈니스 로직을 담당하는 서비스 클래스를 호출하여 필요한 데이터를 처리하거나 저장합니다. - Spring에서는 @RestController 어노테이션을 사용하여 RESTful 웹 서비스를 구현합니다.
서비스 클래스란?
- 비즈니스 로직 처리:
서비스 클래스는 애플리케이션의 비즈니스 로직을 구현합니다. 이는 데이터베이스와의 상호작용을 포함하여, 여러 리포지토리에서 데이터를 조회하고 가공하여 최종적으로 컨트롤러에 전달하는 과정을 포함합니다. - 모듈화:
서비스 클래스를 사용하면 코드의 모듈화가 가능해집니다. 여러 컨트롤러에서 공통적으로 사용되는 기능을 서비스로 분리하여, 중복 코드를 줄이고 유지보수를 용이하게 합니다. 예를 들어, 여러 컨트롤러가 동일한 데이터 처리 로직을 필요로 할 때, 이를 서비스로 만들어 재사용할 수 있습니다. - 보안 강화:
서비스를 통해 데이터베이스에 접근하도록 구현하면, 컨트롤러는 리포지토리에 직접 접근하지 않게 되어 보안성을 높일 수 있습니다. 해커가 컨트롤러를 제어하더라도 리포지토리에 직접 접근할 수 없도록 하는 구조입니다. - DTO와 엔티티 변환:
서비스 클래스는 엔티티 객체와 DTO(Data Transfer Object) 간의 변환을 담당합니다.
엔티티는 데이터베이스와 직접 연결된 객체로, 이를 컨트롤러나 뷰에 직접 사용하기보다는 DTO를 통해 필요한 속성만 전달하는 것이 좋습니다. 이렇게 하면 데이터의 무결성을 유지하고 비즈니스 요구사항에 맞게 데이터를 조작할 수 있습니다. - 의존성 주입 및 IoC :
Spring 프레임워크는 의존성 주입(Dependency Injection)과 제어의 역전(Inversion of Control-객체의 생성 및 제어를 개발자가 아닌 프레임워크나 컨테이너에 맡기는 것을 의미) 기능을 제공합니다.
서비스 클래스는 이러한 기능을 활용하여, 리포지토리와 같은 다른 컴포넌트를 쉽게 주입받아 사용할 수 있습니다. - Spring에서는 @Service 어노테이션을 사용하여 정의합니다.
DAO 클래스란?
- 데이터베이스 연결:
DAO 클래스는 데이터베이스와의 연결을 관리합니다. JDBC, JPA, Hibernate 등의 기술을 사용하여 데이터베이스와 상호작용합니다. - CRUD 작업 수행:
데이터 생성, 조회, 수정, 삭제와 같은 기본적인 데이터 작업을 수행합니다. - 데이터 접근 로직 분리:
비즈니스 로직(Service 클래스)과 데이터 접근 로직을 분리하여 코드의 가독성을 높이고, 테스트를 용이하게 합니다. - Spring에서는 @Repository 어노테이션을 사용하여 정의합니다.
JDBC란?
Java DataBase Connectivity는 DB에 연결 및 작업을 하기 위한 자바 표준 인터페이스
JDBC의 역할
데이터베이스 종류마다(Oracle, MYSQL,PostgreSQL...) 각각의 SQL문을 사용하는데, 각각의 작성 방식이 다릅니다.
이 문제를 해결하고자 JDBC가 등장했습니다.
- 다양한 종류의 DB에 일관된 방식으로 접근 = DB접근 표준화
- SQL문 실행, 데이터 CRUD 작업 수행을 위한 표준 인터페이스 제공 = 데이터베이스 작업 수행 표준화
- 자바 애플리케이션과 DBMS 사이에서 통신을 중개, 번역하는 역할
JDBC는 자바 개발자가 데이터베이스 작업을 효율적으로 수행할 수 있게 해주는 강력한 도구입니다.
이를 통해 개발자는 데이터베이스의 종류에 관계없이 일관된 코드를 작성할 수 있으며, 애플리케이션의 유지보수성과 확장성을 크게 향상시킬 수 있습니다.
DTO 클래스란?
- 데이터 캡슐화:
DTO는 여러 개의 데이터를 하나의 객체로 묶어 전송할 수 있게 해줍니다. 이를 통해 네트워크 호출 시 전송하는 데이터의 양을 줄일 수 있습니다. - 계층 간 데이터 전송:
DTO는 주로 프레젠테이션 계층과 서비스 계층, 또는 서비스 계층과 데이터 접근 계층 간에 데이터를 전송하는 데 사용됩니다. - 비즈니스 로직 분리:
DTO는 비즈니스 로직을 포함하지 않기 때문에, 데이터 구조와 비즈니스 로직을 명확히 분리할 수 있습니다. 이는 코드의 가독성을 높이고 유지보수를 용이하게 합니다. - 유효성 검사:
DTO를 사용하면 클라이언트에서 입력한 데이터를 서버에 전달하기 전에 유효성 검사를 수행할 수 있습니다.
Entity 대신 DTO를 사용하는 이유
- View Layer와 DB Layer의 역할을 분리하기 위해서
객체를 표현하기 위한 계층과 객체를 저장하는 계층의 역할을 분리 - Entity 객체의 변경을 피하기 위하여
테이블과 매핑되어있는 Entity 클래스를 요구사항마다 변경하게되면 여러 클래스에 영향을 끼치게 된다. - View와 통신하는 DTO 클래스는 요구사항에 따라 변경된다.
View(클라이언트)와 통신하는 DTO 클래스(View Layer), 예를 들어 ResDTO, ReqDTO는 요구사항에 따라 자주 변경된다.
어떤 요청에서는 특정 값이 추가될 수도 있고, 특정값이 없을 수도 있다.
DTO에 요구사항에 따른 로직을 추가해 ENtity의 도메인 모델링을 지킬 수 있다.