[Info]Tags categorized posts and contents patterns..

[AJAX] Ajax Code E xamples.. [Book] About the book.. [CSS] CSS Code E xamples.. [DB] Sql Code E xamples.. [DEV] All development stor...

2016년 3월 22일 화요일

[EP]제11회 한국 스프링 사용자 모임 세미나 후기 #1..

출처 : Outsider's Dev Story https://blog.outsider.ne.kr/

지난 13일 명동에서 KSUG가 주최하는 제11회 한국 스프링 사용자 모임 세미나가 열려서 갔다가 왔습니다. 10회 세미나가 4월 17일에 열렸으니 6개월여만이군요.

Keynote
시작은 KSUG의 회장이신 fupfin님이 Keynote(?)로 시작되었습니다. 보통 컴퓨터 사이언스라고 부르는데 이 단어는 약간 이상하게 들립니다. 사이언스라는 것은 무언가 발견해내는 과정인데 프로그래밍은 문제를 해결해 나가는 과정입니다. 


스프링은 스프링이 복잡한 것이 아니고 스프링이 해결하려는 문제가 기존의 스트럿츠가 해결하려고 했던 문제 들에 비해서 훨씬 복잡한 문제를 해결하려고 하기 때문이고 각 문제별로 해결하는 방식을 보면 오히려 아주 단순합니다.

프레임워크를 어떻게 정의하는지 보겠습니다.

프레임워크는 공통적인 고수준의 패턴이고 클래스이다. - Larry Best

문제를 해결하려는 사고방식이고 그것을 코드로 만든 것이다. 그래서 한가지 문제를 여러가지로 해결 할 수 있다. - Kent Beck

애플리케이션의 뼈대를 구축하는 것이다. - Mary Shaw


발표하시는 fupfin님Kent Beck의 Framework에 대한 정의

그러면 아키텍쳐란 무엇일까요? 켄트벡은 패턴으로 문제를 해결하려고 하면서 아키텍쳐가 발현되는 것이고 한번에 나오는 것이 아니라 작은 스텝을 통해서 점점 진화하게 되는 것이라고 했습니다. 초반에 아키텍쳐를 잡아놓은 것이 후반에 변경사항에 대처를 못하게 되고 이것이 개발자를 어렵게 만드는 경우가 많이 있습니다.

스트럿츠2 역시 좋은 프레임워크라고 생각합니다. 여기서 스트럿츠2는 앞에서 얘기한 Larry와 Mary의 생각을 적용하고 있다고 볼 수 있습니다. 이는 총체적으로 문제를 해결하려고 하고 있는 반면에 스프링은 문제해결을 위해서 여러가지 중에 선택해서 사용할 수 있도록 하고 있습니다. 또한 스트럿츠2는 특정 패턴을 적용하려고 하고 이 부분의 문제가 발견되면 다른 패턴으로 변경하는 식으로 대처하고 있지만 스프링은 이렇지 않습니다. 핸들러 같을 것을 보면 그냥 Object이고 내부적으로는 버전이 올라가면서도 거의 달라지지 않았습니다. 스트럿츠가 표준을 잡고 강제하려고 하고 있다면 스프링은 선택권을 개발자에게 주기 때문에 발전 가능성이 많이 있습니다.

Spring Trouble Shooting - 백기선
백기선님의 최근 교육을 진행하면서 받은 여러가지 질문과 트러블 케이스들의 경험을 모아 스프링 트러블 슈팅이라는 주제로 발표를 했습니다.

Spring Trouble Shooting 발표발표하시는 백기선님

@Autowired
같은 타입의 빈이 등록되어 있을 경우 @Autowired하였을 때 의도치 않은 결과가 나오는 트러블 상황을 보여주었습니다. @Autowired의 동작원리를 이해해야 하는데 해당 타입의 빈이 1개있으면 바로 찾고 여러개일 경우에는 같은 이름의 빈이 있어야 동작합니다. 때문에 의도치 않은 장애를 피하려면 같은 타입의 빈이 여러개 일경우 명시적으로 이름을 설정하고 주입받을 곳에서 @Autowired 대신 @Resource를 사용하라고 하였습니다.

또한 컴포넌트 스캔( <context:component-scan default-package="easy"/> )과 <bean/> 설정을 혼용해서 쓰지 않아야 합니다. 혼용해서 쓸 경우 컴포넌트 스캔뒤에 XML의 DI정보로 덮어쓰기 때문에 XML로 등록할 빈은 @Component를 사용하지 말아야 합니다.

@Transactional
트랜잭션을 사용하기 위해 @Transactional 애노테이션을 붙힌 클래스에 인터페이스를 사용하려고 추가하니까 Bean을 제대로 찾지 못하는 트러블 상황을 보여주었습니다. @Transactional을 사용하면 프록시가 만들어지게 되는데 인터페이스가 없을 경우에는 클래스를 가지고 프록시를 만들지만 인터페이스가 있게 되면 클래스가 아닌 인터페이스로 만들기 때문에 프록시 타입은 인터페이스의 타입이 됩니다.
@Transactional을 사용하면 이미 스프링의 AOP를 사용하고 있는 것이고 <tx:annotation-driven />는 인터페이스가 있으면 JDK프록시를 사용하고 인터페이스가 없으면 CGLib프록시를 사용합니다. 인터페이스를 만들었다면 인터페이스를 사용하고 클래스기반으로 하고 싶다면 클래스기반 프록시를 명시적으로 선언해햐 하지만 별로 권하지는 않습니다.
ApplicationContext의 상속구조는 부모 ApplicationContext는 자식 ApplicationContext에 있는 빈에는 접근할 수 없고 자식 ApplicationContext는 부모 ApplicationContext에 있는 빈에 접근할 수 있습니다. 이때 AOP에 대한 설정과 AOP를 적용할 빈은 같은 ApplicationContext에 있어야 가능합니다. 부모에서 제대로 설정했다고 하더라도 자식 ApplicationContext에더 덮어쓰면 AOP가 되지 않기 때문에 부모에 등록할 것과 자식에 등록할 것을 잘 구분해야 합니다. 만약 패키지로 구분하는 것이 어렵다면 애노테이션으로 구분합니다.

DispatcherServlet 매핑
최근에는 DispatcherServlet의 URL 패턴에 /app/*를 사용합니다.
DispatcherServlet에 아무것도 등록하지 않으면 기본전략 빈들이 모두 등록 되지만 명시적으로 하나를 등록하게 되면 나머지 빈들은 등록이 되지 않게 됩니다. 때문에 기본 전략에 의지하다가 추가등록을 하게 되면 잘 돌아가던 서비스가 제대로 돌아가지 않는 문제가 생길수 있기 때문에 기본전략에 의지하기 보다는 필요한 전략을 등록하는 것이 좋습니다.

발표가 끝나고 깜짝 이벤트(?)로 토비의 스프링3의 저자이신 Toby님과의 iChat연결을 통한 질답시간이 있었습니다.

토스3을 공부하면 스프링을 잘할수 있는가에 대한 질문에 Toby님은 스프링을 공부하는데는 여러가지 방법이 있는데 개별 기술을 따로 공부하게 되면 새로운 것이 나올때마다 서로 연결이 안되서 어렵게 느껴질 수 있는데 오히려 전체를 이해하면 더 나을 수 있다고 하셨습니다. 스프링으로 만들어 놓은 것을 가져다가 쓰는 수준이 아니라 스프링의 개념과 철학을 이해하고 개발할 수 있도록 하는 것을 목적으로 쓴 책입니다. 중요한 것은 스프링 전문가가 되는 것이 아니라 스프링의 개념과 철학을 이용해서 자신이 개발하는 애플리케이션을 잘 구축하는 것이 더 중요하고 스프링보다 애플리케이션에 더 초점을 맞추어야 합니다.

분책에 대한 질문에 대해서는 분책을 하게되면 지금과 같은 종이를 사용할 수 없기 때문에 기대처럼 얇아지지 않아서 소용이 없을것 같다고 하셨고 후속책에 대한 질문에는 현재는 구체적인 것은 없고 당초 스프링의 이해, 실제로 어떻게 사용하고 선택하는가, 어떻게 확장하는가의 3부작으로 생각했었는데 마지막 확장에 대한 부분은 쓰지 못했다고 얘기하셨습니다.


간디 코스프레(?)도 하는 쇼맨쉽과 Head First시리즈가 생각나는 PPT가 상당히 인상적이었습니다. 저는 현재 스프링으로 업무를 하고 있지는 않기 때문에 트러블슈팅부분에 대해서는 바로바로 와닿지는 않았지만 트러블 슈팅으로 인한 스프링 개발의 권장사항을 미리 염두에 두고 있어도 충분히 도움이 될 만한 부분이라고 생각했습니다. 특정기술에 대한 설명같은 부분도 좋지만 이렇게 실제 개발할때의 실용적인 부분도 참 유용한것 같습니다.

Rich Domain Model - 조영호
리치 도메인을 이해하려면 리치도메인의 반대되는 개념을 먼저 이해하는 것이 쉽습니다.

Rich Domain Model 발표발표하시는 조영호님

1. 온라인 영화 예매 시스템
이해를 돕기위해 영화 예매시에 여러자기 조건에 따라 할인율이 적용되는 온라인 영화 예매 시스템을 구축하는 시나리오를 준비하셨습니다.
영화(Movie)가 첫번째 도메인 컨셉이며 상영(Showing)정보가 두번째 도메인 컨셉입니다. 세번째로는 할인정책(Discount)가 있는데 절대가격으로 할인하는 Amount Discount와 비율로 할인을 하는 Percent Discount가 있으며 할인규칙(Rule)이 네번째로 몇회차 영화에 할인해 줄것인가 하는 Sequence Rule과 무슨 요일 몇시에 할인할 것인가에 대한 Time Rule이 있습니다.
이 도메인들을 가지고 영화 예매를 할때 적당한 룰을 찾아 할인을 적용하여 그 결과로 예매(Reservation)을 생성하게 됩니다.

2. 데이터 - 지향 설계
데이터를 먼저 생각하고 무엇을 저장할 것인가를 생각하게 됩니다. 그러면 자연스럽게 ERD를 그리게 되는데 이것은 Anemic Domain Model이라고 부르며 테이블의 컬럼과 1:1매핑되는 클래스를 만들게 됩니다 이 클래스는 속성만 가지고 있고 getter/setter만 노출하게 됩니다. 그 후에 이 객체들이 어떻게 동작하는 가(프로세스)에 대해서 고민하게 됩니다. ReservationService를 만들고 예약정보를 보여주는 메서드를 만들고 구현체에서 데이터를 끌어오기 위해서 DAO를 만들게 됩니다. Movie와 Showing정보를 가져오고 Rule정보를 가져와서 적용여부를 판단하고 어떤 할인이 적용되는지 찾아서 적용한뒤 Reservation을 생성해서 디비에 저장하게 됩니다.

데이터 모델에 대한 ERD중앙집중식 제어 스타일의 흐름도

이게 일반적으로 개발하는 방식이고 데이터와 프로세스를 분리하게 되어 프로세스는 모두 서비스레이어에 몰아넣게 됩니다. 이걸 아키텍쳐 패턴으로 보면 Transaction Script 패턴이라고 부르며 실무에서 가장 많이 사용하는 아키텍쳐 패턴입니다.

3. 책임 - 주도 설계
우리가 처음 OOP를 공부할 때 배웠던 "상태와 상태를 처리하는 로직을 같이 두는 것이 OOP이다"라는 개념을 적용한 것이 Rich Domain Model입니다. 이는 데이터 기반이 아닌 책임기반(Responsible Driven)개발입니다. 데이터 - 지향 설계의 중앙집중식에서는 책임이 서비스에 모두 몰려있지만 책임주도에서는 책임이 분산되어 있으며 설계의 관점이 데이터와 프로세스가 아니라 책임기반으로 설계를 하게 됩니다. 그리고 보통 얘기하는 캡슐화는 책임기반으로 설계할 때 달성할 수 있습니다.

책임에 대한 CRC카드위임식, 분식식 제어스타일의 흐름도Rich Domain Model에 새로운 할인 객체를 추가한 모습

책임기반으로 설계할 때는 데이터와 프로세스는 생각하지 않고 이 시스템에 어떤 책임이 있는가를 고민해야 합니다. 시스템의 책임을 결정한 뒤에 어떤 도메인 컨셉에 할당할지를 고민하는 것입니다.
위 예제에서는 예매를 생성할 책임이 있는데 이는 Showing이 상영정보를 알고 있기 때문에 Showing에 할당합니다.(이때 CRC카드를 사용하는데 상단에는 클래스명을 적고 좌측에는 책임을 오른쪽에는 연관클래스를 적습니다.) 여기서 예매정보를 생성하려고 하니 가격을 알아야 하는데 가격을 가장 많이 알고 있는 Movie에 할당하고 필요한 할인율을 위한 책임을 위해 전략개체를 추가해서 DiscountStrategy로 전략패턴을 Movie에 적용하고 Rule을 추가해서 할인여부를 판단하게 됩니다.

설계는 What을 결정하고 구현은 How를 결정하는 것이라고 봤을 때 이 단계는 What을 결정하는 단계입니다. 클래스를 어떻게 만들고 데이터는 어떻게 가져올 것인가 하는 데이터에 대한 생각은 일단 여기서는 하지 않습니다. Anemic Domain Model은 실제적으로 보면 객체지향 설계는 아니고 객체지향 언어를 사용할 뿐입니다. Transaction Script의 단점은 수정이 어렵기 때문에 새로운 할인율이 추가되면 기존 코드를 수정해야 하며 그때문에 if-else구문이 많이 생기게 됩니다. Rich Domain Model의 장점은 OOP의 다형성의 활용이 가능하기 때문에 객체를 추가하고 구성을 바꾸는 것만으로 가능해지게 되고 이것이 Open Closed Principle입니다.

4. 아키텍쳐 & 프레임워크
Rich Domain Model로 설계했을 때 어떻게 구현을 해야하는 가는 프레임워크에 도움을 받을 수 있습니다. 레이어는 정해진 것은 없고 시스템마다 다르지만 앞서 얘기한 부분은 Domain 레이어에 대한 부분입니다. 여기서 중요한 점은 Domain 레이어는 최대한 캡슐화시키고 고립시켜야만 하고 그렇게 해야 POJO기반으로 할 수 있기 때문에 Domian레이어를 바로 노출하지 않고 그 위에 Service레이어를 두어 Service 레이어가 노출되도록 합니다. 여기서 서비스레이어는 Anemic Domain Model에 비해어 아주 간단해 지며 이 경우에는 Operation Script방식으로 코딩하는 것을 선호합니다. 당연히 레이어는 한방향으로만 의존성을 가지도록 해야하며 도메인레이어는 서비스레이어에는 의존하지 않고 하위의 Infrastructure에도 제한적으로만 의존하도록 합니다.

우리가 프레임워크를 쓰는 이유는 POJO로 개발할수 있어서 쓴다고 해도 과언이 아니며 POJO의 3대요소는 DI, AOP, Annotation입니다. 이 3가지 요소를 적용하면 비침투적인 프레임워크를 만들수 있으며 Lightweight 프레임워크라고도 부릅니다.(EJB는 아주 침투적입니다.) DI는 객체간의 의존성 관리이슈로부터 도메인 레이어를 보호하고 수성-사용의 분리 원칙을 적용한 것이며 스프링은 이를 지원하고 있습니다.

POJO의 3대 요소Data Mapper로 DB스키마와 객체모델을 연결한 화면

Rich Domain Model을 적용했을 때 객체모델과 DB스키마간의 불일치를 Impedance Mismatch라고 부르는데 이건 디비 설계과 객체지향 설계의 포커스는 완전히 다르기 때문에 당연한 결과입니다. 디비는 중복의 제거가 목적이고 객체지향은 행위의 효율성에 목적이 있습니다. 이 Impedance Mismatch를 해결하는 것은 아주 어렵기 때문에 데이터지향 설계를 주로 하게 되는 것입니다. 보통 Data Mapper를 사용해서 중간역할을 하도록 하는데 직접만들지는 않고 프레임워크를 사용하는 것이 일반적이며 Data Mapper를 가장 많이 사용하는 것이 Hibernate입니다.

결론
Rich Domain Model은 기술관점이 아닌 설계관점입니다. 자신이 정말 OOP로 설계를 하고 있는가를 먼저 생각하고 그 다음에 기술이 나와야 합니다. 물론 그렇다고 기술이 중요하지 않은 것은 아니며 비침투적인 프레임워크를 사용하지 않고 POJO를 사용하는 것은 거의 불가능합니다. Rich Domain Model을 자제해야 하는 경우는 비즈니스 로직이 단순하고 개발기간이 짧은 경우, 비침투적 프레임워크를 사용할 수 없는 경우, 개발 경험이 부족한 경우, O/R매퍼를 사용할 수 없는 경우나 OOP 설계 경험이 없다면 시도하지 않는 것이 좋습니다. Rich Domain Model을 적용하기 전에 이런 부분에 대한 학습이 필요하며 무조건 좋다는 것은 아니지만 Rich Domain Model이 실무적인 관점(Be Progmatic)에서 어느 경우에 유용할 수 있는 역략을 가질수 있도록 연마해야 합니다.

Q & A
실무에서 팀으로 할때는 어떻게 적용해야 합니까?

회사에서는 주로 성능위주로 많이 하게 되기 때문에 실무에서는 프로토타입정도로만 해봤습니다. 현실적으로는 팀원들의 지식 수준이 어느정도 유사할 경우에는 개발이 좀 빨라지게 됩니다.

관련해서 도움될 만한 책을 추천해 주세요.

객체 지향 - Applying UML and Patterns, 소프트웨어개발의 지혜(Robert C. Martin, Agile Software Development, Principles, Patterns, and Practices)
패턴 - Patterns of Enterprise Application Architecture(Martin Fowler)


저한테는 이번 세미나에서 가장 인상깊었던 세션이었습니다. Rich Domain Model이라는 저한테는 어렵게만 느껴지던 개념을 너무나 쉽고 논리정연하게 설명해 주셨던것 같습니다. 전해 주시는 내용들도 그 내용의 깊이를 알 수 있을 정도로 알찼지만 개념을 이해하기 위한 간단한 예시부터 Rich Domain까지 이어지는 흐름이 너무 자연스러워서 Rich Domain에 대해서 전혀 모르고 있던 저도 그 개념을 이해하기에 너무 좋았던 것 같습니다.
물론 저는 내공이 안되서 Rich Domain을 당장 쓰거나 하지는 못하겠지만 이 개념을 항상 염두에 두고 있는 것 만으로도 큰 도움이 될것 같다는 생각입니다. 언젠가는 Rich Domain Model을 적용해서 개발해 봐야겠지요 ㅎㅎ

댓글 없음:

댓글 쓰기