<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>BeeImp</title>
    <link>https://beeimp.tistory.com/</link>
    <description>안녕하세요. 꼬마벌깨비 '빔프' 입니다.  
블록체인, 데이터 사이언스, 앱, 웹, 보안 등 다양한 분야에 관심이 많은 꼬마 개발자입니다.  </description>
    <language>ko</language>
    <pubDate>Thu, 21 May 2026 14:54:11 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>beeimp</managingEditor>
    <image>
      <title>BeeImp</title>
      <url>https://tistory1.daumcdn.net/tistory/4816612/attach/455c28088fa8462b8f534ebb23777f54</url>
      <link>https://beeimp.tistory.com</link>
    </image>
    <item>
      <title>[Network] REST API란?</title>
      <link>https://beeimp.tistory.com/entry/Network-REST-API%EB%9E%80</link>
      <description>&lt;h1&gt;REST API&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;REST(Representational State Transfer) API&lt;/code&gt;는 데이터 또는 리소스를 HTTP 프로토콜을 통해 URI로 요청하고 응답받는 방식을 의미합니다. API의 역할은 클라이언트와 서버 모두 올바르게 사용할 수 있어야 합니다. 따라서, 올바르게 사용할 수 있는 규칙들을 정의하여 디자인하는 것은 중요한 작업입니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Richardson Maturity Model 정리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://martinfowler.com/articles/richardsonMaturityModel.html&quot;&gt;Richardson Maturity Model&lt;/a&gt;에 따르면 REST API를 실용적으로 적용하기위한 0단계에서 3단계로 성숙도 모델을 정의했습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1372&quot; data-origin-height=&quot;998&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/sy6Ic/btrLj9YCGh1/NF6sCQkkHfuykkiLU4mlOK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/sy6Ic/btrLj9YCGh1/NF6sCQkkHfuykkiLU4mlOK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/sy6Ic/btrLj9YCGh1/NF6sCQkkHfuykkiLU4mlOK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fsy6Ic%2FbtrLj9YCGh1%2FNF6sCQkkHfuykkiLU4mlOK%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;584&quot; height=&quot;425&quot; data-origin-width=&quot;1372&quot; data-origin-height=&quot;998&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;0단계 - 기본 단계&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;0단계에서는 REST API를 사용하지 않고 단순히 HTTP Protocol을 사용하는 &lt;b&gt;기본 단계&lt;/b&gt;입니다. 실용적인 REST API를 만들기 위한 기본 단계라고 할 수 있습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1단계 - 개별 리소스와 통신 준수&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1단계는 &lt;b&gt;개별 리소스와 통신을 준수하는 단계&lt;/b&gt;입니다. 모든 리소스는 각 리소스에 맞는 Endpoint를 사용하여 요청하고 자원에 대한 정보를 응답해야 합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2단계 - HTTP 메소드 준수&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2단계는 &lt;b&gt;HTTP 메소드의 사용에 중점을 둔 단계&lt;/b&gt;입니다. CRUD에 따른 적절한 메소드를 사용해야 합니다. 또한, HTTP 메소드 사용에도 규칙(&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods&quot;&gt;MDN HTTP Request Methods&lt;/a&gt;)을 따릅니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;GET 메소드는 서버의 데이터를 변경하지 않는다.&lt;/li&gt;
&lt;li&gt;POST는 요청마다 새로운 리소스를 생성한다.&lt;/li&gt;
&lt;li&gt;PUT은 요청마다 같은 리소스를 반환하는 멱등성(&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Glossary/Idempotent&quot;&gt;idempotent&lt;/a&gt;)을 가진다.&lt;/li&gt;
&lt;li&gt;PUT은 교체, PATCH는 수정의 용도로 사용한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3단계 - HATEOAS 적용&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막 단계인 3단계는 &lt;b&gt;HATEOAS(Hypertext As The Engine Of Application State)을 적용하는 단계&lt;/b&gt;입니다. HATEOAS는 Hypertext를 통해 애플리케이션의 상태 전이가 가능해야하는 REST 애플리케이션 아키텍처의 제약입니다. 응답 메세지에 리소스의 URI 포함하는데, 이는 효율적으로 리소스와 기능에 접근 가능한 트리거가 될 수 있습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;REST API의 6가지 제약조건(Constraints)&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Client-server
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;리소스가 있는 쪽을 서버, 리소스를 요청하는 쪽을 클라이언트로 정의&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Stateless
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;서버는 클라이언트의 Context를 저장하지 않고, 각각의 요청에 대해 별개로 인식하고 처리&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Cacheable
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;대량의 요청을 효율적으로 처리&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Layered System
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;클라이언트는 REST API 서버만을 호출&lt;/li&gt;
&lt;li&gt;서버는 보안, 로드 밸런싱, 암호화, Proxy 등 다중 계층으로 구성&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Code on Demand(옵션)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;규칙 중에 유일하게 옵션으로 API의 응답을 확인해볼 수 있는 UI 위젯을 제공&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Uniform Interface -&lt;/b&gt; 리소스에 대한 요청을 통일되고, 한정적으로 수행하는 아키텍처 스타일
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Identification of Resources
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;리소스가 URI로 식별되면 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Manipulation of Resources through Representations
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;리소스를 추가, 수정, 삭제 등의 행위를 HTTP Message에 표현을 포함시켜야 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Self-Descriptive Messages
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;메세지를 스스로 설명해야한다.&lt;/li&gt;
&lt;li&gt;Description, Content-Type 등&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Hypermedia As The Engine Of Application State (HATEOAS)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;애플리케이션의 상태는 Hyperlink를 이용해 전이되어야 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
올바른 REST API를 사용하기 위해서는 6가지의 제약조건을 갖춰야 합니다. HTTP API의 사용만으로 Client-Server, Stateless, Cacheable, Layered System, Code on Demand(옵션)는 지켜집니다. 그러나, Uniform Interface를 지키기가 어렵습니다. 그 중에서도 Self-Descriptive Messages, HATEOAS는 잘 지켜지지 않고 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;왜? &lt;code&gt;Uniform Interface&lt;/code&gt; 의 제약조건을 지켜야할까요?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서버와 클라이언트가 있을 때, &lt;code&gt;독립적인 진화&lt;/code&gt;가 가능해집니다. 서버가 여러 업데이트를 진행해도 클라이언트는 업데이트를 할 필요가 없는 것입니다. REST API의 설계 목적가 가장 인접하다고 할 수 있습니다. 예를 들어, 출시한지 얼마안된 모바일 앱의 서버를 지속적으로 최적화하면서 모바일 앱도 업데이트를 요구합니다. 이 경우 사용자는 이용 중 많은 불편함을 느끼게 될 수 있습니다. 즉, 독립적인 진화가 필요합니다. REST API의 설계자인 로이 필딩은 HTTP API를 고치면 앱에 문제가 생기는 부분을 고민했고, Uniform Interface를 만족해야만 REST API라고 말할 수 있게 되었습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;REST API의 제약 조건 중 하나라도 빠지도 REST API인가? NO&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;REST API를 사용해봤다면 한 가지 의문점이 생깁니다. &amp;lsquo;REST API의 제약 조건을 모두 지키지 않지만 잘 동작합니다. 꼭 다 지켜야 REST API인가요? 잘 동작하면 되는거 아닌가요?&amp;rsquo;라고 이야기할 수 있습니다. 로이 필딩은 단호하게 REST의 모든 제약조건을 지키지 않는다면 REST API가 아니라고 이야기합니다. 추가적으로 전체 시스템을 통제할 수 있거나, 독립적인 진화에 관심이 없다면 REST의 모든 제약조건을 고민하지 말라고 이야기합니다. 즉, REST 제약조건을 모두 따르지 않다면 REST API가 아니지만 HTTP API라고 할 수 있는 것입니다. 로이 필딩은 REST의 제약조건을 모두 따르지 않는다면 다른 단어를 써달라고 이야기했습니다. 결국, 단어 선택의 차이일 뿐 사용에 문제가 없다면 HTTP API라고 말하면 되는거 아닐까요? &lt;/p&gt;</description>
      <category>Network</category>
      <category>network</category>
      <category>REST</category>
      <category>REST API</category>
      <category>REST 규칙</category>
      <author>beeimp</author>
      <guid isPermaLink="true">https://beeimp.tistory.com/116</guid>
      <comments>https://beeimp.tistory.com/entry/Network-REST-API%EB%9E%80#entry116comment</comments>
      <pubDate>Sun, 4 Sep 2022 20:06:47 +0900</pubDate>
    </item>
    <item>
      <title>[Network] URL과 URI 차이점</title>
      <link>https://beeimp.tistory.com/entry/URL%EA%B3%BC-URI-%EC%B0%A8%EC%9D%B4%EC%A0%90</link>
      <description>&lt;h1&gt;URL과 URI 차이점&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;URL는 많이 들어봤지만 URI는 뭘까요? 먼저, 많이 들어본 &lt;code&gt;URL(Uniform Resource Locator)&lt;/code&gt;는 네트워크 상에 서비스에 접근하기 위한 리소스의 위치를 의미합니다. &lt;code&gt;URI(Uniform Resource Identifier)&lt;/code&gt;는 URI에 파일의 위치와 요청사항을 추가한 자원의 식별자를 의미합니다. 즉, URI는 URL을 포함하는 개념입니다.&lt;/p&gt;
&lt;pre class=&quot;dts&quot;&gt;&lt;code&gt;http://localhost:8080/about?search=beeimp&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 예시는 일반적인 URI를 작성해보았습니다. 이를 &lt;code&gt;http://&lt;/code&gt;, &lt;code&gt;localhost&lt;/code&gt;, &lt;code&gt;:8080&lt;/code&gt;, &lt;code&gt;/about&lt;/code&gt;, &lt;code&gt;?search=beeimp&amp;amp;date=20220330&lt;/code&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;code&gt;http://&lt;/code&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;scheme&lt;/code&gt;라고 합니다.&lt;/li&gt;
&lt;li&gt;통신 프로토콜이 위치합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;localhost&lt;/code&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;hosts&lt;/code&gt;라고 합니다. 이 부분은&lt;/li&gt;
&lt;li&gt;서버의 IP, Domain이 위치합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;:8080&lt;/code&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;port&lt;/code&gt;라고 합니다.&lt;/li&gt;
&lt;li&gt;서버에서 제공하는 통로의 번호가 위치합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/about&lt;/code&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;url-path&lt;/code&gt;라고 합니다.&lt;/li&gt;
&lt;li&gt;서버에서 웹 페이지, 사진, 영상 등 파일의 경로가 위치합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;?search=beeimp&amp;amp;date=20220330&lt;/code&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;query&lt;/code&gt;라고 합니다.&lt;/li&gt;
&lt;li&gt;서버에 요청할 때 추가적으로 필터링된 값을 받아옵니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;?&lt;/code&gt;기호는 한번만 작성하여 &lt;code&gt;query&lt;/code&gt;의 시작을 의미합니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;key=value&lt;/code&gt;형태로 작성합니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;amp;&lt;/code&gt;는 AND를 의미합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Network</category>
      <category>network</category>
      <category>uri</category>
      <category>url</category>
      <author>beeimp</author>
      <guid isPermaLink="true">https://beeimp.tistory.com/115</guid>
      <comments>https://beeimp.tistory.com/entry/URL%EA%B3%BC-URI-%EC%B0%A8%EC%9D%B4%EC%A0%90#entry115comment</comments>
      <pubDate>Thu, 1 Sep 2022 02:09:36 +0900</pubDate>
    </item>
    <item>
      <title>왜 지갑 주소에는 대소문자가 들어갈까?</title>
      <link>https://beeimp.tistory.com/entry/%EC%99%9C-%EC%A7%80%EA%B0%91-%EC%A3%BC%EC%86%8C%EC%97%90%EB%8A%94-%EB%8C%80%EC%86%8C%EB%AC%B8%EC%9E%90%EA%B0%80-%EB%93%A4%EC%96%B4%EA%B0%88%EA%B9%8C</link>
      <description>&lt;h1&gt;왜 지갑 주소에는 대소문자가 들어갈까?&lt;/h1&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;상황&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이더리움 초창기에는 소문자만 사용하여 주소를 생성했었는데, 잘못된 주소를 입력하여 송금하는 사고가 종종 발생했다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;문제&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이러한 경우 회수가 현실적으로 불가능하여 주소 입력 오류 확인이 필요했다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;해결&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;2016년에 도입된 EIP-55를 통해 주소 오류를 99.9853% 감지&lt;/li&gt;
&lt;li&gt;EIP-55는 주소의 대소문자 형태로 인코딩해 주는 방식으로 checksum한다.&lt;/li&gt;
&lt;li&gt;checksum은 prefix인 0x를 뗀 소문자를 사용해서 표현한 주소의 해시값이 역할을 수행한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;방법&lt;/h2&gt;
&lt;pre class=&quot;python&quot;&gt;&lt;code&gt;'''EIP-55 Code'''
import eth_utils

def checksum_encode(addr): # Takes a 20-byte binary address as input
    hex_addr = addr.hex()
    checksummed_buffer = &quot;&quot;

    # Treat the hex address as ascii/utf-8 for keccak256 hashing
    hashed_address = eth_utils.keccak(text=hex_addr).hex()

    # Iterate over each character in the hex address
    for nibble_index, character in enumerate(hex_addr):

        if character in &quot;0123456789&quot;:
            # We can't upper-case the decimal digits
            checksummed_buffer += character
        elif character in &quot;abcdef&quot;:
            # Check if the corresponding hex digit (nibble) in the hash is 8 or higher
            hashed_address_nibble = int(hashed_address[nibble_index], 16)
            if hashed_address_nibble &amp;gt; 7:
                checksummed_buffer += character.upper()
            else:
                checksummed_buffer += character
        else:
            raise eth_utils.ValidationError(
                f&quot;Unrecognized hex character {character!r} at position {nibble_index}&quot;
            )

    return &quot;0x&quot; + checksummed_buffer

def test(addr_str):
    addr_bytes = eth_utils.to_bytes(hexstr=addr_str)
    checksum_encoded = checksum_encode(addr_bytes)
    assert checksum_encoded == addr_str, f&quot;{checksum_encoded} != expected {addr_str}&quot;

test(&quot;0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed&quot;)
test(&quot;0xfB6916095ca1df60bB79Ce92cE3Ea74c37c5d359&quot;)
test(&quot;0xdbF03B407c01E7cD3CBea99509d93f8DDDC8C6FB&quot;)
test(&quot;0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDb&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;소문자만을 사용하는 이더리움 주소의 해시값을 구한다.&lt;/li&gt;
&lt;li&gt;이더리움 주소와 해시값을 왼쪽부터 하나씩 확인하면서 다음과 같을 경우 대문자로 수정한다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이더리움 주소가 0xa 이상&lt;/li&gt;
&lt;li&gt;해시값이 0x8 이상인 경우&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;입력 오류가 있을 경우 위와같은 checksum 인코딩에서 미스매치가 발생하여 오류를 쉽게 검출할 수 있다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;결론&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;EIP-55를 통해 지갑 주소의 무결성을 보호하기 위해 대소문자를 사용한다.&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Blockchain/Ethereum</category>
      <category>checksum</category>
      <category>EIP-55</category>
      <category>Ethereum</category>
      <category>무결성</category>
      <category>이더리움</category>
      <author>beeimp</author>
      <guid isPermaLink="true">https://beeimp.tistory.com/114</guid>
      <comments>https://beeimp.tistory.com/entry/%EC%99%9C-%EC%A7%80%EA%B0%91-%EC%A3%BC%EC%86%8C%EC%97%90%EB%8A%94-%EB%8C%80%EC%86%8C%EB%AC%B8%EC%9E%90%EA%B0%80-%EB%93%A4%EC%96%B4%EA%B0%88%EA%B9%8C#entry114comment</comments>
      <pubDate>Mon, 29 Aug 2022 20:52:58 +0900</pubDate>
    </item>
    <item>
      <title>[Project] 누구(Who)가 아닌 기술을 신뢰하는 Klaytn 기반 티켓팅 서비스</title>
      <link>https://beeimp.tistory.com/entry/Project-%EB%88%84%EA%B5%ACWho%EA%B0%80-%EC%95%84%EB%8B%8C-%EA%B8%B0%EC%88%A0%EC%9D%84-%EC%8B%A0%EB%A2%B0%ED%95%98%EB%8A%94-Klaytn-%EA%B8%B0%EB%B0%98-%ED%8B%B0%EC%BC%93%ED%8C%85-%EC%84%9C%EB%B9%84%EC%8A%A4</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 프로젝트 개요&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;445&quot; data-origin-height=&quot;196&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bIZY0t/btrIPYxGABh/XT7tzhaXxw9C4UCz0ptEqK/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bIZY0t/btrIPYxGABh/XT7tzhaXxw9C4UCz0ptEqK/img.gif&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bIZY0t/btrIPYxGABh/XT7tzhaXxw9C4UCz0ptEqK/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/bIZY0t/btrIPYxGABh/XT7tzhaXxw9C4UCz0ptEqK/img.gif&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;420&quot; height=&quot;185&quot; data-origin-width=&quot;445&quot; data-origin-height=&quot;196&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;TT 란 ?&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;누구(Who)가 아닌 기술을 신뢰하는 Klaytn 기반 티켓팅 서비스&lt;/b&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Trust Ticket, TT는 블록체인 기술을 이용한 티켓팅 서비스를 제공합니다.&lt;br /&gt;TT 이용자는 이벤트를 기획할 수도 있고, 다른 이벤트를 참여할 수 있습니다.&lt;br /&gt;이벤트 참여를 하면 각 이벤트에서 발행하는 토큰을 받을 수 있고, 이는 입장티켓 또는 응모당첨권으로 사용합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;배포 링크&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Github&lt;/b&gt;: &lt;a href=&quot;https://github.com/codestates/BEB-04-ZeroTeb&quot;&gt;https://github.com/codestates/BEB-04-ZeroTeb&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Mobile&lt;/b&gt; : &lt;a href=&quot;http://server.beeimp.com:18080/file?fn=tt.apk&quot;&gt;다운링크&lt;/a&gt; (스토어 배포 심사 중)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Server&lt;/b&gt; - &lt;a href=&quot;https://documenter.getpostman.com/view/21835071/UzQvtjyt&quot;&gt;POST API Document&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;WEB&lt;/b&gt; - &lt;a href=&quot;https://tt.beeimp.com&quot;&gt;https://tt.beeimp.com&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. 프로젝트 소개&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;토큰 이코노미&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;왜 필요한가요?
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이벤트가 돌연 취소
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;상황 - 소비자는 이벤트 기획측 또는 플랫폼에서 알 수 없는 이유로 콘서트 취소에 대해 일방적인 통보를 받았습니다.&lt;/li&gt;
&lt;li&gt;문제 - 소비자는 일방적인 통보를 받았음에도 보상을 받을 수 없습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;티켓 사재기
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;상황 - 암표상들은 개인의 이익을 위해 이벤트에서 티켓을 구매 후 몰래 재판매합니다.&lt;/li&gt;
&lt;li&gt;문제 - 암표상들은 공정한 티켓 획득 기회를 미리 사재기를 하여 웃돈을 붙여 표를 판매하기 때문에 위법하다고 할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;플랫폼의 서비스 종료
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;상황 - 이용하던 거래 플랫폼이 어떠한 이유로 유지할 수 없어 서비스를 종료했습니다.&lt;/li&gt;
&lt;li&gt;문제 - 이용하던 거래 플랫폼 서비스가 종료되면서 소비자의 모든 기록이 삭제되면서 지금까지의 활동이 확인할 수 없습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;각 플랫폼의 제약
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;상황 - 이용하던 거래 플랫폼이 아닌 타 거래 플랫폼을 이용한다.&lt;/li&gt;
&lt;li&gt;문제 - 타 거래 플랫폼에서는 이전에 이용하던 거래 플랫폼에서 참여했던 콘서트 내역을 가져올 수 없거나 참여했던 실물 콘서트 티켓을 모두 등록해야하는 불편함을 가집니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;무엇을 얻을 수 있나요?
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;소비자는 이벤트가 갑자기 취소되더라도 티켓 가격의 103%를 보상 받을 수 있습니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이벤트 기획자는 이벤트를 등록하면서 티켓으로 판매하여 얻을 수 있는 총액의 5%(보증금 3%, 수수료 2%)를 지불합니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;보증금은 이벤트 성공시 이벤트 기획자에게 반환됩니다.&lt;/li&gt;
&lt;li&gt;수수료는 주로 컨트랙트 실행, 서버 유지비에 사용됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;이벤트가 최소되면 소비자는 대해 티켓의 103%를 보상 받습니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이벤트 기획자의 보증금이 피해 보상금으로 사용합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;소비자는 공정한 티 켓케득 기회를 얻을 수 있습니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이벤트가 종료될 때까지 토큰 거래가 불가능합니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;SBT와 NFT를 적절히 사용하여 참여에 대한 티켓의 주요 목적을 달성합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;소비자는 이용하던 티켓 플랫폼이 종료되더라도 모든 기록을 잃지 않습니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;데이터베이스가 손상되더라도 Klaytn Network에서 복구 가능합니다.&lt;/li&gt;
&lt;li&gt;만약, 해당 플랫폼의 서비스가 종료되더라도 모든 기록은 Klaytn Network에 투명하게 저장되어 토큰형 티켓의 거래 또는 확인이 가능합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;이벤트 기획자는 이용하던 여러 티켓 플랫폼이 통합적으로 VIP를 관리할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;누가 할 수 있나요?
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;카카오 계정이 있다면 누구든 사용 가능하고 누구든 될 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;언제, 어디서 사용할 수 있나요?
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;모바일 기기에 종류에 상관없이 언제, 어디서든 이용 가능합니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;React-Native로 앱이 제작되어 Android, ios에 상관없이 사용 가능합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;언제, 어디서든 이벤트를 등록할 수 있습니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;PC, Mobile 모두 지원합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;언제, 어디서든 티켓을 구매, 응모, 인증, 확인 가능합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;어떻게 사용할 수 있나요?
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;카카오톡 앱을 설치합니다. ( 이미 다 있으실 거에요 )&lt;/li&gt;
&lt;li&gt;앱 서비스에서 클립을 가입합니다.&lt;/li&gt;
&lt;li&gt;TT 앱을 설치합니다. ( 앱 스토어, 플레이 스토어 등 배포 예정입니다! )&lt;/li&gt;
&lt;li&gt;TT 앱을 실행하여 이벤트 등록부터 티켓 구매, 응모, 조회, 인증, 확인까지 자유롭게 이용 가능합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Klaytn 사용한 이유&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;카카오 클립으로 누구나 간단하게 지갑 생성 가능합니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;복잡한 지갑 생성 과정을 거치지 않고, 국민 메신저 서비스로 자리 잡은 카카오톡 앱이 있다면 사용 가능한 클립을 사용하기 위해 채택했습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;속도와 가격 측면에서 용이합니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;가격 - 트랜잭션에서 발생하는 가스비가 1~20원 수준으로 매우 저렴합니다.&lt;/li&gt;
&lt;li&gt;속도 - 이론적 측면이 아닌 실제 4000 TPS의 처리량을 가집니다&lt;/li&gt;
&lt;li&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ckT4ju/btrINMEse7k/h2f1m5kEbSFEqyTHzqKclk/img.png&quot; width=&quot;655&quot; height=&quot;182&quot; data-image-src=&quot;https://blog.kakaocdn.net/dn/ckT4ju/btrINMEse7k/h2f1m5kEbSFEqyTHzqKclk/img.png&quot; data-origin-width=&quot;1164&quot; data-origin-height=&quot;324&quot; /&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;WorkFlow&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://s3.us-west-2.amazonaws.com/secure.notion-static.com/cf0f5056-6d86-4ca2-9611-81d6b80b9789/%EB%8B%A4%EC%9D%B4%EC%96%B4%EA%B7%B8%EB%9E%A8.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&amp;amp;X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&amp;amp;X-Amz-Credential=AKIAT73L2G45EIPT3X45%2F20220802%2Fus-west-2%2Fs3%2Faws4_request&amp;amp;X-Amz-Date=20220802T143631Z&amp;amp;X-Amz-Expires=86400&amp;amp;X-Amz-Signature=4dbcd47adf2b2a05ef887d6fa14e9abbdcdcf822d7bf7cf46be155e2f47506a3&amp;amp;X-Amz-SignedHeaders=host&amp;amp;response-content-disposition=filename%20%3D%22%25EB%258B%25A4%25EC%259D%25B4%25EC%2596%25B4%25EA%25B7%25B8%25EB%259E%25A8.png%22&amp;amp;x-id=GetObject&quot; alt=&quot;다이어그램.png&quot; /&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;기능별 시연 영상&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;랜딩 페이지 (WEB)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;450&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tOQ0P/btrIAEBdUga/T1U5dzFNtjfkaYUcNOqtqk/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tOQ0P/btrIAEBdUga/T1U5dzFNtjfkaYUcNOqtqk/img.gif&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tOQ0P/btrIAEBdUga/T1U5dzFNtjfkaYUcNOqtqk/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/tOQ0P/btrIAEBdUga/T1U5dzFNtjfkaYUcNOqtqk/img.gif&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;450&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;450&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;Klip 로그인
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Klip을 이용한 개발Klip에서 request key를 받아 서버로 전송하고, 서버에서 Klip과 통신해서 사용자를 인증합니다. 인증된 사용자에게 JWT 토큰을 발행하여, TT의 기능을 사용할 수 있도록 합니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;img src=&quot;https://s3.us-west-2.amazonaws.com/secure.notion-static.com/4ab12f12-4b5e-4458-b834-af58487c39ce/ezgif.com-gif-maker_%283%29.gif?X-Amz-Algorithm=AWS4-HMAC-SHA256&amp;amp;X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&amp;amp;X-Amz-Credential=AKIAT73L2G45EIPT3X45%2F20220802%2Fus-west-2%2Fs3%2Faws4_request&amp;amp;X-Amz-Date=20220802T143757Z&amp;amp;X-Amz-Expires=86400&amp;amp;X-Amz-Signature=8df9f93210cca61432f872541b8ef956b26983a2ff1b0c9010fdfdad9a22a7ec&amp;amp;X-Amz-SignedHeaders=host&amp;amp;response-content-disposition=filename%20%3D%22ezgif.com-gif-maker%2520%283%29.gif%22&amp;amp;x-id=GetObject&quot; alt=&quot;ezgif.com-gif-maker (3).gif&quot; /&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;현재 Klip API에서 테스트 넷을 지원하지 않습니다. 그래서 Klip의 일부 기능들을 서버에서 구현하여 Klip API의 역할을 대체합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;이벤트 등록(모바일)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;간편한 이벤트 등록&lt;/li&gt;
&lt;li&gt;스마트폰으로 간단하게 이벤트를 등록할 수 있고, 많은 데이터를 등록하는 사람들을 위해 웹으로도 등록할 수 있습니다.&lt;/li&gt;
&lt;li&gt;토큰 발행
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;
&lt;div&gt;&lt;img src=&quot;https://s3.us-west-2.amazonaws.com/secure.notion-static.com/45c9553b-1345-4f3c-8d08-14bca9bc1064/enroll.gif?X-Amz-Algorithm=AWS4-HMAC-SHA256&amp;amp;X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&amp;amp;X-Amz-Credential=AKIAT73L2G45EIPT3X45%2F20220802%2Fus-west-2%2Fs3%2Faws4_request&amp;amp;X-Amz-Date=20220802T143832Z&amp;amp;X-Amz-Expires=86400&amp;amp;X-Amz-Signature=04b19570595ef33a8c24ed1c96004e328dc11367d3d9033ac093a50a307d08bf&amp;amp;X-Amz-SignedHeaders=host&amp;amp;response-content-disposition=filename%20%3D%22enroll.gif%22&amp;amp;x-id=GetObject&quot; alt=&quot;enroll.gif&quot; /&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;이벤트가 등록되면, 컨트랙트는 토큰을 서버에 발행합니다. 발행된 토큰은 구매를 통해 얻을 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;이벤트 등록(웹)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;
&lt;div&gt;&lt;img src=&quot;https://s3.us-west-2.amazonaws.com/secure.notion-static.com/91cfc03f-6573-43be-a84c-39ab69183231/TT_2.gif?X-Amz-Algorithm=AWS4-HMAC-SHA256&amp;amp;X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&amp;amp;X-Amz-Credential=AKIAT73L2G45EIPT3X45%2F20220802%2Fus-west-2%2Fs3%2Faws4_request&amp;amp;X-Amz-Date=20220802T143901Z&amp;amp;X-Amz-Expires=86400&amp;amp;X-Amz-Signature=342642ba5b4ba6fa62b6a7dab37e4e94e33cd14f5af27867c6f572a2120b8751&amp;amp;X-Amz-SignedHeaders=host&amp;amp;response-content-disposition=filename%20%3D%22TT_2.gif%22&amp;amp;x-id=GetObject&quot; alt=&quot;TT_3.gif&quot; /&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div&gt;&lt;img src=&quot;https://s3.us-west-2.amazonaws.com/secure.notion-static.com/4c7456eb-c06f-4e52-a45c-2bb9fa6dac22/TT_3.gif?X-Amz-Algorithm=AWS4-HMAC-SHA256&amp;amp;X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&amp;amp;X-Amz-Credential=AKIAT73L2G45EIPT3X45%2F20220802%2Fus-west-2%2Fs3%2Faws4_request&amp;amp;X-Amz-Date=20220802T143912Z&amp;amp;X-Amz-Expires=86400&amp;amp;X-Amz-Signature=1f76c65c75ff2d75046d4c50e98663e5a4cb0c213e83d3aa84cf193c358ea35e&amp;amp;X-Amz-SignedHeaders=host&amp;amp;response-content-disposition=filename%20%3D%22TT_3.gif%22&amp;amp;x-id=GetObject&quot; alt=&quot;TT_2.gif&quot; /&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;이벤트 티켓 구매/응모
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;티켓 구매&lt;/li&gt;
&lt;li&gt;서버는 티켓을 구매한 사용자에게 티켓을 전송합니다. 사용자가 쉽게 구매할 수 있도록 Klip API를 사용하여, 편의성을 높였습니다.&lt;/li&gt;
&lt;li&gt;티켓 응모
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;
&lt;div&gt;&lt;img src=&quot;https://s3.us-west-2.amazonaws.com/secure.notion-static.com/67a11b2d-a9f5-4ecf-a9e6-ec63dacb6bbe/ezgif.com-gif-maker_%284%29.gif?X-Amz-Algorithm=AWS4-HMAC-SHA256&amp;amp;X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&amp;amp;X-Amz-Credential=AKIAT73L2G45EIPT3X45%2F20220802%2Fus-west-2%2Fs3%2Faws4_request&amp;amp;X-Amz-Date=20220802T143923Z&amp;amp;X-Amz-Expires=86400&amp;amp;X-Amz-Signature=664426eb4547a4b581f4294cc12cfe1267a82e9c2191f985b900d5c51aca877d&amp;amp;X-Amz-SignedHeaders=host&amp;amp;response-content-disposition=filename%20%3D%22ezgif.com-gif-maker%2520%284%29.gif%22&amp;amp;x-id=GetObject&quot; alt=&quot;ezgif.com-gif-maker (4).gif&quot; /&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;응모한 사용자의 주소를 컨트랙트에 보관합니다. 이벤트 응모 가능 기간이 지나면 서버가 자동으로 이벤트 추첨을 컨트랙트에 요청합니다. 이벤트 추첨은 응모자 중 랜덤으로 당첨자를 선정합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;QRcode 생성
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;간편한 티켓 생성
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;
&lt;div&gt;&lt;img src=&quot;https://s3.us-west-2.amazonaws.com/secure.notion-static.com/2d29df49-8a91-4792-84c7-ffd89fdea228/ezgif.com-gif-maker_%285%29.gif?X-Amz-Algorithm=AWS4-HMAC-SHA256&amp;amp;X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&amp;amp;X-Amz-Credential=AKIAT73L2G45EIPT3X45%2F20220802%2Fus-west-2%2Fs3%2Faws4_request&amp;amp;X-Amz-Date=20220802T143935Z&amp;amp;X-Amz-Expires=86400&amp;amp;X-Amz-Signature=9d92485df1cd72ea46b892613bc2e4cf8a57c8f4239e7c2c42ba317217835a07&amp;amp;X-Amz-SignedHeaders=host&amp;amp;response-content-disposition=filename%20%3D%22ezgif.com-gif-maker%2520%285%29.gif%22&amp;amp;x-id=GetObject&quot; alt=&quot;ezgif.com-gif-maker (5).gif&quot; width=&quot;353&quot; height=&quot;725&quot; /&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;QR 코드는 앱에서 티켓을 클릭할 때 발행되고, 서버는 해당 QR에 유효 기한을 부여합니다. QRcode는 nonce 데이터를 가지고 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;QRcode 유효성 확인
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;티켓 확인하기서버는 해당 이벤트의 QRcode인지, 유효 기한이 남았는지 검사합니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;
&lt;div&gt;&lt;img src=&quot;https://s3.us-west-2.amazonaws.com/secure.notion-static.com/ed13c14e-4de0-4736-8cf1-f1b56d7ca7e4/ezgif.com-gif-maker_%286%29.gif?X-Amz-Algorithm=AWS4-HMAC-SHA256&amp;amp;X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&amp;amp;X-Amz-Credential=AKIAT73L2G45EIPT3X45%2F20220802%2Fus-west-2%2Fs3%2Faws4_request&amp;amp;X-Amz-Date=20220802T143945Z&amp;amp;X-Amz-Expires=86400&amp;amp;X-Amz-Signature=577d93a9a1eb848820e78c3cdf029b11dad727f36193349ce68509bcf9ff4121&amp;amp;X-Amz-SignedHeaders=host&amp;amp;response-content-disposition=filename%20%3D%22ezgif.com-gif-maker%2520%286%29.gif%22&amp;amp;x-id=GetObject&quot; alt=&quot;ezgif.com-gif-maker (6).gif&quot; width=&quot;355&quot; height=&quot;730&quot; /&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;QR Reader는 QRcode에서 읽은 데이터(nonce, event_id)를 서버로 전송합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;검색
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;원하는 이벤트 찾기&lt;/li&gt;
&lt;li&gt;사용자는 Keyword가 포함한 이벤트를 검색할 수 있습니다.&lt;/li&gt;
&lt;li&gt;인기 있는 이벤트 (개발 진행 중)이후 같은 키워드가 들어오면 count값을 올려주고, count가 가장 많은 키워드를 인기 검색어로 정합니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;
&lt;div&gt;&lt;img src=&quot;https://s3.us-west-2.amazonaws.com/secure.notion-static.com/2fee9b14-ab86-4837-8a50-e04b332d2020/ezgif.com-gif-maker_%287%29.gif?X-Amz-Algorithm=AWS4-HMAC-SHA256&amp;amp;X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&amp;amp;X-Amz-Credential=AKIAT73L2G45EIPT3X45%2F20220802%2Fus-west-2%2Fs3%2Faws4_request&amp;amp;X-Amz-Date=20220802T143959Z&amp;amp;X-Amz-Expires=86400&amp;amp;X-Amz-Signature=fd2e88b4013b81a02b9e9bb015cc37ea367a9701db51928610b933b8874e2ecf&amp;amp;X-Amz-SignedHeaders=host&amp;amp;response-content-disposition=filename%20%3D%22ezgif.com-gif-maker%2520%287%29.gif%22&amp;amp;x-id=GetObject&quot; alt=&quot;ezgif.com-gif-maker (7).gif&quot; /&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;사용자가 검색한 키워드 중 검색 결과가 유효한 데이터를 DB에 저장합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;내 주변
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;나와 가까운 이벤트 찾기
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;
&lt;div&gt;&lt;img src=&quot;https://s3.us-west-2.amazonaws.com/secure.notion-static.com/659e79af-abf2-4645-8f55-6d7693e5178c/ezgif.com-gif-maker_%288%29.gif?X-Amz-Algorithm=AWS4-HMAC-SHA256&amp;amp;X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&amp;amp;X-Amz-Credential=AKIAT73L2G45EIPT3X45%2F20220802%2Fus-west-2%2Fs3%2Faws4_request&amp;amp;X-Amz-Date=20220802T144010Z&amp;amp;X-Amz-Expires=86400&amp;amp;X-Amz-Signature=fe8ffd54606a360c96236db270e8f9c2a38d8f7838d67ff2457fe013b9e33956&amp;amp;X-Amz-SignedHeaders=host&amp;amp;response-content-disposition=filename%20%3D%22ezgif.com-gif-maker%2520%288%29.gif%22&amp;amp;x-id=GetObject&quot; alt=&quot;ezgif.com-gif-maker (8).gif&quot; width=&quot;349&quot; height=&quot;718&quot; /&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;현재 위치의 좌표를 서버로 보냅니다. 서버는 Map API를 통해 사용자의 지역을 찾고, 이벤트의 좌표와 거리를 구해 사용자에게 출력해 줍니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. 기술 스택&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1342&quot; data-origin-height=&quot;2248&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uNdMU/btrIKmz4lem/dau5uieHQa5LINkqsQmUx1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uNdMU/btrIKmz4lem/dau5uieHQa5LINkqsQmUx1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uNdMU/btrIKmz4lem/dau5uieHQa5LINkqsQmUx1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuNdMU%2FbtrIKmz4lem%2Fdau5uieHQa5LINkqsQmUx1%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;683&quot; height=&quot;1144&quot; data-origin-width=&quot;1342&quot; data-origin-height=&quot;2248&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4. 관련 문서&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;시나리오 기반 WorkFlow&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://www.figma.com/proto/EiawCKjCRga7uzldcSx5fu/ZeroTEB_Architecture?node-id=85%3A2&amp;amp;scaling=min-zoom&amp;amp;page-id=0%3A1&quot;&gt;https://www.figma.com/proto/EiawCKjCRga7uzldcSx5fu/ZeroTEB_Architecture?node-id=85%3A2&amp;amp;scaling=min-zoom&amp;amp;page-id=0%3A1&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;App Prototype&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://www.figma.com/proto/ISnNAWq8EU68Np1WNlIS3P/ZeroTEB_Mockup?node-id=5%3A6&amp;amp;starting-point-node-id=5%3A6&quot;&gt;https://www.figma.com/proto/ISnNAWq8EU68Np1WNlIS3P/ZeroTEB_Mockup?node-id=5%3A6&amp;amp;starting-point-node-id=5%3A6&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;5. 내가 수행한 역할&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Project Management&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;Notion&lt;/code&gt;을 통해 프로젝트 전체 work-flow 기획&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Discord&lt;/code&gt;에서 &lt;code&gt;Github Webhook&lt;/code&gt;를 연결하여 &lt;code&gt;Github bot&lt;/code&gt; 연결&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Blockchain&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;KIP17&lt;/code&gt;을 활용한 &lt;code&gt;Solidity&lt;/code&gt; 컨트랙트 작성
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이벤트 생성&lt;/li&gt;
&lt;li&gt;이벤트 토큰 민팅, 거래, 응모&lt;/li&gt;
&lt;li&gt;이벤트 당첨자 추첨 - 랜덤함수 구현&lt;/li&gt;
&lt;li&gt;이벤트 종료&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Back-End&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;DB 생성 및 원격 연결 - &lt;code&gt;Mongo Atlas&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;JWT 인증 기능 구현 - &lt;code&gt;Nest.js&lt;/code&gt; &lt;code&gt;@Guard&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;DB 정보 추가 및 업데이트 Scheduling 구현 - &lt;code&gt;Nest.js @Cron&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;컨트랙트 실행 API 구현 - &lt;code&gt;Caver-js&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;서버 자동 배포
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;Azure VM&lt;/code&gt; 위에 &lt;code&gt;Docker&lt;/code&gt;, &lt;code&gt;Jenkins&lt;/code&gt; 설치&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Github Webhook&lt;/code&gt;에 &lt;code&gt;Jenkins&lt;/code&gt;설정&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Jenkins Pipeline&lt;/code&gt; 작성&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Front-End (WEB)&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Lending Page&lt;/li&gt;
&lt;li&gt;Create Event Page&lt;/li&gt;
&lt;li&gt;Created View Page&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;6. 회고&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;초기 목표(시작하게 된 목표)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로젝트 초기 목표
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;투자에 과열된 NFT 또는 SBT에 대한 새로운 인식 제공&lt;/li&gt;
&lt;li&gt;누구나 이벤트 성공 여부에 대한 최대 보상 제도 도입&lt;/li&gt;
&lt;li&gt;누구나 이벤트를 생성 수 있고 혜택을 받을 수 있는 서비스 구현&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;팀장으로써 목표&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;팀원들 간의 심리적 갈등이 없이 프로젝트가 즐겁게 시작하여 마무리&lt;/li&gt;
&lt;li&gt;저를 포함한 팀원이 프로젝트에서 얻고자하는 방향 및 결과물 완성&lt;/li&gt;
&lt;li&gt;각 포지션의 개발&lt;/li&gt;
&lt;li&gt;프로젝트 이슈 관리&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;개인 목표&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;모두 피해 받지 않는 토큰 이코노미 설계&lt;/li&gt;
&lt;li&gt;티켓팅 컨트랙트 작성 및 배포&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;현실(실제 어떤 원인에 의해 문제가 발생했고 해결했는가?)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;각 포지션에만 집중할 수 있는 환경
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;상황 - 백엔드에서 개발한 API를 통해 프론트에서 테스트를 진행해야 합니다.&lt;/li&gt;
&lt;li&gt;문제 - 프론트에서 API를 테스트하기 위해서는 백엔드 서버를 로컬에 다운받아 서버를 실행시켜 테스트해야하는 어려움이 있었습니다.&lt;/li&gt;
&lt;li&gt;해결 - 클라우드 서비스 중 Azure를 이용하여 VM을 생성하여 Docker와 Jenkins를 설치했습니다. Jenkins를 프로젝트 Github Webhook과 연결하여 push 이벤트가 발생하면 빌드하여 실행할 수 있도록 설정했습니다. 이를 통해, 서버에서는 API를 개발 후 push하면 프론트에서는 해당 API를 사용할 수 있었습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;카카오 클립 메인넷만 지원
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;상황 - 앱에서 로그인, 이벤트 등록, 티켓 구매, 응모 등 카카오 클립 지갑을 통해 컨트랙트에 요청해야 했습니다.&lt;/li&gt;
&lt;li&gt;문제 - 테스트 환경에서 진행하는 프로젝트에서 카카오 클립이 테스트넷을 지원하지 않았습니다.&lt;/li&gt;
&lt;li&gt;해결 - 가스비가 발생하지 않는 로그인 인증 부분만 카카오 클립을 사용하고, 이외의 클립 API는 서버에서 자체적으로 테스트용 지갑을 생성 후 매칭하여 서버 API를 통해 대체 했습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;당첨자를 뽑기 위한 랜덤 함수 구현
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;상황 - 이벤트 응모를 진행하면 당첨자를 뽑는 추첨을 진행해야 했습니다.&lt;/li&gt;
&lt;li&gt;문제 - 이중 반복문을 사용하여 suffle을 구현하게 되면 시간 복잡도 n^2으로 높은 가스비가 발생할 수 있었습니다.&lt;/li&gt;
&lt;li&gt;해결 - 해시 함수를 통해 랜덤한 값을 응모자 수의 나머지 값으로 랜덤한 인덱스를 생성하고 순차적으로 Swap했습니다. 이를 통해, 시간 복잡도 n을 달성하여 가스비 절감과 속도 성능을 향상 시킬 수 있었습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;후기(지속, 개선, 포기할 것은 무엇인가, 아쉬운 점)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;포기 - 개인적으로 설계했던 시나리오 수정
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;내용 - 팀원을 뽑기 전, 개인적으로 설계했던 시나리오를 수정했습니다.&lt;/li&gt;
&lt;li&gt;포기한 이유 - 팀원 모두 프로젝트를 재밌게 진행하기 위해 시나리오를 수정했습니다. 포괄적으로 제시했던 아이디어에서 개인적으로 했으면 좋겠던 시나리오가 있었는데, 그 시나리오를 포함하여 다른 팀원들이 생각하는 시나리오를 수합하여 투표를 진행하여 최종적으로 하나의 시나리오를 채택하게 되었습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;지속 - 각 포지션에 해당하는 독립적인 작업 부여
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;내용 - POSTMAN의 Mock server 기능을 활용하여 프로젝트 진행 간 백엔드와 프론트에 대한 기능 개발 유무와 상관없이 테스트 API를 사용하여 간섭없이 각 개발을 진행할 수 있었습니다.&lt;/li&gt;
&lt;li&gt;지속하려는 이유 - 이전에 프로젝트를 진행할 때는 백엔드에서 API를 개발할 때까지 데이터를 가져올 수 없어 더미 데이터를 추가하고 진행했었습니다. 이 과정에서 더미 데이터 위치에 API를 연결해야하는 추가 작업이 필요 했었는데, 추가 작업을 진행하지 않아 생산성을 향상시킬 수 있었습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;아쉬운점 - 진행 상황 관리 부족
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;내용 - 일일 2회 회의를 진행하면서 이슈 사항을 정리하면서 프로젝트를 관리했습니다.&lt;/li&gt;
&lt;li&gt;아쉬운 이유 - 프로젝트 기한이 다가오면서 팀원들의 일일 프로젝트 작업을 제대로 확인하지 못했습니다. 또한, 다들 지쳐가고 와중에 팀장으로써 제대로 독려를 못한 것 같아 아쉬웠습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;개선 - 지속적인 진행 상황 확인 및 관리
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;내용 - 아쉬운점과 같습니다.&lt;/li&gt;
&lt;li&gt;개선하려는 이유 - 프로젝트 결과물이 개인적으로 기대하는 만큼 UI가 그려지지 못해 너무 아쉬웠습니다. 팀장으써 각 팀원의 컨디션과 진행 상황을 제대로 파악하지 못했기 때문이라고 생각합니다. 바쁠수록 돌아가라는 말이 있습니다. 추후 프로젝트를 진행하게 된다면, 다음 사항을 생각하면서 개선하려고 합니다.
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;기본 기능, 주요 기능, 고급 기능, 추가 기능 등 기능들을 단계별 세분화 개발&lt;/li&gt;
&lt;li&gt;지속적으로 결과물을 평가하고 일정을 조정하여 프로젝트를 관리&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Blockchain/Project</category>
      <category>KIP17</category>
      <category>Klaytn</category>
      <category>mongodb</category>
      <category>Nest.js</category>
      <category>Next.js</category>
      <category>Project</category>
      <category>react-native</category>
      <category>React.js</category>
      <category>redux</category>
      <category>typescript</category>
      <author>beeimp</author>
      <guid isPermaLink="true">https://beeimp.tistory.com/113</guid>
      <comments>https://beeimp.tistory.com/entry/Project-%EB%88%84%EA%B5%ACWho%EA%B0%80-%EC%95%84%EB%8B%8C-%EA%B8%B0%EC%88%A0%EC%9D%84-%EC%8B%A0%EB%A2%B0%ED%95%98%EB%8A%94-Klaytn-%EA%B8%B0%EB%B0%98-%ED%8B%B0%EC%BC%93%ED%8C%85-%EC%84%9C%EB%B9%84%EC%8A%A4#entry113comment</comments>
      <pubDate>Tue, 2 Aug 2022 23:47:51 +0900</pubDate>
    </item>
    <item>
      <title>[TIL] Nest 중복 호출 오류, Node process.cwd()와 __dirname의 차이</title>
      <link>https://beeimp.tistory.com/entry/TIL-Nest-%EC%A4%91%EB%B3%B5-%ED%98%B8%EC%B6%9C-%EC%98%A4%EB%A5%98-Node-processcwd%EC%99%80-dirname%EC%9D%98-%EC%B0%A8%EC%9D%B4</link>
      <description>&lt;h1&gt;[TIL] Nest 중복 호출 오류, Node &lt;code&gt;process.cwd()&lt;/code&gt;와 &lt;strong&gt;&lt;code&gt;__dirname&lt;/code&gt;의 차이&lt;/strong&gt;&lt;/h1&gt;
&lt;h2&gt;날짜&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;2022.07.13.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;목표&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input checked=&quot;&quot; disabled=&quot;&quot; type=&quot;checkbox&quot;&gt; Nest.js 학습&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;내용&lt;/h2&gt;
&lt;h3&gt;Nest.js - &lt;code&gt;@**InjectConnection&lt;/code&gt;** 중복 호출 오류&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;오류 메세지&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  ERROR [ExceptionHandler] Nest can&amp;#39;t resolve dependencies of the AuthService (JwtService, ?, UsernameConnection). Please make sure that the argument UserConnection at index [1] is available in the AuthModule context.

  Potential solutions:
  - If UserConnection is a provider, is it part of the current AuthModule?
  - If UserConnection is exported from a separate @Module, is that module imported within AuthModule?
    @Module({
      imports: [ /* the Module containing UserConnection */ ]
    })&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;원인&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;@**InjectConnection&lt;/code&gt;** 가 두번 선언되어서 오류 발생&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-tsx&quot;&gt;export class AuthService {
constructor(
  private jwtService: JwtService,
  **@InjectConnection(User.name) private userModel: Model&amp;lt;User&amp;gt;,
  @InjectConnection(Username.name) private usernameModel: Model&amp;lt;Username&amp;gt;,**
) {}
  ...
}&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;해결&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-tsx&quot;&gt;  export class AuthService {
      userModel: Model&amp;lt;UserDocument&amp;gt;;
    usernameModel: Model&amp;lt;UsernameDocument&amp;gt;;
    constructor(
      private jwtService: JwtService,
          **@InjectConnection() private readonly mongooseConnection: Connection,**
    ) {
          this.userModel = mongooseConnection.model(User.name);
      this.usernameModel = mongooseConnection.model(Username.name);
      }
      ...
  }&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Node.js - &lt;code&gt;process.cwd()&lt;/code&gt;와 &lt;strong&gt;&lt;code&gt;__dirname&lt;/code&gt;의 차이&lt;/strong&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;process.cwd()&lt;/code&gt;&lt;ul&gt;
&lt;li&gt;전역 객체의 메소드&lt;/li&gt;
&lt;li&gt;프로세스의 현재 작업 디렉토리를 문자열 값으로 리턴&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;__dirname&lt;/code&gt;&lt;ul&gt;
&lt;li&gt;현재 스크립트의 디렉토리 이름&lt;/li&gt;
&lt;li&gt;전역이 아니라 각 모듈에 대해 로컬을 문자열 값으로 리턴&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;결론&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;오류의 원인을 정확히는 모르겠지만 잘 해결되었습니다.&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>I Learned/TIL</category>
      <category>InjectConnection</category>
      <category>Nest.js</category>
      <category>node</category>
      <category>process.cwd()</category>
      <category>__dirname</category>
      <author>beeimp</author>
      <guid isPermaLink="true">https://beeimp.tistory.com/112</guid>
      <comments>https://beeimp.tistory.com/entry/TIL-Nest-%EC%A4%91%EB%B3%B5-%ED%98%B8%EC%B6%9C-%EC%98%A4%EB%A5%98-Node-processcwd%EC%99%80-dirname%EC%9D%98-%EC%B0%A8%EC%9D%B4#entry112comment</comments>
      <pubDate>Wed, 13 Jul 2022 23:27:09 +0900</pubDate>
    </item>
    <item>
      <title>[TIL] Mongo - import json file</title>
      <link>https://beeimp.tistory.com/entry/Mongo-import-json-file</link>
      <description>&lt;h1&gt;[TIL] Mongo - import json file&lt;/h1&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;날짜&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;2022.07.12&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;내용&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;MongoDB - import json file for macOS&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;mongoimport 설치
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;brew install mongodb/brew/mongodb-database-tools&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;실행&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-bash&quot;&gt;  $ mongoimport \
      --uri=&amp;lt;Atlas Cluster URI&amp;gt; \
      --drop=&amp;lt;File Name&amp;gt;.json
      --jsonArray
    -c &amp;lt;Collection Name&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;결론&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;랜덤하게 생성한 JSON 형태의 파일을 MongoDB에 import하는 방법을 학습 및 실습 했습니다.&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>I Learned/TIL</category>
      <category>Import</category>
      <category>json</category>
      <category>mongodb</category>
      <author>beeimp</author>
      <guid isPermaLink="true">https://beeimp.tistory.com/111</guid>
      <comments>https://beeimp.tistory.com/entry/Mongo-import-json-file#entry111comment</comments>
      <pubDate>Wed, 13 Jul 2022 02:02:42 +0900</pubDate>
    </item>
    <item>
      <title>[TIL] Klip, EIP-5114</title>
      <link>https://beeimp.tistory.com/entry/TIL-Klip-EIP-5114</link>
      <description>&lt;h1&gt;[TIL] Klip, EIP-5114&lt;/h1&gt;
&lt;h2&gt;날짜&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;2022.07.10&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;목표&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input checked=&quot;&quot; disabled=&quot;&quot; type=&quot;checkbox&quot;&gt; SBT 구현을 위한 학습&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;내용&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;h3&gt;KaKao Klip - App2App API&lt;/h3&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Authentication&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;기본적으로 인증이 필요하지 않음&lt;/li&gt;
&lt;li&gt;API 요청시 - Request Key를 발급하여 사용&lt;/li&gt;
&lt;li&gt;Request Key 발급 절차&lt;ol&gt;
&lt;li&gt;prepare API를 통해 인증 또는 서명할 내용을 전달&lt;ul&gt;
&lt;li&gt;응답으로 Request Key를 전달&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;전달받은 Request Key를 이용하여 Deep Link를 호출하고, 모바일 카카오톡 더보기 탭에 있는 Klip 실행&lt;/li&gt;
&lt;li&gt;처리 결과는 Result API를 통해 polling&lt;ul&gt;
&lt;li&gt;Query 파라미터 Request Key에 어떤 요청에 대한 처리 결과를 얻고자 하는지 전달&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Ethereum - EIP-5114 : SoulBound Token&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;SoulBound Token : 거래 불가능 NFT&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-solidity&quot;&gt;interface IERC5114 {
    // fired anytime a new instance of this token is minted
    // this event **MUST NOT** be fired twice for the same `tokenId`
    event Mint(uint256 indexed tokenId, address indexed nftAddress, uint256 indexed nftTokenId);

    // returns the NFT token that owns this token.
    // this function **MUST** throw if the token hasn&amp;#39;t been minted yet
    // this function **MUST** always return the same result every time it is called after it has been minted
    // this function **MUST** return the same value as found in the original `Mint` event for the token
    function ownerOf(uint256 index) external view returns (address nftAddress, uint256 nftTokenId);

    // returns a censorship resistant URI with details about this token collection
    // the metadata returned by this is merged with the metadata return by `tokenUri(uint256)`
    // the collectionUri **MUST** be immutable and content addressable (e.g., ipfs://)
    // the collectionUri **MUST NOT** point at mutable/censorable content (e.g., https://)
    // data from `tokenUri` takes precedence over data returned by this method
    // any external links referenced by the content at `collectionUri` also **MUST** follow all of the above rules
    function collectionUri() external view returns (string collectionUri);

    // returns a censorship resistant URI with details about this token instance
    // the tokenUri **MUST** be immutable and content addressable (e.g., ipfs://)
    // the tokenUri **MUST NOT** point at mutable/censorable content (e.g., https://)
    // data from this takes precedence over data returned by `collectionUri`
    // any external links referenced by the content at `tokenUri` also **MUST** follow all of the above rules
    function tokenUri(uint256 tokenId) external view returns (string tokenUri);
}&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;결론&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;클레이튼에서 SBT 구현을 위해 이더리움 EIP에서 SBT 관련 부분을 공부했습니다.&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>I Learned/TIL</category>
      <category>EIP-5114</category>
      <category>Ethereum</category>
      <category>Kakao</category>
      <category>Klip</category>
      <category>sbt</category>
      <category>SoulBound</category>
      <author>beeimp</author>
      <guid isPermaLink="true">https://beeimp.tistory.com/110</guid>
      <comments>https://beeimp.tistory.com/entry/TIL-Klip-EIP-5114#entry110comment</comments>
      <pubDate>Sun, 10 Jul 2022 01:54:48 +0900</pubDate>
    </item>
    <item>
      <title>[TIL] Nest.js 프로바이더와, React-Native 안드로이드 설정</title>
      <link>https://beeimp.tistory.com/entry/TIL-Nestjs-%ED%94%84%EB%A1%9C%EB%B0%94%EC%9D%B4%EB%8D%94%EC%99%80-React-Native-%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C-%EC%84%A4%EC%A0%95</link>
      <description>&lt;h1&gt;[TIL] Nest.js 프로바이더와, React-Native 안드로이드 설정&lt;/h1&gt;
&lt;h2&gt;날짜&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;2022.01.01&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;목표&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input checked=&quot;&quot; disabled=&quot;&quot; type=&quot;checkbox&quot;&gt; Nest.js 학습&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;내용&lt;/h2&gt;
&lt;h3&gt;Nest.js - Provider&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Provider : 앱이 제공하는 핵심 기능인 비즈니스 로직 수행&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Service, Repository, Factory, Helper 등&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;@injectable&lt;/code&gt; 데코레이터 사용&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;다른 어떤 Nest 컴포넌트에서도 주입 가능해짐&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-tsx&quot;&gt;import { Injectable } from &amp;#39;@nestjs/common&amp;#39;;

@Injectable()
export class UsersService {
  ...

remove(id: number) {
  return `This action removes a #${id} user`;
}
}&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;사용&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-tsx&quot;&gt;  @Controller(&amp;#39;users&amp;#39;)
  export class UsersController {
    constructor(private readonly usersService: UsersService) {}
      ...

      @Delete(&amp;#39;:id&amp;#39;)
      remove(@Param(&amp;#39;id&amp;#39;) id: string) {
        return this.usersService.remove(+id);
      }
  }&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;React-Native - 안드로이드 설정&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;OS - macOS ( m1 )&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;기본 설치&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;  # Node &amp;amp; Watchman
  $ brew install node
  $ brew install watchman&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Java Development Kit&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;  $ brew tap homebrew/cask-versions
  $ brew install --cask zulu11&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Android Studio 개발 환경 설정&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Android SDK&lt;/li&gt;
&lt;li&gt;Android SDK Platform&lt;/li&gt;
&lt;li&gt;Android Virtual Device&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;SDK Platforms 설치&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Appearance &amp;amp; Behavior → System Settings → Android SDK → Click ‘Show Package Details’&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Android SDK Platform 31&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ARM 64 v8a System Image&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Google APIs ARM 64 v8a System Image&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;ANDROID_SDK_ROOT 환경 변수 설정&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;  $ export ANDROID_SDK_ROOT=$HOME/Library/Android/sdk
  $ export PATH=$PATH:$ANDROID_SDK_ROOT/emulator
  $ export PATH=$PATH:$ANDROID_SDK_ROOT/platform-tools&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;project 생성&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;  $ npx react-native init AwesomeTSProject # --template react-native-template-typescript&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;서버 실행&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;  $ npx react-native start&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;앱 실행&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;  $ npm run android&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;결론&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;API 31 버전이 기본으로 되어 있었고, m1이라 약간 설치가 달랐습니다. API 32 버전을 사용하고 arm 관련 설치 해주니 잘 동작했습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;참조링크&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://wikidocs.net/148511&quot;&gt;https://wikidocs.net/148511&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>I Learned/TIL</category>
      <category>Android</category>
      <category>mobile</category>
      <category>Nest.js</category>
      <category>provider</category>
      <category>react-native</category>
      <author>beeimp</author>
      <guid isPermaLink="true">https://beeimp.tistory.com/109</guid>
      <comments>https://beeimp.tistory.com/entry/TIL-Nestjs-%ED%94%84%EB%A1%9C%EB%B0%94%EC%9D%B4%EB%8D%94%EC%99%80-React-Native-%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C-%EC%84%A4%EC%A0%95#entry109comment</comments>
      <pubDate>Fri, 8 Jul 2022 02:03:53 +0900</pubDate>
    </item>
    <item>
      <title>[TIL] Nest.js 컨트롤러 부분 학습</title>
      <link>https://beeimp.tistory.com/entry/TIL-Nestjs-%EC%BB%A8%ED%8A%B8%EB%A1%A4%EB%9F%AC-%EB%B6%80%EB%B6%84-%ED%95%99%EC%8A%B5</link>
      <description>&lt;h1&gt;[TIL] Nest.js 컨트롤러 부분 학습&lt;/h1&gt;
&lt;h2&gt;날짜&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;2022.07.06.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;목표&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input checked=&quot;&quot; disabled=&quot;&quot; type=&quot;checkbox&quot;&gt; Nest.js 학습&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;내용&lt;/h2&gt;
&lt;h3&gt;Nest.js - Controller&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;MVC 패턴에서 Controller에 해당&lt;ul&gt;
&lt;li&gt;Request로 받은 데이터를 처리하고 결과를 Response하는 인터페이스 역할&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Nest.js - Routing&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;데코레이터 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-jsx&quot;&gt;@Get(&amp;#39;/hello&amp;#39;)
getHello(): string {
  return this.appService.getHello();
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;와일드카드 사용 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-jsx&quot;&gt;@Get(&amp;#39;he*lo&amp;#39;)
getHello(): string {
  return this.appService.getHello();
}&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Nest.js - Request/Response Object&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-tsx&quot;&gt;import { Request, Response } from &amp;#39;express&amp;#39;;
import { Controller, Get, Req, Res, Param } from &amp;#39;@nestjs/common&amp;#39;;
import { AppService } from &amp;#39;./app.service&amp;#39;;

@Controller()
export class AppController {
  constructor(private readonly appService: AppService) {}

  @Get(&amp;#39;:id&amp;#39;)
  getHello(
        @Param(&amp;#39;id&amp;#39;) id: string, // Parameter
        @Req() req: Request, 
        @Res() res: Response
    ): string {
    res.send(this.appService.getHello(id));
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Nest.js - Custom Header&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-tsx&quot;&gt;import { Header } from &amp;#39;@nestjs/common&amp;#39;;

@Header(&amp;#39;Key&amp;#39;, &amp;#39;Value&amp;#39;)
@Get()
getHello(): string {
  return this.appService.getHello();
}

// 또는

@Header(&amp;#39;Key&amp;#39;, &amp;#39;Value&amp;#39;)
@Get()
getHello(
    @Res() res: Response
): string {
    res.header(&amp;#39;Key&amp;#39;, &amp;#39;Value&amp;#39;);
  res.send(this.appService.getHello());
}&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Nest.js - Redirection&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;클라이언트를 다른 페이지로 이동시키고 싶은 경우 사용&lt;/li&gt;
&lt;li&gt;HTTP code - 301, 307, 308&lt;ul&gt;
&lt;li&gt;아니면 제대로 동작 안할 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-tsx&quot;&gt;@Get(&amp;#39;redirect/docs&amp;#39;)
@Redirect(&amp;#39;https://docs.nestjs.com&amp;#39;, 302)
getDocs(@Query(&amp;#39;version&amp;#39;) version) {
  if (version &amp;amp;&amp;amp; version === &amp;#39;5&amp;#39;) {
    return { url: &amp;#39;https://docs.nestjs.com/v5/&amp;#39; };
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Nest.js - Sub-Domain Routing&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;하위 도메인 설정&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-tsx&quot;&gt;  @Controller({ host: &amp;#39;api.beeimp.com&amp;#39; }) // 하위 도메인 요청 처리 설정
  export class ApiController {
    @Get() // 같은 루트 경로
    index(): string {
      return &amp;#39;BeeImp API&amp;#39;; // 다른 응답
    }
  }&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Nest.js - Payload (@Body)&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-tsx&quot;&gt;// DTO(Data Transfer Object) 정의
export class CreateUserDto {
  name: string;
  email: string;
}

@Post()
create(@Body() createUserDto: CreateUserDto) {
  const { name, email } = createUserDto;

  return `유저를 생성 - 이름: ${name}, 이메일: ${email}`;
}&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;결론&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Nest.js 조금만 더 공부하면 편하게 API를 구축할 수 있을 것 같다는 생각이 들었습니다.&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>I Learned/TIL</category>
      <category>Controller</category>
      <category>header</category>
      <category>Nest.js</category>
      <category>payload</category>
      <category>redirection</category>
      <category>Routing</category>
      <author>beeimp</author>
      <guid isPermaLink="true">https://beeimp.tistory.com/108</guid>
      <comments>https://beeimp.tistory.com/entry/TIL-Nestjs-%EC%BB%A8%ED%8A%B8%EB%A1%A4%EB%9F%AC-%EB%B6%80%EB%B6%84-%ED%95%99%EC%8A%B5#entry108comment</comments>
      <pubDate>Wed, 6 Jul 2022 23:45:28 +0900</pubDate>
    </item>
    <item>
      <title>[TIL] Nest.js Decoration</title>
      <link>https://beeimp.tistory.com/entry/TIL-Nestjs-Decoration</link>
      <description>&lt;h1&gt;[TIL] Nest.js Decoration&lt;/h1&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;날짜&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;2022.07.04&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;목표&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;input disabled=&quot;disabled&quot; type=&quot;checkbox&quot; /&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;내용&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Nest.js - 데코레이터&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;파이썬의 데코레이터나 자바의 어노테이션과 유사&lt;/li&gt;
&lt;li&gt;클래스, 메서드, 접근자, 프로퍼티, 매개변수에 적용 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;JS - +로 숫자형 변환&lt;/h3&gt;
&lt;pre class=&quot;sqf&quot;&gt;&lt;code&gt;const str = '123';

console.log(typeof str); // string
console.log(typeof Number(str)); // number
console.log(typeof parseInt(str)); // number

console.log(typeof +str); // number&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;결론&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;nest.js의 데코레이션을 보면서 자바 스프링이 생각났습니다. 이미 스프링 조금 공부해봤기에 비교적 쉽게 배울 수 있을 것 같습니다.&lt;/li&gt;
&lt;li&gt;JS에서 +로 숫자형으로 바로 변환 가능함을 알게 되었습니다.&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>I Learned/TIL</category>
      <category>decoration</category>
      <category>javascript</category>
      <category>Nest.js</category>
      <author>beeimp</author>
      <guid isPermaLink="true">https://beeimp.tistory.com/107</guid>
      <comments>https://beeimp.tistory.com/entry/TIL-Nestjs-Decoration#entry107comment</comments>
      <pubDate>Tue, 5 Jul 2022 01:03:47 +0900</pubDate>
    </item>
  </channel>
</rss>