<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>sofarsogood</title>
        <link>https://velog.io/</link>
        <description>느려서 바쁘다</description>
        <lastBuildDate>Mon, 11 Oct 2021 06:14:19 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>sofarsogood</title>
            <url>https://images.velog.io/images/rand_guy/profile/c07db9a7-66d8-4fdd-841c-e0f97b5f3ca1/IMG_7907.JPG</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. sofarsogood. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/rand_guy" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[Project#2] 코드로 살펴보는 두번째 React 프로젝트]]></title>
            <link>https://velog.io/@rand_guy/Project2-%EC%BD%94%EB%93%9C%EB%A1%9C-%EC%82%B4%ED%8E%B4%EB%B3%B4%EB%8A%94-%EB%91%90%EB%B2%88%EC%A7%B8-React-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8</link>
            <guid>https://velog.io/@rand_guy/Project2-%EC%BD%94%EB%93%9C%EB%A1%9C-%EC%82%B4%ED%8E%B4%EB%B3%B4%EB%8A%94-%EB%91%90%EB%B2%88%EC%A7%B8-React-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8</guid>
            <pubDate>Mon, 11 Oct 2021 06:14:19 GMT</pubDate>
            <description><![CDATA[<p><code>전체 코드의 일부분만 가져왔습니다.</code></p>
<hr>
<h3 id="문제--유저가-올리는-파일의-이미지를-미리볼-수-있게-해주세요">문제 : 유저가 올리는 파일의 이미지를 미리볼 수 있게 해주세요.</h3>
<p><a href="https://www.youtube.com/watch?v=-L_NpY3ExXc"><img src="https://images.velog.io/images/rand_guy/post/a216e735-59bb-4618-b075-177b9987247f/image.png" alt=""></a></p>
<p>file 타입 input 태그는 files라는 속성을 갖는다. Files 속성은 FilesList 타입의 객체를 반환한다. 해당 객체에는 선택된 파일들이 모두 담겨있다. 이를 배열의 형태로 변환, URL.createObejctURL() 메서드로 file 객체의 URL을 DOM스트링으로 반환한다. 해당 URL을 img태그의 src속성에 부여한다. 그러면 배열변수 imageArray에 들어있는 URL의 개수만큼 미리보기 이미지가 렌더된다. 또한 깊은 복사를 통해 객체를 복사하여 새롭게 파일을 등록할때, 새로운 이미지들만 들어가는 것이 아니고 기존의 이미지에 추가되는 기능을 제공했다.</p>
<p><img src="https://images.velog.io/images/rand_guy/post/ea6cc4cd-1580-4f76-8e6f-1a533ba2cc61/image-20211002180739327.png" alt=""></p>
<hr>
<h3 id="문제--등록할-수-있는-이미지를-7개로-제한해주세요">문제 : 등록할 수 있는 이미지를 7개로 제한해주세요.</h3>
<p><a href="https://www.youtube.com/watch?v=-L_NpY3ExXc"><img src="https://images.velog.io/images/rand_guy/post/1aa15abb-9fe2-42b0-af1b-c0843c80c9ba/image.png" alt=""></a></p>
<p><strong>첫번째 실패</strong> : 처음에는 선택된 이미지의 길이가 7개가 넘으면 해당 이미지 배열을 7개로 제한하고 메세지를 표시하게 했다. 그런데 생명주기 문제로 인해서, 7개가 넘으면 작동하길 바랬던 기능이 7개가 넘고나서 등록하는 파일들에게 작동했다. </p>
<p><strong>두번째 해결</strong> : 관련 자료를 찾아보던 중, 해달 파일이 변하는 순간에 기능이 작동해야 했다. 그렇기에 useEffect를 사용하여 의존성배열에 선택된 이미지들이 담기는 배열을 넣었다. 이로써 값이 변경될 때 마다, 위 조건문을 통과할 때에 해당 기능이 구현되었다. </p>
<p><img src="https://images.velog.io/images/rand_guy/post/6df2332f-6d99-42dc-965b-348056a1180f/image-20211002180759918.png" alt=""></p>
<hr>
<h3 id="문제--미리보기-이미지에서-삭제버튼을-누르면-이미지가-삭제되게-해주세요">문제 : 미리보기 이미지에서 삭제버튼을 누르면 이미지가 삭제되게 해주세요</h3>
<p><img src="https://images.velog.io/images/rand_guy/post/c9f26f6a-a019-434d-b354-31f67e39cde8/image-20211002180815939.png" alt=""></p>
<p><strong>첫번째 실패</strong> : 처음에는 map 메서드를 통해 각 이미지에 할당되는 index의 역활을 하는 id 값을 지정했다. 해당 id 값으로 index를 지정하여 splice 메서드를 사용하여 배열에서 삭제 시키는 기능을 구현하려고 했다. 그러나 의도와 다르게, delete버튼이 실행되면 해당 index의 이미지가 없어지지만 앞에 있던 이미지가 그자리를 대체하는 기능이 생겼다.</p>
<p><strong>두번째 실패</strong> : 관련 자료를 찾아보던 중, 얕은 복사와 깊은 복사에 대해 이해하게 되었다. 작성했던 기능은 얕은 복사로 인해 참조 해오는 값의 변화로 인해 값이 변경되지 않았다. 그래서 깊은 복사를 적용했다. 그렇지만 기능은 잘 구현되지 않았다.</p>
<p><strong>세번째 성공</strong> : 하지만 알고보니 함수형 컴포넌트로 코드를 작성했기에, useState hook으로 기존의 스테이트를 변경해서 가져오기 때문에, 복사로 인한 문제는 아니었다. 그러다가 확인해보니 delete함수의 argument로 주어지는 값이 배열의 index 값이 올바르게 설정되어있지 않았다. 이 문제를 해결하니 요구되던 기능이 실행되었다.</p>
<hr>
<h2 id="느낀점">느낀점</h2>
<p>2차 프로젝트를 하면서 처음으로 함수형 컴포넌트를 사용했다. 이를 통해 hooks의 개념과 Lifecycle을 적극 사용할 수 있었다. 또한 1차때와 다르게 하나의 기능에 집중하면서 코드를 작성하게 되니, 관련된 정보를 많이 보게 되고 자바스크립트에 대해서 더 이해할 수 있었다. <strong>새로운 기능을 만들 때, 물어보는 것 보다, 스스로 구글링하고 이해하면서 나가는 나의 성격 때문인지, 멘토님들 보다 구글링을 하면서 문제를 해결했다.</strong> 다른 사람들에 비해 생산성은 낮았던 것 같지만, 내가 제대로 이해했기에 다른 사람에게도 명확하게 설명할 수 있었다. </p>
<p>3차 프로젝트에서는 타입스크립트와 자바스크립트에 대한 더 깊은 이해, 그리고 useEffect와 같은 기능으로 인한 지나치게 많은 렌더 등의 이슈를 다른 hooks와 브라우저, 네트워크 공부를 통해 한 단계 성장하길 기대하고 있다. 재충전의 시간을 가지고 다시 또 시작할 프로젝트가 기대된다. </p>
<p>** 결과물 영상 : <a href="https://www.youtube.com/watch?v=-L_NpY3ExXc">https://www.youtube.com/watch?v=-L_NpY3ExXc</a> **
** 결과물 링크 : <a href="https://github.com/joshhhso/23-2nd-GWAPANG-frontend">https://github.com/joshhhso/23-2nd-GWAPANG-frontend</a> **</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Project#2] 타임라인으로 살펴보는 두번째 React 프로젝트]]></title>
            <link>https://velog.io/@rand_guy/Project2-%ED%83%80%EC%9E%84%EB%9D%BC%EC%9D%B8%EC%9C%BC%EB%A1%9C-%EC%82%B4%ED%8E%B4%EB%B3%B4%EB%8A%94-%EB%91%90%EB%B2%88%EC%A7%B8-React-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8</link>
            <guid>https://velog.io/@rand_guy/Project2-%ED%83%80%EC%9E%84%EB%9D%BC%EC%9D%B8%EC%9C%BC%EB%A1%9C-%EC%82%B4%ED%8E%B4%EB%B3%B4%EB%8A%94-%EB%91%90%EB%B2%88%EC%A7%B8-React-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8</guid>
            <pubDate>Mon, 11 Oct 2021 05:47:51 GMT</pubDate>
            <description><![CDATA[<hr>
<p><img src="https://images.velog.io/images/rand_guy/post/164ee8e3-0dac-4ba9-81b6-461b2f22c6a1/image.png" alt=""></p>
<ul>
<li>일정 : 8월17일 ~ 8월27일 (주말 제외 8일)</li>
<li>스택 : React, Javscript, StyledComponent, CSS, Git, Trello, Slack</li>
<li>인원 : 프론트엔드 3명 / 백엔드 2명</li>
</ul>
<hr>
<h2 id="1주차--함수형-컴포넌트-그리고-파일-s3서버에-업로드하기">1주차 : 함수형 컴포넌트, 그리고 파일 S3서버에 업로드하기...</h2>
<p>감사(?)하게도 팀원의 추천으로 다시 한번 PM을 맡게 되었다. 내가 제출했던 웹 사이트가 되니 책임감이 들고 팀원들과 함께 1차보다 잘 만들어 보고 싶다는 마음이 들었다. 하지만 이러한 생각은 첫 세션에서 깨지게 되는데...</p>
<p>1차 프로젝트를 하면서 클래스형 컴포넌트, 그리고 state와 친해질 수 있었다. 또한 REST api와 fetch함수로 데이터를 주고받았다. 2주동안 사귄 친구를 뒤로하고 첫 세션에서 다른 친구들을 소개받았다. 함수형 컴포넌트, useState, useEffect, 그리고 axios 라이브러리를 알게되었다. 또한 서버도 백엔드의 로컬서버가 아닌 클라우드 서버, AWS를 사용해보기로 햇으며, styled.componenet, 카카오 소셜 로그인, git rebase, custom Hook에 대해서도 배우고 적용하기로 했다.  </p>
<h3 id="다시-쇼핑몰-이번엔-셀러를-위한-웹사이트">다시 쇼핑몰? 이번엔 셀러를 위한 웹사이트!</h3>
<hr>
<p>화요일, 첫 스프린트 미팅을 가질 때, 우리는 1차 프로젝트처럼 유저의 입장에서 웹 페이지를 클론하고 싶었다. 유려한 CSS, 그리고 전에는 해보지 않은 기능을 제작해보고 싶었다. 하지만 멘토님들의 의견 중, &#39;웹 개발자는 구매자 뿐만 아니라 판매자를 위한 웹 사이트를 제작해야 한다&#39;라는 말이 크게 와닿았다. 팀원. 모두 이 말에 크게 공감하여 &#39;판매자 입장의 웹 페이지를 제작해보는 것으로 방향을 바꾸게 되었다.</p>
<p>새로운 기술을 배워야 했기에, 1주차는 정신없이 지나갔다. 하루에 세션 두세개를 듣고 나면 막상 코드를 작성하는 시간은 얼마 되지 않았다. 또한 기획에 있어서 서로 원하는 바가 다르단 걸 알 수 있었다. 하지만 토론과 투표를 통해 &#39;과일을 판매하는 이커머스 사이트&#39;로 결정되었다. 초기세팅과 프로젝트 진행(scrum)에 있어서는 다들 한 차례 경험을 했기 때문에, 트렐로를 통해 문제없이 소통할 수 있었다.</p>
<p>그렇게 수요일 오후부터 코드를 작성하기 시작했다. 내가 맡은 업로드 페이지에는 다양한 데이터를 작성하고 받아오고 수정할 수 있어야 했다. </p>
<h3 id="crudcreate-receive-update-delete">CRUD(Create, Receive, Update, Delete)</h3>
<hr>
<p>당시에는 몰랐지만 이러한 기능을 가진 페이지를 CRUD 페이지라고 부른다. 생성하고 받아오고 수정하고 삭제할 수 있는 페이지이다. 업로드 페이지는 셀러가 판매하는 상품을 등록할 수 있는 페이지다. 그렇기에 서버와의 통신이 필수적이었다. </p>
<p>페이지 레이아웃을 제작하면서 수요일을 보냈다. 그리고 목요일부터 파일 업로드를 시작했다. Html을 공부할 때, 서버와 통신하기 위해 input과 form태그를 이용해 데이터를 송수신할 수 있다는 것을 알고 있었다. 하지만 이러한 쉬운 생각은 제일 첫 업로드에서 부터 난관에 마주치게 되면서 부서지게 되엇다.</p>
<h3 id="input-typefile"><code>&lt;input type=&quot;file&quot;&gt;</code></h3>
<hr>
<p>마플샵에서 상품 업로드 페이지를 볼 수 없었기에, 나는 번개장터를 참고하기로 했다. 번개장터의 첫 업로드 기능은 이미지였다. 이미지를 클릭하면 업로드 창이 뜬다. 그리고 이미지를 업로드하면 우측에 미리보기가 뜨고, 미리보기의 삭제버튼을 누르면 업로드한 이미지가 삭제되었다. </p>
<p>흥미롭고 해보고 싶다는 생각과 이걸 빨리 끝내서 프로젝트에 폐를 끼치지 않을 수 있을까? 라는 생각이 들었다. <strong>하지만 고민이 무슨 소용인가? 당장 구글링을 시작했다.</strong></p>
<h3 id="filelist와-formdata-그리고-useeffect">filelist와 formdata, 그리고 useEffect</h3>
<hr>
<p>코드에 대해서는 다음 편에서 소개할테니, 과정만 간단히 소개하겠다. 구글링을 통해 스택오버플로우를 뒤져보면서 file을 서버와 통신하기 위한 방법들을 찾을 수 있었다. 정확히 나에게 필요한 코드는 없었지만 <strong>어떻게 파일을 저장하고, 전달하는 개념을 이해할 수 있었다.</strong> 이를 통해 <code>input type file</code> 의 속성 중 하나인 filelist에 도달하여 저장된 파일에 접근할 수 있었다. 저장된 파일들은 유사배열의 형태로 저장되어있었다. 그래서 Array.from 메서드를 통해 배열로 변환하여 파일을 부모 컴포넌트로 전달할 수 있었다. 그리고 이를 formdata라는 객체에 담아서 서버로 전달하게 되었다. 이외에도 많은 과정이 있었지만 이는 다음 편에서~</p>
<h3 id="usestate-useeffect-스터디-진행하다">useState, useEffect 스터디 진행하다</h3>
<hr>
<p>이렇게 파일을 찾아 서버로 전달하는 과정을 통해 useState, useEffect에 대한 이유를 이해할 수 있었다. 하지만 완벽하게 이햏자 못한체 사용하는 느낌을 지울 수 없었다. 이때, 1차에서 느낀 점 중 하나인, <strong>&#39;&#39;다른 사람의 코드를 이해하려면 같은 것을 공부해야 한다&#39;&#39;</strong> 라는 점이 생각났다. 그래서 프론트엔드 팀원들을 모아서 함께 useState와 useEffect를 공부하는 스터디를 진행하기로 했다.</p>
<p>스터디를 진행하게 되니 자연스럽게 서로의 코드도 공유할 수 있었다. 수시로 다른 사람의 코드를 보고 이해하고 하는 과정을 겪으니 내 코드에도 발전이 생겼다. 아무 이유없이 사용되었던 useState를 반드시 필요할 때만 사용할 수 있엇고, useEffect로 인한 무한 렌더링을 겪지 않아도 되었으며, 원하는 생명주기에 상태를 변화시킬 수 있었다.</p>
<h3 id="2주차--들뜬-마음을-붙잡으며-코딩하다">2주차 : 들뜬 마음을 붙잡으며 코딩하다</h3>
<hr>
<p>2주차에는 위코드의 모든 사람들의 마음이 뜬 것처럼 행동했다. 3차 프로젝트로 협업을 가게될 회사들이 발표되는 주였다. 그래서인지 전체적인 분위기가 프로젝트보다는 기업협업을 준비하는 분위기였다. 그럼에도 <strong>나의 프로젝트에 책임감을 가지고 임해야 된다는 마인드때문에</strong> 끝까지 마무리하려고 노력했다.</p>
<p>특히 프로젝트를 하면서, 나의 부족함을 더욱 많이 느끼고, 내가 어떤 것을 더 좋아하는 지 파악할 수 있었다. 단순히 문제를 해결하기 위한 코드보다, 문제를 해결하기 위한 모든 방법을 적용하고 싶었다. 2차 프로젝트에서 어려움이 있었으나 프로젝트를 잘 완성할 수 있었다.</p>
<p><strong>프로젝트 링크 : <a href="https://github.com/joshhhso/23-2nd-GWAPANG-frontend">https://github.com/joshhhso/23-2nd-GWAPANG-frontend</a></strong></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[✖️코드카타 #7 - x만큼 간격이 있는 n개의 숫자]]></title>
            <link>https://velog.io/@rand_guy/%EC%BD%94%EB%93%9C%EC%B9%B4%ED%83%80-7-x%EB%A7%8C%ED%81%BC-%EA%B0%84%EA%B2%A9%EC%9D%B4-%EC%9E%88%EB%8A%94-n%EA%B0%9C%EC%9D%98-%EC%88%AB%EC%9E%90</link>
            <guid>https://velog.io/@rand_guy/%EC%BD%94%EB%93%9C%EC%B9%B4%ED%83%80-7-x%EB%A7%8C%ED%81%BC-%EA%B0%84%EA%B2%A9%EC%9D%B4-%EC%9E%88%EB%8A%94-n%EA%B0%9C%EC%9D%98-%EC%88%AB%EC%9E%90</guid>
            <pubDate>Tue, 14 Sep 2021 01:38:12 GMT</pubDate>
            <description><![CDATA[<hr>
<h3 id="문제">문제</h3>
<ul>
<li>정수x 가 x씩 증가하는 숫자를 n개 지니는 배열을 반환하라</li>
</ul>
<h3 id="생각">생각</h3>
<ul>
<li>ex) x = 2, n = 5;</li>
<li>2가 5번씩(반복) 더해지면 된다.</li>
</ul>
<h3 id="코드">코드</h3>
<blockquote>
<pre><code class="language-javascript">function solution(x, n) {
  var answer = [];
  let empty = 0;
  for (let i = 0; i &lt; n; i++){
    empty = empty + x;
    answer.push(empty);
  }

  return answer;
}</code></pre>
</blockquote>
<h3 id="다른사람">다른사람</h3>
<blockquote>
<pre><code class="language-javascript">let array = Array(n).fill(x).map((el, i) =&gt; {return el*(i+1)});</code></pre>
<ul>
<li>n개의 값을 지닌 Array를 생성한다.</li>
<li>n개의 값을 x로 채운다.<ul>
<li>[2,2,2,2,2]의 배열을 map 함수로 반복시킨다.</li>
<li>매개변수 el, i를 이용하여 값을 반환한다.<ul>
<li>el 은 array의 값 / i 는 count이다.</li>
<li><code>el * ( i + 1 )</code> 로 [2, 4, 6, 8, 10]을 만든다. </li>
</ul>
</li>
</ul>
</li>
</ul>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[📖 코드카타 #6 - 문자열 내 p와 y의 개수]]></title>
            <link>https://velog.io/@rand_guy/%EC%BD%94%EB%93%9C%EC%B9%B4%ED%83%80-4-ic450b1f</link>
            <guid>https://velog.io/@rand_guy/%EC%BD%94%EB%93%9C%EC%B9%B4%ED%83%80-4-ic450b1f</guid>
            <pubDate>Mon, 13 Sep 2021 01:46:44 GMT</pubDate>
            <description><![CDATA[<h2 id="문자열-내-p와-y의-개수">문자열 내 p와 y의 개수</h2>
<hr>
<h4 id="조건">조건</h4>
<ul>
<li>대문자 / 소문자가 섞여있는 문자열 S</li>
<li>S가 &#39;p&#39;의 개수와 &#39;y&#39;의 개수를 가지고 있을 때, 같으면 True, 다르면 False</li>
<li>&#39;p&#39;, &#39;y&#39;가 없으면 True를 리턴하라</li>
</ul>
<h4 id="첫번째-생각">첫번째 생각</h4>
<ul>
<li>string.toLowerCase()로 모두 소문자로 변환한다.</li>
<li>for 문을 통해 p와 y를 다른 변수에 넣는다</li>
<li>그리고 둘의 길이를 비교한다.</li>
</ul>
<blockquote>
<pre><code class="language-javascript">function solution(s) {
  let pLength = [];
  let yLength = [];

  const lowCase = s.toLowerCase();
  const array = lowCase.split(&#39;&#39;);
  for ( i = 0; i &lt; lowCase.length; i++) {
    if (lowCase[i] === &#39;p&#39;) {
      pLength.push(lowCase[i]);
    } else if (lowCase[i] === &#39;y&#39;) {
      yLength.push(lowCase[i])
    } 
  }

  if (pLength.length === yLength.length) {
    return true
  } else if (pLength.length === 0 &amp;&amp; yLength.length === 0) {
    return true
  } if (pLength.length !== yLength.length) {
    return false
  }
}
</code></pre>
</blockquote>
<h4 id="다른-사람-생각">다른 사람 생각</h4>
<ul>
<li>다 대문자로 만들고 &#39;P&#39;를 없앤 길이 === &#39;Y&#39;를 없앤 길이면 return True</li>
<li>조건문을 줄 필요가 없다. 위 하나의 조건문으로 아래 3개의 조건문을 충족<ul>
<li>P와 Y의 길이가 같으면 true</li>
<li>P와 Y가 없으면 true</li>
<li>P와 Y의 길이가 다르면 false</li>
</ul>
</li>
</ul>
<blockquote>
<pre><code class="language-javascript">function solution(s) {
  return s.toUpperCase().split(&#39;P&#39;).length === s.toUpperCase().split(&#39;Y&#39;).length;
}</code></pre>
<p>holymoly~</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[📞 코드카타 #5 - 핸드폰 번호 가리기]]></title>
            <link>https://velog.io/@rand_guy/%EC%BD%94%EB%93%9C%EC%B9%B4%ED%83%80-5-%ED%95%B8%EB%93%9C%ED%8F%B0-%EB%B2%88%ED%98%B8-%EA%B0%80%EB%A6%AC%EA%B8%B0</link>
            <guid>https://velog.io/@rand_guy/%EC%BD%94%EB%93%9C%EC%B9%B4%ED%83%80-5-%ED%95%B8%EB%93%9C%ED%8F%B0-%EB%B2%88%ED%98%B8-%EA%B0%80%EB%A6%AC%EA%B8%B0</guid>
            <pubDate>Fri, 10 Sep 2021 01:49:49 GMT</pubDate>
            <description><![CDATA[<h2 id="문제">문제</h2>
<hr>
<ul>
<li>전화번호가 문자열 phone_number로 주어졌을 때, <ul>
<li>전화번호의 뒷 4자리를 제외한 </li>
<li>나머지 숫자를 전부 <code>*</code>으로 가린 문자열을 리턴하라</li>
</ul>
</li>
</ul>
<h2 id="생각">생각</h2>
<hr>
<ul>
<li>뒤에 숫자 4자리는 항상 필요하니까 따로 보관한다(slice)</li>
<li>앞에 오는 숫자를 &#39;*&#39;로 바꾼다<ul>
<li>앞에 오는 숫자들은 뒤에 네자리를 제거한 길이를 구한다(slice &amp; length)</li>
<li>그리고 &#39;*&#39;을 위에서 구한 앞자리의 길이에 곱한다(repeat)</li>
</ul>
</li>
</ul>
<h2 id="코드">코드</h2>
<hr>
<blockquote>
<pre><code class="language-javascript">function solution(phone_number) {
  return phone_number = &#39;*&#39;.repeat(phone_number.slice(0, -4).length) + phone_number.slice(-4);
}
</code></pre>
<ul>
<li>바로 성공은 했으나 가독성이 좋지않아서 아래처럼 재구성했다.</li>
</ul>
<pre><code class="language-javascript">function solution(phone_number) {
  const numStar = &#39;*&#39;.repeat(phone_number.slice(0, -4).length)
  const lastDigits = phone_number.slice(-4); 
  const answer = numStar + lastDigits
  return answer;
}</code></pre>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[CSS] navbar의 특정 메뉴만 반응형으로 작동하기 ]]></title>
            <link>https://velog.io/@rand_guy/CSS-navbar%EC%9D%98-%ED%8A%B9%EC%A0%95-%EB%A9%94%EB%89%B4%EB%A7%8C-%EB%B0%98%EC%9D%91%ED%98%95%EC%9C%BC%EB%A1%9C-%EC%9E%91%EB%8F%99%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@rand_guy/CSS-navbar%EC%9D%98-%ED%8A%B9%EC%A0%95-%EB%A9%94%EB%89%B4%EB%A7%8C-%EB%B0%98%EC%9D%91%ED%98%95%EC%9C%BC%EB%A1%9C-%EC%9E%91%EB%8F%99%ED%95%98%EA%B8%B0</guid>
            <pubDate>Thu, 09 Sep 2021 07:52:59 GMT</pubDate>
            <description><![CDATA[<hr>
<blockquote>
<pre><code class="language-html">&lt;div className=&quot;navContainer&quot;&gt;
    &lt;div className=&quot;brand&quot;&gt;
        &lt;div className=&quot;logo&quot;&gt;LOGO&lt;/div&gt;
    &lt;/div&gt;
    &lt;div className=&quot;section&quot;&gt;
        &lt;div className=&quot;number number1&quot;&gt;123&lt;/div&gt;
       &lt;div className=&quot;number&quot;&gt;234&lt;/div&gt;
        &lt;div className=&quot;number&quot;&gt;345&lt;/div&gt;
        &lt;div className=&quot;number&quot;&gt;456&lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;</code></pre>
</blockquote>
<blockquote>
<pre><code class="language-css">.navContainer {
    display: flex;
    justify-content: center;
    align-items: center;
    background-color: black;
    height: 100px;
    color: white;
    margin: 0 auto;
}

.brand {
    height: 60px;
    width: 200px;
    background-color: blue;
}

.logo {
    height: 60%;
    width: 180px;
    margin: 10px;
    background-color: green;
}

.section {
    display: flex;
    background-color: red;
    width: 900px;
    height: 60px;
}

.number {
    width: 100px;
    background-color: brown;
    margin: 10px;
}

.number1 {
    flex-grow: 1;
}
</code></pre>
</blockquote>
<p><img src="https://images.velog.io/images/rand_guy/post/1db84450-20f0-4169-9971-bbaa45eac19d/ezgif.com-video-to-gif-4.gif" alt=""></p>
<h2 id="🕵🏻♂️-결론">🕵🏻‍♂️ 결론</h2>
<hr>
<h4 id="flex-grow"><a href="https://developer.mozilla.org/ko/docs/Web/CSS/flex-grow">Flex-grow</a></h4>
<p>여태까지는 Flex-grow를 Navbar의 모든 메뉴의 사이즈를 비율로 조정할 때, 사용했다.</p>
<ul>
<li>하지만 특정 메뉴의 사이즈만 브라우저의 크기에 반응하도록 만들 때, </li>
<li>반응하길 원하는 메뉴에만 flex-grow를 설정하면 크기에 맞춰서 사이즈가 커졌다가 작아졌다가 한다. </li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[🍉 코드카타 #4 ]]></title>
            <link>https://velog.io/@rand_guy/%EC%BD%94%EB%93%9C%EC%B9%B4%ED%83%80-4</link>
            <guid>https://velog.io/@rand_guy/%EC%BD%94%EB%93%9C%EC%B9%B4%ED%83%80-4</guid>
            <pubDate>Thu, 09 Sep 2021 01:39:20 GMT</pubDate>
            <description><![CDATA[<p>프로그래머스 문제 : 수박수박수박수박수박수?</p>
<h2 id="조건">조건</h2>
<hr>
<ul>
<li>길이가 N</li>
<li>수박수박수박수.. 패턴 문즈열을 반환하는 함수 solution을 완성하ㅏㄹ?</li>
<li>ex) n = 4 라면 수박수박을 리턴하고 3이면 수박수를 리턴하라</li>
</ul>
<h2 id="생각">생각</h2>
<hr>
<ul>
<li>조건으로 주어진 단어가 &quot;수박 &quot;이다</li>
<li>수박은 길이가 2인 문자열이다.</li>
<li>그러므로 N을 2로 나누어 &quot;수박&quot;이 최대로 들어갈 수 있는 길이를 구한다.<ul>
<li>만약 짝수라면 더 이상 추가할 것 없이 answer에 출력한다.</li>
<li>만약 홀수라면 &#39;수&#39;를 추가해서 출력한다.</li>
</ul>
</li>
</ul>
<h2 id="코드">코드</h2>
<hr>
<blockquote>
<pre><code class="language-JavaScript">function solution(n) {
  let answer = &quot;수박&quot;.repeat(Math.floor(n/2))
  // n이 홀수인 경우, &#39;.5&#39;가 반환된다.그래서 floor를 사용하여 소수점이하로 내림한다.
  // repeat 메서드로 갯수만큼 반복한다.

  if ( n%2 !== 0 ) {
    answer = answer + &#39;수&#39; 
  }
  // 만약 n이 홀수라면 &#39;수&#39;를 더해서 반환한다.

  return answer;
}</code></pre>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[리액트 UI 라이브러리 정리]]></title>
            <link>https://velog.io/@rand_guy/%EB%A6%AC%EC%95%A1%ED%8A%B8-UI-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC-%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@rand_guy/%EB%A6%AC%EC%95%A1%ED%8A%B8-UI-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC-%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Fri, 03 Sep 2021 06:49:44 GMT</pubDate>
            <description><![CDATA[<hr>
<p><a href="https://usecode.pw/10-best-react-ui-library/">순위 10위를 리스트한 블로그</a> 와 <a href="https://betterprogramming.pub/the-top-3-react-ui-libraries-for-beginners-6987f7b62c78">외국 블로그</a>를 참조하여 리액트 기반의 UI를 편리하게 디자인할 수 있는 라이브러리 중 3가지를 추려봤습니다. </p>
<Br>

<h2 id="1-material-ui">1. <a href="https://material-ui.com">Material-UI</a></h2>
<hr>
<p><img src="https://images.velog.io/images/rand_guy/post/f9e189e0-333f-4844-a7d0-1fc5e770c1f9/image.png" alt="">구글 머테리얼 디자인을 기반을 제작되었다. 유니클로, 아마존, 넷플릭스, 스포티파이 등의 기업에서 사용 될 정도로 인기가 많고 관리가 잘되어 있는 라이브러리다. 대부분의 UI와 관련된 모든 것이 준비되어있다. </p>
<ul>
<li><h4 id="장점">장점</h4>
<ul>
<li>글로벌 스타일 시트(ex. normalize.css)를 사용하지 않아도 필수적인 스타일을 적용시킬 수 있다.</li>
<li>전체적으로 동일한 디자인을 선보여서 UX에 도움이 된다.</li>
<li>업데이트가 잦다</li>
<li>자유도가 높다</li>
<li>오피셜 사이트 정리가 잘 되어있다.</li>
</ul>
</li>
<li><h4 id="단점">단점</h4>
<ul>
<li>필요없는 UI가 많이 적용되어있는 경우가 있다.</li>
<li>호환성이 제한적이다. iOS, Windows 등의 호환성이 Android 호환성에 의해 제한되어있다.</li>
<li>구글 가이드라인에 의해서 Theme이 적용되기에 브랜딩이 제한적일 수 있다.</li>
</ul>
</li>
</ul>
<br>


<h2 id="2-ant-design">2. <a href="https://ant.design/">Ant Design</a></h2>
<hr>
<p><img src="https://images.velog.io/images/rand_guy/post/a2154367-8a3a-41dc-90b2-44c6e466edb0/image.png" alt="">타입스크립트(Typescript) 기반으로 제작된 라이브러리이다. 사용에 있어서 편리하여 최근 많이 사용되는 추세이다.</p>
<ul>
<li><h4 id="장점-1">장점</h4>
<ul>
<li><a href="https://ant.design/components/overview/">컴포넌트들이 많다</a></li>
<li><a href="https://ant.design/docs/react/getting-started">오피셜 사이트에 예시가 많다</a></li>
<li>다양한 회사들이 사용중이다.</li>
<li><a href="https://www.youtube.com/watch?v=pTYFVQ7w550">Youtube 강의</a></li>
</ul>
</li>
<li><h4 id="단점-1">단점</h4>
<ul>
<li><a href="https://ant.design/docs/react/customize-theme">커스터마이즈하기 어렵다.</a></li>
</ul>
</li>
</ul>
<br>

<h2 id="3-react-bootstrap"><a href="https://react-bootstrap.github.io">3. React Bootstrap</a></h2>
<hr>
<p><img src="https://images.velog.io/images/rand_guy/post/39c82802-4f05-4685-b91d-442bad4ac35c/image.png" alt="">인기높은 CSS 프레임워크 Bootstrap을 리액트 기반으로 만들었다.  리액트를 사용해보지 않았으나 부트스트랩을 사용해본 사람이라면 편리하게 사용 가능하다. 하지만 대부분의 유저들이 부트스트랩 그리드 시스템을 적용해야 할 때 사용한다.</p>
<ul>
<li><h4 id="장점-2">장점</h4>
<ul>
<li>컨테이너, rows, columns 등의 레이아웃과 컨텐츠를 나열하는데 부트스트랩의 그리드 시스템이 사용되었다.</li>
<li>반응형으로 제작하기에 편리하다</li>
<li>사용법이 굉장히 잘 정리되어 있다.</li>
<li>부트스트랩 4의 Thme을 지원한다</li>
</ul>
</li>
<li><h4 id="단점-2">단점</h4>
<ul>
<li>컴포넌트가 많지 않다</li>
<li>프로퍼티도 적다.</li>
</ul>
</li>
</ul>
<h3 id="의견--시간이-많다면-material-ui-없다면-ant-design-그리고-bootstrap-유저-react-bootstrp">의견 : 시간이 많다면 material UI, 없다면 Ant Design, 그리고 Bootstrap 유저? React Bootstrp</h3>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TIL]BABEL과 폴리필, 그리고 AST]]></title>
            <link>https://velog.io/@rand_guy/TILBABEL%EA%B3%BC-%ED%8F%B4%EB%A6%AC%ED%95%84-%EA%B7%B8%EB%A6%AC%EA%B3%A0-AST</link>
            <guid>https://velog.io/@rand_guy/TILBABEL%EA%B3%BC-%ED%8F%B4%EB%A6%AC%ED%95%84-%EA%B7%B8%EB%A6%AC%EA%B3%A0-AST</guid>
            <pubDate>Thu, 02 Sep 2021 06:48:47 GMT</pubDate>
            <description><![CDATA[<h2 id="babel-왜-바벨을-사용할까">BABEL? 왜 바벨을 사용할까?</h2>
<hr>
<p>코어 자바스크립트 문서에 따르면, 자바스크립트는 계속해서 진화한다. 그렇기에 많은 유저들의 다양한 제안을 <a href="https://tc39.es/ecma262/">ECMA사이트</a> 정기적으로 정리하고 있다. 그리고 궁극적으로 ECMA Script Specification (<a href="https://www.ecma-international.org/publications-and-standards/standards/ecma-262/">명세서</a>)에 등록된다. 이렇게 등록된 제안들을 각 브라우저, 자바스크립트 엔진을 만드는 조직은 새롭게 작성된 명세서의 기능들을 차례대로 구현한다. 하지만 이러한 과정은 빠르게 진행되지 않는다.</p>
<p>이런 경우, 명세서에 등록된 지 얼마 안 된 기능이 특정 엔진에서 지원되지 않아 원하는 대로 작동되지 않는 경우가 있다. 그리고 브라우저나 플랫폼마다 보여지는 모습이 다른 경우가 있다. 이를 최적화해주는 작업을 &#39;&#39;크로스 브라우징&#39;(Cross Browsing)이라고 한다. 이런 문제를 해결해주는 툴이 바벨이다. 바벨은 추상화 수준을 유지한 채로 코드를 변화시키는 트랜스파일러의 역활을 실행한다.</p>
<blockquote>
<p>추상화란 복잡함 속에서 필요한 관점만을 추출하는 행위. 개발은 추상화를 통해 문제를 해석하고 해결하는 프로그램을 만드는 과정이다.</p>
</blockquote>
<h3 id="바벨">바벨</h3>
<hr>
<p>바벨은 트랜스 파일러로, 모던 자바스크립트 코드를 구 표준을 준수하는 코드로 바꿔준다. 바벨을 통해 ES+6의 자바스크립트 코드는 하위 버전으로 변환한다. 이를 통해, 인터넷 익스플로어에서도 동작한다.</p>
<h4 id="바벨의-빌드-단게">바벨의 빌드 단게</h4>
<ol>
<li><p>파싱(parsing) : 코드를 읽고 추상 구문 트리(AST)로 변환하는 단계</p>
<blockquote>
<p>추상 구문 트리(AST)</p>
<p>npm install을 통해 설치된 <code>devDependencies</code> 를 확인하면 다양한 도구들이 발전하여 도움을 준다는 것을 눈으로 확인할 수 있다. 이는 프로덕션 코드*에 포함되지 않는 JS모듈이지만 중요하다. 이 도구들은 모두 AST 처리를 기반으로 구축되었다. </p>
<p> Abstract Syntax Tree, AST(추상 구문 트리)는 프로그래밍 언어의 문법에 따라 소스 코드 구조를 표시하는 계층적 프로그램 표현이다. 각 AST 노드는 소스 코드의 항목에 해당한다. 그렇다면 바벨은 어떻게 AST를 활용하는가?</p>
<p>바벨은 정확히는 JS 컴파일러이다. 일반적으로 크로스 브라우징을 위해 사용되지만, 이는 바벨의 플러그인 그룹 중 하나에 불과하다. 바벨은 코드 압축 / React 문법(ex. JSX)를 트랜스파일할 때, Flow를 위한 플러그인으로도 사용한다.</p>
<p>파싱 단계에서 AST를 구축하고, 변환 단계에서 적용된 플러그인을 통해 AST를 탐색, 수정하여 생성 단계에서 수정된 AST에서 새로운 코드를 생성한다.</p>
</blockquote>
<blockquote>
<blockquote>
<p>​    *프로덕션 코드 : 프로젝트의 로직을 포함하고 어플리케이션(제품)에서 실행되는 시스템의 부분을 의미한다</p>
</blockquote>
</blockquote>
</li>
<li><p>변환(Transforming) : 추상 구문 트리를 변경</p>
</li>
<li><p>출력(Printing) : 변경된 결과물을 출력한다.</p>
</li>
</ol>
<p>여기서 바벨은 파싱과 출력을 담당한다. 하지만 변환은 플러그인 맡아서 진행한다. <strong>바벨 플러그인은 바벨이 어떤 코드를 어떻게 변환할 지에 대한 규칙을 나타낸다.</strong> 이는 일일이 바벨 플러그인을 설정하여 입맛에 맞게 변경할 수 있다.</p>
<p><strong>하지만 프리셋을 설정하여 필요한 플러그인들을 목적에 따라 세트로 묶어서 적용하기도 한다.</strong> 현재 바벨은 env 하나로 합쳐서 편리하게 사용할 수 있다. 대표적인 프리셋은 ES6+로 변환하는 preset-env가 있다.</p>
<h3 id="폴리필">폴리필</h3>
<hr>
<p>폴리필은 <strong>최신 ECMAscript 환경을 만들기 위해 코드가 실행되는 환경에 존재하지 않는 빌트인, 메소드 등을 추가</strong>하는 역활을 한다. 폴리필의 예로는 ES6의 Promise 객체는 env 프리셋을 가지고 변환해도 IE에서 인식하지 못한다. 이러한 경우, <strong>폴리필을 통해 Promise를 ES5 방식으로 구현하여 해결한다.</strong></p>
<br>

<h2 id="결론">결론</h2>
<hr>
<p>코어자바스크립트에서 바벨에 대한 설명을 보게되어 조금 더 알아보게 되었다. 이를 통해서 AST 추상구문트리에 대해서도 이해 할 수 있었다. 제대로 이해하기 위해서는 추가적으로 블로그를 작성하거나 자주 읽어보러 다시 와야겠다.</p>
<blockquote>
</blockquote>
<p><a href="https://devowen.com/293">참고자료</a>
<a href="https://ko.javascript.info/polyfills">참고자료1</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[크롬 디버깅 과정 정리]]></title>
            <link>https://velog.io/@rand_guy/%ED%81%AC%EB%A1%AC-%EB%94%94%EB%B2%84%EA%B9%85-%EA%B3%BC%EC%A0%95-%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@rand_guy/%ED%81%AC%EB%A1%AC-%EB%94%94%EB%B2%84%EA%B9%85-%EA%B3%BC%EC%A0%95-%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Thu, 02 Sep 2021 04:25:03 GMT</pubDate>
            <description><![CDATA[<h1 id="chrome으로-디버깅하기">Chrome으로 디버깅하기</h1>
<hr>
<p>디버깅은 스크립트 내 에러를 검출해 제거하는 일련의 과정을 의미한다.</p>
<p>모던 브라우저와 호스트 환경 대부분은 개발자 도구 안에서 UI 형태로 디버깅 툴을 구비했다. </p>
<h3 id="source-패널">Source 패널</h3>
<hr>
<p><img src="https://images.velog.io/images/rand_guy/post/60d4739a-01f2-4ddd-bb3d-0f925590c909/image.png" alt=""></p>
<ol>
<li><strong>파일 탐색 영역 :</strong> 페이지를 구성하는 데 쓰인 모든 리소스를 트리 형태로 표시</li>
<li><strong>코드 에디터 영역 :</strong> 소스 코드 편집</li>
<li><strong>자바스크립트 디버깅 영역</strong> : 디버깅 툴 제공</li>
</ol>
<h4 id="중단점">중단점</h4>
<hr>
<p><img src="https://images.velog.io/images/rand_guy/post/893523ff-8d14-4bdc-ba20-4fe73c9bcead/image.png" alt=""></p>
<p>중단점을 사용하면 실행이 중지된 시점에 변수가 어떤 값을 담는지 알 수 있다.</p>
<p>실행이 중지된 시점을 기준으로 명령어 실행 가능</p>
<h4 id="debugger-명령어">debugger 명령어</h4>
<hr>
<blockquote>
<pre><code class="language-javascript">function hello(name) {
  let phrase = `Hello, ${name}!`;

  debugger;  // &lt;-- 여기서 실행이 멈춥니다.

  say(phrase);
}</code></pre>
<p>debugger 명령어는 중단점을 설정한 효과를 본다. (에디터를 떠나지 않고 중단점 설정하는 용이)</p>
</blockquote>
<h4 id="중단점을-통해-확인할-수-있는-것">중단점을 통해 확인할 수 있는 것</h4>
<hr>
<p><img src="https://images.velog.io/images/rand_guy/post/6a70ef09-b8f9-4f03-b028-2d5594357a8d/image.png" alt=""></p>
<ol>
<li><strong>Watch - 표현식을 평가하고 결과를 표시</strong><ul>
<li><code>+버튼</code> (add expression)을 클릭하고 원하는 표현식을 입력하고 <code>enter</code> 를 누르면 중단 시점의 값 표시 </li>
<li>입력한 표현식은 실행 과정 중에 재평가 진행</li>
</ul>
</li>
<li><strong>Call Stack - 코드를 중단점으로 안내한 실행 경로를 역순으로 표시</strong></li>
<li><strong>Scope - 현재 정의된 모든 변수를 출력</strong><ul>
<li>Local : 함수의 지역변수<ul>
<li>this의 정보도 따로 출력</li>
</ul>
</li>
<li>Global : 전역변수</li>
</ul>
</li>
</ol>
<h4 id="실행-추적하기">실행 추적하기</h4>
<hr>
<p><span style="color:grey"> 실행 추적하기는 아이콘이 필요하여 <a href="https://ko.javascript.info/debugging-chrome">코어자바스크립트</a> 페이지에서 확인하길 바랍니다.</span></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[🦅 코드카타 #3]]></title>
            <link>https://velog.io/@rand_guy/%EC%BD%94%EB%93%9C%EC%B9%B4%ED%83%80-3</link>
            <guid>https://velog.io/@rand_guy/%EC%BD%94%EB%93%9C%EC%B9%B4%ED%83%80-3</guid>
            <pubDate>Thu, 02 Sep 2021 01:50:38 GMT</pubDate>
            <description><![CDATA[<h1 id="🦅-폰켓몬-문제">🦅 폰켓몬 문제</h1>
<hr>
<p><strong>축약) 중복되는 값이 존재하는 배열에서 절반을 가져갈 때, 최대한 중복이 되지 않게 가져가는 값들의 개수를 반환하라</strong></p>
<ol>
<li>중복되는 값을 제거하고 새로운 값을 만든다 (new Set(nums))<ul>
<li>Set 객체는 유일한 원시값을 반환한다</li>
</ul>
</li>
<li>최대 값이 될 개수(N/2)를  정의한다. (nums.length/2)</li>
<li>절반으로 나눈 개수를 최대로 설정하여 그 안에서 중복되지 않는 값들을 넣어서 개수를 확인 후, 반환<ul>
<li>splice로 0번부터 최대 개수(nums.length/2)만 splice해서 반환한다. </li>
</ul>
</li>
</ol>
<p><img src="https://images.velog.io/images/rand_guy/post/4e7b9e25-2840-4fdf-af71-76cf8a0e8fe1/%EC%BD%94%EC%B9%B42.png" alt=""></p>
<h2 id="오늘의-배움--set-"><a href="https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Set">오늘의 배움 ( SET )</a></h2>
<hr>
<blockquote>
<p><strong><code>Set</code></strong> 객체는 자료형에 관계 없이 <a href="https://developer.mozilla.org/ko/docs/Glossary/Primitive">원시 값</a>과 객체 참조 모두 유일한 값을 저장할 수 있습니다.</p>
<pre><code class="language-JavaScript">const set1 = new Set([1, 2, 3, 4, 5]);

console.log(set1.has(1));
// expected output: true

console.log(set1.has(5));
// expected output: true

console.log(set1.has(6));
// expected output: false</code></pre>
<p>매개변수는 반복 가능한 객체가 전달된 경우, 그 요소는 모두 새로운 <code>Set</code>에 추가됩니다. </p>
<p>만약 매개변수를 명시하지 않거나 <code>null</code>을 전달하면, 새로운 <code>Set</code>은 비어 있는 상태가 됩니다.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TIL]코어=>자바스크립트와 친해지기 #2 - While & 반복문]]></title>
            <link>https://velog.io/@rand_guy/TIL%EC%BD%94%EC%96%B4%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EC%99%80-%EC%B9%9C%ED%95%B4%EC%A7%80%EA%B8%B0-2-While-%EB%B0%98%EB%B3%B5%EB%AC%B8</link>
            <guid>https://velog.io/@rand_guy/TIL%EC%BD%94%EC%96%B4%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EC%99%80-%EC%B9%9C%ED%95%B4%EC%A7%80%EA%B8%B0-2-While-%EB%B0%98%EB%B3%B5%EB%AC%B8</guid>
            <pubDate>Wed, 01 Sep 2021 12:40:16 GMT</pubDate>
            <description><![CDATA[<hr>
<ul>
<li><h3 id="반복문-빠져나오기"><strong>반복문 빠져나오기</strong></h3>
<blockquote>
<pre><code class="language-javascript">let sum = 0;

while (true) {
  let value = +prompt(&quot;숫자를 입력하세요.&quot;, &#39;&#39;);
  if (!value) break; // (*)
  sum += value;
}

alert( &#39;합계: &#39; + sum );

// 유저가 cancel 버튼(임의)를 눌러 조건이 충족되어 반복문이 즉시 중단된다면
// 제어 흐름이 반복문 아래 첫 번째 줄로 이동한다.

// 이는 본문 가운데 혹은 본문 여러 곳에서 조건을 확인해야 하는 경우에
// &#39;무한 반복문 + break&#39; 조합을 사용하면 좋다.</code></pre>
</blockquote>
</li>
<li><h3 id="조건에-맞춰-다음-반복으로-넘어가기"><strong>조건에 맞춰 다음 반복으로 넘어가기</strong></h3>
<blockquote>
<pre><code class="language-javascript">for (let i = 0; i &lt; 10; i++) {
    // 10까지 1씩 증가하는 반복문
  // 조건이 참이라면 남아있는 본문은 실행되지 않습니다.
  if (i % 2 == 0) continue;
  // i를 2로 나눈 값의 나머지가 0이면 반복을 멈추고 다음 이터레이션을 강제로 실행한다.
  alert(i); // 1, 3, 5, 7, 9가 차례대로 출력됨
  // 나머지 값이 0인 경우를 다 패싱했기 때문에 홀수만 출력
}

// continue는 중첩을 줄이는데 큰 도움이 된다.

for (let i = 0; i &lt; 10; i++) {
  if (i % 2) {
    alert( i );
  }
}
// 같은 코드임에도 중첩 레벨이 늘어나고 코드가 길어지면 가독성이 떨어진다.</code></pre>
</blockquote>
</li>
<li><h3 id="breakcontinue-그리고-label"><strong>break/continue 그리고 label</strong></h3>
<blockquote>
<pre><code class="language-javascript">// 여러개의 중첩을 한번에 빠져나와야 하는 경우라면..?!

outer: for (let i = 0; i &lt; 3; i++) {
  for (let j = 0; j &lt; 3; j++) {
    let input = prompt(`(${i},${j})의 값`, &#39;&#39;);
    // 사용자가 아무것도 입력하지 않거나 Cancel 버튼을 누르면 두 반복문 모두를 빠져나옵니다.
    if (!input) break outer; // (*)
    // input의 값이 변경되면 label에 해당되는 식별자 앞에 break를 넣어 해당 반복문을 탈출한다
  }
}
alert(&#39;완료!&#39;);</code></pre>
</blockquote>
</li>
<li><h3 id="switch문은-언제-사용하면-좋을까-">*<em>Switch문은 언제 사용하면 좋을까? *</em></h3>
<blockquote>
<pre><code class="language-JavaScript">switch (browser) {
  case &#39;Edge&#39;:
    alert( &quot;Edge를 사용하고 계시네요!&quot; );
    break;

  case &#39;Chrome&#39;:
  case &#39;Firefox&#39;:
  case &#39;Safari&#39;:
  case &#39;Opera&#39;:
    alert( &#39;저희 서비스가 지원하는 브라우저를 사용하고 계시네요.&#39; );
    break;

  default:
    alert( &#39;현재 페이지가 괜찮아 보이길 바랍니다!&#39; );</code></pre>
</blockquote>
</li>
</ul>
<br>

<h2 id="결론">결론</h2>
<hr>
<p>전에는 알지 못했던 break / continue의 사용조건, 그리고 label을 알 수 있었다. 자주 사용되지는 않더라도 코드가 길어지고 가독성이 어려울 때, 사용하면 유용하다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TIL]코어=>자바스트립트와 친해지기 #1 - 연산자]]></title>
            <link>https://velog.io/@rand_guy/TIL%EC%BD%94%EC%96%B4%EC%9E%90%EB%B0%94%EC%8A%A4%ED%8A%B8%EB%A6%BD%ED%8A%B8%EC%99%80-%EC%B9%9C%ED%95%B4%EC%A7%80%EA%B8%B0-1-%EC%97%B0%EC%82%B0%EC%9E%90</link>
            <guid>https://velog.io/@rand_guy/TIL%EC%BD%94%EC%96%B4%EC%9E%90%EB%B0%94%EC%8A%A4%ED%8A%B8%EB%A6%BD%ED%8A%B8%EC%99%80-%EC%B9%9C%ED%95%B4%EC%A7%80%EA%B8%B0-1-%EC%97%B0%EC%82%B0%EC%9E%90</guid>
            <pubDate>Wed, 01 Sep 2021 06:44:43 GMT</pubDate>
            <description><![CDATA[<hr>
<p>전에는 무슨 얘긴지 이해도 안되고 어떻게 사용해할지도 몰랐다. 이제 조금 알게 되었으니, 다시 한번 도전해본다. 자바스크립트와 친해지기. 과거에 지나치듯 보게 되고 이해되지 않았던 내용들 그리고 애매했던 내용을 정리한다.</p>
<h2 id="👨🏻💻-기본-연산자와-수학">👨🏻‍💻 기본 연산자와 수학</h2>
<hr>
<ul>
<li><p><strong>할당 연산자 체이닝</strong> </p>
<blockquote>
<pre><code class="language-javascript">let a, b, c;

c = 2 + 2;
b = c;
a = c;

alert( a ); // 4
alert( b ); // 4
alert( c ); // 4</code></pre>
</blockquote>
</li>
</ul>
<ul>
<li><p><strong>복합 할당 연산자</strong></p>
<blockquote>
<pre><code class="language-javascript">let n = 2;
n += 5; // n은 7이 됩니다(n = n + 5와 동일).
n *= 2; // n은 14가 됩니다(n = n * 2와 동일).

alert( n ); // 14</code></pre>
</blockquote>
</li>
</ul>
<ul>
<li><p><strong>비트 연산자</strong></p>
<blockquote>
<pre><code class="language-javascript">// 비트 연산자는 암호를 다뤄야 할 때 유용하다.

비트 AND ( &amp; )
비트 OR ( | )
비트 XOR ( ^ )
비트 NOT ( ~ )
왼쪽 시프트(LEFT SHIFT) ( &lt;&lt; )
오른쪽 시프트(RIGHT SHIFT) ( &gt;&gt; )
부호 없는 오른쪽 시프트(ZERO-FILL RIGHT SHIFT) ( &gt;&gt;&gt; )</code></pre>
</blockquote>
</li>
</ul>
<ul>
<li><p><strong>쉼표 연산자</strong></p>
</li>
<li><blockquote>
<pre><code class="language-javascript">// 쉼표 연산자는 여러 표현식을 코드 한 줄에서 평가할 수 있게 해준다.
// 표현식 각각이 모두 평가되지만 마지막 표현식의 평가 결과만 반환된다. 

let a = (1 + 2, 3 + 4);
alert( a ); // 7 (3 + 4의 결과)

// 하지만 여러동작을 하나의 줄에서 처리할 때 용이하다.
// 한 줄에서 세 개의 연산이 수행됨

for (a = 1, b = 3, c = a * b; a &lt; 10; a++) {
 ...
}</code></pre>
</blockquote>
</li>
</ul>
<br>

<h2 id="👨🏻💻-비교연산자">👨🏻‍💻 비교연산자</h2>
<hr>
<ul>
<li><p><strong>동등 연산자 &amp;&amp; 일치 연산자</strong> </p>
<blockquote>
<pre><code class="language-javascript">a == b // 동등 연산자 : 비교할 피연산자를 다른 자료형으로 변경하여 비교한다. 값만 비교
a === b // 일치 연산자 : 형 변환 없이 값을 비교한다. 엄격한 동등 연산자.</code></pre>
</blockquote>
</li>
</ul>
<br>

<h2 id="👨🏻💻-if와-를-사용한-조건-처리">👨🏻‍💻 if와 &quot;?&quot;를 사용한 조건 처리</h2>
<hr>
<ul>
<li><p><strong>불린형으로의 변환</strong> </p>
<blockquote>
<pre><code class="language-javascript">falsy값 = [숫자 0, 빈 문자열&quot;&quot;, null, undefined, NaN]
Truthy값 = 위와 반대같은 값은 불린 형으로 변환할 때, truthy가 된다</code></pre>
</blockquote>
</li>
<li><p><strong>조건부 연산자 &#39;?&#39;</strong></p>
<blockquote>
<pre><code class="language-javascript">// 조건에 따라 다른 값을 변수에 할당해줘야 할때 
// &#39;물음표 연산자&#39; / &#39;조건부 연산자&#39;
// 피연산자가 세 개이기 때문에 &#39;삼항 연산자&#39;라고 부르기도 한다. 
// 피연산자가 세 개인 연산자는 조건부 연산자가 유일하다</code></pre>
</blockquote>
</li>
</ul>
<br>

<h2 id="👨🏻💻-논리-연산자">👨🏻‍💻 논리 연산자</h2>
<hr>
<ul>
<li><p><strong>OR 연산자 체이닝의 추가기능</strong> + <strong>단락평가</strong></p>
<blockquote>
<pre><code class="language-javascript">result = value1 || value2 || value3;
// 이렇게 작성하게 되면 자바스크립트는 어떻게 작동하는가?
// 왼쪽부터 오른쪽으로 피연산자 평가
// 각 피연산자를 불린 형변환 - 변환한 값이 true면 stop - 해당 피연산자의 변환 전 값을 반환
// 피연산자 모두를 평가한 경우(모든 연산자가 false) - 마지막 피연산자를 반환

alert( 1 || 0 ); // 1 (1은 truthy임)

alert( null || 1 ); // 1 (1은 truthy임)
alert( null || 0 || 1 ); // 1 (1은 truthy임)

alert( undefined || null || 0 ); // 0 (모두 falsy이므로, 마지막 값을 반환함)

// 이러한 기능을 아래의 예제와 같이 사용 가능하다
    // 1. 변수 또는 표현식으로 구성된 목록에서 첫 번째 truthy 얻기
let firstName = &quot;&quot;;
let lastName = &quot;&quot;;
let nickName = &quot;바이올렛&quot;;

alert( firstName || lastName || nickName || &quot;익명&quot;); // 바이올렛

    // 2. 단락 평가 (short circuit evaluation)
    // 단락 평가는 truthy를 만나면 나머지 값들을 건드리지 않은 채 평가를 멈추는 평가이다.
  // 동작 방식은 두 번째 피연산자가 변수 할당과 같은 부수적인 효과(side effect)를 가지는 표현식 일때 명확히 볼수 있다.

true || alert(&quot;not printed&quot;); // 작동안함
false || alert(&quot;printed&quot;); // &quot;printed&quot; 작동함

  // 첫 번째 OR연산자는 true를 만나자마자 평가를 멈춤
  // 그렇기에 연산자의 왼쪽 조건이 falsy일때만 명령어를 실행하고자 할 때 자주 사용된다.
</code></pre>
</blockquote>
</li>
<li><p>*<em>AND연산자 *</em>+ NOT연산자</p>
<blockquote>
<pre><code class="language-javascript">// 위에서 OR연산자를 정리하였기에 비교하여 정리합니다.

// AND 연산자는 첫 번째 falsy를 반환한다.
// OR 연산자는 첫 번째 truthy를 반환한다.

// + 프로젝트 기간중에 &amp;&amp; 연산자를 state값의 변경에 따라 나타나게 할 때, 사용했다.

{state === 1 &amp;&amp; alert(&quot;abc&quot;)} 
// state값이 1이면 &quot;abc&quot;가 실행된다.

++++
// NOT연산자(!)의 우선순위는 모든 논리 연산자중 가장 높아서 가장 먼저 실행된다</code></pre>
</blockquote>
</li>
<li><p><strong>null병합연산자 ??</strong></p>
<blockquote>
<p>null병합연산자(nullish coalescing operator)는 &#39;확정되어있는&#39; 변수를 찾을 수 있다.</p>
<ul>
<li>?? 과 ||의 차이<ul>
<li>OR연산자는 첫 번째 truthy 값을 반환한다.</li>
<li>null병합연산자는 첫 번째 정의된(defined) 값을 반환한다.<ul>
<li>null / undefined 등의 아직 정의되지 않은 값은 지나간다.</li>
</ul>
</li>
</ul>
</li>
</ul>
<pre><code class="language-javascript">height = height ?? 100;

let height = 0;

alert(height || 100); // 100
alert(height ?? 100); // 0</code></pre>
<p>??의 연산자 우선순위는 ?와 = 보다만 높다</p>
<p>괄호 없이 ??를 ||나 &amp;&amp;와 함께 사용하는건 금지되어있다</p>
</blockquote>
</li>
</ul>
<br>

<h2 id="👨🏻💻-결론">👨🏻‍💻 결론</h2>
<hr>
<p>연산자에만 해도 내가 명확하게 설명할 수 없는 내용이 이만큼이나 있었다... 너희를 위해 자주 돌아오겠다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TIL] 타입스크립트 개념잡기 #3 - 기본 타입zip]]></title>
            <link>https://velog.io/@rand_guy/TIL-%ED%83%80%EC%9E%85%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EA%B0%9C%EB%85%90%EC%9E%A1%EA%B8%B0-3-%EA%B8%B0%EB%B3%B8-%ED%83%80%EC%9E%85zip</link>
            <guid>https://velog.io/@rand_guy/TIL-%ED%83%80%EC%9E%85%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EA%B0%9C%EB%85%90%EC%9E%A1%EA%B8%B0-3-%EA%B8%B0%EB%B3%B8-%ED%83%80%EC%9E%85zip</guid>
            <pubDate>Tue, 31 Aug 2021 09:09:38 GMT</pubDate>
            <description><![CDATA[<h1 id="typescript-기본-타입">Typescript 기본 타입</h1>
<hr>
<h4 id="불리언--boolean-">불리언 ( Boolean )</h4>
<ul>
<li><code>let isDone: boolean = false;</code> </li>
</ul>
<h4 id="숫자--number-">숫자 ( Number )</h4>
<ul>
<li><code>let decimal: number = 6;</code></li>
</ul>
<h4 id="문자열--string-">문자열 ( String )</h4>
<ul>
<li><code>let color: string = &quot;blue&quot;;</code></li>
<li><code>color = &#39;red&#39;;</code></li>
<li>템플릿 리터럴도 적용된다. 표현식도 포함가능하다<ul>
<li><code>let sentence: string = &#39;yellow, my name is ${ name }. age is ${ age + 1 }</code></li>
</ul>
</li>
</ul>
<h4 id="배열--array-">배열 ( Array )</h4>
<blockquote>
<pre><code class="language-typescript">// 배열 타입은 두가지 방법으로 선언 가능하다.
let list: number[] = [1,2,3];
// 1. 배열 요소들을 나타내는 타입 뒤에 []를 쓴다.

let list: Array&lt;number&gt; = [1,2,3];
// 2. 제네릭 배열 타입을 쓴다.</code></pre>
</blockquote>
<h4 id="튜플--tuple-">튜플 ( Tuple )</h4>
<ul>
<li>튜플은 요소의 타입과 개수가 고정된 배열을 나타낸다.<ul>
<li>모든 요소들의 타입이 모두 같을 필요는 없다.</li>
</ul>
</li>
</ul>
<blockquote>
<pre><code class="language-typescript">// 튜플 타입으로 선언
let x: [string, number];
// 초기화
x = [&quot;hello&quot;, 10]; // 위 선언된 변수의 타입과 같음으로 성공
// 잘못된 초기화
x = [10, &#39;hello&#39;]; // 오류</code></pre>
<p>정해진 인덱스에 위치한 요소에 접근하면 해당 타입이 나타난다. 그 외에는 오류가 발생한다.</p>
</blockquote>
<h4 id="열거--enum-">열거 ( Enum )</h4>
<ul>
<li><strong>JavaScript 표훈 자료형 집합과 사용하면 도움이 될만한 데이터 형이다?</strong><ul>
<li>enum은 값의 집합에 더 나은 이름을 붙여준다?</li>
<li>enum은 기본적으로 배열처럼 0부터 시작하는 번호를 가진다.</li>
<li>하지만 번호를 수동으로 설정하여 변경할 수 있다.</li>
</ul>
</li>
</ul>
<blockquote>
<pre><code class="language-typescript">enum Color {Red, Green, Blue}
let c: Color = Color.Green;
// 기본 세팅

enum Color {Red = 1, Green, Blue}
let c: Color = Color.Green;
// 이렇게 Red에 숫자 1을 할당하면 1번부터 시작하는 번호를 각각 가진다. // Green = 2, Blue = 3

enum Color {Red = 1, Green = 3, Blue = 4}
let c: Color = Color.Green;
// 이렇게 하면 각각 번호가 매겨진 값들을 Key로 사용할 수 있다.

let colorNmae: string = Color[3]; // &#39;Green&#39;
// 위처럼 배열과 객체 사이처럼 값을 가져올 수 있다.</code></pre>
</blockquote>
<h4 id="any">Any</h4>
<ul>
<li>컴파일 검사를 통과하는 값을 지정할 때 사용되는 타입<ul>
<li>유저 / 서드 파티 라이버리 / 동적 컨텐츠에게 값을 받을 경우</li>
</ul>
</li>
</ul>
<blockquote>
<pre><code class="language-typescript">let notSure: any = 4 ;
notSure = &quot;maybe string&quot;
notSure = false; // 이렇게 모든 값을 허용한다.

// 또한, any 타입은 타입의 일부만 알고 전체는 알지 못할 때 유용하다. ex) 여러 다른 타입이 섞인 배열
let list: any[] = [1, true, &#39;free&#39;];</code></pre>
</blockquote>
<h4 id="void">Void</h4>
<ul>
<li>void는 어떤 타입도 존재할 수 없을 때 사용된다. <strong>any의 반대 타입</strong></li>
<li>함수에서 반환 값이 없을 때 반환 타입을 표현하기 위해 자주 사용된다.</li>
</ul>
<blockquote>
<pre><code class="language-typescript">function warnUser(): void {
console.log(&quot;warning&quot;);
}
// 이러면 반환 값이 없어도 실행된다.
// void 타입 변수는 null, undefined만 할당된다

let unusable: void = undefined;
unusable = null; // 성공 -- 이것이 가능한 이유는 &#39;--strictNullChecks&#39;를 사용하지 않아서</code></pre>
</blockquote>
<h4 id="null-and-undefined">Null and Undefined</h4>
<ul>
<li>null 과 undefined는 자신의 타입 이름으로 사용된다</li>
</ul>
<blockquote>
<pre><code class="language-typescript">let u: undefined = undefined;
let n: null = null;</code></pre>
</blockquote>
<ul>
<li><strong>기본적으로 null 과 undefined는 다른 모든 타입의 하위 타입이다.</strong><ul>
<li>그러므로 null / undefined는 number와 같은 타입에 할당된다.</li>
<li>하지만 <code>--strictNullChecks</code> 를 사용하면 오직 any와 각자 타입에서만 할당 가능하다.<ul>
<li>예외적으로 undefined는 void에 할당 가능하다..</li>
</ul>
</li>
</ul>
</li>
<li><strong>일반적인 에러를 방지하기 위해 사용된다</strong><ul>
<li>유니언 타입을 활용하여 <code>string | null | undefined</code> 처럼 사용한다.</li>
</ul>
</li>
</ul>
<h4 id="never">Never</h4>
<ul>
<li>절대 발생할 수 없는 타입을 나타낸다. </li>
<li>함수 표현식 / 화살표 함수 표현식에서 항상 오류를 발생시키거나 절대 반환하지 않는 반환 타입으로 쓰인다??<ul>
<li>변수 또한 타입 가드에 의해 아무 타입도 얻지 못하게 좁혀지면 never 타입을 얻게 된다?</li>
</ul>
</li>
<li><strong>never도 다른 모든 타입의 할당 가능한 하위 타입이다.</strong><ul>
<li>하지만 어떤 타입도 never에 할당되거나 하위타입이 아니다. 심지어 any도 안됨</li>
</ul>
</li>
</ul>
<blockquote>
<pre><code class="language-typescript">// never를 반환하는 함수는 함수의 마지막에 도달할 수 없다.
function error(message: string): never {
throw new Error(message);
}

// 반환 타입이 never로 추론된다. error 함수의 타입이 never이기 때문에
function fail() {
return error(&quot;someting fail&quot;);
}

// never를 반환하는 함수는 함수의 마지막에 도달할 수 없다. while도 도달못한다
function infiniteLooop(): never {
while (true) {
}
}</code></pre>
</blockquote>
<h3 id="객체--object-">객체 ( Object )</h3>
<ul>
<li><p>객체는 원시 타입이 아닌 타입을 나타낸다.</p>
<ul>
<li>원시타입 : <code>number, string, boolean, bigint, symbol, null, undefined</code></li>
</ul>
</li>
<li><p>object 타입을 쓰면, <code>object.create</code> 같은 API가 더 잘 나타난다?</p>
</li>
</ul>
<blockquote>
<pre><code class="language-typescript">declare function create(o: object | null): void; 
// 함수의 타입이 void여서 실행문 없어도 오류가 발생하지 않는다.
// create로 받아오는 매개변수는 object여야 실행된다.

create({ props: 0}); // 객체여서 실행
create(null); // null은 왜 되는거야??
create(undefined); // undefined는 또 왜 안되는거야??</code></pre>
</blockquote>
<h4 id="타입-단언--type-assertions-">타입 단언 ( Type assertions )</h4>
<ul>
<li>타입 단언은 컴파일러를 대신해서 인간이 대신 검사를 했다고 타입 스크립트에게 고지한다.<ul>
<li>타입단언은 런타임에 영향을 미치지 않는다. 또한 타입스크립트가 개발자가 어떤 검사를 수행했다고 인지한다.</li>
</ul>
</li>
</ul>
<blockquote>
<pre><code class="language-typescript">// 두가지 형식이 있다

// 1. angle-bracket 문법
let someValue: any = &quot;this stirng!&quot;;
let strLength: number = (&lt;string&gt;someValue).length;
// any 타입의 변수의 앞에 타입을 angle-bracket으로 적어주고 대괄호로 감싸주면 string으로 컴파일된다.

// 2. as 문법
let someValue: any = &quot;this stirng too&quot;;
let strLength: number = (someValue as string).length;
// any 타입의 변수의 뒤에 &#39;as type&#39;으로 적어주고 대괄호로 감싸면 string으로 컴파일된다.</code></pre>
<p><strong>Typescript와 JSX를 함께 사용할 때는 as문법만 허용된다</strong></p>
</blockquote>
<br>

<h2 id="결론">결론</h2>
<hr>
<p>새로운 친구들이 많다. 후후  </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TIL] 타입스크립트 개념잡기 #2 - JS vs TS]]></title>
            <link>https://velog.io/@rand_guy/TIL-%ED%83%80%EC%9E%85%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EA%B0%9C%EB%85%90%EC%9E%A1%EA%B8%B0-2-JS-vs-TS</link>
            <guid>https://velog.io/@rand_guy/TIL-%ED%83%80%EC%9E%85%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EA%B0%9C%EB%85%90%EC%9E%A1%EA%B8%B0-2-JS-vs-TS</guid>
            <pubDate>Tue, 31 Aug 2021 06:25:12 GMT</pubDate>
            <description><![CDATA[<h4 id="정적-타입-검사자static-type-checker">정적 타입 검사자(Static Type Checker)</h4>
<ul>
<li>어떤 것이 오류인지와 어떤 것이 연산 되는 값에 기인하지 않음을 정하는 것</li>
<li>그래서 타입스크립트는 프로그램을 실행하기 전에 값의 종류를 기반으로 프로그램의 오류를 찾는다.</li>
</ul>
<h4 id="타입types">타입(Types)</h4>
<ul>
<li><p>Typescript는 다른 종류의 값들을 사용할 수 있는 방법이 추가된 타입이 있는 상위 집합이다.</p>
</li>
<li><blockquote>
<pre><code class="language-typescript">console.log(4 / []);  // NaN
// 이렇게 작성하면 javascript는 구문적으로 옳기 때문에 NaN을 출력한다.
console.log(4 / []); // @errors: 2363
// 하지만 typescript는 배열로 숫자를 나누는 연산이 옳지 않다 판단하여 오류를 발생한다.</code></pre>
<p>만약 javscript를 typescript로 옮기면, 코드를 어떻게 작성했는지에 따라 타입 오류를 볼 수 있따.</p>
<ul>
<li>이는 코드상의 문제 / Typescript의 지나친 보수성</li>
<li>이런 오류를 제거하기 위해서는 다양한 TypeScript 구문을 추가하는 방법을 제공한다</li>
</ul>
</blockquote>
</li>
</ul>
<h4 id="런타임-특성runtime-behavior">런타임 특성(Runtime Behavior)</h4>
<ul>
<li>TypeScript는 JavaScript 코드의 런타임 특성을 절대 변화시키지 않는다.</li>
<li>Typescript가 코드에 타입 오류가 있음을 검출해도, 같은 방식으로 실행 시키는 것을 보장한다.</li>
<li>이는 프로그램 작동을 중단시킬 수 있는 미묘한 차이를 걱정하지 않고 두 언어간의 전환을 위한 Typescript의 약속이다.</li>
</ul>
<h4 id="삭제된-타입erased-types">삭제된 타입(Erased Types)</h4>
<ul>
<li>TypeScript의 컴파일러가 코드 검사를 마치면 타입을 삭제해서 &quot;컴파일된&quot; 코드를 만든다.</li>
<li>코드가 타입스크립트의 컴파일을 거치고 나면 일반 JS코드에서 타입 정보를 확인 할 수 없다.<ul>
<li>이러한 이유는 프로그램의 특성을 변화시키지 않기 위해서 이다.</li>
</ul>
</li>
</ul>
<h2 id="👨🏻💻-자바스크립트를-안다면">👨🏻‍💻 자바스크립트를 안다면...</h2>
<hr>
<h4 id="타입-추론--types-by-inference-">타입 추론 ( Types by Inference )</h4>
<ul>
<li>Typescript는 Javscript의 작업을 개선하기 위해 내부적으로 Javascript의 작동방식을 이해하고 타입을 지정한다.</li>
</ul>
<h4 id="타입-정의하기--defining-types-">타입 정의하기 ( Defining Types )</h4>
<ul>
<li><p>Javascript의 다양한 디자인 패턴에 타입을 제공하기 힘들 경우, 명시 가능한 Javascript 언어의 확장을 지원한다.</p>
<blockquote>
<pre><code class="language-typescript"> interface User = {
   name: &quot;Hayes&quot;,
   id: 0,
 }                                        // interface로 선언하여 새로운 변수에 적용시킬 수 있다. 똑같은 모양으로 만들어야 하는듯

// --cut--

// case.1
const user: User = {            
  name: &quot;HOYO&quot;,
  id: 123,
}                                            // 이렇게 작성하면 위의 interface User가 적용된다

// case.2
const user: User = {            
  username: &quot;HOYO&quot;,
  id: 123,
}                                            // 키 값을 interface와 다르게 적용하면 `@errors: 2322`를 보여주면서 경고를 준다

</code></pre>
</blockquote>
</li>
<li><p>자세한 내용은 Interface에서 이어서</p>
</li>
</ul>
<h4 id="타입-구성--composing-types-">타입 구성 ( Composing Types )</h4>
<ul>
<li><p>객체들을 조합하여 더 크고 복잡한 객체를 만드는 방법과 유사하게 TypeScript에 타입으로 이를 수행하는 도구가 있다.</p>
<ul>
<li>대표적인 예시로는 <strong>Union</strong> 과 <strong>Generic</strong> 있다.</li>
</ul>
</li>
<li><p><strong>유니언 ( Union )</strong></p>
<blockquote>
<pre><code class="language-typescript">// 유니언은 타입이 여러 타입 중 하나일 수 있음을 선언하는 방법이다.

type modal = modal | Unmodal;
type OddNumber = 1 | 3 | 5 | 7 | 9;

// 위처럼 들어올 수 있는 값의 타입을 여러개로 지정할 수 있다.

function getLength(obj: string | string[]) {
  return obj.length;
}

// 이런 식이라면 array 또는 string을 받는 함수를 만들 수 있다.

function Array(obj: string | string[]) {
  if (typeof obj === &quot;string&quot;) {
    return [obj];
  }
}// 위 방식 처럼 `typeof x === &quot;type&quot;`를 사용하여 타입에 해당될 때를 조건으로 줄 수 있다.</code></pre>
</blockquote>
</li>
</ul>
<ul>
<li><p><strong>제네릭 ( Generic )</strong></p>
<ul>
<li><p>Typescript 제네릭 시스템은 타입에 변수를 제공하는 방법이다.</p>
<ul>
<li>const, let 대신에 type으로 변수를 선언한다. 이렇게 제네릭을 사용하는 고유 타입을 선언할 수 있다.</li>
</ul>
</li>
<li><p>EX) Array =&gt; 제네릭이 없는 배열은 어떤 것이든 포함된다. 하지만 제네릭이 있는 배열은 배열 안의 값을 설명할 수 있다.</p>
<blockquote>
<pre><code class="language-typescript">type StringArray = Array&lt;string&gt;;
type NumberArray = Array&lt;number&gt;;
type ObjectWithNameArray = Array&lt;{ name: string }&gt;;</code></pre>
</blockquote>
</li>
<li><p>자세한 내용은 제네릭에서</p>
</li>
</ul>
</li>
</ul>
<h4 id="구조적-타입-시스템--structural-type-system-">구조적 타입 시스템 ( Structural Type System )</h4>
<ul>
<li><p>Typescript의 핵심 원칙 중 하나는 <strong>타입 검사가 값이 있는 형태에 집중한다는 것</strong></p>
<ul>
<li>이는 &quot;덕 타이핑(duck typing)&quot; or &quot;구조적 타이핑&quot;이라고 불린다.</li>
</ul>
</li>
<li><p>구조적 타입 시스테엠에서 두 객체가 같은 형태를 가지면 같은 것으로 간주된다.</p>
<blockquote>
<pre><code class="language-typescript">interface Point {
  x: number;
  y: number;
}

function printPoint(p: Point) {
  console.log(`${p.x}, ${p.y}`);
}

const point = { x: 12, y: 26 };
printPoint(point); // &quot;12, 26&quot;

// 이렇게 작동되는 이유는 interface Point와 변수 point가 같은 형태를 가지고 있기 때문이다.
// 이런 형태 일치에는 일치시킬 객체의 필드의 하위 집합만 필요하다?

const poin3 = { x: 12, y: 26, z: 89 };
printPoint(point3) // &quot;12, 26&quot; =&gt; 이는 형태에 맞는 값만 출력하는 구조적 타입 시스템 덕분이다.
                                     // 만약 형태가 맞지 않으면 error가 발생한다.


// 이는 클래스에서도 동일하게 적용된다

class VirtualPint {
  x: number;
  y: number;

  constructor(x: number, y:number) {
    this.x = x;
    this.y = y;
  }
}

const newVwpoint = new VirtualPint(13, 56);
printPoint(newVwpoint); // &quot;13, 56&quot; =&gt; 자세한 내용은 클래스에서</code></pre>
</blockquote>
</li>
</ul>
<br>

<h2 id="🙆🏻♂️-결론">🙆🏻‍♂️ 결론</h2>
<hr>
<p>타입스크립트 공식문서를 보면서 공부하기 시작했다. 자바스크립트를 공부하면서 개념에 대한 이해가 코드에서도 나타는 것을 많이 느꼈다. 그렇기에 느리더라도 개념을 다지면서 나아가기 위해 공식문서를 보면서 공부합니다. 다음시간엔 핸드북을 차례대로 살펴볼 예정입니다. Yee!  </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TIL]타입스크립트 개념잡기 #1]]></title>
            <link>https://velog.io/@rand_guy/TIL%ED%83%80%EC%9E%85%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EA%B0%9C%EB%85%90%EC%9E%A1%EA%B8%B0-1</link>
            <guid>https://velog.io/@rand_guy/TIL%ED%83%80%EC%9E%85%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EA%B0%9C%EB%85%90%EC%9E%A1%EA%B8%B0-1</guid>
            <pubDate>Mon, 30 Aug 2021 12:27:58 GMT</pubDate>
            <description><![CDATA[<h1 id="👋🏻-타입스크립트-시작하기">👋🏻 타입스크립트 시작하기</h1>
<hr>
<p>자바스크립트는 웹 페이지에 사소한 상호작용을 추가하기 위한 스크립팅 언어로 시작되었다. 현재 자바스크립트는 프론트엔드와 백엔드 어플리케이션을 어우르는 언어로 성장했다. 프로그램의 크기, 범위, 및 복잡성은 기하급수적으로 커졌지만, 자바스크립트 언어의 능력은 여전하다. 자바스크립트의 독창적인 런타임 의미 체계와 언어와 프로그램 복잡성 간의 불일치는 에러를 일으키는 가장 큰 원인이 되었다.</p>
<p>특히 타입 오류, 다른 종류의 값이 예상되는 곳에 특정한 값이 사용된 경우에 타입스크립트가 사용된다. 타입스크립트의 목표는 <strong>자바스크립트 프로그램의 정적 타입 검사자이다.</strong> 코드가 실행되기 전에 실행하고(정적), 프로그램 타입이 정확한지 확인하는 도구(타입 검사)이다.</p>
<h2 id="타입스크립트를-사용하는-이유">타입스크립트를 사용하는 이유</h2>
<hr>
<ul>
<li><p><strong>IDE를 적극적으로 활용한다 (자동완성, 타입확인)</strong></p>
<ul>
<li><blockquote>
<p>IDE는 Integrated Development Environment(통합 개발 환경)이란 공통된 개발자 툴을 하나의 그래픽 사용자 인터페이스(GUI)로 결합하는 어플리케이션을 구축하기 위한 소프트웨어이다.</p>
</blockquote>
</li>
<li><p>함수를 사용 할 때, 해당 함수가 어떤 파라미터를 필요로 하는지, 어떤 값을 반환하는지 코드를 확인하지 않아도 된다.</p>
</li>
<li><p>컴포넌트 사용 시, props에 무엇을 전달해야 하는지, JSX를 작성하는 과정에서 알려준다.</p>
</li>
<li><p>컴포넌트 내부에서도 자신의 props에 어떤 값이 있는지, state에 어떤 값이 있는지 알 수 있다.</p>
<ul>
<li>리덕스와 함께 사용하면 스토어 안에 어떤 상태가 있는지 바로 조회 가능하다.</li>
</ul>
</li>
</ul>
</li>
</ul>
<ul>
<li><strong>실수방지</strong><ul>
<li>함수 컴포넌트 등의 타입 추론이 된다.</li>
<li>사소한 오타를 만들어도 코드를 실행하지 않고 IDE상에서 바로 알 수 있게 된다.</li>
<li>null / undefined인 값의 내부 값 혹은 함수를 호출에도 사전에 null 채킹하지 않으면 오류를 띄운다.</li>
</ul>
</li>
</ul>
<h2 id="타입스크립트-사용하는-방법">타입스크립트 사용하는 방법</h2>
<hr>
<ul>
<li>터미널에서 <code>npm install -g typescript</code><ul>
<li><code>tsc --init</code> 으로 필요한 옵션을 지정할 수 있다.<ul>
<li><strong>target</strong> : 컴파일된 코드가 어던 환경에서 실행될 지 정의<ul>
<li>화살표 함수 -&gt; es5 -&gt; 함수 선언문으로 만든다.</li>
</ul>
</li>
<li><strong>module</strong> : 컴파일된 코드가 어떤 모듈 시스템을 사용될 지 정의한다.</li>
<li><strong>strict</strong> : 모든 타입 체킹 옵션을 활성화 한다는 것을 의미</li>
<li><strong>esModuleInterop</strong> : common js 모듈 형태로 이루어진 파일을 es2015 모듈 형태롤 불러올 수 있다.</li>
<li><strong>outDir</strong> : 컴파일된 파일들이 저장되는 경로를 지정할 수 있다.</li>
</ul>
</li>
</ul>
</li>
</ul>
<h2 id="기본-타입">기본 타입</h2>
<hr>
<blockquote>
<pre><code class="language-typescript">let count = 0;
count += 1;
count = &#39;typescript&#39;; // 숫자였던 변수에 문자열을 할당하면 에러가 발생한다

const message: string = &#39;hello world&#39;;
// 변수를 선언할 때, 식별자 옆에 &#39;: type&#39;을 지정한다.

const done: boolean = true; // boolean 값

const number: number[] = [1,2,3]; // 숫자 배열
const message: string[] = [&#39;a&#39;,&#39;b&#39;,&#39;c&#39;]; // 문자열 배열
// 배열도 위와 같이 지정 가능하다.

message.push(1); // 문자열 배열에 숫자를 push하려고 하면 에러가 발생한다.

let mightBeUndefined: sting | undefined = undefined; 
// string 일수도 있고 undefined 일 수도 있다.
let nullableNumber : number | null = null;
// number 일수도 있고 null 일 수도 있다.

let color: &#39;red&#39; | &#39;orange&#39; | &#39;yellow&#39; = &#39;red&#39;; // 세개의 값중 하나이다.
color = &#39;yellow&#39;;
color = &#39;green&#39;; // 위에 정해진 조건에 맞지 않아 에러가 발생한다.
console.log() // &#39;green&#39; 형식은 &#39;red&#39; | &#39;orange&#39; | &#39;yellow&#39; 형식에 할당될 수 없다.

// tsc명령어를 입력해서 컴파일하려고 하면 실패한다.</code></pre>
</blockquote>
<h2 id="함수에서-타입-정의하기">함수에서 타입 정의하기</h2>
<hr>
<blockquote>
<pre><code class="language-typescript">function sum(x: number, y: number): number {
  return x + y;
}

sum(1,2);

// 여기서 sum에 포커스되면 함수의 파라미터로 필요한 값의 타입을 바로 알려준다.
// sum 함수의 가장 우측에 적용된 타입 &#39;: number&#39;는 결과물의 타입을 지정한 것이다.
// 그래서 &#39;return null&#39;과 같이 타입과 맞지 않은 값을 리턴하면 오류가 발생한다.
console.log(sum(null)) // &#39;null&#39;형식은 &#39;number&#39; 형식에 할당할 수 없다.</code></pre>
<pre><code class="language-typescript">function sumArray(numbers: number[]): number {
  return numbers.reduce((acc, current) =&gt; acc + current, 0);
}

const total = sumArray([1,2,3,4,5]);

// 이렇게 배열의 내장함수를 사용할 때에도 타입을 유추해준다.
// &#39;(parameter)의 타입이 number라는 것을 명시해준다&#39;

function returnNothing(): void {
  console.log(&#39;hl&#39;)
}

// 반환 타입을 void로 설정하면 함수에서 아무것도 반환하지 않을 수 있다.</code></pre>
</blockquote>
<hr>
<p>벨로퍼트님과 포이엠웹님, 그리고 타입스크립트 공식문서를 살펴보면서 나아갈 타입스크립트 공부의 시작입니다. 화이팅~!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TIL] Input 타입 File로 여러개 이미지 업로드와 미리보기 몇가지 예시..]]></title>
            <link>https://velog.io/@rand_guy/TIL-Input-%ED%83%80%EC%9E%85-File%EB%A1%9C-%EC%9D%B4%EB%AF%B8%EC%A7%80-%EC%97%85%EB%A1%9C%EB%93%9C%EC%99%80-%EB%AF%B8%EB%A6%AC%EB%B3%B4%EA%B8%B0</link>
            <guid>https://velog.io/@rand_guy/TIL-Input-%ED%83%80%EC%9E%85-File%EB%A1%9C-%EC%9D%B4%EB%AF%B8%EC%A7%80-%EC%97%85%EB%A1%9C%EB%93%9C%EC%99%80-%EB%AF%B8%EB%A6%AC%EB%B3%B4%EA%B8%B0</guid>
            <pubDate>Sun, 22 Aug 2021 16:28:52 GMT</pubDate>
            <description><![CDATA[<h1 id="🙆🏻♂️-이미지-파일-업로더--이미지-파일-미리보기-제작과정">🙆🏻‍♂️ 이미지 파일 업로더 &amp; 이미지 파일 미리보기 제작과정</h1>
<hr>
<h3 id="이미지를-업로드하는-방법"><strong>이미지를 업로드하는 방법</strong></h3>
<ul>
<li><p>Input 태그의 Type을 File로 하여 업로드한다.</p>
<ul>
<li><p>value = 파일 경로</p>
<ul>
<li>보안상 브라우젱서 직접 접근 X, <code>c:/fakepath/</code>르ㄹ 포함하여 숨김</li>
</ul>
</li>
<li><p>accept : 이미지 유형 지정</p>
<ul>
<li><code>Image/*</code>: png 같은 이미지 파일<ul>
<li>Image 대신 video, audio, / <code>&quot;.pdf, .doc, .csv&quot;</code>  등이 가능하다</li>
</ul>
</li>
</ul>
</li>
<li><p>Capture : 휴대폰일 시, 카메라 시작</p>
<ul>
<li>Camera, camcorder, microphone 가능</li>
</ul>
</li>
<li><p>Multiple : 여러개 이미지 등록가능</p>
</li>
<li><p>FileList: Array-like object로 File들을 가지고 있는 객체이다.</p>
<ul>
<li><p>이는 files type의 엘리먼트로 선택된 파일의 리스트에 접근할 수 있다.</p>
</li>
<li><p>드래그 앤 드랍 API 사용할 때 파일의 리스트에도 사용됨 (DataTransfer객체 참조)</p>
</li>
<li><blockquote>
<input id="fileItem" type="file">

<p>var file = document.getElementById(&#39;fileItem&#39;).files[0]</p>
<p>위 같은 방식으로 파일에 접근할 수 있다.</p>
</blockquote>
</li>
<li><p>참조하기 위해서는 <code>for of</code> 혹은 <code>Array.from()</code> 로 변환참조 가능</p>
</li>
</ul>
</li>
<li><p>FIle : 읽기 전용</p>
<ul>
<li>가지고 있는 속성<ul>
<li>Name : 파일 이름</li>
<li>Size : 파일 크기</li>
<li>Type : MIME 유형</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="input-file-타입-실행-과정"><strong>input File 타입 실행 과정</strong></h3>
<ul>
<li><p>로컬에서 파일을 선택한 파일은 File로 정의 / FilesList에 저장됨</p>
</li>
<li><p>파일을 선택하면 input, change EventHandler 발생, 선택된 파일은 HTMLInputElement.files에 저장</p>
<ul>
<li>onChnage는 포커스를 잃을 때 발생</li>
<li>onInput은 값이 변경된 직후 발생<ul>
<li>순서상 onInput이 먼저~</li>
</ul>
</li>
</ul>
</li>
<li><p><strong>업로드한 이미지를 미리보기 위해서는 FileReader 객체를 사용한다.</strong></p>
<ul>
<li>웹 어플리케이션이 비동기적으로 데이터를 읽기 위하여 읽을 파일을 가리키는 File/Blob 객체를 이용해 파일 내용을 읽고 사용자의 컴퓨터에 저장한다</li>
</ul>
</li>
</ul>
<pre><code class="language-javascript">// state
state: {
  // 업로드한 파일 객체를 저장할 state
   detailImageFile: null,
  // 업로드한 파일 객체의 이미지 url을 저장할 state
   detailImageUrl: null,
}


// set file reader function : FileReader가 onload되면 FileReader의 result를 반환
   // setImageFromFile은 file, setImageUrl을 매개변수로 받는다
const setImageFromFile = ({ file, setImageUrl }) =&gt; {
  // reader에 빈 FileReader 객체를 선언한다.
   let reader = new FileReader();
  // FilerReader.onload : load 이벤트의 핸들로.
  // 해당 이벤트는 읽기 동작이 성공적으로 완료되었을 때마다 발생
  // 비동기여서 원하는 동작을 위해 callback으로 실행해야 한다.
      // 읽기 동장이 성공적으로 완료되면 함수를 실행한다
   reader.onload = function () {
     // setImageUrl 함수는 result키에 reader(FileReader).result를 value 값으로 넣는다
     // reader.result = 파일의 내용을 반환한다.
      setImageUrl({ result: reader.result });
   };

  // FileReader의 readAsDataURL메서드 파일 내용 반환이 완료되면 그 파일의 URL을 가져온다
   reader.readAsDataURL(file);
};

  // 위 함수는 매개변수로 전달되는 file의 url을 받아오고 setImageUrl은 result 키 값에 reader.result를 준다

// render JSX
const fileInputArea = 
    &lt;&gt;
      &lt;input
          type=&quot;file&quot;
          id=&quot;detail_image&quot;
          accept=&quot;image/*&quot;
                  // 변화가 발생하면 callback 함수가 실행된다
                  // target(input.file)의 files객체 도달
                  // 이 사람은 바로 const { files } = event.target 을 이렇게 해버린 것이다
                      // {target: {files}}
          onChange={({ target: { files } }) =&gt; {
            // 만약 filesr가 있다면 (files의 method는 length 뿐)
              if (files.length) {
                // 위에서 정의한 SetImageFromFile 함수에서 구조분해를 해서 보냄
                    // File에 files[0]를
                       // setImageUrl에 매개변수 result도 구조분해 해버리네.. 
                             // 함수 실행하면 setState({detailImageFile: files[0], detailImageUrl: result})한다...
                  setImageFromFile({
                      file: files[0],
                      setImageUrl: ({ result }) =&gt; setState({detailImageFile: files[0], detailImageUrl: result});
              }
          }}
      /&gt;
      //detailImageFile이 있다면
        // src에 변경된 스테이트 값을 넣는다
      {detailImageFile &amp;&amp; (
        &lt;div className=&quot;image_area&quot;&gt;
          &lt;img src={detailImageUrl} alt={detailImageFile.name} /&gt;
        &lt;/div&gt;
      )}
    &lt;/&gt;</code></pre>
<ul>
<li>내가 원했던 기능을 만든 사람의 코드</li>
</ul>
<pre><code class="language-javascript">  // useState 빈배열을 만듬 &#39;선택된 파일들&#39;
    const [selectedFiles, setSelectedFiles] = useState([]);

    // 이벤트를 매개변수로 받는 함수 정의
  const handleImageChange = e =&gt; {
    // e.target.files가 있는지 찍어봄
    console.log(e.target.files);
    // 만약 이벤트 타겟의 파일들이 있다면
    if (e.target.files) {
      // filesArry 변수를 선언한다. 그 변수에는
      // e.target.files를 배열로 만듬
          // Array.from = 유사배열 / 반복가능 객체를 얕게 복사해 새로운 Array객체로 만드는 것이다
        // 그래서 맵을 돌려서 각 배열의 파일이 포함된 배열을 리턴한다.
          // CreateObjectURL은 주어진 객체를 가리키는 URL을 DOMString으로 반환
              // 해당 URL은 자신을 생성한 창의 document가 사라지면 함께 무효화
               // 객체 URL을 해제하기 위해서 revokeObjectURL()을 호출
      const filesArray = Array.from(e.target.files).map(file =&gt;
        URL.createObjectURL(file)
      );
            // filesArray에 맵으로 돌린 URL들이 잘 담겨있는지 확인
      console.log(&#39;filesArray: &#39;, filesArray);

      // setSelectedFiles(usestate)로 스테이트 업데이트
      // prevImages로 전 이미지들을 얕은 복사해서 가져오고 그 배열에 새롭게 추가된 filesArray를 추가
      setSelectedFiles(prevImages =&gt; prevImages.concat(filesArray));
      // 그리고 다시한번 Array.from(e.target.files).map을 해서 file 객체의 URL을 해제한다.
        // 이건 계속 메모리 누수가 발생하는걸 없애기 위해서 하는 것이다.
        // 만약 revokeObjectURL을 하지않으면 해당 파일의 URL을 브라우저가 계속 저장한다.
        // 하지만 위에서 State에 파일을 concat해줬기 때문에 더이상 브라우저에서 해당 URL을 지니지 않아도 된다.
      Array.from(e.target.files).map(
        file =&gt; URL.revokeObjectURL(file) 
      );
    }
  };

    // renderPhotos라는 함수를 선언한다.
  // 이 함수는 나중에 이미지가 렌더되는 곳에서 state를 받아서 맵으로 돌려서 보여주는 기능을 한다.
  const renderPhotos = source =&gt; {
    console.log(&#39;source: &#39;, source);
    return source.map(photo =&gt; {
      return &lt;PreviewImage src={photo} alt=&quot;&quot; key={photo} /&gt;;
    });
  };
  ...
    &lt;input onchange={handleImageChange}&gt;
  ...
  {renderPhotos(selectedFiles)}


</code></pre>
<ul>
<li>업로드한 이미지는 FormData 형태로 S3에 업로드한다<ul>
<li>Key: image</li>
<li>Value: File Addres</li>
</ul>
</li>
</ul>
<pre><code class="language-javascript">1차 시도
const onImgChange = async(event: any) =&gt; {
  setLogoLoading(true);
  const formData = new FormData();
  formData.append(&#39;image&#39;, event.target.files[0]);
  const response = await apiClient.post(&#39;/brand/logo_image&#39;, formData);
  // reponse.data.location이 업로드한 파일의 url
  setLogoLoading(false);
}

2차 시도
const setFile = e =&gt; {
  const formData = new FormData();
  formData.append(&#39;image&#39;, ImageForUpload);
  axios.post(&#39;public/data/SellerUpload.json&#39;, formData);
};</code></pre>
<ul>
<li><p>Delete 버튼 만들기</p>
<ul>
<li>Delete 버튼을 클릭하면 버튼도 사라지고 이미지도 사라지고 데이터도 사라져야한다...</li>
<li>이 모든걸 충족하기 위해선 &lt; button, image, data &gt;를 한번에 다뤄야한다.<ul>
<li>filter함수를 통해서 조건에 맞지 않는 배열을 다시 전달하고 그 배열이 데이터로 전달되어야 한다</li>
</ul>
</li>
</ul>
</li>
<li><p>example</p>
<blockquote>
<pre><code class="language-javascript">const App = () =&gt; {
// 새로운 배열 스테이트를 만든다
const [pics, setPics] = useState([]);
//  버튼을 클릭 하면 id 값으로 특정하여 가져오게 했다.
const removeImage = (id) =&gt; {
// 새롭게 스테이트를 변경한다.
// 매개변수를 주고 매개변수를 필터로 돌려서 아이템을 리턴하는데 id가 맞으면 제외한다.
setPics((oldState) =&gt; oldState.filter((item) =&gt; item.id !== id));
};

useEffect(() =&gt; {
// 기존에 이미지를 가져오는 함수
setPics(allImages);
}, []);
return (
&lt;div className=&quot;App&quot;&gt;
   // 맵함수로 데이터 있는데로 돌린다
{pics.map((pic) =&gt; {
  return (
    &lt;div style={{ marginBottom: &quot;100px&quot; }}&gt;
        // 이미지 데이터의 아이디를 보여주고
      {pic.id}
      &lt;img
        src={pic.imgUrl}
        width=&quot;100px&quot;
        height=&quot;100px&quot;
        alt=&quot;placeholder grey 100px&quot;
      /&gt;
      // 버튼을 클릭하면 비동기로 removeImage(pic.id)가 전달되어 작동
      &lt;button onClick={() =&gt; removeImage(pic.id)}&gt;X&lt;/button&gt;
    &lt;/div&gt;
  );
})}
&lt;/div&gt;
);
};

export default App;</code></pre>
</blockquote>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TIL] React 함수형 컴포넌트의 useEffect와 친해지기]]></title>
            <link>https://velog.io/@rand_guy/TIL-React-%ED%95%A8%EC%88%98%ED%98%95-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8%EC%9D%98-useEffect%EC%99%80-%EC%B9%9C%ED%95%B4%EC%A7%80%EA%B8%B0</link>
            <guid>https://velog.io/@rand_guy/TIL-React-%ED%95%A8%EC%88%98%ED%98%95-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8%EC%9D%98-useEffect%EC%99%80-%EC%B9%9C%ED%95%B4%EC%A7%80%EA%B8%B0</guid>
            <pubDate>Sun, 22 Aug 2021 15:01:18 GMT</pubDate>
            <description><![CDATA[<p><span style="color:lightgrey">오늘은 useEffect에 대한 공부를 해보려고 합니다.
useState는 계속 사용하게 되니 친해지는 감도 있고 구조와 원리도 익숙해지고 있습니다.
하지만 useEffect는 life-cycle과 연관되어 있다보니 자주 다루지 않기도 하기 때문에 아직 어렵습니다.</span></p>
<hr>
<h2 id="effect-hook">Effect Hook</h2>
<ul>
<li>Effect Hook은 React Class의 componentDidMount / componentDidUpdate / componentWillUnmount와 같은 목적으로 제공되는 하나의 API라고 생각할 수 있다.</li>
<li>사용할 때에는 <code>useEffect(() =&gt; {}, [count])</code>처럼 사용한다.</li>
<li>의존성 배열을 받는 이유?<ul>
<li><strong>React hook 함수들은 불필요한 작업을 줄이기 위해서 두 번째 인자로, 첫 번째 함수가 의존해야하는 배열을 받는다.</strong></li>
<li>의존성 배열을 사용할 때, 주의깊게 사용해야 한다. useEffect는 무한루프를 발생시킬 수 있다.</li>
</ul>
</li>
</ul>
<h2 id="무한-루프">무한 루프?</h2>
<ul>
<li>무한 루프란 useEffect안에서 state를 변경하는 함수를 실행하게 되면 시점이 정해지지 않은 setState는 계속해서 state를 변경시킨다. 그러므로 멈추지않고 함수를 실행하게 된다.</li>
<li>이러한 무한루프를 방지하기 위해서는 state를 변경하는 함수를 포함할 때, <ul>
<li><strong>반드시 해당 state를 의존성배열에 넣어줘야 한다.</strong></li>
</ul>
</li>
</ul>
<h2 id="effect-hook은-어떻게-작동하는가">Effect Hook은 어떻게 작동하는가?</h2>
<blockquote>
<pre><code class="language-javascript">**첫번쨰**
useEffect(() =&gt; {
  console.log(CDM + CDU)
}) // 의존성 배열이 없음으로 매 render 마다 useEffect안에 있는 함수가 실행된다
</code></pre>
</blockquote>
<p><strong>두번째</strong>
useEffect(() =&gt; {
  console.log(CDM)
  return () =&gt; console.log(CWU)
}, []) // 두번째 인자인 의존성 배열이 비어있음으로 CDM때 한번 실행되고 이후로는 실행되지 않음
       // 하지만 위처럼 return 하여 콜백함수로 실행하면 CWU일때, 실행된다</p>
<blockquote>
</blockquote>
<p><strong>세번째</strong>
useEffect(() =&gt; {
  console.log(CDM)
  console.log(CDU) + shouldComponentUpdate
  return () =&gt; console.log(clean-up) 
}, [state]) // 의존성배열에 state가 들어오면 CDM때 실행되고
             // 컴포넌트가 업데이트될 때도 실행된다. 추가적으로 state에 변경이 감지될 때도 실행된다.
            // callback함수를 만들면 closure에 의해 과거의 값을 기억하는 함수가 실행된다. 
<strong>데이터 fetch 할 때</strong>
useEffect(() =&gt; {
  fetch(url)
}, [state]) // 의존성 배열에 state가 있으면 fetch해온 data가 state가 변경될 때마다 실행된다
             // 그렇다면 받아오는 데이터 값이 변경되어야 할 때, 사용하면 좋다. (filter, search)</p>
<p>```</p>
<h2 id="여기서-다시-살펴보는-react-life-cycle">여기서 다시 살펴보는 React Life-Cycle!!</h2>
<p><img src="https://cdn.filestackcontent.com/ApNH7030SAG1wAycdj3H" alt=""></p>
<ul>
<li>Life-cycle을 복습함으로써 useEffect가 작동하는 방식과 과정을 다시한번 이해해보자.</li>
</ul>
<h2 id="clean-up-함수">Clean-Up 함수</h2>
<ul>
<li>useEffect의 추가적인 기능 중에는 Clean-Up 함수가 잇다.</li>
<li>위에서 설명했듯이 의존성 배열에 state가 있을 때,  콜백함수로 함수를 실행하게 되면 업데이트 되기 이전의 값을 가진 함수를 볼 수 있다.</li>
<li>callback 함수로 실행된 값은 setState에 의해 변하지 않고 그대로 존재한다.<ul>
<li>이를 통해서 이펙트가 호출되기 전과 컴포넌트가 언마운트될 때 호출되면서 이전 이펙트로 인한 결과를 정리한다.</li>
<li>이는 일반적으로는 사용되지 않지만 effect가 실행될 시점에 렌더가 완료되어 있음을 보장할 수 있다.</li>
<li><strong>눈으로 확인 하긴 어렵지만 확실한 마무리가 필요한 작업을 수행할 때 활용한다.</strong></li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Project#1] 코드로 살펴보는 첫 React 클론 프로젝트]]></title>
            <link>https://velog.io/@rand_guy/Project1-3</link>
            <guid>https://velog.io/@rand_guy/Project1-3</guid>
            <pubDate>Fri, 20 Aug 2021 01:50:04 GMT</pubDate>
            <description><![CDATA[<p><span style="color: grey">위코드에서 2주동안 프론트엔드 3명, 백엔드 2명, 총 5인으로 진행한 프로젝트를 &#39;진행 / 서비스  / 코드&#39;라는 세가지 주제로 블로그 글을 작성하려고 합니다. 이번 글의 주제는 <strong>코드</strong>입니다. 2주의 시간을 후회없이 보낼 수 있었습니다. 즐거운 글이 되길 바랍니다.</span>
<br></p>
<hr>
<h1 id="🙇🏻♂️-캐러셀-기능">🙇🏻‍♂️ 캐러셀 기능</h1>
<p><img src="https://images.velog.io/images/rand_guy/post/416b15b0-3f82-4ed1-83b1-67a851592241/carusel.gif" alt=""><img src="https://images.velog.io/images/rand_guy/post/b5319e79-b0df-4d58-b742-d45deeab94d1/image.png" alt=""></p>
<h3 id="🤷🏻♂️-코드-설명">🤷🏻‍♂️ 코드 설명</h3>
<p>나는 캐러셀을 만들기 위해 margin-left를 사용하여 이미지가 이동하도록 만들었다. 
하지만 이미지를 이동시키는 버튼을 데이터의 길이에 맞춰 사라지게 만들고 싶었다.
그래서 rightEnd라는 변수를 선언하여 받아오는 배열의 길이에 맞춰 디스플레이가 사라지게 만들었다.</p>
<h3 id="🤷🏻♂️-문제">🤷🏻‍♂️ 문제</h3>
<p>마지막 이미지가 끝에 위치했을 때, 버튼을 사라지게 하고 싶었다. 
하지만 이미지가 처음 위치에 도착해야 버튼이 사라졌다.
큰 문제는 아니었다. <strong>화면에 나타나는 이미지들의 개수를 곱해서 반대방향으로 더해서 해결했다.</strong></p>
<h3 id="🤷🏻♂️-리팩토링">🤷🏻‍♂️ 리팩토링</h3>
<p>ref에 대해 조금 알게된 지금 생각해보니, 일일이 이미지의 width를 찾아서 손수 작성할 필요가 없다.
<code>ref.current.clientWidth</code>를 사용하여 자동으로 변경될 수 있도록 할 수 있다.</p>
<p>마찬가지로 마지막 이미지가 마지막에 도달할 하게 만드는 방법도
<code>ref.current.clientWidth * number of images on viewport</code> 하면 자동화 할 수 있다.</p>
<br>

<hr>
<h1 id="🙇🏻♂️-그래프-기능">🙇🏻‍♂️ 그래프 기능</h1>
<p><img src="https://images.velog.io/images/rand_guy/post/20a9434a-efe4-45b6-83a2-d1dfdff56608/image.png" alt=""><img src="https://images.velog.io/images/rand_guy/post/be928b57-dbbf-4cf3-81ff-0241379e4f83/image.png" alt=""></p>
<h3 id="🤷🏻♂️-코드-설명-1">🤷🏻‍♂️ 코드 설명</h3>
<p>내게 요구된 상황은 백엔드에 쌓여있는 카페에 대한 별점의 값을 받아서 가장 높은 별점을 기준으로 높낮이가 다른 그래프를 만들어야 했다. reduce함수를 통해 최대 값을 찾는 계산기를 만들어서 데이터 값들 중 가장 큰 값을 찾을 수 있었다. 찾은 최대 값을 그래프의 최대높이인 88px를 기준으로 나머지 값의 높이를 찾을 수 있었다. 그리고 가장 높은 값인 88px의 height를 가진 그래프에 색상을 변경해주는 함수를 만들었다.</p>
<h3 id="🤷🏻♂️-문제-1">🤷🏻‍♂️ 문제</h3>
<p>나에게 문제가 되었던 점은 그래프를 만들어내는 과정에 있어서 반복되는 코드가 너무 많다는 점이었다.
끝까지 해결하고 싶었으나 조건을 어떻게 주어야 할지 고민이 되고 해야할 기능이 많아 지나치게 되었다.</p>
<h3 id="🤷🏻♂️-리팩토링-1">🤷🏻‍♂️ 리팩토링</h3>
<p>map과 children에 대해 전 보다 더 알게 된 지금, 같은 코드를 반복하지 않고 짧게 만들 수 있을 것 같다. 2차 프로젝트가 끝나면 리팩토링을 진행하겠다.</p>
<br>

<hr>
<h1 id="🙇🏻♂️-별점평가-기능">🙇🏻‍♂️ 별점평가 기능</h1>
<p><img src="https://images.velog.io/images/rand_guy/post/401f26da-7a4e-4a67-ada8-52e590f0c53a/ezgif.com-video-to-gif-2.gif" alt=""><img src="https://images.velog.io/images/rand_guy/post/3d702465-eea4-4483-a835-9d32b6d008b6/image.png" alt=""></p>
<h3 id="🤷🏻♂️-코드-설명-2">🤷🏻‍♂️ 코드 설명</h3>
<p>마우스의 움직임에 따라 평점의 색상이 변경되어야 했기에, 마우스 이벤트를 사용하기 위해서는 각 브라우저 고유의 이벤트(nativeEvent)와 리액트에서 모든 브라우저에 통용되는 <a href="https://www.google.com/url?sa=t&amp;rct=j&amp;q=&amp;esrc=s&amp;source=web&amp;cd=&amp;cad=rja&amp;uact=8&amp;ved=2ahUKEwizwKvX_MTyAhVBRd4KHY-tDagQFnoECAgQAQ&amp;url=https%3A%2F%2Fko.reactjs.org%2Fdocs%2Fevents.html&amp;usg=AOvVaw1ZsJUR-8qoGa3RA_rRpkhh">합성이벤트(synthetic Event)</a>를 알고 사용해야 했다. 그리하여 별에는 offsetX를 주어 해당 노드의 별점의 가로 길이를 기준으로 부모 노드(<a href="https://velog.io/@edie_ko/JavaScript-event-target%EA%B3%BC-currentTarget%EC%9D%98-%EC%B0%A8%EC%9D%B4%EC%A0%90">currentTarget</a>)의 <a href="https://ohgyun.com/571">offsetWidth</a>에 비교하여 별점의 값을 변화하게 했다. 그리고 별의 색상을 변경 시키기 위해, 1 ~ 5까지 기준 값을 주어서, 기준 값에서 state 값을 뺀 값이 0.5면 반 별을 보여주고, 같거나 클 경우에는 노란별을 조건부 연산자로 나타냈다.</p>
<h3 id="🤷🏻♂️-문제-2">🤷🏻‍♂️ 문제</h3>
<p>나를 가장 애쓰게 만든 기능이지 아니었을까 싶다. 처음에는 이 기능을 만들기위해 왓챠피디아 사이트를 살펴보면서 어떻게하면 왓챠피디아 처럼 작동하게 할 수 있을까 많은 고민을 했다. 하지만 일단 가장 중점을 두려고 했던 부분은 세가지였다. 별점 위를 지나갈 때 색상이 지나가는 것, 별이 반개씩 보이는 것 그리고 클릭 시 0.5 ~ 5 점의 값이 전달되어야 한다는 것이었다. 이 문제를 해결하기 위해서 로직을 생각해보려고 노력했다. 특히 왓챠피디아 사이트를 조사하면서 느낀 노란 별 컨테이너의 크기를 마우스에 따라 조절하는 로직을 구현하려고 노력했다.</p>
<blockquote>
<p>별점 기능 만들기</p>
</blockquote>
<p>로직 1번</p>
<blockquote>
</blockquote>
<ol>
<li>빈 별(5개)을 map 돌려서 만든다</li>
<li>별 5개의 각각의 인덱스와, 사용자가 클릭/호버함으로써 생성된 rating값 (별점 값)을 비교해 조건부 렌더링(색칠)함.<ol>
<li>내가 3번째 별인데, 들어온 rating 값이 나보다 크거나 같으면 나는 풀 별이 되어야 한다</li>
<li>내가 3번째 별인데, 들어온 rating 값이 나보다 0.5점이 작으면(2.5) 나는 반 별이 되어야 한다<blockquote>
</blockquote>
로직 2번<blockquote>
</blockquote>
</li>
</ol>
</li>
<li>다섯개의 이미지 태그(빈별)를 만든다</li>
<li>추가로 다섯개의 이미지 태그(찬별)를 만든다<ol>
<li>찬별을 감싸는 태그를 만드다<ol>
<li>컨테이너는 absolute로 똑같은 위치에 지정</li>
</ol>
</li>
</ol>
</li>
<li>찬별의 컨테이너를 마우스가 호버할 때
<a href="https://hianna.tistory.com/493">1. 호버하는 위치 값을 구한다 (e.screenX)</a><ol>
<li>호버하는 위치 값에 따라서 컨테이너의 width가 변경된다 (setState)</li>
</ol>
</li>
<li>호버하는 곳에서 클릭하면 <ol>
<li>호버하는 곳에 할당된 값을 전달한다 (state)<ol>
<li>범위를 지정하여 범위마다 onClick을 지정한다.</li>
</ol>
</li>
</ol>
</li>
</ol>
<h4 id="첫번째-실패">첫번째 실패</h4>
<p>하지만 하루를 꼬박 노력한 나의 결과는 실패로 돌아갔다. 첫째는 마우스의 위치에 따라 별의 색상이 변경되어야 하는데, 색상은 변경되지만 전의 별들이 예전 색으로 돌아가게 되었다. 결국 이 문제를 해결하지 못하고 다른 방법을 찾아 나서야 했다.</p>
<h4 id="두번째-실패">두번째 실패</h4>
<p>다음 방법은 왓챠피디아 처럼, 컨테이너의 크기를 조절하려고 했다. 하지만 마우스의 가로축 움직임에 따라 계속 색상이 변경되는 것이 아니라, 0.5 단위로 색상을 유지시키는 것에 실패했다.</p>
<h4 id="세번째-성공">세번째 성공</h4>
<p>실패를 거듭하고 있을 때, 구글링을 하던 중, <a href="https://velog.io/@1703979/YPP-2">이분이 작성하신 블로그를 통해 별점을 구현한 방법을 보게 되었다.</a> 해당 블로그 글을 보면서 hover에 값을 주는 것, 합성 이벤트를 이용하여 0.5 단위로 색상을 변경하는 코드를 배울 수 있었다. 이를 통해서 두번의 실패를 겪었던 문제를 해결하고, 클릭했을 때, 부모 컴포넌트에 함수를 이용하여 전달하고 이를 POST하여 백엔드 데이터에 접근 할 수 있었다. </p>
<h3 id="🤷🏻♂️-리팩토링-2">🤷🏻‍♂️ 리팩토링</h3>
<p>이번 프로젝트에 있어서 가장 고난이 되고 어려운 과정이었다. 스스로 해냈다는 마음보다는 다른 사람의 코드를 통해 별점을 구현한 것 같아서 아쉬운 마음이 많이 들었다. 그리고 별점을 구현하기 위해서 열심히 작성하 코드들을 따로 보관하지 않아서 아쉽다. 이를 통해, 열심히 작성한 코드들을 따로 저장해서 관리하는 습관을 드릴 수 있을 것 같다. 또한 실패했던 두번째 방법으로 리팩토링을 진행해보고 싶다. 합성이벤트와 별점을 계산하는 방법을 알게되었기에, 0.5단위로 색상을 유지시키는 문제점을 해결할 수 있을 것이다.</p>
<br>

<hr>
<h1 id="🙇🏻♂️-메뉴-컴포넌트-재활용">🙇🏻‍♂️ 메뉴 컴포넌트 재활용</h1>
<p><img src="https://images.velog.io/images/rand_guy/post/3da02527-5590-4db1-ab65-2b4e7f56378a/%EC%9E%AC%ED%99%9C%EC%9A%A91.png" alt=""><img src="https://images.velog.io/images/rand_guy/post/ed85cdbd-5e18-4bc9-aee6-1ddc7f026cb7/%EC%9E%AC%ED%99%9C%EC%9A%A92.png" alt=""></p>
<h3 id="🤷🏻♂️-코드-설명-3">🤷🏻‍♂️ 코드 설명</h3>
<p>children을 사용하여 다른 데이터를     받아오는 컴포넌트를 재활용 했다.</p>
<h3 id="🤷🏻♂️-과정">🤷🏻‍♂️ 과정</h3>
<p>처음에 문제가 되었던 것은 다른 데이터를 받아와야 한다는 것이었다. 예제나 구글링을 통해서는 컴포넌트를 재활용하여 그 안에 직접 데이터를 삽입하는 과정이 있었다. 그렇기에 어떻게하면 하나의 컴포넌트로 다른 데이터를 표현할 수 있을까 고민했다. 결국 다른 값을 가진 같은 키값을 프롭스로 전달하여 각각 위치에 있는 같은 컴포넌트에 변화를 줄 수 있다고 생각했고, 이는 생각처럼 이뤄져서 굉장히 기뻤다.</p>
<br>

<hr>
<h1 id="🙇🏻♂️-필터-기능">🙇🏻‍♂️ 필터 기능</h1>
<p><img src="https://images.velog.io/images/rand_guy/post/c2d3da86-478a-466a-9d4b-7607fcc13568/ezgif.com-video-to-gif-3.gif" alt=""><img src="https://images.velog.io/images/rand_guy/post/ecda3c3f-36fe-4b3c-a6b9-919188a0ab50/%EB%B8%94%EB%A1%9C%EA%B7%B8_%ED%95%84%ED%84%B0%EC%BD%94%EB%93%9C.png" alt=""><img src="https://images.velog.io/images/rand_guy/post/0fbcd376-d076-46cc-b103-eded733fa1cf/%EB%B8%94%EB%A1%9C%EA%B7%B8_%ED%95%84%ED%84%B0%EC%BD%94%EB%93%9C2.png" alt=""></p>
<h3 id="🤷🏻♂️-코드-설명-4">🤷🏻‍♂️ 코드 설명</h3>
<p>Query Parameter와 모달창, 그리고 비동기 함수를 사용하여 필터기능을 구현했다.</p>
<h3 id="🤷🏻♂️-문제-3">🤷🏻‍♂️ 문제</h3>
<p>가장 큰 문제가 되었던 것은 각각 다른 값이 주어진 필터를 눌러도 계속해서 하나의 데이터만 변경이 되었다. 무슨 이유인지 찾지 못해 어려움을 겪었다. 이러한 문제가 되었던 이유는 하나의 기능으로 각각의 데이터를 변경시켜주지 못했기 때문이다. 그래서 별점과 좋아요 데이터를 다루는 각각의 기능을 만들어서 문제를 해결했다. </p>
<p>그리고 필터가 두번 클릭해야 작동하는 문제가 있었다. 이는 onClcik시에 작동하는 shootRate함수와 그 안에서 부모로 스테이트를 전달하는 함수의 비동기 문제로 인해 발생했다. 각 함수들을 콜백함수로 만들어 비동기 문제를 해결했다.</p>
<h3 id="🤷🏻♂️-리팩토링-3">🤷🏻‍♂️ 리팩토링</h3>
<p>아직까지 해당 코드를 하나로 만들지 못했다. 반복되는 코드들이 많아서 충분히 리팩토링을 통해서 줄일 수 있을 것 같다. 2차 프로젝트가 끝나면 꼭 해보자.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Project#1] 서비스로 살펴보는 첫 React 클론 프로젝트]]></title>
            <link>https://velog.io/@rand_guy/Project1-service</link>
            <guid>https://velog.io/@rand_guy/Project1-service</guid>
            <pubDate>Sun, 15 Aug 2021 18:24:14 GMT</pubDate>
            <description><![CDATA[<p><span style="color: grey">위코드에서 2주동안 프론트엔드 3명, 백엔드 2명, 총 5인으로 진행한 프로젝트를 &#39;진행 / 서비스  / 코드&#39;라는 세가지 주제로 블로그 글을 작성하려고 합니다. 이번 글의 주제는 <strong>서비스</strong>입니다. 2주의 시간을 후회없이 보낼 수 있었습니다. 즐거운 글이 되길 바랍니다.</span>
<br></p>
<hr>
<h1 id="🙇🏻♂️-영화-소개-카페-소개">🙇🏻‍♂️ 영화 소개? 카페 소개!</h1>
<p><img src="https://images.velog.io/images/rand_guy/post/97d65e42-f448-4a31-931d-535248b8fc21/image.png" alt="">
왓챠피디아는 영화를 소개하고 평가하는 사이트이다. 여기서 컨텐츠인 &#39;영화&#39;를 다른 주제로 바꾸면 어떤가?
식당, 카페, 책, 드라마, 음악, 등등 사람들이 즐기는 모든 것들이 평가할 수 있는 대상이 된다. </p>
<p><strong>그렇다면 왜 카페였나?</strong></p>
<hr>
<h1 id="🙇🏻♂️-어디-괜찮은-카페-없나">🙇🏻‍♂️ 어디 괜찮은 카페 없나?</h1>
<p><img src="https://media.giphy.com/media/kPtv3UIPrv36cjxqLs/giphy.gif" alt=""></p>
<p><strong>첫 번째로, 내가 카페를 좋아한다.</strong> 커피를 좋아하고 각각의 개성이 들어난 공간을 향유하는 경험이 좋다. 하지만 나만 좋아한다는 이유로 할 수 있는 것이 기획은 아니다. 많은 사람들이 공통적으로 느끼고 공감하는 것을 서비스로 제공하는 것이 좋은 기획이라고 생각했다.</p>
<p><strong>두 번째로, 사람들이 카페를 좋아한다.</strong> 서울에는 카페가 굉장히 많다. 뉴스래빗이 조사한 결과에 따르면, 전국 카페 개수의 22%,  1만8535곳이 서울에 있다는 것이다. 이렇게 카페가 많기에 좋고 이쁜 카페를 소개하는 소셜미디어, 매거진 등은 있다. 하지만 카페를 소개하는 것은 하나의 컨텐츠일 뿐, 서비스의 핵심이 아니었다.  </p>
<p>그래서 우리는 오직 카페만을 소개하고 평가를 내릴 수 있는 사이트를 만들어 보는게 어떨까 고민하게 되었다. 바로 사용 가능한 사이트는 아니지만 실제로 이용자의 입장에서 고민하면서 만들었다. </p>
<hr>
<h1 id="👨🏻💻-메인페이지">👨🏻‍💻 메인페이지</h1>
<p><img src="https://images.velog.io/images/rand_guy/post/b7560a1a-be20-4c05-8758-1f0613fb04e2/%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%202021-08-16%20%EC%98%A4%EC%A0%84%202.44.35.png" alt="">
커피보다는 카페의 분위기를 보여줄 수 있는 인테리어 사진을 메인으로 설정했다. 또한 border-radius도 보다 부드러운 느낌을 주기위해 더 강하게 주었다. 기본 틀은 기존의 왓챠피디아의 레이아웃과 리스트을 따라서 만들었다. 심플하면서도 핵심정보만 제공하는 왓챠피디아의 디자인이 굉장히 효과적이고 멋있다고 느꼈다. </p>
<hr>
<h1 id="👨🏻💻-상세페이지">👨🏻‍💻 상세페이지</h1>
<p><img src="https://images.velog.io/images/rand_guy/post/491619bf-2edb-4bf7-bd24-41680d9b3436/image.png" alt=""></p>
<p>상세페이지 역시 왓챠피디아의 레이아웃을 동일하게 가져왔다. 메인 사진이었던 인테리어 사진을 배경화면으로 변경했다. 그리고 메인 포스터의 자리에는 시그니쳐 메뉴를 배치했다. 이를 통해 해당 카페가 지향하는 분위기와 맛을 처음부터 전달할 수 있도록 만들어봤다. 좋아요 기능과 별점 기능을 통해 해당 카페에 대한 자신의 의견을 사람들과 나눌 수 있다는 점이 사이트를 더욱 매력적으로 만든다고 생각했다. </p>
<p><img src="https://images.velog.io/images/rand_guy/post/68fcd1aa-0459-47bd-a0bb-1ade2a21567e/image.png" alt=""></p>
<p><strong>기존 왓챠피디아에서 영화의 정보, 캐스트, 예고편, 등을 볼수 있는 부분을 수정하여 위와 같이 변경했다.</strong></p>
<p>카페의 정보를 먼저 간략하게 보여주고 더보기를 통해 카페에 대해 자세히 알 수 있는 내용을 볼 수 있다. 카페에서 가장 중요한 요소인 커피와 다른 메뉴들을 보여줄 수 있는 사진들을 캐러셀로 제작했다. 추가로 인테리어 사진을 클릭하면 큰 모달창으로 볼 수 있도록 만들었다. 이를 통해서 유저가 카페의 정보, 분위기를 사진을 통해 최대한 경험할 수 있도록 만들었다.</p>
<p><img src="https://images.velog.io/images/rand_guy/post/5ac87328-8990-421c-9f06-873f3c306840/image.png" alt=""></p>
<p><img src="https://images.velog.io/images/rand_guy/post/750b352d-4846-4812-ae3d-5fb5e51e7715/image.png" alt=""></p>
<p>왓챠피디아에서는 영화에 대한 평가를 보여줬던 그래프와 리뷰를 카페에 대한 자료로 만들었다.
메인 색상을 커피색과 비슷한 브라운계열의 색상으로 하여 카페를 다루는 사이트라는 걸 다시 한번 기억할 수 있도록 했다. </p>
<p><img src="https://images.velog.io/images/rand_guy/post/34112232-5596-48a4-9734-8aab93f0f904/image.png" alt="">
현재 보고있는 카페와 같은 지역에 있는 카페들을 추천하는 섹션을 만들었다. 
방문하려는 카페가 문을 닫았을 때, 자리가 없을 때, 주변의 카페를 찾아 갈 수 있도록 만들어 보았다.</p>
<p><img src="https://images.velog.io/images/rand_guy/post/ac39e651-6b81-4607-ae5d-affa4c609083/image.png" alt=""></p>
<p>회원가입을 하고 로그인을 하면 평점, 좋아요, 코멘트 기능을 활성화 되도록 설정했다.
참여하기 위해서는 사이트에 가입할 수 있도록 만들어 보았다. 좋아하는 걸, 별로인 걸 나누고 싶은게 사람이다 싶다.
<br></p>
<hr>
<h1 id="👨🏻💻-마이페이지">👨🏻‍💻 마이페이지</h1>
<p><img src="https://images.velog.io/images/rand_guy/post/676686d7-096c-48f4-b4cd-f557b283fcdb/image.png" alt=""></p>
<p>마이페이지를 통해서 유저가 좋아요, 평가한 카페를 필터(평점순, 역순)을 통해 확인 할 수 있도록 만들었다.
기존 왓챠피디아에서는 두번의 페이지 이동을 통해 필터를 할 수 있었다. 영화, 책, 드라마 등의 카테고리를 가진 왓챠피디아와 다르게 카페 하나만 목적으로 하는 사이트인 만큼 한번에 모든 걸 확인 할 수 있도록 심플하고 편리한 마이페이지를 만드려고 했다.
<br></p>
<hr>
<h1 id="👨🏻💻-검색페이지">👨🏻‍💻 검색페이지</h1>
<p><img src="https://images.velog.io/images/rand_guy/post/b8cd20b5-9054-434f-93a0-4695c1ac0dce/image.png" alt="">
검색페이지 역시 카페에 해당되는 주소, 이름을 제외한 부분을 최소화한 심플한 레이아웃으로 제작했다.
<br></p>
<hr>
<h1 id="🙆🏻♂️-결론">🙆🏻‍♂️ 결론</h1>
<p>주어진대로 제작했다면 이렇게 서비스를 설명하는 블로그를 만들 이유가 없었을 것이다. 하지만 기획을 조금 추가하는 것 만으로 사이트를 만들 때, 다양한 부분을 고민하면서 만들 수 있었다. <strong>실제로 유저가 이용한다면 불편하지 않을까?</strong> 라는 기능은 빼고 필요한 기능을 추가하는 등의 과정이 생기면서 프로젝트에 더 애착을 가지고 진행할 수 있었다. </p>
<p>또한 프론트엔드 팀원들의 미적감각으로 이렇게 멋진 페이지들을 구현할 수 있었다. 모든 팀원들에게 너무나 감사하고 추후에 다시 한 팀으로 리팩토링을 진행하고 싶다. 현재는 이용할 수 없는 사이트이지만 추후에 리팩토링과 AWS를 통해 실제로 작동하는 사이트가 되기를 기대해본다.</p>
]]></description>
        </item>
    </channel>
</rss>