oh-my-oop 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (660) hide show
  1. package/MCP_STRUCTURE.md +301 -0
  2. package/README.md +167 -0
  3. package/SCOPE.md +27 -0
  4. package/dist/application/discovery.d.ts +133 -0
  5. package/dist/application/discovery.js +62 -0
  6. package/dist/application/discovery.js.map +1 -0
  7. package/dist/cli.d.ts +2 -0
  8. package/dist/cli.js +80 -0
  9. package/dist/cli.js.map +1 -0
  10. package/dist/config.d.ts +16 -0
  11. package/dist/config.js +32 -0
  12. package/dist/config.js.map +1 -0
  13. package/dist/domain/collaborators.d.ts +2 -0
  14. package/dist/domain/collaborators.js +26 -0
  15. package/dist/domain/collaborators.js.map +1 -0
  16. package/dist/domain/ids.d.ts +4 -0
  17. package/dist/domain/ids.js +23 -0
  18. package/dist/domain/ids.js.map +1 -0
  19. package/dist/domain/model.d.ts +71 -0
  20. package/dist/domain/model.js +2 -0
  21. package/dist/domain/model.js.map +1 -0
  22. package/dist/domain/schemas.d.ts +213 -0
  23. package/dist/domain/schemas.js +79 -0
  24. package/dist/domain/schemas.js.map +1 -0
  25. package/dist/domain/stereotypes.d.ts +7 -0
  26. package/dist/domain/stereotypes.js +65 -0
  27. package/dist/domain/stereotypes.js.map +1 -0
  28. package/dist/index.d.ts +2 -0
  29. package/dist/index.js +21 -0
  30. package/dist/index.js.map +1 -0
  31. package/dist/io/classStore.d.ts +9 -0
  32. package/dist/io/classStore.js +39 -0
  33. package/dist/io/classStore.js.map +1 -0
  34. package/dist/io/collaborationStore.d.ts +7 -0
  35. package/dist/io/collaborationStore.js +32 -0
  36. package/dist/io/collaborationStore.js.map +1 -0
  37. package/dist/io/design.d.ts +3 -0
  38. package/dist/io/design.js +22 -0
  39. package/dist/io/design.js.map +1 -0
  40. package/dist/io/designIndex.d.ts +6 -0
  41. package/dist/io/designIndex.js +49 -0
  42. package/dist/io/designIndex.js.map +1 -0
  43. package/dist/io/frontmatter.d.ts +8 -0
  44. package/dist/io/frontmatter.js +31 -0
  45. package/dist/io/frontmatter.js.map +1 -0
  46. package/dist/io/history.d.ts +10 -0
  47. package/dist/io/history.js +38 -0
  48. package/dist/io/history.js.map +1 -0
  49. package/dist/io/useCaseStore.d.ts +8 -0
  50. package/dist/io/useCaseStore.js +36 -0
  51. package/dist/io/useCaseStore.js.map +1 -0
  52. package/dist/io/workspace.d.ts +14 -0
  53. package/dist/io/workspace.js +82 -0
  54. package/dist/io/workspace.js.map +1 -0
  55. package/dist/oop/commands.d.ts +446 -0
  56. package/dist/oop/commands.js +319 -0
  57. package/dist/oop/commands.js.map +1 -0
  58. package/dist/oop/conformance.d.ts +16 -0
  59. package/dist/oop/conformance.js +30 -0
  60. package/dist/oop/conformance.js.map +1 -0
  61. package/dist/prompts/discovery.d.ts +2 -0
  62. package/dist/prompts/discovery.js +41 -0
  63. package/dist/prompts/discovery.js.map +1 -0
  64. package/dist/prompts/imagineWithoutController.d.ts +2 -0
  65. package/dist/prompts/imagineWithoutController.js +75 -0
  66. package/dist/prompts/imagineWithoutController.js.map +1 -0
  67. package/dist/prompts/index.d.ts +2 -0
  68. package/dist/prompts/index.js +17 -0
  69. package/dist/prompts/index.js.map +1 -0
  70. package/dist/prompts/phasePressureTest.d.ts +2 -0
  71. package/dist/prompts/phasePressureTest.js +69 -0
  72. package/dist/prompts/phasePressureTest.js.map +1 -0
  73. package/dist/prompts/rddIntro.d.ts +2 -0
  74. package/dist/prompts/rddIntro.js +53 -0
  75. package/dist/prompts/rddIntro.js.map +1 -0
  76. package/dist/prompts/review.d.ts +2 -0
  77. package/dist/prompts/review.js +45 -0
  78. package/dist/prompts/review.js.map +1 -0
  79. package/dist/prompts/stateMachineIntrospect.d.ts +2 -0
  80. package/dist/prompts/stateMachineIntrospect.js +80 -0
  81. package/dist/prompts/stateMachineIntrospect.js.map +1 -0
  82. package/dist/prompts/tellDontAskRephrase.d.ts +2 -0
  83. package/dist/prompts/tellDontAskRephrase.js +66 -0
  84. package/dist/prompts/tellDontAskRephrase.js.map +1 -0
  85. package/dist/render/diff.d.ts +21 -0
  86. package/dist/render/diff.js +84 -0
  87. package/dist/render/diff.js.map +1 -0
  88. package/dist/render/mermaid.d.ts +24 -0
  89. package/dist/render/mermaid.js +53 -0
  90. package/dist/render/mermaid.js.map +1 -0
  91. package/dist/render/sideBySide.d.ts +14 -0
  92. package/dist/render/sideBySide.js +91 -0
  93. package/dist/render/sideBySide.js.map +1 -0
  94. package/dist/resources/index.d.ts +2 -0
  95. package/dist/resources/index.js +349 -0
  96. package/dist/resources/index.js.map +1 -0
  97. package/dist/server.d.ts +2 -0
  98. package/dist/server.js +22 -0
  99. package/dist/server.js.map +1 -0
  100. package/dist/tools/alternatives.d.ts +2 -0
  101. package/dist/tools/alternatives.js +9 -0
  102. package/dist/tools/alternatives.js.map +1 -0
  103. package/dist/tools/classes.d.ts +2 -0
  104. package/dist/tools/classes.js +13 -0
  105. package/dist/tools/classes.js.map +1 -0
  106. package/dist/tools/collaborations.d.ts +2 -0
  107. package/dist/tools/collaborations.js +8 -0
  108. package/dist/tools/collaborations.js.map +1 -0
  109. package/dist/tools/compare.d.ts +2 -0
  110. package/dist/tools/compare.js +9 -0
  111. package/dist/tools/compare.js.map +1 -0
  112. package/dist/tools/conformance.d.ts +3 -0
  113. package/dist/tools/conformance.js +11 -0
  114. package/dist/tools/conformance.js.map +1 -0
  115. package/dist/tools/diagram.d.ts +2 -0
  116. package/dist/tools/diagram.js +9 -0
  117. package/dist/tools/diagram.js.map +1 -0
  118. package/dist/tools/discovery.d.ts +2 -0
  119. package/dist/tools/discovery.js +23 -0
  120. package/dist/tools/discovery.js.map +1 -0
  121. package/dist/tools/index.d.ts +2 -0
  122. package/dist/tools/index.js +27 -0
  123. package/dist/tools/index.js.map +1 -0
  124. package/dist/tools/init.d.ts +2 -0
  125. package/dist/tools/init.js +9 -0
  126. package/dist/tools/init.js.map +1 -0
  127. package/dist/tools/oop.d.ts +9 -0
  128. package/dist/tools/oop.js +26 -0
  129. package/dist/tools/oop.js.map +1 -0
  130. package/dist/tools/responsibilities.d.ts +2 -0
  131. package/dist/tools/responsibilities.js +13 -0
  132. package/dist/tools/responsibilities.js.map +1 -0
  133. package/dist/tools/state.d.ts +2 -0
  134. package/dist/tools/state.js +8 -0
  135. package/dist/tools/state.js.map +1 -0
  136. package/dist/tools/useCases.d.ts +2 -0
  137. package/dist/tools/useCases.js +18 -0
  138. package/dist/tools/useCases.js.map +1 -0
  139. package/dist/tools/validate.d.ts +2 -0
  140. package/dist/tools/validate.js +9 -0
  141. package/dist/tools/validate.js.map +1 -0
  142. package/dist/tradeoff/engine.d.ts +61 -0
  143. package/dist/tradeoff/engine.js +171 -0
  144. package/dist/tradeoff/engine.js.map +1 -0
  145. package/dist/tradeoff/heuristics/classSplit.d.ts +3 -0
  146. package/dist/tradeoff/heuristics/classSplit.js +94 -0
  147. package/dist/tradeoff/heuristics/classSplit.js.map +1 -0
  148. package/dist/tradeoff/heuristics/collaborationShape.d.ts +2 -0
  149. package/dist/tradeoff/heuristics/collaborationShape.js +82 -0
  150. package/dist/tradeoff/heuristics/collaborationShape.js.map +1 -0
  151. package/dist/tradeoff/heuristics/collectionShape.d.ts +2 -0
  152. package/dist/tradeoff/heuristics/collectionShape.js +113 -0
  153. package/dist/tradeoff/heuristics/collectionShape.js.map +1 -0
  154. package/dist/tradeoff/heuristics/dualSubjectComparison.d.ts +2 -0
  155. package/dist/tradeoff/heuristics/dualSubjectComparison.js +114 -0
  156. package/dist/tradeoff/heuristics/dualSubjectComparison.js.map +1 -0
  157. package/dist/tradeoff/heuristics/errorHandling.d.ts +2 -0
  158. package/dist/tradeoff/heuristics/errorHandling.js +110 -0
  159. package/dist/tradeoff/heuristics/errorHandling.js.map +1 -0
  160. package/dist/tradeoff/heuristics/responsibilitySplit.d.ts +23 -0
  161. package/dist/tradeoff/heuristics/responsibilitySplit.js +183 -0
  162. package/dist/tradeoff/heuristics/responsibilitySplit.js.map +1 -0
  163. package/dist/tradeoff/heuristics/stereotypeChoice.d.ts +2 -0
  164. package/dist/tradeoff/heuristics/stereotypeChoice.js +23 -0
  165. package/dist/tradeoff/heuristics/stereotypeChoice.js.map +1 -0
  166. package/dist/tradeoff/heuristics/strategyOrPolicy.d.ts +2 -0
  167. package/dist/tradeoff/heuristics/strategyOrPolicy.js +110 -0
  168. package/dist/tradeoff/heuristics/strategyOrPolicy.js.map +1 -0
  169. package/dist/tradeoff/heuristics/valueObjectShape.d.ts +2 -0
  170. package/dist/tradeoff/heuristics/valueObjectShape.js +111 -0
  171. package/dist/tradeoff/heuristics/valueObjectShape.js.map +1 -0
  172. package/dist/tradeoff/templates.d.ts +2 -0
  173. package/dist/tradeoff/templates.js +33 -0
  174. package/dist/tradeoff/templates.js.map +1 -0
  175. package/dist/util/log.d.ts +1 -0
  176. package/dist/util/log.js +7 -0
  177. package/dist/util/log.js.map +1 -0
  178. package/dist/util/mcp.d.ts +4 -0
  179. package/dist/util/mcp.js +18 -0
  180. package/dist/util/mcp.js.map +1 -0
  181. package/dist/validate/cohesion.d.ts +3 -0
  182. package/dist/validate/cohesion.js +88 -0
  183. package/dist/validate/cohesion.js.map +1 -0
  184. package/dist/validate/collectionWrapper.d.ts +3 -0
  185. package/dist/validate/collectionWrapper.js +131 -0
  186. package/dist/validate/collectionWrapper.js.map +1 -0
  187. package/dist/validate/coupling.d.ts +3 -0
  188. package/dist/validate/coupling.js +47 -0
  189. package/dist/validate/coupling.js.map +1 -0
  190. package/dist/validate/cycle.d.ts +3 -0
  191. package/dist/validate/cycle.js +101 -0
  192. package/dist/validate/cycle.js.map +1 -0
  193. package/dist/validate/dataDuplication.d.ts +3 -0
  194. package/dist/validate/dataDuplication.js +150 -0
  195. package/dist/validate/dataDuplication.js.map +1 -0
  196. package/dist/validate/dependencyDirection.d.ts +3 -0
  197. package/dist/validate/dependencyDirection.js +106 -0
  198. package/dist/validate/dependencyDirection.js.map +1 -0
  199. package/dist/validate/dualUseKnowing.d.ts +3 -0
  200. package/dist/validate/dualUseKnowing.js +137 -0
  201. package/dist/validate/dualUseKnowing.js.map +1 -0
  202. package/dist/validate/emptyObjectFill.d.ts +3 -0
  203. package/dist/validate/emptyObjectFill.js +119 -0
  204. package/dist/validate/emptyObjectFill.js.map +1 -0
  205. package/dist/validate/findings.d.ts +22 -0
  206. package/dist/validate/findings.js +12 -0
  207. package/dist/validate/findings.js.map +1 -0
  208. package/dist/validate/functionDecompositionExcess.d.ts +3 -0
  209. package/dist/validate/functionDecompositionExcess.js +120 -0
  210. package/dist/validate/functionDecompositionExcess.js.map +1 -0
  211. package/dist/validate/functionNotObject.d.ts +3 -0
  212. package/dist/validate/functionNotObject.js +80 -0
  213. package/dist/validate/functionNotObject.js.map +1 -0
  214. package/dist/validate/godObject.d.ts +6 -0
  215. package/dist/validate/godObject.js +76 -0
  216. package/dist/validate/godObject.js.map +1 -0
  217. package/dist/validate/presentationInDomain.d.ts +3 -0
  218. package/dist/validate/presentationInDomain.js +57 -0
  219. package/dist/validate/presentationInDomain.js.map +1 -0
  220. package/dist/validate/primitiveWrapper.d.ts +3 -0
  221. package/dist/validate/primitiveWrapper.js +106 -0
  222. package/dist/validate/primitiveWrapper.js.map +1 -0
  223. package/dist/validate/rules.d.ts +24 -0
  224. package/dist/validate/rules.js +269 -0
  225. package/dist/validate/rules.js.map +1 -0
  226. package/dist/validate/singletonStatefulHolder.d.ts +3 -0
  227. package/dist/validate/singletonStatefulHolder.js +128 -0
  228. package/dist/validate/singletonStatefulHolder.js.map +1 -0
  229. package/dist/validate/strategyAsymmetry.d.ts +3 -0
  230. package/dist/validate/strategyAsymmetry.js +131 -0
  231. package/dist/validate/strategyAsymmetry.js.map +1 -0
  232. package/dist/validate/testability.d.ts +5 -0
  233. package/dist/validate/testability.js +157 -0
  234. package/dist/validate/testability.js.map +1 -0
  235. package/dist/validate/vagueName.d.ts +3 -0
  236. package/dist/validate/vagueName.js +136 -0
  237. package/dist/validate/vagueName.js.map +1 -0
  238. package/dist/validate/validationLocation.d.ts +3 -0
  239. package/dist/validate/validationLocation.js +120 -0
  240. package/dist/validate/validationLocation.js.map +1 -0
  241. package/lessons/STYLE_GUIDE.md +304 -0
  242. package/lessons/woowacourse-kotlin-blackjack/2chang5/33-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +293 -0
  243. package/lessons/woowacourse-kotlin-blackjack/Choisehyeon/52-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +106 -0
  244. package/lessons/woowacourse-kotlin-blackjack/Choisehyeon/9-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +282 -0
  245. package/lessons/woowacourse-kotlin-blackjack/DYGames/14-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +182 -0
  246. package/lessons/woowacourse-kotlin-blackjack/DYGames/37-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +122 -0
  247. package/lessons/woowacourse-kotlin-blackjack/EmilyCh0/12-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +117 -0
  248. package/lessons/woowacourse-kotlin-blackjack/EmilyCh0/38-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +291 -0
  249. package/lessons/woowacourse-kotlin-blackjack/HANDOVER.md +1475 -0
  250. package/lessons/woowacourse-kotlin-blackjack/HamBeomJoon/119-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +251 -0
  251. package/lessons/woowacourse-kotlin-blackjack/HamBeomJoon/137-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +459 -0
  252. package/lessons/woowacourse-kotlin-blackjack/Hevton/100-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +282 -0
  253. package/lessons/woowacourse-kotlin-blackjack/Hevton/82-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +303 -0
  254. package/lessons/woowacourse-kotlin-blackjack/Hogu59/71-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +134 -0
  255. package/lessons/woowacourse-kotlin-blackjack/Hogu59/96-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +323 -0
  256. package/lessons/woowacourse-kotlin-blackjack/JoYehyun99/66-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +210 -0
  257. package/lessons/woowacourse-kotlin-blackjack/Junyoung-WON/101-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +191 -0
  258. package/lessons/woowacourse-kotlin-blackjack/Junyoung-WON/80-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +253 -0
  259. package/lessons/woowacourse-kotlin-blackjack/Leeyerin0210/108-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +516 -0
  260. package/lessons/woowacourse-kotlin-blackjack/Leeyerin0210/133-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +541 -0
  261. package/lessons/woowacourse-kotlin-blackjack/RightHennessy/22-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +278 -0
  262. package/lessons/woowacourse-kotlin-blackjack/RightHennessy/48-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +188 -0
  263. package/lessons/woowacourse-kotlin-blackjack/SeongHoonC/16-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +228 -0
  264. package/lessons/woowacourse-kotlin-blackjack/SeongHoonC/54-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +227 -0
  265. package/lessons/woowacourse-kotlin-blackjack/Yunseok-Nam/76-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +279 -0
  266. package/lessons/woowacourse-kotlin-blackjack/Yunseok-Nam/86-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +203 -0
  267. package/lessons/woowacourse-kotlin-blackjack/aprilgom/105-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +162 -0
  268. package/lessons/woowacourse-kotlin-blackjack/aprilgom/64-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +279 -0
  269. package/lessons/woowacourse-kotlin-blackjack/boogi-woogi/18-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +188 -0
  270. package/lessons/woowacourse-kotlin-blackjack/boogi-woogi/36-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +769 -0
  271. package/lessons/woowacourse-kotlin-blackjack/briandr97/19-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +226 -0
  272. package/lessons/woowacourse-kotlin-blackjack/briandr97/59-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +193 -0
  273. package/lessons/woowacourse-kotlin-blackjack/chaehyuns/70-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +175 -0
  274. package/lessons/woowacourse-kotlin-blackjack/chaehyuns/98-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +206 -0
  275. package/lessons/woowacourse-kotlin-blackjack/chanho0908/123-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +277 -0
  276. package/lessons/woowacourse-kotlin-blackjack/chanho0908/150-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +219 -0
  277. package/lessons/woowacourse-kotlin-blackjack/chws0508/26-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +259 -0
  278. package/lessons/woowacourse-kotlin-blackjack/chws0508/43-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +189 -0
  279. package/lessons/woowacourse-kotlin-blackjack/cucumber99/109-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +351 -0
  280. package/lessons/woowacourse-kotlin-blackjack/cucumber99/149-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +147 -0
  281. package/lessons/woowacourse-kotlin-blackjack/devfeijoa/121-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +168 -0
  282. package/lessons/woowacourse-kotlin-blackjack/devfeijoa/153-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +116 -0
  283. package/lessons/woowacourse-kotlin-blackjack/doabletuple/126-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +680 -0
  284. package/lessons/woowacourse-kotlin-blackjack/doabletuple/142-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +739 -0
  285. package/lessons/woowacourse-kotlin-blackjack/donghyun81/116-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +297 -0
  286. package/lessons/woowacourse-kotlin-blackjack/donghyun81/147-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +244 -0
  287. package/lessons/woowacourse-kotlin-blackjack/dpcks0509/78-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +232 -0
  288. package/lessons/woowacourse-kotlin-blackjack/dpcks0509/88-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +137 -0
  289. package/lessons/woowacourse-kotlin-blackjack/etama123/112-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +269 -0
  290. package/lessons/woowacourse-kotlin-blackjack/etama123/148-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +240 -0
  291. package/lessons/woowacourse-kotlin-blackjack/gaeun5744/102-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +146 -0
  292. package/lessons/woowacourse-kotlin-blackjack/gaeun5744/69-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +224 -0
  293. package/lessons/woowacourse-kotlin-blackjack/gahyunkim/118-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +397 -0
  294. package/lessons/woowacourse-kotlin-blackjack/gahyunkim/141-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +215 -0
  295. package/lessons/woowacourse-kotlin-blackjack/giovannijunseokim/106-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +395 -0
  296. package/lessons/woowacourse-kotlin-blackjack/giovannijunseokim/134-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +219 -0
  297. package/lessons/woowacourse-kotlin-blackjack/haeum808/62-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +230 -0
  298. package/lessons/woowacourse-kotlin-blackjack/haeum808/89-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +169 -0
  299. package/lessons/woowacourse-kotlin-blackjack/hwannow/110-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +221 -0
  300. package/lessons/woowacourse-kotlin-blackjack/hwannow/132-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +573 -0
  301. package/lessons/woowacourse-kotlin-blackjack/hxeyexn/103-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +188 -0
  302. package/lessons/woowacourse-kotlin-blackjack/hxeyexn/81-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +301 -0
  303. package/lessons/woowacourse-kotlin-blackjack/hyemdooly/21-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +613 -0
  304. package/lessons/woowacourse-kotlin-blackjack/hyemdooly/35-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +691 -0
  305. package/lessons/woowacourse-kotlin-blackjack/hyunji1203/13-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +206 -0
  306. package/lessons/woowacourse-kotlin-blackjack/ii2001/79-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +153 -0
  307. package/lessons/woowacourse-kotlin-blackjack/ii2001/85-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +318 -0
  308. package/lessons/woowacourse-kotlin-blackjack/ijh1298/128-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +250 -0
  309. package/lessons/woowacourse-kotlin-blackjack/ijh1298/135-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +269 -0
  310. package/lessons/woowacourse-kotlin-blackjack/inseonyun/28-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +346 -0
  311. package/lessons/woowacourse-kotlin-blackjack/inseonyun/49-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +360 -0
  312. package/lessons/woowacourse-kotlin-blackjack/ippnsj/30-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +152 -0
  313. package/lessons/woowacourse-kotlin-blackjack/ippnsj/42-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +213 -0
  314. package/lessons/woowacourse-kotlin-blackjack/jaeyeongjo/73-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +247 -0
  315. package/lessons/woowacourse-kotlin-blackjack/jaeyeongjo/87-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +900 -0
  316. package/lessons/woowacourse-kotlin-blackjack/jerry8282/125-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +248 -0
  317. package/lessons/woowacourse-kotlin-blackjack/jerry8282/151-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +243 -0
  318. package/lessons/woowacourse-kotlin-blackjack/jinuemong/63-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +281 -0
  319. package/lessons/woowacourse-kotlin-blackjack/jinuemong/92-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +283 -0
  320. package/lessons/woowacourse-kotlin-blackjack/jiyuneel/113-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +348 -0
  321. package/lessons/woowacourse-kotlin-blackjack/jiyuneel/140-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +265 -0
  322. package/lessons/woowacourse-kotlin-blackjack/junjange/61-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +270 -0
  323. package/lessons/woowacourse-kotlin-blackjack/junjange/93-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +465 -0
  324. package/lessons/woowacourse-kotlin-blackjack/junseo511/107-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +296 -0
  325. package/lessons/woowacourse-kotlin-blackjack/junseo511/145-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +316 -0
  326. package/lessons/woowacourse-kotlin-blackjack/ki960213/11-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +175 -0
  327. package/lessons/woowacourse-kotlin-blackjack/kimhm0728/72-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +458 -0
  328. package/lessons/woowacourse-kotlin-blackjack/kimhm0728/97-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +225 -0
  329. package/lessons/woowacourse-kotlin-blackjack/kkosang/68-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +221 -0
  330. package/lessons/woowacourse-kotlin-blackjack/kkosang/94-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +158 -0
  331. package/lessons/woowacourse-kotlin-blackjack/kmkim2689/65-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +252 -0
  332. package/lessons/woowacourse-kotlin-blackjack/kmkim2689/90-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +460 -0
  333. package/lessons/woowacourse-kotlin-blackjack/krrong/32-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +216 -0
  334. package/lessons/woowacourse-kotlin-blackjack/krrong/46-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +285 -0
  335. package/lessons/woowacourse-kotlin-blackjack/m6z1/122-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +177 -0
  336. package/lessons/woowacourse-kotlin-blackjack/m6z1/144-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +155 -0
  337. package/lessons/woowacourse-kotlin-blackjack/medAndro/130-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +683 -0
  338. package/lessons/woowacourse-kotlin-blackjack/medAndro/143-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +678 -0
  339. package/lessons/woowacourse-kotlin-blackjack/moondev03/114-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +262 -0
  340. package/lessons/woowacourse-kotlin-blackjack/moondev03/131-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +498 -0
  341. package/lessons/woowacourse-kotlin-blackjack/murjune/77-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +287 -0
  342. package/lessons/woowacourse-kotlin-blackjack/murjune/91-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +280 -0
  343. package/lessons/woowacourse-kotlin-blackjack/no1msh/31-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +250 -0
  344. package/lessons/woowacourse-kotlin-blackjack/otter66/24-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +302 -0
  345. package/lessons/woowacourse-kotlin-blackjack/otter66/58-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +391 -0
  346. package/lessons/woowacourse-kotlin-blackjack/oungsi2000/111-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +253 -0
  347. package/lessons/woowacourse-kotlin-blackjack/oungsi2000/136-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +540 -0
  348. package/lessons/woowacourse-kotlin-blackjack/parkjiminnnn/117-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +819 -0
  349. package/lessons/woowacourse-kotlin-blackjack/parkjiminnnn/139-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +683 -0
  350. package/lessons/woowacourse-kotlin-blackjack/pingu244/20-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +258 -0
  351. package/lessons/woowacourse-kotlin-blackjack/pingu244/41-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +171 -0
  352. package/lessons/woowacourse-kotlin-blackjack/re4rk/34-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +289 -0
  353. package/lessons/woowacourse-kotlin-blackjack/re4rk/8-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +297 -0
  354. package/lessons/woowacourse-kotlin-blackjack/rhkrwngud445/17-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +279 -0
  355. package/lessons/woowacourse-kotlin-blackjack/rhkrwngud445/50-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +145 -0
  356. package/lessons/woowacourse-kotlin-blackjack/rhthrhrl0/23-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +253 -0
  357. package/lessons/woowacourse-kotlin-blackjack/rhthrhrl0/39-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +238 -0
  358. package/lessons/woowacourse-kotlin-blackjack/rosemin928/129-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +726 -0
  359. package/lessons/woowacourse-kotlin-blackjack/rosemin928/138-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +845 -0
  360. package/lessons/woowacourse-kotlin-blackjack/s6m1n/67-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +220 -0
  361. package/lessons/woowacourse-kotlin-blackjack/s6m1n/99-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +229 -0
  362. package/lessons/woowacourse-kotlin-blackjack/s9hn/10-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +284 -0
  363. package/lessons/woowacourse-kotlin-blackjack/sh1mj1/75-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +224 -0
  364. package/lessons/woowacourse-kotlin-blackjack/songpink/74-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +238 -0
  365. package/lessons/woowacourse-kotlin-blackjack/songpink/95-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +216 -0
  366. package/lessons/woowacourse-kotlin-blackjack/sujin9/15-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +132 -0
  367. package/lessons/woowacourse-kotlin-blackjack/sujin9/47-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +265 -0
  368. package/lessons/woowacourse-kotlin-blackjack/tmdgh1592/29-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +305 -0
  369. package/lessons/woowacourse-kotlin-blackjack/tmdgh1592/51-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +278 -0
  370. package/lessons/woowacourse-kotlin-blackjack/tobae-time/115-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +305 -0
  371. package/lessons/woowacourse-kotlin-blackjack/tobae-time/154-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +298 -0
  372. package/lessons/woowacourse-kotlin-blackjack/whk06061/25-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +235 -0
  373. package/lessons/woowacourse-kotlin-blackjack/whk06061/53-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +130 -0
  374. package/lessons/woowacourse-kotlin-blackjack/wondroid-world/124-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +486 -0
  375. package/lessons/woowacourse-kotlin-blackjack/wondroid-world/152-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +482 -0
  376. package/lessons/woowacourse-kotlin-blackjack/yrsel/120-1/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +194 -0
  377. package/lessons/woowacourse-kotlin-blackjack/yrsel/146-2/353/213/250/352/263/204-/353/270/224/353/236/231/354/236/255.md +444 -0
  378. package/lessons/woowacourse-kotlin-lotto/2chang5/27-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +155 -0
  379. package/lessons/woowacourse-kotlin-lotto/2chang5/52-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +187 -0
  380. package/lessons/woowacourse-kotlin-lotto/Choisehyeon/14-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +206 -0
  381. package/lessons/woowacourse-kotlin-lotto/Choisehyeon/47-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +119 -0
  382. package/lessons/woowacourse-kotlin-lotto/DYGames/2-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +83 -0
  383. package/lessons/woowacourse-kotlin-lotto/DYGames/34-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +88 -0
  384. package/lessons/woowacourse-kotlin-lotto/EmilyCh0/12-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +107 -0
  385. package/lessons/woowacourse-kotlin-lotto/EmilyCh0/40-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +135 -0
  386. package/lessons/woowacourse-kotlin-lotto/HANDOVER.md +217 -0
  387. package/lessons/woowacourse-kotlin-lotto/HamBeomJoon/121-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +66 -0
  388. package/lessons/woowacourse-kotlin-lotto/HamBeomJoon/139-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +75 -0
  389. package/lessons/woowacourse-kotlin-lotto/Hevton/76-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +21 -0
  390. package/lessons/woowacourse-kotlin-lotto/Hevton/92-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +122 -0
  391. package/lessons/woowacourse-kotlin-lotto/Hogu59/100-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +110 -0
  392. package/lessons/woowacourse-kotlin-lotto/Hogu59/68-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +84 -0
  393. package/lessons/woowacourse-kotlin-lotto/JoYehyun99/60-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +176 -0
  394. package/lessons/woowacourse-kotlin-lotto/JoYehyun99/96-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +71 -0
  395. package/lessons/woowacourse-kotlin-lotto/Junyoung-WON/61-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +143 -0
  396. package/lessons/woowacourse-kotlin-lotto/Junyoung-WON/93-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +16 -0
  397. package/lessons/woowacourse-kotlin-lotto/Leeyerin0210/109-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +57 -0
  398. package/lessons/woowacourse-kotlin-lotto/Leeyerin0210/135-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +115 -0
  399. package/lessons/woowacourse-kotlin-lotto/PROGRESS.md +160 -0
  400. package/lessons/woowacourse-kotlin-lotto/README.md +77 -0
  401. package/lessons/woowacourse-kotlin-lotto/RightHennessy/32-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +178 -0
  402. package/lessons/woowacourse-kotlin-lotto/RightHennessy/5-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +149 -0
  403. package/lessons/woowacourse-kotlin-lotto/SUMMARY.md +369 -0
  404. package/lessons/woowacourse-kotlin-lotto/SeongHoonC/25-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +129 -0
  405. package/lessons/woowacourse-kotlin-lotto/SeongHoonC/37-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +27 -0
  406. package/lessons/woowacourse-kotlin-lotto/Yunseok-Nam/72-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +137 -0
  407. package/lessons/woowacourse-kotlin-lotto/Yunseok-Nam/86-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +17 -0
  408. package/lessons/woowacourse-kotlin-lotto/aprilgom/102-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +62 -0
  409. package/lessons/woowacourse-kotlin-lotto/aprilgom/64-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +146 -0
  410. package/lessons/woowacourse-kotlin-lotto/boogi-woogi/11-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +26 -0
  411. package/lessons/woowacourse-kotlin-lotto/boogi-woogi/29-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +26 -0
  412. package/lessons/woowacourse-kotlin-lotto/briandr97/26-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +52 -0
  413. package/lessons/woowacourse-kotlin-lotto/briandr97/51-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +123 -0
  414. package/lessons/woowacourse-kotlin-lotto/chaehyuns/71-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +115 -0
  415. package/lessons/woowacourse-kotlin-lotto/chaehyuns/97-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +107 -0
  416. package/lessons/woowacourse-kotlin-lotto/chanho0908/124-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +51 -0
  417. package/lessons/woowacourse-kotlin-lotto/chanho0908/129-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +149 -0
  418. package/lessons/woowacourse-kotlin-lotto/chws0508/24-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +117 -0
  419. package/lessons/woowacourse-kotlin-lotto/chws0508/50-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +167 -0
  420. package/lessons/woowacourse-kotlin-lotto/cucumber99/116-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +155 -0
  421. package/lessons/woowacourse-kotlin-lotto/cucumber99/147-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +223 -0
  422. package/lessons/woowacourse-kotlin-lotto/devfeijoa/125-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +68 -0
  423. package/lessons/woowacourse-kotlin-lotto/devfeijoa/153-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +107 -0
  424. package/lessons/woowacourse-kotlin-lotto/doabletuple/119-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +157 -0
  425. package/lessons/woowacourse-kotlin-lotto/doabletuple/138-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +77 -0
  426. package/lessons/woowacourse-kotlin-lotto/donghyun81/111-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +67 -0
  427. package/lessons/woowacourse-kotlin-lotto/donghyun81/152-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +124 -0
  428. package/lessons/woowacourse-kotlin-lotto/dpcks0509/80-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +141 -0
  429. package/lessons/woowacourse-kotlin-lotto/dpcks0509/87-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +134 -0
  430. package/lessons/woowacourse-kotlin-lotto/etama123/112-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +170 -0
  431. package/lessons/woowacourse-kotlin-lotto/etama123/148-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +183 -0
  432. package/lessons/woowacourse-kotlin-lotto/gaeun5744/101-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +21 -0
  433. package/lessons/woowacourse-kotlin-lotto/gaeun5744/78-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +158 -0
  434. package/lessons/woowacourse-kotlin-lotto/gahyunkim/107-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +83 -0
  435. package/lessons/woowacourse-kotlin-lotto/gahyunkim/136-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +51 -0
  436. package/lessons/woowacourse-kotlin-lotto/giovannijunseokim/106-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +171 -0
  437. package/lessons/woowacourse-kotlin-lotto/giovannijunseokim/137-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +111 -0
  438. package/lessons/woowacourse-kotlin-lotto/haeum808/67-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +52 -0
  439. package/lessons/woowacourse-kotlin-lotto/haeum808/95-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +97 -0
  440. package/lessons/woowacourse-kotlin-lotto/hwannow/113-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +235 -0
  441. package/lessons/woowacourse-kotlin-lotto/hwannow/132-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +149 -0
  442. package/lessons/woowacourse-kotlin-lotto/hxeyexn/77-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +141 -0
  443. package/lessons/woowacourse-kotlin-lotto/hxeyexn/98-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +162 -0
  444. package/lessons/woowacourse-kotlin-lotto/hyemdooly/17-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +19 -0
  445. package/lessons/woowacourse-kotlin-lotto/hyemdooly/28-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +23 -0
  446. package/lessons/woowacourse-kotlin-lotto/hyunji1203/15-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +171 -0
  447. package/lessons/woowacourse-kotlin-lotto/hyunji1203/48-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +150 -0
  448. package/lessons/woowacourse-kotlin-lotto/ii2001/62-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +104 -0
  449. package/lessons/woowacourse-kotlin-lotto/ii2001/88-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +20 -0
  450. package/lessons/woowacourse-kotlin-lotto/ijh1298/122-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +179 -0
  451. package/lessons/woowacourse-kotlin-lotto/ijh1298/133-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +153 -0
  452. package/lessons/woowacourse-kotlin-lotto/inseonyun/3-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +222 -0
  453. package/lessons/woowacourse-kotlin-lotto/inseonyun/49-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +166 -0
  454. package/lessons/woowacourse-kotlin-lotto/ippnsj/16-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +154 -0
  455. package/lessons/woowacourse-kotlin-lotto/ippnsj/55-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +145 -0
  456. package/lessons/woowacourse-kotlin-lotto/jaeyeongjo/59-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +68 -0
  457. package/lessons/woowacourse-kotlin-lotto/jaeyeongjo/83-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +53 -0
  458. package/lessons/woowacourse-kotlin-lotto/jerry8282/115-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +97 -0
  459. package/lessons/woowacourse-kotlin-lotto/jerry8282/134-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +145 -0
  460. package/lessons/woowacourse-kotlin-lotto/jinuemong/63-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +144 -0
  461. package/lessons/woowacourse-kotlin-lotto/jinuemong/89-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +148 -0
  462. package/lessons/woowacourse-kotlin-lotto/jiyuneel/128-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +52 -0
  463. package/lessons/woowacourse-kotlin-lotto/jiyuneel/144-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +149 -0
  464. package/lessons/woowacourse-kotlin-lotto/junjange/58-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +148 -0
  465. package/lessons/woowacourse-kotlin-lotto/junjange/81-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +178 -0
  466. package/lessons/woowacourse-kotlin-lotto/junseo511/120-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +153 -0
  467. package/lessons/woowacourse-kotlin-lotto/junseo511/131-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +188 -0
  468. package/lessons/woowacourse-kotlin-lotto/ki960213/43-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +24 -0
  469. package/lessons/woowacourse-kotlin-lotto/ki960213/8-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +159 -0
  470. package/lessons/woowacourse-kotlin-lotto/kimhm0728/74-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +50 -0
  471. package/lessons/woowacourse-kotlin-lotto/kimhm0728/94-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +176 -0
  472. package/lessons/woowacourse-kotlin-lotto/kkosang/85-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +145 -0
  473. package/lessons/woowacourse-kotlin-lotto/kmkim2689/70-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +97 -0
  474. package/lessons/woowacourse-kotlin-lotto/kmkim2689/82-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +157 -0
  475. package/lessons/woowacourse-kotlin-lotto/krrong/19-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +161 -0
  476. package/lessons/woowacourse-kotlin-lotto/krrong/41-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +73 -0
  477. package/lessons/woowacourse-kotlin-lotto/m6z1/105-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +67 -0
  478. package/lessons/woowacourse-kotlin-lotto/m6z1/151-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +104 -0
  479. package/lessons/woowacourse-kotlin-lotto/medAndro/127-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +186 -0
  480. package/lessons/woowacourse-kotlin-lotto/medAndro/130-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +132 -0
  481. package/lessons/woowacourse-kotlin-lotto/moondev03/110-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +66 -0
  482. package/lessons/woowacourse-kotlin-lotto/moondev03/141-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +155 -0
  483. package/lessons/woowacourse-kotlin-lotto/murjune/69-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +143 -0
  484. package/lessons/woowacourse-kotlin-lotto/murjune/90-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +177 -0
  485. package/lessons/woowacourse-kotlin-lotto/no1msh/20-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +69 -0
  486. package/lessons/woowacourse-kotlin-lotto/no1msh/46-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +143 -0
  487. package/lessons/woowacourse-kotlin-lotto/otter66/13-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +178 -0
  488. package/lessons/woowacourse-kotlin-lotto/otter66/53-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +160 -0
  489. package/lessons/woowacourse-kotlin-lotto/oungsi2000/126-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +71 -0
  490. package/lessons/woowacourse-kotlin-lotto/oungsi2000/149-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +56 -0
  491. package/lessons/woowacourse-kotlin-lotto/parkjiminnnn/117-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +129 -0
  492. package/lessons/woowacourse-kotlin-lotto/parkjiminnnn/146-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +173 -0
  493. package/lessons/woowacourse-kotlin-lotto/pingu244/33-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +21 -0
  494. package/lessons/woowacourse-kotlin-lotto/pingu244/54-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +30 -0
  495. package/lessons/woowacourse-kotlin-lotto/pingu244/7-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +19 -0
  496. package/lessons/woowacourse-kotlin-lotto/re4rk/31-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +143 -0
  497. package/lessons/woowacourse-kotlin-lotto/re4rk/4-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +66 -0
  498. package/lessons/woowacourse-kotlin-lotto/rhkrwngud445/23-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +26 -0
  499. package/lessons/woowacourse-kotlin-lotto/rhkrwngud445/38-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +129 -0
  500. package/lessons/woowacourse-kotlin-lotto/rhthrhrl0/21-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +146 -0
  501. package/lessons/woowacourse-kotlin-lotto/rhthrhrl0/36-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +150 -0
  502. package/lessons/woowacourse-kotlin-lotto/rosemin928/123-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +179 -0
  503. package/lessons/woowacourse-kotlin-lotto/rosemin928/140-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +126 -0
  504. package/lessons/woowacourse-kotlin-lotto/s6m1n/103-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +119 -0
  505. package/lessons/woowacourse-kotlin-lotto/s6m1n/66-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +118 -0
  506. package/lessons/woowacourse-kotlin-lotto/s9hn/18-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +112 -0
  507. package/lessons/woowacourse-kotlin-lotto/sh1mj1/75-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +104 -0
  508. package/lessons/woowacourse-kotlin-lotto/sh1mj1/91-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +140 -0
  509. package/lessons/woowacourse-kotlin-lotto/songpink/65-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +96 -0
  510. package/lessons/woowacourse-kotlin-lotto/songpink/99-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +64 -0
  511. package/lessons/woowacourse-kotlin-lotto/sujin9/10-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +20 -0
  512. package/lessons/woowacourse-kotlin-lotto/sujin9/35-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +124 -0
  513. package/lessons/woowacourse-kotlin-lotto/tmdgh1592/22-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +30 -0
  514. package/lessons/woowacourse-kotlin-lotto/tmdgh1592/30-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +20 -0
  515. package/lessons/woowacourse-kotlin-lotto/tobae-time/114-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +158 -0
  516. package/lessons/woowacourse-kotlin-lotto/tobae-time/145-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +120 -0
  517. package/lessons/woowacourse-kotlin-lotto/whk06061/42-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +21 -0
  518. package/lessons/woowacourse-kotlin-lotto/whk06061/9-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +89 -0
  519. package/lessons/woowacourse-kotlin-lotto/wondroid-world/118-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +100 -0
  520. package/lessons/woowacourse-kotlin-lotto/wondroid-world/150-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +142 -0
  521. package/lessons/woowacourse-kotlin-lotto/yrsel/108-1/353/213/250/352/263/204-/353/241/234/353/230/220.md +124 -0
  522. package/lessons/woowacourse-kotlin-lotto/yrsel/143-2/353/213/250/352/263/204-/353/241/234/353/230/220.md +108 -0
  523. package/lessons/woowacourse-racingcar/2chang5/33-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +56 -0
  524. package/lessons/woowacourse-racingcar/2chang5/75-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +53 -0
  525. package/lessons/woowacourse-racingcar/CFalws/85-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +56 -0
  526. package/lessons/woowacourse-racingcar/Choisehyeon/46-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +61 -0
  527. package/lessons/woowacourse-racingcar/DYGames/49-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +62 -0
  528. package/lessons/woowacourse-racingcar/EmilyCh0/40-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +64 -0
  529. package/lessons/woowacourse-racingcar/EmilyCh0/57-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +55 -0
  530. package/lessons/woowacourse-racingcar/HamBeomJoon/137-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +55 -0
  531. package/lessons/woowacourse-racingcar/HamBeomJoon/170-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +50 -0
  532. package/lessons/woowacourse-racingcar/Hevton/106-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +54 -0
  533. package/lessons/woowacourse-racingcar/Hevton/118-/353/246/254/355/214/251/355/204/260/353/247/201.md +51 -0
  534. package/lessons/woowacourse-racingcar/Hogu59/108-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +56 -0
  535. package/lessons/woowacourse-racingcar/Hogu59/125-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +59 -0
  536. package/lessons/woowacourse-racingcar/JoYehyun99/111-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +57 -0
  537. package/lessons/woowacourse-racingcar/JoYehyun99/88-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +45 -0
  538. package/lessons/woowacourse-racingcar/Junyoung-WON/127-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +49 -0
  539. package/lessons/woowacourse-racingcar/Junyoung-WON/90-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +49 -0
  540. package/lessons/woowacourse-racingcar/Leeyerin0210/133-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +50 -0
  541. package/lessons/woowacourse-racingcar/Leeyerin0210/159-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +53 -0
  542. package/lessons/woowacourse-racingcar/PROGRESS.md +94 -0
  543. package/lessons/woowacourse-racingcar/README.md +69 -0
  544. package/lessons/woowacourse-racingcar/RightHennessy/51-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +55 -0
  545. package/lessons/woowacourse-racingcar/RightHennessy/58-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +57 -0
  546. package/lessons/woowacourse-racingcar/RunaNam/81-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +44 -0
  547. package/lessons/woowacourse-racingcar/SUMMARY.md +339 -0
  548. package/lessons/woowacourse-racingcar/SeongHoonC/37-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +57 -0
  549. package/lessons/woowacourse-racingcar/SeongHoonC/66-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +48 -0
  550. package/lessons/woowacourse-racingcar/Songusika/84-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +60 -0
  551. package/lessons/woowacourse-racingcar/Yunseok-Nam/114-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +43 -0
  552. package/lessons/woowacourse-racingcar/Yunseok-Nam/96-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +54 -0
  553. package/lessons/woowacourse-racingcar/aprilgom/130-/353/246/254/355/214/251/355/204/260/353/247/201.md +52 -0
  554. package/lessons/woowacourse-racingcar/aprilgom/97-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +49 -0
  555. package/lessons/woowacourse-racingcar/awesomeo184/23-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +48 -0
  556. package/lessons/woowacourse-racingcar/boogi-woogi/35-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +62 -0
  557. package/lessons/woowacourse-racingcar/boogi-woogi/59-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +55 -0
  558. package/lessons/woowacourse-racingcar/briandr97/54-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +57 -0
  559. package/lessons/woowacourse-racingcar/chaehyuns/131-/353/246/254/355/214/251/355/204/260/353/247/201.md +49 -0
  560. package/lessons/woowacourse-racingcar/chaehyuns/99-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +52 -0
  561. package/lessons/woowacourse-racingcar/chanho0908/147-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +54 -0
  562. package/lessons/woowacourse-racingcar/chanho0908/160-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +50 -0
  563. package/lessons/woowacourse-racingcar/chws0508/45-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +61 -0
  564. package/lessons/woowacourse-racingcar/chws0508/73-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +46 -0
  565. package/lessons/woowacourse-racingcar/cucumber99/132-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +55 -0
  566. package/lessons/woowacourse-racingcar/cucumber99/177-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +53 -0
  567. package/lessons/woowacourse-racingcar/devfeijoa/146-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +57 -0
  568. package/lessons/woowacourse-racingcar/doabletuple/149-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +55 -0
  569. package/lessons/woowacourse-racingcar/doabletuple/175-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +53 -0
  570. package/lessons/woowacourse-racingcar/donghyun81/154-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +58 -0
  571. package/lessons/woowacourse-racingcar/dpcks0509/103-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +48 -0
  572. package/lessons/woowacourse-racingcar/dpcks0509/112-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +48 -0
  573. package/lessons/woowacourse-racingcar/drunkenhw/82-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +60 -0
  574. package/lessons/woowacourse-racingcar/etama123/145-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +59 -0
  575. package/lessons/woowacourse-racingcar/gaeun5744/124-/353/246/254/355/214/251/355/204/260/353/247/201.md +53 -0
  576. package/lessons/woowacourse-racingcar/gaeun5744/93-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +60 -0
  577. package/lessons/woowacourse-racingcar/gahyunkim/134-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +53 -0
  578. package/lessons/woowacourse-racingcar/gahyunkim/164-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +54 -0
  579. package/lessons/woowacourse-racingcar/giovannijunseokim/140-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +54 -0
  580. package/lessons/woowacourse-racingcar/haeum808/101-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +55 -0
  581. package/lessons/woowacourse-racingcar/haeum808/129-/353/246/254/355/214/251/355/204/260/353/247/201.md +46 -0
  582. package/lessons/woowacourse-racingcar/hwannow/141-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +56 -0
  583. package/lessons/woowacourse-racingcar/hwannow/157-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +45 -0
  584. package/lessons/woowacourse-racingcar/hxeyexn/109-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +61 -0
  585. package/lessons/woowacourse-racingcar/hxeyexn/128-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +59 -0
  586. package/lessons/woowacourse-racingcar/hyemdooly/50-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +48 -0
  587. package/lessons/woowacourse-racingcar/hyemdooly/68-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +53 -0
  588. package/lessons/woowacourse-racingcar/hyunji1203/29-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +54 -0
  589. package/lessons/woowacourse-racingcar/hyunji1203/60-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +50 -0
  590. package/lessons/woowacourse-racingcar/ii2001/102-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +42 -0
  591. package/lessons/woowacourse-racingcar/ii2001/122-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +49 -0
  592. package/lessons/woowacourse-racingcar/ijh1298/144-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +57 -0
  593. package/lessons/woowacourse-racingcar/injoon2019/24-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +58 -0
  594. package/lessons/woowacourse-racingcar/inseonyun/44-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +60 -0
  595. package/lessons/woowacourse-racingcar/inseonyun/76-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +53 -0
  596. package/lessons/woowacourse-racingcar/ippnsj/36-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +54 -0
  597. package/lessons/woowacourse-racingcar/ippnsj/67-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +57 -0
  598. package/lessons/woowacourse-racingcar/jaeyeongjo/110-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +39 -0
  599. package/lessons/woowacourse-racingcar/jaeyeongjo/89-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +46 -0
  600. package/lessons/woowacourse-racingcar/jinuemong/104-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +49 -0
  601. package/lessons/woowacourse-racingcar/jinuemong/117-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +42 -0
  602. package/lessons/woowacourse-racingcar/jiyuneel/142-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +59 -0
  603. package/lessons/woowacourse-racingcar/junjange/113-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +41 -0
  604. package/lessons/woowacourse-racingcar/junjange/87-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +39 -0
  605. package/lessons/woowacourse-racingcar/junseo511/148-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +52 -0
  606. package/lessons/woowacourse-racingcar/junseo511/165-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +51 -0
  607. package/lessons/woowacourse-racingcar/ki960213/32-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +55 -0
  608. package/lessons/woowacourse-racingcar/ki960213/63-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +51 -0
  609. package/lessons/woowacourse-racingcar/kimhm0728/100-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +52 -0
  610. package/lessons/woowacourse-racingcar/kimhm0728/116-/353/246/254/355/214/251/355/204/260/353/247/201.md +54 -0
  611. package/lessons/woowacourse-racingcar/kkosang/105-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +54 -0
  612. package/lessons/woowacourse-racingcar/kkosang/126-/353/246/254/355/214/251/355/204/260/353/247/201.md +53 -0
  613. package/lessons/woowacourse-racingcar/kmkim2689/123-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +50 -0
  614. package/lessons/woowacourse-racingcar/kmkim2689/92-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +55 -0
  615. package/lessons/woowacourse-racingcar/krrong/34-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +63 -0
  616. package/lessons/woowacourse-racingcar/m6z1/150-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +53 -0
  617. package/lessons/woowacourse-racingcar/m6z1/156-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +40 -0
  618. package/lessons/woowacourse-racingcar/medAndro/153-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +54 -0
  619. package/lessons/woowacourse-racingcar/moondev03/135-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +57 -0
  620. package/lessons/woowacourse-racingcar/moondev03/161-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +52 -0
  621. package/lessons/woowacourse-racingcar/murjune/121-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +50 -0
  622. package/lessons/woowacourse-racingcar/murjune/95-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +54 -0
  623. package/lessons/woowacourse-racingcar/no1msh/43-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +55 -0
  624. package/lessons/woowacourse-racingcar/no1msh/69-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +60 -0
  625. package/lessons/woowacourse-racingcar/otter66/48-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +53 -0
  626. package/lessons/woowacourse-racingcar/otter66/77-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +52 -0
  627. package/lessons/woowacourse-racingcar/oungsi2000/152-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +56 -0
  628. package/lessons/woowacourse-racingcar/oungsi2000/187-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +54 -0
  629. package/lessons/woowacourse-racingcar/parkjiminnnn/143-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +58 -0
  630. package/lessons/woowacourse-racingcar/parkjiminnnn/158-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +54 -0
  631. package/lessons/woowacourse-racingcar/pingu244/38-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +58 -0
  632. package/lessons/woowacourse-racingcar/pingu244/62-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +59 -0
  633. package/lessons/woowacourse-racingcar/re4rk/28-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +60 -0
  634. package/lessons/woowacourse-racingcar/re4rk/55-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +54 -0
  635. package/lessons/woowacourse-racingcar/rhkrwngud445/42-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +53 -0
  636. package/lessons/woowacourse-racingcar/rhkrwngud445/74-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +47 -0
  637. package/lessons/woowacourse-racingcar/rhthrhrl0/31-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +43 -0
  638. package/lessons/woowacourse-racingcar/rosemin928/138-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +53 -0
  639. package/lessons/woowacourse-racingcar/rosemin928/171-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +38 -0
  640. package/lessons/woowacourse-racingcar/s6m1n/120-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +54 -0
  641. package/lessons/woowacourse-racingcar/s6m1n/91-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +62 -0
  642. package/lessons/woowacourse-racingcar/s9hn/53-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +44 -0
  643. package/lessons/woowacourse-racingcar/s9hn/78-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +43 -0
  644. package/lessons/woowacourse-racingcar/sh1mj1/107-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +55 -0
  645. package/lessons/woowacourse-racingcar/sh1mj1/115-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +61 -0
  646. package/lessons/woowacourse-racingcar/songpink/119-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +51 -0
  647. package/lessons/woowacourse-racingcar/songpink/98-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +55 -0
  648. package/lessons/woowacourse-racingcar/sujin9/52-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +48 -0
  649. package/lessons/woowacourse-racingcar/sujin9/61-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +47 -0
  650. package/lessons/woowacourse-racingcar/tmdgh1592/47-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +49 -0
  651. package/lessons/woowacourse-racingcar/tmdgh1592/64-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +53 -0
  652. package/lessons/woowacourse-racingcar/tobae-time/151-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +51 -0
  653. package/lessons/woowacourse-racingcar/tobae-time/167-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +43 -0
  654. package/lessons/woowacourse-racingcar/whk06061/41-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +58 -0
  655. package/lessons/woowacourse-racingcar/wondroid-world/136-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +49 -0
  656. package/lessons/woowacourse-racingcar/wondroid-world/166-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +50 -0
  657. package/lessons/woowacourse-racingcar/yrsel/139-1/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +53 -0
  658. package/lessons/woowacourse-racingcar/yujamint/83-2/353/213/250/352/263/204-/354/236/220/353/217/231/354/260/250-/352/262/275/354/243/274.md +59 -0
  659. package/package.json +46 -0
  660. package/skills/oh-my-oop/SKILL.md +39 -0
@@ -0,0 +1,97 @@
1
+ # PR #95 — [로또] 해음 2단계 미션
2
+
3
+ - **Reviewee:** [@haeum808](https://github.com/haeum808)
4
+ - **PR:** https://github.com/woowacourse/kotlin-lotto/pull/95
5
+ - **단계:** 2단계 (수동 로또 추가)
6
+ - **리뷰어:** @malibinYun
7
+ - **라인 코멘트:** 26
8
+
9
+ ## 잘한 점 (설계 관점)
10
+
11
+ - **`LottoNumber` Flyweight + `from(value)`** — `(1..45).associateWith` 캐싱.
12
+ - **`Lotto` 부생성자 두 종류** — `vararg` + `List<Int>` 두 호출 지점 지원.
13
+ - **`require(numbers.size == LOTTO_SIZE)`** — 도메인 invariant.
14
+ - **자가 인정 흐름** — 학생이 "잘못된 협력이라고 생각합니다. 변경하는 게 맞다고 생각합니다!"라고 *책임 위치*를 스스로 정정.
15
+
16
+ ## 못한 점 (설계 관점)
17
+
18
+ ### 1. `Lotto.findRank(lotto, bonus): Rank` — 등수 계산이 Lotto의 책임?
19
+
20
+ ```kotlin
21
+ class Lotto(val numbers: Set<LottoNumber>) {
22
+ fun findRank(lotto: Lotto, bonusNumber: LottoNumber): Rank {
23
+ val countOfMatch = (lotto.numbers intersect numbers).size
24
+ val matchBonus = lotto.contains(bonusNumber)
25
+ return Rank.valueOf(countOfMatch, matchBonus)
26
+ }
27
+ }
28
+ ```
29
+
30
+ 리뷰어: "거의 다 왔네요! 로또가 자기 자신과 보너스 번호까지 받아서 등수를 반환하고 있네요! 등수를 계산하는 게 로또 티켓이 해야 하는 일이 적절할까요? 스스로가 자기 자신을 비교했을 때, *맞은 번호의 개수* 정도만 반환하게 만들어 보는 건 어떨까요?" 학생: "lotto와 bonus는 WinningNumber가 가지고 있는데 이걸 굳이 'Lotto에게 메시지를 보내서 거기서 처리해!' 처럼 이상하게 코드를 작성. 객체 스스로 상태를 가지고 충분히 처리할 수 있는 책임인데 의미 없이 넘긴 책임이라고 생각합니다. 즉 *잘못된 협력*이라고 생각합니다."
31
+
32
+ ### 2. `LottoMachine`이 일회용 — 재사용 불가
33
+
34
+ ```kotlin
35
+ class LottoMachine(private val money: Money, val manual: Int) {
36
+ private val _lottoes: MutableList<Lotto> = mutableListOf()
37
+ fun makeManualLotto(lotto: Lotto) { _lottoes.add(lotto) }
38
+ fun makeRandomLotto() { repeat(auto.toInt()) { _lottoes.add(Lotto(.)) } }
39
+ }
40
+ ```
41
+
42
+ 리뷰어: "이 객체는 한 번 사용한 뒤, 재활용하지 못하는 형태네요! 객체를 한 개만 만들고, 새로 만들지 않고 로또 생성을 여러 번 할 수 있도록 변경해 보는 건 어떨까요?" 학생: "재활용하지 못하고 적절하지 못한 추가적인 객체라고 생각해서 Money 객체와 합쳐 주었습니다." — *생성자가 상태를 누적*하면 *일회용*. *상태 없는 메서드*면 재사용 가능.
43
+
44
+ ### 3. 랜덤 내장 — 테스트 불가
45
+
46
+ ```kotlin
47
+ fun makeRandomLotto() {
48
+ repeat(auto.toInt()) {
49
+ val randomNumbers = (1..45).shuffled().take(6).sorted() // ⚠ 내장
50
+ _lottoes.add(Lotto(randomNumbers))
51
+ }
52
+ }
53
+ ```
54
+
55
+ 리뷰어: "랜덤에 대한 요소가 다시 테스트할 수 없는 형태로 변경되었네요. 외부로부터 주입받는 형태로 변경해서 테스트 가능하도록 변경해 주세요! 개수만을 비교하는 것은 테스트에 큰 의미를 갖지 못한다고 생각해요. 개발자가 제어 가능한 환경에서 *원하는 로또 티켓 자체*를 검사해야 테스트도 의미가 있어요." 학생: "제어 가능 및 테스트 용이하게 람다를 넘기는 방식으로 변경했습니다." — 람다 주입 OK, `fun interface`도 옵션.
56
+
57
+ ### 4. `contains`에 `any` 사용 — Set의 `contains` 직접 호출 못 함
58
+
59
+ ```kotlin
60
+ operator fun contains(number: LottoNumber): Boolean = numbers.any { it == number }
61
+ ```
62
+
63
+ 리뷰어: "contains 내부 로직을 any를 활용하기보다, set의 기능인 contains를 활용해 보는 건 어떨까요? 시간 복잡도에서 어떤 차이점을 보일까요?" 학생: "선형 탐색이 아닌 해시로 찾게 됩니다. any를 사용하게 되면 O(n)이 나오지만 contains를 사용하면 O(1). 이미 있는 라이브러리 함수를 사용하는 게 맞다고 생각합니다." 리뷰어 후속: "반드시 모든 Set이 시간 복잡도가 O(1)인 것은 아니랍니다! Set은 interface이기에, 다양한 구현체들이 존재해요!" — 학생 답이 *대체로* 맞지만, *구현체 의존*임을 짚어줌.
64
+
65
+ ### 5. `LottoNumber` 캐싱 효과 검증 부재
66
+
67
+ 리뷰어: "캐싱을 활용해 주셨네요! 테스트를 통해 *실제로 같은 인스턴스를 반환하고 있는지* 검증해 보는 건 어떨까요?" 학생: "꼼꼼히 보지 못했습니다! 누군가 코드를 바꿀 수도 있는데 같은 인스턴스를 반환하는지 테스트 코드가 있다면 휴먼 에러를 없앨 수 있을 것 같습니다!" — *캐싱은 미래 변경으로 깨질 수 있는 invariant*. 테스트로 보호.
68
+
69
+ ### 6. `WinningLotto` 책임 위치 명확화
70
+
71
+ 리뷰어: "당첨 티켓이 여러 로또 티켓을 받아 등수를 계산해 주네요! 그렇다면 *1개의 로또 티켓을 받아 비교하는 역할*도 이 객체에 위치하는 게 자연스럽다는 생각이 드네요." 학생: "LottoDrawingResult의 책임으로 변경하고 보너스 번호가 있는지 체크하는 책임을 WinningLotto에 위임했습니다."
72
+
73
+ ## 리뷰어 의견 요지
74
+
75
+ - **메시지 방향 = 책임 소유** — `lotto.findRank(.)`는 *로또가 등수까지 알아야*. `winningLotto.match(lotto)`가 자연.
76
+ - ***일회용 객체* vs *재사용 객체*** — 누적 상태를 보유하면 일회용. 상태 없는 메서드는 재사용.
77
+ - **컬렉션 API의 *시간 복잡도*** — `Set.contains`가 보통 O(1), `any`는 O(n). 단 *구현체 의존*.
78
+ - **캐싱은 *테스트로 보호*해야 미래에 안 깨짐**.
79
+
80
+ - **대표 인용:**
81
+ > 거의 다 왔네요! 로또가 자기 자신과 보너스 번호까지 받아서 등수를 반환하고 있네요! 등수를 계산하는 게 로또 티켓이 해야 하는 일이 적절할까요?
82
+ > — @malibinYun on `src/main/kotlin/lotto/model/Lotto.kt`
83
+
84
+ > 이 객체는 한 번 사용한 뒤, 재활용하지 못하는 형태네요!
85
+ > — @malibinYun on `src/main/kotlin/lotto/model/LottoMachine.kt`
86
+
87
+ > 반드시 모든 Set이 시간 복잡도가 O(1)인 것은 아니랍니다! Set은 interface이기에, 다양한 구현체들이 존재해요!
88
+ > — @malibinYun on `src/main/kotlin/lotto/model/Lotto.kt`
89
+
90
+ ## 얻은 교훈
91
+
92
+ - **메시지 방향 = 도메인 의미** — "당첨 로또가 *내 번호와 비교한다*" (`winningLotto.match(lotto)`) vs "로또가 *당첨인지 확인*" — 전자가 자연. 등수 결정은 *당첨 로또의 행위*.
93
+ - **누적 상태 보유 = 일회용 객체**. `_lottoes.add()`가 누적되면 재사용 불가. *상태 없는 메서드*로 발행물만 반환.
94
+ - **랜덤 외부 주입**은 *테스트 가능성*의 1차 조건. 람다 또는 `fun interface`.
95
+ - **컬렉션 API 선택은 *시간 복잡도*와 *구현체*** — `any` vs `contains`는 의미는 같아도 비용이 다름. *Set의 구현체*까지 확인.
96
+ - **Flyweight 캐싱은 *테스트로 보호*** — 누군가 캐시 로직을 우회하면 *동일 인스턴스 반환*이라는 invariant가 깨짐. 명시 테스트로 안전망.
97
+ - **"잘못된 협력"이라는 학생 자가 표현**이 정확 — *책임 위임이 아니라 책임 전가*는 협력 X.
@@ -0,0 +1,235 @@
1
+ # PR #113 — [환노] 1단계 로또
2
+
3
+ - **Reviewee:** [@hwannow](https://github.com/hwannow)
4
+ - **PR:** https://github.com/woowacourse/kotlin-lotto/pull/113
5
+ - **단계:** 1단계
6
+ - **리뷰어:** @lee-ji-hoon (코니)
7
+ - **라인 코멘트:** 49 (학생 13 + 리뷰어 36)
8
+
9
+ ## 잘한 점 (설계 관점)
10
+
11
+ - **현실 비유로 모델 설계 시도** — *LottoResult = 결과 확인 사이트*, *Controller = 구입자*. (이후 비판되지만 *시도 자체*는 가치 있음).
12
+ - **`PurchaseAmountValidator`, `WinningNumberValidator`, `BonusNumberValidator` 분리** — *각 입력 책임* 의식.
13
+ - **`require` 사용** — 도메인 invariant 표명.
14
+
15
+ ## 못한 점 (설계 관점)
16
+
17
+ ### 1. *Controller가 모든 값 보유* — 현실 비유 오용
18
+
19
+ ```kotlin
20
+ fun run() {
21
+ val purchaseAmount = getPurchaseAmount() // Controller 보관
22
+ val lottos = LottoMachine().buyLottos(purchaseAmount)
23
+ val winningNumber = getWinningNumber()
24
+ val bonusNumber = getBonusNumber(winningNumber)
25
+ val lottoResult = LottoResult(winningNumber, bonusNumber)
26
+ val winningStats = lottoResult.matchLotto(lottos)
27
+ val prize = lottoResult.calculatePrize(winningStats)
28
+ outputView.printProfit(lottoResult.calculateProfit(prize, purchaseAmount)) // 직접 호출
29
+ }
30
+ ```
31
+
32
+ 학생 자가 변호: "LottoResult가 *로또 결과 확인 사이트*, Controller가 *로또를 구입하는 사람*이라고 생각했을 때, *현실에서는 구입 금액, 등수 별 당첨 결과, 상금, 수익률 같은 데이터는 로또 결과 확인 사이트에서 값을 저장하지 않고, 로또를 구입한 당사자가 갖고 있게* 됩니다. 따라서 코드도 위와 같이 *컨트롤러가 대부분의 리턴값을 갖게* 됐습니다. 특히 *등수 별 당첨 결과의 경우, LottoResult 내에서 계산하고 저장하려면 MutableMap 또는 lateinit 또는 var를 사용해야 하기 때문에* `결과를 저장할 객체를 따로 만들어야 할지`에 대해 많은 고민을 했습니다."
33
+
34
+ 리뷰어: "모든 것들을 *현실 세계로 반영하려고 했던 것과 그리고 제 생각에는 현실 세계랑도 안 맞는 부분이 존재해서 Model들이 해야 할 역할들을 제대로 못하고 있다*고 생각을 합니다. 이 부분은 *객체지향에 대해서 많이들 오해를 하고 있는 것이 객체를 현실 세계의 사물과 완전히 같은 것으로 오해를 하고 구현*을 하기 때문인데요. *실제로 모든 객체들이 그럴 수는 없습니다. 예를 들어 'A가 음료를 마신다.'라는 동작을 할 때 음료는 A로 인해서 양이 줄어들어야 하지만 객체지향에서 코드를 작성을 하게 되면 'A가 음료에게 메세지를' 던져서 양이 줄어들게* 되겠죠. 이런 것처럼 *모든 객체들이 현실세계와 완벽하게 동일하게 될 수는 없*습니다. *객체지향 패러다임의 목적은 현실세계를 모방하는 것이 아니라 현실 세계를 기반으로 새로운 세계를 창조하는 것이 메인*이라고 생각을 하는 게 더 좋을 것입니다. 책의 내용을 갖고 와 보자면 「객체지향의 사실과 오해」에서는 이런 말도 있는데요. > *소프트웨어 객체는 현실 속의 객체를 모방하거나 추상화한 것이 아닌 은유할 뿐이다. (쉽게 유추할 수 있도록)* 이처럼 *객체지향에서 객체는 현실 속의 객체를 추상화하고 은유를 할 뿐*이라고 생각해 주시면 더 좋을 같습니다." + "*현실 세계를 기준으로 등수 별 당첨 결과, 상금은 적어도 로또 확인 사이트에서 확인이 가능한 데이터* 같은데요. *어떤 기준으로 그렇게 생각하셨는지* 궁금하네요."
35
+
36
+ ### 2. `run()` *너무 가혹한 함수*
37
+
38
+ ```kotlin
39
+ fun run() {
40
+ val purchaseAmount = getPurchaseAmount() // 10줄
41
+ val lottos = LottoMachine().buyLottos(purchaseAmount)
42
+ outputView.printPurchasedLottos(lottos)
43
+ val winningNumber = getWinningNumber()
44
+ val bonusNumber = getBonusNumber(winningNumber)
45
+ val lottoResult = LottoResult(winningNumber, bonusNumber)
46
+ .
47
+ }
48
+ ```
49
+
50
+ 리뷰어: "*run이라는 함수의 역할이 너무 가혹*하다고 생각이 드네요. 지금 당장은 10줄이지만 *너무 많은 모델들이 포함되어 있는 함수라서 10줄이 20줄 30줄 같은 가독성*이 되어 버립니다. 그리고 *누군가 어떠한 코드를 추가할 때 실수하기도 더 쉬워*지겠죠."
51
+ ```kotlin
52
+ fun run() {
53
+ val lottoRound = createLottoRound()
54
+ val result = playLottoRound(lottoRound)
55
+ displayResult(result)
56
+ }
57
+ ```
58
+ "가령 이런 형태로도 나눠 볼 수 있을 거 같습니다."
59
+
60
+ ### 3. `Validator` *능동 vs 수동* — 책임 위치
61
+
62
+ ```kotlin
63
+ class PurchaseAmountValidator(input: String) { // 외부가 사용
64
+ init {. }
65
+ }
66
+ ```
67
+
68
+ 리뷰어: "`Validator`라는 *역할만 생각했을 때 어떠한 input에 대한 검증*일 것입니다. 그런데 *지금 검증을 하고 있는 것은 input이 메인처럼 보이지만 실제로는 본인의 생성에 대한 검증*인데 이것을 input으로 검증을 하고 있을 뿐이며, *외부에서 validator를 사용하는 게 아니라 validator가 능동적으로 검증을 하는데 수동적이어야 하지 않을까요*?"
69
+
70
+ 후속 (학생 우려): "*사용자로부터 받을 입력이 늘어나게 된다면 각 입력마다 Validator를 만들어야 되는 문제*가 생길 것 같은데."
71
+
72
+ 리뷰어 (도메인 모델링 본질): "*입력에 따른 Validator가 생기는 것은 당연한 일*이라고 생각합니다. *공통된 것들은 추상화를 하거나 비슷한 도메인은 하나의 Validator에서 처리*를 한다든지 하는 방법들이 있죠. 그런데 *지금 이것을 '문제'라고 인식한 이유는 모든 것들이 Controller의 역할이 되어 버려서 그렇게 인식*을 하게 된 것이라고 생각을 하는데 *제가 위에 적어둔 객체지향과 MVC에 대해서 다시 고민*해 보시기 바랍니다." 학생 후속: Validator 전부 제거, *PurchaseAmount.init*으로 이동. 리뷰어: "*모든 입력에 대한 검증을 Validator에서 하는 순간 Validator는 무궁무진하게 늘어나게 될 거에요*! 🫠".
73
+
74
+ ### 4. 테스트만을 위한 `public` 메서드
75
+
76
+ ```kotlin
77
+ class LottoMachine {
78
+ fun generateInternal(): Lotto =. // ⚠ Controller 안 부름
79
+ }
80
+ ```
81
+
82
+ 학생: "controller에서 *직접적인 호출 없이 테스트 코드를 위해 public으로 선언*된 메소드입니다." 리뷰어: "*'private 함수를 왜 테스트해야 하나?'라는 질문을 먼저 해 보면 좋을 거 같*은데요. 현재 *이 함수를 public으로 바꿔서 마음이 걸린다면, 이 함수는 애초에 별도의 책임의 일부로서 원래는 다른 클래스에 들어 있어야 했던 것이거나 테스트가 불필요한 것*일 겁니다."
83
+
84
+ ### 5. `parseToInt` *한 줄 함수 = 추출 가치?*
85
+
86
+ ```kotlin
87
+ private fun parseToInt(input: String): Int { return input.toInt() }
88
+ ```
89
+
90
+ 리뷰어: "*이게 정말 필요했던 함수일까요*? 그렇다면 *winningNumber.map { parseToInt(it) } 여기서 map도 함수화*를 해야 했지 않았을까요?" — *추출 일관성*: 한 곳만 추출하면 *기준 모호*.
91
+
92
+ ### 6. `RandomGenerator`의 *MIN/MAX 결합*
93
+
94
+ ```kotlin
95
+ class RandomGenerator {
96
+ fun getRandomNumberList(): List<Int> {
97
+ return (MIN_NUMBER..MAX_NUMBER).shuffled().take(6) // ⚠ Lotto 도메인 결합
98
+ }
99
+ }
100
+ ```
101
+
102
+ 리뷰어: "*이 클래스와 이 함수는 정말 Random인 Number를 뱉고 있나요? 제가 보기엔 어떤 도메인의 의존적으로 구현이 되어 있어서 특정 MIN과 MAX만 반환*하는 거 같네요" + "RandomGenerator는 *객체지향적 관점에서 봤을 때 어떤 역할을 하고 있을까요? 단순 랜덤으로 이루어진 것들은 모두 Generate해 주는 역할을 해야 하는 걸까요? 그러기엔 너무 가혹*하지 않을까요 🫠" + "로또를 구매하려고 할 때 *그제서야 RandomGenerator를 만드는 것은 뭔가 어색*하지 않나요? *LottoMachine에 내장되어 있어야 할 거 같은 기능*이네요" — *역할 부여*는 *공통 추상*이 아니라 *책임 일치*가 기준.
103
+
104
+ ### 7. *상수 위치 일관성* — 1, 45 다른 곳에 있는데 Lotto 안엔 없음
105
+
106
+ ```kotlin
107
+ class Lotto(.) {
108
+ init {
109
+ require(numbers.all { it in 1..45 }) // ⚠ 하드코딩
110
+ }
111
+ }
112
+ ```
113
+
114
+ 리뷰어: "*1과 45가 이미 다른 곳에 상수화되어 있는데요 여기에는 상수화가 안 되어 있*네요 🫠 즉 *Lotto가 1부터 45라는 개념이 지금 다른 곳에 조금 더 치중이 되어 있는 거 같은데 수정*해 보면 어떨까요!"
115
+
116
+ ### 8. `MutableList` 누적 → `List(n) {. }`
117
+
118
+ ```kotlin
119
+ val lottos: MutableList<Lotto> = mutableListOf()
120
+ repeat(lottoCount) {
121
+ lottos.add(Lotto(randomGenerator.getRandomNumberList()))
122
+ }
123
+ return lottos.toList()
124
+ ```
125
+
126
+ 리뷰어: "전반적으로 *Mutable한 값들은 최소화 해 보려고 했다*. 라는 내용이 있었는데요. *여기도 결국 이렇게 선언을 해 두면 계속 유지보수를 하다 보면 누군가가 이 값에 잘못 변경한다*든지 하는 일이 생길 거 같아요."
127
+ ```kotlin
128
+ fun buyLottos(purchaseAmount: Int): List<Lotto> {
129
+ val randomGenerator = RandomGenerator()
130
+ val lottoCount = getLottoCount(purchaseAmount)
131
+ return List(lottoCount) { Lotto(randomGenerator.getRandomNumberList()) }
132
+ }
133
+ ```
134
+
135
+ ### 9. `InputView` *중복 print + readln* — MVC 의도와 결합도
136
+
137
+ ```kotlin
138
+ fun getPurchaseAmount(): String { println(MESSAGE_INPUT_PURCHASE_AMOUNT); return readln() }
139
+ fun getWinningNumber(): String { println(MESSAGE_INPUT_WINNING_NUMBER); return readln() }
140
+ fun getBonusNumber(): String { println(MESSAGE_INPUT_BONUS_NUMBER); return readln() }
141
+ ```
142
+
143
+ 학생: "세 메소드가 *출력 → 입력값 반환 로직이 동일*해서 `fun getData(message: String): String {. }` 위처럼 *하나의 메소드로 통일*시킬지 고민했는데, 이렇게 될 경우 *호출부에서 출력 메시지를 넘겨주게* 됩니다. 따라서 *출력 부분에 수정이 일어나면 controller를 수정하게 될 텐데, 이는 MVC 패턴의 의도와 맞지 않는 것 같*아서 중복 로직 메소드 세 개를 각각 구현했습니다. 코니는 이에 대해 어떻게 생각하시나요?"
144
+
145
+ 리뷰어: "*제 개인적인 생각으로는 합리적*이라고 생각을 합니다. MVC 패턴의 의도는 *각 계층의 책임을 분리하는 데* 있습니다. *View는 사용자와의 인터랙션, 즉 입력과 출력을 담당하고, Controller는 비즈니스 로직의 흐름을 관리*하는 역할을 합니다. *입력 메시지를 View 내부에 하드코딩해 두면, View가 변경될 때 Controller에 영향을 주지 않는 장점*이 있는데요. *반면에, 하나의 범용 메소드를 만들어 메시지를 호출부에서 넘겨주게 되면, View의 메시지 로직이 Controller로 흘러들어가는 구조*가 됩니다. 이렇게 되면 *출력 메시지에 수정이 필요할 때 Controller까지 수정해야 하는 상황*이 발생할 수 있습니다." — 학생 사유 *지지*. + 추가: "*개인적으로 저 정도의 복잡성이면 딱히 비즈니스적인 것도 없으니 나중에 수정이 일어나도 저기에 수정은 없을 것 같아서 getData()처럼 하나의 함수 정도는 파 두고 다른 예외 함수들을 추가할 거 같*네요."
146
+
147
+ ### 10. *재입력 (`while+catch`)* vs *프로그램 종료*
148
+
149
+ 리뷰어: "전반적으로 *require을 사용해서 error를 만들어 주셨는데 이번엔 Catch해서 유저가 다시 입력을 하게끔 해 보는 건 어떨까요*?
150
+ ```kotlin
151
+ while(true) {
152
+ 1. 유저의 입력
153
+ 2. validate
154
+ 2-1. true -> 입력 그대로 반환
155
+ 2-2. catch -> 유저에게 알려주고 그대로 다시 입력 시작
156
+ }
157
+ ```
158
+ *이 부분은 시간이 남으면 구현해 보는 것으로 하겠습니다! 지금은 다른 부분에 집중*해 주세요!" — *학생 우선순위 보호*.
159
+
160
+ ### 11. *`var price` 변수 의도 모호* — 테스트 시그널 약함
161
+
162
+ ```kotlin
163
+ class LottoMachine {
164
+ val price: Int = LOTTO_PRICE // ⚠ 단순 테스트용 노출
165
+ }
166
+ ```
167
+
168
+ 리뷰어: "이 변수는 *단순 테스트만을 위해서 public*인 것으로 보이는데요. *테스트에서 1_000이라는 값을 확인하기 위함*인데, *꼭 price를 참조해서 확인을 했어야 했을까요*? 이 변수를 사용하는 *테스트 코드의 함수명은 '로또 1장의 가격은 1000원이다'*입니다. 그런데 *LOTTO_PRICE가 2,000원으로 변경이 되었을 때도 price라는 변수를 참조 중이니 테스트가 성공*할 거 같네요. *테스트 함수명에는 1000원인데도요* 🤔" — *테스트가 자기 자신을 참조*하는 *동어 반복* 안티.
169
+
170
+ ### 12. `PurchaseAmount` 네이밍 — *최소 단위* 명시
171
+
172
+ ```kotlin
173
+ class PurchaseAmount(val value: Int) {. }
174
+ ```
175
+
176
+ 리뷰어: "*PurchaseAmount만 봤을 때 이게 최소 단위가 있을 것이라고 예측이 가능*할까요? *객체는 클래스명만 봤을 때 어떤 역할을 할 것인지 어느 정도 납득이 가야 하는데 지금은 좀 아쉽다*는 생각이 있네요 🤔" + "*value라는 네이밍도 조금 더 가다듬*으면 어떨까요" — *클래스명 = 즉시 이해되는 도메인 책임*.
177
+
178
+ ### 13. *View는 멍청해야* — 메시지 선택권
179
+
180
+ 리뷰어: "*제가 가장 좋아하는 말은 'View는 멍청해야 한다.' / 'View는 수동적이어야 한다'*인데요! *View가 어떠한 메시지를 보여줄지 직접 선택하는 것도 가능은 하지만 멍청하게 해 보는 연습*을 해 보면 어떨까요?"
181
+
182
+ ### 14. *양수 체크 2곳* — 검증 위치 일원화
183
+
184
+ 리뷰어: "양수/음수를 확인하는 동작이 *Input에서도 하고 LottoPurchaseAmount init에서도 하는 것*으로 보이는데요. *LottoPurchaseAmount의 특성상 양수만 가능하긴 하지만 Input에서 이미 걸러졌을 것을 또 확인하게 되는 상황*이기도 한데요. 2곳에서 체크하니까 *한 곳은 없애야 한다!라는 것은 아니고, 양수만 가능한 것을 둘 다 체크하는 게 좋을지 한 곳에서만 하는 게 좋을지 한 번 고민*해 보면 좋을 거 같네요!"
185
+
186
+ ### 15. 학생 *필드 vs 생성자* 자가 의문
187
+
188
+ 학생: "이번 리팩토링 진행하면서 피드백 받았던 부분들 적용하려고 노력했습니다. 😭 다만 *아직 어떤 객체에 무엇을 저장해야 할지 감이 잡히지 않습니다*. winningStats, prize, profit을 *LottoCalculator의 필드에 저장하기엔 (선언 → 계산 메소드 → 저장) 로직으로 인해 var로 선언해야 하는 부분도 마음에 걸립니다*."
189
+
190
+ 리뷰어 "음 *근본적으로 왜 필드로 선언을 하려고 했던 것인지 한 번 이야기*를 해 보면 좋을 거 같네요. *생성자와 필드로 선언해야 할 것들이 각각 어떠한 상황에서 선택을 해야 하는지를 고민*해 봤으면 좋겠습니다. 가령 *winningStats를 필드 변수로 선언할 필요가 있을까요? Lotto들이 들어왔을 때 지금처럼 단순히 어떠한 결과값만 나와도 충분*하지 않을까요?" + "*추가로 저런 구조가 고민이 되면 그냥 짜고 리뷰를 받아 보는 것도 답*입니다. *리뷰어 입장에서는 글로만 설명이 되면 어떻게 구조를 잡고 이야기를 하시는 걸까?라는 의문이 계속 들기 때문*이죠! 코드를 리뷰 받기 위함이라면 그 *코드를 구현해 보고 우선 리뷰 요청을 해 보는 것도 팁*입니다."
191
+
192
+ ## 리뷰어 의견 요지
193
+
194
+ - ***객체지향 = 현실 모방 X, 현실 은유***. 「객체지향의 사실과 오해」 인용.
195
+ - **`run` *작은 함수 단위 (Round/Result/Display)***.
196
+ - **`Validator` *능동 vs 수동*** — *생성 시 자기 검증*이 자연.
197
+ - **테스트 위한 `public` 변경 X** — *책임 재배치*가 답.
198
+ - **`MutableList` 누적 → *불변 `List(n) {. }`***.
199
+ - **`InputView`의 *각 메시지 분리* MVC 결합도 낮춤** (학생 사유 지지).
200
+ - **재입력 catch 패턴** — *우선순위 보호*.
201
+ - **`var price` *테스트 위한 노출* = 동어 반복 테스트**.
202
+ - **`PurchaseAmount` *네이밍*에 *최소 단위* 단서**.
203
+ - **`View는 멍청해야*** — 메시지 선택권 최소화.
204
+ - **검증 위치 *일원화*** — 양수 체크 2곳 의식.
205
+
206
+ - **대표 인용:**
207
+ > 객체지향 패러다임의 목적은 *현실 세계를 모방하는 것이 아니라 현실 세계를 기반으로 새로운 세계를 창조하는 것이 메인*이라고 생각을 하는 게 더 좋을 것입니다.
208
+ > — @lee-ji-hoon on `src/main/kotlin/lotto/controller/LottoController.kt`
209
+
210
+ > 소프트웨어 객체는 *현실 속의 객체를 모방하거나 추상화한 것이 아닌 은유할 뿐*이다.
211
+ > — @lee-ji-hoon (조영호 「객체지향의 사실과 오해」 인용)
212
+
213
+ > 모든 것들이 Controller의 역할이 되어 버려서 *그렇게 인식*을 하게 된 것이라고 생각을 하는데 제가 위에 적어둔 *객체지향과 MVC에 대해서 다시 고민*해 보시기 바랍니다.
214
+ > — @lee-ji-hoon on `src/main/kotlin/lotto/controller/LottoController.kt`
215
+
216
+ > 코드를 리뷰 받기 위함이라면 그 *코드를 구현해 보고 우선 리뷰 요청을 해 보는 것도 팁*입니다.
217
+ > — @lee-ji-hoon on `src/main/kotlin/lotto/domain/LottoResult.kt`
218
+
219
+ ## 얻은 교훈
220
+
221
+ - **객체지향 = *현실의 은유, 모방 X*** — 「객체지향의 사실과 오해」 인용. *현실 비유*는 *유추 도구*이지 *설계 원리*가 아님.
222
+ - ***A가 음료를 마신다* → *A가 음료에게 메시지를 던진다*** — *능동/수동 뒤집힘*이 OO의 핵심.
223
+ - **`run` *작은 함수 단위*** — *createLottoRound → playLottoRound → displayResult* 같은 *논리 흐름*. 10줄이지만 *지속 가능*.
224
+ - **`Validator` *능동*** — *외부가 검증*은 *수동*. *객체 스스로 검증 (init)*이 *능동*.
225
+ - **테스트 위한 `public` 변경 = *책임 위치 재검토 신호*** — `internal` 회피하지 말고 *진짜 책임 분리*.
226
+ - **`MutableList` 누적 패턴 → *불변 `List(n) { generator() }`*** — Kotlin 컬렉션 생성 idiom + 불변 보장.
227
+ - **MVC 결합도 = *View 메시지의 위치***. 학생의 *각 메서드 분리*가 *Controller 영향 차단*. 둘 다 정당.
228
+ - **재입력 catch 패턴은 *선택* — *시간/우선순위*에 맡길 수 있음** — 리뷰어가 *학습 부하 조절*.
229
+ - **`var price` *테스트 노출* = 동어 반복** — *2,000원 변경 시에도 테스트 통과*하는 *부정 신호*. 테스트 함수명에 *명시 값*만 있어야.
230
+ - **`PurchaseAmount` 클래스명에 *최소 단위 단서*** — *클래스명만 보고 책임 즉시 파악*이 OO 어휘 기준.
231
+ - **`View는 멍청해야*** — *수동적*. *메시지 선택권* 최소.
232
+ - **검증 위치 일원화** — *Input + 도메인 init* 양쪽이면 *의도적 중복*인지 *실수 중복*인지 명시.
233
+ - **학생 필드 vs 생성자 자가 고민** — *임시 계산값*은 *필드 X, 반환값으로*. *var 회피*가 자연스럽게 *순수 함수*로.
234
+ - **`코드 짜고 리뷰 요청*** — *글로만 설명*하면 리뷰어가 *추측에 의존*. *실제 코드 + 리뷰 요청*이 효율.
235
+ - **「객체지향의 사실과 오해」 = 우테코 리뷰어들의 *공통 교과서*** — 학생들이 *책 인용 학습*하는 신호.
@@ -0,0 +1,149 @@
1
+ # PR #132 — [로또 2단계] 환노 미션
2
+
3
+ - **Reviewee:** [@hwannow](https://github.com/hwannow)
4
+ - **PR:** https://github.com/woowacourse/kotlin-lotto/pull/132
5
+ - **단계:** 2단계 (수동 로또 추가)
6
+ - **리뷰어:** @lee-ji-hoon
7
+ - **라인 코멘트:** 58
8
+
9
+ ## 잘한 점 (설계 관점)
10
+
11
+ - **`LottoGenerator` 인터페이스로 자동 로또 추출 분리** — `LottoMachine`이 generator 구현체에 의존하지 않음.
12
+ - **`LottoNumber` Flyweight 적용** — `(1..45).associateWith(::LottoNumber)`로 미리 생성한 인스턴스를 `from(value)`로 조회. `private constructor`까지 막아 외부 생성 차단.
13
+ - **`var purchasableCount` 외부 변경 가능성을 본인이 의심** — public 가변 필드의 위험을 코멘트에서 명시.
14
+ - **MVC 책임 경계에 대한 자가 의문** — View 분기 처리의 자리에 대해 학생이 먼저 논점 제기.
15
+ - **`OrderSheet`로 입력 정보 묶기 시도** — 흩어진 입력값을 한 객체로 묶으려는 의도는 좋음.
16
+
17
+ ## 못한 점 (설계 관점)
18
+
19
+ ### 1. `Lotto`가 테스트를 위해 `equals`/`hashCode` override
20
+
21
+ ```kotlin
22
+ class Lotto(randomNumbers: List<LottoNumber>) {
23
+ override fun equals(other: Any?): Boolean {
24
+ if (this === other) return true
25
+ if (other !is Lotto) return false
26
+ return numbers.toSet() == other.numbers.toSet()
27
+ }
28
+ override fun hashCode(): Int = numbers.toSet().hashCode()
29
+ }
30
+ ```
31
+
32
+ 리뷰어 지적: "지금 실제 도메인에서 사용이 되지 않는 equals hashCode로 확인이 됐는데요! 단순 테스트 관점에서 편의를 위해서 이렇게 변경을 하는 게 맞을까요?" — *테스트를 위해 도메인 내부 구조를 바꾸는 것*은 본말전도. 정렬 책임을 OutputView로 이동시키니 data class로 단순화 가능했음.
33
+
34
+ ### 2. `LottoPurchaseAmount`가 `lottoPrice`를 생성자 인자로 받음
35
+
36
+ ```kotlin
37
+ class LottoPurchaseAmount(val money: Int, lottoPrice: Int) {
38
+ var purchasableCount: Int // ⚠ public var
39
+ init { purchasableCount = money / lottoPrice }
40
+ }
41
+ ```
42
+
43
+ - **로또 가격을 누가 갖는가**의 책임 모호: `LottoMachine`도 알고 `LottoPurchaseAmount`도 받음. 리뷰어 비유 — "가격을 정해 주는 건 과자 가게이지만 가격이 매겨져 있는 건 과자 자체 아닐까요?"
44
+ - **`var purchasableCount` public** — `lottoPurchaseAmount.purchasableCount = 10` 식으로 검증 후에도 외부에서 덮어쓸 수 있음.
45
+ - **구매 금액 객체에서 구매 가능 수량이 나오는 것 자체가 어색** — 결국 `TotalPurchasableLottoCount`로 분리.
46
+
47
+ ### 3. `stringToLottoNumber(string: String)` — 시그니처에 타입 중복
48
+
49
+ ```kotlin
50
+ private fun stringToLottoNumber(string: String): List<LottoNumber> {
51
+ val splitString = string.split(DELIMITERS).map { it.trim() }
52
+ return splitString.map { LottoNumber(it.toInt()) }
53
+ }
54
+ ```
55
+
56
+ 리뷰어: "여기서 String이라는 정보가 들어갈 필요가 있을까요? string으로 받을 것이다! 라는 것을 이미 표현을 하고 있는 상태니까요!" — 함수명이 *입력 타입*을 기술하면 도메인 어휘가 사라짐.
57
+
58
+ ### 4. `LottoMachine`이 자동/수동/(가능한 하이브리드) 모두 한 클래스에서
59
+
60
+ ```kotlin
61
+ class LottoMachine(.) {
62
+ fun buyLottos(orderSheet: OrderSheet): List<Lotto> {. }
63
+ private fun buyAutoLottos(lottoCount: Int): List<Lotto> {. }
64
+ fun buyManualLottos(lottos: List<String>): List<Lotto> {. }
65
+ }
66
+ ```
67
+
68
+ 리뷰어 시나리오: "나중에 반자동 로또를 발급해 주는 것이 추가가 된다면 함수를 하나 더 추가를 하게 될까요? 이런 형태로 함수가 계속 늘어나다보면 하나의 Machine에 너무 많은 로직들이 들어가게 될 수 있고…" — 결국 `LottoGenerator` 인터페이스에 자동/수동/하이브리드 구현을 두는 **Strategy** 또는 generator 리스트 주입 방식을 권유.
69
+
70
+ ### 5. `OrderSheet`가 책임을 너무 많이 보유
71
+
72
+ ```kotlin
73
+ class OrderSheet(
74
+ val purchaseAmount: LottoPurchaseAmount,
75
+ val manualLottoCount: ManualLottoCount,
76
+ val manualLottoNumber: List<Lotto>
77
+ )
78
+ ```
79
+
80
+ 리뷰어 비교: "주문서의 역할이면 `수동 2장 / 자동 5장 / 총 얼마` 같은 정보만 갖고 있어야 하지 않을까요? 지금 보면 Lotto 자체도 들고 있고 ManualLottoCount도 들고 있다 보니 어색하네요." — 주문서는 *주문 의도*만, 완성된 `Lotto` 인스턴스는 머신의 출력물.
81
+
82
+ ### 6. View가 입력 재시도까지 통째로 처리
83
+
84
+ ```kotlin
85
+ fun getManualLottoCount(): Int {
86
+ while (true) {
87
+ println(MESSAGE_INPUT_MANUAL_LOTTO_COUNT)
88
+ val input = intOrNull(readln())
89
+ if (input != null) return input
90
+ }
91
+ }
92
+ ```
93
+
94
+ `null` 반환만으로는 "왜 실패했는지" 정보가 사라짐. 리뷰어 제안 — `sealed interface InputResult { EmptyInput; NotNumber; Success(Int) }`로 *실패 유형*까지 타입에 담아야 View가 적절한 메시지를 띄울 수 있음.
95
+
96
+ ### 7. `ManualLottoCount`가 `purchasableCount`를 알아야 함
97
+
98
+ ```kotlin
99
+ class ManualLottoCount(val lottoCount: Int, purchasableCount: Int) {
100
+ init { require(lottoCount <= purchasableCount) }
101
+ }
102
+ ```
103
+
104
+ 리뷰어: "수동 로또 수가 총 구매 로또 수를 알아야 할 필요가 있을까요? 전체 구매 수량 → (수동, 자동)으로 묶여서 관리되는 게 맞지 않을까요?" — *수동 수가 가능 수를 안다*는 것은 책임의 역류.
105
+
106
+ ### 8. 테스트 이름이 "어떻게 실패하는지"를 기술
107
+
108
+ ```kotlin
109
+ @ValueSource(ints = [-1, -2, -1000])
110
+ fun `수동으로 구매할 로또 수로 0 미만의 숫자가 들어오면 IllegalArgumentException이 발생한다`(input: Int) {. }
111
+ ```
112
+
113
+ 리뷰어: "주요 관심사는 `0 미만의 숫자가 들어오면 안 된다`인데 이게 어떻게 0이 안 들어오게 하는지는 큰 관심사가 아닐 거예요. exception으로 방지를 하거나 null로 반환을 하거나 등등의 방법은 구현부에서 알아서 할 일이라고 생각" — 테스트명이 **구현 수단(Exception)** 을 가리키면 구현 바꿀 때 테스트도 갈아엎어야 함.
114
+
115
+ ### 9. `Lotto`가 정렬 시점을 저장 시점에 잡음
116
+
117
+ 저장 시점에 sort → data class 못 씀 → equals/hashCode 강제. 학생이 토론 후 "값을 정렬해서 보여 주는 건 UI 로직이다"로 결론. 핵심 — *정렬은 표현*이고, 표현은 OutputView. 도메인이 표현 형식을 가지고 있으면 출력 변경이 도메인 변경.
118
+
119
+ ## 리뷰어 의견 요지
120
+
121
+ 1. **"View는 멍청해야 한다"** — 단, 어디까지 멍청해야 하는지는 팀 합의. 데이터 분기/필터링/정렬이 *비즈니스적이면* 도메인, *표현적이면* View.
122
+ 2. **테스트를 위해 도메인 내부를 바꾸지 말 것** — equals override가 단지 테스트 비교를 위한 것이라면 잘못된 신호. 정렬 책임 자체를 옮기면 data class로 자연스럽게 비교 가능.
123
+ 3. **`null`보다 sealed로 실패 타입화** — `EmptyInput`/`NotNumber`/`Success` 같이 *실패 유형*을 타입에 담아야 호출자가 강제로 분기.
124
+ 4. **책임 비대 시 추상화** — `LottoMachine`에 메서드 늘리기 vs `LottoGenerator` 구현체 늘리기. 후자가 단일 책임 + 테스트 격리.
125
+ 5. **모든 원시 값/문자열 포장 원칙은 *가격*도 예외 아님** — `lottoPrice: Int`로 떠다니면 `LottoMoney`/`LottoPrice` 같은 타입이 어디에 속해야 하는지 자연스럽게 드러남.
126
+
127
+ - **대표 인용:**
128
+ > 단순 테스트 관점에서 편의를 위해서 이렇게 변경을 하는 게 맞을까요? 단순 테스트만을 위한 방법이라면 다른 방법들이 더 있을 거 같은데 한 번 고민해보시면 좋을 거 같습니다.
129
+ > — @lee-ji-hoon on `src/main/kotlin/lotto/domain/Lotto.kt`
130
+
131
+ > `var + public`이면 어떤 문제를 초래할 수 있을까요? Amount를 아는 곳에서 이 값을 의도적으로 변경할 수 있지 않을까요?
132
+ > — @lee-ji-hoon on `src/main/kotlin/lotto/domain/LottoPurchaseAmount.kt`
133
+
134
+ > 로또를 과자, 로또 머신을 과자 가게라고 생각했을 때, 가격을 정해 주는 건 과자 가게이지만 가격이 매겨져 있는 건 과자 자체 아닐까요?
135
+ > — @lee-ji-hoon on `src/main/kotlin/lotto/domain/LottoPurchaseAmount.kt`
136
+
137
+ > `null`로만 반환하면 main 입장에서 "나는 무엇을 해야 하는 거지?"라는 것을 고민하게 될 거예요. sealed로 처리한다면 UI는 상태에 따라 표시할 Text를 정할 수도 있죠.
138
+ > — @lee-ji-hoon on `src/main/kotlin/lotto/view/InputView.kt`
139
+
140
+ ## 얻은 교훈
141
+
142
+ - **테스트를 위해 도메인 내부 구조 바꾸지 말 것.** `equals`/`hashCode`/`toString` override의 동기가 "테스트 통과"라면 책임 위치 재고 신호. 정렬을 OutputView로 옮기니 data class로 자연스럽게 풀림.
143
+ - **`var + public` 필드는 검증을 무효화.** `init { require(.) }`로 막아도 외부에서 setter로 덮어쓸 수 있으면 도메인 무결성 0. 모든 도메인 필드는 `val` 또는 캡슐화된 setter.
144
+ - **`null`은 실패 *유형*을 못 담는다.** 실패 사유가 여러 가지(빈 입력 / 형식 / 범위)면 sealed로 타입화해야 호출자가 의미 있는 분기를 강제받음.
145
+ - **함수 이름에 입력 타입이 들어가면 도메인 어휘 소실.** `stringToLottoNumber(string)` 대신 `parseLotto(input)` 또는 단순히 호출 위치에서 변환.
146
+ - **"본인이 본인의 가격을 안다."** — 로또 가격을 `LottoMachine`/`PurchaseAmount`에 끼워 넣는 대신 `Lotto.price` 또는 `LottoPrice` 값 객체로. 두 곳이 같은 정보를 알면 둘 중 하나는 책임 침범.
147
+ - **메서드 추가 vs 구현체 추가.** 동일 행위의 *전략*이 늘 때 메서드를 추가하면 클래스 비대 + 테스트 폭증. Strategy/구현체 분리가 테스트 격리·유지보수에 유리.
148
+ - **테스트명은 *의도*, 구현 수단 아님.** `"X가 발생한다"` 보다 `"X는 허용되지 않는다"` — 검증 방식(예외/null/Result)이 바뀌어도 테스트명은 유지됨.
149
+ - **`LottoNumber` Flyweight + `private constructor`** = 도메인 객체 수가 유한할 때의 표준 패턴. 추가로 `value class`(Kotlin)나 `record`(Java)로 한 단계 더 최적화 가능.
@@ -0,0 +1,141 @@
1
+ # PR #77 — [해나] 1단계 로또
2
+
3
+ - **Reviewee:** [@hxeyexn](https://github.com/hxeyexn)
4
+ - **PR:** https://github.com/woowacourse/kotlin-lotto/pull/77
5
+ - **단계:** 1단계
6
+ - **리뷰어:** @KwonDae (제이든)
7
+ - **라인 코멘트:** 15
8
+
9
+ ## 잘한 점 (설계 관점)
10
+
11
+ - **한정자 + 원시값 포장 (`LotteryNumber`)** — 리뷰어 칭찬: "한정자를 통해 외부에 공개하지 않고 *원시값 포장을 잘 해 주셨어요* 👍".
12
+ - **`TicketGenerationStrategy` 인터페이스** — Strategy. 리뷰어 칭찬: "인터페이스 💯".
13
+ - **PR 본문에 *4가지 자가 질문***: 캡슐화 복잡도, run vs apply, 중복 상수, 유효성 검증 위치.
14
+ - **후속 라운드 *Set으로 중복 방지*, *전략 생성자 주입*, *가격 default param*** 모두 반영.
15
+
16
+ ## 못한 점 (설계 관점)
17
+
18
+ ### 1. `List` vs `Set` — 중복 방지 *자료구조*로 표현
19
+
20
+ ```kotlin
21
+ class Lottery(private val lotteryNumbers: List<LotteryNumber>) {
22
+ init {
23
+ require(validateDuplicate(lotteryNumbers)) { EXCEPTION_DUPLICATED_NUMBER }
24
+ }
25
+ private fun validateDuplicate(lotteryNumbers: List<LotteryNumber>) =
26
+ lotteryNumbers.size == lotteryNumbers.toSet().size
27
+ }
28
+ ```
29
+
30
+ 리뷰어: "*중복된 번호에 대한 검증이 필요하다면 중복을 방지할 수 있도록 자료구조를 사용*해 보는 건 어떨까요?" — *제약을 타입으로 표현*. 학생: "*List 대신 Set을 사용해 중복을 방지*하도록 수정했습니다!"
31
+
32
+ ### 2. `toString()` 의존 — 문구 변경 시 도메인 변경
33
+
34
+ ```kotlin
35
+ override fun toString() = "[${lotteryNumbers.map { it.number }.joinToString(", ")}]\n"
36
+ ```
37
+
38
+ 리뷰어: "지금은 *단순 출력문이기에 문제가 되지 않*지만 *view에 보여지는 문구를 수정해 달라는 요청이 왔을 때 도메인 모델의 toString() 함수를 수정*해야겠네요. *어떠한 문구에 의존하지 않고 여러 구분자에 대응이 가능*하도록 할 수 있을까요?"
39
+
40
+ ### 3. `LottoNumber.fromInput`의 `split` — View 책임
41
+
42
+ ```kotlin
43
+ fun fromInput(input: String): Lottery {
44
+ return input.split(LOTTERY_DELIMITER).map { LotteryNumber.fromInput(it) }
45
+ .run { Lottery(this) }
46
+ }
47
+ ```
48
+
49
+ 리뷰어: "위와 동일합니다. 또한, *split하는 로직은 view와 관련이 있어 보이*네요." — *문자열 파싱* = View 책임. 도메인은 *List<Int>* 받기.
50
+
51
+ ### 4. `LOTTO_TICKET_PRICE` *내부 상수 의존* — 가격 인상 시 변경 범위 큼
52
+
53
+ ```kotlin
54
+ class RandomTicketGenerationStrategy(private val amount: Amount) {
55
+ override fun issueTicket(): Ticket {
56
+ repeat(amount.money / LOTTO_TICKET_PRICE) {. } // ⚠ 내부 상수
57
+ }
58
+ }
59
+ ```
60
+
61
+ 리뷰어: "현재는 로또 가격이 1000으로 고정되어 있어서 문제가 없지만 *로또 가격이 인상되었다면, 검증하는 비즈니스 로직 내부 코드도 변경되어야 하고 테스트 코드도 변경*되어야 합니다. *내부 상수에 의존하지 않고 유연하게 대처*해 볼까요?" 학생: "주 생성자에 *로또 가격을 추가하고, 기본 값을 두어 가격이 인상되면 주 생성자의 디폴트 값만 변경*할 수 있도록 하여 비즈니스 로직 내부 코드와 테스트 코드는 변경되지 않도록 수정했습니다!" 후속 리뷰어: "기본 값이 있는 *파라미터 활용으로, 비즈니스 로직을 보다 유연*하게 활용할 수 있게 되었네요".
62
+
63
+ ### 5. *랜덤 요소 외부 주입*
64
+
65
+ 리뷰어: "*랜덤의 요소가 변경되면 비즈니스 로직도 변경되어야 할까요*? 로또 뿐 아니라 *랜덤 요소가 변경되어도 랜덤 요소를 외부로부터 주입받아 LottoNumberGenerator 로직을 재사용 가능*하게끔 해볼까요?" — *함수형 인터페이스 또는 LottoNumberGenerator 분리*.
66
+
67
+ ### 6. `LotteryStore.setStrategy()` *Builder 패턴 가짜*
68
+
69
+ ```kotlin
70
+ class LotteryStore {
71
+ private var ticketGenerationStrategy: TicketGenerationStrategy = DefaultTicketGenerationStrategy()
72
+
73
+ fun setStrategy(ticketGenerationStrategy: TicketGenerationStrategy): LotteryStore {
74
+ this.ticketGenerationStrategy = ticketGenerationStrategy
75
+ return this
76
+ }
77
+ }
78
+ ```
79
+
80
+ 리뷰어: "Controller에서 *실수로 strategy를 설정해 주지 않으면 DefaultTicketGenerationStrategy으로 테스트 코드가 출력*이 될 수 있겠네요.! *어떻게 하면 LotteryStore를 사용할 때 테스트 코드에서는 TestStrategy, 로또에서는 LottoStrategy를 사용하도록 유도*할 수 있을까요?" 학생: "주 생성자로 *TicketGenerationStrategy을 의존성 주입*하여 테스트 코드에서는 ExplictStrategy, 로또 스토어에서는 RandomStrategy를 사용하도록 유도하게 수정했습니다!" 후속 리뷰어: "*어떠한 전략을 따르는 로또가게*인지를 나타내게 되었네요 👍". — *생성자 주입 = 의무 명시*, *setter 주입 = 실수 허용*.
81
+
82
+ ### 7. `.run`/`.apply` 남용 — 학생 질문
83
+
84
+ 학생 질문 (PR 본문): "run은 람다 식의 결과를 반환해 주고, apply는 수신 객체 자체를 반환해 준다고 알고 있습니다. *이를 적용할 때마다 어떤 걸 사용해야 하는지 아직 기준이 모호*할 게 느껴질 때가 많은데." 리뷰어: "*저는 개인적으로 run 대신 의미 있는 변수를 사용하여 표현*하려고 하며, apply는 *하나의 변수에 반복되는 패턴(ex. builder) 같은 경우 통일성*을 주기 위해 apply 블럭 안에서 설정해 주곤 합니다." 학생 후속:
85
+ ```diff
86
+ -return numbers.map { LotteryNumber(it) }.run { Lottery(this) }
87
+ +val lotteryNumbers = numbers.map { LotteryNumber(it) }
88
+ +return Lottery(lotteryNumbers)
89
+ ```
90
+ 리뷰어 칭찬: "*변수 활용으로 가독성이 한층 높아졌네요* 👍 이제 *어떤 값을 반환하려는 함수인지 보다 명확*해졌어요."
91
+
92
+ ### 8. *중복 상수 위치* — 학생 자가 질문
93
+
94
+ 학생: "1. 각각의 파일에서만 사용되는 부분은 각각의 파일에서 관리하고, *공통적으로 쓰이는 상수들은 별도의 상수 파일을 만들어서 관리*. 2. 지금처럼 각각의 파일에서 필요한 상수는 각각의 파일에서 관리. 이건 해나의 의견도 궁금하네요." 리뷰어: "*단지 2번의 경우에는 수정이 필요할 때 모든 곳에서 수정을 요구*하겠죠? *실수로라도 바꾸지 않았다면 상이한 결과*를 나타낼 겁니다." — *유지보수 단위*는 *단일 진입점*.
95
+
96
+ ### 9. *init vs 팩토리 메서드* — 학생 자가 질문
97
+
98
+ 학생: "유효성 검증을 *init 블록에서 처리하는 방법과 팩토리 메서드에서 처리하는 방법, 이 두 가지를 같이 사용*했는데." 리뷰어: "*복잡하다는 건 어느 정도가 복잡한 걸까요*?🧐 *팩토리 메서드를 통해 로또 상점 객체를 만들 때 검증을 하는 과정을 담당*할 수 있겠고 *로또 상점 객체가 만들어지고, 로또를 생성할 때 로또의 init 블럭에서 검증*을 진행할 수 있겠네요. 말그대로 *팩토리 메서드는 객체를 만들어 내는 공장(Factory)을 만드는 패턴*이라고 생각해 주시면 될 것 같습니다." — *init = 자기 invariant*, *factory = 입력 변환 + 객체 생성 결정*.
99
+
100
+ ### 10. ktlint
101
+
102
+ 리뷰어: "*ktlint를 확인*해 주세요!" (이미지 첨부).
103
+
104
+ ## 리뷰어 의견 요지
105
+
106
+ - **제약을 *타입/자료구조*로 표현** — 중복 방지 = Set.
107
+ - **`toString` View 책임** — *문구 변경 시 도메인 안전*.
108
+ - **문자열 *split*은 View** — 도메인은 *변환된 입력*.
109
+ - ***Default* 파라미터로 *생성자 가격 주입***.
110
+ - **랜덤 *외부 주입***.
111
+ - **`setStrategy` 가짜 Builder X** — *생성자 주입 강제*.
112
+ - **`.run`/`.apply` *남용 회피*** — 의미 있는 변수.
113
+ - **상수 *단일 진입점*** — 분산 시 변경 누락 위험.
114
+ - **`init` = 자기 invariant, `factory` = 입력 변환 + 생성 결정**.
115
+
116
+ - **대표 인용:**
117
+ > 중복된 번호에 대한 검증이 필요하다면 *중복을 방지할 수 있도록 자료구조를 사용*해 보는 건 어떨까요?
118
+ > — @KwonDae on `src/main/kotlin/model/Lottery.kt`
119
+
120
+ > view에 보여지는 문구를 수정해 달라는 요청이 왔을 때 *도메인 모델의 toString() 함수를 수정해야겠*네요. *어떠한 문구에 의존하지 않고 여러 구분자에 대응이 가능*하도록 할 수 있을까요?
121
+ > — @KwonDae on `src/main/kotlin/model/Lottery.kt`
122
+
123
+ > Controller에서 *실수로 strategy를 설정해 주지 않으면* DefaultTicketGenerationStrategy으로 테스트 코드가 출력이 될 수 있겠네요.!
124
+ > — @KwonDae on `src/main/kotlin/model/LotteryStore.kt`
125
+
126
+ > 단지 2번의 경우에는 수정이 필요할 때 *모든 곳에서 수정을 요구*하겠죠? *실수로라도 바꾸지 않았다면 상이한 결과*를 나타낼 겁니다.
127
+ > — @KwonDae on README.md
128
+
129
+ ## 얻은 교훈
130
+
131
+ - **제약을 *자료구조*로 표현** — *중복 방지*는 검증이 아니라 *타입* (`Set`). *불가능한 상태*를 *불가능한 타입*으로.
132
+ - **`toString` 도메인 침투 = 미래 비용** — *문구 변경 요청* 시 *도메인 변경*.
133
+ - **문자열 `split`은 View** — 도메인은 *변환된 입력* (`List<Int>`).
134
+ - **`Default` 파라미터로 *변경 단일 지점*** — `lottoTicketPrice: Int = 1_000`는 *가격 인상 시 한 줄 변경*.
135
+ - **랜덤 *외부 주입*** — *함수형 인터페이스* (`() -> Int`)로 *테스트 가능성* + *재사용*.
136
+ - **`setStrategy` 가짜 Builder X** — *Controller가 까먹으면 Default*인 *암묵 의존*. 생성자 주입 = *의무*.
137
+ - **`.run`/`.apply` 회피** — *지역 변수 + 명시적 호출*이 *어떤 값을 반환하는지* 드러냄. 리뷰어 칭찬: "변수 활용으로 가독성 높아졌네요".
138
+ - **상수 *공통 상수 파일*** — 분산 관리 시 *수정 누락*. *단일 진입점*.
139
+ - **`init` = *자기 invariant*** (개수, 범위), **`factory` = *입력 변환 + 생성 결정*** (String → List<Int>). 둘 다 사용 정당.
140
+ - **자가 4가지 질문을 PR 본문에 정리** — 리뷰어가 *체계적 응답* 가능. 좋은 *PR 설명 패턴*.
141
+ - **ktlint** — *형식 자동화*는 *코드 리뷰의 첫 게이트키퍼*.