<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>혹독한 겨울에 자라 배울수록 겸손한 보리</title>
    <link>https://cupeanimus.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Mon, 27 Jul 2026 18:34:52 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>보리ing</managingEditor>
    <item>
      <title>헥사고날 아키텍처를 사용해야하는 이유?</title>
      <link>https://cupeanimus.tistory.com/119</link>
      <description>&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;이용자와 트래픽이 많지 않기 때문에 특정 도메인에 필요한 데이터만 많고 나머지는 데이터가 많지 않다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 모듈은 분리되었으나 DB는 통합된 모놀리식과 MSA의 중간형태인, 멀티 모듈 프로젝트가 만들어진다.&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;/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;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;그런데도 사용해?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;헥사고날에서 강조하는 부분은&lt;/p&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;DIP&lt;/li&gt;
&lt;li&gt;3 layer (클린아키텍처)&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 style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;자기 역할만 Port 기반 모킹을 통해 테스트(모킹할 부분이 적다)&lt;/li&gt;
&lt;li&gt;비즈니스로직은 의존성이 없기 때문에 모킹이 거의 없다&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;객체지향에서 강조하는 DIP와 OCP를 자연스럽게 구현
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;plugin architecture &amp;rarr; hexagonal의 adapter&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&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;&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;핵심은 이 아키텍처를 사용하면 자연스럽게 DIP와 OCP를 따르는 코드를 구현하게 된다는 것이다.&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;만드는데의 비용을 3이라면 유지보수 비용을 10이라는 글을 본 적이 있다.&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;</description>
      <author>보리ing</author>
      <guid isPermaLink="true">https://cupeanimus.tistory.com/119</guid>
      <comments>https://cupeanimus.tistory.com/119#entry119comment</comments>
      <pubDate>Wed, 30 Nov 2022 00:43:56 +0900</pubDate>
    </item>
    <item>
      <title>DDD START</title>
      <link>https://cupeanimus.tistory.com/114</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2022-09-12&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;chapter 1&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;p data-ke-size=&quot;size16&quot;&gt;DDD와 MSA에 대한 시도로 블로그 등을 통해 접했던 내용이지만 아주 쉽게 설명한 글을 통해 다시 한 번 정리할 수 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;또한, 작년 우테코 PRO에서 객체지향코드를 강조하며 객체에 불명확한 set 메서드 네임에 대한 이유를 다시 보게 되면서 반가운 감이 있었다. 이를 인지한 상태에서 메서드를 정의할 때, 엔티티에서는 set이 오히려 적절하다고 생각하는 경우가 많아 예시처럼 anti pattern, 피해야하는 규칙을 생각하기 보단 우선적으로 고려하는 것에 따르는게 좋다고 생각하고 있다. 네이밍 같은 경우 책에서 얘기하는 의미 전달이다.&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;2022-09-12&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;chapter 2&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;- 아키텍처&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- DIP&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;- 모듈&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;이 챕터에서는 흔히 사용하고 있는 계층 구조의 구성에 대한 설명과 함께 중요한 개념이 되는 상위 계층에서 하위 계층으로의 의존만 존재하고, 하위 계층은 상위 계층을 의존하지 않는다는 규칙과, 이럴 경우 상위계층에서 하위 계층의 의존으로 인해 테스트가 힘들고, 변경에 취약한 점을 설명하고 적절하게 이를 해결하기 위한 객체지향의 원칙 중 하나인 DIP(Dependency Inversion Principle): 의존 제어 역전 원칙을 통한 해결법을 보여준다. 1장에서 느꼈던 거지만 정말 개발을 시작하는 주니어에게 필요한 지식을 쉽게 잘 설명하고 있는 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한, DIP의 주사항을 얘기하며 DIP의 핵심은 고수준 모듈이 저수준 모듈에 의존하지 않도록 하기 위함인데 구조만 보고 저수준 모듈에서 인터페이스를 추출하면서 DIP를 올바르게 적용한 것이라 착각할 수있는 점을 짚어줬다.&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;b&gt;애그리거트&lt;/b&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;b&gt;2022-09-17&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;chapter 3&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;애그리거트는 프로그래밍을 하면서 자주 마주치는 개념이다. 때문에 대략적으로 이해하고 있었는데 이 챕터를 통해 좀 더 구체적으로 알게 되었다. 애그리거트는 군집화란 것만 이해하고 넘어 갈 수 있는데, 모델링을 할 때 이를 활용한다면 쉽게 표현할 수 있게 된다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;1. 일관성을 관리하는 기준으로 애그리거트를 나눈다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;2. 즉 유사한 개념으로 모으는 것으로 끝나는 것이 아닌, 동일한 라이프사이크를 갖는 객체를 모아 애그리거트를 이루게 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;3. 애그리거트 루트의 핵심은 일관성이 깨지지 않도록 한다.&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;&lt;b&gt;2022-09-18&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;chapter 4, 5&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;애그리거트로 나눈 모델들을 저장소에 저장하고 다루는 방법을 다룬다. 실제로 위 개념을 잘 이해하고 있다 하여도 외부 저장소에 저장하고 꺼내려고 하면 많은 제약과 어려움에 부딪힌다. 자바의 표준 ORM인 JPA를 이용하여 리포지터리와 애그리거트를 구현하는 방법을 설명한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;두 챕터에선 엔티티와 밸류 매핑, 밸류 컬렉션 매핑, 애그리거트 로딩 전략과 영속성 전파, 식별자 생성 기능, 동적인 조회를 위한 JPA스펙 구현, 정렬과 페이징 등 전반적인 기능을 잘 설명해주고 있고, 또한 JPA의 많은 옵션과 기능들의 예시를 보여준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비록 점점 더 MSA로 넘어가고, nosql사용 비중이 높아지며 모델들의 매핑 관계가 단순화되고 있지만, 유용한 옵션과 사용 예시를 잘 보여주고 있다. 특히, 무심코 쓰고 있는 JPA의 구현과 로직이 어떻게 돌아가는지 이해하는데 도움이 되는 내용이 많이 들어 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1232&quot; data-origin-height=&quot;557&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/DdekO/btrMljGxZVE/6RioM6cCz2bm2omZRcur91/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/DdekO/btrMljGxZVE/6RioM6cCz2bm2omZRcur91/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/DdekO/btrMljGxZVE/6RioM6cCz2bm2omZRcur91/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDdekO%2FbtrMljGxZVE%2F6RioM6cCz2bm2omZRcur91%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;1232&quot; height=&quot;557&quot; data-origin-width=&quot;1232&quot; data-origin-height=&quot;557&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2022-09-21&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;chapter 6 응용 서비스와 표현 영역&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;- 표현 영역의 역할&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 값 검증과 권한 검사&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 장에서는 MVC 패턴과 객체지향에 대해 경험이 있는 사람이라면 자연스럽게 읽어 나갈 내용들이 담겨져 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자에게 기능을 제공하기 위해 도메인과 사용자 사이에 표현 영역과 응용 영역을 거치게 되는데 이 영역간 역할에 대한 내용이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;흔히 controller를 표현영역, service를 응용 영역이라 하고 각 영역별 책임을 구분한다.&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;b&gt;표현 영역의 책임&lt;/b&gt;&lt;/p&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;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉 사용자로부터 요청받아 필요한 작업을 수행할 응용 계층으로 연결해주고 결과를 사용자에게 전달하는 것이다.&lt;/p&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;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;&lt;b&gt;단순 조회인 경우는?&amp;nbsp;&lt;/b&gt;굳이 응용 서비스를 만들 필요 없이 응용 계층에서 조회 전용 기능을 사용한다. 응용 서비스가 꼭 존재하고 거쳐야 한다는 강박관념을 가질 필요는 없다. 하지만 팀 내에서 최근에는 규칙에 대한 강박이 있어, 단순 조회기능이라도 반드시 응용계층을 거치는 것으로 결정 되었는데 유연함에 대해 기회가 된다면 다시 나눠보면 좋을 것 같다.&lt;/p&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;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;응용 영역의 책임&lt;/b&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;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;역할을 설명하며 응용 서비스가 도메인 영역과 표현 영역을 연결해주는 창구인 파사드(facade) 역할을 한다고 말한다.&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;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2022-09-21&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;chapter7 도메인 서비스&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;한 애그리거트로 기능을 구현할 수 없을 때가 많다. 여기서는 결제 금액 계산 로직을 예로 두고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;이런 경우에는 어떻게 해야 할까? 주문과 같이 어느 한 애그리거트에서 담당하게 해야 할까? 이렇게 해결 할 수도 있지만 이런 경우 결제 금액 계산에서 할인 정책은 주문의 구성요소와는 거리가 멀지만 주문에서 책임을 갖게 된다. 이렇게 억지로 특정 애그리거트에서 구현하게 되면 자신의 책임의 범위를 넘어서는 기능을 구현하기 때문에 코드가 길어지고 외부에 대한 의존이 높아지게 된다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;도메인 서비스&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;&lt;/b&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>개발/책</category>
      <author>보리ing</author>
      <guid isPermaLink="true">https://cupeanimus.tistory.com/114</guid>
      <comments>https://cupeanimus.tistory.com/114#entry114comment</comments>
      <pubDate>Tue, 13 Sep 2022 02:20:41 +0900</pubDate>
    </item>
    <item>
      <title>스프링 핵심 원리 - 고급편</title>
      <link>https://cupeanimus.tistory.com/107</link>
      <description>&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;2022-05-21&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;매번 느끼는 거지만 김영한님은 친절하게 동작원리를 설명하신다는 거다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(예를들어 @Service, @Repository를 사용하면서 해당 어노테이션에 @Component가 있는 것을 보여주며&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;그리고 우연찮게 얻은 꿀팁은, 에러가 있을때 f2키를 누르면 해당 에러로 바로 이동하는 것이다.&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;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;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;/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-05-22&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;웹 개발자에게 중요한 동시성 문제를 아주 쉽고 간단한 케이스를 통해 경험하고, 이해하여 쉽게 해결하는 방법이 설명되어 있다.&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;그리고 자연스럽게 configuration을 만들고 bean을 등록하고 싱글톤 특성에 대해 알려주는 것 역시 스프링에 대해 완전히 이해하지 못한 이들에게 소중한 영양분이 될 것 같았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막으로 이 챕터의 주제인 쓰레드로컬을 사용하며 동시성 문제를 해결하고, 주의점 마저 친절히 그림과 함께 잘 설명하여 실수로 잘못된 사용을 줄이는 정성을 보였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(ThreadLocal는 생성하는데 비용이 들기 때문에 Thread pool에서 꺼내 재사용하고, 각 Thread의 정보로 Map처럼 정보를 저장하기 때문에 ThreadLocal에 담아 사용한 값은 해당 쓰레드가 종료하기 전에 초기화를 해줘야한다. 그렇지 않으면 memory leak이나 예상치 못한 값을 전달 받을 수 있다.)&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;아. 마지막으로 처음 Bean에서 LogStace의 구현체가 FieldLogStace에서 ThreadLocalLogStace로 대체하는 것만으로 다른 추가작업 없이 간단히 바꾸며 ocp에 대한 얘기 역시 깨알 같았다.&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;2022-06-20&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;간단한 예제를 통해 공통 로그를 담당하는 추상 탬플릿과, 독립적으로 로그를 출력하는 상속하여 구현한 코드를 알아 보았다.&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-06-26&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;탬플릿 메서드 패턴은 기본 골격 구조를 정의하고 구체적인 단계는 서브클래스에서 정의를 하는데, 문제는 이를 위해 서브 클래스는 부모클래스를 상속받는다는 점이다. 때문에 상속을 통한 치명적인 단점. 즉 강 결합 현상이 발생하고, 서브 클래스에서 정의한 부분의 경우 부모클래스 로직을 전혀 사용하지 않는데 항상 함께 하는 불편함이 있다.&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;</description>
      <category>개발/강의</category>
      <author>보리ing</author>
      <guid isPermaLink="true">https://cupeanimus.tistory.com/107</guid>
      <comments>https://cupeanimus.tistory.com/107#entry107comment</comments>
      <pubDate>Sat, 21 May 2022 23:59:58 +0900</pubDate>
    </item>
    <item>
      <title>만들면서 배우는 클린 아키텍처</title>
      <link>https://cupeanimus.tistory.com/106</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;1독(2022-04-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;이 책에서 마음에 들었던 점은 why로 시작하여 how로, 물음표로 시작하여 자연스럽게 느낌표로 끝나도록 서술되어 있다.&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;이미 현재 업무에서 MSA와 헥사고날 아키텍처를 도입하고 있어 익숙한 부분이 많았지만 읽으면서 좀 더 호기심을 갖고 문제를 깊게 생각해볼 수가 있었다.&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;</description>
      <category>개발/책</category>
      <author>보리ing</author>
      <guid isPermaLink="true">https://cupeanimus.tistory.com/106</guid>
      <comments>https://cupeanimus.tistory.com/106#entry106comment</comments>
      <pubDate>Wed, 20 Apr 2022 23:31:16 +0900</pubDate>
    </item>
    <item>
      <title>spring에서 private 테스트는 어떻게 할까? (feat. ReflectionTestUtils, kotlin)</title>
      <link>https://cupeanimus.tistory.com/104</link>
      <description>&lt;pre id=&quot;code_1648391725371&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;ReflectionTestUtils.getField(target(Object or class), fieldName) as fieldType&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;테스트코드를 짜다보면 테스트 후 private field가 제대로 바꼈는지 확인하거나 private fun 을 확인하고 싶을때가 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런경우&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;spring에 내장되어있는 ReflectionTestUtils 를 사용해서 간단히 테스트를 할 수 있다.&lt;/p&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;a href=&quot;https://www.baeldung.com/spring-reflection-test-utils&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://www.baeldung.com/spring-reflection-test-utils&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/test/util/ReflectionTestUtils.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/test/util/ReflectionTestUtils.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 위해 만든 클래스니 간단히 형태만 보자&lt;/p&gt;
&lt;pre class=&quot;kotlin&quot;&gt;&lt;code&gt;class Number(var number: Int, private var bonus: Int = 3) {

    fun add(addedNumber: Int) {
        number += addedNumber
        addBonus()
    }

    private fun addBonus() {
        if (bonus &amp;gt; 0) {
            number++
            bonus--
            return
        }
        refillBonus(10)
    }

    private fun refillBonus(refilledNumber: Int) {
        bonus = refilledNumber

    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같이 number와 bonus값을 입력받아 숫자를 더할때 보너스가 있다면 1씩 추가되는 Number가 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이때 add가 되고나면 bonus가 정상적으로 깎였는지 알고 싶지만, private라 꺼내어 확인할 수 가 없다.&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;&lt;span data-token-index=&quot;0&quot; data-reactroot=&quot;&quot;&gt;ReflectionTestUtils.getField(&lt;/span&gt;&lt;span data-token-index=&quot;1&quot; data-reactroot=&quot;&quot;&gt;target(Object or class)&lt;/span&gt;&lt;span data-token-index=&quot;2&quot; data-reactroot=&quot;&quot;&gt;, &lt;/span&gt;&lt;span data-token-index=&quot;3&quot; data-reactroot=&quot;&quot;&gt;fieldName&lt;/span&gt;&lt;span data-token-index=&quot;4&quot; data-reactroot=&quot;&quot;&gt;) as &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot; data-token-index=&quot;5&quot; data-reactroot=&quot;&quot;&gt;fieldType&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;span style=&quot;color: #000000;&quot; data-token-index=&quot;5&quot; data-reactroot=&quot;&quot;&gt;의 형태로 필드를 가져올 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;@Test
fun `getBonusFieldTest`() {
    // given
    val number = Number(10, 5)

    // when
    number.add(1)

    // then
    val bonus = ReflectionTestUtils.getField(number, &quot;bonus&quot;) as Int
    assertThat(bonus).isEqualTo(4)
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한, addBonus와 refillBonus와 같이 private 메서드를 테스트하고 싶다면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span data-token-index=&quot;0&quot; data-reactroot=&quot;&quot;&gt;ReflectionTestUtils.invokeMethod&amp;lt;Type&amp;gt;(target, methodName, parameters(args))&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span data-token-index=&quot;0&quot; data-reactroot=&quot;&quot;&gt;와 같은 형태로 private 메서드를 실행시켜 테스트를 할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span data-token-index=&quot;0&quot; data-reactroot=&quot;&quot;&gt;method네임 다음부터는 args형태의 파라미터이니, 파라미터 수만큼 순서대로 입력하면 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;@Test
fun `privateAddBonusTest`() {
    // given
    val number = Number(10, 1)

    // when
    ReflectionTestUtils.invokeMethod&amp;lt;Number&amp;gt;(number, &quot;addBonus&quot;)

    // then
    val bonus = ReflectionTestUtils.getField(number, &quot;bonus&quot;) as Int
    assertThat(bonus).isEqualTo(0)
}


@Test
fun `privateRefillBonusTest`() {
    // given
    val number = Number(10, 1)

    // when
    ReflectionTestUtils.invokeMethod&amp;lt;Number&amp;gt;(number, &quot;refillBonus&quot;,10)

    // then
    val bonus = ReflectionTestUtils.getField(number, &quot;bonus&quot;) as Int
    assertThat(bonus).isEqualTo(10)
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>개발/Spring</category>
      <author>보리ing</author>
      <guid isPermaLink="true">https://cupeanimus.tistory.com/104</guid>
      <comments>https://cupeanimus.tistory.com/104#entry104comment</comments>
      <pubDate>Sun, 27 Mar 2022 23:38:51 +0900</pubDate>
    </item>
    <item>
      <title>이펙티브 코틀린</title>
      <link>https://cupeanimus.tistory.com/103</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;아이템1. 가변성을 제한하라(2022-03-07, 2022-04-14)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 불변객체 사용 이점을 설명하며 몇 가지 규칙들에 대해 알려주고 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;주제와 마찬가지로 규칙은 var보다 val, mutable보다 immutable과 같이 불변성 타입을 사용하고, 가변적인 것은 외부 노출을 숨기는 것으로 기본적으로 객체지향을 염두하고 있는 것에서 크게 벗어나지 않고 있다.&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;&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;</description>
      <category>개발/책</category>
      <author>보리ing</author>
      <guid isPermaLink="true">https://cupeanimus.tistory.com/103</guid>
      <comments>https://cupeanimus.tistory.com/103#entry103comment</comments>
      <pubDate>Mon, 7 Mar 2022 02:29:57 +0900</pubDate>
    </item>
    <item>
      <title>@Transactional 옵션을 사용하지 않는다면?</title>
      <link>https://cupeanimus.tistory.com/102</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;일단 기본적으로 @Transactional 에서 많이 사용되는 readOnly 옵션의 default 는 false이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1876&quot; data-origin-height=&quot;630&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ZQC4O/btru7SjQqMC/AAHKECwfAaFSvazJNJOAT1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ZQC4O/btru7SjQqMC/AAHKECwfAaFSvazJNJOAT1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ZQC4O/btru7SjQqMC/AAHKECwfAaFSvazJNJOAT1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZQC4O%2Fbtru7SjQqMC%2FAAHKECwfAaFSvazJNJOAT1%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;1876&quot; height=&quot;630&quot; data-origin-width=&quot;1876&quot; data-origin-height=&quot;630&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;때문에 서비스레벨에서 해당 메서드의 Transaction 관리를 하려고 할때 대부분 @Transactional만 붙이고 있는 것이다.&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;그렇다면 아무런 옵션도 붙이지 않고 jpa를 사용한다면 &lt;/b&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;p data-ke-size=&quot;size16&quot;&gt;우선, spring-data-jpa에서 제공하는 JpaRepository의 기본 구현체는 SimpleJpaRepository이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내부를 들여다보면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에서 알 수 있듯 구현 메서드들의 기본 값은 readonly를 띄고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 C-R-&lt;s&gt;U&lt;/s&gt;-D에 대해 알아보자.&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;Create&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저장하는 메서드에 대해서는 Transactional옵션을 추가 선언하고 있다. 즉 위 default처럼 readonly=false이며 영속성 관리를 한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1238&quot; data-origin-height=&quot;164&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/39f4P/btrvdQNvpID/5WkenTYWPm1s5ygbhqZQEK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/39f4P/btrvdQNvpID/5WkenTYWPm1s5ygbhqZQEK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/39f4P/btrvdQNvpID/5WkenTYWPm1s5ygbhqZQEK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F39f4P%2FbtrvdQNvpID%2F5WkenTYWPm1s5ygbhqZQEK%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;1238&quot; height=&quot;164&quot; data-origin-width=&quot;1238&quot; data-origin-height=&quot;164&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1512&quot; data-origin-height=&quot;184&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/daiPWY/btru9qaWXpp/nuUNVZ97cFC3EGEDkkIJY0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/daiPWY/btru9qaWXpp/nuUNVZ97cFC3EGEDkkIJY0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/daiPWY/btru9qaWXpp/nuUNVZ97cFC3EGEDkkIJY0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdaiPWY%2Fbtru9qaWXpp%2FnuUNVZ97cFC3EGEDkkIJY0%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;1512&quot; height=&quot;184&quot; data-origin-width=&quot;1512&quot; data-origin-height=&quot;184&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;b&gt;Read&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;find 문은 메서드의 override만 하고 있으며 Transaction 옵션에 대한 추가 선언은 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;getById, exists 역시 마찬가지이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1568&quot; data-origin-height=&quot;638&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Beo7m/btru5byWz9A/SNKXVy5YhYqiv3RIfsU2ak/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Beo7m/btru5byWz9A/SNKXVy5YhYqiv3RIfsU2ak/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Beo7m/btru5byWz9A/SNKXVy5YhYqiv3RIfsU2ak/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBeo7m%2Fbtru5byWz9A%2FSNKXVy5YhYqiv3RIfsU2ak%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;1568&quot; height=&quot;638&quot; data-origin-width=&quot;1568&quot; data-origin-height=&quot;638&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1328&quot; data-origin-height=&quot;132&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bMRyYV/btrviIIEBDj/8CHX0403h6MOp9FhLkwLik/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bMRyYV/btrviIIEBDj/8CHX0403h6MOp9FhLkwLik/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bMRyYV/btrviIIEBDj/8CHX0403h6MOp9FhLkwLik/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbMRyYV%2FbtrviIIEBDj%2F8CHX0403h6MOp9FhLkwLik%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;1328&quot; height=&quot;132&quot; data-origin-width=&quot;1328&quot; data-origin-height=&quot;132&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1798&quot; data-origin-height=&quot;434&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bgrYo3/btrvbhyZD7D/Wm9Z0dOGi0u8bu1kIH4591/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bgrYo3/btrvbhyZD7D/Wm9Z0dOGi0u8bu1kIH4591/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bgrYo3/btrvbhyZD7D/Wm9Z0dOGi0u8bu1kIH4591/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbgrYo3%2FbtrvbhyZD7D%2FWm9Z0dOGi0u8bu1kIH4591%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;1798&quot; height=&quot;434&quot; data-origin-width=&quot;1798&quot; data-origin-height=&quot;434&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1834&quot; data-origin-height=&quot;166&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Roa7W/btrvl7A9Y7S/Ok20FkMt2HKzWrpFdgZLyK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Roa7W/btrvl7A9Y7S/Ok20FkMt2HKzWrpFdgZLyK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Roa7W/btrvl7A9Y7S/Ok20FkMt2HKzWrpFdgZLyK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FRoa7W%2Fbtrvl7A9Y7S%2FOk20FkMt2HKzWrpFdgZLyK%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;1834&quot; height=&quot;166&quot; data-origin-width=&quot;1834&quot; data-origin-height=&quot;166&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;b&gt;Delete&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Save와 마찬가지로 @Transactional 을 새로 선언하고 있다. 즉 readonly=false인 것이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1122&quot; data-origin-height=&quot;198&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dGZbKu/btrveKULc9T/BJjT4Yx0XqxkkDqv8KiMFK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dGZbKu/btrveKULc9T/BJjT4Yx0XqxkkDqv8KiMFK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dGZbKu/btrveKULc9T/BJjT4Yx0XqxkkDqv8KiMFK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdGZbKu%2FbtrveKULc9T%2FBJjT4Yx0XqxkkDqv8KiMFK%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;1122&quot; height=&quot;198&quot; data-origin-width=&quot;1122&quot; data-origin-height=&quot;198&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1118&quot; data-origin-height=&quot;224&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/WpPZ4/btrvatrKK1G/DD9WICOFsEOVtpyKC9gbY1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/WpPZ4/btrvatrKK1G/DD9WICOFsEOVtpyKC9gbY1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/WpPZ4/btrvatrKK1G/DD9WICOFsEOVtpyKC9gbY1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FWpPZ4%2FbtrvatrKK1G%2FDD9WICOFsEOVtpyKC9gbY1%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;1118&quot; height=&quot;224&quot; data-origin-width=&quot;1118&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;&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본적으로 Save와 Delete에 대해선 @Transaction 이 사용되고 있다(readOnly = false)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;select문인 find에 대해선 @Transaction(ReadOnly = true) 옵션이 사용되고 있다.&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;즉, jpa를 사용하면서 이미 정의된 메서드를 따로 설정없이 사용한다면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;select&lt;/b&gt; 메서드에 대해선 &lt;b&gt;@Transactional(ReadOnly = true)&lt;/b&gt; 가&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나머지(&lt;b&gt; save, update, delete&lt;/b&gt;)에 대해선&amp;nbsp; &lt;b&gt;@Transactional &lt;/b&gt;이&lt;b&gt; 생략&lt;/b&gt;되어 있다고 생각하면 된다.&lt;/p&gt;</description>
      <category>개발/Spring</category>
      <author>보리ing</author>
      <guid isPermaLink="true">https://cupeanimus.tistory.com/102</guid>
      <comments>https://cupeanimus.tistory.com/102#entry102comment</comments>
      <pubDate>Mon, 7 Mar 2022 02:21:42 +0900</pubDate>
    </item>
    <item>
      <title>소프트웨어 장인</title>
      <link>https://cupeanimus.tistory.com/100</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;(2022-02-12, 2022-03-06)&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;개발자를 택한 순간부터 좋은 개발자가 되길 꿈꾼다. 이 책은 현실적으로 더 좋은 개발자가 되기 위한 길잡이가 되어준다.&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;1. 장인 정신을 갖고 스스로의 기술을 발전 시키고&lt;/b&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;b&gt;2. 좋은 동료들과 함께 더 좋은 개발 문화를 만드는 것&lt;/b&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;/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;1. 커리어의 주인은 나다.&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;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;3. 스스로만의 문제해결 방법 찾기&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;4. 좋은 코드를 위한 노력&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;초판 발행 2015년 9월인 책에서 최근 IT회사에서 강조하고 있는 애자일, TDD, 리팩터링과 같은 내용을 수없이 반복하며 강조하고 있다. 또한, 좋은 코드를 위한 익스트림 코드에 대한 생각은 20년이다 더 되었다. 즉, 기본과 같은 생각이고 방법은 다르되 이에대한 생각은 끊임없이 가져가야 한다.&lt;/p&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;현재 우리팀 채용 공고는 완벽한가? 나름 고심하고 작성하였기에 좋은 예시에 가깝지만 개발자들에게 좀 더 매력적으로 보이게끔 수정할 수 있을 것 같다. 또한, 질문에서 팀에서 추구하고 있는 방향에 관련된 질문을 충분히 하고 정답지가 정해진 질문이 아닌 이에대해 할 수 있는 질문을 하려고 한번 더 생각하게 됐다.&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;6. 좋은 개발 문화 만들기&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;7. 단순한 설계&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;다시 처음으로 돌아온 느낌이지만, 마지막에 되풀이한 만큼 나 역시 기본에 충실해야 한다고 생각하기에 마지막에 적어본다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;  개발자라면 누구나 갖고 있을 생각을 잘 정리했을 뿐인 이 책이 많은 추천을 받고 있는 이유는 대부분 이 당연한 생각들을 잊곤하기 때문이다. 가끔 스스로를 돌아볼 때 나는 소프트웨어 장인이 되어가고 있는지 한번 더 생각해볼 것 같다.&lt;/p&gt;</description>
      <category>개발/책</category>
      <category>소프트웨어 장인</category>
      <author>보리ing</author>
      <guid isPermaLink="true">https://cupeanimus.tistory.com/100</guid>
      <comments>https://cupeanimus.tistory.com/100#entry100comment</comments>
      <pubDate>Sun, 6 Mar 2022 22:56:27 +0900</pubDate>
    </item>
    <item>
      <title>mysql varchar size변경</title>
      <link>https://cupeanimus.tistory.com/98</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;출처 - &lt;a href=&quot;https://kimdubi.github.io/mysql/varchar/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://kimdubi.github.io/mysql/varchar/&lt;/a&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;문제는 스펙에 사이즈가 나와있어, 해당 사이즈를 명확히 할 것인지.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스펙을 정의한 곳에 신뢰가 완전하지 않아 여유를 둘 것인지에 대한 고민이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론 varchar형태가 가변형이기 때문에 크게 해도 성능상 이슈가 없으니 미리 크게 잡아두는게 편하지 않냐는 생각과&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;추후 사이즈를 변경하는것에 대한 부담감을 갖지 않도록 사이즈 변경은 db에 무리없이 작업할 수 있는지 알아봤다.&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;1. varchar size 256 bytes 이하구간에서 증가시키는 경우&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1632795494051&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;### varchar(1) =&amp;gt; varchar(63)

mysql&amp;gt; alter table test modify a varchar(63), algorithm=inplace, lock = none;
Query OK, 0 rows affected (0.04 sec)
Records: 0  Duplicates: 0  Warnings: 0&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;metadata만 변경되므로 부담없다.&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;2. 256bytes 이하에서 256bytes이상으로 증가시키는 경우&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1632795858104&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;### vachar(63) =&amp;gt; varchar(64)

mysql&amp;gt; alter table test modify a varchar(64), algorithm=inplace, lock = none;
ERROR 1846 (0A000): ALGORITHM=INPLACE is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY.&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;algorithm=COPY 방식을 사용하여야 한다.&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;&lt;b&gt;3. 256bytes 이상에서 증가시키는 경우&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1632796012024&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;### varchar(64) =&amp;gt; 그 이상

mysql&amp;gt; alter table test modify b varchar(640), algorithm=inplace, lock = none;
Query OK, 0 rows affected (0.04 sec)
Records: 0  Duplicates: 0  Warnings: 0&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;metadata만 변경되므로 부담없다.&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;4. 사이즈를 줄이는 경우&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1632796098054&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;       Table: test
Create Table: CREATE TABLE `test` (
  `a` varchar(63) DEFAULT NULL,
  `b` varchar(640) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
1 row in set (0.00 sec)



mysql&amp;gt; alter table test modify b varchar(600), algorithm=inplace, lock = none;
ERROR 1846 (0A000): ALGORITHM=INPLACE is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY.
mysql&amp;gt; alter table test modify a varchar(1), algorithm=inplace, lock = none;
ERROR 1846 (0A000): ALGORITHM=INPLACE is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY.&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;algorithm=COPY 방식을 사용하여야 한다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;정리.&lt;/b&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;사이즈를 증가하는 경우 크기가256bytes을 지나치게 된다면 algorithm=COPY 방식을 사용하여야 해서 부담이 될 수 있다.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;줄이는 경우는 크기와 상관없이 모두 algorithm=COPY 방식을 사용하여야 하기 때문에 부담된다.&amp;nbsp;&lt;/b&gt;&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;&lt;b&gt;기타&lt;/b&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;charset이 utf8mb인 경우 1글자(varchar1)당 4byte이기 때문에 varchar(64)가 기준이 된다.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;charset이 utf8은 1글자당 3byte이고, varchar(86)이 기준이 된다.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;256bytes가 기준이 되는 이유는 256bytes를 초과하게 되면 MySql 내부적으로 컬럼의 실제 저장 길이를 관리하는 flag가 1 byte에서 2byte로 커져야 하기 때문이다.&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>개발/MySQL</category>
      <author>보리ing</author>
      <guid isPermaLink="true">https://cupeanimus.tistory.com/98</guid>
      <comments>https://cupeanimus.tistory.com/98#entry98comment</comments>
      <pubDate>Tue, 28 Sep 2021 11:36:47 +0900</pubDate>
    </item>
    <item>
      <title>The RED : 백발의 개발자를 꿈꾸며 : 코드리뷰, 레거시와 TDD by 백명석, 최범균 - 2부. 코드리뷰</title>
      <link>https://cupeanimus.tistory.com/96</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;s&gt;1. 코드리뷰의 필요성&lt;/s&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;s&gt;2. 목적&lt;/s&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;I'm not a greate programmer. I'm just a good programmer with great habits&lt;br /&gt;- Kent Beck&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;정리를 하다가보니 코드리뷰의 중요성과 목적에 대해선 어느정도는 모두가 다 알고 있을 것이라고 생각된다.&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;강의를 통해 다시 상기하게 된 것은 코드리뷰는 상대방을 깎아내리는게 아닌 함께 더 좋은 품질의 코드를 만들어 가는 것이다.&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;다행이도 현재 팀은 상대가 누구이든 존중과 배려가 담겨 있으며 생각을 전하는데 스스럼없다.&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;&amp;nbsp;&lt;/p&gt;</description>
      <author>보리ing</author>
      <guid isPermaLink="true">https://cupeanimus.tistory.com/96</guid>
      <comments>https://cupeanimus.tistory.com/96#entry96comment</comments>
      <pubDate>Mon, 6 Sep 2021 02:23:46 +0900</pubDate>
    </item>
  </channel>
</rss>