<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>Trend IT</title>
    <link>https://show-me-the-money.tistory.com/</link>
    <description>안녕하세요!
6년차 풀스택 개발자 H입니다.
카카오채널에서 &amp;quot;개발자H&amp;quot;를 검색해보세요!</description>
    <language>ko</language>
    <pubDate>Sat, 16 May 2026 05:54:40 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>개발자_H</managingEditor>
    <image>
      <title>Trend IT</title>
      <url>https://tistory1.daumcdn.net/tistory/2843852/attach/787f43e526bb44f2af0cba5a6c46cd03</url>
      <link>https://show-me-the-money.tistory.com</link>
    </image>
    <item>
      <title>[AWS Event Bridge] AWS에서 간단하게 Scheduler 사용하는 방법</title>
      <link>https://show-me-the-money.tistory.com/entry/AWS-Event-Bridge-AWS%EC%97%90%EC%84%9C-%EA%B0%84%EB%8B%A8%ED%95%98%EA%B2%8C-Scheduler-%EC%82%AC%EC%9A%A9%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95</link>
      <description>&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 style=&quot;color: #000000; text-align: start;&quot;&gt;서비스의 백엔드를 개발할 때 흔하게 필요한 기능이 바로 스케줄링인데요.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;주기적으로 로직을 수행한다거나 푸시 예약 발송하는 작업이라던가 이런 기능들을 구현할 때 스케줄러를 사용하게 됩니다. 작은 서비스라면 프레임워크 레벨에서 라이브러리 형태로 쓸 수도 있구요. 이런 주기적인 로직 수행 작업이 서비스의 주요 기능이라 중요한 경우에는 Message Queue를 사용하기도 합니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;AWS Serverless Application Model(이하 SAM)로 서버리스 개발을 했을 때 아주 효과적으로 사용할 수 있는 스케줄러가 있습니다. 이번에 소개할 Event Bridge Scheduler죠.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;설정한 일정(Cron기반)이나 특정 주기로 자동으로 로직을 실행할 수 있습니다. 다양한 AWS 서비스들과 연동이 가능하기 때문에 서버리스 환경으로 개발한다면 충분히 좋은 선택지가 될꺼라고 생각합니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;이제 Event Bridge Scheduler를 사용해서 주기적으로 Lambda 함수를 실행시켜보겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3794&quot; data-origin-height=&quot;1864&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/VD1Ul/btsml3Hcelf/gFGIJv0hCnTvi5pscigQ2K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/VD1Ul/btsml3Hcelf/gFGIJv0hCnTvi5pscigQ2K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/VD1Ul/btsml3Hcelf/gFGIJv0hCnTvi5pscigQ2K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FVD1Ul%2Fbtsml3Hcelf%2FgFGIJv0hCnTvi5pscigQ2K%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;3794&quot; height=&quot;1864&quot; data-origin-width=&quot;3794&quot; data-origin-height=&quot;1864&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;먼저 일정 이름을 작성하고 일정 패턴을 선택합니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;일회성으로 실행하고 끝나도록 설정할 수도 있습니다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;반복된 일정으로 선택하면 유형을 선택할 수 있는데요. Cron기반이나 Rate(주기) 기반으로 설정할 수 있습니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;Cron은 스케줄러의 정규 표현식이라고 생각하면 됩니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;총 7개 필드로 구성되어 있으며 형식은 아래와 같습니다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; color: #000000; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;초 : 0~59까지의 값&lt;/li&gt;
&lt;li&gt;분 : 0~59까지의 값&lt;/li&gt;
&lt;li&gt;시 : 0~23까지의 값&lt;/li&gt;
&lt;li&gt;일 : 1~31까지의 값&lt;/li&gt;
&lt;li&gt;월 : 1~12 혹은 JAN ~ DEC까지의 값&lt;/li&gt;
&lt;li&gt;요일 : 0 ~ 6 혹은 SUN ~ SAT까지의 값&lt;/li&gt;
&lt;li&gt;연도 : empty or 1970 ~ 2099까지의 값&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;그리고 Cron 표현식을 사용할 때 특수문자를 쓸 수 있는데요. 특수문자의 의미도 같이 살펴보겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; color: #000000; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;* : 모든 값을 의미합니다.&lt;/li&gt;
&lt;li&gt;? : 특정한 값이 없음을 의미합니다.&lt;/li&gt;
&lt;li&gt;- : 범위를 뜻합니다. 예를 들어 수요일부터 금요일까지는 WED-FRI로 표현합니다.&lt;/li&gt;
&lt;li&gt;, : 특별한 값일 때만 동작합니다. 예를 들어 월, 목 지정하는 경우 MON, THU로 표현합니다.&lt;/li&gt;
&lt;li&gt;/ : 시작시간 / 단위를 의미합니다. 예를 들어 5분 정각에 10분 주기로 실행한다면 5/10으로 표현합니다.&lt;/li&gt;
&lt;li&gt;L : 일(day)에서 사용하면 마지막 일을 의미하고 요일에서는 마지막 요일을 의미합니다.&lt;/li&gt;
&lt;li&gt;W : 가장 가까운 평일을 의미합니다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;#: 몇 째 주의 특정 요일을 표현할 때 사용합니다. 예를 들어 3#2라고 하면 둘째 주 수요일(3번째)을 의미합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;예를 한번 들어보면,&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;yaml&quot; style=&quot;color: #000000; text-align: start;&quot;&gt;&lt;code&gt;# Cron 표현식
00 13 * * ? *&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;위의 표현식은 매일 13시 정각에 주어진 일을 실행하겠다는 의미가 됩니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;Cron 표현식에 넣으면 다음 10개가 실행될 날짜를 보여줍니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;의도한 것이 맞는지 확인 후 넘어갑니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1450&quot; data-origin-height=&quot;1718&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bye6hZ/btsl6MOr1Ld/nmqJhIHWVldWcVK9KBBmyk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bye6hZ/btsl6MOr1Ld/nmqJhIHWVldWcVK9KBBmyk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bye6hZ/btsl6MOr1Ld/nmqJhIHWVldWcVK9KBBmyk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbye6hZ%2Fbtsl6MOr1Ld%2FnmqJhIHWVldWcVK9KBBmyk%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;1450&quot; height=&quot;1718&quot; data-origin-width=&quot;1450&quot; data-origin-height=&quot;1718&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;스케줄러에 등록할 때 기간도 설정할 수 있습니다. 주기적으로 반복되는 일이지만 특정 기간만 사용하고 싶을 때(예를 들어, 이벤트 기간 동안 주기적으로 통계를 집계하는 람다함수를 실행한다던지)에 설정하면 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2246&quot; data-origin-height=&quot;1782&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bfw3Zf/btsmd2JWSHD/khvoUWzBJQJG62msnE97WK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bfw3Zf/btsmd2JWSHD/khvoUWzBJQJG62msnE97WK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bfw3Zf/btsmd2JWSHD/khvoUWzBJQJG62msnE97WK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbfw3Zf%2Fbtsmd2JWSHD%2FkhvoUWzBJQJG62msnE97WK%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;2246&quot; height=&quot;1782&quot; data-origin-width=&quot;2246&quot; data-origin-height=&quot;1782&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;이제 실행할 대상을 선택합니다. 템플릿 형식의 대상에서 AWS Lambda Invoke를 선택합니다. 스케줄러가 Lambda 함수를 실행시켜 줍니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1574&quot; data-origin-height=&quot;1780&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dBAboZ/btsml3tEGNf/lFxVz3xkyqPQSQK2TocRo1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dBAboZ/btsml3tEGNf/lFxVz3xkyqPQSQK2TocRo1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dBAboZ/btsml3tEGNf/lFxVz3xkyqPQSQK2TocRo1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdBAboZ%2Fbtsml3tEGNf%2FlFxVz3xkyqPQSQK2TocRo1%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;1574&quot; height=&quot;1780&quot; data-origin-width=&quot;1574&quot; data-origin-height=&quot;1780&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;새로운 Lambda 함수 코드를 작성할 수도 있고 AWS SAM에 등록된 Lambda 함수들 목록도 나타납니다. 원하는 함수를 선택하면 됩니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2078&quot; data-origin-height=&quot;1650&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Nf0C7/btsmktmnNWd/YoQZ7AVPuql1MdlPfJQz41/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Nf0C7/btsmktmnNWd/YoQZ7AVPuql1MdlPfJQz41/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Nf0C7/btsmktmnNWd/YoQZ7AVPuql1MdlPfJQz41/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FNf0C7%2FbtsmktmnNWd%2FYoQZ7AVPuql1MdlPfJQz41%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;2078&quot; height=&quot;1650&quot; data-origin-width=&quot;2078&quot; data-origin-height=&quot;1650&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;Lambda 함수를 스케줄러가 실행했는데 정상적으로 완료가 안될 수도 있습니다. 이럴 때를 대비해 재시도 정책을 설정할 수 있는데요.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;먼저 완료가 되지 않은 이벤트를 유지하는 시간을 설정합니다. 특별한 이유가 없다면 기본값을 사용하는 것도 좋습니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;재시도 횟수도 서비스 특성에 맞게 설정합니다. 중요한 로직이라면 재시도 횟수를 높게 설정하는 것이 적합할 수 있습니다. 설정된 재시도 횟수만큼 재시도한 뒤에도 제대로 완료되지 않으면 해당 이벤트가 삭제됩니다. 이때, 실패한 이벤트가 무시되지 않고 끝까지 처리되어야 하는 경우 Dead-Letter Queue(DLQ)를 구성하면 됩니다. 실패한 이벤트들을 저장했다가 처리하는 Amazon SQS(Simple Queue Service)입니다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2158&quot; data-origin-height=&quot;1774&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ro6YW/btsml4TDdw6/OcNZVp7Okggv4nbgToqbe0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ro6YW/btsml4TDdw6/OcNZVp7Okggv4nbgToqbe0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ro6YW/btsml4TDdw6/OcNZVp7Okggv4nbgToqbe0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fro6YW%2Fbtsml4TDdw6%2FOcNZVp7Okggv4nbgToqbe0%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;2158&quot; height=&quot;1774&quot; data-origin-width=&quot;2158&quot; data-origin-height=&quot;1774&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;권한 역시 중요한데요. Amazon SQS와 통합되어 있거나 다른 연동 서비스가 있는 경우 그에 맞는 역할과 권한이 설정되어야 합니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;이제 다음 버튼을 누르면 지금까지 설정한 내용들이 나옵니다. 확인 후, 문제없으면 저장을 눌러 스케줄러에 일정 등록을 완료합니다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;banner.gif&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;400&quot;&gt;&lt;a href=&quot;http://m.site.naver.com/1aseY&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ndQSn/btsmd1Eb1Tl/86nYuM7ezhn5R5a7hJXiR0/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/ndQSn/btsmd1Eb1Tl/86nYuM7ezhn5R5a7hJXiR0/img.gif&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;400&quot; data-filename=&quot;banner.gif&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;400&quot;/&gt;&lt;/a&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>개발을 파헤치다/서버 인프라</category>
      <category>AWS</category>
      <category>cron</category>
      <category>event bridge</category>
      <category>scheduler</category>
      <author>개발자_H</author>
      <guid isPermaLink="true">https://show-me-the-money.tistory.com/134</guid>
      <comments>https://show-me-the-money.tistory.com/entry/AWS-Event-Bridge-AWS%EC%97%90%EC%84%9C-%EA%B0%84%EB%8B%A8%ED%95%98%EA%B2%8C-Scheduler-%EC%82%AC%EC%9A%A9%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95#entry134comment</comments>
      <pubDate>Mon, 3 Jul 2023 17:12:55 +0900</pubDate>
    </item>
    <item>
      <title>[Python] Class Method와 Static Method 차이 쉽게 이해하기</title>
      <link>https://show-me-the-money.tistory.com/entry/Python-Class-Method%EC%99%80-Static-Method-%EC%B0%A8%EC%9D%B4-%EC%89%BD%EA%B2%8C-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;image.png&quot; data-origin-width=&quot;1487&quot; data-origin-height=&quot;645&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kPKwr/btse3Fz6mkt/zi4fFaFiatyDb5l0kiBep1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kPKwr/btse3Fz6mkt/zi4fFaFiatyDb5l0kiBep1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kPKwr/btse3Fz6mkt/zi4fFaFiatyDb5l0kiBep1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkPKwr%2Fbtse3Fz6mkt%2Fzi4fFaFiatyDb5l0kiBep1%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;1487&quot; height=&quot;645&quot; data-filename=&quot;image.png&quot; data-origin-width=&quot;1487&quot; data-origin-height=&quot;645&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;span style=&quot;color: #000000; text-align: start;&quot;&gt;class method와 static method는 상속에서 확실한 차이가 있습니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;이 둘 모두 클래스에서 객체를 생성하지 않고 바로 접근하는 정적 메서드의 역할을 하는데요.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;객체별로 달라지는 것이 아니기 때문에 흔히 유틸리티성 클래스를 만들 때 많이 사용합니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;기본적인 사용은 아래와 같이 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;python&quot; style=&quot;color: #000000; text-align: start;&quot;&gt;&lt;code&gt;class Test:
    @staticmethod
    def add(x,y) :
        return x + y

print Test.add(1,1) # 2

t = Test()
print t.add(1,1)  # 2
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;python에서는 다른 언어와는 다르게 정적 메서드임에도 불구하고 객체에서도 접근이 가능합니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;이 부분을 유의해야합니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;python&quot; style=&quot;color: #000000; text-align: start;&quot;&gt;&lt;code&gt;class Test:
    @classmethod
    def add(cls, x, y) :
        return x + y
        
print Test.add(1,1) # 2&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;classmethod는 첫 번째 인자로 객체 자신(self)이 반드시 들어갑니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;이렇게 사용하면 둘이 큰 차이가 없어 보입니다. 하지만 상속에서 둘의 결과가 명확하게 달라지는데요.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;pre class=&quot;ruby&quot; style=&quot;color: #000000; text-align: start;&quot;&gt;&lt;code&gt;class Language:
    default = &quot;English&quot;
    
    def __init__(self):
        self.show = '나의 언어는 ' + self.default
    @classmethod
    def class_my_language(cls):
        return cls()
        
    @staticmethod
    def static_my_language():
        return Language()
    
    def print_language(self):
        print(self.show)
        
class KoreanLanguage(Language):
    default = &quot;한국어&quot;
    &lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;reasonml&quot; style=&quot;color: #000000; text-align: start;&quot;&gt;&lt;code&gt;a = KoreanLanguage.static_my_language()
b = KoreanLanguage.class_my_language()

a.print_language() &amp;gt;&amp;gt; 나의 언어는 English
b.print_language() &amp;gt;&amp;gt; 나의 언어는 한국어&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;위의 결과에서도 알 수 있듯이 static method는 부모 클래스의 속성값을 가져옵니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;하지만 class method에서는 객체 자신(cls or self)을 활용해서 객체 자신의 클래스 속성을 가져오는 것을 알 수 있습니다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;</description>
      <category>개발을 파헤치다/쉽게 풀어쓴 개념</category>
      <author>개발자_H</author>
      <guid isPermaLink="true">https://show-me-the-money.tistory.com/133</guid>
      <comments>https://show-me-the-money.tistory.com/entry/Python-Class-Method%EC%99%80-Static-Method-%EC%B0%A8%EC%9D%B4-%EC%89%BD%EA%B2%8C-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0#entry133comment</comments>
      <pubDate>Mon, 15 May 2023 12:02:34 +0900</pubDate>
    </item>
    <item>
      <title>[AWS] SAM(Serverless Application Model)에 새로운 Lambda Layer 추가하는 방법 (feat. 초보자도 쌉가능)</title>
      <link>https://show-me-the-money.tistory.com/entry/AWS-SAMServerless-Application-Model%EC%97%90-%EC%83%88%EB%A1%9C%EC%9A%B4-Lambda-Layer-%EC%B6%94%EA%B0%80%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95-feat-%EC%B4%88%EB%B3%B4%EC%9E%90%EB%8F%84-%EC%8C%89%EA%B0%80%EB%8A%A5</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;다운로드.png&quot; data-origin-width=&quot;364&quot; data-origin-height=&quot;138&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cEaROO/btseQU5PuUk/sggkIhFoB6iY0VxnQ0bLcK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cEaROO/btseQU5PuUk/sggkIhFoB6iY0VxnQ0bLcK/img.png&quot; data-alt=&quot;Lambda Layers&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cEaROO/btseQU5PuUk/sggkIhFoB6iY0VxnQ0bLcK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcEaROO%2FbtseQU5PuUk%2FsggkIhFoB6iY0VxnQ0bLcK%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;364&quot; height=&quot;138&quot; data-filename=&quot;다운로드.png&quot; data-origin-width=&quot;364&quot; data-origin-height=&quot;138&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Lambda Layers&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;Lambda Layer는 Lambda 함수에서 사용하는 라이브러리들을 더 손쉽게 관리할 수 있게 해주는 도구인데요. Lambda 함수를 실제 서비스에 사용하다 보면 다양한 패키지들이 얽히고설키게 됩니다. 당연히 함수의 크기가 커지게 되고 관리 또한 불편합니다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;또, 어떤 패키지들은 런타임 환경을 다르게해야 돌아가는 경우도 있죠.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;이런 불편함을 해결해 줄 수 있는 것이 바로 Lambda Layer입니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;Layer라는 단어에서 느낄 수 있듯이, 여러 패키지가 합쳐진 Lambda 함수를 계층으로 나누는 것인데요. 즉, 여러 패키지들을 계층으로 나누어 따로 관리할 수 있는 것입니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;이렇게 하면 먼저 Lambda 함수의 크기가 줄어들게 됩니다. 필요한 패키지들을 Layer로 만들어서 관리하기 때문에 적용 여부를 설정하기도 훨씬 간편하죠.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;여기에서는 AWS SAM(Serverless Application Model) 프로젝트에서 Lambda Layer를 적용하는 방법을 알아보도록 하겠습니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;시나리오는 이렇습니다. 현재 구현 중인 API 서버가 있습니다. AWS SAM으로 구성되어 있고 각 API가 Lambda 함수와 연계되는 상황입니다. 데이터 분석을 위해 Mix Panel 패키지를 설치하려 하는데 이것을 Lambda Layer로 적용하려고 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;edited_Image (3).jpg&quot; data-origin-width=&quot;636&quot; data-origin-height=&quot;690&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kAETJ/btseSCpUcBt/Lz1deJHD0Xqd7O3hVzyhI0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kAETJ/btseSCpUcBt/Lz1deJHD0Xqd7O3hVzyhI0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kAETJ/btseSCpUcBt/Lz1deJHD0Xqd7O3hVzyhI0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkAETJ%2FbtseSCpUcBt%2FLz1deJHD0Xqd7O3hVzyhI0%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;345&quot; height=&quot;374&quot; data-filename=&quot;edited_Image (3).jpg&quot; data-origin-width=&quot;636&quot; data-origin-height=&quot;690&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;Lambda Layer를 적용하기 위해서는 패키지를 zip 파일로 압축해야하는데요.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;먼저 패키지 설치를 해야 합니다. 위의 프로젝트 구조를 보면 aws_lambdas에는 API 로직에 해당하는 Lambda 함수들이 모여있습니다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;aws_lambda_layers에는 패키지들이 zip으로 압축되어 모여있는데요.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;이것들을 SAM 프로젝트의 template.yaml에서 정의해 주면 됩니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;margin: 15px 0; text-align: center;&quot;&gt;
&lt;script src=&quot;https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-7266388803558468&quot;&gt;&lt;/script&gt;
&lt;!-- 본문 중간 광고 --&gt; &lt;ins class=&quot;adsbygoogle&quot; style=&quot;display: block;&quot; data-ad-client=&quot;ca-pub-7266388803558468&quot; data-ad-slot=&quot;5396402228&quot; data-ad-format=&quot;auto&quot; data-full-width-responsive=&quot;true&quot;&gt;&lt;/ins&gt;
&lt;script&gt;
     (adsbygoogle = window.adsbygoogle || []).push({});
&lt;/script&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;Layer로 올릴 패키지 zip 파일 생성&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;이제 패키지를 설치하겠습니다. 설치 이전에 먼저 알아두어야 할 사실이 있는데요.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;Lambda Layer에 적용할 패키지 설치는 반드시 python이라는 디렉터리 안에서 진행되어야 합니다. 이건 왜 그런 걸까요?&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;Lambda Layer는 여러 Lambda 함수들이 공통적으로 사용하게 됩니다. 각각의 Lambda 함수들은 Layer를 /opt 디렉터리 밑에 export해서 사용하게 됩니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;이때 PATH 환경변수를 참조하게 되는데요. 이 변수에 경로가 /opt/python으로 설정이 되어있습니다. 이것은 Layer들이 같은 디렉토리 구조를 갖게 만들어서 여러 Lambda 함수들이 Layer에 접근하여 패키지를 사용할 때 문제없이 동작하게 하기 위한 것입니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;즉, 경로 문제 때문에 디렉터리 구조를 통일한 것이죠. 그렇기 때문에 python이라는 디렉토리 안에 패키지를 설치하지 않으면 Lambda 함수 실행 시 module을 찾을 수 없다는 에러가 발생하게 됩니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;자, 그럼 이제 패키지를 설치해 봅시다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;프로젝트의 aws_lambda_layers 디렉터리로 이동한 뒤, python이라는 디렉토리를 생성합니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;jboss-cli&quot; style=&quot;color: #000000; text-align: start;&quot;&gt;&lt;code&gt;$ cd ./aws_lambda_layers
$ mkdir ./python&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;python 디렉토리 내에서 패키지를 설치해 줍니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;jboss-cli&quot; style=&quot;color: #000000; text-align: start;&quot;&gt;&lt;code&gt;$ cd ./python
$ pip3 install -t ./ mixpanel &quot;urllib3&amp;lt;2&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;이제 해당 패키지를 zip 파일로 압축합니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;jboss-cli&quot; style=&quot;color: #000000; text-align: start;&quot;&gt;&lt;code&gt;$ cd ../
$ zip -r python-mixpanel.zip ./python&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;urllib3 Lambda 이슈&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;앞서 mixpanel 패키지를 설치할 때 urllib3 &amp;lt;2라는 부분이 붙는데요. 이에 대한 얘기를 좀 해봐야 합니다. mixpanel 패키지를 설치하면 내부적으로 requests 패키지와 urllib3 패키지가 설치됩니다. 이때 urllib3 패키지에 이슈가 좀 있는데요. 2.0.3 버전으로 올라가면서 Boto3와 호환성 문제가 발생하게 되었습니다. Boto3는 AWS 서비스를 사용하기 위한 라이브러리인데요.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;{&quot;errorMessage&quot;:&lt;span&gt;&amp;nbsp;&lt;/span&gt;&quot;Unable to import module 'prompt_runner': cannot import name 'DEFAULT_CIPHERS' from 'urllib3.util.ssl_' (/var/task/urllib3/util/ssl_.py)&quot;,&amp;nbsp;&quot;errorType&quot;:&quot;Runtime.ImportModuleError&quot;,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&quot;requestId&quot;:&lt;span&gt;&amp;nbsp;&quot;5700983c-a460-4e87-bef6-6cbb309d1659&quot;,&amp;nbsp;&lt;/span&gt;&quot;stackTrace&quot;:[]}&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;Boto3와 urllib3 2.0.3 버전 호환성 문제 때문에 위와 같은 에러가 발생하게 됩니다. 따라서 이 문제를 해결하기 위해 mixpanel 패키지 설치 시 urllib3의 버전대를 2 버전 이하로 조정해줘야 합니다. urllib3&amp;lt;2라는 표현은 2 버전대 이하에서 가장 안정적인 패키지 버전으로 설치를 한다는 의미입니다. 이렇게 설치를 하고 zip으로 압축하면 에러 없이 Lambda 함수에서 안정적으로 실행됩니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;Lambda Layer 속성 정의&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;이제 template.yaml에 Lambda Layer 속성을 정의해야 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;dts&quot; style=&quot;color: #000000; text-align: start;&quot;&gt;&lt;code&gt;# template.yaml

  LambdaLayerPythonMixPanel:
    Type: AWS::Serverless::LayerVersion
    Properties:
      LayerName: python-mixpanel
      ContentUri: ../aws_lambda_layers/python-mixpanel.zip
      CompatibleRuntimes:
        - python3.9
      RetentionPolicy: Retain
      
      &lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;위처럼 Layer zip 파일 위치와 이름 그리고 호환 런타임을 적어줍니다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;이렇게 정의를 하면 필요한 Lambda 함수에서 Layer 추가를 통해 사용할 수 있습니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;Lambda 함수에 Layer 적용&lt;/h2&gt;
&lt;pre class=&quot;bash&quot; style=&quot;color: #000000; text-align: start;&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;TestApi:
Type: AWS::Serverless::Function
Properties:
    FunctionName: TestApi
    CodeUri: TestApi
    Handler: lambda_function.lambda_handler
    Runtime: python3.9
    Role: !GetAtt RoleLambdaStepFunction.Arn
    Layers:
    - !Ref LambdaLayerPythonRequestsToolbelt
    - !Ref LambdaLayerPythonMixPanel
    Events:
    AnyMethod:
        Type: Api
        Properties:
        RestApiId: !Ref AuthorizerApi
        Auth:
            ApiKeyRequired: true
            Authorizer: UserAuthorizer
        Path: '/test-api'
        Method: ANY
Metadata:
    BuildMethod: makefile&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;이제 Lambda 함수를 정의할 때 Properties &amp;gt; Layers에 앞서 정의한 Lambda Layer 속성을 넣어주면 적용이 끝난 것입니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;이렇게 Layer를 정의해 두고 필요한 Lambda 함수에만 선택해서 적용할 수 있습니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;</description>
      <category>개발을 파헤치다/서버 인프라</category>
      <author>개발자_H</author>
      <guid isPermaLink="true">https://show-me-the-money.tistory.com/132</guid>
      <comments>https://show-me-the-money.tistory.com/entry/AWS-SAMServerless-Application-Model%EC%97%90-%EC%83%88%EB%A1%9C%EC%9A%B4-Lambda-Layer-%EC%B6%94%EA%B0%80%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95-feat-%EC%B4%88%EB%B3%B4%EC%9E%90%EB%8F%84-%EC%8C%89%EA%B0%80%EB%8A%A5#entry132comment</comments>
      <pubDate>Fri, 12 May 2023 18:13:59 +0900</pubDate>
    </item>
    <item>
      <title>[AWS DynamoDB] DynamoDB에서 Scan과 Query의 제대로 알고쓰기 (엄청난 성능차이...!)</title>
      <link>https://show-me-the-money.tistory.com/entry/AWS-DynamoDB-DynamoDB%EC%97%90%EC%84%9C-Scan%EA%B3%BC-Query%EC%9D%98-%EC%A0%9C%EB%8C%80%EB%A1%9C-%EC%95%8C%EA%B3%A0%EC%93%B0%EA%B8%B0-%EC%97%84%EC%B2%AD%EB%82%9C-%EC%84%B1%EB%8A%A5%EC%B0%A8%EC%9D%B4</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;데이터 조회는 DB를 사용할 때 아주 기본적인 기능이라고 할 수 있습니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;어떤 방식으로 데이터를 조회하느냐에 따라 성능이 달라지고 그만큼 서비스 질이 좌우되기도 하죠. 당연히 서비스 입장에서는 가능한 한 빨리 원하는 데이터를 찾아서 유저에게 보여주는 것이 좋습니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;DynamoDB는 I/O 성능과 확장성에 이점이 있는 데이터베이스인데요.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;이것도 특성을 제대로 알고 사용한다는 전제하에 의미가 있는 말입니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;Dynamo에서는 데이터 조회를 위해 두 가지 방식을 제공합니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;바로 Scan과 Query입니다. Scan과 Query 모두 item collection을 가져오기 위한 기능이지만 동작 방식은 상당히 다릅니다. 제대로 알&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;고 사용하느냐 마느냐에 따라 매우 큰 성능차이가 발생할 수 있습니다.&lt;/span&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-filename=&quot;Image (2).jpg&quot; data-origin-width=&quot;1716&quot; data-origin-height=&quot;894&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/QWM1q/btseQsV3Wzk/nZg1L8mN7fwbOgrWWNrcYK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/QWM1q/btseQsV3Wzk/nZg1L8mN7fwbOgrWWNrcYK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/QWM1q/btseQsV3Wzk/nZg1L8mN7fwbOgrWWNrcYK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQWM1q%2FbtseQsV3Wzk%2FnZg1L8mN7fwbOgrWWNrcYK%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;1716&quot; height=&quot;894&quot; data-filename=&quot;Image (2).jpg&quot; data-origin-width=&quot;1716&quot; data-origin-height=&quot;894&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;위 그림은 Dynamo를 사용해서 아이템을 가져오고 싶을 때 다양한 시나리오 중에서 어떤 방식을 쓰면 좋을지 나타낸 것인데요. 여기에서 Scan과 Query의 차이점을 알 수 있습니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;Scan은 일치하는 요소를 찾기 위해 전체 테이블을 조회하는 것입니다. 그래서 primary key나 secondary key 값이 없을 때 사용하죠. Dynamo는 파티션키와 범위키 두 가지를 통해 기본키를 정하는데요. 이 키값마저 모를 때 사용하는 것이 Scan입니다. 상당히 리소스가 많이 드는 방식이라 가능하면 사용하지 않는 게 좋겠죠. 특히 사용자가 요청하는 API에서는 Scan을 쓰는 것을 최대한 피해야 합니다. 이런 리소스 많이 먹는 요청이 동시다발적으로 들어오면 성능이 엄청 안 좋아질 테니깐요.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;Query의 경우 primary key나 secondary key값을 가지고 조회를 하기 때문에 훨씬 빠르게 찾아낼 수 있습니다. 도서관에서 책을 찾는다고 가정해 보죠. 도서관에는 정말 수많은 책들이 있습니다. Scan을 통해서 책을 찾는다는 것은 책 제목을 가지고 전체 도서관을 뒤지는 것을 의미합니다. 정말 오래 걸리겠죠? 하지만 Query로 찾게 된다면 지정된 구역의 몇 번째 칸이라는 정보를 알고서 찾는 것과 같습니다. 뒤져야 할 가짓수가 훨씬 적어져서 빠르게 찾을 수 있죠. 이런 특징 때문에 Query를 쓰려면 반드시 index가 설정이 되어있어야 합니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;위 그림에서 사용하는 GetItem이나 BatchGetItem 역시 Query와 마찬가지로 key값을 알고 있기 때문에 더 빠르게 아이템을 가져올 수 있습니다. 결국 key값을 알고 있느냐 없느냐로 Scan이냐 Query냐가 결정되는 것이죠.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;따라서 DynamoDB를 설계할 때 index를 잘 설정하는 것이 매우 중요합니다.&lt;/span&gt;&lt;/p&gt;</description>
      <category>개발을 파헤치다/서버 인프라</category>
      <author>개발자_H</author>
      <guid isPermaLink="true">https://show-me-the-money.tistory.com/131</guid>
      <comments>https://show-me-the-money.tistory.com/entry/AWS-DynamoDB-DynamoDB%EC%97%90%EC%84%9C-Scan%EA%B3%BC-Query%EC%9D%98-%EC%A0%9C%EB%8C%80%EB%A1%9C-%EC%95%8C%EA%B3%A0%EC%93%B0%EA%B8%B0-%EC%97%84%EC%B2%AD%EB%82%9C-%EC%84%B1%EB%8A%A5%EC%B0%A8%EC%9D%B4#entry131comment</comments>
      <pubDate>Thu, 11 May 2023 17:03:43 +0900</pubDate>
    </item>
    <item>
      <title>[AWS DynamoDB] PynamoDB 기본 사용법 정리(CRUD)</title>
      <link>https://show-me-the-money.tistory.com/entry/AWS-DynamoDB-PynamoDB-%EA%B8%B0%EB%B3%B8-%EC%82%AC%EC%9A%A9%EB%B2%95-%EC%A0%95%EB%A6%ACCRUD</link>
      <description>&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PynamoDB는 AWS의 DynamoDB를 Python에서 좀 더 쉽게 사용할 수 있도록 해주는 ORM 라이브러리입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PynamoDB를 통해서 table 생성을 비롯한 쿼리, 아이템 생성 등 기본적인 DB 데이터 조작을 할 수 있는데요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번에는 그 기본이 될 수 있는 item 생성 및 수정 삭제에 대해서 알아보도록 하겠습니다.&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;Model 사용하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;PynamoDB를 사용해서 기본적인 CRUD(Create, Read, Update, Delete)를 하는 방법을 살펴보겠습니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;먼저 테스트용 Model을 아래와 같이 생성합니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;pre class=&quot;isbl&quot; style=&quot;color: #000000; text-align: start;&quot;&gt;&lt;code&gt;from pynamodb.models import Model

class TestModel(Model):

    class Meta:
        region = &quot;ap-northeast-2&quot;
        table_name = &quot;test_table&quot;
        billing_mode = &quot;PAY_PER_REQUEST&quot;
        
    pk = UnicodeAttribute(hash_key=True)
    attr_1 = NumberAttribute(default=0)
    attr_2 = UnicodeAttribute(null=True)
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;item 생성하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;이제 위 TestModel에 새로운 아이템을 생성합니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;livecodeserver&quot; style=&quot;color: #000000; text-align: start;&quot;&gt;&lt;code&gt;item = TestModel()
item.pk = uuid.uuid1()
item.attr_1 = 10
item.attr_2 = &quot;attr2&quot;
item.save()&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;반드시 save 메서드를 호출해야 DB에 적용(commit)됩니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;item 수정하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;DynamoDB에서는 transaction을 비롯한 atomic operation을 지원하는데요.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;item update의 경우 atomic하게 item을 수정하는 것이 가능합니다. 또한, hash_key에 해당하는 item이 존재하지 않으면 생성까지 해줍니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #000000; text-align: start;&quot;&gt;&lt;code&gt;item = TestModel.get(hash_key=id)
item.update(actions=[
    TestModel.attr_1.set(20),
    TestModel.attr_2.set(&quot;value&quot;)
])&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;item 삭제&lt;/h3&gt;
&lt;pre class=&quot;livecodeserver&quot; style=&quot;color: #000000; text-align: start;&quot;&gt;&lt;code&gt;item = TestModel.get(hash_key=key)
item.delete()&lt;/code&gt;&lt;/pre&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;item 가져오기&lt;/h3&gt;
&lt;pre class=&quot;routeros&quot; style=&quot;color: #000000; text-align: start;&quot;&gt;&lt;code&gt;item = TestModel.get(hash_key=key)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;hash key값 혹은 hash key와 range key를 활용해서 특정 아이템을 가져올 수 있습니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;</description>
      <category>개발을 파헤치다/서버 인프라</category>
      <author>개발자_H</author>
      <guid isPermaLink="true">https://show-me-the-money.tistory.com/130</guid>
      <comments>https://show-me-the-money.tistory.com/entry/AWS-DynamoDB-PynamoDB-%EA%B8%B0%EB%B3%B8-%EC%82%AC%EC%9A%A9%EB%B2%95-%EC%A0%95%EB%A6%ACCRUD#entry130comment</comments>
      <pubDate>Mon, 8 May 2023 11:02:42 +0900</pubDate>
    </item>
    <item>
      <title>[AWS LightSail] LightSail에 5분만에 SSL 인증서 적용하는 방법 (이거보다 쉬운거 없음!!!)</title>
      <link>https://show-me-the-money.tistory.com/entry/AWS-LightSail-LightSail%EC%97%90-5%EB%B6%84%EB%A7%8C%EC%97%90-SSL-%EC%9D%B8%EC%A6%9D%EC%84%9C-%EC%A0%81%EC%9A%A9%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95-%EC%9D%B4%EA%B1%B0%EB%B3%B4%EB%8B%A4-%EC%89%AC%EC%9A%B4%EA%B1%B0-%EC%97%86%EC%9D%8C</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;Lightsail은 EC2에 비해 더 경량화된 서버 호스팅을 제공하는데요. 간단한 웹 서비스나, Wordpress를 서비스할 수 있도록 다양한 패키지도 제공합니다. EC2가 전문가용이라면 Lightsail은 일반용이라고 생각하면 편합니다. 웹사이트를 Lightsail을 통해 호스팅 하는 경우 SSL 인증서 적용을 해야 하는데요. 원래라면 인증서 구매부터 적용까지 좀 복잡한 과정을 거쳐야 하지만 여기서 제공하는 Let&amp;rsquo;s encrypt를 사용하면 5분 만에 SSL 인증서를 적용할 수 있습니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;Route53 도메인 설정&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;Let&amp;rsquo;s encrypt로 인증서를 설치하고 적용하려면 먼저 기본 세팅이 되어있어야합니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;AWS의 Route53에 해당 도메인 호스팅 영역이 설정이 되어있어야 합니다. 그리고 A 레코드를 생성해서 Lightsail 인스턴스와 연결을 해주어야 하는데요.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&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;2760&quot; data-origin-height=&quot;1916&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/LPtEA/btsdORQ0ryQ/n8FRfz420xEyMaWOZnb1W0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/LPtEA/btsdORQ0ryQ/n8FRfz420xEyMaWOZnb1W0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/LPtEA/btsdORQ0ryQ/n8FRfz420xEyMaWOZnb1W0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLPtEA%2FbtsdORQ0ryQ%2Fn8FRfz420xEyMaWOZnb1W0%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;2760&quot; height=&quot;1916&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;2760&quot; data-origin-height=&quot;1916&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;위처럼 A 레코드를 생성하고 라우팅 대상에 Lightsail의 public ip 혹은 static ip를 적어줍니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;만약 서브도메인을 활용하려면 A 레코드의 레코드 이름에 서브 도메인을 적어주면 됩니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;예를 들어,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;a style=&quot;text-align: start;&quot; href=&quot;http://example.com/&quot;&gt;example.com&lt;/a&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;도메인을 사용하는데 blog.example.com을 웹사이트 주소로 하고 싶다면 A 레코드에 blog.example.com을 적어주면 됩니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;이렇게 연결한 뒤 해당 도메인으로 접속해서 Lightsail에 세팅된 웹사이트가 정상적으로 나오는지 확인합니다. 만약 Wordpress가 설치되어 있다면 Wordpress 사이트가 나와야 합니다. 아직 SSL 인증서는 적용되지 않은 상태입니다.&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;div style=&quot;margin: 15px 0; text-align: center;&quot;&gt;
&lt;script src=&quot;https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-7266388803558468&quot;&gt;&lt;/script&gt;
&lt;!-- 본문 중간 광고 --&gt; &lt;ins class=&quot;adsbygoogle&quot; style=&quot;display: block;&quot; data-ad-client=&quot;ca-pub-7266388803558468&quot; data-ad-slot=&quot;5396402228&quot; data-ad-format=&quot;auto&quot; data-full-width-responsive=&quot;true&quot;&gt;&lt;/ins&gt;
&lt;script&gt;
     (adsbygoogle = window.adsbygoogle || []).push({});
&lt;/script&gt;
&lt;/div&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;edited_Image (1).jpg&quot; data-origin-width=&quot;2078&quot; data-origin-height=&quot;1666&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/buJjjo/btsdO2LRdHD/cZkWmKJcPjIOjWM0ub66d1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/buJjjo/btsdO2LRdHD/cZkWmKJcPjIOjWM0ub66d1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/buJjjo/btsdO2LRdHD/cZkWmKJcPjIOjWM0ub66d1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbuJjjo%2FbtsdO2LRdHD%2FcZkWmKJcPjIOjWM0ub66d1%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;2078&quot; height=&quot;1666&quot; data-filename=&quot;edited_Image (1).jpg&quot; data-origin-width=&quot;2078&quot; data-origin-height=&quot;1666&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;이제 Lightsail 콘솔에 들어갑니다. Route53에 연결된 인스턴스의 터미널 아이콘을 선택해서 SSH Console에 접속합니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;이제 아래 명령어를 입력합니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;armasm&quot; style=&quot;color: #000000; text-align: start;&quot;&gt;&lt;code&gt;$ sudo /opt/bitnami/bncert-tool&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;만약 업데이트하라고 뜬다면 y를 누른 후 다시 위 명령어를 입력해 줍니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&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;2086&quot; data-origin-height=&quot;1754&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bjGAhp/btsdTRuXpXH/0XH7tRScVofyCkQJWTpFv1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bjGAhp/btsdTRuXpXH/0XH7tRScVofyCkQJWTpFv1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bjGAhp/btsdTRuXpXH/0XH7tRScVofyCkQJWTpFv1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbjGAhp%2FbtsdTRuXpXH%2F0XH7tRScVofyCkQJWTpFv1%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;2086&quot; height=&quot;1754&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;2086&quot; data-origin-height=&quot;1754&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;이제 인증서 설치를 진행하는데요. SSL 인증서를 적용할 도메인을 입력합니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;그럼 www가 포함된 도메인도 함께 적용할 거냐고 물어보는데 원하면 y 아니면 n를 선택합니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;그리고 HTTP 요청이 올 때 HTTPS로 리다이렉션 할 것이냐고 물어보는데 y를 선택합니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;그럼 사용자가 http를 통해 접속해도 알아서 https 요청으로 바꿔주기 때문에 편리하고 좋습니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&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;2100&quot; data-origin-height=&quot;1784&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bGk37u/btsdRg3aMkm/zdXno9p2VQNlWQTzj0cTG1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bGk37u/btsdRg3aMkm/zdXno9p2VQNlWQTzj0cTG1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bGk37u/btsdRg3aMkm/zdXno9p2VQNlWQTzj0cTG1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbGk37u%2FbtsdRg3aMkm%2FzdXno9p2VQNlWQTzj0cTG1%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;2100&quot; height=&quot;1784&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;2100&quot; data-origin-height=&quot;1784&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;인증서를 설치하게 전에 안내사항이 나오고 동의하냐고 물어보는데요. y를 누르면 진행됩니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;이어서 이메일을 입력하고 Let&amp;rsquo;s Encrypt 구독에 동의하냐고 물어보면 y를 누릅니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;진행하게 되면 먼저 Web server를 멈추고 SSL 인증서를 설치하게 됩니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;Let&amp;rsquo;s encrypt 인증서는 무료이고 3개월마다 갱신해줘야 하는데요. 자동 갱신이 되도록 구독하는 설정을 하면 번거롭게 갱신할 필요가 없습니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;모든 설정을 적용하고 다시 Web Server를 시작해 주는데요. 이 과정이 2분 내외기 때문에 사이트가 오랫동안 다운되지는 않습니다. 만약 트래픽이 아주 많이 발생하는 사이트라면 사용자가 적은 시간에 진행하던지 미리 공지를 띄우고 진행하는 것이 좋습니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;가장 좋은 것은 사이트 생성할 때 SSL을 적용해 주는 것이겠죠.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2100&quot; data-origin-height=&quot;1282&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pnmrs/btsdRfDbTXW/FyIkKYf02Sq0HeeAKl5A10/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pnmrs/btsdRfDbTXW/FyIkKYf02Sq0HeeAKl5A10/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pnmrs/btsdRfDbTXW/FyIkKYf02Sq0HeeAKl5A10/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fpnmrs%2FbtsdRfDbTXW%2FFyIkKYf02Sq0HeeAKl5A10%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;2100&quot; height=&quot;1282&quot; data-origin-width=&quot;2100&quot; data-origin-height=&quot;1282&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;모든 설치가 완료되었습니다. 백업 파일의 위치를 알려주는데 참고하면 좋습니다. 문제가 생겼을 때 복원할 수 있으니까요.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;하지만 가장 편한 방법은 Lightsail Snapshot을 설치 전에 미리 생성해 놓고 문제가 생겼을 때 복원하는 것입니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;이제 설정한 도메인으로 접속해 보면 https가 적용되어 브라우저에서 안전한 사이트라고 뜨는 것을 확인할 수 있습니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;</description>
      <category>개발을 파헤치다/서버 인프라</category>
      <author>개발자_H</author>
      <guid isPermaLink="true">https://show-me-the-money.tistory.com/129</guid>
      <comments>https://show-me-the-money.tistory.com/entry/AWS-LightSail-LightSail%EC%97%90-5%EB%B6%84%EB%A7%8C%EC%97%90-SSL-%EC%9D%B8%EC%A6%9D%EC%84%9C-%EC%A0%81%EC%9A%A9%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95-%EC%9D%B4%EA%B1%B0%EB%B3%B4%EB%8B%A4-%EC%89%AC%EC%9A%B4%EA%B1%B0-%EC%97%86%EC%9D%8C#entry129comment</comments>
      <pubDate>Thu, 4 May 2023 11:59:44 +0900</pubDate>
    </item>
    <item>
      <title>[AWS S3] S3 Life Cycle 설정으로 비용 절감하는 방법</title>
      <link>https://show-me-the-money.tistory.com/entry/AWS-S3-S3-Life-Cycle-%EC%84%A4%EC%A0%95%EC%9C%BC%EB%A1%9C-%EB%B9%84%EC%9A%A9-%EC%A0%88%EA%B0%90%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;S3를 활용해서 이미지나 파일 리소스들을 저장하게 되면 대개의 경우 쓰지 않는 리소스들이 생기게 마련입니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;임시로 리소스를 업로드해 놓고 서버 어플리케이션에서 처리하게끔 구현하는 경우가 많은데요. 실제로 사용되지 않은 리소스들이 모여있을 때 낭비를 막기 위해 주기적으로 제거해 주면 비용 절감을 할 수 있겠죠.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;이럴 때 사용하는 것이 바로 S3의 Life Cycle인데요. 이번에는 임시 디렉토리에 업로드된 후 사용되지 않는 리소스들을 주기적으로 삭제하는 설정을 해보도록 하겠습니다.&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;div style=&quot;margin: 15px 0; text-align: center;&quot;&gt;
&lt;script src=&quot;https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-7266388803558468&quot;&gt;&lt;/script&gt;
&lt;!-- 본문 중간 광고 --&gt; &lt;ins class=&quot;adsbygoogle&quot; style=&quot;display: block;&quot; data-ad-client=&quot;ca-pub-7266388803558468&quot; data-ad-slot=&quot;5396402228&quot; data-ad-format=&quot;auto&quot; data-full-width-responsive=&quot;true&quot;&gt;&lt;/ins&gt;
&lt;script&gt;
     (adsbygoogle = window.adsbygoogle || []).push({});
&lt;/script&gt;
&lt;/div&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;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;S3의 bucket의 관리 탭에세 수명 주기 규칙 생성을 클릭합니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&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;1730&quot; data-origin-height=&quot;1676&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cFscr8/btsdPKig10A/bg0M60cIKZdrmNWBmshJBk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cFscr8/btsdPKig10A/bg0M60cIKZdrmNWBmshJBk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cFscr8/btsdPKig10A/bg0M60cIKZdrmNWBmshJBk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcFscr8%2FbtsdPKig10A%2Fbg0M60cIKZdrmNWBmshJBk%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;1730&quot; height=&quot;1676&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1730&quot; data-origin-height=&quot;1676&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;수명 주기 규칙 이름을 설정하고 규칙 범위를 선택합니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;버킷의 모든 객체에 적용하기 보다는 접두사(prefix) 필터링을 통해 특정 디렉토리의 리소스들을 삭제하는 것이 훨씬 효율적이겠죠.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;접두사를 입력할 때에는 앞에 /를 절대 입력하지 않도록 합니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;예를 들어 tmp 디렉토리 밑의 객체에 수명 주기를 적용하고 싶다면 위처럼 tmp/라고 접두사를 입력해야 합니다. /tmp라고 쓰면 에러가 발생합니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;이렇게 하려면 애초에 클라이언트에서 이미지 업로드하는 방식을 잘 설계하는 것이 중요합니다. 이 부분이 궁금하시다면 이전 포스트를 참고해 주세요.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://show-me-the-money.tistory.com/entry/AWS-S3-Pre-Signed-URL-%EC%B4%88%EA%B0%84%EB%8B%A8-%EC%82%AC%EC%9A%A9-%EB%B0%A9%EB%B2%95&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2023.04.24 - [개발을 파헤치다/서버 인프라] - AWS S3 Pre-Signed URL 초간단 사용 방법&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1683097332983&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;AWS S3 Pre-Signed URL 초간단 사용 방법&quot; data-og-description=&quot;보통 사용자가 S3 bucket에 접근해서 파일을 다운로드하거나 업로드하려면 3가지 방법이 가능합니다. public bucket으로 만들기 : 이렇게 구성하면 따로 관리할 필요 없이 모든 사용자가 S3 bucket에 파&quot; data-og-host=&quot;show-me-the-money.tistory.com&quot; data-og-source-url=&quot;https://show-me-the-money.tistory.com/entry/AWS-S3-Pre-Signed-URL-%EC%B4%88%EA%B0%84%EB%8B%A8-%EC%82%AC%EC%9A%A9-%EB%B0%A9%EB%B2%95&quot; data-og-url=&quot;https://show-me-the-money.tistory.com/entry/AWS-S3-Pre-Signed-URL-%EC%B4%88%EA%B0%84%EB%8B%A8-%EC%82%AC%EC%9A%A9-%EB%B0%A9%EB%B2%95&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/vZgRc/hySvro7p5K/EeyZKKdAUKS2eE13fFjtYk/img.png?width=800&amp;amp;height=551&amp;amp;face=0_0_800_551,https://scrap.kakaocdn.net/dn/bmOIH8/hyStW5m3Bg/4Cp88GyQJUjyWklQEkDMUK/img.png?width=800&amp;amp;height=551&amp;amp;face=0_0_800_551,https://scrap.kakaocdn.net/dn/lDy53/hySvpY8M5v/Y7jh0f0KlSMQdEujKYKba0/img.png?width=1210&amp;amp;height=834&amp;amp;face=0_0_1210_834&quot;&gt;&lt;a href=&quot;https://show-me-the-money.tistory.com/entry/AWS-S3-Pre-Signed-URL-%EC%B4%88%EA%B0%84%EB%8B%A8-%EC%82%AC%EC%9A%A9-%EB%B0%A9%EB%B2%95&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://show-me-the-money.tistory.com/entry/AWS-S3-Pre-Signed-URL-%EC%B4%88%EA%B0%84%EB%8B%A8-%EC%82%AC%EC%9A%A9-%EB%B0%A9%EB%B2%95&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/vZgRc/hySvro7p5K/EeyZKKdAUKS2eE13fFjtYk/img.png?width=800&amp;amp;height=551&amp;amp;face=0_0_800_551,https://scrap.kakaocdn.net/dn/bmOIH8/hyStW5m3Bg/4Cp88GyQJUjyWklQEkDMUK/img.png?width=800&amp;amp;height=551&amp;amp;face=0_0_800_551,https://scrap.kakaocdn.net/dn/lDy53/hySvpY8M5v/Y7jh0f0KlSMQdEujKYKba0/img.png?width=1210&amp;amp;height=834&amp;amp;face=0_0_1210_834');&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;AWS S3 Pre-Signed URL 초간단 사용 방법&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;보통 사용자가 S3 bucket에 접근해서 파일을 다운로드하거나 업로드하려면 3가지 방법이 가능합니다. public bucket으로 만들기 : 이렇게 구성하면 따로 관리할 필요 없이 모든 사용자가 S3 bucket에 파&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;show-me-the-money.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;2014&quot; data-origin-height=&quot;1862&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c5NfiU/btsdIpf1sg0/oNNwXl2LrDvBCP9xDywjWk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c5NfiU/btsdIpf1sg0/oNNwXl2LrDvBCP9xDywjWk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c5NfiU/btsdIpf1sg0/oNNwXl2LrDvBCP9xDywjWk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc5NfiU%2FbtsdIpf1sg0%2FoNNwXl2LrDvBCP9xDywjWk%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;2014&quot; height=&quot;1862&quot; data-origin-width=&quot;2014&quot; data-origin-height=&quot;1862&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;이제 수명 주기 규칙을 설정합니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;객체의 현재 버전 만료와 객체의 이전 버전 영구 삭제를 체크하면&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;업로드된 객체의 버전 만료 일수와 이전 버전 영구 삭제 일수를 설정할 수 있습니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;위와 같이 설정하면 업로드 된 후 1일 뒤에 버전이 만료되고 그 이후에 1일이 지나면 영구 삭제되게 됩니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;여기서 주의할 점이 있는데 Amazon S3에서 업로드 된 객체의 만료 날짜를 익일 자정(UTC 기준)부터 계산한다는 점입니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;예를 들어, 2023년 5월 1일 10:30(UTC)에 객체를 생성하고 3일 후에 만료되도록 수명 주기 규칙을 설정했다고 합시다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;그럼 실제 삭제 날짜는 2023년 5월 5일 00:00(UTC)이 됩니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;5월 2일 00:00(UTC)을 기준으로 3일 후를 계산하기 때문입니다. 따라서 규칙이 실행되는지 확인할 때 이 점을 유의해서 확인해야 합니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3596&quot; data-origin-height=&quot;1772&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cK0yvc/btsdJhaXX2E/CQ4FkOwlbKxmPIMT0Kk9G1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cK0yvc/btsdJhaXX2E/CQ4FkOwlbKxmPIMT0Kk9G1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cK0yvc/btsdJhaXX2E/CQ4FkOwlbKxmPIMT0Kk9G1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcK0yvc%2FbtsdJhaXX2E%2FCQ4FkOwlbKxmPIMT0Kk9G1%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;3596&quot; height=&quot;1772&quot; data-origin-width=&quot;3596&quot; data-origin-height=&quot;1772&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;저장을 누르면 수명 주기 규칙이 생성됩니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;</description>
      <category>개발을 파헤치다/서버 인프라</category>
      <author>개발자_H</author>
      <guid isPermaLink="true">https://show-me-the-money.tistory.com/128</guid>
      <comments>https://show-me-the-money.tistory.com/entry/AWS-S3-S3-Life-Cycle-%EC%84%A4%EC%A0%95%EC%9C%BC%EB%A1%9C-%EB%B9%84%EC%9A%A9-%EC%A0%88%EA%B0%90%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95#entry128comment</comments>
      <pubDate>Wed, 3 May 2023 16:03:02 +0900</pubDate>
    </item>
    <item>
      <title>[Git] SourceTree에서 여러 계정 같이 사용하는 꿀팁 (feat. 2023 최신)</title>
      <link>https://show-me-the-money.tistory.com/entry/Git-SourceTree%EC%97%90%EC%84%9C-%EC%97%AC%EB%9F%AC-%EA%B3%84%EC%A0%95-%EA%B0%99%EC%9D%B4-%EC%82%AC%EC%9A%A9%ED%95%98%EB%8A%94-%EA%BF%80%ED%8C%81-feat-2023-%EC%B5%9C%EC%8B%A0</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;SourceTree는 데스크톱 환경에서 편하게 Git이나 Bitbucket 같은 버전관리를 할 수 있도록 도와주는 GUI 툴입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;SourceTree를 사용하다보면 다양한 계정을 사용하고 싶은 상황이 생기는데요. 업무용 계정에 연결된 프로젝트도 있고, 개인적으로 진행하는 사이드 프로젝트와 연결된 계정도 있을 수 있잖아요. 여러 계정에 연결된 프로젝트들을 한 번에 SourceTree에서 관리할 수 있는 꿀팁을 알려드리겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;SourceTree에서는 여러 계정을 사용할 수 있는데요. 특정 Repository를 클론하기 위해서는 그에 맞는 권한을 가진 계정이 연동되어있어야 합니다.&lt;/span&gt;&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;1768&quot; data-origin-height=&quot;842&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cuUk3l/btscApBkskr/KRKbuNxgQt3ZyeTD3DV5a0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cuUk3l/btscApBkskr/KRKbuNxgQt3ZyeTD3DV5a0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cuUk3l/btscApBkskr/KRKbuNxgQt3ZyeTD3DV5a0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcuUk3l%2FbtscApBkskr%2FKRKbuNxgQt3ZyeTD3DV5a0%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;1768&quot; height=&quot;842&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1768&quot; data-origin-height=&quot;842&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;SourceTree &amp;gt; 설정 &amp;gt; 계정으로 들어갑니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;계정을 추가해서 OAuth, HTTPS를 선택하고 계정연결을 클릭합니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;그럼 브라우저상에 로그인된 Attlassian 계정으로 자동 연결됩니다. 추가할 계정을 로그인하고 계정 연결 버튼을 눌러서 계정을 추가합니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;그리고 다른 계정을 연결할 때에는 브라우저상에서 계정을 전환한 뒤 동일한 작업을 반복해 줍니다. 그럼 여러 개의 계정을 등록할 수 있습니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;계정이 모두 등록되면 특정 Repository를 가져올 때 권한 관련 에러가 뜨지 않게 됩니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;이제 로컬에 Repository를 클론 한 뒤에 프로젝트별 계정 설정을 어떻게 하는지 살펴보겠습니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&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;2456&quot; data-origin-height=&quot;1084&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BNwiR/btsczLdkUyu/XEgJL5fQspopad7Y9rqBh0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BNwiR/btsczLdkUyu/XEgJL5fQspopad7Y9rqBh0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BNwiR/btsczLdkUyu/XEgJL5fQspopad7Y9rqBh0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBNwiR%2FbtsczLdkUyu%2FXEgJL5fQspopad7Y9rqBh0%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;2456&quot; height=&quot;1084&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;2456&quot; data-origin-height=&quot;1084&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;프로젝트를 클릭한 뒤 오른쪽 상단에 설정에 들어갑니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&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;1118&quot; data-origin-height=&quot;1070&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/blwUau/btscGMoTFxg/CCCFfbCM1IJLcWFZkQgCa0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/blwUau/btscGMoTFxg/CCCFfbCM1IJLcWFZkQgCa0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/blwUau/btscGMoTFxg/CCCFfbCM1IJLcWFZkQgCa0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FblwUau%2FbtscGMoTFxg%2FCCCFfbCM1IJLcWFZkQgCa0%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;1118&quot; height=&quot;1070&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1118&quot; data-origin-height=&quot;1070&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;고급탭에 사용자 정보를 수정해 주면 되는데요. 기본적으로 전역 사용자 설정이 되어있습니다. 해당 프로젝트에서 다른 계정 정보를 사용하고 싶다면 전역 사용자 설정을 해제하고 알맞은 사용자이름(Username)과 이메일 주소를 적어주고 저장해 줍니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2084&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/AkWLg/btscGLjd7OU/LqA26CezHoSpfK5LZJefR1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/AkWLg/btscGLjd7OU/LqA26CezHoSpfK5LZJefR1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/AkWLg/btscGLjd7OU/LqA26CezHoSpfK5LZJefR1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FAkWLg%2FbtscGLjd7OU%2FLqA26CezHoSpfK5LZJefR1%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;2084&quot; height=&quot;1080&quot; data-origin-width=&quot;2084&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;설정을 저장하고 나와서 커밋창을 보면 인증정보가 변경된 것을 확인할 수 있습니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;이렇게 여러 개의 계정을 등록하고 프로젝트별로 그에 맞는 계정으로 버전관리를 진행할 수 있습니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;</description>
      <category>개발을 파헤치다/쉽게 풀어쓴 개념</category>
      <author>개발자_H</author>
      <guid isPermaLink="true">https://show-me-the-money.tistory.com/127</guid>
      <comments>https://show-me-the-money.tistory.com/entry/Git-SourceTree%EC%97%90%EC%84%9C-%EC%97%AC%EB%9F%AC-%EA%B3%84%EC%A0%95-%EA%B0%99%EC%9D%B4-%EC%82%AC%EC%9A%A9%ED%95%98%EB%8A%94-%EA%BF%80%ED%8C%81-feat-2023-%EC%B5%9C%EC%8B%A0#entry127comment</comments>
      <pubDate>Tue, 25 Apr 2023 18:38:52 +0900</pubDate>
    </item>
    <item>
      <title>AWS S3 Pre-Signed URL 초간단 사용 방법</title>
      <link>https://show-me-the-money.tistory.com/entry/AWS-S3-Pre-Signed-URL-%EC%B4%88%EA%B0%84%EB%8B%A8-%EC%82%AC%EC%9A%A9-%EB%B0%A9%EB%B2%95</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;보통 사용자가 S3 bucket에 접근해서 파일을 다운로드하거나 업로드하려면 3가지 방법이 가능합니다.&lt;/span&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal; color: #000000; text-align: start;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li style=&quot;list-style-type: decimal;&quot;&gt;public bucket으로 만들기 : 이렇게 구성하면 따로 관리할 필요 없이 모든 사용자가 S3 bucket에 파일을 올리거나 다운로드할 수 있습니다. 하지만 공개되서는 안 되는 파일에 대한 접근을 설정할 수 없다는 점이 단점입니다.&lt;/li&gt;
&lt;li style=&quot;list-style-type: decimal;&quot;&gt;IAM 자격증명 공유 : Access Key pari(access key, secret access key)를 설정해서 특정 사람만 저장소를 쓸 수 있게 제한하는 방법입니다. 하지만 관리가 힘들고 자격증명이 바뀌거나 유출될 경우 모든 사람에게 다시 key pair를 줘야 한다는 단점이 있습니다.&lt;/li&gt;
&lt;li style=&quot;list-style-type: decimal;&quot;&gt;IAM 사용자 역할 부여 : IAM을 통해 역할 권한을 부여합니다. 이렇게하면 지정한 사람만 저장소에 접근이 가능합니다. 하지만 여전히 관리가 불편하고 사용자 숫자 제한(5000개)이라는 제한사항이 존재합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;이렇게 Bucket 자체를 보안상의 이유로 공개적으로 운영하기는 좀 그렇고, 그렇다고 사용자에게 S3 접근권한을 설정하고 관리하기 버거울 때 사용하는 것이 바로 Pre-Signed Url입니다. 미리 서명된 URL이라는 의미인데요. 이 URL로 아래와 같은 일들을 할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; color: #000000; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;발급받은 URL로 파일을 다운로드 받거나 업로드할 수 있음&lt;/li&gt;
&lt;li&gt;URL의 만료기간을 설정하여 만료된 이후 접근을 제한할 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;굉장히 편리하겠죠?&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Image.jpg&quot; data-origin-width=&quot;1210&quot; data-origin-height=&quot;834&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/WttBs/btscwEj4tfg/m8XuTDSpdryTwmuZGKVh20/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/WttBs/btscwEj4tfg/m8XuTDSpdryTwmuZGKVh20/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/WttBs/btscwEj4tfg/m8XuTDSpdryTwmuZGKVh20/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FWttBs%2FbtscwEj4tfg%2Fm8XuTDSpdryTwmuZGKVh20%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;1210&quot; height=&quot;834&quot; data-filename=&quot;Image.jpg&quot; data-origin-width=&quot;1210&quot; data-origin-height=&quot;834&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;Pre-signed Url은 아래와 같은 흐름으로 사용합니다.&lt;/span&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal; color: #000000; text-align: start;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li style=&quot;list-style-type: decimal;&quot;&gt;사용자가 Pre-Signed Url 요청&lt;/li&gt;
&lt;li style=&quot;list-style-type: decimal;&quot;&gt;백엔드(앱서버)에서 Pre-Signed Url 생성을 S3에 요청&lt;/li&gt;
&lt;li style=&quot;list-style-type: decimal;&quot;&gt;S3에서 Pre-Signed Url을 발행&lt;/li&gt;
&lt;li style=&quot;list-style-type: decimal;&quot;&gt;백엔드에서 사용자에게 Pre-Signed Url 응답&lt;/li&gt;
&lt;li style=&quot;list-style-type: decimal;&quot;&gt;사용자가 Pre-Signed Url로 파일 업로드/다운로드&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;margin: 15px 0; text-align: center;&quot;&gt;
&lt;script src=&quot;https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-7266388803558468&quot;&gt;&lt;/script&gt;
&lt;!-- 본문 중간 광고 --&gt; &lt;ins class=&quot;adsbygoogle&quot; style=&quot;display: block;&quot; data-ad-client=&quot;ca-pub-7266388803558468&quot; data-ad-slot=&quot;5396402228&quot; data-ad-format=&quot;auto&quot; data-full-width-responsive=&quot;true&quot;&gt;&lt;/ins&gt;
&lt;script&gt;
     (adsbygoogle = window.adsbygoogle || []).push({});
&lt;/script&gt;
&lt;/div&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 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;Pre-signed URL을 쓰는 이유&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;Pre-signed Url은 주로 두 가지 목적으로 사용합니다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; color: #000000; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;보안상의 이유 : 앞에서 설명한 것처럼 완전히 Bucket을 오픈하지 않고 특정 사람에게만 공개해서 사용하기 위해 씁니다. 예를 들어, 회원 가입자나 결제한 사람에게만 특정 이미지 콘텐츠를 보여준다던지 하는 기능을 구현할 때 딱이겠죠.&lt;/li&gt;
&lt;li&gt;성능상의 이유 : 단순히 보안적인 이유로만 사용하지 않습니다. 보통 이미지 업로드를 비롯한 파일 업로드는 서버를 거치도록 구현합니다. 저장소에 서비스 관련 민감한 정보들이 저장될 수 있어 사용자가 직접 저장소에 접근하는 것은 보안적으로 문제가 발생할 가능성이 높기 때문이죠. 그래서 파일이 서버를 한번 거쳐서 S3에 저장되는 이중 작업을 해야 합니다.&lt;br /&gt;하지만 위에서처럼 서버에서는 Pre-Signed Url만 발행해 주고 사용자가 해당 Url을 통해서만 파일을 업로드하게 되면 앞의 이중작업이 필요 없게 됩니다. 훨씬 효율적이죠.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;Pre-Signed Url 발급하기&lt;/h3&gt;
&lt;pre class=&quot;python&quot; style=&quot;color: #000000; text-align: start;&quot;&gt;&lt;code&gt;&quot;&quot;&quot;
    클라이언트에서 AWS S3 업로드를 위한 Pre-signed Url을 생성하는 메서드 
&quot;&quot;&quot;
@classmethod
def get_pre_signed_url(cls, file_name: str, service_name: str, exp_time: int = 300) -&amp;gt; str:
    s3_client = boto3.client('s3')
    try:
        object_key = service_name + &quot;/&quot; + file_name
        response = s3_client.generate_presigned_url(
           ClientMethod='put_object',
            Params={
                'Bucket': BUCKET_NAME_CONTENTS,
                'Key': object_key
            },
            ExpiresIn=exp_time
        )
        return response
    except StorageError as e:
        raise e
            &lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;위 예제는 python에서 boto3(Python용 AWS SDK) 활용해서 Pre-signed Url을 생성하는 것인데요.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;Url 생성 메서드가 boto3에 있기 때문에 아주 쉽습니다. 다만, 들어가는 Parameter에 대해서는 제대로 알 필요가 있죠.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;generate_presigned_url 메서드에는 총 3개의 Parameter가 들어갑니다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal; color: #000000; text-align: start;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li style=&quot;list-style-type: decimal;&quot;&gt;Client Method : 사용자가 어떤 작업을 할 것인지 의미하는 Param. put_object는 파일 업로드, get_object는 파일 가져오기를 의미합니다. 또, URL을 통해 요청을 보낼 때 설정한 HTTP Method로 보내야 합니다. 예를 들어, put_object로 URL을 생성했다면 PUT Method로 요청을 보내야합니다.&lt;/li&gt;
&lt;li style=&quot;list-style-type: decimal;&quot;&gt;Params : S3 Bucket에 대한 정보와 파일이 저장될 키값(파일 이름)을 설정합니다.&lt;/li&gt;
&lt;li style=&quot;list-style-type: decimal;&quot;&gt;ExpiresIn : URL 만료 시간을 설정합니다. 단위는 초입니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;위 메서드를 실행하면 Pre-Signed Url이 리턴되게 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;Postman으로 이미지 업로드 해보기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;이제 Pre-Signed Url을 받았으면 실제로 사용해 봐야겠죠?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1514&quot; data-origin-height=&quot;636&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/QYlj2/btsca03jbY8/hifXPjX2EkfmIishYm8o91/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/QYlj2/btsca03jbY8/hifXPjX2EkfmIishYm8o91/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/QYlj2/btsca03jbY8/hifXPjX2EkfmIishYm8o91/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQYlj2%2Fbtsca03jbY8%2FhifXPjX2EkfmIishYm8o91%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;1514&quot; height=&quot;636&quot; data-origin-width=&quot;1514&quot; data-origin-height=&quot;636&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;해당 Url로 Postman을 통해 요청을 보내보겠습니다. PUT 메서드로 이미지 파일을 업로드해볼 건데요.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;파일을 업로드할 때 HTTP 요청의 Body에 파일을 Binary 형태로 담아서 보내게 됩니다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;위처럼 URL을 적고 알맞은 HTTP Method를 선택한 뒤, Body &amp;gt; binary를 선택합니다. 그럼 Select files 버튼이 나오는데 이걸로 보내려는 파일을 선택합니다. 그리고 요청을 보내면 200 OK 응답이 오게 됩니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;만약, 403 에러가 뜬다면 2가지 가능성이 있는데요.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal; color: #000000; text-align: start;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li style=&quot;list-style-type: decimal;&quot;&gt;URL이 만료된 경우 : 만료시간을 너무 짧게 설정해서 이미 사용할 수 없는 상태일 수 있습니다.&lt;/li&gt;
&lt;li style=&quot;list-style-type: decimal;&quot;&gt;잘못된 권한 접근인 경우 : 예를 들어 파일 가져오기(get_object)를 설정해서 URL을 생성했는데 막상 요청은 PUT으로 보내게 되면 설정 내용이 다르다며 실행이 거부됩니다.&lt;/li&gt;
&lt;/ol&gt;</description>
      <category>개발을 파헤치다/서버 인프라</category>
      <author>개발자_H</author>
      <guid isPermaLink="true">https://show-me-the-money.tistory.com/126</guid>
      <comments>https://show-me-the-money.tistory.com/entry/AWS-S3-Pre-Signed-URL-%EC%B4%88%EA%B0%84%EB%8B%A8-%EC%82%AC%EC%9A%A9-%EB%B0%A9%EB%B2%95#entry126comment</comments>
      <pubDate>Mon, 24 Apr 2023 19:34:07 +0900</pubDate>
    </item>
    <item>
      <title>JWT의 구조와 장단점</title>
      <link>https://show-me-the-money.tistory.com/entry/JWT%EC%9D%98-%EA%B5%AC%EC%A1%B0%EC%99%80-%EC%9E%A5%EB%8B%A8%EC%A0%90</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://show-me-the-money.tistory.com/entry/JWTJSON-Web-Token은-왜-쓸까-등장하게-된-배경&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2023.04.19 - [개발을 파헤치다/쉽게 풀어쓴 개념] - JWT(JSON Web Token)은 왜 쓸까? 등장하게 된 배경&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1682053426351&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;JWT(JSON Web Token)은 왜 쓸까? 등장하게 된 배경&quot; data-og-description=&quot;JWT는 무엇인가 JWT(JSON Web Token)는 웹상에서 사용되는 토큰에 대한 표준 규격(RFC 7519)을 얘기합니다. 특정 기술 이름이 아니라 HTTP처럼 표준을 정의한 것입니다. 의미를 한번 파헤쳐서 살펴보면 JSON&quot; data-og-host=&quot;show-me-the-money.tistory.com&quot; data-og-source-url=&quot;https://show-me-the-money.tistory.com/entry/JWTJSON-Web-Token은-왜-쓸까-등장하게-된-배경&quot; data-og-url=&quot;https://show-me-the-money.tistory.com/entry/JWTJSON-Web-Token%EC%9D%80-%EC%99%9C-%EC%93%B8%EA%B9%8C-%EB%93%B1%EC%9E%A5%ED%95%98%EA%B2%8C-%EB%90%9C-%EB%B0%B0%EA%B2%BD&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/HVcei/hySlNU05zP/1Mv12KJznyjdA7YpWUZzdK/img.jpg?width=310&amp;amp;height=163&amp;amp;face=0_0_310_163,https://scrap.kakaocdn.net/dn/bz9KiN/hySmWW2MoT/Tacci5ileLTUgO8cGMn9X0/img.jpg?width=310&amp;amp;height=163&amp;amp;face=0_0_310_163,https://scrap.kakaocdn.net/dn/CsmGj/hySlN8yFDC/EKFtWqIwUOh4pBTgHetYk1/img.png?width=1388&amp;amp;height=898&amp;amp;face=0_0_1388_898&quot;&gt;&lt;a href=&quot;https://show-me-the-money.tistory.com/entry/JWTJSON-Web-Token은-왜-쓸까-등장하게-된-배경&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://show-me-the-money.tistory.com/entry/JWTJSON-Web-Token은-왜-쓸까-등장하게-된-배경&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/HVcei/hySlNU05zP/1Mv12KJznyjdA7YpWUZzdK/img.jpg?width=310&amp;amp;height=163&amp;amp;face=0_0_310_163,https://scrap.kakaocdn.net/dn/bz9KiN/hySmWW2MoT/Tacci5ileLTUgO8cGMn9X0/img.jpg?width=310&amp;amp;height=163&amp;amp;face=0_0_310_163,https://scrap.kakaocdn.net/dn/CsmGj/hySlN8yFDC/EKFtWqIwUOh4pBTgHetYk1/img.png?width=1388&amp;amp;height=898&amp;amp;face=0_0_1388_898');&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;JWT(JSON Web Token)은 왜 쓸까? 등장하게 된 배경&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;JWT는 무엇인가 JWT(JSON Web Token)는 웹상에서 사용되는 토큰에 대한 표준 규격(RFC 7519)을 얘기합니다. 특정 기술 이름이 아니라 HTTP처럼 표준을 정의한 것입니다. 의미를 한번 파헤쳐서 살펴보면 JSON&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;show-me-the-money.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전 글에서는 JWT(JSON Web Token)이 등장하게 된 배경과 개념에 대해서 알아봤습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번에는 JWT의 구조와 장단점에 대해서 좀 더 명확하게 살펴보도록 하겠습니다.&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;JWT 구조&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;JWT로 인증을 하는 방식 자체는 Cookie&amp;amp;Session을 사용했을 때와 완전히 다르지는 않습니다. 하지만 JWT가 기존의 문제를 해결할 수 있는 이유는 서명된 토큰이라는 점. 그래서 사용자 식별 정보를 Token 자체에 담을 수 있다는 점입니다. 서명이 되어있기 때문에 서버에서 이 Token이 정상인지 아닌지 검증할 수 있습니다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;JWT는 아래와 같은 구조를 가지는데요.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; color: #000000; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Header : 토큰의 유형과 서명 알고리즘이 명시됩니다.&lt;/li&gt;
&lt;li&gt;Payload : 사용자의 인증/인가 정보가 포함됩니다.&lt;/li&gt;
&lt;li&gt;Signature : Header와 Payload가 개인키로 서명되어 저장됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;Header&lt;/h3&gt;
&lt;pre class=&quot;json&quot; style=&quot;color: #000000; text-align: start;&quot;&gt;&lt;code&gt;{
    &quot;typ&quot;: &quot;JWT&quot;,
    &quot;alg&quot;: &quot;HS512&quot;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;Header에는 위와 같이 토큰의 유형(typ)과 어떤 알고리즘(alg)을 사용했는지 명시됩니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;Payload&lt;/h3&gt;
&lt;pre class=&quot;json&quot; style=&quot;color: #000000; text-align: start;&quot;&gt;&lt;code&gt;{
    &quot;sub&quot;: &quot;1&quot;,
    &quot;iss&quot;: &quot;ori&quot;,
    &quot;exp&quot;: 1636989717,
    &quot;iat&quot;: 1636987917
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;Payload에는 보통 Claim이라고 하는 사용자의 인증에 대한 정보를 담고 있습니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;JWT의 장점은 인증을 위해 매번 DB 테이블을 조회할 필요가 없다는 점인데요.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;바로 Payload에 정보가 들어있기 때문에 가능합니다. Claim에 어떤 값을 넣을지는 개발자가 정할 수 있지만 JWT의 표준 스펙을 알아보는 게 먼저겠죠.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;표준 스펙상 Key값은 3글자로 되어있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; color: #000000; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;iss (Issuer) : 토큰 발급자&lt;/li&gt;
&lt;li&gt;sub (subject) : 인증 주체. 사용자에 대한 식별 값&lt;/li&gt;
&lt;li&gt;aud (audience) : 토큰 대상자. 클라이언트를 의미합니다&lt;/li&gt;
&lt;li&gt;exp (expiration time) : 토큰 만료 시간&lt;/li&gt;
&lt;li&gt;iat (issued at) : 토큰 발급 시간&lt;/li&gt;
&lt;li&gt;nbf ( not before) : 토큰 활성 날짜. 이 날짜 이전의 토큰은 활성화 되지 않음을 의미&lt;/li&gt;
&lt;li&gt;jti (JWT Id) : JWT 토큰 식별자. issur가 여러 명일 때 이를 구분하기 위한 값&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;표준 스펙으로 이렇게 정의가 되어있고 이것이 모두 들어갈 필요는 없습니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;서비스 특성이나 서버 아키텍처를 고려해서 정의하면 됩니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;중요한 원칙은 Payload에 민감한 정보를 담지 않는 것입니다. Header나 Payload는 json이 인코딩 되어있을 뿐이지 특별한 암호화가 걸려있는 것이 아니기 때문에 누구나 이 값을 가지고 디코딩을 한다면 Header나 Payload값을 알 수 있습니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;다시 말해서, JWT에는 단순히 식별을 하기 위한 정보만을 담아야합니다. 민감한 개인정보는 절대 넣어서는 안 됩니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;Signature&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2276&quot; data-origin-height=&quot;1294&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bJMWKo/btsbPXxbJHw/zv9RssKvPGAktv1H3hBdT1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bJMWKo/btsbPXxbJHw/zv9RssKvPGAktv1H3hBdT1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bJMWKo/btsbPXxbJHw/zv9RssKvPGAktv1H3hBdT1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbJMWKo%2FbtsbPXxbJHw%2Fzv9RssKvPGAktv1H3hBdT1%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;2276&quot; height=&quot;1294&quot; data-origin-width=&quot;2276&quot; data-origin-height=&quot;1294&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;위의 Signature 구조를 확인해 보면 JWT를 생성할 때 Base64로 인코딩 된 Header와 Payload를 개인키를 가지고 암호화합니다. 그 결과값이 Signature인 것이죠. 이 값은 서버에있는 개인키로만 암호화를 풀 수 있기때문에 클라이언트가 풀 수 있는 방법이 없습니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;JWT 인증과정을 살펴보면,&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; color: #000000; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;JWT를 헤더에 담아 클라이언트가 서버로 HTTP 요청을 보낸다&lt;/li&gt;
&lt;li&gt;서버가 개인키를 가지고 Signature를 복호화 한 다음, base64로 인코딩된 header와 payload를 디코딩하고 그 값이 일치하는지 확인한다.&lt;/li&gt;
&lt;li&gt;값이 일치하면 인증을 허용한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;만약 클라이언트가 payload에 조작된 값을 넣어 요청을 보내면 서버가 애초에 발급했던 정보와 다르므로 인증이 거부되겠죠.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;margin: 15px 0; text-align: center;&quot;&gt;
&lt;script src=&quot;https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-7266388803558468&quot;&gt;&lt;/script&gt;
&lt;!-- 본문 중간 광고 --&gt; &lt;ins class=&quot;adsbygoogle&quot; style=&quot;display: block;&quot; data-ad-client=&quot;ca-pub-7266388803558468&quot; data-ad-slot=&quot;5396402228&quot; data-ad-format=&quot;auto&quot; data-full-width-responsive=&quot;true&quot;&gt;&lt;/ins&gt;
&lt;script&gt;
     (adsbygoogle = window.adsbygoogle || []).push({});
&lt;/script&gt;
&lt;/div&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 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;JWT 장단점&lt;/h2&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;장점&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc; color: #000000; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이미 JWT 자체가 인증된 정보이기 때문에 세션 저장소와 같이 별도의 인증 관련 저장소가 필수적으로 필요하지 않습니다.&lt;/li&gt;
&lt;li&gt;클라이언트의 상태를 저장하지 않기 때문에 사용자가 많이 늘어나도 Session에 비해 크게 메모리를 차지하지 않습니다.&lt;/li&gt;
&lt;li&gt;사용자를 식별할 수 있는 정보가 토큰에 포함되어 있기 때문에 Session을 사용할 때와 달리 인증 관련 조회가 필요 없습니다.&lt;/li&gt;
&lt;li&gt;Cookie를 사용하지 않으므로 CORS(Cross-Origin Resource Sharing) 문제에서 자유롭습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;단점&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc; color: #000000; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;인증관련 특정한 기능을 구현할 때 한계가 있을 수 있습니다. 예를 들어, 현재 로그인된 사용자의 모든 장비들을 나열해 주는 것처럼 사용자의 상태값을 서버에서 알아야 하는 기능구현에는 제한사항이 있습니다.&lt;/li&gt;
&lt;li&gt;Cookie&amp;amp;Session과는 다르게 base64 인코딩을 통해 정보를 전달하므로 데이터의 크기가 큽니다. 네트워크 전달 시 부하가 더 생길 수 있습니다.&lt;/li&gt;
&lt;li&gt;Token을 탈취당하면 만료될 때까지 대처가 불가능하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;마지막 단점으로 쓴 Token 탈취에 대해서 부가적으로 설명을 드리겠습니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;Session의 경우 Cookie만 쓸 때에 비해 좋았던 점이 바로 보안적인 부분이었는데요.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;Session ID를 탈취당하더라도 저장소의 값을 지워서 인증이 안되도록 할 수 있었죠.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;하지만 JWT 같은 경우 한번 서버에서 발급을 하게 되면 클라이언트가 관리하는 형태이기 때문에 서버 쪽에서 조치할 수 있는 게 없습니다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;이런 경우 JWT 스펙에 나와있던 토큰 만료 시간(exp)을 짧게 가져가는 것으로 보완할 수 있는데요. 만료시간을 짧게 가져가면 토큰이 탈취된다고 해도 짧은 시간만 유효하기 때문에 피해를 최소화할 수 있겠죠.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;</description>
      <category>개발을 파헤치다/쉽게 풀어쓴 개념</category>
      <author>개발자_H</author>
      <guid isPermaLink="true">https://show-me-the-money.tistory.com/125</guid>
      <comments>https://show-me-the-money.tistory.com/entry/JWT%EC%9D%98-%EA%B5%AC%EC%A1%B0%EC%99%80-%EC%9E%A5%EB%8B%A8%EC%A0%90#entry125comment</comments>
      <pubDate>Fri, 21 Apr 2023 14:04:50 +0900</pubDate>
    </item>
  </channel>
</rss>