조엘 온 소프트웨어

저자
조엘 스폴스키 지음
출판사
에이콘출판 | 2005-04-15 출간
카테고리
컴퓨터/IT
책소개
2005년 15회 JOLT상 수상작! 아마존 선정 컴퓨터 인터넷...
가격비교


Aㅏ......

드디어 다 읽은 이 책 ㅠ_ㅠ...

날 너무 힘들게 했다 orz 


고작 책 하나 읽는데 무려 4주 이상 걸린 듯 싶다.

읽고 싶은 책으로 시작해서 읽어야만 하는 책으로 끝나버렸다. 

- 억지로 꾸역꾸역 읽은 듯한 느낌이라 - 지금 리뷰를 쓰는 이 시점에도 

뭔가 찜찜하고 반성해야만 할 것 같은 기분이다.



그래서 보통 같으면 목차를 하나씩 훑으면서 자세히 리뷰를 썼지만

이번에는 기억에 남는 일부 장에 대해서만 리뷰하겠다. 

(이 책은 제대로 못 읽었다는 느낌이 강해서 차후 다시 읽을 책 리스트에 올랐다 OTL)


→ 근데 막상 책을 다시 훑으면서 쓰다보면, 나름 자세히 쓰게 되더라.




< 1부 > 비트와 바이트 : 프로그래밍 실전



1장. 언어 선택


- 순수 C :  빠른 속력이 필요할 때


- MFC, C++ : 배포판 크기를 윈도우용으로 최소화 해야 한다면 정적 링크 언어를 선택


- JAVA : 맥, 윈도우, 리눅스에서 돌아갈 GUI 가 필요할 때 (GUI 가 완벽하지는 못하겠지만 실행은 되니까)


- Visual Basic : 작업 시간이 충분하지는 않지만 멋지게 보이는 GUI 를 만들어야 할 때

(하지만 배포판 크기가 커지는 데다가 윈도우에 묶여야만 한다는 단점이 있음)


- Perl : 속력에 무관하며 어떤 유닉스 기계에도 돌아가는 명령행 도구가 필요할 때


- JavaScript : 웹 브라우저 내부에서 동작해야 한다면 피할 수 없는 녀석


- SQL 내장 프로시저 부문 : 몇몇 회사에서 제공하는 독점적인 SQL 파생 버전을 이용해야만 함


=> 05년도 책이라 이보다 더 나은, 상황에 따라 더 적절한 언어들이 생겼을 수도 있겠지만

그래도 참고할 만한 내용이라 남겨본다. 요새 VB 를 쓰는 곳이 있나 싶기도 하고...

'VB 대신에 WPF 를 쓰지 않나?' 라는 생각이 든다. 잘은 모르겠다.




2장. 기본으로 돌아가기


- 소프트웨어 개발에 있어 최하위단 에서 벌어지는 단순한 동작 원리에 대해 논한다.

이 장의 내용은 책에서 완전 초반에 다루는 내용인데다 내가 이 책을 읽는데 4주가 걸렸음에도

블로그에 꼭 남기고 싶다는 생각을 한번도 잊은 적이 없다.



- C언어에서 문자열이 동작하는 방법에 대해...

void strcat(char* dest, char* src)
{
    while(*dest) dest++;        // NULL 문자열을 찾아간다
    while(*dest++ = *src++);    // dest 뒤에 src 글자를 하나씩 붙여나간다
}

눈치챘겠지만 이 코드에는 문제가 있다.

어떤 문자열에 여러 개의 문자열을 이어 붙이기 위해 이 함수를 여러 번 호출한다면...

NULL 을 찾기위해 1번째 while 루프를 미친듯이 돌려야 한다. (러시안 페인트공 알고리즘)


이를 해결하는 건 간단하다.

char* strcat(char* dest, char* src)
{
    while(*dest) dest++;        // NULL 문자열을 찾아간다
    while(*dest++ = *src++);    // dest 뒤에 src 글자를 하나씩 붙여나간다
    return --dest;    // 마지막 문자열의 위치를 반환, 이유는 첫번째 while 문 참고
}

이렇게 하면 O(n²) 의 복잡도를 O(n) 으로 줄일 수 있다.

너무 당연한 거 아니냐고 생각할 수도 있지만 글쎄...

그래도 중요하다고는 생각하니 남기고 싶었다. 기본이니까.



- malloc 은 어떻게 동작할까?

malloc 의 본질은 사용 가능한 메모리 블록을 Linked List 로 길게 연결한 Free Chain(자유 체인) 이다.


malloc 은 Linked List를 따라가며, 요청받은 메모리 양보다 큰 블록을 찾는다.

이렇게 찾은 블록을 2개로 쪼개서 하나는 호출한 사용자에게 반환하며, 

쪼개고 난 다음에 남아있는 블록은 다시 Linked List에 넣어둔다.


free를 호출할 때, free 는 해제한 메모리를 Free Chain에 추가한다.

결국 Free Chain 은 자그마한 조각으로 잘게 쪼개지므로, 

큰 메모리를 할당 받기 원할 때 원하는 크기를 충족하는 조각이 없을 수도 있다.

이럴 경우 malloc이 Time out을 선언한 다음에 Free Chain 주위를 샅샅이 훑어 조각을 정렬하고,

인접한 작은 자유 블록을 더 큰 블록으로 결합한다.


결국... malloc 의 성능이 결코 아주 빠르다고 볼 수 없다. (malloc은 항상 Free Chain을 돌아다님)

정리하는 과정에서 종종 예측할 수 없을 정도로 너무 느려질 수 있다는 사실을 알게 된다.


덧붙여 말하자면, 이런 현상은 Garbage Collection을 지원하는 시스템과 동일한 성능 특성이며, 

시스템 성능 저하 원인이 Garbage Collection 이라는 주장이 전적으로 옳지만은 않는 결론에 도달하게 된다. 



- 똑똑한 프로그래머는 항상 2배수로(4, 8, 16...) 메모리 블록을 할당하는 방법으로

잠재적인 혼란을 최소화 한다. 이렇게 말하면 상당히 큰 공간을 낭비하는 듯이 보일 지는 몰라도

항상 50% 이하로 기억공간을 소비한다는 사실을 확인할 수 있다고 한다.

=> 솔직히 이부분은 이해가 잘 안 된다ㅡㅡ........orz



- JAVA 에서 얼핏 알고 있었던 이야기지만...

String 클래스와 String Builder 클래스의 차이점을 따져 2가지 중에서 무엇을 사용할 지

생각해야 할 필요가 있다. 차이점은 스스로 찾아보자. 나도 어쩌다 누군가의 블로그에서

차이점을 알게 됐는데, 꽤 중요한 내용이라고 생각했지만 따로 정리를 안 했다. 차후 포스팅 하겠다.




3장. 조엘 테스트 : 더 나은 코드를 위한 12단계


1. 소스코드 관리 시스템을 사용하고 있습니까?

2. 한 번에 빌드를 만들어 낼 수 있습니까?

3. 일일 빌드를 하고 있습니까?

4. 버그 추적시스템을 운영하고 있습니까?

5. 코드를 새로 작성하기 전에 버그를 수정합니까?

6. 일정을 업데이트하고 있습니까?

7. 명세서를 작성하고 있습니까?

8. 조용한 작업 환경에서 일하고 있습니까?

9. 경제적인 범위 내에서 최고 성능의 도구를 사용하고 있습니까?

10. 테스터를 별도로 두고 있습니까?

11. 프로그래머 채용 인터뷰 때 코딩 테스트를 합니까?

12. 무작위 사용편의성 테스트를 수행하고 있습니까?


개당 1점씩, 10점 이하는 심각한 문제가 있다고 한다.

이 테스트에 대해서는 난 노코멘트 하겠다. 잘 모르겠다.




4장. 개발자가 꼭 알아두어야 할 유니코드와 문자 집합에 대한 고찰


ASCII 코드 : 32 ~ 127 사이의 숫자를 이용해 영문 표현이 가능. (32 는 공백(space))

7비트로 글자를 저장할 수 있다.


하지만 대다수의 컴퓨터가 8비트인 바이트 단위를 쓰기 때문에 ASCII 에서는 1비트가 남게된다.

즉, 128~255 사이에 위치한 코드를 마음대로 요리할 수 있다는 이야기이다.


그래서 이 사이에 어떤 값을 넣느냐에 대해서 많은 사람들이 동시에 동상이몽을 하게 된다.

IBM PC가 고안한 OEM 문자집합(유럽형 언어를 위한)를 시작으로 

온갖 OEM 문자 집합 형식이 생겨나면서 각 언어권 별로 용도에 맞게 128 글자를 정의했다.


예를 들어 A 나라에서는 resume 으로 보이는 글자가 B 나라에서는 rλsumλ 이런 식으로

보일 수 있다는 이야기이다.


이런 상황 속에 ANSI 표준 위원회에서는 ANSI 표준을 만들어 이 난투극를 끝냈다.

하지만 여전히 지역에 따라 128 이상 문자를 다루는 여러 방법이 존재했고 

이렇게 각기 다른 시스템을 '코드 페이지'라고 부른다.


그런데 여기서 생각해봐야할 건 아시아권 코드 페이지 이다. 

아시아 문자집합은 8비트로 표현하기에는 부족하다는 점이 사람을 골 때리게 한다.


그래서 DBCS(Doublc Bytes Character Set) 이라 하는 2바이트 문자 집합 시스템으로 해결하게 된다.

몇몇 글자는 1바이트로, 다른 글자는 2바이트에 저장하는 방식인데 짜증나는 부분이

문자열을 따라 쉽게 앞으로 나갈 수는 있어도 뒤로 돌아오기에는 무척 번거롭다는 점이다.


문자열에서 왔다갔다 하기 위해 s++, s-- 만으로는 안 된다는 점인데 그래서 윈도우에서는

AnsiNext, AnsiPrev 같은 함수를 쓰도록 독려했대나 뭐래나.



결국 8비트로는 안 되겠다 싶어 나온 게 사랑스러운 Unicode.

많은 사람들이 유니코드가 16 비트(2바이트)로 표현되기 때문에 

65536 개의 문자만을 사용할 수 있다고 생각한다는데(나도 그랬고), 

사실 이미 코드 숫자가 65536 를 넘었다고 한다.

모든 유니코드 글자는 실제로 2바이트로 압축할 수 조차 없다고 한다. (싱기방기ㅇㅅㅇ)


Unicode 는 실제로 글자를 다루는 일종의 철학이라고 한다. 각 글자에 존재하는 관념적인 철자마다

고유 번호를 붙여놓았고 'U+0645' 식으로 표현한다고 한다. (U+는 유니코드, 숫자는 16진)


저런 식으로 표현한 것을 '코드 포인트' 라고 한다.


여기서 머리 아프게 '인코딩' 이야기가 나온다.

예를 들어서 'Hello' 를 유니코드로 표현해보겠다.


U+0048    U+0065    U+006C    U+006C    U+006F


이 코드 포인트 숫자를 각각 2 바이트로 저장하면, (Big Endian)


00 48     00 65     00 6C     00 6C     00 6F


여기서 다른 표현법이 있다고 하면, (Little Endian)


48 00    65 00    6C 00    6C 00    00 6F


그지같게도(?) 글자 표현법이 Big Endian, Little Endian 으로 나뉘게 되어

유니코드 저장 방식이 2가지로 나뉘어 버리게 된다. 


따라서 이를 구분하기 위해 유니코드 문자열 시작 부분에 

FE FF 를 저장하는 관례가 생기게 된다. (UTF-16/Little Endian 의 경우)

이를 유니코드 바이트 순서 표시라고 부르며, 상위와 하위 바이트 순서를 바꿀 경우 FF FE로 보이게 된다.


아무튼 유니코드 인코딩 초기 방식이 이따구여서(?) 

미국 국적 프로그래머 사이에서 이야기가 상당히 많았던 것 같았다.

일반 영문 텍스트의 경우 U+00FF 상위에 존재하는 코드 포인트를 거의 사용하지 않기 때문이래나 뭐래나.

나는 아시아권이니 저 인간들이 느끼는 감정따위 이해할 수 있을리가.


하지만 이 때 'UTF-8' 이 등장하게 된다.

유니코드 코드 포인트를 따르는 문자열을 저장하기 위한 또 다른 시스템으로,

8 bit 인 1 바이트를 사용해 매직 U+넘버를 기억 공간에 저장한다.


0~127 사이에 존재하는 모든 코드 포인트를 단일 바이트로 저장하고,

128 이상인 코드 포인트만 2, 3 바이트에서 시작해 최대 6바이트까지 확장해서 저장한다.


이런 방식을 적용할 경우 모든 어떤 코드 포인트도 올바르게 저장할 수 있다는 특성을 얻게 된다.



조엘님이 이 장에서 가장 강조하는 것은

"일반 텍스트 라는 개념은 존재하지 않는다."

인코딩 방식을 모르는 문자열은 아무 의미가 없기때문에

메모리, 파일 또는 e-mail 내부에 문자열이 있으면 이 문자열 인코딩이 무엇인지 알아야만 하며, 

그렇지 않으면 그 문자열을 해석할 수 없어 사용자에게 올바르게 보여줄 수 없다는 것이다.



문자 집합에 대한 역사적인 관점으로 쭉 훑어 보았는데~~

평소에 이와 관련된 에피소드가 있다면..

DB에서 데이터 저장하다가 인코딩 때문에 빡쳤던 경험과 기타 웹 개발 경험,

최근에는 바이너리 파일 까보다가 Little Endian 표기법으로 약간의 삽질을 했던 경험 정도?


꽤나 심오한 세계인 것 같기도 하고 아무튼 어렵다 ㅡㅡ;; 

조엘님은 결코 어렵지 않다고 하지만 전 어렵네요 ㅇㅇ..orz


범상용화적인 소프트웨어를 개발하려는 분, 혹은 하시는 분들은 반드시 알아야 할 내용이 아닌가 싶다. 

물론 나도 이해하려고 이 장을 몇 번이나 뒤적거렸다. 언젠간 다시 찾아보게 될 내용이라 생각된다.


조금 찜찜한 게 있다면 내가 이렇게 막 장황하게 적었는데도

잘 이해가 안 되는 것 같다 ㅋㅋㅋㅋ 으앙 모르겠다




15장. 쏘면서 움직여라 


요즘 신입의 자세로 열심히 노력하면서도, ""잘"" 하는 사람으로 거듭나고자 

스스로를 궁지에 모는 행동을 많이 하는 것 같아 내심 스트레스가 많이 쌓여서 우울했었다.

(사실 지금도 약간 그런 상태지만)


그런데 이 장을 읽으면서 조금이나마 위안을 얻을 수 있었다.


첫 줄부터 '저는 가끔 일이 전혀 손에 잡히지 않을 때가 있습니다' 라고 적혀있다.

업무효율이 떨어지는 기간이 하루, 이틀.. 심하게는 몇 주를 허비하게 되는 때도 여러 번 있었다고 한다.


일에 몰입하기는 커녕 흐름을 타지 못 했고, 자신의 존재가 마치 사라져버린 것 같았다고.


그리고 자신이 실제로 하루에 생산성 높게 코딩을 하는 시간이 

고작 2~3시간에 불과하다는 사실이 무척 괴로웠다고 한다. 


즉, 하루동안 일에 몰입하기까지의 장벽은 너무나도 높다는 것이었다.

그 장벽만 넘으면 일에 몰입해 생산성을 높일 수 있는데.


그런데 너무 이런 압박감에 시달릴 필요가 없다는 것을 깨닫게 된 것이

군대에서 '적들을 향해 총을 쏴서 적의 머리를 숙이게 만들고, 그 시점에 적과의 거리를 점차 좁혀간다'라는

엄호 사격 전술을 알게 되었을 때부터 15년이 지난 후였다.


내가 움직이지 않으면 적군은 무슨 일이 벌어졌는지 눈치채게 되고,

내가 쏘지 않으면 적이 사격해 나를 꼼짝 못하게 만들 것이다.


그러니 매일 조금씩 움직여야만 한다고 한다.


코드가 ㅄ같고 아무도 원하지 않는다는 사실이 문제가 되는 것이 아니라는 것이다.

늘 조금씩 움직이면서 코드를 쓰고 버그를 지속적으로 잡아낸다면, 시간은 내 편이 된다는 것이다.


다음은 책에서 그대로 따왔다. 내가 요약해서 적을 수도 있겠지만,

담담하게 풀어 쓴 문체 자체까지 내게는 위안이 되었기 때문에 인용하겠다.


매일 조금씩 앞으로 나아가야 합니다. 이렇게 하다보면 조만간 당신이 이길 것입니다.

어제 하루동안 제가 한 일이라고는 FogBUGZ 에서 컬러 정책을 조금 개선한 사항뿐입니다.

이 정도면 충분합니다. 조금씩 발전해 나가는 겁니다.

날이 갈수록 우리 소프트웨어는 점점 더 좋아지며, 더 많은 고객을 확보할 수 있다는 점을 노릴 뿐입니다.

Oracle 정도로 큰 회사가 되고 난 다음에 거대한 전략을 생각해도 늦지 않습니다.

매일 아침 출근해서 에디터를 여는 것만으로도 충분합니다.




16장. 장인정신 


요약하면, 장인정신이 필요한 경우가 있는 건 이해하지만

모든 소프트웨어 개발에 항상 장인정신을 투자할 필요는 없다고 충고하는 장이다.


나의 경우는 완벽주의자에 가깝기 때문에 이것저것 사소한 것에도 까다롭게 구는 경우가 많다.


하지만 조엘님은 나같은 사람에게 날카롭게 지적하듯이 

'1%의 결함을 고치기 위해 500% 달하는 노력이 필요할 수 있다

그럼에도 불구하고 추가 비용을 감당할 정도로 충분한, 고칠 가치가 있는 결함인가?' 라고 해주셨다.


일반 소비자를 위한 상용 소프트웨어, 또는 상품 소프트웨어를 개발하는 방법만이

장인정신에 투자할 수 있는 유일한 길이라고 한다. => 장기간에 걸쳐 경쟁우위를 제공하는 핵심 요인이 될테니까.

(사내용 인사 관리 프로그램 같은 경우, 이런 장인정신을 뒷받침할 수준까지 이르지 못한다)


왠지 예전에 내가 인턴 생활을 할 때 사내용 프로그램 개발에

투철한 장인정신을 발휘했던 내 모습을 떠올리게 된다. 으으.




< 2부 > 개발자 다루기



20장. 인터뷰를 위한 게릴라 가이드


- 조엘님이 말한 채용 프로세스 : 


1) 이력서

i. 실수가 많은 이력서 버린다 (ex. Windows를 Window로 썼다든가) : 꼼꼼한 사람을 뽑기 위해

ii. 과거에 특별히 어려운 선별 과정을 거친 경험이 있는지 (ex. 입학 기준이 높은 대학, 깐깐하게 사람 뽑는 회사)


2) 전화 인터뷰 :

i.  프로그래밍 문제 하나로 한 30분 정도 이야기를 나눔 (ex. XML Parser 를 어떻게 짜실 건가요?)


3) 대면 인터뷰 :

i. 면접관은 적어도 6명은 되야 하고, 최소 5명은 동료 프로그래머로 채운다.

   이 중에서 2명 이상의 면접관이 지원자가 별로라고 하면 고용을 안 하는 게 낫다고 한다.

ii. 지원자를 동시에 인터뷰 하지 않고, 각 인터뷰는 화이트보드가 있는 방에서 1:1 로 진행한다.



- 조엘님이 생각하는 좋은 지원자

i. 똑똑하다.

- 잡다한 지식을 많이 알아야 한다는 것이 아님

(ex. 오라클 8i에서 varchar와 varchar2 의 차이 => 인터넷에서 15초면 찾을 수 있는 내용)

ii. 업무를 성실하게 완수한다.


사람을 파악할 수 있는 방법은 말할 기회를 주는 것이기 때문에

개방형 질문이나 문제를 던져야 한다고 한다. 그러면 어떤 질문을 해야하는지 다음을 살펴보자.

(※ 참고로 조엘님은 면접 전에 지원자에 대한 선입견을 품지 않으려고 극도로 조심한다고 한다. ex. 학벌)



- 해야할 질문 :


1. 첫 인사 

지원자를 편하게 해주려는 목적으로, 여기서 첫인사는 지원자가 하는 인사라기 보다는

면접관이 지원자에게 하는 인사이다. (ex, 오는 길이 어땠는지, 면접관 소개, 인터뷰 진행 방식 등)


2. 최근 프로젝트 경력에 대한 질문

- 개방형 질문의 예시 :

ex. 지난 학기에 들은 수업 중 가장 좋아했던 수업은 무엇이죠? 전산 과목이 아니어도 좋습니다.

ex. 전 직장에서 했던 최근 프로젝트는 어떤 프로젝트 였나요?


- 개방형 질문을 던져놓고 초점을 맞춰야 할 자질 3가지 :

i. 열정

똑똑한 사람은 자신이 수행한 프로젝트에 대해서 열정적으로 말하게 됨

(이야기를 하면서 흥분하게 되고 말이 빨라지고 손짓이 따르게 됨),

반면 인터뷰 내내 무덤덤한 사람은 별로.

ii. 상대 수준에 맞게 설명 :

다른 사람에게 자기 아이디어를 납득 시키기 위해서는 어떤 태도를 취해야 되는지 아는 사람인가.

iii. 팀 프로젝트 였다면 리더십을 발휘했을 것 같은지


3. 답변 불가능한 질문

- 한때 구글에서 나왔었다는 면접 문제들...(짜증) :

ex. LA에는 주유소가 몇 개나 있을까요? 워싱턴 기념탑 무게는 몇 톤일까요? 등등


- 문제 해결 능력 + 창의력 이 있는 사람인지 :

지원자가 당황해 하면 힌트를 던져주되, 계속 멍청하게 앉아 있는 경우

이 사람은 구조의 손길만을 기다리는 사람으로 문제 해결 능력이 부족하다고 판단.


4. 프로그래밍 문제

- 종이 주고 손코딩 : 코드가 10줄 넘는 문제는 피하자. 

제들을 보면 실제 N사가 이걸 보고 베낀 듯한 면접 질문들 몇개 있음...


i. 원래 저장위치에서 문자열을 역순으로 변환하기

: 함수 성능이 어떤지, strlen 함수를 몇 번 호출했는지 판단, O(n) 이면 충분함에도 불구하고 

루프 안에서 strlen 을 계속 호출하는 바람에 O(n²) 인 strrev() 를 본적도 있다고.


ii. Linked List 를 역순으로 만들기

: 똑똑한 지원자라면 바로 코드를 안 짜고 구현 전에 계획을 짤 것이다.

아마 옆 귀퉁이에 네모와 네모를 연결한 화살표를 그리기 시작할 것임.


iii. 한 바이트에서 1인 비트 세기

: C 비트 연산을 아는지 확인하려는 의도가 아님,

똑똑한 지원자는 1번만 만들면 되는 참조표를 이용할 것임(많아야 256 개니까)

또는 처음에만 bit 를 세서 참조표에 저장하는 캐쉬 사용을 제안 등등...

목적은 코드를 다듬고, 최적화하고, 개선할 방법을 찾아내는 능력이 있는지 보기 위함.


iv. 이진 검색

v. 문자열에서 '연속적으로 문자가 반복되는 길이(run-length)'가 가장 긴 부문문자열 찾기

vi. atoi

vii. itoa (스택이나 strrev 를 써야하기 때문에 좋은 문제)



좋은 프로그래머라는 증거 몇 가지 :

i. 간단한 규칙이라도 변수 명명법을 사용.

ii. C에서 상수는 "==" 왼쪽에 두는 버릇.

(ex. if (x == 0) 이 아니라 if (0 == x) 라고 쓴다든가)

iii. while 루프에서 변하지 않는 값이 무엇인지를 본능적으로 안다.

(ex. while (index <= length) 가 아니라 while (index < length)

iv. C++에서는 가상 소멸자를 사용한다.



5. 자신의 코드에 만족하는가?

- 4.에서 작성한 코드에 만족하는지 물어본다

- 손코딩이다 보니 실수는 하기 마련, 하지만 실수를 찾아낼수 있어야 한다는 게 포인트.

ex. 문자열 함수에서 NULL 종결자, 세미콜론, 길이가 0인 문자열이 들어오면 안 돌아가거나, 

malloc이 실패하면 GPF가 발생. (General Protection Fault 의 약자, 

프로세서의 메모리 보호 하드웨어가 잘못된 주소 접근을 잡아낼 경우 발생한다)


6. 질문이 있는가?

- 우수한 지원자는 직장을 선택할 수 있기 때문에 면접관은 일방적으로 인터뷰를 하는 입장만은 

   아니라는 사실을 명심해라. 인터뷰는 상대방도 여기가 일할 만한 곳인지 파악하는 시간이다.

   (가끔 면접관들 중에 상당히 거드름 피우는 ㅄ 같은 놈들도 많다, 회사에 대한 이미지를 다 깎아먹음)


- 일부 면접관은 총명한 질문을 하는지 판단하려고 들지만 조엘님의 경우, 

이 시점에서 어떤 질문을 하든 이미 결정을 내렸기 때문에 개의치 않는다고 한다.


하지만 꽤 흥미롭거나 인상깊은 질문으로 었다는 이야기도 많이 들어봤다.




26장. 허술한 추상화의 법칙


모든 쓸 만한 추상화에는 어딘가에 구멍이 존재합니다.


-> 차후 이 책을 다시 읽을 때, 이 부분을 자세히 읽고 분명히 이해해야 할 필요가 있다고 느낌.

지금의 나로서는 사실 이해가 잘 안 되서 ㅠ_ㅠ 중요 문구만 남기겠다.




< 3부 > 조엘 따라하기



31장. 말단이면서도 해내기


- 전략 1 : 혼자라도 하십시오

일일 빌드 서버가 없다면? 만들면 된다. 밤마다 일일 빌드를 돌리고, 다른 팀원에게 이메일을 보내라.

빌드 단계가 너무 복잡하다? makefile 을 써라.

사용편의성 테스트를 아무도 안 한다? 종이나 VB 프로토타입을 사무직 친구에게 보여주면서 직접 테스트 해라.


- 전략 2 : 입소문의 힘을 이용하십시오

전략 1과 비슷한 내용이라 생략.


- 전략 3 : 우수한 인재를 모으십시오

이 내용이 왜 이 장에 포함되어 있는지 잘 모르겠다. 말단이라면서

우수한 인재를 팀으로 끌어들이라면서 채용과 인터뷰 업무에 참여하라고 한다.

말단이 그게 가능한 건가? 아니면 조엘님이 말하는 '말단'이 내가 생각하는 '말단'이랑은 다른 건가?


- 전략 4 : 고문관은 봉쇄해야 합니다

고문관이란 질 낮은 코드로 다른 질 좋은 코드까지 더럽히는 사람을 일컫는 말이다.

이 사람의 코드를 보면 마음 같아서는 전부 버리고 새로 다시 짜고 싶겠지만 참아야 한다!!


그냥 내버려 두고 코드에서 생기는 버그를 계속 보고 한다.

그러면 고문관은 보고할 버그가 없어질 때까지 그 작업에 매달리게 될 것이다.

다시 말해 다른 코드를 해치지 않을 것이다. (진짜 그런지는 솔직히 조금 의문이다)


- 전략 5 : 방해 받지 않는 곳으로!

와.............. 대박 공감이다. 

내가 예민한데다 약간 산만해서 그런지 일할 때 만큼은 조용한 환경에서 일하는 걸 좋아한다.

나 같은 말단이 자리를 지키지 않는다는 건 눈치보이기 쉽상이지만...

노트북 들고 조용한 곳에서 생산성 있게만 작업할 수 있다면 어디든 좋을 것 같다 OTL


- 전략 6 : 꼭 필요한 인물이 되십시오

조엘님의 경우, 옛날에 말단 프로그래머로 어떤 회사에서 일할 때 회사가 조엘 테스트 2점이었다고 한다.

그래서 업무 환경을 고쳐야 되겠다고 작정을 했다고 한다. (헉...)


하지만 같이 일 하는 사람들에게 좋은 인상을 심어주는 일이 무엇보다 중요하다는 점도

알고 있었기에 매일 하루 7시간은 무조건 코드를 짰다고 한다. 

(무수한 체크인 만큼 다른 팀원에게 좋은 인상을 주는 방법은 없기 때문!!

-> 내가 전에 인턴했을 때는 일을 엄청 하면서도 체크인을 잘 안해서 ㅄ 될 뻔한 적도 있음)


하지만 매일 퇴근 전 1시간은 업무 환경 개선에 힘을 쏟았다고 한다.

이 시간 동안 일일 빌드, 버그 DB 설치, 명세서 작성, 업무와 관련된 문서 작성 등등.

그렇게 노력하니까 조금씩 나아졌다고 한다.


실제로 이게 가능한가....? 싶기도 하지만.. 만약에 어떤 말단이 이런 짓(?)을 한다면

이 사람은 꼭 필요한 사람이라고 느낄 거라고 확신한다. 생각이 있는 관리자라면.



조엘님은 책임자가 아니라도 변환를 일으킬 수 있다고 해주시면서

그렇지 못하면 적을 만들게 된다고 한다.


내게 있어서 전략 1, 5, 6 만큼은 뭔가 와닿는 것이 있었다. 특히 1, 6.





그 외 4부, 5부도 있지만 내가 다룰 만한 내용은 없는 것 같으니 생략하겠다.


이번 책은 다른 책에 비해 조금 두꺼웠다. 한 500 페이지 가까이 되니... ㅠ_ㅠ

아직 독서 습관이 안 잡힌 나로서는 솔직히 부담스러웠다. 그래서 읽는 것조차 힘들었고.


당분간 개발자를 위한 서적은 쉴 생각. 너무 개발자 서적만 읽었더니 오히려 스트레스 받는 것 같다.

독서 습관 들이려다 지치고 싶지는 않으니 다른 책들도 읽어 봐야 겠다.


원래 이 책 읽고나서 More Joel on software 도 읽으려고 했는데... 좀 쉬었다가 읽어야겠다.


확실히 배울 점이 많은 책이었다는 건 분명하지만 왠지 지쳐버렸다 ㅠ_ㅠ.. (리뷰를 써서 그런가?)

아무튼 휴식이 필요해


by kelicia 2014. 10. 12. 18:31


언리얼 엔진 4 문서에서 '데이터 주도형 게임 플레이 요소' 라는 글을 읽고

따라해보다가 설명된 것 치고는 은근히 어물쩡(?) 설명되있어서 

사람을 몇 시간씩 구글링하게 만들게 한다ㅡㅡ+...


열받아서 나처럼 헤매는 이가 없도록 포스팅을 하게 됐다.



그래서 오늘 할 것은 

".csv 파일의 데이터를 언리얼 엔진4 에서 사용할 수 있도록 DataTable 오브젝트를 생성하는 가이드 라인" 을 

작성해 보겠다. 

+ 팁으로 일부 버그에 대한 핸들링도 언급하겠다.


다소 영문 문서를 그대로 번역한 느낌의 말투가 있더라도 양해를(__)

제가 직접 해본 것을 기반으로 포스팅한 거라 "반드시 이렇다!" 라는 건 아닙니다!




언리얼 엔진4에서 사용되는 DataTable 의 유형은 크게 2 가지이다.


1) Data Table

어떤 데이터 타입이든 자유롭게 정의할 수 있다. 

ex ) int, string, TAssetPtr<UTexture>, 기타 등등.


2) Curve Table

부동소수점 실수 타입의 데이터만 정의할 수 있고 곡선 상의 보간에 특화된 테이블이다.


- Curve 는 게임 내의 밸런스나 기술/능력에 대한 특성 조절에 유용하게 사용될 수 있다고 한다.

예를 들어 게임 난이도 설정에 따라 HP 가 달라지는 몬스터가 있는 경우

100 ~ 10,000 범위의 HP Curve 를 선형이든 큐브형이든 어떤 방식으로 정의한 후에,

어려움의 난이도 에서 몬스터의 HP 값을 그 Curve 의 최소 / 최대 값 의 75% 정도에서

따오면 된다.

(Curve Table 의 경우, 자세한 내용을 다루는 것은 못봐서 이 정도로만 언급하겠다)




그러면 아까 위에서 말한 가이드 라인으로 돌아와서

크게 5가지 스텝으로 나누어 설명하도록 하겠다.


1. .csv 파일 생성

2. FTableRowBase 를 상속받는 구조체를 생성

3. 코드 빌드 후 언리얼 엔진 재실행

4. 컨텐츠 브라우저에 .csv 파일을 드래그앤드롭 하면 DataTable 오브젝트 생성

5. 블루 프린트나 코드에서 4. 의 오브젝트를 이용해 데이터에 접근 가능




1. 언리얼 엔진에 import 할 .csv 파일을 생성한다.


다음과 같이 엑셀에서 데이터를 만든 후, 저장할 때 .csv 파일을 생성해도 된다.

A1 은 비워두라고 되어있지만 굳이 쓰고 싶다면 써도 큰 문제는 없다.


왜냐하면 첫 번째 컬럼 값들은 Row ID 를 나타냄으로서 

데이터 테이블에서 Row 를 구분하기 위해 반드시 있어야 하는 기본적인 아이라 

언리얼 엔진4에서 이 파일을 import 할 때, 첫 번째 컬럼은 건너뛰어 버리기 때문이다.

(관련 링크 : CreateTableFromCSVString

https://docs.unrealengine.com/latest/INT/API/Runtime/Engine/Engine/UDataTable/CreateTableFromCSVString/index.html )


내가 만든 샘플 데이터(.csv)들은 다음과 같이 생겼다.




2. FTableRowBase 를 상속받는 구조체를 생성한다.



언리얼 엔진에서 프로젝트를 열고, 코드를 추가해준다. 

이 때 주의해야 할 점은 None 이 아니라 언리얼 엔진에서 제공하는 클래스를 반드시 상속받도록 하자.

안 그러면 차후 빌드할 때 꽤나 골치 아파진다.. 그냥 Dummy 클래스 하나 만든다고 생각하자.


저 같은 경우에는 'Show All Classes' 에 체크하고 Engine 클래스를 상속 받았습니다.

별 뜻 없습니다. 단지 None 으로 하고 구조체만 달랑 정의했다가 -매우 - 피봤기 때문에ㅠ_ㅠ

누군가가 "이렇게 하니까 되던데요" 라고 하는 코드를 보고 저 클래스를 상속 받았을 뿐.


Engine 클래스가 아니더라도 Actor 를 받아도 되고 상관 없습니다.

구조체 정의하기 전에 언리얼 엔진의 클래스를 반드시 상속 받는 Dummy 클래스를 만드는 게 포인트.



저 같은 경우 빈 프로젝트에서 데이터 테이블을 생성하고 있었는데,

찾아보니 이 문제(?)를 해결 하기 위해서는 프로젝트에 반드시 언리얼 엔진에서 

상속받은 클래스가 적어도 1개 이상 있어야 한다고 한다.

(관련 링크 : https://answers.unrealengine.com/questions/71182/can-not-derivate-from-struct-ftablerowbase.html )



클래스를 만들었으면 구조체를 정의하는데 그 안에

1.에서 만든 데이터 필드들의 이름과 동일하게 변수들을 작성해주면 된다.


내가 만든 데이터들을 기반으로 구조체를 작성해 본 결과는 다음과 같다.

언리얼 엔진에서 Engine 클래스를 상속받은 MyDataAsset 이라는 클래스를 생성했고,

아래 코드는 MyDataAsset.h 에 작성하였다. LevelUpdata 라는 구조체를 만들었다.



아까 위에서 보여준 .csv 파일에서 첫번째 셀의 값에 Name 이라는 값을 넣어주었지만

코드에서는 적어주지 않았다. 적어도 되고 안 적어도 되는 듯 싶지만...


언리얼 엔진4 문서에서는 생략하길래 그냥 나도 생략해버렸다. 귀찮아서.


여기서 포인트는 구조체가 FTableRowBase 를 상속받았다는 점.

아, 참고로 언리얼 엔진 구조체 내에는 함수를 정의할 수 없다고 한다. 

(상당히 내겐 충격적이었음_-_ .......... 구조체 내에 함수 정의를 못 해서

밑에 다룰 버그 관련 내용에서 살짝 귀찮게 됨)



코드 따라서 입력하기 귀찮으신 분들은 포스팅 맨 아래 참고 링크들

따라가셔서 ctrl + c,v 하시면 됩니다~




3. 빌드를 하고 언리얼 엔진을 재실행 시킨다.


주의해야 할 점은 빌드 하기 전에는 반드시 언리얼 엔진을 종료시켜야 한다.

안 그러면 LNK 에러를 미친 듯이 뿜어낼 수 있다. (정확한 이유는 잘 모르겠음)


엔진 종료 -> 빌드 -> 엔진 재실행


순서로 가자.




4. 엔진의 컨텐츠 브라우저에서 1. 에서 만든 .csv 파일을 드래그앤드롭 한다.



이 때, 다음과 같은 다이얼로그 박스가 하나 나올 것이다.



3. 에서 정의한 구조체인 LevelUpData 가 보일 것이다.

만약 2.에서 언리얼 엔진으로부터 상속 받은 클래스가 없다면 저 망할 Row Type 에 

내가 정의한 구조체가 뜨지 않는, 짜증나는 현상의 연속을 보게 될 것이다. -> 이것때문에 삽질 겁나 함.



아무튼 여기까지 Import 과정을 모두 마쳤으면 위의 스샷처럼 콘텐츠 브라우저에

'DataTable' 이라는 초록색 오브젝트가 생긴 것을 볼 수 있다 :-)


오브젝트를 더블 클릭하면,


요렇게 이쁘게 나오는 것을 볼 수 있다.


참고로 중간에 .csv 파일의 데이터가 수정되었다면 

엔진 쪽에서 만든 오브젝트를 우클릭 -> Reimport 하면 변경된 데이터를 볼 수 있다.



그런데 ! 주의해야할 점을 알려준다면 

위와 같이 어떤 파일의 상대주소를 데이터로 넣었을 때, 제대로 안 뜨는 경우가 있다.


나의 경우 어떤 삽질을 했냐면...


엑셀 파일에서 "Texture2d'/Game/Textures/AchievementIcon2'" 라고 입력을 한 뒤에

.csv 파일로 변환해서 그 파일을 열어보면 어처구니 없게도 ㅡ_ㅡ

양쪽에 큰 따옴표가 2개씩 더 붙어서 나오는 현상이 있었다.

이렇게. -> """Texture2d'/Game/Textures/AchievementIcon2'"""


저런 경우에는 언리얼 엔진에서 import 한 데이터가 None 으로 뜨게 되버린다.


또는 큰 따옴표를 빼먹고 Texture2d'/Game/Textures/AchievementIcon2' 라는 데이터가

.csv 파일에 저장되어있을 때, import 하면 데이터가

Texture2d' 까지 밖에 안 보이는 현상이 있었다.


위 스샷 처럼 정확한 주소를 보이게 하려면 .csv 파일을 열어봤을 때, 데이터가

"Texture2d'/Game/Textures/AchievementIcon2'" 와 같이 정확히 한쌍의 큰 따옴표만 감싸고 있어야 한다는 점.


그러니 엑셀에서 큰 따옴표를 사용해 데이터를 저장할 때는 주의하자 ! !



참고로 아래는 언리얼 엔진 문서에서 발췌한 내용이다.

The double quotes around the asset type are important for the property importing pipeline. Without them, the text is imported as Texture2d'.





5. 블루프린트나 코드 상에서 4.에서 생성한 오브젝트에 접근해보자.


여기서 중요한 건, 블루프린트에서 데이터에 접근할 때 짜증나는 버그가 존재한다.

차후 엔진 측에서 고쳐줄 지는 모르겠지만 지금 언리얼 엔진 4.4 버전 상에서는 아직도 존재한다.


1) 블루프린트에서 DataTable 오브젝트에 접근 하기


무슨 버그가 있는지 일단 살펴보겠다.

아래에 보면 개발자가 정의한 데이터 테이블에 있는 데이터에 접근하기 위해 

"Get Data Table Row (DataTable Object 이름)" 라는 노드가 존재한다.

이게 문제다.



빨간색으로 'X' 표시 되어있는 부분이 문제의 버그다.

막상 블루프린트 작성할 때는 멀쩡히 잘 연결되다가 언리얼 엔진을 종료하고

다시 이 프로젝트를 열면 저기 표시되어 있는 링크 부분이 사라지게 되는 버그가 발생한다.

그래서 데이터에 접근이 안 되서 컴파일 할 수 없다고 난리다. 


(데이터 테이블의 초기화 문제였나? 암튼 그런 쪽으로 뭔가 버그가 있는 듯 했다.

구글링했을 때 영문으로 뭐라고 나와있었는데 이해할 수 없었다. 아시는 분은 방명록에 남겨주시면 ㄳㄳ (__)

자세한 링크는

https://answers.unrealengine.com/questions/67457/get-data-table-row-bug.html )


결국, 문제의 'Get Data Table Row' 노드를 사용할 수 없다.

그러니 우회하는 방법으로 데이터에 접근하자. 꽤 간단하게 해결되는 문제다.



여기서부터 내가 구글링의 도움을 받아 실험한 결과를 토대로 작성한 가이드 라인이다.

정답은 아니고 '이런 식으로 해결 할 수 있다고 하네요' 정도로만 읽어주시면 감사하겠습니다 :-)



① 언리얼 엔진에서 코드를 추가한다.

내 경우에는 Actor 를 부모 클래스로 상속받아 'DummyActor' 클래스를 생성했다.



② DummyActor.h 에 다음과 같이 작성해준다.



사실 나는 아까 선언했던 LevelUpData 구조체 안에 getTableRow() 함수를 넣으려고 했지만 

위에서 이미 언급했듯이 구조체 안에 함수 선언을 할 수가 없다...ㄱ-....아놔..


그래서 따로 울며 겨자먹기로 새로 클래스를 만들어 위와 같이 코드를 작성해주었다.



③ DummyActor.cpp 에 다음과 같이 작성해준다.



빨간색 네모 박스에 있는 코드가 핵심이다.



④ 언리얼 엔진을 종료하고 빌드한 후, 엔진을 재실행하자.



⑤ 내 경우에는 게임이 Play 될 때 좌측 상단에 데이터를 출력하는 걸 테스트하고 싶었다.

그래서 잘은 모르지만(?) : 참고로 필자는 언리얼 엔진4 써 본지 얼마 안 된 조금 멍청한 초보다.

GameMode 를 상속받아 블루프린트를 생성하였다.



⑥ 블루프린트에서 DataTable Row Handler 타입의 변수를 하나 생성해 

Default value 에서는 4.에서 생성한 Data Table 오브젝트에 연결 할 수 있다.

Row Name 은 데이터 테이블에서 행을 구분해주는 첫번째 컬럼을 말한다. 가져오길 원하는 RowID 값을 선택하면 된다.


아까 정의한 getTableRow 함수를 가져와야 하니 DummyActor 변수도 생성해주자.



⑦ 다음과 같이 데이터에 접근할 수 있다.

원하는 데이터에 접근해 마음대로 지지고 볶고 하시면 됩니다. 잘 안 보이시면 이미지 클릭.





여기까지 블루프린트에서 DataTable 에 있는 데이터에 접근하는 방법이었습니다.


코드 부분은 제가 따로 테스트를 하려고 시도했지만...

언리얼 엔진4의 최소 메모리 스펙이 8GB 인데... 제 컴이 그 절반 밖에 안되는 녀석이라

여기까지 도달하는 데도 수많은 시간이 걸렸습니다 흑흑 ㅠ_ㅠ


그래서 코드로 데이터 접근하는 부분인 제가 직접 해보지는 못 했구요,

관련 자료 링크만 정리 해서 남겨봅니다.




* 엑셀 데이터로 게임 플레이 구동시키기(한글) :

https://www.unrealengine.com/ko/blog/driving-gameplay-with-data-from-excel


* 데이터 주도형 게임플레이 요소(한글, 영문은 주소에서 KOR 를 INT 로 바꿔주세요) :

https://docs.unrealengine.com/latest/KOR/Gameplay/DataDriven/index.html


2개 링크 모두 비슷한 설명 수준이구요, 자세한 설명은 아닙니다.

그냥 '이러한 흐름을 거치면 .csv 파일이 import  됩니다. 하하:D' 정도?


* 제가 방금 언급했던 미처 확인하지 못한 코드에 대한 자료는 언리얼 엔진4 위키에 있습니다. 아래 링크 참조.

https://wiki.unrealengine.com/Using_excel_to_store_gameplay_data_-_DataTables



되는 것만으로도 감지덕지한 기분으로 하다보니 미처 '이 부분은 왜 이렇게 되는거임?' 이라는 궁금증이

있었음에도 불구하고, 일단 되게끔 만드는 데 집중하다보니 부족한 부분이 많이 있습니다 ㅠ_ㅠ


혹시 지적해주실 내용이 있으시다면 조금 귀찮으시더라도

방명록에 꼭 남겨주세요. 수정해야할 부분은 수정하도록 하겠습니다 :-)



'Programming' 카테고리의 다른 글

유니티로 개발할 때 많이 쓰이는 .gitignore  (0) 2017.08.07
[C]printf()에서 "%ul"와 "%lu"의 차이?  (0) 2015.07.05
자료구조 : Linked List  (0) 2014.04.25
Delegate (대리자)  (1) 2013.12.20
[Python, C#]Lambda Form  (0) 2013.12.19
by kelicia 2014. 9. 22. 14:39


http://slipp.net/questions/268



많은 댓글 토론? 들이 난무하는 글이나 기억에 남는 댓글만 가져와본다.


장원준 from 생활코딩.

프로그래밍은 추상적인 목표를 구체화하고 구현하는 쪽이 강하고 인문학은 구체적인 현상이나 상황을 모아서 추상화하는 쪽에 더 강합니다. 물론 둘 다 한쪽 방향의 사고만 하는 것은 아니겠지만 큰 흐름은 반대방향이죠. 한쪽 방향은 결과물을 만들고 다른 방향은 목표를 만들어냅니다. 시키는 것만 구현하는 프로그래머가 싫다면 새로운 목표들을 찾는 안목이 있어야겠지요 ^^


류동국 from server-side-architecture-group.

IT의 역사는 50년 정도입니다. 다른 인문사회학은 인류의 탄생과 그 궤를 같이 합니다.
소프트웨어 공학의 역사를 보면, 초기에 많은 방법론이나 프로세스에서, 사람이라는 요소를 배제한 경우가 많았습니다.
소프트웨어를 만드는 가장 큰 요소는 컴퓨터가 아니라 사람이라는 인식은 우리나라에서는 아직도 생소한 개념이죠.  
많은 프로젝트를 진행해보면 실제로 가장 중요한 동인은 인간이며, 인간과의 관계속에서 소프트웨어들이 만들어집니다.
해외는 이러한 부분을 상당히 일찍 연구하기 시작했고, 소프트웨어 심리학을 발전시키기도 했죠. (이 책은 1971년에 초판이 발행되고 내용은 아직도 놀랍도록 유효합니다.)
또한 모든 상황의 배경이 되는 인문학을 모르면, 큰 흐름과 큰 그림을 그리는 것에 상당히 취약함을 보이게 됩니다.
가끔 최신 기술에 대한 많은 글들을 읽게 되면, 해당 기술 자체에 매몰되는 것을 많이 보게 됩니다.
사실 그러한 기술들이 나오게된 사유의 배경과 깊이를 알고, 원리를 이해하는 것이, 기껏해야 남들이 만들어놓은 기술의 사용법 정도를 익히는 것보다 훨씬 가치있을 것입니다.
또 다른 사례로 sw 아키텍처 관련 서적이나 자료를 보면 개요부분엔 항상 역사 또는 건축에 대한 이야기로 부터 시작됩니다. 인문학적 지식이 없는 사람들에겐 아무런 insight를 주지 못합니다.
하지만, 인문학을 아는 이는, 전체를 관통하는 큰 줄기가 머리를 스치게 되죠. 앞으로 이런 이야기가 전개 되겠구나 하고 말이죠. 
사실 소프트웨어 개발은 컴퓨터를 도구로 할 뿐인 너무나 사회적이고 인간적인 활동이었던 거죠.


2개의 덧글을 읽고.. 형용하기는 어려우나 이해할 수 있었고 뭔가 와닿는 부분이 있었다.

그래서 블로그에 남겨본다.



http://gamjachoi.blogspot.kr/2013/08/blog-post.html


개인의 생각을 굉장히 진솔한? 느낌으로 적은 글.

공감할 수 있었고 중요하다고 생각되는 부분을 인용해본다.


프로그램 실력이나 기술은 매우 중요하다. 하지만 그것 자체가 새로운 도전을 시작하게 하지는 못한다. 삶에 대한 진지한 고민으로 말미암아 가슴에서 우러나오는 용기와 도전 정신이 새로운 모험을 하게 만든 다. 이것이 현대를 살아가는 개발자들이 인문학을 해야 하는 이유이다. 인문학을 통해서 인생에 대한 새로운 안목을 갖고, 새로운 내 안 에 있는 용기를 발견해야 한다. 이번 주말에는 시간을 내어서 인문학 속에서 왜 사는지 그리고 어떻게 살아야 하는지 진지하게 고민을 해 보면 어떨까?



http://news.mt.co.kr/mtview.php?no=2013041508100425605


'프로그래머가 인문학을 해야 하는 이유'와는 거리가 있지만,

'이런 사람도 있구나' 정도를 느낀 기사. 

(링크 따라가면 지저분한 광고가 덕지덕지 붙은 언론사 홈페이지의 기사로 넘어가서 짜증)


일부만 발췌해봤다.


시인 된 프로그래머 "인문학 감성이 IT와 만날때"

(중략)

"시를 왜 쓰냐고요? 시를 통해 내 감정을 표현하고 그 감정을 다른 사람들과 공유할 때 느끼는 희열이 얼마나 큰지 몰라요. 현대인은 외롭잖아요. 사회적 위치에 오른 것같고 일도 많이 한 것같지만 막상 남는 건 별로 없죠. 술 마실 때만 감정을 표현하지 말고 글로 자신을 표현해보라고 주변에도 많이 권합니다."


존경스럽고 그런 정도는 아니나...

(기사가 조금 마음에 안 드는 게 시를 쓰는 게 인문학 감성까지라고 할 수 있는 건지는 모르겠다)


왜 저 부분을 발췌해왔냐면

글로 자신을 표현해보라는 부분이 마음에 들었다.


태어나서 주입식 교육 아래 글을 써 본 빈도는 매우 적으나... 

내가 글을 썼을 때의 느낀 감정을 회상해보면 어떤 글을 썼든 간에

뭔가 스스로가 차분해지는 기분이었다. 생각이 조금씩 정리가 되면서 뜬구름 같은 것들이 가라앉는 기분?


그럼에도 불구하고 요즘 다시 글을 안 쓰고 있는..(..)

나를 반성해본다.

- 반성하다가 논지에 벗어나버렸다 -




돌아와서 이 포스팅을 하게 된 이유를 간단히 남기자면,



리딩으로 리드하라

저자
이지성 지음
출판사
문학동네 | 2010-11-17 출간
카테고리
자기계발
책소개
[꿈꾸는 다락방] 이지성의 전 국민 인문고전 독서 프로젝트! 정...
가격비교


인문학적 소양을 쌓아야 한다고(정확히는 인문고전 독서를 해야한다) 아주 눈에 글씨가 박힐 정도로

여러 가지 이유들로 설득하면서 자기 주장을 반복적으로 강조하는 책이랄까.


이 책에 대해서 따로 리뷰를 남길 지는 모르겠으나

왠지 읽다가 살짝 뭔가 답답했는지 이 새벽에 갑자기 구글 검색창에 

'프로그래머 인문학' 이딴 검색질을 하다가 결국엔 짤막하게 포스팅까지 하고 있다.


뭐 하는 애일까 나 ㅋㅋ



나중에라도 이 포스팅 제목대로

내가 생각하는 그 이유에 대해 정리가 된다면 추가로 포스팅해야겠다.


by kelicia 2014. 8. 28. 01:47

중복 컴파일 방지를 위해 자주 쓰이는 전처리기 지시자들에 대해 비교해 보고자 한다.



1) #ifndef


먼저 다음과 같은 코드가 있다고 하자.


First.h

#ifndef _FIRST
#define _FIRST

class First
{
};
#endif

Second.h

#ifndef _SECOND
#define _SECOND

#include "First.h"

class Second
{
};
#endif

Main.cpp

#include "First.h"
#include "Second.h"

void Main()
{
}


Main.cpp 를 컴파일 해보면 #include 의 작동방식에 따라

그 파일의 코드가 그대로 복사될 것이다.


#ifndef _FIRST
#define _FIRST

class First
{
};
#endif

////////////////////////////////

#ifndef _SECOND
#define _SECOND

#include "First.h"

class Second
{
};
#endif

////////////////////////////////

void Main()
{
}


위와 같이 되고 Second 에서 또 한번 #include "First.h" 를 읽게 될 것이다.

그 결과로 ,


#ifndef _FIRST
#define _FIRST

class First
{
};
#endif

////////////////////////////////

#ifndef _SECOND
#define _SECOND

#ifndef _FIRST
#define _FIRST

class First
{
};
#endif

class Second
{
};
#endif

////////////////////////////////

void Main()
{
}


위의 코드와 같이 Main.cpp 에는 First.h 이 2번 복사되는 결과를 볼 수 있다.


결론을 내리자면, #ifndef 의 방식으로 중복 컴파일을 피하는 것은

#include 명령어를 사용한 횟수 만큼 전처리기가 그 파일을 복사해오고,

복사해 온 코드 상단에 작성된 #ifndef 구문을 읽고 컴파일 여부를 확인 한다는 것이다.


이렇게 결론을 지으면 

'그런데도 왜 이 방식을 써서 중복 컴파일 방지를 하냐 ?!'

라고 할 수 있다. 물론 장점도 존재하고 포스팅 마무리할 때쯤 언급하겠다.




2) #pragma once


그런데 나는 - pragma - 라는 단어가 대체 무슨 뜻인지 궁금해서 찾아보았다.



짜증. 괜히 맛있는 치킨만 먹고 싶어졌다.

그냥 컴파일러 지시자? 정도로만 이해해야겠다.


구글에 검색해도 pragma 가 뭐 하는 녀석인지만 나와있지,

정작 pragma 라는 단어 자체의 뜻에 대해서는 잘 안 나오는 듯_-_



어쨌든 잡소리였고 다시 중복 컴파일 방지를 위한 #pragma once 명령어로 돌아가자.


이 지시자가 의미하는 바는 '1번만 컴파일 하겠다' 라는 뜻으로 알고 있다.

msdn 에 따르면 (http://msdn.microsoft.com/en-us/library/4141z1cx(v=vs.80).aspx)


Pragma 지시자의 토큰 값으로 들어갈 수 있는 once 키워드 : 
Specifies that the file will be included (opened) only once by the compiler when compiling a source code file.

Remark : This can reduce build times as the compiler will not open and read the file after the first #include of the module.


아까 말한 것과 다를 바 없고, 이게 전부다. 

#ifndef 과 다르게 include 로 인해 여러 번 파일을 열어서 읽는 것이 아니라서 빌드 타임을 감소시킬 수 있다는 점.




3) 정리


#ifndef

- 앞서 보았듯이 헤더 파일을 여러 번 include 하게 되면 define 여부를 계속 체크해야 되기 때문에

컴파일 단계 중에서 파일 해석 단계의 속도가 #pragma once 에 비해서 다소 느리다고 할 수 있다.

하지만 장점을 꼽자면 전처리기 지시자(Preprocessor directive)라서 모든 컴파일러에서 동작한다는 점이다.


#pragma once :

- 1번만 컴파일 하고 그 뒤로부터는 동일한 파일의 경우, 읽기조차 하지 않는다. 그래서 파일 해석 단계의 속도가

#ifndef 보다는 빠르다. 하지만 아까 사전적 의미를 찾아봤을 때, 자세히 보면 'A compiler directive' 라고 적혀있다.

컴파일러 지시자로 특정 컴파일러에서만 동작하는 지시자이며 Visual C++ 5.0 이상에서만 동작한다고 한다.



얼핏 속도면에서 보면 #pragma once 가 좋아보일 수 있으나 

거대 프로젝트가 아닌 이상 속도에서 큰 차이를 볼 수 있을까? 하는 의문이 든다.


그리고 안정성(호환성)과 범용성을 고려한다면 #ifndef 방식을 택해야 할 것이다.




4) Reference


http://ace01kr.tistory.com/entry/%ED%97%A4%EB%8D%94%ED%8C%8C%EC%9D%BC-%EC%A4%91%EB%B3%B5%EB%B0%A9%EC%A7%80-pragma-once-vs-ifndefendif


http://neodreamer-dev.tistory.com/310


http://msdn.microsoft.com/en-us/library/t22e924w(v=vs.80).aspx


'Programming > C++' 카테고리의 다른 글

dynamic_cast 연산자  (0) 2014.10.26
정적 바인딩(Static binding) vs. 동적 바인딩(Dynamic binding)  (0) 2014.08.19
by kelicia 2014. 8. 25. 19:21


* Binding 

- 프로그램 구성 요소의 성격을 결정해주는 것

ex ) 변수의 데이터 타입이 무엇인지 정해지는 것




 종류

정적 바인딩(Static binding)

동적 바인딩(Dynamic binding)

 정의

 컴파일 시간에 성격이 결정되는 것

 실행 시간(runtime)에 성격이 결정되는 것

 예시

C언어 컴파일 시간에 변수의 데이터 타입이 결정

Python(Interpreter 언어) 런타임에 값에 따라 

 변수의 데이터 타입이 결정

 장단점

 컴파일 시간에 많은 정보가 결정되므로 실행 효율↑

 런타임에 자유롭게 성격이 바뀌므로 적응성↑




* 함수의 바인딩

- 함수를 만들어 컴파일을 하면 각각의 코드가 메모리 어딘가에 저장된다.

그리고 함수를 호출하는 부분에는 그 함수가 저장된 메모리 번지수(주소값)이 저장된다.


프로그램 실행 → 함수 호출 → 함수가 저장된 주소로 점프 → 함수 실행 → 원래 위치


위 과정에서 함수를 호출하는 부분에 함수가 위치한 메모리 번지로 연결시켜 주는 것을 바인딩(Binding) 이라고 한다.



- 함수를 바인딩하는 2가지 방법

(1) 정적 바인딩 (일반 함수)

컴파일 시간에 호출될 함수로 점프할 주소가 결정되어 바인딩 되는 것.

(2) 동적 바인딩 (가상 함수)

실행 파일을 만들 때 바인딩 되지 않고 보류 상태 둔다.

점프할 메모리 번지를 저장하기 위한 메모리 공간(4 byte)을 가지고 있다가 런타임에 결정.

=> 단점 : 타입 체킹으로 인한 수행 속도 저하 / 메모리 공간 낭비

=> 가급적 정적 바인딩 사용


?? 2 가지의 단점이 있음에도 불구하고 동적 바인딩을 하는 이유 ??

- 어떤 포인터에 의해 접근되었는 지에 상관없이 참조된 인스턴스의 실제 클래스형에 따라 재정의된 함수 호출이 가능!




이 포스팅의 원본 출처이자 C++ 에서

Template, 정적 바인딩 vs. Virtual Function, 동적 바인딩 으로 실험한 결과를 볼 수 있는 블로그 :

http://blog.daum.net/sox25/2


위 출처에서 정적 바인딩이 항상 동적 바인딩 보다 빠르다고 할 수 없다는 결과를 볼 수 있다.





* 프로그래밍 언어에서의 2가지 Type System


(1) 정적 타입 (Static Type)

- 컴파일 시에 타입이 결정

- 변수를 선언할 때, 반드시 앞에 타입을 명시해야 하는 언어들은 모두 정적 타입 시스템에 속한다.

ex ) C, C++, Java ...


- 결국 장점에 대해 언급을 하자면,

. 컴파일 시에 타입에 대한 정보를 결정하기 때문에 속도↑ (효율성↑)

타입 에러로 인한 문제점을 초기에 발견할 수 있어 타입의 안정성↑


(2) 동적 타입 (Dynamic Type)

- 런타임 시에 타입이 결정

- 코드를 작성할 때, 변수 타입을 명시하지 않고 런타임에 변수의 값에 따라 타입이 결정되는 시스템.

ex ) Python, Ruby, SmallTalk ...


- 장점 : 유연성 (혹은 적응성)

런타임까지 타입에 대한 결정을 끌고 갈 수 있기 때문에 많은 선택의 여지가 있다.

- 단점 : 안정성

인터프리터 언어는 배우기는 쉬우나 실행 도중에 변수에 예상치 못한 타입이 들어와 Type Error 를 뿜는 경우가 생긴다.

그러니 너무 편리함에만 의존하면 안정성 저하를 유발할 수 있다.




* Type System 에 따른 상속의 의미 차이


객체지향에서 중요한 개념 중에 하나가 다형성(Polymorphism) 이고,

일반적으로 다형성은 함수의 오버라이딩, 즉 동적 바인딩에 의한 것이다.


(1) 정적 타입(Static Type) 의 상속

: 코드 재사용 + 타입의 호환성 유지 를 목적으로 한다.

- 컴파일 시에 상속의 관계를 파악하여 상속관계에 있는 객체들 간의 타입 호환성을 유지해

타입은 컴파일 시에 결정되나 메소드 호출 시에 값에 따라 그 객체의 메소드를 호출하게 된다.

이와 같은 방법으로 동적 바인딩에 대한 문제를 해결했다고 할 수 있다.


(2) 동적 타입(Dynamic Type) 의 상속

: 코드 재사용 을 목적으로 한다.

- 타입 속성에 따라 메소드의 형태만 같으면 동적 바인딩을 유도할 수 있다.



간단하게 예시를 보면,

a.call();


정적 타입의 경우 :

컴파일 시에 a 객체의 타입에 호환될 수 있는 타입을 결정하고, 

런타임 시에 객체의 값에 따른 호환성 있는 객체의 메소드를 호출한다.

=> 즉, 상위 클래스의 코드 재사용과 동시에 타입의 호환성을 유지하는 목적을 가진다.


동적 타입의 경우 :

동적 타입 시스템에 의해 동적 바인딩이 자동적으로 유도되어 단지 상위 클래스의 코드를 상속받는 의미가 전부다.




바인딩이 일어나는 타이밍에 관련 포스팅 :

http://destiny738.tistory.com/178



휴.. 팔수록 어렵다 ㅠ_ㅠ


'Programming > C++' 카테고리의 다른 글

dynamic_cast 연산자  (0) 2014.10.26
.h 컴파일 : #ifndef vs. #pragma once  (0) 2014.08.25
by kelicia 2014. 8. 19. 11:25


01. 3D 그래픽의 이해



1. 3D 그래픽 파이프라인



1.1 게임 엔진을 구성하는 소스코드 모듈들

- User Input (사용자 입력)

- Resource Management (자원 관리)

- Loading and Rendering Graphics (그래픽 로딩과 렌더링)

- Interpreting and Executing Scripts (스크립트 해석과 실행)

- Playing Sound Effects (음향 처리)

- Artificial Intelligence (인공 지능)



1.4 좌표계

- Mesh (3차원 공간상의 객체) 를 기하학적으로 표현하기 위해선 좌표계가 필요하다.

- 2차원 좌표계(2차원 직교 좌표계, 화면(스크린) 좌표계), 3차원 좌표계(왼손 좌표계, 오른손 좌표계)

(출처 : http://msdn.microsoft.com/en-us/library/windows/apps/ff729721.aspx)


(출처 : http://blog.daum.net/jty71/15645437)



- 모델(or 지역) 좌표계와 월드 좌표계

- 모델 좌표계 : 객체의 지역적 공간(Local space)을 표현하는 좌표계(모델마다 별도의 좌표계를 갖고 있다고 가정)

- 월드 좌표계 : 게임 세계 전체를 하나의 통일된 좌표계로 표현하기 위한 좌표계(전역 좌표계)

(출처 : http://msdn.microsoft.com/en-us/library/windows/desktop/bb206365(v=vs.85).aspx)



1.5 와인딩 순서(Winding Order)

- Mesh 를 구성하는 다각형의 정점들을 나열하는 순서. 

즉, 다각형의 정점 or 모서리가 어떤 순서로 연결되는지를 나타냄.

- 은면(Back Face Culling : 카메라에서 보이지 않는 면) 제거를 수행하기 위해 사용한다.

- 시계 방향, 반시계 방향 순서가 있는데 Direct3D는 기본적으로 시계방향. (보통 반시계가 기본임)

Direct3D 기준으로 눈에 보이는 면들이 시계방향으로 와인딩 되기 때문에 
보이지 않는 면의 경우 반시계방향으로 와인딩 된다고 할 수 있다.

(출처 : http://cookiejeon.tistory.com/3)



1.6 화면 렌더링

- 화가의 알고리즘(Painter's Algorithm) : 3차원 세상을 2차원 평면에 그리는 과정이나 비효율적.

 자세한 내용은 위키백과.

http://ko.wikipedia.org/wiki/%ED%99%94%EA%B0%80_%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98 )





2. 변환 파이프라인


① 정점(지역 좌표계)

월드 변환 (World Transformation)

② 월드 좌표계

카메라 변환 (View, Camera Transformation)

③ 카메라 좌표계

------------------------------------------------ ↑ 3D, ↓2D 좌표

투영 변환 (Projection Transformation)

④ 투영 좌표계

화면 변환 (Screen Transformation)

⑤ 화면 좌표계



* 참고로 Primitive Transformation 에는 3가지 종류가 있다.

1) Translation (이동)   2) Rotation (회전)   3) Scaling (크기)

(관련 링크 : http://msdn.microsoft.com/en-us/library/windows/apps/ff729722.aspx)



# 월드 변환(World Transformation)

- 회전 변환 + 평행이동 변환을 통해 지역 좌표계로 표현된 객체의 Mesh 가 월드 좌표계로 변환되는 과정

(회전 변환 계산법 생략*), (회전을 먼저 하냐 평행을 먼저 하냐에 따라 결과가 다르다는 점 주의)

(출처 : http://goldface.tistory.com/archive/20120205)


# 카메라 변환(View, Camera Transformation)

- 월드 좌표계로 변환된 정점을 카메라 좌표계로 변환하는 것을 말한다.

- 3차원 공간이 투영되어 가상 카메라에 나타나는 2차원 평면을 카메라 평면이라 한다.

- 가상 카메라는 위치, 방향, FOV(Field of View) 와 같은 속성을 가진다.

※ FOV : 특정 방향과 특정 위치에서 어떤 물체가 보이는 지를 말한다. 

   사람의 경우 앞(Forward)을 향해 FOV를 가지고 있다. 그래서 자신의 뒤에 무엇이 있는지 볼 수 없다.

※ 화각(Viewing Angle) : 카메라에서 볼 수 있는 각도, 화각에 따라 FOV 공간의 형태가 달라진다.

아래 그림에서 Θ에 해당한다.


사람은 너무 가깝거나 or 너무 멀거나 하는 물체는 제대로 볼 수 없다.

그래서 컴퓨터 그래픽에서는 이 FOV 를 다음과 같이 View Frustum 으로 표현한다.


View Frustum 은 총 6개의 면으로 이루어져 있고 그 중 2 개는 XY 평면과 평행하다.

아래 그림에서 a 면이 Near-Z, b 면이 Far-Z 평면이라 불린다.

FOV 가 넓을수록 View Frustum 의 부피도 커지고 그만큼 시야가 넓어지는 것을 의미한다.


보통 좌표계에서 Z 축이 Forward 방향을 나타낸다. (X 축이 좌우, Y 축이 상하, Z 축이 앞뒤)

(출처 : http://msdn.microsoft.com/en-us/library/windows/apps/ff729721.aspx)

- 카메라 변환 과정

1) 카메라를 월드 좌표계의 원점으로 평행이동

2) 1)과 같은 변환을 게임 세계의 모든 객체에 적용

3) 카메라 좌표계 축들이 월드 좌표계 축들과 일치하도록 회전 변환

4) 3)과 같은 변환을 게임 세계의 모든 객체에 적용

(출처 : http://msdn.microsoft.com/en-us/library/windows/apps/ff729721.aspx)



# 투영 변환(Projection Transformation)

- 카메라 좌표계에서 카메라에 보이는 객체에 대하여 카메라와 객체까지의 거리는 기본적으로 Z 좌표로 근사할 수 있다.

- 카메라와 Mesh 사이의 Z 좌표가 증가할 때 메시의 각 정점 X, Y 좌표를 Z 좌표(ViewSpaceZ)의 z 값에 반비례하도록

변환하면 원근 효과를 나타낼 수 있다.

- 카메라 FOV 공간에 있는 정점들이 투영되는 공간은 투영 윈도우(Projection Window) 라고 한다.

-1 <= X <= 1, -1 <= Y <= 1 :: 카메라 FOV 공간에 포함된 정점들을 투영 변환했을 때 값들의 범위

(그외의 값을 갖는 점들은 카메라 FOV 공간에 포함되지 않아 보이지 않음)

- 투영 변환 :

X(projected) = x / ( z / d )

Y(projected) = y / ( z / d )

d 는 카메라에서 투영 평면까지의 거리를 의미한다.

d = 1 인 경우는 FOV 의 화각이 90도인 경우를 말한다. Direct3D의 경우 항상 1.0 의 값으로 설정.

- 쉽게 설명하자면,

투영 변환이란 3D 좌표 → 2D 좌표로 바꾸는 작업이다. 그러면 어떻게 바꾸냐?

FOV 의 화각이 90도 라고 했을 때(d=1),

(x, y, z) → (x/z, y/z, z/z) → (x/z, y,z, 1) 으로 바꿔버린다.

그러면 모든 정점들의 Z 좌표 값이 모두 1이 될 것이다. 

즉, 한 평면에 모든 정점들이 표현되고 이는 2D 좌표와 다를 것이 없다.


여기서 중요한 건 d=1 이라는 가정이다. 정확히는 z / (z/d) = 1 / d 가 되어

투영 변환된 Z좌표의 값은 0 <= Z <= 1 값을 갖게 될 것이다.

'그러면 2D가 아니지 않느냐?' 라고 생각할 수 있는데 왜 이렇게 되어야 하는 지는

Z-Buffer 얘기를 해야하는데 위에 '화가의 알고리즘' 관련 링크를 따라가 보면 알 수 있다 :-)



# 화면 변환(Screen Transformation)

- 투영 변환을 거친 정점은 2차원 좌표라고 생각할 수 있다.

이러한 2차원 좌표를 화면 좌표계로 변환하여 2차원 화면의 Pixel 로 그리는 단계.

- 렌더링할 대상의 화면 영역을 뷰포트(Viewport) 라고 한다.

(출처 : http://www.asksatyam.com/2011/01/window-to-viewporttransformation.html)


아무리 비율 좋은 Mesh 라고 한다고 해도 화면 비율에 맞게 렌더링 하다보면

위와 같은 현상이 나타날 수 있다. 그러니 다음과 같은 식을 이용한다.


- 픽셀 위치 좌표계 :

ScreenX = projVertex.x * (ViewportWidth / 2) + ViewportLeft + (ViewportWidth / 2)

ScreenY = - projVertex.y * (ViewportHeight / 2) + ViewportTop + (ViewportHeight /2)


ViewportLeft, ViewportTop : 뷰포트의 원점 위치

ViewportWidth, ViewportHeight : 뷰포트 가로, 세로 크기

※ 투영 좌표계는 좌표계 한가운데가 원점인 직교 좌표계이고, 

뷰포트는 왼쪽 상단이 원점인 좌표계이므로 Y 축의 방향이 서로 반대 방향이라 (-) 부호를 붙인다.




Transformation Pipeline 의 흐름을 잘 이해할 수 있는 이미지를 가져와봤다.

(출처 : https://forum.libcinder.org/topic/finding-an-object-s-screen-coordinates)



* 그 외 참조 :

http://code.msdn.microsoft.com/windowsapps/Direct3D-Tutorial-Win32-829979ef


by kelicia 2014. 7. 21. 21:11



실용주의 프로그래머

저자
앤드류 헌트, 데이비드 토머스 지음
출판사
인사이트 | 2014-03-28 출간
카테고리
컴퓨터/IT
책소개
The Pragmatic Programmer 숙련공에서 마스터로...
가격비교



코딩 호러 시리즈를 읽으면서 매우 자주 소개된 책이 2권있다.

하나는 조엘 시리즈, 다른 하나는 이 책이다.


이미 아주 예전에 출간되었으나 최근에 디자인이 인사이트 특유의 심플한 디자인으로

탈바꿈되서 새로 나왔다. 목차를 보니 크게 다른 점은 없었다. (페이지 수는 이게 조금더 많다)



다른 분들이 쓰신 책 서평을 보니 거의 다 칭찬일색인데...

에..뭐랄까... 내가 코딩 호러 시리즈에서 이 책에 대한 내용을 심하게

네타 당했는지 읽는 내내 '많이 봤던 내용들이네...?' 하면서 지루하더라.

그래서 진짜 겨우 읽었다. 머릿속에 잘 들어오지가 않아서 여러모로 아쉽다.


물론 아주 유명한 책인 만큼 공감할 수 있는 부분, 새롭게 깨달음을 얻는 부분들도 있었으나

저자님께서 Perl 을 무지 좋아하시는 것 같았다ㅋㅋㅋㅋㅋ

나는 Perl 을 잘 모르기 때문에 저자님께서 씡나게 Perl 얘기를 하면 지루....

'보이지 않는 이 거리감 어쩔거야 ㅋㅋㅋ' 라는 생각이 조금 들었다.



제길. 이거 먼저 읽고 코딩호러 시리즈를 읽었어야 하는데 ㅋㅋㅋㅋㅋㅋㅋ

리뷰를 써야되나 말아야되나 솔직히 지금 포스팅하고 있는 시점에서도 고민된다 ㅋㅋ


진짜 어디서 본 내용들 많이 나오더라.

깨진 유리창 이야기 부터 고무 오리 기법, select 는 망가졌어 등등

중복되는 내용은 대충 훌훌 읽었....ㅋ


막상 이렇게 시작부터 책을 까도 막상 리뷰 쓰다보면 엄청 써대니 잡소리는 여기까지 하겠다.




1. 실용주의 철학


'돌멩이 수프와 삶은 개구리' 부분은 재밌게 읽었다.

스토리는 조금 억지스럽지 않았나 싶기도 했지만 그로부터 얻는 교훈에서는 느낀 바가 없진 않다.


'지식 포트폴리오'

- 지식 포트폴리오를 만들라고 하는데 매우 공감한다. 

그렇기 때문에 나는 이 블로그를 개설했었다.

주로 프로그래밍 관련 포스팅만 해서 다각화가 조금 부족한 면이 있지만

확실히 나는 개발 관련 포스팅을 해놓고 필요할 때 다시 보는 경우가 굉장히 많다.

이렇게 반복학습을 하면서 더욱 그 내용을 상기시키게 되서 더욱 지식 자산을 견고히 쌓게 된다.


블로그 개설을 강요하는 건 아니지만 ㅡ_ㅡ; (하지만 제프 앳우드님은 블로그를 하라고 하셨지)

아무튼 이 책에는 지식 포트폴리오를 관리하는 가이드 라인이 소개 되어 있다.

1) 매년 새로운 언어를 최소 하나는 배워라.

2) 기술 서적을 분기마다 한 권씩 읽어라.

3) 비 기술 서적도 읽어라.

4) 수업을 들어라.

5) 지역 사용자 모임에 참여하라.

6) 다른 환경에서 실험해보라.

7) 요즘 흐름을 놓치지 마라.

8) 인터넷을 이용하라.


사실 회사 일에 치여 살다보면 지금 하고 있는 일과 관련없는 공부를 하기가 힘들다는 건 현실이다.

지친 심신을 위한 휴식도 중요하지만 휴식이 지나치지 않은가에 대해 경계할 필요가 있는 것 같다.

물론 나에게 해당되는 얘기다 ㅋ 너무 쉬기만 하면 머리가 급속도로 포맷이 되니까 ㅡ_ㅡ


아, 그리고 이 장에서 Guru 가 뭔지 대강 알게되었다.




2. 실용주의 접근법


'중복의 해악'

- DRY : Do NOT repeat yourself

책 읽다보면 DRY 가 정말 많이 나온다. 그만큼 중복을 피하라는 것을 강조한다.


'예광탄'

- 목표물을 찾기 위해 예광탄을 써라.


프로토타이핑 VS. 예광탄 코드 

* 프로토타이핑 : 최종 시스템의 어떤 특정한 측면을 탐사해보는 것이 목표다.

진짜 프로토타입 방식을 따른다면, 어떤 개념을 구현해 보려고 시도할 때 대충 끼워 맞춘 것들을

모두 버린 후, 실험 과정에서 얻은 교훈을 바탕으로 다시 코드를 만들게 된다.


* 예광탄 코드 : 문제에 대한 대응 방법이다.

'애플리케이션이 전체적으로 어떻게 연결되는지 알고 싶고,

사용자들에게 실제로 이 애플리케이션이 어떻게 상호작용하는지 보이고 싶고,

개발자들에게는 코드를 붙일 아키텍처적 골격을 제시하고 싶다.' 라고 생각하는 경우, 

대강 구현한 알고리즘과 단순하지만 동작은 하는 사용자 인터페이스로 구성된 예광탄을 만들 것이다.


프로토타입은 나중에 버릴 수 있는 코드를 만드는 것이고,

예광탄 코드는 기능은 별로 없지만 완결된 코드이며 최종 시스템 골격의 일부를 보인다.




3. 기본적인 도구


'일반 텍스트의 힘'

- 지식을 일반 텍스트로 저장하라.


* 단점 

1) 압축된 이진 포맷을 사용하는 것보다 더 많은 공간을 차지할 수 있고

2) 일반 텍스트 파일을 해석하고 처리하는데 더 많은 계산이 필요할 수 있다.


* 장점

1) 구식이 되는 것에 대한 보험

2) 호환성

3) 더 쉬운 테스트


장점이 단점을 다 덮고도 남는다고 강조하신다ㅎ

지식을 저장하는 최고의 포맷은 Plain Text 라고 하시면서.




4. 실용주의 편집증


'단정적 프로그래밍'

- 연습문제가 재미있길래 가져와봤다.


Q. 간단한 현실 점검. 다음 '불가능한' 것들 중 무엇이 실제로 일어날 수 있는가?

1. 한 달이 28일 보다 적은 것

2. stat(".", &sb) == -1 (즉, 현재 디렉터리에 접근할 수 없다)

3. C++ 에서 a = 2; b = 3; if ( a+b != 5 ) exit(1);

4. 내각의 합이 180도가 아닌 삼각형

5. 60초가 아닌 1분

6. 자바에서 (a+1) <= a


해답

1. 1752년의 10월은 19일 밖에 없다. 그레고리 교황의 달력 개혁의 일부로

달력 간의 날짜를 맞추기 위해서 이런 일이 생겼다고 한다.


2. 다른 프로세스가 디렉토리를 없앴거나 디렉토리를 읽을 퍼미션이 없을 수 있다. 또는 &sb가 잘못 되거나.


3. 함정. (a 와 b 의 자료형을 명시하지 않았기 때문에)

연산자 오버로딩 때문일수도 있고, 또는 a 와 b 가 동일한 변수의 참조 변수일 수도 있다.


4. 비유클리드 기하학에서 삼각형의 내각의 합은 180도 안 될 수도 있다.

구 표면에 그려진 삼각형을 생각해보자.


5. 윤분(leap minute)은 61초나 62초일 수도 있다.


6. 오버플로 때문에 a+1 값이 음수가 될 수도 있다.



'리소스 사용의 균형'

- 기억에 남는 연습문제가 있었다.


Q. 일부 C 개발자와 C++ 개발자들은 어떤 포인터가 가리키는 메모리의 할당을 해제한 다음에는

반드시 그 포인터가 NULL 을 가리키게 하곤 한다. 왜 이것이 좋은 생각일까?


해답

대부분의 C나 C++ 구현에서는 어떤 포인터가 정말 유효한 메모리를 가리키는지 확인할 방법이 없다.

어떤 메모리 영역의 할당을 해제한 다음에 프로그램의 나중 부분에서 그것을 참조하는 잘못은

자주 일어난다. 그때쯤이면, 가리키는 메모리는 다른 목적을 위해 재할당되어 있을 수도 있다.


프로그래머는 포인터를 NULL 로 맞추어 놓음으로써 이런 잘못된 참조를 하지 않을 수 있기를 기대한다.

대부분의 경우 NULL 포인터를 참조하는 것은 런타임 에러를 발생하기 때문이다.

(비공개 포스팅에도 한번 언급했지만 NULL 포인터는 

일반적으로 '0' 이라는 값을 갖으며 유효한 참조나 메모리 주소를 가르키지 않는다)




5. 구부러지거나 부러지거나


'메타프로그래밍'

- 코드에는 추상화를, 메타데이터에는 세부 내용을.


메타데이터는 애플리케이션을 기술하는 모든 데이터로 보통 컴파일타임이 아닌 런타임에 접근, 사용된다.

메타데이터를 이용하여 반환 매개 변수, 사용자 선호사항, 설치 디렉터리와 같은

애플리케이션 설정 옵션을 기술하라. ex) 윈도우에서 .ini 확장자 파일




6. 코딩하는 동안 해야할 일들


'우연에 맡기는 프로그래밍'

- 우연에 맡기는 프로그래밍을 하지 말라.


휴... 왠지 이 파트를 읽으면서 나도 모르게 반성하게 되었다.

애초에 시작부터 우연에 맡기는 프로그래밍을 하는 것도 큰 잘못이고 어리석은 짓이나..

내 경우에는 조금 다르다.


코딩을 하다가 내가 생각했던 방식대로 계속 잘 안 되면 다른 방법을 찾게 된다.

다른 방법 역시 뭔가 계속 안 되면 나는 멘붕에 빠지기 시작하면서 짜증 지수가 최고조로 급상승.


결국 폭발하면 반드시 되게끔 만들어보이겠다는 오기가 생기기 시작해

온갖 수단과 방법을 가리지 않고(?) 마구잡이로 덤벼든다. 

생각해보면 이 과정은 우연에 맡기는 프로그래밍과 크게 다를 바 없다.

안 되니까 될 때까지 미친 애마냥 이거저거 막 찔러보는......


이래서 냉정과 침착 (=멘탈甲) 이 필요하다.



'리팩터링'

- 언제 리팩터링을 해야할까?

1) 중복(DRY)    2) 직교성이 좋지 않은 설계    3) 유효기간이 끝난 지식    4) 성능


연습문제가 3문제 있는데 모두 풀어볼 만한 흥미로운 문제였다.

풀면서 느낀 건 디자인 패턴 공부를 해놓은게 확실히 도움이 된다.

'읽기 좋은 코드가 좋은 코드다' 라는 책도 풀다가 중간에 생각날 정도로 도움이 됐다.




7. 프로젝트 전에


'요구사항의 구렁텅이'

- 요구사항을 수집하지 말고 채굴하라.


ㅋㅋㅋㅋ... 이 파트 읽으면서 설마 객체지향 수업시간에 징하게 배웠던

Use-Case 가 나올 줄이야 ㅋㅋㅋㅋㅋ 심지어 UML 도 나와서 좀 웃겼다.

'와, 이게 실제로 쓰이긴 쓰이나 보구나....' 싶었다.

개인적으로 Use-Case 작성하는 것에 대해 >매우< 스트레스 받는다ㅋㅋㅋ


그리고 요구사항을 수집하지 말고 채굴하라고 하는데... 맞는 얘기다.

실제로 내가 인턴했을 때 전달 받은 요구사항에 대한 문서들을 모아 잘 정리해서 

내 나름대로 코딩을 하고 있었다. (문서 중간에 조금 의심스러운 부분이 있었음에도 불구하고)

그런데 중간에 요구사항이 변경되는 바람에... 내가 우려했었던 그 부분에 대한 코드를 통째로 날렸다 ^^ㅋ


그러니 수집하지 말자. 채굴하자. 정말 쌀알만한 한 점의 의심스러운 부분이라도 캐내자.




8. 실용주의 프로젝트


'결국은 모두 글쓰기'

- 아무리 흐린 먹물이라도 가장 훌륭한 기억력보다 낫다.


진짜... 저 말에 매우매우매우 10000% 동의한다.

특히 나는 일주일도 안 되서 내가 전에 무엇을 했었는지 기억을 잘 못한다. ㅠ_ㅠ

그래서 혹시라도 까먹을까봐 불안해서 핸드폰이나 주변에 잘 보는 곳에 기록을 남긴다.


이는 개발할 때도 마찬가지다. 예를 들어 소스 코드 주석.

책에서 JavaDoc 도구가 제안하는 주석의 수준을 하나의 예를 들어 보여주는데 훌륭했다.

그리고 적절한 주석이 제자리에 있으면 JavaDoc 이나 DOC++ 같은 도구가 API 수준의 문서를

자동으로 추출, 포맷까지 해준다고 한다. 한번 해볼 가치가 있다고 느꼈다.


나의 경험을 비추어 봤을 때... 

인턴을 하면서 내가 분명히 무슨 이유가 있어서 어떤 코드를 작성을 했는데

대리님께서 그 코드를 보고 이거 누가했냐면서 왜 이렇게 해놓았냐고 약간 짜증이 섞인 말로 물어보셨다.


그래서 내가 한 거라고는 밝혔는데 문제는 왜 그랬었는지 내가 기억을 못 했다 ! ! ! ! (real 상황이었음)

지금 생각만해도 정말 절망스러웠다....ㅋㅋㅋㅋㅋ...

거의 한소리 듣기 일보 직전에 내 사수님께서 그 이유를 기억하셔서 잘 설명해주셨고,

이유가 잘 먹혀서(?) 결국 그 코드는 보존하게 되었다. 


Aㅏ, 정말.... 주석....

잘 달아놓자 ㅠ_ㅠ.............!


그리고 공부한 내용은 잘 정리해서 기록에 남기자. 나중에 진짜 다시 찾아보게 된다.



'오만과 편견'

- 자신의 작품에 서명하라.


마지막 파트라서 그런가, 꽤 중요한 내용이라고 생각된다.

'내가 이걸 만들었고, 내 작품의 품질을 보증합니다' 라는 뜻의 서명.

품질의 보증수표 ㅋㅋㅋㅋ 마치 화가들이 자신의 작품에 서명하듯이.


그러고보니 인턴할 때 누군가의 코드를 보고 있었는데

가끔가다 주석에 닉네임 같은 것이 적혀있었다. 

그걸보고 '누군지 몰라도 꽤 자신이 있나보다..' 라는 생각을 하게 되었다.

사실 자신이 있는 것도 있는 거지만 그만큼 자기 코드에 대해 책임을 지겠다는 뜻인데.


나는 아직 초보 개발자여서 내 코드에 대한 자신이 없기때문에 사실 지금은 서명하는 게 조금 두렵다.

더 솔직히 까발리자면(?) 누군가에게 지적받는 게 두려운 것 같다.


초보 개발자이든 뭐든 간에 맡은 일을 하다가 지적받을 수도 있는거고,

'받아들일 건 받아들이자' 면서 머리 속으로도 쿨하게 넘기려고 하는데도

막상 지적받으면 스스로가 창피하고 뭔가 굴욕적? 이다 ㅋㅋㅋㅋ 이러면 안되는데.


좀 더 덤덤하게 철판을 깔고 더 배운다는 자세로 내 흔적을 남겨야 할텐데. ㅋㅋㅋ

아니면 지적도 못 하게 완벽하게 코드를 짜든가. (실질적으로 이건 불가능)


쩝. 아무튼 책임 회피를 하는 것 만큼 최악인 것도 없으니

내 개인의 창피함 보다는 책임감을 좀 더 중요시 여기려고 노력해야겠다.




역시 리뷰 쓰다보니 앞에 지루하다고 투덜댈 때는 언제고 마구 쓰게 된다ㅋ

가끔 기록 강박증이 있는 건가 스스로 의구심이 들 때가 있지만 아직 그 단계까지는 아닌듯.


나는 좀 글을 써야된다. 평소에 너무 안 쓰니까 어휘력도 딸리고 표현력도 딸리고 ㅋㅋㅋㅋㅋ orz

다음엔 조엘 시리즈 ㄱㄱ ~


by kelicia 2014. 7. 4. 01:54

불타오르는 프로그래밍 트렌드 15가지, 그리고 식어가는 트렌드 15가지

Peter Wayner | InfoWorld

프로그래머들은 시시각각 유행이 바뀌는 패션업계를 비웃기 좋아한다. 치마 길이도 올라갔다 내려갔다 바뀌고 색상 유행도 항상 바뀌고, 넥타이도 두꺼워졌다 얇아졌다 항상 바뀌곤 한다. 하지만 기술업계에서는 기술, 엄밀성, 과학, 수학, 정밀성이 유행보다 더욱 중요하다.

그렇다고 해도 프로그래밍에 유행이란게 존재하지 않는 것은 아니다. 차이점이라면 프로그래밍 트렌드는 효율성, 증가된 커스터마이징, 사용 편의성에 의해 주도된다는 정도다. 이런 요소들을 한가지 이상 제공하는 신기술은 이전 세대를 완전히 갈아치운다. 그래서 그냥 엉뚱히 나오는게 아니라 그럴만한 이유가 있는 유행이다.

다음은 요즘 프로그래머들 사이에 지금 떠오르는 유행과 식어가는 유행 목록이다. 여기 소개된 목록에 대해서 모두가 동의하지 않을 수 있다. 하지만 그 점이 바로 빠르게 변하고, 열정적인 토론이 일어나고, 갑자기 재기하기도 하는 프로그래밍이라는 일의 매력이 아닐까?

뜬다: 전처리기
진다: 풀 랭귀지 스택(Full language stacks)


얼마 전까지 만해도 새로운 프로그래밍 언어를 개발하려면 칩에 맞춰 코드를 비트로 바꾸는 모든 것들을 새로 만들어야 했다. 그러던 중에 어떤 이가 이전 작업들 위에 그대로 편승할 수 있다는 점을 알아냈다. 그 결과 이제 똑똑한 아이디어를 가진 사람들은 풍부한 라이브러리와 API를 갖추고 새로운 코드를 예전 형태로 번역하는 전처리기(preprocessor)만 만들면 된다.

그런 식으로 다이나믹 타이핑(dynamic typing)을 좋아하는 이들은 과도하게 엄격한 구두법이 없는 단순한 자바 버전인 그루비(Groovy)를 만들었다. 자바스크립트(JavaScript)를 고치고 싶어했던 이들은 역시 부담스러운 구문법 없이 코딩할 수 있게 해주는 전처리기인 커피스크립트(CoffeeScript)를 만들었다. JVM상에서 실행되는 클로주어(Clojure)나 스칼라(Scala)같은 십여 개의 언어들이 있지만, JVM은 하나뿐이다. 바퀴는 다시 발명할 필요가 없지 않나?

뜬다: 자바스크립트 MV*프레임워크
진다: 자바스크립트 파일


오래 전, 모든 이들은 알림 상자를 띄우거나 이메일 주소에 @ 표시를 포함시키기 위해 자바스크립트를 배웠다. 이제는 HTML AJAX 앱이 아주 정교해져서 맨땅에서 시작하는 사람은 거의 없다. 정교한 프레임워크를 선택해 비즈니스 로직을 실행하는 글루 코드를 조금 작성하는 것이 더 간편하다. 켄도(Kendo), 센차(Sencha), 제이쿼리 모바일(jQuery Mobile), 앵귤러JS(AngularJS), 엠버(Ember), 백본(Backbone), 미티어 JS(Meteor JS)같은 십여 가지 프레임워크가 있는데, 이 모두가 웹 앱과 페이지의 이벤트, 컨텐츠를 잘 처리해 준다.

뜬다: CSS 프레임워크
진다: 제네릭 폭포수 스타일 시트(Generic Cascading Style Sheets)


과거에는 웹 페이지를 화려하게 꾸민다는 것이 CSS 파일을 열어 'font-style:italic' 같은 명령어를 사용하는 정도였다. 그렇게 힘든 아침 업무를 마치고 파일을 저장한 후 점심을 먹으러 가면 됐다. 그러나 이제 웹 페이지들은 너무나도 세련돼, 그런 단순 명령으로 꾸미는 것이 불가능해졌다. 색깔 하나만 바꿔도 모든 것이 다 엉클어진다. 마치 공동 운명체나 생태계처럼 모든게 연결돼 있다.

그런 부분에서 SASS와 그 사촌격인 컴파스(Compass)같은 CSS 프레임워크의 입지가 탄탄하다. 이들은 실변수, 내포화 블록, 믹스-인같은 프로그래밍 구조를 제공해 문법에 맞으면서도 안정적인 코딩을 도와준다. 프로그래밍 측면에서는 새롭게 들리지 않을 수도 있지만, 디자인 측면에서는 매우 큰 진보다.

뜬다: 캔버스상의 SVG + 자바스크립트
진다: 플래시


오랫동안 플래시는 사람들을 미치게 만들어왔지만, 아티스트들은 언제나 그 결과물에 만족해했다. 외곽선이 매끄럽게 처리된 렌더링은 매우 훌륭하기 때문에 많은 재능 있는 아티스트들은 세련된 결과물을 얻기 위해 플래시 기술을 폭넓게 사용해왔다.

그러나 이제 자바스크립트 레이어도 그 정도를 지원하게 되면서, 브라우저 제조사와 개발자들은 플래시의 종말을 기대할 수 있게 됐다. 이들은 SVG(Scalable Vector Graphics)같은 새로운 포맷은 DOM 레이어와 더 깊게 통합된다. SVG와 HTML은 하나의 큰 태그 파일을 구성하는데, 이는 웹 개발자들이 쓰기에 더 간편한 경우가 많다. 또한, 캔버스(Canvas) 객체에 세밀한 그림 그리기가 가능한 API들이 많고 비디오 카드의 지원도 받을 수 있다. 이들을 사용하면 더는 플래시를 쓸 이유가 없다.

뜬다: 거의 빅 데이터(하둡 없는 분석)
진다: 빅 데이터(하둡과 함께)


누구나 대학에서 중요한 인물이 되고 싶어한다. 그러나 상황이 여의치 않다면 자신이 충분히 돋보일 수 있는 적당한 수준의 대학을 찾게 된다. 마찬가지다. '빅 데이터'라는 단어가 중역 회의실에서 처음 흘러나오기 시작했을 때 이들이 마치 요트를 사거나 초고층 빌딩을 짓는 것처럼 가장 강력한 빅데이터 시스템을 찾는 일이 놀라운 것은 아니다.

재미있는 점은, 많은 문제가 빅 데이터 솔루션이 필요할 만큼 그리 큰 일이 아니라는 사실이다. 물론 구글이나 야후같은 기업들은 우리의 모든 웹 브라우징을 추적하고, 페타바이트나 요타바이트급 데이터 파일들을 보유하고 있다. 하지만 대부분의 회사들은 기본 PC의 RAM 정도면 충분할 만한 작은 데이터세트를 가지고 있다. 필자는 16GB RAM이 장착된 PC에서 지금 기사를 쓰고 있는데 이는 상당량의 바이트와 수십억 개의 이벤트를 담기에 충분하다. 대부분의 알고리즘에서 데이터를 SSD에서 스트리밍하기 때문에 메모리에 읽힐 필요가 없다.

병렬로 실행되는 하둡 클라우드 내의 십여 대의 기계의 빠른 응답시간을 필요로 하는 인스턴스들이 있겠지만, 대부분은 협업이나 커뮤니케이션을 신경 쓰지 않고 단일 기기상에서의 플러깅만으로도 충분할 것이다.

뜬다: 게임 프레임워크
진다: 네이티브 게임 개발


한때 게임 개발은 C에 있어서 모든 것을 백지에서부터 시작할 수 있는 개발자들을 충분히 채용하는 것을 의미했다. 물론 엄청난 돈이 들지만 보기에는 좋아 보이니까. 그러나 이제 어느 누구도 커스텀 코드를 감당할 만큼 사치를 부릴 수가 없게 되었다. 대부분의 게임 개발자는 오래 전에 자존심을 버리고 유니티(Unity), 코로나(Corona), 립GDX(LibGDX)같은 라이브러리를 활용해 개발하기 시작했다. 이들은 라이브러리의 인스트럭션만큼 C 코드를 작성하지 않는다. 우리의 즐기는 게임들이 자존심을 걸고 제작되지 않고 똑같은 엔진을 달고 찍혀나왔다는데 실망해야 할까? 오히려 대부분의 개발자는 그 세부내역과 씨름하지 않아도 돼서 한숨 돌리고, 게임 플레이, 나레이션, 캐릭터, 아트 부분에 집중할 수 있게 됐다.

뜬다: 단일-페이지 웹 앱
진다: 웹사이트


웹 페이지가 고정 텍스트와 이미지로 가득 찼던 시절을 기억하는가? 모든 정보를 웹 사이트라고 불리는 별개의 웹 페이지의 네트워크 안에 모두 담는 게 얼마나 간편하면서도 진기한 일인가. 새로운 웹 앱들은 컨텐츠로 채워진 대규모 데이터베이스의 얼굴이다.

웹 앱이 정보를 원할 때는, 그 정보를 데이터베이스에서 끌어와 로컬 몰드에 쏟아 붓는다. 웹 페이지를 구축하는데 필요한 모든 웹 기타요소들로 데이터를 교정 볼 필요도 없다. 데이터 레이어는 프레젠테이션과 포매팅 레이어와 완전히 별개다. 여기에다 모바일 컴퓨팅의 부상 역시 또 하나의 요소다: 앱처럼 작동하는 단일의 호응적으로 설계된 웹페이지는 앱스토어의 모든 혼잡으로부터 벗어나기 안성맞춤이다.

뜬다: 모바일 웹 앱
진다: 네이티브 모바일 앱


어떤 모바일 컨텐츠에 대해 훌륭한 아이디어가 있다고 가정해보자. 그 아이디어를 기반으로 iOS, 안드로이드, 윈도우 8, 어쩌면 블랙베리 OS까지 별개 버전으로 개발할 수 있을 것이다. 그 각 OS마다 다른 언어로 작업하는 별개의 팀이 필요하다. 그리고 각각 플랫폼의 앱스토어마다 앱이 사용자들에게 모습을 드러낼 수 있게 되기까지 엄청난 노력이 들어간다.

아니면 그냥 하나의 HTML 앱을 만들고 이를 모든 플랫폼에서 실행되도록 웹사이트에 올려도 된다. 만약 변경사항이 있더라도 앱스토어로 가서 빠른 검토와 버그 수정을 요청할 필요도 없다. 이제 HTML 레이어가 더 빨라지고 있으며 더 빠른 칩에서 실행됨에 따라, 이런 접근방식은 더 복잡하고 상호 소통적인 앱에서도 네이티브앱과 경쟁할 수 있게 되었다.


뜬다: 안드로이드
진다: iOS


불과 몇 년 전만 해도 이런 말을 애플스토어를 보고 이런 말을 할 수 있었을까? 시대는 바뀐다. 아이폰과 아이패드가 애플의 풍부하고 세련된 유저 인터페이스를 선호하는 열성 팬들을 계속 보유하게 만들고 있지만, 단순 판매량만 비교하면 안드로이드가 점점 더 늘어나고 있다. 안드로이드 휴대폰이 전체 판매량의 70%를 넘어선다는 보고도 있다.

이유는 단순하다. 가격 때문일 것이다. iOS 기기들이 높은 가격대를 유지하는 반면, 안드로이드 기기들은 막대한 경쟁으로 인해 가격대가 낮게 형성되었고, 태블릿같은 경우 애플 제품의 1/5 가격대도 있다. 그만큼의 가격경쟁력의 매력이 있다.

하지만 또 다른 요소는 오픈소스의 효과일 것이다. 누구든지 시장에서 겨룰 수 있게 됐고 실제로 그렇다. 큰 안드로이드 태블릿도 있고 작은 태블릿도 있다. 안드로이드 카메라와 심지어 안드로이드 냉장고도 있다. 누구도 혁신에 대해 구글에 문의할 필요가 없다. 아이디어가 있으면 그냥 실행하면 된다.

뜬다: GPU
진다: CPU


소프트웨어가 단순하고 설명이 깔끔하게 한 줄로 표시되었을 때에는 CPU가 어려운 작업을 수행했기 때문에 컴퓨터의 핵심이었다. 이제 비디오 게임들에는 병렬로 실행되는 확장적인 그래픽 루틴으로 가득 채워져 있는데, 비디오카드가 그 실행을 담당한다. 멋진 비디오카드에 500달러, 600달러 이상씩 쓰기도 쉬운데, 몇몇 심각한 게임광들은 그 이상도 쓴다. 이는 기본형 데스크톱 가격의 두 배가 넘는 금액이다. 게이머들만 GPU 카드를 자랑하는게 아니다. 컴퓨터 과학자들도 요즘에는 많은 병렬 애플리케이션을 변환시켜 GPU상에서 수백 배 빠르게 실행시킨다.

뜬다: GitHub
진다: Resumes


물론 중학교 체스 동아리 부회장같은 경력을 포함시켜 화려하게 꾸며진 이력서로 그 사람에 대해 알 수 있을 것이다. 하지만 누군가의 실제 코드를 읽는 것은 훨씬 더 풍부하고 유익하다. 유용한 메모를 남겨 놓았나? 별 쓸데없는 걸 작게 나누는데 너무 많은 시간을 허비했나? 확장을 위한 실질적 아키텍쳐가 있나? 이런 모든 질문들에 대한 궁금증은 코드를 보면 풀린다. 이는 오픈소스 프로젝트 참여가 점점 구직에 중요해지고 있는 이유이기도 하다. 상용 프로젝트에서 코드 공유는 어렵지만, 오픈소스 코드는 어디든 갈 수 있다.

뜬다: 임대 (Renting)
진다: 구매 (Buying)


아마존(Amazon)이 추수감사절 쇼핑기간 동안 컴퓨터와 전자제품 판매치를 공개했을 때, 아마존은 그들의 자랑할만한 클라우드 거래 내역은 포함시키지 않았다. 얼마전만해도 회사들은 그들 자체 데이터센터를 마련해 그들이 구매한 컴퓨터를 구동할 자체 직원을 채용했다. 이제 회사들은 컴퓨터, 직원, 심지어 소프트웨어까지도 시간 별로 임대한다. 어느 누구도 구매하는 번거로움을 원하지 않는다. 웹사이트가 소문이 나고 클릭 별로 모든 가격이 매겨진다는 것을 인식할 때까지는 다 좋은 아이디어다. 이제 아마존이 클라우드를 드론으로 배달하는 방법만 찾게 된다면, 이 트렌드가 본격화될 것이다.

뜬다: 웹 인터페이스
진다: IDE


오래 전, 사람들은 명령행 컴파일러를 사용했다. 그리고 누군가 이를 편집기 등의 도구와 통합해 IDE를 만들어냈다. 이제 IDE의 시대마저 작동중인 시스템 코드 편집까지도 가능한 브라우저 기반 툴에 의해 대체되고 있다.

예를 들어 워드프레스(WordPress)의 작동 방식이 마음에 들지 않는다면, 워드프레스의 내장 편집기를 사용해 즉석에서 코드를 수정할 수 있다. 마이크로소프트의 애저(Azure)는 자바스크립트 글루 코드를 자체 포털에 바로 쓸 수 있게 지원한다. 이런 시스템들은 최선의 디버깅 환경을 제공하지는 않으며, 생산 코드 편집에 따른 위험성도 존재하지만, 아이디어 자체는 관심 있게 볼 필요가 있다.

뜬다: Node.js
진다: JavaEE, PHP, 루비 온 레일즈


서버 세계에서는 언제나 운영체제가 프로그래머들의 모든 고집불통, 비효율적, 혹은 방종한 행태까지도 마음껏 할 수 있게 해주는 스레드 모델을 잘 다뤄왔다. 바보 같은 루프나 낭비적인 소비 연산 코드라도 운영체제가 스레드 사이의 변환으로 성능 균형을 맞췄다.

그때 Node.js는 프로그래밍의 자바스크립트 콜백(Callback) 모델과 함께 발맞췄고, 코드가 한때 알림 상자에서만 사용되었던 장난감 언어(Toy Language)에서 가능하게 되어 기대했던 것보다도 더 빠르게 실행되었다. 갑자기 새로운 스레드 생성의 간접비용이 명백해지고, Node.js가 떠올랐다. 프로그래머들이 제대로 행동하지 않을 때 문제가 발생하지만, 그 책임감은 대부분 긍정적으로 작용하게 된다. 자원 제약을 프로그래머에게 분명하게 하는 것이 보통 더 빠른 코드 생성을 가져온다.


Node.js 역시 브라우저와 서버 사이의 조화 제공으로 혜택을 받는다. 양쪽에서 동일 코드가 실행되어 개발자들의 기능 사용과 복제가 쉬워진다. 그 결과 Node.js 레이어는 인터넷에서 가장 뜨거운 화제가 됐다.

뜬다: 해커스페이스
진다: 대학


4년간 25만달러까지 내는 대학도 있다. 어떤 곳은 미리 큰 할인으로 월 50달러만 받는다. 어떤 대학은 미식축구 경기장, 총장을 위한 멋진 저택, 호화스러운 기숙사, 4색 잡지 등에 돈을 쓴다. 어떤 대학은 3D 프린터, 오실로스코프, 납땜 인두 등을 산다.

해커스페이스(Hackerspaces)는 대학 산학 단지의 막대한 간접비용 없이 혁신을 육성하고 있다. 이들은 관료제나 에머슨(Emerson)이 말한 틀에 박힌 “편협한 고정관념” 없이 창업을 확산시키고 부를 쌓는 사회적 네트워크를 만들고 있다. 강좌들은 한 학기 내내 끌지 않는다. 학생들은 배움을 위해 일년 전에 입학 원서를 낼 필요가 없다. 해커스페이스의 즉각적인 특성은 빠르게 움직이는 기술 세계에 더 잘 맞는다. 


editor@itworld.co.kr


출처 : http://www.itworld.co.kr/news/85553?page=0,0


오역이 많으나 읽어볼 만한 기사라고 생각한다.

특히 벌써 하둡이 진다는 말이 인상깊었다ㅋㅋ 

꽤 주목받는 기술이라 그래도 조금은 오래가지 않을까 했는데.


by kelicia 2014. 6. 6. 17:26


'Pattern' 이란 특정 컨텍스트 내에서 주어진 문제에 대한 해결책이다.


- 'Context' 란 패턴이 적용되는 상황을 뜻하고, 반복적으로 일어날 수 있는 상황이어야만 한다.

- 'Problem' 이란 이루고자 하는 목적을 뜻하며 제약조건도 포함된다.

- 'Solution' 이란 누구든지 적용해서 일련이 제약조건 내에서 목적을 달성할 수 있는 일반적인 디자인을 뜻한다.


※ 'Force' : Problem 이 목적과 제약조건으로 구성되는데, 이를 합쳐서 Force 라 한다.

Solution 이 Force 의 양면 사이에서 균형을 이룰 수 있어야만 제대로 된 패턴이 만들어진다.



# 1~11 장 까지 배웠던 패턴 복습 #

- Strategy

교환 가능한 행동을 캡슐화하고 위임을 통해서 어떤 행동을 사용할지 결정한다.

- Observer

상태가 변경되면 다른 객체들에게 연락을 돌릴 수 있게 해준다.

- Decorator

객체를 감싸서 새로운 행동을 제공한다.

- Factory Method

생성할 구상 클래스를 서브클래스에서 결정한다.

- Abstract Factory :

클라이언트에서 구상 클래스를 지정하지 않으면서도 일군의 객체를 생성할 수 있도록 해준다.

- Singleton :

오직 하나의 객체만 생성되도록 한다.

- Command :

요청을 객체로 감싼다.

- Adapter

객체를 감싸서 다른 인터페이스를 제공한다.

- Facade

일련의 클래스에 대해서 간단한 인터페이스를 제공한다.

- Template Method :

알고리즘의 개별 단계를 구현하는 방법을 서브클래스에서 결정한다.

- Iterator

컬렉션이 어떻게 구현되었는지 드러내지 않으면서 컬렉션 내에 있는 모든 객체에 대해

반복 작업을 처리할 수 있게 해준다.

- Composite :

클라이언트에서 객체 컬렉션과 개별 객체를 똑같이 다룰 수 있도록 해준다.

- State

상태를 기반으로 한 행동을 캡슐화한 다음 위임을 통해서 필요한 행동을 선택한다.

- Proxy :

객체를 감싸서 그 객체에 대한 접근을 제어한다.



* 디자인 패턴 분류하기

1) 생성 패턴(Creational pattern) :

객체 인스턴스 생성을 위한 패턴으로, 클라이언트와 그 클라이언트에서 생성해야 할

객체 인스턴스 사이의 연결을 끊어주는 패턴이다.

- Singleton, Factory Method, Abstract Factory


2) 행동 패턴(Behavioral pattern) :

클래스와 객체들이 상호작용하는 방법 및 역할을 분담하는 방법과 관련된 패턴이다.

- Observer, Command, Iterator, State, Strategy, Template Method


3) 구조 패턴(Structural pattern) :

클래스 및 객체들을 구성을 통해서 더 큰 구조로 만들 수 있게 해주는 것과 관련된 패턴이다.

- Adapter, Composite, Decorator, Facade, Proxy



* GoF (Gang of Four)

- 가장 훌륭한 패턴 카탈로그이자 디자인 패턴의 정석인

'Design Patterns : Element of Reusable Object-Oriented Software'를 

(한글판 이름은 'GoF 의 디자인 패턴 : Design Patterns'기술한 4인방 (Gang of Four) 을 가르키는 말이다.


- 에릭 감마(Erich Gamma), 리차드 헬름(Richard Helm), 랠프 존슨(Ralph Johnson),

존 블라사이즈(John Vlissides) 를 가르켜 GoF 라고 한다. 처음으로 패턴 카탈로그를 만드신 분들이다.


by kelicia 2014. 6. 5. 00:12


* Compound Pattern :

일반적으로 자주 생길 수 있는 문제를 해결하기 위한 용도로 

2개 이상의 패턴을 결합해서 사용하는 것을 뜻한다.



패턴 몇 개를 결합해서 쓴다고 해서 무조건 컴파운드 패턴이 되는 것은 아니다.

위의 정의에도 이미 언급했듯이 무엇을 위한 용도인지 확실히 이해하자.


진정한 컴파운드 패턴이라 할 수 있는 'MVC' 에 대해 알아보고,

이 MVC 를 웹 환경에 맞게 변형시킨 '모델 2 (Model 2)' 까지 살펴보겠다.


이 책을 공부하기 전까지 MVC 가 컴파운드 패턴인지도 몰랐다.

예전에 MVC 관련 포스팅을 한 적이 있지만 내가 무지했다는 기분을 떨쳐낼 수 없다ㅠ_ㅠ



1. MVC


MVC 는 잘 알다시피 Model - View - Controller 의 약자이다.


Model :

모든 데이터, 상태 및 어플리케이션 로직이 들어있다. View 와 Controller 에서 Model 의 상태를 조작하거나

가져오기 위한 인터페이스를 제공한다. 또한 Model 에서 자신의 상태 변화에 대해서 Observer 들한테 연락을

해주긴 하지만, 기본적으로 Model 은 View 및 Controller 에게 별 관심이 없다.

View :

Model 을 표현하는 방법을 제공한다. 일반적으로 화면에 표시하기 위해 필요한 상태 및 데이터는

Model 에서 직접 가져온다.

Controller :

사용자로부터 입력을 받아서 그것이 Model 에게 어떤 의미가 있는지 파악한다.



이 MVC 에는 어떤 패턴들이 결합되어 있는 형태인지 알아보자.


이미 앞 장에서 살펴본 패턴들이 눈에 띄는데 하나씩 살펴보겠다.



Model 이 Observable 에 해당하고, Model 의 상태가 바뀔 때마다 

Model 로부터 정보를 전달받고 싶은 녀석들이 Observer 에 해당한다.

이를 이용하면 Model 을 View 와 Controller 로부터 완전히 독립시킬 수 있다.


이 패턴에 대해 잘 모른다면 '2장 Observer 패턴'을 참고하자.



Controller 는 View 의 행동(Behavior)에 해당하며, 

View 가 다른 행동을 원한다면 간단하게 다른 Controller 로 교환하기만 하면 된다.


즉, Controller 가 전략을 제공하고 View 에서는 어플리케이션의 겉모습에만 신경쓰고

인터페이스의 행동에 대한 결정은 모두 Controller 에게 맡긴다.

이는 View 를 Model 로부터 분리시키는 데에 도움이 된다.


자세한 'Strategy 패턴'은 1장을 참고하자.



View 안에서는 내부적으로 Composite 패턴을 써서 윈도우, 패널, 버튼 같은 다양한 구성요소를 관리한다.

각 디스플레이 항목은 복합 객체(윈도우 등) 또는 잎(버튼)이 될 수 있다.


Controller 가 View 에게 화면을 갱신해달라고 요청할 때, 최상위 View 구성요소한테만

화면을 갱신하라고 요청하면 된다. 나머지는 Composite 패턴에 의해 자동으로 처리된다.


이해가 잘 안 된다면 'Composite 패턴'은 9장을 참고하자.



책에 예제 코드가 있긴하지만 포스팅하기엔 양이 많아 생략한다ㅡ_ㅡ

MVC 가 왜 진정한 Compound 패턴인지만 이해하기로 하자.




2. Model 2


MVC 를 브라우저/서버 모델에 맞게 변형시켜서 사용하고는 하는데,

가장 많이 쓰이는 방법이 '모델 2 (Model 2)' 이다.


어떤 식으로 돌아가는 지 살펴보자.


① HTTP 요청

보통 사용자 ID, 비밀번호와 같은 Form 데이터가 함께 서블릿으로 전달된다.

서블릿에서는 이러한 데이터를 받아 Parsing 한다.


② Servlet 이 Controller 역할을 한다.

사용자 요청을 처리하고 대부분의 경우에 모델(보통 DB)에 어떤 요청을 하게 된다.

요청을 처리한 결과는 일반적으로 자바빈(JavaBean) 형태로 포장된다.


③ Controller 는 컨트롤을 View 에게 넘긴다.

View 는 JSP 에 의해 표현된다. JSP 에서는 (④ 자바빈을 통해 얻은) 모델의 View 를

나타내는 페이지만 만들어주면 된다. 물론 다음 단계를 위해 몇 가지 제어해야 할 일이 있을 수도 있다.


⑤ View 에서 HTTP 를 통해 웹 브라우저에게 페이지를 전달한다.



- Model 2 는 단지 깔끔한 디자인에 불과한 것이 아니다 -

디자인적인 면에서 Model, View, Controller 를 분리시켜줄 뿐만이 아니라

제작 책임까지도 분리시켜줄 수 있다.

Model 2 가 등장하면서 개발자들은 Servlet 에만 전념하면 되고,

웹 제작자들은 간단한 Model 2 스타일의 JSP 만 다루면 되는 환경이 조성되었다.

그래서 웹 제작자들은 HTML 과 간단한 JavaBeans 만 건드리면 된다.



* Design Patterns 과 Model 2

- 모델 2 는 MVC 를 웹에 맞게 적응시킨 것이다. 

비록 모델 2 가 MVC 와 똑같이 생긴 것은 아니나 여전히 MVC 의 핵심 요소들을 포함하고 있다.


Observer 패턴

View 는 더 이상 Model 의 Observer 라 할 수 없다. 

Model 한테 등록해서 Model 의 상태가 바뀌었다는 연락을 받는다거나 하지 않기 때문이다. 

하지만 Controller 가 빈(Bean)을 건네주는 덕분에 Model 의 상태가 바뀐 것을 간접적으로 연락을 받는다.

View 에서는 브라우저로 HTTP 응답을 할 때만 Model 의 상태 정보가 필요하기 때문에

HTTP 응답을 하지 않는 상태에서 Model 로부터 연락을 받아봤자 할 일이 없다.


Strategy 패턴

고전적인 MVC 처럼 View 객체에 Controller 객체에 대한 레퍼런스가 들어가는 방식으로 구현되지 않는다.

하지만 여전히 (Servlet 으로 만든) Controller 가 View 의 행동을 구현하는 전략 객체로 쓰이고,

다른 행동을 원할 때 다른 Controller 로 바꿀 수 있다.


Composite 패턴

HTML 코드를 통해서 웹 브라우저에 렌더링된다는 차이점은 있지만 

결국은 여기에서 쓰이는 View 도 중첩된 그래픽 구성요소로 이루어진다.




* 객체지향의 기초 :

1) 추상화    2) 캡슐화    3) 다형성    4) 상속



* 객체지향의 원칙 :

1) 바뀌는 부분은 캡슐화 한다.

2) 상속보다는 구성을 활용한다.

3) 구현이 아닌 인터페이스에 맞춰서 프로그래밍 한다.

4) 서로 상호작용을 하는 객체 사이에서는 가능하면 느슨하게 결합하는 디자인을 사용해야 한다.

5) 클래스는 확장에 대해서는 열려 있어야 하지만 코드 변경에 대해서는 닫혀 있어야 한다(OCP).

6) 추상화된 것에 의존해라. 구상 클래스에 의존해서는 안 된다(의존성 뒤집기 법칙).

7) 친한 친구들하고만 이야기한다(최소 지식 원칙).

8) 먼저 연락하지 마세요. 저희가 연락 드리겠습니다(헐리우드 원칙).

9) 어떤 클래스가 바뀌게 되는 이유는 한 가지 뿐이어야만 한다(단일 역할 원칙).



* 이 장에서의 정리 :

- MVC 패턴은 Observer, Strategy, Composite 패턴으로 이루어진 Compound 패턴이다.

- Model 에서는 Observer 패턴을 이용해 옵저버들에 대한 의존성은 없애고, 옵저버들에게

  자신의 상태가 변경되었음을 알릴 수 있다.

- View 에서는 Composite 패턴을 이용해 사용자 인터페이스를 구현한다. 

  보통 패널이나 프레임, 버튼과 같은 중첩된 구성요소로 구성된다.

- Controller 는 Strategy 패턴을 이용해 View 에 대한 전략 객체가 된다.

  View 에서는 Controller 를 바꾸기만 하면 다른 행동을 활용할 수 있다.

- MVC 는 이 3 가지 패턴을 통해 서로 연결된다. 

  느슨하게 결합되기 때문에 깔끔하면서도 유연하게 구현할 수 있다.

- 새로운 Model 을 기존의 View 및 Controller 하고 연결해서 쓸 때는 Adapter 패턴을 활용하자.

- Model 2 는 MVC 를 웹 어플리케이션에 맞게 적용한 디자인이라 할 수 있다.



(이미지 출처 :

http://www.07net01.com/linux/Head_First_Design_Patterns_Notes_286645_1367843500.html

http://stackoverflow.com/questions/5217611/the-mvc-pattern-and-swing)


by kelicia 2014. 6. 3. 17:27
| 1 2 3 4 5 6 |