<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>__dan_n.log</title>
        <link>https://velog.io/</link>
        <description></description>
        <lastBuildDate>Mon, 08 Jan 2024 16:08:59 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>__dan_n.log</title>
            <url>https://velog.velcdn.com/images/__dan_n/profile/e99875ce-a91c-4458-9997-fe29ec0e05c4/image.jpg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. __dan_n.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/__dan_n" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[TypeScript] does not exist on type 'jsx.intrinsicelements' ]]></title>
            <link>https://velog.io/@__dan_n/TypeScript-does-not-exist-on-type-jsx.intrinsicelements</link>
            <guid>https://velog.io/@__dan_n/TypeScript-does-not-exist-on-type-jsx.intrinsicelements</guid>
            <pubDate>Mon, 08 Jan 2024 16:08:59 GMT</pubDate>
            <description><![CDATA[<h3 id="문제-상황">문제 상황</h3>
<p>modal 안에 들어갈 content 컴포넌트를 만들고 있었는데, 만든 컴포넌트를 불러오는 과정에서 <em>does not exist on type &#39;jsx.intrinsicelements&#39;</em> 에러가 발생했다.</p>
<h3 id="코드">코드</h3>
<pre><code class="language-typescript">import { Modal } from &quot;antd&quot;;

export const content = () =&gt; {
  return (
    &lt;&gt;
      &lt;div&gt;title&lt;/div&gt;
      &lt;div&gt;content&lt;/div&gt;
    &lt;/&gt;
  )
};

export const ConfirmModal = ({ values, callback }) =&gt; {
  return Modal.info({
    title: `${values.title}`,
    // error 발생 
    content: &lt;content /&gt;,
    okText: &quot;확인&quot;,
    cancelText: &quot;취소&quot;,
    onOk: callback,
    okCancel: true,
  });
};
</code></pre>
<h3 id="해결-방법">해결 방법</h3>
<p>이러한 오류는 JSX에서 지원되지 않는 속성이나 메서드를 사용하려고 할 때 발생할 수 있다. 해결하기 위해서는 아래와 같은 다양한 방법이 있다.</p>
<ul>
<li>타입 정의 확인 </li>
<li>TypeScript 버전 확인<ul>
<li>때로는 TypeScript 버전 간의 호환성 문제로 오류가 발생할 수 있다. </li>
</ul>
</li>
<li>타입 선언 추가 </li>
</ul>
<p>등등 다양한 방법이 있지만 내 경우는 아주 간단하게.. 컴포넌트의 이름을 <code>Content</code> 로 변경하니 해결되었다. </p>
<blockquote>
<p><strong>JSX에서 컴포넌트 식별</strong>
JSX에서는 컴포넌트와 HTML 태그를 구별하기 위해 컴포넌트 이름의 첫 글자가 대문자인지 여부를 사용한다. 
대문자로 시작하면 컴파일러가 이를 컴포넌트로 인식하고, 소문자로 시작하면 일반 HTML 태그로 인식한다.</p>
</blockquote>
<p>이러한 이유로 JSX 혹은 TSX 를 사용할 때는 컴포넌트 이름의 첫 글자를 대문자로 작성해야한다 ! 근데 가끔 까먹는다.
끗 </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Python] 파이썬 제곱 구하기 - pow, math.pow, ** 차이점]]></title>
            <link>https://velog.io/@__dan_n/Python-%ED%8C%8C%EC%9D%B4%EC%8D%AC%EC%97%90%EC%84%9C%EC%9D%98-pow-math.pow-%EC%97%B0%EC%82%B0%EC%9E%90-%EC%B0%A8%EC%9D%B4%EC%A0%90</link>
            <guid>https://velog.io/@__dan_n/Python-%ED%8C%8C%EC%9D%B4%EC%8D%AC%EC%97%90%EC%84%9C%EC%9D%98-pow-math.pow-%EC%97%B0%EC%82%B0%EC%9E%90-%EC%B0%A8%EC%9D%B4%EC%A0%90</guid>
            <pubDate>Sat, 06 Jan 2024 10:41:09 GMT</pubDate>
            <description><![CDATA[<h3 id="내장함수-pow">내장함수 pow</h3>
<ul>
<li><code>pow(x, y, z=None)</code> 형태로 사용된다.<ul>
<li>x = 밑, y = 지수, z = option(나머지 계산에 이용)</li>
<li>pow(x, y, z) 로 사용할 경우, 결과는 (x ** y) % z 와 동일하다.</li>
</ul>
</li>
<li>첫 번째 인자 x를 y번 거듭제곱하고, 세 번째 인자 z로 나눈 나머지를 반환한다. z가 제공되지 않으면 단순한 거듭제곱 값을 반환한다.</li>
<li>pow 함수는 내장 함수이기 때문에 별도의 import 없이 사용 가능하다.<pre><code class="language-python"># example
result = pow(2, 3)  # 2^3 = 8</code></pre>
<blockquote>
<p><strong>특징</strong>
pow의 반환값은 파라미터의 type에 따라 결정된다.
파라미터가 정수인 경우 정수를 반환하고, 부동소수점인 경우 부동소수점을 반환한다.</p>
</blockquote>
</li>
</ul>
<h3 id="mathpow">math.pow</h3>
<ul>
<li><code>math.pow(x, y)</code> 형태로 사용된다.</li>
<li>항상 두 개의 인자를 받아서 x를 y번 거듭제곱한 값을 반환한다.</li>
<li>math 모듈을 import해야 사용할 수 있다.<pre><code class="language-python"># example
import math
</code></pre>
</li>
</ul>
<p>result = math.pow(2, 3)  # 2^3 = 8.0</p>
<pre><code>&gt; **특징**
math.pow 는 항상 부동소수점을 반환한다. (결과값이 항상 float이다)
정수 결과가 필요한 경우 ** 연산자나 pow 함수를 사용하는 것이 더 적절할 수 있다.
&gt;

### ** 연산자
* `x ** y` 형태로 사용된다.
* 가장 짧고 간단한 방법으로 거듭제곱을 수행할 수 있다.
* ** 연산자는 내장 연산자이기 때문에 별도의 import 없이 사용 가능하다.
```python
# example
result = 2 ** 3  # 2^3 = 8</code></pre><blockquote>
<p><strong>특징</strong>
<code>**</code> 의 반환값은 파라미터의 type에 따라 결정된다.
속도 측면에서 <code>**</code> 연산자가 일반적으로 더 빠르다. </p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[CSS] transform 을 이용한 아이템 가운데 정렬 + 레이어 겹쳐서 배치하기]]></title>
            <link>https://velog.io/@__dan_n/transform</link>
            <guid>https://velog.io/@__dan_n/transform</guid>
            <pubDate>Thu, 04 Jan 2024 15:46:15 GMT</pubDate>
            <description><![CDATA[<h3 id="들어가며">들어가며</h3>
<p>내가 만들고 싶은 디자인은 요것이다! 노란 박스 안에 상자와 캐시 받기라는 말풍선이 함께 들어가야하며, 말풍선은 노란 박스를 살짝 벗어나게 위치해야한다. 
css 속성을 어떻게 줘야할까! (?)
나는 개발할 때 아직도 css 파트가 제일 어렵고 그만큼 제일 중요한 것 같다......
<img src="https://velog.velcdn.com/images/__dan_n/post/2ff3498e-52c8-4903-a2f3-cf363d5965e9/image.png" alt=""></p>
<h3 id="레이어-겹쳐서-배치">레이어 겹쳐서 배치</h3>
<ul>
<li><code>position: absolute;</code>
부모 요소인 StyledWrapper를 기준으로 위치가 결정된다.
(StyledWrapper 에는 position: relative; 로 설정되어있기 때문이다)</li>
<li><code>top: -10px;</code>
부모 요소의 위쪽으로 10px만큼 이동시킨다.</li>
<li><code>z-index: 1;</code>
요소의 쌓임 순서를 설정한다. 1로 설정되어 있어 다른 형제 요소들보다 위에 표시된다.</li>
</ul>
<p>이렇게 하면 tooltip class를 가진 말풍선이 노란 박스보다 조금 더 위의 위치에 있게 된다. </p>
<blockquote>
</blockquote>
<p><strong>position: relative</strong>
일반적인 흐름에 따라 배치되며, 다른 인접한 요소들과의 상대적인 위치를 기준으로 이동된다.
자신을 기준으로 하는 상대적인 위치를 가지므로, 다른 요소들과 겹치거나 다른 요소들에게 영향을 주지 않으면서 위치를 조절할 수 있다.
<strong>position: absolute</strong>
부모 요소나 기준이 되는 가장 가까운 조상 요소 중 position이 relative, absolute, fixed, 또는 sticky인 요소(static이 아닌 요소)를 기준으로 위치가 결정된다.
따라서 부모 요소나 기준이 되는 요소의 위치에 따라 절대적으로 이동한다.</p>
<blockquote>
</blockquote>
<h3 id="아이템-가운데-정렬">아이템 가운데 정렬</h3>
<ul>
<li><code>transform: translateX(-50%);</code>
가로 방향으로 자기 자신의 50%만큼 왼쪽으로 이동시킨다. 아이템을 <i>수평 가운데 정렬</i> 할 수 있다. </li>
</ul>
<blockquote>
</blockquote>
<p><strong>transform 속성</strong>은 이동의 정도를 백분율로 지정한다. 
여기서 <strong>translateX(-50%)</strong>는 요소의 가로 폭의 50%만큼 왼쪽으로 이동하라는 의미이다.</p>
<blockquote>
</blockquote>
<h3 id="전체-코드">전체 코드</h3>
<pre><code class="language-Javascript">&lt;StyledWrapper&gt;
      &lt;img
        className=&quot;tooltip&quot;
        src={&#39;/images/svg/challenge/ic-teamwalk-proofshot-reward-tooltip.svg&#39;}
      /&gt;
      &lt;img className=&quot;reward&quot; src={icon} onClick={onClick} /&gt;
    &lt;/StyledWrapper&gt;</code></pre>
<pre><code class="language-typescript">const StyledWrapper = styled.div`
    position: relative;
    .tooltip {
      position: absolute;
      top: -10px;
      transform: translateX(-50%);
      z-index: 1;
      }

  .reward {
    padding: 9px;
    border-radius: 8.3px;
    box-shadow: 0 0 3px 0 #ffd200;
    background-color: #fffde7;
  }
`;</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[React] 배열 렌더링]]></title>
            <link>https://velog.io/@__dan_n/React-%EB%B0%B0%EC%97%B4-%EB%A0%8C%EB%8D%94%EB%A7%81</link>
            <guid>https://velog.io/@__dan_n/React-%EB%B0%B0%EC%97%B4-%EB%A0%8C%EB%8D%94%EB%A7%81</guid>
            <pubDate>Wed, 13 Dec 2023 02:46:13 GMT</pubDate>
            <description><![CDATA[<h3 id="들어가며">들어가며</h3>
<p>이 코드의 조건이 동일하기때문에 하나로 묶고 싶었는데, <code>&lt;&gt;</code> (Fragment) 로 묶게 되면 Collapse.Panel의 부모가 변경되므로 deps 등의 영향을 받을 수 있다. 그래서 deps 를 바꾸지 않으면서 두 조건문을 하나로 합치는 방법에 대해 고민했다.</p>
<pre><code class="language-javaScript">{challengeType === &quot;PHOTO&quot; &amp;&amp; (
  &lt;Collapse.Panel header=&quot;인증샷 로고 등록&quot; key=&quot;uploadPhotoLogo&quot;&gt;
    &lt;Form.Item label=&quot;인증샷 로고 등록&quot;&gt;
      &lt;UploadPhotoLogo /&gt;
    &lt;/Form.Item&gt;
  &lt;/Collapse.Panel&gt;
)}

{challengeType === &quot;PHOTO&quot; &amp;&amp; (
  &lt;Collapse.Panel header=&quot;인증샷 규격 안내 설정&quot; key=&quot;photoSpecGuide&quot;&gt;
    &lt;Form.Item label=&quot;인증샷 규격 안내 설정&quot;&gt;
      &lt;PhotoSpecGuide /&gt;
    &lt;/Form.Item&gt;
  &lt;/Collapse.Panel&gt;
)}</code></pre>
<h3 id="해결방안">해결방안</h3>
<p>그래서 생각해낸 방법이 각각의 Collapse.Panel을 별도의 배열 요소로 만들어주고, 이 배열을 JSX에서 {}로 감싸서 렌더링 하는 것이다. 이렇게 하면 두개의 조건문을 하나로 합치면서도 각각의 Collapse.Panel이 독립적으로 존재하도록 할 수 있다. </p>
<pre><code class="language-javaScript">{challengeType === &quot;PHOTO&quot; &amp;&amp; [
  &lt;Collapse.Panel header=&quot;인증샷 로고 등록&quot; key=&quot;uploadPhotoLogo&quot;&gt;
    &lt;Form.Item label=&quot;인증샷 로고 등록&quot;&gt;
      &lt;UploadPhotoLogo /&gt;
    &lt;/Form.Item&gt;
  &lt;/Collapse.Panel&gt;,
  &lt;Collapse.Panel header=&quot;인증샷 규격 안내 설정&quot; key=&quot;photoSpecGuide&quot;&gt;
    &lt;Form.Item label=&quot;인증샷 규격 안내 설정&quot;&gt;
      &lt;PhotoSpecGuide /&gt;
    &lt;/Form.Item&gt;
  &lt;/Collapse.Panel&gt;
]}
</code></pre>
<h3 id="마무리">마무리</h3>
<p>배열까지 렌더링이 가능한...리액트는 최고다. 여러개의 조건문으로 적었을때보다 가독성도 좋아지고 코드 반복성도 줄여준다 🏷️
끗!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Goodbye .. 가 아니라 HELLO Clean Code !]]></title>
            <link>https://velog.io/@__dan_n/Goodbye-..-%EA%B0%80-%EC%95%84%EB%8B%88%EB%9D%BC-HELLO-Clean-Code</link>
            <guid>https://velog.io/@__dan_n/Goodbye-..-%EA%B0%80-%EC%95%84%EB%8B%88%EB%9D%BC-HELLO-Clean-Code</guid>
            <pubDate>Wed, 06 Dec 2023 05:06:21 GMT</pubDate>
            <description><![CDATA[<h3 id="시작하며">시작하며</h3>
<p>&quot;클린 코드&quot; 의 중요성을 알고있고 코드를 작성할때 적용하려고 노력하고있다. 코드를 작성하는 과정에서도, 작성한 후에도 코드리뷰를 거치며 어떻게 추상화하면 좋을지, 구조를 어떻게 변경하면 좋을지 등 이것저것 변경사항을 적용힌다. </p>
<p>추상화가 잘 된 코드, 독립성을 가지고 있는 코드, 네이밍이 잘 되어있는 코드, 특히 중복이 없는 코드가 좋은 코드 (즉, 클린 코드) 라고 생각했다. 하지만 <a href="https://overreacted.io/goodbye-clean-code/">이 글</a>을 읽으며 클린 코드란 무엇인가에 대해 다시 한 번 생각하게 되었다. </p>
<h3 id="그래서-나는">그래서 나는</h3>
<p>작성자가 겪은 상황에 내 상황을 빗대어 생각해볼 수 있었다. 여섯개의 타입마다 icon 과 클릭했을때 실행할 onClick 함수를 가지고 있다. 아이템 리스트를 받아서 각 아이템의 상태에 따라 보여줄 아이콘 이미지와, 클릭 함수를 다르게 하여 보여주는 것이 목적이다. 6개의 조건 처리를 위해 각 조건을 객체로 추상화하여 관리하는 것이 코드 중복을 해소할 수 있을 것 같았다.</p>
<p>무작정 if 문을 통해 타입을 확인하는 것보다는 아래처럼 코드를 그룹화 하는 것이 반복된 계산을 줄여줄 것이라고 생각했다. </p>
<pre><code class="language-typescript">// 기존 코드
interface StampButtonAttrs {
  icon: string;
  onClick: () =&gt; void;
}

interface StampButtonAttrsDatabase {
  [key: string]: StampButtonAttrs;
}

const StampTypeMap: StampButtonAttrsDatabase = {
    OPEN: { icon: &#39;image-url&#39;, onClick: null  },
    PENDING: {
      icon: &#39;image-url&#39;,
      onClick: () =&gt;
        ModalDom.alert({
          closeText: &#39;&#39;,
          text: &#39;&#39;,
        }),
    },
    REWARD: {
      icon: &#39;image-url&#39;,
      onClick: null,
    },
    CLOSE: { icon: &#39;image-url&#39;, onClick: null },
    DONE: { icon: &#39;image-url&#39;, onClick: null },
    REJECT: {
      icon: &#39;image-url&#39;,
      onClick: () =&gt;
        ModalDom.alert({
          closeText: &#39;&#39;,
          text: &#39;&#39;,
        }),
    },
  };</code></pre>
<p>특정 아이콘을 추가하거나 동작을 변경하려면 모든 곳에서 메서드를 업데이트하는 대신 한 곳에서 이를 수행할 수 있다. 한 곳에서 그룹으로 관리 되고 있고, map 한번으로 컴포넌트를 그릴 수 있기 때문에 나름 클린 코드라고 생각했는데.....더보기</p>
<pre><code class="language-typescript">// 개선된 코드
return (
  ...
  {stamp.status === &#39;OPEN&#39; &amp;&amp; (
                 &lt;StampButton
                  icon=&quot;image-url&quot;
                  onClick={handleCameraOpen}
                /&gt;
              )}
              {stamp.status === &#39;PENDING&#39; &amp;&amp; (
                &lt;StampButton
                  icon=&quot;image-url&quot;
                  onClick={() =&gt;
                    ModalDom.alert({
                      closeText: &#39;&#39;,
                      text: &#39;&#39;,
                    })
                  }
                /&gt;
              )}
              {stamp.status === &#39;REWARD&#39; &amp;&amp; (
                &lt;StampButton icon=&quot;image-url&quot; onClick={null} /&gt;
              )}
              {stamp.status === &#39;CLOSE&#39; &amp;&amp; (
                &lt;StampButton icon=&quot;image-url&quot; onClick={null} /&gt;
              )}
              {stamp.status === &#39;DONE&#39; &amp;&amp; (
                &lt;StampButton icon=&quot;image-url&quot; onClick={null} /&gt;
              )}
              {stamp.status === &#39;REJECT&#39; &amp;&amp; (
                &lt;StampButton
                  icon=&quot;image-url&quot;
                  onClick={() =&gt;
                    ModalDom.alert({
                      closeText: &#39;&#39;,
                      text: &#39;&#39;,
                    })
                  }
                /&gt;
              )}
              )</code></pre>
<p>코드 리뷰 이후 위처럼 코드를 바꾸었다. 나는 &quot;클린 코드, 반복적인 계산 제거&quot;에만 집중하다보니, 읽기 쉬운 코드를 만들지 못했던 것이다. 첫번째 코드가 더욱 깔끔해 보일 수는 있지만, 코드를 이해하기 위해 파악해야할 요소들이 많다. (ex. interface 구조 파악 등)</p>
<p>그렇다고 클린 코드를 지양하자는 것은 아니다. 하나의 로직이 여러 곳에서 쓰이고, 중요한 역할을 하고 있다면 추상화를 적절히 활용하여 클린 코드에 집중하는 것이 좋다. 하지만 위와 같은 경우는 한번만 쓰일 기능이며, 그저 아이템들을 보여주는 기능에 불과하기 때문에, 추상화에 집중하기 보다는 한 눈에 보기 쉬운 코드가 나은 것이다. </p>
<p>두번째 코드처럼 작성하게 되면 반복되는 로직이 추가되고, 코드가 길어질 수는 있으나, 코드가 단순하며 이해하기 쉽다. </p>
<h3 id="마치며">마치며</h3>
<p>물론 클린 코드가 중요하지만....클린 코드 책도 읽었지만.... 때로는 클린 코드에 지나치게 집중하는 것이, <strong>읽기 쉬운 코드(이해하기 쉬운 코드)</strong> 생성을 방해하는 것 같다. 
또한 복잡한 코드를 단순하게 만들기 위해 클린 코드를 작성하려고 했던 건데, 생각해보니 오히려 더 복잡하게 바뀌었다. </p>
<p>앞으로도 클린 코드를 작성하기 위해 탐구하고, 노력할 것임은 변하지 않지만 이번 경험을 계기로 새로운 관점이 생겼다 !!! 누군가 내 코드를 볼때, <strong>한번 더 생각하지 않아도 되는 코드</strong>를 만들고 싶다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JavaScript] Intersection Observer를 이용하여 무한 스크롤 구현하기]]></title>
            <link>https://velog.io/@__dan_n/Intersection-Observer</link>
            <guid>https://velog.io/@__dan_n/Intersection-Observer</guid>
            <pubDate>Wed, 29 Nov 2023 01:14:18 GMT</pubDate>
            <description><![CDATA[<h2 id="🛠️-들어가며">🛠️ 들어가며</h2>
<p>무한 스크롤은 페이지의 최하단에 도달했을 때, 새로운 콘텐츠를 받아와서 로딩하는 방식으로 동작한다. 이번에는 무한 스크롤을 통해 이미지 그리드를 만든 뒤, 화면의 최하단에 도달하면 추가 이미지를 로드해오는 기능을 구현할 것이다. 
<img src="https://velog.velcdn.com/images/__dan_n/post/4f9dfbd6-36ac-434d-a9cf-6668e5e9e51b/image.gif" alt="">
이렇게! 
동영상 만들면서 스크롤을 잘라버렸지만 ... 실제로는 스크롤이 하단에 닿았을 때, 새로운 이미지가 로드된다. </p>
<p>Intersection Observer는 이 전에 FadeIn animation을 구현할 때 잠시 다뤄본 적이 있다. 비슷한 맥락으로 target 을 관찰해서 특정 위치에 도달했을 때 이벤트(ex. 이미지 로드)를 실행시키는 로직으로 무한 스크롤을 구현하면 될 것같다.
요거 !  <a href="https://velog.io/@__dan_n/React-custom-hooks-%EB%A5%BC-%EC%9D%B4%EC%9A%A9%ED%95%98%EC%97%AC-scroll-event-%EB%A7%8C%EB%93%A4%EA%B8%B0">custom hooks 를 이용하여 scroll event 만들기</a> </p>
<h2 id="🎧-intersection-observer-사용-방법">🎧 Intersection Observer 사용 방법</h2>
<h3 id="옵저버-인스턴스-생성">옵저버 인스턴스 생성</h3>
<p><code>new IntersectionObserver()</code> 를 통해 observer 인스턴스를 생성한다. 생성한 observer 로 관찰할 대상을 지정할 수 있다. 
<code>new IntersectionObserver()</code> 생성자는 두 개의 매개변수(<code>callback 함수, options)</code>를 갖는다. </p>
<pre><code class="language-typescript">// observer 인스턴스 생성
let options = {
  root: null,
  rootMargin: &#39;0px&#39;,
  threshold: 0.5
}
const observer = new IntersectionObserver(callback, options);</code></pre>
<h3 id="callback-함수">callback 함수</h3>
<p>target(관찰 대상)이 등록되거나, 가시성에 변화가 생기면 실행된다. 
콜백 함수는 두개의 매개변수<code>(entries, observer)</code>를 가지고 있다.</p>
<p>나는 이미지 무한 스크롤을 구현할 것이기 때문에 <code>fetchNextImage</code> 라는 함수를 만들어서, 다음 리스트(이미지)를 불러오도록 했다. </p>
<ul>
<li><code>fetchNextImage</code>: 교차 상태가 됐을 때 실행할 함수 <pre><code class="language-typescript">const callback = (entries, observer) =&gt; {
  entries.forEach((entry) =&gt; {
    entry.isIntersecting &amp;&amp; fetchNextImage();
  });
}</code></pre>
</li>
</ul>
<blockquote>
</blockquote>
<p><strong>Intersection Observer 의 콜백 함수 호출 조건</strong>
(1) target(관찰 대상)이 뷰포트나 지정해준 root 요소와 교차할 때
(2) 관찰자(observer)가 최초로 타겟을 관측하였을 때</p>
<blockquote>
</blockquote>
<h3 id="isintersecting">isIntersecting</h3>
<p>관찰 대상이 루트 요소와 교차 상태인지 아닌지 반환한다. </p>
<ul>
<li>루트 요소와 교차되면 true, 교차되지 않았으면 false를 반환한다.<pre><code class="language-typescript">const callback = (entries) =&gt; {
  entries.forEach((entry) =&gt; {
    console.log(entry.isIntersecting);
    // true 혹은 false 출력
  });
};</code></pre>
</li>
</ul>
<h3 id="observe">observe()</h3>
<p>target(관찰 대상)의 관찰을 시작할 때 사용한다. 
나는 이미지 그리드를 target 으로 하기 때문에 그리드의 끝에 target을 지정해두었고,observe()의 인수로 넣어서 관찰 대상으로 지정했다. </p>
<pre><code class="language-typescript">const target = useRef(null);
// 코드 생략 
&lt;&gt;
    &lt;StyledWrapper&gt;
        &lt;div className=&quot;photo-list-wrap&quot;&gt;{images}&lt;/div&gt;
        &lt;div ref={target} className=&quot;infinity-point&quot; /&gt;
    &lt;/StyledWrapper&gt;
&lt;/&gt;

// 코드 생략
observer.observe(target);</code></pre>
<h3 id="unobserve">unobserve()</h3>
<p>target(관찰 대상)의 관찰을 중지할 때 사용한다. </p>
<pre><code class="language-typescript">observer.unobserve(target);</code></pre>
<h3 id="disconnect">disconnect()</h3>
<p>observer 가 관찰하는 모든 target의 관찰을 중지할 때 사용한다. </p>
<pre><code class="language-typescript">observer.disconnect();</code></pre>
<h3 id="options">options</h3>
<p>options는 observer 인스턴스를 생성할 때 필요한 인수이다. 아래 세가지 값을 옵션으로 지정할 수 있다. </p>
<pre><code class="language-typescript">let options = {
  root: null,
  rootMargin: &#39;0px&#39;,
  threshold: 0.5
}

const observer = new IntersectionObserver(callback, options);</code></pre>
<h4 id="1-root">1. root</h4>
<p>관찰 대상의 가시성 기준이 되는 화면이다. <code>null</code> 이거나 지정되지 않으면 브라우저의 뷰포트로 설정된다. </p>
<ul>
<li>default: 브라우저의 viewport</li>
</ul>
<h4 id="2-threshold">2. threshold</h4>
<p>target(관찰 대상)의 가시성이 얼마나 필요한지를 나타내는 값이다.
ex) threshold = 0.5 -&gt; 타겟의 가시성이 50%일 때 옵저버가 실행된다. </p>
<h4 id="3-rootmargin">3. rootMargin</h4>
<p>root가 가진 바깥 여백(margin)이다. </p>
<ul>
<li>default: 0</li>
</ul>
<h2 id="무한-스크롤의-장단점">무한 스크롤의 장단점</h2>
<blockquote>
</blockquote>
<p><strong>장점</strong></p>
<ul>
<li>사용자는 별도의 추가 동작(ex. 버튼 클릭 등)이 필요없이 편리하게 사용할 수 있다.<blockquote>
</blockquote>
</li>
<li><em>단점*</em></li>
<li>스크롤을 내리면서 많은 컨텐츠를 로드했을 때, 원하는 콘텐츠를 다시 찾거나  해당 위치로 돌아가기 어렵다.</li>
<li>한 페이지 내에 상대적으로 많은 컨텐츠가 로드될 가능성이 있기 때문에, 성능이 저하될 수 있다. <blockquote>
</blockquote>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[헤드 퍼스트 디자인 패턴] chapter 3. 데코레이터 패턴(decorator pattern)]]></title>
            <link>https://velog.io/@__dan_n/%ED%97%A4%EB%93%9C-%ED%8D%BC%EC%8A%A4%ED%8A%B8-%EB%94%94%EC%9E%90%EC%9D%B8-%ED%8C%A8%ED%84%B4-chapter-3.-%EB%8D%B0%EC%BD%94%EB%A0%88%EC%9D%B4%ED%84%B0-%ED%8C%A8%ED%84%B4decorator-pattern</link>
            <guid>https://velog.io/@__dan_n/%ED%97%A4%EB%93%9C-%ED%8D%BC%EC%8A%A4%ED%8A%B8-%EB%94%94%EC%9E%90%EC%9D%B8-%ED%8C%A8%ED%84%B4-chapter-3.-%EB%8D%B0%EC%BD%94%EB%A0%88%EC%9D%B4%ED%84%B0-%ED%8C%A8%ED%84%B4decorator-pattern</guid>
            <pubDate>Fri, 27 Oct 2023 13:13:57 GMT</pubDate>
            <description><![CDATA[<h3 id="데코레이터-패턴decorator-pattern">데코레이터 패턴(decorator pattern)</h3>
<p>데코레이터 패턴(decorator pattern)은 객체에 추가적인 요건을 <strong>동적으로 추가</strong> 한다. 데코레이터는 서브클래스를 만드는 것을 통해서 기능을 유연하게 확장할 수 있는 방법을 제공한다. 
데코레이터 패턴을 사용하면 <em>원래 클래스의 코드는 전혀 바꾸지 않고도 내가 만든 객체에 새로운 임무를 부여할 수 있다.</em></p>
<blockquote>
</blockquote>
<ul>
<li>데코레이터의 슈퍼클래스는 자신이 장식하고 있는 슈퍼클래스와 같다.</li>
<li>한 객체를 여러 개의 데코레이터로 감쌀 수 있다.</li>
<li>데코레이터는 자신이 감싸고 있는 객체와 같은 슈퍼클래스를 가지고 있기 때문에 원래 객체(싸여져 있는 객체)가 들어갈 자리에 데코레이터 객체를 집어넣어도 상관없다.</li>
<li>데코레이터는 자신이 장식하고 있는 객체에서 어떤 행동을 위임하는 것 외에 원하는 추가적인 작업을 수행할 수 있다.</li>
<li>객체는 언제든지 감쌀 수 있기 때문에 실행중에 필요한 데코레이터를 마음대로 적용할 수 있다.<blockquote>
</blockquote>
</li>
</ul>
<blockquote>
</blockquote>
<p><strong>OCP(open-closed principle)</strong>
확장에 대해서는 열려 있어야 하지만 코드 변경에 대해서는 닫혀 있어야 한다. <em>기존 코드는  건드리지 않은 채로 확장을 통해서 새로운 행동을 간단하게 추가</em> 하는 것이 목표이다. </p>
<blockquote>
</blockquote>
<h3 id="예시">예시</h3>
<p><img src="https://velog.velcdn.com/images/__dan_n/post/09ed7177-3c69-413e-b162-b83c41b5e03c/image.png" alt=""></p>
<p><em>Milk, Mocha, Soy, Whip</em> 는 각각의 첨가물을 나타내는 데코레이터이다. 
특정 음료에 첨가물로 음료를 장식(Decoration) 할 수 있다. 기존의 음료는 건드리지 않은 채로 첨가물을 추가하여(= 확장을 통해) 새로운 행동을 간단하게 추가하는 것이 바로 데코레이터 패턴이다.
이처럼 데코레이터 패턴을 사용하면 <strong>인터페이스는 바꾸지 않고 책임(기능)만 추가할 수 있다.</strong> 
하지만 데코레이터 패턴을 사용하면 잡다한 클래스들이 너무 많아진다는 단점이 있다.</p>
<h3 id="마치며">마치며</h3>
<p>데코레이터 패턴을 사용하면 인터페이스를 바꾸지 않아도 쉽게 기능 추가가 가능해서 편해서 코드를 확장하기 좋다. (OCP 를 아주 잘 지키는 듯) 
하지만 기능을 덧붙이다 보면 클래스가 너무 방대해질 것 같다. 객체를 잘 분리해놓지 않으면 구조를 파악하기 어렵고 오히려 복잡해질 수 있다.
아무튼 그렇다 🐿</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[헤드 퍼스트 디자인 패턴] chapter 2. 옵저버 패턴(Observer Pattern)]]></title>
            <link>https://velog.io/@__dan_n/%ED%97%A4%EB%93%9C-%ED%8D%BC%EC%8A%A4%ED%8A%B8-%EB%94%94%EC%9E%90%EC%9D%B8-%ED%8C%A8%ED%84%B4-chapter-2.-%EC%98%B5%EC%A0%80%EB%B2%84-%ED%8C%A8%ED%84%B4Observer-Pattern</link>
            <guid>https://velog.io/@__dan_n/%ED%97%A4%EB%93%9C-%ED%8D%BC%EC%8A%A4%ED%8A%B8-%EB%94%94%EC%9E%90%EC%9D%B8-%ED%8C%A8%ED%84%B4-chapter-2.-%EC%98%B5%EC%A0%80%EB%B2%84-%ED%8C%A8%ED%84%B4Observer-Pattern</guid>
            <pubDate>Fri, 27 Oct 2023 12:18:44 GMT</pubDate>
            <description><![CDATA[<h3 id="시작하며">시작하며</h3>
<p>이 글은 <a href="https://www.yes24.com/Product/Goods/108192370">헤드퍼스트 디자인 패턴</a> 을 읽으며 정리한 글이다. 내가 정리해두고 내가 다시 보기 위해 쓰는 중이다! 내정내보
&quot;유지보수에 대한 고민을 하는 개발자&quot;로서, 유지보수 가능한 코드 작성은 프로젝트의 장기적인 성공을 위해 필수적이라고 생각한다. 그렇기에 변경에 용이한 코드를 작성하는 것은 매우 중요하다 !!!!💡 <strong>헤드퍼스트 디자인패턴</strong> 에서는 유지보수에 용이한 코드를 작성하기 위한 패턴을 제안하고, 예제 코드에 패턴을 적용해서 개선되는 모습을 보여준다.</p>
<h3 id="옵저버-패턴">옵저버 패턴</h3>
<p><strong>옵저버 패턴(Observer Pattern)</strong> 은 한 객체의 상태가 바뀌면 그 객체에 의존하는 다른 객체에게 연락이 가고 자동으로 내용이 갱신되는 방식으로, 일대다(one-to-many) 의존성을 정의한다.</p>
<p><img src="https://velog.velcdn.com/images/__dan_n/post/c07768f4-3380-4d9d-a625-330c20a45a64/image.png" alt="">
위 사진처럼 주제와 옵저버들 사이에 일대다 관계가 정의된다. 옵저버는 주제에 연관되어 있으며, 주제의 상태가 바뀌면 옵저버에게 정보가 전달된다.
위 예시에서는 주제가 변경되면 연관된 옵저버인 foo, bar, qux, baz 객체에게 정보가 전달될 것이다. </p>
<h3 id="느슨한-결합loose-coupling">느슨한 결합(Loose Coupling)</h3>
<p><strong>느슨한 결합(Loose Coupling)</strong> 은 객체들이 상호작용할 수는 있지만, 서로를 잘 모르는 관계를 의미한다. 앞으로 읽을 내용에 나오겠지만, 느슨한 결합을 활용하면 유연성이 아주 좋아진다. 옵저버 패턴은 느슨한 결합을 보여주는 훌륭한 예이다.</p>
<ul>
<li>주제는 옵저버가 특정 인터페이스(Observer Interface)를 구현한다는 사실만 알고 있다.</li>
<li>옵저버는 언제든지 새로 추가할 수 있다. 새로운 형식의 옵저버를 추가할 때도 주제를 변경할 필요가 전혀 없다.</li>
<li>주제와 옵저버는 서로 <strong>독립적으로 재사용</strong> 할 수 있다. 주제나 옵저버가 달라져도 서로에게 영향을 미치지 않는다. </li>
</ul>
<h3 id="디자인-원칙">디자인 원칙</h3>
<ul>
<li>상호작용하는 객체 사이에는 가능하면 느슨한 결합을 사용해야 한다.<ul>
<li>느슨하게 결합하는 디자인을 사용하면 변경 사항이 생겨도 무난히 처리할 수 있는 유연한 객체지향 시스템을 구축할 수 있다. <strong>객체 사이의 상호의존성을 최소화</strong>할 수 있기 때문이다</li>
</ul>
</li>
</ul>
<blockquote>
</blockquote>
<p>** 옵저버 데이터 방식의 푸시(push) vs 풀(pull)**</p>
<ul>
<li>푸시(push): 주제가 옵저버로 데이터를 보냄</li>
<li>풀(pull): 옵저버가 주제로부터 데이터를 당겨옴 <blockquote>
</blockquote>
</li>
</ul>
<h3 id="✅-결론">✅ 결론</h3>
<ul>
<li>옵저버 패턴은 객체들 사이에 일대다 관계를 정의한다.</li>
<li>주제는 동일한 인터페이스를 써서 옵저버에게 연락을 한다. ex) update()</li>
<li>Observer 인터페이스를 구현하기만 하면 어떤 구상 클래스의 옵저버라도 패턴에 참여할 수 있다.  </li>
<li>주제는 옵저버들이 Observer 인터페이스를 구현한다는 것을 제외하면 옵저버에 관해 전혀 모른다. 따라서 이들 사이의 결합은 느슨한 결합이다.</li>
<li>옵저버 패턴을 사용하면 주제가 데이터를 보내거나(push) 옵저버가 데이터를 가져올(pull) 수 있다. </li>
<li>느슨한 결합(Loose Coupling)은 코드의 변경을 유연하게 만든다.</li>
</ul>
<h3 id="마치며">마치며</h3>
<p>옵저버패턴을 사용하면 주제를 바꾸지 않고도 주제의 상태에 의존하는 객체들을 바꿀 수 있다. 코드 중 일부분의 변경이 다른 부분까지의 변경을 불러일으킬 때가 있는데, 옵저버 패턴을 적용하여 느슨한 결합을 사용하면 의도치 않은 변경을 막고, 유연한 변경을 하기에 적합하다. 그렇기 때문에 나중에 유지보수 할 때 편하게 작업할 수 있을 것 같다. ⭐️</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[클린 소프트웨어] chapter 11. 의존 관계 역전 원칙 (DIP), chapter 12. 인터페이스 분리 원칙 (ISP)]]></title>
            <link>https://velog.io/@__dan_n/%ED%81%B4%EB%A6%B0-%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4-chapter-11.-%EC%9D%98%EC%A1%B4-%EA%B4%80%EA%B3%84-%EC%97%AD%EC%A0%84-%EC%9B%90%EC%B9%99-DIP-chapter-12.-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4-%EB%B6%84%EB%A6%AC-%EC%9B%90%EC%B9%99-ISP</link>
            <guid>https://velog.io/@__dan_n/%ED%81%B4%EB%A6%B0-%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4-chapter-11.-%EC%9D%98%EC%A1%B4-%EA%B4%80%EA%B3%84-%EC%97%AD%EC%A0%84-%EC%9B%90%EC%B9%99-DIP-chapter-12.-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4-%EB%B6%84%EB%A6%AC-%EC%9B%90%EC%B9%99-ISP</guid>
            <pubDate>Thu, 07 Sep 2023 07:44:51 GMT</pubDate>
            <description><![CDATA[<h2 id="💡-chapter-11-의존-관계-역전-원칙-dip">💡 Chapter 11. 의존 관계 역전 원칙 (DIP)</h2>
<h3 id="의존-관계-역전-원칙dip---dependency-inversion-principle">의존 관계 역전 원칙(DIP) - Dependency-Inversion Principle</h3>
<blockquote>
</blockquote>
<p>** 의존 관계 역전 원칙(DIP) **
상위 수준의 모듈이 하위 수준의 모듈에 의존해서는 안 된다. 둘 다 추상화에 의존해야 한다.
또한 추상화는 구체적인 사항에 의존해서는 안 된다. 구체적인 사항이 추상화에 의존해야 한다.</p>
<blockquote>
</blockquote>
<h3 id="기존의-병폐">기존의 병폐</h3>
<ul>
<li>상위 수준의 모듈이 하위 수준의 모듈에 의존하는 경우<ul>
<li>상위 수준의 모듈은 어플리케이션의 본질을 담고 있다.</li>
<li>그러나 상위 모듈이 하위 모듈에 의존할 때, <strong>하위 모듈 변경은 상위 모듈에 직접적인 영향을 미칠 수 있고, 나아가서 상위 수준 모듈이 변경되게 할 수도 있다.</strong></li>
<li>상위 모듈은 어떤 식으로든 하위 모듈에 의존해서는 안 된다.</li>
</ul>
</li>
<li>정책이 구체적인 것에 의존하는 경우<ul>
<li>정책을 결정하는 것은 상위 수준의 모듈이다.</li>
<li>우리가 재사용하기를 원하는 것은 정책을 결정하는 상위 수준의 모듈이다.</li>
<li>상위 수준의 모듈이 하위 수준의 모듈에 독립적이면, 재사용하기 쉽다.</li>
</ul>
</li>
</ul>
<h3 id="역전inversion">역전(inversion)</h3>
<p>잘 설계된 객체 지향 프로그램의 의존성 구조는 전통적인 절차적 방법에 의해 일반적으로 만들어진 의존성 구조가 <em> 역전 </em> 된 것이다.</p>
<h3 id="레이어-나누기">레이어 나누기</h3>
<blockquote>
<p>잘 구조화된 모든 객체 지향 아키텍처는 레이어를 분명하게 정의했다. 여기서 각 레이어는 잘 정의되고 제어되는 인터페이스를 통해 일관된 서비스의 집합을 제공한다. - 부치(Booch) -</p>
</blockquote>
<h3 id="미숙한-레이어">미숙한 레이어</h3>
<img src="https://velog.velcdn.com/images/__dan_n/post/2424c1ed-cd9e-4465-b88b-59097695f0a8/image.png" width="50" height:="100">

<h3 id="역전된-레이어">역전된 레이어</h3>
<p><img src="https://velog.velcdn.com/images/__dan_n/post/e1cf6e01-7b24-4028-8d05-9898981fea22/image.png" alt=""></p>
<h3 id="그래서-역전은">그래서 역전은?</h3>
<p>의존성의 방향을 역전시키고, 하위 수준 모듈이 상위 수준 모듈에 선언된 인터페이스에 의존하게 만드는 것
여기서 역전은 의존성 뿐만 아니라, <strong>인터페이스 소유권</strong> 에 대한 것도 의미한다.</p>
<h3 id="헐리우드hollywood-원칙이란">헐리우드(Hollywood) 원칙이란?</h3>
<ul>
<li>하위 수준 모듈에서 시스템에 접속을 할 수는 있지만, 어떤 식으로 그 모듈을 사용할지는 상위 수준 모듈에서 결정하게 된다.</li>
<li>즉, 상위 수준 모듈에서 하위 수준 모듈에 <code>먼저 연락하지 마세요. 저희(상위 수준 모듈)가 먼저 연락 드리겠습니다.</code> 라고 말하는 원칙이다.</li>
<li>DIP와 관계가 깊다.</li>
</ul>
<p><strong>이렇게 의존성을 역전시킴으로써, 우리는 좀 더 유연하고, 튼튼하고, 이동이 쉬운 구조를 만들 수 있다.</strong></p>
<h3 id="추상화에-의존하자">추상화에 의존하자</h3>
<p>구체 클래스(concrete class)에 의존해서는 안 되고, 프로그램의 모든 관계는 어떤 추상 클래스나 인터페이스에 맺어져야 한다.</p>
<blockquote>
</blockquote>
<p>고지식한 원칙</p>
<ul>
<li>어떤 변수도 구체 클래스에 대한 포인터나 참조값을 가져서 안 된다.</li>
<li>어떤 클래스도 구체 클래스에서 파생(상속)되어서는 안 된다.</li>
<li>어떤 메소드도 그 기반 클래스에서 구현된 메소드를 오버라이드해서는 안 된다 
: LSP포함<blockquote>
</blockquote>
</li>
</ul>
<p>구체 클래스가 너무 많이 변경 되지 않으면서, 다른 비슷한 파생 클래스가 만들어지지 않는다면 이것에 의존하는 것은 그리 큰 해가 되지 않는다 </p>
<p>→ 휘발적인 클래스에는 직접적으로 의존하지 않아야 한다. </p>
<p><strong>너무 고지식할 필요까진 없다.</strong></p>
<p>→ 상황에 따라서 고지식할 때도 있고, 유연하게 넘겨야할 때도 있다.</p>
<h3 id="결론">결론</h3>
<ul>
<li>전통적인 절차 지향 방식은 정책이 구체적인 것에 의존하는 의존성 구조를 만든다. 이 경우 정책이 구체적인 것의 변경에 따라 같이 변한다.</li>
<li>객체 지향 프로그래밍은 이것을 역전 시켜서 구체적인 것과 정책이 모두 추상화에 의존하게 한다.</li>
<li>프로그램의 의존성이 역전되어 있다면 이것은 객체 지향 설계이며, 의존성이 역전되어 있지 않다면 절차적 설계이다.</li>
<li>의존성 역전을 사용하면 프레임워크가 재사용 가능해지고, 변경에 탄력적이며, 추상화와 구체적 사항이 서로 분리되어 있기 때문에, 이 코드는 유지보수하기가 훨씬 쉽다.</li>
</ul>
<h2 id="💡-chapter-12-인터페이스-분리-원칙-isp">💡 Chapter 12. 인터페이스 분리 원칙 (ISP)</h2>
<h3 id="인터페이스-분리-원칙isp---interface-segregation-principle">인터페이스 분리 원칙(ISP) - Interface-Segregation Principle</h3>
<ul>
<li>ISP는 ‘비대한’ 인터페이스의 단점을 해결한다.</li>
<li>비대한 인터페이스는 응집력이 없는 인터페이스이다.</li>
</ul>
<h3 id="인터페이스-오염">인터페이스 오염</h3>
<ul>
<li>클라이언트가 사용하지 않는 인터페이스가 구현되어 있는 경우 </li>
<li>일부 구상체에 불필요한 인터페이스가 구현되어 있는 경우 </li>
<li>파생 클래스가 새로운 메소드를 필요로 할 때마다 그 메소드가 기반 클래스에도 포함되어야 한다. 이것은 기반 클래스의 인터페이스를 ‘비대하게’ 만든다
→ <strong>불필요한 복잡성</strong> 과 <strong>불필요한 중복성</strong></li>
</ul>
<h3 id="클라이언트가-인터페이스에-미치는-반대-작용">클라이언트가 인터페이스에 미치는 반대 작용</h3>
<ol>
<li>클라이언트의 요구사항 변경으로 인해 인터페이스가 변경되는 경우가 자주 생긴다.</li>
<li>이 상황에서 해당 인터페이스가 비대해서 여러 구상체를 지니고 있으면, 요구사항 변경으로 인한 영향 범위가 넓다.</li>
<li>그로 인해서 비용과 부작용의 위험성이 급격하게 증가한다.</li>
</ol>
<blockquote>
<p>** 인터페이스 분리 원칙(ISP) **
클라이언트가 자신이 사용하지 않는 메소드에 의존하도록 되어서는 안 된다.</p>
</blockquote>
<p>어떤 클라이언트(A)가 자신은 사용하지 않지만 다른 클라이언트(B)가 사용하는 메소드를 포함하는 클래스에 의존할 때, 그 클라이언트(A)는 다른 클라이언트(B)가 그 클래스에 가하는 변경에 영향을 받게 된다. 
우리는 가능하다면 이런 결합을 막고 싶다. 따라서 <em> 인터페이스를 분리 </em> 하기를 원한다.</p>
<h3 id="다중-상속을-통한-분리">다중 상속을 통한 분리</h3>
<img src="https://velog.velcdn.com/images/__dan_n/post/e5a0f7c8-e969-44b4-8cda-fe6b27db2291/image.png" width="100" height="100">

<p>위 구조처럼 다중 상속을 통해 인터페이스를 분리할 경우, 기반 클래스들은 분리된 인터페이스를 통해 같은 객체를 사용하게 된다. 이는 다른 클라이언트의 변경에 의한 영향을 피할 수 있다.</p>
<h3 id="복합체와-단일체">복합체와 단일체</h3>
<p>만약 인터페이스 복수 개(복합체)와 클래스 1개(단일체) 중 선택해야 할 경우에는 <strong>인터페이스 복수 개(복합체)인 방식으로 구현하라.</strong></p>
<h3 id="결론-1">결론</h3>
<ul>
<li>비대한 클래스는 클라이언트간의 높은 결합도를 유발한다.</li>
<li>클라이언트는 자신이 사용하는 메소드에만 의존해야 하는데, 비대한 클래스에 변경을 가하면 모든 나머지 클래스가 영향을 받게 된다
→ <strong>클라이언트 고유의(client-specific) 인터페이스 여러 개로 분해해야 한다. 
→ 이렇게 하면 호출하지 않는 메소드에 대한 클라이언트의 의존성을 끊고, 클라이언트가 서로에 대해 독립적이 되게 만들 수 있다</strong></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[클린 소프트웨어] chapter 10. 리스코프 치환 원칙 LSP]]></title>
            <link>https://velog.io/@__dan_n/%ED%81%B4%EB%A6%B0-%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4-chapter-10.-%EB%A6%AC%EC%8A%A4%EC%BD%94%ED%94%84-%EC%B9%98%ED%99%98-%EC%9B%90%EC%B9%99-LSP</link>
            <guid>https://velog.io/@__dan_n/%ED%81%B4%EB%A6%B0-%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4-chapter-10.-%EB%A6%AC%EC%8A%A4%EC%BD%94%ED%94%84-%EC%B9%98%ED%99%98-%EC%9B%90%EC%B9%99-LSP</guid>
            <pubDate>Tue, 05 Sep 2023 11:48:40 GMT</pubDate>
            <description><![CDATA[<h3 id="리스코프-치환-원칙lsp---liskov-substitution-principle">리스코프 치환 원칙(LSP) - Liskov Substitution Principle</h3>
<blockquote>
<p>서브타입(subtype)은 그것의 기반 타입(base type)으로 치환 가능해야 한다.</p>
</blockquote>
<p>LSP 위반은 잠재적인 OCP 위반이다. (LSP 위반은 OCP 위반을 유발한다)</p>
<h3 id="is-a-상속은-is-a-관계이다">IS-A (상속은 IS-A 관계이다)</h3>
<p>상속은 IS-A관계에서 사용하는 것이 가장 좋다. 
상속에서 IS-A 관계는 * 일반적인 개념과 구체적인 개념 사이의 관계*이다.
상위 클래스가 일반적인 개념이고, 하위 클래스가 구체적인 개념이 된다. 즉, 일반 클래스(상위 클래스)를 구체화 하는 상황에서 상속을 사용해야 한다. </p>
<blockquote>
<p><strong>예시</strong>
고양이는 동물이다.
Cat is an Animal
💡 * 상위 클래스: 동물 / 하위 클래스: 고양이 *</p>
</blockquote>
<h3 id="유효성은-본래-갖추어진-것이-아니다">유효성은 본래 갖추어진 것이 아니다</h3>
<ul>
<li>모델만 별개로 본 뒤, 그 모델의 유효성(validity)을 충분히 검증할 수 없다.</li>
<li>처음부터 모든 설계를 예상하려고 한다면 시스템을 불필요한 복잡성의 위기로 이끈다. 취약성을 느낄 때까지 ** 가장 명백한 LSP 위반 **을 제외한 나머지의 처리는 연기하는게 최선이다. </li>
</ul>
<h3 id="계약에-의한-설계dbc---design-by-contract">계약에 의한 설계(DBC) - design by contract</h3>
<ul>
<li>합리적인 추정을 명시적으로 만들어서 LSP를 강제한다.</li>
<li>DBC 를 사용하면 작성자는 클래스의 계약사항을 명시적으로 정한다.</li>
<li>이 계약은 메소드의 사전조건과 사후조건을 선언하는 것으로 구체화된다.</li>
<li>파생된 객체는 기반 클래스가 받아 들일 수 있는 것은 모두 받아들일 수 있어야하며, 기반 클래스의 모든 사후조건을 따라야 한다. 즉, 파생 클래스의 행위와 출력은 기반 클래스의 제약을 위반해서는 안된다.</li>
<li>파생 클래스에서는 사전 조건과 같거나 약한 조건, 사후 조건보다 같거나 강한 수준에서 대체할 수 있다</li>
</ul>
<h3 id="lsp를-따르는-해결책">LSP를 따르는 해결책</h3>
<p><img src="https://velog.velcdn.com/images/__dan_n/post/4634a5b2-7b64-4bdc-82af-9b0d39c90de4/image.png" alt="">
예를 들어, PersistentSet이 어떤 스트림에도 쓰이고 나중에 다른 어플리케이션에 의해서도 다시 읽힐 수 있는 집합이라고 가정했을 때,
만약 Add 메서드가 특정 타입인 경우 <code>PersistentObject</code>에서 파생된 것이 아닌 경우에는 LSP를 위배하게 된다.</p>
<p><img src="https://velog.velcdn.com/images/__dan_n/post/b4c76c38-46d4-4f89-87cd-9e2612c298b6/image.png" alt=""></p>
<p>이때, 위 구조처럼 LSP 관점에서 문제가 되는 메서드는 서브 클래스로 분리하고 문제 없는 메서드는 기반 클래스로 분리하면 문제를 해결할 수 있다.</p>
<h3 id="공통-인자-추출인터페이스-분리-하기">공통 인자 추출(인터페이스 분리) 하기</h3>
<p><img src="https://velog.velcdn.com/images/__dan_n/post/bf815eee-8934-48dc-aa5a-999df9ae0730/image.png" alt=""></p>
<p>LSP를 지키기위한 다양한 방식 중 가장 적용하기 편한 설계 수단이 공통 인자 추출(인터페이스 분리) 방법이다. 공통 인자를 추출하는 방법은 위 사진과 같다. </p>
<ul>
<li>최상위에 인터페이스를 하나 선언한다. (Shape)<ul>
<li>클라이언트는 해당 인터페이스에 의존하면 된다.</li>
</ul>
</li>
<li>인터페이스를 구현하는 추상클래스나 클래스를 생성한다. (Rectangle)<ul>
<li>그리고 해당 클래스를 <strong>구성</strong> 해서 인터페이스를 구현하면 된다. (Square)</li>
</ul>
</li>
</ul>
<h3 id="lsp-위반의-단서를-보여주는-휴리스틱heuristic">LSP 위반의 단서를 보여주는 휴리스틱(heuristic)</h3>
<p>LSP 위반의 단서를 보여주는 휴리스틱은 다음과 같다.</p>
<ul>
<li>기반 클래스보다 덜한 동작을 하는 파생 클래스는 보통 그 기반 클래스와 치환이 불가능하므로 LSP를 위반한다.</li>
<li>기반 클래스에서 발생하지 않는 예외를 파생 클래스의 메소드에 추가 시켰을 때 이들은 치환 가능하지 않을 수 있다. </li>
</ul>
<h3 id="결론">결론</h3>
<p>** LSP는 OCP를 가능하게 하는 요인 중 하나이다.**  이것은 기반 타입으로 표현된 모듈을 수정 없이도 확장 가능하게 만드는, <strong>서브 타입의 (특히 행위) 치환 가능성을 말한다.</strong>
즉, LSP는 모듈을 수정 없이도 확장 가능하게 만들어주기 때문에, &quot;수정에 닫혀있고 확장에 열려있어야  한다&quot; 를 주장하는 OCP 를 가능하게 한다.
또한 LSP에서 상속을 주요하게 다루기 때문에, 관련해서 자주 쓰이는 &#39;IS-A&#39; 관계에 대해서도 잘 알아두면 좋을 것 같다.
끗 ! </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[클린 소프트웨어] chapter 8. 단일 책임 원칙(SRP), chapter 9. 개방 폐쇄 원칙(OCP)]]></title>
            <link>https://velog.io/@__dan_n/%ED%81%B4%EB%A6%B0-%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4-chapter-8.-%EB%8B%A8%EC%9D%BC-%EC%B1%85%EC%9E%84-%EC%9B%90%EC%B9%99SRP-chapter-9.-%EA%B0%9C%EB%B0%A9-%ED%8F%90%EC%87%84-%EC%9B%90%EC%B9%99OCP</link>
            <guid>https://velog.io/@__dan_n/%ED%81%B4%EB%A6%B0-%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4-chapter-8.-%EB%8B%A8%EC%9D%BC-%EC%B1%85%EC%9E%84-%EC%9B%90%EC%B9%99SRP-chapter-9.-%EA%B0%9C%EB%B0%A9-%ED%8F%90%EC%87%84-%EC%9B%90%EC%B9%99OCP</guid>
            <pubDate>Mon, 07 Aug 2023 12:20:12 GMT</pubDate>
            <description><![CDATA[<h2 id="⚙️-chapter-8-단일-책임-원칙srp">⚙️ Chapter 8. 단일 책임 원칙(SRP)</h2>
<h3 id="단일-책임-원칙srp---single-responsibility-principle">단일 책임 원칙(SRP) - Single-Responsibility Principle</h3>
<blockquote>
</blockquote>
<p>** 단일 책임 원칙(SRP) ** 
한 클래스는 단 한가지의 변경 이유만을 가져야 한다. (= 한 클래스는 한 가지의 책임만을 가져야 한다)</p>
<blockquote>
</blockquote>
<p>한 클래스가 하나 이상의 책임을 맡게 되었을 때, 한 책임에 대한 변경은 다른 책임을 충족시키는 클래스의 능력을 떨어트리거나 저하시킬 수 있다. </p>
<h3 id="srp를-지키지-않으면">SRP를 지키지 않으면?</h3>
<ul>
<li>책임이 섞이게되므로 불필요한 컴파일 시간, 메모리 영역을 소비할 수 있다.</li>
<li>한 애플리케이션의 변경이 다른 애플리케이션의 재빌드, 재테스트를 유발하며, 잘못 동작할 수 있다.</li>
</ul>
<h3 id="책임이란-무엇인가">책임이란 무엇인가?</h3>
<blockquote>
<p>** 책임(responsibility): **
변경을 위한 이유</p>
</blockquote>
<p><strong>변경의 축은 변경이 실제로 일어날 때만 변경의 축이다.</strong> 아무 증상도 없는데 이 문제에 SRP나 다른 원칙을 적용하는 것은 현명하지 못하다. </p>
<h3 id="결론">결론</h3>
<p>두가지 이상의 책임을 맡고 있다고 해서 무조건 SRP를 적용하는 것은 현명하지 못하다. 어플리케이션의 현 상황에 따라서 두 책임이 분리될 수 있도록 해야한다. 
중요한 것은 ** <em>요구사항의 변경에 맞게 적절하게 책임을 분배</em> ** 하는 것인 것 같다.</p>
<h2 id="⚙️-chapter-9-개방-폐쇄-원칙ocp">⚙️ Chapter 9. 개방 폐쇄 원칙(OCP)</h2>
<h3 id="개방-폐쇄-원칙ocp---open-closed-principle">개방 폐쇄 원칙(OCP) - Open-Closed Principle</h3>
<p>모든 시스템은 생명주기 동안에 변화한다. 이것은 개발 중인 시스템이 첫 번째 버전보다 오래 남길 원한다면 반드시 염두에 두어야 할 사실이다. </p>
<blockquote>
<p>** 개방 폐쇄 원칙(OCP) ** 
소프트웨어 개체(클래스, 모듈, 함수 등)는 확장에 대해 열려 있어야 하고, 수정에 대해서는 닫혀 있어야 한다.</p>
</blockquote>
<ul>
<li><p>확장에 대해 열려 있다. (= 요구 사항이 변경될 때 새로운 행위를 추가해 모듈을 확장할 수 있다)</p>
</li>
<li><p>수정에 대해 닫혀 있다. (= 모듈의 행위를 확장하는 것이 소스 코드의 변경을 초래하는 것은 아니다)</p>
<blockquote>
</blockquote>
</li>
<li><p><strong>경직성</strong>(한군데의 변경이 의존적인 모듈의 단계적인 변경을 불러일으킴) 문제를 해결할 수 있다.</p>
</li>
<li><p>OCP가 잘 적용된다면, 이미 제대로 동작하고 있던 기존 코드를 변경하는 것이 아니라 새로운 코드를 추가함으로써 변경할 수 있게 된다.</p>
</li>
</ul>
<p>→ 모듈의 소스코드를 변경하지 않고 모듈의 행위를 확장해야 한다 </p>
<h3 id="해결책은-추상화다">해결책은 추상화다</h3>
<p>모듈은 고정된 추상화에 의존하기 때문에 수정에 대해 닫혀있고, 추상화의 새 파생 클래스들을 만듦으로써 확장이 가능하다 </p>
<blockquote>
<p>** 일반화(Generalization) 을 통한 추상화: ** 인터페이스 or 추상클래스</p>
</blockquote>
<h3 id="왜-abstractserver이-아니라-clientinterface일까">왜 AbstractServer이 아니라 ClientInterface일까?</h3>
<ul>
<li>추상 클래스(인터페이스)는 자신을 구현하는 클래스보다 클라이언트에 더 밀접하게 관련되어 있기 때문이다.</li>
</ul>
<h3 id="예상과-자연스러운-구조">예상과 자연스러운 구조</h3>
<p>모든 상황에서 자연스러운 모델은 없다. 닫혀 있지 않은 것에 대한 변경은 항상 존재한다</p>
<ol>
<li>폐쇄는 완벽할 수 없기 때문에, ** 전략적 **이어야 한다. 설계자는 자신의 설계에서 닫혀 있는 변경의 종류를 선택해야 한다.</li>
<li>경험에서 얻은 통찰력이 필요하다.</li>
<li>가장 중요한 것은 미리 설계하지 말고, <strong>변경이 일어날 때까지 기다리는 것</strong> 이다.</li>
</ol>
<blockquote>
<p>** 올가미 놓기 **
불필요한 복잡성이 발생할 수 있다. 그렇기 때문에 처음에는 코드가 변경되지 않을 것이라고 생각하고 작성한 다음, 변경이 일어나면 나중에 해당 종류의 변경으로부터 보호되는 추상화를 구현 한다.</p>
</blockquote>
<h3 id="결론-1">결론</h3>
<ul>
<li>애플리케이션의 모든 부분에 추상화를 적용하지 말고, 프로그램에서 자주 변경되는 부분에만 추상화를 적용해야 한다.</li>
<li>어설픈 추상화를 피하는 일은 추상화 자체만큼이나 중요하다. → 어설프게 추상화 할 바에는 그냥 하지 말자! </li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[클린 소프트웨어] chapter 7. 애자일 설계란 무엇인가?]]></title>
            <link>https://velog.io/@__dan_n/%ED%81%B4%EB%A6%B0-%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4-chapter-7.-%EC%95%A0%EC%9E%90%EC%9D%BC-%EC%84%A4%EA%B3%84%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80</link>
            <guid>https://velog.io/@__dan_n/%ED%81%B4%EB%A6%B0-%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4-chapter-7.-%EC%95%A0%EC%9E%90%EC%9D%BC-%EC%84%A4%EA%B3%84%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80</guid>
            <pubDate>Mon, 07 Aug 2023 11:31:11 GMT</pubDate>
            <description><![CDATA[<h3 id="시작하며">시작하며</h3>
<p>이번 장은 시스템을 설계하는 과정에서 갖춰야할 것들에 대해 설명하고 있다. 시스템을 완성하는 것도 중요하지만, 코드가 점점 유지보수하기 어려워지면 재설계(renewal)를 필요로 하기 때문에, 이를 설계 단계에서 방지해야 한다.</p>
<h3 id="설계의-악취-부패하고-있는-소프트웨어의-냄새">설계의 악취: 부패하고 있는 소프트웨어의 냄새</h3>
<ul>
<li>경직성(Rigidity): 다른 부분까지 많이 변경해야하기 때문에 단순한 방법으로 변경이 어렵다. (코드가 의존적인 경우, 한 부분을 변경하려고 하면 얽혀있는 다른 부분까지 변경해야하기 때문에 번거로움)<ul>
<li>취약성(Fragility): 시스템이 취약할 경우, 변경 했을 때 아무런 관련이 없는 부분까지 망가지기 쉽다.</li>
<li>부동성(Immobility): 설계를 재사용하기 어렵기 때문에, 재사용 가능한 컴포넌트로 구분하기 어렵다. </li>
<li>점착성(Viscosity): 제대로 동작하기 어렵다. 점착성이 있는 프로젝트는 설계를 유지하기 어렵다.</li>
<li>불필요한 복잡성(Needless Complexity): 과도한 설계 또는 유용하지 않은 기반구조가 포함되어있다. (미래에 일어날 일들을 과도하게 준비함)</li>
<li>불필요한 반복(Needless Repetition): 반복적인 구조가 설계에 포함되어있다. 반복된 부분을 찾아내서 적절한 추상화를 통해 이를 없애면 시스템을 유지보수 하기 쉬워진다.</li>
<li>불투명성(Opacity): 혼란스러운 표현을 지양해야 한다. 코드를 읽고 이해하기 어렵다. 다른 사람이 보았을 때 한눈에 이해하기 쉬운 표현을 사용하는 것이 좋다.</li>
</ul>
</li>
</ul>
<h3 id="무엇이-소프트웨어의-부패를-촉진하는가">무엇이 소프트웨어의 부패를 촉진하는가?</h3>
<p>우리는 때때로 예상하지 않았던 요구사항의 변경을 해결하기 위해 설계를 변경하게 된다. 하지만 요구사항 때문에 설계가 실패한다면 우리의 설계 방식에 문제가 있는 것이다. 그렇기 때문에 변경에 대해서 탄력적인 설계를 만들어야 하고, 이것을 보호할 수 있는 방식을 찾아야 한다. </p>
<h3 id="애자일-팀은-소프트웨어가-부패하도록-내버려두지-않는다">애자일 팀은 소프트웨어가 부패하도록 내버려두지 않는다</h3>
<p>지속적인 리팩토링을 하는 것이 도움이 된다. 설계를 단순하게 유지하고 단위 테스트 및 인수 테스트로 뒷받침하여 설계를 유연하고 변경하기 쉬운 것으로 유지할 수 있다. </p>
<p>요구사항은 끊임없이 변화한다. 새로운 요구사항을 만족시키기 위해 미래에 있을 비슷한 종류의 변경에도 탄력적일 수 있도록 만든다. </p>
<p>→ 애자일 팀은 처음 모듈을 설계할 때 변경될 사항을 예상하지 않고 가장 간단한 방법으로 설계하였다. 또한 나중에 변경될 요구사항에 대해서는 추가적인 처리를 지금 하지 않았다. 요구사항이 변경된 다음에야 비로소 탄력적일 수 있도록 모듈의 설계를 바꾸었다. </p>
<h3 id="애자일-개발자는-해야-할-일을-어떻게-알았는가">애자일 개발자는 해야 할 일을 어떻게 알았는가?</h3>
<ol>
<li>그들은 애자일 실천방법으로 문제를 찾아냈다.<br>→ 의존성의 방향 때문에 유연하지 않음 (현재 상위 수준의 모듈이 하위 수준의 모듈에 의존하고 있음) </li>
<li>그들은 설계 원칙을 적용해 문제를 진단했다. 
→ DIP를 적용하여 의존성을 거꾸로 뒤집어야 함 </li>
<li>그리고 그들은 적절한 디자인 패턴을 적용해 문제를 해결했다. 
→ 전략(STRATEGY)패턴을 적용해 해결함</li>
</ol>
<p>위와 같이 소프트웨어 개발의 세 측면 사이에서 일어나는 상호작용이 바로 설계 작업이다.</p>
<h3 id="가능한-좋은-상태로-설계-유지하기">가능한 좋은 상태로 설계 유지하기</h3>
<ul>
<li>다음은 없다. 나쁜 냄새가 나면 미루지 말고 바로 개선해야한다.</li>
<li>작은 단위의 부패라도 방치하면 나중에는 감당할 수 없을 정도로 위험이 커진다. </li>
</ul>
<h3 id="결론">결론</h3>
<ul>
<li>애자일의 설계는 과정이지, 결과가 아니다.</li>
<li>시스템의 설계를 간단하고 명료하게 유지하려는 노력이다.</li>
</ul>
<h3 id="마치며-⛳️">마치며 ⛳️</h3>
<p>시스템을 완성하는 것에 초점을 두지 않고, 나중에 할 유지보수까지 고려하여 어떻게 설계해야하는지 알게 되었다. 좋은 소프트웨어를 만들기 위하여 작은 문제가 발생하면 바로 고치고, 지속적인 리팩토링을 통하여 미래에 있을 변화에 탄력적일 수 있도록 관리해야겠다! </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JavaScript] JavaScript의 IIFE 사용]]></title>
            <link>https://velog.io/@__dan_n/JavaScript-JavaScript%EC%9D%98-IIFE-%EC%82%AC%EC%9A%A9</link>
            <guid>https://velog.io/@__dan_n/JavaScript-JavaScript%EC%9D%98-IIFE-%EC%82%AC%EC%9A%A9</guid>
            <pubDate>Wed, 02 Aug 2023 02:45:48 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/__dan_n/post/b4bc27a4-df6d-43e2-a500-017c5ceca47a/image.PNG" alt=""></p>
<h3 id="들어가며">들어가며</h3>
<p>컴포넌트의 리턴문 안에서 다중 조건에 따라 다른 value를 적용하고 싶어서 처음에는 삼항 연산자에 조건을 덧붙여서 사용했으나, 가독성면에서 좋지 않은 것 같다는 생각이 들었다. 그래서 <code>switch</code> 문을 이용하여 조건에 따라 다른 value를 반환하는 함수를 만들어서 호출하는 방식으로도 바꾸어보았지만, 그럴 필요없이 자바스크립트의 IIFE 를 이용하면 된당. </p>
<h3 id="iife란">IIFE란?</h3>
<Blockquote>
  IIFE(Immediately Invoked Function Expression)는 함수를 정의하고 즉시 실행하여 함수 내부의 코드를 실행하는 패턴이다.
  </Blockquote>

<p>  IIFE 를 사용하면 함수가 정의되자마자 바로 실행되며, 반환된 결과가 JSX의 내용으로 사용된다.</p>
<h3 id="사용-예시">사용 예시</h3>
<pre><code class="language-javascript">const Product = () =&gt; {
    return (
      &lt;&gt;
        {(() =&gt; {
          const criterion = product.criterion; 
          const value = product[criterion];
          switch (criterion) {
            case &quot;CONVERSION_RATE_SESSION&quot;:
              return value.toFixed(3);
            case &quot;REVENUE&quot;:
              return value.toLocaleString();
            default:
              return value;
         }   
       })()}
     &lt;/&gt;
    )
}
</code></pre>
<p>위 코드에서는 <code>{}</code> 안에 IIFE를 작성하고 있다. 
맨 마지막에 있는 <strong><code>()</code>가 IIFE를 실행하는 역할</strong>을 하며, <strong>함수가 즉시 실행</strong>되고 <strong>반환된 결과가 JSX의 내용</strong>으로 사용된다. 
따라서 <code>{}</code> 안에 있는 IIFE가 실행되면서, 내부의 조건문(criterion 값에 따라 value 값을 처리하여 반환)에 따라 원하는 결과가 컴포넌트의 반환 값으로 출력된다.</p>
<Blockquote>
  함수를 <b>function() {}</b> 과 같이 작성되면,이 코드는 함수 선언문(statement) 으로 해석된다.<br/>
 반면, <b>()</b> 와 같이 괄호로 묶어주게 되면 이것은 함수 선언문이 아닌 함수 표현식으로 해석된다.
  </Blockquote>

<h3 id="iife-사용-이유">IIFE 사용 이유</h3>
<p>** 1. 블록 스코프 **
IIFE를 사용하여 코드를 감싸면, 내부에 있는 변수들이 블록 스코프를 가지게 된다. 이는 외부에 있는 변수들과 겹치지 않아서 <em>변수명 충돌을 방지</em> 하는 데 도움이 된다.</p>
<p>**  2. 깔끔한 JSX **
IIFE를 사용하면 JSX에서 <em> 불필요한 변수 선언을 최소화</em> 할 수 있다. 함수 안에서 필요한 계산을 하고, 최종 결과만 JSX에 사용할 수 있다.</p>
<h3 id="마치며">마치며</h3>
<p>선언 하자마자 실행시킬 수 있는 방법이 이미 만들어져있는게 넘 신기하고... 역시 JS에는 없는게 없당
끗 !! 🐰</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[클린 소프트웨어] chapter 2. 익스트림 프로그래밍 소개 ]]></title>
            <link>https://velog.io/@__dan_n/%ED%81%B4%EB%A6%B0-%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4-chapter-2.-%EC%9D%B5%EC%8A%A4%ED%8A%B8%EB%A6%BC-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D-%EC%86%8C%EA%B0%9C</link>
            <guid>https://velog.io/@__dan_n/%ED%81%B4%EB%A6%B0-%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4-chapter-2.-%EC%9D%B5%EC%8A%A4%ED%8A%B8%EB%A6%BC-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D-%EC%86%8C%EA%B0%9C</guid>
            <pubDate>Sat, 29 Jul 2023 07:22:18 GMT</pubDate>
            <description><![CDATA[<h3 id="시작하며">시작하며</h3>
<p>익스트림 프로그래밍은 chapter1 에서 등장했던 애자일 방법론 중 하나이다. 비즈니스 상의 요구가 시시각각 변동이 심한 소규모 프로젝트에 적합한 개발 방법론이다. </p>
<h3 id="xp-실천방법">XP 실천방법</h3>
<p><strong>고객 팀 구성원</strong></p>
<ul>
<li>고객과 개발자가 서로 긴밀하게 작업하면서 서로의 문제를 인식하고 이를 해결하기 위해 노력해야 한다</li>
</ul>
<p><strong>사용자 스토리(user story)</strong></p>
<ul>
<li>현재 진행 중인 요구사항에 관한 대화의 연상 기호이다</li>
<li>고객이 우선순위와 추정 비용에 근거해 요구사항의 구현 일정을 수립하게 해주는 계획 툴이다</li>
</ul>
<p><strong>짧은 반복</strong></p>
<ul>
<li>XP 프로젝트는 일반적으로 개발 중인 소프트웨어를 2주마다 공개한다.</li>
<li>반복(Iteration) 계획 : Minor delivery(최종 제품에 반영될수도 , 그렇지 않을수도 있음) : 보통 2주</li>
<li>릴리즈 계획 : Major delivery(보통 최종 제품에 포함됨) : Iteration(2주) * 6 = 보통 3개월</li>
</ul>
<p><strong>인수 테스트(acceptance test)</strong></p>
<ul>
<li>이 테스트는 시스템이 고객이 명시한대로 동작하는지 여부를 명시한다</li>
</ul>
<p><strong>짝 프로그래밍</strong></p>
<ul>
<li><strong>결함이 적고</strong> 더 나은 프로그램을 만들 수 있어서 전체적으로 <strong>효율성은 좋아진다</strong></li>
</ul>
<p><strong>TDD(Test-Driven Development)</strong></p>
<ul>
<li>테스트는 프로그램이 잘 동작하는지 점검할 수 있게 해준다</li>
<li>리팩토링을 용이하게 한다.</li>
<li>코드를 모듈별로 분리하여 독립적으로 테스트될 수 있게 해야 한다</li>
</ul>
<p><strong>공동 소유권</strong></p>
<ul>
<li>도메인이나 구조 별로 담당자를 특별하게 구분하지 않는다. 즉, 전문 분야의 일에만 묶여있지 않는다</li>
</ul>
<p><strong>지속적 통합(continuous Integration)</strong></p>
<ul>
<li>비차단 소스 제어 방식 사용(nonblocking source control) → 언제나 편하게 코드를 
check-in(push), check-out(pull) 할 수 있어야 한다.</li>
<li>하루에도 여러 번 처음부터 끝까지 전체 시스템을 빌드 한다.</li>
</ul>
<p><strong>지속 가능한 속도</strong></p>
<ul>
<li>소프트웨어 프로젝트는 마라톤이다. 꾸준히 지속 가능한 속도 (pace)로 달려야 한다</li>
</ul>
<p><strong>열린 작업 공간</strong></p>
<ul>
<li>팀 내 소통은 언제나 열려 있어야 한다. War room에서 함께 일하는 것이 생산성을 향상 시킨다</li>
</ul>
<p><strong>계획 세우기 게임</strong></p>
<ul>
<li>짧은 반복과 빈번한 릴리즈를 통해서 고객과 개발자사 프로젝트 리듬에 익숙해 지면, 프로젝트의 소요 기간과 비용을 빠르게 측정할 수 있게 된다.</li>
</ul>
<p><strong>단순한 설계</strong></p>
<p>최대한 단순한 방식으로 요구사항을 구현한다. 만약 요구사항이 필요로 할 때만 인프라가 추가된다.</p>
<ul>
<li>어떻게든 동작하는 가장 단순한 것을 생각한다. 현재 스토리를 구현하는 가장 단순한 솔루션을 선택한다</li>
<li>인프라(기반구조)가 필요하지 않을 것이라는 가정에서 시작한다. 기반구조를 추가하는 것이 효과적이라는 확실한 증거가 있을 때 추가한다</li>
<li>코드를 중복해서 쓰지 않는다. 중복성(redundancy)를 제거하는 최선의 방법은 추상화(abstraction)이다. 추상형을 사용하면 결합성(coupling)이 낮아진다</li>
</ul>
<p><strong>리팩토링</strong></p>
<ul>
<li>코드 구조는 퇴화하기 쉬우며, 언제나 잦은 리팩토링으로 이를 극복해야 한다. 리팩토링은 행위에 영향을 주지 않고 시스템 구조를 개선한다.</li>
</ul>
<p><strong>메타포(metaphor)</strong></p>
<ul>
<li>전체 시스템을 하나로 묶는 큰 그림. 이것은 모든 개별적인 모듈의 위치와 형태를 명백하게 만든다.</li>
</ul>
<h3 id="결론">결론</h3>
<p>XP는 에자일 개발 프로세스를 구성하는 단순하고 구체적인 방식의 집합이다.</p>
<h3 id="마치며">마치며</h3>
<p>XP는 소규모 프로젝트에 적용하기 좋은 방법론이기 때문에, 아직 대규모 프로젝트보다는 소규모 프로젝트를 많이 다루는 나에게 더 적합할 것 같다. 
XP는 빠르게 변하는 니즈에 대처하기 유연한 개발방식인 것 같다.🥨</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[클린 소프트웨어] chapter 1. 애자일 실천 방법]]></title>
            <link>https://velog.io/@__dan_n/%ED%81%B4%EB%A6%B0-%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4-chapter-1.-%EC%95%A0%EC%9E%90%EC%9D%BC-%EC%8B%A4%EC%B2%9C-%EB%B0%A9%EB%B2%95</link>
            <guid>https://velog.io/@__dan_n/%ED%81%B4%EB%A6%B0-%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4-chapter-1.-%EC%95%A0%EC%9E%90%EC%9D%BC-%EC%8B%A4%EC%B2%9C-%EB%B0%A9%EB%B2%95</guid>
            <pubDate>Sat, 29 Jul 2023 06:40:15 GMT</pubDate>
            <description><![CDATA[<h3 id="시작하며">시작하며</h3>
<p>소프트웨어디자인패턴이라는 과목을 들으면서 읽게 된 <a href="https://www.yes24.com/Product/Goods/39497990">클린 소프트웨어</a> 에 대해 정리한 글이다. 읽다보니 흥미가 생겨서 정리해두고 나중에 다시 보기 위해 쓰는 중이다! 사실은 시험 공부 하기 위해 정리한 글... 이지만 어찌됐든 내가 정리한 건 맞으니까 ..</p>
<h3 id="계속되는-악순환">계속되는 악순환</h3>
<ol>
<li>많은 프로젝트가 실천방법 없이 프로젝트를 진행한다.</li>
<li>그로 인해 실패를 경험하게 되고 결과와 산출물을 요구하는 프로세스가 생긴다.</li>
<li>하지만 까다롭고 많은 프로세스는 오히려 <strong>계속되는 악순환</strong>을 생기게 하여 프로세스를 더욱 복잡하게 만든다 → 이는 <em>소프트웨어 위기</em> 와 연결된다.</li>
<li>아이러니 하게도 위와 같은 프로세스를 채택하는 회사가 빠르게 늘어났다</li>
</ol>
<h3 id="애자일-연합">애자일 연합</h3>
<p>** 애자일 소프트웨어 개발 선언문 **</p>
<ul>
<li>프로세스와 툴보다 개인과 상호작용이 우선이다.<ul>
<li>프로그래밍 실력은 평범하지만 서로 잘 대화하는 팀이 성공할 가능성이 높다.</li>
<li>팀을 만들기 위해 노력하고 그런 뒤에 팀의 필요를 기반으로 환경을 구축하자.</li>
<li>팀을 구성하는 일은 환경을 구축하는 일보다 더 중요하다.</li>
</ul>
</li>
<li>포괄적인 문서보다 동작하는 소프트웨어가 우선이다.<ul>
<li>설계 원리와 구조에 대한 문서를 쓰고 유지하되, <em>짧고 요약적</em> 이어야 한다.</li>
<li>새로운 팀원에게 정보를 전할 수 있는 제일 좋은 기록은 code 와 team이다</li>
<li>그 필요가 급박하고 중요하지 않다면 아무 문서도 만들지 마라  </li>
<li>Martin 의 문서화 제 1법칙-</li>
</ul>
</li>
<li>계약 협상보다 고객 협력이 우선이다.<ul>
<li>규칙적으로 자주 고객의 피드백을 받아야 한다.</li>
<li>개발팀과 고객이 가까이서 일한다. (고객과의 협력)</li>
</ul>
</li>
<li>계획에 따르는 것 보다 변화에 대한 반응이 우선이다.<ul>
<li>소프트웨어 프로젝트의 성공과 실패를 좌우하는 것은 변화에 대한 반응 능력이다</li>
<li>가까운 시일 내에 수행할 테스크에 대해서만 세부적인 계획을 세우고, 나머지 부분은 탄력적으로 조정할 수 있다.</li>
</ul>
</li>
</ul>
<p>** 원칙 ** </p>
<ul>
<li>우리의 최고 가치는 유용한 소프트웨의 빠르고 지속적인 공개를 통해 고객을 만족시키는 것이다.<ul>
<li>자주 공개할 수록 최종 품질도 좋았다. 에자일 실천 방법은 빨리 자주 공개하는 것이다</li>
</ul>
</li>
<li>개발 후반부에 접어들었다 할지라도, 요구사항 변경을 환영하라<ul>
<li>변화를 걱정하지 않고 요구 사항 변경을 긍정적인 것으로 본다.</li>
<li>소프트웨어의 구조를 탄력적으로 유지하기 위해서 노력하기 때문에, 요구사항이 변경됐을 때 시스템에 최소한의 영향을 미치게 된다.</li>
</ul>
</li>
<li>개발 중인 소프트웨어를 자주 공개하라<ul>
<li>문서와 계획 꾸러미가 아닌, 고객의 요구를 만족시키는 소프트웨어를 공개해야한다</li>
</ul>
</li>
<li>업무를 하는 사람과 개발자는 계속 함께 일해야 한다. 
→ 소프트웨어는 지속적으로 관리되어야 한다</li>
<li>의욕적인 개인들을 중심으로 프로젝트를 구성하라. 환경과 필요로 하는 지원을 제공하고 그들이 그 일을 해낼 것이라 믿고 맡겨둬라. 
→ 사람이 성공의 가장 중요한 요소이다</li>
<li>개발 팀 내에서 정보를 전달하고 공유하는 가장 효율적이고 효과적인 방법은 직접 일대일로 대화하는 것이다.</li>
<li>개발 중인 소프트웨어가 진척 상황의 일차적 척도다.</li>
<li>애자일 프로세스는 지속 가능한 개발을 촉진한다. 스폰서, 개발자, 사용자는 무한히 지속적인 pace를 유지할 수 있어야 한다.<ul>
<li>지나치게 빨리 나아가는 것은 엄청난 실패로 이어진다. 에자일 팀은 속도를 조절하여 프로젝트 기간 동안 가장 높은 질의 기준을 유지할 수 있을 정도로 일한다</li>
</ul>
</li>
<li>우수 기술과 좋은 설계에 대한 지속적인 관심은 속도를 향상한다.<ul>
<li>높은 품질은 빠른 속도에 있어서 중요한 요소이기 때문에 자신이 작성할 수 있는 가장 높은 품질의 코드만 만든다.</li>
</ul>
</li>
<li>단순성(아직 끝내지 않은 일의 양을 최대화하는 예술)은 필수적이다.<ul>
<li>내일의 문제를 예상하는데 지나친 관심을 두지 않으며, 가장 간단하고 고품질의 작업을 오늘 행한다.</li>
</ul>
</li>
<li>최고의 아키텍쳐, 요구사항, 설계는 자기 조직적인 팀에서 나온다.<ul>
<li>책임감은 팀원 개개인이 아닌 온전한 팀에게 전달된다.</li>
<li>에자일 팀은 프로젝트의 모든 분야에서 함께 일하고 각 팀원이 전체 분야에 참여한다</li>
</ul>
</li>
<li>규칙적으로 팀은 좀 더 효과적인 방법을 반영해야 하고, 적절히 그 행위를 조율하고 조정해야 한다.</li>
</ul>
<h3 id="결론">결론</h3>
<ul>
<li>프로세스가 늘어나는 악순환은 프로젝트 실패의 원인 중 하나이다.</li>
<li>애자일은 그들이 목표에 다다르기 위해 간단한 테크닉에 초점을 맞추는 것을 돕기 위한 방법으로서 만들어졌다.</li>
</ul>
<h3 id="마치며">마치며</h3>
<p>chapter1은 프로젝트의 성공을 위해 어떤 원칙들을 따라야하는지 잘 소개된 글이라고 생각한다. 내가 생각했던 것보다 어려운 원칙이 아니라서 실전에 적용해볼 수 있을 것 같다. 자세한 설명이 덧붙여 있어서 읽으며 공감하게 된 내용이다 🐿. 
성공하는 프로젝트란 이런거구낭.....</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JavaScript] undefined 와 null 의 차이점]]></title>
            <link>https://velog.io/@__dan_n/undefined-%EC%99%80-null-%EC%9D%98-%EC%B0%A8%EC%9D%B4%EC%A0%90</link>
            <guid>https://velog.io/@__dan_n/undefined-%EC%99%80-null-%EC%9D%98-%EC%B0%A8%EC%9D%B4%EC%A0%90</guid>
            <pubDate>Wed, 19 Jul 2023 05:30:51 GMT</pubDate>
            <description><![CDATA[<p>undefined와 null은 JavaScript에서 모두 값이 없음을 나타내는 것이지만 미묘한 차이가 있다. </p>
<h3 id="null">null</h3>
<ul>
<li>null은 값이 없음을 명시적으로 표현하는데 사용한다.</li>
<li>undefined는 값이 지정되지 않은 경우를 의미하지만, null의 경우에는 해당 변수가 어떤 객체도 가리키고 있지 않다는 것을 의미한다.</li>
</ul>
<pre><code class="language-javascript">// 값이 의도적으로 비어있음을 표현하는 경우
let a = null;
console.log(a); // null

const person = { name: &#39;hyun&#39; };
person.name = null;
console.log(person.name); // null</code></pre>
<h3 id="undefined">undefined</h3>
<ul>
<li>undefined는 변수가 선언되었지만 값을 할당하지 않은 경우의 기본값이다.</li>
<li>변수가 선언되지 않은 상태에서 접근하면 자동으로 undefined가 할당된다.</li>
<li>함수가 반환값을 지정하지 않거나, 객체의 속성이 존재하지 않는 경우에도 undefined가 반환된다.</li>
</ul>
<pre><code class="language-javascript">// 1. 값을 할당하지 않은 변수
let a;
console.log(a); // undefined

// 2. 함수가 반환 값을 지정하지 않은 경우
function foo() {

}
console.log(foo()); // undefined

// 3. 선언되지 않은 변수에 접근한 경우
const obj = { a: 10 };
console.log(obj.b); // undefined</code></pre>
<h3 id="👻-알아둘-점">👻 알아둘 점</h3>
<p><strong>1. undefined와 null은 동일하지 않다.</strong></p>
<pre><code class="language-javascript">console.log(undefined == null); // true
console.log(undefined === null); // false</code></pre>
<p>두 값이 동등성(equality) 비교(==)를 할 경우에는 같은 것으로 취급하지만, 일치성(strict equality) 비교(===)를 할 경우에는 다른 것으로 취급된다.</p>
<p><strong>2. null과 undefined의 type</strong></p>
<pre><code class="language-javascript">typeof null // object
typeof undefined // undefined</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[React] Missing script: "start"]]></title>
            <link>https://velog.io/@__dan_n/React-Missing-script-start</link>
            <guid>https://velog.io/@__dan_n/React-Missing-script-start</guid>
            <pubDate>Thu, 09 Mar 2023 04:44:29 GMT</pubDate>
            <description><![CDATA[<h3 id="👻">👻</h3>
<p>간단한 리액트 작업을 수행하던중 npm start 을 입력하니 <em><strong><span style="color:red">npm ERR! Missing script: &quot;start&quot;</span></strong></em> 라는 에러가 발생하였다.</p>
<h3 id="에러-내용">에러 내용</h3>
<p>자세한 에러 내용은 이러하다.
내가 수행하려는 start 명령과 관련된 스크립트가 존재하지 않는다는 것 같다. </p>
<pre><code>npm ERR! Missing script: &quot;start&quot;
npm ERR! 
npm ERR! Did you mean one of these?
npm ERR!     npm star # Mark your favorite packages
npm ERR!     npm stars # View packages marked as favorites
npm ERR! 
npm ERR! To see a list of scripts, run:
npm ERR!   npm run</code></pre><h3 id="해결-방법">해결 방법</h3>
<p>해결 방법은 간단하다. start 와 관련된 스크립트가 존재하지 않으므로 scripts 명령어를 추가하면 된다. 아래와 같이 package.json 파일에 명령어를 추가해준다.</p>
<pre><code class="language-json">// package.json
{
  &quot;scripts&quot;: {
    &quot;start&quot;: &quot;react-scripts start&quot; 
  },
}</code></pre>
<p>위와 같이 추가한 뒤 npm start 실행하면 문제 없이 실행될 것이다. ✌🏻
끗!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[React] custom hooks 를 이용하여 scroll event 만들기]]></title>
            <link>https://velog.io/@__dan_n/React-custom-hooks-%EB%A5%BC-%EC%9D%B4%EC%9A%A9%ED%95%98%EC%97%AC-scroll-event-%EB%A7%8C%EB%93%A4%EA%B8%B0</link>
            <guid>https://velog.io/@__dan_n/React-custom-hooks-%EB%A5%BC-%EC%9D%B4%EC%9A%A9%ED%95%98%EC%97%AC-scroll-event-%EB%A7%8C%EB%93%A4%EA%B8%B0</guid>
            <pubDate>Tue, 08 Nov 2022 19:29:14 GMT</pubDate>
            <description><![CDATA[<h2 id="구현-사항-🚀">구현 사항 🚀</h2>
<p>오늘 제가 구현하고 싶은 기능은 아래 사진처럼 항상 떠 있는 말풍선을 스크롤 했을 때 FadeIn 되도록 하는 것입니다. 처음에 생각한 방법은 현재 스크롤 된 간격을 구해서, 특정 위치에 도달하면 display: none으로 설정된 말풍선이 보여지도록 바꾸는 것이었는데, 찾아보니 hooks 를 사용하여 간편하게 구현할 수 있다고 하여 hooks를 이용한 방식으로 구현하였습니다.  </p>
<p><img src="https://velog.velcdn.com/images/__dan_n/post/d6d45121-3e71-4a9b-9d97-9102d8b56292/image.png" alt=""></p>
<h2 id="구현-방법-🤔">구현 방법 🤔</h2>
<h3 id="1-custom-hooks-사용-이유">1. custom hooks 사용 이유</h3>
<p>제가 custom hooks를 사용한 가장 큰 이유는 <span style="color: blue">반복되는 로직을 다양한 곳에서 재사용하기 위함</span>입니다. </p>
<p>현재 제가 개발 중인 웹에서는 FadeIn 효과가 한 곳에서만 사용되지만, 보통 규모가 큰 웹에서는 같은 animation을 다양한 곳에서 적용하게 됩니다. 그래서 custom hooks를 사용하여 animation을 구현해 둔다면 다양한 곳에서 같은 animation을 쉽게 적용할 수 있습니다. 
만약 제가 개발중인 웹에서 페이지가 추가되고 같은 애니메이션을 활용할 필요가 생긴다면 같은 커스텀 훅을 가져와서 쉽게 구현할 수 있습니다.
<br/></p>
<h3 id="2-fadein-animation-구현">2. FadeIn animation 구현</h3>
<p>아래 코드에서는 다음과 같은 기능을 합니다. 이벤트가 발생하기 전에는 ref가 가리키고 있는 element를 <strong>opacity= 0, translate3d(0, 50%, 0)</strong> 으로 숨겨 놓다가 (up 방향 기준), 이벤트가 발생하면 onScroll 함수에서 <strong>opacity=1, translate3d(0, 0, 0)</strong> 로 바꿔주어 element를 제자리에 보여줍니다. </p>
<pre><code class="language-javascript">const useScrollFadeIn = () =&gt; {
  const element = useRef();

  const onScroll = useCallback(
    ([entry]:any) =&gt; {
      const { current }:any = element;
      if (entry.isIntersecting) {
        current.style.transitionProperty = &#39;all&#39;;
        current.style.transitionDuration = `${duration}s`;
        current.style.transitionTimingFunction = &#39;cubic-bezier(0, 0, 0.2, 1)&#39;;
        current.style.transitionDelay = `${delay}s`;
        current.style.opacity = 1;
        current.style.transform = &#39;translate3d(0, 0, 0)&#39;;
      }
    },
    [delay, duration],
  );</code></pre>
<br/>
아래 코드에서는 return 시 초기에 element를 숨겨두기 위한 style 요소를 설정합니다. 이때 박스의 css 속성에 opacity 등을 사용했다면 레이아웃이 깨질 수 있습니다. 저는 기존 박스에 opacity 속성을 따로 사용했기 때문에, 원하는 레이아웃을 만들어주기 위해 기존 박스를 감싸는 태그를 추가적으로 만들어서 FadeIn 이벤트를 적용하였습니다. 

<pre><code class="language-javascript">  useEffect(() =&gt; {
    let observer: any;

    if (element.current) {
      observer = new IntersectionObserver(onScroll, { threshold: 0.7 });
      observer.observe(element.current);
    }

    return () =&gt; observer &amp;&amp; observer.disconnect();
  }, [onScroll]);

  return {
    ref: element,
    style: { opacity: 0, transform: handleDirection(direction) },
  };
};</code></pre>
<p>  handleDirection 부분에는 <strong><em>적용하고 싶은 translate3d 값</em></strong> 을 넣어주면 됩니다. 저는 props로 받은 방향에 따라 다른 translate3d 값을 넣어주기위해 handleDirection 이라는 함수를 만들어두고 값을 넣어주었습니다. </p>
<br/>

<h3 id="3-intersectionobserver-란-">3. IntersectionObserver 란 ?</h3>
<p>위에서 FadeIn 기능을 구현할 때 IntersectionObserver 라는 것이 사용되었습니다.
Intersection Observer는 <span style="color: blue">타겟 엘리먼트와, 타겟 엘리먼트의 부모나 뷰포트가 교차하는 부분의 변화를 비동기적으로 관찰하는 API</span>입니다. 
Intersection Observer는 비동기적입니다. intersection이 일어날 때 인자로 넘겨준 callback을 실행시켜줍니다. </p>
<pre><code class="language-javascript">observer = new IntersectionObserver(onScroll, { threshold: 0.7 });
      observer.observe(element.current);</code></pre>
<p>IntersectionObserver에는 파라미터로 특정 스크롤 시점에 실행 할 함수와 Observer 세팅 값들을 넘겨 줍니다.</p>
<ul>
<li>threshold  <ul>
<li>threshold는 타겟이 얼만큼 보여야 callback(여기서는 onScroll 함수)이 작동할지 결정하는 값입니다.</li>
<li>예를 들어 0.7을 넘겨주면 TargetElement가 70% 보이는 시점에 callback을 실행합니다. </li>
<li>배열로도 넘겨줄 수 있습니다. </li>
<li>default 값은 0이며, 1px만 보여도 실행됩니다. </li>
</ul>
</li>
</ul>
<br/>

<h3 id="4-주요-로직">4. 주요 로직</h3>
<ol>
<li>opacity와 translate3d를 이용하여 초기에는 element가 보이지 않게 해둡니다.</li>
<li>Intersection Observer 를 통해 Target Element가 70% 보이는 시점에서 onScroll 함수가 실행됩니다. </li>
<li>onScroll 함수에서 opacity와 translate3d 값을 변경하여 element를 원하는 곳에 위치시킵니다. <br/>

</li>
</ol>
<h3 id="5-구현-완료">5. 구현 완료</h3>
<img src="https://velog.velcdn.com/images/__dan_n/post/209a3e83-a5c4-4e52-9c41-38870e9b4a16/image.GIF" width="100%" height="100%">
FadeIn 기능 완성 ! 

<br/>

<h2 id="마치며-🐱">마치며 🐱</h2>
<p>나는 아직도 hooks가 넘 어렵다.. <br/>그래도 윈도우에 리스너를 달아서 스크롤된 위치를 구하고.. 특정 위치가 될 때마다 각 element의 css를 조절해주려고 했던 나의 초기 생각보다는 IntersectionObserver 와 hook을 사용한 위의 방법이 
<span style="color: gray">편리함이나 코드 재사용성면</span>에서 더 좋은 것 같다. </p>
<p>또한 display 속성이 아닌 <em><strong>opacity</strong>_를 이용해서 element를 숨기는 방식과, 윈도우에서 스크롤 값을 구하는 것이 아니라 _<strong>threshold</strong></em> 를 이용하여 이벤트를 발생시킨다는 방식도 새로웠던 것 같다. 
끗
<br/></p>
<hr>
<h3 id="참고한-글">참고한 글</h3>
<p><a href="https://github.com/jus0k/scroll-hooks">https://github.com/jus0k/scroll-hooks</a></p>
<p><a href="https://godsenal.com/posts/React-Intersection-Observer%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%98%EC%97%AC-%EC%9D%B8%ED%94%BC%EB%8B%88%ED%8A%B8-%EC%8A%A4%ED%81%AC%EB%A1%A4-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0/">https://godsenal.com/posts/React-Intersection-Observer%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%98%EC%97%AC-%EC%9D%B8%ED%94%BC%EB%8B%88%ED%8A%B8-%EC%8A%A4%ED%81%AC%EB%A1%A4-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0/</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[vscode] styled-component 자동완성이 되지 않을 때 ]]></title>
            <link>https://velog.io/@__dan_n/vscode-styled-component-%EC%9E%90%EB%8F%99%EC%99%84%EC%84%B1%EC%9D%B4-%EB%90%98%EC%A7%80-%EC%95%8A%EC%9D%84-%EB%95%8C</link>
            <guid>https://velog.io/@__dan_n/vscode-styled-component-%EC%9E%90%EB%8F%99%EC%99%84%EC%84%B1%EC%9D%B4-%EB%90%98%EC%A7%80-%EC%95%8A%EC%9D%84-%EB%95%8C</guid>
            <pubDate>Thu, 27 Oct 2022 13:05:33 GMT</pubDate>
            <description><![CDATA[<h3 id="문제-상황-🫠">문제 상황 🫠</h3>
<p>styled-component를 이용하여 css 코드를 작성할 때 아래 사진과 같이 자동완성이 되지 않을 때가 있다. disp 까지만 쳐도 display 가 위에 떠야 하는데 정말 불편하게 아무것도 뜨지 않는다. 
<img src="https://velog.velcdn.com/images/__dan_n/post/806bf3bf-492f-4f86-a448-ef967aa6bd8a/image.png" alt="">
또한 아래 사진처럼 코드에 하이라이팅이 전혀 되지 않고 있어서 가독성이 떨어진다. 
<img src="https://velog.velcdn.com/images/__dan_n/post/9e8f5c60-9099-4f1a-9030-8826f9435988/image.png" alt=""></p>
<h3 id="해결-🚀">해결 🚀</h3>
<p>styled-component 확장이 변경되었기 때문에 아래 링크에서 설치하면 된다. 
<a href="https://marketplace.visualstudio.com/items?itemName=styled-components.vscode-styled-components">https://marketplace.visualstudio.com/items?itemName=styled-components.vscode-styled-components</a></p>
<p>그러면 원하던 것처럼 dis까지만 쳐도 display 자동완성이 잘 되는 것을 확인할 수 있다.
<img src="https://velog.velcdn.com/images/__dan_n/post/7b7ef32b-e280-4201-87b2-33fec0eaa929/image.png" alt="">
코드 하이라이팅도 잘 반영되어있다. 가독성이 정말정말 좋아졌다 ! 
<img src="https://velog.velcdn.com/images/__dan_n/post/34f73123-fc77-4f72-ba5a-4ef6efdfd5b5/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[React] react.memo 사용법 ]]></title>
            <link>https://velog.io/@__dan_n/React-react.memo-%EC%82%AC%EC%9A%A9%EB%B2%95</link>
            <guid>https://velog.io/@__dan_n/React-react.memo-%EC%82%AC%EC%9A%A9%EB%B2%95</guid>
            <pubDate>Mon, 29 Aug 2022 10:56:21 GMT</pubDate>
            <description><![CDATA[<h3 id="reactmemo-를-사용한-리렌더링-방지">react.memo 를 사용한 리렌더링 방지</h3>
<p>자식 컴포넌트는 state가 바뀌었을 때, Props가 바뀌었을 때, 그리고 부모 컴포넌트가 리렌더링 됐을 때 리렌더링 됩니다. 
이때 <code>React.memo</code> 라는 함수는 <em>부모 컴포넌트가 리렌더링 됐을 때 자식 컴포넌트가 리렌더링 되는 것을 막아줍니다.</em> state나 props가 바뀌었을 때는 여전히 리렌더링 되지만, 부모 컴포넌트가 바뀌었을때 자식 컴포넌트까지 리렌더링 되는 것을 막아주어 <span style="color: blue">리렌더링 성능 최적화</span>를 돕습니다. </p>
<h3 id="reactmemo-의-원리">react.memo 의 원리</h3>
<p><code>React.memo</code> 를 사용하여 컴포넌트를 감싸게 되면, 감싸고 있는 컴포넌트를 렌더링할 때 이전에 기억하고 있던 결과물을 메모리에 기억해두고 있다가(memoize) 재사용하기 때문에 불필요한 렌더링을 건너뜁니다.</p>
<h3 id="사용법">사용법</h3>
<p>memo 사용법은 간단합니다. Memo 를 import 해온 뒤 컴포넌트를 <code>memo</code> 로 감싸주시면 됩니다. </p>
<pre><code class="language-javascript">import React, {memo} from &quot;react&quot;

function Try({tryInfo}:any) {
    return (
        &lt;li &gt;
            &lt;div&gt;{tryInfo.try}&lt;/div&gt;
            &lt;div&gt;{tryInfo.result}&lt;/div&gt;
        &lt;/li&gt;
    )
}

export default memo(Try)</code></pre>
<p>이제 Try 라는 컴포넌트는 state가 바뀌었을 때, props인 tryInfo가 바뀌었을 때만 리렌더링 됩니다. </p>
<h3 id="언제-사용할까">언제 사용할까?</h3>
<p><img src="https://velog.velcdn.com/images/__dan_n/post/b6520951-cf44-457e-83d6-14131f08e646/image.jpeg" alt="">
그렇다면 React.memo를 항상 사용해야 하는지에 대한 의문이 들었습니다.<br>memo 는 아래와 같은 상황에서 사용하기 좋습니다.</p>
<blockquote>
1. 같은 props를 가진 컴포넌트가 자주 렌더링 되는 경우 <br>
2. 컴포넌트가 무거운 경우
</blockquote>

<p>끗! </p>
<h3 id="참고한-글">참고한 글</h3>
<ul>
<li><a href="https://goongoguma.github.io/2021/09/22/Use-React.memo()-wisely/">https://goongoguma.github.io/2021/09/22/Use-React.memo()-wisely/</a></li>
</ul>
]]></description>
        </item>
    </channel>
</rss>