Software Development

C++ Local Class as Template Argument

이 글은 최철호 군의 local function object를 stl algorithm function들에 사용하지 못하는 이유에 대한 답변입니다.

한마디로 말하면, 로컬 클래스(local class)는 템플릿 인자로 사용될 수 없기 때문입니다.

local function object는 로컬 클래스이고, for_each는 functor (function object)의 타입을 템플릿 인자로 받는 템플릿 함수입니다. 함수 인자로부터 템플릿 인자가 deduce되기 때문에 템플릿 인자가 생략되어 일반 함수처럼 보이는 것 뿐이죠.

템플릿 인자는 linkage를 필요로 합니다. 특정 템플릿 인자에 대한 템플릿의 인스턴스는 서로 다른 컴파일 유닛에서 사용되므로 특정 컴파일 유닛에 속한다고 할 수가 없을거라는 걸 생각하면 당연히 그럴테죠. (컴파일 과정에서 생성된 템플릿 인스턴스는 다른 소스 파일에 존재한다고 생각하시면 편합니다.)

한편, 로컬 클래스는 linkage가 없습니다. (C++ Standard의 [basic.link] 부분을 참조하세요.) 정확한 이유는 모르겠으나, linkage를 가지게 되는 순간부터 문법과 구현 모두 복잡해지기 시작할 것임을 쉽게 상상할 수 있습니다.

gcc 4.1를 사용한 컴파일에서는 ‘no matching function for call to …’와 같은 오류를 발생합니다. 이러한 오류가 발생한 이유는 이해할 수 있으나, 약간이라도 가능성이 있는 경우들을 잘 보여주지 않는 불친절한 gcc 컴파일 오류의 사례를 보여주고 있네요.

로컬 클래스의 인스턴스를 로컬 스코프에서 사용한 이런 자연스러운 경우를 표현하지 못하는 것은 좀 아쉽습니다. C++의 algorithm과 functional은 C++에서 빼놓을 수 없는 요소일 뿐만 아니라 그 사용이 상당히 권장되고 있습니다. 이 때 사용되는 functor들을 일일이 namespace 스코프에 정의해서 namespace에 난립하게 하는 것도 그다지 바람직하지 않은 것 같구요. 로컬 클래스는 오히려 functor와 같은 크기도 작고 용도도 한정적인 경우에 가장 유용하겠죠. 그래서인지 Anthony Williams에 의해 로컬 클래스에 linkage를 부여하자는 제안 (Making Local Classes more Useful)도 나와있네요.

C++ Local Class as Template Argument 더 읽기"

Unicode Support in Programming Languages, Part 1

유니코드 지원

프로그래밍 언어에서 유니코드 (Unicode) 지원은 크게 두가지로 나누어볼 수 있다. 바로 소스 코드(source code)에서의 유니코드 지원과 문자열(string)에서의 유니코드 지원이다. 소스 코드에서의 유니코드 지원은 문자열 리터럴과 클래스, 변수 이름과 같은 심볼들의 이름에서 유니코드 문자를 표현할 수 있음을 의미한다. 문자열에서의 유니코드 지원은 소스 코드에서의 유니코드 지원을 포함한다. 문자열에서의 유니코드 지원은 문자열 변수, 리터럴이 유니코드 문자를 표현할 수 있는가 뿐만 아니라, 문자열과 문자를 다루는 방법, 문자열과 바이너리의 구분, 여러가지 다른 인코딩으로의 변환 등을 포함한다.

이 글에서는 ‘문자열에서의 유니코드 지원’을 중심으로 얘기를 해보자.

C 문자열

C/C++, PHP, Python (< 2.0), Ruby와 같은 언어들에서는 다음과 같은 문자열을 가지고 있다.

  • 문자열은 외부에서 주어진 인코딩으로 인코딩된 바이너리 형태며, 문자열 자체만으로 어떤 인코딩인지는 구분할 수 없는 방식.
  • 문자열과 문자를 다루는 함수는 시스템 로케일 또는 컴파일러에게 주어진 설정에 따른 인코딩을 가정함.
  • 이를 다른 인코딩의 문자열로 변환하는 방법을 문자열에 대한 언어적인 지원이나 라이브러리로 제공.

이러한 문자열 방식의 문제점은 그동안 수많은 프로그래머들을 괴롭혀온 것이라고 볼 수 있다.

  • 유니코드 문자를 사용할 수 없다. 동시에 여러 문자집합을 사용하기 어렵다.
  • 특정 문자집합 인코딩(charset encoding)을 가정하고 프로그래밍하는 경우가 잦아서, I18N이 매우 어렵다.

C와 함께하는 프로그래밍 역사에는 ‘a byte is a character’라는 생각이 깃들여있다. 하나의 문자가 실제로 ‘문자’에 해당하는 문자집합 인코딩을 가진 영어 또는 서유럽 언어에서는 크게 문제가 안되지만, 이른바 멀티바이트(multibyte) 문자열을 사용하는 한국, 중국, 일본과 같은 국가에서는 인코딩 지옥(encoding hell)이라고 부를만큼 사용자나 프로그래머들이 어려움을 겪어왔다고 볼 수 있다.

Java 문자열

Java는 유니코드 지원과 함께 탄생했다. 국제 표준에 해당하는 유니코드에 대한 개념이 그리 보편화되지 않았던 1996년에 Unicode 1.1을 반영하는 Java 1.0이 발표되었다.

  • 타입을 사용한 문자열과 바이너리의 구분: 문자는 char형, 바이트는 byte형을 이용하고, 문자열과 바이너리는 각각의 배열로 표현한다. 문자와 이를 인코딩한 형태를 타입을 이용해 구분했다는 것은 당시로서는 획기적인 것이었다.
  • 유니코드 문자집합 (UCS-2)의 지원: 내부적으로 2byte로 표현되는 char형은 유니코드에서 정의한 UCS-2 문자집합의 코드포인트(codepoint)에 해당했다. Java 5에서 Unicode 4.0을 반영하면서 char형은 UTF-16의 코드유닛(codeunit)을 나타내게 되었다.
  • 문자열과 문자를 다루는 함수는 UTF-16 이외에 더이상 인코딩을 신경쓸 필요가 없게 되었음. (UCS-2에 속하는 문자만 사용한다면 아예 신경 쓸 필요가 없음.)
  • 문자열을 특정 인코딩으로 인코딩하는 방법을 언어적인 지원과 라이브러리로 제공.

Java 초기에는 유니코드 지원으로 인한 성능 문제에 대한 논란이 많았던 걸로 기억한다. 지금 돌이켜보면, 유니코드 문자열의 도입으로 인한 성능 하락은 그리 큰 문제가 아닌 듯하다.

Java의 유니코드 지원 방식은 다른 언어들의 모범이 될만큼 깔끔하고 성공적으로 적용되었다고 생각한다. 개인적으로 가장 맘에 드는 Java의 특징 중 하나가 바로 유니코드 지원이다.

To Be Continued…

다음에는 C/C++의 wchar_t, Perl의 유니코드 지원, Python 2.0의 유니코드 문자열, Python 3000과 PHP 6의 유니코드 문자열, Ruby의 유니코드 지원에 대해서 다루어보겠다.

Unicode Support in Programming Languages, Part 1 더 읽기"

Ease-of-use in Databases

Jim Starkey, a Senior Software Architect for MySQL, said,

what a bother mapping back and forth between fixed-length declaration and variable-length storage! If the Standard would let us, the user could just say, "It’s a number—Just deal with it." Modern languages and frameworks have strings without size. Why not databases?

So that’s how I prefer to deal with ease-of-use versus performance: Make it easy for the user to let the software do the smart thing.

(…)

We’ll change the data model, the data types, the application topology, and the network interface, but they’ll still be relational databases.

Ease-of-use in Databases 더 읽기"

Prefer Broad Design Skills over Platform Knowledge

Martin Fowler, Prefer Design Skills

소프트웨어 개발자를 고용할 때, 플랫폼 지식(platform knowledge) 보다 여러 영역에 걸친 디자인 능력(broad design skill)을 중요하게 보자는 얘기다. 디자인 능력을 갖춘 사람이 플랫폼 지식을 가지기 쉽지만 그 역은 쉽지도 않고 확실하지도 않기 때문이라고 얘기한다.

물론 그가 플랫폼 지식의 중요성을 간과하는 것은 아니다. 여기서 그가 가정하고 있는 것은 바로 배우려고 하는 욕구(desire to learn)배우는 능력(learning skill)이다.

Prefer Broad Design Skills over Platform Knowledge 더 읽기"

Egoless Programming

Egoless Programming이란 개념은 얼마전에 한국어로도 번역된 Gerald Weinberg의 The Psychology of Computer Programming에서 등장한 개념이다.

간단하게 얘기하면, 프로그래머라면 누구나 자신의 프로그램에 대한 애착을 가지고 있는데, 이 때문에 프로그램에 대한 비판을 받아들이지 못하는 것은 피해야한다는 것이다. 사실 프로그램 뿐만 아니라 지식 노동자의 모든 지적 작업의 결과물에는 이러한 경향이 있을 것이라고 생각한다.

팀 환경에서 프로그램에 대한 애착은 나쁜 영향을 미치게 된다. 코드가 아닌 사람을 향하는 비판 때문에 감정을 상하게 되고, 감정이 상할 까봐 비판을 하지 않게 되는 현상이 일어난다. 다른 사람의 잘못을 지적하기가 또는 받기가 두려워서 서로 협력하는 것에 미온적이거나 미루게 된다. 아예 협력하지 않기 위해서 했던 일을 새로 하기도 한다. 코드 리뷰나 회고 같은 활동도 정상적으로 할 수 없다.

이러한 문제는 Ego가 강한 한 개인의 문제라기보다는, 팀 문화의 문제라고 생각한다. 어떤 잘못이 있을 때 원인과 해결 방법에 집중해서 논의가 일어나기 보다는 그 사람의 성격 탓으로 돌리는 행위나 감정을 자극하는 언행들이 팀원 하나하나로부터 조금씩 보이면서 팀의 문화로 형성되는 경향이 있는 듯하다.

이를 방지하기 위해서는 팀 형성 초기 단계부터 세심하게 신경을 쓸 필요가 있다. 의식적으로 팀원의 언행을 살피고 Egoless Programming에 반하는 언행이 보일 경우, 그것을 바람직한 방향으로 수정해주는 것이 필요하다. 누군가가 잘못을 했을 때, 우리는 그에게 잘못을 추궁하는 것이 아니라 더 좋은 방법을 찾고 있다고 얘기해주어야 한다. 애초에 굳이 필요하지않다면 누구의 잘못인가를 공개적으로 찾아보는 행위도 나쁘다. 문제의 내용이 제대로 밝혀졌다면 누구의 실수 였는지는 고의적으로 모호하게 하는 방법도 생각해 볼 만하다. Egoless Programming에 익숙해질 수 있는 코드 리뷰나 회고 같은 활동도 유익한 것 같다. 실제로 코드 리뷰를 해보기 전엔 모두들 그것이 서로에게 감정적인 상처를 줄 것이라고 생각하지만, 적절하게 진행하기만 하다면, 그것이 자연스러울 수 있고 팀원들간의 신뢰를 높여줄 수 있는 방법임을 깨달을 수 있다.

신입 개발자일수록 팀이 어떻게 동작하는 것인지를 잘 이해하지 못하고 있으며 Ego도 강한 편이다. 이러한 점을 말로 지적하는 것도 필요하긴 하겠지만, 경험이 부족한 상태에서 주어진 규칙이란 것은 교장 선생님의 훈화 같은 것이나 다름없다. 오히려 권위가 있는 직책의 개발자나 경험이 많은 개발자가 모범을 보여주는 것이 좋은 것 같다. 그러한 것이 바로 잘 형성된 Egoless한 팀 문화다.

Ten Commandments of Egoless Programming이란 글은 Egoless Programming을 위한 좋은 가이드라인이니 읽어보기 바란다.

Egoless Programming 더 읽기"

Holding a Program in One's Head

다음은 Paul Graham의 글, Holding a Program in One’s Head의 요약입니다.

프로그래밍을 잘하려면, 프로그램 전체를 머리 속에 담아두어야 한다. 이를 위해서는 다음과 같은 규칙이 도움이 된다.

  1. Avoid distractions
  2. Work in long streches
  3. Use succinct languages
  4. Keep rewriting your program
  5. Write rereadable code
  6. Work in small groups
  7. Don’t have multiple people editing the same piece of code
  8. Start small

이 항목들을 지키는 것은 일반적인 프로그래머로서는 쉽지 않다. 신기하게도 이러한 항목들에 맞아떨어지는 것은 비공식적인 개인 프로젝트에서 우연히 이루어진다. 반대로 공식 프로젝트에서는 위의 항목 모두를 만족시키지 못하는 경우도 있다.

이는 개인을 부품으로 보는 것이 미덕인 조직의 특성 자체에 기인한다. 프로그램은 바로 생각인데, 생각(idea)는 분업할 수 있는 것이 아니다. 조직이 프로그래머가 갈구하는 것을 막는다 하더라도 좋은 프로그래머들은 많은 것을 해낼 수 있다. 하지만 그러기 위해서는 종종 조직에 대해 반항하는 행위를 필요로 한다.

좋은 프로그래머들이 혼자서 일하기를 좋아하는 것은 그들이 비우호적이어서가 아니다. 그 이유는 바로 프로그램을 머리 속에 담아두어야 하기 때문이다. 이 점을 이해하는 것은 어떤 조직에도 도움이 되겠지만, 큰 회사들은 프로그래머 개개인이 커다란 일을 하게 놔두지 않기 때문에, 그들의 경쟁자, 스타트업이 비집고 공격할 수 있는 구석이 된다. 하나의 뛰어난 두뇌 (one big brain)에서 풀어야 할 문제를 찾아라.

Holding a Program in One's Head 더 읽기"

Defining Success

Software Engineering 수업에서 Software Crisis를 언급하면서 소프트웨어 프로젝트의 성공율은 극히 낮다는 얘기를 한번쯤은 들어보았을 것이다. 그렇다면 소프트웨어는 언제 성공했다고 얘기할 수 있을까? DDJ 2007년 10월호의 ‘Defining Success‘라는 글은 소프트웨어 IT 종사자들의 프로젝트의 성공에 관한 관념을 조사한 결과를 보여준다.

조사 중 하나는

  • Shipping when the system is ready is more important than shipping on schedule
  • Providing the best ROI is more important than delivering underbudget
  • Delivering high quality is more important than delivering on time and on budget

라는 설문이었는데, 평균적으로 전자의 대답이 다수를 차지한다.

절대적인 수치보다도 재미있는 사실은, 관리자나 주주들에 비해 소프트웨어 프로젝트의 최전방에 있는 프로젝트 관리자는 전자를 택한 비율이 현저히 낮다는 점이다. 어째서 이런 역설적인 결과가 나올까? 이 글에서는, 그 이유가 조직의 보상 체계에 있을지도 모르겠지만, 그게 사실이라면 왜 관리자의 결과와 align되어있지않을까 하는 의문을 던진다.

일반적인 IT 조직 구조 특성상 ROI와 같은 상위 목표는 상급 매니저가 고민하고 미리 결정하기 마련이고, 프로젝트 매니저들에게는 하위 목표인 스케줄과 예산만 주어질 뿐이기 때문에 이러한 결과가 나온 것 같다. 하지만, 조직 구조상의 문제에도 불구하고 주어진 목표를 그대로 수용하는 프로젝트 관리자보다 ROI, 품질과 스케줄, 예산 사이의 밸런스를 고민하는 프로젝트 관리자가 훌륭한 관리자임은 말할 것도 없다.

Defining Success 더 읽기"

Sun's acquisition of MySQL AB

어젯밤에 Sun의 MySQL AB 인수와 Oracle의 BEA 인수라는 소식을 들었다.

Sun과 Oracle은 더이상 언급할 필요도 없는 대기업인데다, MySQL과 BEA 모두 각자의 제품 시장에서는 잘 나가는 플레이어들이라 놀라울 수 밖에 없는 소식이다. 인수가는 Sun의 경우 옵션까지 포함해서 10억 달러, Oracle의 경우엔 85억 달러다.

Sun의 MySQL 인수합병에 대해서 약간 더 얘기해보면, 평소에 구독하던 MySQL 관련 블로그들에서 이 건을 보는 시각은 대체로 비슷하다. 바로 Sun이 그동안 일관되게 보여준 Open Source 지향 정책과 MySQL의 시장성이 시너지를 보여줄 것이라는 것이다.

  • Sun은 서버 시장의 플레이어로서 MySQL을 Solaris 플랫폼에 최적화함으로써 이득을 얻을 것이고,
  • MySQL AB는 MySQL 6 버전이 의미하는 엔터프라이즈급 데이터베이스 시장 진입을 앞두고 충분한 경제력과 소프트웨어 개발 인프라의 측면에서 도움을 얻을 수 있을 것이다.
  • 물론 대기업인 Sun의 관료적인 분위기나 .NET 플랫폼과의 경쟁으로 인해 MySQL에 나쁜 영향을 끼치지 않을까하는 우려도 존재한다.

이 인수 합병건의 평가는 결국 Solaris-MySQL 제품이 얼마나 시장에서 경쟁 우위를 차지할 수 있느냐로 가름이 날 것이다. 엔터프라이즈급 서버 시장은 대체로 소프트웨어에 많이 의존하고 있고, 특히 데이터베이스 서버들도 그러하다. 다시 말해, 하드웨어만 팔거나 소프트웨어만 팔지는 않는다는 것이다. 이러한 면에서 Solaris 플랫폼에 MySQL이 얹혀 엔터프라이즈급 데이터베이스 서버로 판매되는 날도 점쳐볼 수 있을 것이다.

역시 흥미로운 부분은 Oracle과의 경쟁이다. Oracle은 명실상부한 데이터베이스 시장의 탑 플레이어지만 2위인 Microsoft SQL Server의 추격과 나름대로 선전하고 있는 MySQL의 추격 모두 무시할 수는 없는 노릇이다. 얼마전에는 InnoDB 엔진의 기반이라고 할 수 있는 InnoBase를 인수함으로써 MySQL이 가지고 있는 시장에도 관심이 있다는 사실을 내비쳤다. 이러한 사실만 가지고 아직 어떤 예측이 나오기는 힘들지만 이제서야 규모가 비슷해진(?) 데이터베이스 벤더들의 전쟁은 아무튼 흥미진진할 것 같다.

한편, MySQL은 세계적으로 널리 쓰이는 데이터베이스 제품이지만, 어느 정도 규모가 있는 데이터 플랫폼으로서는 아직 부족한 점이 많다. 분산에 대한 해결책으로 Replication과 Clustering이 존재하지만, 아직 걸음마 단계라고 볼 수 밖에 없고, DRDB나 LVM, InnoDB Hot Backup, MySQL Proxy 같은 외부 기술에 의존하는 경우도 많다. 이러한 솔루션들이 성숙하려면 아직 시간이 필요하고, Sun의 지원하에서 아마도 좀 더 쉽게 이루어질 수 있을 것이다.

MySQL 사용자로서 앞으로 MySQL의 발전에 거는 기대는 크다. Sun과 MySQL의 인수합병이 좀 더 나은 세상을 만드는데 도움이 되었으면 좋겠다.

Sun's acquisition of MySQL AB 더 읽기"