<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>(수근수근)</title>
    <link>https://soonysoon.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Thu, 9 Apr 2026 19:29:03 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>InformationFarm</managingEditor>
    <image>
      <title>(수근수근)</title>
      <url>https://tistory1.daumcdn.net/tistory/3559064/attach/efe20aba9f9a48069c232241f46a2fee</url>
      <link>https://soonysoon.tistory.com</link>
    </image>
    <item>
      <title>react memoization 2 ) React.memo</title>
      <link>https://soonysoon.tistory.com/111</link>
      <description>&lt;p data-ke-size=&quot;size14&quot;&gt;1편에서 pure component에 대해서 이야기 했다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;pure component란 PureComponent&lt;span style=&quot;background-color: #ffffff; color: #23272f; text-align: start;&quot;&gt; is similar to &lt;/span&gt;&lt;a style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; href=&quot;https://react.dev/reference/react/Component&quot;&gt;Component&lt;/a&gt;&lt;span style=&quot;background-color: #ffffff; color: #23272f; text-align: start;&quot;&gt; but it skips re-renders for same props and state로 리액트 공식 사이트에서 &lt;br /&gt;설명되어있다. state와 prop가 동일하면 리렌더링을 건너뛰는 컴포넌트라는 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #23272f; text-align: start;&quot;&gt;리액트 최적화 툴 중 하나인 React.memo는 사용자가 해당 컴포넌트가 pure component임을 인지하고 사용하는 최적화 함수이다.&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #23272f; text-align: start;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;React.memo&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;React.memo pure component를 최적화하는 &lt;b&gt;escape hatch&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;function Decoration() {
  return (
    &amp;lt;div className=&quot;decoration&quot;&amp;gt;
      ⛵️
    &amp;lt;/div&amp;gt;
  );
}

const PureDecoration = React.memo(Decoration);

export default PureDecoration;
&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;React.memo를 사용해서 우리는 리액트에게 알려줄 수 있습니다&lt;/p&gt;
&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;이 컴포넌트는 pure해! 따라서 동일한 props와 state라면 리렌더링 할 필요 없어! &amp;rdquo;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리액트는 이전 스냅샷을 기억하고 있기 때문에, props가 변경되지 않으면 새로운 스냅샷을 만들어서 제공하지 않고 기존의 스냅샷을 전달합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>web/React</category>
      <author>InformationFarm</author>
      <guid isPermaLink="true">https://soonysoon.tistory.com/111</guid>
      <comments>https://soonysoon.tistory.com/111#entry111comment</comments>
      <pubDate>Mon, 9 Oct 2023 15:06:41 +0900</pubDate>
    </item>
    <item>
      <title>react memoization 1 ) 왜 최적화 툴이 필요한가?</title>
      <link>https://soonysoon.tistory.com/110</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;최적화가 사실 몸으로 와닿은적이 아직 없다. 따라서 공부도 제대로 안한 경향이 있고, 단순히 리렌더링 안해도되는 것은 최적화 툴(useMemo, useCallback)을 쓰면된다 이정도의 지식이었는데, 제대로 알지도 못하는데 어떻게 쓸 수 있는가 하는 생각이 들었고&lt;br /&gt;좋은 강의(josh)를 통해서 해당 툴이 리액트에서 필요한 이유를 좀 더 깊게 이해할 수 있었다.&lt;/p&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;/p&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;The Basic rule&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;&amp;nbsp;모든 리렌더링은 state value 변경으로 시작되고, 이는 유일한 트리거입니다.&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;p data-ke-size=&quot;size16&quot;&gt;나 또한 잘못알고 있었고, 리렌더링 자료를 찾다보면 리렌더링 되는 조건을 종종 발견할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR'; color: #333333; text-align: center;&quot;&gt;&amp;nbsp;props가 변경되면 컴포넌트는 리렌더링 된다!&amp;nbsp; =&amp;gt; false&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;figure contenteditable=&quot;false&quot; data-ke-type=&quot;emoticon&quot; data-ke-align=&quot;alignLeft&quot; data-emoticon-type=&quot;niniz&quot; data-emoticon-name=&quot;007&quot; data-emoticon-isanimation=&quot;false&quot; data-emoticon-src=&quot;https://t1.daumcdn.net/keditor/emoticon/niniz/large/007.gif&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/keditor/emoticon/niniz/large/007.gif&quot; width=&quot;150&quot; /&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반례를 하나 봅시다.&lt;/p&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;function Counter() {
  const [count, setCount] = React.useState(0);
  
  return (
    &amp;lt;main&amp;gt;
      &amp;lt;BigCountNumber count={count} /&amp;gt;
      &amp;lt;button onClick={() =&amp;gt; setCount(count + 1)}&amp;gt;
        Increment
      &amp;lt;/button&amp;gt;
      &amp;lt;Decoration /&amp;gt;
    &amp;lt;/main&amp;gt;
  );
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Decoration component는 count에 어떠한 영향도 받지 않지만, count상태가 변경됨에 따라 재렌더링됩니다.&lt;/p&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;&amp;rArr; 리액도팀 100%확실할 수 없기 때문입니다. (사용자들이 제대로 이해하고 사용한다고 장담하기 어렵죠...그게 접니다.. &lt;/b&gt;&lt;b&gt;)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리는 항상 pure한 리액트 컴포넌트(같은 props를 넣으면 값은 UI가 생성이되는)를 만들고 싶습니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 현실세계에서는 impure한 컴포넌트를 만들기 무진장 쉽습니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 코드처럼요!&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;function CurrentTime() {
  const now = new Date();

  return (
    &amp;lt;p&amp;gt;It is currently {now.toString()}&amp;lt;/p&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리액트팀의 첫번째 목표는 사용자의 UI가 state에 따라 동기화 되는지입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 사용자에게 오래된 UI를 보여주기보다는 불필요한 리렌터링하는 것을 선택한것이지요!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;따라서 props와 rerender링은 상관이 없습니다!&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;&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;(우리는 일단 사용자 UI가 fresh한 것이 목적이니, 너희가 리액트의 cycle에 대해 이해하게 된다면, 직접 우리가 제공하는 툴을 통해 최적화를 시켜!)&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;이것이 React.memo, useMemo, useCallback이며 왜 배워야하는지도 조금은 명확해졌습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 글은 React.memo를 왜 사용하는지, 어떻게 사용하는지에 대해서 알아보겠습니다.&lt;/p&gt;</description>
      <category>web/React</category>
      <author>InformationFarm</author>
      <guid isPermaLink="true">https://soonysoon.tistory.com/110</guid>
      <comments>https://soonysoon.tistory.com/110#entry110comment</comments>
      <pubDate>Mon, 9 Oct 2023 14:24:20 +0900</pubDate>
    </item>
    <item>
      <title>useEffect callback함수 async키워드를 쓰면 안되는 이유</title>
      <link>https://soonysoon.tistory.com/109</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;Async Effect Gotcha&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;gotcha : 프로그래밍에서 문제는 문서화된 대로 작동하지만 호출하기 쉽고 결과가 예상치 못하거나 불합리하기 때문에 직관에 반하고 실수를 거의 유발하는 시스템, 프로그램 또는 프로그래밍 언어의 유효한 구성입니다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모두 알다시피, await키워드를 사용할 때, async함수 내부여야만 사용할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리액트를 개발하면, useEffect내부에서 비동기 함수를 사용해야하는 일이 꽤나 빈번하다. 특히 컴포넌트가 mount될 때, api를 불러오고 싶은경우가 많을 것이다.(react query, swr을 처음부터 쓰면, 알아서 해줍니다..)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어보자,&lt;/p&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;React.useEffect(async () =&amp;gt; {
    const response = await fetch(ENDPOINT);
    const json = await response.json();

    setTemperature(json.temperature);
  }, []);
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당과 같이 useEffect를 쓰면 다음과 같은 console waring을 받을 수 있다.&lt;/p&gt;
&lt;pre class=&quot;livecodeserver&quot;&gt;&lt;code&gt;It looks like you wrote useEffect(async () =&amp;gt; ...) or returned a Promise. Instead, write the async function inside your effect and call it immediately.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이유는 다음과 같다. effect의 callback으로 비동기 함수를 사용할 수 없기 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해결방법은 다음과 같습니다.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;React.useEffect(() =&amp;gt; {
  async function runEffect() {
    // ... Effect logic here
  }

  runEffect();

  return () =&amp;gt; {
    //  ... Cleanup logic here
  }
}, []);
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비동기 함수명을 지을 때 구처젝인 함수의 기능보다 runEffect같은 일반적인 함수명을 할 것은 권합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;cleanup함수에 runEffect의 function은 들어가서 안됩니다.(스코프내의 함수임)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 우리는 해결방법은 알게되었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;근데 왜! 비동기함수는 Effect의 콜백함수로 허용이 안될까요?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다시 해결방법을 살펴봐보시면, 왜 비동기 함수로 만들고 호출하고 바로 없애는게 바보같아보입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근데 왜 그렇게 해야할까요?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 먼저 분명히 할 것은, &lt;b&gt;비동기함수는 promise를 반환한다는 것&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;for example :&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;async function quickExample() {
  return 5;
}

const result = quickExample();
console.log(result); // Promise
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;useEffect에서 반환하기로 우리가 약속한 것은 cleanup함수입니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 상황을 Effec상황을 봐봅시다.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;React.useEffect(() =&amp;gt; {
  // Effect logic: start an interval
  const intervalId = window.setInterval(() =&amp;gt; {}, 1000);

  // Cleanup logic: stop the interval:
  return () =&amp;gt; {
    window.clearInterval(intervalId);
  };
}, []);
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리가 useEffect를 사용할 때, 우리는 cleanup함수를 전달합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리액트는 dependencies가 변경될 때마다 cleanup함수를 호출합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 중간에 비동기함수가 들어가야한다고 가정해봅시다.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;React.useEffect(async () =&amp;gt; {
  const intervalId = window.setInterval(() =&amp;gt; {}, 1000);

  await someLongRunningProcess();

  // Even though we're returning a function, it'll actually
  // return a *promise* that resolves to a function:
  return () =&amp;gt; {
    window.clearInterval(intervalId);
  };
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비동기 함수이니 반환값이 promise가 될 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 비동기 함수가 작업이 오래 걸리고 있을 때 unmount가 된다면 cleanup함수는 수행되지 않을겁니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런한 어려운 상활을 피하기 위해서 리액트팀은 비동기함수 콜백이 불가능 하도록 결정했을 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대신 우리는 비동기함수 로직을 감싸서 사용할 수 있습니다. 해당과 같은 경우는 cleanup함수를 즉시반환이 가능하기 때문에, 잘못된 gotcha를 피할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 글은 josh강의를 이해하기 위해 일부 정리한것입니다.&amp;nbsp;&lt;/p&gt;</description>
      <category>web/React</category>
      <author>InformationFarm</author>
      <guid isPermaLink="true">https://soonysoon.tistory.com/109</guid>
      <comments>https://soonysoon.tistory.com/109#entry109comment</comments>
      <pubDate>Sun, 8 Oct 2023 15:14:20 +0900</pubDate>
    </item>
    <item>
      <title>datepicker 자동 masking하기</title>
      <link>https://soonysoon.tistory.com/108</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;문제&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 현재 &lt;span style=&quot;background-color: #ffffff; color: #232629;&quot;&gt;react-datepicker&lt;span&gt; library를 활용하고 있는데 input에 날짜를 입력할 때 자동으로 MM-dd-yyyy형태로 작성되게 하고싶은데 mmddyyyy로 들어감&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #232629;&quot;&gt;&lt;span&gt;- locale에 따라 자동으로 formating형태에 따라 대쉬를 넣어주고 싶음&lt;/span&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;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- datepicker에서 열어둔 props의 customInput을 활용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 자동으로 masking을 도와주는 라이브러리(react-text-mask) 사용&lt;br /&gt;(&lt;a href=&quot;https://github.com/text-mask/text-mask/tree/master/react&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/text-mask/text-mask/tree/master/react&lt;/a&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필요한 부분 코드만 작성 (나머지 불필요한 부분들은 삭제함)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- locale에 따라 다르게 mask부분의 배열을 변경해주면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1672930145572&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import ReactDatePicker, { registerLocale } from 'react-datepicker';
import { ko, enUS } from 'date-fns/locale';
import MaskedInput from 'react-text-mask';

function DateInput({
  name,
  selected,
  locale = 'en',
  ...rest
}: props) {
  return (
    &amp;lt;Styled.Wrapper&amp;gt;
      &amp;lt;ReactDatePicker
        customInput={
          &amp;lt;MaskedInput
            mask={
              locale === 'ko'
                ? [/\d/, /\d/, /\d/, /\d/, '-', /\d/, /\d/, '-', /\d/, /\d/]
                : [/\d/, /\d/, '-', /\d/, /\d/, '-', /\d/, /\d/, /\d/, /\d/]
            }
            guide={false}
          /&amp;gt;
        }
        dateFormat={DATE_FORMAT[locale]}
        {...rest}
      /&amp;gt;
    &amp;lt;/Styled.Wrapper&amp;gt;
  );
}

export default DateInput;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;날짜 데이터 유효성&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #24292f;&quot;&gt;1. &lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;text-mask-addons install&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1673100692108&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;yarn add text-mask-addons&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #24292f;&quot;&gt;&lt;span&gt;&lt;a href=&quot;https://github.com/text-mask/text-mask/tree/master/addons/#readme&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/text-mask/text-mask/tree/master/addons/#readme&lt;/a&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. createAutoCorrectedDatePipe api를 통해서 autoCorrectedDatePipe반환 뒤 MaskedInput props로 전달&lt;br /&gt;(저는 locale에 따라 다르게 유효범위를 주고있습니다.)&lt;/p&gt;
&lt;pre id=&quot;code_1673100833476&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import MaskedInput from 'react-text-mask';
import createAutoCorrectedDatePipe from 'text-mask-addons/dist/createAutoCorrectedDatePipe';


function DateInput({
  name,
  selected,
  size = 'large',
  locale = 'en',
  onSelect,
  onChange,
  ...rest
}: Types.DateInputProps) {

  const autoCorrectedDatePipe = createAutoCorrectedDatePipe(
    locale === 'ko' ? 'yyyy-mm-dd' : 'mm-dd-yyyy',
  );


  return (
    &amp;lt;Styled.Wrapper size={size}&amp;gt;
      &amp;lt;ReactDatePicker
        locale={locale}
        name={name}
        selected={selected ? &quot;&quot;}
        customInput={
          &amp;lt;MaskedInput
            mask={
              locale === 'ko'
                ? [/\d/, /\d/, /\d/, /\d/, '-', /\d/, /\d/, '-', /\d/, /\d/]
                : [/\d/, /\d/, '-', /\d/, /\d/, '-', /\d/, /\d/, /\d/, /\d/]
            }
            guide={false}
            pipe={autoCorrectedDatePipe}
          /&amp;gt;
        }&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 찾아보니 mul Input의 유효한값 mask해주는 3rd party library로는 i&lt;span style=&quot;background-color: #ffffff; color: #24292f;&quot;&gt;&lt;span style=&quot;color: #24292f;&quot;&gt;mask&lt;/span&gt; 라이브러리를 소개하고 있네요..&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #24292f;&quot;&gt;i&lt;span style=&quot;background-color: #ffffff; color: #24292f;&quot;&gt;&lt;span style=&quot;color: #24292f;&quot;&gt;mask&lt;/span&gt;와 react-text-mask &lt;/span&gt;장단점을 비교해보는 것이 필요해보입니다...&amp;nbsp; !&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #24292f;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #24292f;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;출처&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;https://stackoverflow.com/questions/56679242/insert-auto-slash-for-date-in-mm-dd-yyyy-format-for-react-datepicker&lt;/blockquote&gt;</description>
      <category>web/React</category>
      <author>InformationFarm</author>
      <guid isPermaLink="true">https://soonysoon.tistory.com/108</guid>
      <comments>https://soonysoon.tistory.com/108#entry108comment</comments>
      <pubDate>Thu, 5 Jan 2023 23:51:45 +0900</pubDate>
    </item>
    <item>
      <title>Typescript handbook 읽고 정리(Narrowing)</title>
      <link>https://soonysoon.tistory.com/107</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-10-20 오전 12.51.50.png&quot; data-origin-width=&quot;852&quot; data-origin-height=&quot;580&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uMt4s/btrOD5sQOCC/YP8VSROBjMHQk4Xi3c3Zgk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uMt4s/btrOD5sQOCC/YP8VSROBjMHQk4Xi3c3Zgk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uMt4s/btrOD5sQOCC/YP8VSROBjMHQk4Xi3c3Zgk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuMt4s%2FbtrOD5sQOCC%2FYP8VSROBjMHQk4Xi3c3Zgk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;481&quot; height=&quot;327&quot; data-filename=&quot;스크린샷 2022-10-20 오전 12.51.50.png&quot; data-origin-width=&quot;852&quot; data-origin-height=&quot;580&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h1&gt;Narrowing&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;narrowing 타입을 좁혀나간다 이런 의미같다.. 살펴보자&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 장에서 타입스크립트가 제공하는 (자바스크립트가 제공하는 키워드이기도 하지만..? 이를 타입스크립트는 narrowing용으로 사용도 하는 것 같다.) Type guards들에 대해서 하나씩 알아보자!&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선 첫 번째 예제를 하나 보여주는데 아래와 같다&lt;/p&gt;
&lt;pre class=&quot;lua&quot;&gt;&lt;code&gt;function padLeft(padding: number | string, input: string) {
  if (typeof padding === &quot;number&quot;) {
    return &quot; &quot;.repeat(padding) + input;
  }
  return padding + input;
}
&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;타입스크립트는 typeof라는 타입 가드의 형태로 구체적인 유형으로 한번 더 Narrowing해주는 작업을 진행한다. 그럼 type guards인 typeof키워드에 대해서 알아보자&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;typeof type guards&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바스크립트 typeof를 지원하여 런타임에 우리가 가지고 있는 값의 유형에 대해 정보를 제공한다. TypeScript는 이를 통해 특정 문자열 집합을 반환할 것으로 예상한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;string&lt;/li&gt;
&lt;li&gt;number&lt;/li&gt;
&lt;li&gt;bigint&lt;/li&gt;
&lt;li&gt;boolean&lt;/li&gt;
&lt;li&gt;symbol&lt;/li&gt;
&lt;li&gt;undefined&lt;/li&gt;
&lt;li&gt;object&lt;/li&gt;
&lt;li&gt;function&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;padLeft에서 보았 듯이, typeof는 JavaScript 라이브러리에서 자주 사용하여 TypeScript는 다른 분기의 유형을 좁히는 것을 이해할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TypeScript에서 typeof에 반환되는 값에 대해 체크하는 것이 유형 가드입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;타입스크립트는 타입이 다른 값에서 어떻게 동작하는지 인코딩하기 때문에 자바스크립트에서 그것의 기묘함 중 일부를 알고 있다. 아래의 예를 봐보면&lt;/p&gt;
&lt;pre class=&quot;typescript&quot;&gt;&lt;code&gt;function printAll(strs: string | string[] | null) {
  if (typeof strs === &quot;object&quot;) {
    for (const s of strs) {
      // Object is possibly 'null'
      console.log(s);
    }
  } else if (typeof strs === &quot;string&quot;) {
    console.log(strs);
  } else {
    // do nothing
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 코드를 보면 Object is possibly 'null' 에러를 내뿜는데, 그 이유는 object타입으로 타입을 좁히면 string[], null이 narrowing이 된다. (null의 타입도 object라는 사실~!)&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Truthiness narrowing&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;진실은 사전에서 찾을 수 있는 단어는 아닐지 몰라도, 자바스크립트에서는 아주 많이 들을 수 있는 단어야.JavaScript에서 조건에 대한 표현식을 사용하는데, 예를 들어 &amp;amp;&amp;amp;, ||, if, ! 등등이 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바스크립트에서는 if와 같은 분기문으로 해당 조건에 따라 강제분기를 합니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;0&lt;/li&gt;
&lt;li&gt;NaN&lt;/li&gt;
&lt;li&gt;&amp;ldquo;&amp;rdquo; (empty string)&lt;/li&gt;
&lt;li&gt;null&lt;/li&gt;
&lt;li&gt;0n(the bigint version of Zero)&lt;/li&gt;
&lt;li&gt;null&lt;/li&gt;
&lt;li&gt;undefined&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 값들은 false로 강제되고, 나머지는 다 true로 강제된다.&lt;/p&gt;
&lt;pre class=&quot;typescript&quot;&gt;&lt;code&gt;function printAll(strs: string | string[] | null) {
  if (strs &amp;amp;&amp;amp; typeof strs === &quot;object&quot;) {
    for (const s of strs) {
      console.log(s);
    }
  } else if (typeof strs === &quot;string&quot;) {
    console.log(strs);
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드를 보면 자연스럽게 truthy만 확인함으로써 나머지 에러들을 자연스럽게 제거하는 것을 확인할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;typeof 키워드만으로는 Null체크를 못해주기 때문에, 앞에서 falsy를 필터링해주어서 narrowing을 해준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;truthiness을 boolean을 !부정함으로써 좁히는 것도 방법입니다.&lt;/p&gt;
&lt;pre class=&quot;maxima&quot;&gt;&lt;code&gt;function multiplyAll(
  values: number[] | undefined,
  factor: number
): number[] | undefined {
  if (!values) {
    return values;
  } else {
    return values.map((x) =&amp;gt; x * factor);
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Equality narrowing&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TypeScript는 또한 switch 문을 사용하고 ==,! ==, ==, == 및! =와 같은 동등성 검사를 좁은 유형으로 사용합니다.&lt;/p&gt;
&lt;pre class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot;&gt;&lt;code&gt;if (x === y) {
    // We can now call any 'string' method on 'x' or 'y'.
    x.toUpperCase();
          //(method) String.toUpperCase(): string
    y.toLowerCase();
          //(method) String.toLowerCase(): string
  } else {
    console.log(x);
               //(parameter) x: string | number
    console.log(y);
               //(parameter) y: string | boolean
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;타입스크립트는 x,y가 같은 경우는&amp;nbsp; string이여야 동일함을 알고 있다. 따라서 첫번째 if문에서 타입스크립트는 x,y를 string으로 narrowing합니다. 또한 else문에서는 다양한 경우의 수가 오는 것까지 타입스크립트가 자동으로 추론합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;The &lt;b&gt;in&lt;/b&gt; operator narrowing&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JavaScript에는 개체에 이름이 있는 속성인 in 연산자가 있는지 여부를 결정하는 Type Guard가 있습니다. TypeScript는 잠재타입을 in으로 narrowing하여 고려합니다.&lt;/p&gt;
&lt;pre class=&quot;typescript&quot;&gt;&lt;code&gt;type Fish = { swim: () =&amp;gt; void };
type Bird = { fly: () =&amp;gt; void };
 
function move(animal: Fish | Bird) {
  if (&quot;swim&quot; in animal) {
    return animal.swim();
  }
 
  return animal.fly();
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;animal에는 Fish와 Bird가 있는데, animal속성에 따라 다르게 move동작을 해야하는데 이럴 때 in을 사용하여 narrowing합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;instanceof narrowing&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바스크립트에는 값이 다른 값의 &quot;인스턴스&quot;인지 여부를 확인하는 typeguard 연산자가 있다. 자바스크립트 x 인스턴스에서 foo의 프로토타입 체인이 foo.protype을 포함하고 있는지 확인한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예상하셨겠지만, instanceof 또한 타입가드이며 typeScript는 instanceof에 의해 타입을 좁힙니다.&lt;/p&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;function logValue(x: Date | string) {
  if (x instanceof Date) {
    console.log(x.toUTCString());
           //(parameter) x: Date
  } else {
    console.log(x.toUpperCase());
          //(parameter) x: string
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Assignments (할당을 통한 narrowing)&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞서 말했듯이 어떤 변수에 대입하면 TypeScript는 =할당 기준으로 오른쪽을 먼저 해석하여 왼쪽의 타입을 적절하게 좁힙니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래의 코드를 보면 처음에 삼항연산자를 통해서 x를 string과 number로 자동 narrowing을 해줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후에 x에 boolean값을 할당하면 x는 처음에 선언한 것만 가능하다고 타입스크립트가 에러를 던져주는 것을 확인할 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot;&gt;&lt;code&gt;let x = Math.random() &amp;lt; 0.5 ? 10 : &quot;hello world!&quot;;  //let x: string | number
x = 1;
console.log(x);   //let x: number
x = true; //불리언 값을 넣으려고 하면 에러가 남!
//Type 'boolean' is not assignable to type 'string | number'.
//처음에 선언한 것만 사용이 가능하다.
console.log(x);
     //let x: string | number&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Control flow analysis&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금까지 TypeScript가 특정 분기 내에서 좁혀지는 몇 가지 기본적인 예를 살펴보았다. 하지만 모든 변수에서 살펴보면 if, while, conditional 등을 통해 typeguard를 찾는 것 이상의 일이 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rArr; 코드의 흐름에 컨트롤에 따라서 typeguard가 지정이 된다는 의미같다. (잘 모르겠음)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Using type predicates&amp;nbsp;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리는 지금까지 좁히기를 처리하기 위해 기존 JavaScript 구문과 함께 작업했지만 때로는 코드 전체에서 유형이 어떻게 변경되는지에 대한 직접적인 제어를 원할 수도 있습니다. 사용자 정의 type guard를 직접 정의하기 위해서&amp;nbsp; is키워드를 통해 제어해줄 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;actionscript&quot;&gt;&lt;code&gt;function isFish(pet: Fish | Bird): pet is Fish {
  return (pet as Fish).swim !== undefined;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;isFish가 일부 변수와 함께 호출될 때마다, TypeScript는 만약 원래 타입이 호환이 되면 해당 변수를 특정 유형으로 좁힙니다.(isFish가 type guard이다)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;// Both calls to 'swim' and 'fly' are now okay.
let pet = getSmallPet();
 
if (isFish(pet)) {
  pet.swim();
} else {
  pet.fly();
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Discriminated unions&lt;/b&gt;&lt;/h2&gt;
&lt;pre class=&quot;groovy&quot;&gt;&lt;code&gt;interface Shape {
  kind: &quot;circle&quot; | &quot;square&quot;;
  radius?: number;
  sideLength?: number;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위를 보면 문자의 타입을 union을 사용하고있음을 알 수 있다.&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;pre class=&quot;ada&quot;&gt;&lt;code&gt;function getArea(shape: Shape) {
  return Math.PI * shape.radius ** 2;
//Object is possibly 'undefined'.
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반지름이 정의되지 않을 수도 있기 때문에 에러가 난다. shape의 속성에 검사를 수행한다면?&lt;/p&gt;
&lt;pre class=&quot;fortran&quot;&gt;&lt;code&gt;function getArea(shape: Shape) {
  if (shape.kind === &quot;circle&quot;) {
    return Math.PI * shape.radius ** 2;
//Object is possibly 'undefined'.
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;radius가 옵셔널이기 때문에 없을 수도 있다고 에러가난다. 우리는 위에서 배운 ! 을 사용하여 무조건 undefined가 아니라고 말한다.&lt;/p&gt;
&lt;pre class=&quot;fortran&quot;&gt;&lt;code&gt;function getArea(shape: Shape) {
  if (shape.kind === &quot;circle&quot;) {
    return Math.PI * shape.radius! ** 2;
  }
}
&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;적합한 방법은 아래와 같다&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;interface Circle {
  kind: &quot;circle&quot;;
  radius: number;
}
 
interface Square {
  kind: &quot;square&quot;;
  sideLength: number;
}
 
type Shape = Circle | Square;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; Shape를 분리하여 필요한 속성에 따라 다르게 분리한다.&lt;/p&gt;
&lt;pre class=&quot;fortran&quot;&gt;&lt;code&gt;function getArea(shape: Shape) {
  if (shape.kind === &quot;circle&quot;) {
    return Math.PI * shape.radius ** 2;
                      
  }
}
&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;Discriminated unions 는 이러한 예제 뿐만아니라, 네트워크(클라이언트/서버 통신)를 통해 메시지를 전송하거나 상태 관리 프레임워크에서 돌연변이를 인코딩할 때처럼 자바스크립트에서 모든 종류의 메시징 체계를 표현하는 데 유용하다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;The never Type&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;범위를 좁힐 때 조합의 선택권을 모든 가능성을 제거하고 남는 것이 없을 정도로 줄일 수 있습니다. 이 경우 TypeScript는 존재하지 않아야 하는 상태를 나타내기 위해 never 유형을 사용합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Exhaustiveness checking (철저한 체크!)&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Never 유형은 모든 유형에 할당할 수 있지만, Never 유형은 할당할 수 없다(Never 자체는 제외). 이것은 당신이 좁히기를 사용할 수 있고 스위치 문에서 철저한 점검을 하기 위해 절대 나타나지 않는 것에 의존할 수 있다는 것을 의미한다. 예를 들어, 모든 가능한 경우가 처리되지 않았을 때 절대로 발생하지 않을 모양을 할당하려고하는 getArea 함수에 기본값을 추가하십시오.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1666194391019&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;type Shape = Circle | Square;
 
function getArea(shape: Shape) {
  switch (shape.kind) {
    case &quot;circle&quot;:
      return Math.PI * shape.radius ** 2;
    case &quot;square&quot;:
      return shape.sideLength ** 2;
    default:
      const _exhaustiveCheck: never = shape;
      return _exhaustiveCheck;
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Shape 타입에 Triangle을 추가하게 되면 타입스크립트는 어떠한 타입도 와서는 안되는 never타입인데 타입이 있다는&amp;nbsp; 에러가 뜨게 된다.&lt;/p&gt;
&lt;pre id=&quot;code_1666194406282&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;interface Triangle {
  kind: &quot;triangle&quot;;
  sideLength: number;
}
 
type Shape = Circle | Square | Triangle;
 
function getArea(shape: Shape) {
  switch (shape.kind) {
    case &quot;circle&quot;:
      return Math.PI * shape.radius ** 2;
    case &quot;square&quot;:
      return shape.sideLength ** 2;
    default:
      const _exhaustiveCheck: never = shape;
Type 'Triangle' is not assignable to type 'never'.
      return _exhaustiveCheck;
  }
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>type &amp;amp; Javascript</category>
      <author>InformationFarm</author>
      <guid isPermaLink="true">https://soonysoon.tistory.com/107</guid>
      <comments>https://soonysoon.tistory.com/107#entry107comment</comments>
      <pubDate>Thu, 20 Oct 2022 00:53:53 +0900</pubDate>
    </item>
    <item>
      <title>Typescript handbook 읽고 정리</title>
      <link>https://soonysoon.tistory.com/106</link>
      <description>&lt;h1&gt;Everyday Types&lt;/h1&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;Array&amp;lt;number&amp;gt; vs number[]&lt;/li&gt;
&lt;li&gt;두개의 차이점을 이야기하자만, 전자는 generic syntax고, 후자는 shortand구문으로 제너릭이 필요한 경우 전자를 사용하면 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;any&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;any를 사용하는 경우 추가적인 타입검사 자체가 비활성화되며 보통 굳이 긴타입으로 정의하는 것이 비효율적일 때 사용한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;noImplicitAny 설정을 켜놓는 경우는 any를 사용하는 경우 오류를 발생시킵니다. (설정하기 나름이다&amp;hellip;)&lt;/p&gt;
&lt;/blockquote&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;const name : string = &amp;ldquo;Mercury&amp;rdquo;&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;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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;반환값은 표기하지 않아도 되는게 일반적? 왜..? &amp;rarr; return 문을 바탕으로 반환타입이 자동 추론되기 때문,&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;actionscript&quot;&gt;&lt;code&gt;function getFavoriteNumber(): number {
  return 26;
}
&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;함수 호출시 함수가 어떻게 호출될지 알 수 있다면, 매개변수에 자동으로 타입을 부여한다.(이러한 것은 문맥적 타입부여라고 한다.)&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;타입을 지정하지 않으면 any로 간주&lt;/li&gt;
&lt;li&gt;쉬워서 예시로 대체&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;// 매개 변수의 타입은 객체로 표기되고 있습니다.
function printCoord(pt: { x: number; y: number }) {
  console.log(&quot;The coordinate's x value is &quot; + pt.x);
  console.log(&quot;The coordinate's y value is &quot; + pt.y);
}
printCoord({ x: 3, y: 7 });
&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;/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;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;pre class=&quot;xquery&quot;&gt;&lt;code&gt;function printId(id: number | string) {
  if (typeof id === &quot;string&quot;) {
    // 이 분기에서 id는 'string' 타입을 가집니다
 
    console.log(id.toUpperCase());
  } else {
    // 여기에서 id는 'number' 타입을 가집니다
    console.log(id);
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rArr; 두개의 유니언 타입이 동일 메서드를 내장하고 있다면 문맥을 통해 상황을 좁히지 않아도 사용할 수 있다.&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;pre class=&quot;crmsh&quot;&gt;&lt;code&gt;type ID = number | string;
&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;css&quot;&gt;&lt;code&gt;interface Point {
  x: number;
  y: number;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고자료 - &lt;a href=&quot;https://medium.com/humanscape-tech/type-vs-interface-언제-어떻게-f36499b0de50&quot;&gt;https://medium.com/humanscape-tech/type-vs-interface-언제-어떻게-f36499b0de50&lt;/a&gt; interface vs type Interface 는&amp;nbsp;&lt;b&gt;선언 병합이 가능&lt;/b&gt; 하지만,&amp;nbsp;Type Alias는 불가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TypeScript 팀은&amp;nbsp;&lt;a href=&quot;https://ko.wikipedia.org/wiki/%EA%B0%9C%EB%B0%A9-%ED%8F%90%EC%87%84_%EC%9B%90%EC%B9%99&quot;&gt;개방-폐쇄 원칙&lt;/a&gt;에 따라 확장에 열려있는 JavaScript 객체의 동작 방식과 비슷하게 연결하도록&amp;nbsp;Interface를 설계했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 TypeScript 팀은 가능한&amp;nbsp;Type Alias보단&amp;nbsp;Interface를 사용하고, 합 타입 혹은 튜플 타입을 반드시 써야 되는 상황이면&amp;nbsp;Type Alias를 사용하도록 권장하고 있습니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;타입단언 (as)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자가 더 타입에 대한 정보를 잘 아니까 너에게 권한을 줄게!의 의미에서 생긴 타입스크립트의 키워드이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;타입 assertion은 컴파일러에 의해서 제거된다. 따라서 검사는 런타임중에 이루어지지 않는다. 따라서 틀리더라도 예외가 발생하지 않는다.&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;pre class=&quot;bash&quot;&gt;&lt;code&gt;let x: &quot;hello&quot; = &quot;hello&quot;;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같은 예시를 보면 딱히? 왜 쓸까? 하는 생각이 든다&amp;hellip;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 유니언과 함께 사용한다면?&lt;/p&gt;
&lt;pre class=&quot;1c&quot;&gt;&lt;code&gt;const direction : &quot;left&quot; | &quot;rigth&quot; |&quot;up&quot; |&quot;down&quot; = &quot;up&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;딱 봐도 쓸 곳이 많아보이죠? 필요없는 것은 만들지도 않았을 겁니다.ㅋㅋ&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-10-05 오후 11.17.47.png&quot; data-origin-width=&quot;592&quot; data-origin-height=&quot;462&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/QeBPV/btrNTKV9jmn/rntkp88pkRMfkwMGg6b2Z0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/QeBPV/btrNTKV9jmn/rntkp88pkRMfkwMGg6b2Z0/img.png&quot; data-alt=&quot;타입스크립트 너는 다 계획이 있구나&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/QeBPV/btrNTKV9jmn/rntkp88pkRMfkwMGg6b2Z0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQeBPV%2FbtrNTKV9jmn%2Frntkp88pkRMfkwMGg6b2Z0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;359&quot; height=&quot;280&quot; data-filename=&quot;스크린샷 2022-10-05 오후 11.17.47.png&quot; data-origin-width=&quot;592&quot; data-origin-height=&quot;462&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;b&gt;리터럴도 추론이 될까요 그럼?&lt;/b&gt;&lt;/p&gt;</description>
      <category>type &amp;amp; Javascript</category>
      <author>InformationFarm</author>
      <guid isPermaLink="true">https://soonysoon.tistory.com/106</guid>
      <comments>https://soonysoon.tistory.com/106#entry106comment</comments>
      <pubDate>Wed, 5 Oct 2022 23:18:35 +0900</pubDate>
    </item>
    <item>
      <title>HTTP 흐름 가볍게 이해하기 (1~3까지)</title>
      <link>https://soonysoon.tistory.com/104</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;  HTTP이 발전 이해하기  &lt;/span&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;HTTP/0.9&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;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;GET메소드만 존재&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;HTML만 읽을 수 있고 클라이언트 정보 X&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;하지만 WWW의 근간이 되어 더욱이 발전할 수 있었음&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;HTTP/1.0&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;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;헤더를 통해 클라이언트와 서버 정보 전달이 가능해졌다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;또한, content-type헤더를 통해서 HTML뿐만 아니라, 이미지 동영상같은 다양한 정보를 주고 받을 수 있게 되었다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;POST가 추가되어 클라이언트의 정보를 웹으로 전달할 수 있게 되었다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;content-Encoding을 통해서 클라이언트와 서버간의 압축정보를 공유가 가능해졌다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;HTTP/1.1&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;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;HTTP의 첫 번쨰 공식 표준버전이다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;GET, POST, PUT, DELETE의 함수를 모두 지원&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;하나의 TCP 연결을 지속적 연결을 추가함으로 재사용해 많은 콘텐츠 전달&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;via 헤더로 중계서버 정보 공유, accept헤더로 클라이언트 지원 형식을 알 수 있게 됨&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;하지만 HOL(Head-Of-Line-blocking)문제를 해결하지 못했다.&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이는 서버가 응답을 지연하면 나머지의 요청또한 지연이 되는 것을 의미한다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;HTTP/2&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;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;보다 개선된 웹프로토콜을 위해 구글이 시작한 SPDY프로젝트이다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;텍스트 방식으 프로토콜 메시지를 binaray format을 사용해 경량화 함&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;HTTP1.1의 비해 멀티플렉싱, 스트림 우선순위 설정, 헤더압축, 서버 푸시같은 최적화 기능이 추가되었다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;HTTP2.0은 HOC의 문제를 해결했으나 TCP의 HOC문제는 해결하지 못했다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;HTTP&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;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;새로운 프로토콜인 QUIC(전송프로토콜)를 사용하는 HTTP의 최상위 버전이다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;QUIC는 UDP프로토콜을 채택했고, 구글에서 개발을 하였습니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;QUIC는 한 번 맺은 QUIC를 최대한 재사용하기 때문에 클라이언트와 서버간의 연결을 만다는 과정의 시간이 대폭 줄어들었다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;하지만 아직은 실험적인 단계이므로 많이 사용하지 않는다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-08-03 오후 9.55.02.png&quot; data-origin-width=&quot;1086&quot; data-origin-height=&quot;970&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ct5SDn/btrIPYyGRK3/nKy2kKqMXStzzaMYfbGTgK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ct5SDn/btrIPYyGRK3/nKy2kKqMXStzzaMYfbGTgK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ct5SDn/btrIPYyGRK3/nKy2kKqMXStzzaMYfbGTgK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fct5SDn%2FbtrIPYyGRK3%2FnKy2kKqMXStzzaMYfbGTgK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;716&quot; height=&quot;640&quot; data-filename=&quot;스크린샷 2022-08-03 오후 9.55.02.png&quot; data-origin-width=&quot;1086&quot; data-origin-height=&quot;970&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;  HTTP/2의 최적화 기술  &lt;/span&gt;&lt;/h2&gt;
&lt;aside&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;  HTTP2의 가장 큰 목표는 클라이언트와 서버가 컨텐츠주고받는 시간을 줄이고 서버 응답이 느린 콘텐츠가 다른 정상적인 컨텐츠를 방해하지 않도록 하는 것&lt;/span&gt;&lt;/aside&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&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;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;기존 텍스트 방식을 이진프레임방식으로 바꾸며 프로토콜을 경량화했다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;HTTP요청과 응답의 중복헤더를 걸러 내어 헤더의 크기를 최소화 함&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;서버푸시를 통해 서버가 미리 빠르게 전송하여 RTT를 최소화 함&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;구글 SPDY를 통해 최대 55%빠른 앱을 만듬&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;HTTP/2 의 이진프레임&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;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;HTTP2 이전에 요청과 응답은 메세지라는 단위로 구성되어있다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;HTTP/2에서는 메시지 단위 말고도 프레임, 스트림이라는 단위가 푸가되었다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;프레임 : HTTP2통신상 가장 작은 정보 단위이며 헤더나 데이터 중 하나&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;메세지 : HTTP1과 마찬가지로 응답단위이고 다수의 프레임으로 이루어져있음&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;스트림 : 클라이언트와 서버 사이의 맺어진 연경을 통해 양방향으로 주고 받는 하나 혹은 복수의 메지시이다.&lt;/span&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-08-03 오후 9.55.26.png&quot; data-origin-width=&quot;1076&quot; data-origin-height=&quot;418&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pPXYq/btrIUmLZpxe/e8sw3szsUQVWI8jgwXjXVk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pPXYq/btrIUmLZpxe/e8sw3szsUQVWI8jgwXjXVk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pPXYq/btrIUmLZpxe/e8sw3szsUQVWI8jgwXjXVk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpPXYq%2FbtrIUmLZpxe%2Fe8sw3szsUQVWI8jgwXjXVk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1076&quot; height=&quot;418&quot; data-filename=&quot;스크린샷 2022-08-03 오후 9.55.26.png&quot; data-origin-width=&quot;1076&quot; data-origin-height=&quot;418&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;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;여러 프레임이 모여 메세지가 되고, 여러개의 메세지가 모여서 스트림이 된다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;큰 데이터는 여러개의 프레임에 나뉘어 전달되는데 멀티플렉싱이 적용되어 순서에 상관없이 전달이 되고 클라이언트는 프레임들을 조림하여 완료하여 완전한 데이터를 만들어 낸다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;하나의 TCP연결을 통해 다수의 클라이 언트 요청과 서버의 응답이 비동기 방식으로 이루어지는 멀티플렉싱을 사용되어 HTTP1.1의 HOC문제가 자연스레 해결이 되었다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;멀티플렉싱&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-08-03 오후 9.55.39.png&quot; data-origin-width=&quot;988&quot; data-origin-height=&quot;444&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FRn0v/btrINuSC3hN/Up7gHMuDGhKJp2BsLsZTPk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FRn0v/btrINuSC3hN/Up7gHMuDGhKJp2BsLsZTPk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FRn0v/btrINuSC3hN/Up7gHMuDGhKJp2BsLsZTPk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFRn0v%2FbtrINuSC3hN%2FUp7gHMuDGhKJp2BsLsZTPk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;988&quot; height=&quot;444&quot; data-filename=&quot;스크린샷 2022-08-03 오후 9.55.39.png&quot; data-origin-width=&quot;988&quot; data-origin-height=&quot;444&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;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;파이프라이닝은 선입선출의 방식을 계속해서 사용했기 때문에 HOC가 해결되지 않았다. HTTP멀티플렉싱의 스트림의 유연한 구조로 인해 응답 프레임들은 요청 순서에 상관없이 만들어진 순서대로 클라이 언트에 전달이 가능하다&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;code&gt;멀티플렉싱&lt;/code&gt; : TCP 연결상에서 다수의 클라이언트 요청과 서버의 응답이 비동기방식으로 이루어지는 기술을 멀티플렉싱이라 한다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&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;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;HTTP1.1까지는 content-Encoding을 헤더를 통한 알고리즘을 사용해 HTTP페이로드를 서버에서 압축했다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;따라서 헤더는 압축없이 그대로 전달이 되는 문제가 있었다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;HTTP2는 클라이언트와 서버사이의 가상테이블을 설정하고 중복되는 헤더값을 테이블에 저장하고 참고하는 방식으로 중복 전달을 제거했다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;클라이언트가 두번의 요청을 보낸다고 가정하면 HTTP/1.x의 경우 두개의 요청 Header에 중복 값이 존재해도 그냥 중복 전송한다. 하지만 HTTP/2에선 Header에 중복값이 존재하는 경우 Static/Dynamic Header Table 개념을 사용하여 중복 Header를 검출하고 중복된 Header는 index값만 전송하고 중복되지 않은 Header정보의 값은 Huffman Encoding 기법으로 인코딩 처리 하여 전송한다.&lt;/span&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-08-03 오후 9.55.54.png&quot; data-origin-width=&quot;1108&quot; data-origin-height=&quot;446&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/0hybH/btrIT8G34CU/nCey3vkyFaHfvGqvFES3r1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/0hybH/btrIT8G34CU/nCey3vkyFaHfvGqvFES3r1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/0hybH/btrIT8G34CU/nCey3vkyFaHfvGqvFES3r1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F0hybH%2FbtrIT8G34CU%2FnCey3vkyFaHfvGqvFES3r1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1108&quot; height=&quot;446&quot; data-filename=&quot;스크린샷 2022-08-03 오후 9.55.54.png&quot; data-origin-width=&quot;1108&quot; data-origin-height=&quot;446&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;서버 푸시&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;클라이언트의 요청이 없이도 서버가 응답을 알아서 보내는 서버푸시 기능이 HTTP2에서 추가되었다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-08-03 오후 9.56.11.png&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;428&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/JdHW5/btrIJ7C4hzN/zVhubbqGvJqk1cRoBgHlM1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/JdHW5/btrIJ7C4hzN/zVhubbqGvJqk1cRoBgHlM1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/JdHW5/btrIJ7C4hzN/zVhubbqGvJqk1cRoBgHlM1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJdHW5%2FbtrIJ7C4hzN%2FzVhubbqGvJqk1cRoBgHlM1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1024&quot; height=&quot;428&quot; data-filename=&quot;스크린샷 2022-08-03 오후 9.56.11.png&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;428&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;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;서버푸시의 대상은 웹서버 관리자나 개발자가 미리정할 수 있다.&lt;/span&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-08-03 오후 9.56.37.png&quot; data-origin-width=&quot;1032&quot; data-origin-height=&quot;246&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bnXYyZ/btrIK8Itp6Z/Bzyeo8gSlGHJh5liUaUf4K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bnXYyZ/btrIK8Itp6Z/Bzyeo8gSlGHJh5liUaUf4K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bnXYyZ/btrIK8Itp6Z/Bzyeo8gSlGHJh5liUaUf4K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbnXYyZ%2FbtrIK8Itp6Z%2FBzyeo8gSlGHJh5liUaUf4K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1032&quot; height=&quot;246&quot; data-filename=&quot;스크린샷 2022-08-03 오후 9.56.37.png&quot; data-origin-width=&quot;1032&quot; data-origin-height=&quot;246&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;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;추가적인 왕복이 필요하지 않다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  HTTP/3의 최적화 기술 ⛱️&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;QUIC (새로운 전송계층)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;구글에서 개발한 OSI 네번째 계층인 전송계층 프로토콜이다.&lt;/li&gt;
&lt;li&gt;Quick UDP Internet Connections를 의미한다.&lt;/li&gt;
&lt;li&gt;전달 속도 향상과 더불어 클라이언트와 서버의 연걸 수를 최소화하고 대역폭을 예상해 패킷의 혼잡을 피하는 것이 주요 특징이다&lt;/li&gt;
&lt;li&gt;클라이언트가 서버를 한 번이라도 접속을 했다면, 별로의 정보교환 없이 바로 데이터를 보내는 기술을 Zero RTT라고 한다.&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-08-03 오후 9.58.58.png&quot; data-origin-width=&quot;1098&quot; data-origin-height=&quot;550&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Lm0Ls/btrINtTI3zL/QmUi3Aer3KZhE7pu8DuDnk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Lm0Ls/btrINtTI3zL/QmUi3Aer3KZhE7pu8DuDnk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Lm0Ls/btrINtTI3zL/QmUi3Aer3KZhE7pu8DuDnk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLm0Ls%2FbtrINtTI3zL%2FQmUi3Aer3KZhE7pu8DuDnk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1098&quot; height=&quot;550&quot; data-filename=&quot;스크린샷 2022-08-03 오후 9.58.58.png&quot; data-origin-width=&quot;1098&quot; data-origin-height=&quot;550&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;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;UDP로 바꾸는게 성능향상이 되는이유&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;UDP의 헤더의 크기가 작은만큼 보내는 데이터의 지연을 줄일 수 있습니다.&lt;/li&gt;
&lt;li&gt;QUIC 방식이 UDP의 방식으로 Zero RTT(Round Trip Time, 왕복 시간)로 연결에 걸리는 시간이 줄어듭니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;HTTP/3의 특징&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;가장 큰 특징은 TCP/IP기반의 레이어 프로토콜인 HTTP를 QUIC위로 이동시켰다는 것이다.&lt;/li&gt;
&lt;li&gt;이를 HQ라고 부른다(HTTP over QUIC)&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-08-03 오후 9.59.30.png&quot; data-origin-width=&quot;1034&quot; data-origin-height=&quot;498&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bcA2Ik/btrIO3GZR62/3XU4F0nLc2KDW2S8BwBmZ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bcA2Ik/btrIO3GZR62/3XU4F0nLc2KDW2S8BwBmZ1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bcA2Ik/btrIO3GZR62/3XU4F0nLc2KDW2S8BwBmZ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbcA2Ik%2FbtrIO3GZR62%2F3XU4F0nLc2KDW2S8BwBmZ1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1034&quot; height=&quot;498&quot; data-filename=&quot;스크린샷 2022-08-03 오후 9.59.30.png&quot; data-origin-width=&quot;1034&quot; data-origin-height=&quot;498&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;</description>
      <category>web</category>
      <author>InformationFarm</author>
      <guid isPermaLink="true">https://soonysoon.tistory.com/104</guid>
      <comments>https://soonysoon.tistory.com/104#entry104comment</comments>
      <pubDate>Wed, 3 Aug 2022 21:59:57 +0900</pubDate>
    </item>
    <item>
      <title>CSS Ecosystem</title>
      <link>https://soonysoon.tistory.com/102</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Vanilla CSS&lt;/b&gt;&lt;/h3&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;/ul&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;범위가 지정되지 않는 단점이 있다. 한 곳에 작성한 CSS는 모든 곳에 진행되기 때문에 BEM과 같은 명명법을 통해서 해결해 나갈 수 있으나, 이는.. 엄청난 노력이 필요함&lt;/li&gt;
&lt;li&gt;최적의 브라우저 지원을 위해 많은 CSS에 대해서 브라우저의 접두서를 추가해야함&lt;/li&gt;
&lt;li&gt;JS와의 공유가 어려움&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;b&gt;Sass&amp;nbsp; /&amp;nbsp; Less&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Scss는 바닐라 CSS로 컴파일 되는 전처리기 입니다. 중첩, 변수 및 iteration의 기능으로 바닐라 CSS를 커버합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;작동방식은 타입스크립트와 비슷합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Less 도 Sass와 방식이 아주 유사한데, 차이점이라고 하면 변수에 지정을 다르게 한다&lt;/p&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;for-loop, mixin nesting 같은 강력한 도구가 포함&lt;/li&gt;
&lt;li&gt;바닐라 CSS에 비해 좋음&lt;/li&gt;
&lt;/ul&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;CSS로 검파일 되기 때문에 본질적으로는 전역적으로 유지된다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;빌드시간으로 인해 실시간으로 반영이 안됨 이러한 이유때문에 Sass변수는 CSS변수 만큼 강력하지 않음&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 id=&quot;aphrodite&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Aphrodite&lt;/b&gt;&amp;nbsp;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이름이 이쁜데... 처음들어본다 최초의 CSS-in-JS중 하나라고 합니다. Styled-component와 유사하게 보임&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1658144247562&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import { StyleSheet, css } from 'aphrodite';
function App() {
  return (
    &amp;lt;div className={css(styles.wrapper)}&amp;gt;
      Hello World!
    &amp;lt;/div&amp;gt;
  );
}
const styles = StyleSheet.create({
  wrapper: {
    backgroundColor: 'gray',
    minHeight: 200,
    '@media (min-width: 1025px)': {
      fontSize: '1.25rem',
    },
  },
});&lt;/code&gt;&lt;/pre&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;CSS 내에서 JS를 사용할 수 있습니다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;자동으로 prefix를 추가해주기 때문에 걱정할 필요가 없다.&lt;/li&gt;
&lt;/ul&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;2020년에 새로운 릴리즈가 없고 활발한 프로젝트가아니다.&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;b&gt;CSS 모듈&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;css모듈은 바닐라 css로 작성하고 JS로 가져올 수 있는 도구입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1658149109314&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/* App.module.css */
.wrapper {
  background-color: gray;
  min-height: 200px;
}
@media (min-width: 1025px) {
  .wrapper {
    font-size: 1.25rem;
  }&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1658149116449&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// App.js
import styles from './App.module.css';
function App() {
  return (
    &amp;lt;div className={styles.wrapper}&amp;gt;
      Hello World!
    &amp;lt;/div&amp;gt;
  );
}&lt;/code&gt;&lt;/pre&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;/ul&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;css와 js간에 데이터 공유가 어렵습니다.&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 id=&quot;single-file-components&quot; data-ke-size=&quot;size26&quot;&gt;Single-file components&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴포넌트가 지정된 파일에서 CSS룰 생성하는 방법&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;큰 이점은 스타일과 마크업이 동일한파일에 작성되어 파일간의 이동이 줄어든다는 점이다.&lt;/p&gt;
&lt;pre id=&quot;code_1658149442190&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// Hello.vue
&amp;lt;template&amp;gt;
  &amp;lt;p&amp;gt;Hello World&amp;lt;/p&amp;gt;
&amp;lt;/template&amp;gt;
&amp;lt;style scoped&amp;gt;
  p {
    background-color: gray;
    min-height: 200px;
  }
  @media (min-width: 1025px) {
    p {
      font-size: 1.25rem;
    }
  }
&amp;lt;/style&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 id=&quot;styled-components&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;styled-components&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스타일 컴포넌트도 css-in-JS솔루션이다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1658153226448&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import styled from 'styled-components';
function App() {
  return (
    &amp;lt;Wrapper&amp;gt;
      Hello World!
    &amp;lt;/Wrapper&amp;gt;
  );
}
const Wrapper = styled.div`
  background-color: gray;
  min-height: 200px;
  @media (min-width: 1025px) {
    font-size: 1.25rem;
  }
`;&lt;/code&gt;&lt;/pre&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;CSS를 작성하는 것처럼 느껴져서 사용하기 쉽다.&lt;/li&gt;
&lt;li&gt;애니메이션 및 전역스타일을 위한 도구를 제공한다.&lt;/li&gt;
&lt;li&gt;개발자의 만족도가 높아진다.&lt;/li&gt;
&lt;li&gt;SSR을 지원하고 성능이 매우 향상되고 있다.&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;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;빌드시스템이 빌표하다&lt;/li&gt;
&lt;li&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;p data-ke-size=&quot;size16&quot;&gt;이 말고도, Emotion, Tailwind같은&amp;nbsp; 도구들이 많이 생기고 있어 우리가 사용할 수 있는 CSS 도구들은 너무~ 많다.&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;</description>
      <category>web/CSS</category>
      <author>InformationFarm</author>
      <guid isPermaLink="true">https://soonysoon.tistory.com/102</guid>
      <comments>https://soonysoon.tistory.com/102#entry102comment</comments>
      <pubDate>Mon, 18 Jul 2022 23:14:51 +0900</pubDate>
    </item>
    <item>
      <title>[ Rendering Logic2 ] Sticky Positioning</title>
      <link>https://soonysoon.tistory.com/101</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;Sticky Positioning&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;position : sticky는 스크롤 할 때 요소가 상태적인 위치에서 고정위치로 전환되는 속성입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;position : sticky 뿐만 아니라 top, right, left, bottom등 하나 이상을 선택해야 수행이 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Sticky position에는 몇가지 특이한 세부사항이 있는데 이를 살펴보자!&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;span style=&quot;color: #ef5369;&quot;&gt;&lt;b&gt;Stays in their box&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;position : sticky가 자주 간과되는 것은 상위 컨테이너에서 외부 스크롤을 따르지 않는다는 것이다.&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 alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-06-26 오후 9.45.38.png&quot; data-origin-width=&quot;1460&quot; data-origin-height=&quot;780&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bQkIM9/btrFLCMdrMy/D8LFamrOJstWhwxO3PIRrk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bQkIM9/btrFLCMdrMy/D8LFamrOJstWhwxO3PIRrk/img.png&quot; data-alt=&quot;스크롤을 내리지 않았을 때.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bQkIM9/btrFLCMdrMy/D8LFamrOJstWhwxO3PIRrk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbQkIM9%2FbtrFLCMdrMy%2FD8LFamrOJstWhwxO3PIRrk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;671&quot; height=&quot;358&quot; data-filename=&quot;스크린샷 2022-06-26 오후 9.45.38.png&quot; data-origin-width=&quot;1460&quot; data-origin-height=&quot;780&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;스크롤을 내리지 않았을 때.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-06-26 오후 9.46.28.png&quot; data-origin-width=&quot;1486&quot; data-origin-height=&quot;780&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bAWeri/btrFRdj7s3C/oTcFH1ig4KldWTJ9r1l731/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bAWeri/btrFRdj7s3C/oTcFH1ig4KldWTJ9r1l731/img.png&quot; data-alt=&quot;스크롤을 내릴 때&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bAWeri/btrFRdj7s3C/oTcFH1ig4KldWTJ9r1l731/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbAWeri%2FbtrFRdj7s3C%2FoTcFH1ig4KldWTJ9r1l731%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/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;365&quot; data-filename=&quot;스크린샷 2022-06-26 오후 9.46.28.png&quot; data-origin-width=&quot;1486&quot; data-origin-height=&quot;780&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;아래의 예시를 보면 Section1, 2, 3가 내려도 컨텐츠 옆에 붙어서 유지되는 것을 확인 할 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래의 코드를 통해서 이를 구현할 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1656247813790&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;section h2 {
  position: sticky;
  top: 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-06-26 오후 9.49.39.png&quot; data-origin-width=&quot;1480&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bquUlZ/btrFId7I0HY/g2d9KKIgPXJWKjWuMege1k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bquUlZ/btrFId7I0HY/g2d9KKIgPXJWKjWuMege1k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bquUlZ/btrFId7I0HY/g2d9KKIgPXJWKjWuMege1k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbquUlZ%2FbtrFId7I0HY%2Fg2d9KKIgPXJWKjWuMege1k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;674&quot; height=&quot;1080&quot; data-filename=&quot;스크린샷 2022-06-26 오후 9.49.39.png&quot; data-origin-width=&quot;1480&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-06-26 오후 9.51.43.png&quot; data-origin-width=&quot;1510&quot; data-origin-height=&quot;1034&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/AZ6y1/btrFRb0VgdU/MXfSh4PK6oe7KeLtmk4t20/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/AZ6y1/btrFRb0VgdU/MXfSh4PK6oe7KeLtmk4t20/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/AZ6y1/btrFRb0VgdU/MXfSh4PK6oe7KeLtmk4t20/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FAZ6y1%2FbtrFRb0VgdU%2FMXfSh4PK6oe7KeLtmk4t20%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;663&quot; height=&quot;1034&quot; data-filename=&quot;스크린샷 2022-06-26 오후 9.51.43.png&quot; data-origin-width=&quot;1510&quot; data-origin-height=&quot;1034&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;&lt;b&gt;Offset&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;position value는 top/right/left/bottom이 작동하는 방식에 영향을 준다.&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;상대 위치지정을 사용하면, 자연스러운 유입 위치에서 이동한다.&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;아래의 예시처럼 .sticky에 &amp;nbsp;position: sticky;width: 50px; height: 50px;를 주고 각각 다른 공에 top설정을 다르게 지정한 후&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-06-26 오후 9.58.51.png&quot; data-origin-width=&quot;1454&quot; data-origin-height=&quot;966&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ewHqkQ/btrFOwLhXjL/xe91RypkNiyfkNViHRfM7K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ewHqkQ/btrFOwLhXjL/xe91RypkNiyfkNViHRfM7K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ewHqkQ/btrFOwLhXjL/xe91RypkNiyfkNViHRfM7K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FewHqkQ%2FbtrFOwLhXjL%2Fxe91RypkNiyfkNViHRfM7K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1454&quot; height=&quot;966&quot; data-filename=&quot;스크린샷 2022-06-26 오후 9.58.51.png&quot; data-origin-width=&quot;1454&quot; data-origin-height=&quot;966&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;&lt;b&gt;Not Incorporeal 무형적이 않다&lt;/b&gt;&lt;/span&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&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-06-26 오후 10.06.35.png&quot; data-origin-width=&quot;1492&quot; data-origin-height=&quot;874&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ebICdb/btrFJmpPAnR/dwigGfy4wEy2LkiD2xASTk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ebICdb/btrFJmpPAnR/dwigGfy4wEy2LkiD2xASTk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ebICdb/btrFJmpPAnR/dwigGfy4wEy2LkiD2xASTk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FebICdb%2FbtrFJmpPAnR%2FdwigGfy4wEy2LkiD2xASTk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;671&quot; height=&quot;393&quot; data-filename=&quot;스크린샷 2022-06-26 오후 10.06.35.png&quot; data-origin-width=&quot;1492&quot; data-origin-height=&quot;874&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-06-26 오후 10.06.52.png&quot; data-origin-width=&quot;1526&quot; data-origin-height=&quot;498&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/AGP1l/btrFGPMaGi0/rdvy4LauHd4SgkRuxctUSk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/AGP1l/btrFGPMaGi0/rdvy4LauHd4SgkRuxctUSk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/AGP1l/btrFGPMaGi0/rdvy4LauHd4SgkRuxctUSk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FAGP1l%2FbtrFGPMaGi0%2Frdvy4LauHd4SgkRuxctUSk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/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;224&quot; data-filename=&quot;스크린샷 2022-06-26 오후 10.06.52.png&quot; data-origin-width=&quot;1526&quot; data-origin-height=&quot;498&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 id=&quot;horizontal-stickiness&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;&lt;b&gt;Horizontal stickiness&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;고정위치는 거의! 수직 스크롤과 함꼐 사용되지만 반드시 그럴 필요는 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래는 수평으로의 예이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-06-26 오후 10.09.45.png&quot; data-origin-width=&quot;1516&quot; data-origin-height=&quot;834&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b2tyPN/btrFLCFvdas/E3UKKBigSu5BViSlDSX101/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b2tyPN/btrFLCFvdas/E3UKKBigSu5BViSlDSX101/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b2tyPN/btrFLCFvdas/E3UKKBigSu5BViSlDSX101/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb2tyPN%2FbtrFLCFvdas%2FE3UKKBigSu5BViSlDSX101%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/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;834&quot; data-filename=&quot;스크린샷 2022-06-26 오후 10.09.45.png&quot; data-origin-width=&quot;1516&quot; data-origin-height=&quot;834&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;&lt;b&gt;Trouble Shooting&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;position : sticky 가 적용되지 않는 경우들이 종종있는데, 몇 가지 이유에 대해서 알아보자.&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;A parent is hiding / mamging overflow&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 흔한 이유인데 부모요소의 &amp;nbsp;overflow: auto; 가 있는 경우 해당 이슈가 생긴다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리가 overflow에 hiddent이나 scroll이나, auto를 설정하는 경우 내부에서의 context만 stick이고 &lt;span&gt;더 큰 context에서는 반영이 되지 않는다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;그 이유는 더 큰 context가 스크롤이 가능할 때만 요소의 sticky가 동작을 한다&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&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-07-03 오후 6.55.31.png&quot; data-origin-width=&quot;2102&quot; data-origin-height=&quot;914&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bbIasf/btrGnV4Dwbr/fYDPDg7RYF1u0ljOUzUaZ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bbIasf/btrGnV4Dwbr/fYDPDg7RYF1u0ljOUzUaZ0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bbIasf/btrGnV4Dwbr/fYDPDg7RYF1u0ljOUzUaZ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbbIasf%2FbtrGnV4Dwbr%2FfYDPDg7RYF1u0ljOUzUaZ0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;754&quot; height=&quot;914&quot; data-filename=&quot;스크린샷 2022-07-03 오후 6.55.31.png&quot; data-origin-width=&quot;2102&quot; data-origin-height=&quot;914&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;position : sticky는 상위 한개의 context에서만 작동하므로, main에 scroll가능하도록 만들던지, 조상 요소의 해당 요소를 붙인다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;the-container-isnt-big-enough&quot; data-ke-size=&quot;size26&quot;&gt;The container isn't big enough&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;sticky요소가 상위 컨테이너내에서 이동할 공간이 있는지 확인을 해라&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;sticky요소는 뷰포트를 따르기 때문에 상위컨테이너에서 공간이 있는 경우만 sticky요소가 작용한다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;the-sticky-element-is-stretched&quot; data-ke-size=&quot;size26&quot;&gt;The sticky element is stretched&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;flex, gird속성을 사용한 경우에는 요소가 상위 컨테이너에서 움직일 공간이 없도록 만들기 때문에 sticky요소가 cross축을 따라 늘어나는 것이 가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;theres-a-thin-gap-above-my-sticky-header&quot; data-ke-size=&quot;size26&quot;&gt;There's a thin gap above my sticky header!&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;뷰포트 가장 자리를 기준으로 요소를 배치하려는 경우 얇은 1px 의 간격이 생긴다. 이것은 화소에 대한 반올림 문제인데&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래의 코드 스니펫으로 이를 해결할 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1656844660245&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;header {
  position: sticky;
  top: -1px; /* -1px instead of 0px */
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>web/CSS</category>
      <author>InformationFarm</author>
      <guid isPermaLink="true">https://soonysoon.tistory.com/101</guid>
      <comments>https://soonysoon.tistory.com/101#entry101comment</comments>
      <pubDate>Sun, 26 Jun 2022 22:26:19 +0900</pubDate>
    </item>
    <item>
      <title>[ Rendering Logic2 ] Fixed Positioning</title>
      <link>https://soonysoon.tistory.com/99</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;Fixed Positioning&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;fixed positioning은 absolute와 비슷한 역할을 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;차이점은 훨씬 반항적이여서 뷰포트에서만 억제가 가능하다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(viewport는 현재 눈에 보이는 웹사이트의 일부)&lt;/p&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 alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-06-15 오전 8.39.30.png&quot; data-origin-width=&quot;588&quot; data-origin-height=&quot;532&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/te1Qq/btrENfSFaXg/z4Ugr7yx4weXLpklkvvX40/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/te1Qq/btrENfSFaXg/z4Ugr7yx4weXLpklkvvX40/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/te1Qq/btrENfSFaXg/z4Ugr7yx4weXLpklkvvX40/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fte1Qq%2FbtrENfSFaXg%2Fz4Ugr7yx4weXLpklkvvX40%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;385&quot; height=&quot;532&quot; data-filename=&quot;스크린샷 2022-06-15 오전 8.39.30.png&quot; data-origin-width=&quot;588&quot; data-origin-height=&quot;532&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 해당 버튼은 스크롤할 때도 움직이지 않고 고정되어있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f2f2f2; color: #0a0c10;&quot;&gt;Instead of the closest non-static ancestor, it listens to the&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&amp;ldquo;initial containing block&amp;rdquo;&lt;span style=&quot;background-color: #f2f2f2; color: #0a0c10;&quot;&gt;, a box the size and position of the&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;viewport&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;absolute 로 modal을 만든 것 처럼, fixed 로도 모달같은 오버레이 효과를 줄 수 있습니다.&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-06-15 오전 8.52.19.png&quot; data-origin-width=&quot;1610&quot; data-origin-height=&quot;860&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bcFaet/btrEO426o4x/EA9mLP3tKvsjN5sY8qwfQK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bcFaet/btrEO426o4x/EA9mLP3tKvsjN5sY8qwfQK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bcFaet/btrEO426o4x/EA9mLP3tKvsjN5sY8qwfQK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbcFaet%2FbtrEO426o4x%2FEA9mLP3tKvsjN5sY8qwfQK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1610&quot; height=&quot;860&quot; data-filename=&quot;스크린샷 2022-06-15 오전 8.52.19.png&quot; data-origin-width=&quot;1610&quot; data-origin-height=&quot;860&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 style=&quot;color: #000000;&quot;&gt;Absolute와 fixed의 차이점을 보면, 스크롤의 대해서 영향을 받는지 안받는지에 대해서 알 수 있습니다!&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(앞으로 modal은 &lt;span style=&quot;color: #000000;&quot;&gt;fixed가 좋지 않을까? 생각을 해봅니다....&lt;/span&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;the-transform-exception&quot; data-ke-size=&quot;size26&quot;&gt;The transform exception (변환 예외)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반적으로 fixed는 viewport 기준으로 배치되지만 한가지 예외가 있습니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;parent나 grand parent가 transform 속성을 사용하는 경우는 &lt;span style=&quot;background-color: #f2f2f2; color: #0a0c10;&quot;&gt;fixed element&amp;nbsp;&lt;span style=&quot;background-color: #ffffff;&quot;&gt; 에 containing블록이 되어 absolutly-positioned 된다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f2f2f2; color: #0a0c10;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;기억 할 점은 transform된 부모가 fixed children을 가질 수 없다는 것이다.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-06-15 오전 8.59.44.png&quot; data-origin-width=&quot;596&quot; data-origin-height=&quot;768&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bzHcsj/btrEQSg9FCf/ZM6FSQt7tt3AKGt2Bcb3dK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bzHcsj/btrEQSg9FCf/ZM6FSQt7tt3AKGt2Bcb3dK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bzHcsj/btrEQSg9FCf/ZM6FSQt7tt3AKGt2Bcb3dK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzHcsj%2FbtrEQSg9FCf%2FZM6FSQt7tt3AKGt2Bcb3dK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;461&quot; height=&quot;594&quot; data-filename=&quot;스크린샷 2022-06-15 오전 8.59.44.png&quot; data-origin-width=&quot;596&quot; data-origin-height=&quot;768&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;fixed가 작동하지 않는 원인을 파악할 수 있습니다!&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래는 해당 스니펫입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1655251399553&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const selector = '.the-fixed-child';
function findCulprits(elem) {
  if (!elem) {
    throw new Error(
      'Could not find element with that selector'
    );
  }
  let parent = elem.parentElement;
  while (parent) {
    const {
      transform,
      willChange
    } = getComputedStyle(parent);
    if (transform !== 'none' || willChange === 'transform') {
      console.warn(
        '  Found a culprit!  \n',
        parent,
        { transform, willChange }
      );
    }
    parent = parent.parentElement;
  }
}
findCulprits(document.querySelector(selector));&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>web/CSS</category>
      <author>InformationFarm</author>
      <guid isPermaLink="true">https://soonysoon.tistory.com/99</guid>
      <comments>https://soonysoon.tistory.com/99#entry99comment</comments>
      <pubDate>Wed, 15 Jun 2022 09:05:10 +0900</pubDate>
    </item>
  </channel>
</rss>