인터페이스의 이해와 활용

인터페이스라는 단어를 처음 들어보는 개발자는 없을 것이다. 때로는 디지털 기기나, 기술 변화를 설명할 때도 자주 사용되는 말이다 보니, 일반인들 중에서도 아는 사람이 많은 단어라고 할 수 있다. 그런데 정작 인터페이스가 무엇인지 설명해보라고 요청하면 말문이 막히는 경우가 많다. 객체나 클래스는 아는데 인터페이스는 잘 모른다? 그런데, 다들 중요하다고 한다. 제대로 이해하지 못하면 제대로 쓰지 못하는 법이다. 확실히 이해하고 적절히 활용할 수 있도록 해보자.

기초지식 : 객체와 클래스에 대한 이해, 객체지향 언어 개발 경험

응용분야 : 시스템 분석 및 설계, 프레임워크 개발 등

-----------------------------------------------


객체지향 언어를 이용해 개발하는 프로그래머들 중에서 객체나 클래스를 이해하지 못하는 개발자는 없을 것이다. 이를 모른다면 아예 개발을 할 수 없을 터이니 말이다. 하지만, 추상 클래스라던가 인터페이스를 제대로 이해하는 개발자를 만나는 것은 드문 일이다. 그럴 법도 한 것이 사실 인터페이스를 몰라도 개발하는데 전혀 지장은 없기 때문이다. 그럼 인터페이스는 불필요한 기술이거나, 전문가들이 높은 내공을 과시하기 위해 장식에 불과한 것일까? 하지만, 곳곳에서 ‘인터페이스를 이용해서 개발 혹은 설계하라‘는 격언이 많이 인용되는 것을 볼 수 있다. 인터페이스라는 것은 엄밀히 말하면 ’구현‘ 기술이 아니라 ’설계‘ 기술이다. 복잡한 시스템을 단순하게 표현하고, 명확히 설계하는데 유용한 기술이기 때문에 개발자들에게는 멀리 느껴지는 것이다. 몰라도 된다고 하지만, 설계자로 거듭나고 싶어 하는 개발자에게는 꼭 정복해야 하는 개념, 그것이 바로 인터페이스인 것이다.


인터페이스 개념 이해

우선 인터페이스라는 용어에 익숙해지는 과정이 필요하다. 필자는 독자 분들이 인터페이스라는 용어에 대해 거부감을 가지고 있거나, 난해하다고 여기고 있다고 가정하고 있다. 따라서 처음에는 약간 쉬운 이야기로 풀어갈 것이다.


사전적 정의 (연결 고리)

인터페이스(interface)는 영어에서 유래한 단어이므로 영단어를 분석해보자. 인터페이스는 face 단어 앞에 inter라는 접두어가 연결된 것이다. 이 점에 착안해서 인터페이스의 정의를 내리면 좀 더 쉽게 이해할 수 있는데다 오래도록 기억할 수 있다. (다행히도 둘 다 아주 쉬운 단어다.)

face는 얼굴이고 inter는 마주 본다 혹은 사이에 위치한다는 뜻을 가지고 있다. 즉, 인터페이스는 두 사람(혹은 두 개체)이 마주 보고 있는 모습에서 둘을 연결하는 무언가를 위미하는 것이다. 여기서 양측은 이질적인 것, 다른 것을 의미한다. 그러니 인터페이스는 다른 언어를 쓰는 외국인 간에 통역하는 기계라거나, 서로 다른 것을 연결하는 고리 등을 지칭한다는 것을 알 수 있다.


다리(bridge), 관문(gate) 혹은 어댑터(adapter)

인터페이스라는 단어를 그대로 암기하기 보다는 다리, 관문 혹은 어댑터라는 용어를 함께 기억하는 것이 좋다. 앞으로 본 문서에서 설명하는 내용을 읽으면서 이해가 가지 않을 때마다 인터페이스는 ‘서로 다른 세계(혹은 시스템)를 연결하는 관문‘이라고 떠올리면 좀 더 쉽게 받아들여질 거라 확신한다.


추상화의 단계

앞서 인터페이스의 일반적인 정의를 설명했는데 객체지향 기술 혹은 소프트웨어에서 말하는 인터페이스라는 것은 무언지 떠올리기에는 설명이 너무 막연하다고(혹은 막막하게) 여겨질 것이다. 그래서 이번에는 반대 과정으로 설명해 볼 것이다. 소프트웨어를 구성하는 부품(컴포넌트, 함수, 라이브러리)들의 진화 역사를 통해서 인터페이스라는 개념이 어떻게 소프트웨어 세상에 나타나게 되었는지 알아보자.

덤으로 한 가지 더 이야기하자. 추상화라는 말이 어렵다는 개발자를 많이 접하게 되는데, 추상화의 영어 단어가 무엇인가? abstraction인데, 사전을 뒤져보면 ‘요약’이라는 풀이가 있다. 책(혹은 논문)을 쓸 때, 가장 앞에서 책 전부를 요약해 한 페이지로 설명한 것도 abstract라고 한다. 추상화라는 단어와 함께 ‘요약’을 떠올리자. 의외로 어렵지 않게 받아들여질 것이다. 결국, 복잡한 것에서 중요한 것만을 남기고 단순화 시키는 작업이 바로 추상화인 것이다.


함수와 변수

소프트웨어를 구성하는 가장 작은 부품이 무어냐고 물으면 대체로 함수(function)라는 것에 이의가 없을 것이다. (명령어는 너무 작은 단위라 부품이라고 부르기는 어렵다.) 소프트웨어 초창기(1950년대~1970년대)에는 모든 프로그래머가 함수들을 연결해 프로그램을 개발했고, 지금도 여전히 함수만으로 개발하는 언어(C 언어)가 널리 사용되고 있다. 함수는 어떤 기능을 수행할 수 있도록 준비된 부품이고, 변수라는 저장소에 자료를 담아서 사용자가 원하는 결과를 만들어 낸다. 그런데 자료를 담고 있는 변수는 함수 안에 있을 수도 있고, 밖에 있을 수도 있다. 즉, 함수와 변수는 분리되어 있다.


객체 혹은 클래스

함수들을 집합시켜 개발을 하다 보니 복잡한 문제를 푸는데 있어서 단점이 드러나기 시작했다. 함수와 변수가 분리되어 있으니, 자동차를 만드는데 연료통이 차 밖에 달려 있거나, 아예 연료 파이프를 끌고 다니는 모양새로 만들어지는 경우가 발생하는 것이다. 환기구와 각종 케이블이 모두 겉으로 드러나 있는 건물들을 상상해보라. 과연 그런 도시에서 살 수 있겠는가? 도저히 이래서는 안 되겠다는 반성 때문에 함수와 자료를 한꺼번에 묶어서 부품을 만드는 방식이 제안되었다. 두 가지를 묶어서 객체라고 표현하기로 하고 똑같은 객체들의 집합은 클래스라고 부르기로 했다. 요약하면, 객체는 함수 밖에 있던 변수를 안으로 집어넣고 보이지 않게 만들어 추상화(요약) 시킨 것이다.


추상 클래스 (abstract class)

클래스라는 개념을 통해서 기능과 자료를 함께 묶는데 성공하고 나니, 개발자(혹은 설계자)들은 더욱 욕심을 내기 시작했다. 모든 부품을 늘 완제품 상태로 만들 필요가 있는가? 고급 개발자(설계)는 핵심 기능만 가진 미완성 반제품을 만들고 다른 사람이 장식(혹은 부가 기능)을 추가해서 완성하게 하는 건 어떠냐는 아이디어를 내놓은 것이다.

클래스를 만들 때는 어떤 함수는 완성하고, 다른 기능은 상속해서 구현해야 하게끔 비워놓은 것이 바로 추상 클래스이다. 이런 방식으로 만들면 특정 회사(혹은 개발팀)가 필요한 모든 것을 만들 필요가 없게 된다.

차트(chart)를 그리는 클래스 라이브러리를 만들어 파려는 개발 회사를 예로 들어보자. 고객들의 요구는 너무나 다양해서 차트 글자 크기나 색상 조정 뿐 아니라 온갖 장식을 추가하고 싶을 것이다. 그렇다고 모든 요구를 만족하는 제품을 만들다 보면 제품 출시 시점은 엄청나게 늦어지고 말 것이다. 차라리, 기본적인 차트 생성 기능을 제공하고 장식을 손쉽게 추가할 수 있도록 만든다면 보다 빨리 제품을 출시할 수 있고 더 많은 고객들이 만족할 것이며, 더 많이 팔 수 있게 된다. (소프트웨어도 상품인지라 완벽하면 더할 나위 없이 좋겠지만 많이 팔리지 않으면 가치가 없어지는 것이다)

그럼 추상 클래스보다 함수 내역을 제공하고 사용자(개발자)가 임의로 조합하는 방법도 있지 않는가 하고 반문하실 것이다. 사용하는 사람 입장에서 함수들을 잘못된 순서로 사용하면 원하는 결과를 얻을 수 없지만, 추상 클래스는 작업 순서가 추상 클래스 내에 정확히 정해져 있고, 사용하는 사람은 필요한 부분만 추가하는 방식이기 때문에 오동작할 가능성이 극히 적어지는 것이다. (물론 추상 클래스를 사용하면 사용자가 전체 흐름을 이해할 수 없다는 단점이 발생한다.)


그리고 인터페이스

이제 인터페이스가 등장할 차례다. 추상 클래스는 반제품이라고 했는데, 이왕에 요약해 가는 김에 완전히 구현을 제외하고 필요한 기능 내역만을 작성하는 어떨까 하는 아이디어를 떠올리게 된 것이다. 다른 말로 스펙(spec, specification)만을 기술한다고 말하는데, 설계하는 사람이 원하는 기능의 명칭과 입출력 값의 내역(종류와 타입)만을 기술한 것을 인터페이스라고 한다.

함수, 클래스, 추상 클래스를 작성하려면 클래스 내부에서 동작하는 코드를 작성해야 하므로 분명히 개발자가 필요하다. 하지만, 인터페이스를 작성하는데 있어서는 개발자가 필요하지 않다. 설계자 입장에서 이보다 더 좋을 수는 없다. 물론 그렇다고 해서 개발 경험이 전혀 없거나, 소프트웨어를 이해하지 못하는 사람도 작성할 수 있다는 건 아니다. 오히려, 개발 경험이 풍부한 사람만이 자신이 작성한 인터페이스가 실제 구현 가능한지 예측할 수 있다. (예지 능력을 가져야 한다는 말이 될 수도 있다.)

그나저나 왜 명세 클래스(spec class)라거나 요구 정의(needs definition) 같은 단어가 아니라 난데없이 인터페이스라는 단어를 쓰게 된 것일까? 앞서 설명한 내용을 되짚어 보자. 개발자와 설계자는 어찌 보면 다른 일을 사람들이다. (자동차 디자인 하는 사람과 자동차 만드는 사람은 같이 일하지만 서로 다른 직업으로 분류하는 것과 마찬가지다) 그러니, 서로 다른 일을 하는 사람들 사이에 의사소통을 위한 도구라서 인터페이스라고 불리게 된 것이다. 게다가 클래스처럼 구현 코드를 포함하지 있지도 않으니 유사한 용어는 오히려 혼동을 일으킨다.


인터페이스 활용 방안

제대로 이해하는 것도 중요하지만 그것을 활용할 수 없다면 애써 학습한 시간이 낭비되고 말 것이다. 인터페이스가 실무에서 적용되는 사례들을 모아 더욱 와 닿을 수 있게끔 설명해 볼 것이다.


표준 정의

소프트웨어 업계에는 다양한 표준화 조직(혹은 기관)이 존재하는데 표준의 필요성에서 대해서 상세히 설명할 필요는 없을 것이다. 전세계 개발자가 공통으로 사용하기를 바라는 어떤 서비스를 설계하는데 있어서 인터페이스는 아주 유용한 방법이다. 구현 코드가 필요 없기 때문에 운영체제나 하드웨어에 상관없이 표준을 만들 수 있기 때문이다. 예를 들어, 자바 표준 위원회 같은 곳에서 인터페이스를 정의하면 HP, 썬, IBM, Microsoft 같은 기업이나 아파치 같은 공개소프트웨어 개발 단체에서 실제 구현한 제품을 만들면 되는 것이다. 이렇게 되면 개발자들은 똑같은 방식으로 개발할 수 있으면서 다양한 성능과 특색을 가진 제품(웹 서버, 미들웨어 등)들을 골라서 쓸 수 있다.


설계자와 개발자의 소통

개발 조직이 아주 거대한 회사라면 개발하는 사람과 설계하는 사람이 함께 토론하면서 개발하는 것이 어려울 수도 있다. 설계자와 개발자 아예 다른 기업에서 일할 수도 있다. 과거의 방식대로라면 설계자는 요구 문서를 정리해서 개발자에게 전달하고 개발자는 나름대로 상상력을 발휘해서 각종 클래스를 만들고 조합해야 한다. 만약, 개발자가 설계자의 의도를 제대로 이해하지 못했다면 개발 도중에 심각한 잘못이 발견되는 재앙이 발생할 수도 있다. 하지만, 인터페이스 정의를 설계자가 작성하면 개발자는 훨씬 편하게 작업할 수 있게 된다. 왜냐하면 어쨌든 인터페이스도 컴파일 가능한 소스이므로 이해하기 쉽고 즉시 구현 작업이 가능하기 때문이다.


내부와 외부, 현재와 미래의 연결

그 어떤 개발자도 거대한 시스템을 단시간에 개발할 수는 없다. 혹은 혼자서 모든 것을 만들 수는 없다. 그러나 인터페이스를 정의해두면 내부의 개발자가 아니라 외부의 누군가가 부족한 부분을 추가하거나, 가까운 미래에 기능을 추가하는 것이 용이해진다. 인터페이스를 사용하면 구체적인 내용을 정의하지 않고도 전체를 조직하는 것이 가능하기 때문에 개발 시간을 단축하는 효과를 누릴 수 있다. 반면에 클래스만을 사용한다면 내용이 없는 불완전한 코드의 집합이 되거나 아니면 컴파일 할 수 없고 실행시켜 볼 수 없는 시스템이 만들어 진다.


플랫폼, 프레임워크(라이브러리)와 어플리케이션의 연결

최근의 개발 환경을 들여다보면, 많은 곳에서 인터페이스가 활용된다는 것을 알 수 있다. 스프링, 스트럿츠 같은 프레임워크, 톰캣 웹 컨테이너, EJB 서버 혹은 닷넷 서버에서 여러분이 필요한 기능을 작성할 때 인터페이스를 구현하게 된다. 최신 어플리케이션은 더 이상 모든 작업을 구현하지 않는다. 웹 서비스를 예로 들자면 서버와 브라우저 간의 연결, 데이터베이스 연결 등의 작업은 거의 플랫폼 역할을 담당하는 별도의 서버가 담당한다. 어플리케이션은 서버가 요구하는 인터페이스를 구현해 꼭 필요한 비즈니스 로직(UI 생성, 자료 가공 등)만을 제공하는 것이다. 이로서 성능, 개발 생산성, 보안 등 모든 면에서 신뢰도와 만족도가 증가하게 되는 것이다.


이질적인 기능의 조합

서로 다른 성질을 가진 기능들을 조합하고자 할 경우에도 인터페이스가 사용된다. 가장 대표적인 예가 자바에서 Runnable 인터페이스인데, 클래스와 달리 인터페이스는 다중상속을 허용하기 때문에 특정 비즈니스 로직을 담고 있는 클래스에 멀티스레드 기능을 추가하기 쉬워진다. 한 가지 예를 더 들자면, 자동차와 비행기를 설계한 후에 나는 자동차를 추가하고 싶다고 한다면 자동차와 비행기를 인터페이스로 정의한 후, ‘나는 자동차’는 두 인터페이스를 구현하게끔 설계하면 되는 것이다.


마치면서

인터페이스는 개발 과정을 통제(control)하려는 노력의 산물이며 족쇄이다. 인터페이스에 의해 설계된 시스템에서 개발자는 설계자의 의도에서 벗어날 수 없게 되는 것이다. 그러나 통제됨으로써 자유도가 줄어든다는 단점에 비해서 오류를 극적으로 감소시키며, 표준화를 통한 생산성 향상을 실현할 수 있다는 장점이 더 많기 때문에 앞으로 더 많은 곳에서 사용될 것이다. 만약, 개발자가 수동적으로 구현하는 것을 원치 않는다면 인터페이스를 이해하고 오히려 적극적으로 활용해야 할 것이다. 인터페이스는 거대한 시스템을 손쉽게 설계할 수 있고, 이해할 수 있게 하면서도 작성이 손쉬운 강력한 도구인 것이다.

이미 거의 모든 개발 환경에서 인터페이스가 보편화 되어 버렸다. 자바, 닷넷 그리고 수많은 프레임워크들이 인터페이스 기반으로 설계되고 개발되고 있다. 피할 수 없다면 차라리 적극적으로 받아들이는 것이 낫고, 나아가 설계자로 거듭날 수 있다면 금상첨화가 아니겠는가?

 

모 잡지에 기고했다가, 낙첨되어 버린 바람에 블로그에 올립니다. 아래한글을 그대로 복사해서 붙이기 하다보니 글씨가 작게 나오네요. 편집하기 까다로와서 그대로 올립니다.

by 써니 | 2007/01/02 11:41 | Development | 트랙백(2) | 덧글(6)

Tracked from 좌충우돌 세상이야기 at 2007/01/16 12:42

제목 : 천천히 다시 음미 해보자.
인터페이스의 이해와 활용 나야 아직 C개발자라 객체지향적 프로그래밍을 쓰고 있지 않지만 요 근래 추세로 봐서는 C++,java를 상황에 맞게 다루어야 하기 때문에 조금씩 공부하고 있다. 중간 중간 인터페이스란 것을 보긴 했지만 역시 먼지 잘.... 내가 이해한 인터페이스와 매칭이 안된다...ㅎㅎ ...more

Tracked from 인생버전v2.0 at 2007/08/11 00:25

제목 : 추상함수와 인터페이스를 왜 써?
C#을 공부하면서 "추상함수"와 "인터페이스"에 접어들면서...개념 자체도 참으로 난해 했지만 더 혼란스러웠던건 그 어디에도 이 두가지 기법을 "왜 사용하는가?"에 대해서 명확한 답을 들을 수 없다는 것이었다. 사용 방법을 외울 수는 있지만 사용의 이유와 상황을 알 수 없으니...외운다고 그것이 오래 기억되거나 꼭 필요한 때에 떠오를리 만무하지 않은가. 난감하던 때에 써니님의 가려운 곳을 긁어 주는 글을 보았다....more

Commented by 부엉 at 2007/01/02 12:15
흑흑..
오랜만에 보는 명쾌한 OO얘기군요..
주위에 좀 권해줘야 겠습니다..
좋은글 감사합니다. (__)
Commented by 똘기 at 2007/01/02 14:14
잘 읽고 갑니다^^
Commented at 2007/01/02 15:57
비공개 덧글입니다.
Commented by 붕어가시 at 2007/01/02 19:18
intergrated communication이란 마케팅개념에 interface 개념을 도입하려고 구상중이었는데 반가운 글 읽고 갑니다. 아 물론 제가 더 높이 올라간 후 적용하려구요^^
Commented by Naive at 2007/01/02 19:53
바로 체크포스트에 넣어뒀습니다.^^; 공부에 많은 도움이 되겠군요. 언제나 좋은 글, 좋은 자료 감사합니다!
Commented by nimbus9030 at 2007/01/16 12:38
읽긴 읽었으나 완벽히 이해가 안되는...+_+
역시 더욱 더 많이 공부하고 배워야 겠습니다.
※ 이 포스트는 더 이상 덧글을 남길 수 없습니다.

◀ 이전 페이지          다음 페이지 ▶