<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>jjung-developer.log</title>
        <link>https://velog.io/</link>
        <description>🧚🏻‍♀️ Front-End Developer</description>
        <lastBuildDate>Thu, 20 Jul 2023 12:59:21 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>jjung-developer.log</title>
            <url>https://images.velog.io/images/jjung-developer/profile/1a219117-f30e-4b8e-b1a9-117d9e632a06/KakaoTalk_Photo_2021-05-19-19-16-12.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. jjung-developer.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/jjung-developer" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[Android] 왜 play store에 앱 검색이 안될까?]]></title>
            <link>https://velog.io/@jjung-developer/Android-%EC%99%9C-play-store%EC%97%90-%EC%95%B1-%EA%B2%80%EC%83%89%EC%9D%B4-%EC%95%88%EB%90%A0%EA%B9%8C</link>
            <guid>https://velog.io/@jjung-developer/Android-%EC%99%9C-play-store%EC%97%90-%EC%95%B1-%EA%B2%80%EC%83%89%EC%9D%B4-%EC%95%88%EB%90%A0%EA%B9%8C</guid>
            <pubDate>Thu, 20 Jul 2023 12:59:21 GMT</pubDate>
            <description><![CDATA[<p>앱을 오픈한지 9개월..
나는 맥북 + 아이폰 조합을 쓰기 때문에 안드로이드 핸드폰은 테스트용으로 있고, 윈도우는 접해본지가 언젠지 기억도 안난다...🫠</p>
<p>아무튼! MIT님이 제보해주신 오류 내용</p>
<pre><code>&#39; 웹 구글 플레이 스토어에서 앱 검색이 되지 않는다&#39;</code></pre><p>라는 내용이었다</p>
<p>엥..? 왜...?
(맨날 하는 말)</p>
<p>바로 구글링에 들어갔다.</p>
<h4 id="결론--우리-앱에서-사용하는-안드로이드-내장-기능-권한이-있는데-ex-카메라-위치-등등-그-권한을-사용-할-수-없는-디바이스의-경우-앱-매칭이-되지-않아-검색이-되지-않는-것"><strong>결론 : 우리 앱에서 사용하는 안드로이드 내장 기능 권한이 있는데 (ex 카메라, 위치 등등) 그 권한을 사용 할 수 없는 디바이스의 경우 앱 매칭이 되지 않아 검색이 되지 않는 것</strong></h4>
<p>구글 플레이에서 앱을 필터링 할 수 있는 element가 있다.
다양하게 있는데 오늘 사용 할 element는 </p>
<pre><code>&lt;uses-feature&gt;</code></pre><p><strong>uses-feature</strong>의 옵션은 name, required, glEsVersion이 있는데
<strong>name</strong>에는 사용한 하드웨어 or 소프트웨어 기능의 name을 
<strong>required</strong>는 boolean값이 들어가는데, ture를 넣을 경우 디바이스에서 명시된 기능을 사용 할 수 없을 때 설치를 할 수 없도록 설정
false를 넣을 경우 디바이스에서 해당 기능을 사용 할 수 없더라도 설치를 할 수 있도록 허용</p>
<p>그렇다면, 어떠한 권한들을 사용하면 이러한 제한이 생기는걸까?</p>
<p><a href="https://developer.android.com/guide/topics/manifest/uses-feature-element?hl=ko#hw-features">공식문서</a>에 아주 잘 나와있음!</p>
<p>우리 앱은 카메라 권한을 사용하고 있었기 때문에
<img src="https://velog.velcdn.com/images/jjung-developer/post/9f164f44-a8fb-4f7a-b7fc-546efa34d92c/image.png" alt="">
공식 문서에 따라 uses-feature 코드를 추가 해주었다.</p>
<pre><code>&lt;uses-feature android:name=&quot;android.hardware.camera&quot; android:required=&quot;false&quot; /&gt;
&lt;uses-feature android:name=&quot;android.hardware.camera.autofocus&quot; android:required=&quot;false&quot; /&gt;</code></pre><p>정말 기본적인 설정 오류를 이제서야 발견했다니 ㅠㅠ
RN을 작업하다보면 IOS , Android오류들을 많이 보게되는데 Native 코드와 설정을 건드는것은 늘 어려운것 같다 🫠</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[SVG]]></title>
            <link>https://velog.io/@jjung-developer/9mc1w84y</link>
            <guid>https://velog.io/@jjung-developer/9mc1w84y</guid>
            <pubDate>Mon, 08 Aug 2022 14:38:17 GMT</pubDate>
            <description><![CDATA[<h1 id="svg">SVG</h1>
<h1 id="1-svgscalable-vector-graphics란">1. SVG(Scalable Vector Graphics)란?</h1>
<p><img src="https://velog.velcdn.com/images/jjung-developer/post/5b663a5c-ae6e-4c98-9df9-27964225e1ff/image.png" alt=""></p>
<ul>
<li>확장가능한 벡터 그래픽 (벡터 이미지는 Pixcel이 아닌 점과 점 사이를 계산하여 그리는 이미지)</li>
<li>픽셀을 이용하여 그림을 그리는 <code>png</code>  <code>jpg</code> 파일들과 다르게 벡터를 기반으로 이미지를 표현</li>
</ul>
<br>
<br>

<h1 id="2-svg를-사용해야-하는-이유">2. SVG를 사용해야 하는 이유</h1>
<p><img src="https://velog.velcdn.com/images/jjung-developer/post/ce4b226a-97da-4545-bd5c-3a461ffa157e/image.png" alt=""></p>
<ul>
<li>XML 포맷으로 파일이 작성되므로 HTML, JS, CSS로 조작이 가능합니다.
⇒ 텍스트 에디터로 작성하고 또 작성된 이미지를 수정할 수 있음</li>
<li>벡터를 기반으로 그려지므로 사이즈를 크게 해도 깨지지 않고 파일 크기가 동일합니다.
⇒ Web에서 Device의 Ratio를 대응하기 위해 기존 사이즈보다 x2된 사진으로 대응하는데 SVG를 사용하면 자동으로 대응되게 되어 원본과 x2를 모두 준비할 필요가 없습니다.</li>
<li>복잡한 이미지의 경우 용량이 일반 이미지보다 클 수도 있지만, SVGO(웹기반 GUI SVGOMG)와 같은 도구를 이용하면 SVG 파일 크기를 30~ 60% 이상 쉽게 압축이 가능합니다.</li>
<li>SVG 파일은 코드가 아닌 텍스트로 작성됩니다. 스크린 리더와 검색 엔진이 이를 분석할 수 있으므로 접근성 및 SEO 목적에 적합합니다.
⇒ 페이지 로딩 시간은 검색 엔진 순위의 또 다른 중요한 요소입니다.</li>
</ul>
<br>
<br>


<h1 id="3-svg-만들기">3. SVG 만들기</h1>
<blockquote>
<p>웹을 위한 SVG 제작 과정은 매우 간단합니다. 
선호하는 벡터 그래픽 편집기 (Illustrator, Sketch, Inkscape [무료], [shape 레이어를 사용하는 경우 Photoshop에서도 가능])에서 작업 할 수 있습니다.
저희가 사용하는 XD와 가장 많이 사용하는 Illustratord을 중심으로 설명하겠지만, 모든 소프트웨어에도 동일하게 적용하여 작업할 수 있습니다.</p>
</blockquote>
<h2 id="3-1--adobe-xd">3-1.  Adobe XD</h2>
<p><strong>macOS ⇒</strong> 오브젝트 또는 아트보드를 선택하고 <strong>파일</strong> &gt; <strong>내보내기</strong>로 이동하거나 <strong>Cmd + E</strong>를 누릅니다.
<strong>windows</strong> ⇒ 오브젝트 또는 아트보드를 선택하고 <strong>파일</strong> &gt; <strong>내보내기</strong>로 이동합니다.</p>
<p><img src="https://velog.velcdn.com/images/jjung-developer/post/330b6034-9de2-4a3e-a9a9-72350a633804/image.png" alt="">
<img src="https://velog.velcdn.com/images/jjung-developer/post/aa0b90c8-8b26-456d-9367-4abab8f2a6d3/image.png" alt=""></p>
<ul>
<li><strong>프레젠테이션 속성</strong>: 각 SVG 태그에서 각 스타일 속성에 대해 별도의 XML 속성을 사용합니다. 이 포맷은 SVG 에셋을 Android Studio와 함께 사용해야 합니다.</li>
<li><strong>내부 CSS</strong>: CSS 클래스와 함께 단일 스타일 태그를 사용하고 오브젝트 사이의 스타일링 설정을 동일한 스타일과 공유하여 파일 크기를 줄입니다.</li>
<li><strong>임베드</strong>: 비트맵 이미지가 SVG 파일로 인코딩됩니다.</li>
<li><strong>링크</strong>: 비트맵 이미지가 SVG 파일에 대한 참조와 별개로 저장됩니다.</li>
</ul>
<h2 id="3-2--adobe-illustrator">3-2.  Adobe illustrator</h2>
<p><strong>파일 &gt; 내보내기 &gt; SVG</strong>를 선택합니다.</p>
<p><img src="https://velog.velcdn.com/images/jjung-developer/post/5860a538-e608-49db-9ed8-5b58363fc0d2/image.png" alt="">
<img src="https://velog.velcdn.com/images/jjung-developer/post/d24800fe-7ec7-4881-b807-9563626c8511/image.png" alt=""></p>
<ul>
<li><p><strong>프레젠테이션 속성</strong>: 각 SVG 태그의 개별 스타일 속성에 대해 별도의 XML 속성을 사용합니다. 이 형식은 Android Studio에서 SVG 에셋을 사용하는 데 필요합니다.</p>
</li>
<li><p><strong>내부 CSS</strong>: 스타일이 동일한 객체 사이에서 스타일 지정 설정을 공유하는 CSS 클래스를 포함하는 단일 &#39;<style>&#39; 태그를 사용합니다. 이로 인해 파일 크기가 더 작아질 수 있습니다.</p>
</li>
<li><p><strong>인라인 스타일</strong>: CSS 구문으로 결합된 모든 태그의 스타일 속성을 포함하는 SVG 태그별로 단일 &#39;style&#39; 속성을 사용합니다.</p>
</li>
<li><p><strong>디테일한 속성들 보기</strong></p>
<ul>
<li><strong>글꼴</strong>. SVG 파일에 나타낼 글꼴을 선택합니다. 윤곽선은 패스 정의를 보존하며 , 호환성이 가장 높습니다.</li>
<li><strong>이미지</strong>: 이미지를 문서 내에 포함된 이미지로 저장할 것인지 또는 문서에 대한 외부 파일로 연결할 것인지 선택합니다.</li>
<li><strong>개체 ID</strong>: ID 유형(이름)을 SVG 파일의 개체에 지정하는 방법을 선택합니다. 레이어 이름, 최소 또는 고유 중에서 선택합니다. 이 옵션은 개체의 복제 이름을 처리하는 방식과 내보낸 CSS 파일에서 개체의 이름이 지정되는 방식을 결정합니다.</li>
<li><strong>10진수</strong>: 개체 위치의 정밀도를 위해 유지할 정보의 양을 선택합니다. 십진수 값이 클수록 개체가 배치되는 방법의 정밀도가 늘어나며, 이 경우 렌더링된 SVG를 시각적으로 정확하게 볼 수 있습니다. 하지만 십진수 값을 늘리면 결과로 내보낸 SVG의 파일 크기도 늘어납니다.</li>
<li><strong>축소</strong>: 빈 그룹과 빈 공간을 제거하여 SVG의 파일 크기를 최적화합니다. 이 옵션을 선택하면 결과 SVG 코드의 가독성이 줄어듭니다.</li>
<li>반응형. 이 옵션을 선택하면 생성된 SVG의 크기가 브라우저 내에서 조절됩니다. 기록된 절대 크기 값은 없습니다.</li>
<li><strong>코드 표시</strong>: 내보낸 내용을 기본 텍스트 편집기에서 엽니다.</li>
<li><strong>브라우저에 표시</strong> (아이콘): 이미지를 기본 웹 브라우저에 표시합니다.</li>
</ul>
</li>
</ul>
<br>
<br>



<h1 id="4-svg-사용하기">4. SVG 사용하기</h1>
<blockquote>
<p>웹에서 SVG를 사용하는 방법은 다양합니다.
해상도 독립성 및 파일 용량의 최소화를 위해서는, 
SVG를 일반 이미지 형식과 같이 <code>&lt;img&gt;</code>로 참조하거나, CSS에서 <code>background-image</code>
로 참조합니다.</p>
</blockquote>
<h2 id="4-1--img">4-1. &lt; Img &gt;</h2>
<p>일반 이미지와 같이 SVG를 사용할 수 있습니다. <strong>이 메서드는 조작 기능을 제한</strong>합니다.</p>
<pre><code class="language-html">&lt;img src=&quot;sample.svg&quot; alt=&quot;sample Logo&quot; height=&quot;65&quot; width=&quot;68&quot;&gt;</code></pre>
<h2 id="4-2-background-image">4-2. <strong>Background-image</strong></h2>
<p>인코딩을 하면 다운로드하는 동안 나머지 스타일 로딩을 차단시키기 때문에 사용하지 않는 편이 좋습니다. 
<strong>이 메서드는 조작 기능을 제한</strong>합니다.</p>
<pre><code class="language-html">.logo {
  background-image: url(sample.svg);
}</code></pre>
<h2 id="4-3-inline">4-3. <strong>Inline</strong></h2>
<p>SVG 코드를 인라인하면 HTTP 요청은 저장되지만, 이미지는 브라우저에 캐시되지 않습니다. 
조작이 가장 쉬운 방법이지만, 인라인 SVG 코드를 유지하는 것은 어려울 수 있습니다.</p>
<pre><code class="language-html">&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; viewBox=&quot;0 0 68 65&quot;&gt;
  &lt;path fill=&quot;#1A374D&quot; d=&quot;M42 27v-20c0-3.7-3.3-7-7-7s-7 3.3-7 7v21l12 15-7 15.7c14.5 13.9 35 2.8 35-13.7 0-13.3-13.4-21.8-26-18zm6 25c-3.9 0-7-3.1-7-7s3.1-7 7-7 7 3.1 7 7-3.1 7-7 7z&quot;/&gt;
  &lt;path d=&quot;M14 27v-20c0-3.7-3.3-7-7-7s-7 3.3-7 7v41c0 8.2 9.2 17 20 17s20-9.2 20-20c0-13.3-13.4-21.8-26-18zm6 25c-3.9 0-7-3.1-7-7s3.1-7 7-7 7 3.1 7 7-3.1 7-7 7z&quot;/&gt;
&lt;/svg&gt;</code></pre>
<h2 id="4-4--object">4-4. &lt; Object &gt;</h2>
<p><code>&lt;object&gt;</code>요소는 <code>HTML</code>문서 내에 직접 내장(inline)시키지 않고 SVG를 조작하는 경우에 가장 좋은 방법입니다.</p>
<pre><code class="language-html">&lt;object type=&quot;image/svg+xml&quot; data=&quot;sample.svg&quot;&gt;샘플 이미지 입니다.&lt;/object&gt;</code></pre>
<table>
<thead>
<tr>
<th></th>
<th>Object</th>
<th>Inline</th>
<th>Img</th>
<th>Background-image</th>
</tr>
</thead>
<tbody><tr>
<td>CSS 조작</td>
<td>O</td>
<td>O</td>
<td>일부 inline</td>
<td>일부 inline</td>
</tr>
<tr>
<td>JS 조작</td>
<td>O</td>
<td>O</td>
<td>X</td>
<td>X</td>
</tr>
<tr>
<td>SVG 조작</td>
<td>O</td>
<td>O</td>
<td>O</td>
<td>O</td>
</tr>
<tr>
<td>SVG 애니메이션</td>
<td>O</td>
<td>O</td>
<td>X</td>
<td>X</td>
</tr>
</tbody></table>
<br>
<br>



<h1 id="5-css-조작">5. CSS 조작</h1>
<blockquote>
<p>SVG의 가장 큰 장점은 CSS 사용해 스타일을 변경할 수 있다는 것입니다. 
일부 페이지에서 파란색 아이콘을 주황색으로 바꾸고 싶을 때, 
새 파란색 아이콘을 다시 만들지 않아도 됩니다.</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/jjung-developer/post/5c7a7185-298b-4259-bb0a-15bbe0553797/image.png" alt="">
<img src="https://velog.velcdn.com/images/jjung-developer/post/9a7caa5b-cd83-44e3-aa84-76f7a236478b/image.png" alt=""></p>
<h2 id="5-1-인라인-스타일">5-1. 인라인 스타일</h2>
<p><code>&lt;style&gt;</code>태그와 <code>&lt;![CDATA [...]]&gt;</code>태그로 스타일을 묶습니다.</p>
<pre><code class="language-html">&lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; viewBox=&quot;0 0 68 65&quot;&gt;
  &lt;style type=&quot;text/css&quot;&gt;
    &lt;![CDATA[
    .firstb { fill: yellow; }
    .secondb { fill: red; }
    ]]&gt;
  &lt;/style&gt;
  &lt;path class=&quot;secondb&quot; d=&quot;M42 27v-20c0-3.7-3.3-7-7-7s-7 3.3-7 7v21l12 15-7 15.7c14.5 13.9 35 2.8 35-13.7 0-13.3-13.4-21.8-26-18zm6 25c-3.9 0-7-3.1-7-7s3.1-7 7-7 7 3.1 7 7-3.1 7-7 7z&quot;/&gt;
  &lt;path class=&quot;firstb&quot; d=&quot;M14 27v-20c0-3.7-3.3-7-7-7s-7 3.3-7 7v41c0 8.2 9.2 17 20 17s20-9.2 20-20c0-13.3-13.4-21.8-26-18zm6 25c-3.9 0-7-3.1-7-7s3.1-7 7-7 7 3.1 7 7-3.1 7-7 7z&quot;/&gt;
&lt;/svg&gt;</code></pre>
<h2 id="5-2-외부-스타일">5-2. 외부 스타일</h2>
<pre><code class="language-html">// &lt;svg&gt;태그 전에 선언
&lt;?xml-stylesheet type=&quot;text/css&quot; href=&quot;style.css&quot;?&gt;</code></pre>
<pre><code class="language-html">// style.css 파일 내
.firstb { fill: yellow; }
.secondb { fill: red; }</code></pre>
<br>
<br>



<h1 id="6-js-조작">6. JS 조작</h1>
<blockquote>
<p>외부 JS로 작업 할 때 (SVG 파일 내 코드를 삽입하지 않고) SVG가 인라인으로 HTML문서안에 내장되어 있으면, 다른 DOM요소처럼 타켓팅 할 수 있습니다. 
<code>&lt;object&gt;</code>를 사용하는 경우 <code>contentDocument</code>로 타겟팅 할 수 있습니다.</p>
</blockquote>
<pre><code class="language-html">window.onload=function() {
  var object = document.getElementById(&quot;logoObject&quot;);
  var svgDocument = object.contentDocument;
  var svgb1 = svgDocument.getElementsByClassName(&quot;firstb&quot;);
  var svgb2 = svgDocument.getElementsByClassName(&quot;secondb&quot;);
  svgb1[0].setAttribute(&quot;fill&quot;, &quot;yellow&quot;);
  svgb2[0].setAttribute(&quot;fill&quot;, &quot;red&quot;);
};</code></pre>
<br>
<br>



<h1 id="7--애니매이션">7.  애니매이션</h1>
<blockquote>
<p>SVG 애니메이션은 CSS3 애니메이션 또는 JS 애니메이션을 기반으로 한 애니메이션 효과를 적용할 수 있습니다.
<a href="http://snapsvg.io/">Snap.svg</a> 와 같은 자바스크립트 라이브러리를 사용해 복잡한 애니메이션도 비교적 쉽게 만들 수 있습니다.</p>
</blockquote>
<p><a href="https://codepen.io/jjung-developer/pen/YzYbqQR">https://codepen.io/jjung-developer/pen/YzYbqQR</a></p>
<h2 id="7-1-인터렉티브-애니메이션">7-1. 인터렉티브 <strong><strong>애니메이션</strong></strong></h2>
<p>SVG 애니메이션에서 인터렉티브한 애니메이션 효과를 주려면 <code>begin=&quot;mouseover&quot;&amp; begin=&quot;mouseout&quot;</code>
을 추가 하거나, CSS3 애니메이션에 SVG 요소에 클래스를 추가하고 호버에 스타일을 적용 할 수 있습니다.</p>
<p><a href="https://codepen.io/jjung-developer/pen/QWaRNaN">https://codepen.io/jjung-developer/pen/QWaRNaN</a></p>
<br>
<br>



<h1 id="8-유의사항">8. 유의사항</h1>
<aside>
💡 복잡한 벡터로 이루어진 **svg**는 자칫 png 이미지보다 용량이 커지고 코드가 복잡해질 수 있습니다.
- IE8/안드로이드 2.3이하 버전에서는 **svg**를 지원하지 않습니다.

</aside>


<br>
<br>



<h1 id="🗒-참고-자료">🗒 참고 자료</h1>
<ul>
<li><a href="https://helpx.adobe.com/kr/illustrator/using/svg.html#enhancements">Adobe 공식 홈페이지</a></li>
<li><a href="https://www.w3schools.com/graphics/svg_intro.asp">w3schools SVG 튜토리얼</a></li>
<li><a href="https://brunch.co.kr/@ggk234/11">SVG를 사용하는 이유</a></li>
<li><a href="https://www.theteams.kr/teams/865/post/64932">왜 SVG로 갈아탔는가?</a></li>
<li><a href="https://code-masterjung.tistory.com/107">svg를 사용해야하는 이유</a></li>
<li><a href="https://www.sitepoint.com/add-svg-to-web-page/">웹페이지에 SVG추가하기</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[React,ReactNative] 카카오 주소 검색 - 라이브러리 이용하기 (react-daum-postcode)]]></title>
            <link>https://velog.io/@jjung-developer/ReactReactNative-%EC%B9%B4%EC%B9%B4%EC%98%A4-%EC%A3%BC%EC%86%8C-%EA%B2%80%EC%83%89-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC-%EC%9D%B4%EC%9A%A9%ED%95%98%EA%B8%B0-react-daum-postcode</link>
            <guid>https://velog.io/@jjung-developer/ReactReactNative-%EC%B9%B4%EC%B9%B4%EC%98%A4-%EC%A3%BC%EC%86%8C-%EA%B2%80%EC%83%89-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC-%EC%9D%B4%EC%9A%A9%ED%95%98%EA%B8%B0-react-daum-postcode</guid>
            <pubDate>Tue, 05 Jul 2022 12:37:03 GMT</pubDate>
            <description><![CDATA[<p>회사에서 RN작업을 하다가 카카오 우편 주소 검색 API을 사용 할 일이 생겼었다.
대기업 api답게 docs가 깔끔하게 정리되어있었지만... 남들 다 쉽다는 것도 나는 어렵기때문에...🫠</p>
<p>docs예제는 바닐라 js 로 되어있었고 레거시 코드가 많아 전부 리액트로 바꾸기에는 리소스가 많이 들어갈것 같다고 생각하던 참에 구글링을 하던 중 대부분의 사람들이 react-daum-postcode 라이브러리를 사용한다는 것을 알게 되었다.</p>
<p>차근차근 사용법을 보니 그렇게 어려워보이지 않아서 나도 바로 적용해보았다!
그리고 실제로도 매우 쉬웠다!!!</p>
<p><a href="https://github.com/actbase/react-daum-postcode">리드미</a>에 나와있는대로 그대로 따라하면 된다</p>
<pre><code>npm install @actbase/react-daum-postcode

or

yarn add @actbase/react-daum-postcode</code></pre><p>나는 React Native 환경에서 작업을 하기때문에 추가로 webView를 설치했다</p>
<pre><code>npm install react-native-webview
npx pod-install</code></pre><p>주소 검색 API를 사용할 페이지에 react-daum-postcode를 import를 하고</p>
<pre><code>import Postcode from &#39;@actbase/react-daum-postcode&#39;;</code></pre><p>코드를 적어준다</p>
<pre><code>&lt;Postcode
 style={{ flex: 1, width: &#39;100%&#39;, zIndex: 999 }}
 jsOptions={{ animation: true }}
 onSelected={data =&gt; getAddressData(data)}
 onError={function (error: unknown): void {
 throw new Error(&#39;Function not implemented.&#39;);
 }}
/&gt;

const getAddressData = data =&gt; {
 let defaultAddress = &#39;&#39;; // 기본주소
 if (data.buildingName === &#39;N&#39;) {
   defaultAddress = data.apartment;
 } else {
   defaultAddress = data.buildingName;
 }

 navigation.goBack();
 route.params.onSelect({
   zone_code: data.zonecode,
   default_address: data.address + &#39; &#39; + defaultAddress,
 });
};</code></pre><p>onSelected 옵션은 결과값을 클릭할때 실행되는 함수이고 나는 결과값을 클릭하면 이전 페이지로 결과값을 가져갔다</p>
<p>데이터를 console로 찍어보면</p>
<p><img src="https://velog.velcdn.com/images/jjung-developer/post/b445731e-10dd-466c-ac3b-8c83266c6ad5/image.png" alt=""></p>
<p>여기서 원하는 값을 추출하면 된다.</p>
<p><img src="https://velog.velcdn.com/images/jjung-developer/post/22003277-ce26-46a0-8131-593324d1fc04/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/jjung-developer/post/b95f7489-29ac-4010-80d7-64c50539088c/image.gif" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[React,ReactNative] Context API ]]></title>
            <link>https://velog.io/@jjung-developer/ReactReactNative-Context-API</link>
            <guid>https://velog.io/@jjung-developer/ReactReactNative-Context-API</guid>
            <pubDate>Sat, 25 Jun 2022 13:55:13 GMT</pubDate>
            <description><![CDATA[<p>리액트에서 서로 다른 두 컴포넌트에 같은 데이터가 필요하다고 할 때, 
컴포넌트가 부모자식 관계로 되어있지 않다면 컴포넌트 간의 직접적인 데이터 전달은 어렵다. 
데이터를 자식 컴포넌트로 보내고, 다시 그 데이터를 필요한 컴포넌트로 전달해야한다. 하지만 이렇게 Prop이 많아지면 이 prop가 어디에서 왔는지 확인하기 정말 어려워진다.</p>
<p>그렇기때문에 각 어플리케이션에 알맞은 상태관리 툴을 선택해 상태를 잘 관리하는 것이 중요하다.</p>
<p>나 같은 경우에는 회사 앱 프로젝트를 작업하며 점점 늘어져가는 페이지 deps에 혼란을 느꼈다. (코드가 돌아가긴 하는데 이건 뭔가 아닌거같다는 느낌이 들었다) 그러던중 사수분께서 Context API로 관리해 보라는 말씀을 해주셨고 바로 적용을 해보았다.</p>
<br>

<h2 id="🙃-context-api">🙃 Context API</h2>
<blockquote>
<p>ContextAPI는 react는 16.3 버전부터 정식적으로 지원하고 있다.
Context API는 Redux와 같은 상태관리 라이브러리와는 달리 <code>Provider</code>, <code>useContext</code>, <code>createContext</code> 개념만 알면 적용가능하다. <em>(그럼에도 Redux와 같은 상태관리 라이브러리를 쓰는 이유는 밑에서..)</em></p>
</blockquote>
<h3 id="✍🏻-createcontext">✍🏻 createContext</h3>
<p>먼저 createContext를 선언할 파일을 하나 만든다. (<code>App.js</code>에서 만들어도 상관은 없지만 컴포넌트 분리를 위해 나누었다)
<img src="https://velog.velcdn.com/images/jjung-developer/post/68536410-ee5c-4dfe-8bbd-691f520bbee9/image.png" alt=""></p>
<ul>
<li>context 객체를 만든다. 컴포넌트가 이 context를 사용하려면 해당 컴포넌트 상위에 provider로 부터 context를 정의한 변수 MyNameContext를 감싸면 된다</li>
<li>여기서 name은 값을 저장할 변수이고 changeName은 name을 바꿀 함수이다.</li>
</ul>
<br>

<h3 id="✍🏻-provider">✍🏻 Provider</h3>
<p>createContext를 선언한 파일 안에서 Provider를 사용 할 것이다.
(이걸 이제 <code>App.js</code>에서 import 할 것이기 때문!)
<img src="https://velog.velcdn.com/images/jjung-developer/post/8503130d-27ec-40d0-866e-30319c5dc657/image.png" alt=""></p>
<ul>
<li>provider는 정의한 context를 하위 컴포넌트에게 전달하는 역할을 한다.</li>
<li>provider를 전달하는 변수는 꼭!!! value가 있어야한다.</li>
</ul>
<p>위에서 만든 파일을 <code>App.js</code>에 import 한다.
<img src="https://velog.velcdn.com/images/jjung-developer/post/2cf197a7-1e86-458e-8664-13ccc81bd1bf/image.png" alt=""></p>
<p>선언한 MyNameStore를 context를 사용하고 싶은 컴포넌트 상위에 감싼다
<img src="https://velog.velcdn.com/images/jjung-developer/post/fba88edd-e48e-4340-96f8-5ab54ce8f70b/image.png" alt=""></p>
<p>이렇게 감싸게 되면 Content1과 Content2 컴포넌트에서는 Context에서 선언한 name과 changeName을 사용 할 수 있다.</p>
<br>

<h3 id="✍🏻-usecontext">✍🏻 useContext</h3>
<p>useContext를 통해 Context 값들을 불러온다.</p>
<br>

<ul>
<li>Content1에서는 name을 &#39;호정&#39;으로 바꿀 것이다
<img src="https://velog.velcdn.com/images/jjung-developer/post/98c133bb-1c76-4d64-9155-bd6022afd9e8/image.png" alt=""></li>
<li>Context2에서는 name을 선언 할 것이다
<img src="https://velog.velcdn.com/images/jjung-developer/post/4eb6db08-ff54-4ecc-8779-2e426e955292/image.png" alt=""></li>
</ul>
<br>
<br>

<blockquote>
<p>위와 같이 ContextAPI를 사용한다면 provider하위에 context를 가진 component는 provider의 value로 가진 state가 변화할 때마다, 전부 re render된다. 
Context로 관리 하는 값이 위의 예시처럼 하나라면 성능에 큰 영향이 없겠지만 실제 프로젝트에서는 Context로 관리되는 값들이 많을 수도 있다. 관리하는 값이 많아질 수록 불필요한 render가 많아진다는 이야기다.
이러한 비효율을 대처하기 위해 나온 여러 상태관리 라이브러리들이 있다.
대표적으로는 Redux와 ReactQuery, Recoil이 있다.
ContextAPI를 공부하면서 여러 라이브러리들에 대해서도 알아보았는데 (아주 살짝) 나중에 기회가 된다면 회사 프로젝트에도 상태관리 라이브러리를 도입한다면 좋을 것 같았다.
또한 현재 내가 따로 하고 있는 스터디에서는 ReactQuery를 쓰는데 상태관리 라이브러리는 처음이라 많이 헤맸었는데 이제는 뭔가 알아가는거 같아 이 부분도 나중에 포스팅 해보려한다!</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Swift] 나만의 iOS 앱 개발 입문 : iOS개발 강의 (1-2)]]></title>
            <link>https://velog.io/@jjung-developer/Swift-%EB%82%98%EB%A7%8C%EC%9D%98-iOS-%EC%95%B1-%EA%B0%9C%EB%B0%9C-%EC%9E%85%EB%AC%B8-iOS%EA%B0%9C%EB%B0%9C-%EA%B0%95%EC%9D%98-1-2</link>
            <guid>https://velog.io/@jjung-developer/Swift-%EB%82%98%EB%A7%8C%EC%9D%98-iOS-%EC%95%B1-%EA%B0%9C%EB%B0%9C-%EC%9E%85%EB%AC%B8-iOS%EA%B0%9C%EB%B0%9C-%EA%B0%95%EC%9D%98-1-2</guid>
            <pubDate>Tue, 07 Dec 2021 12:52:18 GMT</pubDate>
            <description><![CDATA[<p><img src="https://images.velog.io/images/jjung-developer/post/7dd06250-dd8d-4e70-80c9-5076e2644cab/thumb-course-Swift.jpeg" alt=""></p>
<h1 id="개요">개요</h1>
<blockquote>
<p>패스트캠퍼스에서 진행하는 나만의 iOS 앱 개발 입문 : iOS개발 강의를 듣고 작성하는 글 입니다.</p>
</blockquote>
<br>

<h1 id="📅-2주차">📅 2주차</h1>
<blockquote>
<p>이제 어느정도 swift라는 언어에 감이 잡혔다! 역시 모든 언어는 for문부터 돌려봐야 한다 ㅎㅎ 아직 문법이 익숙하지 않지만 그래도 이게 새로운 언어를 배우는 즐거움이니까 🧚🏻‍♀️</p>
</blockquote>
<br>

<h1 id="✅-optional">✅ Optional</h1>
<blockquote>
<p>ts의 optional과 비슷하다 있어도 되고! 없어도 되고! 타입이 string이어도 되고 아니어도 되고!
그치만 swift에서는 신기한게 있다 optional로 선언을 하고 변수에 값을 넣으면 박스에서 꺼내야한다는 것이다! 이것이 무슨말인가하면...</p>
</blockquote>
<pre><code>var carName: String?
carName = &quot;탱크으~&quot;</code></pre><p><img src="https://images.velog.io/images/jjung-developer/post/0c6ae7a4-520b-412d-b7d7-524e5ccb7750/image.png" alt=""></p>
<p>이런식으로 optional박스 안에 값이 들어가있다! 이제 값을 어떻게     박스에서 꺼내느냐가 핵심이다!</p>
<h2 id="👉🏻-forced-unwrapping">👉🏻 Forced unwrapping</h2>
<pre><code>print(carName!)</code></pre><blockquote>
<p>억지로 박스를 까는것이다!</p>
</blockquote>
<br>

<h2 id="👉🏻-optional-binding-if-let">👉🏻 Optional binding (if let)</h2>
<pre><code>if let unwrappedCarName = carName {
    print(unwrappedCarName)
} else {
    print(&quot;car name 없다&quot;)
}</code></pre><blockquote>
<p>if문을 사용하여 carName이 있다면 unwrappedCarName에 값을 넣어주고 없으면 없다는 print문을 실행한다. 이렇게 조건이 단순한 경우에는 level이 단조롭지만 깊은 조건을 만나게 되면 level이 아주 보기 힘들게 될 것이다. 이러한 문제점을 해결해주는 것이 guard이다</p>
</blockquote>
<br>

<h2 id="👉🏻-optional-binding-guard">👉🏻 Optional binding (guard)</h2>
<pre><code>func printParsedInt(from: String) {
    guard let parsedInt = Int(from) else {
        print(&quot;Int로 컨버팅 안된다&quot;)
        return
    }
    print(parsedInt)
}
printParsedInt(from: &quot;100&quot;)</code></pre><blockquote>
<p>위 if let보다 훨씬 간단해졌다! 그리고 return문을 통한 불필요한 코드 실행을 하지 않는다</p>
</blockquote>
<br>

<h2 id="👉🏻-nil-coalescing">👉🏻 Nil coalescing</h2>
<pre><code>let myCarName:String = carName ?? &quot;모델s&quot;
// 만약에 carName이 nil이면 모델s를 넣어라</code></pre><blockquote>
<p>박스를 까봤더니 값이 nil이면 default값을 주자!</p>
</blockquote>
<br>
<br>

<h1 id="✅-array">✅ Array</h1>
<blockquote>
<p>swift의 array는 타입이 같은 것끼리만 담아야한다!</p>
</blockquote>
<p><span style="color:red">evenNumbers2은[2,4,6,8]이라고 가정한다</span></p>
<h2 id="👉🏻-배열-추가">👉🏻 배열 추가</h2>
<pre><code>evenNumbers2.append(10) // 배열 추가
evenNumbers2 += [12,14,16] // 배열 추가
evenNumbers2.append(contentsOf: [18,20])</code></pre><br>

<h2 id="👉🏻-isempty">👉🏻 isEmpty</h2>
<pre><code>let isEmpty = evenNumbers2.isEmpty</code></pre><blockquote>
<p>evenNumbers2가 비어있나? boolean값을 반환한다.</p>
</blockquote>
<br>

<h2 id="👉🏻-count">👉🏻 count</h2>
<pre><code>evenNumbers2.count</code></pre><blockquote>
<p>배열의 개수가 몇개인지 [1,2,3] =&gt; 3반환</p>
</blockquote>
<br>

<h2 id="👉🏻-first">👉🏻 first</h2>
<pre><code>let firstItem = evenNumbers2.first </code></pre><blockquote>
<p>evenNumbers2의 첫번째 값을 나타낸다. 반환값은 배열이 빈 값일 수도 있기때문에 옵셔널로 반환이 된다.</p>
</blockquote>
<br>

<h2 id="👉🏻-min-max">👉🏻 min, max</h2>
<pre><code>evenNumbers2.min()
evenNumbers2.max()</code></pre><br>

<h2 id="👉🏻---contain-insert">👉🏻 ... , contain, insert</h2>
<pre><code>let firstThree = evenNumbers2[0...2]
evenNumbers2.contains(3) // 3을 반환하는 것이 있니? boolean으로 반환
evenNumbers2.insert(0, at: 9) // 9번째에 0을 넣는다 (나머지는 뒤로밀림)</code></pre><blockquote>
<p>... =&gt; 배열의 0번째부터 2번째까지 가져온다 ([2,4,6])
contains =&gt; 해당값을 반환하는것이 있으면 true 없으면 false
insert =&gt; 값을 바꿔준다.</p>
</blockquote>
<br>
<br>

<h1 id="✅-dictionary">✅ Dictionary</h1>
<blockquote>
<p>key값은 유일해야한다.</p>
</blockquote>
<pre><code>var scoreDic:[String:Int] = [&quot;jjung&quot;:20, &quot;ho&quot;:10,&quot;min&quot;:40]
if let score = scoreDic[&quot;jjung&quot;] {
    score
} else {
    print(&quot;스코어 없음&quot;)
}// 20
scoreDic[&quot;won&quot;] // nil</code></pre><br>

<h2 id="👉🏻-isempty-count">👉🏻 isEmpty, count</h2>
<pre><code>scoreDic.isEmpty
scoreDic.count</code></pre><br>

<h2 id="👉🏻-dictionary-업데이트-추가">👉🏻 Dictionary 업데이트, 추가</h2>
<pre><code>scoreDic[&quot;jjung&quot;] = 99 // 업데이트
scoreDic[&quot;gg&quot;] = 100 // 추가</code></pre><br>

<h2 id="👉🏻-dictionary-삭제">👉🏻 Dictionary 삭제</h2>
<pre><code>scoreDic[&quot;gg&quot;] = nil</code></pre><br>

<h2 id="👉🏻-for-loop">👉🏻 For loop</h2>
<pre><code>for (name, score) in scoreDic {
    print(&quot;\(name), \(score)&quot;)
}</code></pre><br>

<h2 id="👉🏻-keys">👉🏻 keys</h2>
<pre><code>for key in scoreDic.keys { // key값만 가져옴
    print(key)
}</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[Swift] 나만의 iOS 앱 개발 입문 : iOS개발 강의  (1-1)]]></title>
            <link>https://velog.io/@jjung-developer/Swift-%EB%82%98%EB%A7%8C%EC%9D%98-iOS-%EC%95%B1-%EA%B0%9C%EB%B0%9C-%EC%9E%85%EB%AC%B8-iOS%EA%B0%9C%EB%B0%9C-%EA%B0%95%EC%9D%98-1</link>
            <guid>https://velog.io/@jjung-developer/Swift-%EB%82%98%EB%A7%8C%EC%9D%98-iOS-%EC%95%B1-%EA%B0%9C%EB%B0%9C-%EC%9E%85%EB%AC%B8-iOS%EA%B0%9C%EB%B0%9C-%EA%B0%95%EC%9D%98-1</guid>
            <pubDate>Mon, 29 Nov 2021 12:29:40 GMT</pubDate>
            <description><![CDATA[<p><img src="https://images.velog.io/images/jjung-developer/post/a0dec4cf-3feb-4d62-aacc-ddc84e54c264/thumb-course-Swift.jpeg" alt=""></p>
<h1 id="개요">개요</h1>
<blockquote>
<p>패스트캠퍼스에서 진행하는 나만의 iOS 앱 개발 입문 : iOS개발 강의를 듣고 작성하는 글 입니다. </p>
</blockquote>
<br>
<hr>
<br>

<h1 id="📅-1주차">📅 1주차</h1>
<blockquote>
<p>핑계를 적어보자면... 강의가 1주차 하나만 열려있길래.. (1)만 들었는데 갑자기(?)보니까 (2)까지 열려있는거다!! 분명 주말전까지만해도 안열려있었는데 😱 음.. 일단은 (1)까지만 들었던 내용을 정리해보려한다.
나는 프론트엔트 개발자이다. 지금까지는 js를 공부해왔으며, 지금 회사 코드도 따라가기 벅차지만 ㅠㅠ.. 뭔가 refresh한 공부를 하고싶었다...^^ (그리고 예전부터 ios개발을 꼭! 해보고싶었다)
누가보면 고작 2달된 프론트엔드 신입이... js나 공부하지... 라고 말 할 수 있겠지만 😕 회사공부에 방해가 되지 않는 선에서 공부하려 한다!</p>
</blockquote>
<br>

<h2 id="✅-튜플">✅ 튜플</h2>
<pre><code>var tuple : (string,string,Bool) = (&quot;choi&quot;,&quot;hojung&quot;,true)
print(&quot;성 : \(tuple.0) 이름 : \(tuple.1)&quot;)</code></pre><blockquote>
<p>Swift 에서 튜플이란 다양한 값(데이터)들의 묶음 이라 할 수있다. 
튜플의 구성 요소들은 서로 같은 타입일 필요가 없다. 같은 타입을 여러개 사용해도 상관없고, 각각 다른 타입을 사용해도 상관없다는 의미이다. 또한 튜플 안에 들어갈 수 있는 값들의 개수도 사용하고 싶은 만큼 사용이 가능하다.
개인적으로 느끼기엔.. 배열 + 딕셔너리 = 튜플 (?) 이라는 생각이 들었던 데이터 타입이다!</p>
</blockquote>
<br>

<h2 id="✅-var-let">✅ var, let</h2>
<p><img src="https://images.velog.io/images/jjung-developer/post/a833151e-1f9b-451b-bbbe-81de40265b5f/image.png" alt=""></p>
<blockquote>
<p>js에서는 var와 let은 값을 바꿀 수 있는 변수 선언 방식이다! 하지만! swift에서는 다르게 쓰인다.
var는 js와 동일한 변수 선언 방식이고 let은 반대의 개념이다! js에서 const와 같이 값을 바꿀 수 없다.</p>
</blockquote>
<br>

<h2 id="✅--range">✅ ... range</h2>
<p><img src="https://images.velog.io/images/jjung-developer/post/71a41933-a7bc-494a-9228-9e1fa7aaf59b/image.png" alt="">
<img src="https://images.velog.io/images/jjung-developer/post/1f94ceae-19a9-4d4c-85cb-1fc772b0823f/image.png" alt=""></p>
<blockquote>
<p>일일히 for문으로 안돌려도 0~10까지의 숫자를 표현 할 수 있다!</p>
</blockquote>
<br>

<h2 id="✅-for문">✅ for문</h2>
<p><img src="https://images.velog.io/images/jjung-developer/post/c1053629-75e6-40ec-aa76-25c62d55dadd/image.png" alt=""></p>
<blockquote>
<p>기본적인 for문과 크게 다르지 않다!
주목해야 할 것은 3가지!
<strong>1. _의 사용</strong> : i가 밑에서 쓰이지 않는다면 굳이 i로 선언하지 않고 _로 나타내도 된다.
<strong>2. where의 사용</strong> : where를 사용하면 for문안에 if문을 사용하는 것과 같다!
3. <strong>continue의</strong> 사용 : 건너 뛰기가 가능하다!</p>
</blockquote>
<br>

<h2 id="✅-while문">✅ while문</h2>
<p><img src="https://images.velog.io/images/jjung-developer/post/6610e0cc-429f-4c00-ae7a-9a4be8294772/image.png" alt=""></p>
<blockquote>
<p>마찬가지로 기본적 while문과 크게 다르지 않다.
<strong>1. 조건에 ...range, _, where 가능</strong> : 위의 for문에서 설명</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ReactNative] Component, Navigation]]></title>
            <link>https://velog.io/@jjung-developer/ReactNative-Component</link>
            <guid>https://velog.io/@jjung-developer/ReactNative-Component</guid>
            <pubDate>Fri, 03 Sep 2021 02:54:57 GMT</pubDate>
            <description><![CDATA[<p>RN을 공부하며, React와 비슷했던 점, 달랐던 점, 새로 알게 된 점 등을 이야기 해보려 한다!  </p>
<blockquote>
<p>내가 느낀 RN의 첫 인상은 음? 응? 비슷한데 묘하게 다르네... UI는 역시 아이폰 💫</p>
</blockquote>
<br>

<h1 id="👉🏻-ui구현">👉🏻 UI구현</h1>
<p>기존에 웹 ui구현과 크게 다른점은 flex속성이다.
RN은 기본적인 flex속성이 열(세로)(column) 방향으로 이루어져 있다.
그래서 우리가 웹에서 했던 속성대로 부모에 flex를 주게 된다면 우리의 생각과는 다르게 ui가 표출된다</p>
<p><em><strong>1:1:1</strong></em>
<img src="https://images.velog.io/images/jjung-developer/post/8baf0bd2-5a1d-4c90-9914-324e126ff1e7/111.png" alt="">
<img src="https://images.velog.io/images/jjung-developer/post/2fac40d5-9b54-417a-80bb-ddcf2bec0a1f/Simulator%20Screen%20Shot%20-%20iPhone%2012%20-%202021-09-03%20at%2011.16.22.png" alt=""></p>
<br>

<p><em><strong>1:3:1</strong></em>
<img src="https://images.velog.io/images/jjung-developer/post/d6fe63b8-98a3-4d09-b745-95e1a40c98d2/131.png" alt="">
<img src="https://images.velog.io/images/jjung-developer/post/8f5eb770-ac15-4ab0-83a0-1567ecaa6c87/Simulator%20Screen%20Shot%20-%20iPhone%2012%20-%202021-09-03%20at%2011.16.29.png" alt=""></p>
<blockquote>
<p>부모태그의 flex:1은 화면 전체를 사용하겠다는 이야기이고, 자식 태그들은 부모 View 크기의 특정 비율만큼 차지한다! 
flex와 %는 부모의 크기에 영향을 받으므로 이 속성을 사용할 때, 부모의 크기를 지정하지 않았는지 잘 확인해야한다!
만약, 세로정렬이 아닌 가로정렬을 나타내고 싶다면 Flex Direction 스타일을 사용한다. Flex Direction은 row(행), column(열) 속성을 나타낸다</p>
</blockquote>
<br>
<br>


<h1 id="👉🏻-댓글-달기-기능">👉🏻 댓글 달기 기능</h1>
<p><img src="https://images.velog.io/images/jjung-developer/post/79975936-2766-4ab9-b9f1-9bb9540ef41a/Sep-03-2021%2010-31-05.gif" alt=""></p>
<p>전체적인 로직은 react와 다르지 않았다. 다른 점이 있다면 html태그들이 아닌 Text, View같은 RN태그들을 쓴다는것! input도 마찬가지였다.</p>
<p><img src="https://images.velog.io/images/jjung-developer/post/1d19445c-173d-45a5-8628-187de65e44c1/code.png" alt=""></p>
<p>input과 button에는 react와 비슷한 Attributes가 들어간다.
Button에서 </p>
<p>여기서, 새로알게된 부분은! &nbsp; <span style="font-size:22px;"><strong>함수 사용법</strong></span></p>
<blockquote>
<p>()=&gt;{}로 map함수를 돌렸었는데,    함수 내 로직이 전부 return문일 경우 
()=&gt;()로 함수를 작성하게 되면 return문은 생략되고, 함수 내의 코드가 전부 return이 된다!
처음엔 RN에서만 그렇게 쓰는 줄 알았는데, 혹시나 해서 js에서 돌려보니까 js에서도 가능하다! react에서도 가능!</p>
</blockquote>
<br>
<br>


<h1 id="👉🏻-picker">👉🏻 picker</h1>
<p><img src="https://images.velog.io/images/jjung-developer/post/9856ce9d-fb92-47a7-bb40-924d588d4cfb/%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-09-03%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%2011.36.22.png" alt="">
<img src="https://images.velog.io/images/jjung-developer/post/2234d55e-712c-4aad-aaeb-3dfb6718f05c/%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-09-03%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%2011.47.20.png" alt="">
공식문서에서 제공해주는 picker!  <em><strong>향후 릴리즈에서는 제거 될 예정이라고 한다!</strong></em> 해당 warning에서 알려주는 react-native-picker/picker를 사용해보았다.</p>
<br>

<p><img src="https://images.velog.io/images/jjung-developer/post/128e5051-f6b5-4778-bffe-d13818d5fe71/picker.gif" alt=""></p>
<p><img src="https://images.velog.io/images/jjung-developer/post/30056f53-818a-497a-8059-ecd649881567/picker.png" alt=""></p>
<blockquote>
<p>selectedValue에서 초기값을 설정해주고 onVauleChange를 통해 picker를 제어한다.</p>
</blockquote>
<br>
<br>

<h1 id="👉🏻-navigation">👉🏻 Navigation</h1>
<blockquote>
<p>페이지 이동을 위한 Navigation이다.
stack, tab, draw를 배웠다. 
같은 라이브러리가 사용되며, 전체적은 flow는 같다.
다양한 옵션을 통해 텍스트, style을 할 수 있으며,
Stack.Screen을 씀으로써 navation에 있는 함수들을 porps로 전달할 수도 있다. Navigator를 쓰며 react에서 썻던 동적 라우팅과 매우 유사하다고 느꼈다! props로 값을 넘겨주는것, parms로 값을 받는것 등등.. 비슷하면서 다른 react와 rn !</p>
</blockquote>
<h2 id="✍🏻-stack">✍🏻 Stack</h2>
<p><img src="https://images.velog.io/images/jjung-developer/post/46e8daec-8b58-4964-98e0-cecd4573061a/Sep-03-2021%2014-00-22.gif" alt=""></p>
<p><img src="https://images.velog.io/images/jjung-developer/post/2d250601-6f12-42b0-8729-fd416521487f/navigator.png" alt=""></p>
<p><img src="https://images.velog.io/images/jjung-developer/post/ba1a333c-f879-45ac-902b-0fe239eb545b/navigator2.png" alt=""></p>
<p><img src="https://images.velog.io/images/jjung-developer/post/b36f4533-f319-4e0f-824b-df9055e49d3a/navigator3.png" alt=""></p>
<p>** 왜 벨로그에만 gif를 올리면 깨지는지 모르겠다 ㅠㅠ user페이지에도 To User Home이라는 버튼도 있고.. 값 넘겨주는것도 보이는데 ㅠㅠ</p>
<blockquote>
<p>버튼을 통해 페이지 이동이 가능하다. props로 값을 넘겨주고 parms로 값을 받을 수 있다. (아래 Navigation동일)</p>
</blockquote>
<br>

<h2 id="✍🏻-tab">✍🏻 Tab</h2>
<p><img src="https://images.velog.io/images/jjung-developer/post/997c610e-495c-4635-8c40-5c4319835c44/Sep-03-2021%2014-15-36.gif" alt=""></p>
<p><img src="https://images.velog.io/images/jjung-developer/post/17ce0880-c6dd-49d1-bf03-65773efb2c01/tab.png" alt=""></p>
<p>** 여기서도 깨진다 ㅠㅠ tab이 활성화 되면 해당 탭이 토마토색으로 변하는데 ㅠㅠ</p>
<br>

<h2 id="✍🏻-drawer">✍🏻 Drawer</h2>
<p><img src="https://images.velog.io/images/jjung-developer/post/2092e6e9-18c5-4eff-9cb9-a0b22d08b3c3/Sep-03-2021%2014-24-10.gif" alt=""></p>
<p><img src="https://images.velog.io/images/jjung-developer/post/d208ff11-6167-48ec-93a5-6bac753957ec/draw1.png" alt=""></p>
<p>** 여기서도 깨진다 ㅠㅠ!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ReactNative] 개발환경 세팅]]></title>
            <link>https://velog.io/@jjung-developer/ReactNative-%EA%B0%9C%EB%B0%9C%ED%99%98%EA%B2%BD-%EC%84%B8%ED%8C%85</link>
            <guid>https://velog.io/@jjung-developer/ReactNative-%EA%B0%9C%EB%B0%9C%ED%99%98%EA%B2%BD-%EC%84%B8%ED%8C%85</guid>
            <pubDate>Tue, 31 Aug 2021 11:49:05 GMT</pubDate>
            <description><![CDATA[<p>기업협업 1일차.. ReactNative를 쓰기 위해 개발환경 셋팅을 시작했다.
근데.. 한줄 입력할때마다 오류 발생...^^ 가뜩이나 불안정한 RN인데 심지어 m1오류까지 더해지니..🤦🏻‍♀️</p>
<p><a href="https://dev-yakuza.posstree.com/ko/react-native/install-on-mac/">이 블로그</a>를 보고 개발환경을 셋팅했다.
여러 블로그들에 환경세팅법은 많을테니 환경세팅 중 발생한 오류들에 대해 글을 쓰고자한다.</p>
<h1 id="🚫-no-similarly-named-formulae-found">🚫 No similarly named formulae found</h1>
<p><code>Watchman 설치</code>중 만난 오류 문구..</p>
<blockquote>
<p><code>rm -fr $(brew --repo homebrew/core)</code></p>
</blockquote>
<p><strong>brew의 코어 디렉터리를 삭제 후 다시 설치하면 된다!</strong></p>
<br>

<h1 id="🚫-error--unknown-command-cask">🚫 Error : unknown command cask</h1>
<p>가장 많은 시간을 뺏겼던 오류,,,
JDK를 설치를 하고, version확인을 했지만 계속 cask 오류가 떳다 🥺 
<img src="https://images.velog.io/images/jjung-developer/post/500bbf70-1155-462a-9bf2-04f8bb4e0034/%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-08-31%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.52.47.png" alt=""></p>
<p><img src="https://images.velog.io/images/jjung-developer/post/20eca49a-370b-4e4a-9df2-eb5cbcf00040/%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-08-31%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.52.39.png" alt=""></p>
<blockquote>
<p><code>arch -arm64 brew install --cask</code></p>
</blockquote>
<p>검색을 해보니까 m1칩 오류였다 
*<em>arch -arm64로 다시 install해주며 해결 *</em>✨</p>
<br>

<h1 id="🚫-the-following-build-commands-failed">🚫 The following build commands failed</h1>
<p>와와 이제 거의 다 했따!!! run해보자!!!!!
응~ 안돼 ~ 🤯</p>
<blockquote>
<pre><code>sudo gem install cocoapods --pre
pod update</code></pre></blockquote>
<pre><code>
cocoapods에서 오류가 났던것이다!
대체,,, 오류가 안나는 곳이 없어 😇

&lt;br&gt;

# 🚫 npm ERR! code ELIFECYCLE

이제 되겠지 ? 하고 run을 다시 돌려봤지만 또 다시 오류...

&gt; ```
npm cache clean --force
rm -rf node_modules package-lock.json
npm install</code></pre><p>npm 캐시와 node_modules, package-lock.json을 제거하고 npm 을 다시 install 해주면 된다.</p>
<br>

<h1 id="🚫-duplicated-files-or-mocks-please-check-the-console-for-more-info">🚫 duplicated files or mocks. please check the console for more info</h1>
<p>와와 된다!!! 신나게 rn을 구경 하던 중...
나도 모르게 이상한 짓을 했다보다... (기억안남 😅)
이상한 에러가 시뮬레이션 창에 뜨는 것이다! </p>
<p>이러한 오류에 대한 원인은 2가지가 있는데</p>
<ul>
<li>package.json 파일의 name 값이 react-native 규칙과 다르다는 것</li>
<li>루트 폴더 내에 package.json 파일이 두 개</li>
</ul>
<p>나같은 경우는 2번째 경우였다.
무슨 이유에선지.. package.json이 두개가 생긴지는 모르겠다...ㅎ</p>
<h1 id="🔥-tmi">🔥 TMI</h1>
<blockquote>
<p>꼬박 하루가 걸렸던 RN설치... 터미널을 너무 무서워 하는 나였는데
이번 계기로 조금은 극복을 한 것 같다 💪🏻
내일부터는 다시 TS 공부와 RN 공부 시작!!</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TypeScript] interface]]></title>
            <link>https://velog.io/@jjung-developer/TypeScript-interface</link>
            <guid>https://velog.io/@jjung-developer/TypeScript-interface</guid>
            <pubDate>Sun, 29 Aug 2021 09:46:06 GMT</pubDate>
            <description><![CDATA[<h1 id="interface">interface</h1>
<pre><code>let user:object;

user = {
    name : &#39;jjung&#39;,
    age:26
}

console.log(user.name);</code></pre><p>이렇게 작성하면 ts에서는 user.name에서 오류가 난다!</p>
<pre><code>type Score = &#39;A&#39; | &#39;B&#39; | &#39;C&#39; | &#39;F&#39;;

interface User {
    name : string;
    age : number;
    gender? : string; // 있어도 되도 없어도 되는 옵셔널
    readonly birthYear : number; // 읽기전용 속성으로 수정 할 수 없음
    [grade:number] : Score;
}

let user : User = {
    name : &#39;jjung&#39;,
    age:26,
    gender:&quot;fale&quot;,
    birthYear : 1996,
    1:&#39;A&#39;,
    2:&#39;B&#39;,
}

user.gender = &#39;male&#39;; // 수정또한 가능</code></pre><blockquote>
<p>이럴떄는 interface를 사용하자!
각각의 설명은 코드에 적어놓았다!
? 옵셔널, readonly, [], score</p>
</blockquote>
<pre><code>interface Add {
    (num1:number,num2:number) : number;
    // 매개변수 : 리턴값 or void
}

const add : Add = function (x,y) {
    return x+y;
}
add (10,20);

interface IsAdult {
    (age:number) : boolean;
    // 인터페이스에서 함수의 속성값도 지정이 가능하다.
}

const a :IsAdult = (age) =&gt; {
    return age &gt; 19;
}

a(26) // true</code></pre><blockquote>
<p>이렇게 함수로도 나타낼 수 있다!
()은 매개변수를, :는 리턴값을 나타낸다</p>
</blockquote>
<p>함수를 좀 더 자세히 보면...</p>
<pre><code>function addFun (num1:number,num2:number):number {
    return num1+num2
}

function IsAdultFun (age:number):boolean {
    return age &gt; 19
}

function hello(name?:string){
    return `Hello, ${name || &#39;world&#39;}`
}
function hello2(name = &quot;world&quot;){ // 매개변수에 초기값 할당 , 자동으로 타입은 string이 된다. 매개변수에 초기값이 있으면 자동으로 옵셔널이 된다.
    return `Hello, ${name}`
}
const result = hello();
// 매개변수를 옵셔널로 지정을 하여 name이 있으면 name을 출력하고,
// 없으면 world를 출력합니다. (선택적 매개변수)
// 매개변수가 두개 일 경우 반드시 선택적 매개변수는 뒤에 위치하고 있어야한다.

function addFun2 (...nums:number[]) { // 입력하는 모든 것을 nums에 담는다. 스프레드 연산자는 반드시 배열로 할당을 해야한다.
    return nums.reduce((result,num) =&gt; result + num,0);
}

addFun2(1,3,4);
// 스프레드 연산자를 통해 매개변수를 배열로 만들어줌</code></pre><p>함수를 저장할 변수의 타입은 화살표 기호를 이용 할 수 있다.
함수를 구현하는 코드에서는 따로 타입을 정의하지 않아도 된다.</p>
<pre><code>const getText: (name:string, age:number) =&gt; string = function(name,age) {
 return &#39;123&#39;;
}</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[TypeScript] 타입스크립트란?]]></title>
            <link>https://velog.io/@jjung-developer/TypeScript-%ED%83%80%EC%9E%85%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EB%9E%80</link>
            <guid>https://velog.io/@jjung-developer/TypeScript-%ED%83%80%EC%9E%85%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EB%9E%80</guid>
            <pubDate>Sun, 29 Aug 2021 07:41:46 GMT</pubDate>
            <description><![CDATA[<h1 id="typescript">TypeScript</h1>
<p>우리가 사용하는 브라우져들은 타입스크립트를 이해하지 못한다.
그래서 js로 변환해서 브라우져에서 사용할 수 있다.
이런 번거로운 일이 있음에도 불구하고 우리는 왜 typescript를 쓰는것일까?</p>
<blockquote>
<p><strong>javascript (동적언어)</strong> : 런타입에 타입이 결정 / 오류 발견
<strong>typescript (정적언어)</strong> : 컴파일 타임에 타입 결정 / 오류 발견</p>
</blockquote>
<p>typescript는 코드 작성 시간은 길어지겠지만, 안정적이고 빠르게 작업을 진행 할 수 있는 장점이 있다!</p>
<br>

<pre><code>function add (num1,num2) {
    console.log(num1+num2);
}

add(); // NaN
add(1); // NaN
add(1,2); // 3
add(2,3,4); // 5
add(&#39;hello&#39; + &#39;world&#39;); //helloworld </code></pre><p>이러한 코드를 js에서 실행한다고 했을때, 오류없이 실행이 될 것이다.
그러나 typescript에서 실행했을때는 친절히(?) 오류들을 알려준다</p>
<p><img src="https://images.velog.io/images/jjung-developer/post/9ac1da52-79dc-4cb5-bbf3-2cc81b9f95b5/%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-08-29%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%204.31.56.png" alt="">
매개변수num1의 타입이 any타입이다. 라고 경고를 주는 것이다!
any타입 일 수 도 있지만, 지양하는 것이 좋다.</p>
<p><img src="https://images.velog.io/images/jjung-developer/post/b8018f98-b19b-4e71-99ea-f3684c61d5b8/%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-08-29%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%204.32.06.png" alt="">
add함수는 2개의 매개변수를 가지고 있는데 가지고 있는 매개변수는 0이다. 라고 알려준다.</p>
<p>그렇다면 typescript는 어떻게 작성할까?</p>
<pre><code>function add (num1:number,num2:number) {
    console.log(num1+num2);
}</code></pre><blockquote>
<p>:을 하고 원하는 타입을 적어준다.
배열도 마찬가지다</p>
</blockquote>
<pre><code>function showItems (arr:number[]) {
    arr.forEach((item) =&gt; {
        console.log(item)
    })
}</code></pre><h2 id="데이터-타입">데이터 타입</h2>
<pre><code>// let fruit:string = &#39;orange&#39;
// let age:number = 20;
// let isAdult:boolean = true;
// let a:number[] = [1,2,3];
// let a2:Array&lt;number&gt; = [1,2,3];

let fruit = &#39;orange&#39;
let age = 20;
let isAdult = true;
let a = [1,2,3];
let a2 = [1,2,3];</code></pre><p>이미 값이 입력되어 있는상태라면 위의 :데이터타입은 생략이 가능하다.</p>
<pre><code>//튜플

let b:[string,number];

b=[&#39;z&#39;,1];
// b = [1,&#39;z&#39;];</code></pre><p>배열안의 각각 타입을 지정 할 수 있다.</p>
<pre><code>// enum 비슷한 속성들끼리 모아놓음
enum Os {
    window = 3,
    ios = 10,
    android
}

let myOs:Os;
// myOs에는 Os의 window,ios,android 만 입력할 수 있다.
// 특정값만 입력할 수 있도록

myOs = Os.window;</code></pre><p>enum은 비슷한 속성끼리 모아놓은 데이터이다.
값은 숫자 또는 문자열이 들어 갈 수 있다.
<em><strong>단 문자열을 할당 할 경우 단방향 맵핑만이 가능하다.</strong></em></p>
<pre><code>enum Fruit {
    Apple, // 0
    Banana = 5 , // 5
    Orange, // 6
}
const v1: Fruit = Fruit.Apple;
const v2: Fruit.Apple | Fruit.Banana = Fruit.Banana;
console.log(Fruit.Banana); // 5
console.log(Fruit[&#39;Banana&#39;]; // 5
console.log(Fruit[5]); // Banana</code></pre><p>enum에 초기값을 할당하지 않으면 자동으로 첫번째 요소에 0이 할당된다.
명시적으로 값을 입력하지 않으면 이전 원소에서 1만큼 증가한 값이 할당된다.</p>
<br>
<br>

<h2 id="함수">함수</h2>
<p><em><strong>함수 오버로드</strong></em></p>
<pre><code>// add 함수 작성하기
// 두 매개변수가 모두 문자열이면 문자열을 반환한다.
// 두 매개변수가 모두 숫자이면 숫지를 반환한다.
// 두 매개변수를 서로 다른 타입으로 압력하면 안된다.

function add(x:number | string, y: number| string): number | string {
    if(typeof x === &#39;number&#39; &amp;&amp; typeof y === &#39;number&#39;){
        return x+y;
    } else {
        const result = Number(x) + Number(y);
        return result.toString();
    }
}
const v1:number = add(1,2);
console.log(1,&#39;2&#39;);</code></pre><p> 이러한 경우 console.log(1,&#39;2&#39;);는 작동을 잘 하고, const v1:number = add(1,2);에서는 오류가 난다.
 에러가 나는 이유는 함수가 number 또는 string을 반환하기 때문에 만약 string을 반환하게 되면 number가 아니라서 오류가 나는 것이다.</p>
<p> 이러한 경우의 해결법이 함수 오버로드
 함수를 정의한 코드 위에</p>
<pre><code>function add(x:number, y:number) : number;
function add(x:string, y:string) : string;</code></pre><p> 두 줄을 추가해준다.
 위에 두 줄은 단지 타입 정보이기 때문에 컴파일해서 js가 됐을때는 타입정보는 제거가 된다!</p>
 <br>

<p><em><strong>named prameters</strong></em></p>
<pre><code>function getText({
    name,
    age = 15,
    language,
}: {
    name: string;
    age: number;
    language?: string;
}) : string {
    const nameText = name.substr(0,10);
    const ageText = age &gt;= 35 ? &#39;senior&#39; : &#39;junior&#39;;
    return `name: ${nameText}, age: ${ageText}, language: ${language}`
}</code></pre><p>매개변수를 객체로 감싸주고, 그뒤에 타입을 정의해준다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[TIL 34 - React Function & hook (2)]]></title>
            <link>https://velog.io/@jjung-developer/TIL-34-React-Function-hook-2</link>
            <guid>https://velog.io/@jjung-developer/TIL-34-React-Function-hook-2</guid>
            <pubDate>Sun, 15 Aug 2021 11:29:12 GMT</pubDate>
            <description><![CDATA[<h1 id="👉🏻-react-hook">👉🏻 React Hook</h1>
<h2 id="✍🏻-usecallback">✍🏻 useCallback</h2>
<blockquote>
<p>함수 안에서 사용한 값이 바뀌면 함수를 호출해서 연산하고, 값이 바뀌지 않으면 이전에 연산한 값을 재새용한다. 함수 안에서 state나 props가 바뀌면 함수를 호출해서 실행한다.
useCallback을 사용하지 않은 함수들은 컴포넌트가 리렌더링 될 때 마다 새로 만들어진다.
함수가 새로 만들어지는 것이 성능을 떨어트리지는 않지만, 
컴포넌트 결과물을 재사용하거나 하는 최적화 작업을 할 때 함수를 재사용하는 것이 필요하다.</p>
</blockquote>
<pre><code>const onCreate = useCallback(() =&gt; {
    const user = {
        id: nexId.current,
        username,
        email,
    }
    setUsers(users.concat(user));
    // setUsers([...users, user]);
},[users,username,email])</code></pre><p><strong>기본형태</strong> 
<span style="color:red">useCallback(function,deps)</span></p>
<ul>
<li>function : 재사용 할 함수</li>
<li>deps : 검사할 특정 값을 담은 배열</li>
</ul>
<br>
<hr>
<br>


<h2 id="✍🏻-usehistory-uselocation-useparams">✍🏻 useHistory, useLocation, useParams</h2>
<blockquote>
<p>우리가 1차 프로젝트때 사용했던 props와 유사한 hook이다.
2차플젝때는 hook으로 사용하면 편할 것 같아 알아보았다.</p>
</blockquote>
<br>


<h3 id="✅-usehistory">✅ useHistory</h3>
<blockquote>
<p>props를 통해 받던 history를 한줄의 함수로 받을 수 있다.</p>
</blockquote>
<pre><code>const Home = (): JSX.Element =&gt; {
  const history = useHistory();
  // history를 props에서 얻어왔을 때 처럼 동일하게 사용 가능하다.

  return (
    &lt;div onClick={() =&gt; history.push(&#39;/auth&#39;)}&gt;
      &lt;div&gt;Hello!&lt;/div&gt;
    &lt;/div&gt;
  );
};

export default Home;
// withRouter hoc가 필요없다.</code></pre><br>

<h3 id="✅-uselocation">✅ useLocation</h3>
<blockquote>
<p>useLocation hooks는 사용자가 현재 머물러있는 페이지에 대한 정보를 알려주는 hook이다</p>
</blockquote>
<pre><code>import React from &#39;react&#39;;
import { useLocation } from &#39;react-router-dom&#39;;

const Home = (): JSX.Element =&gt; {
  const location = useLocation();
  console.log(location);

  return (
    &lt;&gt;&lt;/&gt;
  );
}

export default Home;</code></pre><p>위 코드에서 console을 찍어보면,  pathname과 search라는 객체을 알 수 있다.</p>
<p>pathname은 만약 웹 url이 <a href="http://localhost:3000/home?keyword=%EB%A6%AC%EC%95%A1%ED%8A%B8">http://localhost:3000/home?keyword=리액트</a> 이라고 가정했을때, 쿼리스트링을 제외한 /home이 출력 된다</p>
<p>search는 쿼리스트링을 분석해야하는 상황에서 유용하다. 앞에서 pathname이 출력했던 부분을 제외한 쿼리스트링이 출력되며, 결과는 ?keyword=리액트 라는 출력결과가 나온다. 출력된 값은 query-string이라는 쿼리스트링 파싱 라이브러리를 이용하여 제대로 된 값을 얻어낼 수 있다.</p>
<pre><code>import React from &#39;react&#39;;
import { useLocation } from &#39;react-router-dom&#39;;
import queryString from &#39;query-string&#39;;

const Home = (): JSX.Element =&gt; {
  const { search } = useLocation();
  // search: ?keyword=리액트

  const { keyword } = queryString.parse(search);
  // keyword 출력결과: &quot;리액트&quot;

  return (
    &lt;&gt;&lt;/&gt;
  );
}

export default Home;
</code></pre><br>

<h3 id="✅-useparams">✅ useParams</h3>
<blockquote>
<p> useParams는 path parameter의 정보를 얻을 수 있는 hooks이다.</p>
</blockquote>
<p>기존에는 match props를 이용하여 match.params.id의 형식으로 접근을 해야 했지만, useParams를 이용하면 좀 더 간단하게 접근 가능하다.</p>
<pre><code>import React from &#39;react&#39;;
import { useParams } from &#39;react-router-dom&#39;;

const Home = () =&gt; {
  const { id } = useParams();
  // 동적 라우팅 값으로 걸어둔 이름으로 객체를 가져올 수 있다.

  // 현재 주소의 값이 http://localhost:3000/home/3 일때
  console.log(id); // &quot;3&quot;이 출력된다.

  return (
    &lt;&gt;&lt;/&gt;
  );
};

export default Home;</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[TIL 33 - React Function & hook (1)]]></title>
            <link>https://velog.io/@jjung-developer/TIL-33-React-Function-hook</link>
            <guid>https://velog.io/@jjung-developer/TIL-33-React-Function-hook</guid>
            <pubDate>Sat, 14 Aug 2021 14:03:12 GMT</pubDate>
            <description><![CDATA[<h1 id="react-hook">React Hook</h1>
<blockquote>
<p>원래 class에서만 state를 사용하여 state의 값을 관리할 수 있었다.
hook이 나오게 되면서 Function에서도 state를 사용할 수 있게 됐다. 이러한 계기로 function이 class와 같은 급으로 부상하게 되었다. 또한 라이프 사이클도 사용할 수 있게 되었다</p>
</blockquote>
<br>

<h2 id="👉🏻-함수형에서-props를-받기">👉🏻 함수형에서 props를 받기</h2>
<p>매개변수로 들어가는 변수명은 아무렇게나 지어도 된다 (보기 편하게 props로 넣었다.)</p>
<pre><code>function FuncComp (props) {
  return(
    &lt;div className=&quot;container&quot;&gt;
      &lt;p&gt;{props.initNumber}&lt;p&gt;
    &lt;/div&gt;
  )
}</code></pre><br>
<hr>
<br>

<h2 id="👉🏻-함수-내장-hook">👉🏻 함수 내장 hook</h2>
<h3 id="✍🏻-state를-호출하는-usestate">✍🏻 state를 호출하는 useState()</h3>
<blockquote>
<p>useState는 length가 2인 배열을 반환한다. [0]에는 초기값이 들어가고, [1]에는 setState함수가 들어간다.
<br>
이러한 useState를 나타내는 방법으로는</p>
</blockquote>
<pre><code>const [age,setAge] = useState(26)</code></pre><br>

<h3 id="✍🏻-라이프-사이클을-나타-낼-수-있는-useeffect">✍🏻 라이프 사이클을 나타 낼 수 있는 useEffect()</h3>
<blockquote>
<p>첫번째 인자로 함수가 들어가고 render가 끝난 후 호출된다.
마치 class함수의 componentDidMount와 componentDidUpdate와 같다.</p>
</blockquote>
<pre><code>const [count, setCount] = useState(0);

  useEffect(() =&gt; {
    document.title = `You clicked ${count} times`;
  });</code></pre><blockquote>
<p>그럼 componentWillUnMount는 어떻게 호출할까?
return에 함수를 주게되면 return 함수가 실행될때 componentWillUnMount와 같다.</p>
</blockquote>
<pre><code>useEffect(() =&gt; {
    function handleStatusChange(status) {
      setIsOnline(status.isOnline);
    }
    ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
    // effect 이후에 어떻게 정리(clean-up)할 것인지 표시합니다.
    return function cleanup() {
      ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
    };
  });</code></pre><h4 id="🔥-불필요한-render를-막는법">🔥 불필요한 render를 막는법</h4>
<pre><code>const [count, setCount] = useState(0);

  useEffect(() =&gt; {
    document.title = `You clicked ${count} times`;
  },[count]);</code></pre><blockquote>
<p>위 코드의 useEffect안에는 count 변수만 있다. 하지만 컴포넌트 내의 다른 변수들이 상태값이 바뀌면 다른 변수들도 render가 새로 된다. 이렇게 불필요한 render를 막는 방법이 있을까? useEffect의 두번째 인자로 해당 변수를 추가해주면 count 변수가 바뀌지 않는다면 다른 변수의 상태값이 바뀌어도 render가 되지 않는다.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Project] motemote 클론 코딩 회고록]]></title>
            <link>https://velog.io/@jjung-developer/Project-%EB%AA%A8%ED%8A%B8%EB%AA%A8%ED%8A%B8-%ED%81%B4%EB%A1%A0-%EC%BD%94%EB%94%A9</link>
            <guid>https://velog.io/@jjung-developer/Project-%EB%AA%A8%ED%8A%B8%EB%AA%A8%ED%8A%B8-%ED%81%B4%EB%A1%A0-%EC%BD%94%EB%94%A9</guid>
            <pubDate>Fri, 13 Aug 2021 07:46:37 GMT</pubDate>
            <description><![CDATA[<h1 id="🔥-motemote-클론-코딩-회고록">🔥 motemote 클론 코딩 회고록</h1>
<blockquote>
<p>위코드에 들어온지 한달이 되던 날, 우리는 1차 프로젝트를 시작했다. 불과 한달 전까지만해도 for문 if문을 겨우 돌리는 우리였는데,, 플젝을 시작하라니 ... 😱 역시나 예상대로 처음엔 우여곡절도 많았고 너무 힘들었다 하지만 너무너무너무 얻은게 많은 나의 첫 플젝 🥺</p>
</blockquote>
<br>
<hr>
<br>

<h2 id="✍🏻-1차-sprint">✍🏻 1차 Sprint</h2>
<blockquote>
<p>조 편성이 발표 됐고, 우리는 곧장 만나 사이트를 확인했다.
사실 모트모트 사이트를 나현님 발표때 들어보긴 했는데 그 때 들은 것을 제외하면 초면인 사이트였다.
모트모트는 문구류를 파는 쇼핑몰이었고 flow는 딱 기본적인 쇼핑몰이었다.</p>
</blockquote>
<br>

<h3 id="👉🏻-nav-footer">👉🏻 Nav, Footer</h3>
<p><img src="https://images.velog.io/images/jjung-developer/post/53c3bc0a-cdb6-4632-bc92-069bc82fb10d/%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-08-13%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%206.32.01.png" alt="">
<img src="https://images.velog.io/images/jjung-developer/post/a61977cd-4421-472b-a42e-300c721ed371/%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-08-13%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%206.32.13.png" alt=""></p>
<blockquote>
<p>우선 내가 빨리 쳐낼 수  있는 css 요소가 대부분인 nav,footer를 맡았다.
실제로도 멘토님들의 빠른 피드백과 수정, merge가 이뤄졌다.</p>
</blockquote>
<br>

<h3 id="👉🏻-mian">👉🏻 <strong>Mian</strong></h3>
<p><img src="https://images.velog.io/images/jjung-developer/post/1b2f838f-1996-4e24-87c9-38b84495f12d/Aug-13-2021%2018-38-43.gif" alt=""></p>
<blockquote>
<p><strong>1. 슬라이드 구현</strong></p>
</blockquote>
<ul>
<li>라이브러리 slick을 써서 구현했었다! slick는 퍼블리셔때 많이 써봤던 라이브러리라 음,, 다를게 없네,, 쉬운데? 하고 썻는데 라이브러리는 1차때 쓰면 안된다는 사실을 뒤늦게 알았다 ^^ ㅎㅎㅎㅎㅎㅎ 부랴부랴 로직을 짜기 위해 노트와 펜을 꺼냈던 기억이... 로직이 그렇게 어렵지 않아 큰 이슈없이 구현했던 기능이다.</li>
</ul>
<blockquote>
<p><strong>2. BEST ITEM</strong></p>
</blockquote>
<ul>
<li>Best Item api를 fetch를 통해 받아와 뿌려줬다</li>
<li>조건부 랜더링을 통해 할인금액이 있으면 밑에 빨간색으로 할인금액을 표출시켰고 원가에는 line-through를 주어 삭제(?)처럼 표출시켰다</li>
<li>조건부 랜더링을 통해 stock(재고)이 0일 경우 sold out라벨을 표출시켰다.</li>
<li>이미지는 master가 어떤 비율로 올릴지 모르니까, 이미지가 비율대로 줄어들 수 있도록 css를 적용시켰다. <em><strong>(참고로 이 코드는 내가 퍼블리셔때부터 자주 쓰던 코드이다! 좋은건 나눠쓰기! 저한테 찾아오면 코드 설명을 자세히 해드리겠습니다 😇)</strong></em>
<img src="https://images.velog.io/images/jjung-developer/post/afba03dc-2671-4f3a-bfb6-b84fb14e720e/code.png" alt=""></li>
</ul>
<br>

<h3 id="👉🏻-productlist">👉🏻 ProductList</h3>
<p><img src="https://images.velog.io/images/jjung-developer/post/023d8132-907c-47cd-aaa1-a7716fd226ee/Aug-14-2021%2015-33-42.gif" alt=""></p>
<blockquote>
<p><strong>3. Product List</strong></p>
</blockquote>
<ul>
<li>BestItem에 있던 레이아웃과 동일!</li>
<li>color filter를 api로 받아오는 것이 아니는 해당 컬러가 display:block, display:none이 되도록 코딩하였다.</li>
<li><span style="color:red"><strong>자세한 설명은 아래에서 하겠다!!!</strong></span></li>
</ul>
<br>
<hr>
<br>

<h2 id="✍🏻-2차-sprint">✍🏻 2차 Sprint</h2>
<blockquote>
<p>1차 스프린트가 금요일날 끝나고, 나는 주말내내 리뷰 post와 get을 위해 공부를 했다. 특히 이미지를 첨부파일로 올리는 방식을 하고싶었기때문에 <strong>form Data를 사용</strong>하여 로직을 짜놨다. form Data를 구글링 하던중 <strong>FileReader</strong>도 알게 되어 같이 공부를 했다. (back api가 완성 된 상태가 아니라 테스트도 못해보고 혼자 생각해서 로직을 짯어야 했다 🥺) 또한 axios도 같이 공부하여 <strong>fetch 대신 write에는 axios를 사용</strong>했다.
<br>
생각보다 코딩이 너무 일찍끝나버렸다...ㅎ 처음에 리뷰를 하고싶었던 이유는 form data도 있었지만 완전한 CRUD를 하고싶었다. 그치만 아직 다른 팀원들은 작업중이기에.. 시간이 촉박해보여 <strong>나현님과 같이 장바구니를 하기로 하였다.</strong>
나현님이 레이아웃 및 컴포넌트는 전부 나눠놓으신 상태였고, 같이 get post path delete만 api통신을 하면 되는 상태였다.</p>
</blockquote>
<br>


<h3 id="👉🏻-review">👉🏻 Review</h3>
<p><img src="https://images.velog.io/images/jjung-developer/post/e92cc0a5-3c7f-4cd7-8097-adfcd3396ad4/Aug-14-2021%2016-06-53.gif" alt="">
<img src="https://images.velog.io/images/jjung-developer/post/bdf29f82-3834-4318-8854-673823a51540/Aug-14-2021%2015-54-00.gif" alt=""></p>
<blockquote>
</blockquote>
<p><strong>1. 리뷰 get</strong></p>
<ul>
<li>api의 결과 값에 따라 alert창을 띄워주었다. (리뷰 권한이 없습니다!,로그인 후 이용해주세요!,이미 작성하신 상품입니다!)</li>
<li>모든 조건이 맞았을 때 this.props.history.push을 이용하여 페이지를 이동하며 state에 itemId값을 들고 갔다</li>
<li>모든 리뷰 리스트의 별점을 배열로 만들어 reduce를 이용하여 리뷰 평균 평점을 나타냈다</li>
</ul>
<blockquote>
<p><strong>2. 리뷰 post</strong></p>
</blockquote>
<ul>
<li>별점을 onMouseOver와 dataset을 이용하여 마우스가 hover했을때 별점이 반응하도록 했고, 클릭했을때는 고정값으로 값을 넘겨주었다.</li>
<li>FormData를 이용하여 axios로 body를 보내주었다</li>
<li><span style="color:red"><strong>자세한 설명은 아래에서 하겠다!!!</strong></span></li>
</ul>
<br>

<h3 id="👉🏻-cart">👉🏻 Cart</h3>
<p><img src="https://images.velog.io/images/jjung-developer/post/fff7d7fc-6bf3-47bd-b4fa-ad9e27318a3b/Aug-14-2021%2016-34-16.gif" alt=""></p>
<blockquote>
<p><strong>1. 수량변경</strong></p>
</blockquote>
<ul>
<li>업,다운 버튼을 누르면 수량이 변경되며 총 결제 금액이 바뀐다.</li>
<li><span style="color:red"><strong>자세한 설명은 아래에서 하겠다!!!</strong></span></li>
</ul>
<blockquote>
<p><strong>2. 삭제</strong></p>
</blockquote>
<ul>
<li>삭제를 누르면 해당 아이템 삭제된다</li>
<li><span style="color:red"><strong>자세한 설명은 아래에서 하겠다!!!</strong></span></li>
</ul>
<blockquote>
<p><strong>3. 장바구니로 이동하는 팝업 문구</strong></p>
</blockquote>
<ul>
<li>만약에 장바구니에 해당 아이템이 있으면 &quot;이미 있는 상품입니다. 장바구니에 추가하시겠습니까?&quot; 해당 아이템이 없으면 &quot;장바구니로 이동하시겠습니까?&quot;라고 뜬다.</li>
<li>여기에 대한 이야기도... <span style="color:red"><strong>자세한 설명은 아래에서 하겠다!!!</strong></span></li>
</ul>
<br>
<hr>
<br>

<h2 id="✍🏻-우여곡절-우당탕탕-🤸🏻♂️">✍🏻 우여곡절 우당탕탕 🤸🏻‍♂️</h2>
<h3 id="✅-git">✅ git</h3>
<blockquote>
<p>브랜치에 익숙하지 않아 계속 한 브랜치에서 여러 작업을 하고 다른 브랜치로 옮겨갈때 기존에 브랜치에서 작업했던 작업물이 날라가는 일이 발생하였다 😱
다행이 간단한 css파일이라 금방 작업을 다시 했지만 다시는 이런일이 반복되면 안되니까... 온 사방에 🌟브랜치 확인 브랜치 확인🌟 이라는 문구를 써놓고 남은 플젝을 이어갔었다!</p>
</blockquote>
<br>

<h3 id="✅-product-list">✅ Product List</h3>
<h4 id="🔥-1차-시도">🔥 1차 시도</h4>
<p><img src="https://images.velog.io/images/jjung-developer/post/7e32af5c-33ab-4ed6-9c2e-a3caaa0d5942/code2.png" alt=""></p>
<blockquote>
<p>state에 selectColor를 넣어 선택을 한 color가 selectColor에 넣어지게 했었다.
그렇게 했더니... state에 있는 selectColor가 모든 section에 적용이 되니 다른 section에도 해당 color가 적용이 되어 버렸다 🥺</p>
</blockquote>
<br>

<h4 id="🔥-2차-시도">🔥 2차 시도</h4>
<p><img src="https://images.velog.io/images/jjung-developer/post/316467b6-bdf8-480a-876d-9ba1f87a600b/code3.png" alt="">
<img src="https://images.velog.io/images/jjung-developer/post/807abc03-363e-4ed6-9cb6-33197db428c9/code4.png" alt=""></p>
<blockquote>
<p>무한 삽질을 하고 있었던 나에게... 성훈님이 state에 담는 color값을 배열로 받아 그 인덱스와 section Index가 일치하게 하면 되지 않을까요? 라고 힌트를 쓱 던져주고 사라지셨다..ㅎㅎ 다시 또 무한 삽질 중 드디어 됐다!!! 🧚🏻‍♀️
<br>
Array() 내장함수를 통해 원하는 배열만큼 길이를 만들어주고, fill을 통해 &#39;&#39;빈 값으로 배열을 만들었다. 해당 color를 클릭했을 때 clickColorDefault함수를 실행시켰다. clickColorDefault함수는 dataset을 통해 color값을 받아 오고, 그 컬러 값을 selectColorset의 인자값으로 sectionIndex값과 함께 넘겨준다.
selectColorSet은 배열의 불변성을 유지하기 위해 스프레드 연산자를 통해 새로운 변수에 복사를 해주고, sectionIndex 값에 color값을 넣어주고 setState을 해준다!
<br>
data-set의 활용을 처음 알게 해준 color Filter,,,! 사실 api를 받아와 get을 해주면 쉬운 작업이었겠지만 조금은 다른 방식으로 해보고 싶었다 (실무에서는 api을 받아와 뿌려주는 방식을 더 많이 쓰겠지...?ㅎㅎ)</p>
</blockquote>
<br>

<h3 id="✅-review-post">✅ Review post</h3>
<p><img src="https://images.velog.io/images/jjung-developer/post/a27bbe56-bbe9-48b2-88c7-2bd8ed2d0455/code5.png" alt=""></p>
<blockquote>
<p>하나도 버릴 것 없는 코드,,,,, 🧚🏻‍♀️
정말정말 고생 많이 했던 코드다 🥺...
<br>
주말에 <a href="https://velog.io/@jjung-developer/TIL-32-FormData">Form Data와 FileReader를 공부하며 작성했던 코드</a>! 
드디어 백과 맞춰보는 날...! 두근두근 
500에러^~^ ㅎㅎㅎㅎㅎ
500에러가 떳어도 나는 안심하지 못했다 ㅠㅠ,, api문제가 큰 확률로 500에러가 뜨지만 양쪽 다 처음 하는 작업이기에 혹여나 내 잘못일수도 있기에 여기 저기 종성님 선호님과 함께 알아봤다. 알아본 결과! 나는 form Data로 데이터를 주고 있었는데, api에서는 json으로 받고있으니 이게 될리가 없었다 🤦🏻‍♀️
선호님과 종성님이 이틀동안 작업한 결과,,, 성공 🧚🏽‍♂️
셋이서 엑박이 아닌 사진이 뜨는걸 보고 소리를 질렀다 🥳 ㅎㅎㅎㅎㅎㅎㅎㅎ
<br>
정말 API의 중요성을 느꼈던 부분이었다. 내가 원하는 기능이 있는데 API가 없으면 어쩌지? 혹은 반대로 백은 API구현을 다 해놨는데 내가 그걸 앞에서 못받아주면 어쩌지? 라는 생각이 들었다. 내가 원하는 기능을 끝까지 붙들고 API를 만들어준 종성님과 선호님께 너무 감사한마음이 든다 👍🏻</p>
</blockquote>
<br>

<h3 id="✅-cart-수량변경">✅ Cart 수량변경</h3>
<blockquote>
<p>나현님이 sos를 했던 수량변경 부분
<strong>문제상황</strong>은
detail에서 수량이 정해져서 cart로 넘어오는데 up버튼과 down버튼을 눌렀을때 +1씩 total금액이 늘어나는 것이 아닌 +1을해도 detail에서 수량이 정해져 온 만큼 늘어나는 것이었다!
<br>
나는 <strong>index를 이용하여 내가 클릭한 이벤트 index와 같으면 그 객체의 수량만 up시켜주기</strong> 라는 로직이 떠올랐다.
map을 통해 아이템들을 출력시키고 있었기에 그렇게 클릭한 이벤트의 index를 찾았는데... 찾았는데.... 어떻게 +1시키지....?ㅎㅎ...
성훈님 sos!!! 
<em><strong>&quot;로직은 굳! 불변성을 지키면서 +1시키면 됩니다!&quot;</strong></em>
<br>
나는 문득 종택님의 위스타그램 코드 리뷰가 생각났고! 그걸 활용해서 우리는 코드를 작성했다!
<br>
마지막으로 도현님이 +1과 -1함수가 같은데 합칠 수 있지 않을까요? 라고 말씀을 해주셨고 드디어 나온 최종코드 💫</p>
</blockquote>
<p><img src="https://images.velog.io/images/jjung-developer/post/323dfb00-3d46-4cd0-b481-bb0e16d97161/code7.png" alt=""></p>
<br>

<h3 id="✅-cart-버튼이-왜-맘대로-작동하지🤯">✅ Cart 버튼이 왜 맘대로 작동하지..🤯</h3>
<blockquote>
<p>api를 호출 하려면 Index가 필요해 index를 인자로 받오는 함수였다.
버튼을 onClick을 하면 함수를 호출하도록 했고, 그렇게 했더니..... 왜 페이지가 로딩 되자마자 함수가 작동하는거지??? ()을 안쓰면 어떻게 하지?? 매개변수로 넘겨줘야하는데???? 😱
<br>
콜백에 화살표 함수를 사용하면 됩니다!!!!
정말 쓸모가 많을 것 같은 코드이다 🔥</p>
</blockquote>
<p><img src="https://images.velog.io/images/jjung-developer/post/7f0e4afa-db35-494c-a9b9-5f44fc167a03/code78.png" alt=""></p>
<br>

<h3 id="✅-cart-삭제">✅ Cart 삭제</h3>
<blockquote>
<p>delete api는 뭐 삭제만 하면 되니까 쉽지~ 라는 나의 큰 착각...🌟
<br>
<strong>문제상황</strong>은 삭제버튼을 클릭하면 db에는 삭제가 제대로 실행이 되는데 우리 쪽에서는 다시 get을 해줘도 새로고침이 되지 않아 수동으로 새로고침을 해야하는 상황이었다! 이걸로 4시간을 붙잡고 있었다~~
이것때문에 점심도 안먹으려는거 선호님이 점심먹는데 데리고 가주셨다....
<br>
4시간을 삽질한 결과는 조금은 허무했다..(아니야 얻은게 많아.... 호정아)</p>
</blockquote>
<pre><code>.then(data =&gt; data.json())
.then(data =&gt; {
  this.getCartData();
});</code></pre><p>처음에 작성했던 코드이다.
여기서 나는 대단한 착각을 했었다. 이거는 get이 아니라 post인데 then을 통해서 나는 뭘 받아오는데??? 왜 data를 json으로 파싱하고 있었지???
api에서는 성공을 해도 아무것도 보내주질 않는데... 왜냐구? post니까!! (MESSAGE를 받을 수 도 있지만 해당 api는 MESSAGE를 보내주지 않고 있었다...)
<br>
data를 받아오는 것이 아닌 status를 받아와 status가 204일때, get을 하는 함수를 실행하도록 로직을 바꾸었다.
정말 너무 힘들었던 4시간이었다... 🤯 중간에 울뻔했던건 비밀 ^-^</p>
<p><img src="https://images.velog.io/images/jjung-developer/post/80f862d0-b39c-47c7-a5aa-beb93d7f221a/code9.png" alt=""></p>
<br>

<h3 id="✅-cart로-이동하는-팝업-문구">✅ Cart로 이동하는 팝업 문구</h3>
<blockquote>
<p>결과부터 말하자면 이 부분은 포기한 부분이다.. 🙇🏻‍♀️ (포기는 아니고.. 효율성을 위해.... 음...🤔)
결국엔 종성님과 선호님이 api에서 처리해주는 걸로 해주신 부분..
<br>
<strong>문제상황</strong>은 장바구니에 해당 아이템이 있으면 &quot;이미 있는 상품입니다. 장바구니에 추가하시겠습니까?&quot; 문구가 해당 아이템이 없으면 &quot;장바구니로 이동하시겠습니까?&quot;문구가 뜨고 이동하는 api uri도 달라 버튼도 각각 만들어주어야했다.
조건문을 통해 문구를 제어하면 쉽게 풀리지않을까? 라고 생각했었다.. 근데 왜 자꾸 반대로 뜨니....? 그럼 반대로 if문을 적자!! 응? 왜 텍스트랑 uri가 반대니...? 이 루트를 무한 반복 겪는데....
선호님과 종성님이 😇처럼 나타나 api에서 처리해주는 걸로 바꿔주셨다...
당장 내일이 발표라 해결된 것만 확인하고 넘어갔다
<br>
뒤늦게 확인을 해보니 부모 컴포넌트에서 map이 돌아가고 있고 자식 컴포넌트에도 조건부 렌더링이 걸려있는데... 이게 문제였을까...? 아무튼 해결과는 별개로 너무 아쉬웠던 부분이었다 🥺</p>
</blockquote>
<br>

<h3 id="✅-동적라우팅">✅ 동적라우팅</h3>
<blockquote>
<p>뭔가 그냥 멀리서 봤을때부터 어려워 보였던 동적 라우팅...
1차 스프린트때 연욱님께 한 5번 물어보고.. 도현님께도 3번정도 물어본 부분이다 ㅎㅎ 두 분다 2차 스프린트 가게되면 하게 될거라고 이야기 하셨지만
나는 그냥 얼른 해버리고 싶었다 .. 성격급한거 여기서 나오고.. ㅋㅋㅋ
그래서 1차 스프린트를 마무리 하며 내가 구현한 nav -&gt; list, main-&gt;detail부분까지는 잡아 놨었다.
<br>
종성님이 주신 api명세서 보고 뚝딱 하니 너무 신기하게도 정말 뚝딱 하고 내가 원하는 화면이 나왔다 😱
그렇게 한번 물꼬가 트이니 2차스프린트 막바지에서도 동적 라우팅 부분에서 막힌 것 없이 술술 흘러갔다! (다른 부분에서 오류 폭팔이었지만 🔥)</p>
</blockquote>
<br>
<hr>
<br>

<h2 id="📌-나의-첫-프로젝트를-마치며">📌 나의 첫 프로젝트를 마치며..</h2>
<p>여기까지 회고록을 작성하는데 5시간 정도 걸린 것 같다..
그만큼 내가 배운게 많고, 느낀점이 많았다는거겠지?</p>
<p>처음 팀원이 발표 됐을때 다들 말을 몇번 해보지 않은 분들이 대부분이 었다.. 아니 대부분이 아니라 전부였다 😅
백분들과의 소통도 걱정을 많이 했었는데(아무래도 양쪽 다 처음인 상황이었고 백이 무엇을 원하는지, 어떻게 구현을 하는지 무지해 막연히 두려웠었다),
나현님의 리드로 충돌 한 번 없이 물 흘러가듯 흘러갔던 우리들의 첫 프로젝트</p>
<p>개인적으로는 힘들었던 시간도 있었다. 내 성격에 내가 스트레스를 받아 팀원들 앞에서 눈물을 보였던 일도 있었다. 나는 한 번 시작한 일은 끝을 봐야하는 사람이다. 그리고 기한이 정해져 있으면 무조건 그 전에 끝내놔야한다. 이러한 성격이 나한테 너무 큰 압박으로 다가온것같았다. 나는 욕심도 많아서 (이러니까 되게 못되먹은 사람같.... 아닌데...🥺) 코드가 깔끔했으면 좋겠고, 간결했으면 좋겠다 그런데, 기한이 정해져 있으니 코드를 정리 할 시간이 너무 촉박했다.
그런 시간이 있고 난 후 , 선호님이 &quot;우리 금요일이 발표니까 수요일까지 기능구현 하는걸로 하고 그 이후로 안돼는 기능들은 그냥 깔끔하게 포기해요!&quot; 라고 말씀을 하셨고 뭔가 나는 그때 이후로 마음을 비웠던 것 같다.. 내가 할 수 있는 능력치에서 최선을 다 하자고 그리고 그 외의 영역들은 다음기회에 도전하면 되니까! 개발자 한달하고 관둘거 아니니까!! 🥳  그렇게 1차 스프린트가 끝났고 2차 스프린트는 부담없이! 정말 개발을 즐겼던거 같다! (+나현님과 같이 장바구니를 구현해서 그런거일지도 ㅎㅎㅎ)</p>
<p>그렇게 부담없이 진행하다보니 결과물은 만족스러웠다! 우리가 발표할때 지선님이 &quot;선배기수들꺼 리팩토링한거 아니죠?&quot; 라고 말씀 하셨고 우리도 너무너무너무너무 만족했었다!!!</p>
<p>물론 아쉬웠던 부분들도 있었지만...</p>
<ul>
<li>컴포넌트 분리 (메인 베스트아이템과 productlist는 같은 컴포넌트를 써서 구현할 수 있지 않았을까)</li>
<li>리뷰 수정/삭제 구현</li>
<li>fetch, axios 예외처리 등등...</li>
</ul>
<p>리팩토링을 통해 몇몇개는 수정하겠지만 전체적인 로직이 바뀌는 일은 아무래도 오랜 시간이 걸릴것같다.</p>
<p><img src="https://images.velog.io/images/jjung-developer/post/18c19146-a5b0-427d-8b51-9ff28730937d/iOS%20%E1%84%8B%E1%85%B5%E1%84%86%E1%85%B5%E1%84%8C%E1%85%B5.jpg" alt=""></p>
<p>마지막으로 한번의 다툼 없이 2주동안 12시간씩 코딩했던 우리 팀원들 ❤️
2차 스프린트때는 로비에 6명이 거의 붙박이었다 ㅋㅋㅋㅋㅋㅋㅋ
다른 팀들이 우리가 없어 방이 너무 추웠다고...</p>
<br>
<br>

<p>1차 프로젝트 잘 놀다 갑니다 🔥🔥🔥🔥🔥
<img src="https://images.velog.io/images/jjung-developer/post/ad7062ab-dfda-407e-8b92-fdc346703605/%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-08-13%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%201.58.32.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[TIL 32 - FormData & FlieReader]]></title>
            <link>https://velog.io/@jjung-developer/TIL-32-FormData</link>
            <guid>https://velog.io/@jjung-developer/TIL-32-FormData</guid>
            <pubDate>Sun, 08 Aug 2021 08:10:27 GMT</pubDate>
            <description><![CDATA[<h1 id="👉🏻-formdata">👉🏻 FormData</h1>
<blockquote>
<p>FromData란 ajax로 폼 전송을 가능하게 해주는 FormData 객체이다.
보통은 Ajax로 폼(form 태그) 전송을 할 일이 거의 없다.
주로 JSON 구조로 &quot;KEY-VALUE&quot; (키와 값) 구조로 데이터를 전송한다.
하지만, form전송이 필요한 경우가 있는데, 이미지를 ajax로 업로드할 때 필요하다.
이미지는 base64, buffer, 2진 data 형식으로 서버로 전송해도 된다.</p>
</blockquote>
<br>

<h2 id="✍🏻-formdata-만들기">✍🏻 FormData 만들기</h2>
<pre><code>let formData = new FormData();
formData.append(&#39;name&#39;, &#39;zerocho&#39;);
formData.append(&#39;item&#39;, &#39;orange&#39;);
formData.append(&#39;item&#39;, &#39;melon&#39;);</code></pre><blockquote>
<p><code>new FormData()</code>로 새로운 객체를 생성해준다. append 메소드로 key-value 형식으로 하나씩 추가한다. 같은 키를 가진 값을 여러 개 넣을 수도 있다. 덮어씌워지지 않고 추가된다.</p>
</blockquote>
<br>
append로 넣을 수만 있는 게 아니라 내용물을 확인할 수도 있다.

<pre><code>formData.has(&#39;item&#39;); // true
formData.has(&#39;money&#39;); // false
formData.get(&#39;item&#39;); // orange
formData.getAll(&#39;item&#39;); // [&#39;orange&#39;, &#39;melon&#39;]</code></pre><blockquote>
<p>has 메소드로는 해당하는 키가 존재하는 지 확인할 수 있다. get 메소드로 직접 가져올 수 있다. 유의할 점은 get은 처음 저장한 값 하나만 불러온다.</p>
</blockquote>
<br>
<hr>
<br>

<h2 id="✍🏻-formdata-지우기">✍🏻 FormData 지우기</h2>
<blockquote>
<p>delete 메소드를 사용하면 된다. append와 비슷한 set 메소드가 있는데, set과 append의 차이점은 set도 추가를 해주기는 하지만, 기존 키가 있으면 그 값을 모두 덮어씌워버린다.</p>
</blockquote>
<pre><code>formData.delete(&#39;test&#39;);
formData.set(&#39;item&#39;, &#39;apple&#39;);</code></pre><br>
<hr>
<br>

<h1 id="👉🏻-fliereader">👉🏻 FlieReader</h1>
<blockquote>
<p>웹 애플리케이션이 비동기적으로 데이터를 읽기 위하여 읽을 파일을 가리키는 File혹은 Blob객체를 이용해 파일의 내용을(혹은 raw data버퍼로) 읽고 사용자의 컴퓨터에 저장하는 것을 가능하게 한다.</p>
</blockquote>
<br>

<h2 id="✍🏻-filereaderonload">✍🏻 FileReader.onload()</h2>
<blockquote>
<p>load 이벤트의 핸들러. 이 이벤트는 읽기 동작이 성공적으로 완료되었을 때마다 발생한다.
비동기이므로 원하는 동작을 위해 CALLBACK 함수를 이용하는 것이 좋다.</p>
</blockquote>
<br>


<h2 id="✍🏻-filereaderreadastextfile-encoding">✍🏻 FileReader.readAsText(FILE, ENCODING)</h2>
<blockquote>
<p>파라미터 : 1. 읽을 객체, 2. 인코딩
특정 파일, Blob객체를 텍스트로 읽기 시작하며 두번째 파라미터로 읽을 때 사용되는 인코딩을 지정할 수 있다.</p>
</blockquote>
<ul>
<li>참고 
<a href="https://developer.mozilla.org/en-US/docs/Web/API/FileReader/FileReader">https://developer.mozilla.org/en-US/docs/Web/API/FileReader/FileReader</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[TIL 31 - 얕은 복사(shallow copy) VS 깊은 복사(deep copy)]]></title>
            <link>https://velog.io/@jjung-developer/TIL-31-%EC%96%95%EC%9D%80-%EB%B3%B5%EC%82%ACshallow-copy-VS-%EA%B9%8A%EC%9D%80-%EB%B3%B5%EC%82%ACdeep-copy</link>
            <guid>https://velog.io/@jjung-developer/TIL-31-%EC%96%95%EC%9D%80-%EB%B3%B5%EC%82%ACshallow-copy-VS-%EA%B9%8A%EC%9D%80-%EB%B3%B5%EC%82%ACdeep-copy</guid>
            <pubDate>Sat, 31 Jul 2021 05:38:07 GMT</pubDate>
            <description><![CDATA[<p><img src="https://images.velog.io/images/jjung-developer/post/9b296373-728b-4944-a1f1-f78181740b97/%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-31%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.04.57.png" alt=""></p>
<blockquote>
<p>종택님의 코드리뷰로 공부하게 된 얕은 복사와 깊은복사
사전스터디 기간 js를 공부하며 얼핏 들었던 개념이었다. 그치만 그때는 deep한 지식보다 기초를 쌓기 바빳기 때문에 그냥 넘어갔는데 플젝 시작전 정리 할 수 있는 기회가 생겼다 💪🏻</p>
</blockquote>
<br>
<hr>
<br>

<h1 id="👉🏻-얕은-복사shallow-copy">👉🏻 얕은 복사(shallow copy)</h1>
<pre><code>const obj = {name:&quot;hojung&quot;};
const newObj = obj;
newObj.name = &quot;jungmin&quot;;
console.log(obj); // { name: &#39;jungmin&#39; }
console.log(newObj); // { name: &#39;jungmin&#39; }</code></pre><blockquote>
<p>왜 obj를 newObj로 복사해 newObj의 name값을 바꾸면 obj까지 영향을 미치는 것일까?
위와 같은 코드를 <code>얕은 복사</code>라고 부른다.
그렇다면, <em><strong>obj가 불변함을 가지고 있으려면 어떻게 해야할까?</strong></em></p>
</blockquote>
<br>
<hr>
<br>

<h1 id="👉🏻-깊은-복사deep-copy">👉🏻 깊은 복사(deep copy)</h1>
<pre><code>const obj = {name:&quot;hojung&quot;};
const newObj = Object.assign({},obj);</code></pre><blockquote>
<p>obj를 newObj에 복사를 해준다 (<a href="https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Object/assign">Object.assign메소드 mdn문서 참고</a>)</p>
</blockquote>
<br>


<pre><code>newObj.name = &quot;jungmin&quot;
console.log(newObj); // { name: &#39;jungmin&#39; }
console.log(obj); // { name: &#39;hojung&#39; }</code></pre><blockquote>
<p>복사한 객체의 name에 jungmin값을 넣는다. 
이렇게 복사하여 새로운 객체를 만들게 되면 원본객체인 obj가 불변함을 유지할 수 있고, 동시에 복제본을 변경 시키는 것을 통해 가변적까지 달성 할 수 있다.</p>
</blockquote>
<br>
<hr>
<br>

<h1 id="👉🏻-중첩된-객체의-복사는">👉🏻 중첩된 객체의 복사는?</h1>
<pre><code>const obj = {name:&#39;choi&#39;, score:[1,2]}
const newObj = Object.assign({},obj);
newObj.score.push(3);
console.log(newObj); // {name:&#39;choi&#39;, score:[1,2,3]}
console.log(obj); // {name:&#39;choi&#39;, score:[1,2,3]}</code></pre><blockquote>
<p>Object.assign을 통해 객체의 프로퍼티만을 복사하고, 
value가 원시타입이 아닌, 객체타입일 경우 값을 저장하는 것이 아닌 객체의 주소 값을 저장한다. 그렇기때문에 프로퍼티값이 객체인 경우에는 값 또한 복제를 해야한다.</p>
</blockquote>
<br>

<pre><code>newObj.score = obj.score.concat();
newObj.score.push(3);
console.log(newObj); // {name:&#39;choi&#39;, score:[1,2,3]}
console.log(obj); // {name:&#39;choi&#39;, score:[1,2]}</code></pre><blockquote>
<p>concat, slice, ArryFrom,Spread Operator와 같이 복제를 해주는 배열 메서드를 사용한다. 원본에 대해 <code>불변함</code>을 유지할 수 있게된다.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[TIL 29 - map 함수 적용시 key props를 부여]]></title>
            <link>https://velog.io/@jjung-developer/TIL-29-map-%ED%95%A8%EC%88%98-%EC%A0%81%EC%9A%A9%EC%8B%9C-key-props%EB%A5%BC-%EB%B6%80%EC%97%AC</link>
            <guid>https://velog.io/@jjung-developer/TIL-29-map-%ED%95%A8%EC%88%98-%EC%A0%81%EC%9A%A9%EC%8B%9C-key-props%EB%A5%BC-%EB%B6%80%EC%97%AC</guid>
            <pubDate>Thu, 29 Jul 2021 06:05:39 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p><a href="https://ko.reactjs.org/docs/lists-and-keys.html">리액트 공식문서</a> 를 참고하여 작성한 게시글입니다.</p>
</blockquote>
<br>
<hr>
<br>

<h1 id="👉🏻-왜-오류가-나지">👉🏻 왜 오류가 나지?</h1>
<p><img src="https://images.velog.io/images/jjung-developer/post/8ad29333-359e-4c8a-afc7-87562371eb4e/%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-29%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%202.16.05.png" alt=""></p>
<blockquote>
<p>나는 그냥 컴포넌트를 나눠 map을 돌려줬을 뿐인데.. 왜 오류가 나지?</p>
</blockquote>
<p>리액트 공부 중 나타난 오류에 멘붕 🥺... 반복되는 JSX를 map을 돌려줬을 뿐인데 오류가 난다고??
해답은 공식문서를 통해 쉽게 얻을 수 있었다! 🔥</p>
<br>


<h2 id="✅-key">✅ key?</h2>
<blockquote>
<p>React에서의 <code>key</code>는 React가 반복되는 어떤 항목을 변경, 추가 또는 삭제 할 지 식별하는 것을 돕는 속성이다.</p>
</blockquote>
<p>쉽게 말해 <span style="color:red"><strong>랜더링 시 컴포넌트 배열에 어떤 변화가 일어났는지 리액트가 더욱 빠르게 알아내기 위해 사용한다.</strong></span></p>
<br>

<h2 id="✅-key-설정하기">✅ key 설정하기</h2>
<blockquote>
<p><code>key</code>를 설정하는 가장 좋은 방법은 리스트 다른 항목들 사이에서 해당 항목을 고유하게 식별 할 수 있는 문자열을 사용하는 것이다. 즉, <code>key</code>값은 언제나 유일한 값이어야만 한다.</p>
</blockquote>
<p>게시판의 게시물을 렌더링 하는 예시가 있다면, 게시물 번호를 <code>key</code>값으로 설정 할 수 있다.</p>
<pre><code>{this.state.feedList.map(feed =&gt; {
 return (
  &lt;FeedCard
   key={feed.id}
   id={feed.id}
   content={feed.content}
   writer={feed.user_name}
   imgs={feed.img}
   userId={userId}
  /&gt;
 );
})}</code></pre><p>만약, 안정적인 <code>key</code>값이 없다면 최후의 수단으로 인덱스를 <code>key</code>값으로 사용 할 수 있다. 그렇지만 이로인해 성능이 저하되거나 컴포넌트의 state와 관련된 문제가 발생 할 수 있다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[TIL 28 - 자식 컴포넌트에서 state변경]]></title>
            <link>https://velog.io/@jjung-developer/TIL-27-%EC%9E%90%EC%8B%9D-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8%EC%97%90%EC%84%9C-state%EB%B3%80%EA%B2%BD</link>
            <guid>https://velog.io/@jjung-developer/TIL-27-%EC%9E%90%EC%8B%9D-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8%EC%97%90%EC%84%9C-state%EB%B3%80%EA%B2%BD</guid>
            <pubDate>Sat, 24 Jul 2021 13:09:47 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>인스타그램 클론 코딩 컴포넌트를 나누던 중, 자식에서 setSate를 해야 할 일이 생겼다! setState는 state가 관리 되고 있는 곳에서 써야하는데,,, 어쩌지? 바로 구글링! 🔥</p>
</blockquote>
<h1 id="1️⃣-자식-컴포넌트-함수-분리">1️⃣ 자식 컴포넌트 함수 분리</h1>
<p><strong><span style="color:red;">기존 자식컴포넌트 함수</span></strong></p>
<pre><code>commentAdd = e =&gt; {
    e.preventDefault();
    if (e.target.comment.value === &#39;&#39;) {
      alert(&#39;댓글을 입력해주세요!&#39;);
      return;
    }
    const _comments = this.props.commentData.concat({
      id: this.props.userId,
      txt: e.target.comment.value,
      likeHeartBtn: false,
      key: this.props.keyData,
    });
    this.commentKey = this.commentKey + 1;
    this.setState({
      comments: _comments,
      commentBtn: true,
    });
    e.target.comment.value = &#39;&#39;;
  };</code></pre><p>여기서...!! setState 선언 부분만 쏙! 빼서 부모 컴포넌트로 선언한다</p>
<br>

<h1 id="2️⃣-부모-컴포넌트-함수-작성">2️⃣ 부모 컴포넌트 함수 작성</h1>
<p><strong><span style="color:red;">부모컴포넌트 함수 추가</span></strong></p>
<pre><code>bringState = _comments =&gt; {
    this.commentKey = this.commentKey + 1;
    this.setState({
      comments: _comments,
      commentBtn: true,
    });
  };</code></pre><p>부모 컴포넌트에 있는 setState를 하는 함수를 props로 부모 컴포넌트에 전달해준다</p>
<br>


<h1 id="3️⃣-부모-컴포넌트-함수-자식-컴포넌트에게-전달">3️⃣ 부모 컴포넌트 함수 자식 컴포넌트에게 전달</h1>
<pre><code>&lt;CommentInput
  commentData={this.state.comments}
  btnState={this.state.commentBtn}
  keyData={this.commentKey}
  onSubmit={this.bringState}
  handleButtonState={this.handleButtonState}
  userId={this.props.userId}
  commentKey={this.commentKey}
/&gt;</code></pre><p>onSubmit={this.bringState} 로 자식 컴포넌트에게 setState함수를 저달하였다</p>
<br>

<h1 id="4️⃣-자식-컴포넌트-함수-수정">4️⃣ 자식 컴포넌트 함수 수정</h1>
<pre><code>commentAdd = e =&gt; {
    e.preventDefault();
    if (e.target.comment.value === &#39;&#39;) {
      alert(&#39;댓글을 입력해주세요!&#39;);
      return;
    }
    const _comments = this.props.commentData.concat({
      id: this.props.userId,
      txt: e.target.comment.value,
      likeHeartBtn: false,
      key: this.props.keyData,
    });
    this.props.onSubmit(_comments);
    e.target.comment.value = &#39;&#39;;
  };</code></pre><p>this.props.onSubmit(_comments);로 setState를 하는 시점에 함수를 호출하여 setState를 실행시켜주었다!</p>
<br>
<hr>
<br>

<h1 id="📌-tmi">📌 TMI</h1>
<blockquote>
<p>props와 state개념을 확실하게 알지못하면 이해하기 힘든 개념이라고 생각한다 🥺 그래도 방법을 찾은 뒤 혼자 코드를 구현하는거 보면 어느정도 이해는 한 것 같다 ㅎㅎ! 리액트 플젝은 처음이라 아직 컴포넌트의 기준이 명확히 세워지지 못해 엉망이다.. 이렇게 시행착오를 겪어가며 성장해 나가는거겠지 💫</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[TIL 26 - Component / props / state ]]></title>
            <link>https://velog.io/@jjung-developer/TIL-26-Component-props-state</link>
            <guid>https://velog.io/@jjung-developer/TIL-26-Component-props-state</guid>
            <pubDate>Mon, 19 Jul 2021 15:11:39 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p><a href="https://reactjs-kr.firebaseapp.com/docs/components-and-props.html">리액트 공식문서</a>를 참고하여 작성 한 글입니다.</p>
</blockquote>
<br>
<hr>
<br>

<h2 id="👉🏻-component-">👉🏻 Component ?</h2>
<blockquote>
<p>UI을 재사용 할 수 있는 부분을 분리한 것을 말한다</p>
</blockquote>
<pre><code> function App() {
  return (
    &lt;div&gt;
       &lt;h1&gt; Hello, Sara!&lt;/h1&gt;
       &lt;h1&gt; Hello, Cahal!&lt;/h1&gt;
       &lt;h1&gt; Hello, Edite!&lt;/h1&gt;
    &lt;/div&gt;
  );
}</code></pre><p> 위와 같은 함수가 있다고 가정해보자
 여기서 h1이 반복되고 있다는 것을 알 수 있다.
 또한, Hello, (이름)! 텍스트도 안에 있는 이름만 바뀌고 모두 같은 형식을 가지고 있는 것을 알 수 있다!
 이런 UI가 반복되는 것, 즉 재사용이 가능한 부분은 컴포넌트로 나누어 관리하는 것이 효율적이다</p>
<pre><code> function Welcome(props) {
  return &lt;h1&gt;Hello, {props.name}&lt;/h1&gt;;
}

function App() {
  return (
    &lt;div&gt;
      &lt;Welcome name=&quot;Sara&quot; /&gt;
      &lt;Welcome name=&quot;Cahal&quot; /&gt;
      &lt;Welcome name=&quot;Edite&quot; /&gt;
    &lt;/div&gt;
  );
}</code></pre><p> 위 코드를 Welcome 컴포넌트로 분리해 props로 name값을 받아주어 관리하였다. 간단한 코드라 아직은 왜! 컴포넌트로 나누는 것이 효율적인 방법인지 이해가 잘 되지 않겠지만 (나도 그랬다! 😱) 컴포넌트를 분리하며 프로젝트를 하다보면 유지보수 및 가독성이 좋아지는 것을 느낄 수 있을 것이다.</p>
<br>
<hr>
<br>

<h1 id="👉🏻-props">👉🏻 props</h1>
<blockquote>
<p>props 는 properties 의 줄임말로 우리가 어떠한 값을 컴포넌트에게 전달해줘야 할 때, props 를 사용한다</p>
</blockquote>
<pre><code>function Welcome(props) {
  return &lt;h1&gt;Hello, {props.name}&lt;/h1&gt;;
}</code></pre><p>위 코드에서 name값을 전달 해주기 위해 props값을 사용하였다.
props 는 객체 형태로 전달되며, 만약 name 값을 조회하고 싶다면 <code>props.name</code> 을 조회하면 된다.</p>
<br>
<hr>
<br>

<h1 id="👉🏻-state">👉🏻 state</h1>
<blockquote>
<p>state는 (함수 내에 선언된 변수처럼) 컴포넌트 안에서 관리되는 정보이다.</p>
</blockquote>
<pre><code>this.state = {
      id: &#39;&#39;,
      pw: &#39;&#39;,
      btn: false,
    };</code></pre><p>함수의 현재 상태값을 나타낸다.
state를 변경해주고 싶다면 <code>setState</code>을 사용하여 변경 할 수 있다.</p>
<h2 id="✍🏻-setstate">✍🏻 setState</h2>
<blockquote>
<p>setState()는 컴포넌트의 state 객체에 대한 업데이트를 실행한다. state가 변경되면, 컴포넌트는 리렌더링된다</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[TIL 24 - [Pre-course] 중간 시험(1차) - <JavaScript>]]></title>
            <link>https://velog.io/@jjung-developer/TIL-24-Pre-course-%EC%A4%91%EA%B0%84-%EC%8B%9C%ED%97%981%EC%B0%A8-JavaScript</link>
            <guid>https://velog.io/@jjung-developer/TIL-24-Pre-course-%EC%A4%91%EA%B0%84-%EC%8B%9C%ED%97%981%EC%B0%A8-JavaScript</guid>
            <pubDate>Sat, 17 Jul 2021 14:57:00 GMT</pubDate>
            <description><![CDATA[<h1 id="pre-course-중간-시험">[Pre-course] 중간 시험</h1>
<blockquote>
<p>위코드 생활 2주차 프리코스가 끝났다 🥺...
아침에 데일리 킥오프 시작 -&gt; 오전공부 or 세션 -&gt; 점심 -&gt; 세션 -&gt; 과제 or 개인공부 -&gt; 저녁 -&gt; 개인공부 
10 -10이 정말 짧게 느껴졌던 2주였다..!! 앞으로는 더 빨리 가겠지...?
프리코스가 끝나며 봤던 중간시험! js를 이주 내내해서 그런가 문제 난이도가 많이 어려운편은 아니었던거 같다! 풀긴 풀었는데.. 만족스럽지 못한 코드들..
삼항연산자로 바꾸려고 했던 것도 있었고, 일일히 for문으로 쓰던 리플릿과는 다르게 메서드를 쓰려고 노력했다 💪🏻</p>
</blockquote>
<br>

<h2 id="📌-getfind-함수를-작성하세요">📌 getFind 함수를 작성하세요.</h2>
<p>문자와 문자열이 주어졌을때, getFind 함수는 주어진 문자열에서 주어진 문자가 나타나는 첫번째 위치를 반환합니다.</p>
<p>Notes: 문자열의 첫번째 문자는 인덱스 값 0 을 가집니다. 만약 문자열에 해당 문자가 여러번 나타나면, 첫번째로 나타나는 위치를 반환해야 합니다. 만약 문자가 문자열에 존재하지 않는다면, -1 을 반환해야 합니다.</p>
<p><strong>중요!! indexOf 함수를 사용하지 마세요.</strong></p>
<pre><code>function getFind(filter, sentence) { 
  for(let i = 0; i &lt; sentence.length; i++) {
    if (filter === sentence[i]) {
      return i;
    }
  } return -1;
}</code></pre><blockquote>
<p>return -1의 시점이 헷갈렸던 문제였다! else를 선언해 -1을 줬더니 계속 다른 값이 나와 다시 생각을 했던 문제...😱</p>
</blockquote>
<br>

<h2 id="📌-find_longest_word-함수를-만들어-주세요">📌 find_longest_word 함수를 만들어 주세요.</h2>
<p>주어진 리스트안에 있는 단어중 가장 긴 단어를 찾을수 있도록 함수를 완성해주세요.</p>
<pre><code>function find_longest_word(arr) {
  const arryLength = arr.map(x =&gt; x.length);
  const maxEl = Math.max(...arryLength);
  const longIndex = arryLength.indexOf(maxEl);
  return arry[longIndex];
}</code></pre><blockquote>
<p>제일 처음엔 중첩된 for문으로 문제를 풀었었다! 그런데 갑자기 공부했던 Math.max함수가 떠올라 mdn검색후 다시 풀었던 문제! 확실히 중첩 for문보다 코드가 간결해졌다! 메서드의 중요성,,,,🌟</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[TIL 23 - [clone] Instagram - js ]]></title>
            <link>https://velog.io/@jjung-developer/TIL-23-clone-Instagram-js</link>
            <guid>https://velog.io/@jjung-developer/TIL-23-clone-Instagram-js</guid>
            <pubDate>Fri, 16 Jul 2021 01:10:28 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>인스타그램 클론코딩! js로 진행하였다. 필수구현 , 추가구현 , 리팩토링까지 완료하며 느꼇던 점, 어려웠던 부분을 정리하려 한다🔥</p>
</blockquote>
<br>

<h1 id="📖-login-페이지">📖 Login 페이지</h1>
<h2 id="👉🏻-id---포함--pw--5글자-이상-시-로그인-버튼-활성화">👉🏻 id &gt; &#39;@&#39; 포함 / pw &gt; 5글자 이상 시 로그인 버튼 활성화</h2>
<p><img src="https://images.velog.io/images/jjung-developer/post/3a4c74fb-b256-4d24-8e15-5c7cb5b22eca/login.gif" alt=""></p>
<pre><code>&lt;div id=&quot;login&quot;&gt;
  &lt;div class=&quot;loginWrap&quot;&gt;
     &lt;h1 class=&quot;sitelogo&quot;&gt;Westargram&lt;/h1&gt;
     &lt;form action=&quot;main.html&quot;&gt;
       &lt;input type=&quot;text&quot; class=&quot;input idInput&quot; name=&quot;id&quot; placeholder=&quot;전화번호, 사용자 이름 또는 이메일&quot; required&gt;
       &lt;input type=&quot;password&quot; class=&quot;input pwdInput&quot; name=&quot;password&quot; placeholder=&quot;비밀번호&quot; required&gt;
       &lt;button&gt;로그인&lt;/button&gt;
     &lt;/form&gt;
     &lt;a href=&quot;#&quot; class=&quot;forgetIink&quot;&gt;비밀번호를 잊으셨나요?&lt;/a&gt;
  &lt;/div&gt;
&lt;/div&gt;</code></pre><pre><code>const form = document.querySelector(&quot;#login form&quot;);
const id = document.querySelector(&quot;#login form .idInput&quot;);
const pwd = document.querySelector(&quot;#login form .pwdInput&quot;);
const button = document.querySelector(&quot;#login button&quot;);

form.addEventListener(&quot;keyup&quot;, function activeButton(){
    ((id.value.length &gt;= 1 ) &amp;&amp; (pwd.value.length &gt;= 5) &amp;&amp; (id.value.indexOf(&quot;@&quot;) &gt; -1)) ? button.style.opacity = &quot;1&quot; : button.style.opacity = &quot;0.5&quot;;
});</code></pre><ul>
<li>필수 구현 사항 : input값이 들어갈때 버튼 활성화</li>
<li>추가 구현 사항 : id &gt; &#39;@&#39; 포함 / pw &gt; 5글자 이상 시 로그인 버튼 활성화</li>
</ul>
<blockquote>
<p>input과 button을 form으로 묶어 form에 addEventListener을 주었다. 또한 input의 속성에 required를 추가하여, input에 값이 있을때만 submit이 되도록 하였다.
event는 keyup을 주어 키보드를 누르고 떼는 순간 이벤트가 발생하도록 했다.
그리고 이번에 처음 써봤던 <em><strong>삼항 연산자!</strong></em> 처음에는 너무 낯설었는데 모든 if문을 삼항연산자로 구현하니 이제는 삼항 연산자가 더 편해졌다!</p>
</blockquote>
<br>
<hr>
<br>

<h1 id="📖-main-페이지">📖 main 페이지</h1>
<h2 id="👉🏻-댓글-내용-입력-후-enter-press-혹은-게시-버튼-클릭-시-댓글-추가-기능--input입력-시-게시-버튼-활성화">👉🏻 댓글 내용 입력 후 Enter press, 혹은 게시 버튼 클릭 시 댓글 추가 기능 / input입력 시 게시 버튼 활성화</h2>
<p><img src="https://images.velog.io/images/jjung-developer/post/2a29344d-76ff-48f7-aeef-ee1406ffbfca/Jul-16-2021%2013-43-53.gif" alt=""></p>
<pre><code>&lt;div class=&quot;feeds&quot;&gt;
    &lt;article&gt;
        &lt;div class=&quot;feed&quot;&gt;
            &lt;div class=&quot;writer&quot;&gt;
                &lt;a href=&quot;#&quot; class=&quot;writerInfo&quot;&gt;
                    &lt;div class=&quot;writerImg&quot;&gt;
                        &lt;img alt=&quot;프로필 이미지&quot; src=&quot;images/profile_img.jpeg&quot;&gt;
                    &lt;/div&gt;
                    &lt;div class=&quot;writerId&quot;&gt;canon_mj&lt;/div&gt;
                &lt;/a&gt;
                &lt;a href=&quot;#&quot; class=&quot;writerOtherMenu&quot;&gt;
                    &lt;img alt=&quot;게시글에 대한 다른메뉴 보기&quot; src=&quot;images/feed_writer_other_menu.png&quot;&gt;
                &lt;/a&gt;
            &lt;/div&gt;
            &lt;div class=&quot;imgs&quot;&gt;
                &lt;img alt=&quot;피드 이미지&quot; src=&quot;images/feed_img.png&quot;&gt;
            &lt;/div&gt;
            &lt;div class=&quot;feedInfoWrap&quot;&gt;
                &lt;div class=&quot;feedLink&quot;&gt;
                    &lt;div class=&quot;feedLinkLeft&quot;&gt;
                        &lt;a href=&quot;#&quot;&gt;&lt;img alt=&quot;좋아요 아이콘&quot; src=&quot;images/feed_link_left1.png&quot;&gt;&lt;/a&gt;
                        &lt;a href=&quot;#&quot;&gt;&lt;img alt=&quot;댓글 아이콘&quot; src=&quot;images/feed_link_left2.png&quot;&gt;&lt;/a&gt;
                        &lt;a href=&quot;#&quot;&gt;&lt;img alt=&quot;쪽지 아이콘&quot; src=&quot;images/feed_link_left3.png&quot;&gt;&lt;/a&gt;
                    &lt;/div&gt;
                    &lt;div class=&quot;feedLinkRight&quot;&gt;
                        &lt;a href=&quot;#&quot;&gt;&lt;img alt=&quot;책갈피 아이콘&quot; src=&quot;images/feed_link_right1.png&quot;&gt;&lt;/a&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
                &lt;div class=&quot;likeCount&quot;&gt;
                    &lt;div class=&quot;likeImg&quot;&gt;
                        &lt;img alt=&quot;좋아요 누른 사람의 프로필사진&quot; src=&quot;images/profile_img.jpeg&quot;&gt;
                    &lt;/div&gt;
                    &lt;div class=&quot;likeInfo&quot;&gt;
                        &lt;a href=&quot;#&quot; class=&quot;likeUser&quot;&gt;anieworld&lt;/a&gt;님 &lt;a href=&quot;#&quot; class=&quot;likeUserOther&quot;&gt;외 10명&lt;/a&gt;이 좋아합니다
                    &lt;/div&gt;
                &lt;/div&gt;
                &lt;div class=&quot;feedDecs&quot;&gt;
                    &lt;a href=&quot;#&quot; class=&quot;feedWriter&quot;&gt;canon_mj&lt;/a&gt;
                    &lt;div class=&quot;feedTxt&quot;&gt;위워크에서 진행한 베이킹 클래스... &lt;a href=&quot;#&quot;&gt;더 보기&lt;/a&gt;&lt;/div&gt;
                &lt;/div&gt;
                &lt;div class=&quot;feedComment&quot;&gt;
                    &lt;ul&gt;&lt;/ul&gt;
                    &lt;div class=&quot;feedTime&quot;&gt;42분전&lt;/div&gt;
                &lt;/div&gt;
            &lt;/div&gt;
            &lt;div class=&quot;feedCommentInput&quot;&gt;
                &lt;form&gt;
                    &lt;input type=&quot;text&quot; class=&quot;input&quot; name=&quot;comment&quot; placeholder=&quot;댓글달기...&quot;&gt;
                    &lt;button class=&quot;commentBtn&quot;&gt;게시&lt;/button&gt;
                &lt;/form&gt;
            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/article&gt;
&lt;/div&gt;</code></pre><pre><code>const commentSubmit = () =&gt; {
    const commentList = document.querySelector(&quot;.feedComment ul&quot;);
    const commentText = commentInput.value;
    commentInput.value = &quot;&quot;;
    const li = document.createElement(&quot;li&quot;);
    commentList.appendChild(li);
    const a = document.createElement(&quot;a&quot;);
    li.appendChild(a);
    a.innerText = &quot;user_id&quot;;
    const p = document.createElement(&quot;p&quot;);
    li.appendChild(p);
    p.innerText = commentText;
    const buttonHeart = document.createElement(&quot;button&quot;);
    buttonHeart.classList.add(&quot;heartBtn&quot;);
    buttonHeart.innerText = &quot;좋아요하트&quot;;
    li.appendChild(buttonHeart);
    buttonHeart.addEventListener(&quot;click&quot;, likeHeart);
    const deleteButton = document.createElement(&quot;button&quot;);
    deleteButton.classList.add(&quot;deleteBtn&quot;);
    deleteButton.innerText = &quot;삭제버튼&quot;;
    li.appendChild(deleteButton);
    deleteButton.addEventListener(&quot;click&quot;, deleteComment);
}
commentForm.addEventListener(&quot;submit&quot;, handleCommentSubmit);
commentForm.addEventListener(&quot;keyup&quot;, function activeCommentButton () {commentInput.value !== &quot;&quot; ? commentButton.style.opacity = &quot;1&quot; : commentButton.style.opacity = &quot;0.3&quot;});</code></pre><blockquote>
<p>✅ <strong>핵심 포인트</strong></p>
</blockquote>
<ul>
<li>createElement, appendChild, innerText 구분 및 순서 확인 잘 하기!</li>
</ul>
<blockquote>
<p>📌 <strong>댓글 등록</strong></p>
</blockquote>
<ol>
<li>.feedComment ul에 li값을 추가해주기 위해, .feedComment ul을 commentList로 선언한다.</li>
<li>input값을 commentText값에 넣어주고 input값을 초기화 시킨다.</li>
<li>createElement을 통해 li을 만들어준다 (a,p,button 도 마찬가지로)</li>
<li>commentText값을 p안에 innerText을 통해 넣어준다 (a,p,button 도 마찬가지로 넣고 싶은 값을 넣어준다)</li>
<li>만든 태그들을 appendChild 을 통해 html에 뿌려준다 (li는 ul안에, a / p / button은 li안에 넣어준다)</li>
</ol>
<blockquote>
<p>📌 <strong>input입력 시 게시글 버튼 활성화</strong>
keyup을 통해 키를 누르고 뗄 때 이벤트가 발생되도록 구현하였다.
input값이 비어있지 않을때는 opacity값을 1로, 반대일 경우에는 0.3으로 값을 주었다.</p>
</blockquote>
<br>

<h2 id="👉🏻-댓글-좋아요--삭제-기능">👉🏻 댓글 좋아요 / 삭제 기능</h2>
<p><img src="https://images.velog.io/images/jjung-developer/post/58739b09-ddb1-480f-bec6-5fa89a75019b/Jul-16-2021%2014-00-02.gif" alt=""></p>
<p><strong>➡️  추가 코드</strong></p>
<pre><code>const likeHeart = (e) =&gt; {
    e.preventDefault();
    const li = e.target.parentElement;
    e.target.classList.contains(&quot;active&quot;) ? e.target.classList.remove(&quot;active&quot;) : e.target.classList.add(&quot;active&quot;);
}

const deleteComment = (e) =&gt; {
    e.preventDefault();
    const li = e.target.parentElement;
    li.remove();
}</code></pre><pre><code>main .feeds .feed .feedComment ul li button {
    border: 0;
    text-indent: -999em;
    display: block;
    width: 20px;
    height: 20px;
    position: absolute;
    top: 50%;
    margin-top: -10px;
    background-color: transparent;
    background-size: 100% 100%;
}

#main .feeds .feed .feedComment ul li button.heartBtn {
    right: 30px;
    background-image: url(&quot;../images/feed_link_left1.png&quot;);
}

#main .feeds .feed .feedComment ul li button.heartBtn.active {
    background-image: url(&quot;../images/feed_link_left1_active.png&quot;);
}

#main .feeds .feed .feedComment ul li button.deleteBtn {
    right: 0;
    background-image: url(&quot;../images/close.png&quot;);
}</code></pre><blockquote>
<p>위에서 댓글 등록할 때 만들어 놨던 button(heartBtn,deleteBtn)을 css로 꾸며주고, 이벤트를 걸어주었다! 🔥 </p>
</blockquote>
<ul>
<li><strong>e.preventDefault();</strong> : 이벤트 기본 속성으로 버튼을 누르게 되면 새로고침이 된다. 이를 막기위해 e(event)에 preventDefault함수를 걸어주는 것이다. preventDefault 함수를 주게 되면 새로고침 되는 현상을 강제로 막게 된다.<ul>
<li><strong>e.target.parentElement</strong> : e에 클릭한 button를 찾아 준 뒤(e.target), parentElement를 통해 button의 부모를 찾아준다.</li>
<li><strong>e.target.classList.contains(&quot;active&quot;)</strong> : e에 클릭한 button의 class에 acitve가 있는지 없는지 확인한다. (acitve가 있으면 background-image값이 바뀐다)</li>
<li><strong>li.remove();</strong> : e.target을 통해 알아낸 li를 지운다.</li>
</ul>
</li>
</ul>
<br>

<h2 id="👉🏻-nav-프로필-사진-클릭-시-메뉴-박스-생성-메뉴-박스-바깥-영역-클릭시-닫히도록">👉🏻 nav 프로필 사진 클릭 시 메뉴 박스 생성 (메뉴 박스 바깥 영역 클릭시 닫히도록)</h2>
<p><img src="https://images.velog.io/images/jjung-developer/post/f82472b4-7bc1-4b54-8edd-4be93e27c618/Jul-16-2021%2014-51-23.gif" alt=""></p>
<pre><code>const openMypage = (e) =&gt; {
    mypagePop.style.display = &quot;block&quot;;
}

const closePop = (e) =&gt; {
    (!mypageBox.contains(e.target)) &amp;&amp; (!searchZone.contains(e.target)) ? (mypagePop.style.display = &quot;none&quot;) &amp;&amp; (searchPop.style.display = &quot;none&quot;) : false;
}</code></pre><blockquote>
<p>시간을 은근 많이 잡아 먹었던 부분 😱 
contains(e.target) 을 찾는데에 시간이 오래 걸렸었다..
만들어 놓고 보니 검색기능 팝업과 겹쳐 함수를 묶어 주었다!
e.target은 이벤트가 실행 된 영역이라고 앞에서 설명했다.
<strong>e.taeget이 포함되지 않은 영역을 선택 했을 때(contains)</strong>, style.display = &quot;none&quot;을 실행시켜준다.</p>
</blockquote>
<br>

<h2 id="👉🏻-반응형-구현">👉🏻 반응형 구현</h2>
<p><img src="https://images.velog.io/images/jjung-developer/post/a1a7a9c8-0dc0-4fa7-bb55-2f7cbba91492/Jul-16-2021%2015-41-11.gif" alt=""></p>
<pre><code>@media (max-width: 1024px) {
    .sideMenu {display:none;}
    #main .feeds {width:100%;}
}</code></pre><blockquote>
<p>브라우져가 1024px에 도달하면 오른쪽 메뉴가 없어지도록 반응형을 구현하였다.</p>
</blockquote>
<br>

<h2 id="👉🏻-검색기능-구현">👉🏻 검색기능 구현</h2>
<p><img src="https://images.velog.io/images/jjung-developer/post/0f0510d6-ccf2-4baf-89db-91381798b9a6/Jul-16-2021%2015-44-38.gif" alt=""></p>
<pre><code>const idOfWestagram = [
    {id: &quot;W0nhong__&quot;, imgUrl: &quot;images/profile_img.jpeg&quot;, info: &quot;W0nhong소개글&quot;, profileUrl: &quot;https://www.naver.com/&quot;},
    {id: &quot;hj._.__s2&quot;, imgUrl: &quot;images/profile_img.jpeg&quot;, info: &quot;hj._.__s2소개글&quot;, profileUrl: &quot;https://www.daum.net/&quot;},
    {id: &quot;kvwowv&quot;, imgUrl: &quot;images/profile_img.jpeg&quot;, info: &quot;kvwowv소개글&quot;, profileUrl: &quot;https://wecode.co.kr/?gclid=CjwKCAjwlrqHBhByEiwAnLmYUD8aCer8FbdtZ8BzOFlwHX8HI-HwDbdHb4PW6-YW1NDDsDwMYGlsZRoCurgQAvD_BwE&quot;},
    {id: &quot;kvvow22&quot;, imgUrl: &quot;images/profile_img.jpeg&quot;, info: &quot;kvvow22소개글&quot;, profileUrl: &quot;#&quot;},
    {id: &quot;abcd_efg&quot;, imgUrl: &quot;images/profile_img.jpeg&quot;, info: &quot;abcd_efg소개글&quot;, profileUrl: &quot;#&quot;},
    {id: &quot;abcd_efaaaa__&quot;, imgUrl: &quot;images/profile_img.jpeg&quot;, info: &quot;abcd_efaaaa__소개글&quot;, profileUrl: &quot;#&quot;},
    {id: &quot;ww0_jfd&quot;, imgUrl: &quot;images/profile_img.jpeg&quot;, info: &quot;ww0_jfd소개글&quot;, profileUrl: &quot;#&quot;}
];

const searchDataPaint = () =&gt; {
    idOfWestagram.forEach((el)=&gt;{
        const li = document.createElement(&quot;li&quot;);
        const a = document.createElement(&quot;a&quot;);
        a.href = el.profileUrl;
        a.target= &quot;_blank&quot;;
        const searchImg = document.createElement(&quot;div&quot;);
        searchImg.classList.add(&quot;searchImg&quot;);
        const img = document.createElement(&quot;img&quot;);
        img.src = el.imgUrl;
        const searchInfo = document.createElement(&quot;div&quot;);
        searchInfo.classList.add(&quot;searchInfo&quot;);
        const userId = document.createElement(&quot;div&quot;);
        userId.classList.add(&quot;userId&quot;);
        userId.innerText = el.id;
        const userInfo = document.createElement(&quot;div&quot;);
        userInfo.classList.add(&quot;userInfo&quot;);
        userInfo.innerText = el.info;
        searchUl.appendChild(li);
        li.appendChild(a);
        a.appendChild(searchImg);
        searchImg.appendChild(img);
        a.appendChild(searchInfo);
        searchInfo.appendChild(userId);
        searchInfo.appendChild(userInfo);
    });
}

const searchFilter = (e) =&gt; {
    const searchText = searchInput.value.toUpperCase(); 
    const li = searchUl.getElementsByTagName(&quot;li&quot;);
    Array.from(li).forEach((el) =&gt; {
        const userName = el.getElementsByTagName(&quot;div&quot;)[1].getElementsByTagName(&quot;div&quot;)[0];
        const txtValue = userName.innerText;
        txtValue.toUpperCase().indexOf(searchText) &gt; -1 ? el.style.display = &quot;block&quot; : el.style.display = &quot;none&quot;;
    });
}

searchForm.addEventListener(&quot;keyup&quot;, searchFilter);
window.addEventListener(&quot;load&quot;, searchDataPaint);</code></pre><blockquote>
</blockquote>
<ul>
<li><ol>
<li>idOfWestagram 배열에 가상 데이터를 만든 후 window가 로드되면 searchDataPaint를 실행시켜 li를 생성한다.</li>
</ol>
</li>
<li><ol start="2">
<li>input데이터를 모두 대문자로 바꿔준뒤 ul안에 있는 모든 li를 - getElementsByTagName를 통해 배열로 바꾼다.</li>
</ol>
</li>
<li><ol start="3">
<li>getElementsByTagName를 통해 만든 배열은 유사배열이므로 forEach,map같은 메소드를 실행하면 Type Error가 뜬다!</li>
</ol>
</li>
<li><ol start="4">
<li>Array.from(li)을 통해 li를 찐! 배열로 만들어준다.</li>
</ol>
</li>
<li><ol start="5">
<li>li안에 있는 2번째 div안에 있는 1번째 div(userName)를 변수로 선언한다.</li>
</ol>
</li>
<li><ol start="6">
<li>userNamed의 텍스트를 가져와 대문자로 바꿔준 뒤, 찾을 텍스트(검색할 텍스트)를 indexOf로 조건문을 만든다</li>
</ol>
</li>
<li><ol start="7">
<li>찾을 텍스트가 있으면 (num &gt; -1) display:block이고, 찾을 텍스트가 없으면 (num = -1) display:none;이 된다!</li>
</ol>
</li>
</ul>
<br>
<hr>
<br>

<h1 id="📌-tmi">📌 TMI</h1>
<h2 id="아쉬운-부분-🙇🏻♀️">아쉬운 부분 🙇🏻‍♀️</h2>
<blockquote>
<p>원래 검색기능을 
첫 번째 글자 입력 시, 첫 번째 글자가 일치하는 아이디 출력 -&gt; 두 번째 글자 입력 시, 두 번째 글자까지 일치하는 아이디 출력
이렇게 구현을 하고 싶었다....... 입력하는 값이 id에 포함되는 값을 표출하는 것이 생각보다 오래 걸리지 않아서 오! 할 수 있겠다! 했는데 ㅎㅎ...
생각 할 것이 너무나도 많았다...
도현님께 얻은 키워드는 빈 배열을 선언 후 조건문을 걸어 다시 그 배열을 뿌려주는 것이다! 그치만... 그렇게 구현하지 못했다 😱
마지막 날 컨디션도 너무 좋지 못했고 온전히 코딩에만 집중하지 못했던 탓도 있는것 같다ㅠㅠ </p>
</blockquote>
<br>

<h2 id="느낀점-🔥">느낀점 🔥</h2>
<blockquote>
<p>리팩토링을 하기 전 내 코드를 다시한번 더욱 더!!! 꼼꼼히!!!! 제발 확인하자,,
왜 늘 커밋을 하고 난 다음에 수정할 코드가 보이는 것일까 😂
그리고 이번 프로젝트를 진행하면서 너무 신기했던건 2시간 동안 붙잡고 있었던 코드를 도현님께 여쭤봤는데 도현님께 내 코드를 설명하면서 내가 그 코드를 완전히 이해해버려 답까지 혼자 찾아냈다....ㅎㅎ 왜 혼자 할 떄는 그게 안될까 🥺 ... </p>
</blockquote>
]]></description>
        </item>
    </channel>
</rss>