루비에 열광하는 사람들은 한참 살피다가 'Humane Interface' 라는 용어를 자주 보아왔다. 이 말은 루비 사용자들의 클래스 인터페이스 작성 경향을 보여준다. 또한 이 용어는 API 를 설계하는 다른 사고를 보여주는 용어인 Minimal Interface와 재미있는 대조를 이룬다.
Humane Interface의 핵심은 사람들이 하고자 하는 것고, 상식적으로 이를 쉽게 그것을 할 수 있도록 인터페이스를 설계하는 것이다.

Humane Interface 는 점진적으로 커지는 경향을 보이는데다가 Humane Interface 에 입각한 인터페이스 설계자는 인터페이스가 커지는 것에 대해서 걱정하지 않는다는 점에서 Minimal Interface와 분명한 대조를 이룬다. 그렇다고 해서 Humane Interface 를 갖는 클래스가 구현할 때도 커져야 한다는 것은 아니다. 근본적인 기능면에서는 양자는 상당히 흡사하다.

Java 와 Ruby 의 List 컴포넌트를 비교하면 둘 사이의 차이점을 확연하게 볼 수 있다. Java 는 25개의 메소드 선언을 포함하는 java.util.List 인터페이스를 갖고 있다. Ruby 는 Array 클래스(이름과 달리 배열이 아니라 list)를 갖고 있는데 메소드 숫자는 78개이다. 메소드 숫자는 서로 다른 스타일이 존재한다는 단서라고 할 수 있다. 두 컴포넌트는 기본적으로 동일한 서비스를 제공하지만, Ruby 의 Array 는 많은 부가적인 기능을 포함하고 있다. 이들 기능은 Java 의 Minimal Interface 기반 위에서 어렵지 않게 구축할 수 있다.

둘 사이의 차이를 확연히 하기 위해서 작은 예제 하나를 보자. List 이 마지막 항목을 얻는 것인데, Java 에서는 다음과 같이 할 수 있다:

aList.get(aList.size -1)

Ruby 에서 같은 것을 수행하면:

anArray.last

사실 더 놀라운 것은 Ruby 의 Array 는 first 메소드도 갖고 있다는 점이며, anArray[0] 가 아니라 anArray.first 로 쓸 수 있다.

Ruby의 부가 기능 중에서는 좀 더 복잡한 기능도 있다. Ruby 의 Array 는 flatten 메소드를 갖고 있는데, 중첩된 Array 를 단일 수준으로 변환할 수 있다.

irb> [1,2,[3,4,[5,6],7],8].flatten => [1, 2, 3, 4, 5, 6, 7, 8]

강조하고 싶은 점은 last 와 같이 단순한 기능이든 flatten 과 같은 복잡한 기능이든 Ruby 의 부가적인 기능 모두는 Java 의 List 인터페이스의 메소드 숫자를 늘리지 않고도 클라이언트가 직접 구현할 수 있다는 것이다. Minimal Interface 지지자 관점에서는 동일한 서비스를 제공한다면 최소한의 메소드를 갖는데 초점을 맞추는 반면 Humane Interface 지지자들은 필요하다면 메소드를 추가하는 경향을 보인다.

그렇다면 무엇을 기준으로 Humane Interface 에 메소드를 추가해야 하는가 하는 의문을 갖게 된다. 누구나 원하는 것 모두를 추가한다면 너무 복잡한 클래스를 만들게 될 것이다. Humane Interface 지지자들은 클래스의 가장 일반적인 용도가 무엇이냐를 식별하고 이를 쉽게 수행할 수 있도록 설계하려고 노력한다.

이러한 원칙은 메소드를 부여하는 것에 국한된 것이 아니라 작명에도 적용된다. RubyConf 에서 Tanaka Akira 는 자주 쓰이는 메소드에 짧은 이름을 붙이는 것이 유용하다는 것을 강조했다. 자주 사용되기 때문에 친숙해져 있기 때문에 짧은 이름을 쓰는 것이 기억하는 면에서나 가독성, 타이핑 측면에서 유리하다는 것이다. DateTime 클래스에서 기본 날짜 형식을 파싱하는 디폴트 메소드는 parse 인 반면 어떠한 형식의 날짜도 모두 지원하는 보다 유연한 메소드 이름은 strptime 인데 상대적으로 자주 쓰이지 않는다는 측면을 이러한 현상의 한 예로 볼 수 있다.

Ruby 의 Humane Interface 철학이 만들어낸 또 하나의 재미있는 현상은 메소드 이름에 대한 별칭이다. List 의 길이를 원할 때, length 나 size 중에 무엇을 사용해야 할까? 라이브러리에 따라 다른 경우가 일반적이지만 Ruby 의 Array 는 둘 모두를 갖고 있다. Ruby 사용자 관점에서는 라이브러리 사용자가 어떤 것을 쓸 지를 기억하는 것보다는 둘 다 지원하는 것이 더 쉽다는 것이다.

인터페이스 설계에 있어 어떤 스타일이 가장 좋으냐는 쉽게 풀리지 않는 우문이다. 끝으로 Humane Interface 지지자의 주장을 요약해 보겠다. (다른 측면을 보려면 간결함을 지향하는 인터페이스(Minimal Interface)를 보라.)

객체의 강점은 객체가 갖는 데이터보다는 주로 행위에서 찾을 수 있다. 최소한의 서비스만 제공한다면 다수의 사용자들은 동일한 사례에 대해 동일한 코드를 양산할 것이다. flatten 메소드가 없다면 수많은 사람들이 각자 재귀함수를 작성할 것이다. 이것은 어려운 일은 아니지만, 빈번하게 발생하는 일이라면 많은 사람들이 각자 노력을 기울일 필요가 있는가?

last 와 같이 단순한 서비스의 경우에도 라이브러리 사용자는 관용구와 같은 idiom 을 배울 필요가 있다. 직관적인 사용법이 있다면 돌아갈 필요는 없다. 좋은 소프트웨어는 사용자를 먼저 생각해야 하고, 그들의 삶을 편안하게 해주어야 한다. Humane Interface 는 이러한 원칙을 따른다.

Humane Interface 는 보다 많은 일을 수행함으로써 사용자를 부담을 덜어준다. 특히 개발자에게는 소스코드 읽기와 작성 모두에 있어 일반적인 작업을 쉽게 해주는 API 가 필요하다.

Humane Interface 나 Minimal Interface, 모두 훌륭한 근거를 갖고 있다. 쉬운 판단은 아니지만, 개인적으로는 Humane Interface 쪽이 끌린다.

원문: HumaneInterface

* forgiving API라는 표현도 쓰네요. (2008.7.1 추가)
이올린에 북마크하기(0) 이올린에 추천하기(0)

이글을 읽는 독자라면 프로그래밍 언어인 루비(Ruby)에 대한 관심과 논란이 많음을 알고 있으리라 생각된다. 그중에서도 웹 애플리케이션 개발 프레임워크인 Rails에 대해서는 더욱 두드러지다. 어떤 이들은 Rails가 앞으로 나아갈 방향이라고 말하기도 하고, 다른 이들은 위험한 시도로 폄하하기도 한다.

나는 몇 년전부터 루비를 다뤘다. 나는 pragmatics 시리즈에 관심을 갖게 되었고, 곧 스크립트 언어중에서 루비를 가장 좋아하게 되었다. 시간이 흐를수록 내 사이트, 그 중에서도 이 블리키(bliki)의 많은 부분은 루비로 개발했다. 나는 루비를 무척 좋아한다.

내가 루비를 좋아하는 것과 고객의 프로젝트에서 사용하는 것은 별개의 문제다. 고객의 프로젝트에서 루비가 적합한지 평가하는 것은 시스템의 특징에 달려있다. 한편, 루비를 평가하고자 들면 동적인 타입 정의(dynamic typing)와 설정없이 컨벤션을 따르는 것(convention over configuration)의 장단점 논란이나 프로세스기반 프로그래밍과 쓰레드 기반 프로그래밍의 차이에 관한 논란을 마주하게 된다. 이러한 논란은 유용하긴 하지만 나는 이들에 대해 언급하는 것을 조심하게 된다. 토론에 의해서이를 평가하는 것은 무척이나 어려운 일이며 고객의 프로젝트에서 평판이 좋은 기술 탓에 프로젝트가 지연되는 일을 겪기도 한다. 나는 토론보다는 경험에 기반해서 평가를 내린다. 루비를 사용했던 사람과 주요 프로젝트에 적용되었던 기록을 갖고 있는 사람을 찾는다. 공공연하게 이러한 내용들이 기록된 것을 찾을 수 있다. 많은 사람들이 루비에 매력을 느낀다. 그들은 다른 언어를 통해서도 성공적인 경험을 갖고 있지만, 루비는 그와는 다른 이점을 제공한다고 한다. Andy, Prags, Justin Gehtland, Bruce Tate, David Geary 등은 루비에 더욱 관심을 가게 하는 이들이다. 그러나, 나의 주로 ToughtWork의 직원들의 경험을 최우선시하는 편협함을 갖게 된다.

아직 이른 감이 있지만,  몇몇 프로젝트를 루비를 활용하여 진행했고, 아직까지는 상당히 긍정적이다. 자바나 C#에 보해 눈에 띌 정도로 생산적이냐는 질문을 받으면, 매번 강하게 그렇다고 얘기한다. 적절한 프로젝트에 사용하는 경우는 이는 옳은 대답이라고 생각된다. 그렇다면 어떠한 적합한 프로젝트인가 하는 물음이 남는다.

우리회사가 수행하는 몇몇 웹 프로젝트는 모두 Rails의 영역에 부합하는 것이지만 서로 다른 측면을 갖고 있다.
  • 사용자가 터치 스크린을 이용해 조작하는 키오스크 장비 개발. UI가 Ajax 스타일에 딱 맞기 때문에 Rails를 사용한다. 그러나, 리눅스 환경하에서 하드웨어 장비와의 통신, 암호화나 복잡한 네트워크 관련된 기능들을 포함하고 있다.
  • 배치 공정에서 수많은 SQL 조작을 하는데 Ruby를 쓰는 경우가 있다. Ruby 구무문이 궁극적으로는 SQL로 변환되어 실제작업이 수행된다.  전형적인 Rails 애플리케이션은 아니지만, 앞단에서 Rails의 역할은 상당히 적절하다.
  • 여러모로 전형적인 웹 애플리케이션으로 취급할 수 있는 프로젝트이지만 상당량의 데이터를 여러 유형으로 변환해야 하고 보기 좋은 그래프나 차트를 출력해야 하는 것이 포함되어 있는 경우.
이 모든 경우에 있어 다른 플랫폼과 비교했을 때, 루비가 발휘하는 기능과 가치는 점점 막강해지고 있다. 이런 연유로 빠른 개발과 생산성이 요구되는 경우라면, 루비를 심각하게 고려해보라고 권하고 싶다. 아직은 몇몇 의문이 남아있다. 특히 아직은 초기라 팀에 변화가 가해진다거나 하는 상황에서 어떠한 일이 벌어질지에 대해선 알 수 없다. 어떤 이들은 루비의 동적인 특성과 도구 부족을 문제삼고, 루비 적용으로 발생하는 단순함이 진정함 강점이라고 말한다. 이러한 유형의 문제는 아직은 뭐라 말하기 힘든 것이기에 더 알게 되면 그때가서 이글을 갱신하겠다.

Cedric Beust는 자신의 글
에서 루비가 아무리 훌륭한 플랫폼이라고 해도 주류가 되지는 못할 것이라고 논리적인 주장을 펼쳤다. 나는 그의 주장이 충분히 설득력이 있다고 생각한다. 과거에도 충분히 생산성이 뛰어난 플랫폼이 있었지만 현재 주류로 자리잡지는 못한 선례는 많다. 주류 플랫폼을 취급하는 경우라면 아직은 시간을 두고 지켜볼 필요가 있다. 주류 여부를 따지는 문제에는 관심이 없는 이들도 상당하다.

또한, 여러 프로젝트가 정치적인 이유나 기타 의사소통의 문제로 생산성 저하를 겪는 일은 다분히 발생한다. 이러한 경우라면 루비의 장점은 별로 두드러져보이지 않게 된다. 그러나, 전체적으로 봤을 때 나는 점점 속도나 응답성, 생산성이 중요한 민감한 작업에도 루비를 사용하는 것에 긍정적인 생각을 갖게 된다.


기타 참고 사항
국내 Ruby 호스팅 업체: http://rails.korserve.net/


답글 보기

이올린에 북마크하기(0) 이올린에 추천하기(0)

DSL(domain specific language)는 범용적인 문제에 초점을 맞추는 일반적인 프로그래밍 언어와는 다르게 특수한 문제에만 초점을 맞추는 언어다. DSL은 컴퓨터의 역사와 함께 오래도록 회자되었다.

DSL을 많이 사용하는 커뮤니티인 유닉스 커뮤니티에서는 그것을 작은 언어(little languages) 혹은 미니 언어(mini languages)로 부른다. 흔히 그것을 little 언어 또는 mini 언어라고 부릅니다. (Eric Raymond는 이러한 전통을 논한 유용한 기록을 제공한다.) 널리 통용되는 유닉스식 접근은 하나의 언어에 대한 문법을 정의하고, 목적하는 언어를 코드를 생성하거나 DSL을 위한 번역 프로그램(interpreter)를 작성한다. 유닉스는 이러한 작업을 도와주는 많은 툴을 갖고 있다. 나는 주로 이런 종류의 DSL을 External DSL이라고 지칭한다. XML 설정 파일도 하나의 External DSL이다.

Lisp과 smalltalk 커뮤니티 또한 DSL에 대한 강한 전통을 갖고 있지만 사용하는 방식에 있어서 차이가 있다. 그들은 새로운 언어를 정의하기 보다는 범용적인 목적의 언어를 DSL로 변형시킨다.(Paul Graham은 이를 Programming Bottom-Up에서 잘 설명해놓았다.) 이러한 Internal DSL(또는 embedded DSL)은 프로그래밍 언어를 그대로 활용하여 DSL을 정의한다. 이것은 어떤 언어에서도 작업할 수 있는 보편적인 방법이다. 나는 항상 접하는 문제를 DSL의 형태로 정의할 수 있는 기능에 대해 고민해왔다. 그런데 Lisp과 Smalltalk 사용자들은 훨씬 앞서 이런한 방법을 활용했다.

최근에 작성한 나의 논문, Language Workbenches가 DSL의 Killer-app 인가?에는 이들 두 가지 형태의 DSL에 대한 많은 예를 수록하고 있다. 또한, 두가지 방안에 대한 장단점을 자세하게 언급했고,  DSL이 널리 보급되었으면 하는 마음에 최근 개발 된 language workbench 도구에 대해 많은 이야기를 했다.

이러한 두 가지 조류는 PragDaveThe Pragmatic Programmers, LLC의 영향력의 배경이기도 하다. The Pragmatic Programmers, LLC는 오랫동안 DSL의 팬이었다. 특히, 유닉스 진영의 전통의 영향을 따르는 훌륭한 논의가 The Pragmatic Programmer의 12절에 있다. 아마도 난 그 내용을 Pragmaticum 12이라고 말해야 할 것 같다. Dave[각주:1]는 그의 사려 깊은 인터뷰[각주:2]에서 코드 생성 기능을 자주 활용하지만, 루비(Ruby)를 사용할 때는 다르다고 말한다.

나는 항상 DSL을 만든다는 생각으로 설계를 해나가곤 했다. DSL로 활용할 의도로 클래스와 메소드를 만들어 가는 것이다. 내가 사용하는 언어가 허용하는 범위내에서 최대한의 시도를 했지만, 한계에 부딪히면 곧바로 코드 생성을 활용했다. ThoughtWorks에서 우리는 코드 생성을 사용해 왔고 비슷한 기술들을 우리의 커다란 시스템에서 사용해 왔다. 어떤 언어를 사용하느냐에 따라 DSL과 같은 별도의 언어에 대한 필요성도 현격하게 달라진다. Smalltalk를 사용할 때 별도의 언어를 필요로 하지 않았지만, C++/Java/C#에서는 별도의 언어가 필요한 것은 너무나도 자연스러운 일이다.

결과적으로 다른 언어에 비해 internal DSL에 적합한 언어가 존재하는 것은 자명해 보인다. Lisp과 smalltalk를 통해서 전통적인 어어에 비해 하나의 기본적인 아이디어에 충실해서 보다 간단하면서 특정 분야에 충실한 최소지향적 언어(minimalist languages)가 internal DSL에 적합하다고 결론을 지었다. (function application을 위한 Lisp과 객체와 메시지에 특화된 Smailltalk) 그러나, 루비는 보다 프로그래머사이의 관습을 선호하며, Lisp이나 Smalltalk과는 달리 방대한 (기능과 API를 가진) 언어이지만, internal DSL에 적합하다.

그래서 아마도 internal DSL이 필요로 하는 것은 적절한 선택에서 비롯한 간명함이라고 생각된다. 널리 쓰이는 것들을 쉽게 사용할 수 있게 해주고, 복잡함을 최대한 해소한 멋진 문법을 제공해야 한다. 그것이 어떤 언어든 이러한 간명함을 갖는 것은 매우 중요한다. 나는 종종 java나 c#보다 Smalltalk이나 루비로 프로그래밍을 즐기는 이유를 글로 표현하는 것이 어려움을 알게 된다. 주로 그 이유로 정적인 타입 정의와 동적인 타입 정의를 언급했지만, 그때마다 나는 핵심을 놓치고 있음을 느꼈다. 아마도 Internal DSL에 대한 친밀함이 그 핵심에 더욱 가까울 것이다.


원문: DomainSpecificLanguage

번역: 영회, 백기선
  1. Dave Thomas, The Pragmatic Programmer의 공동 저자이면서 The Pragmatic Programmers, LLC를 대표하는 인물인 듯 합니다. 아마 PragDave는 그의 블로그인 것 같은데, Martin Fowler가 원문의 PragDave에 걸어둔 링크는 http://pragprog.com/pragdave였는데 현재는 http://pragmaticprogrammer.com/으로 포워딩 되고 있습니다. [본문으로]
  2. 현재 링크가 깨져 있다. [본문으로]
이올린에 북마크하기(0) 이올린에 추천하기(0)