<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>TL&amp;amp;D</title>
    <link>https://gmyankee.tistory.com/</link>
    <description>컴퓨터, 프로그래밍, 블록체인, S/W, A.I, Python, JavaScript</description>
    <language>ko</language>
    <pubDate>Mon, 20 Apr 2026 06:51:33 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>TL&amp;amp;D</managingEditor>
    <image>
      <title>TL&amp;amp;D</title>
      <url>https://tistory1.daumcdn.net/tistory/1742565/attach/e8b342d814fa4874bf070ddb1db17854</url>
      <link>https://gmyankee.tistory.com</link>
    </image>
    <item>
      <title>유튜브 썸네일 추출 및 다운로드 부터 리사이징까지</title>
      <link>https://gmyankee.tistory.com/entry/%EC%9C%A0%ED%8A%9C%EB%B8%8C-%EC%8D%B8%EB%84%A4%EC%9D%BC-%EC%B6%94%EC%B6%9C-%EB%B0%8F-%EB%8B%A4%EC%9A%B4%EB%A1%9C%EB%93%9C-%EB%B6%80%ED%84%B0-%EB%A6%AC%EC%82%AC%EC%9D%B4%EC%A7%95%EA%B9%8C%EC%A7%80</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://tools.tlnd.cc/ko/youtube-thumbnail-downloader-resizer&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://tools.tlnd.cc/ko/youtube-thumbnail-downloader-resizer&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1754041739417&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;유튜브 썸네일 다운로드, 크기 조절 및 확장자 변환 - 무료 썸네일 추출기&quot; data-og-description=&quot;유튜브 영상 썸네일을 손쉽게 다운로드하고 원하는 크기와 다양한 형식(JPG, PNG, TIFF, WEBP)으로 변환하세요. 빠르고 간편한 무료 온라인 도구로 고화질 썸네일 이미지를 추출하고 즉시 다운로드 &quot; data-og-host=&quot;tools.tlnd.cc&quot; data-og-source-url=&quot;https://tools.tlnd.cc/ko/youtube-thumbnail-downloader-resizer&quot; data-og-url=&quot;https://tools.tlnd.cc/ko/youtube-thumbnail-downloader-resizer&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/clOEsp/hyZrsbJHX3/iMfKfFbIoifAKrUbwHaBu0/img.png?width=800&amp;amp;height=420&amp;amp;face=0_0_800_420&quot;&gt;&lt;a href=&quot;https://tools.tlnd.cc/ko/youtube-thumbnail-downloader-resizer&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://tools.tlnd.cc/ko/youtube-thumbnail-downloader-resizer&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/clOEsp/hyZrsbJHX3/iMfKfFbIoifAKrUbwHaBu0/img.png?width=800&amp;amp;height=420&amp;amp;face=0_0_800_420');&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;유튜브 썸네일 다운로드, 크기 조절 및 확장자 변환 - 무료 썸네일 추출기&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;유튜브 영상 썸네일을 손쉽게 다운로드하고 원하는 크기와 다양한 형식(JPG, PNG, TIFF, WEBP)으로 변환하세요. 빠르고 간편한 무료 온라인 도구로 고화질 썸네일 이미지를 추출하고 즉시 다운로드&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;tools.tlnd.cc&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;641&quot; data-origin-height=&quot;323&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bhoNXj/btsPDLzxVhz/ariL9RKlKwnI1tCbofrAi1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bhoNXj/btsPDLzxVhz/ariL9RKlKwnI1tCbofrAi1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bhoNXj/btsPDLzxVhz/ariL9RKlKwnI1tCbofrAi1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbhoNXj%2FbtsPDLzxVhz%2FariL9RKlKwnI1tCbofrAi1%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;641&quot; height=&quot;323&quot; data-origin-width=&quot;641&quot; data-origin-height=&quot;323&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;placeholder&lt;/b&gt; 내용을 보면 유튜브 쇼츠&lt;b&gt;(youtube&lt;/b&gt; &lt;b&gt;shorts)&lt;/b&gt; 도 지원하고 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;사용방법&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;338&quot; data-origin-height=&quot;270&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cEUwya/btsPF1HKhsc/KeGLZxVcXfCsXfoeIWdXgK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cEUwya/btsPF1HKhsc/KeGLZxVcXfCsXfoeIWdXgK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cEUwya/btsPF1HKhsc/KeGLZxVcXfCsXfoeIWdXgK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcEUwya%2FbtsPF1HKhsc%2FKeGLZxVcXfCsXfoeIWdXgK%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;338&quot; height=&quot;270&quot; data-origin-width=&quot;338&quot; data-origin-height=&quot;270&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;썸네일 추출을 하고자 하는 영상을 우클릭해서 주소를 복사하거나&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주소창에서 URL을 복사하거나 플레이중인 영상에서 우클릭을 통해 동영상 링크 공유를 해서 URL을 어떻게해서든 획득했다면&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;621&quot; data-origin-height=&quot;794&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ug5Rl/btsPDW12aU4/tv1vvpzQSTHhEaFSd9GSEK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ug5Rl/btsPDW12aU4/tv1vvpzQSTHhEaFSd9GSEK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ug5Rl/btsPDW12aU4/tv1vvpzQSTHhEaFSd9GSEK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fug5Rl%2FbtsPDW12aU4%2Ftv1vvpzQSTHhEaFSd9GSEK%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;621&quot; height=&quot;794&quot; data-origin-width=&quot;621&quot; data-origin-height=&quot;794&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 추출이 진행됩니다&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;기본적으로 이미지는 HD (1280x720) 크기로 적용되고 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이미지를 클릭하면 변환된 원본 이미지가 새탭으로 열리기도 하지만&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;적용 다운로드 버튼을 통해 진행해볼수도 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <author>TL&amp;amp;D</author>
      <guid isPermaLink="true">https://gmyankee.tistory.com/393</guid>
      <comments>https://gmyankee.tistory.com/entry/%EC%9C%A0%ED%8A%9C%EB%B8%8C-%EC%8D%B8%EB%84%A4%EC%9D%BC-%EC%B6%94%EC%B6%9C-%EB%B0%8F-%EB%8B%A4%EC%9A%B4%EB%A1%9C%EB%93%9C-%EB%B6%80%ED%84%B0-%EB%A6%AC%EC%82%AC%EC%9D%B4%EC%A7%95%EA%B9%8C%EC%A7%80#entry393comment</comments>
      <pubDate>Fri, 1 Aug 2025 18:57:33 +0900</pubDate>
    </item>
    <item>
      <title>Cloudflare 내 서비스의 캐시는 잘 동작하는 걸까?</title>
      <link>https://gmyankee.tistory.com/entry/Cloudflare-%EB%82%B4-%EC%84%9C%EB%B9%84%EC%8A%A4%EC%9D%98-%EC%BA%90%EC%8B%9C%EB%8A%94-%EC%9E%98-%EB%8F%99%EC%9E%91%ED%95%98%EB%8A%94-%EA%B1%B8%EA%B9%8C</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Cloudflare 를 사용하는 많은 사용자들이 생각보다 놓치고 있는 부분입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;326&quot; data-origin-height=&quot;28&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xr9S3/btsGct9BkQF/Kb23NJNfvoTGjuvriLp9qK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xr9S3/btsGct9BkQF/Kb23NJNfvoTGjuvriLp9qK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xr9S3/btsGct9BkQF/Kb23NJNfvoTGjuvriLp9qK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fxr9S3%2FbtsGct9BkQF%2FKb23NJNfvoTGjuvriLp9qK%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;326&quot; height=&quot;28&quot; data-origin-width=&quot;326&quot; data-origin-height=&quot;28&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Cf-Cache-Status 는 기본적으로 HIT 가 설정되지 않는 이상 대부분 캐싱이 적중하지 않았다는 의미입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대표적으로 DYNAMIC 은 Cloudflare가 판단할때 캐싱할 가치가 없다고 판단한건데 대표적인 이유는 공식문서에서 기재되어 있습니다.&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;829&quot; data-origin-height=&quot;661&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/XDMEV/btsGefvvY7f/j0DkCm1TSTHgWsyWpg36IK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/XDMEV/btsGefvvY7f/j0DkCm1TSTHgWsyWpg36IK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/XDMEV/btsGefvvY7f/j0DkCm1TSTHgWsyWpg36IK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FXDMEV%2FbtsGefvvY7f%2Fj0DkCm1TSTHgWsyWpg36IK%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;829&quot; height=&quot;661&quot; data-origin-width=&quot;829&quot; data-origin-height=&quot;661&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 이미지 및 링크에 명시된 확장자의 경우 별도의 설정 없이도 기본적으로 캐싱에 반드시 적중합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 첫줄 내용을 읽어보면 HTML은 기본적으로 cache 하지 않는다고 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이유는 동적 컨텐츠가 많기 때문이겠죠?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이걸 해결하기 위해서는 cloudflare 에 등록한 도메인별 캐시 설정이 필요합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1078&quot; data-origin-height=&quot;715&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/74cuN/btsGcJdqQM5/tgisCPkmBngcyljkDkKAGK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/74cuN/btsGcJdqQM5/tgisCPkmBngcyljkDkKAGK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/74cuN/btsGcJdqQM5/tgisCPkmBngcyljkDkKAGK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F74cuN%2FbtsGcJdqQM5%2FtgisCPkmBngcyljkDkKAGK%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;1078&quot; height=&quot;715&quot; data-origin-width=&quot;1078&quot; data-origin-height=&quot;715&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;캐시 룰을 위와 같이 설정합니다.&lt;/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;gt; 캐시에 적합&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;에지 TTL -&amp;gt; 캐시 제어 헤더가 있는 경우 사용하고, 없는 경우 기본 Cloudflare 캐싱 동작을 사용합니다.&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;에지 TTL의 2번째를 선택하는 이유는 코드로 따지면 override 가 가능해진다는 의미입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자가 정의한 cache-control / cdn-cache-control / cloudflare-cdn-cache-control 헤더를 선언해서 사용자가 정의한걸 먼저 따르게 되는건데 없을땐 기본 동작으로 할당하는거죠.&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번째의 경우는 코드나 서버 설정의 별도 처리 없이 cloudflare 프록시내에서 강제로 설정하게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 Edge Cache를 설정하지 않은 경우 cloudflare의 pages 및 worker 등에서 응답이 굉장히 느립니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히나 한국의 경우 Enterprise 요금제를 사용하지 않을 경우 ICN(인천) 리전의 연산 및 응답을 받지 못하기 때문에 AWS 같은 서비스 대비 가격 말고는 이점이 없는 수준이 되는거죠.&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;하지만 Edge TTL을 사용한다면 Cloudfront 급의 속도까진 아니지만 그와 유사한 것을 무료로 사용할 수 있게됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Trouble Shooting</category>
      <author>TL&amp;amp;D</author>
      <guid isPermaLink="true">https://gmyankee.tistory.com/390</guid>
      <comments>https://gmyankee.tistory.com/entry/Cloudflare-%EB%82%B4-%EC%84%9C%EB%B9%84%EC%8A%A4%EC%9D%98-%EC%BA%90%EC%8B%9C%EB%8A%94-%EC%9E%98-%EB%8F%99%EC%9E%91%ED%95%98%EB%8A%94-%EA%B1%B8%EA%B9%8C#entry390comment</comments>
      <pubDate>Sat, 30 Mar 2024 00:30:17 +0900</pubDate>
    </item>
    <item>
      <title>Remix.js Dark Theme 설정</title>
      <link>https://gmyankee.tistory.com/entry/Remixjs-Dark-Theme-%EC%84%A4%EC%A0%95</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Nuxt3의 nitro가 Cloudflare Pages Functions에서 GET 메소드 이외의 처리를 하지 않은 크나큰 충격으로 Vercel을 손절하고 갈아탄 Remix도 역시 나사가 몇가지씩 빠져있었습니다.&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;Vue Svelte Astro Nuxt2 Nuxt3 Sveltekit 등 다양한 Reactive Framework를 사용해왔지만, React는 JSX 문법이 싫어서 항상 꺼려왔는데 대부분의 프레임워크가 Vercel이 관여하고 있어서 결국 Remix로 돔황쳤습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Nuxt3와 Astro의 강제 주입식 문법으로 인해서 React의 함수들이 어색하진 않았는데&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리믹스의 문제점은 크게 2가지가 나타났습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;b&gt;뒤로가기 캐싱&lt;/b&gt; 안됨. 일부러 그런건지는 모르겠지만 이전페이지 데이터를 다시 불러옵니다. 이럴거면 굳이 Hydrate는 뭐하러 하나 싶을정도...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;b&gt;Cookie 관리의 잘못된 예제&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;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;다크테마는 흔히 쿠키를 통해 저장해서 사용을 많이 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 React 진영에는 확실히 Frontend 개발자분들의 생태계가 많다보니 서버로의 처리를 위임하는 듯한 예제가 좀 많았는데,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 예시로 다크 테마의 예제가 있었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대표적으로 구글 검색시 제일 먼저 노출되는 예제 입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.mattstobbs.com/remix-dark-mode/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://www.mattstobbs.com/remix-dark-mode/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1675849883115&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;The Complete Guide to Dark Mode with Remix&quot; data-og-description=&quot;Dark Mode can be surprisingly tricky to add with any framework. But Remix gives us some unique tools to deliver a fantastic user experience. In this post, we'll look at how Remix allows us to use the platform to provide a perfect theming solution.&quot; data-og-host=&quot;www.mattstobbs.com&quot; data-og-source-url=&quot;https://www.mattstobbs.com/remix-dark-mode/&quot; data-og-url=&quot;https://www.mattstobbs.com/remix-dark-mode/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/rjikG/hyRxPskMD4/5oLv7MDdk7N3WXJD61sy41/img.png?width=1280&amp;amp;height=675&amp;amp;face=0_0_1280_675,https://scrap.kakaocdn.net/dn/caPbwg/hyRxYv26js/c2bCkeruRpsmxDBoYpsd1k/img.png?width=1280&amp;amp;height=675&amp;amp;face=0_0_1280_675&quot;&gt;&lt;a href=&quot;https://www.mattstobbs.com/remix-dark-mode/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.mattstobbs.com/remix-dark-mode/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/rjikG/hyRxPskMD4/5oLv7MDdk7N3WXJD61sy41/img.png?width=1280&amp;amp;height=675&amp;amp;face=0_0_1280_675,https://scrap.kakaocdn.net/dn/caPbwg/hyRxYv26js/c2bCkeruRpsmxDBoYpsd1k/img.png?width=1280&amp;amp;height=675&amp;amp;face=0_0_1280_675');&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;The Complete Guide to Dark Mode with Remix&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Dark Mode can be surprisingly tricky to add with any framework. But Remix gives us some unique tools to deliver a fantastic user experience. In this post, we'll look at how Remix allows us to use the platform to provide a perfect theming solution.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.mattstobbs.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 외에도 Codepen등 클라우드 코드 예시도 비슷한 양상이었습니다.&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;1. loader를 이용해 request header로 부터 Cookie 응답을 반환&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 1번의 쿠키를 state 또는 context 등을 통해 메모리에 적재&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 테마 업데이트를 위해 action 으로 API 생성&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. fetcher.Form 으로 post 요청해 action API에 쿠키 변경을 적용&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5.&amp;nbsp;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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2번까진 괜찮았는데 도대체 어떻게 생각을하면 서버로 요청을 보내서 쿠키를 적용시킬 생각을 하는지 신기합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇다고 쿠키에 httponly secure samesite를 설정할것도 아니면서 말이죠...&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;아마 킹리적 갓심으로는 Remix에서 제공해주는 Cookie 와 Session 이 있기 때문에 그러한 발상이 있었을거라고 추측됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 제가 리액트를 리믹스를 통해 처음써봤기 때문에 더 유연한 작성이 있을 수 있으니 그점은 양해해주세요 (밑밥까는중)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시작하기전 개선되는 프로세스를 나열해보면&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. loader에서 request Header에 있는 Cookie 정보를 읽어온 뒤 이를 json으로 반환&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 1번에서 획득한 다크테마 정보를 state에 적재하고 context를 통해 global 상태로 적용&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. context 바인딩에서 획득한 다크테마 상태값과 토글 함수를 이용해 쿠키 적용 및 상태 적용&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;1. context / hook 작성&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. root.tsx에 적용 끝&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;1. Context 및 Custom Hook작성&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저는 app/contexts 라는 폴더를 만들어 &lt;b&gt;app/contexts/theme.ts&lt;/b&gt; 파일에 작성하였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;폴더의 경로나 위치가 강제되지 않으니 유연하게 작성하시면 됩니다.&lt;/p&gt;
&lt;pre id=&quot;code_1675850726978&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import { createContext, useState } from &quot;react&quot;;

interface ThemeContextType {
    toggleTheme(): void
    isDarkMode: boolean
}

const DARK_MODE_KEY = 'REMIX:DARK'
const NEVER = 'Fri, 31 Dec 9999 23:59:59 GMT' // MDN:: https://developer.mozilla.org/en-US/docs/Web/API/Document/cookie#example_3_do_something_only_once

function setCookie(name: string, value: string | boolean, ttl: number = 0) {
    const expire = new Date();
    expire.setDate(expire.getTime() + ttl);
    document.cookie = `${name}=${value}; expires=${ttl &amp;gt; 0 ? expire.toUTCString() : NEVER};`
}

export const ThemeContext = createContext&amp;lt;ThemeContextType&amp;gt;({
  isDarkMode: false, toggleTheme: () =&amp;gt; { }
})

export function useTheme(defaultValue: boolean = false): [boolean, ()=&amp;gt; void] {
    const [darkTheme, setDarkTheme] = useState(defaultValue);

    function toggleTheme(): void {
        setCookie(DARK_MODE_KEY, !darkTheme)
        setDarkTheme(!darkTheme)
    }

    return [darkTheme, toggleTheme]
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;go언어에서는 소문자 시작의 함수명은 private 해서 대문자로 쓰고싶지만... 리액트 공식문서에서 &lt;a href=&quot;https://ko.reactjs.org/docs/hooks-custom.html#using-a-custom-hook&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;useFunction 형식을 사용하라고 권고&lt;/a&gt;해서 어쩔수없이 useTheme 입니다.&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;Context API 예시들을 보면, Reducer를 따로 작성하시는 분들이 보이더군요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금은 사장되서 잘 안쓰이는 Vue2 시절 Vuex의 Mutation Action을 작성하는 느낌이었는데, 오히려 장황해보이는 것 같기도하고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;useState를 이용하면 굳이 필요없길래 그냥 대충 만들었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금 이글을 보고 따라하시는 여러분도 걍 복붙해서 쓰시면 짧고 굵고 얼마나 좋나여&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;딱히 코드 설명할게 없어서 패스...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&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. root.tsx 적용&lt;/b&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1675850649381&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// root.tsx
import { json, LoaderArgs } from &quot;@remix-run/cloudflare&quot;;
import { ThemeContext, useTheme } from &quot;./contexts/theme&quot;;

export const loader = async ({ request }: LoaderArgs) =&amp;gt; {
  let isDarkMode = false
  const cookies = request.headers.get('cookie')?.split('; ')
  const index = cookies?.findIndex(str =&amp;gt; str.includes(DARK_MODE_KEY)) || -1;
  if (index &amp;gt; -1 &amp;amp;&amp;amp; cookies) {
    const val = cookies[index].split('=')[1]
    isDarkMode = val === 'true' ? true : false
  }
  return json({ isDarkMode })
}

export default function App() {
  const { isDarkMode } = useLoaderData&amp;lt;typeof loader&amp;gt;();
  const [darkTheme, toggleTheme] = useTheme(isDarkMode);

  return (
    &amp;lt;html lang=&quot;ko&quot;&amp;gt;
      &amp;lt;head&amp;gt;
        &amp;lt;Meta /&amp;gt;
        &amp;lt;Links /&amp;gt;
      &amp;lt;/head&amp;gt;
      &amp;lt;StateContext.Provider value={{isDarkMode: darkTheme, toggleTheme}}&amp;gt;
        &amp;lt;body className={darkTheme ? 'dark' : ''}&amp;gt;
          // ... 하위 컴포넌트
          &amp;lt;ScrollRestoration /&amp;gt;
          &amp;lt;Scripts /&amp;gt;
          &amp;lt;LiveReload /&amp;gt;
        &amp;lt;/body&amp;gt;
      &amp;lt;/StateContext.Provider&amp;gt;
    &amp;lt;/html&amp;gt;
  );
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;root에서는 &lt;b&gt;useLoaderData&lt;/b&gt; 를 통해 loader 함수에서 &lt;b&gt;cookie&lt;/b&gt; 정보를 읽고, 이를 &lt;b&gt;JSON&lt;/b&gt;으로 반환하게 하였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 과정을 통해 페이지 &lt;b&gt;첫 접근(새로고침 포함)&lt;/b&gt;시&lt;b&gt; 다크테마&lt;/b&gt;가 &lt;b&gt;활성&lt;/b&gt;상태인지 &lt;b&gt;비 활성&lt;/b&gt;상태인지 구분할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;useTheme&lt;/b&gt; 는 위에서 받아온 정보를 기본값으로 넣어주고, darkTheme 및 toggleTheme를 context 로 전달합니다.&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;b&gt;toggleTheme()&lt;/b&gt; 를 호출하면 &lt;b&gt;body태그 class에 dark&lt;/b&gt; 가 적용되는 것을 볼 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;Remix의 loader가 하위 요청으로 발생하는지 SSR 접근시 동시에 먼저 처리하고 UI를 렌더링하는지 직접 디스코드에서 질문하였는데 1분만에 답변을 받았습니다.&lt;br /&gt;&lt;br /&gt;결론은 하위 요청은 발생하지 않고, SSR 접근시 먼저 처리후 UI를 렌더링 한다고 합니다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;이렇게 짧게 끝날걸 예제들은 뭔 꼴랑 다크테마 설정하는 쿠키를 가지고 어떻게해서든 기어코 죽어라 프레임워크 내장함수좀 써보겠다고 api action 만들고 fetcher 선언해서 fetcher.Form 으로 또 요청해가지고 괜히 불러왔던 데이터까지 다 새로 요청하고 요청이랑 서버 부하만 늘리고 있는 이상한 예제가 많아서 작성해보았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 나중에 프로젝트 생성할때마다 복붙하기 귀찮은 면도 없잖아 있는 것 같군요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론 서버로 요청해서 처리해야하는 쿠키들도 존재합니다. httponly secure samesite 등의 설정을하여 악의적인 사용자가 javascript를 이용해 세션이나 타 사이트에서 접근하지 못하게 하는 요청의 경우는 다른 예제들처럼 서버로 요청해서 쿠키를 설정하는 것이 올바른 선택지입니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 보안 설정해도 매우 쉽게 돚거할 수 있어서 그냥 &lt;s&gt;ㅈ밥거르기 용으로&lt;/s&gt; 설정할때 써먹는 방법입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Tutorial &amp;amp; Training/JavaScript</category>
      <category>react</category>
      <category>Remix</category>
      <category>다크테마</category>
      <category>리믹스</category>
      <category>리액트</category>
      <category>설정</category>
      <category>쿠키</category>
      <author>TL&amp;amp;D</author>
      <guid isPermaLink="true">https://gmyankee.tistory.com/388</guid>
      <comments>https://gmyankee.tistory.com/entry/Remixjs-Dark-Theme-%EC%84%A4%EC%A0%95#entry388comment</comments>
      <pubDate>Wed, 8 Feb 2023 21:15:24 +0900</pubDate>
    </item>
    <item>
      <title>메이플 커마 - 메애기 코디 분석 및 공유 서비스 공개</title>
      <link>https://gmyankee.tistory.com/entry/%EB%A9%94%EC%9D%B4%ED%94%8C-%EC%BB%A4%EB%A7%88-%EB%A9%94%EC%95%A0%EA%B8%B0-%EC%BD%94%EB%94%94-%EB%B6%84%EC%84%9D-%EB%B0%8F-%EA%B3%B5%EC%9C%A0-%EC%84%9C%EB%B9%84%EC%8A%A4-%EA%B3%B5%EA%B0%9C</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://maple.curma.cc&quot;&gt;https://maple.curma.cc&lt;/a&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1674969902360&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;메이플 코디 공유&quot; data-og-description=&quot;메이플스토리의 다양한 유저들의 코디를 확인하고 내 코디를 공유해보세요! 가장 많이 사용한 코디부터 같은 부위를 사용한 다른 코디까지 지금 바로 만나 보실수 있어요!&quot; data-og-host=&quot;maple.curma.cc&quot; data-og-source-url=&quot;https://maple.curma.cc&quot; data-og-url=&quot;https://maple.curma.cc&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/pXrZG/hyRq5Bq9CP/kVhI5Rnkj1N4YoI6ZKw7w1/img.png?width=800&amp;amp;height=420&amp;amp;face=0_0_800_420,https://scrap.kakaocdn.net/dn/bjPQ4X/hyRq94UFL1/EWBKRt7S6J9FOTO8wlxyEK/img.png?width=800&amp;amp;height=420&amp;amp;face=0_0_800_420&quot;&gt;&lt;a href=&quot;https://maple.curma.cc&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://maple.curma.cc&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/pXrZG/hyRq5Bq9CP/kVhI5Rnkj1N4YoI6ZKw7w1/img.png?width=800&amp;amp;height=420&amp;amp;face=0_0_800_420,https://scrap.kakaocdn.net/dn/bjPQ4X/hyRq94UFL1/EWBKRt7S6J9FOTO8wlxyEK/img.png?width=800&amp;amp;height=420&amp;amp;face=0_0_800_420');&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;메이플 코디 공유&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;메이플스토리의 다양한 유저들의 코디를 확인하고 내 코디를 공유해보세요! 가장 많이 사용한 코디부터 같은 부위를 사용한 다른 코디까지 지금 바로 만나 보실수 있어요!&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;maple.curma.cc&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메이플 커마는 메이플스토리 캐릭터의 코디 정보를 분석 및 공유하는 써드파티 서비스입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&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;개발 계기&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;메이플 지지의 코디 컬렉션은 극히 일부 기능일 뿐입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한, 메이플 스토리 공식홈페이지에 게시되어 있는 코디 베스트라는 기능이 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코디 베스트는 코디/룩 정보 없이 그냥 자랑하는 기능이며 이를 추천 등의 액션을 통해서 주간 베스트를 적용합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막으로 대부분의 코디 관련 써드파티 서비스들은 DB화가 아닌 JAM Stack 위주의 정적서비스로 개발되어&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://maplestory.io&quot;&gt;https://maplestory.io&lt;/a&gt; 에 요청을 보내어 시뮬레이션을 하는 서비스가 대 다수 입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같은 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;개발을 진행하게 되었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;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;초기 버전 출시 당시의 메이플 커마는 메이플 금손이라는 이름으로 런칭하였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음에는 아바타 정보를 역산하지 못하였고, 유저들이 로그인 후 자유롭게 수정할 수 있는 모습으로 출시되었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또 초기 배포 당시에는&lt;b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;Nuxt3&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;프레임워크가 예상치 못한 이슈가 있었는데,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;Cloudflare Pages Functions&lt;/b&gt;로 배포시&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;GET&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;메소드를 제외하고는 사용하지 못한다는 문제를 출시 직전에 발견하였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;급하게&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;Cloudflare Worker&lt;/b&gt;로 API를 만들어 출시하였었지만, 앞으로도 Cloudflare Pages를 계속해서 이용할텐데 Nuxt는 이제 2버전에 이어 여전히 꼭 나사가 몇개씩 빠져있어서 앞으로는 일할때 요구하지 않는 이상 사용하지는 않을듯 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;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;출시 이후 페타코님의 도움을 받아 아바타 주소에 대한 역산을 적용하였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이로 인해 초기 버전에서 사용되었던 코디 정보 수정 기능을 과감하게 제거하였고, 아바타 주소 역산으로만 동작하게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;역산의 경우 일부 오탐이 있으며 대략 정확도는 95% 이상이라고 추측하고 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오탐은 피부 그리고 성형에서 발견되며, 성형의 경우 오탐 발견시 버그 제보를 통해 제보해주시거나 별도의 연락 또는 개인적으로 발견시 DB에 강제 주입하거나 매핑을 교체하는식으로 적용할 수 있게 DB 모델을 설계하였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;679&quot; data-origin-height=&quot;443&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zroyW/btrXpbqcMsA/xq1hHMpzuLZmsBaFQyP3YK/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zroyW/btrXpbqcMsA/xq1hHMpzuLZmsBaFQyP3YK/img.webp&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zroyW/btrXpbqcMsA/xq1hHMpzuLZmsBaFQyP3YK/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzroyW%2FbtrXpbqcMsA%2Fxq1hHMpzuLZmsBaFQyP3YK%2Fimg.webp&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;443&quot; data-origin-width=&quot;679&quot; data-origin-height=&quot;443&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;메이플 지지의 코디분석 기능과 비교&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;362&quot; data-origin-height=&quot;254&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Gi8jY/btrXoDmY3Ae/QHcOy81lgsCpVFoWq9djZ1/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Gi8jY/btrXoDmY3Ae/QHcOy81lgsCpVFoWq9djZ1/img.webp&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Gi8jY/btrXoDmY3Ae/QHcOy81lgsCpVFoWq9djZ1/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGi8jY%2FbtrXoDmY3Ae%2FQHcOy81lgsCpVFoWq9djZ1%2Fimg.webp&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;362&quot; height=&quot;254&quot; data-origin-width=&quot;362&quot; data-origin-height=&quot;254&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메이플 지지에서는 표기되는 부위가 총 7부위  입니다.&amp;nbsp; 위 캐릭터의 경우 모자와 헤어 총 2가지 부위 밖에 역산되지 않았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;368&quot; data-origin-height=&quot;745&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b9NWkL/btrXnKNEanZ/6Xkb1Vh9KVyqscWcGK7p21/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b9NWkL/btrXnKNEanZ/6Xkb1Vh9KVyqscWcGK7p21/img.png&quot; data-alt=&quot;https://maple.curma.cc/characters/83250&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b9NWkL/btrXnKNEanZ/6Xkb1Vh9KVyqscWcGK7p21/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb9NWkL%2FbtrXnKNEanZ%2F6Xkb1Vh9KVyqscWcGK7p21%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;368&quot; height=&quot;745&quot; data-origin-width=&quot;368&quot; data-origin-height=&quot;745&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://maple.curma.cc/characters/83250&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메이플 커마에서는 총 15부위를 역산합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한벌옷이 추출되는 경우에는 상의/하의가 표기되지 않으며, 반대로 상의/하의가 추출된 경우 한벌옷이 추출되지 않습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&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;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;아바타 주소 역산하기&lt;/b&gt;&lt;/h2&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;메이플 지지는 최대 6개까지 지난 코디의 아바타를 보여주게됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지난 코디의 이미지는 보여주지만 해당 아바타의 코디 정보를 볼 수는 없기 때문에 많이 아쉬운 부분이 있었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 이를 메이플 커마에서 분석이 가능합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;352&quot; data-origin-height=&quot;224&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Eb8m0/btrXwiV7UYv/5JjkZfADetggDBGRDX7SDk/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Eb8m0/btrXwiV7UYv/5JjkZfADetggDBGRDX7SDk/img.webp&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Eb8m0/btrXwiV7UYv/5JjkZfADetggDBGRDX7SDk/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEb8m0%2FbtrXwiV7UYv%2F5JjkZfADetggDBGRDX7SDk%2Fimg.webp&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;352&quot; height=&quot;224&quot; data-origin-width=&quot;352&quot; data-origin-height=&quot;224&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메이플 지지에서 정보를 추출하고 싶은 컬렉션의 이미지에 마우스 우클릭 후 `이미지 주소 복사` 를 클릭합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;731&quot; data-origin-height=&quot;444&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/75oLu/btrXrTbxMIC/awRIz7jh4mTjiybT9HRpc0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/75oLu/btrXrTbxMIC/awRIz7jh4mTjiybT9HRpc0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/75oLu/btrXrTbxMIC/awRIz7jh4mTjiybT9HRpc0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F75oLu%2FbtrXrTbxMIC%2FawRIz7jh4mTjiybT9HRpc0%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;731&quot; height=&quot;444&quot; data-origin-width=&quot;731&quot; data-origin-height=&quot;444&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메이플 커마의 메인페이지에 있는 입력창에 아바타 주소 붙여넣기 후 검색을 누르면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;484&quot; data-origin-height=&quot;741&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rUasG/btrXwiPmkjo/697GqkfSi4XDjwmzRIEeuk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rUasG/btrXwiPmkjo/697GqkfSi4XDjwmzRIEeuk/img.png&quot; data-alt=&quot;https://maple.curma.cc/characters/266194&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rUasG/btrXwiPmkjo/697GqkfSi4XDjwmzRIEeuk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrUasG%2FbtrXwiPmkjo%2F697GqkfSi4XDjwmzRIEeuk%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;484&quot; height=&quot;741&quot; data-origin-width=&quot;484&quot; data-origin-height=&quot;741&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://maple.curma.cc/characters/266194&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉시 주소를 역산후 DB에 자동등록되며 분석된 경로로 자동 이동되어 정보를 보여주게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존에는 클라이언트에서 이 과정을 진행하였지만, 일부 호환되지 않는 기기 및 웹 표준기술을 지키지 않는 아이폰의 Safari 브라우저 등에서 정보 추출이 진행되지 않는 문제가 발생하여 이를 서버에서 역산하도록 변경하였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;캐릭터 이름을 통한 검색도 지원하지만, 아바타 주소와는 다르게 메이플 스토리 랭킹서버에서 해당 캐릭터를 조회후 아바타 주소를 추출하여 역산하는 과정을 거치기 때문에, 상대적으로 주소 입력 방식보다는 느린 이슈가 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아바타 주소 역산 속도는 평균 0.007초 정도 소요 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 데이터베이스에 등록하는 과정또는 캐릭터를 검색하는 과정 등으로 인해 시간이 좀 더 소요됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최대 10초 이상 응답하지 않는 경우 새로고침을 권장드립니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&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;처음 메이플 커마를 설계할 당시 가장 먼저 염두에 두었던 기능입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;같은 부위를 사용한 다른 유저의 다른 코디를 보고 싶었기에 해당 기능을 추가하였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;분석된 코디의 각 부위에 대한 모든 다른 코디를 보여주게 되며, 해당 부위에 다른 유저 코디가 없는경우 노출되지 않습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;747&quot; data-origin-height=&quot;774&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pvTBM/btrXtRLiNGK/JQgxUvPQpKTftmiUAQQAS1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pvTBM/btrXtRLiNGK/JQgxUvPQpKTftmiUAQQAS1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pvTBM/btrXtRLiNGK/JQgxUvPQpKTftmiUAQQAS1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpvTBM%2FbtrXtRLiNGK%2FJQgxUvPQpKTftmiUAQQAS1%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;747&quot; height=&quot;774&quot; data-origin-width=&quot;747&quot; data-origin-height=&quot;774&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;742&quot; data-origin-height=&quot;780&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/5hB9K/btrXtSwFNgg/hlSknrHJfq3R1CjASSFbqK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/5hB9K/btrXtSwFNgg/hlSknrHJfq3R1CjASSFbqK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/5hB9K/btrXtSwFNgg/hlSknrHJfq3R1CjASSFbqK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F5hB9K%2FbtrXtSwFNgg%2FhlSknrHJfq3R1CjASSFbqK%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;742&quot; height=&quot;780&quot; data-origin-width=&quot;742&quot; data-origin-height=&quot;780&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;740&quot; data-origin-height=&quot;771&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bki9h7/btrXm8aqkQV/7a2OTm3ovWTfvteRz28KOK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bki9h7/btrXm8aqkQV/7a2OTm3ovWTfvteRz28KOK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bki9h7/btrXm8aqkQV/7a2OTm3ovWTfvteRz28KOK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbki9h7%2FbtrXm8aqkQV%2F7a2OTm3ovWTfvteRz28KOK%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;740&quot; height=&quot;771&quot; data-origin-width=&quot;740&quot; data-origin-height=&quot;771&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;740&quot; data-origin-height=&quot;763&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/SpDFL/btrXqC8XhuC/OVZC2xxAK0fNpPhrLiAY90/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/SpDFL/btrXqC8XhuC/OVZC2xxAK0fNpPhrLiAY90/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/SpDFL/btrXqC8XhuC/OVZC2xxAK0fNpPhrLiAY90/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FSpDFL%2FbtrXqC8XhuC%2FOVZC2xxAK0fNpPhrLiAY90%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;740&quot; height=&quot;763&quot; data-origin-width=&quot;740&quot; data-origin-height=&quot;763&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞에서 말씀드렸던것 처럼 피부에서는 오탐이 발견되었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 피부의 경우는 성형과다르게 매핑을 수정할 수 없어서 아직도 어떻게 할지는 고민중입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&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;캐릭터 이미지 관련 기능&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;277&quot; data-origin-height=&quot;208&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d2BiGc/btrXn6bSaba/5FlZl19K71U2JqAp0ZaSY0/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d2BiGc/btrXn6bSaba/5FlZl19K71U2JqAp0ZaSY0/img.webp&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d2BiGc/btrXn6bSaba/5FlZl19K71U2JqAp0ZaSY0/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd2BiGc%2FbtrXn6bSaba%2F5FlZl19K71U2JqAp0ZaSY0%2Fimg.webp&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;277&quot; height=&quot;208&quot; data-origin-width=&quot;277&quot; data-origin-height=&quot;208&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;272&quot; data-origin-height=&quot;211&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cqF3QT/btrXonLbakL/kN8xhqYH7kijC6TfYLtu20/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cqF3QT/btrXonLbakL/kN8xhqYH7kijC6TfYLtu20/img.webp&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cqF3QT/btrXonLbakL/kN8xhqYH7kijC6TfYLtu20/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcqF3QT%2FbtrXonLbakL%2FkN8xhqYH7kijC6TfYLtu20%2Fimg.webp&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;211&quot; data-origin-width=&quot;272&quot; data-origin-height=&quot;211&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&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;좌측 화살표 4개가 있는 아이콘의 경우는 위 이미지들과 같이 망토가 보이는 이미지로 축소 또는 확대하는 버튼입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우측 2가지는 각각 &lt;b&gt;클립보드 복사(좌)&lt;/b&gt;와 &lt;b&gt;저장 버튼(우)&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클립보드 복사의 경우 일부 유저분들이 카톡이나 디스코드 등의 메신저로 다운받지 않고 바로 전송할 수 있도록 또는&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일부 메이플스토리 유튜브 편집자 분들께서 좀더 편하게 일하시라고 추가해본 기능입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저장시 파일명은 아바타 주소를 파일명으로 저장되기 때문에 나중에 까먹으셔도 파일명을 통해 주소를 이어붙이면 언제든 검색이 가능합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;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;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;403&quot; data-origin-height=&quot;232&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ILvW4/btrXm7buQHq/vW2hpkSKS4IVnSI2lh0XK1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ILvW4/btrXm7buQHq/vW2hpkSKS4IVnSI2lh0XK1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ILvW4/btrXm7buQHq/vW2hpkSKS4IVnSI2lh0XK1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FILvW4%2FbtrXm7buQHq%2FvW2hpkSKS4IVnSI2lh0XK1%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;403&quot; height=&quot;232&quot; data-origin-width=&quot;403&quot; data-origin-height=&quot;232&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코디 정보에서는 위 이미지와 같이 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;- 가운데는 코디 정보 카드를 이미지로 저장하는 기능입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 우측 버튼은 해당 코디 정보 페이지의 주소를 클립보드로 복사하여 공유하는 기능입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&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;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;통계는 처음에 서비스가 너무 밋밋한 느낌이있어서 추가한 기능입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;총 15부위에 대한 적용 비율과 횟수에 대한 통계치이며, 이 통계 수치는 메이플 커마에 등록된 캐릭터들의 정보를 기반으로 집계 및 산출되었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쿼리 성능의 문제가 있어서 최대 100개 까지만 노출됩니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;768&quot; data-origin-height=&quot;780&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c3vEKQ/btrXm7buUnq/HokZ2iw0NkrbEsD8MkFdQk/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c3vEKQ/btrXm7buUnq/HokZ2iw0NkrbEsD8MkFdQk/img.webp&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c3vEKQ/btrXm7buUnq/HokZ2iw0NkrbEsD8MkFdQk/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc3vEKQ%2FbtrXm7buUnq%2FHokZ2iw0NkrbEsD8MkFdQk%2Fimg.webp&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;768&quot; height=&quot;780&quot; data-origin-width=&quot;768&quot; data-origin-height=&quot;780&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&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;믹염(믹스염색) 헤어&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;그냥 제가 보려고 만든 기능이었는데 생각보다 분석 기능 만큼 많이들 좋아해주신 기능입니다.&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;- 믹염은 매일 오전 10시에 정보를 동기화합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 모바일에서 볼때도 색상에 대한 구분이 쉽도록 컬러표가 아닌, 텍스트로 색상을 표기하였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;749&quot; data-origin-height=&quot;780&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/SDPZr/btrXpcbCbbk/WwEzlGtLEEoeAgRRsxFhFK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/SDPZr/btrXpcbCbbk/WwEzlGtLEEoeAgRRsxFhFK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/SDPZr/btrXpcbCbbk/WwEzlGtLEEoeAgRRsxFhFK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FSDPZr%2FbtrXpcbCbbk%2FWwEzlGtLEEoeAgRRsxFhFK%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;749&quot; height=&quot;780&quot; data-origin-width=&quot;749&quot; data-origin-height=&quot;780&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;734&quot; data-origin-height=&quot;828&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/AaeaD/btrXnIoJGtn/9bsrsKIjyYBUX9DSsLE1mK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/AaeaD/btrXnIoJGtn/9bsrsKIjyYBUX9DSsLE1mK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/AaeaD/btrXnIoJGtn/9bsrsKIjyYBUX9DSsLE1mK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FAaeaD%2FbtrXnIoJGtn%2F9bsrsKIjyYBUX9DSsLE1mK%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;734&quot; height=&quot;828&quot; data-origin-width=&quot;734&quot; data-origin-height=&quot;828&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;720&quot; data-origin-height=&quot;832&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ot4gp/btrXo6vEJnr/WDxBcB2NIJBkERxqBNKzPk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ot4gp/btrXo6vEJnr/WDxBcB2NIJBkERxqBNKzPk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ot4gp/btrXo6vEJnr/WDxBcB2NIJBkERxqBNKzPk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fot4gp%2FbtrXo6vEJnr%2FWDxBcB2NIJBkERxqBNKzPk%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;720&quot; height=&quot;832&quot; data-origin-width=&quot;720&quot; data-origin-height=&quot;832&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;666&quot; data-origin-height=&quot;450&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bIQpi2/btrXm8VLW2k/FUTTeTMoGL2jbDn5qUfII0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bIQpi2/btrXm8VLW2k/FUTTeTMoGL2jbDn5qUfII0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bIQpi2/btrXm8VLW2k/FUTTeTMoGL2jbDn5qUfII0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbIQpi2%2FbtrXm8VLW2k%2FFUTTeTMoGL2jbDn5qUfII0%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;666&quot; height=&quot;450&quot; data-origin-width=&quot;666&quot; data-origin-height=&quot;450&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;651&quot; data-origin-height=&quot;365&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bnNujB/btrXn72UxZW/v9HUMskkvUUnX15LDsK1mk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bnNujB/btrXn72UxZW/v9HUMskkvUUnX15LDsK1mk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bnNujB/btrXn72UxZW/v9HUMskkvUUnX15LDsK1mk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbnNujB%2FbtrXn72UxZW%2Fv9HUMskkvUUnX15LDsK1mk%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;651&quot; height=&quot;365&quot; data-origin-width=&quot;651&quot; data-origin-height=&quot;365&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;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;믹스 렌즈는 믹염의 반응이 더 좋아진다면 적용해볼 예정입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;믹염 + 믹렌은 경우의수가 대충 계산해도 170만개의 이미지를 들고있어야 해서 할지 말지 고민중입니다...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;적용 가능한 방법도 모색중이긴 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&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;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;믹염을 제외한 이미지의 경우는 넥슨사의 메이플 아바타 CDN으로부터 이미지를 획득하게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 메이플 커마는 목록에서 기본적으로 200개의 캐릭터 이미지를 불러오기 때문에 과도한 요청으로 해당 서버가 받을 부담이 매우 클거라 생각하여, 별도의 이미지 프록시를 적용하였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이미지 프록시 서버를 통해서 넥슨 CDN에서는 제공하지 않는 캐시 컨트롤을 적용함으로써 1차적으로 브라우저 캐시 2차적으로는 Cloudflare사의 CDN Edge Cache가 적용됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프록시 서버로부터 오류가 발생할 경우 자동으로 넥슨 CDN으로 요청하게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&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;불편하시겠지만, 그래도 광고는 있습니다....&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재는 도메인 변경 이슈로 잠깐 노출되지 않는데, Google Adsense 라고 표기되어 있는 박스들은 광고가 노출되는 위치입니다.&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;메이플 커마 기준으로는 하루에 잘벌어야 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;하지만 광고가 없다면 갈수록 늘어날 DB 및 서버의 비용을 감당할 수 없기 때문에 최소한의 수익창출이므로 양해 부탁드립니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;광고의 경우 컨텐츠를 최대한 방해하지 않는 배치를 적용하였습니다. (자동광고는 제가 아니라 구글이 한거라...)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&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;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;페이지 하단에 버그제보 및 문의 피드백 등이 존재합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클릭시 커마 서비스의 디스코드 서버로 연결됩니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;503&quot; data-origin-height=&quot;301&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Qzr17/btrXt8M1kgM/Tahcwtjvh6qFxQI2yipuYK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Qzr17/btrXt8M1kgM/Tahcwtjvh6qFxQI2yipuYK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Qzr17/btrXt8M1kgM/Tahcwtjvh6qFxQI2yipuYK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQzr17%2FbtrXt8M1kgM%2FTahcwtjvh6qFxQI2yipuYK%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;503&quot; height=&quot;301&quot; data-origin-width=&quot;503&quot; data-origin-height=&quot;301&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;API 공유&lt;/b&gt;&lt;/h2&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;a href=&quot;https://maplestory.io&quot;&gt;https://maplestory.io&lt;/a&gt; 여기서 아이템 정보 및 헤어 정보 그리고 이미지를 동기화합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 API로부터 받은 정보이기 때문에, 저 또한 CORS 없이 적용하였습니다. 해당 정보들은 정적사이트를 통해 배포하였기 때문에 무료로 운영되고 있어서 다른분들이 가져다가 쓰셔도 되도록 하였습니다.&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;maplestory.io가 KMST 를 빠르게 반영해준다면, KMS에 적용되기전에 믹염 정보가 반영될 수 있기 때문에&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;미리 믹염 비율을 조정하고 헤어를 확인해볼 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;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;a href=&quot;https://api.maple.curma.cc/version.json&quot;&gt;https://api.maple.curma.cc/version.json&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어떤 버전으로 적용되어 있는지 확인할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;360&quot; data-origin-height=&quot;112&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ol5Zl/btrXo4YVfeP/13ozUhloaEyYYmcXkhsf9k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ol5Zl/btrXo4YVfeP/13ozUhloaEyYYmcXkhsf9k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ol5Zl/btrXo4YVfeP/13ozUhloaEyYYmcXkhsf9k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fol5Zl%2FbtrXo4YVfeP%2F13ozUhloaEyYYmcXkhsf9k%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;360&quot; height=&quot;112&quot; data-origin-width=&quot;360&quot; data-origin-height=&quot;112&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;326&quot; data-origin-height=&quot;46&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/svB4S/btrXqEyUT4m/MRHwueiH6m8lGuicWnP8L1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/svB4S/btrXqEyUT4m/MRHwueiH6m8lGuicWnP8L1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/svB4S/btrXqEyUT4m/MRHwueiH6m8lGuicWnP8L1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsvB4S%2FbtrXqEyUT4m%2FMRHwueiH6m8lGuicWnP8L1%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;326&quot; height=&quot;46&quot; data-origin-width=&quot;326&quot; data-origin-height=&quot;46&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;region은 메이플스토리 한국 서버기준으로는 KMS와 KMST가 있으며, KMST는 테스트서버를 의미합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;version의 1150은&amp;nbsp; KMST의 1.2.150 버전을 의미합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;createdAt 은 해당 정보를 동기화를 하여 파일을 생성한 시각입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&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;a href=&quot;https://api.maple.curma.cc/singles.json&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://api.maple.curma.cc/singles.json&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주로 메이플 커마 검색에 사용되는 기능입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;색상이 함께 표기되는 아이템은 색상 명을 제거하였고, 중복된 아이템명은 제거하였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;235&quot; data-origin-height=&quot;972&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/XLkn1/btrXm7P5J6d/N52oo3y9qFHkTPT3PddmZ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/XLkn1/btrXm7P5J6d/N52oo3y9qFHkTPT3PddmZ1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/XLkn1/btrXm7P5J6d/N52oo3y9qFHkTPT3PddmZ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FXLkn1%2FbtrXm7P5J6d%2FN52oo3y9qFHkTPT3PddmZ1%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;235&quot; height=&quot;972&quot; data-origin-width=&quot;235&quot; data-origin-height=&quot;972&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;part&lt;/b&gt;는 어떤 부위인지를 나타내는 정보입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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;a href=&quot;https://api.maple.curma.cc/hairs.json&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://api.maple.curma.cc/hairs.json&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메이플 커마 믹염에서 노출되는 헤어 종류입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;334&quot; data-origin-height=&quot;381&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mEXgg/btrXpaZbeyf/sJx4AESKctAjW5gZYcvOZ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mEXgg/btrXpaZbeyf/sJx4AESKctAjW5gZYcvOZ0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mEXgg/btrXpaZbeyf/sJx4AESKctAjW5gZYcvOZ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmEXgg%2FbtrXpaZbeyf%2FsJx4AESKctAjW5gZYcvOZ0%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;334&quot; height=&quot;381&quot; data-origin-width=&quot;334&quot; data-origin-height=&quot;381&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;gender는 성별을 의미하지만, maplestory.io 에서 일부 헤어 성별이 잘못 지정된 경우가 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메이플 커마에서는 별도의 필터링을 거쳐서 표기하고 있지만, API를 사용하실때는 이를 유의해서 사용하셔야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&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;a href=&quot;https://api.maple.curma.cc/hairs/&amp;lt;hairId&amp;gt;&quot;&gt;https://api.maple.curma.cc/hairs/&amp;lt;hairId&amp;gt;&lt;/a&gt;.png&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://api.maple.curma.cc/hairs/64397.png&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://api.maple.curma.cc/hairs/64397.png&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;hairs 목록에 존재하는 헤어 이미지는 위 주소처럼 요청하실 수 있습니다.&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;이미지는 각 개별로 저장하기엔 사용자가 요청하는 구간이 너무 많아서 sprite 방식으로 변경할지는 아직 고민중에 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&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;카카오 개발 커뮤니티를 통해서 문의를 진행해둔 상황이긴합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Cloudflare 를 무료 버전으로 사용할때는 아래 링크처럼 메이플 커마는 정상 동작합니다.&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;a href=&quot;https://maple.curma.cc/characters/266229&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://maple.curma.cc/characters/266229&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1674974246827&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;266229번 코디&quot; data-og-description=&quot;[BLACKPINK] 베놈 시크, 주황색 안개 셀린 헤어, 졸린 조용한 얼굴, 투명 안경, 아련한 메이크업, 체인드롭 이어링, 밀키 피부, 칠흑의 날개 코트, 큐티 펑크 구두, 투명 장갑, 은하 음악회, 미스터리 &quot; data-og-host=&quot;maple.curma.cc&quot; data-og-source-url=&quot;https://maple.curma.cc/characters/266229&quot; data-og-url=&quot;https://maple.curma.cc/characters/266229&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bQRS1M/hyRqYoQRgM/mPD3ZQXubd19yUxPSg6tjk/img.png?width=96&amp;amp;height=96&amp;amp;face=0_0_96_96,https://scrap.kakaocdn.net/dn/c8y5Xt/hyRqYPUAjt/SSbGkXu9NRHUAVXTxKP5TK/img.png?width=96&amp;amp;height=96&amp;amp;face=0_0_96_96&quot;&gt;&lt;a href=&quot;https://maple.curma.cc/characters/266229&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://maple.curma.cc/characters/266229&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bQRS1M/hyRqYoQRgM/mPD3ZQXubd19yUxPSg6tjk/img.png?width=96&amp;amp;height=96&amp;amp;face=0_0_96_96,https://scrap.kakaocdn.net/dn/c8y5Xt/hyRqYPUAjt/SSbGkXu9NRHUAVXTxKP5TK/img.png?width=96&amp;amp;height=96&amp;amp;face=0_0_96_96');&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;266229번 코디&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;[BLACKPINK] 베놈 시크, 주황색 안개 셀린 헤어, 졸린 조용한 얼굴, 투명 안경, 아련한 메이크업, 체인드롭 이어링, 밀키 피부, 칠흑의 날개 코트, 큐티 펑크 구두, 투명 장갑, 은하 음악회, 미스터리&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;maple.curma.cc&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;하지만 Cloudflare Pro를 유료 버전을 적용한 경우 아래와 같이 노출되지 않는 문제가 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://goldenhand.pro/arts/3UVigKoQJj&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://goldenhand.pro/arts/3UVigKoQJj&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 부분은 카카오측과 클라우드플레어사 측에서 개선을 해야겠지만, 저 또한 양측을 이용하는 유저로써 또 앞으로 cloudflare를 통해서 서비스하는 유저들이 있을 수 있으니 지속된 발전을 위해 계속해서 협력할 것 입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&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;자매품&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;현재는 아직 광고 심사를 위해서 연결하지 않았지만, 자매품으로 로스트아크, 프롬프트가 존재합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;던파의 경우 현재 개발 과정중에 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;던파가 완료되면, 로스트아크 커마와 프롬프트 커마가 분리 및 개편이 대대적으로 적용될 예정입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로스트아크: &lt;a href=&quot;https://goldenhand.pro&quot;&gt;https://goldenhand.pro&lt;/a&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프롬프트: &lt;a href=&quot;https://goldenhand.pro/arts&quot;&gt;https://goldenhand.pro/arts&lt;/a&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;긴글 읽어주셔서 감사합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;커마에 추가되었으면 하는 게임이 있다면 언제든 디스코드를 통해 연락주세요!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;선코디 후육성이 되는 그날까지...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Develop/Javascript</category>
      <category>금손</category>
      <category>로아</category>
      <category>메이플</category>
      <category>믹염</category>
      <category>분석</category>
      <category>시뮬</category>
      <category>지지</category>
      <category>커마</category>
      <category>코디</category>
      <category>프롬프트</category>
      <author>TL&amp;amp;D</author>
      <guid isPermaLink="true">https://gmyankee.tistory.com/387</guid>
      <comments>https://gmyankee.tistory.com/entry/%EB%A9%94%EC%9D%B4%ED%94%8C-%EC%BB%A4%EB%A7%88-%EB%A9%94%EC%95%A0%EA%B8%B0-%EC%BD%94%EB%94%94-%EB%B6%84%EC%84%9D-%EB%B0%8F-%EA%B3%B5%EC%9C%A0-%EC%84%9C%EB%B9%84%EC%8A%A4-%EA%B3%B5%EA%B0%9C#entry387comment</comments>
      <pubDate>Sun, 29 Jan 2023 15:40:51 +0900</pubDate>
    </item>
    <item>
      <title>Cloudflare D1 로컬 모드</title>
      <link>https://gmyankee.tistory.com/entry/Cloudflare-D1-%EB%A1%9C%EC%BB%AC-%EB%AA%A8%EB%93%9C</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1670664327932&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;wrangler d1 execute &amp;lt;DB_NAME&amp;gt; --local --file=schema.sql

wrangler d1 execute example --local --file=schema.sql&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;schema.sql 은 backup된 데이터를 cloudflare d1 대시보드에서 다운받거나,&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 명령을 통해 backup 본을 다운받습니다.&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;643&quot; data-origin-height=&quot;689&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/QkWZs/btrThd7dHXQ/rg5F0KZziKDvZkFfCGX8vK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/QkWZs/btrThd7dHXQ/rg5F0KZziKDvZkFfCGX8vK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/QkWZs/btrThd7dHXQ/rg5F0KZziKDvZkFfCGX8vK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQkWZs%2FbtrThd7dHXQ%2Frg5F0KZziKDvZkFfCGX8vK%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;643&quot; height=&quot;689&quot; data-origin-width=&quot;643&quot; data-origin-height=&quot;689&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다운받으면 sqlite의 파일로 dump된 파일을 뱉는데, 이걸 DB Browser for Sqlite 같은걸이용해서 연뒤, 데이터베이스 내보내기를 SQL 확장자로 내보내면 DDL과 DML을 뱉습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 sql의 파일명이 길어서 불편하니 schema.sql 로 바꾸고 다시 맨처음 명령 실행하면 되는데&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;D1_ALL_ERROR 발생시 프로젝트 폴더내 .wrangler/state/d1 에 있는 DB를 모두 삭제해준 뒤 다시 명령을 실행하면 충돌나는 파일이 제거되기 때문에 정상 동작 가능합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1670671796371&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# wrangler d1 backup create &amp;lt;db_name&amp;gt;
wrangler d1 backup create example


# 현재 버그가 있어서 --output 옵션이 명시되지 않으면 동작하지 않습니다.
# wrangler d1 backup download &amp;lt;binding_db_name&amp;gt; &amp;lt;uuid&amp;gt; --output=&amp;lt;save_path&amp;gt;
wrangler d1 backup download DB 12345678-1234-5678-123456789012 --output=&quot;.wrangler/state/d1/DB.sqlite3&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;--output 을 wrangler가 참조하는 DB 위치로 바로 꽂아버리면 별다른 조치없이 개발서버에 디비를 반영할 수 있습니다.&lt;/p&gt;</description>
      <category>Develop/Javascript</category>
      <category>backup</category>
      <category>CloudFlare</category>
      <category>D1</category>
      <category>dev</category>
      <category>export</category>
      <category>import</category>
      <category>migrate</category>
      <category>Migrations</category>
      <category>persist</category>
      <author>TL&amp;amp;D</author>
      <guid isPermaLink="true">https://gmyankee.tistory.com/386</guid>
      <comments>https://gmyankee.tistory.com/entry/Cloudflare-D1-%EB%A1%9C%EC%BB%AC-%EB%AA%A8%EB%93%9C#entry386comment</comments>
      <pubDate>Sat, 10 Dec 2022 18:29:02 +0900</pubDate>
    </item>
    <item>
      <title>Cloudflare D1 Database Sqlite3 Alpha 사용 후기</title>
      <link>https://gmyankee.tistory.com/entry/Cloudflare-D1-Database-Sqlite3-Alpha-%EC%82%AC%EC%9A%A9-%ED%9B%84%EA%B8%B0</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;628&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vlRL0/btrTgnCkZlc/5RBL5pNGvo91hhGq0cyi70/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vlRL0/btrTgnCkZlc/5RBL5pNGvo91hhGq0cyi70/img.png&quot; data-alt=&quot;클라우드플레어 블로거에서 돚거한 이미지&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vlRL0/btrTgnCkZlc/5RBL5pNGvo91hhGq0cyi70/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FvlRL0%2FbtrTgnCkZlc%2F5RBL5pNGvo91hhGq0cyi70%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;1200&quot; height=&quot;628&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;628&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;클라우드플레어 블로거에서 돚거한 이미지&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;Cloudflare 의 서버리스 제품에서 굉장히 오랫동안 기다려오고 D1의 예고가 등장하자마자 존버의 존버를 했던 바로 Serverless DB의 결정체 &lt;b&gt;sqlite3&lt;/b&gt; 기반의 &lt;b&gt;DB&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;현재는 Alpha 버전으로만 제공하고 있지만, 현재까지 출시된 d1-ORM 이나 &lt;b&gt;Prepare&lt;/b&gt;로 사용되는 &lt;b&gt;better-sqlite3&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;또한, 서버리스의 DB 이자 Sqlite3를 이용하여 Edge 단에서 동작하는 Cloudflare의 특징을 잘 살려낸 만큼 여타 서비스들과 마찬가지로 HTTP REST API를 통해 제공도 하는데, DB가 읽기 전용 토큰으로 사용해서 노출되도 괜찮다면 경우에 따라서는 &lt;b&gt;클라이언트가 직접적으로 통신&lt;/b&gt;도 가능하다는 이야기가 됩니다. (요금 폭탄은 본인의 몫)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 위와 같은 HTTP 통신 DB가 필요로했던 가장 큰 이유는 Cloudflare Worker가 Node.js의 서버와 Web Worker의 중앙 지점의 느낌에서 동작하기 때문에, TCP 연결이 불가능 했었습니다. 이러한 상황에서 사용할 수 있는 DB로는 클라우드에서 제공해주는 HTTP DB인 &lt;b&gt;Fauna&lt;/b&gt;, &lt;b&gt;Dynamo&lt;/b&gt;, &lt;b&gt;Arango&lt;/b&gt; 처럼 &lt;b&gt;HTTP&lt;/b&gt; 를 제공해주는 &lt;b&gt;DB&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;Haskell&lt;/b&gt;로 포팅되서 만들어진 &lt;b&gt;Postgresql REST API&lt;/b&gt; 서버가 같이 도는 것 정도 있었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;D1의 Alpha 테스트는 공개적으로 진행되고 있고, D1이 먼저 공개된 서비스는&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Worker보다는 Cloudflare가 주력해서 하나의 풀스택으로 묶어버리기 위해 밀고 있는 Cloudflare Pages 입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Pages에서 Functions를 통해 DB와 직접적으로 통신해서 &lt;b&gt;Hydration SSR&lt;/b&gt; 서버를 올리라고 마치 유도하는 것 같았죠.&lt;br /&gt;(결국에는 Worker에도 보이기 시작했지만요)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;단점&lt;/b&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;b&gt;Sqlite3&lt;/b&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;sqlite3 안써본지가 5년이나 지났는데 postgresql, mysql, mariadb만 쓰다가 쓰면 Type에서 어어..? 싶은 순간이 옵니다.&lt;/li&gt;
&lt;li&gt;datetime 미지원 -&amp;gt; Text로 선언하고, 쿼리시 datetime(created_at) 이런식으로 표현&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;테이블 수정 불가능&lt;/b&gt;&amp;nbsp;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;웹 대시보드 상에서 아직 제공하지 않습니다.&lt;/li&gt;
&lt;li&gt;cli 명령을 통해 &lt;b&gt;원격 DB&lt;/b&gt;에 붙어서&lt;b&gt; ALTER TABLE&lt;/b&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: circle;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;위와 같은 내용입니다. 대시보드에서만 제공하지 않습니다.&lt;/li&gt;
&lt;li&gt;마찬가지로&lt;b&gt; cli&lt;/b&gt; 명령으로&amp;nbsp; &lt;b&gt;ALTER TABLE&lt;/b&gt;이나&lt;b&gt; CREATE TABLE&lt;/b&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: circle;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;웹 대시보드 상에서 제공하지 않습니다.&lt;/li&gt;
&lt;li&gt;백업트리거가 주기적으로 동작하고 있지만, 수동으로도 가능합니다. 이를 통해 DB 덤프를 생성하여 로컬에서 &lt;br /&gt;&lt;a href=&quot;https://sqlitebrowser.org/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;b&gt;DB Browser for SQLite&lt;/b&gt;&lt;/a&gt; 같은 프로그램을 사용하여 확인할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;d1-console 오픈소스의 불완전 함&lt;/b&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;알파이니 그럴 수 있습니다...&lt;/li&gt;
&lt;li&gt;예를들면 SELECT * FROM posts 라는 쿼리를 통해 posts 테이블을 조회하는 경우 오류가 발생&lt;/li&gt;
&lt;li&gt;SELECT title from posts 라는 쿼리를 날리면 한글의 경우 일부가 표기 안됨.&lt;/li&gt;
&lt;li&gt;대체방안으로 그냥 공식적으로 지원하는 &lt;b&gt;wrangler d1&lt;/b&gt; 을 이용하는게 정신건강에 좋습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;HTTP 요청의 단점&lt;/b&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;사실 http 요청은 공식 API에도 아직 게재가 안된건데 오픈소스 보고 뚫어서 사용중입니다.&lt;/li&gt;
&lt;li&gt;http 요청의 경우 prepare가 없어서 직접 구현하던가 무시하고 작성해야 합니다.&lt;/li&gt;
&lt;li&gt;prepare 없이 작성하는 경우 삽입하는 내용중에 ;(세미콜론) 이 포함되어 있을때 오류가 발생합니다.&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;dev 실행시 로컬 모드 강제성&lt;/b&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;cloudflare pages / functions + Nuxt3 로 진행하는 중 삽질을 쥰내 했습니다.&lt;/li&gt;
&lt;li&gt;dev 모드로 동작시 로컬 모드가 강제적으로 동작합니다.&lt;/li&gt;
&lt;li&gt;dev 동작하기 전에&lt;b&gt; schema.sql&lt;/b&gt; 등을 이용하거나 &lt;b&gt;exeucte&lt;/b&gt; 명령으로 로컬 db의 테이블을 생성해주어야 합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Nuxt.js 연동의 부실한 설명&lt;/b&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Next.js 연동 예제 오픈소스 보고 훔쳐서 발견했습니다.&lt;/li&gt;
&lt;li&gt;아래와 같이 실행해야 합니다. wrangler로 실행하는데 -- npm run dev 명령을 뒤에 붙여서 &lt;br /&gt;&lt;b&gt;package.json&lt;/b&gt;에 정의된 dev 스크립트를 실행시키게합니다.&lt;br /&gt;&lt;br /&gt;이렇게되면 wrangler가 실행하기전에 &lt;b&gt;dev&lt;/b&gt;를 프록시로 먼저 실행시키고 &lt;b&gt;wrangler&lt;/b&gt; 서버가 동작합니다.&lt;br /&gt;실행 이후 콘솔(터미널) 에서&lt;b&gt; b&lt;/b&gt; 를 누르면 &lt;b&gt;브라우저&lt;/b&gt;를 띄워주는데 그 주소 및 포트가 앞으로 개발하실때 보셔야하는 주소이고 거기서만 &lt;b&gt;functions&lt;/b&gt;에 정의한 API가 정상적으로 동작합니다.&lt;br /&gt;&lt;br /&gt;ex) Nuxt 기본 포트가 3000이라면, wrangler 실행시 대체로 8788포트로 실행됨.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;autoit&quot;&gt;&lt;code&gt;npx wrangler@pages pages dev --local --persist -- npm run dev&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;&amp;nbsp;&lt;/p&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;장점&lt;/b&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;b&gt;HTTP 로 쿼리 수행 가능&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;일부 제한적인 환경 Cloudflare Worker 또는 다른 언어들을 사용해서 분리 개발하는데 DB는 같은 곳을 바라볼때, HTTP라는 공통된 규격이 있다는 것은 별다른 의존성없이도 가능하다는 것을 의미합니다.&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;가장 강력한 장점입니다. 하다못해 AWS RDS 같은 것을 사용하면, 결국 수직/수평 확장에 대해서 언젠가는 고민을 해야합니다. 돈을 쳐발라서 오토스케일링을 걸던가 하는 방법이죠. 하지만 클라우드 제공사들은 DB서버는 유독 비싸게 요금을 받습니다. RDS 프리티어가 끝나면 젤 꾸진거 써도 &lt;b&gt;월 75,000원 이상&lt;/b&gt;이 찍히는 것을 확인하실 수 있습니다.&lt;/li&gt;
&lt;li&gt;Cloudflare가 관리하니 샤딩이나 성능에 대한 고려가 없습니다.&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;Cloudflare의 유일 무이한 장점입니다. AWS/Google/Oracle/IBM/Naver 를 예시로들면 해당 국가의 그것도 특정 리전내에서만 서버가 돌고 백업이되고 하기 때문에, 사용자가 결국 글로벌 서비스 진출시 타 리전까지 등록하지 않으면 클라우드 제공사들은 이를 제공해주지 않습니다.&lt;br /&gt;(극단적인 예시로, 서울/경기에 핵이떨어져서 IDC가 모두 공중분해되면 서비스가 마비되지만 Cloudflare는 가장 가까운 CDN으로 알아서 잡아줍니다. [클플은 한국 버린지 오래라 어차피 오사카/도쿄가 젤 가깝습니다.])&lt;/li&gt;
&lt;li&gt;현재는 Alpha 테스트 단계라 사용하는 국가 리전만 이용 가능합니다. &lt;br /&gt;(별다른 리전 설정은 없습니다. 가까운 리전 자동 적용)&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;p data-ke-size=&quot;size16&quot;&gt;아무리 쥐어짜도 장점이 더 없습니다. 그냥 DB인데 사실 가격 정책이 어떻게 정해지느냐에 따라 갈리겠지만,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서버리스 DB이니 만큼 쿼리 요청의 따른 지불 비용이 예상됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;HTTP 쿼리 요청 방법&lt;/b&gt;&lt;/h2&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;access token 발급 방법&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://dash.cloudflare.com/profile/api-tokens&quot;&gt;https://dash.cloudflare.com/profile/api-tokens&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;* DB ID&amp;nbsp;&lt;/b&gt;발급은 그냥 DB 생성하고 해당 db 상세페이지 들어가면 보입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* &lt;b&gt;Account ID &lt;/b&gt;확인은 &lt;b&gt;Workers 탭&lt;/b&gt; -&amp;gt; &lt;b&gt;개요&lt;/b&gt; -&amp;gt; 우측 탭 중앙쯤에 &lt;b&gt;계정 ID&lt;/b&gt;라고 표기되어 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1670598180479&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// Base URL
https://api.cloudflare.com/client/v4/accounts/{account_id}/d1/database/{db_id}/query&lt;/code&gt;&lt;/pre&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;pre id=&quot;code_1670598201560&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// Authorization 쓰기 싫으면 X-Auth-Key, X-Auth-Email 사용 하셔야합니다.
{
	&quot;header&quot;: {
		&quot;Authroization&quot;: &quot;Bearer &amp;lt;access_token&amp;gt;&quot;
	}
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;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;b&gt;Javascript - Axios 사용&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1670598264736&quot; class=&quot;go&quot; data-ke-language=&quot;go&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const uri = &quot;https://api.cloudflare.com/client/v4/accounts/{account_id}/d1/database/{db_id}/query&quot;
const options = {header: {Authroization: &quot;Bearer &amp;lt;access_token&amp;gt;&quot;}}
const payload = {sql: &quot;SELECT * FROM &amp;lt;table_name&amp;gt;&quot;}
axios.post(uri, payload, options)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JS로 작성하였으나, 타 언어도 동일합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Python3 - requests 사용&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1670598361589&quot; class=&quot;go&quot; data-ke-language=&quot;go&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import requests

uri = f&quot;https://api.cloudflare.com/client/v4/accounts/{account_id}/d1/database/{db_id}/query&quot;
headers = {&quot;Authroization&quot;: f&quot;Bearer {access_token}&quot;}

const payload = {&quot;sql&quot;: &quot;SELECT * FROM &amp;lt;table_name&amp;gt;&quot;}
requests.post(uri, json=payload, headers=headers)&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Go 1.19&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1670598639643&quot; class=&quot;go&quot; data-ke-language=&quot;go&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 필요한것만 추출한거라 직접 결과 보고 뽑으시는게 좋습니다.
type QueryResponse struct {
	Result []struct {
		Results []struct {
			// 여기 컬럼 정의 필요
		} `json:&quot;results&quot;`
		Success bool `json:&quot;success&quot;`
		Meta    struct {
			Duration      float64     `json:&quot;duration&quot;`
			LastRowID     interface{} `json:&quot;last_row_id&quot;`
			Changes       interface{} `json:&quot;changes&quot;`
			ServedBy      string      `json:&quot;served_by&quot;`
			InternalStats interface{} `json:&quot;internal_stats&quot;`
		} `json:&quot;meta&quot;`
	} `json:&quot;result&quot;`
}


// 알잘딱 ㅇㅈ? 솔직히 이거보고 이해못하면 go언어 삭제해야됨.
var AccountID string 
var DatabaseID string

func main() {
	target := new(QueryResponse)
	client := &amp;amp;http.Client{}
    
    	uri := fmt.Sprintf(&quot;https://api.cloudflare.com/client/v4/accounts/%s/d1/database/%s/query&quot;, AccountID, DatabaseID)
	payload, _ := json.Marshal(query)

	req, _ := http.NewRequest(http.MethodPost, uri, bytes.NewBuffer(payload))
	req.Header.Set(&quot;content-type&quot;, &quot;application/json&quot;)
	req.Header.Set(&quot;Authorization&quot;, fmt.Sprintf(&quot;Bearer %s&quot;, AccessToken))
    	resp, err := client.Do(req)
	if err != nil {
		log.Fatalln(err)
	}

	defer resp.Body.Close()
	_ = json.NewDecoder(resp.Body).Decode(target)
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Develop/Javascript</category>
      <category>CDN</category>
      <category>CloudFlare</category>
      <category>D1</category>
      <category>Database</category>
      <category>DB</category>
      <category>edge</category>
      <category>functions</category>
      <category>Pages</category>
      <category>serverless</category>
      <category>SQLite3</category>
      <author>TL&amp;amp;D</author>
      <guid isPermaLink="true">https://gmyankee.tistory.com/385</guid>
      <comments>https://gmyankee.tistory.com/entry/Cloudflare-D1-Database-Sqlite3-Alpha-%EC%82%AC%EC%9A%A9-%ED%9B%84%EA%B8%B0#entry385comment</comments>
      <pubDate>Sat, 10 Dec 2022 00:21:37 +0900</pubDate>
    </item>
    <item>
      <title>AI 이미지 프롬프트 추출 Browser JavaScript 기반</title>
      <link>https://gmyankee.tistory.com/entry/AI-%EC%9D%B4%EB%AF%B8%EC%A7%80-%ED%94%84%EB%A1%AC%ED%94%84%ED%8A%B8-%EC%B6%94%EC%B6%9C</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Novel AI와 Web UI를 통해 생성한 AI 이미지는 우클릭 이미지 복사나 별도의 프로그램이나 서비스를 통해 재생성을 하지 않는 이상, PNG 파일 헤더내의 chunk로 정보를 저장합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;당연하게도 positive prompt(긍정 프롬프트) 또는 negative prompt(부정 프롬프트)가 길어질 수록 파일의 크기도 커집니다.&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;하지만 이러한 정보가 있어야 많은 사람들이 AI 이미지를 생성할 때 이를 참고하여 이러한 이미지를 만들 수 있구나 혹은 돚거(도적)질을 할 수 있게됩니다.&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;서버를 거치지 않고, 오직 클라이언트 JavaScript만을 사용하여, 이미지내에서 프롬프트를 추출하는 서비스를 만들게되어 공개합니다.&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;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Demo&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://prompt.tlnd.cc&quot;&gt;https://prompt.tlnd.cc&lt;/a&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1670233836066&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;AI Generate Image&quot; data-og-description=&quot;+ only &amp;#96;.PNG&amp;#96; image file + images created by WebUI / Novel AI + Don't request upload a server. + only Client Extract.&quot; data-og-host=&quot;prompt.tlnd.cc&quot; data-og-source-url=&quot;https://prompt.tlnd.cc&quot; data-og-url=&quot;https://prompt.tlnd.cc&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/er29Xu/hyQNX4WcAY/qlmTKIIKK4b9KWlb3xhukk/img.png?width=512&amp;amp;height=512&amp;amp;face=0_0_512_512&quot;&gt;&lt;a href=&quot;https://prompt.tlnd.cc&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://prompt.tlnd.cc&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/er29Xu/hyQNX4WcAY/qlmTKIIKK4b9KWlb3xhukk/img.png?width=512&amp;amp;height=512&amp;amp;face=0_0_512_512');&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;AI Generate Image&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;+ only `.PNG` image file + images created by WebUI / Novel AI + Don't request upload a server. + only Client Extract.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;prompt.tlnd.cc&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1874&quot; data-origin-height=&quot;983&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ouNIB/btrSUH7YMGq/0EfaeRdbTj43At700VRsKk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ouNIB/btrSUH7YMGq/0EfaeRdbTj43At700VRsKk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ouNIB/btrSUH7YMGq/0EfaeRdbTj43At700VRsKk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FouNIB%2FbtrSUH7YMGq%2F0EfaeRdbTj43At700VRsKk%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;1874&quot; height=&quot;983&quot; data-origin-width=&quot;1874&quot; data-origin-height=&quot;983&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;514&quot; data-origin-height=&quot;2005&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lf4An/btrSSMviB7b/O25lNDtck0lI0IkzeXWOyK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lf4An/btrSSMviB7b/O25lNDtck0lI0IkzeXWOyK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lf4An/btrSSMviB7b/O25lNDtck0lI0IkzeXWOyK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Flf4An%2FbtrSSMviB7b%2FO25lNDtck0lI0IkzeXWOyK%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;514&quot; height=&quot;2005&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;514&quot; data-origin-height=&quot;2005&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우마무스메 (속칭 말딸)의 하루 우라라를 만든 &lt;b&gt;prompt를&lt;/b&gt; 포함한 이미지입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;NAI(novel ai) 또는 Web UI로 생성한 PNG 이미지를 업로드하면 즉시, 서버를 거치지 않고 오직 브라우저 상에서 이미지를 분석하고 정보를 추출해냅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;webui에서 생성하였던, Novel AI에서 생성하였던지 간에, 양측의 가중치로 변환하는 복사 기능을 포함하였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Develop/Javascript</category>
      <category>ai generate image</category>
      <category>AI Image</category>
      <category>automatic111</category>
      <category>EXIF</category>
      <category>nai</category>
      <category>negative</category>
      <category>novelai</category>
      <category>Positive</category>
      <category>prompt</category>
      <category>webui</category>
      <author>TL&amp;amp;D</author>
      <guid isPermaLink="true">https://gmyankee.tistory.com/384</guid>
      <comments>https://gmyankee.tistory.com/entry/AI-%EC%9D%B4%EB%AF%B8%EC%A7%80-%ED%94%84%EB%A1%AC%ED%94%84%ED%8A%B8-%EC%B6%94%EC%B6%9C#entry384comment</comments>
      <pubDate>Mon, 5 Dec 2022 18:55:16 +0900</pubDate>
    </item>
    <item>
      <title>NSFW.JS 를 빠르게 사용하기</title>
      <link>https://gmyankee.tistory.com/entry/NSFWJS-%EB%A5%BC-%EB%B9%A0%EB%A5%B4%EA%B2%8C-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://gmyankee.tistory.com/381&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://gmyankee.tistory.com/381&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1670233523617&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;NSFWJS + TFJS WASM + Web Worker&quot; data-og-description=&quot;개요 한국어로는 후방주의 ㅎㅂ) 이런식으로 혼자있을때가 아닌 경우 음란물이 있을 수 있으니 주의하라는 의미로 많이 사용하는 용어인데, 영어로는 nsfw(not safe for work) 라고 표현합니다. nsfwjs&quot; data-og-host=&quot;gmyankee.tistory.com&quot; data-og-source-url=&quot;https://gmyankee.tistory.com/381&quot; data-og-url=&quot;https://gmyankee.tistory.com/381&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/dA5dvt/hyQMBh5LLa/t3uCC4PisnN5CVQv3Js0r0/img.png?width=356&amp;amp;height=197&amp;amp;face=0_0_356_197&quot;&gt;&lt;a href=&quot;https://gmyankee.tistory.com/381&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://gmyankee.tistory.com/381&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/dA5dvt/hyQMBh5LLa/t3uCC4PisnN5CVQv3Js0r0/img.png?width=356&amp;amp;height=197&amp;amp;face=0_0_356_197');&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;NSFWJS + TFJS WASM + Web Worker&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;개요 한국어로는 후방주의 ㅎㅂ) 이런식으로 혼자있을때가 아닌 경우 음란물이 있을 수 있으니 주의하라는 의미로 많이 사용하는 용어인데, 영어로는 nsfw(not safe for work) 라고 표현합니다. nsfwjs&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;gmyankee.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지난번에 게시한 NSFW JS의 &lt;b&gt;Demo&lt;/b&gt; 페이지를 추가하였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;nsfw.png&quot; data-origin-width=&quot;512&quot; data-origin-height=&quot;512&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/K203H/btrSWwLpaNl/78CCPGt2BrrOMp3sgj1gFK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/K203H/btrSWwLpaNl/78CCPGt2BrrOMp3sgj1gFK/img.png&quot; data-alt=&quot;썸네일 및 테스트 이미지&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/K203H/btrSWwLpaNl/78CCPGt2BrrOMp3sgj1gFK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FK203H%2FbtrSWwLpaNl%2F78CCPGt2BrrOMp3sgj1gFK%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;512&quot; height=&quot;512&quot; data-filename=&quot;nsfw.png&quot; data-origin-width=&quot;512&quot; data-origin-height=&quot;512&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;썸네일 및 테스트 이미지&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;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Demo&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://nsfw.tlnd.cc&quot;&gt;https://nsfw.tlnd.cc&lt;/a&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1670233540435&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;NSFW JS + WASM on Web Worker&quot; data-og-description=&quot;- with Tensorflow.js wasm version - with Web Worker Not Main Thread - don't request upload a server. - only client side nsfw validate.&quot; data-og-host=&quot;nsfw.tlnd.cc&quot; data-og-source-url=&quot;https://nsfw.tlnd.cc&quot; data-og-url=&quot;https://nsfw.tlnd.cc&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/CcPkZ/hyQNYpeqY7/YLkdPPRezcKA5qeR3e6ysK/img.png?width=512&amp;amp;height=512&amp;amp;face=0_0_512_512&quot;&gt;&lt;a href=&quot;https://nsfw.tlnd.cc&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://nsfw.tlnd.cc&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/CcPkZ/hyQNYpeqY7/YLkdPPRezcKA5qeR3e6ysK/img.png?width=512&amp;amp;height=512&amp;amp;face=0_0_512_512');&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;NSFW JS + WASM on Web Worker&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;- with Tensorflow.js wasm version - with Web Worker Not Main Thread - don't request upload a server. - only client side nsfw validate.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;nsfw.tlnd.cc&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Tensorflow의 wasm 버전과 Web Worker를 이용하여 빠른 모델로드 그리고 빠른 연산 수행을 진행하며,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메인스레드의 부하를 주지 않아 쾌적한 nsfw 체크가 가능합니다.&lt;/p&gt;</description>
      <category>Develop/Javascript</category>
      <category>NSFW</category>
      <category>SFW</category>
      <category>ㅎㅂ</category>
      <category>ㅎㅂㅈㅇ</category>
      <category>후방주의</category>
      <author>TL&amp;amp;D</author>
      <guid isPermaLink="true">https://gmyankee.tistory.com/383</guid>
      <comments>https://gmyankee.tistory.com/entry/NSFWJS-%EB%A5%BC-%EB%B9%A0%EB%A5%B4%EA%B2%8C-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0#entry383comment</comments>
      <pubDate>Mon, 5 Dec 2022 18:47:23 +0900</pubDate>
    </item>
    <item>
      <title>Gorm 에서 constraint로 OnDelete 설정이 안될 때</title>
      <link>https://gmyankee.tistory.com/entry/Gorm-%EC%97%90%EC%84%9C-constraint%EB%A1%9C-OnDelete-%EC%84%A4%EC%A0%95%EC%9D%B4-%EC%95%88%EB%90%A0-%EB%95%8C</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Go언어 에서 많은 ORM이 있지만, 여러가지 써보아도 결국 GORM으로 회귀하게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;매우 많은 기능과 이미 많이 쌓인 커뮤니티 그리고 사용이 쉽기 때문이죠.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 제약사항 설정 중 on delete CASCADE를 설정한다던가 SET NULL 을 넣는다 등을 Auto Migrate 과정에서 진행하고 싶을 수 도 있습니다. 당연히 ORM 코드상에서 명시하여 DB에 자동설정이 되어야 orm을 쓰는 의미가 있기도 하구요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Node.js의 대부분 ORM들은 물리적 db에 이과정을 진행하지 않는 경우가 많긴 하지만요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 foreignKey에 constraint를 넣어도 물리 DB상에서는 constraint로 on delete on update가 적용되지 않는 현상이 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이럴 경우 &lt;span&gt;GORM에서는&lt;span&gt; &lt;/span&gt;&lt;/span&gt;이를 검증하지만 실제 Table에서는 CASCADE가 실제로 설정되지 않았기 때문에 오류가 발생합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 와 같은 현상이 발생한 가장 큰 이유는 GORM의 명시 &lt;b&gt;선언의 우선순위&lt;/b&gt;가 문제가 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/go-gorm/gorm/issues/4289#issuecomment-943366275&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/go-gorm/gorm/issues/4289#issuecomment-943366275&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1667045093118&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;MySQL Migration - OnUpdate / OnDelete CASCADE not being applied to schema &amp;middot; Issue #4289 &amp;middot; go-gorm/gorm&quot; data-og-description=&quot;Hi! Firstly, thanks for a great library, it is really intuitive and the documentation is excellent. However, I am having difficulty understanding why a constraint I am adding to my foreign keys is ...&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/go-gorm/gorm/issues/4289#issuecomment-943366275&quot; data-og-url=&quot;https://github.com/go-gorm/gorm/issues/4289&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/TOhxE/hyQn2MzSXa/CcGVjprenVbmHtko1CQVkK/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/go-gorm/gorm/issues/4289#issuecomment-943366275&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/go-gorm/gorm/issues/4289#issuecomment-943366275&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/TOhxE/hyQn2MzSXa/CcGVjprenVbmHtko1CQVkK/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;MySQL Migration - OnUpdate / OnDelete CASCADE not being applied to schema &amp;middot; Issue #4289 &amp;middot; go-gorm/gorm&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Hi! Firstly, thanks for a great library, it is really intuitive and the documentation is excellent. However, I am having difficulty understanding why a constraint I am adding to my foreign keys is ...&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;위 댓글 내용 처럼 호출하는 부모 모델상에서 constraint를 걸어주고 실제 Table에서 확인을 해보면 적용이 되는 것을 볼 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Tutorial &amp;amp; Training</category>
      <category>Cascade</category>
      <category>constraint</category>
      <category>gorm</category>
      <category>on_delete</category>
      <category>on_update</category>
      <category>set null</category>
      <category>strcit</category>
      <category>제약사항</category>
      <author>TL&amp;amp;D</author>
      <guid isPermaLink="true">https://gmyankee.tistory.com/382</guid>
      <comments>https://gmyankee.tistory.com/entry/Gorm-%EC%97%90%EC%84%9C-constraint%EB%A1%9C-OnDelete-%EC%84%A4%EC%A0%95%EC%9D%B4-%EC%95%88%EB%90%A0-%EB%95%8C#entry382comment</comments>
      <pubDate>Sat, 29 Oct 2022 21:05:41 +0900</pubDate>
    </item>
    <item>
      <title>NSFWJS + TFJS WASM + Web Worker</title>
      <link>https://gmyankee.tistory.com/entry/NSFWJS-TFJS-WASM-Web-Worker</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;한국어로는 후방주의 ㅎㅂ) 이런식으로 혼자있을때가 아닌 경우 음란물이 있을 수 있으니 주의하라는 의미로 많이 사용하는 용어인데, 영어로는 &lt;span&gt;nsfw(not safe for work)&lt;span&gt;&amp;nbsp;라고 표현합니다.&lt;/span&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;a href=&quot;https://github.com/infinitered/nsfwjs&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;nsfwjs&lt;/a&gt;는 Tensorflow의 JS버전인 tfjs를 사용하여 mobile net 버전의 모델을 사용해서 client side에서 성인 이미지를 판별하는 오픈소스입니다.&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;span&gt;하지만 첫 페이지 접근시 모델을 불러오는 속도가 굉장히 느립니다.&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/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;이 문제를 해결하기 위해서 저는 nsfwjs의 코드가 그리많지 않았고, &lt;b&gt;Tensorflow js&lt;/b&gt;를 사용하는것을 확인해서&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;a href=&quot;https://github.com/tensorflow/tfjs/tree/master/tfjs-backend-wasm&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;TFJS WASM&lt;/a&gt; 버전으로 &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;직접 만들게 되었습니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Demo&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://nsfw.tlnd.cc&quot;&gt;https://nsfw.tlnd.cc&lt;/a&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1670233448542&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;NSFW JS + WASM on Web Worker&quot; data-og-description=&quot;- with Tensorflow.js wasm version - with Web Worker Not Main Thread - don't request upload a server. - only client side nsfw validate.&quot; data-og-host=&quot;nsfw.tlnd.cc&quot; data-og-source-url=&quot;https://nsfw.tlnd.cc&quot; data-og-url=&quot;https://nsfw.tlnd.cc&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/CcPkZ/hyQNYpeqY7/YLkdPPRezcKA5qeR3e6ysK/img.png?width=512&amp;amp;height=512&amp;amp;face=0_0_512_512&quot;&gt;&lt;a href=&quot;https://nsfw.tlnd.cc&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://nsfw.tlnd.cc&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/CcPkZ/hyQNYpeqY7/YLkdPPRezcKA5qeR3e6ysK/img.png?width=512&amp;amp;height=512&amp;amp;face=0_0_512_512');&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;NSFW JS + WASM on Web Worker&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;- with Tensorflow.js wasm version - with Web Worker Not Main Thread - don't request upload a server. - only client side nsfw validate.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;nsfw.tlnd.cc&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;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span&gt;&lt;span&gt;그래서 이게 뭔데?&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;b&gt;서버 없이 Javascript&lt;/b&gt; 만 사용해서, &lt;b&gt;성인 이미지를 판별&lt;/b&gt;할 수 있는 &lt;b&gt;코드&lt;/b&gt; 입니다.&lt;/span&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span&gt;&lt;span&gt;문제점&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 tfjs wasm을 사용했을때는 첫 페이지 접근시 메인스레드에 영향은 없지만, 첫 호출시에는 모델을 로드할때 nsfwjs 와 마찬가지로 메인스레드에 부하가 심해, &lt;b&gt;브라우저가 멈추는 현상&lt;/b&gt;이 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 시간이 짧으면 괜찮지만, 사양에 따라서 &lt;b&gt;2~7초&lt;/b&gt; 정도 소요되었는데&amp;nbsp;이걸 개선하기 위해 &lt;b&gt;Web Worker를 사용&lt;/b&gt;하여 백그라운드 스레드를 이용해 메인스레드에 영향이 없도록 &lt;b&gt;개선&lt;/b&gt;하는 방법을 착안했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&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;결과&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;356&quot; data-origin-height=&quot;197&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/PqnJP/btrO9CPvdql/a6js1MZ9XFv9aVqcF98yYk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/PqnJP/btrO9CPvdql/a6js1MZ9XFv9aVqcF98yYk/img.png&quot; data-alt=&quot;NSFWJS의 결과&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/PqnJP/btrO9CPvdql/a6js1MZ9XFv9aVqcF98yYk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FPqnJP%2FbtrO9CPvdql%2Fa6js1MZ9XFv9aVqcF98yYk%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;356&quot; height=&quot;197&quot; data-origin-width=&quot;356&quot; data-origin-height=&quot;197&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;NSFWJS의 결과&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;514&quot; data-origin-height=&quot;47&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/K5TDW/btrO9Pajypa/yq4IfqybxpwSjJ638HkKw1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/K5TDW/btrO9Pajypa/yq4IfqybxpwSjJ638HkKw1/img.png&quot; data-alt=&quot;상단: TFJS WASM / 하단 TFJS WASM + Webworker&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/K5TDW/btrO9Pajypa/yq4IfqybxpwSjJ638HkKw1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FK5TDW%2FbtrO9Pajypa%2Fyq4IfqybxpwSjJ638HkKw1%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;514&quot; height=&quot;47&quot; data-origin-width=&quot;514&quot; data-origin-height=&quot;47&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;상단: TFJS WASM / 하단 TFJS WASM + Webworker&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;NSFWJS와 비교했을때 약간의 오차가 있기는 하지만, 이미지를 판별하는데 있어서는 문제가 될 정도는 아닙니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메인스레드와도 오차가 있기는 한데 그것도 판별하는데 있어서 문제가 될 정도의 수치는 아닙니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;카카오 비전 성인 이미지 판별 API와 비교했을때는 더이상 모델 학습을 안하는지 생각보다 좋은 결과를 주지 못합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 adult 점수만 매기기 때문에, 굉장히 애매모호합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;무료인데 서버도 없이 이렇게 판단할 수 있다는 것은 굉장히 강력하다고 생각됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또 누군가에게는 반드시 필요로 할 것이라 생각해서 오픈소스로 공개합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 코드는 아래에서 확인하실 수 있습니다.&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;기호에 맞게 Hentai, Porn, Drawing, Sexy, Neutral 문구를 변경해서 사용하시면 됩니다.&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;a href=&quot;https://gist.github.com/YankeeTube/ee96f60f57b9038ee0b703fc6620e7d9&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://gist.github.com/YankeeTube/ee96f60f57b9038ee0b703fc6620e7d9&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1666244400073&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;So Very Fast NSFWJS on TFJS WASM + Web Worker&quot; data-og-description=&quot;So Very Fast NSFWJS on TFJS WASM + Web Worker. GitHub Gist: instantly share code, notes, and snippets.&quot; data-og-host=&quot;gist.github.com&quot; data-og-source-url=&quot;https://gist.github.com/YankeeTube/ee96f60f57b9038ee0b703fc6620e7d9&quot; data-og-url=&quot;https://gist.github.com/YankeeTube/ee96f60f57b9038ee0b703fc6620e7d9&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cwC4ve/hyQaydH9Ps/63QupYDHt9Wo3ay84GJJBK/img.png?width=1280&amp;amp;height=640&amp;amp;face=0_0_1280_640&quot;&gt;&lt;a href=&quot;https://gist.github.com/YankeeTube/ee96f60f57b9038ee0b703fc6620e7d9&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://gist.github.com/YankeeTube/ee96f60f57b9038ee0b703fc6620e7d9&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cwC4ve/hyQaydH9Ps/63QupYDHt9Wo3ay84GJJBK/img.png?width=1280&amp;amp;height=640&amp;amp;face=0_0_1280_640');&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;So Very Fast NSFWJS on TFJS WASM + Web Worker&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;So Very Fast NSFWJS on TFJS WASM + Web Worker. GitHub Gist: instantly share code, notes, and snippets.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;gist.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>Develop/Javascript</category>
      <category>NSFW</category>
      <category>nsfwjs</category>
      <category>tensorflow</category>
      <category>tensorflow js</category>
      <category>tfjs</category>
      <category>WASM</category>
      <category>web worker</category>
      <category>ㅎㅂ</category>
      <category>후방주의</category>
      <author>TL&amp;amp;D</author>
      <guid isPermaLink="true">https://gmyankee.tistory.com/381</guid>
      <comments>https://gmyankee.tistory.com/entry/NSFWJS-TFJS-WASM-Web-Worker#entry381comment</comments>
      <pubDate>Thu, 20 Oct 2022 14:42:18 +0900</pubDate>
    </item>
  </channel>
</rss>