<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>jonguk.log</title>
        <link>https://velog.io/</link>
        <description>안녕하세요! 만나서 반갑습니다.</description>
        <lastBuildDate>Tue, 12 Dec 2023 08:01:04 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>jonguk.log</title>
            <url>https://velog.velcdn.com/images/loo-ke/profile/e554e666-7b23-4875-8177-df0ccdae37ef/image.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. jonguk.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/loo-ke" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[vue.js 설치 및 세팅]]></title>
            <link>https://velog.io/@loo-ke/vue.js-%EC%84%A4%EC%B9%98-%EB%B0%8F-%EC%84%B8%ED%8C%85</link>
            <guid>https://velog.io/@loo-ke/vue.js-%EC%84%A4%EC%B9%98-%EB%B0%8F-%EC%84%B8%ED%8C%85</guid>
            <pubDate>Tue, 12 Dec 2023 08:01:04 GMT</pubDate>
            <description><![CDATA[<h2 id="vue-설치">vue 설치</h2>
<h4 id="nodejs-설치">node.js 설치</h4>
<ul>
<li>npm 사용을 위해 node.js 다운로드<h4 id="vs-code-설치-및-익스텐션-설치">vs code 설치 및 익스텐션 설치</h4>
</li>
<li>에디터 설치 후 </li>
<li>익스텐션<ul>
<li>Vetur</li>
<li>Vue 3 Snippets</li>
<li>HTML CSS Support</li>
</ul>
</li>
</ul>
<h4 id="vs-터미널">vs 터미널</h4>
<ol>
<li><p>vue 설치</p>
<blockquote>
<p><code>npm install -g @vue/cli</code></p>
</blockquote>
</li>
<li><p>파일 생성</p>
<blockquote>
<p><code>vue create 파일명</code></p>
</blockquote>
</li>
</ol>
<h3 id="에러">에러</h3>
<h4 id="vue-파일-생성중-에러">vue 파일 생성중 에러</h4>
<ul>
<li>대충 권한이 없다고 하고 error 메세지중에 밑의 코드를 입력하라고 안내가 되어있었다.</li>
</ul>
<blockquote>
<p><code>sudo chown -R 501:20 &quot;/Users/내맥북이름/.npm&quot;</code>
그 결과, 설치 성공!!</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[면접... 트러블슈팅(?)...]]></title>
            <link>https://velog.io/@loo-ke/%EB%A9%B4%EC%A0%91...-%ED%8A%B8%EB%9F%AC%EB%B8%94%EC%8A%88%ED%8C%85</link>
            <guid>https://velog.io/@loo-ke/%EB%A9%B4%EC%A0%91...-%ED%8A%B8%EB%9F%AC%EB%B8%94%EC%8A%88%ED%8C%85</guid>
            <pubDate>Wed, 06 Dec 2023 08:41:34 GMT</pubDate>
            <description><![CDATA[<p>면접을 봤다...
아쉬운 부분 투성인데 너무 아쉬웠던 부분은 사전 과제에 대해 추가 요구사항을 푸는 것이다.
디바운스 기능에 maxWait의 기능을 넣어서 구현하는 방법을 생각해보라고 하셨는데 너무 긴장한 나머지 대충 얼렁뚱땅 넘어갔다....
멍청하게 setTimeout에 인자를 더 준다고 말했다.</p>
<pre><code>const debounce = (func, wait = 500, immediate = false) =&gt; {
  let timeoutId;
  let promise;
  let resolvePromise; 

  const setPromise = () =&gt; {
    if(resolvePromise) {
      resolvePromise();
      resolvePromise = null;
    }
  }

  const debounced = () =&gt; {
    const later = () =&gt; {
      timeoutId = null;
      if (!immediate) {
        func();
        setPromise();
      }
    }
    clearTimeout(timeoutId);

    if (!promise) {
      promise = new Promise(resolve =&gt; {
        resolvePromise = resolve;
      });
    }
    if (immediate) {
      func();
      setPromise();
    }
    timeoutId = setTimeout(later, wait);

    return promise;
  };

  debounced.cancel = () =&gt; {
    clearTimeout(timeoutId);
    timeoutId = null;
    setPromise();
  };

  return debounced;
}
</code></pre><p>이 코드에서 만약 지정된 시간에 디바운스가 실행이 안되면 최대 지정 시간에는 실행되게 하라는 추가사항이였다...</p>
<p>그렇다면 maxWait을 인자로 받고 받은 인자를 이용해서 만들면 될거라고 생각했다.
여기까지는 좋았으나 갑자기 웬걸 setTimeout에 너무 집중하는 바람에 setTimeout에 인자를 추가한다고 했다.
setTimeout을 재 설정해서 인자에 추가한다고 했어야됐는데....
코드로 보면</p>
<pre><code>const debounce = (func, wait = 500, immediate = false, maxWait = 1000) =&gt; {
  let timeoutId;
  let maxTimeoutId;// 새로운 변수 선언해줌
  let promise;
  let resolvePromise; 

  const setPromise = () =&gt; {
    if(resolvePromise) {
      resolvePromise();
      resolvePromise = null;
    }
  }

  const debounced = () =&gt; {
    const later = () =&gt; {
      timeoutId = null;
      if (!immediate) {
        func();
        setPromise();
      }
      maxTimeoutId = null; 
      clearTimeout(maxTimeoutId);
    }
    clearTimeout(timeoutId);
    clearTimeout(maxTimeoutId);//이전 setTimeout이 할당된 maxTimeoutId를 클리어 해줌

    if (!promise) {
      promise = new Promise(resolve =&gt; {
        resolvePromise = resolve;
      });
    }
    if (immediate) {
      func();
      setPromise();
    }
    timeoutId = setTimeout(later, wait);
    maxTimeoutId = setTimeout(()=&gt;{
      if(timeoutId){
        later();
    }}, maxWait);

    return promise;
  };

  debounced.cancel = () =&gt; {
    clearTimeout(timeoutId);
    timeoutId = null;
    setPromise();
  };

  return debounced;
}
</code></pre><h4 id="실행-과정">실행 과정</h4>
<ol>
<li>maxWait을 인자로 받음</li>
<li>setTimeout()에 의해 maxWait 시간이 지난 후 later가 실행되게 설정</li>
<li>만약 later가 wait만 기다렸다가 실행이 되면 함수는 promise를 완료상태로 만들고 max를 clear 해준다.</li>
<li>만약 later가 실행이 안되면 setTimeout에 의해 max시간이 지나고 later가 실행돼서 max를 clear해서 초기화 해준다.</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[면접 예상 질문]]></title>
            <link>https://velog.io/@loo-ke/%EB%A9%B4%EC%A0%91-%EC%98%88%EC%83%81-%EC%A7%88%EB%AC%B8</link>
            <guid>https://velog.io/@loo-ke/%EB%A9%B4%EC%A0%91-%EC%98%88%EC%83%81-%EC%A7%88%EB%AC%B8</guid>
            <pubDate>Mon, 04 Dec 2023 13:09:24 GMT</pubDate>
            <description><![CDATA[<p>자기소개
성격의 장단점
취미 특기
지원 동기
비전공자인데 개발을 시작한 계기
이 업계의 비전은 어떻게 될 것 같나?
가장 중요한 역량은?
가장 큰 성취
5년 후 나의 모습
앞으로 어떻게 노력할 것인가?
프로젝트시 팀 불화
생산성을 높이기 위해 시도했던 부분
프로젝트가 끝나고 부족한점은?
트러블 슈팅
회사에 궁금한점
마지막 하고싶은 말</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[기술면접]]></title>
            <link>https://velog.io/@loo-ke/%EA%B8%B0%EC%88%A0%EB%A9%B4%EC%A0%91</link>
            <guid>https://velog.io/@loo-ke/%EA%B8%B0%EC%88%A0%EB%A9%B4%EC%A0%91</guid>
            <pubDate>Mon, 04 Dec 2023 10:48:55 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>이 블로그 참고 많이 했습니다 감사합니다 ㅠㅜㅠㅜ <a href="https://velog.io/@wkahd01/%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C-%EB%A9%B4%EC%A0%91-%EB%AC%B8%EC%A0%9C-%EC%9D%80%ED%96%89-HTML-%EC%A7%88%EB%AC%B8-%EB%8B%B5%EB%B3%80">https://velog.io/@wkahd01/%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C-%EB%A9%B4%EC%A0%91-%EB%AC%B8%EC%A0%9C-%EC%9D%80%ED%96%89-HTML-%EC%A7%88%EB%AC%B8-%EB%8B%B5%EB%B3%80</a></p>
</blockquote>
<blockquote>
<p><a href="https://beomy.github.io/tech/javascript/javascript-runtime/">https://beomy.github.io/tech/javascript/javascript-runtime/</a></p>
</blockquote>
<h3 id="자바스크립트란">자바스크립트란?</h3>
<ul>
<li>자바스크립트는 싱글 스레드, 논 블로킹 언어입니다. <h3 id="싱글-스레드">싱글 스레드</h3>
</li>
<li>하나의 힙 영역과 하나의 콜스택을 가집니다. 한번에 한가지 일밖에 하지 못합니다. <h3 id="콜스택">콜스택</h3>
</li>
<li>함수가 실행되는 순서를 기억합니다. 함수를 실행하려면 스택의 가장 위에 해당함수를 넣게 되고, 함수에서 리턴이 일어나면 스택의 가장 위쪽 함수에서 함수를 꺼냅니다.<h3 id="블로킹">블로킹</h3>
</li>
<li>싱글 스레드는 스택이 하나밖에 없기 때문에 한가지 일만 할 수 있습니다. 웹 브라우자에서 코드가 실행되는데 코드가 종료될 때까지 유저가 클릭해도 어떤 반응을 하지 않는 상태가 됩니다. 콜 스택이 멈춘 상태를 블로킹 상태라고 합니다.<h3 id="논-블로킹">논 블로킹</h3>
</li>
<li>비동기 콜백으로 블로킹 문제를 해결합니다. 하나의 요청이 완료될 때까지 기다리지 않고 동시에 다른 작업을 수행합니다. <h3 id="비동기">비동기</h3>
</li>
<li>특정 코드의 실행이 끝날때까지 기다려주지 않고 나머지 코드를 먼저 실행하는 것입니다. 대표적으로 promise, async/await이 있습니다.<h3 id="브라우저-렌더링-과정">브라우저 렌더링 과정</h3>
</li>
</ul>
<ol>
<li>서버에 HTML, CSS 파일을 요청 후 응답으로 받음</li>
<li>DOM, CSSOM 생성 </li>
<li>DOM과 CSSOM을 합쳐서 렌더트리 생성</li>
<li>각 요소의 위치나 크기를 계산 후 계산한 요소들을 paint한다.<h3 id="호이스팅">호이스팅</h3>
</li>
</ol>
<ul>
<li><p>모든 선언이 코드의 선두로 끌어 올려진 것</p>
<h3 id="클로저">클로저</h3>
</li>
<li><p>부모 함수 내의 자식 함수에서 부모 함수에 선언된 변수에 접근이 가능하게 해주고 외부에서 함수 내의 변수에 조작을 하지 못하게 은닉하는 것</p>
<h3 id="rest-api">REST API</h3>
</li>
<li><p>클라이언트가 서버로 데이터를 요청할 때 브라우저 주소처럼 작성된 루트로 HTTP 메서드를 활용해 CRUD를 요청하고 HTTP 응답코드를 사용해 서버의 상태를 나타내는 것</p>
<h3 id="restful">RESTful</h3>
</li>
<li><p>REST API를 제공하는 우베 서비스를 RESTful 이라고 한다.</p>
<h3 id="spa">SPA</h3>
</li>
<li><p>최초 한번 페이지 전체를 로딩한 후 데이터만 변경해서 사용(하나의 페이지에서 실행됨)</p>
<h3 id="csr">CSR</h3>
</li>
<li><p>사용자가 접속하면 서버는 빈 HTML 파일에 어떤 자바 스크립트 파일이 필요한지 적어서 보낸다.</p>
</li>
<li><p>클라이언트는 HTML을 받아 자바스크립트를 다운 받고 렌더링을 한다.</p>
</li>
<li><p>최초 로드 시 필요한 파일을 전부 받고 사용자의 필요에 따라 클라이언트 단에서 받아와 렌더링 하는 방식</p>
<blockquote>
<p>장점 : 렌더링 속도가 빠름
단점 : 초반 뼈대만 다운 받기 때문에 SEO에 취약, 초기 렌더링 속도가 느리다</p>
</blockquote>
<h3 id="ssr">SSR</h3>
</li>
<li><p>사용자가 접속하면 웹 어플리케이션은 서버로 요청을 보내고 서버는 HTML, CSS, JS 렌더링을 마친 후 클라이언트로 보내준다.</p>
</li>
<li><p>새로 고침이 일어날때마다 새로운 페이지에 대한 요청을 하는 방식</p>
</li>
<li><p>SEO 측면에서 유리하다.</p>
<blockquote>
<p>장점 : 초기 렌더링 속도가 빠르다, SEO에 최적화
단점 : 매 렌더링마다 서버를 거침, 속도가 느림</p>
</blockquote>
<h3 id="쿠키-세션-로컬">쿠키, 세션, 로컬</h3>
</li>
<li><p>쿠키 : 크기가 매우 작고 보안에 취약</p>
</li>
<li><p>세션 : 브라우저가 유지 되는 동안 데이터를 보관, 브라우저 닫으면 데이터 소멸 -&gt; 장바구니 데이터</p>
</li>
<li><p>로컬 : 데이터를 저장하면 영구적으로 저장. -&gt; 자동 로그인 데이터</p>
<h3 id="이벤트-전파">이벤트 전파</h3>
</li>
<li><p>생성된 이벤트 객체는 이벤트를 발생시킨 DOM 요소인 이벤트 타깃을 중심으로 DOM트리를 통해 전파</p>
<h4 id="이벤트-버블링">이벤트 버블링</h4>
</li>
<li><p>이벤트가 하위요소에서 상위요소로 전파</p>
<h4 id="이벤트-캡쳐링">이벤트 캡쳐링</h4>
</li>
<li><p>이벤트가 상위요소에서 상위요소로 전파</p>
<h3 id="이벤트-위임">이벤트 위임</h3>
</li>
<li><p>부모 요소에 이벤트를 부여해 버블링을 통해 하위 요소를 동작시킬대 해당 이벤트를 발생시킬 수 있다.</p>
<h3 id="타입스크립트">타입스크립트</h3>
</li>
<li><p>정적 타입을 명시하여 타입 관련 오류를 미리 잡아낼 수 있다.</p>
</li>
<li><p>코드에 목적을 명시하고 목적에 맞지 않은 타입의 변수나 함수들에서 에러를 발생시켜 에러를 사전에 제거할 수 있다.</p>
</li>
<li><p>뒷 단계에서 버그를 발견했을 때 처리 비용이 기하 급수적으로 늘어남</p>
<h3 id="실행-컨텍스트">실행 컨텍스트</h3>
</li>
</ul>
<ol>
<li>전역 실행 컨텍스트 생성/소스코드 실행</li>
</ol>
<ul>
<li>var로 선언한 전역 변수는 객체 환경 레코드에 저장됨.</li>
<li>const, let으로 선언한 전역 변수는 선언적 환경 레코드에 저장됨.</li>
</ul>
<ol start="2">
<li>edit 함수 실행 컨텍스트 생성/소스코드 실행</li>
</ol>
<ul>
<li>전역 환경 레코드와 달리 함수 환경 레코드는 분리되지 않고, 한 장소에서 var,const,let 모두를 처리한다.</li>
</ul>
<h3 id="http">HTTP</h3>
<ul>
<li>웹에서 정보를 주고 받기 위한 프로토콜<h3 id="https">HTTPS</h3>
</li>
<li>보안되지 않은 HTTP를 보완하기 위해 등장, 암호화하여 민감한 정보를 보호하는 보안 프로토콜</li>
</ul>
<h3 id="디바운스">디바운스</h3>
<ul>
<li>일정 시간안에 같은 요청이 여러번 반복되면 그룹화해서 일정 시간 지난 후 한번만 호출<h3 id="쓰로틀링">쓰로틀링</h3>
</li>
<li>마지막 함수가 호출된 후 일정시간이 지난 후 다시 호출</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[JS - 렌더링]]></title>
            <link>https://velog.io/@loo-ke/JS-%EB%A0%8C%EB%8D%94%EB%A7%81</link>
            <guid>https://velog.io/@loo-ke/JS-%EB%A0%8C%EB%8D%94%EB%A7%81</guid>
            <pubDate>Fri, 01 Dec 2023 09:44:04 GMT</pubDate>
            <description><![CDATA[<h3 id="브라우저의-렌더링-과정">브라우저의 렌더링 과정</h3>
<pre><code>1. 브라우저는 HTML, CSS, jS 등 렌더링에 필요한 리소스를 요청 -&gt; 서버로부터 응답
2. 브라우저의 렌더링 엔진은 서버로부터 응담된 HTML과 CSS를 *파싱하여 DOM, CSSOM을 생성하고 결합하여 렌더 트리를 생성
3. 브라우저의 자바스크립트 엔진은 서버로부터 응답된 자바스크립트를 파싱 AST 생성 바이트코드(?)로 변환, 이때 자바스크립트는 DOM API를 통해 DOM과 CSSOM을 변경할 수 있다. 변경된 DOM과 CSSOM은 다시 렌더 트리로 결합된다.
4. 렌더트리를 기반으로 HTML 요소의 레이아웃을 계싼 후 브라우저 화면에 HTML 요소를 페인팅</code></pre><blockquote>
<p>파싱 : 프로그래밍 언어의 문법에 맞게 작성된 텍스트 문서를 읽어 들이기 위해 텍스트 문서의 문자열 토큰으로 분해. 쉽게 해석이라고 생각하면 된다.</p>
</blockquote>
<p>뭔가 이해가 안되는 것 같아서 다시 찾아봤다....</p>
<pre><code>브라우저의 동작 원리
1. HTML 마크업을 처리하고 DOM 트리를 빌드한다. (&quot;무엇을&quot; 그릴지 결정한다.)
2. CSS 마크업을 처리하고 CSSOM 트리를 빌드한다. (&quot;어떻게&quot; 그릴지 결정한다.)
3. DOM 및 CSSOM 을 결합하여 렌더링 트리를 형성한다. (&quot;화면에 그려질 것만&quot; 결정)
4. 렌더링 트리에서 레이아웃을 실행하여 각 노드의 기하학적 형태를 계산한다. (&quot;Box-Model&quot; 을 생성한다.)
5. 개별 노드를 화면에 페인트한다.(or 래스터화)</code></pre><blockquote>
<p>참고 자료 : 모던 자바스크립트 딥 다이브
참고 자료 : <a href="https://github.com/JaeYeopHan/Interview_Question_for_Beginner/tree/main/FrontEnd#%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80%EC%9D%98-%EB%8F%99%EC%9E%91-%EC%9B%90%EB%A6%AC">https://github.com/JaeYeopHan/Interview_Question_for_Beginner/tree/main/FrontEnd#%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80%EC%9D%98-%EB%8F%99%EC%9E%91-%EC%9B%90%EB%A6%AC</a></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[JS - 디바운스와 스로틀]]></title>
            <link>https://velog.io/@loo-ke/JS-%EB%94%94%EB%B0%94%EC%9A%B4%EC%8A%A4%EC%99%80-%EC%8A%A4%EB%A1%9C%ED%8B%80</link>
            <guid>https://velog.io/@loo-ke/JS-%EB%94%94%EB%B0%94%EC%9A%B4%EC%8A%A4%EC%99%80-%EC%8A%A4%EB%A1%9C%ED%8B%80</guid>
            <pubDate>Thu, 30 Nov 2023 07:53:00 GMT</pubDate>
            <description><![CDATA[<p>scroll, resize, input, mousemove 등 같은 이벤트를 짧은 시간에 연속적으로 발생하는 이벤트들이 있는데 이러한 이벤트들은 성능에 문제를 줄 수 있다.
<strong>디바운스</strong>와 <strong>쓰로틀</strong>은 짧은 시간에 연속해서 발생하는 이벤트를 그룹화해서 과도한 이벤트 핸들러의 호출을 방지하는 프로그래밍 기법이다.</p>
<h3 id="디바운스">디바운스</h3>
<ul>
<li>짧은 시간 발생하는 이벤트를 그룹화해서 마지막에 한번만 이벤트 핸들러가 호출되도록 하는 기법</li>
<li>EX) input 이벤트가 짧은 시간 연속으로 발생하는 경우에 사용<pre><code>// 디바운스 예시
&lt;script&gt;
  const $input = document.querySelector(&quot;input&quot;);
  const $text = document.querySelector(&quot;.text&quot;);
  const debounce = (callback, delay) =&gt; {
      let timeId;
      // debounce 함수는 timeId를 기억하는 클로저를 반환
      return event =&gt; {
      // delay가 경과하기 이전에 이벤트가 발생하면 이전 타이머를 취소 -&gt; 새로운 타이머 재설정
      // delay보다 짧은 간격으로 이벤트가 발생하면 callback은 호출 안됨
          if(timeId) clearTimeout(timeId);
          timeId = setTimeout(callback, delay, event);
      };
  };
  // debounce 함수가 반환하는 클로저가 이벤트 핸들러 등록
  // 300ms보다 짧은 간격으로 이벤트 발생하면 debounce 함수의 콜백 호출 안함
  // 300ms 동안 input 이벤트가 발생하지 않으면 debounce 함수 호출!
  $input.oninput = debounce(e =&gt; {
      $text.textContent = e.target.value;
   }, 300)
&lt;/script&gt;</code></pre>주로 resize이벤트, input 요소에 입력된 값으로 ajax 요청하는 자동완성 기능, 버튼 중복클릭 방지 처리 등에 사용된다.<blockquote>
<p>Underscore의 debounce 함수나 Lodash의 debounce 함수를 권장</p>
</blockquote>
</li>
</ul>
<h3 id="스로틀">스로틀</h3>
<ul>
<li><p>짧은 시간동안 이벤트가 연속해서 발생하더라도 일정 시간 간격으로 이벤트 핸들러가 최대 한번만 호출된다.</p>
</li>
<li><p>일정 시간 단위로 이벤트 핸들러가 호출되도록 호출 주기를 만든다.</p>
<pre><code>// 스로틀 예시
&lt;script&gt;
  const $container = document.querySelector(&quot;.container&quot;);
  const $text = document.querySelector(&quot;.text&quot;);

  const throttle = (callback, delay) =&gt; {
      let timeId;
      // throttle 함수는 timeId를 기억하는 클로저를 반환
      return event =&gt; {
      // delay가 경과하기 이전에 이벤트가 발생하면 아무 것도 하지 않음
      // delay 간격으로 callback 호출
          if(timeId) return;
          timeId = setTimeout(() =&gt; {
                callback(event);
              timeId = null;
          }, delay, event);
      };
  };

  $container.addEventListener(&quot;scroll&quot;, throttle(() =&gt; {
      $text.textContent = ++ throttle;
  }, 100));
&lt;/script&gt;</code></pre><p>주로 scroll 이벤트 처리나 무한 스크롤 구현에 쓰인다.</p>
<blockquote>
<p>Underscore의 throttle 함수나 Lodash의 throttle 함수를 권장</p>
</blockquote>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[원티드 프리온보딩 챌린지]]></title>
            <link>https://velog.io/@loo-ke/%EC%9B%90%ED%8B%B0%EB%93%9C-%ED%94%84%EB%A6%AC%EC%98%A8%EB%B3%B4%EB%94%A9-%EC%B1%8C%EB%A6%B0%EC%A7%80</link>
            <guid>https://velog.io/@loo-ke/%EC%9B%90%ED%8B%B0%EB%93%9C-%ED%94%84%EB%A6%AC%EC%98%A8%EB%B3%B4%EB%94%A9-%EC%B1%8C%EB%A6%B0%EC%A7%80</guid>
            <pubDate>Fri, 24 Nov 2023 02:07:33 GMT</pubDate>
            <description><![CDATA[<p>들어가기 앞서 힘들었던 로직에 대해 서술하라고 했는데 협업에서의 문제점을 이야기 하고싶다. 부트캠프를 수료하고 개인적으로 팀 프로젝트의 일원으로 들어가 새로운 취업 포트폴리오 프로젝트를 진행했다. 프로젝트를 진행하는 도중 다른 분들과의 협업을 경험해보며 많은 것을 느꼈다. </p>
<h3 id="프론트-설계-및-기획의-부재">프론트 설계 및 기획의 부재</h3>
<ul>
<li>프로젝트 내에서 프론트엔드 개발자들이 취준생에 개발 경력이 없던 사람들이 모여 프론트 설계 및 기획을 거치지 않고 개발을 진행</li>
<li>가지각색의 폴더 및 파일명</li>
<li>통일되지 않은 컴포넌트 패턴들 </li>
<li>검증하지 않고 PR을 실행 등으로 인해 반복적인 충돌</li>
<li>이로 인해 서로간의 코드리뷰 및 소통의 부재로 이어짐<h3 id="코드리뷰의-부재">코드리뷰의 부재</h3>
</li>
<li>팀 프로젝트의 강점이자 장점이 다른 개발자들의 코드를 보며 많이 배운다고 생각</li>
<li>코드 컨벤션, 커밋 컨벤션, 브랜치 관리 등 모든 것들의 약속이 없는 상태에서 코드리뷰는 불가능하다고 생각</li>
<li>각자만의 코드 스타일로 가독성이 떨어짐</li>
<li>코드리뷰를 진행하지 않으니 서로의 소통의 부재로 이어짐<h3 id="소통의-부재">소통의 부재</h3>
</li>
<li>앞서 설명한 이유로 소통의 부재가 진행</li>
<li>매번 회의 및 PR 시 충돌 해결의 시간이 필요</li>
<li>협업의 효율이 현저히 떨어짐</li>
</ul>
<blockquote>
<p> 협업 시 CI/CD의 중요성, 소통의 중요성을 한번 더 느낌</p>
</blockquote>
<h3 id="나에-대한-아쉬움">나에 대한 아쉬움</h3>
<ul>
<li>성능 최적화를 고려하지 않고 코드 작성<ul>
<li>코드의 용량 및 이미지 최적화 적용 필요</li>
</ul>
</li>
<li>컴포넌트 수의 증가에 따른 폴더구조 혼잡</li>
<li>가독성을 고려하지 않은 코드 작성</li>
<li>복잡한 파일구조</li>
</ul>
<blockquote>
<p>아직 위와 같은 부분들이 부족한 점과 고쳐 나가야할 점이라고 생각</p>
</blockquote>
<p><strong>아직 부족한 것도 많고 배울 것도 많지만 긍정적으로 꾸준히 하다보면 기회가 올거라 믿습니다! 파이테잉..!</strong></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Redux]]></title>
            <link>https://velog.io/@loo-ke/Redux</link>
            <guid>https://velog.io/@loo-ke/Redux</guid>
            <pubDate>Tue, 30 May 2023 10:45:08 GMT</pubDate>
            <description><![CDATA[<h1 id="01-redux-소개">01. Redux 소개</h1>
<h2 id="redux">Redux?</h2>
<ul>
<li>앱 전체 상태를 쉽게 관리하기 위한 라이브러리.</li>
<li>Redux의 많은 개념들이 Flux pattern에서 차용됨.</li>
<li>주로 React 앱과 같이 사용.</li>
<li>redux.js.org에서 수많은 문서를 참고할 수 있고, 웹상에 Redux를 활용한 앱 구축 사례가 많음.<h2 id="언제-사용">언제 사용??</h2>
</li>
<li>앱 전체의 상태 관리가 필요할 때.</li>
<li>복잡한 비동기 처리가 있는 상태 관리가 필요할 때.</li>
<li>앱의 상태가 복잡하고, 이를 체계적으로 관리하고 싶을 때.</li>
<li>상태 관리 패턴을 도입하여, 여러 개발자와 협업하고 싶을 때.</li>
<li>logger, devtool 등을 활용하여 상태를 관리할 필요가 있을 때.<h2 id="원칙">원칙</h2>
</li>
<li>Single source of truth - Store는 단 하나이며, 모든 앱의 상태는 이곳에 보관됨.</li>
<li>Immutability – 상태는 오로지 읽을 수만 있다. 변경하려면 모든 상태가 변경 되어야 함. </li>
<li>Pure function – 상태의 변경은 어떠한 사이드 이펙트도 만들지 않아야 함.<h1 id="02-redux의구조">02. Redux의구조</h1>
<h2 id="구조">구조</h2>
</li>
<li>redux는 자유롭게 확장하여 사용할 수 있음.</li>
<li>내부적으로 action과 데이터가 어떻게 흐르는지 이해하고, middleware, enhancer 등을 이용하여 redux를 확장함.<h2 id="middleware">middleware</h2>
</li>
<li>action은 dispatch 이후 모든 middleware를 먼저 통과한 후에 reducer에 도달.</li>
<li>redux-thunk, redux-logger 등의 라이브러리를 적용.<h2 id="enhancer">enhancer</h2>
</li>
<li>action은 dispatch 이후 모든 middleware를 먼저 통과한 후에 reducer에 도달.</li>
<li>redux devtools 등의 라이브러리를 적용.<h1 id="03-redux-toolkit-활용">03. redux-toolkit 활용</h1>
<h1 id="04-redux를-react에-연결하기">04. Redux를 React에 연결하기</h1>
<h1 id="05-redux를-이용한-비동기-처리">05. Redux를 이용한 비동기 처리</h1>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[React - 5]]></title>
            <link>https://velog.io/@loo-ke/React-5</link>
            <guid>https://velog.io/@loo-ke/React-5</guid>
            <pubDate>Fri, 19 May 2023 08:52:43 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>useState, useEffect, fetch를 중점적으로 공부하자!
useReducer 몰라도 된다!!</p>
</blockquote>
<h2 id="이전-코드-복습">이전 코드 복습</h2>
<ul>
<li>counter 기능 구현하기!<ul>
<li>input에 있는 값만큼 더하기</li>
<li>button 누를 때 마다 더하기!</li>
</ul>
</li>
</ul>
<h2 id="버튼을-클릭하지-않아도-숫자가-늘어나는-기능">버튼을 클릭하지 않아도 숫자가 늘어나는 기능</h2>
<ul>
<li>setInterval()<pre><code>//interval 실행
id = setInterval(() =&gt; {
console.log(1);
}, 1000);

</code></pre></li>
</ul>
<p>// 끌때
clearInterval(id)</p>
<pre><code>&gt; useEffect의 첫번째 파라미터는 콜백함수, 콜백함수의 리턴값은 함수고, 그 함수는 컴포넌트가 제거될 때 호출된다.

## 클로저</code></pre><p>a = () =&gt; {
  let id = 1;
  return () =&gt; {
    console.log(id);
  }
}
a()//() =&gt; { console.log(id); }</p>
<pre><code></code></pre><p>b = a()</p>
<pre><code>
## 자동으로 숫자가 올라가는 기능에서 start, stop 기능 추가해보기~!
## MUI 복습!
- Container
- Grid
- ButtonGroup
- Button
  - variant=&quot;contained&quot;(색이 차있는 버튼 /  없으면 색 없는 버튼)
- theme로 색상 변경하기!</code></pre><pre><code>import { blue, grey } from &quot;@mui/material/colors&quot;;
const darkThema = createTheme({
    palette: {
    primary: grey,
  },
});




&lt;ThemeProvider theme={darkThema}&gt;
   &lt;Counter4UseEffect /&gt;
&lt;/ThemeProvider&gt;</code></pre><pre><code>- 위와 같이 Theme태그 안에 있는 태그들의 버튼은 다 grey 컬러로 바꼈다.
- context API로 인해 변경되었다는데... 이해가 안된다,....ㅎ
### context API
&gt; https://www.youtube.com/watch?v=JQ_lksQFgNw


- 잘쓰면 고수소리 듣는다!!</code></pre><p>// 기본 구조
import React from &quot;react&quot;;</p>
<p>export function ContextAPI() {
  return (
    <div className="layout">
      <h1>Context api</h1>
      <button>+</button>
      <ContextAPISub />
    </div>
  );
}
function ContextAPISub() {
  return (
    <div className="layout">
      <h1>sub</h1>
      <button>+</button>
    </div>
  );
}</p>
<pre><code>- useContext를 이용해서 자식의 속성들(디자인속성)을 덮어 씌어버릴 수 있다.
- useContext는 useContext를 구독하고 있는 컴포넌트들만 동적으로 렌더링이 된다.총 5개의 컴포넌트 중에 3개만 가지고 있다면 3개만 재렌더링 된다.
### useReducer</code></pre><p>const [변경될 값, 바꾸라고 하는 명령] = useReducer(값을 변경하는 함수, 기본값);
function 값을변경하는함수(oldCount:number, action:string):number{
  if(action === &quot;UP&quot;){
    return oldCount + 1;
  } else if(action === &quot;DOWN&quot;){
    return oldCount - 1;
  } else if(action === &quot;RESET&quot;){
    return 0;
  }
}</p>
<pre><code>- useState의 경쟁자
- 똑같은 일을 함
- 근데 취지가 좀 다름
- useState의 장점 = 이해하기 쉬움
- useReducer의 장점 = 상태를 이해하면 쉬움!

오오ㅗ옹 개신기해!!</code></pre><p>function MyUseReduce() {
  // const [count, setCount] = useState(0);
  function countReducer(oldCount: number, action: string): number {
    console.log(oldCount, action);
    return oldCount;
  }
  const [count, countDispatch] = useReducer(countReducer, 10);
  return (
    <div className="layout">
      <h1>useReduce</h1>
      &lt;button
        onClick={() =&gt; {
          // setCount(count + 1);
          countDispatch(&quot;UP&quot;);
        }}
      &gt;
        +
      </button>
      &lt;button
        onClick={() =&gt; {
          // setCount(count - 1);
          countDispatch(&quot;DOWN&quot;);
        }}
      &gt;
        -
      </button>
      &lt;button
        onClick={() =&gt; {
          // setCount(0);
          countDispatch(&quot;RESET&quot;);
        }}
      &gt;
        0
      </button>
      {count}
    </div>
  );
}</p>
<pre><code>- console.log로 값을 확인했으면 이제 useRedecer을 이용해 값을 변경해보자!</code></pre><p>function MyUseReduce() {
  // const [count, setCount] = useState(0);
  function countReducer(oldCount: number, action: string): number {
    console.log(oldCount, action);
    if (action === &quot;UP&quot;) {
      return oldCount + 1;
    } else if (action === &quot;DOWN&quot;) {
      return oldCount - 1;
    } else if (action === &quot;RESET&quot;) {
      return 0;
    }
    return oldCount;
  }
  const [count, countDispatch] = useReducer(countReducer, 10);
  return (
    <div className="layout">
      <h1>useReduce</h1>
      &lt;button
        onClick={() =&gt; {
          // setCount(count + 1);
          countDispatch(&quot;UP&quot;);
        }}
      &gt;
        +
      </button>
      &lt;button
        onClick={() =&gt; {
          // setCount(count - 1);
          countDispatch(&quot;DOWN&quot;);
        }}
      &gt;
        -
      </button>
      &lt;button
        onClick={() =&gt; {
          // setCount(0);
          countDispatch(&quot;RESET&quot;);
        }}
      &gt;
        0
      </button>
      {count}
    </div>
  );
}</p>
<pre><code>

**_출처 : 엘리스 아카데미_**</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[React - 4]]></title>
            <link>https://velog.io/@loo-ke/React-4</link>
            <guid>https://velog.io/@loo-ke/React-4</guid>
            <pubDate>Wed, 17 May 2023 17:10:51 GMT</pubDate>
            <description><![CDATA[<h1 id="이론">이론</h1>
<h3 id="지난-시간-counter-함수들-복습">지난 시간 counter 함수들 복습!!</h3>
<h3 id="mui-사용">MUI 사용</h3>
<h4 id="container">container</h4>
<ul>
<li><p>설치 </p>
<ul>
<li>터미널에 <code>npm install @mui/material @emotion/react @emotion/styled</code> </li>
</ul>
</li>
<li><p>import하자!</p>
<ul>
<li><code>import { Container } from &quot;@mui/material&quot;;</code></li>
</ul>
</li>
<li><p>코드 사용</p>
<ul>
<li>```function App() {
return (<Container>
  <Counter></Counter>
</Container>
);
}```
#### Grid</li>
</ul>
</li>
<li><p>import</p>
<ul>
<li><code>import Grid from &quot;@mui/material/Grid&quot;;</code></li>
</ul>
</li>
<li><p>사용</p>
<ul>
<li>```
function App() {
return (<Container>
  <Grid container>
    <Counter></Counter>
    <Counter></Counter>
    <Counter></Counter>
    <Counter></Counter>
    <Counter></Counter>
    <Counter></Counter>
  </Grid>
</Container>
);
}```</li>
</ul>
</li>
<li><p>그리드를 이용하기!!</p>
<pre><code>function App() {
return (
  &lt;Container&gt;
    &lt;Grid container spacing={1}&gt;
      &lt;Grid item xs={12} sm={6} md={4}&gt;
        &lt;Counter&gt;&lt;/Counter&gt;
      &lt;/Grid&gt;
      &lt;Grid item xs={12} sm={6} md={4}&gt;
        &lt;Counter&gt;&lt;/Counter&gt;
      &lt;/Grid&gt;
      &lt;Grid item xs={12} sm={6} md={4}&gt;
        &lt;Counter&gt;&lt;/Counter&gt;
      &lt;/Grid&gt;
    &lt;/Grid&gt;
  &lt;/Container&gt;
);
}</code></pre><h3 id="toggle-버튼-만들기">toggle 버튼 만들기</h3>
<pre><code>function Counter2() {
const [open, setOpen] = useState(false);
return (
  &lt;div style={{ border: &quot;10px solid black&quot;, padding: 20 }}&gt;
    &lt;h1&gt;Counter - Dialog&lt;/h1&gt;
    &lt;Button
      variant=&quot;contained&quot;
      onClick={() =&gt; {
        setOpen(true);
      }}
    &gt;
      Run
    &lt;/Button&gt;

    &lt;div style={{ display: open ? &quot;block&quot; : &quot;none&quot; }}&gt;
      &lt;h2&gt;Dialog Counter&lt;/h2&gt;
      &lt;button&gt;+&lt;/button&gt; 0
      &lt;Button
        variant=&quot;contained&quot;
        onClick={() =&gt; {
          setOpen(false);
        }}
      &gt;
        close
      &lt;/Button&gt;
    &lt;/div&gt;
  &lt;/div&gt;
);
}</code></pre><h3 id="토글을-dialog로-만들기">토글을 Dialog로 만들기!</h3>
<pre><code>import Dialog from &quot;@mui/material/Dialog&quot;;
</code></pre></li>
</ul>
<p>...
function Counter2() {
  const [open, setOpen] = useState(false);
  return (
    &lt;div style={{ border: &quot;10px solid black&quot;, padding: 20 }}&gt;
      <h1>Counter - Dialog</h1>
      &lt;Button
        variant=&quot;contained&quot;
        onClick={() =&gt; {
          setOpen(true);
        }}
      &gt;
        Run
      </Button></p>
<pre><code>  &lt;Dialog open={open}&gt;// 여기 바꿔줌!!
    &lt;h2&gt;Dialog Counter&lt;/h2&gt;
    &lt;button&gt;+&lt;/button&gt; 0
    &lt;Button
      variant=&quot;contained&quot;
      onClick={() =&gt; {
        setOpen(false);
      }}
    &gt;
      close
    &lt;/Button&gt;
  &lt;/Dialog&gt;
&lt;/div&gt;</code></pre><p>  );
}</p>
<pre><code>### dialog 이용해보기</code></pre><p>import Dialog from &quot;@mui/material/Dialog&quot;;
import DialogTitle from &quot;@mui/material/DialogTitle&quot;;
import DialogContent from &quot;@mui/material/DialogContent&quot;;
import DialogActions from &quot;@mui/material/DialogActions&quot;;</p>
<p>...</p>
<p>function Counter2() {
  const [open, setOpen] = useState(false);
  return (
    &lt;div style={{ border: &quot;10px solid black&quot;, padding: 20 }}&gt;
      <h1>Counter - Dialog</h1>
      &lt;Button
        variant=&quot;contained&quot;
        onClick={() =&gt; {
          setOpen(true);
        }}
      &gt;
        Run
      </Button></p>
<pre><code>  &lt;Dialog
    open={open}
    onClose={() =&gt; {
      setOpen(false);
    }}
  &gt;
    &lt;DialogTitle&gt;Dialog Title&lt;/DialogTitle&gt;
    &lt;DialogContent&gt;
      &lt;p&gt;Lorem ipsum dolor sit amet consectetur, adipisicing elit.&lt;/p&gt;
      &lt;button&gt;+&lt;/button&gt; 0
    &lt;/DialogContent&gt;
    &lt;DialogActions&gt;
      &lt;Button
        variant=&quot;contained&quot;
        onClick={() =&gt; {
          setOpen(false);
        }}
      &gt;
        close
      &lt;/Button&gt;
    &lt;/DialogActions&gt;
  &lt;/Dialog&gt;
&lt;/div&gt;</code></pre><p>  );
}</p>
<pre><code>

### random 컬러 리턴해주는 함수!</code></pre><p>function getRandomColor() {
  const letters = &quot;0123456789ABCDEF&quot;;
  let color = &quot;#&quot;;
  for (let i = 0; i &lt; 6; i++) {
    color += letters[Math.floor(Math.random() * 16)];
  }
  return color;
}</p>
<pre><code></code></pre><div style={{ border: "10px solid" + getRandomColor(), margin: "20px 0" }}>
    ...
</div>
```
## JSON 서버 
> npx json-server --port 9999 --watch db.json

<ul>
<li>db.json 파일 생성된 것 확인!!</li>
<li><a href="http://localhost:9999/posts">http://localhost:9999/posts</a> 를 입력하면 화면이 뜬다!
<img src="https://velog.velcdn.com/images/loo-ke/post/16c21a7e-1950-43fc-aab5-8f3996b35a3a/image.png" alt=""><h2 id="fetch-api">fetch API</h2>
</li>
<li>Promise를 사용함~!</li>
<li>fetch를 사용할때 첫번째 파라미터는 URL</li>
<li>then에는 모두 함수가 들어간다!</li>
<li>첫번째 then에 (resp)=&gt;resp.json()</li>
<li>두번째 then (result) =&gt;{ console.log(result)}</li>
</ul>
<pre><code>fetch(&#39;http://localhost:9999/counter&#39;)
    .then((resp)=&gt;resp.json())
    .then((result)=&gt;{
        console.log(result.value);
    })</code></pre><p><img src="https://velog.velcdn.com/images/loo-ke/post/07c7f48e-e97e-4f45-999d-59e239e26e8f/image.png" alt=""></p>
<h3 id="useeffect를-사용해보기">useEffect를 사용해보기</h3>
<ul>
<li>컴포넌트가 실행될 때 마다 실행됨.</li>
<li>마지막에 빈 배열을 추가해주면 최초 1회만 실행하게 된다!<pre><code>useEffect(() =&gt; {
  fetch(&quot;http://localhost:9999/counter&quot;)
    .then((resp) =&gt; resp.json())
    .then((result) =&gt; {
      console.log(result);
      setCount(result.value);
    });
}, []);</code></pre></li>
<li>위의 코드는 서버의 값을 변경하지 않는다.<pre><code>fetch(&quot;http://localhost:9999/counter&quot;, {
          method: &quot;PATCH&quot;,
          body: JSON.stringify({ value: count + 1 }),
          headers: {
            &quot;Content-Type&quot;: &quot;application/json&quot;,
          },
        })
          .then((resp) =&gt; resp.json())
          .then((result) =&gt; {setCount(result.value)});</code></pre></li>
<li>이러면 서버값도 바뀜!!!!</li>
<li>오오 개신기해!!</li>
</ul>
<p><strong><em>출처 : 엘리스 아카데미</em></strong></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[React - 상태 관리]]></title>
            <link>https://velog.io/@loo-ke/React-%EC%83%81%ED%83%9C-%EA%B4%80%EB%A6%AC</link>
            <guid>https://velog.io/@loo-ke/React-%EC%83%81%ED%83%9C-%EA%B4%80%EB%A6%AC</guid>
            <pubDate>Mon, 15 May 2023 12:35:13 GMT</pubDate>
            <description><![CDATA[<h1 id="1-상태-관리">1. 상태 관리</h1>
<h2 id="상태-관리">상태 관리</h2>
<ul>
<li>상태 관리 기술이란 앱 상에서의 데이터를 메모리 등에 저장하고 하나 이상의 컴포넌트에서 데이터를 공유하는 것.</li>
<li>한 컴포넌트 안에서의 상태, 여러 컴포넌트 간의 상태, 전체 앱의 상태 관리를 모두 포함.<h2 id="mpa와-spa에서의-상태-관리">MPA와 SPA에서의 상태 관리</h2>
</li>
<li>MPA에서는 서버의 데이터를 이용해 페이지를 렌더링하므로, 클라이언트의 데이터와 서버의 데이터가 큰 차이를 가지지 않음.</li>
<li>SPA에서는 자체적으로 데이터를 갖고, 서버와의 동기화가 필요한 데이터만을 처리. 그 외의 데이터는 Client만의 데이터로 유지.<h2 id="상태-관리-기술의-도입">상태 관리 기술의 도입</h2>
</li>
<li>상태가 많지 않거나, 유저와의 인터렉션이 많지 않다면 매 작업 시 서버와 동기화 하더라도 충분함.</li>
<li>앱이 사용하는 데이터가 점점 많아지고, 유저와 인터렉션 시 임시로 저장하는 데이터가 많아지는 경우 상태 관리를 고려.</li>
<li>FE 뿐만 아니라, BE와의 데이터 통신도 충분히 고려해야 함.<h2 id="장점">장점</h2>
</li>
<li>높은 품질의 코드를 작성하는 데 유리</li>
<li>성능 최적화, 네트워크 최적화 등에 유리</li>
<li>데이터 관리의 고도화</li>
</ul>
<h2 id="단점">단점</h2>
<ul>
<li>Boilerplate 문제.(외부 라이브러리를 적용할 경우)</li>
<li>파악해야 할 로직과 레이어가 많아짐.</li>
<li>잘못 사용할 경우, 앱의 복잡도만을 높이거나, 성능을 악화.</li>
</ul>
<h1 id="2-상태-관리-기술이-해결하는-문제">2. 상태 관리 기술이 해결하는 문제</h1>
<h3 id="데이터-캐싱과-재활용">데이터 캐싱과 재활용</h3>
<ul>
<li>SPA에서 페이지 로딩 시마다 모든 데이터를 로딩한다면, 사용자 경험 측면에서 MPA를 크게 넘어서기 힘듦.</li>
<li>오히려네트워크요청수가많아져더느릴수도있음.</li>
<li>변경이 잦은 데이터가 아니라면, 데이터를 캐싱하고 재활용함. </li>
<li>변경이 잦다면, 데이터의 변경 시점을 파악해 최적화.<ul>
<li>ex)일정 시간마다 서버에 저장, 타이핑 5초 후 서버에 저장  <h3 id="prop-drilling">Prop Drilling</h3>
</li>
</ul>
</li>
<li>컴포넌트가 복잡해지는 경우, 상위 부모와 자식 컴포넌트 간의 깊이가 커짐. </li>
<li>최하단의 자식 컴포넌트가 데이터를 쓰기 위해 최상위 컴포넌트부터 데이터를 보내야 하는 상황이 발생.</li>
<li>Context API 등을 활용, 필요한 컴포넌트에서 데이터를 가져올 수 있음. </li>
<li>컴포넌트 간의 결합성을 낮춤.</li>
</ul>
<h1 id="3-flux-pattern">3. Flux pattern</h1>
<ul>
<li>MVC Pattern<ul>
<li>MVC Pattern이란 애플리케이션을 Model, View, Controller로 분리하여 개발하는 소프트웨어 디자인 패턴 중 하나입니다.</li>
</ul>
</li>
<li>Flux Pattern<ul>
<li>하나의 유저 인터렉션이 무조건 하나의 업데이트만 만들 수 있는 것은 아닙니다. 예를 들어 특정 버튼을 클릭했을 때 여러개의 액션을 만들 수 있기 때문입니다.</li>
</ul>
</li>
<li>MVC 패턴의 경우, 하나의 유저 인터렉션 발생 시 그 인터렉션으로 발생한 업데이트가 다른 연쇄 업데이트를 만들어낼 수 있습니다. 따라서 업데이트의 근원을 추적하기 힘든 반면 Flux 패턴은 연쇄 업데이트가 아닌 단방향 업데이트만을 만들어낼 수 있습니다.</li>
</ul>
<h2 id="flux-pattern">Flux pattern?</h2>
<ul>
<li>2014년에 Facebook에서 제안한 웹 애플리케이션 아키텍처 패턴.</li>
<li>Unidirectional data flow를 활용, 데이터의 업데이트와 UI 반영을 단순화.</li>
<li>React의 UI 패턴인 합성 컴포넌트와 어울리도록 설계.</li>
<li>redux, react-redux 라이브러리의 Prior art.<h2 id="flux-pattern-vs-mvc-pattern">Flux Pattern vs MVC Pattern</h2>
</li>
<li>MVC 패턴에서는, View에서 특정 데이터를 업데이트하면 연쇄적인 업데이트가 일어남.</li>
<li>특정 유저의 인터렉션이 여러 UI 컴포넌트가 사용하는 데이터에 영향을 줄 때, MVC만으로는 앱의 복잡도를 낮추거나 업데이트의 흐름을 따라가기 어려움. </li>
<li>Flux는 하나의 유저 인터렉션 당 하나의 Update만을 만들도록 함.</li>
<li>data와 업데이트가 한 방향으로 흐르므로 UI의 업데이트를 예측하기 쉬움.<h2 id="flux-구조">Flux 구조</h2>
</li>
<li>Action -&gt; Dispatcher -&gt; Store -&gt; View 순으로 데이터가 흐름.<h1 id="4-usestate-useref-usecontext-usereducer">4. useState, useRef, useContext, useReducer</h1>
<h2 id="상태-관리에-사용되는-훅">상태 관리에 사용되는 훅</h2>
</li>
<li>외부 라이브러리 없이 React가 제공하는 훅 만으로 상태 관리를 구현하기 위해 사용. </li>
<li>함수형 컴포넌트에 상태를 두고, 여러 컴포넌트 간 데이터와 데이터 변경 함수를 공유하는 방식으로 상태를 관리하게 됨.<h3 id="usestate">useState</h3>
</li>
<li>단순한 하나의 상태를 관리하기에 적합함.</li>
<li><code>const [ state, setState ] = useState(initState | initFn)</code></li>
<li>state가 바뀌면, state를 사용하는 컴포넌트를 리렌더함.</li>
<li>useEffect와 함께, state에 반응하는 훅을 구축.<h3 id="useref">useRef</h3>
</li>
<li>상태가 바뀌어도 리렌더링하지 않는 상태를 정의함.</li>
<li>즉, 상태가 UI의 변경과 관계없을 때 사용.
ex) setTimeout의 timerId 저장</li>
<li>uncontrolled component의 상태를 조작하는 등, 리렌더링을 최소화하는 상태 관리에 사용됨.
ex) Dynamic Form 예시<h3 id="usecontext">useContext</h3>
</li>
<li>컴포넌트와 컴포넌트 간 상태를 공유할 때 사용.</li>
<li>부분적인 컴포넌트들의 상태 관리, 전체 앱의 상태 관리를 모두 구현.</li>
<li>Context Provider 안에서 렌더링되는 컴포넌트는, useContext를 이용해 깊이 nested 된 컴포넌트라도 바로 context value를 가져옴.</li>
<li>context value가 바뀌면 내부 컴포넌트는 모두 리렌더링됨.<h3 id="usereducer">useReducer</h3>
</li>
<li>useState보다 복잡한 상태를 다룰 때 사용.</li>
<li>별도의 라이브러리 없이 flux pattern에 기반한 상태 관리를 구현.</li>
<li><code>const [state, dispatch] = useReducer(reducer, initState)</code></li>
<li>nested state 등 복잡한 여러 개의 상태를 한꺼번에 관리하거나, 어떤 상태에 여러 가지 처리를 적용할 때 유용.</li>
<li>상태 복잡하다면, useState에 관한 callback을 내려주는 것보다
dispatch를 prop으로 내려 리렌더링을 최적화하는 것을 권장.<h1 id="5-usestate를-활용한-상태-관리">5. useState를 활용한 상태 관리</h1>
</li>
<li>상위 컴포넌트에서 state와 state 변경 함수를 정의하고, 그 state나 변경 함수를 사용하는 컴포넌트까지 prop으로 내려주는 패턴.</li>
<li>state가 변경되면, 중간에 state를 넘기기만 하는 컴포넌트들도 모두 리렌더링됨.</li>
<li>상태와 상태에 대한 변화가 단순하거나, 상대적으로 소규모 앱에서 사용하기에 적합.<h1 id="6-usecontext를-활용한-상태-관리">6. useContext를 활용한 상태 관리</h1>
</li>
<li>Provider 단에서 상태를 정의하고, 직접 상태와 변경 함수를 사용하는 컴포넌트에서 useContext를 이용해 바로 상태를 가져와 사용하는 패턴.</li>
<li>useReducer와 함께, 복잡한 상태와 상태에 대한 변경 로직을 두 개 이상의 컴포넌트에서 활용하도록 구현 가능.</li>
<li>state는 필요한 곳에서만 사용하므로, 불필요한 컴포넌트 리렌더링을 방지. </li>
<li>Prop Drilling(Plumbing)을 방지하여 컴포넌트 간 결합도를 낮춤.</li>
</ul>
<p><strong><em>출처 : 엘리스 아카데미</em></strong></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[React - 비동기 통신, promise]]></title>
            <link>https://velog.io/@loo-ke/React-%EB%B9%84%EB%8F%99%EA%B8%B0-%ED%86%B5%EC%8B%A0-promise</link>
            <guid>https://velog.io/@loo-ke/React-%EB%B9%84%EB%8F%99%EA%B8%B0-%ED%86%B5%EC%8B%A0-promise</guid>
            <pubDate>Mon, 15 May 2023 12:10:00 GMT</pubDate>
            <description><![CDATA[<h1 id="1-자바스크립트-비동기1">1. 자바스크립트 비동기1</h1>
<h3 id="등장">등장</h3>
<ul>
<li>초기 웹 환경에서는, 서버에서 모든 데이터를 로드하여 페이지를 빌드했으므로 자바스크립트에는 별도의 비동기 처리가 필요하지 않았음.</li>
<li>Ajax 기술의 등장으로 페이지 로드 없이 client-side에서 서버로 요청을 보내 데이터를 처리할 수 있게 됨.</li>
<li>XMLHttpRequest라는 객체를 이용해 서버로 요청을 보낼 수 있게 됨.<h3 id="자바스크립트와-비동기">자바스크립트와 비동기</h3>
</li>
<li>자바스크립트는 single-threaded language이므로, 만일 서버 요청을 기다려야 한다면 유저는 멈춰있는 브라우저를 보게 될 것.</li>
<li>따라서 동기가 아닌 비동기 처리를 이용해 서버로 통신할 필요가 있음.</li>
<li>비동기 요청 후, main thread는 유저의 입력을 받거나, 페이지를 그리는 등의
작업을 처리.</li>
<li>비동기 응답을 받으면, 응답을 처리하는 callback 함수를 task queue에 넣음.</li>
<li>event queue는 main thread에 여유가 있을 때 task queue에서 함수를 꺼내 실행.<h3 id="동기">동기</h3>
</li>
<li>해당 코드 블록을 실행할 때 thread의 제어권을 넘기지 않ㅇ고 순서대로 실행하는 것을 의미<h3 id="비동기">비동기</h3>
</li>
<li>코드의 순서와 다르게 실행</li>
<li>비동기 처리 코드를 감싼 블록은 task queue에 넣어짐</li>
<li>main thred가 동기 코드를 실행한 후에 제어권이 돌아왔을 때 event loop가 task queue에 넣어진 비동기 코드를 실행함.</li>
</ul>
<h1 id="2-자바스크립트-비동기2">2. 자바스크립트 비동기2</h1>
<h3 id="비동기-처리를-위한-내부-구조">비동기 처리를 위한 내부 구조</h3>
<ul>
<li><p>브라우저에서 실행되는 자바스크립트 코드는 event driven 시스템으로 작동. </p>
<ul>
<li>(이벤트 드리븐 ? = task queue에 이벤트를 넣어 하나씩 실행하는 시스템을 말한다.)</li>
</ul>
</li>
<li><p>웹앱을 로드하면 브라우저는 HTML document를 읽어 문서에 있는 CSS code, JS code를 불러옴.</p>
</li>
<li><p>자바스크립트 엔진은 코드를 읽어 실행.</p>
</li>
<li><p>브라우저의 main thread는 자바스크립트 코드에서 동기적으로 처리되어야 할 코드 실행 외에도, 웹 페이지를 실시간으로 렌더링하고, 유저의 입력을 감지하고, 네트워크 통신을 처리하는 등 수많은 일을 처리.</p>
</li>
<li><p>비동기 작업을 할당하면, 비동기 처리가 끝나고 브라우저는 task queue에 실행 코드를 넣음.</p>
</li>
<li><p>main thread는 event loop를 돌려, task queue에 작업이 있는지 체크.</p>
</li>
<li><p>작업이 있으면 task를 실행.</p>
<h1 id="3-promise">3. Promise</h1>
<h3 id="callback-pattern-vs-promise">Callback pattern vs Promise</h3>
</li>
<li><p>비동기 처리 후 실행될 코드를 Callback function으로 보내는 것.</p>
<ul>
<li>setTimeOut()</li>
</ul>
</li>
<li><p>비동기 처리가 고도화되면서, Callback hell 등이 단점으로 부각됨. - Promise를 활용하여 비동기 처리의 순서 조작, 에러 핸들링, 여러 비동기 요청 처리 등을 쉽게 처리할 수 있게 됨.</p>
<h3 id="promise">promise</h3>
</li>
<li><p>Promise 객체는, 객체가 생성 당시에는 알려지지 않은 데이터에 대한 Proxy. </p>
</li>
<li><p>비동기 실행이 완료된 후에, <code>.then</code>, <code>.catch</code>, <code>.finally</code> 등의 핸들러를 붙여 각각 데이터 처리 로직, 에러 처리 로직, 클린업 로직을 실행.</p>
</li>
<li><p>then 체인을 붙여, 비동기 실행을 마치 동기 실행처럼 동작하도록 함.</p>
<pre><code>returnPromise()
.then(num =&gt; {
console.log(&quot;First random number : &quot;, num) })
.catch(error =&gt; {
  console.error(&quot;Error occured : &quot;, error)
})
.finally(() =&gt; {
  console.log(&quot;Promise returned.&quot;)
})</code></pre><h3 id="상태">상태</h3>
</li>
<li><p>Promise 객체는 pending, fulfilled, rejected 3개의 상태를 가짐. </p>
</li>
<li><p>fulfilled, rejected 두 상태를 settled 라고 지칭.</p>
</li>
<li><p>pending은 비동기 실행이 끝나기를 기다리는 상태.</p>
</li>
<li><p>fulfilled는 비동기 실행이 성공한 상태.</p>
</li>
<li><p>rejected는 비동기 실행이 실패한 상태.</p>
<h3 id="다중-promise-핸들러">다중 promise 핸들러</h3>
</li>
<li><p>Promise.all()은 모든 프로미스가 fulfilled 되길 기다림. 하나라도 에러 발생시, 모든 프로미스 요청이 중단됨.</p>
</li>
<li><p>Promise.allSettled()는 모든 프로미스가 settled 되길 기다림.</p>
</li>
<li><p>Promise.race()는, 넘겨진 프로미스들 중 하나라도 settled 되길 기다림.</p>
</li>
<li><p>Promise.any() - 넘겨진 프로미스 중 하나라도 fulfilled 되길 기다림.</p>
<h1 id="4-asyncawait">4. async/await</h1>
</li>
<li><p>Promise 체인을 구축하지 않고도. promise를 직관적으로 사용할 수 있는 문법.</p>
</li>
<li><p>try...catch 문으로 에러를 직관적으로 처리</p>
</li>
<li><p>async function을 만들고, promise를 기다려야하는 표현 앞에 await을 붙임.</p>
<h3 id="여러-개의-await">여러 개의 await</h3>
</li>
<li><p>여러 개의 await을 순서대로 나열하여, then chain을 구현할 수 있음. </p>
</li>
<li><p>try... catch 문을 자유롭게 활용하여 에러 처리를 적용.</p>
<h1 id="5-postman-open-api-cors">5. POSTMAN, Open API, CORS</h1>
<h3 id="postman">postman</h3>
</li>
<li><p>서버와의 통신을 위해 API를 활용하는 경우 활용</p>
</li>
<li><p>API를 테스트하기 위한 도구</p>
</li>
<li><p>포스트맨 짱짱맨!</p>
<h3 id="open-api">open API</h3>
</li>
<li><p>RESTful API를 하나의 문서로 정의하기 위한 문서 표준</p>
<h3 id="cors">CORS</h3>
</li>
<li><p>Cross-Origin Resource Sharing.</p>
</li>
<li><p>브라우저는 모든 요청 시 Origin 헤더를 포함.</p>
</li>
<li><p>서버는 Origin 헤더를 보고, 해당 요청이 원하는 도메인에서부터 출발한 것인지를 판단.</p>
</li>
<li><p>다른 Origin에서 온 요청은 서버에서 기본적으로 거부함.</p>
</li>
<li><p>웹사이트에 악성 script가 로드되어, 수상한 요청을 하는 것을 막기 위함. </p>
</li>
<li><p>반대로, 익명 유저로부터의 DDos공격 등을 막기 위함.</p>
</li>
<li><p>서버에 직접 CORS 설정을 할 수 없다면, Proxy 서버 등을 만들어 해결.</p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[SPA, 라우팅(React-router)]]></title>
            <link>https://velog.io/@loo-ke/SPA-%EB%9D%BC%EC%9A%B0%ED%8C%85React-router</link>
            <guid>https://velog.io/@loo-ke/SPA-%EB%9D%BC%EC%9A%B0%ED%8C%85React-router</guid>
            <pubDate>Thu, 11 May 2023 18:46:21 GMT</pubDate>
            <description><![CDATA[<h1 id="spa">SPA</h1>
<ul>
<li>SPA(Single Page Application)은 하나의 페이지 요청으로 전체 웹앱을 사용하는 방식</li>
<li>유저는 웹페이지를 사용하며 모바일 앱 같은 경험을 느낌.<h2 id="특징">특징</h2>
</li>
<li>Client-side routing 기술을 활용, 페이지 진입 시 리로드없이 라우팅함.</li>
<li>AJAX 기술을 활용, 페이지 이동 시 서버에 데이터만 요청하여 자바스크립트로 페이지를 만듦.</li>
<li>MPA와 다르게, 여러 페이지를 하나의 앱의 구성요소로 보고 여러 페이지 간의 스타일, 컴포넌트를 재활용하는 방향으로 구현.</li>
<li>자바스크립트만을 활용해 전체 페이지를 만들기에, 첫 요청 시 빈 페이지를 받게 됨.<h2 id="장점">장점</h2>
</li>
<li>서버에서 페이지를 만들 필요가 없으므로 CDN에 캐싱이 가능.</li>
<li>매번 페이지 요청을 할 필요가 없어 네트워크 요청이 줄어듦.<ul>
<li>마찬가지로 데이터 요청 등을 캐싱하여 재사용하는 등 제약 조건이 줄어듦.</li>
</ul>
</li>
<li>웹사이트를 개별 페이지보다는 하나의 앱으로 보는 설계로 고도의 소프트웨어 설계와<ul>
<li>패턴을 적용할 수 있음.<h2 id="단점">단점</h2>
</li>
</ul>
</li>
<li>MPA방식 보다는 Search Engine Optimization에 불리함.</li>
<li>하나의 자바스크립트 앱이 지속하므로, 메모리 관리와 성능, 데이터 활용 등이 중요.</li>
<li>여러 페이지를 전송받는 것 보다, 하나의 거대한 자바스크립트 앱을 전송받아야 하므로 코드가 많아질수록 로드 속도가 느려짐.<h2 id="spa에서-라우팅">SPA에서 라우팅</h2>
</li>
<li>주로 History API 혹은 URL Hash를 이용해 페이지 리로드 없는 페이지 전환을 구현.</li>
<li>history, location 등 HTML5 API를 활용.</li>
<li>visibilitychange, popstate, beforeunload 등 window event를 활용하여 페이지 전환 등의 이벤트 시 핸들러를 등록.</li>
<li><strong>react-router, reach-router 등의 라이브러리를 활용하면, 라우팅 관련 기능을 쉽게 사용할 수 있음.</strong><h1 id="mpa">MPA</h1>
</li>
<li>MPA(Multi Page Application)은 서버에 미리 여러 페이지를 두고, 유저가 네비게이션 시 요청에 적합한 페이지를 전달.</li>
<li>미리 서버에서 전체 페이지를 빌드해 브라우저로 전송됨.</li>
<li>서버에 라우팅을 처리하는 기능이 있고, 서버에서 여러 페이지를 관리함.</li>
<li>페이지 요청마다 모든 리소스를 다시 받아오므로, 페이지 간 데이터를 재활용하기 힘듬.<h1 id="react-router">react-router</h1>
<h2 id="react-router-1">react-router</h2>
</li>
<li>Declarative routing for React.(imperative와 다른 패턴!)</li>
<li>React의 JSX를 이용하거나, History API를 사용하여 라우팅을 구현. - 웹에서는 react-router-dom을 사용.</li>
<li>적용 시, 서버의 모든 path에서 같은 앱을 서빙하도록 해야 함.<h2 id="기능">기능</h2>
</li>
<li>React 컴포넌트를 특정 path와 연결하면, 해당하는 path로 진입 시 컴포넌트를 렌더링하게 함.</li>
<li>query, path variable 등 URL parameter를 얻어 활용함.</li>
<li>조건에 맞지 않을 경우 redirect 함.</li>
<li>페이지 이동 시, 이벤트 핸들러를 등록함.</li>
<li>/posts/my-post-1 등의 nested route를 구현함.<h2 id="사용">사용</h2>
</li>
<li><code>&lt;BrowserRouter&gt;</code> 로 감싸 Router Context를 제공해야 함.</li>
<li>Route로 path를 정의하고, 그 안에 렌더링하고자 하는 컴포넌트를 넣음. </li>
<li>Link로 특정 페이지로 이동 시, 리로드 없이 페이지가 이동함.</li>
<li>Switch로, 매칭되는 라우트 하나를 렌더링하게 함.</li>
</ul>
<pre><code>// App.jsx
import { BrowserRouter, Route, Switch } from &#39;react-router-dom&#39;
export function App() {
  return (
    &lt;BrowserRouter&gt; 
      &lt;Switch&gt;
        &lt;Route path=&quot;/about&quot;&gt;&lt;AboutPage /&gt;&lt;/Route&gt;
        &lt;Route path=&quot;/contact&quot;&gt;&lt;ContactPage /&gt;&lt;/Route&gt;
        &lt;Route path=&quot;/&quot;&gt;&lt;HomePage /&gt;&lt;/Route&gt;
      &lt;/Switch&gt;
    &lt;/BrowserRouter&gt;
) }</code></pre><ul>
<li>path=&quot;/&quot;를 맨 마지막에 넣은 이유는 맨 위에 있다면 계속 홈페이지만 렌더링 해주기 떄문에 맨 아래에다가 넣는다~!<pre><code>// HomePage.jsx
import { NavLink } from &#39;react-router-dom&#39;
function HomePage() {
return (
  &lt;div&gt;
      &lt;nav&gt;
          &lt;NavLink to=&quot;/&quot;&gt;Home&lt;/NavLink&gt;
          &lt;NavLink to=&quot;/about&quot;&gt;About&lt;/NavLink&gt;                 &lt;NavLink to=&quot;/contact&quot;&gt;Contact&lt;/NavLink&gt;
      &lt;/nav&gt;
      &lt;div&gt;Home 페이지&lt;/div&gt;
  &lt;/div&gt;
) }</code></pre><pre><code>//AboutPage.jsx
import { NavLink } from &#39;react-router-dom&#39;
function AboutPage() {
return (
  &lt;div&gt;
      &lt;nav&gt;
          &lt;NavLink to=&quot;/&quot;&gt;Home&lt;/NavLink&gt;
          &lt;NavLink to=&quot;/about&quot;&gt;About&lt;/NavLink&gt;                 &lt;NavLink to=&quot;/contact&quot;&gt;Contact&lt;/NavLink&gt;
      &lt;/nav&gt;
      &lt;div&gt;About 페이지&lt;/div&gt;
  &lt;/div&gt;
) }</code></pre><h1 id="react-router-컴포넌트">react-router 컴포넌트</h1>
<h2 id="browserrouter">BrowserRouter</h2>
</li>
<li>HTML5의 History API를 사용하여, UI와 URL의 싱크를 맞추는 역할. - 모든 URL에 대해 동작하게 하기 위해서는 서버 설정 필요.</li>
<li>모든 path 앞의 basename을 지정할 수 있음.
ex) basename=&quot;/ko&quot;</li>
<li>forceRefresh로, 페이지 이동 시 리프레시할 것인지 지정할 수 있음.<h2 id="switch">Switch</h2>
</li>
<li>여러 Route 중 매치되는 Route 위에서부터 <strong>하나 선택하여</strong> 렌더링함.</li>
<li>매칭되는 Route가 없으면 아무것도 보여주지 않음.<ul>
<li>fallback용으로 404 Not Found Page를 추가함.</li>
</ul>
</li>
<li>path=&quot;/&quot;의 경우 모든 path에 매칭되므로 exact 키워드를 추가하거나
가장 아래로 내림.<h2 id="route">Route</h2>
</li>
<li>path와 컴포넌트를 매칭함.</li>
<li>매칭되는 컴포넌트는 children으로 넣어주거나 component prop으로 넘김.</li>
<li>exact 키워드로 정확하게 매칭하는 path를 설정함.</li>
<li>Route로 렌더링 되는 최상위 컴포넌트는 match, location, history를 prop으로 받음.</li>
<li>render prop으로, 매칭되었을 때 실제 어떤 컴포넌트를 렌더링할지 통제함.<h2 id="redirect">Redirect</h2>
</li>
<li>Link와 비슷하나, 렌더링되면 to prop으로 지정한 path로 이동함.</li>
<li>Switch 안에서 쓰일 경우, from, to를 받아 이동하게 만듦.
ex) from=&quot;/&quot; to=&quot;/login&quot;<h2 id="link-navlink">Link, NavLink</h2>
</li>
<li>to prop을 특정 URL로 받아, 클릭 시 네비게이션 함.</li>
<li>anchor tag를 래핑함.</li>
<li>NavLink의 경우, 매칭 시 어떤 스타일을 가질지 등의
추가 기능이 있음.</li>
<li>to에 location object나 함수를 받을 수 있음.<h2 id="sehistory-uselocation-useparams-useroutematch">seHistory, useLocation, useParams, useRouteMatch</h2>
</li>
<li>최상위 컴포넌트가 아니더라도, hook으로 react-router 관련 객체에 접근할 수 있음.</li>
<li>history, location, params, match 객체에 접근함.</li>
</ul>
<h1 id="react-router-응용">React-router 응용</h1>
<h2 id="private-route-만들기">Private Route 만들기</h2>
<ul>
<li><p>특정 조건이 충족되지 않았을 때 다른 페이지로 Redirect 하도록 하는 기능. </p>
</li>
<li><p>유저의 상세 페이지, 개인정보 변경 페이지등을 만들 때 사용됨.</p>
<pre><code>function PrivateRoute({ component: Component, ...props }) {
return &lt;Route {...props} render={props =&gt; {
  const isLoggedIn = !!getUserInfo()
  if (!isLoggedIn) {
    return &lt;Redirect to=&quot;/login&quot; /&gt;
  }
  return &lt;Component {...props} /&gt;
}}
}</code></pre></li>
<li><p>오오 이거 써봐야겟따!!!</p>
<h2 id="query-string-활용하기">query string 활용하기</h2>
</li>
<li><p>URL의 query string 정보를 활용해 앱을 구성할 수 있음.</p>
</li>
<li><p>URLSearchParams API를 활용함.</p>
</li>
</ul>
<p><strong><em>출처 : 엘리스 아카데미</em></strong></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[React-3]]></title>
            <link>https://velog.io/@loo-ke/React-3</link>
            <guid>https://velog.io/@loo-ke/React-3</guid>
            <pubDate>Wed, 10 May 2023 16:52:46 GMT</pubDate>
            <description><![CDATA[<h1 id="이론">이론</h1>
<h2 id="setstate를-callback함수로-전해줄-수-있다">setState를 callback함수로 전해줄 수 있다.</h2>
<pre><code>const [count, setCount] = useState&lt;number&gt;();
function up () {
    setCount((prevState) =&gt; {
        return prevState + 1;
    });
}</code></pre><ul>
<li>이렇게~!<pre><code>const [count, setCount] = useState&lt;number&gt;(0);
function up () {
setCount(count+3);
setCount(count+2);
setCount(count+1);
}
//1</code></pre></li>
<li>이렇게 하면 맨 마지막에 가져온 + 1만 실행이 된다!</li>
<li>그런데 set함수에 callback함수로 전달해주면 기능이 달라진다!<pre><code>const [count, setCount] = useState&lt;number&gt;(0);
function up () {
  setCount((prevState) =&gt; {
      return prevState + 1;
  });//1
  setCount((prevState) =&gt; {
      return prevState + 1;
  });//2
  setCount((prevState) =&gt; {
      return prevState + 1;
  });//3
}</code></pre></li>
<li>State값을 새로운 값으로 만들어서 리턴해줌!!</li>
</ul>
<pre><code>리액트에서 set을 다루는 방법
1. state를 바로 넣어서 다루기
 setter를 함수안에 여러개 넣으면 의도하지 않은 동작이 일어날수 있다


 function up(){setCount(count+1)}


2. 콜백함수로 감싸서 다루기
이전 state 값을 사용해서 새로운 값을 만들고 싶다면 콜백함수로 감싸는게 안전!


  function up(){
    setCount((prev)=&gt;{
      return prev + 1
    })
  }</code></pre><h2 id="두번째-예제클릭-시-현재-시간-출력">두번째 예제(클릭 시 현재 시간 출력)</h2>
<ul>
<li>배열이나 객체 방식의 데이터를 다룸!</li>
<li><em>Counter2에서 li태그를 넣을때 key값을 주지 않으면 에러를 받게 된다.*</em></li>
<li>이를 해결하기 위해 추가되는 Li태그에 key값을 부여한다!!<pre><code>function Counter2() {
const [times, setTimes] = useState&lt;String[]&gt;([]);
console.log(&#39;component - times&#39;, times);
function up() {
  const newTimes = [...times];
  newTimes.push(getCurrentTime());
  setTimes(newTimes);
}
return (
  &lt;&gt;
    &lt;h1&gt;카운터2&lt;/h1&gt;
    &lt;button onClick={up}&gt;+&lt;/button&gt;
    &lt;ol&gt;
      {times.map((value, index) =&gt; {//index를 받고
        return &lt;li key={index}&gt;{value}&lt;/li&gt;;// key에 넣어줌!!!
      })}
    &lt;/ol&gt;
  &lt;/&gt;
);
}</code></pre><h2 id="여태까지-배운거-짬뽕해보자">여태까지 배운거 짬뽕해보자~!</h2>
<h3 id="예제-2번-따라서-해보기">예제 2번 따라서 해보기!</h3>
<pre><code>function Counter4() {
const [step, setStep] = useState(1);
const [count, setCount] = useState&lt;countType[]&gt;([]);
console.log(&#39;count&#39;, count);
return (
  &lt;&gt;
    &lt;h1&gt;Counter4&lt;/h1&gt;
    &lt;input
      type=&quot;number&quot;
      value={step}
      onChange={(e) =&gt; {
        setStep(Number(e.target.value));
      }}
    /&gt;
    &lt;button
      onClick={() =&gt; {
        const newCount = [...count];
        newCount.push({ time: getCurrentTime(), step: step });
        setCount(newCount);
      }}
    &gt;
      +
    &lt;/button&gt;
    &lt;ul&gt;
      {count.map((value, index) =&gt; {
        return (
          &lt;li key={index}&gt;
            {value.time}, {value.step}
          &lt;/li&gt;
        );
      })}
    &lt;/ul&gt;
    0
  &lt;/&gt;
);
}</code></pre></li>
<li>현재 시간 출력과 입력 값의 합을 구하는 코드!<pre><code>function Counter4() {
const [step, setStep] = useState(1);
const [count, setCount] = useState&lt;countType[]&gt;([]);
console.log(&#39;count&#39;, count);
let total = 0;
for (let i = 0; i &lt; count.length; i++) {
  total = total + count[i].step;
}
return (
  &lt;&gt;
    &lt;h1&gt;Counter4&lt;/h1&gt;
    &lt;input
      type=&quot;number&quot;
      value={step}
      onChange={(e) =&gt; {
        setStep(Number(e.target.value));
      }}
    /&gt;
    &lt;button
      onClick={() =&gt; {
        const newCount = [...count];
        newCount.push({ time: getCurrentTime(), step: step });
        setCount(newCount);
      }}
    &gt;
      +
    &lt;/button&gt;
    {total}
    &lt;ul&gt;
      {count.map((value, index) =&gt; {
        return (
          &lt;li key={index}&gt;
            {value.time}, {value.step}
          &lt;/li&gt;
        );
      })}
    &lt;/ul&gt;
  &lt;/&gt;
);
}</code></pre></li>
<li>흠... 보면서 해석하고 쓰는건 가능한데 직접 만드는게 문제다...<h4 id="debugger">debugger</h4>
</li>
<li>debugger를 호출하면
<img src="https://velog.velcdn.com/images/loo-ke/post/9883146e-520b-4fa8-b1a5-a7e5997bd925/image.png" alt=""></li>
</ul>
<h3 id="reduce를-이용해서-현재시간과-누적-값-출력하기">reduce를 이용해서 현재시간과 누적 값 출력하기</h3>
<blockquote>
<p>배열.reduce((누적된값, 현재순번의원소)=&gt; return 누적된값 + 현재순번의원소},0)</p>
</blockquote>
<pre><code>count.reduce((acc, cur) =&gt; {
        console.log(acc, cur);
        return acc + cur.step;
      }, 0)</code></pre><h3 id="ul를-테이블로-바꿔서-출력">ul를 테이블로 바꿔서 출력~!</h3>
<ul>
<li>ul &gt; li의 태그를 table &gt; tr &gt; td로 바꿔서 출력!!<pre><code>  &lt;table&gt;
      {count.map((value, index) =&gt; {
        return (
          &lt;tr key={index}&gt;
            &lt;td&gt;{value.time}&lt;/td&gt;
            &lt;td&gt;{value.step}&lt;/td&gt;
          &lt;/tr&gt;
        );
      })}
    &lt;/table&gt;</code></pre><h3 id="번외--원격-저장소-코드들-저장해보기">번외 : 원격 저장소 코드들 저장해보기~!</h3>
</li>
<li>vs코드에서 버튼으로 pull, push 하는 것을 보았다~!</li>
</ul>
<h3 id="다시-돌아와서-우리가-만든-코드-css-적용해보기">다시 돌아와서 우리가 만든 코드 css 적용해보기!</h3>
<p><strong>인라인 스타일로 넣었다. 그런데 css를 다른 컴포넌트에서도 활용하게 해보자!</strong></p>
<h4 id="인라인-스타일을-사용하면">인라인 스타일을 사용하면?</h4>
<ul>
<li>해당 컴포넌트에만 적용이 된다.</li>
<li>모듈화가 된다.</li>
<li>코드와 가깝기 때문에 찾기에 쉽다.</li>
<li>다른 곳에서 재활용하기 까다롭고 CSS의 문법이 아니다.<h4 id="파일로-쪼개면">파일로 쪼개면?</h4>
</li>
<li>재사용하기 좋다!</li>
<li>만약 다른 컴포넌트에 이름이 중복된 클래스가 있다면 그 친구때문에 간섭이 생긴다.<h4 id="stylemodulecss-사용해보기">style.module.css 사용해보기</h4>
새 파일(App.module.css)을 만들고 간단한 style 태그를 작성!<pre><code>.layout {
border: 10px solid blue;
}
</code></pre></li>
</ul>
<pre><code>### 번외 : 리팩토링 해보기
- 옮기고 싶은 컴포넌트를 드래그해서 마우스 오른쪽 클릭 &gt; 리팩토링 &gt; new file 클릭! &gt; 신세계~
그럼 우리가 만든 코드가 모듈이 된다~! 

### 번외 : import React,{useState} from &#39;react&#39;; 에서 {}가 있고 없고의 차이를 알아보자
- export default와 export의 차이
- export default
  - export default를 사용하면 export한 파일의 대장을 끌고 온다.
  - 그러면 import 할 때 중괄호{}를 사용하지 않는다.
- export
  - 이건 대표가 아니니까 이름을 명확하게 입력해야된다.</code></pre><p>  export contentType <del>~</del></p>
<p>  import {contentType} from &#39;./<del>~</del>&#39;;</p>
<pre><code>  이름 정확하게 입력!!!!

## MUI
&gt;https://mui.com/

- 부트스트랩 같은 거!! 다른 사람이 만들어 놓은거 가져다 쓸 수 있다!</code></pre><p>새 터미널 열고!
npm install @mui/material @emotion/react @emotion/styled</p>
<p>```
<img src="https://velog.velcdn.com/images/loo-ke/post/b5bd1415-9afe-48fa-8a1c-1f14f818cccc/image.png" alt="">
package.json에서 설치된 것을 확인!</p>
<ul>
<li><code>&lt;Container&gt;&lt;/Container&gt;</code>를 입력한 후 저 태그 안에 여태까지 만든 컴포넌트들을 넣으면 화면을 확대해도 가운데 정렬을 자동으로 한다~! 개꿀!</li>
</ul>
<p><strong><em>출처 : 엘리스 아카데미</em></strong></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[React-2]]></title>
            <link>https://velog.io/@loo-ke/React-2</link>
            <guid>https://velog.io/@loo-ke/React-2</guid>
            <pubDate>Wed, 10 May 2023 16:51:13 GMT</pubDate>
            <description><![CDATA[<h1 id="이론">이론</h1>
<blockquote>
<p>이고잉 코치님이 주신 선물~~
<a href="https://stackblitz.com/">https://stackblitz.com/</a></p>
</blockquote>
<h2 id="스택블리츠에서-지난-주에-했던거-구현">스택블리츠에서 지난 주에 했던거 구현~</h2>
<h2 id="프리티어-설정하는-방법">프리티어 설정하는 방법</h2>
<blockquote>
<p>vsCode에서 설치하는 것: 혼자 개발한다면 이것도 좋습니다.
prettierrc에 설정 담아놓기: 여러사람들과 코드를 공유한다면 이렇게 해야합니당 컨벤션을 맞추는 것을 저장할 때마다 강제하기 위해서! </p>
</blockquote>
<blockquote>
<p><a href="https://velog.io/@dum6894/%EA%B0%9C%EB%B0%9C%ED%99%98%EA%B2%BD-vscode-prettier-%EC%84%A4%EC%B9%98-%EB%B0%8F-%EC%82%AC%EC%9A%A9%EB%B2%95">https://velog.io/@dum6894/%EA%B0%9C%EB%B0%9C%ED%99%98%EA%B2%BD-vscode-prettier-%EC%84%A4%EC%B9%98-%EB%B0%8F-%EC%82%AC%EC%9A%A9%EB%B2%95</a></p>
</blockquote>
<h2 id="counter2-만들기">Counter2 만들기</h2>
<h3 id="현재-시간을-출력하는-버튼-만들기">현재 시간을 출력하는 버튼 만들기!</h3>
<pre><code>// 현재 시간을 구하는 함수
function getCurrentTime() {
  const now = new Date();
  const hours = String(now.getHours()).padStart(2, &#39;0&#39;);
  const minutes = String(now.getMinutes()).padStart(2, &#39;0&#39;);
  const seconds = String(now.getSeconds()).padStart(2, &#39;0&#39;);

  return `${hours}:${minutes}:${seconds}`;
}

console.log(getCurrentTime());</code></pre><ul>
<li>현재 시간을 구해주는 함수를 챗지피티로 만들어보았다~!</li>
<li>컴포넌트에 getCurrentTime함수 호출해서 적용해보기~! <pre><code>// Counter2 컴포넌트
function Counter2() {
const [times, setTimes] = useState([]);
function up() {
  times.push(getCurrentTime());
  console.log(&#39;up-times&#39;, times);
  setTimes(times);
}
return (
  &lt;&gt;
    &lt;h1&gt;카운터2&lt;/h1&gt;
    &lt;button onClick={up}&gt;+&lt;/button&gt;
    &lt;ol&gt;&lt;/ol&gt;
  &lt;/&gt;
);
}</code></pre><h4 id="--상태의-데이터-타입이-배열이나-객체면-복제하고-복제본을-수정한다">- 상태의 데이터 타입이 배열이나 객체면 복제하고 복제본을 수정한다!!</h4>
<pre><code>function Counter2() {
const [times, setTimes] = useState([]);
console.log(&#39;component - times&#39;, times);
function up() {
  const newTimes = [...times];
  newTimes.push(getCurrentTime());
  setTimes(newTimes);
}
return (
  &lt;&gt;
    &lt;h1&gt;카운터2&lt;/h1&gt;
    &lt;button onClick={up}&gt;+&lt;/button&gt;
    &lt;ol&gt;&lt;/ol&gt;
  &lt;/&gt;
);
}</code></pre></li>
<li>새로운 배열을 복제해서 복제한 배열을 수정하는 코드!
<em>여기까지 커밋!</em></li>
</ul>
<h2 id="typescript-제네릭-타입-설명">TypeScript 제네릭 타입 설명!</h2>
<p><img src="https://velog.velcdn.com/images/loo-ke/post/47af554b-ca1a-4343-948e-be9cb51ff95b/image.png" alt=""></p>
<ul>
<li>위의 코드를 보면 매개변수에 타입을 지정하지 않아서 any타입으로 출력이 되는 것을 볼 수 있다!</li>
</ul>
<p><strong>그럼 타입을 지정해보자!</strong></p>
<pre><code>function containNumber(a:number,b:number){
    return[a,b]
}
console.log(containNumber(10,20))
//const a:number[] = [1,2] // 숫자만 들어오는 배열이다!!!</code></pre><ul>
<li><p>이렇게 타입을 명시해줘서 내가 원하는 타입을 지정할 수 있다!</p>
</li>
<li><p>제네릭 : 데이터 타입을 넘버로 특화시킨 함수를 일반화해서 어떤 데이터 타입도 수용할 수 있게 하겠다. 그러면서 타입 안정성을 놓치지 않겠다!</p>
<pre><code>function containGeneric&lt;T&gt;(a:T,b:T):T[]{
  return [a,b];
}
console.log(containGeneric&lt;number&gt;(1,2));//number부분을 string으로 바꾸면 string타입을 받게 된다!!</code></pre></li>
<li><p>함수 선언 부분에서는 아직 들어올 타입을 모르겠다!</p>
</li>
<li><p>함수 호출 부분에서 데이터 타입을 명시해줘서 타입을 알려준다!!</p>
</li>
<li><p>함수 호출 부분에서 <code>&lt;데이터타입&gt;</code>을 생략해줄 수 있다.
<code>console.log(containGeneric(1,2));</code></p>
</li>
</ul>
<h3 id="다시-카운터-돌아와서-오류-해결하기">다시 카운터 돌아와서! 오류 해결하기!!</h3>
<ul>
<li>타입에 대해서 이야기 하고있다!!</li>
<li>지금 Counter2의 useState의 타입은 never이다.</li>
<li>never란 ?<blockquote>
<ul>
<li>보통 state의 intialState에 들어가는 값을 보고 타입을 자동적으로 추론하는데(따라서 안써도 되는 경우가 있음), []이렇게 빈 배열의 경우는 추측할 수 없기 때문에 never[]로 인식합니당 </li>
</ul>
</blockquote>
</li>
</ul>
<blockquote>
<p>void는 없다! 이고 never는 추측할 수 없어요 입니당</p>
</blockquote>
<p>(void는 return값이 없다는 뜻!)</p>
<pre><code>const [times, setTimes] = useState([&#39;&#39;]);
// const [times, setTimes] = useState&lt;String[]&gt;([]);
// string[]이 들어온다는 것을 명시해주자!!</code></pre><ul>
<li>위의 코드를 적용하면 에러 사라짐!!<h4 id="근데-콘솔-왜-두번씩-실행됨">근데 콘솔 왜 두번씩 실행됨?</h4>
</li>
<li><strong>개발 단계(환경)이라서 콘솔이 두번씩 실행 된다!! 실제 서버는 한번 실행!!</strong><h3 id="이제-브라우저에-출력할-수-있게-해보자">이제 브라우저에 출력할 수 있게 해보자!</h3>
</li>
<li>맵 메소드를 이용할 것인데 <strong>map()</strong>이란?
<img src="https://velog.velcdn.com/images/loo-ke/post/f218b7f9-9d72-4e36-bd76-3d3bf02a44d6/image.png" alt=""><pre><code>a = [1,2,3]
b = a.map((value) =&gt; {
  return value * 2
}
)
console.log(a,b);//[1,2,3] [2,4,6];</code></pre><pre><code>function Counter2() {
const [times, setTimes] = useState&lt;String[]&gt;([]);
console.log(&#39;component - times&#39;, times);
function up() {
  const newTimes = [...times];
  newTimes.push(getCurrentTime());
  setTimes(newTimes);
}
return (
  &lt;&gt;
    &lt;h1&gt;카운터2&lt;/h1&gt;
    &lt;button onClick={up}&gt;+&lt;/button&gt;
    &lt;ol&gt;
      {times.map((value) =&gt; {
        return &lt;li&gt;{value}&lt;/li&gt;;
      })}
    &lt;/ol&gt;
  &lt;/&gt;
);
}</code></pre></li>
<li>ol태그 안에 map 함수를 이용해서 출력을 하게 했다!!</li>
</ul>
<h2 id="form">form</h2>
<ul>
<li>input의 값을 받아와서 새로운 state로 변경 되어야 input의 value로 들어가고 계산이 된다!<pre><code>function Counter3() {
const [count, setCount] = useState&lt;number&gt;(0);
const [step, setStep] = useState&lt;number&gt;(1);
return (
  &lt;&gt;
    &lt;h1&gt;Counter3&lt;/h1&gt;
    &lt;input
      type=&quot;number&quot;
      value={step}
      onChange={(e) =&gt; {
        setStep(Number(e.target.value));
      }}
    &gt;&lt;/input&gt;
    &lt;button onClick={() =&gt; setCount(count + step)}&gt;+&lt;/button&gt;
    {count}
  &lt;/&gt;
);
}</code></pre></li>
</ul>
<blockquote>
<p>끝내기 전에 확장 기능 소개~!
<a href="https://react.dev/learn/react-developer-tools">https://react.dev/learn/react-developer-tools</a></p>
</blockquote>
<p><strong><em>출처 : 엘리스 아카데미</em></strong></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[5. styled-components]]></title>
            <link>https://velog.io/@loo-ke/5.-styled-components</link>
            <guid>https://velog.io/@loo-ke/5.-styled-components</guid>
            <pubDate>Tue, 09 May 2023 09:03:38 GMT</pubDate>
            <description><![CDATA[<h2 id="styled-components">Styled-components</h2>
<ul>
<li>자바스크립트 파일 안에 스타일을 정의하고, React 컴포넌트처럼 활용.</li>
<li>자바스크립트 코드와 긴밀히 연계하여 다양한 코드를 작성할 수 있음.</li>
<li>별도의 CSS 파일을 만들지 않고 하나의 파일 안에 스타일을 관리하고 싶을때 유리.</li>
<li>스타일 코드와 컴포넌트 코드 간의 결합을 나누고 싶을때 유리.</li>
<li>tagged template literal이라는 문법을 활용.</li>
<li>CSS 코드에 post-css, minification, Sass 적용.</li>
<li>CSS 코드를 겹치지 않게 처리.<ul>
<li>클래스 이름 자체가 hash.</li>
</ul>
</li>
</ul>
<p><strong><em>출처 : 엘리스 아카데미</em></strong></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[4. CSS Flexbox]]></title>
            <link>https://velog.io/@loo-ke/4.-CSS-Flexbox</link>
            <guid>https://velog.io/@loo-ke/4.-CSS-Flexbox</guid>
            <pubDate>Tue, 09 May 2023 09:03:21 GMT</pubDate>
            <description><![CDATA[<h2 id="css-flexbox-model">Css FlexBox Model</h2>
<ul>
<li><p>HTML element를 하나의 상자로 간주하고, 그 안에서 어떻게 내부 item을 배열할 것인가를 스타일 하는 모델.</p>
</li>
<li><p>1차원의 레이아웃을 디자인하는 데 사용.</p>
</li>
<li><p>responsive design에 유리.</p>
</li>
<li><p>가운데 정렬,비율로 정렬 등을 처리할때 유리.</p>
<h3 id="flexbox-기본-개념">FlexBox 기본 개념</h3>
</li>
<li><p>flex container - Flexbox 아이템을 담는 컨테이너.</p>
</li>
<li><p>Flex Item - 컨테이너 안에 담긴 아이템.</p>
</li>
<li><p>Flex axis - flex 아이템의 방향을 결정하는 축.</p>
<h3 id="flexbox-properties---container">Flexbox properties - container</h3>
</li>
<li><p>flex-direction</p>
<ul>
<li>row, column 등의 방향을 결정.</li>
</ul>
</li>
<li><p>justify-content</p>
<ul>
<li>main axis에서의 정렬을 결정</li>
</ul>
</li>
<li><p>align-items</p>
<ul>
<li>cross axis에서의 정렬을 결정.</li>
</ul>
</li>
<li><p>flex-wrap</p>
<ul>
<li>flex container가 내부 item의 width를 합친 것보다 작아질 때, 어떻게 정렬할 것인지를 결정.<h3 id="flexbox-properties---item">Flexbox properties - item</h3>
</li>
</ul>
</li>
<li><p>flex-grow</p>
<ul>
<li>flex container가 커질 때 item이 얼마만큼 늘어날 것인지를 결정.</li>
</ul>
</li>
<li><p>flex-shrink</p>
<ul>
<li>flex container가 줄어들 때 item이 얼마만큼 줄어들 것인지를 결정.</li>
</ul>
</li>
<li><p>flex-basis</p>
<ul>
<li>기준점이 되는 item의 크기.</li>
</ul>
</li>
<li><p>justify-self</p>
<ul>
<li>한 아이템을 main-axis에 따라 어떻게 정렬할 것인지를 결정.</li>
</ul>
</li>
<li><p>align-self</p>
<ul>
<li>한 아이템을 cross-axis에 따라 어떻게 정렬할 것인지를 결정.</li>
</ul>
</li>
<li><p>order</p>
<ul>
<li>flex container에서 item의 순서를 결정.<h3 id="예시">예시</h3>
<pre><code>.container {
display: flex; flex-direction: column;
}
.wrapper {
  width: 100%;
}
.three {
  display: flex;
}
.four, .five {
  flex: 1;
}</code></pre><img src="https://velog.velcdn.com/images/loo-ke/post/a7094ae3-a5a7-4cf1-9d45-a3b3c91d4cec/image.png" alt=""></li>
</ul>
<p><strong><em>출처 : 엘리스 아카데미</em></strong></p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[3. CSS, Sass]]></title>
            <link>https://velog.io/@loo-ke/3.-CSS-Sass</link>
            <guid>https://velog.io/@loo-ke/3.-CSS-Sass</guid>
            <pubDate>Tue, 09 May 2023 09:03:05 GMT</pubDate>
            <description><![CDATA[<h2 id="css-box-model">CSS Box Model</h2>
<ul>
<li>CSS layout의 기본이 되는 모델</li>
<li>content-box, padding-box, border-box, margin-box 순으로 하나의 엘리멘트를 감싸고 있다.</li>
<li>bo의 타입은 inline, block enrkwl</li>
<li>display:inline, display:inline-block, display:block으로 서로 다른 box type을 적용 가능</li>
</ul>
<p><img src="https://velog.velcdn.com/images/loo-ke/post/f6e3fef2-4d49-4ae2-b889-8dd4fd69cd19/image.png" alt=""></p>
<h3 id="position">position</h3>
<ul>
<li>static<ul>
<li>position의 default 값으로, element는 normal flow를 따라 위치함.</li>
</ul>
</li>
<li>relative<ul>
<li>normal flow를 따라 위치하되, 자기 자신에 상대적으로 위치함.</li>
</ul>
</li>
<li>absolute<ul>
<li>normal flow에서 벗어나 가장 가까운 ancestor에 상대적으로 위치함.</li>
</ul>
</li>
<li>fixed<ul>
<li>normal flow를 벗어나 viewport에 상대적으로 위치함.</li>
</ul>
</li>
<li>sticky<ul>
<li>normal flow에 따라 위치하되, 가장 가까운 scrolling ancestor에 상대적으로 위치함.<h3 id="units">units</h3>
</li>
</ul>
</li>
<li>px, pt, cm, in<ul>
<li>절대적인 길이를 표현하는 unit.</li>
</ul>
</li>
<li>rem, em, %<ul>
<li>특정 값에 상대적인 길이를 표현하는 unit.</li>
</ul>
</li>
<li>vw, vh, vmin, vmax<ul>
<li>viewport에 상대적인 길이를 표현하는 unit.<h2 id="sass">Sass</h2>
</li>
</ul>
</li>
<li>Syntactically Awesome Style Sheets. CSS Preprocessor.</li>
<li>SCSS, Sass 문법을 지원함.</li>
<li>모듈, 믹스인, nested style, 변수, 조건문, 반복문 등의 기능으로 CSS를 프로그래밍 언어적으로 활용하도록 확장.</li>
<li>styled-components는 Sass를 기본적으로 지원함.<h3 id="sass-1">Sass &amp;</h3>
</li>
<li>&amp;는 자기 자신을 나타내는 placeholder. </li>
<li>기존 CSS의 selector 문법을 응용하여 복잡한 스타일을 적용.<h3 id="sass-variable">Sass variable</h3>
</li>
<li>믹스인, partial 와 함께 Sass가 제공하는 코드 관리 방법 중 하나.</li>
<li>색상, 사이즈등 자주 등장하는 값을 주로 변수로 사용함.<pre><code>$color-red: red;
$color-white: #fff;
.reset-button { 
  color: $color-red; 
  &amp;:hover {
      color: $color-white;
    }
}</code></pre><h3 id="sass-nested-style">Sass nested style</h3>
<pre><code>$color-red: red;
$color-white: #fff;
.reset-button {
  color: $color-red;
  &amp;:hover {
      color: $color-white;
    }
  &gt; button {} 
}</code></pre></li>
<li>위의 코드에서 hover부분처럼 작성할 수 있음<h3 id="sass-mixins-import-include">Sass mixins, import, include</h3>
</li>
<li>mixins - 여러 스타일을 한꺼번에 묶어서 사용할 수 있다고 정의할 수 있다.<pre><code>@mixins font-style-1 {
font-size: 36pt;
line-height: 1.5;
font-weight: 700;
letter-spacing: -0.05;
}</code></pre></li>
<li>import, include - 컴포넌트처럼 사용 가능~!<pre><code>@import &#39;./font-styles.scss&#39;
</code></pre></li>
</ul>
<p>.button {
  @include font-style-1;
  background: red;
}</p>
<p>```</p>
<p><strong><em>출처 : 엘리스 아카데미</em></strong></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[2. React 앱에서의 스타일링 방법]]></title>
            <link>https://velog.io/@loo-ke/2.-React-%EC%95%B1%EC%97%90%EC%84%9C%EC%9D%98-%EC%8A%A4%ED%83%80%EC%9D%BC%EB%A7%81-%EB%B0%A9%EB%B2%95</link>
            <guid>https://velog.io/@loo-ke/2.-React-%EC%95%B1%EC%97%90%EC%84%9C%EC%9D%98-%EC%8A%A4%ED%83%80%EC%9D%BC%EB%A7%81-%EB%B0%A9%EB%B2%95</guid>
            <pubDate>Tue, 09 May 2023 09:02:38 GMT</pubDate>
            <description><![CDATA[<h2 id="css-import">CSS import</h2>
<ul>
<li>CSS 파일을 import 해서 사용</li>
<li>필요한 모든 css 스타일을 하나의 파일에 작성하여, 자바스크립트 파일과 코드 분리 가능<h3 id="css-import-장단점">css import 장단점</h3>
</li>
<li>단순히 css파일만을 import하여 사용할 수 있어 편리</li>
<li>컴포넌트가 많지 않을 경우 하나의 CSS 파일에 코드를 관리하는 것도 가능</li>
<li>CSS 파일은 분리할 수 있으나, namespace를 나눌 수 없음.</li>
<li>만일 스타일이 겹칠 경우 cascading rule에 따라, 마지막에 나온 룰이 덮어 씌어짐<h2 id="css-module">CSS module</h2>
</li>
<li>하나의 CSS module 파일 안에 작성한 스타일은 하나의 파일 namespace로 관리.</li>
<li>class name 뒤에 겹치지 않는 hash를 붙임</li>
<li>스타일이 겹치는 상황을 해결</li>
<li>두 단어 이상의 경우, class명을 camelCase로 이름을 지음.<pre><code>import styles from &quot;./input-with-button.module.css&quot;;
</code></pre></li>
</ul>
<p>export function InputWithButton() {
    return (
      <div className={styles.container}>
        <input type="text" name="text" className={styles.input} />
        <button className={styles.button}>Submit</button>
      </div>
    ); 
}</p>
<p>```</p>
<h2 id="css-in-js">CSS-in-JS</h2>
<ul>
<li>별도의 CSS 파일을 만들지 않고 하나의 컴포넌트 파일 안에서 스타일을 작성</li>
<li>자바스크립트 문법을 그대로 활용하여 코드를 작성(자주 활용하는 색상 변수로 선언 후 호출 가능!)</li>
<li>React 컴포넌트를 사용하는 것 처럼 사용</li>
<li>Sass 문법 활용 가능</li>
</ul>
<p><strong><em>출처 : 엘리스 아카데미</em></strong></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[1. React 스타일링]]></title>
            <link>https://velog.io/@loo-ke/React-%EC%8A%A4%ED%83%80%EC%9D%BC%EB%A7%81</link>
            <guid>https://velog.io/@loo-ke/React-%EC%8A%A4%ED%83%80%EC%9D%BC%EB%A7%81</guid>
            <pubDate>Mon, 08 May 2023 16:19:54 GMT</pubDate>
            <description><![CDATA[<h1 id="1-react-앱에서의-스타일링-overview">1. React 앱에서의 스타일링 overview</h1>
<h2 id="스타일링은-왜-중요할까">스타일링은 왜 중요할까?</h2>
<ul>
<li>사용자가 한 눈에 알아보게 하기 위해!<h2 id="좋은-앱을-만들려면">좋은 앱을 만들려면?</h2>
</li>
<li>번들 사이즈에 대한 고려<ul>
<li>CSS코드가 차지하는 사이즈는 무척 중요한 요소</li>
</ul>
</li>
<li>앱 성능에 대한 고려<ul>
<li>animation, transition 등 유저와의 상호작용에서 스타일 코드의 성능이 중요</li>
</ul>
</li>
<li>사용자에게 유리한 UI/UX를 고려<ul>
<li>스타일링에 대한 지식으로, 고급 테크닉을 적용하여 더 나은 UI/UX를 반영</li>
</ul>
</li>
<li>자바스크립트를 이용한 다양한 스타일 기법<ul>
<li>토글링, 애니메이션, 다크모드 복잡한 컴포넌트 등은 자바스크립트에 대한 지식만으로 구현하기 힘듬</li>
</ul>
</li>
<li>유지보수가 용이하고 확장 가능한 코드를 작성<ul>
<li>스타일에 관련된 코드를 어떻게 작성하고 관리하는가에 대한 지식이 필요</li>
</ul>
</li>
</ul>
<h1 id=""></h1>
<h1 id="-1"></h1>
<p><strong><em>출처 : 엘리스 아카데미</em></strong></p>
]]></description>
        </item>
    </channel>
</rss>