Outsider's Dev Story

Stay Hungry. Stay Foolish. Don't Be Satisfied.
RetroTech 팟캐스트 44BITS 팟캐스트

KSUG 번개 세미나 후기

지난주 토요일 2일에 KSUG에서 번개세미나가 있었습니다. 이 세미나는 제목그대로 갑자기 기획되어서 진행된 세미나로 KSUG를 만들었던 Toby님이 호주에서 업무차 귀국을 하면서 마련된 세미나였습니다. 사실 이 세미나 후기를 쓸까말까 고민했었습니다만 그냥 기록차 씁니다. 왜냐하면 총 3개의 세션이었는데 하나는 제 세션이었고 한 세션은 발표후 잠시의 휴식과 Toby님을 비롯한 다른 분들과 잠시 대화를 나누느라고 듣지 못했기 때문이지요.(결과적으로는 한세션만 들었습니다. ㅠㅠ)

사용자 삽입 이미지

위에 나온 것이 시간표입니다. 앞에서 말씀드렸다 시피 정상혁님의 "TDD with Spring batch"는 개인 사정으로 후반부만 들어서 내용을 잘 이해못한 관계로 생략합니다.(흑흑) 세미나에 대한 백채널은 봄싹에서 만든 LiveLog에 남겨져 있습니다.




다형성 쿼리가 가져오는 문제를 해결하기 위한 싱글리시버 구조의 더블 디스패치를 활용한 비지너 패턴 전용 전략 - 이일민
이번 세미나가 열린 이유중 하나인 Toby님의 세션입니다. 제목이 너무 길어서 무슨 내용인지 파악하기가 좀 어렵긴 한데 결과적으로는 더블디스패치와 비지터패턴에 대한 얘기였습니다.

개발자는 시대의 흐름을 잘 따라가야 한다는 얘기를 하시면서 SaaS나 PaaS같은 용어를 본따서 DaaD(DI as a Design Pattern)라는 용어로 비유하시며 DI를 디자인패턴의 일종으로 보는 것으로 발표는 시작되었습니다. DI는 결국 오브젝트들 사이의 관계를 분리해서 제 3자가 맡게 되는 것으로써 DI를 사용하지 않는다면 Dependency Resolution 코드는 Client쪽에(사용하는 입장) 들어갈 수 밖에 없습니다. 이렇게 클라이언트가 사용대상의 위치나 구체적인 부분에 대해서 모르고 그냥 사용한다는 부분에서 클라우드 컴퓨팅의 구조랑 유사한 면이 있다면서 DaaC(DI as a Cloud Computing)에 비유하셨습니다.

서론은 서론이고 본격적인 얘기인 더블디스패치에 대한 이야기가 시작되었습니다. 토비님이 설명하시는 건 이번이 두번째로 듣는 건데 토비의 스프링 3에서도 그렇지만 어떤 개념을 설명하기 위해서 기초적인 수준의 코드에서 발전시켜나가면서 개념을 설명하시는 건 정말 최고인듯 합니다. 디자인패턴이란 것이 상당히 난해한데다가 더블디스패치라는 평소에 접하지 못했던 디자인패턴임에도 소스를 발전시키면서 보니 이해하기가 상당히 쉬웠습니다.(물론 제가 실제로 써먹을 수 있냐에 대한 부분은 다른 얘기이지만요.)




더블디스패치는 Daniel Ingalls가 1986년 OOPLSA에서 "A simple technique for handling multiple polymorphism"라는 이름으로 발표한 디자인 패턴으로 싱글디스패치 언어인 Java에서 다중 다형성을 처리하는 디자인 패턴입니다. 예시로 들어 주신 내용은 Post클래스를 상속받은 Text와 Image클래스가 있고 SNS클래스를 상속받은 Facebook, GooglePlus 클래스가 있을 때 SNS클래스들에 Text와 Image를 포스팅할 수 있는 것을 처리하는 방법으로 구조에 대한 소스는 여기 있습니다.(Toby님이 소스를 Github에 공유해 주셨기에 따로 소스는 적지않고 링크로 대체합니다.) 실제로 이것을 구현하기 위한 첫 단계로는 각 Post클래스의 구현체들에서 if문을 통해서 각각의 클래스를 확인해서 해당 SNS에 포스팅해주는 방식입니다. 동작은 원하는 대로 되지만 이렇게 작성했을 경우 새로운 SNS클래스가 추가되었을 때 모든 Post 구현클래스의 if문을 추가해 주어야 한다는 문제가 발생합니다.

if문을 해결하기 위해서 가장 먼저 떠오르는 생각은 오버로딩으로 구현하는 것입니다.(해당 소스에서 Post클래스에는 postOn으로 되어 있고 구현클래스에는 post로 되어 있는데 오타일뿐 결과는 동일합니다.)  여기서 의도한 것은 파라미터의 클래스에 따라 오버로딩된 함수가 호출되도록 하려는 것이었지만 결과적으로는 모두 Unsupported가 나타나게 됩니다. 이렇게 되는 이유는 자바가 싱글디스패치 언어라서 런타임시에는 리시버만 판단하고 파라미터의 실제 타입은 판단하지 않기 때문입니다.(여기서 리시버는 A.method(B)일때 A를 말합니다.) 실제적으로는 Facebook, GooglePlus 클래스가 넘겨지지만 런타임시에는 이를 모두 SNS타입으로 판단하기 때문에 기대했던 오버로딩의 효과가 나타나지 않습니다.

이 문제를 해결하기 위해서 더블디스패치를 적용합니다. 더블디스패치의 방법은 각 Post의 구현클래스에서 postOn() 메서드를 하나만 두고 파라미터로 받는 SNS를 리시버로 해서 자기자신(this)를 파라미터로 해서 다시 호출합니다. 그래서 실제 포스트 하는 함수는 반대로 SNS클래스쪽으로 이동하게 되고 SNS 구현클래스에서 Post의 타입별로 오버로딩함수들을 구현하면 원하는 모든 SNS에 타입별로 포스트되는 결과를 얻을 수 있습니다. 이렇게 구현된 결과는 if문으로 구현했던 코드보다 OCP가 적용되었기 때문에 SNS를 훨씬 유연하고 안정된 확장성을 가진 소스가 됩니다. 비지터패턴은 더블디스패치랑 상당히 유사한데 앞에서 적용한 더블디스패치를 비지터패턴에서 사용하는 용어로 재정의하면 이름만 달라졌을 뿐 동일한 형태의 소스가 됨을 알 수 있습니다.

이렇게 복잡하게 구현하느니 그냥 처음에 구현했던 if문 구조의 instanceof를 사용하는 것이 낫다고 생각할 수도 있지만 더블디스패치를 썼을때의 또하나의 장점은 Proxy를 사용했을 때 나타납니다. ORM등을 사용하면 객체가 Proxy로 감싸지는 경우가 많은데 이렇게 Proxy를 쓰게 되면 instanceof를 사용했을때 모두 Proxy타입으로 판단되기 때문에 instanceof를 사용할 수 없습니다. 이렇게 Proxy가 사용된 상황에서 더블디스패치를 적용하면 아무런 문제없이 정상적으로 동작함을 알 수 있습니다. 이 문제는 Hibernate에서 Proxy때문에 자주 질문되던 내용으로 개발자들이 더블디스패치를 이용해서 이 문제를 해결할 수 있다는 것을 알게 되면서 Proxy Visitor Pattern이라고도 불리웁니다.




Epilogue



마지막으로 패널토의도 있었는데 다양한 얘기가 오가서 따로 정리하기가 어렵습니다. 개인적으로는 개발자의 미래와 비슷한 주제에서 fupfin님산업혁명이전에 회사의 단순노동만 하던 노동자에서 산업혁명이후에 노동자들이 공장설비를 소유하게 되면서 회사를 나가게 되면 설비도 같이 들고 나가기 때문에 자연스럽게 Owner들이 엔지니어들을 대우하게 되었던 것(기억이 정확치 않;;)에 비유하시면서 우리는 설비를 가지고 있는 사람들이고 퇴사할때 기술을 그대로 들고 다른 곳으로 가면 그만이고 이런 부분을 인지 못하고 회사에서 시키는 일만 하는 사람으로만 자신을 생각하면 대접을 받을 수 없다는 얘기를 하시면서 40대가 넘는 엔지니어가 드문 현실에 안타까워 하셨는데 개인적으로 많은 공감이 갔습니다.

갑작스럽게 준비된 번개세미나였음에도 Microsoft의 장소제공과 에이콘의 후원으로 먹을게 풍족하고 즐거웠던 세미나였습니다.
2011/07/04 23:55 2011/07/04 23:55