<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>justlog</title>
    <link>https://justlog.tistory.com/</link>
    <description>Secret Due Due Die-early</description>
    <language>ko</language>
    <pubDate>Mon, 6 Jul 2026 13:47:19 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>euidong</managingEditor>
    <image>
      <title>justlog</title>
      <url>https://tistory1.daumcdn.net/tistory/4620820/attach/391948cb19e44065a2673aece8f9736c</url>
      <link>https://justlog.tistory.com</link>
    </image>
    <item>
      <title>2. Instruction</title>
      <link>https://justlog.tistory.com/39</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Reference&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;405&quot; data-origin-height=&quot;500&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/8TOZg/btrzliNIyom/Y5Bxqhfu2QMwdGamSpiiyk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/8TOZg/btrzliNIyom/Y5Bxqhfu2QMwdGamSpiiyk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/8TOZg/btrzliNIyom/Y5Bxqhfu2QMwdGamSpiiyk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F8TOZg%2FbtrzliNIyom%2FY5Bxqhfu2QMwdGamSpiiyk%2Fimg.jpg&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;220&quot; height=&quot;272&quot; data-origin-width=&quot;405&quot; data-origin-height=&quot;500&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;David A. Patterson, John L. Hennessy&lt;b&gt;,&lt;/b&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;Computer Organization and Design&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;본 Posting은 다음 교제를 기반으로 챕터 별로 정리 한 내용입니다. 아래부터는 편의를 위해 &quot;-다&quot;로 표현합니다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴퓨터가 알아들을 수 있는 명령을 우리는 Instruction이라고 한다. 그렇다면, 이들을 모아놓은 단어장(Vocabulary)는 &lt;b&gt;Instruction set&lt;/b&gt;이 되는 것이다. 이런 의미에서 현대의 computer는 이를 기반으로 동작하도록 설계되었기 때문에, 이를&amp;nbsp;&lt;b&gt;Instruction set architecture&lt;/b&gt;라고 부른다. 해당 책에서는 MIPS를 기준으로 하기 때문에 똑같이 MIPS를 기준으로 설명합니다. 이는 다른 processor들과 매우 유사하니 이를 배우면 쉽게 다른 것도 이해할 수 있을 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇다면, Instruction이란 무엇일까? 이는 기계어(0과 1로 이루어진 이진수 체계)의 형태로 표현된다. 따라서, 이를 Assembly Instruction이라고도 한다. 이는 hardware에게 특정 동작을 수행하도록 하는 명령어라고 할 수 있다. 그렇기에 우리가 실행하거나 작성하는 모든 program들은 사실 Instruction들의 집합이라고 볼 수 있다. 실제로 Computer에서 Program이 동작할 때, 이는 Computer는 memory에 program의 내용과 program에서 사용할 data들을 위한 공간을 배정해준다. 그런 후에 실제로 실행될 때에는 program의  Instruction을 차례차례 읽어가면서 실행하는 것이다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Assembly Instruction의 구성요소&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본적으로 MIPS는 32bit(=4Bytes) 시스템을 사용한다. 따라서, 하나의 Instruction은 4 Bytes로 표현된다. 이를 하나의 가장 단위라고 여겨서 word라고도 부른다. 따라서, 64bit(=8Bytes) CPU에서는 1 word가 8 Bytes가 될 수도 있다. 결국 모든 Instruction이  0과 1로 이루어진다. 하지만, 이는 너무 읽기 어렵기 때문에 우선 Assembly(기계어보다는 사람의 언어에 가깝지만 아주 원초적인 형태의 언어) Instruction을 알아볼 것이다. 이를 기계어로 바꾸는 것은 해당 포스팅의 밑에서 다룬다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;1. Operand&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;연산을 위해서 필요한 것은 연산자와 피연산자이다. 보통의 programming 언어에서는 이를 변수라고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MIPS에서는 총 두 가지의 변수 type이 존재한다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Constant&lt;br /&gt;&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Register No&lt;/b&gt;&lt;br /&gt;하드웨어 상의 register들과 programming에서의 변수와 차이점이 있다면, 바로 갯수의 제한이 있다는 것이다. 보통은 갯수를 32개로 제한한다. 그렇게 하는 것이 효율적이라고 찾아냈다고 한다. 더 많이 써도 Clock Cycle이 더 소모될 뿐이고, 적다면 표현력이 부족해지 수도 있다. 또한, 하나의 register의 크기 또한 우리는 대게 32bit(1 word)로 제한한다. 이를 표현할 때에는 보통 $ 표시를 활용하고, register는 특정 목적을 위해서 지정되어 있다. (밑에 표를 참고)&lt;br /&gt;Instruction에서는 Register를 가르키기 위해서 5bit를 사용한다. $2^5$이면 모든 Register를 구분할 수 있기 때문이다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Memory Address&lt;/b&gt;&lt;br /&gt;해당 공간에는 기본적으로 register에 담기진 못한 모든 정보가 저장된다. 왜냐하면, register 가 하나의 변수를 표현할 수 있는데 만약, 변수가 32개를 넘어간다면, 이를 처리하는 것이 매우 버거워 진다. 따라서, 이를 임시로 저장해두어야 한다. 따라서, 이를 memory에 잠깐 저장하는데 이를 &lt;b&gt;spilling register&lt;/b&gt;라고 부른다. &lt;br /&gt;좀 더 복잡한 데이터 구조를 가지는 경우에도 이를 모두 register에 담는 것은 불가능하다. 따라서, 우리는 Memory라는 것을 활용한다. Memory는 8bit 단위로 한 칸으로 나누어 4개의 칸을 합친 것을 하나의 단위로 봅니다. (왜냐하면 이것이 4x8bit = 32bit = 1word가 되기 때문이다.) 따라서, 우리가 특정 값에 접근할 때에는 4의 배수로 접근하는 것이 올바른 접근이다. 또한, 하나의 데이터가 4개의 칸으로 쪼개지기 때문에 저장 방법에 차이가 있을 수 있다. 어떤 사람들은 앞 자리부터 차곡차곡 넣을 수도 있지만, 누구는 역순으로도 넣을 수 있기 때문에 이를 유의해야 한다. MIPS에서는 앞에서붙터 차곡차곡 넣는 Big Endian 방식을 사용한다. (즉, 4개 중 가장 낮은 주소값에 높은 값을 의미하는 값(MSB)이 쓰인다.)&lt;br /&gt;하나의 Memory address를 가르키기 위해서는 32bit가 필요하다. 이렇게 하여 $2^{32}$ = 4GB 이하까지의 Memory는 가르킬 수 있는 것이다. Instruction 자체가 32bit인데, 이를 Instruction에 바로 넣을 수는 없기 때문에 특정 Memory address를 가르키기 위해서 별도의 register에 해당 Memory의 address를 저장해두고 해당 지점부터 offset을 constant로 전달하는 식으로 표기한다.(여기서 4의 배수로 memory가 표현되므로, 2bit를 뺀다고 해도 30bit로 여전히 많다.)&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음은 MIPS의 Register와 Memory를 나타낸 것이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-04-14 오후 8.48.23.png&quot; data-origin-width=&quot;1752&quot; data-origin-height=&quot;734&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Zyn8H/btrzqmVCp3z/VqgyS2Z1qosQlQDmClm8kk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Zyn8H/btrzqmVCp3z/VqgyS2Z1qosQlQDmClm8kk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Zyn8H/btrzqmVCp3z/VqgyS2Z1qosQlQDmClm8kk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZyn8H%2FbtrzqmVCp3z%2FVqgyS2Z1qosQlQDmClm8kk%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;1752&quot; height=&quot;734&quot; data-filename=&quot;스크린샷 2022-04-14 오후 8.48.23.png&quot; data-origin-width=&quot;1752&quot; data-origin-height=&quot;734&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상식적으로 알아두고 갈 부분은 reigster는 직접적으로 연산이 이루어지는 곳이기 때문에, register에 접근하는 비용이 memory에 접근하는 부분보다 확연하게 비용이 싸다.(시간이 짧게 걸린다.) 따라서, 이를 효율적으로 다루어주는 것이 효율 향상에 도움이 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2. Operation&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모든 computer는 기본적인 연산을 수행할 수 있어야 한다. MIPS에서는 다음과 같은 표기법을 사용한다.&lt;/p&gt;
&lt;pre class=&quot;shell&quot; data-ke-language=&quot;shell&quot;&gt;&lt;code&gt;1. &amp;lt;명령어(operation)&amp;gt; &amp;lt;연산자(operand) 1&amp;gt; &amp;lt;연산자(operand) 2&amp;gt; &amp;lt;연산자(operand) 3&amp;gt;

2. &amp;lt;명령어(operation)&amp;gt; &amp;lt;연산자(operand) 1&amp;gt; &amp;lt;연산자(operand) 2&amp;gt;

3. &amp;lt;명령어(operation)&amp;gt; &amp;lt;연산자(operand)&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마치 우리가 영어를 처음 배울 때, 1형식, 2형식 배우는 형태랑 유사하다. 그리고 여기서는 모든 문장이 명령형으로 구성된다는 점을 유의하자. 이에 따라서, 다음 MIPS 의 피연산자(operand)와 주요  Operation을 살펴보자.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;b&gt;Add / Substract&lt;/b&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$$ add \text{ 연산자1} \text{ 연산자2} \text{ 연산자3} $$&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모든 연산의 기본으로 위의 형태 중에서 첫번째에 해당한다. 이를 수학 기호로 나타내면 다음과 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$$ \text{연산자1} = \text{연산자2} + \text{연산자3} $$&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Substraction 연산도 이와 동일하게 동작한다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;b&gt;Load / Save&lt;/b&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리가 Register에 특정 데이터를 저장하기를 원한다면, $zero register 에 저장하기를 원하는 값 또는 register를 add해서 해당 register에 저장하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$$ add \text{ [저장을 원하는 register No]} \text{ \$zero} \text{ 1234} $$&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만, Memory에 데이터를 저장하기 위해서는 별도의 명령어가 필요하다. 그것이 save 명령어 입니다. 앞 서 말한 것과 같이 memory address를 직접적으로 Instruction에 표현할 수는 없기 때문에 특정 register에 주소값을 저장하고, 해당 주소를 base로 해서 offset을 더해서 주소를 찾는 형태로 수행한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$$ sw \text{ [저장할  register No]} \text{ [Memory의 Base Address를 가진 register No]} \text{ offset} $$&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이와 반대로 Memory에서 데이터를 register로 불러올 때에도 별도의 명령어가 필요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$$ lw \text { [불러올 register No]} \text{ [Memory의 Base Address를 가진 register No]} \text{ offset} $$&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;b&gt;Jump&lt;/b&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Instruction 역시 Memory에 상주하고 있는데, 만약 필요에 따라 이전 Instruction으로 돌아가거나 Instruction을 뛰어넘어야 한다면, 그때 사용할 수 있는 Instruction이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$$ j \text{ [이동할 instruction offset]} $$&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;b&gt;Branch&lt;/b&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Branch(분기)는 특정 조건의 부합 여부를 확인하고, Jump를 수행하는 Instruction이다. 이를 위한 operator가 beq, bne가 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$$ beq \text{ [비교할 register1]} \text{ [비교할 register2]} \text{ [이동할 instruction offset]} $$&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;register1과 2가 서로 동일하다면, 해당 instruction offset으로 이동하라는 의미이다. bne는 반대로 두 register가 다를 때에 이동할 수 있다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;b&gt;기타 주요 명령어&lt;/b&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-04-14 오후 8.48.40.png&quot; data-origin-width=&quot;1756&quot; data-origin-height=&quot;546&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b9RoSB/btrzrMsOeFq/NpzguLmgFkPKpkrT5P9Xp1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b9RoSB/btrzrMsOeFq/NpzguLmgFkPKpkrT5P9Xp1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b9RoSB/btrzrMsOeFq/NpzguLmgFkPKpkrT5P9Xp1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb9RoSB%2FbtrzrMsOeFq%2FNpzguLmgFkPKpkrT5P9Xp1%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;1756&quot; height=&quot;546&quot; data-filename=&quot;스크린샷 2022-04-14 오후 8.48.40.png&quot; data-origin-width=&quot;1756&quot; data-origin-height=&quot;546&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;* PC : Program Counter의 줄임말로 현재 실행하고 있는 Program에서 어느 위치의 Instruction을 실행시키고 있는지를 나타낸다. 이를 이용해서 CPU는 다음 Instruction을 불러온다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;* offset : offset은 대게 instruction 단위로 나타내기 때문에 1 offset은 4Bytes를 의미한다. 따라서, offset을 실제 주소에 더할 때에는 곱하기 4(실제로는 shift left 2)를 해야한다. 이로 인해서, 현재 Instruction의 다음 Instruction의 주소를 PC+4 라고 한다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt; Instruction를 이용한  Programming 언어 기본 요소 구현&lt;/b&gt;&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;1. 조건문 (if / else)&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1649924797953&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;if (i == j) 
	f = g + h;
else
	f = g - h;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음과 같은 c의 조건문 코드를 아래와 같은 Instruction들로 변환이 가능하다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;autoit&quot;&gt;&lt;code&gt;bne $s3, $s4, Else # go to Else if i != j
add $s0, $s1, $s2 # f = g + h (skipped if i != j)
j Exit # go to Exit

Else: 
sub $s0, $s1, $s2 # f = g - h (skipped if i = j)

Exit:
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 Else는 임의의 offset을 나타낸다. 따라서, &quot;Else:&quot;라고 표시된 부분에 해당하는 offset이라고 생각하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Switch/Case 문 같은 경우는 if/else로 변환해서 나타내기도 하고, 아니면 Switching 위치를 적어놓은 Table을 만들어서 해당 위치로 바로 이동하는 식으로 구현하기도 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2. 반복문 (while)&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1649924997204&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;while(save[i] == k)
	i += 1;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음과 같은 c의 반복문을 아래와 같은 Instruction들로 변환이 가능하다.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;# $t1 : save[i] address pointer
# $t0 : save[i] value
# $s3 : i
# $s6 : save의 base address (save[0] address pointer)
# $s5 : k

# sll shift left &quot;&amp;lt;&amp;lt;&quot; 를 의미합니다. 
# 즉, 아래에서는 두 번하므로, *2^2를 의미합니다.
Loop: 
sll $t1, $s3, 2 # temp reg $t1 = i * 4
add $t1, $t1, $s6 # $t1 = address of save[i]
lw $t0, 0($t1) # temp reg $t0 = save[i]
bne $t0, $s5, Exit # go to Exit if save[i] != k
addi $s3, $s3, 1 # i = i + 1
j Loop # go to Loop

Exit:
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;3. 함수 (function)&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;procedure는 대게 function(함수)이라고도 불린다. 함수를 우리는 하나의 예시를 통해서 설명할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;procedure를 비밀 작전을 맡고 떠난 spy라고 하자. 작전은 자원을 습득하여, 특정 작업을 수행하고, 흔적을 감춘 뒤에, 바람직한 결과를 들고 돌아오는 것을 의미한다. 즉, spy는 작업을 마치고, 원하는 결과를 갖고 왔지만, 해당 결과 외에는 아무것도 바뀌지 않기를 기대한다. (누군가한테 의심받지 않아야하기 때문에)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 과정이 똑같이 함수의 호출마다 발생한다. 아래는 이를 다소 축약한 형태입니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;parameter를 procedure가 접근할 수 있는 곳에 위치시킵니다.&lt;/li&gt;
&lt;li&gt;control을 procedure(callee)로 옮깁니다.&lt;/li&gt;
&lt;li&gt;procedure는 해당하는 자원(parameter)을 습득합니다.&lt;/li&gt;
&lt;li&gt;목표한 바를 수행합니다.&lt;/li&gt;
&lt;li&gt;결과값을 자신을 호출한 program(caller)이 접근할 수 있는 곳에 위치시킵니다.&lt;/li&gt;
&lt;li&gt;control을 호출한 곳(caller)으로 넘깁니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;* 여기서 control이 이동했다는 것은  PC값이 PC+4가 아닌 함수의 주소로 이동했다는 것을 의미합니다.&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;이를 구현하기 위해서 우리는 다음과 같은 별도의 register를 사용합니다.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;$a0 - $a3 : 4 argument(=parameter) registers.
$v0 - $v1 : 2 return value registers.
$ra : 1 return address register. 원래 위치를 기억하기 위한 register.
&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;$a와 $v는 사실 함수 사용에서 필수적이기 때문에 쉽게 받아들일 수 있지만, $ra가 의아할 수 있을 것이다. 이는 procedure를 호출했던 시점으로 다시 돌아오기 위해서 호출한 시점의 주소(실제로는 호출한 시점에서 다음 Instruction의 주소)를 저장하고 있는 것이다. 이러한 과정 즉, $ra에 저장과 jump를 동시에 해주는 것이 jal instruction이다. 이는 바로 다음 instruction을 가르키도록 하여 PC+4로 저장하고, 특정 지점으로 이동한다. 그리고 돌아올 때에는 jr instruction을 이용해서 $ra로 돌아올 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약, 더 많은 변수를 return value, argument로 쓰고 싶다면 우리는 이를 memory로 옮기는 과정을 수행해야 한다. 이때, computer 에서는 stack이라는 구조를 사용한다. (실제로 구현하는 것은 아니고, 마치 stack 처럼 사용하기에 이렇게 부른다.) Stack pointer라는 register($sp)를 이용하여 현재 사용하고자 하는 data가 stack의 어디를 가르키고 있는지를 저장한다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;b&gt;실제 예제&lt;/b&gt;&lt;/blockquote&gt;
&lt;pre id=&quot;code_1649930639074&quot; class=&quot;cpp&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;int leaf_example (int g, int h, int i, int j) {
	int f;
	
	f = (g + h) - (i + j);
	return f;
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1649930700655&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;leaf_example:
addi $sp, $sp, &amp;ndash;12 # adjust stack to make room for 3 items
sw $t1, 8($sp) # save register $t1 for use afterwards
sw $t0, 4($sp) # save register $t0 for use afterwards
sw $s0, 0($sp) # save register $s0 for use afterwards

add $t0,$a0,$a1 # register $t0 contains g + h
add $t1,$a2,$a3 # register $t1 contains i + j
sub $s0,$t0,$t1 # f = $t0 &amp;ndash; $t1, which is (g + h)&amp;ndash;(i + j)

add $v0,$s0,$zero # returns f ($v0 = $s0 + 0)

lw $s0, 0($sp)  # restore register $s0 for caller
lw $t0, 4($sp)  # restore register $t0 for caller
lw $t1, 8($sp)  # restore register $t1 for caller
addi $sp,$sp,12 # adjust stack to delete 3 items

jr $ra # jump back to calling routine&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 방식을 통해서, 만약 우리가 argument를 각 argument register 채워주고, &quot;jal leaf_example&quot;를 수행하게 되면, 해당 함수를 실행하는 것과 같은 동작을 하게 되는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만, 더 고민해야 하는 경우가 있다. 바로 함수 안에서 또 함수를 호출하는 경우이다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;b&gt;Nested Function call(Function 내부에서 Function의 호출)&lt;br /&gt;&lt;/b&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;procedure가 또 procedure를 호출하는 경우에는 어떻게 해야할까? 이 때에는 간단한게 stack의 retuern address를 저장해놓고, $ra를 덮어씌우는 식으로 작동한다. 아래는 recursive call을 수행한 경우를 담은 내용이다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;int fact (int n) {
	if (n &amp;lt; 1) 
		return 1;
	else
		return n * fact(n-1); 
}
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;mipsasm&quot;&gt;&lt;code&gt;fact:
addi  $sp, $sp, &amp;ndash;8    # adjust stack for 2 items
sw    $ra, 4($sp)     # save the return address
sw    $a0, 0($sp)     # save the argument n
# slti 는 $a0의 값이 상수보다 작다면, 0 크다면 1이 저장됩니다.
slti  $t0, $a0, 1     # test for n &amp;lt; 1
beq   $t0, $zero, L1  # if n &amp;gt;= 1, go to L1

addi  $sp, $sp, 8     # pop 2 items off stack

addi  $v0, $zero, 1   # return 1
jr    $ra             # return to caller

L1: addi $a0,$a0,&amp;ndash;1   # n &amp;gt;= 1: argument gets (n &amp;ndash; 1)
jal fact              # call fact with (n &amp;ndash;1)

lw $a0, 0($sp)        # return from jal: restore argument n 
lw $ra, 4($sp)        # restore the return address
addi $sp, $sp, 8      # adjust stack pointer to pop 2 items

mul $v0,$a0,$v0       # return n * fact (n &amp;ndash; 1)
jr   $ra              # return to the caller
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 끝일 거 같지만, 마지막으로 생각해야 할 게 있다. 바로 내부에서 또 local variable을 선언한 경우이다. 이 경우에도 memory에 공간에 저장해야 하는데 이때에도 stack pointer를 이동 시켜서 구현하는 것은 후에 동작에 혼란을 야기할 수 있다. 따라서, frame pointer라는 것을 추가로 할당하였다. 이는 함수의 진입 시점에 stack pointer의 초기 위치를 가르킨다. 따라서, 쉽게 후에 돌아올 지점을 알 수 있기에 stack pointer를 더 유동적으로 움직일 수 있다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;여러 변수 형태 표현법&lt;/b&gt;&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Signed Numbers&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반적으로 unsigned number라고 하면, 0과 양수를 포함하는 범위이다. 하지만, signed number는 음수까지 포함한다. 그렇다면, 컴퓨터에서는 음수를 어떻게 표현할 수 있을까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사람의 머리로 가장 쉽게 생각할 수 있는 방법은 부호를 나타내기 위한 별도의 표시 bit를 하나 넣어주면 될 거 같다는 생각을 할 것이다. 이것이 정확하다. 바로 오른쪽 끝에 있는 bit가 1이면 음수 0이면 양수로 보는 방식이다. 1이 맨 앞에 올 때는 0이 원래 1의 역할을 대신한다. 그리고 0이 앞에 올 때는 원래 계산하던대로 수행하면 된다. 그러면 놀랍게도 우리가 생각하는 것처럼 덧셈 뺄셈 연산이 동작한다. 그리고 오른쪽 끝에 있는 수를 우리는 MST 라고 하고, 이를 sign bit라고 부른다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;0000 0000 0000 0000 0000 0000 0000 0000(two) = 0(ten) 
0000 0000 0000 0000 0000 0000 0000 0001(two) = 1(ten)
0000 0000 0000 0000 0000 0000 0000 0010(two) = 2(ten)
...
0111 1111 1111 1111 1111 1111 1111 1101(two) = 2,147,483,645(ten)
0111 1111 1111 1111 1111 1111 1111 1110(two) = 2,147,483,646(ten)
0111 1111 1111 1111 1111 1111 1111 1111(two) = 2,147,483,647(ten)
1000 0000 0000 0000 0000 0000 0000 0000(two) = &amp;ndash;2,147,483,648(ten)
1000 0000 0000 0000 0000 0000 0000 0001(two) = &amp;ndash;2,147,483,647(ten)
1000 0000 0000 0000 0000 0000 0000 0010(two) = &amp;ndash;2,147,483,646(ten)
...
1111 1111 1111 1111 1111 1111 1111 1101(two) = &amp;ndash;3(ten)
1111 1111 1111 1111 1111 1111 1111 1110(two) = &amp;ndash;2(ten)
1111 1111 1111 1111 1111 1111 1111 1111(two) = &amp;ndash;1(ten) 
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;b&gt;Proof&lt;br /&gt;&lt;/b&gt;&lt;/blockquote&gt;
&lt;pre id=&quot;code_1649931749967&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 덧셈
  1111 1111 1111 1110 (-2)
+                   1 (+1)
----------------------
  1111 1111 1111 1111 (-1)


                   11  (+3)
+ 1111 1111 1111 1000  (-8)
----------------------
  1111 1111 1111 1011  (-5)


# 뺄셈 1
  1111 1111 1111 1110 (-2)
-                   1 (+1)
----------------------
  1111 1111 1111 1101 (-3)


# 뺄셈 2
                   11  (+3)
- 1111 1111 1111 1000  (-8)
----------------------
                   11  (+3)
+ 0000 0000 0000 1000  (+8)
----------------------
  0000 0000 0000 1011  (+11)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;연산을 하다보면, 당연히 너무 큰 양수를 더하게 되면 overflow가 발생할 수 있는데 이 경우 운영체제마다 compiler마다 처리 방식이 상이하다. C에서는 overflow가 되면 그대로 값을 내놓기 때문에, 대게 굉장히 큰 음수가 나오게 된다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Character&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;computer에서 수가 아닌 값을 어떻게 표현할 수 있는가는 ASCII code 표가 답해줄 수 있을 것이다. 하나의 문자를 우리는 character라고 부르고, ASCII code 표와 같은 방식을 통해서 수를 글자로 변환하여 표현한다. 또한, 하나의 문자가 아닌 단어, 문장에 이르게 되면 이를 우리는 string이라고 하며, 이는 이 데이터의 길이를 표기하기 위해서 다음 3가지 중 하나를 선택하게 된다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;string의 가장 앞에 길이를 나타내는 값을 넣어준다.&lt;/li&gt;
&lt;li&gt;string을 구조체로 만들어서 길이를 나타내는 값을 따로 넣는다.&lt;/li&gt;
&lt;li&gt;string의 가장 끝 문자를 구분자로 채워서 구분할 수 있도록 한다. &amp;rArr; C에서는 \0 을 사용하여 구분한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Representing Instruction with Machine Language&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에 나온 MIPS Assembly code를 이제 MIPS의 기계어로 변환하는 과정을 수행할 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다시 한 번 설명하자면, 우리의 program들은 사실상 instruction의 집합이라고 볼 수 있다. 또한, 현대의 컴퓨터는 이러한 instruction들을 memory에 마치 데이터처럼 쌓아서 실행시킨다. 그래서 우리는 이러한 프로그램 실행 방식을 &lt;b&gt;stored program&lt;/b&gt; 이라고 부른다. 우리는 위에서 memory에 데이터를 저장하기 위해서 하나의 word 즉 32bit를 사용했다. 따라서, 우리의 instruction도 하나의 word 단위로 표현한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 그림은 32bit의 각 각 부분이 무엇을 의미하는지를 표현한 것이다. 위의 연산을 표시하기 위해서 다음과 같이 word를 구분한다. 이때 주의할 점은 큰 값을 처리할 때에는 I-Type을 사용하기 때문에 형태가 기본형인 R-Type과는 다소 다른 것을 볼 수 있다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;b&gt;R-Type&lt;/b&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;138&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/4A8Sr/btrzq6x8xWN/s2AtjOSNZsErncuHk4xWXk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/4A8Sr/btrzq6x8xWN/s2AtjOSNZsErncuHk4xWXk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/4A8Sr/btrzq6x8xWN/s2AtjOSNZsErncuHk4xWXk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F4A8Sr%2Fbtrzq6x8xWN%2Fs2AtjOSNZsErncuHk4xWXk%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;1280&quot; height=&quot;138&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;138&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;op : opcode라고 불리며, instruction의 동작이 무엇인지를 정의한다. (ex. add, jump, ...)&lt;/li&gt;
&lt;li&gt;rs : first source register&lt;/li&gt;
&lt;li&gt;rt : second source register&lt;/li&gt;
&lt;li&gt;rd : destination register. 연산의 결과값이 저장되는 위치를 의미한다.&lt;/li&gt;
&lt;li&gt;shamt : shift amount라는 의미로 shift 연산을 사용할 때 이용된다.&lt;/li&gt;
&lt;li&gt;funct : op field에서 구체적인 동작을 정의할 때 사용한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;b&gt;I-Type&lt;br /&gt;&lt;/b&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;138&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/GcZfL/btrzqztNXMR/kn0klKoouEUxGjhBs5nfn0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/GcZfL/btrzqztNXMR/kn0klKoouEUxGjhBs5nfn0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/GcZfL/btrzqztNXMR/kn0klKoouEUxGjhBs5nfn0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGcZfL%2FbtrzqztNXMR%2Fkn0klKoouEUxGjhBs5nfn0%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;1280&quot; height=&quot;138&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;138&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;op : opcode라고 불리며, instruction의 동작이 무엇인지를 정의한다. (ex. addi, jump, ...)&lt;/li&gt;
&lt;li&gt;rs : first source register&lt;/li&gt;
&lt;li&gt;rt : second source register&lt;/li&gt;
&lt;li&gt;constraint or address : 긴 값이 필요한 연산에서는 다음과 같은 형태로 표현한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Addressing&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MIPS는 여러가지 instruction을 가지고 있기 때문에, 주소를 targeting하는 방식도 여러가지이다. 또한, 따른 instruction set architecture에서도 다양한 방법을 통해서 memory의 주소를 가르킨다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Immediate addressing : 상수를 통해 직접 address를 지정하는 방식이다.&lt;/li&gt;
&lt;li&gt;Register addressing : register로 address를 지정하는 방식이다.&lt;/li&gt;
&lt;li&gt;Base addressing : 상수에 특정 register값을 더해서 구하는 방식이다.(MIPS &amp;rarr; Load Word, Save Word)&lt;/li&gt;
&lt;li&gt;PC-relative addressing : PC 값에 상수 값을 더해서 구하는 방식이다. (MIPS &amp;rarr; Branch)&lt;/li&gt;
&lt;li&gt;Psedodirect addressing : PC의 맨앞 내자리를 가져와서 쓰는 방식이다. (MIPS &amp;rarr; Jump)&lt;/li&gt;
&lt;/ol&gt;</description>
      <category>Computer Architecture</category>
      <category>Computer Architecture</category>
      <category>instruction</category>
      <category>MIPS Instruction Set</category>
      <category>MIPS Operation</category>
      <category>컴퓨터구조</category>
      <author>euidong</author>
      <guid isPermaLink="true">https://justlog.tistory.com/39</guid>
      <comments>https://justlog.tistory.com/39#entry39comment</comments>
      <pubDate>Thu, 14 Apr 2022 20:28:34 +0900</pubDate>
    </item>
    <item>
      <title>Dynamic Programming</title>
      <link>https://justlog.tistory.com/38</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;정의&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리말로 동적 계획법이라고 번역되어지는 말입니다. 우선 명칭에 대해서 좀 어색할 수 있다. 이는 해당 어원이 오래되었기 때문입니다. 당시에 programming이란 문제 풀이를 위한 planning(계획) 정도로 생각했습니다. 따라서, &lt;b&gt;Dynamic Programming이 의미하는 바는 다단계 처리에 대한 최적화된 계획법 정도로 해석&lt;/b&gt;할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Dynamic Programming을 사용하기 위해서는 해당 문제가 다음과 같은 조건을 만족할 때입니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;Optimal Substructure&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Overlapping Subproblem&lt;/b&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Optimal Substructure&lt;/b&gt;란 문제의 최적해가 이것의 하위 문제(subproblem)의 최적해에 의해서 정의되어질 수 있어야 한다는 것입니다. 쉽게 말해서 수열의 경우 점화식을 작성할 수 있어야 한다는 의미입니다. 가장 일반적인 예시가 fibonacci 수열을 예로 들 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$$ fibo(n) = fibo(n-1) + fibo(n-2)$$&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Overlapping Subproblem&lt;/b&gt;이란 문제의 하위 문제(subproblem)들이 중첩해서 사용되는 경우를 말합니다. 위의 fibonacci 수열만 보아도 fibo(100)은 fibo(101), fibo(102)를 계산하기 위해서 쓰이기 때문에 중복이 발생하며, 더 나아가 fibo(101), fibo(102)를 사용하는 경우에는 fibo(100)을 다시 계산해야 합니다. 이것은 굉장한 비용을 초례합니다.&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;이러한 문제들에 대한 해결책으로써 Dynamic Programming에서는 점화식을 이용해서 문제를 해결하지만, 이때, 한 번 계산한 값을 두 번 계산하지 않도록 하는 것입니다. &lt;b&gt;이를 가능하게 하는 것이 Memoization(함수의 실행 결과를 저장)입니다. &lt;/b&gt;즉, 이전에 호출한 함수의 결과값을 별도의 저장 공간(array, list, map, file 등)에 저장해두는 것입니다. 이를 통해서 우리는 problem의 subproblem이 이미 계산된 적이 있다면, 하위 문제를 다시 풀 필요없이 바로 solution(점화식)을 계산할 수 있는 것입니다. 이를 통해서,&lt;b&gt; 계산 시간을 획기적으로 줄일 수 있습니다. 하지만, 추가적인 memory를 사용한다는 점을 반드시 기억해야 합니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 계속해서 반복 및 교체되어 사용되는 단어가 점화식, solution, optimal substructure, function, 함수입니다. 이는 모두 같은 뜻을 가지는데, 여기서도 특히 함수는 &lt;b&gt;referential transparency&lt;/b&gt;를 보장하는 함수만을 지칭합니다. 수학에서는 아주 당연한 얘기이지만, input값이 동일할 때 항상 같은 output을 내놓아야 한다는 것입니다. programming에서의 함수는 대게 side effect가 존재할 수 있고, 외부 변수를 사용하기도 하므로, 같은 input이라도 상황(context)에 따라 다른 output이 발생할 수도 있는데 이러한 것이 해당 함수에서는 발생해서는 안된다는 것입니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;구현&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본적으로 Dynamic Programming을 적용하기 위해서는 반드시 위에서 언급한 두 조건을 만족하는지를 확인해야 합니다. 따라서, 먼저 점화식을 찾아내고, 이것이 반복 사용되는지를 반드시 확인한 후에 적용하는 것이 기본입니다.&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;Dynamic Programming의 기본적인 구현 방식은 두 가지가 존재합니다. 둘 다 장단점이 있기 때문에 이것에 유의하여 사용해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서, 아래에서는 가장 기본적인 예시로 combination을 구하는 방식을 두 가지 방식으로 구현하겠습니다. 일단 Combination은 다음과 같은 점화식을 만족합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$$ {{}_{n}C_{k}} = {{}_{n-1}C_{k-1}} + {{}_{n-1}C_{k}}$$&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서, 이를 Dynamic Programming을 통해서 구현할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1. Top Down(=Recursive)&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;먼저 input으로 들어올 데이터의 크기를 고려하여, cache list의 크기를 지정합니다. 그 후에 점화식을 함수 내에서 나타내고, 해당 함수값을 return해주면 됩니다. 이때 중요한 것이 이미 함수값을 계산한 적이 있는지를 확인하고 있다면, 바로 return해버리는 점입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1649909764301&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;size = 100
# 1차원 배열
cache = [-1] * size

# 2차원 배열
cache = [[-1 for _ in range(size)] for _ in range(size)]

# 기저값 세팅
cache[0][0] = 1
cache[1][0] = 1
cache[1][1] = 1

# 함수 지정
def recursive_call(a, b):
    # 이미 저장된 값이 있는 경우 return
    if cache[a][b] != -1:
        return cache[a][b]
    # 없다면, 연산 및 저장 후 return
    cache[a][b] = cache[a-1][b-1] + cache[a-1][b]
    return cache[a][b]
    
print(recursive_call(10, 2))&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 방식의 가장 큰 장점은 이해하기 쉽다는 것입니다. 점화식이 분명하게 들어나며, 값을 찾아가는 과정을 상상하는 것이 쉽습니다. 또한, 모든 경우의 수를 탐색하지 않을 수 있다는 점이 있습니다. 왜냐하면, 연관된 데이터만 찾기 때문에 관련 없는 데이터는 찾지 않을 수도 있습니다. &lt;b&gt;하지만,&amp;nbsp;&lt;/b&gt;recursive call인 만큼 함수 호출의 최대 횟수가 정해져있어, 모든 경우에 올바른 답을 찾지는 못합니다. 이를 해결하기 위해서 끊어서 실행 시켜두는 방법도 있습니다. 예를들어 200을 구하는 문제면, 50, 100, 150을 미리 호출해둡니다. 하지만, 이 또한, 매번 적용할 수 있는 방법은 아니기에 대다수의 경우에는 Bottom Up으로 구현하는 것을 추천합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2. Bottom Up(with Loop)&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 똑같은 원리를 이용해서 구현한 Combination입니다. for문을 이용해서 처음부터 끝까지 구하면서 올라가는 방식입니다. 이렇게 하게 되면, 빈틈없이 아래부터 계산하는지를 체크하면서 구현해야합니다. 중간에 빈값이 발생하는 경우가 없도록 하는 것이 중요합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1649910342061&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;size = 100
# 1차원 배열
cache = [-1] * size

# 2차원 배열
cache = [[-1 for _ in range(size)] for _ in range(size)]

# 기저값 세팅
cache[0][0] = 1
cache[1][0] = 1
cache[1][1] = 1

# 함수 지정
for i in range(2, size):
	for j in range(0, i+1):
    	cache[i][j] = cache[i-1][j-1] + cache[i-1][j]
    
print(cache[10][2])&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;문제 풀이&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모든 Dynamic Programming 문제를 풀기 위해서 거쳐야 하는 단계는 총 3단계입니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;문제를&lt;/b&gt; &lt;b&gt;정의&lt;/b&gt;한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;점화식&lt;/b&gt;을 찾는다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;시간 복잡도&lt;/b&gt;를 만족하는지 확인한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;공간 복잡도&lt;/b&gt;를 만족하는지 확인한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제를 정의하고, 점화식을 찾을 때에 나타나는 대략 4가지 유형을 나누어 보았습니다. 제가 만든 분류기준이니 공식적이지는 않습니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;1. 자신의 Subproblem으로만 표현되는 유형&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;A = operate(sub A, sub A)&lt;/b&gt;와 같은 형태로 나타나는 경우를 말한다. 이 경우에는 문제의 재정의가 필요없이 바로 점화식을 작성하면 됩니다. 이런 유형의 문제가 위에서 살펴보았던 combination, fibonacci가 대표적입니다. 가장 기본적인 예시를 풀어봅시다.&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;b&gt;백준 11726&lt;br /&gt;&lt;/b&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;*문제를 읽고 오시기 바랍니다.&lt;/p&gt;
&lt;figure id=&quot;og_1649998964706&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;11726번: 2&amp;times;n 타일링&quot; data-og-description=&quot;2&amp;times;n 크기의 직사각형을 1&amp;times;2, 2&amp;times;1 타일로 채우는 방법의 수를 구하는 프로그램을 작성하시오. 아래 그림은 2&amp;times;5 크기의 직사각형을 채운 한 가지 방법의 예이다.&quot; data-og-host=&quot;www.acmicpc.net&quot; data-og-source-url=&quot;https://www.acmicpc.net/problem/11726&quot; data-og-url=&quot;https://www.acmicpc.net/problem/11726&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/z76cr/hyN2AMbESK/msKoOcejbWQD5nnWfKcOKK/img.png?width=2834&amp;amp;height=1480&amp;amp;face=0_0_2834_1480,https://scrap.kakaocdn.net/dn/MgzH7/hyN2HdsKiP/JnlSTwj1loYk65fmeeYlm0/img.png?width=1381&amp;amp;height=554&amp;amp;face=0_0_1381_554&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/11726&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.acmicpc.net/problem/11726&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/z76cr/hyN2AMbESK/msKoOcejbWQD5nnWfKcOKK/img.png?width=2834&amp;amp;height=1480&amp;amp;face=0_0_2834_1480,https://scrap.kakaocdn.net/dn/MgzH7/hyN2HdsKiP/JnlSTwj1loYk65fmeeYlm0/img.png?width=1381&amp;amp;height=554&amp;amp;face=0_0_1381_554');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;11726번: 2&amp;times;n 타일링&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;2&amp;times;n 크기의 직사각형을 1&amp;times;2, 2&amp;times;1 타일로 채우는 방법의 수를 구하는 프로그램을 작성하시오. 아래 그림은 2&amp;times;5 크기의 직사각형을 채운 한 가지 방법의 예이다.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.acmicpc.net&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 이 문제는 2xN 평면에 타일을 채울 수 있는 경우의 수를 찾는 것이 목표입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서, $cache[n] = \text{2xN을 채울 수 있는 경우의 수}$라고 정의하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한, 규칙을 찾아보면 해당 값은 다음과 같은 pattern을 가진다는 것을 알 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;IMG_15A003BE6A04-1.jpeg&quot; data-origin-width=&quot;3201&quot; data-origin-height=&quot;1000&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tnObT/btrzuvLQAOV/1VrJCZIjoo9pRmtKGzFBXK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tnObT/btrzuvLQAOV/1VrJCZIjoo9pRmtKGzFBXK/img.jpg&quot; data-alt=&quot;f(n) = f(n-1) + f(n-2)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tnObT/btrzuvLQAOV/1VrJCZIjoo9pRmtKGzFBXK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtnObT%2FbtrzuvLQAOV%2F1VrJCZIjoo9pRmtKGzFBXK%2Fimg.jpg&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;598&quot; height=&quot;187&quot; data-filename=&quot;IMG_15A003BE6A04-1.jpeg&quot; data-origin-width=&quot;3201&quot; data-origin-height=&quot;1000&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;f(n) = f(n-1) + f(n-2)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;f(n)의 처음 시작을 세로 block으로 시작하면, 다음 block들의 경우의 수는 모두 이전에 구한 경우의 수와 같고, 처음 block을 가로 block으로 설정하면, 위에 block을 놓으면 아래도 가로로 놓는 것이 강제됩니다. 따라서, 가로로 위 아래를 두는 수 밖에 없고, 이렇게 두면 이전전에 두었던 것과 동일한 형태로 놓는 경우의 수만큼의 경우를 갖게 됩니다. 따라서, 결론상 현재의 block의 경우의 수는 이렇게 두 개의 경우의 수의 합으로 정의할 수 있는 것입니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;관련 유형 : 1463, 11727, 11052, 16194, 15988, 1699, 2193&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2. 문제의 재정의가 필요한 유형&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;A = operate(B), A' = operate(sub B, sub B)&lt;/b&gt;와 같은 형태로 나타나는 경우를 말한다. 이와 같은 유형은 기존에 제시된 문제에 특정 조건을 추가하여, 최종값을 구한 후에 이를 이용해서 답을 구하는 방식입니다. 이 경우에는 문제를 다시 정의해야 하기 때문에 다소 어려울 수 있습니다. 쉬운 예제부터 풀어보겠습니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;b&gt;백준 1912&lt;/b&gt;&lt;/blockquote&gt;
&lt;figure id=&quot;og_1649999847920&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;1912번: 연속합&quot; data-og-description=&quot;첫째 줄에 정수 n(1 &amp;le; n &amp;le; 100,000)이 주어지고 둘째 줄에는 n개의 정수로 이루어진 수열이 주어진다. 수는 -1,000보다 크거나 같고, 1,000보다 작거나 같은 정수이다.&quot; data-og-host=&quot;www.acmicpc.net&quot; data-og-source-url=&quot;https://www.acmicpc.net/problem/1912&quot; data-og-url=&quot;https://www.acmicpc.net/problem/1912&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/Ny9q9/hyN2GyTAmd/T1fwSRXxBxNOf7rlb3Ciy1/img.png?width=2834&amp;amp;height=1480&amp;amp;face=0_0_2834_1480&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/1912&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.acmicpc.net/problem/1912&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/Ny9q9/hyN2GyTAmd/T1fwSRXxBxNOf7rlb3Ciy1/img.png?width=2834&amp;amp;height=1480&amp;amp;face=0_0_2834_1480');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;1912번: 연속합&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;첫째 줄에 정수 n(1 &amp;le; n &amp;le; 100,000)이 주어지고 둘째 줄에는 n개의 정수로 이루어진 수열이 주어진다. 수는 -1,000보다 크거나 같고, 1,000보다 작거나 같은 정수이다.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.acmicpc.net&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 문제는 점화식으로 나타기가 어렵습니다. 따라서, 약간 문제를 바꾸어서 나타내야 합니다. 수열을 A라 하고, 수열의 i번째 원소를 A[i]라고 할 때, A[i]를 마지막 연속 합의 값으로 했을 때, 최댓값을 S[i]라고 합시다. 이 경우에 이전의 연속합이 음수인 경우는 오히려 값이 낮아지기 때문에 이때는 A[i]를 반환하고, 그렇지 않은 경우에는 S[i-1]에 A[i]를 더해서 연속합을 구하면 됩니다. 따라서 다음과 같은 형태가 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$$ \begin{align} S[i] &amp;amp; = S[i-1] + A[i] (\text{if } S[i-1] &amp;gt; 0)\\ &amp;amp; = A[i] \end{align} $$&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;와 같은 형태로 나타낼 수 있습니다. 이를 이용해서, S 중에서 가장 큰 값을 찾으면, 그것이 답이 됩니다. 여기서 S가 cache와 같은 역할입니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;관련 유형 : 11053, 2225&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;3. Problem의 Subproblem과 다른 Subproblem이 연계되는 유형&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;A= operate(sub A, sub B), B = operate(sub A, sub B)&lt;/b&gt;와 같은 형태로 나타나는 경우를 말합니다. 이와 같은 유형은 두 개 이상의 subproblem이 서로 연계되기 때문에 이들을 동시에 연산하면서, 진행해야 합니다. 일반적으로는 이중 배열을 이용해서 수행하는 것이 일반적입니다. 이런 내용들을 대게 문제에서 제약사항이 있는 문제에 많이 사용됩니다. 예제를 보면 쉽게 이해가 됩니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;b&gt;백준 2133&lt;/b&gt;&lt;/blockquote&gt;
&lt;figure id=&quot;og_1650002518274&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;2133번: 타일 채우기&quot; data-og-description=&quot;3&amp;times;N 크기의 벽을 2&amp;times;1, 1&amp;times;2 크기의 타일로 채우는 경우의 수를&amp;nbsp;구해보자.&quot; data-og-host=&quot;www.acmicpc.net&quot; data-og-source-url=&quot;https://www.acmicpc.net/problem/2133&quot; data-og-url=&quot;https://www.acmicpc.net/problem/2133&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/2133&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.acmicpc.net/problem/2133&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;2133번: 타일 채우기&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;3&amp;times;N 크기의 벽을 2&amp;times;1, 1&amp;times;2 크기의 타일로 채우는 경우의 수를&amp;nbsp;구해보자.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.acmicpc.net&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞 서 풀었던 2xn 타일 문제와 똑같지만, 3xn으로 바뀌었을 뿐이다. 이번에도, 앞에서 부터 한 번씩 경우의 수를 따져보는 것이 중요하다. 먼저 세로를 넣은 경우에는 아래에 가로가 하나 강제되는 것을 볼 수 있다. 그리고, 가로로 넣은 경우에는 세로로 세우거나 가로로 세우는 것을 볼 수 있다. 따라서, 3가지의 경우의 수로 볼 수 있다. 하지만, 우리가 구하고자 하는 모양과는 다른 모양의 조각이 남는 것을 볼 수 있다. 따라서, 우리가 구하고자 하는 것(3xn을 채우는 경우의 수)을 cache[n][0]이라 하고, 그를 위해 부가적으로 해결해야 하는 문제(밑변이 n이고, 윗변은 n-1, 좌는 2, 우는 3인 도형을 채우는 경우의 수)를 cache[n][1]이라고 하자.&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-filename=&quot;IMG_01B90AE76808-1.jpeg&quot; data-origin-width=&quot;2237&quot; data-origin-height=&quot;1000&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cCJS5P/btrzrLJiFHi/51v9diNA3lDrAo1nHXCQaK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cCJS5P/btrzrLJiFHi/51v9diNA3lDrAo1nHXCQaK/img.jpg&quot; data-alt=&quot;cache[n][0] = cache[n-2][0] + 2 x cache[n-1][1]&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cCJS5P/btrzrLJiFHi/51v9diNA3lDrAo1nHXCQaK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcCJS5P%2FbtrzrLJiFHi%2F51v9diNA3lDrAo1nHXCQaK%2Fimg.jpg&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;869&quot; height=&quot;388&quot; data-filename=&quot;IMG_01B90AE76808-1.jpeg&quot; data-origin-width=&quot;2237&quot; data-origin-height=&quot;1000&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;cache[n][0] = cache[n-2][0] + 2 x cache[n-1][1]&lt;/figcaption&gt;
&lt;/figure&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-filename=&quot;IMG_890A4C7252E4-1.jpeg&quot; data-origin-width=&quot;3625&quot; data-origin-height=&quot;1000&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bYQ0ta/btrzsQp5dmr/VWtQwokS7gzDzoummWh8JK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bYQ0ta/btrzsQp5dmr/VWtQwokS7gzDzoummWh8JK/img.jpg&quot; data-alt=&quot;cache[n][1] = cache[n-1][0] + cache[n-1][1]&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bYQ0ta/btrzsQp5dmr/VWtQwokS7gzDzoummWh8JK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbYQ0ta%2FbtrzsQp5dmr%2FVWtQwokS7gzDzoummWh8JK%2Fimg.jpg&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;3625&quot; height=&quot;1000&quot; data-filename=&quot;IMG_890A4C7252E4-1.jpeg&quot; data-origin-width=&quot;3625&quot; data-origin-height=&quot;1000&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;cache[n][1] = cache[n-1][0] + cache[n-1][1]&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 이를 반복해서 풀어나가면 쉽게 답을 구할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 식으로 하나의 subproblem을 풀기 위해서 연계되는 subproblem이 생기는 유형도 존재한다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&amp;nbsp;관련 유형 : 11054, 13398, 1309, 2156, 1149&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;4. 동적계획법을 통해서 얻은 결과값을 추적하는 유형&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 유형은 상당히 간단하게도 parent라는 별도의 list를 만들어서 구현할 수 있다. 즉, cache의 값을 갱신해줄 때 영향을 준 subproblem의 index를 저장해두는 것이다. 이를 통해서 해당 값이 어디서부터 유래되었는지를 후에 추적하는 것이 가능하다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;b&gt;백준 14002&lt;/b&gt;&lt;/blockquote&gt;
&lt;figure id=&quot;og_1650004912517&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;14002번: 가장 긴 증가하는 부분 수열 4&quot; data-og-description=&quot;수열 A가 주어졌을 때, 가장 긴 증가하는&amp;nbsp;부분&amp;nbsp;수열을 구하는 프로그램을 작성하시오. 예를 들어, 수열 A = {10, 20, 10, 30, 20, 50} 인 경우에 가장 긴 증가하는 부분&amp;nbsp;수열은&amp;nbsp;A = {10, 20, 10, 30, 20, 50} 이&quot; data-og-host=&quot;www.acmicpc.net&quot; data-og-source-url=&quot;https://www.acmicpc.net/problem/14002&quot; data-og-url=&quot;https://www.acmicpc.net/problem/14002&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/fK8Qk/hyN2Ow021c/sW08JKdDKb31YXaNS3bzA1/img.png?width=2834&amp;amp;height=1480&amp;amp;face=0_0_2834_1480&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/14002&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.acmicpc.net/problem/14002&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/fK8Qk/hyN2Ow021c/sW08JKdDKb31YXaNS3bzA1/img.png?width=2834&amp;amp;height=1480&amp;amp;face=0_0_2834_1480');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;14002번: 가장 긴 증가하는 부분 수열 4&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;수열 A가 주어졌을 때, 가장 긴 증가하는&amp;nbsp;부분&amp;nbsp;수열을 구하는 프로그램을 작성하시오. 예를 들어, 수열 A = {10, 20, 10, 30, 20, 50} 인 경우에 가장 긴 증가하는 부분&amp;nbsp;수열은&amp;nbsp;A = {10, 20, 10, 30, 20, 50} 이&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.acmicpc.net&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;유형 2와 동일한 풀이로 풀 수 있는 문제이다. 만약, cache값을 수정하는 연산이 발생하면, parent를 변경하면 된다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에 언급한 모든 풀이는 해당 Github에 존재합니다.&lt;/p&gt;
&lt;figure id=&quot;og_1650007160474&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - euidong/BOJ: 백준 알고리즘 문제 풀이&quot; data-og-description=&quot;백준 알고리즘 문제 풀이. Contribute to euidong/BOJ development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/euidong/BOJ&quot; data-og-url=&quot;https://github.com/euidong/BOJ&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bp4iSN/hyN2IcvuE5/iWyzurYgJBY9OOnXt3uta1/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/euidong/BOJ&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/euidong/BOJ&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bp4iSN/hyN2IcvuE5/iWyzurYgJBY9OOnXt3uta1/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;GitHub - euidong/BOJ: 백준 알고리즘 문제 풀이&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;백준 알고리즘 문제 풀이. Contribute to euidong/BOJ development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Algorithm</category>
      <category>#BOJ2133</category>
      <category>Algorithm</category>
      <category>BOJ11726</category>
      <category>BOJ14002</category>
      <category>BOJ1912</category>
      <category>dynamic programming</category>
      <category>memoization</category>
      <category>Optimal Structural</category>
      <category>Overlapping Subproblem</category>
      <category>Referential Transparency</category>
      <author>euidong</author>
      <guid isPermaLink="true">https://justlog.tistory.com/38</guid>
      <comments>https://justlog.tistory.com/38#entry38comment</comments>
      <pubDate>Thu, 14 Apr 2022 13:51:12 +0900</pubDate>
    </item>
    <item>
      <title>1. Abstractions and Tech</title>
      <link>https://justlog.tistory.com/37</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Reference&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;405&quot; data-origin-height=&quot;500&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/la201/btrziwY9I6f/8joG3LTLhuzL84KHvKgJI0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/la201/btrziwY9I6f/8joG3LTLhuzL84KHvKgJI0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/la201/btrziwY9I6f/8joG3LTLhuzL84KHvKgJI0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fla201%2FbtrziwY9I6f%2F8joG3LTLhuzL84KHvKgJI0%2Fimg.jpg&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;220&quot; height=&quot;272&quot; data-origin-width=&quot;405&quot; data-origin-height=&quot;500&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;David A. Patterson, John L. Hennessy&lt;b&gt;,&lt;/b&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;Computer Organization and Design&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;본 Posting은 다음 교제를 기반으로 챕터 별로 정리 한 내용입니다. 아래부터는 편의를 위해 &quot;-다&quot;로 표현합니다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;1. 8 Greate Ideas&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴퓨터 구조를 설계하는 과정에서 중요하게 여겨지는 8가지 핵심 아이디어들이다. 뿐만 아니라 이는 전체적인 컴퓨터 과학에서 중요하다고 볼 수 있는 아이디어들이다. 따라서, 앞으로의 Posting에서 Why라는 의문이 든다면, 아래 8가지 이유 중의 하나로 설명할 수 있다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;Moore's Law&lt;/b&gt;&lt;br /&gt;18 ~ 24 개월마다 컴퓨터 성능의 지대한 영향을 미치는 IC 칩의 성능이 2배씩 성장한다는 Moore의 주장에서 유래하였다. 즉, &lt;b&gt;컴퓨터의 성능은 지수적으로 빠르게 성장을 하고 있음을 의미한다.&lt;/b&gt; 이로 인해 구조를 설계하는 과정에서도 현재의 IC 칩의 성능에 맞추는 것이 아닌 이보다 더 큰 성능을 타겟으로 설정을 한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Abstraction&lt;br /&gt;&lt;/b&gt;우리 말로 추상화라고 표현하며, 복잡한 하위 내용을 모두 기술하지 않고, 간단하게 표현하여 이를 쉽게 사용할 수 있도록 하는 방식이다. 이를 통해서, &lt;b&gt;설계 과정에서의 복잡도를 줄일 수 있다.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Common Case Fast&lt;br /&gt;드물게 일어나는 case보다는 일반적인 case를 빠르게 만듬으로써 성능을 향상시킬 수 있다.&lt;/b&gt; 드물게 일어나는 case는 매우 복잡하고, 해결하기도 난해할 수 있다. 하지만, 대게의 경우 일반적인 case는 간단하다. 이를 최적화하는 것이 전체적인 시스템 성능 향상에 큰 도움이 되는 것은 당연하며 해결도 매우 쉽다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Performance via Parallelism&lt;br /&gt;&lt;/b&gt;성능 향상을 위한 방법은 크게 두 가지이다. 하나는 하나의 장치의 성능을 올리는 것이고 또 하나가 바로&amp;nbsp;&lt;b&gt;하나의 작업을 여러 명이 동시에 수행하는 방식이다.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Performance via Pipelining&lt;br /&gt;&lt;/b&gt;성능 향상을 위한 병렬처리 방식 중에서 가장 유명한 방식이 pipelining이다. 쉽게 생각하면, 분업이라고 할 수 있다. &lt;b&gt;여러 명이서 하나의 목적을 위해 일을 할 때, 효율적으로 작업하기 위해서 업무를 분담하여 동시에 작업&lt;/b&gt;하는 방식이다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Performance via Prediction&lt;/b&gt;&lt;br /&gt;우리는 무슨 작업을 할 때, 아직 결정되지 않은 사항 때문에 기다리는 경우가 있는데, 이것이 어떻게 될지를 &lt;b&gt;예측하여 기다리지 않고, 미리 진행하자&lt;/b&gt;는 발상에서 나온 것이다. 만약, 이 예측의 적중률이 높다면, 성능 향상에 굉장한 도움을 줄 수 있다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Hierarchy of Memories&lt;br /&gt;&lt;/b&gt;컴퓨터의 사용자가 원하는 메모리는 빠르고, 크고, 싸야 한다. 하지만, 빠르기 위해서는 비싸야하고, 크기 위해서도 비싸야 한다. 그래서 생각해낸 방법이 계층화이다. &lt;b&gt;빠르고, 작은 memory를 위로 쌓고, 느리고, 큰 memory를 아래로 쌓음으로써 비용을 절감&lt;/b&gt;하자는 것이다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Dependability via Redundancy&lt;/b&gt;&lt;br /&gt;컴퓨터는 빠르기만 해서 되는 것은 아니다. &lt;b&gt;신뢰&lt;/b&gt;할 수 있는 시스템을 구축해야 한다. 실패하지 않는 시스템을 구축하는 것은 매우 힘든 일이기 때문에, 우리는 &lt;b&gt;여분 장치&lt;/b&gt;를 두어 이를 통해서 실패 시에 이를 떠맡을 수 있도록 하는 설계를 해야 한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;2. Below Your Program&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;program 밑에는 무엇이 있는가?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리의 program은 모두 application software이고, 이는 hardware 바로 위에 존재하는 것이 아닌 system software위에서 동작하게 된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;993&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cEcFBe/btrzihH1tG3/5YgprsS5mFqKpJRznGA33K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cEcFBe/btrzihH1tG3/5YgprsS5mFqKpJRznGA33K/img.png&quot; data-alt=&quot;Computer Architecture Nutshell&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cEcFBe/btrzihH1tG3/5YgprsS5mFqKpJRznGA33K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcEcFBe%2FbtrzihH1tG3%2F5YgprsS5mFqKpJRznGA33K%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;612&quot; height=&quot;475&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;993&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Computer Architecture Nutshell&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;System Software&lt;/b&gt;는 Hardware를 직접적으로 제어하거나 computer가 작동하기 위해 필수적이며 기본적인 softwre를 말한다. 그 중에서 가장 대표적인 것이 OS이고 &lt;b&gt;OS&lt;/b&gt;는 사실상 우리가 보는 Software와 Hardware 간의 interface역할을 한다. 예를 들어, memory 관리, process 관리 등(이는 OS 에서 자세히 배웁시다.)을 수행한다. 반면, &lt;b&gt;Application&lt;/b&gt; &lt;b&gt;Software&lt;/b&gt;는 직접적으로 hardware를 관리하거나 필수적인 요소는 아니지만 computer를 통해서 가치있는 작업을 수행하도록 한다. 대표적인 예시가 웹브라우저, word, game 등이 여기에 포함된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 그렇다면, 우리가 만든 코드(Application Software)가 어떻게 실행되어질 수 있을까? 이 또한, System Software인 compiler, assembler, linker, loader의 도움을 통해서 실행되어진다. &lt;b&gt;compiler&lt;/b&gt;는 우리가 고 수준의 언어(C++, Java, 등)로 만든 software code를 Assembly 언어로 변경한다. 그러면, 이를 &lt;b&gt;Assembler&lt;/b&gt;가 0과 1로 이루어진 기계어로 번역해준다. 해당 작업이 끝나면, &lt;b&gt;Linker&lt;/b&gt;가 나타나 여러 개로 나뉘어져있던 이 파일과 기존 라이브러리를 하나의 파일로 묶어주는 역할을 한다. 이 작업을 마치고 만들어진 최종 파일을 실행하고자할 때, &lt;b&gt;Loader&lt;/b&gt;는 이를 memory에 올리는 역할을 한다. 이렇게 실행된 program은 여기서 그치지 않고, memory의 아예 다른 영역에 위치하는 library도 불러와서 사용하는 것이 가능하다. 이것을 &lt;b&gt;Dynamic Linked Library&lt;/b&gt;(DLL)라고 한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;1122&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Z6TSD/btrzgJdqXvk/gGeoG27X4kOiAJOm89ZLqK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Z6TSD/btrzgJdqXvk/gGeoG27X4kOiAJOm89ZLqK/img.png&quot; data-alt=&quot;하나의 코드가  하나의 process가 되기까지의 과정&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Z6TSD/btrzgJdqXvk/gGeoG27X4kOiAJOm89ZLqK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZ6TSD%2FbtrzgJdqXvk%2FgGeoG27X4kOiAJOm89ZLqK%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;556&quot; height=&quot;624&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;1122&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;하나의 코드가  하나의 process가 되기까지의 과정&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 하나의 코드를 작성하면, 실제로 실행되기까지 여러 작업들을 거쳐야만 한다. 그럼에도 assembly 언어나 기계어를 사용하여 코딩을 하지 않는 이유는 아래 세 가지 이유가 주요하다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;사람이 이해하기 쉽다.&lt;/li&gt;
&lt;li&gt;생산성을 높일 수 있다.&lt;/li&gt;
&lt;li&gt;Compiler와 assembly를 통해서 어디서든 돌아가는 프로그램을 제작할 수 있다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;3. Under the Covers&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리의 컴퓨터는 어떻게 이루어지는가를 크고 얇게 한 번 알아볼 것이다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Input Device&lt;/b&gt; : 우리의 입력을 받는 부분이다. 마우스, 키보드, 터치스크린 등이 있다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Output Device&lt;/b&gt; : 우리가 출력을 받는 부분이다. 모니터, 프린터 등이 있다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;IC(Integrated Circuits, Chip)&lt;/b&gt; : 집적 회로로 번역되어지며, 통상 우리가 chip이라고 부르는 녀석들이다. 이들은 적게는 수십개 많게는 억 단위 이상에 이르는 양의 transister를 가지고 있고, 이를 통해서 데이터를 저장하거나 처리하는 역할을 할 수 있다. 즉, IC를 통해서 CPU, Memory를 만들 수 있다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;trasistor: 쉽게 말해서 전기를 통해서 on/off를 수행할 수 있는 switch라고 볼 수 있다. 이를 통해서, 데이터를 연산하거나 저장하는 것이 가능하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;CPU (Central Processor Unit, Processor, MicroProcessor)&lt;/b&gt; : 중앙 처리 장치라는 의미로, 각종 연산과 I/O Device 처리 등의 중심 역학을 수행한다. CPU는 크게 두 개의 요소로 이루어진다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;DataPath : 수학적인 연산을 수행한다.&lt;/li&gt;
&lt;li&gt;Control : program의 instruction이 무엇을 요구하는지를 입출력 장치, memory 또는 datapath에 전달합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Memory(RAM(Random Access Memory), main memory, primary memory)&lt;/b&gt; : 실행되고 있는 프로그램이 위치하는 곳이다. 실행되는 프로그램에 대한 정보와 같은 내용을 포함한다고 할 수 있다. 이는 DRAM으로 이루어진다. 또한, Random Access Memory라고 불리는 이유는 어느 위치에 데이터를 저장하고 있어도 해당 데이터를 찾는데 걸리는 시간이 동일하기 때문이다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;DRAM(Dynamic Random Access Memory) : IC chip을 통해서 만들어진다. 여기서 Random Access란 접근할 때, 앞에서부터 차례로 접근하는 것이 아닌 한 번에 바로 짚을 수 있음을 의미한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Cache Memory&lt;/b&gt; : 대게 Cache라고도 부르며, Processor 내부에 존재하는 memory라고 볼 수 있다. 즉, 실제 Memory의 buffer 기능을 한다. 여기서는 SRAM을 사용한다.&lt;/li&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;SRAM(Static Random Aceess Memory) : DRAM보다는 빠르지만, 집적도가 낮고 더 비싸기 때문에 많이 사용할 수는 없는 chip이다. 하지만, 성능 향상을 위해서 processor 바로 앞에 buffer로써 사용한다.&lt;/li&gt;
&lt;li&gt;buffer : 자료구조의 queue를 이용한 것으로, 처리를 요청한 대상과 처리를 수행하는 대상 사이에서 데이터를 잠깐 보관하기 위한 장소로 사용된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;&lt;b&gt;Secondary Memory&lt;/b&gt; : main memory는 휘발성이라는 특징을 갖고 있기 때문에 시스템이 종료되어 전기가 더 이상 공급되지 않으면, 모든 데이터는 날라간다. 이를 막기 위해서 그리고 부족한 main memory의 저장공간을 보조하기 위해서 보조 기억 장치를 사용한다. 이것에 사용되는 것은 크게 두 가지 이다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;magnatic disk : 자기 disk를 이용해서 정보를 저장하는 방식이다. 전기가 공급되지 않음에도 정보를 저장하고 있을 수 있다.&lt;/li&gt;
&lt;li&gt;flash memory : 반도체를 이용하여 데이터를 저장하며, DRAM보다는 느리지만, 더 싸고 휘발성이 없다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Instruction Set Architecture(ISA, architecture)&lt;/b&gt; : 0과 1로 이루어진 기계어가 들어왔을 때, 이것이 무슨 의미인지를 나타내는 instruction  Set에 따라 CPU가 알맞은 연산을 수행하는 architecture이다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Instruction  Set : hardware에게 동작을 요청하는 하나의 명령어를 Instruction이라고 한다. 이들이 무슨 역할을 하는지를 정리해놓은 것이 Instruction Set이다. 이를 통해서, Operating System은 hardware에 접근하여 특정 동작을 수행시킬 수 있다.&lt;/li&gt;
&lt;li&gt;ABI(Application Binary Interface) : application 단에 programmer가 hardware 작업 등을 수행하기 위하여 호출할 수 있다. 이를 통해서, binary한 동작도 application programmer가 조작할 수 있다. 일반적인 API와 역할이 동일하지만, programming language가 아닌 machine language를 사용하여 구현되기 때문에 hardware 접근 등에 제한이 없다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;4. Performance&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리가 Computer의 성능을 측정하는 것은 중요하다. 왜냐하면, 이를 지표로 계속해서 computer의 성능을 향상시켜야 하기 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 우리는 다음과 같이 표현하는 것이 일반적이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$$\text{Excution Time} = \text{Clock Cycle Time} \times {\text{Number of Instruction}} \times {CPI}$$&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, &lt;b&gt;총 실행 시간(Execution Time)&lt;/b&gt;은 &lt;b&gt;한 번 Clock이 회전하는데 걸리는 시간(Clock Cycle Time)&lt;/b&gt;에 해당 &lt;b&gt;program의 instruction 수(Number of Instruction)&lt;/b&gt; 그리고 &lt;b&gt;하나의 instruction을 처리하는데 걸리는 clock cycle의 횟수(CPI)&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: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;한 번 회전하는데 걸리는 시간을 줄이기 위해 클락 frequency를 높인다. &lt;b&gt;하지만, 회전열로 인해 현재는 frequency를 올리는 것은 포기하고 있다.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;프로그램을 잘 짜거나 Compiler를 더욱 더 최적화하여 instruction의 수를 줄인다.&lt;/li&gt;
&lt;li&gt;하드웨어를 잘 설계해서 명령 하나를 처리하는데 걸리는 시간(CPI)을 줄인다.&lt;/li&gt;
&lt;li&gt;동시에 여러 CPU를 실행시켜서, 실행을 하는 unit 자체를 더 만드는 방법도 있다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서, 앞으로 우리가 Performance를 올리기 위해서, Compiler를 어떻게 최적화할지를 계략적으로 배우며, 하드웨어를 어떻게 잘 설계할지를 자세히 알아볼 것이다. 또한, Parallelism을 통해서 작업을 더 빠르게 수행하는 방법 또한 다룰 것이다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;+ Amdahl's Law&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;작업의 성능을 개선시켰을 때 이전과 비교하여 얼마나 효율이 증가했는지를 보여주는 지표이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$$1\over{(1-P) + {P\over{S}}}$$&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 개선된 작업이 전체에서 차지하는 비율을 P라고 하고, 해당 작업의 향상된 작업 효율을 S라고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약, 전체에 10%를 차지하는 작업을 2배 빠르게 진행한다면,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$${1\over{(1-0.1) + {0.1\over{2}}}} = {1\over{0.95}} \approx 1.05$$&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서, 단기간의 성능향상을 하고 싶다면, 비율이 큰 작업의 성능향상을 꾀하는 것이 좋다는 것을 알 수 있다.&lt;/p&gt;</description>
      <category>Computer Architecture</category>
      <category>Amdal's Law</category>
      <category>Base Element of Computer</category>
      <category>Computer Architecture</category>
      <category>Computer Performance</category>
      <category>Moore's law</category>
      <category>System Software</category>
      <author>euidong</author>
      <guid isPermaLink="true">https://justlog.tistory.com/37</guid>
      <comments>https://justlog.tistory.com/37#entry37comment</comments>
      <pubDate>Wed, 13 Apr 2022 21:54:34 +0900</pubDate>
    </item>
    <item>
      <title>Brute Force</title>
      <link>https://justlog.tistory.com/36</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;우리가 알고리즘을 생각할 때, 가장 먼저 떠올릴 수 있는 방법 중에 하나입니다. 가장 기본적인 알고리즘이기 때문에, 굳이 설명을 하지 않아도 자연스럽게 채득하는 경우가 대부분이지만, 사고의 틀을 정하여 더 빠르게 답을 찾을 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Brute Force를 직접적으로 번역하면, 이는 &quot;무차별&amp;nbsp; 대입&quot;정도로 생각할 수 있습니다. 이는 여러 가지의 경우의 수에서 최적의 답이 한 개 이상 존재할 때, 모든 경우의 수를 하나하나 대입해보면서, 정답이 맞는지를 확인하는 방식입니다. 즉, 가능한 모든 경우를 만들고, 그 후에 이것이 정답인지를 계속해서 확인하는 과정이 알고리즘의 핵심입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 흔한 예시가 해커들이 특정 유저의 password를 알아내기 위해서 모든 경우의 수를 대입하여 확인하는 것이 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;해결 방법&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 알고리즘의 구현 순서는 다음과 같습니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;모든 경우의 수를 헤아린다.&lt;/li&gt;
&lt;li&gt;하나의 경우의 수를 갖고 하는 연산의 횟수를 헤아린다.&lt;/li&gt;
&lt;li&gt;해당 알고리즘이 시간 내에 작동할 수 있는지 확인한다.&lt;br /&gt;대게, 1초동안 할 수 있는 연산은 대략 1억회라고 가정하면 쉽습니다.&lt;/li&gt;
&lt;li&gt;알고리즘을 직접 구현한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;대표 예시&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모든 경우의 수를 확인하는 문제가 굉장히 많기 때문에, 순열/조합/부분집합 문제가 굉장히 많습니다. 고등학교 시절 C, P로 경우의 수를 푸는 문제를 굉장히 많이 풀었다면, 아마 쉽게 할 수 있을 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 순열 조합을 가장 효율적으로 구현하는 방법에 대해서, 일단 정리를 해보겠습니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;1. 순열(Permutation)&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1649036795940&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def permutation_helper(k, arr=[], prev=[]):
    if len(prev) == k:
        return [prev]
    ss = []
    for idx in range(len(arr)):
        ss += permutation_helper(k, arr[:idx] + arr[idx+1:], prev + [arr[idx]])
    return ss


def permutation(n, k):
    arr = [i for i in range(1, n+1)]
    return permutation_helper(k, arr, [])
    
print(permutation(5, 2))
print(permutation_helper(2, [1,2,3,4,5], []))&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2. 조합(Combination)&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1649036946294&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def combination_helper(k, arr=[], prev=[]):
    if len(prev) == k:
        return [prev]
    ss = []
    for idx in range(len(arr)):
        ss += combination_helper(k, arr[idx+1:], prev + [arr[idx]])
    return ss


def combination(n, k):
    arr = [i for i in range(1, n+1)]
    return combination_helper(k, arr, [])

print(combination(5, 2))
print(combination_helper(2, [1,2,3,4,5], []))&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;3. 부분집합(Subset)&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1649036902503&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def subset_helper(k, arr=[], prev=[]):
    if len(prev) == k:
        return []
    ss = []
    for idx in range(len(arr)):
        ss.append(prev + [arr[idx]])
        ss += subset_helper(k, arr[idx+1:], prev + [arr[idx]])
    return ss


def subset(n, k):
    arr = [i for i in range(1, n+1)]
    return subset_helper(k, arr, [])

print(subset(5, 2))
print(subset_helper(2, [1,2,3,4,5], []))&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Algorithm</category>
      <category>Algorithm</category>
      <category>Brute Force</category>
      <category>Combination</category>
      <category>permutation</category>
      <category>경우의수</category>
      <category>순열</category>
      <category>조합</category>
      <author>euidong</author>
      <guid isPermaLink="true">https://justlog.tistory.com/36</guid>
      <comments>https://justlog.tistory.com/36#entry36comment</comments>
      <pubDate>Mon, 4 Apr 2022 10:01:15 +0900</pubDate>
    </item>
    <item>
      <title>Modulo</title>
      <link>https://justlog.tistory.com/35</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;해당 Posting에서는 Modulo연산의 정의와 특징을 이해하고, 이를 이용한 알고리즘을 소개합니다.&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;사칙연산과 같은 연산자입니다. 하지만, modulo 연산은 기존 사칙연산과는 다른 다양한 특징을 가지기 때문에, 이를 정리하고 이해하는 것은 중요합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 modulo 연산이란 무엇인지부터 알아야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$$a = bq + r$$&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$$r = a \mod b = a \mod q$$&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;$100 \mod 3 = 1$&lt;/li&gt;
&lt;li&gt;$12 \mod 32 = 12$&lt;/li&gt;
&lt;li&gt;$123 \mod 11 = 2$&lt;/li&gt;
&lt;li&gt;$1 \mod 1 = 0$&lt;/li&gt;
&lt;/ol&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;쉽게 말해서, a와 b에 대해서, 나눗셈한 나머지를 반환하는 연산자입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이는 여러 programming 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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;특징&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;연산 결과는 0보다 크거나 같고 연산을 수행하는 값($b$)보다는 작습니다.&lt;/li&gt;
&lt;li&gt;만약, modulo 연산을 했을 때, 결과가 같다면, 두 정수는 &lt;b&gt;합동&lt;/b&gt;이라고 합니다. 이에 따라, 합동인 정수는 무한히 많습니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;연산 특징&lt;/b&gt;&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;덧셈의 항등원(0)이 존재합니다.&lt;/b&gt;&lt;br /&gt;$(A + 0) \% C = A \% C$&lt;/li&gt;
&lt;li&gt;&lt;b&gt;덧셈의 역원(-A = C-A)이 존재합니다.&lt;/b&gt;&lt;br /&gt;$-A \% C = (C - A) \% C$&lt;br /&gt;ex) $-105 \% 100 = -5 \% 100 = 95$&lt;/li&gt;
&lt;li&gt;$(A+B) \% C = \{(A\%C) + (B\%C)\} \% C$&lt;br /&gt;ex) $54 \% 17 = \{(29\%17) + (25\%17)\} \% 17 = (12+8) \%17 = 3 $&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; letter-spacing: 0px;&quot;&gt;$(A-B) \% C = \{(A\%C) - (B\%C)\} \% C$&lt;br /&gt;ex) $54 \% 17 = \{(70\%17) - (16\%17)\} \% 17 = (2-16) \%17 = -14 \% 17 = 3 $&lt;br /&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; letter-spacing: 0px;&quot;&gt;$(A \times B) \% C = \{(A\%C) \times (B\%C)\} \% C$&lt;br /&gt;&lt;/span&gt;ex) $960 \% 17 = \{(20\%17) \times (18\%17)\} \% 17 = (3 \times 1) \%17 = 3 $&lt;/li&gt;
&lt;li&gt;&lt;b&gt;정수 k, p에 대하여, p가 k의 약수라면,&lt;/b&gt;&lt;br /&gt;$A^k \% C = (A^{k \over p}\%C)^p \% C$&lt;br /&gt;ex) $2^{10}(=1024) \% 29 = (2^5(=32) \% 29)^2 \%29 = 3^2 \% 29 = 9$&lt;/li&gt;
&lt;li&gt;&lt;b&gt;곱셈의 항등원(1)이 존재합니다. ($ C \ge 2$)&lt;/b&gt;&lt;br /&gt;$A \times 1 \% C = A \% C$&lt;/li&gt;
&lt;li&gt;&lt;b&gt;곱셈의 역원(A^{-1})가 존재합니다.&lt;/b&gt;&lt;br /&gt;$A \times A^{-1} \% C = 1 $&lt;br /&gt;하지만, 이를 구하는 것은 직접 해보는 수밖에 없습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;곱셈의 역원을 통해서 나눗셈을 정의할 수 있습니다.&lt;/b&gt;&lt;br /&gt;$ ({B \over{A}} ) \% C = B \times A^{-1} \% C$&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같은 특징들 때문에, 수의 범위를 제한하는 문제를 푼다고할 때, 굉장히 유용하게 이를 이용할 수 있습니다. 왜냐하면, modulo 합동끼리는 사칙연산의 여러 특징들을 모두 사용할 수 있기 때문입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;교환 법칙, 결합법칙, 역원, 항등원이 모두 존재합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한, 만약,&lt;b&gt; 나누는 수가 만약 소수라면&lt;/b&gt;, 나눗셈을 더 쉽게 정의할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;바로 &lt;b&gt;Fermat's little theorem(페르마의 소정리)&lt;/b&gt;를 활용하는 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이에 따르면, $A^{n-1} \% C = 1$이라는 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 통해서, 우리는 아래를 증명할 수 있으며,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$$ A \times A^{-1} \% C = 1&amp;nbsp; % C $$&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$$ A \times A^{-1} \% C = A^{n-1} \% C $$&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$$ A^{-1} \% C = A^{n-2} \% C $$&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결론상 다음과 같이 나눗셈을 변형할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$$ {A\over B} \% C = A\times B^{n-2} \% C$$&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;유클리드 호제법&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최대공약수(GCD), 최소공배수(LCM)를 구하는 문제에서 가장 단골로 사용되는 알고리즘입니다.&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-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;큰 수(p)로 작은 수(q)를 modulo 연산하여, 결과값(r)을 얻습니다.&lt;/li&gt;
&lt;li&gt;r이 0이라면, q는 최대공약수입니다.&lt;/li&gt;
&lt;li&gt;그렇지 않다면, q와 r을 갖고, 1로 돌아가서 다시 시행합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 결과를 통해서, 최대공약수(GCD)를 구할 수 있고, 모두가 알다시피, 최소공배수는 ${p \times q}\over {gcd}$이므로, 쉽게 유도가 가능합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Algorithm</category>
      <category>Algorithm</category>
      <category>Modulo</category>
      <author>euidong</author>
      <guid isPermaLink="true">https://justlog.tistory.com/35</guid>
      <comments>https://justlog.tistory.com/35#entry35comment</comments>
      <pubDate>Fri, 1 Apr 2022 15:28:46 +0900</pubDate>
    </item>
    <item>
      <title>Bitcoin (4) - Blockchain</title>
      <link>https://justlog.tistory.com/34</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;icons8-team-Ph5_4TnXXYE-unsplash.jpg&quot; data-origin-width=&quot;6016&quot; data-origin-height=&quot;4016&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/djelpv/btrxfuC73zh/kgfW9FBYm9TUNnEgZJPtZK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/djelpv/btrxfuC73zh/kgfW9FBYm9TUNnEgZJPtZK/img.jpg&quot; data-alt=&quot;Photo by Icons8 Team on Unsplash&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/djelpv/btrxfuC73zh/kgfW9FBYm9TUNnEgZJPtZK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdjelpv%2FbtrxfuC73zh%2FkgfW9FBYm9TUNnEgZJPtZK%2Fimg.jpg&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;6016&quot; height=&quot;4016&quot; data-filename=&quot;icons8-team-Ph5_4TnXXYE-unsplash.jpg&quot; data-origin-width=&quot;6016&quot; data-origin-height=&quot;4016&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Photo by Icons8 Team on Unsplash&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Reference&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;- Programming Bitcoin&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1648104898305&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;Programming Bitcoin&quot; data-og-description=&quot;Dive into Bitcoin technology with this hands-on guide from one of the leading teachers on Bitcoin and Bitcoin programming. Author Jimmy Song shows Python programmers and developers how to program &amp;hellip; - Selection from Programming Bitcoin [Book]&quot; data-og-host=&quot;www.oreilly.com&quot; data-og-source-url=&quot;https://learning.oreilly.com/library/view/programming-bitcoin/9781492031482/&quot; data-og-url=&quot;https://www.oreilly.com/library/view/programming-bitcoin/9781492031482/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/xOrcP/hyNI1aTWN7/tjHLDnkjcHRpkE52yh4bHk/img.jpg?width=140&amp;amp;height=184&amp;amp;face=0_0_140_184&quot;&gt;&lt;a href=&quot;https://learning.oreilly.com/library/view/programming-bitcoin/9781492031482/&quot; data-source-url=&quot;https://learning.oreilly.com/library/view/programming-bitcoin/9781492031482/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/xOrcP/hyNI1aTWN7/tjHLDnkjcHRpkE52yh4bHk/img.jpg?width=140&amp;amp;height=184&amp;amp;face=0_0_140_184');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Programming Bitcoin&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Dive into Bitcoin technology with this hands-on guide from one of the leading teachers on Bitcoin and Bitcoin programming. Author Jimmy Song shows Python programmers and developers how to program &amp;hellip; - Selection from Programming Bitcoin [Book]&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.oreilly.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;해당 Posting은 Bitcoin이 무엇이고, 이것으로 무엇을 할 수 있는지에 대해서 설명하지 않고 Bitcoin을 구현하는 기술에 대하여 다룹니다.&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;또한, 책의 모든 내용을 충실히 번역하는 것이 아닌 작성자의 생각이 많이 담겨 있으니 유의 바랍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;해당 chapter에서는 Blockchain Network 구조에 대한 이해와 실용성을 향상하기 위한 MerkleTree, Bloom Filter, SigWit에 대해서 정리합니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전 Chapter에서는 Transaction의 소유 여부를 확인하는 방법에 대해서 자세히 다루었습니다. 거기서 Transaction의 사용 여부를 확인할 때에는 UTXO(Unspent Transaction Output) set이라는 것을 사용한다고 하였습니다. 그렇다면, 이는 어떻게 생성되고, 어떻게 관리되는지를 해당 part에서 한 번 다루어보겠습니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1.  Blockchain&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리의 Transaction을 저장하기 위해서 여러 가지 방법을 강구해보았습니다. 모든 Transaction을 표의 형태로 저장해두는 것도 방법이 될 수 있습니다. 하지만, Bitcoin에서는 이를 Block이라는 단위로 저장하였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;1-1.  Block&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1-1-1. 정의&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Block이란 Transaction을 저장하는 하나의 단위라고 볼 수 있습니다. 하나의 Block의 크기는 1MB로 제한되어있습니다. (물론 지금은 여러 다른 변종에서는 이 제한이 다르기도 합니다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1-1-2. 구조&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서, Block에는 이를 만족하는 Transaction의 갯수만큼만을 저장할 수 있습니다. 이를 이루는 구조는 다음과 같습니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Header : 해당 Block에 대한 설명을 위한 정보를 포함합니다. 특히, 해당 Block의 정당성을 확인하기 위한 내용을 포함합니다.&lt;/li&gt;
&lt;li&gt;Coinbase Transaction : Block에 존재하는 첫번째 Transaction을 의미합니다.&lt;/li&gt;
&lt;li&gt;Transactions : 여러 user들의 거래 내용을 포함하는 내용입니다. 이 안에도 Block 생성자를 위한 보상이 포함됩니다. 보상이 없다면, 해당 transaction의 우선순위는 낮을 수밖에 없습니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blockchain.jpeg&quot; data-origin-width=&quot;2183&quot; data-origin-height=&quot;1000&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cJ0hgW/btrxcySEUEE/CotmcLdRQCI4k0FS3O6cH0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cJ0hgW/btrxcySEUEE/CotmcLdRQCI4k0FS3O6cH0/img.jpg&quot; data-alt=&quot;Blockchain&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cJ0hgW/btrxcySEUEE/CotmcLdRQCI4k0FS3O6cH0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcJ0hgW%2FbtrxcySEUEE%2FCotmcLdRQCI4k0FS3O6cH0%2Fimg.jpg&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;646&quot; height=&quot;296&quot; data-filename=&quot;blockchain.jpeg&quot; data-origin-width=&quot;2183&quot; data-origin-height=&quot;1000&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Blockchain&lt;/figcaption&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;size18&quot;&gt;&lt;b&gt;1-1-3. Coinbase Transaction&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본적으로 모든 Transaction은 이전 Transaction의 Output을 가르키고 있어야 하며, 이것이 자신의 것이라는 증명을 포함해야 합니다. 그렇다면, 의문이 생기는 부분이 있습니다. 모든 Transaction의 끝으로 갔을 때, 과연 기반 Transaction은 어디서 오는가에 대한 고민을 하게 됩니다. 그것이 되는 것이 바로 이 Coinbase Transaction입니다. 이는 이전 Transaction의 Output 없이도 정의할 수 있습니다. 이는 해당 Block을 만들어낸 생성자에게 보상을 제공하는 의미에서 Bitcoin을 제공합니다. 해당 Transaction은 이전 Transaction을 가리키는 값이 모두 0으로 초기화되어있어 쉽게 식별이 가능합니다. 또한, 특이하게도, Coinbase Transaction의 정당성은 Block 자체가 증명하기 때문에, input의 ScriptSig 부분은 무의미한 데이터가 됩니다. 따라서, 여기에는 자신만의 철학을 담은 문구를 사용할 수도 있었습니다. 하지만, 시간이 좀 흐른 후에는 여기에 Block의 height(제일 첫 번째 Block과의 거리)를 표시하는 용도로 사용합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;왜 Block을 생성한 사람에게 Bitcoin을 제공하는 것일까요? 이는 이제 앞으로 살펴볼 PoW에서 다루겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1-1-4. Header&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Header는 총 6개의 정보를 포함합니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Version : BIP(Bitcoin Improvement Proposal)이라는 이름으로 여러 개의 Bitcoin 시스템의 향상을 위한 제안들이 존재합니다. 이를 통해서 실제로 Block의 Version이 바뀌기도 합니다. 그런데, 이것이 이전 Version의 Block과 호환이 된다면, 이를 Soft Fork라고 하고, 이전 Version과 호환되지 않는 독립적인 Chain으로 분리되는 것을 Hard Fork라고 부릅니다.&lt;/li&gt;
&lt;li&gt;Previous Block : Blockchain이라고 불리는 이유라고 볼 수 있습니다. 이전에 보았던 Transaction 처럼 Block 역시 이전 Block과 연결되어 있습니다. 이를 통해서 모든 거래 장부의 조회가 가능합니다.&lt;/li&gt;
&lt;li&gt;Merkle root : 해당 Block이 소유하고 있는 Transaction의 hash값을 기반으로 만든 트리 구조에서 root에 해당하는 값입니다. 이는 후에 Block 내부에 Transaction 여부를 확인하기 위한 도구로 사용합니다.&lt;/li&gt;
&lt;li&gt;Timestamp : 해당 Block의 생성 시점을 의미합니다.&lt;/li&gt;
&lt;li&gt;Bits : 앞으로 나올 PoW part에서 다루는 내용으로, 이는 특정 작업의 난이도를 표현합니다.&lt;/li&gt;
&lt;li&gt;Nonce : 앞으로 나올 PoW part에서 다루는 내용으로, 이는 특정 작업에서 사용하는 변수값에 해당합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1-1-5. Proof of Work(PoW)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이는 Blockchain에서 최초로 만들어진 개념은 아닙니다. 기존에 Spam mail을 막기 위한 수단으로 사용된 적이 있는 기술입니다. 이 기술의 목적은 무분별한 가짜, 사기, 무의미한 데이터가 빈번하게 네트워크 상에서 공유되는 걸 막는 것입니다. 즉, 누군가 악의적으로 Bitcoin 시스템을 마비시키기 위해서, 악의적으로 데이터를 무차별적으로 보내면, Block의 Transaction을 증명하는 데에만 너무 많은 자원을 소모하게 될 수도 있습니다. 따라서, 이를 막기 위해서 만들어진 것이 PoW입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하나의 Block을 만들고, 공유하고, 검증받기 위해서는 반드시 어떤 특정 목표값에 해당하는 값을 찾도록 하여 이러한 무분별한 Block의 생성을 막도록 하는 것입니다. Bitcoin에서는 하나의 Block을 만드는 데 걸리는 시간을 평균 10분이 될 수 있도록 계속해서, 난이도를 수정하는 Algorithm을 갖고 있습니다. (2016 Block 단위로 난이도는 갱신됩니다.)&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-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;어떻게 평균 10분이 걸리는 문제를 낼 수 있는가?&lt;br /&gt;hash 함수 중 hash256(sha-1 라는 hash 함수를 두 번 연속으로 수행하는 방법)을 사용하면, 이를 수행할 수 있습니다. sha 함수는 결과 값으로 나온 데이터의 각 자리가 1을 가질 확률이 1/2이라고 할 수 있습니다. 또한, 역연산을 통해서 찾을 수도 없기 때문에, 연속해서 0이 n개 나오는 값을 찾으라고 했을 때, 무작정 수행을 반복하면서 찾을 수밖에 없습니다. 이를 한 번 수행하는 데 걸리는 시간을 Block에 담긴 timestamp를 기반으로 계산하여 평균상 10분이 나오도록 값을 조정해준다면, 이것이 가능합니다. 이때 우리가 Block header에서 nonce라는 값을 계속해서 바꿔주고, 이를 포함한 Block header를 hash 하여 연속해서 0이 n개 나오도록 하는 nonce값을 찾게 된다면, 이것이 바로 하나의 Block이 되는 것입니다.&amp;nbsp;&amp;nbsp;&lt;/li&gt;
&lt;li&gt;난이도라는 것은 어떻게 변경되는 것일까?&lt;br /&gt;Computer의 성능은 실시간으로 계속해서 발전하고 있습니다. 그렇기에 Block을 하나 채굴하는데 걸리는 시간은 계속해서 짧아질 것이라고 추측할 수 있지만, Bitcoin 시스템에서는 이 난이도 값을 bits라는 Block의 header를 통해서 통제할 수 있습니다.&lt;/li&gt;
&lt;li&gt;Block에 담긴 Transaction은 어디에서 오는가?&lt;br /&gt;Block에 담기는 Transaction은 모두 채굴자(Block을 생성하고자 하는 자)가 송금한 기록이 아닌 주변 node들로부터 전달받은 Transaction이 대부분입니다. 채굴자는 이를 Block에 담을 수 있는 양만큼 모아서 Block Header를 작성한 후, nonce라는 값을 찾아 떠나는 것입니다. 이때 Block에 담기는 Transaction의 우선순위는 Block을 만드는 이에게 달려 있습니다.&lt;/li&gt;
&lt;li&gt;Block을 왜 만들어주는가?&lt;br /&gt;아까도 말했듯이 Coinbase Transaction은 채굴자(Block을 생성하고자 하는 자)에게 향하는 output을 가집니다. 그렇기에 채굴자는 이를 통해서 Bitcoin을 벌 수 있는 것입니다. 또한, Transaction을 Block에 올리기 위해서, 주변 node들에게 Bitcoin 송금자들이 이를 요청하면서, 수수료 일부를 해당 node에게 가는 output으로 지정하기 때문에, Block을 만든다는 것은 Bitcoin을 버는 것과 같은 행위로 볼 수 있습니다. 또한, 올라갈 Transaction의 우선순위는 이 수수료에 기반하여 생성됩니다.&lt;/li&gt;
&lt;li&gt;Block을 중간에 누가 바꿔서 자신의 것이라고, 바꾸면 어떻게 되는가?&lt;br /&gt;최초로 발견한 Block에 대해서 누군가 이것을 자신이 발견했다고, 속이는 것은 의미가 없습니다. 애초에 Block을 도용하는 것은 이것을 통해서 발생하는 수수료를 일부 취하겠다는 것인데, 이는 Block 내부의 Transaction을 바꾸어야 하고, 이를 바꾼다는 것은 header의 merkle root 값을 바꾸는 결과를 초래합니다. 그렇게 되면 당연히 이전의 nonce값이 가지는 효과는 모두 사라지기 때문에, 도용한다는 것 자체가 불가능합니다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Block의 검증은 어떻게 이루어지는가?&lt;br /&gt;위에서 보았듯이 Block을 만들기 위해서는 앞에서부터 연속해서 0이 n개 나오게 하는 Block의 hash값을 찾아야 합니다. 하지만, 우리가 해당 Block을 받고, 이를 hash 한 후에 비교를 통해서, 이 Block이 적절한지 파악하는 것은 단 한 번의 hash로 가능합니다. 그렇기 때문에, 검증은 매우 쉽지만, 생성은 굉장히 어렵게 되는 것입니다.&lt;/li&gt;
&lt;li&gt;nonce field의 크기가 정해져있던데 모든 nonce를 모두 사용했는데도 찾을 수 없다면 어떻게 되나요?&lt;br /&gt;이때에는 coinbase transaction의 값을 살짝 조정합니다. 이를 조정하게 되면, merkle root의 값도 변경되기 때문에, hash를 다시 수행할 수 있습니다.&lt;/li&gt;
&lt;li&gt;BlockChain에 동시에 여러 Node가 등록을 하게 되면 어떻게 되는가?&lt;br /&gt;일단 Block을 만들게 되면, 해당 채굴자는 이를 전파합니다. 이것이 올바른지를 파악한 다른 Node들은 이를 자신의 Blockchain에 연결하게 되고, 똑같이 전파하기를 반복합니다. 이렇게 다른 모든 Node들이 해당 Block을 포함하는 Blockchain을 갖게 되면, 해당 Block은 이제 타당하다고 할 수 있습니다. 그렇지만 동시에 여러 Block을 받은 경우에는 해당 Block을 여러 개 모두 병렬로 연결해두고 있다가, 가장 먼저 새로운 Block이 연결된 Block을 채택하고, 나머지 기존 Block은 버리게 됩니다. 그렇기에 Block을 채굴했다고 끝인 게 아니라 완전히 선택되기까지는 완벽하게 Bitcoin을 획득했다고는 볼 수 없습니다. 그렇기에 대개의 경우에는 자신을 포함한 Block이 6개 연결되었을 때, 비로소 해당 Block이 Blockchain에 완벽하게 등록되었다고 보는 것이 일반적입니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1-1-6. Genesis Block&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Block 내에서도 최초의 Transaction이 존재하듯이, Block 또한, 최초의 Block이 존재합니다. 이를 우리는 Genesis Block이라고 부르고, 모든 Block의 최상단은 해당 Block이 됩니다. 해당 Block의 Coinbase Transaction의 ScriptSig에는 Bitcoin의 창시자 Satoshi의 동기가 담긴 문구를 포함시켰다. &lt;br /&gt;(chancellor on brink of second bailout for banks)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;1-2. P2P network&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리가 생각하는 Internet과 게임 산업과 각종 서비스들은 대게 큰 규모의 Server를 가지고 있는 업체가 자신들의 서비스를 해당 Server를 통해서 모든 Client(사용자)들에게 제공하는 형태를 띄고 있습니다. 즉, 소프트웨어 개발자가 소프트웨어를 제공함과 동시에 소프트웨어 사용자가 통신하여 얻을 데이터들도 모두 소프트웨어 개발자가 관리한다는 특징이 있습니다. 이것이 대게 일반적인 형태의 서비스입니다. 하지만, 이와 전혀 다른 구조를 가지고 있는 것이 P2P network입니다. 이는 Peer to Peer의 줄임말로, 각 Client(사용자) 간의 연결을 통해서 Service를 제공한다는 점이 매우 특이한 점입니다. 즉, 개발자는 Software를 만들고, 이를 배포하는 역할만을 하고, Software 끼리의 통신은 Server를 통해서 수행되는 것이 아닌 각 Software끼리 연결되어 하나의 거대한 통신 network를 만드는 형식입니다. 이렇게 만든 네트워크는 Software만 무결하게 만들었다면, 서로가 서로를 검증하고, 주체적으로 판단할 수 있는 환경을 만들어서 더 건전한 네트워크 환경을 만들 수도 있습니다. 기존의 Server 구조에서는 모든 Client의 요청을 Server에서 해결하기 때문에, 부담이 매우 크고, 해킹의 타깃이 되는 등 하나의 시스템에 대한 부하가 굉장히 크다는 단점이 있습니다. 하지만, P2P 구조에서는 이러한 부담을 나눠가지기 때문에 오히려 안전해질 수 있다고 볼 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서, Bitcoin에서는 Block을 공개하기 위한 P2P network를 사용합니다. 중앙에 있는 시스템 없이 개인이 언제든지 모든 Blockchain을 보관하고 있을 수 있고, 이를 이용해서 특정 거래에 대하여 검증을 하는 등의 작업을 수행할 수 있도록 합니다. 그렇기에 서로가 서로를 감시하며, 서로가 보내는 데이터에 대한 100%의 신뢰를 갖지 않고, 직접 검증을 통해서 다시 한 번 확인하도록 하는 것입니다. 이것이 Bitcoin에서 추구하는 탈중앙화 된 거래 관리 방식이라고 할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;cs-arch.jpeg&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;1035&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bkOS2O/btrxgxZZBks/rtOwhxXIO25IYycNK29N21/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bkOS2O/btrxgxZZBks/rtOwhxXIO25IYycNK29N21/img.jpg&quot; data-alt=&quot;Client-Server Architecture&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bkOS2O/btrxgxZZBks/rtOwhxXIO25IYycNK29N21/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbkOS2O%2FbtrxgxZZBks%2FrtOwhxXIO25IYycNK29N21%2Fimg.jpg&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;415&quot; height=&quot;429&quot; data-filename=&quot;cs-arch.jpeg&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;1035&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Client-Server Architecture&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;p2p-arch.jpeg&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;1101&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cUlMNZ/btrxiYvGloz/SK07jrEsiK8Hzk8ZjYKuKk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cUlMNZ/btrxiYvGloz/SK07jrEsiK8Hzk8ZjYKuKk/img.jpg&quot; data-alt=&quot;P2P Architecture&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cUlMNZ/btrxiYvGloz/SK07jrEsiK8Hzk8ZjYKuKk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcUlMNZ%2FbtrxiYvGloz%2FSK07jrEsiK8Hzk8ZjYKuKk%2Fimg.jpg&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;459&quot; height=&quot;506&quot; data-filename=&quot;p2p-arch.jpeg&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;1101&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;P2P Architecture&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;1-3.  Blockchain Data Types&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;P2P network를 통해서 Block과 Transaction이 공유가 되기 때문에, Bitcoin 시스템 내에서는 데이터를 다음과 같이 3가지로 나누어 보관합니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;mempool : 승인되지 않은 Transaction을 보관하는 pool입니다. miner들은 이를 Block에 담아서 P2P network로 다시 공유하고, 이를 받은 node는 이를 Blockchain에 연결시켜서 Block을 만들어냅니다.&lt;/li&gt;
&lt;li&gt;Blockchain : Block을 하나의 긴 chain의 형태로 보관하는 것입니다. 이는 모든 Bitcoin 거래에 해당하는 가계부(원장)이라고 할 수&amp;nbsp; 있습니다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;UTXO set : 이전에도 살펴보았지만, 우리는 Transaction의 검증을 수행할 때 반드시 해당 Transaction의 사용여부를 확인할 필요가 있습니다. 따라서, 해당 Transaction 중에서 사용되지 않은 Transaction Output을 Blockchain에서부터 추출하여 별도로 저장하는 것입니다. 이를 통해서, 전체 Blockchain을 조회하는 것보다 빠르게 사용하지 않은 Transaction output을 찾을 수 있습니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blockchain-data.jpeg&quot; data-origin-width=&quot;1046&quot; data-origin-height=&quot;999&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FecAq/btrxhMQdkZQ/gqH0wccC1PeFTGZ5fmaj6k/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FecAq/btrxhMQdkZQ/gqH0wccC1PeFTGZ5fmaj6k/img.jpg&quot; data-alt=&quot;Blockchain data types&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FecAq/btrxhMQdkZQ/gqH0wccC1PeFTGZ5fmaj6k/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFecAq%2FbtrxhMQdkZQ%2FgqH0wccC1PeFTGZ5fmaj6k%2Fimg.jpg&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;551&quot; height=&quot;526&quot; data-filename=&quot;blockchain-data.jpeg&quot; data-origin-width=&quot;1046&quot; data-origin-height=&quot;999&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Blockchain data types&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;1-4. Blockchain Node Types&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;P2P network에서는 여러 개의 node가 존재할 수 있습니다. 어떤 Node에서는 Block 자체를 생성해내는 역할을 할 수도 있고, 어떤 Node에서는 최소한의 Transaction 만을 가지는 경우도 존재합니다. 이에 대해서, 알아보도록 합시다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Full Node&lt;/li&gt;
&lt;li&gt;Miner Node&lt;/li&gt;
&lt;li&gt;Light Node&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;1-5. Block 내의 Transaction의 존재 여부&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Block 내의 Transaction의 여부를 파악하기 위해서는 간단히 Block에서 Transaction을 찾아서 조회하는 것이 가장 간편합니다. 하지만, 이것이 불가능한 경우가 있습니다. 바로, 모든 Blockchain을 담을 수가 없는 경우입니다. 2022년 현재를 기점으로 Blockchain의 데이터 사이즈는 400GB를 넘어섰습니다. 이를 Smartphone과 같은 장치에서 모두 보관하는 것은 불가능합니다. 따라서, 이를 좀 더 간소화할 수 있는 방법을 찾는 과정에서 만들어진 것이 Header의 Merkle Root입니다. 이것의 원리를 알기 위해서 Merkle Tree에서부터 알아보아야 합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2. Merkle Tree&lt;/b&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2-1.&amp;nbsp; 배경&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Blockchain의 뭐든 Block을 갖고 있는 것은 어떤 Node에게는 굉장히 큰 부담이 될 수 있습니다. 따라서, 우리가 이를 보관함으로써 하고자 했던 행동으로 관심을 돌린 것입니다. 원래 목적인 Block 내의 Transaction의 존재 여부를 확인하는 것이 목표였기 때문에, 이를 모두 유지할 필요는 없습니다. 그래서, 이에 대한 요약본을 가지는 것이 바로 Merkle Tree입니다.&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2-2.&amp;nbsp; 정의&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MerkleTree는 Proof of Inclusion(포함 여부를 증명)하기 위해 고안된 data structure(자료구조)입니다. 이름에서부터 느낄 수 있겠지만, 구조는 Tree 형태를 갖고 있습니다. 또한, 이는 두 개의 핵심 개념에 의해서 구현됩니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Ordered List&lt;/li&gt;
&lt;li&gt;Hash Function&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구조화하는 방법은 매우 간단합니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Ordered List를 leaf 노드 갯수로 갖는 complete binary tree(leaf node를 제외하고는 모든 node가 채워져 있으며, 왼쪽에서부터 데이터가 채워지는 형태입니다.)를 만드는 것이 목표이므로, 모든 Ordered List를 포함할 수 있는 leaf node를 가지는 complete binary tree를 생성합니다.&lt;/li&gt;
&lt;li&gt;이제 leaf노드에 각 ordered list의 element들을 hash function을 적용하여, 채워넣습니다.&lt;/li&gt;
&lt;li&gt;이제 각 leaf 노드에서부터 차근차근 위로 올라가면서, tree 구조의 모든 node의 값을 채울 것입니다. 여기서 parent의 값은 left node의 hash 값과 right node의 hash값을 이어 붙여서(더하는 것이 아니라 이어서 붙입니다.) 다시 한번 hash function을 적용하는 식으로 구합니다.&lt;/li&gt;
&lt;li&gt;여기서, 만약 왼쪽 node는 있지만, 오른쪽 node가 없는 경우, 왼쪽 node를 복사하여 오른쪽 node에 붙여 넣습니다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;이 과정을 반복하면서, root 노드에 있는 값까지 구해냅니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 만들어진 것이 merkle tree입니다. 이 구조가 왜 포함 증명을 하기에 적합한지를 알아보도록 하겠습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;merkletree.jpeg&quot; data-origin-width=&quot;1564&quot; data-origin-height=&quot;1000&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yDhRb/btrxbNCKlAf/VgJ4ZxWgoFeYxNKIQadMmK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yDhRb/btrxbNCKlAf/VgJ4ZxWgoFeYxNKIQadMmK/img.jpg&quot; data-alt=&quot;Merkle Tre&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yDhRb/btrxbNCKlAf/VgJ4ZxWgoFeYxNKIQadMmK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FyDhRb%2FbtrxbNCKlAf%2FVgJ4ZxWgoFeYxNKIQadMmK%2Fimg.jpg&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;686&quot; height=&quot;439&quot; data-filename=&quot;merkletree.jpeg&quot; data-origin-width=&quot;1564&quot; data-origin-height=&quot;1000&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Merkle Tre&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2-3. &lt;b&gt;동작원리&lt;/b&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$H_6$ 라는 Transaction이 Merkle Tree의 포함되어있는지를 확인하기 위해서 다음과 같은 방식으로 사용될 수 있습니다. Light Node가 Blockchain에서 Transaction의 존재 여부를 확인하고자 할 때 다음과 같은 연산을 수행할 수 있습니다. 먼저, 근처의 Full Node에게 Flag Bit와 Hash 값을 요청하는 것입니다. 그리고, 이를 이용해서, 정말 $H_6$가 포함되었는지를 확인할 수 있습니다. Flag Bit와 보낼 Hash 데이터는 다음과 같이 선정됩니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;먼저 Merkle Tree를 위해서 설명한 대로 제작하고 이를 보관합니다.&lt;/li&gt;
&lt;li&gt;그리고 해당 Transaction Hash 값에 해당하는 Block에서 해당 Transaction Hash를 찾습니다. 아래에서는 노란색입니다.&lt;/li&gt;
&lt;li&gt;그렇다면, 만약 우리가 파란색으로 표시된 데이터만 있다면, 보라색 값을 유추할 수 있다고 할 수 있습니다.&lt;/li&gt;
&lt;li&gt;또한, 우리는 Merkle Root 값을 갖고 있기 때문에, 이를 통해 유추해낸 Merkle Root값과 Merkle Root이 같다면, 해당 Transaction이 해당 Block에 있다는 것은 증명되었다고 할 수 있습니다.&amp;nbsp;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;merkletree-2.jpeg&quot; data-origin-width=&quot;1824&quot; data-origin-height=&quot;1000&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cNvAiG/btrxiuVIjUR/FKj9c2epxna5sKmDEAZOuK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cNvAiG/btrxiuVIjUR/FKj9c2epxna5sKmDEAZOuK/img.jpg&quot; data-alt=&quot;Merkle Tree의 Proof of Inclusion&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cNvAiG/btrxiuVIjUR/FKj9c2epxna5sKmDEAZOuK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcNvAiG%2FbtrxiuVIjUR%2FFKj9c2epxna5sKmDEAZOuK%2Fimg.jpg&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;1824&quot; height=&quot;1000&quot; data-filename=&quot;merkletree-2.jpeg&quot; data-origin-width=&quot;1824&quot; data-origin-height=&quot;1000&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Merkle Tree의 Proof of Inclusion&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서, 우리가 가지고 있어야 할 데이터는 우리가 보낸 파란색 hash의 값과 위치를 유추할 수 있는 값만 있으면 됩니다.&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-filename=&quot;merkletree-3.jpeg&quot; data-origin-width=&quot;1430&quot; data-origin-height=&quot;999&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qnmVI/btrxgESrqD5/LXBQ3l9WKVFdvec0KHjn51/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qnmVI/btrxgESrqD5/LXBQ3l9WKVFdvec0KHjn51/img.jpg&quot; data-alt=&quot;Merkle Tree의 Flag bits와 Hashes&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qnmVI/btrxgESrqD5/LXBQ3l9WKVFdvec0KHjn51/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqnmVI%2FbtrxgESrqD5%2FLXBQ3l9WKVFdvec0KHjn51%2Fimg.jpg&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;1430&quot; height=&quot;999&quot; data-filename=&quot;merkletree-3.jpeg&quot; data-origin-width=&quot;1430&quot; data-origin-height=&quot;999&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Merkle Tree의 Flag bits와 Hashes&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 Flag Bits와 Hashes만을 갖고 있으면, 이제 우리는 이를 역연 산하는 것도 가능합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;3. BloomFilter&lt;/b&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;3-1. 배경&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Blockchain의 기반은 뿌리 깊은 불신에서부터 시작됩니다. 여기서, 이전에, 내가 가지고 있는 Transaction에 대해서 조회하는 것은 자신의 자산을 노출하는 것이 될 수도 있습니다. 따라서, 자신의 자신을 감추기 위해서 사용하는 것이 Bloom Filter입니다. Bloom Filter는 완벽하게 감추는 것은 아니지만, 다른 데이터와 중첩되도록 하여 쉽게 추측할 수 없도록 하는 데 있습니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;3-2. 정의&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Bloom Filter란 데이터를 hash 하고, 이를 Bit field라는 영역으로 나누어 담는 것입니다. 나누어 담은 데이터는 1개의 Bucket이라는 영역에 담기게 됩니다. 이때 Bucket은 하나의 Bit가 될 수도 있고, 여러 개의 Bits가 될 수도 있습니다. 또한, 동일한 Bucket에 담기는 데이터의 양은 평균적으로 &quot;$ \text{# of data} \div \text{# of  bucket} $&quot;가 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여러 개의 Bits를 하나의 Bucket으로 쓰는 경우에는, 다음과 같이 많은 양의 Bucket이 만들어질 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;bloomFilter-1.jpeg&quot; data-origin-width=&quot;1974&quot; data-origin-height=&quot;1000&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cIAveS/btrxiu9zd2W/UwEdbHKCQkVWkFtPSGZ8i0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cIAveS/btrxiu9zd2W/UwEdbHKCQkVWkFtPSGZ8i0/img.jpg&quot; data-alt=&quot;1 Bit Bucket&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cIAveS/btrxiu9zd2W/UwEdbHKCQkVWkFtPSGZ8i0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcIAveS%2Fbtrxiu9zd2W%2FUwEdbHKCQkVWkFtPSGZ8i0%2Fimg.jpg&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;467&quot; height=&quot;237&quot; data-filename=&quot;bloomFilter-1.jpeg&quot; data-origin-width=&quot;1974&quot; data-origin-height=&quot;1000&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;1 Bit Bucket&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;bloomFilter-2.jpeg&quot; data-origin-width=&quot;1264&quot; data-origin-height=&quot;1000&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BEVra/btrxcK6YiiY/ssO58jk0JmsEm14gpBomy1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BEVra/btrxcK6YiiY/ssO58jk0JmsEm14gpBomy1/img.jpg&quot; data-alt=&quot;2 Bit Bucket&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BEVra/btrxcK6YiiY/ssO58jk0JmsEm14gpBomy1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBEVra%2FbtrxcK6YiiY%2FssO58jk0JmsEm14gpBomy1%2Fimg.jpg&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;719&quot; height=&quot;568&quot; data-filename=&quot;bloomFilter-2.jpeg&quot; data-origin-width=&quot;1264&quot; data-origin-height=&quot;1000&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;2 Bit Bucket&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;3-3. 동작원리&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저, 데이터를 hash 하여 임의의 값을 생성해냅니다. 그리고 해당 값을 Bit Field의 크기로 modulo 연산(%)을 수행해주어 나온 결과를 넣어주면 됩니다. 만약, Bucket의 크기를 1 이상으로 하고 싶다면, 다른 hash 함수를 수행하거나 다시 한번 연산을 수행하여 만들도록 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;4. SegWit&lt;/b&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;4-1. 배경&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 거래의 양이 급격히 증가하면, Block에 담을 수 있는 Transaction의 양을 늘리는 것에 대한 토의가 빈번했습니다. 이 상황에서 어떻게 하면 더 효율적인 Transaction의 저장을 할지에 대한 고민이 깊어졌습니다. 또한, Transaction의 ScriptSig Part는 ScriptPubKey와 결합하여 안정적인 결과만 내놓을 수 있으면 되기 때문에, Transaction의 ScriptSig는 하나의 고정된 데이터가 아닌 여러 다른 형태를 가질 수 있었습니다. 또한, 이를 바꾸게 되면, Transaction의 값을 Hash 하여 얻는 Transaction의 ID가 변경되기 때문에, 다른 Transaction으로 여기고 Bug가 발생하기도 하였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;4-2.  정의&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Segrete Witness의 줄임말로, Block에서 부터 서명 부분을 분리하는 것을 목표로 만들어졌습니다. 이렇게 하게 되면, 두 가지 장점을 가질 수 있습니다. 바로, 하나의 Block에 더 많은 Transaction을 포함할 수 있을 뿐만 아니라 서명 부분의 코드가 조금씩만 바뀌어도 Transaction ID가 바뀌어 혼란이 발생하는 Transaction Malleability 위협을 차단할 수 있다는 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;4-3. 동작원리&amp;nbsp;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;바로 기존 ScriptSig 부분을 비워두는 것이 핵심입니다. 이를 통해서, 변화하지 않는 형태로 두고, 이전에 보았던 p2psh의 redeemScript처럼 후에 변환할 수 있는 ScriptSig를 별도로 저장하도록 하는 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원리는 Simple 하지만, 여기서 기억해야 될 것은 SegWit가 Soft-fork를 통해서 구현될 수 있다는 점입니다. 즉, 이전에 SegWit를 사용하지 않는 Node들과도 호환이 된다는 점입니다. Soft-fork를 유지하기 위해서, 구조는 더 복잡해지고, 이해할 수 없는 형태가 될 수 있습니다. 하지만, 이것이 Bitcoin 시스템에서 호환성이 큰 문제가 될 수 있다는 것을 보여주는 아주 대표적인 예시이기 때문에 이를 알아두면 좋습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전 글과 동일하게 구현 사항은 github에 정의해두었습니다.&lt;/p&gt;
&lt;figure id=&quot;og_1648104920223&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - euidong/bitcoin: BitCoin Implementation&quot; data-og-description=&quot;BitCoin Implementation. Contribute to euidong/bitcoin development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/euidong/bitcoin&quot; data-og-url=&quot;https://github.com/euidong/bitcoin&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/N8Nd3/hyNNf1m9E6/pS1qCcDtfL7eGBSU3CK4lk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/euidong/bitcoin&quot; data-source-url=&quot;https://github.com/euidong/bitcoin&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/N8Nd3/hyNNf1m9E6/pS1qCcDtfL7eGBSU3CK4lk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;GitHub - euidong/bitcoin: BitCoin Implementation&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;BitCoin Implementation. Contribute to euidong/bitcoin development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;</description>
      <category>BlockChain</category>
      <category>Bitcoin</category>
      <category>block</category>
      <category>blockchain</category>
      <category>BloomFilter</category>
      <category>CoinbaseTransaction</category>
      <category>MerkleRoot</category>
      <category>Merkletree</category>
      <category>P2P</category>
      <category>pow</category>
      <category>Segwit</category>
      <author>euidong</author>
      <guid isPermaLink="true">https://justlog.tistory.com/34</guid>
      <comments>https://justlog.tistory.com/34#entry34comment</comments>
      <pubDate>Fri, 25 Mar 2022 17:59:54 +0900</pubDate>
    </item>
    <item>
      <title>Bitcoin (3) -  Transaction</title>
      <link>https://justlog.tistory.com/33</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;icons8-team-Ph5_4TnXXYE-unsplash.jpg&quot; data-origin-width=&quot;6016&quot; data-origin-height=&quot;4016&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/XkxRt/btrwMFXZsyX/VJYHkKwUzlgPU5HAL0SKHK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/XkxRt/btrwMFXZsyX/VJYHkKwUzlgPU5HAL0SKHK/img.jpg&quot; data-alt=&quot;Photo by Icons8 Team on Unsplash&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/XkxRt/btrwMFXZsyX/VJYHkKwUzlgPU5HAL0SKHK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FXkxRt%2FbtrwMFXZsyX%2FVJYHkKwUzlgPU5HAL0SKHK%2Fimg.jpg&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;6016&quot; height=&quot;4016&quot; data-filename=&quot;icons8-team-Ph5_4TnXXYE-unsplash.jpg&quot; data-origin-width=&quot;6016&quot; data-origin-height=&quot;4016&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Photo by Icons8 Team on Unsplash&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Reference&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;- Programming Bitcoin&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1647758957505&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;Programming Bitcoin&quot; data-og-description=&quot;Dive into Bitcoin technology with this hands-on guide from one of the leading teachers on Bitcoin and Bitcoin programming. Author Jimmy Song shows Python programmers and developers how to program &amp;hellip; - Selection from Programming Bitcoin [Book]&quot; data-og-host=&quot;www.oreilly.com&quot; data-og-source-url=&quot;https://learning.oreilly.com/library/view/programming-bitcoin/9781492031482/&quot; data-og-url=&quot;https://www.oreilly.com/library/view/programming-bitcoin/9781492031482/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/xOrcP/hyNI1aTWN7/tjHLDnkjcHRpkE52yh4bHk/img.jpg?width=140&amp;amp;height=184&amp;amp;face=0_0_140_184&quot;&gt;&lt;a href=&quot;https://learning.oreilly.com/library/view/programming-bitcoin/9781492031482/&quot; data-source-url=&quot;https://learning.oreilly.com/library/view/programming-bitcoin/9781492031482/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/xOrcP/hyNI1aTWN7/tjHLDnkjcHRpkE52yh4bHk/img.jpg?width=140&amp;amp;height=184&amp;amp;face=0_0_140_184');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Programming Bitcoin&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Dive into Bitcoin technology with this hands-on guide from one of the leading teachers on Bitcoin and Bitcoin programming. Author Jimmy Song shows Python programmers and developers how to program &amp;hellip; - Selection from Programming Bitcoin [Book]&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.oreilly.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;해당 Posting은 Bitcoin이 무엇이고, 이것으로 무엇을 할 수 있는지에 대해서 설명하지 않고 Bitcoin을 구현하는 기술에 대하여 다룹니다.&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;또한, 책의 모든 내용을 충실히 번역하는 것이 아닌 작성자의 생각이 많이 담겨 있으니 유의 바랍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;해당 chapter에서는 Bitcoin이 실제로 어떻게 전달되며, Bitcoin을 이용한 거래는 어떻게 수행되는지를 다룹니다. 또한, 이를 위해 Bitcoin에서 구축한 Script라는 language를 소개하고 여러 인증 방식을 소개합니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1. Transaction&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Transaction은 Bitcoin의 꽃이라고 표현할 수 있을 정도로 가장 중요한 위치를 차지하고 있습니다. 앞서 보았던, Signature, Serialization 역시 이를 위한 토대라고 보시면 됩니다. 우선 Transaction이 무엇인지에 대해서부터 알아봅시다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Transaction의 뜻을 한국어로 번역하면, 거래라고 할 수 있습니다. &lt;b&gt;Bitcoin system 상에서는, Bitcoin을 누군가에게 전송하는 행위를 Transaction이라고 정의합니다.&lt;/b&gt; Bitcoin 상에서 Transaction은 여러 &lt;b&gt;특이한 속성&lt;/b&gt;을 가집니다. 이를 이해하는 것이 Bitcoin을 이해하는 기반이 될 것입니다. (아래 특징은 저의 주관적인 생각을 담은 것입니다. 더 많은 특징이 있지만, 해당 chapter에서 설명할 내용을 이해하기 위해서는 다음 내용을 일단 머릿속에 새기고 가도록 합시다.)&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;1-1. 특징&lt;/b&gt;&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;공개성 (Public)&lt;/b&gt; : 모든 Transaction은 공유됩니다. 누구나 원한다면, 조회가 가능합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;연속성 (Continuity)&lt;/b&gt; : coinbase에서 직접 생성한 Transaction을 제외하고는 모든 Transaction은 이전 Transaction에 의존하여 정의됩니다. 또한, 해당 chapter에서는 coinbase에서 생성된 Transaction에서는 고려하지 않습니다. (실생활에서 생각해보면, 거래라는 것도 은행에서 직접 전달받은 돈이 아니라면, 모두 다른 사람과의 거래를 통해서 생성되는 것이므로 당연하다고 할 수 있습니다.)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;일회성 (One time)&lt;/b&gt; : 하나의 Transaction이 여러 번 사용될 수 없습니다. 단 한 번만 사용됩니다. (Transaction은 output을 여러 개 가지므로, 이들이 각 각 사용될 수는 있어도, 같은 Transaction의 같은 output은 단 한 번만 사용되어야 한다는 점입니다. 그렇기에 잔돈이 발생한다면, Transaction에 다시 자신에게 보내는 output을 생성합니다.)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;익명성 (Anonymous)&lt;/b&gt; : 해당 Transaction의 output을 사용할 사람을 명시하지 않습니다. 즉, 누구나 해당 Transaction output의 소유권을 주장할 수 있습니다. (실제 세상에서 누가 누구에게 보내는 것인지는 알 수 없습니다. 원한다면, 거래 address를 계속 바꿀 수도 있습니다. 그리고 그렇게 계속 바꾸는 것을 권장하기도 합니다.)&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Transaction을 통해서 우리는 Bitcoin을 받을 수도 있고, 전달할 수도 있으며, 해당 Bitcoin이 자신의 소유라는 것을 증명할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한, 기억해두어야 할 점은 Transaction의 Output은 Bitcoin을 포함한다는 사실을 기억합시다. 그리고, 모든 Bitcoin은 Transaction에 의해서 존재한다는 것을 기억하는 것입니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이것이 어떻게 가능한지 Transaction의 &lt;b&gt;구성 요소&lt;/b&gt;를 먼저 살펴보고 알아보도록 합시다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;1-2. 구성요소&lt;/b&gt;&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;Version&amp;nbsp;&lt;/b&gt;: Transaction의 version이 존재합니다. Bitcoin 자체가 계속해서 발전해왔기 때문에, 하나의 version으로 고정되어 있지는 않습니다. 대게는 1이지만, 필요에 따라 다른 version을 써야 하는 경우도 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Outputs&amp;nbsp;&lt;/b&gt;: 여러 개의 output을 가질 수 있으며, 각 output은 다음과 같은 값을 포함합니다.
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;amount&lt;/b&gt; : 해당 output이 가질 bitcoin의 양을 의미합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;ScriptPubKey&lt;/b&gt; : 해당 output이 후에 사용될 때, 정당한 권한이 있는지를 확인할 수단이 됩니다. 마치 금고의 잠금 장치라고 생각할 수 있습니다. 이를 어떻게 잠그는지에 대해서는 밑에서 Script part에서 설명합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Inputs&amp;nbsp;&lt;/b&gt;: 하나의 input은 이전 Transaction 중 하나의 output을 가르키고 있으며, 이를 여러 개 가질 수 있습니다. 여기서 각 input은 두 가지 기능을 할 수 있어야 합니다. 첫째로, &lt;b&gt;특정 Transaction의 하나의 output을 식별&lt;/b&gt;할 수 있어야 합니다. 사용하고자 하는 &lt;b&gt;Transaction이 자신의 것임을 증명&lt;/b&gt;할 수 있어야 합니다.&lt;b&gt;&lt;/b&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;PrevTxId&lt;/b&gt; : 이전 Transaction을 고유하게 식별할 수 있는 값입니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;PrevTxIndex &lt;/b&gt;: 이전 Transaction의 output 중 하나를 식별하기 위한 값입니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;ScriptSig&amp;nbsp;&lt;/b&gt;: 해당 output이 자신이 사용할 수 있는 데이터임을 증명할 수 있는 수단입니다. 마치 금고의 열쇠로 생각할 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Sequence &lt;/b&gt;: 초기에 Bitcoin 설계 시에는 동시에 서로 간에 너무 많은 Transaction이 생기는 것을 막기 위해서, 여러 Transaction을 하나의 Transaction으로 통합시키기를 원했습니다. 그래서 그때 해당 거래가 몇 번째 인지를 표시하기 위한 수단으로 사용되었으나 현재에는 보안상의 취약점이 발견되어 사용되고 있지 않기에, 4 bytes little endian으로 최댓값(0xffffffff)으로 표기합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Locktime&amp;nbsp;&lt;/b&gt;: 위에서 설명한 Sequence 처럼, Transaction을 어느 정도 시간이 될 때까지 Transaction의 input으로써 사용되는 것을 막는 것입니다. 이는 다음 chapter에서 설명할 Block의 height가 될 수도 있고, Unix timestamp를 통해서 시간을 지정할 수도 있습니다. 이 또한, 4 bytes를 통해서 표현합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;transaction-1.jpeg&quot; data-origin-width=&quot;1754&quot; data-origin-height=&quot;1000&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bTgxhF/btrwJVHhu3l/hUuPQxt2pjxnYhLAkPqkL1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bTgxhF/btrwJVHhu3l/hUuPQxt2pjxnYhLAkPqkL1/img.jpg&quot; data-alt=&quot;Transaction의 구성요소&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bTgxhF/btrwJVHhu3l/hUuPQxt2pjxnYhLAkPqkL1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbTgxhF%2FbtrwJVHhu3l%2FhUuPQxt2pjxnYhLAkPqkL1%2Fimg.jpg&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;632&quot; height=&quot;360&quot; data-filename=&quot;transaction-1.jpeg&quot; data-origin-width=&quot;1754&quot; data-origin-height=&quot;1000&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Transaction의 구성요소&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;1-3. 추가 개념&lt;/b&gt;&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;Fee&lt;/b&gt;&lt;br /&gt;&lt;b&gt;일명 거래 수수료&lt;/b&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; letter-spacing: 0px;&quot;&gt;라고 생각할 수 있습니다. 대게, 이 거래를 확인해주는 miner들에게 주어지는 보상으로 생각할 수 있습니다. 송신자는 거래를 할 때, 이를 인증받기 위해서 이를 확인해줄 여러 제3자들에게 일정 수수료를 제시합니다. 빠른 거래를 원한다면, 더 많은 비용을, 천천히 해도 상관이 없다면, 적은 비용을 투자할 수 있습니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; letter-spacing: 0px;&quot;&gt;&lt;b&gt;UTXO(Unspent Transaction Output) Set&lt;/b&gt;&lt;br /&gt;&lt;/span&gt;사용하지 않은 Transaction Output의 집합입니다. 이를 유지할 수 있어야지만, 왜냐하면, 두 번 이상 사용한다는 것 자체를 막아야만 하기 때문입니다. 모든 UTXO를 포함하고 있으며, 이를 계속해서 추적하는 노드를 Full nodes라고 부르며, 이것이 있어야지만 Bitcoin 거래를 빠르게 수행할 수 있습니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Transaction이라는 것은 결국 Bitcoin을 전달하는 방법입니다. 이것이 있어야만 우리는 실세계에 있는 물건을 사는 명분을 가질 수 있는 것입니다. 그런데 여기서, 의문점이 가장 크게 생길 수 있는 부분이 있습니다. 뭔가 거래를 하기 위해서는 Transaction을 통해서 Bitcoin을 보내야 하는 것은 이해했는데, 내가 보낼 때 사용하는 Transaction이 모두에게 공개된다고 했는데, 이게 자신의 것이라는 것을 어떻게 증명할 수 있을까요? 이 방법으로 고안된 것이 Script입니다. 이에 대해서 살펴봅시다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;transaction-2.jpeg&quot; data-origin-width=&quot;1335&quot; data-origin-height=&quot;999&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/0L54h/btrwLh38oet/efVoM14EDWK14AiJGpAV7k/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/0L54h/btrwLh38oet/efVoM14EDWK14AiJGpAV7k/img.jpg&quot; data-alt=&quot;Transaction의 관계 형성&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/0L54h/btrwLh38oet/efVoM14EDWK14AiJGpAV7k/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F0L54h%2FbtrwLh38oet%2FefVoM14EDWK14AiJGpAV7k%2Fimg.jpg&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;679&quot; height=&quot;508&quot; data-filename=&quot;transaction-2.jpeg&quot; data-origin-width=&quot;1335&quot; data-origin-height=&quot;999&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Transaction의 관계 형성&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2. Script&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Bitcoin(Transaction의 Output)을 전달할 때, 이를 누구나 쓸 수 없게 &lt;b&gt;잠그는 과정(lock)&lt;/b&gt;이 필요하고, 후에는 이를 사용할 수 있게&amp;nbsp;&lt;b&gt;해제 과정(unlock)&lt;/b&gt;이 필요합니다. Bitcoin에서는 이를 위해서 Script라는 것을 고안해냈습니다. Script는 완성된 형태로 존재할 때, 해당 output의 소유가 자신이라는 것을 &lt;b&gt;누구나 인정할 수 있는 문서&lt;/b&gt;가 됩니다. 그래서 이를 반으로 잘라서, 하나는 output 쪽에 붙여두고(&lt;b&gt;ScriptPubkey&lt;/b&gt;), 나머지 하나(&lt;b&gt;ScriptSig&lt;/b&gt;)는 자신이 소유하고 있다가 사용할 때, 이 조각을 들이 밀어서 자신임을 인정하는 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;그렇다면, Script라는 것이 도대체 무엇이길래 &lt;b&gt;누구나 인정할 수 있는 문서&lt;/b&gt;가 될 수 있는 것일까요? 이는 Script의 해석법을 알면, 이해할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2-1. Script (language)&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Script라고 쓰기도 하고, Script language라고도 부르는 해당 언어는&amp;nbsp;영어 같은 사람의 언어로 작성되지도 않고, python이나 c와 같은 &lt;b&gt;turning complete(=모든 계산 가능한 문제를 표현할 수 있는&lt;/b&gt;, 대게는 loop, condition, memory 제어 기능을 포함하는지를 의미합니다.&lt;b&gt;)&lt;/b&gt;한 programming language 로 작성하지 않습니다. 왜냐하면, 이러한 Script는 &lt;b&gt;효율&lt;/b&gt;을 위해서 너무 복잡한 로직을 가져서도 안되고, 보안상의 &lt;b&gt;취약점&lt;/b&gt;을 만들 수 있는 수단 자체를 막기 위해서 입니다. 따라서, Bitcoin의 Script에서는 loop문을 허용하지 않는 형태를 가집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2-2. 구성요소&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Script를 해석하기 위해서는, 구성요소를 먼저 알아야 합니다. 따라서, 각 구성요소에 대해서 알아보겠습니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;Element&lt;/b&gt; : 일반 programming language에서 variable이 하는 역할을 맡습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Operation&lt;/b&gt; : 일반 programming language에서 function의 역할을 맡습니다. 이는 element를 받아서 동작을 수행하여, Stack의 변화를 일으킵니다. 만약, 중간의 Operation의 동작이 실패한다면, 해당 Script의 실행은 종료되고, 타당하지 않은 Script라는 결론을 내놓습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Stack&lt;/b&gt; : 일반 programming language와는 다르지만, 후위 표현법에 기반한 language에서는 흔히 볼 수 있는 특징입니다. element가 존재할 수 있는 공간으로 operation은 stack 안에 있는 element만을 소비하여 동작합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전체 코드는 위에서부터 실행되면서, 마치 하나의 stack처럼 구성되며, 후위 표기식처럼 동작한다고 생각하면 됩니다. 후위 표기식에서는 element가 먼저 나오고 이를 기억해두고 있다가 연산을 수행하는 방식입니다. (따라서, stack이 필요한 것입니다.) 따라서, 위에서 부터 실행하면서 element가 나온다면, stack에 쌓아두고, operation이 나온다면 stack에 있는 데이터를 최신순으로 사용합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2-3. Operation의 종류&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞 서 Script는 turning complete한 언어가 아니라고 했으므로, operation에는 loop를 포함하지 않거나 현재는 사용되지 않습니다. 또한, 보안상 취약점이 밝혀진 Operation 역시 사용되지 않습니다. 여기서는 Script의 특성을 설명할 수 있는 몇 가지의 Operation을 설명하고 동작 방식을 설명합니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;OP_DUP&lt;/b&gt; : stack에 있는 element 중 가장 앞에 있는 element를 복사해서 stack에 추가합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;OP_x&lt;/b&gt;(number) : stack에 x element를 추가합니다. 이때, x는 0 ~ 16까지의 수를 뜻합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;OP_PUSHDATAx&lt;/b&gt; : 먼저 x byte에 해당하는 값을 받습니다. 이는 이제 stack에 입력할 데이터의 크기를 의미합니다. 그 후 입력받은 길이만큼을 읽어 들인 후에 이를 stack에 추가합니다. x는 1, 2,4가 존재하지만, stack에 입력하는 데이터는 최대 520 bytes 까지만 허용합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;OP_VERIFY&lt;/b&gt; : stack에서 하나의 값을 꺼낸 후, 1인지를 확인합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;OP_EQUAL&lt;/b&gt; : stack에서 두 개의 값을 꺼낸 후, 서로 같은지를 확인하고, 같다면 1 다르다면, 0을 추가합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;OP_CHECKSIG&lt;/b&gt; : stack에서 두 개의 값을 꺼낸 후, 첫 번째 element는 PubKey 그리고, 두 번째 element는 Signature로 하여 ECDSA를 만족시키는지를 확인합니다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;OP_MULTI_CHECK_SIG&lt;/b&gt; : 이는 stack에 PubKey와 Signature가 하나 이상일 때, 이를 모두 확인하는 방법입니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;OP_HASH160, OP_SHA1, OP_SHA256, OP_HASH256&lt;/b&gt; : stack의 하나의 element를 꺼낸 후, hash하여 다시 stack에 추가합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추가적인 Operation에 대해서도 궁금하다면, 아래 link를 참고해주세요.&lt;/p&gt;
&lt;figure id=&quot;og_1647849180736&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Script - Bitcoin Wiki&quot; data-og-description=&quot;Bitcoin uses a scripting system for transactions. Forth-like, Script is simple, stack-based, and processed from left to right. It is intentionally not Turing-complete, with no loops. A script is essentially a list of instructions recorded with each transac&quot; data-og-host=&quot;en.bitcoin.it&quot; data-og-source-url=&quot;https://en.bitcoin.it/wiki/Script&quot; data-og-url=&quot;https://en.bitcoin.it/wiki/Script&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://en.bitcoin.it/wiki/Script&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://en.bitcoin.it/wiki/Script&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Script - Bitcoin Wiki&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Bitcoin uses a scripting system for transactions. Forth-like, Script is simple, stack-based, and processed from left to right. It is intentionally not Turing-complete, with no loops. A script is essentially a list of instructions recorded with each transac&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;en.bitcoin.it&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;b&gt;2-3. Goal&lt;/b&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Script의 최종 목적은&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;Script의 모든 구성요소를 실행시켜서, 중간에 operation의 에러 없이 stack에 1이라는 숫자를 남기는 것입니다.&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;따라서, 해석이 실패하는 경우는 두 가지 입니다. Script의 해석 도중에 operation이 에러를 발생시켰거나, 모든 Script를 해석했음에도 stack에 1이 아닌 값이 있거나 아무 값도 없는 경우입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아까 말했듯이 우리는 이 Script를 두 개의 조각(ScriptPubKey, ScriptSig)으로 나눕니다. 즉, 코드를 중간에 툭 잘라버린다는 것입니다. 그래서, 후반부에 해당하는 내용(ScriptPubKey)을 Transaction의 Output에 넣어서 보관합니다. 그래서, ScriptPubKey에 전반부에 해당하는 ScriptSig를 가진 사람이 있다면, 그 사람이 Transaction의 Output에 있는 Bitcoin을 해당하는 amount만큼 사용할 수 있다는 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;script-1.jpeg&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;1092&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/crbKHg/btrwKFc5BAm/HD37uZDMjMtMEs7lYDhGmk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/crbKHg/btrwKFc5BAm/HD37uZDMjMtMEs7lYDhGmk/img.jpg&quot; data-alt=&quot;Script의 결합&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/crbKHg/btrwKFc5BAm/HD37uZDMjMtMEs7lYDhGmk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcrbKHg%2FbtrwKFc5BAm%2FHD37uZDMjMtMEs7lYDhGmk%2Fimg.jpg&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;213&quot; height=&quot;233&quot; data-filename=&quot;script-1.jpeg&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;1092&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Script의 결합&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2-4. Example&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 ScriptPubKey가 주어졌다고 가정합시다. 그렇다면, 이는 마치 하나의 문제처럼 느껴질 수 있고, 우리는 이를 만족하는 값을 ScriptSig에 넣어서 만들어주기만 하면 됩니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;2-4-1. $x^2 + x = 6$을 만족하는 x 값 넣기&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;완성된 Script에서 x에 무엇이 들어가면 될지를 추측해봅시다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bvuI88/btrwGkA3Lx4/5Vc0se1Dx0Jmwky38NPGSK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bvuI88/btrwGkA3Lx4/5Vc0se1Dx0Jmwky38NPGSK/img.png&quot; data-is-animation=&quot;undefined&quot; data-origin-width=&quot;999&quot; data-origin-height=&quot;648&quot; data-filename=&quot;blob&quot; width=&quot;217&quot; height=&quot;141&quot; data-widthpercent=&quot;50.09&quot; style=&quot;width: 49.5096%; margin-right: 10px;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bvuI88/btrwGkA3Lx4/5Vc0se1Dx0Jmwky38NPGSK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbvuI88%2FbtrwGkA3Lx4%2F5Vc0se1Dx0Jmwky38NPGSK%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;999&quot; height=&quot;648&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dc1UkS/btrwJV1zGFO/iV4OousXHiJJ0bDK9kl3VK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dc1UkS/btrwJV1zGFO/iV4OousXHiJJ0bDK9kl3VK/img.jpg&quot; data-is-animation=&quot;undefined&quot; data-origin-width=&quot;1536&quot; data-origin-height=&quot;1000&quot; data-filename=&quot;script-ex1-2.jpeg&quot; style=&quot;width: 49.3276%;&quot; data-widthpercent=&quot;49.91&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dc1UkS/btrwJV1zGFO/iV4OousXHiJJ0bDK9kl3VK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdc1UkS%2FbtrwJV1zGFO%2FiV4OousXHiJJ0bDK9kl3VK%2Fimg.jpg&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;1536&quot; height=&quot;1000&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/H60p8/btrw5PFLn8Q/tiLC7nt7XUhRgI35zObrDK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/H60p8/btrw5PFLn8Q/tiLC7nt7XUhRgI35zObrDK/img.jpg&quot; data-is-animation=&quot;undefined&quot; data-origin-width=&quot;1864&quot; data-origin-height=&quot;999&quot; data-filename=&quot;script-ex1-3.jpeg&quot; style=&quot;width: 26.9882%; margin-right: 10px;&quot; data-widthpercent=&quot;27.63&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/H60p8/btrw5PFLn8Q/tiLC7nt7XUhRgI35zObrDK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FH60p8%2Fbtrw5PFLn8Q%2FtiLC7nt7XUhRgI35zObrDK%2Fimg.jpg&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;1864&quot; height=&quot;999&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/sMCJT/btrw44iRLOb/O8x5ksgM39VscPWeLGsLyk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/sMCJT/btrw44iRLOb/O8x5ksgM39VscPWeLGsLyk/img.jpg&quot; data-is-animation=&quot;undefined&quot; data-origin-width=&quot;2182&quot; data-origin-height=&quot;1000&quot; data-filename=&quot;script-ex1-4.jpeg&quot; data-widthpercent=&quot;32.31&quot; style=&quot;width: 31.5608%; margin-right: 10px;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/sMCJT/btrw44iRLOb/O8x5ksgM39VscPWeLGsLyk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsMCJT%2Fbtrw44iRLOb%2FO8x5ksgM39VscPWeLGsLyk%2Fimg.jpg&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;2182&quot; height=&quot;1000&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bj1wZk/btrwVsL6kno/vegNMkhPahfprnIoJ9b4z0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bj1wZk/btrwVsL6kno/vegNMkhPahfprnIoJ9b4z0/img.jpg&quot; data-is-animation=&quot;undefined&quot; data-origin-width=&quot;2705&quot; data-origin-height=&quot;1000&quot; data-filename=&quot;script-ex1-5.jpeg&quot; style=&quot;width: 39.1255%;&quot; data-widthpercent=&quot;40.06&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bj1wZk/btrwVsL6kno/vegNMkhPahfprnIoJ9b4z0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbj1wZk%2FbtrwVsL6kno%2FvegNMkhPahfprnIoJ9b4z0%2Fimg.jpg&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;2705&quot; height=&quot;1000&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cCjDRE/btrwZ0uyVyH/ggWFaLvXYQe5q9ksVAMxA1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cCjDRE/btrwZ0uyVyH/ggWFaLvXYQe5q9ksVAMxA1/img.jpg&quot; data-is-animation=&quot;undefined&quot; data-origin-width=&quot;2537&quot; data-origin-height=&quot;1000&quot; data-filename=&quot;script-ex1-6.jpeg&quot; style=&quot;width: 29.9855%; margin-right: 10px;&quot; data-widthpercent=&quot;30.7&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cCjDRE/btrwZ0uyVyH/ggWFaLvXYQe5q9ksVAMxA1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcCjDRE%2FbtrwZ0uyVyH%2FggWFaLvXYQe5q9ksVAMxA1%2Fimg.jpg&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;2537&quot; height=&quot;1000&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bnmXSC/btrwVrzFzNm/ZQSNcGTj37QkaK2oN33w60/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bnmXSC/btrwVrzFzNm/ZQSNcGTj37QkaK2oN33w60/img.jpg&quot; data-is-animation=&quot;undefined&quot; data-origin-width=&quot;2863&quot; data-origin-height=&quot;1000&quot; data-filename=&quot;script-ex1-7.jpeg&quot; style=&quot;width: 33.8386%; margin-right: 10px;&quot; data-widthpercent=&quot;34.64&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bnmXSC/btrwVrzFzNm/ZQSNcGTj37QkaK2oN33w60/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbnmXSC%2FbtrwVrzFzNm%2FZQSNcGTj37QkaK2oN33w60%2Fimg.jpg&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;2863&quot; height=&quot;1000&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b1pv9D/btrwVsk6dTA/up08vLwfA3yX2Tcj8AJbDK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b1pv9D/btrwVsk6dTA/up08vLwfA3yX2Tcj8AJbDK/img.jpg&quot; data-is-animation=&quot;undefined&quot; data-origin-width=&quot;2864&quot; data-origin-height=&quot;1000&quot; data-filename=&quot;script-ex1-8.jpeg&quot; style=&quot;width: 33.8504%;&quot; data-widthpercent=&quot;34.66&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b1pv9D/btrwVsk6dTA/up08vLwfA3yX2Tcj8AJbDK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb1pv9D%2FbtrwVsk6dTA%2Fup08vLwfA3yX2Tcj8AJbDK%2Fimg.jpg&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;2864&quot; height=&quot;1000&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결론상 $x^2 + x = 6$을 만족하는 x값이 필요하므로 $ x = 2$여야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;b&gt;2-4-2. SHA-1의 collision을 발생시키는 두 개의 값&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번에는 다음과 같은 ScriptPubKey가 주어졌을 때, ScriptSig로 뭐가 들어가야 할지를 추측해봅시다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;script-ex2-1.jpeg&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;2138&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kTlYQ/btrwLg5eFlW/ywB8SvXFCstMoWvIAUErA0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kTlYQ/btrwLg5eFlW/ywB8SvXFCstMoWvIAUErA0/img.jpg&quot; data-alt=&quot;ScriptPubKey&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kTlYQ/btrwLg5eFlW/ywB8SvXFCstMoWvIAUErA0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkTlYQ%2FbtrwLg5eFlW%2FywB8SvXFCstMoWvIAUErA0%2Fimg.jpg&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;176&quot; height=&quot;2138&quot; data-filename=&quot;script-ex2-1.jpeg&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;2138&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;ScriptPubKey&lt;/figcaption&gt;
&lt;/figure&gt;
&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;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/loDOx/btrwLg5eGQQ/KMxKcxSxfyPDhPj4l5jKKK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/loDOx/btrwLg5eGQQ/KMxKcxSxfyPDhPj4l5jKKK/img.jpg&quot; data-is-animation=&quot;undefined&quot; data-origin-width=&quot;2086&quot; data-origin-height=&quot;1000&quot; data-filename=&quot;script-ex2-2.jpeg&quot; style=&quot;width: 28.0684%; margin-right: 10px;&quot; data-widthpercent=&quot;28.74&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/loDOx/btrwLg5eGQQ/KMxKcxSxfyPDhPj4l5jKKK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FloDOx%2FbtrwLg5eGQQ%2FKMxKcxSxfyPDhPj4l5jKKK%2Fimg.jpg&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;2086&quot; height=&quot;1000&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/N76y1/btrwMHaqQkl/aKGLUI04VQBsfNulgiCJYK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/N76y1/btrwMHaqQkl/aKGLUI04VQBsfNulgiCJYK/img.jpg&quot; data-is-animation=&quot;undefined&quot; data-origin-width=&quot;2502&quot; data-origin-height=&quot;1000&quot; data-filename=&quot;script-ex2-3.jpeg&quot; style=&quot;width: 33.666%; margin-right: 10px;&quot; data-widthpercent=&quot;34.47&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/N76y1/btrwMHaqQkl/aKGLUI04VQBsfNulgiCJYK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FN76y1%2FbtrwMHaqQkl%2FaKGLUI04VQBsfNulgiCJYK%2Fimg.jpg&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;2502&quot; height=&quot;1000&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bm1jYy/btrwIhYk4wQ/SkHfpk3slO54IS2xm5WhOk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bm1jYy/btrwIhYk4wQ/SkHfpk3slO54IS2xm5WhOk/img.jpg&quot; data-is-animation=&quot;undefined&quot; data-origin-width=&quot;2671&quot; data-origin-height=&quot;1000&quot; data-filename=&quot;script-ex2-4.jpeg&quot; style=&quot;width: 35.94%;&quot; data-widthpercent=&quot;36.79&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bm1jYy/btrwIhYk4wQ/SkHfpk3slO54IS2xm5WhOk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbm1jYy%2FbtrwIhYk4wQ%2FSkHfpk3slO54IS2xm5WhOk%2Fimg.jpg&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;2671&quot; height=&quot;1000&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/9vZIJ/btrwMFDF5eo/1fAKwLljilkFla9qjTRTz0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/9vZIJ/btrwMFDF5eo/1fAKwLljilkFla9qjTRTz0/img.jpg&quot; data-is-animation=&quot;undefined&quot; data-origin-width=&quot;2702&quot; data-origin-height=&quot;1000&quot; data-filename=&quot;script-ex2-5.jpeg&quot; style=&quot;width: 37.4615%; margin-right: 10px;&quot; data-widthpercent=&quot;38.35&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/9vZIJ/btrwMFDF5eo/1fAKwLljilkFla9qjTRTz0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F9vZIJ%2FbtrwMFDF5eo%2F1fAKwLljilkFla9qjTRTz0%2Fimg.jpg&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;2702&quot; height=&quot;1000&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/upS3b/btrwKFxpjvh/mIh2aKkHqaL9JC2ubo0kjk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/upS3b/btrwKFxpjvh/mIh2aKkHqaL9JC2ubo0kjk/img.jpg&quot; data-is-animation=&quot;undefined&quot; data-origin-width=&quot;2455&quot; data-origin-height=&quot;1000&quot; data-filename=&quot;script-ex2-6.jpeg&quot; style=&quot;width: 34.037%; margin-right: 10px;&quot; data-widthpercent=&quot;34.85&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/upS3b/btrwKFxpjvh/mIh2aKkHqaL9JC2ubo0kjk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FupS3b%2FbtrwKFxpjvh%2FmIh2aKkHqaL9JC2ubo0kjk%2Fimg.jpg&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;2455&quot; height=&quot;1000&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/be5QVZ/btrwRyRygOb/dxfKkgof6QDKK3Mayzb6p0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/be5QVZ/btrwRyRygOb/dxfKkgof6QDKK3Mayzb6p0/img.jpg&quot; data-is-animation=&quot;undefined&quot; data-origin-width=&quot;1888&quot; data-origin-height=&quot;1000&quot; data-filename=&quot;script-ex2-7.jpeg&quot; data-widthpercent=&quot;26.8&quot; style=&quot;width: 26.1759%;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/be5QVZ/btrwRyRygOb/dxfKkgof6QDKK3Mayzb6p0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbe5QVZ%2FbtrwRyRygOb%2FdxfKkgof6QDKK3Mayzb6p0%2Fimg.jpg&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;1888&quot; height=&quot;1000&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/SmLui/btrwPbCiaNz/vOo0rnf8TrZFMGTlPDKxwK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/SmLui/btrwPbCiaNz/vOo0rnf8TrZFMGTlPDKxwK/img.jpg&quot; data-is-animation=&quot;undefined&quot; data-origin-width=&quot;1616&quot; data-origin-height=&quot;1000&quot; data-filename=&quot;script-ex2-8.jpeg&quot; style=&quot;width: 37.8064%; margin-right: 10px;&quot; data-widthpercent=&quot;38.71&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/SmLui/btrwPbCiaNz/vOo0rnf8TrZFMGTlPDKxwK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FSmLui%2FbtrwPbCiaNz%2FvOo0rnf8TrZFMGTlPDKxwK%2Fimg.jpg&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;1616&quot; height=&quot;1000&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Mvh5L/btrwLhJPjzW/NkJiXDWpnzPsCWnJO3pv11/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Mvh5L/btrwLhJPjzW/NkJiXDWpnzPsCWnJO3pv11/img.jpg&quot; data-is-animation=&quot;undefined&quot; data-origin-width=&quot;1353&quot; data-origin-height=&quot;1000&quot; data-filename=&quot;script-ex2-9.jpeg&quot; data-widthpercent=&quot;32.41&quot; style=&quot;width: 31.6535%; margin-right: 10px;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Mvh5L/btrwLhJPjzW/NkJiXDWpnzPsCWnJO3pv11/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FMvh5L%2FbtrwLhJPjzW%2FNkJiXDWpnzPsCWnJO3pv11%2Fimg.jpg&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;1353&quot; height=&quot;1000&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/v461b/btrwIgLUbsv/TRZXZ4nNsmhvHMxI7WU9t0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/v461b/btrwIgLUbsv/TRZXZ4nNsmhvHMxI7WU9t0/img.jpg&quot; data-is-animation=&quot;undefined&quot; data-origin-width=&quot;1206&quot; data-origin-height=&quot;1000&quot; data-filename=&quot;script-ex2-10.jpeg&quot; style=&quot;width: 28.2145%;&quot; data-widthpercent=&quot;28.88&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/v461b/btrwIgLUbsv/TRZXZ4nNsmhvHMxI7WU9t0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fv461b%2FbtrwIgLUbsv%2FTRZXZ4nNsmhvHMxI7WU9t0%2Fimg.jpg&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;1206&quot; height=&quot;1000&quot;/&gt;&lt;/span&gt;&lt;/div&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;결론상 다음의 조건을 만족하는 h, k를 &lt;b&gt;ScriptSig&lt;/b&gt;로 넣어주면 됩니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&amp;nbsp;$h \ne k$&lt;/li&gt;
&lt;li&gt;$sha1(h) = sha1(k)$&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이는 SHA-1이 collision을 발생하게 하는 두 개의 값을 넣어주면 됩니다. (이를 찾을 수 있는지 없는지가 hash함수의 성능을 표시하는데 가장 큰 지표가 됩니다.)&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;이와 같은 형태로 특정 수학 문제, 또는 hash collision 예시에 대해서 Bitcoin을 통해서 현상금을 걸기도 한다고 합니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2-5. 주요 Script&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 예시를 살펴보았지만, 사실 위와 같은 형태로 Script를 표현한다면, 누구나 해당 Transaction의 Output안에 있는 Bitcoin을 사용할 수 있을 것입니다. 이제 나만 사용할 수 있는 Transaction Output을 만들기 위한 주요 Script 형태를 알아보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;2-5-1. p2pk(Pay to PubKey)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;ScriptPubKey&lt;/b&gt;에는 PubKey와 OP_CHECKSIG 두 개를 넣어두고, &lt;b&gt;ScriptSig&lt;/b&gt;에 Signature만 넣어두는 방식입니다. 이 방식 때문에, Transaction Output에 있는 ScriptPubKey의 이름이 이렇게 불려지고, Transaction Input의 ScriptSig의 이름이 정해지게 된 것입니다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;p2pk.jpeg&quot; data-origin-width=&quot;999&quot; data-origin-height=&quot;1583&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/8R13W/btrwJwAYTh8/GiPK0HZyHXOGZFdJgKtk8K/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/8R13W/btrwJwAYTh8/GiPK0HZyHXOGZFdJgKtk8K/img.jpg&quot; data-alt=&quot;p2pk&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/8R13W/btrwJwAYTh8/GiPK0HZyHXOGZFdJgKtk8K/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F8R13W%2FbtrwJwAYTh8%2FGiPK0HZyHXOGZFdJgKtk8K%2Fimg.jpg&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;392&quot; height=&quot;621&quot; data-filename=&quot;p2pk.jpeg&quot; data-origin-width=&quot;999&quot; data-origin-height=&quot;1583&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;p2pk&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;2-5-2. p2pkh(Pay to PubKey Hash)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;p2pk에서 문제가 하나 발생할 수 있습니다. 바로 공개키가 모든 이들에게 보인다는 점입니다. 이것이 왜 문제일 수 있냐고 할 수 있지만, 해당 거래 자체가 모두 공개되기 때문에 공개키를 열어두고, 긴 시간 동안 사용하지 않는다면, 언제 가는 무식하게 풀어나가는 과정에서 답을 찾아낼 수도 있습니다. 따라서, 대게는 공개키의 유효시간을 두고 하는 것이 일반적인 경우가 많습니다. 하지만, Transaction의 유효기간을 둘 수 없으므로, PubKey를 바로 공개하지 않는 방식입니다. 따라서, 이름에서부터 느껴지겠지만,&lt;b&gt; PubKey의 hash를 수행&lt;/b&gt;합니다. 그리고, 결론적으로 거래를 사용할 때, output을 사용하는 입장에서, pubkey와 signature를 모두 사용하는 방식입니다. (여기서 PubKey에 hash160을 수행하고, Base58로 encoding 한 것을 address라고 합니다.)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;p2pkh-1.jpeg&quot; data-origin-width=&quot;1463&quot; data-origin-height=&quot;1000&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bizsix/btrwK9R5PZJ/FSgfw1HD5DnYd1BnvZSOK0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bizsix/btrwK9R5PZJ/FSgfw1HD5DnYd1BnvZSOK0/img.jpg&quot; data-alt=&quot;ScriptPubKey 와 ScriptSig&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bizsix/btrwK9R5PZJ/FSgfw1HD5DnYd1BnvZSOK0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbizsix%2FbtrwK9R5PZJ%2FFSgfw1HD5DnYd1BnvZSOK0%2Fimg.jpg&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;448&quot; height=&quot;306&quot; data-filename=&quot;p2pkh-1.jpeg&quot; data-origin-width=&quot;1463&quot; data-origin-height=&quot;1000&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;ScriptPubKey 와 ScriptSig&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;p2pkh-2.jpeg&quot; data-origin-width=&quot;1173&quot; data-origin-height=&quot;1000&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bu1st3/btrwA0IHTYh/65KSk7skFZsCeK769oRBm0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bu1st3/btrwA0IHTYh/65KSk7skFZsCeK769oRBm0/img.jpg&quot; data-alt=&quot;Script의 성공적인 동작예시 1&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bu1st3/btrwA0IHTYh/65KSk7skFZsCeK769oRBm0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbu1st3%2FbtrwA0IHTYh%2F65KSk7skFZsCeK769oRBm0%2Fimg.jpg&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;581&quot; height=&quot;496&quot; data-filename=&quot;p2pkh-2.jpeg&quot; data-origin-width=&quot;1173&quot; data-origin-height=&quot;1000&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Script의 성공적인 동작예시 1&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;p2pkh-3.jpeg&quot; data-origin-width=&quot;1406&quot; data-origin-height=&quot;1000&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lne9d/btrwJv9UIed/rNNdHU6M8dBiRXkT2Y7nak/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lne9d/btrwJv9UIed/rNNdHU6M8dBiRXkT2Y7nak/img.jpg&quot; data-alt=&quot;Script의 성공적인 동작예시 2&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lne9d/btrwJv9UIed/rNNdHU6M8dBiRXkT2Y7nak/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Flne9d%2FbtrwJv9UIed%2FrNNdHU6M8dBiRXkT2Y7nak%2Fimg.jpg&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;590&quot; height=&quot;420&quot; data-filename=&quot;p2pkh-3.jpeg&quot; data-origin-width=&quot;1406&quot; data-origin-height=&quot;1000&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Script의 성공적인 동작예시 2&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;2-5-3. p2psh (Pay to Script Hash)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;p2psh는 여러 개의 key와 signature를 가지는 경우에 사용할 수 있습니다. 여러 개의 PubKey를 포함하고 있는 RedeemScript라는 것을 Hash 하여 ScriptPubKey에 추가시키는 것입니다. RedeemScript라고 불리는 이유는 이것이 후에 다시 하나의 Script로 동작하기 때문입니다. 내부에 들어가는 RedeemScript는 Serialization 해서 element로 넣습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;p2sh-1.jpeg&quot; data-origin-width=&quot;2154&quot; data-origin-height=&quot;1000&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/1sv5L/btrwJV8h42j/qgQU5JwGWqKQ34SJAdEpr0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/1sv5L/btrwJV8h42j/qgQU5JwGWqKQ34SJAdEpr0/img.jpg&quot; data-alt=&quot;ScriptPubKey, ScriptSig 과 RedeemScript&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/1sv5L/btrwJV8h42j/qgQU5JwGWqKQ34SJAdEpr0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F1sv5L%2FbtrwJV8h42j%2FqgQU5JwGWqKQ34SJAdEpr0%2Fimg.jpg&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;616&quot; height=&quot;286&quot; data-filename=&quot;p2sh-1.jpeg&quot; data-origin-width=&quot;2154&quot; data-origin-height=&quot;1000&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;ScriptPubKey, ScriptSig 과 RedeemScript&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;p2sh-2.jpeg&quot; data-origin-width=&quot;1207&quot; data-origin-height=&quot;1000&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/n2ocY/btrwA0BVv47/KZxZsCS8KRkaInTaMovp4K/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/n2ocY/btrwA0BVv47/KZxZsCS8KRkaInTaMovp4K/img.jpg&quot; data-alt=&quot;Script의 동작 예시 - 1&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/n2ocY/btrwA0BVv47/KZxZsCS8KRkaInTaMovp4K/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fn2ocY%2FbtrwA0BVv47%2FKZxZsCS8KRkaInTaMovp4K%2Fimg.jpg&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;578&quot; height=&quot;479&quot; data-filename=&quot;p2sh-2.jpeg&quot; data-origin-width=&quot;1207&quot; data-origin-height=&quot;1000&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Script의 동작 예시 - 1&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;p2sh-3.jpeg&quot; data-origin-width=&quot;1580&quot; data-origin-height=&quot;1000&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cAQfmi/btrwGkgKMRs/u7wVH4kw0WBC1KxyPXb5v0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cAQfmi/btrwGkgKMRs/u7wVH4kw0WBC1KxyPXb5v0/img.jpg&quot; data-alt=&quot;Script의 동작 예시 - 2&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cAQfmi/btrwGkgKMRs/u7wVH4kw0WBC1KxyPXb5v0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcAQfmi%2FbtrwGkgKMRs%2Fu7wVH4kw0WBC1KxyPXb5v0%2Fimg.jpg&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;564&quot; height=&quot;357&quot; data-filename=&quot;p2sh-3.jpeg&quot; data-origin-width=&quot;1580&quot; data-origin-height=&quot;1000&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Script의 동작 예시 - 2&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;p2sh-4.jpeg&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;1195&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cPpP1M/btrwLgKXsGS/xZ44sahictCTckBkU9UhN1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cPpP1M/btrwLgKXsGS/xZ44sahictCTckBkU9UhN1/img.jpg&quot; data-alt=&quot;Script의 동작 예시 - 3&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cPpP1M/btrwLgKXsGS/xZ44sahictCTckBkU9UhN1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcPpP1M%2FbtrwLgKXsGS%2FxZ44sahictCTckBkU9UhN1%2Fimg.jpg&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;573&quot; height=&quot;685&quot; data-filename=&quot;p2sh-4.jpeg&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;1195&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Script의 동작 예시 - 3&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;2-5-0.  Signature 생성&lt;br /&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주요 Script를 알아보기 전에 빠트린 부분을 먼저 채우고 가야 합니다. 바로, 이전에 ECDSA에서 사용하던 변수 중 현재 누락된 변수를 채우는 것입니다. 이전에 살펴봤듯이 특정 data의 소유가 자신이라는 것을 인증하기 위해서, ECDSA에서는 공개하는 데이터로 Signature와 data의 hash 값 그리고 Public Key를 이용했고, 공개하지 않고, 자신만 가지는 데이터로 Private Key라는 것을 가졌습니다. 여기서 누락된 것은 바로 &lt;b&gt;data의 hash 값&lt;/b&gt;과 &lt;b&gt;Signature의 생성 &lt;/b&gt;방법입니다.(왜냐하면, Signature는 data의 hash값이 존재해야만 수행할 수 있기 때문입니다.) 이는 어떻게 만들어지는 알아봅시다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;현재의 Transaction에서 모든 input의 ScriptSig를 빈 값으로 변환합니다.&lt;/li&gt;
&lt;li&gt;그리고, ScriptSig를 생성해야 하는 input에 ScriptSig 부분에만 이전 Transaction의 ScriptPubKey를 대입합니다. (이해를 돕기 위해서 이렇게 썼지만, 이 방법만 있는 것은 아닙니다. 이런 방법이 몇 개 더 있으면, 이 방법에 대한 식별 값이 4번에서 표시됩니다.)&lt;/li&gt;
&lt;li&gt;이를 이제 Serialization 합니다.&lt;/li&gt;
&lt;li&gt;Hash 방법에 해당하는 data의 맨 뒤에 4 bytes로 삽입합니다.&lt;/li&gt;
&lt;li&gt;그리고, 이를 Hash 합니다.&lt;/li&gt;
&lt;li&gt;이렇게 생성된 hash 값을 이용해서 Signature를 생성합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제, 우리는 z와 signature를 생성했습니다. 이제 Transaction의 생성자는 signature를 포함시킬 수 있게 되었습니다. 또한, Transaction을 볼 수 있는 다른 모든 사람들도 해당 Transaction이 타당한지 확인하기 위해서는 단지 Transaction을 위와 같이 변경하여서, z를 얻을 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;3. Transaction Validation&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇다면, 우리는 Transaction이 언제 타당하다고 말할 수 있을까요? 바로 다음 세 가지를 만족시켜야지 우리는 해당 Transaction이 타당하다고 합니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; letter-spacing: 0px;&quot;&gt;사용하고자 하는 Transaction의 output이 진짜 사용된 적이 없는지를 확인해야 합니다.&lt;br /&gt;이는 위에서 제시했던 UTXO를 조회하는 방법으로 수행합니다. 지금은 이 정도로 밖에 설명할 수 없지만, 이는 후에서 더 자세히 다룹니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Transaction의 input들보다 output들이 더 큰 값을 내보내지는 않았는지 확인해야 합니다.&lt;br /&gt;이는 이전 Transaction Output을 모두 더한 값이 혹여 현재 Transaction의 Output의 총합보다 큰지를 확인하도록 해야 합니다. 위의 진짜 사용 여부를 확인하는 과정에서 이전 Transaction output의 amount도 알 수 있으므로 이는 쉽게 계산할 수 있습니다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;ScriptSig + ScriptPubKey로 만들어진 최종 Script가 타당한지 확인해야 합니다.&lt;br /&gt;이는 위에서 진행했던 Script의 Check를 통해서 수행 가능합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 모든 과정을 통과했을 때, 우리는 해당 Transaction이 타당하다고 말할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;4. Transaction Creation&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제까지의 모든 것을 정리하여, Transaction의 생성 과정을 모두 정리해보겠습니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt; Transaction을 통해 Bitcoin을 보낼 대상의 PubKey 또는 address(PubKey를 hash + Base58)를 받아오고, 얼마나 Bitcoin을&amp;nbsp; 보낼지(amount)를 결정합니다.&lt;/li&gt;
&lt;li&gt;Transaction의 fee로 얼마나 지출할지를 결정합니다.&lt;/li&gt;
&lt;li&gt;Inputs가 사용하는 이전 Transaction Outputs의 합이 (fee + 지출할 Bitcoin) Outputs의 총합보다 크도록 CTXO를 하나 이상 선택합니다. (이 과정에서 CTXO가 정말 사용된 것이 아닌 것인지에 대한 확인도 수행합니다.)&lt;/li&gt;
&lt;li&gt;CTXO가 자신의 값임을 증명할 수 있도록 Signature를 생성하고, (이 과정에서 당연히 2-5-0에서 설명된 과정이 수행됩니다.) 이전 Transaction Output에서 제시한 &lt;b&gt;ScriptPubKey&lt;/b&gt;와 결합했을 때, 타당한 Script가 될 수 있도록 하는 &lt;b&gt;ScriptSig&lt;/b&gt;를 생성합니다.&lt;/li&gt;
&lt;li&gt;위에서 생성한 ScriptSig와 이전 Transaction Output을 특정할 수 있는 값을 묶어서 Transaction Input들을 작성합니다.&lt;/li&gt;
&lt;li&gt;Bitcoin을 보낼 대상의 address를 이용해서, 적절한 &lt;b&gt;ScriptPubKey&lt;/b&gt;를 생성하여, amount와 함께 Transaction Output들을 만듭니다. 이때 잔돈이 발생한다면, 자신에게 다시 보내는 Transaction Output도 생성해야 합니다.&lt;/li&gt;
&lt;li&gt;Transaction에 version, locktime 등을 추가하여, Transaction을 최종으로 생성합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전 글과 동일하게 구현 사항은 github에 정의해두었습니다.&lt;/p&gt;
&lt;figure id=&quot;og_1647916456519&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - euidong/bitcoin: BitCoin Implementation&quot; data-og-description=&quot;BitCoin Implementation. Contribute to euidong/bitcoin development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/euidong/bitcoin&quot; data-og-url=&quot;https://github.com/euidong/bitcoin&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/N8Nd3/hyNNf1m9E6/pS1qCcDtfL7eGBSU3CK4lk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/euidong/bitcoin&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/euidong/bitcoin&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/N8Nd3/hyNNf1m9E6/pS1qCcDtfL7eGBSU3CK4lk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;GitHub - euidong/bitcoin: BitCoin Implementation&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;BitCoin Implementation. Contribute to euidong/bitcoin development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;</description>
      <category>BlockChain</category>
      <category>Bitcoin</category>
      <category>MultiSig</category>
      <category>P2PK</category>
      <category>P2PKH</category>
      <category>P2SH</category>
      <category>script</category>
      <category>transaction</category>
      <category>Tx</category>
      <author>euidong</author>
      <guid isPermaLink="true">https://justlog.tistory.com/33</guid>
      <comments>https://justlog.tistory.com/33#entry33comment</comments>
      <pubDate>Tue, 22 Mar 2022 11:22:55 +0900</pubDate>
    </item>
    <item>
      <title>Bitcoin (2) -  Serialization</title>
      <link>https://justlog.tistory.com/32</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;icons8-team-Ph5_4TnXXYE-unsplash.jpg&quot; data-origin-width=&quot;6016&quot; data-origin-height=&quot;4016&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/djbYEJ/btrwhdB7Eg1/XWENlugTmSlqz63K8YZJ0K/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/djbYEJ/btrwhdB7Eg1/XWENlugTmSlqz63K8YZJ0K/img.jpg&quot; data-alt=&quot;Photo by Icons8 Team on Unsplash&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/djbYEJ/btrwhdB7Eg1/XWENlugTmSlqz63K8YZJ0K/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdjbYEJ%2FbtrwhdB7Eg1%2FXWENlugTmSlqz63K8YZJ0K%2Fimg.jpg&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;6016&quot; height=&quot;4016&quot; data-filename=&quot;icons8-team-Ph5_4TnXXYE-unsplash.jpg&quot; data-origin-width=&quot;6016&quot; data-origin-height=&quot;4016&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Photo by Icons8 Team on Unsplash&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Reference&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;- Programming Bitcoin&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1647569097258&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;Programming Bitcoin&quot; data-og-description=&quot;Dive into Bitcoin technology with this hands-on guide from one of the leading teachers on Bitcoin and Bitcoin programming. Author Jimmy Song shows Python programmers and developers how to program &amp;hellip; - Selection from Programming Bitcoin [Book]&quot; data-og-host=&quot;www.oreilly.com&quot; data-og-source-url=&quot;https://learning.oreilly.com/library/view/programming-bitcoin/9781492031482/&quot; data-og-url=&quot;https://www.oreilly.com/library/view/programming-bitcoin/9781492031482/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/xOrcP/hyNI1aTWN7/tjHLDnkjcHRpkE52yh4bHk/img.jpg?width=140&amp;amp;height=184&amp;amp;face=0_0_140_184&quot;&gt;&lt;a href=&quot;https://learning.oreilly.com/library/view/programming-bitcoin/9781492031482/&quot; data-source-url=&quot;https://learning.oreilly.com/library/view/programming-bitcoin/9781492031482/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/xOrcP/hyNI1aTWN7/tjHLDnkjcHRpkE52yh4bHk/img.jpg?width=140&amp;amp;height=184&amp;amp;face=0_0_140_184');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Programming Bitcoin&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Dive into Bitcoin technology with this hands-on guide from one of the leading teachers on Bitcoin and Bitcoin programming. Author Jimmy Song shows Python programmers and developers how to program &amp;hellip; - Selection from Programming Bitcoin [Book]&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.oreilly.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;해당 Posting은 Bitcoin이 무엇이고, 이것으로 무엇을 할 수 있는지에 대해서 설명하지 않고 Bitcoin을 구현하는 기술에 대하여 다룹니다.&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;또한, 책의 모든 내용을 충실히 번역하는 것이 아닌 작성자의 생각이 많이 담겨 있으니 유의 바랍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;해당 chapter에서는 Bitcoin에서 데이터를 어떻게 Serialization 하고, Parsing 하는지에 대해서 다룹니다.&lt;/b&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저, Serialization이 무엇인지부터 알아보아야 합니다. Serialization이란 현재 programmer가 만들어놓은 data(Class Instance, 등)를 network를 통해서 다른 computer로 옮기거나, 저장 장치 file 등으로 옮겨 담을 때, &lt;b&gt;연속적으로 표현되는 형태&lt;/b&gt;로 구조화하는 방법을 말합니다. 대게, 이러한 처리는 원본 데이터를 변환하기 때문에, 이를 원래 data로 변환하는 Parsing과 짝을 이룹니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터마다, 그리고 사람마다 더 좋다고 생각하는 serialization 방식은 매우 많습니다.&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-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;효율성&lt;/b&gt; : 변환하는 데이터가 짧게 표현될 수록 더 효율적으로 전달이 가능하다는 것은 자명하기에 이는 가장 중요한 요소 중 하나입니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;보안성&lt;/b&gt; : network로 전달이 될 가능성이 높기 때문에, 이를 전달받은 누구나 이를 변환할 수 있다면, 위험할 수 있습니다. 따라서, 보안성을 위해서, 암호화 또는 hashing을 수행하기도 합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;안정성&lt;/b&gt; : 대게 보안성과 묶어서 설명하지만, 여기서는 분리하였습니다. 즉, 데이터가 중간에 손실되지 않고, 안정적으로 제대로 도착했는지를 확인할 수 있도록 하는 것도 중요합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;표준&lt;/b&gt; : 결국 Serialization을 하더라도, 이를 수신받은 입장에서는 이를 번역한 내용에 관심이 있기에, 이를 번역할 방법이 서로 공유가 되어있어야 합니다. 그렇기에 많은 경우에, Serialization을 표준으로 정해진 방식을 통해서 수행됩니다. 또는, 새로운 표준을 만들어서 수행합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;가독성&lt;/b&gt; : 대게, serialization된 데이터 자체를 사람 간에 구두로 전달해야 할 경우가 있습니다. 이를 위해서, 인간 친화적인 형태로 데이터를 변조하는 경우도 많습니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저, Bitcoin에서 구체적으로 어떤 식으로 Serialization을 살펴보기 전에 기반 기술을 알아볼 것입니다. 각 기술에 대해서 이미 알고 있다면, 바로 다음으로 넘어가도 좋습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1.  Byte화&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반적으로, Serialization을 수행한 결과물은 bytes(8bit) 형태로 나타나는 것이 일반적입니다. 왜냐하면, 당연히 일반적인 programming에서 사용되는 integer(4 bytes) 형태로 표현하는 것은 비효율적이기 때문입니다. 또한, 컴퓨터 자체가 byte 단위로 데이터를 알아먹기 때문에, 컴퓨터 친화적으로 데이터를 변환한다고 생각하면 될 거 같습니다. 따라서, 데이터를 변환하여 결과물이 byte 단위로 묶이는 것이 일반적입니다. (+ 단순히 좀 더 효율적인 형태로 변환했다고 생각해도 됩니다. 그러기 위해서, 사람이 해당 문자를 보고, 한 번에 무슨 숫자인지 찾아내기는 좀 힘들어집니다.)&lt;/p&gt;
&lt;pre id=&quot;code_1647571136227&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// c++을 안다면 도움이 되겠지만, c를 잘 모르신다면, 이해할려고 하지말고 넘어가셔도 됩니다.
int a = 255 // 4 bytes
char a = 255 // 1 byte&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;여기서, byte type을 다룰 때, 항상 발생하는 문제인 &lt;b&gt;호환성&lt;/b&gt;을 확인해야 합니다. 사람은 일반적으로 수를 쓸 때, 왼쪽에서부터 큰수가 나오며, 오른쪽으로 쓰는 것이 표준처럼 정해져 있습니다. 하지만, computer 세계에서는 그렇지 않기 때문에, 왼쪽이 큰 수 인지, 오른쪽이 큰 수 인지를 정해줄 필요가 있습니다. 따라서, 이를 표준으로 정해서 어떤 데이터를 serialization 할 때 왼쪽이 큰 수가 되는 (Big endian)을 사용할지, 오른쪽이 큰 수가 되는 (Little endian)을 사용할지를 반드시 정해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2. Base58&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 이해하기 위해서는 Base64를 먼저 이해해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이는 특정 데이터를 총 64개의 문자 (10(숫자) + 26(알파벳 소문자) + 26(알파벳 대문자) + 2(기호 +, /))로 이루어진 문자 체계로 변환하는 것을 말합니다. 우리가 하나의 byte(8 bits)로 256개의 데이터를 표현할 수 있지만, 다음과 같이 Base64로 변환하게 되면 6bit을 사용하기 때문에 결과적으로 데이터의 크기가 커지는 현상이 발생하게 됩니다.(결국에는 byte단위로 전송하는데, 그중에 6bit만 사용하기 때문입니다.) 그럼에도 이를 사용하는 이유는 &lt;b&gt;호환성&lt;/b&gt;을 높이기 위해서 입니다. 국제적인 표준이기 때문에, Base64를 이용한다면, 어떤 시스템에서도 이를 해석하는 데는 문제가 없습니다. 따라서, 이러한 형태로의 변환은 굉장히 빈번히 사용됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇다면, Base58은 무엇인가에 대해서 고민을 해보아야 합니다. Base58이란, Base64에 &lt;b&gt;가독성&lt;/b&gt;을 높이기 위한 version이라고 생각할 수 있습니다. 바로 사람이 읽었을 때, 헷갈릴 수 있겠다고 판단되는 데이터를 과감하게 제거해버리는 것입니다. 따라서, 기존의 Base64에서 0(숫자 0), O(대문자 o), l(소문자 L), I(대문자 i), +, /를 제거하여 표현하는 것입니다. 따라서, 결론상 58개의 문자 (9(숫자) + 25(소문자) + 24(대문자))로 표현하는 방식입니다. 또한, 부가적으로 &lt;b&gt;안정성&lt;/b&gt;을 높이기 위해서, base58에서는 hash256을 이용해서 만들어진 데이터를 추가로 전송하여, checksum으로 사용하는 구현도 존재합니다. (checksum이란, 수신을 받은 측에서 데이터의 손실 여부를 확인할 때, 사용할 수 있는 데이터를 말합니다. 여기서는 자세히 다루지 않습니다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;3. DER(Distinguished Encoding Rule)&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;serialization 기법 중에 하나입니다. 이름에서부터 느껴지다시피 serialization을 수행할 때, 정확한 구분자와 길이를 data 앞에 배치시켜서 변환을 쉽게 하기 위한 방법 중에 하나입니다. 여기서는, Bitcoin에서 사용하는 DER 방식만 다루기에 해당 방식이 어떻게 돌아가는지만 다루겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;BitCoin에서는 Signature(서명)을 전달할 때, 해당 방식을 사용하는데, 이는 이 전 chapter에서 살펴봤듯이 두개의 integer로 이루어집니다. 그렇기에 여러 개를 보낼 때, 이를 감싸 줄 수 있는 Sequence와 Integer 형을 보낼 때, 사용하는 구분자를 data 앞에 넣어주어야 합니다. (Sequence = 0x30, Integer = 0x02) 또한, data의 사이즈 역시 같이 붙여주어야 합니다. (단위가 byte라는 것을 유의합시다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서, 형태가 다음과 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;&lt;span style=&quot;background-color: #fafafa;&quot;&gt;0x30 + {전체 전송 data의 사이즈} + 0x02 + {보낼 integer data의 사이즈} + {전송할 data(bytes)} + 0x02 + {보낼 integer data의 사이즈} + {전송할 data(bytes)}&lt;/span&gt;&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;예시로 다음을 들 수 있습니다. 만약에 1과 2라는 수를 동시에 보내고 싶을 때에는 다음과 같이 전달된다고 볼 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;0x30\0x06\0x02\0x01\0x01\0x02\0x01\0x02&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;/p&gt;
&lt;figure id=&quot;og_1647572414319&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;ASN 형식의 DER 인코딩 - Win32 apps&quot; data-og-description=&quot;인증서 등록 API에서 지 원하는 ASN 데이터 형식이 Distinguished Encoding Rules (DER)를 사용 하 여 인코딩 되는 방법입니다.&quot; data-og-host=&quot;docs.microsoft.com&quot; data-og-source-url=&quot;https://docs.microsoft.com/ko-kr/windows/win32/seccertenroll/about-der-encoding-of-asn-1-types&quot; data-og-url=&quot;https://docs.microsoft.com/ko-kr/windows/win32/seccertenroll/about-der-encoding-of-asn-1-types&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/eimuxH/hyNJ6KfVnh/DIEKT1oWsz4x19ol9ypNjK/img.png?width=400&amp;amp;height=400&amp;amp;face=0_0_400_400&quot;&gt;&lt;a href=&quot;https://docs.microsoft.com/ko-kr/windows/win32/seccertenroll/about-der-encoding-of-asn-1-types&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://docs.microsoft.com/ko-kr/windows/win32/seccertenroll/about-der-encoding-of-asn-1-types&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/eimuxH/hyNJ6KfVnh/DIEKT1oWsz4x19ol9ypNjK/img.png?width=400&amp;amp;height=400&amp;amp;face=0_0_400_400');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;ASN 형식의 DER 인코딩 - Win32 apps&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;인증서 등록 API에서 지 원하는 ASN 데이터 형식이 Distinguished Encoding Rules (DER)를 사용 하 여 인코딩 되는 방법입니다.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;docs.microsoft.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;4. SEC(Standards for Efficient Cryptography)&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;serialization 기법 중에 하나이며, 특히 암호화 과정에서 사용되는 표준 정도로 볼 수 있습니다. 대게 ECC(Elliptic Curve Cryptography)의 암호화 시에 생성된 public key 등에 대한 표준화 내용을 포함합니다. Bitcoin에서는 Public key 전송 시에 SEC를 사용함으로 이에 대한 내용만을 다루겠습니다.&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;먼저, 여기서는 Public key를 두 가지 mode로 표현합니다.&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;첫 번째로, 압축(compression)을 사용하지 않은 표현법으로 이는 매우 단순합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선은, 0x04를 데이터 맨 앞에 붙이고, 순서대로 Public key의 X좌표, Y좌표를 붙여주면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;&lt;span style=&quot;background-color: #fafafa;&quot;&gt;0x04 + {public key's x (bytes)} + {public key's y (bytes)}&lt;/span&gt;&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이는 항상 사이즈가 65(1 + 32 + 32)bytes로 고정된다는 점을 알 수 있을 것입니다. (그렇기 때문에, 위에서 설명한 DER 방식없이도 전송이 가능합니다.)&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;두 번째로, 압축(compression)을 사용하는 표현법입니다. 전송하는 두 개의 데이터 $x$,$y$가 Elliptic Curve 위에 존재한다는 연관점을 활용하는 것입니다. ($y^2 = x^3 + ax + b$)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$x$만 보내고, $y$를 알기 위해서는 두 가지 문제를 해결할 수 있어야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;제곱근 연산($\sqrt{y^2}$)이 가능한가?&lt;/li&gt;
&lt;li&gt;제곱근으로 나온 결과값 중 어떤 것이 근인지 확신할 수 있는가?&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 제곱근 연산은 다음과 같은 상황에서는 쉽게 구할 수 있습니다. ($p+1$이 4의 배수인 경우)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$$ p \% 4 = 3$$&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$$(p + 1) \% 4 = 0$$&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다행히도, Bitcoin가 사용하는 ECDSA에서는 이를 만족합니다. 그렇다면, 아래의 식을 만족하여 쉽게 제곱근을 구할 수 있습니다. (중간에 $(p+1)/2$ 이 가능한 이유는 Prime number는 2를 제외하고는 모두 홀수 이기 때문입니다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$$w^2 = v$$&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$$w^{p-1} \% p = 1$$&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$$w=w^{(p+1)/2}=w^{2(p+1)/4} = (w^2)^{(p+1)4} = v^{(p+1)/4} $$&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또 하나의 제곱근을 구할 때에는 간단하게 다음을 수행합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$$-w = p - w$$&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음으로, 제곱근으로 나온 값 중 특정하는 방법은 바로 홀수인지 짝수인지를 알려주는 1byte만을 전송해주면 됩니다. 왜냐하면, 위에 식에서 알 수 있듯이 $w$가 짝수이면, 또 다른 근인 $-w$는 홀수일 수 밖에 없기 때문입니다. ($p$ = 홀수)&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;우선은, 0x02 또는 0x03 데이터를 맨 앞에 붙이고, 순서대로 Public key의 X좌표를 붙여주면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;&lt;span style=&quot;background-color: #fafafa;&quot;&gt;짝수 : 0x02 + {public key's x (bytes)}&lt;/span&gt;&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;&lt;span style=&quot;background-color: #fafafa;&quot;&gt;홀수 : 0x03 + {public key's x (bytes)}&lt;/span&gt;&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이는 항상 사이즈가 33(1 + 32)bytes로 고정된다는 점을 알 수 있을 것입니다.&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;figure id=&quot;og_1647581276264&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Standards for Efficient Cryptography Group&quot; data-og-description=&quot;Standards for Efficient Cryptography Group Purpose The Standards for Efficient Cryptography Group (SECG), an industry consortium, was founded in 1998 to develop commercial standards that facilitate the adoption of efficient cryptography and interoperabilit&quot; data-og-host=&quot;www.secg.org&quot; data-og-source-url=&quot;https://www.secg.org/&quot; data-og-url=&quot;https://www.secg.org/&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://www.secg.org/&quot; data-source-url=&quot;https://www.secg.org/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('&amp;quot;&amp;quot;');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Standards for Efficient Cryptography Group&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Standards for Efficient Cryptography Group Purpose The Standards for Efficient Cryptography Group (SECG), an industry consortium, was founded in 1998 to develop commercial standards that facilitate the adoption of efficient cryptography and interoperabilit&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.secg.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;5. Hash160, Hash256&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;hash라는 것 역시 serialization part에서 빈번하게 등장할 수 밖에 없는 내용입니다. hash란 다음과 같은 특징을 가지는 함수를 말합니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;one way function : 역연산이 불가능연산입니다.&lt;/li&gt;
&lt;li&gt;return fixed length : 반환된 결과값이 항상 일정한 길이를 가집니다.&lt;/li&gt;
&lt;li&gt;collision with very low probability : 반환된 결과값이 충돌될 가능성이 사실상 없다. 즉, 완벽한 1:1 대칭은 아니지만, 이에 매우 근사한다는 것입니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;hash의 전반적인 설명은 여기서 다루지 않기 때문에, 이정도만 기억해두시면 됩니다. 역연산이 불가능하기 때문에, 대게 데이터를 알 수 없는 형태로 저장하고자 하는 경우에 많이 사용합니다. 대표적인 예시로 MD-5, SHA-1, SHA-2(SHA-256, SHA-512, ...)가 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;hash는 대게의 경우 매우 제대로 잘 동작하지만, collision에 의해서 망가지는 경우가 있습니다. 따라서, 이를 보안하기 위해서 계속해서 새로운 방법들이 고안 되었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서, Bitcoin에서는 SHA256 이후에 이를 다시 한 번 ripemd160을 수행하는 것을 Hash160이라고 하고, SHA256을 연달아서 두 번 수행하는 것은 Hash256이라고 합니다. 이름에서 알 수 있다시피, Hash160은 결과값이 160bits(20bytes), SHA256은 256bits(32bytes)입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;6. Varint&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Variable + int의 합성어로 variable length로 integer data를 serialization하는 방법을 제시합니다. 최대 수의 범위는 $2^{64} - 1$까지 표현할 수 있기 때문에 매우 유용하며, 불필요한 데이터의 전송을 최소화할 수 있습니다. 내용 자체는 매우 간단합니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;해당 수가 253보다 작다면 1 byte만 이용해서 바로 표현합니다.&lt;/li&gt;
&lt;li&gt;그렇지 않고, 해당 수가 2^16 - 1 보다 작다면, 253(0xfd)를 prefix로 맨 앞에 붙이고, 2 byte를 이용해서 표현합니다.&lt;/li&gt;
&lt;li&gt;그렇지 않고, 해당 수가 2^32 - 1 보다 작다면, 254(0xfe)를 prefix로 맨 앞에 붙이고, 4 byte를 이용해서 표현합니다.&lt;/li&gt;
&lt;li&gt;그렇지 않고, 해당 수가 2^64 - 1 보다 작다면, 255(0xff)를 prefix로 맨 앞에 붙이고, 8 byte를 이용해서 표현합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 0으로 앞에 남는 byte를 보내는 양을 효과적으로 줄일 수 있기 때문에, 변수 상태의 integer를 전송할 때 많이 사용됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 Bitcoin에서 Serialization를 수행하는 경우를 구체적으로 살펴보겠습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1. Public Key&amp;nbsp;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본적으로 Public key는 모두에게 공개되어야 하는 정보 중에 하나입니다. 따라서, 이를 효율적으로 분배하는 문제 역시 중요하다고 할 수 있습니다. Bitcoin에서는 앞 서 살펴보았던, SEC, Base58를 이용하며, 필요에 따라서&amp;nbsp;hash160을 이용해서 내용을 감추기도 합니다.&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;일반적으로, SEC와 Base58을 이용하여, 데이터를 전송하는 이유는 후에 Public Key 역시 사람들에게 쉽게 노출이 되는데, 이를 쉽게 사람들이 알아볼 수 있게 하기 위함이며, hash160을 사용하는 이유는 Public Key를 감추기 위해서 입니다. 이 말이 이상하게 들릴 수 있는데, Public key가 Open 되고 바로 사용된다면, 문제가 되지 않지만, Public Key가 공개되고 오랜 시간이 지난다면, 문제가 발생할 가능성이 생기기 때문입니다. (너무나 오랫동안 노출된다면, private key가 결국은 해독될 수도 있습니다.) 이는 바로 다음 chapter에서 더 알아볼 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2. Signature&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Signature 방식 같은 경우는 표준처럼 넓게 사용되는 DER을 사용합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;3. Private Key&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Private key를 전송한다는 것은 굉장한 위험을 초래할 수 있습니다. 하지만, 그럼에도 불구하고, 이를 전송해야할 경우가 있습니다. usb에 저장하고 싶다거나 별도의 software로 옮기고 싶은 경우도 존재합니다. 따라서, 이를 위한 Serialization Format도 존재합니다. 우리는 이를 WIF(Wallet Import Format)이라고 부릅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이는 이름에서부터 느껴지듯이 Bitcoin에서 파생된 standard라고 볼 수 있습니다. 또한, 이는 Base58로 encoding된다는 점 정도만 기억하면 충분합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한, 위에서는 다루지 않았지만, Bitcoin network는 개발용(testnet)과 실제 서비스용(mainnet)을 가지고 있기 때문에, 이를 구분하는 구분자를 각 serialization 앞에 표시하는 것을 원칙으로 합니다.&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;mainnet = 0x80&lt;/li&gt;
&lt;li&gt;testnet = 0xef&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;4. Number of data&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;bitcoin 상에서도 여러 개의 데이터를 전송해야 하는 경우가 많습니다. 그런데, 만약 해당 데이터의 갯수가 정해져있는 것이 아니라 때에 따라서 변경되는 경우에는 위에서 제시한 Varint를 사용할 수 밖에 없습니다. 이는 바로 다음 Chapter에서 알아볼 Transaction 내부에서 많이 사용되는 것을 알 수 있습니다.&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;이전 글과 동일하게 구현 사항은 github에 정의해두었습니다.&lt;/p&gt;
&lt;figure id=&quot;og_1647581395904&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - euidong/bitcoin: BitCoin Implementation&quot; data-og-description=&quot;BitCoin Implementation. Contribute to euidong/bitcoin development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/euidong/bitcoin&quot; data-og-url=&quot;https://github.com/euidong/bitcoin&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/pB08T/hyNJbsXzSm/UsjVwNA2KganLIhBxSgj60/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/euidong/bitcoin&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/euidong/bitcoin&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/pB08T/hyNJbsXzSm/UsjVwNA2KganLIhBxSgj60/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;GitHub - euidong/bitcoin: BitCoin Implementation&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;BitCoin Implementation. Contribute to euidong/bitcoin development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>BlockChain</category>
      <category>Base58</category>
      <category>Bitcoin</category>
      <category>der</category>
      <category>SEC</category>
      <category>serialization</category>
      <category>WIF</category>
      <author>euidong</author>
      <guid isPermaLink="true">https://justlog.tistory.com/32</guid>
      <comments>https://justlog.tistory.com/32#entry32comment</comments>
      <pubDate>Fri, 18 Mar 2022 14:51:25 +0900</pubDate>
    </item>
    <item>
      <title>Bitcoin (1) -  ECDSA를 이용한 서명</title>
      <link>https://justlog.tistory.com/31</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;icons8-team-Ph5_4TnXXYE-unsplash.jpg&quot; data-origin-width=&quot;6016&quot; data-origin-height=&quot;4016&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/djdlOd/btrwIpOWU1J/HivYBdAQW1eWGzitwAcptK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/djdlOd/btrwIpOWU1J/HivYBdAQW1eWGzitwAcptK/img.jpg&quot; data-alt=&quot;Photo by Icons8 Team on Unsplash&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/djdlOd/btrwIpOWU1J/HivYBdAQW1eWGzitwAcptK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdjdlOd%2FbtrwIpOWU1J%2FHivYBdAQW1eWGzitwAcptK%2Fimg.jpg&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;6016&quot; height=&quot;4016&quot; data-filename=&quot;icons8-team-Ph5_4TnXXYE-unsplash.jpg&quot; data-origin-width=&quot;6016&quot; data-origin-height=&quot;4016&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Photo by Icons8 Team on Unsplash&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Blockchain을 공부하게 되었는데, 이번 기회에 제대로 하자는 생각에서 Bitcoin 구현을 직접 수행해볼 생각입니다. 학습에 사용한 책은 아래에 나와있는 책을 활용하였습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Reference&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;- Programming Bitcoin&lt;/span&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1647353190722&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;Programming Bitcoin&quot; data-og-description=&quot;Dive into Bitcoin technology with this hands-on guide from one of the leading teachers on Bitcoin and Bitcoin programming. Author Jimmy Song shows Python programmers and developers how to program &amp;hellip; - Selection from Programming Bitcoin [Book]&quot; data-og-host=&quot;www.oreilly.com&quot; data-og-source-url=&quot;https://learning.oreilly.com/library/view/programming-bitcoin/9781492031482/&quot; data-og-url=&quot;https://www.oreilly.com/library/view/programming-bitcoin/9781492031482/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/xOrcP/hyNI1aTWN7/tjHLDnkjcHRpkE52yh4bHk/img.jpg?width=140&amp;amp;height=184&amp;amp;face=0_0_140_184&quot;&gt;&lt;a href=&quot;https://learning.oreilly.com/library/view/programming-bitcoin/9781492031482/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://learning.oreilly.com/library/view/programming-bitcoin/9781492031482/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/xOrcP/hyNI1aTWN7/tjHLDnkjcHRpkE52yh4bHk/img.jpg?width=140&amp;amp;height=184&amp;amp;face=0_0_140_184');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Programming Bitcoin&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Dive into Bitcoin technology with this hands-on guide from one of the leading teachers on Bitcoin and Bitcoin programming. Author Jimmy Song shows Python programmers and developers how to program &amp;hellip; - Selection from Programming Bitcoin [Book]&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.oreilly.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;해당 Posting은 Bitcoin이 무엇이고, 이것으로 무엇을 할 수 있는지에 대해서 설명하지 않고 Bitcoin을 구현하는 기술에 대하여 다룹니다.&lt;/b&gt; 또한, 책의 모든 내용을 충실히 번역하는 것이 아닌 작성자의 생각이 많이 담겨 있으니 유의 바랍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;해당 chapter에서는 데이터의 인증을 어떻게 수행할 것인가에 대한 세부적인 내용을 다루겠습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;(+) 들어가기에 앞 서...&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Bitcoin에서는 결제가 발생할 때, 이전 거래에서 얻은 Bitcoin을 통해서만 결제가 가능합니다. (거래를 통해 Bitcoin을 받은 적이 없다면, Bitcoin이 없는 것으로 간주합니다.)&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한, 우리는 이 거래 내역을 모두가 볼 수 있도록 공개합니다. 이 상황에서 우리가 특정 거래 내역에서 돈을 받은 사람이 자신이고, 그 거래에서 얻은 Bitcoin을 현재 거래에 사용할 것임을 증명하기 위해서는 어떻게 해야할까요?&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반적으로 인증이라는 것은 누군가가 특정 사실을 증명하는 것을 말합니다. 여기서는, 데이터의 작성자가 진짜 작성자가 맞는지를 확인하는 것입니다. 이는 대게 믿을 만한 제3 자에게 맡기거나 직접 눈으로 확인하는 방식이 있습니다. 하지만, 매번 이를 수행하는 것은 어렵기 때문에 우리는 원본 데이터에 &lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; letter-spacing: 0px;&quot;&gt;서명을 하는 것을 택합니다. 이를 통해서, 자신이 해당 데이터의 작성자임을 분명하게 표시할 수 있습니다. 그런데, 이것을 programming 적으로 구현하는 것은 쉬운 일이 아닙니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; letter-spacing: 0px;&quot;&gt;대게 이를 위해서 우리는 공개키 방식이라는 것을 사용합니다.&lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; letter-spacing: 0px;&quot;&gt; 공개키 방식이란, 암호화하는 도구와 해독하는 도구가 서로 다른 경우를 말합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; letter-spacing: 0px;&quot;&gt;즉, 해독하는 도구는 누구나에게나 제공을 하고, 암호화하는 도구는 자신만이 가지고 있도록 하여, 원본 데이터와 원본 데이터를 암호화한 데이터를 같이 보내면, 이를 받은 사용자들이 해독하는 도구를 통해 암호화한 데이터를 복구하고, 원본데이터와 대조해보면, 원본데이터의 작성자가 전송자임을 명확하게 확신할 수 있는 것입니다. 즉, 원본데이터를 암호화한 데이터가 바로 하나의 서명이 되는 것입니다. 왜냐하면, 이를 암호화하는 키는 전송한 사람만 갖고 있기 때문입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; letter-spacing: 0px;&quot;&gt;&lt;b&gt;programming적으로 이러한 공개키 방식을 구현하는 것은 one way function (한 방향 함수, 암호화는 쉽지만 inversion이 어려운 함수, 암호화 도구)이면서, trap door(속임수, 해독하는 도구)를 가지는 algorithm을 찾아내는 것입니다.&lt;/b&gt; 즉, key를 갖고 있으면 쉽게 암호를 생성할 수 있지만, key가 없다면, 이를 만드는 것이 사실상 불가능하도록 만드는 것입니다. 여기에서 일반적으로 가장 많이 사용되는 것이 RSA라는 소인수 분해의 난해함을 이용하는 algorithm이 있습니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; letter-spacing: 0px;&quot;&gt;하지만, &lt;/span&gt;Bitcoin에서는 서명을 하기 위해서, ECDSA(Elliptic Curve Digital Signature Algorithm)를 사용합니다. 따라서, 여기서는 이 기술에 대해서 자세히 알아볼 것입니다.&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;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;유한 공간 Finite Field&lt;/li&gt;
&lt;li&gt;타원 곡선 Elliptic Curve&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서, 이에 대한 내용을 이제부터 하나하나씩 살펴보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1. 유한 공간 Finite Field&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;들어가기에 앞 서 두 가지 개념을 정리하고 가야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저, 소수입니다. &lt;b&gt;소수(Prime Number)&lt;/b&gt;는 1과 자신 이외의 자연수로 나눌 수 없는, 1보다 큰 자연수입니다. 또한, 해당 숫자들은 규칙성을 갖고 있지 않기 때문에, 하나의 소수가 주어진 뒤에 이보다 큰 바로 다음 소수를 찾는 것은 직접 해보지 않으면 알 수 없습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음은 &lt;b&gt;modulo(나머지 연산자, %)입니다.&lt;/b&gt; 특정 값을 나누고, 남은 나머지를 반환하는 연산자라고 말할 수 있습니다.&lt;br /&gt;$$10 \% 3 = 1, 10 \% 2 = 0$$&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 연산은 일반적인 대수학의 연산과는 다르게 동작하게 하기 때문에, 이에 대하여, 앞으로 사용할 특징 몇 가지를 정리해보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;$ a \% b \lt b $&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; letter-spacing: 0px;&quot;&gt;$ (a * b) \% c = \{(a \% c) * (b \% c)\} \% c $&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;$ a^{b} \% (b-1) = 1 $&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 3가지 특징에 대한 자세한 증명은 여기서 다루기보다, 궁금하시다면, 직접 찾아보시길 바랍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 통해서 Finite Field에서의 연산을 표현할 수 있으니 이를 기억해둡시다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Finite Field&lt;/b&gt;란 특정 소수보다 작은, 0을 포함한 자연수 집합으로, 이루어지고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$$ F_3 = \{ 0, 1, 2 \} $$&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$$ F_{11} = \{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 \} $$&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 6가지 조건을 만족하는 집합을 의미합니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;Additive closed, 덧셈에 대하여 닫혀있다.&lt;/li&gt;
&lt;li&gt;Multiplicative closed, 곱셈에 대하여 닫혀있다.&lt;/li&gt;
&lt;li&gt;Additive identity, 덧셈에 대한 항등원($0$) 을 갖는다.&lt;/li&gt;
&lt;li&gt;Multicative identity, 곱셈에 대한 항등원($1$) 을 갖는다.&lt;/li&gt;
&lt;li&gt;Additive inverse, 덧셈에 대한 역원($-a$)을 갖는다.&lt;/li&gt;
&lt;li&gt;Multicative inverse, 곱셈에 대한 역원($a^{-1}$)을 갖는다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 조건을 살펴보기에 앞서서 Finite Field를 정의하는 소수보다 큰 값은 해당 소수를 통해서 modulo 연산되어, Finite Field에 속하게 됩니다. (이는 modulo 연산의 첫 번째 특징($a \% b \lt b $)을 통해 알 수 있습니다.) 마치 시계와 같이 순환하는 구조를 가진다고 생각할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 통해서, Finite Field의 첫 번째와 두 번째 조건은 만족한다는 것을 알 수 있습니다. 왜냐하면, 덧셈과 곱셈으로 생성된 결괏값은 반드시 다시 Finite Field에 속하게 되기 때문입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;세 번째, 네 번째 조건은 소수는 항상 2보다 크기 때문에, 0과 1을 포함할 수밖에 없음을 알 수 있습니다. 따라서, Finite Field는 덧셈과 곱셈에 대한 항등원을 가진다는 것을 확인할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다섯 번째는 다음과 같습니다.&lt;br /&gt;$F_{p} = \{0,1,2,3,..., p - 2, p - 1\}$이고, $ a \in F_{p} $인 경우&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$$ -a = p - a $$&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;라고 정의할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여섯 번째는 다음과 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$F_{p} = \{0,1,2,3,..., p - 2, p - 1\}$ 이고, $ a \in F_{p} $인 경우&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$$ a^{-1} = a^{-1} * 1 = a^{-1} * a^{p-1} $$&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$$ a^{-1} = a^{p - 2} $$&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;modulo의 세 번째 특징을 활용하여 다음과 같이 정의할 수 있습니다.&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;이러한 modulo 연산을 활용하는 Finite Field의 특징은 다음과 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에서 보았듯이 덧셈과 곱셈 연산은 역원이 존재하여, 결괏값을 갖고 역으로 원래 값을 찾아내는 것이 가능합니다. 하지만, 이 공간에 역이 없는 연산자를 추가한다면 어떻게 될까요? 이를 기억하고 넘어갑시다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2. 타원 곡선 Elliptic Curve&lt;/b&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;$$ y^2 = x^3 + ax + b$$&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;ecc.jpeg&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;1032&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/GtbVH/btrv8ESuSXl/cukR1mcU2wKisgNtlRKLq0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/GtbVH/btrv8ESuSXl/cukR1mcU2wKisgNtlRKLq0/img.jpg&quot; data-alt=&quot;Elliptic Curve&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/GtbVH/btrv8ESuSXl/cukR1mcU2wKisgNtlRKLq0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGtbVH%2Fbtrv8ESuSXl%2FcukR1mcU2wKisgNtlRKLq0%2Fimg.jpg&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;305&quot; height=&quot;315&quot; data-filename=&quot;ecc.jpeg&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;1032&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Elliptic Curve&lt;/figcaption&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;바로, 각 타원 곡선과 3개의 점을 가지는 선을 그었을 때, 항상 다음 식을 만족한다는 것입니다. (R은 타원곡선과 만나는 세 번째 점을 X축 대칭이동한 점을 말합니다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$$ P + Q = R $$&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;3point.jpeg&quot; data-origin-width=&quot;999&quot; data-origin-height=&quot;1049&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kwZyK/btrv6X56VgJ/qlbULIKAPBQantJxp7yty1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kwZyK/btrv6X56VgJ/qlbULIKAPBQantJxp7yty1/img.jpg&quot; data-alt=&quot;Elliptic Curve Addition - 1&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kwZyK/btrv6X56VgJ/qlbULIKAPBQantJxp7yty1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkwZyK%2Fbtrv6X56VgJ%2FqlbULIKAPBQantJxp7yty1%2Fimg.jpg&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;272&quot; height=&quot;286&quot; data-filename=&quot;3point.jpeg&quot; data-origin-width=&quot;999&quot; data-origin-height=&quot;1049&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Elliptic Curve Addition - 1&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$P(x_1, x_2)$, $Q(x_2, y_2)$가 타원 곡선 $y^2=x^3 + ax + b$ 위의 점이라고 할 때, $R(x_3, y_3)$의 좌표는 다음과 같이 표현할 수 있습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;$ s = {dx \over dy} = { 3x^2 \over&amp;nbsp; 2y } = { {y_2 - y_1} \over&amp;nbsp; {x_2 - x_1}} $&lt;/li&gt;
&lt;li&gt;$ x_3 = s^2 - x_1 -x_2 $&lt;/li&gt;
&lt;li&gt;$ y_3 = s(x_1 - x_3) - y_1 $&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 연산 역시 다음과 같은 조건을 만족시킵니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Identity, 항등원이 존재한다. =&amp;gt; $ A + I = A $&lt;/li&gt;
&lt;li&gt;Invertibility, 역원이 존재한다. =&amp;gt; $ A = (a_1, a_2)이면, -A= (a_1, -a_2) $&lt;/li&gt;
&lt;li&gt;Commutativity, 교환 법칙 =&amp;gt; $ A + B = B + A $&lt;/li&gt;
&lt;li&gt;Associativity, 결합 법칙 =&amp;gt; $ A + (B + C) = (A + B) + C $&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서의 역원은 x축 대칭 이동을 통해 얻은 값이라는 것을 확인할 수 있습니다. 또한, 교점이 세 개인 시점에서 직선의 기울기를 무한대로 계속 올리다 보면 결국은 y축에 대칭인 형태로 직선이 만들어지는 것을 볼 수 있습니다. (아래 그림에서 두 번째) 이 경우에 우리는 실제로는 교점이 두 개지만, 무한대 지점에서 교점이 하나 더 있다고 말하고 이를 I(Infinity)라고 정의합니다. 그렇게 되면, 항등원이 바로 I가 되는 것을 확인할 수 있습니다. (두 번째 그림에서 $P + I = P$가 되는 것을 확인할 수 있습니다.) 이를 통해서 두 번째에 존재하는 역원까지도 증명이 가능합니다.($P + (-P) = I$)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nrMwe/btrv3fz9tyq/SGuKT2GxTcrlEJ7afqMmtk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nrMwe/btrv3fz9tyq/SGuKT2GxTcrlEJ7afqMmtk/img.png&quot; data-is-animation=&quot;undefined&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;1139&quot; data-filename=&quot;blob&quot; data-widthpercent=&quot;46.63&quot; style=&quot;width: 46.0844%; margin-right: 10px;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nrMwe/btrv3fz9tyq/SGuKT2GxTcrlEJ7afqMmtk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnrMwe%2Fbtrv3fz9tyq%2FSGuKT2GxTcrlEJ7afqMmtk%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;1000&quot; height=&quot;1139&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Vc8np/btrv4Kfim03/gym09cDklXz6RPwL3uqHQ0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Vc8np/btrv4Kfim03/gym09cDklXz6RPwL3uqHQ0/img.jpg&quot; data-is-animation=&quot;undefined&quot; data-origin-width=&quot;1004&quot; data-origin-height=&quot;999&quot; data-filename=&quot;1point.jpeg&quot; data-widthpercent=&quot;53.37&quot; style=&quot;width: 52.7528%;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Vc8np/btrv4Kfim03/gym09cDklXz6RPwL3uqHQ0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FVc8np%2Fbtrv4Kfim03%2Fgym09cDklXz6RPwL3uqHQ0%2Fimg.jpg&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;1004&quot; height=&quot;999&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;Elliptic Curve Addition - 2&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;세 번째는 너무나 자명하기 때문에 넘어가고, 네 번째는 아래 그림을 통해서 설명할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주황색 : $ (P + Q) + S = R_1 + S = T $&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;초록색 : $ (P + S) + Q = R_2 + Q = T $&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;ecc_associativity.jpeg&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;1022&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bmDCt3/btrv6dg1mB2/8CZsFFaX1QzWH5ehKBd7F1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bmDCt3/btrv6dg1mB2/8CZsFFaX1QzWH5ehKBd7F1/img.jpg&quot; data-alt=&quot;Eliptic Curve Addition - 3&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bmDCt3/btrv6dg1mB2/8CZsFFaX1QzWH5ehKBd7F1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbmDCt3%2Fbtrv6dg1mB2%2F8CZsFFaX1QzWH5ehKBd7F1%2Fimg.jpg&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;358&quot; data-filename=&quot;ecc_associativity.jpeg&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;1022&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Eliptic Curve Addition - 3&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추가적으로 살펴볼 수 있는 하나의 연산을 하나 더 알아보고 갑시다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;바로 접선에서 연산입니다. 이 경우는 P와 Q가 같다고 여깁니다. 즉, 자기 자신을 두 번 더 하는 것과 같습니다. 따라서, 우리는 이를 $ P + P = R = 2P $라고 표현합니다. 또한, 이를 반복하면서, 결과 값을 도출할 수 있습니다. 따라서, 우리는 다음과 같은 식도 작성이 가능합니다. (이를 우리는 Elliptic Curve에서의&amp;nbsp;&lt;b&gt;Scalar Multiplication&lt;/b&gt;이라고 합니다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$$ kP = R $$&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 계산하기 위해서는, 일반적으로 k 번의 Elliptic Curve Addition을 수행하게 됩니다. 하지만, 이를 더 간략화할 수 있는 방법이 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$$ R = 63P = (1 + 2 + 4 + 8 + 16 + 32) P = (1 + (1+1) + (2+2) + (4+4) + (8+8) + (16+16)) P $$&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 이전 계산의 결과를 현재 계산에 활용하여 계산을 더 빠르게 할 수 있습니다. 위 예시에서는 62(63 - 1) 번의 더하기 연산을 10번으로 줄인 것을 볼 수 있습니다. (물론 이외에도 많은 방식으로 최적화를 할 수 있지만, 이 정도면 대게 충분합니다.)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;2point-1.jpeg&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;1027&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/clgs3z/btrv4ltkRrw/IflyRrvyCDfJLZ7rofIbxk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/clgs3z/btrv4ltkRrw/IflyRrvyCDfJLZ7rofIbxk/img.jpg&quot; data-alt=&quot;Elliptic Curve Addition - 4&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/clgs3z/btrv4ltkRrw/IflyRrvyCDfJLZ7rofIbxk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fclgs3z%2Fbtrv4ltkRrw%2FIflyRrvyCDfJLZ7rofIbxk%2Fimg.jpg&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;317&quot; height=&quot;326&quot; data-filename=&quot;2point-1.jpeg&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;1027&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Elliptic Curve Addition - 4&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 주목할 포인트를 하나 짚어보고 가야합니다. 우리가 $R$과, $P$를 알고 있을 때, $k$ 구하는 것이 가능할까요?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이는 쉽지 않은 문제가 됩니다. 왜냐하면, 이러한 scalar multiplcation문제에서는 역원이 존재하지 않기 때문에, k에 값을 1부터 대입해보면서 확인해 볼 수밖에 없습니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 기본이 되는 두 이론을 세팅하였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단은 유의해야 할 점은 바로 Finite Field로 Elliptic Curve를 가져오게 되면, 이는 discrete(불연속) 해진다는 점입니다. 또한, Scalar Multiplication에도 변화가 발생합니다. &lt;b&gt;바로 순환이라는 것이 생긴다는 점입니다.&lt;/b&gt; $nP = R = 0$ 이 되는 $n$값이 존재하게 된다는 것입니다. 또한, 역원이 없는 성질 또한 유지되기 때문에, $kP$를 통해서 생성된 값($R$)과 P를 모두 공개하더라도, $k$가 밝혀질 가능성은 $n$값이 커질수록 불가능에 가깝다는 것입니다.&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;실제로 Bitcoin에서는 이 N을 매우 크게 설정하였기 때문에 문제가 없다고 할 수 있습니다. 한 번 Bitcoin에서, Finite Field 상의 Elliptic Curve의 모든 변수를 정리해봅시다.&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;기본적으로, 해당 암호화에 사용되는 모든 값의 단위는 256 bits 즉, 32 bytes를 사용합니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Elliptic Curve의 형태 : $a=0$, $b=7$을 사용하는 secp256k 1을 사용합니다. 이 형태는 다음과 같습니다. $$y^2 = x^3 + 7$$&lt;/li&gt;
&lt;li&gt;Finite Field의 소수 : 위에서 말한 대로 $n$의 값을 크게 하기 위해서 finite field 자체의 크기도 매우 커져야 하기 때문에, $p$ 역시 매우 큽니다. $$p = 2^{256} - 2^{32} - 977 $$&lt;/li&gt;
&lt;li&gt;Scalar Multiplication에 사용되는 Elliptic Curve 위의 한 점($G$) : 이 또한 매우 크기 때문에 각 좌표별로 따로 적겠습니다. $G_x = $ &lt;span data-annotation-id=&quot;be0f11be-9a7e-4786-b81e-ca571220ed81&quot;&gt;0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798&lt;br /&gt;&lt;/span&gt;&lt;span data-annotation-id=&quot;be0f11be-9a7e-4786-b81e-ca571220ed81&quot;&gt;$G_y = $ 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8&lt;/span&gt;&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;span data-annotation-id=&quot;be0f11be-9a7e-4786-b81e-ca571220ed81&quot;&gt;Scalar Mutiplication에 의해서 만들어지는 $k$의 범위 ($n$)&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;: 위에서도 보았겠지만, 0x는 16진수를 의미합니다.&lt;/span&gt;&lt;br /&gt;$n = $ 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141&lt;br /&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span data-annotation-id=&quot;be0f11be-9a7e-4786-b81e-ca571220ed81&quot;&gt;위의 데이터를 보다시피 매우 큰 범위의 값을 사용하는 것을 알 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span data-annotation-id=&quot;be0f11be-9a7e-4786-b81e-ca571220ed81&quot;&gt;여기서 한 번 우리가 암호화 키와 해독 키(공개키)를 각 각 만들어보도록 하겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span data-annotation-id=&quot;be0f11be-9a7e-4786-b81e-ca571220ed81&quot;&gt;먼저, 암호화 키($e$)를 만드는 것은 매우 쉽습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span data-annotation-id=&quot;be0f11be-9a7e-4786-b81e-ca571220ed81&quot;&gt;바로 $n$보다 작은 임의의 수를 고르면 됩니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span data-annotation-id=&quot;be0f11be-9a7e-4786-b81e-ca571220ed81&quot;&gt;그리고, 이를 이용해서, 우리는 바로 해독 키인 공개키를($P$) 만들 수 있습니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span data-annotation-id=&quot;be0f11be-9a7e-4786-b81e-ca571220ed81&quot;&gt;$$ P = eG $$&lt;/span&gt;&lt;span data-annotation-id=&quot;be0f11be-9a7e-4786-b81e-ca571220ed81&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 하면 끝입니다. 우리는 $e$를 모르기 때문에, $P$와 $G$가 모두가 아는 값이라고 할지라도 $e$를 알아낼 수 없습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇기에 우리는 안심하고, P를 공개할 수 있는 것입니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span data-annotation-id=&quot;be0f11be-9a7e-4786-b81e-ca571220ed81&quot;&gt;이제 우리는 이것을 이용해서 한 번 서명을 통한 인증을 수행해보도록 하겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span data-annotation-id=&quot;be0f11be-9a7e-4786-b81e-ca571220ed81&quot;&gt;먼저, 우리가 보내고자 하는 데이터를 $m$이라고 하겠습니다. 하지만, 이를 바로 사용하는 것은 쉽지 않습니다. 왜냐하면, 보내고자 하는 데이터의 크기가 32 bytes를 항상 만족하지 않기 때문입니다. 그렇다면, 이를 32 bytes로 변환해줄 방법이 필요할 것입니다. 그래서, 우리는 hashing을 수행합니다. 또한, 원본데이터 자체를 알아볼 수 없게 바꿔버리는 역할도 해서 암호화의 역할도 할 수 있습니다. 이를 통해서 만들어진 데이터를 우리는 $z$라고 하겠습니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 여기서, 우리는 비밀키가 아닌 또 하나의 값을 하나 생성해야 합니다. 바로 $k$입니다. 이는 비밀키와 마찬가지로 $n$보다 작은 32bytes로 지정해야 합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$$ kG = R $$&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;을 전송자 측에서 계산을 하고, $R$의 $x$ 좌표를 $r$이라고 정의하면 거의 모든 설정은 끝났다고 할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 진짜로 서명을 시작할 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;바로&lt;span&gt; &lt;/span&gt;&lt;/span&gt;$ uG + vP = kP = R $라고 할 때,&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$$ u + ve = k $$&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$$ u = z / s $$&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$$ v = r / s $$&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가 되도록 하는 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 되면, $u$라는 값은 $z$를 가지므로, 원본 데이터를 포함한다고 할 수 있습니다. 또한, $v$는 $r$을 포함하기 때문에 결과 값 자체를 포함하고 있다고 볼 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이는 해당 방정식을 풀어서 보면, $$ s = ( z + re ) / k $$라는 것을 알 수 있습니다. 여기서 $e$와 $k$라는 감춰져야만 하는 값이 두 개 포함되는 것을 알 수 있습니다. 해당 방정식은 안전하게도 $e$, $k$가 모두 변수로 남기 때문에 $s$, $z$, $r$을 안다고 해도 $e$와 $k$를 구할 수는 없습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서, $s$와 $r$을 하나로 합쳐서 하나의 서명(Signature)을 이루게 됩니다.&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;따라서, 전송자는 $z$(보낼 데이터)와 $r$, $s$(서명)를 전송함으로써, 데이터의 수신자가 직접 서명의 적절함을 확인할 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span data-annotation-id=&quot;be0f11be-9a7e-4786-b81e-ca571220ed81&quot;&gt;수신자는 이제 받은 데이터를 통해서 다음 과정을 진행한다고 볼 수 있습니다.&lt;/span&gt;&lt;span data-annotation-id=&quot;be0f11be-9a7e-4786-b81e-ca571220ed81&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt; $u$와 $v$를 생성합니다. ($u = z / s $, $v = r / s$)&lt;/li&gt;
&lt;li&gt;$uG + vP$의 연산을 수행합니다.&lt;/li&gt;
&lt;li&gt;위의 결괏값을 통해서 얻은 좌표값의 x 좌표와 r 값을 비교하여 동일한지를 확인합니다.&lt;br /&gt;$$ uG + vP = R $$&lt;/li&gt;
&lt;li&gt;이것이 동일하다면, 해당 데이터는 인증된 데이터입니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이것이 BitCoin에서 사용하는 서명 방식인 ECDSA입니다. 이에 대한 구현은 github에 올려 두었으니, 확인을 원하시면 체크해보시길 바랍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1647424658989&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - euidong/bitcoin: BitCoin Implementation&quot; data-og-description=&quot;BitCoin Implementation. Contribute to euidong/bitcoin development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/euidong/bitcoin&quot; data-og-url=&quot;https://github.com/euidong/bitcoin&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/ikUeQ/hyNH0LTEcM/5cAsKW7lkur0kMdEbXgAS0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/euidong/bitcoin&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/euidong/bitcoin&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/ikUeQ/hyNH0LTEcM/5cAsKW7lkur0kMdEbXgAS0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;GitHub - euidong/bitcoin: BitCoin Implementation&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;BitCoin Implementation. Contribute to euidong/bitcoin development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>BlockChain</category>
      <category>Bitcoin</category>
      <category>blockchain</category>
      <category>ECC</category>
      <category>ecdsa</category>
      <author>euidong</author>
      <guid isPermaLink="true">https://justlog.tistory.com/31</guid>
      <comments>https://justlog.tistory.com/31#entry31comment</comments>
      <pubDate>Wed, 16 Mar 2022 18:15:34 +0900</pubDate>
    </item>
    <item>
      <title>Object Oriented System's Design Patterns [4 - Behavioral Pattern]</title>
      <link>https://justlog.tistory.com/30</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;Reference&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Design Patterns: Elements of reusable object oriented software.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Refactoring GURU :&amp;nbsp;&lt;a href=&quot;https://refactoring.guru/design-patterns/structural-patterns&quot;&gt;https://refactoring.guru/design-patterns/structural-patterns&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;Behavioral Pattern&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Algorithm과 object 간의 책임 분배에 관한 pattern입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; 즉, object의 사용 목적에 따라서 method를 정의할 때, 많이 사용되는 구현 pattern을 의미합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;1.  Chain of Responsibility(CoR)&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;chainOfResponsibility_pattern.jpeg&quot; data-origin-width=&quot;999&quot; data-origin-height=&quot;1155&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/RTZGp/btrvEGjx1c2/6hxU34XT8GDmpUhsIgaA2k/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/RTZGp/btrvEGjx1c2/6hxU34XT8GDmpUhsIgaA2k/img.jpg&quot; data-alt=&quot;Chain of Resposibility Pattern&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/RTZGp/btrvEGjx1c2/6hxU34XT8GDmpUhsIgaA2k/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FRTZGp%2FbtrvEGjx1c2%2F6hxU34XT8GDmpUhsIgaA2k%2Fimg.jpg&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;517&quot; height=&quot;598&quot; data-filename=&quot;chainOfResponsibility_pattern.jpeg&quot; data-origin-width=&quot;999&quot; data-origin-height=&quot;1155&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Chain of Resposibility Pattern&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;request를 여러 handler들을 하나의 chain으로 연결한 object에 전달하여 request를 처리하는 방식입니다.&lt;/b&gt; 여기서 각 각의 handler는 스스로 작업을 끝내고 response를 보낼 수도 있고, 이를 다음 handler로 전달할 수도 있으며, 해당 request를 이용해서 side effect를 만들 수도 있다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;이는 대게 request를 처리하는 module을 설계하는 과정에서 많이 사용됩니다. 예를 들어, REST API 를 구현하고자 할 때, 여러 request에서 공통적으로 사용되는 logic을 별도의 middleware라는 것으로 분리하여 구현하고 재활용하는 것을 많이 볼 수 있습니다. (ex. nodeJS express, Go http.Handler, etc...)&amp;nbsp;&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;여기서 CoR의 특징을 살펴보고 갑시다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Request의 처리 순서도 제어할 수 있습니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;각 handler가 하나의 역할만 하도록 하여, 유연성과 가독성을 높일 수 있습니다.(Single Responsibility)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;새로운 handler의 추가가 기존 code의 영향을 주지 않습니다. (Open/Close)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #f3c000; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;2. Command&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;command_pattern.jpeg&quot; data-origin-width=&quot;1143&quot; data-origin-height=&quot;1000&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cBz6yE/btrvAae7pxG/qmNUZ3fryvWamfKkFTz0vK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cBz6yE/btrvAae7pxG/qmNUZ3fryvWamfKkFTz0vK/img.jpg&quot; data-alt=&quot;Command Pattern&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cBz6yE/btrvAae7pxG/qmNUZ3fryvWamfKkFTz0vK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcBz6yE%2FbtrvAae7pxG%2FqmNUZ3fryvWamfKkFTz0vK%2Fimg.jpg&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;575&quot; height=&quot;503&quot; data-filename=&quot;command_pattern.jpeg&quot; data-origin-width=&quot;1143&quot; data-origin-height=&quot;1000&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Command Pattern&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;모든 request를 하나의 queue에 저장하고, 처리자는 queue의 순서에 따라서, request를 처리하는 pattern입니다.&lt;/b&gt; 이러한 방식은 request를 마치 하나의 method paratemer로 받아들이도록 하고, request의 실행을 queue로 관리함으로써, 쉽게 되돌리기 기능도 지원하도록 할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;쉽게 예를 들면, 식당에서 웨이터는 주문을 받아서, 영수증을 순서에 따라서 order board에 붙이면, 주방장은 이를 보고, 순서에 따라서 요리를 내보내는 형식이라고 보면 되겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;구현 시에는 Command라는 Interface를 구현하는 각각의 Command class를 작성합니다. 여기서 각 Command는 생성 시에 receiver를 전달받아서, 호출 시에 이를 Receiver에게 전달할 수 있도록 합니다. 그리고, Command Interface를 호출하는 Invoker를 선언해줍니다.&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Command의 특징은 다음과 같습니다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Command 단위로 class를 구분할 수 있기 때문에 유연성이 높아집니다. (Single Responsibility)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;새로운 Command의 추가가 기존 code에 영향을 주지 않습니다. (Open/Close)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;되돌리기와 다시 재생 등의 동작의 구현이 쉽습니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;3. Iterator&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;iterator_pattern.jpeg&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;1124&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/l4bB2/btrvyhSaAKS/gCUVYjrOAcC5HctJs5PlTk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/l4bB2/btrvyhSaAKS/gCUVYjrOAcC5HctJs5PlTk/img.jpg&quot; data-alt=&quot;Iterator Pattern&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/l4bB2/btrvyhSaAKS/gCUVYjrOAcC5HctJs5PlTk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fl4bB2%2FbtrvyhSaAKS%2FgCUVYjrOAcC5HctJs5PlTk%2Fimg.jpg&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;488&quot; height=&quot;548&quot; data-filename=&quot;iterator_pattern.jpeg&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;1124&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Iterator Pattern&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;내부의 구현물을 들어내지 않은 상태에서 구성요소를 순환하기 위해 고안된 pattern입니다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;기본적으로는 iterator는 다음과 같은 요소로 이루어집니다.&lt;/span&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;현재 자신의 구성요소를 retuern하는 method&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;다음 iterator를 반환하는 method&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;다음 iterator가 존재하는지를 체크하는 method&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;해당 object를 통해서 전체 구조를 순환할 수 있도록 하는 방식입니다. 주요 예시는 file 입출력을 예를 들 수 있습니다. 대게 while 문을 통해서 더 이상 읽을 문자가 없을 때까지 line 단위로 받아오며, next를 호출하는 식의 구현을 많이 보았을 것입니다. 이를 사용하는 이유는 두 가지로 들 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;object 내의 자세한 구현을 감추기 위해서&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;필요에 따라 여러 iterator를 생성하기 위해서&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;대게 object가 하나 이상의 동일 object를 포함하게 된다면, 이 object를 순환할 수 있는 방법은 여러 가지가 존재하게 됩니다. 예를 들어 tree를 구현했다고 했을 때, 기본적으로 depth first search, breadth first search을 생각할 수 있습니다. 하지만, 상황에 따라서 효율적인 방식이 다르기 때문에, 각기 다른 순환 방식을 지원하는 것이 좋습니다.&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;iterator의 특징을 살펴보고 갑시다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Iterator 각 각에 필요로 하는 algorithm을 구현할 수 있기 때문에 유연한 구조를 가질 수 있습니다. (Single Responsibility)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;새로운 iterator의 추가가 기존 code에 영향을 미치지 않습니다. (Open/Close)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;object로부터 생성된 각 iterator는 서로 독립적으로 동작할 수 있습니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;하지만, 해당 구현은 다루고자 하는 데이터의 양이 적은 경우 지나칠 수도 있고, 직접 접근하는 것보다 속도가 느릴 수 밖에 없습니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;4. Mediator&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;mediator_pattern.jpeg&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;1059&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cQTuvQ/btrvE3S9xt4/BPkpK7SttsZ9AzvPzzwlek/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cQTuvQ/btrvE3S9xt4/BPkpK7SttsZ9AzvPzzwlek/img.jpg&quot; data-alt=&quot;Mediator Pattern&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cQTuvQ/btrvE3S9xt4/BPkpK7SttsZ9AzvPzzwlek/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcQTuvQ%2FbtrvE3S9xt4%2FBPkpK7SttsZ9AzvPzzwlek%2Fimg.jpg&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;468&quot; height=&quot;496&quot; data-filename=&quot;mediator_pattern.jpeg&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;1059&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Mediator Pattern&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;object 간의 혼란스러운 의존성을 줄이기 위해서 고안된 pattern으로, &lt;b&gt;object 간의 직접적인 사용을 제한하고, mediator라는 중계자를 통해서만 동작할 수 있도록 하는 pattern&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;여기서 adapter의 특징을 살펴보고 갑시다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;디양한 object 간의 communication을 추출할 수 있기 때문에, object 본연의 작업에 집중하여 편리하고 유지하기 쉽게 만듭니다. (Single Responsibility)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;새로운 mediator를 추가할 때, 기존 code의 변경이 필요 없습니다. (Open/Close)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;각 Object 간의 의존성을 제거할 수 있습니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;개발이 진행될수록 mediator가 전체 시스템을 관리하는 a God Object가 되고, mediator를 사용하는 모든 object가 이에 의존성이 생기게 됩니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;5. Memento&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;memento_pattern.jpeg&quot; data-origin-width=&quot;1407&quot; data-origin-height=&quot;1000&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bA3vBT/btrvE3FylFu/tLRvUsjTBkSENyutcqxwR1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bA3vBT/btrvE3FylFu/tLRvUsjTBkSENyutcqxwR1/img.jpg&quot; data-alt=&quot;Memento Pattern&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bA3vBT/btrvE3FylFu/tLRvUsjTBkSENyutcqxwR1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbA3vBT%2FbtrvE3FylFu%2FtLRvUsjTBkSENyutcqxwR1%2Fimg.jpg&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;531&quot; height=&quot;377&quot; data-filename=&quot;memento_pattern.jpeg&quot; data-origin-width=&quot;1407&quot; data-origin-height=&quot;1000&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Memento Pattern&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;object의 상태 변경에 이전 상태가 큰 영향을 미치거나 history에 대한 구현이 필요한 경우 구현할 수 있습니다. &lt;b&gt;object의 구체적인 구현에 대한 내용을 제외하고, 이전 상태를 저장하고, 필요에 따라 이를 다시 불러와서 사용하는 pattern&lt;/b&gt;입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;구현을 하기 위해서는, 본래의 object를 그대로 두고, 필요로 하는 private variables를 포함하는 memento를 구현하여 state를 받을 수 있는 method를 포함하게 해서, 이 memento들만 caretaker라는 object에서 list형태의 history로 저장할 수 있도록 합니다.&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt; memento의 특징은 다음과 같습니다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;기존 object의 encapsulation을 유지하면서, 기능을 구현할 수 있습니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;기존 code를 그대로 유지한 채로 caretaker를 통해서, history logic을 작성할 수 있습니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;그러나, memento를 유지하기 위한 추가적인 공간이 필요하며, 오래된 데이터 삭제를 위한 원본을 향한 추적이 필요로 됩니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #f3c000; font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;6. Observer&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;observer_pattern.jpeg&quot; data-origin-width=&quot;1282&quot; data-origin-height=&quot;1000&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cQTfZk/btrvE5wHlFP/uOsXp5t4PHxvRbM9HZYne1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cQTfZk/btrvE5wHlFP/uOsXp5t4PHxvRbM9HZYne1/img.jpg&quot; data-alt=&quot;Observer Pattern&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cQTfZk/btrvE5wHlFP/uOsXp5t4PHxvRbM9HZYne1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcQTfZk%2FbtrvE5wHlFP%2FuOsXp5t4PHxvRbM9HZYne1%2Fimg.jpg&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;678&quot; height=&quot;529&quot; data-filename=&quot;observer_pattern.jpeg&quot; data-origin-width=&quot;1282&quot; data-origin-height=&quot;1000&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Observer Pattern&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;가장 많이 쓰이면서, 중요한 pattern 중에 하나라고 생각합니다.&lt;b&gt; subscription 로직을 정의하고, subscription을 수행한 모든 object에게 특정 event의 발생을 전달하는 방식입니다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;즉, object에서 특정 event가 발생하면, 이를 계속해서 broadcasting 하는 방식입니다. 따라서, 이를 구독하고 있는 각 object가 이에 따른 처리를 수행하는 방식입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;구현을 하기 위해서는, &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;Command Pattern과 굉장히 유사하다고할 수 있습니다. Command Pattern은 Queue에 Command를 차곡차곡 쌓아두고, 이를 사용하기를 원하는 Object가 이를 찾아가는 방식이라면, Observer Pattern은 저장하기보다는 이를 필요로 하는 Object에게 전달하는 방식입니다.&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;여기서 adapter의 특징을 살펴보고 갑시다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;새로운 Subscriber, Publisher가 기존 code에 영향을 미치지 않습니다. (Open/Close)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;실행 중에 object간의 관계를 생성하는 것이 가능합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;그러나, Subscriber 간의 순서를 정의하거나 각 event의 순서를 엄밀히 구현하는 것은 별도의 구현체를 필요로 합니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;7. State&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;state_pattern.jpeg&quot; data-origin-width=&quot;1038&quot; data-origin-height=&quot;1000&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/byW0XJ/btrvAcjEKph/gy9AIbUN9KKRhWDT5YQ5K1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/byW0XJ/btrvAcjEKph/gy9AIbUN9KKRhWDT5YQ5K1/img.jpg&quot; data-alt=&quot;State Pattern&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/byW0XJ/btrvAcjEKph/gy9AIbUN9KKRhWDT5YQ5K1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbyW0XJ%2FbtrvAcjEKph%2Fgy9AIbUN9KKRhWDT5YQ5K1%2Fimg.jpg&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;502&quot; height=&quot;484&quot; data-filename=&quot;state_pattern.jpeg&quot; data-origin-width=&quot;1038&quot; data-origin-height=&quot;1000&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;State Pattern&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;object의 내부 상태가 변화할 때마다 동작을 바꾸도록 하는 pattern입니다.&lt;/b&gt; 마치 object가 이것의 class를 바꾸는 것과 같은 효과를 볼 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;가장 일반적으로 볼 수 있는 예시가 게시글 작성이다. 엄격한 절차를 따르는 글 작성에는 다음 세 가지의 과정을 거치게 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;제출 전&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;제출 완료 (검토 중)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;배포 (업로드 완료)&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;각 단계마다 사용할 수 있는 method와 각 method의 동작이 달라질 수 있습니다. 이를 별도의 class로 나누지 않고, 하나의 class로 만들면서 state를 포함하도록 함으로써, 이를 내부에서 control 할 수 있도록 하는 pattern입니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;구현 시에는 각 State를 별도의 Class로 분리하고, 그 내부에서 변경되는 method를 직접 구현하도록 합니다. 따라서, 실제 state를 포함한 원본 class는 이 state에 정의된 method를 호출하도록 할 수 있습니다.&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;state의 특징을 살펴보고 갑시다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;별도의 state를 class로 분리하기 때문에, 유연한 구조를 만들 수 있습니다. (Single Responsibility)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;새로운 state의 추가가 기존 code에 영향을 주지 않습니다. (Open/Close)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;8. Strategy&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;strategy_pattern.jpeg&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;1093&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/q883l/btrvwKfZcb3/0mpJPWmTPqcR9chKH71mYk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/q883l/btrvwKfZcb3/0mpJPWmTPqcR9chKH71mYk/img.jpg&quot; data-alt=&quot;Strategy Pattern&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/q883l/btrvwKfZcb3/0mpJPWmTPqcR9chKH71mYk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fq883l%2FbtrvwKfZcb3%2F0mpJPWmTPqcR9chKH71mYk%2Fimg.jpg&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;572&quot; height=&quot;625&quot; data-filename=&quot;strategy_pattern.jpeg&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;1093&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Strategy Pattern&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;동일한 method에 대해서 여러 algorithm을 정의하고, 각각을 별도의 class로 나누어 상호 호환이 가능하도록 하는 pattern입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;즉, object의 method 자체를 별도의 interface로 분리하는 방식이라고 이해할 수 있습니다.&amp;nbsp;&lt;/b&gt;앞서 보았던 state는 context(문맥)에 따라서, 상태가 바뀌지만 Strategy Pattern에서는 행위 자체가 바뀐다고 생각하면 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;대게 게임에서 쉽게 예시를 생각할 수 있습니다. player의 skill을 interface화 시키고, 해당 동작에 따른 damage와 mp 변화 등을 각 skill마다 직접 계산하여 player object로 전달할 수 있다고 생각하면 쉽습니다.&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;strategy의 특징을 살펴보고 갑시다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;실행 중의 특정 strategy를 선택하여 실행시키는 것이 가능합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;각 strategy에 대한 자세한 구현을 감출 수 있습니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;대게 상속 형태를 대체하여 사용하는 것이 가능합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;새로운 strategy의 추가가 기존 code에 영향을 미치지 않습니다. (Open/Close)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;9. Template Method&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;templateMethod_pattern.jpeg&quot; data-origin-width=&quot;1284&quot; data-origin-height=&quot;999&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cPOG8x/btrvE5DnPCA/gIAw6HAosz18Y4Ghlj7tT1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cPOG8x/btrvE5DnPCA/gIAw6HAosz18Y4Ghlj7tT1/img.jpg&quot; data-alt=&quot;Template Method Pattern&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cPOG8x/btrvE5DnPCA/gIAw6HAosz18Y4Ghlj7tT1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcPOG8x%2FbtrvE5DnPCA%2FgIAw6HAosz18Y4Ghlj7tT1%2Fimg.jpg&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;542&quot; height=&quot;422&quot; data-filename=&quot;templateMethod_pattern.jpeg&quot; data-origin-width=&quot;1284&quot; data-origin-height=&quot;999&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Template Method Pattern&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;algorithm의 skeleton을 상위 class에 정의하고, 전체적인 구조는 바꾸지 않으면서 각 단계에 대한 구현을 override 하는 pattern입니다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;따라서, 전공과목 과제를 하다 보면 교수님들이 skeleton 코드를 준다고 했을 때, 대게 구조만 있고, 각 함수의 내부가 비어 있는 것을 볼 수 있었던 거 같습니다. 따라서, 해당 class를 inherit 하여 구체적인 구현을 하는 식으로 class를 만들면 됩니다.&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;template method의 특징은 다음과 같습니다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;구현의 내용을 줄이고, 중복되는 코드의 사용을 줄일 수 있습니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;그러나, skeleton에 의한 제한으로 불가피하게 code의 변경이 발생할 수 있습니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;10. Visitor&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;visitor_pattern.jpeg&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;1045&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cvKfAA/btrvGaRKWAI/RNCorCTciFPk0kBBkl3ZYK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cvKfAA/btrvGaRKWAI/RNCorCTciFPk0kBBkl3ZYK/img.jpg&quot; data-alt=&quot;Visitor Pattern&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cvKfAA/btrvGaRKWAI/RNCorCTciFPk0kBBkl3ZYK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcvKfAA%2FbtrvGaRKWAI%2FRNCorCTciFPk0kBBkl3ZYK%2Fimg.jpg&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;522&quot; height=&quot;546&quot; data-filename=&quot;visitor_pattern.jpeg&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;1045&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Visitor Pattern&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;특정 object에 접근하려는 object에 따라 별도의 algorithm을 적용하는 pattern입니다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;즉, 사용하고자 하는 object를 하나의 interface로 추상화하고, 각 object는 이를 사용할 client(visitor)를 허용할 것인지 그리고 어떤 algorithm을 수행할 것인지를 정의해둡니다. 사용할 수 있는 예시는 사용할 수 있는 Element의 종류가 매우 다양하며 계속해서 추가될 가능성이 높을 때 사용할 수 있습니다. 그렇지만, Visitor의 추가는 매우 어렵기 때문에 이에 유의해야 합니다.&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;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;여기서 adapter의 특징을 살펴보고 갑시다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;새로운 algorithm의 추가가 기존 code의 변경없이 가능합니다. (Open/Close)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;동일한 class 내부에서 동일한 동작을 여러 version으로 정의할 수 있어 유연합니다. (Single Responsibility)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;그러나, visitor의 추가는 기존 algorithm의 수정을 불러올 수 있습니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Tech</category>
      <category>Command Pattern</category>
      <category>CoR Pattern</category>
      <category>Design Pattern</category>
      <category>Mediator Pattern</category>
      <category>Memento Pattern</category>
      <category>Observer Pattern</category>
      <category>State Pattern</category>
      <category>Strategy Pattern</category>
      <category>Template Method Pattern</category>
      <category>Visitor Pattern</category>
      <author>euidong</author>
      <guid isPermaLink="true">https://justlog.tistory.com/30</guid>
      <comments>https://justlog.tistory.com/30#entry30comment</comments>
      <pubDate>Thu, 10 Mar 2022 11:22:52 +0900</pubDate>
    </item>
  </channel>
</rss>