Effective Modern C++ 번역서 나왔습니다.

류광, 2015/09/22 15:11
Effective Modern C++ 번역서 나왔습니다.

Effecitve Modern C++ 번역서가 9월 초 출간되었습니다.

이펙티드 모던 C++: C++11과 C++14를 효과적으로 사용하는 42가지 방법

이 책을 굳이 따로 소개할 필요는 없겠지요? 대신 역주의 일부를 인용합니다:

[인용]

이 책을 포함한 Effective C++ 시리즈를 아주 잘 나타내는 말로 ‘최고의 두 번째 책(the best second book)’이 있습니다. 이는 C++ 전반에 대한 기초를 닦을수 있는 좀 더 두꺼운 교과서(‘첫 번째 책’)를 읽은 후에 볼 만한 책 중에는 이 시리즈가 최고라는 뜻입니다. 첫 번째 책을 건너뛰고 이 시리즈부터 보기 시작하면 C++이 다소 비틀리고 괴팍한 언어라는 잘못된 인상을 받기 쉽습니다. 이 책의 경우에는 특히 C++11과 C++14에 전반적으로 익숙해질 필요가 있는데, 안타까운 것은 C++에 대한 ‘최고의 첫 번째 책’이라 할 수 있는 The C++ Programming Language 제4판(C++11에 맞게 상당 부분 개정된)의 번역서가 이 글을 쓰는 현재 아직 나오지 않았다는 점입니다. 아무쪼록, 웹에 있는 자료들이라도 최대한 모아서 미리 기초를 닦으시길 당부합니다. 웹 검색 시 ‘C++11’뿐만 아니라 ‘C++0x’도 검색할 필요가 있을 것입니다.

제 블로그에도 C++11 글들이 좀 있고, C++14와 C++17에 관한 글도 기회가 되는 대로 써보겠습니다.

top
TAG C++, 번역서
트랙백 0 : 의견 # + 0

generic과 general, 그리고 일반적 프로그래밍

류광, 2015/09/12 14:16
Generic Programming을 일반적 프로그래밍이라고 옮기는 것에 관해

예전부터 제 번역서에서 Generic Programming(이하 GP)을 ‘일반적 프로그래밍’으로 옮기고 있는데요. 언젠가 “‘일반적’은 general을 우리말로 옮긴 것인데 general과 generic은 다른 것이므로 generic을 ‘일반적’으로 옮기는 것은 틀렸다”라는 주장을 어떤 블로그(지금은 없어진)에서 본 적이 있습니다. 이런 주장은 영어와 한국어 단어가 항상 일대일로 대응되지는 않는다는 아주 간단한 반박으로도 설득력을 잃습니다. 오히려, general을 천편일률적으로 ‘일반적’으로 옮기는 것이 더 문제일 것입니다. 종합, 보편, 범용, 포괄 등등 문맥에 따라 적합한 말이 많이 있습니다

사실, 일반적 프로그래밍이라는 번역이 “틀렸다”라는 다양한 주장들은 모두 그냥 “generic이라는 표제어에 대해 ‘일반적’이라는 용어를 제시하는 영한사전들이 여럿 있다” 정도로 반박이 가능합니다. 적어도 틀린 것은 아니라는 것이지요. 그러나 좀 더 생산적인 논의를 위해서는 ‘일반적’보다 더 나는 무언가가 있는가를 따져 보아야 할 것입니다.

‘일반’ 보다 더 나은 무언가로 ‘총칭’이라는 용어를 들기도 합니다. 저도 한 때 “총칭적”을 고민했지만, 당시는 너무 생소하다고 생각해서 사용하지 않았고 지금은 ‘일반적’보다 나을 것이 없다는 생각으로 사용하지 않습니다.

총칭이라는 단어를 사용하는 글로는 최흥배 님의 About STL : C++ STL 프로그래밍(1)이 있는데요. 중간의 “The cow is an animal.” 예문과 관련해서 저와 해석이 다른 부분이 있습니다. 네이버 사전에서 “The cow is an animal.”은 총칭 자체가 아니라 ‘총칭 단수’에 대한 예입니다. 즉, 제가 보기에 그 예문이 나타내고자 하는 것은 소를 동물로 총칭하는 것이 아니라, 소 전체의 어떤 특성을 ‘그 소(the cow)’라는 단수로 총칭할 수 있다는 것입니다.

생각해보면, “소는 동물이다”라는 개념을 C++에서 표현하는 방법은 템플릿(GP의 필수 요소인) 외에도 여러 가지입니다.

Animal the_cow; // 클래스와 객체
class Cow: public Animal {...}; // 기반 클래스와 파생 클래스
typedef Animal<Mamal, Ruminatable> Cow; // 클래스 템플릿과 인스턴스
                                        //(Ruminatable은 ‘되새김 가능’)
using Cow = Animal<Mamal, Ruminatable>; // C++11 별칭 선언

단지 그 수준 또는 대상이 다를 뿐, 이들은 모두 일반/보편 대 특수/구체 관계를 나타냅니다. 템플릿과 그 인스턴스뿐만 아니라 보통의 클래스와 객체 역시 generic한 것과 그보다 specific한 것의 관계이고, 기반 클래스와 파생 클래스 역시 마찬가지입니다. 즉, 총칭은 (중의적으로)일반적입니다.

어쨌거나, GP의 핵심은 specific할 필요가 없는 것은 최대한 generalize(genericize?)한다는 것인데, 조금 말장난을 하자면 일반적으로 specific하지 않은 것을 나타내는 용어로는 ‘일반적’이 가장 일반적이 아닌가 합니다. 적어도 총칭보다는 일반적입니다. 이 글 도입부의 ‘주장’을 다시 꺼내자면, generic과 general의 차이를 강조하기보다는 유사성을 강조하는 것이 더 낫다고 반박할 수 있겠습니다.

전적으로 추측이지만, 애초에 GP라는 용어가, 일반성을 강조하는 프로그래밍 스타일을 가리켜 그냥 general programming이라고 부르려니 general이 말 그대로 너무 일반적이어서 그와 거의 같은 뜻의 generic이라는 용어로 대체한 것일 지도 모르겠습니다. 예를 들어 GPG 시리즈의 섹션 1은 항상 다른 좀 더 구체적인 섹션들(수학, 인공지능, 그래픽 등등)로 분류하기에는 적합하지 않은 일반적인 게임 프로그래밍 기법들을 담는데, 그 섹션의 제목이 ‘General Programming’입니다. 번역서들에서는 ‘프로그래밍 일반’이고요.

한 가지 흥미로운 것은 GP의 사실상의 창시자인 알렉스 스테파노프(STL의 설계자, 최초 구현자)가 몇 년 전 출간한 필생의 역작(아마도) Elements of Programing(폴 맥존스와 공저)에 species와 genus라는 용어가 쓰인다는 것인데요. 요즘은 모르겠지만 저는 생물 분류 체계를 ‘종속과목강문계’로 배웠는데, species와 genus가 바로 종과 속입니다. generic이 이 genus에서 나온 것이라면, 전에 어떤 번역서에서 GP를 ‘생성적 프로그래밍’이라고 옮긴 것이 나름 의미가 있겠습니다(아마도 템플릿으부터 좀 더 구체적인 코드가 생성된다는 점을 고려해서 생성적이라는 용어를 선택했을 가능성이 더 크겠지만요).[1]

그렇다고 GP를 번역할 때 생물학이나 생태학적 문맥을 중요하게 고려할 필요는 없어 보입니다. 즉, ‘속적’ 프로그래밍 같은 요어를 고려할 필요는 없겠습니다. 애초에 species와 genus 자체가 생물학에 한정된 용어가 아니고요. 그리고 아마도 species와 genus는 저 책을 쓰다 보니, 특히 몇 가지 공리들과 그로부터 논리적으로 연역된 정리들을 통해서 프로그래밍의 원리를 서술하려다 보니 도입된 게 아닌가 합니다. 즉, species와 genus는 단지 특수한(specific) 것과 일반적인(general, generic)것을 대비하기 위한 용어로 채용될 것일 뿐일 것입니다. 저 책 이전의 스테파노프의 논문이나 인터뷰 등에서는 species와 genus를 보지 못했습니다(제가 덜 찾아본 것일 수도 있으니 혹시 발견하면 제보 바랍니다!).

‘일반’이라는 단어를 살린다고 할 때, 곽용재 님이 제시하신 ‘일반화’ 프로그래밍도 고려 대상입니다. GP와 관련해서 generalize라는 말이 흔히 쓰인다는 점에서 그럴듯하긴 하지만, 일반화 형식이나 일반화 함수 등등‘프로그래밍’ 이외의 단어와 결합할 때 좀 어색한 면이 있습니다. 다른 단어와의 결합을 생각하면 관형사‘일반적’이 낫다고 봅니다. ‘~된’를 붙여서 관형사로 만든 ‘일반화된’도 생각해볼 수 있는데(일반화된 프로그래밍, 일반화된 함수, 일반화된 형식 등), 글자 수가 더 많은 것도 마음에 안 들지만 GP의 한 방향만 강조한다는 느낌이 들어서 꺼려집니다. int swap(int, int)double swap(double, double)에서 template<class T> T swap(T, T)로 가는 것뿐만 아니라 template<class T> T swap(T, T)에서 template<> void* swap(void*, void*)로 가는 것도 GP의 중요한 요소이니까요(비록 후자를 '특수화'라고 부르긴 하지만요).[2]

이런 고민으로 generic은 그냥 ‘일반적’으로 하는 것이 낫다는 것이 최종 결론입니다. 단, 일반적이 말 그대로 너무 일반적이다 보니, 적어도 검색 편의를 위해서라도 general과 generic의 번역을 구별할 필요는 있겠습니다. 그래서 저는 다음과 같은 원칙을 적용하고 있습니다.

  • general은 문맥에 맞게 종합적, 보편적, 범용적, 포괄적 등으로 다양하게 번역하되, ‘일반적’이 가장 적합한 경우에는 ‘일반적인’, ‘일반적으로’ 등으로 항상 조사를 붙인다
  • GP의 문맥에서 쓰이는 generic은 조사 없이 ‘일반적’으로 번역한다. 예: ‘일반적 프로그래밍’, ‘일반적 함수’, ‘일반적 형식’ 등등.

이런 원칙을 여러 번역서에서 큰 문제 없이 잘 적용해 왔는데, 아쉽게도 Effective Modern C++에서 예외가 발생했습니다. 관련 역주의 일부를 인용하자면:

[인용]

그러나 maximally generic을 옮긴 ‘최대한 일반적인’은 예외이다. 이처럼 generic 앞에 부사가 붙은 경우에는 ‘일반적’에 조사를 붙이지 않으면 좀 어색하기 때문이다.

이런 예외가 앞으로 더 나오지 않으리라는 보장은 없는데요. 이런 예외가 조사 유무를 통한 general과 generic의 구분에 얼마나 큰 타격이 될지는 모르겠습니다만 아직은 버틸만 합니다...


[1] 그러나 생성적 프로그래밍은 ‘Generative Programming’(이라는 용어가 실제로 있습니다)과 훨씰 더 강하게 결합합니다. Generative Programming는 문자 그대로 소스 코드를 자동으로 생성하는 데 중점을 둔 프로그래밍입니다.

[2] 한편, 일반화된 프로그래밍이라는 용어에 관해 “그렇다면 애초에 Generic Programming이 아니라 Generalized Programming이라고 불렀겠지요”라고 날카롭게 지적하신 분이 있었는데요. 이는 Oriented Programming의 번역에 대한 몇몇 제안이 사실은 한국어 용어 선택의 문제라기보다는 Oriented Programming라는 이름 자체에 대한 문제 제기이라는 점을 연상케 합니다.

top
트랙백 0 : 의견 # + 0

C++ RAII(Resource Acquisition Is Initialization)의 해석

류광, 2015/08/18 22:16
RAII라는 이름 자체에 대한 "꿈보다 해몽"

조만간 번역서가 출판될 Effective Modern C++ 어딘가에 다음과 같은 문구가 나옵니다:

[인용]

(RAII 자체는 “Resource Acquisition Is Initialization”을 뜻하지만, 사실 이 기법의 핵심은 초기화가 아니라 파괴이다.)

관련해서 기억나는, 10년도 더 된 논의가 하나 있습니다: GpgStudy 포럼 “클래스 생성시 ... ”

특히 조순현 님의 답글제 답글이 이번 블로그 글과 관련이 있는데요. 제 답글에 등장하는 http://tinyurl.com/4ogc8는 현재는 깨진 링크이고, 원래 의도한 해당 뉴스그룹 글은 이것입니다.

당시는 “RAII의 핵심은 초기화가 아니라 파괴”라는 관점에서 답글을 달았지만, 지금은 조순현 님(당시 닉은 ‘수렁’)의 “자동변수뿐만 아니라 자원 획득은 거의 모든 경우에 있어서 초기화(준비 완료)여야 한다고 생각합니다.”라는 의견을(곁들여서 C++의 예외에 대해서도) 좀 더 논의했다면 좋았겠다고 후회하고 있습니다.

한편, 그 논의와는 무관하게, 저는 전부터 RAII라는 용어의 유래가 궁금했습니다. ‘함흥차사’가 무슨 뜻인지가 아니라 그런 뜻에 왜 ‘함흥차사’라는 이름이 왜 붙었는지 궁금해하는 것과 비슷하게요. 겸사겸사 해서 지금까지 생각한 것들을 장황하게나마 써보겠습니다.

“Resource Acquisition Is Initialization”이라는 문장은 다음 두 가지로 해석할 수 있습니다.

  1. “자원 획득은 초기화이다”
  2. “자원 획득이 초기화이다”

토씨 하나만 다른 문장들이지만 의미는 사뭇 다릅니다. 1번은 “자원 획득은 무엇인가?”에 대한 답이고, 2번은 “무엇이 초기화인가?”에 대한 답입니다.

C++ 객체의 수명 주기를 참작할 때, 그리고 답의 ‘초기화’라는 단어를 생각할 때, “자원 획득은 무엇인가?”라는 질문에는 “자원 획득은 언제 일어나야 하는가?”라는 질문이 포함되어 있다고 생각할 수 있습니다. 비슷한 논리로, “무엇이 초기화인가?”라는 질문에는 “초기화 시점에서 주로 수행해야 할 작업은 무엇인가?”라는 질문이 포함되어 있겠고요.

그 두 질문의 답을 합친다면, “자원 획득은 초기화 시점에서 일어나야 하며, 초기화 시점에서 해야 할 중요한 작업은 자원 획득이다”가 되겠습니다. 그런데 이러한 답이 의미가 있으려면, 객체의 유효성(앞의 포럼 논의에서는 Testors 님이 여러 번 강조하신 ‘인스턴스의 무결성’)에 대한 다음과 같은 관점이 필요합니다.

  1. 생성이 완료된 객체는 유효한 객체이어야 한다. 즉, 유효하지 않은 객체가 생성되어서는 안 된다.
  2. 필요한 자원들을 획득하지 못한 객체는 유효한 객체가 아니다.

이러한 관점에서 “자원 획득은/이 초기화이다”는 모든 자원은 생성자 안에서 완전하게 획득해야 하며, 획득하지 못한 자원이 하나라도 있는 상태에서 생성자가 완료되어서는 안 된다는 뜻이라 할 수 있습니다. 그리고 대칭성에 의해, 파괴(소멸)되어서 더 이상 유효하지 않게 된 객체는 그 어떤 자원도 가지고 있지 않아야 합니다. 이로부터 흔히 통용되는 RAII의 뜻, 즉 “(예외가 발생해도 누수가 일어나지 않도록)소멸자에서 자원을 해제하는 기법”을 이끌어 낼 수 있고요.

물론 이는 “꿈보다 해몽”입니다. 사실 “Resource Acquisition Is Initialization”이라는 문구를 만든(The Design and Evolution of C++ 참고) 비야네 스트롭스트룹 본인은 RAII가 어떤 중심 개념을 대표하는 이름치고는 ‘clumsy’한(서투른, 재치 없는, 꼴사나운 등등) 이름이라고 말합니다(Bill Venners와의 인터뷰). 다른 인터뷰에서도 비슷한 말을 한 것으로 기억하며, 그렇다고 더 나은 이름을 제시한 적도 없는 것으로 알고 있습니다. 어쨌든, 비록 자원 획득이 초기화 시점에서 일어나지 않았다고 해도 소멸자에서 자원을 해제하는 기법은 여전히 유효하고 유용하다는 점에서[1], 그런 기법을 RAII라고 부르는 것은 그리 적합하지 않은 것은 사실입니다. 그래서 “scope guard” 같은 용어를 사용하는 경우도 있고요.

덧붙여 말하자면, 앞에서 말한 ‘관점’이 단지 RAII를 제대로 해석하는 데 필요한 것은 물론 아닙니다. 이런 관점은 거창하게 말하면 코드의 정확성 검증이나 보장에 큰 도움이 되고, 실용적으로 표현하자면 “제대로 사용하기는 쉽고 잘못 사용하기는 어려운” 클래스를 만드는 데에도 도움이 될 것입니다. 이 주제에 대해서도 언제 한 번 글을 써보겠습니다.

마지막으로 한 마디 더…. 언급한 포럼 논의에서는 예외와 오류 처리에 관한 논의를 자제해 달라고 했지만[2], 사실 RAII를 이야기하면서, 그리고 “생성이 완료된 객체는 유효한 객체이어야 하고 유효하지 않은 객체가 생성되어서는 안 된다”는 관점으로 객체를 고찰할 때 예외에 대한 이야기를 빼놓는 것은 예외 입장에서는 서운한 일일 것입니다. 이와 관련해서 comp.lang.c++.moderated에 Andrei Alexandrescu(Loki 라이브러리와 Modern C++ Design 저자)가 올린 질문 “Are throwing default constructors bad style, and if so, why?”에서 시작된 논의가 있는데, 곱씹어 볼만한(그리고 앞에서 언급한 GpgStudy 포럼 논의에서 다루지 못한) 부분들이 많이 있습니다. 앞의 ‘관점’에 대한 글을 쓰게 된다면(아마도), 예외에 대한 이야기도 당연히 포함될 것입니다.


[1] 물론 문자 그대로의 의미에서의 RAII가 지켜진다면 필요하지 않았을 추가 점검을 소멸자에서(그리고 어쩌면 생성 이후에 자원을 획득하는 여러 멤버 함수들에서도) 수행해야 하겠지만요.

[2] 아마도 당시 있었던 어떤 소모적인 논쟁 때문이었거나, 흔히 쓰이던 계통구조(트리) 스타일 게시판이 아닌 소위 ‘플랫(flat)’ 스타일의 게시판인 phpBB 시스템의 특성 때문이었을 것입니다.

top
트랙백 0 : 의견 # + 0

루아(Lua)의 사용자 정의 리터럴

류광, 2015/06/24 22:25
루아의 간결한 함수 호출 구문을 이용한 사용자 정의 리터럴 흉내내기

본문 열기

top
트랙백 0 : 의견 # + 0

Functional Programming in Scala 번역서 나왔습니다

류광, 2015/04/07 17:57
Functional Programming in Scala 번역서 "스칼라로 배우는 함수형 프로그래밍" 출간 소식

본문 열기

top
TAG 번역서
트랙백 0 : 의견 # + 0

◀ PREV : [1] : [2] : [3] : [4] : [5] : [6] : [7] : [8] : ... [58] : NEXT ▶