<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>Just do debug</title>
    <link>https://kbcoding.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Sun, 12 Apr 2026 05:08:53 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>큐범</managingEditor>
    <image>
      <title>Just do debug</title>
      <url>https://tistory1.daumcdn.net/tistory/4696741/attach/c19e5accda41461abc25a5eed6e95983</url>
      <link>https://kbcoding.tistory.com</link>
    </image>
    <item>
      <title>서킷브레이커 정리 및 resilience4j 적용기</title>
      <link>https://kbcoding.tistory.com/137</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;resilience4j&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MSA 환경에서 서킷브레이커, 유량제어는 매우 중요한 개념으로 보다 더 안전한 서비스 운영을 위해 사용되는 개념이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서비스가 확장되면서 같은 팀 내에서 분리된 서비스가 한 쪽으로 의존(트래픽)을 하면서 A의 서버가 B의 API를 비동기로 호출하면서 데이터를 가져오는 상황이 발생한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;A의 서버를 개발하는 나는 몇 가지 상황을 대비해야한다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;B의 서버가 죽어있다면?&lt;/li&gt;
&lt;li&gt;B의 서버가 CPU 자원 부족으로 죽기 직전이라면?&lt;/li&gt;
&lt;li&gt;B의 서버가 순간적인 에러를 뱉는다면?&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 A서버는 B의 서버가 회복할 수 있도록 기다려줌과 동시에 장애가 전파되지 않도록 막아야한다. 여기서 내가 가져올 수 있는 것은 서킷브레이커이다.&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;150&quot; data-origin-height=&quot;186&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b2OLXM/btsIUB4RIIj/esgmOcAiYbUzfIFngUZUsk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b2OLXM/btsIUB4RIIj/esgmOcAiYbUzfIFngUZUsk/img.png&quot; data-alt=&quot;서킷브레이커&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b2OLXM/btsIUB4RIIj/esgmOcAiYbUzfIFngUZUsk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb2OLXM%2FbtsIUB4RIIj%2FesgmOcAiYbUzfIFngUZUsk%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;150&quot; height=&quot;186&quot; data-origin-width=&quot;150&quot; data-origin-height=&quot;186&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;집에서 사용하는 두꺼비집이라 불리는 누전차단기, 회로차단기가 서킷브레이커이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발자들 세계에서 사용하는 서킷브레이커는 각각의 시스템간 장애가 전파되지 않도록 차단을 목적으로 두는 것을 말한다. 서킷브레이커는 상태에 따라서 서로 다른 동작을 한다.&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;426&quot; data-origin-height=&quot;164&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zeQDV/btsIUzlBaBV/QyFfyiKE2oFcgocQ83e7Tk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zeQDV/btsIUzlBaBV/QyFfyiKE2oFcgocQ83e7Tk/img.png&quot; data-alt=&quot;서킷브레이커 상태&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zeQDV/btsIUzlBaBV/QyFfyiKE2oFcgocQ83e7Tk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzeQDV%2FbtsIUzlBaBV%2FQyFfyiKE2oFcgocQ83e7Tk%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;426&quot; height=&quot;164&quot; data-origin-width=&quot;426&quot; data-origin-height=&quot;164&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;&lt;br /&gt;서킷브레이커의 상태는 보통상태와 특별한 생태가 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보통상태에서 3개로 분류가 된다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;CLOSED: 정상적으로 호출되고 응답을 주는 상태로 실패율이나 느린 호출 비율이 임계값을 넘지 않은 경우이다.&lt;/li&gt;
&lt;li&gt;OPEN: 문제 발생이 감지된 상태, 일정 기간동안 너무 많은 요청이 실패했거나 너무 느리게 응답하는 경우 서킷 브레이커가 열려 더이상 요청을 막은 상태이다.&lt;/li&gt;
&lt;li&gt;HALF_OPEN: 문제 발생이 감지된 상태, 서킷 브레이커가 일정 시간이 지난 후 다시 닫힐지 열릴지 결정하기 위해 일부 요청을 허용 하는 상태&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특별한 상태는 2개로 분류된다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;DISABLED: 항상 호출을 허용하는 상태&lt;/li&gt;
&lt;li&gt;FORCE_OPEN: 항상 호출을 거부하는 상태&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서킷 브레이커는 슬라이딩 윈도우(Sliding Window)를 사용하여 상태의 변화여부를 결정한다. 슬라이딩 윈도우는 횟수 방식(COUNT-BASED)과 시간 방식(TIME_BASED)가 있는데 방식에 따라 슬라이딩 윈도우 안에서 정해진 확률보다 높은 확률로 호출에 실패하게 되면 상태를 OPEN으로 변경한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OPEN 상태에서는 연동된 시스템 호출을 시도하지 않으며, 바로 호출 실패 Exception이 발생하여 정해진 Fallback동작을 수행한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OPEN 이후 설정한 시간이 지나면 HALF_OPEN 상태로 변경되며 호출이 정상화되었는지 다시한번 실패 확률로 확인한다. 정상화되었다고 판되면 CLOSED 상태로 변경되지만 아직 정상화되지 못했다고 판단되면 다시 OPEN 상태로 되돌아간다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;서킷브레이커 라이브러리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서킷 브레이커를 처리할 수 있게 도와주는 라이브러리는 대표적으로 4개가 있다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Resilience4J&lt;/li&gt;
&lt;li&gt;Spring Cloud Circuit Breaker&lt;/li&gt;
&lt;li&gt;Hystrix&lt;/li&gt;
&lt;li&gt;Sentinel&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 중 최근에도 커밋이 찍혀있으며 활발하게 오픈소스로 개발이 이루어지는 것은 Resilience4J이다. 따라서, Resilience4J를 선택하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/resilience4j/resilience4j&quot;&gt;https://github.com/resilience4j/resilience4j&lt;/a&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Resilience4J란?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Resilience는 회복 탄력성이다. 4는 For J는 Java&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Resilience For Java 즉, 회복 탄력성을 자바를 위해 만들어진 라이브러리이다. 우리는 여기서 회복 탄력성에 집중해야한다. 시스템은 나날이 복잡해져 가면서 고객들에게 고가용성을 유지해야하고 장애는 전파가 되지 않도록 해야한다. 그렇다면 의존성이 있는 시스템끼리는 서로 장애가 일어나지 않도록 연산작업(트래픽)에 대해서 보낼지 말지를 결정하여 트래픽을 받는 시스템에서 자원이 부족한 상황에서 다운이 되는 상황이 발생하지 않도록 막아야한다. 여기서 다시 회복을 할 수 있도록 하는 것이 회복탄력성이다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Resilience4J 적용하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Getting Started를 확인하여 적용하기 (Java 17 이상을 요구한다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://resilience4j.readme.io/docs/getting-started&quot;&gt;https://resilience4j.readme.io/docs/getting-started&lt;/a&gt;&lt;/p&gt;
&lt;pre class=&quot;clean&quot;&gt;&lt;code&gt;    //Resilience4J
    implementation(&quot;io.github.resilience4j:resilience4j-spring-boot3:2.2.0&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;config는 boot의 application.yml 혹은 application.properties를 통해 스프링 빈에 설정 값을 주입할 수 있다.&lt;/p&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;resilience4j:
  circuitbreaker:
    configs:
      default:
        registerHealthIndicator: true
        slidingWindowType: COUNT_BASED
        slidingWindowSize: 10
        minimumNumberOfCalls: 5
        slowCallRateThreshold: 100
        slowCallDurationThreshold: 60000
        failureRateThreshold: 60
        permittedNumberOfCallsInHalfOpenState: 3
        waitDurationInOpenState: 60s
        automatic-transition-from-open-to-half-open-enabled: true
    instances:
      circuit-sample-common: # circuitbreaker name
        baseConfig: default # 기본 config 지정
      circuit-sample-3000:
        baseConfig: default
        slowCallDurationThreshold: 3000 # 응답시간이 느린것으로 판단할 기준 시간 [ms]&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;SlidingWindowType&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SlidingWindowType에 COUNT_BASED, TIME_BASED가 있다. 공식문서에 의하면 둘의 시간 복잡도는 O(1)이고 공간 복잡도는 O(WindowSize)이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;COUNT_BASED: 마지막 슬라이딩 WindowSize 호출이 기록되고 집계된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TIME_BASED: 마지막 슬라이딩 WindowSize 초의 호출이 기록되고 집계된다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;slidingWindowSize&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서킷의 상태가 CLOSED일 때 요청의 결과를 기록하기 위한 슬라이딩 윈도우의 크기&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;minimumNumberOfCalls&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서킷이 실패율 또는 지연된 응답을 계산하기 전 요구되는 최소 요청의 수, 예시에서는 최소 5개의 요청이 있어야 서킷이 계산을 한다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;slowCallRateThreshold&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지연된 응답 Threadhold 퍼센트 값으로 느린 호출의 백분율이 임계값과 같거나 크면 CircuitBreaker가 개방으로 전환되고 단락 호출이 시작된다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;slowCallDurationThreshold&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요청이 느린 것으로 간주되는 기간&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;failureRateThreshold&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실패율 Threadhold 퍼센트 값으로 실패율 임계값보다 크거나 같으면 CircuitReaker가 개방으로 전환하고 단락 호출을 시작한다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;permittedNumberOfCallsInHalfOpenState&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서킷이 HALF_OPEN상태일 때 허용되는 호출수를 의미한다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;waitDurationInOpenState&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서킷의 상태가 OPEN에서 HALF_OPEN으로 변경되기 전에 Circuit Break가 기다리는 시간이다. 예시에서는 20초 이후에 변경된다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;automatic-transition-from-open-to-half-open-enabled&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;true/false로 Wait Duration In Open State기간이 지난 이후에 Open에서 Half-Open으로 자동으로 상태가 변경된다. 하나의 쓰레드가 CircuitBreaker의 모든 인스턴스들을 모니터링하며 상태를 확인한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Resilience4J 상황 시연&lt;/h3&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;@Slf4j
@Service
public class AService {

    @CircuitBreaker(name = &quot;circuit-sample-common&quot;, fallbackMethod = &quot;fallback2&quot;)
    public String callOutService() {
        throw new RuntimeException(&quot;에러발생!&quot;);
    }

    private String fallback2(CallNotPermittedException e) {
        log.error(&quot;Circuit breaker is open {}&quot;, e.getMessage());
        return &quot;fallback&quot;;
    }

}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OUTPUT&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;2024-08-02T13:56:42.277+09:00 ERROR 84435 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: java.lang.RuntimeException: 에러발생!] with root cause
java.lang.RuntimeException: 에러발생!
2024-08-02T13:56:43.324+09:00 ERROR 84435 --- [nio-8080-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: java.lang.RuntimeException: 에러발생!] with root cause
java.lang.RuntimeException: 에러발생!
2024-08-02T13:56:44.361+09:00 ERROR 84435 --- [nio-8080-exec-3] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: java.lang.RuntimeException: 에러발생!] with root cause
java.lang.RuntimeException: 에러발생!
2024-08-02T13:56:45.406+09:00 ERROR 84435 --- [nio-8080-exec-4] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: java.lang.RuntimeException: 에러발생!] with root cause
java.lang.RuntimeException: 에러발생!
2024-08-02T13:56:46.455+09:00 ERROR 84435 --- [nio-8080-exec-5] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: java.lang.RuntimeException: 에러발생!] with root cause
java.lang.RuntimeException: 에러발생!

2024-08-02T13:56:47.493+09:00 ERROR 84435 --- [nio-8080-exec-6] com.example.resilience.a.AService        : Circuit breaker is open CircuitBreaker 'circuit-sample-common' is OPEN and does not permit further calls&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설정해둔 임계치인 5회를 넘기자 그대로 fallbackMethod를 실행하고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 설정에서는 최소 5개의 호출이 발생하고 그 중 3개(60%)가 실패할 경우 서킷이 OPEN 상태로 변경된다. 서킷이 열리면 설정된 시간(60초) 동안 새로운 호출을 차단한다. 이후 서킷은 Half-Open 상태로 전환되고 일부 호출을 허용하여 시스템의 상태를 확인한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;주의 Catch한 에러는 CircuitBreaker에 포함되지 않는다.&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CircuitBreaker를 적용한 분들은 짐작을 하였겠지만, CircuitBreaker의 내부는 AOP를 통해 구현되어 있습니다. 따라서, 해당 메서드에서 발생하는 catch가 이루어질 경우, CircuitBreaker는 포함되지 않습니다.&lt;/p&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;    @CircuitBreaker(name = &quot;circuit-sample-common&quot;, fallbackMethod = &quot;fallback2&quot;)
    public String callOutService() {
        try {
            throw new RuntimeException(&quot;에러발생!&quot;);
        }catch (Exception e) {
            log.error(&quot;에러발생: {}&quot;, e.getMessage());
            return &quot;catch error&quot;;
        }
    }
&lt;/code&gt;&lt;/pre&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://resilience4j.readme.io/docs/micrometer&quot;&gt;https://resilience4j.readme.io/docs/micrometer&lt;/a&gt; 매트릭 정보는 해당 사이트에서 확인 가능하다. (본 글은 Spring Actuator를 통해 확인)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://resilience4j.readme.io/docs/grafana-1&quot;&gt;https://resilience4j.readme.io/docs/grafana-1&lt;/a&gt; 해당 사이트가서 확인을 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;grafana JSON 파일 링크 &lt;a href=&quot;https://resilience4j.readme.io/docs/grafana-1&quot;&gt;https://resilience4j.readme.io/docs/grafana-1&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;1802&quot; data-origin-height=&quot;1224&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oB7V1/btsIUgmpXwd/kCOMEOq2cnSLPkgg4WCKd1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oB7V1/btsIUgmpXwd/kCOMEOq2cnSLPkgg4WCKd1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oB7V1/btsIUgmpXwd/kCOMEOq2cnSLPkgg4WCKd1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoB7V1%2FbtsIUgmpXwd%2FkCOMEOq2cnSLPkgg4WCKd1%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;1224&quot; data-origin-width=&quot;1802&quot; data-origin-height=&quot;1224&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서킷브레이커가 작동하는 일이 없도록....&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Reference.&lt;/p&gt;
&lt;figure id=&quot;og_1722924388563&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;CircuitBreaker&quot; data-og-description=&quot;Getting started with resilience4j-circuitbreaker&quot; data-og-host=&quot;resilience4j.readme.io&quot; data-og-source-url=&quot;https://resilience4j.readme.io/docs/circuitbreaker&quot; data-og-url=&quot;https://resilience4j.readme.io/docs/circuitbreaker&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/re1HR/hyWKFErTUN/oLlRqlxjBa5R3qu0WZx3U1/img.png?width=607&amp;amp;height=874&amp;amp;face=0_0_607_874,https://scrap.kakaocdn.net/dn/bp2KUJ/hyWKz5h7Dp/XNPjFP1Et9mI3KVq0z6wk1/img.png?width=616&amp;amp;height=842&amp;amp;face=0_0_616_842&quot;&gt;&lt;a href=&quot;https://resilience4j.readme.io/docs/circuitbreaker&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://resilience4j.readme.io/docs/circuitbreaker&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/re1HR/hyWKFErTUN/oLlRqlxjBa5R3qu0WZx3U1/img.png?width=607&amp;amp;height=874&amp;amp;face=0_0_607_874,https://scrap.kakaocdn.net/dn/bp2KUJ/hyWKz5h7Dp/XNPjFP1Et9mI3KVq0z6wk1/img.png?width=616&amp;amp;height=842&amp;amp;face=0_0_616_842');&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;CircuitBreaker&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Getting started with resilience4j-circuitbreaker&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;resilience4j.readme.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>Spring</category>
      <category>Circuitbreaker</category>
      <category>서킷브레이커</category>
      <author>큐범</author>
      <guid isPermaLink="true">https://kbcoding.tistory.com/137</guid>
      <comments>https://kbcoding.tistory.com/137#entry137comment</comments>
      <pubDate>Tue, 6 Aug 2024 15:07:00 +0900</pubDate>
    </item>
    <item>
      <title>[Java] 릴리즈 버전별 특징</title>
      <link>https://kbcoding.tistory.com/135</link>
      <description>&lt;h2&gt;Java 8 LTS (2014.03)&lt;/h2&gt;
&lt;p&gt;지원 기간 : 2030.12&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;람다 표현식 (Lambda Expressions)&lt;/li&gt;
&lt;li&gt;스트림 API (Streams API)&lt;/li&gt;
&lt;li&gt;새로운 날짜와 시간 API (java.time)&lt;ul&gt;
&lt;li&gt;Ex) LocalDateTime&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;인터페이스의 디폴트 메서드 (Default Methods)&lt;/li&gt;
&lt;li&gt;메타공간 (Metaspace) 메모리 관리&lt;ul&gt;
&lt;li&gt;Permanent Heap 영역이 제거 - Perm은 JVM에 의해 크기가 강제되던 영역&lt;/li&gt;
&lt;li&gt;Metaspace영역은 OS레벨에서 관리하는 영역이 되기에 Metaspace가 Native메모리를 이용함으로서 개발자는 영역 확보의 상한에 대한 오버헤드가 감소한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Java 9 (2017.09)&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;모듈 시스템 (Project Jigsaw)&lt;ul&gt;
&lt;li&gt;Jigsaw는 모듈을 만들고 모듈에 명시적으로 외부에서 호출할 수 있는 API를 선언한다. 언어 레벨에서 API 작성자가 외부에 노출한 API 외에는 접근할 수 없도록 설계 되어 있고 사용할 다른 모듈을 사용하는 경우는 선언적으로 사용한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;JShell (REPL)&lt;/li&gt;
&lt;li&gt;HTTP/2 클라이언트 API&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Java 10 (2018.03)&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;지역 변수 타입 추론 (var)&lt;/li&gt;
&lt;li&gt;가비지 컬렉터 개선&lt;/li&gt;
&lt;li&gt;병렬 풀 GC&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Java 11 LTS (2018.09)&lt;/h2&gt;
&lt;p&gt;지원 기간 2026.09&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;새로운 String 메서드(lines, strip, repeat 등)&lt;/li&gt;
&lt;li&gt;HTTP 클라이언트 API 표준화 (HttpClient)&lt;/li&gt;
&lt;li&gt;Lambda 파라미터의 지역변수 문법&lt;/li&gt;
&lt;li&gt;JavaFX 분리&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Java 12 (2019.03)&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Switch Expressions (프리뷰)&lt;/li&gt;
&lt;li&gt;G1 가비지 컬렉터 개선&lt;/li&gt;
&lt;li&gt;JVM Constants API&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Java 13 (2019.09)&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Switch Expressions (프리뷰 개선)&lt;/li&gt;
&lt;li&gt;텍스트 블록 (Text Blocks) (프리뷰)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Java 14 (2020.03)&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Switch Expressions 표준화&lt;/li&gt;
&lt;li&gt;텍스트 블록 (Text Blocks) (프리뷰 개선)&lt;/li&gt;
&lt;li&gt;레코드 (Records) (프리뷰)&lt;/li&gt;
&lt;li&gt;패턴 매칭 (Pattern Matching) for instanceof (프리뷰)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Java 15 (2020.09)&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;텍스트 블록 (Text Blocks) 표준화&lt;/li&gt;
&lt;li&gt;숨겨진 클래스 (Hidden Classes)&lt;/li&gt;
&lt;li&gt;ZGC 개선&lt;/li&gt;
&lt;li&gt;Records (프리뷰 개선)&lt;/li&gt;
&lt;li&gt;패턴 매칭 for instanceof (프리뷰 개선)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Java 16 (2021.03)&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;레코드 (Records) 표준화&lt;/li&gt;
&lt;li&gt;패턴 매칭 for instanceof 표준화&lt;/li&gt;
&lt;li&gt;Vector API (Incubator)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Java 17 LTS (2021.09)&lt;/h2&gt;
&lt;p&gt;지원 기간 2029.09&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;장기 지원 (LTS) 버전.&lt;/li&gt;
&lt;li&gt;패턴 매칭 for switch (프리뷰).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;String result = switch (obj) { case Integer i -&amp;gt; &amp;quot;Integer: &amp;quot; + i; case Long l -&amp;gt; &amp;quot;Long: &amp;quot; + l; case Double d -&amp;gt; &amp;quot;Double: &amp;quot; + d; case String s -&amp;gt; &amp;quot;String: &amp;quot; + s; default -&amp;gt; &amp;quot;Unknown type&amp;quot;; };&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Sealed Classes.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;// Animal.java public sealed class Animal permits Dog, Cat { // Animal class implementation } // Dog.java public final class Dog extends Animal { // Dog class implementation } // Cat.java public final class Cat extends Animal { // Cat class implementation }&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Foreign Function &amp;amp; Memory API (Incubator).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;System.loadLibrary(&amp;quot;example&amp;quot;); // Load the native library&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;난수 생성 API 추가&lt;/li&gt;
&lt;li&gt;&lt;code&gt;// 기본 랜덤 생성기 사용 RandomGenerator random = RandomGenerator.of(&amp;quot;Random&amp;quot;); System.out.println(&amp;quot;Random: &amp;quot; + random.nextInt()); // L64X128MixRandom 생성기 사용 RandomGenerator l64x128MixRandom = RandomGenerator.of(&amp;quot;L64X128MixRandom&amp;quot;); System.out.println(&amp;quot;L64X128MixRandom: &amp;quot; + l64x128MixRandom.nextInt()); // Xoshiro256PlusPlus 생성기 사용 RandomGenerator xoshiro256PlusPlus = RandomGenerator.of(&amp;quot;Xoshiro256PlusPlus&amp;quot;); System.out.println(&amp;quot;Xoshiro256PlusPlus: &amp;quot; + xoshiro256PlusPlus.nextInt());&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Java 18 (2022.03)&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;UTF-8 기본 인코딩&lt;/li&gt;
&lt;li&gt;Simple Web Server&lt;/li&gt;
&lt;li&gt;Code Snippets in Java API Documentation&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Java 19 (2022.09)&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Project Loom (Virtual Threads) (프리뷰)&lt;/li&gt;
&lt;li&gt;Foreign Function &amp;amp; Memory API 개선&lt;/li&gt;
&lt;li&gt;Vector API 개선&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Java 20 (2023.03)&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Scoped Values (Incubator)&lt;/li&gt;
&lt;li&gt;Improved Pattern Matching&lt;/li&gt;
&lt;li&gt;Further Virtual Threads improvements&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Java 21 (2023.09)&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Project Panama (Foreign Function &amp;amp; Memory API)&lt;/li&gt;
&lt;li&gt;Enhanced Pattern Matching for switch (표준화)&lt;/li&gt;
&lt;li&gt;Improved Virtual Threads (Hit)&lt;/li&gt;
&lt;li&gt;Structured Concurrency (Incubator)&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>JAVA</category>
      <author>큐범</author>
      <guid isPermaLink="true">https://kbcoding.tistory.com/135</guid>
      <comments>https://kbcoding.tistory.com/135#entry135comment</comments>
      <pubDate>Tue, 30 Jul 2024 15:54:33 +0900</pubDate>
    </item>
    <item>
      <title>[JAVA] Arrays.sort() Collection.sort() 정렬 알고리즘</title>
      <link>https://kbcoding.tistory.com/134</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Java에서 정렬에 대해서 크게 Arrays.sort()와 Collection.sort()가 존재하는데 이 두 메서드는 내부 구현에 차이가 있어 정리를 하고자 한다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Arrays.sort()&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-06-17 오전 10.58.59.png&quot; data-origin-width=&quot;601&quot; data-origin-height=&quot;342&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yfe6g/btsH0w350VE/ufZjPhwkPX8F89VKKKK6k0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yfe6g/btsH0w350VE/ufZjPhwkPX8F89VKKKK6k0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yfe6g/btsH0w350VE/ufZjPhwkPX8F89VKKKK6k0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fyfe6g%2FbtsH0w350VE%2FufZjPhwkPX8F89VKKKK6k0%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;601&quot; height=&quot;342&quot; data-filename=&quot;스크린샷 2024-06-17 오전 10.58.59.png&quot; data-origin-width=&quot;601&quot; data-origin-height=&quot;342&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;배열을 정리하는데 사용된다. 원시 타입 배열(int[], char[], etc.)와 객체 배열(String[], Integer[], etc.) 모두 정렬할 수 있다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;정렬 방식&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원시 타입 배열의 경우, Dual-Pivot Quicksort&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-06-17 오전 10.59.09.png&quot; data-origin-width=&quot;605&quot; data-origin-height=&quot;213&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/EqGfZ/btsH0lhtUi6/X8kOX3xhPSeeamZ8czQpUk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/EqGfZ/btsH0lhtUi6/X8kOX3xhPSeeamZ8czQpUk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/EqGfZ/btsH0lhtUi6/X8kOX3xhPSeeamZ8czQpUk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEqGfZ%2FbtsH0lhtUi6%2FX8kOX3xhPSeeamZ8czQpUk%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;605&quot; height=&quot;213&quot; data-filename=&quot;스크린샷 2024-06-17 오전 10.59.09.png&quot; data-origin-width=&quot;605&quot; data-origin-height=&quot;213&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;객체 배열의 경우, TimSort&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-06-17 오전 10.59.26.png&quot; data-origin-width=&quot;614&quot; data-origin-height=&quot;149&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b7Iiin/btsH1a0qCC9/JqKsl5SPBos28CC0ohfMK1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b7Iiin/btsH1a0qCC9/JqKsl5SPBos28CC0ohfMK1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b7Iiin/btsH1a0qCC9/JqKsl5SPBos28CC0ohfMK1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb7Iiin%2FbtsH1a0qCC9%2FJqKsl5SPBos28CC0ohfMK1%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;614&quot; height=&quot;149&quot; data-filename=&quot;스크린샷 2024-06-17 오전 10.59.26.png&quot; data-origin-width=&quot;614&quot; data-origin-height=&quot;149&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Collection.sort()&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-06-17 오전 10.59.39.png&quot; data-origin-width=&quot;583&quot; data-origin-height=&quot;80&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ux5eY/btsH0VJgRye/eYYVmMGdFJzaxwFWuCfda1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ux5eY/btsH0VJgRye/eYYVmMGdFJzaxwFWuCfda1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ux5eY/btsH0VJgRye/eYYVmMGdFJzaxwFWuCfda1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fux5eY%2FbtsH0VJgRye%2FeYYVmMGdFJzaxwFWuCfda1%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;583&quot; height=&quot;80&quot; data-filename=&quot;스크린샷 2024-06-17 오전 10.59.39.png&quot; data-origin-width=&quot;583&quot; data-origin-height=&quot;80&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;List를 정렬하는데 사용되어 List 인터페이스를 구현한 모든 컬렉션(ArrayList, LinkedList 등)을 정렬할 수 있다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;정렬방식&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TimSort 방식으로 정렬을 하는데 TimSort를 정렬에 Arrays.sort()의 메서드를 사용한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-06-17 오전 10.59.56.png&quot; data-origin-width=&quot;631&quot; data-origin-height=&quot;282&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bFroNc/btsH2l07ZOu/QY8bp3EEADQoTl0l4tek6k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bFroNc/btsH2l07ZOu/QY8bp3EEADQoTl0l4tek6k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bFroNc/btsH2l07ZOu/QY8bp3EEADQoTl0l4tek6k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbFroNc%2FbtsH2l07ZOu%2FQY8bp3EEADQoTl0l4tek6k%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;631&quot; height=&quot;282&quot; data-filename=&quot;스크린샷 2024-06-17 오전 10.59.56.png&quot; data-origin-width=&quot;631&quot; data-origin-height=&quot;282&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Arrays.sort는 왜 DualPivotQuickSort를 채택했을까?&lt;/h2&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;성능
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Quick sort의 경우 pivot 주변에서 데이터의 위치 이동이 빈번하게 발생하기에 참조 지역성이 좋으며 메모리를 추가로 사용하지 않는다.&lt;/li&gt;
&lt;li&gt;비교 연산 감소 - Dual Pivot Quicksort는 두 개의 피벗을 사용하여 배열을 세 부분으로 나누어 이로인해 평균적으로 비교 연산의 수가 줄어들어 single pivot Quicksort보다 더 빠르게 동작할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Tim Sort와의 비교
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;배열에서는 리스트보다 더 빠르게 요소에 접근 할 수 있기 때문에 timsort 보다는 dual pivot quicksort가 더 적합하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Tim Sort&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 정렬 알고리즘은 Insertion sort와 Merge Sort를 결합하여 만들어졌으며, 안정적인 두 정렬 방법을 결합했기에 안정적이며, 추가 메모리는 사용하지만 기존의 Merge sort에 비해 적은 추가 메모리를 사용하여 다른 정렬 알고리즘의 단점을 최대한 극복한 알고리즘이다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;동작원리&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;데이터를 최소 크기의 run(부분적으로 정렬된 데이터의 연속된 구간)으로 분할&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;입력 배열을 여러 개의 run으로 나눕니다. &lt;code&gt;MIN_RUN&lt;/code&gt;이라는 값이 있으며, 이는 보통 32에서 64 사이입니다.&lt;/li&gt;
&lt;li&gt;하지만 run의 크기는 고정되지 않으며, 이미 정렬된 부분을 최대한 활용합니다. 예를 들어, 배열의 일부가 이미 정렬되어 있으면, 그 부분 전체를 하나의 run으로 취급합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;각 run을 삽입 정렬(Insertion Sort)로 정렬&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;작은 run들은 삽입 정렬을 사용하여 정렬합니다. 삽입 정렬은 작은 배열에서 매우 효율적으로 동작합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;정렬된 run들을 병합&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;정렬된 run들을 병합하여 더 큰 정렬된 run을 만듭니다. 이 과정은 병합 정렬(Merge Sort)을 사용합니다.&lt;/li&gt;
&lt;li&gt;병합 과정에서 &lt;code&gt;galloping mode&lt;/code&gt;라는 최적화 기법을 사용하여 두 run이 많이 정렬되어 있을 때 병합을 가속화합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;반복적인 병합&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;병합된 run들을 다시 병합하여 최종적으로 하나의 정렬된 배열을 만듭니다.&lt;/li&gt;
&lt;li&gt;병합 규칙에 따라 stack-like 구조를 사용하여 병합 순서를 관리합니다. 예를 들어, 특정 크기 조건을 만족하지 않으면 병합을 지연시키거나 조정합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Collection.sort는 왜 Tim Sort를 채택했는가?&lt;/h2&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;하이브리드 알고리즘
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Tim Sort는 삽입 정렬(Insertion Sort)과 병합 정렬(Merge Sort)의 하이브리드 알고리즘으로 삽입 정렬은 작은 데이터 세트에 대해 매우 빠르게 동작하고 병합 정렬은 큰 데이터 세트에 대해 안정적이고 효융적으로 동작한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;최악의 경우에 대한 고려
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Tim Sort는 최악의 경우에도 O(n log n)의 시간 복잡도를 보장하여 정렬 알고리즘에서 매우 중요한 요소로 최악의 경우에도 예측 가능한 성능을 제공한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;안정 정렬
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;TimSort는 안정 정렬 알고리즘으로 동일한 값의 요소들이 정렬 후에도 원래의 상대적인 순서를 유지한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;결론, 그래서 뭐를 써야하나?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;늘 개발하면서 겪는 문제지만 이것은 결국 Trade Off 관계이다. 안전성을 중요시 할 경우, Tim Sort를 속도를 우선시 할 경우, Quick Sort를 사용하면 된다.&lt;/p&gt;
&lt;p data-ke-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;Reference.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://d2.naver.com/helloworld/0315536&quot;&gt;https://d2.naver.com/helloworld/0315536&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.baeldung.com/cs/quicksort-vs-timsort&quot;&gt;https://www.baeldung.com/cs/quicksort-vs-timsort&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://velog.io/@disdos0928/%EC%96%B4%EB%96%A4-%EC%A0%95%EB%A0%AC-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98%EC%9D%84-%EC%82%AC%EC%9A%A9%ED%95%A0%EA%B9%8C&quot;&gt;https://velog.io/@disdos0928/어떤-정렬-알고리즘을-사용할까&lt;/a&gt;&lt;/p&gt;</description>
      <category>JAVA/JAVA Algorithm, Datastruct</category>
      <author>큐범</author>
      <guid isPermaLink="true">https://kbcoding.tistory.com/134</guid>
      <comments>https://kbcoding.tistory.com/134#entry134comment</comments>
      <pubDate>Mon, 17 Jun 2024 11:00:23 +0900</pubDate>
    </item>
    <item>
      <title>[DB] Mysql 옵티마이저 힌트</title>
      <link>https://kbcoding.tistory.com/130</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;옵티마이저&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MySQL 옵티마이저는 SQL 쿼리를 가장 효율적인 방법으로 실행하기 위해 쿼리를 분석하고 실행 계획을 선택하는 구성 요소입니다. 데이터베이스 내부에서 쿼리를 처리할 때 여러 가지 실행 경로가 가능할 수 있는데, 옵티마이저의 역할은 가능한 실행 경로 중에서 비용(리소스 사용, 시간 등)이 가장 낮은 경로를 찾아 선택하는 것입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;MySQL 옵티마이저의 주요 기능&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쿼리 분석: 옵티마이저는 제공된 SQL 쿼리를 분석하여 구문적, 의미적 오류가 없는지 확인합니다. 이 단계에서 쿼리가 유효하고 실행 가능한지 검토합니다.&lt;br /&gt;쿼리 최적화: 옵티마이저는 다양한 최적화 기법을 사용하여 쿼리를 개선합니다. 예를 들어, 필요없는 조건을 제거하거나, 조인 순서를 변경하거나, 인덱스를 활용하는 방법 등을 적용할 수 있습니다.&lt;br /&gt;실행 계획 생성: 옵티마이저는 가능한 여러 실행 계획을 고려하여 각각의 비용을 추정합니다. 이 추정은 통계 정보를 바탕으로 하는데, 이 정보는 테이블의 행 수, 열의 분포, 인덱스의 특성 등을 포함할 수 있습니다.&lt;br /&gt;실행 계획 선택: 모든 가능한 실행 계획의 비용을 추정한 후, 옵티마이저는 가장 비용이 낮은 실행 계획을 선택합니다. 이 계획이 실제 쿼리 실행 시 사용됩니다.&lt;br /&gt;통계 관리: 옵티마이저의 성능은 사용 가능한 통계 정보의 정확성에 크게 의존합니다. MySQL은 통계 정보를 자동으로 갱신하거나 사용자가 수동으로 갱신할 수 있게 관리 도구를 제공합니다.&lt;br /&gt;MySQL 옵티마이저는 이러한 과정을 통해 쿼리의 성능을 향상시키고, 시스템 리소스를 효율적으로 사용하도록 돕습니다. 특히 대규모 데이터를 처리하거나 복잡한 쿼리를 실행할 때, 옵티마이저의 역할은 매우 중요합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;옵티마이저 힌트&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MySQL에서 옵티마이저 힌트는 개발자가 SQL 쿼리의 실행 계획에 직접 개입할 수 있도록 해주는 도구이다. MySQL 8.0 버전에서 사용 가능한 힌트는 종류가 매우 다양하며, 옵티마이저 힌트가 미치는 영향 범위도 매우 다양하다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;옵티마이저 힌트 종류&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;인덱스: 특정 인덱스의 이름을 사용할 수 잇는 옵티마이저 힌트&lt;/li&gt;
&lt;li&gt;테이블: 특정 테이블의 이름을 사용할 수 있는 옵티마이저 힌트&lt;/li&gt;
&lt;li&gt;쿼리 블록: 특정 쿼리 블록에 사용할 수 있는 옵티마이저 힌트, 힌트가 명시된 쿼리 블록에 대해서 영향을 미치는 힌트이다.&lt;/li&gt;
&lt;li&gt;글로벌(쿼리 전체): 전체 쿼리 블록 대해서 영향을 미치는 힌트&lt;/li&gt;
&lt;/ol&gt;</description>
      <category>DB</category>
      <author>큐범</author>
      <guid isPermaLink="true">https://kbcoding.tistory.com/130</guid>
      <comments>https://kbcoding.tistory.com/130#entry130comment</comments>
      <pubDate>Tue, 23 Apr 2024 08:54:08 +0900</pubDate>
    </item>
    <item>
      <title>[DB] 풀 테이블 스캔과 인덱스 스캔</title>
      <link>https://kbcoding.tistory.com/129</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;mysql 옵티마이저는 다음과 같은 조건이 일치할때 주로 풀 테이블 스캔&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;테이블의 레코드 건수가 너무 작아서 인덱스를 통해 읽는 것보다 풀 테이블 스캔을 하는 편이 더 빠른경우&lt;/li&gt;
&lt;li&gt;WHERE 절이나 ON 절에 인덱스를 이용할 수 있는 적절한 조건이 없는 경우&lt;/li&gt;
&lt;li&gt;인덱스 레인지 스캔을 사용할 수 있는 쿼리라고 하더라도 옵티마이저가 판단한 조건 일치 레코드 건수가 너무 많은 경우&lt;/li&gt;
&lt;li&gt;강제 풀 테이블 스캔을 해야하는 경우&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;스트리밍 처리&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;mysql 스트리밍 처리&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서버 쪽에서 처리할 데이터가 얼마인지에 관계없이 조건에 일치하는 레코드가 검색될 때마다 바로바로 클라이언트로 전송해주는 방식을 의미한다. 이 방식으로 쿼리를 처리할 경우 클라이언트는 쿼리를 요청하고 곧바로 원했던 첫 번째 레코드를 전달 받는다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;특징&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;쿼리 결과를 한 번에 모두 생성하지 않는 방식이다.&lt;/li&gt;
&lt;li&gt;대신 서버는 결과를 한 행씩 또는 작은 묶음 단위로 클라이언트에게 전송한다.&lt;/li&gt;
&lt;li&gt;스트리밍 처리는 전체 결과 집합을 메모리에 저장할 필요가 없어 메모리 사용량을 줄일 수 있다.&lt;/li&gt;
&lt;li&gt;결과를 점진적으로 받기 때문에, 첫 번째 결과를 빠르게 얻을 수 있고, 전체 데이터를 기다리지 않아도 된다.&lt;/li&gt;
&lt;li&gt;대용량 데이터 처리나 실시간 처리가 필요한 어플리케이션에 적합하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;mysql 버퍼링 처리&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Order by나 Group by와 같은 처리는 쿼리의 결과가 스트리밍되는 것을 불가능하게 한다. 우선 where 조건에 일치하는 모든 레코드를 가져온 후, 정렬하거나 그루핑해서 차례대로 보내야 하기 때문이다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;특징&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;서버가 쿼리의 전체 결과를 먼저 생성하고 이를 메모리에 저장한 후 클라이언트에게 전송하는 방식이다.&lt;/li&gt;
&lt;li&gt;결과 집합이 클라이언트로 전송되기 전에 서버 메모리에 저장되므로, 대용량 결과 집합을 처리할 때는 메모리 사용량이 증가할 수 있다.&lt;/li&gt;
&lt;li&gt;작은 결과 집합을 빠르게 전체적으로 받을 수 있으므로, 데이터 크기가 작은 어플리케이션에 유리하다.&lt;/li&gt;
&lt;li&gt;일반적인 웹 어플리케이션과 같이 결과 집합이 크지 않은 경우에 적합하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JDBC는 MySQL 서버는 레코드를 읽자마자 클라이언트로 그 결과를 전달할 것이다. 하지만 JDBC는 MySQL 서버로부터 받는 레코드를 일단 내부 버퍼에 모두 담아둔다. 그리고 마지막 레코드가 전달될 때까지 기다렸다가 모든 결과를 전달받으면 그때서야 비로소 클라이언트의 애플리케이션에 반환한다. 즉, MySQL 서버는 스트리밍 방식으로 처리해서 반환하지만 클라이언트의JDBC 라이브러리가 버퍼링하는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Reference.&lt;/p&gt;
&lt;figure id=&quot;og_1712620929104&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;Real MySQL 8.0 (1권) | 백은빈 - 교보문고&quot; data-og-description=&quot;Real MySQL 8.0 (1권) | MySQL 서버를 활용하는 프로젝트에 꼭 필요한 경험과 지식을 담았습니다!《Real MySQL 8.0》은 《Real MySQL》을 정제해서 꼭 필요한 내용으로 압축하고, MySQL 8.0의 GTID와 InnoDB 클러스&quot; data-og-host=&quot;product.kyobobook.co.kr&quot; data-og-source-url=&quot;https://product.kyobobook.co.kr/detail/S000001766482&quot; data-og-url=&quot;https://product.kyobobook.co.kr/detail/S000001766482&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/f8sek/hyVMTQRy2q/aiLz0iN2Pr6N4jRmczUJXK/img.jpg?width=458&amp;amp;height=569&amp;amp;face=0_0_458_569,https://scrap.kakaocdn.net/dn/Ut2Qv/hyVJZZs2Mf/OrMNEkzhinLt2IQyMMkokK/img.jpg?width=458&amp;amp;height=569&amp;amp;face=0_0_458_569,https://scrap.kakaocdn.net/dn/trt2v/hyVMWGPlNT/KPMbEOb5B9JHeMBKnvyib1/img.jpg?width=814&amp;amp;height=3987&amp;amp;face=0_0_814_3987&quot;&gt;&lt;a href=&quot;https://product.kyobobook.co.kr/detail/S000001766482&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://product.kyobobook.co.kr/detail/S000001766482&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/f8sek/hyVMTQRy2q/aiLz0iN2Pr6N4jRmczUJXK/img.jpg?width=458&amp;amp;height=569&amp;amp;face=0_0_458_569,https://scrap.kakaocdn.net/dn/Ut2Qv/hyVJZZs2Mf/OrMNEkzhinLt2IQyMMkokK/img.jpg?width=458&amp;amp;height=569&amp;amp;face=0_0_458_569,https://scrap.kakaocdn.net/dn/trt2v/hyVMWGPlNT/KPMbEOb5B9JHeMBKnvyib1/img.jpg?width=814&amp;amp;height=3987&amp;amp;face=0_0_814_3987');&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;Real MySQL 8.0 (1권) | 백은빈 - 교보문고&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Real MySQL 8.0 (1권) | MySQL 서버를 활용하는 프로젝트에 꼭 필요한 경험과 지식을 담았습니다!《Real MySQL 8.0》은 《Real MySQL》을 정제해서 꼭 필요한 내용으로 압축하고, MySQL 8.0의 GTID와 InnoDB 클러스&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;product.kyobobook.co.kr&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>DB</category>
      <category>DB</category>
      <category>mysql</category>
      <author>큐범</author>
      <guid isPermaLink="true">https://kbcoding.tistory.com/129</guid>
      <comments>https://kbcoding.tistory.com/129#entry129comment</comments>
      <pubDate>Tue, 9 Apr 2024 09:02:14 +0900</pubDate>
    </item>
    <item>
      <title>[Spring] @Async vs WebFlux</title>
      <link>https://kbcoding.tistory.com/128</link>
      <description>&lt;h1&gt;Spring @Async vs Spring WebFlux&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;글을 작성하게된 계기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실무에서 서버간 통신을 할때 비동기로 호출해야하는 경우가 있었다. 처음에는 @Async를 사용하였는데 좀 더 깊게 파보니 Spring WebFlux도 많이 사용하는 것을 확인하고 WebFlux도 동시에 써보았는데 WebFlux가 더 빠른 것을 보았다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Spring @Async&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;설명&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;code&gt;@Async&lt;/code&gt;&lt;/b&gt; 어노테이션은 Spring에서 제공하는 비동기 실행 방법으로 메서드를 별도의 스레드에서 비동기적으로 실행한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;code&gt;@Async&lt;/code&gt;&lt;/b&gt;는 Spring의 AOP 기능을 활용하여 메서드 호출을 비동기적으로 처리한다. 이는 스레드 풀을 사용하여 별도의 스레드에서 실행되며, 비동기 작업의 결과 또는 상태는 &lt;b&gt;&lt;code&gt;Future&lt;/code&gt;&lt;/b&gt; 객체를 통해 관리할 수 있다. &lt;b&gt;&lt;code&gt;@Async&lt;/code&gt;&lt;/b&gt;는 간단하고 효율적인 비동기 처리 방법을 제공하여, 리소스를 효율적으로 사용하면서 애플리케이션의 성능을 향상시킬 수 있다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;적용 사례&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;code&gt;@Async&lt;/code&gt;&lt;/b&gt;는 주로 단일 작업에 대한 비동기 처리가 필요할 때 사용됩니다. 예를 들어, 이메일 보내기, 파일 업로드, 복잡한 계산 수행 등의 작업에 적합합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;장점&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구현이 간단하고, 기존 코드에 쉽게 통합할 수 있다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;단점&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;복잡한 비동기 작업 흐름이나 백프레셔(backpressure) 관리 등에는 적합하지 않다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;예시 코드&lt;/h3&gt;
&lt;pre class=&quot;less&quot;&gt;&lt;code&gt;@Configuration
@EnableAsync
public class AsyncConfig {
    // 필요한 경우 여기에 사용자 정의 스레드 풀 설정을 추가할 수 있습니다.
}

public class AsyncService {
    @Async(name = 'test')
    public void asyncTest() {
        try {
            Thread.sleep(1000);
            log.info(&quot;Async Test&quot;);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Spring Webflux&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;설명&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;code&gt;Spring WebFlux&lt;/code&gt;&lt;/b&gt;는 Spring 5에서 도입된 반응형 프로그래밍을 위한 웹 프레임워크이다. 이는 논블로킹(non-blocking) I/O와 비동기적 실행을 지원하며, 더 효율적인 리소스 사용과 높은 처리량을 제공한다. &lt;b&gt;&lt;code&gt;Mono&lt;/code&gt;&lt;/b&gt;와 &lt;b&gt;&lt;code&gt;Flux&lt;/code&gt;&lt;/b&gt;와 같은 리액티브 타입을 사용하여 데이터 스트림을 처리한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;적용사례&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;WebFlux는 동시에 많은 요청을 처리해야 하거나, 데이터 스트림을 연속적으로 처리해야 할 때 유용하다. 예를 들어, 실시간 데이터 처리, 대규모 파일 처리, 웹 소켓 통신 등에 적합하다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;장점&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;높은 동시성 처리 능력, 리소스 효율성, 백프레셔 관리 기능을 제공한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;단점&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비동기와 반응형 프로그래밍 모델은 학습 곡선이 높으며, 복잡할 수 있다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;예시 코드&lt;/h3&gt;
&lt;pre class=&quot;kotlin&quot;&gt;&lt;code&gt;@Configuration
public class WebClientConfig {

    @Bean
    public WebClient webClient() {
        return WebClient.create(&quot;http://example.com/api&quot;); // 여기에 외부 API의 기본 URL을 설정합니다.
    }
}

@Configuration
public class RouterConfig {

    @Bean
    public RouterFunction&amp;lt;ServerResponse&amp;gt; personRouter(PersonHandler handler) {
        return route(GET(&quot;/person/{id}&quot;), request -&amp;gt; handler.getPerson(request.pathVariable(&quot;id&quot;)))
                .andRoute(GET(&quot;/persons&quot;), request -&amp;gt; handler.getAllPersons());
    }
}

@Component
public class ApiService {

    public Mono&amp;lt;String&amp;gt; getExternalData() {
        return webClient.get()
                        .uri(&quot;/data&quot;) // 외부 API의 특정 경로
                        .retrieve()
                        .bodyToMono(String.class); // 응답을 String으로 변환
    }
}

@RestController
public class ApiController {

    private final ApiService apiService;

    @Autowired
    public ApiController(ApiService apiService) {
        this.apiService = apiService;
    }

    @GetMapping(&quot;/external-data&quot;)
    public Mono&amp;lt;String&amp;gt; fetchExternalData() {
        return apiService.getExternalData(); // 서비스에서 외부 API 호출
    }
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Spring</category>
      <author>큐범</author>
      <guid isPermaLink="true">https://kbcoding.tistory.com/128</guid>
      <comments>https://kbcoding.tistory.com/128#entry128comment</comments>
      <pubDate>Mon, 25 Mar 2024 14:22:01 +0900</pubDate>
    </item>
    <item>
      <title>[JAVA] GC(Garbage Collector) 동작과정, 종류, Java Default GC, Java Command</title>
      <link>https://kbcoding.tistory.com/127</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;GC(Garbage Collector)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;동적으로 할당한 메모리 영역 중 사용하지 않는 영역을 탐지하여 해제하는 기능&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;GC 종류&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;SerialGC
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;단일 스레드로 작동한다.&lt;/li&gt;
&lt;li&gt;JVM 옵션: &lt;b&gt;&lt;code&gt;-XX:+UseSerialGC&lt;/code&gt;&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;ParallelGC
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;여러 개의 스레드를 사용하여 Young Genertaion영역에서 가비지 컬렉션을 수행한다.&lt;/li&gt;
&lt;li&gt;JVM 옵션: &lt;b&gt;&lt;code&gt;-XX:+UseParallelGC&lt;/code&gt;&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Parallel Old GC
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Parallel GC의 구세대 버전으로 Old Generation 영역에서 병렬로 가비지 컬렉션을 수행한다.&lt;/li&gt;
&lt;li&gt;JVM 옵션: &lt;b&gt;&lt;code&gt;XX:+UseParallelOldGC&lt;/code&gt;&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;JVM 옵션: &lt;b&gt;&lt;code&gt;XX:+UseParallelOldGC&lt;/code&gt;&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Concurrent Mark Sweep(CMS) GC
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;낮은 중지 시간을 목표로 하는 멀티프로세싱 환경에 적합하다.&lt;/li&gt;
&lt;li&gt;JVM 옵션: &lt;b&gt;&lt;code&gt;-XX:+UseConcMarkSweepGC&lt;/code&gt;&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;G1(Grabage-First) Collector
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;큰 힙을 관리하고 예측 가능한 중지 시간을 제공하는 데 적합하다.&lt;/li&gt;
&lt;li&gt;힙을 여러 개의 작은 영역으로 나누어 관리한다.&lt;/li&gt;
&lt;li&gt;JVM 옵션: &lt;b&gt;&lt;code&gt;-XX:+UseG1GC&lt;/code&gt;&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;ZGC(Z Garbage Collector)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Java 11부터 사용 가능한 저지연(law latency) 가비지 컬렉터&lt;/li&gt;
&lt;li&gt;대규모 힙과 멀티 프로세서 환경에서 중지 시간을 최소화하는 데 초점을 맞춘다.&lt;/li&gt;
&lt;li&gt;JVM 옵션: &lt;b&gt;&lt;code&gt;XX:+UseZGC&lt;/code&gt;&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Shenandoah
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ZGC와 유사하게 저지연 가비지 컬렉션을 목표로한다.&lt;/li&gt;
&lt;li&gt;대규모 힙에서도 짧은 중지 시간을 제공한다.&lt;/li&gt;
&lt;li&gt;JVM 옵션: &lt;b&gt;&lt;code&gt;XX:+UseShenandoahGC&lt;/code&gt;&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;stop-the-world&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;GC를 실행하기 위해 JVM이 애플리케이션 실행을 멈추는 것이다. stop-the-world가 발생하면 GC를 실행하는 쓰레드를 제외한 나머지 쓰레드는 모두 작업을 멈춘다. GC 작업을 완료한 이후에야 중단해 두었던 작업을 다시 시작한다. 모든 GC 알고리즘은 stop-the-world가 발생한다. 대부분의 GC 튜닝은 stop-the-world의 시간을 줄이는 것이다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;GC에서 관리하는 JVM의 영역&lt;/h2&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;힙(Heap): JVM에서 가장 큰 메모리 영역, 힙은 다음과 같은 세부 영역으로 나뉜다.
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Young Genertaion
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;새로 생성된 객체들이 할당되는 영역으로 대부분의 객체가 금방 사용하지 않게 되는 객체를 위한 곳이다. Eden영역과 Survivor 영역이 포함된다.&lt;/li&gt;
&lt;li&gt;해당 영역에서 발생하는 GC를 Minor GC라고 하며 Major GC에 비해 빠르다.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;Old Generation
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Young에서 오래 살아남은 객체들이 이동되는 곳이다. 이 영역은 객체가 더 오래 존재한 곳이다.&lt;/li&gt;
&lt;li&gt;해당 영역에서 발생하는 GC를 Major GC라고 하며 Minor GC에 비해 느리다.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;Permanent Generation Or Metaspace
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;클래스와 메소드에 대한 메타데이터가 저장되는 영역 PS. Java 8부터는 PerGen이 Metaspace로 대체되었다.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;스택(Stack): Java 메소드의 호출과 실행에 사용된다.&lt;/li&gt;
&lt;li&gt;코드(Code): 프로그램의 바이트코드 즉 컴파일된 클래스와 인터페이스의 코드가 저장되는 영역&lt;/li&gt;
&lt;li&gt;네이티브 메소드 스택(Native Method Stack): 자바 외의 언어로 작성된 네이티브 코드를 위한 스택&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가비지 컬렉션은 힙 영역을 주 대상으로 관리하며 힙 내의 객체들 중에서 더이상 사용되지 않는 객체들을 식별하고 이를 수집하여 메모리를 해제한다. 다른 영역들은 각각 스레드나 JVM자체에 의해 관리가 되며 가비지 컬렉션의 대상이 아니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;GC 과정&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 새로운 객체가 Eden 공간에 할당된다. 두 Survivor 영역은 빈 공간으로 시작한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;960&quot; data-origin-height=&quot;720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kLRBk/btsFlT8Fci4/ACUilyTlHkylljintvyPO0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kLRBk/btsFlT8Fci4/ACUilyTlHkylljintvyPO0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kLRBk/btsFlT8Fci4/ACUilyTlHkylljintvyPO0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkLRBk%2FbtsFlT8Fci4%2FACUilyTlHkylljintvyPO0%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;494&quot; height=&quot;371&quot; data-origin-width=&quot;960&quot; data-origin-height=&quot;720&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. Eden 공간이 가득차면 Minor GC가 작동한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;960&quot; data-origin-height=&quot;720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cFrRvE/btsFmfcDFes/TS909FcIR5MYI0ttkz5v90/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cFrRvE/btsFmfcDFes/TS909FcIR5MYI0ttkz5v90/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cFrRvE/btsFmfcDFes/TS909FcIR5MYI0ttkz5v90/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcFrRvE%2FbtsFmfcDFes%2FTS909FcIR5MYI0ttkz5v90%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;498&quot; height=&quot;374&quot; data-origin-width=&quot;960&quot; data-origin-height=&quot;720&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 참조된 객체는 첫번째 Survivor 영역으로 이동하고 참조가 없는 객체는 Eden 영역에서 제거한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;960&quot; data-origin-height=&quot;720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/5lB9Z/btsFp7khMzF/kDItNi5bbOAbK5vTMftUc1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/5lB9Z/btsFp7khMzF/kDItNi5bbOAbK5vTMftUc1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/5lB9Z/btsFp7khMzF/kDItNi5bbOAbK5vTMftUc1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F5lB9Z%2FbtsFp7khMzF%2FkDItNi5bbOAbK5vTMftUc1%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;499&quot; height=&quot;374&quot; data-origin-width=&quot;960&quot; data-origin-height=&quot;720&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 다음 Minor GC에서는 Eden 공간에서도 동일한(1~3) 작업이 발생합니다. 참조되지 않은 객체는 삭제되고 참조된 객체는 생존 공간으로 이동한다. 다만, 이 경우에는 두 번째 생존 공간(S1)으로 이동하고 첫 번째 생존 공간(S0)의 마지막 마이너 GC의 객체는 수명이 증가하고 S1으로 이동한다. 살아남은 모든 객체가 S1으로 이동하면 S0와 Eden 모두 지워진다. 이제 생존자 공간에는 서로 aged를 가지는 객체가 있는 것을 염두하자.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;960&quot; data-origin-height=&quot;720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/buwbPw/btsFqX9zHVY/d3xK4EsFIQnUwkdM9X16PK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/buwbPw/btsFqX9zHVY/d3xK4EsFIQnUwkdM9X16PK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/buwbPw/btsFqX9zHVY/d3xK4EsFIQnUwkdM9X16PK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbuwbPw%2FbtsFqX9zHVY%2Fd3xK4EsFIQnUwkdM9X16PK%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;491&quot; height=&quot;368&quot; data-origin-width=&quot;960&quot; data-origin-height=&quot;720&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br /&gt;5. 다음 Minor GC 에서는 동일한 프로세스가 발생한다. 하지만, 이번에는 Survivor 영역이 전환된다. 참조된 객체는 S1(두번째 Survivor 영역)에서 S0(첫번째 Survivor 영역)으로 이동된다. 살아남은 객체들은 aged 된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;960&quot; data-origin-height=&quot;720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/E0OeZ/btsFjVFU5oh/OqYxSi68IuoqkAr2F0Clc0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/E0OeZ/btsFjVFU5oh/OqYxSi68IuoqkAr2F0Clc0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/E0OeZ/btsFjVFU5oh/OqYxSi68IuoqkAr2F0Clc0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FE0OeZ%2FbtsFjVFU5oh%2FOqYxSi68IuoqkAr2F0Clc0%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;497&quot; height=&quot;373&quot; data-origin-width=&quot;960&quot; data-origin-height=&quot;720&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;6. 아래의 슬라이드에서는 프로모션을 보여준다. Minor GC 후에 오래된 객체가 특정 연령 임계값(해당 예에서는 8)에 도달하면 Young Genertaion에서 Old Generation로 전환된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;960&quot; data-origin-height=&quot;720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Mv8WA/btsFkV6IrrE/ZSeJkXKuZ0w5kqxfNHqtyk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Mv8WA/btsFkV6IrrE/ZSeJkXKuZ0w5kqxfNHqtyk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Mv8WA/btsFkV6IrrE/ZSeJkXKuZ0w5kqxfNHqtyk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FMv8WA%2FbtsFkV6IrrE%2FZSeJkXKuZ0w5kqxfNHqtyk%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;493&quot; height=&quot;370&quot; data-origin-width=&quot;960&quot; data-origin-height=&quot;720&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;7. Minor GC가 계속 발생하면 객체는 Young Genertaion에서 Old Generation으로 이동한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;960&quot; data-origin-height=&quot;720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/n8aeE/btsFm85j9W2/pPkKgda3pFoQazxcsK1K1K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/n8aeE/btsFm85j9W2/pPkKgda3pFoQazxcsK1K1K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/n8aeE/btsFm85j9W2/pPkKgda3pFoQazxcsK1K1K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fn8aeE%2FbtsFm85j9W2%2FpPkKgda3pFoQazxcsK1K1K%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;492&quot; height=&quot;369&quot; data-origin-width=&quot;960&quot; data-origin-height=&quot;720&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Java에서 GC 사용 예시&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;명령어&lt;/h3&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;System.gc();
Runtime.getRuntime().gc();&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 명령어들은 JVM에게 가비지 컬렉션을 실행하도록 요청한다. 하지만, 실제로 가비지 컬렉션이 실행될 시기와 방식은 JVM의 가비지 컬렉터 구현에 달려있다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;JVM 옵션을 통한 가비지 컬렉터 설정&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;&lt;code&gt;XX:+UseSerialGC&lt;/code&gt;&lt;/b&gt;: 시리얼 가비지 컬렉터를 사용하도록 설정합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;code&gt;XX:+UseParallelGC&lt;/code&gt;&lt;/b&gt;: 병렬 가비지 컬렉터를 사용하도록 설정합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;code&gt;XX:+UseParallelOldGC&lt;/code&gt;&lt;/b&gt;: 구세대 영역에 대해 병렬 가비지 컬렉터를 사용합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;code&gt;XX:+UseConcMarkSweepGC&lt;/code&gt;&lt;/b&gt;: CMS(Concurrent Mark-Sweep) 가비지 컬렉터를 사용합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;code&gt;XX:+UseG1GC&lt;/code&gt;&lt;/b&gt;: G1(Garbage-First) 가비지 컬렉터를 사용합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Ex)&lt;/p&gt;
&lt;pre class=&quot;groovy&quot;&gt;&lt;code&gt;java -XX:+UseG1GC -Xms512m -Xmx4g -XX:NewRatio=3 -XX:SurvivorRatio=6 -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:gc-log.txt -jar application.jar&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;&lt;code&gt;XX:+UseG1GC&lt;/code&gt;&lt;/b&gt;: G1 가비지 컬렉터를 사용합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;code&gt;Xms512m&lt;/code&gt;&lt;/b&gt;: JVM의 초기 힙 크기를 512MB로 설정합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;code&gt;Xmx4g&lt;/code&gt;&lt;/b&gt;: JVM의 최대 힙 크기를 4GB로 설정합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;code&gt;XX:NewRatio=3&lt;/code&gt;&lt;/b&gt;: 신세대와 구세대의 메모리 비율을 1:3으로 설정합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;code&gt;XX:SurvivorRatio=6&lt;/code&gt;&lt;/b&gt;: 신세대 내의 에덴 영역과 서바이버 영역의 비율을 1:6으로 설정합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;code&gt;XX:+PrintGCDetails&lt;/code&gt;&lt;/b&gt;, &lt;b&gt;&lt;code&gt;XX:+PrintGCDateStamps&lt;/code&gt;&lt;/b&gt;: 가비지 컬렉션의 상세 정보와 타임스탬프를 콘솔에 출력합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;code&gt;Xloggc:gc-log.txt&lt;/code&gt;&lt;/b&gt;: 가비지 컬렉션 로그를 'gc-log.txt' 파일에 기록합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;JVM옵션을 통한 가비지 컬렉션 튜닝&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;&lt;code&gt;Xms&amp;lt;size&amp;gt;&lt;/code&gt;&lt;/b&gt;: JVM의 초기 힙 크기를 설정합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;code&gt;Xmx&amp;lt;size&amp;gt;&lt;/code&gt;&lt;/b&gt;: JVM의 최대 힙 크기를 설정합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;code&gt;Xmn&amp;lt;size&amp;gt;&lt;/code&gt;&lt;/b&gt;: 신세대 영역의 크기를 설정합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;code&gt;XX:NewRatio=&amp;lt;ratio&amp;gt;&lt;/code&gt;&lt;/b&gt;: 신세대와 구세대의 비율을 설정합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;code&gt;XX:SurvivorRatio=&amp;lt;ratio&amp;gt;&lt;/code&gt;&lt;/b&gt;: 에덴 영역과 서바이버 영역의 비율을 설정합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;code&gt;XX:+PrintGCDetails&lt;/code&gt;&lt;/b&gt;, &lt;b&gt;&lt;code&gt;XX:+PrintGCDateStamps&lt;/code&gt;&lt;/b&gt;, &lt;b&gt;&lt;code&gt;Xloggc:&amp;lt;file&amp;gt;&lt;/code&gt;&lt;/b&gt;: GC 로그를 상세하게 출력하거나 파일로 저장합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Ex)&lt;/p&gt;
&lt;pre class=&quot;groovy&quot;&gt;&lt;code&gt;java -Xms512m -Xmx4g -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=70 -XX:+ScavengeBeforeFullGC -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:gc-log.txt -jar application.jar&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;java -Xms512m -Xmx4g -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=70 -XX:+ScavengeBeforeFullGC -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:gc-log.txt -jar application.jar&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;&lt;code&gt;Xms512m&lt;/code&gt;&lt;/b&gt;: JVM의 초기 힙 크기를 512MB로 설정합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;code&gt;Xmx4g&lt;/code&gt;&lt;/b&gt;: JVM의 최대 힙 크기를 4GB로 설정합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;code&gt;XX:+UseConcMarkSweepGC&lt;/code&gt;&lt;/b&gt;: CMS(Concurrent Mark-Sweep) 가비지 컬렉터를 사용합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;code&gt;XX:+CMSParallelRemarkEnabled&lt;/code&gt;&lt;/b&gt;: CMS 가비지 컬렉션 중 병렬 리마크 단계를 활성화합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;code&gt;XX:+UseCMSInitiatingOccupancyOnly&lt;/code&gt;&lt;/b&gt;: 힙 사용량 기반의 CMS 가비지 컬렉션 시작을 활성화합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;code&gt;XX:CMSInitiatingOccupancyFraction=70&lt;/code&gt;&lt;/b&gt;: 힙의 70%가 사용되었을 때 CMS 가비지 컬렉션을 시작합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;code&gt;XX:+ScavengeBeforeFullGC&lt;/code&gt;&lt;/b&gt;: 전체 GC 전에 젊은 세대의 가비지 컬렉션을 수행합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;code&gt;XX:+PrintGCDetails&lt;/code&gt;&lt;/b&gt;, &lt;b&gt;&lt;code&gt;XX:+PrintGCDateStamps&lt;/code&gt;&lt;/b&gt;: 가비지 컬렉션의 상세 정보와 타임스탬프를 콘솔에 출력합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;code&gt;Xloggc:gc-log.txt&lt;/code&gt;&lt;/b&gt;: 가비지 컬렉션 로그를 'gc-log.txt' 파일에 기록합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Java 버전별 디폴트 GC 알고리즘&lt;/h2&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Java 1.3 이하
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Serial GC&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Java 1.4 ~ Java 5
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Parallel GC&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Java 6 ~ Java 8
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Parallel Old GC&lt;/li&gt;
&lt;li&gt;Java 8u40부터 G1 GC가 도입되었으나, Parallel Old GC가 여전히 디폴트다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Java 9 ~ Java 10
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;G1 GC&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Java 11 이후
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;G1 GC&lt;/li&gt;
&lt;li&gt;Java 11부터 ZGC가 실험적으로 도입되었으나 디폴트는 G1GC이다.&lt;/li&gt;
&lt;li&gt;Java 15부터 Shenandoah가 실험적으로 추가되었다.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Reference.&lt;br /&gt;&lt;a href=&quot;https://www.oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/index.html&quot; target=&quot;_self&quot;&gt;&lt;span&gt;https://www.oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/index.html&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;&lt;a href=&quot;https://wiki.openjdk.org/display/zgc/Main#Main-JDK11&quot; target=&quot;_self&quot;&gt;&lt;span&gt;https://wiki.openjdk.org/display/zgc/Main#Main-JDK11&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;&lt;a href=&quot;https://stackoverflow.com/questions/33206313/default-garbage-collector-for-java-8&quot; target=&quot;_self&quot;&gt;&lt;span&gt;https://stackoverflow.com/questions/33206313/default-garbage-collector-for-java-8&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;</description>
      <category>JAVA</category>
      <author>큐범</author>
      <guid isPermaLink="true">https://kbcoding.tistory.com/127</guid>
      <comments>https://kbcoding.tistory.com/127#entry127comment</comments>
      <pubDate>Thu, 29 Feb 2024 11:03:37 +0900</pubDate>
    </item>
    <item>
      <title>레디스 RedLock의 수행방식과 한계</title>
      <link>https://kbcoding.tistory.com/126</link>
      <description>&lt;h1&gt;레디스 분산락&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 글에서는 Redis의 분산락에 대한 개념을 설명한다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;글을 쓰게 된 이유&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 진행하고 있는 프로젝트에서 선착순 이벤트를 진행하는데 현재 소프트웨어 아키텍쳐로는 선착순에 대해서 보장할 방법이 없었다. MySQL에 부담을 주기에는 사이드 이펙트가 크고 DB를 하나의 백엔드만 사용하고 있는 것이 아니고 다른 서버에서도 사용하고 잇기에 만약 DB에 문제가 생길 경우, 이펙트가 큰 상황이라서 DB 부담하는 것은 보기에서 제거를 했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞으로의 기획 로드맵과 현재의 기획 부분에서 Redis가 적합한 선택이 될 것 같아 Redis를 선택하여 도입하였다. 도입과 동시에 선착순 이벤트에 대해서 정상적인 처리가 이루어졌지만 급하게 적용한 탓에 레디스의 분산락에 대한 이해가 부족하여 해당 개념에 대해서 정리를 해보고자 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;분산락(Distributed Lock)은 여러 컴퓨터 시스템이 네트워크를 통해 연결된 분산 시스템 환경에서 자원에 대한 동시 접근을 조절하기 위해 사용되는 동기화 메커니즘이다. 이는 여러 노드가 동일한 데이터나 자원에 접근하고자 할 때 발생할 수 있는 충돌을 방지하는 데 필요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Point. 레디스는 싱글 스레드로 동작한다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;[Redis에서 분산락을 제공하는 이유]&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단일 레디스 노드는 단일 장애 지점(Single Point Of Failure)이 될 가능성이 있다. 해당 문제를 해결하기 위해서는 Master-Slave 복제(replication) 레디스 서버를 구축하기도 하나, 해당 아키텍쳐는 경쟁상태(race condition)이 발생할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단일 장애 지점(Single Point Of Failure) : 시스템 구성 요소 중에서 동작하지 않으면 전체 시스템이 중단되는 요소&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;경쟁 상태(Race Condition) : 여러 개의 프로세스가 공유 자원에 동시 접근할 때 실행 순서에 따라 결과값이 달라질 수 있는 현상이다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;경쟁 상태가 발생하는 시나리오&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;클라이언트 A는 마스터에서 잠금을 획득한다.&lt;/li&gt;
&lt;li&gt;키에 대한 쓰기가 복제본으로 전송되기 전에 마스터가 충돌이 발생한다..&lt;/li&gt;
&lt;li&gt;복제본이 마스터로 승격됩니다.&lt;/li&gt;
&lt;li&gt;클라이언트 B는 A가 이미 잠금을 보유하고 있는 동일한 리소스에 대한 잠금을 획득합니다. &lt;b&gt;SAFETY VIOLATION!&lt;/b&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h1&gt;[RedLock]&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;레디스는 위의 단일 장애 지점과 경쟁 상태를 해결하기 위해 Red Lock 알고리즘을 제안한다. Red Lock은 Redis Lock이라고도 불린다. 레드락은 N개의 단일 레디스 노드들을 이용하여, Quorum 이상의 노드에서 잠금을 획득하면 락을 획득하는 매커니즘이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Redlock은 아래의 3가지 특성을 지킨다고 이야기한다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;상호배제 : 오직 한 순간에 하나의 워커 락을 획득한다.&lt;/li&gt;
&lt;li&gt;데드락 방지 : 락 이후 어떠한 문제로 인해 락을 풀지 못하고 종료된 경우라도 다른 워커가 락을 획득할 수 있어야한다.&lt;/li&gt;
&lt;li&gt;내결함성 : Redis 노드가 작동하는 한 모든 워커는 락을 걸고 해제할 수 있어야한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;[Red Lock 작업 수행]&lt;/h2&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;현재 시간을 ms단위로 가져온다.&lt;/li&gt;
&lt;li&gt;모든 인스턴스에서 동일한 키 이름과 임의의 값을 사용하여 모든 N 인스턴스에서 순차적으로 잠금을 획득하려고 시도한다. 2단계에서 각 인스턴스에 잠금을 설정할 때 클라이언트는 잠금을 획득하기 위해 총 잠금 자동 해제 시간에 비해 작은 제한 시간을 사용한다. 예를들어, 자동 해제 시간이 10초인 경우 제한 시간은 5~50ms 범위 일 수도 있다. 이렇게 하면 클라이언트가 다운된 Redis 노드와 통신하려고 오랫동안 차단되는 것을 방지할 수 있다.&lt;/li&gt;
&lt;li&gt;클라이언트는 1단계에서 얻은 타임 스탬프를 현재 시간에서 빼서 잠금을 획득하는 데 경과된 시간을 계산하여 클라이언트가 대부분의 인스턴스(최소 3개)에서 잠금을 획득할 수 있었던 경우에만 해당된다. 잠금을 획득하는데, 소요된 총 시간이 잠금 유효 시간보다 작을 경우 잠금을 획득한 것으로 간주된다.&lt;/li&gt;
&lt;li&gt;잠금이 획득된 경우 유효 시간은 3단계에서 계산된 대로 초기 유효 시간에서 경과 시간을 뺀 것으로 간주한다.&lt;/li&gt;
&lt;li&gt;클라이언트가 어떠한 이유로 잠금 획득에 실패한 경우(N/2+1 인스턴스를 잠글 수 없거나 유효 시간이 음수인 경우) 모든 인스턴스의 잠금을 해제하려고 시도한다.(그렇지 않다고 생각되는 인스턴스도 포함)&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;[RedLock의 한계]&lt;/h2&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Clock Drift&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;RedLock은 노드간의 동기화된 시계는 없지만, 로컬 시간에 기반하여 작동하기에 현실에서 클럭이 정확한 속도 동작하지 않으면 클럭 드리프트(Clock Drift) 현상으로 인해 알고리즘이 보장이 안될 수 있다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;클라이언트 1이 분산락을 획득한다.&lt;/li&gt;
&lt;li&gt;클라이언트 1에서 애플리케이션이 중지가 발생하고, 그 사이에 분산락이 만료된다.&lt;/li&gt;
&lt;li&gt;클라이언트 2는 분산락을 획득하고 파일에 접근한다.&lt;/li&gt;
&lt;li&gt;클라이언트 1의 애플리케이션이 복구되고 파일을 접근한다.&lt;/li&gt;
&lt;li&gt;동시성 문제가 발생한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Untitled.png&quot; data-origin-width=&quot;1100&quot; data-origin-height=&quot;400&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eoQCfZ/btsEWN2JtRz/WKRt5QPuiPJbif8SulO4gK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eoQCfZ/btsEWN2JtRz/WKRt5QPuiPJbif8SulO4gK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eoQCfZ/btsEWN2JtRz/WKRt5QPuiPJbif8SulO4gK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeoQCfZ%2FbtsEWN2JtRz%2FWKRt5QPuiPJbif8SulO4gK%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;1100&quot; height=&quot;400&quot; data-filename=&quot;Untitled.png&quot; data-origin-width=&quot;1100&quot; data-origin-height=&quot;400&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반적으로 GC 시간이 짧으나, Stop-The-World GC는 잠금이 만료될 수 있을 만큼 충분히 오래 지속될 수 있기에 GC 일시 중지는 때때로 몇 분 동안 지속되는 것으로 알려져 있다. 따라서, 락 점유의 만료 기간을 가지는 것은 선택이 아닌 필수다. 하지만 프로세스를 멈추는 이유는 GC외에도 다양한데 이 중 문제가 될 만한 것은 네트워크 지연 등에 의해서도 RedLock 알고리즘을 보장 못받을 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 네트워크 문제를 해결하기 위해 모든 펜싱 토큰 또는 버전을 포함하여 아래와 같이 처리할 수 있다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; start=&quot;2&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Network에 기반한 운영&lt;br /&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Untitled 1.png&quot; data-origin-width=&quot;1100&quot; data-origin-height=&quot;400&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cHpOR5/btsEZbVSkIB/OxgKl8ParyjEVTQEXLzJX0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cHpOR5/btsEZbVSkIB/OxgKl8ParyjEVTQEXLzJX0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cHpOR5/btsEZbVSkIB/OxgKl8ParyjEVTQEXLzJX0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcHpOR5%2FbtsEZbVSkIB%2FOxgKl8ParyjEVTQEXLzJX0%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;1100&quot; height=&quot;400&quot; data-filename=&quot;Untitled 1.png&quot; data-origin-width=&quot;1100&quot; data-origin-height=&quot;400&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;RedLock에는 기본으로 제공하는 펜싱 토큰 기능이 없으므로, 클라이언트에서 네트워크 문제로 인해 경쟁 상태(race condition)가 발생하여 동시성 문제가 발생할 수 있다. 해당 문제를 해결하기 위해 Redis의 단일 노드에 카운터를 관리하며 단일 장애 지점이 되어 해당 레디스가 사이드 이펙트가 매우 커지는 경우가 있을수 있다. 여러 노드에 카운터를 유지하면서 카운터가 동기화되지 않을 수 있다.&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;Reference.&lt;/p&gt;
&lt;figure id=&quot;og_1708303900075&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;How to do distributed locking &amp;mdash; Martin Kleppmann&amp;rsquo;s blog&quot; data-og-description=&quot;How to do distributed locking Published by Martin Kleppmann on 08 Feb 2016. As part of the research for my book, I came across an algorithm called Redlock on the Redis website. The algorithm claims to implement fault-tolerant distributed locks (or rather, &quot; data-og-host=&quot;martin.kleppmann.com&quot; data-og-source-url=&quot;https://martin.kleppmann.com/2016/02/08/how-to-do-distributed-locking.html&quot; data-og-url=&quot;https://martin.kleppmann.com/2016/02/08/how-to-do-distributed-locking.html&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bBWC1X/hyVjmHxxTJ/rSxKWuV66RSB7wNiYFL1bk/img.png?width=1100&amp;amp;height=400&amp;amp;face=0_0_1100_400,https://scrap.kakaocdn.net/dn/wgbZ7/hyVjlojamX/A61E9HkfkKikoz5B0zf611/img.png?width=1100&amp;amp;height=400&amp;amp;face=0_0_1100_400&quot;&gt;&lt;a href=&quot;https://martin.kleppmann.com/2016/02/08/how-to-do-distributed-locking.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://martin.kleppmann.com/2016/02/08/how-to-do-distributed-locking.html&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bBWC1X/hyVjmHxxTJ/rSxKWuV66RSB7wNiYFL1bk/img.png?width=1100&amp;amp;height=400&amp;amp;face=0_0_1100_400,https://scrap.kakaocdn.net/dn/wgbZ7/hyVjlojamX/A61E9HkfkKikoz5B0zf611/img.png?width=1100&amp;amp;height=400&amp;amp;face=0_0_1100_400');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;How to do distributed locking &amp;mdash; Martin Kleppmann&amp;rsquo;s blog&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;How to do distributed locking Published by Martin Kleppmann on 08 Feb 2016. As part of the research for my book, I came across an algorithm called Redlock on the Redis website. The algorithm claims to implement fault-tolerant distributed locks (or rather,&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;martin.kleppmann.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>DB</category>
      <category>Redis</category>
      <category>redisLock</category>
      <category>redLock</category>
      <author>큐범</author>
      <guid isPermaLink="true">https://kbcoding.tistory.com/126</guid>
      <comments>https://kbcoding.tistory.com/126#entry126comment</comments>
      <pubDate>Mon, 19 Feb 2024 09:52:51 +0900</pubDate>
    </item>
    <item>
      <title>[DB] PK AutoIncrement VS UUID</title>
      <link>https://kbcoding.tistory.com/124</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;테이블을 설계하는 과정에서 PK에 대한 고민을 많이 갖게 되었다. PK를 부여하는 방식에 여러 방식이 있지만, 대표적인 두가지는 UUID와 AI(Auto Increment)를 대표적으로 사용한다.&amp;nbsp;&lt;br&gt;나는 현재 AI(Auto Increment)를 사용 중이다. AI를 선택하게 된 이유는 현재 서비스는 하나의 데이터베이스에서 서비스를 운영중이기에 PK생성을 DBMS에 이관하여도 괜찮다고 판단하였다. &lt;b&gt;하지만, 여러개의 DBMS에서 사용할 경우 한 row의 고유한 값을 보장할 수 없다.&lt;/b&gt;&lt;br&gt;&amp;nbsp;&lt;br&gt;해당 고민을 하면서 AI와 UUID에 대한 어떠한 트레이드 오프가 있는지 정리해보고자 한다.&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;h2 data-ke-size=&quot;size26&quot;&gt;Auto Increment&lt;/h2&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;데이터베이스에서 사용되는 속성으로, 특정 필드의 값이 자동으로 증가하는 기능이며 해당 기능은 테이블에 새로운 레코드를 추가할 때마다 해당 필드의 값이 자동으로 증가하게 된다. 예를들어, 사용자 정보를 저장하는 테이블에서 각 사용자에게 고유한 ID를 부여하고 싶을 때 'autoincrement' 속성을 사용할 수 있다. 처음 사용자가 추가되면 ID는 1로 설정되며, 다음 사용자가 추가될 때 ID는 자동으로 2가 된다.&lt;/p&gt;&lt;h3 data-ke-size=&quot;size23&quot;&gt;Auto Increment를 PK로 설정할 경우 이점&lt;/h3&gt;&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt; 
 &lt;li&gt;성능 최적화 : 많은 데이터베이스 시스템에서, 연속된 정수 값으로 구성된 기본 키는 인덱싱 및 조회 성능에 이점을 제공할 수 있다. 인덱스의 이점을 가지고 있다. 
  &lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt; 
   &lt;li&gt;MySQL의 기본 엔진인 InnoDB는 B+tree 구조로 이루어져 있는데 해당 구조는 UUID에 비해 Auto Increment가 성능의 이점을 가진다.&lt;/li&gt; 
   &lt;li&gt;UUID는 16Byte의 길이를 가진 문자열은 대표적인 Int(4Byte) or Long(8Byte)에 비해 속도가 느려 Auto Increment가 성능의 이점을 가진다.&amp;nbsp;&lt;/li&gt; 
  &lt;/ul&gt; &lt;/li&gt; 
 &lt;li&gt;고유성 보장 : 자동으로 값을 증가시켜 중복 없이 고유한 값을 생성하므로, 이를 기본 키로 사용할 경우 중복된 값을 걱정할 필요가 없다.&lt;/li&gt; 
&lt;/ul&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;&lt;h2 data-ke-size=&quot;size26&quot;&gt;UUID(Universally Unique Identifier)&lt;/h2&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;네트워크상에서 고유성을 보장하는 ID 표준 규약으로 UUID는 여러 시스템에서 객체나 정보를 고유하게 식별하는 데 사용될 수 있는 고유한 ID를 제공하기 위해 설계되었다.&lt;/p&gt;&lt;h3 data-ke-size=&quot;size23&quot;&gt;UUID의 버전별 특징&lt;/h3&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;버전&amp;nbsp;1:&amp;nbsp;현재의&amp;nbsp;타임스탬프와&amp;nbsp;MAC&amp;nbsp;주소를&amp;nbsp;기반으로&amp;nbsp;생성&lt;br&gt;버전&amp;nbsp;2:&amp;nbsp;DCE&amp;nbsp;보안의&amp;nbsp;특정&amp;nbsp;값과,&amp;nbsp;타임스탬프&amp;nbsp;및&amp;nbsp;MAC&amp;nbsp;주소를&amp;nbsp;기반으로&amp;nbsp;생성&lt;br&gt;버전&amp;nbsp;3:&amp;nbsp;이름&amp;nbsp;기반&amp;nbsp;UUID로,&amp;nbsp;MD5&amp;nbsp;해시를&amp;nbsp;사용&lt;br&gt;버전&amp;nbsp;4:&amp;nbsp;무작위&amp;nbsp;생성&lt;br&gt;버전&amp;nbsp;5:&amp;nbsp;이름&amp;nbsp;기반&amp;nbsp;UUID로,&amp;nbsp;SHA-1&amp;nbsp;해시를&amp;nbsp;사용&lt;br&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 data-ke-size=&quot;size23&quot;&gt;UUID를 PK로 설정할 경우 이점&lt;/h3&gt;&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;li&gt;전역적 고유성(Global Uniqueness) : UUID는 전 세계적으로 고유한 값을 가지기에 여러 데이터베이스나 시스템 간의 데이터를 병합하거나 이동할 때 기본 키 충돌의 위험이 매우 적다.&lt;/li&gt;&lt;li&gt;중앙 관리 불필요 : UUID는 중앙에서의 관리나 생성 없이도 고유한 값을 생성할 수 있다. 따라서, 분산된 시스템에 유용하며, 클라이언트에서 직접 레코드의 키를 생성할 수 있다.&lt;/li&gt;&lt;li&gt;비 예측 값 : UUID는 무작위 생성으로 Auto Incremet와 달리 이전과 이후 레코드의 고유 값을 알 수 없기에 보안성을 상승시킨다.&lt;/li&gt;&lt;li&gt;데이터베이스 독립적, 복제 및 백업 용이성....&lt;/li&gt;&lt;li&gt;단점: 크기, 성능, 가독성&lt;/li&gt;&lt;/ul&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;&lt;h2 data-ke-size=&quot;size26&quot;&gt;결론&lt;/h2&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;나는 데이터베이스를 설계할 기회가 있어 한다면, 요구사항에 MSA가 없고 한 테이블에 40억 row가 생길 일이 없다면 Auto Increment로 설정한다. 그 이유는 UUID는 16Byte로 인덱스 성능 저하를 초래하며 가독성이 안좋다는 것은 개발자 입장에서 매우 큰 단점을 가진다.&lt;br&gt;예를들어 A라는 개발자가 B라는 개발자에게 132번 Row를 확인하라고 하는 것과 550e8400-e29b-41d4-a716-446655440000의 Row를 확인하라는 것은 생각보다 많은 리소스가 소모된다.&lt;br&gt;그럼 무조건 적으로 PK에는 Auto Increment가 옳은 것인가? 그렇지는 않다. 요구사항에 MSA가 있어 다양한 데이터베이스를 사용하며 UUID를 사용한다면 시스템의 전체 데이터베이스의 각각의 Row의 고유성을 가지기에 서버간 통신에도 많은 안전성을 가져다준다. 또한, 개발 도중에 데이터베이스를 변경해야하는 경우가 있다면 UUID가 Auto Increment에 비해 종속성이 매우 낮다.&lt;br&gt;&amp;nbsp;&lt;br&gt;해당 케이스도 Trade-Off 관계로 모든 개발은 Trade-Off 관계에서 적절한 관계를 찾아야한다.&lt;br&gt;&lt;b&gt;상황에 맞게 사용하는 것이 무엇보다 중요하다.&lt;/b&gt;&lt;/p&gt;</description>
      <category>DB</category>
      <category>autoincrement</category>
      <category>DB</category>
      <category>PK</category>
      <category>UUID</category>
      <author>큐범</author>
      <guid isPermaLink="true">https://kbcoding.tistory.com/124</guid>
      <comments>https://kbcoding.tistory.com/124#entry124comment</comments>
      <pubDate>Sat, 19 Aug 2023 23:15:09 +0900</pubDate>
    </item>
    <item>
      <title>[DB] MySQL 내부 엔진</title>
      <link>https://kbcoding.tistory.com/123</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;강의를 듣던 중 MySQL 서버의 내부를 소개해주는 내용이 있어 정리하고자 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MySQL은 오픈 소스 관계형 데이터베이스 관리 시스템(RDBMS)이다. MySQL은 웹 애플리케이션을 위한 데이터베이스로 특히 많이 사용된다.&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;MySQL 아키텍처&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-08-05 오후 12.54.38.png&quot; data-origin-width=&quot;689&quot; data-origin-height=&quot;327&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d95wWR/btsqd4oHoKh/bESYoDd5ZxvVpTXXsgX05K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d95wWR/btsqd4oHoKh/bESYoDd5ZxvVpTXXsgX05K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d95wWR/btsqd4oHoKh/bESYoDd5ZxvVpTXXsgX05K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd95wWR%2Fbtsqd4oHoKh%2FbESYoDd5ZxvVpTXXsgX05K%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;327&quot; data-filename=&quot;스크린샷 2023-08-05 오후 12.54.38.png&quot; data-origin-width=&quot;689&quot; data-origin-height=&quot;327&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;h3 data-ke-size=&quot;size23&quot;&gt;MySQL 엔진 내부&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면 MySQL 엔진의 내부는 다음과 같이 쿼리 파서, 전처리기, 옵티마이저, 쿼리실행기를 거쳐서 스토리지 엔진으로 넘어간다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-08-05 오후 12.56.48.png&quot; data-origin-width=&quot;651&quot; data-origin-height=&quot;308&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lSqsZ/btsqd3pNfPf/vlHomNYKPoeA08tjyoSrQk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lSqsZ/btsqd3pNfPf/vlHomNYKPoeA08tjyoSrQk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lSqsZ/btsqd3pNfPf/vlHomNYKPoeA08tjyoSrQk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlSqsZ%2Fbtsqd3pNfPf%2FvlHomNYKPoeA08tjyoSrQk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;651&quot; height=&quot;308&quot; data-filename=&quot;스크린샷 2023-08-05 오후 12.56.48.png&quot; data-origin-width=&quot;651&quot; data-origin-height=&quot;308&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 글에서는 MySQL 엔진 내부에서 어떠한 역할을 하는지 확인하려한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;쿼리파서&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;SQL을 파싱하여 Syntax Tree를 만든다.&lt;/li&gt;
&lt;li&gt;이 과정에서 문법 오류 검사가 이루어진다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;전처리기&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;쿼리파서에서 만든 Tree를 바탕으로 전처리 시작한다.&lt;/li&gt;
&lt;li&gt;이블이나 컬럼 존재 여부, 접근권한 등 Semantic 오류 검사를 진행한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쿼리파서와 전처리기는 컴파일 과정과 매우 유사하지만, SQL은 프로그래밍 언어처럼 컴파일 타임때 검증할 수 없어 매번 구문 평가를 진행한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;옵티마이저&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;쿼리를 처리하기 위한 여러 방법들을 만들고, 각 방법들의 비용 정보와 테이블의 통계정보를 이용해 비용을 산정한다.&lt;/li&gt;
&lt;li&gt;테이블 순서, 불필요한 조건 제거, 통계정보를 바탕으로 전략을 결정한다. (실행 계획 수립)&lt;/li&gt;
&lt;li&gt;옵티마이저가 어떤 전략을 결정하느냐에 따라 성능이 많이 달라진다.&lt;/li&gt;
&lt;li&gt;가끔씩 성능이 나쁜 판단을 해 개발자가 힌트를 사용해 도움을 줄 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MySQL 캐시&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;MySQL 5.0 까지는 쿼리 캐시라는 것이 있었으나, 8.0대에 들어와서는 쿼리 캐시가 폐기되었다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;파싱&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;소프트 파싱: SQL, 실행 계획을 캐시에서 찾아 옵티마이저 과정을 생략하고 실행 단계로 넘어간다.&lt;/li&gt;
&lt;li&gt;하드 파싱: SQL, 실행 계획을 캐시에서 찾지못해 옵티마이저 과정을 거치고나서 실행 단계로 넘어간다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MySQL에는 소프트 파싱이 없다. 하지만, 5버전 까지는 쿼리 캐시가 있었다. 쿼리 캐시는 SQL에 해당 데이터를 저장하는 것인데 데이터를 캐시하기 때문에 테이블의 데이터가 변경되면 캐시의 데이터도 함께 갱신시켜줘야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Oracle에는 소프트 파싱이 존재한다. 실행계획까지만 캐싱을 진행하고, 모든 SQL 매핑하여 데이터까지 캐싱하지는 않는다. 하지만, 힌트나 설정으로 가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;쿼리 캐시 결론&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;MySQL의 쿼리캐시, Oracle의 소프트 파싱 모두 성능 최적화를 위해 캐시라는 기술을 도입한 사례이다. 하지만, 캐시의 범위가 각 다르다. 캐시를 도입할때는 항상 만료 정책을 고려해야하며 쿼리캐시는 소프트 파싱에 비해 조회성능은 더 높지만 캐시 데이터 관리에 더 높은 비용이 들어간다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;스토리지 엔진&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;디스크에서 데이터를 가져오거나 저장하는 역할을 한다.&lt;/li&gt;
&lt;li&gt;MySQL 스토리지 엔진은 플러그인 형태로 Handler API만 맞춘다면 직접 구현해서 사용할 수 있다.&lt;/li&gt;
&lt;li&gt;InnoDB, MyIsam 등 여러개의 스토리지 엔진이 존재한다.&lt;/li&gt;
&lt;li&gt;8.0 버전 부터는 InnoDB 엔진이 디폴트이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;InnoDB&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;InnoDB는 MySQL의 기본 스토리지 엔진입니다. 이 엔진은 트랜잭션-세이프(transaction-safe) 기능을 제공하며, 대규모 데이터베이스 시스템에서 높은 성능과 확장성을 제공하기 위해 설계되었습니다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;트랜잭션 지원: InnoDB는 완전한 ACID(원자성, 일관성, 고립성, 지속성) 호환 트랜잭션을 지원합니다. 이는 트랜잭션 중 하나라도 실패하면 변경 사항을 롤백(undo)하고, 모든 트랜잭션이 성공적으로 완료되면 커밋(commit)하는 기능을 의미합니다.&lt;/li&gt;
&lt;li&gt;행 수준 잠금: InnoDB는 동시성을 높이기 위해 행 수준의 잠금을 지원합니다. 이는 여러 사용자가 동시에 다른 행에 접근할 수 있게 해주어 성능을 향상시킵니다.&lt;/li&gt;
&lt;li&gt;외래 키 지원: InnoDB는 외래 키(foreign key) 제약 조건을 지원합니다. 이는 한 테이블의 데이터가 다른 테이블의 데이터에 의존할 때 데이터 무결성을 보장하는 데 도움이 됩니다.&lt;/li&gt;
&lt;li&gt;MVCC(Multi-Version Concurrency Control): InnoDB는 MVCC를 사용하여 여러 트랜잭션이 동시에 같은 데이터에 접근할 수 있도록 합니다. 이는 읽기와 쓰기 동작간의 잠금 경합을 줄이며, 동시성을 높이는 데 도움이 됩니다.&lt;/li&gt;
&lt;li&gt;크래시 복구 기능: InnoDB는 트랜잭션 로그와 체크포인트를 사용하여 시스템 장애 후에도 데이터를 안전하게 복구할 수 있습니다.&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Reference.&lt;/p&gt;
&lt;figure id=&quot;og_1691209525347&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;백엔드 개발자를 위한 한 번에 끝내는 대용량 데이터 &amp;amp; 트래픽 처리 초격차 패키지 Online.  | 패스&quot; data-og-description=&quot;데이터 처리 4대장 : MySQL, MongoDB, Kafka, Redis 외 31가지 기술스택 활용을 담은 초격차 강의! 실무 경험에 기반한 18가지 Use Case와 105개 실습 클립으로 대용량 테이터 &amp;amp; 처리를 완벽하게 경험해보세요!&quot; data-og-host=&quot;fastcampus.co.kr&quot; data-og-source-url=&quot;https://fastcampus.co.kr/dev_online_bedata&quot; data-og-url=&quot;https://fastcampus.co.kr/dev_online_bedata&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bSCITF/hyTx2DiTMp/7hKgMhi8Dm96klKrtZlEq1/img.png?width=1200&amp;amp;height=631&amp;amp;face=0_0_1200_631&quot;&gt;&lt;a href=&quot;https://fastcampus.co.kr/dev_online_bedata&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://fastcampus.co.kr/dev_online_bedata&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bSCITF/hyTx2DiTMp/7hKgMhi8Dm96klKrtZlEq1/img.png?width=1200&amp;amp;height=631&amp;amp;face=0_0_1200_631');&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;백엔드 개발자를 위한 한 번에 끝내는 대용량 데이터 &amp;amp; 트래픽 처리 초격차 패키지 Online. | 패스&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;데이터 처리 4대장 : MySQL, MongoDB, Kafka, Redis 외 31가지 기술스택 활용을 담은 초격차 강의! 실무 경험에 기반한 18가지 Use Case와 105개 실습 클립으로 대용량 테이터 &amp;amp; 처리를 완벽하게 경험해보세요!&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;fastcampus.co.kr&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>DB</category>
      <category>mysql</category>
      <category>mysql innodb</category>
      <category>쿼리캐시</category>
      <author>큐범</author>
      <guid isPermaLink="true">https://kbcoding.tistory.com/123</guid>
      <comments>https://kbcoding.tistory.com/123#entry123comment</comments>
      <pubDate>Sat, 5 Aug 2023 13:23:37 +0900</pubDate>
    </item>
    <item>
      <title>[모니터링] loki, Promtail를 통해 log 모니터링</title>
      <link>https://kbcoding.tistory.com/122</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;프로젝트를 진행하면서 어플리케이션, CPU 모니터링에 대해서는 진행중이었으나 WAS에 에러가 발생하면 이를 로컬 환경에서 같이 에러시연을 하는데 문제는 에러 시연이 발생하지 않는 경우에 로그를 직접 보거나 프로세스의 콘솔을 확인하는 상황도 종종 발생했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Log 모니터링을 찾아보던 중 elasticsearch와 Loki가 나왔다. 현재 프로젝트에는 grafana가 적용되어 있고 이를 기반으로 작성하기는 loki가 더욱 적용하기 편해보였다.&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;Loki&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;730&quot; data-origin-height=&quot;197&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/6rcBT/btskgdUI815/V5oT30fUoUPIfvkHg3pkkK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/6rcBT/btskgdUI815/V5oT30fUoUPIfvkHg3pkkK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/6rcBT/btskgdUI815/V5oT30fUoUPIfvkHg3pkkK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F6rcBT%2FbtskgdUI815%2FV5oT30fUoUPIfvkHg3pkkK%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;730&quot; height=&quot;197&quot; data-origin-width=&quot;730&quot; data-origin-height=&quot;197&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특징&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;수평 확장&lt;/li&gt;
&lt;li&gt;다중 로그 집계 시스템&lt;/li&gt;
&lt;li&gt;대규모 시스템에도 효율적인 데이터 처리&lt;/li&gt;
&lt;li&gt;오픈소스&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;699&quot; data-origin-height=&quot;289&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bsWTTJ/btsknPSiSXR/Zn3K1O6xdqWgD8sDCFekok/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bsWTTJ/btsknPSiSXR/Zn3K1O6xdqWgD8sDCFekok/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bsWTTJ/btsknPSiSXR/Zn3K1O6xdqWgD8sDCFekok/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbsWTTJ%2FbtsknPSiSXR%2FZn3K1O6xdqWgD8sDCFekok%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;699&quot; height=&quot;289&quot; data-origin-width=&quot;699&quot; data-origin-height=&quot;289&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;loki는 promtail을 통해 로그를 가져와서 로그를 저장한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;promtail은 그라파나 로키(Loki)의 로그 수집 에이전트로 사용되는 오픈 소스 소프트웨어이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;역할&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Promtail : 로그 파일이 존재하는 서버에서 로그를 loki로 전송한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Loki : promtail 로그를 수신받아서 이를 저장/분류한다.&lt;/p&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;Promtail을 통해 로그를 loki로 보내고 이를 grafana에서 모니터링 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모든 것은 Docker로 진행된다.&lt;/p&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;본 실습은 grafana가 설치되어 있는 가정 하에 진행한다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. loki 설치&lt;/p&gt;
&lt;pre id=&quot;code_1687133070721&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;wget https://raw.githubusercontent.com/grafana/loki/v2.8.0/cmd/loki/loki-local-config.yaml -O loki-config.yaml
docker run --name loki -d -v $(pwd):/mnt/config -p 3100:3100 grafana/loki:2.8.0 -config.file=/mnt/config/loki-config.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. promtail 설치&lt;/p&gt;
&lt;pre id=&quot;code_1687133088256&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;wget https://raw.githubusercontent.com/grafana/loki/v2.8.0/clients/cmd/promtail/promtail-docker-config.yaml -O promtail-config.yaml
docker run --name promtail -d -v $(pwd):/mnt/config -v /var/log:/var/log --link loki grafana/promtail:2.8.0 -config.file=/mnt/config/promtail-config.yaml&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;lt;현재 실행하는 디렉토리에&amp;gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;promtail-config.yaml과 loki-config.yaml이 있어야한다.&lt;/p&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;datasources -&amp;gt; add new data source&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;702&quot; data-origin-height=&quot;96&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cGhmcI/btskhDk4Vme/HIJJrCHk9N2uW55EQMD9KK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cGhmcI/btskhDk4Vme/HIJJrCHk9N2uW55EQMD9KK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cGhmcI/btskhDk4Vme/HIJJrCHk9N2uW55EQMD9KK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcGhmcI%2FbtskhDk4Vme%2FHIJJrCHk9N2uW55EQMD9KK%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;702&quot; height=&quot;96&quot; data-origin-width=&quot;702&quot; data-origin-height=&quot;96&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. URL에 IP:3100하고 Save&amp;amp;Test 진행&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;707&quot; data-origin-height=&quot;702&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bai9xb/btskrnBeqsi/PP3hfWhDdM9j9J6w8SVIbK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bai9xb/btskrnBeqsi/PP3hfWhDdM9j9J6w8SVIbK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bai9xb/btskrnBeqsi/PP3hfWhDdM9j9J6w8SVIbK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbai9xb%2FbtskrnBeqsi%2FPP3hfWhDdM9j9J6w8SVIbK%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;707&quot; height=&quot;702&quot; data-origin-width=&quot;707&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;추가로 Auth가 있다면 Basic Auth로 설정하면 된다.&lt;/p&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 data-ke-size=&quot;size16&quot;&gt;Explore에서 Loki를 선택 후 원하는 로그 파일을 확인한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1780&quot; data-origin-height=&quot;1227&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/0sPVf/btskuXCgeOZ/5v18KlpGShXkJwVrqjT631/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/0sPVf/btskuXCgeOZ/5v18KlpGShXkJwVrqjT631/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/0sPVf/btskuXCgeOZ/5v18KlpGShXkJwVrqjT631/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F0sPVf%2FbtskuXCgeOZ%2F5v18KlpGShXkJwVrqjT631%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;1780&quot; height=&quot;1227&quot; data-origin-width=&quot;1780&quot; data-origin-height=&quot;1227&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추가 경로 설정 원할 경우&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;promtail-config.yaml&lt;/p&gt;
&lt;pre id=&quot;code_1687133590369&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;server:
  http_listen_port: 9080
  grpc_listen_port: 0

positions:
  filename: /tmp/positions.yaml

clients:
  - url: http://loki:3100/loki/api/v1/push

scrape_configs:
- job_name: system
  static_configs:
  - targets:
      - localhost
    labels:
      job: varlogs # 로그 파일 수집 모음
      __path__: /var/log/*log # 로그파일 경로
  - targets: #example
      - localhost
    labels:
      job: WAS-LOG
      __path__: /var/log/was/*log&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추가 로그를 설정 후 컨테이너를 재시작해주면 적용된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공식문서(꼭 확인!)&lt;/p&gt;
&lt;figure id=&quot;og_1687133605814&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;Install Grafana Loki with Docker or Docker Compose |  Grafana Loki documentation&quot; data-og-description=&quot;Open source Install Grafana Loki with Docker or Docker Compose You can use Grafana Cloud to avoid installing, maintaining, and scaling your own instance of Grafana Loki. Create a free account to get started, which includes free forever access to 10k metric&quot; data-og-host=&quot;grafana.com&quot; data-og-source-url=&quot;https://grafana.com/docs/loki/latest/installation/docker/&quot; data-og-url=&quot;https://grafana.com/docs/loki/latest/installation/docker/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/k0G9F/hyS2A0MfKy/XY66knvd6BISnx6kJvKDlk/img.jpg?width=1200&amp;amp;height=700&amp;amp;face=0_0_1200_700,https://scrap.kakaocdn.net/dn/1oMSC/hyS2HlgYCA/7VRfVCtcIna8f6qresKsMk/img.jpg?width=1200&amp;amp;height=700&amp;amp;face=0_0_1200_700&quot;&gt;&lt;a href=&quot;https://grafana.com/docs/loki/latest/installation/docker/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://grafana.com/docs/loki/latest/installation/docker/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/k0G9F/hyS2A0MfKy/XY66knvd6BISnx6kJvKDlk/img.jpg?width=1200&amp;amp;height=700&amp;amp;face=0_0_1200_700,https://scrap.kakaocdn.net/dn/1oMSC/hyS2HlgYCA/7VRfVCtcIna8f6qresKsMk/img.jpg?width=1200&amp;amp;height=700&amp;amp;face=0_0_1200_700');&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;Install Grafana Loki with Docker or Docker Compose | Grafana Loki documentation&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Open source Install Grafana Loki with Docker or Docker Compose You can use Grafana Cloud to avoid installing, maintaining, and scaling your own instance of Grafana Loki. Create a free account to get started, which includes free forever access to 10k metric&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;grafana.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>Cloud</category>
      <category>Grafana</category>
      <category>Loki</category>
      <category>Monitoring</category>
      <author>큐범</author>
      <guid isPermaLink="true">https://kbcoding.tistory.com/122</guid>
      <comments>https://kbcoding.tistory.com/122#entry122comment</comments>
      <pubDate>Mon, 19 Jun 2023 09:13:36 +0900</pubDate>
    </item>
    <item>
      <title>[강의 후기] Practical Testing: 실용적인 테스트 가이드 후기</title>
      <link>https://kbcoding.tistory.com/121</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;TDD 스터디를 마치고 실제 회사에서는 어떤 방식으로 테스트를 진행하는지 궁금증을 가지던 중에&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인프런에 테스트에 대한 신규 강의와 수강평이 좋아 수강을 하게 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 글은 내가 테스트 강의를 들으면서 공감이 되는 부분을 중점으로 기술한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;테스트는 왜 필요할까?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;강사의 테스트 생각 : 귀찮다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나의 생각 : 고려해야 할 것이 많다.&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;QA에 대한 테스트&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;커버할 수 없는 영역이 발생한다.&lt;/li&gt;
&lt;li&gt;경험과 감에 의존한다.&lt;/li&gt;
&lt;li&gt;늦은 피드백이 발생한다.&lt;/li&gt;
&lt;li&gt;유지보수의 어려움&lt;/li&gt;
&lt;li&gt;소프트웨어 신뢰도가 낮아진다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;테스트를 하는 이유&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;빠른 피드백&lt;/li&gt;
&lt;li&gt;자동화&lt;/li&gt;
&lt;li&gt;소프트웨어 신뢰도 상승&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;테스트 코드를 작성하지 않을 경우&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;변화가 생기는 매순간마다 발생할 수 있는 모든 Case를 고려해야 한다.&lt;/li&gt;
&lt;li&gt;변화가 생기는 매순간마다 모든 팀원이 동일한 고민을 해야한다.&lt;/li&gt;
&lt;li&gt;빠르게 변화하는 소프트웨어의 안정성을 보장할 수 없다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;테스트 코드가 병목이 된다면&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로덕션 코드의 안정성을 제공하기 힘들어진다.&lt;/li&gt;
&lt;li&gt;테스트 코드 자체가 유지보수하기 어려운, 새로운 짐이 된다.&lt;/li&gt;
&lt;li&gt;잘못된 검증이 이루어질 가능성이 생긴다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;올바른 테스트 코드는&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;자동화 테스트로 비교적 빠른 시간 안에 버그를 발견할 수 있고, 수동 테스트에 드는 비용을 크게 절약할 수 있다.&lt;/li&gt;
&lt;li&gt;소프트웨어의 빠른 변화를 지원한다.&lt;/li&gt;
&lt;li&gt;팀원들의 집단 지성을 팀 차원의 이익으로 승격시킨다.&lt;/li&gt;
&lt;li&gt;가까이 보면 느리지만, 멀리 보면 가장 빠르다. -&amp;gt; 소프트웨어의 검증이 코드로 한번 더 검증이 된다는 것은 질 좋은 소프트웨어임을 증명한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;테스트하기 어려운 영역&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;관측할 때마다 다른 값에 의존하는 코드
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;현재 날짜/시간, 랜덤 값, 전역 변수/함수, 사용자 입력 등&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;외부 세계에 영향을 주는 코드
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;표준 출력, 메시지 발송, 데이터베이스에 기록하기 등&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;강의에서는 LocalDateTime.now()를 사용하지 않고 특정 시점에 대해서 테스트를 했다. 즉, 테스트를 할때마다 변하는 시간에 대해서 테스트를 하는 것은 올바른 설계가 아니다. (물론 예외 상황도 존재할 수 있다)&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;@NotBlank, @NotNull, @NotEmpty&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;@NotNull = &amp;ldquo; &amp;rdquo;&lt;/li&gt;
&lt;li&gt;@NotEmpty = &amp;ldquo;&amp;rdquo;, &amp;ldquo; &amp;ldquo;&lt;/li&gt;
&lt;li&gt;@NotBlank = 문자가 필수로 필요한 경우 (공백을 인정하지 않음)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컨트롤러에 필요한 Validation인지 Service에서 필요한 Validation처리인지 역할을 구분해야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;책임분리를 고려하여 Service의 dto와 controller의 dto를 분리할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 현재까지 @Valid에 대한 테스트를 컨트롤러가 아닌 Service Layer에서 처리했다. 이는 잘못된 설계였다. 강사님은 Controller와 Service에 대한 DTO도 분리하였다. (개인적으로 가장 많이 배운 설계) 객체 지향적 설계로 각각의 Layer는 다른 Layer에 종속적이지 않은 하나의 '모듈'이 되어야한다. Controller의 Request와 Service Request가 동일하지 않게 가져오는 것이 객체지향 SOLID에서 SRP원칙으로 하나의 클래스는 하나의 책임을 가지도록 했다. 하지만, 이는 특정 상황에 필요한 설계로 MSA와 같은 분리가 필요한 상황에서 필요하기에 프로젝트의 성격에 따라 다른 적절한 설계 방식을 사용해야한다.&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;Test Double - 이는 TDD 스터디에서 정리했기에 간단하게 정리한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Dummy : 아무 것도 하지 않는 깡통 객체&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Fake : 단순한 형태로 동일한 기능은 수행하나, 프로덕션에서 쓰기에는 부족한 객체&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Stub : 테스트에서 요청한 것에 대해 미리 준비한 결과를 제공하는 객체 그 외에는 응답하지 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Spy : Stub이면서 호출된 내용을 기록하여 보여줄 수 있는 객체 일부는 실제 객체처럼 일부만 Stubbing 할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Mock : 행위에 대한 기대를 명세하고, 그에 따라 동작하도록 만들어진 객체&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 data-ke-size=&quot;size16&quot;&gt;강사님께서 강의중 가장 많이 이야기한 것은 &quot;테스트는 문서다&quot;이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 새로운 회사에서 개발을 임하면서 테스트에 대해서 깊게 생각을 하게 되었고 실제 다른 회사에서는 어떤 방식으로 테스트를 하는지 궁금하여 수강하게된 강의에서 많은 것을 배우면서 가장 많이 배운 것은 &quot;테스트는 문서의 역할을 가지게 해야한다&quot;이다. 현재 내가 맡은 프로젝트의 이전 개발자는 코드에 대해서 컨벤션도 엉망이며 테스트는 물론 코드에 대한 메타 데이터도 존재하지 않다. 이를 하나하나 이해하며 새롭게 바꾸면서 테스트 코드의 중요성을 깨우치고 있다. 단순히 테스트 코드는 나에게 빌드할때 한번 더 검증하는 수단이었으나, 테스트 코드는 이 프로젝트를 맡게되는 이후의 개발자와의 소통이다. 테스트 코드를 통해 로직의 깊이 있게 검증하며 이해할 수 있다. 실제로, TDD 스터디를 통해 테스트 로직이 얼마나 비즈니스 로직을 이해하는 것에 도움이 된다는 것을 몸소 느겼다. 테스트는 그 어떠한 설명서보다 이해하기 쉽게 만들어지는 소프트웨어의 설명서이다.&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;figure id=&quot;og_1686477323752&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;Practical Testing: 실용적인 테스트 가이드 - 인프런 | 강의&quot; data-og-description=&quot;이 강의를 통해 실무에서 개발하는 방식 그대로, 깔끔하고 명료한 테스트 코드를 작성할 수 있게 됩니다. 테스트 코드가 왜 필요한지, 좋은 테스트 코드란 무엇인지 궁금하신 모든 분을 위한 강&quot; data-og-host=&quot;www.inflearn.com&quot; data-og-source-url=&quot;https://www.inflearn.com/course/practical-testing-%EC%8B%A4%EC%9A%A9%EC%A0%81%EC%9D%B8-%ED%85%8C%EC%8A%A4%ED%8A%B8-%EA%B0%80%EC%9D%B4%EB%93%9C/dashboard&quot; data-og-url=&quot;https://www.inflearn.com/course/practical-testing-%EC%8B%A4%EC%9A%A9%EC%A0%81%EC%9D%B8-%ED%85%8C%EC%8A%A4%ED%8A%B8-%EA%B0%80%EC%9D%B4%EB%93%9C&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/pp2FU/hySW7kx51i/zZhGkEbFS8srmmu8QuKUyK/img.png?width=1200&amp;amp;height=781&amp;amp;face=0_0_1200_781,https://scrap.kakaocdn.net/dn/1EP0x/hySWmwfvkL/9ShhMixksspZHsWpwun2fk/img.png?width=1200&amp;amp;height=781&amp;amp;face=0_0_1200_781,https://scrap.kakaocdn.net/dn/exg7v/hySW0eFhiN/mkAYzVNkunKKiPAFnKy6P1/img.png?width=2772&amp;amp;height=1558&amp;amp;face=0_0_2772_1558&quot;&gt;&lt;a href=&quot;https://www.inflearn.com/course/practical-testing-%EC%8B%A4%EC%9A%A9%EC%A0%81%EC%9D%B8-%ED%85%8C%EC%8A%A4%ED%8A%B8-%EA%B0%80%EC%9D%B4%EB%93%9C/dashboard&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.inflearn.com/course/practical-testing-%EC%8B%A4%EC%9A%A9%EC%A0%81%EC%9D%B8-%ED%85%8C%EC%8A%A4%ED%8A%B8-%EA%B0%80%EC%9D%B4%EB%93%9C/dashboard&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/pp2FU/hySW7kx51i/zZhGkEbFS8srmmu8QuKUyK/img.png?width=1200&amp;amp;height=781&amp;amp;face=0_0_1200_781,https://scrap.kakaocdn.net/dn/1EP0x/hySWmwfvkL/9ShhMixksspZHsWpwun2fk/img.png?width=1200&amp;amp;height=781&amp;amp;face=0_0_1200_781,https://scrap.kakaocdn.net/dn/exg7v/hySW0eFhiN/mkAYzVNkunKKiPAFnKy6P1/img.png?width=2772&amp;amp;height=1558&amp;amp;face=0_0_2772_1558');&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;Practical Testing: 실용적인 테스트 가이드 - 인프런 | 강의&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;www.inflearn.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>TDD</category>
      <category>Practical Testing: 실용적인 테스트 가이드</category>
      <category>Spring boot test</category>
      <category>tdd</category>
      <category>test</category>
      <category>인프런</category>
      <author>큐범</author>
      <guid isPermaLink="true">https://kbcoding.tistory.com/121</guid>
      <comments>https://kbcoding.tistory.com/121#entry121comment</comments>
      <pubDate>Sun, 11 Jun 2023 18:55:52 +0900</pubDate>
    </item>
    <item>
      <title>[DB] 데이터 플랫폼 사업단의 Data 이야기</title>
      <link>https://kbcoding.tistory.com/120</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;회사에서 진행하는 사내 기술 세미나를 참석하게 되어 이를 정리하기로 하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2022년 가트너의 IT 전략 기술 트렌드&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;성장 가속 부문
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;제너레이티브 AI : 제너레이티브 AI는 텍스트 설명을 기반으로 이미지를 생성하는 인공지능 프로그램입니다.&lt;/li&gt;
&lt;li&gt;오토노믹 시스템 : 주위 환경에 맞춰 스스로 관리하는 시스템이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;변화 형성 부문&amp;nbsp;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;컴포저블 애플리케이션 : 비즈니스 중심의 모듈식 컴포넌트로 구성되어 있는 어플리케이션을 뜻한다.&lt;/li&gt;
&lt;li&gt;의사결정 인텔리전스 : 상황에 따라 스스로 일을 결정해 처리함으로써 결정을 돕는 인공지능이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;신뢰 구축 부문
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;데이터 패브릭 : 분산 데이터에 대한 액세스를 최적화하고 데이터 소비자에게 셀프 서비스 제공을 위해 지능적으로 큐레이션 및 오케스트레이션 할 수 있는 데이터 관리 아키텍처이다.&lt;/li&gt;
&lt;li&gt;사이버보안 메시 : 이용자나 신원을 중심으로 보안 경계를 정의해, 독립된 환경과 컴퓨팅 환경에서도 회사 보유 데이터에 안전하게 접근할 수 있도록 해준다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2023년 가트너의 IT 전략 기술 트렌드&lt;/h3&gt;
&lt;ol style=&quot;text-align: start;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;디지털 면역체계&lt;/li&gt;
&lt;li&gt;응용 관측 가능성&lt;/li&gt;
&lt;li&gt;AI 신뢰 위험 보안관리(AI TRiSM)&lt;/li&gt;
&lt;li&gt;산업 클라우드 플랫폼&lt;/li&gt;
&lt;li&gt;플랫폼 엔지니어링&lt;/li&gt;
&lt;li&gt;무선 가치 실현&lt;/li&gt;
&lt;li&gt;슈퍼앱&lt;/li&gt;
&lt;li&gt;적응형 AI&lt;/li&gt;
&lt;li&gt;메타버스 (사업단의 핵심) : &quot;디지털 화폐와 대체불가능한 토큰(NFT)으로 구현되는 자체적 가상 경제를 갖출 것이다.&quot;&lt;/li&gt;
&lt;li&gt;지속가능한 기술&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;데이터의 과거와 현재&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;과거에는 데이터와 콘텐츠의 개념을 구분한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 현재는 데이터 콘텐츠가 포함되고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;과거에는 데이터와 정보의 개념을 구분해서 생각한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;데이터 : 데이터는 발생한 상태 그대로 기록한 것이다.&lt;/li&gt;
&lt;li&gt;정보 : 의도를 가지고 데이터를 가공한 결과&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재는 데이터와 정보를 엄격하게 구분하지 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 처리시간의 감소와 단계의 축소&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;데이터 웨어하우스의 용어와 의미&lt;/h3&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;rarr; 데이터 웨어하우스 &amp;rarr; 데이터 소비자&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;빅데이터의 등장과 문제점&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제 발생 : 비구조적 데이터를 DW에 쌓을 수 없다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;DW에 보관하기 위해서는 데이터 식별자와 데이터 형태 등을 정해야한다.&lt;/li&gt;
&lt;li&gt;비구조적 데이터는 사이즈가 너무 크다.&lt;/li&gt;
&lt;li&gt;DW에 담기에는 비용이 비싸진다.&lt;/li&gt;
&lt;li&gt;발생한 데이터를 화용하지 못하고 버릴 수는 없다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;데이터 레이크의 등장&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터를 가공하여 사용할 수 있는 형태로 보관하기 보다는 발생한 모습 그대로 일단 한 곳에 모아두고 필요할 때 가공하여 사용하자는 것&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;레이크, 즉 호수는 모든 강에서 흘러 들어오는 물줄기를 버리지 않고 일단 담아둔다는 의미와 상통한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사전처리보다 필요시 처리하는 데이터 레이크가 더 비용적으로 효율적이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터 레이크는 대규모 데이터를 수집하고 저장하는 고도로 확장 가능한 저장소다. 데이터 레이크는 다양한 형식의 데이터를 수집하고 저장하며, 원시 형식으로 저장된다. 이는 데이터의 유연성과 다양성을 보장하며, 데이터가 수집되는 단계에서부터 분석 및 가공이 필요한 시점까지의 모든 단계에서 데이터를 보존한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;데이터 카탈로그의 등장&lt;/h3&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;데이터 카탈로그는 조직 내의 데이터 자원을 관리하는 중앙 집중식 메타데이터 저장소다. 데이터 카탈로그는 데이터 레이크 및 다른 데이터 소스에서 추출된 데이터에 대한 메타데이터를 기록하고 관리한다. 이는 데이터의 검색, 이해, 공유 및 재사용을 용이하게 한다. 데이터 카탈로그는 데이터의 위치, 보안 정책, 데이터 소유자 등의 정보를 추적하며, 데이터에 대한 검색 및 엑세스를 표준화한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3가지 메타데이터의 조합&lt;/h3&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;비즈니스 메타데이터 :&amp;nbsp;데이터의 비즈니스적 의미와 관련된 정보를 담고 있다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p style=&quot;color: #1a1b1f; text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>DB</category>
      <category>data</category>
      <category>nft</category>
      <category>데이터레이크</category>
      <category>데이터카탈로그</category>
      <category>메타데이터</category>
      <author>큐범</author>
      <guid isPermaLink="true">https://kbcoding.tistory.com/120</guid>
      <comments>https://kbcoding.tistory.com/120#entry120comment</comments>
      <pubDate>Sat, 20 May 2023 15:44:59 +0900</pubDate>
    </item>
    <item>
      <title>[TDD] 테스트 범위와 종류</title>
      <link>https://kbcoding.tistory.com/119</link>
      <description>&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-filename=&quot;스크린샷 2023-03-06 오전 12.53.42.png&quot; data-origin-width=&quot;524&quot; data-origin-height=&quot;329&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/1NC8z/btr1XQhJAhf/jrXc6pFajLubFub8WlkPi0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/1NC8z/btr1XQhJAhf/jrXc6pFajLubFub8WlkPi0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/1NC8z/btr1XQhJAhf/jrXc6pFajLubFub8WlkPi0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F1NC8z%2Fbtr1XQhJAhf%2FjrXc6pFajLubFub8WlkPi0%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;524&quot; height=&quot;329&quot; data-filename=&quot;스크린샷 2023-03-06 오전 12.53.42.png&quot; data-origin-width=&quot;524&quot; data-origin-height=&quot;329&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하나의 기능이 올바르게 동작하려면 컨트롤러, 서비스, 모델과 같은 자바 코드와 프레임워크, 설정에 문제가 없어야 할 뿐 아니라 브라우저에서 실행되는 자바스크립트 코드, HTML과 CSS 등이 정상 동작해야 한다. 또한, DB의 테이블도 올바르게 생성해야한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;기능 테스트와 E2E테스트&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기능 테스트(Functional Testing)는 사용자 입장에서 시스템이 제공하는 기능이 올바르게 동작하는지 확인한다. 이 테스트를 수행하려면 시스템을 구동하고 사용하는데 필요한 모든 구성요소가 필요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기능 테스트는 사용자가 직접 사용하느 웹 브라우저나 모바일 앱부터 시작해서 데이터베이스나 외부 서비스에 이르기까지 모든 구성 요소를 하나로 엮어서 진행한다. 기능 테스트는 끝에서 끝가지 올바른지 검사하기 때문에 E2E(End to End)테스트로도 볼 수 있다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;통합테스트&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;통합 테스트(Integration Testing)는 시스템의 각 구성 요소가 올바르게 연동되는지 확인한다. 기능 테스트가 사용자 입장에서 테스트하는데 반해 통합 테스트는 소프트웨어의 코드를 직접 테스트한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;단위 테스트&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단위 테스트(Unit Testing)는 개별 코드나 컴포넌트가 기대한대로 동작하는지 확인한다. 지금까지 이 책에서 살펴본 테스트가 주로 단위 테스트 코드이다. 단위 테스트는 한 클래스나 한 메서드와 같은 작은 범위를 테스트한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;테스트 범위 간 차이&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;통합 테스트를 실행하려면 DB나 캐시 서버와 같은 연동 대상을 구성해야 한다. 기능 테스트를 실행하려면 웹 서버를 구동하거나 모바일 앱을 폰에 설치해야 할 수도 있다. 또한, 통합 테스트나 기능 테스트는 테스트 상황을 만들어내기 위해 많은 노력이 필요하다. 반면에 단위 테스트는 테스트 코드를 빼면 따로 준비할 것이 없다.&lt;/li&gt;
&lt;li&gt;통합 테스트는 DB 연결, 소켓 통신, 스프링 컨테이너 초기화와 같이 테스트 실행 속도를 느리게 만드는 요인이 많다. 기능 테스트는 추가로 브라우저나 앱을 구동하고 화면의 흐름에 따라 알맞은 상호 작용을 해야 한다. 반면에 단위 테스트는 서버를 구동하거나 DB를 준비할 필요가 없다. 테스트 대상이 의존하는 기능을 대역으로 처리하면 되므로 테스트 실행 속도가 빠르다.&lt;/li&gt;
&lt;li&gt;통합 테스트나 기능 테스트로는 상황을 준비하거나 결과 확인이 어렵거나 불가능할 때가 있다. 외부 시스템과 연동해야 하는 기능이 특히 그렇다. 이런 경우에는 단위 테스트와 대역을 조합해서 상황을 만들고 결과를 확인해야 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;테스트 범위에 따른 테스트 코드 개수와 시간&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;테스트를 자동화한다는 것은 결국 코드로 작성한 테스트를 실행한다는 것을 의미한다. 통합 테스트는 기능 테스트에 비해 제약이 덜하다. 단위 테스트는 통합 테스트로도 만들기 힘든 상황을 쉽게 구성할 수 있다. 기능테스트나 통합 테스트에서 모든 예외 상황을 테스트하면 단위 테스트는 줄어든다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;외부 연동이 필요한 테스트 예&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모든 외부 연동 대상을 통합 테스트에서 다룰수 없지만 일부 외부 대상은 어느정도 수준에서 제어가 가능하다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;WireMock을 이용한 REST 클라이언트 테스트&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;통합 테스트 하기 어려운 대상이 외부서버이다. WireMock을 사용하면 서버 API를 스텁으로 대체할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;WireMockServer는 HTTP 서버를 흉내 낸다.&lt;/b&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;테스트 실행 전에 WireMockServer를 시작한다. 실제 HTTP 서버가 뜬다.&lt;/li&gt;
&lt;li&gt;테스트에서 WireMockServer의 동작을 기술한다.&lt;/li&gt;
&lt;li&gt;HTTP 연동을 수행하는 테스트를 실행한다.&lt;/li&gt;
&lt;li&gt;테스트 실행 후에 WireMockServer를 중지한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;스프링 부트의 내장 서버를 이용한 API 기능 테스트&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스프링 부트를 사용한다면 API에 대한 테스트를 JUnit 코드로 작성 할 수 있다.&lt;/p&gt;
&lt;p data-ke-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;Refence.&lt;/p&gt;
&lt;div&gt;
&lt;figure id=&quot;og_1678031672678&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;book&quot; data-og-title=&quot;테스트 주도 개발 시작하기 - YES24&quot; data-og-description=&quot;TDD(Test-Driven Development)는 테스트부터 시작한다. 구현을 먼저 하고 나중에 테스트하는 것이 아니라 먼저 테스트를 하고 그다음에 구현한다. 구현 코드가 없는데 어떻게 테스트할 수 있을까? 여기&quot; data-og-host=&quot;www.yes24.com&quot; data-og-source-url=&quot;http://www.yes24.com/Product/Goods/89145195&quot; data-og-url=&quot;http://www.yes24.com/Product/Goods/89145195&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/4XIVy/hyRwE5pJRQ/875syyPkf3KKmkkxfMPOD1/img.jpg?width=872&amp;amp;height=1200&amp;amp;face=0_0_872_1200,https://scrap.kakaocdn.net/dn/f6K6r/hyRwE5pJWD/V8ngxu85qDA913HN5AnEWK/img.jpg?width=872&amp;amp;height=1200&amp;amp;face=0_0_872_1200,https://scrap.kakaocdn.net/dn/BSM0l/hyRwzQypUz/8ExVV58VPrIq3kXEB7Tk1k/img.jpg?width=872&amp;amp;height=1200&amp;amp;face=0_0_872_1200&quot;&gt;&lt;a href=&quot;http://www.yes24.com/Product/Goods/89145195&quot; data-source-url=&quot;http://www.yes24.com/Product/Goods/89145195&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/4XIVy/hyRwE5pJRQ/875syyPkf3KKmkkxfMPOD1/img.jpg?width=872&amp;amp;height=1200&amp;amp;face=0_0_872_1200,https://scrap.kakaocdn.net/dn/f6K6r/hyRwE5pJWD/V8ngxu85qDA913HN5AnEWK/img.jpg?width=872&amp;amp;height=1200&amp;amp;face=0_0_872_1200,https://scrap.kakaocdn.net/dn/BSM0l/hyRwzQypUz/8ExVV58VPrIq3kXEB7Tk1k/img.jpg?width=872&amp;amp;height=1200&amp;amp;face=0_0_872_1200');&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;테스트 주도 개발 시작하기 - YES24&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;TDD(Test-Driven Development)는 테스트부터 시작한다. 구현을 먼저 하고 나중에 테스트하는 것이 아니라 먼저 테스트를 하고 그다음에 구현한다. 구현 코드가 없는데 어떻게 테스트할 수 있을까? 여기&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.yes24.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;/div&gt;</description>
      <category>TDD</category>
      <category>tdd</category>
      <author>큐범</author>
      <guid isPermaLink="true">https://kbcoding.tistory.com/119</guid>
      <comments>https://kbcoding.tistory.com/119#entry119comment</comments>
      <pubDate>Mon, 6 Mar 2023 00:55:00 +0900</pubDate>
    </item>
    <item>
      <title>[Cloud] AWS, Azure, GCP에 대한 비교</title>
      <link>https://kbcoding.tistory.com/118</link>
      <description>&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;들어가며&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클라우드 서비스 세계적으로 유명한 곳은 &lt;span&gt;AWS, Azure, Google&lt;/span&gt;이 존재한다&lt;span&gt;. &lt;/span&gt;그 외에도 국내에는 &lt;span&gt;Naver Cloud Flattform&lt;/span&gt;이 존재한다&lt;span&gt;. AWS&lt;/span&gt;는 &lt;span&gt;Amazon Web Service&lt;/span&gt;로 아마존에서 제공하고 &lt;span&gt;Azure&lt;/span&gt;는 &lt;span&gt;Microsoft, Google Colud Platform&lt;/span&gt;은 구글에서 제공한다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;text-align: center;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;AWS&lt;/span&gt;&lt;/h3&gt;
&lt;div&gt;
&lt;div id=&quot;ftn2&quot;&gt;
&lt;div id=&quot;ftn2&quot;&gt;
&lt;div id=&quot;ftn2&quot;&gt;
&lt;div id=&quot;ftn2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;AWS&lt;/span&gt;는 가장 많은 시장 점유율로 &lt;span&gt;33%&lt;/span&gt;를 차지하고 있어 &lt;span&gt;Private Cloud &lt;/span&gt;서비스 분야에서 타 서비스 대비 장점을 갖고 있다&lt;span&gt;. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;AWS&lt;/span&gt;의 &lt;span&gt;IaaS&lt;/span&gt;는 &lt;span&gt;Elastic Compute Cloud(EC2)&lt;/span&gt;가 그 예이며 메인 컴퓨팅 서비스&lt;span&gt;. &lt;/span&gt;프로세서&lt;span&gt;, &lt;/span&gt;스토리지 네트워크&lt;span&gt;, &lt;/span&gt;운영체제 등 폭넓고 세분화된 스펙을 제공한다&lt;span&gt;. EC2&lt;/span&gt;의 경우&lt;span&gt;, &lt;/span&gt;가장 많이 사용해봤기에 어떠한 장단점이 있는지 파악하고 있다&lt;span&gt;. &lt;/span&gt;내가 느낀 &lt;span&gt;EC2&lt;/span&gt;의 장점은 첫째&lt;span&gt;, &lt;/span&gt;초보자도 쉽게 &lt;span&gt;IaaS&lt;/span&gt;를 누릴수 있는 것이었다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;503&quot; data-origin-height=&quot;374&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Z1hXv/btr0Iv0oJ8a/MAG5xdSWPhAkJJFk0UQoZK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Z1hXv/btr0Iv0oJ8a/MAG5xdSWPhAkJJFk0UQoZK/img.png&quot; data-alt=&quot;&amp;amp;lt;사이드 프로젝트의 EC2 - 모니터링&amp;amp;gt;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Z1hXv/btr0Iv0oJ8a/MAG5xdSWPhAkJJFk0UQoZK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZ1hXv%2Fbtr0Iv0oJ8a%2FMAG5xdSWPhAkJJFk0UQoZK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;503&quot; height=&quot;374&quot; data-origin-width=&quot;503&quot; data-origin-height=&quot;374&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;&amp;lt;사이드 프로젝트의 EC2 - 모니터링&amp;gt;&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;EC2&lt;/span&gt;를 만들때 유저는 실제로 옷을 사듯이 &lt;span&gt;OS, &lt;/span&gt;유형&lt;span&gt;, &lt;/span&gt;네트워크&lt;span&gt;, &lt;/span&gt;키 등을 편리하게 사용할 수 있으며 &lt;span&gt;AWS&lt;/span&gt;는 해당 탭마다 정보를 제공해 사용자는 해당 탭에 대한 내용도 알아볼 수 있게하였다&lt;span&gt;. &lt;/span&gt;둘째&lt;span&gt;, &lt;/span&gt;타사 대비 많은 레퍼런스와 공식문서의 정리가 제일 잘 되어 있었다&lt;span&gt;. &lt;/span&gt;셋째&lt;span&gt;, &lt;/span&gt;서비스의 범위가 매우 높아 &lt;span&gt;AWS&lt;/span&gt;파트너쉽을 통해 업체는 &lt;span&gt;AWS&lt;/span&gt;가 직접 관리를 해주는 서비스도 제공해준다&lt;span&gt;. &lt;/span&gt;단점은 첫째&lt;span&gt;, EC2&lt;/span&gt;에 대한 커스텀이 복잡하고 과금에 대해서 프리티어가 주어지나 타사 대비 비싼 감이 있었다&lt;span&gt;. &lt;/span&gt;둘째&lt;span&gt;, &lt;/span&gt;세부적인 컨트롤이 가능하기에 다소 복잡하게 관리가 이루어지는 경우가 있었다&lt;span&gt;. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;AWS&lt;/span&gt;의 &lt;span&gt;Paas&lt;/span&gt;는 &lt;span&gt;Elastic Beanstalk, Lightsail, AWS App Runner&lt;/span&gt;가 존재한다&lt;span&gt;. Elastic Beanstalk&lt;/span&gt;는 다양한 언어와 서버 프로그램이 내장되어 있어 코드만 업로드하면 용량 프로비저닝&lt;span&gt;(&lt;/span&gt;자원할당&lt;span&gt;)&lt;/span&gt;과 로드 밸런싱&lt;span&gt;, &lt;/span&gt;오토 스케일링 및 모니터링까지 이르는 배포과정을 자동으로 처리해준다&lt;span&gt;. Lightsail&lt;/span&gt;는 저렴한 비용으로 애플리케이션 및 웹 사이트를 빠르게 구축할 수 있는 서비스이며 &lt;span&gt;Word &lt;/span&gt;등 사전에 구성된 애플리케이션을 통해 빠르게 웹 사이트 구축이 가능하다&lt;span&gt;. AWS App Runner&lt;/span&gt;는 컨테이너와 된 애플리케이션 및 &lt;span&gt;API&lt;/span&gt;를 대규모로 빠르게 배포할 수 있도록 지원하는 완전 관리형 서비스이다&lt;span&gt;. &lt;/span&gt;웹 애플리케이션을 자동 구축 및 배포하고 암호화를 통한 트래픽 로드 밸런싱 수행 및 오토스케일링을 수행한다&lt;span&gt;. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;AWS&lt;/span&gt;&lt;span&gt;의 컨테이너 관리는 &lt;span&gt;Amazon ECR(Elastic Container Registry)&lt;/span&gt;서비스를 통해 구축이 가능하다&lt;span&gt;. ECR&lt;/span&gt;을 통해 컨테이너 이미지를 푸시하고 모든 도구를 관리할 수 있다&lt;span&gt;. &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;&lt;br /&gt;
&lt;div id=&quot;ftn2&quot;&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;451&quot; data-origin-height=&quot;129&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/3UgSG/btr0Iv0oIuI/1ZnAa59KZzckn4P7597qB1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/3UgSG/btr0Iv0oIuI/1ZnAa59KZzckn4P7597qB1/img.png&quot; data-alt=&quot;&amp;amp;lt;출처-AWS ECR작동방식&amp;amp;gt;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/3UgSG/btr0Iv0oIuI/1ZnAa59KZzckn4P7597qB1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F3UgSG%2Fbtr0Iv0oIuI%2F1ZnAa59KZzckn4P7597qB1%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;451&quot; height=&quot;129&quot; data-origin-width=&quot;451&quot; data-origin-height=&quot;129&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;&amp;lt;출처-AWS ECR작동방식&amp;gt;&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;AWS ECS Anywhere&lt;/span&gt;를 통해 컨테이너를 실행할 수 있다&lt;span&gt;. ECS&lt;/span&gt;는 컨테이너기반 애플리케이션에서 도구를 제공해준다&lt;span&gt;. &lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;451&quot; data-origin-height=&quot;112&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eTklT2/btr0JN0PegV/zm7P0kfaapUt2pp6mxYKd0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eTklT2/btr0JN0PegV/zm7P0kfaapUt2pp6mxYKd0/img.png&quot; data-alt=&quot;&amp;amp;lt;출처-AWS ECS Anywhere 작동방식&amp;amp;gt;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eTklT2/btr0JN0PegV/zm7P0kfaapUt2pp6mxYKd0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeTklT2%2Fbtr0JN0PegV%2Fzm7P0kfaapUt2pp6mxYKd0%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;451&quot; height=&quot;112&quot; data-origin-width=&quot;451&quot; data-origin-height=&quot;112&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;&amp;lt;출처-AWS ECS Anywhere 작동방식&amp;gt;&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;그러면 쿠버네티스의 주 목적인 컨테이너의 관리가 이루어져야하는데 이것을 &lt;span&gt;Amazon EKS Anywhere&lt;/span&gt;가 한다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;EKS Anywhere&lt;/span&gt;를 통해 쿠버네티스 클러스터를 운영이 가능하다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;451&quot; data-origin-height=&quot;126&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cy9wMk/btr0HywAwP8/OgjJgFdHtAWtKhbT3Xg541/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cy9wMk/btr0HywAwP8/OgjJgFdHtAWtKhbT3Xg541/img.png&quot; data-alt=&quot;&amp;amp;lt;출처 &amp;amp;amp;ndash; AWS EKS anywhere 작동방식&amp;amp;gt;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cy9wMk/btr0HywAwP8/OgjJgFdHtAWtKhbT3Xg541/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcy9wMk%2Fbtr0HywAwP8%2FOgjJgFdHtAWtKhbT3Xg541%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;451&quot; height=&quot;126&quot; data-origin-width=&quot;451&quot; data-origin-height=&quot;126&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;&amp;lt;출처 &amp;amp;ndash; AWS EKS anywhere 작동방식&amp;gt;&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;Azure&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Azure&lt;/span&gt;는 점유율 &lt;span&gt;20%&lt;/span&gt;로 &lt;span&gt;MS&lt;/span&gt;사에서 만들었기에 &lt;span&gt;MS&lt;/span&gt;관련 서비스와 높은 호환성을 가진다&lt;span&gt;. Azure&lt;/span&gt;의 &lt;span&gt;IaaS&lt;/span&gt;는 &lt;span&gt;Azure Virtual Machines&lt;/span&gt;에는 &lt;span&gt;Linux, Window Server&lt;/span&gt;가 존재하고 가상 머신에는 &lt;span&gt;A&lt;/span&gt;시리즈부터 &lt;span&gt;N&lt;/span&gt;시리즈가 존재한다&lt;span&gt;. PaaS&lt;/span&gt;는 &lt;span&gt;App Service, Batch, Azure Spring Cloud, Cloud Services&lt;/span&gt;가 존재하는데 학부 수준에서 공부를 위해 유용하게 쓰일만한 것은 &lt;span&gt;App Service&lt;/span&gt;는 &lt;span&gt;Application Service&lt;/span&gt;를 구축하기 위한 완전 관리형 플랫폼이다&lt;span&gt;. Azure Spring App&lt;/span&gt;은 &lt;span&gt;Spring Boot&lt;/span&gt;와 호환성이 좋으며 &lt;span&gt;Spring Cloud Azure&lt;/span&gt;는 &lt;span&gt;Spring &lt;/span&gt;공식적으로 지원하는 서비스이기에 &lt;span&gt;Azure&lt;/span&gt;와 호환성이 매우 좋다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;956&quot; data-origin-height=&quot;484&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bo37Mq/btr0JBMQ1dS/Ycf7cWfkAxQ6EMAPcRyDV1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bo37Mq/btr0JBMQ1dS/Ycf7cWfkAxQ6EMAPcRyDV1/img.png&quot; data-alt=&quot;Azure Spring Apps&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bo37Mq/btr0JBMQ1dS/Ycf7cWfkAxQ6EMAPcRyDV1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbo37Mq%2Fbtr0JBMQ1dS%2FYcf7cWfkAxQ6EMAPcRyDV1%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;478&quot; height=&quot;242&quot; data-origin-width=&quot;956&quot; data-origin-height=&quot;484&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Azure Spring Apps&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Azure Kubernetes Service&lt;/span&gt;는 운영 오버헤드를 &lt;span&gt;Azure&lt;/span&gt;가 관리하여 &lt;span&gt;Kubernetes &lt;/span&gt;클러스터 배포를 단순화할 수 있다&lt;span&gt;. &lt;/span&gt;호스팅 되는 &lt;span&gt;Kubernetes &lt;/span&gt;서비스인 &lt;span&gt;Azure&lt;/span&gt;는 상태 모니터링 및 유지관리 등 작업 처리를 할 수 있다&lt;span&gt;. Azure Kubernetes Service&lt;/span&gt;는 크게 &lt;span&gt;4&lt;/span&gt;가지의 서비스를 제공한다&lt;span&gt;. &lt;/span&gt;첫째&lt;span&gt;,&lt;/span&gt;엔터프라이즈급 컨테이너 오케스트레이션을 위해 &lt;span&gt;Kubernetes &lt;/span&gt;클러스터의 자동화된 관리를 할 수 있다&lt;span&gt;. &lt;/span&gt;둘째&lt;span&gt;, &lt;/span&gt;디버깅&lt;span&gt;, CI/CD, &lt;/span&gt;로깅 등 자동 노드 유지 관리를 통한 엔드투엔드 개발자의 생산성을 높여준다&lt;span&gt;. &lt;/span&gt;셋째&lt;span&gt;, &lt;/span&gt;대규모 거버넌스를 위해 컨테이너 보안을 모니터링 및 유지 관리하는 고급 &lt;span&gt;ID &lt;/span&gt;및 액세스 관리한다&lt;span&gt;. &lt;/span&gt;넷째&lt;span&gt;, Azure Arc&lt;/span&gt;를 사용하여 인프라에 &lt;span&gt;AKS&lt;/span&gt;배포를 통해 &lt;span&gt;Linux, Windows Server &lt;/span&gt;및 &lt;span&gt;IoT &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;h3 style=&quot;text-align: center;&quot; data-ke-size=&quot;size23&quot;&gt;GCP&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Google Cloud Platform&lt;/span&gt;은 구글에서 제공하는 클라우드 컴퓨팅 서비스로 시장 점유율 &lt;span&gt;10%&lt;/span&gt;로 앞서 소개한 클라우드 회사 대비 낮은 점유율을 갖고 있다&lt;span&gt;. &lt;/span&gt;구글 클라우드 플랫폼은 &lt;span&gt;IaaS&lt;/span&gt;서비스는 구글 컴퓨트 엔진&lt;span&gt;(Goole Compute Engine, GCE), &lt;/span&gt;빅테이블&lt;span&gt;, &lt;/span&gt;빅쿼리가 있다&lt;span&gt;. &lt;/span&gt;구글 컴퓨트 엔진의 운영체제는 리눅스&lt;span&gt;, &lt;/span&gt;윈도우&lt;span&gt;, FreeBSD, NetBSD&lt;/span&gt;가 있고 &lt;span&gt;GCE&lt;/span&gt;는 &lt;span&gt;FM &lt;/span&gt;런칭 이전에 &lt;span&gt;Oauth 2.0 &lt;/span&gt;기반의 인증을 수행해야 하는 단점이 있다&lt;span&gt;. &lt;/span&gt;빅테이블은 구글의 파일 시스템으로 고성능 데이터 스토리지 시스템이다&lt;span&gt;. &lt;/span&gt;그리고 빅 쿼리는 대용량&lt;span&gt;, &lt;/span&gt;페타바이트급 이상의 데이터에 대해 분석을 가능하게 하는 관리형 서버리스 컴퓨팅 데이터 웨어하우스이다&lt;span&gt;. &lt;/span&gt;그 다음 &lt;span&gt;GCP&lt;/span&gt;의 &lt;span&gt;PaaS&lt;/span&gt;는 구글 앱 엔진으로&lt;span&gt;(Google App Engine, GAE) &lt;/span&gt;웹 응용 프로그램을 개발하고 구글의 인프라에서 실행하고 버전 관리할 수 있다&lt;span&gt;. Google Kubernetes Engine(GKE) Kubernetes&lt;/span&gt;를 자동으로 배포&lt;span&gt;, &lt;/span&gt;확장&lt;span&gt;, &lt;/span&gt;관리할 수 있으며 안전한&lt;span&gt; Google &lt;/span&gt;인프라에서 컨테이너화된 애플리케이션을 배포&lt;span&gt;, &lt;/span&gt;확장 및 관리하기 위한 관리형 환경을 말한다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;AWS, Azure, GCP 장단점 비교&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫째&lt;span&gt;, AWS&lt;/span&gt;에 대해서 장단점을 파악 해보면 &lt;span&gt;AWS&lt;/span&gt;의 장점은 가장 높은 시장 점유율로 많은 레퍼런스와 성공사례가 있다는 것이다&lt;span&gt;. &lt;/span&gt;따라서 서비스를 제공하는 범위가 타사 대비 매우 높으며 파트너 생태계가 매우 잘 이루어져 있다&lt;span&gt;. &lt;/span&gt;단점은 &lt;span&gt;AWS&lt;/span&gt;를 사용하기 위해서 &lt;span&gt;AWS&lt;/span&gt;의 시스템에 대한 이해도가 필요하며 규모가 큰 하이브리드 클라우드의 지원이 부족하고 &lt;span&gt;AWS&lt;/span&gt;의 서비스의 범위가 크기에 파악하기 힘든 경향이 있다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;둘째&lt;span&gt;, Azure&lt;/span&gt;의 장단점을 파악해보면 &lt;span&gt;Azure&lt;/span&gt;의 장점은 다른 &lt;span&gt;MS &lt;/span&gt;서비스 및 제품과의 이식성이 좋기에 &lt;span&gt;MS teams, word &lt;/span&gt;등 다른 서비스와 같이 사용하기 좋다&lt;span&gt;. &lt;/span&gt;오픈 소스 애플리케이션 스택에 대한 많은 도움을 받을 수 있다&lt;span&gt;. AWS&lt;/span&gt;에서 부족한 하이브리드 클라우드에 대해서 솔루션이 제공된다&lt;span&gt;. &lt;/span&gt;가상 환경에서도 모두 잘 실행되는 사용 사례가 만이 존재한다&lt;span&gt;. &lt;/span&gt;하지만 단점은 대규모 구현의 빈약한 규모가 있으며 &lt;span&gt;Azure &lt;/span&gt;또한&lt;span&gt;, &lt;/span&gt;구현하기 위해서 인프라에 대해서 전문 지식이 필요하다&lt;span&gt;. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;셋째&lt;span&gt;, GCP&lt;/span&gt;의 장단점을 파악해보면 &lt;span&gt;GCP&lt;/span&gt;의 장점은 오픈 소스 커뮤니티에 대한 기여했다&lt;span&gt;. &lt;/span&gt;또한&lt;span&gt;, &lt;/span&gt;현재 각광받는 분야인 분석 및 머신러닝에 대한 많은 투자가 이루어지고 빅데이터 애플리케이션&lt;span&gt;, ML &lt;/span&gt;벤처 및 클라우드 네이티브 애플리케이션을 위한 최적의 옵션이다&lt;span&gt;. &lt;/span&gt;단점은 타사 대비 시장 점유율이 낮아 성공 레퍼런스가 비교적 부족하고 계약협상에 대해서 타사 대비 까다로운 계약 협상이 있다&lt;span&gt;. &lt;/span&gt;또한&lt;span&gt;, &lt;/span&gt;규모가 다른 회사에 비해 적기에 파트너 생태계가 규모가 작다&lt;span&gt;. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;만약 내가 클라우드를 도입한다면 &lt;/span&gt;&lt;span&gt;3가지 클라우드 기업 중 어느 것을 선택하겠는가?&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 서비스 스타트업에서 클라우드 컴퓨팅을 도입한다면 단연&lt;span&gt;, AWS&lt;/span&gt;를 채택할 것이다&lt;span&gt;. &lt;/span&gt;그 근거를 &lt;span&gt;3&lt;/span&gt;가지가 있다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫째&lt;span&gt;, &lt;/span&gt;가장 높은 시장 점유율&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;AWS&lt;/span&gt;는 국내를 넘어 전 세계적으로 가장 높은 클라우드 시장성을 가지고 있다&lt;span&gt;. &lt;/span&gt;또한&lt;span&gt;, &lt;/span&gt;시장 점유율은 기업 경쟁간의 우의를 점하고 있다는 지표를 나타내기도 한다&lt;span&gt;. &lt;/span&gt;실제로 &lt;span&gt;AWS&lt;/span&gt;를 운용해보며 런칭을 진행해 본 결과 &lt;span&gt;AWS&lt;/span&gt;는 가장 많은 레퍼런스가 나왔다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;둘째&lt;span&gt;, &lt;/span&gt;합리적 가격&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;3&lt;/span&gt;사 중 가장 저렴한 가격이라면 그것은 아니다&lt;span&gt;. &lt;/span&gt;단&lt;span&gt;, &lt;/span&gt;합리적인 가격이라고 생각한다&lt;span&gt;. AWS&lt;/span&gt;는 파트너십을 통해서 직원이 직접 관리해주는 서비스도 제공하며 시장에 &lt;span&gt;DevOps &lt;/span&gt;개발자의 선택 비중으로 본다면&lt;span&gt; AWS &lt;/span&gt;관련 개발자가 채용과정에서 가장 수월할 것으로 생각된다&lt;span&gt;. &lt;/span&gt;실제로 &lt;span&gt;AWS&lt;/span&gt;의 설정을 통해서 &lt;span&gt;AWS&lt;/span&gt;의 가상서버는 코크로치랩스가&lt;span&gt; TPC-C &lt;/span&gt;테스트에서 파생시킨&lt;span&gt; OLTP &lt;/span&gt;성능평가 결과상 가장 비용효율적인 상품으로 &lt;span&gt;AWS&lt;/span&gt;의&lt;span&gt; c5a.4xlarge &lt;/span&gt;인스턴스는&lt;span&gt; GCP&lt;/span&gt;의 가성비 최고상품대비&lt;span&gt; 12% &lt;/span&gt;저렴하고&lt;span&gt; MS&lt;/span&gt;애저 대비로는&lt;span&gt; 35% &lt;/span&gt;저렴한&lt;span&gt; &lt;/span&gt;기사가 있다&lt;span&gt;. &lt;/span&gt;그리고 &lt;span&gt;AWS&lt;/span&gt;는 스타트업 클라우드에는 사용료를 일정 부분 할인해주는 서비스도 지원하고 특정 기간에 사용률을 기반으로 앞으로의 추세를 분석해주는 서비스가 존재하기에 스타트업에서 매우 필수적인 클라우드 제공 업체이다&lt;span&gt;. &lt;/span&gt;스타트업의 효율적인 클라우드 사용을 위해 각 기업의 상황에 맞는 기간할인&lt;span&gt;, &lt;/span&gt;금액설정&lt;span&gt;, &lt;/span&gt;단기 사용등 &lt;span&gt;3&lt;/span&gt;가지 경우를 권고하는데 이를 &lt;span&gt;AWS&lt;/span&gt;에서 분석 및 결과를 추출해주니 매우 유용하다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;셋째&lt;span&gt;, AWS &lt;/span&gt;스타트업 서비스&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;AWS&lt;/span&gt;에서는 스타트업을 지원해주는 &lt;span&gt;AWS &lt;/span&gt;스타트업 서비스가 있다&lt;span&gt;. AWS &lt;/span&gt;상에서 스타트업을 구축하기에 다른 스타트업 창업자들과 매칭시켜주기도 하며 이를 통해 비즈니스 성장을 도모한다&lt;span&gt;. &lt;/span&gt;다양한&lt;span&gt; AWS &lt;/span&gt;스타트업 프로그램을 지원하고 있는데 이를 이용하면 인프라 서비스를 넘어 스타트업의 시작&lt;span&gt;, &lt;/span&gt;성장&lt;span&gt;, &lt;/span&gt;비즈니스 확장을 받을 수 있다&lt;span&gt;. &lt;/span&gt;이를 기반으로 &lt;span&gt;Airbnb, Zocdoc &lt;/span&gt;등의 유니콘 기업의 클라우드 서비스를 제공해준 이력이 있기에 스타트업과 자사 대형 고객들을 연결해주는 프로그램인&lt;span&gt; AWS &lt;/span&gt;커넥션&lt;span&gt;, &lt;/span&gt;스타트업의 빠른 시작을 지원하는 &lt;span&gt;AWS Public Sector Startup Ramp&lt;/span&gt;도 있으며 스타트업의 운영 가속화를 위한 검증&lt;span&gt;, &lt;/span&gt;출시&lt;span&gt;, &lt;/span&gt;지원&lt;span&gt;, &lt;/span&gt;영업에 대한 지침을 제공하는 &lt;span&gt;AWS &lt;/span&gt;파트너 네트워크 서비스도 제공한다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 &lt;span&gt;3&lt;/span&gt;가지의 근거를 통해 만약 내가 스타트업의 클라우드 컴퓨팅을 도입한다면 &lt;span&gt;AWS&lt;/span&gt;를 채택 할 것이다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Reference.&lt;/h2&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;figure id=&quot;og_1677395696257&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;AWS App Runner &amp;ndash; 손쉽게 코드를 높은 확장성의 안전한 웹 애플리케이션 배포하기 | Amazon Web Services&quot; data-og-description=&quot;컨테이너는 웹 애플리케이션을 패키징하는 기본 방법이 되었습니다. 저는 컨테이너가 제공하는 속도, 생산성 및 일관성을 선호하지만 컨테이너 개발 워크 플로우에는 컨테이너 이미지를 처음 &quot; data-og-host=&quot;aws.amazon.com&quot; data-og-source-url=&quot;https://aws.amazon.com/ko/blogs/korea/app-runner-from-code-to-scalable-secure-web-apps/&quot; data-og-url=&quot;https://aws.amazon.com/ko/blogs/korea/app-runner-from-code-to-scalable-secure-web-apps/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/wLSZF/hyRKPrJJkB/626KbEvKVuok0M1HY1HUyk/img.png?width=1024&amp;amp;height=536&amp;amp;face=0_0_1024_536,https://scrap.kakaocdn.net/dn/nsNdf/hyRKWEngHL/QwJwMkP57ezjhC9QHxfQS0/img.png?width=1024&amp;amp;height=536&amp;amp;face=0_0_1024_536,https://scrap.kakaocdn.net/dn/Y0SHX/hyRKUfvw5F/uK6MuEueKxVN8XqIk4HLKK/img.jpg?width=806&amp;amp;height=731&amp;amp;face=0_0_806_731&quot;&gt;&lt;a href=&quot;https://aws.amazon.com/ko/blogs/korea/app-runner-from-code-to-scalable-secure-web-apps/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://aws.amazon.com/ko/blogs/korea/app-runner-from-code-to-scalable-secure-web-apps/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/wLSZF/hyRKPrJJkB/626KbEvKVuok0M1HY1HUyk/img.png?width=1024&amp;amp;height=536&amp;amp;face=0_0_1024_536,https://scrap.kakaocdn.net/dn/nsNdf/hyRKWEngHL/QwJwMkP57ezjhC9QHxfQS0/img.png?width=1024&amp;amp;height=536&amp;amp;face=0_0_1024_536,https://scrap.kakaocdn.net/dn/Y0SHX/hyRKUfvw5F/uK6MuEueKxVN8XqIk4HLKK/img.jpg?width=806&amp;amp;height=731&amp;amp;face=0_0_806_731');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;AWS App Runner &amp;ndash; 손쉽게 코드를 높은 확장성의 안전한 웹 애플리케이션 배포하기 | Amazon Web Services&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;aws.amazon.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id=&quot;og_1677395685943&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;가상 프라이빗 서버 및 웹 호스팅&amp;ndash;Amazon Lightsail&amp;mdash;Amazon Web Services&quot; data-og-description=&quot;WordPress, Magento, Prestashop, Joomla와 같은 사전 구성된 애플리케이션을 통해 단 몇 번의 클릭으로 블로그, 전자 상거래 또는 개인 웹 사이트를 구축합니다.&quot; data-og-host=&quot;aws.amazon.com&quot; data-og-source-url=&quot;https://aws.amazon.com/ko/lightsail&quot; data-og-url=&quot;https://aws.amazon.com/ko/lightsail/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/jRG54/hyRKVyI1Hg/ZOy0aCYQmZI912pScytFfk/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/GqL4v/hyRKYI0laY/CY2arFKyHdaUEAV5mE2hC0/img.png?width=179&amp;amp;height=109&amp;amp;face=0_0_179_109,https://scrap.kakaocdn.net/dn/bOwkDw/hyRKL3XmRI/mHjwiTMscY7qSHvB6ngC3K/img.png?width=300&amp;amp;height=200&amp;amp;face=0_0_300_200&quot;&gt;&lt;a href=&quot;https://aws.amazon.com/ko/lightsail&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://aws.amazon.com/ko/lightsail&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/jRG54/hyRKVyI1Hg/ZOy0aCYQmZI912pScytFfk/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/GqL4v/hyRKYI0laY/CY2arFKyHdaUEAV5mE2hC0/img.png?width=179&amp;amp;height=109&amp;amp;face=0_0_179_109,https://scrap.kakaocdn.net/dn/bOwkDw/hyRKL3XmRI/mHjwiTMscY7qSHvB6ngC3K/img.png?width=300&amp;amp;height=200&amp;amp;face=0_0_300_200');&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;가상 프라이빗 서버 및 웹 호스팅&amp;ndash;Amazon Lightsail&amp;mdash;Amazon Web Services&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;WordPress, Magento, Prestashop, Joomla와 같은 사전 구성된 애플리케이션을 통해 단 몇 번의 클릭으로 블로그, 전자 상거래 또는 개인 웹 사이트를 구축합니다.&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;figure id=&quot;og_1677395677899&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;Virtual Machines 시리즈 | Microsoft Azure&quot; data-og-description=&quot;개발/테스트용 초급 수준 VM부터 집약적 워크로드를 위한 GPU 지원 VM에 이르기까지 모든 애플리케이션 요구 사항을 위한 Azure의 다양한 VM(가상 머신)을 확인하세요.&quot; data-og-host=&quot;azure.microsoft.com&quot; data-og-source-url=&quot;https://azure.microsoft.com/ko-kr/pricing/details/virtual-machines/series/&quot; data-og-url=&quot;https://azure.microsoft.com/ko-kr/pricing/details/virtual-machines/series/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/t7JDi/hyRKRJRQC6/1XDaIdOESJJdvuBB06i330/img.png?width=600&amp;amp;height=315&amp;amp;face=0_0_600_315,https://scrap.kakaocdn.net/dn/MFIvm/hyRKNAGfKA/0fR1GjXE0cmReJcli6NNOK/img.png?width=600&amp;amp;height=315&amp;amp;face=0_0_600_315&quot;&gt;&lt;a href=&quot;https://azure.microsoft.com/ko-kr/pricing/details/virtual-machines/series/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://azure.microsoft.com/ko-kr/pricing/details/virtual-machines/series/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/t7JDi/hyRKRJRQC6/1XDaIdOESJJdvuBB06i330/img.png?width=600&amp;amp;height=315&amp;amp;face=0_0_600_315,https://scrap.kakaocdn.net/dn/MFIvm/hyRKNAGfKA/0fR1GjXE0cmReJcli6NNOK/img.png?width=600&amp;amp;height=315&amp;amp;face=0_0_600_315');&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;Virtual Machines 시리즈 | Microsoft Azure&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;개발/테스트용 초급 수준 VM부터 집약적 워크로드를 위한 GPU 지원 VM에 이르기까지 모든 애플리케이션 요구 사항을 위한 Azure의 다양한 VM(가상 머신)을 확인하세요.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;azure.microsoft.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id=&quot;og_1677395671052&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;App Service &amp;mdash; Build and Host Web Apps | Microsoft Azure&quot; data-og-description=&quot;Migrate and build apps. Azure App Service is a fully managed platform for creating web applications. The app service offers a range of app development plans and services.&quot; data-og-host=&quot;azure.microsoft.com&quot; data-og-source-url=&quot;https://azure.microsoft.com/en-us/products/app-service/#overview&quot; data-og-url=&quot;https://azure.microsoft.com/en-us/products/app-service&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cGpLzl/hyRKUT8nrw/s5LSXesaYRv7KngaiIgIyK/img.jpg?width=2880&amp;amp;height=800&amp;amp;face=0_0_2880_800,https://scrap.kakaocdn.net/dn/VyQBo/hyRKXpK5bJ/HS1QFuOvT6dNEl7cncloCK/img.png?width=905&amp;amp;height=519&amp;amp;face=0_0_905_519&quot;&gt;&lt;a href=&quot;https://azure.microsoft.com/en-us/products/app-service/#overview&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://azure.microsoft.com/en-us/products/app-service/#overview&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cGpLzl/hyRKUT8nrw/s5LSXesaYRv7KngaiIgIyK/img.jpg?width=2880&amp;amp;height=800&amp;amp;face=0_0_2880_800,https://scrap.kakaocdn.net/dn/VyQBo/hyRKXpK5bJ/HS1QFuOvT6dNEl7cncloCK/img.png?width=905&amp;amp;height=519&amp;amp;face=0_0_905_519');&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;App Service &amp;mdash; Build and Host Web Apps | Microsoft Azure&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Migrate and build apps. Azure App Service is a fully managed platform for creating web applications. The app service offers a range of app development plans and services.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;azure.microsoft.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id=&quot;og_1677395647371&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 | Home&quot; data-og-description=&quot;Cloud Your code, any cloud&amp;mdash;we&amp;rsquo;ve got you covered. Connect and scale your services, whatever your platform.&quot; data-og-host=&quot;spring.io&quot; data-og-source-url=&quot;https://spring.io/projects/spring-cloud-azure&quot; data-og-url=&quot;https://spring.io&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://spring.io/projects/spring-cloud-azure&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://spring.io/projects/spring-cloud-azure&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;Spring | Home&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Cloud Your code, any cloud&amp;mdash;we&amp;rsquo;ve got you covered. Connect and scale your services, whatever your platform.&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;br /&gt;
&lt;figure id=&quot;og_1677395635208&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;Azure Kubernetes Service 소개 - Azure Kubernetes Service&quot; data-og-description=&quot;Azure에서 컨테이너 기반 애플리케이션을 배포 및 관리하는 Azure Kubernetes Service의 기능 및 이점을 알아봅니다.&quot; data-og-host=&quot;learn.microsoft.com&quot; data-og-source-url=&quot;https://learn.microsoft.com/ko-kr/azure/aks/intro-kubernetes&quot; data-og-url=&quot;https://learn.microsoft.com/ko-kr/azure/aks/intro-kubernetes&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/kKy0d/hyRKWxCAYn/iZ22FZyKxzKK3MDXLzBTl0/img.png?width=400&amp;amp;height=400&amp;amp;face=0_0_400_400&quot;&gt;&lt;a href=&quot;https://learn.microsoft.com/ko-kr/azure/aks/intro-kubernetes&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://learn.microsoft.com/ko-kr/azure/aks/intro-kubernetes&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/kKy0d/hyRKWxCAYn/iZ22FZyKxzKK3MDXLzBTl0/img.png?width=400&amp;amp;height=400&amp;amp;face=0_0_400_400');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Azure Kubernetes Service 소개 - Azure Kubernetes Service&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Azure에서 컨테이너 기반 애플리케이션을 배포 및 관리하는 Azure Kubernetes Service의 기능 및 이점을 알아봅니다.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;learn.microsoft.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1677395612712&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;아마존 선두, 다음은 구글&amp;hellip;가성비로 본 클라우드 빅3 | 아주경제&quot; data-og-description=&quot;세계 클라우드 시장 점유율 1위 아마존웹서비스(AWS)가 일반적인 온라인트랜잭션처리(OLTP) 환경에서 마이크로소프트(MS)와 구글클라우드보다 나은 가성비를 보여주는 것으로 나타났다.19일 분산 &quot; data-og-host=&quot;www.ajunews.com&quot; data-og-source-url=&quot;https://www.ajunews.com/view/20210119092532013?redirect=mobile&quot; data-og-url=&quot;https://www.ajunews.com/view/20210119092532013?redirect=mobile&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/NUAyP/hyRKVlbzFG/UGXgRRa3DUuD277r5nvhJ0/img.jpg?width=640&amp;amp;height=307&amp;amp;face=0_0_640_307,https://scrap.kakaocdn.net/dn/c4R06i/hyRKKxbTsq/51ZxbjKkxGjKwasq1Xuav1/img.jpg?width=617&amp;amp;height=816&amp;amp;face=0_0_617_816,https://scrap.kakaocdn.net/dn/ci6sT1/hyRKWj5ULb/P9fm48siqWPAaVNjEUwQ81/img.jpg?width=640&amp;amp;height=426&amp;amp;face=0_0_640_426&quot;&gt;&lt;a href=&quot;https://www.ajunews.com/view/20210119092532013?redirect=mobile&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.ajunews.com/view/20210119092532013?redirect=mobile&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/NUAyP/hyRKVlbzFG/UGXgRRa3DUuD277r5nvhJ0/img.jpg?width=640&amp;amp;height=307&amp;amp;face=0_0_640_307,https://scrap.kakaocdn.net/dn/c4R06i/hyRKKxbTsq/51ZxbjKkxGjKwasq1Xuav1/img.jpg?width=617&amp;amp;height=816&amp;amp;face=0_0_617_816,https://scrap.kakaocdn.net/dn/ci6sT1/hyRKWj5ULb/P9fm48siqWPAaVNjEUwQ81/img.jpg?width=640&amp;amp;height=426&amp;amp;face=0_0_640_426');&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;아마존 선두, 다음은 구글&amp;hellip;가성비로 본 클라우드 빅3 | 아주경제&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;세계 클라우드 시장 점유율 1위 아마존웹서비스(AWS)가 일반적인 온라인트랜잭션처리(OLTP) 환경에서 마이크로소프트(MS)와 구글클라우드보다 나은 가성비를 보여주는 것으로 나타났다.19일 분산&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.ajunews.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;br /&gt;
&lt;figure id=&quot;og_1677395617057&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;스타트업을 위한 AWS - Amazon Web Services(AWS)&quot; data-og-description=&quot;Airbnb에서 Zocdoc에 이르기까지 세계 최고의 스타트업들이 AWS를 기반으로 구축되었습니다. 하지만 이들의 성공 뒤에는 전폭적인 지원이 있었습니다. 기술 과제를 해결해야 하거나, 훌륭한 엔지니&quot; data-og-host=&quot;aws.amazon.com&quot; data-og-source-url=&quot;https://aws.amazon.com/ko/startups/?customer-references-cards.sort-by=item.additionalFields.sortDate&amp;amp;customer-references-cards.sort-order=desc&amp;amp;awsf.customer-references-location=*all&amp;amp;awsf.customer-references-industry=*all&quot; data-og-url=&quot;https://aws.amazon.com/ko/startups/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/fWBSZ/hyRKVS1ZwP/BD1PKkAuRodAYlTkuvOlbK/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/startups/?customer-references-cards.sort-by=item.additionalFields.sortDate&amp;amp;customer-references-cards.sort-order=desc&amp;amp;awsf.customer-references-location=*all&amp;amp;awsf.customer-references-industry=*all&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://aws.amazon.com/ko/startups/?customer-references-cards.sort-by=item.additionalFields.sortDate&amp;amp;customer-references-cards.sort-order=desc&amp;amp;awsf.customer-references-location=*all&amp;amp;awsf.customer-references-industry=*all&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/fWBSZ/hyRKVS1ZwP/BD1PKkAuRodAYlTkuvOlbK/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;스타트업을 위한 AWS - Amazon Web Services(AWS)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Airbnb에서 Zocdoc에 이르기까지 세계 최고의 스타트업들이 AWS를 기반으로 구축되었습니다. 하지만 이들의 성공 뒤에는 전폭적인 지원이 있었습니다. 기술 과제를 해결해야 하거나, 훌륭한 엔지니&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;/div&gt;
&lt;/div&gt;</description>
      <category>Cloud</category>
      <category>AWS</category>
      <category>azure</category>
      <category>Cloud</category>
      <category>GCP</category>
      <category>클라우드 회사 비교</category>
      <author>큐범</author>
      <guid isPermaLink="true">https://kbcoding.tistory.com/118</guid>
      <comments>https://kbcoding.tistory.com/118#entry118comment</comments>
      <pubDate>Sun, 26 Feb 2023 16:16:18 +0900</pubDate>
    </item>
    <item>
      <title>[GDSC] CICD 세션 결말 해석</title>
      <link>https://kbcoding.tistory.com/117</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;GDSC(Google Developer Student Club)에서 개발 기술에 대해서 하나씩 선정하여 세션을 진행하게 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 CICD에 대해서 진행하였고 CICD의 필요성과 수동 배포 방식의 워크플로우와 비교하여 설명하였다.&lt;/p&gt;
&lt;figure id=&quot;og_1677225637484&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;[Session] CICD / 한규범&quot; data-og-description=&quot;CI/CD 의미 CI &amp;rArr; Continuous Intrgration (지속적 통합) CD &amp;rArr; Continous Delivery (지속적 전달) CD &amp;rArr; Continuous deployment (지속적 배포) Continuous Intrgration 개발자를 위한 자동화 프로세스인 지속적인 통합을 의미 &quot; data-og-host=&quot;gdsc-mju.tistory.com&quot; data-og-source-url=&quot;https://gdsc-mju.tistory.com/18&quot; data-og-url=&quot;https://gdsc-mju.tistory.com/18&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/boXzNa/hyRJQEmez0/e2aBgG34IKXLs8nbGEZZL0/img.png?width=800&amp;amp;height=450&amp;amp;face=537_211_578_257,https://scrap.kakaocdn.net/dn/bESEXR/hyRJKKTlyK/Rp5ufynkOfE83hRkppT5n1/img.png?width=800&amp;amp;height=450&amp;amp;face=537_211_578_257,https://scrap.kakaocdn.net/dn/XNuub/hyRJJ6htAJ/y4ob7qkkwt2QmAzr7Vzo91/img.png?width=1920&amp;amp;height=1080&amp;amp;face=1290_507_1383_606&quot;&gt;&lt;a href=&quot;https://gdsc-mju.tistory.com/18&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://gdsc-mju.tistory.com/18&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/boXzNa/hyRJQEmez0/e2aBgG34IKXLs8nbGEZZL0/img.png?width=800&amp;amp;height=450&amp;amp;face=537_211_578_257,https://scrap.kakaocdn.net/dn/bESEXR/hyRJKKTlyK/Rp5ufynkOfE83hRkppT5n1/img.png?width=800&amp;amp;height=450&amp;amp;face=537_211_578_257,https://scrap.kakaocdn.net/dn/XNuub/hyRJJ6htAJ/y4ob7qkkwt2QmAzr7Vzo91/img.png?width=1920&amp;amp;height=1080&amp;amp;face=1290_507_1383_606');&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;[Session] CICD / 한규범&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;CI/CD 의미 CI &amp;rArr; Continuous Intrgration (지속적 통합) CD &amp;rArr; Continous Delivery (지속적 전달) CD &amp;rArr; Continuous deployment (지속적 배포) Continuous Intrgration 개발자를 위한 자동화 프로세스인 지속적인 통합을 의미&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;gdsc-mju.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나의 CICD 세션의 목표는 툴에 의존하기 보다는 CICD를 도입하면 개발방식에 대해서 변화를 가져오는 것을 이해하기 바라는 마음으로 작성하였다.&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;결론의 내용은 &quot;열차를 타지 말고 택시를 타라&quot;이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;열차를 타지 말고 택시를 타라&quot;는 데브옵스(DevOps)에서의 일종의 말장난으로, 소프트웨어 배포를 비유적으로 비교한 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 &quot;열차&quot;는 예전에 많이 사용되었던 워터폴 방식의 소프트웨어 개발 모델을 의미하며, 이 모델은 소프트웨어 개발 생명주기를 단계별로 구분하여 한 단계가 끝나면 다음 단계로 넘어가는 선형적인 방식으로 작업을 처리했다. 이 방식은 전체적으로 진행 상황을 파악하기 어렵고, 문제 발생 시 수정하기 어려워지는 등 여러 가지 문제점이 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반면에 &quot;택시&quot;는 데브옵스에서 추구하는 지속적인 통합/배포(CI/CD)를 의미하며, 이는 소프트웨어 개발과 운영을 하나로 통합하여 작은 단위로 빈번한 배포를 통해 빠른 피드백과 지속적인 개선을 가능하게 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;따라서, &quot;열차를 타지 말고 택시를 타라&quot;는 더 빠르고 유연한 소프트웨어 배포 방식을 추구하자는 의미의 말이다.&lt;/b&gt;&lt;/p&gt;</description>
      <category>cicd</category>
      <category>DevOps</category>
      <author>큐범</author>
      <guid isPermaLink="true">https://kbcoding.tistory.com/117</guid>
      <comments>https://kbcoding.tistory.com/117#entry117comment</comments>
      <pubDate>Fri, 24 Feb 2023 17:01:36 +0900</pubDate>
    </item>
    <item>
      <title>[TDD] 테스트 가능한 설계</title>
      <link>https://kbcoding.tistory.com/116</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;테스트 어려운 코드&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모든 코드를 테스트할 수 있는 것은 아니다. 개발을 진행하다 보면 테스트하기 어려운 코드를 만나게 된다. 이를 살펴보고 이를 어떻게 테스트 가능한 코드로 변경하는 지 파악한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;하드 코딩된 경로&lt;/h3&gt;
&lt;pre class=&quot;lsl&quot;&gt;&lt;code&gt;Path path = Paths.get(&quot;D:\\\\data\\\\pay\\\\cp0001.csv)
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하드 코딩된 경로뿐만 아니라 하드코딩된 IP 주소, 포트 번호도 테스트를 어렵게 만든다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;의존 객체를 직접 생성&lt;/h3&gt;
&lt;pre class=&quot;haxe&quot;&gt;&lt;code&gt;private PayInfoDao payInfoDao = new PayInfoDao();
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;테스트를 어렵게 만드는 또 다른요인은 의존 대상을 직접 생성하고 있다는 점이다. 해당 코드를 테스트 하려면 PatInfoDao가 올바르게 동작하는데 필요한 모든 환경을 구성해야한다. DB를 준비해야하고 필요한 테이블도 만들어야 한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;정적 메서드 사용&lt;/h3&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;public LoginResult login(String id, String pw) {
    int resp = authService.authenticate(id, pw);
    if (resp == -1) return LoginResult.badAuthKey();

    if (resp == 1) {
        Customer c = customerRepo.findOne(id);
        return LoginResult.authenticated(c);
    } else {
        return LoginResult.fail(resp);
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 코드는 AuthUtil 클래스의 정적 메서드를 사용하고 있다. AuthUtil 클래스가 인증 서버와 통신하는 경우 이 테스트하려면 동작하고 있는 인증 서버가 필요하다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;실행 시점에 따라 달라지는 결과&lt;/h3&gt;
&lt;pre class=&quot;ebnf&quot;&gt;&lt;code&gt;LocalDate now = LocalDate.now();
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;같은 테스트 코드라도 어제가지는 문제 없이 성공하던 코드가 오늘 실패할 수 있다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;역할이 섞여 있는 코드&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;포인트 계산 로직만 테스트하기 어렵다. 포인트 계산 자체는 이 두 DAO와 상관이 없다. 포인트 계산에 필요한 것은 두개의 DAO가 필요하기 때문이다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;그 외의 테스트가 어려운 코드&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;메서드 중간에 소켓 통신 코드가 포함한다.&lt;/li&gt;
&lt;li&gt;콘솔에서 입력을 받거나 결과를 콘솔에 출력한다.&lt;/li&gt;
&lt;li&gt;테스트 대상이 사용하는 의존 대상 클래스가 메서드가 final이다. 이 경우 대역으로 대체가 어려울 수 있다.&lt;/li&gt;
&lt;li&gt;테스트 대상의 소스를 소유하고 있지 않아 수정이 어렵다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;테스트 가능한 설계&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;하드 코딩된 상수를 생성자나 메서드 파라미터로 받기&lt;/h3&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;public void setFilePath(String filePath) {
    this.filePath = filePath;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;의존 대상을 주입 받기&lt;/h3&gt;
&lt;pre class=&quot;cpp&quot;&gt;&lt;code&gt;public void setPayInfoDao(PayInfoDao payInfoDao) {
    this.payInfoDao = payInfoDao;
}

&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;테스트하고 싶은 코드를 분리하기&lt;/h3&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;public class PointRule {

    public int calculate(Subscription s, Product p, LocalDate now) {
        int point = 0;
        if (s.isFinished(now)) {
            point += p.getDefaultPoint();
        } else {
            point += p.getDefaultPoint() + 10;
        }
        if (s.getGrade() == GOLD) {
            point += 100;
        }
        return point;
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;public int calculatePoint(User u) {
    Subscription s = subscriptionDao.selectByUser(u.getId());
    if (s == null) throw new NoSubscriptionException();
    Product p = productDao.selectById(s.getProductId());
    LocalDate now = times.today();
    return pointRule.calculate(s, p, now);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클래스로 분리하여테스가 가능하도록 한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;시간이나 임의 값 생성 기능 분리하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 일자를 구하는 기능을 분리하고 분리한 대상을 주입할 수 있게 변경하면 테스트를 원하는 상황으로 쉽게 제어할 수 있다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;외부 라이버리는 직접 사용하지 말고 감싸서 사용하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대역으로 대체하기 어려운 외부 라이브러리가 있다면 외부 라이브러리를 직접 사용하지 말고 외부 라이브러리와 연동하기 위한 타입을 따로 만든다. 테스트 대상 코드는 새로 분리한 타입을 사용함으로써 외부 연동으로 필요한 기능을 쉽게 대역으로 대체할 수 있게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Reference.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1676815460721&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;book&quot; data-og-title=&quot;테스트 주도 개발 시작하기 - YES24&quot; data-og-description=&quot;TDD(Test-Driven Development)는 테스트부터 시작한다. 구현을 먼저 하고 나중에 테스트하는 것이 아니라 먼저 테스트를 하고 그다음에 구현한다. 구현 코드가 없는데 어떻게 테스트할 수 있을까? 여기&quot; data-og-host=&quot;www.yes24.com&quot; data-og-source-url=&quot;http://www.yes24.com/Product/Goods/89145195&quot; data-og-url=&quot;http://www.yes24.com/Product/Goods/89145195&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/4XIVy/hyRwE5pJRQ/875syyPkf3KKmkkxfMPOD1/img.jpg?width=872&amp;amp;height=1200&amp;amp;face=0_0_872_1200,https://scrap.kakaocdn.net/dn/f6K6r/hyRwE5pJWD/V8ngxu85qDA913HN5AnEWK/img.jpg?width=872&amp;amp;height=1200&amp;amp;face=0_0_872_1200,https://scrap.kakaocdn.net/dn/BSM0l/hyRwzQypUz/8ExVV58VPrIq3kXEB7Tk1k/img.jpg?width=872&amp;amp;height=1200&amp;amp;face=0_0_872_1200&quot;&gt;&lt;a href=&quot;http://www.yes24.com/Product/Goods/89145195&quot; data-source-url=&quot;http://www.yes24.com/Product/Goods/89145195&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/4XIVy/hyRwE5pJRQ/875syyPkf3KKmkkxfMPOD1/img.jpg?width=872&amp;amp;height=1200&amp;amp;face=0_0_872_1200,https://scrap.kakaocdn.net/dn/f6K6r/hyRwE5pJWD/V8ngxu85qDA913HN5AnEWK/img.jpg?width=872&amp;amp;height=1200&amp;amp;face=0_0_872_1200,https://scrap.kakaocdn.net/dn/BSM0l/hyRwzQypUz/8ExVV58VPrIq3kXEB7Tk1k/img.jpg?width=872&amp;amp;height=1200&amp;amp;face=0_0_872_1200');&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;테스트 주도 개발 시작하기 - YES24&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;TDD(Test-Driven Development)는 테스트부터 시작한다. 구현을 먼저 하고 나중에 테스트하는 것이 아니라 먼저 테스트를 하고 그다음에 구현한다. 구현 코드가 없는데 어떻게 테스트할 수 있을까? 여기&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.yes24.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>TDD</category>
      <category>tdd</category>
      <author>큐범</author>
      <guid isPermaLink="true">https://kbcoding.tistory.com/116</guid>
      <comments>https://kbcoding.tistory.com/116#entry116comment</comments>
      <pubDate>Sun, 19 Feb 2023 23:05:04 +0900</pubDate>
    </item>
    <item>
      <title>[TDD] 대역</title>
      <link>https://kbcoding.tistory.com/115</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;외부 요인은 테스트 작성을 어렵게 만들 뿐만 아인라 테스트 결과도 예측할 수 없게 만든다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Double&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;영어로 된 테스트 관련 글을 읽으면 test double이란 표현이 자주 나오는데 여기서 double은 본 장에서 설명하는 대역에 해당한다. 즉, test double은 테스트에서 진짜 대신 사용할 대역을 의미한다.&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;대역종류 설명&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;대역종류&lt;/td&gt;
&lt;td&gt;설명&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;스텁(Stub)&lt;/td&gt;
&lt;td&gt;구현을 단순한 것으로 대체한다. 테스트에 맞게 단순히 원하는 동작을 수행한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;가짜(Fake)&lt;/td&gt;
&lt;td&gt;제품에는 적합하지 않지만, 실제 동작하는 구현을 제공한다. DB대신에 메모리를 이용해서 구현한 것과 같다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;스파이(Spy)&lt;/td&gt;
&lt;td&gt;호출된 내역을 기록한다. 기록한 내용은 테스트 결과를 검증할 때 사용한다. 스텁이기도 하다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;모의(Mock)&lt;/td&gt;
&lt;td&gt;기대한대로 상호작용하는지 행위를 검증한다. 기대한 대로 동작하지 않으면 익셉션을 발생할 수 있다. 모의 객체는 스텁이자 스파이기도 된다.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;구현 전에 설계해보기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구현전에 모든 기능을 설계하는 것은 불가능하다. 왜냐면 개발을 진행하는 동안에도 요구사항이 계속해서 바뀌기 때문이다. 그럼에도 불구하고 단위 기능을 구현하기에 앞서 어떤 구성 요소가 필요할지 고민하는 것은 의존 대상을 도출할 때 도움이 된다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;상황과 결과 확인을 위한 협업 대상(의존) 도출과 대역 사용&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한 테스트는 특정한 상황에서 기능을 실행하고 그 결과를 확인한다. 실제 구현을 이용하면 상황을 만들기 어려울 때가 많다. 제어하기 힘든 외부 상황이 존재하면 다음과 같은 방법으로 의존을 도출하고 이를 대역으로 대신할 수 있다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;제어하기 힘든 외부 상황을 별도 타입으로 분리&lt;/li&gt;
&lt;li&gt;테스트 코드는 별도로 분리한 타입의 대역을 생성&lt;/li&gt;
&lt;li&gt;생성한 대역을 테스트 대상의 생성자 등을 이용해서 전달&lt;/li&gt;
&lt;li&gt;대역을 이용해서 상황 구성&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대역은 의존하는 대상을 구현하지 않아도 테스트 대상을 완성할 수 있게 만들어주며 이는 대기 시간을 줄여주어 개발 속도를 올리는 데 도움이 된다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;모의 객체를 과하게 사용하지 않기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모의 객체는 스텁과 스파이를 지원하므로 대역으로 모의 객체를 많이 사용한다. 모의 객체를 이용하면 대역 클래스를 만들지 않아도 되니까 처음에는 편할 수 있다. 하지만 결과 값을 확인하는 수단으로 모의 객체를 사용하기 시작하면 결과 검증 코드가 길어지고 복잡해진다. 특히 하나의 테스트를 위해 여러 모의 객체를 사용하기 시작하면 결과 검증 코드의 복잡도는 배로 증가한다. 게다가 모의 객체는 기본적으로 메서드 호출 여부를 검증하는 수단이기 때문에 테스트 대상과 모의 객체 간의 상호 작용이 조금만 바뀌어도 테스트가 깨지기 쉽다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DAO나 리포지토리와 같이 저장소에 대한 대역은 메모리를 이용한 가짜 구현을 사용하는 것이 테스트 코드 관리에 유리하다.&lt;/p&gt;
&lt;p data-ke-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;h4 data-ke-size=&quot;size20&quot;&gt;Reference.&lt;/h4&gt;
&lt;figure id=&quot;og_1676220653981&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;book&quot; data-og-title=&quot;테스트 주도 개발 시작하기 - YES24&quot; data-og-description=&quot;TDD(Test-Driven Development)는 테스트부터 시작한다. 구현을 먼저 하고 나중에 테스트하는 것이 아니라 먼저 테스트를 하고 그다음에 구현한다. 구현 코드가 없는데 어떻게 테스트할 수 있을까? 여기&quot; data-og-host=&quot;www.yes24.com&quot; data-og-source-url=&quot;http://www.yes24.com/Product/Goods/89145195&quot; data-og-url=&quot;http://www.yes24.com/Product/Goods/89145195&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/4XIVy/hyRwE5pJRQ/875syyPkf3KKmkkxfMPOD1/img.jpg?width=872&amp;amp;height=1200&amp;amp;face=0_0_872_1200,https://scrap.kakaocdn.net/dn/f6K6r/hyRwE5pJWD/V8ngxu85qDA913HN5AnEWK/img.jpg?width=872&amp;amp;height=1200&amp;amp;face=0_0_872_1200,https://scrap.kakaocdn.net/dn/BSM0l/hyRwzQypUz/8ExVV58VPrIq3kXEB7Tk1k/img.jpg?width=872&amp;amp;height=1200&amp;amp;face=0_0_872_1200&quot;&gt;&lt;a href=&quot;http://www.yes24.com/Product/Goods/89145195&quot; data-source-url=&quot;http://www.yes24.com/Product/Goods/89145195&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/4XIVy/hyRwE5pJRQ/875syyPkf3KKmkkxfMPOD1/img.jpg?width=872&amp;amp;height=1200&amp;amp;face=0_0_872_1200,https://scrap.kakaocdn.net/dn/f6K6r/hyRwE5pJWD/V8ngxu85qDA913HN5AnEWK/img.jpg?width=872&amp;amp;height=1200&amp;amp;face=0_0_872_1200,https://scrap.kakaocdn.net/dn/BSM0l/hyRwzQypUz/8ExVV58VPrIq3kXEB7Tk1k/img.jpg?width=872&amp;amp;height=1200&amp;amp;face=0_0_872_1200');&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;테스트 주도 개발 시작하기 - YES24&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;TDD(Test-Driven Development)는 테스트부터 시작한다. 구현을 먼저 하고 나중에 테스트하는 것이 아니라 먼저 테스트를 하고 그다음에 구현한다. 구현 코드가 없는데 어떻게 테스트할 수 있을까? 여기&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.yes24.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>TDD</category>
      <author>큐범</author>
      <guid isPermaLink="true">https://kbcoding.tistory.com/115</guid>
      <comments>https://kbcoding.tistory.com/115#entry115comment</comments>
      <pubDate>Mon, 13 Feb 2023 01:51:17 +0900</pubDate>
    </item>
    <item>
      <title>[TDD] 테스트 코드의 구성</title>
      <link>https://kbcoding.tistory.com/114</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;이번 주차 블로그 글은 GDSC에서 제가 직접한 글을 첨부하도록 하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1675685762071&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;[TDD] 5. 테스트 코드의 구성&quot; data-og-description=&quot;작성자 : 한규범 기능에서의 상황 주어진 상황에 따라 기능 실행 결과는 달라진다. 이는 테스트 코드 구조에도 영향을 주는데 이에 관한 내용을 이어서 살표보자. 상황 찾기 노련한 개발자는 어&quot; data-og-host=&quot;gdsc-mju.tistory.com&quot; data-og-source-url=&quot;https://gdsc-mju.tistory.com/26&quot; data-og-url=&quot;https://gdsc-mju.tistory.com/26&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/dmMkor/hyRwGvpB4b/6OjThBeKovwTbAaLORCOM0/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/cj7153/hyRwGa5ywI/pIOH73jMt3JwhGNQlRchvk/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800&quot;&gt;&lt;a href=&quot;https://gdsc-mju.tistory.com/26&quot; data-source-url=&quot;https://gdsc-mju.tistory.com/26&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/dmMkor/hyRwGvpB4b/6OjThBeKovwTbAaLORCOM0/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/cj7153/hyRwGa5ywI/pIOH73jMt3JwhGNQlRchvk/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800');&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;[TDD] 5. 테스트 코드의 구성&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;gdsc-mju.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Reference.&lt;/p&gt;
&lt;figure id=&quot;og_1675685820316&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;book&quot; data-og-title=&quot;테스트 주도 개발 시작하기 - YES24&quot; data-og-description=&quot;TDD(Test-Driven Development)는 테스트부터 시작한다. 구현을 먼저 하고 나중에 테스트하는 것이 아니라 먼저 테스트를 하고 그다음에 구현한다. 구현 코드가 없는데 어떻게 테스트할 수 있을까? 여기&quot; data-og-host=&quot;www.yes24.com&quot; data-og-source-url=&quot;http://www.yes24.com/Product/Goods/89145195&quot; data-og-url=&quot;http://www.yes24.com/Product/Goods/89145195&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/4XIVy/hyRwE5pJRQ/875syyPkf3KKmkkxfMPOD1/img.jpg?width=872&amp;amp;height=1200&amp;amp;face=0_0_872_1200,https://scrap.kakaocdn.net/dn/f6K6r/hyRwE5pJWD/V8ngxu85qDA913HN5AnEWK/img.jpg?width=872&amp;amp;height=1200&amp;amp;face=0_0_872_1200,https://scrap.kakaocdn.net/dn/BSM0l/hyRwzQypUz/8ExVV58VPrIq3kXEB7Tk1k/img.jpg?width=872&amp;amp;height=1200&amp;amp;face=0_0_872_1200&quot;&gt;&lt;a href=&quot;http://www.yes24.com/Product/Goods/89145195&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;http://www.yes24.com/Product/Goods/89145195&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/4XIVy/hyRwE5pJRQ/875syyPkf3KKmkkxfMPOD1/img.jpg?width=872&amp;amp;height=1200&amp;amp;face=0_0_872_1200,https://scrap.kakaocdn.net/dn/f6K6r/hyRwE5pJWD/V8ngxu85qDA913HN5AnEWK/img.jpg?width=872&amp;amp;height=1200&amp;amp;face=0_0_872_1200,https://scrap.kakaocdn.net/dn/BSM0l/hyRwzQypUz/8ExVV58VPrIq3kXEB7Tk1k/img.jpg?width=872&amp;amp;height=1200&amp;amp;face=0_0_872_1200');&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;테스트 주도 개발 시작하기 - YES24&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;TDD(Test-Driven Development)는 테스트부터 시작한다. 구현을 먼저 하고 나중에 테스트하는 것이 아니라 먼저 테스트를 하고 그다음에 구현한다. 구현 코드가 없는데 어떻게 테스트할 수 있을까? 여기&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.yes24.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>TDD</category>
      <author>큐범</author>
      <guid isPermaLink="true">https://kbcoding.tistory.com/114</guid>
      <comments>https://kbcoding.tistory.com/114#entry114comment</comments>
      <pubDate>Mon, 6 Feb 2023 21:17:09 +0900</pubDate>
    </item>
    <item>
      <title>[TDD] JUnit5 기초</title>
      <link>https://kbcoding.tistory.com/113</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;Junit5 모듈 구성&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Junit5는 크게 세 개의 요소로 구성되어 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JUnit 플랫폼: 테스팅 프레임워크를 구동하기 위한 런처와 테스트 엔진을 위한 API를 제공한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JUnit 주피터(Jupiter): JUnit5를 위한 테스트 API와 실행 엔진을 제공한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JUnit 빈티지(Vintage): Junit 3과 4로 작성된 테스트를 Junit5 플랫폼에서 실행하기 위한 모듈을 제공한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-01-29 오전 12.07.09.png&quot; data-origin-width=&quot;1228&quot; data-origin-height=&quot;600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/egBmHF/btrXmRT1BsB/0c9cD4uinsgLOKdZn2KwM0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/egBmHF/btrXmRT1BsB/0c9cD4uinsgLOKdZn2KwM0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/egBmHF/btrXmRT1BsB/0c9cD4uinsgLOKdZn2KwM0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FegBmHF%2FbtrXmRT1BsB%2F0c9cD4uinsgLOKdZn2KwM0%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;1228&quot; height=&quot;600&quot; data-filename=&quot;스크린샷 2023-01-29 오전 12.07.09.png&quot; data-origin-width=&quot;1228&quot; data-origin-height=&quot;600&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Junit5 는 테스트를 위한 API로 주피터 API를 제공한다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;@Test 애노테이션과 테스트 메서드&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JUnit 모듈을 설정했다면 JUnit을 이용해서 테스트 코드를 작성하고 실행할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Junit의 Assertions 클래스는 assertEquals() 메서드와 같이 값을 검증하기 위한 목적의 다양한 정적 메서드를 제공한다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;public class SumTest {

    @Test
    public void sum(){
        int result = 2 + 3;
        Assertions.assertEquals(5,result);
     }
     
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;주요 단언 메서드&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메서드 설명&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;메서드&lt;/td&gt;
&lt;td&gt;설명&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;assertEquals(expected, actual)&lt;/td&gt;
&lt;td&gt;실제 값(actual)이 기대하는 값(expectec)과 같은지 검사한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;assertNotEquals(unexpected, actual)&lt;/td&gt;
&lt;td&gt;실제 값(actual)이 특정 값(unexpected)과 같지 않은지 검사한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;assertSame(Object expected, Object actual)&lt;/td&gt;
&lt;td&gt;두 객체가 동일한 객체인지 검사한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;assertNotSame(Object unexpected, Object actual)&lt;/td&gt;
&lt;td&gt;두 객체가 동일하지 않은 객체인지 검사한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;assertTrue(boolean condition)&lt;/td&gt;
&lt;td&gt;값이 true인지 검사한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;assertFalse(boolean condition)&lt;/td&gt;
&lt;td&gt;값이 false인지 검사한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;assertNull(Object actual)&lt;/td&gt;
&lt;td&gt;값이 null인지 검사한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;assertNotNull(Object actual)&lt;/td&gt;
&lt;td&gt;값이 null이 아닌지 검사한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;fail()&lt;/td&gt;
&lt;td&gt;테스트를 실패 처리한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Exception관련 메서드&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메서드 설명&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;메서드&lt;/td&gt;
&lt;td&gt;설명&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;assertThrows(Class&amp;lt;T&amp;gt; expectedType, Executable excutable)&lt;/td&gt;
&lt;td&gt;executable을 실행한 결과로 지정한 타입의 익셉션이 발생하는지 검사한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;assertDoesBotThrow(Executable executable)&lt;/td&gt;
&lt;td&gt;executable을 실행한 결과로 익셉션이 발생하지 않는지 검사한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;경우에 따라 일단 모든 검증을 실행하고 그중에 실패한 것이 있는지 확인하고 싶을 때가 있다. 이럴때 사용할 수 있는 것이 assertAll() 메서드이다. 다음은 assertAll() 메서드의 사용 예이다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;assertAll(
        () -&amp;gt; assertEquals(3,5/2),
        () -&amp;gt; assertEquals(4,2*2),
        () -&amp;gt; assertEquals(6,11/2)
);
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;테스트 라이프 사이클&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;@BeforeEach 애노테이션과 @AfterEach 애노테이션&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;jUnit은 각 테스트 메서드마다 다음 순서대로 코드를 실행한다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;테스트 메서드를 포함한 객체 생성&lt;/li&gt;
&lt;li&gt;(존재하면) @BeforeEach 애노테이션이 붙은 메서드 실행&lt;/li&gt;
&lt;li&gt;@Test 애노테이션이 붙은 메서드 실행&lt;/li&gt;
&lt;li&gt;(존재하면) @After 애노테이션이 붙은 메서드 실행&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;public class LifecycleTest {

    public LifecycleTest(){
        System.out.println(&quot;new LifecycleTest&quot;);
    }

    @BeforeEach
    void setUp(){
        System.out.println(&quot;setUp&quot;);
    }

    @Test
    void a(){
        System.out.println(&quot;A&quot;);
    }

    @Test
    void b(){
        System.out.println(&quot;B&quot;);
    }

    @AfterEach
    void tearDown(){
        System.out.println(&quot;tearDown&quot;);
    }

}

&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결과&lt;/p&gt;
&lt;pre class=&quot;haxe&quot;&gt;&lt;code&gt;new LifecycleTest
setUp
A
tearDown
new LifecycleTest
setUp
B
tearDown
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;@BeforEach : 테스트를 실행하는데 필요한 준비 작업을 할 때 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;@AfterEach : 테스트를 실행한 후에 정리할 것이 있을 때 사용한다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;BeforeAll 애노테이션과 AfterAll 애노테이션&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;@BeforeAll : 정적 메서드에 붙이는데 이 메서드는 클래스의 모든 테스트 메서드를 실행하기 전에 한 번 실행된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;@AfterAll : 클래스의 모든 테스트 메서드를 실행한 뒤애 실행된다. 이 역시 정적 메서드에 적용한다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;테스트 메서드간 실행 순서 의존과 필드 공유하지 않기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 테스트 메서드는 서로 독립적으로 동작해야한다. 한 테스트 메서드의 결과에 따라 다른 테스트 메서드의 실행 결과가 달라지면 안 된다. 그런 의미에서 테스트 메서드가 서로 필드를 공유한다거나 실행 순서를 가정하고 테스트를 작성하지 말아야한다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;추가 애노티에션 : @DisplayName, @Disabled&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;@DisplayName : 테스트에 표시 이름을 붙일 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;@Disabled : 특정 테스트를 실행하지 않고 싶을 때 사용한다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;모든 테스트 실행 명령어&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;mvn test (래퍼를 사용하는 경우 mvnw test)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;gradle test (래퍼를 사용하는 경우 gradlew test)&lt;/p&gt;
&lt;p data-ke-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;figure id=&quot;og_1674918693888&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;5주차 - JUnit 5 기초 - 한규범 &amp;middot; Issue #49 &amp;middot; GDSC-MYONGJI/22-23-TDD-Study&quot; data-og-description=&quot;⭐ Chapter 5. JUnit 5 기초 JUnit 5 모듈 구성, 애노테이션과 메서드들과 라이프 사이클 등을 이해하고 테스트 코드를 더 능숙하게 작성할 수 있도록 한다. JUnit 5에 대해 알아보고, 숙지하기 Chap 5의 내&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/GDSC-MYONGJI/22-23-TDD-Study/issues/49&quot; data-og-url=&quot;https://github.com/GDSC-MYONGJI/22-23-TDD-Study/issues/49&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/tcHx8/hyRqZVcFQa/tie15ay6PSo2uzVKELUIk1/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/GDSC-MYONGJI/22-23-TDD-Study/issues/49&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/GDSC-MYONGJI/22-23-TDD-Study/issues/49&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/tcHx8/hyRqZVcFQa/tie15ay6PSo2uzVKELUIk1/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;5주차 - JUnit 5 기초 - 한규범 &amp;middot; Issue #49 &amp;middot; GDSC-MYONGJI/22-23-TDD-Study&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;⭐ Chapter 5. JUnit 5 기초 JUnit 5 모듈 구성, 애노테이션과 메서드들과 라이프 사이클 등을 이해하고 테스트 코드를 더 능숙하게 작성할 수 있도록 한다. JUnit 5에 대해 알아보고, 숙지하기 Chap 5의 내&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;Reference.&lt;/p&gt;
&lt;figure id=&quot;og_1674918544795&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;book&quot; data-og-title=&quot;테스트 주도 개발 시작하기 - YES24&quot; data-og-description=&quot;TDD(Test-Driven Development)는 테스트부터 시작한다. 구현을 먼저 하고 나중에 테스트하는 것이 아니라 먼저 테스트를 하고 그다음에 구현한다. 구현 코드가 없는데 어떻게 테스트할 수 있을까? 여기&quot; data-og-host=&quot;www.yes24.com&quot; data-og-source-url=&quot;http://www.yes24.com/Product/Goods/89145195&quot; data-og-url=&quot;http://www.yes24.com/Product/Goods/89145195&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/jqq4x/hyRqZVcCkb/6DGYj7nOSpJhzowdIWreY0/img.jpg?width=872&amp;amp;height=1200&amp;amp;face=0_0_872_1200,https://scrap.kakaocdn.net/dn/6q11x/hyRpPfDKiD/DSiIRTOIeLNoPuFgwk2Zr0/img.jpg?width=872&amp;amp;height=1200&amp;amp;face=0_0_872_1200,https://scrap.kakaocdn.net/dn/blKbVy/hyRpGbUnKW/H5ekzWUU72mgRWkKWDaxik/img.jpg?width=872&amp;amp;height=1200&amp;amp;face=0_0_872_1200&quot;&gt;&lt;a href=&quot;http://www.yes24.com/Product/Goods/89145195&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;http://www.yes24.com/Product/Goods/89145195&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/jqq4x/hyRqZVcCkb/6DGYj7nOSpJhzowdIWreY0/img.jpg?width=872&amp;amp;height=1200&amp;amp;face=0_0_872_1200,https://scrap.kakaocdn.net/dn/6q11x/hyRpPfDKiD/DSiIRTOIeLNoPuFgwk2Zr0/img.jpg?width=872&amp;amp;height=1200&amp;amp;face=0_0_872_1200,https://scrap.kakaocdn.net/dn/blKbVy/hyRpGbUnKW/H5ekzWUU72mgRWkKWDaxik/img.jpg?width=872&amp;amp;height=1200&amp;amp;face=0_0_872_1200');&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;테스트 주도 개발 시작하기 - YES24&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;TDD(Test-Driven Development)는 테스트부터 시작한다. 구현을 먼저 하고 나중에 테스트하는 것이 아니라 먼저 테스트를 하고 그다음에 구현한다. 구현 코드가 없는데 어떻게 테스트할 수 있을까? 여기&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.yes24.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>TDD</category>
      <author>큐범</author>
      <guid isPermaLink="true">https://kbcoding.tistory.com/113</guid>
      <comments>https://kbcoding.tistory.com/113#entry113comment</comments>
      <pubDate>Sun, 29 Jan 2023 00:11:37 +0900</pubDate>
    </item>
    <item>
      <title>[TDD] 기능 명세 ∙ 설계</title>
      <link>https://kbcoding.tistory.com/112</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;기능 명세&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발자는 코드를 작성하고 빌드하여 이를 사용자가 사용할 수 있게 배포한다. 설계는 기능 명세로부터 시작한다. 스토리보드를 포함한 다양한 형태의 요구사항 문서를 이용해서 기능 명세를 구체화한다. 기능 명세를 구체화하는 동안 입력과 결과를 도출하고 이렇게 도출한 기능 명세를 코드에 반영한다. 기능 명세의 입력과 결과를 코드에 반영하는 과정에서 기능의 이름, 파라미터, 리턴 타입 등이 결정된다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;설계 과정을 지원하는 TDD&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TDD에서 가장 중요한 것을 테스트 코드를 먼저 작성한다는 점이다. 리턴 타입과 파라미터 타입에 대해서 고민은 곧 설계 과정이다. 타입의 이름을 정의하고 타입이 제공할 기능을 결정하는 것은 기본 적인 설계 행위이다. TDD 자체가 설계는 아니지만, TDD를 하다 보면 테스트 코드를 작성하는 과정에서 일부 설계를 진행하게 된다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;이름&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&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;TDD는 테스트를 통과할 만큼만 코드를 작성한다. 필요한 것으로 예측해서 미리 코드를 만들지 않는다. 유연한 설계는 필요한 시점에 추가하고 설계가 불필요해지는 것을 방지한다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;기능 명세 구체화&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모호한 상황을 만나면 이를 구체적인 예로 바꾸어 테스트 코드에 반영한다. 즉 테스트 코드는 예를 이용한 구체적인 명세가 된다. 구체적인 예는 개발자가 요구사항을 더 잘 이해할 수 있도록 만든다. &lt;b&gt;복잡한 로직을 구현하는 것은 결국 개발자&lt;/b&gt; 이므로 개발자는 최대한 예외적인 상황이나 복잡한 상황에 해당하는 구체적인 예를 끄집어내야 한다. 이를 위한 가장 좋은 방법은 담당자와 대화를 하는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1674191799455&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;4주차 - TDD ∙ 기능 명세 ∙ 설계 - 한규범 &amp;middot; Issue #40 &amp;middot; GDSC-MYONGJI/22-23-TDD-Study&quot; data-og-description=&quot;#37 ⭐ Chapter 4. TDD ∙ 기능 명세 ∙ 설계 설계하고 정의하는 과정을 TDD와 함께 정리해본다. 기능 명세, 설계 및 구체화 과정 이해하기 Chap 4의 내용을 개인 기술 블로그에 정리한 후 자신의 issue에 c&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/GDSC-MYONGJI/22-23-TDD-Study/issues/40&quot; data-og-url=&quot;https://github.com/GDSC-MYONGJI/22-23-TDD-Study/issues/40&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/b2ulkB/hyRlvmut1e/2pP0JsMHH2N7k6q1viGx31/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/GDSC-MYONGJI/22-23-TDD-Study/issues/40&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/GDSC-MYONGJI/22-23-TDD-Study/issues/40&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/b2ulkB/hyRlvmut1e/2pP0JsMHH2N7k6q1viGx31/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;4주차 - TDD ∙ 기능 명세 ∙ 설계 - 한규범 &amp;middot; Issue #40 &amp;middot; GDSC-MYONGJI/22-23-TDD-Study&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;#37 ⭐ Chapter 4. TDD ∙ 기능 명세 ∙ 설계 설계하고 정의하는 과정을 TDD와 함께 정리해본다. 기능 명세, 설계 및 구체화 과정 이해하기 Chap 4의 내용을 개인 기술 블로그에 정리한 후 자신의 issue에 c&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;Reference.&lt;/p&gt;
&lt;figure id=&quot;og_1674191778456&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;book&quot; data-og-title=&quot;테스트 주도 개발 시작하기 - YES24&quot; data-og-description=&quot;TDD(Test-Driven Development)는 테스트부터 시작한다. 구현을 먼저 하고 나중에 테스트하는 것이 아니라 먼저 테스트를 하고 그다음에 구현한다. 구현 코드가 없는데 어떻게 테스트할 수 있을까? 여기&quot; data-og-host=&quot;www.yes24.com&quot; data-og-source-url=&quot;http://www.yes24.com/Product/Goods/89145195&quot; data-og-url=&quot;http://www.yes24.com/Product/Goods/89145195&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/csr4Vu/hyRgv8Zogw/fSblHFiHAhARNaVYOL8ZYK/img.jpg?width=872&amp;amp;height=1200&amp;amp;face=0_0_872_1200,https://scrap.kakaocdn.net/dn/V1Qdu/hyRgl6kazS/dGc0zKpxL4ctlql8fmboQK/img.jpg?width=872&amp;amp;height=1200&amp;amp;face=0_0_872_1200,https://scrap.kakaocdn.net/dn/cu9yag/hyRhJLgpBk/w5bKHwdfdIIuVkteBWej01/img.jpg?width=872&amp;amp;height=1200&amp;amp;face=0_0_872_1200&quot;&gt;&lt;a href=&quot;http://www.yes24.com/Product/Goods/89145195&quot; data-source-url=&quot;http://www.yes24.com/Product/Goods/89145195&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/csr4Vu/hyRgv8Zogw/fSblHFiHAhARNaVYOL8ZYK/img.jpg?width=872&amp;amp;height=1200&amp;amp;face=0_0_872_1200,https://scrap.kakaocdn.net/dn/V1Qdu/hyRgl6kazS/dGc0zKpxL4ctlql8fmboQK/img.jpg?width=872&amp;amp;height=1200&amp;amp;face=0_0_872_1200,https://scrap.kakaocdn.net/dn/cu9yag/hyRhJLgpBk/w5bKHwdfdIIuVkteBWej01/img.jpg?width=872&amp;amp;height=1200&amp;amp;face=0_0_872_1200');&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;테스트 주도 개발 시작하기 - YES24&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;TDD(Test-Driven Development)는 테스트부터 시작한다. 구현을 먼저 하고 나중에 테스트하는 것이 아니라 먼저 테스트를 하고 그다음에 구현한다. 구현 코드가 없는데 어떻게 테스트할 수 있을까? 여기&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.yes24.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>TDD</category>
      <category>chap 4</category>
      <category>tdd</category>
      <category>테스트 주도 개발 시작하기</category>
      <author>큐범</author>
      <guid isPermaLink="true">https://kbcoding.tistory.com/112</guid>
      <comments>https://kbcoding.tistory.com/112#entry112comment</comments>
      <pubDate>Fri, 20 Jan 2023 14:17:38 +0900</pubDate>
    </item>
    <item>
      <title>[TDD] 테스트 코드 작성 순서</title>
      <link>https://kbcoding.tistory.com/111</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;테스트 코드 작성 순서&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;쉬운 경우에서 어려운 경우로 진행&lt;/li&gt;
&lt;li&gt;예외적인 경우에서 정상인 경우로 진행&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;초반에 복잡한 테스트부터 시작하면 안되는 이유&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&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;가장 구현하기 쉬운 경우부터 시작하면 빠르게 테스트를 통과시킬 수 있다. 보통 수 분에서 십여분 이내에 구현을 완료해서 테스트를 통과시킬 수 있을 만큼 쉬운 것을 선택한다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;예외상황을 먼저 테스트해야 하는 이유&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예외상황을 전혀 고려하지 않은 코드에 예외 상황을 반영하려면 코드의 구조를 뒤집거나 코드 중간에 예외 상황을 처리하기 위해 조건문을 중복해서 추가하는 일이 벌어진다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;완급조절&lt;/h2&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;정해진 값을 리턴&lt;/li&gt;
&lt;li&gt;값 비교를 이용해서 정해진 값을 리턴&lt;/li&gt;
&lt;li&gt;다양한 테스트를 추가하면서 구현을 일반화&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;뻔한 구현이라도 위 단계를 거쳐서 연습하는 것과 바로 구현하는 것에는 차이가 있다. 단계적으로 나아가는 연습을 하지 않는 개발자는 조금만 구현이 떠오르지 않아도 진전을 이루지 못하고 막혀 있거나 한 번에 많은 코드를 구현하려고 시도하다 구현에 실패하게 된다. 중요한 것은 테스트 - 구현 - 확인이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;구현코드에 대해서 분리하고 생각해내며 코드를 작성하는 것을 연습해야한다. 한번에 많은 구현을 하려는 것은 버그를 야기한다.&lt;/b&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;테스트를 통과한 뒤에는 적당한 후보가 보이면 리팩토링을 진행한다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;테스트 작성 순서 연습&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;매달 비용을 지불해야 사용할 수 있는 유료 서비스를 가정한다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;서비스를 사용하려면 매달 1만원을 선불로 납부한다. 납부일 기준으로 한 달 뒤가 서비스 만료일이 된다.&lt;/li&gt;
&lt;li&gt;2개월 이상 요금을 납부할 수 있다.&lt;/li&gt;
&lt;li&gt;10만원을 납부하면 서비스를 1년 제공한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 테스트를 추가하기 전에 리팩토링&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메서드의 파라미터 개수가 세 개 이상이면 객체로 바꿔 한 개로 줄이는 것을 고려해야한다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;시작이 안 될 때는 단언부터 고민&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&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;TDD를 하다 구현이 막힐 때가 있다. 과감하게 코드를 지우고 미련없이 다시 시작한다. 어떤 순서로 테스트 코드를 작성했는지 돌이켜보고 순서를 바꿔서 다시 진행한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;쉬운 테스트, 예외적인 테스트&lt;/li&gt;
&lt;li&gt;완급조절&lt;/li&gt;
&lt;/ul&gt;
&lt;figure id=&quot;og_1673614218855&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;3주차 - 테스트 코드 작성 순서 - 한규범 &amp;middot; Issue #25 &amp;middot; GDSC-MYONGJI/22-23-TDD-Study&quot; data-og-description=&quot;⭐ Chapter 3. 테스트 코드 작성 순서 어떤 테스트로 시작해야 하는지, 우선시 되어야 하는 테스트는 무엇인지를 공부하고 완급 조절을 통해 TDD에 보다 능숙해질 수 있도록 한다. 테스트 작성 순서 &quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/GDSC-MYONGJI/22-23-TDD-Study/issues/25&quot; data-og-url=&quot;https://github.com/GDSC-MYONGJI/22-23-TDD-Study/issues/25&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bsr9V0/hyRhOZ6AMq/omSUcA51va9dgtfv0EJvHK/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/GDSC-MYONGJI/22-23-TDD-Study/issues/25&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/GDSC-MYONGJI/22-23-TDD-Study/issues/25&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bsr9V0/hyRhOZ6AMq/omSUcA51va9dgtfv0EJvHK/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;3주차 - 테스트 코드 작성 순서 - 한규범 &amp;middot; Issue #25 &amp;middot; GDSC-MYONGJI/22-23-TDD-Study&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;⭐ Chapter 3. 테스트 코드 작성 순서 어떤 테스트로 시작해야 하는지, 우선시 되어야 하는 테스트는 무엇인지를 공부하고 완급 조절을 통해 TDD에 보다 능숙해질 수 있도록 한다. 테스트 작성 순서&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;figure id=&quot;og_1673614102692&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;book&quot; data-og-title=&quot;테스트 주도 개발 시작하기 - YES24&quot; data-og-description=&quot;TDD(Test-Driven Development)는 테스트부터 시작한다. 구현을 먼저 하고 나중에 테스트하는 것이 아니라 먼저 테스트를 하고 그다음에 구현한다. 구현 코드가 없는데 어떻게 테스트할 수 있을까? 여기&quot; data-og-host=&quot;www.yes24.com&quot; data-og-source-url=&quot;http://www.yes24.com/Product/Goods/89145195&quot; data-og-url=&quot;http://www.yes24.com/Product/Goods/89145195&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/csr4Vu/hyRgv8Zogw/fSblHFiHAhARNaVYOL8ZYK/img.jpg?width=872&amp;amp;height=1200&amp;amp;face=0_0_872_1200,https://scrap.kakaocdn.net/dn/V1Qdu/hyRgl6kazS/dGc0zKpxL4ctlql8fmboQK/img.jpg?width=872&amp;amp;height=1200&amp;amp;face=0_0_872_1200,https://scrap.kakaocdn.net/dn/cu9yag/hyRhJLgpBk/w5bKHwdfdIIuVkteBWej01/img.jpg?width=872&amp;amp;height=1200&amp;amp;face=0_0_872_1200&quot;&gt;&lt;a href=&quot;http://www.yes24.com/Product/Goods/89145195&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;http://www.yes24.com/Product/Goods/89145195&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/csr4Vu/hyRgv8Zogw/fSblHFiHAhARNaVYOL8ZYK/img.jpg?width=872&amp;amp;height=1200&amp;amp;face=0_0_872_1200,https://scrap.kakaocdn.net/dn/V1Qdu/hyRgl6kazS/dGc0zKpxL4ctlql8fmboQK/img.jpg?width=872&amp;amp;height=1200&amp;amp;face=0_0_872_1200,https://scrap.kakaocdn.net/dn/cu9yag/hyRhJLgpBk/w5bKHwdfdIIuVkteBWej01/img.jpg?width=872&amp;amp;height=1200&amp;amp;face=0_0_872_1200');&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;테스트 주도 개발 시작하기 - YES24&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;TDD(Test-Driven Development)는 테스트부터 시작한다. 구현을 먼저 하고 나중에 테스트하는 것이 아니라 먼저 테스트를 하고 그다음에 구현한다. 구현 코드가 없는데 어떻게 테스트할 수 있을까? 여기&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.yes24.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>TDD</category>
      <category>tdd</category>
      <category>테스트 주도 개발</category>
      <category>테스트 코드</category>
      <author>큐범</author>
      <guid isPermaLink="true">https://kbcoding.tistory.com/111</guid>
      <comments>https://kbcoding.tistory.com/111#entry111comment</comments>
      <pubDate>Fri, 13 Jan 2023 21:49:51 +0900</pubDate>
    </item>
    <item>
      <title>[TDD] 시작하기</title>
      <link>https://kbcoding.tistory.com/110</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;TDD, 즉 테스트 주도 개발(Test-driven Development)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;테스트부터 시작한다. 구현을 먼저하고 나중에 테스트하는 것이 아니라 &lt;b&gt;먼저 테스트를 하고 그 다음에 구현한다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TDD 예: 암호 검사기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;검사할 규칙&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;길이가 8글자 이상&lt;/li&gt;
&lt;li&gt;0부터 9사이의 숫자를 포함&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;3개의 규칙을 충족하면 암호는 강함&lt;/li&gt;
&lt;li&gt;2개의 규칙을 충족하면 암호는 보통&lt;/li&gt;
&lt;li&gt;1개의 규칙을 충족하면 암호는 약함&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;assertEquals(기댓값,결과값);&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;테스트 코드 작성&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;첫 번째 테스트 - 모든 규칙을 충족하는 경우&lt;/h3&gt;
&lt;pre class=&quot;crystal&quot;&gt;&lt;code&gt;public enum PasswordStrength {
	INVALID,NORMAL,STRONG
}
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;@Test
void meetsAllCriteria_Then_Strong(){
    PasswordStrengthMeter meter = new PasswordStrengthMeter();
    PasswordStrength result = meter.meter(&quot;ab12!@AB&quot;);
    assertEquals(PasswordStrength.STRONG, result);
    PasswordStrength result2 = meter.meter(&quot;abc1!Add&quot;);
    assertEquals(PasswordStrength.STRONG, result2);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;두 번째 테스트 - 길이만 8글자 미만이고 나머지 조건은 충족하는 경우&lt;/h3&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;@Test
void meetsOtherCriteria_except_for_Length_Then_Normal(){
    PasswordStrengthMeter meter = new PasswordStrengthMeter();
    PasswordStrength result = meter.meter(&quot;ab12!@A&quot;);
    assertEquals(PasswordStrength.NORMAL,result);
    PasswordStrength result2 = meter.meter(&quot;Ab12!c&quot;);
    assertEquals(PasswordStrength.NORMAL,result2);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;세번째 테스트 - 숫자를 포함하지 않고 나머지 조건은 충족하는 경우&lt;/h3&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;@Test
void meetsOtherCriteria_except_for_number_The_Normal(){
    PasswordStrengthMeter meter = new PasswordStrengthMeter();
    PasswordStrength result = meter.meter(&quot;ab!@ABqwer&quot;);
    assertEquals(PasswordStrength.NORMAL,result);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;코드 정리 - 중복 제거&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 중복코드를 제거하면 첫 번째 예시 기준으로 다음과 같은 코드가 된다.&lt;/p&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;public class PasswordStrengthMeterTest {

    private PasswordStrengthMeter meter = new PasswordStrengthMeter();

    @Test
    void meetsAllCriteria_Then_Strong(){
        PasswordStrength result = meter.meter(&quot;ab12!@AB&quot;);
        assertEquals(PasswordStrength.STRONG, result);
        PasswordStrength result2 = meter.meter(&quot;abc1!Add&quot;);
        assertEquals(PasswordStrength.STRONG, result2);
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 중복 코드를&lt;/p&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;PasswordStrength result = meter.meter(&quot;ab12!@AB&quot;);
assertEquals(PasswordStrength.STRONG, result);
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래와 같이 메서드를 생성해&lt;/p&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;private void assertStrength(String password, PasswordStrength expStr){
    PasswordStrength result = this.meter.meter(password);
    assertEquals(expStr,result);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래와 같이 중복 코드를 제거한다.&lt;/p&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;@Test
void meetsAllCriteria_Then_Strong(){
    assertStrength(&quot;ab12!@AB&quot;,PasswordStrength.STRONG);
    assertStrength(&quot;abc1!Add&quot;,PasswordStrength.STRONG);
}

@Test
void meetsOtherCriteria_except_for_Length_Then_Normal(){
    assertStrength(&quot;ab12!@A&quot;,PasswordStrength.NORMAL);
    assertStrength(&quot;Ab12!c&quot;,PasswordStrength.NORMAL);
}

@Test
void meetsOtherCriteria_except_for_number_The_Normal(){
    assertStrength(&quot;ab!@ABqwer&quot;,PasswordStrength.NORMAL);
}

&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;주의할 점 : 중복을 제거 이후에도 꼭 테스트 코드를 실행해보고 무분별한 제거는 가독성을 떨어뜨릴 수 있다.&lt;/h4&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;네 번째 테스트: 값이 없는 경우&lt;/h3&gt;
&lt;pre class=&quot;aspectj&quot;&gt;&lt;code&gt;@Test
void nullInput_Then_Invalid(){
    assertStrength(null,PasswordStrength.INVALID);
}

@Test
void emptyInput_Then_Invalid(){
    assertStrength(&quot;&quot;,PasswordStrength.INVALID);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래와 같은 검증을 추가해준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;if (s == null || s.isEmpty()) return PasswordStrength.INVALID;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;다섯번째 테스트: 대문자를 포함하지 않고 나머지 조건을 충족하는 경우&lt;/h3&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;@Test
void meetsOtherCriteria_except_for_Uppercase_Then_Normal(){
    assertStrength(&quot;ab12!@df&quot;,PasswordStrength.NORMAL);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래와 같은 검증을 추가해준다.&lt;/p&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;private boolean meetsContainingUppercaseCriteria(String s) {
    for (char ch : s.toCharArray()){
        if (Character.isUpperCase(ch)){
            return true;
        }
    }
    return false;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;여섯 번째 테스트: 길이가 8글자 이상인 조건만 충족하는 경우&lt;/h3&gt;
&lt;pre class=&quot;aspectj&quot;&gt;&lt;code&gt;@Test
void meetsOnlyLengthCriteria_Then_Weak(){
    assertStrength(&quot;abdefghi&quot;,PasswordStrength.WEAK);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;meter함수의 내용을 다음과 같이 수정한다.&lt;/p&gt;
&lt;pre class=&quot;kotlin&quot;&gt;&lt;code&gt;public PasswordStrength meter(String s) {
    if (s == null || s.isEmpty()) return PasswordStrength.INVALID;
    boolean lengthEnough = s.length() &amp;gt;= 8;
    boolean containsNum = meetsContainingNumberCriteria(s);
    boolean containsUpp = meetsContainingUppercaseCriteria(s);
    if(!lengthEnough){
        return PasswordStrength.NORMAL;
    }
    if (!containsNum) return PasswordStrength.NORMAL;
    if (!containsUpp) return PasswordStrength.NORMAL;
    return PasswordStrength.STRONG;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 코드를 보면 if 절의 위치를 두 로직을 구분하기 위해 이동하였다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;개별 규칙을 검사하는 로직&lt;/li&gt;
&lt;li&gt;규칙을 검사한 결과에 따라 암호 강도를 계산하는 로직&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;일곱 번째 테스트: 숫자 포함 조건만 충족하는 경우&lt;/h3&gt;
&lt;pre class=&quot;aspectj&quot;&gt;&lt;code&gt;@Test
void meetsOnlyNumCriteria_Then_Weak(){
    assertStrength(&quot;12345&quot;,PasswordStrength.WEAK);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;meter함수의 내용을 다음과 같이 수정한다.&lt;/p&gt;
&lt;pre class=&quot;sas&quot;&gt;&lt;code&gt;if (!lengthEnough &amp;amp;&amp;amp; containsNum &amp;amp;&amp;amp; !containsUpp)
    return PasswordStrength.WEAK;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;여덟 번째 테스트: 대문자 포함 조건만 충족하는 경우&lt;/h3&gt;
&lt;pre class=&quot;aspectj&quot;&gt;&lt;code&gt;@Test
void meetsOnlyUpperCriteria_Then_Weak(){
    assertStrength(&quot;ABZEF&quot;, PasswordStrength.WEAK);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;meter함수의 내용을 다음과 같이 수정한다.&lt;/p&gt;
&lt;pre class=&quot;sas&quot;&gt;&lt;code&gt;if (!lengthEnough &amp;amp;&amp;amp; !containsNum &amp;amp;&amp;amp; containsUpp)
    return PasswordStrength.WEAK;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;코드정리: meter() 메서드 리팩토링&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;전체 리팩토링 이전&lt;/h4&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;public class PasswordStrengthMeter {
    public PasswordStrength meter(String s) {
        if (s == null || s.isEmpty()) return PasswordStrength.INVALID;
        boolean lengthEnough = s.length() &amp;gt;= 8;
        boolean containsNum = meetsContainingNumberCriteria(s);
        boolean containsUpp = meetsContainingUppercaseCriteria(s);

        if (lengthEnough &amp;amp;&amp;amp; !containsNum &amp;amp;&amp;amp; !containsUpp)
            return PasswordStrength.WEAK;
        if (!lengthEnough &amp;amp;&amp;amp; containsNum &amp;amp;&amp;amp; !containsUpp)
            return PasswordStrength.WEAK;
        if (!lengthEnough &amp;amp;&amp;amp; !containsNum &amp;amp;&amp;amp; containsUpp)
            return PasswordStrength.WEAK;

        if(!lengthEnough){
            return PasswordStrength.NORMAL;
        }
        if (!containsNum) return PasswordStrength.NORMAL;
        if (!containsUpp) return PasswordStrength.NORMAL;
        return PasswordStrength.STRONG;
    }

    private boolean meetsContainingUppercaseCriteria(String s) {
        for (char ch : s.toCharArray()){
            if (Character.isUpperCase(ch)){
                return true;
            }
        }
        return false;
    }

    private boolean meetsContainingNumberCriteria(String s) {
        for (char ch : s.toCharArray()){
            if(ch &amp;gt;= '0' &amp;amp;&amp;amp; ch &amp;lt;= '9'){
                return true;
            }
        }
        return false;
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;WEAK 리팩토링&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;리팩토링 이전&lt;/h4&gt;
&lt;pre class=&quot;sas&quot;&gt;&lt;code&gt;if (lengthEnough &amp;amp;&amp;amp; !containsNum &amp;amp;&amp;amp; !containsUpp)
    return PasswordStrength.WEAK;
if (!lengthEnough &amp;amp;&amp;amp; containsNum &amp;amp;&amp;amp; !containsUpp)
    return PasswordStrength.WEAK;
if (!lengthEnough &amp;amp;&amp;amp; !containsNum &amp;amp;&amp;amp; containsUpp)
    return PasswordStrength.WEAK;
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;리팩토링 이후&lt;/h4&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;int metCounts = 0;
boolean lengthEnough = s.length() &amp;gt;= 8;
if (lengthEnough) metCounts++;
boolean containsNum = meetsContainingNumberCriteria(s);
if (containsNum) metCounts++;
boolean containsUpp = meetsContainingUppercaseCriteria(s);
if (containsUpp) metCounts++;

if (metCounts == 1) return PasswordStrength.WEAK;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;NORMAL 리팩토링&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;리팩토링 이전&lt;/h4&gt;
&lt;pre class=&quot;gauss&quot;&gt;&lt;code&gt;if(!lengthEnough){
    return PasswordStrength.NORMAL;
}
if (!containsNum) return PasswordStrength.NORMAL;
if (!containsUpp) return PasswordStrength.NORMAL;
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;리팩토링 이후&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;if (metCounts == 2) return PasswordStrength.NORMAL;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;전체 리팩토링&lt;/h3&gt;
&lt;pre class=&quot;smali&quot;&gt;&lt;code&gt;    public PasswordStrength meter(String s) {
        if (s == null || s.isEmpty()) return PasswordStrength.INVALID;
        int metCounts = 0;
        if (s.length() &amp;gt;= 8) metCounts++;
        if (meetsContainingNumberCriteria(s)) metCounts++;
        if (meetsContainingUppercaseCriteria(s)) metCounts++;

        if (metCounts == 1) return PasswordStrength.WEAK;
        if (metCounts == 2) return PasswordStrength.NORMAL;

        return PasswordStrength.STRONG;
    }

&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;아홉 번째 테스트: 아무 조건도 충족하지 않는 경우&lt;/h3&gt;
&lt;pre class=&quot;aspectj&quot;&gt;&lt;code&gt;@Test
void meetsNoCriteria_Then_Weak(){
    assertStrength(&quot;abc&quot;,PasswordStrength.WEAK);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;meter함수의 내용을 다음과 같이 수정한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;if (metCounts &amp;lt;= 1) return PasswordStrength.WEAK;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;코드정리: 코드 가독성 개선&lt;/h3&gt;
&lt;pre class=&quot;lisp&quot;&gt;&lt;code&gt;int metCounts = 0;
if (s.length() &amp;gt;= 8) metCounts++;
if (meetsContainingNumberCriteria(s)) metCounts++;
if (meetsContainingUppercaseCriteria(s)) metCounts++;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;public PasswordStrength meter(String s) {
        if (s == null || s.isEmpty()) return PasswordStrength.INVALID;
        int metCounts = getMetCriteriaCounts(s);

        if (metCounts &amp;lt;= 1) return PasswordStrength.WEAK;
        if (metCounts == 2) return PasswordStrength.NORMAL;

        return PasswordStrength.STRONG;
    }

    private int getMetCriteriaCounts(String s) {
        int metCounts = 0;
        if (s.length() &amp;gt;= 8) metCounts++;
        if (meetsContainingNumberCriteria(s)) metCounts++;
        if (meetsContainingUppercaseCriteria(s)) metCounts++;
        return metCounts;
    }
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 다른 개발자가 보더라도 다음과 같은 코드를 읽을 수 있다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;암호가 Null이거나 빈 문자열이면 암호 강도는 INVALID이다.&lt;/li&gt;
&lt;li&gt;충족하는 규칙 개수를 구한다.&lt;/li&gt;
&lt;li&gt;충족하는 규칙 개수가 1개 이하면 암호 강도는 WEAK이다.&lt;/li&gt;
&lt;li&gt;충족하는 규칙 개수가 2개면 암호 강도는 NORMAL이다.&lt;/li&gt;
&lt;li&gt;이 외 경우(즉 충족하는 규칙 개수가 2개보다 크면) 암호 강도는 STRONG이다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;TDD 흐름&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;테스트 - 코딩 - 리팩토링 - 테스트를 반복한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TDD는 테스트를 먼저 작성하고 테스트를 통과시킬 만큼 코드를 작성하고 리팩토링으로 마무리 하는 과정을 반복한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래의 1번부터 4번을 반복한다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;기능을 검증하는 테스트를 작성&lt;/li&gt;
&lt;li&gt;작성한 테스트를 통과하지 못하면 통과하는 코드를 작성&lt;/li&gt;
&lt;li&gt;작성한 코드를 리팩토링&lt;/li&gt;
&lt;li&gt;리팩토링 후 다시 테스트 실행&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;레드-그린-리팩터&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TDD 사이클을 레드(Red)-그린(Green)-리팩터(refactor)로 부르기도 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;레드는 실패하는 테스트를 의미한다. 레드는 테스트 코드가 실패하면 빨간색을 이용해서 실패한 테스트를 보여주는데서 비롯했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그린은 성공한 테스트를 의미한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리팩터는 리팩토링 과정을 의미한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Reference.&lt;/p&gt;
&lt;figure id=&quot;og_1672940300352&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;book&quot; data-og-title=&quot;테스트 주도 개발 시작하기 - YES24&quot; data-og-description=&quot;TDD(Test-Driven Development)는 테스트부터 시작한다. 구현을 먼저 하고 나중에 테스트하는 것이 아니라 먼저 테스트를 하고 그다음에 구현한다. 구현 코드가 없는데 어떻게 테스트할 수 있을까? 여기&quot; data-og-host=&quot;www.yes24.com&quot; data-og-source-url=&quot;http://www.yes24.com/Product/Goods/89145195&quot; data-og-url=&quot;http://www.yes24.com/Product/Goods/89145195&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/mFyqP/hyRasSlZb2/jbcuH1b8jpHXX6cKbtyH5k/img.jpg?width=872&amp;amp;height=1200&amp;amp;face=0_0_872_1200,https://scrap.kakaocdn.net/dn/cCxZl8/hyRbHtx35q/DVikVo9L35nLRKRSjMlMZk/img.jpg?width=872&amp;amp;height=1200&amp;amp;face=0_0_872_1200,https://scrap.kakaocdn.net/dn/bnJnD3/hyRbI0h14N/xpvQaVsWkssAK7TRbmug9k/img.jpg?width=872&amp;amp;height=1200&amp;amp;face=0_0_872_1200&quot;&gt;&lt;a href=&quot;http://www.yes24.com/Product/Goods/89145195&quot; data-source-url=&quot;http://www.yes24.com/Product/Goods/89145195&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/mFyqP/hyRasSlZb2/jbcuH1b8jpHXX6cKbtyH5k/img.jpg?width=872&amp;amp;height=1200&amp;amp;face=0_0_872_1200,https://scrap.kakaocdn.net/dn/cCxZl8/hyRbHtx35q/DVikVo9L35nLRKRSjMlMZk/img.jpg?width=872&amp;amp;height=1200&amp;amp;face=0_0_872_1200,https://scrap.kakaocdn.net/dn/bnJnD3/hyRbI0h14N/xpvQaVsWkssAK7TRbmug9k/img.jpg?width=872&amp;amp;height=1200&amp;amp;face=0_0_872_1200');&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;테스트 주도 개발 시작하기 - YES24&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;TDD(Test-Driven Development)는 테스트부터 시작한다. 구현을 먼저 하고 나중에 테스트하는 것이 아니라 먼저 테스트를 하고 그다음에 구현한다. 구현 코드가 없는데 어떻게 테스트할 수 있을까? 여기&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.yes24.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;</description>
      <category>TDD</category>
      <category>tdd</category>
      <category>tdd 실습</category>
      <category>tdd 흐름</category>
      <author>큐범</author>
      <guid isPermaLink="true">https://kbcoding.tistory.com/110</guid>
      <comments>https://kbcoding.tistory.com/110#entry110comment</comments>
      <pubDate>Fri, 6 Jan 2023 02:39:21 +0900</pubDate>
    </item>
    <item>
      <title>프로젝트 회고 [명식이 - 명지대의 식사를 책임지다! ver1.0 ]</title>
      <link>https://kbcoding.tistory.com/109</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nijaJ/btrVjOKiQbw/UuxOprMuTf5WTy83D0rD51/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nijaJ/btrVjOKiQbw/UuxOprMuTf5WTy83D0rD51/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nijaJ/btrVjOKiQbw/UuxOprMuTf5WTy83D0rD51/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnijaJ%2FbtrVjOKiQbw%2FUuxOprMuTf5WTy83D0rD51%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1280&quot; height=&quot;720&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&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;개발기간 2022.10 ~ ING&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;플랫폼 Android, IOS&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참여인원 서버 1명, AOS 1명, IOS 1명, 디자이너 2명 (총 5명)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;담당역할 PM, 기획, Back-end, DevOps&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;명식이는 &quot;명지대학교의 식사를 책임지다!&quot;를 슬로건을 가지고 출발한 앱이다. 첫 시작은 인문 캠퍼스 공사를 거치며 학생식당이 신규로 들어오며 기존의 학식메뉴를 제공해주는 에브리타임에서는 제공하지 않고 학생들은 직접 학생식당에 가서 사진을 찍고 이를 에브리타임 커뮤니티에서 공유하여 많은 학생들이 불편함을 느끼는 것을 들었다. 안드로이드 친구와 학생식당 메뉴를 알려주는 앱을 만들자는 의견에서 시작했다. 시작을 하기로 마음을 먹고 1주일 만에 개발을 마치고 배포를 진행했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;배포를 진행하고 커뮤니티와 오프라인 홍보물을 부착하여 유저가 900명까지 모이기 시작하며 실제 배포를 하는 개발자의 느낌을 느끼며 내가 개발한 것에 성취감을 느끼며 고맙다는 학생들의 이야기를 들을 때면 보람을 크게 느꼈다. 해당 프로젝트를 진행하며 내가 배운 것, 개선사항을 포스핑하기로 했다.&amp;nbsp;&lt;/p&gt;
&lt;h1 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h1&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;배운것&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1.&amp;nbsp; 실제 서비스 운영 경험&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제 서비스 운영 해본 다는 것은 단지 개발을 해서 커밋을 하고 PR을 날리는 것이 아니고 상상 이상으로 떨리는 것이었다. 당장 내 PR로 인해서 수 백명의 유저들이 즉각적인 불편함을 느낀다는 것이 부담스러웠으며 CICD 파이프라인이 잘못되는 것은 아닐지 걱정이 많았다. &lt;span style=&quot;background-color: #006dd7; color: #ffffff;&quot;&gt;&lt;b&gt;걱정이 많을 수록 고민은 많이 했고 고민은 나에게 성장을 가져다줬다. &lt;/b&gt;&lt;/span&gt;걱정은 Dev(개발), Prod(배포) 서버를 분리하게 하였고 DB 또한 분리하였으며 브랜치별 CICD 전략 구성하여 main 브랜치에 PR이 발생할 경우, prod서버에 배포가 되고 develop 브랜치의 경우, dev서버에 배포가 진행되도록 하였다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. 인터뷰&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;감사하게도 학생회에서 서면 인터뷰를 진행 요청을 받고 인터뷰를 진행하였다. &lt;span style=&quot;background-color: #006dd7; color: #ffffff;&quot;&gt;&lt;b&gt;내가 개발한 것을 비개발자와 개발자들에게 글로 설명&lt;/b&gt;&lt;/span&gt;해야하는 부분을 배우게 되었다. 예를들어 Server를 Dev와 Prod로 분리한 것과 CICD 구축한 것을 설명하는 것을 개발자들을 위해 Spring yml설정 파일을 통해 매개변수로 Dev와 Prod를 입력받고 이에 해당하는 DB서버에 접속하다록 구축하였다고 설명하고 CICD를 Jenkins에서 gradle을 통해 빌드하여 jar파일을 도커로 이미지로 만들어 도커허브로 배포서버로 간다는 것을 설명하였다. 여기서 비개발자들에게는 해당 기술이 서비스에 어떤 방향으로 유저에게 전달되는지를 설명하였다. CICD를 구축하여 긴급하게 수정할 오류가 있을 경우, 기존의 반영 속도보다 더 빠르게 반영되는 방식이라고 설명하였다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-01-03 오후 11.24.04.png&quot; data-origin-width=&quot;1852&quot; data-origin-height=&quot;1162&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/paR5e/btrVjm8lF5S/jKNdsg6kd24lElPwab7BeK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/paR5e/btrVjm8lF5S/jKNdsg6kd24lElPwab7BeK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/paR5e/btrVjm8lF5S/jKNdsg6kd24lElPwab7BeK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpaR5e%2FbtrVjm8lF5S%2FjKNdsg6kd24lElPwab7BeK%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;578&quot; height=&quot;1162&quot; data-filename=&quot;스크린샷 2023-01-03 오후 11.24.04.png&quot; data-origin-width=&quot;1852&quot; data-origin-height=&quot;1162&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. 소규모 팀의 힘&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전의 진행한 프로젝트를 보면 서버를 개인 프로젝트 외에는 가장 소규모로 진행된 프로젝트였다. &lt;span style=&quot;background-color: #006dd7; color: #ffffff;&quot;&gt;소규모로 진행되기에 기민성이 올라가며&lt;/span&gt; 팀은 개발 및 디자인에 있어서 즉각적인 결과물이 보였으며 배포 이후에도 가장 많이 수정작업이 이루어져 1.9.1버전까지 업데이트를 진행했다. 배포 이후에도 유지보수를 진행한 첫 프로젝트였다. 유지보수를 하기에 이후에 수정을 고려한 코드를 작성하며 주기적인 회의를 거치며 개발을 짧은 시간에 큰 성과를 가져왔다.&lt;/p&gt;
&lt;h1&gt;&amp;nbsp;&lt;/h1&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;개선사항&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 로드 밸런스&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;명식이 서버에는 로드 밸런스를 적용하지 못했다. 그 말은 Prod서버에서 문제가 발생할 경우, 서비스의 이용에 차질이 바로 이어진다는 것이다. 이것이 늘 걱정이었다. 물론 Jenkins에서 파이프라인을 구축하여 문제가 생길 경우 이전의 배포로 이루어지지만, Jenkins의 생명주기는 배포 서버에서 문제가 생기는 것은 막지 못한다. 다행스럽게 서비스를 런칭하는 동안 Prod서버에 문제가 생긴 적은 없으나 로드 밸런스를 적용했더라면 더욱 안정적인 서비스를 제공할 수 있었지 않을 가 하는 아쉬움이 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ffffff; background-color: #006dd7;&quot;&gt;&lt;b&gt;다음 버전에는 Nginx를 적용하여 로드 밸런스를 적용할 예정이다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2.&amp;nbsp; 모니터링의 부재&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모니터링은 직접 로그를 확인하거나, AWS에서 직접 제공하는 모니터링을 활용하였다. 모니터링을 못하는 것이 이렇게 불편한 일인줄 몰랐다. 다른 프로젝트에서 모니터링에 대해서 필요성을 느끼지 못했지만 실제 유저가 있는 서비스에서 모니터링은 매우 중요한 요소였다. 모니터링의 데이터를 의사결정에 큰 지표가 되었으며 개발 팀이 언제 배포를 이루어지게 할 것인지, 특정 시간에 Scale-out할 것인지 등 다양한 의사결정에 활용할 수 있을 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #006dd7; color: #ffffff;&quot;&gt;&lt;b&gt;다음 버전에는 prometheus grafana를 사용하여 모니터링과 시각화를 적용할 예정이다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. 조회를 더욱 빠르게는 못했을 까?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대부분의 유저는 간단하게 금일 메뉴만 확인 할 것으로 예상된다. 그렇다면, 금일 메뉴만을 캐시 메모리(Redis)에 넣고 관리를 했다면 더욱 빠르게 조회가 가능하지 않았을까? 하는 아쉬움이 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Redis에 대해서 다양한 테스트를 거치고 적용을 검토해봐야겠다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;App DownLoad Link&lt;/h2&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AppStore&lt;/p&gt;
&lt;figure id=&quot;og_1672755256015&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;&amp;lrm;명식이 : 명지대의 식사를 책임지다!&quot; data-og-description=&quot;&amp;lrm;주요 기능 안내 1. '오늘의 학식' 메뉴 일간 / 주간 조회 - 메뉴을 일 단위 / 주 단위로 조회가 가능합니다. - 메뉴에 대하여 맛있어요 / 맛없어요 평가를 선택할 수 있습니다. 2. 명지 맛집 - 명지&quot; data-og-host=&quot;apps.apple.com&quot; data-og-source-url=&quot;https://apps.apple.com/kr/app/%EB%AA%85%EC%8B%9D%EC%9D%B4/id6443913080&quot; data-og-url=&quot;https://apps.apple.com/kr/app/%EB%AA%85%EC%8B%9D%EC%9D%B4-%EB%AA%85%EC%A7%80%EB%8C%80%EC%9D%98-%EC%8B%9D%EC%82%AC%EB%A5%BC-%EC%B1%85%EC%9E%84%EC%A7%80%EB%8B%A4/id6443913080&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/ThUTM/hyQ87z82d2/5AqKRdTT7KY4fbrWwHO4ZK/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/b1Vz5x/hyQ8VGqZmh/GJDKijwdHoPNnfSGf9J2R1/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://apps.apple.com/kr/app/%EB%AA%85%EC%8B%9D%EC%9D%B4/id6443913080&quot; data-source-url=&quot;https://apps.apple.com/kr/app/%EB%AA%85%EC%8B%9D%EC%9D%B4/id6443913080&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/ThUTM/hyQ87z82d2/5AqKRdTT7KY4fbrWwHO4ZK/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/b1Vz5x/hyQ8VGqZmh/GJDKijwdHoPNnfSGf9J2R1/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;&amp;lrm;명식이 : 명지대의 식사를 책임지다!&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;&amp;lrm;주요 기능 안내 1. '오늘의 학식' 메뉴 일간 / 주간 조회 - 메뉴을 일 단위 / 주 단위로 조회가 가능합니다. - 메뉴에 대하여 맛있어요 / 맛없어요 평가를 선택할 수 있습니다. 2. 명지 맛집 - 명지&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;apps.apple.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PlayStore&lt;/p&gt;
&lt;figure id=&quot;og_1672755256016&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;명식이 : 명지대의 식사를 책임지다! - Google Play 앱&quot; data-og-description=&quot;명지대학교 인문캠퍼스 학식 식단표와 주변 식당, 카페 정보를 제공합니다&quot; data-og-host=&quot;play.google.com&quot; data-og-source-url=&quot;https://play.google.com/store/apps/details?id=com.myongsik.myongsikandroid&quot; data-og-url=&quot;https://play.google.com/store/apps/details?id=com.myongsik.myongsikandroid&amp;amp;hl=ko&amp;amp;gl=JP&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bRyhwA/hyQ86Bdj7v/cWaTiKLArk3J8th2RrwSsk/img.png?width=512&amp;amp;height=512&amp;amp;face=0_0_512_512,https://scrap.kakaocdn.net/dn/d5lyc5/hyQ8VsUtMj/3cHU3U7Q0gCeWLM4eqbOsK/img.png?width=600&amp;amp;height=300&amp;amp;face=0_0_600_300,https://scrap.kakaocdn.net/dn/OqxB1/hyQ8SJH50j/whWtRCleqKfofcol89WUtK/img.png?width=240&amp;amp;height=240&amp;amp;face=0_0_240_240&quot;&gt;&lt;a href=&quot;https://play.google.com/store/apps/details?id=com.myongsik.myongsikandroid&quot; data-source-url=&quot;https://play.google.com/store/apps/details?id=com.myongsik.myongsikandroid&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bRyhwA/hyQ86Bdj7v/cWaTiKLArk3J8th2RrwSsk/img.png?width=512&amp;amp;height=512&amp;amp;face=0_0_512_512,https://scrap.kakaocdn.net/dn/d5lyc5/hyQ8VsUtMj/3cHU3U7Q0gCeWLM4eqbOsK/img.png?width=600&amp;amp;height=300&amp;amp;face=0_0_600_300,https://scrap.kakaocdn.net/dn/OqxB1/hyQ8SJH50j/whWtRCleqKfofcol89WUtK/img.png?width=240&amp;amp;height=240&amp;amp;face=0_0_240_240');&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;명식이 : 명지대의 식사를 책임지다! - Google Play 앱&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;play.google.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;/div&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;GitHub&lt;/h2&gt;
&lt;figure id=&quot;og_1672940986646&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 - MYONGSIK/Server:   명식이 : 명지대의 식사를 책임지다!&quot; data-og-description=&quot;  명식이 : 명지대의 식사를 책임지다! Contribute to MYONGSIK/Server development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/MYONGSIK/Server&quot; data-og-url=&quot;https://github.com/MYONGSIK/Server&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/1XfeV/hyQ8SJHXN6/WNyXsWwzaGLVrDsG4cEN1K/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/MYONGSIK/Server&quot; data-source-url=&quot;https://github.com/MYONGSIK/Server&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/1XfeV/hyQ8SJHXN6/WNyXsWwzaGLVrDsG4cEN1K/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 - MYONGSIK/Server:   명식이 : 명지대의 식사를 책임지다!&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;  명식이 : 명지대의 식사를 책임지다! Contribute to MYONGSIK/Server 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;h2 data-ke-size=&quot;size26&quot;&gt;Skill Stack&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bQoUWU/btrVe5GxScP/4Omt19peHMQwmNiEFGWEh1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bQoUWU/btrVe5GxScP/4Omt19peHMQwmNiEFGWEh1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bQoUWU/btrVe5GxScP/4Omt19peHMQwmNiEFGWEh1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbQoUWU%2FbtrVe5GxScP%2F4Omt19peHMQwmNiEFGWEh1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1280&quot; height=&quot;720&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Infra Structure&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/JhRSv/btrVjQnQfqL/5GSFopVY0TgkFy0fSY70pk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/JhRSv/btrVjQnQfqL/5GSFopVY0TgkFy0fSY70pk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/JhRSv/btrVjQnQfqL/5GSFopVY0TgkFy0fSY70pk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJhRSv%2FbtrVjQnQfqL%2F5GSFopVY0TgkFy0fSY70pk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1280&quot; height=&quot;720&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;CICD&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kKF1k/btrVfj5H30q/XiYkZRtYuU2X3PwgH2UXa0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kKF1k/btrVfj5H30q/XiYkZRtYuU2X3PwgH2UXa0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kKF1k/btrVfj5H30q/XiYkZRtYuU2X3PwgH2UXa0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkKF1k%2FbtrVfj5H30q%2FXiYkZRtYuU2X3PwgH2UXa0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1280&quot; height=&quot;720&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&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;</description>
      <category>회고</category>
      <author>큐범</author>
      <guid isPermaLink="true">https://kbcoding.tistory.com/109</guid>
      <comments>https://kbcoding.tistory.com/109#entry109comment</comments>
      <pubDate>Wed, 4 Jan 2023 15:39:09 +0900</pubDate>
    </item>
    <item>
      <title>[gRPC] gRPC 사용후기</title>
      <link>https://kbcoding.tistory.com/108</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;이번 22-2 클라이언트 서버 프로그래밍 수업에서 gRPC 기술을 적용하여 수강신청 시스템을 구축하였다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 포스터에서는 gRPC를 사용하면서 느낀 사용후기와 깃을 포스팅하겠다.&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;우선, 수업에서는 RMI(자바 원격 함수 호출)로 메서드를 호출하는 기술인데 같은 호출 기술인 gRPC로 진행하였다. 내가 진행한 프로젝트는 수강신청 시스템 구축으로 아래와 같은 프로세스간 통신을 한다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-12-29 오후 12.43.22.png&quot; data-origin-width=&quot;582&quot; data-origin-height=&quot;64&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/leNDb/btrUSvdd9Pk/BwC8WdMyCxlKddo64m9Ipk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/leNDb/btrUSvdd9Pk/BwC8WdMyCxlKddo64m9Ipk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/leNDb/btrUSvdd9Pk/BwC8WdMyCxlKddo64m9Ipk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FleNDb%2FbtrUSvdd9Pk%2FBwC8WdMyCxlKddo64m9Ipk%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;582&quot; height=&quot;64&quot; data-filename=&quot;스크린샷 2022-12-29 오후 12.43.22.png&quot; data-origin-width=&quot;582&quot; data-origin-height=&quot;64&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;h2 data-ke-size=&quot;size26&quot;&gt;내가 느낀 장점&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;통신&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로세스간 통신은 현재 기술 발전의 핵심인 분산에서 관심있는 분야이다. 서비스를 좀 더 안정적으로 배포하기 위해서 서비스를 나누는데 필요한 것이 통신이다. gRPC는 통신을 매우 효율적으로 할 수 있게 해준다. proto3버전을 사용하면 넓은 언어 호환성과 xml, json에 비해 빠른 속도와 가벼운 데이터 크기 이 점에서 통신의 속도와 호환성에 보장받을 수 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;공식문서&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공식문서가 매우 잘되어있었다. 거기서 써져있는 코드를 따라치면 자동으로 실행해 볼 수 있는 코드가 제공되었고 해당 기술에 대해서도 gRPC뿐 아니라 RPC의 기술에서 어떤 점이 다른지, 왜 나오게 되었는지를 잘 설명해주었다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;내가 느낀 단점&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;사례&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;gRPC를 사용하면서 많은 오류를 접했지만 검색할때 다른 기술에 비해(스프링, DB 등) 많은 사례가 없는 것이 아쉬웠다. 이는 시간이 해결해줄 것이라 생각한다. 그래서 더욱 공식문서를 들여다보게 되었다.&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;proto 파일의 수정&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 Client, Server, Data 프로젝트에는 각각의 proto 파일이 존재하는데 어느 한곳에서라도 proto 파일의 변경이 가해지면 다른 곳의 proto 파일도 최신화를 해줘야한다는 점이 아쉬웠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1672284701323&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 - Qbeom0925/grpc-enrolmentSystem: gRPC를 이용한 수강신청 시스템 구축&quot; data-og-description=&quot;gRPC를 이용한 수강신청 시스템 구축. Contribute to Qbeom0925/grpc-enrolmentSystem development by creating an account on GitHub.&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/Qbeom0925/grpc-enrolmentSystem&quot; data-og-url=&quot;https://github.com/Qbeom0925/grpc-enrolmentSystem&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/h0JjY/hyQ5vUmEis/RnVe9R4aeHmaG0nkhMYv61/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/Qbeom0925/grpc-enrolmentSystem&quot; data-source-url=&quot;https://github.com/Qbeom0925/grpc-enrolmentSystem&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/h0JjY/hyQ5vUmEis/RnVe9R4aeHmaG0nkhMYv61/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 - Qbeom0925/grpc-enrolmentSystem: gRPC를 이용한 수강신청 시스템 구축&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;gRPC를 이용한 수강신청 시스템 구축. Contribute to Qbeom0925/grpc-enrolmentSystem development by creating an account on GitHub.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;</description>
      <category>gRPC</category>
      <category>gRPC</category>
      <category>grpc 사용</category>
      <category>Proto</category>
      <author>큐범</author>
      <guid isPermaLink="true">https://kbcoding.tistory.com/108</guid>
      <comments>https://kbcoding.tistory.com/108#entry108comment</comments>
      <pubDate>Sat, 31 Dec 2022 14:00:47 +0900</pubDate>
    </item>
    <item>
      <title>[gRPC] gRPC 특징, 장단점</title>
      <link>https://kbcoding.tistory.com/107</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;gRPC 소개&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;gRPC는 protocol buffer와 RPC를 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2022.12 당시, IDL로는 proto3를 사용하며 호환하는 언어로는 Java, C++, Python, Java Lite, Ruby, JavaScript, Objective-C, C#을 호환한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;gRPC의 핵심은&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;분산&lt;/b&gt;으로 클라이언트 응용 프로그램을 서버에서 함수를 원격 호출할 수 있어 MSA(Micro Service Architecture)를 구현하기 수월하다. gRPC 서버에서는 Stub을 통한 호출을 처리할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;687&quot; data-origin-height=&quot;450&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b6h2XR/btrUMPqJalT/2DGWshBMhuZkZgve3czbP0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b6h2XR/btrUMPqJalT/2DGWshBMhuZkZgve3czbP0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b6h2XR/btrUMPqJalT/2DGWshBMhuZkZgve3czbP0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb6h2XR%2FbtrUMPqJalT%2F2DGWshBMhuZkZgve3czbP0%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;687&quot; height=&quot;450&quot; data-origin-width=&quot;687&quot; data-origin-height=&quot;450&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;gRPC 특징&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. Protocol Buffere&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;gRPC는 IDL을 Protocol Buffere(.proto)를 사용한다.&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;2. Service definition&lt;/h2&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;service EducationService {
	rpc basicRead(BasicRequest) returns (BasicResponse){}
}

message BasicRequest {
  string message = 1;
}

message BasicResponse {
  string message = 1;
  string statusCode = 2;
  string statusMessage = 3;
}&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. Channels&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;gRPC channel은 특정 host와 port에 대해 gRPC서버에 대한 연결을 제공한다.&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;4. RPC Life Cycle&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;단항(Unary) RPC&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;a. 클라이언트가 Stub메서드를 호출하면 이 호출에 대한 클라이언트의 메타데이터를 RPC가 호출되었음을 알린다. 서버는 호출을 확인하고 초기 메타데이터를 바로 되돌려 보내거나 클라이언트의 요청 메시지를 기다릴 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;b. 서버가 클라이언트의 요청 메시지를 받으면 응답을 생성하고 채우는 데 필요한 모든 작업을 수행한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;c. 그런 다음 응답은 상태 세부 정보 및 선택적인 후행 메타데이터와 함께 클라이언트에 반환된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;d. 응답상태가 OK이면 클아이언트는 클라이언트 측에서 호출 응답 완료를 응답 받는다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Server Streaming RPC&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클라이언트 request 1번, 서버 Response 유지&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서버가 클라이언트 요청에 대한 응답으로 메시지 스트림을 반환한다는 점을 제외하면 Unary RPC와 유사하다. 모든 메시지를 보낸 후 서버의 상태 세부 정보 및 선택적 메타데이터가 클라이언트로 전송된다. 이렇게 하면 서버측에서 처리가 완료되고 클라이언트는 서버의 모든 메시지를 받으면 된다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Client Streaming RPC&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클라이언트 request 1번, 서버 Response &lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;1번&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클라이언트가 단일 메시지 대신 서버에 미시지 스트림을 보낸다. 서버는 일반적으로 클라이언트의 모든 메시지를 수신한 후에 대개 단일 메시지로 응답한다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Bidirectional streaming RPC&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DEADLINE_EXCEEDED gRPC를 사용하면 클라이언트는 RPC가 오류로 종료되기 전에 RPC가 완료될 때까지 대기할 시간을 지정할 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;RPC termination&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;gRPC에서 클라이언트와 서버는 모두 호출의 성공 여부를 독립적이고 로컬에서 결정하므로 결론이 일치하지 않을 수 있다. 예를 들어 서버 측에서는 성공적으로 완료되었지만(&amp;ldquo;내 모든 응답을 보냈습니다!&amp;rdquo;) 클라이언트 측에서는 실패한 RPC가 있을 수 있다(&amp;ldquo;응답이 마감 시간 이후에 도착했습니다!&amp;rdquo;).&lt;span&gt;&amp;nbsp;&lt;/span&gt;클라이언트가 모든 요청을 보내기 전에 서버가 완료를 결정할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Cancelling an RPC&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클라이언트나 서버는 언제든지 RPC를 취소할 수 있다.&lt;/p&gt;
&lt;p data-ke-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;gRPC 장점&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;protocol buffer사용&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;protocol buffere는 IDL xml, json에 비해 데이터 크기가 작아 결과적으로 리소스 사용량을 줄여 응답시간을 줄일 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;xml, json으로도 변환하는 기능도 지원한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;HTTP 2.0지원&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HTTP1.1은 TCP연결 관련하여 비효율적인 연결방식을 HTTP2.0을 통해 서버푸시와 1.1버전 대비 효율적인 연결이 가능해졌다.&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;넓은 언어 호환성&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 Java, Python, Objective-C, C++을 지원하고 proto3의 경우 Kotlin, Dart, Go, Ruby,&amp;nbsp; C#을 추가적으로 지원한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;분산 환경&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최근의 개발 환경을 보면 핵심은 분산이다. 기존의 서비스를 분산하여 에러에 대해서 대처를 유연하게 대응하는 것이 중요한 시대이다. 이를 해결할 수 있는 것이 gRPC환경으로 분산환경 구축이 가능하다.&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;gRPC 단점&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;.proto파일에 대한 업데이트&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;gRPC로 연결되어 있는 서버 클라이언트에서 어느 한쪽에서라도 변경이 일어나면 proto파일을 업데이트 해야하는 단점이 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Reference.&lt;/p&gt;
&lt;figure id=&quot;og_1672243223992&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;Introduction to gRPC&quot; data-og-description=&quot;An introduction to gRPC and protocol buffers.&quot; data-og-host=&quot;grpc.io&quot; data-og-source-url=&quot;https://grpc.io/docs/what-is-grpc/introduction/&quot; data-og-url=&quot;https://grpc.io/docs/what-is-grpc/introduction/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/eUgXu/hyQ30O1Ywi/xO3lL72QjOtekZtcQqJ4Hk/img.png?width=1500&amp;amp;height=1500&amp;amp;face=0_0_1500_1500,https://scrap.kakaocdn.net/dn/b4S02T/hyQ33SyopB/lh2VKskrvwlPNcFCQkj4xk/img.png?width=1500&amp;amp;height=1500&amp;amp;face=0_0_1500_1500&quot;&gt;&lt;a href=&quot;https://grpc.io/docs/what-is-grpc/introduction/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://grpc.io/docs/what-is-grpc/introduction/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/eUgXu/hyQ30O1Ywi/xO3lL72QjOtekZtcQqJ4Hk/img.png?width=1500&amp;amp;height=1500&amp;amp;face=0_0_1500_1500,https://scrap.kakaocdn.net/dn/b4S02T/hyQ33SyopB/lh2VKskrvwlPNcFCQkj4xk/img.png?width=1500&amp;amp;height=1500&amp;amp;face=0_0_1500_1500');&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;Introduction to gRPC&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;An introduction to gRPC and protocol buffers.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;grpc.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id=&quot;og_1672243821426&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;Core concepts, architecture and lifecycle&quot; data-og-description=&quot;An introduction to key gRPC concepts, with an overview of gRPC architecture and RPC life cycle.&quot; data-og-host=&quot;grpc.io&quot; data-og-source-url=&quot;https://grpc.io/docs/what-is-grpc/core-concepts/&quot; data-og-url=&quot;https://grpc.io/docs/what-is-grpc/core-concepts/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cRspFi/hyQ3VGXJSK/6HoVOV43sykeiuuSZckyCK/img.png?width=1500&amp;amp;height=1500&amp;amp;face=0_0_1500_1500,https://scrap.kakaocdn.net/dn/cEIovh/hyQ5Ep2JFG/JPJYUIO4yFoIh6P4VWMiyk/img.png?width=1500&amp;amp;height=1500&amp;amp;face=0_0_1500_1500&quot;&gt;&lt;a href=&quot;https://grpc.io/docs/what-is-grpc/core-concepts/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://grpc.io/docs/what-is-grpc/core-concepts/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cRspFi/hyQ3VGXJSK/6HoVOV43sykeiuuSZckyCK/img.png?width=1500&amp;amp;height=1500&amp;amp;face=0_0_1500_1500,https://scrap.kakaocdn.net/dn/cEIovh/hyQ5Ep2JFG/JPJYUIO4yFoIh6P4VWMiyk/img.png?width=1500&amp;amp;height=1500&amp;amp;face=0_0_1500_1500');&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;Core concepts, architecture and lifecycle&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;An introduction to key gRPC concepts, with an overview of gRPC architecture and RPC life cycle.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;grpc.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>gRPC</category>
      <category>gprc 장점</category>
      <category>gRPC</category>
      <category>grpc 단점</category>
      <author>큐범</author>
      <guid isPermaLink="true">https://kbcoding.tistory.com/107</guid>
      <comments>https://kbcoding.tistory.com/107#entry107comment</comments>
      <pubDate>Fri, 30 Dec 2022 02:35:10 +0900</pubDate>
    </item>
    <item>
      <title>[gRPC] Protocol Buffere(proto3) 소개, 사용법</title>
      <link>https://kbcoding.tistory.com/106</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;Protocol Bufferes&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구조화된 데이터를 직렬화 하기 위한 구글의 언어 중립적, 확장 가능한 메커니즘이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터를 한 번 구성하는 방법을 정의한 후에 특수 생성된 소스 코드를 사용하여 다양한 데이터 스트림과 다양한 언어를 사용하여 구조화된 데이터를 쉽게 쓰고 읽을 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Protocol Buffere은 IDL로서 data structure를 정의한 다음, proto파일을 protocol buffere compiler를 통해 컴파일한다. 컴파일된 소스코드를 사용하여 데이터를 읽고 쓴다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Protocol Bufferes는 현재 Java, Python, Objective-C, C++을 지원하고 proto3의 경우 Kotlin, Dart, Go, Ruby,&amp;nbsp; C#을 추가적으로 지원한다.&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;Proto3&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서버는 클라이언트로부터 응답(Response)를 하는데 거기서 대부분 들어가는 statusCode와 statusMwssage가 있습니다. 아래의 예시 코드를 통해서 다음과 같이 구성할 수 있습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size18&quot;&gt;Code&lt;/h2&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;syntax = &quot;proto3&quot;;
option java_package = &quot;com.grpc.education&quot;;
option java_multiple_files = true;
package education;

message BasicResponse {
  int32 userNum = 1;
  string statusCode = 2;
  string statusMessage = 3;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;BasicResponse 메시지 선언에서 볼 수 있는 것은 메시지를 구성하는 데이터에 대해서 각각 선언을 해주는 형식을 가진다.&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Field 특징&lt;/span&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Field Types은 scalar types, enum, fild type선언이 가능하다.&lt;/span&gt;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;각 field는 고유한 field 번호를 갖는다. &lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;field 번호에 따라 다른 인코딩 방식 - 1~15 방식이 효율적이다.&lt;/span&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;1~15 1Byte&lt;/li&gt;
&lt;li&gt;16~2047 2byte&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Proto&amp;nbsp; 장단점&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Proto 장점&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1. 데이터의 크기가 작다.&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터의 크기가 작은 경우, 통신이 빠르다는 이점이 있다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2. proto &amp;lt;-&amp;gt; json 전환 유틸을 지원한다.&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3. xml비해 3~10배 작고 20~100배 빠르고 더 간결하고 덜 모호하고 더 쉬운 데이터 엑세스 클래스를 제공. &amp;lt;- 공식문서&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&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;Proto 단점&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1. Proto 포맷에 대한 사전지식이 요구된다.&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2. 바이트 형태로 인해서 가독성 저하된다.&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Reference.&lt;/p&gt;
&lt;figure id=&quot;og_1672238790965&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;Protocol Buffers &amp;nbsp;|&amp;nbsp; Google Developers&quot; data-og-description=&quot;Protocol buffers are a language-neutral, platform-neutral extensible mechanism for serializing structured data.&quot; data-og-host=&quot;developers.google.com&quot; data-og-source-url=&quot;https://developers.google.com/protocol-buffers&quot; data-og-url=&quot;https://developers.google.com/protocol-buffers&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bdjZhO/hyQ31NUF8T/4MumCoEnT8ZgEcXNsUCn21/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630&quot;&gt;&lt;a href=&quot;https://developers.google.com/protocol-buffers&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://developers.google.com/protocol-buffers&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bdjZhO/hyQ31NUF8T/4MumCoEnT8ZgEcXNsUCn21/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630');&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;Protocol Buffers &amp;nbsp;|&amp;nbsp; Google Developers&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Protocol buffers are a language-neutral, platform-neutral extensible mechanism for serializing structured data.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;developers.google.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>gRPC</category>
      <category>gRPC</category>
      <category>Proto</category>
      <category>proto3</category>
      <category>protocol bufferes</category>
      <author>큐범</author>
      <guid isPermaLink="true">https://kbcoding.tistory.com/106</guid>
      <comments>https://kbcoding.tistory.com/106#entry106comment</comments>
      <pubDate>Thu, 29 Dec 2022 00:13:31 +0900</pubDate>
    </item>
    <item>
      <title>[Clean Code] 1장 깨끗한 코드</title>
      <link>https://kbcoding.tistory.com/105</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;데이브 토마스 &amp;ldquo;깨끗한 코드란 다른 사람이 고치기 쉽다고 단언한다.&amp;rdquo;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마이클 페더스 &amp;ldquo;깨끗한 코드는 언제나 누군가 주의 깊게 짰다는 느낌을 준다.&amp;rdquo;&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;ldquo;중복줄이기, 표현 높이기, 초반부터 간단한 추상화 고려하기, 한 기능만 수행하라.&amp;rdquo;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로그램을 단순하게 보이도록 만드는 열쇠는 언어가 아니다. 언어를 단순하게 보이도록 만드는 열쇠는 프로그래머다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저자&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;우리는 저자다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;@author필드는 저자를 소개한다. 저자가 있다는 것은 독자가 있다. 그리고 저제에게는 독자와 잘 소통할 &lt;b&gt;책임&lt;/b&gt;이 있다. 우리는 새 코드를 짜면서 끊임없이 기존 코드를 읽는다. 그 말은 기존 코드가 읽기 쉬워야 쓸때 편하다는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보이스카우트 규칙 &amp;ldquo;캠핑장은 처음 왔을 때보다 더 깨끗하게 해놓고 떠나라&amp;rdquo;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;체크아웃할 때보다 좀 더 깨끗한 코드를 체크인한다면 코드는 절대 나빠지지 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지속적인 개선이야말로 전문가 정신의 본질이 아니던가?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;내 생각&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시간이 없어 급하게 짠 코드를 보고 새로운 코드를 짜는 것은 읽기 어렵기 때문에 다시 시간이 낭비가 된다. 여기서 모순이 발생한다. &lt;b&gt;시간이 없어 급하게 짠 코드가 시간을 더 없게 만드는 것이다.&lt;/b&gt; 우리는 코드를 짤 때 읽기 쉽게 쓰는 것이 가장 시간을 절약하는 것임을 알아야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Reference.&lt;/p&gt;
&lt;figure id=&quot;og_1672195484873&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;book&quot; data-og-title=&quot;Clean Code 클린 코드 - YES24&quot; data-og-description=&quot;애자일 소프트웨어의 혁명적인 패러다임을 제시하는 책이다. 저자 로버트 마틴은 오브젝트 멘토(Object Mentor)의 동료들과 힘을 모아 &amp;lsquo;개발하며&amp;rsquo; 클린 코드를 만드는 최상의 애자일 기법을 정제&quot; data-og-host=&quot;www.yes24.com&quot; data-og-source-url=&quot;http://www.yes24.com/Product/Goods/11681152&quot; data-og-url=&quot;http://www.yes24.com/Product/Goods/11681152&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/fsKAI/hyQ3YDc47s/xkTJTmuF0l7tDpbLnW6UhK/img.jpg?width=455&amp;amp;height=600&amp;amp;face=0_0_455_600,https://scrap.kakaocdn.net/dn/4woOO/hyQ3Qyuauh/nTa1W4bBB2qK1HXMCzuNfK/img.jpg?width=455&amp;amp;height=600&amp;amp;face=0_0_455_600,https://scrap.kakaocdn.net/dn/Rd9K2/hyQ3XYBChy/D3DMTU8S8vMaFEwHOkv7U0/img.jpg?width=455&amp;amp;height=600&amp;amp;face=0_0_455_600&quot;&gt;&lt;a href=&quot;http://www.yes24.com/Product/Goods/11681152&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;http://www.yes24.com/Product/Goods/11681152&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/fsKAI/hyQ3YDc47s/xkTJTmuF0l7tDpbLnW6UhK/img.jpg?width=455&amp;amp;height=600&amp;amp;face=0_0_455_600,https://scrap.kakaocdn.net/dn/4woOO/hyQ3Qyuauh/nTa1W4bBB2qK1HXMCzuNfK/img.jpg?width=455&amp;amp;height=600&amp;amp;face=0_0_455_600,https://scrap.kakaocdn.net/dn/Rd9K2/hyQ3XYBChy/D3DMTU8S8vMaFEwHOkv7U0/img.jpg?width=455&amp;amp;height=600&amp;amp;face=0_0_455_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;Clean Code 클린 코드 - YES24&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;애자일 소프트웨어의 혁명적인 패러다임을 제시하는 책이다. 저자 로버트 마틴은 오브젝트 멘토(Object Mentor)의 동료들과 힘을 모아 &amp;lsquo;개발하며&amp;rsquo; 클린 코드를 만드는 최상의 애자일 기법을 정제&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.yes24.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>Clean Code</category>
      <author>큐범</author>
      <guid isPermaLink="true">https://kbcoding.tistory.com/105</guid>
      <comments>https://kbcoding.tistory.com/105#entry105comment</comments>
      <pubDate>Wed, 28 Dec 2022 11:45:00 +0900</pubDate>
    </item>
    <item>
      <title>[gRPC] gRPC 개념, RPC, IDL비교(XML, JSON, Protocol Buffer)</title>
      <link>https://kbcoding.tistory.com/104</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;gRPC란?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구글이 개발한 오픈 소스 원격 프로시저 호출 시스템(RPC)이다. 호출을 위해 TCP/IP 프로토콜과 HTTP2.0 프로토콜을 사용하고 IDL(Interface Definication Language)로 protocol buffer를 사용한다.&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;RPC(Remote Procedure call)란?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한 프로그램이 네트워크의 세부 정보를 이해하지 않고도 네트워크 안의 다른 컴퓨터에 있는 프로그램에서 서비스를 요청하는 프로토콜&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;263&quot; data-origin-height=&quot;221&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/WfLqw/btrTKqY79wu/EK6PCeCue2KdQAw2bLO2cK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/WfLqw/btrTKqY79wu/EK6PCeCue2KdQAw2bLO2cK/img.png&quot; data-alt=&quot;Microsoft RPC 작동방식&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/WfLqw/btrTKqY79wu/EK6PCeCue2KdQAw2bLO2cK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FWfLqw%2FbtrTKqY79wu%2FEK6PCeCue2KdQAw2bLO2cK%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;263&quot; height=&quot;221&quot; data-origin-width=&quot;263&quot; data-origin-height=&quot;221&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Microsoft RPC 작동방식&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;HTTP 2.0&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HTTP(Hypertext Transfer Protocol)는 웹 환경에서 사용되는 통신 프로토콜로 OSI 7 Layer에서 최상위인 Application Layer에서 사용한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HTTP에 대한 역사&lt;/p&gt;
&lt;figure id=&quot;og_1671108889926&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;[Network] HTTP(Stateful Stateless 차이, 비 연결성, 클라이언트 서버 구조 ...)&quot; data-og-description=&quot;HTTP (HyperText Transfer Protocol) - 역사 HTTP/0.9 1991년: GET 메서드만 지원, HTTP 헤더X HTTP/1.0 1996년: 메서드, 헤더 추가 HTTP/1.1 1997년: 가장 많이 사용, 우리에게 가장 중요한 버전 RFC2068 (1997) -&amp;gt; RFC2616 (1999) -&amp;gt; &quot; data-og-host=&quot;kbcoding.tistory.com&quot; data-og-source-url=&quot;https://kbcoding.tistory.com/96?category=964825&quot; data-og-url=&quot;https://kbcoding.tistory.com/96&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/m8Lsn/hyQTNWRnDf/EHgfdgPb8WKqSWT7KloU9K/img.png?width=478&amp;amp;height=251&amp;amp;face=0_0_478_251,https://scrap.kakaocdn.net/dn/ZHbzZ/hyQU6UG2Qt/gwWmlajoF5TXuF9t23s5T0/img.png?width=478&amp;amp;height=251&amp;amp;face=0_0_478_251,https://scrap.kakaocdn.net/dn/ARnAP/hyQU4JldTN/M8xHPpsXrNXqcPMq2UBN8K/img.png?width=832&amp;amp;height=247&amp;amp;face=0_0_832_247&quot;&gt;&lt;a href=&quot;https://kbcoding.tistory.com/96?category=964825&quot; data-source-url=&quot;https://kbcoding.tistory.com/96?category=964825&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/m8Lsn/hyQTNWRnDf/EHgfdgPb8WKqSWT7KloU9K/img.png?width=478&amp;amp;height=251&amp;amp;face=0_0_478_251,https://scrap.kakaocdn.net/dn/ZHbzZ/hyQU6UG2Qt/gwWmlajoF5TXuF9t23s5T0/img.png?width=478&amp;amp;height=251&amp;amp;face=0_0_478_251,https://scrap.kakaocdn.net/dn/ARnAP/hyQU4JldTN/M8xHPpsXrNXqcPMq2UBN8K/img.png?width=832&amp;amp;height=247&amp;amp;face=0_0_832_247');&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;[Network] HTTP(Stateful Stateless 차이, 비 연결성, 클라이언트 서버 구조 ...)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;HTTP (HyperText Transfer Protocol) - 역사 HTTP/0.9 1991년: GET 메서드만 지원, HTTP 헤더X HTTP/1.0 1996년: 메서드, 헤더 추가 HTTP/1.1 1997년: 가장 많이 사용, 우리에게 가장 중요한 버전 RFC2068 (1997) -&amp;gt; RFC2616 (1999) -&amp;gt;&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;kbcoding.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HTTP는 기본적으로 서버-클라이언트 구조를 따라 HTTP 프로토콜 통신을 위해서는 클라이언트는 서버로 Requst를 보내고 Response를 받는 형태를 갖는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HTTP 2.0은 한 Connection으로 동시 여러개 메시지를 주고받으며, 비동기적으로 1.1버전에 비해 효율적이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;884&quot; data-origin-height=&quot;720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bi1Na9/btrTKHl06xe/i1VMNodhJLkmGOrqYimSgk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bi1Na9/btrTKHl06xe/i1VMNodhJLkmGOrqYimSgk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bi1Na9/btrTKHl06xe/i1VMNodhJLkmGOrqYimSgk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbi1Na9%2FbtrTKHl06xe%2Fi1VMNodhJLkmGOrqYimSgk%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;480&quot; height=&quot;391&quot; data-origin-width=&quot;884&quot; data-origin-height=&quot;720&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;h2 data-ke-size=&quot;size26&quot;&gt;IDL(Interface Definition Language)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서버와 클라이언트가 정보를 저장하는 규칙이다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size16&quot;&gt;XML(eXtensible Markup Langauge)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터를 정의하는 규칙을 제공하는 마크업언어로 다른 프로그래밍 언어와 달리 XML은 다체적으로 컴퓨팅 작업을 수행할 수 없다. 데이터를 저장하고 전달하기 위해 만들어졌다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;JSON(JavaScript Object Notation)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존 XML의 가독성과 속도를 보완하여 등장한 것으로 key-value구조를 갖는다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Protocol buffer(proto)&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구조화된 데이터를 직렬화하는 방식으로 유선이나 데이터 저장을 목적으로 서로 통신할 프로그램을 개발할때 유용하다. 프로토콜 버퍼는 데이터를 이진수로 변환하는 특징이 있다. 그렇기에 다음과 같은 장점을 가진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 빠른 전송 속도&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. CPU 사용량 감소&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 파일크기의 감소&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. XML대비 가독성이 좋다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;proto 코드 예시&lt;/p&gt;
&lt;pre class=&quot;cmake&quot;&gt;&lt;code&gt;syntax = &quot;proto3&quot;;
option java_package = &quot;com.grpc.education&quot;;
option java_multiple_files = true;
package education;

message EmptyRequest{
}

message BasicRequest {
  string message = 1;
}

message BasicResponse {
  string message = 1;
  string statusCode = 2;
  string statusMessage = 3;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1278&quot; data-origin-height=&quot;750&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ciA6aK/btrTMQPRPsn/TiSQ3Q1J8MgZmpFiWYMCxk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ciA6aK/btrTMQPRPsn/TiSQ3Q1J8MgZmpFiWYMCxk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ciA6aK/btrTMQPRPsn/TiSQ3Q1J8MgZmpFiWYMCxk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FciA6aK%2FbtrTMQPRPsn%2FTiSQ3Q1J8MgZmpFiWYMCxk%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;1278&quot; height=&quot;750&quot; data-origin-width=&quot;1278&quot; data-origin-height=&quot;750&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;h2 data-ke-size=&quot;size26&quot;&gt;gRPC&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;gRPC는 protocol buffer와 RPC를 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2022.12 당시, IDL로는 proto3를 사용하며 호환하는 언어로는 Java, C++, Python, Java Lite, Ruby, JavaScript, Objective-C, C#을 호환한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;gRPC의 핵심은 &lt;b&gt;분산&lt;/b&gt;으로 클라이언트 으용 프로개름을 서버에서 함수를 원격 호출할 수 있어 MSA(Micro Service Architecture)를 구현하기 수월하다. gRPC 서버에서는 Stub을 통한 호출을 처리할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;gRPC 구조&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;687&quot; data-origin-height=&quot;450&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/7Aphm/btrTIrR4BpT/5bRgDRqCHZFvemEoBZ1syK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/7Aphm/btrTIrR4BpT/5bRgDRqCHZFvemEoBZ1syK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/7Aphm/btrTIrR4BpT/5bRgDRqCHZFvemEoBZ1syK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F7Aphm%2FbtrTIrR4BpT%2F5bRgDRqCHZFvemEoBZ1syK%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;687&quot; height=&quot;450&quot; data-origin-width=&quot;687&quot; data-origin-height=&quot;450&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;Reference.&lt;/p&gt;
&lt;figure id=&quot;og_1671111276958&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;Introduction to gRPC&quot; data-og-description=&quot;An introduction to gRPC and protocol buffers.&quot; data-og-host=&quot;grpc.io&quot; data-og-source-url=&quot;https://grpc.io/docs/what-is-grpc/introduction/&quot; data-og-url=&quot;https://grpc.io/docs/what-is-grpc/introduction/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/wx8YO/hyQTM4F7ug/Xf0ZqCEe1hg0gYSWv5u88k/img.png?width=1500&amp;amp;height=1500&amp;amp;face=0_0_1500_1500,https://scrap.kakaocdn.net/dn/bsnpuk/hyQTNoZRum/mjCKn7bmtNRfbdYikLe9K0/img.png?width=1500&amp;amp;height=1500&amp;amp;face=0_0_1500_1500&quot;&gt;&lt;a href=&quot;https://grpc.io/docs/what-is-grpc/introduction/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://grpc.io/docs/what-is-grpc/introduction/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/wx8YO/hyQTM4F7ug/Xf0ZqCEe1hg0gYSWv5u88k/img.png?width=1500&amp;amp;height=1500&amp;amp;face=0_0_1500_1500,https://scrap.kakaocdn.net/dn/bsnpuk/hyQTNoZRum/mjCKn7bmtNRfbdYikLe9K0/img.png?width=1500&amp;amp;height=1500&amp;amp;face=0_0_1500_1500');&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;Introduction to gRPC&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;An introduction to gRPC and protocol buffers.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;grpc.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id=&quot;og_1671108345412&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;RPC 작동 방식 - Win32 apps&quot; data-og-description=&quot;RPC 도구는 클라이언트가 원격 서버 프로그램에 있는 프로시저를 직접 호출하는 것처럼 사용자에게 표시됩니다.&quot; data-og-host=&quot;learn.microsoft.com&quot; data-og-source-url=&quot;https://learn.microsoft.com/ko-kr/windows/win32/rpc/how-rpc-works&quot; data-og-url=&quot;https://learn.microsoft.com/ko-kr/windows/win32/rpc/how-rpc-works&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/2rwXo/hyQTKMsAgQ/2Uaxw0lGkokKNzOJMc9tCk/img.png?width=400&amp;amp;height=400&amp;amp;face=0_0_400_400,https://scrap.kakaocdn.net/dn/no92S/hyQUVTa8Py/zF9bjNBvOEiQjzSUxqr1k0/img.png?width=263&amp;amp;height=221&amp;amp;face=0_0_263_221&quot;&gt;&lt;a href=&quot;https://learn.microsoft.com/ko-kr/windows/win32/rpc/how-rpc-works&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://learn.microsoft.com/ko-kr/windows/win32/rpc/how-rpc-works&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/2rwXo/hyQTKMsAgQ/2Uaxw0lGkokKNzOJMc9tCk/img.png?width=400&amp;amp;height=400&amp;amp;face=0_0_400_400,https://scrap.kakaocdn.net/dn/no92S/hyQUVTa8Py/zF9bjNBvOEiQjzSUxqr1k0/img.png?width=263&amp;amp;height=221&amp;amp;face=0_0_263_221');&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;RPC 작동 방식 - Win32 apps&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;RPC 도구는 클라이언트가 원격 서버 프로그램에 있는 프로시저를 직접 호출하는 것처럼 사용자에게 표시됩니다.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;learn.microsoft.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id=&quot;og_1671111285624&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;gRPC 1 - gRPC란?&quot; data-og-description=&quot;배경지식 gRPC는 Google에서 개발한 RPC(Remote Procedure Call) 시스템입니다. 전송을 위해 TCP/IP 프로토콜과 HTTP 2.0 프로토콜을 사용하고 IDL(Interface Definition language)로 protocol buffer를 사용합니다. gRPC에 대&quot; data-og-host=&quot;chacha95.github.io&quot; data-og-source-url=&quot;https://chacha95.github.io/2020-06-15-gRPC1/&quot; data-og-url=&quot;https://chacha95.github.io/2020-06-15-gRPC1/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bJO5cn/hyQTDs29Wr/rIJXRPk749APbmKlaE39tK/img.png?width=225&amp;amp;height=225&amp;amp;face=0_0_225_225,https://scrap.kakaocdn.net/dn/dcs4Dw/hyQTFqTexQ/3KvyTcJvsoB5VyUmPkz8uk/img.png?width=225&amp;amp;height=225&amp;amp;face=0_0_225_225,https://scrap.kakaocdn.net/dn/dKRWgx/hyQUXwG2n3/kB0U3gGytzHegv2MXKxa4k/img.png?width=1321&amp;amp;height=747&amp;amp;face=0_0_1321_747&quot;&gt;&lt;a href=&quot;https://chacha95.github.io/2020-06-15-gRPC1/&quot; data-source-url=&quot;https://chacha95.github.io/2020-06-15-gRPC1/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bJO5cn/hyQTDs29Wr/rIJXRPk749APbmKlaE39tK/img.png?width=225&amp;amp;height=225&amp;amp;face=0_0_225_225,https://scrap.kakaocdn.net/dn/dcs4Dw/hyQTFqTexQ/3KvyTcJvsoB5VyUmPkz8uk/img.png?width=225&amp;amp;height=225&amp;amp;face=0_0_225_225,https://scrap.kakaocdn.net/dn/dKRWgx/hyQUXwG2n3/kB0U3gGytzHegv2MXKxa4k/img.png?width=1321&amp;amp;height=747&amp;amp;face=0_0_1321_747');&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;gRPC 1 - gRPC란?&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;배경지식 gRPC는 Google에서 개발한 RPC(Remote Procedure Call) 시스템입니다. 전송을 위해 TCP/IP 프로토콜과 HTTP 2.0 프로토콜을 사용하고 IDL(Interface Definition language)로 protocol buffer를 사용합니다. gRPC에 대&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;chacha95.github.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id=&quot;og_1671109454904&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;What is the Difference between HTTP 1.2 and HTTP 2.0 versions? why should I care?&quot; data-og-description=&quot;Well, this question is very basic, but many of us don't know what is the exact purpose, and why the name has changed and what might be the difference. Since,&amp;nbsp;we all know HTTP is&amp;nbsp;protocol&amp;nbsp;that is widely used over&amp;nbsp;internet, HTTP 1.&quot; data-og-host=&quot;www.linkedin.com&quot; data-og-source-url=&quot;https://www.linkedin.com/pulse/what-difference-between-http-12-20-versions-why-should-anand-bhagwat&quot; data-og-url=&quot;https://www.linkedin.com/pulse/what-difference-between-http-12-20-versions-why-should-anand-bhagwat&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/89C92/hyQUZ2l4lC/0oKfsHsFqmWG7kZONBgFvK/img.png?width=884&amp;amp;height=720&amp;amp;face=0_0_884_720,https://scrap.kakaocdn.net/dn/dly5F7/hyQUYWFG3U/rxjnn2E5CbXrca7QGatba1/img.png?width=884&amp;amp;height=720&amp;amp;face=0_0_884_720,https://scrap.kakaocdn.net/dn/xqyvk/hyQTEyIMSS/9twlgg1c7f4yn0b2kacHSK/img.png?width=884&amp;amp;height=720&amp;amp;face=0_0_884_720&quot;&gt;&lt;a href=&quot;https://www.linkedin.com/pulse/what-difference-between-http-12-20-versions-why-should-anand-bhagwat&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.linkedin.com/pulse/what-difference-between-http-12-20-versions-why-should-anand-bhagwat&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/89C92/hyQUZ2l4lC/0oKfsHsFqmWG7kZONBgFvK/img.png?width=884&amp;amp;height=720&amp;amp;face=0_0_884_720,https://scrap.kakaocdn.net/dn/dly5F7/hyQUYWFG3U/rxjnn2E5CbXrca7QGatba1/img.png?width=884&amp;amp;height=720&amp;amp;face=0_0_884_720,https://scrap.kakaocdn.net/dn/xqyvk/hyQTEyIMSS/9twlgg1c7f4yn0b2kacHSK/img.png?width=884&amp;amp;height=720&amp;amp;face=0_0_884_720');&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;What is the Difference between HTTP 1.2 and HTTP 2.0 versions? why should I care?&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Well, this question is very basic, but many of us don't know what is the exact purpose, and why the name has changed and what might be the difference. Since,&amp;nbsp;we all know HTTP is&amp;nbsp;protocol&amp;nbsp;that is widely used over&amp;nbsp;internet, HTTP 1.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.linkedin.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>gRPC</category>
      <category>gRPC</category>
      <category>HTTP</category>
      <category>HTTP2.0</category>
      <category>IDL</category>
      <category>JSON</category>
      <category>Proto</category>
      <category>Protocol Buffer</category>
      <category>xml</category>
      <author>큐범</author>
      <guid isPermaLink="true">https://kbcoding.tistory.com/104</guid>
      <comments>https://kbcoding.tistory.com/104#entry104comment</comments>
      <pubDate>Thu, 15 Dec 2022 22:05:36 +0900</pubDate>
    </item>
    <item>
      <title>[CS] 컴퓨터의 구성(Software, Hardware, SystemBus)</title>
      <link>https://kbcoding.tistory.com/103</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;컴퓨터의 구성&amp;nbsp;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;하드웨어( Hardware): 컴퓨터를 구성하는 기계적 장치&lt;/li&gt;
&lt;li&gt;소프트웨어(Software) : 하드웨어의 동작을 지시하고 제어하는 명령어 집합&lt;/li&gt;
&lt;/ul&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;하드웨어(Hardware)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CPU(중앙처리장치) : 프로그램의 모든 정보를 처리하는 역할을 담당한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;RAM(주기억 장치) : 프로그램 실행과 휘발성 데이터를 저장하는 공간&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HDD,SDD(보조기억 장치) : 내장형 기억 장치로 비휘발성 데이터를 저장하는 공간&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;IO Device(마우스, 프린터, 모니터 등)&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;소프트웨어(Software)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시스템 소프트웨어(System Software) : OS, 로더, 장치 드라이버, 컴파일러&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;응용 소프트웨어(Application Software) : 크롬, 유튜브, 멜론 등&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;펌웨어(Firmware)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특정 하드웨어 장치에 포함된 &lt;b&gt;소프트웨어&lt;/b&gt;로 소프트웨어를 읽어 실행하거나 수정이 가능한 장치를 뜻한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하드웨어의 제어와 구동을 담당하는 일종의 운영체제이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대부분의 펌웨어는 ROM, PROM에 저장된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예) 바이오스, 스마트폰, 가전 전자제품의 프로그램&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;1280&quot; data-origin-height=&quot;675&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dxhKUx/btrRJOVi24l/7x0TYno3onsPCMKsCDNKN1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dxhKUx/btrRJOVi24l/7x0TYno3onsPCMKsCDNKN1/img.png&quot; data-alt=&quot;출처 : https://velog.io/@mee9204/컴퓨터의-구조&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dxhKUx/btrRJOVi24l/7x0TYno3onsPCMKsCDNKN1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdxhKUx%2FbtrRJOVi24l%2F7x0TYno3onsPCMKsCDNKN1%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;688&quot; height=&quot;363&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;675&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처 : https://velog.io/@mee9204/컴퓨터의-구조&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하드웨어의 구성은 각 화살표는 시스템 버스(SystemBus)라 한다.&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;중앙처리장치(Central Processing Unit, CPU)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴퓨터는 인간을 형상화해서 만들어진 기계인데 CPU는 인간의 두뇌 역할을 담담한다. 주기억장치에서 프로그램의 명령과 데이터를 읽어 처리하고 명령어의 &lt;b&gt;수행 순서&lt;/b&gt;를 제어한다. 중앙처리장치는 비교와 연산을 담당하는 ALU(산술 논리 장치)와 명령어의 해석과 실행을 담당하는 제어장치, 속도가 빠른데이터 기억 장소인 레지스터로 구성한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;기억장치&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로그램, 데이터, 연산값 등을 저장하는 장치이다. 주기억장치와 보조기억장치로 나눠지며&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주기억 장치는 RAM, ROM으로 실행중인 프로그램과 같은 프로그램에 같은 프로그램에 필요한 데이터를 &lt;b&gt;일시적&lt;/b&gt;으로 저장해 휘발성 특징을 가지고 있다. 보조기억장치는 HDD, SDD 등을 의미하며 주기억장치에 비해 속도성은 떨어지지만 &lt;b&gt;비휘발성&lt;/b&gt;으로 영구적인 보관이 가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;입출력장치&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;입력, 출력 장치로 나뉘어진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;입력장치는 컴퓨터 내부로 값을 입력하는 장치로 키보드, 마우스가 대표적이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;출력장치는 컴퓨터 외부로 값을 표현하는 장치로 프린터, 모니터, 스피커가 대표적이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;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;350&quot; data-origin-height=&quot;256&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cMpD3j/btrRKKk7Oec/87elKgDWKJAHYIXbbhjQ20/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cMpD3j/btrRKKk7Oec/87elKgDWKJAHYIXbbhjQ20/img.png&quot; data-alt=&quot;출처 : Wikipedia - System Bus&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cMpD3j/btrRKKk7Oec/87elKgDWKJAHYIXbbhjQ20/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcMpD3j%2FbtrRKKk7Oec%2F87elKgDWKJAHYIXbbhjQ20%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;350&quot; height=&quot;256&quot; data-origin-width=&quot;350&quot; data-origin-height=&quot;256&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처 : Wikipedia - System Bus&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;h3 data-ke-size=&quot;size23&quot;&gt;주소 버스(Address Bus)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;메모리의 주소나 I/O Unit의 &lt;b&gt;포트 번호&lt;/b&gt;를 전달한다.&lt;/li&gt;
&lt;li&gt;중앙처리장치가 주기억장치나 입출력장치로 기억장치 주소를 전달하는 통로로&amp;nbsp;&lt;b&gt;'단방향'버스&lt;/b&gt;이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;데이터 버스(Data Bus)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;데이터를 전달하는 통로&lt;/li&gt;
&lt;li&gt;각 구성요소(CPU, Memory, I/O Unit)는 &lt;b&gt;양방향&lt;/b&gt;으로 데이터 전달이 가능한 버스를 사용한다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;제어버스(Control Bus)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;제어 신호 전달한다.&lt;/li&gt;
&lt;li&gt;Read/Write 신호를 전달한다.&lt;/li&gt;
&lt;li&gt;각 구성요소(CPU, Memory, I/O Unit)는 &lt;b&gt;양방향&lt;/b&gt;으로 데이터 전달이 가능한 버스를 사용한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>CS</category>
      <category>기억장치</category>
      <category>소프트웨어</category>
      <category>시스템 버스</category>
      <category>컴퓨터구성</category>
      <category>펌웨어</category>
      <category>하드웨어</category>
      <author>큐범</author>
      <guid isPermaLink="true">https://kbcoding.tistory.com/103</guid>
      <comments>https://kbcoding.tistory.com/103#entry103comment</comments>
      <pubDate>Mon, 21 Nov 2022 20:51:18 +0900</pubDate>
    </item>
    <item>
      <title>[DB] 동시성 이슈(Concurrency Issue)</title>
      <link>https://kbcoding.tistory.com/102</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;동시성(Concurrency)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;동시성은 운영체제에서 사용되는 용어로 동시에 실행되는 것처럼 보이는 것으로 논리적인 개념으로 싱글코어와 멀티코어에서 가능하다. 해당 글에서 사용되는 &lt;b&gt;DB에서의 여러개의 스레드(요청)이 동시에 같은 주소의 값(데이터)을 참조하여 접근 및 수정하는 것을 의미&lt;/b&gt;한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를들어,&amp;nbsp; 트랜젝션 A가 알렉스라는 이름을 읽고 트랜젝션 B가 밥을 추가해 같은 트랜젝션에서 1번의 리드와 3번의 리드가 다른 것을 확인한다. 유령 레코드가 나타나는 현상으로 이를 팬텀리드(Phantom Read)라 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-11-15 오전 12.23.21.png&quot; data-origin-width=&quot;432&quot; data-origin-height=&quot;271&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bM7xUV/btrRd62nd03/0VYSIbZH4HXyuIFKQZuG71/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bM7xUV/btrRd62nd03/0VYSIbZH4HXyuIFKQZuG71/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bM7xUV/btrRd62nd03/0VYSIbZH4HXyuIFKQZuG71/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbM7xUV%2FbtrRd62nd03%2F0VYSIbZH4HXyuIFKQZuG71%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;432&quot; height=&quot;271&quot; data-filename=&quot;스크린샷 2022-11-15 오전 12.23.21.png&quot; data-origin-width=&quot;432&quot; data-origin-height=&quot;271&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반적으로 문제 해결 방식에는 두 가지 방법이 존재한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;1. 비관적 동시성 제어&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;데이터를 비관적으로 바라보며 다른 요청에 의해서 수정될 가능성을 염두하여 Lock을 거는 방식이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;데이터베이스의 데이터를 잠그고 다른 사용자가 동일한 잠금을 보유하지 못하도록 한다. 이는 데이터베이스로 통하는 문을 하나만 놔두고 하나의 트랜젝션이 DB에 접근할 동안 다른 트랜젝션이 접근을 못하게 하는 방식이다. &lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;장점&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;구현이 간단하다.&amp;nbsp; 데이터 서버는&amp;nbsp; 잠금을 지원하기 때문에 제어를 쉽게 구현할 수 있다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;매우 간단하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;단점&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;확장성이 좋지 않다.&lt;/li&gt;
&lt;li&gt;교착 상태(Dead Lock)에 빠지기 쉽다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;예를들어, 치킨집 지점관리자 1은 A지점 데이터에 대해서 수정을 하고 2는 B지점 데이터에 수정을한다. 수정을 하는 동안 각각의 A, B지점에 데이터는 '잠금'상태에 들어간다. 이후 관리자 1은 B를 2는 A를 수정하기 원하는데 '잠금' 상태로 인하여 각각 원하는 다음 지점에 대해서 기다리로 결정하면 교착상태가 발생한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;잠금이 오래 지속될 수 있다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size20&quot;&gt;적용방식&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. DB에서 제공하는 데이터 Lock수준을 높인다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. select for update 활용하여 Lock을 잡는다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. transaction의 write Lock(Exclusive Lock)을 사용한다. DB는 데이터를 수정할 경우, write lock이 발동되고 트랜젝션이 끝날때까지 Lock은 유지된다.&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;size20&quot;&gt;2. 낙관적 동시성 제어&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터가 다른 요청에 의해 변경되지 않고 한 트랜잭션에 의해서 수정될 것을 염두한 방법으로&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;장점&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;확장성이 높다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;구현이 간단하다.&amp;nbsp; &amp;nbsp; &amp;nbsp; 행 버전을 사용할 경우 구현하기가 비교적 쉽다.&lt;/li&gt;
&lt;li&gt;교착상태의 위험이 적다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;단점&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;안전성이 떨어진다.&lt;/li&gt;
&lt;li&gt;요청을 재시도하는 경우가 많아진다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size20&quot;&gt;적용방식&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 마지막 업데이트를 최신으로 덮어쓴다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 사용자가 변경한 필드를 비교한다. 이는 데이터 변경 이후 커밋을 하기 이전에 사용자가 데이터를 읽을 때와 동일한지 확인하는 작업이다. 기존에 읽은 데이터와 데이터베이스의 데이터가 같지 않으면 서버는 사용자의 변경 사항을 커밋하지 않고 사용자에게 알린다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Reference&lt;/p&gt;
&lt;figure id=&quot;og_1668439542203&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;Phantom Read&quot; data-og-description=&quot;I. Phantom Read 정의 한 트랜잭션 내에서 같은 쿼리를 두 번 수행 시, 첫 번째 쿼리에서 없던 레코드(유령, Phantom)가 두 번째 쿼리에서 발생하는 현상 절차 절차 트랜잭션 데이터 예제 설명 ① Read Tran&quot; data-og-host=&quot;itpenote.tistory.com&quot; data-og-source-url=&quot;https://itpenote.tistory.com/616&quot; data-og-url=&quot;https://itpenote.tistory.com/616&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/dJnCiV/hyQznqedKs/ZDgjZdO6DSVy0oAlbWZJGk/img.png?width=340&amp;amp;height=215&amp;amp;face=0_0_340_215,https://scrap.kakaocdn.net/dn/eJaCg/hyQzi3wNyu/wCamIjBKQiaK0djGoKgTkk/img.png?width=340&amp;amp;height=215&amp;amp;face=0_0_340_215,https://scrap.kakaocdn.net/dn/yaeYv/hyQzqHdI76/6K3oCyG0zfYIeuHEICYKD0/img.png?width=340&amp;amp;height=215&amp;amp;face=0_0_340_215&quot;&gt;&lt;a href=&quot;https://itpenote.tistory.com/616&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://itpenote.tistory.com/616&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/dJnCiV/hyQznqedKs/ZDgjZdO6DSVy0oAlbWZJGk/img.png?width=340&amp;amp;height=215&amp;amp;face=0_0_340_215,https://scrap.kakaocdn.net/dn/eJaCg/hyQzi3wNyu/wCamIjBKQiaK0djGoKgTkk/img.png?width=340&amp;amp;height=215&amp;amp;face=0_0_340_215,https://scrap.kakaocdn.net/dn/yaeYv/hyQzqHdI76/6K3oCyG0zfYIeuHEICYKD0/img.png?width=340&amp;amp;height=215&amp;amp;face=0_0_340_215');&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;Phantom Read&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;I. Phantom Read 정의 한 트랜잭션 내에서 같은 쿼리를 두 번 수행 시, 첫 번째 쿼리에서 없던 레코드(유령, Phantom)가 두 번째 쿼리에서 발생하는 현상 절차 절차 트랜잭션 데이터 예제 설명 ① Read Tran&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;itpenote.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id=&quot;og_1668439803591&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;Database Concurrency Conflicts in the Real World&quot; data-og-description=&quot;A lot of articles have been written about database concurrency conflict detection and the various ways of handling them.Unfortunately most of these arti...&quot; data-og-host=&quot;www.codemag.com&quot; data-og-source-url=&quot;https://www.codemag.com/article/0607081/Database-Concurrency-Conflicts-in-the-Real-World&quot; data-og-url=&quot;https://www.codemag.com/article/0607081/Database-Concurrency-Conflicts-in-the-Real-World&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/fnvu8/hyQzqUOCeH/RjY7tkk7MjdKtoVyLFJY30/img.png?width=240&amp;amp;height=400&amp;amp;face=92_35_135_82&quot;&gt;&lt;a href=&quot;https://www.codemag.com/article/0607081/Database-Concurrency-Conflicts-in-the-Real-World&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.codemag.com/article/0607081/Database-Concurrency-Conflicts-in-the-Real-World&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/fnvu8/hyQzqUOCeH/RjY7tkk7MjdKtoVyLFJY30/img.png?width=240&amp;amp;height=400&amp;amp;face=92_35_135_82');&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;Database Concurrency Conflicts in the Real World&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;A lot of articles have been written about database concurrency conflict detection and the various ways of handling them.Unfortunately most of these arti...&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.codemag.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_1668440258151&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;[DB] 동시성 문제 해결방법&quot; data-og-description=&quot;동시성 문제가 무엇이고 해결방법에 대하여 알아보도록 한다.&quot; data-og-host=&quot;chrisjune-13837.medium.com&quot; data-og-source-url=&quot;https://chrisjune-13837.medium.com/db-%EB%8F%99%EC%8B%9C%EC%84%B1-%EB%AC%B8%EC%A0%9C-%ED%95%B4%EA%B2%B0%EB%B0%A9%EB%B2%95-f5e52e2e3&quot; data-og-url=&quot;https://chrisjune-13837.medium.com/db-%EB%8F%99%EC%8B%9C%EC%84%B1-%EB%AC%B8%EC%A0%9C-%ED%95%B4%EA%B2%B0%EB%B0%A9%EB%B2%95-f5e52e2e3&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bh73KI/hyQzk1kIHy/cvUHgXjLDC13x1moKVAUA0/img.png?width=1200&amp;amp;height=346&amp;amp;face=0_0_1200_346&quot;&gt;&lt;a href=&quot;https://chrisjune-13837.medium.com/db-%EB%8F%99%EC%8B%9C%EC%84%B1-%EB%AC%B8%EC%A0%9C-%ED%95%B4%EA%B2%B0%EB%B0%A9%EB%B2%95-f5e52e2e3&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://chrisjune-13837.medium.com/db-%EB%8F%99%EC%8B%9C%EC%84%B1-%EB%AC%B8%EC%A0%9C-%ED%95%B4%EA%B2%B0%EB%B0%A9%EB%B2%95-f5e52e2e3&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bh73KI/hyQzk1kIHy/cvUHgXjLDC13x1moKVAUA0/img.png?width=1200&amp;amp;height=346&amp;amp;face=0_0_1200_346');&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;[DB] 동시성 문제 해결방법&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;chrisjune-13837.medium.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>DB</category>
      <category>DB</category>
      <category>DB Concurrency Issue</category>
      <category>동시성</category>
      <category>동시성이슈</category>
      <author>큐범</author>
      <guid isPermaLink="true">https://kbcoding.tistory.com/102</guid>
      <comments>https://kbcoding.tistory.com/102#entry102comment</comments>
      <pubDate>Tue, 15 Nov 2022 01:11:06 +0900</pubDate>
    </item>
    <item>
      <title>[JPA] N+1 문제 및 해결 방안</title>
      <link>https://kbcoding.tistory.com/101</link>
      <description>&lt;h2 data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;N+1이란?&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;연관 관계가 설정된 엔티티를 조회할 경우에 조회된 데이터 갯수 N번 만큼 연관관계의 조회 쿼리가 추가로 발생하여 데이터를 읽어와 서버와 데이터의 접촉이 N번 발생하는 현상이다.&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;h2 data-ke-size=&quot;size16&quot;&gt;가정&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;한 게시물에는 여러개의 해시태그를 들 수 있다.&lt;/li&gt;
&lt;li&gt;해시태그는 한 게시물에만 속한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;kotlin&quot;&gt;&lt;code&gt;@Entity
@Getter
@Setter
@NoArgsConstructor
public class Board {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = &quot;board_id&quot;)
    private Long id;
    private String content;

    @OneToMany(mappedBy = &quot;board&quot;, fetch = FetchType.EAGER)
    private List&amp;lt;HashTag&amp;gt; hashTags = new ArrayList&amp;lt;&amp;gt;();

    public Board(String content) {
        this.content = content;
    }


}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;kotlin&quot;&gt;&lt;code&gt;@Entity
@Getter
@Setter
@NoArgsConstructor
public class HashTag {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;

    @ManyToOne
    private Board board;

    public HashTag(String name) {
        this.name = name;
    }
}
&lt;/code&gt;&lt;/pre&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-ke-style=&quot;style1&quot;&gt;4개의 해시태그를 생성했다.&lt;/li&gt;
&lt;li data-ke-style=&quot;style1&quot;&gt;10개의 게시물을 생성한다.&lt;/li&gt;
&lt;li data-ke-style=&quot;style1&quot;&gt;각 게시물에는 4개씩 해시태그가 들어가있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;@Test
@Commit
public void 게시물조회(){

    ArrayList&amp;lt;HashTag&amp;gt; hashTags = new ArrayList&amp;lt;&amp;gt;();
    for(int i=0; i&amp;lt;4; i++){
        HashTag hashTag = new HashTag(&quot;hashtag&quot; + i);
        hashTags.add(hashTag);
    }
    hashTahRepository.saveAll(hashTags);

    List&amp;lt;Board&amp;gt; boards = new ArrayList&amp;lt;&amp;gt;();
    for(int i=0; i&amp;lt;10; i++){
        Board board = new Board(&quot;board&quot; + i);
        board.setHashTags(hashTags);
        boards.add(board);
    }

    em.clear();

    System.out.println(&quot;------------------------------------------------------------------------&quot;);
    List&amp;lt;Board&amp;gt; boardAll = boardRepository.findAll();
    assertFalse(boardAll.isEmpty());
 }&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;아래와 같이 단순 게시물을 조회했을 뿐인데 해시태그의 select 문이 나가는 것을 알 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-10-09 오후 8.30.08.png&quot; data-origin-width=&quot;1962&quot; data-origin-height=&quot;263&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uaLSj/btrN5Gs16xQ/GWgR2lenWHIs6d5FHEHQW0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uaLSj/btrN5Gs16xQ/GWgR2lenWHIs6d5FHEHQW0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uaLSj/btrN5Gs16xQ/GWgR2lenWHIs6d5FHEHQW0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuaLSj%2FbtrN5Gs16xQ%2FGWgR2lenWHIs6d5FHEHQW0%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;1962&quot; height=&quot;263&quot; data-filename=&quot;스크린샷 2022-10-09 오후 8.30.08.png&quot; data-origin-width=&quot;1962&quot; data-origin-height=&quot;263&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;그러면 entity의 연관관계에서 fetch를 즉시로딩(EAGER)이 아니라 지연로딩(LAZY)라면 다른가??&lt;/p&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;@OneToMany(mappedBy = &quot;board&quot;, fetch = FetchType.LAZY)
private List&amp;lt;HashTag&amp;gt; hashTags = new ArrayList&amp;lt;&amp;gt;();&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-10-09 오후 8.40.56.png&quot; data-origin-width=&quot;808&quot; data-origin-height=&quot;46&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cGsxxV/btrN9lazeol/y9cQXl8YwyXeR67CcIjQnk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cGsxxV/btrN9lazeol/y9cQXl8YwyXeR67CcIjQnk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cGsxxV/btrN9lazeol/y9cQXl8YwyXeR67CcIjQnk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcGsxxV%2FbtrN9lazeol%2Fy9cQXl8YwyXeR67CcIjQnk%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;808&quot; height=&quot;46&quot; data-filename=&quot;스크린샷 2022-10-09 오후 8.40.56.png&quot; data-origin-width=&quot;808&quot; data-origin-height=&quot;46&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와같이 쿼리문이 한번 날라가게 되었지만&lt;/p&gt;
&lt;pre class=&quot;abnf&quot;&gt;&lt;code&gt;System.out.println(&quot;------------------------------------------------------------------------&quot;);
List&amp;lt;Board&amp;gt; boardAll = boardRepository.findAll();
System.out.println(&quot;------------------------------------------------------------------------&quot;);
boardAll.forEach(board -&amp;gt; {
    board.getHashTags().size();
});&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음과같이 접근을 하게되면 아래와 같은 N+1의 문제가 다시 생긴다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-10-09 오후 8.54.43.png&quot; data-origin-width=&quot;1971&quot; data-origin-height=&quot;288&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zDv99/btrN79anzin/VUPLDtSkYyxK7tnLSOoLeK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zDv99/btrN79anzin/VUPLDtSkYyxK7tnLSOoLeK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zDv99/btrN79anzin/VUPLDtSkYyxK7tnLSOoLeK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzDv99%2FbtrN79anzin%2FVUPLDtSkYyxK7tnLSOoLeK%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;1971&quot; height=&quot;288&quot; data-filename=&quot;스크린샷 2022-10-09 오후 8.54.43.png&quot; data-origin-width=&quot;1971&quot; data-origin-height=&quot;288&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;h2 data-ke-size=&quot;size26&quot;&gt;문제해결 방법&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Fetch join&lt;/h3&gt;
&lt;pre class=&quot;n1ql&quot;&gt;&lt;code&gt;@Query(&quot;select b from Board b join fetch b.hashTags&quot;)
List&amp;lt;Board&amp;gt; findAllJoinFetch();&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1665317003289&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Hibernate: select board0_.board_id as board_id1_0_0_, hashtags1_.id as id1_2_1_, board0_.content as content2_0_0_, hashtags1_.board_board_id as board_bo3_2_1_, hashtags1_.name as name2_2_1_, hashtags1_.board_board_id as board_bo3_2_0__, hashtags1_.id as id1_2_0__ from board board0_ inner join hash_tag hashtags1_ on board0_.board_id=hashtags1_.board_board_id&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음과 같이&amp;nbsp; INNER JOIN으로 필요한 hashtag를 불러오는 쿼리를 볼 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만, fetch join은 Entity연관관계에서 FetchType을 설정했다면 사용할수 없는 단점이 있다. 따라서, 현재 LAZY로 해놓은 상황에서는 select를 하는 순간 연관 관계의 데이터를 가져오기 때문에 Fetch Join으로 해결 할 수 없다. 그리고 페이징 쿼리를 사용할 수 없는 단점이 있다.&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;EntityGraph&lt;/h3&gt;
&lt;pre class=&quot;less&quot;&gt;&lt;code&gt;@EntityGraph(attributePaths = &quot;hashTags&quot;)
@Query(&quot;select b from Board b&quot;)
List&amp;lt;Board&amp;gt; findAllEntityGraph();&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1665317312608&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Hibernate: select board0_.board_id as board_id1_0_0_, hashtags1_.id as id1_2_1_, board0_.content as content2_0_0_, hashtags1_.board_board_id as board_bo3_2_1_, hashtags1_.name as name2_2_1_, hashtags1_.board_board_id as board_bo3_2_0__, hashtags1_.id as id1_2_0__ from board board0_ left outer join hash_tag hashtags1_ on board0_.board_id=hashtags1_.board_board_id&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Fetch Join과는 다르게 Left Outer Join이 나가는 것을 볼 수 있다. @EntityGraph attributePaths의 역할은 가져올 필드명을 지정하면 면 지연로딩이아닌 즉시로딩으로 가져온다.&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;Fetch Join과 EntityGraph 사용시 주의점&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Fetch Join과 EntityGraph는 JPQL을 사용해 Join문을 사용한다. 공통적으로 Catesian Product에 의해 Board수 만큼 Hashtag가 중복이 발생할 수 있다. 따라서, 중복에 대해서 주의해야한다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;중복발생시&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;컬렉션 Set을 사용한다.&lt;/li&gt;
&lt;li&gt;distinct를 사용한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;BatchSize&lt;/h3&gt;
&lt;pre class=&quot;less&quot;&gt;&lt;code&gt;@BatchSize(size = 5)
@OneToMany(mappedBy = &quot;board&quot;, fetch = FetchType.LAZY)
private List&amp;lt;HashTag&amp;gt; hashTags = new ArrayList&amp;lt;&amp;gt;();
&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1665317936912&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Hibernate: select hashtags0_.board_board_id as board_bo3_2_1_, hashtags0_.id as id1_2_1_, hashtags0_.id as id1_2_0_, hashtags0_.board_board_id as board_bo3_2_0_, hashtags0_.name as name2_2_0_ from hash_tag hashtags0_ where hashtags0_.board_board_id in (?, ?, ?, ?, ?)
Hibernate: select hashtags0_.board_board_id as board_bo3_2_1_, hashtags0_.id as id1_2_1_, hashtags0_.id as id1_2_0_, hashtags0_.board_board_id as board_bo3_2_0_, hashtags0_.name as name2_2_0_ from hash_tag hashtags0_ where hashtags0_.board_board_id in (?, ?, ?, ?, ?)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지연로딩이기에 Board를 조회해서 해시태그에 접근할 경우 다음과 같은 IN절을 배치 사이즈만큼 인자로 넘어가서 2번이 날라가는 것을 알수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;EX) BatchSize 20 해시태그 100개 IN절이 5번 조회&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;FetchMode.SUBSELECT&lt;/span&gt;&lt;/h3&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;@Fetch(FetchMode.SUBSELECT)
@OneToMany(mappedBy = &quot;board&quot;, fetch = FetchType.LAZY)
private List&amp;lt;HashTag&amp;gt; hashTags = new ArrayList&amp;lt;&amp;gt;();&lt;/code&gt;&lt;/pre&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div data-rnw-media-class=&quot;1934-196__1932-_b1430-196&quot;&gt;
&lt;div&gt;
&lt;div data-rnw-media-class=&quot;1933-__1931&quot;&gt;
&lt;div&gt;
&lt;div data-key=&quot;6ed14b5930014453aa78e8a0edbfcf06&quot;&gt;
&lt;div data-block-content=&quot;6ed14b5930014453aa78e8a0edbfcf06&quot;&gt;
&lt;pre id=&quot;code_1665317802766&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Hibernate: select hashtags0_.board_board_id as board_bo3_2_1_, hashtags0_.id as id1_2_1_, hashtags0_.id as id1_2_0_, hashtags0_.board_board_id as board_bo3_2_0_, hashtags0_.name as name2_2_0_ from hash_tag hashtags0_ where hashtags0_.board_board_id in (select board0_.board_id from board board0_)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음과 같이 모든 로딩에 대해서 대응이 가능하고 성능최적화 부분에서 좋은 전략이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;QueryDSL의 QueryBuilder를 사용!&lt;/h3&gt;</description>
      <category>JPA</category>
      <category>fetch join</category>
      <category>JPA</category>
      <category>jpa n+1</category>
      <category>n+1</category>
      <author>큐범</author>
      <guid isPermaLink="true">https://kbcoding.tistory.com/101</guid>
      <comments>https://kbcoding.tistory.com/101#entry101comment</comments>
      <pubDate>Sun, 9 Oct 2022 21:23:16 +0900</pubDate>
    </item>
    <item>
      <title>프로젝트 회고 [플랩업]</title>
      <link>https://kbcoding.tistory.com/100</link>
      <description>&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;177&quot; data-origin-height=&quot;170&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d2e4Y6/btrNiNF1XmW/QjuBD42BjcW7Ch1KHPISg1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d2e4Y6/btrNiNF1XmW/QjuBD42BjcW7Ch1KHPISg1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d2e4Y6/btrNiNF1XmW/QjuBD42BjcW7Ch1KHPISg1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd2e4Y6%2FbtrNiNF1XmW%2FQjuBD42BjcW7Ch1KHPISg1%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;177&quot; height=&quot;170&quot; data-origin-width=&quot;177&quot; data-origin-height=&quot;170&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발기간 2022.06 ~ 2022.09 (3개월)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;플랫폼 Android&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;유저 (로그인, 수정, 보안) 개발, &lt;b&gt;CICD(Docker, DockerHub, Jenkins) 파이프라인 구축&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;infra 서버 구축, NCP이용한 SMS 문자 인증&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;패키지 구조 설정, Exception Handler구성&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 앱런칭은 방학기간에 사이드 프로젝트를 진행하고싶어 지인들로 구성하여 앱런칭을 진행하였다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 앱런칭에 회고를 작성한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;회고&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;첫째, 코드리뷰의 부재&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기술 발전에 큰 도움이 된 것은 &lt;b&gt;'집단지성&lt;/b&gt;'이라고 생각한다. 코드리뷰는 집단지성을 극대화 할 수 있다. 하지만, 각각의 팀원은 사이드 프로젝트이기에 투자할 수 있는 시간은 모두가 달랐다. 그렇기에 코드리뷰를 진행하게 되면 누군가에게 업무가 몰리는 현상이 일어나 코드리뷰를 진행하지 않았다. 하지만, 프로젝트가 끝나고 난 이후 다른 사람들의 코드를 보면 충분히 배울 점과 아쉬운 부분이 있었는데 이것들을 서로 짚어줬더라면 서로 &lt;b&gt;성장&lt;/b&gt;하는 프로젝트가 됐을텐데 아쉬움이 남는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;둘째, 모니터링과 이중화&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;실제 서비스를 한다고 생각했으면 아래와 같은 아키텍쳐를 가졌을까?&quot; 라는 생각에서 시작되었다. 실제 서비스와 사용 유저가 있었으면 단순히 2개의 서버로 CI서버와 CD서버로 구성하지 않았을 것이다. 개발 서버와 배포 서버를 분리하고 사용자들의 안정적인 사용이 가능하게 설계를 해야했는데 이중화 작업을 하지 못해서 DB만 이중화를 진행하고 서버는 이중화를 진행하지 않았다. 또한, 모니터링을 통해 몇 명의 유저가 어떠한 호출에 서버의 자원이 어느정도 사용되는지 모니터링 툴을 반영했어야 했다. 그 점에서 사이드 프로젝트를 단순히 토이 프로젝트 수준으로 내가 규제한 것은 아닌지? 생각하게 되며 다음 프로젝트에서는 &lt;b&gt;실제 서비스와 유저가 있다고 생각하고 설계&lt;/b&gt;를 하는 것이 나에게 많은 성장할 것 같다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;셋째, 실제 사용자 유치&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;총 3번의 앱 출시를 거치면서 실제 유저가 있던 적은 없다. 출시에 의의를 두고 개발하였지만 실제 사용자가 없는 것은 때로는 허망함을 줄 때도 종종 있었다. 실제 트래픽을 관리해보고 싶은 욕구도 있는데 막상 출시가 이루어지면 다들 개발에도 루즈해지는 것도 있으며 새로운 프로젝트를 시작하는 경우가 많았다. &lt;b&gt;이제는 실제 사용자를 유치해보고 싶다.&lt;/b&gt; 그렇다면 다시 서비스(앱)를 돌아보면 유저가 좋아하는 서비스인지 내가 성장을 위한 서비스인지 묻는다면 나는 내가 성장을 위한 서비스였다. 내가 넣고싶은 기술과 아키텍쳐를 넣었다. 그 부분에서 사용자 유치는 힘들지않았을까 라는 생각과 이제는 &lt;b&gt;내가 하고싶은 기술을 사용자가 원하는 서비스에 넣는 프로젝트&lt;/b&gt;를 진행하고 싶다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&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;h2 data-ke-size=&quot;size26&quot;&gt;개발환경&lt;/h2&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Language&lt;/td&gt;
&lt;td&gt;JAVA (JDK 1.8)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Infra&lt;/td&gt;
&lt;td&gt;AWS EC2(Ubuntu 20.04), RDS, S3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Framework&lt;/td&gt;
&lt;td&gt;Spring Framework 2.7.1, Hibernate&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DB&lt;/td&gt;
&lt;td&gt;MySQL&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Library, API&lt;/td&gt;
&lt;td&gt;JPA, Naver Cloud Platform, JWT&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CICD&lt;/td&gt;
&lt;td&gt;Jenkins, Docker, DockerHub&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Collaboration&lt;/td&gt;
&lt;td&gt;Slack, Swagger, Figma, Discord&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;CICD&lt;/h2&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-09-29 오전 12.28.33.png&quot; data-origin-width=&quot;1198&quot; data-origin-height=&quot;591&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/CKSsS/btrNk9g7RZV/xknQbaSKE6MtMWUXYwmRq1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/CKSsS/btrNk9g7RZV/xknQbaSKE6MtMWUXYwmRq1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/CKSsS/btrNk9g7RZV/xknQbaSKE6MtMWUXYwmRq1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCKSsS%2FbtrNk9g7RZV%2FxknQbaSKE6MtMWUXYwmRq1%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;1198&quot; height=&quot;591&quot; data-filename=&quot;스크린샷 2022-09-29 오전 12.28.33.png&quot; data-origin-width=&quot;1198&quot; data-origin-height=&quot;591&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;ERD&lt;/h2&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;960&quot; data-origin-height=&quot;443&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cz4CVv/btrNkC4NlTR/5U7kp9gd7vKTOhrULMNblK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cz4CVv/btrNkC4NlTR/5U7kp9gd7vKTOhrULMNblK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cz4CVv/btrNkC4NlTR/5U7kp9gd7vKTOhrULMNblK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcz4CVv%2FbtrNkC4NlTR%2F5U7kp9gd7vKTOhrULMNblK%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;960&quot; height=&quot;443&quot; data-origin-width=&quot;960&quot; data-origin-height=&quot;443&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;</description>
      <category>회고</category>
      <category>프로젝트 회고</category>
      <category>회고</category>
      <author>큐범</author>
      <guid isPermaLink="true">https://kbcoding.tistory.com/100</guid>
      <comments>https://kbcoding.tistory.com/100#entry100comment</comments>
      <pubDate>Thu, 29 Sep 2022 00:36:40 +0900</pubDate>
    </item>
    <item>
      <title>[Network] HTTP 상태코드</title>
      <link>https://kbcoding.tistory.com/99</link>
      <description>&lt;h2 data-ke-size=&quot;size18&quot;&gt;상태코드&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클라이언트가 보낸 요청의 처리 상태를 응답에서 알려주는 기능&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;1xx(Informational): 요청이 수신되어 처리 중을 의미한다.&lt;/li&gt;
&lt;li&gt;2xx(Successful): 요청 정상 처리한다.&lt;/li&gt;
&lt;li&gt;3xx(Refirection): 요청을 완료하려면 추가 행동이 필요하다.&lt;/li&gt;
&lt;li&gt;4xx(Client Error): 클라이언트 오류, 잘못된 문법등으로 서버가 요청을 수행할 수 없다.&lt;/li&gt;
&lt;li&gt;5xx(Server Error): 서버 오류, 서버가 정상 요청을 처리하지 못한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;미래에 새로운 상태 코드가 추가되어도 클라이언트를 변경하지 않아도 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;299 -&amp;gt; 2xx(Successful)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;451 -&amp;gt; 4xx(Client Error)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;599 -&amp;gt; 5xx(Server Error)&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;2xx(Sucessful) - 클라이언트의 요청을 성공적으로 처리&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;200 OK - 요청 성공&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-09-22 오후 3.49.01.png&quot; data-origin-width=&quot;1330&quot; data-origin-height=&quot;630&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bcarJ8/btrMNVjY0zX/yVUuoQwLeWWGScJVAPng4k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bcarJ8/btrMNVjY0zX/yVUuoQwLeWWGScJVAPng4k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bcarJ8/btrMNVjY0zX/yVUuoQwLeWWGScJVAPng4k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbcarJ8%2FbtrMNVjY0zX%2FyVUuoQwLeWWGScJVAPng4k%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;550&quot; height=&quot;261&quot; data-filename=&quot;스크린샷 2022-09-22 오후 3.49.01.png&quot; data-origin-width=&quot;1330&quot; data-origin-height=&quot;630&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;201 Created - 요청 성공해서 새로운 리소스가 생성된다.&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-09-22 오후 3.49.19.png&quot; data-origin-width=&quot;1556&quot; data-origin-height=&quot;766&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bSNsfp/btrMNVxuPW5/IeXlU9suJXy7tZY3OFO0ck/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bSNsfp/btrMNVxuPW5/IeXlU9suJXy7tZY3OFO0ck/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bSNsfp/btrMNVxuPW5/IeXlU9suJXy7tZY3OFO0ck/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbSNsfp%2FbtrMNVxuPW5%2FIeXlU9suJXy7tZY3OFO0ck%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;550&quot; height=&quot;271&quot; data-filename=&quot;스크린샷 2022-09-22 오후 3.49.19.png&quot; data-origin-width=&quot;1556&quot; data-origin-height=&quot;766&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;202 Acepted - 요청 접수되었으나 처리가 완료되지 않았다.&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;204 No Content - 서버가 요청을 성공적으로 수행했지만, 응답 페이로드 본문에 보낼 데이터가 없다.&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;save 버튼의 결과로 아무 내용이 없어도 된다.&lt;/li&gt;
&lt;li&gt;save 버튼을 눌러도 같은 화면을 유지해야 한다.&lt;/li&gt;
&lt;li&gt;결과 내용이 없어도 204메시지 만으로 성공을 인식할 수 있다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;205 Reset Content&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;206 Partial Content&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;207Multi-Status&lt;/h4&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;3xx (Redirection) - 요청을 완료하기 위해 유저 에이전트의 추가 조치 필요하다.&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;웹 브라우저는 3xx 응답의 결과에 Location 헤더가 있으면, Location 위치로 자동 이동(리다이렉트)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-09-22 오후 4.13.41.png&quot; data-origin-width=&quot;1308&quot; data-origin-height=&quot;682&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c4GuMg/btrMNUyFf3k/jpIsSpTGaPptwBBQAehb8k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c4GuMg/btrMNUyFf3k/jpIsSpTGaPptwBBQAehb8k/img.png&quot; data-alt=&quot;자동 리다이렉트의 흐름&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c4GuMg/btrMNUyFf3k/jpIsSpTGaPptwBBQAehb8k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc4GuMg%2FbtrMNUyFf3k%2FjpIsSpTGaPptwBBQAehb8k%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;550&quot; height=&quot;287&quot; data-filename=&quot;스크린샷 2022-09-22 오후 4.13.41.png&quot; data-origin-width=&quot;1308&quot; data-origin-height=&quot;682&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;예로는 JWT토큰만료에 의한 재인증 토큰 발급이 될 수 있다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;리다이렉션의 종류&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;영구 리다이렉션 - 특정 리소스의 URI가 영구적으로 이동한다.&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;301, 308&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ex) /members -&amp;gt; /users&amp;nbsp; ||&amp;nbsp; /event -&amp;gt; /new-event&lt;/li&gt;
&lt;li&gt;301 Moved Permanetly
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;리다이렉트시 요청 메서드가 GET으로 변하고, 본문이 제거될 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-09-22 오후 4.44.01.png&quot; data-origin-width=&quot;1300&quot; data-origin-height=&quot;730&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/K9SBr/btrMOntGXoN/GdHryeNwnvFcUkZzQ4bZK1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/K9SBr/btrMOntGXoN/GdHryeNwnvFcUkZzQ4bZK1/img.png&quot; data-alt=&quot;영구 리다렉션 - 301&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/K9SBr/btrMOntGXoN/GdHryeNwnvFcUkZzQ4bZK1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FK9SBr%2FbtrMOntGXoN%2FGdHryeNwnvFcUkZzQ4bZK1%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;550&quot; height=&quot;309&quot; data-filename=&quot;스크린샷 2022-09-22 오후 4.44.01.png&quot; data-origin-width=&quot;1300&quot; data-origin-height=&quot;730&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;영구 리다렉션 - 301&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;308 Permanent Redirect
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;301과 기능은 같음&lt;/li&gt;
&lt;li&gt;리다이렉트시 요청 메서드와 본문 유지(처음 POST를 보내면 리다이렉트도 POST 유지)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;position: absolute;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-09-22 오후 4.44.44.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;734&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ebi1mS/btrMKrYUf2t/AxospyHhZajuEM0g3ztWOK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ebi1mS/btrMKrYUf2t/AxospyHhZajuEM0g3ztWOK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ebi1mS/btrMKrYUf2t/AxospyHhZajuEM0g3ztWOK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Febi1mS%2FbtrMKrYUf2t%2FAxospyHhZajuEM0g3ztWOK%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;550&quot; height=&quot;315&quot; data-filename=&quot;스크린샷 2022-09-22 오후 4.44.44.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;734&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일시 리다이렉션 - 일시적인 변경&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;주문 완료 후 주문 내역 화면으로 이동한다.&lt;/li&gt;
&lt;li&gt;PRG: Post/Redirect/Get
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;PRG 이후 리다이렉트
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;URL이 이미 POST -&amp;gt; GET으로 리다이렉트 된다.&lt;/li&gt;
&lt;li&gt;새로 고침 해도 GET으로 결과 화면만 조회된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특수 리다이렉션 - 결과 대신 캐시를 사용&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size16&quot;&gt;3xx 목록&lt;/h3&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;300 Multiple Choices&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;301 Moved Permanetly&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;302 Found&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;303 See Other&lt;span&gt;&amp;nbsp;&lt;/span&gt;(since HTTP/1.1)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;304 Not Modified (RFC 7232)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;305 Use Proxy (since HTTP/1.1)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;306 Switch Proxy&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;307 Temporary Redirect (since HTTP/1.1)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;308 Permanent Redirect (RFC 7538)&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size16&quot;&gt;결론&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;307, 303을 권장하지만 현실적으로 이미 많은 애플리케이션 라이브러리들이 302를 기본값으로 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자동 리다이렉션시에 GET으로 변해도 되면 그냥 302를 사용해도 큰 문제는 없다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;304 Not Modified&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;캐시를 목적으로 사용한다.&lt;/li&gt;
&lt;li&gt;클라이언트에게 리소스가 수정되지 않았음을 알려준다. 따라서 클라이언트는 로컬PC에 저장된 캐시를 재사용한다.&lt;/li&gt;
&lt;li&gt;304 응답은 응답에 메시지 바디를 로컬 캐시를 사용해야 하므로 포함하면 안된다.&lt;/li&gt;
&lt;li&gt;조건부 GET, HEAD요청시 사용한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size16&quot;&gt;4xx - 클라이언트 오류&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;클라이언트의 요청에 잘못된 문법등으로 서버가 요청을 수행할 수 없다.&lt;/li&gt;
&lt;li&gt;오류의 원인이 클라이언트에 있다.&lt;/li&gt;
&lt;li&gt;클라이언트가 이미 잘못된 요청, 데이터를 보내고 있기 때문에, 똑같은 재시도가 실패한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;400 Bad Request - 클라이언트가 잘못된 요청을 해서 서버가 요청을 처리할 수 없다.&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;요청 구문, 메시지 등등 오류&lt;/li&gt;
&lt;li&gt;클라이언트는 요청 내용을 &lt;b&gt;다시 검토&lt;/b&gt;하고 보내야한다.&lt;/li&gt;
&lt;li&gt;요청 파라미터가 잘못되거나, API 스펙이 맞지 않을 때 400번 에러가 발생한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;401 Unauthorized - 클라이언트가 해당 리소스에 대한 인증이 필요하다.&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;인증이 되지 않는 경우에 발생.&lt;/li&gt;
&lt;li&gt;401 오류 발생시 응답에 WWW-Authenticate 헤더와 함께 인증 방법을 설명한다.&lt;/li&gt;
&lt;li&gt;Ex)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;인증(Authentication): 본인이 누구인지 확인, (로그인)&lt;/li&gt;
&lt;li&gt;인가(Authorization): 권한부여 (ADMIN 권한 처럼 특정 리소스에 접근할 수 있는 권한, 인증이 있어야 인가가 존재한다)&lt;/li&gt;
&lt;li&gt;오류 메시지가 Unauthorized이지만 인증이 되지 않는다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;403 Forbidden - 서버가 요청을 이해했지만 승인을 거부한다.&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;주로 인증 자격은 증명 되었지만, 접근 권한이 불충분한 경우에 사용한다.&lt;/li&gt;
&lt;li&gt;예를들어, 일반 회원이 관리자 페이지에 접근시.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;404 Not Found - 요청 리소스를 찾을 수 없다.&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;요청 리소스가 서버에 없다.&lt;/li&gt;
&lt;li&gt;또는 클라이언트가 권한이 부족한 리소스에 접근할 때 해당 리소스를 숨기고 싶을 경우에도 사용한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;5xx - 서버 오류&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서버 내부 문제로 오류 발생에 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서버에 문제가 있기 때문에 재시도 하면 성공할 수도 있다.(복구가 되거나 등등)&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;500&amp;nbsp; Internal Server Error - 서버 문제로 오류 발생, 애매하면 500 오류&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;서버 내부 문제로 오류 발생에 사용된다.&lt;/li&gt;
&lt;li&gt;애매한 경우에 500 오류&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;503 Service Unavailable - 서비스 이용 불가&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;서버 일시적인 과부화 또는 예정된 작업으로 잠시 요청을 처리할 수 없는 경우에 사용&lt;/li&gt;
&lt;li&gt;Retry-After&amp;nbsp; 헤더 필드로 얼마뒤에 복구되는지 보낼 수도 있다.&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Network</category>
      <category>200 error</category>
      <category>300 error</category>
      <category>400 error</category>
      <category>404</category>
      <category>500 Error</category>
      <category>HTTP</category>
      <category>http status</category>
      <category>Network</category>
      <category>상태코드</category>
      <author>큐범</author>
      <guid isPermaLink="true">https://kbcoding.tistory.com/99</guid>
      <comments>https://kbcoding.tistory.com/99#entry99comment</comments>
      <pubDate>Thu, 22 Sep 2022 16:45:03 +0900</pubDate>
    </item>
    <item>
      <title>[Network] HTTP 메서드 활용</title>
      <link>https://kbcoding.tistory.com/98</link>
      <description>&lt;h2 data-ke-size=&quot;size23&quot;&gt;클라이언트에서 서버로 데이터 전송&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;데이터 전달 방식은 크게 2가지이다.&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size23&quot;&gt;1. 쿼리 파라미터를 통한 데이터 전송&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;GET, 정렬 필터로 주로 검색어에 사용된다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2.&amp;nbsp; 메시지 바디를 통한 데이터 전송&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;POST, PUT, PATCH&lt;/li&gt;
&lt;li&gt;회원 가입, 상품 주문, 리소스 등록, 리소스 변경&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4가지 상황&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;1.&amp;nbsp; 정적 데이터 조회&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이미지, 정적 텍스트 문서&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;2. 동적 데이터 조회&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;주로 검색, 게시판 목록에서 정렬 필터로 쓰인다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;3. HTML FORM을 통한 데이터 전송&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;회원 가입, 상품 주문, 데이터 변경에 쓰인다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;4. HTTP API를 통한 데이터 전송&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;회원가입, 상품 주문, 데이터 변경&lt;/li&gt;
&lt;li&gt;서버 to 서버, 앱 클라이언트, 웹 클라이언트(Ajax)&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;정적 데이터 조회의 경우(쿼리 파라미터 미사용)&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-09-16 오후 6.47.13.png&quot; data-origin-width=&quot;1392&quot; data-origin-height=&quot;546&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/3LYPt/btrMkt80DN3/BFnc2FmNOjpGYXBfTxaZXK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/3LYPt/btrMkt80DN3/BFnc2FmNOjpGYXBfTxaZXK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/3LYPt/btrMkt80DN3/BFnc2FmNOjpGYXBfTxaZXK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F3LYPt%2FbtrMkt80DN3%2FBFnc2FmNOjpGYXBfTxaZXK%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;550&quot; height=&quot;216&quot; data-filename=&quot;스크린샷 2022-09-16 오후 6.47.13.png&quot; data-origin-width=&quot;1392&quot; data-origin-height=&quot;546&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이미지, 정적 텍스트 문서&lt;/li&gt;
&lt;li&gt;조회는 GET 사용&lt;/li&gt;
&lt;li&gt;정적 데이터는 일반적으로 쿼리 파라미터 없이 리소스 경로로 단순하게 조회 가능하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;동적 데이터 조회의 경우(쿼리 파라미터 사용)&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-09-16 오후 6.47.59.png&quot; data-origin-width=&quot;1374&quot; data-origin-height=&quot;604&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bul8RR/btrMiQdLqMH/eI50wmcagd1USKnuUKP5Dk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bul8RR/btrMiQdLqMH/eI50wmcagd1USKnuUKP5Dk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bul8RR/btrMiQdLqMH/eI50wmcagd1USKnuUKP5Dk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbul8RR%2FbtrMiQdLqMH%2FeI50wmcagd1USKnuUKP5Dk%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;550&quot; height=&quot;242&quot; data-filename=&quot;스크린샷 2022-09-16 오후 6.47.59.png&quot; data-origin-width=&quot;1374&quot; data-origin-height=&quot;604&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;주로 검색, 게시판 목록에서 정렬 필터(검색어)&lt;/li&gt;
&lt;li&gt;조회 조건을 줄여주는 필터, 조회 결과를 정렬하는 정렬 조건에 주로 사용한다.&lt;/li&gt;
&lt;li&gt;조회는 GET 메서드를 사용한다.&lt;/li&gt;
&lt;li&gt;GET은 쿼리 파라미터 사용해서 데이터를 전달한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;HTML Form 데이터 전송&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;POST 전송 저장 과정&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-09-16 오후 6.51.36.png&quot; data-origin-width=&quot;1470&quot; data-origin-height=&quot;568&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cfqb4V/btrMkR2Pm97/PcCKXRKiT4HpJjzDYJbBJK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cfqb4V/btrMkR2Pm97/PcCKXRKiT4HpJjzDYJbBJK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cfqb4V/btrMkR2Pm97/PcCKXRKiT4HpJjzDYJbBJK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcfqb4V%2FbtrMkR2Pm97%2FPcCKXRKiT4HpJjzDYJbBJK%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;550&quot; height=&quot;213&quot; data-filename=&quot;스크린샷 2022-09-16 오후 6.51.36.png&quot; data-origin-width=&quot;1470&quot; data-origin-height=&quot;568&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;GET 전송 저장 과정 - 리소스 변경이 발생하는 곳에 사용하면 안된다.&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-09-16 오후 6.52.03.png&quot; data-origin-width=&quot;1434&quot; data-origin-height=&quot;552&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/JiyfO/btrMi4JE21C/t9K5DV3M1tBIWKmhaPgNQk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/JiyfO/btrMi4JE21C/t9K5DV3M1tBIWKmhaPgNQk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/JiyfO/btrMi4JE21C/t9K5DV3M1tBIWKmhaPgNQk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJiyfO%2FbtrMi4JE21C%2Ft9K5DV3M1tBIWKmhaPgNQk%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;550&quot; height=&quot;212&quot; data-filename=&quot;스크린샷 2022-09-16 오후 6.52.03.png&quot; data-origin-width=&quot;1434&quot; data-origin-height=&quot;552&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;multipart/form-data&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-09-16 오후 6.55.26.png&quot; data-origin-width=&quot;1444&quot; data-origin-height=&quot;582&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ux3ZT/btrMkf4dS8U/WQ8z5swkfkxpJOTNSMDIbk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ux3ZT/btrMkf4dS8U/WQ8z5swkfkxpJOTNSMDIbk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ux3ZT/btrMkf4dS8U/WQ8z5swkfkxpJOTNSMDIbk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fux3ZT%2FbtrMkf4dS8U%2FWQ8z5swkfkxpJOTNSMDIbk%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;550&quot; height=&quot;222&quot; data-filename=&quot;스크린샷 2022-09-16 오후 6.55.26.png&quot; data-origin-width=&quot;1444&quot; data-origin-height=&quot;582&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;HTML Form 데이터 전송&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;HTML Form submi시 POST 전송 - 데이터 변경에 관한 것들이 해당한다.&lt;/li&gt;
&lt;li&gt;Content-Type: application/x-www-form-urlencoded 사용한다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;form의 내용을 메시지 바디를 통해서 전송한다. (key = value, 쿼리 파라미터 형식이다.)&lt;/li&gt;
&lt;li&gt;전송 데이터를 url encoding 처리한다. ex) 김abc -&amp;gt; %EA%B9%80abc&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;HTML Form은 GET 전송도 가능&lt;/li&gt;
&lt;li&gt;Content-Type: multipart/form-data
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;파일 업로드 같은 바이너리 데이터 전송시 사용한다.&lt;/li&gt;
&lt;li&gt;다른 종류의 여러 파일과 폼의 내용을 함께 전송이 가능하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;HTML Form 전송은 GET, POST만 지원한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size16&quot;&gt;HTTP API 설계 예시&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HTTP API - 컬렉션&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;POST 기반 등록&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HTTP API - 스토어&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;PUT 기반 등록&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HTML FORM 사용&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;GET, POST만 지원&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;API 설계 - POST 기반 등록&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;회원 &lt;/span&gt;&lt;span&gt;목록 &lt;/span&gt;&lt;span&gt;/members &lt;/span&gt;&lt;span&gt;-&amp;gt; GET&lt;br /&gt;&lt;/span&gt;&lt;span&gt;회원 &lt;/span&gt;&lt;span&gt;등록 &lt;/span&gt;&lt;span&gt;/members &lt;/span&gt;&lt;span&gt;-&amp;gt; POST&lt;br /&gt;&lt;/span&gt;&lt;span&gt;회원 &lt;/span&gt;&lt;span&gt;조회 &lt;/span&gt;&lt;span&gt;/members/{id} &lt;/span&gt;&lt;span&gt;-&amp;gt; GET&lt;br /&gt;&lt;/span&gt;&lt;span&gt;회원 &lt;/span&gt;&lt;span&gt;수정 &lt;/span&gt;&lt;span&gt;/members/{id} &lt;/span&gt;&lt;span&gt;-&amp;gt; PATCH, PUT, POST &lt;/span&gt;&lt;span&gt;회원 &lt;/span&gt;&lt;span&gt;삭제 &lt;/span&gt;&lt;span&gt;/members/{id} &lt;/span&gt;&lt;span&gt;-&amp;gt; DELETE&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;POST 신규 자원 등록의 특징&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span&gt;클라이언트는 등록될 리소스의 URI를 모른다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;회원 등록 /members -&amp;gt; POST&lt;/li&gt;
&lt;li&gt;POST /members&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;서버가 새로 등록된 리소스 URI를 생성해준다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span&gt;컬렉션(Collection)&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;서버가 관리하는 리소스 디렉토리&lt;/li&gt;
&lt;li&gt;서버가 리소스의 URI를 생성하고 관리한다.&lt;/li&gt;
&lt;li&gt;여기서 컬렉션은 /members이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;API 설계 - PUT 기반 등록&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;파일 &lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;목록 &lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;/files &lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;-&amp;gt; GET&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;파일 &lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;조회 &lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;/files/{filename} &lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;-&amp;gt; GET &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;파일 &lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;등록 &lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;/files/{filename} &lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;-&amp;gt; PUT&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;파일 &lt;/span&gt;&lt;span&gt;삭제 &lt;/span&gt;&lt;span&gt;/files/{filename} &lt;/span&gt;&lt;span&gt;-&amp;gt; DELETE &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;파일 &lt;/span&gt;&lt;span&gt;대량 등록 &lt;/span&gt;&lt;span&gt;/files &lt;/span&gt;&lt;span&gt;-&amp;gt; POST &lt;/span&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;PUT 신규 자원 등록 특징&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클라이언트가 리소스 URI를 알고 있어야 한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;파일 등록 /file/{filename} -&amp;gt; PUT&lt;/li&gt;
&lt;li&gt;PUT /files/kbcoding.jpg&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클라이언트가 직접 리소스의 URI를 지정한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스토어(Store)&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;클라이언트가 관리하는 리소스 저장소&lt;/li&gt;
&lt;li&gt;클라이언트가 리소스의 URI를 알고 관리한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;HTML FORM 사용할 경우&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HTML FORM은 GET, POST만 지원한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AJAX 같은 기술을 사용해서 해결 가능 하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;GET, POST만 지원하므로 제약이 존재하다.&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;HTML FORM 설계 예시&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;회원&amp;nbsp;목록 /members &lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;-&amp;gt; GET&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt; &lt;span&gt;회원&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;등록 폼 &lt;/span&gt;&lt;span&gt;/members/new &lt;/span&gt;&lt;span&gt;-&amp;gt; GET &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;span&gt;회원&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;등록 /members/new, /members &lt;/span&gt;&lt;span&gt;-&amp;gt; POST &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;span&gt;회원&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;조회 /members/{id} &lt;/span&gt;&lt;span&gt;-&amp;gt; GET&lt;br /&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;회원&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;수정 폼 &lt;/span&gt;&lt;span&gt;/members/{id}/edit &lt;/span&gt;&lt;span&gt;-&amp;gt; GET &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;span&gt;회원&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;수정 /members/{id}/edit, /members/{id} &lt;/span&gt;&lt;span&gt;-&amp;gt; POST &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;span&gt;회원&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;삭제 /members/{id}/delete &lt;/span&gt;&lt;span&gt;-&amp;gt; POST &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;Reference.&lt;/p&gt;
&lt;div&gt;
&lt;figure id=&quot;og_1663325130759&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;모든 개발자를 위한 HTTP 웹 기본 지식 - 인프런 | 강의&quot; data-og-description=&quot;실무에 꼭 필요한 HTTP 핵심 기능과 올바른 HTTP API 설계 방법을 학습합니다., - 강의 소개 | 인프런...&quot; data-og-host=&quot;www.inflearn.com&quot; data-og-source-url=&quot;https://www.inflearn.com/course/http-%EC%9B%B9-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC/dashboard&quot; data-og-url=&quot;https://www.inflearn.com/course/http-%EC%9B%B9-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/p2uCj/hyPHlL8rnP/FSHVAfR7vB6LuDscYKm2L0/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/cup7EJ/hyPHuPQztK/8dojym58kWgVGYwtbk2PIK/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/bz75cR/hyPF0CPhif/43fiyMsmSdrR0alrfh5msk/img.jpg?width=1200&amp;amp;height=666&amp;amp;face=0_0_1200_666&quot;&gt;&lt;a href=&quot;https://www.inflearn.com/course/http-%EC%9B%B9-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC/dashboard&quot; data-source-url=&quot;https://www.inflearn.com/course/http-%EC%9B%B9-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC/dashboard&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/p2uCj/hyPHlL8rnP/FSHVAfR7vB6LuDscYKm2L0/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/cup7EJ/hyPHuPQztK/8dojym58kWgVGYwtbk2PIK/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/bz75cR/hyPF0CPhif/43fiyMsmSdrR0alrfh5msk/img.jpg?width=1200&amp;amp;height=666&amp;amp;face=0_0_1200_666');&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;모든 개발자를 위한 HTTP 웹 기본 지식 - 인프런 | 강의&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;실무에 꼭 필요한 HTTP 핵심 기능과 올바른 HTTP API 설계 방법을 학습합니다., - 강의 소개 | 인프런...&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.inflearn.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;</description>
      <category>Network</category>
      <category>Get</category>
      <category>HTML</category>
      <category>HTTP</category>
      <category>HTTP Method</category>
      <category>http method 종류</category>
      <category>Network</category>
      <category>Post</category>
      <author>큐범</author>
      <guid isPermaLink="true">https://kbcoding.tistory.com/98</guid>
      <comments>https://kbcoding.tistory.com/98#entry98comment</comments>
      <pubDate>Sat, 17 Sep 2022 20:46:20 +0900</pubDate>
    </item>
    <item>
      <title>[Network] HTTP Method(GET, POST, PUT, PATCH, DELETE)</title>
      <link>https://kbcoding.tistory.com/97</link>
      <description>&lt;h3 data-ke-size=&quot;size16&quot;&gt;URI 설계의 중요한 것은 리소스 식별&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;API URI(Uniform Resource Identifier)&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;리소스의 의미
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;회원을 등록하고 수정하고 조회하는 것은 리소스가 아니다.&lt;/li&gt;
&lt;li&gt;예를들어 자원을 캐라 -&amp;gt; 자원이 리소스이다.&lt;/li&gt;
&lt;li&gt;회원이라는 개념 자체가 바로 리소스인 것이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;회원이라는 리소스만 식별하면 된다. -&amp;gt; 회원 리소스를 URI에 매핑하면 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;좋지 못한 URI설계&lt;br /&gt;- 회원 목록 조회 /read-member-list &lt;br /&gt;- 회원 조회 /read-member-by-id &lt;br /&gt;- 회원 등록 /create-member &lt;br /&gt;- 회원 수정 /update-member &lt;br /&gt;- 회원 삭제 /delete-member&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;좋은 URI 설계&lt;br /&gt;- 회원 목록 조회 /members &lt;br /&gt;- 회원 조회 /members/{id} &lt;br /&gt;- 회원 등록 /members/{id} &lt;br /&gt;- 회원 수정 /members/{id} &lt;br /&gt;- 회원 삭제 /members/{id}&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Post. 계층 구조상 상위 컬렉션으로 보고 복수 단어 사용을 권장한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;리소스와 행위를 분리&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;URI는 리소스만 식별하고 리소스와 해당 리소스를 대상으로 하는 행위를 분리하는 것이 옳다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 리소스: 회원&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 행위: 조회, 등록, 삭제, 변경&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 좋은 URI 설계를 보면 구분하는 방법이 의아할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 구분 짓는 것은&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;HTTP 메서드&lt;/b&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;HTTP 메서드의 종류&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;GET: 리소스 조회한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;POST: 요청 데이터 처리, 주로 등록에 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PUT: 리소스를 대체, 해당 리소스가 없으면 생성한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PATCH: 리소스 부분 변경한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DELETE: 리소스 삭제한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;기타 메서드&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HEAD: GET과 동일하지만 메시지 부분을 제외하고, 상태 줄과 헤더만 반환한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OPTIONS: 대상 리소스에 대한 통신 가능 옵션(메서드)을 설명(주로 CORS에서 사용)한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CONNECT: 대상 자원으로 식별되는 서버에 대한 터널을 설정한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;RACE: 대상 리소스에 대한 경로를 따라 메시지 루프백 테스트를 수행한다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;GET&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock floatRight&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-09-13 오전 1.41.31.png&quot; data-origin-width=&quot;436&quot; data-origin-height=&quot;121&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cfbklt/btrL1zuCk33/JaJQdkN4VAPfXWuAgYSuz0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cfbklt/btrL1zuCk33/JaJQdkN4VAPfXWuAgYSuz0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cfbklt/btrL1zuCk33/JaJQdkN4VAPfXWuAgYSuz0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcfbklt%2FbtrL1zuCk33%2FJaJQdkN4VAPfXWuAgYSuz0%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;236&quot; height=&quot;65&quot; data-filename=&quot;스크린샷 2022-09-13 오전 1.41.31.png&quot; data-origin-width=&quot;436&quot; data-origin-height=&quot;121&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리소스 조회한다.&lt;/p&gt;
&lt;p style=&quot;position: absolute;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;position: absolute;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서버에 전달하고 싶은 데이터는 query(쿼리 파라미터, 쿼리 스트링)를 통해서 전달한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메시지 바디를 사용해서 데이터를 전달할 수 있지만, 지원하지 않는 곳이 많아서 권장하지 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size16&quot;&gt;GET 동작 과정&lt;/h3&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 메시지 전달&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-09-13 오전 1.43.47.png&quot; data-origin-width=&quot;750&quot; data-origin-height=&quot;327&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pNgqu/btrL0UeyrXM/t8XaIm3ECy0exr3NPWKw9K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pNgqu/btrL0UeyrXM/t8XaIm3ECy0exr3NPWKw9K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pNgqu/btrL0UeyrXM/t8XaIm3ECy0exr3NPWKw9K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpNgqu%2FbtrL0UeyrXM%2Ft8XaIm3ECy0exr3NPWKw9K%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;750&quot; height=&quot;327&quot; data-filename=&quot;스크린샷 2022-09-13 오전 1.43.47.png&quot; data-origin-width=&quot;750&quot; data-origin-height=&quot;327&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;2. 서버 도착&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-09-13 오전 1.44.03.png&quot; data-origin-width=&quot;734&quot; data-origin-height=&quot;313&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lfjV6/btrLTU7CwdI/Rt8PapJvI4BmXvzTPxJd10/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lfjV6/btrLTU7CwdI/Rt8PapJvI4BmXvzTPxJd10/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lfjV6/btrLTU7CwdI/Rt8PapJvI4BmXvzTPxJd10/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlfjV6%2FbtrLTU7CwdI%2FRt8PapJvI4BmXvzTPxJd10%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;734&quot; height=&quot;313&quot; data-filename=&quot;스크린샷 2022-09-13 오전 1.44.03.png&quot; data-origin-width=&quot;734&quot; data-origin-height=&quot;313&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;3. 응답 데이터&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-09-13 오전 1.44.14.png&quot; data-origin-width=&quot;691&quot; data-origin-height=&quot;326&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bCFQjO/btrLPcVBUNx/DDbV0c3Yol8jwneh9BYt3k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bCFQjO/btrLPcVBUNx/DDbV0c3Yol8jwneh9BYt3k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bCFQjO/btrLPcVBUNx/DDbV0c3Yol8jwneh9BYt3k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbCFQjO%2FbtrLPcVBUNx%2FDDbV0c3Yol8jwneh9BYt3k%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;691&quot; height=&quot;326&quot; data-filename=&quot;스크린샷 2022-09-13 오전 1.44.14.png&quot; data-origin-width=&quot;691&quot; data-origin-height=&quot;326&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock floatRight&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-09-13 오전 1.45.02.png&quot; data-origin-width=&quot;314&quot; data-origin-height=&quot;145&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/di5WPH/btrLNqGM13t/QMMOgRXnkJCn7yRjU4bE0K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/di5WPH/btrLNqGM13t/QMMOgRXnkJCn7yRjU4bE0K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/di5WPH/btrLNqGM13t/QMMOgRXnkJCn7yRjU4bE0K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdi5WPH%2FbtrLNqGM13t%2FQMMOgRXnkJCn7yRjU4bE0K%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;314&quot; height=&quot;145&quot; data-filename=&quot;스크린샷 2022-09-13 오전 1.45.02.png&quot; data-origin-width=&quot;314&quot; data-origin-height=&quot;145&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;POST&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요청 데이터를 처리한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메시지 바디를 통해 서버로 여청 데이터를 전달한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서버는 요청 데이터를 처리하고 메시지 바디를 통해 들어온 테이터를 처리하는 모든 기능을 수행한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주로 전달된 데이터로 신규 리소스 등록, 프로세스 처리에 사용된다.&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;POST 동작 과정&lt;/h3&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 메시지 전달&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-09-13 오전 1.53.53.png&quot; data-origin-width=&quot;724&quot; data-origin-height=&quot;314&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Psx94/btrL1zaj08I/maPjKxiY712vcWLkyOy2H1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Psx94/btrL1zaj08I/maPjKxiY712vcWLkyOy2H1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Psx94/btrL1zaj08I/maPjKxiY712vcWLkyOy2H1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FPsx94%2FbtrL1zaj08I%2FmaPjKxiY712vcWLkyOy2H1%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;314&quot; data-filename=&quot;스크린샷 2022-09-13 오전 1.53.53.png&quot; data-origin-width=&quot;724&quot; data-origin-height=&quot;314&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;2. 신규 리소스 생성&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-09-13 오전 1.54.12.png&quot; data-origin-width=&quot;723&quot; data-origin-height=&quot;300&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/erkDSh/btrLYjMA4Tt/MZ7GXqHOfXXzVHfdmFYWA0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/erkDSh/btrLYjMA4Tt/MZ7GXqHOfXXzVHfdmFYWA0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/erkDSh/btrLYjMA4Tt/MZ7GXqHOfXXzVHfdmFYWA0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FerkDSh%2FbtrLYjMA4Tt%2FMZ7GXqHOfXXzVHfdmFYWA0%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;723&quot; height=&quot;300&quot; data-filename=&quot;스크린샷 2022-09-13 오전 1.54.12.png&quot; data-origin-width=&quot;723&quot; data-origin-height=&quot;300&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;3. 응답 데이터&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-09-13 오전 1.54.29.png&quot; data-origin-width=&quot;670&quot; data-origin-height=&quot;327&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cJCCf6/btrLNqNzgTY/vpnFtvFbMukSb1j148I2S0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cJCCf6/btrLNqNzgTY/vpnFtvFbMukSb1j148I2S0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cJCCf6/btrLNqNzgTY/vpnFtvFbMukSb1j148I2S0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcJCCf6%2FbtrLNqNzgTY%2FvpnFtvFbMukSb1j148I2S0%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;670&quot; height=&quot;327&quot; data-filename=&quot;스크린샷 2022-09-13 오전 1.54.29.png&quot; data-origin-width=&quot;670&quot; data-origin-height=&quot;327&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;POST에서 요청 데이터를 처리한다는 뜻은&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공식 스펙: POST 메서드는 대상 리소스가 리소스의 고유 한 의미 체계에 따라 요청에 포함 된 표현을 처리하도록 요청합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 리소스 URI에 POST 요청이 오면 요청 데이터를 어떻게 처리할지 리소스마다 따로 정해야 함 -&amp;gt; &lt;b&gt;정해진 것이 없음&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;POST 총정리&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 새 리소스 생성(등록)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- 서버가 아직 식별하지 않은 새 리소스를 생성한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 요청 데이터를 처리&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- 단순히 데이터를 생성하거나, 변경하는 것을 넘어서 프로세스를 처리해야하는 경우.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 예를들어, 주문에서 결제완료 -&amp;gt; 배달시작 -&amp;gt; 배달완료 처럼 단순히 값 변경을 넘어 프로세스의 상태가 변경되는 경우&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- POST의 결과로 새로운 리소스가 생성되지 않을 수도 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 예를들어, POST /orders/{orderId}/start-delivery (컨트롤 URI)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;3. 다른 메서드로 처리하기 애매한 경우&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 예를들어, JSON으로 조회 데이터를 넘겨야 하는데, GET 메서드를 사용하기 어려운 경우&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 애매한 것들은 POST로 처리하자.&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;size16&quot;&gt;PUT&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리소스를 대체&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; - 리소스가 있으면 대체&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; - 리소스가 없으면 생성&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; - 리소스를 덮어버린다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;클라이언트가 리소스를 식별&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; - 클라이언트가 리소스 위치를 알고 URI 지정한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; - 이 점이 POST와 다르다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size26&quot;&gt;PUT 동작 과정&lt;/h3&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리소스가 있는경우 1&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-09-13 오전 2.06.50.png&quot; data-origin-width=&quot;748&quot; data-origin-height=&quot;324&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vpUij/btrLStvGKp6/6iQT4VBxiTXkVmpLQmVQ7k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vpUij/btrLStvGKp6/6iQT4VBxiTXkVmpLQmVQ7k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vpUij/btrLStvGKp6/6iQT4VBxiTXkVmpLQmVQ7k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FvpUij%2FbtrLStvGKp6%2F6iQT4VBxiTXkVmpLQmVQ7k%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;748&quot; height=&quot;324&quot; data-filename=&quot;스크린샷 2022-09-13 오전 2.06.50.png&quot; data-origin-width=&quot;748&quot; data-origin-height=&quot;324&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;리소스가 있는 경우 2&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-09-13 오전 2.08.01.png&quot; data-origin-width=&quot;670&quot; data-origin-height=&quot;326&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bfEoKK/btrLR70wYHh/zxmKqSzwm8G4jMArNvzg30/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bfEoKK/btrLR70wYHh/zxmKqSzwm8G4jMArNvzg30/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bfEoKK/btrLR70wYHh/zxmKqSzwm8G4jMArNvzg30/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbfEoKK%2FbtrLR70wYHh%2FzxmKqSzwm8G4jMArNvzg30%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;670&quot; height=&quot;326&quot; data-filename=&quot;스크린샷 2022-09-13 오전 2.08.01.png&quot; data-origin-width=&quot;670&quot; data-origin-height=&quot;326&quot;/&gt;&lt;/span&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;리소스가 없는 경우 1&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-09-13 오전 2.08.16.png&quot; data-origin-width=&quot;646&quot; data-origin-height=&quot;322&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/byWMuv/btrL1zOVpDJ/roHqcRsHbU76exxGWUW1H1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/byWMuv/btrL1zOVpDJ/roHqcRsHbU76exxGWUW1H1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/byWMuv/btrL1zOVpDJ/roHqcRsHbU76exxGWUW1H1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbyWMuv%2FbtrL1zOVpDJ%2FroHqcRsHbU76exxGWUW1H1%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;322&quot; data-filename=&quot;스크린샷 2022-09-13 오전 2.08.16.png&quot; data-origin-width=&quot;646&quot; data-origin-height=&quot;322&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;리소스가 없는 경우 2&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-09-13 오전 2.08.29.png&quot; data-origin-width=&quot;694&quot; data-origin-height=&quot;314&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/8okZC/btrLXOMFHtY/T9PHfiZgKkrM2izf151yL0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/8okZC/btrLXOMFHtY/T9PHfiZgKkrM2izf151yL0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/8okZC/btrLXOMFHtY/T9PHfiZgKkrM2izf151yL0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F8okZC%2FbtrLXOMFHtY%2FT9PHfiZgKkrM2izf151yL0%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;314&quot; data-filename=&quot;스크린샷 2022-09-13 오전 2.08.29.png&quot; data-origin-width=&quot;694&quot; data-origin-height=&quot;314&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;리소스를 완전히 대체한다 1&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-09-13 오전 2.08.54.png&quot; data-origin-width=&quot;744&quot; data-origin-height=&quot;302&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lCQww/btrLStCsbAI/eMpbJ528RbGF5WHhkJcTkK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lCQww/btrLStCsbAI/eMpbJ528RbGF5WHhkJcTkK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lCQww/btrLStCsbAI/eMpbJ528RbGF5WHhkJcTkK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlCQww%2FbtrLStCsbAI%2FeMpbJ528RbGF5WHhkJcTkK%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;744&quot; height=&quot;302&quot; data-filename=&quot;스크린샷 2022-09-13 오전 2.08.54.png&quot; data-origin-width=&quot;744&quot; data-origin-height=&quot;302&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;리소스를 완전히 대체한다 2&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-09-13 오전 2.09.02.png&quot; data-origin-width=&quot;696&quot; data-origin-height=&quot;313&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kDrrd/btrLZPYNkl0/uL2Q6COykoitBGXMeAbdUK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kDrrd/btrLZPYNkl0/uL2Q6COykoitBGXMeAbdUK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kDrrd/btrLZPYNkl0/uL2Q6COykoitBGXMeAbdUK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkDrrd%2FbtrLZPYNkl0%2FuL2Q6COykoitBGXMeAbdUK%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;696&quot; height=&quot;313&quot; data-filename=&quot;스크린샷 2022-09-13 오전 2.09.02.png&quot; data-origin-width=&quot;696&quot; data-origin-height=&quot;313&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size16&quot;&gt;PATCH&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리소스를 부분 변경한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;PATCH 동작 과정&lt;/h3&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리소스 부분 변경1&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-09-13 오전 2.10.27.png&quot; data-origin-width=&quot;748&quot; data-origin-height=&quot;351&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bzTT7C/btrLYkrctwg/pYA4HXdfqaCWU6c4sopfKK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bzTT7C/btrLYkrctwg/pYA4HXdfqaCWU6c4sopfKK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bzTT7C/btrLYkrctwg/pYA4HXdfqaCWU6c4sopfKK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzTT7C%2FbtrLYkrctwg%2FpYA4HXdfqaCWU6c4sopfKK%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;748&quot; height=&quot;351&quot; data-filename=&quot;스크린샷 2022-09-13 오전 2.10.27.png&quot; data-origin-width=&quot;748&quot; data-origin-height=&quot;351&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;리소스 부분 변경2&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-09-13 오전 2.10.52.png&quot; data-origin-width=&quot;686&quot; data-origin-height=&quot;313&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dsMnkN/btrLQohbSTr/pD67P2nTOypiwsvHD7wffk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dsMnkN/btrLQohbSTr/pD67P2nTOypiwsvHD7wffk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dsMnkN/btrLQohbSTr/pD67P2nTOypiwsvHD7wffk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdsMnkN%2FbtrLQohbSTr%2FpD67P2nTOypiwsvHD7wffk%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;313&quot; data-filename=&quot;스크린샷 2022-09-13 오전 2.10.52.png&quot; data-origin-width=&quot;686&quot; data-origin-height=&quot;313&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size16&quot;&gt;DELETE&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리소스를 제거한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;DELETE 동작 과정&lt;/h3&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리소스 제거 1&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-09-13 오전 2.11.28.png&quot; data-origin-width=&quot;728&quot; data-origin-height=&quot;305&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xMfw7/btrLTDdQHLc/96AzH8ESv3rMzhEyJ0T650/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xMfw7/btrLTDdQHLc/96AzH8ESv3rMzhEyJ0T650/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xMfw7/btrLTDdQHLc/96AzH8ESv3rMzhEyJ0T650/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxMfw7%2FbtrLTDdQHLc%2F96AzH8ESv3rMzhEyJ0T650%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;728&quot; height=&quot;305&quot; data-filename=&quot;스크린샷 2022-09-13 오전 2.11.28.png&quot; data-origin-width=&quot;728&quot; data-origin-height=&quot;305&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;리소스 제거 2&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-09-13 오전 2.11.46.png&quot; data-origin-width=&quot;655&quot; data-origin-height=&quot;287&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/XFiqU/btrLOnCZpba/6zynLXqw0b3vClU6K32f51/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/XFiqU/btrLOnCZpba/6zynLXqw0b3vClU6K32f51/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/XFiqU/btrLOnCZpba/6zynLXqw0b3vClU6K32f51/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FXFiqU%2FbtrLOnCZpba%2F6zynLXqw0b3vClU6K32f51%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;655&quot; height=&quot;287&quot; data-filename=&quot;스크린샷 2022-09-13 오전 2.11.46.png&quot; data-origin-width=&quot;655&quot; data-origin-height=&quot;287&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size16&quot;&gt;HTTP 메서드 속성&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;안전(Safe Methods)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;멱등(Idempotent Methods)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;캐시가능(Cacheable Methods)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-09-13 오후 8.39.54.png&quot; data-origin-width=&quot;1300&quot; data-origin-height=&quot;518&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/82jCj/btrL3zifo0d/wvWSsDBlNddtZZwlOEMpr0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/82jCj/btrL3zifo0d/wvWSsDBlNddtZZwlOEMpr0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/82jCj/btrL3zifo0d/wvWSsDBlNddtZZwlOEMpr0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F82jCj%2FbtrL3zifo0d%2FwvWSsDBlNddtZZwlOEMpr0%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;550&quot; height=&quot;219&quot; data-filename=&quot;스크린샷 2022-09-13 오후 8.39.54.png&quot; data-origin-width=&quot;1300&quot; data-origin-height=&quot;518&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size16&quot;&gt;안전 - 호출해도 리소스를 변경하지 않는다.&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;멱등(Idempotent)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;f(f(x)) = f(x)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한 번 호출하든 두 번 호출하든 n번 호출하든 결과가 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;멱등 메서드&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;GET: 한 번 조회하든, 두 번 조회하든 같은 결과가 조회된다.&lt;/li&gt;
&lt;li&gt;PUT: 결과를 대체한다. 따라서 같은 요청을 여러번 해도 최종 결과는 같다.&lt;/li&gt;
&lt;li&gt;DELETE: 결과를 삭제한다. 같은 요청을 여러번 해도 삭제된 결과는 똑같다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;POST&lt;/b&gt;: 멱등이 아니다! 두 번 호출하면 같은 결제가 중복해서 발생할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;멱등의 활용으로 자동 복구 메커니즘을 가질 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Q: 재요청 중간에 다른 곳에서 리소스를 변경해버리는 경우는??&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Ex)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자1: GET -&amp;gt; username:A, age:20&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자2: PUT -&amp;gt; username:A, age:30&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자1: GET -&amp;gt; username:A, age:30 -&amp;gt; 사용자2의 영향으로 바뀐 데이터 조회&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size16&quot;&gt;A: 멱등은 외부 요인으로 중간에 &lt;b&gt;리소스가 변경되는 것 까지는 고려하지는 않는다.&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size16&quot;&gt;캐시가능(Cacheable)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;응답 결과 리소스를 캐시해서 사용해도 되는가?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;GET, HEAD, POST, PATCH 캐시가능&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제로는 GET, HEAD 정도만 캐시로 사용&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- POST, PATCH는 본문 내용까지 캐시 키로 고려해야 하는데, 구현이 쉽지않다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Reference.&lt;/p&gt;
&lt;figure id=&quot;og_1663069171457&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;HTTP - 위키백과, 우리 모두의 백과사전&quot; data-og-description=&quot;위키백과, 우리 모두의 백과사전. HTTP(HyperText Transfer Protocol, 문화어: 초본문전송규약, 하이퍼본문전송규약)는 W3 상에서 정보를 주고받을 수 있는 프로토콜이다. 주로 HTML 문서를 주고받는 데에 &quot; data-og-host=&quot;ko.wikipedia.org&quot; data-og-source-url=&quot;https://ko.wikipedia.org/wiki/HTTP&quot; data-og-url=&quot;https://ko.wikipedia.org/wiki/HTTP&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cTcU4h/hyPMRjXd2n/xp6r7CfUpd1MkuKaJ4nLj0/img.png?width=1200&amp;amp;height=642&amp;amp;face=0_0_1200_642,https://scrap.kakaocdn.net/dn/eSwuf/hyPLnLyqab/Q1KS0EKb8nqFN8hhWHHyyk/img.png?width=800&amp;amp;height=428&amp;amp;face=0_0_800_428,https://scrap.kakaocdn.net/dn/btDbwJ/hyPLdhTcD1/ODr9nUuvCSwGpHr5rU9q91/img.png?width=640&amp;amp;height=342&amp;amp;face=0_0_640_342&quot;&gt;&lt;a href=&quot;https://ko.wikipedia.org/wiki/HTTP&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://ko.wikipedia.org/wiki/HTTP&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cTcU4h/hyPMRjXd2n/xp6r7CfUpd1MkuKaJ4nLj0/img.png?width=1200&amp;amp;height=642&amp;amp;face=0_0_1200_642,https://scrap.kakaocdn.net/dn/eSwuf/hyPLnLyqab/Q1KS0EKb8nqFN8hhWHHyyk/img.png?width=800&amp;amp;height=428&amp;amp;face=0_0_800_428,https://scrap.kakaocdn.net/dn/btDbwJ/hyPLdhTcD1/ODr9nUuvCSwGpHr5rU9q91/img.png?width=640&amp;amp;height=342&amp;amp;face=0_0_640_342');&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;HTTP - 위키백과, 우리 모두의 백과사전&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;위키백과, 우리 모두의 백과사전. HTTP(HyperText Transfer Protocol, 문화어: 초본문전송규약, 하이퍼본문전송규약)는 W3 상에서 정보를 주고받을 수 있는 프로토콜이다. 주로 HTML 문서를 주고받는 데에&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;ko.wikipedia.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id=&quot;og_1663000835229&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;HTTP 요청 메서드 - HTTP | MDN&quot; data-og-description=&quot;HTTP는 요청 메서드를 정의하여, 주어진 리소스에 수행하길 원하는 행동을 나타냅니다. 간혹 요청 메서드를 &amp;quot;HTTP 동사&amp;quot;라고 부르기도 합니다. 각각의 메서드는 서로 다른 의미를 구현하지만, 일부&quot; data-og-host=&quot;developer.mozilla.org&quot; data-og-source-url=&quot;https://developer.mozilla.org/ko/docs/Web/HTTP/Methods&quot; data-og-url=&quot;https://developer.mozilla.org/ko/docs/Web/HTTP/Methods&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/lueyC/hyPLrzIi2Y/Ygn7cheeMGreVICJzrnCI1/img.png?width=1920&amp;amp;height=1080&amp;amp;face=0_0_1920_1080&quot;&gt;&lt;a href=&quot;https://developer.mozilla.org/ko/docs/Web/HTTP/Methods&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://developer.mozilla.org/ko/docs/Web/HTTP/Methods&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/lueyC/hyPLrzIi2Y/Ygn7cheeMGreVICJzrnCI1/img.png?width=1920&amp;amp;height=1080&amp;amp;face=0_0_1920_1080');&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;HTTP 요청 메서드 - HTTP | MDN&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;HTTP는 요청 메서드를 정의하여, 주어진 리소스에 수행하길 원하는 행동을 나타냅니다. 간혹 요청 메서드를 &quot;HTTP 동사&quot;라고 부르기도 합니다. 각각의 메서드는 서로 다른 의미를 구현하지만, 일부&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;developer.mozilla.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id=&quot;og_1663000698657&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;모든 개발자를 위한 HTTP 웹 기본 지식 - 인프런 | 강의&quot; data-og-description=&quot;실무에 꼭 필요한 HTTP 핵심 기능과 올바른 HTTP API 설계 방법을 학습합니다., - 강의 소개 | 인프런...&quot; data-og-host=&quot;www.inflearn.com&quot; data-og-source-url=&quot;https://www.inflearn.com/course/http-%EC%9B%B9-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC/dashboard&quot; data-og-url=&quot;https://www.inflearn.com/course/http-%EC%9B%B9-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/p2uCj/hyPHlL8rnP/FSHVAfR7vB6LuDscYKm2L0/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/cup7EJ/hyPHuPQztK/8dojym58kWgVGYwtbk2PIK/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/bz75cR/hyPF0CPhif/43fiyMsmSdrR0alrfh5msk/img.jpg?width=1200&amp;amp;height=666&amp;amp;face=0_0_1200_666&quot;&gt;&lt;a href=&quot;https://www.inflearn.com/course/http-%EC%9B%B9-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC/dashboard&quot; data-source-url=&quot;https://www.inflearn.com/course/http-%EC%9B%B9-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC/dashboard&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/p2uCj/hyPHlL8rnP/FSHVAfR7vB6LuDscYKm2L0/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/cup7EJ/hyPHuPQztK/8dojym58kWgVGYwtbk2PIK/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/bz75cR/hyPF0CPhif/43fiyMsmSdrR0alrfh5msk/img.jpg?width=1200&amp;amp;height=666&amp;amp;face=0_0_1200_666');&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;모든 개발자를 위한 HTTP 웹 기본 지식 - 인프런 | 강의&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;실무에 꼭 필요한 HTTP 핵심 기능과 올바른 HTTP API 설계 방법을 학습합니다., - 강의 소개 | 인프런...&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.inflearn.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>Network</category>
      <author>큐범</author>
      <guid isPermaLink="true">https://kbcoding.tistory.com/97</guid>
      <comments>https://kbcoding.tistory.com/97#entry97comment</comments>
      <pubDate>Fri, 16 Sep 2022 21:48:24 +0900</pubDate>
    </item>
    <item>
      <title>[Network] HTTP(Stateful Stateless 차이, 비 연결성, 클라이언트 서버 구조 ...)</title>
      <link>https://kbcoding.tistory.com/96</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;HTTP (HyperText Transfer Protocol)&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;- 역사&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;HTTP/0.9 1991&lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;년&lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;: GET &lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;메서드만 지원&lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;, HTTP &lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;헤더&lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;X&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HTTP/1.0 1996년: 메서드, 헤더 추가&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;HTTP/1.1 1997년: 가장 많이 사용, 우리에게 가장 중요한 버전&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;RFC2068 (1997) -&amp;gt; RFC2616 (1999) -&amp;gt; RFC7230~7235 (2014)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HTTP/2 2015년: 성능 개선&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HTTP/3 진행중: TCP 대신에 UDP 사용, 성능 개선&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size16&quot;&gt;- 기반 프로토콜&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TCP: HTTP/1.1, HTTP/2&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;UDP: HTTP/3&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 HTTP/1.1 주로 사용&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; - HTTP/2, HTTP/3 도 점점 증가&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size23&quot;&gt;- HTTP 특징&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클라이언트 서버 구조를 갖는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;무상태(Stateless) 프로토콜, 비연결성&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size23&quot;&gt;- 클라이언트 서버 구조&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Request Response구조를 갖는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클라이언트는 서버에 요청을 보내고, 응답을 대기한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서버가 요청에 대한 결과를 만들어서 응답한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-09-12 오후 2.57.17.png&quot; data-origin-width=&quot;613&quot; data-origin-height=&quot;136&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/VSwel/btrLLWMyvDP/2LJigT0Wl5QNB2LM7Ss941/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/VSwel/btrLLWMyvDP/2LJigT0Wl5QNB2LM7Ss941/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/VSwel/btrLLWMyvDP/2LJigT0Wl5QNB2LM7Ss941/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FVSwel%2FbtrLLWMyvDP%2F2LJigT0Wl5QNB2LM7Ss941%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;613&quot; height=&quot;136&quot; data-filename=&quot;스크린샷 2022-09-12 오후 2.57.17.png&quot; data-origin-width=&quot;613&quot; data-origin-height=&quot;136&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Stateful, Stateless&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;- 무상태 프로토콜 [스테이리스(Stateless)]&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서버가 클라이언트의 상태를 보존하지 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;장점: 서버 확장성이 높다.(Sacle out)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단점: 클아이언트가 추가 데이터를 전송한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size20&quot;&gt;Stateful의 상황&lt;/h3&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;고객: 이 노트북 얼마인가요?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;점원: 100만원 입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;고객: 2개 구매하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;점원: 200만원 입니다. 신용카드, 현금중에 어떤 걸로 구매 하시겠어요?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;점원: 200만원 결제 완료되었습니다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size20&quot;&gt;Stateful의 점원이 중간에 바뀐다는 상황&lt;/h3&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;고객: 이 노트북 얼마인가요?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;점원A: 100만원 입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;고객: 2개 구매하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;점원B: ? 무엇을 2개 구매하시겠어요?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;고객: 신용카드로 구매하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;점원C: ? 무슨 제품을 몇 개 신용카드로 구매하시겠어요?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상태 유지- Stateful&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;고객: 이 노트북 얼마인가요?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;점원: 100만원 입니다. (노트북 상태 유지)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;고객: 2개 구매하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;점원: 200만원 입니다. 신용카드, 현금중에 어떤 걸로 구매 하시겠어요? (노트북, 2개 상태 유지)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;고객: 신용카드로 구매하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;점원: 200만원 결제 완료되었습니다. (노트북, 2개, 신용카드 상태 유지)&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;무상태 - Stateless&lt;/h3&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;고객: 이 노트북 얼마인가요?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;점원: 100만원 입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;고객: 노트북 2개 구매하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;점원: 노트북 2개는 200만원 입니다. 신용카드, 현금중에 어떤 걸로 구매 하시겠어요?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;고객: 노트북 2개를 신용카드로 구매하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;점원: 200만원 결제 완료되었습니다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size16&quot;&gt;무상태 - Stateless, 점원이 중간에 바뀌면?&lt;/h3&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;고객: 이 노트북 얼마인가요?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;점원A: 100만원 입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;고객: 노트북 2개 구매하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;점원B: 노트북 2개는 200만원 입니다. 신용카드, 현금중에 어떤 걸로 구매 하시겠어요?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;고객: 노트북 2개를 신용카드로 구매하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;점원C: 200만원 결제 완료되었습니다&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size16&quot;&gt;Stateful, Stateless 정리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Stateful(상태 유지): 중간에 다른 점원이 바뀌면 안된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(중간에 다른 점원으로 바뀔 때 상태 정보를 다른 점원에게 미리 알려줘야 한다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Stateless(무상태): 중간에 다른 점원으로 바뀌어도 된다.&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;&amp;nbsp; &amp;nbsp;- 갑자기 클라이언트 요청이 증가해도 서버를 대거 투입할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 무상태는 응답 서버를 쉽게 바꿀 수 있다. -&amp;gt; 무한한 서버 증설 가능&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;Stateful(상태 유지) - 항상 같은 서버가 유지 되어야한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-09-12 오후 3.09.30.png&quot; data-origin-width=&quot;478&quot; data-origin-height=&quot;251&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bdHMzw/btrLStPFwSX/PBWP3TSbiHXcbFNMMJjDoK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bdHMzw/btrLStPFwSX/PBWP3TSbiHXcbFNMMJjDoK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bdHMzw/btrLStPFwSX/PBWP3TSbiHXcbFNMMJjDoK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbdHMzw%2FbtrLStPFwSX%2FPBWP3TSbiHXcbFNMMJjDoK%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;478&quot; height=&quot;251&quot; data-filename=&quot;스크린샷 2022-09-12 오후 3.09.30.png&quot; data-origin-width=&quot;478&quot; data-origin-height=&quot;251&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;중간에 서버가 장애가 나면? 클라이언트의 상태 정보가 사라진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반면에, Stateless(무상태)는 아무 서버나 호출하면 되기에 서버2에서 호출하면된다.&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-09-12 오후 3.11.57.png&quot; data-origin-width=&quot;497&quot; data-origin-height=&quot;289&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/suTYQ/btrLMAvPPK4/reuPzOS0A6va2t8A2hjR3K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/suTYQ/btrLMAvPPK4/reuPzOS0A6va2t8A2hjR3K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/suTYQ/btrLMAvPPK4/reuPzOS0A6va2t8A2hjR3K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsuTYQ%2FbtrLMAvPPK4%2FreuPzOS0A6va2t8A2hjR3K%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;327&quot; height=&quot;190&quot; data-filename=&quot;스크린샷 2022-09-12 오후 3.11.57.png&quot; data-origin-width=&quot;497&quot; data-origin-height=&quot;289&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/td&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-09-12 오후 3.12.48.png&quot; data-origin-width=&quot;470&quot; data-origin-height=&quot;262&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nZU1F/btrLStozaRF/CIub4iRvdkgtfbBcRt3KaK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nZU1F/btrLStozaRF/CIub4iRvdkgtfbBcRt3KaK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nZU1F/btrLStozaRF/CIub4iRvdkgtfbBcRt3KaK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnZU1F%2FbtrLStozaRF%2FCIub4iRvdkgtfbBcRt3KaK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;345&quot; height=&quot;192&quot; data-filename=&quot;스크린샷 2022-09-12 오후 3.12.48.png&quot; data-origin-width=&quot;470&quot; data-origin-height=&quot;262&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size16&quot;&gt;Stateless의 한계&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 모든 것을 무상태로 설계 할 수 있는 경우도 있고 없는 경우도 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 무상태 &amp;bull; 예) 로그인이 필요 없는 단순한 서비스 소개 화면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 상태 유지 &amp;bull; 예) 로그인&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 로그인한 사용자의 경우 로그인 했다는 상태를 서버에 유지&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 일반적으로 브라우저 쿠키와 서버 세션등을 사용해서 상태 유지&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-상태 유지는 최소한만 사용&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;비 연결성&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HTTP는 기본이 연결을 유지하지 않는 모델이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반적으로 초 단위의 이하의 빠른 속도로 응답한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1시간 동안 수천명이 서비스를 사용해도 실제 서버에서 동시에 처리한느 요청은 수십개 이하로 매우 작다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- 예) 웹 브라우저에서 계속 연속해서 검색 버튼을 누르지는 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서버 자원을 매우 효율적으로 사용할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;비 연결성 - 한계와 극복&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TCP/IP 연결을 새로 맺어야 함 - 3 way handshake 시간 추가된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;웹 브라우저로 사이트를 요청하면 HTML 뿐만 아니라 자바스크립트, css, 추가 이미지 등 등 수 많은 자원이 함께 다운로드된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금은 HTTP 지속 연결(Persistent Connections)로 문제를 해결한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HTTP/2, HTTP/3에서 더 많은 최적화가 이루어진다.&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 349px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 349px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 349px; text-align: center;&quot;&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-09-12 오후 3.17.34.png&quot; data-origin-width=&quot;431&quot; data-origin-height=&quot;332&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Ns5CS/btrLWng6hJy/rrnChIImKjbNSug9uXK2N0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Ns5CS/btrLWng6hJy/rrnChIImKjbNSug9uXK2N0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Ns5CS/btrLWng6hJy/rrnChIImKjbNSug9uXK2N0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FNs5CS%2FbtrLWng6hJy%2FrrnChIImKjbNSug9uXK2N0%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;350&quot; height=&quot;270&quot; data-filename=&quot;스크린샷 2022-09-12 오후 3.17.34.png&quot; data-origin-width=&quot;431&quot; data-origin-height=&quot;332&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;span&gt;&lt;br /&gt;&lt;/span&gt;HTTP 초기&lt;/td&gt;
&lt;td style=&quot;width: 50%; text-align: center; height: 349px;&quot;&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;419&quot; data-origin-height=&quot;332&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/5hH3p/btrLNo2XVS7/RI9YIABC3LkGDxMyew11f1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/5hH3p/btrLNo2XVS7/RI9YIABC3LkGDxMyew11f1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/5hH3p/btrLNo2XVS7/RI9YIABC3LkGDxMyew11f1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F5hH3p%2FbtrLNo2XVS7%2FRI9YIABC3LkGDxMyew11f1%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;350&quot; height=&quot;277&quot; data-origin-width=&quot;419&quot; data-origin-height=&quot;332&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;span&gt;&lt;br /&gt;&lt;/span&gt;HTTP 지속 연결&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size20&quot;&gt;HTTP 메시지&lt;/h3&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%; text-align: center;&quot;&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-09-12 오후 3.20.50.png&quot; data-origin-width=&quot;379&quot; data-origin-height=&quot;432&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bIQUvI/btrLPonO4Ti/fUx9CkZV3ydkk41f36MyvK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bIQUvI/btrLPonO4Ti/fUx9CkZV3ydkk41f36MyvK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bIQUvI/btrLPonO4Ti/fUx9CkZV3ydkk41f36MyvK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbIQUvI%2FbtrLPonO4Ti%2FfUx9CkZV3ydkk41f36MyvK%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;350&quot; height=&quot;399&quot; data-filename=&quot;스크린샷 2022-09-12 오후 3.20.50.png&quot; data-origin-width=&quot;379&quot; data-origin-height=&quot;432&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-09-12 오후 3.20.56.png&quot; data-origin-width=&quot;809&quot; data-origin-height=&quot;449&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ci2AI8/btrLNxr1Qkr/xRLXSQ5sSK3mVPsnTsu6o1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ci2AI8/btrLNxr1Qkr/xRLXSQ5sSK3mVPsnTsu6o1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ci2AI8/btrLNxr1Qkr/xRLXSQ5sSK3mVPsnTsu6o1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fci2AI8%2FbtrLNxr1Qkr%2FxRLXSQ5sSK3mVPsnTsu6o1%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;350&quot; height=&quot;194&quot; data-filename=&quot;스크린샷 2022-09-12 오후 3.20.56.png&quot; data-origin-width=&quot;809&quot; data-origin-height=&quot;449&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-09-12 오후 3.21.20.png&quot; data-origin-width=&quot;832&quot; data-origin-height=&quot;247&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/EpPje/btrLNw7HOgl/eTVz1nlWsgwyjHdeWz3qi1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/EpPje/btrLNw7HOgl/eTVz1nlWsgwyjHdeWz3qi1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/EpPje/btrLNw7HOgl/eTVz1nlWsgwyjHdeWz3qi1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEpPje%2FbtrLNw7HOgl%2FeTVz1nlWsgwyjHdeWz3qi1%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;832&quot; height=&quot;247&quot; data-filename=&quot;스크린샷 2022-09-12 오후 3.21.20.png&quot; data-origin-width=&quot;832&quot; data-origin-height=&quot;247&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock floatRight&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-09-12 오후 3.23.51.png&quot; data-origin-width=&quot;357&quot; data-origin-height=&quot;91&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wepZ1/btrLXOS63MY/sJ3MseuRrdsbuRck8Vb0i0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wepZ1/btrLXOS63MY/sJ3MseuRrdsbuRck8Vb0i0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wepZ1/btrLXOS63MY/sJ3MseuRrdsbuRck8Vb0i0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwepZ1%2FbtrLXOS63MY%2FsJ3MseuRrdsbuRck8Vb0i0%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;91&quot; data-filename=&quot;스크린샷 2022-09-12 오후 3.23.51.png&quot; data-origin-width=&quot;357&quot; data-origin-height=&quot;91&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size16&quot;&gt;시작 라인 - 요청 메시지&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;start-line = request-line / status-line&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;request-line = method SP(공백) request-target SP HTTP-version CRLF(엔터)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HTTP 메서드 (GET: 조회)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요청 대상 (/search?q=hello&amp;amp;hl=ko)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HTTP Version&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 floatRight&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-09-12 오후 3.24.17.png&quot; data-origin-width=&quot;354&quot; data-origin-height=&quot;96&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tN0X0/btrLMx6RvVJ/uxIsddtb7L23And9Qk2Ad1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tN0X0/btrLMx6RvVJ/uxIsddtb7L23And9Qk2Ad1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tN0X0/btrLMx6RvVJ/uxIsddtb7L23And9Qk2Ad1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtN0X0%2FbtrLMx6RvVJ%2FuxIsddtb7L23And9Qk2Ad1%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;354&quot; height=&quot;96&quot; data-filename=&quot;스크린샷 2022-09-12 오후 3.24.17.png&quot; data-origin-width=&quot;354&quot; data-origin-height=&quot;96&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size16&quot;&gt;시작 라인 - 요청 메시지(HTTP 메서드)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;종류: GET, POST, PUT, DELETE...&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;- GET: 리소스 조회&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- POST: 요청 내역 처리&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 floatRight&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-09-12 오후 3.25.23.png&quot; data-origin-width=&quot;418&quot; data-origin-height=&quot;100&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dCHlnA/btrLVXpd6eG/OJta2NNUk2sECmOztInPH1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dCHlnA/btrLVXpd6eG/OJta2NNUk2sECmOztInPH1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dCHlnA/btrLVXpd6eG/OJta2NNUk2sECmOztInPH1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdCHlnA%2FbtrLVXpd6eG%2FOJta2NNUk2sECmOztInPH1%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;418&quot; height=&quot;100&quot; data-filename=&quot;스크린샷 2022-09-12 오후 3.25.23.png&quot; data-origin-width=&quot;418&quot; data-origin-height=&quot;100&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size16&quot;&gt;시작 라인 - 요청 메시지(요청 대상)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;absolute-path[?query] (절대경로[?쿼리]) &lt;br /&gt;절대경로= &quot;/&quot; 로 시작하는 경로&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고: *, http://...?x=y 와 같이 다른 유형의 경로지정 방법도 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;+ 마지막은 HTTP Version =&amp;nbsp; HTTP/1.1&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock floatRight&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-09-12 오후 3.27.13.png&quot; data-origin-width=&quot;293&quot; data-origin-height=&quot;150&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bJ21Sy/btrLMyx1KMw/wfaINUKU9AtQ2k2ZWWiqV0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bJ21Sy/btrLMyx1KMw/wfaINUKU9AtQ2k2ZWWiqV0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bJ21Sy/btrLMyx1KMw/wfaINUKU9AtQ2k2ZWWiqV0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbJ21Sy%2FbtrLMyx1KMw%2FwfaINUKU9AtQ2k2ZWWiqV0%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;293&quot; height=&quot;150&quot; data-filename=&quot;스크린샷 2022-09-12 오후 3.27.13.png&quot; data-origin-width=&quot;293&quot; data-origin-height=&quot;150&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size20&quot;&gt;시작 라인 - 응답 메시지&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;start-line = request-line / status-line&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;status-line = HTTP-version SP status-code SP reason-phrase CRLF&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HTTP 버전&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HTTP 상태 코드: 요청 성공, 실패를 나타낸다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp;200: 성공&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp;400: 클라이언트 요청 오류&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp;500: 서버 내부 오류&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이유 문구: 사람이 이해할 수 있는 짧은 상태 코드 설명 글&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size20&quot;&gt;HTTP 헤더&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;header-field = field-name &quot;:&quot; OWS field-value OWS (OWS:띄어쓰기 허용)&lt;br /&gt;field-name은 대소문자 구문 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HTTP 전소에 필요한 모든 부가정보가 들어간다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size20&quot;&gt;HTTP 메시지 바디&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제 전송할 데이터&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HTML, 이미지, 영상 등등 byte로 표현할 수 있는 모든 데이터 전송 가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Reference.&lt;/p&gt;
&lt;figure id=&quot;og_1662961537234&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;모든 개발자를 위한 HTTP 웹 기본 지식 - 인프런 | 강의&quot; data-og-description=&quot;실무에 꼭 필요한 HTTP 핵심 기능과 올바른 HTTP API 설계 방법을 학습합니다., - 강의 소개 | 인프런...&quot; data-og-host=&quot;www.inflearn.com&quot; data-og-source-url=&quot;https://www.inflearn.com/course/http-%EC%9B%B9-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC/dashboard&quot; data-og-url=&quot;https://www.inflearn.com/course/http-%EC%9B%B9-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/p2uCj/hyPHlL8rnP/FSHVAfR7vB6LuDscYKm2L0/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/cup7EJ/hyPHuPQztK/8dojym58kWgVGYwtbk2PIK/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/bz75cR/hyPF0CPhif/43fiyMsmSdrR0alrfh5msk/img.jpg?width=1200&amp;amp;height=666&amp;amp;face=0_0_1200_666&quot;&gt;&lt;a href=&quot;https://www.inflearn.com/course/http-%EC%9B%B9-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC/dashboard&quot; data-source-url=&quot;https://www.inflearn.com/course/http-%EC%9B%B9-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC/dashboard&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/p2uCj/hyPHlL8rnP/FSHVAfR7vB6LuDscYKm2L0/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/cup7EJ/hyPHuPQztK/8dojym58kWgVGYwtbk2PIK/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/bz75cR/hyPF0CPhif/43fiyMsmSdrR0alrfh5msk/img.jpg?width=1200&amp;amp;height=666&amp;amp;face=0_0_1200_666');&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;모든 개발자를 위한 HTTP 웹 기본 지식 - 인프런 | 강의&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;실무에 꼭 필요한 HTTP 핵심 기능과 올바른 HTTP API 설계 방법을 학습합니다., - 강의 소개 | 인프런...&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.inflearn.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>Network</category>
      <category>HTML</category>
      <category>HTTP</category>
      <category>http 메시지</category>
      <category>무상태 프로토콜</category>
      <category>클라이언트 서버 구조</category>
      <author>큐범</author>
      <guid isPermaLink="true">https://kbcoding.tistory.com/96</guid>
      <comments>https://kbcoding.tistory.com/96#entry96comment</comments>
      <pubDate>Thu, 15 Sep 2022 16:31:20 +0900</pubDate>
    </item>
    <item>
      <title>[MSA] Micro Service Pattern(API Gateway, Service discovery, Service Mesh)</title>
      <link>https://kbcoding.tistory.com/95</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Micro Service Pattern - API Gateway&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-09-05 오후 3.27.13.png&quot; data-origin-width=&quot;656&quot; data-origin-height=&quot;478&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dl4c2U/btrLuwL6gwA/wkTWi4HA057DlHMNGdb9l0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dl4c2U/btrLuwL6gwA/wkTWi4HA057DlHMNGdb9l0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dl4c2U/btrLuwL6gwA/wkTWi4HA057DlHMNGdb9l0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdl4c2U%2FbtrLuwL6gwA%2FwkTWi4HA057DlHMNGdb9l0%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;350&quot; height=&quot;255&quot; data-filename=&quot;스크린샷 2022-09-05 오후 3.27.13.png&quot; data-origin-width=&quot;656&quot; data-origin-height=&quot;478&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;service1,2,3가 전부 사용되는 데이터가 필요해지면 각각의 서비스를 호출해야해서 총 6번의 호출과 반환이 이루어지는데 각각의 결과 값을 기다려야한다. 여기서의 문제점은 service1,2,3 각각의 주소를 알아야하는 단점이 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-09-05 오후 3.26.47.png&quot; data-origin-width=&quot;518&quot; data-origin-height=&quot;564&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/09Lct/btrLjj88ynT/2SQUhuXg9F0Yladx6zE9i0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/09Lct/btrLjj88ynT/2SQUhuXg9F0Yladx6zE9i0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/09Lct/btrLjj88ynT/2SQUhuXg9F0Yladx6zE9i0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F09Lct%2FbtrLjj88ynT%2F2SQUhuXg9F0Yladx6zE9i0%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;350&quot; height=&quot;381&quot; data-filename=&quot;스크린샷 2022-09-05 오후 3.26.47.png&quot; data-origin-width=&quot;518&quot; data-origin-height=&quot;564&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 상황은 Application과 service사이에 API gatway를 두어서, 요청을 동시에 service1,2,3에 보낸 후, 데이터를 취합하여 다시 클라이언트로 보낸다. API Gateway를 두어서 하나의 api point만 알아도 되는 이점이 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 마이크로 소프트 공식문저 중 -&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;API Gateway 이점&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&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;- 서비스가 웹 우호적이 아닌 *AMQP(Advanced Mwssage Queuing Protocol) 등의 메시징 프로토콜을 사용할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- API 게이트웨는 인증, 로깅 SSL 종료, 부하 분산 등의 다른 교차 기능을 수핼할 수 있다.&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;*AMQP: 메시지 지향 미들 웨어를 위한 개방형 표준 응용 계층 프로토콜.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Micro Service Pattern - Service discovery&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;탄생배경&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클라우드를 사용할 경우, auto scaling에 따라 service instance가 유동적으로 변하며 IP 주소가 계속 바뀌게 되며, 이데 대한 정보를 취득할 수 있는 방법일 필요해진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클라이언트나 API 게이트웨이가 호출할 서비스를 찾아주는 메커니즘이 필요하게 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 Client-Side/Server-Side Discovery Pattern을 적용하면 해결이 가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MSA와 같은 분산 환경은 서비스 간의 원격 호출로 구성된다. 원격 서비스 호출은 IP 주소와 포트를 이용하는 방식으로 클라우드 환경이 되면서 서비스가 오토 스케일링 등에 의해서 동적으로 생성되거나&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컨테이너 기반의 배포로 인해서, 서비스의 IP가 동적으로 변경되는 일의 빈도가 늘어난다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-09-05 오후 3.36.20.png&quot; data-origin-width=&quot;1172&quot; data-origin-height=&quot;474&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bqVMvz/btrLuCr0p0R/df5XgrAwAezoWKJ5T4S7r1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bqVMvz/btrLuCr0p0R/df5XgrAwAezoWKJ5T4S7r1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bqVMvz/btrLuCr0p0R/df5XgrAwAezoWKJ5T4S7r1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbqVMvz%2FbtrLuCr0p0R%2Fdf5XgrAwAezoWKJ5T4S7r1%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;450&quot; height=&quot;182&quot; data-filename=&quot;스크린샷 2022-09-05 오후 3.36.20.png&quot; data-origin-width=&quot;1172&quot; data-origin-height=&quot;474&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Service A의 인스턴스들이 생성될때, Service A에 대한 주소를 Servie registry(서비스 등록 서버)에 등록해놓는다. Service A를 호출하고자 하는 클라이언트는 Service registry에 Service A의 주소를 물어보고 등록된 주소를 받아서 그 주소로 서비스를 호출한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-09-05 오후 3.46.10.png&quot; data-origin-width=&quot;1146&quot; data-origin-height=&quot;562&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bfKx91/btrLmzjiJ09/krxeMxMWY7Z9T4kMnl3eak/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bfKx91/btrLmzjiJ09/krxeMxMWY7Z9T4kMnl3eak/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bfKx91/btrLmzjiJ09/krxeMxMWY7Z9T4kMnl3eak/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbfKx91%2FbtrLmzjiJ09%2FkrxeMxMWY7Z9T4kMnl3eak%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;450&quot; height=&quot;221&quot; data-filename=&quot;스크린샷 2022-09-05 오후 3.46.10.png&quot; data-origin-width=&quot;1146&quot; data-origin-height=&quot;562&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Service discovery 기능을 구현하는 방법으로는 크게 Client discovery방식과 Server side discovery 방식이 있다. Service Client가 Service registry에서 서비스의 위치를 찾아서 호출하는 방식을 Client side dicovery이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 호출이 되는 서비스 앞에 일종의 proxy서버(로드밸런서)를 넣는 방식인데, 서비스 클라이언트는 이 로드 밸런서를 호출하면 로드밸런서가 Service registry로 부터 등록된 서비스의 위치를 리턴하고, 이를 기반으로 라우팅 하는 방식이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Micro Service Pattern - Service Mesh&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;563&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cUT0wJ/btrLugv2jkb/Eia1bkfPIpw96GWwVYHlbK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cUT0wJ/btrLugv2jkb/Eia1bkfPIpw96GWwVYHlbK/img.png&quot; data-alt=&quot;Service Mesh&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cUT0wJ/btrLugv2jkb/Eia1bkfPIpw96GWwVYHlbK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcUT0wJ%2FbtrLugv2jkb%2FEia1bkfPIpw96GWwVYHlbK%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;500&quot; height=&quot;220&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;563&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Service Mesh&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서비스 간의 전체 연결 구조를 파악하기 어려우며 이로 인해서 장애가 났을 경우, 어느 서비스에 장애가 났는지 추적에 대한 어려움이 생긴다. 또한, 특정 서비스의 장애가 다른 서비스에 영향을 주는 문제들을 겪을 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-09-05 오후 4.02.32.png&quot; data-origin-width=&quot;886&quot; data-origin-height=&quot;584&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ba8tkb/btrLu3iFDbp/xvWwuBKhRE1tp4DbipiWnk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ba8tkb/btrLu3iFDbp/xvWwuBKhRE1tp4DbipiWnk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ba8tkb/btrLu3iFDbp/xvWwuBKhRE1tp4DbipiWnk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fba8tkb%2FbtrLu3iFDbp%2FxvWwuBKhRE1tp4DbipiWnk%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;500&quot; height=&quot;330&quot; data-filename=&quot;스크린샷 2022-09-05 오후 4.02.32.png&quot; data-origin-width=&quot;886&quot; data-origin-height=&quot;584&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞의 문제와 같은 장애 전파의 예는 써킷 브레이커(Circit breaker)라는 디자인 패턴으로 해결할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-09-05 오후 4.04.22.png&quot; data-origin-width=&quot;1260&quot; data-origin-height=&quot;458&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cpcZyB/btrLsrLB5Qh/t6SQSdVmEV5yUBOam5WNLK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cpcZyB/btrLsrLB5Qh/t6SQSdVmEV5yUBOam5WNLK/img.png&quot; data-alt=&quot;서킷 브레이커 패턴&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cpcZyB/btrLsrLB5Qh/t6SQSdVmEV5yUBOam5WNLK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcpcZyB%2FbtrLsrLB5Qh%2Ft6SQSdVmEV5yUBOam5WNLK%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;500&quot; height=&quot;182&quot; data-filename=&quot;스크린샷 2022-09-05 오후 4.04.22.png&quot; data-origin-width=&quot;1260&quot; data-origin-height=&quot;458&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;Reference.&lt;/p&gt;
&lt;figure id=&quot;og_1662360855490&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;마이크로 서비스 아키텍처 스타일 - Azure Architecture Center&quot; data-og-description=&quot;Azure에서 마이크로 서비스 아키텍처 스타일의 이점, 과제 및 모범 사례에 대해 알아봅니다.&quot; data-og-host=&quot;docs.microsoft.com&quot; data-og-source-url=&quot;https://docs.microsoft.com/ko-kr/azure/architecture/guide/architecture-styles/microservices&quot; data-og-url=&quot;https://docs.microsoft.com/ko-kr/azure/architecture/guide/architecture-styles/microservices&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/m478Y/hyPHl6MsRO/vhoIVyKkhucikXcaRekiRK/img.png?width=400&amp;amp;height=400&amp;amp;face=0_0_400_400,https://scrap.kakaocdn.net/dn/ibYee/hyPHrMGfnz/jSYBx6GDMCZ72hRxW2n2Fk/img.png?width=987&amp;amp;height=399&amp;amp;face=0_0_987_399&quot;&gt;&lt;a href=&quot;https://docs.microsoft.com/ko-kr/azure/architecture/guide/architecture-styles/microservices&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://docs.microsoft.com/ko-kr/azure/architecture/guide/architecture-styles/microservices&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/m478Y/hyPHl6MsRO/vhoIVyKkhucikXcaRekiRK/img.png?width=400&amp;amp;height=400&amp;amp;face=0_0_400_400,https://scrap.kakaocdn.net/dn/ibYee/hyPHrMGfnz/jSYBx6GDMCZ72hRxW2n2Fk/img.png?width=987&amp;amp;height=399&amp;amp;face=0_0_987_399');&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;마이크로 서비스 아키텍처 스타일 - Azure Architecture Center&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Azure에서 마이크로 서비스 아키텍처 스타일의 이점, 과제 및 모범 사례에 대해 알아봅니다.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;docs.microsoft.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id=&quot;og_1662360287302&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;AMQP - 위키백과, 우리 모두의 백과사전&quot; data-og-description=&quot;위키백과, 우리 모두의 백과사전. AMQP(Advanced Message Queuing Protocol, 어드밴스트 메시지 큐잉 프로토콜)는 메시지 지향 미들웨어를 위한 개방형 표준 응용 계층 프로토콜이다. AMQP의 정의 기능들은 &quot; data-og-host=&quot;ko.wikipedia.org&quot; data-og-source-url=&quot;https://ko.wikipedia.org/wiki/AMQP&quot; data-og-url=&quot;https://ko.wikipedia.org/wiki/AMQP&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://ko.wikipedia.org/wiki/AMQP&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://ko.wikipedia.org/wiki/AMQP&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;AMQP - 위키백과, 우리 모두의 백과사전&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;위키백과, 우리 모두의 백과사전. AMQP(Advanced Message Queuing Protocol, 어드밴스트 메시지 큐잉 프로토콜)는 메시지 지향 미들웨어를 위한 개방형 표준 응용 계층 프로토콜이다. AMQP의 정의 기능들은&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;ko.wikipedia.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id=&quot;og_1662361285377&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;서비스 메쉬(service mesh) 개념, 기능, 작동방식, 최적화 방법&quot; data-og-description=&quot;서비스 메쉬(서비스 메시)란 애플리케이션에 구축된 인프라 레이어를 뜻하며, 마이크로서비스 라우팅을 요청하고 개별 프록시들이 모여 메쉬 네트워크를 형성합니다.&quot; data-og-host=&quot;www.redhat.com&quot; data-og-source-url=&quot;https://www.redhat.com/ko/topics/microservices/what-is-a-service-mesh&quot; data-og-url=&quot;https://www.redhat.com/ko/topics/microservices/what-is-a-service-mesh&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/qedzk/hyPHmq5zgS/2DcOySyQ0Fma3j5DSDLsAk/img.jpg?width=1200&amp;amp;height=630&amp;amp;face=770_127_1004_383,https://scrap.kakaocdn.net/dn/N677h/hyPHqUyj0q/AlHzsk6w0Vz6Jiln46uxL0/img.jpg?width=1200&amp;amp;height=630&amp;amp;face=770_127_1004_383,https://scrap.kakaocdn.net/dn/w4sUq/hyPHktgFyi/xYhsacPkmDEQgMxxufv7RK/img.png?width=1680&amp;amp;height=740&amp;amp;face=0_0_1680_740&quot;&gt;&lt;a href=&quot;https://www.redhat.com/ko/topics/microservices/what-is-a-service-mesh&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.redhat.com/ko/topics/microservices/what-is-a-service-mesh&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/qedzk/hyPHmq5zgS/2DcOySyQ0Fma3j5DSDLsAk/img.jpg?width=1200&amp;amp;height=630&amp;amp;face=770_127_1004_383,https://scrap.kakaocdn.net/dn/N677h/hyPHqUyj0q/AlHzsk6w0Vz6Jiln46uxL0/img.jpg?width=1200&amp;amp;height=630&amp;amp;face=770_127_1004_383,https://scrap.kakaocdn.net/dn/w4sUq/hyPHktgFyi/xYhsacPkmDEQgMxxufv7RK/img.png?width=1680&amp;amp;height=740&amp;amp;face=0_0_1680_740');&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;서비스 메쉬(service mesh) 개념, 기능, 작동방식, 최적화 방법&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;www.redhat.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>Micro Service Architecture</category>
      <author>큐범</author>
      <guid isPermaLink="true">https://kbcoding.tistory.com/95</guid>
      <comments>https://kbcoding.tistory.com/95#entry95comment</comments>
      <pubDate>Wed, 14 Sep 2022 17:08:39 +0900</pubDate>
    </item>
    <item>
      <title>[MSA] MSA(Micro Service Architecture) 정의</title>
      <link>https://kbcoding.tistory.com/94</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;MSA의 정의를 알기 위해서는 그와 반대되는 모노리스 시스템에 대해서 이해해야한다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모노리스(Monoliths)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 프로젝트에 모든 코드가 모여있어, 시스템 구조가 간결하고 빠르게 구축할 수 있다,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 애플리케이션이 한 덩어리로 구성하며 단일 프로세스로 실행해야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 한꺼번에 수정, 배포되어야한다. 하나가 실패하면 모두 실패됨을 의미한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제점: 작은 부분을 수정해도 전체 부분에 대해서 영향을 줄 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모노리스를 클라우드 인프라에서 활용시에 스케일 아웃의 대상은 모노리스 전체가 된다. 그것만으로 충분히 확장성, 탄력성이 보장가능하나 비용효율적이지 않다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그에 비해 마이크로 서비스는 애플리케이션이 &lt;b&gt;여러개의 서비스 조각으로 구성&lt;/b&gt;된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Micro Service Architecture 정의&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Micro Service는 작고, 독립적이며, 느슨하게 결합되어 있어 하나의 소규모 개발자 팀이 작성하고 유지 관리할 수 있다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서비스는 각기 독립적인 기능을 제공한다. 서비스가 사용하는 저장소는 다른 서비스와 완벽히 격리된다. 따라서 독립적으로 수정 가능하며 별도 배포, 확장 가능하다. 따라서, &lt;b&gt;하나의 서비스 실패는 전체 실패가 아닌 부분적인 실패를 의미&lt;/b&gt;한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;확장시, 특정 기능별 독립적으로 확장 가능하며 특정 서비스의 변경 시 서비스 만 빌드, 배포가 진행된다. 독립적으로 서로 다른 언어로 개발 가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MSA의 특징&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-09-05 오후 3.17.03.png&quot; data-origin-width=&quot;1108&quot; data-origin-height=&quot;760&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/JJILc/btrLqV7a7p0/UbyG52Xmsardpo45idqyrk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/JJILc/btrLqV7a7p0/UbyG52Xmsardpo45idqyrk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/JJILc/btrLqV7a7p0/UbyG52Xmsardpo45idqyrk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJJILc%2FbtrLqV7a7p0%2FUbyG52Xmsardpo45idqyrk%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;500&quot; height=&quot;343&quot; data-filename=&quot;스크린샷 2022-09-05 오후 3.17.03.png&quot; data-origin-width=&quot;1108&quot; data-origin-height=&quot;760&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 하나의 시스템에서 개발 기술 환경이 다르다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- n개의 인스턴스가 있는데 이를 MSA라 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 서비스 자체 외에도 관리/오케스트레이션, API 게이트웨이와 같이 몇 가지 다른 구셩 요소가 기존 마이크로 서비스 아키텍쳐에 추가된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Reference.&lt;/p&gt;
&lt;figure id=&quot;og_1662358604252&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;What are microservices?&quot; data-og-description=&quot;Microservices - also known as the microservice architecture - is an architectural style that structures an application as a collection of loosely coupled services, which implement business capabilities. The microservice architecture enables the continuous &quot; data-og-host=&quot;microservices.io&quot; data-og-source-url=&quot;https://microservices.io/&quot; data-og-url=&quot;http://microservices.io/index.html&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/ent8Fa/hyPFV2UXwP/UMay4TKH5GxbnLaTlRDCtk/img.jpg?width=720&amp;amp;height=903&amp;amp;face=0_0_720_903,https://scrap.kakaocdn.net/dn/GJBsc/hyPF5qWcTU/gm09wCqKnmwfYnOQzU3Bk0/img.png?width=1377&amp;amp;height=445&amp;amp;face=0_0_1377_445,https://scrap.kakaocdn.net/dn/pWbYg/hyPHpH42CS/UzKCNykn7vRyrV3dvMfb3K/img.jpg?width=500&amp;amp;height=389&amp;amp;face=0_0_500_389&quot;&gt;&lt;a href=&quot;https://microservices.io/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://microservices.io/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/ent8Fa/hyPFV2UXwP/UMay4TKH5GxbnLaTlRDCtk/img.jpg?width=720&amp;amp;height=903&amp;amp;face=0_0_720_903,https://scrap.kakaocdn.net/dn/GJBsc/hyPF5qWcTU/gm09wCqKnmwfYnOQzU3Bk0/img.png?width=1377&amp;amp;height=445&amp;amp;face=0_0_1377_445,https://scrap.kakaocdn.net/dn/pWbYg/hyPHpH42CS/UzKCNykn7vRyrV3dvMfb3K/img.jpg?width=500&amp;amp;height=389&amp;amp;face=0_0_500_389');&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;What are microservices?&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Microservices - also known as the microservice architecture - is an architectural style that structures an application as a collection of loosely coupled services, which implement business capabilities. The microservice architecture enables the continuous&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;microservices.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;
&lt;figure id=&quot;og_1662358878908&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;마이크로 서비스 아키텍처 스타일 - Azure Architecture Center&quot; data-og-description=&quot;Azure에서 마이크로 서비스 아키텍처 스타일의 이점, 과제 및 모범 사례에 대해 알아봅니다.&quot; data-og-host=&quot;docs.microsoft.com&quot; data-og-source-url=&quot;https://docs.microsoft.com/ko-kr/azure/architecture/guide/architecture-styles/microservices&quot; data-og-url=&quot;https://docs.microsoft.com/ko-kr/azure/architecture/guide/architecture-styles/microservices&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/m478Y/hyPHl6MsRO/vhoIVyKkhucikXcaRekiRK/img.png?width=400&amp;amp;height=400&amp;amp;face=0_0_400_400,https://scrap.kakaocdn.net/dn/ibYee/hyPHrMGfnz/jSYBx6GDMCZ72hRxW2n2Fk/img.png?width=987&amp;amp;height=399&amp;amp;face=0_0_987_399&quot;&gt;&lt;a href=&quot;https://docs.microsoft.com/ko-kr/azure/architecture/guide/architecture-styles/microservices&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://docs.microsoft.com/ko-kr/azure/architecture/guide/architecture-styles/microservices&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/m478Y/hyPHl6MsRO/vhoIVyKkhucikXcaRekiRK/img.png?width=400&amp;amp;height=400&amp;amp;face=0_0_400_400,https://scrap.kakaocdn.net/dn/ibYee/hyPHrMGfnz/jSYBx6GDMCZ72hRxW2n2Fk/img.png?width=987&amp;amp;height=399&amp;amp;face=0_0_987_399');&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;마이크로 서비스 아키텍처 스타일 - Azure Architecture Center&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Azure에서 마이크로 서비스 아키텍처 스타일의 이점, 과제 및 모범 사례에 대해 알아봅니다.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;docs.microsoft.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Micro Service Architecture</category>
      <category>Cloud</category>
      <category>Micro Service Architecture</category>
      <category>MSA</category>
      <author>큐범</author>
      <guid isPermaLink="true">https://kbcoding.tistory.com/94</guid>
      <comments>https://kbcoding.tistory.com/94#entry94comment</comments>
      <pubDate>Tue, 13 Sep 2022 16:22:43 +0900</pubDate>
    </item>
    <item>
      <title>[MSA] MSA(Micro Service Architecture) 탄생배경 사용이유</title>
      <link>https://kbcoding.tistory.com/93</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;왜 &lt;span&gt;MSA&lt;/span&gt;인가&lt;span&gt;?&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;MSA&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-filename=&quot;스크린샷 2022-09-05 오후 3.01.44.png&quot; data-origin-width=&quot;2666&quot; data-origin-height=&quot;1452&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cWI7PA/btrLk351EGI/pSYwlSQCSwVZXnx0vMUu7K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cWI7PA/btrLk351EGI/pSYwlSQCSwVZXnx0vMUu7K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cWI7PA/btrLk351EGI/pSYwlSQCSwVZXnx0vMUu7K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcWI7PA%2FbtrLk351EGI%2FpSYwlSQCSwVZXnx0vMUu7K%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;550&quot; height=&quot;300&quot; data-filename=&quot;스크린샷 2022-09-05 오후 3.01.44.png&quot; data-origin-width=&quot;2666&quot; data-origin-height=&quot;1452&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;*&lt;/span&gt;아키텍쳐는 시스템의 구조이다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;과거에는 시스템의 구조보다는 알고리즘&lt;span&gt;, &lt;/span&gt;데이터 구조에 집중적이었다&lt;span&gt;. &lt;/span&gt;소프트웨어의 복잡도와 활용도가 올라감에 따라 구조에 대한 중요도가 올라가게 되었다&lt;span&gt;. &lt;/span&gt;즉&lt;span&gt;, &lt;/span&gt;과거에는 클래스나 모듈 내부에 관심이 있었다&lt;span&gt;. &lt;/span&gt;왜냐하면 컴퓨터의 자원이 현 시대와는 다르게 성능 확장 및 시스템에 대한 접근성이 좋지 않았다. 하지만 현재는 어디에서나 네트워크의 발전과 클라우드 컴퓨팅을 통해 시스템에 접근이 가능하다. 위의 표를 보면, 소프트웨어 아키텍쳐는 1990년대에 크게 관심을 갖기 시작했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면 왜 소프트웨어 아키텍쳐가 관심을 가지게 된건지 알아볼 필요가 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시간이 지남에 따라 소프트웨어는 현대 시대에 스며들어 고객의 요구사항은 &lt;b&gt;복잡도&lt;/b&gt;를 갖고 발전했다.&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;분산 컴퓨팅이 등장하고 그와 맞게 더 잘게 분산 되어진 MSA가 등장하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아키텍쳐 트렌드의 흐름&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. Main-Frame&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. Client/Server&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. Web&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. SOA(Service Oriented Architecture)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. REST&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;6. MSA&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MSA는 공식적인 정의가 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 이를 정리하면서 나의 정리는 'MSA는 분산되어지는 것이다.'라고 생각한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MSA의 특징&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 마이크로 서비스 아키텍처의 서비스들은 독립적인 deploy가 이루어져야한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 서비스의 교체가 쉽다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 서비스 기능별로 분류된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 서비스들은 규모가 작고, 메시지 전달이 가능하며 컨텍스트별로 묶이며 자율적으로 개발되며 독립적으로 전개할 수 있으며 분산적이며 빌드가 되며 자동화된 프로세스들로 출시된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MSA의 장점:&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. 유연한 확장으로 과부화된 서비스에 대해서만 확장이 가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MSA의 단점:&amp;nbsp;&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. 통합 테스트의 어려움이 존재한다.&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-filename=&quot;스크린샷 2022-09-05 오후 3.04.37.png&quot; data-origin-width=&quot;942&quot; data-origin-height=&quot;462&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bA6u0v/btrLuCepuR6/43Jw2YYstW558v8ztu9Pk0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bA6u0v/btrLuCepuR6/43Jw2YYstW558v8ztu9Pk0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bA6u0v/btrLuCepuR6/43Jw2YYstW558v8ztu9Pk0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbA6u0v%2FbtrLuCepuR6%2F43Jw2YYstW558v8ztu9Pk0%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;550&quot; height=&quot;270&quot; data-filename=&quot;스크린샷 2022-09-05 오후 3.04.37.png&quot; data-origin-width=&quot;942&quot; data-origin-height=&quot;462&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 사진을 보면 각각의 클라이언트에서 각각의 다른 서비스에서 다른 DB를 통해 하나의 시스템을 완성하는 것을 볼 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;612&quot; data-origin-height=&quot;413&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cQJI7n/btrLj9RcvaG/eodyj6gqda0oBMOhWn5K20/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cQJI7n/btrLj9RcvaG/eodyj6gqda0oBMOhWn5K20/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cQJI7n/btrLj9RcvaG/eodyj6gqda0oBMOhWn5K20/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcQJI7n%2FbtrLj9RcvaG%2Feodyj6gqda0oBMOhWn5K20%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;456&quot; height=&quot;308&quot; data-origin-width=&quot;612&quot; data-origin-height=&quot;413&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;넷플릭스의 아키텍쳐를 보면 연두색은 서비스이도 서비스들끼리 연결된 모습을 볼 수 있다. 서비스 간의 연결성이 매우 많은 것을 확인 할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;총평&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 IT업계에서 시대를 이끌어가는 대표적인 기업들은 MSA로 개발이 진행된다. 이런 것처럼 &lt;b&gt;나는 MSA가 왜 나오게 되었고 기술의 발전에서 공통된 기술은 무엇인지 고민하며 앞으로 나올 기술에서도 공통된 기술이 무엇인지 생각해보아야 한다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Reference.&lt;/p&gt;
&lt;figure id=&quot;og_1662191634105&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;에스코어&quot; data-og-description=&quot;에스코어는 디지털 혁신을 위한 고급 프로페셔널 서비스를 제공합니다. 매니지먼트 컨설팅과 소프트웨어 테크놀로지 서비스 오퍼링을 살펴보세요.&quot; data-og-host=&quot;s-core.co.kr&quot; data-og-source-url=&quot;https://s-core.co.kr/insight/view/%EB%8B%B9%EC%8B%A0%EC%9D%98-msa%EB%8A%94-%EC%95%88%EB%85%95%ED%95%98%EC%8B%A0%EA%B0%80%EC%9A%94-msa%EB%A5%BC-%EB%B3%B4%EC%99%84%ED%95%98%EB%8A%94-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98-edmevent-drive/&quot; data-og-url=&quot;https://s-core.co.kr/insight/view/%EB%8B%B9%EC%8B%A0%EC%9D%98-msa%EB%8A%94-%EC%95%88%EB%85%95%ED%95%98%EC%8B%A0%EA%B0%80%EC%9A%94-msa%EB%A5%BC-%EB%B3%B4%EC%99%84%ED%95%98%EB%8A%94-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98-edmevent-drive/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/r7plz/hyPGaK6zzT/53rZdv5NjiPWtYccYaTQjk/img.png?width=312&amp;amp;height=158&amp;amp;face=0_0_312_158,https://scrap.kakaocdn.net/dn/byNf6p/hyPFZv2bo7/kDtOvgPZGKLpXyeEf4kNd0/img.png?width=583&amp;amp;height=292&amp;amp;face=0_0_583_292,https://scrap.kakaocdn.net/dn/baWYoJ/hyPF6IHeWY/vlcsk5RBcu92Qs0haxdgTK/img.png?width=492&amp;amp;height=346&amp;amp;face=0_0_492_346&quot;&gt;&lt;a href=&quot;https://s-core.co.kr/insight/view/%EB%8B%B9%EC%8B%A0%EC%9D%98-msa%EB%8A%94-%EC%95%88%EB%85%95%ED%95%98%EC%8B%A0%EA%B0%80%EC%9A%94-msa%EB%A5%BC-%EB%B3%B4%EC%99%84%ED%95%98%EB%8A%94-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98-edmevent-drive/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://s-core.co.kr/insight/view/%EB%8B%B9%EC%8B%A0%EC%9D%98-msa%EB%8A%94-%EC%95%88%EB%85%95%ED%95%98%EC%8B%A0%EA%B0%80%EC%9A%94-msa%EB%A5%BC-%EB%B3%B4%EC%99%84%ED%95%98%EB%8A%94-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98-edmevent-drive/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/r7plz/hyPGaK6zzT/53rZdv5NjiPWtYccYaTQjk/img.png?width=312&amp;amp;height=158&amp;amp;face=0_0_312_158,https://scrap.kakaocdn.net/dn/byNf6p/hyPFZv2bo7/kDtOvgPZGKLpXyeEf4kNd0/img.png?width=583&amp;amp;height=292&amp;amp;face=0_0_583_292,https://scrap.kakaocdn.net/dn/baWYoJ/hyPF6IHeWY/vlcsk5RBcu92Qs0haxdgTK/img.png?width=492&amp;amp;height=346&amp;amp;face=0_0_492_346');&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;s-core.co.kr&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id=&quot;og_1662191440727&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;What are microservices?&quot; data-og-description=&quot;Microservices - also known as the microservice architecture - is an architectural style that structures an application as a collection of loosely coupled services, which implement business capabilities. The microservice architecture enables the continuous &quot; data-og-host=&quot;microservices.io&quot; data-og-source-url=&quot;https://microservices.io/&quot; data-og-url=&quot;http://microservices.io/index.html&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/QSTxH/hyPFZbJvXu/6Fvf1dPIcfDezOIMqKjaXk/img.png?width=1034&amp;amp;height=689&amp;amp;face=0_0_1034_689,https://scrap.kakaocdn.net/dn/bTDxfw/hyPF1HoafC/SntdyjAmMumx7SC6D9Yk10/img.jpg?width=720&amp;amp;height=903&amp;amp;face=0_0_720_903,https://scrap.kakaocdn.net/dn/blyr40/hyPF0obj9f/bjeM3CxxYqnSyNZgRKmJ4K/img.jpg?width=500&amp;amp;height=389&amp;amp;face=0_0_500_389&quot;&gt;&lt;a href=&quot;https://microservices.io/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://microservices.io/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/QSTxH/hyPFZbJvXu/6Fvf1dPIcfDezOIMqKjaXk/img.png?width=1034&amp;amp;height=689&amp;amp;face=0_0_1034_689,https://scrap.kakaocdn.net/dn/bTDxfw/hyPF1HoafC/SntdyjAmMumx7SC6D9Yk10/img.jpg?width=720&amp;amp;height=903&amp;amp;face=0_0_720_903,https://scrap.kakaocdn.net/dn/blyr40/hyPF0obj9f/bjeM3CxxYqnSyNZgRKmJ4K/img.jpg?width=500&amp;amp;height=389&amp;amp;face=0_0_500_389');&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;What are microservices?&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Microservices - also known as the microservice architecture - is an architectural style that structures an application as a collection of loosely coupled services, which implement business capabilities. The microservice architecture enables the continuous&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;microservices.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>Micro Service Architecture</category>
      <category>Architecture</category>
      <category>MSA</category>
      <category>software</category>
      <author>큐범</author>
      <guid isPermaLink="true">https://kbcoding.tistory.com/93</guid>
      <comments>https://kbcoding.tistory.com/93#entry93comment</comments>
      <pubDate>Mon, 12 Sep 2022 16:07:10 +0900</pubDate>
    </item>
    <item>
      <title>[Network] URI, URL, URN</title>
      <link>https://kbcoding.tistory.com/92</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;URI,&amp;nbsp;URL,&amp;nbsp;URN&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;URI는 로케이터(&lt;b&gt;l&lt;/b&gt;ocator), 이름(&lt;b&gt;n&lt;/b&gt;ame) 또는 둘다 추가로 분류 될 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-09-05 오전 12.24.27.png&quot; data-origin-width=&quot;1066&quot; data-origin-height=&quot;632&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cFj5Et/btrLihXkiCv/Hmaft1IGj5E0oHIoaVcqS1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cFj5Et/btrLihXkiCv/Hmaft1IGj5E0oHIoaVcqS1/img.png&quot; data-alt=&quot;https://www.ietf.org/rfc/rfc3986.txt - 1.1.3. URI, URL, and URN&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cFj5Et/btrLihXkiCv/Hmaft1IGj5E0oHIoaVcqS1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcFj5Et%2FbtrLihXkiCv%2FHmaft1IGj5E0oHIoaVcqS1%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;550&quot; height=&quot;326&quot; data-filename=&quot;스크린샷 2022-09-05 오전 12.24.27.png&quot; data-origin-width=&quot;1066&quot; data-origin-height=&quot;632&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://www.ietf.org/rfc/rfc3986.txt - 1.1.3. URI, URL, and URN&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;URI: 리소스의 식별&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;URL: 리소스의 위치&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;URN: 리소스의 이름&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-09-05 오전 12.25.51.png&quot; data-origin-width=&quot;1664&quot; data-origin-height=&quot;722&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/YF59H/btrLj95toat/Gy8qvDL2Sb18aAOvtQzR90/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/YF59H/btrLj95toat/Gy8qvDL2Sb18aAOvtQzR90/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/YF59H/btrLj95toat/Gy8qvDL2Sb18aAOvtQzR90/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FYF59H%2FbtrLj95toat%2FGy8qvDL2Sb18aAOvtQzR90%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;550&quot; height=&quot;239&quot; data-filename=&quot;스크린샷 2022-09-05 오전 12.25.51.png&quot; data-origin-width=&quot;1664&quot; data-origin-height=&quot;722&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;h2 data-ke-size=&quot;size26&quot;&gt;URI&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;U&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;niform: &lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;리소스 식별하는 통일된 방식&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;R&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;esource: &lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;자원&lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;, URI&lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;로 식별할 수 있는 모든 것&lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;제한 없음&lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;I&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;dentifier: &lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;다른 항목과 구분하는데 필요한 정보&lt;/span&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;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;URL, URN&lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;URL - Locator: 리소스가 있는 위치를 지정한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;URN - Name: 리소스에 이름을 부여한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;위치는 변할 수 있지만, 이름은 변하지 않는다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;URN 이름만으로 실제 리소스를 찾을 수 있는 방법이 보편화 되지 않는다.&lt;/span&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;URL분석&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;https://www.google.com/search?q=hello&amp;amp;hl=ko&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;URL&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;scheme://[userinfo@]host[:port][/path][?query][#fragment]&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;&lt;/span&gt;https://www.google.com:443/search?q=hello&amp;amp;hl=ko&lt;/p&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;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;프로토콜&lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;(https) &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;호스트명&lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;(www.google.com) &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;포트 번호&lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;(443)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;패스&lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;(/search)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;쿼리 파라미터&lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;(q=hello&amp;amp;hl=ko)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;URL - scheme&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;b&gt;scheme&lt;/b&gt;://[userinfo@]host[:port][/path][?query][#fragment]&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;https&lt;/b&gt;://www.google.com:443/search?q=hello&amp;amp;hl=ko&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 주로 프로토콜을 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 프로토콜은 어떤 방식으로 자원에 접근할 것인가 하는 약속 규칙이다. 예를들어, Http, Https, ftp 등이 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- http는 80포트, https는 443포트를 주로 사용하고 &lt;b&gt;포트는 생략이 가능하다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- https는 http에 보안 추가한 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;URL-userinfo&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;scheme://&lt;b&gt;[userinfo@]&lt;/b&gt;host[:port][/path][?query][#fragment]&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;https://www.google.com:443/search?q=hello&amp;amp;hl=ko&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- URL에 사용자 정보를 포함해서 인증하는 방식이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;URL-host&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;scheme://[userinfo@]&lt;b&gt;host&lt;/b&gt;[:port][/path][?query][#fragment]&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;https://&lt;b&gt;www.google.com&lt;/b&gt;:443/search?q=hello&amp;amp;hl=ko&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 호스트명으로 도메인명 또는 IP 주소를 직접 사용가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;URL-PORT&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;scheme://[userinfo@]host&lt;b&gt;[:port]&lt;/b&gt;[/path][?query][#fragment]&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;https://www.google.com:&lt;b&gt;443&lt;/b&gt;/search?q=hello&amp;amp;hl=ko&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 접속 포트로 일반적으로 생략하며 생략시에는 http는 80, https는 443을 넣는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;URL-path&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;scheme://[userinfo@]host[:port]&lt;b&gt;[/path]&lt;/b&gt;[?query][#fragment]&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;https://www.google.com:443/&lt;b&gt;search&lt;/b&gt;?q=hello&amp;amp;hl=ko&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 리소스 경로(path), 계층적 구조&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 예를들어 /home/file1.jpg.&amp;nbsp; &amp;nbsp; &amp;nbsp; /members/100.&amp;nbsp; &amp;nbsp; &amp;nbsp;/items/iphone12.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;URL-query&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;scheme://[userinfo@]host[:port][/path]&lt;b&gt;[?query]&lt;/b&gt;[#fragment]&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;https://www.google.com:443/search&lt;b&gt;?q=hello&amp;amp;hl=ko&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- key = value형태로 ?로 시작해서 &amp;amp;로 추가 가능하다. Ex)keyA=valueA&amp;amp;keyB=valueB&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- query parameter, query string 등으로 불린다. 웹서버에 제공하는 파라미터, 문자 형태이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;URL-fragment&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;scheme://[userinfo@]host[:port][/path][?query]&lt;b&gt;[#fragment]&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;https://docs.spring.io/spring-boot/docs/current/reference/html&lt;b&gt;#getting-&lt;/b&gt;&lt;/span&gt;&lt;b&gt;&lt;span&gt;started.html&lt;/span&gt;&lt;span&gt;#getting-started-introducing-spring-boot&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;- html 내부 북마크 등에 사용되며 서버에 전송하는 정보가 아니다.&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;Reference.&lt;/p&gt;
&lt;figure id=&quot;og_1662830313420&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;모든 개발자를 위한 HTTP 웹 기본 지식 - 인프런 | 강의&quot; data-og-description=&quot;실무에 꼭 필요한 HTTP 핵심 기능과 올바른 HTTP API 설계 방법을 학습합니다., - 강의 소개 | 인프런...&quot; data-og-host=&quot;www.inflearn.com&quot; data-og-source-url=&quot;https://www.inflearn.com/course/http-%EC%9B%B9-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC/dashboard&quot; data-og-url=&quot;https://www.inflearn.com/course/http-%EC%9B%B9-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/p2uCj/hyPHlL8rnP/FSHVAfR7vB6LuDscYKm2L0/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/cup7EJ/hyPHuPQztK/8dojym58kWgVGYwtbk2PIK/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/bz75cR/hyPF0CPhif/43fiyMsmSdrR0alrfh5msk/img.jpg?width=1200&amp;amp;height=666&amp;amp;face=0_0_1200_666&quot;&gt;&lt;a href=&quot;https://www.inflearn.com/course/http-%EC%9B%B9-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC/dashboard&quot; data-source-url=&quot;https://www.inflearn.com/course/http-%EC%9B%B9-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC/dashboard&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/p2uCj/hyPHlL8rnP/FSHVAfR7vB6LuDscYKm2L0/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/cup7EJ/hyPHuPQztK/8dojym58kWgVGYwtbk2PIK/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/bz75cR/hyPF0CPhif/43fiyMsmSdrR0alrfh5msk/img.jpg?width=1200&amp;amp;height=666&amp;amp;face=0_0_1200_666');&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;모든 개발자를 위한 HTTP 웹 기본 지식 - 인프런 | 강의&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;실무에 꼭 필요한 HTTP 핵심 기능과 올바른 HTTP API 설계 방법을 학습합니다., - 강의 소개 | 인프런...&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.inflearn.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>Network</category>
      <category>Network</category>
      <category>URI</category>
      <category>url</category>
      <category>URN</category>
      <author>큐범</author>
      <guid isPermaLink="true">https://kbcoding.tistory.com/92</guid>
      <comments>https://kbcoding.tistory.com/92#entry92comment</comments>
      <pubDate>Sun, 11 Sep 2022 01:43:38 +0900</pubDate>
    </item>
    <item>
      <title>[Network] PORT, DNS(Domain Name System)</title>
      <link>https://kbcoding.tistory.com/91</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;PORT의 탄생 배경&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하나의 IP에서 한번에 둘 이상의 연결을 해야하는 경우는&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-09-05 오전 12.20.07.png&quot; data-origin-width=&quot;2074&quot; data-origin-height=&quot;976&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tSb0e/btrLhZo2dZK/HKflE8ZplgpPpcFYpFKYV1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tSb0e/btrLhZo2dZK/HKflE8ZplgpPpcFYpFKYV1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tSb0e/btrLhZo2dZK/HKflE8ZplgpPpcFYpFKYV1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtSb0e%2FbtrLhZo2dZK%2FHKflE8ZplgpPpcFYpFKYV1%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;550&quot; height=&quot;259&quot; data-filename=&quot;스크린샷 2022-09-05 오전 12.20.07.png&quot; data-origin-width=&quot;2074&quot; data-origin-height=&quot;976&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TCP/IP 패킷 정보를 보면 출발지 PORT와 목적지 PORT를 넣어서 패킷 보내기에 PORT를 알 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서, 아래와 같은 방식으로 서버와 PORT를 포함해 통신한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-09-05 오전 12.21.10.png&quot; data-origin-width=&quot;1930&quot; data-origin-height=&quot;1034&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bpxtHA/btrLqXXhv2k/A03f7rTrYpK7kkK3sRdii0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bpxtHA/btrLqXXhv2k/A03f7rTrYpK7kkK3sRdii0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bpxtHA/btrLqXXhv2k/A03f7rTrYpK7kkK3sRdii0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbpxtHA%2FbtrLqXXhv2k%2FA03f7rTrYpK7kkK3sRdii0%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;550&quot; height=&quot;295&quot; data-filename=&quot;스크린샷 2022-09-05 오전 12.21.10.png&quot; data-origin-width=&quot;1930&quot; data-origin-height=&quot;1034&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;화상통화의 경우,&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클라이언트에서 서버로 200.200.200.2&lt;b&gt;:32202 &lt;/b&gt;로 요청을 보내고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서버에서 클라이언트로 100.100.100.1:21000로 응답을 보낸다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PORT&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 0 ~ 65535 할당 가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 0 ~ 1023 잘 알려진 포트로 사용하지 않는 것이 좋다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;- FTP - 20,21&lt;/li&gt;
&lt;li&gt;TELNET - 23&lt;/li&gt;
&lt;li&gt;HTTP - 80&lt;/li&gt;
&lt;li&gt;HTTPS -443&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DNS 탄생 배경&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;IP는 기억하기 어렵고, 변경될 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DNS&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;도메인 네임 시스템(Domain Name System)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전화번호부 같은 역할로 도메인 명을 IP 주소로 변환해주는 역할을 한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-09-05 오전 12.18.39.png&quot; data-origin-width=&quot;796&quot; data-origin-height=&quot;464&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cqTnKP/btrLiCNF74b/tcFK3IfLZ2eof3uZ61uQW1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cqTnKP/btrLiCNF74b/tcFK3IfLZ2eof3uZ61uQW1/img.png&quot; data-alt=&quot;DNS 동작 방식&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cqTnKP/btrLiCNF74b/tcFK3IfLZ2eof3uZ61uQW1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcqTnKP%2FbtrLiCNF74b%2FtcFK3IfLZ2eof3uZ61uQW1%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;550&quot; height=&quot;321&quot; data-filename=&quot;스크린샷 2022-09-05 오전 12.18.39.png&quot; data-origin-width=&quot;796&quot; data-origin-height=&quot;464&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;DNS 동작 방식&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Reference.&lt;/p&gt;
&lt;figure id=&quot;og_1662304908906&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;모든 개발자를 위한 HTTP 웹 기본 지식 - 인프런 | 강의&quot; data-og-description=&quot;실무에 꼭 필요한 HTTP 핵심 기능과 올바른 HTTP API 설계 방법을 학습합니다., - 강의 소개 | 인프런...&quot; data-og-host=&quot;www.inflearn.com&quot; data-og-source-url=&quot;https://www.inflearn.com/course/http-%EC%9B%B9-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC/dashboard&quot; data-og-url=&quot;https://www.inflearn.com/course/http-%EC%9B%B9-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/p2uCj/hyPHlL8rnP/FSHVAfR7vB6LuDscYKm2L0/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/cup7EJ/hyPHuPQztK/8dojym58kWgVGYwtbk2PIK/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/bz75cR/hyPF0CPhif/43fiyMsmSdrR0alrfh5msk/img.jpg?width=1200&amp;amp;height=666&amp;amp;face=0_0_1200_666&quot;&gt;&lt;a href=&quot;https://www.inflearn.com/course/http-%EC%9B%B9-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC/dashboard&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.inflearn.com/course/http-%EC%9B%B9-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC/dashboard&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/p2uCj/hyPHlL8rnP/FSHVAfR7vB6LuDscYKm2L0/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/cup7EJ/hyPHuPQztK/8dojym58kWgVGYwtbk2PIK/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/bz75cR/hyPF0CPhif/43fiyMsmSdrR0alrfh5msk/img.jpg?width=1200&amp;amp;height=666&amp;amp;face=0_0_1200_666');&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;모든 개발자를 위한 HTTP 웹 기본 지식 - 인프런 | 강의&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;실무에 꼭 필요한 HTTP 핵심 기능과 올바른 HTTP API 설계 방법을 학습합니다., - 강의 소개 | 인프런...&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.inflearn.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>Network</category>
      <category>DNS</category>
      <category>ip</category>
      <category>Network</category>
      <category>TCP</category>
      <category>UDP</category>
      <author>큐범</author>
      <guid isPermaLink="true">https://kbcoding.tistory.com/91</guid>
      <comments>https://kbcoding.tistory.com/91#entry91comment</comments>
      <pubDate>Sat, 10 Sep 2022 01:22:08 +0900</pubDate>
    </item>
    <item>
      <title>[Network] TCP, UDP</title>
      <link>https://kbcoding.tistory.com/90</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;TCP 전송 제어 프로토콜&lt;/b&gt;(Transmission Control Protocol)&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;TCP 특징&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 연결지향 - &lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;TCP 3 way handshake (&lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;가상 연결&lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;)&lt;/span&gt;&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. 순서 보장&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 신뢰할 수 있는 프로토콜&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. 현재는 대부분 TCP 사용&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;TCP/IP패킷 정보&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-09-05 오전 12.02.48.png&quot; data-origin-width=&quot;1782&quot; data-origin-height=&quot;1044&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bGhiV3/btrLr3QwN51/j5ZHvJc7cnZm09negemL6K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bGhiV3/btrLr3QwN51/j5ZHvJc7cnZm09negemL6K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bGhiV3/btrLr3QwN51/j5ZHvJc7cnZm09negemL6K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbGhiV3%2FbtrLr3QwN51%2Fj5ZHvJc7cnZm09negemL6K%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;341&quot; height=&quot;200&quot; data-filename=&quot;스크린샷 2022-09-05 오전 12.02.48.png&quot; data-origin-width=&quot;1782&quot; data-origin-height=&quot;1044&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;h4 data-ke-size=&quot;size20&quot;&gt;TCP 3 way handshake&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SYN은 synchronized로 동기화라는 뜻이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ACK는 acknowledgement code 확인이라는 뜻이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-09-04 오후 11.57.41.png&quot; data-origin-width=&quot;1956&quot; data-origin-height=&quot;1094&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wDQJu/btrLotoAIW6/RJ7Q49SQybtkAtrdAqDyd1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wDQJu/btrLotoAIW6/RJ7Q49SQybtkAtrdAqDyd1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wDQJu/btrLotoAIW6/RJ7Q49SQybtkAtrdAqDyd1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwDQJu%2FbtrLotoAIW6%2FRJ7Q49SQybtkAtrdAqDyd1%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;500&quot; height=&quot;280&quot; data-filename=&quot;스크린샷 2022-09-04 오후 11.57.41.png&quot; data-origin-width=&quot;1956&quot; data-origin-height=&quot;1094&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;h4 data-ke-size=&quot;size20&quot;&gt;데이터 전달 보증&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-09-05 오전 12.01.36.png&quot; data-origin-width=&quot;1778&quot; data-origin-height=&quot;536&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tlayX/btrLhJ020eR/BoHk8DtS8Q8kkxgWquUtEk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tlayX/btrLhJ020eR/BoHk8DtS8Q8kkxgWquUtEk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tlayX/btrLhJ020eR/BoHk8DtS8Q8kkxgWquUtEk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtlayX%2FbtrLhJ020eR%2FBoHk8DtS8Q8kkxgWquUtEk%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;500&quot; height=&quot;151&quot; data-filename=&quot;스크린샷 2022-09-05 오전 12.01.36.png&quot; data-origin-width=&quot;1778&quot; data-origin-height=&quot;536&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;h4 data-ke-size=&quot;size20&quot;&gt;순서 보장&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-09-05 오전 12.01.48.png&quot; data-origin-width=&quot;1912&quot; data-origin-height=&quot;626&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bPsfWx/btrLihwdQCf/LCvoYKr2CObWDTJwaG9bvK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bPsfWx/btrLihwdQCf/LCvoYKr2CObWDTJwaG9bvK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bPsfWx/btrLihwdQCf/LCvoYKr2CObWDTJwaG9bvK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbPsfWx%2FbtrLihwdQCf%2FLCvoYKr2CObWDTJwaG9bvK%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;500&quot; height=&quot;164&quot; data-filename=&quot;스크린샷 2022-09-05 오전 12.01.48.png&quot; data-origin-width=&quot;1912&quot; data-origin-height=&quot;626&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;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;UDP 사용자 데이터그램 프로토콜&lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;(User Datagram Protocol)&lt;/span&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;UDP 특징&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 하얀 도화지에 비유해서 기능이 거의 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 연결 지향 - TCP 3 way handshake를 지원하지 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 데이터 전달 보증을 지원하지 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 순서를 보장하지 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. 데이터 전달 및 순서가 보장되지 않지만, 단순하고 빠르다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;UDP -&amp;gt; IP와 거의 같다. +PORT +체크섬 정도만 추가하고 애플리케이션에서 추가 작업이 필요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Reference.&lt;/p&gt;
&lt;figure id=&quot;og_1662304054967&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;모든 개발자를 위한 HTTP 웹 기본 지식 - 인프런 | 강의&quot; data-og-description=&quot;실무에 꼭 필요한 HTTP 핵심 기능과 올바른 HTTP API 설계 방법을 학습합니다., - 강의 소개 | 인프런...&quot; data-og-host=&quot;www.inflearn.com&quot; data-og-source-url=&quot;https://www.inflearn.com/course/http-%EC%9B%B9-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC/dashboard&quot; data-og-url=&quot;https://www.inflearn.com/course/http-%EC%9B%B9-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/p2uCj/hyPHlL8rnP/FSHVAfR7vB6LuDscYKm2L0/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/cup7EJ/hyPHuPQztK/8dojym58kWgVGYwtbk2PIK/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/bz75cR/hyPF0CPhif/43fiyMsmSdrR0alrfh5msk/img.jpg?width=1200&amp;amp;height=666&amp;amp;face=0_0_1200_666&quot;&gt;&lt;a href=&quot;https://www.inflearn.com/course/http-%EC%9B%B9-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC/dashboard&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.inflearn.com/course/http-%EC%9B%B9-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC/dashboard&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/p2uCj/hyPHlL8rnP/FSHVAfR7vB6LuDscYKm2L0/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/cup7EJ/hyPHuPQztK/8dojym58kWgVGYwtbk2PIK/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/bz75cR/hyPF0CPhif/43fiyMsmSdrR0alrfh5msk/img.jpg?width=1200&amp;amp;height=666&amp;amp;face=0_0_1200_666');&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;모든 개발자를 위한 HTTP 웹 기본 지식 - 인프런 | 강의&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;실무에 꼭 필요한 HTTP 핵심 기능과 올바른 HTTP API 설계 방법을 학습합니다., - 강의 소개 | 인프런...&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.inflearn.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>Network</category>
      <category>ip</category>
      <category>Network</category>
      <category>TCP</category>
      <category>UDP</category>
      <author>큐범</author>
      <guid isPermaLink="true">https://kbcoding.tistory.com/90</guid>
      <comments>https://kbcoding.tistory.com/90#entry90comment</comments>
      <pubDate>Fri, 9 Sep 2022 01:07:51 +0900</pubDate>
    </item>
    <item>
      <title>[Network] 인터넷 네트워크</title>
      <link>https://kbcoding.tistory.com/89</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;인터넷에서 컴퓨터 통신하는 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예) 클라이언트가 서버로 부터 통신하는 방법&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-09-04 오후 11.36.53.png&quot; data-origin-width=&quot;755&quot; data-origin-height=&quot;201&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bXMXRm/btrLjiIdkeP/XbYSfCFmBa07pixKIPkwzk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bXMXRm/btrLjiIdkeP/XbYSfCFmBa07pixKIPkwzk/img.png&quot; data-alt=&quot; &quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bXMXRm/btrLjiIdkeP/XbYSfCFmBa07pixKIPkwzk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbXMXRm%2FbtrLjiIdkeP%2FXbYSfCFmBa07pixKIPkwzk%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;383&quot; height=&quot;102&quot; data-filename=&quot;스크린샷 2022-09-04 오후 11.36.53.png&quot; data-origin-width=&quot;755&quot; data-origin-height=&quot;201&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt; &lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-09-04 오후 11.39.09.png&quot; data-origin-width=&quot;696&quot; data-origin-height=&quot;194&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cY3JP3/btrLmyp80Yi/bB8XmkxSO4a5rHy0NUGCp1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cY3JP3/btrLmyp80Yi/bB8XmkxSO4a5rHy0NUGCp1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cY3JP3/btrLmyp80Yi/bB8XmkxSO4a5rHy0NUGCp1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcY3JP3%2FbtrLmyp80Yi%2FbB8XmkxSO4a5rHy0NUGCp1%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;387&quot; height=&quot;108&quot; data-filename=&quot;스크린샷 2022-09-04 오후 11.39.09.png&quot; data-origin-width=&quot;696&quot; data-origin-height=&quot;194&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서버는 해당 메시지를 받고 OK 라는 반환을 한다.&lt;/p&gt;
&lt;p data-ke-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;인터넷 망에는 수 많은 노드가 존재하는데 다음과 같이 각각의 IP(Internet Protocol)를 부여한다. 실제 생활에 적용을 하면, 집 주소와 같은 역할을 한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-09-04 오후 11.41.03.png&quot; data-origin-width=&quot;873&quot; data-origin-height=&quot;380&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/crez9m/btrLj95seM4/J3UEDcXIKywLvUkzoyale0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/crez9m/btrLj95seM4/J3UEDcXIKywLvUkzoyale0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/crez9m/btrLj95seM4/J3UEDcXIKywLvUkzoyale0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcrez9m%2FbtrLj95seM4%2FJ3UEDcXIKywLvUkzoyale0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;612&quot; height=&quot;266&quot; data-filename=&quot;스크린샷 2022-09-04 오후 11.41.03.png&quot; data-origin-width=&quot;873&quot; data-origin-height=&quot;380&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;h4 data-ke-size=&quot;size20&quot;&gt;IP의 역할&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;지정한 IP 주소(IP Address)에 데이터를 전달한다.&lt;/li&gt;
&lt;li&gt;패킷(Packet)이라는 통신 단위로 데이터 전달한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면 아래와 같이 클라이언트에서 &quot;Hello, world!&quot;라는 문구를 보내는 경우, 인터넷의 노드를 통해 서버로 전달한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-09-04 오후 11.43.14.png&quot; data-origin-width=&quot;831&quot; data-origin-height=&quot;414&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wg8dK/btrLhsZvQY8/qWZZpDmQITd7ZEnoVB6AHk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wg8dK/btrLhsZvQY8/qWZZpDmQITd7ZEnoVB6AHk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wg8dK/btrLhsZvQY8/qWZZpDmQITd7ZEnoVB6AHk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fwg8dK%2FbtrLhsZvQY8%2FqWZZpDmQITd7ZEnoVB6AHk%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;560&quot; height=&quot;279&quot; data-filename=&quot;스크린샷 2022-09-04 오후 11.43.14.png&quot; data-origin-width=&quot;831&quot; data-origin-height=&quot;414&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 다음 아래와 같이 서버는 다시 클라이언트에게 OK를 반환한다. 즉, 전달이 잘 되었다는 것을 알려준다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-09-04 오후 11.44.11.png&quot; data-origin-width=&quot;846&quot; data-origin-height=&quot;414&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bPsmTk/btrLmxdIIjC/Jao1ssja2ldZrzmWXCcKb1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bPsmTk/btrLmxdIIjC/Jao1ssja2ldZrzmWXCcKb1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bPsmTk/btrLmxdIIjC/Jao1ssja2ldZrzmWXCcKb1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbPsmTk%2FbtrLmxdIIjC%2FJao1ssja2ldZrzmWXCcKb1%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;576&quot; height=&quot;282&quot; data-filename=&quot;스크린샷 2022-09-04 오후 11.44.11.png&quot; data-origin-width=&quot;846&quot; data-origin-height=&quot;414&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;h4 data-ke-size=&quot;size20&quot;&gt;IP 프로토콜의 한계&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. 비연결성&lt;/b&gt;&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-filename=&quot;스크린샷 2022-09-04 오후 11.48.08.png&quot; data-origin-width=&quot;874&quot; data-origin-height=&quot;406&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dCKdmp/btrLk4pi55u/5HiZedT77zkQkBtWXRd231/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dCKdmp/btrLk4pi55u/5HiZedT77zkQkBtWXRd231/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dCKdmp/btrLk4pi55u/5HiZedT77zkQkBtWXRd231/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdCKdmp%2FbtrLk4pi55u%2F5HiZedT77zkQkBtWXRd231%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;541&quot; height=&quot;251&quot; data-filename=&quot;스크린샷 2022-09-04 오후 11.48.08.png&quot; data-origin-width=&quot;874&quot; data-origin-height=&quot;406&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. 비신뢰성&lt;/b&gt;&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-filename=&quot;스크린샷 2022-09-04 오후 11.48.19.png&quot; data-origin-width=&quot;847&quot; data-origin-height=&quot;406&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bcPSeP/btrLj9RYXld/qBD3dbAsQ56DzOBTOXiy9K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bcPSeP/btrLj9RYXld/qBD3dbAsQ56DzOBTOXiy9K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bcPSeP/btrLj9RYXld/qBD3dbAsQ56DzOBTOXiy9K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbcPSeP%2FbtrLj9RYXld%2FqBD3dbAsQ56DzOBTOXiy9K%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;536&quot; height=&quot;257&quot; data-filename=&quot;스크린샷 2022-09-04 오후 11.48.19.png&quot; data-origin-width=&quot;847&quot; data-origin-height=&quot;406&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-09-04 오후 11.48.43.png&quot; data-origin-width=&quot;903&quot; data-origin-height=&quot;411&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c4fD3Y/btrLk3KHVgv/fMmKKCYONiWjPz6IlQ5pQk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c4fD3Y/btrLk3KHVgv/fMmKKCYONiWjPz6IlQ5pQk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c4fD3Y/btrLk3KHVgv/fMmKKCYONiWjPz6IlQ5pQk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc4fD3Y%2FbtrLk3KHVgv%2FfMmKKCYONiWjPz6IlQ5pQk%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;521&quot; height=&quot;237&quot; data-filename=&quot;스크린샷 2022-09-04 오후 11.48.43.png&quot; data-origin-width=&quot;903&quot; data-origin-height=&quot;411&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. 프로그램 구분&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp;같은 IP를 사용하는 서버에서 통신하는 애플리케이션이 둘 이상이면 구분을 할 수 없다.&lt;/p&gt;
&lt;p data-ke-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;IP 프로토콜의 한계를 극복할 수 있는 것이 TCP, UDP이다.&lt;/p&gt;
&lt;p data-ke-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;Reference.&lt;/p&gt;
&lt;figure id=&quot;og_1662303030772&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;모든 개발자를 위한 HTTP 웹 기본 지식 - 인프런 | 강의&quot; data-og-description=&quot;실무에 꼭 필요한 HTTP 핵심 기능과 올바른 HTTP API 설계 방법을 학습합니다., - 강의 소개 | 인프런...&quot; data-og-host=&quot;www.inflearn.com&quot; data-og-source-url=&quot;https://www.inflearn.com/course/http-%EC%9B%B9-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC/dashboard&quot; data-og-url=&quot;https://www.inflearn.com/course/http-%EC%9B%B9-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/p2uCj/hyPHlL8rnP/FSHVAfR7vB6LuDscYKm2L0/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/cup7EJ/hyPHuPQztK/8dojym58kWgVGYwtbk2PIK/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/bz75cR/hyPF0CPhif/43fiyMsmSdrR0alrfh5msk/img.jpg?width=1200&amp;amp;height=666&amp;amp;face=0_0_1200_666&quot;&gt;&lt;a href=&quot;https://www.inflearn.com/course/http-%EC%9B%B9-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC/dashboard&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.inflearn.com/course/http-%EC%9B%B9-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC/dashboard&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/p2uCj/hyPHlL8rnP/FSHVAfR7vB6LuDscYKm2L0/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/cup7EJ/hyPHuPQztK/8dojym58kWgVGYwtbk2PIK/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/bz75cR/hyPF0CPhif/43fiyMsmSdrR0alrfh5msk/img.jpg?width=1200&amp;amp;height=666&amp;amp;face=0_0_1200_666');&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;모든 개발자를 위한 HTTP 웹 기본 지식 - 인프런 | 강의&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;실무에 꼭 필요한 HTTP 핵심 기능과 올바른 HTTP API 설계 방법을 학습합니다., - 강의 소개 | 인프런...&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.inflearn.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>Network</category>
      <category>ip</category>
      <category>Network</category>
      <category>protocol</category>
      <category>TCP</category>
      <category>UDP</category>
      <category>인터넷</category>
      <author>큐범</author>
      <guid isPermaLink="true">https://kbcoding.tistory.com/89</guid>
      <comments>https://kbcoding.tistory.com/89#entry89comment</comments>
      <pubDate>Fri, 9 Sep 2022 00:51:29 +0900</pubDate>
    </item>
    <item>
      <title>[Cloud] 스케일업(Scale-up)과 스케일 아웃(Scale-out)</title>
      <link>https://kbcoding.tistory.com/88</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;스케일링에는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;스케일업, 스케일아웃&lt;/b&gt;이 존재한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Scale up은&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;인스턴스의&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;성능을 늘리는&lt;/b&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;상황이며&lt;b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;수직 스케일링&lt;/b&gt;이라고도 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-09-03 오후 3.45.14.png&quot; data-origin-width=&quot;1122&quot; data-origin-height=&quot;514&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b9Z2yz/btrLjkrK5Sv/C7IChMhKbZj3fFrr3Ic3gk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b9Z2yz/btrLjkrK5Sv/C7IChMhKbZj3fFrr3Ic3gk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b9Z2yz/btrLjkrK5Sv/C7IChMhKbZj3fFrr3Ic3gk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb9Z2yz%2FbtrLjkrK5Sv%2FC7IChMhKbZj3fFrr3Ic3gk%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;458&quot; height=&quot;210&quot; data-filename=&quot;스크린샷 2022-09-03 오후 3.45.14.png&quot; data-origin-width=&quot;1122&quot; data-origin-height=&quot;514&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&gt;반면, 스케일 아웃은&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;물리적인 규모&lt;/b&gt;를 늘리 것이며&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;수평 스케일링&lt;/b&gt;이라고도 한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-09-03 오후 3.47.16.png&quot; data-origin-width=&quot;876&quot; data-origin-height=&quot;742&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/IQh0n/btrLg8sFKtg/kg9kGNhWS5RzRxZMVRKJRk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/IQh0n/btrLg8sFKtg/kg9kGNhWS5RzRxZMVRKJRk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/IQh0n/btrLg8sFKtg/kg9kGNhWS5RzRxZMVRKJRk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FIQh0n%2FbtrLg8sFKtg%2Fkg9kGNhWS5RzRxZMVRKJRk%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;293&quot; height=&quot;248&quot; data-filename=&quot;스크린샷 2022-09-03 오후 3.47.16.png&quot; data-origin-width=&quot;876&quot; data-origin-height=&quot;742&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;스케일 업과 스케일 아웃에 대한 정리&lt;/h4&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&amp;nbsp;&lt;/td&gt;
&lt;td&gt;스케일업(수직 스케일링)&lt;/td&gt;
&lt;td&gt;스케일아웃(수평 스케일링)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;확장성&lt;/td&gt;
&lt;td&gt;성능 확장에 한계가 있다.&lt;/td&gt;
&lt;td&gt;지속적 확장이 가능하다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;서버비용&lt;/td&gt;
&lt;td&gt;성능 증가에 따른 비용 증가폭이 크며, 일반적으로 비용부담이 크다.&lt;/td&gt;
&lt;td&gt;비교적 저렴한 서버를 사용하므로 일반적으로 비용부담이 적다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;운영비용&lt;/td&gt;
&lt;td&gt;관리 편의성이나 운영비용은 스케일업에 따라 큰 변화는 없다.&lt;/td&gt;
&lt;td&gt;대수가 늘어날수록 관리편의성이 떨어지며, 서버의 상면비용을 포함한 운영비용이 증가한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;장애&lt;/td&gt;
&lt;td&gt;한대의 서버에 부하가 집중되는 만큼 장애시 장애 영향도가 크다.&lt;/td&gt;
&lt;td&gt;읽기/쓰기가 여러대의 서버에 분산되어 처림됨으로 장애 시 전면 장애의 가능성이 적다.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Cloud</category>
      <category>Cloud</category>
      <category>Scale</category>
      <category>Scale-out</category>
      <category>scale-up</category>
      <author>큐범</author>
      <guid isPermaLink="true">https://kbcoding.tistory.com/88</guid>
      <comments>https://kbcoding.tistory.com/88#entry88comment</comments>
      <pubDate>Thu, 8 Sep 2022 17:10:14 +0900</pubDate>
    </item>
    <item>
      <title>[Cloud] 오토 스케일링(Auto Scaling)</title>
      <link>https://kbcoding.tistory.com/87</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;오토 스케일링(Auto Scaling)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Auto = 자동&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Scaling = [컴퓨터] 크기 조정&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;자동으로 크기를 조정&lt;/b&gt; 즉, 컴퓨터의 크기(성능)을 탄력적으로 축소 확장을 할 수 있는 유연성을 말한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오토 스케일링은 클라우드의 CPU, Memory, Traffic과 같이 증가되는 특정 시간 및 상황에 알맞게 시스템이 자동으로 오토 스케일리을 통해 시스템의 부하를 막는다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-09-03 오후 3.55.50.png&quot; data-origin-width=&quot;2416&quot; data-origin-height=&quot;1614&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/epRkZZ/btrLgRSisT3/0qrpkqoIQtKR7nmtWDA9Ik/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/epRkZZ/btrLgRSisT3/0qrpkqoIQtKR7nmtWDA9Ik/img.png&quot; data-alt=&quot;실제 사용중인 EC2 모니터링&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/epRkZZ/btrLgRSisT3/0qrpkqoIQtKR7nmtWDA9Ik/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FepRkZZ%2FbtrLgRSisT3%2F0qrpkqoIQtKR7nmtWDA9Ik%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;531&quot; height=&quot;355&quot; data-filename=&quot;스크린샷 2022-09-03 오후 3.55.50.png&quot; data-origin-width=&quot;2416&quot; data-origin-height=&quot;1614&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;실제 사용중인 EC2 모니터링&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대표적인 클라우드 제공 기업(CSP) AWS의 오토 스케일링을 보면 간단하게 EC2, DB, Aurora 등 리소스에 대한 규모 조정 계획을 수립을 통해 사용자에게 클라우드의 규모를 간단하게 조정할 수 있는 서비스를 제공해준다.&lt;/p&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-filename=&quot;스크린샷 2022-09-03 오후 3.59.07.png&quot; data-origin-width=&quot;724&quot; data-origin-height=&quot;506&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b0HKAK/btrLgYKrK3k/QqhZkYvEUJFKRzKEkVngG1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b0HKAK/btrLgYKrK3k/QqhZkYvEUJFKRzKEkVngG1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b0HKAK/btrLgYKrK3k/QqhZkYvEUJFKRzKEkVngG1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb0HKAK%2FbtrLgYKrK3k%2FQqhZkYvEUJFKRzKEkVngG1%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;416&quot; height=&quot;291&quot; data-filename=&quot;스크린샷 2022-09-03 오후 3.59.07.png&quot; data-origin-width=&quot;724&quot; data-origin-height=&quot;506&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AWS는 특정 시점에 네트워크 정보와 시스템 리소스 메트릭 정보들을 모니터링 서비스로 수집한 이후, 사용자가 지정한 일정 임계치를 넘어가면 오토스케일링 그룹으로 알림을 발송해 서버수를 늘리거나 줄이는 방식으로 작동한다. 위의 사진과 같이 최소 사이즈 단위를 규정하고 디폴트 성능을 정하고 디폴트 성능을 초과하면 Scale out이 필요하다는 것을 알림 보내는 방식이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Reference&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://docs.aws.amazon.com/autoscaling/ec2/userguide/what-is-amazon-ec2-auto-scaling.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://docs.aws.amazon.com/autoscaling/ec2/userguide/what-is-amazon-ec2-auto-scaling.html&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Cloud</category>
      <category>Auto Scaling</category>
      <category>AWS</category>
      <category>Cloud</category>
      <author>큐범</author>
      <guid isPermaLink="true">https://kbcoding.tistory.com/87</guid>
      <comments>https://kbcoding.tistory.com/87#entry87comment</comments>
      <pubDate>Wed, 7 Sep 2022 17:08:35 +0900</pubDate>
    </item>
    <item>
      <title>[Algorithm] JAVA 코드업 기초 100제 (기초-1차원배열, 2차원배열) 1093 ~ 1099</title>
      <link>https://kbcoding.tistory.com/86</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;1093 : [기초-1차원배열] 이상한 출석 번호 부르기1(설명)&lt;/b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		String s1 = sc.nextLine();
		String s2 = sc.nextLine();
		
		int[] array = new int[23];
		int[] call = Arrays.stream(s2.split(&quot; &quot;))
				.mapToInt(Integer::parseInt)
				.toArray();
		
		for(int i=0; i&amp;lt;Integer.parseInt(s1); i++) {
			array[call[i]]++;
		}
		
		for(int j=1; j&amp;lt;23; j++) {
			System.out.print(array[j]+&quot; &quot;);
		}
	}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;1094 : [기초-1차원배열] 이상한 출석 번호 부르기2(설명)&lt;/b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		
		int s1 = sc.nextInt();
		int[] array = new int[s1];

		
		for(int i =0; i&amp;lt;s1; i++) {
			array[i] = sc.nextInt();
		}
		
		for(int j = array.length-1; j&amp;gt;=0; j-- ) {
			System.out.print(array[j]+&quot; &quot;);
		}
	}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;1095 : [기초-1차원배열] 이상한 출석 번호 부르기3(설명)&lt;/b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		
		int s1 = sc.nextInt();
		int[] array = new int[s1];

		
		for(int i =0; i&amp;lt;s1; i++) {
			array[i] = sc.nextInt();
		}
		
		int min=23;
		
		for(int j=0; j&amp;lt;array.length; j++) {
			if(array[j]&amp;lt;min) min= array[j];
		}
		
		System.out.println(min);
	}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;1096 : [기초-2차원배열] 바둑판에 흰 돌 놓기(설명)&lt;/b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		
		int n = sc.nextInt();
		int[][] array = new int[19][19];
		
		for(int i=0; i&amp;lt;n; i++) {
			int x = sc.nextInt();
			int y = sc.nextInt();
			
			array[x][y]=1;
		}
		
		for(int j=1; j&amp;lt;array.length; j++) {
			for(int k=1; k&amp;lt;array.length; k++) {
				System.out.print(array[j][k]);
			}
			System.out.print(&quot;\\n&quot;);
		}
	}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;1097 : [기초-2차원배열] 바둑알 십자 뒤집기(설명)&lt;/b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		
		int[][] array = new int[20][20];
		
		for(int i=1; i&amp;lt;array.length; i++) {
			for(int j=1; j&amp;lt;array.length; j++) {
				array[i][j]=sc.nextInt();	
			}
		}
		
		int n = sc.nextInt(); 
		
		for(int i=0; i&amp;lt;n; i++) {
			int x = sc.nextInt();
			int y = sc.nextInt();
			
			for(int j=1; j&amp;lt;array.length; j++) {
				if(array[x][j]==0) array[x][j]=1;
				else array[x][j]=0;
			}
			for(int k=1; k&amp;lt;array.length; k++) {
				if(array[k][y]==0) array[k][y]=1;
				else array[k][y]=0;
			}
		}
		
		
		for(int j=1; j&amp;lt;array.length; j++) {
			for(int k=1; k&amp;lt;array.length; k++) {
				System.out.print(array[j][k]);
			}
			System.out.print(&quot;\\n&quot;);
		}
	}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;1098 : [기초-2차원배열] 설탕과자 뽑기&lt;/b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		
		int[][] array;
		
		int h,w,n,l,d,x,y; 
		h=sc.nextInt();
		w=sc.nextInt();
		
		array=new int[h][w];
		
		n=sc.nextInt();
		
		for(int i=0; i&amp;lt;n; i++) {
			l=sc.nextInt();
			d=sc.nextInt();
			x=sc.nextInt();
			y=sc.nextInt();
			
			for(int j=0; j&amp;lt;l; j++) {
				if(d==0) array[x-1][y-1+j]=1;
				else array[x-1+j][y-1]=1;
			}
		}
		
		for(int i=0; i&amp;lt;w; i++) {
			for(int j=0; j&amp;lt;w; j++) {
				System.out.print(array[i][j]+&quot; &quot;);
			}
			System.out.print(&quot;\\n&quot;);
		}
	}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;1099 : [기초-2차원배열] 성실한 개미&lt;/b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		
		int[][] array=new int[11][11];
		
		for (int i=1; i&amp;lt;=10; i++) {
			for (int j=1; j&amp;lt;=10; j++) {
				array[i][j] = sc.nextInt();
			}
		}
		
		int x = 2;
		int y = 2;
		
		while(true) {
			if(array[x][y]==0) {
				array[x][y]=9;
				y++;
			}
			if(array[x][y]==1) {
				y--;
				x++;
			}
			if(array[x][y]==2) {
				array[x][y]=9;
				break;
			}else if(array[x][y]+1 ==1 &amp;amp;&amp;amp; array[x+1][y]==1) {
				if(array[x][y]==0) array[x][y]=9;
				
				break;
			}
		}
		
		for(int i=1; i&amp;lt;=10; i++) {
			for(int j=1; j&amp;lt;=10; j++) {
				System.out.print(array[i][j]+&quot; &quot;);
			}
			System.out.print(&quot;\\n&quot;);
		}
	}
&lt;/code&gt;&lt;/pre&gt;</description>
      <category>JAVA/JAVA Algorithm, Datastruct</category>
      <author>큐범</author>
      <guid isPermaLink="true">https://kbcoding.tistory.com/86</guid>
      <comments>https://kbcoding.tistory.com/86#entry86comment</comments>
      <pubDate>Tue, 6 Sep 2022 02:50:42 +0900</pubDate>
    </item>
    <item>
      <title>[Algorithm] JAVA 코드업 기초 100제 (기초-종합) 1078 ~ 1092</title>
      <link>https://kbcoding.tistory.com/85</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;1078 : [기초-종합] 짝수 합 구하기(설명)&lt;/b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int s = sc.nextInt();
		
		int sum=0;
		for(int i=0; i&amp;lt;=s; i++) {
			if(i%2==0) {
				sum +=i;
			}
		}
		System.out.println(sum);
	}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;1079 : [기초-종합] 원하는 문자가 입력될 때까지 반복 출력하기&lt;/b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		String s = sc.nextLine();
		
		
		String[] array = s.split(&quot; &quot;);
		
		for(String x: array) {
			System.out.println(x);
			if(x.equals(&quot;q&quot;)) break;			
		}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;1080 : [기초-종합] 언제까지 더해야 할까?&lt;/b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;processing&quot;&gt;&lt;code&gt;public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int key = sc.nextInt();
		int sum=0;
		
		for (int i=0; i&amp;lt;=key; i++) {
			sum+=i;
			if(sum&amp;gt;=key) {
				System.out.println(i);
				break;
			}
		}
	}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;1081 : [기초-종합] 주사위를 2개 던지면?(설명)&lt;/b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		String s = sc.nextLine();
		
		int[] array = Arrays.stream(s.split(&quot; &quot;))
				.mapToInt(Integer::parseInt)
				.toArray();
		
		for(int i=1; i&amp;lt;=array[0]; i++) {
			for(int j=1; j&amp;lt;=array[1]; j++) {
				System.out.println(i+&quot; &quot;+j);
			}
		}
	}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;1082 : [기초-종합] 16진수 구구단?&lt;/b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int c = sc.nextInt(16);
		
		for(int i=1; i&amp;lt;=16; i++) {
			System.out.printf(&quot;%X*%X=%X\\n&quot;,c,i,c*i);
		}
	}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;1083 : [기초-종합] 3 6 9 게임의 왕이 되자!(설명)&lt;/b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;processing&quot;&gt;&lt;code&gt;public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int key = sc.nextInt();
		
		for(int i=1; i&amp;lt;=key; i++) {
			if(i%3==0) {
				System.out.print(&quot;X &quot;);
			}else {
				System.out.print(i+&quot; &quot;);
			}
		}
	}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;1084 : [기초-종합] 빛 섞어 색 만들기(설명)&lt;/b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		String s = sc.nextLine();
		
		int[] array = Arrays.stream(s.split(&quot; &quot;))
				.mapToInt(Integer::parseInt)
				.toArray();
		
		int count=0;
		
		for(int i=0; i&amp;lt;array[0]; i++) {
			for(int j=0; j&amp;lt;array[1]; j++) {
				for(int k=0; k&amp;lt;array[2]; k++) {
					System.out.println(i+&quot; &quot;+j+&quot; &quot;+k+&quot; &quot;);
					count++;
				}
			}
		}
		System.out.println(count);
	}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;1085 : [기초-종합] 소리 파일 저장용량 계산하기(설명)&lt;/b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		String key = sc.nextLine();
		
		String[] array = key.split(&quot; &quot;);
		
		double h = Double.valueOf(array[0]);
		double b = Double.valueOf(array[1]);
		double c = Double.valueOf(array[2]);
		double s = Double.valueOf(array[3]);
		
		System.out.printf(&quot;%.1f MB&quot;,(h*b*c*s)/8/1024/1024);
	}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;1086 : [기초-종합] 그림 파일 저장용량 계산하기(설명)&lt;/b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		String key = sc.nextLine();
		
		String[] array = key.split(&quot; &quot;);
		
		double w = Double.valueOf(array[0]);
		double h = Double.valueOf(array[1]);
		double b = Double.valueOf(array[2]);
		
		System.out.printf(&quot;%.2f MB&quot;,(w*h*b)/8/1024/1024);
	}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;1087 : [기초-종합] 여기까지! 이제 그만~(설명)&lt;/b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;processing&quot;&gt;&lt;code&gt;public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int key = sc.nextInt();
		
		int sum=0;
		for(int i=0; i&amp;lt;=key; i++) {
			sum+=i;
			if(sum&amp;gt;=key) {
				System.out.println(sum);
				break;
			}
		}
	}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;1088 : [기초-종합] 3의 배수는 통과?(설명)&lt;/b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;processing&quot;&gt;&lt;code&gt;public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int key = sc.nextInt();
		
		for(int i=0; i&amp;lt;=key; i++) {
			if(i%3!=0) {
				System.out.print(i+&quot; &quot;);
			}
		}
	}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;1089 : [기초-종합] 수 나열하기1&lt;/b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		String s = sc.nextLine();
		
		int a = Integer.parseInt(s.split(&quot; &quot;)[0]);
		int d = Integer.parseInt(s.split(&quot; &quot;)[1]);
		int n = Integer.parseInt(s.split(&quot; &quot;)[2]);
		
		for(int i=a; i&amp;lt;n; i++) {
			a+=d;
		}
		System.out.println(a);
	}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;1090 : [기초-종합] 수 나열하기2&lt;/b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		String s = sc.nextLine();
		
		int a,r,n;
		a=Integer.parseInt(s.split(&quot; &quot;)[0]);
		r=Integer.parseInt(s.split(&quot; &quot;)[1]);
		n=Integer.parseInt(s.split(&quot; &quot;)[2]);
		
		for(int i=a; i&amp;lt;=n; i++) {
			a*=r;
		}
		System.out.println(a);
	}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;1091 : [기초-종합] 수 나열하기3&lt;/b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		String s = sc.nextLine();
		
		int a,m,d,n;
		a=Integer.parseInt(s.split(&quot; &quot;)[0]);
		m=Integer.parseInt(s.split(&quot; &quot;)[1]);
		d=Integer.parseInt(s.split(&quot; &quot;)[2]);
		n=Integer.parseInt(s.split(&quot; &quot;)[3]);
		
		for(int i=a; i&amp;lt;n; i++) {
			a=a*m+d;
		}
		System.out.println(a);
	}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;1092 : [기초-종합] 함께 문제 푸는 날(설명)&lt;/b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		String s = sc.nextLine();
		
		int a,b,c,day;
		a=Integer.parseInt(s.split(&quot; &quot;)[0]);
		b=Integer.parseInt(s.split(&quot; &quot;)[1]);
		c=Integer.parseInt(s.split(&quot; &quot;)[2]);
		
		day=1;
		
		while(day%a!=0 || day%b!=0 || day%c!=0) day++;
		System.out.println(day);
	}
&lt;/code&gt;&lt;/pre&gt;</description>
      <category>JAVA/JAVA Algorithm, Datastruct</category>
      <author>큐범</author>
      <guid isPermaLink="true">https://kbcoding.tistory.com/85</guid>
      <comments>https://kbcoding.tistory.com/85#entry85comment</comments>
      <pubDate>Mon, 5 Sep 2022 02:10:25 +0900</pubDate>
    </item>
    <item>
      <title>[Algorithm] JAVA 코드업 기초 100제 (기초-반복실행구조) 1071 ~ 1077</title>
      <link>https://kbcoding.tistory.com/84</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;1071 : [기초-반복실행구조] 0 입력될 때까지 무한 출력하기1(설명)&lt;/b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		String s = sc.nextLine();
		
		String[] array = s.split(&quot; &quot;);
		
		for(String x : array) {
			if(!x.equals(&quot;0&quot;)) {
				System.out.println(x);
			}else {
				break;
			}
		}
	}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;1072 : [기초-반복실행구조] 정수 입력받아 계속 출력하기(설명)&lt;/b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		
		int key = sc.nextInt(); 
		int[] array = new int[key];
		
		for(int i=0; i&amp;lt;array.length; i++) {
			array[i] = sc.nextInt();
		}
		
		for(int x : array) {
			System.out.println(x);
		}
		
	}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;1073 : [기초-반복실행구조] 0 입력될 때까지 무한 출력하기2(설명)&lt;/b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		
		while(true) {
			int i = sc.nextInt();
			
			if(i==0) break;
			System.out.println(i);
		}
	}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;1074 : [기초-반복실행구조] 정수 1개 입력받아 카운트다운 출력하기1(설명)&lt;/b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int i = sc.nextInt();

		while(i!=0) {
			System.out.println(i);
			i--;
		}
	}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;1075 : [기초-반복실행구조] 정수 1개 입력받아 카운트다운 출력하기2(설명)&lt;/b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int i = sc.nextInt();

		while(i!=0) {
			i--;
			System.out.println(i);
		}
	}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;1076 : [기초-반복실행구조] 문자 1개 입력받아 알파벳 출력하기(설명)&lt;/b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		char c = sc.next().charAt(0);

		for(int i=97; i&amp;lt;=c; i++) {
			System.out.print(Character.toString(i)+&quot; &quot;);
		}
	}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;1077 : [기초-반복실행구조] 정수 1개 입력받아 그 수까지 출력하기(설명)&lt;/b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int c = sc.nextInt();

		for(int i=0; i&amp;lt;=c; i++) {
			System.out.println(i);
		}
	}
&lt;/code&gt;&lt;/pre&gt;</description>
      <category>JAVA/JAVA Algorithm, Datastruct</category>
      <author>큐범</author>
      <guid isPermaLink="true">https://kbcoding.tistory.com/84</guid>
      <comments>https://kbcoding.tistory.com/84#entry84comment</comments>
      <pubDate>Sun, 4 Sep 2022 03:12:33 +0900</pubDate>
    </item>
    <item>
      <title>[Algorithm] JAVA 코드업 기초 100제 (기초-삼항연산, 선택실행 구조) 1063 ~ 1070</title>
      <link>https://kbcoding.tistory.com/83</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;1063 : [기초-삼항연산] 두 정수 입력받아 큰 수 출력하기(설명)&lt;/b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		String s = sc.nextLine();
		String[] data = s.split(&quot; &quot;);
		
		int a = Integer.valueOf(data[0]);
		int b = Integer.valueOf(data[1]);
		
		System.out.printf(&quot;%d&quot;, a&amp;gt;b?a:b);
	}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;1064 : [기초-삼항연산] 정수 3개 입력받아 가장 작은 수 출력하기(설명)&lt;/b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		String s = sc.nextLine();
		String[] data = s.split(&quot; &quot;);
		
		int a = Integer.valueOf(data[0]);
		int b = Integer.valueOf(data[1]);
		int c = Integer.valueOf(data[2]);
		
		System.out.printf(&quot;%d&quot;, (a&amp;lt;b ? a:b) &amp;lt; c ? (a&amp;lt;b?a:b):c);
	}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;1065 : [기초-조건/선택실행구조] 정수 3개 입력받아 짝수만 출력하기(설명)&lt;/b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		String s = sc.nextLine();
		String[] data = s.split(&quot; &quot;);
		
		for(int i=0; i&amp;lt;data.length; i++) {
			if(Integer.valueOf(data[i])%2==0) {
				System.out.println(data[i]);
			}
		}
	}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;1066 : [기초-조건/선택실행구조] 정수 3개 입력받아 짝/홀 출력하기(설명)&lt;/b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		String s = sc.nextLine();
		String[] data = s.split(&quot; &quot;);
		
		for(int i=0; i&amp;lt;data.length; i++) {
			if(Integer.valueOf(data[i])%2==0) {
				System.out.println(&quot;even&quot;);
			}else {
				System.out.println(&quot;odd&quot;);
			}
		}
	}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;1067 : [기초-조건/선택실행구조] 정수 1개 입력받아 분석하기(설명)&lt;/b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		String s = sc.nextLine();
		String[] data = s.split(&quot; &quot;);
		
		for(int i=0; i&amp;lt;data.length; i++) {
			if(Integer.valueOf(data[i])&amp;gt;0) {
				System.out.println(&quot;plus&quot;);
			}else {
				System.out.println(&quot;minus&quot;);
			}
			if(Integer.valueOf(data[i])%2==0) {
				System.out.println(&quot;even&quot;);
			}else {
				System.out.println(&quot;odd&quot;);
			}
		}
	}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;1068 : [기초-조건/선택실행구조] 정수 1개 입력받아 평가 출력하기(설명)&lt;/b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int i = sc.nextInt();
		
		if(i&amp;gt;=90) System.out.println(&quot;A&quot;);
		else if(i&amp;gt;=70) System.out.println(&quot;B&quot;);
		else if(i&amp;gt;=40) System.out.println(&quot;C&quot;);
		else if(i&amp;gt;=00) System.out.println(&quot;D&quot;);
	}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;1069 : [기초-조건/선택실행구조] 평가 입력받아 다르게 출력하기(설명)&lt;/b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		String i = sc.nextLine();
		
		switch(i) {
			case &quot;A&quot;:
				System.out.println(&quot;best!!!&quot;);
				break;
			case &quot;B&quot;:
				System.out.println(&quot;good!!!&quot;);
				break;
			case &quot;C&quot;:
				System.out.println(&quot;run!&quot;);
				break;
			case &quot;D&quot;:
				System.out.println(&quot;solowly~&quot;);
				break;
			default:
				System.out.println(&quot;what?&quot;);
				break;
		}
	}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;1070 : [기초-조건/선택실행구조] 월 입력받아 계절 출력하기(설명)&lt;/b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int i = sc.nextInt();
		
		switch(i) {
			case 3:
			case 4:
			case 5:
				System.out.println(&quot;spring&quot;);
				break;
			case 6:
			case 7:
			case 8:
				System.out.println(&quot;summer&quot;);
				break;
			case 9:
			case 10:
				System.out.println(&quot;fall&quot;);
				break;
			default:
				System.out.println(&quot;winter&quot;);
				break;
		}
	}
&lt;/code&gt;&lt;/pre&gt;</description>
      <category>JAVA/JAVA Algorithm, Datastruct</category>
      <author>큐범</author>
      <guid isPermaLink="true">https://kbcoding.tistory.com/83</guid>
      <comments>https://kbcoding.tistory.com/83#entry83comment</comments>
      <pubDate>Sat, 3 Sep 2022 03:11:47 +0900</pubDate>
    </item>
  </channel>
</rss>