인터페이스 프로그래밍과 스프링 IoC/DI

스프링프레임워크가 지지하는 프로그래밍 철학 중 가장 대표적인 것이 인터페이스에 대한 프로그래밍(programming to interface)이다. IoC/DI기반의 애플리케이션 구조의 장점을 살리기 위해서라도 인터페이스 프로그래밍은 필수이다. 그래서 스프링의 빈(bean)의 의존대상을 가리키는 레퍼런스변수는 인터페이스를 이용한다. 그래야지만 의존대상이 바뀌었을 때 소스코드의 수정없이 외부에서 설정파일을 이용해서 변경가능하다는 IoC/DI의 장점을 누릴 수 있다. 덕분에 strategy pattern과 같은 인터페이스 프로그래밍을 이용한 디자인패턴이 스프링 애플리케이션에서는 너무나도 자연스럽게 사용된다.

따라서 스프링을 이용하는 개발자들은  인터페이스 프로그래밍에 익숙해진다.

스프링 컨테이너가 직접 제공하는 DI(의존삽입)가 아닌 DL(의존검색)방식의 매핑에 의해 연동되는 MVC컨트롤러류를 제외하면 대부분의 애플리케이션 컴포넌트 빈들은 당연히 인터페이스를 이용해서 작성하게 된다.

 

스프링의 인터페이스 프로그래밍의 장점과 필요성

그렇다면 스프링의 인터페이스 프로그래밍의 장점은 무엇인가?

가장 대표적으로 생각해볼 수 있는 것은 역시 구현의 변경이 용이하다는 것이다. 

그런데 프레임워크 내부처럼 확장성을 중요시 해야하는 경우가 아닌 일반 비즈니스 컴포넌트에서 구현을 바꿔가며 사용해야하는 경우는 어떤 것일까?

첫째는 다양한 퍼시스턴트 기술 또는 여러가지 다른 구현코드의 교환 또는 확장이 필요로하는 DAO레이어일 것이다. 원래 DAO패턴 자체가 그런 목적을 가지고 인터페이스 프로그래밍을 권장한다. 스프링의 DAO레이어의 빈들도 마찬가지 일 것이다.

하지만 과연 여러가지 종류의 DB에 따른 구현을 바꿔가면서 써야하는 경우가 얼마나될까? 상용으로 판매되는 솔루션이나 제품인 경우 다양한 고객의 DB환경을 고려해야 하기때문에 반드시 필요할 것이다. 하지만 하이버네이트처럼 다이나믹한 DB Dialect를 외부설정을 통해서 지원하고 추상화된 HQL과 API를 이용해서 DB독립적인 퍼시스턴트 프로그래밍이 가능한 기술을 쓴다면 DB에 따른 구현의 교환만을 위해서라면 구지 DAO를 인터페이스를 통해서 노출할 필요가 없을지도 모르겠다.

서비스레이어의 빈도 그 로직의 구현을 변경 또는 교환해가면서 쓰는 경우가 얼마나 될까? 사실 거의 없는 것 같다. 꼭 필요한 경우라면 EJB와 POJO빈 두가지를 같이 써야하는 경우가 있겠다. EJB로 개발한 애플리케이션을 스프링기반의 POJO빈으로 아주 점진적인 변경을 해야 할 때라면 말이다. 아주 특별한 경우일 것이다.

그럼에도 빈을 인터페이스를 통해서 구현해야 하는 두번째 이유를 꼽자면 테스트용이성(testability) 때문이다. DAO가 연동되는 인테그레이션 테스트를 해야하는 경우 DAO레이어의 뒤에 있는 외부리소스(주로 DB)는 상대적으로 무겁고 느린데다 자동화된 테스트하기가 불편하기 때문에 DAO의 이전 레이어를 테스트할 때 DAO를 스텁(stub)이나 목(mock)을 사용하는 것이 권장된다. 그렇게 할 경우 DAO에 의존적인 빈들의 유닛테스트/독립테스트(isolated test)가 손쉽게 가능하다. 스텁이나 목을 만드는 가장 일반적인 방법은 의존대상의 인터페이스를 구현해서 만들기 때문이다. Static mock을 만드는 경우뿐만 아니라 다이나믹프록시를 사용하는 목 프레임워크를 사용할 경우에도 목을 만들기 위해서 인터페이스를 요구하기 때문이다.

이 점은 서비스레이어의 빈들에게도 같은 이유로 적용된다.

스프링의 중요한 개발철학의 한가지가 바로 자동화된 테스트이다. 유닛/인테그레이션 테스트를 손쉽게 하기 위해서 반드시 지켜야 할 것이 바로 인터페이스 프로그래밍이다.

하지만 cglib와 같은 바이트코드조작기술을 이용하면 클래스의 프록시를 다이나믹하게 만드는 것이 가능하기 때문에 EasyMock class extension등과 같이 cglib를 사용하는 목 프레임워크를 사용하면 인터페이스 없이도 클래스의 목 오브젝트를 만들 수 있다. 물론 라이브러리의 도움없이 코드를 이용해 직접 목을 구현하려면 클래스를 상속해서 오버라이드하지 못하는 경우에는 그 구현이 불가능할 수도 있다.

또 서비스레이어처럼 트랜잭션의 경계(transaction demarcation) 역할을 하는 경우에는 트랜잭션 기능의 동적인 삽입을 위해서 AOP를 사용한다. 스프링AOP는 기본적으로 JDK에서 지원하는 다이나믹프록시를 사용하기 때문에 이를 위해서는 그 타겟인 서비스레이어의 빈들이 인터페이스로 구현되어있어야 한다. 다이나믹 프록시를 사용할 수 있다는 것이 바로 인터페이스 프로그래밍이 주는 주요한 장점중의 하나이다. 일반적으로 애플리케이션 개발자가 다이나믹 프록시를 직접 쓸일은 별로 없다. 가장 많이 필요로하는 케이스는 스프링AOP의 적용의 경우이다.

하지만 역시 cglib를 이용해서 클래스를 동적으로 확장해한다면 클래스에 대해서도 다이나믹프록시를 구현할 수 있으니 반드시 인터페이스가 필요로 하는 것은 아니다. 사실 cglib가 JDK의 다이나믹프록시보다 성능이 더 빠르기도 하다.

—————————————————————————————–

Note. JDK버전이 올라갈수록 다이나믹프록시의 성능이 좋아진 것은 사실이지만 여전히 cglib가 빠르다. 특히 JDK버전이 낮을 수록 다이나믹프록시와 cglib성능이 크게 차이가 난다.

Hibernate도 2.x까지는 many-to-one에서 프록시를 쓰기 위해서는 대상 엔티티의 인터페이스 구현이 요구되었다. 물론 cglib를 쓸 수도 있지만 초기엔 인터페이스를 만드는 것이 기본적으로 권장되기도 했다. cglib의 버그와 common-loggings와의 충돌등이 문제제가 있는 등의 초기에 cglib를 기본으로 사용하기는 부담스러웠을 것 같다. 그래서 many-to-one이 기본적으로 lazy가 아닌 eager모드로 설정되었다. 그때문에 불편을 느낀 많은 개발자(나를 포함해서)들의 요구로 3.x에서는 lazy-loading이 디폴트로 잡히고 cglib로 프록시를 구현하는 것이 디폴트로 사용되었다. Many-to-one에서의 lazy-loading의 필요성이 매우 높고 cglib의 그동안 안성정과 성능의 인정을 받은 덕분인 것 같다.

—————————————————————————————–

구현의 교환, 테스트 작성의 용이성, 다이나믹 프록시 이 세가지가 로드존슨이 그 책에서 주로 언급한 인터페이스에 대한 프로그래밍의 장점이다.

하지만 위에서 언급했듯이 이러한 기능들이 일반적인 비즈니스 애플리케이션에서 항상 요구되는 것이 아니며 또 인터페이스가 아니어도 충족시킬 수 있는 방법이 존재한다.

 

인터페이스당 한개씩의 구현이 가져오는 문제

거의 대부분의 경우에 애플리케이션의 빈은  인터페이스당 하나씩의 구현만 존재하는 것이 현실이다. 여러가지 환경으로의 이동성(portability)이 중요한 솔루션류의 제품이 아니고 특정 회사와 환경에 제한적인 애플리케이션이라면 대부분이 그렇다고 여겨진다.

유닛테스트를 위한 목을 cglib를 이용하는 목 프레임워크를 사용해서 다이나믹하게 만든다면 그때는 대부분의 빈은 인터페이스당 구현클래스가 하나씩만 존재하게 될 것이다.

그런 상황에서의 문제점을 짚어보자. 인터페이스 사용이 그 명분을 제외하고 현실적인 장점이 없다면 오히려 개발을 번거롭게 할 것이다.

첫째는 인터페이스와 구현클래스가 각각 존재하므로 코드의 양이 늘어난다. 또 네이밍관례을 적절하게 부여하지 못했을 경우 매번 구현클래스가 무엇인지 스프링 설정파일을 통해서 확인해야 한다. 또한 메소드가 추가되거나 시그니처가 변경될 경우 매번 인터페이스와 클래스 양쪽을 다 수정해줘야 한다. 수백,수천개의 클래스들 사이를 왔다 갔다 하면서 매번 그 작업을 하는 것이 얼마나 번거로운지는 겪어본 사람은 안다.

두번째는 IDE를 사용할 때 매우 편리한 기능중의 하나인 코드의 네이게이션편의성(navigability)이 떨어진다.

이클립스를 사용할 때 내가 가장 편리하게 생각하고 자주 사용하는 기능이 바로 타입의 계층구조를 보여주는 것(open type hierachy-F4)과 선언열기(open declaration-F3) 기능이다. 특히 F3를 통해서 특정 메소드의 구현코드를 바로 찾아가는 것은 매우 편리한 기능중의 하나이다.

문제는 인터페이스를 사용하는 경우에 선언열기(F3)를 해봐야 인터페이스의 메소드 시그니처만 열린다는 것이다. 사실 그 경우에 개발자가 원하는 것은 그 구현클래스의 메소드인데 말이다. 단 하나의 구현만 존재하는 경우인데도 불구하고 그 구현클래스를 단축키 하나로 바로 찾아갈 수 없다는 점에서 나는 가끔 인터페이스를 사용한 것에 대해서 불편을 느끼기 시작한다.

그 경우 원하는 구현클래스의 메소드로 이동하기 위해서 내가 주로 사용하는 방법은 두가지이다. 하나는 F4를 눌러서 계층구조를 보고 그 인터페이스의 하위에 나오는 구현클래스를 클릭한다. 그 클래스의 소스가 열리면 거기서 다시 원하는 메소드로 이동한다. 안타깝게도 이 방법은 타입계층구조 뷰에서 클릭을 할때 원하는 구현메소드로 바로 이동을 하지 않기 때문에 번거롭게 다시 메소드를 찾아야하는 불편이 따른다.

이 때는 타입계층구조 뷰를 열기보다는 빠른 타입계층구조(quick type hierachy - ctrl-T)를 이용하는 것이 낫다. 재밌게도 같은 타입계층구조 기능이지만 일반 뷰와 달리 퀵뷰에서 구현클래스를 클릭하면 해당 메소드로 바로 이동한다는 것이다. 퀵뷰는 원래 에디터상의 컨텍스트를 유지한 채로 다음 동작을 하기 때문인 것 같다. 일반 계층구조 창을 열면 그 컨텍스트에서 벗어나게 되기 때문에 원하는 메소드로 바로 이동할 수 없는 것일테고. 아무튼 이 빠른 타입계층구조(ctrl-T)는 매우 편리한 이클립스 기능중의 하나이다.

하지만 퀵뷰(ctrl-T)도 기능도 선언열기(F3)에 비하면 단점이 있다.

첫째는 구현 클래스가 하나이더라도 타입계층구조 뷰를 띄운뒤 마우스 클릭을 하거나 키보드로 선택을 해야하는 번거로움이 있다. 단 하나의 구현이라 사실 원하는 결과가 뻔한데도 말이다. 물론 이것은 코드바로 열기라기 보다는 계층구조 조회의 기능이니까 어쩔수가 없겠지만 말이다.

두번째는 더 심각한데 만약 열기를 원하는 메소드가 더 상위의 수퍼인터페이스에 정의되어있는 경우라면 그 인터페이스로부터 상속,구현된 모든 인터페이스와 구현클래스가 다 튀어나온다는 점이다. 예를 들어 DAO의 반복되는 메소드를 generic을 이용해서 손쉽게 구현하도록 만들었다고 하자. 이 경우 GenericDao 인터페이스를 상속해서 일반 DAO에서 사용하고 그 일반 DAO를 사용하는 코드 중 GenericDao에 정의된 메소드에서  타입계층구조 퀵뷰(ctrl-T)를  열면 일반 DAO의 하위구조가 나오는게 아니라 GenericDAO를 상속한 모든 인터페이스와 그 하위클래스가 다 나와버린다. 이런 경우라면 빠른 타입계층구조기능을 쓰는 것이 아무런 유익이 없다.

그럼 이 때는 다시 F4->구현클래스클릭->Ctrl-O->메소드 찾기의 네단계를 거쳐서 원하는 메소드로 이동해야 할까?

이클립스 3.2.2를 쓰고 있는 내가 발견한 다른 방법은 없는 것 같다. (혹시 있는데 내가 모르는 걸까?)

좀 정리하자면 인터페이스당 한개의 구현이라면 다른 장점이 별로 없는 상황에서는 코드의 양이 많고 코드 네비게이션의 편의성이 떨어지는 단점이 있으므로 오히려 개발생산성만 저하된다는 것이다.

 

별 도움 안되는 결론

그렇다면 이런 경우라면 특별한 장점도 없고 생산성만 떨어뜨리는 인터페이스를 단순한 레이어구조의 애플리케이션용 스프링 빈에서는 구지 쓸 필요가 없는 걸까?

그럼에도 그건 아니라고 얘기하고 싶다.

그렇긴 한데… 요즘엔 자꾸 인터페이스 프로그래밍을 너무 당연하게만 신봉해온 것은 아닐까 하는 생각이 자꾸 든다.

꼭 필요한 것이 아니라면 과감하게 제거하고 실용적인 방법을 선택을 한 루비온레일스를 경험하면서 또 인터페이스 프로그래밍 못지 않은 장점을 가진 루비의 다이나믹 타이핑 또는 덕(duck) 타이핑등을 보면서 자바의 인터페이스에 대해서 조금씩 그 환상이 벗겨져 가는 것 같다.

물론 바이트코드조작 같은 로우레벨의 복잡한 기능의 도움없이 순수한 자바언어만으로 생각해 볼때는 인터페이스 프로그래밍은 반드시 필요하다. 

앞으로 좀 더 고민해볼 문제다.

그럼에도 불구하고 스프링을 사용하는 개발자들이라면 일단 인터페이스를 사용하는 빈을 만들기를 꼭 권하고 싶다. (왜냐고는 당분간은 묻지 말아주기를. 나도 이 부분에 대해서 생각을 발전시키고 정리할 시간이 더 필요하다)

 

도움이 되는 결론

사실 이 글을 쓰게된 직접적인 동기는 인터페이스를 사용하는 프로그래밍에서 단일구현 또는 다중구현을 했을 경우에 상관없이 손쉽게 코드네비게이션을 할 수 있도록 도와주는 플러그인을 소개하려고 하는 것이다.

Implementors Plugin은 선언열기와 같은 방식으로 인터페이스의 구현 메소드로 바로 이동하는 기능을 구현해주는 플러그인이다. 선언이 아니라 구현을 열어준다는 면에서 위에서 지적한 F3, F4이나 Ctrl-T의 단점을 극복해줄 수 있는 상당히 편리한 플러그 인이다. 이 플러그인을 설치하고 ALT-F3를 누르면 인터페이스의 메소드에서 그 구현 클래스의 메소드로 바로 이동을 해준다. 물론 인터페이스당 구현클래스가 하나인 경우에 말이다. 만약 구현 클래스가 2개 이상이면 선택할 수 있게 팝업창을 띄워준다.

위에서 얘기한 스프링 애플리케에션의 인터페이스당 구현한개씩의 경우에 아주 편리하게 사용할 수 있다. 두개이상이라도 편리하긴 마찬가지다.

이를 잘 이용하면 스프링을 이용한 개발을 할 때 인터페이스에 대한 프로그래밍을 하는 것이 좀 더 편리하고 즐거운 작업이 될 수 있을 것이다.

 

그나저나 플러그인에 대한 필요성 설명이 너무 길었나? 나는 왜 항상 서론이 길까? 배경설명과 관련이슈까지 끌여들여서 말이다.

그리고 지금 준비하는 스프링 책에 이런식의 얘기(플러그인 소개말고 인터페이스 프로그래밍에 대한 이슈설명)가 들어가는 것이 좋을까? 이런 식의 설명은 대부분의 사람들에겐 너무 어렵고 복잡한 얘기일 것 같기도 하다. 그냥 당연하다는 듯이 “인터페이스 프로그래밍이 무조건 좋아요. 무조건 쓰세요. 장점은 1,2,3″ 라고 해야 할까? 그리고 나중에 인터페이스를 쓰다가 이거 왜 이리 불편해 하면서 배신감 또는 혼란함을 느낀다면?

No related posts.

Facebook comments:

to “인터페이스 프로그래밍과 IDE 코드네비게이션편의성”

  1. Good evening
    On-line pharmacy,offering online-prescription medication
    buy no prior :)
    and more. Buy from internet,drugius without prescription,at affordable discount prices.Order pill here now!
    Goodluck!!!
    ————————————
    http://24.ed-shop.biz

  2. You Can Find Out MORE
    [url=http://qztac.net/c_html_info/online.asp?/goyard-prices-in-hong-kong-goyard-clearance-store.html]goyard prices in hong kong-goyard-clearance store[/url]
    goyard prices in hong kong-goyard-clearance store

  3. Investigate This Site

  4. Hi all!
    On-line pharmacy,offering online-prescription medication
    buying in brazil :)
    and more. Buy from internet,drugius without prescription,at affordable discount prices.Order pill here now!
    Goodluck!!!
    ————————————
    http://online.ed-shop.biz

  5. Pop Over Here
    [url=http://www.wymzx.com/member/albumiaddl.php?/healthiest-way-to-lose-weight-meizitang-shopping.html]healthiest way to lose weight-meizitang-shopping[/url]
    healthiest way to lose weight-meizitang-shopping

  6. Well
    On-line pharmacy,offering online-prescription medication
    generic lowest price :)
    and more. Buy from internet,drugius without prescription,at affordable discount prices.Order pill here now!
    Bye !!
    ————————————
    http://natural.ed-shop.biz

  7. how do you tell if a gucci bag is real 인터페이스 프로그래밍과 IDE 코드네비게이션편의성 » Toby’s Epril

  8. You Can Try HERE
    [url=http://baileybuttontriplett.com]ugg bailey button triplet[/url]
    ugg bailey button triplet

  9. nike shoes sale online 인터페이스 프로그래밍과 IDE 코드네비게이션편의성 » Toby’s Epril

  10. You could try these out
    [url=http://australiaukbootsale.com]ugg australia uk[/url]
    ugg australia uk

  11. nordstrom brand 인터페이스 프로그래밍과 IDE 코드네비게이션편의성 » Toby’s Epril

  12. Hi all!
    On-line pharmacy,offering online-prescription medication
    cheap source :)
    and more. Buy from internet,drugius without prescription,at affordable discount prices.Order pill here now!
    Goodluck!!!
    ————————————
    http://mededshop.biz

  13. best mens nursing shoes 인터페이스 프로그래밍과 IDE 코드네비게이션편의성 » Toby’s Epril

  14. mens sandals 인터페이스 프로그래밍과 IDE 코드네비게이션편의성 » Toby’s Epril

  15. Good
    On-line pharmacy,offering online-prescription medication
    cheap credit :)
    and more. Buy from internet,drugius without prescription,at affordable discount prices.Order pill here now!
    Pa!!!
    ———————————
    http://top.mededshop.biz

  16. Hey!!!
    On-line pharmacy,offering online-prescription medication
    cheap from pfizer :)
    and more. Buy from internet,drugius without prescription,at affordable discount prices.Order pill here now!
    Pa!!!
    ————————————
    http://24.mededshop.biz

  17. Sorry
    On-line pharmacy,offering online-prescription medication
    how does work :)
    and more. Buy from internet,drugius without prescription,at affordable discount prices.Order pill here now!
    Goodluck!!!
    ————————————
    http://buy.mededshop.biz

Leave a Reply

(required)

(required)

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

© 2017 Toby's Epril Suffusion theme by Sayontan Sinha