<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>kyung-baa.log</title>
        <link>https://velog.io/</link>
        <description>나는야 경바</description>
        <lastBuildDate>Thu, 05 Jan 2023 06:56:55 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>kyung-baa.log</title>
            <url>https://images.velog.io/images/kyung-baa/profile/4432b103-d960-432b-be7c-c475c2930958/social.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. kyung-baa.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/kyung-baa" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[getStaticPaths]]></title>
            <link>https://velog.io/@kyung-baa/getStaticPaths</link>
            <guid>https://velog.io/@kyung-baa/getStaticPaths</guid>
            <pubDate>Thu, 05 Jan 2023 06:56:55 GMT</pubDate>
            <description><![CDATA[<p><a href="https://velog.io/@mskwon/next-js-static-generation-fallback">https://velog.io/@mskwon/next-js-static-generation-fallback</a>
<a href="https://steadily-worked.tistory.com/604">https://steadily-worked.tistory.com/604</a></p>
<h2 id="사전렌더링-ssr">사전렌더링 SSR</h2>
<p>공식문서에서는 데이터가 있든 없든, 가능하다면 Static Generation을 사용할 것을 추천한다. 왜냐면 build time에 한 번 만들어지고나서 CDN에 의해 served 되는데, 이 경우는 매 요청시마다 페이지를 렌더링하는 SSR보다 더 빠르기 때문.. 예를 들면</p>
<p>Marketing pages (판매 페이지)
Blog posts (블로그 글)
E-commerce product listings (온라인 커머스 및 상품 나열)
스스로에게 물어봤을 때, 유저의 요청 이전에 이 페이지를 띄워야되는지? 가 맞다면 Static Generation을 쓰면 되고, 그게 아니라면 SSR을 쓰면 된다.</p>
<p>예를 들면, 지*<em>속적으로 업데이트되는 페이지의 경우 *</em>유저의 요청이 있기 전에 사전 렌더링을 할 수 없으므로 이 경우에 Static Generation은 좋은 아이디어가 아니다. 이 경우 두 가지 방법 중 하나를 사용해야 한다.
페이지의 일부 부분에 대해 사전 렌더링을 스킵하고 클라이언트 사이드의 JavaScript 또는 TypeScript를 사용할 수 있다.2) SSR을 사용하기
-&gt; 2. Server Side Rendering(바로아래)에서</p>
<p>1) Static Generation과 Clien Side Rendering(CSR)을 사용하기
2. Server Side Rendering(SSR)</p>
<p>서버 사이드 렌더링을 사용할 경우, 각 요청시 마다 페이지를 사전 렌더링한다. 페이지가 CDN에 의해 캐싱될 수 없으므로 Static Generation에 비해서는 더 느릴 것이다.
그렇지만, 사전에 렌더링된 페이지들은 항상 최신 상태를 유지한다.
For example, suppose that your page needs to pre-render frequently updated data (fetched from an external API). You can writegetServerSidePropswhich fetches this data and passes it toPagelike below:
만약 페이지가 (외부 API로부터 fetch해 오는) 업데이트되는 데이터를 항상 사전 렌더링해야 할 경우, 이 데이터를 받아와서 Page로 넘기는 getServerSideProps를 사용해야한다.</p>
<h2 id="getstaticpaths-반환-객체">getStaticPaths 반환 객체</h2>
<p>이 때, 어떤 path들에 대해서 정적 페이지 생성을 할지 정하는 getStaticPaths 함수는 반환 객체로 paths 키와 fallback 키를 반드시 포함시켜야한다.</p>
<p>pages/users/[id].js에서 getStaticPaths 함수가 아래와 같은 객체를 반환하면,</p>
<p>// getStaticPaths
return {
  paths: [
    { params: { id: &#39;1&#39; } },
    { params: { id: &#39;2&#39; } }
  ],
  fallback: ...
}
Next JS는 users/1, users/2 페이지를 빌드타임에 생성하게 된다.</p>
<p><strong>paths</strong>
어떤 path의 페이지들을 빌드 타임에 생성할지 정하는 배열이다.</p>
<p>paths 배열에서 각각의 params 값은 페이지 이름에 있는 파라미터와 일치해야한다.</p>
<p>여기서 주의할 점들은 다음과 같다.</p>
<p>만약 파일명이 pages/users/[userId].js 였다면, params 객체도 userId 키값을 가지고 있어야한다.
파일명이 pages/[...slug]와 같이 catch-all 라우트를 이용중인 경우, params 객체는 slug 배열을 가지고 있어야한다.
파일명이 pages/[[..slug]]와 같이 optional catch-all 라우트를 이용중인 경우, null / [] / undefined / false 값을 넣어주면 루트 라우트를 렌더링하게 된다.
fallback
빌드 타임에 생성해놓지 않은 path로 요청이 들어온 경우 어떻게 할지 정하는 boolean 또는 &#39;blocking&#39; 값이다.</p>
<p>false인 경우</p>
<p>getStaticPaths가 반환하지 않은 모든 path에 대해서 404 페이지를 반환한다.</p>
<p>아래와 같은 경우에 사용할 수 있다</p>
<p>적은 숫자의 path만 프리렌더링 해야하는 경우
새로운 페이지가 추가 될 일이 많지 않은 경우
→ 새로운 페이지가 자주 추가 된다면, 추가될때마다 다시 빌드해줘야한다
true인 경우</p>
<p>getStaticProps의 동작이 바뀌게 된다.</p>
<p>getStaticPaths가 반환한 path들은 빌드 타임에 HTML로 렌더링된다</p>
<p>이외의 path들에 대한 요청이 들어온 경우, 404 페이지를 반환하지 않고, 페이지의 &quot;fallback&quot; 버전을 먼저 보여준다</p>
<p>백그라운드에서 Next js가 요청된 path에 대해서 getStaticProps 함수를 이용하여 HTML 파일과 JSON 파일을 만들어낸다</p>
<p>백그라운드 작업이 끝나면, 요청된 path에 해당하는 JSON 파일을 받아서 새롭게 페이지를 렌더링한다. 사용자 입장에서는 [ fallback → 풀 페이지 ]와 같은 순서로 화면이 변하게된다.</p>
<p>새롭게 생성된 페이지를 기존의 빌드시 프리렌더링 된 페이지 리스트에 추가한다. 같은 path로 온 이후 요청들에 대해서는 이때 생성한 페이지를 반환하게된다.</p>
<p>&quot;fallback&quot; 상태일 때 보여줄 화면은 next/router의 router.isFallback 값 체크를 통해서 조건 분기하면 된다. 이때 페이지 컴포넌트는 props로 빈값을 받게된다.</p>
<p>// pages/posts/[id].js
import { useRouter } from &#39;next/router&#39;</p>
<p>function Post({ post }) {
  const router = useRouter()</p>
<p>  // If the page is not yet generated, this will be displayed
  // initially until getStaticProps() finishes running
  if (router.isFallback) {
    return <div>Loading...</div>
  }</p>
<p>  // Render post...
}
아래와 같은 경우에 사용할 수 있다</p>
<p>데이터에 의존하는 정적 페이지를 많이 가지고 있으나, 빌드 시에 모든 페이지를 생성하는건 너무나 큰 작업일 때
몇몇 페이지들만 정적으로 생성하게 하고, fallback 옵션을 true로 설정해주면 이후 요청이 오는 것에 따라서 정적 페이지들을 추가하게 된다
→ 빌드 시간도 단축하고, 대부분 사용자들의 응답 속도도 단축할 수 있다
&#39;blocking&#39;일 경우</p>
<p>true일 경우와 비슷하게 동작하지만, 최초 만들어놓지않은 path에 대한 요청이 들어온 경우 fallback 상태를 보여주지 않고 SSR처럼 동작한다. 이후 true 옵션과 같이 기존의 정적 페이지 리스트에 새로 생성한 페이지를 추가한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[netlify 배포 오류]]></title>
            <link>https://velog.io/@kyung-baa/netlify-%EB%B0%B0%ED%8F%AC-%EC%98%A4%EB%A5%98</link>
            <guid>https://velog.io/@kyung-baa/netlify-%EB%B0%B0%ED%8F%AC-%EC%98%A4%EB%A5%98</guid>
            <pubDate>Tue, 29 Nov 2022 07:41:11 GMT</pubDate>
            <description><![CDATA[<p>netlify로 정적인 사이트 배포하는건 쉽다면서?
껄껄 해볼까 하고 얼마전에 만든 todolist를 배포해보았다.
실패</p>
<p> <strong>첫번째 방법</strong>
 Build command를 yarn build에서 CI= yarn build로 변경
 실패 깔끔하게 실패 </p>
<p> <strong>두번째 방법</strong>
Deploy log를 보니까 TodoList.module.css를 찾을 수 없다고 했다.
<img src="https://velog.velcdn.com/images/kyung-baa/post/3248652f-e7a2-4aaa-a012-f7e23f2e851f/image.png" alt="">
왜? 이해가 안되네 </p>
<p>git에 들어가서 보니<img src="https://velog.velcdn.com/images/kyung-baa/post/be55235f-52c3-4ef7-a72d-69d3c624b745/image.png" alt="">
TodoLIst.module.css라고 자랑스럽게 올려두었다.</p>
<p>git은 대소문자 구별을 못한다고 한다.
모든건 내잘못 
<code>git config core.ignorecase false</code>로 무시하지 말아달라고 한다음 다시 깃에 푸시했다. </p>
<p>그리고 지금은 배포되는지 기다리는중 엄청 다 해결한것처럼 썼는데 만약 안되면 어떻게 하지 ..... 그럼 또 다른 방법을 찾아봐야지 뭐</p>
<p>오 된다 헤헤
<a href="https://resplendent-daffodil-d96309.netlify.app/">https://resplendent-daffodil-d96309.netlify.app/</a>
소박한 투두리스트 완성 </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[e.preventDefault()와 e.stopPropagation() ]]></title>
            <link>https://velog.io/@kyung-baa/e.preventDefault%EC%99%80-e.stopPropagation</link>
            <guid>https://velog.io/@kyung-baa/e.preventDefault%EC%99%80-e.stopPropagation</guid>
            <pubDate>Wed, 23 Nov 2022 04:15:53 GMT</pubDate>
            <description><![CDATA[<p>심심하기도 하고 그래서 간단한 todolist 다시 만들다가 엉뚱한 실수를 반복했다. </p>
<pre><code class="language-javascript">  const handleModifySubmit = (e) =&gt; {
    e.preventDefault();
    onUpdate({ ...todo, text: modifyText });
    handleModifyStatus();
  };

{modifyStatus ? (
        &lt;li&gt;
          &lt;input
            type=&quot;checkbox&quot;
            id=&quot;checkbox&quot;
            checked={status === &quot;completed&quot;}
            onChange={handleStatus}
          /&gt;
          &lt;label htmlFor=&quot;checkbox&quot;&gt;{text}&lt;/label&gt;

          &lt;button onClick={handleDelete}&gt;
            &lt;AiTwotoneDelete size=&quot;20px&quot; /&gt;
          &lt;/button&gt;

          &lt;button onClick={handleModifyStatus}&gt;
            &lt;AiFillEdit size=&quot;20px&quot; /&gt;
          &lt;/button&gt;
        &lt;/li&gt;
      ) : (
        &lt;form&gt;
          &lt;input
            type=&quot;text&quot;
            onChange={handleModifyText}
            defaultValue={text}
          &gt;&lt;/input&gt;
          &lt;button
            onClick={handleModifySubmit}
            disabled={modifyText.trim() !== &quot;&quot; ? false : true}
          &gt;
            &lt;AiFillEdit /&gt;
          &lt;/button&gt;
        &lt;/form&gt;
      )}</code></pre>
<p>아니 수정하려고 수정완료 버튼을 클릭하면 자꾸 새로고침되서 리렌더링되길래
무슨일이람하고 고민하다가 갑자기 아 <code>e.preventDefault()</code>를 안해준것이 떠올랐다. 기본적인 내용이었는데 왜 벌써 잊었을까 이럴때는 블로그에 적어야지 했는데 전에 <code>e.preventDefault();</code>, <code>e.stopPropagation()</code> 두개를 가끔씩 헷깔려했던 기억이 나서 두개를 비교해보았다.</p>
<h1 id="eventpreventdefault">event.preventDefault()</h1>
<p><code>e.preventDefault()</code>의 역할은 기본으로 정의된 이벤트를 작동하지 못하게하는 메서드이다.
예를 들어 <code>&lt;a&gt;</code>태그같이 페이지 이동을 해주는 태그들에게 <code>e.preventDefault()</code>메서드를 실행시켜주면 페이지 이동을 막아준다. </p>
<h1 id="eventstoppropagation">event.stopPropagation()</h1>
<p>전에 밥모건프로젝트 당시 모달창을 만들었다. 세상에 닫기 버튼과 모달창 외부의 화면을 클릭했을때에만 닫혀야하는데 모달창 내부만 클릭해도 닫혀버려서 당황했었다. 
이건 전에도 기재했던 이벤트 버블링 (자식element에서 발생한 이벤트가 부모 element순으로 전달되는 현상) 인데, 얘를 막아주려면 사용하는게 <code>event.stopPropagation();</code>메서드이다. 
이벤트의 전파는 막아주지만 그렇다고 해서 기본이벤트를 막아주진 않는다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[SyntaxError 해결]]></title>
            <link>https://velog.io/@kyung-baa/SyntaxError-%ED%95%B4%EA%B2%B0</link>
            <guid>https://velog.io/@kyung-baa/SyntaxError-%ED%95%B4%EA%B2%B0</guid>
            <pubDate>Tue, 25 Oct 2022 03:43:15 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>SyntaxError: unknown: Namespace tags are not supported by default. React&#39;s JSX doesn&#39;t support namespace tags. You can turn on the &#39;throwIfNamespace&#39; flag to bypass this warning.</p>
</blockquote>
<p>포트폴리오 작업중 svg파일을 import하는 과정에서 위와 같은 오류가 생겼다.</p>
<p>벡터 이미지 다운로드 후 삽입 시 특정 태그에서만 발생하는 SyntaxError로, 해당 부분을 아래처럼 수정해주어야 한다. JSX 영역에 있으므로 SVG 태그는 camelCase로 작성되어야 한다고 한다.</p>
<blockquote>
<p>  sketch:type -&gt; sketchType
    xmlns:xlink -&gt; xmlnsXlink
    xlink:href  -&gt; xlinkHref</p>
</blockquote>
<p>나는 이렇게 수정하지 않고 <a href="https://www.svgminify.com/">https://www.svgminify.com/</a> 여기에 svg파일을 수정하였다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Recoil : Duplicate atom key]]></title>
            <link>https://velog.io/@kyung-baa/Recoil-Duplicate-atom-key</link>
            <guid>https://velog.io/@kyung-baa/Recoil-Duplicate-atom-key</guid>
            <pubDate>Tue, 04 Oct 2022 07:43:38 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p><a href="https://github.com/facebookexperimental/Recoil/issues/733">https://github.com/facebookexperimental/Recoil/issues/733</a></p>
</blockquote>
<h1 id="recoil--duplicate-atom-key">Recoil : Duplicate atom key</h1>
<h2 id="오류">오류</h2>
<p><img src="https://velog.velcdn.com/images/kyung-baa/post/c82d58b8-e9e1-4dbb-a99e-a66875741863/image.png" alt="">
사이드 프로젝트를 진행하던 중 또 생소한 오류를 만났다.
recoil을 처음 사용해보니 당연한가 싶기도 하지만 이렇게 써놓으면 나중에 금방 찾겠지...딱히 뭔가 동작하긴 하던데 역시 찜찜해서 찾아보니 생각보다 금방 찾을 수 있었다. 
Next.js 개발 중 파일이 변경되면 다시 빌드되는 과정에서 atom으로 만든 state가 재선언된다. key는 항상 고유값을 가져야하는데 재선언되는 과정에서 이미 key로 선언된 값을 key로 사용해서 문제가 발생한다.</p>
<h2 id="해결">해결</h2>
<h4 id="난수를-생성해주는-uuid모듈-설치">난수를 생성해주는 uuid모듈 설치</h4>
<p><code>npm i --save-dev @types/uuid</code></p>
<blockquote>
<p><a href="https://www.npmjs.com/package/uuid">https://www.npmjs.com/package/uuid</a></p>
</blockquote>
<h4 id="key에-생성한-난수-넣기">key에 생성한 난수 넣기</h4>
<pre><code class="language-typescript">import { atom } from &quot;recoil&quot;;
import { v4 as uuidv4 } from &#39;uuid&#39;;

export const UserSelectState = atom({
  key: `userState/${uuidv4()}`,
  default: {
    userLocation: &quot;&quot;,
    userTemp: &quot;0&quot;,
  },
});</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[arrow function {} 괄호]]></title>
            <link>https://velog.io/@kyung-baa/arrow-function-%EA%B4%84%ED%98%B8</link>
            <guid>https://velog.io/@kyung-baa/arrow-function-%EA%B4%84%ED%98%B8</guid>
            <pubDate>Fri, 23 Sep 2022 03:17:52 GMT</pubDate>
            <description><![CDATA[<p>어우 뭐야 난 왜 이게 또 긴가민가 하는거야 </p>
<p>const add:Add = (a,b) =&gt; a+b 를 함수로 풀면 다음과 같게 된다.</p>
<pre><code>function add(a, b) {
return (a+b)
}</code></pre><p>const add:Add = (a,b) =&gt; {a+b} 를 함수로 풀면 다음과 같게 된다.</p>
<pre><code>function add(a, b) {
a+b;
}</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[wanted Week 4-1 ]]></title>
            <link>https://velog.io/@kyung-baa/wanted-Week-4-1</link>
            <guid>https://velog.io/@kyung-baa/wanted-Week-4-1</guid>
            <pubDate>Tue, 20 Sep 2022 05:35:31 GMT</pubDate>
            <description><![CDATA[<h4 id="quertystring-vs-state">QuertyString vs state</h4>
<p>state로 관리할 경우 새로고침 할때 초기화됨
ux적인 측면에서 쿼리스트링이 더 좋다. 주소창에서 복사할 경우 다른 페이지에서 붙여넣었을때 그대로 사용 가능하다. 페이지 스크롤 할때 백페이지쯤 봤을때 어떤 게시글을 보고 다시 되돌아갔을 때, 
모든 정보가 초기화되어있다면 사용자가 너무 힘들다. 구글에서도 검색했을 때, 그 주소 검색 정보를URI
에 담고 있다.</p>
<h4 id="함수명-작명하기">함수명 작명하기</h4>
<p>함수의 기능이 뭘 하는지 알아보기 쉽도록 해야함 
onChange ={onChange} =&gt; 이런식으로 하면 코드를 해석을 매번 해야함 
언제 실행되는지가 아니라 무슨 동작을 하는지가 중요함.</p>
<h4 id="id속성">ID속성</h4>
<p>리액트의 요소에 ID속성을 부여해도 될까? 
안된다. 아이디는 그 전체에서 유일한 속성이다 리액트는 재사용이 중요한데 같은 document에서 사용할 수 없다. ID속성일 경우 독립적으로도 사용 불가하다. 
꼭 사용해야할 경우에는 class명으로 사용할것 </p>
<h4 id="불필요한-연산">불필요한 연산</h4>
<pre><code class="language-javascript">const paginationList = [...new Array(pageLength)];</code></pre>
<p>-&gt;</p>
<pre><code class="language-javascript">const paginationList =new Array;</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[SSR, CSR]]></title>
            <link>https://velog.io/@kyung-baa/SSR-CSR</link>
            <guid>https://velog.io/@kyung-baa/SSR-CSR</guid>
            <pubDate>Thu, 15 Sep 2022 05:09:43 GMT</pubDate>
            <description><![CDATA[<h1 id="ssr--server-side-rendering">SSR | Server Side Rendering</h1>
<p>*<em>SSR | Server Side Rendering
말 그대로 서버쪽에서 렌더링 준비를 끝마친 상태로 클라이어트에 전달하는 방식
*</em>
<img src="https://velog.velcdn.com/images/kyung-baa/post/cf3115e3-04da-4f18-9f40-791ae44f7b59/image.png" alt=""></p>
<p>User가 Website 요청을 보냄.
Server는 &#39;Ready to Render&#39;. 즉, 즉시 렌더링 가능한 html파일을 만든다.
(리소스 체크, 컴파일 후 완성된 HTML 컨텐츠로 만든다.)
클라이언트에 전달되는 순간, 이미 렌더링 준비가 되어있기 때문에 HTML은 즉시 렌더링 된다. 그러나 사이트 자체는 조작 불가능하다. (Javascript가 읽히기 전이다.)
클라이언트가 자바스크립트를 다운받는다.
다운 받아지고 있는 사이에 유저는 컨텐츠는 볼 수 있지만 사이트를 조작 할 수는 없다. 이때의 사용자 조작을 기억하고 있는다.
브라우저가 Javascript 프레임워크를 실행한다.
JS까지 성공적으로 컴파일 되었기 때문에 기억하고 있던 사용자 조작이 실행되고 이제 웹 페이지는 상호작용 가능해진다.
<img src="https://velog.velcdn.com/images/kyung-baa/post/aa34a178-bcf1-4fa0-93db-eb2355d201df/image.png" alt=""></p>
<blockquote>
<p>서버에서 이미 렌더 가능한 상태로 클라이언트에 전달되기 때문에 JS가 다운로드 되는동안 사용자는 무언가를 보고 있을 수 있다. </p>
</blockquote>
<h1 id="csr--client-side-rendering">CSR | Client Side Rendering</h1>
<p><strong>말 그대로 SSR과 달리 렌더링이 클라이언트 쪽에서 일어난다.
즉, 서버는 요청을 받으면 클라이언트에 HTML과 JS를 보내준다. 클라이언트는 그것을 받아 렌더링을 시작한다.</strong></p>
<blockquote>
</blockquote>
<ol>
<li>User가 Website 요청을 보냄.</li>
<li>CDN이 HTML 파일과 JS로 접근할 수 있는 링크를 클라이언트로 보낸다.</li>
</ol>
<p><strong>CDN : aws의 cloudflare를 생각하면 됨. 엔드 유저의 요청에 &#39;물리적&#39;으로 가까운 서버에서 요청에 응답하는 방식</strong></p>
<ol start="3">
<li>클라이언트는 HTML과 JS를 다운로드 받는다.
(이때 SSR과 달리 유저는 아무것도 볼 수 없다.😡)</li>
</ol>
<p>클라이언트는 HTML과 JS를 다운로드 받는다.
(이때 SSR과 달리 유저는 아무것도 볼 수 없다.😡)
생략
다운이 완료된 JS가 실행된다. 데이터를 위한 API가 호출된다.
(이때 유저들은 placeholder를 보게된다. )
서버가 API로부터의 요청에 응답한다.
API로부터 받아온 data를 placeholder 자리에 넣어준다. 이제 페이지는 상호작용이 가능해진다.</p>
<p><img src="https://velog.velcdn.com/images/kyung-baa/post/493bf0da-50b8-4750-9a55-e1d7e5ba2f61/image.png" alt=""></p>
<h1 id="각각의-차이">각각의 차이</h1>
<h2 id="1-웹페이지를-로딩하는-시간">1) 웹페이지를 로딩하는 시간</h2>
<p>웹 페이지 로딩의 종류는 두 가지로 나눌 수 있다.
하나는 웹 사이트의 가장 첫 페이지를 로딩하는 것.
다른 하나는 나머지를 로딩하는 것</p>
<p><strong>첫 페이지 로딩시간.</strong>
CSR의 경우 HTML, CSS와 모든 스크립트들을 한 번에 불러온다. 반면 SSR은 필요한 부분의 HTML과 스크립트만 불러오게 된다. 따라서 평균적으로 SSR이 더 빠르다.</p>
<p><strong>나머지 로딩 시간</strong>
첫 페이지를 로딩한 후, 사이트의 다른 곳으로 이동하는 식의 동작을 가정하자. CSR은 이미 첫 페이지 로딩할 때 나머지 부분을 구성하는 코드를 받아왔기 때문에 빠르다.
반면, SSR은 첫 페이지를 로딩한 과정을 정확하게 다시 실행한다. 그래서 더 느리다.</p>
<h2 id="2-seo-대응">2) SEO 대응</h2>
<p>검색 엔진은 자동화된 로봇인 &#39;크롤러&#39;로 웹 사이트들을 읽는다. CSR은 자바스크립트를 실행시켜 동적으로 컨텐츠가 생성되기 때문에 자바스크립트가 실행 되어야 meatadata가 바뀌었다.
(이전 크롤러들은 자바스크립트를 실행시키지 않았었기에 SEO 최적화가 필수적이었다. 구글이 그 트렌드를 바꾸고 있다고 한다.)</p>
<p>SSR은 애초에 서버 사이드에서 컴파일되어 클라이언트로 넘어오기 때문에 크롤러에 대응하기 용이하다.</p>
<p><strong>3) 서버 자원 사용</strong>
SSR이 서버 자원을 더 많이 사용한다. 매번 서버에 요청을 하기 때문이다.</p>
<h1 id="사용권장-예시">사용권장 예시</h1>
<h2 id="ssr">SSR</h2>
<p>네트워크가 느릴 때 😓
(CSR은 한번에 모든 것을 불러오지만 SSR은 각 페이지마다 나눠불러오기 때문)
SEO(serach engine optimization : 검색 엔진 최적화)가 필요할 때.
최초 로딩이 빨라야하는 사이트를 개발 할 때
메인 스크립트가 크고 로딩이 매우 느릴 때</p>
<blockquote>
<p>CSR은 메인스크립트가 로딩이 끝나면 API로 데이터 요청을 보낸다. 하지만 SSR은 한번의 요청에 아예 렌더가 가능한 페이지가 돌아온다.</p>
</blockquote>
<p>웹 사이트가 상호작용이 별로 없을 때.</p>
<h2 id="csr">CSR</h2>
<p>네트워크가 빠를 때
서버의 성능이 좋지 않을 때
사용자에게 보여줘야 하는 데이터의 양이 많을 때.
(로딩창을 띄울 수 있는 장점이 있다.)
메인 스크립트가 가벼울 때
SEO 따윈 관심 없을 때😤
웹 어플리케이션에 사용자와 상호작용할 것들이 많을 때. (아예 렌더링 되지 않아서 사용자의 행동을 막는 것이 경험에 오히려 유리함.)</p>
<blockquote>
<p><a href="https://velog.io/@vagabondms/%EA%B8%B0%EC%88%A0-%EC%8A%A4%ED%84%B0%EB%94%94-SSR%EA%B3%BC-CSR%EC%9D%98-%EC%B0%A8%EC%9D%B4">https://velog.io/@vagabondms/기술-스터디-SSR과-CSR의-차이</a></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[Webpack, Babel, Polyfill]]></title>
            <link>https://velog.io/@kyung-baa/Webpack-Babel-Polyfill</link>
            <guid>https://velog.io/@kyung-baa/Webpack-Babel-Polyfill</guid>
            <pubDate>Thu, 15 Sep 2022 04:24:11 GMT</pubDate>
            <description><![CDATA[<h1 id="webpack">Webpack</h1>
<p><img src="https://velog.velcdn.com/images/kyung-baa/post/a36a464d-8c8a-4f8c-bd3c-45d848310fb5/image.png" alt=""></p>
<blockquote>
<p>웹팩은 여러개의 파일을 하나로 합쳐주는 모듈 번들러</p>
</blockquote>
<p>웹팩(Webpack)은 의존성을 분석해 모듈을 번들(여러 개를 하나로 묶어주는)시켜주는 역할을 한다. 프로젝트를 개발하다보면 수 많은 라이브러리들을 사용하게 되는데 빌드(build)라는 과정을 통해 하나의 파일로 짠!하고 만들어 준다.</p>
<h1 id="babel">Babel</h1>
<blockquote>
<p>바벨은 트랜스파일러로, 모던 자바스크립트 코드를 구 표준을 준수하는 코드로 바꿔준다. Babel은 구 브라우저에서도 최신자바스크립트 코드를 작동하도록 변환해준다.</p>
</blockquote>
<p>세상 사람들은 정말 다양한 종류의 버전의 브라우저를 사용하고 있다. 이건 누가 일괄 업데이트한다고 해결되는 문제도 아니라서 어떤 특정 버전을 딱 맞추기 어렵다. 대부분의 업체에서 최신 버전의 브라우저를 권장하지만 생각보다 이런 일에 관심없는 사람도 많고, 일례로 쇼핑몰과 같이 사람들이 온라인에서 돈을 쓰면서 매출을 올리는 회사들은 구형 브라우저를 쓰는 사람들을 그냥 무시하고 서비스 개발을 진행할수가 없다. 최대한 그 사람들이 불편없이 돈을 쓰고 가도록 만들어 줘야 한다. 하지만 개발자들은 어떤가. 수 십년 지난 브라우저에서만 도는 기능을 위해 지저분한 코드를 작성해야 하거나 최신 기능을 포기해야 하는 일까지 생긴다. 코드가 복잡해지니 당연히 유지보수는 어려워진다. 이런 이유로 개발자들은 최신의 코드를 쓰면서 최대한 많은 사람들이 사용하는데 불편함없이 만들어 주는게 바벨이다. 바벨은 최신 자바스크립트 문법을 구형 브라우저에서도 돌 수 있도록 코드 자체를 변환시킨다.</p>
<h1 id="polyfill">Polyfill</h1>
<p>Babel은 컴파일-타임에 코드를 구 브라우저에서 사용가능하게 변환하지만, ES6이상에서 새롭게 추가된 Promise, Map, Set 같은 전역객체들이나 String.padStart등 전역 객체에 추가된 메서드등 컴파일-타임의 코드변환으로는 해결하기 어렵기 때문에 폴리필(polyfill)이 필요하다.
즉, 구 브라우저에서 최신 자바스크립트 코드를 사용하기 위해 Babel을 이용했지만, 일부 기능들은 polyfill로 추가해줘야한다. </p>
<blockquote>
<p>참고
<a href="https://devlog.jwgo.kr/2018/12/03/webpack-babel-react/">https://devlog.jwgo.kr/2018/12/03/webpack-babel-react/</a></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[브라우저 렌더링 과정]]></title>
            <link>https://velog.io/@kyung-baa/%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80-%EB%8F%99%EC%9E%91-%EC%9B%90%EB%A6%AC</link>
            <guid>https://velog.io/@kyung-baa/%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80-%EB%8F%99%EC%9E%91-%EC%9B%90%EB%A6%AC</guid>
            <pubDate>Tue, 13 Sep 2022 05:09:43 GMT</pubDate>
            <description><![CDATA[<h2 id="브라우저-동작-원리">브라우저 동작 원리</h2>
<h2 id="브라우저의-주요-기능">브라우저의 주요 기능</h2>
<p>브라우저의 주요 기능은 사용자가 선택한 자원을 서버에 요청하고 브라우저의 표시하는 것이다. 자원은 보통 HTML문서지만 PDF 혹은 이미지 또는 다른 형태일 수 있다. 자원의 주소는 <strong>URI(Uniform Resource Identifier)</strong> 에 의해 정해진다.</p>
<p>브라우저는 HTML과 CSS명세에 따라 HTML파일을 해석해서 표시하는데 이는 웹 표준화 기구 W3C(World Wide Web Consortium)에서 정한다. 과거에는 일부만 이 명세에 따르고 독자적인 방법으로 확장하면서 웹 제작자가 호환성 문제를 겪었지만 최근에는 대부분 이 명세를 따른다. </p>
<blockquote>
</blockquote>
<p>웹 브라우저는 동기(Synchronous)적으로 (HTML + CSS), Javascript 언어를 해석하여 내용을 화면에 보여주는 응용 소프트웨어.</p>
<h2 id="브라우저의-사용자-인터페이스-요소">브라우저의 사용자 인터페이스 요소</h2>
<ul>
<li>URI를 입력하는 주소 표시 줄</li>
<li>이전 버튼, 다음 버튼</li>
<li>북마크</li>
<li>새로 고침 버튼, 현재 문서 로드 정지 버튼</li>
<li>홈 버튼</li>
</ul>
<p>브라우저의 사용자 인터페이스는 표준 명세가 없음에도 서로를 모방하여 오늘날에 이르렀다. (파이어폭스의 다운로드 관리자와 같이 브라우저에 특화된 기능도 있음)</p>
<h2 id="브라우저의-기본구조">브라우저의 기본구조</h2>
<p><img src="https://velog.velcdn.com/images/kyung-baa/post/92cc78f4-f43c-4fcd-a0a2-ec627e3623b5/image.png" alt=""></p>
<ul>
<li><p>*<em>사용자 인터페이스 *</em>
주소 표시줄, 이전 다음버튼 북마크 메뉴 등 요청한 페이즈를 보여주는 창을 제외한 나머지 부분</p>
</li>
<li><p><strong>브라우저 엔진</strong>
사용자 인터페이스와 렌더링 엔진 사이의 동작을 제어</p>
</li>
<li><p><strong>렌더링 엔진</strong>
요청한 콘텐츠를 표시 HTML요청시 HTML과 CSS를 파싱하여 화면에 표시</p>
</li>
<li><p><strong>통신</strong>
HTTP요청과 같은 네트워크 호출에 사용된다. 플랫폼 독립적인 인터페이스이며 각 플랫폼 하부에서 실행됨</p>
</li>
<li><p><strong>UI백엔드</strong> - 콤보 박스와 창 같은 기본 장치를 그린다. 플랫폼에서 명시하지 않은 일반적인 인터페이스 체계를 사용한다.</p>
</li>
<li><p><strong>자바스크립트 해석기</strong>
자바스크립트 코드를 해석하고 실행</p>
</li>
<li><p><strong>자료 저장소</strong>
자료를 저장하는 계층. 쿠키나, 세션, 로컬스토리지등 브라우저 메모리를 활용하여 저장하는 영역이다.</p>
</li>
</ul>
<h2 id="렌더링-엔진">렌더링 엔진</h2>
<blockquote>
<p>렌더링 엔진은 HTML, XML, 이미지 등 요청받은 내용을 브라우저 화면에 표시하는 엔진</p>
</blockquote>
<p>각 브라우저마다 렌더링 엔진이 다르기 때문에 같은 페이지가 다르게 보이는 경우가 있다.</p>
<h3 id="렌더링-엔진의-종류">렌더링 엔진의 종류</h3>
<ul>
<li>Blink - 크롬, 오페라 </li>
<li>Webkit - 사파리</li>
<li>Trident - 익스플로어</li>
<li>EdgeHTML - 마이크로소프트 엣지 </li>
</ul>
<p>렌더링 엔진은 좀 더 나은 사용자 경험을 위해 가능하면 빠르게 내용을 표시한다. 그래서 일련의 과정들이 동기적으로 진행되지 않는다.
HTML을 파싱할 때까지 기다리지 않고 렌더트리 배치와 그리기 과정을 시작한다. </p>
<h3 id="렌더링-엔진-동작-과정">렌더링 엔진 동작 과정</h3>
<p>렌더링 엔진은 서버로부터 응답받은 HTMl 문서를 얻는것으로 시작한다. </p>
<h4 id="parsing--html과-css파일을-파싱해서-각-tree를-만든다">Parsing | HTML과 CSS파일을 파싱해서 각 Tree를 만든다</h4>
<p>브라우저가 페이지를 렌더링하려면 가장 먼저 받아온 HTML과 파일을 해석해야한다. Parsing단계는 HTML파일을 해석하여 DOM(Document Object Model) Tree를 구성하는 단계이다.</p>
<p>파싱 중 HTML에 CSS가 포함되어 있다면 CSSOM(CSS Object Model) Tree 구성 작업도 함께 진행한다.
<img src="https://velog.velcdn.com/images/kyung-baa/post/56bd5d42-a3e5-4b7b-8c04-06badc3545c7/image.png" alt=""></p>
<p>DOM은 마크업과 1:1의 관계이다. 마크업은 HTML Hyper Text Markup Language의 Markup을 말한다.</p>
<h4 id="style--두-tree를-결함하여-rendering-tree를-만든다">Style | 두 Tree를 결함하여 Rendering Tree를 만든다</h4>
<p>Style 단계에서는 Parsing 단계에서 생성된 DOM Tree와 CSSOM Tree를 매칭시켜서 Render Tree를 구성한다. Render Tree는 실제로 화면에 그려질 Tree이다. 
표시해야할 순서 문서의 시각적인 구성 요소로써 올바른 순서로 내용을 그려낼 수 있도록 하기위한 목적임
렌더러와 DOM은 1:1대응 관계가 아니다. 시각적으로 보이지 않는 HTML태그들은(메타태그나 diplay:none head등) 제외된다. 즉 렌더트리는 페이지를 렌더링하는데 필요한 노드만 포함함. </p>
<h4 id="layout--rendering-tree에서-각-노드의-위치와-크기-계산">Layout | Rendering Tree에서 각 노드의 위치와 크기 계산</h4>
<p>Layout 단계에서는 Render Tree를 화면에 어떻게 배치해야 할 것인지 노드의 정확한 위치와 크기를 계산한다.
루트부터 노드를 순회하면서 노드의 정확한 크기와 위치를 계산하고 Render Tree에 반영한다. 만약 크기 값을 %로 지정하였다면, Layout 단계에서 % 값을 계산해서 픽셀 단위로 변환한다.</p>
<p> <strong>여기서의 노드는 HTML에 p,div태그등을 말한다.</strong></p>
<h4 id="paint--계산된-값을-이용해-각-노드를-화면상의-실제-픽셀로-변환하고-레이어를-만든다">Paint | 계산된 값을 이용해 각 노드를 화면상의 실제 픽셀로 변환하고, 레이어를 만든다</h4>
<p>Paint 단계에서는 Layout 단계에서 계산된 값을 이용해 Render Tree의 각 노드를 화면상의 실제 픽셀로 변환한다. 이때 픽셀로 변환된 결과는 하나의 레이어가 아니라 여러 개의 레이어로 관리된다.
당연한 말이지만 스타일이 복잡할수록 Paint 시간도 늘어난다. 예를 들어, 단색 배경의 경우 시간과 작업이 적게 필요하지만, 그림자 효과는 시간과 작업이 더 많이 필요하다.</p>
<h4 id="composite--레이어를-합성하여-실제-화면에-나타낸다">Composite | 레이어를 합성하여 실제 화면에 나타낸다</h4>
<p>Composite 단계에서는 Paint 단계에서 생성된 레이어를 합성하여 실제 화면에 나타낸다. 우리는 화면에서 웹 페이지를 볼 수 있다.</p>
<h4 id="javascript-해석기엔진">Javascript 해석기(엔진)</h4>
<p>HTML을 파싱하는 도중 Script 태그를 만나게되면 Script 코드를 실행을 하기위해 Javascript 엔진으로 제어 권한을 넘긴다. Javascript 엔진이 일을 다 끝내면 다시 DOM Tree를 구축한다.  Script 태그를 중간에 넣을시 DOM Tree를 구축 하는 도중 Javascript 엔진이 실행이되고 중간에 DOM Tree를 구축 하다 중지하고. Javascript 엔진이 기계어 컴파일까지 완료가 된후 다시 DOM Tree를 구축합니다.</p>
<h5 id="javascript-위치">javascript 위치</h5>
<ul>
<li><strong>body요소의 가장 하단</strong>
Dom이 완성되지 않은 상태에서 자바스크립트가 DOM엔진을 조작하면 에러가 발행함
HTML요소들이 스크립트 로딩 지연으로 인해 렌더링에 지장을 받지않아 로딩시간 단축</li>
</ul>
<h5 id="하단에-두고-싶지-않다면">하단에 두고 싶지 않다면</h5>
<p><strong>async</strong>
<code>javascript &lt;script async src=&quot;script.js&quot;&gt;</code>
<img src="https://velog.velcdn.com/images/kyung-baa/post/4dedf732-3f2d-4609-b285-c8b4af452cfb/image.png" alt=""></p>
<p>script태그를 만나도 html 파싱이 중단되지 않는다. script 로드와 html parsing이 함께 이루어지다가 script 로드가 끝나면 script가 실행되는 시점에 html parsing이 잠시 중단되고 실행이 끝나면 html parsing이 재개된다.</p>
<p><strong>defer</strong>
<code>javascript &lt;script defer src=&quot;script.js&quot;&gt;</code>
<img src="https://velog.velcdn.com/images/kyung-baa/post/149ad9f5-482e-417f-9c23-a3cbe1e93ad9/image.png" alt="">
 script 태그를 만나도 script 로드의 시작부터 끝까지 html parsing이 중단되지 않으며 html parsing이 끝나고 난 뒤에야 script가 실행</p>
<blockquote>
<p>참고
<a href="https://d2.naver.com/helloworld/59361">https://d2.naver.com/helloworld/59361</a>
<a href="https://bbangson.tistory.com/87">https://bbangson.tistory.com/87</a>
<a href="https://velog.io/@takeknowledge/script-%ED%83%9C%EA%B7%B8%EB%8A%94-%EC%96%B4%EB%94%94%EC%97%90-%EC%9C%84%EC%B9%98%ED%95%B4%EC%95%BC-%ED%95%A0%EA%B9%8C%EC%9A%94">https://velog.io/@takeknowledge/script-태그는-어디에-위치해야-할까요</a></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[원티드 2-1]]></title>
            <link>https://velog.io/@kyung-baa/%EC%9B%90%ED%8B%B0%EB%93%9C-2-1</link>
            <guid>https://velog.io/@kyung-baa/%EC%9B%90%ED%8B%B0%EB%93%9C-2-1</guid>
            <pubDate>Tue, 06 Sep 2022 05:54:56 GMT</pubDate>
            <description><![CDATA[<h2 id="과제-리뷰">과제 리뷰</h2>
<h3 id="커밋-히스토리">커밋 히스토리:</h3>
<p>세부내용 기입 ( 왜는 필수 어떻게는 코드를 보면 알수 있다.)
동일한 커밋일경우 리베이스를 통한 스쿼시를 사용해서 커밋 메세지를 정리해야한다. 
<img src="https://velog.velcdn.com/images/kyung-baa/post/785167d3-348e-43aa-9da0-9688fa280078/image.png" alt=""></p>
<p>이런식으로 해야함</p>
<h3 id="스타일드-컴포넌트의-위치">스타일드 컴포넌트의 위치</h3>
<p><img src="https://velog.velcdn.com/images/kyung-baa/post/a15601ca-e6e6-4a9b-917a-34a07d07b9eb/image.png" alt="">
이런식으로 스타일 선언부가 위에 있으면 다른 사람이 읽기 힘들다. 
기능에 관해 궁금해서 확인하는데 비교적 덜 중요한 스타일이 위에 있는것 보다는 아래에 있어야한다. 
회사마다 컨벤션에 따라 위에 선언되는 경우도 있긴하지만 보통은 핵심
적인 내용이 위에 있어야한다.
상수데이터도 마찬가지로 컴포넌트 하단에 있는것이 좋다.</p>
<blockquote>
<p>?? 
css in js style을 컴포넌트 내 style.js로 만들어서 export로 사용하는 경우도 많던데 이 경우와 한 컴포넌트에 있는 것과 차이는 어떤 차이가 있을까요. 
두개의 차이는 없다 회사의 컨벤션 차이임. 멘토님은 한파일안에 스타일이 있는 부분을 선호한다. 그래도 속한 회사나 팀의 컨벤션을 따름 </p>
</blockquote>
<h3 id="공백활용">공백활용</h3>
<p><img src="https://velog.velcdn.com/images/kyung-baa/post/4a0e6a7f-434d-4154-81cb-760cbb5be1f2/image.png" alt="">
스테이트 부분과 리턴문 사이는 공백이 있으면 가독성이 훨씬 좋아진다. 
<img src="https://velog.velcdn.com/images/kyung-baa/post/fa502a37-f8be-40e2-9f98-549d0f23d35f/image.png" alt="">
이런식으로 공백 활용</p>
<h3 id="불필요한-코드">불필요한 코드</h3>
<p><img src="https://velog.velcdn.com/images/kyung-baa/post/71425d9f-3868-49c9-96d7-b03a1628342c/image.png" alt="">
-&gt;</p>
<p><img src="https://velog.velcdn.com/images/kyung-baa/post/4ff3365b-a752-4c58-8307-aaea713ca347/image.png" alt=""></p>
<h3 id="분기-사용자제">분기 사용자제</h3>
<p><img src="https://velog.velcdn.com/images/kyung-baa/post/abb3c1b2-cca5-44f4-99ca-53a9f1f7a796/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/kyung-baa/post/337513de-69d3-4c0c-8390-e11340ce8d10/image.png" alt=""></p>
<h3 id="map함수-제대로-사용하기">map함수 제대로 사용하기</h3>
<p>새로운 배열 -map
반복 -foreach문 </p>
<h3 id="consolelog금지">console.log금지</h3>
<p>console.err될 수 있으면 활용할것 
찍으면 바로 지우던가 eslint사용 
허스키 사용해서 제어할 것</p>
<h3 id="사용성">사용성</h3>
<p><img src="https://velog.velcdn.com/images/kyung-baa/post/328ecaa5-e3eb-4cd7-80b1-3900572d113f/image.png" alt="">
페이지가 이동했을경우 페이지 제일 상단</p>
<h3 id="상수-컨벤션">상수 컨벤션</h3>
<p>상수 UPPERCASE + SNAKE_CASE 사용</p>
<h3 id="파일구조">파일구조</h3>
<p>같은 기능을 하는 컴포넌트들은 한군데(페이지의 conponent폴더)에 몰아넣고 
component폴더는 header, footer같은 애들만 넣어둠</p>
<h4 id="별도의-컴포넌트로-빼는-경우">별도의 컴포넌트로 빼는 경우</h4>
<p>ui가 재사용될 경우 
재사용되지는 않지만 컴포넌트안의 로직이 복잡할 경우 내용이 길어질경우 UI가 복잡하다고 판단할 수 있다. 이건 개인의 판단</p>
<h3 id="금지되는-변수명">금지되는 변수명</h3>
<p><img src="https://velog.velcdn.com/images/kyung-baa/post/0f13eefa-5749-4d00-bb9f-329d24961ea4/image.png" alt="">
userData와 userInfo이거 둘의 내용을 구별할 수 있음? 
못함 ...... 이런 변수명은 사용하지 말자
<img src="https://velog.velcdn.com/images/kyung-baa/post/0e0d8ee2-35b2-4eff-9b21-e9c6df450731/image.png" alt="">
string도 끝까지 string가 아닐 수도 있음 </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[이벤트 버블링]]></title>
            <link>https://velog.io/@kyung-baa/%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EB%B2%84%EB%B8%94%EB%A7%81%EA%B3%BC-%EC%BA%A1%EC%B2%98%EB%A7%81</link>
            <guid>https://velog.io/@kyung-baa/%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EB%B2%84%EB%B8%94%EB%A7%81%EA%B3%BC-%EC%BA%A1%EC%B2%98%EB%A7%81</guid>
            <pubDate>Thu, 01 Sep 2022 04:51:43 GMT</pubDate>
            <description><![CDATA[<h1 id="이벤트-버블링">이벤트 버블링</h1>
<h2 id="버블링bubbling">버블링(bubbling)</h2>
<blockquote>
<p>한 요소에 이벤트가 발생하면, 이 요소에 할당된 핸들러가 동작하고 이어서 부모요소의 핸들러가 동작함 가장 최상단의 요소를 만날때까지 이 과정은     반복되며 요소 각각에 한당된 핸들러가 동작한다.</p>
</blockquote>
<h3 id="버블링-예제">버블링 예제</h3>
<pre><code class="language-javascript">&lt;style&gt;
  body * {
    margin: 10px;
    border: 1px solid blue;
  }
&lt;/style&gt;

&lt;form onclick=&quot;alert(&#39;form&#39;)&quot;&gt;FORM
  &lt;div onclick=&quot;alert(&#39;div&#39;)&quot;&gt;DIV
    &lt;p onclick=&quot;alert(&#39;p&#39;)&quot;&gt;P&lt;/p&gt;
  &lt;/div&gt;
&lt;/form&gt;</code></pre>
<p><img src="https://velog.velcdn.com/images/kyung-baa/post/585f82a9-da48-4b01-a265-a2386a000e21/image.png" alt=""></p>
<h4 id="가장-안쪽의-p태그를-클릭하면-일어나는일">가장 안쪽의 <code>&lt;p&gt;</code>태그를 클릭하면 일어나는일</h4>
<p>1.<code>&lt;p&gt;</code>에 할당된 <code>onClick</code> 핸들러가 동작한다.
2. 바깥의 <code>&lt;div&gt;</code>에 할당된 핸들러가 동작한다. 
3. 그 바깥의 <code>&lt;form&gt;</code>에 할당된 핸들러가 동작합니다.
4. <code>document</code> 객체를 만날 때까지, 각 요소에 할당된 <code>onclick</code> 핸들러가 동작합니다.</p>
<p><img src="https://velog.velcdn.com/images/kyung-baa/post/bd53b07e-2d0e-4ebb-b3bb-616b6e5e78ea/image.png" alt="">
이런 동작 방식 떄문에<code>&lt;p&gt;</code>요소 클릭시 <code>&lt;p&gt;</code>-&gt;<code>&lt;div&gt;</code>-&gt;<code>&lt;form&gt;</code> 순서대로 3개의 alert창이 뜬다.
-&gt; 이런 흐름을 이벤트 버블링이라고 한다. 이벤트가 가장 깊은 곳에 있는 요소에서 시작해서 부모요소를 거슬로 올라가는 모습이 마치 물속 거품과 닮았기 때문</p>
<blockquote>
<p><strong>❗️거의 모든 이벤트는 버블링 된다.</strong>
거의 다 된다. 거의 
focus 이벤트와 같이 버블링 되지 않는 이벤트도 있음</p>
</blockquote>
<h3 id="eventtarget">event.target</h3>
<p>부모 요소의 핸들러는 이벤트가 정확히 발생했는지 등에 대한 자세한 정보를 얻을 수 있다. 
이벤트가 발생한 가장 안쪽의 요소는 타깃(target) 요소라고 불리고, event.target을 사용해 접근할 수 있다.</p>
<h4 id="eventtarget과-thiseventcurrenttarget의-차이">event.target과 this(=event.currentTarget)의 차이</h4>
<ul>
<li>event.target은 실제 이벤트가 시작된 ‘타깃’ 요소입니다. 버블링이 진행되어도 변하지 않는다.</li>
<li>this는 ‘현재’ 요소로, 현재 실행 중인 핸들러가 할당된 요소를 참조</li>
</ul>
<p>핸들러는 form.onclick 하나밖에 없지만 이 핸들러에서 폼 안의 모든 요소에서 발생하는 클릭 이벤트를 ‘잡아내고(catch)’ 있습니다. 클릭 이벤트가 어디서 발생했든 상관없이 <form> 요소까지 이벤트가 버블링 되어 핸들러를 실행시키기 때문입니다.</p>
<p>form.onclick 핸들러 내의 this와 event.target은 다음과 같습니다.</p>
<p>this(event.currentTarget) – <form> 요소에 있는 핸들러가 동작했기 때문에 <form> 요소를 가리킵니다.
event.target – 폼 안쪽에 </p>
<h2 id="캡쳐링capturing">캡쳐링(capturing)</h2>
<p>부모 element에서 발생된 event가 자식 element순으로 전달 되는 현상</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Async / Await]]></title>
            <link>https://velog.io/@kyung-baa/Async-Await</link>
            <guid>https://velog.io/@kyung-baa/Async-Await</guid>
            <pubDate>Thu, 01 Sep 2022 04:25:53 GMT</pubDate>
            <description><![CDATA[<h1 id="async--await">Async / Await</h1>
<h2 id="async">Async</h2>
<ul>
<li><p>Promise를 대체할 수 있다. </p>
</li>
<li><p>async / await 키워드를 통해 쉽게 promise객체를 생성하고 then, catch를 대신해서 사용할 수 있다.</p>
</li>
<li><p>async를 function앞에 붙이면 함수가 promise역할을 하게된다.</p>
<h2 id="await">Await</h2>
</li>
<li><p>then 대신에 사용할 수 있는 Await</p>
</li>
<li><p>단순한 의미는 기다려 달라는 뜻인데 비동기적으로 처리를 할때 promise를 기다려 달라는 의미</p>
</li>
<li><p>단 await는 async안에서만 사용할 수 있는 키워드</p>
</li>
<li><p>await는 promise가 실패할 경우 에러가 발생하고 멈춘다. </p>
</li>
<li><p>이를 방지하고자 try{} catch{}구문을 사용한다.</p>
<h2 id="try-catch">try{} catch{}</h2>
<pre><code class="language-javascript">async function cal() {
let test = new Promise((resolve, reject) =&gt; {
  let sum = 1 + 1;
  resolve(sum);
});

try { //try 를 먼저 실행해보고 실행되면 try 문 그대로 출력
  let result = await test;
  console.log(result)
} catch { // try 가 실패시, catch 문 출력
  console.log(&#39;fail&#39;)
}
}
</code></pre>
</li>
</ul>
<p>cal();</p>
<pre><code>&gt;순차적으로 많은것을 실행할때 유용하다.

```javascript
async function getDataOne() {
    const result = await fetchData() // 데이터를 가져오는데 3초의 시간이 걸린다면 이를 기다려줌
    return result
}

async function getDataTwo() {
    const result = await fetchData() // 데이터를 가져오는데 3초의 시간이 걸린다면 이를 기다려줌
    return result
}

function getAllData() {
    return Promise.all([getDataOne(), getBanana()])
    .then(data =&gt; 
        console.log(data) // 데이터를 병렬로 가져오기 때문에 3초의 시간 소요
    )
}

getAllData().then(console.log)</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[비동기 호출 callback, promise]]></title>
            <link>https://velog.io/@kyung-baa/%EB%B9%84%EB%8F%99%EA%B8%B0-%ED%98%B8%EC%B6%9C-callback-promise</link>
            <guid>https://velog.io/@kyung-baa/%EB%B9%84%EB%8F%99%EA%B8%B0-%ED%98%B8%EC%B6%9C-callback-promise</guid>
            <pubDate>Thu, 01 Sep 2022 02:53:34 GMT</pubDate>
            <description><![CDATA[<h1 id="비동기-호출-callback-promise">비동기 호출 callback, promise</h1>
<h2 id="js-동기식-처리">Js 동기식 처리</h2>
<p><strong>동기식 처리</strong> </p>
<ul>
<li>한번에 하나의 작업만 수행하는 싱글스레드방식</li>
<li>자바스크립트를 실행하는 웹브라우저는 stack이라는 코드 실행공간이 있는데 거기서 한번에 하나씩 수행해준다. </li>
</ul>
<p><strong>예외</strong></p>
<ul>
<li>시간이 오래 걸리는 코드는 stack에서 제외시켜 wep API라는 대기실에서 대기하게 하고 나중에 실행 시킨다. (ajax, setTimeout, eventLister 등) - 읽는 시점과 동작 시점이 다른 코드들</li>
<li>이런 처리 방식을 비동기방식이라고 함</li>
<li>실행이 오래걸린다고? 그럼 기다려 일단 실행 가능한 애들 먼저 실행해줄게 </li>
<li>자바스크립트 언어자체의 기능이 아닌 자바스크립트 실행을 도와주는 웹브라우저가 해주는 역할<blockquote>
<p>대표적으로 사용되는 곳은 서버쪽과 데이터를 주고 받을 때 사용하는데, 클라이언트쪽에서 서버쪽에 비동기 요청을 하고 클라이언트에서는 다른 작업을 수행하고 있다가 서버쪽에서 모든 작이 완료되면 resoponse를 해주면, 그 순간 전달받은 데이터를 클라이언트에서 사용하는 방식</p>
</blockquote>
</li>
</ul>
<pre><code class="language-javascript">console.log(1);
setTimeout(function(){
  console.log(2);
}, 1000);
console.log(3);</code></pre>
<p>먼저 수행할 수 있는 1,3 출력 후 1초뒤 2 출력</p>
<h2 id="callback">callback</h2>
<ul>
<li>ES6버전 이전에 사용되던 비동기 처리 방법</li>
<li>다른 함수가 실행을 끝낸 뒤 실행되는 함수</li>
<li>코드를 통해 명시적으로 호출하는 함수가 아니라 함수를 등록해 놓은 후 어떠한 이벤트가 발생하거나, 특정 시점에 도달했을 때 시스템에서 호출하는 함수</li>
<li>파라미터로 함수를 전달받아서 함수의 내부에서 실행</li>
<li>쉽게 말해서 함수안에 들어가는 함수를 callback함수라고 한다.</li>
</ul>
<h3 id="콜백함수-사용이유">콜백함수 사용이유</h3>
<ul>
<li>Js에서 비동기적 프로그램을 할 수 있기 때문</li>
<li>Js는 싱글 스레드를 사용하는데 멈춤을 방지해준다. 블로깅을 방지하여 싱글 스레드가 논블록킹으로 동작하게한다. </li>
</ul>
<pre><code class="language-javascript">function add5(a, callback) {
  setTimeout(() =&gt; callback(a + 5), 100)
// 100ms가 지난 후 함수로 입력받은 callback에 a + 10값을 다시 입력하여 callback함수 호출
}
add5(10, function (res) { // add5가 입력받는 callback함수 정의 부분
  console.log(res)
});</code></pre>
<p>add5 호출하는 부분 첫번째 인자는 5, 함수 생성 후 전달
add5함수 내부에서는 입력받은 함수 callback에 a + 5 후 다시 호출 </p>
<h3 id="callback-hell">Callback Hell</h3>
<p>callback은 사용하기 편리하지만 연속적으로 사용하게 되면 유지보수가 힘들어진다는 단점이 있다. </p>
<pre><code class="language-javascript">add5(10, res =&gt; {
  add5(res, res =&gt; {
    add5(res, res =&gt; {
      add5(res, res =&gt; {
        console.log(res)
      })
    })
  })
})</code></pre>
<p>이런식으로 몇번 연속 호출하게 되면 그것이 바로 지옥....</p>
<h2 id="promise">Promise</h2>
<ul>
<li><p>기본적으로는 callback함수와 하는 일이 같다.</p>
</li>
<li><p>Promise는 작업이 끝난 후 실행할 함수를 제공하는 것이 아니라 Promise자체 메소드인<code>then()</code>을 호출한다.</p>
<pre><code class="language-javascript">function add10(a) {
return new Promise(resolve =&gt; setTimeout(() =&gt; resolve(a + 10), 100));
}//Promise사용 시 작업이 끝났음을 알려주는 resolve를 인자로 받아들임.
add10(10)
.then(add10)
.then(add10)
.then(add10)
.then((res) =&gt; console.log(res))

console.log(add10(10));
sPromise { &lt;pending&gt; }</code></pre>
<p>promise는 then()과 같은 다른 메소드를 연속적으로 사용이 가능하다는 이점을 가지고 있다. callback함수를 사용했을 때와는 다르게 코드를 작성하고 이해하기 쉬워짐.</p>
<p><code>add10()</code>가 결과값을 promise로 리턴한다.</p>
</li>
</ul>
<h3 id="promise-장점">Promise 장점</h3>
<p>callback 함수와 비교해서 code 가 옆으로 길어지지가 않는다</p>
<pre><code class="language-javascript">let first = new Promise(function (resolve, reject) { // resolve 는 성공, reject 는 실패 한것을 나타냄
  resolve(); // resolve 가 실행이 되면 밑에 .then 이 실행이 됨
  reject(); // reject 가 실행이 되면 밑에 .catch 가 실행됨
});
first.then(() =&gt; {
  // first 가 성공일 경우 실행 할 코드
}).then(() =&gt; {
  // 그다음에 실행할 것
}).catch(() =&gt; {
  // catch 는 위의 코드가 실패 했을 경우 실행 하는 code
})</code></pre>
<h3 id="promise의-세가지-상태">Promise의 세가지 상태</h3>
<ul>
<li>resolve: 성공</li>
<li>pending: 판정대기</li>
<li>rejected: 실패</li>
</ul>
<p> 비동기적 처리가 가능하게 바꿔주는 문법! 
 callback대신 사용할 수 있으며 보기 쉽게 만들어줌</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[var, let, const의 차이]]></title>
            <link>https://velog.io/@kyung-baa/var-let-const%EC%9D%98-%EC%B0%A8%EC%9D%B4</link>
            <guid>https://velog.io/@kyung-baa/var-let-const%EC%9D%98-%EC%B0%A8%EC%9D%B4</guid>
            <pubDate>Thu, 01 Sep 2022 01:47:26 GMT</pubDate>
            <description><![CDATA[<h1 id="var-let-const의-차이">var, let, const의 차이</h1>
<h2 id="편하게-사용하는-var의-문제점">편하게 사용하는 var의 문제점</h2>
<ul>
<li>중복선언이 가능하기 때문에 예기치 않은 값으로 인해 오류가 생길 수 있으며 수정하려면 하나하나 할당된 값을 확인해야한다.</li>
<li>함수레벨 스코프로 인해 함수 외부에서 선언할 경우 모두 전역변수로 사용된다.</li>
<li>변수 선언문 이전에 변수를 참조하면 언제나 undefined를 반환한다. (호이스팅)</li>
</ul>
<blockquote>
<p>ES6에서 나온 let과 const 키워드는 var키워드의 문제점을 해결했다. </p>
</blockquote>
<h2 id="재선언과-재할당">재선언과 재할당</h2>
<h3 id="let">let</h3>
<blockquote>
<p>재선언 불가, 재할당 가능</p>
</blockquote>
<pre><code>let name = &#39;hooo&#39;
console.log(name) // output: hooo

let name = &#39;hooo&#39; // output: Uncaught SyntaxError: Identifier &#39;name&#39; has already been declared

name = &#39;kyungba&#39;
console.log(name) // output: kyungba</code></pre><h3 id="const">const</h3>
<blockquote>
<p>재선언, 재할당 불가 -&gt; 반드시 선언과 할당을 동시에 해야한다.</p>
</blockquote>
<pre><code>const name; // output: Uncaught SyntaxError: Missing initializer in const declaration
const name = &#39;hooo&#39;</code></pre><p><strong>const는 재선언과 재할당이 불가능</strong>하다. <strong>원시값은 수정이 불가하나 배열과 오브젝트의 경우 수정이 가능</strong>하다. const는 재선언과 재할당은 불가지만 불변을 의미하는 것은 아니다. </p>
<pre><code>// 원시값의 재할당
const name = &#39;hooo&#39; 
name = &#39;hooo&#39; // output: Uncaught TypeError: Assignment to constant variable.

// 객체의 재할당
const name = {
  eng: &#39;hooo&#39;,
}
name.eng = &#39;hooo&#39;

console.log(name) // output: { eng: &quot;hooo&quot; }</code></pre><h3 id="블록-레벨-스코프">블록 레벨 스코프</h3>
<blockquote>
<p>let, const 키워드로 선언한 변수는 모두 코드 블록(ex. 함수, if, for, while, try/catch 문 등)을 지역 스코프로 인정하는 블록 레벨 스코프를 따른다.</p>
</blockquote>
<pre><code>var a = 1

if (true) {
  var a = 5
}

console.log(a) // output: 5

let a = 1

if (true) {
  let a = 5
}

console.log(a) // output: 1</code></pre><p>var 키워드 사용시 5가 출력되었지만 let의 경우 if문안에 스코프에만 5가 적용된다. (const도 동일하게 적용)</p>
<h2 id="변수-호이스팅">변수 호이스팅</h2>
<h3 id="let-1">let</h3>
<p>let 키워드로 선언한 변수는 선언과 할당(초기화)이 따로 이루어진다. 즉, 런타임 이전에 자바스크립트 엔진에 의해 선언 단계가 먼저 실행되지만, 초기화 단계가 실행되지 않았을 때 해당 변수에 접근하려고 하면 참조 에러가 뜬다.</p>
<pre><code>console.log(name) // output: Uncaught ReferenceError: name is not defined

let name = &#39;hooo&#39;</code></pre><p>따라서 let 키워드로 선언한 변수는 스코프의 시작 지점부터 초기화 단계 시작 지점까지 변수를 참조할 수 없는 <strong>일시적 사각지대(Temporal Dead Zone: TDZ)</strong> 구간에 존재한다.</p>
<h3 id="const-1">const</h3>
<p>const는 선언과 할당(초기화)가 동시에 이루어진다. </p>
<pre><code>console.log(name) // output: Uncaught ReferenceError: Cannot access &#39;name&#39; before initialization

const name = &#39;hooo&#39;</code></pre><p>let 키워드로 선언한 경우, 런타임 이전에 선언이 되어 자바스크립트 엔진에 이미 존재하지만 초기화가 되지 않았기 때문에 <code>name is not defined</code>라는 문구가 떴다. 하지만 const 키워드로 선언한 경우, 선언과 초기화가 동시에 이루어져야 하지만 런타임 이전에는 실행될 수 없다. 따라서 초기화가 진행되지 않은 상태이기 때문에 <code>Cannot access &#39;name&#39; before initialization</code> 에러 문구가 뜬다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[hoisting 호이스팅]]></title>
            <link>https://velog.io/@kyung-baa/hoisting-%ED%98%B8%EC%9D%B4%EC%8A%A4%ED%8C%85</link>
            <guid>https://velog.io/@kyung-baa/hoisting-%ED%98%B8%EC%9D%B4%EC%8A%A4%ED%8C%85</guid>
            <pubDate>Thu, 01 Sep 2022 01:31:34 GMT</pubDate>
            <description><![CDATA[<h1 id="hoisting-호이스팅">hoisting 호이스팅</h1>
<blockquote>
<p>변수명을 자바스크립트에게 알려주는 것 → 선언
변수에 값을 저장하는 것 → 할당
변수에 저장된 값을 읽어오는 것 → 참조</p>
</blockquote>
<p>자바 스크립트에서 변수 선언은 <strong>선언 -&gt; 초기화</strong> 단계를 거쳐 수행한다.</p>
<p><strong>선언 단계</strong>
변수명을 등록하여 자바스크립트 엔진의 변수의 존재 알림
*<em>초기화 단계 *</em>
값을 저장하기 위한 메모리 공간을 확보하고 암묵적으로 undefined를 할당해 초기화한다.</p>
<h2 id="변수-호이스팅">변수 호이스팅</h2>
<pre><code>var hooo
console.log(hooo) // output: undefined</code></pre><p> var 키워드를 사용하여 변수 선언했을 때, 선언과 초기화가 동시에 이루어져 hooo에 암묵적으로 undefined를 할당해 초기화 함</p>
<pre><code>console.log(hooo) // output: undefined
var hooo</code></pre><p> 반대로 console.log를 먼저 찍어도 undefined가 나오는 걸 확인할 수 있다. </p>
<p>이는 변수선언이 런타임에서 진행되는 것이 아니라 이미 그 이전 단계에서 실행되기 때문이다. 자바 스크립트는 소스코드를 한줄씩 순차적으로 실행하기에 앞서, <strong>모든 선언문 (변수 선언, 함수 선언등)을 찾아내 먼저 실행</strong>한다. </p>
<p>즉, *<em>변수 선언이 어디에 있던, 다른 코드보다 먼저 실행되는데 이를 호이스팅(hoisting)이라고 한다. *</em></p>
<p>변수 선언 뿐만 아니라 var, let, const, function, class 키워드를 사용해 선언한 모든 식별자는 호이스팅이 된다.</p>
<pre><code>var hooo  // 변수 선언
hooo = &#39;나는야경바&#39; // 값 할당
var hooo = &#39;나는야경바&#39; // 변순 선언과 할당</code></pre><p>변수 선언은 하나의  statement로 단축 표현할 수 있지만, 두개의 실행 시점이 다르다. 변수** 선언이 호이스팅되어 런타임 이전에 실행** 되지만 <strong>값의 할당은 소스 코드가 순차적으로 실행되는 런타임에 실행</strong>된다.</p>
<p>-&gt; 변수의 할당과 console.log의 실행하는 위치에 따라 반환되는 값이 다름</p>
<pre><code>var hooo
console.log(hooo) // output: undefined
hooo = &#39;나는야경바&#39; 
console.log(hooo) // output: &#39;나는야경바&#39; </code></pre><p>재할당은 변수에 저장된 값을 다른 값으로 변경하는 것으로, 만약 변경할 수 없는 값이라면 이는 변수가 아니라 상수(constant)라 부른다.</p>
<blockquote>
<p>보는것처럼 선언과 할당을 아주 자유롭게 한다. 변수를 새로 선언했음에도 에러가 나지 않고 각기 다른 값이 잘 뜬다.  매우 유연한 방식으로 테스트 코드에서는 사용이 편리하지만 나중에 코드량이 많아진다면 어디서 선언했는지 찾기가 힘들어진다. </p>
</blockquote>
<h2 id="함수-호이스팅">함수 호이스팅</h2>
<h3 id="함수가-정의되는-네가지-방식">함수가 정의되는 네가지 방식</h3>
<pre><code>// 1. 함수 선언문
// 함수 이름 생략 불가능
function add(x, y) {
  return x + y
}

// 2. 함수 표현식
// 함수 이름 생략 가능
var add = function(x, y) {
  return x + y
}
// 함수 이름 작성 시,
// var add = function plus(x, y) {
//   return x + y
// }

// 3. Function 생성자 함수
var add = new Function(&#39;x&#39;, &#39;y&#39;, &#39;return x+ y&#39;)

// 4. 화살표 함수
var add = (x, y) =&gt; x + y</code></pre><h3 id="함수-선언문과-함수-표현식의-호이스팅-결과">함수 선언문과 함수 표현식의 호이스팅 결과</h3>
<pre><code>console.dir(add) // output: f add(x, y)
console.dir(sub) // output: undefined

// 함수 호출
console.log(add(2, 5)) // output: 7
console.log(sub(2, 5)) // output: Uncaught TypeError: sub is not a function

// 함수 선언문
function add(x, y) {
  return x + y
}

// 함수 표현식
var sub = function(x, y) {
  return x + y
}</code></pre><p><strong>함수 선언문</strong>의 경우, 런타임 이전에 자바스크립트 엔진에서 먼저 실행되어, 함수 자체를 호이스팅 시킬 수 있다. </p>
<p>반면, <strong>함수 표현식</strong>은 위에서 봤던 변수 호이스팅과 같이 런타임 이전에 해당 값을 <code>undefined</code>로 초기화만 시키고, 런타임에서 해당 함수 표현식이 할당되어 그때 객체가 된다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[TIL 26: Git Workflow & Rebase]]></title>
            <link>https://velog.io/@kyung-baa/TIL-26-Git-Workflow-Rebase</link>
            <guid>https://velog.io/@kyung-baa/TIL-26-Git-Workflow-Rebase</guid>
            <pubDate>Sun, 10 Jul 2022 06:23:49 GMT</pubDate>
            <description><![CDATA[<h3 id="git에서는-브랜치를-병합할-때-사용하는-두-가지-방법">git에서는 브랜치를 병합할 때 사용하는 두 가지 방법</h3>
<p><strong>1. git merge
2. git rebase</strong></p>
<h3 id="git-merge">git merge</h3>
<pre><code>//1. master 브랜치로 이동
$git checkout master

//2. 병합할 브랜치를 master브랜치에 merge
$git merge [master에 병합할 브랜치 명]

//위 1,2를 한번에 표현 가능
$git merge [master에 병합할 브랜치 명] master</code></pre><p>병합을 하면 합쳐진 브랜치의 커밋 메시지가 중복으로 쌓이게 됩니다.
커밋 순서를 바꾸지 않습니다.
존재하는 브랜치가 변경되지 않습니다.
새로운 merge commit을 생성합니다.
git merge --abort : 병합을 취소하는 명령어</p>
<p><img src="https://velog.velcdn.com/images/kyung-baa/post/00c6679a-376f-4a3a-b4be-658244492bf5/image.png" alt="">
위 이미지는 Main 브랜치에 Feature 브랜치를 병합하는 과정을 나타냅니다.
커밋 순서가 변경되지 않고, 기존 분기는 유지되는 모습을 확인할 수 있습니다.</p>
<h3 id="git-rebase">git rebase</h3>
<p><img src="https://velog.velcdn.com/images/kyung-baa/post/663bf6a8-e560-4257-8d85-932e296df511/image.png" alt=""></p>
<p>Feature 브랜치를 Main 브랜치에 병합을 나타내는 이미지 입니다.
위 그림처럼 Feature 브랜치의 커밋은 Main 브랜치가 가지고 있던 기존의 커밋 뒤에 위치하게 됩니다.</p>
<pre><code>//master에 rebase 할 브랜치로 이동
$git checkout [rebase 할 브랜치]
$git rebase master

//rebase 할 브랜치를 master 브랜치에 merge
$git checkout master</code></pre><h3 id="rebase-사용법">rebase 사용법</h3>
<pre><code class="language-//수정할">//git rebase -i [수정을 시작할 커밋의 이전 커밋] 형식으로 입력
$git rebase -i HEAD~4

//4개의 커밋 리스트 노출
hint: Waiting for your editor to close the file...
pick 907c451 commit1
pick 1a7c765 commit2
pick v07c952 commit3
pick 40jc438 commit4

//사용할수있는 명령어 리스트
# Commands:
# p, pick &lt;commit&gt; = use commit
# r, reword &lt;commit&gt; = use commit, but edit the commit message
# e, edit &lt;commit&gt; = use commit, but stop for amending
# s, squash &lt;commit&gt; = use commit, but meld into previous commit
# f, fixup &lt;commit&gt; = like &quot;squash&quot;, but discard this commit&#39;s log message
# x, exec &lt;command&gt; = run command (the rest of the line) using shell
# b, break = stop here (continue rebase later with &#39;git rebase --continue&#39;)
# d, drop &lt;commit&gt; = remove commit
# l, label &lt;label&gt; = label current HEAD with a name
# t, reset &lt;label&gt; = reset HEAD to a label
# m, merge [-C &lt;commit&gt; | -c &lt;commit&gt;] &lt;label&gt; [# &lt;oneline&gt;]
# .       create a merge commit using the original merge commit&#39;s
# .       message (or the oneline, if no original merge commit was
# .       specified). Use -c &lt;commit&gt; to reword the commit message.
</code></pre>
<h4 id="pick">pick</h4>
<p>-커밋을 사용하겠다는 의미, 이를 이용해 커밋의 순서를 바꿀 수 있고, 커밋의 해시값을 이용해 특정 커밋을 가져올 수 있습니다.</p>
<ul>
<li><p>rebase 명령어를 실행하면 기본적으로 pick으로 설정돼있기 때문에 아무것도 변경하지 않고 종료한다면, 커밋에 대하여 어떠한 변경도 일어나지 않게 됩니다.</p>
</li>
<li><p>위 코드에서 commit2와 commit3의 순서를 바꾼다면, 커밋 순서와 커밋 해시값까지 변경됩니다.</p>
</li>
</ul>
<p>​</p>
<h4 id="reword">reword</h4>
<ul>
<li><p>커밋 메시지를 변경하는 명령어</p>
</li>
<li><p>커밋 메시지를 변경할 커밋 앞에 reword 명령으로 수정하고, 저장하면 해당 커밋의 메시지를 다시 작성하는 에디터 창이 열리게 됩니다.</p>
</li>
<li><p>커밋 메시지와 커밋의 해시값 또한 변경됩니다.</p>
</li>
</ul>
<p>​</p>
<h4 id="edit">edit</h4>
<ul>
<li><p>reword 명령어는 커밋 메시지만 변경하는 명령이라면, edit 명령어는 커밋 메시지뿐만 아니라 커밋의 작업 내용까지 변경할 수 있습니다.</p>
</li>
<li><p>commit4라는 커밋을 edit으로 바꾸고 저장 후 종료하면, 변경할 커밋으로 checkout됨, 그 상태에서 변경 작업을 수행하면 됩니다.</p>
</li>
<li><p>그 후 변경사항을 저장하기 위해 아래와 같은 명령어 입력</p>
<pre><code>//staged 상태 변경
$git add . 
</code></pre></li>
</ul>
<p>//변경할 커밋메시지 입력
$git commit --amend -m &quot;commit4-amend&quot;</p>
<p>//rebase처리
$git rebase --continue</p>
<ul>
<li><p>커밋 내용과 메시지 모두 변경됩니다.</p>
<pre><code></code></pre></li>
</ul>
<p>​</p>
<h4 id="squash">squash</h4>
<ul>
<li>squash 명령어는 해당 커밋을 이전 커밋과 합치는 명령어입니다.</li>
</ul>
<p>pick 907c451 commit1
pick 1a7c765 commit2
squash v07c952 commit3
pick 40jc438 commit4</p>
<ul>
<li><p>commit3 커밋을 직전 커밋인 commit2 커밋과 합치기 위해 squash로 변경합니다.</p>
</li>
<li><p>저장 후 종료하면 커밋 메시지를 수정할 수 있는 에디터 창이 뜹니다.</p>
</li>
<li><p>합쳐질 커밋들의 메시지를 확인한 후 그대로 종료하면 아래와 같이 이전 커밋과 하나로 합쳐진 것을 볼 수 있습니다.</p>
<pre><code>pick 907c451 commit1
pick 73dc735 commit2
pick 40jc438 commit4</code></pre></li>
</ul>
<h4 id="fixup">fixup</h4>
<ul>
<li><p>fixup 명령어는 squash와 동일하게 해당 커밋을 이전 커밋과 합치는 명령어이지만, 커밋 메시지는 합쳐지지 않습니다.</p>
</li>
<li><p>결과적으로 이전 커밋의 커밋 메시지만 남게 됩니다.</p>
</li>
</ul>
<p>​</p>
<h4 id="exec">exec</h4>
<ul>
<li><p>exec 명령어를 이용하면, 각각의 커밋이 적용된 후 실행할 shell 명령어를 지정할 수 있습니다.</p>
</li>
<li><p>각각의 커밋이 실행된다는 것을 확인하기 위해 중간중간에 메시지를 넣는 행위입니다.</p>
</li>
</ul>
<p>​</p>
<h4 id="drop">drop</h4>
<ul>
<li><p>drop 명령어는 커밋 히스토리에서 커밋을 삭제합니다.</p>
</li>
<li><p>drop으로 변경 후 저장하면, 해당 커밋이 drop 되는 것을 확인 가능합니다.</p>
<pre><code>pick 907c451 commit1
drop 73dc735 commit2
pick 40jc438 commit4</code></pre></li>
</ul>
<h3 id="rebase-유의사항">rebase 유의사항</h3>
<ul>
<li><p>이전의 커밋 히스토리를 변경하기 때문에 항상 주의가 필요합니다.</p>
</li>
<li><p>만약 이미 Github과 같은 원격 저장소에 push까지 한 커밋이라면, 변경한 커밋들은 원격 저장소에 push 되지 않을 것입니다.</p>
</li>
<li><p>이때 git push --force  혹은 git push -f 명령으로 강제로 원격 저장소에 커밋 히스토리를 덮어쓸 수 있습니다.</p>
</li>
<li><p>만약 이전에 push 한 커밋들을 다른 개발자들과 공유하고 있었다면, 커밋 히스토리의 불일치가 발생해 git이 꼬이는 현상이 발생할 수 있습니다.</p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[TIL:25 Software Testing]]></title>
            <link>https://velog.io/@kyung-baa/TIL25-Software-Testing</link>
            <guid>https://velog.io/@kyung-baa/TIL25-Software-Testing</guid>
            <pubDate>Sat, 09 Jul 2022 12:09:48 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/kyung-baa/post/70c0f1c3-ad8c-4076-baf8-1275999b1e00/image.png" alt=""></p>
<blockquote>
<p>사용자의 행동에 따른 일련의 흐름에 흠집이 없어야한다.
로그인 —————&gt; 구매 ————&gt; 로그아웃 </p>
</blockquote>
<h2 id="테스트를-하는-이유-why-test">테스트를 하는 이유 why test</h2>
<p>*<em>&gt; 결함 확인  (선 결함 확인 후 수정) -&gt; 사전방지 -&gt; 시간절약 
-&gt; 구조 개선 -&gt; 품질 개선 -&gt; 확장성 *</em>
시간 절약의 이유: 
재설계의 시간을 줄일 수 있음, 
디버깅의 시간을 줄일 수 있음</p>
<h3 id="manual-testing">Manual Testing</h3>
<p><img src="https://velog.velcdn.com/images/kyung-baa/post/643ec159-5011-4717-9090-226a42b214eb/image.png" alt="">
일련의 모든 내용을 하나하나 손수 확인함
하지만 주가 되어서는 안됨 불안정성의 증대 
시스템 하나에는 많은 이벤트들이 있는데 하나하나 확인하다보면 사람이기 때문에 실수할 수 있고 인력이 많이 소모된다. 
비용이 많이 올라감 ( 인력비용 시간비용 등 ) 
테스트 속도가 느림 </p>
<h3 id="automation-testing">Automation Testing</h3>
<p><img src="https://velog.velcdn.com/images/kyung-baa/post/0e130155-77d7-42f9-8856-646595595233/image.png" alt=""></p>
<h3 id="시스템-테스트-전략-3가지">시스템 테스트 전략 3가지</h3>
<p><img src="https://velog.velcdn.com/images/kyung-baa/post/e4910784-267c-4475-bcb7-70fc353b15f1/image.png" alt=""></p>
<p><strong>End-to-End (E2E) Tests</strong></p>
<p><strong>Integration Test</strong>
통합 테스트 다양한 디렉토리와 파일들이 산발되어 작업이 되는데,
이 코드들이 통합되어 잘 돌아가는지 확인해보는 과정 </p>
<p><strong>Unit Test 
단위 테스트 회</strong>원가입 시 메일이 중복인지 아이디는 잘 들어가는지 등등 확인</p>
<h4 id="end-to-end-e2e-tests">End-to-End (E2E) Tests</h4>
<p><img src="https://velog.velcdn.com/images/kyung-baa/post/77c16529-e0f2-4ea0-a955-36060684e49d/image.png" alt="">
Cypress ui ux 흐름에대해 테스트하는 도구</p>
<h4 id="integration-test">Integration Test!</h4>
<p><img src="https://velog.velcdn.com/images/kyung-baa/post/431a6743-ccca-46d4-8bcd-44360f2ba1cf/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/kyung-baa/post/bbe0e702-1703-430f-b7ac-f08af8974e94/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Bob Morgan ]]></title>
            <link>https://velog.io/@kyung-baa/Bob-Morgan</link>
            <guid>https://velog.io/@kyung-baa/Bob-Morgan</guid>
            <pubDate>Sat, 09 Jul 2022 12:04:05 GMT</pubDate>
            <description><![CDATA[<p>Bob Morgan 두번째 프로젝트를 시작했다. </p>
<p>제주도의 맛집을 소개하며 예약 및 위치 안내기능을 갖춘 사이트로 
사실은 다른 자동차 사이트의 일부 페이지였던 부분을 따로 떼서 우리의 프로젝트로 삼았다. </p>
<p>기능 부분이 거의 없어서 예약기능과 리뷰 (페이지 하단 댓글 기능 구현)까지 진행하기로 결정하여 지금 진행중에 있다. </p>
<p>확실히 1차 프로젝트보다는 성장했는지 훨씬 수월하면서도.. 다른 새로운 기능들에 고뇌하고 있다. </p>
<p>1차 프로젝트에서 사용하지 않았던 라이브러리들까지 같이 사용하면서 캐러셀 부분을 쉽게 구현하게 되었다. </p>
<p>다만 부트스트랩 같이 UI부분을 도와주는 ant design을 함께 사용하게 되었는데 으... 색상 한번 수정하는데 하나하나 styled component에 nesting까지 사용해서 고치는게 여간 번거로운 일이 아니다. </p>
<p>함께 사용하면 더 편할거라고 생각했지만 양날의 검일까..</p>
<p>아직은 내 마음대로 커스텀하는게 쉽진 않지만 하나하나 만들기 번거로운 부분들을 편하게 만들 수 있어서 조금 더 손에 익숙하도록 해야겠다. </p>
<h2 id="frontend">Frontend</h2>
<ol>
<li>소셜 로그인 페이지 <ol>
<li>카카오 로그인</li>
</ol>
</li>
<li>메인 페이지 <ol>
<li>슬라이드</li>
<li>검색 기능(지역, 음식 종류)</li>
</ol>
</li>
<li>(상세 검색 + 전체 맛집) 리스트<ol>
<li>지역 검색( /regions)</li>
<li>음식 종류<a href="/places">한,중,일,양,카</a></li>
<li>필터링</li>
<li>마우스 좌표 기능 애니메이션 배너</li>
<li>랜덤 맛집 리스트 캐러셀?</li>
<li>맛집 무한 스크롤</li>
</ol>
</li>
<li>맛집 상세 페이지 ** <ol>
<li>맛집 이미지 캐러셀</li>
<li>네이버 플레이스 연결 버튼</li>
</ol>
</li>
</ol>
<p>내가 담당하는 부분은 상세페이지 
1차때는 상품 리스트 부분이었으니 이번에는 상세페이지를 담당하게 되었다. 다른 팀원분들도 모두 열심히 똘똘 뭉쳐서 화이팅 : ) </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[TIL:24 dotenv]]></title>
            <link>https://velog.io/@kyung-baa/TIL23-dotenv</link>
            <guid>https://velog.io/@kyung-baa/TIL23-dotenv</guid>
            <pubDate>Sun, 03 Jul 2022 08:04:21 GMT</pubDate>
            <description><![CDATA[<h2 id="환경변수란">환경변수란?</h2>
<blockquote>
<p>프로세스가 컴퓨터에서 동작하는 방식에 영향을 미치는 동적인 값들의 모임 [위키피디아]</p>
</blockquote>
<p>환경변수는 OS입장에서 해당 프로세스를 실행시키기 위하여 참조하는 변수이다.
우리가 컴퓨터로 하는 모든 작업들은(게임, 인터넷창띄우기, 그림판, 메모장, ...) OS라는 프로그램에 의하여 실행되는 자식프로세스인데 이 프로세스들을 실행킬 때 OS입장에서 참조하는 변수가 바로 환경변수이다.</p>
<h2 id="dotevnenv란">dotevn(.env)란?</h2>
<blockquote>
<p>Dotenv is a zero-dependency module that loads environment variables from a .env file into process.env. Storing configuration in the environment separate from code is based on The Twelve-Factor App methodology. [dotenv 공식문서]
해석 : Dotenv는 .env 파일에서 process.env로 환경 변수를 로드하는 제로 종속성 모듈입니다.</p>
</blockquote>
<p>dotenv는 환경변수를 .env파일에 저장하고 process.env로 로드하는 의존성 모듈이다.
dotenv를 사용하는 이유는 우리가 개발을 하는 과정에서 서버주소, 고유 API KEY 값 등 필요한 정보들을 저장을 하게 된다. 그리고 이러한 정보들은 민감한 정보임과 동시에 보안이 이루어져야 하는 정보들이다. 만약 이러한 정보들이 오픈소스(깃허브)에 공개될 경우, 해킹을 당하거나 보안적인 면에서 위험할 수 있다.</p>
<p>이러한 문제로 dotenv패키지를 이용하여 환경변수 파일(.env)을 외부에 만들어 접근할 수 있게 하고, 개발 초기 단계에서 세팅하기를 권고한다.</p>
<h2 id="dotenv-패키지">dotenv 패키지</h2>
<h3 id="dotenv-설치하기">dotenv 설치하기</h3>
<pre><code># npm

npm install dotenv
</code></pre><h3 id="env파일-생성">.env파일 생성</h3>
<pre><code># .env 파일

DATABASE_NAME=&#39;[DB명]&#39;
DATABASE_USERNAME=&#39;root&#39;
DATABASE_PASSWORD=&#39;&#39;</code></pre><ul>
<li>설치 후 .env파일을 루트경로에 생성한 후 안에 들어갈 텍스트는 반드시 이름 = 값형식으로 적어준다.
[환경변수는 특정 process를 위한 key-value 형태의 변수]</li>
</ul>
<h3 id="requiredotenvconfig">require(&#39;dotenv&#39;).config()</h3>
<pre><code># 해당 파일
//import dotenv from &#39;dotenv&#39;
require(&#39;dotenv&#39;).config();</code></pre><ul>
<li>.env를 사용하고자 하는 파일 안에 dotenv를 부른다.</li>
<li>dotenv.config()는 현재 디렉토리의 .env파일을 자동으로 인식하여 환경변수를 세팅한다.</li>
<li>dotenv.config(경로)는 원하는 .env파일의 위치를 직접 지정하여 세팅할 수 있다.</li>
</ul>
<h3 id="dotenv-주의사항">dotenv 주의사항</h3>
<pre><code># .gitignore 파일

# dotenv environment variables file
.env</code></pre><ul>
<li>.env파일에 저장하더라도 .env파일을 오픈소스(깃허브)에 올린다면 공개하는 것과 다름없기때문에 .gitignore파일에 .env파일을 추가하여 무시해준다.<blockquote>
</blockquote>
.env파일은 루트에 위치해야한다.
이거 위치 제대로 설정안해주면 에러난다.<blockquote>
<p><a href="https://velog.io/@reveloper-1311/DB-Node.js%EC%97%90%EC%84%9C-%ED%99%98%EA%B2%BD%EB%B3%80%EC%88%98-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0dotenv">https://velog.io/@reveloper-1311/DB-Node.js%EC%97%90%EC%84%9C-%ED%99%98%EA%B2%BD%EB%B3%80%EC%88%98-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0dotenv</a> 원본 글</p>
</blockquote>
</li>
</ul>
]]></description>
        </item>
    </channel>
</rss>