<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>amenable-c.log</title>
        <link>https://velog.io/</link>
        <description>가보자고</description>
        <lastBuildDate>Fri, 11 Nov 2022 12:50:32 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>amenable-c.log</title>
            <url>https://velog.velcdn.com/images/amenable-c/profile/019db7d5-86ca-4570-aa59-6dc092eda59d/social_profile.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. amenable-c.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/amenable-c" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[프리코스 2주차] 숫자 야구 게임 미션 회고]]></title>
            <link>https://velog.io/@amenable-c/%ED%94%84%EB%A6%AC%EC%BD%94%EC%8A%A4-2%EC%A3%BC%EC%B0%A8-%EC%88%AB%EC%9E%90-%EC%95%BC%EA%B5%AC-%EA%B2%8C%EC%9E%84-%EB%AF%B8%EC%85%98-%ED%9A%8C%EA%B3%A0</link>
            <guid>https://velog.io/@amenable-c/%ED%94%84%EB%A6%AC%EC%BD%94%EC%8A%A4-2%EC%A3%BC%EC%B0%A8-%EC%88%AB%EC%9E%90-%EC%95%BC%EA%B5%AC-%EA%B2%8C%EC%9E%84-%EB%AF%B8%EC%85%98-%ED%9A%8C%EA%B3%A0</guid>
            <pubDate>Fri, 11 Nov 2022 12:50:32 GMT</pubDate>
            <description><![CDATA[<blockquote>
<ol>
<li>전체적인 미션의 방향</li>
<li>과제를 진행하면서 배운점</li>
<li>추가적인 공부가 요구되는 사항들</li>
<li>공통 피드백</li>
</ol>
</blockquote>
<h2 id="1-전체적인-미션의-방향">1. 전체적인 미션의 방향</h2>
<p>이번 주차의 미션은 &#39;숫자 야구 게임&#39;을 만드는 것이다.
기본적인 게임의 규칙은 1부터 9까지의 서로 다른 수로 이루어진 3자리의 수를 맞추는 게임이다.(숫자와 자리 수가 같은 경우 - 스트라이크, 숫자만 같고 자리 수가 다른 경우 - 볼)</p>
<ul>
<li><h4 id="1-게임에-필요한-플레이어와-상대방등을-만들어서-객체-지향으로-설계한다">1. 게임에 필요한 &#39;플레이어&#39;와 &#39;상대방&#39;등을 만들어서 객체 지향으로 설계한다.</h4>
</li>
<li><h4 id="2-예외를-발생시킨다-illegalargumentexception-이용">2. 예외를 발생시킨다. (IllegalArgumentException 이용)</h4>
</li>
<li><h4 id="3-테스트케이스-작성">3. 테스트케이스 작성</h4>
<img src="https://velog.velcdn.com/images/amenable-c/post/455fb7e2-7353-43b4-ae21-c87f1d22b4db/image.png" alt=""></li>
</ul>
<h2 id="2-과제를-진행하면서-배운점">2. 과제를 진행하면서 배운점</h2>
<h4 id="1-객체-지향-설계">1. 객체 지향 설계</h4>
<ul>
<li>숫자 야구 게임을 위해서 &#39;Player&#39;, &#39;Computer(상대방)&#39;, 그리고 &#39;Game&#39;으로 객체를 나누었다.
그리고 각각의 역할에 대해서 기능들을 추가하여 객체 지향적으로 개발을 진행하였다.</li>
</ul>
<h4 id="2-예외-처리">2. 예외 처리</h4>
<ul>
<li><p>플레이어의 입력에 대해서 예외처리를 하였다.
예를 들어, &#39;서로 다른 세자리 수&#39;를 입력해야 하는 경우에 &#39;2자리 수를 입력하거나&#39;, &#39;문자를 입력하거나&#39;, &#39;223과 같이 중복된 수를 입력한 경우&#39; 예외 처리를 하였다.</p>
</li>
<li><p>그리고 예외가 발생한 경우 즉시 애플리케이션을 종료해야함으로 게임이 시작되는 순간부터 try-catch를 사용하여 예외가 발생한 경우 바로 애플리케이션이 종료되도록 처리하였다.</p>
</li>
</ul>
<h4 id="3-테스크-케이스-작성">3. 테스크 케이스 작성</h4>
<ul>
<li>&#39;JUnit5&#39;와 &#39;단위 테스트&#39;에 대해서 공부하고 블로그에 글을 올린 경험이 있다.
JUnit5를 사용하는 것에는 문제가 없었지만 단위 테스트를 작성하는데 어려움이 있었다.
특히 private가 있는 메서드의 경우 TEST에서 접근을 할 수가 없는 문제가 있었다. (물론 구글링을 해보니 private라도 접근하는 방법이 있었다....)(추후 해당 방법에 대한 글을 작성할 예정이다.)
그래서 접근이 가능한 메서드를 이용하여 최대한 단위 테스트가 가능하도록 테스트를 작성하였다.</li>
</ul>
<h2 id="3-공통-피드백">3. 공통 피드백</h2>
<h4 id="1-기능-목록을-재검토한다">1. 기능 목록을 재검토한다.</h4>
<ul>
<li>기능 목록을 클래스 설계와 구현, 함수(메서드) 설계와 구현과 같이 너무 상세하게 작성하지 않는다.</li>
<li>클래스 이름, 함수(메서드) 시그니처와 반환값은 언제든지 변경될 수 있기 때문이다.</li>
<li>너무 세세한 부분까지 정리하기보다 구현해야 할 기능 목록을 정리하는데 집중한다.</li>
<li>정상적인 경우도 중요하지만, 예외적인 상황도 기능 목록에 정리한다.</li>
<li>특히 예외 사항은 시작 단게에서 모두 찾기 힘들기 때문에 기능을 구현하면서 계속해서 추가해 나간다.</li>
</ul>
<h4 id="2-값을-하드-코딩하지-않는다">2. 값을 하드 코딩하지 않는다.</h4>
<ul>
<li>문자열, 숫자 등의 값을 하드 코딩하지 않는다.</li>
<li>상수(static final)를 만들고 이름을 부여해 이 변수의 역할이 무엇인지 의도를 드러내라.</li>
<li>구글에서 &quot;java 상수&quot;와 같은 키워드로 검색해 상수 구현 방법을 학습하고 적용해 본다.</li>
</ul>
<h4 id="3-구현-순서도-코딩-컨벤션이다">3. 구현 순서도 코딩 컨벤션이다.</h4>
<ul>
<li>클래스는 상수, 멤버 변수, 생성자, 메서드 순으로 작성한다.</li>
</ul>
<h4 id="4-변수-이름에-자료형은-사용하지-않는다">4. 변수 이름에 자료형은 사용하지 않는다.</h4>
<ul>
<li>변수 이름에 자료형, 자료 구조 등을 사용하지 않는다. (ex. carNameList, arrayString 등)</li>
</ul>
<h4 id="5-한-함수가-한-가지-기능만-담당하게-한다">5. 한 함수가 한 가지 기능만 담당하게 한다.</h4>
<ul>
<li>함수 길이가 길어진다면 한 함수에서 여러 일을 하려고 하는 경우일 가능성이 높다. </li>
<li>예를 들어 한 함수에서 &#39;안내 문구 출력, 사용자 입력, 유효값 검증&#39; 등의 일을 한다면 이를 적절하게 분리해야 한다.</li>
</ul>
<h4 id="6-처음부터-큰-단위의-테스트를-만들지-않는다">6. 처음부터 큰 단위의 테스트를 만들지 않는다.</h4>
<ul>
<li>테스트의 중요한 목적 중 하나는 내가 작성하는 코드에 대해 빠르게 피드백을 받는 것이다.</li>
<li>시작부터 큰 단우의 테스트를 만들게 된다면 작성한 코드에 대한 피드백을 받기까지 많은 시간이 걸린다.</li>
<li>그래서 문제를 작게 나누고, 그 중 핵심 기능에 가까운 부분부터 작게 테스트를 만들어 나간다.</li>
</ul>
<h2 id="4-추가적인-공부가-요구되는-사항들">4. 추가적인 공부가 요구되는 사항들</h2>
<h4 id="1-private로-지정된-메서드의-테스트-방법">1. private로 지정된 메서드의 테스트 방법</h4>
<h4 id="2-함수가-한-가지-기능만-담당하도록-설계-연습을-꾸준히-한다">2. 함수가 한 가지 기능만 담당하도록 설계 연습을 꾸준히 한다!</h4>
]]></description>
        </item>
        <item>
            <title><![CDATA[[프리코스 1주차] 온보딩 회고]]></title>
            <link>https://velog.io/@amenable-c/%ED%94%84%EB%A6%AC%EC%BD%94%EC%8A%A4-1%EC%A3%BC%EC%B0%A8-%EC%98%A8%EB%B3%B4%EB%94%A9-%ED%9A%8C%EA%B3%A0</link>
            <guid>https://velog.io/@amenable-c/%ED%94%84%EB%A6%AC%EC%BD%94%EC%8A%A4-1%EC%A3%BC%EC%B0%A8-%EC%98%A8%EB%B3%B4%EB%94%A9-%ED%9A%8C%EA%B3%A0</guid>
            <pubDate>Thu, 10 Nov 2022 16:28:35 GMT</pubDate>
            <description><![CDATA[<blockquote>
<ol>
<li>전체적인 미션의 방향</li>
<li>과제를 진행하면서 배운점</li>
<li>추가적인 공부가 요구되는 사항들</li>
<li>공통 피드백</li>
</ol>
</blockquote>
<h2 id="1-전체적인-미션의-방향">1. 전체적인 미션의 방향</h2>
<p>&#39;온보딩&#39;이라는 단어에서 알 수 있듯이 4주차까지 미션을 진행하기에 필요한 기본적인 사항들을 배우는 시간이었다. 
Java Collection 자료구조(List, Set, Map 등)를 사용하면서 7가지 문제를 푸는 방식으로 미션이 진행되었다.
<img src="https://velog.velcdn.com/images/amenable-c/post/541d1468-141b-4b22-bfab-e10562c3609a/image.png" alt=""></p>
<h2 id="2-과제를-진행하면서-배운점">2. 과제를 진행하면서 배운점</h2>
<h4 id="1-java-언어-활용">1. JAVA 언어 활용</h4>
<ul>
<li>C++를 사용해서 코딩테스트를 준비할 때에는 다양한 자료구조들을 사용하였는데, JAVA를 통해 프로젝트를 할 때에는 생각보다 다양한 자료구조를 사용하지 못했구나라는 생각을 하였다.
그래서 이번 과제를 통해 JAVA에서 다양한 자료구조를 사용해볼 수 있었다.</li>
</ul>
<h4 id="2-네이밍-연습">2. 네이밍 연습</h4>
<ul>
<li>&#39;과제 제출&#39;이라는 압박감으로 네이밍에 많은 신경을 썼다.</li>
<li>어떻게 하면 더 쉽게 코드를 이해할 수 있을까부터 시작해서 반복문에 있는 값(항상 쓰던 i)까지 모두 고려하여 이름을 부여하였다.</li>
</ul>
<h2 id="3-공통-피드백">3. 공통 피드백</h2>
<h4 id="1-이름을-통해-의도를-드러낸다">1. 이름을 통해 의도를 드러낸다.</h4>
<ul>
<li>나 자신, 다른 개발자와의 소통을 위해 가장 중요한 활동 중의 하나가 좋은 이름 짓기이다. </li>
<li>변수 이름, 함수(메서드) 이름, 클래스 이름을 짓는데 시간을 투자하라. 이름을 통해 변수의 역할, 함수의 역할, 클래스의 역할에 대한 의도를 드러내기 위해 노력하라. 연속된 숫자를 덧붙이거나(a1, a2, ..., aN), 불용어(Info, Data, a, an, the)를 추가하는 방식은 적절하지 못하다.</li>
</ul>
<h4 id="2-축약하지-않는다">2. 축약하지 않는다.</h4>
<ul>
<li>의도를 드러낼 수 있다면 이름이 길어져도 괜찮다.
<img src="https://velog.velcdn.com/images/amenable-c/post/0640aee6-0097-47ad-b79a-5e735d223e5d/image.png" alt=""></li>
</ul>
<h4 id="3-공백도-코딩-컨벤션이다">3. 공백도 코딩 컨벤션이다.</h4>
<ul>
<li>공백 라인을 의미 있게 사용하는 것이 좋아 보이며, 문맥을 분리하는 부분에 사용하는 것이 좋다.</li>
<li>과도한 공백은 다른 개발자에게 의문을 줄 수 있다.</li>
</ul>
<h4 id="4-배열-대신-java-collection을-사용한다">4. 배열 대신 Java Collection을 사용한다.</h4>
<ul>
<li>Java Collection 자료구조(List, Set, Map 등)를 사용하면 데이터를 조작할 때 다양한 API를 사용할 수 있다.
<img src="https://velog.velcdn.com/images/amenable-c/post/acb58a5f-7e6f-4827-8f80-677e3f23596e/image.png" alt=""></li>
</ul>
<h2 id="4-추가적인-공부가-요구되는-사항들">4. 추가적인 공부가 요구되는 사항들</h2>
<h4 id="1-의미-있는-이름을-작성하는-방법---변수-이름-함수메서드-이름-클래스-이름">1. 의미 있는 이름을 작성하는 방법 - (변수 이름, 함수(메서드) 이름, 클래스 이름)</h4>
<h4 id="2-java-collection-자료구조의-다양한-api-사용법">2. Java Collection 자료구조의 다양한 API 사용법</h4>
]]></description>
        </item>
        <item>
            <title><![CDATA[웹 요청과 응답]]></title>
            <link>https://velog.io/@amenable-c/%EC%9B%B9-%EC%9A%94%EC%B2%AD%EA%B3%BC-%EC%9D%91%EB%8B%B5</link>
            <guid>https://velog.io/@amenable-c/%EC%9B%B9-%EC%9A%94%EC%B2%AD%EA%B3%BC-%EC%9D%91%EB%8B%B5</guid>
            <pubDate>Wed, 09 Nov 2022 15:29:23 GMT</pubDate>
            <description><![CDATA[<blockquote>
<ol>
<li>HTTP 개념</li>
<li>요청과 응답 흐름</li>
<li>HTTP Request 구조</li>
<li>HTTP Response 구조</li>
<li>추가사항</li>
</ol>
</blockquote>
<h2 id="1-http-개념">1. HTTP 개념</h2>
<ul>
<li>HyperText Transfer Protocol</li>
<li>HyperText(HTML) 문서를 교환하기 위해 만들어진 Protocol(통신 규약)</li>
<li>주로 TCP를 사용하고 HTTP3부터는 UDP를 사용하며 80번 포트를 사용</li>
</ul>
<h2 id="2-요청과-응답-흐름">2. 요청과 응답 흐름</h2>
<p><img src="https://velog.velcdn.com/images/amenable-c/post/668d2165-9cca-4490-8acc-ab8ebc480aed/image.png" alt=""></p>
<p>클라이언트와 서버가 HTTP(s)의 규약 아래에 요청과 응답을 주고 받음.</p>
<h4 id="1-클라이언트client">1. 클라이언트(Client)</h4>
<p>정보, 자원, 서비스를 사용하는 측
요청을 보내는 측
$\to$ 예시 : 웹브라우저(크롬, 파이어폭스, 사파리 등등)</p>
<h4 id="2-서버server">2. 서버(Server)</h4>
<p>정보, 자원, 서비스를 제공하는 측
요청을 받고 응답하는 측
$\to$ 예시 : 웹 서버(아파치 HTTP서버, NGINX, 마이크로소프트 인터넷 정보 서비스(IIS) 등등)</p>
<h2 id="3-http-request-구조">3. HTTP Request 구조</h2>
<figure class="half">
    <img src="https://velog.velcdn.com/images/amenable-c/post/708fe6b4-7022-4b44-8b75-57d790d1f84f/image.png">
    <img src="https://velog.velcdn.com/images/amenable-c/post/0ce00a28-9ba1-4d63-aa1e-72ebb1df0623/image.png">
</figure>

<h4 id="1-start-line">1. Start Line</h4>
<p>구조 
$\to$ [HTTP Method][Request target][HTTP version] 
$\to$ 예시) GET / test.html HTTP/1.1</p>
<ol>
<li>HTTP Method
: 요청의 의도를 담고 있는 GET, POST, PUT, DELETE 등이 해당함</li>
<li>Request target
: HTTP Request가 전송되는 목표 주소</li>
<li>HTTP version
: version에 따라서 Request 메시지 구조나 데이터가 다를 수 있어서 version을 명시해야 함.</li>
</ol>
<h4 id="2-headers">2. Headers</h4>
<p>해당 Request에 대한 추가 정보를 담고 있는 부분 
$\to$ 요청 하려는 서버 호스트 이름, 포트 번호, cookie, authorization</p>
<h4 id="3-body">3. Body</h4>
<p>HTTP request가 전송하는 데이터를 담고 있는 부분</p>
<h2 id="4-http-response-구조">4. HTTP Response 구조</h2>
<p><img src="https://velog.velcdn.com/images/amenable-c/post/b744edd0-5133-4311-9aec-847531cf0e2c/image.png" alt=""></p>
<h4 id="1-status-line">1. Status Line</h4>
<p><img src="https://velog.velcdn.com/images/amenable-c/post/3e18e87d-c908-42c5-a9e7-62079c0b2e1a/image.png" alt="">
구조 
$\to$ [HTTP version] [Status Code] [Status Text] 
$\to$ 예시) HTTP/1.1 200 OK</p>
<ol>
<li>HTTP version</li>
<li>Status Code</li>
<li>Status Text</li>
</ol>
<h4 id="2-headers-1">2. Headers</h4>
<p>Request Headers와 동일 (다만, response에서만 사용되는 header 값들도 존재)</p>
<h4 id="3-body-1">3. Body</h4>
<p>Request Body와 일반적으로 동일 (비어있을수도 있음)</p>
<h2 id="5-추가사항">5. 추가사항</h2>
<p>클라이언트 (웹 브라우저)가 응답을 받은 후 필요한 리소스들을 추가 요청하여 응답을 받는다.
$\to$ 예를 들어, 특정 홈페이지에 접속한 경우 자바스크립트, 이미지 파일 등을 추가적으로 요청하여 받음. 
<img src="https://velog.velcdn.com/images/amenable-c/post/f9e8fcb2-851a-42e1-8adb-50d1acfb64f2/image.png" alt=""></p>
<blockquote>
<p>이 글은 아래의 사이트 내용을 참고하였습니다.
$\to$ <a href="https://hahahoho5915.tistory.com/62">https://hahahoho5915.tistory.com/62</a>
$\to$ <a href="https://www.youtube.com/watch?v=0jV7xOUcKog&amp;list=PLgXGHBqgT2TvpJ_p9L_yZKPifgdBOzdVH&amp;index=151">https://www.youtube.com/watch?v=0jV7xOUcKog&amp;list=PLgXGHBqgT2TvpJ_p9L_yZKPifgdBOzdVH&amp;index=151</a></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[단위테스트(Unit Test)와 TDD]]></title>
            <link>https://velog.io/@amenable-c/%EB%8B%A8%EC%9C%84%ED%85%8C%EC%8A%A4%ED%8A%B8Unit-Test%EC%99%80-TDD</link>
            <guid>https://velog.io/@amenable-c/%EB%8B%A8%EC%9C%84%ED%85%8C%EC%8A%A4%ED%8A%B8Unit-Test%EC%99%80-TDD</guid>
            <pubDate>Wed, 09 Nov 2022 14:46:33 GMT</pubDate>
            <description><![CDATA[<blockquote>
<ol>
<li>단위테스트의 개념 및 필요성</li>
<li>좋은 단위 테스트의 특징</li>
<li>TDD 개념 및 절차</li>
<li>기본 방식과의 차이점</li>
<li>TDD의 장점과 단점</li>
</ol>
</blockquote>
<h2 id="1-단위테스트의-개념-및-필요성">1. 단위테스트의 개념 및 필요성</h2>
<h4 id="1-단위테스트의-개념">1. 단위테스트의 개념</h4>
<ul>
<li>하나의 모듈을 기준으로 독립적으로 진행되는 가장 작은 단위의 테스트
(모듈 : 애플리케이션에서 작동하는 하나의 기능 또는 메소드)</li>
<li>TDD에서 말하는 테스트가 단위테스트</li>
</ul>
<p>$\to$ 통합테스트
    1. 모듈을 통합하는 과정에서 모듈 간의 호환성을 확인하기 위해 수행되는 테스트
    2. 통합된 모듈이 올바르게 연계되어 동작하는지 검증하기 위한 테스트</p>
<h4 id="2-단위-테스트의-필요성">2. 단위 테스트의 필요성</h4>
<ul>
<li>통합 테스트를 위해서는 캐시나 DB 등 다른 컴포넌트와 실제 연결이 필요 $\to$ 비용(시간)이 상당히 커짐</li>
<li>단위 테스트는 해당 부분만 독립적으로 테스트하기 때문에 리팩토링시 빠르게 문제 확인 가능
$\to$ 단위 테스트는 수시로 빠르게 돌리면서 문제를 파악할 수 있는 장점이 있음.<h2 id="2-좋은-단위-테스트의-특징first규칙">2. 좋은 단위 테스트의 특징(FIRST규칙)</h2>
<h4 id="1-fast">1. FAST</h4>
</li>
<li>좋은 단위 테스트는 실행이 빨라야한다.</li>
</ul>
<h4 id="2-independent">2. INDEPENDENT</h4>
<ul>
<li>좋은 단위 테스트는 테스트하고자 하는 단위 기능에 집중해야 한다.</li>
</ul>
<h4 id="3-repeatable">3. REPEATABLE</h4>
<ul>
<li>좋은 단위 테스트는 반복적으로 수행하더라도 항상 같은 결과를 반환해야 한다.</li>
</ul>
<h4 id="4-self-validating">4. Self-Validating</h4>
<ul>
<li>좋은 단위 테스트는 기대하는 결과가 무엇인지 단언(assert)해야 한다.</li>
<li>System.out.println과 log.info를 이용하는 것이 아닌 Junit에서 재공하는 assert와 같은 검증 코드를 이용</li>
</ul>
<h4 id="5-timely">5. Timely</h4>
<ul>
<li>좋은 단위 테스트는 미루지 않고 즉시 작성해야 한다.</li>
</ul>
<h2 id="3-tdd의-개념-및-절차">3. TDD의 개념 및 절차</h2>
<h4 id="1-tdd의-개념">1. TDD의 개념</h4>
<ul>
<li>Test-Driven Development = 테스트 주도 개발</li>
<li>반복 테스트를 이용한 소프트웨어 방법론으로 작은 단위의 테스트 케이스를 작성하고 이를 통과하는 코드를 추가하는 단계를 반복하여 구현한다.<h4 id="2-tdd-절차">2. TDD 절차</h4>
<img src="https://velog.velcdn.com/images/amenable-c/post/f37880a6-1f13-4dec-8e96-aa53393a6c34/image.png" alt=""></li>
</ul>
<ol>
<li><p>RED 단계
: 실패하는 테스트 코드를 먼저 작성</p>
</li>
<li><p>GREEN 단계
: 테스트 코드를 성공시키기 위한 실제 코드를 작성</p>
</li>
<li><p>REFACTOR 단계
: 중복 코드 제거, 일반화 등의 리팩토링을 수행</p>
</li>
</ol>
<h2 id="4-기존-방식과의-차이점">4. 기존 방식과의 차이점</h2>
<h4 id="1-기존-방식">1. 기존 방식</h4>
<p><img src="https://velog.velcdn.com/images/amenable-c/post/caf5b85e-99d1-4ccf-a743-04b3cd210a68/image.png" alt=""></p>
<ul>
<li><p>재설계로 인해 개발자는 코드를 삽입, 수정, 삭제 하는 과정에서 불필요한 코드가 남거나 중복처리 될 가능성이 있다. </p>
</li>
<li><p>코드들의 재사용이 어렵고 관리가 어려워져 유지보수를 어렵게 만든다.</p>
<h4 id="2-tdd-개발-방식">2. TDD 개발 방식</h4>
<p><img src="https://velog.velcdn.com/images/amenable-c/post/3e8efa94-7b22-4de5-bc6b-1074f67107fb/image.png" alt=""></p>
</li>
<li><p>테스트 코드를 작성하는 도중에 발생하는 예외 사항(버그, 수정사항)들을 테스트 케이스에 추가하고 설계를 개선한다.</p>
</li>
<li><p>테스트가 통과된 코드만을 코드 개발 단계에서 실제 코드로 작성</p>
</li>
<li><p>이러한 반복적인 단계가 진행되면서 자연스럽게 코드의 버그가 줄어들고 소스코드는 간결해짐</p>
</li>
</ul>
<h2 id="5-tdd의-장점과-단점">5. TDD의 장점과 단점</h2>
<h4 id="1-장점">1. 장점</h4>
<ol>
<li>보다 튼튼한 객체 지향적인 코드 생산</li>
<li>재설계 시간의 단축</li>
<li>디버깅 시간의 단축</li>
<li>테스트 문서의 대체 가능</li>
<li>추가 구현의 용이함</li>
</ol>
<h4 id="2-단점">2. 단점</h4>
<ol>
<li>생산성이 저하될 수도 있음</li>
<li>TDD를 사용하지 않았을 때와 대비하여 초기 비용 발생</li>
<li>팀이 테스트코드에 익숙하지 않은 경우 테스트코드에 집중할 수 없다. </li>
</ol>
<blockquote>
<p>이 글은 아래의 사이트 내용을 참고하였습니다.
$\to$ <a href="https://wooaoe.tistory.com/33">https://wooaoe.tistory.com/33</a>
$\to$ <a href="https://mangkyu.tistory.com/182">https://mangkyu.tistory.com/182</a>
$\to$ <a href="https://mangkyu.tistory.com/143">https://mangkyu.tistory.com/143</a>
$\to$ <a href="https://media.fastcampus.co.kr/knowledge/dev/tdd/">https://media.fastcampus.co.kr/knowledge/dev/tdd/</a>
$\to$ <a href="https://velog.io/@sdb016/%EC%A2%8B%EC%9D%80-%EB%8B%A8%EC%9C%84-%ED%85%8C%EC%8A%A4%ED%8A%B8-FIRST%EC%97%90-%EB%8C%80%ED%95%98%EC%97%AC">https://velog.io/@sdb016/%EC%A2%8B%EC%9D%80-%EB%8B%A8%EC%9C%84-%ED%85%8C%EC%8A%A4%ED%8A%B8-FIRST%EC%97%90-%EB%8C%80%ED%95%98%EC%97%AC</a>
$\to$ <a href="https://yuricoding.tistory.com/91">https://yuricoding.tistory.com/91</a></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[JUnit5 개념 및 사용방법]]></title>
            <link>https://velog.io/@amenable-c/JUnit5-%EA%B0%9C%EB%85%90-%EB%B0%8F-%EC%82%AC%EC%9A%A9%EB%B0%A9%EB%B2%95</link>
            <guid>https://velog.io/@amenable-c/JUnit5-%EA%B0%9C%EB%85%90-%EB%B0%8F-%EC%82%AC%EC%9A%A9%EB%B0%A9%EB%B2%95</guid>
            <pubDate>Wed, 09 Nov 2022 14:17:25 GMT</pubDate>
            <description><![CDATA[<blockquote>
<ul>
<li><ol>
<li>JUnit5 개념</li>
</ol>
</li>
</ul>
</blockquote>
<ul>
<li><ol start="2">
<li>JUnit5 어노테이션 종류</li>
</ol>
</li>
<li><ol start="3">
<li>JUnit5 테스트 라이프 사이클</li>
</ol>
</li>
<li><ol start="4">
<li>Assert 메서드</li>
</ol>
</li>
<li><ol start="5">
<li>보조 어노테이션</li>
</ol>
</li>
<li><ol start="6">
<li>JUnit5 Assumption</li>
</ol>
</li>
</ul>
<h2 id="1-junit5-개념">1. JUnit5 개념</h2>
<ul>
<li><p>JUnit5란 자바 개발자가 가장 많이 사용하는 테스팅 기반 프레임워크이다.</p>
</li>
<li><p>Java8 부터 사용가능</p>
</li>
<li><p>JUnit Platform, JUnit Jupiter, JUnit Vintage가 결합한 형태</p>
<ol>
<li>JUnit Platfor : 테스트를 실행해주는 런쳐와 TestEngine API를 제공</li>
<li>Jupiter : TestEngine API 구현체로 JUnit5에서 제공</li>
<li>Vintage : TestEngine API 구현체로 JUnit3, 4에서 제공</li>
</ol>
</li>
</ul>
<h2 id="2-junit5-어노테이션-종류">2. JUnit5 어노테이션 종류</h2>
<table>
<thead>
<tr>
<th>JUnit5 어노테이션</th>
<th>내용</th>
<th>JUnit4 어노테이션</th>
</tr>
</thead>
<tbody><tr>
<td>@Test</td>
<td>테스트 Method임을 선엄함</td>
<td>@Test</td>
</tr>
<tr>
<td>@ParameterizedTest</td>
<td>매개변수를 받는 테스트를 작성할 수 있음.</td>
<td></td>
</tr>
<tr>
<td>@RepeatedTest</td>
<td>반복되는 테스트를 작성할 수 있음.</td>
<td></td>
</tr>
<tr>
<td>@TestFactory</td>
<td>@Test로 선언된 정적 테스트가 아닌 동적으로 테스트를 사용함.</td>
<td></td>
</tr>
<tr>
<td>@TestInstance</td>
<td>테스트 클래스의 생명주기를 설정함.</td>
<td></td>
</tr>
<tr>
<td>@@TestTemplate</td>
<td>공급자에 의해 여러 번 호출될 수 있도록 설계된 테스트 케이스 템플릿임을 나타냄</td>
<td></td>
</tr>
<tr>
<td>@TestMethodOrder</td>
<td>테스트 메소드 실생 순서를 구성하는데 사용함</td>
<td></td>
</tr>
<tr>
<td>@DisplayName</td>
<td>테스트 클래스 또는 메소드의 사용자 정의 이름을 선언할 때 사용함</td>
<td></td>
</tr>
<tr>
<td>@DisplayNameGeneration</td>
<td>이름 생성기를 선엄함. 예를 들어 &#39;_&#39;를 공백 문자로 치환해주는 생성기가 있음(new_test-&gt;new test)</td>
<td></td>
</tr>
<tr>
<td>@BeforeEach</td>
<td>모든 테스트 실행 전에 실행할 테스트에 사용함.</td>
<td>@Before</td>
</tr>
<tr>
<td>@AfterEach</td>
<td>모든 테스트 실행 후에 실행할 테스트에 사용함.</td>
<td>@After</td>
</tr>
<tr>
<td>@BeforeAll</td>
<td>현재 클래스를 실행하기 전에 제일 먼저 실행할 테스트를 작성하는데 사용함. static으로 선언</td>
<td>@BeforeClass</td>
</tr>
<tr>
<td>@AfterAll</td>
<td>현재 클래스 종료 후 해당 테스트를 실행함. static으로 선언</td>
<td>@AfterClass</td>
</tr>
<tr>
<td>@Nested</td>
<td>클래스를 정적이 아닌 중첩 테스트 클래스임을 나타냄</td>
<td></td>
</tr>
<tr>
<td>@Tag</td>
<td>클래스 또는 메소드 레벨에서 태그를 선언할 때 사용. 메이븐을 사용할 경우 설정에서 테스트를 태그를 인식해 포함하거나 제외시킬 수 있음.</td>
<td></td>
</tr>
<tr>
<td>@Disabled</td>
<td>클래스나 테스트를 사용하지 않음을 표시</td>
<td>@Ignore</td>
</tr>
<tr>
<td>@Timeout</td>
<td>테스트 실행 시간을 선언한 후 초과되면 실패하도록 설정</td>
<td></td>
</tr>
<tr>
<td>@ExtendWith</td>
<td>확장을 선언적으로 등록할 때 사용</td>
<td></td>
</tr>
<tr>
<td>@RegisterExtension</td>
<td>필드를 통해 프로그래밍 방식으로 확장을 등록할 때 사용</td>
<td></td>
</tr>
<tr>
<td>@TempDir</td>
<td>필드 주입 또는 매개변수 주입을 통해 임시 디렉토리를 제공하는데 사용</td>
<td></td>
</tr>
</tbody></table>
<h2 id="3-junit5-테스트-라이프-사이클">3. JUnit5 테스트 라이프 사이클</h2>
<p>하나의 테스트 클래스에서 아래와 같이 어노테이션을 설정하여 <strong>테스트 라이프 사이클</strong>을 만들 수 있다.</p>
<p><img src="https://velog.velcdn.com/images/amenable-c/post/1b68d2df-c310-46cb-a6ee-0367792f7926/image.png" alt=""><em>[Example1]</em></p>
<p><img src="https://velog.velcdn.com/images/amenable-c/post/9bd67cc0-f0e8-4612-9632-eb0ca4b48ccc/image.png" alt=""><em>[Example2]</em></p>
<h2 id="4-assert-메서드">4. Assert 메서드</h2>
<h4 id="1-기본">1. 기본</h4>
<ul>
<li>assertEquals()<h4 id="2-그룹">2. 그룹</h4>
</li>
<li>여러 검증을 하나로 묶어서 테스트하는 것</li>
<li>assertAll()<h4 id="3-예외처리">3. 예외처리</h4>
</li>
<li>실행한 코드에서 특정 인셉션이 발생하는지 확인할 때 사용</li>
<li>assertThrows()<h4 id="4-시간초과">4. 시간초과</h4>
</li>
<li>특정 시간 안에 실행이 끝나는지 확인하고 싶을 때 사용</li>
<li>assertTimeout(), assertTimeoutPreemptively()</li>
</ul>
<h2 id="5-보조-어노테이션">5. 보조 어노테이션</h2>
<h4 id="1-displayname">1. @DisplayName</h4>
<ul>
<li>테스트 클래스나 메서드의 표시 이름을 지정</li>
</ul>
<h4 id="2-disabled">2. @Disabled</h4>
<ul>
<li>테스트 실행 대상에서 제외<img src="https://velog.velcdn.com/images/amenable-c/post/18a44845-c1e0-440e-9105-7943f98dee68/image.png" width="300" height="300"/>
<img src="https://velog.velcdn.com/images/amenable-c/post/def51f1a-f922-4f3a-9a00-ab32ca7c8d79/image.png" width="400" height="300"/>

</li>
</ul>
<h2 id="6-junit5-assumption">6. JUnit5 Assumption</h2>
<ul>
<li>특정 환경에 있을 때만 테스트를 진행하도록 할 때 사용
<img src="https://velog.velcdn.com/images/amenable-c/post/9b04483f-4625-4ab0-969e-85fa42c813a5/image.png" alt=""></li>
</ul>
<blockquote>
<p>이 글은 아래의 사이트 내용을 참고하였습니다.
$\to$ <a href="https://steady-coding.tistory.com/349">https://steady-coding.tistory.com/349</a>
$\to$ <a href="https://insight-bgh.tistory.com/507">https://insight-bgh.tistory.com/507</a>
$\to$ <a href="https://velog.io/@ehddek/JUnit-%EC%9D%B4%EB%9E%80">https://velog.io/@ehddek/JUnit-%EC%9D%B4%EB%9E%80</a>
$\to$ <a href="https://javacan.tistory.com/entry/JUnit-5-Intro">https://javacan.tistory.com/entry/JUnit-5-Intro</a>
$\to$ <a href="https://gaemi606.tistory.com/entry/JUnit5-Test-LifeCycle">https://gaemi606.tistory.com/entry/JUnit5-Test-LifeCycle</a>
$\to$ <a href="https://beststar-1.tistory.com/28">https://beststar-1.tistory.com/28</a></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[AWS 과금 방지 방법]]></title>
            <link>https://velog.io/@amenable-c/AWS-%EA%B3%BC%EA%B8%88-%EB%B0%A9%EC%A7%80-%EB%B0%A9%EB%B2%95</link>
            <guid>https://velog.io/@amenable-c/AWS-%EA%B3%BC%EA%B8%88-%EB%B0%A9%EC%A7%80-%EB%B0%A9%EB%B2%95</guid>
            <pubDate>Sat, 01 Oct 2022 14:03:16 GMT</pubDate>
            <description><![CDATA[<blockquote>
<ul>
<li>AWS 과금을 방지하는 방법들</li>
</ul>
</blockquote>
<h4 id="1-사용하지-않는-계정-및-리소스-삭제">1. 사용하지 않는 계정 및 리소스 삭제</h4>
<h4 id="2-mfa-설정하기">2. MFA 설정하기</h4>
<h4 id="3-git에-access-key와-secret-key가-올라가지-않도록-항상-주의">3. Git에 Access Key와 Secret key가 올라가지 않도록 항상 주의</h4>
<h4 id="4-비용에-대한-알람-설정">4. 비용에 대한 알람 설정</h4>
<p>결제 대시보드 - Budgets 에서 설정이 가능하다.
free티어 사용량에 대한 알람, 지정된 예산에 대한 알람 등을 받을 수 있다.</p>
<h4 id="5요금-폭탄이-나오면-환불-요청을-해라">5.요금 폭탄이 나오면 환불 요청을 해라.</h4>
<p>AWS Support 센터에 티켓을 만들어 요금 해지 요청을 한다.</p>
<blockquote>
<p>출처 : <a href="https://brunch.co.kr/@topasvga/1308">https://brunch.co.kr/@topasvga/1308</a></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[객체지향 쿼리언어-2]]></title>
            <link>https://velog.io/@amenable-c/%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5-%EC%BF%BC%EB%A6%AC%EC%96%B8%EC%96%B4-2</link>
            <guid>https://velog.io/@amenable-c/%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5-%EC%BF%BC%EB%A6%AC%EC%96%B8%EC%96%B4-2</guid>
            <pubDate>Wed, 20 Jul 2022 08:04:00 GMT</pubDate>
            <description><![CDATA[<blockquote>
<ul>
<li><ol>
<li>경로 표현식</li>
</ol>
</li>
</ul>
</blockquote>
<ul>
<li><ol start="2">
<li>다형성 쿼리</li>
</ol>
</li>
<li><ol start="3">
<li>엔티티 직접 사용</li>
</ol>
</li>
<li><ol start="4">
<li>Named 쿼리</li>
</ol>
</li>
<li><ol start="5">
<li>벌크 연산</li>
</ol>
</li>
</ul>
<h2 id="1-경로-표현식">1. 경로 표현식</h2>
<h4 id="1-경로-표현식-용어-정리">1. 경로 표현식 용어 정리</h4>
<ul>
<li>상태 필드(state field) : 단순히 값을 저장하기 위한 필드</li>
<li>연관 필드(association field) : 연관관계를 위한 필드</li>
</ul>
<h4 id="2-경로-표현식-특징">2. 경로 표현식 특징</h4>
<ul>
<li>상태 필드 : 경로 탐색의 끝. 탐색X</li>
<li>단일 값 연관 경로 : 묵시적 내부 조인(inner join) 발생. 탐색O</li>
<li>컬렉션 값 연관 경로 : 묵시적 내부 조인 발생. 탐색X(컬렉션으로 들어오는거라서 탐색을 할 수가 없음)</li>
</ul>
<h4 id="3-명시적-조인--묵시적-조인">3. 명시적 조인 &amp; 묵시적 조인</h4>
<ul>
<li>명시적 조인 : join 키워드 직접 사용</li>
<li>묵시적 조인 : 경로 표현식에 의해 묵시적으로  SQL 조인 발생(내부 조인만 가능)</li>
</ul>
<h4 id="4-실무-조언">4. 실무 조언</h4>
<ul>
<li>가급적 묵시적 조인 대신에 명시적 조인 사용</li>
<li>조인은 SQL 튜닝에 중요 포인트</li>
<li>묵시적 조인은 조인이 일어나는 상황을 한눈에 파악하기 어려움</li>
</ul>
<h4 id="5-jpql---페치조인fetch-join실무에서-정말정말-중요함">5. JPQL - 페치조인(fetch join)(실무에서 정말정말 중요함)</h4>
<ul>
<li>SQL 조인 종류X</li>
<li>JPQL에서 성능 최적화를 위해 제공하는 기능</li>
<li>연관된 엔티티나 컬렉션을 SQL 한 번에 함께 조회하는 기능</li>
<li>join fetch 명령어 사용</li>
<li>즉시로딩과 비슷(만약 그냥 따로 가져온다고 하면 지연로딩 때문에 n번 SQL이 나감  $\to$ N+1 문제 발생)</li>
</ul>
<ol>
<li>일대다 상황</li>
</ol>
<ul>
<li>일에 해당하는 다의 수 만큼 컬렉션 개수가 결정됨(일대다에서 데이터가 뻥튀기 될 수 있다는 것을 유념)</li>
</ul>
<ol start="2">
<li>페치 조인과 일반 조인의 차이</li>
</ol>
<ul>
<li>일반 조인 : 단지 SELECT 절에서 지정한 엔티티만 조회할 뿐. 연관관계 고려X</li>
<li>페치 조인 : 연관된 엔티티도 함께 조회(즉시로딩). 객체 그래프를 SQL 한번에 조회하는 개념</li>
</ul>
<ol start="3">
<li>페치 조인의 특징과 한계</li>
</ol>
<ul>
<li>페치 조인 대상에는 별칭을 줄 수 없다.</li>
<li>둘 이상의 컬렉션은 페치 조인 할 수 없다.(&#39;일대다대다&#39;가 되어서 곱하기가 됨 $\to$ 데이터가 예상하지 못하게 많이 늘어날 수 있음)</li>
<li>컬렉션을 페치 조인하면 페이징 API를 사용할 수 없다.(데이터가 뻥튀기 되고, 페이지 사이즈 설정에 따라 정보가 누락될 수 있기 때문)
$\to$ 해결책1. 다대일로 방향을 뒤집어서 해결
$\to$ 해결책2. fetch join을 빼고,지연로딩으로 하는거 (근데 이거는 성능 안 나옴)
$\to$ 해결책3. @BatchSize(size = 100)를 이용하기 = 지연로딩으로 끌어올때, 100개씩 넘기는거 (N+1을 해결하는 방법중 하나)(hibernate.default_batch_fetch_size의 value를 100으로 지정하고 진행할 수도 있음)</li>
</ul>
<h2 id="2-다형성-쿼리">2. 다형성 쿼리</h2>
<p>조회 대상을 특정 자식으로 한정</p>
<h2 id="3-엔티티-직접-사용">3. 엔티티 직접 사용</h2>
<p>JPQL에서 엔티티를 직접 사용하면 SQL에서 해당 엔티티의 기본 키 값을 사용</p>
<h2 id="4-named-쿼리">4. Named 쿼리</h2>
<h4 id="1-named-쿼리---정적-쿼리">1. Named 쿼리 - 정적 쿼리</h4>
<ul>
<li>미리 정의해서 이름을 부여해두고 사용하는 SQL</li>
<li>어노테이션, XML에 정의</li>
<li>애플리케이션 로딩 시점에 초기화 후 재사용</li>
<li>애플리케이션 로딩 시점에 쿼리를 검증</li>
</ul>
<h4 id="2-named-쿼리---어노테이션">2. Named 쿼리 - 어노테이션</h4>
<h4 id="3-named-쿼리---xml에-정의">3. Named 쿼리 - XML에 정의</h4>
<h4 id="4-springdatejpa-이용">4. SpringDateJPA 이용</h4>
<pre><code>public interface UserRepository extends JpaRepository&lt;User, Long&gt; {

    @Query(&quot;select u from User u where u.emailAddress = ?1&quot;)
    User findByEmailAddress(String emailAddresss);
}</code></pre><ul>
<li>여기에 있는 쿼리가 네임드 쿼리 역할 $\to$ 이름없는 네임드 쿼리</li>
<li>JPA가 네임드쿼리로 등록해버림 $\to$ 파싱 시점에 에러 다 잡아줌</li>
<li>엔티티에 적는거는 너무 지저분해져서 springDataJpa에 섞어서 사용하기</li>
</ul>
<h2 id="5-벌크-연산">5. 벌크 연산</h2>
<ul>
<li>JPA는 벌크성보다는 실시간 단건에 집중되어있는 경향이 있음
$\to$ 그래서 벌크연산이라는 것을 제공</li>
<li>벌크연산 주의 사항
(1) 벌크 연산은 영속성 컨텍스트를 무시하고 데이터베이스에 직접 쿼리를 날림
(2) 그래서, 벌크 연산을 먼저 수행 후 영속성 컨텍스트 초기화하기!!!(em.clear())</li>
</ul>
<blockquote>
<p>이 글은 김영한님의 &#39;자바 ORM 표준 JPA 프로그래밍 - 기본편&#39;을 수강하고 정리한 내용입니다.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[객체지향 쿼리언어-1]]></title>
            <link>https://velog.io/@amenable-c/%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5-%EC%BF%BC%EB%A6%AC%EC%96%B8%EC%96%B41</link>
            <guid>https://velog.io/@amenable-c/%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5-%EC%BF%BC%EB%A6%AC%EC%96%B8%EC%96%B41</guid>
            <pubDate>Wed, 20 Jul 2022 07:27:43 GMT</pubDate>
            <description><![CDATA[<blockquote>
<ul>
<li><ol>
<li>객체지향 쿼리 언어 소개</li>
</ol>
</li>
</ul>
</blockquote>
<ul>
<li><ol start="2">
<li>JPQL</li>
</ol>
</li>
<li><ol start="3">
<li>기본 문법과 기능</li>
</ol>
</li>
<li><ol start="4">
<li>페치 조인</li>
</ol>
</li>
</ul>
<h2 id="1-객체지향-쿼리-언어-소개">1. 객체지향 쿼리 언어 소개</h2>
<p>JPQl, JPA Criteria, QueryDSL, 네이티브 SQL, JDBC API 직접 사용, MyBati, SpringJdbcTemplate 함께 사용
$\to$ 복잡한 쿼리를 짤 수 있어야 한다는 것에서 시작</p>
<h2 id="2-jpql">2. JPQL</h2>
<h4 id="1-jpql">1. JPQL</h4>
<ul>
<li>테이블이 아닌 객체를 대상으로 검색하는 객체 지향 쿼리(=객체지향SQL)(SQL은 데이터베이스 테이블을 대상으로 쿼리)</li>
<li>JPQL을 짜면, 결국에는 SQL로 번역이 되어서 실행이 됨</li>
</ul>
<h4 id="2-criteria">2. Criteria</h4>
<ul>
<li>위의 JPQL은 결국 String 이라서 동적 쿼리를 날리기가 어려움(string끼기 띄워쓰기 등을 고려해서 붙일때 발생하는 여러가지 문제)</li>
<li>그래서 나온것이 Criteria</li>
<li>쿼리를 코드로 짜는 것</li>
<li>쉬운거 같으면서 어려움(sql같은거는 조금 더 직관적인데, 이거는 조금 혼란스러움)</li>
<li>동적 쿼리로 짜기가 좋다. </li>
<li>Java코드라서 에러를 바로 확인 가능</li>
<li>결론
$\to$ 실무에서 안씀(못 알아보겠어서, 유지보수가 안됨
$\to$ 그냥 이런게 있구나 정도
$\to$ Criteria 대신에 Query DSL 사용 권장</li>
</ul>
<h4 id="3-querydsl">3. QueryDSL</h4>
<ul>
<li>문자가 아닌 자바코드로 JPQL을 작성할 수 있음</li>
<li>JPQL 빌더 역할<ul>
<li>컴파일 시점에 문법 오류를 찾을 수 있음</li>
</ul>
</li>
<li>동적쿼리 작성 편리함</li>
<li>단순하고 쉬움</li>
<li>실무 사용 권장</li>
</ul>
<h4 id="4-네이티브-sql">4. 네이티브 SQL</h4>
<ul>
<li>JPA가 제공하는 SQL을 직접 사용하는 기능</li>
<li>JPQL로 해결할 수 없는 특정 데이터베이스에 의존적인 기능</li>
</ul>
<h4 id="5-결론">5. 결론</h4>
<p>JPQL과 QueryDSL을 잘 사용하자</p>
<h2 id="3-기본-문법과-기능">3. 기본 문법과 기능</h2>
<h4 id="1-jpql-문법">1. JPQL 문법</h4>
<ul>
<li>엔티티와 속성은 대소문자 구분함(Member, age)</li>
<li>JPQL 키워드는 대소문자 구분 못함(SELECT, FROM, where)</li>
<li>엔티티 이름 사용, 테이블 이름이 아님(Member)</li>
<li>별칭은 필수(m)(as는 생략 가능)</li>
</ul>
<h4 id="2-typequery-query">2. TypeQuery, Query</h4>
<ul>
<li>TypeQuery : 반환 타입이 명확할 때 사용</li>
<li>Query : 반환 타입이 명확하지 않을 때 사용</li>
</ul>
<h4 id="3-결과-조회-api">3. 결과 조회 API</h4>
<ul>
<li>query.getResultList() : 결과가 하나 이상일 때. 리스트 반환 $\to$ 결과가 없으면 빈 리스트 반환</li>
<li>query.getSingleResult() : 결과가 정확히 하나. 단일 객체 반환 $\to$ 결과가 없거나, 둘 이상이면 exception 남</li>
</ul>
<h4 id="4-파라미터-바인딩">4. 파라미터 바인딩</h4>
<p>(1) 이름 기준(이거 쓰기)</p>
<pre><code>SELECT m FROM Member m where m.username=:username
query.setParameter(&quot;username&quot;, usernameParam);</code></pre><p>(2) 위치 기준</p>
<pre><code>SELECT m FROM Member m where m.username=?1
query.setParameter(1, usernameParam);</code></pre><ul>
<li>중간에 하나 끼워넣으면 순서가 밀리는 이유때문에, 이거 쓰지말기</li>
</ul>
<h4 id="5-페이징-api">5. 페이징 API</h4>
<ul>
<li>JPA는 페이징을 다음 두 API로 추상화</li>
<li>setFirstResult(int stratPosition) : 조회 시작 위치(0부터 시작)</li>
<li>setMaxResults(int maxResult) : 조회할 데이터 수</li>
</ul>
<h2 id="4-페치-조인">4. 페치 조인</h2>
<h4 id="1-내부조인">1. 내부조인</h4>
<ul>
<li>멤버는 있고 팀이 없는경우, 데이터가 아예 안 나옴</li>
<li><code>SELECT m FROM Member m [INNER] JOIN m.team t</code><h4 id="2-외부조인">2. 외부조인</h4>
</li>
<li>멤버는 있고 팀이 없는경우, 팀 데이터는 다 널이고 멤버는 조회가 됨</li>
<li><code>SELECT m FROM Member m LEFT [OUTER] JOIN m.team t</code></li>
</ul>
<h4 id="3-서브쿼리">3. 서브쿼리</h4>
<ul>
<li>JPA는 WHERE, HAVING 절에서만 서브 쿼리 사용 가능</li>
<li>FROM 절의 서브 쿼리는 현재 JPQL에서 불가능
$\to$ 해결책1. 조인으로 풀어서 해결
$\to$ 해결책2. 쿼리를 두번 날리기</li>
</ul>
<blockquote>
<p>이 글은 김영한님의 &#39;자바 ORM 표준 JPA 프로그래밍 - 기본편&#39;을 수강하고 정리한 내용입니다.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[값 타입]]></title>
            <link>https://velog.io/@amenable-c/%EA%B0%92-%ED%83%80%EC%9E%85</link>
            <guid>https://velog.io/@amenable-c/%EA%B0%92-%ED%83%80%EC%9E%85</guid>
            <pubDate>Wed, 20 Jul 2022 06:49:47 GMT</pubDate>
            <description><![CDATA[<blockquote>
<ul>
<li><ol>
<li>기본값 타입</li>
</ol>
</li>
</ul>
</blockquote>
<ul>
<li><strong>2. 임베디드 타입(복합 값 타입)</strong></li>
<li><ol start="3">
<li>값 타입과 불변 객체</li>
</ol>
</li>
<li><ol start="4">
<li>값 타입의 비교</li>
</ol>
</li>
<li><strong>5. 값 타입 컬렉션</strong></li>
</ul>
<h2 id="1-기본값-타입">1. 기본값 타입</h2>
<h4 id="1-jpa의-데이터-타입-분류">1. JPA의 데이터 타입 분류</h4>
<p>(1) 엔티티 타입</p>
<ul>
<li>@Entity로 정의하는 객체</li>
<li>데이터가 변해도 식별자로 지속해서 추적 가능</li>
</ul>
<p>(2) 값 타입 </p>
<ul>
<li>int, Integer, String처럼 단순히 값으로 사용하는 자바 기본 타입이나 객체</li>
<li>식별자가 없고 값만 있으므로 변경시 추적 불가</li>
</ul>
<h4 id="2-값-타입-분류">2. 값 타입 분류</h4>
<p>(1) 기본값 타입</p>
<ul>
<li>자바 기본 타입(int, double), 래퍼 클래스(Integer, Long), String</li>
</ul>
<p>(2) 임베디드 타입</p>
<ul>
<li>embedded type, 복합 값 타입</li>
</ul>
<p>(3) 컬렉션 값 타입</p>
<ul>
<li>collection value type</li>
</ul>
<h4 id="3-주의">3. 주의</h4>
<ul>
<li>자바의 기본 타입은 절대 공유하면 안됨</li>
</ul>
<h2 id="2-임베디드-타입복합-값-타입">2. 임베디드 타입(복합 값 타입)</h2>
<p><img src="https://velog.velcdn.com/images/amenable-c/post/fa0de15c-3a09-4b3d-9851-8df03e57fa47/image.png" alt=""></p>
<ul>
<li>새로운 값 타입을 직접 정의할 수 있음</li>
<li>주로 기본 값 타입을 모아서 만들어서 복합 값 타입이라고도 함</li>
<li>사용법
(1) @Embeddable : 값 타입을 정의하는 곳에 표시
(2) @Embedded : 값 타입을 사용하는 곳에 표시</li>
<li>장점
(1) 재사용
(2) 높은 응집도
(3) 해당 값 타입만 사용하는 의미 있는 메소드를 만들 수 있음</li>
<li>임베디드 타입과 테이블 맵핑
(1) 임베디드 타입은 엔티티의 값일 뿐이다.
(2) 임베디드 타입을 사용하기 전과 후에 맵핑하는 테이블은 같다.
(3) 객체와 테이블을 아주 세밀하게(find-grained) 맵핑하는 것이 가능
(4) 잘 설게한 ORM 애플리케이션은 맵핑한 테이블의 수보다 클래스의 수가 더 많음</li>
</ul>
<h2 id="3-값-타입과-불변-객체">3. 값 타입과 불변 객체</h2>
<p>값 타입은 복잡한 객체 세상을 조금이라도 단순화하려고 만든 개념이다. 따라서 값 타입은 단순하고 안전하게 다룰 수 있어야 한다.</p>
<h4 id="1-값-타입-공유-참조--값-타입-복사">1. 값 타입 공유 참조 &amp; 값 타입 복사</h4>
<ul>
<li>임베디드 타입 같은 값 타입을 여러 엔티티에서 공유하면 위험함(부작용 발생)</li>
<li>값 타입의 실제 인스턴스인 값을 공유하는 것은 위험</li>
<li>대신 값(인스턴스)를 복사해서 사용<h4 id="2-한계-및-해결책">2. 한계 및 해결책</h4>
</li>
<li>객체 타입은 참조 값을 직접 대입하는 것을 막을 방법이 없다.</li>
<li>객체의 공유 참조는 피할 수 없다.</li>
<li>객체 타입을 수정할 수 없게 만들면 부작용을 원천 차단</li>
<li>값 타입은 불변 객체(immutable object)(생성 시점 이후 절대 값을 변경할 수 없는 객체)로 설계해야 함</li>
<li>생성자로만 값을 설정하고 수정자(Setter)를 만들지 않으면 됨
$\to$ Setter가 없어서 값을 바꿀 수 없을때 바꾸는 법 = 변경을 원하는 값들로 객체를 다시 만든 후, 그 객체로 다시 세팅</li>
</ul>
<p><strong><em>불변이라는 작은 제약으로 부작용이라는 큰 재앙을 막을 수 있다.</em></strong></p>
<h2 id="4-값-타입의-비교">4. 값 타입의 비교</h2>
<h4 id="1-동일성identity-비교">1. 동일성(identity) 비교</h4>
<ul>
<li>인스턴스의 참조 값을 비교, ==사용<h4 id="2-동등성equivalence-비교">2. 동등성(equivalence) 비교</h4>
</li>
<li>인스턴스의 값을 비교, equals() 사용</li>
<li>값 타입은 a.equals(b)를 사용해서 동등성 비교를 해야함</li>
<li>equals를 오버라이드 해줘야 함(지원해주고 있는 형태를 참조해서 쓰기)(해쉬코드도 구현해줘야 함)(사실 현업에서 그렇게 비교할 일이 많지는 않다고 하심...)</li>
</ul>
<h2 id="5-값-타입-컬렉션">5. 값 타입 컬렉션</h2>
<p><img src="https://velog.velcdn.com/images/amenable-c/post/9d4439ef-2589-44c0-b792-07edb25832ce/image.png" alt=""></p>
<p>Set과 List를 테이블의 DB에 저장할 수 없으므로, 별도로 뽑아야 함</p>
<h4 id="1-사용">1. 사용</h4>
<ul>
<li>값 타입을 하나 이상 저장할 때 사용</li>
<li>@ElementCollection, @CollectionTable 사용</li>
</ul>
<h4 id="2-수정-방법">2. 수정 방법</h4>
<ul>
<li>값 타입은 변경하는게 아니라 새로운 걸로 완전히 교체해야함(앞의 내용 참고)</li>
<li>컬렉션의 경우, remove로 원래꺼 지우고, 새로 add를 하여 넣기</li>
</ul>
<h4 id="3-제약-사항">3. 제약 사항</h4>
<ul>
<li>값 타입은 엔티티와 다르게 식별자 개념이 없다</li>
<li>값은 변경하면 추적이 어렵다</li>
<li>값 타입 컬렉션에 변경 사항이 발생하면, 주인 엔티티와 연관된 모든 데이터를 삭제하고, 값 타입 컬렉션에 있는 현재 값을 모두 다시 저장한다. $\to$ 값 타입을 사요하면 안된다는 말...</li>
<li>값 타입 컬렉션을 맵핑하는 테이블은 모든 컬럼을 묶어서 기본키를 구성해야 함. $\to$ null입력X, 중복 저장X</li>
</ul>
<h4 id="4-진짜-사용법">4. 진짜 사용법</h4>
<ul>
<li>진짜 간단할때만 사용. (치킨, 피자 같은거를 고를때)</li>
<li>주소, 이력과 같은 정보는 엔티티로 관리하기</li>
</ul>
<blockquote>
<p>이 글은 김영한님의 &#39;자바 ORM 표준 JPA 프로그래밍 - 기본편&#39;을 수강하고 정리한 내용입니다.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[프록시와 연관관계 관리]]></title>
            <link>https://velog.io/@amenable-c/%ED%94%84%EB%A1%9D%EC%8B%9C%EC%99%80-%EC%97%B0%EA%B4%80%EA%B4%80%EA%B3%84-%EA%B4%80%EB%A6%AC</link>
            <guid>https://velog.io/@amenable-c/%ED%94%84%EB%A1%9D%EC%8B%9C%EC%99%80-%EC%97%B0%EA%B4%80%EA%B4%80%EA%B3%84-%EA%B4%80%EB%A6%AC</guid>
            <pubDate>Wed, 20 Jul 2022 05:55:32 GMT</pubDate>
            <description><![CDATA[<blockquote>
<ul>
<li>프록시</li>
</ul>
</blockquote>
<ul>
<li>즉시 로딩과 지연 로딩</li>
<li>지연 로딩 활용</li>
<li>영속성 전이 : CASCADE</li>
<li>고아 객체</li>
<li>영속성 전이 + 고아 객체, 생명주기</li>
</ul>
<h2 id="1-프록시">1. 프록시</h2>
<p><img src="https://velog.velcdn.com/images/amenable-c/post/dcedc59d-fd41-4ac1-ae79-57f64c3e0a55/image.png" alt=""></p>
<h4 id="1-emgetreference">1. em.getReference()</h4>
<ul>
<li>데이터베이스 조회를 미루는 가짜(프록시) 엔티티 객체 조회</li>
<li>DB에 쿼리가 안 나가는데, 객체가 조회되는 것</li>
<li>진짜를 넘겨주는게 아니라, 가짜(프록시)엔티티 객체를 줌</li>
<li>껍데기는 같지만, 안에는 비어있는 것</li>
<li>프록시 객체를 호출하면 프록시 객체는 실제 객체의 메소드 호출</li>
</ul>
<h4 id="2-프록시-객체의-초기화">2. 프록시 객체의 초기화</h4>
<pre><code>Member member = em.getReference(Member.class, &quot;id1&quot;);
member.getName();</code></pre><p><img src="https://velog.velcdn.com/images/amenable-c/post/169272ee-afe9-4c56-8731-059508826973/image.png" alt=""></p>
<h4 id="3-프록시의-특징">3. 프록시의 특징</h4>
<ul>
<li>프록시 객체는 처음 사용할 때 한 번만 초기화</li>
<li>프록시 객체를 초기화 할 때, 프록시 객체가 실제 엔티티로 바뀌는 것은 아님, 초
기화되면 프록시 객체를 통해서 실제 엔티티에 접근 가능</li>
<li>프록시 객체는 원본 엔티티를 상속받음, 따라서 타입 체크시 주의해야함 (== 비
교 실패, 대신 instance of 사용)</li>
<li>영속성 컨텍스트에 찾는 엔티티가 이미 있으면 em.getReference()를 호출해
도 실제 엔티티 반환</li>
<li>영속성 컨텍스트의 도움을 받을 수 없는 준영속 상태일 때, 프록시를 초기화하면
문제 발생(하이버네이트는 org.hibernate.LazyInitializationException 예외를 터트림)</li>
</ul>
<p>근데, getReference를 잘 쓰지는 않음
$\to$ 이거를 알아야지 즉시로딩과 지연로딩을 잘 이해할 수 있어서 배우는 것!</p>
<h2 id="2-즉시-로딩과-지연-로딩">2. 즉시 로딩과 지연 로딩</h2>
<h4 id="1즉시-로딩">1.즉시 로딩</h4>
<p><img src="https://velog.velcdn.com/images/amenable-c/post/ceaa79b8-c507-4ce5-8690-87e3264db6ee/image.png" alt=""></p>
<ul>
<li>Member를 조회할 때 Team도 함께 조회하는 것<h4 id="2-지연-로딩">2. 지연 로딩</h4>
<img src="https://velog.velcdn.com/images/amenable-c/post/b1453d1b-3b68-49a6-82a0-019e69e5a995/image.png" alt=""></li>
<li>Member를 조회할 때 Team을 같이 조회하지 않고, Team을 사용할 일이 있을 때 조회를 하는 것</li>
</ul>
<h4 id="3-프록시와-즉시로딩-주의">3. 프록시와 즉시로딩 주의</h4>
<ul>
<li>가급적 지연 로딩만 사용(여러개의 엔티티가 엮여있으면, 다 조회가 되는 문제 때문)</li>
<li>즉시 로딩은 JPQL에서 N+1 문제(최초쿼리는 1개인데, 그에 대한 추가 쿼리가 N가 나간다고 해서 N+1 문제)를 일으킴 $\to$ em.find의 경우는 JPA가 최적화를 해서 한번에 되지만, JPQL 같은 경우는 그냥 SQL을 날리면서 즉시로딩이 필요한거를 다시 또 가져옴</li>
<li>@ManyToOne, @OneToOne은 기본이 즉시 로딩임. $\to$ LAZY로 설정 필요!!!</li>
</ul>
<h2 id="3-지연-로딩-활용">3. 지연 로딩 활용</h2>
<p>이론적인 내용. 실무에서는 다 지연로딩으로 사용하기</p>
<h2 id="4-영속성-전이--cascade">4. 영속성 전이 : CASCADE</h2>
<ul>
<li>특정 엔티티를 영속 상태로 만들 때 연관된 엔티티도 함께 영속 상태로 만들고 싶을 때 사용 $\to$ 엔티티를 영속화할 때, 연관된 엔티티도 함께 영속화하는 편리함을 제공</li>
<li>지연로딩, 즉시로딩, 연관관계  세팅과 전혀 관계가 없는 것</li>
<li>사용시기
(1) 하나의 부모가 자식을 관리할 때 의미가 있음 (소유자가 하나일때, parent만 child를 소유할 때)
(2) 다른 것들과 관계가 있을 때 쓰면 안됨 (Child가 Parent 뿐만 아니라 다른 것들과 관계가 있을때)</li>
</ul>
<h2 id="5-고아-객체">5. 고아 객체</h2>
<h4 id="1-고아-객체-제거">1. 고아 객체 제거</h4>
<ul>
<li>부모 엔티티와 연관관계가 끊어진 자식 엔티티를 자동으로 삭제<h4 id="2-주의">2. 주의</h4>
</li>
<li>참조하는 곳이 하나일 때 사용해야 함</li>
<li>특정 엔티티가 개인 소유할 때 사용</li>
</ul>
<h2 id="6-영속성-전이--고아-객체-생명주기">6. 영속성 전이 + 고아 객체, 생명주기</h2>
<ul>
<li>CascadeType.ALL + orphanRemovel=true</li>
<li>두 옵션을 모두 활성화 하면 부모 엔티티를 통해서 자식의 생명 주기를 관리할 수 있음</li>
<li>도메인 주도 설계(DDD)의 Aggregate Root개념을 구현할 때 유용</li>
</ul>
<blockquote>
<p>이 글은 김영한님의 &#39;자바 ORM 표준 JPA 프로그래밍 - 기본편&#39;을 수강하고 정리한 내용입니다.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[소주콘(소문난 주니어 콘퍼런스) Shot 1 : 진로 빨강 뚜껑]]></title>
            <link>https://velog.io/@amenable-c/%EC%86%8C%EC%A3%BC%EC%BD%98%EC%86%8C%EB%AC%B8%EB%82%9C-%EC%A3%BC%EB%8B%88%EC%96%B4-%EC%BD%98%ED%8D%BC%EB%9F%B0%EC%8A%A4-Shot-1-%EC%A7%84%EB%A1%9C-%EB%B9%A8%EA%B0%95-%EB%9A%9C%EA%BB%91</link>
            <guid>https://velog.io/@amenable-c/%EC%86%8C%EC%A3%BC%EC%BD%98%EC%86%8C%EB%AC%B8%EB%82%9C-%EC%A3%BC%EB%8B%88%EC%96%B4-%EC%BD%98%ED%8D%BC%EB%9F%B0%EC%8A%A4-Shot-1-%EC%A7%84%EB%A1%9C-%EB%B9%A8%EA%B0%95-%EB%9A%9C%EA%BB%91</guid>
            <pubDate>Tue, 19 Jul 2022 12:46:06 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/amenable-c/post/6cebd5da-e15e-4327-8b32-f78692ebb7e9/image.png" alt=""></p>
<blockquote>
<ul>
<li>매 달 3억명이 사용하는 서비스 터뜨리기, 그리고 예방하기 (이수재)</li>
</ul>
</blockquote>
<ul>
<li>좋은 질문은 좋은 대답을 만든다 with relay (정미량)</li>
<li>만들어는 봤나?! 해커톤! (강윤수)</li>
<li>고양이는 야옹야옹하고 웁니다 (정문성, 이상민)</li>
<li>고등학생 CTO가 스타트업에서 살아남는 법 (권동한)</li>
<li>오픈소스에 초보 개발자가 기여하는 방법 (김성일)</li>
</ul>
<h2 id="1-매-달-3억명이-사용하는-서비스-터뜨리기-그리고-예방하기-이수재">1. 매 달 3억명이 사용하는 서비스 터뜨리기, 그리고 예방하기 (이수재)</h2>
<h4 id="1-서버가-죽었다-첫-번째-에러-경험">1. 서버가 죽었다. (첫 번째 에러 경험)</h4>
<ul>
<li>문제점 및 해결 방안
(1) No Alert $\to$ Alert 생성
(2) No Linter $\to$ Linter 생성
(3) No Test $\to$ 시간이 없어도 테스트 하자...
(4) Power of Feature Flags $\to$ 항상 동적으로 동작하게 하여 복구를 빠르게 하자.
(5) Always Automate $\to$ 항상 자동화가 되게끔하라!</li>
</ul>
<h4 id="2-서버가-죽지-않았는데-검색이-안된다두-번째-에러-경험">2. 서버가 죽지 않았는데, 검색이 안된다...(두 번째 에러 경험)</h4>
<ul>
<li>문제점 및 해결 방안
(1) (Not Enough) Alert 
(2) Dependency $\to$ 제대로 작동할것이라는 가정하에 프로그램을 동작시키면 안됨!
(3) 외부 서비스는 항상 실패를 가정하자
(4) 중요한 것은 우리 서버만이 아닌 서비스다. $\to$ 코드의 존재 의의는 최종 사용자를 위한 것</li>
</ul>
<h4 id="3-위의-두-가지-에러를-통해-강연자님께서-느낀점">3. 위의 두 가지 에러를 통해 강연자님께서 느낀점</h4>
<p>(1) 빠른 성능, 좋은 기능도 좋지만 안정감 있고 신뢰감 있는 서비스가 먼저다.(BC2 경험을 통한 것)
(2) 안전 장치 덕분에 릴리즈에 대한 부담이 줄어서 개발 속도가 오히려 빨라질 수도 있다.</p>
<h2 id="2-좋은-질문은-좋은-대답을-만든다-with-relay-정미량">2. 좋은 질문은 좋은 대답을 만든다 with relay (정미량)</h2>
<ul>
<li><p>행복한 질문 생활을 하기 위한 방법
(1) 문제 상황에 대해 깔끔하게 분석 후 정리하자.
(2) 공식 Docs를 읽고, 공식적인 내요을 참조로 제시하자
(3) 충분한 고민 후에도 해결이 되지 않으면 질문하자.
(4) 필요한 정보를 충분하고 간결하게 전달하자.
(5) 질문 받는 사람은 맥락을 모른다.
(6) 질문의 대상은 가까운 개발자분들, 사내 개발자분들 외에도 Stackoverflow, 공식 커뮤니티등이 될 수 있다.
(7) 질문을 두려워하지 말자.
(8) 질문 후 결과는 꼭 잘 정리해서 다시 공유를 하자.</p>
</li>
<li><p>질문 내용 정리(간단 버전)
$\to$ 상황
$\to$ 맥락
$\to$ 무슨 시도를 했는지!!
$\to$ 어떤것에 대한 답이 필요한지</p>
</li>
</ul>
<h2 id="3-만들어는-봤나-해커톤-강윤수">3. 만들어는 봤나?! 해커톤! (강윤수)</h2>
<p>해커톤을 기획하면서 겪은 어려운점 및 경험을 말씀해주셨습니다.</p>
<h2 id="4-고양이는-야옹야옹하고-웁니다-정문성-이상민">4. 고양이는 야옹야옹하고 웁니다 (정문성, 이상민)</h2>
<ul>
<li><p>고양이의 분리불안을 해소시키는 것을 목표로 토이프로젝트 시작하셨다고 함.</p>
</li>
<li><p>라즈베리파이, 소리 기술에 대한 머신러닝, Flutter 등을 이용하여 서비스 구축</p>
</li>
<li><p>느낀점
$\to$ 임베디드 관련해서 프로젝트를 할 때 너무 힘들었던 경험이 있었는데, 다시 이렇게 재밌는 서비스를 보니 또 다시 해보고 싶다는 생각이 든다.
$\to$ Flutter를 빠르게 배우고 사용하셨다는 점에서, 새로운 기술을 배우고 빨리 적용시켜보고 싶은 욕심이 생긴다.</p>
</li>
</ul>
<h2 id="5-고등학생-cto가-스타트업에서-살아남는-법-권동한">5. 고등학생 CTO가 스타트업에서 살아남는 법 (권동한)</h2>
<p>vcl, 리팩토링 경험, FastAPI 등 다양한 경험에 대해서 얘기를 해주셨다.
아직까지 안 써본 기술들이라서 정확히 이해를 하지는 못했지만, 어린 나이에 빠른 시간 안에 성장한 모습을 보면서 많은 동기부여가 되었다!!!</p>
<h2 id="6-오픈소스에-초보-개발자가-기여하는-방법-김성일">6. 오픈소스에 초보 개발자가 기여하는 방법 (김성일)</h2>
<h4 id="1-라이센스-규정에-대한-설명mit-apache-gpl">1. 라이센스 규정에 대한 설명(MIT, APACHE, GPL)</h4>
<h4 id="2-오픈-소스-기여가-좋은-이유">2. 오픈 소스 기여가 좋은 이유</h4>
<ul>
<li>문제 해결 능력 상승 $\to$ 명확한 답이 없는 문제라서</li>
<li>커뮤니케이션 능력 상승 $\to$ 처음부터 끝까지 소통을 기반으로 함 + 영어로 소통하는 경우가 많음(기술적인 언어, 공적인 언어)</li>
</ul>
<h4 id="3-기여를-시작하기-위한-대상을-찾는-법">3. 기여를 시작하기 위한 대상을 찾는 법</h4>
<ul>
<li>관심이 있거나 사용하고 있는 오픈소스에 기여하자.(사용하는 프로그램 혹은 라이브러리에서 찾기)</li>
<li>스스로 불련한 점을 겪고 있는 것에서 찾아보기</li>
<li>작은 프로젝트부터 시작하기(큰 프로젝느는 구조 파악부터 너무 오래 걸림...)</li>
</ul>
<h4 id="4-오픈-소스-기여과정-및-설명">4. 오픈 소스 기여과정 및 설명</h4>
<p>(1) Issue(문제를 작성하는 과정)</p>
<ul>
<li>mainainer가 이해하기 쉽게, 최대한 자세하게 작성하기 </li>
<li>issue template가 있으면 형식에 맞춰 작성하기</li>
</ul>
<p>(2) 코드 혹은 문서 수정 및 추가</p>
<p>(3) PR 작성
: 무엇을 어떻게 수정하였는지 최대한 자세하게 작성하자</p>
<p>(4) CI(지속적인 통합)
: Github Actions와 같은 CI툴에 의해 코드 스타일 체크 및 테스트등을 수행</p>
<p>(5) Review
: 단순히 검사를 받는 것이 아닌, 서로간의 소통을 통해 더 좋은 방법을 논의 하는 것</p>
<p>(6) Merge</p>
<h4 id="5-코드-작성만이-기여가-아니다">5. 코드 작성만이 기여가 아니다.</h4>
<ul>
<li>오타 고치기</li>
<li>번역하기 (다수의 국가에서 사용되는 프로젝트는 번역이 필요함)</li>
<li>버그 제보하기</li>
</ul>
<h4 id="6-오픈소스-기여시-주의할-점">6. 오픈소스 기여시 주의할 점</h4>
<p>(1) 올바르게 기여하기
: 가이드라인 준수(CONTRIBUTING.md)
: 코딩 스타일 준수
(2) 기다림은 필수
: maintainer의 직업은 maintainer가 아니다!
(3) 좌절하지 않기
: 항상 pr이 merge 될 수 없음 (그래도 시도 자체도 의미 있는 행위)</p>
<h4 id="7-tips">7. Tips</h4>
<p>(1) Good First Issue(초보자가 고치기 쉬운 이슈) $\to$ 이걸 모아놓은 사이트도 있음 
// Up For Grabs도 참고하기
(2) 오픈소스 컨트리뷰톤 이용하기
(3) 기여를 위한 기여하지 않기
: 이력서 한 줄을 위해, 억지로 기여하지 말자
: 억지로하면 흥미도 금방 잃고, 재미도 없다.
: 자신이 관심있고 사용하는걸 하자!!</p>
<p><a href="https://velog.io/@kshired/%EC%98%A4%ED%94%88%EC%86%8C%EC%8A%A4%EC%97%90-%EC%B4%88%EB%B3%B4-%EA%B0%9C%EB%B0%9C%EC%9E%90%EA%B0%80-%EA%B8%B0%EC%97%AC%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95">강연자님의 참고 레퍼런스</a></p>
<blockquote>
<p>이 글은 &#39;소주콘(소문난 주니어 콘퍼런스) Shot 1 : 진로 빨강 뚜껑&#39;에 참석하고 정리한 내용입니다.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[고급맵핑]]></title>
            <link>https://velog.io/@amenable-c/%EA%B3%A0%EA%B8%89%EB%A7%B5%ED%95%91</link>
            <guid>https://velog.io/@amenable-c/%EA%B3%A0%EA%B8%89%EB%A7%B5%ED%95%91</guid>
            <pubDate>Fri, 15 Jul 2022 03:01:02 GMT</pubDate>
            <description><![CDATA[<blockquote>
<ul>
<li><ol>
<li>상속관계 맵핑</li>
</ol>
</li>
</ul>
</blockquote>
<ul>
<li><ol start="2">
<li>@MappedSuperclass</li>
</ol>
</li>
</ul>
<h2 id="1-상속관계-맵핑">1. 상속관계 맵핑</h2>
<ul>
<li>관계형 데이터베이스는 상속관계X</li>
<li>슈퍼타입 서브타입 관계라는 모델링 기법이 객체 상속과 유사</li>
<li>상속관계 맵핑 = 슈퍼타입 서브타입 논리 모델을 실제 물리 모델로 구현하는 방법(객체의 상속과 구조와 DB의 슈퍼타입 서브타입 관계를 맵핑)</li>
<li>전략 3개 
(1) 각각의 테이블로 변환 $\to$ 조인 전략
(2) 통합 테이블로 변환 $\to$ 단인 테이블 전략
(3) 서브타입 테이블로 변환 $\to$ 구현 클래스마다 테이블 전략
$\to$ 논리 모델을 위와 같은 3가지의 구체적인 물리모델로 구현할 수 있는데, 객체 입장에서는 다 똑같음.</li>
<li>주요 어노테이션
(1) @Inheritance(strategy=IngetitanceType.XXX)
$\to$ JOINED : 조인전략
$\to$ SINGLE_TABLE : 단일 테이블 전략
$\to$ TABLE_PER_CLASS : 구현 클래스마다 테이블 전략
(2) DiscriminatorColumn(name=&quot;DTYPE&quot;)
(3) DiscriminatorValue(&quot;XXX&quot;)</li>
</ul>
<h4 id="1-조인-전략">1. 조인 전략</h4>
<p><img src="https://velog.velcdn.com/images/amenable-c/post/5d4bc42b-4a67-4f63-8d0e-4d0324c5222d/image.png" alt=""></p>
<p>(1) 장점</p>
<ul>
<li>테이블 정규화</li>
<li>외래 키 참조 무결성 제약조건 활용가능</li>
<li>저장공간 효율화
(2) 단점</li>
<li>조회시 조인을 많이 사용, 성능 저하</li>
<li>조회 쿼리가 복잡함</li>
<li>데이터 저장시 INSERT SQL 2번 호출
(3) DTYPE</li>
<li>구분하는 컬럼</li>
<li>쿼리를 날렸을 때, 자식의 누구때문에 들어온건지 알 수 있게 해줌 $\to$ 운영이나 DB의 작업에서 필요한것 (@DiscriminatorColumn을 쓰면 설정 됨)</li>
<li>자식 클래스에 @DiscriminatorValue(&quot;XXX&quot;)를 설정하므로써 Entity명이 아닌 다른 이름으로 바꿔서 DTYPE에 표현할 수 있음(@DiscriminatorValue(&quot;M&quot;)으로 하면, MEMBER로 표시되는게 M으로 표시 됨)</li>
</ul>
<h4 id="2-단일-테이블-전략">2. 단일 테이블 전략</h4>
<p><img src="https://velog.velcdn.com/images/amenable-c/post/62a4332e-ec7e-4d7b-a4f5-718616c5c020/image.png" alt=""></p>
<ol>
<li>장점</li>
</ol>
<ul>
<li>조인이 필요 없으므로 일반적으로 조회 성능이 빠름</li>
<li>조회 쿼리가 단순함</li>
</ul>
<ol start="2">
<li>단점</li>
</ol>
<ul>
<li>자식 엔티티가 맵핑한 컬럼은 모두 null 허용</li>
<li>단일 테이블에 모든 것을 저장하므로 테이블이 커질 수 있음. 상황에 따라서 조회 성능이 오히려 느려질 수 있음.</li>
</ul>
<ol start="3">
<li>추가사항</li>
</ol>
<ul>
<li>단일테이블에서 @DiscriminatorColumn을 안써도 DTYPE 생성해줌
$\to$ 조인전략에서는 테이블이 분리되어있으니깐 어떻게든 누구의 데이터인지 알 수 있는데, 단일 테이블에서는 알 수 있는 방법이 없음. 그래서 DTYPE이 필수로 생성됨</li>
</ul>
<h4 id="3-구현-클래스마다-테이블전략">3. 구현 클래스마다 테이블전략</h4>
<p><img src="https://velog.velcdn.com/images/amenable-c/post/79bb4517-a6ff-4dac-92f7-24b37f6104b5/image.png" alt=""></p>
<ol>
<li>장점</li>
</ol>
<ul>
<li>서브 타입을 명확하게 구분해서 처리할 때 효과적</li>
<li>not null 제약조건 사용 가능</li>
</ul>
<ol start="2">
<li>단점</li>
</ol>
<ul>
<li>여러 자식 테이블을 함께 조회할 때 성능이 느림(UNION SQL 필요) </li>
<li>자식 테이블을 통합해서 쿼리하기 어려움</li>
</ul>
<ol start="3">
<li>추가 개념</li>
</ol>
<ul>
<li>@DiscriminatorColumn이 의미가 없음(넣어도 사용 안됨)(테이블 자체가 다르기때문에)</li>
<li>특정 한 곳에서 가져올 때는 괜찮은데, 부모 클래스에서 가져올때는 모든 것을 다 확인하고 가져옴</li>
</ul>
<h4 id="4-전략-3가지-정리">4. 전략 3가지 정리</h4>
<ol>
<li>조인 전략</li>
</ol>
<ul>
<li>이게 정석</li>
<li>외래 키 참조 무결성 제약조건 활용가능(다른 테이블에서 부모클래스만 보면 된다는거)</li>
</ul>
<ol start="2">
<li>단일 테이블 전략</li>
</ol>
<ul>
<li>단순하고, 확장할 가능성도 별로 없을꺼 같을때 이거 선택</li>
<li>null 허용한다는게 치명적인 단점</li>
</ul>
<ol start="3">
<li>구현 클래스마다 테이블 전략</li>
</ol>
<ul>
<li>묶이는게 없음</li>
<li>이거 쓰면 안됨.</li>
</ul>
<h2 id="2-mappedsuperclass">2. @MappedSuperclass</h2>
<p><img src="https://velog.velcdn.com/images/amenable-c/post/142b5b32-b1fa-48c9-b549-667875b4c4ca/image.png" alt=""></p>
<ul>
<li>DB는 다른데 객체 입장에서 속성만 상속해서 사용하고 싶을때 사용</li>
<li>하나의 클래스를 @MappedSuperclass를 이용해서 만들고, extends를 이용해서 다른 클래스들이 상속 받기</li>
<li>조금 더 정확하게 말하면 상속관계 맵핑이 아님. 그냥 속성만 내려주는 것</li>
<li>직접 생성해서 사용할 일이 없으므로 추상 클래스 권장</li>
<li>참고 : @Entity 클래스는 엔티티나 @MappedSuperClass로 지정한 클래스만 상속 가능</li>
</ul>
<blockquote>
<p>이 글은 김영한님의 &#39;자바 ORM 표준 JPA 프로그래밍 - 기본편&#39;을 수강하고 정리한 내용입니다.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[다양한 연관관계 맵핑]]></title>
            <link>https://velog.io/@amenable-c/%EB%8B%A4%EC%96%91%ED%95%9C-%EC%97%B0%EA%B4%80%EA%B4%80%EA%B3%84-%EB%A7%B5%ED%95%91</link>
            <guid>https://velog.io/@amenable-c/%EB%8B%A4%EC%96%91%ED%95%9C-%EC%97%B0%EA%B4%80%EA%B4%80%EA%B3%84-%EB%A7%B5%ED%95%91</guid>
            <pubDate>Fri, 15 Jul 2022 02:40:36 GMT</pubDate>
            <description><![CDATA[<blockquote>
<ul>
<li><ol>
<li>연관관계 맵핑시 고려사항 3가지</li>
</ol>
</li>
</ul>
</blockquote>
<ul>
<li><ol start="2">
<li>다대일[N:1]</li>
</ol>
</li>
<li><ol start="3">
<li>일대다[1:N]</li>
</ol>
</li>
<li><ol start="4">
<li>일대일[1:1]</li>
</ol>
</li>
<li><ol start="5">
<li>다대다[N:M]</li>
</ol>
</li>
</ul>
<h2 id="1-연관관계-맵핑시-고려사항-3가지">1. 연관관계 맵핑시 고려사항 3가지</h2>
<h4 id="1-다중성">1. 다중성</h4>
<p>@ManyToOne, @OneToMany, @OneToOne, @ManyToMany</p>
<h4 id="2-단방향-양방향">2. 단방향, 양방향</h4>
<ol>
<li>테이블</li>
</ol>
<ul>
<li>외래 키 하나로 양쪽 조인 가능</li>
<li>사실 방향이라는 개념이 없음</li>
</ul>
<ol start="2">
<li>객체</li>
</ol>
<ul>
<li>참조용 필드가 있는 쪽으로만 참조 가능</li>
<li>한쪽만 참조하면 단방향</li>
<li>양쪽이 서로 참조하면 양방향</li>
</ul>
<h4 id="3-연관관계의-주인">3. 연관관계의 주인</h4>
<ul>
<li>테이블은 외래 키 하나로 두 테이블이 연관관계를 맺음</li>
<li>객체 양방향 관계는 참조가 2군데 있음. 둘 중에 테이블의 외래 키를 관리할 곳을 지정해야 함.</li>
<li>연관관계의 주인 = 외래 키를 관리하는 참조</li>
<li>주인의 반대편 = 외래 키에 영향을 주지 않음. 단순 조회만 가능</li>
</ul>
<h2 id="2-다대일n1">2. 다대일[N:1]</h2>
<p><img src="https://velog.velcdn.com/images/amenable-c/post/54211a48-eb3b-4003-a58f-07d1102379e4/image.png" alt=""></p>
<ul>
<li>가장 많이 사용하는 연관관계</li>
</ul>
<h2 id="3-일대다1n">3. 일대다[1:N]</h2>
<p><img src="https://velog.velcdn.com/images/amenable-c/post/8ceaf69a-0c7d-4401-9140-6eda227fc5d2/image.png" alt=""></p>
<ul>
<li>권장하지 않음(실무에서 거의 안 쓰신다고 함...)</li>
<li>일대다 단방향 맵핑보다는 <strong>다대일 양방향 맵핑</strong>을 사용하자</li>
</ul>
<h2 id="4-일대일11">4. 일대일[1:1]</h2>
<p><img src="https://velog.velcdn.com/images/amenable-c/post/06a98102-5df1-49e4-9060-4aeeb9f433ea/image.png" alt=""></p>
<ul>
<li>주 테이블이나 대상 테이블 중에 외래 키 선택 가능</li>
<li>외래 키에 데이터베이스 유니크(UNI) 제약조건 추가</li>
<li>외래 키 관련 예시(외래키를 MEMBER에 두기 vs LOCKER에 두기)<ol>
<li>DBA 입장
(1) 시간이 지나서 비지니스 룰이 &#39;하나의 회원이 여러 개의 라커를 가지게 한다.&#39;로 바뀌면, LOCKER쪽에 외래키가 있는게 더 바꾸기 쉬움
(만약에 MEMBER에 외래키가 있으면, 변경 포인트가 많음)
(2) &#39;하나의 라커를 여러명이 공유하도록 한다.&#39; 면 반대가 맞음</li>
<li>개발자 입장
(1) 멤버에 라커가 있는게 여러가지로 유리
$\to$ 멤버를 조회할 때, 라커에 대한 값이 있는지 없는지 쉽게 나옴</li>
</ol>
</li>
</ul>
<h2 id="5-다대다nm">5. 다대다[N:M]</h2>
<p><img src="https://velog.velcdn.com/images/amenable-c/post/b6ab8183-671b-4afc-9cd0-5305964697a4/image.png" alt=""></p>
<ul>
<li>실무에서 쓰면 안됨
추가데이터가 들어오면 쓸 수가 없음(중간테이블에 맵핑 정보만 들어가고, 추가 정보를 더 넣는게 불가능 하다는 것)
쿼리가 직관적이지 않게 날라감(중간테이블 때문에 생각한것과 다르게 쿼리가 나감)</li>
<li>한계 극복
$\to$ @OneToMany, @ManyToOne으로 변경</li>
</ul>
<blockquote>
<p>이 글은 김영한님의 &#39;자바 ORM 표준 JPA 프로그래밍 - 기본편&#39;을 수강하고 정리한 내용입니다.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[SpringBoot & S3 (이미지)]]></title>
            <link>https://velog.io/@amenable-c/SpringBoot-S3-%EC%9D%B4%EB%AF%B8%EC%A7%80</link>
            <guid>https://velog.io/@amenable-c/SpringBoot-S3-%EC%9D%B4%EB%AF%B8%EC%A7%80</guid>
            <pubDate>Fri, 15 Jul 2022 01:29:12 GMT</pubDate>
            <description><![CDATA[<blockquote>
<ol>
<li>AWS 서비스에서 처리해야 하는 것들</li>
<li>로컬 환경에서 처리해야 하는 것들</li>
</ol>
</blockquote>
<h2 id="1-aws-서비스에서-처리해야-하는-것들">1. AWS 서비스에서 처리해야 하는 것들</h2>
<ol>
<li>S3 bucket 생성</li>
<li>퍼블릭 엑세스 설정</li>
<li>퍼블릭 정책 활성화</li>
</ol>
<ul>
<li><a href="awspolicygen.s3.amazonaws.com/policygen.html">버킷 정책 생성 참고</a></li>
</ul>
<ol start="4">
<li>엑세스 키 생성</li>
</ol>
<ul>
<li>S3에 접근하려면 별도의 인증 과정이 필요한데, 이때 사용되는 것이 엑세스 키</li>
<li>엑세스 키는 AWSAccessKeyId와 AWSSecretKey로 구성</li>
<li>이거를 application.yml과 같은 파일에 입력해줘야함.(GitHub 이용할때, 이런 정보들 안 올리도록 조심!!! ./gitignore 이용!!!)</li>
</ul>
<h2 id="2-로컬-환경에서-처리해야-하는-것들">2. 로컬 환경에서 처리해야 하는 것들</h2>
<h4 id="1-gradle-설정">1. gradle 설정</h4>
<p>상황마다 달라서, 구글링해보기</p>
<h4 id="2-s3uploaderjava-생성">2. S3Uploader.java 생성</h4>
<pre><code>@Slf4j
@RequiredArgsConstructor
@Component
public class S3Uploader {

    private final AmazonS3Client amazonS3Client;

    @Value(&quot;${cloud.aws.s3.bucket}&quot;)
    private String bucket;

    public String upload(MultipartFile multipartFile, String dirName) throws IOException {
        File uploadFile = convert(multipartFile)
                .orElseThrow(() -&gt; new IllegalArgumentException(&quot;MultipartFile -&gt; File로 전환이 실패했습니다.&quot;));

        return upload(uploadFile, dirName); // 밑으로 이동
    }

    private String upload(File uploadFile, String dirName) {
        String fileName = dirName + &quot;/&quot; + uploadFile.getName();
        String uploadImageUrl = putS3(uploadFile, fileName); // 여기에서 S3에 올리는듯 // 밑에 함수
        removeNewFile(uploadFile); // 맨 밑에 함수
        return uploadImageUrl;
    }

    private String putS3(File uploadFile, String fileName) { // 여기서 실제로 s3에 올라감
        amazonS3Client.putObject(new PutObjectRequest(bucket, fileName, uploadFile).withCannedAcl(CannedAccessControlList.PublicRead));
        return amazonS3Client.getUrl(bucket, fileName).toString();
    }

    private void removeNewFile(File targetFile) { // 로컬에 저장한 정보를 이용해서 올렸다가, 로컬에 저장된거를 지우는거 같은데?
        if (targetFile.delete()) {
            log.info(&quot;파일이 삭제되었습니다.&quot;); //이게 제대로 실행 되는거
        } else {
            log.info(&quot;파일이 삭제되지 못했습니다.&quot;);
        }
    }

    private Optional&lt;File&gt; convert(MultipartFile file) throws IOException {
        String fileName = file.getOriginalFilename();
        File convertFile = new File(file.getOriginalFilename());
        //System.out.println(convertFile.createNewFile()); // 이미 있으면 false, 없으면 true
        if(convertFile.createNewFile()) { // 파일이 이전에 존재하지 않으면 true를 띄우고 들어감.
            try (FileOutputStream fos = new FileOutputStream(convertFile)) {
                fos.write(file.getBytes());
            }
            return Optional.of(convertFile);
        }
        return Optional.empty();
    }


}</code></pre><ul>
<li>S3Uploader.java $\to$ S3에 정적 파일을 올리는 기능을 함</li>
<li>동작 방식
(1) MultipartFile을 전달 받음
(2) convert를 통하여 MultipartFile을 File로 전환
(3) 전환된 File을 S3에 &#39;public 읽기&#39; 권한으로 put
(4) 로컬에 생성된 File 삭제(MultipartFile을 File로 전환하는 과정에서 로컬에 파일이 생성되었음)
(5) 업로드된 파일의 S3 URL 주소를 반환</li>
<li>위의 코드에서 &#39;dirName&#39;은 S3에 생성된 디렉토리</li>
</ul>
<h4 id="3-controller">3. Controller</h4>
<pre><code>@PostMapping(&quot;/upload&quot;)
    @ResponseBody
    public String upload(@RequestParam(&quot;data&quot;) MultipartFile multipartFile) throws IOException {
        return s3Uploader.upload(multipartFile, &quot;static&quot;);
    }</code></pre><p>받아온 multipartFile과 S3에 생성된 디렉토리의 이름(여기에서는 &quot;static&quot;)을 입력</p>
<blockquote>
<p>이 글은 향로님의 &#39;SpringBoot &amp; AWS S3 연동하기&#39;를 통해 기능을 구현해보고 정리한 내용입니다.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[Specification]]></title>
            <link>https://velog.io/@amenable-c/Specification</link>
            <guid>https://velog.io/@amenable-c/Specification</guid>
            <pubDate>Fri, 15 Jul 2022 00:56:54 GMT</pubDate>
            <description><![CDATA[<blockquote>
<ol>
<li>Specification을 구현하는 방법</li>
</ol>
</blockquote>
<h2 id="1-specification">1. Specification</h2>
<h4 id="1-repository에서-jpaspecificationexecutor를-상속받기">1. Repository에서 JpaSpecificationExecutor를 상속받기</h4>
<ul>
<li>JpaSpecificationExecutor에는 기존의 JpaRepository에 있는 메서드와 비슷하지만 인자로 Specification이 있다는 점이 다름</li>
</ul>
<h4 id="2-criteriabuilder를-통해-지정된-객체에-아래와-같은-방식을-통해-다양한-쿼리를-날림">2. criteriaBuilder를 통해, 지정된 객체에 아래와 같은 방식을 통해 다양한 쿼리를 날림.</h4>
<pre><code>criteriaBuilder.equal(root.get(&quot;name&quot;), name);

criteriaBuilder.like(root.get(&quot;content&quot;), &quot;%&quot; + content + &quot;%&quot;);

criteriaBuilder.equal(root.get(&quot;origin&quot;), origin);

criteriaBuilder.between(root.get(&quot;date&quot;), start, end);

criteriaBuilder.lessThanOrEqualTo(root.get(&quot;date&quot;), end);</code></pre><p>아래는 자세한 코드</p>
<pre><code>public class ItemSpecification {
    public static Specification&lt;Item&gt; equalName(String name){
        return new Specification&lt;Item&gt;() {
            @Override
            public Predicate toPredicate(Root&lt;Item&gt; root, CriteriaQuery&lt;?&gt; query, CriteriaBuilder criteriaBuilder) {
                return criteriaBuilder.equal(root.get(&quot;name&quot;), name);
            }
        };
    }

    public static Specification&lt;Item&gt; likeContent(String content){
        return new Specification&lt;Item&gt;() {
            @Override
            public Predicate toPredicate(Root&lt;Item&gt; root, CriteriaQuery&lt;?&gt; query, CriteriaBuilder criteriaBuilder) {
                return criteriaBuilder.like(root.get(&quot;content&quot;), &quot;%&quot; + content + &quot;%&quot;);
            }
        };
    }

    public static Specification&lt;Item&gt; equalOrigin(String origin){
        return new Specification&lt;Item&gt;() {
            @Override
            public Predicate toPredicate(Root&lt;Item&gt; root, CriteriaQuery&lt;?&gt; query, CriteriaBuilder criteriaBuilder) {
                return criteriaBuilder.equal(root.get(&quot;origin&quot;), origin);
            }
        };
    }

    public static Specification&lt;Item&gt; betweenDate(LocalDate start, LocalDate end){
        return new Specification&lt;Item&gt;() {
            @Override
            public Predicate toPredicate(Root&lt;Item&gt; root, CriteriaQuery&lt;?&gt; query, CriteriaBuilder criteriaBuilder) {
                return criteriaBuilder.between(root.get(&quot;date&quot;), start, end);
            }
        };
    }

    public static Specification&lt;Item&gt; greaterThanOrEqualDate(LocalDate start){
        return new Specification&lt;Item&gt;() {
            @Override
            public Predicate toPredicate(Root&lt;Item&gt; root, CriteriaQuery&lt;?&gt; query, CriteriaBuilder criteriaBuilder) {
                return criteriaBuilder.greaterThanOrEqualTo(root.get(&quot;date&quot;), start);
            }
        };
    }

    public static Specification&lt;Item&gt; lessThanOrEqualDate(LocalDate end){
        return new Specification&lt;Item&gt;() {
            @Override
            public Predicate toPredicate(Root&lt;Item&gt; root, CriteriaQuery&lt;?&gt; query, CriteriaBuilder criteriaBuilder) {
                return criteriaBuilder.lessThanOrEqualTo(root.get(&quot;date&quot;), end);
            }
        };
    }

    public static Specification&lt;Item&gt; betweenPrice(Long min, Long max){
        return new Specification&lt;Item&gt;() {
            @Override
            public Predicate toPredicate(Root&lt;Item&gt; root, CriteriaQuery&lt;?&gt; query, CriteriaBuilder criteriaBuilder) {
                return criteriaBuilder.between(root.get(&quot;price&quot;), min, max);
            }
        };
    }

    public static Specification&lt;Item&gt; greaterThanOrEqualPrice(Long min){
        return new Specification&lt;Item&gt;() {
            @Override
            public Predicate toPredicate(Root&lt;Item&gt; root, CriteriaQuery&lt;?&gt; query, CriteriaBuilder criteriaBuilder) {
                return criteriaBuilder.greaterThanOrEqualTo(root.get(&quot;price&quot;), min);
            }
        };
    }

    public static Specification&lt;Item&gt; lessThanOrEqualPrice(Long max){
        return new Specification&lt;Item&gt;() {
            @Override
            public Predicate toPredicate(Root&lt;Item&gt; root, CriteriaQuery&lt;?&gt; query, CriteriaBuilder criteriaBuilder) {
                return criteriaBuilder.lessThanOrEqualTo(root.get(&quot;price&quot;), max);
            }
        };
    }

}</code></pre><h4 id="3-controller-에서의-구현">3. Controller 에서의 구현</h4>
<pre><code>Specification&lt;Item&gt; spec = (root, query, criteriaBuilder) -&gt; null;

        if(name != null){
            spec = spec.and(ItemSpecification.equalName(name));
        }
        if(content != null){
            spec = spec.and(ItemSpecification.likeContent(content));
        }
        if(origin != null){
            spec = spec.and(ItemSpecification.equalOrigin(origin));
        }
        if(start != null &amp;&amp; end != null){
            spec = spec.and(ItemSpecification.betweenDate(start, end));
        }
        if(start != null &amp;&amp; end != null){
            spec = spec.and(ItemSpecification.greaterThanOrEqualDate(start));
        }
        if(start == null &amp;&amp; end != null){
            spec = spec.and(ItemSpecification.lessThanOrEqualDate(end));
        }
        if(min != null &amp;&amp; max != null){
            spec = spec.and(ItemSpecification.betweenPrice(min, max));
        }
        if(min != null &amp;&amp; max == null){
            spec = spec.and(ItemSpecification.greaterThanOrEqualPrice(min));
        }
        if(min == null &amp;&amp; max != null){
            spec = spec.and(ItemSpecification.lessThanOrEqualPrice(max));
        }


        model.addAttribute(&quot;specResults&quot;, itemRepository.findAll(spec));</code></pre><ol>
<li><code>Controller에서 Specification&lt;Item&gt; spec = (root, query, criteriaBuilder) -&gt; null;</code> 로 설정하여 일단 spec을 정의</li>
<li>그리고 spec = spec.and(ItemSpecification.equalName(name)) 등을 통해 계속해서 찾고자 하는 조건 추가</li>
<li>마지막에 itemRepository.findAll(spec));을 통해 한번에 가져옴</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[GitHub로 협업하기]]></title>
            <link>https://velog.io/@amenable-c/GitHub%EB%A1%9C-%ED%98%91%EC%97%85%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@amenable-c/GitHub%EB%A1%9C-%ED%98%91%EC%97%85%ED%95%98%EA%B8%B0</guid>
            <pubDate>Thu, 14 Jul 2022 12:42:33 GMT</pubDate>
            <description><![CDATA[<blockquote>
<ul>
<li><ol>
<li>Git과 GitHub의 차이</li>
</ol>
</li>
</ul>
</blockquote>
<ul>
<li><ol start="2">
<li>Git의 특징(분산 버전 관리 시스템)</li>
</ol>
</li>
<li><ol start="3">
<li>충돌 관리</li>
</ol>
</li>
<li><ol start="4">
<li>Repository Workflow</li>
</ol>
</li>
<li><ol start="5">
<li>Convention(협약)</li>
</ol>
</li>
<li><ol start="6">
<li>Management</li>
</ol>
</li>
<li><ol start="7">
<li>Collaboration(협업)</li>
</ol>
</li>
<li><ol start="8">
<li>Pull Request</li>
</ol>
</li>
</ul>
<h2 id="1-git과-github의-차이">1. Git과 GitHub의 차이</h2>
<p>GitHub는 Git을 활용한 code hosting platform이다.</p>
<h2 id="2-git의-특징">2. Git의 특징</h2>
<h4 id="1-git">1. Git</h4>
<ul>
<li>분산(Distributed) 버전 관리 시스템
$\to$ 분산이란? = 각각의 컴퓨터에 저장소(Repository)가 분리되어 있다.(commit을 하면 자신의 repository에 쌓이고, push를 하면 remote repository에 올라가는 거!!)</li>
</ul>
<h4 id="2-흐름">2. 흐름</h4>
<ol>
<li>Clone 또는 Init
Local Repsitory 생성</li>
<li>commit
Local repository에 작업이 쌓이는 것</li>
<li>push(local과 remote sync를 맞추는 것)
Remote repository에 작업이 올라가는 것</li>
<li>pull(local과 remote sync를 맞추는 것)
Remote repository에서 Local repository로 작업을 가져오는것</li>
</ol>
<h2 id="3-충돌-관리">3. 충돌 관리</h2>
<h4 id="1-충돌이-발생하는-이유">1. 충돌이 발생하는 이유</h4>
<p>협업자 간 Git History 불일치</p>
<h4 id="2-충돌-분석">2. 충돌 분석</h4>
<ul>
<li>충돌 위치(파일, 라인)</li>
<li>충돌 유형(단순 코드 스타일 차이, 로직 변경 또는 리팩터링, 동시 추가)</li>
<li>충돌 원인(이력이 틀어진 시점)</li>
</ul>
<h4 id="3-하면-안되는-것">3. 하면 안되는 것</h4>
<ul>
<li>발생한 충돌을 의논 없이 수정하기(단순 코드 스타일 제외 = 코드 스타일을 정의해놨다는 전제하에는 지워도 됨)</li>
<li><code>git push --force</code>(branch랑 commit history가 틀어짐)</li>
</ul>
<h2 id="4-repository-workflow">4. Repository Workflow</h2>
<h4 id="1-centralized-와-forking의-차이">1. Centralized 와 Forking의 차이</h4>
<p><img src="https://velog.velcdn.com/images/amenable-c/post/9fd1fe6e-2b28-4bb1-aba4-4fe9b44b5ce2/image.png" alt="">
(1) Centralized</p>
<ul>
<li>&quot;Origin - Local&quot;로 구성</li>
<li>Remote repository(그룹저장소)가 origin이 되고, Local repository(개인 저장소)가 Local이 됨 </li>
</ul>
<p>(2) Fork</p>
<ul>
<li>&quot;Upstream - Origin - Local&quot;로 구성</li>
<li>Remote repository(그룹저장소)가 Upastream이 되고, Local repository(개인 저장소)가 Origin이 됨 </li>
<li>push를 하면 개인저장소(origin)에 들어감 $\to$ 그룹저장소에는 반영이 안됨</li>
<li>PR로 개인 저장소와 그룹 저장소 sync 맞추기</li>
</ul>
<h2 id="5-convention협약">5. Convention(협약)</h2>
<p>(1) Coding Style
Naming, Indentation, Quote
(2) Structure
File / Directory, Architecture
(3) Commit
Conventional Commits, Angular Commit Message
(4) Branching
Git Flow, GitHub Flow, GitLab Flow
(5) Automation
CI / CD</p>
<h2 id="6-management">6. Management</h2>
<h4 id="1-issue">1. Issue</h4>
<ul>
<li>문제</li>
<li>할 일(TODO)</li>
<li>관심사<h4 id="2-issue를-잘-사용하는-법">2. Issue를 잘 사용하는 법</h4>
</li>
<li>&#39;레이블&#39;을 달아서 시각적으로 만들기</li>
<li>&#39;template&#39; 사용하기(.github를 만들고, template 생성하면 됨)</li>
<li>&#39;Project(진행상황별로 기록)와 &#39;Milestone(기한을 맞추어서 작업해야 하는 것)&#39;사용</li>
</ul>
<h4 id="3-github-issue의-pros-and-consjira와-같은-다른-도구와-비교">3. GitHub Issue의 Pros and Cons(Jira와 같은 다른 도구와 비교)</h4>
<p>(1) 장점</p>
<ul>
<li>접근성이 높다.</li>
<li>도구의 파편화를 막을 수 있다.</li>
<li>Jira보다 빠르다.</li>
<li>누구나 볼 수 있다.(Jira는 초대된 팀 멤버만 볼 수 있음)</li>
</ul>
<p>(2) 단점</p>
<ul>
<li>Project와 Milestone 등이 아직 불편함.</li>
</ul>
<h2 id="7-collaboration협업">7. Collaboration(협업)</h2>
<h4 id="1-존중합시다">1. 존중합시다.</h4>
<h4 id="2-친절합시다">2. 친절합시다.</h4>
<h4 id="3-겸손합시다">3. 겸손합시다.</h4>
<h2 id="8-pull-request">8. Pull Request</h2>
<ul>
<li>코드를 통합하는 방법 중 하나</li>
<li>Git의 기능이 아닌, GitHub의 기능</li>
<li>코드 리뷰 수행 가능</li>
</ul>
<blockquote>
<p>이 글은 DND에서 제공된 &#39;GitHub로 협업하기&#39; 세미나를 듣고 정리한 내용입니다.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[AWS 사용자의 10가지 실수]]></title>
            <link>https://velog.io/@amenable-c/AWS-%EC%82%AC%EC%9A%A9%EC%9E%90%EC%9D%98-10%EA%B0%80%EC%A7%80-%EC%8B%A4%EC%88%98</link>
            <guid>https://velog.io/@amenable-c/AWS-%EC%82%AC%EC%9A%A9%EC%9E%90%EC%9D%98-10%EA%B0%80%EC%A7%80-%EC%8B%A4%EC%88%98</guid>
            <pubDate>Thu, 14 Jul 2022 06:03:03 GMT</pubDate>
            <description><![CDATA[<blockquote>
<ul>
<li><ol>
<li>클라우드를 공부하려고 AWS 가입부터 한다.</li>
</ol>
</li>
</ul>
</blockquote>
<ul>
<li><ol start="2">
<li>AWS 루트 계정에 아이디와 암호만으로 로그인한다.</li>
</ol>
</li>
<li><ol start="3">
<li>아무 블로그에 있는 실습에 따라 Github에 코드를 올린다</li>
</ol>
</li>
<li><ol start="4">
<li>복잡하고 돈이 드는 아키텍처를 먼저 공부한다.</li>
</ol>
</li>
<li><ol start="5">
<li>처음부터 복잡한 클라우드 아키텍처를 구현한다.</li>
</ol>
</li>
<li><ol start="6">
<li>매월 초가 되어서야 AWS 요금이 나온걸 알았다.</li>
</ol>
</li>
<li><ol start="7">
<li>혼자 AWS 문제를 해결을 해보려고 애쓴다.</li>
</ol>
</li>
<li><ol start="8">
<li>AWS 문제 해결을 위해 영어로 힘들게 이야기 하고 있다.</li>
</ol>
</li>
<li><ol start="9">
<li>서비스 개발 및 배포에만 클라우드를 쓰고 있다.</li>
</ol>
</li>
<li><ol start="10">
<li>클라우드 공부 방법과 경력 개발에 대해 혼자 고민하고 있다.</li>
</ol>
</li>
</ul>
<h2 id="1-클라우드를-공부하려고-aws-가입부터-한다">1. 클라우드를 공부하려고 AWS 가입부터 한다.</h2>
<p>$\to$ AWS 무료 교육 및 실습을 활용하세요.</p>
<ul>
<li>AWSOME DAY 참여하기</li>
<li>AWS Educate</li>
<li>Amazon SageMaker Studio Lab(이걸로 머신러닝 되는거 같음)</li>
</ul>
<h2 id="2-aws-루트-계정에-아이디와-암호만으로-로그인한다">2. AWS 루트 계정에 아이디와 암호만으로 로그인한다.</h2>
<p>$\to$ 멀티팩터인증(MFA)를 설정하세요</p>
<ul>
<li>MFA 추가하고, 로그인 할때마다 MFA를 추가적으로 인증하기</li>
</ul>
<h2 id="3-아무-블로그에-있는-실습에-따라-github에-코드를-올린다">3. 아무 블로그에 있는 실습에 따라 Github에 코드를 올린다</h2>
<p>$\to$ IAM USER로 사용 권한을 제한하세요.</p>
<ul>
<li>&#39;엑세스 키ID&#39;와 &#39;Seceret Key&#39;는 누구와도 공유하면 안됨 (특히 깃헙 같은 곳에 올리면 안됨)(해킹에 의해 과다 요금이 나오기도 함)</li>
<li>엑세스키가 꼭 필요하다면 루트 사용자 대신 IAM 사용자에 연결된 키를 사용하기</li>
</ul>
<h2 id="4-복잡하고-돈이-드는-아키텍처를-먼저-공부한다">4. 복잡하고 돈이 드는 아키텍처를 먼저 공부한다.</h2>
<p>$\to$ AWS 실습 가이드를 활용하자</p>
<ul>
<li>AWS 시작하기 페이지에 가면 단계별 자습서가 있음</li>
</ul>
<h2 id="5-처음부터-복잡한-클라우드-아키텍처를-구현한다">5. 처음부터 복잡한 클라우드 아키텍처를 구현한다.</h2>
<p>$\to$ Amazon LightSail을 이용하세요.</p>
<ul>
<li>&#39;천만 사용자를 위한 클라우드 아키텍처&#39; 강의가 매년 업데이트 되고 있으니깐 참고하기.</li>
<li>&#39;가상 서버, 애플리케이션 배포, 데이터베이스, 네트워킹, 스토리지 등 다양한 기능&#39;이 있는 것이 Amazon LightSail</li>
</ul>
<h2 id="6-매월-초가-되어서야-aws-요금이-나온걸-알았다">6. 매월 초가 되어서야 AWS 요금이 나온걸 알았다.</h2>
<p>$\to$ AWS Budget 알람을 설정하세요.</p>
<ul>
<li>과금 알람 설정하기</li>
<li>월별 예산을 설정하고 예산이 소비되는 %에 따라서 알람이 오게 할 수 있음.</li>
</ul>
<h2 id="7-혼자-aws-문제를-해결을-해보려고-애쓴다">7. 혼자 AWS 문제를 해결을 해보려고 애쓴다.</h2>
<p>$\to$ AWS Trusted Advisor를 활용하세요.</p>
<ul>
<li>축적된 모범 사례를 통해 어드바이저를 주는 것.</li>
<li>한달에 30달러 정도를 부과하면 24시간 AWS support enginer의 도움도 받을 수 있음</li>
</ul>
<h2 id="8-aws-문제-해결을-위해-영어로-힘들게-이야기-하고-있다">8. AWS 문제 해결을 위해 영어로 힘들게 이야기 하고 있다.</h2>
<p>$\to$ AWS 한국어 기술 지원을 활용하세요.</p>
<ul>
<li>티켓의 이름을 한국어로 지정하면 한국어 엔지니어에게 문제가 배치될 수 있음</li>
<li>또한, &#39;한국 사람에게 배치해주세요.&#39;라고 글을 남겨도 됨.</li>
</ul>
<h2 id="9-서비스-개발-및-배포에만-클라우드를-쓰고-있다">9. 서비스 개발 및 배포에만 클라우드를 쓰고 있다.</h2>
<p>$\to$ 국내 사업 지원 프로그램을 활용하세요.</p>
<ul>
<li>AWS Korea의 사람들과 연결 고리(AWS 문의하기로 요청하면 됨)</li>
<li>AWS Activate, AWS Smart Boost Up, AWS 파트너 프로그램, </li>
</ul>
<h2 id="10-클라우드-공부-방법과-경력-개발에-대해-혼자-고민하고-있다">10. 클라우드 공부 방법과 경력 개발에 대해 혼자 고민하고 있다.</h2>
<p>$\to$ AWS 커뮤니티에 참여하세요.</p>
<ul>
<li>AWS 한국 사용자 모임(AWSKRUG) 이용하기</li>
<li>페이스북(awkrug.org), slack(slack.awkrug.org), meetup(meetup.com/awskrug), 카카오톡(AWS의 모든것), 유튜브(youtube.com/awskrug) 이용</li>
</ul>
<p>*<em>AWS 디지털 교육 *</em>
: AWS Skill Builder 이용하기</p>
<blockquote>
<p>이 글은 &#39;AWS Builders Online Series&#39;의 &#39;AWS 사용자의 10가지 실수 - 이것만은 피하세요!&#39;에 참석하고 정리한 내용입니다.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[코딩테스트 필수로직]]></title>
            <link>https://velog.io/@amenable-c/%EC%BD%94%EB%94%A9%ED%85%8C%EC%8A%A4%ED%8A%B8-%ED%95%84%EC%88%98%EB%A1%9C%EC%A7%81</link>
            <guid>https://velog.io/@amenable-c/%EC%BD%94%EB%94%A9%ED%85%8C%EC%8A%A4%ED%8A%B8-%ED%95%84%EC%88%98%EB%A1%9C%EC%A7%81</guid>
            <pubDate>Mon, 11 Jul 2022 04:52:18 GMT</pubDate>
            <description><![CDATA[<blockquote>
<ul>
<li>lower_bound와 upper_bound</li>
</ul>
</blockquote>
<ul>
<li>시계방향과 반시계방향 회전</li>
<li>배열의 합(accumulate), 배열 중 가장 큰 요소(max_element), 배열 부분 회전</li>
<li>함수인자로 전달해서 변수 수정하기</li>
<li>n진법 변환</li>
<li>내림차순 정렬 &amp; 커스텀 정렬</li>
<li>2차원 배열을 회전하는 함수</li>
</ul>
<h2 id="1-lower_bound와-upper_bound">1. lower_bound와 upper_bound</h2>
<ul>
<li>정렬된 배열에서 어떤 값이 나오는 지점이나 어떤 값이 나오기 전의 위치를 반환하려고 할 때 사용</li>
<li>그림
(1) lower_bound : 0번째 배열의 원소부터 찾아서 어떠한 값의 &#39;이상이 되는 위치&#39;를 반환
(2) upper_bound : 그 값이 시작되기 전의 위치를 반환(뒤에서부터라고 생각) 
$\to$ 1, 2, 2, 3, 4에서 upper_bound(2)를 하면 3을 return
$\to$ 반환되는 값은 이터레이터이기 때문에 v.begin() 또는 a[0]을 빼주어서, int형으로 몇번째인지를 파악</li>
<li>찾고자 하는 수가 없는 경우
(1) &quot;1, 2, 3, 5&quot;에서 <code>lower_bound(a.begin(), a.end(), 4) - a.begin()</code>은 3을 반환(5를 가르키는 인덱스)
(2) &quot;2, 3, 4, 5, 7&quot;에서 범위의 양 끝단을 벗어나는 경우<pre><code>cout &lt;&lt; upper_bound(v.begin(), v.end(), 6) - v.begin() &lt;&lt; endl; // 4(7을 가르킴)
cout &lt;&lt; lower_bound(v.begin(), v.end(), 6) - v.begin() &lt;&lt; endl; // 4(7을 가르킴)
cout &lt;&lt; upper_bound(v.begin(), v.end(), 9) - v.begin() &lt;&lt; endl; // 5
cout &lt;&lt; lower_bound(v.begin(), v.end(), 9) - v.begin() &lt;&lt; endl; // 5
cout &lt;&lt; upper_bound(v.begin(), v.end(), 0) - v.begin() &lt;&lt; endl; // 0
cout &lt;&lt; lower_bound(v.begin(), v.end(), 0) - v.begin() &lt;&lt; endl; // 0</code></pre></li>
</ul>
<h2 id="2-시계방향과-반시계방향-회전">2. 시계방향과 반시계방향 회전</h2>
<ul>
<li>rotata(first, middle, last)</li>
<li>first와 last 사이에 있는 부분배열에서, middle이 가리키는 요소가 first로 가며 회전한다고 생각<pre><code>rotate(v.begin(), v.begin() + v.size() - 1, v.end()); // 시계 방향 
rotate(v.begin(), v.begin() + 1, v.end()); // 반시계 방향 </code></pre></li>
</ul>
<h2 id="3-배열의-합accumulate-배열-중-가장-큰-요소max_element-배열-부분-회전">3. 배열의 합(accumulate), 배열 중 가장 큰 요소(max_element), 배열 부분 회전</h2>
<ol>
<li>배열의 합(accumulate)
<code>accumulate(v.begin(), v.end(), 0);</code></li>
<li>배열 중 가장 큰 요소(max_element)
<code>max_element(v.begin(), v.end());</code></li>
<li>배열 부분 회전</li>
</ol>
<ul>
<li>아래 코드는 반시계방향으로 회전이고, 응용을 하면 시계방향으로도 가능<pre><code>int temp = v[i];
v[i] = v[i + 1];
v[i + 1] = v[i + 2];
v[i + 2] = v[i + 3];
v[i + 3] = temp;</code></pre></li>
</ul>
<h2 id="4-함수인자로-전달해서-변수-수정하기">4. 함수인자로 전달해서 변수 수정하기</h2>
<p>(1) <code>void ch1(int %a) a = 2;</code> $\to$ ch1(a)로 함수 호출
(2) <code>void ch2(int *a) *a = 3;</code> $\to$ ch1(&amp;a)로 함수 호출</p>
<h2 id="5-n진법-변환">5. n진법 변환</h2>
<pre><code>#include &lt;bits/stdc++.h&gt;
using namespace std;
vector&lt;int&gt; v;

int main(){
    int n = 100;
    int b = 2; // 바꿀 진법

    while(n &gt; 1){
        v.push_back(n % b);
        n /= b;
    }

    if(n==1) v.push_back(1);
    reverse(v.begin(), v.end());
    for(int a : v){
        if(a &gt;= 10)
            cout &lt;&lt; char(a + 55);
        else
            cout &lt;&lt; a;
    }

    return 0;
}</code></pre><h2 id="6-내림차순-정렬--커스텀-정렬">6. 내림차순 정렬 &amp; 커스텀 정렬</h2>
<pre><code>sort(v.begin(), v.end(), greater&lt;int&gt;());
sort(v.begin(), v.end(), greater&lt;pair&lt;int, int&gt;&gt;());

sort(v.begin(), v.end(), cmp);</code></pre><h2 id="7-2차원-배열을-회전하는-함수">7. 2차원 배열을 회전하는 함수</h2>
<pre><code>// 왼쪽으로 90도
void rotate90(vector&lt;vector&lt;int&gt;&gt; &amp;key){
    int m = key.size();
    vector&lt;vector&lt;int&gt;&gt; temp(m, vector&lt;int&gt;(m, 0));
    for(int i = 0; i &lt; m; i++){
        for(int j = 0; j &lt; m; j++){
            temp[i][j] = key[j][m - i - 1];
        }
    }
    key = temp;
    return;
}
// 오른쪽으로 90도
void rotate90(vector&lt;vector&lt;int&gt;&gt; &amp;key){
    int m = key.size();
    vector&lt;vector&lt;int&gt;&gt; temp(m, vector&lt;int&gt;(m, 0));
    for(int i = 0; i &lt; m; i++){
        for(int j = 0; j &lt; m; j++){
            temp[i][j] = key[m - j - 1][i];
        }
    }
    key = temp;
    return;
}
</code></pre><blockquote>
<p>이 글은 큰돌님의 &#39;10주완성 C++코딩테스트 | 알고리즘 IT취업&#39;을 수강하고 정리한 내용입니다.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[포인터 & 수학]]></title>
            <link>https://velog.io/@amenable-c/%ED%8F%AC%EC%9D%B8%ED%84%B0-%EC%88%98%ED%95%99</link>
            <guid>https://velog.io/@amenable-c/%ED%8F%AC%EC%9D%B8%ED%84%B0-%EC%88%98%ED%95%99</guid>
            <pubDate>Sun, 10 Jul 2022 13:05:57 GMT</pubDate>
            <description><![CDATA[<blockquote>
<ul>
<li>포인터</li>
</ul>
</blockquote>
<ul>
<li>수학</li>
</ul>
<h2 id="1-포인터">1. 포인터</h2>
<h4 id="1-포인터-1">1. 포인터</h4>
<ul>
<li><p>주소연산자 &amp; $\to$ <code>&amp;변수</code>로 사용 $\to$ 주소값 반환</p>
</li>
<li><p>참조 연산자 * $\to$ <code>*포인터의 이름</code>, <code>*주소</code>로 사용 $\to$ 포인터에 저장된 주소에 저장되어 있는 값을 반환</p>
</li>
<li><p>포인터를 이용하여 값을 꺼내는 방법 두 가지
(1) <code>(pointer_name)-&gt;(variable_name)</code>
(2) <code>(*pointer_name).variable_name</code></p>
</li>
</ul>
<h4 id="2-이터레이터와-포인터">2. 이터레이터와 포인터</h4>
<ul>
<li>이터레이터
(1) 컨테이너(배열 등)의 메모리 주소를 가리키는 데 사용되며 주소값을 바로 반환하지 않는 포인터의 일종(begin()과 end()를 많이 씀)
(2) 주소값을 바로 반환하지 않기 때문에 주소값을 출력하려면 &amp;*를 통해 출력해야 함<pre><code>cout &lt;&lt; v.begin() &lt;&lt; endl; // 에러
cout &lt;&lt; &amp;*(v.begin()) &lt;&lt; endl; // 주소값 출력</code></pre></li>
</ul>
<h4 id="3-call-by-reference--call-by-value">3. call by reference &amp; call by value</h4>
<ul>
<li>어떠한 값을 함수로 넘겨서 변하게 만들고 싶을 때는 주소값을 넘겨야 함</li>
<li>그저 값만 넘기면 안됨!</li>
</ul>
<h4 id="4-배열과-포인터">4. 배열과 포인터</h4>
<ul>
<li>배열의 이름은 배열의 주소값의 첫 번째 시작 주소를 가르킨다.</li>
</ul>
<h2 id="2-수학">2. 수학</h2>
<h4 id="1-순열과-조합">1. 순열과 조합</h4>
<ol>
<li>순열(permutation)</li>
</ol>
<ul>
<li>순서가 정해진 임의의 집합을 다른 순서로 섞는 연산</li>
</ul>
<ol start="2">
<li>조합(combination)</li>
</ol>
<ul>
<li>순서가 없음</li>
<li>몇 명을 뽑아서 갈 것인가를 쓸 때 사용</li>
</ul>
<h4 id="2-정수론">2. 정수론</h4>
<ol>
<li><p>최대공약수(gcd)와 최소공배수(lcm)</p>
<pre><code>int gcd(int a, int b){
 if(a == 0)
     return b;

 return gcd(b % a, a);
}
</code></pre></li>
</ol>
<p>int lcm(int a, int b){
    return (a*b) / gcd(a, b);
}</p>
<p>```</p>
<ol start="2">
<li><p>모듈러 연산
(1)  a ≡ b mod n과 b ≡ c mod n 은 a ≡ c mod n 을 의미
(2) [(a mod n)+(b mod n)] mod n = (a+b) mod n
(3) [(a mod n)-(b mod n)] mod n = (a-b) mod n
(4) [(a mod n)<em>(b mod n)] mod n = (a</em>b) mod n</p>
</li>
<li><p>에라토스테네스의 채</p>
</li>
</ol>
<ul>
<li>소수가 아닌 값들에 대한 불리언 배열을 만들어 소수만을 걸러낼 수 있는 방법</li>
</ul>
<ol start="4">
<li>등차수열의 합</li>
</ol>
<ul>
<li>등차수열의 합 = n(n+1) / 2</li>
</ul>
<blockquote>
<p>이 글은 큰돌님의 &#39;10주완성 C++코딩테스트 | 알고리즘 IT취업&#39;을 수강하고 정리한 내용입니다.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[날짜 & 시간 필터링 구현]]></title>
            <link>https://velog.io/@amenable-c/%EB%82%A0%EC%A7%9C-%EC%8B%9C%EA%B0%84-%ED%95%84%ED%84%B0%EB%A7%81-%EA%B5%AC%ED%98%84</link>
            <guid>https://velog.io/@amenable-c/%EB%82%A0%EC%A7%9C-%EC%8B%9C%EA%B0%84-%ED%95%84%ED%84%B0%EB%A7%81-%EA%B5%AC%ED%98%84</guid>
            <pubDate>Sun, 10 Jul 2022 06:09:27 GMT</pubDate>
            <description><![CDATA[<blockquote>
<ul>
<li><ol>
<li>JpaRepository</li>
</ol>
</li>
</ul>
</blockquote>
<ul>
<li><ol start="2">
<li>다중 필터링</li>
</ol>
</li>
<li><ol start="3">
<li>주의 사항</li>
</ol>
</li>
</ul>
<h2 id="1-jparepository">1. JpaRepository</h2>
<ul>
<li>JpaRepository만 잘 사용해도 기본적인 필터링 기능을 구현할 수 있을 것이라고 생각한다.<h4 id="1-jparepository-정의-및-설명">1. JpaRepository 정의 및 설명</h4>
(1) Spring Data JPA에서 제공하는 인터페이스
(2) 인터페이스에 따로 @Repository등의 어노테이션을 추가할 필요가 없다.</li>
</ul>
<h4 id="2-사용법">2. 사용법</h4>
<p>JpaRepository를 상속받을 때는 사용될 Entity 클래스와 ID값이 들어가게 된다.
<code>public interface ItemRepository extends JpaRepository&lt;Item, Long&gt;</code></p>
<h4 id="3-기본-기능단순히-상속하는-것만으로도-아래-기능-제공">3. 기본 기능(단순히 상속하는 것만으로도 아래 기능 제공)</h4>
<p>(1) save()
(2) findOne()
(3) findAll()
(4) count()
(5) delete()</p>
<h4 id="4-query-메소드-추가">4. Query 메소드 추가</h4>
<p>$\to$ 규칙에 맞는 메서드를 작성해야 한다.
(1) findBy로 시작 =&gt; 쿼리를 요청하는 메서드
(2) countBy로 시작 =&gt; 쿼리 결과 레코드 수를 요청하는 메서드
(3) 실제 사용</p>
<pre><code>    List&lt;Item&gt; findByDateBetween(LocalDate start, LocalDate end); // start 시간부터 end시간까지
    List&lt;Item&gt; findByPriceBetween(Long min, Long max); // min 가격부터 max 가격까지</code></pre><h2 id="2-다중-필터링">2. 다중 필터링</h2>
<ul>
<li>And와 Or을 사용하여 다중 필터링을 구현할 수 있다.
<code>List&lt;Item&gt; findByDateBetweenAndPriceBetween(LocalDate start, LocalDate end, Long min, Long max);</code>
<code>List&lt;Item&gt; findByDateBetweenOrPriceBetween(LocalDate start, LocalDate end, Long min, Long max);</code></li>
</ul>
<h2 id="3-주의-사항">3. 주의 사항</h2>
<ul>
<li>API를 통하여 start와 end 같은 시간을 가져올 때, <code>@DateTimeFormat(iso = DateTimeFormat.ISO.DATE)</code> 등의 방식을 추가해야지 시간으로 입력이 받아짐.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/amenable-c/post/e2e39ed9-087f-4da8-8565-d4bca1a25dc4/image.png" alt=""></p>
]]></description>
        </item>
    </channel>
</rss>