<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>blissful</title>
        <link>https://velog.io/</link>
        <description></description>
        <lastBuildDate>Thu, 08 Jul 2021 16:14:59 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>blissful</title>
            <url>https://images.velog.io/images/blissful-y0/profile/e42a4fdb-844d-4f2c-99b1-bc98e3297d96/KakaoTalk_Image_2021-05-10-10-33-05.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. blissful. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/blissful-y0" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[Firebase] Firebase로 Realtime Chat Application 만들기 [1]]]></title>
            <link>https://velog.io/@blissful-y0/firebase</link>
            <guid>https://velog.io/@blissful-y0/firebase</guid>
            <pubDate>Thu, 08 Jul 2021 16:14:59 GMT</pubDate>
            <description><![CDATA[<p>팀 프로젝트 진행 중, 원하는 서비스를 구현하기 위해 실시간 채팅 서비스를 구축하게 되었다. 직접 Node.js 서버에 Socket.io를 활용하여 서비스를 구현하는 것이 가장 바람직하겠으나, Socket.io의 방대한 정보량에 GG를 선언하고 Firebase를 사용해 실시간 채팅 서비스를 구현하기로 결정했다. Firebase는 굉장히 공식 문서가 친절하기 때문에, 공식 문서만 읽고도 웬만한 서비스 구축이 가능하다. 프로젝트 용 실전 기능 구현 전, 간단히 테스트 용으로 Slack의 채팅 부분을 클론 코딩해 보려고 한다.</p>
<p>Udemy의 <a href="https://www.udemy.com/course/build-a-slack-chat-app-with-react-redux-and-firebase/">Build a Slack Chat App with React, Redux, and Firebase :  Reed Barger</a> 강의를 베이스로 Mock App을 만드는 것이 어떻냐는 추천을 받았는데, 해당 강의는 아쉽게도 React의 클래스형 컴포넌트로 작성이 되어 있다. 마침 클래스형을 함수형으로 바꾸는 연습이 필요했던 때라, 나는 강의를 참고하되 코드는 함수형으로 작성했다.</p>
<h3 id="firebase-setting-auth--userdb-설계">Firebase Setting: Auth / userDB 설계</h3>
<p><img src="https://images.velog.io/images/blissful-y0/post/ca3ab254-02f5-4638-b8c8-c9d7f7cf07eb/%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-09%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%201.29.45.png" alt="">
기본적인 Firebase 셋팅을 마쳤으면, 이메일/비밀번호를 이용한 로그인/회원가입 방식을 사용하기 위해서 Authentication 메뉴의 이메일/비밀번호를 활성화시켜야 한다.
<img src="https://images.velog.io/images/blissful-y0/post/d4e6bb4e-66b8-4d15-8009-c149fe794cf7/%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-09%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%201.37.02.png" alt="">
또한, 채팅을 위해 Realtime Database를 사용할 예정이기 때문에 user에 관련된 DB를 셋업하는 것 역시 필수다. Realtime DB는 JSON 형태로 저장되며, 나는 채팅에 필요한 정보가 유저의 이름과 그 유저의 아바타(프로필 사진)이기 때문에, 두 가지의 정보만 DB에 저장하려고 한다.따라서, 데이터 구조는 아래와 같이 설계했다.</p>
<pre><code class="language-javascript">{
  &quot;users&quot;: {
    &quot;user.uid(유저 고유 아이디)&quot;: {
      &quot;name&quot;: 유저 이름,
      &quot;avartar&quot; : 유저 프로필 사진
    },
  }
}
</code></pre>
<h3 id="auth를-사용하여-유저-정보-만들기">Auth를 사용하여 유저 정보 만들기</h3>
<p>회원가입 폼에 적힌 정보를 받아 Firebase Auth에 넘겨 주기는 매우 간단하다. 나는 handleSubmit이라는 함수를 작성해, 해당 함수가 실행되면 아래의 코드가 실행되도록 코딩했다.</p>
<pre><code class="language-javascript">  const handleSubmit = (event) =&gt; {
    event.preventDefault();
    // 중복 클릭 방지를 위해 disable 버튼 활성화
    setLoading(true);
    firebase
      .auth()
      .createUserWithEmailAndPassword(이메일, 패스워드)
      .catch((error) =&gt; {
        const errorCode = error.code;
        const errorMessage = error.message;
        console.log(errorCode, &quot;:&quot;, errorMessage);
      });
  };</code></pre>
<p><img src="https://images.velog.io/images/blissful-y0/post/ecc697e4-7eec-4ad7-b1f1-90d069fdec7e/%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-09%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%201.47.03.png" alt="">
함수가 성공적으로 실행되면, Authentication의 Users에 전달한 정보가 잘 저장된다. 이제 이 정보를 Realtime Database에 넘겨야 한다.</p>
<h3 id="보여질-닉네임과-아바타-설정하기">보여질 닉네임과 아바타 설정하기</h3>
<pre><code class="language-javascript"> const handleSubmit = (event) =&gt; {
    event.preventDefault();
    // 중복 클릭 방지를 위해 disable 버튼 활성화
    setLoading(true);
    firebase
      .auth()
      .createUserWithEmailAndPassword(이메일, 패스워드)
      .then((userCredential) =&gt; {
        const user = userCredential.user;
        user
          .updateProfile({
            displayName: 유저 설정 닉네임,
            photoURL: 프로필 사진 주소
          })
      .catch((error) =&gt; {
        const errorCode = error.code;
        const errorMessage = error.message;
        console.log(errorCode, &quot;:&quot;, errorMessage);
      });</code></pre>
<p><code>firebase.auth().createUserWithEmailandPassword</code> 함수는 이메일과 패스워드밖에 인자로 받지 않기 때문에, 따로 유저에게서 받아온 프로필 사진 정보와 닉네임을 저장해 주기 위해선 추가적인 설정이 필요하다. 해서, userCredential.user로 받아온 정보에 updateProfile 함수를 사용해 내가 원하는 정보를 입력해 주었다.</p>
<h3 id="realtime-database에-유저-정보-등록">Realtime Database에 유저 정보 등록</h3>
<p>Realtime Database에 동시적으로 정보가 저장되는 것이 아니기 때문에, 회원가입으로 받아온 정보를 DB에 넘겨주는 2차 작업을 해야 한다. 코드의 가독성을 위해, DB에 저장하는 함수는 따로 선언해 주었다.</p>
<pre><code class="language-js">const database = firebase.database().ref(&quot;users/&quot;);
// users는 DB의 최상위 노드
const saveUser = (user) =&gt; {
  return database.child(user.uid).set({
    name: user.displayName,
    avartar: user.photoURL,
    });
  };
// user로 받아온 값을 user.uid 값인 child 노드를 생성한다. 
// 이후 name / avatar 값을 덮어씌운다.
 const handleSubmit = (event) =&gt; {
    event.preventDefault();
    // 중복 클릭 방지를 위해 disable 버튼 활성화
    setLoading(true);
    firebase
      .auth()
      .createUserWithEmailAndPassword(이메일, 패스워드)
      .then((userCredential) =&gt; {
        const user = userCredential.user;
        user
          .updateProfile({
            displayName: 유저 설정 닉네임,
            photoURL: 프로필 사진 주소
          })
      // 이후, user의 값을 saveUser에 인자로 넘긴다
      .then(() =&gt;
            saveUser(user).then(() =&gt; {
              console.log(&quot;User Saved&quot;);
            })
          )
          .catch((err) =&gt; {
            console.log(err);
          });</code></pre>
<p>함수가 잘 실행이 됐다면, &quot;User Save&quot; 로그가 찍히며 Realtime DB에 잘 저장이 된다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TIL-08] Scope & Hositing]]></title>
            <link>https://velog.io/@blissful-y0/dsaf</link>
            <guid>https://velog.io/@blissful-y0/dsaf</guid>
            <pubDate>Wed, 19 May 2021 01:20:40 GMT</pubDate>
            <description><![CDATA[<h2 id="22-스코프scope란-무엇인가">2.2 스코프(Scope)란 무엇인가?</h2>
<blockquote>
<p>현재 실행되는 컨텍스트를 말한다. 여기서 컨텍스트는 값과 표현식이 &quot;표현&quot;되거나 참조 될 수 있음을 의미한다. 만약 변수 또는 다른 표현식이 &quot;해당 스코프&quot;내에 있지 않다면 사용할 수 없다. 스코프는 또한 계층적인 구조를 가지기 때문에 하위 스코프는 상위 스코프에 접근할 수 있지만 반대는 불가하다. </p>
</blockquote>
<ul>
<li><a href="https://developer.mozilla.org/ko/docs/Glossary/Scope">https://developer.mozilla.org/ko/docs/Glossary/Scope</a></li>
</ul>
<h2 id="222-var-let-const">2.2.2 var, let, const</h2>
<ul>
<li>var 키워드로 선언한 변수와 let, const로 선언한 변수의 스코프는 다르게 동작한다.</li>
</ul>
<h3 id="222-1-var">2.2.2-1 var</h3>
<ul>
<li>var 키워드로 선언한 변수는 중복 선언이 가능하다.</li>
<li>var 키워드로 선언한 변수는 오로지 함수의 코드 블록만을 지역 스코프로 인정한다. 따라서 함수 외부에서 var 키워드로 선언한 변수는 코드 블록 내에서 선언해도 모두 전역 변수가 된다.</li>
<li>var 키워드로 변수를 선언하면 <strong>변수 호이스팅</strong>에 의해 변수 선언문이 스코프의 선두로 끌어 올려진 것처럼 동작한다. 즉, 변수 <strong>호이스팅</strong>에 의해 var 키워드로 선언한 변수는 변수 선언문 이전에 참조할 수 있다. 단, undefined를 반환한다.</li>
</ul>
<pre><code class="language-jsx">var x = 1;
if (true) {
 var x = 10 // 중복 선언됨
};

console.log(x); // 10</code></pre>
<h3 id="222-2-let">2.2.2-2 let</h3>
<ul>
<li>let 키워드로 이름이 같은 변수를 중복 선언하면 문법 에러가 발생한다.</li>
<li>let 키워드로 선언된 변수는 블록 레벨 스코프를 따른다.</li>
</ul>
<pre><code class="language-jsx">let bar = 123;
let bar = 456; // syntax error</code></pre>
<pre><code class="language-jsx">let foo = 1; // 전역 변수
{ 
    let foo = 2; // 지역 변수
    let bar = 3; // 지역 변수
}

console.log(foo); // 1
console.log(bar); // Reference error</code></pre>
<h3 id="222-3-const">2.2.2-3 const</h3>
<ul>
<li>const 키워드는 상수를 선언하기 위해 사용된다.</li>
<li>const 키워드로 선언한 변수는 반드시 선언과 동시에 초기화해야 한다.</li>
<li>const 키워드로 선언한 변수는 재할당이 금지된다. 단, 변수에 객체를 할당한 경우 값을 변경할 수 있다.</li>
</ul>
<pre><code class="language-jsx">const foo = 1;
const foo; // 할당하지 않을 경우 syntax error 발생</code></pre>
<p><img src="https://images.velog.io/images/blissful-y0/post/5bb07565-8b45-4756-93a7-dd72c84be6be/Untitled%20(1).png" alt=""></p>
<h2 id="scope-quiz">SCOPE QUIZ</h2>
<p><a href="https://docs.google.com/presentation/d/1LKRodJXWMNqBDFL3Y3EUCtuUs0N-dq5r6HpCGaanXMg/edit?usp=sharing">https://docs.google.com/presentation/d/1LKRodJXWMNqBDFL3Y3EUCtuUs0N-dq5r6HpCGaanXMg/edit?usp=sharing</a></p>
<p>따로 스코프 개념을 정확히 이해하기 위해 퀴즈를 만들어 풀어 보았다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TIL 07] Operators, 논리 연산자]]></title>
            <link>https://velog.io/@blissful-y0/sdfsdf</link>
            <guid>https://velog.io/@blissful-y0/sdfsdf</guid>
            <pubDate>Tue, 18 May 2021 06:41:54 GMT</pubDate>
            <description><![CDATA[<h2 id="operators-연산자란-무엇인가">Operators, 연산자란 무엇인가?</h2>
<p>연산자란 프로그래밍에서 쓰이는 기호들이다. 연산자는 기본적으로 사용자에게 값(Value)을 변환(transform)할 수 있게 해 준다. 연산자에는 산술, 문자열, 증감, 비교, 대입, 삼항, 논리, 비트연산자 등이 있다.</p>
<h2 id="논리-연산자-logical-operators">논리 연산자 (Logical Operators)</h2>
<ul>
<li><strong>💡 Before we start, False 값들을 알아보자!</strong><ul>
<li>0</li>
<li>-0</li>
<li>false</li>
<li>undefined</li>
<li>null</li>
<li>&quot;&quot;</li>
<li>&#39;&#39;</li>
<li>``</li>
<li>NaN</li>
</ul>
</li>
</ul>
<h3 id="not-operator">NOT Operator</h3>
<ul>
<li><code>!</code>를 이용해 표현한다.</li>
<li><code>!</code> 뒤에 오는 값을 <code>true</code>(Boolean)으로 변환할 수 있다면 <code>false</code>를 반환한다. 그렇지 않을 경우 <code>true</code>를 반환한다.</li>
<li>결과적으로, false 값들은 ! 연산자를 사용할 경우 true로 반환된다.</li>
<li>종종 <code>!!</code>을 사용하는 경우를 볼 수 있는데, boolean 값으로 데이터를 활용하기 위함이다.</li>
</ul>
<pre><code class="language-jsx">!true; // false
!2; // false
!&quot;abc&quot; // false

!false; // true
!0 // true
!undefined // true</code></pre>
<h2 id="logical-or-operator">Logical OR Operator</h2>
<ul>
<li><code>||</code>로 표현한다.</li>
<li><code>true</code>나 <code>false</code> 값이 아닌 피연산자(operand) 값이 반환된다.</li>
</ul>
<p>가동 프로세스는 다음과 같다.</p>
<ol>
<li>연산자 기준, 왼쪽부터 <code>true</code> 값을 찾는다.</li>
<li><code>True</code>값을 찾은 경우 연산을 중지하고 해당 값을 반환한다.</li>
<li>마지막까지 <code>true</code> 값을 찾지 못한 경우, 가장 마지막에 위치한 값을 반환한다.</li>
</ol>
<h2 id="logical-and-operator">Logical AND Operator</h2>
<ul>
<li><code>&amp;&amp;</code>로 표현한다.</li>
<li><code>true</code>나 <code>false</code> 값이 아닌 피연산자(operand) 값이 반환된다.</li>
</ul>
<p>가동 프로세스는 다음과 같다.</p>
<ol>
<li>연산자 기준, 왼쪽부터 <code>false</code> 값을 찾는다.</li>
<li><code>false</code> 값을 찾은 경우 연산을 중지하고 해당 값을 반환한다.</li>
<li>마지막까지 <code>false</code> 값을 찾지 못한 경우, 가장 마지막에 위치한 값을 반환한다.</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TIL-06] optional-chaning, props, patterns]]></title>
            <link>https://velog.io/@blissful-y0/TIL-06-props</link>
            <guid>https://velog.io/@blissful-y0/TIL-06-props</guid>
            <pubDate>Mon, 17 May 2021 05:52:58 GMT</pubDate>
            <description><![CDATA[<p>지난 주에 활용했던 freeboard를 활용해서 실무에서 주로 사용하는 폴더 구조인 container/presenter 패턴을 적용시키는 실습을 했다. 오늘 코드캠프에서 배운 내용은 아래와 같다.</p>
<ul>
<li>optional-chaning</li>
<li>props</li>
<li>destructring (구조 분해 할당)</li>
<li>container-presenter / atomic 패턴</li>
</ul>
<h3 id="optional-chaning">optional-chaning</h3>
<p>지난 주, useQuery API를 사용해 DB로부터 받아온 데이터를 렌더링할 때, 조건부 렌더링을 사용해 &#39;undefined&#39; 에러를 해결했었다. React의 state가 컴포넌트 변수인 점을 활용한 건데, event로부터 받아온 값이 컴포넌트 변수인 setData에 할당되어, 해당 변수가 호출이 되면 rerendering하는 React의 개념을 활용했다.</p>
<pre><code class="language-javascript"> const [data, setData] = useState({
   writer: &quot;&quot;,
   password: &quot;&quot;,
   title: &quot;&quot;,
   contents: &quot;&quot;,
  }); // data의 디폴트 값은 &quot;&quot;, 그러나...

 const onChangeInput = (event) =&gt; {
   const userData = { ...data, 
                     [event.target.name]: event.target.value };
   setData(userData);
 }; // 여기서 이벤트로 받아온 값들을 setData에 할당

   data &amp;&amp; data.fetchProfile
// &amp;&amp; 연산자의 성질을 활용, data.fetchProfile이 false일 때 data를 반환, 
// data.fetchProfile이 true일 때는 data.fetchProfile을 반환</code></pre>
<p>그러나 이 방법에는 문제가 있다. 현재 코드는 단 한 가지의 상황만 존재해 &amp;&amp; 연산자를 사용해도 전혀 문제가 없었다, 하지만... 만약 내가 원하는 코드가 fetchProfile에서 더 타고 들어가야 한다면? 예를 들어......</p>
<pre><code class="language-javascript">data.fetchProfile.name.firstname.surname
data &amp;&amp; data.fetchProfile &amp;&amp; data.fetchProfile.name &amp;&amp; data.fetchProfile.name.firstname &amp;&amp; data.fet.... 어쩌구!
// name이 없는 경우가 있다면? firstname이 없다면?</code></pre>
<p>경우의 수만 봐도 벌써 머리가 아프다. 이런 고민을 한 번에 날릴 수 있는 방법이 있으니 그게 바로 <code>optional-chaning</code>이다.</p>
<blockquote>
<p>optional chaining 연산자는 참조나 기능이 undefined 또는 null일 수 있을 때 연결된 객체의 값에 접근하는 단순화할 수 있는 방법을 제공한다.</p>
</blockquote>
<pre><code class="language-javascript">let nestedProp = obj.first &amp;&amp; obj.first.second;
let nestedProp = obj.first?.second;
let nestedProp = ((obj.first === null || obj.first === undefined) 
        ? undefined : obj.first.second);</code></pre>
<p><a href="https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Operators/Optional_chaining">MDN: Optional chaning</a></p>
<p>optional chaning을 사용하면, 위의 data 케이스를 간단하게 정리할 수 있다.</p>
<pre><code class="language-javascript">data?.fetchBoard?.name?.firstname?.surname</code></pre>
<h3 id="props--destructring-구조-분해-할당">Props &amp; destructring (구조 분해 할당)</h3>
<p>리액트는 크게 두 가지 특징이 있다.</p>
<ul>
<li>선언형</li>
<li>컴포턴트 기반</li>
</ul>
<p>리액트를 처음 접했을 때는, 어떻게 리액트가 UI 관리에 용이한지, 왜 컴포넌트 기반의 라이브러리인지 이해할 수 없었다.</p>
<blockquote>
<p>개념적으로 컴포넌트는 JavaScript 함수와 유사합니다. “props”라고 하는 임의의 입력을 받은 후, 화면에 어떻게 표시되는지를 기술하는 React 엘리먼트를 반환합니다.
<a href="https://ko.reactjs.org/docs/components-and-props.html">React: Components and Props</a></p>
</blockquote>
<p><code>props</code>는 <code>부모 컴포넌트가 자식 컴포넌트에게 넘겨준 데이터와 기능등</code>을 의미한다.</p>
<p><img src="https://images.velog.io/images/blissful-y0/post/ace623f6-8c4f-4446-aad3-4dead6f374bf/%EC%A0%9C%EB%AA%A9%20%EC%97%86%EB%8A%94%20%ED%94%84%EB%A0%88%EC%A0%A0%ED%85%8C%EC%9D%B4%EC%85%98.png" alt=""></p>
<p>위의 그림은 오늘 미니 과제에서 사용했던 나의 코드이다. Component와 Props를 별개의 파일로 저장하여 관리하는 Container/Presenter 패턴을 사용했다. 이 패턴에 대한 내용은 밑에 이어진다.</p>
<p>앞서 우리는 props가 부모 컴포넌트로부터 자식 컴포넌트에게 넘겨준 데이터와 기능이라 설명했다. 즉 위의 그림대로라면 Container는 부모 컴포넌트이고, Presenter는 자식 컴포넌트가 된다. <code>ViewUI</code>는 Container인 <code>QueryDetailPage</code> 함수로부터 <code>data</code> 정보를 받아 ViewUI를 렌더링하게 된다. 이때 <code>data</code>는 <code>props</code> 가 된다.</p>
<p>여기서 한 가지 의문점이 생겼는데, props로 전달 받은 데이터는 <code>props.원하는 데이터</code> 형식으로 접근한다. 이 접근 방식은 Object의 value 값 접근 방식과 동일한데, 혹시 props를 디스트럭쳐링 할 수 있지 않을까, 생각이 들었다. 해서, props를 console.dir 해 보았다.
<img src="https://images.velog.io/images/blissful-y0/post/571bc1e2-1d97-43ca-826c-8b53e9a11529/%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-05-17%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%206.55.05.png" alt=""></p>
<p>예상했던대로였다. 지금은 전달 받은 데이터의 갯수가 적으니 읽는데 무리가 없지만 나중에 수십 개의 props 내부 데이터를 처리할 때 props.AA, props.BB  방식으로 접근하면 가독성에 문제가 있을 것 같아 디스트럭쳐링을 했다.</p>
<p><img src="https://images.velog.io/images/blissful-y0/post/c3a4bda6-51ad-4d1d-8a9b-f467e08174f4/%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-05-17%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%207.00.11.png" alt=""></p>
<p>좀 더 코드의 가독성이 좋아지고, 시멘틱해졌다.</p>
<h3 id="containerpresentor--atomic-pattern">container/presentor &amp; atomic pattern</h3>
<blockquote>
<p><a href="https://velog.io/@holim0/React-Design-Pattern">성균관코린이 님의: React Design Pattern</a></p>
</blockquote>
<p>오늘 미니 과제에 사용한 디자인 패턴은 Container/Presentor 패턴이었다. 사용을 해 보며 내가 느꼈던 장점은 아래와 같았다.</p>
<ul>
<li>재사용하기 굉장히 좋았다.</li>
<li>로직을 관리하는 공간, JSX를 렌더링하는 공간이 분리되어 유지보수가 편리하다.</li>
</ul>
<p>Atomic 패턴은 디자이너와 협업하기 굉장히 좋다는데, 직접 사용해 본 것은 아니라 잘 모르겠다. 위에 링크된 글을 보며 좀 더 공부하는 시간을 가져야 할 것 같다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TIL-05] Javascript의 Value & Type]]></title>
            <link>https://velog.io/@blissful-y0/TIL-05</link>
            <guid>https://velog.io/@blissful-y0/TIL-05</guid>
            <pubDate>Fri, 14 May 2021 06:40:37 GMT</pubDate>
            <description><![CDATA[<h1 id="1-data-type의-종류">1. Data Type의 종류</h1>
<p><img src="https://images.velog.io/images/blissful-y0/post/468b237b-679f-400f-ae44-4de07153e7cb/Untitled.png" alt="">
<strong>코어 자바스크립트, 정재남 저 @</strong></p>
<p>기본형(Primitive)과 참조형(Reference)를 구분하는 기준은 다음과 같다.</p>
<ul>
<li>기본형은 연산 시 값이 담긴 주솟값을 복사한다.</li>
<li>참조형은 값이 담긴 주솟값들로 이루어진 묶음을 가리키는 주솟값을 복제한다.</li>
</ul>
<p>기본형은 불변성(immutability)를 띈다.  1-6에서 이 내용에 대해 좀 더 깊게 알아본다.</p>
<p>자바스크립트는 <strong>Dynamic typing 언어(동적 언어는 개발 속도가 빠르지만, 다양한 오류를 일으킬 수 있다. 정적 언어인 Typescript로 보완 가능하다)</strong>이다. 따라서 직접 데이터의 종류를 <strong>define할 필요 없으며</strong>, 데이터 종류는 자동적으로 할당된다.</p>
<h2 id="1-string-type-문자열">1. String Type (문자열)</h2>
<ul>
<li>&quot; &quot; 또는 &#39; &#39;, 즉 따옴표를 이용해 표현한다. 어느 쪽을 사용하든 상관없으나 코드 내내 사용하는 따옴표는 통일하도록 하자.</li>
<li>문자열은 서로 더할 수 있음. 예를 들어, &quot;I love&quot;와 &quot;chicken&quot;이라는 두 개의 문자열이 존재하는 경우 &quot;I love&quot; + &quot;chicken&quot; = &quot; I love chicken&quot;을 만들 수 있다.</li>
<li>문자열은 유사 배열(Arry)이다.
유사 배열이기 때문에, index를 이용해 각 문자열에 접근이 가능하다. index는(indexOf, lastindexOf 등) 배열에서 지정된 요소를 찾을 수 있는 메서드이다.</li>
</ul>
<pre><code class="language-jsx">console.log(&quot;chicken&quot;.legnth);
// expected output: 7
console.log(&quot;chicken&quot;.indexOf(&quot;C&quot;);
// expected output: 0</code></pre>
<p>string 역시 유사 배열로 취급되기 때문에, 상기 코드와 같은 메서드를 실행시킬 수 있다. 아래 래퍼 객체에 대한 설명을 읽으면 이해가 쉽다.</p>
<h2 id="2-number-type-숫자열">2. Number Type (숫자열)</h2>
<ul>
<li>숫자는 말 그대로 &#39;숫자&#39;이다.</li>
<li>따라서 더하기, 빼기, 곱하기, 나누기 등의 연산이 가능하다.</li>
<li>MDN의 Math 내장 객체를 사용하면 다양한 연산들이 가능하다. 쌍곡아크사인 같은 것도 가능하다. (<a href="https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Math">https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Math</a>)</li>
<li>Infinity 또는 -Infinity처럼 무한을 표현하는 값도 있다.</li>
<li>NaN(Not A Number)이라는 값 역시 숫자이다.</li>
</ul>
<pre><code class="language-jsx">Number(&quot;123&quot;);
// expected output : 123
Number(&quot;abc&quot;);
// expected output : NaN

하지만, typeOf를 사용할 경우

typeof(Number(&quot;123&quot;))
&quot;number&quot;
typeof(Number(&quot;abc&quot;))
&quot;number&quot;

&quot;123&quot;과 &quot;abc&quot; 값 모두 Number로 취급된다. NaN 역시 숫자값이기 때문.</code></pre>
<h3 id="막간을-이용해서">막간을 이용해서...</h3>
<ol>
<li><strong>Number() 등의 래퍼 객체란 무엇인가?</strong></li>
</ol>
<p>Data Type Diagram을 참고하면, JS에는 총 6개의 원시(Primitive) 데이터 타입이 있다.</p>
<p>Number, String, Boolean, null, undefined, symbol</p>
<p>이 원시 타입에 대응하기 위해, JS에는 래퍼 객체(wrapper object)라는 개념이 있다.</p>
<p>String(), Number(), Boolean(), Symbol()</p>
<p>래퍼 객체는 말 그대로, 원시 타입을 감싸는 형태의 객체이다. </p>
<p>원시형 데이터 타입은 본래 객체와 같이 메서드를 가질 수 없으나, JS는 일시적으로 &#39;Number&#39;, &#39;String&#39;, &#39;Boolean&#39;, &#39;Symbol&#39; 타입에 일시적으로 &#39;객체&#39;화가 되는 것을 허락하며, 따라서 메서드를 사용할 수 있게 된다. 즉 래퍼 객체는, 원시 타입 데이터를 객체화 시켜주는 개념이다.</p>
<h2 id="3-boolean-type">3. Boolean Type</h2>
<ul>
<li>True(참) 또는 False(거짓), 두 가지 값이 존재한다.</li>
<li>어떤 값이 Truthy하고, False한지는 후의 1-2 Operation에서 자세하게 후술.</li>
</ul>
<h2 id="4-undefined--null-type">4. Undefined / Null Type</h2>
<h3 id="undefined-type이란">Undefined Type이란?</h3>
<ul>
<li>&quot;없음 값&quot;이다. 없다는 &quot;값&quot;이다. 값이 할당되지 않은 &quot;값&quot;인 것.</li>
</ul>
<pre><code class="language-jsx">// 초기값이 할당되지 않은 변수
let hi;
console.log(hi); // undefined

// 초기값이 할당되지 않은 매개변수
function bye (a, b) {
  console.log(a); // 1
  console.log(b); // undefined
}
bye(1);

// 객체에서 존재하지 않는 속성을 접근하는 경우
const person = {
  age: &#39;18&#39;
};
console.log(person.height); // undefined</code></pre>
<h3 id="null-type이란">Null Type이란?</h3>
<ul>
<li>&quot;없음&quot; 값이다. 값이 없다는 뜻이다.</li>
<li>null === null is true</li>
<li>undefined은 값이 아직 할당되지 않거나, 존재하지 않는 경우 사용하는 &quot;없음&quot;이다. null의 경우 존재하지 않는 &quot;없음&quot;이다. 아래 코드를 보자.</li>
</ul>
<pre><code class="language-jsx">let greeting = [ &quot;hi&quot;, &quot;hello&quot;, ];
console.log(greeting);
// (2) [&quot;hi&quot;, &quot;hello&quot;]
let greeting = null;
console.log(greeting);
// null</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TIL-04] GraphQL, Apollo Client Mutation 실습]]></title>
            <link>https://velog.io/@blissful-y0/TIL-04</link>
            <guid>https://velog.io/@blissful-y0/TIL-04</guid>
            <pubDate>Thu, 13 May 2021 09:40:30 GMT</pubDate>
            <description><![CDATA[<p>전날 GraphQL을 통해 어떻게 데이터를 백엔드 서버에 요청하며, 역으로 백엔드에서는 어떻게 DB를 받는지 간단한 개념 정리를 했다. 오늘은 실습 위주의 날로, 크게 두 가지의 미니 과제를 진행하며 비동기 자바스크립트에 대해 공부했다.</p>
<h3 id="오늘의-codecamp-미니-과제">오늘의 code.camp 미니 과제</h3>
<ul>
<li>KoreanJSON의 DB에서 axios를 이용해 자료를 가져와 화면에 뿌려주기</li>
<li>GraphQL의 Mutation의 기능을 사용하여 DB에 게시글 전달하기</li>
</ul>
<p>첫 번째 미니 과제의 경우 생각보다 빠르게 마무리할 수 있어 추가적으로 countIndex라는 변수를 만들어 버튼을 누를 때마다 다음의 데이터를 불러올 수 있는 기능을 추가하였다.</p>
<pre><code class="language-javascript"> const [titleFnfo, setTitleInfo] = useState(&quot;전달받은 정보가 표기됩니다.&quot;);
 const [content, setCotents] = useState(&quot;&quot;);
 const [updatedAt, setUpdatedAt] = useState(&quot;&quot;);
 const [count, setCount] = useState(1);

async function handleClickGetPost() {
    const datalength = await axios.get(&quot;https://koreanjson.com/posts&quot;);
    const data = await axios.get(`https://koreanjson.com/posts/${count}`);
    let date = new Date(data.data.updatedAt);
    let dateObject = {
      year: date.getFullYear(),
      month: String(date.getMonth() + 1).padStart(2, &quot;0&quot;),
      date: date.getDate() - 1,
    };
    let countIndex = count + 1;
    if (countIndex &gt; datalength.data.length) {
      countIndex = 0;
    }
    setTitleInfo(data.data.title);
    setCotents(data.data.content);
    setUpdatedAt(`${dateObject.year}-${dateObject.month}-${dateObject.date}`);
    setCount(countIndex);</code></pre>
<p>두 번째 미니과제를 진행하면서, 다시 한번 문서를 잘 읽어보는 습관이 필요하다는 것을 실감했는데. 무려 400 에러와 한 시간 동안 씨름을 했다.</p>
<p><img src="https://images.velog.io/images/blissful-y0/post/a30bba93-30f0-4824-9b3e-206deb346101/%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-05-13%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%208.05.55.png" alt=""></p>
<p>이 화면과 약 한 시간 동안 씨름하며, 내 코드가 어디서 잘못됐는지 수도 없이 체크했는데, 코드에는 문제가 없었다. 아니, 문제는 있었지만 그건 코드의 문법 문제가 아닌 단순히 내 부주의의 문제였다.</p>
<p><img src="https://images.velog.io/images/blissful-y0/post/8baeebd1-869d-44d0-98bb-35b9ba3d7d8d/%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-05-13%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%208.06.07.png" alt="">
<img src="https://images.velog.io/images/blissful-y0/post/3a48cf3b-e36a-4933-9855-450b7a4dc383/%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-05-13%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%208.53.44.png" alt=""></p>
<p>그렇다.
리턴 값으로 지정되어 있지 않은 password를 요청하니 당연히 400 에러가 날 수밖에 없지. 이 사실을 깨닫고 코드 수정 후 정상 작동화면을 봤을 땐 솔직히 울고 싶은 심정이었다. 상식적으로 누가 비밀번호 찾기 기능도 아닌데 비밀번호 값을 리턴하냐고! 하지만 이것 또한 플레이그라운드 스키마를 정독하라는 자바스크립트 신의 계시라고 생각하기로 했다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TIL-03] React와 친해지기 2편 - Component의 Life-Cycle (생명 주기)]]></title>
            <link>https://velog.io/@blissful-y0/TIL-SDF</link>
            <guid>https://velog.io/@blissful-y0/TIL-SDF</guid>
            <pubDate>Wed, 12 May 2021 05:51:25 GMT</pubDate>
            <description><![CDATA[<p>이전 글에서는 React의 Component 개념에 대해 간략하게 정리했다. 이번 글에서는 클래스형 컴포넌트를 통해 Life-Cycle 개념에 대해 정리해 보았다. 사실 React 버전 16.8부터 Hook의 등장으로, Class 기반 코드를 작성할 필요 없이 굉장히 편리하게 기존의 Life-Cycle(생명 주기)를 이용한 기능들을 사용할 수 있게 되었다. 그러나 공식 문서에서 거듭 강조했듯, Hook은 <strong>기존 React의 컨셉을 대체하지 않으며</strong>, 단지 props, state, context, refs 등의 React 개념에 직관적인 API를 제공할 뿐이다. 즉, React의 근간인 셈이다. </p>
<h1 id="react-class형-component의-life-cycle">React Class형 Component의 Life-Cycle</h1>
<p><img src="https://images.velog.io/images/blissful-y0/post/64311880-5789-415d-9cb9-1d982b6bd6f6/image.png" alt="React LifeCycle in ES6">
<a href="https://twitter.com/sstur_/status/970706983060848640?s=20">React LifeCycle in ES6 by Simon Sturner</a></p>
<p>모든 React Component들은 반드시 세 가지 과정을 거친다.</p>
<ul>
<li>Mounting(마운팅): Component가 마운팅되거나, DOM에 Component가 추가될 때 발생.</li>
<li>Updating(업데이팅): React가 props 또는 state의 변경을 감지했을 때 발생.</li>
<li>Unmounting(언마운팅): React가 DOM tree로부터 Component를 제거할 때 발생.</li>
</ul>
<h2 id="mounting-phase">Mounting Phase</h2>
<p>React Component가 마운트될 때 발생하는 것들은 다음과 같다.</p>
<ul>
<li>constructor</li>
<li>getDerivedStatefromProps</li>
<li>render</li>
<li>componentDidMount</li>
</ul>
<h3 id="constructor">constructor</h3>
<p><code>constructor</code>는 컴포넌트의 생성자 메서드로, 컴포넌트가 만들어질 때 가장 먼저 실행되는 메서드이다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TIL-02] React와 친해지기 1편 - Component란 무엇인가?]]></title>
            <link>https://velog.io/@blissful-y0/TIL-02</link>
            <guid>https://velog.io/@blissful-y0/TIL-02</guid>
            <pubDate>Tue, 11 May 2021 12:02:49 GMT</pubDate>
            <description><![CDATA[<p>프론트엔드 개발자를 지망하는 사람이라면 누구나 들어봤을 세 개의 이름이 있다. 바로 <code>React, Angular, Vue.js</code>다. 이전 글에도 간략히 말했지만, React는 현재 프론트엔트에서 가장 핫한 라이브러리이다. 리액트의 역사나, 누가 만들었는지, 왜 배워야 하는지 등의 내용은 검색하면 쏟아지는 내용이며, 학습자로서 이미 그 중요성을 알고 있기 때문에 굳이 짚고 넘어가지는 않을 생각이다. 어차피 밑의 사진 한 장이면 &#39;WHY REACT?&#39;라는 질문은 해소되니까.
<img src="https://images.velog.io/images/blissful-y0/post/0dea683f-495c-4403-89cb-126133f40630/image.png" alt="">
&#39;WHY REACT?&#39; 대답은 심플하다. 많이 쓰니까.</p>
<h1 id="react의-특징">React의 특징</h1>
<blockquote>
<p>React는 사용자 인터페이스를 구축하기 위한 선언적이고 효율적이며 유연한 JavaScript 라이브러리입니다. “컴포넌트”라고 불리는 작고 고립된 코드의 파편을 이용하여 복잡한 UI를 구성하도록 돕습니다. <a href="https://ko.reactjs.org/tutorial/tutorial.html#what-is-react">React란 무엇인가요?  - React 공식 문서</a></p>
</blockquote>
<p>리액트는, 간단히 설명하자면 UI를 위한 JS 라이브러리이다. 리액트는 컴포넌트 기반의 라이브러리로, <code>스스로 상태를 관리하는 캡슐화된 컴포넌트를 만들며, 이를 조합해 복잡한 UI를 만들어낼 수 있다.</code> 즉, 리액트의 가장 기본은 컴포넌트이다. 리액트를 공부하면서, 공식 문서의 설명이 조금 부족하다고 느꼈었는데 <a href="https://medium.com/little-big-programming/react%EC%9D%98-%EA%B8%B0%EB%B3%B8-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8%EB%A5%BC-%EC%95%8C%EC%95%84%EB%B3%B4%EC%9E%90-92c923011818">React의 기본, 컴포넌트를 알아보자 - Jisu Park</a> 님의 이 글이 아주 큰 도움이 되었다. 이 분의 비유대로 만일 React를 <code>UI = View(State)</code>라는 하나의 함수로 여긴다면, React의 특징이자 장점들을 아주 쉽게 이해할 수 있게 된다.</p>
<ul>
<li>대부분의 함수가 그러하듯, <strong>단방향 사고</strong>가 강제된다.</li>
<li><code>state</code>, <code>props</code>에 따른 <strong>렌더링 결과</strong>가 바뀌지 않는다. 즉, 불변성을 지킬 수 있다.</li>
<li>함수 내용을 정의하듯 JSX(React의 HTML 개념)을 통해 화면을 어떻게 렌더링할지 정의할 수 있다.</li>
<li>함수 간 합성이 가능하듯 컴포넌트끼리의 합성이 가능하다.</li>
</ul>
<h2 id="jsx란-무엇인가">JSX란 무엇인가?</h2>
<p>컴포넌트를 알아보기에 앞서, JSX를 먼저 공부했다. JSX는 간단히 설명하자면, <code>React 전용의 HTML</code>이다.</p>
<pre><code class="language-jsx">&lt;div&gt;
  &lt;div class=&quot;title&quot;&gt;제목&lt;/div&gt;
  &lt;button onclick=&quot;alert();&quot;&gt;버튼&lt;/button&gt;
&lt;/div&gt; 
// 기존 HTML 방식

&lt;div&gt;
  &lt;div className=&quot;title&quot;&gt;제목&lt;/div&gt;
  &lt;button onClick=&quot;alert();&quot;&gt;버튼&lt;/button&gt;
&lt;/div&gt;
// JSX 방식</code></pre>
<p>JSX 코드를 보면 알겠지만, 기존의 HTML과 큰 차이는 없다. <code>camalcase</code>를 사용한다는 것 정도. 물론, 웹브라우저는 <code>HTML</code>, <code>CSS</code>, <code>Javascript</code>만 읽을 수 있기 때문에, 최종적으로 실행될 때는 React가 JSX를 HTML로 Babel을 통해 변환시켜 실행된다.</p>
<h2 id="react의-component란-무엇인가">React의 Component란 무엇인가?</h2>
<p>컴포넌트를 간단히 설명하자면 UI 또는 기능을 <code>부품화</code>하여 <code>재사용 가능</code>하게 하는 것과 같다. 나는 이 컴포넌트를 <code>금형</code>으로 이해했다. 큰 틀인 <code>Component</code>가 있다면, 우리는 그 틀 안에서 넣고 싶은 정보인 <code>props</code>를 집어넣는다. 핸드폰 케이스를 예를 들자면, <code>아이폰 12</code>라는 모델의 금형에 내가 만들고 싶은 디자인을 집어넣어 최종적으로는 여러 종류의 <code>아이폰 12 핸드폰 케이스</code>를 만들 수 있다. 우리는 이것과 비슷한 개념을 잘 알고 있는데, 바로 <code>함수</code>이다. 그렇다, 컴포넌트는 <code>function</code>이다. React의 컴포넌트를 작성에는 두 가지 방법이 있다. </p>
<ul>
<li>클래스형</li>
<li>함수형</li>
</ul>
<p>최근 많은 기업들이 함수형 컴포넌트를 주로 사용한다고 하나, 기존에 만들어진 서비스들은 클래스형으로 되어 있는 경우도 많기 때문에 두 가지 선언 방식 모두 숙지해 둘 필요가 있다.</p>
<pre><code class="language-jsx">/// 클래스형 컴포넌트

import { Component } from &#39;react&#39;;

class New extends Component {
    render() {
        return &lt;div&gt;이것은 클래스형 컴포넌트이다.&lt;/div&gt;
    }
}

export default New 

/// 함수형 컴포넌트

export default function New() {
  return &lt;div&gt;이것은 함수형 컴포넌트이다.&lt;/div&gt;
}

/// 함수형 컴포넌트는 간단하게 화살표 함수(ES6)로도 정의할 수 있다.

const New = () =&gt; &lt;div&gt;이것은 화살표 함수로 선언한 함수형 컴포넌트입니다.&lt;/div&gt;

export default New
</code></pre>
<p>물론 데이터는 <code>각 컴포넌트에 맞게 변경하여 사용</code>이 가능하다. </p>
<h2 id="react는-왜-html을-js-코드로-가져왔는가">React는 왜 HTML을 JS 코드로 가져왔는가?</h2>
<p>이 방식의 장점은 간단하다. 로직과 마크 업이 하나의 Component에 담기게 되면, 상세하게 나뉘어진 페이지들을 여러 유닛으로 나누어 관심사 분리를 할 수 있다. 예를 들어, 쇼핑몰 사이트에서 여성의류 Page가 있다면, 그 여성의류 Page 부모 Component 안에서 아우터, 상의, 하의 등의 자식 Component 등으로 <code>props</code>를 전달할 수 있게 된다. 이는 차후 서비스가 방대해질 때 유지보수가 편해지는 이점이 있다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TIL-01] 보일러플레이트(boilterplate)란?]]></title>
            <link>https://velog.io/@blissful-y0/TIL-01-React-Next-JS-Emotion</link>
            <guid>https://velog.io/@blissful-y0/TIL-01-React-Next-JS-Emotion</guid>
            <pubDate>Tue, 11 May 2021 12:02:35 GMT</pubDate>
            <description><![CDATA[<h3 id="react란">React란?</h3>
<p>React는 Javascript를 효율적으로 사용할 수 있도록 도와주는 &quot;라이브러리&quot;이다. 페이스북, 인스타그램, 에어비앤비 등이 React를 채용하고 있으며, 코드캠프에서도 가장 중점적으로 배우게 될 스택이다. 라이브러리와 프레임워크의 차이점, React와 Vue 중 어느 것을 사용해야 할지 등의 글은 구글링만 해도 쏟아져 나옴으로 굳이 적지 않겠다.</p>
<p><img src="https://images.velog.io/images/blissful-y0/post/4a3e67c1-2a31-45f6-83a4-a9e8516f51f1/%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-05-11%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%209.57.38.png" alt="">
바닐라JS를 사용한 코딩은 이전부터 해 왔지만, 리액트를 사용한 것은 처음이라 index.html, script.js, style.css의 심플한 구성에 익숙한 사람은 아마 위의 화면을 보고 겁부터 먹을 수 있다. 일단 내가 그랬기 때문이다. 하지만 이 보일러플레이트(사진의 것을 보일러플레이트라 부른다)는 생각보다 알기에 어렵지 않았다. 구성은 굉장히 간단하다.</p>
<ol>
<li><p>node_modules
npm, yarn 등을 사용해 다운로드 받은 라이브러리와 프레임워크의 저장소이다. 나의 경우 프로젝트를 진행하며 emotion/styled를 사용했고 &quot;@emotion/styled&quot;; 로 import했다.</p>
</li>
<li><p>pages
보여 줄 페이지들이 저장되어 있는 곳이다. 
<img src="https://images.velog.io/images/blissful-y0/post/2ab908c5-338c-4469-9544-9630af278642/%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-05-11%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%2010.07.01.png" alt="">
이런 식으로, board 폴더를 만들어 그 안에 FAQ 페이지를 만드는 방식으로 진행했다.</p>
</li>
<li><p>public
아이콘 등의 사진이 저장되어 있는 곳이다.</p>
</li>
<li><p>styles
이름부터 css 파일이 저장될 것 같은 곳이다. 실제로 css 파일이 저장되는 곳이다.</p>
</li>
<li><p>.gitignore
push 시에 제외할 파일을 기록해 둔다.</p>
</li>
<li><p>package.json
사용설명서이다. 몇 번째 버전이고, 라이브러리나 프레임워크는 어떤 빌드를 사용했는지 기록해 두는 곳이다.</p>
</li>
<li><p>README.md
개발자들이 가장 먼저 읽게 될 첫 번째 친구, README 파일이다.</p>
</li>
<li><p>yarn.lock
위의 package.json 파일과 동일하나 어떤 버전의 라이브러리 / 프레임워크를 사용했는지 상세하게 기록된 파일이다. 열면 # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 라는 문구가 반긴다. 만지지 말자.</p>
</li>
</ol>
]]></description>
        </item>
    </channel>
</rss>