<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>kok202</title>
    <link>https://kok202.tistory.com/</link>
    <description>개발 기록</description>
    <language>ko</language>
    <pubDate>Wed, 8 Apr 2026 22:18:13 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>kok202</managingEditor>
    <item>
      <title>Sonarkube - 소나 큐브 java 규칙 번역</title>
      <link>https://kok202.tistory.com/355</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;929&quot; data-origin-height=&quot;224&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/sH2Ux/btrYWakgdFT/AUDTmzhcFnxeR782wm1z50/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/sH2Ux/btrYWakgdFT/AUDTmzhcFnxeR782wm1z50/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/sH2Ux/btrYWakgdFT/AUDTmzhcFnxeR782wm1z50/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsH2Ux%2FbtrYWakgdFT%2FAUDTmzhcFnxeR782wm1z50%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;929&quot; height=&quot;224&quot; data-origin-width=&quot;929&quot; data-origin-height=&quot;224&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;죽어있나 살아있나 할만하면 돌아오는 근황입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;올해 상반기에는 소나 큐브에 있는 java 규칙을 번역하는 프로젝트를 진행 중입니다. 작년에 회사 동료의 집들이를 갔다가 오픈 소스 기여같은 걸 진행해보고 싶다고 하시더라구요. 저는 또 꾸준히하는 것은 자신이 있어서, 그럼 평상시에 관심이 많았던 정적 분석 도구인 소나 큐브의 규칙들을 번역해보자 해서 진행하고 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바쪽 규칙이 총 600개 정도 되는 데, 원래의 계산대로라면 하루에 한 개씩해서 1년안에 마무리하는 게 목표였습니다. 그런데 생각보다 규칙이 그렇게 어렵지 않고 매일같이 하기에는 급한 일이 생기는 경우도 많더라고요.&amp;nbsp; 그래서 지금은 비정기적으로 하루에 3개씩한다거나 어떤 주에는 한주에 20개씩 하는 경우도 있는 것 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 미약하지만 현재 대략 150개 룰정도가 번역이 되서, 슬슬 블로그 같은 곳에 공유할만 해졌다 싶어서 공유드리네요. 아래는 번역 중인 깃헙 페이지와 깃허브 레포지토리 주소입니다~ 깃헙 페이지는 조금 더 꾸며야 하는데, 일단 규칙을 번역하는게 먼저니까요. 프로젝트 이름은 Sonarkube이고 sonarqube에서 한국어 번역을 뜻하는 k만 갖다 붙였습니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://kantabile.github.io/sonarkube/&quot;&gt;https://kantabile.github.io/sonarkube/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1676274334995&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;홈 - Sonarkube&quot; data-og-description=&quot;URL 매개변수와 같은 사용자 제공 데이터는 항상 신뢰할 수 없고 오염된 것으로 간주해야 합니다. 오염된 데이터에서 직접 쿠키를 만들면 공격자가 세션 식별자를 알려진 값(Set-Cookie, sessionId )으&quot; data-og-host=&quot;kantabile.github.io&quot; data-og-source-url=&quot;https://kantabile.github.io/sonarkube/&quot; data-og-url=&quot;https://kantabile.github.io/sonarkube/&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://kantabile.github.io/sonarkube/&quot; data-source-url=&quot;https://kantabile.github.io/sonarkube/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('&amp;quot;&amp;quot;');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;홈 - Sonarkube&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;URL 매개변수와 같은 사용자 제공 데이터는 항상 신뢰할 수 없고 오염된 것으로 간주해야 합니다. 오염된 데이터에서 직접 쿠키를 만들면 공격자가 세션 식별자를 알려진 값(Set-Cookie, sessionId )으&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;kantabile.github.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/kantabile/sonarkube&quot;&gt;https://github.com/kantabile/sonarkube&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1676274334995&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - kantabile/sonarkube&quot; data-og-description=&quot;Contribute to kantabile/sonarkube development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/kantabile/sonarkube&quot; data-og-url=&quot;https://github.com/kantabile/sonarkube&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/CRyUl/hyRBWKPzvI/KZWtw3rLYZciPF3NuuY8Ak/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/kantabile/sonarkube&quot; data-source-url=&quot;https://github.com/kantabile/sonarkube&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/CRyUl/hyRBWKPzvI/KZWtw3rLYZciPF3NuuY8Ak/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;GitHub - kantabile/sonarkube&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Contribute to kantabile/sonarkube development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;번역 난이도가 생각보다 어렵지 않습니다. contribution을 환영하고 있으니 참고해주시길 바랍니다~&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style8&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원래는 셋이서 진행할 예정이었는데, 다른 동료분들이 생겼습니다.&amp;nbsp;너무나 훌륭한 분이시니 참고해주시길!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;메인 리딩:&lt;/b&gt; &lt;a href=&quot;https://github.com/isangu&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/isangu&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1676274309299&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;profile&quot; data-og-title=&quot;isangu - Overview&quot; data-og-description=&quot;isangu has 22 repositories available. Follow their code on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/isangu&quot; data-og-url=&quot;https://github.com/isangu&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/eM8l0/hyRBUfa010/e6VxgwovpGxRbCR7rL2VM1/img.jpg?width=460&amp;amp;height=460&amp;amp;face=0_0_460_460&quot;&gt;&lt;a href=&quot;https://github.com/isangu&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/isangu&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/eM8l0/hyRBUfa010/e6VxgwovpGxRbCR7rL2VM1/img.jpg?width=460&amp;amp;height=460&amp;amp;face=0_0_460_460');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;isangu - Overview&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;isangu has 22 repositories available. Follow their code on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/GimunLee/tech-refrigerator&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/GimunLee/tech-refrigerator&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1676274275963&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - GimunLee/tech-refrigerator:   기술 냉장고입니다.   기술 면접 , 전공 시험 , 지식 함양 등 분&quot; data-og-description=&quot;  기술 냉장고입니다.   기술 면접 , 전공 시험 , 지식 함양 등 분명 도움될 거예요!   - GitHub - GimunLee/tech-refrigerator:   기술 냉장고입니다.   기술 면접 , 전공 시험 , 지식 함양 등 분명 도&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/GimunLee/tech-refrigerator&quot; data-og-url=&quot;https://github.com/GimunLee/tech-refrigerator&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bpTbZD/hyRBNNTMgV/gA5aAk5RoBS4aRmLBNYzJk/img.jpg?width=1421&amp;amp;height=882&amp;amp;face=0_0_1421_882&quot;&gt;&lt;a href=&quot;https://github.com/GimunLee/tech-refrigerator&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/GimunLee/tech-refrigerator&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bpTbZD/hyRBNNTMgV/gA5aAk5RoBS4aRmLBNYzJk/img.jpg?width=1421&amp;amp;height=882&amp;amp;face=0_0_1421_882');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;GitHub - GimunLee/tech-refrigerator:   기술 냉장고입니다.   기술 면접 , 전공 시험 , 지식 함양 등 분&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;  기술 냉장고입니다.   기술 면접 , 전공 시험 , 지식 함양 등 분명 도움될 거예요!   - GitHub - GimunLee/tech-refrigerator:   기술 냉장고입니다.   기술 면접 , 전공 시험 , 지식 함양 등 분명 도&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://bourbonkk.tistory.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://bourbonkk.tistory.com/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1676274067947&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;해커의 개발일기&quot; data-og-description=&quot;블로그에는 해킹과 취약점 내용, 개발하고 있는 부분들, 관심 있는 부분, 주식 분석 알고리즘(?) 같은 것들을 다룰 생각입니다.&quot; data-og-host=&quot;bourbonkk.tistory.com&quot; data-og-source-url=&quot;https://bourbonkk.tistory.com/&quot; data-og-url=&quot;https://bourbonkk.tistory.com&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cazlDA/hyRAoCcLeM/UOt6E5EcBhtL74Jg6wtoL0/img.jpg?width=721&amp;amp;height=961&amp;amp;face=370_367_595_526,https://scrap.kakaocdn.net/dn/yfcqH/hyRAcIxANm/ipEdGxBaJdORupQhYw6Wx1/img.jpg?width=721&amp;amp;height=961&amp;amp;face=370_367_595_526&quot;&gt;&lt;a href=&quot;https://bourbonkk.tistory.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://bourbonkk.tistory.com/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cazlDA/hyRAoCcLeM/UOt6E5EcBhtL74Jg6wtoL0/img.jpg?width=721&amp;amp;height=961&amp;amp;face=370_367_595_526,https://scrap.kakaocdn.net/dn/yfcqH/hyRAcIxANm/ipEdGxBaJdORupQhYw6Wx1/img.jpg?width=721&amp;amp;height=961&amp;amp;face=370_367_595_526');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;해커의 개발일기&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;블로그에는 해킹과 취약점 내용, 개발하고 있는 부분들, 관심 있는 부분, 주식 분석 알고리즘(?) 같은 것들을 다룰 생각입니다.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;bourbonkk.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://ssungwxx.github.io/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://ssungwxx.github.io/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1676274219970&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;SugnwooKim's place&quot; data-og-description=&quot; &quot; data-og-host=&quot;ssungwxx.github.io&quot; data-og-source-url=&quot;https://ssungwxx.github.io/&quot; data-og-url=&quot;https://ssungwxx.github.io&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://ssungwxx.github.io/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://ssungwxx.github.io/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;SugnwooKim's place&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;ssungwxx.github.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>[개발] 개인 프로젝트</category>
      <category>kantabile</category>
      <category>sonarkube</category>
      <category>sonarqube</category>
      <category>소나큐브</category>
      <category>칸타빌레</category>
      <author>kok202</author>
      <guid isPermaLink="true">https://kok202.tistory.com/355</guid>
      <comments>https://kok202.tistory.com/355#entry355comment</comments>
      <pubDate>Mon, 13 Feb 2023 16:50:16 +0900</pubDate>
    </item>
    <item>
      <title>2022년 프로젝트 회고</title>
      <link>https://kok202.tistory.com/354</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;관리를 거의하지 않는 티스토리이지만, 일기 겸 해서 2022년을 회고하며 올해는 목표를 얼마나 달성했는지 살펴보려고 합니다. 평상시에 거의 이런 짓을 하지 않지만, 어느 순간 개인들한테도 연말 행사처럼 이런 내용을 정리할 수 있는 기회가 있으면 좋겠다라는 생각을 했거든요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아무튼, 저는 매년 1월 첫째쯤해서 올해의 목표같은 것을 설정합니다. 이렇게 들으면 거창하지만 아래 그림을 보면 얼마나 볼품 없는지 아실겁니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-12-25 오후 7.37.47.png&quot; data-origin-width=&quot;504&quot; data-origin-height=&quot;540&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bHPjAj/btrUuiGxKmX/Gp8zaMut6FfF50aaQHT3B0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bHPjAj/btrUuiGxKmX/Gp8zaMut6FfF50aaQHT3B0/img.png&quot; data-alt=&quot;2022년의 목표&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bHPjAj/btrUuiGxKmX/Gp8zaMut6FfF50aaQHT3B0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbHPjAj%2FbtrUuiGxKmX%2FGp8zaMut6FfF50aaQHT3B0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;294&quot; height=&quot;315&quot; data-filename=&quot;스크린샷 2022-12-25 오후 7.37.47.png&quot; data-origin-width=&quot;504&quot; data-origin-height=&quot;540&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;2022년의 목표&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;돌이켜보니 그래도 달성률이 65%는 되는군요. (개발 서적은 7/10...!) 독립은 어떻게 했다치고! 일단 읽은 책부터 정리해볼게요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;올해 읽은 개발 서적&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;도메인 주도 설계 &lt;a href=&quot;https://kok202.tistory.com/342&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://kok202.tistory.com/342&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;테스트&amp;nbsp;주도&amp;nbsp;개발로&amp;nbsp;배우는&amp;nbsp;객체&amp;nbsp;지향&amp;nbsp;설계와&amp;nbsp;실천&amp;nbsp;&lt;a href=&quot;https://kok202.tistory.com/345&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://kok202.tistory.com/345&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;레거시 코드 활용 전략 &lt;a href=&quot;https://kok202.tistory.com/346&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://kok202.tistory.com/346&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;쏙쏙 들어오는 함수형 코딩 &lt;a href=&quot;https://kok202.tistory.com/347&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://kok202.tistory.com/347&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;오브젝트&amp;nbsp;디자인&amp;nbsp;스타일&amp;nbsp;가이드 &lt;a href=&quot;https://kok202.tistory.com/349&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://kok202.tistory.com/349&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;대규모 서비스를 지탱하는 기술&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;개발자의&amp;nbsp;글쓰기&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;올해 읽은 교양 서적&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;라프&amp;nbsp;코스터의&amp;nbsp;재미이론&lt;/li&gt;
&lt;li&gt;팩트풀니스&lt;/li&gt;
&lt;li&gt;실리콘밸리의&amp;nbsp;팀장들&lt;/li&gt;
&lt;li&gt;당신의&amp;nbsp;가격은&amp;nbsp;틀렸습니다&lt;/li&gt;
&lt;li&gt;애자일&amp;nbsp;&amp;amp;&amp;nbsp;스크럼&amp;nbsp;프로젝트&amp;nbsp;관리&lt;/li&gt;
&lt;li&gt;애자일, 민첩하고 유연한 조직의 비밀&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;개발 7년차, 매니저 1일차&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;열심히 읽었다고 생각했는데, 생각보다 많이 읽지는 못했던 것 같습니다. 연초의 목적은 개발 서적을 10권 읽는 것이었지만, 올해 읽은건 7권이네요. 아쉽게 달성하지는 못한 모습입니다. 하지만 목표를 새울 때 갯수 채우기에 급급해서 어거지로 책을 읽으려 했던 것은 아니니, 그냥 `개발 서적 10권 읽기` 목표도 그냥 달성한 것으로 체크했습니다.ㅋㅋㅋ 돌이켜보면 읽었던 책들이 모두 만족스럽고 충분히 내재화 되었다고 생각하니까요.&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;심리적으로 만족했으면 된거 아닐까요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;금년도에 읽었던 책들은 전부 다 괜찮았던 것 같습니다.  그래서 연말에 준비한 강의에도 많이 인용될 수 있었던 것 같고요. 블로그에 리뷰까지 남긴 책들은 정말 강력 추천하는 책들입니다. 개발하시는 분들 중에 무엇을 읽어야할지 고민이 되시는 분들이 계신다면, 위에 책들 중 하나쯤 사서 공부해보면, 후회하지 않으실 겁니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;교양 서적 같은 경우, 연말이 되면서는 주로 매니징과 관련된 책을 읽기 시작한 것 같습니다. 아무래도 현업을 하면서 부족하다고 생각하는 내용에 손이 가더라구요. 그래서 매니징 관련 책을 많이 읽게 된 것 같습니다. 문제는 &lt;span&gt;매니징과 관련된 내용은&lt;span&gt; 아무리 &lt;/span&gt;&lt;/span&gt;읽어도 체득된다는 느낌이 전혀 안든다는 점입니다.  &amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 매번 느끼는 거지만, 저는 이공계생이다보니 문학보다는 비문학이나 수필이 훨씬 재밌더라고요. 어렸을 때부터 소설 책을 추천해주는게 아니라 비문학 책을 부모님 추천해줬다면 책 읽는게 좀 더 습관화가 되었을것 같은데, 이건 좀 아쉬운 부분입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2022.05 사이드 프로젝트 (1) Duby 오픈&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://kok202.tistory.com/348&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://kok202.tistory.com/348&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1671964318981&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;Duby 를 오픈했습니다.&quot; data-og-description=&quot;Duby 기간 2021.11.01 ~ 진행중 https://duby.dev/ Duby duby.dev 오픈 그래프 태그가 빠져서 만들어진 링크가 예쁘진 않네요! 조만간 추가해야겠습니다. 이번 개인 프로젝트는 개발자들에게 필요한 툴킷을 모&quot; data-og-host=&quot;kok202.tistory.com&quot; data-og-source-url=&quot;https://kok202.tistory.com/348&quot; data-og-url=&quot;https://kok202.tistory.com/348&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/eYfsX/hyQ1qsvbVT/LWhmfSJosKbhPzd3REQih0/img.png?width=800&amp;amp;height=671&amp;amp;face=0_0_800_671,https://scrap.kakaocdn.net/dn/buSwj5/hyQ1lLub8F/MJLiMSwDaIP7h27MA1Hkzk/img.png?width=800&amp;amp;height=671&amp;amp;face=0_0_800_671,https://scrap.kakaocdn.net/dn/bH0PDd/hyQ1qsvb0h/G9YcxKqeUB4KSBYzXODM5k/img.png?width=2118&amp;amp;height=1778&amp;amp;face=0_0_2118_1778&quot;&gt;&lt;a href=&quot;https://kok202.tistory.com/348&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://kok202.tistory.com/348&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/eYfsX/hyQ1qsvbVT/LWhmfSJosKbhPzd3REQih0/img.png?width=800&amp;amp;height=671&amp;amp;face=0_0_800_671,https://scrap.kakaocdn.net/dn/buSwj5/hyQ1lLub8F/MJLiMSwDaIP7h27MA1Hkzk/img.png?width=800&amp;amp;height=671&amp;amp;face=0_0_800_671,https://scrap.kakaocdn.net/dn/bH0PDd/hyQ1qsvb0h/G9YcxKqeUB4KSBYzXODM5k/img.png?width=2118&amp;amp;height=1778&amp;amp;face=0_0_2118_1778');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Duby 를 오픈했습니다.&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Duby 기간 2021.11.01 ~ 진행중 https://duby.dev/ Duby duby.dev 오픈 그래프 태그가 빠져서 만들어진 링크가 예쁘진 않네요! 조만간 추가해야겠습니다. 이번 개인 프로젝트는 개발자들에게 필요한 툴킷을 모&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;kok202.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;회사 동기와 함께 개발했던 이 프로젝트는 무사히 마무리되어 서비스되고 있습니다. 아무래도 제가 필요하다 느끼는 기능을 개발해서 오픈한 것이다 보니, 저조차도 자주 들어가는 사이트라 만족도가 아주 높습니다. 종종 주변 개발자분들에게 추천드리는데, 다들 반응이 좋고, 업무할 때도 자주 참조하여 사용해주셔서, 개발하길 잘했다라는 생각을 들게 해주는 서비스 중 하나입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;firebase 통해 호스팅하고 있어서 돈도 거의 안나가는 혜자 프로젝트중 하나입니다 :)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2022.09 사이드 프로젝트 (2) 오픈 전 종료.&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결국 오픈하지 않았지만, 친구와 함께 개발하던 사이드 프로젝트가 하나 있었습니다. 거의 7월~9월 정도 이 서비스를 개발하기 위해 달렸던 것 같은데요. 대부분의 서비스가 그렇듯 아쉽게도 이 프로젝트는 세상의 빛을 보질 못했습니다. 나름 야심차게 준비했고, 아이디어도 괜찮다고 생각했는데, 최종 단계에 가서야 시장성이 없다는 생각이 들었던거죠.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그동안 해보지 않았던 방식으로 협업을 해봤는데, 협업을 하면서 좀 지쳤던 부분이 있어서, 당분간은 팀프로젝트를 하지 말아야겠다라는 생각을 했네요. 현재 개발중인 또 다른 사이드 프로젝트가 있는데, 이건 독고다이로 개발중인 프로젝트라 내년 중순에는 오픈하는 것을 목표로 달리고 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2022.11 Crowddeer 폐업&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-11-28 오전 11.04.12.png&quot; data-origin-width=&quot;3584&quot; data-origin-height=&quot;1756&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mqHXL/btrUvWwjfaZ/omo2wbqQk7jRJxsz80lveK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mqHXL/btrUvWwjfaZ/omo2wbqQk7jRJxsz80lveK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mqHXL/btrUvWwjfaZ/omo2wbqQk7jRJxsz80lveK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmqHXL%2FbtrUvWwjfaZ%2Fomo2wbqQk7jRJxsz80lveK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;3584&quot; height=&quot;1756&quot; data-filename=&quot;스크린샷 2022-11-28 오전 11.04.12.png&quot; data-origin-width=&quot;3584&quot; data-origin-height=&quot;1756&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쥐도새도 모르게 크라우드 디어는 폐업하였습니다. 역사의 뒤안길로 사라진 이 서비스는, 사실 DAU 가 1도 안나왔기 때문에...ㅋㅋㅋ 과감하게 접을 수 있었습니다. 사실 처음에는 접으려고 했던 것은 아닙니다. 서비스의 흥망성쇄는 둘째치고 이 사이트는 &quot;혼자서 이 정도까지 개발할 수 있다&quot;는 것을 보여주는 포토폴리오처럼 사용되고 있었기에, 그래도 왠만하면 유지하려 했거든요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 k8s에 인증서 관련된 에러가 잠깐 뜨길래, 수정하려고 들어갔는데, 갑자기 문득 생각이 드는 겁니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;이게 월간 10만원 정도를 써가면서 까지 유지해야하는건가...?&quot; 라는 생각이요. 사용하는 사람이 한 분이라도 계신다면 모르겠는데, &lt;span&gt;대체 누구를 위해 10만원씩 낭비하고 있는건지.&lt;span&gt; &lt;/span&gt;&lt;/span&gt;한 번 그런 생각이 드니 충동적으로 그냥 서비스를 접자라는 생각으로 이어졌네요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정말 돌이켜보면 아무도 사용하지 않는 서비스를 위해 별의별 기능을 다 고려해서 넣었던 것 같습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;자기들만의 위키를 만들 수도 있었고&lt;/li&gt;
&lt;li&gt;포토카드를 만들 수도 있었고&lt;/li&gt;
&lt;li&gt;비공개 카페를 만들 수도 있었고&lt;/li&gt;
&lt;li&gt;모은 포토카드를 편집할 수도 있는 대시보드도 지원했지요.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;s&gt;이럴거면 차라리 침하하 개발에 지원하는게 나았을지도...? &lt;/s&gt;이 사이트를 개발하고 운영하면서 새삼 느꼈습니다. &lt;b&gt;사용자가 없는 서비스는 아무런 비즈니스 밸류를 전달하지 못한다는&lt;/b&gt;. 근본적이면서도 핵심적인 내용을요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2022.12 인프런 강의 오픈&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://kok202.tistory.com/353&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://kok202.tistory.com/353&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1671964350223&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;Java/Spring 주니어 개발자를 위한 오답노트&quot; data-og-description=&quot;인프런에 강의를 하나 올리게 되서 홍보차 글을 작성하네요! 올해의 버킷 리스트중 하나로 강의를 하나 찍어서 올리는 게 있었는데요. 연말이 가기 전에 어떻게 마무리해서 결국 오픈하게 됐습&quot; data-og-host=&quot;kok202.tistory.com&quot; data-og-source-url=&quot;https://kok202.tistory.com/353&quot; data-og-url=&quot;https://kok202.tistory.com/353&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/jB8bU/hyQ1sjzKuG/DqE9vsF3kg6lhFDFtsj661/img.png?width=800&amp;amp;height=520&amp;amp;face=0_0_800_520,https://scrap.kakaocdn.net/dn/clDaj1/hyQ1dmp4gj/zsiNdkkTnVgYkzxXqKIudk/img.png?width=800&amp;amp;height=520&amp;amp;face=0_0_800_520&quot;&gt;&lt;a href=&quot;https://kok202.tistory.com/353&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://kok202.tistory.com/353&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/jB8bU/hyQ1sjzKuG/DqE9vsF3kg6lhFDFtsj661/img.png?width=800&amp;amp;height=520&amp;amp;face=0_0_800_520,https://scrap.kakaocdn.net/dn/clDaj1/hyQ1dmp4gj/zsiNdkkTnVgYkzxXqKIudk/img.png?width=800&amp;amp;height=520&amp;amp;face=0_0_800_520');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Java/Spring 주니어 개발자를 위한 오답노트&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;인프런에 강의를 하나 올리게 되서 홍보차 글을 작성하네요! 올해의 버킷 리스트중 하나로 강의를 하나 찍어서 올리는 게 있었는데요. 연말이 가기 전에 어떻게 마무리해서 결국 오픈하게 됐습&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;kok202.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러던 중 다행히도 올해 중순부터 준비하던 인터넷 강의는 어찌저찌해서 오픈할 수 있게 됬습니다. 강의 소개에서도 작성되어 있지만, 이 강의는 제가 그동안 많은 주니어분들을 만나면서 해왔던 문답들을 모아둔거라, 진짜 나름 칼을 갈고 만든 강의입니다. 이게 얼마나 팔리고 수강생들한테 어떤 가치를 전달해줄 지는 아직 물음표가 있지만, 그래도 많은 분들이 수강해주셔서 조금이라도 도움이 되었으면 하네요. :)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 강의와 관련해서는 비하인드 스토리가 많습니다. 하지만 이걸 구구절절 다 풀기에는 배경 설명도 해야하고 너무 길어지니 나중에 기회가 될 때 강의가 나오게 된 배경부터 어떻게 만들어졌는지를 풀어볼 수 있도록 할게요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;계속 미루고 미루다가 11월 말이 되서야 MD와 미팅하고, 내용을 진행했었습니다. 어떻게해서든 12월에는 오픈하고 싶었기에, 급박한 일정에 맞춰 작업을 도와준 인프런 MD님과 영상 편집을 도와준 우리 편집자님, 너무 감사합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2022.현재&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재의 저는 새로운 사이드 프로젝트를 시작했습니다. 이번에는 초심으로 돌아가 제가 원래 하고 싶었던 게임 개발을 해볼 생각입니다. 원래는 이것도 3개월을 예정해두고 시작한 프로젝트인데, 얼마나 밀릴지, 오픈은 할 수 있을지도 의문이네요. 아직까지는 무언가를 만드는게 너무나 재밌기 때문에 내년도 목표에서도 사이드 프로젝트 2개 오픈은 그대로 있지 않을까 싶습니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어느덧 2022년도 끝나갑니다. 그동안 무얼했나 생각도 들면서, 돌이켜보니 은근 많은 일을 했네요. 나이 먹으면 시간이 빨리간다고 느끼는게 어떤 건지도 알 것 같다는 생각이 듭니다. 몇이나 이 글을 읽을지 모르겠지만, 22년 고생하셨습니다. 다들 연말 잘 마무리하시고 23년에는 더 좋은 일로 가득하길 바랍니다.&lt;/p&gt;</description>
      <category>[개발] 기록/기록</category>
      <category>2022년</category>
      <category>강의</category>
      <category>백엔드</category>
      <category>스프링</category>
      <category>인프런</category>
      <category>주니어</category>
      <author>kok202</author>
      <guid isPermaLink="true">https://kok202.tistory.com/354</guid>
      <comments>https://kok202.tistory.com/354#entry354comment</comments>
      <pubDate>Sun, 25 Dec 2022 20:21:06 +0900</pubDate>
    </item>
    <item>
      <title>Java/Spring 주니어 개발자를 위한 오답노트</title>
      <link>https://kok202.tistory.com/353</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;인프런에 강의를 하나 올리게 되서 홍보차 글을 작성하네요!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;올해의 버킷 리스트중 하나로 강의를 하나 찍어서 올리는 게 있었는데요. &lt;br /&gt;연말이 가기 전에 어떻게 마무리해서 결국 오픈하게 됐습니다. :) &lt;br /&gt;그리하여 홍보차 글쓰기 위해 전단지를 돌리는 중인데, 관심 있으신 분들은 오셔서 한번 씩 봐주시고 가시면 감사하겠습니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;초급자를 위해 준비한 [백엔드, 개발 &amp;middot; 프로그래밍] 강의이고요.&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=PAYouphJvT4&amp;amp;ab_channel=woogeunkim&quot;&gt;https://www.youtube.com/watch?v=PAYouphJvT4&amp;amp;ab_channel=woogeunkim&lt;/a&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignCenter&quot; data-video-host=&quot;youtube&quot; data-video-url=&quot;https://www.youtube.com/watch?v=PAYouphJvT4&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/LRgPO/hyQ1dfC0vG/lEWJ0jkdiGr2RozhZZl0P1/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=0_0_1280_720&quot; data-video-width=&quot;860&quot; data-video-height=&quot;484&quot; data-video-origin-width=&quot;860&quot; data-video-origin-height=&quot;484&quot; data-ke-mobilestyle=&quot;widthContent&quot;&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/PAYouphJvT4&quot; width=&quot;860&quot; height=&quot;484&quot; frameborder=&quot;&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;figcaption&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래와 같은 내용을 다룹니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;주니어 개발자가 많이 하는 실수 교정 &lt;/b&gt;&lt;/li&gt;
&lt;li&gt;주니어 개발자가 스프링을 쓰면서 많이 하는 실수 교정&lt;/li&gt;
&lt;li&gt;의존성 / Entity 등에 대한 잘못된 오해 교정&lt;/li&gt;
&lt;li&gt;실무에 필요한 개념 정리 (MSA, ACL 등)&lt;/li&gt;
&lt;li&gt;백엔드 개발자에게 필요한 인프라 / 네트워크 개념 정리&lt;/li&gt;
&lt;li&gt;&lt;span&gt;스프링 환경에서 객체 지향적인 코드를 짜는 법 (TDA 등)&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;스프링 및 JPA를 다룰 줄 알게된 주니어 개발자 1~3년차를 대상으로 하는 강의라서, 실무에 도움이 될 만한 내용으로 준비했습니다!&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상세한 내용은 강의 소개 페이지에 작성해둬서, 길게 적어두지 않으려합니다. 성장을 빠르게 하고 싶은&amp;nbsp; 주니어들을 위한 경험치 스타트 부스트팩이라고 봐주시면 좋겠네요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;강의로 바로가기 &lt;a href=&quot;https://inf.run/SrgW&quot;&gt;https://inf.run/SrgW&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1671963013162&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Java/Spring&amp;nbsp;주니어 개발자를&amp;nbsp;위한 오답노트 - 인프런 | 강의&quot; data-og-description=&quot;스프링이랑 JPA를 조금 다룰 줄 알게 된 당신, 앞으로 성장하기 위해 무엇을 어떻게 공부해야 할까요? 혹시 설계 공부를 해보겠다고 디자인 패턴을 공부하면서 패턴들을 무작정 암기하고 계시진 &quot; data-og-host=&quot;www.inflearn.com&quot; data-og-source-url=&quot;https://inf.run/SrgW&quot; data-og-url=&quot;https://www.inflearn.com/course/%EC%9E%90%EB%B0%94-%EC%8A%A4%ED%94%84%EB%A7%81-%EC%A3%BC%EB%8B%88%EC%96%B4-%EA%B0%9C%EB%B0%9C%EC%9E%90-%EC%98%A4%EB%8B%B5%EB%85%B8%ED%8A%B8?inst=28a980f0&amp;amp;utm_source=instructor&amp;amp;utm_medium=referral&amp;amp;utm_campaign=inflearn_%ED%8A%B8%EB%9E%98%ED%94%BD_promotion-link&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/b8wlFz/hyQ1pG8qZT/WVwYWerdotQW17CAlCtEn0/img.png?width=1200&amp;amp;height=781&amp;amp;face=0_0_1200_781,https://scrap.kakaocdn.net/dn/CDKZ6/hyQ1sRoClg/9cvzcuV9WGD5PmyJFmFeN0/img.png?width=1200&amp;amp;height=781&amp;amp;face=0_0_1200_781,https://scrap.kakaocdn.net/dn/c1By8O/hyQ1lxYlLQ/N5YEVhJoLQkIfgNmKqtgT0/img.png?width=1380&amp;amp;height=1356&amp;amp;face=0_0_1380_1356&quot;&gt;&lt;a href=&quot;https://inf.run/SrgW&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://inf.run/SrgW&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/b8wlFz/hyQ1pG8qZT/WVwYWerdotQW17CAlCtEn0/img.png?width=1200&amp;amp;height=781&amp;amp;face=0_0_1200_781,https://scrap.kakaocdn.net/dn/CDKZ6/hyQ1sRoClg/9cvzcuV9WGD5PmyJFmFeN0/img.png?width=1200&amp;amp;height=781&amp;amp;face=0_0_1200_781,https://scrap.kakaocdn.net/dn/c1By8O/hyQ1lxYlLQ/N5YEVhJoLQkIfgNmKqtgT0/img.png?width=1380&amp;amp;height=1356&amp;amp;face=0_0_1380_1356');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Java/Spring&amp;nbsp;주니어 개발자를&amp;nbsp;위한 오답노트 - 인프런 | 강의&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;스프링이랑 JPA를 조금 다룰 줄 알게 된 당신, 앞으로 성장하기 위해 무엇을 어떻게 공부해야 할까요? 혹시 설계 공부를 해보겠다고 디자인 패턴을 공부하면서 패턴들을 무작정 암기하고 계시진&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.inflearn.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>[개발] 개인 프로젝트</category>
      <category>Spring</category>
      <category>강의</category>
      <category>백엔드</category>
      <category>스프링</category>
      <category>인프런</category>
      <category>자바</category>
      <category>주니어</category>
      <author>kok202</author>
      <guid isPermaLink="true">https://kok202.tistory.com/353</guid>
      <comments>https://kok202.tistory.com/353#entry353comment</comments>
      <pubDate>Sun, 25 Dec 2022 19:12:50 +0900</pubDate>
    </item>
    <item>
      <title>앵귤러 강의 정리</title>
      <link>https://kok202.tistory.com/351</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;회사 업무중 앵귤러를 다뤄야하는 프로젝트가 생겨 아래 강의를 듣고 정리합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.inflearn.com/course/Angular/dashboard&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://www.inflearn.com/course/Angular/dashboard&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1656767543029&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;[무료] Angular(2+) Front에서 Back까지 - Nest js를 알려면 Angular 모듈을 알아야한다! - 인프런 | 강의&quot; data-og-description=&quot;이 강좌는 Angular의 기본 개념을 익히는데 그 목적을 두고 있습니다. Nest js도 잘 하려면 이 기본 개념을 알아야하죠. Angular는 러닝커브가 높다고들 이야기가 되곤하는데, 전혀 어렵지 않음을 알려&quot; data-og-host=&quot;www.inflearn.com&quot; data-og-source-url=&quot;https://www.inflearn.com/course/Angular/dashboard&quot; data-og-url=&quot;https://www.inflearn.com/course/Angular&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cNPsQQ/hyOYsZIPpM/QqlNdScyIaWUkvxCx7ohp1/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/FU4Au/hyOW2avql3/A7BEn1kMhGScZYD1WvslEk/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/dpYEVA/hyOYhcO4ya/1KKhWLCSHHNkfDXgbifdmK/img.png?width=1200&amp;amp;height=781&amp;amp;face=0_0_1200_781&quot;&gt;&lt;a href=&quot;https://www.inflearn.com/course/Angular/dashboard&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.inflearn.com/course/Angular/dashboard&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cNPsQQ/hyOYsZIPpM/QqlNdScyIaWUkvxCx7ohp1/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/FU4Au/hyOW2avql3/A7BEn1kMhGScZYD1WvslEk/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/dpYEVA/hyOYhcO4ya/1KKhWLCSHHNkfDXgbifdmK/img.png?width=1200&amp;amp;height=781&amp;amp;face=0_0_1200_781');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[무료] Angular(2+) Front에서 Back까지 - Nest js를 알려면 Angular 모듈을 알아야한다! - 인프런 | 강의&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;이 강좌는 Angular의 기본 개념을 익히는데 그 목적을 두고 있습니다. Nest js도 잘 하려면 이 기본 개념을 알아야하죠. Angular는 러닝커브가 높다고들 이야기가 되곤하는데, 전혀 어렵지 않음을 알려&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.inflearn.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;@Input&lt;/h3&gt;
&lt;pre id=&quot;code_1656767634604&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 리액트로 치면 Props 에 대응되는 개념인 듯.
@Component(...)
class MyComponent {
    @Input test: string;
}

// 외부에서는 []=으로 입력
&amp;lt;my-component [test]=&quot;helloworld&quot;/&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;@Output&lt;/h3&gt;
&lt;pre id=&quot;code_1656767780621&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 흔히보는 event dispatcher
@Component(...)
class MyComponent {
    @Output myEvent: new EventEmitter();
}

// 외부에서는 ()=으로 입력
&amp;lt;my-component [myEvent]=&quot;myEventListener($event)&quot;/&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;생명 주기&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ngOnChanges&lt;/li&gt;
&lt;li&gt;ngOnInit&lt;/li&gt;
&lt;li&gt;ngDoCheck&lt;/li&gt;
&lt;li&gt;ngAfterContentInit&lt;/li&gt;
&lt;li&gt;ngAfterContentChecked&lt;/li&gt;
&lt;li&gt;ngAfterViewInit&lt;/li&gt;
&lt;li&gt;ngAfterViewChecked&lt;/li&gt;
&lt;li&gt;ngDestroy&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;ngOnChanges&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;앵귤러 컴포넌트의 Lifecycle 중 하나&lt;/li&gt;
&lt;li&gt;@Input 데이터가 변경될 경우 실행됨&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;앵귤러 모듈시스템&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;delcaration: const, 컴포넌트를 생성, 앵귤러 모듈이 컴포넌트를 사용할 수 있겠끔 함. (하나의 컴포넌트는 하나의 모듈에만 선언될 수 있음.)&lt;/li&gt;
&lt;li&gt;exports: 컴포넌트를 노출&lt;/li&gt;
&lt;li&gt;imports: 모듈을 import&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;router-outlet&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;app-routing-module 에 의해 match 되는 컴포넌트가 보이는 부분&lt;/li&gt;
&lt;li&gt;RouterModule.for(~): 이런 path 일 때 router-outlet 에 ~ 을 보여줘라&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;라우팅&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;[routerLink]: RouterModule 을 import 할 때 사용할 수 있는 anchor attribute&lt;/li&gt;
&lt;li&gt;Router 를 주입받아 router.navigateByUrl 을 사용&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;메소드 바인딩&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;{{메소드}}&lt;/li&gt;
&lt;li&gt;메소드 바인딩은 비추천.&lt;/li&gt;
&lt;li&gt;성능에 영향을 줌.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;서비스&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;@Injectable: 서비스를 정의&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;서비스 주입 방법&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;방법 1. @Components({providers}) 상위 레벨에서만 의존성 주입을 해주는지 확인.&lt;/li&gt;
&lt;li&gt;방법 2. @NgModule({providers}) Component 레벨의 providing 은 서비스를 계속 생성하게됨. Module 수준으로 관리하여 서비스를 독립적으로 유지가능.&lt;/li&gt;
&lt;li&gt;방법 3. @Injectable({providedIn}) 특정 모듈에 서비스를 주입 시켜 놓음. (권장)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Injector 의 검색순서&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;자신의 컴포넌트&lt;/li&gt;
&lt;li&gt;부모 컴포넌트&lt;/li&gt;
&lt;li&gt;루트 컴포넌트 까지 계속 부모-자식 관계를 타고 올라감&lt;/li&gt;
&lt;li&gt;루트 모듈&lt;/li&gt;
&lt;li&gt;하위 모듈&lt;/li&gt;
&lt;li&gt;자신이 속한 모듈까지 계속 내려옴&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결과적으로 가장 먼저 만나게되는 inject 되는 값을 사용하게됨.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;ng-content&lt;/h3&gt;
&lt;div&gt;
&lt;div&gt;&lt;span style=&quot;color: #24292f;&quot;&gt;props.children&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt; 에 대응되는 값인 듯&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;</description>
      <category>[정리] 직무별 개념 정리/프론트엔드</category>
      <author>kok202</author>
      <guid isPermaLink="true">https://kok202.tistory.com/351</guid>
      <comments>https://kok202.tistory.com/351#entry351comment</comments>
      <pubDate>Sat, 2 Jul 2022 22:32:04 +0900</pubDate>
    </item>
    <item>
      <title>오브젝트 디자인 스타일 가이드 (2/2) CQRS, 추상화, 이벤트, 책임</title>
      <link>https://kok202.tistory.com/350</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;http://www.yes24.com/Product/Goods/91167539&quot;&gt;http://www.yes24.com/Product/Goods/91167539&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1654506632988&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;book&quot; data-og-title=&quot;오브젝트 디자인 스타일 가이드 - YES24&quot; data-og-description=&quot;잘 작성한 객체지향 코드는 읽고 변경하고 디버그하기 즐겁다. 이 책에서 보여주는 객체 디자인에 대한 보편적 모범 사례를 익혀 코딩 스타일을 향상하자. 이 명확한 규칙은 어떤 객체지향 언어&quot; data-og-host=&quot;www.yes24.com&quot; data-og-source-url=&quot;http://www.yes24.com/Product/Goods/91167539&quot; data-og-url=&quot;http://www.yes24.com/Product/Goods/91167539&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bWQDak/hyOFCPpCDc/I4hBXLwVyemJ6KDEwf3SmK/img.jpg?width=940&amp;amp;height=1200&amp;amp;face=433_339_483_393,https://scrap.kakaocdn.net/dn/4TEFT/hyOFvpeHdl/zrjCvC3tDJOfA1pMfQwYk1/img.jpg?width=940&amp;amp;height=1200&amp;amp;face=433_339_483_393,https://scrap.kakaocdn.net/dn/bZkQm8/hyOFCaNngA/E7gp1VxWUVXrRcDRWcvQk1/img.jpg?width=940&amp;amp;height=1200&amp;amp;face=433_339_483_393&quot;&gt;&lt;a href=&quot;http://www.yes24.com/Product/Goods/91167539&quot; data-source-url=&quot;http://www.yes24.com/Product/Goods/91167539&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bWQDak/hyOFCPpCDc/I4hBXLwVyemJ6KDEwf3SmK/img.jpg?width=940&amp;amp;height=1200&amp;amp;face=433_339_483_393,https://scrap.kakaocdn.net/dn/4TEFT/hyOFvpeHdl/zrjCvC3tDJOfA1pMfQwYk1/img.jpg?width=940&amp;amp;height=1200&amp;amp;face=433_339_483_393,https://scrap.kakaocdn.net/dn/bZkQm8/hyOFCaNngA/E7gp1VxWUVXrRcDRWcvQk1/img.jpg?width=940&amp;amp;height=1200&amp;amp;face=433_339_483_393');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;오브젝트 디자인 스타일 가이드 - YES24&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;잘 작성한 객체지향 코드는 읽고 변경하고 디버그하기 즐겁다. 이 책에서 보여주는 객체 디자인에 대한 보편적 모범 사례를 익혀 코딩 스타일을 향상하자. 이 명확한 규칙은 어떤 객체지향 언어&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.yes24.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;코드 레벨에 대한 설명이 많아 이는 생략하고 보편적인 가치 위주로 정리합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; ) 은 사견입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;변경 메소드가 반환 값을 갖게 하지마라&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;변경과 반환이 둘다 있으면 클라이언트 입장에서 혼란스럽다.&lt;/li&gt;
&lt;li&gt;메소드는 항상 명령 메소드 이거나 질의 메소드 이어야한다. (CQRS)&lt;/li&gt;
&lt;li&gt;테스트를 위해 종종 command 메소드가 return this 를 하는 경우도 있는데, 이것도 피해야할 패턴중 하나다. 명령 메소드의 반환 타입은 void 여야한다는 규칙을 위반한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;변경 메소드 on VO&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;VO 의 명령 메소드는 서술형이어야한다.&lt;/p&gt;
&lt;pre id=&quot;code_1654506632991&quot; class=&quot;actionscript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 이것보다
final class Position
{
    public function moveLeft(int steps): Position
    {
    }
}

// 이게 낫다
final class Position
{
    public function toTheLeft(int steps): Position
    {
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(  moveLeft는 속성을 변경할 것 같지만, toTheLeft는 새로운 값이 될것 같음을 암시한다. 메소드 이름을 전치사로 시작해보려 하면 좋을 듯하다)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;변경 메소드 on Entity&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Entity 는 VO 와 다르게 조작을 허용하는 메소드가 있다.&lt;/li&gt;
&lt;li&gt;변경 가능 객체의 변경 메소드는 명령 메소드이어야한다. (반환 값이 void 타입의 메소드)&lt;/li&gt;
&lt;li&gt;변경 메소드는 상태 변경 요청이 유효한지까지 확인해야한다.&lt;/li&gt;
&lt;li&gt;변경 메소드의 테스트는 테스트를 위해 getter 를 만들지 말고 event record 방식으로 검증해라.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1654506632991&quot; class=&quot;reasonml&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public function moveLeft_테스트(): void
{
    // given
    player = new Player(new Position(10, 20));
    
    // when
    player.moveLeft(4);
    
    // then
    assertTrue(player.recordedEvents().contains(new PlayerMoved(new Position(6, 20))));
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Fluent interface&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;변경 가능한 객체에는 fluent interface 를 구현하지 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(  fluent interface 에서 체이닝을 위해 반환할 경우 변경가능한 객체를 반환해서는 안된다.)&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1654506632992&quot; class=&quot;n1ql&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;queryBuilder = QueryBuilder.create(); // fluent interface 를 이렇게 사용할 경우

qb1 = queryBuilder 
    .select(/* ... */)
    .from(/* ... */)
    .where(/* ... */)
    .orderBy(/* ... */);

qb2 = queryBuilder // 제대로 동작할지 예측할 수 없다.
   .select(/* ... */)
   .from(/* ... */)
   .where(/* ... */)
   .orderBy(/* ... */);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;CQRS&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;메소드는 항상 명령 메소드 이거나 질의 메소드 이어야한다.&lt;/li&gt;
&lt;li&gt;명령 메소드는 반환 타입이 void 여야한다.&lt;/li&gt;
&lt;li&gt;명령 메소드의 이름은 클라이언트가 객체에 나타내는 작업을 수행하기 지시할 수있는 명령형 이름을 사용하는 것이 좋다.&lt;/li&gt;
&lt;li&gt;명령 메소드가 너무 많은 일을 하지 않는 것이 좋다. 부차적인 작업이 있다면 유효 범위를 제한하고 이벤트를 pub/sub 하는 것이 좋다.&lt;/li&gt;
&lt;li&gt;질의 메소드는 반환 타입이 단일 타입이어야한다.&lt;/li&gt;
&lt;li&gt;데이터 수집에는 질의 메소드를 사용하고 다음 단계로 진행할 때는 명령 메소드를 사용한다.&lt;/li&gt;
&lt;li&gt;항상 CQRS 가 해답인 것은 아니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;이벤트&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이벤트를 사용한 설계는 다음과 같은 장점이 있다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;원본 메소드를 변경하지 않고도 더 많은 부수 효과를 추가할 수 있다.&lt;/li&gt;
&lt;li&gt;부수적인 효과에만 필요한 의존성을 원본 객체에 주입하지 않으므로 원본 객채를 더욱 분리할 수 있다.&lt;/li&gt;
&lt;li&gt;원한다면 백그라운드 프로세스에서 부수 효과를 처리할 수 있다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;시스템 경계&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시스템 경계를 넘는 명령에는 추상화를 정의한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;find vs get&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메소드 이름으로 불확실성을 보여주기 위해 find 를 쓸 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;get 접두어를 남발하지 마라.&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;get 접두어는 갖고 있는 정보를 제공한다는 의미다. 찾아오라는 지시가 아니다.&lt;/p&gt;
&lt;pre id=&quot;code_1654506632993&quot; class=&quot;angelscript&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Products {
    public int sumPrice() {
        return this.products.stream().mapToLong(Product::getPrice).sum();
    }
}

class Products {
    // BAD
    public int getSumPrice() {
        return this.products.stream().mapToLong(Product::getPrice).sum();
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Mock 프레임워크&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;⭐⭐⭐ &lt;b&gt;Mock framework 는 일반적으로 좋은 디자인이 나오는 것을 방해한다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반복적인 코드 몇 줄을 줄일 수 있지만 코드를 읽고 유지하기 어려운 비용이 생긴다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;명령 메소드 호출은 Mock 으로만 검증한다.&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;명령 메소드가 다른 명령 메소드를 호출할 때는 후자를 Mock 으로 만드는 것이 좋다. 명령을 적어도 한 번은 호출해야 한다 하더라도 두 번 이상 호출해서는 안된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;테스트 대역의 분류&lt;/h3&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 104px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style8&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;width: 19.2635%; height: 19px;&quot;&gt;사용처&lt;/td&gt;
&lt;td style=&quot;width: 12.0543%; height: 19px;&quot;&gt;이름&lt;/td&gt;
&lt;td style=&quot;width: 68.6821%; height: 19px;&quot;&gt;설명&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 19.2635%; height: 51px;&quot; rowspan=&quot;3&quot;&gt;질의 메소드에 사용&lt;/td&gt;
&lt;td style=&quot;width: 12.0543%; height: 17px;&quot;&gt;Dummy&lt;/td&gt;
&lt;td style=&quot;width: 68.6821%; height: 17px;&quot;&gt;타입만 바른 비기능 객체&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 12.0543%; height: 17px;&quot;&gt;Stub&lt;/td&gt;
&lt;td style=&quot;width: 68.6821%; height: 17px;&quot;&gt;타입이 올바르고 지정된 값을 반환하는 객체&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 12.0543%; height: 17px;&quot;&gt;Fake&lt;/td&gt;
&lt;td style=&quot;width: 68.6821%; height: 17px;&quot;&gt;타입이 올바르고 자체 논리가 있는 객체&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 19.2635%; height: 34px;&quot; rowspan=&quot;2&quot;&gt;명령 메소드에 사용&lt;/td&gt;
&lt;td style=&quot;width: 12.0543%; height: 17px;&quot;&gt;Mock&lt;/td&gt;
&lt;td style=&quot;width: 68.6821%; height: 17px;&quot;&gt;메소드 호출을 확인하기 위한 객체&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 12.0543%; height: 17px;&quot;&gt;Spy&lt;/td&gt;
&lt;td style=&quot;width: 68.6821%; height: 17px;&quot;&gt;메소드 호출을 나중에 확인하기 위한 객체 (호출된 내용을 기록함)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(  이 5가지에 대해서는 항상 포스팅이나 책마다 내용이 조금씩 달라서 혼란스러운데, 일단 이 책의 정의가 제일 단순하고 와닿는 듯.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;책임 나누기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;읽기와 쓰기 모델을 분리한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Entity를 변경할 권한이 없는 클라이언트에 변경할 수 있는 Entity 를 전달해서는 절대 안된다. 이렇게되면 어느날 갑자기 클라이언트가 Entity를 수정하려할 수도 있다. 이는 결국 프로그램에 일어난 일을 파악하기 어렵게 만든다. 디자인 개선을 위해 가장 먼저 해야할 일이 쓰기 모델과 읽기 모델을 분리해야하는 이유다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;읽기 모델과 쓰기 모델을 분리하는 과정&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1590&quot; data-origin-height=&quot;1536&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ziSuI/btrD0r7B26Y/mOLYKlRbiUx6j2Z2mzgN7K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ziSuI/btrD0r7B26Y/mOLYKlRbiUx6j2Z2mzgN7K/img.png&quot; data-alt=&quot;책임을 분리하는 과정을 Step by step 으로 나눔.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ziSuI/btrD0r7B26Y/mOLYKlRbiUx6j2Z2mzgN7K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FziSuI%2FbtrD0r7B26Y%2FmOLYKlRbiUx6j2Z2mzgN7K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1590&quot; height=&quot;1536&quot; data-origin-width=&quot;1590&quot; data-origin-height=&quot;1536&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;책임을 분리하는 과정을 Step by step 으로 나눔.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;읽기 모델은 쓰기 모델에서 직접 생성할 수 있다. 하지만 더 효율적인 방법은 쓰기 모델에서 사용하는 데이터 근원에서 생성하는 것이다. 이렇게 할 수 없거나 읽기 모델을 효율적인 방법으로 생성할 수 없으면 도메인 이벤ㅌ를 사용해 오랜 시간에 걸쳐 읽기 모델을 구축한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;이벤트 소싱&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;읽기 모델을 구축하는 데 이벤트를 사용하는 것 외에도 쓰기 모델을 재구성하는데 이벤트를 사용하면 상황이 훨씬 더 복잡해진다. 이 기법을 이벤트 소싱이라 하는데, 쓰기 모델과 읽기 모델을 분리하는 발상에는 매우 잘 들어맞으나 객체 사이에 책임을 나누는 더 좋은 방법만 찾는다면 굳이 필요하지는 않다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;서비스 행위 변경하기&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;클래스를 변경하는 일반적인 대안은 매소드를 재정의하는 것인데, 이는 더 많은 문제를 일으킬 수 있다.&lt;/li&gt;
&lt;li&gt;일반적으로 클래스 코드 대신 객체 그래프 구조를 변경하는게 더 낫다.&lt;/li&gt;
&lt;li&gt;일부를 변경하는 것보다 대체하는 게 더 낫다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;상속을 지양해라.&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;흔히 코드를 재사용하기 위해 상속을 사용하지만 코드를 재사용하는 데 더 강력한 형태는 Composition 이다. 하지만 경우에 따라 의존성 주입을 지원하지 못하는 경우라면 trait 을 사용하길 권한다. trait 은 평범한 코드 재사용, 즈 컴파일러 수준의 코드 복사/붙여넣기다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(  서비스 행위를 변경하고 싶다면 상속보다 추상화된 Comosition 을 사용하자)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(  상속은 리스코프 치환 원칙을 고려하면서 진행되야한다. 굳이 어려운 치환 원칙까지 고려해서 상속할 생각하기보다 그냥 Composition 을 사용해라.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;클래스는 기본적으로 final 로 선언해라.&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;서비스는 클래스를 fianl 로 표시해야함을 이미 주장했다. 상속대신 객체 구성을 사용해 행위를 변경하는게 더 좋고 유연한 방법이다.&lt;/li&gt;
&lt;li&gt;Entity, VO 와 마찬가지로 다른 객체 타입에도 유사한 질문을 해야한다. final 이어야할까? 그래야한다.&lt;/li&gt;
&lt;li&gt;이 규칙의 유일한 예외는 객체 상속 계통을 선언할 때다. 이때는 부모 클래스를 확장해 이런 객체 사이 관계를 나타낼 수 있다.&lt;/li&gt;
&lt;li&gt;그리고 공개 인터페이스가 아닌 모든 메소드는 private 으로 만들어라.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;이벤트 디스패처&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이벤트 디스패처 방식을 사용할 때 장점은 기존 논리를 변경하지 않고 서비스에 행위를 추가할 수 있다는 점이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이벤트 디스패처를 사용할 때 단점은 이름이 매우 일반적이라는 점인데, 이벤트를 발행할 때 하는 dispatch 라는 메소드가 이면에 어떤일이 일어나는지를 명확하게 하지 못한다. 또한 어떤 이벤트에 어느 subscriber 가 응답하는지 알아내는 것이 어려울 수도 있다. 대안은 추상화를 도입하는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;추상화 vs 구현체&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Controller -&amp;gt; concrete&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Service -&amp;gt; concrete&lt;/li&gt;
&lt;li&gt;Entity, VO -&amp;gt; concrete&lt;/li&gt;
&lt;li&gt;Repository -&amp;gt; interface&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;기타&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;객체에 담긴 데이터를 상태라고도 한다.&lt;/li&gt;
&lt;li&gt;SUT (Subject undert test): 테스트할 대상 ( : System under test 가 좀 더 보편적인 어휘인 듯)&lt;/li&gt;
&lt;li&gt;규칙을 따른 넋이 중요하지만 품질이 그리 중요하지 않은 예외적인 상황에는 유연하게 임한다. 때로는 공들인 만큼 보상이 따르지 않을 수 있디 때문이다.&lt;/li&gt;
&lt;li&gt;대부분의 개발자는 객체가 아니라 클래스를 테스트하는 경향이 있다. 객체를 테스트하라. 클래스 테스트는 클래스 자체가 바뀔 때마다 항상 바뀐다. 객체 테스트는 테스트하는 객체의 구현 내용과 더욱 분리되어 있다. 객체 테스트가 장기적으로 유용하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;서평&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서비스란 무엇인가에대한 생각이 많이 담긴 책이었습니다. 목차만 읽어도 도움되는 내용이 많은 책이라고 생각합니다. 자바랑 스프링에 대한 내용은 한번도 언급하지 않는데, 오히려 스프링을 이해하는데 더 도움을 주었습니다. 매번 설계 관련 책을 읽을 때마다 느끼는 것은 DDD, TDD, 함수형 프로그래밍들이 사실 OOP 하나를 바라보고 있다는 것입니다. 전혀 기대 안했는데, 근래에 읽은 책중에 또 영감을 많이 준 책이라 감명 받아 정리글을 남깁니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래는 원서를 공개한 것으로 추정되는 사이트인데요. 영어를 잘하신다면 여기서도 읽을 수 있을 것 같아 좋아보입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.manning.com/books/object-design-style-guide&quot;&gt;https://www.manning.com/books/object-design-style-guide&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1654506632995&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Object Design Style Guide&quot; data-og-description=&quot;Elevate your coding style by mastering the universal best practices for object design. Explore techniques for creating pro-quality OO code that can stand the test of time.&quot; data-og-host=&quot;www.manning.com&quot; data-og-source-url=&quot;https://www.manning.com/books/object-design-style-guide&quot; data-og-url=&quot;https://www.manning.com/books/object-design-style-guide&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/gckDw/hyOFEmb3ZC/lUInnOdXYMLn5K7LHJNUwK/img.jpg?width=360&amp;amp;height=451&amp;amp;face=250_78_274_104,https://scrap.kakaocdn.net/dn/czfBkl/hyOFx1F8IX/agzTTXkZVHKMPqhukbhLxk/img.jpg?width=360&amp;amp;height=451&amp;amp;face=250_78_274_104,https://scrap.kakaocdn.net/dn/bRV6mh/hyOFDgvFBR/AjaTchz8eNK0vscfKBAK4K/img.jpg?width=264&amp;amp;height=331&amp;amp;face=179_55_204_82&quot;&gt;&lt;a href=&quot;https://www.manning.com/books/object-design-style-guide&quot; data-source-url=&quot;https://www.manning.com/books/object-design-style-guide&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/gckDw/hyOFEmb3ZC/lUInnOdXYMLn5K7LHJNUwK/img.jpg?width=360&amp;amp;height=451&amp;amp;face=250_78_274_104,https://scrap.kakaocdn.net/dn/czfBkl/hyOFx1F8IX/agzTTXkZVHKMPqhukbhLxk/img.jpg?width=360&amp;amp;height=451&amp;amp;face=250_78_274_104,https://scrap.kakaocdn.net/dn/bRV6mh/hyOFDgvFBR/AjaTchz8eNK0vscfKBAK4K/img.jpg?width=264&amp;amp;height=331&amp;amp;face=179_55_204_82');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Object Design Style Guide&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Elevate your coding style by mastering the universal best practices for object design. Explore techniques for creating pro-quality OO code that can stand the test of time.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.manning.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>[공부] 독서/오브젝트 디자인 스타일 가이드</category>
      <category>CQRS</category>
      <category>mock</category>
      <category>이벤트</category>
      <category>책임</category>
      <category>추상화</category>
      <author>kok202</author>
      <guid isPermaLink="true">https://kok202.tistory.com/350</guid>
      <comments>https://kok202.tistory.com/350#entry350comment</comments>
      <pubDate>Mon, 6 Jun 2022 18:33:56 +0900</pubDate>
    </item>
    <item>
      <title>오브젝트 디자인 스타일 가이드 (1/2) 서비스와 객체</title>
      <link>https://kok202.tistory.com/349</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;http://www.yes24.com/Product/Goods/91167539&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;http://www.yes24.com/Product/Goods/91167539&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1654498390563&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;book&quot; data-og-title=&quot;오브젝트 디자인 스타일 가이드 - YES24&quot; data-og-description=&quot;잘 작성한 객체지향 코드는 읽고 변경하고 디버그하기 즐겁다. 이 책에서 보여주는 객체 디자인에 대한 보편적 모범 사례를 익혀 코딩 스타일을 향상하자. 이 명확한 규칙은 어떤 객체지향 언어&quot; data-og-host=&quot;www.yes24.com&quot; data-og-source-url=&quot;http://www.yes24.com/Product/Goods/91167539&quot; data-og-url=&quot;http://www.yes24.com/Product/Goods/91167539&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bWQDak/hyOFCPpCDc/I4hBXLwVyemJ6KDEwf3SmK/img.jpg?width=940&amp;amp;height=1200&amp;amp;face=433_339_483_393,https://scrap.kakaocdn.net/dn/4TEFT/hyOFvpeHdl/zrjCvC3tDJOfA1pMfQwYk1/img.jpg?width=940&amp;amp;height=1200&amp;amp;face=433_339_483_393,https://scrap.kakaocdn.net/dn/bZkQm8/hyOFCaNngA/E7gp1VxWUVXrRcDRWcvQk1/img.jpg?width=940&amp;amp;height=1200&amp;amp;face=433_339_483_393&quot;&gt;&lt;a href=&quot;http://www.yes24.com/Product/Goods/91167539&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;http://www.yes24.com/Product/Goods/91167539&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bWQDak/hyOFCPpCDc/I4hBXLwVyemJ6KDEwf3SmK/img.jpg?width=940&amp;amp;height=1200&amp;amp;face=433_339_483_393,https://scrap.kakaocdn.net/dn/4TEFT/hyOFvpeHdl/zrjCvC3tDJOfA1pMfQwYk1/img.jpg?width=940&amp;amp;height=1200&amp;amp;face=433_339_483_393,https://scrap.kakaocdn.net/dn/bZkQm8/hyOFCaNngA/E7gp1VxWUVXrRcDRWcvQk1/img.jpg?width=940&amp;amp;height=1200&amp;amp;face=433_339_483_393');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;오브젝트 디자인 스타일 가이드 - YES24&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;잘 작성한 객체지향 코드는 읽고 변경하고 디버그하기 즐겁다. 이 책에서 보여주는 객체 디자인에 대한 보편적 모범 사례를 익혀 코딩 스타일을 향상하자. 이 명확한 규칙은 어떤 객체지향 언어&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.yes24.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;코드 레벨에 대한 설명이 많아 이는 생략하고 보편적인 가치 위주로 정리합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; ) 은 사견입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;의존성&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체 A가 일을 처리하는데 객체 B를 필요하면 A가 B에 의존한다고 한다. A가 B에 의존하는 방식은 여러가지다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;A에서 B 인스턴스를 만들어서 의존할 경우&lt;/li&gt;
&lt;li&gt;알고 있는 위치에서 B 인스턴스를 가져와서 의존할 경우&lt;/li&gt;
&lt;li&gt;생성할 때 주입한 B의 인스턴스에 의존할 경우&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;의존성을 가져오는 것이&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;Service location&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;(서비스 위치 지정)이며, 생성자 인자를 통해 의존성을 얻는 것이&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;의존성 주입&lt;/b&gt;이라고 이해해도 충분하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Composition&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한 객체를 다른 객체의 속성에 할당하는 것을 객체 컴포지션 (object composition)이라고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;객체의 두 종류&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;작업을 수행하거나 정보를 반환하는 서비스 객체&amp;nbsp;&lt;/li&gt;
&lt;li&gt;데이터를 담고 있으며 데이터를 조작하거나 가져오는 행위를 선택적으로 드러내는 객체&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;서비스란 무엇인가?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;작업을 수행, 정보를 반환하며, 생명 주기가 단순하고,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;한번 생성으로 영원히 일을 하는 객체.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;서비스의 불변성&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;⭐⭐⭐&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;서비스는 불변해야한다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서비스의 인스턴스를 만든 후에는 행위가 바뀌어선 안된다. 서비스가 인스턴스화 된 이후 의존성 주입이 되면 서비스의 행위를 바꾸게 만든다. 이는 서비스를 예측 불가능하게 만드는 요소중 하나다. ( : setter 자체가 서비스에 있으면 안된다는 의미)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;서비스에 의존성 주입&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;생성자 주입으로 의존성을 주입해야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;생성자 주입으로 의존성을 주입할 때는 필요한 것의 위치가 아니라 필요한 것 자체를 주입해야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;서비스 위치 지정자 (service locator)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에서 말한 필요한 것을 들고 있는 객체. 어떤 의미에서&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;서비스 위치 지정자는 올바른 키를 알고 잇으면 서비스를 가져올 수 있는 맵&lt;/b&gt;과 같다. 서비스 위치 지정자는 프로그램안의 사용가능한 모든 서비스에 접근할 수 잇게 해주기 때문에, 서비스 위치 지정자를 이용한 생성자 주입으로 처리하려는 유혹에 빠질 수 있다. 하지만 그렇게 되면 코드에서 추가적인 함수 호출을 하게되 서비스(혹은 어떤 컴포넌트든 상관없음)가 실제 어떤 일을 하는지가 모호해진다. 추가로 서비스 위치 지정자를 주입 받은 서비스 입장에서는 필요한 데이터에 어떻게 접근해서 가져와야하는지 알아야할 필요도 생긴다. 따라서 필요한 것 자체를 주입하는 것이 좋다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서비스 위치 조정자를 부르는 데 다음과 같은 용어들이 사용된다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Service locator&lt;/li&gt;
&lt;li&gt;관리자 (manager)&lt;/li&gt;
&lt;li&gt;레지스트리&lt;/li&gt;
&lt;li&gt;컨테이너&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;생성자 주입에 사용되는 파라미터는 Optional 이면 안된다.&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Optional 이 코드를 불필요하게 복잡하게 만든다. 설정 값을 필수 인자로 두면서 합리적인 기본값도 같이 제공하고 싶다면 Configuration 을 전달하는 방법도 있다. 하지만 그래도 필요한 의존성을 완전히 드러내는 것이 좋다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;생성자 주입만 사용한다.&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;객체를 불완전한 상태로 생성할 수 없어야한다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서비스는 불변이어야 한다. 인스턴스 생성을 마친 후에는 바꿀 수 없어야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(  생성자 주입을 사용해야하는 이유 중 하나로 멤버 변수를 final로 만들 수 있다라는 글이 많다. 항상 그런 글들을 읽다보면, final 로 만든게 대체 뭐가 좋은데? 라는 의문이 남았다. 책에서 해답을 알려주는데, 서비스에 사용되는 멤버 변수를 final 로 만들 수 있는게 중요한 것이 아니다. 서비스 자체가 불변하는 협력 객체를 의미하기 때문에 final 로 되어있어야 서비스라고 할 수 있는 것이다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;생성자에서는 속성을 할당하는 일만 한다.&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;생성자에 속성 할당 외 다른 책임이 주어지면 할당에 규칙이 생기고 이것이 서비스를 복잡하게 만드는 요인이 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(  생성자에 요구되는 책임은 assert, assign 두 개인 듯.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;정적 의존성을 사용하지 않는다.&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;시스템 호출 (특히 시간)을 명백히 한다.&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시간과 관련한 의존성을 드러내지 않으면, 런타임에 상관없이 해당 코드는 항상 실제 현재 시각을 사용하여 동작할 것이다. 그렇게 되면 테스트 코드가 있을 때 테스트를 언제 수행하는지에 따라 테스트 결과가 달라진다. 이는 테스트를 불안정하게 만들고 특정 시점 이후에 테스트를 수행하면 실패하게 되는 원인이 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;( : Time.getCurrentTimestamp() 같은 코드를 만들어선 안되는 이유)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;생성자 주입시 할 수 있는 방법.&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필요한 것을 주입한다 &amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; 필요한 것의 위치를 주입한다 &amp;gt;&amp;gt; | 절대하면 안되는 것: Optional 주입&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;객체&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체는 항상 일관성 있는 상태로 존재하도록 하는 것이 좋다. 예를들어 Position 이라는 객체가 있을 때 setX, setY 가 있으면 일관성을 해친다. x, y 가 중요한 객체라면 x, y 입력없이는 생성을 못하도록 하는 것이 좋다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;도메인의 불변성을 보호해야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;생성자에 의미있는 데이터를 요구해야한다.&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를들어 Positon 에서 x 가 [-200, 200] 안의 값만 허용한다하면, 이를 검증하는 로직이 생성자에 있어야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(  종종 주석으로 경고 메시지가 담긴 코드를 볼 수 있는데, 주석만 달지말고 유호하지 않은 값이 들어오면 예외를 던지고, 예외를 던지는지 확인하는 테스트 코드를 작성하는 것이 낫다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;생성자 테스트&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;생성자는 실패해야하는 것만 테스트한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(  생성자 테스트는 예외를 던지는지만 테스트하는 것이 좋다. 생성자에 값이 제대로 할당 됬는지 알기 위해 getter 가 무분별하게 만들어지는 것을 유도한다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Named constructor&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정적 팩토리 메소드를 명명한 생성자(named constructor)라고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;명명한 생성자의 이름은 create 같은 어휘보다 도메인에 더 적합한 이름이 있다면 이를 사용하는 것이 좋다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체를 생성하기 위한 도메인 별 동의어를 도입하는 데 사용할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;새로운 객체 추출&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;의존성을 주입할 때 항상 같이 다니는 객체가 있다면 새로운 객체로 추출해서 나타낸다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex. Amount + Currency -&amp;gt; Money&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;서비스를 메소드 인자로 전달해도 되는가?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서비스를 메소드 인자로 전달하는 것은 다소 이상할 수 있다. 다른 구현 방법을 고려하는 것도 합리적이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어떤 사례에서는 서비스를 메소드 인자로 전달해야 한다는 점이, 그 행위 대신 서비스를 구현해야한다는 암시일 수 있다라고도 본다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;VO, DTO, Entity&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가급적이면 어땐 객체를 만들려할 때 VO &amp;gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;Entity &amp;gt; DTO 순으로 만들 것을 고민하는 것이 좋다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;VO&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;불변 객체&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;값이 변경되어야할 일이 있다면 변경하는 대신 새로운 객체로 교체한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(  VO 의 변경자는 새로운 VO 를 반환해야한다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;DTO&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로퍼티가 public 으로 선언되도 되는 객체.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(  이건 솔직히 잘모르겠다. 아무리 DTO 라고 해도 멤버 변수를 public 으로 만드는게 맞는걸까?)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(  만약 lombok 을 사용해 @Getter, @Setter 를 무분별하게 달았다면 이는 이미 DTO 일 수 있다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Entity (개체)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;변경을 추적할 수 있다. (개체 안에 어떤 변경 명령이 들어왔는지 추적할 수 있도록 이벤트를 기록할 수 있다.)&amp;nbsp;&lt;/li&gt;
&lt;li&gt;식별 가능하다.&lt;/li&gt;
&lt;li&gt;응용 프로그램의 도메인 개념이다.&lt;/li&gt;
&lt;li&gt;수명 주기가 있다.&lt;/li&gt;
&lt;li&gt;영속성을 갖는다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(  항상 Entity 관련 글을 읽어보면 식별 가능한 클래스라고해서 Id 가 있으면 Entity 다라고 주장하는 글을 많이 봤는데, 그럴때마다 드는 의문이 &quot;그럼 VO 나 DTO 가 id 를 들고 잇으면 그것도 Entity 로 봐야하는가?&quot; 였다. Entity 에서 중요한 것은 &lt;b&gt;식별 가능하다는 것보다 명령이 가능한 데이터인가?&lt;/b&gt; 가 좀 더 맞아보인다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Entity 구현의 원칙&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;개체 상태를 변경하는 메소드의 반환 타입은 void 이고 이름은 명령형이어야한다.&lt;/li&gt;
&lt;li&gt;메소드 호출로 개체의 상태가 유효하지 않게 되지 않도록 보장해야한다.&lt;/li&gt;
&lt;li&gt;개체 내부에서 일어나는 일을 테스트 하기 위해 내부를 모두 노출해서는 안된다. 대신 변경 기록을 유지하고 기록을 노출해서 객체가 변경된 내용과 바뀐 이유를 알 수 있어야한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>[공부] 독서/오브젝트 디자인 스타일 가이드</category>
      <category>dto</category>
      <category>Entity</category>
      <category>VO</category>
      <category>디자인</category>
      <category>불변</category>
      <category>서비스</category>
      <category>오브젝트</category>
      <author>kok202</author>
      <guid isPermaLink="true">https://kok202.tistory.com/349</guid>
      <comments>https://kok202.tistory.com/349#entry349comment</comments>
      <pubDate>Mon, 6 Jun 2022 18:09:34 +0900</pubDate>
    </item>
    <item>
      <title>Duby 를 오픈했습니다.</title>
      <link>https://kok202.tistory.com/348</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Duby&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기간 2021.11.01 ~ 진행중&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2118&quot; data-origin-height=&quot;1778&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/coclu0/btrDxn5hkPN/68t3RIk61SSLlqUy6kbN30/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/coclu0/btrDxn5hkPN/68t3RIk61SSLlqUy6kbN30/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/coclu0/btrDxn5hkPN/68t3RIk61SSLlqUy6kbN30/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcoclu0%2FbtrDxn5hkPN%2F68t3RIk61SSLlqUy6kbN30%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2118&quot; height=&quot;1778&quot; data-origin-width=&quot;2118&quot; data-origin-height=&quot;1778&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://duby.dev/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://duby.dev/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1653914207745&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Duby&quot; data-og-description=&quot;&quot; data-og-host=&quot;duby.dev&quot; data-og-source-url=&quot;https://duby.dev/&quot; data-og-url=&quot;https://duby.dev/&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://duby.dev/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://duby.dev/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Duby&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;duby.dev&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오픈 그래프 태그가 빠져서 만들어진 링크가 예쁘진 않네요! 조만간 추가해야겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 개인 프로젝트는 개발자들에게 필요한 툴킷을 모아둔 사이트입니다. 회사 동기였던 &lt;a href=&quot;https://github.com/yeonjuan&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/yeonjuan&lt;/a&gt; 와 함께 팀 프로젝트 형태로 진행했는데, 협업 자체도 좋았지만 개발 관련해서는 React lazy loading 에 관한 내용을 알 수 있어서 좋았습니다. 장기적으로는 개발 커뮤니티로 발전하는 방향도 생각하고 있는데, 당장은 실무에서 필요한 개발 도구들을 모아보자고 합의가되서 툴킷으로 방향잡고 집중해봤네요. 필요한 도구가 있다면 피드백 주시는대로 추가를 고려해보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;주요 기능&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;JSON 포맷터&lt;/li&gt;
&lt;li&gt;JWT 디코더&lt;/li&gt;
&lt;li&gt;JSON diff 뷰어&lt;/li&gt;
&lt;li&gt;SQL 포맷터&lt;/li&gt;
&lt;li&gt;HTML minifie&lt;/li&gt;
&lt;li&gt;YAML diff 뷰어&lt;/li&gt;
&lt;li&gt;YAML to JSON&lt;/li&gt;
&lt;li&gt;YAML 포맷터&lt;/li&gt;
&lt;li&gt;인코더 디코더&lt;/li&gt;
&lt;li&gt;암호화&lt;/li&gt;
&lt;li&gt;네이밍 컨벤션 변환기&lt;/li&gt;
&lt;li&gt;Gitignore 테스트&lt;/li&gt;
&lt;li&gt;TEXT 길이 카운터&lt;/li&gt;
&lt;li&gt;TEXT diff 뷰어&lt;/li&gt;
&lt;li&gt;Epochmillis&lt;/li&gt;
&lt;li&gt;크론탭(crontab)&lt;/li&gt;
&lt;li&gt;마크다운(Markdown) 프리뷰&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제로 업무하면서 사용하기 편한 방식으로 개발하는 것을 생각했기 때문에, 저부터가 자주 들어가는 사이트가 되도록 했습니다. 특히 Epochmillis 와 Cron, Text diff 는 자주 들어가는 것 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;후기&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로젝트 이름은 Duby 라는 이름으로 지었습니다. 이름의 배경은 긴데, 간략하게 요약하면 Dev + Ruby 의 약자입니다.&lt;/li&gt;
&lt;li&gt;vscode 느낌나는 룩앤필로 사이트를 개발했는데, 이에 맞춰 로고도 vscode 로고로 루비 아이콘을 형상화 하도록 했습니다.&lt;/li&gt;
&lt;li&gt;firebase + mongo DB를 이용하여 개발되었는데, 백엔드에 nestJS 를 처음으로 사용했습니다. Spring boot 와 매우 유사한데, 개인적으론 스프링 부트가 현업에서도 쓰고있어서 그런지 훨씬 편했던 것 같습니다. 대신 firebase function 을 이용하여 백엔드를 만들기에는 nestJS 만한게 없었던 것 같습니다.&lt;/li&gt;
&lt;li&gt;Github action 을 처음 써봤는데, 상당히 괜찮았던 것 같습니다. 개인 프로젝트에 Jenkins 나 Ansible 을 마련해서 쓸 수 없으니, 깃헙 액션은 앞으로의 개인 프로젝트에서도 자주 사용할 것 같습니다.&lt;/li&gt;
&lt;li&gt;엔터테이먼트 성격의 도구를 넣는 것도 고려했으나 (ex. 사다리, 타이머...) 일단 개발 도구에만 집중하기로 했습니다!&lt;/li&gt;
&lt;li&gt;api 서버가 cold - warm 스타트를 하기 때문에 최초 로그인 시도시 살짝 지연 될 수 도 있습니다.&lt;/li&gt;
&lt;li&gt;api 서버에는 테스트 코드를 추가하면서 작업하였습니다. 부끄러운 얘기지만 이 api 서버의 코드 커버리지는 67%정도입니다. nestJS 는 익숙치않아서 모듈 파일들에 대한 테스트 작성이 어려웠던 것 같습니다. e2e 테스트도 손에 잘 안익었고요.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1396&quot; data-origin-height=&quot;122&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/us5EN/btrDzkl2kbl/Qb3nikFCH4VQSf9jo5kZk1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/us5EN/btrDzkl2kbl/Qb3nikFCH4VQSf9jo5kZk1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/us5EN/btrDzkl2kbl/Qb3nikFCH4VQSf9jo5kZk1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fus5EN%2FbtrDzkl2kbl%2FQb3nikFCH4VQSf9jo5kZk1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;745&quot; height=&quot;122&quot; data-origin-width=&quot;1396&quot; data-origin-height=&quot;122&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;잠깐 테스트 얘기가 나와서 언급하자면, 현업에서 간단한 신규 프로젝트를 런칭할 기회가 생겨서 TDD 접근 방식으로 개발을 해봤습니다. 거기서 겪었던 경험으로 조만간 테스트 관련 글을 하나 더 올릴 것 같습니다. 그 프로젝트의 커버리지는 대략 95%정도 됩니다!&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1352&quot; data-origin-height=&quot;278&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/blx6LG/btrDzkM6EDV/Rq4tq2hD5AKL1Us6gQUNfK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/blx6LG/btrDzkM6EDV/Rq4tq2hD5AKL1Us6gQUNfK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/blx6LG/btrDzkM6EDV/Rq4tq2hD5AKL1Us6gQUNfK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fblx6LG%2FbtrDzkM6EDV%2FRq4tq2hD5AKL1Us6gQUNfK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;757&quot; height=&quot;156&quot; data-origin-width=&quot;1352&quot; data-origin-height=&quot;278&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실무에 필요한 도구 위주로 모아놨습니다! 한번쯤 둘러보시고 들어오셔서 원하시는 도구가 있다면 북마크 해가시면 좋을 것 같습니다. :)&lt;/p&gt;</description>
      <category>[개발] 개인 프로젝트/Duby</category>
      <category>Decoder</category>
      <category>dev tool</category>
      <category>duby</category>
      <category>Encoder</category>
      <category>epochmillis</category>
      <category>gitignore</category>
      <category>json</category>
      <category>markdown</category>
      <category>toolkit</category>
      <category>YAML</category>
      <author>kok202</author>
      <guid isPermaLink="true">https://kok202.tistory.com/348</guid>
      <comments>https://kok202.tistory.com/348#entry348comment</comments>
      <pubDate>Tue, 31 May 2022 00:10:26 +0900</pubDate>
    </item>
    <item>
      <title>쏙쏙 들어오는 함수형 코딩</title>
      <link>https://kok202.tistory.com/347</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;http://www.yes24.com/Product/Goods/108748841&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;http://www.yes24.com/Product/Goods/108748841&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1653823871719&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;book&quot; data-og-title=&quot;쏙쏙 들어오는 함수형 코딩 - YES24&quot; data-og-description=&quot;소프트웨어의 복잡성을 다루기 위해 꼭 읽어야 할 책이 책은 함수형 사고를 통해 의도하지 않은 복잡성이 코드 전체로 퍼져나가는 것을 막고 프로그래밍을 간단하게 하는 법을 담았다. 시스템&quot; data-og-host=&quot;www.yes24.com&quot; data-og-source-url=&quot;http://www.yes24.com/Product/Goods/108748841&quot; data-og-url=&quot;http://www.yes24.com/Product/Goods/108748841&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/b24JTx/hyOzSx6G0N/hfDh2NK8RV5XmhMWzZdcP0/img.jpg?width=920&amp;amp;height=1200&amp;amp;face=0_0_920_1200,https://scrap.kakaocdn.net/dn/bEN7zM/hyOzVVV8UQ/CNQ8mhozCcb8bp5bVZ8nB1/img.jpg?width=920&amp;amp;height=1200&amp;amp;face=0_0_920_1200,https://scrap.kakaocdn.net/dn/bV6V4b/hyOzV2IbEb/8WahNpAlhrYEAOTug7iYj0/img.jpg?width=920&amp;amp;height=1200&amp;amp;face=0_0_920_1200&quot;&gt;&lt;a href=&quot;http://www.yes24.com/Product/Goods/108748841&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;http://www.yes24.com/Product/Goods/108748841&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/b24JTx/hyOzSx6G0N/hfDh2NK8RV5XmhMWzZdcP0/img.jpg?width=920&amp;amp;height=1200&amp;amp;face=0_0_920_1200,https://scrap.kakaocdn.net/dn/bEN7zM/hyOzVVV8UQ/CNQ8mhozCcb8bp5bVZ8nB1/img.jpg?width=920&amp;amp;height=1200&amp;amp;face=0_0_920_1200,https://scrap.kakaocdn.net/dn/bV6V4b/hyOzV2IbEb/8WahNpAlhrYEAOTug7iYj0/img.jpg?width=920&amp;amp;height=1200&amp;amp;face=0_0_920_1200');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;쏙쏙 들어오는 함수형 코딩 - YES24&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;소프트웨어의 복잡성을 다루기 위해 꼭 읽어야 할 책이 책은 함수형 사고를 통해 의도하지 않은 복잡성이 코드 전체로 퍼져나가는 것을 막고 프로그래밍을 간단하게 하는 법을 담았다. 시스템&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.yes24.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;코드 레벨에 대한 설명이 많아 이는 생략하고 보편적인 가치 위주로 정리합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; ) 은 사견입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;함수형 프로그래밍&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;수학 함수를 사용하고 부수 효과를 피하는 것이 특징인 프로그래밍 패러다임&lt;/li&gt;
&lt;li&gt;부수효과 없이 순수 함수마 사용하는 프로그래밍 스타일&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;부수효과&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;부수효과는 함수가 리턴 값 이외에 하는 모든 일을 의미한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;부수효과는 소프트웨어를 사용하는 근본적인 이유다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;  가급적이면 부수 효과를 사용하지 않으려 해야하는 것이지 부수효과 자체를 부정해서는 안된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;부수효과의 예시&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이메일 보내기&lt;/li&gt;
&lt;li&gt;파일 읽기&lt;/li&gt;
&lt;li&gt;불빛을 깜빡이기&lt;/li&gt;
&lt;li&gt;웹 요청을 하기&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;함수형 사고를 위한 중요 개념 2가지&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;액션 / 계산 / 데이터를 구분해서 생각하기&lt;/li&gt;
&lt;li&gt;일급 추상&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;액션 / 계산 / 데이터&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;액션: 암묵적 입출력 갖는 함수&lt;/li&gt;
&lt;li&gt;계산: 명시적 입출력 만을 갖는 함수&lt;/li&gt;
&lt;li&gt;데이터: 수동적이고 투명한 value&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;불변 데이터를 위한 두가지 원칙&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;카피 온 라이트: 데이터를 변경할 때 복사본을 만들어 수정하고 반환하는 것.&lt;/li&gt;
&lt;li&gt;방어적 복사: 안전하지 않은 코드(서드파티 or 레거시 코드)를 사용하기 전 / 후에 데이터를 복사해서 사용하는 것.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;액션과 계산을 구분하면 좋은 이유&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;계산은 외부에 영향을 주지 않기 때문에 쉽게 테스트가 가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt; &amp;nbsp;CQRS 와 같은 맥락이고 단어만 다르다라는 느낌을 받음.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;함수형 프로그래머는 액션을 가급적 사용하려하지 않아야한다.&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;  인터페이스를 이용하면 액션도 런터임에 따라 계산이 될 수 있게 할 수 있다. 테스트 환경에서는 SUT 를 계산으로 동작하고, 실행 환경에서는 액션으로 동작하게 만들 수 있음. 계산의 가장 큰 장점은 deterministic 하다는 점인 듯&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;함수에 암묵적 입력과 출력이 있으면 액션이 된다.&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;명시적 입력: 매개변수&lt;/li&gt;
&lt;li&gt;명시적 출력: 리턴값&lt;/li&gt;
&lt;li&gt;암묵적 입력: 전역변수 get (매개 변수 외 다른 입력)&lt;/li&gt;
&lt;li&gt;암묵적 출력: 전역변수 수정 (리턴값 외 다른 출력)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;불변 데이터를 쓰면 데모리를 더 쓰고 느릴까?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;분명 불변 데이터를 사용하지 않는 것보다 메모리를 더쓰고 느릴 수 있다. 하지만 불변 데이터를 사용해도 대용량 고성능 시스템의 구현 사례가 많다. 불변 데이터 구조를 사용하고 속도가 느린 부분을 최적화하면 된다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가비지 콜렉터는 생각보다 빠르며, 생각보다 복사는 많이 일어나지 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;함수형 프로그래밍에서 map, filter, reduce 같은 체인을 최적화 하는 것을 스트림 결합이라고 부른다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;구조적 공유&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두개의 중첩된 데이터 구조가 어떤 참조를 공유한다면 구조적 공유라고한다. 데이터가 바뀌지 않는 불변 데이터 구조라면 구조적 공유는 안전하지만 불변이 아니라면 불안전하다.&lt;/p&gt;
&lt;pre id=&quot;code_1653825155504&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Object test = new Object();
List&amp;lt;Object&amp;gt; listA = List.of(test);
List&amp;lt;Object&amp;gt; listB = List.of(test);
// 구조적 공유 listA 와 listB 는 test 참조값을 둘다 갖고 있다.&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;오프 바이 원&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주로 배열을 반복해서 처리할 때 &quot;크다&quot; 또는 &quot;크거나 같다&quot;와 같은 비교문을 잘못 선택해 의도하지 않게 마지막 항목을 처리하지 못하거나 처리하는 오류.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;추상화 벽을 만들어야하는 이유 (  인터페이스를 만들어야 하는 이유)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;추상화 벽에 코드가 많을수록 구현이 변경되었을 때 고쳐야 할 것이 많습니다.&lt;/li&gt;
&lt;li&gt;추상화 벽에 있는 코드는 낮은 수준의 코드이기 때문에 더 많은 버그가 있을 수 있습니다.&lt;/li&gt;
&lt;li&gt;낮은 수준의 코드는 이해하기 더 어렵습니다.&lt;/li&gt;
&lt;li&gt;추상화 벽에 코드가 많을수록 팀 간 조율해야할 것도 많아집니다.&lt;/li&gt;
&lt;li&gt;추상화 벽에 인터페이스가 많으면 알아야할 것이 많아 사용하기 어려워집니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;비기능적 요구사항&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;  소프트웨어의 기능적 요구사항 외 프로그래머가 챙겨야할 가치. 소프트웨어 설계가 필요한 이유와 맥락을 같이 한다.&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;테스트성: 어떤 것을 테스트하는 것이 가장 중요한가&lt;/li&gt;
&lt;li&gt;유지보수성: 요구사항이 바뀌었을 때 가장 쉽게 고칠 수 있는 코드는 어떤 코드인가&lt;/li&gt;
&lt;li&gt;재사용성: 어떤 함수가 재사용하기 좋은지&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;의존성 트리&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;의존성 트리 상단에 있는 코드는 자주 변경될 것이고 테스트가 오래가지 않을 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;의존성 트리 하단에 있는 코드는 덜 변경될 것이고 테스트가 오래갈 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;=&amp;gt; 트리 하단에 있는 테스트들이 더 가치가 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;=&amp;gt; 트리 하단에 있을 수록&amp;nbsp; 재사용하기 좋습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;=&amp;gt; 트리 하단에 있을 수록 덜 변경되어 유지보수하기 좋습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;고차함수&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(  함수를 값으로 갖는 함수)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;고차함수를 이용한 카피 온 라이트 예제&lt;/p&gt;
&lt;pre id=&quot;code_1653826049614&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const copyOnWrite = (array, delegate) =&amp;gt; {
  let copy = array.slice();
  delegate(copy);
  return copy;
}

const setValue = (array, index, value) =&amp;gt; {
  return copyOnWrite(array, (copy) =&amp;gt; {
    copy[index] = value;
  });
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;서평&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;부푼 기대를 안고 읽었으나, 후반부는 사실상 Stream, Stream 이 어떤 식으로 구현 되어있는지가 주된 내용입니다. 이미 stream 에 익숙하다면 사실상 읽을 필요가 없어서 책의 절반만 유용했습니다. 일급 추상을 왜 일급 추상이라고 부르는지와 고차 함수를 왜 고차 함수라고 부르는지 궁금해서 읽었는데, 뭔가 명확한 설명은 얻기 어려웠고, 그냥 위키피디아 수준의 지식을 얻어갈 수 있었습니다. 책 내용은 어렵지 않아서 입문용으로는 좋아보입니다.&lt;/p&gt;</description>
      <category>[공부] 독서</category>
      <author>kok202</author>
      <guid isPermaLink="true">https://kok202.tistory.com/347</guid>
      <comments>https://kok202.tistory.com/347#entry347comment</comments>
      <pubDate>Sun, 29 May 2022 23:00:56 +0900</pubDate>
    </item>
    <item>
      <title>레거시 코드 활용 전략</title>
      <link>https://kok202.tistory.com/346</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;http://www.yes24.com/Product/Goods/64586851&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;http://www.yes24.com/Product/Goods/64586851&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1650129405896&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;book&quot; data-og-title=&quot;레거시 코드 활용 전략 - YES24&quot; data-og-description=&quot;시스템 내에 오래된 코드를 다루는 방법을 배울 수 있다. 오래된 코드, 즉 레거시 코드는 그 코드에 익숙한 사람도 없고, 테스트 루틴도 없어 관리하기 어렵다. 저자는 다년간의 현장 경험과 실&quot; data-og-host=&quot;www.yes24.com&quot; data-og-source-url=&quot;http://www.yes24.com/Product/Goods/64586851&quot; data-og-url=&quot;http://www.yes24.com/Product/Goods/64586851&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/c5mHak/hyN37W2xLB/jiesvSHebKqK31kkk3nLM1/img.jpg?width=960&amp;amp;height=1200&amp;amp;face=0_0_960_1200,https://scrap.kakaocdn.net/dn/bMZny3/hyN3Zq9c8j/gXa94o2jD9WEEPYZ1WUqlk/img.jpg?width=960&amp;amp;height=1200&amp;amp;face=0_0_960_1200,https://scrap.kakaocdn.net/dn/bodbqk/hyN3ZYZ0TH/QD0KvfGcdnvvj2CrFBuGU0/img.jpg?width=960&amp;amp;height=1200&amp;amp;face=0_0_960_1200&quot;&gt;&lt;a href=&quot;http://www.yes24.com/Product/Goods/64586851&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;http://www.yes24.com/Product/Goods/64586851&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/c5mHak/hyN37W2xLB/jiesvSHebKqK31kkk3nLM1/img.jpg?width=960&amp;amp;height=1200&amp;amp;face=0_0_960_1200,https://scrap.kakaocdn.net/dn/bMZny3/hyN3Zq9c8j/gXa94o2jD9WEEPYZ1WUqlk/img.jpg?width=960&amp;amp;height=1200&amp;amp;face=0_0_960_1200,https://scrap.kakaocdn.net/dn/bodbqk/hyN3ZYZ0TH/QD0KvfGcdnvvj2CrFBuGU0/img.jpg?width=960&amp;amp;height=1200&amp;amp;face=0_0_960_1200');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;레거시 코드 활용 전략 - YES24&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;시스템 내에 오래된 코드를 다루는 방법을 배울 수 있다. 오래된 코드, 즉 레거시 코드는 그 코드에 익숙한 사람도 없고, 테스트 루틴도 없어 관리하기 어렵다. 저자는 다년간의 현장 경험과 실&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.yes24.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;코드 레벨에 대한 설명이 많아 이는 생략하고 보편적인 가치 위주로 정리합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; ) 은 사견입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;레거시 코드&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;저자가 생각하는 레거시 코드란 단순히 테스트 루틴이 없는 코드다.&lt;/b&gt; 다만 이 정의는 다소 불완전하다. 테스트 루틴이 없는 코드는 나쁜코드다. 코드가 얼마나 훌륭하게 작성돼 있는지는 상관없다. 아무리 깔끔하고 객체 지향적이며 캡슐화가 잘돼 있어도 소용없다. 테스트 루틴이 있으면 코드의 동작을 빠르게 검증하며 수정할 수 있다. 테스트 루틴이 없으면 우리가 작성하고 있는 코드가 좋아지고 있는지 나빠지고 있는지 제대로 알 수 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;변경&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드를 변경할 때 변경 대상만 집중하면 안 된다. 어떻게 기존의 동작에 영향을 미치지 않고 유지할 수 있을지 고민해야한다. 불행히도 기존의 동작을 그대로 유지한다는 것은 단순히 코드를 그대로 두는 것 이상의 의미를 갖는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;변경을 회피해선 안된다. 변경을 자주 하지 않으면 개발자의 실력이 녹슬기 쉽다. 거대한 클래스를 분할하는 작업을 일주일에 두세 번 정도 꾸준히 하지 않으면, 나중에는 감당하기 힘든 수준이 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;변경 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시스템을 변경하는 방법은 크게 두 가지로 나눌 수 있다. 첫째는 &quot;편집 후 기도하기&quot; 이며, 둘째는 &quot;보호 후 수정하기&quot;이다. &lt;b&gt;안타깝게도 편집 후 기도하는 방식은 아무리 신중하게 주의를 기울여도 그에 비례해서 안전성이 높아진다는 보장이 없다.&lt;/b&gt; 보호 후 수정하기의 기본 개념은 변경할 때 안전망을 이용하자는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;회귀 테스트&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;회귀 테스트란 주기적으로 테스트를 실행해 정상적인 동작 여부를 확인하고 지금까지와 마찬가지로 소프트웨어가 동작하는지 조사하는 것을 의미한다. 변경 대상 코드의 주변에 배치된 테스트 루틴들은 소프트웨어 바이스(고정 장치) 역할을 할 수 있다. 소프트웨어의 동작 대부분을 고정시키고, 변경하고자 하는 부분만 변경하고 있음을 확인할 수 있다는 뜻이다. 불행히도 회귀테스트는 애플리케이션 수준의 테스트로서 간주돼왔다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;대규모 테스트의 문제&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;오류 위치 파악이 어렵다. 테스트 루틴이 테스트 대상과 멀어질 경우 테스트 실패의 의미를 파악하기 힘들어진다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;실행시간이 길다. 테스트 루틴이 길이가 길어질 수록 실행하는데 오랜 시간이 걸린다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;커버리지 파악이 힘들다. 코드를 실행시키는 값들의 연결 관계 파악이 어렵다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;단위 테스트는 빨라야한다.&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실행에 0.1초가 걸리는 단위 테스트는 느린 단위 테스트다. 빠르지 않다면 단위 테스트가 아니다. 테스트를 위한 특별한 작업을 해야하거나 데이터베이스, 네트워크 통신, 파일 시스템을 사용한다면, 단위테스트가 아니다. (  테스트의 크기에 관한 정의는 구글의 소프트웨어 엔지니어링 책이 좀 더 잘 정의한 듯)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;테스트를 추가하기 어려운 상황&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;테스트 루틴을 작성하고 실행하는데 인스턴스를 생성하기 어려운 상황이 있다. 예를 들어 클래스 생성에 DBConnection 이 필요한 경우다. 이 DB 연결을 테스트 루틴에서 어떻게 처리할 수 있을까? 실제로 DB를 생성해야할까? 그러기 위해선 많은 작업이 수반돼야 할 것이다. DB 를 거치는 테스트는 속도가 느려질 것이다. 또 다른 예시로 Servlet 인스턴스를 생성하는 것은 더 어렵다. 이러한 값들을 아예 인수로 받지 않는 방법에 대해서도 고민해보지만, 코드 변경이 올바른지 확인한다는 테스트 목적을 생각해보면,&amp;nbsp; 이렇게 나머지 코드를 함부로 변경해도 되는지 의문이 들 때가 있다. (  결국 추상화가 잘안되서 생기는 문제)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 레거시 코드에 테스트코드를 추가할 때 딜레마가 생긴다. 코드 변경을 하려면 테스트 코드를 배치해야한다. 그런데 테스트 코드를 배치하려면 코드 변경이 필요할 때가 많다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;테스트 루틴을 배치할 때 의존 관계를 제거하는 이유&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;감지:&amp;nbsp; 코드 내에서 계산된 값에 접근할 수 없을 때 이를 감지하기 위해 의존 관계를 제거한다.&lt;/li&gt;
&lt;li&gt;분리: 코드를 테스트에 넣을 수 없을 때 코드를 분리하기 위해 의존 관계를 제거한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;분리를 위한 다양한 기법은 있으나 감지는 보통 협업 클래스를 위장하는 기법(fake or mock)을 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;가짜 객체가 진짜 테스트를 지원할 수 있는가?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어떤 사람들은 가짜 객체를 이용한 테스트가 진짜 테스트냐고 반문할 수 있다. 우리는 이러한 테스트를 통해 소프트웨어의 오작동을 모두 알아낼 수 있다고 단언할 수 있는 것은 아니다. 그렇다고 해서 이 테스트 마저 진짜가 아니라고 할 수는 없다. 우리는 테스트 루틴을 작성할 때 분할 정복 접근법을 사용해야한다. 가짜 객체를 이용한 테스트가 중요하지 않은 테스트라고는 할 수 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;봉합&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;봉합 지점이란 코드를 직접 편집하지 않고도 프로그램의 동작을 변경할 수 있는 위치를 말한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(  회사에서 많이 쓰는 support - process 패턴, OCP)&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(  기존의 코드를 봉합 지점으로 만드는 방법 중 하나는, 추상화를 이용하여 의존성 주입하는 것이다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;봉합에는 다양한 방식이 있는데, C 나 C++ 에서 사용할 수 있을 법한 링크 봉합, 전처리기 봉합이 있으며 가상 함수를 이용한 객체 봉합 방식이 존재한다. 일반적으로 객체 봉합은 객체지향 언어에서 가장 적합한 방법이다. 전처리 봉학과 링크 봉함은 의존관계가 매우 복잡하거나 다른 대안이 없을 경우에 최후의 카드로서 사용하는 것이 바람직하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드 변경을 위한 의존 관계를 제거하고 테스트 루틴을 작성하는 작업은 개발자의 시간을 많이 뺏앗는다. 하지만 대부분 결국 개발 시간과 시행착오를 줄여 시간을 절약해준다. 그런데 결국이란 대체 언제를 가리키는 것일까? 이는 현실 세계의 딜레마다. 지금 시간을 투자할 것인지, 나중에 시간을 투자할 것인지 선택해야 한다. (* 여기서 말하는 시간 절약이란 테스트 루틴이 오류를 포착함으로써 절얀된 시간과 오류 탐색에드는 모든 시간을 포함하여 말하는 것이다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;데코레이터 패턴&lt;/h3&gt;
&lt;pre id=&quot;code_1650210675222&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;abstract class ToolControllerDecorator extends ToolController {
    protected ToolController controller;
    public ToolControllerDecorator(ToolController controller) {
        this.controller = controller;
    }
    public void raise() {
        controller.raise();
    }
    public void lower() {
        controller.lower();
    }
    public void step() {
        controller.step();
    }
    public void on() {
        controller.on();
    }
    public void off() {
        controller.off();
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;컴파일 방화벽&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추상화, 인터페이스를 이용한 의존 관계를 제거하면 빌드 속도도 빨라진다. 구체 클래스가 변경되어도 협업에 사용되는 클래스는 인터페이스이기 때문에 상위 모듈의 재빌드가 필요없이 때문이다. 어떻게 보면 이는 &quot;컴파일 방화벽&quot;을 설치한 것이라고 말할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;LSP&lt;b&gt; [SOLID]&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LSP 를 준수하는데 도움이 되는 대략적인 규칙은 다음과 같다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;가급적 추상이 아닌 실체 메소드를 재정의 하지 않는다. 실체 메소드를 자주 재정의하면 코드가 혼란스러워진다.&lt;/li&gt;
&lt;li&gt;불가피하게 실체 메소드를 재정의 하는 경우, 그 메소드 내에서 재정의 대상 메소드를 호출할 수 있는지 확인한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;테스트 코드 관리&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;테스트 코드에는 최종적으로 출시되는 배포 코드와 동일한 기준이 적용될 필요가 없다. 테스트 코드를 쉽게 작성하기 위해서라면 public 변수를 정의해서 캡슐화를 위반하는 일도 별 문제는 아니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;숨겨진 의존 관계&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(  생성자에 의존성을 넣는 것보다 매개변수로 의존성을 건내주는 방식 의존성을 더 드러내는 방법이다.) 생성자 매개변수화 기법은 생성자의 의존 관계를 외부화하는 쉬운 방법인데, 많은 사람들이 이 기법을 잊어버리곤 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;전역 변수&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반적으로 전역 변수는 몇가지 이유에서 바람직하지 않다. 첫째로 투명하지 않다는 점이다. 일반적으로 어떤 코드를 봤을 때 그 코드가 무엇에 영향을 미치는지 알 수 있는 것이 바람직하다. 하지만 전역 변수가 자주 사용될 경우 단순한 메소드의 동작이 어떤 영향을 미치는지 알 수 없게 되는 경우가 많다. (  isActivatedAdmin...)&lt;/p&gt;
&lt;pre id=&quot;code_1650211201481&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Account account = new Account();
account.deposit(1);

// 전역 변수를 남발하는 시스템이라면 이 값을 1이라고 확신할 수 있을까?
int balance = account.getBalance();&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;둘째로 클래스가 어느 전역 변수를 사용 중인지, 제대로 이해한 후에 테스트에 적절한 상태로 설정해야한다는 점에서 테스트를 더 어렵게 만든다는 점이다. 설정해야하는 상태가 테스트 케이스마다 다르다면 상태 설정을 하는 작업은 상당히 지루한 일이 될 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;싱글톤&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;많은 사람들이 전역 변수를 갖기 위해 싱글톤을 생성하곤 한다. 변수를 필요한 장소로 전달하는 것이 어렵기 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Null 전달하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금 작성중인 테스트에서 인스턴스를 만들기 위해 생성자를 사용하고 있다 치자. 생성자에게 전달되는 매개변수중 정말로 필요한 것은 무엇인가? 매개변수중 테스트에 불필요한 값은 Null 전달 하는 기법을 사용할 수 있다. 테스트와 직접 의존 관계를 갖는 것만 주입하고 필요하다면 가짜 객체를 생성해 전달할 수 도 있다. (  개인적으로 Builder 를 좋아하는 이유.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;테스트하기 어려운 메소드&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;private 메소드&lt;br /&gt;private 메소드는 테스트하지 않는 것이 낫다. private 메소드를 테스트해야 한다면 그 메소드를 public 으로 만들었어야 한다는 것이다. public 으로 만드는 것이 꺼려진다면 이는 곧 클래스가 너무 많은 책임을 갖고 있음을 의미하며, 클래스를 수정해야한다는 뜻이다.&amp;nbsp;&amp;nbsp;&lt;/li&gt;
&lt;li&gt;final 메소드&lt;br /&gt;언어마다 서브 클래스화를 방지하는 구문을 제공한다. 자바에서는 final 예약어가 있다. 이는 보안에 민감한 클래스를 보호하는 역할을 한다. final 메소드때문에 테스트하기는 어렵다면 개발을 뭔가 잘못한 것이다.&amp;nbsp; 제어 범위를 벅어난 라이브러리에 직접 의존하는등의 이유로 스스로 어려움을 초래한 경우일 확률이 높다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;CQRS&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;하나의 메소드는 명령이나 쿼리여야하며, 두 가지 기능을 모두 가져서는 안된다.&lt;/b&gt; 명령은 객체의 상태를 변경할 수 있지만, 값을 반환하지 않는다. 쿼리는 값을 반환하지만 객체를 변경하지 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;영향 스케치&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;변경을 했을 때 어디까지 영향이 있을지를 그려보는 것. 변경의 대상이 되는 클래스를 사용하는 클래스들을 모두 파악한다. 특히 슈퍼 클래스나 서브 클래스가 있을 경우, 조사 대상에서 슈퍼 클래스나 서브 클래스를 사용하는 경우가 빠지지 않도록 주의한다. 변경하려는 대상이 메소드인 경우 메소드가 매개변수의 값을 변경하지 않는지도 파악한다. 전역 변수나 정적 변수를 사용하고 있다면 이 값을 변경하지 않는지도 파악한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;조임 지점&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;영향 스케치 안에 영향이 집중되는 곳이다. 조임 지점을 테스트하면 다수의 메소드를 테스트할 수 있다. 조임 지점은 자연적인 캡슐화의 경계다. 조임 지점을 찾았다면, 코드의 상당 부분과 관련이 있는 모든 영향이 통과하는 곳을 발견한 것과 같다. 그런 의미에서 조임 지점을 테스트하는 것은 어려운 프로그램 변경 작업을 시작하기에 이상적인 방법이다. 하지만 조임 지점만을 테스트하면 단위 테스트가 점점 소규모 통합 테스트로 커질 수 있다. 단위 테스트를 작성할 때 핵심은 가급적 독립적인 클래스로 테스트를 진행해야 한다는 것이다. 단위 테스트의 목적은 객체들이 전체적으로 올바르게 동작하는지 확인하는 것이 아니라 하나의 객체가 어떻게 동작하는지 확인하는 것이다. 따라서 필요하다면 가짜 클래스를 사용할 필요도 있다. 가짜 클래스를 사용함으로 써 단위 테스트를 단순화 할 수 있기 때문이다.&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;상위 수준 테스트만 작성하고 싶어요.&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상위 수준에서의 테스트는 리팩토링에 유용하다. 개발자들은 변경 대상 인터페이스에 대해 다수의 소규모 테스트 루틴들이 존재하면 변경이 러여워진다고 생각하기 쉽다. 하지만 실제로 대부분의 변경이 생각만큼 어렵지 않다. 테스트 코드 변경을 점진적이고 안전하게 진행할 수 있기 때문이다. 상위 수준 테스트가 분명 중요하긴 하지만, 단위 테스트를 대체할 수 없다. 상위 수준 테스트는 단위 테스트를 위한 첫 단계 정도로 간주하는 것이 좋다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;교차 지점&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특정 변경에 의한 영향을 감지할 수 있는 프로그램의 위치를 말한다. 교차 지점과 변경 지점의 거리가 떨어지면 테스트 설정이 어려워지며 피드백이 효과적이지 못하게 된다. (  테스트 후 검증을 위해 호출해야하는 메소드...? 정도로 생각하면 좋을 듯.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;문서화 테스트&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존 동작 유지에 피룡한 테스트를 문서화 테스트라고 부른다. 문서화 테스트는 코드 실제 동작의 특징을 나타내는 테스트로 시스템의 현재 동작을 있는 그대로 문서화 하는 테스트다. 문서화 테스트의 목적은 버그를 찾는 것이 아니다. 시스템의 현재 동작과의 차이라는 형태로 나타나는 버그(regression)를 나중에 발견하기 위한 목적이다. 따라서 코드의 실제 동작을 기록하는 것이 주가 되어야한다. 만약 문서화 테스트를 작성하다 버그를 발견하면 어떻게 할까? 상황에 따라 다르다. 시스템이 아직 출시되지 않았다면 수정하는 것이 맞고 아니라면 파급 효과를 고려하여 버그를 수정할지 말지 결정해야한다. 저자는 일반적으로 바로 수정하는 방식을 선호한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;라이브러리 호출&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;라이브러리 내의 클래스를 직접 호출하는 코드를 여러 곳에 분산시키면 안 된다. 현재 사용중인 라이브러리 코드가 나중에 바뀔 일이 결코 없을 것이라고 생각한다면, 단순히 근거없는 예측에 지나지 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;API 호출&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;시스템은 API 호출로 부터 분리할 수 있는 핵심 로직을 갖고 있어야한다. 기본적으로 두가지 접근 방법이 있다. 첫째로 API 를 포장하는 것이고 둘째로 책임을 기반으로 추출하는 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;비대한 클래스&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;클래스가 커지면 혼란을 야기한다. 무엇을 변경해야할지 다른 클래스에 어떤 영향을 미치는지 파악하기 어려워진다. 협업에 있어서도 conflict 가 빈번해진다. 추가로 테스트 코드 작성도 어려워진다. &lt;/span&gt;&lt;span&gt;비대한 클래스는 책임을 파악하고 적절한 분리 방법을 익혀 분리할 수 있어야한다. 비대한 클래스를 분리하는 방식에는 다음과 같은 방식들이 있다.&lt;/span&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;메소드를 분류한다. 이름이 비슷한 메소드를 찾고 접근 제한자를 함께 적어봐서 묶을 만한 메소드가 있는지 찾아본다.&lt;/li&gt;
&lt;li&gt;숨겨진 메소드를 조사한다. 클래스 내에 private 메소드가 많다면 별도의 클래스로 추출해야함을 의미한다.&lt;/li&gt;
&lt;li&gt;변경 가능한 결정사항을 찾는다. 예를 들어 updateScreen 메소드가 있다면 이름만으로 얼마나 많은 일을 하는지, 얼마나 많은 책임을 갖고 있는지 알 수 없다. 그렇다면 클래스를 추출하기 전 메소드 추출 리팩토링을 조금 해두는 것이 좋다. 이를 위해 결정사항을 찾는다. 코드에 얼마나 많은 가정이 포함되어 있는가?&lt;/li&gt;
&lt;li&gt;내부 관계를 찾는다. 인스턴스 변수와 메소드 사이의 관계를 찾는다. 어떤 인스턴스 변수가 일부의 메소드에서만 사용되고 있지 않는가? 클래스 안에는 이른바 덩어리라고 부른 넋이 존재한다. 이 덩어리를 찾기 위한 또 다른 기법은 클래스 내부의 관계에 대해 간단한 스케치를 그리는 것인데 이를 기능 스케치라고 부른다.&lt;/li&gt;
&lt;li&gt;주요 책임을 찾는다. 클래스의 책임을 한 개의 문장으로 기술하도록 노력한다.&lt;/li&gt;
&lt;li&gt;스크래치 리팩토링을 수행한다.&lt;/li&gt;
&lt;li&gt;현재 작업에 집중한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;인터페이스 분리 원칙 &lt;b&gt;[SOLID]&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;거대한 클래스의 경우 모든 클라이언트가 클래스 내의 모든 메소드를 사용하는 것은 거의 볼 수 없다. 대체로 특정 클라이언트마다 주로 사용하는 메소드들이 다르기 때문이다. 따라서 메소드 그룹마다 인터페이스를 작성하고 거대한 클래스에서 인터페이스를 구현하면, 클라이언트들은 특정 인터페이스를 통해 거대한 클래스를 참조할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;기능 스케치&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;기능 스케치는 영향 스케치와 매우 유사한데, 화살표 방향이 반대라는 중요한 차이점이 존재한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;중복 제거&lt;br /&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;중복 코드를 제거하면 설계의 진짜 모습이 드러난다. 중복 제거는 설계를 가다듬는 강력한 방법이다. 설계가 유연해질 뿐만 아니라 변경을 더욱 빠르고 쉽게할 수 있도록 해준다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;개방/폐쇄 원칙 &lt;b&gt;[SOLID]&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;설계가 잘돼 있다면 신규 기능 추가를 위해 그리 많은 코드 변경을 하지 않아도 된다는 뜻이다. 대부분 중복 제거를 잘한 코드는 자연스럽게 개방/폐쇄 원칙을 따르게 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;괴물 메소드&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;불릿 메소드: 들여쓰기가 거의 돼있지 않은 메소드를 말한다.&lt;/li&gt;
&lt;li&gt;혼잡 메소드: 들여쓰기 된 한개의 대규모 단락으로 구성된 메소드를 말한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;리팩토링&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;괴물 메소드를 리팩토링할 때는 가급적 추가 클래스, 추가 기능을 넣지 않도록한다. 일단 이상해보여도 메소드 분할을 진행한다. 메소드를 별도의 클래스로 옮기는 것은 어떤 방향으로 변경하는 것이 올바른지 명확해진 이후에도 언제든지 할 수 있다. 작은 조각부터 먼저 추출해서 점진적으로 메소드를 개선해 나가야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로그래밍을 할 때 한 번에 큰 부분을 건드리기 쉽다. 그렇게 되면 결국 코드가 실제로 어떤 일을 하는지 신중히 작업하기 보다 그저 코드가 동작하게 만드는 데 급급해질 것이다. &lt;span&gt;천 리 길도 한 걸음 부터다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;천재형 프로그래머&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;수 많은 상태를 기억하고 코드를 보자마자 이해할 수 있는 능력은 매우 유용한 재능일 수 있다. &lt;span&gt;개발자들은 이러한 이른바 천재형 프로그래머 이야기에 깊이 매료 되는 경우가 많다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;하지만 그것이 실제로 더 나은 의사 결정을 내리는 데 대단한 도움을 주는 것은 아니다. 현재의 저자는 각 언어의 세세한 점에 대해서는 조금 덜 알지라도 예전보다 더 나은 프로그래머라고 생각한다. 판단력은 중요한 프로그래밍 스킬이다. 천재 프로그래머를 어설프게 모방하다가 곤란한 상황에 빠질 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;의존 관계 제거 기법&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;매개변수 적응&lt;br /&gt;클래스에 인터페이스 추출을 사용할 수 없거나 매개변수를 가짜로 만들기 어려울 때 사용할 수 있는 기법. (  테스트를 위한 매개변수를 생성하기 조차 어려울 때 ex. HttpSerlvetRequest) 인터페이스에 세부 구현이 아니라 책임을 전달하도록 한다. 이를 통해 코드의 가독성과 유지 보수성이 향상된다.&lt;/li&gt;
&lt;li&gt;메소드 객체 추출&lt;br /&gt;어떤 경우에는 클래스를 단독으로 인스턴스화 하는데 많은 시간이 걸릴 수 있다. 이 리팩토링 기법의 개념을 한마디로 말하면 대규모 메소드를 새로운 클래스로 바꾸는 것이다.&lt;/li&gt;
&lt;li&gt;정의 완성&lt;br /&gt;일부 언어에서는 어떤 타입을 선언한 후 다른 곳에서 이를 정의할 수 있다. 이 기능을 활용해 의존 관계를 제거할 수 있다.&lt;/li&gt;
&lt;li&gt;전역 참조 캡슐화&lt;br /&gt;전역 변수를 클래스로 옮김으로써 코드를 분리한다.&lt;br /&gt;(  전역 참조를 내재화 하고 캡슐화하기)&lt;/li&gt;
&lt;li&gt;정적&amp;nbsp;메소드&amp;nbsp;드러내기&lt;/li&gt;
&lt;li&gt;호출&amp;nbsp;추출과&amp;nbsp;재정의&lt;/li&gt;
&lt;li&gt;팩토리&amp;nbsp;메소드&amp;nbsp;추출과&amp;nbsp;재정의&lt;/li&gt;
&lt;li&gt;get&amp;nbsp;메소드&amp;nbsp;추출과&amp;nbsp;재정의&lt;/li&gt;
&lt;li&gt;구현체&amp;nbsp;추출&lt;/li&gt;
&lt;li&gt;더&amp;nbsp;복잡한&amp;nbsp;예제&lt;/li&gt;
&lt;li&gt;인터페이스&amp;nbsp;추출&lt;br /&gt;많은 언어에서 사용하는 가장 안전한 의존 관계 제거 기법 중 하나. 혹시 순서를 잘못 따라도 컴파일러가 즉시 알려주기 때문에 버그가 생길 가능성이 매우 낮다.&lt;/li&gt;
&lt;li&gt;인스턴스&amp;nbsp;위임&amp;nbsp;도입&lt;/li&gt;
&lt;li&gt;정적&amp;nbsp;set&amp;nbsp;메소드&amp;nbsp;도입&lt;br /&gt;(  싱글톤을 테스트하기 위해 어거지로 사용하는 방식. 본질적으로 싱글톤은 두개가 존재해선 안되나 런타임용 싱 톤과 테스트용 싱글톤이 필요하기 때문에 어쩔 수 없이 사용해야하는 경우에 쓴다.)&lt;/li&gt;
&lt;li&gt;연결&amp;nbsp;대체&lt;br /&gt;(  절차 지향 언어에서 Linke 를 이용한 테스트 용 다형성을 지원하는 방법이라고 이해됨)&lt;/li&gt;
&lt;li&gt;생성자&amp;nbsp;매개변수화&lt;br /&gt;생성자 안에서 하나의 객체를 생성하는 경우, 가장 쉽게 대체하는 방법은 생성을 외부화하는 것이다.&lt;br /&gt;(  new 인스턴스를 생성자로 전달하는 새로운 생성자를 따로 만드는 방법)&lt;/li&gt;
&lt;li&gt;메소드&amp;nbsp;매개변수화&lt;/li&gt;
&lt;li&gt;매개변수&amp;nbsp;원시화&lt;/li&gt;
&lt;li&gt;특징&amp;nbsp;끌어올리기&lt;/li&gt;
&lt;li&gt;의존&amp;nbsp;관계&amp;nbsp;밀어&amp;nbsp;내리기&lt;br /&gt;현재 클래스를 추상으로 만들고 새로운 배포용 클래스가 될 서브 클래스를 하나 생성한다. 그리고 모든 골칫거리 의존 관계를 그 클래스 안으로 밀어 내린다.&lt;/li&gt;
&lt;li&gt;함수를&amp;nbsp;함수&amp;nbsp;포인터로&amp;nbsp;대체&lt;br /&gt;(  회사에서 테스트 가능하게 구조를 변경하는 방법에 대해서 논의한 적이 있는데, Repository 대신 메소드를 전달하자는 의견을 낸적이 있음. 이와 상당히 유사한 듯. 절차 지향 언어에서 사용해볼만하다.)&lt;/li&gt;
&lt;li&gt;전역&amp;nbsp;참조를&amp;nbsp;get&amp;nbsp;메소드로&amp;nbsp;대체&lt;/li&gt;
&lt;li&gt;서브클래스화와&amp;nbsp;메소드&amp;nbsp;재정의&lt;br /&gt;객체 지향 프로그램에서 의존 관계를 제거하는데 사용되는 주요 기법. 실제로 다른 기법은 이 기법의 변종이라고 할 수 있다.&lt;/li&gt;
&lt;li&gt;인스턴스&amp;nbsp;변수&amp;nbsp;대체&lt;/li&gt;
&lt;li&gt;템플릿&amp;nbsp;재정의&lt;/li&gt;
&lt;li&gt;텍스트&amp;nbsp;재정의&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(  결국 모든 기법이 테스트를 위한 fake 를 전달하기 위해 사용되는 방법들이라고 보인다. 리플렉션 같은 기능을 이용한 강제 fake 주입 방법보다, 설계를 이용하여 fake 를 전달하도록 해서 유연한 설계에 더 가까워지도록 할 수 있는 방법들인 듯)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;매개변수 적용&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;매개변수 적용 기법 적용 전&lt;/p&gt;
&lt;pre id=&quot;code_1650215901534&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class ARMDispatcher {
    public void populate(HttpServletRequest request) {
        String[] values = request.getParameterValues(pageStateName);
        if (values != null &amp;amp;&amp;amp; values.length &amp;gt; 0) {
            marketBindings.put(pageStateName + getDateStamp(), values[0]);
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;매개변수 적은 기법 적용 후&lt;/p&gt;
&lt;pre id=&quot;code_1650216021687&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class ARMDispatcher
    public void populate(ParameterSource source) {
        String values = source.getParameterForName(pageStateName);
        if (value != null) {
            marketBindings.put(pageStateName + getDateStamp(), value);
        }
    }
}

class ServletParameterSource implements ParameterSource {
    private HttpServletRequest request;
    public ServletParameterSource(HttpServletRequest request) {
        this.request = request;
    }
    String getParameterValue(String name) {
        String[] values = request.getParameterValues(name);
        if (values == null || values.length &amp;lt; 1)
            return null;
        return values[0];
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;생성자 매개변수화&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;생성자 매개변수화 적용 전&lt;/p&gt;
&lt;pre id=&quot;code_1650216490226&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class MailChecker {
    public MailChecker(int checkPeriodSeconds) {
        this.receiver = new MailReceiver();
        this.checkPeriodSeconds = checkPeriodSeconds;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;생성자 매개변수화 적용 후&lt;/p&gt;
&lt;pre id=&quot;code_1650216523417&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class MailChecker {
    public MailChecker(int checkPeriodSeconds) {
        this(new MailReceiver(), checkPeriodSeconds);
    }
    public MailChecker(MailReceiver receiver,
        int checkPeriodSeconds) {
        this.receiver = receiver;
        this.checkPeriodSeconds = checkPeriodSeconds;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;기타&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;xUnit 테스트 프레임 워크는 원래 켄트 벡이 스몰토크로 작성한 것이다. 나중에 켄트벡과 에릭 감마가 자바로 이식한 것이 JUnit 이다.&lt;/li&gt;
&lt;li&gt;좋은 설계는 테스트 가능한 설계며, 테스트 불가능한 설계는 나쁜 설계다.&lt;/li&gt;
&lt;li&gt;아키텍트는 개발 팀에 참여해 매일 함께 일해야한다. 아키텍트가 따로 있는 것은 좋지만, 아키텍쳐를 유지하려면 팀원 전체가 아키텍처가 무엇인지 알고 관심을 기울여야 한다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;신규 기능을 추가할 때보다 레거시 코드를 다룰 때가 설계 스킬을 발휘할 기회가 훨씬 많다.&lt;/li&gt;
&lt;li&gt;인터페이스 수준에서 단일 책임 원칙을 도입하려면 더 많은 작업이 필요하다. 구현 수준에서 단일 책임 원칙을 제대로 도입하면, 인터페이스 수준에서도 도입하기가 쉽다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;클래스를 추출할 때 발생하는 버그 중에서 가장 찾기 어려운 것은 상속 관련 버그다. 메소드를 어떤 클래스에서 다른 클래스로 옮기는 것은 상대적으로 매우 안전한 작업이다. 컴파일러가 사라진 메소드에 대한 알람을 띄워주기 때문이다. 하지만 상속을 이용하고 있는 클래스라면 이야기가 달라진다. 메소드를 옮기고 나면 기초 클래스 내에 있는 동일한 이름의 메소드 호출이 되기 때문에 컴파일러가 이를 찾지 못한다.&lt;/li&gt;
&lt;li&gt;약어 사용은 지양한다. (378p)&lt;/li&gt;
&lt;li&gt;일반적으로 기본 객체들을 변경하는 set 메소드를 제공하는 것은 좋지 않은 관례다. 이러한 set 메소드들은 클라이언트들이 객체가 살아있는 동안 그 객체의 동작을 완전히 변경하게 만들기도 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(  TDD, DDD, SOLID, OOP, 설계 공부를 하면할 수록 모두가 가리키고 있는 어떤 하나의 그림이 있다는 것을 느낀다. 결국 테스트하기 쉬운 코드가 좋은 코드고 테스트를 고려한 코드가 확장에도 유리한 코드다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>[공부] 독서/레거시 코드 활용 전략</category>
      <category>레거시</category>
      <category>레거시 코드</category>
      <category>레거시 코드 활용 전략</category>
      <category>테스트</category>
      <author>kok202</author>
      <guid isPermaLink="true">https://kok202.tistory.com/346</guid>
      <comments>https://kok202.tistory.com/346#entry346comment</comments>
      <pubDate>Mon, 18 Apr 2022 02:42:10 +0900</pubDate>
    </item>
    <item>
      <title>테스트 주도 개발로 배우는 객체 지향 설계와 실천</title>
      <link>https://kok202.tistory.com/345</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a href=&quot;http://www.yes24.com/Product/Goods/9008455&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;http://www.yes24.com/Product/Goods/9008455&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1649082268335&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;book&quot; data-og-title=&quot;테스트 주도 개발로 배우는 객체 지향 설계와 실천 - YES24&quot; data-og-description=&quot;TDD로 좀 더 탄탄한 객체 지향 개발을 이끄는 안내서 소프트웨어 개발의 여러 층위에서 TDD가 어떻게 작동하는지 보여주면서 테스트로 코드를 객체 지향적으로 구성하고 기능을 구현하며 목 객체&quot; data-og-host=&quot;www.yes24.com&quot; data-og-source-url=&quot;http://www.yes24.com/Product/Goods/9008455&quot; data-og-url=&quot;http://www.yes24.com/Product/Goods/9008455&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/S6WUo/hyNUsgZwtY/d4MMyVIYQh8Ktxbg2cekKk/img.jpg?width=313&amp;amp;height=400&amp;amp;face=0_0_313_400,https://scrap.kakaocdn.net/dn/GHWOM/hyNVL64WuG/SyvJ1RqgzYQnGhhO2ED5Lk/img.jpg?width=313&amp;amp;height=400&amp;amp;face=0_0_313_400,https://scrap.kakaocdn.net/dn/buIgAr/hyNVJBqill/BRyi041jPtgMHIaNXUsn01/img.jpg?width=313&amp;amp;height=400&amp;amp;face=0_0_313_400&quot;&gt;&lt;a href=&quot;http://www.yes24.com/Product/Goods/9008455&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;http://www.yes24.com/Product/Goods/9008455&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/S6WUo/hyNUsgZwtY/d4MMyVIYQh8Ktxbg2cekKk/img.jpg?width=313&amp;amp;height=400&amp;amp;face=0_0_313_400,https://scrap.kakaocdn.net/dn/GHWOM/hyNVL64WuG/SyvJ1RqgzYQnGhhO2ED5Lk/img.jpg?width=313&amp;amp;height=400&amp;amp;face=0_0_313_400,https://scrap.kakaocdn.net/dn/buIgAr/hyNVJBqill/BRyi041jPtgMHIaNXUsn01/img.jpg?width=313&amp;amp;height=400&amp;amp;face=0_0_313_400');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;테스트 주도 개발로 배우는 객체 지향 설계와 실천 - YES24&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;TDD로 좀 더 탄탄한 객체 지향 개발을 이끄는 안내서 소프트웨어 개발의 여러 층위에서 TDD가 어떻게 작동하는지 보여주면서 테스트로 코드를 객체 지향적으로 구성하고 기능을 구현하며 목 객체&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.yes24.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;코드 레벨에 대한 설명이 많아 이는 생략하고 보편적인 가치 위주로 정리합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; ) 은 사견입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;앨런 케이 어록 &lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;객체란 서로 메시지를 주고받는 생물학적 세포와 비슷해야한다.&lt;/li&gt;
&lt;li&gt;중요한&amp;nbsp;것은&amp;nbsp;메시지&amp;nbsp;전달이며&amp;nbsp;위대하고&amp;nbsp;성장&amp;nbsp;가능한&amp;nbsp;시스템을&amp;nbsp;만들&amp;nbsp;때의&amp;nbsp;핵심은&amp;nbsp;모듈&amp;nbsp;간의&amp;nbsp;의사소통에&amp;nbsp;있지&amp;nbsp;모듈의&amp;nbsp;내부&amp;nbsp;특성이나&amp;nbsp;작동&amp;nbsp;방식에&amp;nbsp;있지&amp;nbsp;않다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;품질&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;외부 품질은 시스템이 고객과 사용자의 요구를 얼마나 잘 충족하는 가이다.&lt;/li&gt;
&lt;li&gt;내부 품질은 시스템템이 개발자와 관리자의 요구를 얼마나 잘 충족하는 가이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;결합도&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오디오 콤보&amp;nbsp;&amp;nbsp;시스템템을&amp;nbsp;&amp;nbsp;생각해해보자 오디오 콤보 시스템은 긴밀하게 결합돼있다. 아날로그 라디오를 디지털 라이도로 바꾸고 싶다면 전체 시스템을 다시 구성해야한다. 반대로 만약 컴포넌트를 갖고 시스템을 조립했다면 느슨한 결합도로 수신기만 교체했어도 됬을 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;응집도&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;응집도가 높은 기능은 유지보수하기 쉬워진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;선언적&amp;nbsp;정의&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체 구성을 관리할 목적으로 작성하는 코드를 객체망의 행위에 대한 선언적 정의라고 한다. 시스템을 선언적 정의 방식으로 구축하면 방법이 아니라 목적에 집중할 수 있어 시스템의 행위를 변경하기 쉽게 도와준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Value&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Value 는 양이 고정된 불변 인스턴스다 값은 개별적인 식별자가 없으므로 두 값 인스턴스의 상태가 같다면 사실상 동일한 셈이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;객체&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이&amp;nbsp;책에서는&amp;nbsp;객체라는&amp;nbsp;용어를&amp;nbsp;값에&amp;nbsp;사용하지&amp;nbsp;않으며&amp;nbsp;식별자와&amp;nbsp;상태,&amp;nbsp;처리&amp;nbsp;과정을&amp;nbsp;지닌&amp;nbsp;인스턴스를&amp;nbsp;가리킬&amp;nbsp;때만&amp;nbsp;사용한다.&lt;/li&gt;
&lt;li&gt;객체는&amp;nbsp;역할을&amp;nbsp;하나&amp;nbsp;이상&amp;nbsp;구현한&amp;nbsp;것이며&amp;nbsp;역할은&amp;nbsp;관련된&amp;nbsp;책임의&amp;nbsp;집합이다.&amp;nbsp;책임은&amp;nbsp;어떤&amp;nbsp;과업을&amp;nbsp;수행하거나&amp;nbsp;정보를&amp;nbsp;알아야하는&amp;nbsp;의무를&amp;nbsp;말한다.&amp;nbsp;협력은&amp;nbsp;객체나&amp;nbsp;역할의&amp;nbsp;상호&amp;nbsp;작용에&amp;nbsp;해당한다.&lt;/li&gt;
&lt;li&gt;우리가&amp;nbsp;생각하기에&amp;nbsp;도메인&amp;nbsp;모델은&amp;nbsp;의러한&amp;nbsp;의사소통&amp;nbsp;패턴에&amp;nbsp;속한다.&lt;/li&gt;
&lt;li&gt;객체의&amp;nbsp;호출자는&amp;nbsp;객체가&amp;nbsp;무슨일을&amp;nbsp;하고&amp;nbsp;무엇을&amp;nbsp;의존하는지&amp;nbsp;알고&amp;nbsp;싶어하지&amp;nbsp;어떻게&amp;nbsp;동작하는지를&amp;nbsp;알고&amp;nbsp;싶어&amp;nbsp;하지&amp;nbsp;않는다.&lt;/li&gt;
&lt;li&gt;객체를&amp;nbsp;부분적으로&amp;nbsp;생성하고&amp;nbsp;해당&amp;nbsp;객체의&amp;nbsp;프로퍼티를&amp;nbsp;설정하는&amp;nbsp;식으로&amp;nbsp;마무리하는&amp;nbsp;것은&amp;nbsp;불안정한&amp;nbsp;방법이다.&amp;nbsp;프로그래머가&amp;nbsp;필요한&amp;nbsp;의존성을&amp;nbsp;모두&amp;nbsp;설정하는&amp;nbsp;것을&amp;nbsp;기억해야하기&amp;nbsp;때문이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;협업하는 객체&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;의존성: 한 객체가 자신의 역할을 수행할 수 있게 이웃하는 객체에게 요구하는 서비스다.&lt;/li&gt;
&lt;li&gt;알림: 객체의 상태가 변경되었거나 중요한 활동을 할 때 이웃에게 알리는 경우다.&lt;/li&gt;
&lt;li&gt;조정: 객체의 행위를 더 넓은 시스템의 요건에 맞게 조정하는 경우다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;디미터의&amp;nbsp;법칙&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;묻지말고 말하라 스타일&lt;/li&gt;
&lt;li&gt;객체는&amp;nbsp;다른&amp;nbsp;객체를&amp;nbsp;탐색해&amp;nbsp;뭔가를&amp;nbsp;일어나게&amp;nbsp;해서는&amp;nbsp;안된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;TDD 시작하기&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;TDD&amp;nbsp;를&amp;nbsp;시작하기&amp;nbsp;전에&amp;nbsp;최초&amp;nbsp;기능은&amp;nbsp;어떨까?&amp;nbsp;인수&amp;nbsp;테스트의&amp;nbsp;일환으로&amp;nbsp;테스트는&amp;nbsp;전&amp;nbsp;구간을&amp;nbsp;대상으로&amp;nbsp;실행되어&amp;nbsp;시스템의&amp;nbsp;외부&amp;nbsp;인터페이스에&amp;nbsp;관해&amp;nbsp;필요한&amp;nbsp;피드백을&amp;nbsp;줘야한다.&lt;/li&gt;
&lt;li&gt;자동화된&amp;nbsp;빌드,&amp;nbsp;배포,&amp;nbsp;테스트&amp;nbsp;주기&amp;nbsp;전체를&amp;nbsp;구현해야한다.&amp;nbsp;이렇게&amp;nbsp;하려면&amp;nbsp;첫&amp;nbsp;테스트가&amp;nbsp;실패하는&amp;nbsp;것을&amp;nbsp;보기도&amp;nbsp;전에&amp;nbsp;해야&amp;nbsp;할&amp;nbsp;일이&amp;nbsp;굉장히&amp;nbsp;많다.&lt;/li&gt;
&lt;li&gt;우선&amp;nbsp;동작하는&amp;nbsp;골격을&amp;nbsp;대상으로&amp;nbsp;테스트하고&amp;nbsp;동작하는&amp;nbsp;골격을&amp;nbsp;만드는&amp;nbsp;동안에&amp;nbsp;골격의&amp;nbsp;구조에&amp;nbsp;집중한다.&amp;nbsp;테스트가&amp;nbsp;최대한&amp;nbsp;표현력을&amp;nbsp;갖추게끔&amp;nbsp;테스트를&amp;nbsp;정리하는&amp;nbsp;일에&amp;nbsp;대해서는&amp;nbsp;크게&amp;nbsp;신경쓰지&amp;nbsp;않는다.&lt;/li&gt;
&lt;li&gt;첫&amp;nbsp;테스트의&amp;nbsp;맥락은&amp;nbsp;코딩을&amp;nbsp;시작하기&amp;nbsp;전에&amp;nbsp;전체&amp;nbsp;설계를&amp;nbsp;클래스와&amp;nbsp;알고리즘&amp;nbsp;수준까지&amp;nbsp;끌어내려&amp;nbsp;정교하게&amp;nbsp;다듬자는&amp;nbsp;것이&amp;nbsp;아니다.&lt;br /&gt;피드백&amp;nbsp;소스를&amp;nbsp;구축하고&amp;nbsp;불확실성을&amp;nbsp;일찍&amp;nbsp;드러내기&amp;nbsp;위함이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;TDD 주기와 유지&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;도메인&amp;nbsp;모델&amp;nbsp;객체에&amp;nbsp;단위&amp;nbsp;테스트를&amp;nbsp;수행한&amp;nbsp;다음&amp;nbsp;애플리케이션의&amp;nbsp;나머지&amp;nbsp;부분에&amp;nbsp;해당&amp;nbsp;객체를&amp;nbsp;끼워넣는&amp;nbsp;식으로&amp;nbsp;TDD&amp;nbsp;를&amp;nbsp;시작할&amp;nbsp;수&amp;nbsp;있다.&amp;nbsp;이&amp;nbsp;방식은&amp;nbsp;쉬워보이지만&amp;nbsp;나중에&amp;nbsp;통합할&amp;nbsp;때&amp;nbsp;골머리를&amp;nbsp;앓을&amp;nbsp;가능성이&amp;nbsp;높다.&amp;nbsp;불필요하거나&amp;nbsp;올바르지&amp;nbsp;않은&amp;nbsp;기능을&amp;nbsp;구현하느라&amp;nbsp;시간을&amp;nbsp;낭비하고&amp;nbsp;있는&amp;nbsp;것일&amp;nbsp;수도&amp;nbsp;있기&amp;nbsp;때문이다.&lt;/li&gt;
&lt;li&gt;경험상&amp;nbsp;코드가&amp;nbsp;테스트&amp;nbsp;하기&amp;nbsp;어렵다면&amp;nbsp;주로&amp;nbsp;설계&amp;nbsp;개선이&amp;nbsp;필요하기&amp;nbsp;때문이다.&lt;/li&gt;
&lt;li&gt;너무&amp;nbsp;큰&amp;nbsp;단위로&amp;nbsp;테스트를&amp;nbsp;수행하면&amp;nbsp;코드의&amp;nbsp;모든&amp;nbsp;가능한&amp;nbsp;경로를&amp;nbsp;시도하는&amp;nbsp;조합&amp;nbsp;폭발&amp;nbsp;현상으로&amp;nbsp;개발이&amp;nbsp;중단된다.&amp;nbsp;반면&amp;nbsp;테스트&amp;nbsp;단위를&amp;nbsp;너무&amp;nbsp;세밀하게&amp;nbsp;잡으면&amp;nbsp;테스트하기는&amp;nbsp;쉬워지지만&amp;nbsp;동작하지&amp;nbsp;않는&amp;nbsp;객체에서&amp;nbsp;유래하는&amp;nbsp;문제를&amp;nbsp;놓치고&amp;nbsp;말것이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;설계&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;우리는&amp;nbsp;작성하기&amp;nbsp;쉬운&amp;nbsp;코드보다&amp;nbsp;유지&amp;nbsp;보수하기&amp;nbsp;쉬운&amp;nbsp;코드를&amp;nbsp;높게&amp;nbsp;평가한다.&lt;/li&gt;
&lt;li&gt;전체는&amp;nbsp;부분의&amp;nbsp;합보다&amp;nbsp;단순해야한다.&amp;nbsp;(복합&amp;nbsp;객체의&amp;nbsp;API&amp;nbsp;는&amp;nbsp;구성&amp;nbsp;요소의&amp;nbsp;API&amp;nbsp;보다&amp;nbsp;복잡해서는&amp;nbsp;안된다.)&lt;/li&gt;
&lt;li&gt;인터페이스에&amp;nbsp;선언되는&amp;nbsp;메서드&amp;nbsp;수가&amp;nbsp;적을수록&amp;nbsp;해당&amp;nbsp;메서드를&amp;nbsp;호출하는&amp;nbsp;객체의&amp;nbsp;역할이&amp;nbsp;명확해진다.&lt;/li&gt;
&lt;li&gt;우리는&amp;nbsp;클래스보다&amp;nbsp;인터페이스를&amp;nbsp;강조한다.&amp;nbsp;다른&amp;nbsp;객체에서&amp;nbsp;보는&amp;nbsp;것은&amp;nbsp;결국&amp;nbsp;인터페이스이기&amp;nbsp;때문이다.&lt;/li&gt;
&lt;li&gt;우리는&amp;nbsp;객체에&amp;nbsp;대한&amp;nbsp;클래스를&amp;nbsp;구현&amp;nbsp;세부&amp;nbsp;사항으로&amp;nbsp;본다.&lt;/li&gt;
&lt;li&gt;우리는 애플리케이션 개발을 위한 점진적 개발 단계를 파악할 수 있어야한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;지나간&amp;nbsp;일은&amp;nbsp;눈에&amp;nbsp;잘&amp;nbsp;보이지&amp;nbsp;않는다.&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;'왜 진작 알아차리지 못했을까'하는 생각이 드는 순간들이 있다.&amp;nbsp;&amp;nbsp;분명 설계에 시간을 더 들인다면 설계를 변경하지 않아도 됬을것이다. 정말 그럴까? 그럴 때도 있지만 &lt;b&gt;경험상 설계를 직접 구현해 보는 것만큼 설계에 영향을 주는 것은 없다&lt;/b&gt;. 우리 주변에 설계를 늘 올바른 상태로 유지할 만큼 똑똑한 사람은 얼마 되지 않는다. 우리의 문제 해결 메커니즘은 코드의 핵심 영역으로 좀 더 일찍 파고들어 집단적인 사고를 바꾸는 것이다. 뭔가를 변경할 때 현재 기술로 작은 단계를 밟아가며 테스트해 실수를 막는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Context 독립&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;각&amp;nbsp;객체가&amp;nbsp;해당&amp;nbsp;객체를&amp;nbsp;실행하는&amp;nbsp;시스템에&amp;nbsp;관해&amp;nbsp;아무것도&amp;nbsp;알지&amp;nbsp;못하는&amp;nbsp;것을&amp;nbsp;의미한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;TDD 의 가치&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;TDD&amp;nbsp;의&amp;nbsp;테스트&amp;nbsp;부문에서&amp;nbsp;얻을&amp;nbsp;수&amp;nbsp;있는&amp;nbsp;최고의&amp;nbsp;혜택은&amp;nbsp;코드를&amp;nbsp;망가뜨리지&amp;nbsp;않고도&amp;nbsp;변경할&amp;nbsp;수&amp;nbsp;있다는&amp;nbsp;자신감이다.&lt;/li&gt;
&lt;li&gt;테스트를&amp;nbsp;먼저&amp;nbsp;작성함으로써&amp;nbsp;총&amp;nbsp;세가지&amp;nbsp;가치를&amp;nbsp;얻을&amp;nbsp;수&amp;nbsp;있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;어떻게를 고려하기 전에 달성하고자 하는 바가 무엇인지를 기술하게 만든다.&lt;/li&gt;
&lt;li&gt;테스트 대상 컴포넌트의 규모가 너무 커서 좀 더 작은 컴포넌트로 쪼개야함을 말해준다.&lt;/li&gt;
&lt;li&gt;단위 테스트를 위한 객체를 만들려면 해당 객체의 의존성을 전달해야 하는데, 이러한 의존성이 어디에 있는지를 알아야하게 만든다. 이를 통해 Context 독립성이 높아지는데, 단위 테스트를 구성하기 앞서 대상 객체의 환경을 구성할 수 있어야 하기 때문이다. 객체의 테스트가 어려우다면 의존성 정리가 필요하다는 신호다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;TDD 와 의존성&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;테스트를&amp;nbsp;통해&amp;nbsp;우리는&amp;nbsp;의존하는&amp;nbsp;것이&amp;nbsp;무엇인지&amp;nbsp;알고&amp;nbsp;싶다.&lt;/li&gt;
&lt;li&gt;암시적인&amp;nbsp;의존성도&amp;nbsp;의존성이다.&amp;nbsp;전역&amp;nbsp;값을&amp;nbsp;사용해&amp;nbsp;캡슐화를&amp;nbsp;우회하는&amp;nbsp;것은&amp;nbsp;의존성을&amp;nbsp;감출수&amp;nbsp;있지만,&amp;nbsp;의존성이&amp;nbsp;사라진&amp;nbsp;것은&amp;nbsp;아니다.&amp;nbsp;단지&amp;nbsp;의존성에&amp;nbsp;접근할&amp;nbsp;수&amp;nbsp;없게&amp;nbsp;될&amp;nbsp;뿐이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;TDD 팁&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;서드 파티 API 를 사용하는 경우 어댑터 패턴을 사용할 수 있다. 어댑터 계층은 가능한 얇게 유지하라, 잠재적으로 불안정하고 테스트하기 어려운 코드양을 줄이기 위해서다. (  서드 파티 API 를 Mock 하지 말고 어댑터 계층을 Mock 하여 테스트하라.)&lt;/li&gt;
&lt;li&gt;코드를&amp;nbsp;컴파일&amp;nbsp;가능한&amp;nbsp;상태로&amp;nbsp;유지하라.&amp;nbsp;컴파일이&amp;nbsp;실패할&amp;nbsp;때&amp;nbsp;컴파일러를&amp;nbsp;통해&amp;nbsp;그러한&amp;nbsp;부분에&amp;nbsp;관해&amp;nbsp;알&amp;nbsp;수&amp;nbsp;없으면&amp;nbsp;변경&amp;nbsp;범위가&amp;nbsp;어떻게&amp;nbsp;되는지&amp;nbsp;확실할&amp;nbsp;수&amp;nbsp;없다.&amp;nbsp;컴파일&amp;nbsp;실패는&amp;nbsp;해당&amp;nbsp;브랜치로&amp;nbsp;체크인&amp;nbsp;할&amp;nbsp;수&amp;nbsp;없다는&amp;nbsp;의미이다.&lt;/li&gt;
&lt;li&gt;종종&amp;nbsp;테스트하기&amp;nbsp;어려운&amp;nbsp;기능을&amp;nbsp;발견하면&amp;nbsp;우리는&amp;nbsp;단순히&amp;nbsp;해당&amp;nbsp;기능을&amp;nbsp;어떻게&amp;nbsp;테스트하는지&amp;nbsp;고민하는게&amp;nbsp;아니라&amp;nbsp;왜&amp;nbsp;테스트하기&amp;nbsp;어려운지도&amp;nbsp;자문해본다.&lt;/li&gt;
&lt;li&gt;마법을&amp;nbsp;쓰지않고&amp;nbsp;대체할&amp;nbsp;수&amp;nbsp;없는&amp;nbsp;객체에&amp;nbsp;대해&amp;nbsp;Mock&amp;nbsp;객체를&amp;nbsp;적용해야한다.&lt;/li&gt;
&lt;li&gt;(  생성자가 비대해진다면 둘 중 하나다. 1. 응집도가 낮거나, 2. 역할이 과다한 것이다.)&lt;/li&gt;
&lt;li&gt;객체가&amp;nbsp;역할이&amp;nbsp;너무&amp;nbsp;많다면&amp;nbsp;객체&amp;nbsp;자체의&amp;nbsp;규모가&amp;nbsp;너무&amp;nbsp;크다는&amp;nbsp;것을&amp;nbsp;의미할지&amp;nbsp;모른다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;then&amp;nbsp;구문을&amp;nbsp;조금만&amp;nbsp;작성하라.&amp;nbsp;너무&amp;nbsp;많은&amp;nbsp;예상구문이&amp;nbsp;필요하다는&amp;nbsp;것은&amp;nbsp;너무&amp;nbsp;큰&amp;nbsp;단위로&amp;nbsp;테스트하려는&amp;nbsp;것&amp;nbsp;일&amp;nbsp;수&amp;nbsp;있다.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;단위테스트는&amp;nbsp;1000줄&amp;nbsp;이상이어서는&amp;nbsp;안된다.&lt;/li&gt;
&lt;li&gt;지식의&amp;nbsp;초점이&amp;nbsp;특정&amp;nbsp;객체에&amp;nbsp;초점이&amp;nbsp;맞춰지도록&amp;nbsp;한다.&lt;/li&gt;
&lt;li&gt;데이터&amp;nbsp;대신&amp;nbsp;행위를&amp;nbsp;전달하라.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Bad case&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;테스트&amp;nbsp;이름이&amp;nbsp;테스트의&amp;nbsp;의도를&amp;nbsp;설명하지&amp;nbsp;못한다.&lt;/li&gt;
&lt;li&gt;테스트&amp;nbsp;케이스가&amp;nbsp;여러&amp;nbsp;기능을&amp;nbsp;테스트한다.&lt;/li&gt;
&lt;li&gt;테스트&amp;nbsp;구조가&amp;nbsp;달라서&amp;nbsp;테스트를&amp;nbsp;보는&amp;nbsp;것만으로&amp;nbsp;의도를&amp;nbsp;이해할&amp;nbsp;수&amp;nbsp;없다.&lt;/li&gt;
&lt;li&gt;테스트를&amp;nbsp;준비하는&amp;nbsp;코드가&amp;nbsp;너무&amp;nbsp;많아&amp;nbsp;핵심&amp;nbsp;로직이&amp;nbsp;묻힌다.&lt;/li&gt;
&lt;li&gt;매직 넘버를 사용하지만 그 숫자가 무엇을 의미하는지는 명확하지 않다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;불안정한 테스트의 원인&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;1.&amp;nbsp;테스트가&amp;nbsp;시스템에&amp;nbsp;관련&amp;nbsp;없는&amp;nbsp;부분과&amp;nbsp;테스트&amp;nbsp;대상&amp;nbsp;객체에&amp;nbsp;무관한&amp;nbsp;행위와&amp;nbsp;너무&amp;nbsp;긴밀하게&amp;nbsp;결합되어&amp;nbsp;있다.&lt;/li&gt;
&lt;li&gt;2.&amp;nbsp;테스트가&amp;nbsp;코드의&amp;nbsp;예상&amp;nbsp;행위를&amp;nbsp;과도하게&amp;nbsp;기술해서&amp;nbsp;필요&amp;nbsp;이상으로&amp;nbsp;제약한다.&lt;/li&gt;
&lt;li&gt;3.&amp;nbsp;테스트에서&amp;nbsp;동일한&amp;nbsp;제품&amp;nbsp;코드의&amp;nbsp;행위를&amp;nbsp;시험할&amp;nbsp;때&amp;nbsp;중복이&amp;nbsp;생긴다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;테스트의 핵심&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;테스트의&amp;nbsp;핵심은&amp;nbsp;표현력이다.&amp;nbsp;테스트를&amp;nbsp;읽는&amp;nbsp;사람이&amp;nbsp;뭐가&amp;nbsp;중요한지&amp;nbsp;가늠할&amp;nbsp;수&amp;nbsp;있어야한다.&lt;/li&gt;
&lt;li&gt;테스트의 핵심은 통과가 아니라 실패에 있다. 프로젝트가 테스트를 통과하길 바랄 뿐만 아니라, 테스트가 실제로 존재하는 오류를 감지해 보고하게 만들수도 있어야한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;테스트&amp;nbsp;데이터&amp;nbsp;빌더&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;도메인&amp;nbsp;객체를&amp;nbsp;만들때&amp;nbsp;준비해야할&amp;nbsp;게&amp;nbsp;많다면&amp;nbsp;빌더를&amp;nbsp;이용할&amp;nbsp;수&amp;nbsp;있다.&amp;nbsp;빌더는&amp;nbsp;아래와&amp;nbsp;같은&amp;nbsp;역할을&amp;nbsp;한다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;새로운 객체 생성시 문법적으로 지저분한 부분을 감춰준다.&lt;/li&gt;
&lt;li&gt;기본적인 경우에도 단순하게하고 특별한 테스트일 때도 복잡하게 만들지 않는다.&lt;/li&gt;
&lt;li&gt;객체의 구조적 변화로 부터 테스트 케이스를 보호한다.&lt;/li&gt;
&lt;li&gt;빌더를 이용하면 매개변수의 용도를 밝힐 수 있다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;명령(Command)과&amp;nbsp;질의(Query)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Command&amp;nbsp;는&amp;nbsp;객체의&amp;nbsp;외부&amp;nbsp;세계를&amp;nbsp;바꾸기&amp;nbsp;위해&amp;nbsp;부수&amp;nbsp;효과를&amp;nbsp;낼&amp;nbsp;가능성이&amp;nbsp;있는&amp;nbsp;호출을&amp;nbsp;말한다.&amp;nbsp;메소드&amp;nbsp;호출&amp;nbsp;횟수에&amp;nbsp;따라&amp;nbsp;시스템&amp;nbsp;상태가&amp;nbsp;달라진다.&lt;/li&gt;
&lt;li&gt;Query&amp;nbsp;는&amp;nbsp;세계를&amp;nbsp;바꾸지&amp;nbsp;않아서&amp;nbsp;n&amp;nbsp;번&amp;nbsp;이상&amp;nbsp;호출할&amp;nbsp;수&amp;nbsp;잇는&amp;nbsp;것을&amp;nbsp;말한다.&amp;nbsp;(n&amp;nbsp;&amp;gt;=&amp;nbsp;0)&lt;/li&gt;
&lt;li&gt;명령과&amp;nbsp;질의를&amp;nbsp;구분하여&amp;nbsp;테스트를&amp;nbsp;분리하는&amp;nbsp;것이&amp;nbsp;도움이된다.&lt;/li&gt;
&lt;li&gt;(  책에서는 JMock 을 이와 관련하여 예제가 몇개 나오는데, 이게 진짜로 효용성이 있는지는 긴가민가하다. 부록에나오는 코드도 몇가지 기법은 Interaction Testing 에 가까운 것 같아서... 대신 명령과 질의를 분리하라는 얘기는 꾸준히 다른 책에서도 언급되는 내용이라 굉장히 중요한 가치로 여겨진다.)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;패턴과 타입명&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;책에서는 Repository 나 DAO 패턴을 이용하여 영속성을 구현하는데, 책에서는 이러한 용어를 적극적으로 사용하지 않는다. 이러한 용어를 사용하면 영속화에 대한 지식이 응용 도메인으로 새어나가는 것이기 때문이다. 이는 '포트와 어댑터' 아키텍처를 위반하는 것이다. &lt;b&gt;객체는 영속화 기술에 관해 알 필요가 없어야한다. 중요한 것은 인터페이스 및 클래스와 시스템 내의 다른 클래스와의 관계이다. 어떤 패턴을 쓰고 있는지가 궁금한 것이 아니다.&lt;/b&gt; 따라서 타입명에 Data, Object, Access 같은 일반화된 단어는 가급적 사용을 주의한다. 대신 도메인 개념을 나타내고 애플리케이션과 도메인을 이어주는 방법을 나타내는 이름을 부여하기위해 노력하라.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;비동기 테스트 할 때의 유의사항&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;부하 테스트는 스레드 안전을 보장하지 않는다. 안심할 수 있을 정도만 보장한다.&lt;/li&gt;
&lt;li&gt;비동기적인&amp;nbsp;테스트의&amp;nbsp;경우&amp;nbsp;테스트&amp;nbsp;대상&amp;nbsp;시스템과&amp;nbsp;협력하는&amp;nbsp;것에&amp;nbsp;관해서는&amp;nbsp;신중을&amp;nbsp;기해야한다.&amp;nbsp;그렇지&amp;nbsp;않으면&amp;nbsp;테스트가&amp;nbsp;불안정해져서&amp;nbsp;시스템이&amp;nbsp;동작할&amp;nbsp;때&amp;nbsp;테스트가&amp;nbsp;간헐적으로&amp;nbsp;실패하거나&amp;nbsp;시스템이&amp;nbsp;망가졌을&amp;nbsp;때도&amp;nbsp;테스트가&amp;nbsp;통과할&amp;nbsp;수&amp;nbsp;있다.&lt;br /&gt;테스트에서&amp;nbsp;시스템을&amp;nbsp;관찰하는&amp;nbsp;방법은&amp;nbsp;크게&amp;nbsp;두&amp;nbsp;가지가&amp;nbsp;있다.&amp;nbsp;관찰&amp;nbsp;가능한&amp;nbsp;상태를&amp;nbsp;샘플링하는&amp;nbsp;방법과&amp;nbsp;보내야할&amp;nbsp;이벤트를&amp;nbsp;기다리는&amp;nbsp;방법이다.&lt;/li&gt;
&lt;li&gt;비동기&amp;nbsp;호출이&amp;nbsp;loop&amp;nbsp;를&amp;nbsp;돌며&amp;nbsp;시스템의&amp;nbsp;값을&amp;nbsp;변경시킬&amp;nbsp;경우,&amp;nbsp;polling&amp;nbsp;방식으로&amp;nbsp;하는&amp;nbsp;검증은&amp;nbsp;시스템의&amp;nbsp;변화를&amp;nbsp;놓칠&amp;nbsp;수&amp;nbsp;있다.&amp;nbsp;비동기&amp;nbsp;호출이&amp;nbsp;history&amp;nbsp;를&amp;nbsp;추적할&amp;nbsp;수&amp;nbsp;있게하여&amp;nbsp;호출의&amp;nbsp;결과를&amp;nbsp;확인할&amp;nbsp;수&amp;nbsp;있어야한다.&lt;/li&gt;
&lt;li&gt;몇몇&amp;nbsp;시스템에서는&amp;nbsp;자체&amp;nbsp;이벤트를&amp;nbsp;내부에서&amp;nbsp;일으키도&amp;nbsp;하는데&amp;nbsp;가장&amp;nbsp;흔한&amp;nbsp;것이&amp;nbsp;타이머를&amp;nbsp;이용한&amp;nbsp;스케줄링이다.&amp;nbsp;이럴&amp;nbsp;때&amp;nbsp;사용할&amp;nbsp;수&amp;nbsp;있는&amp;nbsp;유일한&amp;nbsp;해결책은&amp;nbsp;타이머를&amp;nbsp;자체&amp;nbsp;스케줄링에서&amp;nbsp;분리해&amp;nbsp;시스템을&amp;nbsp;결정적으로&amp;nbsp;만드는&amp;nbsp;것이다.&amp;nbsp;이렇게하면&amp;nbsp;테스트에서는&amp;nbsp;스케줄러인&amp;nbsp;척&amp;nbsp;하고&amp;nbsp;이벤트를&amp;nbsp;결정적으로&amp;nbsp;생성해서&amp;nbsp;시스템이&amp;nbsp;각&amp;nbsp;행위를&amp;nbsp;거치게&amp;nbsp;할&amp;nbsp;수&amp;nbsp;있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>[공부] 독서/테스트 주도 개발로 배우는 객체 지향 설계와 실천</category>
      <author>kok202</author>
      <guid isPermaLink="true">https://kok202.tistory.com/345</guid>
      <comments>https://kok202.tistory.com/345#entry345comment</comments>
      <pubDate>Mon, 4 Apr 2022 23:37:01 +0900</pubDate>
    </item>
  </channel>
</rss>