<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>Dove</title>
    <link>https://dpot.tistory.com/</link>
    <description>서버에 AWS 한 스푼..</description>
    <language>ko</language>
    <pubDate>Mon, 8 Jun 2026 05:44:08 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>dev.Dove</managingEditor>
    <image>
      <title>Dove</title>
      <url>https://tistory1.daumcdn.net/tistory/6329907/attach/b7d7774ac995480e895056881cc8a6e3</url>
      <link>https://dpot.tistory.com</link>
    </image>
    <item>
      <title>Header를 이용해 Spring Context에 timezone 세팅</title>
      <link>https://dpot.tistory.com/11</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;851&quot; data-origin-height=&quot;436&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kGAei/btsKT5vfTem/c6cHgWUYorRGbk1lNvbH2K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kGAei/btsKT5vfTem/c6cHgWUYorRGbk1lNvbH2K/img.png&quot; data-alt=&quot;https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/i18n/LocaleContextHolder.html&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kGAei/btsKT5vfTem/c6cHgWUYorRGbk1lNvbH2K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkGAei%2FbtsKT5vfTem%2Fc6cHgWUYorRGbk1lNvbH2K%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;851&quot; height=&quot;436&quot; data-origin-width=&quot;851&quot; data-origin-height=&quot;436&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/i18n/LocaleContextHolder.html&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LocaleResolver를 사용하면, API를 처리하는 로직에서 다국어를 처리할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쿠키를 사용하는 CookieLocaleResolver의 경우 timezone, locale을 지원해 준다. 하지만, Accept-Language를 사용할 경우 AcceptHeaderLocaleResolver를 사용하는데, AcceptHeaderLocaleResolver는 locale만 지원한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;들어가기 전&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;본 포스팅은 Spring Boot3기반으로 작성했습니다. 전체코드는 깃허브를 참고해 주세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/Dove-kim/spring-boot-3-localization&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/Dove-kim/spring-boot-3-localization&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1732332721737&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - Dove-kim/spring-boot-3-localization: Spring Boot 3 국제화 구현&quot; data-og-description=&quot;Spring Boot 3 국제화 구현. Contribute to Dove-kim/spring-boot-3-localization development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/Dove-kim/spring-boot-3-localization&quot; data-og-url=&quot;https://github.com/Dove-kim/spring-boot-3-localization&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bV7Slw/hyXzV1zved/WPgkWYI77ps5tX9qxDrLmk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/qTq5N/hyXzWNeMiY/UEnZKAUlOvxrhjm9FGrUn1/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/Dove-kim/spring-boot-3-localization&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/Dove-kim/spring-boot-3-localization&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bV7Slw/hyXzV1zved/WPgkWYI77ps5tX9qxDrLmk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/qTq5N/hyXzWNeMiY/UEnZKAUlOvxrhjm9FGrUn1/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;GitHub - Dove-kim/spring-boot-3-localization: Spring Boot 3 국제화 구현&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Spring Boot 3 국제화 구현. Contribute to Dove-kim/spring-boot-3-localization development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Timezone.. 이 Header에 필요한가요?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한국계 미국인이 아랍권 국가에서 서비스를 사용할 경우 다음과 같이 정보를 생각할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 언어 - 한국어&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 정책 - 미국&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. time zone - 아랍&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. App이 호출 할 때 쿠키를 사용하는 건 어떨까?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CookieLocaleResolver를 사용하면 timezone을 받을 수 있으나, 웹이 아닌 클라이언트도 쿠키를 세팅해야 하는 기이한 현상이 발생한다. 쿠키도 결국 헤더에 Set-Cookie로 값을 세팅하니, 쿠키의 원형은 결국 Header다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;플랫폼 간 API호출을 통일화하기 위해 쿠키보단 Header를 이용하는 것이 바람직해 보인다.&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;2. 클라이언트가 타임존을 확인해서 계산은 건 어떨까?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;괜찮은 방법이다. 이건 개발 시작전 인터페이스를 협의할 때 클라이언트 개발자와 잘 협의하면 해결된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클라이언트에서 시간을 타임존에 계산할 경우 서버는 unix timestamp나 UTC+00:00 기준 시간을 제공하고 클라이언트가 계산을 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 일부 레거시 서비스의 경우 클라이언트의 수정이 여러가지 원인에 의해 불가해서 서버가 계산을 해 줘야 할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 기본적으로 서버는 기준시간을 제공하여 클라이언트가 timezone을 계산하되 일부 API에서는 Header에 Timezone을 받을 수 있게 구현하는 걸 고려해 볼 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LocaleResoler를 이용하면, 서비스 레이어에서 필요할 경우 timezone을 사용할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Header를 이용해 timezone을 받도록 세팅하기 위해 CookieLocaleResolver를 먼저 확인해 보자&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;CookieLocaleResolver 내부는 Header와 무엇이 다른가?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CookieLocaleResolver는 AbstractLocaleContextResolver를 상속받았고, AcceptHeaderLocaleResolver는 AbstractLocaleResolver를 상속받았다.&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;724&quot; data-origin-height=&quot;87&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ddT2bx/btsKUlxRD1p/mUf4MQDN5Q1KAkRzx27KGk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ddT2bx/btsKUlxRD1p/mUf4MQDN5Q1KAkRzx27KGk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ddT2bx/btsKUlxRD1p/mUf4MQDN5Q1KAkRzx27KGk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FddT2bx%2FbtsKUlxRD1p%2FmUf4MQDN5Q1KAkRzx27KGk%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;724&quot; height=&quot;87&quot; data-origin-width=&quot;724&quot; data-origin-height=&quot;87&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;704&quot; data-origin-height=&quot;49&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cSztUe/btsKUj7UbHt/ybblKtavGiDkOBuno1f4m1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cSztUe/btsKUj7UbHt/ybblKtavGiDkOBuno1f4m1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cSztUe/btsKUj7UbHt/ybblKtavGiDkOBuno1f4m1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcSztUe%2FbtsKUj7UbHt%2FybblKtavGiDkOBuno1f4m1%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;704&quot; height=&quot;49&quot; data-origin-width=&quot;704&quot; data-origin-height=&quot;49&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: #333333; text-align: start;&quot;&gt;AbstractLocaleContextResolver는 AbstractLocaleResolver를 상속받고 timezone을 추가했다.&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;1007&quot; data-origin-height=&quot;119&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/VG3ou/btsKTDMALrM/kJde7MD8xr4VkwlJHhlQ21/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/VG3ou/btsKTDMALrM/kJde7MD8xr4VkwlJHhlQ21/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/VG3ou/btsKTDMALrM/kJde7MD8xr4VkwlJHhlQ21/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FVG3ou%2FbtsKTDMALrM%2FkJde7MD8xr4VkwlJHhlQ21%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;1007&quot; height=&quot;119&quot; data-origin-width=&quot;1007&quot; data-origin-height=&quot;119&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;그러면 AbstractLocaleContextResolver를 상속받아서 특정 Header값을 timezone으로 매핑하고 LocaleContext로 세팅하면 될 듯하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;구현해 보자&lt;/h2&gt;
&lt;pre id=&quot;code_1732334451531&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class AcceptHeaderLocaleAndTimeZoneResolver extends AbstractLocaleContextResolver {
    public static final String LOCALE_HEADER_ATTRIBUTE_NAME = &quot;Accept-Language&quot;;
    public static final String TIME_ZONE_HEADER_ATTRIBUTE_NAME = &quot;Accept-TimeZone&quot;;


    @Override
    public LocaleContext resolveLocaleContext(final HttpServletRequest request) {
        Locale locale = resolveLocale(request);
        TimeZone timeZone = resolveTimeZone(request);

        return new TimeZoneAwareLocaleContext() {
            @Override
            @Nullable
            public Locale getLocale() {
                return locale;
            }

            @Override
            @Nullable
            public TimeZone getTimeZone() {
                return timeZone;
            }
        };
    }

    @Override
    public Locale resolveLocale(HttpServletRequest request) {
        Locale defaultLocale = getDefaultLocale();
        String acceptLanguage = request.getHeader(LOCALE_HEADER_ATTRIBUTE_NAME);

        if (StringUtils.hasText(acceptLanguage)) {
            return Locale.forLanguageTag(acceptLanguage);
        } else {
            return (defaultLocale != null) ? defaultLocale : request.getLocale();
        }
    }

    private TimeZone resolveTimeZone(HttpServletRequest request) {
        String timeZoneHeader = request.getHeader(TIME_ZONE_HEADER_ATTRIBUTE_NAME);

        if (StringUtils.hasText(timeZoneHeader)) {
            try {
                ZoneId zoneId = ZoneId.of(timeZoneHeader);
                return TimeZone.getTimeZone(zoneId);
            } catch (DateTimeException e) {
                // 유효하지 않은 timeZoneHeader 값을 무시하고 기본 TimeZone을 설정
                return getDefaultTimeZone() != null ? getDefaultTimeZone() : TimeZone.getDefault();
            }
        } else {
            return getDefaultTimeZone() != null ? getDefaultTimeZone() : TimeZone.getDefault();
        }
    }

    @Override
    public void setLocaleContext(HttpServletRequest request, @Nullable HttpServletResponse response, @Nullable LocaleContext localeContext) {
        throw new UnsupportedOperationException(&quot;Cannot change HTTP headers - use a different locale resolution strategy&quot;);
    }

    @Override
    public void setLocale(HttpServletRequest request, @Nullable HttpServletResponse response, @Nullable Locale locale) {
        throw new UnsupportedOperationException(&quot;Cannot change HTTP Accept-Language header - use a different locale resolution strategy&quot;);
    }


}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만든 구현체를 Bean으로 등록하면 끝난다.&lt;/p&gt;
&lt;div style=&quot;background-color: #1e1f22; color: #bcbec4;&quot;&gt;
&lt;pre class=&quot;less&quot;&gt;&lt;code&gt;@Configuration
@EnableWebMvc
@RequiredArgsConstructor
public class WebConfig implements WebMvcConfigurer {

    @Bean
    public LocaleResolver localeResolver() {
        return new AcceptHeaderLocaleAndTimeZoneResolver();
    }

}
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;테스트 코드도 작성해 보자&lt;/h2&gt;
&lt;div style=&quot;background-color: #1e1f22; color: #bcbec4;&quot;&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;@WebMvcTest(MainController.class)
class MainControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @Test
    public void givenAcceptTimeZoneHeader_whenResolveTimeZone_thenTimeZoneIsSet() throws Exception {
        // Given
        String acceptTimeZone = &quot;Europe/Paris&quot;;
        TimeZone expectedTimeZone = TimeZone.getTimeZone(acceptTimeZone);

        // When
        String response = mockMvc.perform(get(&quot;/&quot;).header(&quot;Accept-TimeZone&quot;, acceptTimeZone))
                .andExpect(status().isOk())
                .andReturn()
                .getResponse()
                .getContentAsString();

        // Then
        Assertions.assertEquals(response, expectedTimeZone.getID());
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;496&quot; data-origin-height=&quot;100&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lGWQV/btsKT6AWPVf/d9LzwsKsht8ysZKWNt0FC0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lGWQV/btsKT6AWPVf/d9LzwsKsht8ysZKWNt0FC0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lGWQV/btsKT6AWPVf/d9LzwsKsht8ysZKWNt0FC0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlGWQV%2FbtsKT6AWPVf%2Fd9LzwsKsht8ysZKWNt0FC0%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;496&quot; height=&quot;100&quot; data-origin-width=&quot;496&quot; data-origin-height=&quot;100&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Spring Boot 2.1부터는 이미 정의한 Bean의 Overrideing을 불허한다..?&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2093&quot; data-origin-height=&quot;274&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cZNCeb/btsKTjHWzjh/EU8CQmMmndro6bVORq3anK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cZNCeb/btsKTjHWzjh/EU8CQmMmndro6bVORq3anK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cZNCeb/btsKTjHWzjh/EU8CQmMmndro6bVORq3anK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcZNCeb%2FbtsKTjHWzjh%2FEU8CQmMmndro6bVORq3anK%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;2093&quot; height=&quot;274&quot; data-origin-width=&quot;2093&quot; data-origin-height=&quot;274&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;Resolver를 등록하면 위 스크린샷처럼 에러가 발생한다.&lt;/p&gt;
&lt;pre id=&quot;code_1732334808867&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;The bean 'localeResolver', defined in class path resource [com/dove/config/WebConfig.class], could not be registered. A bean with that name has already been defined in class path resource [org/springframework/web/servlet/config/annotation/DelegatingWebMvcConfiguration.class] and overriding is disabled.&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;Spring Boot 2.1부터 스프링은 이 정의된 Bean의 오버라이딩을 막았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 해결하기 위해 오버라이딩을 허용해 준다.&lt;/p&gt;
&lt;pre id=&quot;code_1732334905702&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;spring:
  main:
    allow-bean-definition-overriding: true&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;참고한 글&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.baeldung.com/spring-boot-bean-definition-override-exception#configuration-change-for-spring-boot&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.baeldung.com/spring-boot-bean-definition-override-exception#configuration-change-for-spring-boot&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>개발 고민</category>
      <category>header timezone</category>
      <category>LocaleResolver</category>
      <category>spring</category>
      <category>spring boot</category>
      <category>TimeZone</category>
      <author>dev.Dove</author>
      <guid isPermaLink="true">https://dpot.tistory.com/11</guid>
      <comments>https://dpot.tistory.com/11#entry11comment</comments>
      <pubDate>Sat, 23 Nov 2024 13:10:17 +0900</pubDate>
    </item>
    <item>
      <title>EC2를 이용한 AWS ECS 기반 Spring Boot 3 DataDog 적용</title>
      <link>https://dpot.tistory.com/10</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;4000&quot; data-origin-height=&quot;3000&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/czZOnY/btsJTqgQuIi/9GsThIe5omfd94Fr9TKRsK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/czZOnY/btsJTqgQuIi/9GsThIe5omfd94Fr9TKRsK/img.png&quot; data-alt=&quot;글과 상관없는 DataDog live Seoul 2024&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/czZOnY/btsJTqgQuIi/9GsThIe5omfd94Fr9TKRsK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FczZOnY%2FbtsJTqgQuIi%2F9GsThIe5omfd94Fr9TKRsK%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;4000&quot; height=&quot;3000&quot; data-origin-width=&quot;4000&quot; data-origin-height=&quot;3000&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;글과 상관없는 DataDog live Seoul 2024&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;들어가기 전...&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인프라: AWS ECS, AWS EC2, AWS Linux 2023&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서버: Spring Boot 3(Java 17), Micrometer&amp;nbsp;Tracing&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;결말 미리 보기&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1020&quot; data-origin-height=&quot;568&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bcBviC/btsJS72Nluz/jjtDk7xklRrmMOFevbhKs0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bcBviC/btsJS72Nluz/jjtDk7xklRrmMOFevbhKs0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bcBviC/btsJS72Nluz/jjtDk7xklRrmMOFevbhKs0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbcBviC%2FbtsJS72Nluz%2FjjtDk7xklRrmMOFevbhKs0%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;689&quot; height=&quot;384&quot; data-origin-width=&quot;1020&quot; data-origin-height=&quot;568&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DataDog에 서버의 정보를 보내려면 DataDog agent를 이용해야 하고 EC2 내 서비스들은 APM을 이용해 Agent에게 정보를 보내도록 설정한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;EC2 인스턴스 타입을 c5.large 기준 ENI 제한이 3이다. 이로 인해 ECS 서비스 2개를 실행하고 DataDog agent는 각 ec2에서 2개의 서버 정보를 수집한다. 인스턴스 타입을 변경해서 단일 EC2에 더 많은 서비스를 기동 하면, DataDog host 비용을 절약할 수 있다. DataDog은 agent의 수로 host 수를 측정한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;infrastructure 수집을 포기한다면 단일 agent만 서비스로 실행하고 모든 서비스의 정보를 수집할 수도 있다. 다만 이러면, Datadog을 사용하는 이유가.. 있을까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. DataDog agent ECS 내 등록, 실행&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. datadog-agent.json 파일을 만든다.&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;본 글에서는 agent 내 별도 기능을 미설정했습니다. &lt;a href=&quot;https://docs.datadoghq.com/ko/containers/amazon_ecs/?tab=webui#run-the-agent-as-a-daemon-service&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;문서&lt;/a&gt;를 통해 로그 수집, 프로세스 데이터 수집, 네트워크 정보 수집이 가능하다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a title=&quot;공식문서&quot; href=&quot;https://docs.datadoghq.com/ko/containers/amazon_ecs/apm/?tab=ec2%EB%A9%94%ED%83%80%EB%8D%B0%EC%9D%B4%ED%84%B0%EC%97%94%EB%93%9C%ED%8F%AC%EC%9D%B8%ED%8A%B8&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;공식문서&lt;/a&gt;는 memory를 256으로 세팅하는 json을 보여준다. 본 글에서는 512를 했다. 중요한 건 EC2 기반 ECS에서는 서비스 실행을 위해 task에 설정한 메모리가 EC2 내 여유자원으로 있어야 서비스가 실행된다. c5a.large은 4GB의 메모리를 설정되어 있으나, 실제 사용가능한 메모리는 약 3800MB다. datadog agent를 ec2에서 실행할 경우 512MB를 제외한 용량에서 서비스 메모리를 설정해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;datadog-agent.json&lt;/p&gt;
&lt;pre id=&quot;code_1727939069913&quot; class=&quot;json&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;{
    &quot;family&quot;: &quot;datadog-agent-task&quot;,
    &quot;containerDefinitions&quot;: [
        {
            &quot;name&quot;: &quot;datadog-agent&quot;,
            &quot;image&quot;: &quot;public.ecr.aws/datadog/agent:latest&quot;,
            &quot;cpu&quot;: 100,
            &quot;memory&quot;: 512,
            &quot;portMappings&quot;: [
                {
                    &quot;containerPort&quot;: 8126,
                    &quot;hostPort&quot;: 8126,
                    &quot;protocol&quot;: &quot;tcp&quot;
                }
            ],
            &quot;essential&quot;: true,
            &quot;environment&quot;: [
                {
                    &quot;name&quot;: &quot;DD_SITE&quot;,
                    &quot;value&quot;: &quot;datadoghq.com&quot;
                },
                {
                    &quot;name&quot;: &quot;DD_API_KEY&quot;,
                    &quot;value&quot;: &quot;{datadog api key}&quot;
                }
            ],
            &quot;mountPoints&quot;: [
                {
                    &quot;sourceVolume&quot;: &quot;docker_sock&quot;,
                    &quot;containerPath&quot;: &quot;/var/run/docker.sock&quot;,
                    &quot;readOnly&quot;: true
                },
                {
                    &quot;sourceVolume&quot;: &quot;cgroup&quot;,
                    &quot;containerPath&quot;: &quot;/host/sys/fs/cgroup&quot;,
                    &quot;readOnly&quot;: true
                },
                {
                    &quot;sourceVolume&quot;: &quot;proc&quot;,
                    &quot;containerPath&quot;: &quot;/host/proc&quot;,
                    &quot;readOnly&quot;: true
                },
                {
                    &quot;sourceVolume&quot;: &quot;pointdir&quot;,
                    &quot;containerPath&quot;: &quot;/opt/datadog-agent/run&quot;,
                    &quot;readOnly&quot;: false
                },
                {
                    &quot;sourceVolume&quot;: &quot;containers_root&quot;,
                    &quot;containerPath&quot;: &quot;/var/lib/docker/containers&quot;,
                    &quot;readOnly&quot;: true
                }
            ],
            &quot;volumesFrom&quot;: [],
            &quot;systemControls&quot;: []
        }
    ],
    &quot;volumes&quot;: [
        {
            &quot;name&quot;: &quot;docker_sock&quot;,
            &quot;host&quot;: {
                &quot;sourcePath&quot;: &quot;/var/run/docker.sock&quot;
            }
        },
        {
            &quot;name&quot;: &quot;proc&quot;,
            &quot;host&quot;: {
                &quot;sourcePath&quot;: &quot;/proc/&quot;
            }
        },
        {
            &quot;name&quot;: &quot;cgroup&quot;,
            &quot;host&quot;: {
                &quot;sourcePath&quot;: &quot;/sys/fs/cgroup/&quot;
            }
        },
        {
            &quot;name&quot;: &quot;pointdir&quot;,
            &quot;host&quot;: {
                &quot;sourcePath&quot;: &quot;/opt/datadog-agent/run&quot;
            }
        },
        {
            &quot;name&quot;: &quot;containers_root&quot;,
            &quot;host&quot;: {
                &quot;sourcePath&quot;: &quot;/var/lib/docker/containers&quot;
            }
        }
    ]
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. json 파일을 이용해 task 등록&lt;/h3&gt;
&lt;pre id=&quot;code_1727939577588&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;aws ecs register-task-definition --cli-input-json datadog-agent.json&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;명령어를 통해 ECS task에 DataDog agent를 등록한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1328&quot; data-origin-height=&quot;947&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bBPiZe/btsJUj8ULDQ/ytwCEm5kWLgEUKWTAsSxkK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bBPiZe/btsJUj8ULDQ/ytwCEm5kWLgEUKWTAsSxkK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bBPiZe/btsJUj8ULDQ/ytwCEm5kWLgEUKWTAsSxkK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbBPiZe%2FbtsJUj8ULDQ%2FytwCEm5kWLgEUKWTAsSxkK%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;694&quot; height=&quot;495&quot; data-origin-width=&quot;1328&quot; data-origin-height=&quot;947&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;h3 data-ke-size=&quot;size23&quot;&gt;3. DataDog Agent deamon 실행&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1432&quot; data-origin-height=&quot;1436&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b8u7jj/btsJU95uppc/832XFTVCTIHG3ox3oaR8mk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b8u7jj/btsJU95uppc/832XFTVCTIHG3ox3oaR8mk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b8u7jj/btsJU95uppc/832XFTVCTIHG3ox3oaR8mk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb8u7jj%2FbtsJU95uppc%2F832XFTVCTIHG3ox3oaR8mk%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;715&quot; height=&quot;717&quot; data-origin-width=&quot;1432&quot; data-origin-height=&quot;1436&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 사진처럼 서비스를 생성하면 각 EC2에 DataDog agent가 실행된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1742&quot; data-origin-height=&quot;112&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bsUnOZ/btsJUpgUsh4/M9v1ONnQV4cBki8IVIzhMK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bsUnOZ/btsJUpgUsh4/M9v1ONnQV4cBki8IVIzhMK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bsUnOZ/btsJUpgUsh4/M9v1ONnQV4cBki8IVIzhMK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbsUnOZ%2FbtsJUpgUsh4%2FM9v1ONnQV4cBki8IVIzhMK%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;1742&quot; height=&quot;112&quot; data-origin-width=&quot;1742&quot; data-origin-height=&quot;112&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;2. Spring Boot 3 trace id 설정&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발, 운영 모두 DataDog을 못 사용할 수 도 있다. 또는 spring boot를 이용해 MSA 환경을 구성한 경우 서버에서 Spring Cloud Sleuth를 사용한다. Spring Boot3에서 sleuth는 더 이상 사용이 불가하다. 대신 Micrometer Tracing를 사용하여 log를 설정할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. (선택) Micrometer 설정&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;build.gradle에 micrometer를 설정한다. datadog을 이용하기에 io.zipkin.reporter2는 제외한다. openfeign 사용을 위한 라이브러리도 추가한다.&lt;/p&gt;
&lt;pre id=&quot;code_1727940299333&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;    // Micrometer Tracing
    implementation('io.micrometer:micrometer-tracing-bridge-brave') {
        exclude group: 'io.zipkin.reporter2'
    }
    implementation 'io.github.openfeign:feign-micrometer'&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;logback은 다음과 같이 설정한다.&lt;/p&gt;
&lt;div style=&quot;background-color: #1e1f22; color: #bcbec4;&quot;&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;%X{traceId},%X{spanId}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2.&amp;nbsp; logback 설정&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;datadog traceid는 dd.traceId로 설정해야 주입받을 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;출처: &lt;a href=&quot;https://docs.datadoghq.com/ko/tracing/other_telemetry/connect_logs_and_traces/java/?tab=log4j2&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://docs.datadoghq.com/ko/tracing/other_telemetry/connect_logs_and_traces/java/?tab=log4j2&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1727940537949&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;Correlating Java Logs and Traces&quot; data-og-description=&quot;Connect your Java logs and traces to correlate them in Datadog.&quot; data-og-host=&quot;docs.datadoghq.com&quot; data-og-source-url=&quot;https://docs.datadoghq.com/ko/tracing/other_telemetry/connect_logs_and_traces/java/?tab=log4j2&quot; data-og-url=&quot;https://docs.datadoghq.com/ko/tracing/other_telemetry/connect_logs_and_traces/java/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cdNldu/hyXaHigezU/88wPx1JambCXBXPKOAqCR0/img.png?width=2500&amp;amp;height=1313&amp;amp;face=0_0_2500_1313&quot;&gt;&lt;a href=&quot;https://docs.datadoghq.com/ko/tracing/other_telemetry/connect_logs_and_traces/java/?tab=log4j2&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://docs.datadoghq.com/ko/tracing/other_telemetry/connect_logs_and_traces/java/?tab=log4j2&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cdNldu/hyXaHigezU/88wPx1JambCXBXPKOAqCR0/img.png?width=2500&amp;amp;height=1313&amp;amp;face=0_0_2500_1313');&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;Correlating Java Logs and Traces&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Connect your Java logs and traces to correlate them in Datadog.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;docs.datadoghq.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;pre id=&quot;code_1727940607244&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;property name=&quot;LOG_PATTERN&quot;
  value=&quot;%clr(%d{yyyy-MM-dd HH:m:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) [%clr(${springAppName:-}){yellow},%X{dd.trace_id},%X{dd.span_id:-} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}&quot;/&amp;gt;
   
&amp;lt;appender name=&quot;CONSOLE&quot; class=&quot;ch.qos.logback.core.ConsoleAppender&quot;&amp;gt;
    &amp;lt;encoder&amp;gt;
        &amp;lt;pattern&amp;gt;${LOG_PATTERN}&amp;lt;/pattern&amp;gt;
        &amp;lt;charset&amp;gt;utf8&amp;lt;/charset&amp;gt;
    &amp;lt;/encoder&amp;gt;
&amp;lt;/appender&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;3. Dockerfile을 이용한 datadog apm 설정&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Dockerfile에 apm을 설정하는 건 다음 코드를 참고하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서버에서 traceId를 출력하도록 주입을 위해 DD_LOGS_INJECTION를 설정한다. 추가로 &lt;a href=&quot;https://www.w3.org/TR/trace-context/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;W3C&lt;/a&gt;기반 traceid를 사용하기 위해 DD_TRACE_PROPAGATION_STYLE도 설정한다.&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;DD_AGENT_HOST는 Amazon Linux 2023 기준으로 작성했다. 다른 OS는 &lt;a href=&quot;https://docs.datadoghq.com/ko/containers/amazon_ecs/apm/?tab=ec2%EB%A9%94%ED%83%80%EB%8D%B0%EC%9D%B4%ED%84%B0%EC%97%94%EB%93%9C%ED%8F%AC%EC%9D%B8%ED%8A%B8&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;문서&lt;/a&gt;를 참고...&lt;/p&gt;
&lt;pre id=&quot;code_1727941129780&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#!/bin/bash
FROM amazoncorretto:17
WORKDIR /app

ENV VERSION=&quot;{버전}&quot;
ENV APP_NAME=&quot;{artifact 이름}&quot;

COPY build/libs/${APP_NAME}-${VERSION}.jar .

#DataDog 설정
ENV DD_SERVICE={서비스 명}
ENV DD_LOGS_INJECTION=true 
ENV DD_TRACE_128_BIT_TRACEID_LOGGING_ENABLED=true
ENV DD_TRACE_PROPAGATION_STYLE=tracecontext,datadog
ENV DD_ENV=prod
ENV DD_TRACE_SAMPLE_RATE=1
ENV DD_VERSION=1.0.0

ADD 'https://dtdg.co/latest-java-tracer' dd-java-agent.jar

CMD export DD_AGENT_HOST=$(TOKEN=$(curl -X PUT &quot;http://169.254.169.254/latest/api/token&quot; -H &quot;X-aws-ec2-metadata-token-ttl-seconds: 21600&quot;);curl http://169.254.169.254/latest/meta-data/local-ipv4 -H &quot;X-aws-ec2-metadata-token: $TOKEN&quot;); \
    java -javaagent:dd-java-agent.jar \
    -jar \
    -Djava.net.preferIPv4Stack=true -Dspring.profiles.active=prod \
    ${APP_NAME}-${VERSION}.jar;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;번외. Datadog console에서 보이는 traceid와 서버 traceid가 다르다!&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;566&quot; data-origin-height=&quot;1195&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bw2EjW/btsJToQLq5a/aWpi0BUFkG0XdArt1EFAt0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bw2EjW/btsJToQLq5a/aWpi0BUFkG0XdArt1EFAt0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bw2EjW/btsJToQLq5a/aWpi0BUFkG0XdArt1EFAt0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbw2EjW%2FbtsJToQLq5a%2FaWpi0BUFkG0XdArt1EFAt0%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;566&quot; height=&quot;1195&quot; data-origin-width=&quot;566&quot; data-origin-height=&quot;1195&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://docs.datadoghq.com/ko/tracing/guide/span_and_trace_id_format/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://docs.datadoghq.com/ko/tracing/guide/span_and_trace_id_format/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1727941826543&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;Trace and Span ID Formats&quot; data-og-description=&quot;Datadog, the leading service for cloud-scale monitoring.&quot; data-og-host=&quot;docs.datadoghq.com&quot; data-og-source-url=&quot;https://docs.datadoghq.com/ko/tracing/guide/span_and_trace_id_format/&quot; data-og-url=&quot;https://docs.datadoghq.com/ko/tracing/guide/span_and_trace_id_format/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/5DGIV/hyXd4iybLp/tLICMlsda84jNrdmy0d9vk/img.png?width=2500&amp;amp;height=1313&amp;amp;face=0_0_2500_1313&quot;&gt;&lt;a href=&quot;https://docs.datadoghq.com/ko/tracing/guide/span_and_trace_id_format/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://docs.datadoghq.com/ko/tracing/guide/span_and_trace_id_format/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/5DGIV/hyXd4iybLp/tLICMlsda84jNrdmy0d9vk/img.png?width=2500&amp;amp;height=1313&amp;amp;face=0_0_2500_1313');&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;Trace and Span ID Formats&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Datadog, the leading service for cloud-scale monitoring.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;docs.datadoghq.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;trace id의 형식이 달라 생긴 문제다. 아래 설정을 통해 1&lt;span style=&quot;background-color: #ffffff; color: #2b2e2f; text-align: start;&quot;&gt;28비트 Trace ID는 32자의 소문자 16진수로 보이며 로그의 traceid를 datadog에서 동일하게 보여준다.&lt;/span&gt;&lt;/p&gt;
&lt;div style=&quot;background-color: #1e1f22; color: #bcbec4;&quot;&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;DD_TRACE_128_BIT_TRACEID_LOGGING_ENABLED=true&lt;/code&gt;&lt;/pre&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;참고한 글&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://docs.datadoghq.com/ko/containers/amazon_ecs/apm/?tab=ec2%EB%A9%94%ED%83%80%EB%8D%B0%EC%9D%B4%ED%84%B0%EC%97%94%EB%93%9C%ED%8F%AC%EC%9D%B8%ED%8A%B8&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://docs.datadoghq.com/ko/containers/amazon_ecs/apm/?tab=ec2%EB%A9%94%ED%83%80%EB%8D%B0%EC%9D%B4%ED%84%B0%EC%97%94%EB%93%9C%ED%8F%AC%EC%9D%B8%ED%8A%B8&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1727942046212&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;ECS 애플리케이션 추적&quot; data-og-description=&quot;Datadog, the leading service for cloud-scale monitoring.&quot; data-og-host=&quot;docs.datadoghq.com&quot; data-og-source-url=&quot;https://docs.datadoghq.com/ko/containers/amazon_ecs/apm/?tab=ec2%EB%A9%94%ED%83%80%EB%8D%B0%EC%9D%B4%ED%84%B0%EC%97%94%EB%93%9C%ED%8F%AC%EC%9D%B8%ED%8A%B8&quot; data-og-url=&quot;https://docs.datadoghq.com/ko/containers/amazon_ecs/apm/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/vjxed/hyXedNkeSR/DWR9fSRS1ZbugmKJMpVbm1/img.png?width=2500&amp;amp;height=1313&amp;amp;face=0_0_2500_1313&quot;&gt;&lt;a href=&quot;https://docs.datadoghq.com/ko/containers/amazon_ecs/apm/?tab=ec2%EB%A9%94%ED%83%80%EB%8D%B0%EC%9D%B4%ED%84%B0%EC%97%94%EB%93%9C%ED%8F%AC%EC%9D%B8%ED%8A%B8&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://docs.datadoghq.com/ko/containers/amazon_ecs/apm/?tab=ec2%EB%A9%94%ED%83%80%EB%8D%B0%EC%9D%B4%ED%84%B0%EC%97%94%EB%93%9C%ED%8F%AC%EC%9D%B8%ED%8A%B8&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/vjxed/hyXedNkeSR/DWR9fSRS1ZbugmKJMpVbm1/img.png?width=2500&amp;amp;height=1313&amp;amp;face=0_0_2500_1313');&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;ECS 애플리케이션 추적&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Datadog, the leading service for cloud-scale monitoring.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;docs.datadoghq.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://docs.datadoghq.com/ko/tracing/guide/span_and_trace_id_format/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://docs.datadoghq.com/ko/tracing/guide/span_and_trace_id_format/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1727942046531&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;Trace and Span ID Formats&quot; data-og-description=&quot;Datadog, the leading service for cloud-scale monitoring.&quot; data-og-host=&quot;docs.datadoghq.com&quot; data-og-source-url=&quot;https://docs.datadoghq.com/ko/tracing/guide/span_and_trace_id_format/&quot; data-og-url=&quot;https://docs.datadoghq.com/ko/tracing/guide/span_and_trace_id_format/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/5DGIV/hyXd4iybLp/tLICMlsda84jNrdmy0d9vk/img.png?width=2500&amp;amp;height=1313&amp;amp;face=0_0_2500_1313&quot;&gt;&lt;a href=&quot;https://docs.datadoghq.com/ko/tracing/guide/span_and_trace_id_format/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://docs.datadoghq.com/ko/tracing/guide/span_and_trace_id_format/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/5DGIV/hyXd4iybLp/tLICMlsda84jNrdmy0d9vk/img.png?width=2500&amp;amp;height=1313&amp;amp;face=0_0_2500_1313');&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;Trace and Span ID Formats&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Datadog, the leading service for cloud-scale monitoring.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;docs.datadoghq.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://docs.datadoghq.com/ko/tracing/trace_collection/automatic_instrumentation/dd_libraries/java/?tab=wget&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://docs.datadoghq.com/ko/tracing/trace_collection/automatic_instrumentation/dd_libraries/java/?tab=wget&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1727942059362&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;Tracing Java Applications&quot; data-og-description=&quot;Datadog, the leading service for cloud-scale monitoring.&quot; data-og-host=&quot;docs.datadoghq.com&quot; data-og-source-url=&quot;https://docs.datadoghq.com/ko/tracing/trace_collection/automatic_instrumentation/dd_libraries/java/?tab=wget&quot; data-og-url=&quot;https://docs.datadoghq.com/ko/tracing/trace_collection/automatic_instrumentation/dd_libraries/java/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/c4kpJN/hyXd4QohFH/dw3cnkwrC3PPR0TKjfxM70/img.png?width=2500&amp;amp;height=1313&amp;amp;face=0_0_2500_1313&quot;&gt;&lt;a href=&quot;https://docs.datadoghq.com/ko/tracing/trace_collection/automatic_instrumentation/dd_libraries/java/?tab=wget&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://docs.datadoghq.com/ko/tracing/trace_collection/automatic_instrumentation/dd_libraries/java/?tab=wget&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/c4kpJN/hyXd4QohFH/dw3cnkwrC3PPR0TKjfxM70/img.png?width=2500&amp;amp;height=1313&amp;amp;face=0_0_2500_1313');&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;Tracing Java Applications&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Datadog, the leading service for cloud-scale monitoring.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;docs.datadoghq.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://docs.datadoghq.com/ko/containers/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://docs.datadoghq.com/ko/containers/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1727942072073&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;컨테이너 모니터링&quot; data-og-description=&quot;컨테이너화된 인프라스트럭처에서 데이터를 수집하기 위한 에이전트 설치 및 설정&quot; data-og-host=&quot;docs.datadoghq.com&quot; data-og-source-url=&quot;https://docs.datadoghq.com/ko/containers/&quot; data-og-url=&quot;https://docs.datadoghq.com/ko/containers/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/Pfnu8/hyXazkcvjS/SeFzKjXIkZKw3XC3P40gh0/img.png?width=2500&amp;amp;height=1313&amp;amp;face=0_0_2500_1313&quot;&gt;&lt;a href=&quot;https://docs.datadoghq.com/ko/containers/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://docs.datadoghq.com/ko/containers/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/Pfnu8/hyXazkcvjS/SeFzKjXIkZKw3XC3P40gh0/img.png?width=2500&amp;amp;height=1313&amp;amp;face=0_0_2500_1313');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;컨테이너 모니터링&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;컨테이너화된 인프라스트럭처에서 데이터를 수집하기 위한 에이전트 설치 및 설정&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;docs.datadoghq.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>인프라</category>
      <category>aws ecs datadog</category>
      <category>aws ecs ec2</category>
      <category>datadog</category>
      <category>ec2 datadog</category>
      <category>spring boot3</category>
      <category>spring boot3 datadog</category>
      <author>dev.Dove</author>
      <guid isPermaLink="true">https://dpot.tistory.com/10</guid>
      <comments>https://dpot.tistory.com/10#entry10comment</comments>
      <pubDate>Thu, 3 Oct 2024 16:53:06 +0900</pubDate>
    </item>
    <item>
      <title>기본적인 AWS VPC 구성기</title>
      <link>https://dpot.tistory.com/9</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;371&quot; data-origin-height=&quot;351&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/by2U4z/btsIO2nL2iH/NWCkOGbNEXtZaqE7loqRvK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/by2U4z/btsIO2nL2iH/NWCkOGbNEXtZaqE7loqRvK/img.png&quot; data-alt=&quot;구성할 VPC&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/by2U4z/btsIO2nL2iH/NWCkOGbNEXtZaqE7loqRvK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fby2U4z%2FbtsIO2nL2iH%2FNWCkOGbNEXtZaqE7loqRvK%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;371&quot; height=&quot;351&quot; data-origin-width=&quot;371&quot; data-origin-height=&quot;351&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;구성할 VPC&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2024년 7월 기준 AWS Console ui를 스크린샷으로 캡처했습니다. 추후 ui는 변경될 수 있습니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. VPC 생성&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. VPC 서비스에서 Virtual Private Cloud &amp;gt; VPC &amp;gt; VPC 생성 클릭&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;856&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/O1kCI/btsIO1vDJd0/45sq9vx8nIyoS9rVGU7l40/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/O1kCI/btsIO1vDJd0/45sq9vx8nIyoS9rVGU7l40/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/O1kCI/btsIO1vDJd0/45sq9vx8nIyoS9rVGU7l40/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FO1kCI%2FbtsIO1vDJd0%2F45sq9vx8nIyoS9rVGU7l40%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;1920&quot; height=&quot;856&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;856&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. VPC 생성 정보 입력 후 &quot;생성&quot; 버튼 클릭&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 생성할 리소스: VPC만&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 이름 태그: 원하는 VPC이름 입력&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- IPv4 CIDR: 원하는 IP를 입력(x.x.0.0에 /16 선택 시 x.x.0.0 ~ x.x.255.255)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1674&quot; data-origin-height=&quot;1528&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/XVCPP/btsIP6JCrGm/KMxRX8ZilH2BJdNoOxObS1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/XVCPP/btsIP6JCrGm/KMxRX8ZilH2BJdNoOxObS1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/XVCPP/btsIP6JCrGm/KMxRX8ZilH2BJdNoOxObS1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FXVCPP%2FbtsIP6JCrGm%2FKMxRX8ZilH2BJdNoOxObS1%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;1674&quot; height=&quot;1528&quot; data-origin-width=&quot;1674&quot; data-origin-height=&quot;1528&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;3. 생성한 VPC 확인&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;1798&quot; data-origin-height=&quot;1408&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/HDgHA/btsIQpoBanB/to5MmbgbPfUl5wJYZq0Al1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/HDgHA/btsIQpoBanB/to5MmbgbPfUl5wJYZq0Al1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/HDgHA/btsIQpoBanB/to5MmbgbPfUl5wJYZq0Al1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHDgHA%2FbtsIQpoBanB%2Fto5MmbgbPfUl5wJYZq0Al1%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;1798&quot; height=&quot;1408&quot; data-origin-width=&quot;1798&quot; data-origin-height=&quot;1408&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;2. VPC 서브넷 생성&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. VPC 서비스에서 Virtual Private Cloud &amp;gt; 서브넷 &amp;gt; 서브넷 생성 클릭&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1802&quot; data-origin-height=&quot;702&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ntHgq/btsIOBRCFBI/5CvzXUwEVmZLnD7hvr2lu0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ntHgq/btsIOBRCFBI/5CvzXUwEVmZLnD7hvr2lu0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ntHgq/btsIOBRCFBI/5CvzXUwEVmZLnD7hvr2lu0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FntHgq%2FbtsIOBRCFBI%2F5CvzXUwEVmZLnD7hvr2lu0%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;1802&quot; height=&quot;702&quot; data-origin-width=&quot;1802&quot; data-origin-height=&quot;702&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. VPC ID에 앞서 만든 VPC 선택&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1692&quot; data-origin-height=&quot;770&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bosSZI/btsIRfFKle0/K5JKSenKoeGk3x9ZYs5Bd0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bosSZI/btsIRfFKle0/K5JKSenKoeGk3x9ZYs5Bd0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bosSZI/btsIRfFKle0/K5JKSenKoeGk3x9ZYs5Bd0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbosSZI%2FbtsIRfFKle0%2FK5JKSenKoeGk3x9ZYs5Bd0%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;1692&quot; height=&quot;770&quot; data-origin-width=&quot;1692&quot; data-origin-height=&quot;770&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;3. 퍼블릭 서브넷으로 만들 정보입력 이후 서브넷 생성 클릭&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 서브넷 이름: 퍼블릭 서브넷 이름 입력&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 가용영역: 서울 기준 a, b, c, d 중 하나 선택 가능&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- IPv4 서브넷 CIDR 블록: 원하는 IP 영역을 입력 &lt;a href=&quot;https://ko.rakko.tools/tools/27/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://ko.rakko.tools/tools/27/&lt;/a&gt;를 이용하면 보다 편하게 계산 가능&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1662&quot; data-origin-height=&quot;1668&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/l0hUB/btsIQ1OkNKb/xpKSEqpjtfmnPcw5u0XKJ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/l0hUB/btsIQ1OkNKb/xpKSEqpjtfmnPcw5u0XKJ0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/l0hUB/btsIQ1OkNKb/xpKSEqpjtfmnPcw5u0XKJ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fl0hUB%2FbtsIQ1OkNKb%2FxpKSEqpjtfmnPcw5u0XKJ0%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;1662&quot; height=&quot;1668&quot; data-origin-width=&quot;1662&quot; data-origin-height=&quot;1668&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4.다시 서브넷 생성 클릭 이후 3번과 동일하게 프라이빗 서브넷으로 만들 정보입력 이후 서브넷 생성 클릭&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1678&quot; data-origin-height=&quot;1664&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/81WHS/btsIOr9qw2L/dgHDIgSxHphG3ZUdmCzDqk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/81WHS/btsIOr9qw2L/dgHDIgSxHphG3ZUdmCzDqk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/81WHS/btsIOr9qw2L/dgHDIgSxHphG3ZUdmCzDqk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F81WHS%2FbtsIOr9qw2L%2FdgHDIgSxHphG3ZUdmCzDqk%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;1678&quot; height=&quot;1664&quot; data-origin-width=&quot;1678&quot; data-origin-height=&quot;1664&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;3. 라우팅 테이블 생성&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. VPC 서비스에서 Virtual Private Cloud &amp;gt; 라우팅 테이블 &amp;gt; 라우팅 테이블 생성 클릭&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1816&quot; data-origin-height=&quot;852&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tkQDw/btsIPxub2QM/VpcH7uWo3UAo8jrXdd3t91/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tkQDw/btsIPxub2QM/VpcH7uWo3UAo8jrXdd3t91/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tkQDw/btsIPxub2QM/VpcH7uWo3UAo8jrXdd3t91/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtkQDw%2FbtsIPxub2QM%2FVpcH7uWo3UAo8jrXdd3t91%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;1816&quot; height=&quot;852&quot; data-origin-width=&quot;1816&quot; data-origin-height=&quot;852&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;2. 퍼블릭, 프라이빗 서브넷 2개용 라우팅 테이블을 2개 생성&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1762&quot; data-origin-height=&quot;1310&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bBxNJY/btsIQ1gvqy4/bUGScG9zKFkTm3Xy82Ew10/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bBxNJY/btsIQ1gvqy4/bUGScG9zKFkTm3Xy82Ew10/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bBxNJY/btsIQ1gvqy4/bUGScG9zKFkTm3Xy82Ew10/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbBxNJY%2FbtsIQ1gvqy4%2FbUGScG9zKFkTm3Xy82Ew10%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;1762&quot; height=&quot;1310&quot; data-origin-width=&quot;1762&quot; data-origin-height=&quot;1310&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1752&quot; data-origin-height=&quot;1326&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/v5Eal/btsIP0iqX6z/MeK1YdNP2SSTggtW1zr7ck/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/v5Eal/btsIP0iqX6z/MeK1YdNP2SSTggtW1zr7ck/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/v5Eal/btsIP0iqX6z/MeK1YdNP2SSTggtW1zr7ck/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fv5Eal%2FbtsIP0iqX6z%2FMeK1YdNP2SSTggtW1zr7ck%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1752&quot; height=&quot;1326&quot; data-origin-width=&quot;1752&quot; data-origin-height=&quot;1326&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 만들어진 라우팅 테이블의 ID를 클릭한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1830&quot; data-origin-height=&quot;780&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pH8FR/btsIPzZOQQP/mZnF61yTFzEc8TiFjpNtz1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pH8FR/btsIPzZOQQP/mZnF61yTFzEc8TiFjpNtz1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pH8FR/btsIPzZOQQP/mZnF61yTFzEc8TiFjpNtz1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpH8FR%2FbtsIPzZOQQP%2FmZnF61yTFzEc8TiFjpNtz1%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;1830&quot; height=&quot;780&quot; data-origin-width=&quot;1830&quot; data-origin-height=&quot;780&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 서브넷 연결 &amp;gt; 서브넷 연결 편집 클릭&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1814&quot; data-origin-height=&quot;1448&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cowQPS/btsIPtSX9rN/EYGtCupAcewicnju69rlCk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cowQPS/btsIPtSX9rN/EYGtCupAcewicnju69rlCk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cowQPS/btsIPtSX9rN/EYGtCupAcewicnju69rlCk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcowQPS%2FbtsIPtSX9rN%2FEYGtCupAcewicnju69rlCk%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;1814&quot; height=&quot;1448&quot; data-origin-width=&quot;1814&quot; data-origin-height=&quot;1448&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;5. 각 라우팅 테이블에서 서브넷을 하나씩 선택 후 연결 저장 클릭&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1840&quot; data-origin-height=&quot;1084&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b05EKo/btsIPmTZI3G/Hy7QMEwmOmXrgD4BwP3o11/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b05EKo/btsIPmTZI3G/Hy7QMEwmOmXrgD4BwP3o11/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b05EKo/btsIPmTZI3G/Hy7QMEwmOmXrgD4BwP3o11/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb05EKo%2FbtsIPmTZI3G%2FHy7QMEwmOmXrgD4BwP3o11%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;1840&quot; height=&quot;1084&quot; data-origin-width=&quot;1840&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;6. 서브넷 연결 확인&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1346&quot; data-origin-height=&quot;1376&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/JEP0u/btsIOHjTxpJ/aUQ6kPZakf4OxsO36uHx80/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/JEP0u/btsIOHjTxpJ/aUQ6kPZakf4OxsO36uHx80/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/JEP0u/btsIOHjTxpJ/aUQ6kPZakf4OxsO36uHx80/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJEP0u%2FbtsIOHjTxpJ%2FaUQ6kPZakf4OxsO36uHx80%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;1346&quot; height=&quot;1376&quot; data-origin-width=&quot;1346&quot; data-origin-height=&quot;1376&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;4. 퍼블릭 서브넷을 위한 인터넷 게이트웨이 생성&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;VPC 서비스에서 Virtual Private Cloud &amp;gt; 인터넷 게이트웨이 &amp;gt;&lt;span&gt; 인터넷 게이트웨이&lt;/span&gt;&lt;/span&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;1810&quot; data-origin-height=&quot;796&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cgUXwz/btsIOVoM7rN/TdSCrCSk0Q45DJayIZqH9K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cgUXwz/btsIOVoM7rN/TdSCrCSk0Q45DJayIZqH9K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cgUXwz/btsIOVoM7rN/TdSCrCSk0Q45DJayIZqH9K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcgUXwz%2FbtsIOVoM7rN%2FTdSCrCSk0Q45DJayIZqH9K%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;1810&quot; height=&quot;796&quot; data-origin-width=&quot;1810&quot; data-origin-height=&quot;796&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;2. 이름 태그 입력 후 인터넷 게이트웨이 생성 클릭&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1760&quot; data-origin-height=&quot;1298&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mpcaJ/btsIP5DVq75/pqv79z7PyTEeM8oS8idsAK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mpcaJ/btsIP5DVq75/pqv79z7PyTEeM8oS8idsAK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mpcaJ/btsIP5DVq75/pqv79z7PyTEeM8oS8idsAK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmpcaJ%2FbtsIP5DVq75%2Fpqv79z7PyTEeM8oS8idsAK%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;1760&quot; height=&quot;1298&quot; data-origin-width=&quot;1760&quot; data-origin-height=&quot;1298&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;3. 안내창의 VPC에 연결 버튼 또는 작업 &amp;gt; VPC에 연결 버튼 클릭&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1816&quot; data-origin-height=&quot;1184&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/KBKr8/btsIOUclKa3/kftxua0GV7gXJCTYwQFC2K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/KBKr8/btsIOUclKa3/kftxua0GV7gXJCTYwQFC2K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/KBKr8/btsIOUclKa3/kftxua0GV7gXJCTYwQFC2K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FKBKr8%2FbtsIOUclKa3%2Fkftxua0GV7gXJCTYwQFC2K%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;1816&quot; height=&quot;1184&quot; data-origin-width=&quot;1816&quot; data-origin-height=&quot;1184&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 앞서 만든 VPC 선택 후 인터넷 게이트웨이 연결&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1758&quot; data-origin-height=&quot;796&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cvFfUv/btsIPUJqDw3/qv4HtVDKGz8xveN7ysp0M1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cvFfUv/btsIPUJqDw3/qv4HtVDKGz8xveN7ysp0M1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cvFfUv/btsIPUJqDw3/qv4HtVDKGz8xveN7ysp0M1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcvFfUv%2FbtsIPUJqDw3%2Fqv4HtVDKGz8xveN7ysp0M1%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;1758&quot; height=&quot;796&quot; data-origin-width=&quot;1758&quot; data-origin-height=&quot;796&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;5. &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt; &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;VPC 서비스에서 Virtual Private Cloud &amp;gt; 라우팅 테이블 &amp;gt;&lt;span&gt; 앞서 만든 퍼블릭 서브넷용 라우팅 테이블 ID 클릭&lt;/span&gt;&lt;/span&gt;&lt;/span&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;1810&quot; data-origin-height=&quot;682&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cvP0Dp/btsIQxNELDn/7kUKRAmEaktqjtCqb5S281/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cvP0Dp/btsIQxNELDn/7kUKRAmEaktqjtCqb5S281/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cvP0Dp/btsIQxNELDn/7kUKRAmEaktqjtCqb5S281/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcvP0Dp%2FbtsIQxNELDn%2F7kUKRAmEaktqjtCqb5S281%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;1810&quot; height=&quot;682&quot; data-origin-width=&quot;1810&quot; data-origin-height=&quot;682&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;6. 라우팅 &amp;gt; 라우팅 편집 클릭&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1828&quot; data-origin-height=&quot;1400&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d1NFMY/btsIQe1TiLU/fNNNScpwliRKZYsIktYfik/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d1NFMY/btsIQe1TiLU/fNNNScpwliRKZYsIktYfik/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d1NFMY/btsIQe1TiLU/fNNNScpwliRKZYsIktYfik/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd1NFMY%2FbtsIQe1TiLU%2FfNNNScpwliRKZYsIktYfik%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;1828&quot; height=&quot;1400&quot; data-origin-width=&quot;1828&quot; data-origin-height=&quot;1400&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;7. 라우팅 추가 클릭&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1810&quot; data-origin-height=&quot;898&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bDzxUc/btsIOWBafmS/AJTufqoGZXe8YBP37ZXOC0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bDzxUc/btsIOWBafmS/AJTufqoGZXe8YBP37ZXOC0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bDzxUc/btsIOWBafmS/AJTufqoGZXe8YBP37ZXOC0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbDzxUc%2FbtsIOWBafmS%2FAJTufqoGZXe8YBP37ZXOC0%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;1810&quot; height=&quot;898&quot; data-origin-width=&quot;1810&quot; data-origin-height=&quot;898&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;8. 앞서 만든 인터넷 게이트웨이 정보 입력 후 변경 사항 저장 클릭 &lt;br /&gt;- 대상: 모든 인터넷의 접근을 위해 0.0.0.0 입력 후 앞서 만든 인터넷 게이트웨이 선택&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1752&quot; data-origin-height=&quot;764&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bKvdep/btsIO2H5Hoc/kfYjS5MiAMBQ85eK7dP1Kk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bKvdep/btsIO2H5Hoc/kfYjS5MiAMBQ85eK7dP1Kk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bKvdep/btsIO2H5Hoc/kfYjS5MiAMBQ85eK7dP1Kk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbKvdep%2FbtsIO2H5Hoc%2FkfYjS5MiAMBQ85eK7dP1Kk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1752&quot; height=&quot;764&quot; data-origin-width=&quot;1752&quot; data-origin-height=&quot;764&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style6&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;5. 프라이빗 서브넷용 NAT 게이트웨이 생성&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프라이빗 서브넷에서 인터넷에 접근할 일이 없다면 작업 안 하길 추천한다. NAT 게이트웨이는 생성하면 사용여부와 관계없이 요금이 발생한다.&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;1. VPC 서비스에서 Virtual Private Cloud &amp;gt; NAT 게이트웨이 &amp;gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt; NAT 게이트웨이 생&lt;/span&gt;&amp;nbsp;클릭&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;1824&quot; data-origin-height=&quot;1220&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bcxUzI/btsIQ2Nf86L/bh1iGk4KfABa7deoXHyJzk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bcxUzI/btsIQ2Nf86L/bh1iGk4KfABa7deoXHyJzk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bcxUzI/btsIQ2Nf86L/bh1iGk4KfABa7deoXHyJzk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbcxUzI%2FbtsIQ2Nf86L%2Fbh1iGk4KfABa7deoXHyJzk%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;1824&quot; height=&quot;1220&quot; data-origin-width=&quot;1824&quot; data-origin-height=&quot;1220&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;2. NAT 게이트웨이 정보 입력 후&amp;nbsp; NAT 게이트웨이 생성 클릭&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 이름: 원하는 게이트웨이 이름 입력&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 서브넷: NAT 게이트웨이를 위치할 퍼블릭 서브넷 선택&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 탄력적 IP 할당: 탄력적 IP 할당 버튼을 클릭하면 자동으로 세팅된다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;탄력적 IP 할당 버튼을 클릭하면 EC2 서비스에서 탄력적 IP가 만들어진다.&amp;nbsp;&lt;br /&gt;추후 NAT 게이트웨이를 지워도 탄력적 IP는 살아있으며, &lt;b&gt;AWS 미사용하는 탄력적 IP에 대해 과금&lt;/b&gt;을 하니, 주의가 필요하다.&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1694&quot; data-origin-height=&quot;1298&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/q6l5Y/btsIPV2Dy8m/G3qv25K5gfBQkBd7JfJJt0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/q6l5Y/btsIPV2Dy8m/G3qv25K5gfBQkBd7JfJJt0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/q6l5Y/btsIPV2Dy8m/G3qv25K5gfBQkBd7JfJJt0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fq6l5Y%2FbtsIPV2Dy8m%2FG3qv25K5gfBQkBd7JfJJt0%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;1694&quot; height=&quot;1298&quot; data-origin-width=&quot;1694&quot; data-origin-height=&quot;1298&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;3. VPC 서비스에서 Virtual Private Cloud &amp;gt; 라우팅 테이블 &amp;gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;앞서 만든 프라이빗 서브넷용 라우팅 테이블 ID 클릭&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;1804&quot; data-origin-height=&quot;706&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tnWtr/btsIPxOuNX5/SNk7q0hltTMD5MGxFKFfdk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tnWtr/btsIPxOuNX5/SNk7q0hltTMD5MGxFKFfdk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tnWtr/btsIPxOuNX5/SNk7q0hltTMD5MGxFKFfdk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtnWtr%2FbtsIPxOuNX5%2FSNk7q0hltTMD5MGxFKFfdk%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;1804&quot; height=&quot;706&quot; data-origin-width=&quot;1804&quot; data-origin-height=&quot;706&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;5. 라우팅 &amp;gt; 라우팅 편집 클릭&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1800&quot; data-origin-height=&quot;1334&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bnRFfL/btsIPxucpcx/GfykTCdirZzE125NUnrllK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bnRFfL/btsIPxucpcx/GfykTCdirZzE125NUnrllK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bnRFfL/btsIPxucpcx/GfykTCdirZzE125NUnrllK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbnRFfL%2FbtsIPxucpcx%2FGfykTCdirZzE125NUnrllK%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;1800&quot; height=&quot;1334&quot; data-origin-width=&quot;1800&quot; data-origin-height=&quot;1334&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;6. 라우팅 추가 클릭 후 라우팅 정보 입력 후 변경 사항 저장 클릭&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 대상: 모든 인터넷의 접근을 위해 0.0.0.0 입력 후 앞서 만든 NAT 게이트웨이 선택&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1824&quot; data-origin-height=&quot;808&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ch57nQ/btsIQfNgste/W7RKKoKvT32BkDBnXzVfRk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ch57nQ/btsIQfNgste/W7RKKoKvT32BkDBnXzVfRk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ch57nQ/btsIQfNgste/W7RKKoKvT32BkDBnXzVfRk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fch57nQ%2FbtsIQfNgste%2FW7RKKoKvT32BkDBnXzVfRk%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;1824&quot; height=&quot;808&quot; data-origin-width=&quot;1824&quot; data-origin-height=&quot;808&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;6. 만든 VPC 확인&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;VPC &amp;gt; 만든 VPC 클릭 &amp;gt; 리소스 맵에 들어가면 만들었던 VPC를 GUI로 볼 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3048&quot; data-origin-height=&quot;1530&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cHfyQc/btsIO2uAxj0/GHvkYFWazZ8HhJDkvbMk91/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cHfyQc/btsIO2uAxj0/GHvkYFWazZ8HhJDkvbMk91/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cHfyQc/btsIO2uAxj0/GHvkYFWazZ8HhJDkvbMk91/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcHfyQc%2FbtsIO2uAxj0%2FGHvkYFWazZ8HhJDkvbMk91%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;3048&quot; height=&quot;1530&quot; data-origin-width=&quot;3048&quot; data-origin-height=&quot;1530&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>인프라</category>
      <category>AWS NAT Gateway</category>
      <category>AWS NAT 게이트웨이</category>
      <category>AWS Subnet</category>
      <category>AWS VPC</category>
      <category>aws 인터넷 게이트웨이</category>
      <category>VPC</category>
      <author>dev.Dove</author>
      <guid isPermaLink="true">https://dpot.tistory.com/9</guid>
      <comments>https://dpot.tistory.com/9#entry9comment</comments>
      <pubDate>Sat, 27 Jul 2024 18:20:47 +0900</pubDate>
    </item>
    <item>
      <title>AWS SQS 256KB 이상 대용량 메시지 처리와 Spring Boot</title>
      <link>https://dpot.tistory.com/8</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;173&quot; data-origin-height=&quot;193&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dtnam3/btsIqOIVr4H/MaAy1b07HyPYu5xASd0JdK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dtnam3/btsIqOIVr4H/MaAy1b07HyPYu5xASd0JdK/img.png&quot; data-alt=&quot;출처: https://aws.amazon.com/ko/sqs/&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dtnam3/btsIqOIVr4H/MaAy1b07HyPYu5xASd0JdK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdtnam3%2FbtsIqOIVr4H%2FMaAy1b07HyPYu5xASd0JdK%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;173&quot; height=&quot;193&quot; data-origin-width=&quot;173&quot; data-origin-height=&quot;193&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처: https://aws.amazon.com/ko/sqs/&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;들어가기 전..&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Spring Boot 3.3.1(Java 17)을 기준으로 구현했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2024년 7월 기준 AWS SQS 대용량 전송 라이브러리는 Java, Python만 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;소스는 GitHub에서 확인 가능합니다.&lt;br /&gt;&lt;a title=&quot;Git Hub 주소&quot; href=&quot;https://github.com/Dove-kim/spring-boot-3-aws-sqs-bigmessage&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/Dove-kim/spring-boot-3-aws-sqs-bigmessage&lt;/a&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1720245432168&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - Dove-kim/spring-boot-3-aws-sqs-bigmessage: AWS SQS에서 256KB 이상의 메시지 전송 기능 구현&quot; data-og-description=&quot;AWS SQS에서 256KB 이상의 메시지 전송 기능 구현. Contribute to Dove-kim/spring-boot-3-aws-sqs-bigmessage development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/Dove-kim/spring-boot-3-aws-sqs-bigmessage&quot; data-og-url=&quot;https://github.com/Dove-kim/spring-boot-3-aws-sqs-bigmessage&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/IGgxy/hyWvQTVAD8/yBhOv33JLLjNZOw1HumlO0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/Dove-kim/spring-boot-3-aws-sqs-bigmessage&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/Dove-kim/spring-boot-3-aws-sqs-bigmessage&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/IGgxy/hyWvQTVAD8/yBhOv33JLLjNZOw1HumlO0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;GitHub - Dove-kim/spring-boot-3-aws-sqs-bigmessage: AWS SQS에서 256KB 이상의 메시지 전송 기능 구현&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;AWS SQS에서 256KB 이상의 메시지 전송 기능 구현. Contribute to Dove-kim/spring-boot-3-aws-sqs-bigmessage development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;보낼 수 있는 크기의 제한..?&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;646&quot; data-origin-height=&quot;45&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qmCm0/btsIpfnFrvQ/SukHzoo8HlytFau4pm7KgK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qmCm0/btsIpfnFrvQ/SukHzoo8HlytFau4pm7KgK/img.png&quot; data-alt=&quot;출처: https://aws.amazon.com/ko/sqs/features/&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qmCm0/btsIpfnFrvQ/SukHzoo8HlytFau4pm7KgK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqmCm0%2FbtsIpfnFrvQ%2FSukHzoo8HlytFau4pm7KgK%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;646&quot; height=&quot;45&quot; data-origin-width=&quot;646&quot; data-origin-height=&quot;45&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처: https://aws.amazon.com/ko/sqs/features/&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AWS SQS 완전 관리형에 백만건당 요금을 부과하기에 꽤 저렴하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만.. 큰 메시지를 보낼 때는 제약이 있고 AWS는 S3를 이용해 큰 메시지를 전송하도록 안내한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다행히 Java는 라이브러리를 제공해 준다. 라이브러리를 사용하면 큰 용량의 메시지도 편리하게 보낼 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단점으로는 S3를 추가로 사용하는 이유로&amp;nbsp; S3 저장비용과 데이터를 가져오는 비용을 감수해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;간단한 SQS와 S3 만들기&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 원하는 이름의 표준 대기열을 하나 만든다.&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;944&quot; data-origin-height=&quot;547&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cShn32/btsIqTDr7pJ/6maleXTnYtfNZuxKYLdzVK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cShn32/btsIqTDr7pJ/6maleXTnYtfNZuxKYLdzVK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cShn32/btsIqTDr7pJ/6maleXTnYtfNZuxKYLdzVK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcShn32%2FbtsIqTDr7pJ%2F6maleXTnYtfNZuxKYLdzVK%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;944&quot; height=&quot;547&quot; data-origin-width=&quot;944&quot; data-origin-height=&quot;547&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;h3 data-ke-size=&quot;size23&quot;&gt;2. 메시지 동시 처리를 막기 위해 표시 제한 시간과 기타 설정값을 세팅한다.&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;640&quot; data-origin-height=&quot;551&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/0XhY3/btsIpLNb88I/W2mODsOWKVaXY4KA1rp1Y0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/0XhY3/btsIpLNb88I/W2mODsOWKVaXY4KA1rp1Y0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/0XhY3/btsIpLNb88I/W2mODsOWKVaXY4KA1rp1Y0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F0XhY3%2FbtsIpLNb88I%2FW2mODsOWKVaXY4KA1rp1Y0%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;640&quot; height=&quot;551&quot; data-origin-width=&quot;640&quot; data-origin-height=&quot;551&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;h3 data-ke-size=&quot;size23&quot;&gt;3. 다른 설정은 변경 없이 &quot;대기열 생성&quot; 버튼 클릭&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;650&quot; data-origin-height=&quot;358&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xEhmk/btsIrdBGsaI/wyoFor75tj6mGctuTXKXRK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xEhmk/btsIrdBGsaI/wyoFor75tj6mGctuTXKXRK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xEhmk/btsIrdBGsaI/wyoFor75tj6mGctuTXKXRK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxEhmk%2FbtsIrdBGsaI%2FwyoFor75tj6mGctuTXKXRK%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;650&quot; height=&quot;358&quot; data-origin-width=&quot;650&quot; data-origin-height=&quot;358&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;h3 data-ke-size=&quot;size23&quot;&gt;4. S3 버킷을 만든다.&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;787&quot; data-origin-height=&quot;441&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bD2q7p/btsIreN79Al/GguQCXjCOYdjIN0oOjLFr1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bD2q7p/btsIreN79Al/GguQCXjCOYdjIN0oOjLFr1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bD2q7p/btsIreN79Al/GguQCXjCOYdjIN0oOjLFr1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbD2q7p%2FbtsIreN79Al%2FGguQCXjCOYdjIN0oOjLFr1%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;787&quot; height=&quot;441&quot; data-origin-width=&quot;787&quot; data-origin-height=&quot;441&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;스프링에서 SQS 확장 클라이언트 라이브러리 적용해 보기&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;1. build.gradle 수정&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;a title=&quot;Spring Cloud AWS&quot; href=&quot;https://spring.io/projects/spring-cloud-aws&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://spring.io/projects/spring-cloud-aws&lt;/a&gt;보다 AWS SDK를 직접 사용하는 것을 개인적으로 선호합니다.&lt;/blockquote&gt;
&lt;pre id=&quot;code_1720245504828&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;implementation platform(&quot;software.amazon.awssdk:bom:2.21.1&quot;)
implementation &quot;software.amazon.awssdk:sqs&quot;
implementation &quot;software.amazon.awssdk:s3&quot;

implementation 'com.amazonaws:amazon-sqs-java-extended-client-lib:2.1.1'&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. S3, SQS&amp;nbsp; 클라이언트 bean 등록&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DefaultCredentialsProvider.create()를 통해 서버가 기동 되는 환경에서 AWS CLI나 IAM 역할로 서버에게 AWS 접근을 가능하게 도와준다.&lt;/p&gt;
&lt;pre id=&quot;code_1720245745423&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Configuration
public class AwsConfig {

    @Bean
    public SqsClient sqsClient() {
        return SqsClient.builder()
                .region(Region.AP_NORTHEAST_2)
                .credentialsProvider(DefaultCredentialsProvider.create())
                .build();
    }

    @Bean
    public S3Client s3Client() {
        return S3Client.builder()
                .region(Region.AP_NORTHEAST_2)
                .credentialsProvider(DefaultCredentialsProvider.create())
                .build();
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. AWS SQS 확장 라이브러리 클라이언트에 사전에 만든 S3를 세팅한다.&lt;/h3&gt;
&lt;pre id=&quot;code_1720246237058&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;ExtendedClientConfiguration extendedClientConfig = new ExtendedClientConfiguration()
	.withPayloadSupportEnabled(s3Client, BUCKET_NAME);
this.sqsExtended = new AmazonSQSExtendedClient(SqsClient.builder().build(), extendedClientConfig);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4. SQS에서 메시지를 풀링 한다.&lt;/h3&gt;
&lt;pre id=&quot;code_1720246315273&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// SQS queue url
this.queueUrl = sqsClient.getQueueUrl(builder -&amp;gt; builder
        .queueName(SQS_QUEUE_NAME).build());
ReceiveMessageRequest receiveMessageRequest = ReceiveMessageRequest.builder()
                .queueUrl(queueUrl.queueUrl())
                .maxNumberOfMessages(10)
                .waitTimeSeconds(0)
                .build();
        
ReceiveMessageResponse receiveMessageResponse = sqsExtended
	.receiveMessage(receiveMessageRequest);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5. 읽고 처리한 메시지는 지운다.&lt;/h3&gt;
&lt;pre id=&quot;code_1720246363249&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;DeleteMessageRequest deleteMessageRequest = DeleteMessageRequest.builder()
                .queueUrl(queueUrl.queueUrl())
                .receiptHandle(message.receiptHandle())
                .build();
sqsExtended.deleteMessage(deleteMessageRequest);&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;질문 1. S3는 어떻게 작동을 도와줄까?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;간단하게 메시지를 publish 할 수 있는 컨트롤러를 만들고 postman으로 날려보자.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;861&quot; data-origin-height=&quot;420&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/IHIFo/btsIpT5hBA8/bRjsD4VlLE2PNgW5kp2jX0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/IHIFo/btsIpT5hBA8/bRjsD4VlLE2PNgW5kp2jX0/img.png&quot; data-alt=&quot;간단한 컨트롤러에 약 353KB의 메시지 전송&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/IHIFo/btsIpT5hBA8/bRjsD4VlLE2PNgW5kp2jX0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FIHIFo%2FbtsIpT5hBA8%2FbRjsD4VlLE2PNgW5kp2jX0%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;565&quot; height=&quot;276&quot; data-origin-width=&quot;861&quot; data-origin-height=&quot;420&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;간단한 컨트롤러에 약 353KB의 메시지 전송&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;IDE에서 브레이크 포인트로 메시지 처리를 멈추고&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;683&quot; data-origin-height=&quot;220&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bmB7LF/btsIrfGgUto/sQmFo4nmtu8draJPyJeD7k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bmB7LF/btsIrfGgUto/sQmFo4nmtu8draJPyJeD7k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bmB7LF/btsIrfGgUto/sQmFo4nmtu8draJPyJeD7k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbmB7LF%2FbtsIrfGgUto%2FsQmFo4nmtu8draJPyJeD7k%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;475&quot; height=&quot;153&quot; data-origin-width=&quot;683&quot; data-origin-height=&quot;220&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;S3에 가보니, 전송한 데이터가 파일로 만들어져 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;964&quot; data-origin-height=&quot;498&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/TKsL7/btsIpGE9jc9/zXG2tgt7HysHuOn210mAx0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/TKsL7/btsIpGE9jc9/zXG2tgt7HysHuOn210mAx0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/TKsL7/btsIpGE9jc9/zXG2tgt7HysHuOn210mAx0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FTKsL7%2FbtsIpGE9jc9%2FzXG2tgt7HysHuOn210mAx0%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;434&quot; height=&quot;224&quot; data-origin-width=&quot;964&quot; data-origin-height=&quot;498&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1533&quot; data-origin-height=&quot;907&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qelJQ/btsIqRMocnA/CEEjep2QoW4KtoxShjD96k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qelJQ/btsIqRMocnA/CEEjep2QoW4KtoxShjD96k/img.png&quot; data-alt=&quot;열어보니, 전송한 내용이다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qelJQ/btsIqRMocnA/CEEjep2QoW4KtoxShjD96k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqelJQ%2FbtsIqRMocnA%2FCEEjep2QoW4KtoxShjD96k%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;767&quot; height=&quot;454&quot; data-origin-width=&quot;1533&quot; data-origin-height=&quot;907&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;열어보니, 전송한 내용이다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 SQS client를 이용해 SQS 메시지를 지우면 S3에 있던 데이터도 같이 지워진다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;질문 2. 256KB보다 작은 사이즈의 메시지도 S3가 관여하는가?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PayloadStorageConfigurationBase에서 AmazonSQSExtendedClient를 세팅할 때 항상 S3를 사용할지 옵션이 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;357&quot; data-origin-height=&quot;41&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dpDEau/btsIqwuZLfQ/G8HkLrK4dq5vQJpqgPCQD0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dpDEau/btsIqwuZLfQ/G8HkLrK4dq5vQJpqgPCQD0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dpDEau/btsIqwuZLfQ/G8HkLrK4dq5vQJpqgPCQD0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdpDEau%2FbtsIqwuZLfQ%2FG8HkLrK4dq5vQJpqgPCQD0%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;357&quot; height=&quot;41&quot; data-origin-width=&quot;357&quot; data-origin-height=&quot;41&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;AmazonSQSExtendedClient는 설정 값에 따라 설정이 false이면, 메시지의 크기에 맞춰 S3를 사용할지 결정한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;783&quot; data-origin-height=&quot;138&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bOggtS/btsIqDt4Ud7/LentPvvuw4y0Jejh3MgIz1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bOggtS/btsIqDt4Ud7/LentPvvuw4y0Jejh3MgIz1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bOggtS/btsIqDt4Ud7/LentPvvuw4y0Jejh3MgIz1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbOggtS%2FbtsIqDt4Ud7%2FLentPvvuw4y0Jejh3MgIz1%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;783&quot; height=&quot;138&quot; data-origin-width=&quot;783&quot; data-origin-height=&quot;138&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;즉, 라이브러리에서 256KB보다 작은 메시지는 SQS만 이용하고 256KB보다 클 경우만 S3에 메시지를 저장하고 사용한다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;질문 3. SQS에서는 일정 시간이 지나면 처리 못한 메시지가 사라지는데 S3도 사라지게 할 수 있을까?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;S3 버킷에서 수명주기를 설정하면 SQS에서 메시지 보존 기간만큼 S3에서도 파일을 저장할 수 있다.&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;686&quot; data-origin-height=&quot;1066&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/AyCaX/btsIp5LcwDt/u4PRuzaJQB6R3EExerUvC0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/AyCaX/btsIp5LcwDt/u4PRuzaJQB6R3EExerUvC0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/AyCaX/btsIp5LcwDt/u4PRuzaJQB6R3EExerUvC0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FAyCaX%2FbtsIp5LcwDt%2Fu4PRuzaJQB6R3EExerUvC0%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;686&quot; height=&quot;1066&quot; data-origin-width=&quot;686&quot; data-origin-height=&quot;1066&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;참고한 문서&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://docs.aws.amazon.com/ko_kr/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-s3-messages.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://docs.aws.amazon.com/ko_kr/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-s3-messages.html&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1720247294938&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;자바와 아마존 S3를 사용하여 대용량 Amazon SQS 메시지 관리 - Amazon Simple Queue Service&quot; data-og-description=&quot;Java용 Amazon SQS 확장 클라이언트 라이브러리를 사용하면 Amazon S3에 AWS SDK for Java만 사용하여 Amazon SQS 메시지를 관리할 수 있습니다. Amazon SQS 콘솔 AWS CLI, Amazon SQS HTTP API 또는 기타 SDK로는 이 작업을&quot; data-og-host=&quot;docs.aws.amazon.com&quot; data-og-source-url=&quot;https://docs.aws.amazon.com/ko_kr/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-s3-messages.html&quot; data-og-url=&quot;https://docs.aws.amazon.com/ko_kr/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-s3-messages.html&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://docs.aws.amazon.com/ko_kr/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-s3-messages.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://docs.aws.amazon.com/ko_kr/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-s3-messages.html&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;자바와 아마존 S3를 사용하여 대용량 Amazon SQS 메시지 관리 - Amazon Simple Queue Service&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Java용 Amazon SQS 확장 클라이언트 라이브러리를 사용하면 Amazon S3에 AWS SDK for Java만 사용하여 Amazon SQS 메시지를 관리할 수 있습니다. Amazon SQS 콘솔 AWS CLI, Amazon SQS HTTP API 또는 기타 SDK로는 이 작업을&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;docs.aws.amazon.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://aws.amazon.com/ko/sqs/pricing/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://aws.amazon.com/ko/sqs/pricing/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1720247303911&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;company&quot; data-og-title=&quot;Amazon SQS 요금 | 메시지 대기열 서비스 | AWS&quot; data-og-description=&quot;* 프리 티어 사용량은 매달 GovCloud 리전을 제외한 모든 리전의 사용량을 합산하여 계산되며, 청구서에 자동으로 적용됩니다. 사용되지 않은 프리 티어는 다음 달로 이월되지 않습니다. 제약 조건&quot; data-og-host=&quot;aws.amazon.com&quot; data-og-source-url=&quot;https://aws.amazon.com/ko/sqs/pricing/&quot; data-og-url=&quot;https://aws.amazon.com/ko/sqs/pricing/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/ckB4yu/hyWvRrNheE/kHfDvKXVAK3UEd55NY0KN1/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/LdrPA/hyWvJN4cCS/m6lJwKAgHa32Ab6KWP4XPK/img.png?width=179&amp;amp;height=109&amp;amp;face=0_0_179_109&quot;&gt;&lt;a href=&quot;https://aws.amazon.com/ko/sqs/pricing/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://aws.amazon.com/ko/sqs/pricing/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/ckB4yu/hyWvRrNheE/kHfDvKXVAK3UEd55NY0KN1/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/LdrPA/hyWvJN4cCS/m6lJwKAgHa32Ab6KWP4XPK/img.png?width=179&amp;amp;height=109&amp;amp;face=0_0_179_109');&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;Amazon SQS 요금 | 메시지 대기열 서비스 | AWS&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;* 프리 티어 사용량은 매달 GovCloud 리전을 제외한 모든 리전의 사용량을 합산하여 계산되며, 청구서에 자동으로 적용됩니다. 사용되지 않은 프리 티어는 다음 달로 이월되지 않습니다. 제약 조건&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;aws.amazon.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://spring.io/projects/spring-cloud-aws&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://spring.io/projects/spring-cloud-aws&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1720247341615&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Spring Cloud for Amazon Web Services&quot; data-og-description=&quot;Spring Cloud for Amazon Web Services is a community-run project. The website is https://awspring.io/ and the source repository is located at https://github.com/awspring/spring-cloud-aws. Spring Cloud for Amazon Web Services, eases the integration with host&quot; data-og-host=&quot;spring.io&quot; data-og-source-url=&quot;https://spring.io/projects/spring-cloud-aws&quot; data-og-url=&quot;https://spring.io/projects/spring-cloud-aws&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bFFPY2/hyWvMxf7Sx/VAWKaeete8DhF7XMGvy3T0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/dPWnpS/hyWvLkOQ2l/tMTYuWGXUu62RbQTTn1z20/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://spring.io/projects/spring-cloud-aws&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://spring.io/projects/spring-cloud-aws&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bFFPY2/hyWvMxf7Sx/VAWKaeete8DhF7XMGvy3T0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/dPWnpS/hyWvLkOQ2l/tMTYuWGXUu62RbQTTn1z20/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Spring Cloud for Amazon Web Services&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Spring Cloud for Amazon Web Services is a community-run project. The website is https://awspring.io/ and the source repository is located at https://github.com/awspring/spring-cloud-aws. Spring Cloud for Amazon Web Services, eases the integration with host&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;spring.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>인프라</category>
      <category>AWS SQS</category>
      <category>spring boot aws</category>
      <category>spring sqs</category>
      <category>sqs 대용량</category>
      <author>dev.Dove</author>
      <guid isPermaLink="true">https://dpot.tistory.com/8</guid>
      <comments>https://dpot.tistory.com/8#entry8comment</comments>
      <pubDate>Sat, 6 Jul 2024 15:29:52 +0900</pubDate>
    </item>
    <item>
      <title>AWS Bedrock + Spring Boot + Amazon Bedrock Guardrails를 이용해 간단한 AI 사용해보기</title>
      <link>https://dpot.tistory.com/7</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;307&quot; data-origin-height=&quot;219&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pIArZ/btsH0vqngB3/viUWgDswGnGSoSbXHKpzU1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pIArZ/btsH0vqngB3/viUWgDswGnGSoSbXHKpzU1/img.png&quot; data-alt=&quot;출처: https://aws.amazon.com/ko/bedrock/?gclid=CjwKCAjwmrqzBhAoEiwAXVpgog6_EsXEYtqJQ5fNPU4BEh78xmY_rgkERvlGPEUTpz9-mYdTeHp3VRoCLXIQAvD_BwE&amp;amp;amp;trk=24a8f13a-f5db-4127-bcb7-8b2876aa4265&amp;amp;amp;sc_channel=ps&amp;amp;amp;ef_id=CjwKCAjwmrqzBhAoEiwAXVpgog6_EsXEYtqJQ5fNPU4BEh78xmY_rgkERvlGPEUTpz9-mYdTeHp3VRoCLXIQAvD_BwE:G:s&amp;amp;amp;s_kwcid=AL!4422!3!692062155749!e!!g!!amazon%20bedrock!21058131112!157173586057&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pIArZ/btsH0vqngB3/viUWgDswGnGSoSbXHKpzU1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpIArZ%2FbtsH0vqngB3%2FviUWgDswGnGSoSbXHKpzU1%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;307&quot; height=&quot;219&quot; data-origin-width=&quot;307&quot; data-origin-height=&quot;219&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처: https://aws.amazon.com/ko/bedrock/?gclid=CjwKCAjwmrqzBhAoEiwAXVpgog6_EsXEYtqJQ5fNPU4BEh78xmY_rgkERvlGPEUTpz9-mYdTeHp3VRoCLXIQAvD_BwE&amp;amp;trk=24a8f13a-f5db-4127-bcb7-8b2876aa4265&amp;amp;sc_channel=ps&amp;amp;ef_id=CjwKCAjwmrqzBhAoEiwAXVpgog6_EsXEYtqJQ5fNPU4BEh78xmY_rgkERvlGPEUTpz9-mYdTeHp3VRoCLXIQAvD_BwE:G:s&amp;amp;s_kwcid=AL!4422!3!692062155749!e!!g!!amazon%20bedrock!21058131112!157173586057&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;들어가기전..&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;본게시물은 2024년 6월에 작성했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Java 11, Spring Boot3를 사용했으며, 자세한 소스는 GitHub에 올렸습니다.&lt;/p&gt;
&lt;figure id=&quot;og_1718529110136&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;spring-boot-3-aws-bedrock/src/main/java/com/dpot/bedrock/domain/aichat/service at main &amp;middot; Dove-kim/spring-boot-3-aws-bedrock&quot; data-og-description=&quot;AWS Bedrock + Spring Boot 3. Contribute to Dove-kim/spring-boot-3-aws-bedrock development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/Dove-kim/spring-boot-3-aws-bedrock/tree/main/src/main/java/com/dpot/bedrock/domain/aichat/service&quot; data-og-url=&quot;https://github.com/Dove-kim/spring-boot-3-aws-bedrock/tree/main/src/main/java/com/dpot/bedrock/domain/aichat/service&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/dnlf7F/hyWoAWWvFH/KD4kTw0xpNT1KwksR1QNP0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/Dove-kim/spring-boot-3-aws-bedrock/tree/main/src/main/java/com/dpot/bedrock/domain/aichat/service&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/Dove-kim/spring-boot-3-aws-bedrock/tree/main/src/main/java/com/dpot/bedrock/domain/aichat/service&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/dnlf7F/hyWoAWWvFH/KD4kTw0xpNT1KwksR1QNP0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;spring-boot-3-aws-bedrock/src/main/java/com/dpot/bedrock/domain/aichat/service at main &amp;middot; Dove-kim/spring-boot-3-aws-bedrock&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;AWS Bedrock + Spring Boot 3. Contribute to Dove-kim/spring-boot-3-aws-bedrock development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;AWS Bedrock FM 사용 신청&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한국어를 사용할 수 있으며 토큰제한이 가장 큰(2024년 6월 기준) Cluade 3 모델을 사용해 보자.&amp;nbsp;&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;먼저, 사용하려는 모델의 액세스를 요청해야 사용이 가능하다. 2024년 6월 기준 미국 버지니아 북부에서 가장 많은 모델을 사용할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1587&quot; data-origin-height=&quot;926&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d7cwtK/btsHZ9Bdz9Y/aQi4Je4Mzp4FBjNo6p2Xp1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d7cwtK/btsHZ9Bdz9Y/aQi4Je4Mzp4FBjNo6p2Xp1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d7cwtK/btsHZ9Bdz9Y/aQi4Je4Mzp4FBjNo6p2Xp1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd7cwtK%2FbtsHZ9Bdz9Y%2FaQi4Je4Mzp4FBjNo6p2Xp1%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;1587&quot; height=&quot;926&quot; data-origin-width=&quot;1587&quot; data-origin-height=&quot;926&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원하는 모델의 권한요청을 하고 잠시 기다리면 요청한 모델의 권한이 부여된다.&amp;nbsp;&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;887&quot; data-origin-height=&quot;156&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b3ld3y/btsH16CSzoQ/ReqwUz5dWyvkMvafmLqYeK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b3ld3y/btsH16CSzoQ/ReqwUz5dWyvkMvafmLqYeK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b3ld3y/btsH16CSzoQ/ReqwUz5dWyvkMvafmLqYeK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb3ld3y%2FbtsH16CSzoQ%2FReqwUz5dWyvkMvafmLqYeK%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;887&quot; height=&quot;156&quot; data-origin-width=&quot;887&quot; data-origin-height=&quot;156&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 AWS Bedrock에서 제공업체 &amp;gt; 사용할 모델을 누르면 modelId 및 API 요청 가이드라인을 볼 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1604&quot; data-origin-height=&quot;696&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bYZJwv/btsH1k2A0FV/uK99tLDo3aatZHtP5he4k1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bYZJwv/btsH1k2A0FV/uK99tLDo3aatZHtP5he4k1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bYZJwv/btsH1k2A0FV/uK99tLDo3aatZHtP5he4k1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbYZJwv%2FbtsH1k2A0FV%2FuK99tLDo3aatZHtP5he4k1%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;1604&quot; height=&quot;696&quot; data-origin-width=&quot;1604&quot; data-origin-height=&quot;696&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style5&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;AWS Bedrock Spring Boot3에서 사용하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AWS SDK v2 for Java와 bedrock runtime을 import 한다.&lt;/p&gt;
&lt;pre id=&quot;code_1718527867324&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	implementation platform('software.amazon.awssdk:bom:2.26.3')
	implementation 'software.amazon.awssdk:bedrockruntime'&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AWS Bedrock client도 bean으로 등록한다.&lt;/p&gt;
&lt;pre id=&quot;code_1718527909217&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Configuration
public class AwsConfig {
    @Bean
    public BedrockRuntimeClient bedrockRuntimeClient() {
        return BedrockRuntimeClient.builder()
                .credentialsProvider(DefaultCredentialsProvider.create())
                .region(Region.US_EAST_1)
                .build();
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;선언한 client를 이용해 AWS Bedrock에게 converse api로 요청할 서비스를 만든다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; converse api 문서: &lt;a href=&quot;https://docs.aws.amazon.com/ko_kr/bedrock/latest/APIReference/API_runtime_Converse.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://docs.aws.amazon.com/ko_kr/bedrock/latest/APIReference/API_runtime_Converse.html&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1718528004864&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/**
 * AWS Bedrock Claude3 Sonnet FM을 이용해서 AI와 채팅한다.
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class Claude3SonnetCatChatService implements AiChatService {
    private final String MODEL_ID = &quot;anthropic.claude-3-sonnet-20240229-v1:0&quot;;

    private final String SYSTEM_PROMPT = &quot;너는 고양이야 한국어로 질문하면 '낭'으로 문장을 구성해서 대답하고 다른 나라 언어로 그 언어에 맞춰서 고양이 울음소리로 문장을 구성해서 대답해&quot;;

    private final BedrockRuntimeClient bedrockRuntimeClient;

    @Override
    public String send(String message) {
        // AI에게 전할 message 생성
        Message requestMessage = Message.builder()
                .content(ContentBlock.fromText(message))
                .role(ConversationRole.USER)
                .build();

        // 프롬프트
        SystemContentBlock systemContentBlock = SystemContentBlock.builder()
                .text(SYSTEM_PROMPT)
                .build();

        try {
            // AI 요청을 날린다.
            ConverseResponse response = bedrockRuntimeClient.converse(request -&amp;gt; request
                    .modelId(MODEL_ID)
                    .messages(requestMessage)
                    .system(systemContentBlock)
                    .inferenceConfig(config -&amp;gt; config
                            .maxTokens(512)
                            .temperature(0.5F)
                            .topP(0.9F)));




            // 응답값을 return
            return response.output().message().content().get(0).text();
        } catch (SdkClientException e) {
            log.error(e.toString(), e);
            throw new RuntimeException(e);
        }

    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 간단하게 controller를 만들어서 대화를 시작하면 AI가 답변을 준다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;513&quot; data-origin-height=&quot;546&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/behHbR/btsH18UUaD3/WHtEDk6l2KbraHL33Ldkv0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/behHbR/btsH18UUaD3/WHtEDk6l2KbraHL33Ldkv0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/behHbR/btsH18UUaD3/WHtEDk6l2KbraHL33Ldkv0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbehHbR%2FbtsH18UUaD3%2FWHtEDk6l2KbraHL33Ldkv0%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;513&quot; height=&quot;546&quot; data-origin-width=&quot;513&quot; data-origin-height=&quot;546&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;? AI가 이상하게 답변한다.&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;FM을 사용할 때는 프롬프트를 어떻게 작성하냐에 따라 AI가 의도한 대로 작동할 수도 못 할 수 도 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1718528251709&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;private final String SYSTEM_PROMPT = &quot;너는 고양이야 한국어로 질문하면 &quot;+
            &quot; '낭'으로 문장을 구성해서 대답하고 다른 나라 언어로 그 언어에 맞춰서 &quot;+
            &quot;고양이 울음소리로 문장을 구성해서 대답해&quot;;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 프롬프트를 통해&amp;nbsp; 고양이 같은 사람 AI를 만들고 싶었지만. 진짜 고양이 울음소리만 하는 상황을 마주했다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프롬프트를 수정해서 보다 정확하게 작성할 필요가 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1718528142784&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;private final String SYSTEM_PROMPT = &quot;너는 고양이고 이름은 'WoongCat'이야. &quot; +
        &quot;모든 문장이 끝면 고양이같은 말투를 써야해 &quot; +
        &quot;Q1: 안녕 너는 누구야? &quot; +
        &quot;A1: 난 고양이 웅캣이다냥. 반갑다냥&quot;;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 작성하면, AI에게 역할을 부여하고 예시를 보여주어 AI의 답변을 의도한 방향으로 만들도록 할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;747&quot; data-origin-height=&quot;549&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bfMCjW/btsHZ6xPLd6/rcoiKEszywINsv3IWOfcOk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bfMCjW/btsHZ6xPLd6/rcoiKEszywINsv3IWOfcOk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bfMCjW/btsHZ6xPLd6/rcoiKEszywINsv3IWOfcOk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbfMCjW%2FbtsHZ6xPLd6%2FrcoiKEszywINsv3IWOfcOk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;747&quot; height=&quot;549&quot; data-origin-width=&quot;747&quot; data-origin-height=&quot;549&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제야&amp;nbsp; 말을 하는 고양이 같다. 의도한 방향으로 AI가 잘 답변하는 듯하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style5&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;AI에게 이상한 질문을 한다면..?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI에게 폭력적인 말을 하거나, 불법적인 행위의 질문 나아가서 AI가 의도한 기능 외 다른 기능을 수행한다면, 개발자는 이를 사전에 막아야 한다.&amp;nbsp;&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;862&quot; data-origin-height=&quot;564&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dzeFnl/btsH13F9YCV/9B4BfeknxCNY6dIFYZ22Q0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dzeFnl/btsH13F9YCV/9B4BfeknxCNY6dIFYZ22Q0/img.png&quot; data-alt=&quot;고양이가 갑자기 AI 쳇봇이되는 마법~&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dzeFnl/btsH13F9YCV/9B4BfeknxCNY6dIFYZ22Q0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdzeFnl%2FbtsH13F9YCV%2F9B4BfeknxCNY6dIFYZ22Q0%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;862&quot; height=&quot;564&quot; data-origin-width=&quot;862&quot; data-origin-height=&quot;564&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;고양이가 갑자기 AI 쳇봇이되는 마법~&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 해결하기 위해 AWS는 가드레일을 제공해 준다.&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;1212&quot; data-origin-height=&quot;682&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/baAQoo/btsH01oLo5N/tTZYXFJKMKzTWyc1W5HUAK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/baAQoo/btsH01oLo5N/tTZYXFJKMKzTWyc1W5HUAK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/baAQoo/btsH01oLo5N/tTZYXFJKMKzTWyc1W5HUAK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbaAQoo%2FbtsH01oLo5N%2FtTZYXFJKMKzTWyc1W5HUAK%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;1212&quot; height=&quot;682&quot; data-origin-width=&quot;1212&quot; data-origin-height=&quot;682&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;FM에 입력 출력값의 필터강도를 GUI로 쉽게 설정이 가능하다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1244&quot; data-origin-height=&quot;1146&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tSqBQ/btsHZS7GgUe/w8UzzLZNMgUopFgLdAEmxK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tSqBQ/btsHZS7GgUe/w8UzzLZNMgUopFgLdAEmxK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tSqBQ/btsHZS7GgUe/w8UzzLZNMgUopFgLdAEmxK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtSqBQ%2FbtsHZS7GgUe%2Fw8UzzLZNMgUopFgLdAEmxK%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;1244&quot; height=&quot;1146&quot; data-origin-width=&quot;1244&quot; data-origin-height=&quot;1146&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특정 주제에 대해 필터도 가능하다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;852&quot; data-origin-height=&quot;437&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/3aq1x/btsH0nMIL0H/W3O60KmT58f4vp6k91ESQK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/3aq1x/btsH0nMIL0H/W3O60KmT58f4vp6k91ESQK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/3aq1x/btsH0nMIL0H/W3O60KmT58f4vp6k91ESQK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F3aq1x%2FbtsH0nMIL0H%2FW3O60KmT58f4vp6k91ESQK%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;852&quot; height=&quot;437&quot; data-origin-width=&quot;852&quot; data-origin-height=&quot;437&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;완성된 가드레일은 다음과 같다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1261&quot; data-origin-height=&quot;1108&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/X7lYV/btsH1hZdHYV/anYWLKiEnD81gGOkJ68QIk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/X7lYV/btsH1hZdHYV/anYWLKiEnD81gGOkJ68QIk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/X7lYV/btsH1hZdHYV/anYWLKiEnD81gGOkJ68QIk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FX7lYV%2FbtsH1hZdHYV%2FanYWLKiEnD81gGOkJ68QIk%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;1261&quot; height=&quot;1108&quot; data-origin-width=&quot;1261&quot; data-origin-height=&quot;1108&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 이걸 서비스 코드로 녹이면 다음과 같다. 단, 가드레일 사용 시 converse API 호출은 가드레일 세팅을 미지원한다. 고로 invoke 방식으로 변환해 구현한다.&lt;/p&gt;
&lt;pre id=&quot;code_1718529010118&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/**
 * AWS Bedrock Claude3 Sonnet FM을 이용해서 AI와 채팅한다.
 * With AWS Bedrock Guardrail
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class Claude3SonnetCatChatWithGuardRailService implements AiChatService {
    private final String MODEL_ID = &quot;anthropic.claude-3-sonnet-20240229-v1:0&quot;;

    private final String SYSTEM_PROMPT = &quot;너는 고양이고 이름은 'WoongCat'이야. &quot; +
            &quot;모든 문장이 끝면 고양이같은 말투를 써야해 &quot; +
            &quot;Q1: 안녕 너는 누구야? &quot; +
            &quot;A1: 난 고양이 웅캣이다냥. 반갑다냥&quot;;

    private final BedrockRuntimeClient bedrockRuntimeClient;

    @Override
    public String send(String message) {
        // AI에게 전할 message 생성
        String nativeRequestTemplate = &quot;&quot;&quot;
                {
                    &quot;anthropic_version&quot;: &quot;bedrock-2023-05-31&quot;,
                    &quot;max_tokens&quot;: 512,
                    &quot;temperature&quot;: 0.5,
                    &quot;topP&quot;: 0.9,
                    &quot;system&quot;: &quot;{{system_prompt}}&quot;,
                    &quot;messages&quot;: [{
                        &quot;role&quot;: &quot;user&quot;,
                        &quot;content&quot;: &quot;{{prompt}}&quot;
                    }]
                }&quot;&quot;&quot;;


        String nativeRequest = nativeRequestTemplate
                .replace(&quot;{{prompt}}&quot;, message)
                .replace(&quot;{{system_prompt}}&quot;, SYSTEM_PROMPT);

        try {

            // AI 요청을 날린다.
            InvokeModelResponse invokeModelResponse = bedrockRuntimeClient.invokeModel(InvokeModelRequest.builder()
                    .modelId(MODEL_ID)
                    .body(SdkBytes.fromUtf8String(nativeRequest))
                    .guardrailIdentifier(&quot;s3bowsoa37sy&quot;)
                    .guardrailVersion(&quot;DRAFT&quot;)
                    .build());

            // Decode the response body.
            JSONObject responseBody = new JSONObject(invokeModelResponse.body().asUtf8String());

            // 응답값을 return
            return responseBody.getJSONArray(&quot;content&quot;).getJSONObject(0).getString(&quot;text&quot;);
        } catch (SdkClientException e) {
            log.error(e.toString(), e);
            throw new RuntimeException(e);
        }

    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제는 의도한 대화만 하도록 필터링이 가능하다..!&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;878&quot; data-origin-height=&quot;547&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/5qqBV/btsH0YyWeVp/WMWbzcI460rWcfEUx4nEVK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/5qqBV/btsH0YyWeVp/WMWbzcI460rWcfEUx4nEVK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/5qqBV/btsH0YyWeVp/WMWbzcI460rWcfEUx4nEVK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F5qqBV%2FbtsH0YyWeVp%2FWMWbzcI460rWcfEUx4nEVK%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;878&quot; height=&quot;547&quot; data-origin-width=&quot;878&quot; data-origin-height=&quot;547&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;참고한 자료&lt;/h2&gt;
&lt;figure id=&quot;og_1718529091695&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Java 2.x용 SDK를 사용하는 Amazon Bedrock 런타임 예제 - AWS SDK for Java 2.x&quot; data-og-description=&quot;이 페이지에 작업이 필요하다는 점을 알려 주셔서 감사합니다. 실망시켜 드려 죄송합니다. 잠깐 시간을 내어 설명서를 향상시킬 수 있는 방법에 대해 말씀해 주십시오.&quot; data-og-host=&quot;docs.aws.amazon.com&quot; data-og-source-url=&quot;https://docs.aws.amazon.com/ko_kr/sdk-for-java/latest/developer-guide/java_bedrock-runtime_code_examples.html&quot; data-og-url=&quot;https://docs.aws.amazon.com/ko_kr/sdk-for-java/latest/developer-guide/java_bedrock-runtime_code_examples.html&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://docs.aws.amazon.com/ko_kr/sdk-for-java/latest/developer-guide/java_bedrock-runtime_code_examples.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://docs.aws.amazon.com/ko_kr/sdk-for-java/latest/developer-guide/java_bedrock-runtime_code_examples.html&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Java 2.x용 SDK를 사용하는 Amazon Bedrock 런타임 예제 - AWS SDK for Java 2.x&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;이 페이지에 작업이 필요하다는 점을 알려 주셔서 감사합니다. 실망시켜 드려 죄송합니다. 잠깐 시간을 내어 설명서를 향상시킬 수 있는 방법에 대해 말씀해 주십시오.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;docs.aws.amazon.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;figure id=&quot;og_1718529098803&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Use the Converse API - Amazon Bedrock&quot; data-og-description=&quot;Use the Converse API You can use the Amazon Bedrock Converse API to create conversational applications that send and receive messages to and from an Amazon Bedrock model. For example, you can create a chat bot that maintains a conversation over many turns &quot; data-og-host=&quot;docs.aws.amazon.com&quot; data-og-source-url=&quot;https://docs.aws.amazon.com/ko_kr/bedrock/latest/userguide/conversation-inference.html&quot; data-og-url=&quot;https://docs.aws.amazon.com/ko_kr/bedrock/latest/userguide/conversation-inference.html&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://docs.aws.amazon.com/ko_kr/bedrock/latest/userguide/conversation-inference.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://docs.aws.amazon.com/ko_kr/bedrock/latest/userguide/conversation-inference.html&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Use the Converse API - Amazon Bedrock&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Use the Converse API You can use the Amazon Bedrock Converse API to create conversational applications that send and receive messages to and from an Amazon Bedrock model. For example, you can create a chat bot that maintains a conversation over many turns&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;docs.aws.amazon.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;figure id=&quot;og_1718529103191&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;ConverseRequest (AWS SDK for Java - 1.12.744)&quot; data-og-description=&quot;Inference parameters to pass to the model. Converse supports a base set of inference parameters. If you need to pass additional parameters that the model supports, use the additionalModelRequestFields request field.&quot; data-og-host=&quot;docs.aws.amazon.com&quot; data-og-source-url=&quot;https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/bedrockruntime/model/ConverseRequest.html&quot; data-og-url=&quot;https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/bedrockruntime/model/ConverseRequest.html&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/bedrockruntime/model/ConverseRequest.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/bedrockruntime/model/ConverseRequest.html&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;ConverseRequest (AWS SDK for Java - 1.12.744)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Inference parameters to pass to the model. Converse supports a base set of inference parameters. If you need to pass additional parameters that the model supports, use the additionalModelRequestFields request field.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;docs.aws.amazon.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>인프라</category>
      <category>Ai</category>
      <category>aws bedrock</category>
      <category>Claude3</category>
      <category>claude3 sonnet</category>
      <category>FM</category>
      <category>Java</category>
      <category>spring boot</category>
      <author>dev.Dove</author>
      <guid isPermaLink="true">https://dpot.tistory.com/7</guid>
      <comments>https://dpot.tistory.com/7#entry7comment</comments>
      <pubDate>Sun, 16 Jun 2024 18:13:31 +0900</pubDate>
    </item>
    <item>
      <title>AWS SNS과 FCM 그리고 Spring Boot를 곁들인..</title>
      <link>https://dpot.tistory.com/6</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;805&quot; data-origin-height=&quot;625&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cTzwBK/btsHjBqbSBY/aABkne70tyMSvK0idKi04K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cTzwBK/btsHjBqbSBY/aABkne70tyMSvK0idKi04K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cTzwBK/btsHjBqbSBY/aABkne70tyMSvK0idKi04K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcTzwBK%2FbtsHjBqbSBY%2FaABkne70tyMSvK0idKi04K%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;805&quot; height=&quot;625&quot; data-origin-width=&quot;805&quot; data-origin-height=&quot;625&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;시작하기 앞서&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;본 글은 2024년 4월 말~ 5월 1주 차에 작성했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Spring boot 2, Java 17과 AWS SDK v2를 사용했습니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;언제 이런 기능이 생긴거지..?&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1367&quot; data-origin-height=&quot;166&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bvlPRx/btsHke9k6hG/MUUzpsauf9nbBFOo8fBIT1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bvlPRx/btsHke9k6hG/MUUzpsauf9nbBFOo8fBIT1/img.png&quot; data-alt=&quot;..??????&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bvlPRx/btsHke9k6hG/MUUzpsauf9nbBFOo8fBIT1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbvlPRx%2FbtsHke9k6hG%2FMUUzpsauf9nbBFOo8fBIT1%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;1367&quot; height=&quot;166&quot; data-origin-width=&quot;1367&quot; data-origin-height=&quot;166&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;..??????&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;회사에서 AWS SNS를 이용해 Slack메시지 전송을 구현하려다 우연히 모바일 푸시를 발견했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;새 기능 알럿을 보니, FCM 사용이 가능하다는데, 기존 FCM만 사용하는 것과 차이가 궁금하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;퇴근하고 조금씩 조사한 내용을 정리해 보자&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;AWS SNS 모바일 푸시&lt;/h2&gt;
&lt;figure id=&quot;og_1715177003679&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;모바일 푸시 알림 - Amazon Simple Notification Service&quot; data-og-description=&quot;이 페이지에 작업이 필요하다는 점을 알려 주셔서 감사합니다. 실망시켜 드려 죄송합니다. 잠깐 시간을 내어 설명서를 향상시킬 수 있는 방법에 대해 말씀해 주십시오.&quot; data-og-host=&quot;docs.aws.amazon.com&quot; data-og-source-url=&quot;https://docs.aws.amazon.com/ko_kr/sns/latest/dg/sns-mobile-application-as-subscriber.html&quot; data-og-url=&quot;https://docs.aws.amazon.com/ko_kr/sns/latest/dg/sns-mobile-application-as-subscriber.html&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://docs.aws.amazon.com/ko_kr/sns/latest/dg/sns-mobile-application-as-subscriber.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://docs.aws.amazon.com/ko_kr/sns/latest/dg/sns-mobile-application-as-subscriber.html&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;모바일 푸시 알림 - Amazon Simple Notification Service&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;이 페이지에 작업이 필요하다는 점을 알려 주셔서 감사합니다. 실망시켜 드려 죄송합니다. 잠깐 시간을 내어 설명서를 향상시킬 수 있는 방법에 대해 말씀해 주십시오.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;docs.aws.amazon.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공식 문서를 보니, 푸시 메시지 플랫폼을 AWS SNS로 연결해서 AWS 인프라로 Push 알림을 전송할 수 있는 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구현해보자&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;0. Firebase에서 FCM을 전송할 프로젝트를 먼저 구성해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로젝트 생성 후 설정, &quot;서비스 계정&quot;에서 &quot;새 비공개 키 생성&quot;을 통해 json키를 먼저 받는다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1405&quot; data-origin-height=&quot;859&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vCmBI/btsHgCEf1V4/nw3Jyj1eTnA2kEIzQydaJk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vCmBI/btsHgCEf1V4/nw3Jyj1eTnA2kEIzQydaJk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vCmBI/btsHgCEf1V4/nw3Jyj1eTnA2kEIzQydaJk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FvCmBI%2FbtsHgCEf1V4%2Fnw3Jyj1eTnA2kEIzQydaJk%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;1405&quot; height=&quot;859&quot; data-origin-width=&quot;1405&quot; data-origin-height=&quot;859&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. AWS SNS에서 &quot;푸시 알림&quot;을 선택하고 &quot;플랫폼 어플리 케이션 생성&quot;을 선택한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1316&quot; data-origin-height=&quot;594&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bPL6el/btsHkjphDAp/HKyJz4JmbKb6Mb0l0QpwXK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bPL6el/btsHkjphDAp/HKyJz4JmbKb6Mb0l0QpwXK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bPL6el/btsHkjphDAp/HKyJz4JmbKb6Mb0l0QpwXK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbPL6el%2FbtsHkjphDAp%2FHKyJz4JmbKb6Mb0l0QpwXK%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;1316&quot; height=&quot;594&quot; data-origin-width=&quot;1316&quot; data-origin-height=&quot;594&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 푸시 알림 플랫폼을 &quot;FCM&quot;으로 선택하고 자격증명은 &quot;토큰&quot;으로 한 뒤 Firebase에서 미리 받은 json키를 업로드한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;956&quot; data-origin-height=&quot;772&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dbIl8j/btsHh9nS2P3/cDT1kIuvRekPjtbMLqT0zk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dbIl8j/btsHh9nS2P3/cDT1kIuvRekPjtbMLqT0zk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dbIl8j/btsHh9nS2P3/cDT1kIuvRekPjtbMLqT0zk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdbIl8j%2FbtsHh9nS2P3%2FcDT1kIuvRekPjtbMLqT0zk%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;956&quot; height=&quot;772&quot; data-origin-width=&quot;956&quot; data-origin-height=&quot;772&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;3. Spring Boot에서 사용하기 위해 AWS SDK v2를 gradle에 추가한다.&lt;/p&gt;
&lt;pre id=&quot;code_1715178142306&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;    implementation &quot;software.amazon.awssdk:lambda:2.20.122&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. FCM에서 발급받은 토큰을 AWS SNS에 엔드포인트로 만들고 전송한다.&lt;/p&gt;
&lt;pre id=&quot;code_1715178317359&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;CreatePlatformEndpointResponse platformEndpoint = snsClient.createPlatformEndpoint(CreatePlatformEndpointRequest.builder()
            .platformApplicationArn(&quot;{aws sns 콘솔에서 확인 가능한 arn 값}&quot;)
            .token(token)
            .build());


Notification notification = new Notification(&quot;제목&quot;, &quot;내용&quot;);
PublishResponse publishResponse = snsClient.publish(
	PublishRequest.builder()
        .targetArn(platformEndpoint.endpointArn())
        .message(notification.toJson())
        .build()
);&lt;/code&gt;&lt;/pre&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;AWS SNS를 사용할 이유가 있는가..?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결국 FCM를 AWS SNS로 감싸서 사용하는 형태니, 다음과 같은 특징을 가지고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. AWS 인프라와 연계성이 좋다. (장점)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;gt;&amp;gt; spring boot가 아닌 AWS Lambda로 서버리스 환경을 구성하면, 고가용성에 대한 고민이 사라진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;gt;&amp;gt; Cloud Watch 연동이 가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. AWS 내 인프라 사용에 제약을 인지하고 사용해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;gt;&amp;gt; push를 topic기반으로 전송할 경우 AWS는 구독자의 수를 제한하고 FCM은 최대 구독수를 제한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;gt;&amp;gt; 이건 프로젝트의 성격에 따라 FCM도 AWS 도 둘 다 좋은 선택지가 될 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1752&quot; data-origin-height=&quot;681&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kJyY6/btsHgp57Afk/qjDKSVlEiPdsAeluOmqaAK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kJyY6/btsHgp57Afk/qjDKSVlEiPdsAeluOmqaAK/img.png&quot; data-alt=&quot;https://docs.aws.amazon.com/ko_kr/general/latest/gr/sns.html&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kJyY6/btsHgp57Afk/qjDKSVlEiPdsAeluOmqaAK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkJyY6%2FbtsHgp57Afk%2FqjDKSVlEiPdsAeluOmqaAK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1752&quot; height=&quot;681&quot; data-origin-width=&quot;1752&quot; data-origin-height=&quot;681&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://docs.aws.amazon.com/ko_kr/general/latest/gr/sns.html&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;812&quot; data-origin-height=&quot;123&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nbW3B/btsHgAsTQtF/XNBKI3rvGf99WRa6lZS9AK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nbW3B/btsHgAsTQtF/XNBKI3rvGf99WRa6lZS9AK/img.png&quot; data-alt=&quot;https://firebase.google.com/docs/cloud-messaging/android/topic-messaging?hl=ko&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nbW3B/btsHgAsTQtF/XNBKI3rvGf99WRa6lZS9AK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnbW3B%2FbtsHgAsTQtF%2FXNBKI3rvGf99WRa6lZS9AK%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;812&quot; height=&quot;123&quot; data-origin-width=&quot;812&quot; data-origin-height=&quot;123&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://firebase.google.com/docs/cloud-messaging/android/topic-messaging?hl=ko&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 비용&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;gt;&amp;gt; FCM은 무료다. AWS SNS는 백만건당. $0.5를 청구한다.(한국 리전 기준)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;904&quot; data-origin-height=&quot;268&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/HyVQk/btsHiJbaXyg/F23NcfytqsFtNYN4tIUutK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/HyVQk/btsHiJbaXyg/F23NcfytqsFtNYN4tIUutK/img.png&quot; data-alt=&quot;https://aws.amazon.com/ko/sns/pricing/&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/HyVQk/btsHiJbaXyg/F23NcfytqsFtNYN4tIUutK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHyVQk%2FbtsHiJbaXyg%2FF23NcfytqsFtNYN4tIUutK%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;904&quot; height=&quot;268&quot; data-origin-width=&quot;904&quot; data-origin-height=&quot;268&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://aws.amazon.com/ko/sns/pricing/&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;정리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AWS SNS는 기존 AWS 인프라를 사용하길 원하며, 다양한 주제(몇 만개)를 만들어서 앱을 일괄로 묶어서 푸시 전송할 경우에는 사용할 가치가 있어 보인다. 다만, 프로젝트의 규모가 작으면(구독할 주제가 적을 경우) 굳이 부가적은 AWS SNS 비용을 지불하며 사용할 필요는 없어 보인다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;참고한 사이트&lt;/h2&gt;
&lt;figure id=&quot;og_1715177754343&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;SDK for Java 2.x를 사용하는 Amazon SNS 예제 - AWS SDK for Java 2.x&quot; data-og-description=&quot;이 페이지에 작업이 필요하다는 점을 알려 주셔서 감사합니다. 실망시켜 드려 죄송합니다. 잠깐 시간을 내어 설명서를 향상시킬 수 있는 방법에 대해 말씀해 주십시오.&quot; data-og-host=&quot;docs.aws.amazon.com&quot; data-og-source-url=&quot;https://docs.aws.amazon.com/ko_kr/sdk-for-java/latest/developer-guide/java_sns_code_examples.html&quot; data-og-url=&quot;https://docs.aws.amazon.com/ko_kr/sdk-for-java/latest/developer-guide/java_sns_code_examples.html&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://docs.aws.amazon.com/ko_kr/sdk-for-java/latest/developer-guide/java_sns_code_examples.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://docs.aws.amazon.com/ko_kr/sdk-for-java/latest/developer-guide/java_sns_code_examples.html&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;SDK for Java 2.x를 사용하는 Amazon SNS 예제 - AWS SDK for Java 2.x&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;이 페이지에 작업이 필요하다는 점을 알려 주셔서 감사합니다. 실망시켜 드려 죄송합니다. 잠깐 시간을 내어 설명서를 향상시킬 수 있는 방법에 대해 말씀해 주십시오.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;docs.aws.amazon.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;figure id=&quot;og_1715177779969&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;SubscribeRequest (AWS SDK for Java - 2.25.47)&quot; data-og-description=&quot;Sets whether the response from the Subscribe request includes the subscription ARN, even if the subscription is not yet confirmed. If you set this parameter to true, the response includes the ARN in all cases, even if the subscription is not yet confirmed.&quot; data-og-host=&quot;sdk.amazonaws.com&quot; data-og-source-url=&quot;https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sns/model/SubscribeRequest.html#protocol()&quot; data-og-url=&quot;https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sns/model/SubscribeRequest.html#protocol()&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sns/model/SubscribeRequest.html#protocol()&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/sns/model/SubscribeRequest.html#protocol()&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;SubscribeRequest (AWS SDK for Java - 2.25.47)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Sets whether the response from the Subscribe request includes the subscription ARN, even if the subscription is not yet confirmed. If you set this parameter to true, the response includes the ARN in all cases, even if the subscription is not yet confirmed.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;sdk.amazonaws.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>인프라</category>
      <category>aws push notification</category>
      <category>AWS SNS</category>
      <category>aws sns push message</category>
      <category>FCM</category>
      <category>firebase message</category>
      <category>firebase push</category>
      <category>Java</category>
      <category>push notification</category>
      <category>spring</category>
      <category>spring boot</category>
      <author>dev.Dove</author>
      <guid isPermaLink="true">https://dpot.tistory.com/6</guid>
      <comments>https://dpot.tistory.com/6#entry6comment</comments>
      <pubDate>Wed, 8 May 2024 23:45:08 +0900</pubDate>
    </item>
    <item>
      <title>JPA IdentifierGenerator의 connection에 대해..</title>
      <link>https://dpot.tistory.com/5</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;본 글은 Spring Boot 2.7.13(Java 17), Hibernate 5.6.15 기준으로 작성됨&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JPA에서 ID를 커스텀하게 만들 때 IdentifierGenerator, Configurable를 implements 받아서 ID생성기를 구현한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구글링을 하다보면, session.connection();이나 session.getJdbcConnectionAccess().obtainConnection();를 사용해서 DB connection을 가져온다.&lt;/p&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: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;session.connection()과&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;session.getJdbcConnectionAccess().obtainConnection()는 뭔 차이일까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1단계 일단, 둘 다 디버깅 걸어보자&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;session.connection()&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1044&quot; data-origin-height=&quot;300&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bv2kLf/btss90qnsw1/iqn7wWG0L3YZyhpKFokQgK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bv2kLf/btss90qnsw1/iqn7wWG0L3YZyhpKFokQgK/img.png&quot; data-alt=&quot;application.yml로 설정한 hikari-pool이 보인다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bv2kLf/btss90qnsw1/iqn7wWG0L3YZyhpKFokQgK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbv2kLf%2Fbtss90qnsw1%2Fiqn7wWG0L3YZyhpKFokQgK%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;1044&quot; height=&quot;300&quot; data-origin-width=&quot;1044&quot; data-origin-height=&quot;300&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;application.yml로 설정한 hikari-pool이 보인다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;session.getJdbcConnectionAccess().obtainConnection()&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1447&quot; data-origin-height=&quot;357&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/XgKqx/btssT9CMysZ/0oz7GviD8dVcPOnppVGhHK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/XgKqx/btssT9CMysZ/0oz7GviD8dVcPOnppVGhHK/img.png&quot; data-alt=&quot;어..? hikaripool의 클래스 주소까지 같네..??&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/XgKqx/btssT9CMysZ/0oz7GviD8dVcPOnppVGhHK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FXgKqx%2FbtssT9CMysZ%2F0oz7GviD8dVcPOnppVGhHK%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;1447&quot; height=&quot;357&quot; data-origin-width=&quot;1447&quot; data-origin-height=&quot;357&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;어..? hikaripool의 클래스 주소까지 같네..??&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;2단계, 문서와 코드를 까보자&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;session.connection()&amp;nbsp;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;648&quot; data-origin-height=&quot;104&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Vg40w/btss856EoB8/9HuOjzuojOnl7B7QKwjksK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Vg40w/btss856EoB8/9HuOjzuojOnl7B7QKwjksK/img.png&quot; data-alt=&quot;출처:&amp;amp;amp;nbsp;https://github.com/hibernate/hibernate-orm/blob/main/hibernate-core/src/main/java/org/hibernate/engine/spi/SharedSessionContractImplementor.java&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Vg40w/btss856EoB8/9HuOjzuojOnl7B7QKwjksK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FVg40w%2Fbtss856EoB8%2F9HuOjzuojOnl7B7QKwjksK%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;648&quot; height=&quot;104&quot; data-origin-width=&quot;648&quot; data-origin-height=&quot;104&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처:&amp;amp;nbsp;https://github.com/hibernate/hibernate-orm/blob/main/hibernate-core/src/main/java/org/hibernate/engine/spi/SharedSessionContractImplementor.java&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1405&quot; data-origin-height=&quot;464&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/GW9tK/btssUPjHQDh/YhSuOZB2jIkgXg7nMKZMk0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/GW9tK/btssUPjHQDh/YhSuOZB2jIkgXg7nMKZMk0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/GW9tK/btssUPjHQDh/YhSuOZB2jIkgXg7nMKZMk0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGW9tK%2FbtssUPjHQDh%2FYhSuOZB2jIkgXg7nMKZMk0%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;1405&quot; height=&quot;464&quot; data-origin-width=&quot;1405&quot; data-origin-height=&quot;464&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;하이버네이트가 관리하는 JDBC 커넥션&lt;/blockquote&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;session.getJdbcConnectionAccess().obtainConnection()&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;getJdbcConnectionAccess에 해당하는 JdbcConnectionAccess 인터페이스에 보면,&lt;/p&gt;
&lt;pre id=&quot;code_1693825188361&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/**
 * Provides centralized access to JDBC connections.  Centralized to hide the complexity of accounting for contextual
 * (multi-tenant) versus non-contextual access.
 *
 * @author Steve Ebersole
 */
public interface JdbcConnectionAccess extends Serializable {&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파파고를 통하면,&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1312&quot; data-origin-height=&quot;293&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/7jNEC/btstaxVUhfh/zKRWcd8cme0EVFGNo0fTR0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/7jNEC/btstaxVUhfh/zKRWcd8cme0EVFGNo0fTR0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/7jNEC/btstaxVUhfh/zKRWcd8cme0EVFGNo0fTR0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F7jNEC%2FbtstaxVUhfh%2FzKRWcd8cme0EVFGNo0fTR0%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;1312&quot; height=&quot;293&quot; data-origin-width=&quot;1312&quot; data-origin-height=&quot;293&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;중앙 접근이 가능한 JDBC&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;어떤 걸 써야 하지...??&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;datasource를 빈으로 등록해서 스프링 서버를 구동하면, 둘 다 문제없는 소스다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만, hibernate가 관리하는 JDBC보단 중앙 접근 가능한 방식이 조금 더 좋은 코드로 보인다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추가로, Jboss 사이트의 hibernate문서를 보면, connection()은 4.x버전부터 제거예정이라고 명시했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제거될 함수보다는 session.getJdbcConnectionAccess().obtainConnection()를 쓰는 것이 좋을듯하다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1413&quot; data-origin-height=&quot;228&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mxDMT/btssZdkaDbF/jHK8NFKm9aRK2p9i8IUeoK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mxDMT/btssZdkaDbF/jHK8NFKm9aRK2p9i8IUeoK/img.png&quot; data-alt=&quot;https://docs.jboss.org/hibernate/core/3.5/api/org/hibernate/Session.html#connection()&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mxDMT/btssZdkaDbF/jHK8NFKm9aRK2p9i8IUeoK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmxDMT%2FbtssZdkaDbF%2FjHK8NFKm9aRK2p9i8IUeoK%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;1413&quot; height=&quot;228&quot; data-origin-width=&quot;1413&quot; data-origin-height=&quot;228&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://docs.jboss.org/hibernate/core/3.5/api/org/hibernate/Session.html#connection()&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;여담...&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;520&quot; data-origin-height=&quot;289&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Ll1Eh/btssTotuB7v/JAZM2g986hDrez2OkRC2aK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Ll1Eh/btssTotuB7v/JAZM2g986hDrez2OkRC2aK/img.png&quot; data-alt=&quot;아니.. hibernate 5.x버전 쓰는데, @Deprecated 어노테이션 없던데..;;;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Ll1Eh/btssTotuB7v/JAZM2g986hDrez2OkRC2aK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLl1Eh%2FbtssTotuB7v%2FJAZM2g986hDrez2OkRC2aK%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;335&quot; height=&quot;289&quot; data-origin-width=&quot;520&quot; data-origin-height=&quot;289&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;아니.. hibernate 5.x버전 쓰는데, @Deprecated 어노테이션 없던데..;;;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>개발 고민</category>
      <category>Connection</category>
      <category>jdbc</category>
      <category>spring boot</category>
      <category>spring data JPA</category>
      <author>dev.Dove</author>
      <guid isPermaLink="true">https://dpot.tistory.com/5</guid>
      <comments>https://dpot.tistory.com/5#entry5comment</comments>
      <pubDate>Mon, 4 Sep 2023 20:24:39 +0900</pubDate>
    </item>
    <item>
      <title>단일 책임 원칙과 클린코드 V2</title>
      <link>https://dpot.tistory.com/4</link>
      <description>&lt;blockquote data-ke-style=&quot;style2&quot;&gt;해당 게시글은 과거 개인 블로그에 작성한 내용을 옮긴 내용입니다.&lt;br /&gt;https://tech.dpot.xyz/post/52&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;591&quot; data-origin-height=&quot;588&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c6V5tR/btsqILp84s9/TL8OuUhVOtgH6Jqj7GKCm1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c6V5tR/btsqILp84s9/TL8OuUhVOtgH6Jqj7GKCm1/img.jpg&quot; data-alt=&quot;알죠..? 알면서..&amp;amp;nbsp; (출처:https://www.huffingtonpost.kr/entry/solid_kr_5a9df0e2e4b0479c02564332)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c6V5tR/btsqILp84s9/TL8OuUhVOtgH6Jqj7GKCm1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc6V5tR%2FbtsqILp84s9%2FTL8OuUhVOtgH6Jqj7GKCm1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;591&quot; height=&quot;588&quot; data-origin-width=&quot;591&quot; data-origin-height=&quot;588&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;알죠..? 알면서..&amp;nbsp; (출처:https://www.huffingtonpost.kr/entry/solid_kr_5a9df0e2e4b0479c02564332)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;개발하며 다른 개발자와 협업하는 상황이 많이 온다.&amp;nbsp;서비스의 기획,&amp;nbsp;설계를 함께하면 상관없어도,&amp;nbsp;프로젝트 중간에 개발자가 참여하면 서비스의 전반적 이해를 위해 적지 않은 시간이 필요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;이러한 상황에서 SOLID의 S인 단일 책임 원칙에 준수하여 작성한 소스는 빛난다.&amp;nbsp;실무에서 개발하며,&amp;nbsp;느낀 단일책임원칙을 준수하기 위한 간단한 규칙을 정리해 보려 한다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. Setter 금지&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;생각해 보면 Lombok&amp;nbsp;찬양론을 말하던 개발자였다. @Data하나면 모든 것을 만들어주던 라이브러리의 문제는 생각하지도 않고 사용했던 것부터 클린코드와 이별한 듯하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;JPA와 lombok을 같이 사용할 경우 영속성이 유지된 엔티티에서 update쿼리를 위해 set을 무차별적으로 사용하거나 insert를 위해 서비스단에서 여러 번의 setter을 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;예시1)&amp;nbsp;책을 빌리면 빌렸다고 상태를 바꿔야 해요&lt;/blockquote&gt;
&lt;pre id=&quot;code_1691577158024&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public void rent01() {
    BookRent bookRent = new BookRent();
    bookRent.setRentDateTime(LocalDateTime.now());
    bookRent.setIsRent(true);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;예시2)책임은 클래스가 서비스는 호출만&lt;/blockquote&gt;
&lt;pre id=&quot;code_1691577206498&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public void rent02() {
    BookRent bookRent = new BookRent();
    bookRent.rent();
}
public class BookRent {
    @Id
    private Long id;

    @Column
    private LocalDateTime rentDateTime;

    @Column
    private Boolean isRent;

    public BookRent rent(){
        this.rentDateTime = LocalDateTime.now();
        this.isRent = true;

        return this;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;위 2개의 소스를 보면 더욱 이해가 쉽다.&amp;nbsp;예시 1번의 경우 새로 프로젝트에 참여한 개발자에게 책을 대여할 때 시간과 상태를 바꿔야 한다고 말해야 한다.&amp;nbsp;하지만,&amp;nbsp;예시 2번을 보면 책을 대여하는 메소드를 알려주면 끝난다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;당연히,&amp;nbsp;값의 오류는 방지되고 수정이 필요한 값만 설정할 수 있다.&amp;nbsp;조금 생각해보면, id&amp;nbsp;칼럼 역시 jpa가 persist될때 자동으로 세팅 되며,&amp;nbsp;개발자는 수정할 일이 없다.&amp;nbsp;하지만, @Setter는 잘못 사용하면 id도 변경 가능한 것처럼 보여주기에 자칫 원치 않는 상황을 만들 수 있다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. DTO에서는 다양한 생성자 사용&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;DTO세팅의 책임도 DTO가 가져가도록.&lt;/blockquote&gt;
&lt;pre id=&quot;code_1691577274658&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class&amp;nbsp;BookInfoDto {
&amp;nbsp; &amp;nbsp; private&amp;nbsp;String&amp;nbsp;bookName;

&amp;nbsp; &amp;nbsp; private&amp;nbsp;LocalDateTime&amp;nbsp;createdAt;

&amp;nbsp; &amp;nbsp; private&amp;nbsp;Boolean&amp;nbsp;rentAble&amp;nbsp;=&amp;nbsp;false;

&amp;nbsp; &amp;nbsp; public&amp;nbsp;BookInfoDto(Book book) {
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; this.bookName&amp;nbsp;= book.getBookName();
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; this.createdAt&amp;nbsp;= book.getCreatedAt();

&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; List&amp;lt;BookRent&amp;gt; bookRentList = book.getBookRentList();
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if(!bookRentList.isEmpty()){
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; this.rentAble&amp;nbsp;=&amp;nbsp;true;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }
&amp;nbsp; &amp;nbsp; }

}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;서비스단에서 DTO를 만들고 값을 넣을 때도 set보다 생성자를 쓰길 권장한다.&amp;nbsp;또한,&amp;nbsp;다양한 객체를 받는 생성자를 만들어서 어떠한 값을 받아도 DTO안에서 모든 변환 로직을 관리 할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;이 방법을 통해 혹시라도 여러 서비스에서 DTO를 사용할 수 있으며, DTO의 값이 옳바르지 않음을 보장한다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. validation을 통한 올바른 값만 받기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;Validation은 생각보다 강력합니다.&lt;/blockquote&gt;
&lt;pre id=&quot;code_1691577363803&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@JsonProperty('repeatDay')
@Pattern(regexp = '[1-7](\\|[1-7]{1}){0,6}')
@Schema(description = '반복 요일. 1~7: 월~일', example = '1|2|3|4|5|6|7')
private String repeatDayStr;//반복 요일

@JsonProperty('startDate')
@DateTimeFormat(pattern = 'yyyy-MM-dd')
@Schema(description = '시작 일자', example = 'YYYY-MM-DD')
private LocalDate startDate;//시작 일자&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;종종 client가 이상한 값을 보낼 때가 존재한다.&amp;nbsp;이상한 값의 정의는 다음과 같다.&amp;nbsp;날짜를 받아야 하는데 이상한 형식으로 주기도 하고 새로운 client&amp;nbsp;개발자는 Long&amp;nbsp;타입의 id&amp;nbsp;대신 string 0을 주는 일도 있다.&amp;nbsp;물론,&amp;nbsp;서비스단에서 이러한 값이 틀렸음을 예외 처리하면 된다.&amp;nbsp;하지만 서비스에서는 서비스 로직의 문제만 예외 처리해야 한다고 생각하기에 틀린 값이 아닌 이상한 값은 아예 안 받는 것을 고려해 볼 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;더욱이, Validation은 다양한 어노테이션을 지원한다.&amp;nbsp;가볍게는 숫자 타입의 변수 확인부터 필자가 많이 사용하는 @Pattern까지 어지간한 값은 모두 검사할 수 있다. Validation을 통해 컨트롤러단에 들어온 요청의 값은 틀릴 수 있어도,&amp;nbsp;이상할 수 없음이 보장되었다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;Spring Boot로 개발하며 의존성 역전은 autowired로, 인터페이스 분리 원칙은 Repository를 만들며, OCP와 LSP는 엔티티에서 공통 컬럼을 분리하면 자연스럽게 적용하게 된다. 하지만 SRP (단일 책임 원칙)은 자연스럽게 되는 것이 아닌 신경을 써야 준수하게 되는 원칙인 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;물론,&amp;nbsp;서비스단에서 보기에 너무 소스가 흩뿌려진다고 할 수 있지만,&amp;nbsp;유지보수를 하거나 기획이 변경되었을 때 변경된 객체만 건드리면 되니 단일 책임 원칙을 준수하며 코딩하는 습관을 기르는 것이 좋다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>개발 고민</category>
      <category>SOLID</category>
      <category>spring boot</category>
      <category>SRP</category>
      <category>단일 책임 원칙</category>
      <author>dev.Dove</author>
      <guid isPermaLink="true">https://dpot.tistory.com/4</guid>
      <comments>https://dpot.tistory.com/4#entry4comment</comments>
      <pubDate>Wed, 9 Aug 2023 19:37:55 +0900</pubDate>
    </item>
    <item>
      <title>Linode Objects Storage 구성 및 Spring Cloud aws와 연동</title>
      <link>https://dpot.tistory.com/3</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1446&quot; data-origin-height=&quot;650&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eyyAkg/btsngukYNPa/nKVKqDbEaKrqAi14c90zA0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eyyAkg/btsngukYNPa/nKVKqDbEaKrqAi14c90zA0/img.png&quot; data-alt=&quot;출처:&amp;amp;amp;nbsp;https://www.linode.com/products/object-storage/&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eyyAkg/btsngukYNPa/nKVKqDbEaKrqAi14c90zA0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeyyAkg%2FbtsngukYNPa%2FnKVKqDbEaKrqAi14c90zA0%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;1446&quot; height=&quot;650&quot; data-origin-width=&quot;1446&quot; data-origin-height=&quot;650&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처:&amp;amp;nbsp;https://www.linode.com/products/object-storage/&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Akamai사에서 Linode를 인수하며, Akamai에서 AWS S3와 같은 Object Storage를 서비스하고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Naver Cloud도 S3와 호환되는 저장소를 제공하고 Linode도 S3와 호환되는 Object Storage서비스를 제공한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;S3와 호환되는 저장소라면, AWS SDK로 연결이 가능할 터, 연결해 보자..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. Linode Object 만들어보자&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. AWS, GCP, NCP 모두 비슷한 구조를 가진 듯하다. Linode도 버킷이라는 명칭을 사용하며 생성할 수 있는 버튼이 존재하니 누르자.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1654&quot; data-origin-height=&quot;959&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bMyBkf/btsnjb5xhQQ/58E2PXETX6XAZf22a90TKK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bMyBkf/btsnjb5xhQQ/58E2PXETX6XAZf22a90TKK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bMyBkf/btsnjb5xhQQ/58E2PXETX6XAZf22a90TKK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbMyBkf%2Fbtsnjb5xhQQ%2F58E2PXETX6XAZf22a90TKK%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;615&quot; height=&quot;357&quot; data-origin-width=&quot;1654&quot; data-origin-height=&quot;959&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;2. 버킷의 명칭을 label에 적고, 리전을 골라주면 된다. 2023년 7월 기준 4개 중에서 선택가능하다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1918&quot; data-origin-height=&quot;966&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yttaL/btsng9Hoeir/NcqDjIsT1qlFGZjspGpi9k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yttaL/btsng9Hoeir/NcqDjIsT1qlFGZjspGpi9k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yttaL/btsng9Hoeir/NcqDjIsT1qlFGZjspGpi9k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FyttaL%2Fbtsng9Hoeir%2FNcqDjIsT1qlFGZjspGpi9k%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;662&quot; height=&quot;333&quot; data-origin-width=&quot;1918&quot; data-origin-height=&quot;966&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;3. 버킷을 만드려 하니, 안내문구가 나온다. 요금에 대한 설명이다. aws s3와는 다르게 1TB까지 네트워크비용이 기본요금에 포함되어 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;696&quot; data-origin-height=&quot;333&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bgueEW/btsnitrR49q/t9U4C5bbKBw52RDzX4ZRXk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bgueEW/btsnitrR49q/t9U4C5bbKBw52RDzX4ZRXk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bgueEW/btsnitrR49q/t9U4C5bbKBw52RDzX4ZRXk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbgueEW%2FbtsnitrR49q%2Ft9U4C5bbKBw52RDzX4ZRXk%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;537&quot; height=&quot;257&quot; data-origin-width=&quot;696&quot; data-origin-height=&quot;333&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;4. 버킷에 접글할 때 필요한 액세스키와 시크릿 키를 만들자.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1326&quot; data-origin-height=&quot;529&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/4KRwJ/btsnja6BvC3/JdPJBZpKKwStk6nmUNOKi0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/4KRwJ/btsnja6BvC3/JdPJBZpKKwStk6nmUNOKi0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/4KRwJ/btsnja6BvC3/JdPJBZpKKwStk6nmUNOKi0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F4KRwJ%2Fbtsnja6BvC3%2FJdPJBZpKKwStk6nmUNOKi0%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;1326&quot; height=&quot;529&quot; data-origin-width=&quot;1326&quot; data-origin-height=&quot;529&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;5. Create Access Key를 누르면 key를 만들어서 보여준다. 따로 잘 저장해 두자.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;692&quot; data-origin-height=&quot;491&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cUHxhx/btsoKYrEPt7/8ltcKQ8QtjOO9n1vb296p0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cUHxhx/btsoKYrEPt7/8ltcKQ8QtjOO9n1vb296p0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cUHxhx/btsoKYrEPt7/8ltcKQ8QtjOO9n1vb296p0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcUHxhx%2FbtsoKYrEPt7%2F8ltcKQ8QtjOO9n1vb296p0%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;520&quot; height=&quot;369&quot; data-origin-width=&quot;692&quot; data-origin-height=&quot;491&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. Spring Cloud AWS와 연결&lt;/h2&gt;
&lt;figure id=&quot;og_1689086666708&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Spring Cloud for Amazon Web Services&quot; data-og-description=&quot;Spring Cloud for Amazon Web Services is a community-run project. The website is https://awspring.io/ and the source repository is located at https://github.com/awspring/spring-cloud-aws. Spring Cloud for Amazon Web Services, eases the integration with host&quot; data-og-host=&quot;spring.io&quot; data-og-source-url=&quot;https://spring.io/projects/spring-cloud-aws&quot; data-og-url=&quot;https://spring.io/projects/spring-cloud-aws&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/b2VLiF/hyTioldcBq/70xpvaLxZQzH6HMVRc2HU0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/dRVH7N/hyTgTG7YXW/6K6D4nHKAm84Z6ff7eogDk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://spring.io/projects/spring-cloud-aws&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://spring.io/projects/spring-cloud-aws&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/b2VLiF/hyTioldcBq/70xpvaLxZQzH6HMVRc2HU0/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/dRVH7N/hyTgTG7YXW/6K6D4nHKAm84Z6ff7eogDk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Spring Cloud for Amazon Web Services&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Spring Cloud for Amazon Web Services is a community-run project. The website is https://awspring.io/ and the source repository is located at https://github.com/awspring/spring-cloud-aws. Spring Cloud for Amazon Web Services, eases the integration with host&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;spring.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저, 본 글에서 사용하는 spring cloud aws는 amazon sdk를 이용해 spring 환경에서 편하게 사용할 수 있게 도와주는 프로젝트다.&amp;nbsp;AWS의 crendential을 yml설정을 통해 자동으로 bean설정을 도와준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단, 해당 프로젝트는 &lt;b&gt;community-run project&lt;/b&gt;라고 spring 공식홈페이지에서 공지한다. 3 버전부터는 aws 내 일부 서비스만 사용가능한 점이 아쉬운 점으로 꼽힌다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;aws sdk로 linode obect storage연결은 너무 쉽다. s3연결 생성 시, endpoint만 linode로 변경하면 끝나니, 본글에서는 spring cloud aws기반으로 연결해보려 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추가로 본문에서의 예시는 spring boot 2.7.12(java 17), gradle 7.6.1을 기반으로 한 코드임을 알린다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. spring cloud aws를 추가한다.&lt;/p&gt;
&lt;div style=&quot;background-color: #2b2b2b; color: #a9b7c6;&quot;&gt;
&lt;pre class=&quot;clean&quot;&gt;&lt;code&gt;implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE'&lt;/code&gt;&lt;/pre&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;2. application.yml을 세팅한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 예제는 EC2가 아닌 환경에서 구동할 예정임으로 cloud.aws.stack.auto는 false처리하여 자동으로 spring cloud aws 가 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;AWS CloudFormation를 세팅하는 것을 막는다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;- cloud.aws.region.static은 없을 경우 spring cloud aws가 에러를 유발하기에 linode에서 사용할 기본 리전으로 세팅한다.&lt;/span&gt;&lt;/p&gt;
&lt;div style=&quot;background-color: #2b2b2b; color: #a9b7c6;&quot;&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;cloud:
  aws:
    stack:
      auto: false
    region:
      static: {리전코드}
  linode:
    bucket: {버킷명}
    region: {리전코드}
    credential:
      accessKey: {accessKey}
      secretKey: {secretKey}&lt;/code&gt;&lt;/pre&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;3. yml에 추가한 설정값을 Java class에 바인딩한다.&lt;/p&gt;
&lt;div style=&quot;background-color: #2b2b2b; color: #a9b7c6;&quot;&gt;
&lt;pre class=&quot;less&quot;&gt;&lt;code&gt;@Getter
@Setter
@Component
@ConfigurationProperties(prefix = &quot;cloud.linode&quot;)
public class LinodeProperties {
    private String bucket;
    private String region;
    private Credentials credentials;
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div style=&quot;background-color: #2b2b2b; color: #a9b7c6;&quot;&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;public record Credentials(
        String accessKey,
        String secretKey
) {
}
&lt;/code&gt;&lt;/pre&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;4. 바인딩 한 설정값으로 AmazonS3 Bean을 재 정의한다.&lt;/p&gt;
&lt;div style=&quot;background-color: #2b2b2b; color: #a9b7c6;&quot;&gt;
&lt;pre class=&quot;java&quot;&gt;&lt;code&gt;@Configuration
@RequiredArgsConstructor
public class LinodeConfig {
    private final LinodeProperties linodeProperties;

    @Bean
    public AmazonS3 amazonS3() {
        AWSCredentials credentials = new BasicAWSCredentials(
                linodeProperties.getCredentials().accessKey(),
                linodeProperties.getCredentials().secretKey()
        );

        return AmazonS3ClientBuilder.standard()
                .withEndpointConfiguration(new AwsClientBuilder.EndpointConfiguration(&quot;https://ap-south-1.linodeobjects.com&quot;, linodeProperties.getRegion()))
                .withCredentials(new AWSStaticCredentialsProvider(credentials))
                .build();
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. 원하는 곳에서 AmazonS3을 주입받아서 사용한다.&lt;/p&gt;
&lt;div style=&quot;background-color: #2b2b2b; color: #a9b7c6;&quot;&gt;
&lt;pre class=&quot;less&quot;&gt;&lt;code&gt;@Slf4j
@Component
@RequiredArgsConstructor
public class AwsS3 {
    private final AmazonS3 amazonS3;

    /**
     * 단일 파일을 가져온다.
     *
     * @param key
     * @return
     */
    public S3Object getObject(String bucket, String key) {
        return amazonS3.getObject(bucket, key);
    }

}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;3. 마치며..&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AWS와 호환되는 클라우드 환경이면 AWS SDK로 편하게 사용할 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AWS SDK기반으로 개발하면, 어떤 클라우드 환경의 버킷도 대응할 수 있다.&lt;/p&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;s&gt;AWS SDK가 만능인 건가...&lt;/s&gt;&lt;/p&gt;</description>
      <category>인프라</category>
      <category>Linode</category>
      <category>linode object storage</category>
      <category>spring cloud aws</category>
      <author>dev.Dove</author>
      <guid isPermaLink="true">https://dpot.tistory.com/3</guid>
      <comments>https://dpot.tistory.com/3#entry3comment</comments>
      <pubDate>Wed, 12 Jul 2023 00:14:01 +0900</pubDate>
    </item>
    <item>
      <title>MultipartFile 업로드에 관하여</title>
      <link>https://dpot.tistory.com/2</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;어디에서든지 파일을 다루는 시스템을 설계하고 구현할 일이 생긴다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;도메인은 다르고 파일의 형태는 다르지만, 뭔가 항상 다루는 MultipartFile.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한번 구현해 보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;설계&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필요한 기능은 다음과 같다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;단일 파일 업로드&lt;/li&gt;
&lt;li&gt;업로드한 전체 파일 조회&lt;/li&gt;
&lt;li&gt;업로드한 파일 제거&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 구현에서 고려하지 않을 기능은 다음과 같다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;DB&lt;/li&gt;
&lt;li&gt;다중 파일 업로드&lt;/li&gt;
&lt;li&gt;API controller&lt;/li&gt;
&lt;/ol&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;단순 업로드 구현&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;pre id=&quot;code_1685459327574&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Slf4j
@Service
public class FileService {
    @Value(&quot;${file.upload-path}&quot;)
    private String uploadDirectory;

    public boolean saveFile(MultipartFile multipartFile) {
        //파일이 없으면 별도의 처리를 한다.
        if (multipartFile == null || multipartFile.isEmpty()) {
            return false;
        }

        String fileName = multipartFile.getOriginalFilename();
        File targetFile = new File(uploadDirectory, fileName);
        try{
            FileCopyUtils.copy(multipartFile.getInputStream(), new FileOutputStream(targetFile));

            //저장을 완료하면, multipartFile로 만든 파일은 제거한다.
            targetFile.delete();
        }catch (IOException ioException){
            //파일 저장 실패시 에러 핸들링.
            log.error(ioException.toString(),ioException);
            return false;
        }
        
        return true;

    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f8f8f8; color: #333333; text-align: start;&quot;&gt;MultipartFile를 받아서 파일로 원하는 위치에 저장한다.&amp;nbsp;&lt;br /&gt;파라미터로 받은 &lt;span style=&quot;background-color: #f8f8f8; color: #333333; text-align: start;&quot;&gt;MultipartFile를 File객체로 변환하며, 원하는 위치에 &lt;span style=&quot;background-color: #f8f8f8; color: #333333; text-align: start;&quot;&gt;실제 파일이 만들어진다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;허나.. 용량이 좀 큰 파일을 업로드하면, FileSizeLimitExceededException 에러를 만난다..&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해결해 보자&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;큰 용량을 업로드해 보자&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결론부터 말하면, Spring Boot에 있는 내장 톰캣에서 업로드 용량에 제한을 걸어서 나오는 에러다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1019&quot; data-origin-height=&quot;537&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lHqJD/btsibflH91l/3fkPKa0bq7fVP1nIdaDgW1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lHqJD/btsibflH91l/3fkPKa0bq7fVP1nIdaDgW1/img.png&quot; data-alt=&quot;mulipart 설정을 세팅하는 로직&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lHqJD/btsibflH91l/3fkPKa0bq7fVP1nIdaDgW1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlHqJD%2FbtsibflH91l%2F3fkPKa0bq7fVP1nIdaDgW1%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;603&quot; height=&quot;318&quot; data-origin-width=&quot;1019&quot; data-origin-height=&quot;537&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;mulipart 설정을 세팅하는 로직&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;YAML 또는 properties를 통한 mulipart설정이 없다면, connector에서 값을 가져와 세팅한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;648&quot; data-origin-height=&quot;84&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ILBa7/btsielFemH1/aIklwoiUS0ksTBpPkiN1z1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ILBa7/btsielFemH1/aIklwoiUS0ksTBpPkiN1z1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ILBa7/btsielFemH1/aIklwoiUS0ksTBpPkiN1z1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FILBa7%2FbtsielFemH1%2FaIklwoiUS0ksTBpPkiN1z1%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;648&quot; height=&quot;84&quot; data-origin-width=&quot;648&quot; data-origin-height=&quot;84&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;connector를 보니, Spring Boot 2.7.12(Java 17) 기준 2MB다.&lt;/p&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;background-color: #f8f8f8; color: #333333; text-align: start;&quot;&gt;YAML 또는 properties를 통해 업로드 제한을 변경해 보자!&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;280&quot; data-origin-height=&quot;134&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bKpKyv/btsiaFyfiNh/roXlpdEuqqWDFcZojjAQR0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bKpKyv/btsiaFyfiNh/roXlpdEuqqWDFcZojjAQR0/img.png&quot; data-alt=&quot;Spring Boot 2.7 기준 설정&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bKpKyv/btsiaFyfiNh/roXlpdEuqqWDFcZojjAQR0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbKpKyv%2FbtsiaFyfiNh%2FroXlpdEuqqWDFcZojjAQR0%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;280&quot; height=&quot;134&quot; data-origin-width=&quot;280&quot; data-origin-height=&quot;134&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Spring Boot 2.7 기준 설정&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;application.yml에 설정을 추가하면 보다 큰 용량도 업로드 가능하다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;444&quot; data-origin-height=&quot;103&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bh4NOH/btsicOOFoI5/xHsKn7M701FlQnjfaSK0b1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bh4NOH/btsicOOFoI5/xHsKn7M701FlQnjfaSK0b1/img.png&quot; data-alt=&quot;출처:&amp;amp;amp;nbsp;https://docs.spring.io/spring-boot/docs/2.7.x/api/org/springframework/boot/web/servlet/MultipartConfigFactory.html&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bh4NOH/btsicOOFoI5/xHsKn7M701FlQnjfaSK0b1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbh4NOH%2FbtsicOOFoI5%2FxHsKn7M701FlQnjfaSK0b1%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;444&quot; height=&quot;103&quot; data-origin-width=&quot;444&quot; data-origin-height=&quot;103&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처:&amp;amp;nbsp;https://docs.spring.io/spring-boot/docs/2.7.x/api/org/springframework/boot/web/servlet/MultipartConfigFactory.html&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;공식 문서를 보면 max-file-size는 MultipartFile 1개의 최대 업로드 사이즈, max-request-sizes는 multipart/form-data한 개의&amp;nbsp;요청의&amp;nbsp;최대&amp;nbsp;업로드&amp;nbsp;사이즈&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;만일.. 파일이 5GB, 10GB처럼 크면 어떻게 될까..?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f8f8f8; color: #333333; text-align: left;&quot;&gt;MultipartFile이 커지면 힙메모리에 부하가 갈 것이다. 메모리 부족현상은 당연히 발생할 것이다.&lt;/span&gt;&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;분할 업로드 구현&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하나의 파일을 분할해서 업로드하면, 서버의 트래픽은 증가하지만, 각 요청의 응답 속도는 빨라진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추후 서버를 증설하면 증가된 서버 트래픽도 해결된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;분할 업로드를 직접 IDC에 업로드하는 방법보다는 AWS S3를 이용해서 간단하게 구현해 보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AWS S3에서도 큰 파일을 업로드할 때 파일을 분할해서 업로드할 수 있게 SDK를 제공한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AWS S3의 분할 파일 업로드 프로세스는 다음과 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;분할 파일을 업로드한다고 S3에게 알려준다.&lt;/li&gt;
&lt;li&gt;분할 파일을 업로드한다.&lt;/li&gt;
&lt;li&gt;분할 파일을 다 업로드했다고 S3에게 알려준다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1번 과정에서 S3는 id를 제공한다. id를 이용해서 분할파일을 업로드하고 3번 과정을 통해 S3는 분할 파일을 합쳐서 하나의 온전한 파일로 만든다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 간단하게 구현하면 다음과 같다.&lt;/p&gt;
&lt;pre id=&quot;code_1686235775377&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Service
@RequiredArgsConstructor
public class ChunkedFileService {
    private final AmazonS3Client amazonS3Client;

    public InitiateMultipartUploadResult initiateUploadChunkedFile() {
        //S3 분할 파일 업로드 init
        InitiateMultipartUploadResult initiateMultipartUploadResult = amazonS3Client.initiateMultipartUpload(
                new InitiateMultipartUploadRequest(&quot;버킷 명&quot;, &quot;업로드 위치&quot;));

        //필요할 경우 DB에 분할 파일 업로드 정보 저장.

        return initiateMultipartUploadResult;
    }


    /**
     * 분할 파일을 업로드한다.
     *
     */
    public UploadPartResult uploadChunkedFile(String uploadId, Integer chunkSeq, MultipartFile multipartFile) throws IOException {
        ObjectMetadata objectMetadata = new ObjectMetadata();
        objectMetadata.setContentType(multipartFile.getContentType());
        objectMetadata.setContentLength(multipartFile.getSize());

        UploadPartRequest uploadPartRequest = new UploadPartRequest()
                .withBucketName(&quot;버킷 명&quot;)
                .withKey(&quot;업로드 위치&quot;)
                .withUploadId(uploadId)//initiateMultipartUpload를 통해 받은 id
                .withPartNumber(chunkSeq) // 순차적인 part number (1~10,000)
                .withInputStream(multipartFile.getInputStream())
                .withObjectMetadata(objectMetadata)
                .withPartSize(multipartFile.getSize()); // chunk file size

        return amazonS3Client.uploadPart(uploadPartRequest);
    }

    /**
     * 업로드 한 분할 파일을 하나의 파일로 합친다.
     */
    public CompleteMultipartUploadResult mergeChunkedFile(String uploadId, List&amp;lt;PartETag&amp;gt; eTagList) {
        CompleteMultipartUploadRequest completeRequest = new CompleteMultipartUploadRequest(
                &quot;버킷 명&quot;,
                &quot;업로드 위치&quot;,
                uploadId,
                eTagList);//분할 파일을 업로드 하는 과정에서 받은 eTag들의 list

        return amazonS3Client.completeMultipartUpload(completeRequest);
    }
}&lt;/code&gt;&lt;/pre&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;마무리&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대용량의 파일을 업로드할 때, S3를 이용하면, upload id, etag 등 다양한 값을 사용하게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클라이언트에게 &lt;span style=&quot;background-color: #f8f8f8; color: #333333; text-align: start;&quot;&gt;upload id, etag 등 필요한 값을 주는 방법도 있고 원한다면 서버가 DB에 &lt;span style=&quot;background-color: #f8f8f8; color: #333333; text-align: start;&quot;&gt;upload id, etag를 저장하고 관리하는 방법도 고려할 수 있다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;</description>
      <category>개발 고민</category>
      <category>mulipartfile</category>
      <category>spring</category>
      <author>dev.Dove</author>
      <guid isPermaLink="true">https://dpot.tistory.com/2</guid>
      <comments>https://dpot.tistory.com/2#entry2comment</comments>
      <pubDate>Tue, 30 May 2023 23:07:25 +0900</pubDate>
    </item>
  </channel>
</rss>