<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>min_99.log</title>
        <link>https://velog.io/</link>
        <description></description>
        <lastBuildDate>Sun, 21 Sep 2025 05:48:51 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>min_99.log</title>
            <url>https://velog.velcdn.com/images/min_99/profile/afdf553f-fb74-4419-ba40-de9bf0fc5b2a/image.JPG</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. min_99.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/min_99" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[Tistory로 이사합니다 ]]></title>
            <link>https://velog.io/@min_99/Tistory%EB%A1%9C-%EC%9D%B4%EC%82%AC%ED%95%A9%EB%8B%88%EB%8B%A4</link>
            <guid>https://velog.io/@min_99/Tistory%EB%A1%9C-%EC%9D%B4%EC%82%AC%ED%95%A9%EB%8B%88%EB%8B%A4</guid>
            <pubDate>Sun, 21 Sep 2025 05:48:51 GMT</pubDate>
            <description><![CDATA[<p>Tistory로 블로그 이사 합니다
<a href="https://min-99.tistory.com/">https://min-99.tistory.com/</a></p>
<p>감사합니다 :)</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[직대딩 생활(feat. 인하대학교)]]></title>
            <link>https://velog.io/@min_99/%EC%A7%81%EB%8C%80%EB%94%A9-%EC%83%9D%ED%99%9Cfeat.-%EC%9D%B8%ED%95%98%EB%8C%80%ED%95%99%EA%B5%90</link>
            <guid>https://velog.io/@min_99/%EC%A7%81%EB%8C%80%EB%94%A9-%EC%83%9D%ED%99%9Cfeat.-%EC%9D%B8%ED%95%98%EB%8C%80%ED%95%99%EA%B5%90</guid>
            <pubDate>Sun, 21 Sep 2025 05:22:05 GMT</pubDate>
            <description><![CDATA[<p>안녕하세요,
2024년 한샘에서 FE 개발자로 일하며, 저는 &#39;어떻게 하면 더 좋은 개발자로 성장할 수 있을까?&#39;에 대한 근본적인 고민을 시작했습니다.</p>
<p>주니어 때는 주어진 요구사항을 잘 구현하는 것에 집중했지만, 경력이 쌓이면서 기술적 의사결정을 주도하는 역할을 맡게 되었습니다. 단순히 &#39;이렇게 하면 된다&#39;는 방식을 넘어, &#39;왜&#39; 그렇게 해야 하는지에 대한 논리적 근거를 명확히 제시해야 할 필요성을 느꼈습니다. 저는 이 과정에서 제가 가진 지식의 기반이 흔들리고 있음을 깨달았고, 이러한 기술적 리더십 역량을 강화하기 위해 컴퓨터 과학의 이론적 배경을 다시 배우기로 결심했습니다.</p>
<p>이를 통해 저는 단순한 코드 작성을 넘어, 팀을 설득하고 최적의 아키텍처를 설계하는 데 필수적인 지식을 갖추고자 했습니다. 그리고 이러한 목표에 가장 적합한 교육을 제공하는 <strong>인하대학교 소프트웨어융합공학과</strong> 를 선택하게 되었습니다.</p>
<h3 id="입학-생활">입학 생활</h3>
<div align=center>
<img src="https://velog.velcdn.com/images/min_99/post/d15546b3-7030-4f26-b052-fb0e2528743c/image.jpeg" width="200"  align=right>
<img src="https://velog.velcdn.com/images/min_99/post/ed51c388-440b-4c8a-add5-cb422b57d258/image.jpeg" width="200" align=right>
</div>

<p>1학기 시작 전, 신입생 오리엔테이션을 시작으로 대학 생활을 시작했습니다. 1학기에는 &#39;문제해결을 위한 글쓰기&#39;, &#39;Python을 활용한 데이터 다루기&#39;, 그리고 &#39;일반 수학&#39;을 수강했습니다. 오랜만에 수학 문제를 다시 풀었지만, <strong>정승제 선생님의 &#39;50일 수학&#39;</strong>을 통해 기본 개념을 다진 덕분에 수업을 더 수월하게 따라갈 수 있었습니다. 온라인 수업이 많았던 1학기에는 아침 6시에 기상하여 강의를 듣고, 퇴근 후 남은 과제를 처리하는 루틴을 만들며 학업을 병행했습니다.</p>
<p>방학 동안에는 2학기 수업 준비와 자격증 취득에 도전했습니다. 정보처리기사 실기 시험과 SQLD 시험에서 아쉽게도 한 문제 차이로 불합격했지만, 비록 합격하지 못했더라도 실무에서 당연하게 사용하던 데이터베이스의 정규화, 인덱싱 개념이나 운영체제와 네트워크 이론을 체계적으로 정리할 수 있는 좋은 기회였습니다. 이 경험을 바탕으로 부족한 부분을 보완하여 다음 시험에 다시 도전할 계획입니다.</p>
<p>현재 2학기에는 1학기보다 심화된 수학, 영어, 알고리즘, 객체지향 프로그래밍 과목을 수강 중입니다. 수학은 미적분, 벡터와 행렬, 확률과 통계 등을 배우며 Python 프로그래밍 실습을 병행하고 있습니다. 영어는 원어민 회화 수업을 듣고 있습니다. 처음에는 어려움이 있었지만, 주 2회 개인 보충 수업을 통해 완벽한 문장이 아니더라도 주저 없이 소통을 시도하는 자신감을 얻었습니다. 이를 통해 기술 문서를 더 원활하게 읽고, 글로벌 커뮤니티에도 참여하는 것을 목표로 하고 있습니다.</p>
<p>특히 알고리즘 수업은 고등학교 때 배웠던 자료구조를 다시 접하는 기회입니다. 당시에는 문제를 푸는 것에 집중했다면, 지금은 시간 복잡도와 공간 복잡도를 고려하며 실제 서비스의 성능을 어떻게 최적화할지 고민하고 있습니다. 수업 내용을 바탕으로 개념을 스스로 설명하고, 알고리즘적 사고를 적용해 문제를 해결하는 과정을 블로그에 기록하며 꾸준히 학습할 계획입니다.</p>
<br/>
<img src="https://velog.velcdn.com/images/min_99/post/86466f86-6cd8-4a47-8076-5061b7bf8b51/image.jpeg" width="200" align=right>

<h3 id="앞으로의-계획">앞으로의 계획</h3>
<p>저는 이론적 지식과 실무 경험을 결합해 현재 맡은 서비스의 성능을 최적화하고, 확장 가능한 아키텍처를 설계하는 개발자가 되고 싶습니다.</p>
<p>또한, 영어 의사소통 능력을 키우고 관련 자격증도 취득할 계획입니다. 이를 통해 최신 기술 트렌드와 해외 기술 문서를 빠르게 습득하고, 글로벌 개발자 커뮤니티에서도 적극적으로 소통하며 지식의 폭을 넓히고자 합니다.</p>
<p>아울러, 기초 수학을 넘어 선형대수학과 통계학을 심화 학습하여 데이터 분석이나 AI/머신러닝 등 미래 기술에 대한 기반을 다지고, 프론트엔드와 융합할 수 있는 새로운 도메인을 개척하고 싶습니다.</p>
<p>바쁜 일상이지만, 학업을 통해 얻는 지식과 에너지는 저를 더욱 몰입할 수 있는 개발자로 만들고 있습니다. 앞으로도 이론과 실무의 시너지를 바탕으로 회사의 기술적 발전에 기여하고, 장기적으로 꾸준히 성장하는 개발자가 되겠습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[이벤트 버블링과 캡처링의 차이]]></title>
            <link>https://velog.io/@min_99/%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EB%B2%84%EB%B8%94%EB%A7%81%EA%B3%BC-%EC%BA%A1%EC%B2%98%EB%A7%81%EC%9D%98-%EC%B0%A8%EC%9D%B4</link>
            <guid>https://velog.io/@min_99/%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EB%B2%84%EB%B8%94%EB%A7%81%EA%B3%BC-%EC%BA%A1%EC%B2%98%EB%A7%81%EC%9D%98-%EC%B0%A8%EC%9D%B4</guid>
            <pubDate>Mon, 07 Apr 2025 09:41:55 GMT</pubDate>
            <description><![CDATA[<h3 id="1-질문-던지기">1. 질문 던지기</h3>
<blockquote>
<p>&quot;이벤트 버블링과 캡처링의 차이는 뭔가요?&quot;</p>
</blockquote>
<br/> 

<h3 id="2-답변하기">2. 답변하기</h3>
<h4 id="질문에-대한-답">[질문에 대한 답]</h4>
<blockquote>
<p>&quot;이벤트가 발생하면 기본적으로 이벤트 전파가 일어나는데 이벤트 전파 방향에 따라서 이벤트 버블링이냐, 이벤트 캡처링이냐고 결정 됩니다.&quot;</p>
</blockquote>
<ul>
<li>이벤트 버블링은 거품이 아래에서 위로 올라온다는 것을 비유해 자식 -&gt; 부모로 올라가는 이벤트 전파 방향을 의미 합니다. </li>
<li>이벤트 캡쳐링은 버블링의 반대로 위에서 아래로 내려온다는 것을 의미 합니다.그래서 부모 -&gt; 자식으로 이벤트가 전파 되는 방향을 의미 합니다. </li>
<li>브라우저는 기본이 이벤트 버블링이 발생합니다. 이를 설정하는 방법은 이벤트를 등록할때 3번째 인자로 options를 설정하는데 그 부분을 설정하면 이벤트 전파 방향을 정할 수 있습니다. </li>
</ul>
<h4 id="스스로-질문의-범위-확장해보기">[스스로 질문의 범위 확장해보기]</h4>
<blockquote>
<ul>
<li>이벤트를 막을 수 있는 방법에는 <code>preventDefault()</code>와 <code>stopPropogate()</code>가 있습니다. 둘의 차이는 <code>preventDefault</code>는 이벤트 기본동작을 막는것이고, <code>stopPropogate</code>는 이벤트 전파를 막는것 입니다. </li>
</ul>
</blockquote>
<ul>
<li>이벤트를 체크하는 방법에는 <code>e.target</code>과 <code>e.currentTarget</code>이 있습니다. <code>target</code>은 최초로 이벤트가 발생한 요소이고, <code>currentTarget</code>은 지금 현재 이벤트의 요소 입니다. </li>
<li>이벤트를 등록하는 것은 굉장히 많은 메모리를 잡아먹습니다. 그래서 상위요소에만 이벤트를 등록하고, 하위 요소에서 이벤트가 발생하면 이벤트 전파로 이를 처리하면 적은 메모리로 이벤트를 처리할 수 있습니다. </li>
<li>css중에 이벤트전파를 막는 클릭 이벤트를 발생시키지 않은 css가 있습니다. <code>pointer-events: none</code></li>
</ul>
<h3 id="3-답변부분-교정하기--새롭게-알게-된-사실">3. 답변부분 교정하기 &amp; 새롭게 알게 된 사실</h3>
<blockquote>
<p>1) css의 <code>pointer-events: none</code>은 &#39;이벤트 전파&#39;를 막는다보다는 해당 요소가 마우스 이벤트의 대상이 되지 않게 합니다. 또 이로 인해 이벤트 전파가 막아지는것은 아니며, 이벤트 버블링은 여전히 발생합니다. </p>
</blockquote>
<p>2가지 케이스에 대해서 살펴보겠습니다. </p>
<p>1) 클릭해도 아무일도 안일어남 =&gt; div가 이벤트를 차단해서 button까지 이벤트가 도달되지 않음</p>
<pre><code>&lt;div style=&quot;pointer-events: none;&quot;&gt;
  &lt;button onclick=&quot;alert(&#39;clicked&#39;)&quot;&gt;버튼&lt;/button&gt;
&lt;/div&gt;</code></pre><p>2) button에서 이벤트가 발생할 수 있기 때문에 alert()이 동작하고, 버블링도 발생합니다. 하지만 div 요소는 <code>pointer-events:none</code> 이기 때문에 제외되고 버블링이 발생합니다. </p>
<pre><code>&lt;div style=&quot;pointer-events: none;&quot;&gt;
  &lt;button style=&quot;pointer-events: auto;&quot; onclick=&quot;alert(&#39;clicked&#39;)&quot;&gt;버튼&lt;/button&gt;
&lt;/div&gt;</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[기본동작(Default Behavior)와 합성 이벤트]]></title>
            <link>https://velog.io/@min_99/%EA%B8%B0%EB%B3%B8%EB%8F%99%EC%9E%91Default-Behavior%EC%99%80-%ED%95%A9%EC%84%B1-%EC%9D%B4%EB%B2%A4%ED%8A%B8</link>
            <guid>https://velog.io/@min_99/%EA%B8%B0%EB%B3%B8%EB%8F%99%EC%9E%91Default-Behavior%EC%99%80-%ED%95%A9%EC%84%B1-%EC%9D%B4%EB%B2%A4%ED%8A%B8</guid>
            <pubDate>Mon, 07 Apr 2025 09:41:00 GMT</pubDate>
            <description><![CDATA[<p>이번글을 저번 &#39;이벤트 버블링과 캡처링의 차이&#39;에서 확장된 이벤트 기본동작과 합성 이벤트에 대해서 적어보려고 합니다. </p>
<h3 id="1-기본동작default-behavior-이벤트-정리해보기">1. 기본동작(Default Behavior) 이벤트 정리해보기</h3>
<table>
<thead>
<tr>
<th>요소</th>
<th align="left">이벤트</th>
<th align="center">동작</th>
</tr>
</thead>
<tbody><tr>
<td>a태그</td>
<td align="left">click</td>
<td align="center">링크이동</td>
</tr>
<tr>
<td>form 태그</td>
<td align="left">submit</td>
<td align="center">서버로 form 전송</td>
</tr>
<tr>
<td>input type=&#39;checkbox&#39;</td>
<td align="left">change, click</td>
<td align="center">체크/언체크</td>
</tr>
<tr>
<td>input type=&#39;text&#39;</td>
<td align="left">input, change, focus, keydown, keyup, click 등</td>
<td align="center">텍스트 입력, 커서 깜빡임</td>
</tr>
<tr>
<td>button type=&quot;submit&quot;</td>
<td align="left">click</td>
<td align="center">폼전송</td>
</tr>
<tr>
<td>드래그 동작</td>
<td align="left">mousedown, mousemove, mouseup, selectstart</td>
<td align="center">텍스트 선택</td>
</tr>
</tbody></table>
<br/>

<h3 id="2-합성이벤트-synthetic-event">2. 합성이벤트 (Synthetic Event)</h3>
<ul>
<li>Synthetic Event는 React가 브라우저의 일관성과 메모리 향상(절약)을 위해서 만든 이벤트 시스템입니다. <blockquote>
<p>1) 실제로 React는 기본 이벤트를 랩핑해서 이를 일관된 형태의 구조로 제공합니다. 그래서 event 타입을 찍어보면, &#39;SyntheticEvent&#39;라고 보입니다. 
2) React는 이벤트 등록을 document에 딱 1번만 등록하여 이벤트 위임하는 형태로 이벤트를 처리 하기 때문에 메모리 부분에서 좋다고 볼 수 있습니다. </p>
</blockquote>
</li>
</ul>
<h3 id="3-event-pooling">3. Event Pooling</h3>
<blockquote>
<p>&quot; 이벤트 객체(SyntheticEvent)를 재사용하는 기법 &quot;</p>
</blockquote>
<h4 id="이렇게-된다면-발생할-수-있는-문제점">이렇게 된다면.. 발생할 수 있는 문제점?</h4>
<p>이벤트 핸들러 안에서 비동기 코드나 setTimeout, Promise.then 등에서
SyntheticEvent 객체를 사용하려고 하면 ❗이미 초기화돼서 접근이 안됨.</p>
<pre><code>function App() {
  const handleClick = (e) =&gt; {
    setTimeout(() =&gt; {
      console.log(e.type); // ❌ 여기서 오류가 날 수 있음! e는 이미 null 처리됨
    }, 100);
  };

  return &lt;button onClick={handleClick}&gt;Click me&lt;/button&gt;;
}</code></pre><p>이와 같이 하는 이유는 이벤트가 발생할때마다 새로운 이벤트를 생성하는데 이벤트가 메모리를 많이 잡아 먹음. 그래서 SyntheticEvent 초기화해서 다시 계속 재사용하는 방향으로 메모리 효율을 향상시킵니다. 하지만, <strong>React 17부터는 event pooling 방식을 사용하지 않습니다.</strong> </p>
<h3 id="4-최신-지식-습득하기-react-19">4. 최신 지식 습득하기 (React 19+)</h3>
<ul>
<li><p>이벤트 핸들러의 경우에는 컴포넌트가 다시 렌더링 될때마다 새로 만들어진다. 또 비동기 함수를 사용하면 stale closure문제를 만들 수 있다. </p>
</li>
<li><p>그래서 컴포넌트내에서 간단하게 이벤트를 처리하는게 아니라면, useCallback으로 감싸서 stale 클로져 문제가 발생하지 않도록 하는 것이 좋다. </p>
</li>
<li><p>예전에는 useCallback 대신 useEvent로 해서 항상 최신상태의 event 정보를 가져오는 hook이 제공될거라고 했는데, 현재 React 19 공식문서에는 없다. </p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[React 렌더링 - visibility, display, opacity 그리고 조건부 렌더링]]></title>
            <link>https://velog.io/@min_99/React-%EB%A0%8C%EB%8D%94%EB%A7%81-visibility-display-opacity-%EA%B7%B8%EB%A6%AC%EA%B3%A0-%EC%A1%B0%EA%B1%B4%EB%B6%80-%EB%A0%8C%EB%8D%94%EB%A7%81</link>
            <guid>https://velog.io/@min_99/React-%EB%A0%8C%EB%8D%94%EB%A7%81-visibility-display-opacity-%EA%B7%B8%EB%A6%AC%EA%B3%A0-%EC%A1%B0%EA%B1%B4%EB%B6%80-%EB%A0%8C%EB%8D%94%EB%A7%81</guid>
            <pubDate>Thu, 16 May 2024 22:36:38 GMT</pubDate>
            <description><![CDATA[<h3 id="1-visibility-hidden--opacity--0">1. visibility: hidden &amp;&amp; opacity : 0</h3>
<ul>
<li>visibility: hidden과 opacity : 0은 모두 해당 요소가 화면에 렌더링되지만 투명하게 보이게끔 만들어준다. 하지만, 둘다 여전히 자리를 차지한다. </li>
<li><em>둘의 차이점이라면 visibility:hidden은 뒤에 있는 요소를 클릭할 수 있지만, opacity: 0은 불가능하다는 것.*</em></li>
</ul>
<br/>

<h3 id="2-displaynone">2. display:none</h3>
<p>2) display: none은 해당 요소를 DOM 트리까지만 가져오고 렌더트리에서는 제외해준다. 즉, 레이아웃에 포함되지 않는다. 그래서 해당 요소가 자리조차 차지하지 않게 된다.
하지만, DOM 트리까지 해당 요소를 가져가야 하기 때문에, 해당 요소, 예를 들면 컴포넌트를 생성하기 위해 필요한 계산 과정은 전부 거쳐야 한다. 
*<em>즉, 리렌더링에 따른 자원소모는 피하지 못하는 방법이라는 뜻이다. *</em></p>
<br/>

<h3 id="3-결론">3. 결론</h3>
<blockquote>
<p>=&gt; 그래서 사실 최적화 측면에서 가장 적합한 방법은 조건부 렌더링이다. 
조건부 렌더링을 사용하명 condition에 해당하지 않을때는 아예 렌더링을 하지 않기 때문에 해당 컴포넌트를 생성하는 계산자체가 필요없게 된다. </p>
</blockquote>
<h3 id="4-추가-설명">4. 추가 설명</h3>
<ul>
<li>렌더 트리란, CSSOM과 DOM이 결합된 것을 말한다. 이 렌더 트리는 표시되는 각 요소의 레이아웃을 계산하는데 사용되고 픽셀을 화면에 렌더링하는 페인트 프로세스에 대한 입력으로 작동합니다. 최적의 렌더링 성능을 얻기 위해서는 이러한 각 단계를 최적화하는 것이 중요하다. </li>
<li>렌더트리는 페이지를 렌더링하는데 필요한 노드만 포함합니다. </li>
<li><strong>단, display:none은 렌더트리에 포함되지 않는다. (visibility는 빈상자로 렌더링됨)</strong></li>
<li>렌더트리가 준비되면 &#39;레이아웃&#39; 단계를 진행할 수 있다. </li>
</ul>
<br/>

<hr>
<p>[참고자료]</p>
<p><a href="https://iborymagic.tistory.com/116">https://iborymagic.tistory.com/116</a>
<a href="https://web.dev/articles/critical-rendering-path/render-tree-construction?hl=ko">https://web.dev/articles/critical-rendering-path/render-tree-construction?hl=ko</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[HTTP 요청 헤더 - if-match, if-modified-since, if-none-match]]></title>
            <link>https://velog.io/@min_99/HTTP-%EC%9A%94%EC%B2%AD-%ED%97%A4%EB%8D%94-if-match-if-modified-since-if-none-match</link>
            <guid>https://velog.io/@min_99/HTTP-%EC%9A%94%EC%B2%AD-%ED%97%A4%EB%8D%94-if-match-if-modified-since-if-none-match</guid>
            <pubDate>Thu, 16 May 2024 22:32:08 GMT</pubDate>
            <description><![CDATA[<h3 id="1-if-match">1. If-Match</h3>
<ul>
<li>if-match 헤더를 이해하기 위해서 &quot;ETag 해더&quot;를 먼저 이해하는 것이 좋다. </li>
</ul>
<h3 id="2-etag-해더란">2. ETag 해더란?</h3>
<ul>
<li>ETag 해더는 웹서버가 제공하는 컨텐츠들에 각각 부여되는 일종의 식별자 같은 정보이다. (ETag 정보를 표기한다)</li>
<li>사람에게 지문 또는 주민 등록 번호와 같이 개개인을 구별할 수 있는 정보가 있는 것 같이 ETage도 그런것이다. </li>
<li>웹서버는 클라이언트에서 컨텐츠를 제공할때 ETag 정보도 같이 전달한다. 클라이언트와 프록시서버들은 이 정보를 다음요청(subsequent request)에 사용한다.</li>
</ul>
<blockquote>
<p>사용예시)</p>
</blockquote>
<p>1) PUT URI IF-Match : AABB : &quot;If-Match: AABB&quot;라는 헤더를 포함한 PUT(변경) 요청을 보낸다.
2) 서버는 200 OK, Etag는 CCDD 라고 응답해준다. 
3) 다른 클라이언트가 이 사실을 모르고, PUT URI IF-Match : AABB라고 요청을 보냈다. 
4) 서버는 ETag AABB가 존재하지 않는다고 412 Precondition(전제조건) Failed를 응답한다.</p>
<p>추가적으로, If-Match에 *를 사용하면, 서버가 가지고 있는 ETag 정보와 상관없이 요청을 처리한다.(조금더 정확하게는 컨텐츠의 내용은 모르겠고, 파일이 존재하기만 한다면 요청을 처리해줘라는 뜻이다)</p>
<h3 id="3-if-modified-since">3. If-Modified-Since</h3>
<ul>
<li>If-Modified-Since 해더를 이해하기 위해서는 Last-Modifined 헤더의 의미를 먼저 알아야 한다.  Last-Modifined 헤더는 컨텐츠가 마지막으로 수정된 시간을 나타낸다.</li>
</ul>
<blockquote>
<p>[최초 요청 예시]</p>
</blockquote>
<p>1) GET URL 프록시 서버에 요청
2) origin 서버에 GET URL 요청
3) origin 서버는 200 OK, Last-Modified: Fri, 31 Jul 2017 07:00:00 GMT 라고 응답한다.
4) 프록시 서버는 자신의 디스크나 RAM에 저장한 후 클라이언트에게 응답한다.</p>
<blockquote>
<p>[두번째 요청 예시]</p>
</blockquote>
<p>1) GET URL 프록시 서버에 요청
2) 프록시 서버는 origin 에게 GET URL 요청 if-modified-since: Fri, 31 Jul 2017 07:00:00 GMT라고 요청한다.
3) origin 서버는 동일한 컨텐츠임을 확인하고 변경된 바가 없으니 직접 제공하라는 메시지인 304 Not Modified를 응답한다.
4) 프록시 서버는 자신의 디스크나 RAM에 저장한 후 클라이언트에게 응답한다.</p>
<ul>
<li>If-Modified-Since 헤더는 캐시동작에 있어서 유효한 컨텐츠를 클라이언트에게 제공할 수 있게 해주는 중요한 정보이다. </li>
</ul>
<p>만약, If-Modified-Since 정보에 오류가 있는 경우에는 어떻게 될까? 잘못된 경우라면 형식이 잘못되었다던지, 서버의 현재시간보다 더 늦은 경우라던지, 이런 경우에 웹서버는 If-Modified-Since 정보를 무시하고 , 컨텐츠 전체를 서비스하게 된다. </p>
<h3 id="4-if-none-match">4. IF-None-Match</h3>
<ul>
<li>If-Match 헤더와 반대의 의미라고 이해하면 된다. </li>
<li>결국, IF-Match, IF-None-Match 헤더는 서버가 제공하는 컨텐츠의 변경 여부를 확인하기 위해서 사용되는 해더이다. <ul>
<li>IF-Match : 컨텐츠가 변경되지 않고 같다면...</li>
<li>IF-None-Match : 컨텐츠가 변경되었다면...</li>
</ul>
</li>
<li>if-match는 200또는 412 전제조건이 잘못되었다는 응답을 리턴한다. </li>
<li>if-none-matc는 200 또는 304 Not Modified를 리턴한다.</li>
</ul>
<p><br/><br/></p>
<hr>
<p>[참고자료]
<a href="https://withbundo.blogspot.com/2017/07/http-13-http-iii-if-match-if-modified.html">https://withbundo.blogspot.com/2017/07/http-13-http-iii-if-match-if-modified.html</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[캐싱]]></title>
            <link>https://velog.io/@min_99/%EC%BA%90%EC%8B%B1</link>
            <guid>https://velog.io/@min_99/%EC%BA%90%EC%8B%B1</guid>
            <pubDate>Thu, 16 May 2024 22:29:08 GMT</pubDate>
            <description><![CDATA[<h3 id="1-캐싱이란">1. 캐싱이란?</h3>
<ul>
<li>어떤 데이터를 한 번 받아온 후에 그 데이터를 불러온 저장소보다 가까운 곳에 임시로 저장하여, 필요시 더 빠르게 불러와서 사용하는 프로세스를 의미한다. </li>
<li>엔지니어 입장에서는 재사용을 충분히 많이 할 수 있는 데이터만 선별적으로 캐싱하여, 성능과 비용을 아끼는 것이 중요하다. </li>
</ul>
<br/>

<h3 id="2-브라우저-캐시http-캐시-웹-캐시란">2. 브라우저 캐시(HTTP 캐시, 웹 캐시)란?</h3>
<ul>
<li>브라우저나 HTTP요청을 하는 클라이언트 애플리케이션의 의해 내부 디스크에 이루어지는 캐시이며, HTTP 캐시라고도 불린다. </li>
<li>이러한 캐시는 단일 사용자를 대상으로 하는 사설 캐시(Private Cache)이며, 해당 사용자의 정보만을 저장한다. </li>
<li>브라우저에서 캐싱을 처리하는 속성에는 대포적으로 ETag, Cache-Conrol이 있다. </li>
</ul>
<h3 id="3-cache-control">3. Cache-Control</h3>
<ul>
<li>Cache-Control은 HTTP/1.1의 헤더로, 캐시에 대한 동작을 지정한다.</li>
<li>캐시의 유효 시간(생명주기)와 관련된 내용을 명시하는 헤더이다. </li>
</ul>
<h4 id="1-no-cache">1) no-Cache</h4>
<ul>
<li>request 해더 : 캐싱된 응답값을 받지 않고, 원 서버로부터 응답을 받겠다. </li>
<li>response 해더 : 캐싱된 데이터를 항상 유효한지 확인하도록 하겠다. 캐싱을 하긴 하지만, 원본 서버에는 항상 갔다 오겠다(실제로 아무 캐시를 지정하지 않으려면 no-store로 설정해주어야 한다)</li>
</ul>
<h4 id="2-no-store">2) no-Store</h4>
<ul>
<li>request, response 모두 동일하게 캐시를 사용하지 않겠다라는 의미로 사용한다. </li>
<li>no-store는 로컬에 저장하는 것 자체를 금지한다. </li>
<li>데이터에 민감한 정보가 포함되어 있어 저장 불가 하도록 처리할때 사용한다. </li>
</ul>
<h4 id="3-max-age">3) max-age</h4>
<ul>
<li>캐시 유효시간, 초 단위 설정</li>
<li>Max-age=60 : 60초 동안 캐시를 유지하겠다는 의미이다.</li>
<li>다만, Max-age 60초가 지났다고 해서 해당 리소스에 대한 캐시를 완전히 버리지 않는다. 서버에 한번 물어보고(조건부 요청), 리소스 변경이 없다면 해당 캐싱된 리소스를 그대로 사용한다. </li>
<li>흔히, 캐싱되지 않아야 하는 민감한 리소스에 대해서는 max-age=0을 사용한다.</li>
</ul>
<h4 id="4-age">4) age</h4>
<ul>
<li>Origin server의 응답이 프록시 캐시 서버에 머문 시간, 초 단위(sec)</li>
</ul>
<h4 id="5-expire">5) expire</h4>
<ul>
<li>max-age는 유효시간을 초단위로 설정하였지만, expire는 만료일자를 지정한다. </li>
<li>cache-control 해더에도 Max-age로 유효시간을 명시하는 것이 더 추천되기 때문에, 현재는 사용이 권장되지 않고 하위호한을 위해 사용한다. <ul>
<li>만약, max-age와 동시에 사용되면 expire는 무시된다. </li>
</ul>
</li>
</ul>
<h4 id="6-public">6) public</h4>
<ul>
<li>응답 헤더에 사용할 수 있다. </li>
<li>모든 캐시 서버에 캐시 될 수 있고 사용자 제한 없이 모든 사용자에게 응답이 전달 될 수 있다. </li>
</ul>
<h4 id="7-private">7) private</h4>
<ul>
<li>public 캐시에 저장불가</li>
<li>최종 사용자 개인의 브라우저 환경에서만 캐싱하고, 외부 캐시 서버(CDN등의 범용캐시 서버)에서는 캐싱할 수 없다. 
ex) 로그인을 해서 내정보가 들어있는 페이지 접근지, 내 브라우저가 아닌 만약 다른 외부서버에까지 내정보가 캐싱되는 경우를 방지해준다. 응답 메시지를 어디에 캐시할 것인지를 지정하지 위해서 사용할 뿐, 그 자체로 개인정보를 보호하는 장치가 되지는 않는다. </li>
</ul>
<h4 id="8-s-maxage">8) s-maxage</h4>
<ul>
<li>공유 캐시에 해당하는 캐시에만 적용되는 수명이며, 개인 캐시에서는 무시된디ㅏ. </li>
<li>헤더의 age필드와 비교해서 캐시의 유효성을 판단한다. </li>
</ul>
<h4 id="9-must-revalidate-proxy-revalidate">9) must-revalidate, proxy-revalidate</h4>
<ul>
<li>must-revalidate : 캐시 만료 후 최초 조회 시 origin server에 검증</li>
<li>proxy-revalidate : 위의 내용을 공유(public)캐시에만 적용한다. </li>
</ul>
<h4 id="10-etag">10) ETag</h4>
<ul>
<li>HTTP 응답 해더로 리소스의 특정버전에 대한 식별자라고 하며, 원본 서버가 리소스를 식별하기 위해 부여하는 고유번호이다. </li>
<li>ETag는 캐시 유효성 검사를 위해 사용되며, 캐시된 리소스가 원본 리소스와 일치하는지 확인하는데 사용된다.    </li>
</ul>
<h4 id="11-pragma">11) Pragma</h4>
<ul>
<li>HTTP/1.0 하위 호환성을 위해 사용되는 헤더로, 캐시 제어를 위해 사용된다.</li>
<li>권장하지 않는다.</li>
</ul>
<br/>

<h3 id="4-크롬-브라우저를-기준으로-웹-브라우저는-크게-2가지-방법으로-캐싱을-한다-브라우저-자체-알고리즘에-따름">4. 크롬 브라우저를 기준으로 웹 브라우저는 크게 2가지 방법으로 캐싱을 한다. (브라우저 자체 알고리즘에 따름)</h3>
<p>1) 메모리캐시 : RAM에 데이터를 저장해놓는 방식
2) 디스크 캐시 : 하드 디스크에 파일로 저장해놓고 파일을 읽어서 저장하는 방식</p>
<ul>
<li>디스크 캐시보다는 메모리 캐시가 더 빠르다. 
디스크 캐시는 하드디스크에 접근하는 시간을 개선하기 위해 RAM에서 가져오며,
메모리 캐시는 더 빨리 가져오기 위해 RAM에 접근하지 않고, CPU 칩안에 있는 (L1, L2, L3) 캐시 메모리에 저장한다.</li>
</ul>
<p><strong>캐시의 유효기간의 지난 후 재접속하는 경우에는 status가 200이 아니라 304(Not Modified)로 응답한다.</strong></p>
<br/>

<h3 id="5-캐시-무효화에-대한-전략">5. 캐시 무효화에 대한 전략</h3>
<h4 id="방법1-cache-control-no-cache-cache-control-max-age0-0초-동안-캐시">방법1) cache-control: no-cache, Cache-Control: max-age=0 (0초 동안 캐시)</h4>
<ul>
<li>no-cache 옵션을 사용했다고 해서, 캐시가 사용되지 않는 것이 아니다!!!</li>
<li>캐시해도 되지만, 항상 origin server검증하고 사용해야한다. </li>
<li>서버로 부터 304 응답을 받으면 캐시를 사용한다. </li>
</ul>
<h4 id="방법2-cache-control-no-store">방법2) cache-control: no-store</h4>
<ul>
<li>no-store는 캐시를 사용하지 않겠다는 의미이다.</li>
<li>no-cache, max-age보다 엄격하게 캐시를 완전히 비활성화 한다. </li>
</ul>
<h4 id="방법3-cache-control-must-revalidate">방법3) cache-control: must-revalidate</h4>
<ul>
<li>캐시 만료 전에는 캐시를 사용하며, 캐시가 만료된 후에는 원서버에 검증을 요청한다. </li>
</ul>
<h4 id="방법4-pragmano-cache">방법4) pragma:no-cache</h4>
<ul>
<li>해당 방법은 HTTP 1.0 하위호환을 위해 사용한다. </li>
</ul>
<p><br/><br/><br/><br/></p>
<hr>
<p>[참고자료]</p>
<ul>
<li><a href="https://goddaehee.tistory.com/325">https://goddaehee.tistory.com/325</a></li>
<li><a href="https://yozm.wishket.com/magazine/detail/2341/">https://yozm.wishket.com/magazine/detail/2341/</a></li>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control">https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[뚜까뚜까 chromatic 도입기]]></title>
            <link>https://velog.io/@min_99/%EB%9A%9C%EA%B9%8C%EB%9A%9C%EA%B9%8C-chromatic-%EB%8F%84%EC%9E%85%EA%B8%B0</link>
            <guid>https://velog.io/@min_99/%EB%9A%9C%EA%B9%8C%EB%9A%9C%EA%B9%8C-chromatic-%EB%8F%84%EC%9E%85%EA%B8%B0</guid>
            <pubDate>Sun, 14 Apr 2024 10:30:33 GMT</pubDate>
            <description><![CDATA[<h3 id="1-내가-해결하고자-했던-문제들">1. 내가 해결하고자 했던 문제들..</h3>
<ol>
<li>서비스 안전성</li>
</ol>
<ul>
<li>우리는 현재 리소스가 부족하여 검수를 할 수 있는 상황이 아니였다. 하지만 1주 단위의 빠른 배포가 필요했다.  안전성을 확보하고자 테스팅툴을 알아보고 있었다.</li>
</ul>
<ol start="2">
<li>디자인 시스템 의사결정 퀄리티 향상</li>
</ol>
<ul>
<li>AS-IS는 디자이너 한명이 의사결정을 하는 구조로 이루어졌다. 나는 디자인 시스템에 참여하는 진입장벽을 낮추고 의사결정의 퀄리티를 높이고 싶었다.</li>
</ul>
<ol start="3">
<li>공유에 대한 누락사항 및 의사전달 비용 절감</li>
</ol>
<ul>
<li>현재는 글로만, 어떻게 변경되었는지를 전달하고 있다. 하지만, chromatic을 이용하면 시각적으로 어떤 부분이 달라졌는지를 정확하게 전달 할 수 있었다. (무려 픽셀이 어떻게 달려졌는지까지도..)</li>
</ul>
<h3 id="2-chromatic-시작하기">2. chromatic 시작하기</h3>
<p>  1) <a href="https://www.chromatic.com/">https://www.chromatic.com/</a> 계정을 생성하세요
  <img src="https://velog.velcdn.com/images/min_99/post/146b6e4b-5c8f-4137-bb43-136afeb929f4/image.png" alt="chromatic"></p>
<p>2) git을 연동하세요
3) 프로젝트에 chromatic을 설치하세요
4) chromatic 명령어를 실행하세요</p>
<h3 id="3-우리팀은-chromatic-도입-적응기를-다음과-같이-가졌어요">3. 우리팀은 chromatic 도입 적응기를 다음과 같이 가졌어요</h3>
<p>1) chromatic에 대해서 도입 방향에 대해서 팀내에서 발표 및 회의를 진행했어요
2) 그리고 약 1달의 도입 기간을 갖기고 하여 디자인 검수를 chromatic으로 진행하였습니다
3) 하지만 적용 당시에 어려움이 생겼습니다</p>
<h3 id="4-chromatic-적용의-어려움디자인팀-vs-개발팀fe">4. chromatic 적용의 어려움(디자인팀 VS 개발팀(FE))</h3>
<p>(1) chromatic으로 테스트를 진행하려면, 컴포넌트를 테스트할 수 있는 story가 구현되어 있어야 했는데, story가 기존에 등록되어 있지 않아 변경사항이 모두 &#39;new&#39;로 잡혀 변경된 부분만 잡아내지 못하는 상황 =&gt; chromatic에 대한 story 작업을 push하고 컴포넌트 변경사항을 분리해서 chromatic에 변경사항에 변경사항만 잡히도록 브랜치를 관리 할 것.</p>
<p>  (2) 디자이너가 생각하는 story와 개발자가 말하는 story가 다름. 
    =&gt; 디자이너가 생각하는 story는 figma에 정의된 케이스만 작성되어야 함. 개발자가 생각하는 story는 &quot;테스트 케이스&quot; 테스트 케이스는 디자인에서 정의해준 외의 것들을 필요에 의해서 테스트를 생성할 수 있음. &quot;외의 것들&quot;에 대해서 디자이너나 다른 기획자들이 보고 혼동할 수 있기 때문에 개발자의 테스트 케이스와 디자이너가 정의해준 예시를 구분해서 작성할 것.</p>
<p>  (3) 디자이너는 결국 stroybook에서 개발자도구를 이용해 검수를 진행 함. chromatic에서 어떻게 검수해야 되는지 1개월의 도입기를 거쳤지만, 불편하고 디자인 업무의 프로세스와는 맞지 않다고 생각하심. 
=&gt; chromatic은 마치 개발자 입장에서 PR을 날리는 구조로 되어 있음, 개발자 입장에서 PR은 이미 존재하는 개념이고, 프로세스 상의 이질감이 크게 없음, 하지만 디자인의 입장에서 storybook에서 검수를 진행하고, jira에 댓글만 달면 끝나는 일인데, chromatic의 새로운 툴이 또 도입되어 chromatic도 봐야하고, storybook도 봐야하고, jira도 봐야 하는 이슈가 발생함</p>
<h3 id="5-그렇다고-chroamtic이-갖는-장점이-있는데-버릴만-한가">5. 그렇다고, chroamtic이 갖는 장점이 있는데 버릴만 한가?</h3>
<p>1) 안전성..
2) 공유방법 개선..
3) 히스토리 관리..
4) 디자인 시스템 규모 확장 가능성..</p>
<h3 id="6-그래서-우리팀은-이렇게-결론-내렸어요">6. 그래서 우리팀은 이렇게 결론 내렸어요</h3>
<p>결론은 디자인팀은 &quot;chromatic 도입 반대&quot; 입니다. 
하지만, 장점이 많으니 개발팀에서 내부적으로는 사용해도 좋다 였습니다.</p>
<p>하지만.. 돌릴 때 마다 발생하는 비용지원에 말씀은 없으셨다. </p>
<p>결국 chromatic도입은 이렇게 흐지부지 되어 버렸다.</p>
<h3 id="7-그-후-나의-도전기">7. 그 후 나의 도전기</h3>
<ul>
<li>비용이 너무 비싸서 시각적 회귀테스트를 간단하게 직접 구현해보았습니다. </li>
<li>라이브러리는 Puppeteer를 사용했고, 목표는 총 3가지로 하였습니다. 
1) figma하고 비교해서 차이가 있는지 =&gt; 단순 페이지 비교
2) 이전 버전하고 비교해서 차이가 있는지 =&gt; 단순 페이지 비교
3) 액션을 통한 화면 비교(button 클릭 후 결과페이지 비교)</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[나만의 보일러 플레이트 만들어보기(feat.React)]]></title>
            <link>https://velog.io/@min_99/%EB%82%98%EB%A7%8C%EC%9D%98-%EB%B3%B4%EC%9D%BC%EB%9F%AC-%ED%94%8C%EB%A0%88%EC%9D%B4%ED%8A%B8-%EB%A7%8C%EB%93%A4%EC%96%B4%EB%B3%B4%EA%B8%B0feat.React</link>
            <guid>https://velog.io/@min_99/%EB%82%98%EB%A7%8C%EC%9D%98-%EB%B3%B4%EC%9D%BC%EB%9F%AC-%ED%94%8C%EB%A0%88%EC%9D%B4%ED%8A%B8-%EB%A7%8C%EB%93%A4%EC%96%B4%EB%B3%B4%EA%B8%B0feat.React</guid>
            <pubDate>Thu, 11 Apr 2024 12:45:55 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p> 작성중인 페이지 입니다 :) </p>
</blockquote>
<blockquote>
<p>GitHub : <a href="https://github.com/min-99/react-boilerplate">https://github.com/min-99/react-boilerplate</a></p>
</blockquote>
<h3 id="1-node를-설치하세요">1. Node를 설치하세요</h3>
<ul>
<li>React는 Node.js기반입니다. Nodes.js가 없으면 React가 실행될 수 없어요.</li>
<li><a href="https://nodejs.org/en">https://nodejs.org/en</a> 홈페이지에 접속하여 LTS버전을 설치해주세요.</li>
</ul>
<pre><code>node --version // v20.11.1 - 버전이 뜨면 설치 성공</code></pre><h3 id="2-yarn-berry-설치하기">2. yarn berry 설치하기</h3>
<ul>
<li>필수는 아니지만 npm보다 yarn의 속도가 빠르기 때문에 깔아주는 것이 좋습니다</li>
<li>mac은 home brew설치 후 다운로드 진행<ul>
<li>hone brew : <a href="https://brew.sh/">https://brew.sh/</a></li>
<li>yarn : <a href="https://classic.yarnpkg.com/en/docs/install/#mac-stable">https://classic.yarnpkg.com/en/docs/install/#mac-stable</a></li>
</ul>
</li>
</ul>
<pre><code>yarn --version // - 버전이 뜨면 설치 성공</code></pre><pre><code>brew upgrade yarn // 업데이트 </code></pre><ul>
<li>yarn berry : <a href="https://velog.io/@min_99/%ED%8C%A8%ED%82%A4%EC%A7%80-%EB%A7%A4%EB%8B%88%EC%A0%B8-%EC%A0%95%EB%A6%AC-2%ED%8E%B8yarn-berry">https://velog.io/@min_99/%ED%8C%A8%ED%82%A4%EC%A7%80-%EB%A7%A4%EB%8B%88%EC%A0%B8-%EC%A0%95%EB%A6%AC-2%ED%8E%B8yarn-berry</a></li>
</ul>
<h3 id="3-리액트-프로젝트-생성--typescript-적용">3. 리액트 프로젝트 생성 + typescript 적용</h3>
<p>1) 작업을 진행할 폴더로 이동하세요</p>
<pre><code>cd {작업을 진행할 폴더}</code></pre><p>2) 프로젝트 생성</p>
<pre><code> npx create-react-app {프로젝트 이름} --template typescript</code></pre><p>3) tsconfig 파일 세팅</p>
<pre><code>// tsconfig.ts 파일
&quot;compilerOptions&quot;: {
  &quot;target&quot;: &quot;ES6&quot;, // es6로 변환되도록 설정
    ...
}</code></pre><p>4) 프로젝트 실행시켜보기</p>
<pre><code>yarn start</code></pre><h3 id="4-eslint-적용하기">4. ESLint 적용하기</h3>
<ul>
<li>보푸라기, 먼지 같은 것을 린트(Lint)라고 부른는데 이런 것들을 제거하는 기능
<img src="https://velog.velcdn.com/images/min_99/post/349554d1-38dd-4344-9e0c-8d94b70c23c9/image.png" alt=""></li>
<li>create react app으로 만든 프로젝트에는 이미 eslint 기능이 내장 되어 있습니다. 더 편리하게 사용하기 위해서 ESLint 확장팩을 사용하세요.</li>
</ul>
<p>1) ESLint 확장팩을 설치하세요 (<a href="https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint">https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint</a>)</p>
<p>2) 저장할때 자동으로 수정되는 모드를 사용하세요(in VSCode)
code &gt; preferences &gt; settings 로가서 환경설정 화면으로 간 다음
auto fix on save 검색 후 on 설정</p>
<h3 id="5-prettier-적용하기">5. Prettier 적용하기</h3>
<ul>
<li>코드 포맷팅에 좀 더 초점을 맞춘 기능</li>
<li>ESLint의 역할 중 포맷팅과 겹피는 부분이 있지만, prettier는 좀 더 많고 일관적인 스타일로 코드를 다듬습니다.</li>
<li>eslint와 달리 코드 품질과 관련된 기능은 하지 않습니다.</li>
<li>eslint와 prettier를 둘다 사용하게 되면 충돌이 나게 되어 eslint 규칙을 끄는 것이 필요합니다. </li>
</ul>
<p><strong>How? 어떻게 꺼요?</strong></p>
<ul>
<li>ESLint와 통합 방법을 제공하는 eslint-config-prettier를 설치합니다. </li>
</ul>
<pre><code>yarn add eslint-config-prettier</code></pre><p>// package.json
extends 부분에 prettier를 추가합니다.</p>
<pre><code>&quot;eslintConfig&quot;: {
    ...
    &quot;extends&quot;: [
      ...
      &quot;prettier&quot;
    ],
  },</code></pre><p>ESLint는 중복된 포매팅 규칙을 프리티어에게 맡기고 코드 품질에 관한 검사만 하게됩니다.</p>
<h3 id="6-styled-component-적용하기">6. Styled-component 적용하기</h3>
<ul>
<li>css in js 관련 라이브러리</li>
<li>즉, js파일에서 css를 작성하는 것입니다.</li>
<li>js 파일에서 css를 작성할 수 있고 이를 바로 컴포넌트화 시킬수도 있게됩니다.</li>
</ul>
<pre><code>yarn add styled-components
yarn add @types/styled-components</code></pre><p>// eslint, prettier 잘동작하는지, 충돌 안나는지 확인 할 것
// .husky도 적용할 것</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[왜 React인가요? (feat. 면접질문)]]></title>
            <link>https://velog.io/@min_99/%EC%99%9C-React%EC%9D%B8%EA%B0%80%EC%9A%94-feat.-%EB%A9%B4%EC%A0%91%EC%A7%88%EB%AC%B8</link>
            <guid>https://velog.io/@min_99/%EC%99%9C-React%EC%9D%B8%EA%B0%80%EC%9A%94-feat.-%EB%A9%B4%EC%A0%91%EC%A7%88%EB%AC%B8</guid>
            <pubDate>Thu, 11 Apr 2024 12:44:19 GMT</pubDate>
            <description><![CDATA[<p>안녕하세요
면접을 보면 항상 공통적으로 그때 당시에 &quot;왜 React로 가야 하는가?&quot;에 대해서 팀내 발표를 진행하셨다고 하셨는데 왜 React로 가야 하는지 발표를 하셨나요? 에 대한 저의 생각을 다시 차근차근 적어보려고 합니다.</p>
<h3 id="1-레거시-시스템에-대한-문제내가-해결하고-싶었던-문제">1. 레거시 시스템에 대한 문제(=내가 해결하고 싶었던 문제)</h3>
<p>제가 관리하는 서비스는 페이지 구성이 굉장히 복잡한 서비스 였습니다. </p>
<blockquote>
<p> 얼마나 복잡한데요? </p>
</blockquote>
<ul>
<li>admin에서 구성한 데이터로 UI를 구성하고, 구성한 UI를 클릭할때 마다 아래의 UI가 바뀌어야 하는 페이지 였습니다. 한마디로 데이터 의존성이 굉장히 높은 페이지 였습니다. </li>
</ul>
<p>또, 페이지를 제어하는 javascsript 로직은 모두 하나의 객체에 담겨 있었고,
무엇인가를 수정해야 한다면, 그 컴포넌트를 건드리고, 참조하는 로직이 사방곳곳에 정의되어 있어 배포시 사이드 이펙트가 자주 발생하였습니다. </p>
<p>javascript도 수정이 어려웠지만, css구조도 인라인 스타일, html 내부의 css, css파일에 있는 디자인 정의가 혼합되어 있었습니다. 또 서로 관계없는 컴포넌트인데 UI가 비슷하다는 이유로 같은 클래스를 공유하여 디자인 수정도 쉽지 않았습니다.</p>
<h3 id="2-그러면-왜-react인데요">2. 그러면 왜 React인데요?</h3>
<p>위의 문제를 해결하기 위해서는 React의 코드 스타일과 동작방식, 저희 서비스의 적합성 부분에서 React가 더 이득이라고 생각했습니다. </p>
<h4 id="1-react는-선언형-코드-스타일이기-때문에-가독성이-좋아집니다">1. React는 선언형 코드 스타일이기 때문에 가독성이 좋아집니다.</h4>
<p>  =&gt; 기존에는 들여쓰기와 닫는 태그도 정상적으로 되어 있지 않는 html을 분석해야 했다면, React의 컴포넌트 설계와 선언형 스타일로 코드 파악에 유리하다고 생각합니다. </p>
<h4 id="2-컴포넌트를-재사용할-수-있습니다">2. 컴포넌트를 재사용할 수 있습니다.</h4>
<p>   =&gt; 그때 당시 같은 컴포넌트가 많았는데 이를 컴포넌트화 하고 싶었습니다.</p>
<h4 id="3-dom을-직접건드려야-하는-일이-줄어-듭니다">3. DOM을 직접건드려야 하는 일이 줄어 듭니다.</h4>
<p>   =&gt; 기존에는 직접 dom에 접근하여 변경해야 됬고, 이 로직이 사방 곳곳에 있었다면 이제는 데이터의 변경하는 곳을 한곳으로 정리할 수 있고, 변경하는 곳은 액션의 네이밍으로 쉽게 찾을 수 있습니다. </p>
<br/>

<h3 id="react외의-추가적인-리펙토링-방향-및-추천사항"><strong>[React외의 추가적인 리펙토링 방향 및 추천사항]</strong></h3>
<h4 id="4-typescript-사용">4. typescript 사용</h4>
<ul>
<li>javascript만 사용할 경우보다 타입을 강제하기 때문에, 타입때문에 발생하는 이슈사항들을 사전에 많이 잡을 수 있습니다. </li>
</ul>
<h4 id="5-css-작업방식-개선">5. css 작업방식 개선</h4>
<ul>
<li>styled-component 라이브러리를 사용하여 컴포넌트자체에 css를 같이 정의하는 방향으로 기존의 다양한 css 선언방식을 통일하고 클래스가 겹치는 등에 대한 이슈사항이 없습니다. </li>
</ul>
<h4 id="6-패키지-매니져-사용">6. 패키지 매니져 사용</h4>
<ul>
<li>기존에는 CDN방식으로 라이브러리를 가져다 사용하고 있었는데, 패키지 매니져를 사용함으로서 버전관리에 용이하고 안전성측면에서도 향상 됩니다. </li>
</ul>
<h4 id="7-테스트-용이">7. 테스트 용이</h4>
<ul>
<li>기존에는 php, css, javascript가 모두 섞여 있어서 TEST가 필요한 결제 페이지에서 테스트를 돌리기가 어려웠습니다. 결제부분에 서비스 핵심로직이 모두 다 있기때문에 안정성을 향상 시키려면 개선이 필요했습니다. </li>
</ul>
<h4 id="8-제가-서비스하는-모듈은-client-모듈에-가까웠습니다">8. 제가 서비스하는 모듈은 Client 모듈에 가까웠습니다.</h4>
<ul>
<li>php에 javascript로 구성되어 있었지만,javasciprt는 AJAX로 자기에게 요청을하고 php는 실제 API 서버로 API요청하고 데이터를 넘겨주는 역할만 하고 있었습니다. </li>
</ul>
<br/>

<p>그때 당시, 제가 담당하고 있는 모듈은 추가 기능 개발이 필요했고, 고객을 더 받기 위해서는 서비스 안전성과 성능 개선이 필요하였습니다. (<strong>lighthouse 기준으로 PC가 평균 40점, Mobile이 평균 20점 정도 되는 성능을 가지고 있었습니다</strong>) 조금 더 안정적으로 서비스를 개선하기 위해서는 해당 개선 작업이 필요하다고 느껴 담당자로서 왜 필요한지에 대해서 리더분에게 PPT 발표를 진행하였습니다</p>
<p>이후, TF팀을 결성하여 1차와 2차로 나눠 리팩토링 작업과 프로토타입 개발을 진행했습니다. <strong>그 결과, Lighthouse 기준으로 PC 평균 점수는 40점에서 88점으로 향상되어 48점 상승했으며, Mobile 평균 점수는 20점에서 78점으로 향상되어 58점 상승하는 개선 효과를 보였습니다.</strong> 또한, 제시된 개선 사항을 반영하여 최종적으로 모든 항목이 90점 이상으로 개선되었습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[span과 div 차이]]></title>
            <link>https://velog.io/@min_99/span%EA%B3%BC-div-%EC%B0%A8%EC%9D%B4</link>
            <guid>https://velog.io/@min_99/span%EA%B3%BC-div-%EC%B0%A8%EC%9D%B4</guid>
            <pubDate>Mon, 18 Mar 2024 03:41:22 GMT</pubDate>
            <description><![CDATA[<blockquote>
<ol>
<li>span과 div를 명확하게 설명할 수 있다. </li>
<li>inline과 inline-block 요소를 명확하게 설명할 수 있다. </li>
</ol>
</blockquote>
<h3 id="1-span과-div-차이">1. <code>&lt;span&gt;</code>과 <code>&lt;div&gt;</code> 차이</h3>
<ul>
<li>div 태그는 의믜적으로 관계가 없을 때 주로 사용한다. 오직 내용을 묶는 역할이라고 보면 된다. 하지만, span 태그와 비슷한 역할을 하는데 차이가 있다.</li>
</ul>
<h4 id="무슨-차이">무슨 차이?</h4>
<ul>
<li>div는 줄바꿈 되지만, span 태그는 옆으로 붙는다.</li>
<li>즉, <strong>div는 기본적으로 block요소, span은 inline 요소이다</strong>. </li>
<li>그렇기 때문에 텍스트를 표현할때 div는 사각형 박스 구역으로 공간을 차지하지만, span은 문장 단위로 지정한다. 
<img src="https://velog.velcdn.com/images/min_99/post/1026f105-0c3c-4669-96ba-de2e0a7642b4/image.png" alt=""></li>
<li>노란색 : div</li>
<li>민트색 : span</li>
</ul>
<br/>

<h3 id="2-inline과-inline-block-비슷한거-아닌가요">2. inline과 inline-block 비슷한거 아닌가요?</h3>
<ul>
<li>inline 요소는 대표적으로 <code>&lt;span&gt;</code></li>
<li>block 요소는 대표적으로 <code>&lt;div&gt;</code></li>
</ul>
<h4 id="1-inline">1) inline</h4>
<ul>
<li><p><strong>width, height <span style="color: red">적용불가</span></strong></p>
</li>
<li><p><strong>margin, padding-top, padding-bottom <span style="color: red">적용불가</span></strong></p>
</li>
<li><p>*<em>line-height는 원하는 대로 <span style="color: red">적용불가</span> *</em></p>
</li>
<li><p>요소 : span, a, br, em, strong, input, label, img</p>
<blockquote>
<p>** <code>&lt;span&gt;</code>태그는 text내에 특정 부분에만 스타일을 간단히 주고 싶을 때 주로 사용한다. **</p>
</blockquote>
</li>
</ul>
<h4 id="2-block">2) block</h4>
<ul>
<li>block은 무조건 한줄을 점유하고, 다음 태그는 다음줄로 넘어간다. </li>
<li><strong>verical-align 적용불가</strong></li>
<li><strong>text-align 적용불가</strong></li>
<li>요소 : div, table, h1 ~ h6, p, form, ul, li, ol, dl, dt, dd, pre, blockquote</li>
</ul>
<h4 id="3-inline-block">3) inline-block</h4>
<ul>
<li>inline + block이 섞인 형태, 같은 라인에 여러 태그를 붙일 때 주로 사용한다. </li>
<li>inline의 단점을 커버하는 것이 inline-block이라고도 볼 수 있다. </li>
<li><strong>width, height <span style="color: blue">적용가능</span></strong></li>
<li><strong>margin, padding-top, padding-bottom <span style="color: blue">적용가능</span></strong></li>
<li><strong>line-height는 원하는 대로 <span style="color: blue">적용가능</span></strong></li>
</ul>
<!-- #### 다만, 고려해야 될 부분이 있다. 
- inline-block 끼리 공백이 생기는데, 이때 상위 div에 font-size: 0으로 적용하면 해결된다. 
- inline-block끼리 높이가 안맞을시 상위 공백이 생기는데 이때는 vertical-align을 설정하여 해결할 수있다. -->
<hr>
<h4 id="span-stylecolor-blue코드를-짜면서-기억하면-좋은-점span"><span style="color: blue">코드를 짜면서 기억하면 좋은 점</span></h4>
<ul>
<li>블럭요소내부에는 블럭요소와 인라인 요소를 포함 할 수 있다.  </li>
<li>인라인 요소 내부에는 블럭요소를 포함 할 수 없다. 
=&gt; <strong>이는 보여지는데는 아무런 문제가 없지만, 유효성에 어긋난다</strong>. </li>
</ul>
<hr>
<p>코드리뷰를 하면서 span태그안에 블럭요소를 넣고, 위치를 지정하는 코드를 보면서 잘못되었다는 것은 알았는데 명확하게 설명할 수가 없어서 답답했다. 설명할 수 없다는 건 정확하게 모른다는 것! 너무 오래전에 배워서 정말 당연하다고 생각했던 것 같다. 정리를 기록하면서 이러한 부분들이 많이 매꿔지길 바란다👍🏻
<br/></p>
<p>[참고자료]
<a href="https://sdsupport.cafe24.com/reference/html/block-inline.html">https://sdsupport.cafe24.com/reference/html/block-inline.html</a>
<a href="https://mainia.tistory.com/3289">https://mainia.tistory.com/3289</a>
<a href="https://blog.naver.com/leesd88/220682157303">https://blog.naver.com/leesd88/220682157303</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[패키지 매니져 정리 - 2편(yarn berry)]]></title>
            <link>https://velog.io/@min_99/%ED%8C%A8%ED%82%A4%EC%A7%80-%EB%A7%A4%EB%8B%88%EC%A0%B8-%EC%A0%95%EB%A6%AC-2%ED%8E%B8yarn-berry</link>
            <guid>https://velog.io/@min_99/%ED%8C%A8%ED%82%A4%EC%A7%80-%EB%A7%A4%EB%8B%88%EC%A0%B8-%EC%A0%95%EB%A6%AC-2%ED%8E%B8yarn-berry</guid>
            <pubDate>Sat, 16 Mar 2024 07:47:34 GMT</pubDate>
            <description><![CDATA[<h3 id="1-yarn-berry">1. yarn berry?</h3>
<ul>
<li>yarn berry는 yarn v2이상을 부르는 명칭입니다. </li>
<li>이에 따라서 기존의 yarn v1은 yarn classic이라고 부르게 되었습니다. </li>
</ul>
<p><strong>[사용방법]</strong></p>
<pre><code>npm install -g yarn
yarn set version berry</code></pre><br/>

<h3 id="2-plugnplay">2. Plug&#39;n&#39;Play</h3>
<ul>
<li>기존의 무거웠던 node_modules를 생성하지 않고 패키지들에 대한 정보를 .zip파일로 관리 합니다.</li>
<li>패키지 의존성 정보를 .zip 파일로 압축하여 .yarn/cache 폴더에 저장하고 의존성을 찾을 수 있는 정보를 .pnp.cjs파일에 기록합니다. 
<img src="https://velog.velcdn.com/images/min_99/post/0e7b7534-40cb-4b0b-86a0-3c5fb7bd5045/image.png" alt=""></li>
<li>.pnp.cjs는 의존성 트리를 중첩된 맵으로 표현하지 때문에 디스크 I/O없이도 패키지가 어떤 라이브러리에 의존하는지, 어디에 위치하는지를 바로 알수 있습니다. </li>
<li>따라서, 패키지의 위치를 정확히 알 수 있기 때문에 <strong>시간도 단축</strong>되고, <strong>중복 설치도 방지</strong> 할 수 있습니다. </li>
</ul>
<h3 id="3-zero-install">3. Zero Install</h3>
<ul>
<li>yarn PnP는 의존성을 압축 파일로 관리하기 때문에 의존성의 용량이 작습니다. </li>
<li>예를 들어, 일반적인 node_modules는 1.2GB 크기이며 13만 5천개의 파일로 구성되어 있는 반편, yarn PnP의 의존성은 139MB크기의 2천개의 압축파일로 구성됩니다. </li>
<li>용량과 파일의 수가 적기 떄문에 의존성을 <strong>Git으로 관리 할 수 있습니다</strong>. </li>
<li>이처럼, yarn berry에서 <strong>의존성을 버전관리에 포함하는 것</strong>을 <strong>zero-install</strong>이라고 합니다 </li>
<li><strong>zero-install을 사용하면, git-clone 이후 별도의 설치 필요없이 바로 사용</strong>할 수 있습니다.<blockquote>
<p>[Zero Install 장점]</p>
</blockquote>
1) 새로 저장소를 복제하거나 브랜치를 바꾸었을 때 yarn install을 실행하지 않아도 됩니다. 
2) CI에서 의존성을 설치하는 시간을 크게 절약할 수 있습니다. 
3) 오프라인 캐시 기능으로 인터넷이 연결되지 않아도 패키지를 사용할 수 있습니다. </li>
</ul>
<br/>

<p>[참고자료]</p>
<p><a href="https://toss.tech/article/node-modules-and-yarn-berry">https://toss.tech/article/node-modules-and-yarn-berry</a>
<a href="https://usage.tistory.com/147">https://usage.tistory.com/147</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[패키지 매니져 정리 - 1편(npm vs yarn)]]></title>
            <link>https://velog.io/@min_99/%ED%8C%A8%ED%82%A4%EC%A7%80-%EA%B4%80%EB%A6%AC%EC%9E%90-%EC%A0%95%EB%A6%AC-1%ED%8E%B8npm-vs-yarn</link>
            <guid>https://velog.io/@min_99/%ED%8C%A8%ED%82%A4%EC%A7%80-%EA%B4%80%EB%A6%AC%EC%9E%90-%EC%A0%95%EB%A6%AC-1%ED%8E%B8npm-vs-yarn</guid>
            <pubDate>Sat, 16 Mar 2024 07:03:18 GMT</pubDate>
            <description><![CDATA[<blockquote>
<ol>
<li>자바스크립트 런타임 환경인 노드(Nodes.js)의 패키지 매니져에 대해서 알아보자.<ol start="2">
<li>대표적인 패키지 매니져 npm , yarn, yarn berry에 대해서 알수 있다.</li>
</ol>
</li>
</ol>
</blockquote>
<h3 id="1-npm이-뭔가요">1. npm이 뭔가요?</h3>
<ul>
<li><p>Node Package Manager로, Node의 기본 패키지 매니져 입니다.</p>
</li>
<li><p><strong>이러한 패키지 매니져가 없다면,</strong> 저희는 github에 접속해서 소스코드를 다운로드 받아야 합니다. 또 버전 변경시에 다시 접속해서 소스코드를 재 다운로드를 받아서 재 업로드 해줘야 됩니다..ㅎ </p>
</li>
<li><p>패키지 매니져의 탄생으로 관리의 문제가 개선되었지만, 완벽한 방법이란 없는 것.. 사용하다 보니 문제점이 발견이 되고, 이로 인해, npm , yarn, yarn berry,, 이렇게 발전을 하게됩니다</p>
</li>
</ul>
<br/>

<h3 id="npm-무엇이-문제였나">npm! 무엇이 문제였나?</h3>
<h4 id="1-😵-환경세팅하는-사람들마다-버전이-다-제각각이야-일관되지-않은-버전관리">1. 😵 환경세팅하는 사람들마다 버전이 다 제각각이야!! (일관되지 않은 버전관리)</h4>
<p>1) 시멘틱 버저닝</p>
<ul>
<li>노드 모듈들은 기본적으로 <code>시멘틱 버저닝</code> 이라는 기법을 사용하여 모듈의 버전을 나타냅니다. </li>
<li><code>시멘틱 버저닝</code> : 1.0.0처럼 세가지 숫자로 구분하고 각 자리에 현재 버전이 이전버전과 어떤 관계가 있는지 암시하는 방법입니다. </li>
</ul>
<p>2) 캐럿(^) 기호</p>
<ul>
<li>캐럿 기호를 이용해서 <strong>첫번째 숫자를 제외한 두자리(마이너,패치) 버전까지는 변경을 허용</strong></li>
</ul>
<p>3) 버전 불일치
따라서, <code>npm install</code> 명령어로 모듈을 설치하면 <strong>최신버전을 다운받게 됩니다.</strong></p>
<blockquote>
<p>버전 변경이 허용되기 떄문에 <code>모듈간의 버전이 일치하지 않는 문제</code>가 발생할 수 있다.</p>
</blockquote>
<h4 id="2-🥵-고정되지-않은-설치-순서">2. 🥵 고정되지 않은 설치 순서</h4>
<ul>
<li>개발자의 환경에 따라 모듈들의 설치 순서가 변경 될 수 있다. </li>
<li>이미 만들어진 프로젝트에서 모듈을 추가로 설치하게 될 경우 <code>npm install</code> 명령어를 통해 처음부터 설치하는 사람과의 설치순서가 달라질 수 있다. <blockquote>
<p>npm은 개발자들이 <strong>어떤 순서로 모듈을 추가했는지 알 수 없기 때문</strong>에 모듈 이름을 사전순서대로 정렬하여 순차적으로 설치한다.</p>
</blockquote>
</li>
</ul>
<h4 id="3-🤬-순차적인-설치로-인한-긴-소요시간너무-오래걸려">3. 🤬 순차적인 설치로 인한 긴 소요시간(너무 오래걸려!!)</h4>
<ul>
<li>npm은 모듈을 한번에 하나씩 순차적으로 설치합니다. 
=&gt; 설치해야 되는 모듈이 많을수록 총 설치 시간이 길어지게 됩니다.</li>
</ul>
<br/>

<h3 id="npm의-문제를-해결하여-yarn-출시">npm의 문제를 해결하여, yarn 출시!</h3>
<h4 id="1-버전문제를-해결하다">1. 버전문제를 해결하다</h4>
<ul>
<li>버전고정을 위해 yarn.lock 파일을 사용한다.</li>
<li>yarn.lock 파일로 개발자들의 <strong>항상 같은 버전의 모듈을 사용할 수 있도록 보장한다</strong></li>
</ul>
<p><strong>[npm도 버전문제에 대한 개선방향을 내놓다!]</strong></p>
<ul>
<li><code>npm shrinkwrap</code></li>
<li>하지만, npm의 경우 고정이 필요할 때마다 명령어를 입력해야 한다 </li>
<li>yarn의 경우, 의존성이 달라질때마다 <strong>lock파일을 자동으로 추가</strong>하기 때문에 편리합니다.</li>
</ul>
<h4 id="2-설치-확인을-위한-checksum">2. 설치 확인을 위한 checksum</h4>
<ul>
<li>yarn은 checksum을 이용하여 패키지가 제대로 설치 되었는지 확인 합니다. </li>
<li>yarn.lock 파일을 확인해보면 resolved 주소뒤에 해시값이 추가되어 있는데, 이 해쉬값이 바로 checksum 입니다. </li>
<li>checksum은 패키지 파일의 무결성(정보가 변형되거나 손상되지 않았다)을 확인하는 안전장치 역할을 합니다. </li>
</ul>
<h4 id="3-캐시를-통한-속도-개선">3. 캐시를 통한 속도 개선</h4>
<ul>
<li>yarn은 한번 다운로드한 패키지라면 캐시를 해두기 때문에 다음부터는 매우 빠른 속도로 설치 할 수 있다. </li>
<li>병렬 다운로드를 지원하기 때문에 모듈을 한번에 설치하여 속도가 빠르다.</li>
</ul>
<br/>

<h3 id="✋🏻잠깐">✋🏻잠깐!</h3>
<h4 id="npm-왈--나도-개선진행할께">npm 왈 : 나도, 개선진행할께!</h4>
<blockquote>
<p>시간이 지나고 npm도 많은 부분이 개선되었습니다. package-lock 파일을 통해서 버전을 고정하고, 속도면에서도 yarn과 큰 차이가 없는 수준까지 따라왔습니다. </p>
</blockquote>
<h4 id="하지만-두-패키지-매니저에도-문제가-존재했습니다">하지만, 두 패키지 매니저에도 문제가 존재했습니다.</h4>
<br/>

<h4 id="1-너무-무거운-node_modules">1. 너무 무거운 node_modules!!!</h4>
<p><img src="https://velog.velcdn.com/images/min_99/post/6d244737-439f-4ced-9389-88548307151e/image.png" alt=""></p>
<ul>
<li><p>npm에서 구성하는 node_modules폴더는 매우 큰 용량을 차지 합니다. </p>
</li>
<li><p>npm은 이 무거운 폴더를 경량화시키기 위해 <code>호이스팅</code>을 도입하였습니다. </p>
</li>
<li><p>용량을 줄이는 가장 간단한 방법은 중복을 제거하는 것입니다. </p>
</li>
<li><p>node_modules의 중복된 패키지를 최소화하기 위해 각 패키지가 의존하는 패키지들을 최상단으로 끌어올립니다. 이렇게 되면 <strong>중복된 패키지가 최상단에 하나만 존재</strong>하게 되어 불필요한 중복을 제거할 수 있게 됩니다. </p>
</li>
</ul>
<br/>

<h4 id="2-유령-의존성">2. 유령 의존성</h4>
<p><img src="https://velog.velcdn.com/images/min_99/post/df33aba5-85da-4916-bd6f-1c9743cc6816/image.png" alt=""></p>
<ul>
<li>하지만 이렇게 되면, 나는 <strong>설치한 적이 없지</strong>만 사용하는 패키지가 의존하고 있다는 이유만으로 <strong>사용하지 않는 패키지도 설치</strong>하게 됩니다. 이러한 현상을 <code>유령 의존성</code>이라고 부릅니다. </li>
<li>따라서 <code>비효율적인 설치와 유령 의존성</code> 등은 여전히 npm과 yarn에게 숙제로 남아 있었습니다. </li>
<li>하지만, yarn은 이러한 숙제를 해결한 v2를 공개(2020년 1월)했습니다</li>
</ul>
<br/>

<p>[참고자료]</p>
<ul>
<li><a href="https://toss.tech/article/node-modules-and-yarn-berry">https://toss.tech/article/node-modules-and-yarn-berry</a></li>
<li><a href="https://usage.tistory.com/147">https://usage.tistory.com/147</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[핵클(Hackle) - 시작하기(개발환경세팅)]]></title>
            <link>https://velog.io/@min_99/%ED%95%B5%ED%81%B4Hackle-%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0%EA%B0%9C%EB%B0%9C%ED%99%98%EA%B2%BD%EC%84%B8%ED%8C%85</link>
            <guid>https://velog.io/@min_99/%ED%95%B5%ED%81%B4Hackle-%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0%EA%B0%9C%EB%B0%9C%ED%99%98%EA%B2%BD%EC%84%B8%ED%8C%85</guid>
            <pubDate>Wed, 13 Mar 2024 10:37:10 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>React기준(Next.js 환경)으로 사용법이 작성되었습니다.</p>
</blockquote>
<h3 id="1-핵클이-뭐에요">1. 핵클이 뭐에요?</h3>
<ul>
<li><a href="https://hackle.io/ko/service/">https://hackle.io/ko/service/</a></li>
<li>웹 사이트, 모바일 앱, API 등 클라이언트와 서버에서 동작하는 모든 기능을 테스트 및 분석할 수 있는 플랫폼</li>
</ul>
<h3 id="2-핵클-회원가입을-진행하여-키를-확인-하세요">2. 핵클 회원가입을 진행하여 키를 확인 하세요.</h3>
<ul>
<li>운영 SDK(소프트웨어 개발 키트)키와 개발 SDK키를 확인하세요</li>
<li>SDK키 종류에는 &#39;클라이언트 측&#39;과 &#39;서버 측&#39;이 존재합니다.
<img src="https://velog.velcdn.com/images/min_99/post/1a382e22-fc53-46ae-89c1-6cab00693ca3/image.png" alt=""></li>
</ul>
<h3 id="3-sdk키로-뭐해요">3. SDK키로 뭐해요?</h3>
<pre><code>1. 테스트 그룹 분배
  - 어떤 테스트 그룹(A,B,C)에서 테스트가 진행되었는지 핵클에 집계가 됩니다
2. 기능 플래그
  - 사용자에 대해 특정 기능의 출시여부를 핵클에 집계가 된다
3. 사용자 이벤트 전송
  - 사용자가 어떤 행동을 했는지 핵클에 집계가 된다
4. 데이터 세부 분석
  - 사용자에 대해 분석 기준값을 수집하여 심도 있는 분석이 가능하다
5. 타겟팅
  - 특정 유저에게만 A/B 테스트에 참여할 수 있게 한다</code></pre><h3 id="4-개발-세팅하자">4. 개발 세팅하자</h3>
<h4 id="1-설치-진행">1) 설치 진행</h4>
<pre><code>yarn add @hackler/react-sdk</code></pre><h4 id="2-sdk-초기화설정">2) SDK 초기화(설정)</h4>
<pre><code>- `HackleReactSDKClient`를 SDK키로 초기화하세요. (디버그 모드 ON)</code></pre><blockquote>
<p>GTM을 사용하여 연동을 진행할 경우, Hackle SDK 초기화를 하고, SDK를 GTM 에서 접근할 수 있도록 window에 추가 선언이 필요합니다.</p>
</blockquote>
<pre><code>import {createInstance, HackleProvider} from &quot;@hackler/react-sdk&quot;;

// 설정정보를 포함하여 초기화
const config = {
  debug: true
};

// YOUR_BROWSER_SDK_KEY 자리에 SDK 키를 넣습니다.
const hackleClient = createInstance(&quot;YOUR_BROWSER_SDK_KEY&quot;)

function MyApp({Component, pageProps}) {
  return (
    &lt;HackleProvider hackleClient={hackleClient} supportSSR&gt;
      &lt;Component {...pageProps} /&gt;
    &lt;/HackleProvider&gt;
  )
}

export default MyApp</code></pre><ul>
<li>명시적으로 대시보드를 업데이트 하는 방법(60초에 1번만 호출가능) : <code>hackleClient.fetch();</code></li>
</ul>
<br/>


<h4 id="3-핵클에-사용자-정보를-넘겨보자">3) 핵클에 사용자 정보를 넘겨보자!</h4>
<ul>
<li><p>userId를 넘길 수도 있고, 유저에 대한 속성 데이터를 넘길수도 있다</p>
</li>
<li><p>속성 데이터 예시 : 나이 : 20대이다, 성별: &#39;여&#39; 이다.</p>
<p>   1) userId 설정 방법</p>
<pre><code>   - hackleClient.setUserId(userId);
   - 로그인 시 한번만 설정하면 됩니다.
   - 이미 로그인이 되어있는 사용자의 경우에는 로그인한 정보를 가지고 오는 시점에 호출하면 됩니다</code></pre><p>   2) 사용자 속성 설정 방법</p>
<pre><code>  import { PropertyOperationsBuilder } from &quot;@hackler/react-sdk&quot;

  const operations = new PropertyOperationsBuilder()
       .set(&quot;age&quot;, 42)
       .set(&quot;grade&quot;, &quot;GOLD&quot;)
       .build();

  hackleClient.updateUserProperties(operations);</code></pre></li>
</ul>
<blockquote>
<p>로그아웃시, 아래의 로직을 실행하여 데이터 수집을 막을 것</p>
</blockquote>
<ul>
<li>사용자 ID</li>
<li>사용자 속성<pre><code>hackleClient.resetUser();</code></pre></li>
</ul>
<br/>


<h4 id="4-사용자가-어떻게-행동하는지-살펴보자">4) 사용자가 어떻게 행동하는지 살펴보자!</h4>
<pre><code>// 이벤트 수집
hackleClient.track(&#39;purchase&#39;)

// 이벤트를 속성과 함께 수집
const event = {
  key: &quot;purchase&quot;,
  properties: {
    amount: 4200,
    pay_method: &quot;CARD&quot;,
    is_discount: false,
    product_ids: [42, 43]
  }
}
hackleClient.track(event);</code></pre>]]></description>
        </item>
    </channel>
</rss>