1 00:00:02,391 --> 00:00:06,929 안녕하세요. 산드로 만쿠소 입니다. 2 00:00:06,929 --> 00:00:09,533 이 스크린 케스트에선 3 00:00:09,533 --> 00:00:15,865 테스트 코드가 없는 기존 코드에 4 00:00:15,865 --> 00:00:18,125 먼저 테스트를 작성하고요 5 00:00:18,125 --> 00:00:20,568 테스트 커버리지가 100%가 된 후에 6 00:00:20,568 --> 00:00:23,567 리팩토링으로 개선하는 것을 보여드리겠습니다. 7 00:00:23,567 --> 00:00:25,594 예제의 비즈니스 요구사항은 8 00:00:25,594 --> 00:00:28,607 여행자를 위한 소셜 네트워킹 서비스 같은 것입니다. 9 00:00:28,607 --> 00:00:33,597 콘텐츠를 보려면 로그인을 해야 하고 10 00:00:33,597 --> 00:00:35,550 로그인 후에 11 00:00:35,550 --> 00:00:37,462 다른 사람의 여행 일정을 보려면 12 00:00:37,462 --> 00:00:39,887 그 사람과 친구인 경우에만 조회가 가능합니다. 13 00:00:39,887 --> 00:00:42,125 페이스 북 처럼 말입니다. 14 00:00:42,125 --> 00:00:45,553 그 사람과 친구라면 그 사람의 여행 목록을 볼 수 있고 15 00:00:45,553 --> 00:00:47,678 친구가 아니라면 볼 수가 없습니다. 16 00:00:49,268 --> 00:00:51,169 이 카타에는 규칙이 몇 개 있습니다. 17 00:00:51,169 --> 00:00:56,129 테스트가 없는 코드는 수정을 할 수 없습니다. 18 00:00:57,219 --> 00:01:03,179 따라서 기존 제품 코드를 수정하려면 19 00:01:03,179 --> 00:01:04,980 먼저 기존 코드에 테스트 코드를 작성해야 합니다. 20 00:01:04,980 --> 00:01:10,258 유일한 예외는 IDE의 리팩토링 기능을 사용하는 것 입니다. 21 00:01:10,258 --> 00:01:14,713 절대 소스 코드에 타이핑해서 수정을 하면 안됩니다. 22 00:01:16,063 --> 00:01:19,632 테스트를 작성해가는 순서가 있는데요 23 00:01:19,632 --> 00:01:24,114 소스 코드가 이렇게 생겼다면요 24 00:01:24,114 --> 00:01:29,233 여기 인덴트가 깊은 부분 말고 25 00:01:29,503 --> 00:01:34,435 뎁스가 가장 얕은 부분부터 테스트를 작성할 것 입니다. 26 00:01:35,148 --> 00:01:39,569 그 후에 그 다음으로 얕은 부분의 27 00:01:39,569 --> 00:01:41,472 테스트를 작성하는 거지요. 28 00:01:41,472 --> 00:01:45,420 이런 순서로 테스트를 작성하면 29 00:01:45,527 --> 00:01:47,770 테스트를 작성함에 따라 제품 코드를 더 깊게 이해해 갈 수 있고 30 00:01:47,882 --> 00:01:54,287 테스트 스윗도 점진적으로 만들어 갈 수 있습니다. 31 00:01:54,287 --> 00:01:58,375 만약에 반대로 32 00:01:58,375 --> 00:02:00,209 가장 깊은 부분부터 테스트를 작성하려면 33 00:02:00,209 --> 00:02:06,100 처음부터 대상 코드를 모두 이해해야 하고 34 00:02:06,933 --> 00:02:09,392 많은 양의 테스트 데이터를 준비해야 합니다. 35 00:02:09,392 --> 00:02:13,196 그래서 코드의 얕은 부분에서 깊은 부분으로 테스트하는 것이 좋습니다. 36 00:02:13,196 --> 00:02:15,263 이제 코드를 볼까요 37 00:02:15,263 --> 00:02:20,094 TripService 클래스인데요 38 00:02:20,774 --> 00:02:23,824 서버 단 코드겠지요 39 00:02:24,564 --> 00:02:27,059 기본적으로 40 00:02:27,059 --> 00:02:28,998 유저의 여행 목록을 조회합니다. 41 00:02:28,998 --> 00:02:31,167 파라메터로 유저를 받고 42 00:02:31,167 --> 00:02:35,983 세션 정보에서 43 00:02:35,983 --> 00:02:38,130 로그인 유저 정보를 조회하고 44 00:02:39,200 --> 00:02:44,795 로그인하지 않았다면 예외를 던집니다. 45 00:02:44,795 --> 00:02:50,728 로그인 했다면 46 00:02:50,728 --> 00:02:57,138 로그인 유저가 파라메터로 전달된 유저와 친구인지 확인하고 47 00:02:57,138 --> 00:02:59,859 서로 친구라면 48 00:02:59,859 --> 00:03:03,879 전달된 유저의 여행 목록을 조회합니다. 49 00:03:03,879 --> 00:03:07,748 다 파악한 것은 아닙니다만 50 00:03:07,748 --> 00:03:11,287 일단 테스트를 작성해보겠습니다. 51 00:03:11,287 --> 00:03:14,534 코딩 하기에 편하게 52 00:03:14,534 --> 00:03:17,589 에디터 화면을 배치하도록 하겠습니다. 53 00:03:17,589 --> 00:03:19,725 저는 보통 화면을 둘로 나눠서 54 00:03:19,725 --> 00:03:21,814 하나는 제품 코드를 두고 55 00:03:21,814 --> 00:03:23,304 다른 하나는 테스트 코드를 띄웁니다. 56 00:03:23,304 --> 00:03:27,091 화면을 계속 스위칭할 필요가 없어서 57 00:03:27,091 --> 00:03:31,037 아주 편리해요. 58 00:03:31,037 --> 00:03:33,919 맨 처음으로 할 것은 59 00:03:33,919 --> 00:03:35,848 가장 얕은 부분을 찾는 겁니다. 60 00:03:35,848 --> 00:03:37,068 그게 어떤 코드인지는 잊어도 되요 61 00:03:37,068 --> 00:03:39,198 적어도 잠시 동안은요 62 00:03:39,388 --> 00:03:41,506 레거시 코드에 작업을 할 때 63 00:03:41,506 --> 00:03:42,990 맨 처음으로 할 것은요 64 00:03:43,097 --> 00:03:44,613 레거시 코드가 뭘 하는지 파악하려면요 65 00:03:44,613 --> 00:03:46,151 가장 얕은 부분을 찾는 것 입니다. 66 00:03:46,151 --> 00:03:49,343 Logged user 변수가 Null이 아니라면 67 00:03:49,378 --> 00:03:51,082 예외를 던지네요. 68 00:03:51,082 --> 00:03:53,775 유저가 로그인 상태가 아니면 예외를 던져요. 69 00:03:53,775 --> 00:03:56,833 테스트 코드로 실제로 그렇게 동작하는지 봅시다. 70 00:03:57,473 --> 00:04:12,537 유저가 로그인 상태가 아니면 예외를 던진다 71 00:04:13,177 --> 00:04:16,501 예외를 적어줍시다 72 00:04:16,539 --> 00:04:22,550 UserNotLoggedInException이 나와야 하는 거지요 73 00:04:24,400 --> 00:04:27,414 TripService 인스턴스를 만들어 봅시다 74 00:04:33,453 --> 00:04:34,845 먼저 Import 하고 75 00:04:35,239 --> 00:04:37,163 그 다음에 76 00:04:37,163 --> 00:04:41,644 여행 서비스에서 77 00:04:42,276 --> 00:04:44,346 유저의 여행 목록을 조회하고 78 00:04:44,346 --> 00:04:46,620 일단 유저에는 null을 넣고요 79 00:04:50,289 --> 00:04:52,189 지금 인피니테스트를 사용 중인데요 80 00:04:52,199 --> 00:04:55,975 여기 빨간색으로 결과가 표시되지요 81 00:04:55,975 --> 00:04:59,208 제가 코드를 저장할 때마다 82 00:04:59,208 --> 00:05:00,922 자동으로 필요한 테스트를 실행합니다. 83 00:05:00,922 --> 00:05:02,899 매번 손으로 돌릴 필요가 없어요. 84 00:05:02,899 --> 00:05:05,419 그런데 원래는 이게.. 85 00:05:05,754 --> 00:05:06,536 녹색이어야 하는데요 86 00:05:06,746 --> 00:05:09,624 뭔가 잘못된 거에요 87 00:05:09,624 --> 00:05:19,824 그래서 테스트를 직접 돌리면 88 00:05:19,824 --> 00:05:22,573 어떻게 되어야하냐면.. 89 00:05:22,573 --> 00:05:27,696 UserNotLoggedInException이 나와야 해요 90 00:05:27,696 --> 00:05:30,636 UserNotLoggedInException이 나왔어야 하는데 91 00:05:30,636 --> 00:05:34,894 의존 클래스 관련된 다른 종류의 예외가 생겼군요 92 00:05:34,928 --> 00:05:37,669 어떻게 된거냐하면요 93 00:05:41,119 --> 00:05:46,689 이 부분이 실행되었을 때에요 94 00:05:49,109 --> 00:05:55,189 유저 세션의 로그인 유저를 조회하는데요 95 00:05:56,189 --> 00:05:57,840 유저 세션 코드를 까서 보면 96 00:05:57,840 --> 00:06:00,835 물론 이 건 연습을 위한 예제 코드라서 그래요 97 00:06:00,835 --> 00:06:02,613 예외가 생기게 일부러 작성해놨습니다. 98 00:06:03,303 --> 00:06:06,217 왜냐하면 단위테스트는 다른 클래스들을 호출하면 안되니까요 99 00:06:06,217 --> 00:06:10,747 실수로 이 걸 실행시키면 바로 알 수 있게 하려고요. 100 00:06:11,311 --> 00:06:14,654 만약에 실제 Http Session을 사용하고 있다면 101 00:06:14,654 --> 00:06:18,027 실제 데이터 베이스를 조회하려고 할지도 몰라요 102 00:06:18,027 --> 00:06:19,848 단위테스트하는데 그러면 안되지요. 103 00:06:20,556 --> 00:06:22,978 이제 제대로 테스트하려면 이 코드를 사용하지 않게 만들어야 합니다. 104 00:06:24,238 --> 00:06:26,113 문제는 105 00:06:26,113 --> 00:06:27,732 이게 싱글톤이라 106 00:06:27,732 --> 00:06:32,605 Mock으로 대체할 수가 없다는 점 입니다. 107 00:06:32,605 --> 00:06:37,844 TripService 클래스를 손으로 수정하는 건 금지되어있으니 108 00:06:38,943 --> 00:06:41,900 다른 방법을 찾아야겠지요. 109 00:06:41,900 --> 00:06:44,142 UserSession을 Mock으로 대체할 방법을 찾아야 합니다. 110 00:06:44,142 --> 00:06:48,323 처음에 말한 대로 코드를 수정하는 유일한 방법은 111 00:06:48,323 --> 00:06:50,679 IDE의 리팩토링 기능을 이용하는 것 입니다. 112 00:06:50,679 --> 00:06:51,693 코드에 직접 타이핑하는 것은 안됩니다. 113 00:06:51,693 --> 00:06:53,625 그래서 114 00:06:53,625 --> 00:06:55,547 연결점(Seam)을 만들려고 합니다. 115 00:06:55,547 --> 00:06:59,959 연결점(Seam)은 클래스들이 이어지는 지점을 말합니다. 116 00:06:59,959 --> 00:07:02,741 서로 분리되는 지점이기도 하지요. 117 00:07:02,741 --> 00:07:04,802 이제 TripService와 UserSession 사이에 118 00:07:04,802 --> 00:07:06,466 연결점을 만들겠습니다. 119 00:07:06,466 --> 00:07:09,398 메소드를 하나 만드는데요 120 00:07:09,989 --> 00:07:14,962 이름은 getLoggedInUser로 하고 121 00:07:16,511 --> 00:07:18,283 접근제한자 protected로 122 00:07:19,153 --> 00:07:27,023 이렇게 TripService가 다른 클래스에 접근하는 부분을 분리해서 123 00:07:27,543 --> 00:07:29,474 연결점을 만들었습니다. 124 00:07:30,007 --> 00:07:33,732 나중에 또 손보겠지만요 125 00:07:33,732 --> 00:07:44,853 이제 TripService를 상속받는 TestableTripService 클래스를 126 00:07:44,853 --> 00:07:49,386 만들 수 있겠지요 127 00:07:52,186 --> 00:07:54,431 여기에서 128 00:07:54,471 --> 00:08:03,556 getLoggedInUser 메소드를 오버라이드해서 129 00:08:03,827 --> 00:08:07,330 null을 반환하게 만듭니다. 130 00:08:10,577 --> 00:08:17,812 이제 테스트는 TripService 대신에 TestableTripService를 사용하는 겁니다. 131 00:08:23,662 --> 00:08:28,534 테스트를 실행하면 132 00:08:28,569 --> 00:08:32,208 보시는 데로 테스트가 통과합니다. 133 00:08:32,208 --> 00:08:35,443 가끔 인피니테스트는 이상하게 동작할 때가 있어서 134 00:08:35,535 --> 00:08:39,021 믿기 어려운 경우도 있습니다. 135 00:08:39,021 --> 00:08:44,923 지금도 실패했다고 빨갛게 표시되었지만 실제로는 모두 정상이었지요. 136 00:08:44,956 --> 00:08:49,496 이걸로도 충분하겠지만 137 00:08:49,823 --> 00:08:53,473 테스트를 다시 돌리면.. 모두 통과합니다. 138 00:08:54,206 --> 00:08:58,610 코드 커버리지를 확인하면 139 00:08:59,530 --> 00:09:05,990 제일 얕은 부분의 코드가 실행되었는지 확인할 수 있습니다. 140 00:09:05,990 --> 00:09:08,614 이 것도 팁이에요. 141 00:09:08,614 --> 00:09:11,220 저는 레거시 코드로 작업을 할 때 142 00:09:11,220 --> 00:09:13,143 항상 코드 커버리지를 확인합니다. 143 00:09:13,143 --> 00:09:15,104 보통 코드 커버리지라고 하면 144 00:09:15,104 --> 00:09:16,954 테스트 커버리지라고 생각하는 경우가 많은데요 145 00:09:16,954 --> 00:09:18,726 저는 커버리지 숫자는 신경 쓰지 않습니다. 146 00:09:18,726 --> 00:09:22,710 레거시 코드에 작업을 할 때에는 147 00:09:22,710 --> 00:09:27,918 테스트하려는 코드가 실제로 실행되었는지가 중요합니다. 148 00:09:27,918 --> 00:09:30,897 긍정 오류나 부정 오류 등을 방지해서 149 00:09:30,897 --> 00:09:32,973 정확하게 작업할 수 있습니다. 150 00:09:33,003 --> 00:09:35,125 좋습니다. 151 00:09:35,125 --> 00:09:41,664 커버리지 표시는 지우고요. 152 00:09:47,294 --> 00:09:50,287 그나저나 테스트 코드가 마땅치 않네요 153 00:09:50,287 --> 00:09:52,593 이 테스트는요 154 00:09:52,593 --> 00:09:56,002 유저가 로그인 상태가 아니면 예외를 던진다 155 00:09:57,452 --> 00:10:01,813 이건 로그인하지 않은 유저에 대한 테스트인데요 156 00:10:02,873 --> 00:10:05,067 로그인하지 않은 유저는 어디를 보면 알 수 있지요? 157 00:10:05,137 --> 00:10:08,358 TestableTripService를 생성해서 158 00:10:08,358 --> 00:10:11,229 Null을 인자로 메소드를 호출해서 예외가 생기는데요. 159 00:10:11,229 --> 00:10:14,606 로그인 하지 않은 유저는 어디에 있을까요? 160 00:10:16,785 --> 00:10:18,635 여기지요. 감춰져 있습니다. 161 00:10:18,825 --> 00:10:21,353 그럼 유저 상태가 표현되도록 162 00:10:21,353 --> 00:10:23,593 수정해야겠지요. 163 00:10:23,593 --> 00:10:26,785 그나저나 이 부분은 조금 특이하지요? 164 00:10:26,785 --> 00:10:30,088 자바에서는 조금 이상한 방식이지만 165 00:10:30,088 --> 00:10:32,264 루비에서 종종 사용하는 방법입니다. 166 00:10:32,264 --> 00:10:34,191 에디터에서 코드를 이렇게 접으면 167 00:10:34,191 --> 00:10:38,552 이렇게 명세서처럼 표현이 됩니다. 168 00:10:38,552 --> 00:10:40,097 그냥 명세서인 것처럼 읽는 거지요 169 00:10:40,097 --> 00:10:44,711 "trip service should do something" 170 00:10:44,711 --> 00:10:49,632 저는 이런 방식을 좋아합니다. 171 00:10:50,352 --> 00:10:55,961 로그인 유저 정보가 전혀 안보이니 172 00:10:55,961 --> 00:10:57,502 하나 만들도록 하겠습니다. 173 00:10:58,981 --> 00:11:06,355 loggedInUser를 null로 만들고 174 00:11:07,815 --> 00:11:09,859 멤버 변수로 만든 후에 175 00:11:09,859 --> 00:11:15,649 로그인 유저를 조회할 때에 176 00:11:18,209 --> 00:11:23,326 loggedInUser 필드를 반환하게 하는 거지요. 177 00:11:24,142 --> 00:11:28,647 조금 더 좋아졌지요? 테스트 코드에 유저가 표현되고 있어요. 178 00:11:31,599 --> 00:11:35,383 음.. Null은 좀 별로네요 179 00:11:35,383 --> 00:11:39,426 여기 이 Null의 의미가 분명하지가 않아요. 180 00:11:39,426 --> 00:11:51,008 유저가 로그인하지 않았다는 건 181 00:11:51,008 --> 00:11:55,112 보통 웹 어플리케이션에서 182 00:11:56,613 --> 00:12:01,137 로그인하지 않은 유저는 게스트지요. 183 00:12:01,137 --> 00:12:06,422 여기에 비즈니스 개념을 적용해 볼 수 있겠네요 184 00:12:06,422 --> 00:12:10,642 비즈니스 인력과 대화할 때 사용하는 표현들이요. 185 00:12:10,642 --> 00:12:14,401 네 도메인 언어를 사용하기 시작했습니다. 186 00:12:15,379 --> 00:12:22,429 이 건 여행 목록을 조회할 유저지요 187 00:12:22,549 --> 00:12:25,927 Null 말고 더 명시적으로 188 00:12:28,257 --> 00:12:30,602 Unused User라고 바꾸겠습니다. 189 00:12:39,757 --> 00:12:45,394 어디 볼까요 190 00:12:45,713 --> 00:12:52,950 이 번에는 인피니테스트가 제대로 동작할까요.. 191 00:12:53,863 --> 00:12:54,802 아니군요. 192 00:12:54,802 --> 00:12:58,157 안타깝게도 인피니테스트를 믿기 어렵겠네요. 193 00:13:02,375 --> 00:13:04,714 테스트 코드가 많이 개선되었어요. 194 00:13:04,714 --> 00:13:08,320 그 사이에 인피니테스트가 정상으로 돌아왔네요. 195 00:13:09,030 --> 00:13:11,755 말씀 드렸던 것처럼 196 00:13:11,755 --> 00:13:14,523 이 건 유저가 로그인하지 않았으면 예외를 던지는 테스트인데요 197 00:13:14,523 --> 00:13:16,913 현재 유저는 게스트 198 00:13:16,913 --> 00:13:18,760 그리고 예외를 던지지요 199 00:13:18,760 --> 00:13:19,791 좋습니다. 200 00:13:19,791 --> 00:13:21,524 이제 코드 커버리지를 다시 돌려보겠습니다. 201 00:13:21,524 --> 00:13:23,419 이제 코드 커버리지를 다시 돌려보겠습니다. 202 00:13:30,309 --> 00:13:32,452 그 전에 JUnit을 실행하고요 203 00:13:32,452 --> 00:13:34,001 그냥 확실하게 하는 거에요 204 00:13:34,001 --> 00:13:34,716 좋습니다. 205 00:13:34,770 --> 00:13:37,307 이제 코드 커버리지를 실행합니다. 206 00:13:43,247 --> 00:13:45,433 자 이제 207 00:13:45,462 --> 00:13:46,702 코드 커버리지를 보면요 208 00:13:46,702 --> 00:13:50,701 다음으로 얕은 부분을 쉽게 찾을 수 있습니다. 209 00:13:51,701 --> 00:13:56,261 이 For 반복문이겠지요 210 00:13:57,401 --> 00:14:00,243 친구인 경우라면.. 211 00:14:00,243 --> 00:14:02,411 여기가 제일 깊은 부분이네요 212 00:14:02,411 --> 00:14:05,574 이 부분이 실행되려면 이 값이 true 이어야 하니까요 213 00:14:05,631 --> 00:14:10,190 그러니까 여기까지 실행되려면.. 214 00:14:10,190 --> 00:14:14,368 유저는 로그인 된 상태인데 조회하려는 유저와는 친구가 아닌 경우입니다. 215 00:14:15,158 --> 00:14:19,708 그럼 이 시나리오를 검증하는 테스트를 작성하겠습니다. 216 00:14:19,708 --> 00:14:25,540 커버리지는 그대로 두고요 217 00:14:27,840 --> 00:14:31,701 테스트 이름은 218 00:14:34,481 --> 00:14:48,450 유저가 서로 친구가 아닌 경우에는 여행 목록을 반환하지 않는다로 하겠습니다. 219 00:14:48,450 --> 00:14:54,445 여기 코드를 가져와서요 220 00:14:57,215 --> 00:15:00,080 이제는 로그인한 유저가 필요하지요 221 00:15:00,080 --> 00:15:03,914 이름은 Registered User로 하고 222 00:15:05,062 --> 00:15:06,632 멤버 변수를 만들겠습니다. 223 00:15:14,092 --> 00:15:23,964 여행 목록이 필요하겠지요 224 00:15:24,174 --> 00:15:29,728 이름은 friendTrips로 하고 225 00:15:30,458 --> 00:15:32,110 import 하고 226 00:15:42,970 --> 00:15:44,695 이제 227 00:15:44,695 --> 00:15:45,936 제대로 된 유저가 필요하겠지요 228 00:15:45,936 --> 00:15:48,716 여기에요 229 00:15:49,076 --> 00:15:51,316 그러니까 230 00:15:51,726 --> 00:15:55,126 이름은 friend로 하고 231 00:15:56,096 --> 00:16:00,197 지금 친구가 필요하지요 232 00:16:04,062 --> 00:16:11,363 친구를 추가해주고 233 00:16:13,663 --> 00:16:18,701 브라질로 여행을 간다고 합시다 234 00:16:22,380 --> 00:16:25,177 이제 추가한 친구를 멤버 변수로 만들겠습니다. 235 00:16:41,417 --> 00:16:44,548 친구를 만들었지요 236 00:16:44,928 --> 00:16:48,566 이 친구는 브라질로 여행을 가는 또 다른 친구가 있습니다. 237 00:16:49,046 --> 00:16:52,619 하지만 현재 로그인한 유저와는 238 00:16:53,409 --> 00:16:55,868 친구가 아니네요. 239 00:16:55,868 --> 00:17:01,960 그래서 반환된 여행 목록은 240 00:17:03,655 --> 00:17:08,524 크기가 0 이어야 합니다. 241 00:17:10,904 --> 00:17:13,694 size() 대신에 isEmpty를 사용했어도 242 00:17:13,694 --> 00:17:16,294 무방하겠지요. 243 00:17:16,294 --> 00:17:20,236 인피니테스트는 잘 돌고 있군요 244 00:17:20,320 --> 00:17:24,997 확실하게 JUnit을 직접 실행하겠습니다. 245 00:17:25,137 --> 00:17:27,421 테스트는 통과했습니다. 246 00:17:27,421 --> 00:17:29,726 이미 동작하던 코드들이니 247 00:17:29,726 --> 00:17:30,975 당연히 테스트는 통과하겠지요. 248 00:17:30,975 --> 00:17:33,396 지금은 코드가 어떻게 동작하는지 알아보려고 테스트를 작성하니까요 249 00:17:33,396 --> 00:17:34,624 당연한 겁니다. 250 00:17:34,624 --> 00:17:37,479 코드 커버리지를 다시 돌려봅시다. 251 00:17:37,508 --> 00:17:40,781 커버리지를 보면 조금 더 진도가 나간 것을 알 수 있습니다. 252 00:17:40,781 --> 00:17:44,556 보시는 것처럼 조금 더 깊이 들어갔어요 253 00:17:44,556 --> 00:17:46,165 어떤 코드 였냐면 254 00:17:46,165 --> 00:17:49,279 유저가 로그인 상태이긴 해도 255 00:17:49,279 --> 00:17:50,949 서로 친구는 아닌 경우였지요 256 00:17:52,319 --> 00:17:56,641 이 부분이 항상 false를 반환했지요 257 00:17:57,202 --> 00:17:59,308 아직 끝난 게 아닙니다. 258 00:17:59,308 --> 00:18:02,308 테스트에 중복된 부분들이 있으니 259 00:18:02,308 --> 00:18:04,474 리팩토링을 해야 합니다. 260 00:18:04,474 --> 00:18:06,296 중복 코드를 없애겠습니다. 261 00:18:07,086 --> 00:18:10,784 @Before 메소드를 만들고요 262 00:18:12,558 --> 00:18:15,420 로컬 변수를 263 00:18:15,420 --> 00:18:18,613 멤버 변수로 바꾸겠습니다. 264 00:18:18,642 --> 00:18:20,687 좋습니다. 265 00:18:20,687 --> 00:18:22,238 좋아요. 266 00:18:24,568 --> 00:18:26,605 위로 옮기겠습니다. 267 00:18:35,795 --> 00:18:37,168 좋습니다. 268 00:18:38,288 --> 00:18:44,047 이제 제일 깊은 부분을 테스트하겠습니다. 269 00:18:44,067 --> 00:18:45,674 이 부분이 실행되려면 270 00:18:45,674 --> 00:18:51,574 로그인 유저가 조회 대상인 유저와 친구이고 271 00:18:52,944 --> 00:18:56,169 여행이 조회되는 시나리오가 필요합니다. 272 00:18:59,855 --> 00:19:07,710 유저가 서로 친구인 경우에 친구의 여행 목록을 반환한다. 273 00:19:08,735 --> 00:19:11,072 이 걸 테스트 해야 하지요. 274 00:19:11,072 --> 00:19:13,591 이 부분을 옮겨서... 275 00:19:22,717 --> 00:19:24,967 소스 코드는 절대 Copy & Paste 하지 마세요. 276 00:19:24,967 --> 00:19:26,967 저는 절대 그러지 않습니다. 277 00:19:26,997 --> 00:19:29,316 지금 본 것은 착각입니다. 278 00:19:29,316 --> 00:19:33,275 소스 코드는 절대 Copy & Paste 하지 마세요. 279 00:19:34,435 --> 00:19:37,800 더 추가해야 할 것은요 280 00:19:38,660 --> 00:19:45,833 로그인 유저를 친구로 추가해주고 281 00:19:46,806 --> 00:19:49,182 여행도 하나 더 추가합시다 282 00:20:03,431 --> 00:20:08,223 인피니테스트에는 테스트가 실패했다고 나오지만요 283 00:20:08,223 --> 00:20:11,517 유저들끼리 친구가 되었으니 284 00:20:11,517 --> 00:20:13,910 테스트는 통과할 겁니다. 285 00:20:13,910 --> 00:20:14,777 저장을 하면 286 00:20:14,777 --> 00:20:18,513 여전히 빨간색이네요 287 00:20:18,513 --> 00:20:21,700 테스트를 직접 실행하면 288 00:20:21,700 --> 00:20:25,280 이런 단축키를 잘 못 눌렀네요 289 00:20:25,280 --> 00:20:27,619 윈도우즈를 사용했었는데 290 00:20:27,619 --> 00:20:32,589 맥이랑 인텔리제이랑 이클립스랑 바꾸다 보니 헷갈리네요. 291 00:20:32,589 --> 00:20:37,128 그래도 역시 테스트가 실패합니다. 왜냐하면 292 00:20:37,908 --> 00:20:39,367 화면 배치는 일단 돌려놓고 293 00:20:40,268 --> 00:20:41,816 테스트가 여전히 실패하는 이유는 294 00:20:41,816 --> 00:20:47,416 이 TripDao 때문입니다. 295 00:20:47,416 --> 00:20:49,390 이건 Static 메소드이고 296 00:20:49,550 --> 00:20:53,211 메소드를 실행하면 그냥 297 00:20:53,211 --> 00:20:55,029 예외를 던지게 만들어놨습니다. 298 00:20:55,029 --> 00:20:56,735 299 00:20:56,735 --> 00:20:59,613 TripDAO를 이렇게 만들어 놓은 이유는요 300 00:20:59,613 --> 00:21:01,083 단위 테스트에서는 이런 DAO 같은 다른 클래스들을 실행시키면 안되는데 301 00:21:01,083 --> 00:21:06,523 혹시 실수로 TripDAO를 실행한 경우 바로 알 수 있게 하려고 입니다. 302 00:21:06,523 --> 00:21:13,061 실제 시스템의 DAO는 데이터베이스에 연결해서 데이터를 조회하겠지만 303 00:21:12,721 --> 00:21:17,158 테스트에서는 그러면 안됩니다. 304 00:21:17,158 --> 00:21:21,533 이제 UserSession에 했던 것과 305 00:21:21,533 --> 00:21:25,171 같은 작업을 할 겁니다. 306 00:21:25,171 --> 00:21:29,624 싱글톤이나 Static 메소드 호출 같은 307 00:21:29,624 --> 00:21:32,980 강한 의존 관계를 떼어내는 거지요 308 00:21:32,980 --> 00:21:36,949 메소드에서 객체를 생성하는 것도 똑 같습니다. 309 00:21:36,949 --> 00:21:39,167 자 그러면 310 00:21:39,977 --> 00:21:41,583 메소드를 추가하겠습니다. 311 00:21:42,493 --> 00:21:48,772 이름은 tripsBy로 하고 312 00:21:48,772 --> 00:21:51,293 접근제한자는 protected 313 00:21:51,293 --> 00:21:56,300 이제 테스트 코드로 돌아가서 314 00:22:02,090 --> 00:22:04,414 똑 같은 작업을 하겠습니다. 315 00:22:17,108 --> 00:22:19,844 기본적으로 316 00:22:20,141 --> 00:22:22,319 여행 목록을 반환할 건데요 317 00:22:22,319 --> 00:22:23,668 조회할 유저를 받아서 318 00:22:23,668 --> 00:22:26,775 이 테스트 유저는 여행 일정을 두 개 가지고 있으니까 319 00:22:29,275 --> 00:22:32,476 그 걸 반환할 겁니다. 320 00:22:32,476 --> 00:22:35,154 the user dot trips 321 00:22:36,454 --> 00:22:39,076 바로 테스트 결과에 반영이 되었군요. 322 00:22:40,046 --> 00:22:43,949 코드 커버리지를 확인하면 323 00:22:43,949 --> 00:22:45,098 좋습니다. 324 00:22:45,098 --> 00:22:51,066 이제 기존 코드의 대부분이 325 00:22:51,066 --> 00:22:53,736 테스트 되었네요. 326 00:22:53,736 --> 00:22:59,963 기존 코드를 상속 받은 부분은 테스트가 아니라고 할 수도 있겠지만 327 00:22:59,963 --> 00:23:02,403 작은 연결점이니까 괜찮아요 328 00:23:02,403 --> 00:23:04,881 작은 연결점이니까 괜찮아요 329 00:23:04,881 --> 00:23:07,448 이게 최종 모습이 아니기도 하고요 330 00:23:07,448 --> 00:23:11,678 조금 더 정리를 해 볼까요 331 00:23:11,678 --> 00:23:13,373 보통은요.. 332 00:23:13,373 --> 00:23:19,127 이 건 여기에도 있고 저기에도 있네요 333 00:23:19,127 --> 00:23:24,999 이런 중복 코드는 절대 좋지 않지요 334 00:23:24,999 --> 00:23:26,461 이 건 남겨 두고요 335 00:23:26,461 --> 00:23:28,368 이 건 이쪽으로 옮기겠습니다. 336 00:23:29,598 --> 00:23:31,708 그러면 다른 모든 테스트에 공통이 되지요 337 00:23:31,708 --> 00:23:37,277 로그인 된 유저가 필요한 모든 테스트에 유효합니다. 338 00:23:37,307 --> 00:23:40,045 그런 후에 339 00:23:40,088 --> 00:23:41,879 저장하고 340 00:23:41,879 --> 00:23:44,332 테스트를 직접 돌리면 341 00:23:44,332 --> 00:23:46,438 여전히 녹색이네요 342 00:23:46,438 --> 00:23:47,531 좋습니다. 343 00:23:47,531 --> 00:23:52,048 이 걸로 첫 단계가 완료되었습니다. 344 00:23:52,048 --> 00:23:56,470 테스트가 다 작성되었으니 이제 리팩토링을 시작할 수 있게 되었습니다. 345 00:23:57,450 --> 00:24:02,487 커밋하기 딱 좋은 시점이네요. 346 00:24:02,487 --> 00:24:06,112 git status 347 00:24:06,112 --> 00:24:08,437 git commit 348 00:24:08,437 --> 00:24:17,763 unit tests for trip service 349 00:24:17,763 --> 00:24:19,614 좋습니다. 350 00:24:23,664 --> 00:24:26,109 그런데 이 테스트를 다시 보면요 351 00:24:26,109 --> 00:24:29,593 레거시 코드는 종종.. 352 00:24:29,593 --> 00:24:32,426 지금은 아주 간단한 예제를 보고 있습니다만 353 00:24:33,216 --> 00:24:39,395 훨씬 복잡한 메소드를 생각해보세요 354 00:24:39,395 --> 00:24:42,114 예제에선 데이터 객체를 하나만 만들어도 충분했지만 355 00:24:42,114 --> 00:24:43,428 예제에선 데이터 객체를 하나만 만들어도 충분했지만 356 00:24:43,428 --> 00:24:48,044 코드를 제대로 테스트하려면 종종 357 00:24:48,044 --> 00:24:50,060 거대하고 복잡한 테스트 데이터를 만들어야 하는 경우가 있습니다. 358 00:24:50,060 --> 00:24:53,022 거대하고 복잡한 테스트 데이터를 만들어야 하는 경우가 있습니다. 359 00:24:53,022 --> 00:24:55,161 그럼 테스트 데이터를 생성하는 코드를 정리해볼까요? 360 00:24:55,161 --> 00:24:58,112 여기 저기에 중복 코드들이 있지요 361 00:24:58,112 --> 00:25:01,888 빌더 패턴을 적용해보겠습니다. 362 00:25:01,888 --> 00:25:03,713 빌더 패턴을 적용해보겠습니다. 363 00:25:03,713 --> 00:25:09,018 기본적으로 이런 식으로 사용하게 되는 거지요 364 00:25:09,018 --> 00:25:11,672 테스트용 유저를 생성하는데 365 00:25:12,112 --> 00:25:18,756 366 00:25:23,506 --> 00:25:35,245 ANOTHER_USER, loggedInUser와 친구이고 367 00:25:35,915 --> 00:25:45,607 브라질과 런던으로 여행을 가지요. 368 00:25:46,757 --> 00:25:49,860 이런 식으로 테스트 데이터를 만드는 거에요. 369 00:25:50,470 --> 00:25:51,836 가독성이 훨씬 좋습니다. 370 00:25:51,836 --> 00:25:54,757 그럼 실제로 구현을 해볼까요 371 00:25:55,127 --> 00:25:57,716 일단 build 메소드를 추가합시다. 372 00:25:58,086 --> 00:26:00,337 빌더 패턴을 적용하는 거지요. 373 00:26:01,593 --> 00:26:05,397 UserBuilder를 추가하고 374 00:26:06,667 --> 00:26:11,958 이런 모양을 원하는 겁니다. 375 00:26:11,958 --> 00:26:15,655 이 부분은 주석 처리하고요 376 00:26:16,815 --> 00:26:24,640 377 00:26:25,439 --> 00:26:27,976 378 00:26:30,876 --> 00:26:34,195 aUser 메소드를 만들고요 379 00:26:47,525 --> 00:26:49,961 메소드를 이어서 호출 할 수 있도록 380 00:26:49,961 --> 00:26:52,980 계속 같은 오브젝트를 반환합니다 381 00:26:52,980 --> 00:26:55,186 이러면 메소드를 계속 이어서 호출할 수 있게 됩니다. 382 00:26:55,186 --> 00:26:57,379 UserBuilder를 생성해서 반환하고 383 00:27:00,659 --> 00:27:04,965 다음 메소드를 만들어 봅시다 384 00:27:07,535 --> 00:27:09,562 역시 UserBuilder를 반환하고요 385 00:27:09,752 --> 00:27:15,449 두 개의 유저를 받고 있습니다. 386 00:27:17,039 --> 00:27:21,738 항상 말 했듯이 프로그래밍에는 딱 3개의 숫자만 존재합니다. 387 00:27:21,738 --> 00:27:24,445 0, 1, 그리고 많이 입니다. 388 00:27:24,445 --> 00:27:26,724 그 밖에는 없어요. 389 00:27:26,788 --> 00:27:29,590 인자를 여러 개를 받도록 변경합시다 390 00:27:31,270 --> 00:27:33,300 필요한 수만큼 입력할 수 있도록 391 00:27:33,300 --> 00:27:36,803 가변길이 인자를 사용하겠습니다. 392 00:27:38,113 --> 00:27:41,321 이름은 friends 로 하고 393 00:27:43,211 --> 00:27:47,773 friends 변수에 할당하고 394 00:27:48,043 --> 00:27:50,624 계속 UserBuilder 인스턴스를 반환합니다. 395 00:27:50,624 --> 00:27:52,887 이 것도 만들어 주고요 396 00:27:53,011 --> 00:27:57,611 배열은 반드시 초기화 해야겠지요 397 00:27:57,611 --> 00:28:01,089 398 00:28:05,399 --> 00:28:07,862 399 00:28:08,662 --> 00:28:16,280 좋습니다. 다음 메소드를 만들어 볼까요 400 00:28:16,361 --> 00:28:18,817 401 00:28:18,817 --> 00:28:21,536 똑 같이 하는 겁니다. 402 00:28:21,536 --> 00:28:28,132 메소드에 원하는 개 수만큼 여행 정보를 넣어 줄 수 있겠지요 403 00:28:37,012 --> 00:28:39,210 404 00:28:39,210 --> 00:28:41,015 멤버 변수로 만들고요 405 00:28:41,015 --> 00:28:44,888 저는 보통 406 00:28:44,888 --> 00:28:48,704 읽기 좋은 모양으로 사용하는 코드를 작성하고 407 00:28:48,836 --> 00:28:52,123 그거에 맞춰서 구현 코드를 생성해갑니다. 408 00:28:52,973 --> 00:28:56,549 이 번엔 build 메소드를 생성합니다 409 00:28:56,549 --> 00:29:04,280 맨 밑으로 옮기는 게 좋겠지요 410 00:29:04,280 --> 00:29:10,925 build 메소드가 실제로 객체를 생성하게 됩니다. 411 00:29:11,555 --> 00:29:14,608 유저를 생성하고 412 00:29:15,648 --> 00:29:17,352 이 유저를 반환하게 하고 413 00:29:17,352 --> 00:29:19,075 그리고 414 00:29:19,665 --> 00:29:23,185 여행 목록을 추가하고 415 00:29:23,215 --> 00:29:28,886 친구들을 추가합니다. 416 00:29:32,046 --> 00:29:37,885 메소드 이름은 파라메터 이름과 함께 정하는 게 좋습니다. 417 00:29:37,885 --> 00:29:40,703 읽기에도 좋고 418 00:29:40,703 --> 00:29:43,255 이름에 중복을 피할 수도 있지요. 419 00:29:43,255 --> 00:29:45,992 여행 정보부터 시작할까요 420 00:29:45,992 --> 00:29:49,547 421 00:29:49,547 --> 00:29:52,000 422 00:29:52,030 --> 00:29:56,039 423 00:29:56,239 --> 00:30:02,672 여행을 추가하고 424 00:30:04,262 --> 00:30:06,635 친구 목록도 똑같이 하겠습니다 425 00:30:06,635 --> 00:30:08,872 메소드를 만들고 426 00:30:11,152 --> 00:30:12,281 427 00:30:12,281 --> 00:30:14,648 428 00:30:14,648 --> 00:30:17,045 429 00:30:17,045 --> 00:30:19,935 430 00:30:19,935 --> 00:30:21,935 431 00:30:21,935 --> 00:30:28,482 432 00:30:28,842 --> 00:30:30,781 좋습니다. 433 00:30:30,781 --> 00:30:35,595 인피니테스트 결과도 녹색이군요. 434 00:30:35,645 --> 00:30:39,761 이제 이건 지우고요 435 00:30:41,321 --> 00:30:43,652 여기에도 UserBuilder를 사용할 수 있겠지요 436 00:30:43,652 --> 00:30:45,487 수정 합시다 437 00:31:15,477 --> 00:31:18,578 좋고요. 이 건 주석 처리하고. 438 00:31:18,684 --> 00:31:21,945 테스트를 다시 실행하면, 여전히 성공합니다. 439 00:31:21,945 --> 00:31:23,620 좋습니다. 440 00:31:25,100 --> 00:31:29,763 테스트 가독성이 조금 더 좋아졌습니다. 441 00:31:29,763 --> 00:31:33,512 이제 빌더 클래스를 별도 파일로 빼겠습니다. 442 00:31:33,512 --> 00:31:34,984 443 00:31:34,984 --> 00:31:37,004 Type To New File 기능을 사용해서 444 00:31:39,074 --> 00:31:41,396 별도 클래스로 만들어서 445 00:31:41,396 --> 00:31:47,582 일단 TripServiceTest와 같은 위치에 두겠습니다. 446 00:31:47,582 --> 00:31:49,475 일단 TripServiceTest와 같은 위치에 두겠습니다. 447 00:31:50,345 --> 00:31:52,154 이제 분리되었지요. 448 00:31:52,154 --> 00:31:56,413 static import로 변경하고 449 00:31:56,413 --> 00:31:59,383 이 것도 static import로 변경하고 450 00:31:59,383 --> 00:32:01,997 코드 모양을 맞추겠습니다. 451 00:32:01,997 --> 00:32:04,919 좋고요. 452 00:32:04,919 --> 00:32:09,426 import를 정리하고요 453 00:32:09,426 --> 00:32:12,078 사용하지 않는 import가 있으면 안되겠지요 454 00:32:12,078 --> 00:32:13,618 좋습니다. 455 00:32:13,618 --> 00:32:17,101 이제 테스트가 훨씬 마음에 드네요 456 00:32:17,101 --> 00:32:19,723 테스트를 읽기가 훨씬 좋아졌네요. 457 00:32:19,723 --> 00:32:22,667 이제 커밋을 해야겠지요? 458 00:32:22,667 --> 00:32:24,208 봅시다 459 00:32:24,294 --> 00:32:25,916 460 00:32:25,959 --> 00:32:28,606 461 00:32:29,786 --> 00:32:31,473 462 00:32:31,473 --> 00:32:45,815 UserBuilder created and used in TripServiceTest 463 00:32:45,815 --> 00:32:48,650 좋습니다. 464 00:32:52,820 --> 00:32:56,242 이제 진짜로 리팩토링을 시작할 수 있겠습니다. 465 00:32:56,242 --> 00:32:58,193 아까 이야기 했던 게요 466 00:32:58,193 --> 00:32:59,691 어디 있더라 467 00:33:01,671 --> 00:33:06,793 테스트는 얕은 부분부터 깊은 부분으로 작성하는데요 468 00:33:07,653 --> 00:33:10,463 하지만 리팩토링은 그 반대로 진행합니다. 469 00:33:10,463 --> 00:33:12,645 가장 깊은 부분에서 시작해서 470 00:33:13,585 --> 00:33:16,655 얕은 부분으로 가는 거지요. 471 00:33:17,515 --> 00:33:19,346 왜냐하면 472 00:33:19,346 --> 00:33:22,377 중간 부분부터 리팩토링을 하려면 473 00:33:22,377 --> 00:33:23,951 코드를 전부 이해하고 있어야 하기 때문입니다. 474 00:33:23,951 --> 00:33:25,312 일반적으로 475 00:33:26,522 --> 00:33:29,759 레거시 코드는 글로벌 변수가 많고 476 00:33:29,759 --> 00:33:30,811 의존관계도 복잡하고 477 00:33:30,811 --> 00:33:33,691 변수도 여기 저기서 세팅하고 사용되는데요. 478 00:33:33,691 --> 00:33:36,744 가장 깊은 부분부터 시작하면요 479 00:33:36,744 --> 00:33:39,815 가장 깊은 부분은 뭔가에 의존하지 않습니다. 480 00:33:39,815 --> 00:33:43,251 다른 곳에서 주는 정보를 사용해서 481 00:33:43,251 --> 00:33:45,420 뭔가 하는 게 일반적입니다. 482 00:33:45,420 --> 00:33:48,494 깊은 부분을 추출하면요 483 00:33:48,494 --> 00:33:52,511 깊은 부분부터 리팩토링을 시작하면 484 00:33:52,511 --> 00:33:54,001 코드가 점점 줄어들게 됩니다. 485 00:33:54,001 --> 00:33:56,947 소스 코드를 볼까요 486 00:33:56,947 --> 00:33:59,734 가장 깊은 부분은요 487 00:33:59,734 --> 00:34:01,748 아까 본 것처럼 여기입니다. 488 00:34:01,748 --> 00:34:04,895 이 코드가 실행되려면 489 00:34:04,895 --> 00:34:06,554 이게 true 여야 하는데 490 00:34:06,554 --> 00:34:08,675 여기에서 세팅되는군요. 491 00:34:08,675 --> 00:34:11,568 이 예제 코드는요 492 00:34:11,568 --> 00:34:13,951 가장 깊은 부분에서 493 00:34:13,951 --> 00:34:15,265 하는 일이 별로 없어요 494 00:34:15,265 --> 00:34:18,329 DAO를 호출하는 게 전부라서 495 00:34:18,329 --> 00:34:21,357 특별히 리팩토링 할게 없습니다. 496 00:34:21,357 --> 00:34:24,675 다음으로 깊은 부분은 여기인데요 497 00:34:26,405 --> 00:34:27,940 네 이 부분이요 498 00:34:27,940 --> 00:34:30,462 이 부분을 수정해보겠습니다. 499 00:34:31,752 --> 00:34:34,119 레거시 코드에 작업을 할 때에 500 00:34:34,119 --> 00:34:36,187 아주 중요한 것은 501 00:34:36,187 --> 00:34:41,455 메소드가 이렇게 큰 원인을 파악하는 겁니다. 502 00:34:41,455 --> 00:34:44,140 왜 이렇게 복잡할까요? 503 00:34:44,140 --> 00:34:50,622 일반적으로 메소드가 하는 일이 너무 많아서입니다. 504 00:34:50,622 --> 00:34:52,904 하는 일이 많으니 크기가 커지겠지요 505 00:34:52,904 --> 00:34:58,327 처리 알고리즘을 개선하거나 506 00:34:58,327 --> 00:35:01,172 메소드를 추출하는 것 보다 더 중요한 것은 507 00:35:01,172 --> 00:35:02,789 정말 이 일을 508 00:35:02,789 --> 00:35:04,780 이 메소드가 하는 게 적절한가를 509 00:35:04,780 --> 00:35:07,905 지속적으로 생각해봐야 합니다. 510 00:35:07,905 --> 00:35:10,589 이 경우에는 511 00:35:12,929 --> 00:35:14,464 이 부분을 보면 512 00:35:14,464 --> 00:35:23,856 유저 객체에 친구 정보를 요청하지요 513 00:35:23,856 --> 00:35:27,998 유저 객체에서 받은 친구 목록을 514 00:35:28,000 --> 00:35:29,730 하나 하나 검사해서 515 00:35:29,730 --> 00:35:34,235 로그인 유저가 포함돼있는지를 확인하고 있습니다. 516 00:35:34,235 --> 00:35:36,417 이 건 코드 스멜 중 Feature Envy 입니다. 517 00:35:36,417 --> 00:35:40,028 TripService 클래스가 User 클래스의 역할을 탐내는 거죠 518 00:35:40,153 --> 00:35:42,280 User 클래스가 되고 싶은 겁니다. 519 00:35:42,280 --> 00:35:47,756 여기서 Feature Envy를 풀려면 어떻게 해야지요? 520 00:35:47,756 --> 00:35:52,852 User 클래스가 친구 목록을 가지고 있다면 521 00:35:52,852 --> 00:35:55,214 User 클래스에게 물어보면 됩니다. 522 00:35:55,214 --> 00:35:58,851 "이봐 이 사람이랑 친구인가?" 라고요. 523 00:35:58,851 --> 00:36:03,443 그럼 이 부분을 옮기겠습니다. 524 00:36:03,443 --> 00:36:04,617 일단은요 525 00:36:04,617 --> 00:36:06,771 유저 클래스를 봅시다. 526 00:36:06,771 --> 00:36:08,903 어디 있지요? 527 00:36:10,223 --> 00:36:12,892 이 건 닫고 528 00:36:12,987 --> 00:36:15,264 여기 있네요. 529 00:36:16,624 --> 00:36:18,724 유저 클래스의 테스트를 작성합시다. 530 00:36:18,724 --> 00:36:24,375 이 건 유저 클래스고 531 00:36:24,375 --> 00:36:30,377 테스트 케이스를 새로 만들고요 532 00:36:30,377 --> 00:36:34,925 테스트 경로에 넣어야겠지요 533 00:36:36,425 --> 00:36:40,103 테스트 클래스가 만들어 졌고요 534 00:36:40,103 --> 00:36:43,565 이 쪽으로 옮기겠습니다. 535 00:36:43,565 --> 00:36:46,808 네 이제 뭘 해야지요? 536 00:36:46,808 --> 00:36:53,380 친구인지 확인하는 기능을 User 클래스로 옮길 겁니다. 537 00:36:53,380 --> 00:36:55,445 그냥 User 클래스에게 물어보는 거지요. 538 00:36:55,445 --> 00:36:58,190 "저 사람이랑 친구야?" 라고요. 539 00:36:58,190 --> 00:36:59,071 540 00:36:59,071 --> 00:37:02,499 테스트 먼저 작성해야겠지요 541 00:37:05,639 --> 00:37:11,453 유저들이 친구가 아니면 친구가 아니라고 해야 한다 542 00:37:11,453 --> 00:37:12,840 친구가 아닌 경우부터 테스트하겠습니다. 543 00:37:12,840 --> 00:37:15,149 제일 쉬운 테스트이니까요 544 00:37:15,149 --> 00:37:16,521 가장 간단해요 545 00:37:18,879 --> 00:37:22,342 UserBuilder를 사용해야겠지요 546 00:37:22,342 --> 00:37:34,841 547 00:37:35,049 --> 00:37:44,507 Bob과 친구라고 합시다 548 00:37:44,507 --> 00:37:49,077 549 00:37:50,137 --> 00:37:54,424 그렇다면 550 00:37:55,284 --> 00:38:13,376 Paul과는 친구가 아니겠지요 551 00:38:14,856 --> 00:38:20,712 보시다시피 Bob과 친구인 유저를 하나 만들고 552 00:38:20,712 --> 00:38:24,532 유저에게 Paul과 친구냐고 물어보는 거지요 553 00:38:24,532 --> 00:38:26,271 당연히 친구가 아니겠지요 554 00:38:26,271 --> 00:38:29,660 Bob과 Paul을 생성하겠습니다 555 00:38:38,122 --> 00:38:39,691 Paul도 만들어야지요 556 00:38:49,251 --> 00:38:53,430 이 걸 User 클래스에 추가하려고요 557 00:38:53,430 --> 00:38:55,237 생성하겠습니다. 558 00:39:00,187 --> 00:39:06,498 이 테스트를 통과하기 위해 필요한 최소한의 구현은 559 00:39:06,498 --> 00:39:07,878 false를 반환하는 거지요. 560 00:39:07,878 --> 00:39:10,412 저장 하자마자 561 00:39:10,412 --> 00:39:15,238 인피니테스트가 테스트가 성공했다고 알려주네요. 562 00:39:15,238 --> 00:39:16,465 멋지군요. 563 00:39:16,785 --> 00:39:23,269 유저끼리 친구인 경우도 테스트하겠습니다. 564 00:39:23,269 --> 00:39:34,910 유저들이 친구인 경우 친구라고 알려야 한다. 565 00:39:38,320 --> 00:39:41,967 이 코드를 가져오겠습니다 566 00:39:41,967 --> 00:39:43,558 밑으로 내려서 567 00:39:43,558 --> 00:39:47,434 어떻게 할거냐 하면 568 00:39:47,434 --> 00:39:51,050 Paul과도 친구로 해주고 569 00:39:51,050 --> 00:39:57,613 그러면 당연히 570 00:39:58,383 --> 00:39:59,770 true가 되겠지요 571 00:39:59,770 --> 00:40:05,366 테스트를 통과하지 못했군요 572 00:40:06,386 --> 00:40:08,331 실제로 구현을 해야겠지요 573 00:40:08,331 --> 00:40:11,363 574 00:40:13,363 --> 00:40:14,318 파라메터 이름으로 Paul은 맞지 않겠지요 575 00:40:14,318 --> 00:40:17,836 anotherUser로 변경하고요 576 00:40:25,876 --> 00:40:32,388 좋습니다. 메소드 구현이 되었네요. 577 00:40:32,388 --> 00:40:36,011 테스트로 실행도 되고 있지요. 578 00:40:36,011 --> 00:40:38,305 이 부분은 실행되지 않았지만 579 00:40:38,305 --> 00:40:39,783 상관없지요. 580 00:40:41,153 --> 00:40:44,353 다시 커밋하기에 좋은 타이밍이지요? 581 00:40:46,133 --> 00:40:47,683 582 00:40:47,683 --> 00:40:49,330 583 00:40:49,330 --> 00:40:51,004 584 00:40:55,174 --> 00:41:02,884 isFriendsWith(user) method added to User 585 00:41:04,491 --> 00:41:06,012 좋습니다. 586 00:41:07,892 --> 00:41:11,860 다시 테스트로 돌아가서 587 00:41:11,860 --> 00:41:19,098 커버리지 결과는 지우고요 588 00:41:20,608 --> 00:41:24,471 이제 User 클래스에 새로운 행위가 추가되었습니다. 589 00:41:24,981 --> 00:41:26,452 리팩토링을 할 때에는요 590 00:41:26,452 --> 00:41:28,791 항상 테스트가 성공하는 상태로 작업할 수 있게 노력해야 합니다. 591 00:41:28,791 --> 00:41:30,559 항상 테스트가 성공하는 상태로 작업할 수 있게 노력해야 합니다. 592 00:41:30,559 --> 00:41:32,951 계획 없이 마구 고쳐버리면 안됩니다. 593 00:41:33,601 --> 00:41:35,733 이것 저것 마구 고쳐서 594 00:41:35,733 --> 00:41:37,132 테스트들이 마구 깨져버리면 안됩니다. 595 00:41:37,132 --> 00:41:40,346 하나씩 수정해 가면서 596 00:41:40,346 --> 00:41:41,776 테스트를 같이 실행해야 합니다. 597 00:41:41,790 --> 00:41:44,033 인피니테스트를 사용하는 것도 좋은 방법입니다. 598 00:41:44,033 --> 00:41:46,661 인피니테스트를 사용하는 것도 좋은 방법입니다. 599 00:41:46,661 --> 00:41:49,680 코드를 저장할 때마다 테스트를 실행해서 600 00:41:49,680 --> 00:41:51,151 바로 바로 결과를 알 수 있습니다. 601 00:41:51,151 --> 00:41:54,845 뭔가 수정을 했는데 602 00:41:54,845 --> 00:41:56,616 실수를 했다면 603 00:41:56,616 --> 00:42:00,217 테스트 결과를 보고 바로 알아 챌 수 있습니다. 604 00:42:00,217 --> 00:42:03,782 그러면 Ctrl+Z 한 번으로 복구할 수 있습니다. 605 00:42:03,782 --> 00:42:06,115 Ctrl+Z를 누르고 저장만하면 됩니다. 606 00:42:06,115 --> 00:42:07,306 바로 문제없던 상태로 돌아갈 수 있습니다. 607 00:42:07,306 --> 00:42:12,239 이제 안전하게 리팩토링을 할 수 있게 608 00:42:12,239 --> 00:42:15,984 가능한 작게 변경을 해보겠습니다. 609 00:42:18,764 --> 00:42:22,144 자 610 00:42:22,144 --> 00:42:28,766 여기 불린 변수를 옮겨볼까요? 611 00:42:28,766 --> 00:42:33,915 이 if 구문 안에서만 사용되고 있으니까요 612 00:42:33,915 --> 00:42:35,190 또 다른 팁을 알려드리면요 613 00:42:35,190 --> 00:42:36,498 레거시 코드로 작업을 하다 보면 614 00:42:36,498 --> 00:42:40,318 변수들이 여기 저기에 선언된 경우가 있는데요 615 00:42:40,318 --> 00:42:42,358 가능한 인접하게 모으세요 616 00:42:42,358 --> 00:42:48,219 사용되는 위치에 가깝게 모으세요. 617 00:42:48,219 --> 00:42:51,620 변수가 코드의 위 부분에서는 사용되지 않고 618 00:42:51,620 --> 00:42:53,038 밑에서만 사용되고 있는데 619 00:42:53,038 --> 00:42:54,439 맨 위에 선언되어있다면 620 00:42:54,439 --> 00:42:55,852 사용되는 근처로 변수 선언을 옮기세요 621 00:42:55,852 --> 00:42:58,205 그러면 연관된 코드들이 모여있게 되므로 622 00:42:58,205 --> 00:43:00,850 코드를 분리하기에도 좋습니다. 623 00:43:00,850 --> 00:43:02,894 이제 624 00:43:02,894 --> 00:43:10,145 친구인지를 바로 625 00:43:10,145 --> 00:43:16,843 알 수 있지요 626 00:43:16,843 --> 00:43:22,093 loggedUser보다 loggedInUser가 낫군요 627 00:43:22,093 --> 00:43:23,938 이렇게요 628 00:43:23,938 --> 00:43:25,487 기존 코드에 작업을 하다가 629 00:43:25,487 --> 00:43:28,668 이름이 이상하거나 적당하지 않으면 630 00:43:28,668 --> 00:43:29,997 그 순간에 바로 631 00:43:29,997 --> 00:43:31,698 이름을 바꾸세요. 632 00:43:31,698 --> 00:43:33,238 좋습니다. 여기 보이죠 633 00:43:33,238 --> 00:43:37,850 여기 초록색 상태바를 계속 보는 거에요 634 00:43:37,850 --> 00:43:39,176 코드를 저장할 때마다 635 00:43:39,176 --> 00:43:41,223 수정된 부분의 테스트가 실행돼서 결과가 표시됩니다. 636 00:43:41,223 --> 00:43:47,489 이제 이 부분을 주석 처리할 수 있겠지요 637 00:43:47,489 --> 00:43:49,477 저장을 하고요 638 00:43:49,477 --> 00:43:52,536 테스트 결과를 보니 정상이네요. 639 00:43:52,536 --> 00:43:53,666 이제 지우면 되겠네요. 640 00:43:54,666 --> 00:43:57,265 이 것도 지우고요 641 00:43:58,345 --> 00:44:00,456 그러면 아마도.. 642 00:44:09,923 --> 00:44:12,672 이 건 인라인하고요 643 00:44:12,672 --> 00:44:14,054 좋습니다. 644 00:44:14,584 --> 00:44:16,051 깔끔하네요. 645 00:44:17,761 --> 00:44:23,281 이 것도 금방 바꿀 수 있겠지요 646 00:44:23,281 --> 00:44:25,697 이 부분이요 647 00:44:26,387 --> 00:44:27,720 Guard Clause 패턴을 적용할 수 있겠지요? 648 00:44:27,720 --> 00:44:30,448 이 부분을 Guard Clause로 바꿀 수 있습니다. 649 00:44:30,448 --> 00:44:31,482 Guard Clause는요 650 00:44:31,482 --> 00:44:33,328 파라메터가 들어오자마자 651 00:44:33,328 --> 00:44:35,865 유효성을 검증하는 것이지요. 652 00:44:35,865 --> 00:44:37,430 653 00:44:37,430 --> 00:44:39,693 그러면 654 00:44:40,143 --> 00:44:44,895 이 부분을 Guard Clause로 변경해서 655 00:44:44,895 --> 00:44:46,005 이 if 문을 없애보겠습니다. 656 00:44:48,265 --> 00:44:53,313 loggedInUser가 Null이면 657 00:44:56,293 --> 00:44:58,156 658 00:45:00,336 --> 00:45:02,558 예외를 던지는 거지요. 659 00:45:03,308 --> 00:45:06,733 이 게 위에 있어야겠지요. 660 00:45:09,003 --> 00:45:11,792 저장을 하면 바로 661 00:45:11,792 --> 00:45:13,585 녹색으로 표시되네요. 662 00:45:14,275 --> 00:45:19,897 친절하게도 이클립스가 이 부분은 실행되지 않는 코드라고 알려주네요. 663 00:45:19,897 --> 00:45:23,988 이제 if 문을 삭제할 수 있겠습니다. 664 00:45:27,578 --> 00:45:29,335 저장하고 665 00:45:29,935 --> 00:45:30,577 좋습니다. 666 00:45:30,577 --> 00:45:35,021 지금 리팩토링하는 동안에 한 번도 테스트가 실패하지 않고 있지요. 667 00:45:35,311 --> 00:45:36,583 지금 리팩토링하는 동안에 한 번도 테스트가 실패하지 않고 있지요. 668 00:45:36,583 --> 00:45:39,861 혹시 실수를 해서 실패하는 테스트가 생겨도요 669 00:45:39,861 --> 00:45:42,506 실제 업무 중에는 그럴 수도 있겠지요 670 00:45:42,506 --> 00:45:45,885 Ctrl+Z를 누르면 되요. 671 00:45:45,885 --> 00:45:47,135 금방 이전 상태로 되돌릴 수 있습니다. 672 00:45:47,135 --> 00:45:48,277 그리고 뭐가 잘못된건지 생각하면 됩니다. 673 00:45:48,277 --> 00:45:50,529 테스트를 유지할 수 없는 경우도 있겠지만 674 00:45:50,529 --> 00:45:53,841 가능한 피해야 합니다. 675 00:45:53,841 --> 00:45:57,490 이제 코드가 두 개의 블럭으로 구분되는군요. 676 00:45:58,930 --> 00:46:06,300 첫 번째 블럭은 유저 정보를 검증하고요 677 00:46:06,300 --> 00:46:13,985 두 번째 블럭은 친구의 여행 정보를 조회합니다. 678 00:46:13,985 --> 00:46:17,366 여기서도 조금 더 개선이 가능하겠네요 679 00:46:17,366 --> 00:46:20,223 어디 봅시다 680 00:46:23,233 --> 00:46:25,919 레거시 코드에서 변수를 제거하는 것도 681 00:46:25,919 --> 00:46:28,994 시도해 볼 만한 것 입니다. 682 00:46:28,994 --> 00:46:32,182 변수 개 수가 적을 수록 코드는 더 쉬워지거든요. 683 00:46:32,182 --> 00:46:36,525 조금은 중복이 되거나 684 00:46:36,525 --> 00:46:38,717 메소드를 두 번 호출하게되서 685 00:46:38,717 --> 00:46:41,353 약간의 성능이 희생되는 경우에도 가치가 있습니다. 686 00:46:41,923 --> 00:46:43,565 변수를 줄이는 것은요 687 00:46:43,565 --> 00:46:47,101 변수는 여러 곳에서 값이 세팅되고 참조되기 때문에 688 00:46:47,101 --> 00:46:49,969 긴 코드를 파악하기 어렵게 합니다. 689 00:46:50,179 --> 00:46:51,814 변수를 없애고 690 00:46:51,814 --> 00:46:55,658 메소드를 반복해서 호출하면 691 00:46:55,658 --> 00:46:58,209 코드를 이해하기 쉬워집니다. 692 00:46:58,209 --> 00:47:02,224 그런 후에 꼭 필요한 경우에만 최적화 하면 됩니다. 693 00:47:02,224 --> 00:47:09,585 예를 들어 이런 식으로요. 694 00:47:16,185 --> 00:47:17,741 저장을 하면 695 00:47:17,741 --> 00:47:19,365 문제 없지요? 696 00:47:19,715 --> 00:47:25,885 이런 식으로도 변경할 수 있을 거에요 697 00:47:25,885 --> 00:47:27,197 698 00:47:29,817 --> 00:47:31,614 문제 없고요 699 00:47:32,604 --> 00:47:34,676 700 00:47:35,576 --> 00:47:37,263 이 건 필요 없지요. 701 00:47:37,263 --> 00:47:40,053 그대로입니다. 702 00:47:40,053 --> 00:47:42,420 이 변수는 이제 필요 없지요 703 00:47:42,420 --> 00:47:44,071 이 것도 필요 없고요 704 00:47:44,071 --> 00:47:45,693 테스트는 정상이에요 705 00:47:45,993 --> 00:47:49,269 삼항 연산자를 써서 706 00:47:49,269 --> 00:47:52,851 조금 더 간단하게 해볼까요 707 00:47:52,851 --> 00:47:57,614 예를 들어서 708 00:48:11,854 --> 00:48:13,649 저장을 하면 709 00:48:13,649 --> 00:48:14,858 여전히 녹색이네요. 710 00:48:14,858 --> 00:48:15,849 좋습니다. 711 00:48:15,849 --> 00:48:17,504 그 다음에 712 00:48:17,504 --> 00:48:20,754 이 변수는 두 군데에 사용되고 있는데요 713 00:48:20,754 --> 00:48:22,495 인라인 시키겠습니다. 714 00:48:22,495 --> 00:48:24,307 715 00:48:24,307 --> 00:48:25,531 둘 다 인라인 되었지요. 716 00:48:25,531 --> 00:48:27,006 이런 식이지요. 717 00:48:27,006 --> 00:48:28,613 변수를 없앴습니다. 718 00:48:29,093 --> 00:48:32,524 물론 메소드를 두 번 호출하고 있어요 719 00:48:32,524 --> 00:48:34,890 하지만 코드는 더 간단해졌지요. 720 00:48:34,890 --> 00:48:36,489 물론 이렇게 해서 성능에 문제가 생기면 721 00:48:36,503 --> 00:48:39,903 메소드 호출을 줄이도록 수정해야겠지요. 722 00:48:39,903 --> 00:48:44,855 좋습니다. 훨씬 좋아졌네요. 723 00:48:44,935 --> 00:48:49,044 이 부분은 마음에 들지않는군요.. 724 00:48:51,124 --> 00:48:54,834 메소드로 만들겠습니다. 725 00:48:54,834 --> 00:48:58,117 726 00:49:01,527 --> 00:49:03,867 이렇게 하면 좋은 점은요 727 00:49:05,647 --> 00:49:07,933 예를 들어서요 728 00:49:10,153 --> 00:49:11,771 코드를 보면 729 00:49:11,771 --> 00:49:13,959 테스트를 보면요 730 00:49:15,379 --> 00:49:18,634 테스트 이름은 유저가 로그인하지 않은 경우에 예외를 던진다 731 00:49:18,794 --> 00:49:20,523 로그인 된 유저를 조회한다 732 00:49:20,523 --> 00:49:22,058 예외를 던진다 733 00:49:22,058 --> 00:49:27,100 테스트는 유저가 친구가 아니면 여행 정보를 반환하지 않는다 734 00:49:27,100 --> 00:49:29,738 유저가 로그인 유저와 친구라면 735 00:49:29,738 --> 00:49:31,027 여행 정보가 없고 736 00:49:31,027 --> 00:49:34,334 테스트는 유저가 친구들인 경우에 여행 정보를 조회한다 737 00:49:34,334 --> 00:49:36,318 로그인 유저와 친구인 경우 738 00:49:36,318 --> 00:49:37,851 유저의 여행 목록 739 00:49:37,851 --> 00:49:44,936 이런 식으로 테스트에 사용하는 용어들이 740 00:49:44,936 --> 00:49:46,228 제품 코드 구현에도 그대로 사용되게 됩니다. 741 00:49:46,228 --> 00:49:47,542 제품 코드 구현에도 그대로 사용되게 됩니다. 742 00:49:47,542 --> 00:49:49,916 꼭 이런 식으로 작성해보시길 바랍니다. 743 00:49:49,916 --> 00:49:55,244 잠시 멈추고 커밋하겠습니다. 744 00:49:55,244 --> 00:49:56,765 745 00:49:56,765 --> 00:49:59,122 746 00:49:59,422 --> 00:50:02,157 747 00:50:03,357 --> 00:50:07,543 TripService refactored 748 00:50:09,193 --> 00:50:09,896 좋습니다. 749 00:50:12,336 --> 00:50:13,745 훌륭해요. 750 00:50:15,385 --> 00:50:19,788 이 정도면 충분하겠지요? 751 00:50:20,298 --> 00:50:21,518 마무리할까요? 752 00:50:22,362 --> 00:50:23,279 아닙니다. 753 00:50:23,279 --> 00:50:26,261 아직 한참 멀었습니다. 754 00:50:27,841 --> 00:50:30,296 여기 이 짧은 코드요 755 00:50:30,716 --> 00:50:35,407 어마 어마한 문제점을 가지고 있습니다. 756 00:50:36,267 --> 00:50:39,067 그 중 하나를 이야기하면요 757 00:50:39,067 --> 00:50:40,613 우리는 지금까지 758 00:50:40,613 --> 00:50:45,542 테스트가 없는 레거시 코드에 759 00:50:45,902 --> 00:50:48,444 테스트를 작성했습니다. 760 00:50:48,444 --> 00:50:50,107 그렇게 해서 761 00:50:50,107 --> 00:50:52,268 문제 없이 코드를 수정할 수 있다는 762 00:50:52,268 --> 00:50:55,851 자신감이 생겼어요. 대단한 일이지요. 763 00:50:55,851 --> 00:50:59,068 764 00:50:59,068 --> 00:51:02,047 하지만 반대로 단점도 있는데요 765 00:51:02,047 --> 00:51:04,364 기존 코드의 디자인이 나쁜 경우에는 어떻게 될까요? 766 00:51:05,944 --> 00:51:07,730 기존 코드의 디자인이 나쁜데 767 00:51:08,480 --> 00:51:10,096 그 위에 테스트를 작성해 놓으면 768 00:51:10,096 --> 00:51:12,518 디자인을 수정할 수 없게 만들어 버립니다. 769 00:51:13,058 --> 00:51:14,688 매우 주의해야 해요 770 00:51:14,688 --> 00:51:18,940 원래 디자인 변경은 쉽게 하는 일이 아닌데요 771 00:51:18,940 --> 00:51:22,334 그 위에 테스트들을 얹어버리면 772 00:51:22,334 --> 00:51:24,003 더 변경하기 힘들게 됩니다. 773 00:51:24,003 --> 00:51:25,452 디자인을 변경하는 순간 774 00:51:25,452 --> 00:51:26,917 작성했던 테스트들도 같이 수정해야 하므로 775 00:51:26,917 --> 00:51:28,572 주의해야 합니다. 776 00:51:28,572 --> 00:51:32,110 그럼 이 디자인은 뭐가 문제일까요? 777 00:51:32,500 --> 00:51:35,048 아마도 778 00:51:35,778 --> 00:51:41,252 TripService는 서버단 코드이고 779 00:51:41,252 --> 00:51:42,733 (MVC 중) 모델에 속할 겁니다. 780 00:51:44,023 --> 00:51:51,183 그런데 User Session을 직접 참조하고 있네요 781 00:51:51,183 --> 00:51:57,021 모델이 웹 프레임워크를 참조하면 안되지요 782 00:51:57,021 --> 00:52:01,132 Http Session 같은 것들을 알고 있으면 안됩니다. 783 00:52:01,692 --> 00:52:05,010 이 클래스는 User Session을 직접 참조하는 게 잘못된 겁니다. 784 00:52:05,010 --> 00:52:09,591 해결을 해야 할텐데요 785 00:52:10,021 --> 00:52:11,818 선택할 수 있는 하나의 방법은 786 00:52:11,818 --> 00:52:17,188 로그인 유저를 메소드에 인자로 전달하는 겁니다. 787 00:52:17,188 --> 00:52:23,495 이제 위험한 리팩토링을 시작하겠습니다. 788 00:52:23,495 --> 00:52:26,180 오늘 연습이야 별 문제 없겠습니다만 789 00:52:26,180 --> 00:52:28,543 실제 업무에서 할 때에는 790 00:52:28,543 --> 00:52:29,661 주의를 기울이셔야 합니다. 791 00:52:29,661 --> 00:52:31,321 조심스럽게 792 00:52:31,321 --> 00:52:32,998 언제나 처럼 793 00:52:32,998 --> 00:52:35,200 조금씩 작업하겠습니다. 794 00:52:35,200 --> 00:52:40,283 메소드 파라메터로 로그인 유저를 전달하게 할 건데요 795 00:52:40,283 --> 00:52:42,896 사용할 수 있는 방법은 796 00:52:42,896 --> 00:52:46,285 리팩토링에서 797 00:52:46,285 --> 00:52:48,232 메소드 시그니처를 수정해서 798 00:52:48,232 --> 00:52:50,890 파라메터를 추가하겠습니다. 799 00:52:51,110 --> 00:52:52,994 800 00:52:55,364 --> 00:52:59,251 801 00:52:59,251 --> 00:53:00,912 기본 값은 Null이고요 802 00:53:01,502 --> 00:53:04,340 좋습니다. 803 00:53:04,399 --> 00:53:07,697 이클립스의 리팩토링 기능은 매우 강력합니다. 804 00:53:07,697 --> 00:53:09,612 인텔리제이도 그렇고요. 805 00:53:09,612 --> 00:53:12,628 이 유저 파라메터는 806 00:53:12,628 --> 00:53:14,533 사용되고 있지는 않지요. 807 00:53:14,533 --> 00:53:17,583 테스트 코드를 보면 808 00:53:17,583 --> 00:53:22,745 Null을 전달하는 것으로 변경되어 있네요. 809 00:53:23,215 --> 00:53:25,570 멋지군요. 810 00:53:25,570 --> 00:53:28,626 여기서 문제는요 811 00:53:28,626 --> 00:53:31,506 이 메소드는 제품 코드이니 812 00:53:31,506 --> 00:53:33,525 이미 사용되고 있을 거에요 813 00:53:33,525 --> 00:53:37,261 아마 여러 군데서 사용 중이겠지요. 814 00:53:37,261 --> 00:53:44,536 따라서 사용되는 모든 곳에서 815 00:53:44,536 --> 00:53:47,355 Null을 넣어주고 있을 테니 816 00:53:47,355 --> 00:53:49,686 모든 곳에서 전부 수정을 해줘야 합니다. 817 00:53:49,686 --> 00:53:51,897 잊지 마시기 바랍니다. 818 00:53:52,857 --> 00:53:56,196 일단 지금 819 00:53:58,496 --> 00:53:59,775 해야 할 것은 820 00:53:59,775 --> 00:54:00,816 테스트를 수정해야지요 821 00:54:00,816 --> 00:54:03,642 여기 Null을 전달하는 게 보기 싫군요. 822 00:54:03,642 --> 00:54:05,126 로그인 유저를 전달해야 하니 823 00:54:05,126 --> 00:54:07,720 게스트를 넣어주고요 824 00:54:07,720 --> 00:54:09,761 825 00:54:11,751 --> 00:54:15,227 인피니테스트 결과를 확인하고요 826 00:54:15,227 --> 00:54:22,113 여기에는 로그인 된 유저를 넣어야지요 827 00:54:22,113 --> 00:54:24,433 여기에는 828 00:54:26,623 --> 00:54:30,336 네 여기에도 로그인 된 유저를 넣겠습니다. 829 00:54:36,226 --> 00:54:37,497 좋습니다. 830 00:54:37,497 --> 00:54:39,395 한 번 더 확인해보고요. 831 00:54:39,395 --> 00:54:40,717 좋습니다. 832 00:54:41,787 --> 00:54:45,376 이제 전달되는 파라메터를 사용해야겠지요 833 00:54:46,706 --> 00:54:48,290 이제 834 00:54:49,110 --> 00:54:53,519 전달된 걸 사용할거에요. 835 00:54:53,519 --> 00:54:59,106 파라메터를 사용하게 변경할겁니다. 836 00:54:59,106 --> 00:55:04,050 여기 메소드 호출을 837 00:55:04,050 --> 00:55:06,682 파라메터로 변경하고요 838 00:55:06,682 --> 00:55:08,574 저장을 하면.. 839 00:55:11,294 --> 00:55:14,088 테스트 결과는 정상입니다. 840 00:55:14,088 --> 00:55:16,350 그러면 이 메소드는요 841 00:55:16,350 --> 00:55:18,579 private으로 변경하면 842 00:55:18,579 --> 00:55:22,050 사용 안 된다고 표시가 되지요. 843 00:55:22,050 --> 00:55:25,290 삭제해도 안전하겠군요. 844 00:55:26,340 --> 00:55:29,610 삭제한 후에 845 00:55:29,610 --> 00:55:32,305 이 것도 삭제할 수 있겠지요. 846 00:55:32,305 --> 00:55:35,729 다시 정상으로 돌아왔지요. 847 00:55:35,729 --> 00:55:37,238 유저를 파라메터로 전달하게 848 00:55:37,238 --> 00:55:40,050 리팩토링 했습니다. 849 00:55:40,930 --> 00:55:43,151 이제 할 것은 850 00:55:43,151 --> 00:55:45,604 이 loggedInUser 필드는 851 00:55:45,954 --> 00:55:48,526 필요할 것 같지 않네요. 852 00:55:48,526 --> 00:55:54,684 이렇게 바꾸면요 853 00:55:55,604 --> 00:55:58,927 여기도요 854 00:56:02,057 --> 00:56:05,907 그러면 이클립스가 855 00:56:05,907 --> 00:56:10,250 이 변수가 사용되지 않는다고 알려주지요. 856 00:56:10,250 --> 00:56:14,297 삭제할 수 있겠군요. 857 00:56:14,297 --> 00:56:16,931 삭제하고요. 858 00:56:16,931 --> 00:56:19,144 이 것도요 859 00:56:19,144 --> 00:56:22,953 테스트도 정상입니다. 860 00:56:22,953 --> 00:56:26,395 커밋을 해야겠네요. 861 00:56:26,395 --> 00:56:29,167 오. 여기 경고가 있네요 862 00:56:29,167 --> 00:56:32,750 사용하지 않는 import는 지워야지요 863 00:56:32,750 --> 00:56:35,137 깔끔하게요. 864 00:56:35,137 --> 00:56:37,129 장인정신은 중요합니다. 865 00:56:37,129 --> 00:56:38,836 항상 깔끔하게 유지해야지요. 866 00:56:39,826 --> 00:56:42,407 좋습니다. 잠시 멈추고요. 867 00:56:42,407 --> 00:56:44,401 868 00:56:45,171 --> 00:56:47,032 869 00:56:50,332 --> 00:57:00,543 Logged in user passed in to TripService 870 00:57:01,733 --> 00:57:03,620 좋습니다. 871 00:57:06,470 --> 00:57:08,876 대충 마무리됐을까요. 872 00:57:10,566 --> 00:57:12,997 873 00:57:12,997 --> 00:57:17,129 이 부분은 여전히 마음에 안 드네요. 874 00:57:17,899 --> 00:57:19,315 TripDAO의 875 00:57:19,315 --> 00:57:21,255 static 메소드를 직접 호출하고 있지요. 876 00:57:21,255 --> 00:57:25,345 그래서 이런 식으로 해야만 했어요. 877 00:57:25,345 --> 00:57:30,169 말했듯이 임시적인 방법인데요 878 00:57:30,175 --> 00:57:33,857 제대로 한다면 TripDAO를 주입해서 879 00:57:34,102 --> 00:57:36,248 멤버 변수를 사용하게 만들어야 하는데요 880 00:57:36,346 --> 00:57:38,951 static 메소드라서 881 00:57:38,951 --> 00:57:41,405 다른 것으로 대체하기가 어렵지요. 882 00:57:41,405 --> 00:57:42,722 왜냐하면 일반적으로 883 00:57:42,722 --> 00:57:46,333 인스턴스만 주입이 가능하고 클래스는 불가하기 때문에 884 00:57:46,333 --> 00:57:48,188 Mock으로 대체할 수 없습니다. 885 00:57:48,188 --> 00:57:50,802 그럼 조금 더 수정해서 886 00:57:50,802 --> 00:57:52,612 이 부분을 없애고 887 00:57:52,612 --> 00:57:56,265 TripDAO의 멤버 변수를 만들어 사용하게 해보겠습니다. 888 00:57:56,265 --> 00:57:57,687 TripDAO 클래스를 열어 889 00:57:57,687 --> 00:57:59,088 구현 내용을 보면요 890 00:57:59,088 --> 00:58:00,423 지금 이 코드는 891 00:58:00,423 --> 00:58:02,488 단순한 예제 코드라 예외를 던지고 끝나지만요 892 00:58:02,488 --> 00:58:04,653 단순한 예제 코드라 예외를 던지고 끝나지만요 893 00:58:06,113 --> 00:58:10,391 앞에 이야기한 것처럼 894 00:58:10,391 --> 00:58:11,888 보통은 데이터베이스나 895 00:58:11,888 --> 00:58:12,956 분산 캐시 같은 896 00:58:12,956 --> 00:58:18,240 저장하는 무언가에 엑세스하겠지요. 897 00:58:19,150 --> 00:58:21,292 자 이제 898 00:58:22,012 --> 00:58:28,973 멤버 메소드를 만들건대요. 899 00:58:30,393 --> 00:58:35,448 먼저 테스트를 작성해야겠지요. 900 00:58:37,558 --> 00:58:39,052 901 00:58:42,938 --> 00:58:45,721 902 00:58:47,334 --> 00:58:49,164 테스트 폴더에 넣고 903 00:58:51,646 --> 00:58:53,733 이 것도 흥미로운 기법이니 904 00:58:55,573 --> 00:58:56,982 눈 여겨 보세요. 905 00:58:58,132 --> 00:59:03,334 기존 Static 메소드와 동일한 기능을 하는 906 00:59:03,334 --> 00:59:08,534 인스턴스 메소드를 만들 거에요. 907 00:59:11,530 --> 00:59:13,290 똑 같이 동작하게요. 908 00:59:15,661 --> 00:59:18,445 그냥 Static 키워드를 없애도 가능하겠지요. 909 00:59:18,445 --> 00:59:22,546 여기 static 글자만 지워서요 910 00:59:22,546 --> 00:59:23,902 물론 가능합니다만 911 00:59:23,902 --> 00:59:24,959 그렇게 하면 912 00:59:24,959 --> 00:59:27,574 여기 저기 수정할 게 많을 겁니다. 913 00:59:27,574 --> 00:59:31,951 어플리케이션에서 이 메소드를 사용하는 클래스가 914 00:59:32,331 --> 00:59:35,285 여러 개 있는 상황에서 915 00:59:35,285 --> 00:59:37,965 이걸 인스턴스 메소드로 바꿔버리면 916 00:59:37,965 --> 00:59:39,727 전부 컴파일 에러가 나겠지요. 917 00:59:39,727 --> 00:59:42,515 그러면 일이 너무 커져버립니다. 918 00:59:42,515 --> 00:59:45,498 우린 조금씩 안전하게 작업을 할거니까요 919 00:59:46,068 --> 00:59:48,287 그래서 920 00:59:49,166 --> 00:59:51,203 테스트를 만들겠습니다. 921 00:59:51,203 --> 00:59:53,128 예제 DAO를 테스트하는 거니까 922 00:59:53,128 --> 00:59:54,929 이 테스트가 검증하는 디테일 한 부분에는 923 00:59:54,929 --> 00:59:57,434 집중하실 필요는 없습니다. 924 00:59:57,434 --> 01:00:00,785 그냥 예제 DAO의 동작을 검증하겠습니다. 925 01:00:00,785 --> 01:00:19,857 유저의 여행정보를 조회하면 예외를 발생하는 거지요 926 01:00:21,302 --> 01:00:25,903 예외가 발생해야겠지요. 927 01:00:27,903 --> 01:00:29,802 말씀드린대로 928 01:00:29,802 --> 01:00:33,701 원래는 데이터를 조회해야겠지만 929 01:00:33,732 --> 01:00:35,911 이 예제 코드에서는 930 01:00:35,911 --> 01:00:40,407 바로 예외를 던지지요. 931 01:00:40,407 --> 01:00:41,870 이거지요. 932 01:00:41,870 --> 01:00:44,679 인스턴스 메소드를 사용하려고 하니까요 933 01:00:44,679 --> 01:00:47,836 메소드를 호출하기만 하면 되겠지요 934 01:00:47,836 --> 01:00:49,233 그러니까 935 01:00:49,233 --> 01:00:51,708 936 01:00:54,723 --> 01:01:06,018 937 01:01:09,728 --> 01:01:13,185 인스턴스가 필요하지요 938 01:01:14,845 --> 01:01:16,130 939 01:01:16,130 --> 01:01:18,279 메소드를 생성해서 940 01:01:18,769 --> 01:01:26,240 기존 거랑 똑 같이 동작하게 할 겁니다 941 01:01:32,740 --> 01:01:34,967 테스트는 실패하고 있지요. 당연합니다. 942 01:01:34,967 --> 01:01:37,144 이제는요 943 01:01:37,144 --> 01:01:39,519 기존 static 메소드랑 똑 같이 동작해야 하니까요 944 01:01:39,519 --> 01:01:43,096 945 01:01:45,036 --> 01:01:51,626 이 안에서 946 01:01:51,626 --> 01:01:53,093 기존 메소드를 호출합니다. 947 01:01:54,003 --> 01:01:55,550 이렇게 하는 이유는요 948 01:01:55,550 --> 01:01:56,812 이렇게 하는 이유는요 949 01:01:57,073 --> 01:02:02,570 점진적으로 기존 코드들을 새 메소드를 사용하게 바꿔가려는 거지요. 950 01:02:04,790 --> 01:02:06,327 여기에서 951 01:02:06,327 --> 01:02:09,359 TripService가 인스턴스 메소드를 호출하게 하는 거지요 952 01:02:09,398 --> 01:02:11,230 이렇게 시작해서 953 01:02:11,230 --> 01:02:13,165 Static 메소드를 사용하는 클래스가 없어질 때까지 954 01:02:13,165 --> 01:02:19,120 계속 바꿔나가는 겁니다. 955 01:02:19,120 --> 01:02:20,042 그런 후에 956 01:02:20,042 --> 01:02:21,633 이 Static 메소드의 내용을 복사해서 957 01:02:21,633 --> 01:02:24,325 여기로 옮기고 Static 메소드는 지워버리면 958 01:02:24,325 --> 01:02:25,568 끝이지요. 959 01:02:25,568 --> 01:02:27,208 유용한 기법이에요. 960 01:02:27,208 --> 01:02:28,855 다시 돌아가서 961 01:02:28,855 --> 01:02:35,024 인스턴스 메소드가 완성됐습니다. 962 01:02:35,024 --> 01:02:38,483 이제는 963 01:02:38,483 --> 01:02:43,623 TripDAO를 인젝트 해야 하는데요 964 01:02:44,080 --> 01:02:46,023 965 01:02:46,023 --> 01:02:48,757 방법은 여러 가지가 있습니다. 예를 들어 966 01:02:48,757 --> 01:02:51,225 DI 프레임워크 없이 그냥 할 수도 있겠지요 967 01:02:51,225 --> 01:02:55,115 그냥 TripService의 생성자에 TripDAO를 넣어주면 됩니다. 968 01:02:55,115 --> 01:02:57,201 그렇게 하는 게 969 01:02:57,201 --> 01:02:59,487 가장 간단한 방법입니다. 970 01:02:59,487 --> 01:03:02,776 그래도 대부분의 자바 개발자들은 971 01:03:02,776 --> 01:03:05,837 Spring, Mockito 등을 주로 사용하니까요 972 01:03:05,898 --> 01:03:08,342 Mockito를 이용하는 방법을 보여드리겠습니다. 973 01:03:08,342 --> 01:03:10,695 만약에 Mockito를 사용하지 않으면 974 01:03:10,695 --> 01:03:11,659 그냥 심플하게 975 01:03:11,722 --> 01:03:16,509 생성자를 만들어 TripDAO를 건네주면 됩니다. 976 01:03:16,843 --> 01:03:19,247 그럼 Spring, Mockito를 사용해서 977 01:03:19,247 --> 01:03:21,762 테스트하는 방법을 보여드리겠습니다. 978 01:03:21,826 --> 01:03:26,675 이제 TripDAO를 인젝트 할 수 있도록 979 01:03:26,675 --> 01:03:30,606 테스트를 변경하도록 하겠습니다. 980 01:03:30,606 --> 01:03:33,269 이제 981 01:03:33,315 --> 01:03:35,942 JUnit과 Mockito를 사용할 거니까 982 01:03:36,034 --> 01:03:37,271 983 01:03:37,344 --> 01:03:39,094 984 01:03:42,064 --> 01:03:46,700 Mockito나 JUnit을 사용하지 않는 사람에게는 985 01:03:46,700 --> 01:03:48,409 좀 복잡해 보일 겁니다. 986 01:03:48,409 --> 01:03:52,298 그렇다면 관련 문서들을 읽어보시기 바랍니다. 987 01:03:54,538 --> 01:04:00,891 지금까지는 TestableTripService을 사용하고 있었는데요 988 01:04:00,891 --> 01:04:03,106 지금까지는 TestableTripService을 사용하고 있었는데요 989 01:04:03,856 --> 01:04:06,761 이제 TripService를 바로 사용하겠습니다. 990 01:04:06,761 --> 01:04:09,046 직접 생성하지 않고 주입 받아서요. 991 01:04:09,046 --> 01:04:12,568 TestableTripService를 이제 지워야겠어요 992 01:04:12,568 --> 01:04:15,090 더 이상 필요가 없습니다. 993 01:04:15,625 --> 01:04:18,617 의존하는 것들은 Mock으로 바꿔서 테스트할 수 있게 994 01:04:18,617 --> 01:04:21,305 조금씩 안전하게 작업하겠습니다. 995 01:04:21,305 --> 01:04:23,773 TripService를 하나 더 만들고요 996 01:04:24,223 --> 01:04:25,536 TripService를 하나 더 만들고요 997 01:04:27,476 --> 01:04:36,756 일단 realTripService라고 하고 998 01:04:36,756 --> 01:04:38,409 이건 진짜 TripService의 인스턴스에요 999 01:04:38,409 --> 01:04:41,144 Mock을 만들고요 1000 01:04:52,347 --> 01:04:54,688 TripDAO의 Mock이요 1001 01:05:00,488 --> 01:05:02,737 Mockito 기능을 사용해서 1002 01:05:04,357 --> 01:05:06,028 TripService가 1003 01:05:06,028 --> 01:05:09,846 Mock을 사용하게 하겠습니다. 1004 01:05:11,246 --> 01:05:20,637 Mockito가 어떻게 동작하는지는 오늘 주제에서 조금 벗어나지만 1005 01:05:20,637 --> 01:05:25,918 간단하게 설명 드리면 1006 01:05:25,918 --> 01:05:27,641 실제 TripService 인스턴스가 생성될 때에 1007 01:05:27,641 --> 01:05:30,405 Mockito가 TripService 클래스를 분석해서 1008 01:05:31,005 --> 01:05:35,162 TripService가 사용하는 Mock들을 자동으로 주입시키는 겁니다. 1009 01:05:35,162 --> 01:05:36,973 Mock DAO는 여기에 있고요 1010 01:05:36,973 --> 01:05:40,763 이제 TripService가 이 Mock TripDAO가 필요하다는 것만 명시하면 됩니다. 1011 01:05:41,786 --> 01:05:43,753 일단 그 전에 1012 01:05:43,753 --> 01:05:46,924 이제 이 TripService의 인스턴스를요 1013 01:05:46,924 --> 01:05:48,613 1014 01:05:48,613 --> 01:05:49,408 1015 01:05:49,408 --> 01:05:51,111 조금씩 조금씩 1016 01:05:51,111 --> 01:05:55,042 realTripService로 바꾸고 저장.. 1017 01:05:56,352 --> 01:05:59,958 테스트 결과는 정상이지요 1018 01:06:00,678 --> 01:06:02,947 지금 하려는 거는요 1019 01:06:02,947 --> 01:06:05,562 테스트에서 사용 중인 TestableTripService를 1020 01:06:05,917 --> 01:06:06,979 조금씩 1021 01:06:07,579 --> 01:06:08,989 TripService 인스턴스로 바꾸는 겁니다. 1022 01:06:09,569 --> 01:06:11,077 1023 01:06:11,346 --> 01:06:13,376 이렇게 하면 1024 01:06:13,916 --> 01:06:16,272 정상이지요. 1025 01:06:16,279 --> 01:06:17,414 지금 테스트가 통과하는 이유는 1026 01:06:17,414 --> 01:06:20,456 TripDAO를 사용하지 않기 때문이에요. 1027 01:06:20,456 --> 01:06:22,371 이 코드를 사용하지 않는 테스트들인 거지요. 1028 01:06:23,686 --> 01:06:30,830 이 테스트도 바꾸면요.. 1029 01:06:31,790 --> 01:06:34,690 실패하는 군요. 1030 01:06:34,690 --> 01:06:36,614 이거지요. 1031 01:06:36,614 --> 01:06:38,552 TripService 인스턴스에서 1032 01:06:38,552 --> 01:06:44,196 TripDAO의 Static 메소드를 호출했기 때문에 1033 01:06:44,196 --> 01:06:47,671 TripDAO의 Static 메소드를 호출했기 때문에 1034 01:06:47,671 --> 01:06:49,103 예외가 떨어진 거에요. 1035 01:06:49,103 --> 01:06:51,094 이제 실패한 테스트가 있으니 1036 01:06:51,094 --> 01:06:54,254 제품 코드를 수정해야겠네요. 1037 01:06:56,634 --> 01:06:59,485 그래서 1038 01:06:59,511 --> 01:07:02,190 제품 코드에서요 1039 01:07:02,190 --> 01:07:03,899 스프링인 경우지요 1040 01:07:04,269 --> 01:07:05,721 1041 01:07:17,858 --> 01:07:21,982 import 하고 1042 01:07:21,982 --> 01:07:25,451 TripDAO는 XML에 스프링 빈으로 등록했다고 하고요 1043 01:07:25,451 --> 01:07:26,527 TripDAO는 XML에 스프링 빈으로 등록했다고 하고요 1044 01:07:26,527 --> 01:07:31,569 1045 01:07:31,569 --> 01:07:32,703 좋습니다. 1046 01:07:35,163 --> 01:07:36,834 화면을 늘리고 1047 01:07:38,194 --> 01:07:40,191 1048 01:07:40,215 --> 01:07:41,822 이러면 Mockito가 1049 01:07:41,822 --> 01:07:43,844 이 Mock TripDAO를 1050 01:07:43,850 --> 01:07:46,601 여기 TripService에 넣어줄 겁니다. 1051 01:07:49,427 --> 01:07:52,011 그래서 이 TripDAO를 사용하게 해야 하는데요 1052 01:07:52,401 --> 01:07:54,745 테스트는 실패하고 있지요? 1053 01:07:54,985 --> 01:07:56,949 이 TripDAO를 사용하려면 1054 01:07:56,949 --> 01:08:02,403 이거 대신에 1055 01:08:04,893 --> 01:08:07,214 일단 테스트를 돌리면요 1056 01:08:07,214 --> 01:08:09,919 차이점을 보려고요 1057 01:08:29,432 --> 01:08:30,887 실행하고 1058 01:08:32,749 --> 01:08:35,006 계속 단축키를 잘 못 누르네요 1059 01:08:35,083 --> 01:08:39,907 아직 실제 DAO를 호출해서 에러가 나고 있는 겁니다. 1060 01:08:39,907 --> 01:08:45,323 그래서 인스턴스 메소드를 호출하게 하고 1061 01:08:45,323 --> 01:08:49,473 기존 Static 메소드 대신에 1062 01:08:49,473 --> 01:08:51,457 인스턴스 메소드를 사용하게 해서 1063 01:08:52,357 --> 01:08:55,749 테스트를 실행하면 1064 01:08:55,749 --> 01:08:59,620 에러가 변했지요 1065 01:08:59,620 --> 01:09:02,634 이제 Mock DAO를 사용하고 있는 겁니다. 1066 01:09:03,144 --> 01:09:07,452 화면은 줄이고 1067 01:09:07,452 --> 01:09:12,105 이젠 Mock DAO가 실행된 겁니다. 1068 01:09:12,885 --> 01:09:17,721 MockDAO가 여행 정보 2개를 반환되었어야 하는데 아무것도 없었던 거지요. 1069 01:09:17,901 --> 01:09:19,679 원래 테스트 시나리오는 1070 01:09:19,679 --> 01:09:21,530 여행 정보 2개가 필요하니까요 1071 01:09:23,560 --> 01:09:26,381 이제.. 1072 01:09:26,381 --> 01:09:28,044 이렇게 되는 이유는 1073 01:09:28,044 --> 01:09:31,146 TipService가 Mock TripDAO를 호출하는데 1074 01:09:31,146 --> 01:09:33,012 Mock TripDAO가 어떻게 동작해야 할지 설정하지 않아서 에요. 1075 01:09:33,047 --> 01:09:37,679 그러니까 1076 01:09:40,799 --> 01:09:44,475 1077 01:09:44,475 --> 01:09:48,566 1078 01:09:52,125 --> 01:09:57,811 이 메소드가 호출이 되면 1079 01:09:59,101 --> 01:10:04,745 친구의 여행 목록을 반환해야지요 1080 01:10:04,745 --> 01:10:07,646 지금 하는 건 1081 01:10:07,646 --> 01:10:15,624 Mock DAO가 여행 목록을 반환하게 하는 거지요 1082 01:10:15,624 --> 01:10:19,122 이 코드가 했던 것과 동일하게 1083 01:10:19,122 --> 01:10:21,899 Mock이 동작하도록 하는 겁니다. 1084 01:10:21,899 --> 01:10:25,128 이제 테스트가 통과하는군요 1085 01:10:26,618 --> 01:10:31,067 이제 이걸 private로 바꿀 수 있겠지요 1086 01:10:32,697 --> 01:10:36,721 이 메소드는 이제 필요가 없고요 1087 01:10:38,831 --> 01:10:41,343 전체 테스트를 다시 돌리면 1088 01:10:41,343 --> 01:10:43,306 모두 정상이군요. 1089 01:10:43,306 --> 01:10:45,783 이 클래스가 더 이상 필요 없다는 말이지요 1090 01:10:48,187 --> 01:10:50,952 그건 이 것도 필요 없다는 거고 1091 01:10:51,472 --> 01:10:53,967 이 게 필요 없으면 이 것도 필요 없지요 1092 01:10:54,137 --> 01:10:57,254 이제 이 필드는 사용되지 않네요 1093 01:10:57,254 --> 01:10:58,874 삭제하고요 1094 01:11:00,164 --> 01:11:01,653 그러면 이제 1095 01:11:02,375 --> 01:11:04,350 realTripService는 이름을 바꿔야겠지요 1096 01:11:04,350 --> 01:11:05,770 이제 real은 의미가 없으니까요 1097 01:11:05,770 --> 01:11:07,160 테스트를 작성할 때에 1098 01:11:07,160 --> 01:11:13,534 testee, mock 같은 이름을 사용하는 경우가 종종 있는데요 1099 01:11:13,534 --> 01:11:14,950 실제로 무엇인지를 표현하면 됩니다. 1100 01:11:15,790 --> 01:11:20,208 이건 TripService이니까 그냥 tripService로 충분합니다. 그렇지요? 1101 01:11:20,248 --> 01:11:22,959 좋습니다. 1102 01:11:23,889 --> 01:11:27,427 이제 Test Double 클래스들도 필요 없고 1103 01:11:27,427 --> 01:11:30,450 테스트도 읽기 편합니다. 1104 01:11:30,940 --> 01:11:34,809 테스트를 한 번 더 돌려서 확인하고요. 1105 01:11:34,809 --> 01:11:37,683 여기는 이렇게 바꿀 수 있겠지요. 1106 01:11:43,523 --> 01:11:45,857 1107 01:11:47,367 --> 01:11:49,132 앞에 이야기한 것처럼 1108 01:11:49,132 --> 01:11:53,577 테스트 메소드들을 접으면 1109 01:11:55,374 --> 01:12:00,128 이렇게 되는 거지요. 1110 01:12:00,155 --> 01:12:02,537 유저가 로그인하지 않은 경우 예외를 던진다 1111 01:12:02,537 --> 01:12:05,117 여기에서 로그인 정보를 확인하지요 1112 01:12:05,907 --> 01:12:08,911 유저들이 친구가 아닌 경우 여행 목록을 반환하지 않는다 1113 01:12:08,911 --> 01:12:12,822 친구가 아닌 경우에는 빈 목록을 반환하고요 1114 01:12:13,742 --> 01:12:17,719 유저가 서로 친구인 경우에는 1115 01:12:17,719 --> 01:12:18,992 여행 정보를 반환하지요 1116 01:12:18,992 --> 01:12:22,244 로그인 유저와 친구인 경우에 1117 01:12:22,244 --> 01:12:24,023 여행 목록을 반환합니다. 1118 01:12:28,303 --> 01:12:31,446 이 getter 메소드는 좀 별로네요 1119 01:12:31,446 --> 01:12:35,727 getTripsByUser는요 1120 01:12:36,237 --> 01:12:39,141 getFriendTrips로 1121 01:12:39,881 --> 01:12:41,946 훨씬 낫지요? 1122 01:12:42,486 --> 01:12:45,946 이 변수도 1123 01:12:48,715 --> 01:12:50,672 friend가 좋겠네요 1124 01:12:51,982 --> 01:12:54,166 이런 식이지요 1125 01:12:55,966 --> 01:12:59,460 테스트가 잘 작성되어있으므로 1126 01:12:59,460 --> 01:13:02,282 이런 것들을 해볼 수가 있는 겁니다. 1127 01:13:02,652 --> 01:13:07,155 잠시 멈추고 커밋을 해볼까요. 1128 01:13:07,155 --> 01:13:09,231 1129 01:13:09,962 --> 01:13:12,333 1130 01:13:14,535 --> 01:13:17,504 1131 01:13:19,248 --> 01:13:26,593 TripDAO injected into TripService 1132 01:13:27,803 --> 01:13:30,958 됐습니다. 1133 01:13:30,958 --> 01:13:32,459 이런 식으로 1134 01:13:33,187 --> 01:13:35,400 레거시 코드를 안전하게 리팩토링 할 수 있습니다. 1135 01:13:35,400 --> 01:13:37,326 레거시 코드를 안전하게 리팩토링 할 수 있습니다. 1136 01:13:39,116 --> 01:13:41,296 처음 TripService 코드가 1137 01:13:46,726 --> 01:13:50,083 여기에 있을 텐데요. 1138 01:13:50,116 --> 01:13:53,739 처음에는 이런 코드로 시작했던 겁니다. 1139 01:13:53,739 --> 01:14:03,367 처음에는 이런 코드로 시작했던 겁니다. 1140 01:14:03,367 --> 01:14:05,911 지금은 1141 01:14:06,009 --> 01:14:09,426 스크린 캐스트를 녹화하고 있으니 1142 01:14:09,426 --> 01:14:12,505 한 시간 정도 걸렸는데요 1143 01:14:12,505 --> 01:14:15,860 여기에 사용된 기법들이 익숙한 경우에는요 1144 01:14:15,860 --> 01:14:19,766 저 같은 경우에는 평소에는 20분 정도 걸립니다. 1145 01:14:19,766 --> 01:14:21,925 1146 01:14:21,925 --> 01:14:24,337 뭔가 새로운 기술을 알게 되면 1147 01:14:24,367 --> 01:14:25,976 연습을 하세요 1148 01:14:25,976 --> 01:14:29,387 능숙하게 사용할 때 까지요 1149 01:14:29,387 --> 01:14:32,153 다시 한 번 말씀 드리면 1150 01:14:32,153 --> 01:14:35,241 레거시 코드에 작업을 할 때에는 1151 01:14:35,241 --> 01:14:40,080 깊은 부분부터 작업을 하면 안됩니다. 1152 01:14:40,080 --> 01:14:42,249 항상 얕은 부분부터 시작을 하세요. 1153 01:14:42,249 --> 01:14:44,183 얕은 부분에서 시작해서 깊은 부분으로요. 1154 01:14:44,183 --> 01:14:47,002 얕은 부분에서 테스트를 작성하기 시작해야 합니다 1155 01:14:47,002 --> 01:14:51,176 그러면 작성하는 테스트로 제품 코드를 이해해갈 수 있고 1156 01:14:51,176 --> 01:14:55,301 테스트 데이터를 만들어 가면서 1157 01:14:55,301 --> 01:14:58,381 점점 더 깊은 부분을 테스트할 수 있게 됩니다. 1158 01:14:58,381 --> 01:14:59,975 반대로 1159 01:14:59,975 --> 01:15:01,159 리팩토링을 할 때에는 1160 01:15:01,159 --> 01:15:02,909 가장 깊은 부분부터 시작합니다. 1161 01:15:02,909 --> 01:15:05,179 깊은 부분부터 메소드를 추출하고 1162 01:15:05,179 --> 01:15:08,423 행위를 다른 클래스로 옮기다 보면 1163 01:15:08,423 --> 01:15:11,398 어느 순간부터 코드가 1164 01:15:11,398 --> 01:15:14,426 줄어들기 시작할 겁니다. 1165 01:15:14,426 --> 01:15:16,958 1166 01:15:18,598 --> 01:15:23,509 읽기 좋고 관리하기 좋은 코드를 작성하세요. 1167 01:15:24,036 --> 01:15:25,850 도메인 언어가 코드에 사용되도록 하세요. 1168 01:15:25,850 --> 01:15:27,586 코드에 녹아들 게 하세요. 1169 01:15:27,586 --> 01:15:29,986 1170 01:15:29,986 --> 01:15:31,628 1171 01:15:31,628 --> 01:15:36,872 도메인 언어가 테스트와 제품 코드에 녹아들 게 하세요 1172 01:15:36,872 --> 01:15:42,650 BA와 이야기하는 용어가 테스트 코드 제품 코드에도 그대로 사용되게 하세요. 1173 01:15:43,180 --> 01:15:46,269 심플한 것을 추구하고 1174 01:15:46,269 --> 01:15:49,058 사용하는 프레임워크나 단축키 등도 알아두세요 1175 01:15:49,058 --> 01:15:51,219 신속하게 작업하도록 노력하고 1176 01:15:51,669 --> 01:15:55,732 개발 환경에도 공을 들여서 단축키 등으로 간단하게 1177 01:15:55,732 --> 01:15:57,959 메소드나 클래스를 만들거나 1178 01:15:57,959 --> 01:16:00,063 리팩토링을 할 수 있어야 합니다. 1179 01:16:00,063 --> 01:16:03,564 항상 조금씩 점진적으로 작업하고요 1180 01:16:03,564 --> 01:16:04,718 자주 커밋하세요. 1181 01:16:04,718 --> 01:16:07,210 Git같은 툴을 사용하면 1182 01:16:07,680 --> 01:16:10,405 실수를 하더라도 1183 01:16:10,405 --> 01:16:12,884 Ctrl+Z 나 git reset hard 등으로 1184 01:16:12,884 --> 01:16:14,827 이 전 커밋으로 돌아갈 수 있습니다. 1185 01:16:14,827 --> 01:16:16,957 문제가 없었던 상태로요. 1186 01:16:16,957 --> 01:16:18,685 용기를 가지세요. 1187 01:16:18,685 --> 01:16:22,015 오늘 여러 가지 기법들을 배웠는데요 1188 01:16:22,015 --> 01:16:26,903 오늘 여러 가지 기법들을 배웠는데요 1189 01:16:26,903 --> 01:16:31,416 이제 레거시 코드의 99%에 테스트 작성이 가능할 겁니다. 1190 01:16:31,416 --> 01:16:33,171 그러니 용기를 내서 1191 01:16:33,171 --> 01:16:35,503 오늘 배운 것들을 활용하세요. 1192 01:16:36,823 --> 01:16:39,755 머문 자리는 머물기 전보다 깨끗하게 하고 떠나세요. 1193 01:16:39,755 --> 01:16:41,367 보이 스카웃 규칙이지요. 1194 01:16:41,367 --> 01:16:42,708 깨진 창문 이론도 아시지요. 1195 01:16:42,708 --> 01:16:44,413 코드 냄새가 나면요. 1196 01:16:44,413 --> 01:16:47,959 코드가 그다지 잘 작성된 게 아니라면 1197 01:16:47,959 --> 01:16:49,088 바로 리팩토링 하세요. 1198 01:16:49,088 --> 01:16:50,773 바로 수정하세요. 1199 01:16:50,773 --> 01:16:53,135 유익한 시간이 됐으면 좋겠습니다. 1200 01:16:53,795 --> 01:16:55,701 이상입니다. 1201 01:16:55,701 --> 01:17:00,519 이 카타는 제 깃헙에 있습니다. 1202 01:17:00,519 --> 01:17:03,843 제 깃헙을 방문해보세요. 1203 01:17:03,843 --> 01:17:05,622 이상입니다. 유익한 시간이 되었으면 좋겠습니다. 1204 01:17:05,622 --> 01:17:07,482 감사합니다.