'전산'에 해당되는 글 136

  1. 2011/03/16 로우레벨 (2)
  2. 2010/11/05 디스크... (2)
  3. 2010/06/26 TIOBE Index 2010
  4. 2010/05/04 Mercurial 에서의 branching (6)
  5. 2010/04/16 AlienBrain -> Mercurial 이주기
  6. 2010/03/25 너티독, 그리고 여행의 기록 (2)
  7. 2010/02/09 LUA 를 이용한 RPC
  8. 2009/09/11 lock-free 와 최적화 (9)
  9. 2009/09/09 volatile 과 memory barrier (2)
  10. 2009/09/07 TDD (4)

로우레벨

전산 2011/03/16 01:12
트윗에서 지인 프로그래머들 사이에 최근 C/C++ 프로그래머들이 로우레벨을 너무 모른다는 한탄이 오간걸 보니 예전에 MSDN Magazine 에서 본 기사가 떠오른다.

...
 
다음 질문은 많은 사람이 어려워하는 포인터에 대한 것입니다.

Q : 아직도 포인터(var, object, functional)를 잘 이해하지 못했습니다. 설명을 해 주시거나 공부할 자료를 보내 주실 수 있나요?
C++를 처음 배우고 있으며 포인터가 무엇이고 어떻게 사용되는지 궁금합니다. 많은 책을 보았지만 너무 복잡하게 설명되어 있습니다. 포인터란 특정한 메모리 위치를 가리키는 것으로 알고 있는데 이런 개념이 왜 필요한지 모르겠습니다. 아마도 컴퓨터가 각 위치를 자동으로 추적하려는 것일까요? 답변 부탁드립니다.

필자는 이 질문을 동료 필자인 Matt Pietrek과 John Robbins에게 보내어 조언을 구했습니다. Matt는 이렇게 말하더군요. "그 사람의 생각이 맞다. 포인터는 오래되어 불필요한 개념이며 이제는 배울 필요가 없다." John은 한술 더 뜨더군요. "포인터는 개 이름인줄 알았다. 뭔가 다른 의미가 있나?"
from http://msdn.microsoft.com/ko-kr/magazine/cc163484.aspx (꽤 읽을만 하니 일독을 권한다.)

2011/03/16 01:12 2011/03/16 01:12

디스크...

전산 2010/11/05 23:30
* 코어는 미친듯이 늘어나고 있고, 메모리는 물값만큼이나 싸졌다.

* 해서, 서버 설계에 특별한 문제가 없다면 (특별한 문제가 없도록 만들 수 있으려면 한 10년정도 죽어라 삽질해 봐야 하지만..) , 이상적인 상황일 경우 결국 동접의 병목은 DB 가 결정하게 된다.

* 그런데 안타깝게도 DB 분야에서 혁신적인 성능 향상을 기대하긴 힘들다.

* 메모리 증설이나 중간에 이것저것 트릭을 써서 DB 부하를 경감할 수 있지만, 서버 시동 후 대량으로 몰리는 순간 로그인 요청은 결국 디스크 긁어야 한다.

* 아무리 비싸고 빠른 스토리지라 해도 일반적인 사용 환경에서 하드 디스크 수배 이상의 성능을 내기는 힘들다. 돈이 모든걸 해결해 주지는 않는다...
2010/11/05 23:30 2010/11/05 23:30

TIOBE Index 2010

전산 2010/06/26 01:35

사용자 삽입 이미지

TIOBE index 보러 갔다가 깜놀. Objective-C 는 대체 몇계단이나 상승한거냐? 아이폰이 대단하긴 대단하구나..
2010/06/26 01:35 2010/06/26 01:35
엔드유저에게 프로그램을 릴리즈 하고 난 뒤에 개발은 계속 하면서 릴리즈 버전의 패치도 병행해야 한다. 그리고 수정된 패치들은 개발 버전에도 주기적으로 적용이 되어야 한다.

Mercurial 에서 이것을 하는 방법은 3가지가 있다. git 나 bazaar 같은 다른 DVCS 도 크게 다르지 않을거라 본다.

1. 저장소를 Clone 을 떠놓고 개발버전과 릴리즈 버전 두개의 저장소를 운영한다. Mercurial 은 저장소간 changeset 의 교환이 쉽기 때문에 이 방법은 자연스럽게 사용 가능하다.

2. Mercurial 내에 내장된 브랜치 기능을 사용한다. SVN 의 브랜치 기능과 비슷하다고 보면 될것 같은데 SVN 브랜치를 제대로 써본 적이 없어서 뭐라 말하긴 힘들다.

3.한 저장소 내에서 브랜칭 없이 Head 를 여러개 유지한다.

첫번째 방법은 가장 DVCS 다운 '머지가 간편하고 관리 가능한 풀백업' 이라고 보면 되겠다.

두번째 방법은.. 제대로 쓰기 쉽지 않아 보인다.

이번에 사용해 보려는 것은 세번째 방법이다. 첫번째 방법에서 저장소만 하나를 쓰는것.

아래 스샷은 Devel 고 Release 라는 두개의 Head 를 유지하면서 필요하다고 생각될 때마다 한쪽의 수정사항을 다른쪽에 반영시켜 나가는 것을 보여준다.

사용자 삽입 이미지


간략히 요약해 보자면, 최초 변경점(Start) 이후 엔드유저에게 릴리즈(OBT Release) 되고, 개발 버전은 Devel-? 라는 이름으로 업데이트, 릴리즈 버전의 버그 패치는 Release Patch-? 으로 업데이트 된다. 필요하다고 생각될때 릴리즈 버전의 패치를 개발 버전에 적용시킬 수 있으며 언제든 원하는 시점으로 돌아가 새로운 노드를 생성할 수 있다. 그리고 changeset 간의 머징도 손쉽다.

첫번째 방법이 더 좋지 않을까 하는 생각도 들긴 하지만.. 수 틀리면 원클릭에 다른 방법으로 언제든 갈아타기 쉽고 풀 히스토리가 남는다는것 역시 DVCS 의 장점인지라.. 일단 돌려 보는데 부담이 없어 좋구나.
2010/05/04 20:24 2010/05/04 20:24
사용자 삽입 이미지

진리의 TortoiseHg



혼자서 보름정도 써보고 뻑 가서 회사에 세미나 하고, 팀에 도입해서 이제 거진 한달정도 써봤다. 결론부터 말하자면, AlienBrain, Perforce, SVN 이런거 쓰지 말고 무조건 옮겨타길 추천한다.

현재 현실적으로 선택 가능한 DVCS 에는 3가지 정도가 있다.

1. Git
2. Mercurial
3. Bazaar

셋 다 테스트 해봤는데, Windows 에서 쓸거라면 Mercurial 이 짱이다. Git 는 Windows 에서 쓸만한 물건이 못되는것 같다. 최근 구글 코드에서 공식적으로 Mercurial 을 지원하기 시작했는데, 관련해서 http://code.google.com/p/support/wiki/DVCSAnalysis 도 읽어볼만 하다.

여튼 Mercurial/DVCS 도입으로 인한 장점을 열거해 보자면...

1. Hg Repository Explorer 진짜 짱이다. 한눈에 누가 뭐하는지 다 보이고 코딩 스타일까지 파악할 수 있다. annotate/blame 볼 필요도 없어진다.
2. 릴리즈 관리 편해진다. 브랜치 기능 같은걸 '진짜로' 쓸 수 있다.
3. 다른 부분에 영향을 많이 주는 모듈을 소수 프로그래머가 작업 해야할때, 기존 모델들은 중앙저장소에 체킨한다음 '딴님들은 받아가지 마셈~' 이라고 광고하거나 수작업으로 파일을 퍼날라야 했지만 DVCS 에서는 관련 작업 하는 프로그래머들끼리 changeset 교환해서 작업하면 ok. 끝나면 다른이들에게 퍼주면 된다. (A,B 두 프로그래머가 메세지 헤더같은거 맘대로 고쳐서 지들끼리 push/pull 하면서 만들다가 중앙저장소에 push 하면 끝이다.
4. DB 깨짐, 섭따.. 이딴거 고민 안해도 된다. 인터넷 안되도 revision 올리고 commit 하면서 작업할 수 있다. 서버 백업도 필요 없다.
5. 설치도 간단하다. TortoiseHg 하나 깔면 끝. 서버따위가 없기 때문에 설정도 필요 없다.
6. 개인 저장소의 web serve 기능 참으로 훌륭하다.

단점은....

1. merge 가 안되는 바이너리 파일들 다루기는 곤란하다. 중앙 저장소가 없어서 lock control 이 안된다.
2. Visual Studio 플러긴이 부실하다.
3. commit 하고 난 다음에 중앙저장소로 쓰기로 약속한 머신에 push 를 해줘야 하는데 좀 번거롭다. (DVCS 적응 비용)

이외에는 딱히 모르겠다. 사실 2번은 SVN 도 제대로 안되던거고 3번은 commit 후에 자동으로 push 되게 하는 옵션 켜놓으면 ok.

여튼 무조건 옮겨타라. Windows 플랫폼 기준으로, 일단 돈이 있다면 TortoiseHg (공짜) + AraxisMerge ($250+) 를 추천한다. 현존 최강의 조합이라 할만하다. 울 회사 같은 경우는 AlienBrain 에 내장된 AraxisMerge 를 사용했다. 만약 회사에서 AraxisMerge 를 안사준다면 Beyond Compare 3 ($50) 를 추천한다. AraxisMerge 와 비슷하지만 가격이 1/5 이다. 회사에서 안사주면 사비로 사는것도 좋다. 프로그래밍으로 밥벌어 먹겠다면 이런건 하나 사줘야 되지 않을까..

그리고.. 성급하게 도입하려고 시도하면 에반겔리스트로 몰리기 쉽상이다. 처음엔 기존 SCM 과 공존을 도모하며 도입하는게 좋다. SVN 을 쓰고 있다면 SVN 은 기존대로 쓰고, Mercurial 을 개인 관리 용도로 쓰는것을 추천한다. 미리 혼자 충분히 써보고 장단점을 파악한 다음에 전파를 시도하길 권한다. 아마 두개를 병행해서 써보고 난 뒤라면 도저히 이전 모델을 쓰고싶지 않아질거다.

이하는 몇가지 팁

1. Windows 환경에서 중앙 저장소 서버를 돌릴거라면 Apache 에 mod_wsgi 로 띄우는걸 추천한다.
2. 여러 저장소를 하나의 서버에서 돌리려면 Publishing Repositories with hgwebdir.cgi 를 참조해야 하는데... 아마 그대로 따라해보면 안될거다. Win32 환경에서는 버그때문에 안되는거다. http://mercurial.selenic.com/bts/issue1875 에 보면 패치 있으니까 이걸로 hgwebdir_mod.py 다시 컴파일 해야한다. 파이썬 몰라도 pyc 파일 만들어 덮어 씌우는건 어렵지 않을거다. (사실 나도 루비빠라서 파이썬 모른다. -_-) => 4월1일에 나온 1.5.1 에서는 해결됨
3. 계정관리 하려면 HgLogin 을 써야 할텐데.. 그거 설정하기 힘들다. 그냥 Microsoft 에 있는 "고급 보안이 설정된 Windows 방화벽" 으로 보안 설정 하는게 편하다. 액티브 디렉토리의 컴퓨터/유저/그룹 단위로 IP 방화벽을 걸 수 있다.

... (생각나는데로 줄줄이 추가됩니다)



ps. 개인적으로 빨리 지르지 않아서 후회한 것들 리스트가 업데이트 되었다. 1. 노트북 2. 자동차 3. Mercurial
2010/04/16 00:32 2010/04/16 00:32
요새 업계에서는 너티독 얘기가 한창이다. 다들 판타지를 품는것을 보니 처음 PD 를 달고서 고군분투했던 생각이 난다.

프로젝트를 맡고 나서 한동안 불타올라서 구현하고자 했던것이 있었으니 "개발자 모두가 스스로 즐기면서 게임 개발에 참여/관여하는 팀을 만드는 것" 이라는 아주 단순하고도 이상적인 목표였다. 저런 로망을 갖게 된것은 필드에 입문하고서 스스로가 직군에 한정되지 않고 게임 개발에 전방위 적으로 관여할 수 있는 환경을 절실히 원했기 때문이었다. 당시의 나는 우리도 할 수 있다는 확신을 가지고 있었다.

지금은 그후로 3년이 지났다.

,

얼마전 @henjeon 님 트위터에서 재미난 글귀를 보았다.

사람은 자연성, 가연성, 불연성의 세 부류가 있다. 최소한 가연성 이상은 되어야 조직에서 일할 수 있다.

참 재미나게 표현한것 같다. 아마 창의적인 조직을 오래 매니징 해본분이 쓴 글일거라고 생각한다. 스스로가 3년간 좌충우돌 하면서 절실하게 느낀점은, 생각보다 많은 사람들이자기 자신이 무엇을 원하고 있는지 여전히 모르고 있다는 것이고, 우리 주변에서 가연성 타입의 사람을 찾기도 그리 쉬운일이 아니라는 것이다.

결론부터 말하자면 나는 처음의 목표를 구현하겠다는 생각은 접었다. 지금은 목표를 '모두가 개발에 관여하도록 하자' 에서 '관여 하고 싶은 사람이 그럴 수 있는 창구를 만들어 주자' 로 수정한 상태다. 해외의 B 모사나 너티독같은 곳에서는 그것을 이미 이루어내지 않았는가? 라는 의문이 있을 수도 있겠다. 그런데 나는 '해외' 라는 단어를 쉽게 흘려버리지 말라고 얘기하고 싶다.

현재 나의 일터는 전 세계에 지사를 두고 있는 다국적 그룹에 속해있는 회사이고, 그룹 회장님은 서로간의 커뮤니케이션을 굉장히 중시한다. 해서 해마다 지사의 주요 인사들을 오키나와라던가 뉴질랜드같은곳에 모두 모아서 캠프를 열기도 하고 혹은 본인이 지사를 돌아다니면서 강연을 하기도 하신다.

그분이 회사에 오셔서 팀장급들을 모두 소집해 리더쉽 트레이닝 세미나를 했을때의 일이다. PT 가 끝나고 Q&A 시간이 되었는데 아무런 질문도 없었다. 그러자 세계 투어 하면서 PT 뒤에 QA 시간을 가지면 영/미권 회사에는 질문/건의가 쏟아지고 일본/한국에서는 침묵만이 흐른다는 얘기를 하셨다. 농담조로 얘기하셨지만 난 그 얘기를 그렇게 가볍게 흘려버릴 수 없었다.

글쎄, 나는 지금 '씨바 우린 안돼..' 같은 패배주의적인 얘기를 하려는 것이 아니다. 다만 나는 지금까지 '우리에게 맞지 않는 옷' 을 낭만에 취해 무리하게 입으려 했던게 아닌가 싶은 생각이 드는 것이다. 국내의 유명 스튜디오들의 개발 문화와 PD분들의 이미지에 대한 들여오는 이야기들은 그런 나의 생각을 더욱 확고하게 만드는 것 같다.

자연성인 사람들에게 기운 빠지는 애기를 쓴 것 같아 조금은 미안하지만, 부디 누군가 나의 이런 생각이 틀렸음을 증명해 주면 질투가 나면서도 한편으로는 참 기분이 좋을것 같다.
2010/03/25 02:30 2010/03/25 02:30

LUA 를 이용한 RPC

전산 2010/02/09 10:16
코드 :
-- 함수 호출 핸들러
function CALL_HANDLER( tbl, ... )
  print( "function : " .. tbl.FUNC_NAME )
  a = {...}
  print( "args : " )
  for i = 1, #a do
    print( a[i] )
  end
end


-- tbl 에 호출러를 바인딩
function Bind( tbl )

  mt = {}
  mt.__index = function( tbl, key )

    -- 리턴할 함수 호출을 위한 임시객체
    local tmp = {}
    tmp.FUNC_NAME = key

    -- 핸들러 바인딩
    local inst = {}
    inst.__call = CALL_HANDLER
    setmetatable( tmp, inst )

    return tmp
  end

  setmetatable( tbl, mt )
end

obj = {}
Bind( obj )

obj.aa( "a", 3, 5 )

실행결과 :
$ lua-5.1 call.lua
function : aa
args :
a
3
5

CALL_HANDLER 에 장난을 쳐주면 RPC 로 동작할 수 있다. 확장시키면 리모트의 객체 참조 및 대입등도 가능한데 한번 해서 프로젝트에 적용해 보려다가 갑자기 이게 뭐하는 짓인가 싶어서 관둠.

메타프로그래밍이란건 일단 재밌는데다가 근사해 보이기도 하지만.. 사실은 제한적이고도 쓸데 없는, 사악한 것이 될 가능성이 큰 관계로 너무 빠져들지 않는게 좋다.
2010/02/09 10:16 2010/02/09 10:16

lock-free 와 최적화

전산 2009/09/11 19:34
나는 lock-free 를 사용하지 않는다. 성능이득은 거의 미미한데 비해 투자비용이 너무 과다하다고 생각하기 때문이다. lock-free 같은 하드코어 튜닝 기법 관련해서는 Eric S. Raymond 본좌의 이야기를 경청할 필요가 있겠다.


시간복잡도를 변화시키는 최적화라면 모를까, 선형적인 성능향상은 쓸데없는 짓이며 무어의 법칙앞에 무력할 뿐이라는 얘기인데 나는 저 의견에 동의한다. 링크 따라 가보면 그런짓 할시간에 딴걸 더 만들라고 충고하고 있다. Eric S. Raymond 스스로가 개발자 이므로 피가 되고 살이 되는 이야기를 저렇게 명쾌하게 해줄 수 있는것 같다.

사실 최근에는 무어의 법칙이 한계에 다다라서, 코어를 좀 더 단순하게, 그리고 많이 박는쪽으로 나가고 있다 보니 저 이야기가 진리만은 아니다. 하지만 그렇다 해도 게임에서의 lock-free 는 성능이득이 너무 작다. 내가 커널이나 디바이스 드라이버를 만들거나 혹은 진짜 시간이 남아돌지 않는 이상, lock-free 를 쓰는 일은 없을 것 같다.
2009/09/11 19:34 2009/09/11 19:34
volatile 과 메모리 베리어의 이해부족으로 인한 잘못된 정보가 인터넷에 꽤 널려있다. 특히 한글 문서에서 미묘한 오류를 포함하고 있는 문서가 많이 발견되는것 같다. OOE(Out of order execution) 는 컴파일러와 프로세서에 의해 일어날 수 있는데 어지간한 지식 없이는 메모리 베리어를 제대로 이해하기 힘들다. 오류의 발생 빈도가 낮아재현과 해결이 무척 힘든 부분이기 때문에, 개념부터 바닥의 디테일까지 확실하게 이해해야할 필요가 있다.

관련해서 f군과 수집한 몇가지 자료들을 추천해 본다.

* Eric Eilebrecht - Fun programming problem: a simple lock-free algorithm
* Jonathan Morrison - How Does KeMemoryBarrier Work
* Bartosz Milewski - Who ordered memory fences on an x86?
* David Howells - Linux Kernel Memory barriers

자신은 제대로 이해하고 있고, 응용에도 강하다고 생각한다면 아래의 연습문제를 풀어보자.

1. 인라인 어셈블리는 왜 컴파일러 메모리 베리어로 기능하는가?
2. 컴파일러 메모리 베리어와 프로세서 메모리 베리어는 왜 구분해서 사용되어야 하는가?
3. 크리티컬 섹션이나 뮤텍스 등 동기화 객체로 코드를 동기화하면 메모리 베리어 효과가 발생한다. 그 이유는 무엇인가?

덧. 나라면 여차하면 삑사리 나는짓 하지 않고 그냥 동기화 객체 쓴다.
2009/09/09 19:16 2009/09/09 19:16

TDD

전산 2009/09/07 22:07

나는 TDD 의 장점이 두 가지가 있다고 생각한다.

 

우선 첫 번째는살다 보면 예전에 만들어둔 코드가 이후의 수정 때문에 문제가 생기는 경우가 가끔 있다. 그런데 TDD 로 개발해 왔다면 이전에 작성해 둔 테스트를 활용 할 수 있기 때문에 이런 문제 발견이 쉬워진다. 대신, 코드 인터페이스 변경 시에는 기존의 테스트들도 고쳐주는 수고를 감수해야 할 것이다.

 

두 번째로, TDD 는 결합도(coupling) 낮은 디자인을 유도한다. 코드를 테스트 가능하게 만들려면 인터페이스가 명확해야 하고 어떻게든 다른 모듈과의 관계를 제거하거나 줄여야만 한다. 일반적으로 결합도가 낮은 코드는 좋은 디자인일 확률이 높기 때문에 모든 코드를 테스트 가능하게 유지하다 보면 전체적인 코드 수준도 좋아진다.

 

위와 같은 이유로, 기존의 프로젝트에 TDD 를 적용하는 것은 불가능하다고 본다. TDD 는 좋은 디자인을 유도할 뿐이지 이미 존재하는 나쁜 디자인을 좋은 디자인으로 변화시키지는 않기 때문이다. 켄트 벡은 기존 프로젝트에 TDD 를 어떻게 적용하냐는 질문에 책에서 그것은 책 한권으로 설명해야 하는 분량이다라는 답을 한것 같은데 내 생각에 기존 코드를 테스트 가능하게 만드는 방법은 없다. 그냥 새로 짜는게 빠르고 효율적일거다.

 

그렇다면 Testors는 모든 것을 TDD 로 개발하느냐..? 그렇지 않다. 나는 에반젤리스트도, 방법론자도 아니다. 뭔가가 새로 나오면 그것이 필드에서 실제로 동작하는걸 확인하지 않는 이상은 도입을 꺼린다. 좋은 방법론 1~2년쯤 늦게 도입한다 해서 프로젝트가 망하지는 않는다. 구지 리스크를 감수할 필요 없이 나 빼고 남들이 다 써서 긍정적인 효과가 명백히 드러날때에 써도 늦지 않다.

 

만약 내가 엔진이나 라이브러리나 웹, 혹은 비즈니스 로직을 주로 다루는 프로그래머였다면 대부분을 TDD 로 작성했을지 모르겠다. 하지만 나는 온라인 게임 프로그래머이고(였고) 게임에서 발생하는 상황에 대한 테스트 케이스를 작성하는 것은 쉽지 않다. 이건 숫자들의 합을 더하는 수준의 문제가 아니다. 결합도를 없애는 것만이 능사가 아니며 효율을 위해 어느정도의 관계는 분명히 유지시켜야 한다.

 

사실 TDD 라는 용어를 접하기 전부터 길찾기라던가 기타 게임 개발에 필요한 기하 문제들을 풀때는 항상 테스트를 작성했었다. input & output 이 명확한 이런 문제들을 테스트를 작성하지 않고 작업하는 사람이 정말 근성가이라고 본다.

 

3년쯤 전인가 회사의 UI 엔진을 스크립팅 가능하게 리뉴얼 하는 작업을 한 적이 있었다. 기존의 엔진은 폼 디자이너 툴만이 제공되었는데 이걸 기존 C++ 코드 & 리소스들과의 하위호환성을 유지하면서 루아 스크립팅 & 시뮬레이션이 가능하도록 만드게 목표였다. 작업은 순조로워서 엔진과 툴 모두 쓸만한 수준으로 부작용 없이 리뉴얼 할 수 있었다. 이후 UI 들은 자체 테스트를 내장한 채로 개발이 되었었다. 그런데 어떤 경우들은 테스트 작성 비용이 재현 및 디버깅 비용을 넘어서기도 했다.

 

게임 프로그래밍이란게 그렇다. input output 을 명확하게 정의하기 힘들다. 시간의 흐름도 중요하고 타이밍도 중요하다. 몇몇 특정한 상태에 대한 테스트를 작성하고 유지하는것에 대한 비용은 정말이지 엄청나게 커질 수 있다. 내가 취한 방법은 대부분의 UI 들에서 테스트 작성을 포기하고, 런타임에 재현 및 디버깅이 쉽도록 한 것이었다. 키 하나로 스크립트가 모두 reload 되고, UI 가 문제 발생 이전으로 리셋되는 식이었다.

 

요약하자면, TDD 는 사실 패턴과 마찬가지로 이전부터 쓰는 사람은 모두 써왔던 방법이고, 그게 모든 분야에 사용되고 있지 않은 이유는 당연하게도 TDD 모든것에 대한 해답이 될 수 없기 때문이라고 생각한다. (난 사실 TDD 가 적용될 수 있는 분야가 매우 한정적이라고 생각한다) 문제는 이런글 (http://testors.net/tt/625)들이 귀 얇은 친구들을 혹세무민하여 주화입마에 빠지게 하는것에 있다. (이 대목에서 모 군이 찔려할것 같다...)

 

만약 TDD 가 정말로 결함을 줄여주고 개발 기간을 단축시켜 준다면 (참고: 난 이런 개발 효율이 측정 가능하지 않다고 생각한다), TDD 를 도입하지 않은것을 불안해 할 필요가 없다. 그게 사실이라면 어느샌가 당신 주변의 대부분의 개발자들이 TDD 를 사용해 프로젝트를 진행하고 있게 될거다. 그때 관심 가져도 늦지 않을것 같다.

2009/09/07 22:07 2009/09/07 22:07