<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>코알못</title>
    <link>https://co-de.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Tue, 28 Jul 2026 19:42:17 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>코린이s</managingEditor>
    <image>
      <title>코알못</title>
      <url>https://tistory1.daumcdn.net/tistory/3236221/attach/bf49ba79393942debbf42474bf0c47d0</url>
      <link>https://co-de.tistory.com</link>
    </image>
    <item>
      <title>[문자인코딩] 02) 문자 인코딩/디코딩 실습</title>
      <link>https://co-de.tistory.com/262</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;512&quot; data-origin-height=&quot;512&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cKbCqC/dJMcaadwa1A/u9E6ah6QFihpV8WYGO2V90/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cKbCqC/dJMcaadwa1A/u9E6ah6QFihpV8WYGO2V90/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cKbCqC/dJMcaadwa1A/u9E6ah6QFihpV8WYGO2V90/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcKbCqC%2FdJMcaadwa1A%2Fu9E6ah6QFihpV8WYGO2V90%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;300&quot; height=&quot;300&quot; data-origin-width=&quot;512&quot; data-origin-height=&quot;512&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 실습에 앞서 프로젝트를 생성해보자!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 화면과 같이 자바 프로젝트를 생성하며 자바 21버전을 사용하도록 한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1598&quot; data-origin-height=&quot;1430&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qNQUI/dJMcahKtdE5/8Vg5Qc0p2mp8D25iI136K1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qNQUI/dJMcahKtdE5/8Vg5Qc0p2mp8D25iI136K1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qNQUI/dJMcahKtdE5/8Vg5Qc0p2mp8D25iI136K1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqNQUI%2FdJMcahKtdE5%2F8Vg5Qc0p2mp8D25iI136K1%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;500&quot; height=&quot;447&quot; data-origin-width=&quot;1598&quot; data-origin-height=&quot;1430&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;프로젝트 생성시 Add sample code 에 체크박스 했기 때문에&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;아래와 같이 예제 코드가 들어있다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;메인을 실행하여 동작 여부를 확인해보자!&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1324&quot; data-origin-height=&quot;710&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/2dbw2/dJMcach4542/U0yhtd0lrJHqaFBk97dLbk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/2dbw2/dJMcach4542/U0yhtd0lrJHqaFBk97dLbk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/2dbw2/dJMcach4542/U0yhtd0lrJHqaFBk97dLbk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F2dbw2%2FdJMcach4542%2FU0yhtd0lrJHqaFBk97dLbk%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;500&quot; height=&quot;268&quot; data-origin-width=&quot;1324&quot; data-origin-height=&quot;710&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;결과를 보면 정상적으로 출력 되는것을 볼 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;644&quot; data-origin-height=&quot;398&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bmVlAt/dJMcadnIhwf/2EkKGUWpea7G3P2BS39z00/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bmVlAt/dJMcadnIhwf/2EkKGUWpea7G3P2BS39z00/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bmVlAt/dJMcadnIhwf/2EkKGUWpea7G3P2BS39z00/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbmVlAt%2FdJMcadnIhwf%2F2EkKGUWpea7G3P2BS39z00%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;300&quot; height=&quot;185&quot; data-origin-width=&quot;644&quot; data-origin-height=&quot;398&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 메인 클래스에 아래와 같이 코드를 작성해보자!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 코드는 현재 이용 가능한 모든 문자 집합을 조회하는 코드이다.&lt;/p&gt;
&lt;pre id=&quot;code_1773747395951&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 이용 가능한 모든 Charset 자바 + OS
SortedMap&amp;lt;String,Charset&amp;gt; charsets = Charset.availableCharsets();
for (String charsetName : charsets.keySet()) {
	System.out.println(&quot;charsetName = &quot; + charsetName);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메인을 실행하여 확인해보면 정말 많은 문자 집합이 나오는것을 볼 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문자 집합을 사용하고 싶을경우 이와 같이 확인하여 지원 하는지 확인해 볼 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;620&quot; data-origin-height=&quot;570&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/0Ker0/dJMcaaYRzqk/Zg3rppUcOlzljaIjQqQAKK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/0Ker0/dJMcaaYRzqk/Zg3rppUcOlzljaIjQqQAKK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/0Ker0/dJMcaaYRzqk/Zg3rppUcOlzljaIjQqQAKK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F0Ker0%2FdJMcaaYRzqk%2FZg3rppUcOlzljaIjQqQAKK%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;300&quot; height=&quot;276&quot; data-origin-width=&quot;620&quot; data-origin-height=&quot;570&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음으로 MS949 문자 집합을 조회해보자!&lt;/p&gt;
&lt;div style=&quot;background-color: #1e1f22; color: #bcbec4;&quot;&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;// 문자로 조회
Charset charset = Charset.forName(&quot;MS949&quot;);
System.out.println(&quot;charset = &quot; + charset);&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지원하는 항목에 있었기 때문에 아래와 같이 정상 출력 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러나 ms949 가 아닌 처음 보는 명칭이 나왔다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;출력된 명칭이 본 명칭이며 ms949는 별칭이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리가 forName 에 별칭을 대소문자 구분 없이 입력하면 해당하는 문자 집합을 가져올 수 있다!&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;482&quot; data-origin-height=&quot;142&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cBlXo7/dJMcafZ97h7/D3u7kySrsk1LoRvekMKZI0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cBlXo7/dJMcafZ97h7/D3u7kySrsk1LoRvekMKZI0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cBlXo7/dJMcafZ97h7/D3u7kySrsk1LoRvekMKZI0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcBlXo7%2FdJMcafZ97h7%2FD3u7kySrsk1LoRvekMKZI0%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;300&quot; height=&quot;88&quot; data-origin-width=&quot;482&quot; data-origin-height=&quot;142&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 입력 가능한 별칭은 무엇이 있을까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래와 같이 해당 하는 문자 집합의 별칭을 조회 해 볼 수 있다.&lt;/p&gt;
&lt;div style=&quot;background-color: #1e1f22; color: #bcbec4;&quot;&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;// 별칭 조회
Charset charset = Charset.forName(&quot;MS949&quot;);
Set&amp;lt;String&amp;gt; aliases = charset.aliases();
for (String alias : aliases) {
    System.out.println(&quot;alias = &quot; + alias);
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결과를 보면 우리가 사용한 ms949 별칭을 포함하여 다른 별칭도 확인 할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;456&quot; data-origin-height=&quot;268&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/KL1y5/dJMcab4xIy2/QlC040nHROBaukAVTPo3D0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/KL1y5/dJMcab4xIy2/QlC040nHROBaukAVTPo3D0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/KL1y5/dJMcab4xIy2/QlC040nHROBaukAVTPo3D0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FKL1y5%2FdJMcab4xIy2%2FQlC040nHROBaukAVTPo3D0%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;300&quot; height=&quot;176&quot; data-origin-width=&quot;456&quot; data-origin-height=&quot;268&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Charset.forName 으로 별칭을 입력하여 문자 집합을 가져 올 수 있지만&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;UTF-8 의 경우 아래와 같이 SrandardCharsets 으로 제공하는 상수를 사용하여 문자 집합을 바로 가져올 수 있다.&lt;/p&gt;
&lt;div style=&quot;background-color: #1e1f22; color: #bcbec4;&quot;&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;// 자주 사용하는 문자집합은 상수로 제공
Charset charset2 = StandardCharsets.UTF_8;
System.out.println(&quot;charset2 = &quot; + charset2);&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;출력을 보면 정상적으로 가져온것을 알 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;436&quot; data-origin-height=&quot;130&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b92Eks/dJMcagLzIxX/xW7cfrJtHKtH4MJRvcTimK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b92Eks/dJMcagLzIxX/xW7cfrJtHKtH4MJRvcTimK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b92Eks/dJMcagLzIxX/xW7cfrJtHKtH4MJRvcTimK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb92Eks%2FdJMcagLzIxX%2FxW7cfrJtHKtH4MJRvcTimK%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;300&quot; height=&quot;89&quot; data-origin-width=&quot;436&quot; data-origin-height=&quot;130&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 우리 시스템인 OS 에 설정된 문자 집합을 조회해보자!&lt;/p&gt;
&lt;div style=&quot;background-color: #1e1f22; color: #bcbec4;&quot;&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;// 시스템의 기본 Charset 조회
Charset charset3 = Charset.defaultCharset();
System.out.println(&quot;charset3 = &quot; + charset3);&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저자의 경우 UTF-8 로 설정 되어있는것을 볼 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자 PC 마다 설정 값이 다르므로 저자와 출력은 다를 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;436&quot; data-origin-height=&quot;126&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/DbPiR/dJMcaadv9in/30Zp9SpomcC5hv9BsD0DJ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/DbPiR/dJMcaadv9in/30Zp9SpomcC5hv9BsD0DJ1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/DbPiR/dJMcaadv9in/30Zp9SpomcC5hv9BsD0DJ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDbPiR%2FdJMcaadv9in%2F30Zp9SpomcC5hv9BsD0DJ1%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;300&quot; height=&quot;87&quot; data-origin-width=&quot;436&quot; data-origin-height=&quot;126&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&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;그리고 encoding 메서드를 만들어 인코딩 되는 값을 출력, 몇바이트를 사용했는지 출력되도록 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;String.getByte 에 문자 집합을 변수로 넣으면 해당 문자집합으로 인코딩 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 main 함수에서 A 와 a 가 ASCII 인코딩 했을시 출력이 어떻게 되는지 확인해보자!&lt;/p&gt;
&lt;div style=&quot;background-color: #1e1f22; color: #bcbec4;&quot;&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;private static final Charset EUC_KR = Charset.forName(&quot;EUC-KR&quot;);
private static final Charset MS_949 = Charset.forName(&quot;MS949&quot;);
public static final Charset US_ASCII = StandardCharsets.US_ASCII;

public static void main(String[] args) {
    System.out.println(&quot;== ASCII 영문 처리 ==&quot;);
    encoding(&quot;A&quot;, US_ASCII);
    encoding(&quot;a&quot;, US_ASCII);
}

private static void encoding(String text, Charset charset) {
    byte[] bytes = text.getBytes(charset);
    System.out.printf(&quot;%s -&amp;gt; [%s] 인코딩 -&amp;gt; %s %sbyte\n&quot;, text, charset, Arrays.toString(bytes), bytes.length);
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;main 을 돌려보면 아래와 같이 나온다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;A 의 경우 ASCII 로 인코딩시 65 이며 1byte를 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;a 의 경우 97이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저번 시간에 배운대로 정상적으로 인코딩 되어 출력 되었다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;628&quot; data-origin-height=&quot;166&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/WW5TI/dJMcahjqBup/jK14n3DKHxAhQt8HUHmEa0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/WW5TI/dJMcahjqBup/jK14n3DKHxAhQt8HUHmEa0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/WW5TI/dJMcahjqBup/jK14n3DKHxAhQt8HUHmEa0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FWW5TI%2FdJMcahjqBup%2FjK14n3DKHxAhQt8HUHmEa0%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;300&quot; height=&quot;79&quot; data-origin-width=&quot;628&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;이제 동일한 A 문자를 가지고 여러 문자 집합별 결과가 어떻게 나오는지 확인해보자!&lt;/p&gt;
&lt;div style=&quot;background-color: #1e1f22; color: #bcbec4;&quot;&gt;
&lt;pre class=&quot;processing&quot;&gt;&lt;code&gt;public static final Charset UTF_8 = StandardCharsets.UTF_8;
private static final Charset EUC_KR = Charset.forName(&quot;EUC-KR&quot;);
private static final Charset MS_949 = Charset.forName(&quot;MS949&quot;);
public static final Charset US_ASCII = StandardCharsets.US_ASCII;
public static final Charset ISO_88591 = StandardCharsets.ISO_8859_1;
public static final Charset UTF_16BE = Charset.forName(&quot;UTF-16BE&quot;);

public static void main(String[] args) {
    System.out.println(&quot;== ASCII 영문 처리 ==&quot;);
    encoding(&quot;A&quot;, US_ASCII);
    encoding(&quot;A&quot;, ISO_88591);
    encoding(&quot;A&quot;, EUC_KR);
    encoding(&quot;A&quot;, UTF_8);
    encoding(&quot;A&quot;, UTF_16BE);
}

private static void encoding(String text, Charset charset) {
    byte[] bytes = text.getBytes(charset);
    System.out.printf(&quot;%s -&amp;gt; [%s] 인코딩 -&amp;gt; %s %sbyte\n&quot;, text, charset, Arrays.toString(bytes), bytes.length);
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결과를 확인해보면..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;영문은 US-ASCII, ISO-8859-1, EUC-KR, MS949, UTF-8 모두 ASCII 와 호환된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 문자 집합들은 1byte 만 사용하고 숫자 65로 인코딩 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러나 UTF-16의 경우 ASCII 와 호환되지 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 이유는 결과를 보면 2byte 를 사용하고 숫자 0, 65 로 인코딩 되어 이전 인코딩과는 다른값으로 인코딩 되기 때문이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;666&quot; data-origin-height=&quot;278&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eWVbF3/dJMcaivNRB5/nbUkimKcoxFMayQ4QQQ8a1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eWVbF3/dJMcaivNRB5/nbUkimKcoxFMayQ4QQQ8a1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eWVbF3/dJMcaivNRB5/nbUkimKcoxFMayQ4QQQ8a1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeWVbF3%2FdJMcaivNRB5%2FnbUkimKcoxFMayQ4QQQ8a1%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;300&quot; height=&quot;125&quot; data-origin-width=&quot;666&quot; data-origin-height=&quot;278&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 한글 인코딩을 테스트 해보자!&lt;/p&gt;
&lt;div style=&quot;background-color: #1e1f22; color: #bcbec4;&quot;&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;public static final Charset UTF_8 = StandardCharsets.UTF_8;
private static final Charset EUC_KR = Charset.forName(&quot;EUC-KR&quot;);
private static final Charset MS_949 = Charset.forName(&quot;MS949&quot;);
public static final Charset US_ASCII = StandardCharsets.US_ASCII;
public static final Charset ISO_88591 = StandardCharsets.ISO_8859_1;
public static final Charset UTF_16BE = Charset.forName(&quot;UTF-16BE&quot;);

public static void main(String[] args) {
    System.out.println(&quot;== 한글 지원 ==&quot;);
    encoding(&quot;가&quot;, EUC_KR);
    encoding(&quot;가&quot;, MS_949);
    encoding(&quot;가&quot;, UTF_8);
    encoding(&quot;가&quot;, UTF_16BE); // UTF-16 문자 집합 표기법중 BE, LE 가 있는데 의미하는 바는 인코딩 숫자 표기 되는 순서일뿐 두개는 같다.
}

private static void encoding(String text, Charset charset) {
        byte[] bytes = text.getBytes(charset);
        System.out.printf(&quot;%s -&amp;gt; [%s] 인코딩 -&amp;gt; %s %sbyte\n&quot;, text, charset, Arrays.toString(bytes), bytes.length);
    }&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한글의 경우&amp;nbsp; EUC-KR, MS949 는 동일하게 2byte 를 사용하며 인코딩 된 값도 동일하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러므로 서로 호환 되는것을 알 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저번 시간에 MS949 는 EUC-KR 확장 버전이라고 배웠으며 그렇기 때문에 결과도 동일 하게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러나 UTF-8 의 경우 한글 인코딩은 3byte 를 사용하므로 다르게 인코딩 된것을 볼 수 있으며&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;UTF-16 의 경우에는 2byte 를 사용하나 인코딩 된 값이 다르므로 호환 되지 않는다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;780&quot; data-origin-height=&quot;246&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b5glhE/dJMcag5RTCa/rm0kcnoRGZqK8eBbQGGKX0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b5glhE/dJMcag5RTCa/rm0kcnoRGZqK8eBbQGGKX0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b5glhE/dJMcag5RTCa/rm0kcnoRGZqK8eBbQGGKX0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb5glhE%2FdJMcag5RTCa%2Frm0kcnoRGZqK8eBbQGGKX0%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;350&quot; height=&quot;110&quot; data-origin-width=&quot;780&quot; data-origin-height=&quot;246&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;문자를 byte 로 변경하려면 무조건 문자 집합이 필요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 String.getByte() 인자로 Charset 문자집합을 넘겨줘야 한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;넘겨주지 않을시 시스템 기본 문자집합을 인코딩에 사용한다는 점을 알 고 있어야 한다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 인코딩 &amp;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;test 메서드에서 String.getByte(문자집합) 을 통해 해당 문자집합으로 인코딩 하며&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;new String(인코딩 byte, 문자집합) 을 통해 해당 문자 집합으로 디코딩 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인코딩, 디코딩 할때는 반드시 문자집합을 지정해줘야 하며 지정 안할 시 시스템 default 설정을 따르게 되므로&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실무에서는 시스템 마다 결과가 달라지지 않도록 지정 해주도록 하자!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 main 함수에서 'A' 를 ASCII 로 인코딩 하고 다른 문자 집합으로 디코딩 했을때 결과를 보도록 하자!&lt;/p&gt;
&lt;div style=&quot;background-color: #1e1f22; color: #bcbec4;&quot;&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;public static final Charset ISO_88591 = StandardCharsets.ISO_8859_1;
public static final Charset UTF_8 = StandardCharsets.UTF_8;
private static final Charset EUC_KR = Charset.forName(&quot;EUC-KR&quot;);
private static final Charset MS_949 = Charset.forName(&quot;MS949&quot;);
public static final Charset US_ASCII = StandardCharsets.US_ASCII;
public static final Charset UTF_16_BE = StandardCharsets.UTF_16BE;

public static void main(String[] args) {
    System.out.println(&quot;== 영문 ASCII 인코딩 ==&quot;);
    test(&quot;A&quot;, US_ASCII, US_ASCII);
    test(&quot;A&quot;, US_ASCII, ISO_88591);
    test(&quot;A&quot;, US_ASCII, EUC_KR);
    test(&quot;A&quot;, US_ASCII, MS_949);
    test(&quot;A&quot;, US_ASCII, UTF_8);
    test(&quot;A&quot;, US_ASCII, UTF_16_BE);
}

private static void test(String text, Charset encodingCharset, Charset decodingCharset) {
    byte[] encoded = text.getBytes(encodingCharset);
    String decoded = new String(encoded, decodingCharset);
    System.out.printf(&quot;%s -&amp;gt; [%s] 인코딩 -&amp;gt; %s %sbyte -&amp;gt; [%s] 디코딩 -&amp;gt; %s\n&quot;, text, encodingCharset, Arrays.toString(encoded), encoded.length, decodingCharset, decoded);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결과를 보면 UTF-16 빼고는 모두 ASCII 를 호환 하기 때문에 정상적으로 나오며&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;UTF-16은 지원하지 않기 때문에 '?' 로 나오는것을 볼 수있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1076&quot; data-origin-height=&quot;324&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/CJOda/dJMcaaq2Y6E/qAum6yKYUSz98CiDNnHTRK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/CJOda/dJMcaaq2Y6E/qAum6yKYUSz98CiDNnHTRK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/CJOda/dJMcaaq2Y6E/qAum6yKYUSz98CiDNnHTRK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCJOda%2FdJMcaaq2Y6E%2FqAum6yKYUSz98CiDNnHTRK%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;400&quot; height=&quot;120&quot; data-origin-width=&quot;1076&quot; data-origin-height=&quot;324&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 한글 인코딩 테스트 해보도록 하자!&lt;/p&gt;
&lt;div style=&quot;background-color: #1e1f22; color: #bcbec4;&quot;&gt;
&lt;pre class=&quot;less&quot;&gt;&lt;code&gt;System.out.println(&quot;== 한글 인코딩 ==&quot;);
test(&quot;가&quot;, US_ASCII, US_ASCII);
test(&quot;가&quot;, ISO_88591, ISO_88591);
test(&quot;가&quot;, EUC_KR, EUC_KR);
test(&quot;가&quot;, MS_949, MS_949);
test(&quot;가&quot;, UTF_8, UTF_8);
test(&quot;가&quot;, UTF_16_BE, UTF_16_BE);&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ASCII , ISO-8859의 경우에는 한글 지원 하지 않기 때문에 ? 로 나왔으며&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나머지는 한글 지원하므로 정상적으로 인코딩, 디코딩이 되는것을 볼 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1240&quot; data-origin-height=&quot;316&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mgZcT/dJMcacbjRy5/xmpg149dCMF2G0a8rdoxFK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mgZcT/dJMcacbjRy5/xmpg149dCMF2G0a8rdoxFK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mgZcT/dJMcacbjRy5/xmpg149dCMF2G0a8rdoxFK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmgZcT%2FdJMcacbjRy5%2Fxmpg149dCMF2G0a8rdoxFK%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;450&quot; height=&quot;115&quot; data-origin-width=&quot;1240&quot; data-origin-height=&quot;316&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 복잡한 한글인 '뷁'을 인코딩 해보자!&lt;/p&gt;
&lt;div style=&quot;background-color: #1e1f22; color: #bcbec4;&quot;&gt;
&lt;pre class=&quot;less&quot;&gt;&lt;code&gt;System.out.println(&quot;== 한글 인코딩 - 복잡한 문자 ==&quot;);
test(&quot;뷁&quot;, EUC_KR, EUC_KR);
test(&quot;뷁&quot;, MS_949, MS_949);
test(&quot;뷁&quot;, UTF_8, UTF_8);
test(&quot;뷁&quot;, UTF_16_BE, UTF_16_BE);&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저번 시간에 배운 내용과 같이 EUC-KR 은 자주사용하는 한글만 표기 되도록 집합이 구성되어있어 '뷁'은 문자 집합에 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 ? 로 나오는것을 볼 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 EUC-KR 의 확장 버전인 MS-949와 그 뒤에 나온 UTF-8, 16 모두 정상적으로 인코딩, 디코딩 되는것을 볼 수있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1272&quot; data-origin-height=&quot;234&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/1MbNG/dJMcahjqCIW/ceNkbe9zGK2HvtItoMYVlK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/1MbNG/dJMcahjqCIW/ceNkbe9zGK2HvtItoMYVlK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/1MbNG/dJMcahjqCIW/ceNkbe9zGK2HvtItoMYVlK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F1MbNG%2FdJMcahjqCIW%2FceNkbe9zGK2HvtItoMYVlK%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;470&quot; height=&quot;86&quot; data-origin-width=&quot;1272&quot; data-origin-height=&quot;234&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 한글 인코딩과 디코딩이 다른경우를 보자!&lt;/p&gt;
&lt;div style=&quot;background-color: #1e1f22; color: #bcbec4;&quot;&gt;
&lt;pre class=&quot;less&quot;&gt;&lt;code&gt;System.out.println(&quot;== 한글 인코딩 - 디코딩이 다른경우 ==&quot;);
test(&quot;가&quot;, EUC_KR, MS_949);
test(&quot;뷁&quot;, MS_949, EUC_KR);
test(&quot;가&quot;, MS_949, UTF_8);
test(&quot;가&quot;, UTF_8, MS_949);&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결과를 보면..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;'가' 의 경우 EUC-KR, MS949 모두 지원하므로 정상 인코딩, 디코딩 되어 출력 된것을 볼 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러나 '뷁' 의 경우 EUC_KR 에서 지원하지 않기 떄문에 인코딩은 정상적으로 됐을지라도 디코딩에서 실패하여 '?' 로 노출된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 MS949 와 UTF-8 은 한글 인코딩 되는 byte 수 부터 다르기 때문에 ? 로 나오게 된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1240&quot; data-origin-height=&quot;232&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uioaC/dJMcah4L7gQ/xdeJdFFkGOh8gjnWrf0hXk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uioaC/dJMcah4L7gQ/xdeJdFFkGOh8gjnWrf0hXk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uioaC/dJMcah4L7gQ/xdeJdFFkGOh8gjnWrf0hXk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuioaC%2FdJMcah4L7gQ%2FxdeJdFFkGOh8gjnWrf0hXk%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;480&quot; height=&quot;90&quot; data-origin-width=&quot;1240&quot; data-origin-height=&quot;232&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;영문의 경우에도 보자!&lt;/p&gt;
&lt;div style=&quot;background-color: #1e1f22; color: #bcbec4;&quot;&gt;
&lt;pre class=&quot;less&quot;&gt;&lt;code&gt;System.out.println(&quot;== 영문 인코딩 - 디코딩이 다른경우 ==&quot;);
test(&quot;A&quot;, EUC_KR, UTF_8);
test(&quot;A&quot;, MS_949, UTF_8);
test(&quot;A&quot;, UTF_8, MS_949);
test(&quot;A&quot;, UTF_8, UTF_16_BE);&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;영문의 경우 모두 1byte 로 인코딩 되며 모두 호환 되지만, UTF-16 의 경우 2byte 로 인코딩 값이 다르다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러므로 UTF-16 으로 디코딩 한 부분만 ? 로 나오는것을 볼 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1020&quot; data-origin-height=&quot;234&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/baYRla/dJMcabKhop0/1dvyPSrEodv2iXRPXAKBm1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/baYRla/dJMcabKhop0/1dvyPSrEodv2iXRPXAKBm1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/baYRla/dJMcabKhop0/1dvyPSrEodv2iXRPXAKBm1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbaYRla%2FdJMcabKhop0%2F1dvyPSrEodv2iXRPXAKBm1%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;480&quot; height=&quot;110&quot; data-origin-width=&quot;1020&quot; data-origin-height=&quot;234&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 총 정리 해보자!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;영문&lt;/b&gt;&lt;/span&gt;은 &lt;b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;대부분 모두 호환&lt;/span&gt;&lt;/b&gt; 되나 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;UTF-16 은 호환 되지 않아&lt;/b&gt;&lt;/span&gt; 인코딩/디코딩시 오류 발생 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;한글의&lt;/span&gt;&lt;/b&gt; 경우 &lt;b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;EUC-KR 과 MS949 는 호환&lt;/span&gt;&lt;/b&gt; 되나&lt;u&gt; '뷁' 같이 자주 사용하지 않는 한글은 EUC-KR 에서&lt;/u&gt;는 문자 집합이 없기에 &lt;u&gt;오류 발생&lt;/u&gt;할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;그 외 한글 인코딩/디코딩&lt;/span&gt;&lt;/b&gt;을 다른 문자 집합으로 할때 서로 호환 되지 않아 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;오류 발생&lt;/b&gt;&lt;/span&gt; 할 수 있다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;# 참고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1) byte 출력에 - 가 나오는 이유는 ?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1byte 는 8bit 로 256 가지 표현된다. 그러나 자바에서 byte 는 양수, 음수 모두 표현 가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러므로 십진수로 표기 할때 256 가지 이지만 -128 ~ 127 로 표기 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메모리에 이진수로 저장되는 값은 같으나 화면에 십진수에 표기 되는거만 다른것 뿐이다.&lt;/p&gt;</description>
      <category>JAVA</category>
      <author>코린이s</author>
      <guid isPermaLink="true">https://co-de.tistory.com/262</guid>
      <comments>https://co-de.tistory.com/262#entry262comment</comments>
      <pubDate>Tue, 17 Mar 2026 22:07:52 +0900</pubDate>
    </item>
    <item>
      <title>[문자인코딩] 01) 문자 인코딩이란?</title>
      <link>https://co-de.tistory.com/261</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;512&quot; data-origin-height=&quot;512&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c8LcOv/dJMcadgYXvp/fOjZbl48unaNJKDsvlABp0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c8LcOv/dJMcadgYXvp/fOjZbl48unaNJKDsvlABp0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c8LcOv/dJMcadgYXvp/fOjZbl48unaNJKDsvlABp0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc8LcOv%2FdJMcadgYXvp%2FfOjZbl48unaNJKDsvlABp0%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;350&quot; height=&quot;350&quot; data-origin-width=&quot;512&quot; data-origin-height=&quot;512&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-end=&quot;158&quot; data-start=&quot;110&quot; data-section-id=&quot;17atakv&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;우리는 컴퓨터를 사용하면서 이런 의문을 가진다..&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;158&quot; data-start=&quot;110&quot; data-section-id=&quot;17atakv&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;컴퓨터는 &lt;/span&gt;&lt;span&gt;문자를 &lt;/span&gt;&lt;span&gt;어떻게 &lt;/span&gt;&lt;span&gt;저장할까?&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;220&quot; data-start=&quot;160&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;컴퓨터는 &lt;/span&gt;&lt;span&gt;우리가 &lt;/span&gt;&lt;span&gt;보는 &lt;/span&gt;&lt;span&gt;글자 &lt;/span&gt;&lt;span&gt;그대로를 &lt;/span&gt;&lt;span&gt;저장하지 &lt;/span&gt;&lt;span&gt;않는다.&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;&lt;span&gt;모든 &lt;/span&gt;&lt;span&gt;정보를 &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;과 &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;로만 &lt;/span&gt;&lt;span&gt;처리한다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-end=&quot;311&quot; data-start=&quot;222&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;그 이유는 &lt;/span&gt;&lt;span&gt;컴퓨터의 &lt;/span&gt;&lt;span&gt;메모리는 &lt;/span&gt;&lt;b&gt;&lt;span&gt;반도체&lt;/span&gt;&lt;/b&gt;&lt;span&gt;로 &lt;/span&gt;&lt;span&gt;만들어져 &lt;/span&gt;&lt;span&gt;있고&lt;/span&gt;&lt;br /&gt;&lt;span&gt;전기가 &lt;/span&gt;&lt;b&gt;&lt;span&gt;흐르냐(&lt;/span&gt;&lt;span&gt;1)&lt;/span&gt;&lt;/b&gt;&lt;span&gt; / &lt;/span&gt;&lt;b&gt;&lt;span&gt;안 &lt;/span&gt;&lt;span&gt;흐르냐(&lt;/span&gt;&lt;span&gt;0)&lt;/span&gt;&lt;/b&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;두 &lt;/span&gt;&lt;span&gt;가지 &lt;/span&gt;&lt;span&gt;상태로만 &lt;/span&gt;&lt;span&gt;데이터를 &lt;/span&gt;&lt;span&gt;표현하기 &lt;/span&gt;&lt;span&gt;때문이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;351&quot; data-start=&quot;313&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;그래서 &lt;/span&gt;&lt;span&gt;컴퓨터는 &lt;/span&gt;&lt;span&gt;모든 &lt;/span&gt;&lt;span&gt;데이터를 &lt;/span&gt;&lt;b&gt;&lt;span&gt;이진수(&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;과 &lt;/span&gt;&lt;span&gt;1)&lt;/span&gt;&lt;/b&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;로 &lt;/span&gt;&lt;span&gt;표현한다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-end=&quot;417&quot; data-start=&quot;379&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;컴퓨터에서 &lt;/span&gt;&lt;span&gt;가장 &lt;/span&gt;&lt;span&gt;작은 &lt;/span&gt;&lt;span&gt;데이터 &lt;/span&gt;&lt;span&gt;단위를 &lt;/span&gt;&lt;b&gt;&lt;span&gt;bit(&lt;/span&gt;&lt;span&gt;비트)&lt;/span&gt;&lt;/b&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;라고 &lt;/span&gt;&lt;span&gt;한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;451&quot; data-start=&quot;419&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;1bit&lt;/span&gt;&lt;span&gt;는 &lt;/span&gt;&lt;b&gt;&lt;span&gt;0 &lt;/span&gt;&lt;span&gt;또는 &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;/b&gt;&lt;span&gt; 이진수 &lt;/span&gt;&lt;span&gt;두 &lt;/span&gt;&lt;span&gt;가지를 &lt;/span&gt;&lt;span&gt;표현할 &lt;/span&gt;&lt;span&gt;수 &lt;/span&gt;&lt;span&gt;있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;462&quot; data-start=&quot;453&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;비트 별로 표현할 수 있는 가지수를&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;보자!&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 87px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 19px;&quot;&gt;비트&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 19px;&quot;&gt;표현 가능 수&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 17px;&quot;&gt;1 bit&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 17px;&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;0,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;1 (2가지)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 17px;&quot;&gt;2 bit&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 17px;&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;00,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;01,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;10,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;11 (4가지)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 17px;&quot;&gt;3 bit&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 17px;&quot;&gt;000, 001, 011 .... (8가지)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 17px;&quot;&gt;8 bit&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 17px;&quot;&gt;256가지&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;p data-end=&quot;644&quot; data-start=&quot;581&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;8bit&lt;/span&gt;&lt;span&gt;는 &lt;/span&gt;&lt;b&gt;&lt;span&gt;256&lt;/span&gt;&lt;span&gt;가지 &lt;/span&gt;&lt;span&gt;경우&lt;/span&gt;&lt;/b&gt;&lt;span&gt;를 &lt;/span&gt;&lt;span&gt;표현할 &lt;/span&gt;&lt;span&gt;수 &lt;/span&gt;&lt;span&gt;있으며&lt;/span&gt;&lt;br /&gt;&lt;span&gt;이 &lt;/span&gt;&lt;b&gt;&lt;span&gt;8bit = &lt;/span&gt;&lt;span&gt;1byte(&lt;/span&gt;&lt;span&gt;바이트)&lt;/span&gt;&lt;/b&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;라고 &lt;/span&gt;&lt;span&gt;부른다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-end=&quot;644&quot; data-start=&quot;581&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;그럼 숫자는 어떻게 저장할까 ?&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;예를 &lt;/span&gt;&lt;span&gt;들어 &lt;/span&gt;&lt;b&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;진수 &lt;/span&gt;&lt;span&gt;100&lt;/span&gt;&lt;/b&gt;&lt;span&gt;이라는 &lt;/span&gt;&lt;span&gt;숫자를 &lt;/span&gt;&lt;span&gt;저장한다고 &lt;/span&gt;&lt;span&gt;해보자.&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;732&quot; data-start=&quot;709&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;컴퓨터는 &lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;진수를 &lt;/span&gt;&lt;span&gt;직접 &lt;/span&gt;&lt;span&gt;저장하지 &lt;/span&gt;&lt;span&gt;않는다!&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;732&quot; data-start=&quot;709&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;그래서 &lt;/span&gt;&lt;span&gt;아래와 같이 10진수를 2진수로 &lt;/span&gt;&lt;span&gt;변환하여 저장한다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1773665341543&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;100 (10진수)
&amp;rarr; 1100100 (2진수)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이렇게 &lt;/span&gt;&lt;span&gt;변환된 &lt;/span&gt;&lt;b&gt;&lt;span&gt;이진수 &lt;/span&gt;&lt;span&gt;형태로 &lt;/span&gt;&lt;span&gt;메모리에 &lt;/span&gt;&lt;span&gt;저장된다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 음수는 어떻게 표현할까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;컴퓨터는 &lt;/span&gt;&lt;b&gt;&lt;span&gt;양수와 &lt;/span&gt;&lt;span&gt;음수&lt;/span&gt;&lt;/b&gt;&lt;span&gt;도 &lt;/span&gt;&lt;span&gt;표현해야 &lt;/span&gt;&lt;span&gt;한다. &lt;/span&gt;&lt;span&gt;그래서 &lt;/span&gt;&lt;span&gt;보통 &lt;/span&gt;&lt;b&gt;&lt;span&gt;1bit&lt;/span&gt;&lt;span&gt;를 &lt;/span&gt;&lt;span&gt;부호&lt;/span&gt;&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;표현에 &lt;/span&gt;&lt;span&gt;사용한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;932&quot; data-start=&quot;906&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;예를 &lt;/span&gt;&lt;span&gt;들어 &lt;/span&gt;&lt;b&gt;&lt;span&gt;8bit&lt;/span&gt;&lt;/b&gt;&lt;span&gt;를 &lt;/span&gt;&lt;span&gt;사용한다고 &lt;/span&gt;&lt;span&gt;해보자.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1773665449049&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;1bit &amp;rarr; 부호
7bit &amp;rarr; 숫자 표현&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;부호는 1bit 사용되며 양수는 0 , 음수는 1로 표현된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;그래서 &lt;/span&gt;&lt;span&gt;표현 &lt;/span&gt;&lt;span&gt;범위는 &lt;/span&gt;&lt;span&gt;이렇게 &lt;/span&gt;&lt;span&gt;된다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1773665490545&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;양수 : 0 ~ 127
음수 : -128 ~ -1&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;그럼 &lt;/span&gt;&lt;span&gt;문자는 &lt;/span&gt;&lt;span&gt;어떻게 &lt;/span&gt;&lt;span&gt;저장할까?&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;숫자는 &lt;/span&gt;&lt;span&gt;이진수로 &lt;/span&gt;&lt;span&gt;바꾸면 &lt;/span&gt;&lt;span&gt;된다. &lt;/span&gt;&lt;span&gt;하지만 &lt;/span&gt;&lt;span&gt;문자는 &lt;/span&gt;&lt;span&gt;어떨까?&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1773665533573&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;A
B
a
b&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같은 문자를 0 과 1로 표현하기에는 어렵다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;여기서 &lt;/span&gt;&lt;span&gt;등장하는 &lt;/span&gt;&lt;span&gt;개념이 &lt;/span&gt;&lt;span&gt;바로 &lt;/span&gt;&lt;b&gt;&lt;span&gt;문자 &lt;/span&gt;&lt;span&gt;집합(&lt;/span&gt;&lt;span&gt;Character &lt;/span&gt;&lt;span&gt;Set)&lt;/span&gt;&lt;/b&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;1203&quot; data-start=&quot;1175&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;문자 &lt;/span&gt;&lt;span&gt;집합은 &lt;/span&gt;&lt;span&gt;말 &lt;/span&gt;&lt;span&gt;그대로 &lt;/span&gt;&lt;b&gt;&lt;span&gt;문자를 &lt;/span&gt;&lt;span&gt;숫자에 &lt;/span&gt;&lt;span&gt;매핑해 &lt;/span&gt;&lt;span&gt;놓은 &lt;/span&gt;&lt;span&gt;표&lt;/span&gt;&lt;/b&gt;&lt;span&gt;이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;1277&quot; data-start=&quot;1264&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;예를 &lt;/span&gt;&lt;span&gt;들어 &lt;/span&gt;&lt;span&gt;이런 &lt;/span&gt;&lt;span&gt;식이다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1773665572813&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;A &amp;rarr; 65
B &amp;rarr; 66
a &amp;rarr; 97
b &amp;rarr; 98&lt;/code&gt;&lt;/pre&gt;
&lt;p data-end=&quot;1203&quot; data-start=&quot;1175&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;그래서 &lt;/span&gt;&lt;span&gt;컴퓨터는 &lt;/span&gt;&lt;u&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;문자 &amp;rarr; 숫자 &amp;rarr; 2진수 &lt;/span&gt;&lt;/u&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;이렇게 &lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;변환해서 &lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;저장한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;1382&quot; data-start=&quot;1365&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;그리고 &lt;/span&gt;&lt;span&gt;읽을 &lt;/span&gt;&lt;span&gt;때는 &lt;/span&gt;&lt;span&gt;반대로 &lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;&lt;u&gt;2진수 &amp;rarr; 숫자 &amp;rarr; 문자&lt;/u&gt; 로 읽는다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;1413&quot; data-start=&quot;1407&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이 &lt;/span&gt;&lt;span&gt;과정을 문자 인코딩, 디코딩이라고 표현한다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1773665622095&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;문자 &amp;rarr; 숫자 변환 = 문자 인코딩 (Encoding)
숫자 &amp;rarr; 문자 변환 = 문자 디코딩 (Decoding)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-end=&quot;1495&quot; data-start=&quot;1488&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;그런데 &lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;문제가 발생했다..!&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;1567&quot; data-start=&quot;1540&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;만약 &lt;/span&gt;&lt;span&gt;컴퓨터마다 &lt;/span&gt;&lt;span&gt;문자 &lt;/span&gt;&lt;span&gt;집합이 &lt;/span&gt;&lt;span&gt;다르면 &lt;/span&gt;&lt;span&gt;어떻게 &lt;/span&gt;&lt;span&gt;될까?&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;1574&quot; data-start=&quot;1569&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;예를 &lt;/span&gt;&lt;span&gt;들어&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;pre id=&quot;code_1773665653580&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;A = 65 (컴퓨터1)
A = 120 (컴퓨터2)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;1646&quot; data-start=&quot;1614&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이러면 &lt;/span&gt;&lt;span&gt;서로 &lt;/span&gt;&lt;span&gt;데이터를 &lt;/span&gt;&lt;span&gt;교환할 &lt;/span&gt;&lt;span&gt;때 &lt;/span&gt;&lt;b&gt;&lt;span&gt;문자가 &lt;/span&gt;&lt;span&gt;깨져버린다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-end=&quot;1672&quot; data-start=&quot;1648&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;그래서 &lt;/span&gt;&lt;b&gt;&lt;span&gt;표준 &lt;/span&gt;&lt;span&gt;문자 &lt;/span&gt;&lt;span&gt;집합&lt;/span&gt;&lt;/b&gt;&lt;span&gt;이 &lt;/span&gt;&lt;span&gt;필요해졌다!&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;그래서 &lt;/span&gt;&lt;span&gt;등장한 &lt;/span&gt;&lt;span&gt;것이 &lt;/span&gt;&lt;span&gt;바로&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;1771&quot; data-start=&quot;1709&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span&gt;ASCII (&lt;/span&gt;&lt;span&gt;American &lt;/span&gt;&lt;span&gt;Standard &lt;/span&gt;&lt;span&gt;Code &lt;/span&gt;&lt;span&gt;for &lt;/span&gt;&lt;span&gt;Information &lt;/span&gt;&lt;span&gt;Interchange) &lt;/span&gt;&lt;/b&gt;&lt;span&gt;문자 집합이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;1802&quot; data-start=&quot;1778&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;ASCII&lt;/span&gt;&lt;span&gt;는 &lt;/span&gt;&lt;b&gt;&lt;span&gt;7bit &lt;/span&gt;&lt;span&gt;문자 &lt;/span&gt;&lt;span&gt;집합&lt;/span&gt;&lt;/b&gt;&lt;span&gt;이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;1771&quot; data-start=&quot;1709&quot; data-ke-size=&quot;size16&quot;&gt;2^7 = 128개 문자&lt;span&gt;를 &lt;/span&gt;&lt;span&gt;표현할 &lt;/span&gt;&lt;span&gt;수 &lt;/span&gt;&lt;span&gt;있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;대표적으로&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1882&quot; data-start=&quot;1850&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1858&quot; data-start=&quot;1850&quot; data-section-id=&quot;1wb8ant&quot;&gt;&lt;span&gt;영문 &lt;/span&gt;&lt;span&gt;대문자&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;1867&quot; data-start=&quot;1859&quot; data-section-id=&quot;1vtcewl&quot;&gt;&lt;span&gt;영문 &lt;/span&gt;&lt;span&gt;소문자&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;1872&quot; data-start=&quot;1868&quot; data-section-id=&quot;yim8hf&quot;&gt;&lt;span&gt;숫자&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;1882&quot; data-start=&quot;1873&quot; data-section-id=&quot;2wpy95&quot;&gt;&lt;span&gt;기본 &lt;/span&gt;&lt;span&gt;특수문자&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;1899&quot; data-start=&quot;1884&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;같은 &lt;/span&gt;&lt;span&gt;것들이 &lt;/span&gt;&lt;span&gt;포함되어 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;1899&quot; data-start=&quot;1884&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;하지만 &lt;/span&gt;&lt;span&gt;문제점이 &lt;/span&gt;&lt;span&gt;있었다. &lt;/span&gt;&lt;span&gt;ASCII&lt;/span&gt;&lt;span&gt;는 &lt;/span&gt;&lt;span&gt;이름에서도 &lt;/span&gt;&lt;span&gt;보이듯이 &lt;b&gt;&lt;span&gt;American &lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;b&gt;&lt;span&gt;미국 &lt;/span&gt;&lt;span&gt;중심 &lt;/span&gt;&lt;span&gt;문자&lt;/span&gt;&lt;/b&gt;&lt;span&gt;만 &lt;/span&gt;&lt;span&gt;포함되어 &lt;/span&gt;&lt;span&gt;있었다!&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-end=&quot;1958&quot; data-start=&quot;1935&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;그래서 &lt;/span&gt;&lt;span&gt;유럽에서 &lt;/span&gt;&lt;span&gt;사용하기 &lt;/span&gt;&lt;span&gt;위해 &lt;/span&gt;&lt;b&gt;&lt;span&gt;ISO-&lt;/span&gt;&lt;span&gt;8859-&lt;/span&gt;&lt;span&gt;1 (&lt;/span&gt;&lt;span&gt;Latin-&lt;/span&gt;&lt;span&gt;1)&lt;/span&gt;&lt;/b&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;이 &lt;/span&gt;&lt;span&gt;등장했다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;1958&quot; data-start=&quot;1935&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;ASCII&lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;는 &lt;/span&gt;&lt;b&gt;7bit&lt;/b&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;였지만 &lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;여기에 &lt;/span&gt;&lt;b&gt;1bit를 추가해서 &lt;span&gt;&amp;eacute; 와 같은 라틴어을 포함하여 &lt;/span&gt;8bit&lt;/b&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;로 &lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;만들었다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1773665747276&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;2^8 = 256 문자&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;한국에서도 &lt;/span&gt;&lt;span&gt;컴퓨터 &lt;/span&gt;&lt;span&gt;사용이 &lt;/span&gt;&lt;span&gt;늘어나면서 &lt;/span&gt;&lt;b&gt;&lt;span&gt;한글 &lt;/span&gt;&lt;span&gt;표현 &lt;/span&gt;&lt;span&gt;문제&lt;/span&gt;&lt;/b&gt;&lt;span&gt;가 &lt;/span&gt;&lt;span&gt;생겼다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;2277&quot; data-start=&quot;2260&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;한글은 &lt;/span&gt;&lt;span&gt;글자가 &lt;/span&gt;&lt;span&gt;매우 &lt;/span&gt;&lt;span&gt;많기 &lt;/span&gt;&lt;span&gt;때문에 &lt;/span&gt;&lt;span&gt;ASCII&lt;/span&gt;&lt;span&gt;처럼 &lt;/span&gt;&lt;b&gt;&lt;span&gt;1byte&lt;/span&gt;&lt;span&gt;로는 &lt;/span&gt;&lt;span&gt;표현이 &lt;/span&gt;&lt;span&gt;부족했다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-end=&quot;2320&quot; data-start=&quot;2310&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;그래서 &lt;/span&gt;&lt;span&gt;등장한 &lt;/span&gt;&lt;span&gt;것이 &lt;/span&gt;&lt;b&gt;&lt;span&gt;EUC-&lt;/span&gt;&lt;span&gt;KR &lt;/span&gt;&lt;/b&gt;&lt;span&gt;이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;2350&quot; data-start=&quot;2339&quot; data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;&lt;span&gt;영문 &amp;rarr; 1byte, &lt;/span&gt;&lt;/u&gt;&lt;span&gt;&lt;u&gt;한글 &amp;rarr; 2byte&lt;/u&gt; 로 표현 할 수 있으며 &lt;/span&gt;&lt;u&gt;&lt;span&gt;ASCII&lt;/span&gt;&lt;span&gt;는 &lt;/span&gt;&lt;span&gt;그대로 &lt;/span&gt;&lt;/u&gt;&lt;span&gt;&lt;u&gt;사용하여 호환이 가능&lt;/u&gt;하다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;2350&quot; data-start=&quot;2339&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;그리고 2byte로도 충분히 공간이&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;남아서 한자와 일본어 일부도 포함되어있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;2350&quot; data-start=&quot;2339&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;윈도우에서는 &lt;/span&gt;&lt;span&gt;EUC-&lt;/span&gt;&lt;span&gt;KR&lt;/span&gt;&lt;span&gt;을 &lt;/span&gt;&lt;span&gt;확장한 &lt;/span&gt;&lt;b&gt;&lt;span&gt;MS949&lt;/span&gt;&lt;/b&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;인코딩을 &lt;/span&gt;&lt;span&gt;사용한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;2577&quot; data-start=&quot;2561&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;EUC-&lt;/span&gt;&lt;span&gt;KR&lt;/span&gt;&lt;span&gt;이 &lt;/span&gt;&lt;span&gt;표현하지 &lt;/span&gt;&lt;span&gt;못하던 '쀍 등' 같은 잘 사용하지 않는 한글이 포함된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;2577&quot; data-start=&quot;2561&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;span&gt;현재도 &lt;/span&gt;&lt;b&gt;&lt;span&gt;Windows &lt;/span&gt;&lt;span&gt;한글 &lt;/span&gt;&lt;span&gt;시스템&lt;/span&gt;&lt;/b&gt;&lt;span&gt;에서는 이전 윈도우 호환성을 위해&amp;nbsp;&lt;/span&gt;&lt;span&gt;기본 &lt;/span&gt;&lt;span&gt;인코딩으로 &lt;/span&gt;&lt;span&gt;사용된다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2350&quot; data-start=&quot;2339&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;시간이 &lt;/span&gt;&lt;span&gt;지나면서 &lt;/span&gt;&lt;span&gt;문제가 &lt;/span&gt;&lt;span&gt;생겼다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;2740&quot; data-start=&quot;2714&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;컴퓨터가 &lt;/span&gt;&lt;span&gt;전 &lt;/span&gt;&lt;span&gt;세계적으로 &lt;/span&gt;&lt;span&gt;사용되기 &lt;/span&gt;&lt;span&gt;시작한 &lt;/span&gt;&lt;span&gt;것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;2757&quot; data-start=&quot;2742&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;그래서 &lt;u&gt;&lt;span&gt;모든 &lt;/span&gt;&lt;span&gt;언어를 &lt;/span&gt;&lt;span&gt;하나의 &lt;/span&gt;&lt;/u&gt;&lt;span&gt;&lt;u&gt;문자 집합&lt;/u&gt;으로 표현해야 했으며 그래서 등장한것이 &lt;b&gt;유니코드(Unicode)&lt;/b&gt; 이다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;2757&quot; data-start=&quot;2742&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;span&gt;대표적인 인코딩 방식은 UTF-16, UTF-8 이 있다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;2757&quot; data-start=&quot;2742&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span&gt;UTF-&lt;/span&gt;&lt;/b&gt;&lt;span&gt;&lt;b&gt;16&lt;/b&gt;은 &lt;u&gt;기본으로 2byte 기반&lt;/u&gt;이며 &lt;u&gt;일부 특수 문자(이모지, 고대문자 등)들은 4byte&lt;/u&gt; 를 사용한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;2757&quot; data-start=&quot;2742&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;span&gt;하지만 ASCII 문자도 2byte 를 사용하기에 기존 ASCII(1byte를 사용하므로) 호환되지 않으며&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;2757&quot; data-start=&quot;2742&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;span&gt;저장 공간도 1byte &amp;gt; 2byte 로 늘어나게 되는 단점이 있다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;2757&quot; data-start=&quot;2742&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;span&gt;그래서 나온것이 &lt;b&gt;UTF-8&lt;/b&gt; 이다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;2757&quot; data-start=&quot;2742&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;UTF-&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;은 &lt;/span&gt;&lt;b&gt;&lt;span&gt;가변 &lt;/span&gt;&lt;span&gt;길이 &lt;/span&gt;&lt;span&gt;인코딩&lt;/span&gt;&lt;/b&gt;&lt;span&gt;이다. &lt;/span&gt;&lt;span&gt;즉 &lt;/span&gt;&lt;span&gt;문자에 &lt;/span&gt;&lt;span&gt;따라 &lt;/span&gt;&lt;b&gt;&lt;span&gt;사용하는 &lt;/span&gt;&lt;span&gt;byte&lt;/span&gt;&lt;span&gt;가 &lt;/span&gt;&lt;span&gt;달라진다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1773666152350&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;1byte &amp;rarr; ASCII, 영문, 기본 라틴 문자
2byte &amp;rarr; 그리스어, 히브리어, 라틴 확장
3byte &amp;rarr; 한글, 한자, 일본어
4byte &amp;rarr; 이모지, 고대 문자&lt;/code&gt;&lt;/pre&gt;
&lt;p data-end=&quot;3349&quot; data-start=&quot;3320&quot; data-ke-size=&quot;size16&quot;&gt;UTF-8 은 &lt;span&gt;ASCII가 1byte 를 사용하기에 ASCII로 이전에 저장된 문자와 &lt;/span&gt;&lt;span&gt;완벽히 &lt;/span&gt;&lt;span&gt;호환되며&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;3349&quot; data-start=&quot;3320&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;영문 문서의 경우 그대로 1byte 사용하므로 용량의 증가가 없고(대부분 문서가 영문, 코딩도 영문이므로 중요한 부분중 하나), 전세계 문자 표현도 가능하다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;3349&quot; data-start=&quot;3320&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;그래서 &lt;/span&gt;&lt;span&gt;현재까지 웹사이트, 앱, 서버, DB 와 같이 다양한 곳에서 가장 많이 사용하는 인코딩이 UTF-8가 되었다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-end=&quot;3349&quot; data-start=&quot;3320&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;그래서 정리해보면&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;3830&quot; data-start=&quot;3826&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;컴퓨터는 &lt;/span&gt;&lt;b&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px; background-color: #f6e199;&quot;&gt;문자 &amp;rarr; 숫자 &amp;rarr; 이진수 &lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;로 &lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;데이터를 &lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;저장한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;3886&quot; data-start=&quot;3869&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;그리고 &lt;/span&gt;&lt;span&gt;이 &lt;/span&gt;&lt;span&gt;과정에서 &lt;/span&gt;&lt;span&gt;필요한 &lt;/span&gt;&lt;span&gt;것이&amp;nbsp;&lt;/span&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;문자&amp;nbsp;집합, 문자 &lt;/span&gt;&lt;span&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;인코딩&lt;/span&gt; &lt;/span&gt;&lt;/b&gt;&lt;span&gt;이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;3923&quot; data-start=&quot;3911&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span&gt;ASCII&lt;/span&gt;&lt;/b&gt;&lt;span&gt;에서 &lt;/span&gt;&lt;span&gt;시작해서 &lt;/span&gt;&lt;b&gt;&lt;span&gt;EUC-&lt;/span&gt;&lt;span&gt;KR, &lt;/span&gt;&lt;span&gt;MS949&lt;/span&gt;&lt;/b&gt;&lt;span&gt;를 &lt;/span&gt;&lt;span&gt;거쳐&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;3975&quot; data-start=&quot;3944&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;지금은 &lt;/span&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;UTF-8이 사실상 표준 인코딩&lt;/b&gt;&lt;/span&gt;&lt;span&gt;이 &lt;/span&gt;&lt;span&gt;되었다.&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;</description>
      <category>JAVA</category>
      <author>코린이s</author>
      <guid isPermaLink="true">https://co-de.tistory.com/261</guid>
      <comments>https://co-de.tistory.com/261#entry261comment</comments>
      <pubDate>Mon, 16 Mar 2026 22:12:43 +0900</pubDate>
    </item>
    <item>
      <title>[TDD] SpringBoot 를 통한 TDD 손쉬운 작성 - 05) 테스트 코드 품질 높이기! - 03</title>
      <link>https://co-de.tistory.com/260</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;680&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/DjEmA/dJMcaf6CN5w/c2QKpgqlDSzLWZAKlqM4a0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/DjEmA/dJMcaf6CN5w/c2QKpgqlDSzLWZAKlqM4a0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/DjEmA/dJMcaf6CN5w/c2QKpgqlDSzLWZAKlqM4a0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDjEmA%2FdJMcaf6CN5w%2Fc2QKpgqlDSzLWZAKlqM4a0%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;500&quot; height=&quot;332&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;680&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저번 시간까지는 하나의 값에 대한 검증하는 방법을 배웠다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 시간에는 컬렉션 검증에 자주 사용되는 AssertJ 메서드에서 알아보자!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;1) extracting() 을 이용한 정보 추출 검증, contains() 를 통한 내부값 포함 여부 검증&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체 리스트에서 &lt;b&gt;특정 필드만 추출해서 검증하고 싶을 때&lt;/b&gt; extracting()을 사용해보자!&lt;/p&gt;
&lt;p data-end=&quot;388&quot; data-start=&quot;348&quot; data-ke-size=&quot;size16&quot;&gt;예를 들어 객체 리스트에서 name 필드만 추출해서 검증할 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1773143571891&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;assertThat(users)
    .extracting(User::getName)
    .contains(&quot;Kim&quot;, &quot;Lee&quot;);&lt;/code&gt;&lt;/pre&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;그리고 contains() 를 통해&lt;b&gt; 내부에 해당 값을 전부 포함&lt;/b&gt;하고 있는지 확인한다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;2) containsAll() 목록 포함 여부 검증&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞에 contains() 와 기능 부분은 &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;pre id=&quot;code_1773143599249&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;assertThat(users)
	.extracting(User::getName)
	.containsAll(Arrays.asList(&quot;Kim&quot;,&quot;Lee&quot;));&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;Arrays.asList 와 같이 컬렉션을 넘겨&amp;nbsp;&lt;b&gt;해당 값들을 전부 포함하고 있는지 확인한다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-end=&quot;779&quot; data-start=&quot;738&quot; data-ke-size=&quot;size16&quot;&gt;정의한 값 중에 하나라도 없으면 오류가 발생하고,&lt;b&gt; 해당 값 이외에 다른 값이 더 있어도 오류 발생하지 않는점&lt;/b&gt;은 위 contains() 와 동일하다!&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-end=&quot;779&quot; data-start=&quot;738&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;3) doesNotContain() 요소가 포함되지 않았는지 검증&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;779&quot; data-start=&quot;738&quot; data-ke-size=&quot;size16&quot;&gt;특정 값이 &lt;b&gt;리스트에 존재하지 않는지 확인&lt;/b&gt;하고 싶다면 doesNotContain()을 사용해보자!&lt;/p&gt;
&lt;pre id=&quot;code_1773143625000&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;assertThat(users)
	.extracting(User::getName)
	.doesNotContain(&quot;Kim&quot;);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 하면 name 중에 &quot;Kim' 이 있다면 검증 실패가 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;doesNotContain 을 사용하면 &lt;b&gt;해당 요소가 목록에 포함되어 있지 않은지 검증할 수 있다!&lt;/b&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;4) isSortedAccordingTo() 정렬 기준 검증&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리스트가 &lt;b&gt;특정 기준으로 정렬되어 있는지 확인&lt;/b&gt;하고 싶다면 isSortedAccordingTo()를 사용해보자!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오름차순인지 보려면 아래와 같이 Comparator 코드에는 natualOrder() 을 사용하면 되며&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리가 보통 네츄럴 하게 생각하는 정렬은 오름차순이기에 natualOrder 가 오름차순 정렬을 검증하는것 이라고 한다.&lt;/p&gt;
&lt;div style=&quot;background-color: #1e1f22; color: #bcbec4;&quot;&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;assertThat(numbers).isSortedAccordingTo(Comparator.naturalOrder());&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-end=&quot;1130&quot; data-start=&quot;1099&quot; data-ke-size=&quot;size16&quot;&gt;오름차순은 아래와 같이 간단하게&amp;nbsp; 검증 할 수 있다!&lt;/p&gt;
&lt;div style=&quot;background-color: #1e1f22; color: #bcbec4;&quot;&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;assertThat(numbers).isSorted();&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-end=&quot;1130&quot; data-start=&quot;1099&quot; data-ke-size=&quot;size16&quot;&gt;만약에&amp;nbsp;&lt;b&gt;내림차순 정렬 여부&lt;/b&gt;를 검증 한다고 하면&lt;/p&gt;
&lt;p data-end=&quot;1130&quot; data-start=&quot;1099&quot; data-ke-size=&quot;size16&quot;&gt;뒤에 Comparator 코드만 내림차순인 reverseOrder 로 변경하면 된다!&lt;/p&gt;
&lt;pre id=&quot;code_1773143650050&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;assertThat(numbers)
    .isSortedAccordingTo(Comparator.reverseOrder());&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;직접 Comparator 기준을 작성해서 넣을수도 있다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Comparator 코드 작성하는 방법은 다음에 필요할때 검색해서 사용해보도록 하고 현재는 검증 방법만 알아두도록 하자!&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;5) containsExactly() 정확한 값과 순서 검증&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞에서 contains(), containsAll() 을 통해 리스트의 값이 모두 포함되어 있는지를 검증 할 수 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;여기에 순서까지 체크하고 싶다면 &lt;/b&gt;containsExactly()를 사용해보자!&lt;/p&gt;
&lt;pre id=&quot;code_1773143680476&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;assertThat(numbers)
    .containsExactly(1, 2, 3);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 메서드는&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1511&quot; data-start=&quot;1465&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1480&quot; data-start=&quot;1465&quot; data-section-id=&quot;1yo4i2n&quot;&gt;값이 정확히 같아야 하고&lt;/li&gt;
&lt;li data-end=&quot;1494&quot; data-start=&quot;1481&quot; data-section-id=&quot;1yqt9yx&quot;&gt;순서도 동일해야 하고&lt;/li&gt;
&lt;li data-end=&quot;1511&quot; data-start=&quot;1495&quot; data-section-id=&quot;11p1mai&quot;&gt;추가 데이터도 없어야 한다&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;1548&quot; data-start=&quot;1513&quot; data-ke-size=&quot;size16&quot;&gt;즉 &lt;b&gt;완전히 동일한 목록인지 검증할 때 사용한다&lt;/b&gt;!&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-end=&quot;1548&quot; data-start=&quot;1513&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;6) containsExactlyElementsOf() 동일 목록 + 동일 순서 검증&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;1548&quot; data-start=&quot;1513&quot; data-ke-size=&quot;size16&quot;&gt;containsExactlyElementsOf()도 containsExactly()와 비슷하다.&lt;/p&gt;
&lt;pre id=&quot;code_1773143713092&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;assertThat(numbers)
    .containsExactlyElementsOf(List.of(1, 2, 3));&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 메서드 역시&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1786&quot; data-start=&quot;1760&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1766&quot; data-start=&quot;1760&quot; data-section-id=&quot;1x3hwf3&quot;&gt;값 동일&lt;/li&gt;
&lt;li data-end=&quot;1774&quot; data-start=&quot;1767&quot; data-section-id=&quot;ur01al&quot;&gt;순서 동일&lt;/li&gt;
&lt;li data-end=&quot;1786&quot; data-start=&quot;1775&quot; data-section-id=&quot;zjw342&quot;&gt;추가 데이터 없음&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;1795&quot; data-start=&quot;1788&quot; data-ke-size=&quot;size16&quot;&gt;을 검증한다.&lt;/p&gt;
&lt;p data-end=&quot;1814&quot; data-start=&quot;1797&quot; 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-end=&quot;1895&quot; data-start=&quot;1816&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1849&quot; data-start=&quot;1816&quot; data-section-id=&quot;e5v2zw&quot;&gt;containsExactly() &amp;rarr; 개별 값 입력&lt;/li&gt;
&lt;li data-end=&quot;1895&quot; data-start=&quot;1850&quot; data-section-id=&quot;53q2ba&quot;&gt;containsExactlyElementsOf() &amp;rarr; 컬렉션 형태 입력&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;1947&quot; data-start=&quot;1897&quot; data-ke-size=&quot;size16&quot;&gt;즉 &lt;b&gt;검증 대상 데이터를 List나 Set 형태로 받을 때 사용하기 편하다&lt;/b&gt;!&lt;/p&gt;
&lt;p data-end=&quot;1947&quot; data-start=&quot;1897&quot; data-ke-size=&quot;size16&quot;&gt;끝!&lt;/p&gt;</description>
      <category>JAVA</category>
      <author>코린이s</author>
      <guid isPermaLink="true">https://co-de.tistory.com/260</guid>
      <comments>https://co-de.tistory.com/260#entry260comment</comments>
      <pubDate>Tue, 10 Mar 2026 22:10:14 +0900</pubDate>
    </item>
    <item>
      <title>[TDD] SpringBoot 를 통한 TDD 손쉬운 작성 - 04) 테스트 코드 품질 높이기! - 02</title>
      <link>https://co-de.tistory.com/259</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;680&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/DjEmA/dJMcaf6CN5w/c2QKpgqlDSzLWZAKlqM4a0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/DjEmA/dJMcaf6CN5w/c2QKpgqlDSzLWZAKlqM4a0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/DjEmA/dJMcaf6CN5w/c2QKpgqlDSzLWZAKlqM4a0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDjEmA%2FdJMcaf6CN5w%2Fc2QKpgqlDSzLWZAKlqM4a0%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;500&quot; height=&quot;332&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;680&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저번 시간에 이어서 테스트 코드 품질을 개선하는 방법에 대해서 알아보자!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 시간에는 아래 방법에 대해서 예시를 통해 하나씩 보도록 한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;TestRestTemplate.postForObject&lt;/li&gt;
&lt;li&gt;TestRestTemplate.exchange&lt;/li&gt;
&lt;li&gt;AssertJ.isCloseTo&lt;/li&gt;
&lt;li&gt;@DirtiesContext&lt;/li&gt;
&lt;li&gt;TestFixture&lt;/li&gt;
&lt;li&gt;TestDSL&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리는 TestRestTemplate.postForEntity 를 이전 시간에 사용했다.&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;postForObject&lt;/b&gt; 이다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래와 같이 예제 코드를 작성해보자.&lt;/p&gt;
&lt;pre id=&quot;code_1772944402585&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Users users = Users.builder()
            .name(&quot;코린이&quot;)
            .id(&quot;test&quot;)
            .password(password)
            .build();
            
Users response = client
            .postForObject(&quot;/users&quot;, users, Users.class);
System.out.println(response.getName());&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면 바로 응답 데이터인 Users로 받게 되어 아래와 같이 getBody 를 호출하지 않아도 바로 받아 처리 할 수 있어&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;간단한 요청 테스트에 사용할 수 있다.&lt;/p&gt;
&lt;div style=&quot;background-color: #1e1f22; color: #bcbec4;&quot;&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;Users users = response.getBody();&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div&gt;&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;&lt;/div&gt;
&lt;div&gt;&lt;br /&gt;다음으로는 &lt;b&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;TestRestTemplate.exchange&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;에 대해서 알아보자!&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;exchange() 는 HTTP Header, Method, Entity 등을 모두 지정할 수 있는 메서드이다.&lt;/p&gt;
&lt;div&gt;기존에 사용하던 postForEntity 나 postForObject 의 경우 따로 지정 할 수 없었다.&lt;/div&gt;
&lt;div&gt;그래서 원하는 대로 지정해서 사용하고자 하면 exchange를 사용하면 된다!&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 예시와 같이 Header 과 요청값을 정의하고 exchange 에 넣는다.&lt;/p&gt;
&lt;div&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;HttpHeaders headers = new HttpHeaders();
headers.add(&quot;Authorization&quot;, &quot;Bearer token&quot;);

Users users = Users.builder()
            .name(&quot;코린이&quot;)
            .id(&quot;test&quot;)
            .password(password)
            .build();
HttpEntity&amp;lt;Users&amp;gt; request = new HttpEntity&amp;lt;&amp;gt;(users, headers);

ResponseEntity&amp;lt;Users&amp;gt; response = client.exchange(
    &quot;/users&quot;,
    HttpMethod.POST,
    request,
    Users.class
);

System.out.println(res01.getBody().getName());&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실행해보면 아래와 같이 정상적으로 출력됨을 확인 할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;970&quot; data-origin-height=&quot;364&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/drLtve/dJMcachY7qu/FNuSAdKvXJfk2687bXUWk1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/drLtve/dJMcachY7qu/FNuSAdKvXJfk2687bXUWk1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/drLtve/dJMcachY7qu/FNuSAdKvXJfk2687bXUWk1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdrLtve%2FdJMcachY7qu%2FFNuSAdKvXJfk2687bXUWk1%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;500&quot; height=&quot;188&quot; data-origin-width=&quot;970&quot; data-origin-height=&quot;364&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 검증 기능 하나 더 알아 보자면..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DB에 저장되는 시간을 검증할 때는 현재 시각과 약간의 차이가 발생할 수 있다.&lt;/p&gt;
&lt;p data-end=&quot;4417&quot; data-start=&quot;4383&quot; data-ke-size=&quot;size16&quot;&gt;따라서 정확히 같은 시간을 비교하면 테스트가 실패할 수 있다.&lt;/p&gt;
&lt;p data-end=&quot;4455&quot; data-start=&quot;4419&quot; data-ke-size=&quot;size16&quot;&gt;이때 &lt;b&gt;AssertJ의 isCloseTo&lt;/b&gt; 를 사용하면 된다.&lt;/p&gt;
&lt;p data-end=&quot;4455&quot; data-start=&quot;4419&quot; data-ke-size=&quot;size16&quot;&gt;우선 우리가 regDate 라는 칼럼을 생성하지 않았으므로 아래와 같이 생성한다.&lt;/p&gt;
&lt;div style=&quot;background-color: #1e1f22; color: #bcbec4;&quot;&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;@EntityListeners(AuditingEntityListener.class)
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
@Builder
@Getter
@Entity
public class Users {

    @Id
    String userId;
    String name;
    String password;
    @CreatedDate
    LocalDateTime regDate;
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;@EntityListeners 가 자동으로 @CreatedDate 가 붙은 컬럼에 생성일을 추가하여 Insert 쿼리를 날린다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고 사항으로 만약 Spring 이 아니라 DB에서 자동 생성 되도록 하려면 아래와 같이 수정한다.&lt;/p&gt;
&lt;div style=&quot;background-color: #1e1f22; color: #bcbec4;&quot;&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
@Builder
@Getter
@Entity
public class Users {

    @Id
    String userId;
    String name;
    String password;
    @Column(insertable = false, updatable = false)
    LocalDateTime regDate;
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;@Column(insertable = false, updatable = false) 을 지정하여 업데이트와 임의로 데이터 추가 안되도록 정의하고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;@CreateDate 와 @EntityListeners 를 제거 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 DB 의 regDate 칼럼 생성시 아래와 같이 Default 값 자동으로 들어가도록 설정 해야 한다.&lt;/p&gt;
&lt;pre id=&quot;code_1772963005956&quot; class=&quot;sql&quot; data-ke-language=&quot;sql&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;reg_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 테스트 코드에 Regdate 값을 isCloseTo 로 비교하는 문을 넣는다.&lt;/p&gt;
&lt;div style=&quot;background-color: #1e1f22; color: #bcbec4;&quot;&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;@Test
void 유저_생성(){
    // Arrange
    LocalDateTime now = LocalDateTime.now();
    Users users = UserFixture.createUser();

    // Act
    ResponseEntity&amp;lt;Users&amp;gt; response = userDSL.회원생성(users);

    // Assert
    assertThat(response.getStatusCode().value()).isEqualTo(200);
    assertThat(response.getBody()).isNotNull();
    assertThat(response.getBody()).isNotNull();
    assertThat(response.getBody().getRegDate()).isCloseTo(now, within(1, ChronoUnit.SECONDS));
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 코드는 상단에 테스트 코드 실행시 현재 시간을 저장한 now 와, DB의 regdate 값의 1s 이내 차이 까지는&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;허용 하겠다는 의미로 코드 실행 시점부터 instert 까지 ms 정도 차이가 있을수 있으니&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1s 의 차이는 테스트 통과로 지정한다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 아래와 같이 테스트 코드가 통과하는것을 볼 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;726&quot; data-origin-height=&quot;388&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/GaiL4/dJMcagYYa2g/leb5It6P2mB26bulNrWnl1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/GaiL4/dJMcagYYa2g/leb5It6P2mB26bulNrWnl1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/GaiL4/dJMcagYYa2g/leb5It6P2mB26bulNrWnl1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGaiL4%2FdJMcagYYa2g%2Fleb5It6P2mB26bulNrWnl1%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;500&quot; height=&quot;267&quot; data-origin-width=&quot;726&quot; data-origin-height=&quot;388&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&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;@DirtiesContext&lt;/b&gt; 를 테스트 코드 위에 정의 한다!&lt;/p&gt;
&lt;pre id=&quot;code_1772950624596&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@SpringBootTest
@DirtiesContext
class ServiceTest {
...}&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;스프링에서 bean 생성은 싱글톤 이라서 컨테이너에 빈 하나만 생성되고 계속적으로 사용된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러므로 테스트마다 다음 테스트에 영향을 주면 안되는 경우에 @DistiesContext 를 정의하여&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;매번 빈을 생성하여 테스트 끼리 공유 되지 않도록 할 수 있다!&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 &lt;b&gt;테스트 픽스처(Test Fixture)&lt;/b&gt;에 대해서 알아보자!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;테스트 픽스처(Test Fixture) 는 테스트를 수행하기 위해 미리 준비해두는 데이터나 객체를 의미한다.&lt;/p&gt;
&lt;p data-end=&quot;1423&quot; data-start=&quot;1360&quot; 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;유저 픽스쳐를 만들고 static 으로 유저 생성하는 메소드를 만든다.&lt;/p&gt;
&lt;div style=&quot;background-color: #1e1f22; color: #bcbec4;&quot;&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;package test.commerce.fixture;

import commerce.command.Users;

public class UserFixture {

    public static Users createUser() {
        return Users.builder()
            .name(&quot;코린이&quot;)
            .id(&quot;test&quot;)
            .password(&quot;test&quot;)
            .build();
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 코드는 이전 시간에 만든 테스트 코드 이다.&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;background-color: #1e1f22; color: #bcbec4;&quot;&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;@Test
void 비밀번호검증(
    @Autowired TestRestTemplate client
) {
    // Arrange
    Users users = Users.builder()
        .name(&quot;코린이&quot;)
        .id(&quot;test&quot;)
        .password(&quot;test&quot;)
        .build();

    // Act
    ResponseEntity&amp;lt;Users&amp;gt; response = client
        .postForEntity(&quot;/users&quot;, users, Users.class);

    // Assert
    assertThat(response.getStatusCode().value()).isEqualTo(200);
    assertThat(response.getBody()).satisfies(this::assertName);
    assertThat(response.getBody()).satisfies(this::assertPassword);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&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;div style=&quot;background-color: #1e1f22; color: #bcbec4;&quot;&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;@Test
void 비밀번호검증(
    @Autowired TestRestTemplate client
) {
    // Arrange
    Users users = UserFixture.createUser();

    // Act
    ResponseEntity&amp;lt;Users&amp;gt; response = client.postForEntity(&quot;/users&quot;, users, Users.class);

    // Assert
    assertThat(response.getStatusCode().value()).isEqualTo(200);
    assertThat(response.getBody()).satisfies(this::assertName);
    assertThat(response.getBody()).satisfies(this::assertPassword);
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;매번 사용하는 코드를 미리 준비하는것이 TestFixture 라는것을 알아봤다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 알아볼것은 &lt;b&gt;Test DSL&lt;/b&gt; 이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Test DSL 은 Test Domain Spectific Language 로 영어 그대로 해석해 보면 도메인에 맞게 만든 언어 라는 의미 이다.&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;div style=&quot;background-color: #1e1f22; color: #bcbec4;&quot;&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;@Test
void 유저_생성(
    @Autowired TestRestTemplate client
) {
    // Arrange
    Users users = UserFixture.createUser();

    // Act
    ResponseEntity&amp;lt;Users&amp;gt; response = client.postForEntity(&quot;/users&quot;, users, Users.class);

    // Assert
    assertThat(response.getStatusCode().value()).isEqualTo(200);
    assertThat(response.getBody()).satisfies(this::assertName);
    assertThat(response.getBody()).satisfies(this::assertPassword);
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;Act 부분의 유저 생성 부분을 직관적으로 알 수 있게 DSL 로 만들어 보자&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 UserDSL 을 먼저 생성하여 유저 생성 메서드를 만든다.&lt;/p&gt;
&lt;div style=&quot;background-color: #1e1f22; color: #bcbec4;&quot;&gt;
&lt;pre class=&quot;kotlin&quot;&gt;&lt;code&gt;package test.commerce.dsl;

import commerce.command.Users;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;

@Component
public class UserDSL {

    @Autowired
    TestRestTemplate testRestTemplate;

    public ResponseEntity&amp;lt;Users&amp;gt; 회원생성(Users users) {
        return testRestTemplate.postForEntity(&quot;/users&quot;, users, Users.class);
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;그리고 해당 DSL 을 사용하기 위해서는 해당 빈을 스캔해줘야하는데&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리 실습 같은 경우에는 @SpringTest 에 스캔할 클래스를 지정했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러므로 UserDSL 도 스캔해야하니 지정하도록 한다.&lt;/p&gt;
&lt;div style=&quot;background-color: #1e1f22; color: #bcbec4;&quot;&gt;
&lt;pre class=&quot;coffeescript&quot;&gt;&lt;code&gt;@SpringBootTest(
    classes = {CommerceApiApp.class, UserDSL.class},
    webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT
)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 테스트 코드에 회원 생성하는 부분을 DSL 로 변경한다.&lt;/p&gt;
&lt;pre class=&quot;reasonml&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;@Test
void 유저_생성(
@Autowired UserDSL userDSL){
    // Arrange
    Users users = UserFixture.createUser();

    // Act
    ResponseEntity&amp;lt;Users&amp;gt; response = userDSL.회원생성(users);
    
    // Assert
    assertThat(response.getStatusCode().value()).isEqualTo(200);
    assertThat(response.getBody()).satisfies(this::assertName);
    assertThat(response.getBody()).satisfies(this::assertPassword);
}&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;이렇게 변경하면 행위에 대한 부분을 알기 쉽게 표현하여 가독성이 좋아진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이처럼 데이터를 미리 셋팅하고 준비하는것이 TestFixture 라고 하면,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;테스트 코드 케이스 중 행위에 대한 반복이 이뤄 지게 되는데, 이를 누구나 알기 쉽게 정의 해두는것은 Test DSL 이라고 한다.&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;b&gt;데이터 준비는 Fixture&lt;/b&gt;, &lt;b&gt;행동은 DSL&lt;/b&gt;, &lt;b&gt;검증은 테스트 본문&lt;/b&gt;에 두는 것이다.&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 100%;&quot;&gt;src&lt;br /&gt;&amp;nbsp;└─&amp;nbsp;test&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;└─&amp;nbsp;java&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;├─&amp;nbsp;fixture&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;&amp;nbsp;├─&amp;nbsp;UserFixture&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;&amp;nbsp;└─&amp;nbsp;OrderFixture&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;├─&amp;nbsp;dsl&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;&amp;nbsp;├─&amp;nbsp;UserApiDsl&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│&amp;nbsp;&amp;nbsp;&amp;nbsp;└─&amp;nbsp;OrderApiDsl&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;│&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;└─&amp;nbsp;user&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;└─&amp;nbsp;UserApiTest&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;유저 생성 관련해서 Fixture 를 아래와 같이 둔다. 보면 데이터 준비 관련 내용이다.&lt;/p&gt;
&lt;pre id=&quot;code_1772948439832&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class UserFixture {

    public static UserCreateRequest 회원가입요청내용() {
        return new UserCreateRequest(
                &quot;tester&quot;,
                &quot;tester@test.com&quot;,
                &quot;password123&quot;
        );
    }

}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1772948203643&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class OrderFixture {

    public static OrderCreateRequest 주문요청내용(Long userId) {
        return new OrderCreateRequest(
                userId,
                &quot;상품1&quot;,
                2
        );
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DSL의 경우 테스트에 대한 행위를 둔다.&lt;/p&gt;
&lt;pre id=&quot;code_1772948470149&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Component
public class UserApiDsl {

    private final TestRestTemplate restTemplate;

    public UserApiDsl(TestRestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

    public UserResponse 회원가입(UserCreateRequest request) {
        return restTemplate.postForObject(
                &quot;/users&quot;,
                request,
                UserResponse.class
        );
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1772948298338&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Component
public class OrderApiDsl {

    private final TestRestTemplate restTemplate;

    public OrderApiDsl(TestRestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

    public OrderResponse 주문생성(OrderCreateRequest request) {
        return restTemplate.postForObject(
                &quot;/orders&quot;,
                request,
                OrderResponse.class
        );
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 테스트 코드를 아래와 같이 작성 할 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1772948312115&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Test
void 주문_생성시_상품명_정상리턴() {
	
    UserCreateRequest request = UserFixture.회원가입요청내용();
    
    UserResponse user = userApiDsl.회원가입(request);

    OrderCreateRequest orderRequest =
            OrderFixture.주문요청내용(user.getId());

    OrderResponse order =
            orderApiDsl.주문생성(orderRequest);

    assertThat(order.getProductName()).isEqualTo(&quot;상품1&quot;);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가독성 좋은 코드가 되며, 대상 데이터 준비는 Fixture, 행위 관련 내용은 DSL 에 정의 되어 있는것을 알 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 테스트를 하다 보면 다양한 입력값이 필요하다.&lt;br /&gt;이때 매번 값을 직접 만드는 것은 번거롭기 때문에 임의 값 생성 클래스를 만들어 사용하는 것이 좋다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;패스워드와 이름을 자동 생성하는 제너레이터를 만든다.&lt;/p&gt;
&lt;div style=&quot;background-color: #1e1f22; color: #bcbec4;&quot;&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;package test.commerce.ganerator;

import java.util.UUID;

public class DataGenerator {
    public static String randomPassword() {
        return UUID.randomUUID() + &quot;Password!&quot;;
    }

    public static String randomName() {
        return &quot;user-&quot; + UUID.randomUUID();
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;그리고 Fixture 에 매개변수를 받으면 해당 매개변수로 생성, 그렇지 않으면 랜덤 생성하는 메서드를 만든다.&lt;/p&gt;
&lt;div style=&quot;background-color: #1e1f22; color: #bcbec4;&quot;&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;package test.commerce.fixture;

import commerce.command.Users;
import test.commerce.ganerator.DataGenerator;

public class UserFixture {

    public static Users createUser() {
        return Users.builder()
            .name(DataGenerator.randomName())
            .id(&quot;test&quot;)
            .password(DataGenerator.randomPassword())
            .build();
    }

    public static Users createUser(String name, String password) {
        return Users.builder()
            .name(name)
            .id(&quot;test&quot;)
            .password(password)
            .build();
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 테스트 코드를 아래와 같이 돌리면&lt;/p&gt;
&lt;div style=&quot;background-color: #1e1f22; color: #bcbec4;&quot;&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;@Test
void 유저_생성(){
    // Arrange
    Users users = UserFixture.createUser();

    // Act
    ResponseEntity&amp;lt;Users&amp;gt; response = userDSL.회원생성(users);

    // Assert
    assertThat(response.getStatusCode().value()).isEqualTo(200);
    assertThat(response.getBody()).isNotNull();
    assertThat(response.getBody()).isNotNull();
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정상으로 돌아가는것을 볼 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1178&quot; data-origin-height=&quot;450&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/CScId/dJMcacI4kfr/2wBl8kxyUzbsenlSPfCtL1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/CScId/dJMcacI4kfr/2wBl8kxyUzbsenlSPfCtL1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/CScId/dJMcacI4kfr/2wBl8kxyUzbsenlSPfCtL1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCScId%2FdJMcacI4kfr%2F2wBl8kxyUzbsenlSPfCtL1%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;500&quot; height=&quot;191&quot; data-origin-width=&quot;1178&quot; data-origin-height=&quot;450&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 @BeforeEach 와 @BeforeAll 에 대해서 알아보자!&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;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;어노테이션&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;실행 시점&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;특징&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;@BeforeEach&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span&gt;각 &lt;/span&gt;&lt;span&gt;테스트 &lt;/span&gt;&lt;span&gt;메서드 &lt;/span&gt;&lt;span&gt;실행 &lt;/span&gt;&lt;span&gt;전에 &lt;/span&gt;&lt;span&gt;매번 &lt;/span&gt;&lt;span&gt;실행&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span&gt;테스트마다 &lt;/span&gt;&lt;span&gt;초기 &lt;/span&gt;&lt;span&gt;상태를 &lt;/span&gt;&lt;span&gt;만들어줌&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;@BeforeAll&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span&gt;테스트 &lt;/span&gt;&lt;span&gt;클래스 &lt;/span&gt;&lt;span&gt;시작 &lt;/span&gt;&lt;span&gt;전에 &lt;/span&gt;&lt;span&gt;딱 &lt;/span&gt;&lt;span&gt;한 &lt;/span&gt;&lt;span&gt;번 &lt;/span&gt;&lt;span&gt;실행&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span&gt;공통 &lt;/span&gt;&lt;span&gt;리소스 &lt;/span&gt;&lt;span&gt;초기화 (&lt;/span&gt;&lt;span&gt;DB &lt;/span&gt;&lt;span&gt;연결 &lt;/span&gt;&lt;span&gt;등)&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 예시를 통해 알아보자!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;@BeforeEach 는 매번 실행하는 코드로 매번 계산해야하는 코드가 있다면 아래와 같이 setup 메소드에 어노테이션을 붙인다.&lt;/p&gt;
&lt;pre id=&quot;code_1773455274587&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

class CalculatorTest {

    Calculator calculator;

    @BeforeEach
    void setUp() {
        calculator = new Calculator();
        System.out.println(&quot;BeforeEach 실행&quot;);
    }

    @Test
    void addTest() {
        System.out.println(&quot;addTest 실행&quot;);
    }

    @Test
    void subtractTest() {
        System.out.println(&quot;subtractTest 실행&quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실행을 하면 아래와 같이 로그가 찍히며 테스트 케이스 실행 될때 마다 실행 되는부분을 확인 할 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1773455373077&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;BeforeEach 실행
addTest 실행

BeforeEach 실행
subtractTest 실행&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 @BeforeAll 에 대해서 알아보자!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 DB 연결을 하는 코드 정의가 필요하다고 해보자..! 우선 BeforeAll 어노테이션을 붙이기 위해서는 static 메소드로 정의해야 실행 가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;static 으로 정의 하지 않을시 아래와 같이 빨간줄이 뜨는것을 볼 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;474&quot; data-origin-height=&quot;238&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/TvwaB/dJMcadBbHYx/RqZBkHW3gIGiwNc4CbXwSK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/TvwaB/dJMcadBbHYx/RqZBkHW3gIGiwNc4CbXwSK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/TvwaB/dJMcadBbHYx/RqZBkHW3gIGiwNc4CbXwSK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FTvwaB%2FdJMcadBbHYx%2FRqZBkHW3gIGiwNc4CbXwSK%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;300&quot; height=&quot;151&quot; data-origin-width=&quot;474&quot; data-origin-height=&quot;238&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래와 같이 DB 연결 코드는 @BeforeAll 로 한번 실행 되도록 하고 setup 은 매번 셋팅 되도록 @BeforeEach 로 실행한다면&lt;/p&gt;
&lt;pre id=&quot;code_1773455460971&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class UserServiceTest {

    static Database db;
    UserService userService;

    @BeforeAll
    static void initDB() {
        db = new Database(); // DB 연결
        System.out.println(&quot;BeforeAll 실행&quot;);
    }

    @BeforeEach
    void setUp() {
        userService = new UserService(db); // 테스트용 객체 생성
        System.out.println(&quot;BeforeEach 실행&quot;);
    }
    
    @Test
    void addTest() {
        System.out.println(&quot;addTest 실행&quot;);
    }

    @Test
    void subtractTest() {
        System.out.println(&quot;subtractTest 실행&quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래와 같이 로그가 찍히는것을 볼 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1773455562192&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;BeforeAll 실행

BeforeEach 실행
addTest 실행

BeforeEach 실행
subtractTest 실행&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;끝!&lt;/p&gt;</description>
      <category>JAVA</category>
      <author>코린이s</author>
      <guid isPermaLink="true">https://co-de.tistory.com/259</guid>
      <comments>https://co-de.tistory.com/259#entry259comment</comments>
      <pubDate>Sun, 8 Mar 2026 15:25:24 +0900</pubDate>
    </item>
    <item>
      <title>[TDD] SpringBoot 를 통한 TDD 손쉬운 작성 - 03) 테스트 코드 품질 높이기! - 01</title>
      <link>https://co-de.tistory.com/258</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;680&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/DjEmA/dJMcaf6CN5w/c2QKpgqlDSzLWZAKlqM4a0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/DjEmA/dJMcaf6CN5w/c2QKpgqlDSzLWZAKlqM4a0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/DjEmA/dJMcaf6CN5w/c2QKpgqlDSzLWZAKlqM4a0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDjEmA%2FdJMcaf6CN5w%2Fc2QKpgqlDSzLWZAKlqM4a0%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;500&quot; height=&quot;332&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;680&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;실무에서 테스트 코드를 작성하다 보면 반복 되는 코드가 많거나 가독성이 떨어지는 경우가 많다.&lt;br /&gt;이런 테스트 코드의 품질을 높이기 위한 방법이 있다!&lt;br /&gt;아래 방법을 통해 개선 작업을 진행해보자!&lt;br /&gt;&lt;b&gt;1) assertThat().satisfies()&lt;/b&gt;&lt;br /&gt;satisfies 를 사용하면 아래와 같은 경우 사용 가능하다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;해당 여러 검증 코드를 하나로 묶을 때&lt;/li&gt;
&lt;li&gt;자유롭게 검증 코드를 작성하기 위해&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예시를 통해 알아보자!&lt;br /&gt;우선 간단한 회원 가입 로직을 만들어보자!&lt;br /&gt;간단한 API 를 만들기 위해 필요한 라이브러리는 아래와 같다.&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;dependencies {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;implementation(&quot;org.springframework.boot:spring-boot-starter-web&quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;implementation(&quot;org.springframework.boot:spring-boot-starter-data-jpa&quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;compileOnly(&quot;org.projectlombok:lombok&quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;runtimeOnly(&quot;com.h2database:h2&quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;annotationProcessor(&quot;org.projectlombok:lombok&quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;testImplementation(&quot;org.springframework.boot:spring-boot-starter-test&quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;testRuntimeOnly(&quot;org.junit.platform:junit-platform-launcher&quot;)
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;간단한 유저 엔티티를 정의 하고&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
@Builder
@Getter
@Entity
public class Users {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@Id
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;String id;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;String name;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;String password;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Repository 를 만들자&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;@Repository
public interface UserRespository extends JpaRepository&amp;lt;Users, Integer&amp;gt; {
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 '/users' 를 post 로 호출시 데이터가 저장 될 수 있도록 controller 에 정의 한다. (예시기에 contoller 에 로직을 작성한다.)&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;@RestController
public class TestController {

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@Autowired
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;UserRespository userRespository;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@PostMapping(&quot;/users&quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public ResponseEntity&amp;lt;Users&amp;gt; user(@RequestBody Users users) {

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Users response = userRespository.save(users);

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return ResponseEntity.ok().body(response);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br /&gt;이제 검증 로직을 작성해보자.&lt;br /&gt;여러 검증 코드를 하나로 묶기전에 아래와 같은 코드가 될 수 있다.&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;@Test
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;void 비밀번호검증(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@Autowired TestRestTemplate client
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// Arrange
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Users users = Users.builder()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.name(&quot;코린이&quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.id(&quot;test&quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.password(&quot;test&quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.build();

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// Act
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ResponseEntity&amp;lt;Users&amp;gt; response = client.postForEntity(&quot;/users&quot;, users, Users.class);

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// Assert
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;assertThat(response.getStatusCode().value()).isEqualTo(200);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;assertThat(response.getBody()).isNotNull();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;assertThat(response.getBody().getName()).isEqualTo(&quot;코린이&quot;);

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 코드를 가독성을 위해 같은 코드 끼리 묶어 보자!&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;@Test
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;void 비밀번호검증(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@Autowired TestRestTemplate client
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// Arrange
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Users users = Users.builder()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.name(&quot;코린이&quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.id(&quot;test&quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.password(&quot;test&quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.build();

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// Act
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ResponseEntity&amp;lt;Users&amp;gt; response = client.postForEntity(&quot;/users&quot;, users, Users.class);

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// Assert
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;assertThat(response.getStatusCode().value()).isEqualTo(200);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;assertThat(response).satisfies(res -&amp;gt; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;assertThat(res.getBody()).isNotNull();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;assertThat(res.getBody().getName()).isEqualTo(&quot;코린이&quot;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;});
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상태코드 검증은 따로 두고,&amp;nbsp;body 검증은 하나로 묶어서 표현했다.&lt;br /&gt;이를 통해 상태코드는 200 이여야 하고 ,, body 내용 관련 정책은 이게 맞아야 하는구나 한눈에 알 수 있다.&lt;br /&gt;예시는 복잡하지 않으니 크게 느껴지지 않으나 많은 정책이 들어간다고 하면 관련 있는것끼리 묶었을때 가독성이 훨씬 좋아 질 것이다.&lt;br /&gt;satisfies 는 내부에 자유롭게 코드를 작성할 수 있으므로, 아래와 같이 검증 관련 메소드를 따로 빼서 사용 가능하다.&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;@Test
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;void 비밀번호검증(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@Autowired TestRestTemplate client
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// Arrange
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Users users = Users.builder()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.name(&quot;코린이&quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.id(&quot;test&quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.password(&quot;test&quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.build();

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// Act
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ResponseEntity&amp;lt;Users&amp;gt; response = client.postForEntity(&quot;/users&quot;, users, Users.class);

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;// Assert
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;assertThat(response.getStatusCode().value()).isEqualTo(200);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;assertThat(response.getBody()).satisfies(this::assertName);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;assertThat(response.getBody()).satisfies(this::assertPassword);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;private void assertName(Users users) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;assertThat(users.getName()).isNotNull();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;assertThat(users.getName()).isEqualTo(&quot;코린이&quot;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;private void assertPassword(Users users) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;assertThat(users.getPassword()).isNotNull();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;assertThat(users.getPassword()).matches( p -&amp;gt; p.length() &amp;gt;= 4);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보기 좋게 칼럼 별 검증 로직은 따로 메소드로 빼서 표현하게 된다면 이게 어떤 코드구나 네이밍으로 정리되어 가독성이 좋다.&lt;br /&gt;&lt;b&gt;2) 테스트 클래스 어노테이션 추상화&lt;/b&gt;&lt;br /&gt;이제 어노테이션으로 테스트 클래스의 반복 되는 부분을 줄여 보자!&lt;br /&gt;우리는 보통 테스트 코드를 작성할때,&lt;br /&gt;테스트로 돌아가기 위한 @SpringBootTest 정의,&lt;br /&gt;테스트 코드에서 repository 로 데이터 조작시 원복을 위한 @Transactional,&lt;br /&gt;특정 환경으로 돌아가게 하기 위한 @ActiveProfiles 를 작성한다.&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;@Transactional
@SpringBootTest(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;classes = CommerceApiApp.class,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT
)
@ActiveProfiles(&quot;test&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 코드는 테스트 코드를 작성할때마다 필요하므로 해당 코드를 어노테이션으로 만들어 재사용 해보자!&lt;br /&gt;어노테이션은 @Retention 과 @Target 어노테이션으로 만들수 있다.&lt;br /&gt;Retention 은 언제까지 해당 정보를 유지 할지 결정 하는것으로&lt;br /&gt;Source 는 컴파일 후 사라지고, Class 는 class 파일로 존재, Runtion 으로 하면 실행중에도 유지 되도록 할 수 있다.&lt;br /&gt;여기서는 실행중에도 동작 해야 하므로 Runtime 으로 설정 한다.&lt;br /&gt;다른 경우는 사실 어떤 경우에 사용하는지 감이 안잡힌다.. 나중에 어노테이션을 만들 경우가 있을경우 사용하면서 익히도록 해보자.&lt;br /&gt;그리고 @Target 의 경우 이 어노테이션을 어디에 붙일지 이다.&lt;br /&gt;- 클래스면 type&lt;br /&gt;- 메서드 : method&lt;br /&gt;- field : 필드&lt;br /&gt;- parameter : 파라미터&lt;br /&gt;우리는 테스트 클래스 상단에 붙일 예정이니 type으로 지정 한다.&lt;br /&gt;이제 위에 결정한대로 아래와 같이 UserServiceTest 어노테이션을 만들어 보자!&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Transactional
@SpringBootTest(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;classes = CommerceApiApp.class,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT
)
@ActiveProfiles(&quot;test&quot;)
public @interface UserServiceTest {
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 Test 클래스에 가서 @UserServiceTest 어노테이션을 붙여 본다.&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;@UserServiceTest
@DisplayName(&quot;POST /user&quot;)
public class POST_specs {&lt;/code&gt;&lt;/pre&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;842&quot; data-origin-height=&quot;336&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tYxee/dJMcaaj6p7c/sDlRn9FkN4H22VItGzfWM1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tYxee/dJMcaaj6p7c/sDlRn9FkN4H22VItGzfWM1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tYxee/dJMcaaj6p7c/sDlRn9FkN4H22VItGzfWM1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtYxee%2FdJMcaaj6p7c%2FsDlRn9FkN4H22VItGzfWM1%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;500&quot; height=&quot;200&quot; data-origin-width=&quot;842&quot; data-origin-height=&quot;336&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3) @MethodSource&lt;/b&gt;&lt;br /&gt;이제 우리가 전 시간에 배운 @ParameterizedTest 와 @ValueSource 를 보자!&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;@ParameterizedTest
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@ValueSource(strings = {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&quot;1243&quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&quot;*&amp;amp;^%&quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&quot;test1234&quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;})&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;@ValueSource 에 테스트 변수를 여러 곳에서 사용한다면 한번에 해당 소스를 정의해두고 재 사용하면 코드가 간단해진다.&lt;br /&gt;그렇게 처리 할 수 있는것이 MethodSource 이다!&lt;br /&gt;예시를 통해 알아보자!&lt;br /&gt;@ValuseSource 에 있던 패스워드를 아래와 같이 UserSource 라는 클래스를 만들어&lt;br /&gt;VaildPasswords 라는 static 메서드를 만든다. (@methodSource 에는 static 만 허용 한다.)&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;public class UserSource {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;static Stream&amp;lt;Arguments&amp;gt; validPasswords () {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return Stream.of(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Arguments.of(&quot;1243&quot;, false),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Arguments.of(&quot;*&amp;amp;^%&quot;, false),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Arguments.of(&quot;test1234&quot;, true)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫번째 매개 변수에는 패스워드를 넣고 두번째는 기대하는 검증 결과를 적는다.&lt;br /&gt;이제 테스트 케이스로 가서 아래와 같이 경로를 적고 # 뒤에 메소드 명을 적어두고, 매개 변수로 정의한 값이 넘어 가도록 password 와 expected 를 받는다.&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@ParameterizedTest
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;@MethodSource(&quot;test.commerce.sources.UserSource#validPasswords&quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;void id_잘못된파라미터_400_리턴(String password, boolean expected, @Autowired TestRestTemplate client) {&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 테스트 코드를 실행하면 아래와 같이 2개의 파라미터가 정상적으로 넘어가는것을 볼 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1278&quot; data-origin-height=&quot;452&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cjjdPI/dJMcacoF2Dn/5LlJfUU7Ymw8LsxOy3g0Qk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cjjdPI/dJMcacoF2Dn/5LlJfUU7Ymw8LsxOy3g0Qk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cjjdPI/dJMcacoF2Dn/5LlJfUU7Ymw8LsxOy3g0Qk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcjjdPI%2FdJMcacoF2Dn%2F5LlJfUU7Ymw8LsxOy3g0Qk%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;500&quot; height=&quot;177&quot; data-origin-width=&quot;1278&quot; data-origin-height=&quot;452&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 방식을 쓰면 여러 테스트 코드에서 동일하게 사용하는 케이스를 미리 source 로 정의하여&lt;br /&gt;반복하게 사용하는곳에 재 사용하며 코드를 간결하게 작성 할 수 있다.&lt;/p&gt;</description>
      <category>JAVA</category>
      <author>코린이s</author>
      <guid isPermaLink="true">https://co-de.tistory.com/258</guid>
      <comments>https://co-de.tistory.com/258#entry258comment</comments>
      <pubDate>Mon, 2 Mar 2026 08:15:12 +0900</pubDate>
    </item>
    <item>
      <title>[TDD] SpringBoot 를 통한 TDD 손쉬운 작성 - 02) TDD 작성 해보기!</title>
      <link>https://co-de.tistory.com/257</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;680&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/DjEmA/dJMcaf6CN5w/c2QKpgqlDSzLWZAKlqM4a0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/DjEmA/dJMcaf6CN5w/c2QKpgqlDSzLWZAKlqM4a0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/DjEmA/dJMcaf6CN5w/c2QKpgqlDSzLWZAKlqM4a0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDjEmA%2FdJMcaf6CN5w%2Fc2QKpgqlDSzLWZAKlqM4a0%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;500&quot; height=&quot;332&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;680&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot; data-start=&quot;1087&quot; data-end=&quot;1106&quot;&gt;TDD 를 예시를 통해 알아보자 !&lt;/h2&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;1153&quot; data-end=&quot;1172&quot;&gt;우리는 회원관리 시스템을 만든다고 하자! 그 중 유저 생성 API 로 TDD 를 수행해보자!&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot; data-start=&quot;1153&quot; data-end=&quot;1172&quot;&gt;1) 테스트 시나리오 작성&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;1174&quot; data-end=&quot;1205&quot;&gt;- 유저 생성 API 호출하여 정상 처리시 상태 코드 200을 리턴한다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;1174&quot; data-end=&quot;1205&quot;&gt;- 유저 생성 API 호출시 이름, ID, 패스워드 정보를 전달 받으며 이 중 하나라도 없다면 상태 코드 400을 리턴한다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;1174&quot; data-end=&quot;1205&quot;&gt;- 이름 파라미터는 세자리이며 맞지 않을 경우 상태코드 400을 리턴한다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;1174&quot; data-end=&quot;1205&quot;&gt;- ID 파라미터는 영어로만 이뤄지며 맞지 않을 경우 상태코드 400을 리턴한다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;1174&quot; data-end=&quot;1205&quot;&gt;- 패스워드 파라미터는 영문자 숫자로 이뤄지며 최소 4자리 이상이여야 하며 맞지 않을 경우 상태코드 400을 리턴한다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; data-start=&quot;1207&quot; data-end=&quot;1210&quot; /&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot; data-start=&quot;1212&quot; data-end=&quot;1230&quot;&gt;2) API 설계 문서화&lt;/h3&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot; data-start=&quot;1232&quot; data-end=&quot;1248&quot;&gt;요청 정보&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot; data-start=&quot;1250&quot; data-end=&quot;1294&quot;&gt;
&lt;li data-start=&quot;1250&quot; data-end=&quot;1264&quot;&gt;메서드 : POST&lt;/li&gt;
&lt;li data-start=&quot;1265&quot; data-end=&quot;1280&quot;&gt;경로 : /user&lt;/li&gt;
&lt;li data-start=&quot;1281&quot; data-end=&quot;1287&quot;&gt;헤더 :&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;Content-Type: application/json&lt;/span&gt;&lt;/li&gt;
&lt;li data-start=&quot;1288&quot; data-end=&quot;1294&quot;&gt;본문 :&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1771326465990&quot; class=&quot;crmsh&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;User {
  name: string,
  id : string,
  password: string
}&lt;/code&gt;&lt;/pre&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot; data-start=&quot;1296&quot; data-end=&quot;1312&quot;&gt;성공 응답&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot; data-start=&quot;1314&quot; data-end=&quot;1342&quot;&gt;
&lt;li data-start=&quot;1314&quot; data-end=&quot;1342&quot;&gt;상태 코드 :&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;200 Ok&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot; data-start=&quot;1344&quot; data-end=&quot;1357&quot;&gt;정책&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot; data-start=&quot;1359&quot; data-end=&quot;1401&quot;&gt;
&lt;li data-start=&quot;1359&quot; data-end=&quot;1378&quot;&gt;name 파라미터는 3자 이여야 한다.&lt;/li&gt;
&lt;li data-start=&quot;1379&quot; data-end=&quot;1401&quot;&gt;id 파라미터는 영어로만 이뤄져야 한다.&lt;/li&gt;
&lt;li data-start=&quot;1379&quot; data-end=&quot;1401&quot;&gt;password 파라미터는 영문 또는 숫자로 구성되며 4자리 이상이여야 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot; data-start=&quot;1403&quot; data-end=&quot;1420&quot;&gt;테스트 항목&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot; data-start=&quot;1422&quot; data-end=&quot;1492&quot;&gt;
&lt;li data-start=&quot;1422&quot; data-end=&quot;1438&quot;&gt;정상 요청 &amp;rarr; 200 반환&lt;/li&gt;
&lt;li data-start=&quot;1439&quot; data-end=&quot;1459&quot;&gt;파라미터 없음 &amp;rarr; 400 반환&lt;/li&gt;
&lt;li data-start=&quot;1460&quot; data-end=&quot;1476&quot;&gt;형식 오류 &amp;rarr; 400 반환&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-end=&quot;1210&quot; data-start=&quot;1207&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot; data-start=&quot;1532&quot; data-end=&quot;1568&quot;&gt;3) 테스트 코드 작성&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot; data-start=&quot;1655&quot; data-end=&quot;1674&quot;&gt;&lt;b&gt;AAA 패턴&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;1676&quot; data-end=&quot;1709&quot;&gt;테스트 코드는 보통 Arrange - Act - Assert(&lt;b&gt;AAA) 패턴&lt;/b&gt;으로 작성한다.&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 76px;&quot; border=&quot;1&quot; data-ke-style=&quot;style12&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;width: 25%; height: 19px;&quot;&gt;명칭&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 19px;&quot;&gt;내용&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;width: 25%; height: 19px;&quot;&gt;Arrange(구성)&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 19px;&quot;&gt;&lt;span&gt;테스트용 데이터 준비&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;width: 25%; height: 19px;&quot;&gt;Act(실행)&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 19px;&quot;&gt;&lt;span&gt;테스트 대상 실행&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;width: 25%; height: 19px;&quot;&gt;Assert(검증)&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 19px;&quot;&gt;&lt;span&gt;결과 검증&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;우선 요청 파라미터를 담을 Recode 를 만든다!&lt;/p&gt;
&lt;pre id=&quot;code_1771326465991&quot; class=&quot;delphi&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;public record User(
    String name,
    String id,
    String password
) {
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;그리고 테스트 시나리오대로 테스트 케이스를 만든다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;우선 첫번째 시나리오인 성공시 200을 리턴하는 &lt;u&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;테스트 케이스를 작성 하였다.&lt;/b&gt;&lt;/span&gt;&lt;/u&gt;&lt;/p&gt;
&lt;pre class=&quot;java&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;// [1] SpringBootTest
@SpringBootTest(
    classes = [테스트대상클래스명].class,
    webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT
)
// [2] DisplayName
@DisplayName(&quot;POST /user&quot;)
public class POST_specs {

// [3] Test
    @Test
    void 성공시_200_리턴(
        @Autowired TestRestTemplate client
    ) {
        // [4] Arrange
        User user = new User(
            &quot;corin&quot;,
            &quot;test&quot;,
            &quot;test&quot;
        );

        // [5] Act
        ResponseEntity&amp;lt;Void&amp;gt; response = client.postForEntity(
            &quot;/user&quot;,
            user,
            Void.class
        );

        // [6] Assert
        assertThat(response.getStatusCode().value()).isEqualTo(200);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;하나씩 보자!&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;[1] @SpringBootTest 어노테이션&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;해당 어노테이션은 Spring Boot 환경에서 테스트를 실행하도록 설정하는 부분이다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- classes 옵션&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;미지정 시 전체 빈 스캔하게 되어 모든 컨텍스트를 스캔, 빈 생성 하기에 로딩 시간을 줄이고 싶다면&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;테스트 진행 대상만 클래스를 지정하여 필요한 빈만 로딩하여 테스트 속도를 향상 할 수 있다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT 옵션&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;테스트 실행시 랜덤 포트로 실행 되도록 하여 테스트 실행시 사용중인 포트 이외 포트를 사용하여 테스트 실행 오류를 방지 한다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;[2] @DisplayName 어노테이션&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;테스트 결과 화면에 표시되는 이름을 설정 하는 어노테이션으로 HTTP 메서드명, API 주소를 표기하여 어떤 테스트 인지 알 수 있도록 한다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;[3] @Test 어노테이션&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;메서드에 @Test 를 붙여 테스트 메서드로 동작하도록 한다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;[4] TestRestTemplate 활용&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Spring Boot Test에서는 Http 요청 관련 테스트를 위한 TestRestTemplate을 제공한다. RestTemplate 가 아닌 Test 에서 제공하는 클래스를 이용하면 테스트에 용이하게 정의 되어있어 (예 : 500 에러 시 예외 대신 응답 반환) Http 관련 테스트 진행시 해당 클래스를 이용한다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-end=&quot;2873&quot; data-start=&quot;2847&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;[5] Arrange 단계&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size18&quot; data-end=&quot;2873&quot; data-start=&quot;2847&quot;&gt;정의 단계로, API 요청 파라미터인 User를 정의 한다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-end=&quot;2873&quot; data-start=&quot;2847&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;[6] Act 단계&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size18&quot; data-end=&quot;2873&quot; data-start=&quot;2847&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;실행 단계로, TestRestTemplate 를 이용하여 /user API 로 Post 호출 하며 실행 결과를 얻어온다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-end=&quot;2873&quot; data-start=&quot;2847&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;[7] Assert 단계&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-end=&quot;2873&quot; data-start=&quot;2847&quot;&gt;검증 단계로, 보통 SpringBootTest 에 포함 되어 있는 AssertJ 라이브러리를 사용하여 검증을 코드로 구현한다.&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-end=&quot;2873&quot; data-start=&quot;2847&quot;&gt;아래 코드는 http 상태코드를 받아 200이면 테스트 검증 통과 처리 하며 아니라면 실패 처리 한다.&lt;/p&gt;
&lt;pre id=&quot;code_1771326465993&quot; class=&quot;reasonml&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;assertThat(response.getStatusCode().value()).isEqualTo(200);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;u&gt;해당 테스트 실행 결과를 보자 !!&lt;/u&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;아래와 같이 왼쪽 박스 부분을 보면, DisplayName 에 정의한 내용과 메서드 명이 표기 되어 어떤 테스트인지 한눈에 알 수 있다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;그리고 테스트 결과는 '초록색'이 아닌 '노란색 X 박스'로 표기 되어 검증 실패임을 알 수 있고,&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;그 원인을 오른쪽 박스의 오류 로그를 보면,&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;테스트 코드로 작성한 '상태 코드 200' 이기대한 값이지만 404로 나와 검증 실패 되었음을 알 수 있다!&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;&lt;u&gt;이렇게 켄트 백의 TDD 중 Red 부분 작성이 완료 되었다!&lt;/u&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2064&quot; data-origin-height=&quot;552&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pKsm7/dJMcaaYxMwV/RfPQLBxEWCYKqFXRHk12Ek/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pKsm7/dJMcaaYxMwV/RfPQLBxEWCYKqFXRHk12Ek/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pKsm7/dJMcaaYxMwV/RfPQLBxEWCYKqFXRHk12Ek/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpKsm7%2FdJMcaaYxMwV%2FRfPQLBxEWCYKqFXRHk12Ek%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;2064&quot; height=&quot;552&quot; data-origin-width=&quot;2064&quot; data-origin-height=&quot;552&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;&lt;u&gt;이제 Green 단계를 진행해보자!&lt;/u&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;해당 코드가 통과 할 수 있는 코드를 작성하면 된다. 아래 조건을 만족하면 200을 리턴하면 된다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1401&quot; data-start=&quot;1359&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1378&quot; data-start=&quot;1359&quot;&gt;name 파라미터는 3자 이여야 한다.&lt;/li&gt;
&lt;li data-end=&quot;1401&quot; data-start=&quot;1379&quot;&gt;id 파라미터는 영어로만 이뤄져야 한다.&lt;/li&gt;
&lt;li data-end=&quot;1401&quot; data-start=&quot;1379&quot;&gt;password 파라미터는 영문 또는 숫자로 구성되며 4자리 이상이여야 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이제 200이 나올 수 있도록 작성을 해보자!&lt;/p&gt;
&lt;pre id=&quot;code_1771326465994&quot; class=&quot;less&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;@PostMapping(&quot;/user&quot;)
    public ResponseEntity&amp;lt;?&amp;gt; user(@RequestBody User user) {
        if (user.name().length() == 3 &amp;amp;&amp;amp; user.id().matches(&quot;^[a-zA-Z]*$&quot;) &amp;amp;&amp;amp; user.password().matches(&quot;^[a-zA-Z0-9]{4,}$&quot;)) {
            return ResponseEntity.ok().build();
        }
        return ResponseEntity.badRequest().build();
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;돌려보면 정상적으로 패스 한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;728&quot; data-origin-height=&quot;408&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bEl4Ps/dJMcadt93CG/5iWsL0AW07s4S4DkpYmgLK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bEl4Ps/dJMcadt93CG/5iWsL0AW07s4S4DkpYmgLK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bEl4Ps/dJMcadt93CG/5iWsL0AW07s4S4DkpYmgLK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbEl4Ps%2FdJMcadt93CG%2F5iWsL0AW07s4S4DkpYmgLK%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;300&quot; height=&quot;168&quot; data-origin-width=&quot;728&quot; data-origin-height=&quot;408&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;여기까지 하면 Green 단계 한 사이클을 완료한 것이다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이제 다음 케이스인 '파라미터 없음 &amp;rarr; 400 반환'를 만들어 나머지 Red + Green 단계 진행 해보자!&lt;/p&gt;
&lt;pre id=&quot;code_1771326465994&quot; class=&quot;pgsql&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;@Test
    void 파라미터없을시_400_리턴(@Autowired TestRestTemplate client) {

        // Arrange
        User user = new User(
            null,
            null,
            null
        );

        // Act
        ResponseEntity&amp;lt;Void&amp;gt; response = client.postForEntity(
            &quot;/user&quot;,
            user,
            Void.class
        );

        // Assert
        assertThat(response.getStatusCode().value()).isEqualTo(400);
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이렇게 해서 돌리게 되면 실패하게 되고&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1404&quot; data-origin-height=&quot;602&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b27Tlk/dJMcaca1OCY/ocBK2NzwGoDCldoTK6YEf1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b27Tlk/dJMcaca1OCY/ocBK2NzwGoDCldoTK6YEf1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b27Tlk/dJMcaca1OCY/ocBK2NzwGoDCldoTK6YEf1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb27Tlk%2FdJMcaca1OCY%2FocBK2NzwGoDCldoTK6YEf1%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;500&quot; height=&quot;214&quot; data-origin-width=&quot;1404&quot; data-origin-height=&quot;602&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;파라미터 값이 없을경우 400이 나오도록 코드를 추가한다.&lt;/p&gt;
&lt;pre id=&quot;code_1771326465995&quot; class=&quot;less&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;@PostMapping(&quot;/user&quot;)
    public ResponseEntity&amp;lt;?&amp;gt; user(@RequestBody User user) {
        if(user.name() == null || user.id() == null || user.password() == null) {
            return ResponseEntity.badRequest().build();
        }&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;그리고 돌려보면 테스트 정상 통과 한다!&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;740&quot; data-origin-height=&quot;256&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/SNxSt/dJMcafS6Sqq/KkaXYeJOaRCfvzBZ0adv71/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/SNxSt/dJMcafS6Sqq/KkaXYeJOaRCfvzBZ0adv71/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/SNxSt/dJMcafS6Sqq/KkaXYeJOaRCfvzBZ0adv71/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FSNxSt%2FdJMcafS6Sqq%2FKkaXYeJOaRCfvzBZ0adv71%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;400&quot; height=&quot;138&quot; data-origin-width=&quot;740&quot; data-origin-height=&quot;256&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;그런데 여기서 잘못된 파라미터가 넘어올시 400 리턴되는 케이스가 필요하다는 생각이 들었다.&lt;/u&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;u&gt;이러한 테스트 케이스 추가하는 작업이 Green 단계에서 이뤄진다.&lt;/u&gt;&lt;/span&gt;&lt;/b&gt; 계속해서 체크하며 좋은 테스트 케이스를 만든다!&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;그럼 실습을 위해 id 파라미터에 대해서만 테스트 케이스 추가 작업 해보도록 한다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;id 파라미터는 영어만 받기로 정했기에 '숫자, 특수문자, 영어+숫자' 를 호출했을때 400이 나오는 케이스를 추가한다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;하나의 테스트 케이스에 특정 값만 변경해서 호출하고 싶으면 '@ParameterizedTest' 와 '@ValueSource' 어노테이션을 이용하여 반복 테스트 가능하다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;id 파라미터 예시로 보자!&lt;/p&gt;
&lt;pre id=&quot;code_1771326465995&quot; class=&quot;kotlin&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;@ParameterizedTest
    @ValueSource(strings = {
        &quot;1243&quot;,
        &quot;*&amp;amp;^%&quot;,
        &quot;test1234&quot;
    })
    void id_잘못된파라미터_400_리턴(String id, @Autowired TestRestTemplate client) {

        // Arrange
        User user = new User(
            &quot;코린이&quot;,
            id,
            &quot;test&quot;
        );

        // Act
        ResponseEntity&amp;lt;Void&amp;gt; response = client.postForEntity(&quot;/user&quot;, user, Void.class);

        // Assert
        assertThat(response.getStatusCode().value()).isEqualTo(400);
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;@ValueSource 로 변경 하여 테스트 하고자 하는 값을 나열하고 테스트 매개변수 id 로 받으면 해당 값이 변경되며 호출 된다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;결과는 아래와 같으며 모든 케이스 통과 하였다!&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;752&quot; data-origin-height=&quot;498&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/m7fQX/dJMcaajX66L/xlWPk4jiu5y78na8AMKXKk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/m7fQX/dJMcaajX66L/xlWPk4jiu5y78na8AMKXKk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/m7fQX/dJMcaajX66L/xlWPk4jiu5y78na8AMKXKk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fm7fQX%2FdJMcaajX66L%2FxlWPk4jiu5y78na8AMKXKk%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;400&quot; height=&quot;265&quot; data-origin-width=&quot;752&quot; data-origin-height=&quot;498&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;&lt;u&gt;이제 Refactor 단계를 진행해보자!&lt;/u&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;작성한 코드를 보면 보기 어렵게 되어있고 좋지 않은 코드이다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이렇게 코드를 개선 하는것이 Refactor 과정이다! 아래 변경을 해보자!&lt;/p&gt;
&lt;pre id=&quot;code_1771326465996&quot; class=&quot;pgsql&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;@PostMapping(&quot;/user&quot;)
    public ResponseEntity&amp;lt;?&amp;gt; user(@RequestBody User user) {
        if(user.name() == null || user.id() == null || user.password() == null) {
            return ResponseEntity.badRequest().build();
        }

        if (user.name().length() == 3 &amp;amp;&amp;amp; user.id().matches(&quot;^[a-zA-Z]*$&quot;) &amp;amp;&amp;amp; user.password().matches(&quot;^[a-zA-Z0-9]{4,}$&quot;)) {
            return ResponseEntity.ok().build();
        }

        return ResponseEntity.badRequest().build();
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;코드를 가독성 좋게 기능을 메서드로 뺐다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1771326465996&quot; class=&quot;pgsql&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;@PostMapping(&quot;/user&quot;)
    public ResponseEntity&amp;lt;Void&amp;gt; user(@RequestBody User user) {

        if (hasEmptyParam(user)) {
            return ResponseEntity.badRequest().build();
        }

        if (!isValidUser(user)) {
            return ResponseEntity.badRequest().build();
        }

        return ResponseEntity.ok().build();
    }

    /** null 체크 */
    private boolean hasEmptyParam(User user) {
        return user.name() == null
            || user.id() == null
            || user.password() == null;
    }

    /** 유효성 검사 */
    private boolean isValidUser(User user) {
        return isValidName(user.name())
            &amp;amp;&amp;amp; isValidId(user.id())
            &amp;amp;&amp;amp; isValidPassword(user.password());
    }

    private boolean isValidName(String name) {
        return name.length() == 3;
    }

    private boolean isValidId(String id) {
        return id.matches(&quot;^[a-zA-Z]+$&quot;);
    }

    private boolean isValidPassword(String password) {
        return password.matches(&quot;^[a-zA-Z0-9]{4,}$&quot;);
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이제 테스트 케이스 모두 돌려서 모든 케이스를 통과하는지 최종 점검 한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1064&quot; data-origin-height=&quot;550&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lgwMp/dJMcad10bmx/QcXrkNrH3iyyRQ9LwbGyz0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lgwMp/dJMcad10bmx/QcXrkNrH3iyyRQ9LwbGyz0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lgwMp/dJMcad10bmx/QcXrkNrH3iyyRQ9LwbGyz0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlgwMp%2FdJMcad10bmx%2FQcXrkNrH3iyyRQ9LwbGyz0%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;500&quot; height=&quot;258&quot; data-origin-width=&quot;1064&quot; data-origin-height=&quot;550&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;u&gt;모두 통과 하였으며 TDD 마지막 단계까지 완료 하였다!&lt;/u&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style6&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot; data-start=&quot;3376&quot; data-end=&quot;3387&quot;&gt;최종 정리 !&lt;/h2&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;3389&quot; data-end=&quot;3428&quot;&gt;지금까지 TDD와 테스트 작성 방법을 정리해 보면 다음과 같다고 한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-start=&quot;3430&quot; data-end=&quot;3604&quot;&gt;TDD는 테스트 먼저 작성하고 기능 개발 하며 코드 개선하는 방식이다.&lt;/li&gt;
&lt;li data-start=&quot;3430&quot; data-end=&quot;3604&quot;&gt;Red &amp;rarr; Green &amp;rarr; Refactor 구조로 반복된다.&lt;/li&gt;
&lt;li data-start=&quot;3430&quot; data-end=&quot;3604&quot;&gt;실무에서는 하이브리드 TDD를 많이 사용한다.&lt;/li&gt;
&lt;li data-start=&quot;3430&quot; data-end=&quot;3604&quot;&gt;테스트 코드 작성시에는 AAA 패턴으로 작성 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;3430&quot; data-end=&quot;3604&quot;&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;테스트는 귀찮은 작업이 아니라,&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;3611&quot; data-end=&quot;3652&quot;&gt;미래의 나를 지켜주는 보험이라고 한다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-start=&quot;3654&quot; data-end=&quot;3677&quot; data-is-last-node=&quot;&quot; data-is-only-node=&quot;&quot;&gt;꾸준히 연습하면서 TDD에 익숙해져 보자!&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style6&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;* 참고&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-end=&quot;1568&quot; data-start=&quot;1532&quot;&gt;# Java 에서 record란 무엇인가?&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-end=&quot;3081&quot; data-start=&quot;3050&quot;&gt;record는 Java 17부터 도입된 문법으로 불변 데이터를 정의하는 VO 와 같은 객체를 정의 할때 '보일러 플레이트 코드'를 줄여준다.&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-end=&quot;3089&quot; data-start=&quot;3083&quot;&gt;특징&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;3142&quot; data-start=&quot;3091&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;3098&quot; data-start=&quot;3091&quot;&gt;불변 객체 (필드에 final 이 붙는다.)&lt;/li&gt;
&lt;li data-end=&quot;3142&quot; data-start=&quot;3113&quot;&gt;getter, 생성자(모든 변수 정의된 생성자), toString 자동 생성&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-end=&quot;3185&quot; data-start=&quot;3171&quot;&gt;보일러 플레이트란?&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot; data-end=&quot;3240&quot; data-start=&quot;3187&quot;&gt;반복적으로 작성하는 코드를 의미한다. (같은 내용을 인쇄하는 변경 불가능한 판의 이름이 보일러 플레이트다.)&lt;br /&gt;VO 같은 클래스에 자주 등장한다고 한다.&lt;/p&gt;</description>
      <category>JAVA</category>
      <author>코린이s</author>
      <guid isPermaLink="true">https://co-de.tistory.com/257</guid>
      <comments>https://co-de.tistory.com/257#entry257comment</comments>
      <pubDate>Sun, 1 Mar 2026 17:25:49 +0900</pubDate>
    </item>
    <item>
      <title>[TDD] SpringBoot 를 통한 TDD 손쉬운 작성 - 01) TDD 란 ?</title>
      <link>https://co-de.tistory.com/256</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;680&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/DjEmA/dJMcaf6CN5w/c2QKpgqlDSzLWZAKlqM4a0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/DjEmA/dJMcaf6CN5w/c2QKpgqlDSzLWZAKlqM4a0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/DjEmA/dJMcaf6CN5w/c2QKpgqlDSzLWZAKlqM4a0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDjEmA%2FdJMcaf6CN5w%2Fc2QKpgqlDSzLWZAKlqM4a0%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;500&quot; height=&quot;332&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;680&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-end=&quot;77&quot; data-start=&quot;42&quot; data-ke-size=&quot;size26&quot;&gt;테스트 주도 개발(TDD) 개념부터 실무 활용까지 알아보자!&lt;/h2&gt;
&lt;p data-end=&quot;236&quot; data-start=&quot;79&quot; data-ke-size=&quot;size16&quot;&gt;개발을 하다 보면 &amp;ldquo;테스트는 나중에 하지 뭐&amp;hellip;&amp;rdquo;라고 생각하는 경우가 많다고 한다.&lt;/p&gt;
&lt;p data-end=&quot;236&quot; data-start=&quot;79&quot; data-ke-size=&quot;size16&quot;&gt;하지만 안정적인 서비스를 만들기 위해서는 테스트가 매우 중요하다.&lt;/p&gt;
&lt;p data-end=&quot;236&quot; data-start=&quot;79&quot; data-ke-size=&quot;size16&quot;&gt;이때 등장하는 개념이 바로 TDD(Test-Driven Development) 다!&lt;/p&gt;
&lt;p data-end=&quot;236&quot; data-start=&quot;79&quot; data-ke-size=&quot;size16&quot;&gt;지금부터 하나씩 알아보자!&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-end=&quot;278&quot; data-start=&quot;243&quot; data-ke-size=&quot;size26&quot;&gt;TDD(Test-Driven Development)란?&lt;/h2&gt;
&lt;p data-end=&quot;339&quot; data-start=&quot;280&quot; data-ke-size=&quot;size16&quot;&gt;TDD는 테스트 시나리오대로 코드를 먼저 작성한 뒤,&lt;br /&gt;그 테스트를 통과시키기 위해 코드를 만들고,&lt;br /&gt;이후 리팩토링을 통해 계속해서 개선하는 개발 방법이라고 한다.&lt;/p&gt;
&lt;p data-end=&quot;414&quot; data-start=&quot;341&quot; data-ke-size=&quot;size16&quot;&gt;이 개념은 &lt;b&gt;&lt;span&gt;&lt;span&gt;켄트 벡&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;이 정립한 개발 방법론으로 알려져 있다고 한다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;481&quot; data-start=&quot;464&quot; data-ke-size=&quot;size26&quot;&gt;TDD의 3단계&amp;nbsp;&lt;/h2&gt;
&lt;p data-end=&quot;505&quot; data-start=&quot;483&quot; data-ke-size=&quot;size16&quot;&gt;TDD는 크게 3단계로 반복된다!&lt;/p&gt;
&lt;p data-end=&quot;505&quot; data-start=&quot;483&quot; data-ke-size=&quot;size16&quot;&gt;간단하게 설명하면 아래와 같다!&lt;/p&gt;
&lt;p data-end=&quot;505&quot; data-start=&quot;483&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Red &amp;rarr; 실패하는 테스트 작성&lt;/span&gt;&lt;br /&gt;&lt;span&gt;Green &amp;rarr; 최소한으로 통과&lt;/span&gt;&lt;br /&gt;&lt;span&gt;Refactor &amp;rarr; 구조 개선&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;505&quot; data-start=&quot;483&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;각각의 과정에 대한 내용을 적어보면 아래와 같이 진행한다.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 66px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 17px;&quot;&gt;이름&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 17px;&quot;&gt;내용&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 15px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 15px;&quot;&gt;Red 단계&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 15px;&quot;&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot; data-start=&quot;522&quot; data-end=&quot;591&quot;&gt;
&lt;li data-start=&quot;522&quot; data-end=&quot;539&quot;&gt;테스트 시나리오를 작성한다.&lt;/li&gt;
&lt;li data-start=&quot;540&quot; data-end=&quot;560&quot;&gt;반드시 실패하는 테스트를 만든다.&lt;/li&gt;
&lt;li data-start=&quot;561&quot; data-end=&quot;591&quot;&gt;아직 기능이 없으므로 테스트는 실패 상태라고 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 17px;&quot;&gt;Green 단계&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 17px;&quot;&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot; data-start=&quot;610&quot; data-end=&quot;688&quot;&gt;
&lt;li data-start=&quot;610&quot; data-end=&quot;644&quot;&gt;테스트를 통과할 수 있는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;최소한의 코드&lt;/b&gt;를 작성한다.&lt;/li&gt;
&lt;li data-start=&quot;645&quot; data-end=&quot;668&quot;&gt;빠진 테스트 케이스가 있다면 추가한다.&lt;/li&gt;
&lt;li data-start=&quot;669&quot; data-end=&quot;688&quot;&gt;목표는 &amp;ldquo;일단 통과&amp;rdquo;라고 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 17px;&quot;&gt;Refactor 단계&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 17px;&quot;&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot; data-start=&quot;710&quot; data-end=&quot;764&quot;&gt;
&lt;li data-start=&quot;710&quot; data-end=&quot;734&quot;&gt;코드 개선 및 구조 리팩토링을 진행한다.&lt;/li&gt;
&lt;li data-start=&quot;735&quot; data-end=&quot;764&quot;&gt;이 과정을 통해 설계를 개선한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 모든 테스트 케이스가 통과되면 테스트 작성이 종료 된다!&lt;/p&gt;
&lt;hr data-end=&quot;807&quot; data-start=&quot;804&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;833&quot; data-start=&quot;809&quot; data-ke-size=&quot;size26&quot;&gt;실무에서는 하이브리드 TDD !&lt;/h2&gt;
&lt;p data-end=&quot;897&quot; data-start=&quot;835&quot; data-ke-size=&quot;size16&quot;&gt;이론적으로는 테스트부터 작성하는 것이 이상적이라고 한다.&lt;br /&gt;하지만 실무에서는 &lt;span style=&quot;color: #666666; text-align: start;&quot;&gt;&amp;ldquo;일단 돌아가게부터 만들어 주세요&amp;hellip;&amp;rdquo;&lt;/span&gt; 라는 요구가 많을 수 있다.&lt;/p&gt;
&lt;p data-end=&quot;960&quot; data-start=&quot;923&quot; data-ke-size=&quot;size16&quot;&gt;이런 상황 때문에 테스트를 먼저 만들기 어려운 경우가 많다.&lt;/p&gt;
&lt;p data-end=&quot;991&quot; data-start=&quot;962&quot; data-ke-size=&quot;size16&quot;&gt;그래서 실무에서는 &lt;b&gt;하이브리드 TDD&lt;/b&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 data-end=&quot;991&quot; data-start=&quot;962&quot;&gt;기능 먼저 구현&lt;/li&gt;
&lt;li data-end=&quot;1036&quot; data-start=&quot;1022&quot;&gt;이후 테스트 코드 작성&lt;/li&gt;
&lt;li data-end=&quot;1050&quot; data-start=&quot;1037&quot;&gt;TDD 방식으로 보완&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-end=&quot;1106&quot; data-start=&quot;1087&quot; data-ke-size=&quot;size26&quot;&gt;TDD 단위 테스트&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;하나의 기능만 정확히 테스트하는것이 '단위 테스트'이다.&amp;nbsp;&lt;/u&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;u&gt;외부 의존성 전부 Mock / Stub 처리&lt;/u&gt; 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TDD의 80~90%는 단위 테스트로 진행하며, 각각의 단위 테스트는 서로 영향 주지 않게 작성하며 이를 '&lt;u&gt;테스트 격리&lt;/u&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;u&gt;리팩토링 안전망&lt;/u&gt;' 이라고 부른다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 단위 테스트할때 의존성의 Mock[목], Stub[스텁] 처리 한다고 하는데 해당 개념이 무엇인지 알아보자!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;Mock과 Stub&lt;/u&gt;은 모두 테스트에서 실제 DB, API, 메일 서버 대신 사용하는 &lt;u&gt;가짜 객체&lt;/u&gt;다.&lt;/p&gt;
&lt;p data-end=&quot;410&quot; data-start=&quot;403&quot; data-ke-size=&quot;size16&quot;&gt;이를 사용하는 목적은 아래와 같다!&lt;/p&gt;
&lt;blockquote data-end=&quot;465&quot; data-start=&quot;412&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;p data-end=&quot;465&quot; data-start=&quot;414&quot; data-ke-size=&quot;size16&quot;&gt;✔️ 테스트를 빠르게&lt;br /&gt;✔️ 테스트를 안정적으로&lt;br /&gt;✔️ 외부 환경에 의존하지 않게&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-end=&quot;522&quot; data-start=&quot;493&quot; data-ke-size=&quot;size16&quot;&gt;이제 가짜 객체인 Mock Stub 을 어떤 상황에 쓰는지 알아보자!&lt;/p&gt;
&lt;p data-end=&quot;522&quot; data-start=&quot;493&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Stub&lt;/b&gt; 은 값을 대신 돌려주는 객체로 &lt;b&gt;미리 정해둔 값만 반환하는 역할&lt;/b&gt;을 한다.&lt;/p&gt;
&lt;p data-end=&quot;556&quot; data-start=&quot;524&quot; data-ke-size=&quot;size16&quot;&gt;아래와 같이 적으면 userRepo 에서 kim 값을 찾으면 kim 인 User 객체를 반환하도록 모의로 셋팅 하는것이다.&lt;/p&gt;
&lt;pre id=&quot;code_1771329660476&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;when(userRepo.find(&quot;kim&quot;))
    .thenReturn(new User(&quot;kim&quot;));&lt;/code&gt;&lt;/pre&gt;
&lt;p data-end=&quot;899&quot; data-start=&quot;872&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Mock&lt;/b&gt;은 행동을 검증하는 객체로 &lt;b&gt;메서드가 호출되었는지 자체를 검증&lt;/b&gt;한다.&lt;/p&gt;
&lt;p data-end=&quot;932&quot; data-start=&quot;901&quot; data-ke-size=&quot;size16&quot;&gt;예를 들어 &amp;ldquo;회원가입하면 메일이 반드시 발송되어야 한다&amp;rdquo; 를 검증한다고 해보자!&lt;/p&gt;
&lt;p data-end=&quot;932&quot; data-start=&quot;901&quot; data-ke-size=&quot;size16&quot;&gt;아래와 같이 service.register 을 하면 mailService 에서 해당 이메일로 메일이 가도록 구현 되어있는지 로직만 검증 하는것이다.&lt;/p&gt;
&lt;pre id=&quot;code_1771329835170&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Mock
MailService mailService;  // 가짜

@InjectMocks
UserService service;       // mailService가 service에 주입됨

User user = new User(&quot;kim&quot;, &quot;a@test.com&quot;);

service.register(user);

verify(mailService).send(&quot;a@test.com&quot;);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 개념만 간단하게 알아봐서 사실 실제 작성해보지 않으면 모르겠다..!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 시간에는 실습을 통해 차근차근 TDD에 대해서 알아보자!&lt;/p&gt;</description>
      <category>JAVA</category>
      <author>코린이s</author>
      <guid isPermaLink="true">https://co-de.tistory.com/256</guid>
      <comments>https://co-de.tistory.com/256#entry256comment</comments>
      <pubDate>Mon, 16 Feb 2026 22:16:20 +0900</pubDate>
    </item>
    <item>
      <title>[코테] 재귀함수</title>
      <link>https://co-de.tistory.com/255</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;hello_kitty_recursion_zoom.gif&quot; data-origin-width=&quot;1536&quot; data-origin-height=&quot;1024&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/doWSFo/btsNs5FlB3H/8k7GjAnTxFDdZkRQKgvuAk/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/doWSFo/btsNs5FlB3H/8k7GjAnTxFDdZkRQKgvuAk/img.gif&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/doWSFo/btsNs5FlB3H/8k7GjAnTxFDdZkRQKgvuAk/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/doWSFo/btsNs5FlB3H/8k7GjAnTxFDdZkRQKgvuAk/img.gif&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;500&quot; height=&quot;333&quot; data-filename=&quot;hello_kitty_recursion_zoom.gif&quot; data-origin-width=&quot;1536&quot; data-origin-height=&quot;1024&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt; &amp;nbsp; 재귀함수에 대해서 알아보자!&lt;/h3&gt;
&lt;p data-end=&quot;240&quot; data-start=&quot;155&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;재귀함수&lt;/b&gt;란, &lt;b&gt;자기 자신을 다시 호출하는 함수&lt;/b&gt;를 말한다.&lt;br /&gt;말 그대로, 함수가 &lt;b&gt;자기 자신을 반복적으로 부르는 구조&lt;/b&gt;라고 할 수 있다!&lt;/p&gt;
&lt;p data-end=&quot;321&quot; data-start=&quot;242&quot; data-ke-size=&quot;size16&quot;&gt;재귀를 사용하면 &lt;b&gt;코드를 간결하게 표현&lt;/b&gt;할 수 있고,&lt;br /&gt;특히 &lt;b&gt;반복적인 구조&lt;/b&gt;나 &lt;b&gt;문제를 잘게 쪼개는 상황&lt;/b&gt;에서 유용하게 쓰인다.&lt;/p&gt;
&lt;h3 data-end=&quot;347&quot; data-start=&quot;328&quot; data-ke-size=&quot;size23&quot;&gt;  재귀함수는 언제 고려해야할까?&lt;/h3&gt;
&lt;p data-end=&quot;377&quot; data-start=&quot;349&quot; data-ke-size=&quot;size16&quot;&gt;재귀함수는 다음과 같은 상황에서 고려해볼 수 있다&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-end=&quot;528&quot; data-start=&quot;379&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-end=&quot;421&quot; data-start=&quot;379&quot;&gt;&lt;b&gt;반복적인 계산 구조일 때&lt;/b&gt;&lt;/li&gt;
&lt;li data-end=&quot;528&quot; data-start=&quot;479&quot;&gt;&lt;b&gt;탐색 범위를 계속 줄여야 할 때&lt;/b&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-end=&quot;557&quot; data-start=&quot;535&quot; data-ke-size=&quot;size23&quot;&gt;  재귀함수의 핵심: 탈출 조건!&lt;/h3&gt;
&lt;p data-end=&quot;704&quot; data-start=&quot;559&quot; data-ke-size=&quot;size16&quot;&gt;재귀함수를 사용할 때 가장 중요한 건 &lt;b&gt;탈출 조건&lt;/b&gt;이다!&lt;br /&gt;자기 자신을 계속 부르다 보면 &lt;b&gt;무한 루프&lt;/b&gt;에 빠질 수 있기 때문에,&lt;br /&gt;&lt;b&gt;어디선가 반드시 멈춰야 한다.&lt;/b&gt;&lt;br /&gt;이걸&amp;nbsp;&lt;b&gt;탈출 조건&lt;/b&gt;이라고 한다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h3 data-end=&quot;704&quot; data-start=&quot;559&quot; data-ke-size=&quot;size23&quot;&gt;팩토리얼 예제로 재귀를 이해해보자!&lt;/h3&gt;
&lt;p data-end=&quot;751&quot; data-start=&quot;738&quot; data-ke-size=&quot;size16&quot;&gt;팩토리얼은 &lt;b&gt;1부터 N까지의 정수를 모두 곱한 값&lt;/b&gt;을 말한다.&lt;br /&gt;3!이라면 이렇게 계산된다:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1745138000441&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;3! = 3 &amp;times; 2 &amp;times; 1 = 6&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;857&quot; data-start=&quot;841&quot; data-ke-size=&quot;size16&quot;&gt;연산 하는 방법을 수학적으로 표현하면 아래와 같다!&lt;/p&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1745138009331&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;N! = N &amp;times; (N-1) &amp;times; (N-2) ... &amp;times; 1&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-end=&quot;978&quot; data-start=&quot;923&quot; data-ke-size=&quot;size16&quot;&gt;탐색 범위가 작아지며 반복적인 구조를 가지고 있기에 재귀로 풀면 된다.&lt;/p&gt;
&lt;p data-end=&quot;978&quot; data-start=&quot;923&quot; 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 data-end=&quot;1058&quot; data-start=&quot;1004&quot;&gt;&lt;b&gt;재귀 호출 값&lt;/b&gt; : N - 1&lt;br /&gt;&amp;rarr; 한 단계 작아진 데이터로 나를 다시 호출한다.&lt;/li&gt;
&lt;li data-end=&quot;1108&quot; data-start=&quot;1060&quot;&gt;&lt;b&gt;탈출 조건&lt;/b&gt; : N == 1&lt;br /&gt;&amp;rarr; 더 이상 곱할 게 없을 때 멈춘다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 바탕으로 코드를 작성하면 아래와 같다.&lt;/p&gt;
&lt;pre id=&quot;code_1745138091839&quot; class=&quot;arduino&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;public class Main {
    public static void main(String[] args) {
        System.out.println(&quot;Hello World!&quot;);
        System.out.println(&quot;TEST :: &quot; + solution(3));
    }

    public static int solution(int n) {
        if (n == 1) return 1;
        return n * solution(n - 1);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;테스트 해보면 3! 인 6이 나오는것을 확인할 수 있다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot; data-start=&quot;559&quot; data-end=&quot;704&quot;&gt;회문 예제로 재귀를 이해해보자!&lt;/h3&gt;
&lt;p data-end=&quot;208&quot; data-start=&quot;138&quot; data-ke-size=&quot;size16&quot;&gt;회문이란, 예를 들어 &quot;abcba&quot;처럼&lt;br /&gt;&lt;b&gt;앞에서 읽든, 뒤에서 읽든 똑같은 문자열&lt;/b&gt;을 말한다.&lt;/p&gt;
&lt;p data-end=&quot;277&quot; data-start=&quot;210&quot; data-ke-size=&quot;size16&quot;&gt;쉽게 말해, 종이에 적어놓고 &lt;b&gt;반으로 접었을 때&lt;/b&gt;&lt;br /&gt;&lt;b&gt;왼쪽과 오른쪽이 똑같이 생긴&lt;/b&gt; 문자열이라고 생각하면 된다!&lt;/p&gt;
&lt;p data-end=&quot;277&quot; data-start=&quot;210&quot; data-ke-size=&quot;size16&quot;&gt;회문을 어떻게 처리할지 생각해보면,&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;451&quot; data-start=&quot;337&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;388&quot; data-start=&quot;337&quot;&gt;&lt;b&gt;양 끝 문자&lt;/b&gt;를 비교해서 같으면 &amp;rarr; &lt;b&gt;남은 안쪽 문자열&lt;/b&gt;도 회문인지 확인해보자!&lt;/li&gt;
&lt;li data-end=&quot;451&quot; data-start=&quot;389&quot;&gt;이렇게 점점 문자열을 줄여가다 보면 &amp;rarr; 결국 &lt;b&gt;비교할 게 없어지거나&lt;/b&gt;, &lt;b&gt;다르거나&lt;/b&gt; 중 하나가 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;516&quot; data-start=&quot;453&quot; data-ke-size=&quot;size16&quot;&gt;즉, &lt;b&gt;문자열 양쪽을 잘라가며 반복 확인하는 구조&lt;/b&gt;다.&lt;br /&gt;바로 이런 반복적인 패턴과 탐색 범위가 줄어드는 &lt;b&gt;재귀에 딱 맞는 상황&lt;/b&gt;이다!&lt;/p&gt;
&lt;p data-end=&quot;516&quot; data-start=&quot;453&quot; data-ke-size=&quot;size16&quot;&gt;문제 풀기 앞서 재귀에 필요한 재귀 호출값과 탈출 조건을 정리하면 아래와 같다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; color: #333333; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-start=&quot;1004&quot; data-end=&quot;1058&quot;&gt;&lt;b&gt;재귀 호출 값&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;: s.substring(1, s.length() - 1)&lt;br /&gt;&amp;rarr;&amp;nbsp;맨 앞과 맨 뒤를 제거한 문자열을 넘긴다.&amp;nbsp;&lt;/li&gt;
&lt;li data-start=&quot;1060&quot; data-end=&quot;1108&quot;&gt;&lt;b&gt;탈출 조건 :&amp;nbsp;&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-start=&quot;1060&quot; data-end=&quot;1108&quot;&gt;&lt;b&gt;양 끝이 다르면 return false;&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&amp;rarr; 더 볼 필요 없이 회문이 아니다&lt;/li&gt;
&lt;li data-start=&quot;1060&quot; data-end=&quot;1108&quot;&gt;&lt;b&gt;문자열의 길이가 0 또는 1이면 return true;&lt;/b&gt;&lt;br /&gt;&amp;rarr; 더 비교할 문자가 없으니 회문이다&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 코드로 나타내면 아래와 같다.&lt;/p&gt;
&lt;div style=&quot;background-color: #1e1f22; color: #bcbec4;&quot;&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;public class Main {
    public static void main(String[] args) {
        System.out.println(&quot;Hello World!&quot;);
        System.out.println(&quot;TEST :: &quot; + solution(&quot;abcba&quot;));
    }

    public static boolean solution(String s) {
        if (s.charAt(0) != s.charAt(s.length() - 1)) return false;
        if (s.length() &amp;lt;= 1) return true;
        return solution(s.substring(1, s.length() - 1));
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드 돌려보면 abcba는 앞으로 읽어도 abcba 뒤로 읽어도 abcab 이니 회문으로 true 가 나온다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;끝!&lt;/p&gt;</description>
      <category>ETC</category>
      <author>코린이s</author>
      <guid isPermaLink="true">https://co-de.tistory.com/255</guid>
      <comments>https://co-de.tistory.com/255#entry255comment</comments>
      <pubDate>Sun, 20 Apr 2025 18:22:14 +0900</pubDate>
    </item>
    <item>
      <title>[코테] 이진 탐색</title>
      <link>https://co-de.tistory.com/253</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;400&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/H8210/btsNsk4P2Qo/8WRu1E3OzKnno5JymlAcBk/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/H8210/btsNsk4P2Qo/8WRu1E3OzKnno5JymlAcBk/img.gif&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/H8210/btsNsk4P2Qo/8WRu1E3OzKnno5JymlAcBk/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/H8210/btsNsk4P2Qo/8WRu1E3OzKnno5JymlAcBk/img.gif&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;600&quot; height=&quot;400&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;400&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;탐색에 대해서 알아보자!&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터 속에서 원하는 값을 찾는 대표적인 방법에는&lt;br /&gt;&lt;b&gt;순차 탐색&lt;/b&gt;(Sequential search)&lt;b&gt;&lt;/b&gt;과 &lt;b&gt;이진 탐색&lt;/b&gt;(Binary search)&lt;b&gt;&lt;/b&gt;이라는 방식이 있다.&lt;br /&gt;이 둘은 어떤 차이가 있을까? 그리고 이진 탐색은 왜 더 빠르다고 할까?&lt;br /&gt;지금부터 함께 알아보자!&lt;/p&gt;
&lt;h3 data-end=&quot;248&quot; data-start=&quot;234&quot; data-ke-size=&quot;size23&quot;&gt;순차 탐색(Sequential search)이란?&lt;/h3&gt;
&lt;p data-end=&quot;300&quot; data-start=&quot;250&quot; data-ke-size=&quot;size16&quot;&gt;순차 탐색은 말 그대로 데이터를 &lt;b&gt;앞에서부터 하나씩 차례대로&lt;/b&gt; 확인해보는 방법이다.&lt;/p&gt;
&lt;p data-end=&quot;359&quot; data-start=&quot;302&quot; data-ke-size=&quot;size16&quot;&gt;리스트의 첫 번째 인덱스부터 시작해서,&lt;br /&gt;찾고자 하는 값이 나올 때까지 계속 다음 값을 확인해나간다.&lt;/p&gt;
&lt;p data-end=&quot;402&quot; data-start=&quot;361&quot; data-ke-size=&quot;size16&quot;&gt;  즉, &lt;b&gt;모든 데이터를 순서대로 검사하는 방식&lt;/b&gt;이라고 할 수 있다!&lt;/p&gt;
&lt;h3 data-end=&quot;420&quot; data-start=&quot;404&quot; data-ke-size=&quot;size23&quot;&gt;✅ 시간 복잡도는?&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;500&quot; data-start=&quot;421&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;500&quot; data-start=&quot;421&quot;&gt;&lt;b&gt;O(N)&lt;/b&gt;&lt;br /&gt;데이터가 100개 있다면, 최악의 경우 100번을 다 확인해야 한다.&lt;br /&gt;데이터가 많아질수록 시간이 오래 걸리게 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;이진 탐색(Binary search)이란?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이진 탐색은 &lt;b&gt;정렬된 데이터&lt;/b&gt;에서만 사용할 수 있는 탐색 방법이다.&lt;br /&gt;리스트가 &lt;b&gt;오름차순으로 정렬되어 있다는 조건&lt;/b&gt;이 필요하기에 처음에 배열을 정렬 하고 탐색한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;탐색 방식을 알아보자!&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-end=&quot;778&quot; data-start=&quot;614&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-end=&quot;639&quot; data-start=&quot;614&quot;&gt;리스트의 &lt;b&gt;가운데 값을 확인&lt;/b&gt;해본다.&lt;/li&gt;
&lt;li data-end=&quot;679&quot; data-start=&quot;640&quot;&gt;찾고자 하는 값이 가운데 값보다 &lt;b&gt;작은지, 큰지&lt;/b&gt;를 비교한다.&lt;/li&gt;
&lt;li data-end=&quot;738&quot; data-start=&quot;680&quot;&gt;작다면   &lt;b&gt;왼쪽 절반만&lt;/b&gt; 다시 탐색&lt;br /&gt;크다면   &lt;b&gt;오른쪽 절반만&lt;/b&gt; 다시 탐색&lt;/li&gt;
&lt;li data-end=&quot;778&quot; data-start=&quot;739&quot;&gt;이렇게 범위를 &lt;b&gt;반씩 줄여가며 반복&lt;/b&gt;해서 값을 찾는 방식이다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-end=&quot;803&quot; data-start=&quot;780&quot; data-ke-size=&quot;size23&quot;&gt;  상세하게 알아본다면..!&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;921&quot; data-start=&quot;805&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;848&quot; data-start=&quot;805&quot;&gt;먼저 &lt;b&gt;최소 인덱스(min) 는 0&lt;/b&gt;, &lt;b&gt;최대 인덱스(max)는 배열 크기 - 1 로 셋팅 &lt;/b&gt;한다.&lt;/li&gt;
&lt;li data-end=&quot;902&quot; data-start=&quot;849&quot;&gt;&lt;b&gt;중간 인덱스(mid)&lt;/b&gt;는 (min + max) / 2 값을 &lt;b&gt;내림&lt;/b&gt;해서 정수값이 나오도록 구한다.&lt;/li&gt;
&lt;li data-end=&quot;921&quot; data-start=&quot;903&quot;&gt;중간값 = 리스트[mid]&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;947&quot; data-start=&quot;923&quot; data-ke-size=&quot;size16&quot;&gt;그리고 찾고자 하는 값과 중간값을 비교한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1053&quot; data-start=&quot;949&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;986&quot; data-start=&quot;949&quot;&gt;찾는 값 &amp;lt; 중간값 &amp;rarr; &lt;b&gt;최대 인덱스 = mid - 1&lt;/b&gt;&lt;/li&gt;
&lt;li data-end=&quot;1024&quot; data-start=&quot;987&quot;&gt;찾는 값 &amp;gt; 중간값 &amp;rarr; &lt;b&gt;최소 인덱스 = mid + 1&lt;/b&gt;&lt;/li&gt;
&lt;li data-end=&quot;1053&quot; data-start=&quot;1025&quot;&gt;찾는 값 == 중간값 &amp;rarr; &lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;값을 찾게 된다!&lt;/span&gt;&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;1076&quot; data-start=&quot;1055&quot; data-ke-size=&quot;size16&quot;&gt;이 과정을 찾을 때까지 반복하면 된다.&lt;/p&gt;
&lt;h3 data-end=&quot;1094&quot; data-start=&quot;1078&quot; data-ke-size=&quot;size23&quot;&gt;✅ 시간 복잡도는?&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1182&quot; data-start=&quot;1095&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1182&quot; data-start=&quot;1095&quot;&gt;&lt;b&gt;O(log(N))&lt;/b&gt;&lt;br /&gt;데이터가 많아도 탐색 시간이 급격히 줄어든다!&lt;br /&gt;예를 들어 1024개의 데이터가 있으면, 최대 10번 안에 찾을 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;순차 탐색은 순차적으로 인덱스 0부터 찾는값이 나올때까지 찾는다.&lt;/span&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;br /&gt;&lt;b&gt;데이터의 양이 많아질수록&lt;/b&gt; 이진 탐색이 훨씬 더 효율적이라 데이터가 많고 정렬이 가능하다면 이진 탐색을 사용할것 같다!&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;정수 찾기로 탐색 익숙해지기!&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 순차탐색과 이진 탐색의 개념을 알아 봤으니 문제를 직접 풀어보자!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a style=&quot;background-color: #e6f5ff; color: #0070d1; text-align: start;&quot; href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/181840&quot;&gt;정수 찾기&lt;/a&gt; 문제를 풀어보자! (링크 클릭시 프로그래머스로 이동!)&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;정수 리스트&amp;nbsp;num_list와 찾으려는 정수&amp;nbsp;n이 주어질 때,&amp;nbsp;num_list안에&amp;nbsp;n이 있으면 1을 없으면 0을 return하도록 solution 함수를 완성해주세요.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;순차 탐색으로 구현해보면 아래와 같이 구현해볼 수 있다!&lt;/p&gt;
&lt;div style=&quot;background-color: #1e1f22; color: #bcbec4;&quot;&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;public class Main {

    public static void main(String[] args) {
        int[] num_list = new int[5];
        num_list[0] = 15;
        num_list[1] = 98;
        num_list[2] = 23;
        num_list[3] = 2;
        num_list[4] = 15;
        System.out.println(&quot;TEST :: &quot; + solution(num_list, 20));
    }

    public static int solution(int[] num_list, int n) {
        for (int num : num_list) {
            if (num == n) {
                return 1;
            }
        }
        return 0;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드를 돌려보면 배열에 20이 없으니 0 이 정상적으로 나오는것을 볼 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;값은 정상적으로 나오지만 num_list 크기가 크다면 위에 순차 탐색은 이진 탐색으로 구현한 코드보다 오랜 시간이 소요 될 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 이진탐색으로 구현해보자!&lt;/p&gt;
&lt;pre id=&quot;code_1745132245803&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.util.Arrays;

public class Main {

    public static void main(String[] args) {
        int[] num_list = new int[5];
        num_list[0] = 15;
        num_list[1] = 98;
        num_list[2] = 23;
        num_list[3] = 2;
        num_list[4] = 15;
        System.out.println(&quot;TEST :: &quot; + solution(num_list, 20));
    }

    public static int solution(int[] num_list, int n) {
        if (num_list == null || num_list.length == 0) {
            return 0;
        }
        Arrays.sort(num_list);
        int low = 0;
        int high = num_list.length - 1;
        while (low &amp;lt;= high) {
            int mid = (low + high) / 2;
            if (num_list[mid] == n) {
                return 1;
            }
            if (num_list[mid] &amp;lt; n) {
                low = mid + 1;
            }
            if (num_list[mid] &amp;gt; n) {
                low = mid - 1;
            }
        }
        return 0;
    }
}&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;이진 탐색으로 구현하면 코드는 길어지지만 성능적으로는 좋은 코드이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추가적으로 해당 문제를 아래와 같이 풀어 볼 수도 있다.&lt;/p&gt;
&lt;div style=&quot;background-color: #1e1f22; color: #bcbec4;&quot;&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;public static int solution(int[] num_list, int n) {
    return IntStream.of(num_list).anyMatch(v -&amp;gt; v == n) ? 1 : 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드는 매우 간결해지지만&lt;b&gt; IntStream.of(...).anyMatch(...)&lt;/b&gt;의 경우 내부적으로 &lt;b&gt;순차 탐색&lt;/b&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;/p&gt;</description>
      <category>ETC</category>
      <author>코린이s</author>
      <guid isPermaLink="true">https://co-de.tistory.com/253</guid>
      <comments>https://co-de.tistory.com/253#entry253comment</comments>
      <pubDate>Sun, 20 Apr 2025 14:57:32 +0900</pubDate>
    </item>
    <item>
      <title>[코테] 시간/공간 복잡도</title>
      <link>https://co-de.tistory.com/252</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;시간/공간 복잡도란?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시간 복잡도는 &lt;b&gt;알고리즘이 실행되는데 걸리는 시간/사용되는 공간&lt;/b&gt;을 수학적으로 표현한 개념입니다. 입력 크기 &lt;span&gt;&lt;span&gt;N&lt;/span&gt;&lt;/span&gt;이 커질수록 얼마나 많은 연산이 수행되는지를 알려주기 때문에, 알고리즘의 &lt;b&gt;성능 비교&lt;/b&gt;에 유용 합니다.&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;시간 복잡도 계산법&lt;/h2&gt;
&lt;h3 data-end=&quot;267&quot; data-start=&quot;249&quot; data-ke-size=&quot;size23&quot;&gt;  예제 코드로 살펴보기&lt;/h3&gt;
&lt;p data-end=&quot;306&quot; data-start=&quot;269&quot; data-ke-size=&quot;size16&quot;&gt;아래 코드는 리스트 안에서 가장 큰 숫자를 찾는 간단한 함수입니다:&lt;/p&gt;
&lt;pre id=&quot;code_1744521562289&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def find_max_num(array):
    for number in array:
        is_max_num = True
        for compare_number in array:
            if number &amp;lt; compare_number:
                is_max_num = False
        if is_max_num:
            return number&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;이 코드를 기준으로, 각 부분이 얼마나 많은 연산을 수행하는지 분석해보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;  안쪽의 is_max_num = False 까지 걸리는 시간&lt;/p&gt;
&lt;pre id=&quot;code_1744522485501&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;for number in array:
    for compare_number in array:
        if number &amp;lt; compare_number:
            is_max_num = False&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;905&quot; data-start=&quot;755&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;785&quot; data-start=&quot;755&quot;&gt;array의 길이가 &lt;span&gt;&lt;span&gt;N&lt;/span&gt;&lt;/span&gt;이라고 할 때,&lt;/li&gt;
&lt;li data-start=&quot;786&quot; data-end=&quot;811&quot;&gt;첫번째 for문은&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;N번 반복&lt;/b&gt;됩니다.&lt;/li&gt;
&lt;li data-start=&quot;786&quot; data-end=&quot;811&quot;&gt;두번째 for문도&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;N번 반복&lt;/b&gt;됩니다.&lt;/li&gt;
&lt;li data-end=&quot;905&quot; data-start=&quot;812&quot;&gt;반복 안에서는 조건문 if와 대입문 is_max_num = False가 각각 1번씩 실행되므로, &lt;b&gt;1 + 1 = 2번의 연산&lt;/b&gt;이 매 반복마다 일어납니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;952&quot; data-start=&quot;907&quot; data-ke-size=&quot;size16&quot;&gt;  총 연산 수:&lt;br /&gt;N * N * 2 = 2N^2&lt;/p&gt;
&lt;p data-end=&quot;952&quot; data-start=&quot;907&quot; data-ke-size=&quot;size16&quot;&gt;  그 다음 if is_max_num: 의 시간&lt;/p&gt;
&lt;pre id=&quot;code_1744522592177&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;for number in array:
    if is_max_num:
        return number&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1119&quot; data-start=&quot;1042&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1081&quot; data-start=&quot;1042&quot;&gt;이 부분은 바깥 루프가 한 번씩 돌 때마다 실행 가능성이 있으므로,&lt;/li&gt;
&lt;li data-end=&quot;1119&quot; data-start=&quot;1082&quot;&gt;최대 &lt;b&gt;N번 실행&lt;/b&gt;된다고 볼 수 있고, 조건문 &lt;b&gt;하나&lt;/b&gt;만 있으니&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;1141&quot; data-start=&quot;1121&quot; data-ke-size=&quot;size16&quot;&gt;  총 연산 수:&lt;/p&gt;
&lt;p data-end=&quot;1141&quot; data-start=&quot;1121&quot; data-ke-size=&quot;size16&quot;&gt;N * 1&lt;/p&gt;
&lt;h3 data-end=&quot;1166&quot; data-start=&quot;1148&quot; data-ke-size=&quot;size23&quot;&gt;  최종 시간 복잡도&lt;/h3&gt;
&lt;p data-end=&quot;1184&quot; data-start=&quot;1168&quot; data-ke-size=&quot;size16&quot;&gt;앞서 계산한 두 개를 합치면:&lt;/p&gt;
&lt;p data-end=&quot;1184&quot; data-start=&quot;1168&quot; data-ke-size=&quot;size16&quot;&gt;2N^2 + N&lt;/p&gt;
&lt;p data-end=&quot;1184&quot; data-start=&quot;1168&quot; data-ke-size=&quot;size16&quot;&gt;하지만 시간 복잡도는 &lt;b&gt;대략적인 성능 비교용&lt;/b&gt;이기 때문에, 가장 영향이 큰 항만 남기고 나머지는 생략합니다.&lt;/p&gt;
&lt;p data-end=&quot;1286&quot; data-start=&quot;1266&quot; data-ke-size=&quot;size16&quot;&gt;  따라서 최종 시간 복잡도는:&lt;/p&gt;
&lt;p data-end=&quot;1184&quot; data-start=&quot;1168&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;N^2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-end=&quot;1184&quot; data-start=&quot;1168&quot; data-ke-size=&quot;size23&quot;&gt;여기서 잠깐!&lt;/h3&gt;
&lt;p data-end=&quot;1184&quot; data-start=&quot;1168&quot; data-ke-size=&quot;size16&quot;&gt;가끔 시간 복잡도를 계산하다 보면, 다음과 같이 &lt;b&gt;상수값&lt;/b&gt;이 나오는 경우가 있습니다.&lt;/p&gt;
&lt;p data-end=&quot;214&quot; data-start=&quot;127&quot; data-ke-size=&quot;size16&quot;&gt;예를 들어 어떤 알고리즘이 항상 &lt;b&gt;정확히 26번의 연산&lt;/b&gt;만 수행된다고 해봅시다. 그러면 이 알고리즘의 시간 복잡도는 &lt;b&gt;26&lt;/b&gt;이라고 말할 수 있겠지만 사실 시간 복잡도에서는 &lt;b&gt;이런 상수값은 중요하지 않습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-end=&quot;214&quot; data-start=&quot;127&quot; data-ke-size=&quot;size16&quot;&gt;시간 복잡도는 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;입력 크기&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;N&lt;/span&gt;&lt;/span&gt;이 커질수록 알고리즘의 성능이 &lt;b&gt;어떻게 변하는지를 보는 것&lt;/b&gt;이지, &lt;b&gt;정확한 실행 횟수 자체를 따지는 게 아니기 때문&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-end=&quot;359&quot; data-start=&quot;357&quot; data-ke-size=&quot;size16&quot;&gt;즉,&lt;/p&gt;
&lt;blockquote data-end=&quot;447&quot; data-start=&quot;361&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;p data-end=&quot;447&quot; data-start=&quot;363&quot; data-ke-size=&quot;size16&quot;&gt;&quot;26이나 1이나 결국은 &lt;b&gt;항이 따로 없고 입력 크기에 따라 변하지 않기&lt;/b&gt; 때문에, 시간 복잡도는 &lt;span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;1 입니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-end=&quot;88&quot; data-start=&quot;68&quot; data-ke-size=&quot;size26&quot;&gt; ️ 공간&amp;nbsp;복잡도 계산법&lt;/h2&gt;
&lt;p data-end=&quot;160&quot; data-start=&quot;90&quot; data-ke-size=&quot;size16&quot;&gt;시간 복잡도와 함께 알고리즘을 평가할 때 꼭 함께 고려해야 할 것이 공간 복잡도입니다.&lt;/p&gt;
&lt;p data-end=&quot;262&quot; data-start=&quot;162&quot; data-ke-size=&quot;size16&quot;&gt;공간 복잡도는 &lt;b&gt;문제를 해결하는 데 얼마나 많은 메모리(공간)를 사용하는지&lt;/b&gt;를 나타냅니다.&lt;br /&gt;당연히 &lt;b&gt;필요한 공간을 적게 쓸수록 더 효율적인 알고리즘&lt;/b&gt;이라고 볼 수 있습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  예제 코드로 살펴보기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 코드를 기준으로 어떤 공간들이 사용되었는지 살펴보겠습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1744523203116&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def find_max_occurred_alphabet(string):
    alphabet_occurrence_array = [0] * 26

    for char in string:
        if not char.isalpha():
            continue
        arr_index = ord(char) - ord('a')
        alphabet_occurrence_array[arr_index] += 1

    max_occurrence = 0
    max_alphabet_index = 0
    for index in range(len(alphabet_occurrence_array)):
        alphabet_occurrence = alphabet_occurrence_array[index]
        if alphabet_occurrence &amp;gt; max_occurrence:
            max_occurrence = alphabet_occurrence
            max_alphabet_index = index

    return chr(max_alphabet_index + ord('a'))&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-end=&quot;971&quot; data-start=&quot;954&quot; data-ke-size=&quot;size23&quot;&gt;  사용된 메모리 분석&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1138&quot; data-start=&quot;973&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1028&quot; data-start=&quot;973&quot;&gt;alphabet_occurrence_array &amp;rarr; &lt;b&gt;26개의 공간&lt;/b&gt; 사용 (알파벳 개수)&lt;/li&gt;
&lt;li data-end=&quot;1051&quot; data-start=&quot;1029&quot;&gt;arr_index &amp;rarr; &lt;b&gt;1개&lt;/b&gt;&lt;/li&gt;
&lt;li data-end=&quot;1138&quot; data-start=&quot;1052&quot;&gt;max_occurrence, max_alphabet_index, alphabet_occurrence &amp;rarr; &lt;b&gt;각각 1개씩&lt;/b&gt;, 총 &lt;b&gt;3개&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;1155&quot; data-start=&quot;1140&quot; data-ke-size=&quot;size16&quot;&gt;  전체 공간 사용량은&lt;/p&gt;
&lt;p data-end=&quot;1155&quot; data-start=&quot;1140&quot; data-ke-size=&quot;size16&quot;&gt;26 + 1 + 3 = 30 이 됩니다.&lt;/p&gt;
&lt;h3 data-end=&quot;1204&quot; data-start=&quot;1184&quot; data-ke-size=&quot;size23&quot;&gt;  최종 공간 복잡도&lt;/h3&gt;
&lt;p data-end=&quot;1278&quot; data-start=&quot;1206&quot; data-ke-size=&quot;size16&quot;&gt;이론적으로는 30이지만, &lt;b&gt;입력 크기와 무관하게 고정된 수만큼의 공간만 사용하는 경우&lt;/b&gt;, 공간 복잡도는 &lt;b&gt;상수&lt;/b&gt;로 봅니다.&lt;/p&gt;
&lt;p data-end=&quot;1282&quot; data-start=&quot;1280&quot; data-ke-size=&quot;size16&quot;&gt;즉,&lt;/p&gt;
&lt;blockquote data-end=&quot;1360&quot; data-start=&quot;1284&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;p data-end=&quot;1360&quot; data-start=&quot;1286&quot; data-ke-size=&quot;size16&quot;&gt;&quot;&lt;b&gt;입력에 따라 메모리 사용량이 늘어나지 않기 때문에&lt;/b&gt;, 이 알고리즘의 공간 복잡도는 1 입니다.&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이처럼 &lt;b&gt;시간 복잡도와 공간 복잡도&lt;/b&gt;를 함께 고려해서 계산하면, 보다 &lt;b&gt;효율적이고 현실적인 알고리즘&lt;/b&gt;을 설계할 수 있습니다.&lt;/p&gt;
&lt;p data-end=&quot;211&quot; data-start=&quot;184&quot; data-ke-size=&quot;size16&quot;&gt;그렇다면 이 복잡도들을 &lt;b&gt;어떻게 표기할까요?&lt;/b&gt;&lt;/p&gt;
&lt;h3 data-end=&quot;211&quot; data-start=&quot;184&quot; data-ke-size=&quot;size23&quot;&gt;점근 표기법&lt;/h3&gt;
&lt;p data-end=&quot;211&quot; data-start=&quot;184&quot; data-ke-size=&quot;size16&quot;&gt;복잡도는 보통 &lt;b&gt;수학적인 기호&lt;/b&gt;로 표현하는데, 이를 &lt;b&gt;점근 표기법&lt;/b&gt;이라고 합니다.&lt;/p&gt;
&lt;p data-end=&quot;343&quot; data-start=&quot;321&quot; data-ke-size=&quot;size16&quot;&gt;가장 대표적인 표기법은 다음과 같습니다:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;표기법설명
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-end=&quot;498&quot; data-start=&quot;345&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody data-end=&quot;498&quot; data-start=&quot;376&quot;&gt;
&lt;tr data-end=&quot;433&quot; data-start=&quot;376&quot;&gt;
&lt;td data-end=&quot;404&quot; data-start=&quot;376&quot;&gt;&lt;span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;O&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; (빅 오)&lt;/td&gt;
&lt;td data-end=&quot;433&quot; data-start=&quot;404&quot;&gt;&lt;b&gt;최악의 경우&lt;/b&gt;에 필요한 연산량 또는 공간&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;498&quot; data-start=&quot;434&quot;&gt;
&lt;td data-end=&quot;469&quot; data-start=&quot;434&quot;&gt;&lt;span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&amp;Omega;&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; (빅 오메가)&lt;/td&gt;
&lt;td data-end=&quot;498&quot; data-start=&quot;469&quot;&gt;&lt;b&gt;최선의 경우&lt;/b&gt;에 필요한 연산량 또는 공간&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-end=&quot;536&quot; data-start=&quot;505&quot; data-ke-size=&quot;size23&quot;&gt;❗ 왜 빅오(Big-O) 표기법을 주로 사용할까?&lt;/h3&gt;
&lt;p data-end=&quot;579&quot; data-start=&quot;538&quot; data-ke-size=&quot;size16&quot;&gt;현실에서는 &lt;b&gt;입력값이 언제나 좋게 들어온다는 보장이 없기 때문&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-end=&quot;665&quot; data-start=&quot;581&quot; data-ke-size=&quot;size16&quot;&gt;즉, 우리는 &lt;b&gt;최악의 상황&lt;/b&gt;에서도 알고리즘이 &lt;b&gt;어느 정도 성능을 유지할 수 있어야&lt;/b&gt; 하고, 이를 위해 &lt;b&gt;빅오 표기법을 기준으로 평가&lt;/b&gt;합니다.&lt;/p&gt;
&lt;h3 data-end=&quot;68&quot; data-start=&quot;52&quot; data-ke-size=&quot;size23&quot;&gt;복잡도 표기 예시&lt;/h3&gt;
&lt;p data-end=&quot;104&quot; data-start=&quot;70&quot; data-ke-size=&quot;size16&quot;&gt;복잡도를 점근 표기법으로 표현할 때는 다음과 같이 작성합니다:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;187&quot; data-start=&quot;106&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;151&quot; data-start=&quot;106&quot;&gt;시간 복잡도가 N^2이라면 &amp;rarr; &lt;span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;O&lt;/span&gt;&lt;span&gt;(N^2&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;187&quot; data-start=&quot;152&quot;&gt;공간 복잡도가 1이라면 &amp;rarr; &lt;span&gt;&lt;span&gt;O(1)&lt;/span&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;254&quot; data-start=&quot;189&quot; data-ke-size=&quot;size16&quot;&gt;이처럼 시간과 공간 복잡도는 각각 독립적으로 계산하고, 점근 표기법(Big-O)을 사용해 간단하게 표현합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;873&quot; data-origin-height=&quot;453&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/efThLd/btsNiNNm94r/EgfK1LE8SOpxTnkWoOTlfk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/efThLd/btsNiNNm94r/EgfK1LE8SOpxTnkWoOTlfk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/efThLd/btsNiNNm94r/EgfK1LE8SOpxTnkWoOTlfk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FefThLd%2FbtsNiNNm94r%2FEgfK1LE8SOpxTnkWoOTlfk%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;873&quot; height=&quot;453&quot; data-origin-width=&quot;873&quot; data-origin-height=&quot;453&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-end=&quot;254&quot; data-start=&quot;189&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;각 시간 복잡도는 위 그림과 같이 비교 할 수 있으며 이를 참고하여 다음 시간 부터 알고리즘을 풀어보도록 하자!&lt;/p&gt;</description>
      <category>ETC</category>
      <author>코린이s</author>
      <guid isPermaLink="true">https://co-de.tistory.com/252</guid>
      <comments>https://co-de.tistory.com/252#entry252comment</comments>
      <pubDate>Sun, 13 Apr 2025 14:38:59 +0900</pubDate>
    </item>
  </channel>
</rss>