프로젝트 설계단계에서 개발가이드 검토 중, 데이터 전달 형태를 Map으로 써야할 지 VO를 써야할 지 결정을 하지 못했다.

사실 둘의 차이를 명확하게 모르니 현 프로젝트에 어떤게 더 적합한지 판별하지 못했다.

과장님께 여쭤보고 들은 답변과 좀 더 찾아본 자료들을 합쳐 정리해두어야 겠다~


Q) Map과 VO의 차이는? 언제 Map을 쓰고 언제 VO를 써야하는가? ==> 목적에 맞게 ^_^




Q) VO란?

우선 관련 개념 정의는 아래와 같다.


(1) Java Beans

    : A Java Bean is a reusable software component that can be manipulated  visually in a builer tool.

    : 일반적으로 자바빈은 속성과, 그 속성에 대한 getter, setter 메서드로 구성된 데이터 객체(VO, Value Object)를 말하며

      데이터 전송에 사용되는 객체를 말한다.

    : 자바로 작성된 재사용 가능한 소프트웨어 컴포넌트

    : getter, setter 메서드를 통해 컴포넌트에 접근가능


    ** Java Bean Spec

     - Support for “introspection” so that a builder tool can analyze how a bean works

     - Support for “customization” so that when using an application builder a user can customize the appearance and behaviour of a bean.

     - Support for “events” as a simple communication metaphor than can be used to connect up beans.

     - Support for “properties”, both for customization and for programmatic use.

     - Support for persistence, so that a bean can be customized in an application builder and then have its customized state saved away and reloaded

       later.


(2) DTO

    : Data Transfer Object

    : 계층간 데이터 교환을 위한 객체

    : 일반적인 DTO는 로직을 가지고 있지 않다. 순수한 데이터 객체이며 속성과 속성에 접근하기 위한 getter, setter메서드로만 구성되는 POJO

      (** POJO: 특정 인터페이스 또는 클래스를 상속하지 않는 일반 자바 개체)




Q) VO 작성 시, getter setter  왜 필요한건지?


내가 개발자분들한테 DTO로 VO 사용하라고 가이드했으면서 사실 VO 자체에 대한 명확한 지식이 없었던 것 같다.

왜 변수를 private 으로 선언해 써야하는 건지, getter setter는 왜 매번 필요한건지?

생각해보면 다들 가이드 받은대로 VO 카피해서 사용하기 바쁘지 왜 이렇게 사용하는 것일까 생각은 많이 안하는 것 같다.


실제로 알아보니, 많은 프로그래머 사이에서 getter setter 가 정말 필요해서 쓰는 경우가 몇 프로나 될까 의심하는 사람들이 많았다.

아무 생각없이 써왔던거라 계속 쓰기는 하는데 개발자에게는 소스 작성은 귀찮고, 그에 비해 효과는 잘 모르겠는 존재인 것이다.


쓰더라도 알고쓰자는 심정으로 조사 좀하고 정리해보았다.


우선 VO에 getter, setter를 쓰는 경우

  - 변수에 새로운 값을 할당할 때마다 validation 검사 가능

  - lazy loading 가능

  - read와 write 권한 다르게 설정 가능(public, private 사용)

  - getter, setter는 캡슐화(encapsulation)를 구현하는 가장 기본적인 형태이다. 언뜻보면 그냥 변수를 public으로 선언하여 접근하는 것과

    별반 달라보이지 않는다. 하지만 public으로 선언하여 외부에서 객체의 각 변수에 접근하여 값을 변경하는 경우가 발생할 수 있다.

    객체의 상태는 오직 그 객체의 동작에 의해서만 접근/변경되도록 하는 게 맞다. 한 객체가 다른 객체의 필드를 변경하려는 경우, public

    method를 통해 객체의 상태(필드 값)를 변경해야 한다. 또한 외부에서 접근 가능한 public method는 최소한으로 해야한다.



정리하고 나니 의문이 드는점은, 캡슐화를 위한 방법으로 getter, setter 밖에 없는걸까? 이다. getter, setter 메서드로 접근할 수 있도록

하는 것이 진정한 캡슐화가 맞냐는 의문들도 많던데.. 캡슐화를 위해 사용했다고 하면, getter, setter말고는 다른 방법이 없는 것인지 궁금하다

또, 데이터 객체에 대한 정보 은닉이 항상 필요한가?? 라는 의문도 든다.  의례적으로 쓰고있는 건 아닌지....




Q) Map과 VO 사용 장단점?


(1) Map 사용 시

    [장점]

      - 현재 사내 프레임워크 권장사항은 select 시에는 Map으로, 나머지 CUD 작업은 VO 사용이다. select 하는 경우는 보통 2개 이상의 테이블을

        조인하여 조회하는 경우가 많아 VO로는 표현이 복잡하기 때문

     

    [단점]

      - Map의 key 또는 value가 null인 경우 Map은 해당 필드 자체를 key로 가져가지 않는다. 따라서 쿼리 수행 시, key 값 자체가 존재하지 않아

        오류 발생 (이 경우를 대비하여 쿼리에 jdbcType 선언 필요, 해당 값이 null일 경우 초기화 타입 지정)

      - 여러 타입을 담아야 하기 때문에 Map은 Value 선언 시 Object로 할 수 밖에 없다. 그러나 Object는 최상위 타입이기 때문에 type 이 매치되지

        않는 경우가 발생해도 실제로 돌려보지 않는 한 알 수가 없다.

      - Object로 선언하여 모든 타입을 담기 때문에, 부가적인 casting 작업이 발생 가능하다.


(2) VO 사용 시

    [장점]

      - 비즈니스 로직 상 데이터가 명확해야 하는 경우 VO 권장 (ex: 정산, 공수 산정, 매표 등)

      - 특정 값의 key 또는 value(필수 값인 경우)가 null 인 경우 VO 클래스 내에 선언된 타입으로 초기화 수행됨. 쿼리 수행 시 null로 인한 오류가

        나지 않음

      - 멤버변수에 대한 구체적인 타입을 선언하기 때문에 타입이 매치되지 않는 경우 컴파일 에러가 발생하여 바로 알아챌 수 있다.

      - 반드시 값이 필요한 변수에 대해 생성자 파라미터로 필요한 값을 넣을 수 있어, 이 값이 없는 경우 컴파일 에러가 발생한다.


    [단점]

      - Map에 비해 소스가 많아진다.

      - getter, setter 메서드를 일일이 작성해주어야 하는 번거로움이 있었지만 현재 lombok을 사용하면 annotation 형태로 조금 더 간편하게 사용 할 수

        있다 (@Getter, @Setter)

    


__________________________________________________________________________________________________________________________________________________________
** 본 포스팅에 대해 수정해야할 부분이나 추가 의견 등이 있으신 분들은 댓글 달아주세요. 언제나 환영입니다 :)
** 본 포스팅은 아래의 reference 들을 참고하여 내용을 덧붙인 글입니다. 혹시, 문제가 되는 경우 알려주시면 조치하도록 하겠습니다.

    - https://www.slipp.net/questions/22
    - http://zgundam.tistory.com/65


** 본 포스팅을 reference 자료로 참고하실 분들은 출처를 꼭 밝혀주시기 바랍니다.


 


[AA Role] 프로젝트 정의단계 / 산정/ 인터페이스 설계

 

분석기술

 - 유즈케이스는 중요한 분석 도구

 - 프로토타이핑

 - 프로젝트 영역 식별

 - 비기능요구사항: 기능요구사항은 어플리케이션이 수행해야 하는 것 정의, 비기능요구사항은 기능적인 요구사항을 어플리케이션이

                        성취하는 방법에 대한 제약사항 명시

 

범위정의와 산정

 - 업무측에 유즈케이스에 대한 동의를 얻는다

 - 프로젝트 범위를 결정하는데 사용된 가정을 문서화한다

 - 팀에서 가장 늦은 자원을 기준으로 산정한다

 

 

외부 어플리케이션 인터페이스 설계

 - 인터페이스 방법 선택(ex: 직접 외부 어플리케이션 DB 활용, 웹 서비스, 메시징, EJB, REST 서비스 등)

 

   (1) 외부 어플리케이션 DB 직접 읽기

       : 구현이 가장 쉽고, 비용이 적게 듬

       : 외부 어플리케이션 팀의 개입이 거의 필요 없음

       : 항상 최신의 데이터 제공

       : 외부 어플리케이션의 변화에 역으로 영향 받을 리스크 존재

       : 오라클은 예외지만 대부분의 데이터베이스는 읽을 때 로크가 걸림(성능에 영향 줄 수 있음)

 

    (2) 웹 서비스

       : 웹 서비스는 다른 인터페이스 메서드에 비교하여 개발하고 유지, 보수하기 어렵다

       : 웹 서비스는 대량의 데이터를 가져오는 데 최적화되어 있지 않다

       : 필요할 때 웹 서비스를 사용하지 못할 수 도 있다. 대처 전략 필요

       : 플랫폼 중립적

       : 웹 서비스는 자유롭게 리팩토링 및 재설계 가능(해당 어플리케이션에는 아무런 영향을 미치지 않음)

 

     (3) RESTful 서비스

       : RESTful 웹 서비스는 구조화된 URL을 사용하여 정보 요청 명세를 커뮤니케이션 한다.

       : 플랫폼 중립적

       : 웹 서비스보다 소비하기 쉽다

       : 필요할 때 사용할 수 없을 수도 있다. 대처 전략 필요.

       : 웹 서비스의 WSDL 자체가 서비스를 설명하는 문서로 제공되는 반면에 RESTful 서비스는 이러한 내장된 문서화 전략을 제공하지 않음

 

     (4) 메시징 서비스 활용

       : 비동기적인 커뮤니케이션 방법. 요청이 전달되지만 응답이 즉시 이루어지지 않을 수 있음

       : JMS

       : 전달을 보장한다

       : 플랫폼 중립적

       : Java EE 컨테이너 지원을 받음

       : 내장된 문서화 전략을 제공하지 않음

 

 

 - 데이터 구조

     (1) 외부 어플리케이션에 전달되는 모든 데이터 문서화

 

 - 컨텐츠 교환 트리거 이벤트

 - 에러 처리 프로시저와 책임

     (1) 모든 외부 어플리케이션 인터페이스는 에러 알림 프로시저를 가져야 한다

     (2) 자동으로 에러를 알려주는 방식을 사용

     (3) 에러를 로깅할 때 상세한 설명을 포함시키는 것이 좋다

 

 - AA는 인터페이스 설계 논의를 중재해야 한다

     (1) 외부 어플리케이션에 전송하고 요청하는 모든 사항을 기록한다

     (2) 에러 처리 로직 적절하게 테스트

 

 

[출처] JAVA EE 아키텍트 핸드북 2판

 

 

[AA Role] 프로젝트 계획단계

 

계획단계에서 AA의 역할은 기업마다 크게 달라짐

 

- 업무 분석 주도 및 문서화

- PM을 지원하여 프로젝트 범위 정의

- 필요한 시간과 리소스 산정

- 외부 어플리케이션과의 인터페이스 정의 및 설계

 

1) AA는 프로젝트에서 사용될 기술을 선택한다

   : 기업수준 --> 하드웨어, 운영체제, 소프트웨어, 언어 등

     AA수준 --> ex) XML parser, third party package, utility 등

 

2) AA는 프로젝트에서 사용할 개발방법론과 프레임워크를 추천한다

 

3) AA는 어플리케이션의 종합적인 설계와 구조를 제공한다

 

4) AA는 어플리케이션 설계를 적절하게 문서화해야 한다

   : 설계 문서화는 개발자들과 커뮤니케이션 하는 중요한 단계

   : 문서는 프로젝트 중간에 사람이 교체되더라도 프로젝트가 제대로 유지될 수 있도록 한다

 

5) AA는 코드 작성 가이드라인을 수립한다

   : 예외처리, 로깅, 테스트, 스레딩, 캐싱, 설정 등

 

6) AA는 인프라스트럭처 요구사항을 정의한다

 

 

[AA와 사람들] AA와 PM

1) AA는 PM에게 구현 작업을 식별해주어야 한다

   : AA는 PM이 현실적으로 프로젝트 계획과 산정을 할 수 있도록 도와주어야 한다

 

2) AA는 PM을 도와 관리를 위한 프로젝트 비용과 효과를 산정한다  

 

3) AA는 PM이 개발자 위치에 대한 인사결정을 할 수 있도록 도와준다

 

4) AA는 PM에게 기술적인 충고와 가이드를 제공해야 할 책임이 있다

 

 

[AA와 사람들] AA와 PL

1) AA는 PL에 의해 결정된 어플리케이션 요구사항이 적절한지 확인할 책임이 있다

 

 

AA와 사람들] AA와 디자이너

1) AA는 레이아웃이 기술적인 타당성을 갖는지 확인할 책임이 있다

 

AA와 사람들] AA와 업무 로직 개발자

1) AA는 업무 로직 개발자에게 가이드를 제공한다

   : 업무로직 개발자는 엔터프라이즈 빈, 웹 서비스, 배치 작업, 업무 객체, 데이터 액세스 객체 등의 코드를 작성할 책임을 지닌다

 

AA와 사람들] AA와 데이터 모델러

1) AA는 데이터 모델이 적절한지 확인할 책임이 있다

   : 데이터 모델러는 업무 분석가로부터 제공되는 정보를 사용하여 어플리케이션이 데이터베이스에 저장하는 모든 데이터를 식별하고, 정의하며

     목록을 작성한다. (ER 다이어그램 작성)

 

 

AA와 사람들] AA와 데이터베이스 관리자

1) AA는 데이터베이스 관리자와 함께 작업하여 데이터베이스 저장소에 관련된 이슈나 문제를 해결한다

   : 데이터베이스 관리자는 어플리케이션에 대한 업무 요구사항에 기초하여 데이터베이스 설계를 수행하고, 어플리케이션을 위한 데이터베이스 환경을

     만들고 유지보수한다.

2) AA는 데이터 이관 요구사항이 이관 전문가에게 잘 제공되는지를 확인한다

 

 

AA와 사람들] AA와 테스트 전문가

1) AA는 테스트 전문가와 함께 작업하여 필요한 인프라스트럭처 요구사항과 자원을 식별한다

 

 

[출처] Java EE 아키텍처 핸드북 2판 - 성공적인 아키텍

 

 

 

 

 

 

'Application Architect > AA 일반' 카테고리의 다른 글

아키텍트가 지녀야할 capabilities  (0) 2017.05.14

+ Recent posts