<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>da__hey.log</title>
        <link>https://velog.io/</link>
        <description>🌱   차근차근, 오래 즐겁게!</description>
        <lastBuildDate>Sat, 03 Jul 2021 16:44:32 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>da__hey.log</title>
            <url>https://images.velog.io/images/da__hey/profile/5f7c7bd6-265d-4154-84a9-a3e09ef58925/IMG_3005.JPG</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. da__hey.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/da__hey" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[ Javascript ] sort(), 정렬 함수]]></title>
            <link>https://velog.io/@da__hey/Javascript-sort-%EC%A0%95%EB%A0%AC-%ED%95%A8%EC%88%98</link>
            <guid>https://velog.io/@da__hey/Javascript-sort-%EC%A0%95%EB%A0%AC-%ED%95%A8%EC%88%98</guid>
            <pubDate>Sat, 03 Jul 2021 16:44:32 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>Javascript 배열의 내장 함수 sort()에 대해 이전에 간단히 정리한적이 있지만 이용 방식을 확실히 알고 가도록 다시 정리해보자. </p>
</blockquote>
<hr>
<blockquote>
<h2 id="arrayobjsortsortfunction">arrayObj.sort(sortFunction)</h2>
<p>임의의 Array 객체에 대해서 정렬을 수행하는 함수이다. 
sortFunction에는 정렬 기준을 결정하는 데 사용되는 함수를 추가할 수 있다. sortFunction은 임의의 a, b 두개의 요소를 파라미터로 입력받는다. 이 때 정렬 조건은 다음과 같다.
<br />
ex) 함수 리턴 값을 <code>a - b</code> 라고 했을 때,</p>
</blockquote>
<ul>
<li>리턴 값이 0보다 작을 경우, a가 b보다 앞에 오도록 정렬한다.</li>
<li>리턴 값이 0보다 클 경우, b가 a보다 앞에 오도록 정렬한다.</li>
</ul>
<p>이 조건을 이용하여 숫자, 문자열에 대한 오름차순과 내림차순 정렬을 할 수 있다. </p>
<h3 id="숫자-정렬">숫자 정렬</h3>
<p><img src="https://images.velog.io/images/da__hey/post/1e14c52a-16b1-4bc3-a4fe-b18ce6a18f99/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-07-04%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%201.41.07.png" alt=""></p>
<h3 id="문자열-정렬">문자열 정렬</h3>
<p><img src="https://images.velog.io/images/da__hey/post/c57b55db-3082-41bf-a31b-d33e515f5b5f/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-07-04%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%201.42.33.png" alt=""></p>
<p>오름차순을 기준으로 설명해보자면
순서대로 <code>data</code>의 <code>name</code> 값을 비교해가면서,</p>
<blockquote>
<ul>
<li>a가 b보다 <strong>작을</strong> 경우엔 <strong>-1을 리턴</strong>하여 <strong>a가 b보다 앞에</strong> 오도록</li>
</ul>
</blockquote>
<ul>
<li>a가 b보다 <strong>클</strong> 경우엔 <strong>1을 리턴</strong>하여 <strong>b가 a보다 앞에</strong> 오도록</li>
<li>a와 b가 <strong>같을</strong> 경우엔 <strong>0을 리턴</strong>하여 <strong>순서를 변경하지 않도록</strong> 정렬해준다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ Python ] 문자열 관련 함수 정리]]></title>
            <link>https://velog.io/@da__hey/Python-%EB%AC%B8%EC%9E%90%EC%97%B4-%EA%B4%80%EB%A0%A8-%ED%95%A8%EC%88%98-%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@da__hey/Python-%EB%AC%B8%EC%9E%90%EC%97%B4-%EA%B4%80%EB%A0%A8-%ED%95%A8%EC%88%98-%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Fri, 02 Jul 2021 15:32:16 GMT</pubDate>
            <description><![CDATA[<hr>
<h2 id="count문자">count([문자])</h2>
<p>문자열 중 [문자]의 개수를 반환한다. </p>
<pre><code>a = &quot;hello&quot;
a.count(&#39;l&#39;)
# 2</code></pre><h2 id="find문자">find([문자])</h2>
<p>문자열 중 문자가 처음 나온 위치를 반환한다. 
존재하지 않는다면 -1을 반환한다. </p>
<h2 id="index문자">index([문자])</h2>
<p>문자열 중 문자가 맨 처음으로 나온 위치를 반환한다. 
존재하지 않는다면 오류가 발생한다. </p>
<h2 id="문자join문자열">[문자].join([문자열])</h2>
<p>문자열의 각각의 문자 사이에 문자를 삽입한다. </p>
<pre><code>&quot;,&quot;.join(&#39;hello&#39;)
# h,e,l,l,o</code></pre><h2 id="upper-lower">upper(), lower()</h2>
<p>문자열을 대문자 혹은 소문자로 바꿔준다. </p>
<h2 id="lstrip-rstrip-strip">lstrip(), rstrip(), strip()</h2>
<p>문자열의 왼쪽 혹은 오른쪽 또는 양쪽의 공백을 지워준다. </p>
<h2 id="replace이전-문자열-새-문자열">replace([이전 문자열], [새 문자열])</h2>
<p>특정 문자열을 새로운 문자열로 변경한다. </p>
<pre><code>a = &quot;life is too short&quot;
a.replace(&quot;life&quot;, &quot;day&quot;)
# a = &quot;day is too short&quot;</code></pre><h2 id="split">split()</h2>
<p>괄호 안에 아무 값도 넣지 않으면 공백을 기준으로 문자열을 잘라 리스트로 반환한다. 
괄호 안에 값이 존재하면 그 값으로 문자열을 잘라 리스트로 반환한다. </p>
<pre><code>a = &quot;life is too short&quot;
a.split()
# [&#39;life&#39;, &#39;is&#39;, &#39;too&#39;, &#39;short&#39;]
b = &quot;a:b:c:d&quot;
b.split(&#39;:&#39;)
# [&#39;a&#39;, &#39;b&#39;, &#39;c&#39;, &#39;d&#39;]</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[ React ] nohup으로 백그라운드에서 프로세스 유지하기]]></title>
            <link>https://velog.io/@da__hey/React</link>
            <guid>https://velog.io/@da__hey/React</guid>
            <pubDate>Thu, 24 Jun 2021 14:48:53 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>원격으로 설정된 리눅스 서버로 접근했을 때, <strong>로컬의 세션이 종료될때마다 프로세스도 함께 죽는 현상</strong>이 발생한다. 리눅스에서 제공하는 명령어인 <code>nohup</code>을 이용하면 터미널의 세션 연결이 끊어지더라도 지속적으로 프로세스를 동작할 수 있게 해준다. </p>
</blockquote>
<hr>
<blockquote>
<h3 id="nohup">nohup</h3>
<p>터미널 종료 후 프로세스 작업을 유지해주는 리눅스 명령어</p>
</blockquote>
<p><strong><code>nohup [커맨드 명령어] &amp;</code></strong> 를 이용하여 백그라운드 프로세스를 유지시키려고 했다. 커맨드 명령어에는 자신의 프로젝트를 실행시키는 명령어를 적어주면 된다. </p>
<p><strong><code>nohup yarn start &amp;</code></strong>
하지만 또다시 세션종료와 동시에 프로세스도 죽는 문제가 발생했다😥 
이 문제는 아래 <strong><code>disown</code></strong> 옵션을 추가해서 해결할 수 있었다!</p>
<blockquote>
<h3 id="disown">disown</h3>
<p>터미널 종료 시 프로세스 종료 방지 </p>
</blockquote>
<p><code>disown</code>은 프로세스 작업의 소유권을 shell session에서 해제시키는 옵션이다. 옵션으로 추가해주면 현재 session job list에서 job 들이 빠져나가게 된다. 
(이는 jobs 커맨드로 확인 가능, 프로세스 전체 보기로 보면 프로세스는 남아있는 것을 볼 수 있다.)</p>
<p>따라서 터미널이 종료되어도 SIGHUP이 전달되지 않아서 계속 돌아가게 된다.</p>
<p>nohup을 실행하고 나면 프로젝트 내부에 <code>nohup.out</code>의 이름을 가진 파일이 생성된다. 세션이 종료되어도 프로세스의 출력값을 저장하는 파일로, 언제든지 이 파일을 통해 프로세스의 상태를 확인할 수 있다.</p>
<p>nohup 으로 실행중에 nohup.out 을 비우고 싶다면, 아래 명령어를 사용하면 된다.
<code>cat /dev/null &gt; nohup.out</code></p>
<h4 id="참고-블로그-🔍">참고 블로그 🔍</h4>
<p><a href="https://crazyj.tistory.com/242">https://crazyj.tistory.com/242</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ React Toy Project ] News Viewer |  뉴스 뷰어 실습 프로젝트 ]]></title>
            <link>https://velog.io/@da__hey/React-Toy-Project-News-Viewer-%EB%89%B4%EC%8A%A4-%EB%B7%B0%EC%96%B4-%EC%8B%A4%EC%8A%B5-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8</link>
            <guid>https://velog.io/@da__hey/React-Toy-Project-News-Viewer-%EB%89%B4%EC%8A%A4-%EB%B7%B0%EC%96%B4-%EC%8B%A4%EC%8A%B5-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8</guid>
            <pubDate>Thu, 24 Jun 2021 14:40:34 GMT</pubDate>
            <description><![CDATA[<blockquote>
<h1 id="news-viewer-project">News Viewer Project</h1>
<p>외부 API를 이용하여 최신 뉴스 기사 불러오는 실습 프로젝트</p>
</blockquote>
<h2 id="✨-공부한-기술">✨ 공부한 기술</h2>
<p>React, axios, Sass (+ styled-components), React router</p>
<br >

<h2 id="📚-til">📚 TIL</h2>
<h3 id="axios"><strong>Axios</strong></h3>
<p>원하는 뉴스 기사 데이터를 불러오기 위해 비동기 통신 기술인 <code>axios</code> 의 <code>GET</code> 통신을 이용하였다. </p>
<hr>
<h3 id="asyncawait"><strong>async/await</strong></h3>
<p>서버의 API를 사용할 때에는 네트워크 송수신 과정에서 시간이 소요되기 때문에 작업이 즉시 처리되게 하지 않고, 응답이 수신될 때 까지 기다렸다가 전달받은 응답 데이터를 처리하게 된다. 이를 <strong>&#39;비동기적 처리&#39;</strong> 라고 한다.</p>
<blockquote>
<p>💡 <strong>동기적 처리</strong> : 해당 요청 작업이 <strong>끝날 때 까지 중지 상태</strong>가 되어 다른 작업을 수행할 수 없게 하는 것</p>
</blockquote>
<h3 id="❌">❌</h3>
<p>다음 코드에서는 렌더링 시 <strong>작업을 즉시 처리</strong>하기 때문에, 응답 받은 <code>response</code> 데이터를 찾을 수 없어 오류가 발생할 수 있다.</p>
<p><img src="https://images.velog.io/images/da__hey/post/699e68aa-69d0-48a7-9a83-3a61ad67b163/3.png" alt=""></p>
<h3 id="⭕">⭕</h3>
<p>이는 아래 첨부 사진과 같이 <code>async</code>, <code>await</code>을 이용하여 <strong>비동기적</strong>으로 처리해준다.</p>
<blockquote>
<p>💡 <code>useEffect</code> 함수에는 <code>async</code>를 붙힐 수 없기 때문에, 내부 <code>async</code> 함수를 따로 만들어야 한다!</p>
</blockquote>
<hr>
<h3 id="useeffect"><strong>useEffect</strong></h3>
<p><img src="https://images.velog.io/images/da__hey/post/d14ed053-af63-45ca-8709-74dce5a8844e/2.png" alt=""></p>
<p>사용자가 선택한 카테고리 값에 따라 API URL의 query string이 달라지기 때문에 <code>useEffect</code>의 배열 안에 <code>category</code> 를 넣어주었다. <code>category</code> 값이 변경될 때마다 해당 URL을 통해 데이터를 다시 불러오도록 한다.</p>
<hr>
<h3 id="styled-components"><strong>Styled-Components</strong></h3>
<p><code>Styled-Components</code> 는 npm 패키지를 이용해 쉽게 다음 명령어로 설치 가능하다. </p>
<blockquote>
<p><strong>npm i styled-components</strong></p>
</blockquote>
<p>실제로 사용하기 위해 <code>Styled-Components</code>에서 <code>Styled</code>를 import를 해준다.</p>
<blockquote>
<p><strong>import styled from &quot;styled-components&quot;</strong></p>
</blockquote>
<p><img src="https://images.velog.io/images/da__hey/post/457a1f03-d907-485a-9968-7cff609ff4bf/4.png" alt=""></p>
<p>위 코드에서는 React 컴포넌트인 <code>NavLink</code>에 대한 스타일링을 <code>Category</code>에 정의하여 사용하도록 하였다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ Redux ] Vanilla Redux 알아보기]]></title>
            <link>https://velog.io/@da__hey/Redux-Vanilla-Redux-%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0</link>
            <guid>https://velog.io/@da__hey/Redux-Vanilla-Redux-%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0</guid>
            <pubDate>Thu, 24 Jun 2021 14:37:41 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p><strong>리덕스</strong>는 <strong>데이터를 관리</strong>하는데 도와주는 역할을 한다.
데이터 상태관리를 위해 React나 Angular와 함께 자주 쓰인다. </p>
</blockquote>
<hr>
<blockquote>
<h2 id="store"><code>Store</code></h2>
<p>전체 데이터의 상태를 저장하고 있는 데이터 저장소</p>
</blockquote>
<h3 id="createstore">createStore()</h3>
<p>하나의 Reducer를 가지는 데이터 저장소를 생성하는 함수</p>
<pre><code class="language-jsx">const countStore = createStore(countReducer);</code></pre>
<h3 id="dispatch">dispatch()</h3>
<p>리듀서에게 <code>action</code> 인자를 전송할 수 있는 Store의 함수</p>
<pre><code class="language-jsx">const handleAdd = () =&gt; {
  countStore.dispatch({ type: ADD });
};
const handleMinus = () =&gt; {
  countStore.dispatch({ type: MINUS });
};</code></pre>
<h3 id="subscribe">subscribe()</h3>
<p>데이터가 변경될 때 실행될 함수를 인자로 전송할 수 있는 Store의 함수</p>
<h3 id="getstate">getState()</h3>
<p>Store 내부 데이터의 상태를 확인할 수 있는 Store의 함수</p>
<pre><code class="language-jsx">const onChange = () =&gt; {
  number.innerText = countStore.getState();
};

countStore.subscribe(onChange);</code></pre>
<blockquote>
<h2 id="action"><code>Action</code></h2>
<p>Action은 Store라는 저장소에 정보를 전달하기 위한 데이터 묶음</p>
</blockquote>
<pre><code class="language-jsx">const ADD = &quot;ADD_TODO&quot;
const DELETE = &quot;DELETE_TODO&quot;</code></pre>
<blockquote>
<h3 id="action-creator"><code>Action Creator</code></h3>
</blockquote>
<p>Action Creator는 Action을 생성하기 위한 함수이다.</p>
<pre><code class="language-jsx">const handleAdd = (text) =&gt; {
        return {
                type: ADD,
                text,        
        }
}</code></pre>
<blockquote>
<h2 id="reducer"><code>Reducer</code></h2>
<p>데이터의 상태를 관리할 수 있는 오직 1개의 함수</p>
</blockquote>
<ul>
<li>Store와 데이터 정보를 주고 받는 역할을 해준다.</li>
<li>String 타입으로 전달된 Action을 통해 데이터를 어떻게 변경할지 관리해주는 역할을 한다.</li>
</ul>
<pre><code class="language-jsx">const countReducer = (count = 0, action) =&gt; {
  switch (action.type) {
    case &quot;ADD&quot;:
      return count + 1;
    case &quot;MINUS&quot;:
      return count - 1;
    default:
      return count;
  }
};</code></pre>
<h3 id="combinereducers">CombineReducers()</h3>
<p>많은 리듀서들을 하나로 합쳐 하나의 리듀서로 관리할 수 있도록 해준다.</p>
<pre><code class="language-jsx">import { combineReducers } from &#39;redux&#39;;

const toDoReducer = combineReducers({
  countReducer,
  nameReducer
});</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ React ] 내가 작성한 글/댓글/공감 수정, 삭제, 취소하기]]></title>
            <link>https://velog.io/@da__hey/React-%EB%82%B4%EA%B0%80-%EC%9E%91%EC%84%B1%ED%95%9C-%EA%B8%80%EB%8C%93%EA%B8%80%EA%B3%B5%EA%B0%90-%EC%88%98%EC%A0%95-%EC%82%AD%EC%A0%9C-%EC%B7%A8%EC%86%8C</link>
            <guid>https://velog.io/@da__hey/React-%EB%82%B4%EA%B0%80-%EC%9E%91%EC%84%B1%ED%95%9C-%EA%B8%80%EB%8C%93%EA%B8%80%EA%B3%B5%EA%B0%90-%EC%88%98%EC%A0%95-%EC%82%AD%EC%A0%9C-%EC%B7%A8%EC%86%8C</guid>
            <pubDate>Sat, 05 Jun 2021 11:02:33 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>프로젝트 진행 중 게시판을 만들면서 내가 작성한 글, 댓글, 공감에 대해서만 수정, 삭제 기능을 이용하는 방법을 구현해본 것에 대해 정리한다.</p>
</blockquote>
<hr>
<h2 id="게시물에-대한-권한을-확인하는-속성">게시물에 대한 권한을 확인하는 속성</h2>
<p>내가 작성한 글 or 댓글에만 수정, 삭제 버튼을 렌더링 해주기 위해서 클라이언트는 사용자의 토큰 정보를 헤더에 담아 서버에 전달함으로서 게시물에 대한 권한을 확인하여야 한다.</p>
<blockquote>
<p>게시물은 비로그인 사용자도 볼 수 있어야하기 때문에 토큰이 전송될 때와 전송되지 않을 경우 2가지를 고려하여 구현하였다. </p>
</blockquote>
<p><img src="https://images.velog.io/images/da__hey/post/5013740a-65d5-4dc0-8073-c6c48f291108/6.png" alt=""></p>
<ul>
<li>요청 헤더에 사용자의 토큰을 담아 axios를 이용하여 현재 게시물의 정보를 가져올 수 있는 api를 호출한다. </li>
</ul>
<p>사용자의 권한이 확인되면 서버는 아래 JSON 구조와 같이 응답 데이터에 게시물에 대한 정보와 함께 권한을 확인할 수 있는 <code>editable</code> 속성을 포함하여 전달하도록 구현하였다. 멘토님의 조언을 토대로 서버와 상의하여 데이터의 필드를 설계하였고 실제로 서버에서 받은 응답 데이터의 모습이다. </p>
<p><img src="https://images.velog.io/images/da__hey/post/ad522f35-d5c7-4906-abe8-aa03fcf6acfb/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-06-05%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%207.46.49.png" alt=""></p>
<p><img src="https://images.velog.io/images/da__hey/post/08197a41-f8e2-46a6-9547-128af05d7ef4/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-06-05%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%207.49.24.png" alt=""></p>
<p>댓글, 공감 컴포넌트도 동일하게 각 아이템마다 editable 속성을 통해 권한을 확인하면서 특정 이벤트 실행 가능 여부를 판단하도록 했다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ React ] CORS 알아보기]]></title>
            <link>https://velog.io/@da__hey/React-CORS-%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0</link>
            <guid>https://velog.io/@da__hey/React-CORS-%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0</guid>
            <pubDate>Sat, 05 Jun 2021 10:01:07 GMT</pubDate>
            <description><![CDATA[<blockquote>
<h2 id="💬-들어가며">💬 들어가며</h2>
<p>프로젝트를 진행하면서 초반에 가장 많이 발생했던 CORS 이슈에 대해 확실히 짚고 넘어가기 위해 정리해보려 한다.</p>
</blockquote>
<hr>
<h2 id="cors-가-도대체-뭐지">CORS 가 도대체 뭐지?</h2>
<p>CORS, <em>Cross-Origin Resource Sharing</em> 이라는 정책으로 웹 개발자라면 흔히 겪는 에러의 원인이라고 과언이 아니라고 한다. 실제로 서버와 통신을 진행해서 프로젝트를 진행해 본 경험이 없었던 나는 에러가 발생했을 당시 당황스러웠던 기억이 많다.</p>
<p>CORS는 쉽게 말해서 <strong>&#39;다른 출처 간의 리소스를 공유하는 것에 대한 정책&#39;</strong> 을 의미한다. 이 정책 덕분에 다양한 곳에서 가져오는 리소스가 안전하다는 최소한의 보장을 받을 수 있다. </p>
<h2 id="cors-의-동작-방식">CORS 의 동작 방식</h2>
<p>실제로 어떤 방법을 통해 리소스를 안전하게 사용할 수 있는지 알아보자.</p>
<p>기본적으로 클라이언트가 리소스를 요청할 때에 HTTP 프로토콜을 사용하여 요청을 보내게 되는데, 이때 브라우저는 <code>Request Header</code>에 서버에 요청을 보내는 출처가 담긴 <code>Origin</code>이라는 필드를 함께 담아보낸다. </p>
<blockquote>
<p>실제로 진행 중인 프로젝트에서도 API를 통해 데이터를 요청할 때의 헤더 내용을 다음과 같이 확인할 수 있었다. 
<img src="https://images.velog.io/images/da__hey/post/bf8a69f2-25c8-4eea-b7a5-2dd553ef5d2b/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-06-05%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%204.46.53.png" alt=""></p>
</blockquote>
<p>이후 서버는 이 요청에 대해 응답을 할 때 <code>Response Header</code>에 
<code>Access-Control-Allow-Origin</code> 이라는 필드에 &#39;요청 리소스에 접근이 허용된 출처&#39;를 담게 되고, 이후 응답을 받은 브라우저는 <code>Request Header</code>에 담았던 <code>Origin</code>과 <code>Access-Control-Allow-Origin</code> 필드의 값을 비교해보며 응답이 유효한지에 대해 결정하게 된다.</p>
<p>위 방식이 기본적인 CORS의 흐름이다. 하지만, CORS가 동작하는 방식은 3가지가 존재하기 때문에 개발하는 상황에 따라 자신이 어떤 시나리오에 적용되어있는지 파악한다면 에러를 고치는 것이 한결 쉬워질 것이다. </p>
<hr>
<h3 id="☝🏻-preflight-request">☝🏻 Preflight Request</h3>
<p>가장 많이 마주치는 시나리오는 프리플라이트 요청 방식이다. 이 방식은 브라우저가 본 요청을 보내기 전 예비 요청인 Preflight를 보내면서 요청이 안전한 것인지 확인하는 과정을 거친다. 이 예비 요청에는 HTTP 메소드 중 <code>OPTIONS</code> 메소드가 사용된다. 위에서 첨부한 캡처사진 또한 Preflight 요청이기에 <code>OPTIONS</code> 메소드를 사용하는 것을 확인할 수 있다!</p>
<p>다음으로 눈여겨 보아야 할 것은 예비 요청에 대해 서버가 보낸 응답 헤더에 포함된 <code>Access-Control-Allow-Origin</code> 필드이다. 요청 헤더에서의 Origin 필드의 출처와 응답 헤더에서의 ACAO 필드의 값이 동일한 것을 확인할 수 있다. 만약, ACAO 필드에서 허용하지 않는 출처를 Origin에 담았다면 CORS 정책을 위반하게 되어 에러를 뱉어내게 되는 것이다. </p>
<p><img src="https://images.velog.io/images/da__hey/post/0b3f64b9-3692-42c7-b7db-55b6917b994c/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-06-05%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%205.12.38.png" alt=""></p>
<br />

<h3 id="✌🏻-simple-request">✌🏻 Simple Request</h3>
<p>단순 요청이다. 예비 요청 없이 본 요청을 바로 서버에 보낸다. 이후 ACAO 필드를 확인해서 통신하는 방식은 Preflight 요청 방식과 같다.</p>
<p>하지만 아무 때나 단순 요청이 가능하지 않고, 아래와 같은 특정 조건을 만족하는 경우에만 예비 요청을 생략할 수 있다. 
<img src="https://images.velog.io/images/da__hey/post/02728dd8-0e0e-46ff-9e4c-ef076ce3a030/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-06-05%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%205.35.23.png" alt=""></p>
<ul>
<li>PUT, DELETE 같은 메소드를 사용하지 않으면 된다.</li>
<li>2번에 명시된 필드들은 기본적인 헤더들이기에, 대부분은 조건을 만족하지만 사용자 인증의 경우 <code>Authorization</code> 필드를 사용하므로 이 경우 조건을 만족시킬 수 없다. </li>
<li>대부분의 경우 Content-Type으로 <code>application/json</code>이나 <code>text/xml</code>을 사용하기 때문에 3번 조건 또한 만족시키기 어려운 경우가 많다고 한다.</li>
</ul>
<br />

<h3 id="🤟🏻-credentialed-request">🤟🏻 Credentialed Request</h3>
<p>다른 방법들과 달리 추가 인증을 통해 좀 더 보안을 강화하는 방법이다. </p>
<p>기본적으로 비동기 리소스 요청 API인<code>XMLHttpRequest</code> 나 <code>Fetch</code> 호출을 통해서 브라우저는 자격 증명, 즉 인증과 관련된 헤더를 함부로 요청에 담아 보내지 않는다. 이때 인증 관련 정보를 담을 수 있게 해주는 옵션이 바로 <code>credentials</code> 옵션이다. </p>
<p>자세한 정보는 참고 블로그를 통해 더 알아볼 수 있다. </p>
<h3 id="참고-블로그-🔍">참고 블로그 🔍</h3>
<p><a href="https://evan-moon.github.io/2020/05/21/about-cors/">https://evan-moon.github.io/2020/05/21/about-cors/</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ Web ] 웹 표준과 특성 적용해보기 ]]></title>
            <link>https://velog.io/@da__hey/5g3arclf</link>
            <guid>https://velog.io/@da__hey/5g3arclf</guid>
            <pubDate>Tue, 04 May 2021 08:43:43 GMT</pubDate>
            <description><![CDATA[<h3 id="💬-들어가며">💬 들어가며</h3>
<p>최근 기술 세미나에 참관하여 배웠던 _웹 표준_에 대해 정리해보고 적용시켜보려한다.</p>
<hr>
<blockquote>
<h3 id="웹-표준">웹 표준</h3>
<p>표준화 단체인 W3C가 권고한 표준안에 따라 HTML, CSS, JavaScript 등에 대한 표준 기술을 규정한 것</p>
</blockquote>
<ul>
<li><p>구조적 마크업과 표현, 레이아웃 및 행위 제어를 잘 분리하는 구축 방식 </p>
</li>
<li><p>웹 상에서 지켜야 하는 표준적인 규칙이지만 <del>필수적이진 않다.</del> 하지만 어떤 운영체제, 브라우저든 웹 페이지를 동일하게 보이고 정상작동 되게 하기 위해 필요한 규칙이다.</p>
</li>
</ul>
<blockquote>
<h3 id="웹-표준의-항목">웹 표준의 항목</h3>
<p>크게 4가지가 존재하며, 진행 중인 프로젝트에 반영하여 수정해볼 수 있는 예시들과 함께 설명해보도록 하겠다.</p>
</blockquote>
<br />

<h2 id="1-인지성-☝🏻">1. 인지성 ☝🏻</h2>
<p>정보와 사용자 인터페이스 요소는 <strong>사용자가 인지할 수 있는 형태로</strong> 제공해야한다.</p>
<br />

<p>✅ <strong>대체 텍스트</strong></p>
<p>  이미지 태그를 삽입 시 <strong>대체 텍스트</strong>를 넣어 눈이 아닌 다른 방법으로 웹을 이용하는 사용자들에게 또한 인지성을 제공한다.</p>
<p>✅ <strong>링크 이동</strong>은 <code>a</code> 태그, <strong>이벤트 실행</strong>은 <code>button</code>태그로 설정한다.</p>
<br />


<blockquote>
<p>🎃 <strong>적용해보기</strong></p>
</blockquote>
<p><img src="https://images.velog.io/images/da__hey/post/d475a6b0-c0c0-470b-96ba-b51e20d3c265/image.png" alt=""></p>
<p><strong><code>alt</code> 태그</strong>는 시각 장애인이 사용하는 스크린 리더기나 점자 타자기와 같은 보조기기에서 인식하는 대체 텍스트이다. 이 속성을 사용하여 이미지 태그에 부가 설명을 추가해주었다.</p>
<p><img src="https://images.velog.io/images/da__hey/post/f794a4f9-b233-48f3-9736-01bdc6c66c43/4.png" alt=""></p>
<p>이전에는 상단바에 존재하는 사이트맵의 태그가 모두 <code>Button</code>으로 되어있었다. 링크로 연결되는 태그이므로 <code>Link</code> 태그로 변경해주었다.</p>
<br />

<p><strong>✅ 시멘틱 태그, Semantic = &quot;의미의&quot;</strong></p>
<p>   <strong>태그에 특정 역할, 의미를 부여</strong>함으로서, 컴퓨터, 웹 사용자가 HTML 요소의 의미를 명확히 해석하여 시멘틱 웹을 실현하게 해주는 요소이다.</p>
<ul>
<li>종류 : header, nav, aside, section, article, footer </li>
<li>검색엔진, 개발자에게도 콘텐츠의 의미를 명확히 설명하여 해석할 수 있도록 한다.</li>
<li>검색엔진 최적화(SEO)와 같은 마케팅 도구에 노출 될 가능성 높아진다.<br><img src="https://images.velog.io/images/da__hey/post/5e4b8f83-d9b4-4b04-ae8b-43899116a917/image-20210504105148264.png" alt=""><br />

</li>
</ul>
<h2 id="2-실행성-✌🏻">2. 실행성 ✌🏻</h2>
<p>   사용자가 직접 인터페이스의 요소들을 탐색하여 콘텐츠의 위치를 알 수 있도록 도와줄 수 있어야 한다.
<br />
   ✅ <strong>사이트맵</strong>
   상단바나 드롭다운 기능을 통해 콘텐츠의 위치를 파악할 수 있도록 한다.
    <img src="https://images.velog.io/images/da__hey/post/2bf6fcbc-f558-4829-ba0b-f3262777632b/image-20210504113324149.png" alt=""></p>
<p>   ✅ <strong>키보드 제어</strong>
    키보드를 통해서 컨텐츠에 접근할 수 있도록 한다.
<img src="https://images.velog.io/images/da__hey/post/488c55a9-be3c-4c47-9f6c-7af7722de083/keyboardControl.gif" alt=""></p>
<p>   ✅ <strong>포인터</strong></p>
<p>   컴포넌트에 대해 마우스를 올렸을 때 실행 가능한 이벤트가 존재하는지 알 수 있게 해야한다.</p>
<p><img src="https://images.velog.io/images/da__hey/post/2a7610b6-1323-4140-a95d-a95f70cee8fa/pointer.gif" alt=""></p>
<br />


<h2 id="3-이해성-👌🏻">3. 이해성 👌🏻</h2>
<p>   사용자들이 웹 컨텐츠의 정보들을 이해하고 해석할 수 있어야 한다. 
   <br /></p>
<p>✅ <strong>언어</strong></p>
<p>  스크린 리더 프로그램은 html 문서 작성 시 상단에 위치하는 lang(language)의 속성 값에 따라 언어를 판단하게 된다. 만약, <code>lang=&quot;en&quot;</code> 일 경우에는 영어로 인지하여 한국어는 읽지 못한다. 반면, <code>lang=&quot;ko&quot;</code> 일 경우, 한국어/영어 구분없이 읽을 수 있다.
<img src="https://images.velog.io/images/da__hey/post/6b3b121b-5055-4c6a-a68d-568067a2536d/2.png" alt=""></p>
<ul>
<li>중간에 다른 언어가 사용될 때에는 해당 태그에 lang 속성을 언어에 맞게 추가해주면 된다.<br />

</li>
</ul>
<p>✅ <strong>알림 문구</strong></p>
<p>  사용자가 어떤 이벤트를 실행한 후, 실행값을 인지하고 수정할 수 있도록 알릴 수 있어야 한다.</p>
<blockquote>
<p>🎃 <strong>적용해보기</strong></p>
</blockquote>
<p>  회원가입 시 입력 조건이 일치하지 않을 때, 특정 필드의 값 아래에 알림 문구를 띄우게 구현하여 사용자가 쉽게 수정할 수 있도록 하였다. </p>
<p>  <img src="https://images.velog.io/images/da__hey/post/107f094e-0af6-4536-830e-f76803de0c83/image-20210504145918583.png" alt=""></p>
<h3 id="📚-참고-블로그">📚 참고 블로그</h3>
<ul>
<li><a href="https://velog.io/@ru_bryunak/HTML-%EA%B8%B0%EC%B4%88-2-%EC%8B%9C%EB%A7%A8%ED%8B%B1-%ED%83%9C%EA%B7%B8%EB%9E%80">https://velog.io/@ru_bryunak/HTML-%EA%B8%B0%EC%B4%88-2-%EC%8B%9C%EB%A7%A8%ED%8B%B1-%ED%83%9C%EA%B7%B8%EB%9E%80</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ Typescript ] 기본 데이터 자료형 알기]]></title>
            <link>https://velog.io/@da__hey/Typescript-%EA%B8%B0%EB%B3%B8-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%9E%90%EB%A3%8C%ED%98%95-%EC%95%8C%EA%B8%B0</link>
            <guid>https://velog.io/@da__hey/Typescript-%EA%B8%B0%EB%B3%B8-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%9E%90%EB%A3%8C%ED%98%95-%EC%95%8C%EA%B8%B0</guid>
            <pubDate>Wed, 28 Apr 2021 06:22:12 GMT</pubDate>
            <description><![CDATA[<h1 id="💁♀️-data-type">💁‍♀️ Data Type</h1>
<p>데이터가 메모리가 어떻게 저장되고, 처리되어야 하는지 명시적으로 알려주는 것</p>
<blockquote>
<p><strong>literal</strong>
값 자체가 변하지 않는 값</p>
</blockquote>
<hr>
<h2 id="🌱-기본-자료형-타입-primitive-type">🌱 기본 자료형 타입 (Primitive Type)</h2>
<ul>
<li><p>Object, Reference 형태가 아닌 <strong>실제 값을 저장</strong>하는 자료형</p>
</li>
<li><p><strong>스택(Stack) 메모리</strong>에 저장</p>
<ul>
<li>Boolean, Number, String, Undefined, Null (Javascript)</li>
</ul>
</li>
<li><p><strong>Symbol</strong></p>
<ul>
<li>심볼은 <strong>불변</strong>하고 <strong>유일</strong>함<ul>
<li>객체의 Key로 사용하여 변하지 않는 고유한 값을 설정해줄 수 있음
<img src="https://images.velog.io/images/da__hey/post/169b84b6-10cd-461a-b3b7-907970a15b79/13.png" alt=""></li>
</ul>
</li>
</ul>
</li>
</ul>
<hr>
<h2 id="🔗-참조-타입-reference-type">🔗 참조 타입 (Reference Type)</h2>
<ul>
<li><strong>Array</strong>
  <code>let list: Array&lt;myArray&gt; = [1, 2, 3];
  let list: myArray[] = [1, 2, 3];</code></li>
</ul>
<blockquote>
<h2 id="타입스크립트에서-추가되는-타입">타입스크립트에서 추가되는 타입</h2>
</blockquote>
<ul>
<li><del><strong>Any</strong></del> : 어떤 타입도 상관 없는 타입, 사용하지 않는 게 중요 👀</li>
<li><strong>Void</strong> : 타입이 없는 상태, <strong>함수 리턴 값이 없을 때</strong> 사용</li>
<li><strong>Never</strong> : 리턴에 주로 사용, 아래 3가지가 주로 사용
<img src="https://images.velog.io/images/da__hey/post/1ed8dc1e-33d1-4625-b5be-1127fbaa7299/14.png" alt=""></li>
</ul>
<blockquote>
<ul>
<li><strong>Enum</strong> </li>
</ul>
</blockquote>
<ul>
<li><strong>열거형</strong> 데이터 타입
별도의 값이 설정된 멤버들의 집합으로 이루어진 자료형</li>
<li>쉬운 이름으로 데이터에 접근하기 위해 활용
멤버에 따로 값을 할당하지 않으면 <code>default = 0</code> 이 할당되며, 이후 멤버들은 이전 멤버의 값에 <code>+1</code>된 값이 할당된다. 
<img src="https://images.velog.io/images/da__hey/post/2005bbe0-70d2-40c5-a40f-2d40cc426cfa/15.png" alt=""></li>
</ul>
<blockquote>
<ul>
<li><strong>Tuple</strong></li>
</ul>
</blockquote>
<ul>
<li><strong>Object</strong> 형
배열이지만, 타입이 여러가지인 경우 사용
<img src="https://images.velog.io/images/da__hey/post/f2d897ec-1cbf-49c1-b080-a1030298996b/16.png" alt=""></li>
</ul>
<hr>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ React ] 컴포넌트 생명주기 메서드와 HOOKS ( useState, useEffect ) (1)]]></title>
            <link>https://velog.io/@da__hey/React-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8-%EC%83%9D%EB%AA%85%EC%A3%BC%EA%B8%B0-%EB%A9%94%EC%84%9C%EB%93%9C%EC%99%80-HOOKS-useState-useEffect-1</link>
            <guid>https://velog.io/@da__hey/React-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8-%EC%83%9D%EB%AA%85%EC%A3%BC%EA%B8%B0-%EB%A9%94%EC%84%9C%EB%93%9C%EC%99%80-HOOKS-useState-useEffect-1</guid>
            <pubDate>Tue, 27 Apr 2021 08:07:38 GMT</pubDate>
            <description><![CDATA[<h1 id="컴포넌트-초기-생성-🌱">컴포넌트 초기 생성 🌱</h1>
<p>컴포넌트의 객체가 생성되어 DOM 상에 삽입될 때 아래 순서대로 호출된다.</p>
<ul>
<li><strong><code>constructor()</code></strong><ul>
<li>컴포넌트가 생성될 때 자동으로 호출되는 컴포넌트 생성자 함수</li>
</ul>
</li>
<li><strong><code>render()</code></strong><ul>
<li>클래스 컴포넌트에서 반드시 구현되어야 하는 메서드</li>
</ul>
</li>
<li><strong><code>componentDidMount()</code></strong><ul>
<li>컴포넌트가 화면에 출력될 때 호출되는 함수</li>
<li>외부 라이브러리 연동, axios/fetch를 통한 데이터 요청, DOM 속성 읽기/수정 작업 시 실행  </li>
</ul>
</li>
</ul>
<h1 id="컴포넌트-업데이트-🌷">컴포넌트 업데이트 🌷</h1>
<p>props 또는 state가 변경될 때 컴포넌트를 다시 갱신해주어야 할 필요가 있다. 이 때 사용되는 메서드들이다.</p>
<ul>
<li><p><code>static getDerivedStateFromProps(nextProps, prevState)</code></p>
</li>
<li><p>업데이트 시킬 props의 값(nextProps.value)과 업데이트 전 state의 값(prevState.value)를 매개변수로 갖는다.</p>
</li>
<li><p><code>shouldComponentUpdate(nextProps, nextState)</code></p>
</li>
<li><p>특정 조건에 따라 업데이트를 막아줄 수 있는 함수</p>
</li>
<li><p><code>getSnapshotBeforeUpdate()</code></p>
</li>
<li><p>실제 DOM이 업데이트 되기 전에 이전 상태를 저장하여 가져오는 함수</p>
</li>
<li><p>이 메서드는 props, state의 업데이트에 따라 컴포넌트에 특정 함수를 실행시키고 싶을 때 사용한다.</p>
</li>
<li><p><code>componentDidUpdate()</code> </p>
<ul>
<li>컴포넌트에서 렌더링 호출 후에 발생하는 함수</li>
</ul>
</li>
</ul>
<hr>
<h1 id="hooks-🌴">HOOKS 🌴</h1>
<h2 id="🌊-state-hook">🌊 State Hook</h2>
<blockquote>
<h3 id="usestate"><code>useState</code></h3>
<p>클래스 컴포넌트에서처럼 <code>state</code>를 생성하고 관리할 수 있다.
아래 사진과 같이 대괄호로 묶어 생성하고, 수정한다. </p>
</blockquote>
<h3 id="📌-사용법">📌 사용법</h3>
<p><img src="https://images.velog.io/images/da__hey/post/1ac162c0-8c7d-4bee-b4b1-63bc8f894ca6/image.png" alt=""></p>
<p>✅ <strong>타입스크립과 함께 사용할 때</strong>
원하는 타입 구조의 인터페이스를 생성해주고 다음과 같이 정의해준다.</p>
<pre><code>interface dataInfo {
    name: string,
    age: number
}
const [data, setData] = useState&lt;dataInfo&gt;()</code></pre><ul>
<li>객체나 배열의 state을 생성하고 싶을 때는 다음과 같이 정의해준다. <pre><code>const [data, setData] = useState&lt;dataInfo&gt;(Object)
const [data, setData] = useState&lt;dataInfo[]&gt;([])</code></pre></li>
</ul>
<h2 id="⚡-effect-hook">⚡ Effect Hook</h2>
<blockquote>
<h3 id="useeffect"><code>useEffect</code></h3>
<p>컴포넌트가 <strong>마운트 / 언마운트 / 업데이트</strong> 될 때, 컴포넌트가 렌더링 이후 수행해야 하는 일을 알려주도록 하는 함수</p>
</blockquote>
<h3 id="📌-사용법-1">📌 사용법</h3>
<pre><code>useEffect( () =&gt; {
    // mount 시 실행할 함수
    return () =&gt; {
        // unmount 시 실행할 함수
    ]
}, [deps값]);</code></pre><p>✅ <em><strong>deps 배열에 특정 state가 존재할 때</strong></em>, </p>
<p>1) 컴포넌트가 처음 마운트 될 때 호출
2) 컴포넌트가 언마운트 될 때 호출
3) 해당 state 값이 업데이트 될 때 호출</p>
<p>✅ <em><strong>deps 배열이 빈 배열일 때</strong></em>, </p>
<p>1) 컴포넌트가 처음 마운트 될 때 호출</p>
<h3 id="🎃-실제로-사용해보기">🎃 실제로 사용해보기</h3>
<p>프로젝트 진행 시 사용했던 코드와 함께 설명하겠다. </p>
<p><img src="https://images.velog.io/images/da__hey/post/832c558b-b3c5-4aa2-a789-51327d235268/12.png" alt=""></p>
<p>위 코드는 댓글 <code>commentItem</code>  또는 답글 <code>recommentItem</code>  각각에 추천/비추천의 개수가 변경될 때마다 <code>item</code>에 <code>commentItem</code>, <code>recommentItem</code>을 저장해주어야 하므로 작성된 코드이다. </p>
<p>💡 <strong>deps 배열은 말그대로 배열이므로 여러 개의 변수가 할당되는 것이 가능하다.</strong></p>
<ul>
<li>추천/비추천 버튼을 누르면 컴포넌트의 props로 <code>commentItem</code> 또는 <code>recommentItem</code>이 들어오게 된다. </li>
<li>이 때, 들어온 <strong><code>commentItem</code> 또는 <code>recommentItem</code>의 값</strong>에 따라 <code>setItem</code> 함수를 통해 <code>item</code>에 값을 저장하게 된다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ Javascript ] Ajax : fetch & axios API]]></title>
            <link>https://velog.io/@da__hey/Javascript-Ajax-fetch-axios-API</link>
            <guid>https://velog.io/@da__hey/Javascript-Ajax-fetch-axios-API</guid>
            <pubDate>Tue, 27 Apr 2021 07:32:25 GMT</pubDate>
            <description><![CDATA[<blockquote>
<h1 id="ajax-란">Ajax 란?</h1>
<p>(Asynchronous Javascript And Xml)
Javascript를 이용한 <strong>비동기 통신 기술</strong>로, 클라이언트와 서버 사이에서 <strong>전체 페이지를 리로드 할 필요 없이</strong>,** 필요한 데이터만 로드** 할 수 있다.</p>
</blockquote>
<p>💡 Ajax는 JSON, XML, HTML, txt 등 다양한 형태의 데이터를 주고 받을 수 있다.</p>
<p>💡 Ajax를 구현할 수 있는 기술들 중 최신 기술인 <code>Fetch()</code>, <code>Axios()</code> 에 대해 알아보도록 한다.</p>
<ul>
<li><code>Fetch()</code>, <code>Axios()</code> API 모두 Javascript 라이브러리로, <code>Promise</code> 기반의 비동기 통신 기술이다.
( = <code>Promise</code> 객체 형태로 return 한다. )</li>
</ul>
<hr>
<h2 id="1-fetch">1. fetch</h2>
<ul>
<li>import 하지 않아도 사용 가능하다.</li>
<li>지원하지 않는 브라우저가 있다.</li>
<li>네트워크 에러가 발생했을 때 기다려야 한다.
( reponse timeout API을 제공하지 않음 )</li>
</ul>
<h3 id="1-1-fetch를-이용해보자">1-1. fetch를 이용해보자!</h3>
<pre><code>fetch(url, options)
    .then((response) =&gt; console.log(&quot;response:&quot;, response))
        .catch((error) =&gt; console.log(&quot;error:&quot;, error))</code></pre><ul>
<li>첫번째 인자인 url을 통해 API를 호출한다. 반환된 <code>Promise</code> 타입의 객체는 호출의 성공 여부에 따라 응답 객체(response) 또는 예외 객체(error)를 resolve, reject한다.  </li>
</ul>
<p>🔎 <em>옵션(options) 객체</em> : HTTP 방식(method), HTTP 요청 헤더(headers), HTTP 요청 전문(body) 등을 설정 가능하다. </p>
<p><strong>예제</strong>
다음은 <a href="https://jsonplaceholder.typicode.com/todos">JSONPlaceholder</a>에서 fetch를 이용하여 free API를 호출하는 코드이다. </p>
<p><img src="https://images.velog.io/images/da__hey/post/1a4edbd8-4d6b-4f48-81ad-41b4838c3ec7/image.png" alt=""></p>
<p>🔎 <strong>가져오려는 데이터의 형태</strong></p>
<pre><code> {
    &quot;userId&quot;: 1,
    &quot;id&quot;: 1,
    &quot;title&quot;: &quot;delectus aut autem&quot;,
    &quot;completed&quot;: false
 }</code></pre><p>🔎 (7-11번째줄)</p>
<pre><code>fetch(&#39;https://jsonplaceholder.typicode.com/todos/1&#39;)
  .then(res =&gt; res.json())
  .then(json =&gt; {
      setTodos(data);
      setLoading(false);
  });</code></pre><p>간단히 설명하자면, url에 존재하는 JSON 형태의 데이터를 성공적으로 가져오면 첫번째 <code>.then</code>을 실행한다. 데이터를 JSON 형태로 파싱한 후, 파싱된 데이터는 두번째 <code>.then</code>의 실행으로 인해 <code>todos</code> 변수에 저장된다. </p>
<p>실제 결과를 확인하면 아래와 같다. 
<img src="https://images.velog.io/images/da__hey/post/613651ce-b590-4486-8253-41ab04936c8a/ezgif.com-gif-maker.gif" alt=""></p>
<blockquote>
<p>💭 *<em>예제 실행 시 해결한 issue *</em>
가져오려는 데이터의 타입과 변수의 타입을 올바르게 지정하지 않으면 오류가 발생한다. 위 예제에서 여러개의 object가 담긴 array를 가져오는 것을 제대로 알아보지 않고 하나의 array를 가져오는 거라 생각해서 문제가 발생했었다. </p>
</blockquote>
<hr>
<h2 id="2-axios">2. axios</h2>
<ul>
<li>대부분의 브라우저에서 지원하고 있는 라이브러리이다.</li>
<li>request aborting (요청취소)가 가능하다.</li>
<li><code>catch</code>에 걸렸을 때, <code>.then</code>을 실행하지 않고, console 창에 해당 에러 로그를 보여준다.</li>
<li>fetch 보다 더 많은 기능이 존재한다.</li>
</ul>
<h3 id="2-1-axios를-이용해보자">2-1. axios를 이용해보자!</h3>
<p>클라이언트와 서버 간에 사용되는 <strong>HTTP Methods</strong> 중 많이 사용되는 메서드를 기반으로 알아보도록 한다. ( GET, POST, DELETE, PUT )</p>
<h4 id="🚀-설치와-호출">🚀 설치와 호출</h4>
<p><code>npm install axios</code> or <code>yarn add axios</code>
<code>const axios = require(&#39;axios&#39;);</code> </p>
<hr>
<blockquote>
<h3 id="get">GET</h3>
<p>✅ <strong>GET</strong>은 서버에서 원하는 데이터를 가져와서 보여주기 위해 사용한다. 입력한 url에서 
<code>axios.get(url, [,config])</code></p>
</blockquote>
<p>🚀 <strong>사용해보기</strong>
<img src="https://images.velog.io/images/da__hey/post/255f5bad-2df4-49d2-9601-1c11fec47567/11.png" alt=""></p>
<hr>
<blockquote>
<h3 id="post">POST</h3>
<p>✅ <strong>POST</strong>는 프론트에서 서버에 데이터를 저장하기 위한 용도로 사용한다. 
<code>axios.post(url, {
        data 객체
    }, [,config])</code></p>
</blockquote>
<p>🚀 <strong>사용해보기</strong>
<img src="https://images.velog.io/images/da__hey/post/f380ba30-cca5-4608-bf03-c2a31908e7c6/10.png" alt=""></p>
<hr>
<blockquote>
<h3 id="delete">DELETE</h3>
<p>✅ <strong>DELETE</strong>는 서버에 저장된 데이터를 삭제하기 위해 사용한다.
<code>axios.delete(url, [,config])</code></p>
</blockquote>
<blockquote>
<h3 id="put">PUT</h3>
<p>✅ <strong>PUT</strong>은 프론트에서 서버에 데이터를 저장하기 위한 용도로 사용한다. 
<code>axios.put(url[, data[, config]])</code></p>
</blockquote>
<hr>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ React ] 무한 Scroll Bar 구현과 이슈]]></title>
            <link>https://velog.io/@da__hey/React-%EB%AC%B4%ED%95%9C-Scroll-Bar-%EA%B5%AC%ED%98%84-%EB%B0%8F-%EC%9D%B4%EC%8A%88</link>
            <guid>https://velog.io/@da__hey/React-%EB%AC%B4%ED%95%9C-Scroll-Bar-%EA%B5%AC%ED%98%84-%EB%B0%8F-%EC%9D%B4%EC%8A%88</guid>
            <pubDate>Tue, 27 Apr 2021 01:29:17 GMT</pubDate>
            <description><![CDATA[<blockquote>
<h2 id="💬-들어가며">💬 들어가며</h2>
<p> &#39;숨고&#39; 사이트 클론 프로젝트를 2주간 진행하면서 해결했던 이슈에 대해 정리해보려 한다. 프로젝트 진행 전에도 리액트를 공부하면서 혼자서 이것저것 만들어봤던 경험이 있었지만, 상대적으로 대량의 데이터를 가진 사이트를 서버와 협업하여 만들어보는 경험은 처음이었기 때문에 긴장도 되었고 어떤 것을 배우게 될지 설레기도 했다.</p>
</blockquote>
<hr>
<h2 id="❌-문제-발생">❌ 문제 발생</h2>
<blockquote>
<p>문제는 <strong>유저 데이터를 불러와 렌더링하는 과정</strong>에서 발생했다. </p>
</blockquote>
<p>구현하려고 했던 기능은 사용자가 스크롤을 내려 화면을 이동할 때, 일정 개수만큼 유저 데이터를 가져와 띄워주는 기능이다. 첫 화면에서는 제대로 동작하였지만, 라우팅을 통해 다른 페이지를 이동한 후, 뒤로 가기나 이전 버튼을 통해 돌아오게 되면 엄청난 에러와 함께 1<del>10번의 유저가 아닌 10</del>20번대의 유저들을 불러왔다.</p>
<h2 id="🔎-원인-찾기">🔎 원인 찾기</h2>
<p>먼저 원인을 찾기 위해 스크롤 시 데이터를 불러오는 함수 <code>onScroll()</code> 를 확인했다. 해당 함수 내의 분기 문은 <code>scroll height</code>가 일정 조건을 만족하면 <code>state</code>가 변경되어 데이터를 가져오는 방식이다. 이해를 돕기 위해 코드를 추가했다.</p>
<p><img src="https://images.velog.io/images/da__hey/post/b29a5006-fab9-46c8-bfb4-56b0cffedd41/image.png" alt=""></p>
<ul>
<li>이 함수는 <code>window</code>의 <code>scroll</code>이 실행 되었을 때 발생되는 이벤트 리스너 함수로, 스크롤이 실행되면서 변경되는 <code>scroll height</code>의 값에 따라 작동한다. </li>
<li>발생하는 문제의 원인이 분기 문을 통과하여 유저 배열의 인덱스로 사용되는 <code>preIndex</code>, <code>index</code> 상태 값이 업데이트 되는 것 때문이라고 생각했기에, 페이지 이동 시 <code>scroll height</code>을 확인해보았다. </li>
<li>페이지가 이동하면 1~10까지의 데이터가 불러와지고 <code>scroll height</code>가 대략 1000px 이상이어야 하지만… <strong>터무니없이 작은 수가 저장되어 분기 문을 통과하는 것</strong>을 알게 되었다.</li>
</ul>
<h2 id="💭-고민해보기">💭 고민해보기</h2>
<ol>
<li><p>해결을 위해 처음엔 &#39;<code>scroll height</code> 를 변경시킬 수는 없을까?&#39; 라는 생각이 들었다. 그러기 위해선 미리 <code>scroll height</code> 를 저장시켜 놓아야 했고, 이는 비효율적이라고 판단했다. 유저 리스트를 다른 곳에 저장해놓고 불러오는 방식 또한 다른 데이터 스토어를 이용하지 않고 있었기에 불가 했다.</p>
</li>
<li><p>&#39;Window에 리스너를 붙이지 않고, 유저를 띄우는 클래스 자체에 리스너를 붙여야 하는가?&#39; 하고 수정해보았지만 작동이 되지 않았다.</p>
</li>
</ol>
<h2 id="🤦♀️-드디어-해결">🤦‍♀️ 드디어 해결..!</h2>
<p><strong>기본적이지만 중요했다.</strong>
기존 코드에서는 컴포넌트가 마운트 될 때에 데이터를 가져온 후, 리스너 함수를 붙이도록 구현했다. <em>&#39;분명 데이터를 가져온 후, <code>onScroll()</code> 함수가 실행되도록 구현을 했는데 왜 <code>scroll height</code>의 값은 작은 걸까?</em>&#39; 고민을 하다가 <strong>&#39;데이터를 가지고 오기 전에 리스너 함수가 실행되었을 수 있겠다!&#39;</strong> 라는 생각이 번쩍 들었다.</p>
<p>결과는 역시 <strong>데이터를 가져오기 전 <code>scroll</code>의 리스너 함수가 먼저 실행되어 버리는 비동기 처리 방식으로 코드가 짜여 졌기에</strong> 문제가 발생한 것이었다..</p>
<p><img src="https://images.velog.io/images/da__hey/post/cff2b1d1-cffb-41c3-a7fd-a5dd0f85d5b6/image.png" alt=""></p>
<p>다음과 같이 데이터를 가져온 후, call back 함수에 리스너 함수를 넣어주는 방식으로 코드를 수정하여 문제를 해결할 수 있었다.</p>
<p><img src="https://images.velog.io/images/da__hey/post/a28250fe-219f-4ebe-85bf-939c1daa22c5/scroll.gif" alt=""></p>
<pre><code>                    #뿌듯신기👀</code></pre><h2 id="회고">회고</h2>
<p>아쉬웠다. 리액트를 공부하면서 외부 api에서 데이터를 받아오는 프로젝트 경험이 있었기에 ajax의 비동기적 처리 방식에 대해선 인지하고 있었지만, 막상 직접 페이지부터 컴포넌트까지 설계하여 구현 하다 보니 가장 기본적인 ajax의 특징에 대해서 잊고 문제 해결에 시간이 오래 걸린 것에 대해 아쉬웠다. 하지만 다행이기도 했다. 덕분에 비동기 방식에 대해서 확실히 알 수 있었고, 앞으로 같은 문제가 발생하더라도 더 빠르게 원인을 파악하여 해결할 수 있는 능력을 기를 수 있었기 때문이다.
 어떤 이슈를 해결할 때마다 느끼는 점이지만 실패를 거듭할수록 성장하고 있다고 생각한다. 아직 부족한 점이 많지만 앞으로 겪을 실패들을 또 다른 도전, 또 다른 성장이라고 생각하며 차근차근 성장하는 개발자가 되고 싶다. 🌱</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ Material UI ] Issue : React does not recognize the 'showLabel' prop]]></title>
            <link>https://velog.io/@da__hey/Material-UI-Issue-React-does-not-recognize-the-showLabel-prop</link>
            <guid>https://velog.io/@da__hey/Material-UI-Issue-React-does-not-recognize-the-showLabel-prop</guid>
            <pubDate>Tue, 27 Apr 2021 01:10:33 GMT</pubDate>
            <description><![CDATA[<h2 id="❌-발생한-문제">❌ 발생한 문제</h2>
<p><img src="https://images.velog.io/images/da__hey/post/0d4382fe-6244-4002-833e-e8eed68e8145/image.png" alt=""></p>
<p><code>BottomNavigation</code> 태그에 적절한 props를 사용하지 않았다는 문제였다. 코드 내에서는 에러가 발생하지 않아서 도무지 원인이 무엇인지 알 수 없었다. </p>
<h2 id="🚀-고민해보기">🚀 고민해보기</h2>
<p><img src="https://images.velog.io/images/da__hey/post/0d4382fe-6244-4002-833e-e8eed68e8145/image.png" alt=""></p>
<p>오류 메시지에 제안된 방식으로 <code>showlabels</code>를 삭제해보거나 소문자로 수정해보았지만 해결되지 않았다. 웹서핑을 통해 깃헙의 동일한 이슈를 찾았고, 이를 통해 해결할 수 있었다.</p>
<h2 id="💬-원인--해결">💬 원인 &amp; 해결</h2>
<p><code>BottomNavigation</code> 태그 내부에 <strong>사용해주어야 할 특정 컴포넌트를 사용</strong>하지 않고 <code>Button</code>을 사용하여서 발생</p>
<p><img src="https://images.velog.io/images/da__hey/post/d30decdd-f84f-41f1-bebd-229bd89f8c4e/8.png" alt=""></p>
<p><strong>해결 방법</strong>
MaterialUI 문서에 따라 <code>BottomNavigationAction</code>를 사용하여 해결</p>
<p><strong>수정한 코드</strong>
<img src="https://images.velog.io/images/da__hey/post/4f0c212e-fadf-4aa4-ac90-cc0be2969365/9.png" alt=""></p>
<p>🔎 <strong>참고 블로그</strong></p>
<blockquote>
<p><a href="https://github.com/mui-org/material-ui/issues/14176#issuecomment-454038379">https://github.com/mui-org/material-ui/issues/14176#issuecomment-454038379</a></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ React + Material UI ] Issue : findDOMNode is deprecated in StrictMode error]]></title>
            <link>https://velog.io/@da__hey/React-Material-UI-Issue-findDOMNode-is-deprecated-in-StrictMode-error</link>
            <guid>https://velog.io/@da__hey/React-Material-UI-Issue-findDOMNode-is-deprecated-in-StrictMode-error</guid>
            <pubDate>Sat, 24 Apr 2021 09:25:51 GMT</pubDate>
            <description><![CDATA[<h2 id="💬-목적">💬 목적</h2>
<p>Material UI를 사용하면서 작은 에러들이 곳곳에서 발견 되었는데, Select 컴포넌트 이용 중 처음 발생했던 에러에 대해 얘기해보고자 한다. </p>
<blockquote>
<p><strong><code>findDOMNode is deprecated in StrictMode error</code></strong></p>
</blockquote>
<h2 id="🚀-해결-방법">🚀 해결 방법</h2>
<p><code>Function Component</code>로 프로젝트를 진행하였고 이에 대한 해결 방법부터 먼저 설명하자면,</p>
<p>📌 import한 <code>ThemeProvider</code>를 wrapper tag로 감싸준다. 
📌 <code>unstable_createMuiStrictModeTheme</code>를 실행해 가져오는 리턴 값을 <code>ThemeProvider</code>의 속성 값 <code>theme</code>에 넣어준다.</p>
<p><img src="https://images.velog.io/images/da__hey/post/0e743542-dc18-41f9-84a8-0b68a3a05ee6/6.png" alt=""></p>
<p><code>Class Component</code>에서는 MaterialUI에서 작성한 글을 통해 확인할 수 있다. </p>
<blockquote>
<p><a href="https://ko.reactjs.org/docs/strict-mode.html#warning-about-deprecated-finddomnode-usage">https://ko.reactjs.org/docs/strict-mode.html#warning-about-deprecated-finddomnode-usage</a></p>
</blockquote>
<hr>
<h2 id="❔-발생-이유">❔ 발생 이유</h2>
<p>오류는 해결 되었으니 이제 이유를 알아보자. 
프로젝트 생성 시 CRA(create-react-app)을 이용하면, <code>index.js</code>는 다음과 같이 생성된다. </p>
<p><img src="https://images.velog.io/images/da__hey/post/6fe1e78c-9fa6-461f-b75b-1445615ba0df/7.png" alt=""></p>
<p>위 코드에서 중요 시 봐야할 것은 <code>React.StrictMode</code> 태그이다. </p>
<h2 id="🔎-strictmode-란">🔎 StrictMode 란?</h2>
<p>컴포넌트들을 대상으로 잠재적인 문제들을 알아내기 위한 검사 도구이다. StrictMode 태그로 감싸진 컴포넌트들을 검사하게 되며, React 공식 문서에 따른 검사 기능은 다음과 같다. </p>
<blockquote>
<p><strong>기능</strong></p>
</blockquote>
<ul>
<li>안전하지 않은 생명주기를 사용하는 컴포넌트 발견</li>
<li>레거시 문자열 ref 사용에 대한 경고</li>
<li><strong>권장되지 않는 findDOMNode 사용에 대한 경고</strong></li>
<li>예상치 못한 부작용 검사</li>
<li>레거시 context API 검사
( + 이외에도 향후 더 많은 기능이 추가될 예정이라고 한다.)</li>
</ul>
<p><strong>결론적으로</strong>, _권장되지 않는 DOMNode를 사용해서 발생한 에러_이다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ React ] React, Typescript를 통해 카카오톡 메시지 플랫폼 API 이용해보기]]></title>
            <link>https://velog.io/@da__hey/React-React-Typescript%EB%A5%BC-%ED%86%B5%ED%95%B4-%EC%B9%B4%EC%B9%B4%EC%98%A4%ED%86%A1-%EB%A9%94%EC%8B%9C%EC%A7%80-%ED%94%8C%EB%9E%AB%ED%8F%BC-API-%EC%9D%B4%EC%9A%A9%ED%95%B4%EB%B3%B4%EA%B8%B0</link>
            <guid>https://velog.io/@da__hey/React-React-Typescript%EB%A5%BC-%ED%86%B5%ED%95%B4-%EC%B9%B4%EC%B9%B4%EC%98%A4%ED%86%A1-%EB%A9%94%EC%8B%9C%EC%A7%80-%ED%94%8C%EB%9E%AB%ED%8F%BC-API-%EC%9D%B4%EC%9A%A9%ED%95%B4%EB%B3%B4%EA%B8%B0</guid>
            <pubDate>Sat, 24 Apr 2021 09:24:38 GMT</pubDate>
            <description><![CDATA[<h2 id="카카오톡-메시지-플랫폼-api-이용해보기">카카오톡 메시지 플랫폼 API 이용해보기</h2>
<h2 id="💬-들어가며">💬 들어가며</h2>
<p>사이드 프로젝트를 진행하면서 사용자 초대 링크를 카카오톡 공유 API를 통해 전송하는 기능을 구현하게 되었다. API에서 데이터를 가져오는 실습은 해본 적이 있지만, API를 통해 데이터를 전송해보는 경험은 처음인지라 좀 긴장했다. Javascript, Android, IOS 를 통한 연동 참고 자료는 검색해보면 많았지만 React, Typescript 관련 자료는 많지 않아 애를 좀 먹었다. React, Typescript로 연동한 과정을 차근차근 정리해보도록 하겠다. </p>
<h2 id="🚀-요약-설명">🚀 요약 설명</h2>
<ul>
<li>Kakao Developer 회원가입</li>
<li>애플리케이션 추가</li>
<li>사용하고자 하는 플랫폼에 사이트 도메인 등록</li>
<li>앱 키를 이용해 플랫폼 내에 SDK 설치 및 필요 코드 추가</li>
</ul>
<h2 id="💁♀️-상세-설명">💁‍♀️ 상세 설명</h2>
<h4 id="1-kakao-developer-회원가입">1. <a href="https://accounts.kakao.com/login?continue=https%3A%2F%2Fdevelopers.kakao.com%2Fregister%3Fcontinue%3Dhttps%253A%252F%252Fdevelopers.kakao.com%252F">Kakao Developer</a> 회원가입</h4>
<h4 id="2-내-애플리케이션---애플리케이션-추가하기">2. &#39;내 애플리케이션&#39; - 애플리케이션 추가하기</h4>
<p><img src="https://images.velog.io/images/da__hey/post/03474dbb-0b80-4611-9870-070ca1e253e7/image.png" alt=""></p>
<ul>
<li>앱 아이콘, 앱 이름, 사업자명을 입력하고 저장해준다.</li>
<li>앱 이름은 대부분 홈페이지 명을 사용한다.
(앱 아이콘은 다음 사진에서 참고)</li>
</ul>
<p><img src="https://images.velog.io/images/da__hey/post/02b8c4ff-6f4d-4cbe-87ad-b7deb142a80f/image.png" alt="">
앱 아이콘은 위 빨간 박스를 가리킨다.</p>
<h4 id="3-애플리케이션-설정해주기">3. 애플리케이션 설정해주기</h4>
<ul>
<li>생성된 애플리케이션을 누르면 앱 키, 플랫폼, 기본 정보를 확인할 수 있다.</li>
</ul>
<h4 id="🔑-앱-키">🔑 앱 키</h4>
<ul>
<li>앱 키에선 다음과 같이 발급 받은 고유키를 확인할 수 있고 이를 통해 원하는 플랫폼에서 API를 사용 가능하다. </li>
</ul>
<p><img src="https://images.velog.io/images/da__hey/post/c39fd157-6bcd-4e9f-8e97-b8720263750f/image.png" alt=""></p>
<h4 id="🏝-플랫폼">🏝 플랫폼</h4>
<ul>
<li>플랫폼 설정하기를 통해 사용하고자 하는 플랫폼에서 등록버튼을 누르면 사이트 도메인을 등록할 수 있다. 발급된 앱 키는 등록된 도메인에서만 적용된다.</li>
</ul>
<p><img src="https://images.velog.io/images/da__hey/post/59720e88-fb37-4076-9e1d-5288e3712593/image.png" alt=""></p>
<h4 id="4-코드-추가하기">4. 코드 추가하기</h4>
<blockquote>
<p><strong>Kakao SDK 스크립트 파일 추가하기</strong></p>
</blockquote>
<p>프로젝트의 <code>index.html</code> 파일의 <code>head</code> 태그 내에 다음 코드를 추가한다.
<img src="https://images.velog.io/images/da__hey/post/e34442ef-e820-43e0-abca-538a9f9c740d/2.png" alt=""></p>
<hr>
<blockquote>
<p><strong>발급 받은 앱 키를 통해 초기화하기</strong></p>
</blockquote>
<p>API를 사용할 수 있는지 인증하는 과정이며 다음과 같이 API를 사용하고자 하는 컴포넌트에서 추가해주었다. <strong><code>init</code> 함수의 인자값에 발급 받은 앱 키를 넣어주면 된다</strong>. 나는 <code>.env</code>파일에 저장해 둔 변수를 가져와 넣어주었다.</p>
<p><img src="https://images.velog.io/images/da__hey/post/98ada0ac-99f2-4490-bb49-9db52d8330e0/4.PNG" alt=""></p>
<blockquote>
<p>👀 초기화가 잘 되어 API를 가져왔는지 콘솔로 확인해보면 <code>true</code>값이 뜨고, <code>false</code>라면 초기화를 실패한 것이다. 그런 경우엔 앱 키를 다시 확인해보도록 하자.</p>
</blockquote>
<p>📌 리액트에서는 <code>window</code>를 통해 <strong><code>window.Kakao</code></strong>로 접근해야 한다.</p>
<p>📌 만약, 에러가 뜨면서 <code>Kakao</code>를 가져오지 못한다면 아래와 같이 해결해보자. 내게 발생했던 에러는 다음과 같았다. </p>
<blockquote>
<p><code>&#39;Window &amp; typeof globalThis&#39; 형식에 &#39;Kakao&#39; 속성이 없습니다.</code></p>
</blockquote>
<p>이는 Typescript로 인해 <em>window에 Kakao를 받을 속성 type이 정의되어 있지 않아</em> 발생하는 에러이다. 에러는 아래와 같이 해결할 수 있었다. </p>
<blockquote>
<p>✅ <strong><code>react-app-env.d.ts</code> 에 window의 새로운 속성인 <code>Kakao</code>를 추가한다.</strong></p>
</blockquote>
<p>type을 any로 설정하면 Typescript를 사용하는 이유가 없으므로 <code>Object</code>로 설정하였으나, <code>&#39;Object&#39; 형식에 &#39;Link&#39; 속성이 없습니다.</code> 또 다른 에러가 발생하여 어떤 타입으로 설정해주어야 하는지 찾아봤지만 결국 any로 설정해야 했다. </p>
<pre><code>interface Window {
     Kakao: any
}</code></pre><p>** 🔥 <em>앱 키는 보안을 위해 <code>.env</code> 파일에 저장하여 끌어 쓰는 것이 좋다!</em>** </p>
<blockquote>
<p>🔎 <strong>&#39;.env&#39;가 무엇인가요?</strong>
개발을 하다 보면 외부에 알려지면 안 되는 값, 예를 들면 git, 오픈 소스에 올리면 안되는 값들이 있다. 이 때, 변수를 파일에 따로 설정해두어 사용할 수 있게 환경변수를 저장하는 곳이다. <strong>CRA를 이용해 프로젝트를 생성했다면</strong> 별도의 설치 필요 없이 .env 파일을 생성하여 변수를 저장할 수 있고, 그렇지 않다면 <code>dotenv</code> 라이브러리를 설치하여 동일하게 이용한다. </p>
</blockquote>
<ul>
<li><code>dotenv</code>는 <code>yarn</code>, <code>npm</code>을 통해 설치할 수 있다. 
<code>yarn add dotenv</code> / <code>npm i --save dotenv</code></li>
</ul>
<p>✅ 프로젝트의 _최상위의 위치_에 파일이 존재해야 하며, <code>package-lock.json</code> 과 동일한 경로에 위치시키면 된다!
✅ <code>.gitignore</code> 파일에 <code>.env</code>를 추가해주어 외부에 파일이 노출되지 않도록 설정해준다. 
<img src="https://images.velog.io/images/da__hey/post/1b4e1be1-8c2e-4984-bb99-2bb81734c0c8/image.png" alt=""></p>
<hr>
<blockquote>
<p><strong>카카오톡 메시지 플랫폼 도구 이용하기</strong></p>
</blockquote>
<p>초대코드를 이용해 공유 URL을 전송하는 것이 목적이었으므로, <a href="https://developers.kakao.com/docs/latest/ko/message/js-link#default-template-msg">메시지 API</a>를 사용하였다. </p>
<p><img src="https://images.velog.io/images/da__hey/post/4045c466-3c42-47f0-9a4a-edd54470ed78/5.png" alt=""></p>
<p>내가 만든 공유 버튼을 누르면 위 함수가 실행되면서 원하는 사람에게 아래와 같은 양식의 메시지를 전송하게 된다. </p>
<p><img src="https://images.velog.io/images/da__hey/post/98b9d31e-7e7c-49f4-b177-ba7ffd5e4d98/image.png" alt=""></p>
<hr>
<h3 id="💭-문서와-친해지기">💭 문서와 친해지기</h3>
<p>처음엔 뭐가 뭔지 잘 모르겠어서 문서도 계속 읽어보고, 검색도 해보면서 어떻게 다루는지 알게 되니 재밌게 진행할 수 있었다. 내가 사용한 API 말고도 다양한 도구들이 제공되고 있어 다음에 프로젝트를 하게 되면 또 한번 다른 API를 사용해보고 싶다! </p>
<h3 id="📌-참고-블로그">📌 참고 블로그</h3>
<ul>
<li><a href="https://velog.io/@rjsdnql123/React%EC%97%90%EC%84%9C-dotenv%EC%82%AC%EC%9A%A9%ED%95%98%EB%8A%94%EB%B2%95">React에서 dotenv 사용하는법</a></li>
<li><a href="https://webruden.tistory.com/354">카카오톡 공유하기 API 초간단 사용법</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ React ] 함수 컴포넌트, JSX, Props & State]]></title>
            <link>https://velog.io/@da__hey/React-%ED%95%A8%EC%88%98-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8-JSX-Props-State</link>
            <guid>https://velog.io/@da__hey/React-%ED%95%A8%EC%88%98-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8-JSX-Props-State</guid>
            <pubDate>Tue, 06 Apr 2021 13:17:32 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>🐾 React 에는 <em>클래스 컴포넌트 와 함수 컴포넌트</em> 형태가 존재한다. 
🐾 React 는 <em>JSX</em> 를 통해 Element를 생성한다.
🐾 React 는 <em>Props</em> 와 <em>State</em> 를 통해 컴포넌트의 상태 값을 다룬다.</p>
</blockquote>
<h2 id="🚀-component">🚀 Component</h2>
<h3 id="클래스-컴포넌트">클래스 컴포넌트</h3>
<p>Life Cycle (생명 주기 기능)과 Props, State 를 사용한다.</p>
<h3 id="함수-컴포넌트">함수 컴포넌트</h3>
<p>초기 마운트 속도가 상대적으로 클래스 컴포넌트보다 빠르고, 불필요한 기능이 없으므로 메모리 자원을 절약할 수 있다.</p>
<p>📌 함수 컴포넌트에서도 클래스 컴포넌트의 생명 주기 메서드들과 State를 연결할 수 있는 <strong>HOOKS</strong>를 사용해 State를 사용할 수 있다.</p>
<blockquote>
<p>🔎 클래스 컴포넌트의 Life Cycle과 함수 컴포넌트의 HOOKS에 관해서는 다음 글에서 확인할 수 있다.</p>
</blockquote>
<hr>
<h2 id="🚀-jsx">🚀 JSX</h2>
<p>리액트에서는 Javascript의 모든 기능을 갖춘 JS의 확장 문법인 JSX를 이용하여 엘리먼트를 표현하고 생성한다. 표현하는 데에는 다음과 같은 규칙이 존재한다.</p>
<ul>
<li><p>태그는 꼭 <strong>닫혀야</strong> 한다.</p>
</li>
<li><p>2개 이상의 엘리먼트는 <strong>무조건 하나의 엘리먼트로</strong> 감싸져야 한다.
( 주로 <code>div</code>, <code>Fragment</code> , <code>&lt;&gt;</code> 등을 이용한다. )</p>
</li>
<li><p>조건부 렌더링 : <strong>삼항 연산자</strong> or <strong>AND 연산자</strong>를 이용해야한다. 
( if문을 사용할 수 없다. )</p>
</li>
<li><p><code>style</code> 은 객체 형태로, 클래스의 이름을 설정하는<code>class</code> 는 <code>className</code> 가 대신한다. </p>
<ul>
<li>대쉬 대신 두 문자 이상은 첫번째 문자 대문자!</li>
</ul>
</li>
</ul>
<h2 id="🚀-props--state">🚀 Props &amp; State</h2>
<p><strong>Props</strong> 는 Javascript에서 함수의 인자값과 같은 역할로, 함수 or 클래스에 인자를 제공하고 React 엘리먼트를 반환할 수 있게 한다. </p>
<ul>
<li>부모 컴포넌트가 자식 컴포넌트에게 주는 값으로, 변경 불가</li>
</ul>
<p><strong>State</strong> 는 Props와 유사하지만 비공개적이고, 컴포넌트 내부에서 변경할 수 있는 제어 가능한 데이터의 상태 값이라고도 한다.</p>
<ul>
<li>컴포넌트 내부에서 선언하여 변경할 수 있는 값 
  💡 <code>State</code>의 값은 <code>setState</code>을 통해 변경한다.
  💡 <code>setState</code>은 <strong>객체로 전달되는 값</strong>만 변경한다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ Typescript ] 컴파일러 옵션 세팅하기]]></title>
            <link>https://velog.io/@da__hey/Typescript-%EC%BB%B4%ED%8C%8C%EC%9D%BC%EB%9F%AC-%EC%98%B5%EC%85%98-%EC%84%B8%ED%8C%85%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@da__hey/Typescript-%EC%BB%B4%ED%8C%8C%EC%9D%BC%EB%9F%AC-%EC%98%B5%EC%85%98-%EC%84%B8%ED%8C%85%ED%95%98%EA%B8%B0</guid>
            <pubDate>Mon, 05 Apr 2021 14:20:43 GMT</pubDate>
            <description><![CDATA[<h2 id="compiler-options">Compiler Options</h2>
<ul>
<li><strong>최상위 프로퍼티 **
  ✔ **compilerOptions</strong><ul>
<li><code>type</code> : <code>@types</code> or <code>typeRoots</code><ul>
<li><code>typesRoots</code> : 타입 정의 파일 경로<ul>
<li><code>@types</code> : 패키지 이름</li>
</ul>
</li>
</ul>
</li>
<li><code>target</code> : 빌드의 결과물 버전 설정 (기본 ES3)</li>
<li><code>lib</code> : 기본 type definition 라이브러리 설정
  (지정하지 않으면, <pre><code>target : es3 -&gt; lib : lib.d.ts 사용,
target : es5 -&gt; lib : dom, es5, scripthost 사용,
target : es6 -&gt; lib : dom, es6, dom.iterable, scripthost 사용</code></pre><ul>
<li><code>outDir</code>, <code>outFile</code> : 하나의 파일로 output</li>
</ul>
</li>
<li><code>module</code> : 컴파일 된 모듈의 결과물을 어떤 모듈 시스템으로 할지 설정
  target : es6 -&gt; module : es6
  target :     -&gt; module : commonjs
✔ compileOnSave : 파일 저장 시, 자동 컴파일 여부
✔ extends
✔ files : 입력된 상대 혹은 절대 경로의 파일만 컴파일
✔ include, exclude : <code>.gitignore</code>와 같은 개념</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ Typescript ] 초기 개발 환경 세팅하기 ]]></title>
            <link>https://velog.io/@da__hey/Typescript-%EC%B4%88%EA%B8%B0-%EA%B0%9C%EB%B0%9C-%ED%99%98%EA%B2%BD-%EC%84%B8%ED%8C%85%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@da__hey/Typescript-%EC%B4%88%EA%B8%B0-%EA%B0%9C%EB%B0%9C-%ED%99%98%EA%B2%BD-%EC%84%B8%ED%8C%85%ED%95%98%EA%B8%B0</guid>
            <pubDate>Mon, 05 Apr 2021 14:20:11 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p><strong>Typescript</strong> 
<em>Compiled</em> Language, 정적 타입 언어
<strong>Javascript</strong> 
<em>Interpreted</em> Language, 동적 타입 언어</p>
</blockquote>
<h3 id="🔥-typescript---compiling---javascript-">*<em>🔥 Typescript -&gt; Compiling -&gt; Javascript *</em></h3>
<ul>
<li><p><em>Compiled</em> : 컴파일이 필요한</p>
</li>
<li><p>_Interpreted _: 컴파일러가 필요없는</p>
</li>
<li><p>정적 타입 언어 : 타입이 정해져 있는</p>
</li>
<li><p>동적 타입 언어 : 타입을 자유롭게 변환할 수 있는</p>
</li>
</ul>
<blockquote>
<p>Javascript는 엄격한 규칙이 없고, 코드 관리도 편해 사용하기 쉽다는 장점이 있지만, 규모가 큰 프로젝트를 진행하거나 버그를 최소화 하고 싶을때 한계점이 존재한다. 이로 인해 Typescript가 탄생하게 되었다. Typescript는 언어의 타입을 예측 가능하고, 읽기 쉬운 코드로 Javascript를 더욱 효율적으로 사용할 수 있게 해준다.</p>
</blockquote>
<hr>
<h2 id="🚀-개발-환경-구축하기">🚀 개발 환경 구축하기</h2>
<ul>
<li>프로젝트 생성 후, <code>npm init -y</code>를 통해 package.json 생성</li>
<li><code>npm i typescript</code> - typescript 모듈 설치</li>
</ul>
<blockquote>
<p>👀 <strong><code>-global</code>로 설치하지 않았을 경우,</strong>
다음과 같은 방법으로 프로젝트 내의 컴파일러인 tsc를 이용해서 컴파일한다. 
=&gt; <code>./node_modules/.bin/</code> 안의 명령어로 컴파일</p>
</blockquote>
<ul>
<li><p>npm script에서는 <code>./node_modules/.bin/</code> 내의 명령어는 상대경로를 쓰지 않아도 사용하여 컴파일 될 수 있게 한다.
<img src="https://images.velog.io/images/da__hey/post/82bf120b-bb59-456e-bfbc-1910882bccd4/image.png" alt=""></p>
</li>
<li><p><strong>npm script를 통해 컴파일</strong>
  package.json 파일에 다음과 같이 추가해준다.
<img src="https://images.velog.io/images/da__hey/post/ae9d4366-04fc-4dfd-9edf-6c2a538d26e5/image.png" alt="">
<code>npm run tranpile</code> 을 실행하면, 프로젝트에 test.js 파일이 생성된다.
<img src="https://images.velog.io/images/da__hey/post/e87879d0-5b79-485a-825f-6d5f6dd815bd/image.png" alt=""></p>
</li>
</ul>
<hr>
<h2 id="🚀-초기-환경-세팅">🚀 초기 환경 세팅</h2>
<p>( 모든 명령어는 global로 설치했을 경우로 작성하였다. )</p>
<h3 id="tsc---init"><code>tsc --init</code></h3>
<p><code>tsconfig.json</code> default 파일을 생성한다.</p>
<h3 id="tsc--w"><code>tsc -w</code></h3>
<p>파일이 변경될 때마다 자동으로 컴파일해주는 검사 도구</p>
<h3 id="npm-i-tslint--d"><code>npm i tslint -D</code></h3>
<blockquote>
<p>tslint
Javascript 소스 코드가 코딩 규칙을 준수하는지 확인해주는 코드 분석 도구
<code>tslint --init</code>을 통해 tslint.json 생성</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ RESTful ] REST와 RESTful 알기]]></title>
            <link>https://velog.io/@da__hey/zemww5x6</link>
            <guid>https://velog.io/@da__hey/zemww5x6</guid>
            <pubDate>Mon, 05 Apr 2021 14:19:36 GMT</pubDate>
            <description><![CDATA[<h2 id="rest-란">REST 란,</h2>
<p>Representational State Transfer, 정보를 얻고자 하는 자원에 고유한 이름을 붙혀, 해당 자원의 상태를 서버와 클라이언트 간 주고 받는 것을 의미한다.</p>
<h2 id="rest-의-특징은">REST 의 특징은,</h2>
<p>REST 방법론을 이용해 API를 설계했을 때 아래와 같은 특징을 지닌다.</p>
<p>  <strong>1) 서버/클라이언트 (Server-Client) 구조</strong>
      자원에 대해 클라이언트는 request, 서버는 response 하는 구조로 각각의 역할이 확실하게 구분되고, 일관적인 인터페이스로 분리되어 작동할 수 있다.</p>
<p>  <strong>2) 무상태성 (Stateless)</strong>
      서버는 세션, 쿠키 정보를 별도로 관리하지 않고, 데이터의 상태정보를 기억할 필요 없이, 클라이언트 사이드에서 들어온 요청에 대해서만 처리해주면 되기 때문에 구현이 쉽고 단순해진다.</p>
<p>  <strong>3) 캐시 처리 가능 (Cacheable)</strong>
      클라이언트는 응답 데이터를 캐싱할 수 있어야한다.</p>
<p>  <strong>4) 자체 표현 구조 (Self-descriptiveness)</strong>
      JSON형태의 구조로 구성되어, REST API 메시지를 만 확인하고도 어떤 메서드로 무슨 요청을 하고 있는지 직관적으로 이해가 가능하다.</p>
<p>  <strong>5) 계층형 구조</strong>
      서버의 계층을 다중으로 구성하여, 보안, 암호화 계층 등을 추가하여 구조상의 자유도를 높일 수 있다. Proxy, Gateway와 같은 네트워크 기반의 중간매체 사용도 가능하다. 
      ex) 사용자 인증을 위해 request 헤더에 토큰을 추가하여 서버에서 인증 절차를 거칠 수 있게 한다.</p>
<h2 id="restful-api">RESTful API</h2>
<h3 id="⚠️-uri-설계-시-주의할-점">⚠️ <strong>URI 설계 시 주의할 점</strong></h3>
<ul>
<li>슬래시 구분자(/)는 계층 관계를 나타내는 것에 사용한다.</li>
<li>URI 마지막 문자에 슬래시(/)를 포함하지 않는다.</li>
<li>파일확장자는 URI에 포함하지 않는다.</li>
<li>밑줄(_)은 URI에 포함하지 않으며, 하이픈(-)을 이용하여 가독성을 높인다.</li>
<li>URI 경로에는 소문자가 적합하다.</li>
</ul>
<h3 id="method-방식"><strong>Method 방식</strong></h3>
<p>대표적으로 사용하는 Method는 GET, POST, PUT, DELETE 이다.</p>
<p>🚀 <strong><code>GET</code> 방식</strong></p>
<ul>
<li><code>GET</code>을 통해 해당 자원을 조회하고, 가져올 수 있다.</li>
<li>주소창에 쿼리 스트링이 그대로 노출되어 보안성이 낮다.</li>
<li><code>POST</code> 보다 상대적으로 전송 속도가 빠르다.</li>
</ul>
<hr>
<p>🚀** <code>POST</code> 방식**</p>
<ul>
<li><code>POST</code>를 통해 해당 URI를 요청하면, 자원을 생성한다.
즉, 클라이언트에서 서버로 일정 크기 이상의 데이터를 전송한다. </li>
<li>주소창에 전송 데이터의 정보가 노출되지 않아 <code>GET</code>에 비해 보안성이 높다.</li>
<li><code>GET</code> 보다 속도가 느리다.</li>
<li>서버로 데이터를 전송하기 전 인코딩하고, 전송 후 서버에서 디코딩 작업을 해주어야 한다.</li>
</ul>
<blockquote>
<p>🔎 더 알아보기 : <code>GET</code> vs <code>POST</code> 차이
프로젝트를 진행하면서 <code>GET</code>과 <code>POST</code>의 차이에 대해서 궁금했다. 어떤 상황, 어떤 상태에 맞게 자원을 관리해야하는지 REST의 개념에 더 접근하여 알아보려 한다.
<code>GET</code> 방식
    - 클라이언트에서 서버에 데이터를 요청할 때 주로 사용
    - 전달되는 데이터가 255개의 문자를 초과하면 문제가 발생할 수 있다. 
<code>POST</code> 방식
    - 클라이언트에서 서버로 데이터를 전송할 때 주로 사용
    - 서버에 많은 데이터를 전송하기 위해서 주로 사용</p>
</blockquote>
<hr>
<p>🚀 <strong><code>PUT</code> 방식</strong></p>
<ul>
<li>해당 자원의 전체 교체 및 수정이 필요할 때 사용한다.
🚀 <code>DELETE</code> 방식</li>
<li>해당 자원을 삭제할 때 사용한다.</li>
</ul>
<hr>
<h2 id="💭">💭</h2>
<p>REST에 대한 개념은 알고 있었지만, 추상적이었기에 정확히 어떤 과정을 의미하는지 모르고 있었다. 서버와 클라이언트 간의 데이터를 주고받는 프로젝트를 통해 react-router와 fetch를 더 자세히 공부해보고 실습해보면서, RESTful한 API의 설계 원리에 대해 확실히 알게 된 것 같다. 다만 앞으로 여러 다양한 상황에서 자원을 관리해보면서, 각각의 역할에 맞는 메소드를 활용해 RESTful한 방식에 대해 더 알아가야할 것 같다고 느꼈다 😊 </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ React ]  React-Router Component & Hooks 까지 알아보자!]]></title>
            <link>https://velog.io/@da__hey/React-React-Router-%EA%B3%B5%EB%B6%80%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@da__hey/React-React-Router-%EA%B3%B5%EB%B6%80%ED%95%98%EA%B8%B0</guid>
            <pubDate>Sun, 04 Apr 2021 11:25:10 GMT</pubDate>
            <description><![CDATA[<blockquote>
<h1 id="react-router">React-Router</h1>
<p>사용자의 브라우저가 클라이언트 사이드에서 <strong>뷰 렌더링</strong>을 담당하도록 돕는 라이브러리 </p>
</blockquote>
<p>💡 서버 사이드 렌더링을 할 때에도 라우팅을 도와주는 컴포넌트들을 제공해준다.</p>
<h2 id="라이브러리-설치하기">라이브러리 설치하기</h2>
<p>프로젝트 디렉토리로 이동하여 다음 명령어를 통해 리액트 라우터를 설치한다.</p>
<pre><code>yarn add react-router-dom</code></pre><hr>
<h2 id="1-components-🔥">1. Components 🔥</h2>
<h3 id="route"><code>Route</code></h3>
<ul>
<li>현재 URL 경로와 매치될 경우 보여줄 컴포넌트를 지정하는데 사용하는 컴포넌트
➰ props &gt; <code>path</code> : 매치시킬 경로, <code>component</code> : 보여줄 컴포넌트</li>
</ul>
<pre><code>&lt;Route path=&quot;/home&quot; component={Home} /&gt;</code></pre><hr>
<h3 id="link"><code>Link</code></h3>
<ul>
<li>HTML의 <code>&lt;a&gt;</code>태그와 동일한 역할을 하는 컴포넌트
➰ props &gt; <code>to</code> : 이동할 경로를 지정</li>
</ul>
<pre><code>&lt;Link to=&quot;/home&quot;&gt;This is home&lt;/Link&gt;</code></pre><p> 👉 &#39;This is home&#39; 텍스트는 클릭할 수 있게 렌더링 되어 클릭 시, 주소창 경로는 &#39;.../home&#39;으로 변경된다.</p>
<hr>
<h3 id="router"><code>Router</code></h3>
<ul>
<li><code>Route</code>, <code>Link</code> 컴포넌트가 함께 동작할 수 있도록 연결시켜주는 컴포넌트로, 항상 <code>Router</code>를 공통 상위 컴포넌트로 가져야한다.
➰ props &gt; <code>history</code></li>
</ul>
<pre><code>&lt;Router&gt;
    ...
    &lt;Route /&gt;
    &lt;Route /&gt;
    ...
&lt;/Router&gt;</code></pre><ul>
<li><a href="https://reactrouter.com/web/api/Router"><code>Router</code>의 종류</a>에는 <code>BrowserRouter</code>, <code>HashRouter</code>, <code>withRouter</code> 등이 존재한다.</li>
</ul>
<blockquote>
<p>🔎 ** 더 알아보기 **</p>
</blockquote>
<h3 id="history"><code>history</code></h3>
<p>리액트에서 <code>Router</code>들은 props로 <code>history</code> 객체를 주고 받으며 페이지의 기록을 공유한다.
<code>history</code> 객체를 콘솔로 확인해보면 다양한 메소드와 관련 객체들이 존재한다. 가장 빈번하게 사용되는 메소드는 <code>push()</code>인데, 이는 <code>history.push(&#39;이동하고자 하는 path&#39;)</code>를 통해 원하는 컴포넌트로 이동이 가능하다.
** 1. <code>history</code> 객체 **
<img src="https://images.velog.io/images/da__hey/post/3839e648-6369-4e8d-b60a-905c560d5262/image.png" alt="">
** 2. 예제 코드 **
<img src="https://images.velog.io/images/da__hey/post/9b675aad-5e05-4901-9016-53b03615e8e8/image.png" alt=""></p>
<ul>
<li><code>props</code>로 받은 history의 메소드 <code>push</code>를 이용해 <code>pathname</code>과 <code>state</code>가 담긴 객체를 <code>pathname</code>에 적힌 경로로 전달하는 코드이다.</li>
</ul>
<hr>
<h3 id="hashrouter"><code>HashRouter</code></h3>
<ul>
<li>주소창에 해쉬(#)가 붙는다.</li>
<li>검색 엔진이 읽지 못하기에 거의 사용되지 않는다.
  ( 백엔드가 필요하지 않은 상황에 주로 사용 )</li>
</ul>
<hr>
<h3 id="browserrouter"><code>BrowserRouter</code></h3>
<ul>
<li>HTML5의 <code>history</code> API를 활용한 라우터</li>
<li>주로 사용되는 라우터</li>
</ul>
<hr>
<h3 id="switch"><code>Switch</code></h3>
<ul>
<li>모든 <code>Router</code> 컴포넌트들을 반복하며, 현재 URL과 <code>path</code>가 일치하는 첫번째 요소만 렌더링 하여 라우터 충돌을 막도록 하는 컴포넌트<pre><code>&lt;Router&gt;
&lt;Switch&gt;
   &lt;Route exact path=&quot;/&quot; component = { Main }/&gt;
   &lt;Route path = &quot;/about&quot; component = { About }/&gt;
&lt;/Switch&gt;
&lt;/Router&gt;</code></pre><blockquote>
<p>🔎 ** 더 알아보기 **</p>
</blockquote>
<pre><code>&lt;Router&gt;
&lt;Route exact path=&quot;/&quot; component = { Main }/&gt;
&lt;Route path = &quot;/about&quot; component = { About }/&gt;
&lt;Route path = &quot;/detail&quot; component = { Detail }/&gt;
&lt;Route component = { Error }/&gt;
&lt;/Router&gt;</code></pre>만약, 3가지 <code>path</code>(1<del>3줄)와 일치하지 않아 어떠한 URL로도 이동할 수 없는 경우에 <code>Error</code> 컴포넌트를 띄우기 위해 4번째 줄과 같이 <code>Route</code>를 추가해보자. 실제로 실행시켜보면 어떠한 URL에도 <code>Error</code> 컴포넌트가 렌더링 되는 것을 볼 수 있다.
👉 왜냐하면, 4번째 줄은 매칭시킬 <code>path</code>의 값이 없으므로 ~</del>무조건적으로 렌더링~~이 되기 때문이다.
이를 해결하기 위해 <code>Switch</code>가 등장하였고, 위 코드는 다음으로 해결할 수 있다.<pre><code>&lt;Router&gt;
&lt;Switch&gt;
  &lt;Route exact path=&quot;/&quot; component = { Main }/&gt;
  &lt;Route path = &quot;/about&quot; component = { About }/&gt;
  &lt;Route path = &quot;/detail&quot; component = { Detail }/&gt;
  &lt;Route component = { Error }/&gt;
&lt;/Switch&gt;
&lt;/Router&gt;</code></pre>❔ <code>exact</code> : 정확히 동일한 <code>path</code>가 들어왔을 경우에만 컴포넌트를 렌더링 하도록 하여 중복 컴포넌트 렌더링을 막는다.</li>
</ul>
<h2 id="2-hooks-🔥">2. Hooks 🔥</h2>
<ul>
<li><p>class 작성 필요 없이 상태값(state)와 Hooks를 통해 react-router의 기능들을 이용할 수 있다.</p>
</li>
<li><p>Hooks를 사용하기 전에 match, location, history의 역할에 대해서도 이해할 수 있도록 하자.</p>
</li>
</ul>
<h3 id="uselocation"><code>useLocation</code></h3>
<blockquote>
<p>🐾 <code>location</code> 객체는 현재 페이지의 정보를 가진다. 대표적으로 <code>location.search</code>로 현재 <code>url</code>의 쿼리 스트링을 가져올 수 있다</p>
</blockquote>
<p>🚀 <strong>사용 예시</strong></p>
<pre><code>const location = useLocation();</code></pre><p>다음은 네이버 영어 사전에 &#39;hello&#39;를 검색한 후 <code>location</code>을 확인했을 때의 결과이다.</p>
<p><img src="https://images.velog.io/images/da__hey/post/24a75d06-ec7b-4555-a3d3-f53127eff626/image.png" alt=""></p>
<p><img src="https://images.velog.io/images/da__hey/post/4de25590-cdb8-4306-b3b5-faf60999ac72/image.png" alt=""></p>
<p><code>location</code> 객체 내의 <code>search</code>메소드를 통해 쿼리스트링 결과값을 가져올 수 있다.</p>
<hr>
<h3 id="usehistory"><code>useHistory</code></h3>
<blockquote>
<p>🐾 <code>history</code> 객체는 <strong>브라우저의 이동 기록</strong>들을 가지고 있다. 스택(stack)에 <strong>현재까지 이동한 url 경로들이 담겨있는</strong> 형태로, 주소를 임의로 변경하거나 되돌아갈 수 있도록 해준다</p>
</blockquote>
<p>🚀 <strong>사용 예시</strong></p>
<pre><code>const history = useHistory();

history.push(&#39;/&#39;);</code></pre><p>💡 function component에서도 다음을 통해 페이지 이동 시 <strong>객체를 전달</strong>할 수 있다.</p>
<pre><code>history.push({
    pathName: &#39;/&#39;,
    state: { 
        isOk: true,
        root: main
    }
});</code></pre><p>-&gt; 이동한 페이지의 <code>location.state</code>를 확인하면 전송된 객체의 값들을 가져올 수 있다.</p>
<p><img src="https://images.velog.io/images/da__hey/post/3f9dbb7e-c83e-4e5b-b6b6-5585f686610f/image.png" alt=""></p>
<hr>
<h3 id="useroutematch"><code>useRouteMatch</code></h3>
<blockquote>
<p><code>match</code> 객체에는 <code>Route</code>의 <code>path</code>와 <code>url</code>이 매칭된 대한 정보가 담겨진다. 대표적으로 <code>match.params</code>로 <code>path</code>에 설정한 파라미터값을 가져올 수 있다.</p>
</blockquote>
<p>🚀 <strong>사용 예시</strong></p>
<pre><code>const match = useRouteMatch();</code></pre><p><img src="https://images.velog.io/images/da__hey/post/e03082d4-c897-49cf-b626-5ff053c532b8/image.png" alt=""></p>
<p>❔ <code>match</code> : <code>Route</code> 컴포넌트의 props인 <strong><code>path</code>가 URL에 어떻게 match 되는가</strong>에 대한 정보를 담는 객체</p>
<hr>
<h3 id="useparams"><code>useParams</code></h3>
<ul>
<li>현재 <code>Route</code> 컴포넌트의 <a href="https://reactrouter.com/web/api/match"><code>match.params</code></a> 에 접근해 사용할 수 있도록 한다.</li>
</ul>
<p><code>Main</code> 페이지에서 <code>history.push</code>를 통해 <code>first</code> 페이지로 이동할 때, <code>pathname</code>에 <code>id</code>를 붙여서 푸시해보자. 
<img src="https://images.velog.io/images/da__hey/post/3d0fb473-46ce-443c-9d69-ca6e5b5e347b/image.png" alt=""></p>
<p><code>Route</code>의 속성인 <code>path</code>에는 아래 사진에서 볼 수 있듯이 <code>:id</code>를 추가해주자.</p>
<p><img src="https://images.velog.io/images/da__hey/post/79a2011d-ac14-4407-a9db-3e5a4a2d916f/image.png" alt=""></p>
<p><code>first</code> 페이지에서 <code>params</code>를 확인해보면 <code>main</code> 페이지에서 <code>first</code>로 보낸 <code>params</code> 즉, <code>id</code>값이 <code>url</code>과 페이지에 전송된 것을 확인할 수 있다.</p>
<p><img src="https://images.velog.io/images/da__hey/post/8c3d8e9a-f8c4-4f65-99d3-2eed45b386ad/image.png" alt=""></p>
<hr>
<h2 id="💭">💭</h2>
<p>공식 api 문서와 블로그를 통해 실제로 실습해보고 공부하며 글을 정리해보았지만 실제로 많이 사용해보고 익숙해져야 할 것 같다. </p>
]]></description>
        </item>
    </channel>
</rss>