본문 바로가기

스프링

애플리케이션 아키텍처_이론_VO

* 아키텍처 : 내부 구성요소들이 어떤 책임을 갖고 있고, 어떤 방식으로 서로 관계를 맺고 동작하는지를 규정

 

POJO : 객체지향적인 원리에 충실하면서, 환경과 기술에 종속되지 않고 필요에 따라 재활용될 수 있는 방식으로 설계된 오브젝트

 

 

 

계층형 아키텍처(layered architecture) : 책임과 성격이 다른 것을 크게 그룹으로 만들어 분리해두는 것

 

* 아키텍처 : 내부 구성요소들이 어떤 책임을 갖고 있고, 어떤 방식으로 서로 관계를 맺고 동작하는지를 규정

> 위처럼 아키텍처 및 스프링 컨텍스트를 웹기술의 서블릿컨텍스트/비즈니스 서비스, 데이터 액세스 계층을 담은 루트 컨텍스트로 나누는 이유는 서블릿 컨텍스트를 통째로 다른 기술로 대체할 수 있도록 하기 위해서.

 

 

 

 

 

 

서비스는 API를 직접 다루는 코드가 아니다(JDBC API등을 다룬 DAO를 호출하는 코드임). API를 호출하는 형태로 순수 비즈니스 로직만 담아야 한다.(어떤 구현에 종속되어서는 안된다.)

 

 

 

* 프레젠테이션 계층 : 브라우저상의 웹 클라이언트의 요청 및 응답을 처리

 

 

* 컴포넌트 : 다 코딩하는 것이 아닌 소프트웨어 구성단위(module)를 미리 만든 뒤 필요한 응용 기술을 조립하는 기술

* 서드파티(3) : 프로그래밍을 도와주는 플러그인이나 라이브러리(제조자와 사용자 이외 외부의 생산자를 가르킴)

 

 

 

DAO에는 ResultSet, SQLException을 사용하면 JDBC를 사용하는 강한 결합의 형태가 된다.

 

 

 

따라서 List<User> 와 같은 특정 계층의 기술이나 구현에 종속되어서는 안된다.

*HttpServeltRequest, HttpServletResponse와 같은 타입을 사용하면 JSP Servlet 웹 기술에 종속되는 코드가 되어 재사용이 불가능해짐.

 

 

 

* 접근제어자를 깊이 생각하여 꼭 필요한 부분만 노출시키도록 주의

 

 

* 엔터프라이즈 애플리케이션 : 서버에서 동작하며 기업과 조직의 업무를 처리해주는 시스템. 많은 사용자의 요청을 동시에 처리해야 하기 때문에 서버의 자원을 효율적으로 공유하고 분배해서 사용할 수 있어야한다.

 

 

 

DB/SQL 중심의 로직 구현 : 보통 사용하는 것. 모든 계층의 코드가 조회라는 업무에 종속됨. 내가 보통 사용하던 방식. SQL이 번잡해지고 각 계층은 DB와 클라이언트를 연결해주는 단순 인터페이스로 전락한다.

 

 

 

 

 

* DB(데이터)중심의 아키텍처 (아키텍처 : 내부 구성요소들이 어떤 방식으로 서로 관계를 맺고 동작하는지를 규정)

- 단점

> SQL에 종속되기 때문에 SQL의 변화가 일어나면 각 계층이 같이 변경되어야 한다.

> 필드 하나가 달라져도 거의 비슷한 DAO 메소드를 새로 만들어야 한다.

- 장점

> 많은 개발자들이 추구하긴함. 독립적으로 만드는데 편함.

> 잘 작성된 SQL 하나가 수백 라인의 자바코드가 필요한 비즈니스 로직을 한번에 처리 가능.

 

* 복잡한 SQL을 누구사 쉽고 유연하게 변경가능할까? DB에 부담을 주는게 바람직 할까?

 

DB(데이터) 중심의 업무단위로 코드를 생성하는 것보다는 오브젝트는 비용이 더 적다.

 

 

DB(데이터) 중심의 아키텍처를 선택한다면 스프링의 장점을 제대로 누릴 수 있는 기회를 얻지 못한다.

 

 

 

 

 

 

* 애플리케이션 코드 중심의 아키텍처(아키텍처 : 내부 구성요소들이 어떤 방식으로 서로 관계를 맺고 동작하는지를 규정)

- 장점

> DAOSQL은 상대적으로 단순해지고, 애플리케이션 코드의 비중이 커지는 만큼, 구조는 단순해지고 객체지향 개발의 장점을 살릴 기회가 많아진다.

> 자바 언어로 비즈니스로직이 구현되므로 테스트하기가 수월해진다.

> 각 업무별로 독립적인 개발이 가능하므로 초기 개발 속도가 빠르고, 개발자 사이에 간섭이 없어 독립적인 개발이 가능.

- 단점

> 비즈니스 로직이 복잡해지면 서비스 계층의 코드도 매우 복잡해지고 커진다. 거대한 서비스 계층(fat service layer)을 만들게됨.

> 비즈니스 로직에 따라 SQL이 작성되므로 여전히 결합도가 크다

> 비슷한 기능들이 비즈니스로직에 중복되어 나타나기 쉽다. .(공통으로 뽑을 수도 있지만 일반화하기 쉽지 않다. DAO가 제공하는 값에 따라 포맷과 타입이 달라 공통적인 기능을 만들어 사용하기 힘들다.)

> 본격적인 객체지향적 설계가 적용하기 힘들고, 개발자의 역량에 따라 더 복잡한 비즈니스로직이 될 수 있다.

> 수정시 힘들 수 있다 테스트조차 없다면 SQL보다 더 힘든 스파게티 코드로 전락할 수 있다.

 

 

 

 

카테고리 하나에 여러 개의 상품이 들어온다.

 

 

 

 

 

카테고리 하나에 여러 개의 상품이 들어오고, 상품은 하나의 카테고리를 갖는 관계를 설명이 가능하다.

 

 

 

 

 

 

 

 

 

 

* 오브젝트 중심 아키텍처

> 대개 도메인 모델은 DB의 엔티티 구조와 유사한 형태일 가능성이 높다. 비즈니스 로직에만 존재하는 모델도 있기 때문에 항상 일치하는 것은 아니다.

 

*예를 들어 하나의 카테고리에 여러개의 상품이 들어오는 테이블이 있다고 생각해보자

> 데이터 중심의 아키텍처

- SQL DB관점에서 생각. SQL JOIN을 이용해 2차원 구조의 정보를 맵이나 배열에 담는다.

- 서비스, 프레젠테이션 계층의 코드에서는 List<Map<String, Object>> 타입만 봐서는 안에 담긴 내용이 어떤 것인지 알 수 없다.DAO, SQL 레벨까지 내려가야 알 수 있다.

- 만약 DAO에서 SQL을 변경하거나 필드 개수나 순서, 이름을 바꾼다면 서비스, 프레젠테이션 계층의 코드도 같이 변경 돼야 한다.

- 1:N 관계에 대한 정보를 알 수 없다. SQL을 통해 가공된 데이터의 구조를 알아야 하고, 이를 활용하는 것이 전부이다.

 

> 도메인 모델 중심의 아키텍처

- 애플리케이션 전 계층에서 동일한 의미를 갖는다. SQL이나 웹 페이지의 출력 포맷, 입력 폼 등에 종속되지 않는 일관된 형식의 애플리케이션의 정보를 다룰 수 있게 된다.

- 1:N 관계에 대한 정보를 도메인 모델로 표현가능 (Set<Production> 공통제거한 상품리스트)

- DB Category 테이블에는 Product 테이블과 어떻게 연결되는지에 대한 정보가 없다. 하지만 자바에서는 레퍼런스 변수를 통한 상호 참조가 가능하기 때문에 원한다면 Category 오브젝트에서 다음과 같은 코드로 Category에 속한 Product를 간단히 가져올 수도 있다. Set<Product> products = myCategory.getProducts();)

- 데이터 중심은 조인으로 하나의 맵으로 뭉뚱그려서 가져왔지만, 오브젝트 중심은 Category 오브젝트와 그에 대응되는 Product 열이 5개라면, 5개의 Product가 만들어질 것이다.

 

* 이렇게 가져온 정보를 웹페이지에서 수정해서 다시 DB에 반영해야 한다면?

> 데이터 중심의 아키텍처

- 사용자가 수정한 정보는 다시 맵/배열에 담겨서 전달된다. DB 수정을 담당하는 DAO역시 데이터 구조를 알아야 한다.

 

> 도메인 모델 중심의 아키텍처

- Category Product 정보를 두개의 SQL에서 나눠 가져왔든, 하나의 SQL로 조인해서 가져왔든 상관없다. 서비스 계층에서 필요한 정보를 조건에 맞게 조회해서 도메인 모델 오브젝트 형태로 돌려주는 DAO를 이용하기만 하면 된다. 프레젠테이션 계층역시 어떤 비즈니스인지, 어떤 DAO인지 알필요없이 도메인 오브젝트를 활용해서 필요한 정보를 화면에 출력하기만 하면 된다.

- Category 도메인 모델에 모든 상품을 리턴하는 메서드를 만들어 모든데 공통으로 사용할 수 있고, 비즈니스로직도 줄어든다. (이전 예제의 레벨 오브젝트가 좋은 예임)

 

* 도메인 오브젝트 사용의 문제점

> DAO는 비즈니스 로직의 사용 방식을 알지 못하므로 모든 필드 값을 다 채워서 전달하는 경우가 대부분이어서 손해를 감수해야하는 부분이 존재한다.

> 만약 Product 정보만 필요한 비즈니스 로직은 Product 오브젝트에 관계를 갖고있는 오브젝트를 Category 정보를 포함하여 상당한 낭비가 발생한다.

> Product 정보를 가져올 때 Category가 필요한 경우와 그렇지 않은 경우를 구분해서 DAO를 만들어 줄 수 있지만, 그렇게 되면 데이터 중심 아키텍처의 단점인 DAO와 비즈니스 로직 코드의 결합도가 높아지는 문제가 발생할 수도 있다.

 

 

지연된 로딩(lazy loading) : 최소한의 오브젝트 정보만 읽어두고 관계하고 있는 오브젝트가 필요한 경우에만 다이내믹하게 DB에서 다시 읽어올 수 있다. 무론 그에 따라 DAO 메소드가 추가되고 어느 DAO를 사용할지 서비스 계층에서 알고 있어야 하기 때문에, 약해지긴 했지만 결합이 발생한다.

 

 

 

ORM(Hibernate, JDO, JPA)과 같은 오브젝트 중심 데이터 액세스 기술이 좋지만(지연된 로딩 기법을 자동으로 사용, 코드양이 줄고 데이터 효율도 좋아짐), JDBC를 이용하는 경우라면 지연된 로딩 기법을 추가하는 코드를 넣어 DAO메소드가 늘어나 약간의 결합도를 높이는 수 밖에 없다.

 

* 빈약한 도메인 오브젝트 방식 : 아무런 기능도 갖고 있지 않고 정보만 담겨있는 오브젝트

 

 

 

 

 

 

 

 

풍성한 도메인 오브젝트 방식

 

 

 

 

 

 

 

 

 

 

 

 

 

도메인 계층 방식

 

 

 

 

AspectJ AOP를 사용하면 도메인 오브젝트가 생성되는 시점에 오브젝트 수정자 메소드나 DI용 애노테이션을 참고해서 DI 가능한 대상을 스프링 컨테이너에서 찾아 DI 해주는 기능이다.

 

* 도메인 계층 방식은 많은 비즈니스 로직을 담을 수 있지만

> 자신과 관련 오브젝트에 대한 작업으로 한정돼야 한다. 여러 도메인 오브젝트의 기능을 조합할 때는 서비스계층과 협력을 통해 진행해야한다.

> 도메인 계층을 거치지 않고 바로 데이터 엑세스 계층으로부터 클라이언트에게 제공하는 경우도 서비스 계층이 인터페이스 역할을 담당한다.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

* 엔터프라이즈 애플리케이션 : 서버에서 동작하며 기업과 조직의 업무를 처리해주는 시스템. 많은 사용자의 요청을 동시에 처리해야 하기 때문에 서버의 자원을 효율적으로 공유하고 분배해서 사용할 수 있어야한다. HTTP를 통해 접근하는 웹클라이언트와 백엔드 DB를 사용하는 애플리케이션에 적합함.