< Return to Video

Robert C. Martin: Principles of Component Design.

  • 0:04 - 0:08
    준비 됐나요?
  • 0:09 - 0:11
    좋습니다.
  • 0:23 - 0:25
    저기 빨간 점 보이나요?
  • 0:30 - 0:32
    왜 빨간색일까요?
  • 0:35 - 0:37
    위험해서라고요?
  • 0:38 - 0:41
    마음에 드네요. "이봐! 나를 쿠바로 망명시켜줘."
  • 0:43 - 0:52
    그래요. 이 레이저 때문에 공항에서 잡혀간 적도 있었지요.
  • 0:52 - 0:55
    거기에는 "DANGER" 이라고 써 붙여 있었어요.
  • 0:57 - 0:59
    그나저나 왜 빨간색 일까요?
  • 1:01 - 1:02
    나는 초록색 레이저도 있습니다.
  • 1:02 - 1:05
    모두 레이저 몇 개 정도는 있어야 해요.
  • 1:06 - 1:09
    나는 항상 세 개는 들고 다닙니다.
  • 1:11 - 1:16
    그 중 하나가 빨간색인데요. 가방에 배터리와 함께 들고 다닙니다.
  • 1:16 - 1:18
    ...
  • 1:18 - 1:23
    이 빨간색 레이저는 12달러면 살 수 있습니다.
  • 1:24 - 1:25
    빨간색 레이저 보이지요?
  • 1:25 - 1:29
    멋지지요? 여기 초록색도 있습니다.
  • 1:30 - 1:31
    이 것도 좋아요.
  • 1:33 - 1:35
    아주 밝지요.
  • 1:35 - 1:39
    특별할 건 없지만 그래도 아주 밝아요.
  • 1:39 - 1:41
    이 걸 살짝 개조할 수도 있습니다.
  • 1:41 - 1:45
    레지스터 하나를 교체하면
  • 1:45 - 1:48
    출력을 0.25와트로 높일 수가 있는데요.
  • 1:48 - 1:51
    그러면 풍선 정도는 터트릴 수 있습니다.
  • 1:52 - 1:55
    멋지지요. 펑!
  • 1:57 - 2:01
    하지만 내가 제일 좋아하는 레이저는 이거입니다.
  • 2:02 - 2:05
    왜냐하면
  • 2:07 - 2:13
    저기 보이나요?
  • 2:15 - 2:19
    작은 보라색 점. 저기 위에 보여요?
  • 2:21 - 2:25
    어디 봅시다. 오! 밝게 잘 보이네요.
  • 2:25 - 2:28
    여기 바로 위에요. 아주 밝게 잘 보입니다.
  • 2:28 - 2:31
    하지만 저기에 비추면 잘 보이지 않아요.
  • 2:31 - 2:34
    보이나요? 잘 안보입니다.
  • 2:34 - 2:36
    여기에는 보이나요? 아니군요.
  • 2:36 - 2:39
    음. 잘 안보여요.
  • 2:39 - 2:49
    그런데 이런 걸 발견했어요.
  • 2:51 - 2:57
    그냥 사인펜입니다. 레이저를 쏴도 특별히 달라지진 않네요.
  • 2:57 - 2:59
    하지만 뚜껑을 보세요.
  • 3:02 - 3:05
    노란색이네요!
  • 3:06 - 3:07
    파란색이 아닙니다.
  • 3:08 - 3:11
    저기 오랜지 색 부분 보이나요?
  • 3:11 - 3:14
    잘 보세요. 조심스럽게 겨냥해야 합니다.
  • 3:14 - 3:18
    오! 오랜지 색이에요!
  • 3:18 - 3:20
    이건 어떤 레이저일까요?
  • 3:22 - 3:26
    이 건 조금 다른 레이저입니다.
  • 3:34 - 3:41
    내 안경은 햇빛을 받으면 렌즈가 짙어지는데요
  • 3:45 - 3:48
    잘 보일지 모르겠지만 렌즈들이 모두 까매졌습니다.
  • 3:48 - 3:51
    그렇지요? 여러분들이 안보이네요.
  • 3:51 - 3:53
    이건 자외선 레이저입니다.
  • 3:54 - 3:58
    하지만 자외선 레이저라고 팔지는 않아요. 아마존에서 17달러면 살 수 있습니다.
  • 3:58 - 4:01
    보라색 레이저라고 팔고 있지만 거짓말입니다.
  • 4:01 - 4:07
    보라색 레이저 보다 더 멋진 거에요. 자외선 레이저입니다.
    (역주: Ultra Violet Laser, Violet Laser)
  • 4:07 - 4:10
    누구나 자외선 레이저 하나쯤은 있어야 해요.
  • 4:10 - 4:13
    레이저 포인터로는 쓸모가 없지만
  • 4:13 - 4:17
    안경에 작은 그림들을 그릴 수는 있어요.
  • 4:19 - 4:22
    "안경에 이름을 썼어!"
  • 4:25 - 4:27
    우야당간......
  • 4:29 - 4:31
    저기 코드를 보세요.
  • 4:33 - 4:34
    어떤 코드인지 아는 사람있나요?
  • 4:36 - 4:38
    안경 렌즈가 까매서 볼 수 가 없네요.
  • 4:39 - 4:41
    어떤 코드인지 알겠나요?
  • 4:42 - 4:44
    저건 PDP-8의 소스 코드입니다.
  • 4:45 - 4:49
    1970년대의 소스코드는 저렇게 생겼었습니다.
  • 4:49 - 4:55
    내가 20살 즈음에 저런 코드를 작성했었지요.
  • 4:56 - 4:59
    20대 초반에도 그랬습니다.
  • 5:00 - 5:04
    저 소스 코드를 보세요.
  • 5:04 - 5:06
    어떤 의미인지 아는 사람 있나요?
  • 5:08 - 5:14
    프로그램이 메모리에 로딩될 주소입니다.
  • 5:15 - 5:20
    당시에는 소스 코드에 프로그램이 로딩될 주소를 명시했었습니다.
  • 5:21 - 5:24
    이 프로그램은 메모리 주소 200에 로딩될 겁니다.
  • 5:24 - 5:27
    그리고 데이터는 300에 저장됩니다.
  • 5:27 - 5:28
    어떤가요?
  • 5:29 - 5:33
    당연한거에요. 여러분은 프로그램이 어느 주소에 로딩될지 알아야 합니다.
  • 5:33 - 5:35
    여러분 말고 또 누가 그걸 결정하겠어요?
  • 5:35 - 5:38
    프로그래머가 메모리를 컨트롤 해야지요.
  • 5:39 - 5:41
    이대로는 아무런 문제가 없습니다.
  • 5:43 - 5:46
    다른 그림들도 보여드릴게요.
  • 5:46 - 5:50
    어디 봅시다.
  • 5:50 - 5:55
    이게 아니네요. 이 그림 말고 다른 게 있습니다.
  • 5:56 - 6:02
    요즘은 문서를 열면
  • 6:02 - 6:10
    같이 열렸던 문서들이 모두 같이 열려버려요.
  • 6:11 - 6:12
    저장할 필요 없고요.
  • 6:12 - 6:15
    이게 찾던 그림니다.
  • 6:17 - 6:20
    여러분이 이런 개발 언어를 사용한다고 생각해보세요.
  • 6:21 - 6:24
    그리고 이런 프로그램을 작성하는 거지요.
  • 6:25 - 6:28
    이 프로그램은 여기에 위치합니다. 주소 200에서 시작하지요.
  • 6:29 - 6:32
    여기 다른 사람이 작성한 서브루틴 라이브러리가 있습니다.
  • 6:33 - 6:35
    그나저나 그 당시에는 서브루틴 라이브러리가 드물었지요.
  • 6:35 - 6:38
    필요한 서브루틴은 직접 작성하곤 했습니다.
  • 6:38 - 6:46
    몇 몇 사람이 아주 유용한 서브루틴을 작성한 후에야 사람들은 자신의 프로그램에 그 것들을 넣기 시작했습니다.
  • 6:46 - 6:50
    "그냥 프로그램에 추가해서 같이 컴파일 합시다."
  • 6:50 - 6:52
    보통 그런 방식으로 했지요.
  • 6:52 - 6:53
    서브루틴의 소스 코드를 가져와서 내 코드와 합치는 거죠.
  • 6:54 - 6:55
    그럼 어떤 문제가 있을까요?
  • 6:59 - 7:02
    지금 우린 1970년대를 이야기하고 있습니다.
  • 7:02 - 7:06
    그 당시 프로그램은 종이 테이프에 저장되었습니다.
  • 7:06 - 7:10
    종이 테이프는 초당 50문자 정도를 저장했습니다. 운이 좋은 경우에요.
  • 7:11 - 7:20
    그래서 소스 코드가 길어지면 컴파일 타임이 몇 분씩이나 길어지곤 했습니다.
  • 7:20 - 7:27
    그러다 보면 서브루틴 라이브러리가 너무 길어서 같이 컴파일 하지 못하는 경우도 생깁니다.
  • 7:27 - 7:35
    그런 경우는 서브루틴 라이브러리를 따로 컴파일 해서 메모리 주소 1200에 로딩합니다.
  • 7:36 - 7:42
    메모리 주소 1200에 컴파일된 바이너리 파일을 로딩하는 겁니다.
  • 7:42 - 7:45
    메인 프로그램은 메모리 주소 200에 로딩합니다.
  • 7:45 - 7:49
    그리고 심볼 정보를 담은 작은 파일이 있어요.
  • 7:49 - 7:55
    심볼을 보고 각 서브 루틴들이 어디에 로딩되어 있는지를 알 수 있습니다.
  • 7:55 - 8:03
    예를 들어 Get 서브루틴이 205번지에 있고 Put 서브루틴이 210번지에 있다는 것을 알 수 있는 거지요.
  • 8:04 - 8:07
    심볼 정보들은 프로그램과 함께 컴파일이 됩니다.
  • 8:07 - 8:10
    서브루틴 라이브러리는 따로 로딩됩니다. 그리곤 잘 동작하겠지요.
  • 8:12 - 8:14
    그럼 무엇이 문제일까요?
  • 8:16 - 8:19
    프로그램 크기가 변하지 않는 경우가 있을까요?
  • 8:21 - 8:22
    프로그램은 항상 커집니다!
  • 8:23 - 8:26
    계속 커지다 보면...... 어디 봅시다.
  • 8:28 - 8:30
    여기 다른 그림이 있어요.
  • 8:35 - 8:36
    네 이겁니다.
  • 8:41 - 8:44
    자! 메인 프로그램이 아주 커졌어요.
  • 8:44 - 8:47
    서브루틴을 덮어 써버렸네요. 정상적으로 동작하지 않습니다.
  • 8:49 - 8:56
    메인 프로그램이 서브루틴을 덮어써버렸지만 메인 프로그램은 그걸 모릅니다.
  • 8:56 - 9:02
    메인 프로그램이 1205번지를 호출하면 서브루틴이 아닌 자기의 어딘가를 실행하게 됩니다.
  • 9:03 - 9:04
    개발자도 어떤 상황인지 몰라요.
  • 9:05 - 9:08
    한참 디버깅 한 뒤에야 깨닫습니다. "이런, 프로그램이 너무 커져버렸네!"
  • 9:09 - 9:11
    그럼 어떻게 해결해야 할까요?
  • 9:14 - 9:18
    여러분들은 프로그래머자나요? 잘 생각해보세요.
  • 9:21 - 9:23
    서브루틴 라이브러리를 건너 뛰는 겁니다.
  • 9:24 - 9:27
    서브루틴들을 피해서 메인 프로그램을 배치하고 실행하는 거지요.
  • 9:28 - 9:31
    그런데 서브루틴 라이브러리도 점점 커집니다.
  • 9:32 - 9:40
    그러고 나면...... 이 그림이 맞는지 봅시다.
  • 9:40 - 9:42
    이건가? 네 맞습니다.
  • 9:43 - 9:45
    그러고 나면 이런 문제가 생깁니다.
  • 9:48 - 9:51
    실제 현장에서 발생하던 문제들입니다.
  • 9:51 - 9:54
    이런 문제들을 해결해야만 했었습니다.
  • 9:54 - 9:56
    어떻게 해결했는지 알겠나요?
  • 10:00 - 10:05
    우리는 재배치할 수 있는 코드를 생각해냈습니다.
  • 10:05 - 10:10
    "이봐, 프로그램을 절대 주소 값에 로딩하는 건 너무 문제가 많아."
  • 10:11 - 10:17
    "코드에 프로그램이 로딩될 위치를 넣지 않고 컴파일 하는 방법이 필요해."
  • 10:18 - 10:21
    "로더에게는 로딩할 위치를 따로 알려주는 거야."
  • 10:21 - 10:23
    그러려면 또 다른 이슈가 있습니다.
  • 10:24 - 10:30
    바이너리 파일이 순수한 바이너리가 아니게되는 것 입니다.
  • 10:30 - 10:39
    어떤 숫자는 주소가 아니라 오프셋이라고 말해주는 정보가 바이너리에 추가되기 때문이지요.
  • 10:39 - 10:48
    로더는 오프셋으로 표시된 모든 주소에 시작 주소를 더해야만 합니다.
  • 10:49 - 10:52
    결과적으로 재배치 가능한 로더는 잘 동작했습니다.
  • 10:52 - 10:55
    재배치 가능한 바이너리와 로더를 개발했습니다.
  • 10:55 - 10:57
    하지만 새로운 문제가 생겼습니다.
  • 10:57 - 11:00
    서브루틴이 어디에 있는지를 알아야만 했지요.
  • 11:00 - 11:06
    서브루틴이 임의로 배치된다면 어떻게 로딩된 위치를 알 수 있을까요?
  • 11:06 - 11:11
    결국 그 정보도 바이너리 파일에 추가되어야 합니다.
  • 11:11 - 11:20
    처음에는 순수한 바이너리였던 파일이 점점 괴상한 파일이 되어 버립니다.
  • 11:20 - 11:21
    파일안에 온갖 잡다한 것들이 들어가있지요.
  • 11:21 - 11:28
    이제 바이너리 파일 안에는 서브루틴들의 이름이 들어가야 합니다.
  • 11:28 - 11:32
    그리고 각 서브루틴이 어디에 로딩될지도 알려줘야 하지요.
  • 11:33 - 11:38
    그리고 로더는 각 서브루틴을 어디에 로딩했는지 기억해야 합니다.
  • 11:38 - 11:43
    그런 후에 프로그램에는 또 필요한 것이 있습니다.
  • 11:43 - 11:47
    그건 이렇게 말하겠지요. "이봐, 난 이 프로그램들이 어디에 로딩될지 알아야겠어."
  • 11:47 - 11:53
    "그리고 로더는 프로그램이 사용하는 서브루틴들을 링크해야 해."
  • 11:57 - 12:01
    그 당시의 컴퓨터는 느렸습니다.
  • 12:01 - 12:03
    디스크도 매우 느렸지요.
  • 12:03 - 12:05
    메모리도 많지 않았습니다.
  • 12:05 - 12:08
    디스크도 운이 좋으면 몇 MB 정도 가질 수 있었지요.
  • 12:08 - 12:15
    디스크의 탐색 속도도 매우 느렸습니다.
  • 12:15 - 12:18
    그래서 링크 시간이 아주 오래 걸렸지요.
  • 12:18 - 12:22
    라이브러리가 늘어나면서 점점 더 심해졌습니다.
  • 12:22 - 12:24
    프로그램이 더 많아지고 커지면서
  • 12:24 - 12:26
    링크하는데에 한 시간도 걸렸습니다.
  • 12:26 - 12:28
    여기 링크에 한 시간이나 걸리는 사람이 있나요?
  • 12:28 - 12:31
    여기 80년대에서 일하는 사람이 있어요?
  • 12:31 - 12:33
    이런! 지금도 그렇게 오래 걸린다고요?
  • 12:33 - 12:35
    그럼 C++ 프로그래머겠군요.
  • 12:37 - 12:39
    거기 셔츠에 써있어요.
  • 12:39 - 12:41
    OSLO C++ User Group 이라고요.
  • 12:41 - 12:43
    링크 시간이 너무 길어지는 문제는
  • 12:45 - 12:50
    70년대에도 있었습니다. 그때 프로그램은 훨씬 작았었지만요.
  • 12:50 - 12:58
    해결책은 로딩 중에 링크 단계를 제거하는 거였습니다.
  • 12:58 - 13:02
    링크는 컴파일에 포함되어 두 번째 단계로 수행됐습니다.
  • 13:02 - 13:07
    컴파일이 끝나면 모든 링크 정보가 포함된 재배치 가능한 파일이 만들어 졌습니다.
  • 13:07 - 13:10
    결과적으로 프로그램 실행 시점에 로딩이 가능해졌습니다.
  • 13:10 - 13:12
    속도도 상대적으로 빨랐습니다.
  • 13:13 - 13:18
    그 후 여러 해 동안 이 방식이 유지되었습니다.
  • 13:18 - 13:24
    먼저 컴파일 해서 바이너리 파일을 만들고 바이너리 파일들을 링크해서 실행파일을 만듭니다.
  • 13:24 - 13:26
    그런 후에 실행 파일은 로딩할 수 있게 됩니다.
  • 13:27 - 13:30
    90년대까지 그런 방식을 유지했어요.
  • 13:30 - 13:34
    그러다 90년대에 변화가 생겼습니다.
  • 13:34 - 13:36
    무어의 법칙입니다.
  • 13:37 - 13:38
    무어의 법칙이 무엇이지요?
  • 13:39 - 13:44
    프로세서는 18개월 마다 두 배씩 빨라진다는 것 입니다.
  • 13:44 - 13:53
    1970년대부터 적용해봅시다. 당시의 프로세서는 0.5 MIPS 정도의 처리 능력을 가졌습니다.
  • 13:54 - 13:57
    그런 게 1990년대까지 진행되었지요.
  • 13:57 - 14:00
    그럼 20년이면 18개월이 몇 번이나 지난 것 이지요?
  • 14:00 - 14:02
    18개월이 몇 번 이지요?
  • 14:02 - 14:04
    대략 15번 정도네요.
  • 14:04 - 14:07
    그럼 2의 15승 이네요.
  • 14:08 - 14:09
    어디봅시다.
  • 14:09 - 14:12
    2의 15승이면 얼마나 되지요?
  • 14:12 - 14:14
    대략 32000 정도 향상된 거네요!
  • 14:14 - 14:15
    실제로도 대략 비슷합니다.
  • 14:15 - 14:19
    0.5MHz에서 2.8GHz로 증가했으니까요.
  • 14:19 - 14:22
    음 90년대에는 1GHz 정도였겠지요.
  • 14:22 - 14:25
    당시에는 디스크의 성능도 좋아졌습니다.
  • 14:25 - 14:27
    디스크의 회전 속도가 빨라졌습니다.
  • 14:27 - 14:32
    플래터에 저장되는 데이터도 훨씬 많아져서 헤드가 움직이는 거리도 짧아졌지요.
  • 14:32 - 14:39
    용량이 수백MB나 되는 디스크도 나왔습니다.
  • 14:41 - 14:44
    누군가 아주 좋은 아이디어를 냈습니다.
  • 14:44 - 14:46
    아주 좋은 아이디어에요.
  • 14:47 - 14:50
    "이제 링크를 따로 할 필요가 없겠는걸."
  • 14:51 - 14:54
    "로딩할때 같이 링크해도 되겠네."
  • 14:54 - 14:57
    ActiveX를 기억하나요?
  • 14:57 - 14:59
    OLE는요?
  • 15:00 - 15:02
    DLL이 무엇의 약어이지요?
  • 15:04 - 15:08
    Dynamically Linked Library.
  • 15:08 - 15:11
    로딩될 때에 링크된다는 뜻 입니다.
  • 15:11 - 15:15
    링크 단계가 다시 로더에게 넘어갔습니다.
  • 15:16 - 15:19
    그렇게 지금까지 이어져왔습니다.
  • 15:21 - 15:23
    여기 닷넷 프로그래머 있나요?
  • 15:24 - 15:25
    오! 아주 많군요.
  • 15:25 - 15:28
    자바 프로그래머 손들어 보세요.
  • 15:28 - 15:30
    얼마 없네요. 어떻게 된 거지요?
  • 15:31 - 15:35
    어떻게 닷넷 개발자만 있나요? 아... 이 컨퍼런스가 닷넷 관련된 행사 인가요?
  • 15:36 - 15:42
    닷넷에는 DLL이 있습니다.
  • 15:42 - 15:44
    Dynamically Linked Libraries.
  • 15:44 - 15:46
    자바에는 Jar 파일이 있습니다.
  • 15:46 - 15:51
    Jar 파일도 결국 DLL입니다. 같은 의도로 만들어 졌지요.
  • 15:52 - 15:56
    C++는...... MS 환경에서 작업을 하면 DLL을 사용합니다.
  • 15:56 - 15:59
    UNIX 계열 환경에서 작업을 하면 Shared Library가 있는데요
  • 15:59 - 16:01
    이 것도 역시 DLL과 동일합니다.
  • 16:01 - 16:05
    지금도 동적으로 링크하는 방식이 일반적인데요
  • 16:05 - 16:08
    이런 과정들을 거쳐 현재까지 왔습니다.
  • 16:12 - 16:14
    DLL을 몇 개나 가지고 있나요?
  • 16:15 - 16:19
    비주얼 스튜디오에서 작업하는 사람들
  • 16:19 - 16:20
    솔루션에 프로젝트가 몇 개나 있나요?
  • 16:21 - 16:24
    60개? 그다지 나쁘지 않네요.
  • 16:24 - 16:25
    60개 보다 많은 사람?
  • 16:25 - 16:27
    있군요.
  • 16:27 - 16:28
    200개 이상 되는 사람?
  • 16:31 - 16:33
    왜 그렇게 하는지 아나요?
  • 16:33 - 16:38
    왜 소스 코드를 쪼개서 DLL들에 분산시켜 놓는지 아나요?
  • 16:39 - 16:41
    질문을 다르게 해보겠습니다.
  • 16:41 - 16:44
    어플리케이션을 배포할 때에
  • 16:45 - 16:50
    모든 DLL을 모아서 한 묶음으로 배포하나요?
  • 16:53 - 16:58
    그렇다면 왜 동적으로 링크하지요?
  • 16:58 - 16:59
    정적으로 링크하세요.
  • 17:00 - 17:05
    왜 굳이 동적으로 링크하지요? 모든 DLL을 모아서
  • 17:05 - 17:07
    하나의 거대한 덩어리로 만들고
  • 17:07 - 17:10
    그 덩어리를 디렉터리에 저장한 후에, "이게 우리 시스템이야"
  • 17:12 - 17:17
    동적으로 배포 안 하는데 왜 동적으로 링크하지요?
  • 17:18 - 17:22
    왜 동적 라이브러리가 생겨났지요?
  • 17:22 - 17:29
    동적 라이브러리는 동적으로 배포하기 위해서 만들어진 겁니다.
  • 17:29 - 17:30
    왜지요?
  • 17:33 - 17:36
    네트워크 속도는 조금 있다 이야기 하겠습니다. 잠시만요.
  • 17:36 - 17:39
    네트워크 속도로 인한 변화는 이야기할게 아주 많습니다.
  • 17:39 - 17:44
    90년대에 한 고객이 있었습니다. 실행 파일 크기가 250MB 정도였는데요
  • 17:44 - 17:47
    그 당시에는 아주 큰 프로그램이었습니다. 지금은 아니지만요.
  • 17:47 - 17:52
    그 당시 250MB는 아주 큰 용량이었습니다. CD 한 장에 들어가지도 않았지요.
  • 17:52 - 17:57
    CAD 프로그램이었지요. 포드 같은 회사에 납품했었습니다.
  • 17:57 - 18:02
    포드는 이 프로그램으로 기어나 레버 등을 디자인했습니다.
  • 18:03 - 18:04
    그 고객은 이 프로그램을 정적으로 컴파일 했지요.
  • 18:05 - 18:11
    배포하기 위해 CD 여러장이 필요했습니다.
  • 18:12 - 18:15
    소스 코드 한 줄이 수정되면
  • 18:17 - 18:26
    다시 컴파일 하고 링크한 후에 모든 CD를 다시 구워서 고개들에게 전달해야 했습니다.
  • 18:27 - 18:30
    얼마나 많은 비용이 들었을지 상상이 갈 겁니다.
  • 18:32 - 18:34
    나는 90년대 중반에 거기에 갔었어요.
  • 18:34 - 18:37
    그들을 만났습니다.
  • 18:37 - 18:44
    당시에 그들은 실행파일을 여러 개의 DLL로 쪼개려고 하고 있었는데요.
  • 18:44 - 18:49
    왜냐하면 여러 개의 DLL로 실행파일을 분리해 놓으면
  • 18:49 - 18:52
    소스 코드가 한 줄 바뀌었을 때에
  • 18:52 - 18:57
    관련된 DLL 하나만 배포하면 되기 때문이지요.
  • 18:58 - 19:01
    이메일로 보낼 수 도 있었습니다. 그 당시에는 그것도 큰 일 이었지요.
  • 19:01 - 19:03
    그 당시에 이메일로는 250MB 파일을 보낼 수 없었습니다.
  • 19:03 - 19:08
    요즘에야 어렵지 않지만
  • 19:08 - 19:17
    당시에는 250MB를 이메일로 보내는 건 불가능했습니다. 하지만 100KB 크기의 DLL을 보내는건 가능했지요.
  • 19:17 - 19:20
    그 고객에겐 아주 바람직한 것이었습니다.
  • 19:20 - 19:22
    몇 달을 노력을 해서
  • 19:22 - 19:25
    어플리케이션을 잘게 쪼개서
  • 19:25 - 19:27
    여러 개의 DLL로 만들었지요.
  • 19:27 - 19:29
    그런 후에 치명적인 실수를 깨달았습니다.
  • 19:31 - 19:35
    치명적인 실수는 시스템을 임의의 DLL들로 쪼개는 것이
  • 19:35 - 19:39
    아무런 도움이 안 된다는 것 입니다. DLL들이 서로 서로 의존하는 상황이라면요.
  • 19:40 - 19:43
    DLL들이 서로 의존하고 있는 상황이라면......
  • 19:52 - 19:56
    여기 스캇 마이어의 세미나에 들어갔던 사람 있나요?
  • 19:56 - 19:58
    한 시간 전에 그가 한 연설이요.
  • 19:58 - 20:01
    열쇠구멍 문제에 대한 이야기였지요.
  • 20:01 - 20:08
    열쇠구멍 문제라는 것은 아무런 이유 없이 임의로 제약을 주는 것을 이야기합니다.
  • 20:08 - 20:10
    그냥 임의로 사람들을 구속하는 겁니다.
  • 20:10 - 20:15
    GUI를 예로 들면
  • 20:15 - 20:16
    너무 작은 텍스트 박스를 본 적이 있지요?
  • 20:17 - 20:22
    텍스트 박스에 내용을 많이 적었는데 크기를 조절 할 수 없는 경우 말이에요.
  • 20:22 - 20:26
    심지어 스크롤도 불가능해서 잘 안 보이는 채로 입력한 적 있지 않나요?
  • 20:26 - 20:30
    아니면 스크롤은 할 수 있지만 텍스트의 일부분이 가려지는 경우는요?
  • 20:30 - 20:35
    이게 그가 말한 열쇠구멍 문제입니다.
  • 20:35 - 20:38
    그런데 여기에서도 그런 문제가 있어요.
  • 20:39 - 20:43
    "나는 항상 키보드로 작업을 해야 합니다. 5분이상 손을 떼고 있으면 안 되요."
  • 20:43 - 20:48
    "너무 오래 손을 떼고 있으면 벌을 받게 되요."
  • 20:52 - 20:55
    무슨 이야기를 하고 있었지요? 아 DLL.
  • 20:55 - 20:58
    그래서 그 사람은 모든 DLL을 한 군데에 모았습니다.
  • 20:58 - 21:00
    그런데 DLL들이 서로 서로 의존하고 있다는 것을 잊고 있었어요.
  • 21:01 - 21:04
    원래 목표는 소스 코드 한 줄을 수정하면
  • 21:04 - 21:08
    관련된 DLL 하나 만 배포하는 것 있었지요.
  • 21:08 - 21:12
    '#includes.' C++ 개발자들은 내가 무슨 이야기하는지 알 겁니다.
  • 21:12 - 21:15
    그런데 모든 '#includes' 들이 끔찍하게 얽혀있다는 것을 깨닫게 되었습니다.
  • 21:15 - 21:18
    모두 다시 컴파일하고 다 같이 배포해야만 했던 거지요.
  • 21:18 - 21:20
    결국 그들의 사업을 망했습니다.
  • 21:23 - 21:28
    오늘 강연의 주제는
  • 21:29 - 21:31
    컴포넌트에 대한 것 입니다.
  • 21:31 - 21:33
    컴포넌트 레벨의 디자인 문제들 이지요.
  • 21:33 - 21:36
    가장 먼저 해야 할 것은 '컴포넌트'에 대한 정의입니다.
  • 21:36 - 21:39
    컴포넌트는 무엇인가요? DLL입니다.
  • 21:39 - 21:43
    이제부터 말하는 컴포넌트는 DLL을 이야기하는 겁니다.
  • 21:43 - 21:47
    특정한 종류의 DLL 입니다. 동적으로 배포가 가능한 DLL이요.
  • 21:49 - 21:53
    동적으로 배포 가능한 DLL.
  • 21:53 - 21:56
    왜 동적으로 배포해야 할까요?
  • 21:57 - 22:00
    그건 소스 코드 한 줄이 변경되었을 때에
  • 22:00 - 22:03
    다른 DLL은 그대로 두고 변경된 DLL 한 개만 배포하려고 이겠지요.
  • 22:03 - 22:05
    'DLL 지옥'이 어떤 뜻이지요?
  • 22:05 - 22:09
    Microsoft에서 자기들의 문제를 표현하기 위해
  • 22:10 - 22:12
    정의한 용어입니다.
  • 22:13 - 22:18
    그리고 닷넷이 나오면서 해결됐어야 했지요.
  • 22:18 - 22:22
    그 문구 기억하나요? "닷넷이 DLL 지옥을 치료합니다."
  • 22:22 - 22:28
    하하하! 치료하지 못했지요.
  • 22:28 - 22:32
    DLL 지옥이란 수많은 컴포넌트들이 각각 다른 버전을 가지고 있을 때에
  • 22:32 - 22:35
    서로 맞는 짝이 어떤 것인지 모르는 상태를 이야기합니다.
  • 22:35 - 22:39
    그래서 Maven 같은 툴이 나왔지요.
  • 22:39 - 22:41
    닷넷에는 어떤 툴을 사용하나요?
  • 22:41 - 22:46
    여러 버전들의 DLL들을 관리해주는 툴 말입니다.
  • 22:46 - 22:50
    이 DLL의 버전 1과 저 DLL의 버전 3을 같이 다운받을 수 있게 하는 툴이요.
  • 22:50 - 22:53
    그런 툴이 있나요?
  • 22:54 - 22:55
    너겟 이요?
    (역주: NuGet과 음식 너겟(Nugget)의 발음이 유사함)
  • 22:55 - 22:57
    부드럽고 맛있는 치킨 너겟이요?
  • 22:59 - 23:01
    됐습니다.
  • 23:10 - 23:18
    화면의 저 그래프는 x의 제곱 그래프입니다.
  • 23:18 - 23:20
    그냥 x의 제곱 그래프에요.
  • 23:21 - 23:23
    하지만 다른 의미도 있습니다.
  • 23:23 - 23:29
    저 Y 축은 시스템의 모듈 개수 입니다.
  • 23:29 - 23:34
    모듈의 수에 따라서 가능한 의존 관계의 최대 개수입니다.
  • 23:34 - 23:38
    모듈 개수가 선형적으로 증가할 때에
  • 23:38 - 23:41
    의존 관계는 제곱에 비례해서 증가합니다.
  • 23:44 - 23:49
    이론적으로 연관 관계의 최대 개수는
  • 23:51 - 23:55
    모듈 수의 제곱에 비례합니다.
  • 23:55 - 24:01
    물론 시스템의 모듈들이 서로 마구 마구 의존하게 만들지는 않을 겁니다.
  • 24:03 - 24:04
    설마 그러고 있나요?
  • 24:06 - 24:08
    그래프를 봅시다.
  • 24:09 - 24:20
    모듈의 수에 따른 팀의 생산성을 보여주는 그래프입니다.
  • 24:20 - 24:25
    그나저나 이건 그냥 x의 마이너스 제곱 그래프입니다.
  • 24:25 - 24:28
    실제 데이터를 수집해서 만든 게 아닙니다.
  • 24:29 - 24:34
    그간 겪어온 다양한 사례들을 생각하면서 임의로 만들어 본겁니다.
  • 24:34 - 24:38
    시간이 지나면서 점점 개발 속도가 느려졌던 개발팀들을 생각하면서 말입니다.
  • 24:38 - 24:39
    혹시 경험해본 적 있나요?
  • 24:40 - 24:42
    초기에는 아주 빠른 속도로 개발을 하지요. 세상을 정복할 기세로 말입니다.
  • 24:42 - 24:46
    하지만 1년 지난 후에는 늪지대를 지나는 것처럼 느려져 있지요.
  • 24:46 - 24:49
    왜 느려졌는지도 몰라요.
  • 24:49 - 24:53
    예전에는 1주일이면 가능했던 일이 이제 석 달은 필요합니다.
  • 24:53 - 24:58
    그런데 막상 작업하면 버그가 너무 많이 생겨서 석 달도 부족해져요.
  • 24:58 - 25:04
    개발 기간이 길어지다보면 나타나는 문제들입니다.
  • 25:04 - 25:10
    그 원인 중 하나는 의존 관계가 많아지는 것 입니다.
  • 25:11 - 25:12
    왜 그럴까요?
  • 25:12 - 25:21
    저건 모듈 끼리 가질 수 있는 의존 관계의 최대치입니다.
  • 25:21 - 25:23
    이건 최소의 경우이지요.
  • 25:23 - 25:29
    연관된 모듈들은 서로 의존하기 마련입니다.
  • 25:29 - 25:32
    트리 형태일 때가 의존도가 제일 적습니다.
  • 25:32 - 25:36
    동적으로 링크한다면 더 적게 만들 수도 있겠지요.
  • 25:36 - 25:40
    하지만 보통은 작은 수의 의존 관계를 갖게 됩니다.
  • 25:40 - 25:42
    의존 관계가 몇 개 있지요? 1. 2. 3. 4. 5. 6.
  • 25:42 - 25:45
    모듈 7개 중에 6개로군요.
  • 25:45 - 25:47
    반면에 여기에는
  • 25:47 - 25:51
    아마도 49의 절반인가 보군요.
  • 25:51 - 25:54
    아니죠 그럼 너무 숫자가 적겠네요.
  • 25:54 - 25:58
    그럼 그냥 49개인가요? 모르겠네요. 어쨌든 아주 많습니다.
  • 25:58 - 26:01
    아마도 몇 인가의 제곱에 비례하겠지요.
  • 26:01 - 26:03
    어쩌면 0.5 * (n^2 + 1) 일 수도 있겠습니다.
  • 26:03 - 26:05
    뭐 그런 식이겠지요.
  • 26:05 - 26:08
    어찌되었건 의존 관계의 수가 아주 많습니다.
  • 26:08 - 26:11
    우리가 원하는 건 이게 아니라 저 트리 모양입니다.
  • 26:11 - 26:13
    저렇게 만들기 위해서 노력을 많이 해야 합니다.
  • 26:13 - 26:21
    그런데 어떤 얼간이가 이렇게 만들어버립니다.
  • 26:24 - 26:26
    비주얼 스튜디오는 이런 걸 금지합니다.
  • 26:27 - 26:29
    하지만 비주얼 스튜디오 솔루션 내에서만 해당되지요.
  • 26:29 - 26:34
    비주얼 스튜디오 솔루션에 속한 프로젝트들은 순환 참조를 할 수가 없습니다.
  • 26:34 - 26:35
    아주 바람직한 거지요.
  • 26:35 - 26:36
    순환 참조를 막아주니까요.
  • 26:36 - 26:39
    하지만 솔루션들 간에는 보장되지 않습니다.
  • 26:39 - 26:40
    비주얼 스튜디오의 솔루션이 여러 개 있다면요
  • 26:40 - 26:45
    서로 다른 솔루션에서 빌드된 것들을 링크한다면 여전히 순환 참조가 가능해집니다.
  • 26:45 - 26:51
    저렇게 순환 참조를 만들면 그냥 의존 관계가 하나 늘어난 것처럼 보이지요.
  • 26:51 - 26:53
    하지만 그냥 하나만 추가되는 게 아닙니다.
  • 26:53 - 26:57
    왜냐하면 6번이 2번을 참조합니다. 1번도 2번을 참조하지요.
  • 26:57 - 26:59
    의존관계는 전이됩니다.
  • 26:59 - 27:05
    그래서 6번은 4번과 5번을 의존합니다. 그리고 6번은 3번과 7번을 의존하지요.
  • 27:05 - 27:07
    결국 6번은 모든 모듈에 의존하는 셈입니다.
  • 27:08 - 27:14
    그래서 순환 참조를 가지는 순간 의존관계의 수는 급격하게 늘어나게 됩니다.
  • 27:22 - 27:24
    다시 n의 제곱 그래프입니다.
  • 27:25 - 27:29
    동시에 C++ 컴파에 걸리는 시간의 그래프이기도 하지요.
  • 27:29 - 27:31
    모듈을 추가함에 따라
  • 27:31 - 27:34
    정적으로 링크한다면 컴파일 시간과 링킹 시간이 제곱에 비례해서 증가합니다.
  • 27:34 - 27:36
    하지만 정적으로 링크하지 않는 경우에도 마찬가지입니다.
  • 27:36 - 27:40
    컴파일 시간은 모듈 수의 제곱에 비례해서 증가합니다.
  • 27:40 - 27:45
    모든 모듈들이 서로 의존하고 있다면 말입니다.
  • 27:45 - 27:52
    '#include', import, using 구문들이 순환되게 참조하고 있다면 말입니다.
  • 27:53 - 27:59
    그렇게 되어 있다면 컴파일 타임이 아주 크게 증가해버립니다.
  • 27:59 - 28:01
    C++은 특히 더 그렇습니다.
  • 28:01 - 28:03
    자바와 닷넷은 그렇지 않습니다.
  • 28:04 - 28:06
    자바와 닷넷의 컴파일 시간은 다른 기준을 가집니다.
  • 28:06 - 28:12
    C++ 과는 다른 방식으로 소스 코드를 참조합니다.
  • 28:12 - 28:15
    자바와 닷넷은 선언문을 얻기 위해 바이너리 파일을 읽습니다.
  • 28:15 - 28:19
    C++은 소스 파일을 읽지요.
  • 28:19 - 28:24
    그래서 C++에선 순환 참조가 발생하면 대가를 치룹니다.
  • 28:25 - 28:27
    매우 긴 컴파일 타임으로 말입니다.
  • 28:27 - 28:29
    아주 심하게요.
  • 28:29 - 28:30
    제곱에 비례해서 증가합니다.
  • 28:30 - 28:33
    그래서 모듈이 몇 개 늘어나면 컴파일 타임이 두 배로 증가해버립니다.
  • 28:33 - 28:36
    그래서 우린 뭔가 조치를 해야만 했습니다.
  • 28:36 - 28:39
    워드 커닝햄이 누구인지 아는 사람 있나요?
  • 28:40 - 28:40
    오. 몇 사람 있군요.
  • 28:40 - 28:42
    좋습니다. 모르는 사람들을 위해서 설명하면
  • 28:42 - 28:43
    워드 커닝햄은 위키를 개발한 사람입니다.
  • 28:43 - 28:47
    워드 커닝햄이 위키를 개발했지요.
  • 28:47 - 28:52
    그리고 캔트 벡을 도와 페어 프로그래밍과 테스트 주도 개발을 발명할 수 있게 했습니다.
  • 28:52 - 28:53
    그리고 대부분의 애자일 방법들도요.
  • 28:53 - 28:57
    워드 커닝햄이 누구인지 알아보세요. 아주 흥미로운 친구입니다.
  • 28:57 - 28:59
    아주 오래 전에 그는 스몰 토크 프로그래머였는데요
  • 28:59 - 29:01
    언젠가 물어봤습니다.
  • 29:01 - 29:03
    "워드, 스몰 토크는 왜 사라진 거지?"
  • 29:03 - 29:10
    그가 말했습니다. "스몰 토크는 너무 쉽게 엉망으로 만들 수 있어서 사라졌어."
  • 29:11 - 29:13
    "너 같은 C++ 프로그래머들은"
  • 29:13 - 29:14
    당시에 나는 C++ 프로그래머였습니다.
  • 29:14 - 29:17
    "C++ 프로그래머들은 운이 좋은 거야."
  • 29:17 - 29:19
    "네가 엉망으로 만들면 대가를 치루게 되거든."
  • 29:20 - 29:22
    "스몰토크는 그러지 않았지."
  • 29:23 - 29:27
    자바나 C#도 그러지 않습니다.
  • 29:27 - 29:29
    대가를 치루지 않아도 됩니다.
  • 29:29 - 29:31
    어렵지 않게 엉망으로 만들 수 있습니다.
  • 29:31 - 29:35
    아주 복잡하게 엉키게 만들어버려도 깨닫지를 못해요.
  • 29:35 - 29:39
    다행스럼게도 비주얼 스튜디오는 일부나마 순환 참조를 막아주지요.
  • 29:44 - 29:49
    우리는 nLogN 수준의 생산성을 추구합니다. nLogN 이죠.
  • 29:49 - 29:52
    n^2 대신에요.
  • 29:53 - 30:00
    컴포넌트간의 의존관계는 이렇게 생산성에 큰 영향을 미칩니다.
  • 30:02 - 30:07
    그리고, 1990년대와 2000년 사이에 큰 변화가 생겼습니다.
  • 30:07 - 30:10
    네트워크 속도가 비약적으로 향상되었지요.
  • 30:11 - 30:16
    요즘에는 1GB 크기의 파일을 받기는 어렵지 않습니다.
  • 30:16 - 30:18
    1GB를 10초만에 업로드 할 수도 있지요.
  • 30:18 - 30:19
    요즘엔 아주 쉬운 일이지만요
  • 30:19 - 30:22
    예전에는 훨씬 어려웠습니다.
  • 30:22 - 30:28
    그래서 예전에는 DLL을 하나만 배포하는게 유리하다고 생각했습니다.
  • 30:29 - 30:32
    요즘에는 그냥 모두 모아서 한 덩어리로 배포하지요.
  • 30:32 - 30:36
    왜요? 네트워크가 충분히 빨라져서 지요. 그냥 보내면 됩니다.
  • 30:36 - 30:40
    많은 DLL들을 그냥 하나로 링크된 바이너리처럼 다룰 수 있습니다.
  • 30:42 - 30:43
    그런데 또 다른 이슈가 있습니다.
  • 30:44 - 30:46
    여기 팀으로 일하는 사람이 얼마나 있지요?
  • 30:47 - 30:50
    그렇지요. 모두가 팀으로 일합니다.
  • 30:51 - 30:54
    아침 8시에 출근을 했다고 생각해봅시다.
  • 30:56 - 30:59
    디버깅할 프로그램이 있었어요.
  • 30:59 - 31:02
    제대로 동작하도록 하루 종일 일했습니다.
  • 31:02 - 31:04
    결국 퇴근 할 때엔 완벽하게 동작하게 만들었지요.
  • 31:04 - 31:05
    체크인하고 퇴근을 합니다.
  • 31:05 - 31:07
    그런데 다음 날에 출근해서 보니 동작을 하지 않았습니다.
  • 31:07 - 31:08
    왜 그럴까요?
  • 31:10 - 31:12
    누군가 당신보다 더 늦게 퇴근을 한 거지요.
  • 31:13 - 31:16
    그 사람이 당신이 사용하는 뭔가를 수정한 것 입니다.
  • 31:17 - 31:22
    그래서 다시 동작하도록 하루 종일 일했습니다.
  • 31:22 - 31:24
    그리고 다음 날 출근해 보니 또 동작을 안 합니다.
  • 31:25 - 31:26
    이런 문제가 얼마나 반복 될 수 있을까요?
  • 31:27 - 31:31
    아주 오랜 기간 가능할 겁니다. 규모가 큰 팀에서는 항상 발생할 수 있는 일입니다.
  • 31:31 - 31:35
    서로 서로 방해하게 되는 거지요.
  • 31:35 - 31:37
    물론 이런 문제를 해결할 툴들이 있지요.
  • 31:37 - 31:39
    소스 코드 관리 시스템이 있고요
  • 31:39 - 31:42
    그 밖에도 수 많은 좋은 툴들이 있습니다.
  • 31:42 - 31:47
    그럼에도 불구하고 제대로 관리하지 않으면 이런 문제는 계속 발생합니다.
  • 31:48 - 31:52
    그럼 프로젝트는 어떻게 관리해야 할까요?
  • 31:56 - 31:58
    여기에 원칙이 있습니다.
  • 32:07 - 32:11
    Acyclic Dependencies Principle 이라고 부릅니다.
    (역주: 비 순환적인 의존관계의 원칙)
  • 32:13 - 32:19
    이런 뜻 입니다. "컴포넌트를 여러 개 가지고 있다면"
  • 32:19 - 32:23
    "순환 참조가 없도록 배열해야 한다."
  • 32:23 - 32:26
    그래야만하는 이유는 여럿 입니다. 이미 하나는 이야기 했지요.
  • 32:26 - 32:30
    컴파일 시간이요. 또 의존 관계로 의한 부하도 이야기 했지요.
  • 32:30 - 32:32
    그리고 하나 더 있습니다.
  • 32:34 - 32:39
    Alarm 모듈의 새로운 버전을 릴리즈하려고 합니다.
  • 32:39 - 32:43
    Alarm 모듈을 담당하는 팀은 1.0 버전을 릴리즈하려고 작업 중입니다.
  • 32:43 - 32:49
    Alarm 모듈은 다른 모듈을 사용하지 않습니다.
  • 32:49 - 32:52
    따라서 자유롭게 릴리즈할 수 있지요.
  • 32:52 - 32:56
    1.0 버전을 릴리즈하고
  • 32:56 - 32:58
    1.1 버전 개발을 착수합니다.
  • 32:59 - 33:02
    그런데 지금 Alarm 1.0 버전이 릴리즈되었니까
  • 33:02 - 33:06
    Elevator 모듈과 Conveyor 모듈도 릴리즈할 수 있게 되었습니다.
  • 33:07 - 33:12
    릴리즈 후에 두 모듈도 각각 1.1 버전 개발을 시작합니다.
  • 33:12 - 33:16
    이제 Transport 모듈도 릴리즈 합니다.
  • 33:16 - 33:18
    어떻게 돌아가는지 알겠지요?
  • 33:18 - 33:21
    버전 넘버가 밑에서부터 타고 올라갑니다.
  • 33:21 - 33:27
    1.0 버전이 밑에서 생성되면. 점 점 위로 전파되어 맨 위에까지 도달합니다.
  • 33:27 - 33:30
    버전 넘버가 밑에서부터 위로 전파되는 거지요.
  • 33:30 - 33:33
    자세히 보면 알게 될 겁니다.
  • 33:33 - 33:38
    버전 넘버가 전파되는 경로는 빌드 순서와 동일합니다.
  • 33:38 - 33:42
    의존 관계는 빌드 순서를 따라 전파됩니다.
  • 33:43 - 33:50
    그런데 어떤 얼간이가 이런 짓을 합니다.
  • 33:50 - 33:53
    누구지요?
  • 33:53 - 33:54
    나에요. 내가 그랬어요.
  • 33:54 - 33:59
    난 알람의 서브시스템을 담당하고 있는데
  • 33:59 - 34:02
    컨트롤 패널 화면에 메시지를 표시해야만 해요.
  • 34:02 - 34:07
    그런데 마침 컨트롤 패널에는 Display라는 펑션이 있더라고요.
  • 34:07 - 34:10
    "오. 이걸 호출하면 되겠군." 하면서 사용했습니다.
  • 34:10 - 34:13
    문제 없이 호출할 수 있었어요.
  • 34:13 - 34:17
    컴파일 됐고, 동작도 문제 없었습니다.
  • 34:18 - 34:23
    그런데 다음 날 사람들이 화가나서 내게 찾아왔지요.
  • 34:24 - 34:25
    "도대체 무슨 짓을 한 거야?"
  • 34:26 - 34:33
    "그냥 컨트롤 패널의 Display 펑션을 호출 했을 뿐이에요."
  • 34:33 - 34:35
    "화면에 메시지를 뿌려야만 했거든요."
  • 34:35 - 34:36
    "그렇게 하면 안되지!"
  • 34:36 - 34:38
    왜 안되는 걸까요?
  • 34:40 - 34:41
    우선
  • 34:44 - 34:48
    저 모듈들은 어떤 순서로 빌드해야 할까요?
  • 34:50 - 34:53
    원래는 밑에서부터 위로 빌드해야 합니다.
  • 34:54 - 34:56
    그런데 지금은 밑이 없습니다.
  • 34:56 - 34:58
    따라서 올바른 빌드 순서가 없습니다.
  • 34:58 - 35:01
    컴포넌트 그래프에서 순환 관계가 있다면
  • 35:02 - 35:06
    올바른 빌드 순서를 정할 수 없게 됩니다.
  • 35:07 - 35:11
    따라서 시스템 동작도 정의할 수 없게 됩니다.
  • 35:12 - 35:15
    "Undefined"가 무슨 뜻 이지요? "Undefined"의 정의가 무엇 인가요?
  • 35:16 - 35:18
    정해진 조건에서만 동작한다는 것 입니다.
  • 35:20 - 35:24
    "Undefined" 인 것은 배포 전에는 잘 동작합니다. 하지만 배포되고 나면 동작하지 않게 되지요.
  • 35:25 - 35:29
    이런 순환참조가 있으면 시스템은 심각한 오류를 발생할 수 있습니다.
  • 35:29 - 35:31
    자바에선 흔히 볼 수 있습니다.
  • 35:31 - 35:36
    순환 참조가 있는 자바 시스템이 있다면......
  • 35:36 - 35:37
    빌드는 할 수 있지요.
  • 35:37 - 35:39
    정확한 빌드 순서가 없더라도 말입니다.
  • 35:39 - 35:41
    그런데 테스트를 돌리면 실패합니다.
  • 35:42 - 35:45
    그런데 다른 순서로 빌드를 하면
  • 35:45 - 35:46
    테스트가 성공하기도 합니다.
  • 35:46 - 35:49
    테스트가 패스할 때까지 계속 빌드를 하는 회사도 본적이 있습니다.
  • 35:55 - 35:56
    그런데 더욱 심각한 문제가 있습니다.
  • 35:57 - 36:04
    Conveyor 모듈을 릴리즈 하려고 합니다.
  • 36:04 - 36:06
    1.1 버전을 릴리즈 하려고 하지요.
  • 36:06 - 36:11
    그러러면 Alarm 1.1 버전과 같이 테스트해야 합니다.
  • 36:12 - 36:18
    하지만 Alarm 1.1 버전은 Control Panel 1.1 버전을 기다리고 있지요. 그리고 Control Panel 1.1 버전은 Transport 1.1 버전을 기다리고 있습니다.
  • 36:18 - 36:22
    Transport 1.1 버전은 지금 릴리즈 하려는 Conveyor 1.1 버전을 기다리고 있습니다.
  • 36:22 - 36:28
    그러므로 모든 소스코드를 한군데에 모으기 전에는 릴리즈 할 방법이 없어집니다.
  • 36:28 - 36:31
    통합작업. 누구 기억하는 사람 있나요?
  • 36:31 - 36:32
    통합작업의 즐거움이요.
  • 36:32 - 36:37
    모든 시스템을 통합한 이후에 동작하게 하는 것 이지요.
  • 36:38 - 36:41
    그러는 동안에는 모듈끼리 서로서로 얽히게 되지요.
  • 36:41 - 36:50
    결국 아침에 출근했더니 코드가 동작하지 않는 문제가 다시 발생하게 됩니다.
  • 36:50 - 36:52
    그런데 더 큰 문제가 있습니다.
  • 36:53 - 36:58
    Conveyor를 테스트하려면 Alarm이 필요한데요
  • 36:58 - 37:02
    Alarm은 Control Panel이 필요하고, Control Panel은 Revenue가 필요하고, Revenue는 데이터베이스가 필요합니다.
  • 37:02 - 37:06
    그리고 데이터베이스는 45분이나 걸려서 로딩했더니 테스트하자마자 죽어버립니다.
  • 37:07 - 37:09
    도저히 테스트를 실행할 수가 없어요.
  • 37:09 - 37:14
    Conveyor 모듈 담당자들은 이야기 합니다. "대체 우리 모듈이 데이터베이스가 왜 필요한 거야!?"
  • 37:14 - 37:17
    "음, 의존관계가 이상하게 꼬여서 데이터베이스가 필요한 거야."
  • 37:18 - 37:22
    프로그램을 실행하고 로딩된 DLL 목록을 보면서 이상하게 여긴 사람 없나요?
  • 37:22 - 37:24
    "내가 왜 이런 것들을 사용하지?"
  • 37:24 - 37:27
    C++ 개발자 중에 링크 목록을 보고 놀랐던 사람 없나요?
  • 37:27 - 37:29
    "왜 이런 것들이 링크 목록에 포함되어있는거야?"
  • 37:29 - 37:31
    "내가 왜 이런 것들을 사용하는 거지?"
  • 37:31 - 37:33
    순환 참조를 가지고 있기 때문입니다.
  • 37:33 - 37:35
    그래서 잡스러운 것들이 이것 저것 끌려오는 거지요.
  • 37:35 - 37:43
    그해서 첫 번째 원칙은 컴포넌트간에 순환 참조가 없어야 한다는 것 입니다.
  • 37:43 - 37:45
    그럼 어떻게 해결할 수 있을까요?
  • 37:46 - 37:52
    밑에 있는 모듈이 저 위에 있는 모듈의 펑션을 호출하려면요?
  • 37:52 - 37:53
    어떻게 하겠습니까?
  • 37:55 - 37:57
    음...... 컴포넌트를 하나 추가해도 되겠지요.
  • 37:58 - 38:00
    가능한 방법 중 하나입니다.
  • 38:00 - 38:03
    Control Panel 컴포넌트에서 클래스를 하나 떼어내서
  • 38:03 - 38:05
    Display 컴포넌트에 추가합니다.
  • 38:05 - 38:08
    Alarm 컴포넌트는 Display 컴포넌트를 호출할 수 있어요.
  • 38:08 - 38:10
    Control Panel 컴포넌트도 Display 컴포넌트를 호출할 수 있습니다.
  • 38:11 - 38:12
    이렇게 하면 순환 관계를 깰 수 있지요.
  • 38:12 - 38:14
    일반적인 방법입니다.
  • 38:14 - 38:16
    이 모든 컴포넌트들은 DLL이었지요?
  • 38:16 - 38:23
    따라서 순환 관계를 추가되면 결국 DLL 수가 늘어나게 됩니다.
  • 38:23 - 38:25
    아마도요.
  • 38:25 - 38:28
    또 다른 해결 방법이 있습니다.
  • 38:30 - 38:33
    Dependency Inversion을 사용하는 것이지요.
  • 38:33 - 38:40
    인터페이스를 하나 만듭니다. Display 인터페이스요.
  • 38:40 - 38:42
    Alarm 서브시스템에 추가합니다.
  • 38:42 - 38:45
    그리고 Control Panel이 Display 인터페이스를 구현하게 합니다.
  • 38:46 - 38:48
    그러면 의존 관계가 뒤집히게 됩니다.
  • 38:50 - 38:53
    그리고 순환 관계도 선형으로 바뀝니다.
  • 39:00 - 39:01
    객체지향은 무엇인가요?
  • 39:04 - 39:06
    객체지향 프로그래밍이 무엇인가요?
  • 39:09 - 39:10
    우리가 왜 좋아할까요?
  • 39:11 - 39:15
    어쩌다 모든 프로그래밍 언어가 객체지향이 되었을까요?
  • 39:15 - 39:17
    벌써 30년동안 사용하고 있습니다. 어떤 것인지는 알아야겠지요.
  • 39:17 - 39:19
    (청중) 현실 세계를 모델링 할 수 있습니다.
  • 39:19 - 39:20
    현실 세계를 모델링 할 수 있다. 감사합니다.
  • 39:20 - 39:23
    내가 이렇게 답하라고 저 사람을 여러분 사이에 심어놨습니다.
  • 39:23 - 39:25
    내가 저사람의 답변을 발기 발기 찢어버리려고요.
  • 39:25 - 39:27
    아닙니다. 아주 터무니없는 이야기에요.
  • 39:27 - 39:32
    객체지향이 실 세계를 모델 하기에 더 좋다는 생각은 말도 안됩니다.
  • 39:32 - 39:35
    그건 오래 전에 어떤 사람이 꾸며낸 이야기입니다.
  • 39:35 - 39:39
    관리자를 설득해서 1만2천 달러짜리 C++ 컴파일러를 사게 하려고요.
  • 39:40 - 39:42
    그 것 말고는 관리자를 설득할 방법을 못 찾았기 때문에요.
  • 39:42 - 39:46
    1만2천 달러. 초기 C++ 컴파일러는 매우 비쌌습니다.
  • 39:46 - 39:48
    "1만2천 달러! 그 돈 주고 컴파일러를 사지는 않겠네."
  • 39:48 - 39:50
    "하지만 그게 있으면 현실 세계를 더 잘 반영할 수 있습니다."
  • 39:50 - 39:53
    "아! 그렇다면야......"
  • 39:53 - 39:58
    실세계를 더 잘 반영한다는 것은 완전히 어리석은 생각입니다.
  • 39:58 - 40:05
    객체지향이란게 그냥 데이터와 펑션들이 같이 모여있다는 것 이외에 뭐가 다를 게 있겠어요?
  • 40:05 - 40:07
    캡슐화요. 좋습니다. 캡슐화.
  • 40:07 - 40:09
    하지만 펑션들이 데이터 구조체를 가진다는 점은
  • 40:09 - 40:12
    객체지향이 아닌 언어와 다를 게 있나요?
  • 40:13 - 40:15
    쉽게 답하기는 어렵지요.
  • 40:16 - 40:18
    어떻게 다를까요?
  • 40:18 - 40:22
    네. 데이터 구조체를 펑션과 같이 넣어서 사용하고 있지요.
  • 40:22 - 40:24
    하지만 항상 그래왔습니다.
  • 40:24 - 40:27
    예전의 C 프로그래머도 항상 그래왔습니다.
  • 40:27 - 40:30
    데이터 구조체도 항상 같이 있었죠.
  • 40:30 - 40:34
    아주 유명한 책이 있었지요. "Algorithms plus data structures equals programs"
  • 40:34 - 40:37
    데이터 구조와 펑션이 같이 동작합니다.
  • 40:37 - 40:39
    객체지향에 특별할 것은 없습니다.
  • 40:39 - 40:44
    하지만 객체지향으로 인해 가능해진 게 하나 있긴 합니다.
  • 40:44 - 40:46
    예전에는 위험해서 잘 안 썼지요.
  • 40:46 - 40:47
    다형성입니다.
  • 40:47 - 40:51
    아주 사용하기 쉬운 다형성이지요.
  • 40:51 - 40:53
    C에도 있긴 했습니다.
  • 40:54 - 40:58
    하드웨어에 독립적인 모든 OS는 다형성의 예입니다.
  • 40:58 - 41:03
    어떤 디바이스를 사용할지 모르고 프로그램을 작성할 수 있다면
  • 41:03 - 41:05
    분명히 다형적인 특징을 사용하고 있는 것 입니다.
  • 41:06 - 41:09
    하지만 대부분의 언어에서는 위험합니다.
  • 41:09 - 41:10
    적어도 예전에는 그랬습니다.
  • 41:10 - 41:12
    왜냐하면 펑션 포인터들을 만지작거려야 하거든요.
  • 41:12 - 41:14
    항상 위험한 작업이었지요.
  • 41:15 - 41:19
    객체지향의 도입으로 아주 편리하게 구현할 수 있게 되었습니다.
  • 41:19 - 41:21
    특별히 다형성을 생각하지 않아도 됩니다.
  • 41:21 - 41:24
    자바 같은 경우에는 모든 메소드가 다형적입니다.
  • 41:24 - 41:25
    선택의 여지가 없지요.
  • 41:25 - 41:29
    C#은 선택할 수 있습니다. virtual 키워드를 사용하면 되지요.
  • 41:29 - 41:35
    C++ 프로그래머도 선택할 수 있지요. virtual 키워드를 사용하면 됩니다. 소멸자에는 반드시 써야 하지요.
  • 41:36 - 41:39
    하지만 대부분 별로 신경을 쓰지 않아도 됩니다.
  • 41:39 - 41:42
    모든 펑션들이 다형적이에요. 특별히 신경 쓰지 않아도 됩니다.
  • 41:42 - 41:43
    왜 그럴까요?
  • 41:44 - 41:49
    펑션이 다형적 특징을 가지고 있다면 뭔가 근사한 일이 생깁니다.
  • 41:50 - 41:55
    컨트롤 흐름은 상위 클래스에서 하위 클래스로 향합니다.
  • 41:55 - 41:59
    하지만 소스코드의 의존관계는 반대로 하위 클래스에서 상위 클래스로 향합니다.
  • 42:00 - 42:08
    런타임 의존관계를 변경하지 않고도 소스코드의 의존관계를 뒤집을 수 있습니다.
  • 42:08 - 42:10
    DLL을 어떻게 만들지요?
  • 42:10 - 42:12
    컴포넌트는 어떻게 만드나요?
  • 42:12 - 42:14
    다른 것들과 분리시켜서 만듭니다.
  • 42:14 - 42:17
    하지만 런타임 의존관계는 유지해야 합니다.
  • 42:21 - 42:23
    비주얼스튜디오 쓰는 사람들
  • 42:25 - 42:28
    ReSharper 사용하나요?
  • 42:29 - 42:30
    ReSharper 사용하는 사람?
  • 42:30 - 42:32
    보세요. 모두가 사용합니다.
  • 42:33 - 42:36
    비주얼스튜디오가 ReSharper에 대해서 아나요?
  • 42:38 - 42:39
    아닙니다.
  • 42:39 - 42:42
    비주얼스튜디오가 ReSharper를 호출하나요?
  • 42:43 - 42:45
    그렇지요.
  • 42:45 - 42:49
    컨트롤 흐름은 비주얼 스튜디오에서 Resharper로 향합니다.
  • 42:49 - 42:54
    비주얼 스튜디오는 필요한대로 ReSharper의 펑션을 호출합니다.
  • 42:54 - 43:01
    하지만 비주얼스튜디오 소스 코드는 ReSharper의 소스 코드에 의존하지 않지요.
  • 43:01 - 43:03
    왜냐하면 의존 관계의 방향이 뒤집어졌기 때문이지요.
  • 43:04 - 43:10
    어플리케이션이 어떤 걸 호출할지 모르는 상태에서도
  • 43:10 - 43:12
    호출될 DLL들을 만들 수 있습니다.
  • 43:13 - 43:16
    의존 관계를 뒤집어서 말입니다.
  • 43:16 - 43:17
    의존 관계가 역전되는 거지요.
  • 43:17 - 43:19
    이 것도 순환 참조를 해결하는 좋은 방법입니다.
  • 43:20 - 43:29
    그럼 Control Panel은 Alarm 시스템에 플러그인이 됩니다.
  • 43:29 - 43:32
    Alarm 시스템은 Control Panel에 대해서 모릅니다.
  • 43:32 - 43:36
    Control Panel 은 플러그인이에요.
  • 43:36 - 43:39
    Alarm 시스템은 어떤 플러그인이라도 사용할 수 있습니다.
  • 43:39 - 43:43
    어떤 것이든지 이 Display 펑션을 구현할 수 있습니다.
  • 43:43 - 43:45
    그러면 아주 많은 것들에 알람을 적용할 수 있는 거지요.
  • 43:53 - 43:55
    어떤 것에 의존하겠습니까?
  • 44:02 - 44:05
    안정적인 컴포넌트를 의존하겠습니까?
  • 44:07 - 44:09
    아니면 불안정한 컴포넌트요?
  • 44:11 - 44:12
    뻔한 질문입니다.
  • 44:12 - 44:18
    누구나 안정적인 것을 의존하고 싶어합니다.
  • 44:23 - 44:25
    그러면 안정적이라는 단어를 정의해봅시다.
  • 44:29 - 44:31
    내 레이저 포인터는 안정적인가요?
  • 44:34 - 44:36
    이건 변하지는 않지요.
  • 44:39 - 44:41
    하지만 안정적인가요?
  • 44:41 - 44:44
    안정성은 그렇다 아니다로 표현할 수가 없습니다.
  • 44:44 - 44:46
    안정성은 지속적인 특징을 가집니다.
  • 44:46 - 44:51
    그리고 변화 시키는 데에 필요한 일의 양으로 정의되지요.
  • 44:51 - 44:53
    힘이 많이 필요하면 안정적인 것 입니다.
  • 44:53 - 44:56
    조금의 힘으로도 변화시킬 수 있다면 불안정적인 것이지요.
  • 44:56 - 45:00
    저건 불안정적 입니다.
  • 45:00 - 45:04
    조금만 힘을 써도 상태를 변경시킬 수 있거든요.
  • 45:04 - 45:09
    이건 안정적이라고 말하진 않겠습니다.
  • 45:09 - 45:12
    뒤집는데 힘이 많이 들지 않겠거든요.
  • 45:12 - 45:15
    그리고 여기 강단은 그다지 안정적이지 않은 것 같아요.
  • 45:16 - 45:19
    조심해서 움직여야겠네요.
  • 45:19 - 45:22
    다시 질문해보겠습니다.
  • 45:22 - 45:25
    어떤 것을 의존하겠습니까?
  • 45:25 - 45:27
    쉽게 변경되는 것에 의존하겠어요?
  • 45:27 - 45:29
    아니면 잘 변경되지 않는 것에요?
  • 45:29 - 45:33
    소스코드를 수정하는 경우라면 요?
  • 45:34 - 45:35
    어떤 것에 의존 하겠습니까?
  • 45:35 - 45:40
    소스 코드 변경하기 어려운 모듈에 의존할까요? 아니면 소스 코드를 변겨하기 쉬운 모듈에요?
  • 45:42 - 45:43
    같은 답변입니다.
  • 45:43 - 45:46
    변경하기 어려운 것에 의존해야 합니다.
  • 45:46 - 45:49
    이유는 아주 간단합니다.
  • 45:49 - 45:52
    문자열 클래스를 사용하기 꺼려지나요?
  • 45:52 - 45:53
    아닙니다.
  • 45:53 - 45:55
    왜지요?
  • 45:55 - 45:58
    만약에 누군가가 문자열 클래스를 변경한다면 큰 대가를 지불할 겁니다.
  • 46:00 - 46:01
    문자열 클래스를 사용하는 여러분 보다 훨씬 더 괴로울 거에요.
  • 46:02 - 46:04
    그게 우리가 이야기하는 방정식입니다.
  • 46:04 - 46:06
    어떤 모듈을 사용하는 조건은 다음과 같습니다.
  • 46:07 - 46:12
    그 모듈이 변경됐을 경우 나보다 그 모듈의 개발자가 할 일이 더 많으면 사용합니다.
  • 46:12 - 46:14
    그게 적절한 조건이에요.
  • 46:14 - 46:16
    그런 경우엔 안심하고 사용할 수 있습니다.
  • 46:16 - 46:19
    그 모듈이 잘 변경되지 않을 것 같거나 변경되더라도 그걸 변경한 나쁜 자식이 합당한 대가를 치루게 되는 경우 말입니다.
  • 46:19 - 46:25
    그렇습니다. 우린 손쉽게 변경되는 것에 의존하지 않으려고 합니다.
  • 46:27 - 46:29
    잘 생각해보세요.
  • 46:29 - 46:33
    쉽게 변경되는 것에는 의존하지 않습니다.
  • 46:35 - 46:40
    시스템을 설계할 때에 쉽게 변경할 수 있게 만드는 곳이 있나요?
  • 46:43 - 46:44
    있습니다.
  • 46:44 - 46:50
    시스템 중 어떤 부분이 가장 쉽게 변경될 수 있어야 하지요?
  • 46:53 - 46:54
    GUI입니다.
  • 46:57 - 46:58
    GUI는 쉽게 변합니다.
  • 46:58 - 47:02
    특별한 이유 없이 바뀌기도 합니다.
  • 47:02 - 47:05
    사람들은 그냥 느낌 만으로도 GUI를 변경하기도 하지요.
  • 47:05 - 47:08
    제품 위원회에서 이야기합니다.
  • 47:08 - 47:10
    "이봐, 우리 시스템은 좀 오래되 보여"
  • 47:10 - 47:12
    그게 무슨 말인가요?
  • 47:12 - 47:15
    "우리 시스템은 좀 오래되 보여. 디자인을 바꿔야겠어."
  • 47:15 - 47:19
    "마케팅 팀에서 결정 났어. 완전 새로운 Look & Feel을 입히자고."
  • 47:19 - 47:21
    "동작을 변경할 필요는 없고"
  • 47:21 - 47:23
    "GUI의 Look & Feel 만 변경하는 거야."
  • 47:23 - 47:25
    GUI는 쉽게 바꿀 수 있어야 합니다.
  • 47:25 - 47:29
    GUI 모듈의 소스 코드는 쉽게 변경할 수 있어야 합니다.
  • 47:29 - 47:33
    그 건 다른 모듈이 GUI 모듈에 의존하면 안 된다는 말이지요.
  • 47:34 - 47:37
    어떤 모듈의 소스 코드도 GUI 모듈을 참조해선 안됩니다.
  • 47:38 - 47:42
    GUI 모듈을 향하는 의존 관계가 없어야 합니다.
  • 47:42 - 47:45
    GUI 컴포넌트가 어플리케이션의 다른 모듈들을 의존해야 합니다.
  • 47:45 - 47:49
    다른 컴포넌트들은 GUI 컴포넌트에 의존하면 안됩니다.
  • 47:49 - 47:53
    그렇지 않으면 결국 시스템의 GUI는 수정하기 어렵게 될 겁니다.
  • 47:53 - 47:57
    시스템을 테스트하는 사람이 얼마나 되나요?
  • 47:57 - 47:58
    자동화된 테스트요.
  • 47:59 - 48:00
    GUI를 통해서요.
  • 48:03 - 48:04
    두어 사람 있군요.
  • 48:05 - 48:07
    GUI를 통해서 테스트를 한다고요.
  • 48:07 - 48:11
    그렇다면 쉽게 변해야 하는 것에 의존하고 있는 것 입니다.
  • 48:11 - 48:13
    그러면 결국 GUI 변경하기 어렵게 만들 겁니다.
  • 48:13 - 48:16
    GUI를 통해서 시스템을 테스트를 한다면요.
  • 48:16 - 48:19
    15,000개의 테스트를 GUI를 통해서 수행하는 고객이 있었습니다.
  • 48:19 - 48:21
    앞에서 이야기한 그 고객입니다.
  • 48:21 - 48:22
    그 망한 고객이요.
  • 48:22 - 48:26
    GUI 기반의 15,000개의 테스트요.
  • 48:26 - 48:29
    테스트가 너무 많아서 어떤 테스트인지도 모르고 있었지요.
  • 48:29 - 48:31
    그냥 모두 패스해야 한다는 것만 알았지요.
  • 48:31 - 48:33
    누군가 GUI를 변경한다면요
  • 48:33 - 48:35
    테스트 케이스 중 1000개는 실패하겠지요.
  • 48:35 - 48:37
    너무 많아서 수정하기도 힘들었겠지요.
  • 48:37 - 48:39
    그래서 아주 간단한 규칙을 생각해냈습니다.
  • 48:39 - 48:41
    무엇이었을까요?
  • 48:41 - 48:44
    GUI는 변경하지 않는다!
  • 48:44 - 48:47
    그들은 GUI를 변경하기 어렵게 만들었어요.
  • 48:48 - 48:52
    테스트 케이스를 못쓰게 되는 경우도 있었겠지요.
  • 48:53 - 48:58
    12 M/M를 투자해서 GUI를 통한 테스트 수트를 만들었다고 합시다.
  • 48:58 - 49:02
    그런데 누군가 결정했어요. "GUI 디자인을 변경해야겠어."
  • 49:02 - 49:04
    "기존 GUI를 걷어내고 새로운 GUI를 개발합시다."
  • 49:04 - 49:06
    테스트들은 쓸모가 없어집니다.
  • 49:06 - 49:10
    테스트 케이스를 다시 작성해야 합니다. 하지만 테스트할 시스템이 그 것만 있는 게 아니지요.
  • 49:10 - 49:12
    GUI는 테스트하지 마세요.
  • 49:12 - 49:14
    GUI를 통해서는 아무것도 하지 마세요.
  • 49:14 - 49:19
    어떤 의존 관계도 GUI를 향해선 안됩니다.
  • 49:19 - 49:23
    쉽게 변경하고 싶어하는 게 또 뭐가 있을까요?
  • 49:23 - 49:26
    데이터베이스요.
  • 49:26 - 49:28
    데이터베이스도 쉽게 변경하고 싶어하지요.
  • 49:28 - 49:32
    어플리케이션을 엎어버리지 않고 데이터베이스를 변경 할 수 있기를 원합니다.
  • 49:34 - 49:38
    어떤 의존 관계도 데이터베이스로 향하면 안되겠지요.
  • 49:38 - 49:41
    아무 것도 데이터베이스를 의존하지 않게 해야 합니다.
  • 49:41 - 49:44
    아무 것도 GUI를 의존하지 않게 해야 합니다.
  • 49:46 - 49:54
    불안정적인 것은 의존하면 안됩니다.
  • 49:55 - 49:58
    불안정성은 어떻게 측정 할 수 있을까요?
  • 50:02 - 50:04
    저기 보이나요?
  • 50:05 - 50:06
    저기 위에 있는 컴포넌트요.
  • 50:07 - 50:09
    저건 안정적인가요? 아니면 불안정적인가요?
  • 50:09 - 50:13
    많은 모듈들이 의존하고 있지요.
  • 50:13 - 50:16
    자기가 의존하는 것은 없습니다.
  • 50:16 - 50:17
    따라서 변경하기 어렵지요.
  • 50:17 - 50:20
    변경을 하게 되면 다른 모듈들에도 영향을 미칩니다.
  • 50:20 - 50:25
    따라서 저 컴포넌트는 다른 모듈들에 책임을 지게 되는 거지요.
  • 50:25 - 50:29
    음 이 컴포넌트는 독립적이군요.
  • 50:29 - 50:31
    다른 모듈을 의존하지는 않습니다.
  • 50:31 - 50:33
    책임감있고 독립적입니다.
  • 50:33 - 50:34
    마치 어른 처럼요.
  • 50:37 - 50:39
    안정적이고 어른과 같습니다.
  • 50:40 - 50:41
    저기 아래 컴포넌트를 보세요.
  • 50:42 - 50:44
    많은 모듈들을 이용하고 있네요.
  • 50:45 - 50:47
    저 컴포넌트를 이용하는 모듈은 없어요.
  • 50:47 - 50:48
    책임질 필요가 없겠지요?
  • 50:48 - 50:50
    그리고 의존적입니다.
  • 50:50 - 50:51
    청소년과 같습니다.
  • 50:52 - 50:54
    그리고 안정적이지 않습니다.
  • 50:54 - 50:58
    서로 완전히 반대되는 컴포넌트들이지요.
  • 50:58 - 51:00
    컴포넌트 종류의 양 극단이라고 할 수 있습니다.
  • 51:00 - 51:03
    아주 안정적인 어른과
  • 51:03 - 51:07
    아주 불안정적인 청소년이지요.
  • 51:07 - 51:09
    불안정적인 것은 쉽게 변합니다.
  • 51:09 - 51:12
    가능한 코드를 적게 넣어야겠지요.
  • 51:12 - 51:15
    안정적인 것은 변경하기 어렵습니다.
  • 51:16 - 51:23
    안정적인 정도를 측정할 수 있는 지표를 만들 수 있습니다.
  • 51:23 - 51:26
    'I'라고 부를 거에요.
  • 51:27 - 51:34
    'I' 는 다른 것을 이용하는 관계의 수를
  • 51:34 - 51:37
    나를 이용하는 관계의 수와 다른 것을 이용하는 관계의 수를 더한 것으로 나눈 값입니다.
  • 51:37 - 51:40
    곰곰히 생각해보면
  • 51:40 - 51:44
    'I'는 0부터 1 사이의 값이라는 것을 알게 될 것 입니다.
  • 51:44 - 51:47
    0은 안정적이고, 1은 불안정적입니다.
  • 51:47 - 51:50
    0은 어른이고, 1은 청소년입니다.
  • 51:50 - 51:53
    모두 의존 관계에 대한 이야기입니다.
  • 51:53 - 51:59
    자 그럼 원칙을 다르게 표현해보겠습니다.
  • 52:06 - 52:14
    컴포넌트는 자기보다 잘 변하지 않는 것에 의존해야 한다.
  • 52:14 - 52:22
    다르게 말한다면, 의존 관계의 방향은 'I'가 감소하는 방향으로 향해야 한다.
  • 52:22 - 52:25
    불안정성이 감소하는 것은 안정성이 높아지는 것 이지요.
  • 52:25 - 52:31
    참조하는 수와 참조되는 수를 가지고 간단하게 확인할 수 있어요.
  • 52:32 - 52:37
    순환 참조가 왜 나쁘지요?
  • 52:38 - 52:41
    안정적인 것이 잘 변하는 것을 이용하게되기 때문입니다.
  • 52:45 - 52:48
    그러면 새로운 문제가 생깁니다.
  • 52:48 - 52:50
    뭐냐하면
  • 52:55 - 52:56
    저 맨 밑에 있는 컴포넌트는 어떻지요?
  • 52:58 - 52:59
    안정적인가요? 아닌가요?
  • 53:01 - 53:03
    아주 안정적인 컴포넌트입니다.
  • 53:03 - 53:05
    맨 밑에 위치하기도 하고
  • 53:05 - 53:08
    많은 모듈들이 사용하고 있습니다.
  • 53:09 - 53:10
    변경하기 아주 어려워요.
  • 53:11 - 53:15
    저 컴포넌트를 수정하면 많은 모듈들이 영향을 받게 됩니다.
  • 53:15 - 53:18
    그냥 버전 넘버만 바뀌었는데도 말입니다.
  • 53:24 - 53:29
    저 밑에 있는 것들은 변경하기가 아주 까다롭지요.
  • 53:31 - 53:33
    하지만 벗어날 방법이 있습니다.
  • 53:34 - 53:35
    다형성을 사용하는 것 입니다.
  • 53:37 - 53:43
    어떻게 하면 쉽게 확장되게 만들 수 있을까요?
  • 53:44 - 53:46
    변경하기 까다로운 것이라도 말입니다.
  • 53:49 - 53:50
    추상 클래스로 만드는 것 입니다.
  • 53:51 - 53:54
    추상 클래스는 쉽게 확장할 수 있습니다.
  • 53:55 - 53:57
    직접 수정하지 않고도
  • 53:57 - 54:00
    시스템에 새로운 피처를 추가할 수 있습니다.
  • 54:00 - 54:06
    새로운 기능을 파생 클래스에 담아서 말입니다.
  • 54:06 - 54:09
    그래서 마지막 원칙은 다음과 같습니다.
  • 54:10 - 54:16
    밑에 위치할 수록 더욱 추상적이어야 한다.
  • 54:16 - 54:18
    저 위의 것은 구체적입니다.
  • 54:19 - 54:20
    불안정하고 구체적이지요.
  • 54:20 - 54:23
    저 밑의 것은 추상적이고 안정적입니다.
  • 54:23 - 54:30
    저 트리를 따라 내려갈 수록 추상성은 점점 커져갑니다.
  • 54:32 - 54:39
    추상성은 숫자로 표현될 수 있습니다.
  • 54:39 - 54:46
    추상 클래스의 개 수를 컴포넌트의 전체 클래스 수로 나누는 것 이지요.
  • 54:47 - 54:50
    그러면 0부터 1 사이의 'A' 값을 구할 수 있습니다.
  • 54:50 - 54:52
    0은 구체적인 것 이고요.
  • 54:52 - 54:55
    1은 모두 추상적인 것 입니다. 컴포넌트에 인터페이스 밖에 없는 거지요.
  • 54:55 - 54:59
    그러면 아주 흥미로운 일을 할 수 있습니다.
  • 54:59 - 55:09
    컴포넌트의 'A'와 'I'의 값을 합치면 1이됩니다.
  • 55:09 - 55:13
    'A' 가 1이어서 추상적이거나
  • 55:13 - 55:16
    'I'가 0이어서 안정적입니다.
  • 55:16 - 55:20
    'I'가 0인 경우 불안정적이고
  • 55:20 - 55:21
    'A'가 0인 경우 구체적입니다.
  • 55:21 - 55:23
    'A'와 'I'를 합하면 1이됩니다.
  • 55:23 - 55:27
    마법의 공식입니다. 'A' 더하기 'I'는 1입니다.
  • 55:27 - 55:31
    저기 위에 추상적인 어른이 있지요
  • 55:31 - 55:33
    다른 모두가 의존하고 있습니다. 안정적이란 말이지요.
  • 55:33 - 55:36
    저기 아래에 청소년이 있습니다.
  • 55:37 - 55:42
    다른 곳에서 사용하고 있지 않지요. 하지만 구체적입니다.
  • 55:42 - 55:44
    이 것은 무엇인가요?
  • 55:44 - 55:47
    'A'와 'I'의 합이 1인 것을 보여주고 있지요.
  • 55:48 - 55:53
    컴포넌트들은 저 두 끝 지점에 위치하는 게 가장 이상적이겠지요.
  • 55:53 - 55:54
    왜 그럴까요?
  • 55:56 - 55:59
    여기 왼쪽 위에는 어떤가요?
  • 56:01 - 56:04
    아주 추상적이지요. 아무 것도 의존하지 않습니다.
  • 56:05 - 56:08
    인터페이스가 구현하는 모듈이 하나도 없는 경우이지요. 쓸모 없습니다.
  • 56:09 - 56:11
    여기 쓸 데가 없는 것들입니다.
  • 56:11 - 56:14
    컴포넌트를 저쪽에 위치하게 하면 안됩니다.
  • 56:14 - 56:16
    그럼 여기 오른쪽 아래에는 어떤가요?
  • 56:17 - 56:20
    아주 구체적입니다. 모두가 의존하고 있습니다.
  • 56:20 - 56:22
    데이터베이스 스키마.
  • 56:23 - 56:25
    구체적입니다. 모두가 의존하고 있지요.
  • 56:25 - 56:27
    변경하면 아주 재미나겠지요.
  • 56:27 - 56:30
    그렇지요? 여기 밑에 위치하면 안됩니다.
  • 56:30 - 56:31
    아주 고통스러운 구역이에요.
  • 56:32 - 56:36
    컴포넌트는 저 두 지점에서 가능한 멀리 위치해야 합니다.
  • 56:36 - 56:39
    이상적으로는 컴포넌트를 여기 여기에 위치하면 좋겠지만
  • 56:39 - 56:42
    그렇게 하면 컴포넌트가 까다로워집니다.
  • 56:42 - 56:45
    그래서 최소한 이 선 위에 위치하도록 해야 합니다.
  • 56:46 - 56:48
    아니면 선에 가깝게요.
  • 56:49 - 56:51
    여기에서 마지막 측정 기준이 나옵니다.
  • 56:53 - 56:54
    'D' 입니다.
  • 56:54 - 56:57
    컴포넌트가 저 선에서 얼마나 떨어져있나를 의미합니다.
  • 56:58 - 57:02
    'D'는 'A' 더하기 'I' 빼기 1의 절대값 입니다.
  • 57:02 - 57:05
    계산하기 어렵지 않습니다.
  • 57:05 - 57:07
    'D'는 0과 1사이의 값입니다.
  • 57:07 - 57:10
    0은 선위에 있다는 뜻이고
  • 57:10 - 57:12
    1은 저 나쁜 두 지점에 있다는 것 입니다.
  • 57:12 - 57:15
    저 두 지점 중에 어느 쪽이냐는 절대값 기호를 빼면 알 수 있겠지요.
  • 57:15 - 57:16
    뭐 상관 없습니다.
  • 57:16 - 57:22
    'D'는 의존하는 관계와 의존되는 관계를 보고 알 수 있습니다.
  • 57:22 - 57:24
    추상적인 정도를 측정하는 것 이지요.
  • 57:24 - 57:28
    계산 자체는 어렵지 않습니다.
  • 57:28 - 57:34
    컴포넌트가 저 선위에 있는지 보세요
  • 57:34 - 57:40
    선 위에 있으면 추상적이고 의존되고 있지요.
  • 57:41 - 57:47
    선 위에 없으면 추상적이지만 의존되고 있지 않은 것 입니다.
  • 57:47 - 57:49
    아니면 아주 구체적인데 많이 참조되고 있는 것 입니다.
  • 57:49 - 57:50
    둘다 아주 나쁜 거지요.
  • 57:51 - 57:55
    많은 툴들이 이런 지표들을 자동으로 계산해줍니다.
  • 57:55 - 57:59
    NDepend 써봤나요? NDepend도 이런 지표들을 계산해줍니다.
  • 57:59 - 58:03
    대부분의 정적 분석 툴들이
  • 58:03 - 58:06
    I, D 와 같은 지표들을 계산해줍니다.
  • 58:06 - 58:10
    컴포넌트들의 지표 값들을 쉽게 확인할 수 있습니다.
  • 58:10 - 58:14
    그리고 어떤 것들이 변경하기 쉬워야 할지 생각해보세요.
  • 58:15 - 58:18
    변경하기 쉬운 것들은 청소년과 같은 것들입니다.
  • 58:19 - 58:24
    변경하기 어려운 것은 성인과 같아야 하고 추상적이어야 합니다.
  • 58:24 - 58:28
    구체적이고 청소년 같은 것 들은 변경하기 쉬워야 합니다.
  • 58:28 - 58:32
    추상적이고 어른과 같은 것 들은 변경하기 어려워야 합니다.
  • 58:33 - 58:34
    질문있나요?
  • 58:36 - 58:40
    PDP-8 어셈블리 코드로 시작해서 여기까지 왔군요.
  • 58:43 - 58:45
    질문 있나요? 없어요?
  • 58:45 - 58:46
    좋습니다.
  • 58:47 - 58:48
    이런
  • 58:50 - 58:51
    괜찮습니다. 좋아요.
  • 58:51 - 58:57
    (질문 중)
  • 58:57 - 58:57
  • 58:57 - 59:03
    (질문 중)
  • 59:03 - 59:05
    두 개의 버전이요.
  • 59:05 - 59:07
    (질문 중)
  • 59:07 - 59:10
    하나의 컴포넌트가 2개의 버전으로 존재하는 경우요. 아주 어렵지요.
  • 59:11 - 59:11
  • 59:12 - 59:15
    같은 컴포넌트의 각각 다른 버전의 파일들을 한 시스템에 두지 마세요.
  • 59:15 - 59:17
    그게 DLL 지옥입니다.
  • 59:18 - 59:20
    다른 사람 있나요?
  • 59:21 - 59:24
    String 클래스의 위치는 어디냐고요? 아주 아주 좋은 질문입니다.
  • 59:24 - 59:26
    String 클래스는 저기에 위치합니다.
  • 59:27 - 59:32
    최악의 자리지요. 하지만 아무도 변경하지 않습니다. 따라서 신경 쓸 필요 없습니다.
  • 59:32 - 59:36
    오늘의 모든 이야기는 현재 개발중인 것에 해당됩니다.
  • 59:36 - 59:38
    현재 변경 중인 것 이요.
  • 59:38 - 59:43
    우리 라이브러리의 변경되고 있는 것들을 아주 유의해서 봐야 합니다.
  • 59:43 - 59:46
    라이브러리 중에서 변경되지 않는 것이나
  • 59:46 - 59:49
    변경되지 않는 오래된 라이브러리의 것 들은
  • 59:49 - 59:50
    신경 쓸 필요가 없습니다.
  • 59:51 - 59:52
    그 중 많은 것들이 저런 곳에 위치하겠지만
  • 59:52 - 59:53
    괜찮습니다.
  • 59:53 - 59:55
    저기에 위치하는 것은 없을 것 입니다.
  • 59:56 - 59:58
    뭐 조금은 있을 수도 있겠지요
  • 59:58 - 60:00
    죽은 코드를 제거해본 적 있나요?
  • 60:00 - 60:02
    아무도 상속받지 않는 추상 클래스처럼요?
  • 60:02 - 60:05
    네 실제로 조금은 있을 수 있겠어요.
  • 60:05 - 60:12
    String, Vector, 그 밖의 라이브러리 등이 저기에 위치할 수 있겠습니다. 하지만 신경 쓸 필요 없습니다. 쉽게 변경되지 않을 테니까요.
  • 60:12 - 60:16
    저 그래프로부터 제 3의 축이 여러분 쪽으로 향한다고 생각해보세요.
  • 60:16 - 60:18
    그게 가변성에 대한 축입니다.
  • 60:18 - 60:22
    이 화면의 그래프는 가변성이 1에 가까운 상황이죠.
  • 60:22 - 60:25
    가변성이 0인 경우는 신경 쓸 필요가 없습니다.
  • 60:26 - 60:27
    또 질문 있나요?
  • 60:28 - 60:29
    저기 뒤에요.
Title:
Robert C. Martin: Principles of Component Design.
Description:

more » « less
Video Language:
English

Korean subtitles

Revisions