<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>del-luna.log</title>
        <link>https://velog.io/</link>
        <description>기록이 습관인 개발자</description>
        <lastBuildDate>Tue, 15 Nov 2022 13:23:34 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>del-luna.log</title>
            <url>https://velog.velcdn.com/images/del-luna/profile/236f0779-a65a-4020-a0f1-d006c1c7453a/social_profile.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. del-luna.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/del-luna" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[Virtual DOM 이란?]]></title>
            <link>https://velog.io/@del-luna/Virtual-DOM-%EC%9D%B4%EB%9E%80</link>
            <guid>https://velog.io/@del-luna/Virtual-DOM-%EC%9D%B4%EB%9E%80</guid>
            <pubDate>Tue, 15 Nov 2022 13:23:34 GMT</pubDate>
            <description><![CDATA[<h1 id="virtual-dom-등장-배경">Virtual DOM 등장 배경</h1>
<h2 id="브라우저-렌더링-과정">브라우저 렌더링 과정</h2>
<p><img src="https://velog.velcdn.com/images/del-luna/post/c38709d3-7091-4e31-96bf-0103ff671675/image.png" alt=""></p>
<p>Reference: <a href="https://velog.io/@del-luna/%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80-%EB%A0%8C%EB%8D%94%EB%A7%81-%EC%9B%90%EB%A6%AC">브라우저 렌더링 원리에 대해 설명해주세요.</a> </p>
<h2 id="dom-조작의-비효율성">DOM 조작의 비효율성</h2>
<p>위 과정을 전부 렌더링 될 때 마다 다시해줘야함. (여기서 DOM 트리를 생성하는 것이 비효율 적인게 아니라 <strong>렌더링 하는 과정이 비효율적이다!</strong>)</p>
<p>예전에는 SSR(Server Side Rendering)을 사용하여 서버에서 데이터와 함께 완전한 페이지를 렌더링 해줬다. DOM은 이러한 정적인 페이지를 보여주는 용도였기 때문에 DOM의 동적인 변화가 그렇게 큰 문제는 아니었다.</p>
<p>SPA의 등장과 함께 CSR(Client Side Rendering) 방식이 많이 사용되면서 현재는 DOM 업데이트가 상당히 많이 발생하게 된다.</p>
<h2 id="dom-vs-virtualdom">DOM vs VirtualDOM</h2>
<p>VirtualDOM은 DOM 노드 트리를 복제한 자바스크립트 객체이다. 쉽게 말하면 DOM의 가벼운 버전이다. → class, style등의 속성을 가지지만 DOM api 메서드(getElementById와 같은)를 가지지 않기 때문이다.</p>
<h1 id="virtualdom의-동작-방식">VirtualDOM의 동작 방식</h1>
<ol>
<li>브라우저가 실제 DOM 트리를 생성하고 브라우저 화면에 우리의 어플리케이션 ui가 렌더링 된다.</li>
<li>이때 Virtual DOM은 DOM 트리를 앞서 말했듯 가벼운 버전으로 복사한다.</li>
</ol>
<p><img src="https://miro.medium.com/max/1400/1*8OCCATi8_5HmWI1QpjrRNA.png" alt="https://miro.medium.com/max/1400/1*8OCCATi8_5HmWI1QpjrRNA.png"></p>
<ol>
<li>DOM 노드에 변화가 생기면 Virtual DOM은 새로운 Virtual DOM을 생성한다.<ul>
<li>매번 VirtualDOM을 생성하더라도 메모리상에서 동작하고 렌더링을 하지 않기 때문에 비용이 그렇게 비싸지 않음.</li>
</ul>
</li>
<li>Diff를 통해 변경된 부분만 체크한다 (PATCH)</li>
<li>RealDOM에 PATCH를 적용한다.</li>
</ol>
<p>즉, 변화가 일어날 때마다 렌더링 하는 것이 아니라, 변화를 모두 모아서 한 번만 렌더링 하는 것이 핵심이다.</p>
<h2 id="리액트에서-virtual-dom">리액트에서 Virtual DOM</h2>
<h3 id="render-phase">Render Phase</h3>
<p>Reconciliation(재조정) → Previous VirtualDOM vs Current VirtualDOM 비교하여(Diffing 알고리즘 사용) Real DOM에 필요한 부분(PATCH) 체크 </p>
<p><strong>Diffing 알고리즘</strong></p>
<p>Element들을 비교하게 되는데 Element는 (type, props) 두 가지 속성을 가진다.</p>
<pre><code class="language-jsx">const Element = {
    type: &quot;h1&quot;
    props: {
        title: &quot;foo&quot;
    },
}</code></pre>
<p>Diffing 알고리즘은 두 가지 케이스로 분류된다.</p>
<ol>
<li>type === type: 속성만 변경</li>
<li>type ≠ type: 트리를 재생성한다.</li>
</ol>
<h3 id="commit-phase">Commit Phase</h3>
<p><img src="https://velog.velcdn.com/images/del-luna/post/e67dbae8-314e-4703-aee4-210685be8346/image.png" alt=""></p>
<p>Render Phase에서 체크했던 변경이 필요한 부분을 RealDOM에 반영해주는 부분이다. 만약, 변경이 필요한 부분이 없다면 Commit Phase는 스킵된다.</p>
<h2 id="reference">Reference</h2>
<ul>
<li><a href="https://www.youtube.com/watch?v=6rDBqVHSbgM&amp;t=16s">https://www.youtube.com/watch?v=6rDBqVHSbgM&amp;t=16s</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[React를 사용하는 이유]]></title>
            <link>https://velog.io/@del-luna/React%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%98%EB%8A%94-%EC%9D%B4%EC%9C%A0</link>
            <guid>https://velog.io/@del-luna/React%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%98%EB%8A%94-%EC%9D%B4%EC%9C%A0</guid>
            <pubDate>Tue, 15 Nov 2022 13:20:41 GMT</pubDate>
            <description><![CDATA[<h2 id="react란">React란?</h2>
<p>웹 페이지라는 건물을 쌓는데 필요한 블록(Component)을 만드는 기술이다.</p>
<p>이 블록(Component)를 재사용하여 비슷한 건물을 쌓을 때 이미 만들어진 블록을 바탕으로 빠르게 건물을 완성할 수 있고, 누군가 만들어놓은 블록을 가져와서 내 건물의 블록으로 활용할 수 있게 해주는 도구이자 기술이라고 표현하고 싶다.</p>
<h2 id="react-등장-배경">React 등장 배경</h2>
<h3 id="태초에-jquery-backbone-angularjs가-있었다">태초에 Jquery, Backbone, AngularJS가 있었다..</h3>
<p>Jquery의 경우 쉽고 효율적으로 DOM을 다룰 수 있어서 많은 사랑을 받았고, </p>
<p>Backbone, Angular의 경우 SPA방식을 사용하지만, DOM을 다룰 때 여전히 Jquery를 사용했다.</p>
<h3 id="jquery-방식의-문제점">Jquery 방식의 문제점</h3>
<p>가장 큰 문제는 <strong>속도</strong>!</p>
<p>웹페이지는 브라우저상에서 돔(DOM, Document Object Model)이라는 표준 형식으로 파싱(Parsing)되어 표현된다. 
따라서 사용자 조작에 맞춰 동적으로 변화하는 반응형 웹을 구현하기 위해서는 DOM 조작이 필수적인데, 대부분의 브라우저에서 돔 조작이 발생할 때마다 배치나 화면 표시에 많은 연산을 발생시키다 보니 조작이 빈번해질수록 브라우저 성능이 낮아지는 문제가 있었다.
이러한 이슈를 해결하기 위해 자바스크립트 라이브러리의 하나인 리액트는 VirtualDOM을 채용하여 이를 해결했다.</p>
<h2 id="react의-장점">React의 장점</h2>
<ol>
<li>굉장히 큰 커뮤니티 → 레퍼런스가 많다.</li>
<li>코드 재사용성이 높으며 컴포넌트를 통한 코드 가독성을 높일 수 있다.</li>
<li>VirtualDOM</li>
<li>One Way Data Flow (Flux)</li>
</ol>
<h2 id="react의-단점">React의 단점</h2>
<ol>
<li>높은 상태관리 복잡도</li>
<li>View에 해당하는 부분만 관여하기 때문에 모델링, 라우팅, Ajax등의 기능을 제공하지 않는다.</li>
</ol>
<h2 id="reference">Reference</h2>
<ul>
<li><a href="%5Bhttps://medium.com/@RianCommunity/react%EC%9D%98-%ED%83%84%EC%83%9D%EB%B0%B0%EA%B2%BD%EA%B3%BC-%ED%8A%B9%EC%A7%95-4190d47a28f%5D(https://medium.com/@RianCommunity/react%EC%9D%98-%ED%83%84%EC%83%9D%EB%B0%B0%EA%B2%BD%EA%B3%BC-%ED%8A%B9%EC%A7%95-4190d47a28f)">React 탄생배경과 특징</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[SPA, CSR, SSR 이란?]]></title>
            <link>https://velog.io/@del-luna/SPA-CSR-SSR-%EC%9D%B4%EB%9E%80</link>
            <guid>https://velog.io/@del-luna/SPA-CSR-SSR-%EC%9D%B4%EB%9E%80</guid>
            <pubDate>Tue, 15 Nov 2022 13:19:24 GMT</pubDate>
            <description><![CDATA[<h1 id="csrclient-side-rendering-vs-ssrserver-side-rendering">CSR(Client Side Rendering) vs SSR(Server Side Rendering)</h1>
<p>렌더링 방식이란 결국 화면에 그려지는 HTML을 누가 하느냐 즉, 주체가 누구냐에 따라 CSR, SSR로 나뉘게 된다.</p>
<p><img src="https://velog.velcdn.com/images/del-luna/post/eb36051c-b339-44d7-be55-e66e1d3ed7c4/image.png" alt=""></p>
<pre><code class="language-jsx">&lt;html&gt;
  &lt;head&gt;
    &lt;title&gt;Title&lt;/title&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;div id=&quot;app&quot;&gt;&lt;/div&gt;
  &lt;/body&gt;
&lt;/html&gt;</code></pre>
<p>위의 index.html 파일에는 body 안에 div 하나만 있다. 실제로 이 뼈대 하나만 다운받는다. 우리가 화면을 볼때는 div안에 다양한 tag들이 존재하는데 이를 html파일과 함께 다운받은 js 파일의 로직을 통해서 동적으로 테그나 스타일들을 DOM에 더하여 그리기 때문이다.</p>
<p>다음은 최종적으로 유저가 화면에서 보는 html의 예시 파일이다.</p>
<pre><code class="language-jsx">&lt;html&gt;
  &lt;head&gt;
    &lt;title&gt;Title&lt;/title&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;h1&gt;Hello World!&lt;/h1&gt;
    &lt;p&gt;이것이 최종적으로 화면에서 보고 있는 내용입니다.&lt;/p&gt;
  &lt;/body&gt;
&lt;/html&gt;</code></pre>
<p>쉽게 얘기하면 뼈대만 받고 브라우저(Client)에서 동적으로 DOM을 그리게 되면 CSR이고 위와 같이 이미 다 그려진 DOM을 받게 되면 SSR이다.</p>
<p>CSR, SSR을 살펴보기 전에 SPA부터 살펴보자.</p>
<h2 id="spasingle-page-application">SPA(Single Page Application)</h2>
<p>기술적으로는 SPA는 어떤 페이지를 접속하더라도 HTML, CSS, JS 동일한 파일 하나만 접속한 페이지에 맞게 화면을 구성하고 MPA는 페이지 별로 해당 페이지에 맞는 HTML, CSS, JS 파일을 받아서 화면을 구성한다. 고전적인 방식이 MPA이며 아직도 많이 사용되어지고 있고, 최근 들어 JS 프레임워크들은 SPA를 기본으로 하고 있다.</p>
<p>유저 입장으로 보았을 때는 단순히 페이지 내용이 확 바뀌고 브라우저상에 URL이 다르면 다른 페이지로 인식한다. SPA의 트릭은 하나의 페이지에서 JS를 통하여 보고 있는 DOM의 내용을 모두 제거하고 다른 컨텐츠로 DOM을 채운 다음에 브라우저상에 URL을 강제로 변경하여, 실제로 방문한적도 없는 URL을 방문하여 해당 페이지를 보고 있는 느낌을 주는 것이다.</p>
<h2 id="csrclient-side-rendering">CSR(Client Side Rendering)</h2>
<p><img src="https://velog.velcdn.com/images/del-luna/post/537f35c4-7d78-4871-b3aa-39f75b094765/image.png" alt=""></p>
<p>CSR은 클라이언트 측에서 최초에 1번 서버에서 전체 페이지를 로딩하여 보여준다. 그 이후에는 사용자의 요청이 올 때마다, 자원(Resource)을 서버에서 제공한 후, 클라이언트가 해석하고 렌더링 하는 방식이다.</p>
<p>index.html을 처음 다운 받고 그 안에 js파일들을 다운로드 하게 된다. 모든 코드가 js파일에 존재하기 때문에 처음 번들된 이 파일을 다운받는데 시간이 걸린다.(사용자들이 첫 화면을 보는데 시간이 걸릴 수 있다.)</p>
<h3 id="단점">단점</h3>
<ul>
<li>SEO(검색 엔진 최적화)가 좋지 않다.<ul>
<li>검색 엔진은 index.html을 기준으로 어떤 데이터들이 있는지, 알맞은 태그들이 들어있는지를 판단하여 이 사이트가 알맞은 사이트인지 판단하는데 CSR의 경우 index.html이 초반에 텅 비어있기 때문에 검색엔진의 눈에 띄지 못한다. (구글은 제외)</li>
</ul>
</li>
</ul>
<h3 id="장점">장점</h3>
<ul>
<li><ol>
<li>초기 로딩 속도를 제외하면 나머지 부분은 매우 빠른 사용자 인터랙션 속도를 보여준다. 이미 다운받은 번들링 된 js 파일에 렌더링에 필요한 모든 로직이 들어있기 때문.</li>
</ol>
</li>
<li>서버의 부하를 줄여줄 수 있다.<ul>
<li>서버와는 데이터 주고받는일 밖에 안함</li>
</ul>
</li>
<li>사용성 측면에서 장점<ul>
<li>클라이언트가 페이지 이동할 때 새로고침이 아니라 그냥 리렌더링이 되어버림.(화면 깜빡임 없이 페이지 전환)</li>
</ul>
</li>
</ul>
<h2 id="ssrserver-side-rendering">SSR(Server Side Rendering)</h2>
<p><img src="https://velog.velcdn.com/images%2Flongroadhome%2Fpost%2F11a73998-a9ad-4b6e-a05a-9e5e849d17f8%2F1.png" alt="https://velog.velcdn.com/images%2Flongroadhome%2Fpost%2F11a73998-a9ad-4b6e-a05a-9e5e849d17f8%2F1.png"></p>
<p>전통적인 방식이다. 서버에서 요청한 HTML 파일을 렌더링 마친 상태로 응답해서 로딩 시간이 상대적으로 짧다.</p>
<h3 id="단점-1">단점</h3>
<ul>
<li>각 페이지 별로 로딩 시간 및 새로 고침 현상이 발생한다.</li>
<li>서버가 담당하는일이 많아서 서버에 부하를 줄 가능성이 높다.</li>
</ul>
<h3 id="장점-1">장점</h3>
<ul>
<li>첫 페이지 로딩 시간이 CSR과 비교해 매우 짧다.<ul>
<li>하지만 위 그림에서 보듯 별도의 JS파일을 다운받는 과정이 필요해서 유저 인터랙션에 반응을 보일 때 까지는 조금 시간이 걸린다.)</li>
</ul>
</li>
<li>이미 렌더링된 문서를 전달하므로 SEO에 유리하다.</li>
</ul>
<h2 id="reference">Reference</h2>
<ul>
<li><a href="https://velog.io/@longroadhome/FE-CSRClient-Side-Rendering-vs-SSRServer-Side-Rendering-feat.-React%EB%A5%BC-%EC%A4%91%EC%A0%90%EC%9C%BC%EB%A1%9C">https://velog.io/@longroadhome/FE-CSRClient-Side-Rendering-vs-SSRServer-Side-Rendering-feat.-React를-중점으로</a></li>
<li><a href="https://junghyeonsu.tistory.com/258">https://junghyeonsu.tistory.com/258</a></li>
<li><a href="https://ivorycode.tistory.com/entry/SSRSever-Side-Rendering%EA%B3%BC-CSRClient-Side-Rendering">https://ivorycode.tistory.com/entry/SSRSever-Side-Rendering과-CSRClient-Side-Rendering</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[브라우저 렌더링 원리]]></title>
            <link>https://velog.io/@del-luna/%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80-%EB%A0%8C%EB%8D%94%EB%A7%81-%EC%9B%90%EB%A6%AC</link>
            <guid>https://velog.io/@del-luna/%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80-%EB%A0%8C%EB%8D%94%EB%A7%81-%EC%9B%90%EB%A6%AC</guid>
            <pubDate>Tue, 15 Nov 2022 13:14:28 GMT</pubDate>
            <description><![CDATA[<h1 id="브라우저-렌더링-동작-과정">브라우저 렌더링 동작 과정</h1>
<ol>
<li>브라우저는 HTML, CSS, JS, 이미지, 폰트 등 리소스를 서버에 요청하고, 응답으로 받아온다.</li>
<li>index.html을 받은 브라우저에서는 텍스트로 이루어진 이 파일을 <strong>파싱</strong>하면서 <strong>DOM트리</strong>를 만들어 나간다.</li>
<li>html을 읽다 중간 link tag를 만나 CSS요청이 발생하면 요청과 응답을 거쳐 CSS를 파싱하여 <strong>CSSOM트리</strong>를 만든다.</li>
<li>CSS 파싱이 종료되면 잠시 중단 되었던 html을 다시 읽고 DOM 트리를 완성시킨다.</li>
<li>완성된 DOM 트리와 CSSOM 트리를 합쳐 <strong>렌더트리</strong>를 만들게 된다.</li>
<li>브라우저 JS 엔진은 받아온 JS를 파싱해 AST를 생성하고, 바이트코드로 변환해 실행한다.</li>
<li><strong>렌더트리</strong>를 기반으로 HTML 요소의 <strong>레이아웃</strong>(위치, 크기)을 계산한다.</li>
<li>화면에 HTML요소를 <strong>페인팅</strong>한다.</li>
</ol>
<p><img src="https://velog.velcdn.com/images/del-luna/post/06945813-5143-49e8-ae2c-4360dfcf8e88/image.png" alt=""></p>
<h2 id="parsing">Parsing</h2>
<Blockquote>
HTML 파일을 해석해서 DOM(Document Object Model)을 만들고, CSS파일을 해석해서 CSSOM(CSS Object Model)을 만드는 것!
</Blockquote>

<p>프로그래밍 언어로 작성된 파일을 실행시키기 위해 구문 분석(syntax analysis)을 하는 단계이다. 파일의 문자열들을 문법적 의미를 갖는 최소 단위인 토큰으로 분해하고, 이 토큰들을 문법적 의미와 구조에 따라 노드라는 요소로 만든다. 노드들은 상하관계를 반영해 트리를 형성하는데, 이 트리를 파스트리라고 한다.</p>
<Blockquote>
DOM(Document Object Model) 이란?

<p>쉽게 말해서 HTML 태그를 자바스크립트가 이해할 수 있는 Object(객체)로 표현하는 것!
</Blockquote></p>
<p><img src="https://velog.velcdn.com/images/del-luna/post/8e7a102f-3d96-4f05-b437-bccdf1fb1883/image.png" alt=""></p>
<h2 id="dom트리-생성">DOM트리 생성</h2>
<p>HTML 코드를 파싱해서 뿅! 하고 바로 DOM이 나오면 얼마나 좋겠냐만은, 실제론 아래와 같은 복잡한 여러 절차를 거쳐서 DOM이 나오게 된다.
<img src="https://velog.velcdn.com/images/del-luna/post/19011edd-4348-46ee-81a6-fbf0ec102f00/image.png" alt=""></p>
<p>순서는 다음과 같다.</p>
<ol>
<li>브라우저가 HTML의 원시 바이트를 읽어와 HTML에 정의된 인코딩 (ex: UTF-8)에 따라 개별 문자로 변환한다.</li>
<li>브라우저가 문자열을 (문자열 형태로 표현된 HTML문서) &#39;토큰&#39;단위로 분해한다. (문법적 의미를 갖는 코드의 최소 단위)</li>
<li>분석한 토큰을 바탕으로 노드를 만든다. → 노드를 통해 관계를 표현할 수 있게됨</li>
<li>노드를 바탕으로 DOM을 그린다.</li>
</ol>
<h2 id="rendering-트리-생성">Rendering 트리 생성</h2>
<p><strong>렌더 트리</strong>는 이름처럼 렌더링을 목적으로 만드는 트리이다.</p>
<p>렌더링은 브라우저가 이제 진짜로 사용자에게 보여주기 위한 화면을 그리는 과정이기 때문에, 보이지 않을 요소들은 이 트리에 포함하지 않는다. 예를들어, DOM에서는 meta태그같은 정보전달 목적의 태그나, CSSOM에서는 display:none으로 보이지 않게 해둔 요소 (정확히는 노드)들은 렌더 트리에서는 제외된다. (단, visibility: hidden은 레이아웃 트리에 포함되니 주의하기!)</p>
<p><img src="https://velog.velcdn.com/images/del-luna/post/4da70e60-7086-42f2-aad0-c203adfe92dd/image.png" alt=""></p>
<h2 id="layoutreflow">Layout(Reflow)</h2>
<p>렌더트리를 기반으로 HTML 요소의 레이아웃(위치, 크기)을 계산한다.
이 과정에서 모든 상대적인 측정값은 화면에서 절대적인 픽셀로 변환된다.</p>
<p>  레이아웃은 요소의 기하학적인 속성들을 찾는 과정이다. 아까 만들었던 렌더트리가 여기서 사용되니 다시 떠올려야 한다. 렌더트리에는 요소들의 위치나 크기와 관련된 정보들이 들어있었다. 하지만 이 정보들은 각 요소들에 대한 정보일 뿐, 전체 화면에서 <strong>정확히 어디에 위치할 것인지</strong>에 대해서는 아직 알지 못한다. 이런 계산을 하는 단계가 레이아웃 단계이다. 브라우저는 각 요소들이 전체 화면에서 어디에, 어떤 크기로 배치되어야 할 지 파악하기 위해 렌더트리의 맨 윗부분부터 아래로 내려가며 계산을 진행한다. 모든 값들은 절대적인 단위인 px값으로 변환된다.</p>
<p>예를들어 우리가 <strong>div</strong>요소 하나만 띄우도록 코드를 작성했고, width를 50%로 지정해두었다면, 이 값은 전체 화면 크기(viewport)의 절반 크기로 계산되고, 절대적인 값인 px 단위로 변환되는 식이다.</p>
<p><img src="https://velog.velcdn.com/images/del-luna/post/51b4161d-d167-405b-92f7-80f00120f714/image.png" alt=""></p>
<h2 id="painting">Painting</h2>
<p>화면에 HTML요소를 페인팅한다.</p>
<p>  이제 위치에 대한 계산도 마쳤으니, 정말로 화면에 보여줄 차례
이다. 브라우저 화면은 픽셀이라고 하는 정말 작은 점들로 이루어져 있다. 각각 정보를 가진 픽셀들이 모여 하나의 이미지, 화면을 구성하는 것이다. 따라서 화면에 색상을 입히고, 어떤 요소를 보여주기 위해서는 이 픽셀에 대한 정보가 있어야 한다. 페인팅은 이러한 픽셀들을 채워나가는 과정이다. 따라서 이 과정을 마지막으로 우리는 단순한 텍스트에 불과했던 파일 내용들을 이미지화된 모습으로 브라우저 화면을 통해 볼 수 있게되는 것이다.</p>
<p><img src="https://velog.velcdn.com/images/del-luna/post/f47a92e7-ed33-4c54-8314-96e4922a142b/image.png" alt=""></p>
<h2 id="reference">Reference</h2>
<ul>
<li><a href="https://basemenks.tistory.com/292">https://basemenks.tistory.com/292</a></li>
<li><a href="https://medium.com/%EA%B0%9C%EB%B0%9C%EC%9E%90%EC%9D%98%ED%92%88%EA%B2%A9/%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80%EC%9D%98-%EB%A0%8C%EB%8D%94%EB%A7%81-%EA%B3%BC%EC%A0%95-5c01c4158ce">https://medium.com/개발자의품격/브라우저의-렌더링-과정-5c01c4158ce</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[TypeScript (1)]]></title>
            <link>https://velog.io/@del-luna/TypeScript-1</link>
            <guid>https://velog.io/@del-luna/TypeScript-1</guid>
            <pubDate>Thu, 27 Oct 2022 10:24:20 GMT</pubDate>
            <description><![CDATA[<h1 id="typing-the-props">Typing the Props</h1>
<p>평소에 하는대로 React 컴포넌트를 통해 props를 전달해봅시다.</p>
<pre><code class="language-javascript">import styled from &quot;styled-components&quot;;

const Container = styled.div`
  width: 100px;
  height: 100px;
  background-color: ${props=&gt;props.bgColor};
`;

const Text = styled.h1``;

function Circle({bgColor}){
  return &lt;Container bgColor={bgColor}/&gt;
}

function App() {
  return (
    &lt;&gt;
      &lt;Circle bgColor=&quot;tomato&quot;/&gt;
    &lt;/&gt;
  );
}

export default App;</code></pre>
<p>타입 스크립트에서 이런식으로 작성하면 두 가지 문제점이 발생합니다.</p>
<ol>
<li>props의 타입에 대한 문제</li>
<li>styled-components 내에서 작성한 props.bgColor의 타입에 대한 문제</li>
</ol>
<p>1번을 해결하려면 props의 타입을 interface를 통해 정의해주면 됩니다.</p>
<pre><code class="language-javascript">interface CircleProps {
  bgColor: string;
}

function Circle({bgColor}:CircleProps){
  return &lt;Container bgColor={bgColor}/&gt;
}
</code></pre>
<p>2번의 경우 TypeScript에게 bgColor를 styled-component에게도 보내고 싶다고 알려줘야 합니다.
동일하게 interface를 작성하면 되지만 여기선 bgColor가 string 타입으로 동일하므로 CircleProps를 재사용 해봅시다.</p>
<pre><code class="language-javascript">const Container = styled.div&lt;CircleProps&gt;`
  width: 100px;
  height: 100px;
  background-color: ${props=&gt;props.bgColor};
`;</code></pre>
<p>이렇게 하면 모든 경고가 사라지고 화면이 렌더링 됩니다.</p>
<p><img src="https://velog.velcdn.com/images/del-luna/post/24f4d475-1745-49f8-b75f-93e5989871ea/image.png" alt=""></p>
<p>이번엔 컴포넌트 두개를 통해 하나는 사각형으로 하나는 원으로 출력해봅시다.
동일한 코드로 사각형을 두개 만들어주고, 하나는 원으로 깎아봅시다.</p>
<pre><code class="language-javascript">function App() {
  return (
    &lt;&gt;
      &lt;Circle bgColor=&quot;tomato&quot;/&gt;
      &lt;Circle bgColor=&quot;teal&quot; borderRadius=&quot;100px&quot;/&gt;
    &lt;/&gt;
  );
}</code></pre>
<p>기존에 하던 것 처럼 TS에게 새로운 props이 들어왔으니 타입 힌트를 줘야겠죠?
interface에 새로운 props의 타입을 등록해줍니다.</p>
<pre><code class="language-javascript">interface CircleProps {
  bgColor: string;
  borderRadius: string;
}</code></pre>
<p>그런데 이렇게 하면 첫 번째 도형에서 에러가 납니다.
<code>Property &#39;borderRadius&#39; is missing in type &#39;{ bgColor: string; }&#39; but required in type &#39;CircleProps&#39;.</code></p>
<p>&quot;CircleProps에서 borderRadius 타입 써놓고 왜 사용안하니?&quot; 라는 내용입니다.
이를 해결해주려면 다음과 같이 물음표를 추가해주면 됩니다.</p>
<pre><code class="language-javascript">interface CircleProps {
  bgColor: string;
  borderRadius?: string;
}</code></pre>
<p>이렇게 되면 기존에 string 타입으로만 정의된 borderRadius에 undefined 가 들어와도 허용하겠다는 뜻으로 변경됩니다.
<code>CircleProps.borderRadius?: string | undefined</code></p>
<p><img src="https://velog.velcdn.com/images/del-luna/post/597b68a4-609f-4127-a8d8-3f5533303886/image.png" alt=""></p>
<h1 id="optrinal-props">Optrinal Props</h1>
<p>대분의 경우 컴포넌트의 Props와 Styled Components의 props가 같지는 않습니다.
연습을 위해 두개의 interface를 분리해준 상태로 다시 전체 코드를 봅시다.</p>
<pre><code class="language-javascript">import styled from &quot;styled-components&quot;;

interface ContainerProps{
  bgColor: string;
  borderRadius: string;
}

interface CircleProps {
  bgColor: string;
  borderRadius?: string;
}
const Container = styled.div&lt;ContainerProps&gt;`
  width: 100px;
  height: 100px;
  background-color: ${props=&gt;props.bgColor};
  border-radius: ${props=&gt;props.borderRadius};
`;

const Text = styled.h1``;

function Circle({bgColor, borderRadius}:CircleProps){
  return &lt;Container bgColor={bgColor} borderRadius={borderRadius}/&gt;
}

function App() {
  return (
    &lt;&gt;
      &lt;Circle bgColor=&quot;tomato&quot;/&gt;
      &lt;Circle bgColor=&quot;teal&quot; borderRadius=&quot;100px&quot;/&gt;
    &lt;/&gt;
  );
}

export default App;</code></pre>
<p>만약 이렇게 작성하면 또 styled components 부분에서 에러가 발생할 것 입니다.
제가 ContainerProps에는 ?를 안줬거든요,</p>
<pre><code class="language-javascript">interface ContainerProps{
  bgColor: string;
  borderRadius: string;
}</code></pre>
<pre><code class="language-javascript">interface CircleProps {
  bgColor: string;
  borderRadius?: string;
}</code></pre>
<p>배운지 하루차인 제 생각이지만 ? 기호를 남발해서 undefined를 허용해주는 것은 그다지 TS에서 지향해야 하는 방법은 아닐 것 같습니다.
애초에 TS를 쓰는 목적이 타입 어노테이션을 통해 컴파일 전에 에러를 방지하고자 하는 목적이 크니까요.</p>
<p>그렇다면 이 문제를 어떻게 해결할 수 있을까요?
에러가 나는 부분은 다음 코드입니다.</p>
<pre><code class="language-javascript">return &lt;Container bgColor={bgColor} borderRadius={borderRadius}/&gt;</code></pre>
<p>borderRadius가 한쪽 Container에만 사용되고 있다고 찡찡대니까, default 값을 줘버리면 될 것 같네요.
다음과 같이 바꿔봅시다.</p>
<pre><code class="language-javascript">&lt;Container bgColor={bgColor} borderRadius={borderRadius ?? &quot;0px&quot;}/&gt;</code></pre>
<p>이 코드는 borderRadius값이 존재하면 ??의 왼쪽인 borderRadius를 쓰고, 없으면 &quot;0px&quot;로 하겠다 라는 뜻입니다.</p>
<p>아니면 React Props를 전달할 때 default 값을 주는 방법도 좋겠네요!</p>
<pre><code class="language-javascript">function Circle({bgColor, borderRadius=&quot;0px&quot;}:CircleProps){
  return &lt;Container bgColor={bgColor} borderRadius={borderRadius}/&gt;
}</code></pre>
<p>두 가지 다 좋은 방법인 것 같습니다😊</p>
<h1 id="주관적-후기">주관적 후기</h1>
<p>TypeScript를 배운 첫날인데 굉장히 마음에 들었습니다.
기존에 파이썬을 사용해서 동적 타이핑언어에 익숙해져 있기 때문에 TypeScript를 배우는 것이 꺼려졌는데 오히려 JS보다 훨씬 직관적이고 편했습니다.
애초에 JS는 에러가 엄청 불친절했는데 TS의 경우 매우 친절하게 에러를 알려주기 때문에 내가 뭘 잘못했는지 티칭받는 느낌이었습니다.</p>
<p>결론: TS 짱짱😊</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Styled Components (3)]]></title>
            <link>https://velog.io/@del-luna/Styled-Components-3</link>
            <guid>https://velog.io/@del-luna/Styled-Components-3</guid>
            <pubDate>Wed, 26 Oct 2022 11:52:13 GMT</pubDate>
            <description><![CDATA[<h1 id="animation-and-pseudo-selectors">Animation and Pseudo Selectors</h1>
<p>애니메이션은 기존의 css와 다른점이 딱히 없습니다.
keyframes라는 모듈을 불러와 사용하게 되는데 바로 코드 보시죠.</p>
<pre><code class="language-javascript">import styled, {keyframes} from &quot;styled-components&quot;;

const Container = styled.div`
  margin: 10px;
`;

const animation = keyframes`
  0%{
    transform:rotate(0deg);
    border-radius: 0px;
  }
  50%{
    transform: rotate(360deg);
    border-radius: 100px;
  }
  100%{
    transform:rotate(0deg);
    border-radius: 0px;
  }
`;

const Box = styled.div`
  height: 50px;
  width: 50px;
  background-color: tomato;
  animation: ${animation} 2s ease-in-out infinite;
`;

function App() {
  return (
    &lt;Container&gt;
      &lt;Box /&gt;
    &lt;/Container&gt;
  );
}

export default App;
</code></pre>
<p>keyframes로 animation을 정의해주고
이 애니메이션을 css animation에 불러와주면 끝입니다.
<img src="https://velog.velcdn.com/images/del-luna/post/cc9c7cf8-22e0-4d1c-8b3f-4764db01ccd2/image.png" alt=""></p>
<p>추가적으로 이모지를 하나 넣어봅시다.</p>
<pre><code class="language-javascript">function App() {
  return (
    &lt;Container&gt;
      &lt;Box&gt;
        &lt;span&gt;🎃&lt;/span&gt;
      &lt;/Box&gt;
    &lt;/Container&gt;
  );
}</code></pre>
<p><img src="https://velog.velcdn.com/images/del-luna/post/ca134cc7-62f0-422b-9187-3ac7c3b5dc1b/image.png" alt=""></p>
<p>만약 이 상태에서 이모지에 특정 스타일을 입히고 싶다면 어떻게 해야할까요?</p>
<p>기존 방식대로라면 span 태그로 styled Components를 만들어서 새로운 컴포넌트를 사용하면 될텐데, 이번엔 좀 다른 방식으로 Selector를 활용해 봅시다.</p>
<pre><code class="language-javascript">const Box = styled.div`
  height: 50px;
  width: 50px;
  background-color: tomato;
  display: flex;
  align-items: center;
  justify-content: center;
  animation: ${animation} 2s ease-in-out infinite;

  span{
    font-size: 30px;
  }

`;</code></pre>
<p>단순히 Box 안에 span태그를 cascade형식으로 작성해주는 것으로 끝이 납니다.</p>
<p><img src="https://velog.velcdn.com/images/del-luna/post/d8b58a5a-8fb8-400b-bfc0-dcaad8c8e499/image.png" alt=""></p>
<p>만약! 여기서 span태그를 p나 a태그로 바꾸게 되면 당연히 Selector가 동작하지 않겠죠?
이런 경우에 태그에 의존하지 않고 Selector를 작동하고 싶으면 Emoji라는 새로운 컴포넌트를 작성해서 이 친구를 Box 안에서 select 해주면 될 것 같네요.</p>
<pre><code class="language-javascript">const Emoji = styled.span`
  font-size: 30px;
`

const Box = styled.div`
  height: 50px;
  width: 50px;
  background-color: tomato;
  display: flex;
  align-items: center;
  justify-content: center;
  animation: ${animation} 2s ease-in-out infinite;

  ${Emoji}{
    &amp;:hover{
      font-size: 10px;
    }
  }

`;</code></pre>
<p><img src="https://velog.velcdn.com/images/del-luna/post/b7e30d30-e186-4500-a42f-0ed071b77f3a/image.png" alt=""></p>
<p>hover한 경우 위와 같이 잭오랜턴의 size가 작아집니다.
또한 태그에 상관없이 잘 동작하게 됩니다.</p>
<pre><code class="language-javascript">function App() {
  return (
    &lt;Container&gt;
      &lt;Box&gt;
        &lt;Emoji as=&quot;p&quot;&gt;🎃&lt;/Emoji&gt;
      &lt;/Box&gt;
    &lt;/Container&gt;
  );
}
</code></pre>
<p><img src="https://velog.velcdn.com/images/del-luna/post/5a002fef-9f38-4f83-bd88-c63a2946e84d/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Styled Components (2)]]></title>
            <link>https://velog.io/@del-luna/Styled-Components-2</link>
            <guid>https://velog.io/@del-luna/Styled-Components-2</guid>
            <pubDate>Wed, 26 Oct 2022 11:27:13 GMT</pubDate>
            <description><![CDATA[<h1 id="as-and-attrs">As and Attrs</h1>
<p>버튼 태그를 하나 만들어 봅시다.</p>
<pre><code class="language-javascript">import styled from &quot;styled-components&quot;;

const Container = styled.div`
  margin: 10px;
  background-color: whitesmoke;
  display: flex;
`;

const Btn = styled.button`
  margin: 0 auto;
  color: white;
  background-color: tomato;
  border: 0;
  border-radius: 15px;
`;

function App() {
  return (
    &lt;Container&gt;
      &lt;Btn&gt;Zero&lt;/Btn&gt;
    &lt;/Container&gt;
  );
}

export default App;
</code></pre>
<p><img src="https://velog.velcdn.com/images/del-luna/post/6c55d998-238a-4ebd-9940-ab3a5437f47d/image.png" alt="">
<img src="https://velog.velcdn.com/images/del-luna/post/439779a3-dc3f-4cf8-86e0-5a60520d68af/image.png" alt=""></p>
<p>이 친구는 당연히 button class겠죠?
만약 모종의 이유로 이 style은 그대로 유지하되 다른 태그를 쓰고 싶다면 어떻게 해야 할까요?
이럴 때 사용할 수 있는 것이 &#39;As&#39; 입니다.</p>
<pre><code class="language-javascript">&lt;Btn&gt;Zero&lt;/Btn&gt;
&lt;Btn as=&quot;span&quot;&gt;One&lt;/Btn&gt;</code></pre>
<p><img src="https://velog.velcdn.com/images/del-luna/post/91205546-c3a4-4f45-a481-6fb7a59ebf59/image.png" alt="">
<img src="https://velog.velcdn.com/images/del-luna/post/6f873417-cdea-4587-98d4-e4e4f3e075f6/image.png" alt=""></p>
<p>보시는 것 처럼 style은 동일하지만 태그는 span인 상태로 컴포넌트가 생성되는 것을 확인할 수 있습니다.</p>
<p>이번엔 Attrs에 대해 살펴봅시다.
만약에 특정 html 태그에 대해 모두 동일한 속성을 주고 싶을 때 사용하면 좋은 기능입니다.</p>
<p>Input 기능을 여러개 만들고 모두 required가 필요하다고 가정해봅시다.</p>
<pre><code class="language-javascript">import styled from &quot;styled-components&quot;;

const Container = styled.div`
  margin: 10px;
  background-color: whitesmoke;
`;

const Input = styled.input`
  background-color: tomato;
`;

function App() {
  return (
    &lt;Container&gt;
      &lt;Input required/&gt;
      &lt;Input required/&gt;
      &lt;Input required/&gt;
      &lt;Input required/&gt;
      &lt;Input required/&gt;
    &lt;/Container&gt;
  );
}

export default App;</code></pre>
<p><img src="https://velog.velcdn.com/images/del-luna/post/c13ae8f0-6507-4103-a7b4-8f7d947c8bab/image.png" alt="">
일일이 Input 컴포넌트에  required 속성을 주는건 너무 비효율적인데 한번에 줄 수 있는 방법이 없을까요? 바로 이 때 Attrs를 사용하면 됩니다.
attrs()에는 후에 Input으로 전달될 모든 속성을 가진 오브젝트를 담을 수 있습니다.</p>
<pre><code class="language-javascript">import styled from &quot;styled-components&quot;;

const Container = styled.div`
  margin: 10px;
  background-color: whitesmoke;
`;

const Input = styled.input.attrs({required: true})`
  background-color: tomato;
`;

function App() {
  return (
    &lt;Container&gt;
      &lt;Input /&gt;
      &lt;Input /&gt;
      &lt;Input /&gt;
      &lt;Input /&gt;
    &lt;/Container&gt;
  );
}

export default App;</code></pre>
<p><img src="https://velog.velcdn.com/images/del-luna/post/b18689d1-6f33-43e4-89cf-c39305c24fb3/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Styled Components (1)]]></title>
            <link>https://velog.io/@del-luna/Styled-Components-1</link>
            <guid>https://velog.io/@del-luna/Styled-Components-1</guid>
            <pubDate>Wed, 26 Oct 2022 11:13:03 GMT</pubDate>
            <description><![CDATA[<h1 id="adapting-and-extending">Adapting and Extending</h1>
<p>니꼴라스의 React JS 마스터 클래스를 듣고 정리한 내용입니다.</p>
<p>아주 가벼운 예시인 박스 두개를 Styled Components로 작성해봅시다.</p>
<pre><code class="language-javascript">import styled from &quot;styled-components&quot;;

const Container = styled.div`
  margin: 10px;
  background-color: whitesmoke;
  display: flex;
`;

const BoxOne = styled.div`
  background-color: tomato;
  width: 100px;
  height: 100px;
`;

const BoxTwo = styled.div`
  background-color: aqua;
  width: 100px;
  height: 100px;
`;

function App() {
  return (
    &lt;Container&gt;
      &lt;BoxOne /&gt;
      &lt;BoxTwo /&gt;
    &lt;/Container&gt;
  );
}

export default App;
</code></pre>
<p>결과는 다음과 같습니다.</p>
<p><img src="https://velog.velcdn.com/images/del-luna/post/35cf0584-a9f6-4fa9-8d5b-5c0c124dd507/image.png" alt=""></p>
<p>그런데 BoxOne과 BoxTwo의 코드가 background-color를 제외하면 동일합니다.
코드 재사용을 줄일 수 있는 방법이 있겠죠?
바로 리액트 컴포넌트의 props로 값을 전달하는 방식입니다.</p>
<pre><code class="language-javascript">const Box = styled.div`
  background-color: ${(props)=&gt;props.bgColor};
  width: 100px;
  height: 100px;
`;

function App() {
  return (
    &lt;Container&gt;
      &lt;Box bgColor=&#39;tomato&#39;/&gt;
      &lt;Box bgColor=&#39;aqua&#39;/&gt;
    &lt;/Container&gt;
  );
}

export default App;</code></pre>
<p>이렇게 작성해도 결과는 동일합니다!</p>
<p>만약 기존의 코드를 재사용해서 추가로 css style을 작성하고 싶다면? -&gt; 이 방법 또한 가능합니다.</p>
<pre><code class="language-javascript">const Box = styled.div`
  background-color: ${(props)=&gt;props.bgColor};
  width: 100px;
  height: 100px;
`

const Circle = styled(Box)`
  border-radius: 50px;
`

function App() {
  return (
    &lt;Container&gt;
      &lt;Box bgColor=&#39;tomato&#39;/&gt;
      &lt;Circle bgColor=&#39;aqua&#39;/&gt;
    &lt;/Container&gt;
  );
}

export default App;</code></pre>
<p>Box를 받아 Circle 컴포넌트를 만드는 예제입니다.
기존에 Box에 있는 style을 그대로 사용하기 때문에 props로 color를 전달해서 사용하는 부분도 동일하게 재사용 가능합니다!</p>
<p><img src="https://velog.velcdn.com/images/del-luna/post/a08a0946-8fba-44af-b76e-181bc2916ded/image.png" alt=""></p>
<h1 id="reference">Reference</h1>
<p><a href="https://nomadcoders.co/react-masterclass/lectures/3314">ReactJS 마스터 클래스</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Why Styled Components?]]></title>
            <link>https://velog.io/@del-luna/Why-Styled-Components</link>
            <guid>https://velog.io/@del-luna/Why-Styled-Components</guid>
            <pubDate>Wed, 26 Oct 2022 10:58:13 GMT</pubDate>
            <description><![CDATA[<h1 id="css-in-js">CSS-in-JS</h1>
<p>CSS-in-JS는 css나 scss를 사용하지 않고 JS로 작성한 컴포넌트에 바로 삽입하는 스타일 기법을 뜻합니다.</p>
<p><strong>CSS-in-JS의 장점</strong></p>
<ul>
<li>Local Scoping</li>
<li>Encapsulation</li>
<li>Portability</li>
<li>Reusability</li>
<li>Dynamic Functionality</li>
</ul>
<p><strong>CSS-in-JS의 단점</strong></p>
<ul>
<li>Learning Curve</li>
<li>Extra Layer of Complexity</li>
<li>Code Readability</li>
</ul>
<p>React에서 컴포넌트 스타일링을 하는 세 가지 방법은 다음과 같습니다.</p>
<ul>
<li>외부 css 파일작성해서 className으로 속성 전달하기</li>
<li>inline CSS</li>
<li>CSS-in-JS</li>
</ul>
<p>외부 css파일 작성 및 className 사용은 가장 기본적인 방법입니다.
inline의 경우는 지속성과 확장성이 떨어지므로 React에서 권장하지 않는다고 합니다.</p>
<p>라는게 구글링을 통해 알아본 결과였습니다.</p>
<p>제가 직접 2주간 사용해본 결과 프론트엔드 뉴비의 입장에서 CSS-in-JS의 가장 큰 장점은,
컴포넌트 자체를 커스텀 하는 느낌이라 컴포넌트 변수명을 잘 지으면 직관적으로 어떤 코드인지 이해하기가 쉽습니다. --&gt; 그냥 직관적이고, 가독성이 좋다는 것입니다.</p>
<pre><code>&lt;div style={{backgroundColor:&quot;orange&quot; ~~~ }}&gt;&lt;/div&gt;</code></pre><p>이런 인라인 스타일과, className의 경우엔 남발된 div태그가 어떤 역할인지 이해하려면 style을 직접 읽어야 하는데, Styled Components로 생성한 컴포넌트의 경우엔</p>
<pre><code>const Box = styled.div`
  background-color: ${props =&gt; props.tomato ? &#39;tomato&#39;:&#39;teal&#39;};
  width: 100px;
  height: 100px;
`;

&lt;Box /&gt;
&lt;Box tomato /&gt;</code></pre><p>위와 같이 그냥 컴포넌트 변수명 자체로 직관적으로 다가오는 경우가 많아서 스타일을 굳이 읽지 않아도 어떤 역할을 하는지 이해하기 쉬웠던 것 같습니다.</p>
<h1 id="reference">Reference</h1>
<ul>
<li><a href="https://webdesign.tutsplus.com/articles/an-introduction-to-css-in-js-examples-pros-and-cons--cms-33574">An Introduction to CSS-in-JS: Examples, Pros, and Cons</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[React Carousel 만들기 (1)]]></title>
            <link>https://velog.io/@del-luna/React-Carousel-%EB%A7%8C%EB%93%A4%EA%B8%B0-1</link>
            <guid>https://velog.io/@del-luna/React-Carousel-%EB%A7%8C%EB%93%A4%EA%B8%B0-1</guid>
            <pubDate>Wed, 19 Oct 2022 07:29:29 GMT</pubDate>
            <description><![CDATA[<p><a href="https://velog.io/@97godo/React-Hooks%EB%A1%9C-Carousel-%EB%A7%8C%EB%93%A4%EA%B8%B0">97godo 님의 글</a>을 보고 캐러셀 만들기에 도전해봤습니다.</p>
<h3 id="전체-코드">전체 코드</h3>
<pre><code>const TOTAL_SLIDES = 2; // 전체 슬라이드 개수(총3개. 배열로 계산)

export default function Slider() {
  const [currentSlide, setCurrentSlide] = useState(0);
  const slideRef = useRef(null);

  // Next 버튼 클릭 시
  const NextSlide = () =&gt; {
    if (currentSlide &gt;= TOTAL_SLIDES) {
      // 더 이상 넘어갈 슬라이드가 없으면
      setCurrentSlide(0); // 1번째 사진으로 넘어갑니다.
      // return;  // 클릭이 작동하지 않습니다.
    } else {
      setCurrentSlide(currentSlide + 1);
    }
  };
  // Prev 버튼 클릭 시
  const PrevSlide = () =&gt; {
    if (currentSlide === 0) {
      setCurrentSlide(TOTAL_SLIDES); // 마지막 사진으로 넘어갑니다.
      // return;  // 클릭이 작동하지 않습니다.
    } else {
      setCurrentSlide(currentSlide - 1);
    }
  };

  useEffect(() =&gt; {
    slideRef.current.style.transition = &#39;all 0.5s ease-in-out&#39;;
    slideRef.current.style.transform = `translateX(-${currentSlide}00%)`; // 백틱을 사용하여 슬라이드로 이동하는 에니메이션을 만듭니다.
  }, [currentSlide]);

  return (
    &lt;Container&gt;
      &lt;Text&gt;
        &lt;h1&gt;호두 아가 시절&lt;/h1&gt;
        &lt;p&gt;{currentSlide + 1}번 째 사진&lt;/p&gt;
      &lt;/Text&gt;
      &lt;SliderContainer ref={slideRef}&gt;
        &lt;Slide img={img1} /&gt;
        &lt;Slide img={img2} /&gt;
        &lt;Slide img={img3} /&gt;
      &lt;/SliderContainer&gt;
      &lt;Center&gt;
        &lt;Button onClick={PrevSlide}&gt;Prev&lt;/Button&gt;
        &lt;Button onClick={NextSlide}&gt;Next&lt;/Button&gt;
      &lt;/Center&gt;
    &lt;/Container&gt;
  );
}</code></pre><h2 id="useref를-사용하여-slider-구현하기">UseRef를 사용하여 Slider 구현하기</h2>
<pre><code> useEffect(() =&gt; {
    slideRef.current.style.transition = &#39;all 0.5s ease-in-out&#39;;
    slideRef.current.style.transform = `translateX(-${currentSlide}00%)`;
  }, [currentSlide]);</code></pre><p>탑다운으로 공부하고 있었기 때문에 CSS Transition에 대한 내용인지도 몰랐습니다.</p>
<p>Transition은 아래 4가지의 shorthand property입니다.</p>
<ul>
<li>transition-property</li>
<li>transition-duration</li>
<li>transition-timing-function</li>
<li>transition-delay</li>
</ul>
<p>그러니까 &#39;<strong>all 0.5s ease-in-out</strong>&#39;의 경우 아래와 같습니다.</p>
<ul>
<li>property: all (모든 속성이 transition 효과를 얻는다.)</li>
<li>duration: 0.5s (0.5초 동안 변화가 일어난다.)</li>
<li>timing-function: ease-in-out (시작 지점과 종료 지점의 변화가 천천히 진행된다.)</li>
</ul>
<p><code>translateX(-${currentSlide}00%)</code>;의 경우 이해하기 쉽습니다.
캐러셀의 경우 전체 이미지를 배열처럼 쭉 나열한 것인데, 이를 다음 이미지로 넘기는 것을 구현한 것이라고 볼 수 있습니다.</p>
<p>useEffect의 [currentSlide]를 통해 prev or next 버튼으로 currentSlide의 state가 업데이트 되는 경우 슬라이딩 되도록 해주는 코드라고 볼 수 있습니다.</p>
<h2 id="level-up">Level up</h2>
<p>위 코드에서 개선하고 싶은 부분은 총 3가지 입니다.</p>
<ul>
<li>auto slide 기능 추가</li>
<li>캐러셀 전체의 이미지 개수와 현재 위치를 보여주는 dot 추가</li>
<li>맨 마지막 슬라이드에서 처음으로 돌아갈 때 -&gt; 방향이 아닌 &lt;- 방향으로 초기화 되는 문제</li>
</ul>
<p>다음 포스팅에서는 이 3가지에 대한 내용을 기록해보겠습니다.</p>
]]></description>
        </item>
    </channel>
</rss>