<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>dev_space.log</title>
        <link>https://velog.io/</link>
        <description>개발자 되기</description>
        <lastBuildDate>Sun, 10 Apr 2022 16:22:22 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>dev_space.log</title>
            <url>https://images.velog.io/images/dev_space/profile/226e22ed-d3cf-4949-9e60-672347a005b0/KakaoTalk_Photo_2021-08-15-03-13-27.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. dev_space.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/dev_space" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[React 18 클라이언트 렌더링 API 업데이트 이슈(TS)]]></title>
            <link>https://velog.io/@dev_space/React-18-%ED%81%B4%EB%9D%BC%EC%9D%B4%EC%96%B8%ED%8A%B8-%EB%A0%8C%EB%8D%94%EB%A7%81-API-%EC%97%85%EB%8D%B0%EC%9D%B4%ED%8A%B8-%EC%9D%B4%EC%8A%88TS</link>
            <guid>https://velog.io/@dev_space/React-18-%ED%81%B4%EB%9D%BC%EC%9D%B4%EC%96%B8%ED%8A%B8-%EB%A0%8C%EB%8D%94%EB%A7%81-API-%EC%97%85%EB%8D%B0%EC%9D%B4%ED%8A%B8-%EC%9D%B4%EC%8A%88TS</guid>
            <pubDate>Sun, 10 Apr 2022 16:22:22 GMT</pubDate>
            <description><![CDATA[<h3 id="warning-reactdomrender-is-no-longer-supported-in-react-18-use-createroot-instead-until-you-switch-to-the-new-api-your-app-will-behave-as-if-its-running-react-17">Warning: ReactDOM.render is no longer supported in React 18. Use createRoot instead. Until you switch to the new API, your app will behave as if it&#39;s running React 17.</h3>
<p><img src="https://velog.velcdn.com/images/dev_space/post/801f5811-6392-460b-8b32-f758e5a74fe2/image.png" alt=""></p>
<p>React를 실행하는 과정에 에러가 발생하였는데, <code>ReactDOM.render</code> 는 React18에서 더 이상 사용되지 않는다고 한다.</p>
<h2 id="해결">해결</h2>
<p>index.tsx 파일을 바꿔주었다.</p>
<pre><code class="language-jsx">//index.tsx
import React from &#39;react&#39;;
import ReactDOM from &#39;react-dom/client&#39;;
import App from &#39;./App&#39;;

const root = ReactDOM.createRoot(document.getElementById(&#39;root&#39;) as HTMLElement);

root.render(
  &lt;React.StrictMode&gt;
    &lt;App /&gt;
  &lt;/React.StrictMode&gt;
)
</code></pre>
<p>그런데 새로 변경된 방법으로 렌더링할때 <code>&lt;StrictMode&gt;</code>를 추가하면 컴포넌트가 두 번 렌더링 되버린다.
<img src="https://velog.velcdn.com/images/dev_space/post/f12e8154-14f8-4438-b6f7-c25a1a6efe09/image.png" alt="">
<code>&lt;StrictMode&gt;</code> 를 제거해주니까 한번만 실행되었다.</p>
<pre><code class="language-jsx">import React from &#39;react&#39;;
import ReactDOM from &#39;react-dom/client&#39;;
import App from &#39;./App&#39;;

const root = ReactDOM.createRoot(document.getElementById(&#39;root&#39;) as HTMLElement);

root.render(&lt;App /&gt;);</code></pre>
<blockquote>
<p>typescript에서 <code>import ReactDOM from &#39;react-dom/client&#39;</code> 를 사용하려면
터미널에 <code>npm i --save-dev @types/react-dom</code> 를 입력해서 설치해준다.</p>
</blockquote>
<h1 id="reference">Reference</h1>
<p><a href="https://reactjs.org/blog/2022/03/08/react-18-upgrade-guide.html#updates-to-client-rendering-apis">https://reactjs.org/blog/2022/03/08/react-18-upgrade-guide.html#updates-to-client-rendering-apis</a>
<a href="https://dev.to/osmanforhad/react-js-warning-reactdomrender-is-no-longer-supported-in-react-18-use-createroot-instead-until-you-switch-to-the-new-api-1jhh">https://dev.to/osmanforhad/react-js-warning-reactdomrender-is-no-longer-supported-in-react-18-use-createroot-instead-until-you-switch-to-the-new-api-1jhh</a>
<a href="https://stackoverflow.com/questions/71668256/deprecation-notice-reactdom-render-is-no-longer-supported-in-react-18">https://stackoverflow.com/questions/71668256/deprecation-notice-reactdom-render-is-no-longer-supported-in-react-18</a>
<a href="https://velog.io/@ehrbs2021/React-18-react-dom-Type-%EC%9D%B4%EC%8A%88">https://velog.io/@ehrbs2021/React-18-react-dom-Type-%EC%9D%B4%EC%8A%88</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Next.js란]]></title>
            <link>https://velog.io/@dev_space/Next.js%EB%9E%80</link>
            <guid>https://velog.io/@dev_space/Next.js%EB%9E%80</guid>
            <pubDate>Fri, 08 Apr 2022 16:04:37 GMT</pubDate>
            <description><![CDATA[<h1 id="nextjs-란">NextJS 란?</h1>
<ul>
<li>홈페이지에 보면 <strong>The React Frameworkfor Production</strong> 라는 말이 큼지막하게 써있다.<ul>
<li><strong>생산을 위한 React 프레임워크</strong></li>
</ul>
</li>
<li><strong>Next.js는 하이브리드 정적 및 서버 렌더링, TypeScript 지원, 스마트 번들링, 경로 미리 가져오기 등 생산에 필요한 모든 기능을 통해 최고의 개발자 경험을 제공한다.</strong></li>
<li>React 라이브러리의 프레임워크다.</li>
<li>SSR을 쉽게 구현하도록 도와준다.<ul>
<li>기본적으로 React는 CSR으로 동작한다. 이는 웹사이트를 요청했을 때 빈 HTML을 가져와 JavaScript를 로딩하기에 첫 로딩 시간이 오래걸리고 SEO에 취약하다는 단점이 있는데, Next.js는 미리 데이터가 렌더링된 페이지를 가져올수 있게 해주므로 사용자에게 더 좋은 경험을 주고, 검색 엔진에 잘 노출 될 수 있도록 해주는 SEO에서도 장점을 얻을 수 있다.</li>
<li>React에서도 SSR구현, SEO 최적화가 가능하지만 복잡하다고 한다.</li>
</ul>
</li>
<li>SSR 뿐만 아니라 정적 사이트 생성(Static-Site Generate (SSG))도 가능하게 해준다.<h2 id="기능">기능</h2>
Next.js 공식문서에 나와있는 기능들을 정리해 보자.</li>
</ul>
<h3 id="1-image-optimization">1. Image Optimization</h3>
<p><strong>HTML:</strong></p>
<pre><code class="language-html">&lt;img src=&quot;/my-image.jpg...&gt;</code></pre>
<p><strong>Next.js:</strong></p>
<pre><code class="language-jsx">import Image from &#39;next/image&#39;
&lt;Image src=&quot;/my-img.jpg&quot;...&gt;</code></pre>
<p><code>&lt;Image&gt;</code> 및 즉각적인 빌드를 통한 자동 이미지 최적화.</p>
<ul>
<li><strong>향상된 성능</strong>
최신 이미지 형식을 사용하여 항상 각 장치에 대해 올바른 크기의 이미지를 제공합니다.</li>
<li><strong>시각적 안정성</strong>
누적 레이아웃 이동 자동으로 방지</li>
<li><strong>더 빠른 페이지 로드 (로드 지연)</strong>
이미지가 뷰포트에 들어갈 때만 로드되며, 흐릿한 자리 표시자(선택 사항)가 있습니다.</li>
<li><strong>자산 유연성</strong>
원격 서버에 저장된 이미지의 경우에도 주문형 이미지 크기 조정</li>
</ul>
<blockquote>
<p>로드 지연 : <a href="https://web.dev/lazy-loading/">https://web.dev/lazy-loading</a></p>
</blockquote>
<p>Next.js 를 사용하면 SEO에 강점을 갖도록 이미지가 자동으로 최적화 된다.
<a href="https://nextjs.org/docs/basic-features/image-optimization">Image Optimization</a></p>
<h3 id="2-internationalization">2. Internationalization</h3>
<p>내장 도메인 및 하위 도메인 라우팅 및 자동 언어 감지.</p>
<ul>
<li>국제화 라우팅 및 언어 감지를 “기본적으로” 지원할 뿐 아니라, SSG 또는 SSR에서 모두, 국제화 라우팅 기술 중 가장 널리 사용되는 두 가지 방법 – “하위 경로 라우팅(subpath routing)” 및 “도메인 라우팅(domain routing)”을 지원한다<pre><code class="language-jsx">// next.config.js
module.exports = {
i18n: {
  locales: [&#39;en-US&#39;, &#39;fr&#39;, &#39;nl-NL&#39;],
  defaultLocale: &#39;en-US&#39;,
},
}</code></pre>
pages/blog.js가 있다면, 이 세팅을 통하여 다음과 같은 URL들이 자동 설정된다:</li>
<li>English: <strong>/blog</strong></li>
<li>French: <strong>/fr/blog</strong></li>
<li>Netherlands: <strong>/nl-NL/blog</strong></li>
</ul>
<p><code>defaultLocale: &#39;en-US&#39;</code> 은 기본값이다.
<a href="https://nextjs.org/docs/advanced-features/i18n-routing">Internationalization</a></p>
<h3 id="3-nextjs-analytics">3. Next.js Analytics</h3>
<p>실제 방문자 데이터와 페이지별 통찰력을 기반으로 한 진정한 등대 점수</p>
<ul>
<li>Next.js Analytics를 사용하면 서로 다른 메트릭을 사용하여 페이지의 성능을 분석하고 측정할 수 있습니다.</li>
</ul>
<p><a href="https://nextjs.org/analytics">Next.js Analytics</a>
<a href="https://nextjs.org/docs/advanced-features/measuring-performance">Measuring performance</a></p>
<h3 id="4-zero-config">4. Zero Config</h3>
<p>자동 컴파일 및 번들링. 처음부터 생산에 최적화되어 있다.
<strong>자동설정</strong></p>
<pre><code>npx create-next-app@latest
# or
yarn create next-app
# or
pnpm create next-app</code></pre><p>TypeScript를 사용하는건 끝에 --typescript 를 붙이면 된다.</p>
<p><strong>개발 서버 실행</strong></p>
<pre><code class="language-jsx">npm run dev
or
yarn dev</code></pre>
<p>npm install 을 사용해서 수동 설정도 가능하다.
<a href="https://nextjs.org/docs/getting-started">Zero Config</a></p>
<h3 id="5-hybrid-ssg-and-ssr">5. Hybrid: SSG and SSR</h3>
<p>단일 프로젝트에서 빌드 시 (SSG) 또는 요청 시 (SSR) 페이지를 사전 렌더링합니다.</p>
<ul>
<li><strong>정적사이트 생성(SSG)</strong>
사용자가 처음에 페이지에 접속을 요청했을 경우 사용자에게 렌더링될 빈페이지가 아닌 완성된 html파일을 응답값으로 전달해 준다. 그 후 요청이 들어올때마다 만들어진 html파일을 응답해준다.</li>
<li><strong>서버사이드 렌더링(SSR)</strong>
웹사이트에 접속하면(요청이 들어오게 되면) 서버측에서 html파일을 렌더링하여 완성된 html파일을 클라이언트로 전달을하고 클라이언트에서는 이 html파일을 DOM트리로 전환하여 보여주게 되고 js파일을 해석한다.
<img src="https://velog.velcdn.com/cloudflare/dev_space/5c05d432-7146-4746-8504-cda660b614b5/Untitled.png" alt=""><h4 id="ssg-vs-ssr"><strong>SSG vs SSR</strong></h4>
<h5 id="ssg">SSG</h5>
페이지를 한 번 만들고 CDN에서 제공할 수 있으므로 모든 요청에 대해 서버가 페이지를 렌더링하도록 하는 것보다 훨씬 빠르기 때문에 가능 하면 <strong>정적 생성</strong>(데이터 포함 및 제외)을 사용하는 것이 좋다 .
  다음을 포함한 다양한 유형의 페이지에 대해 정적 생성 을 사용할 수 있다 .<ul>
<li>마케팅 페이지</li>
<li>블로그 게시물</li>
<li>전자상거래 제품 목록</li>
<li>도움말 및 문서<h5 id="ssr">SSR</h5>
SSG 는 사용자의 요청에 앞서 페이지를 미리 렌더링할 수 없다면 좋은 생각이 아니다<strong>.</strong>
해당 페이지에 자주 업데이트되는 데이터가 표시되는 경우 모든 요청에 따라 페이지콘텐츠가 변경될 수 있기 때문이다.</li>
</ul>
</li>
<li><em>이 경우 서버 측 렌더링*</em> 을 사용할 수 있다. 속도는 느려지지만 미리 렌더링된 페이지는 항상 최신 상태로 유지된다. 또는 사전 렌더링을 건너뛰고 클라이언트 측 JavaScript를 사용하여 자주 업데이트되는 데이터를 채울 수 있다.</li>
</ul>
<p>모든 요청에대해서 데이터를 항상 최신상태로 유지하고 싶다면 <strong>SSR</strong>
데이터의 변화가 많지 않고 사용자의 요청이 있기전에도 미리 렌더링을 할 수 있다면 <strong>SSG</strong>
을 사용하는 것이 좋다.</p>
<p>출처 : <a href="https://nextjs.org/learn/basics/data-fetching/two-forms">https://nextjs.org/learn/basics/data-fetching/two-forms</a>
<a href="https://nextjs.org/docs/basic-features/data-fetching/overview">Hybrid: SSG and SSR</a></p>
<h3 id="6-incremental-static-regeneration">6. Incremental Static Regeneration</h3>
<p>빌드 시간 후 정적으로 사전 렌더링된 페이지를 점진적으로 추가 및 업데이트합니다.</p>
<ul>
<li><strong>증분 정적 재생(ISR)을 통해 개발자와 콘텐츠 편집자 는 전체 사이트를 재구축할 필요 없이</strong> 페이지별로 정적 생성을 사용할 수 있다 . ISR을 사용하면 수백만 페이지로 확장하면서 정적의 이점을 유지할 수 있다.</li>
<li>증분 정적 재생성은 전자 상거래, 마케팅 페이지, 블로그 게시물, 광고 지원 미디어 등에 적합하다.</li>
</ul>
<p><a href="https://nextjs.org/docs/basic-features/data-fetching/incremental-static-regeneration">Incremental Static Regeneration</a>
<a href="https://vercel.com/docs/concepts/next.js/incremental-static-regeneration">https://vercel.com/docs/concepts/next.js/incremental-static-regeneration</a>
<a href="https://www.smashingmagazine.com/2021/04/incremental-static-regeneration-nextjs">https://www.smashingmagazine.com/2021/04/incremental-static-regeneration-nextjs</a></p>
<h3 id="7-typescript-support">7. TypeScript Support</h3>
<p>자동 TypeScript 구성 및 컴파일.</p>
<ul>
<li>Next.js는 구성이 필요 없는 설정과 Pages, API 등에 대한 기본 제공 유형을 포함 하여 통합된 TypeScript 환경을 제공한다.<pre><code class="language-jsx">  npx create-next-app@latest --ts
  # or
  yarn create next-app --typescript
  # or
  pnpm create next-app -- --ts</code></pre>
기존 프로젝트에서 시작하려면 루트 폴더에 빈 tsconfig.json 파일을 생성한다.</li>
</ul>
<p><a href="https://nextjs.org/docs/basic-features/typescript">TypeScript Support</a></p>
<h3 id="8-fase-refresh">8. Fase Refresh</h3>
<p>Facebook 규모에서 입증된 빠르고 안정적인 라이브 편집 경험.</p>
<ul>
<li>빠른 새로 고침은 React 구성 요소의 편집에 대한 즉각적인 피드백을 제공하는 Next.js 기능입니다.</li>
<li>빠른 새로 고침은 9.4 이상의 모든 Next.js 응용 프로그램에서 기본적으로 실행됩니다.</li>
<li>Next.js Fast Refresh를 사용하도록 설정한 경우 대부분의 편집은 구성 요소 상태를 잃지 않고 1초 내에 볼 수 있습니다.</li>
</ul>
<p><a href="https://nextjs.org/docs/basic-features/fast-refresh">Fase Refresh</a></p>
<h3 id="9-file-system-routing">9. File-system Routing</h3>
<p><code>pages</code>디렉터리 의 모든 구성 요소는 경로가 됩니다.</p>
<ul>
<li>Next.js는 페이지 개념을 기반으로 하는 파일 시스템 기반 라우터를 가지고 있어 파일이 <code>pages</code> 디렉토리에 추가되면 자동으로 경로로 사용할 수 있다.</li>
</ul>
<pre><code class="language-jsx">&#39;pages/index.js&#39; → &#39;/&#39;
&#39;pages/blog/index.js&#39; → &#39;/blog&#39;</code></pre>
<ul>
<li><code>pages</code> 디렉토리 내의 파일은 가장 일반적인 패턴을 정의하는 데 사용할 수 있다.<pre><code class="language-jsx">&#39;pages/blog/first-post.js&#39; → &#39;/blog/first-post&#39;
&#39;pages/dashboard/settings/username.js&#39; → &#39;/dashboard/settings/username&#39;</code></pre>
</li>
<li>동적으로 경로를 줄 수 있다.<pre><code class="language-jsx">&#39;pages/blog/[slug].js&#39; → &#39;/blog/:slug&#39; (/blog/hello-world)
&#39;pages/[username]/settings.js&#39; → &#39;/:username/settings&#39; (/foo/settings)
&#39;pages/post/[...all].js&#39; → &#39;/post/*&#39; (/post/2020/id/title)</code></pre>
</li>
</ul>
<p><a href="https://nextjs.org/docs/routing/introduction">File-system Routing</a></p>
<h3 id="10-api-routes">10. API Routes</h3>
<p>선택적으로 API 엔드포인트를 생성하여 백엔드 기능을 제공합니다.</p>
<ul>
<li><code>page</code>폴더 내의 모든 파일 <code>pages/api</code>은 <code>/api/*</code>에 매핑 된다. 서버 측 전용 번들이며 클라이언트 측 번들 크기를 늘리지 않는다.</li>
<li>예를 들어 다음 API 루트 <code>pages/api/user.js</code>는 상태 코드가 200인 json 응답을 반환한다.<pre><code class="language-jsx">export default function handler(req, res) {
res.status(200).json({ name: &#39;John Doe&#39; })
}</code></pre>
<a href="https://nextjs.org/docs/api-routes/introduction">API Routes</a><h3 id="11-built-in-css-support">11. Built-in CSS Support</h3>
CSS 모듈을 사용하여 구성 요소 수준 스타일을 만든다. 내장 Sass 지원.</li>
<li>Next.js를 사용하면 JavaScript 파일에서 CSS 파일을 가져올 수 있다. 이것은 Next.js가 <code>[import](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import)</code>JavaScript를 넘어 개념을 확장하기 때문에 가능하다.</li>
<li>전역 스타일 시트를 추가하려면<ul>
<li><code>pages/_app.js</code> 을 만들어서 styles.css 파일을 import 한다.</li>
</ul>
</li>
</ul>
<blockquote>
<p><a href="https://nextjs.org/docs/advanced-features/custom-app">_app 파일</a></p>
</blockquote>
<p><a href="https://nextjs.org/docs/basic-features/built-in-css-support">Built-in CSS Support</a></p>
<h3 id="12-code-splitting-and-bundling">12. Code-splitting and Bundling</h3>
<p>Google Chrome 팀에서 만든 최적화된 번들 분할 알고리즘입니다.</p>
<ul>
<li><p><strong>코드 분할이란?</strong>
<img src="https://velog.velcdn.com/cloudflare/dev_space/b661a572-eb3f-40dc-b728-a328a43190e5/Untitled%20(1).png" alt="">
출처 : <a href="https://crystallize.com/comics/no-code-splitting-vs-code-splitting">https://crystallize.com/comics/no-code-splitting-vs-code-splitting</a>
요청 시 또는 병렬로 로드할 수 있는 다양한 번들 또는 구성 요소로 코드를 분할하는 것이다.
애플리케이션이 복잡해지거나 유지 관리됨에 따라 CSS 및 JavaScript 파일 또는 번들은 바이트 크기가 커진다. 특히 포함된 타사 라이브러리의 수와 크기가 커짐에 따라 더욱 그렇게 되는데, 방대한 파일을 다운로드해야 하는 요구 사항을 방지하기 위해 스크립트를 여러 개의 작은 파일로 분할하여 페이지 로드 시 필요한 기능을 즉시 다운로드할 수 있으며 페이지 또는 애플리케이션이 대화형이 된 후 추가 스크립트가 지연 로드 되어 성능이 향상된다. 코드의 총량은 동일하지만(아마도 몇 바이트 더 클 수 있음) 초기 로드 중에 필요한 코드의 양은 줄일 수 있다.</p>
</li>
<li><p><strong>번들링이란?</strong>
개발자는 애플리케이션을 더 큰 부분의 애플리케이션을 구축하는 데 사용할 수 있는 모듈, 구성 요소 및 기능으로 나눈다. 이러한 내부 모듈과 외부 타사 패키지를 내보내고 가져오면 파일 종속성의 복잡한 웹이 생성되는데, 번들링은 사용자가 웹 페이지를 방문할 때 파일에 대한 요청 수를 줄이는 것을 목표로 <strong>웹 종속성을 해결하고 파일(또는 모듈)을 브라우저에 최적화된 번들로 병합(또는 &#39;패키징&#39;)하는 프로세스</strong> 다.</p>
</li>
</ul>
<p>Bundling 된 파일을 분할해서 로드하여 초기 구동 속도를 빠르게 하고 사용자들에게도 눈에 띄는 성능 향상을 제공한다고 생각하면 된다.
<a href="https://developer.mozilla.org/en-US/docs/Glossary/Code_splitting">Code-splitting and Bundling</a>
<a href="https://nextjs.org/learn/foundations/how-nextjs-works/bundling">https://nextjs.org/learn/foundations/how-nextjs-works/bundling</a></p>
<h1 id="장점을-짧게">장점을 짧게</h1>
<ul>
<li>이미지 최적화 (검색어 노출에 좋다)</li>
<li>직관적인 파일 기반 라우팅 시스템</li>
<li>사전 렌더링, 정적 생성(SSG) 및 서버 측 렌더링(SSR) 모두 페이지 단위로 지원된다.</li>
<li>간단하게 SSG, SSR 구현이 가능하다.</li>
<li>빠른 로딩 (Code-splitting and Bundling)<h1 id="정리">정리</h1>
Next.js는 React를 기반으로 한 프레임워크로 React의 단점을 보완하기 위해 나온 프레임워크라는 생각이 든다. 그리고 Next.js를 사용하는 주된 이유는 SSR 구현과 SEO 최적화를 위해 사용하는 것 같다. React로도 SSR 구현이나 SEO 최적화가 가능하다지만 Next.js를 사용함으로 개발의 비용을 줄여주고 편리성을 늘려주었다.
Next.js를 공부하면서 SSR, SSG, CSR 에 대해서 좀 더 명확하게 이해할 수 있었다.</li>
<li><a href="https://minoo.medium.com/next-js-%EC%B2%98%EB%9F%BC-server-side-rendering-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0-7608e82a0ab1">React로 Next.js 처럼 Server-Side-Rendering 구현하기</a></li>
<li><a href="https://byseop.netlify.app/csr-seo">SPA에서 서버사이드 렌더링을 구축하지 않고 SEO 최적화하기</a><h1 id="reference">Reference</h1>
<a href="https://nextjs.org">https://nextjs.org</a>
<a href="https://velog.io/@syoung125/Next.js-%EA%B8%B0%EB%B3%B8-%EA%B0%9C%EB%85%90-1-Next.js-%EB%9E%80-Next.js%EB%A5%BC-%EC%99%9C-%EC%82%AC%EC%9A%A9%ED%95%A0%EA%B9%8C-Next.js%EC%9D%98-%EC%9E%A5%EC%A0%90%EC%9D%80">https://velog.io/@syoung125/Next.js-%EA%B8%B0%EB%B3%B8-%EA%B0%9C%EB%85%90-1-Next.js-%EB%9E%80-Next.js%EB%A5%BC-%EC%99%9C-%EC%82%AC%EC%9A%A9%ED%95%A0%EA%B9%8C-Next.js%EC%9D%98-%EC%9E%A5%EC%A0%90%EC%9D%80</a>
<a href="https://serzhul.io/REACT/nextjs-%EC%86%8C%EA%B0%9C">https://serzhul.io/REACT/nextjs-%EC%86%8C%EA%B0%9C</a>
<a href="https://defineall.tistory.com/1037">https://defineall.tistory.com/1037</a>
<a href="https://medium.com/@msj9121/next-js-%EC%A0%9C%EB%8C%80%EB%A1%9C-%EC%95%8C%EA%B3%A0-%EC%93%B0%EC%9E%90-8727f76614c9">https://medium.com/@msj9121/next-js-%EC%A0%9C%EB%8C%80%EB%A1%9C-%EC%95%8C%EA%B3%A0-%EC%93%B0%EC%9E%90-8727f76614c9</a>
<a href="https://ivorycode.tistory.com/19">https://ivorycode.tistory.com/19</a>
<a href="https://hyemgu.tistory.com/237">https://hyemgu.tistory.com/237</a>
<a href="https://www.hanl.tech/blog/next-js">https://www.hanl.tech/blog/next-js</a>
<a href="https://thisiscoke.tistory.com/entry/Nextjs-%EA%B3%B5%EC%8B%9D%EB%AC%B8%EC%84%9C-%EC%82%B4%ED%8E%B4%EB%B3%B4%EA%B8%B01-%ED%95%98%EC%9D%B4%EB%B8%8C%EB%A6%AC%EB%93%9C-%EC%95%B1-SSR-SSG-CSR">https://thisiscoke.tistory.com/entry/Nextjs-%EA%B3%B5%EC%8B%9D%EB%AC%B8%EC%84%9C-%EC%82%B4%ED%8E%B4%EB%B3%B4%EA%B8%B01-%ED%95%98%EC%9D%B4%EB%B8%8C%EB%A6%AC%EB%93%9C-%EC%95%B1-SSR-SSG-CSR</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[정규 표현식(Regex)]]></title>
            <link>https://velog.io/@dev_space/%EC%A0%95%EA%B7%9C-%ED%91%9C%ED%98%84%EC%8B%9DRegex</link>
            <guid>https://velog.io/@dev_space/%EC%A0%95%EA%B7%9C-%ED%91%9C%ED%98%84%EC%8B%9DRegex</guid>
            <pubDate>Wed, 23 Feb 2022 13:50:21 GMT</pubDate>
            <description><![CDATA[<h1 id="정규-표현식이란">정규 표현식이란?</h1>
<ul>
<li>특정한 규칙을 가진 문자열의 집합을 표현하는 데 사용하는 형식.</li>
<li>줄여서 ‘정규식&#39; 이라고도 한다.<h1 id="정규-표현식-만들기">정규 표현식 만들기</h1>
정규식을 만드는 방법에는 두 가지가 있다.</li>
</ul>
<p>1.정규식 리터럴(슬래쉬로 감싸는 패턴)을 사용하는 방법.</p>
<ul>
<li><code>let re = /ab+c/</code></li>
</ul>
<p>2.RegExp 객체의 생성자 함수를 호출하는 방법.</p>
<ul>
<li><code>let re = new RegExp(&quot;ab+c&quot;);</code></li>
<li>flag
 a. <code>let re = new RegExp(&#39;ab+c&#39;, &#39;i&#39;);</code>
 b. <code>let re = new RegExp(&#39;/ab+c/&#39;, &#39;i&#39;);</code>
 c. <code>let re = new RegExp(&#39;/ab+c/i&#39;);</code> //ES6<h1 id="정규-표현식-구성">정규 표현식 구성</h1>
<h2 id="메타-문자metacharacter">메타 문자(Metacharacter)</h2>
정규표현식에서 사용하는 기호를 말한다.</li>
</ul>
<table>
<thead>
<tr>
<th>표현식</th>
<th>의미</th>
<th>예</th>
<th>의미</th>
</tr>
</thead>
<tbody><tr>
<td>^</td>
<td>문자열의 시작</td>
<td>^x</td>
<td>x 문자로 문자열이 시작</td>
</tr>
<tr>
<td>$</td>
<td>문자열의 종료</td>
<td>x$</td>
<td>x 문자로 문자열이 종료</td>
</tr>
<tr>
<td>.</td>
<td>임의의 한 문자 (문자의 종류를 가리지 않지만 \는 넣을 수 없음)</td>
<td>.x</td>
<td>임의의 한 문자가 x로 끝남</td>
</tr>
<tr>
<td>+</td>
<td>앞 문자가 하나 이상</td>
<td>x+</td>
<td>x 문자가 한 번 이상 반복됨</td>
</tr>
<tr>
<td>?</td>
<td>앞 문자의 존재 여부</td>
<td>x?</td>
<td>x 문자가 존재할 수도, 존재하지 않을 수도 있음</td>
</tr>
<tr>
<td>*</td>
<td>앞 문자의 반복 여부 (없을 수도 있음)</td>
<td>x*</td>
<td>x 문자가 0번 또는 그 이상 반복됨</td>
</tr>
<tr>
<td>|</td>
<td>or을 표현</td>
<td>x|y</td>
<td>x 또는 y 문자가 존재</td>
</tr>
<tr>
<td>()</td>
<td>그룹을 표현</td>
<td>(x)</td>
<td>x 를 그룹으로 처리함</td>
</tr>
<tr>
<td>()()</td>
<td>그룹들의 집합을 표현. 앞에서 부터 순서대로 번호를 부여하여 관리</td>
<td>(x)(y)</td>
<td>x, y 는 각 그룹의 데이터로 관리</td>
</tr>
<tr>
<td>()(?:)</td>
<td>그룹들의 집합에 대한 예외를 표현하며 그룹 집합으로 관리되지 않음을 의미</td>
<td>(x)(?:y)</td>
<td></td>
</tr>
<tr>
<td>{n}</td>
<td>앞의 문자가 n번 반복</td>
<td>x{n}</td>
<td></td>
</tr>
<tr>
<td>{n,}</td>
<td>앞의 문자가 n번 이상 반복</td>
<td>x{n,}</td>
<td></td>
</tr>
<tr>
<td>{n,m}</td>
<td>앞의 문자가 최소 n번 이상, 최대 m번 이하로 반복</td>
<td>x{n,m}</td>
<td></td>
</tr>
<tr>
<td>[]</td>
<td>내부에 지정된 문자열의 범위 중에서 한 문자만을 선택</td>
<td>[xy]</td>
<td>x 와 y 문자 중에 하나</td>
</tr>
<tr>
<td>[^]</td>
<td>not을 표현</td>
<td>[^xy]</td>
<td>x, y 를 제외한 문자</td>
</tr>
<tr>
<td>[-]</td>
<td>range를 표현</td>
<td>[a-z]</td>
<td>a ~ z 사이의 문자</td>
</tr>
<tr>
<td>\</td>
<td>escape를 표현. 뒤에 특수문자가 오면 특수문자가 아닌 문자 자체를 의미</td>
<td>^</td>
<td>^를 문자로 사용</td>
</tr>
<tr>
<td>\b</td>
<td>word boundary를 표현. 문자와 공백 사이의 문자를 의미</td>
<td>\bby\b</td>
<td>앞과 뒤가 공백인 by 문자열</td>
</tr>
<tr>
<td>\B</td>
<td>non word boundary를 표현. 문자와 공백 사이가 아닌 문자를 의미</td>
<td>\Bcl\B</td>
<td>앞과 뒤가 공백이 아닌 cl 문자열</td>
</tr>
<tr>
<td>\d</td>
<td>digit를 표현(숫자)</td>
<td></td>
<td></td>
</tr>
<tr>
<td>\D</td>
<td>non digit를 표현(숫자가 아닌 문자)</td>
<td></td>
<td></td>
</tr>
<tr>
<td>\s</td>
<td>space를 표현(공백)</td>
<td></td>
<td></td>
</tr>
<tr>
<td>\S</td>
<td>non space를 표현(공백 문자가 아닌 문자)</td>
<td></td>
<td></td>
</tr>
<tr>
<td>\t</td>
<td>tab을 표현(tab 문자)</td>
<td></td>
<td></td>
</tr>
<tr>
<td>\v</td>
<td>vertical tab을 표현(수직 탭)</td>
<td></td>
<td></td>
</tr>
<tr>
<td>\w</td>
<td>word를 표현 (알파벳 + 숫자 + _)</td>
<td></td>
<td></td>
</tr>
<tr>
<td>\W</td>
<td>non word를 표현 (알파벳 + 숫자 + _ 가 아닌 문자)</td>
<td></td>
<td></td>
</tr>
</tbody></table>
<h2 id="플래그flag">플래그(Flag)</h2>
<table>
<thead>
<tr>
<th>Flag</th>
<th>Meaning</th>
<th>Description</th>
</tr>
</thead>
<tbody><tr>
<td>i</td>
<td>Ignore Case</td>
<td>대소문자를 구별하지 않고 검색한다.</td>
</tr>
<tr>
<td>g</td>
<td>Global</td>
<td>문자열 내의 모든 패턴을 검색한다.</td>
</tr>
<tr>
<td>m</td>
<td>Multi Line</td>
<td>문자열의 행이 바뀌더라도 검색을 계속한다.</td>
</tr>
<tr>
<td>## 패턴(Pattern)</td>
<td></td>
<td></td>
</tr>
<tr>
<td>패턴에는 검색하고 싶은 문자열을 지정한다.</td>
<td></td>
<td></td>
</tr>
<tr>
<td>이때 문자열의 따옴표는 생략한다. (따옴표를 포함하면 따옴표까지 검색한다.)</td>
<td></td>
<td></td>
</tr>
<tr>
<td>또한 패턴은 특별한 의미를 가지는 메타 문자(Metacharacter) 또는 기호로 표현할 수 있다.</td>
<td></td>
<td></td>
</tr>
<tr>
<td>즉, 메타 문자와 추출하고 싶은 문자를 합친 것. 패턴의 양식에 따라 문자열에서 문자를 추출한다.</td>
<td></td>
<td></td>
</tr>
<tr>
<td>### 예)</td>
<td></td>
<td></td>
</tr>
<tr>
<td>```js</td>
<td></td>
<td></td>
</tr>
<tr>
<td>const str = &quot;abcd ab bc cd&quot;;</td>
<td></td>
<td></td>
</tr>
<tr>
<td>const regexr = /bc/g;</td>
<td></td>
<td></td>
</tr>
</tbody></table>
<p>console.log(str.match(regexr));
//output [ &#39;bc&#39;, &#39;bc&#39; ]</p>
<pre><code># JS에서 정규식 사용
## RegExp의 메소드
### exec
RegExp.prototype.exec()
대응되는 문자열을 찾는 RegExp 메소드이다.
정보를 가지고 있는 배열을 반환한다.
대응되는 문자열을 찾지 못했다면  NULL을 반환한다.

```js
const regex1 = RegExp(&#39;foo*&#39;, &#39;g&#39;);
const str1 = &#39;table football, foosball&#39;;
let array1;

while ((array1 = regex1.exec(str1)) !== null) {
  console.log(`Found ${array1[0]}. Next starts at ${regex1.lastIndex}.`);
  // expected output: &quot;Found foo. Next starts at 9.&quot;
  // expected output: &quot;Found foo. Next starts at 19.&quot;
}</code></pre><p>flag를 g로 설정하면 <code>regex1.lastIndex</code> 가 변경되며 이 값의 위치부터 검색을 한다. 이러한 특징으로 반복문을 통해 여러 일치하는 항목을 찾을 수 있다.
flag 설정을 안하면 <code>regex1.lastIndex</code> 가 0으로 고정되어 맨 앞의 일치하는 값을 계속 찾아 무한 반복한다.</p>
<h3 id="test">test</h3>
<p>RegExp.prototype.test()
대응되는 문자열이 있는지 검사하는 RegExp 메소드이다.
true 또는 false를 반환한다.</p>
<pre><code class="language-js">const str = &#39;table football&#39;;

const regex = new RegExp(&#39;foo*&#39;);
const globalRegex = new RegExp(&#39;foo*&#39;, &#39;g&#39;);

console.log(regex.test(str));
// expected output: true

console.log(globalRegex.lastIndex);
// expected output: 0

console.log(globalRegex.test(str));
// expected output: true

console.log(globalRegex.lastIndex);
// expected output: 9

console.log(globalRegex.test(str));
// expected output: false</code></pre>
<p>flag를 g로 설정하면 <code>lastIndex</code> 가 변경되며 이 값의 위치부터 문자열을 확인한다.
flag 설정을 안하면 <code>lastIndex</code> 가 0으로 고정된다.</p>
<h2 id="string의-메소드">String의 메소드</h2>
<h3 id="match">match</h3>
<p>String.prototype.match()
대응되는 문자열을 찾는 String 메소드이다.
정보를 가지고 있는 배열을 반환한다.
대응되는 문자열을 찾지 못했다면 NULL을 반환한다.</p>
<pre><code class="language-js">const paragraph = &#39;The quick brown fox jumps over the lazy dog. It barked.&#39;;
const regex = /[A-Z]./g;
const found = paragraph.match(regex);

console.log(found);
// expected output: Array [ &#39;Th&#39;, &#39;It&#39; ]</code></pre>
<h3 id="replace">replace</h3>
<p>String.prototype.replace()
대응되는 문자열을 찾아 다른 문자열로 치환하는 String 메소드이다.</p>
<pre><code class="language-js">const str = &quot;this is a dog&quot;;

console.log(str.replace(&quot;dog&quot;, &quot;monkey&quot;));
// expected output: &quot;this is a monkey&quot;

const regex = /Dog/i;
console.log(str.replace(regex, &quot;ferret&quot;));
// expected output: &quot;this is a ferret&quot;</code></pre>
<p>매개변수</p>
<pre><code class="language-js">replace(regexp, newSubstr)
replace(regexp, replacerFunction)

replace(substr, newSubstr)
replace(substr, replacerFunction)</code></pre>
<p>자세히 : <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace">MDN Web Docs</a></p>
<h3 id="search">search</h3>
<p>String.prototype.search()
대응되는 문자열이 있는지 검사하는 String 메소드 이다.
대응된 부분의 인덱스를 반환한다.
대응되는 문자열을 찾지 못했다면 -1을 반환한다.</p>
<pre><code class="language-js">const paragraph = &quot;abc. 123, 1a2b3c?&quot;;

// any character that is not a word character or whitespace
const regex = /[^\w\s]/g;

console.log(paragraph.search(regex));
// expected output: 3

console.log(regex.lastIndex);
// expected output: 0

console.log(paragraph[paragraph.search(regex)]);
// expected output: &quot;.&quot;</code></pre>
<p>g flag 를 사용해도 exec, test 처럼 lastIndex 값이 변경되지 않는다.</p>
<h3 id="split">split</h3>
<p>String.prototype.split()
정규식 혹은 문자열로 대상 문자열을 나누어 배열로 반환하는 String 메소드이다.</p>
<pre><code class="language-js">const names = &quot;Harry Trump ;Fred Barney; Helen Rigby ; Bill Abel ; Chris Hand &quot;;
const pattern = /\s*;\s*/;

const nameList = names.split(pattern);

console.log(nameList);
/* expected output:
[
  &#39;Harry Trump&#39;,
  &#39;Fred Barney&#39;,
  &#39;Helen Rigby&#39;,
  &#39;Bill Abel&#39;,
  &#39;Chris Hand &#39;
]
*/</code></pre>
<p>names 문자열에서 <code>/\s*;\s*/</code> 에 해당하는 문자열은 <code>&#39; &#39;;</code> 로 ‘공백’ + ‘;’ 이다.
해당 문자열을 기준으로 나눠서 배열로 반환한 값이 nameList에 들어간다.</p>
<h1 id="regexr-test-site">Regexr test site</h1>
<ul>
<li><a href="https://regexr.com/">RegExr: Learn, Build, &amp; Test RegEx</a></li>
<li><a href="https://regexper.com/">Regexper</a></li>
<li><a href="https://www.regextester.com/">https://www.regextester.com/</a></li>
</ul>
<h1 id="reference">Reference</h1>
<p><a href="https://poiemaweb.com/js-regexp">https://poiemaweb.com/js-regexp</a>
<a href="https://ko.wikipedia.org/wiki/%EC%A0%95%EA%B7%9C_%ED%91%9C%ED%98%84%EC%8B%9D#:~:text=%EC%A0%95%EA%B7%9C%20%ED%91%9C%ED%98%84%EC%8B%9D">https://ko.wikipedia.org/wiki/%EC%A0%95%EA%B7%9C_%ED%91%9C%ED%98%84%EC%8B%9D#:~:text=%EC%A0%95%EA%B7%9C%20%ED%91%9C%ED%98%84%EC%8B%9D</a>
<a href="https://hamait.tistory.com/342">https://hamait.tistory.com/342</a>
<a href="https://developer.mozilla.org/ko/docs/Web/JavaScript/Guide/Regular_Expressions">https://developer.mozilla.org/ko/docs/Web/JavaScript/Guide/Regular_Expressions</a>
<a href="https://www.nextree.co.kr/p4327">https://www.nextree.co.kr/p4327</a>
<a href="https://tristan91.tistory.com/463">https://tristan91.tistory.com/463</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[MVVM 패턴]]></title>
            <link>https://velog.io/@dev_space/MVVM-%ED%8C%A8%ED%84%B4</link>
            <guid>https://velog.io/@dev_space/MVVM-%ED%8C%A8%ED%84%B4</guid>
            <pubDate>Sun, 09 Jan 2022 11:23:26 GMT</pubDate>
            <description><![CDATA[<h1 id="mvvm-패턴이란">MVVM 패턴이란?</h1>
<ul>
<li>MVVM은 마틴 파울러의 &#39;프레젠테이션 모델 디자인 패턴&#39;의 변형이다.</li>
<li>비즈니스 로직 또는 백엔드 로직(모델)로 부터 분리시켜서 뷰가 어느 특정한 모델 플랫폼에 종속되지 않도록 해준다.</li>
<li>비즈니스 로직, 백엔드 로직을 UI로부터 분리하게 되면, 테스트, 유지 보수, 재사용이 쉬워진다.</li>
<li>Model + View + View Model을 합친 용어이다.
<img src="https://images.velog.io/images/dev_space/post/a6632ba4-c97a-498b-a443-b447b5f7a081/image.png" alt="">
<img src="https://images.velog.io/images/dev_space/post/634d6cc6-0eb5-4cb1-8ccd-6f3ec068f1cd/image.png" alt="">
출처: <a href="https://ko.wikipedia.org/wiki/%EB%AA%A8%EB%8D%B8-%EB%B7%B0-%EB%B7%B0%EB%AA%A8%EB%8D%B8">위키백과</a>,<a href="https://avulatulasiram.wordpress.com/2018/11/24/android-mvvm-design-pattern">https://avulatulasiram.wordpress.com/2018/11/24/android-mvvm-design-pattern</a><blockquote>
<p><strong>비즈니스 로직</strong>
비즈니스 로직(Business logic)은 컴퓨터 프로그램에서 실세계의 규칙에 따라 데이터를 생성·표시·저장·변경하는 부분을 일컫는다. 이 용어는 특히 데이터베이스, 표시장치 등 프로그램의 다른 부분과 대조되는 개념으로 쓰인다.<a href="https://ko.wikipedia.org/wiki/%EB%B9%84%EC%A6%88%EB%8B%88%EC%8A%A4_%EB%A1%9C%EC%A7%81">위키백과</a></p>
</blockquote>
</li>
</ul>
<h2 id="model">Model</h2>
<p>Model은 데이터를 포함하는 앱의 도메인 모델로 생각할 수 있다. 쉽게 말해서 모델은 앱에서 사용할 데이터에 관련된 행위와 데이터를 다룬다.
<strong>Model은 View, ViewModel 계층을 전혀 신경쓰지 않아도 된다.</strong> 데이터를 어떻게 가지고 있을지만 생각하면 되고, 그 이상의 비즈니스 로직이나 어떻게 보여주는지에 굳이 맞출 필요는 없다.</p>
<h2 id="view">View</h2>
<p>View는 앱의 UI에 대한 코드를 담고 있다. 각 컴포넌트에 대한 정보를 담고, 어느 위치에 어떻게 배치될지 작성되어있다. 디자인적인 요소도 있지만, ViewModel로부터 데이터를 가져와 어떻게 배치할지, 특정 상황에 따라 ViewModel의 어떤 메서드를 이용할지에 대해서도 가지고 있다.
<strong>재사용성이 강조</strong>되며 Model을 직접 소유하지 않아야 한다. ViewModel로부터 받아와서 View에 정보를 집어넣어주는 방식이 일반적이다.</p>
<h2 id="view-model">View Model</h2>
<p>MVVM의 뷰 모델은 값 변환기인데, 이는 뷰 모델이 모델에 있는 데이터 객체를 노출(반환)하는 책임을 지기 때문에 객체를 관리하고 표현하기가 쉬워진다는 것을 의미한다. 이와 같은 이유로 뷰 모델은 뷰 보다는 모델에 가깝다.
<strong>모든 뷰들의 디스플레이 로직을 제외한 대부분의 것들을 처리하며</strong> 앱의 핵심적인 비즈니스 로직을 담고있고 MVC패턴의 Controller와 비슷한 역할을 한다.
<strong>ViewModel은 기본적으로 View에 종속되지 않는다.</strong></p>
<h2 id="특징">특징</h2>
<ul>
<li>ViewModel과 View는 1:N 관계를 가진다.</li>
<li>MVVM에서는 커맨드 패턴과 데이터바인딩을 사용한다.<ul>
<li>커맨드 패턴: View에 입력이 들어오면 커맨드 패턴으로 ViewModel에 명령.</li>
<li>데이터 바인딩: ViewModel의 값이 변하면 자동으로 UI가 업데이트됨.<h3 id="동작원리">동작원리</h3>
<ol>
<li>사용자의 Action이 뷰를 통해 들어옴</li>
<li>뷰에서 Action이 들어오면, Command 패턴으로 뷰모델에 Action을 전달</li>
<li>뷰모델은 모델에게 데이터를 전달</li>
<li>모델은 뷰모델에게 요청 받은 데이터를 응답</li>
<li>뷰모델은 응답 받은 데이터를 가공하여 저장</li>
<li>뷰는 뷰모델과 데이터바인딩하여 화면을 나타냄<blockquote>
<p><strong>Command 패턴</strong></p>
<ul>
<li>요청을 객체의 형태로 캡슐화하여(실행될 기능을 캡슐화함으로써) 사용자가 보낸 요청을 나중에 이용할 수 있도록 매서드 이름, 매개변수 등 요청에 필요한 정보를 저장 또는 로깅, 취소할 수 있게 하는 패턴이다.</li>
<li>커맨드 패턴에는 명령(command), 수신자(receiver), 발동자(invoker), 클라이언트(client)의 네개의 용어가 항상 따른다. <a href="https://k0102575.github.io/articles/2020-02/command-pattern">출처</a></li>
</ul>
</blockquote>
</li>
</ol>
</li>
</ul>
</li>
</ul>
<h2 id="장점">장점</h2>
<ul>
<li>Model과 View 사이의 의존성이 없다.</li>
<li>View와 ViewModel 사이에 의존성이 없다.</li>
<li>독립성을 유지하기에 <ul>
<li>효율적인 유닛 테스트를 할 수 있다.</li>
<li>모듈화 하여 개발할 수 있다.<h2 id="단점">단점</h2>
</li>
</ul>
</li>
<li>뷰에 대한 처리가 복잡해질수록 뷰모델이 거대해져 오버스펙이 될 수 있다.</li>
<li>단순한 UI 작업에서는 MVVM을 구현하는것이 오히려 지나치게 과한것일 수 있다.</li>
<li>앱이 너무 거대해지면 앱의 메모리 소모가 데이터 바인딩때문에 커진다.</li>
<li>ViewModel의 설계가 쉽지 않다.<h2 id="정리">정리</h2>
MVVM 패턴은 Model, View, ViewModel로 구성되어 있습니다.
Model은 앱에서 사용할 데이터에 관련된 행위와 데이터를 다루고, View는 ViewModel로부터 데이터를 가져와 어떻게 배치할지, 특정 상황에 따라 ViewModel의 어떤 메서드를 이용할지에 대해서 다룹니다.
ViewModel은 모든 뷰들의 디스플레이 로직을 제외한 대부분의 것들을 처리하는 앱의 핵심적인 비즈니스 로직을 담고 있습니다.
장점은 Model과 View, View와 ViewModel 사이의 의존성이 없기에 독립성으로 인한 유닛 테스트 및 모듈화 개발을 할 수 있고 유지보수 비용이 적습니다.
단점은 MVVM패턴이 개발 속도 향상이 목적이 아닌 유지보수의 비용 감소에 있어 설계에 어려움이 있고, 단순한 UI 작업에서는 오히려 하는 일에 비해 많은 코드를 작성해야 한다는 단점이 있습니다.</li>
</ul>
<h4 id="공부할-것">공부할 것</h4>
<p>패턴들을 공부하다보니 비즈니스 로직과 Command 패턴에 대해 나오는데 나중에 자세히 살펴보고 넘어가야겠다.</p>
<blockquote>
<p><strong>참고하자</strong>
비즈니스 로직: <a href="https://mommoo.tistory.com/67">https://mommoo.tistory.com/67</a>
Command 패턴: <a href="https://k0102575.github.io/articles/2020-02/command-pattern">https://k0102575.github.io/articles/2020-02/command-pattern</a></p>
</blockquote>
<h3 id="reference">Reference</h3>
<p><a href="https://ko.wikipedia.org/wiki/%EB%AA%A8%EB%8D%B8-%EB%B7%B0-%EB%B7%B0%EB%AA%A8%EB%8D%B8">https://ko.wikipedia.org/wiki/%EB%AA%A8%EB%8D%B8-%EB%B7%B0-%EB%B7%B0%EB%AA%A8%EB%8D%B8</a>
<a href="https://velog.io/@k7120792/Model-View-ViewModel-Pattern">https://velog.io/@k7120792/Model-View-ViewModel-Pattern</a>
<a href="https://medium.com/hcleedev/ios-swiftui%EC%9D%98-mvvm-%ED%8C%A8%ED%84%B4%EA%B3%BC-mvc%EC%99%80%EC%9D%98-%EB%B9%84%EA%B5%90-8662c96353cc">https://medium.com/hcleedev/ios-swiftui%EC%9D%98-mvvm-%ED%8C%A8%ED%84%B4%EA%B3%BC-mvc%EC%99%80%EC%9D%98-%EB%B9%84%EA%B5%90-8662c96353cc</a>
<a href="https://blog.crazzero.com/m/152">https://blog.crazzero.com/m/152</a>
<a href="https://appboong.tistory.com/15">https://appboong.tistory.com/15</a>
<a href="https://scshim.tistory.com/407">https://scshim.tistory.com/407</a>
<a href="https://k0102575.github.io/articles/2020-02/command-pattern">https://k0102575.github.io/articles/2020-02/command-pattern</a>
<a href="https://kaki104.tistory.com/531">https://kaki104.tistory.com/531</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Typescript and React .env]]></title>
            <link>https://velog.io/@dev_space/Typescript-and-React-.env</link>
            <guid>https://velog.io/@dev_space/Typescript-and-React-.env</guid>
            <pubDate>Mon, 27 Dec 2021 09:38:11 GMT</pubDate>
            <description><![CDATA[<p>react &amp; typescript 에서 .env 환경변수 파일을 사용하려 하는데 왜 .env 내용이 자동완성이 안될까 싶어서 찾게되었다.</p>
<pre><code class="language-typescript">//.env.development
REACT_APP_TEST=hello</code></pre>
<pre><code class="language-typescript">//src/App.tsx
function App() {
      console.log(process.env.REACT_APP_TEST);
    return null;
}

export default App;</code></pre>
<p>.env.development 파일을 수정후 react를 재실행하고 process.env.REACT_APP_TEST 를 하면 값이 제대로 나오긴 하는데 자동완성은 안된다.
모듈을 사용해야되는건가 싶어서 이것저것 해보다가 <strong>react-app-env.d.ts</strong> 파일을 사용하여 나타내는 방법을 알게되었다.</p>
<h2 id="dts">d.ts</h2>
<p>우선 d.ts 파일은 선언 파일로 typescript 코드의 타입 추론을 돕는 파일이다.
예를 들면 전역 변수로 선언한 변수를 특정 파일에서 import 구문 없이 사용하는 경우 해당 변수를 인식하지 못한다. 그럴 때 아래와 같이 해당 변수를 선언해서 에러가 나지 않게 할 수 있다.</p>
<pre><code class="language-typescript">declare const global = &#39;sth&#39;;</code></pre>
<p>해당 타입 스크립트 파일에서 사용할 순 있지만 선언되어 있지 않은 전역 변수나 전역 함수는 아래와 같이 타입을 선언할 수 있다.</p>
<pre><code class="language-typescript">// 전역 변수
declare const pi = 3.14;

// 전역 함수
declare namespace myLib {
  function greet(person: string): string;
  let name: string;
}
myLib.greet(&#39;캡틴&#39;);
myLib.name = &#39;타노스&#39;;</code></pre>
<p><a href="https://joshua1988.github.io/ts/usage/declaration.html">출처</a></p>
<p>위와 같은 특성으로 d.ts 파일을 사용하여 전역 변수의 타입을 선언할 수 있다.</p>
<h2 id="react-app-envdts">react-app-env.d.ts</h2>
<blockquote>
<p>CRA?
create-react-app 을 줄여서 CRA라고 많이 부른다.
리액트를 개발한 페이스북에서 만든 리액트 프로젝트용 보일러플레이트라고 생각하면 되는데, 지속적인 패키지들의 버전업과 리액트의 버전업이 활발히 일어나다 보니 자신만의 보일러플레이트를 가지고 있다고 해도 결국 패키지들의 업데이트에 맞춰 지속적인 관리도 해주게 되고 새로운 기술 또는 아키텍처가 생기면 구조변경을 해야하는 경우도 생기기 마련이라 금방 레거시 프로젝트가 된다. 하지만 CRA를 쓰면 리액트의 지속적인 업데이트를 페이스북에서 주관을 하고있고, 그에 맞춰 페이스북에서 이러한 CRA 보일러플레이트를 업데이트를 시켜줍니다. <a href="https://fe-churi.tistory.com/33">(출처)</a>
(CRA가 없다면 우리는 바벨, eslint, 웹팩등을 직접 하나하나 설치하고 해당 파일을 일일히 설정 해주어야 할 것이다<a href="https://hokeydokey.tistory.com/47">(출처)</a>)</p>
</blockquote>
<blockquote>
<p>보일러플레이트
보일러플레이트 또는 보일러플레이트 코드라고 부르는 것은 최소한의 변경으로 여러곳에서 재사용되며, 반복적으로 비슷한 형태를 띄는 코드를 말한다.</p>
</blockquote>
<p>CRA를 사용하여 React app을 생성하면 src 폴더에 react-app-env.d.ts 파일이 생성되는것을 볼 수 있다. 뭔지 몰라서 그냥 지나치곤 했는데 해당 파일을 살펴보면 아래와 같이 작성되어있는것을 볼 수 있다.</p>
<pre><code class="language-typescript">//.src/react-app-env.d.ts
/// &lt;reference types=&quot;react-scripts&quot; /&gt;</code></pre>
<p>위의 코드를 힌트로 해당 경로에 가면 아래의 파일이 있는데</p>
<pre><code class="language-typescript">//.node-modules/react-scripts/lib/react-app.d.ts
/// &lt;reference types=&quot;node&quot; /&gt;
/// &lt;reference types=&quot;react&quot; /&gt;
/// &lt;reference types=&quot;react-dom&quot; /&gt;

declare namespace NodeJS {
  interface ProcessEnv {
    readonly NODE_ENV: &#39;development&#39; | &#39;production&#39; | &#39;test&#39;;
    readonly PUBLIC_URL: string;
  }
}

declare module &#39;*.avif&#39; {
  const src: string;
  export default src;
}

declare module &#39;*.bmp&#39; {
  const src: string;
  export default src;
}

declare module &#39;*.gif&#39; {
  const src: string;
  export default src;
}

declare module &#39;*.jpg&#39; {
  const src: string;
  export default src;
}

declare module &#39;*.jpeg&#39; {
  const src: string;
  export default src;
}

declare module &#39;*.png&#39; {
  const src: string;
  export default src;
}

declare module &#39;*.webp&#39; {
    const src: string;
    export default src;
}

declare module &#39;*.svg&#39; {
  import * as React from &#39;react&#39;;

  export const ReactComponent: React.FunctionComponent&lt;React.SVGProps&lt;
    SVGSVGElement
  &gt; &amp; { title?: string }&gt;;

  const src: string;
  export default src;
}

declare module &#39;*.module.css&#39; {
  const classes: { readonly [key: string]: string };
  export default classes;
}

declare module &#39;*.module.scss&#39; {
  const classes: { readonly [key: string]: string };
  export default classes;
}

declare module &#39;*.module.sass&#39; {
  const classes: { readonly [key: string]: string };
  export default classes;
}</code></pre>
<p>여러 파일 확장자들에 대한 타입이 선언되어 있는것을 볼 수 있고 이를 react-app-env.d.ts에서 참조하는 것으로 유추할 수 있다.
이때 상단의 코드를 살펴보면</p>
<pre><code class="language-typescript">declare namespace NodeJS {
  interface ProcessEnv {
    readonly NODE_ENV: &#39;development&#39; | &#39;production&#39; | &#39;test&#39;;
    readonly PUBLIC_URL: string;
  }
}</code></pre>
<p>process.env. 을 적었을때 자동완성되는 환경변수들을 볼 수 있다.
CRA의 typescript 지원은 NodeJS 네임스페이스 아래의 확장된 정의를 사용하는 것이라 한다.
이것을 우리의 환경에 맞게 확장해주면 된다.</p>
<h2 id="사용하기">사용하기</h2>
<pre><code class="language-typescript">//.src/react-app-env.d.ts
/// &lt;reference types=&quot;react-scripts&quot; /&gt;

declare namespace NodeJS {
    interface ProcessEnv {
              NODE_ENV: &#39;development&#39; | &#39;production&#39; | &#39;test&#39;;
              PUBLIC_URL: string;
              REACT_APP_TEST: string;
    }
}</code></pre>
<p>위와 같이 저장한뒤에 <code>process.env.</code>을 작성하면 REACT_APP_TEST를 자동완성하여 사용할 수 있다.</p>
<h2 id="reference">Reference</h2>
<p><a href="https://dev.to/louisgv/typescript-and-create-react-app-env-136e">https://dev.to/louisgv/typescript-and-create-react-app-env-136e</a>
<a href="https://velog.io/@swanious/TIL-.d.ts%ED%8C%8C%EC%9D%BC%EC%97%90%EC%84%9C-reference-typesreact-scripts%EC%9D%B4-%EB%AD%98%EA%B9%8C">https://velog.io/@swanious/TIL-.d.ts%ED%8C%8C%EC%9D%BC%EC%97%90%EC%84%9C-reference-typesreact-scripts%EC%9D%B4-%EB%AD%98%EA%B9%8C</a>
<a href="https://code-anthropoid.tistory.com/275">https://code-anthropoid.tistory.com/275</a>
<a href="https://joshua1988.github.io/ts/usage/declaration.html#%ED%83%80%EC%9E%85%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EC%84%A0%EC%96%B8-%ED%8C%8C%EC%9D%BC">https://joshua1988.github.io/ts/usage/declaration.html#%ED%83%80%EC%9E%85%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EC%84%A0%EC%96%B8-%ED%8C%8C%EC%9D%BC</a>
<a href="https://fe-churi.tistory.com/33">https://fe-churi.tistory.com/33</a>
<a href="https://jaewook.me/create-react-app-typescript-window-object">https://jaewook.me/create-react-app-typescript-window-object</a>
<a href="https://charlezz.medium.com/%EB%B3%B4%EC%9D%BC%EB%9F%AC%ED%94%8C%EB%A0%88%EC%9D%B4%ED%8A%B8-%EC%BD%94%EB%93%9C%EB%9E%80-boilerplate-code-83009a8d3297">https://charlezz.medium.com/%EB%B3%B4%EC%9D%BC%EB%9F%AC%ED%94%8C%EB%A0%88%EC%9D%B4%ED%8A%B8-%EC%BD%94%EB%93%9C%EB%9E%80-boilerplate-code-83009a8d3297</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[React Recoil]]></title>
            <link>https://velog.io/@dev_space/React-Recoil</link>
            <guid>https://velog.io/@dev_space/React-Recoil</guid>
            <pubDate>Thu, 16 Dec 2021 08:01:07 GMT</pubDate>
            <description><![CDATA[<h1 id="recoil-이란">Recoil 이란?</h1>
<p>Recoil은 React용 상태 관리 라이브러리이다.
Recoil은 Atom이라는 것을 사용하여 각 구성 요소의 상태를 관리하며, useState와 똑같은 API를 사용하기 때문에 생성하고 사용하기에 매우 쉽다.
<img src="https://images.velog.io/images/dev_space/post/d886f021-4fec-49b1-9fd7-8ed8f07da50e/image.png" alt="">
<img src="https://images.velog.io/images/dev_space/post/d29978e7-8913-47b1-a3d3-1ef8721fbe15/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-16%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.51.38.png" alt="">
<a href="https://recoiljs.org">recoil 영상 속 이미지</a>
개인적으로 제일 이해하기 편했던 그림들인데 리액트는 아래와 같이 몇 가지 제한 사항이 있다.</p>
<blockquote>
<ul>
<li>구성 요소의 상태는 공통 조상으로 푸시해야만 공유할 수 있고 여기에는 다시 렌더링 해야하는 거대한 나무가 포함될 수 있습니다.</li>
</ul>
</blockquote>
<ul>
<li>컨텍스트는 각각 고유한 소비자가 있는 무한한 값 집합이 아니라 단일 값만 저장할 수 있습니다.</li>
<li>이 두 가지 모두 트리의 잎(상태가 사용되는 위치)에서 트리의 상단(상태가 있어야 하는 위치)을 코드 분할하기 어렵게 만듭니다.
<a href="https://recoiljs.org/docs/introduction/motivation">출처</a></li>
</ul>
<p>앱에서 어떤 하나의 상태 변경이 다른 여러 컴포넌트에 영향을 줄 수 있는 상황이라면 그 상태 변경 사항이 다른 컴포넌트에서도 필요하게 되는데 위의 제한사항이 불편함으로 다가온다.
그래서 상태관리 라이브러리를 사용하는데 여러 상태관리 라이브러리가 있지만 Recoil은 API와 의미 체계 및 동작 방식을 가능한 한 React스럽게(Reactish) 가져가면서 현상을 해결하려고 제작했다고 한다.</p>
<h1 id="핵심-개념">핵심 개념</h1>
<h2 id="시작하기">시작하기</h2>
<ol>
<li><code>npm i recoil</code>
recoil을 우선 설치해준다.</li>
<li>RecoilRoot
recoil을 사용하려면 RecoilRoot가 상위 트리 어딘가에 나타나야된다.</li>
</ol>
<p>예)</p>
<pre><code class="language-typescript">//index.ts
import React from &#39;react&#39;;
import ReactDOM from &#39;react-dom&#39;;
import App from &#39;./App&#39;;
import { RecoilRoot } from &quot;recoil&quot;;

ReactDOM.render(
  &lt;React.StrictMode&gt;
    &lt;RecoilRoot&gt; //***
      &lt;App /&gt;
    &lt;/RecoilRoot&gt;
  &lt;/React.StrictMode&gt;,
  document.getElementById(&#39;root&#39;)
);</code></pre>
<h2 id="atoms">Atoms</h2>
<ul>
<li>atom은 상태의 단위이다.</li>
<li>컴포넌트가 구독할 수 있는 React state라고 생각하면 된다.</li>
<li>atom이 업데이트 되면 해당 atom을 구독하고 있는 컴포넌트들이 모두 다시 렌더링 된다.</li>
<li>여러 컴포넌트에서 같은 atom을 구독하고 있으면 그 컴포넌트들이 상태를 동일하게 공유한다.</li>
<li>atom을 생성하기 위해서는 고유한 키 값과 디폴트 값을 설정해야한다.<h3 id="예제">예제</h3>
<pre><code class="language-javascript">//atoms.ts
import {atom} from &quot;recoil&quot;;
</code></pre>
</li>
</ul>
<p>export const counterAtom = atom({
    key: &quot;counter&quot;,
    default : 0
})</p>
<pre><code>atom 기능으로 생성한다. (key는 unique해야함)
default 값은 number, string, object, array, function 등 다양하게 가능하다.
```javascript
//ComponentIncrement.js
import { counterAtom } from &quot;./atoms&quot;;
import { useRecoilState } from &quot;recoil&quot;;

export default function ComponentIncrement() {
    const [counter, setCounter] = useRecoilState(counterAtom);
    const onIncrementClick = () =&gt; setCounter(counter + 1);
    return (
        &lt;div&gt;
            &lt;p&gt;Component&lt;/p&gt;
            &lt;p&gt;{counter}&lt;/p&gt;
            &lt;input onClick={onIncrementClick} type=&quot;submit&quot; value=&quot;Increment&quot; /&gt;
        &lt;/div&gt;
    )
}</code></pre><p><strong>useRecoilState</strong>은 useState와 비슷하다고 볼 수 있다.
counter로 counterAtom의 값을 볼 수 있고 setCounter로 counterAtom의 값을 변경할 수 있다.</p>
<p>input을 클릭할 때 마다 onIncrementClick 함수가 실행되어 상태값을 +1 씩 하여 변경한다.</p>
<pre><code class="language-javascript">//ComponentValue.js
import { useRecoilValue } from &quot;recoil&quot;;
import { counterAtom } from &quot;./atoms&quot;;

export default function ComponentValue() {
    const counter = useRecoilValue(counterAtom);
    return (
        &lt;div&gt;
            &lt;p&gt;Component Value Only&lt;/p&gt;
            &lt;p&gt;{counter}&lt;/p&gt;
        &lt;/div&gt;
    )
}</code></pre>
<p><strong>useRecoilValue</strong>는 상태값을 불러온다.</p>
<pre><code class="language-javascript">//App.js
import ComponentIncrement from &quot;./ComponentIncrement&quot;;
import ComponentValue from &quot;./ComponentValue&quot;;

export default function App() {
  return (
    &lt;div&gt;
      &lt;ComponentIncrement /&gt;
      &lt;ComponentValue /&gt;
    &lt;/div&gt;
  );
}</code></pre>
<p><img src="https://images.velog.io/images/dev_space/post/7c1236a2-2e31-45e4-85ff-a58030748560/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-16%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%205.33.35.png" alt="">
ComponentIncrement, ComponentValue 각각 나눠진 컴포넌트지만 ComponentIncrement의 input 버튼에 따라 counterAtom 값을 공유하는것을 볼 수 있다.</p>
<blockquote>
<ul>
<li>useRecoilValue(): atom의 내용을 읽을 수 있다.</li>
</ul>
</blockquote>
<ul>
<li>useSetRecoilState(): atom의 내용을 변경할 수 있다.</li>
<li>useRecoilState(): useRecoilValue &amp; useSetRecoilState 같이 사용 가능하다.</li>
</ul>
<h2 id="selectors">selectors</h2>
<p>selectors는 상태를 기반으로 하는 파생 데이터를 계산하는데 사용된다. 이것은 최소한의 상태 집합이 atom에 저장되고 다른 모든 것은 해당 최소 상태의 함수로 효율적으로 계산되기 때문에 중복 상태를 피할 수 있다.
어떤 구성 요소가 필요하고 어떤 상태에 의존하는지 추적하기 때문에 이 기능적 접근 방식을 매우 효율적으로 만든다.</p>
<ul>
<li>key는 필수이며 unique해야한다.</li>
<li>get은 필수로 넘겨줘야하고 set은 optional이다.<h3 id="예제-todo-list">예제 ToDo List</h3>
<pre><code class="language-typescript">//atoms.ts
import { atom, selector } from &quot;recoil&quot;;
</code></pre>
</li>
</ul>
<p>export enum Categories {
    &quot;TO_DO&quot; = &quot;TO_DO&quot;,
    &quot;DOING&quot; = &quot;DOING&quot;,
    &quot;DONE&quot; = &quot;DONE&quot;,
}</p>
<p>export interface IToDo {
    text: string;
    id: number;
    category: Categories;
}</p>
<p>export const categoryState = atom<Categories>({
    key: &quot;category&quot;,
    default: Categories.TO_DO,
});</p>
<p>export const toDoState = atom&lt;IToDo[]&gt;({
    key: &quot;toDo&quot;,
    default: [],
});</p>
<p>export const toDoSelector = selector({
    key: &quot;toDoSelector&quot;,
    get: ({ get }) =&gt; {
        const toDos = get(toDoState);
        const category = get(categoryState);
        return toDos.filter((toDo) =&gt; toDo.category === category);
    },
});</p>
<pre><code>toDoSelector에서 toDos와 cateforyState를 불러와서 현재 카테고리에 해당하는 toDo 값만 return 한다.
```typescript
//CreateToDo.tsx
import { useForm } from &quot;react-hook-form&quot;;
import { useRecoilValue, useSetRecoilState } from &quot;recoil&quot;;
import { categoryState, toDoState } from &quot;./atoms&quot;;

interface IForm {
    toDo: string;
}

export default function CreateToDo() {
    const setToDos = useSetRecoilState(toDoState);
    const category = useRecoilValue(categoryState);
    const { register, handleSubmit, setValue } = useForm&lt;IForm&gt;();
    const handleValid = ({ toDo }: IForm) =&gt; {
        setToDos((oldToDos) =&gt; [
            { text: toDo, id: Date.now(), category },
            ...oldToDos,
        ]);
        setValue(&quot;toDo&quot;, &quot;&quot;);
    };
    return (
        &lt;form onSubmit={handleSubmit(handleValid)}&gt;
            &lt;input
                {...register(&quot;toDo&quot;, {
                    required: &quot;Please write a To Do&quot;,
                })}
                placeholder=&quot;Write a to do&quot;
            /&gt;
            &lt;button&gt;Add&lt;/button&gt;
        &lt;/form&gt;
    );
}</code></pre><p>ToDo 항목을 생성하는 컴포넌트로 form의 submit시에 handleValid에서 setToDos를 실행하여 toDo를 현재 카테고리 위치에 추가한다.</p>
<pre><code class="language-typescript">//ToDoList.tsx
import React from &quot;react&quot;;
import { useRecoilState, useRecoilValue } from &quot;recoil&quot;;
import { Categories, categoryState, toDoSelector } from &quot;../atoms&quot;;
import CreateToDo from &quot;./CreateToDo&quot;;
import ToDo from &quot;./ToDo&quot;;

export default function ToDoList() {
    const toDos = useRecoilValue(toDoSelector);
    const [category, setCategory] = useRecoilState(categoryState);
    const onInput = (event: React.FormEvent&lt;HTMLSelectElement&gt;) =&gt; {
        setCategory(event.currentTarget.value as Categories);
    };
    return (
        &lt;div&gt;
            &lt;h1&gt;To Dos&lt;/h1&gt;
            &lt;hr /&gt;
            &lt;select value={category} onInput={onInput}&gt;
                &lt;option value={Categories.TO_DO}&gt;To Do&lt;/option&gt;
                &lt;option value={Categories.DOING}&gt;Doing&lt;/option&gt;
                &lt;option value={Categories.DONE}&gt;Done&lt;/option&gt;
            &lt;/select&gt;
            &lt;CreateToDo /&gt;
            {toDos?.map((toDo) =&gt; (
                &lt;ToDo key={toDo.id} {...toDo} /&gt;
            ))}
        &lt;/div&gt;
    );
}</code></pre>
<p>ToDo list를 표여주는 컴포넌트이다.
useRecoilValue에 selector 함수를 넣어서 해당하는 조건의 toDos를 받는다.
category로 현재 categoryState의 상태를 확인하고 select의 option을 선택할때마다 setCategory()를 실행하여 categoryState의 상태를 바꿔준다.</p>
<p>그리고 toDos 안의 내용물을 순차적으로 ToDo 컴포넌트로 보내준다.</p>
<pre><code class="language-typescript">//ToDo.tsx
import React from &quot;react&quot;;
import { useSetRecoilState } from &quot;recoil&quot;;
import { Categories, IToDo, toDoState } from &quot;./atoms&quot;;

export default function ToDo({ text, category, id }: IToDo) {
    const setToDos = useSetRecoilState(toDoState);
    const onClick = (event: React.MouseEvent&lt;HTMLButtonElement&gt;) =&gt; {
        const {
            currentTarget: { name },
        } = event;
        setToDos((oldToDos) =&gt; {
            const targetIndex = oldToDos.findIndex((toDo) =&gt; toDo.id === id);
            const newToDo = { text, id, category: name as IToDo[&quot;category&quot;] };
            return [
                ...oldToDos.slice(0, targetIndex),
                newToDo,
                ...oldToDos.slice(targetIndex + 1),
            ];
        });
    };
    return (
        &lt;li&gt;
            &lt;span&gt;{text}&lt;/span&gt;
            {category !== Categories.DOING &amp;&amp; (
                &lt;button name={Categories.DOING} onClick={onClick}&gt;
                    Doing
                &lt;/button&gt;
            )}
            {category !== Categories.TO_DO &amp;&amp; (
                &lt;button name={Categories.TO_DO} onClick={onClick}&gt;
                    To Do
                &lt;/button&gt;
            )}
            {category !== Categories.DONE &amp;&amp; (
                &lt;button name={Categories.DONE} onClick={onClick}&gt;
                    Done
                &lt;/button&gt;
            )}
        &lt;/li&gt;
    );
}</code></pre>
<p>각 ToDo 를 표시하는 컴포넌트로 카테고리를 변경할 수 있다.
해당 카테고리 버튼을 클릭하면 onClick안의 setToDos를 실행하여 ToDo의 카테고리를 수정한다.
setToDos를 위와같이 안에 함수를 넣어 사용하면 oldToDos안에는 현재 ToDo 전체를 불러온다.
targetIndex는 findIndex로 현재 ToDo의 위치를 찾는다.
newToDo는 현재 ToDo 값을 카테고리만 변경하여 그대로 생성한다.</p>
<pre><code>[...oldToDos.slice(0, targetIndex),
    newToDo,
...oldToDos.slice(targetIndex + 1),]</code></pre><p>현재 ToDo를 잘라버리고 카테고리를 변경한 새로운 ToDo를 넣어 반환하는 코드이다.</p>
<p><code>category !== Categories.DOING &amp;&amp;</code> 는 참일경우 &amp;&amp;뒤의 코드를 사용한다.</p>
<pre><code class="language-typescript">//App.tsx
import ToDoList from &quot;./ToDoList&quot;;

export default function App() {
  return (
    &lt;ToDoList /&gt;
  );
}</code></pre>
<blockquote>
<p><strong>Dynamic Dependencies</strong>
읽기 전용 선택기에는 get종속성을 기반으로 선택기의 값을 평가 하는 메서드가 있습니다. 이러한 종속성이 업데이트되면 선택기가 다시 평가됩니다. 종속성은 선택기를 평가할 때 실제로 사용하는 원자 또는 선택기를 기반으로 동적으로 결정됩니다. 이전 종속성의 값에 따라 다른 추가 종속성을 동적으로 사용할 수 있습니다. Recoil은 현재 데이터 흐름 그래프를 자동으로 업데이트하여 선택자가 현재 종속성 집합의 업데이트에만 가입하도록 합니다.
<a href="https://recoiljs.org/docs/api-reference/core/selector/#dynamic-dependencies">출처</a></p>
</blockquote>
<h3 id="예제-set">예제 (set)</h3>
<p>위의 예제는 selector의 get만 사용하였는데 set도 사용이 가능하다.
Atoms의 예제를 약간만 바꿔봤다.</p>
<pre><code class="language-typescript">//atoms.js
import {atom, selector} from &quot;recoil&quot;;

export const counterAtom = atom({
    key: &quot;counter&quot;,
    default : 0
})

export const countChange = selector({
    key: &quot;selector&quot;,
    get: ({get}) =&gt; get(counterAtom) % 2 === 0,
    set: ({set}, newValue) =&gt; set(counterAtom, newValue as number)
});</code></pre>
<pre><code class="language-typescript">//ComponentValue.tsx
import { useRecoilState, useRecoilValue } from &quot;recoil&quot;;
import { counterAtom, countChange } from &quot;./atoms&quot;;

export default function ComponentValue() {
    const counter = useRecoilValue(counterAtom);
    const [value, setCounter] = useRecoilState(countChange);
    const onZero = () =&gt; setCounter(123);
    return (
        &lt;div&gt;
            &lt;p&gt;Component Value Only&lt;/p&gt;
            &lt;p&gt;{counter}&lt;/p&gt;
            &lt;input onClick={onZero} type=&quot;submit&quot; value=&quot;zero&quot; /&gt;
            &lt;p&gt;{value ? &quot;짝수&quot; : &quot;홀수&quot;}&lt;/p&gt;
        &lt;/div&gt;
    )
}</code></pre>
<p><img src="https://images.velog.io/images/dev_space/post/a466639b-4150-4a01-b745-8dd74987ebae/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-16%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%207.41.28.png" alt="">
<code>const [value, setCounter] = useRecoilState(countChange)</code>
일반적인 상태를 확인하고 수정하는것과 생긴것은 동일하다.
위의 예제의 경우 counterAtom의 상태를 직접 변경하는 것과 countChange로 상태를 변경하는 것에 차이는 없지만 set이 어떻게 작동하는지만 확인해보자.
countChange의 get에 해당하는 value를 불러올때 counterAtom의 값이 짝수면 true, 홀수면 false를 가져온다.
set은 첫번째 인자로 객체, 두번째 인자로 새로운 값이 넘어오고, 첫번째 인자 객체의 set을 사용하여 state값을 바꾼다. 이때 첫번째 인자는 recoil state여야하고 두번째 인자는 바뀔 값에 해당한다.</p>
<blockquote>
<p><strong>Writeable Selectors</strong>
양방향 선택기는 들어오는 값을 매개변수로 수신하고 이를 사용하여 데이터 흐름 그래프를 따라 업스트림으로 변경 사항을 전파할 수 있습니다. 사용자는 선택기를 새 값으로 설정하거나 선택기를 재설정할 수 있기 때문에 들어오는 값은 선택기가 나타내는 것과 동일한 유형이거나 DefaultValue재설정 작업을 나타내는 개체입니다.
이 간단한 선택기는 기본적으로 추가 필드를 추가하기 위해 원자를 래핑합니다. 설정 및 재설정 작업을 통해 업스트림 원자로 전달됩니다.<a href="https://recoiljs.org/docs/api-reference/core/selector/#writeable-selectors">출처</a></p>
</blockquote>
<blockquote>
<p>get함수 만 제공되는 경우 선택기는 읽기 전용이며 RecoilValueReadOnly개체를 반환 합니다. set또한 제공되는 경우 쓰기 가능한 RecoilState개체를 반환 합니다.<a href="https://recoiljs.org/docs/api-reference/core/selector/#writeable-selectors">출처</a></p>
</blockquote>
<h3 id="reference">Reference</h3>
<p><a href="https://nomadcoders.co/react-masterclass">https://nomadcoders.co/react-masterclass</a>
<a href="https://recoiljs.org/docs/introduction/getting-started">https://recoiljs.org/docs/introduction/getting-started</a>
<a href="https://levelup.gitconnected.com/a-new-state-management-for-react-recoil-53ad7480faa4">https://levelup.gitconnected.com/a-new-state-management-for-react-recoil-53ad7480faa4</a>
<a href="https://medium.com/humanscape-tech/recoil-%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0-285b29135d8e">https://medium.com/humanscape-tech/recoil-%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0-285b29135d8e</a>
<a href="https://ui.toast.com/weekly-pick/ko_20200616">https://ui.toast.com/weekly-pick/ko_20200616</a> 
<a href="https://kkangil.github.io/2020/05/24/React-recoiljs-%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0">https://kkangil.github.io/2020/05/24/React-recoiljs-%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[api data에 interface 적용 Tip]]></title>
            <link>https://velog.io/@dev_space/api-data%EC%97%90-interface-%EC%A0%81%EC%9A%A9-Tip</link>
            <guid>https://velog.io/@dev_space/api-data%EC%97%90-interface-%EC%A0%81%EC%9A%A9-Tip</guid>
            <pubDate>Sun, 12 Dec 2021 09:22:01 GMT</pubDate>
            <description><![CDATA[<h3 id="react--typescript">React &amp; TypeScript</h3>
<p><strong>API 데이터를 불러와 사용하기전 interface를 이용해 타입을 적용할때 팁.</strong>
api에서 데이터를 불러올때 다양한 key, value가 존재하는데 이걸 일일이 interface에 써주기에는 너무 번거롭다.
<strong>예)</strong></p>
<pre><code class="language-typescript">const [info, setInfo] = useState&lt;InfoData&gt;();
const [priceInfo, setPriceInfo] = useState&lt;PriceData&gt;();
useEffect(() =&gt; {
  (async () =&gt; {
    const infoData = await (
      await fetch(`https://api.coinpaprika.com/v1/coins/${coinId}`)
    ).json();
    const priceData = await (
      await fetch(`https://api.coinpaprika.com/v1/tickers/${coinId}`)
    ).json();
    console.log(infoData); //****
    console.log(priceData); //****
    setInfo(infoData);
    setPriceInfo(priceData);
  })();
}, []);</code></pre>
<ol>
<li>api를 통해 불러온 데이터 infoData, priceData가 존재하는데 이걸 우선 console.log()로 찍어준다.</li>
<li>아래와 같이 콘솔에 Object가 찍히면
<img src="https://images.velog.io/images/dev_space/post/cba82d74-8868-4ca1-8faa-de60ca39fb17/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-12%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%205.36.41.png" alt="">
두 개의 Object를 각각 우측 마우스를 클릭하여 &#39;Store object as global variable&#39; 를 선택해준다.
그러면 그림과 같이 temp1, temp2 가 생성된다.</li>
<li>Object.keys().join()을 사용한다.
<img src="https://images.velog.io/images/dev_space/post/f5cf4d35-2f92-4e76-bf5b-1d5e602e5958/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-12%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%205.43.26.png" alt="">
생성된 temp를 위와같이 사용하면 key값만 나온다.</li>
<li>출력된 key값들을 복사해서 vscode의 만들고자 하는 interface 안에 넣는다.
<img src="https://images.velog.io/images/dev_space/post/ace22012-45e8-4cad-8a79-1085dbf04343/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-12%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%205.46.19.png" alt="">
그리고 쉼표를 드래그 한 다음에 <code>command + D</code> 를 이용해 모두 선택해주고 <code>Enter</code>를 눌러준다.</li>
<li>그 상태 그대로 <code>command + ➡️</code> 를 사용해 우측 끝으로 이동 후 <code>: ;</code> 를 작성해준다.
<img src="https://images.velog.io/images/dev_space/post/32afbef7-7d10-45dc-a797-d7ef72c45cb7/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-12%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%205.51.25.png" alt="">
아니면 모두 드래그를 한 다음에 <code>option + shift + I</code> 를 클릭해서 우측끝으로 이동한다.</li>
<li>Object.values().map((v)=&gt;typeof v).join()
<img src="https://images.velog.io/images/dev_space/post/1086e6f9-17d2-42b5-b7ea-c613f6e6bee9/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-12%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%205.56.33.png" alt="">
key 값을 얻었을때처럼 그냥 values().join() 해버리면 value 값이 나온다. 하지만 내가 알고싶은것은 Type 이기에 map을 이용해서 typeof 로 출력해준다.</li>
<li>출력된 값을 복사해서 <code>command + D</code> 를 이용해 일렬로 세워준 다음에 전체 잘라낸다.
자르기 <code>command + X</code>
<img src="https://images.velog.io/images/dev_space/post/2b1e7e3e-adae-4e07-8a22-4ca21a32d3ad/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-12%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%205.58.52.png" alt=""></li>
<li>먼저 작성된 key 값들을 전체 드래그 후 <code>option + shift + I</code> 을 통해 우측으로 이동해서 붙여넣기를 해준다.
<img src="https://images.velog.io/images/dev_space/post/750f8856-dbd5-499c-9ab3-1d619227a2af/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-12%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%206.00.43.png" alt=""></li>
<li>정리. 
콘솔에서 값들을 살펴보면 Array인데 Type에는 Object 라고 되어있는 것들이 있다. 이것들을 사용해야 되는 데이터일 경우에 비슷한 방법 또는 직접 타입을 입력하는 등 수정해준다.(사용 안할거면 지워도 된다.)
interface 를 따로 만들어 적용해도된다.</li>
</ol>
<p><strong>예)</strong></p>
<pre><code class="language-typescript">  interface ITag {
      name: string;
      symbol: string;
      rank: number;
  }

  interface InfoData {
      message: ITag[];
  }</code></pre>
<p>Object 들도 key: type을 입력해서 정리해준다.
<strong>예)</strong></p>
<pre><code class="language-typescript">  interface InfoData {
      message: ITag[];
      quotes: {
          USD: {
              ath_date: string;
              ath_price: number;
              market_cap: number;
          }
      }
  }</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[TypeScript]]></title>
            <link>https://velog.io/@dev_space/TypeScript</link>
            <guid>https://velog.io/@dev_space/TypeScript</guid>
            <pubDate>Sat, 11 Dec 2021 16:09:53 GMT</pubDate>
            <description><![CDATA[<h1 id="typescript란">TypeScript란?</h1>
<ul>
<li>JavaScript를 기반으로 한 프로그래밍 언어이다.</li>
<li>JavaScript와는 다른 프로그래밍 언어라 할 수 있다.(완전 다른건 아니다. TypeScript는 JavaScript를 기반으로 하기 때문이다.)</li>
<li>JavaScript와 거의 같은데 새로운 기능을 살짝 추가한거라 볼수있다.</li>
<li>strongly-typed 언어이다.</li>
<li>브라우저는 TypeScript 언어를 못알아 듣는다. 그래서 확인후 이상이 없으면 JavaScript로 반환해준다.<h3 id="strongly-typed">strongly-typed</h3>
프로그래밍 언어가 작동하기 전에 type을 확인하는 것이다.<pre><code class="language-javascript">const plus = (a, b) =&gt; a + b;</code></pre>
를 예로 들면 a와 b가 어떤 타입으로 들어갈지 JavaScript는 정해져있지 않다.
하지만 strongly-typed 언어인 TypeScript는 프로그램이 작동하기전에 데이터의 타입을 확인해줘서 좀 더 안전하게 작업을 할 수 있다.</li>
</ul>
<p>위의 코드를 TypeScript로 바꾸면</p>
<pre><code class="language-typescript">const plus = (a:number, b:number) =&gt; a + b;</code></pre>
<p>a와 b는 number 타입을 가져야 되다는 말이다.
이렇듯 마이웨이인 JavaScript와 다르게 TypeScript는 작은 실수로부터 우리를 보호해준다.</p>
<h1 id="typescript로-react-시작하기">TypeScript로 React 시작하기</h1>
<ol>
<li><strong>TypeScript 설치</strong>
처음 시작에 두 가지 방법이 있다.
<code>npx create-react-app my-app --template typescript</code>
or
<code>yarn create react-app my-app --template typescript</code>
위의 방법은 처음 리액트 앱을 만들때 <code>--template typescrip</code> 를 추가해서 생성하는 것이다.
<code>npm install --save typescript @types/node @types/react @types/react-dom @types/jest</code>
or
<code>yarn add typescript @types/node @types/react @types/react-dom @types/jest</code>
두 번째 방법은 기존 앱에 필요한 모듈들을 설치해 주는 것이다.</li>
<li>아래의 방법으로 TypeScript 모듈을 설치했다면
확장자를 변경해줘야된다.
React, TypeScript 에서는 확장자 .js 를 사용하지 않고 .tsx 를 사용한다.
(TypeScript는 .ts)</li>
<li>모듈 설치
일반적인 js모듈을 설치해서 사용하면 typescript는 사용하지 못한다.
예를 들어
<code>npm i styled-components</code> 
로 모듈을 설치하고 TypeScript 에서 사용하려하면 사용이 안되는데 이유는 styled-components 가 javascript 로 되어있기 때문인데, 이걸 되게 하려면
<code>npm i --save @types/styled-components</code>
를 사용해 설치해주면 된다.</li>
</ol>
<blockquote>
<p>@types 란?
매우 큰 Github repository로 유명한 npm 라이브러리를 사람들이 모여서 TypeScipt에서 사용 가능하게 type definition을 만들어놓은 저장소이다.
<a href="https://github.com/DefinitelyTyped/DefinitelyTyped">https://github.com/DefinitelyTyped/DefinitelyTyped</a></p>
</blockquote>
<blockquote>
<p>만약 TypeScript 선언이 없는 모듈을 import 한다면?
<code>npm i --save-dev $types/[모듈 이름]</code> 을 입력해서 확인을 하자.
Github repository 에서 검색하는건 추천하지 않는다. 대부분에 파일이 숨겨져 있기때문.</p>
</blockquote>
<h2 id="interface">interface</h2>
<p>Object 형식으로 타입을 정의해서 사용할 수 있다.</p>
<pre><code class="language-typescript">interface PlayerShape {
    name: string;
      age: number;
};
const sayHello = (playerObj: PlayerShape) =&gt; 
    `Hello ${playerObj.name} you are ${playerObj.age} years old.`;
sayHello({name: &quot;gjeon&quot;, age:12});
sayHello({name: &quot;hi&quot;, age:30});</code></pre>
<p>propTypes 와 매우 유사하지만 interface는 TypeScript와 코드가 실행되기 전에 확인해 준다는 차이점이 있다.</p>
<h2 id="optional-props">Optional Props</h2>
<p>위의 interface를 보면 무조건 정의된 인자가 들어와야하고 기본값이 정해져 있지 않다. </p>
<pre><code class="language-typescript">import styled from &quot;styled-components&quot;;

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

const Container = styled.div&lt;ContainerProps&gt;`
  width: 200px;
  height: 200px;
  background-color: ${(props) =&gt; props.bgColor};
  border-radius: 100px;
  border: 1px solid ${(props) =&gt; props.borderColor};
`;

interface CircleProps {
    bgColor: string;
    borderColor?: string;
    text?: string;
}

function Circle({ bgColor, borderColor, text = &quot;default text&quot; }: CircleProps) {
    return (
        &lt;Container bgColor={bgColor} borderColor={borderColor ?? bgColor}&gt;
        {text}
        &lt;/Container&gt;
    );
}

export default Circle;</code></pre>
<p><code>borderColor?: string</code> 을 보면 : 옆에 ? 가 들어가 있다. 의미는 borderColor 라는 인자가 들어올 수도 있고 안들어올수도 있다는 말이다.</p>
<p>interface 를 두 번 사용했는데 아래 interface에서는 <code>borderColor?:</code> 로 값이 안들어와도 되지만 styled-components의 Container 는 <code>borderColor:</code>를 필수로 필요로 하기에 에러가 발생한다. 이러한 경우 ??를 사용할수도 있다.
<code>&lt;Container bgColor={bgColor} borderColor={borderColor ?? bgColor}&gt;</code>
<code>borderColor ?? bgColor</code> ??은 borderColor의 값이 undefined 일 경우 bgColor 값으로 적용돼서 <code>borderColor=bgColor</code>가 되어 props로 넘겨준다.</p>
<p><code>{ bgColor, borderColor, text = &quot;default text&quot; }</code>
text가 비어있을 경우 &quot;default text&quot;가 값으로 적용되어 들어가는 것으로 javascrip이다.</p>
<h2 id="state">State</h2>
<p>TypeScript로 useState()를 사용하면 default값을 통해 타입을 정의해준다.</p>
<pre><code class="language-typescript">const [counter, setCounter] = useState(1);</code></pre>
<p>default 값으로 1이 들어가서 counter는 number라고 정의된다. 그리고 setCounter도 number를 사용하는 액션이라는 것을 알 수 있다.
이처럼 초기값으로 유추하여 타입을 정의한다.</p>
<p>하지만 다른 타입으로 바뀌는걸 원한다면 아래와 같이 작성한다.</p>
<pre><code class="language-typescript">const [counter, setCounter] = useState&lt;number|string&gt;(1);</code></pre>
<p>counter는 number 또는 string 이라는 의미이다.</p>
<h2 id="forms">Forms</h2>
<pre><code class="language-typescript">import React, { useState } from &quot;react&quot;;

function App() {
  const [value, setValue] = useState(&quot;&quot;);
  const onChange = (event: React.FormEvent&lt;HTMLInputElement&gt;) =&gt; {
    const {
      currentTarget: { value },
    } = event;
    setValue(value);
  };
  const onSubmit = (event: React.FormEvent&lt;HTMLFormElement&gt;) =&gt; {
    event.preventDefault();
    console.log(&quot;hello&quot;, value);
  };
  return (
    &lt;div&gt;
      &lt;form onSubmit={onSubmit}&gt;
        &lt;input
          value={value}
          onChange={onChange}
          type=&quot;text&quot;
          placeholder=&quot;username&quot;
        /&gt;
        &lt;button&gt;Log in&lt;/button&gt;
      &lt;/form&gt;
    &lt;/div&gt;
  );
}
export default App;</code></pre>
<p><code>event: React.FormEvent&lt;HTMLFormElement&gt;</code>와 같이 생소한 부분이 나온다.
event의 타입도 정의해줘야 되는데 이때 &#39;any&#39; 타입이 올수도 있다. &#39;any&#39; 타입은 어떤 타입이든 올 수 있다는 말인데, 가능한한 any 타입은 배제하고 이제 무슨 타입인지를 쓰거나 설명하고자 노력해야 한다고 한다.
이때 event에 타입을 추가하는 방식이
<code>React.FormEvent&lt;HTMLFormElement&gt;</code>이다.
상황에 따라 어떤 종류의 Element에 따라 이벤트가 실행될지를 나타낸 것이다.
event 타입을 정의해주는 것을 제외한 나머지는 JavaScript + React 와 같다.</p>
<blockquote>
<p>ReactJs 내의 TypeScript로 작업을 할때 어디에 타입이 있는지 어떤 타입을 넣어야 되는지 구글링을 많이 해야된다.<a href="https://reactjs.org/docs/events.html">React 이벤트 가이드</a></p>
</blockquote>
<h2 id="themes">Themes</h2>
<p>themes 를 사용할 때 타입을 정의하는것을 해보자.
styled-components theme과 typescript를 연결하는 지시를 따라한다.
<strong>Create a declarations file</strong>
<a href="https://styled-components.com/docs/api#create-a-declarations-file">https://styled-components.com/docs/api#create-a-declarations-file</a>
선언 파일을 만들어준다. (.d.ts로 끝남)</p>
<pre><code class="language-typescript">//styled.d.ts
import &quot;styled-components&quot;;

declare module &quot;styled-components&quot; {
  export interface DefaultTheme {
    textColor: string;
    bgColor: string;
    btnColor: string;
  }
}</code></pre>
<p>이렇게 생성한 파일은 우리가 이전에 @types/styled-components를 통해 설치한 index.d.ts 파일을 확장한다.</p>
<pre><code class="language-typescript">//theme.ts
import { DefaultTheme } from &quot;styled-components&quot;;

export const lightTheme: DefaultTheme = {
  bgColor: &quot;white&quot;,
  textColor: &quot;black&quot;,
  btnColor: &quot;tomato&quot;,
};

export const darkTheme: DefaultTheme = {
  bgColor: &quot;black&quot;,
  textColor: &quot;white&quot;,
  btnColor: &quot;teal&quot;,
};</code></pre>
<p>병합된 DefaultTheme를 import해서 불러온뒤 타입으로 정의해서 사용한다.</p>
<pre><code class="language-typescript">//index.tsx
import React from &quot;react&quot;;
import ReactDOM from &quot;react-dom&quot;;
import { ThemeProvider } from &quot;styled-components&quot;;
import App from &quot;./App&quot;;
import { darkTheme, lightTheme } from &quot;./theme&quot;;

ReactDOM.render(
  &lt;React.StrictMode&gt;
    &lt;ThemeProvider theme={darkTheme}&gt;
      &lt;App /&gt;
    &lt;/ThemeProvider&gt;
  &lt;/React.StrictMode&gt;,
  document.getElementById(&quot;root&quot;)
);</code></pre>
<p>나머지는 javascript에서 theme을 사용하는 것과 같다.</p>
<blockquote>
<p>declaration merging(병합 선언)
<a href="https://www.typescriptlang.org/docs/handbook/declaration-merging.html">https://www.typescriptlang.org/docs/handbook/declaration-merging.html</a></p>
</blockquote>
<h2 id="reference">Reference</h2>
<p><a href="https://nomadcoders.co/react-masterclass">https://nomadcoders.co/react-masterclass</a>
<a href="https://create-react-app.dev/docs/adding-typescript/">https://create-react-app.dev/docs/adding-typescript/</a>
<a href="https://dev.to/rajuashok/create-styled-d-ts-to-make-typescript-work-with-styled-components-5dk4">https://dev.to/rajuashok/create-styled-d-ts-to-make-typescript-work-with-styled-components-5dk4</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[styled-components]]></title>
            <link>https://velog.io/@dev_space/styled-components</link>
            <guid>https://velog.io/@dev_space/styled-components</guid>
            <pubDate>Sat, 11 Dec 2021 10:50:47 GMT</pubDate>
            <description><![CDATA[<h1 id="styled-components-란">styled-components 란?</h1>
<ul>
<li>javascript에서 css를 사용할 수 있도록 도와주는 CSS-in-JS 스타일링 프레임워크다.</li>
<li>styled-components는 React 컴포넌트 시스템의 스타일링을 위해 CSS를 어떻게 향상시킬 수 있는지 궁금해한 결과이다.</li>
<li>React와 React Native 모두에서 사용할 수 있다.<h2 id="react-컴포넌트-스타일링">React 컴포넌트 스타일링</h2>
React 컴포넌트의 스타일을 지정하는 방법에는 여러 가지가 있다.<h3 id="외부-css파일에서-css를-사용">외부 CSS파일에서 CSS를 사용</h3>
전통적인 방법이다.<pre><code class="language-css">//Movie.module.css
.movie__title {
  background-color: red;
  color: white;
}</code></pre>
<pre><code class="language-javascript">//Movie.js
import styles from &quot;./Movie.module.css&quot;;
</code></pre>
</li>
</ul>
<p>function Movie({title}) {
    return (
        <div className={styles.movie__title}>
              <h1>{title}</h1>
          </div>
    )
}</p>
<pre><code>애플리케이션이 비대해지면 css파일이 점점 커지고 복잡해지기 시작한다. 이에 대한 솔루션으로 SASS가 도입되고 도움도 되지만 추상화 조차도 그 자체로 복잡해지기 시작한다.
&gt;sass는 mixin을 통해 공통 패턴을 의미적이고 재사용 가능한 덩어리로 추상화 가능하다.

### React 구성 요소 내부에 CSS를 사용
```javascript
//Movie.js
function Movie({title}) {
    return (
        &lt;div style={{backgroundColor: &quot;red&quot;, color: &quot;white&quot;}}&gt;
              &lt;h1&gt;{title}&lt;/h1&gt;
          &lt;/div&gt;
    )
}</code></pre><p>이 방법은 지속 가능하지도 확장이 가능하지도 않기 때문에 권장하지 않는다.</p>
<h3 id="css-in-js">CSS-in-JS</h3>
<p>javascript를 사용하여 구성 요소의 스타일을 지정하는 기술이다.
이 javascript가 구문 분석되면 CSS가 스타일 요소로 생성되어 DOM 위에 직접 첨부된다.
styled-components, Emotion, JSS, Radium, Aphrodite 등의 프레임워크가 많이 있다.
그중 styled-components가 가장 인기가 많다.</p>
<h1 id="styled-components-시작하기">styled-components 시작하기</h1>
<ol>
<li>설치 <code>npm i styled-components</code></li>
<li>styled-components를 import 해준다.<pre><code class="language-javascript">import styled from &quot;styled-components&quot;;</code></pre>
<h2 id="예제">예제</h2>
<a href="https://nomadcoders.co/react-masterclass">노마드코더</a> 강의의 예제를 정리<h3 id="1">1.</h3>
<pre><code class="language-javascript">import styled from &quot;styled-components&quot;;
</code></pre>
</li>
</ol>
<p>const Father = styled.div<code>display: flex;</code>;
const BoxOne = styled.div<code>background-color: teal;
  width: 100px;
  height: 100px;</code>;
const BoxTwo = styled.div<code>background-color: tomato;
  width: 100px;
  height: 100px;</code>;</p>
<p>function App() {
  return (
    <Father>
      <BoxOne />
      <BoxTwo />
    </Father>
  );
}
export default App;</p>
<pre><code>![](https://images.velog.io/images/dev_space/post/2b243e95-88b6-4fbb-a0d8-b442b9d8dbf8/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-11%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%204.57.40.png)
변수를 생성하면서 import 해준 styled. 뒤에 HTML요소를 적고 백틱을 입력해서 적용하고 싶은 스타일을 입력해주면 된다.
그리고 해당 스타일이 적용된 요소를 넣고 싶은 부분에 생성한 변수명을 넣어준다.
&lt;Father&gt;
  &lt;BoxOne /&gt;
  &lt;BoxTwo /&gt;
&lt;/Father&gt;
### 2.
위의 예제를 보면 스타일이 중복된 값이 있음을 볼 수 있다.
그걸 더 깔끔하게 적용해보자.
```javascript
import styled from &quot;styled-components&quot;;

const Father = styled.div`
    display: flex;
`;
const Box = styled.div`
  background-color: ${(props) =&gt; props.bgColor};
  width: 100px;
  height: 100px;
`;

function App() {
  return (
    &lt;Father&gt;
      &lt;Box bgColor=&quot;teal&quot; /&gt; {/*bgColor는 props로 보낸다.*/}
      &lt;Box bgColor=&quot;tomato&quot; /&gt;
    &lt;/Father&gt;
  );
}
export default App;</code></pre><p><img src="https://images.velog.io/images/dev_space/post/0d5db8a5-12e9-43f0-ba6a-65a321dc903c/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-11%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%205.04.40.png" alt="">
위의 예제보다 짧은 코드로 같은 화면이 완성된다.
<code>&lt;Box bgColor=&quot;teal&quot; /&gt;</code> 에서 bgColor 는 정해진 값이 아니다.
<code>background-color: ${(props) =&gt; props.bgColor};</code> props. 뒤에 오는 문자와 동일하면 된다.</p>
<h3 id="3">3.</h3>
<p>다른 스타일을 간편하게 가져다 확장해서 스타일을 적용해 사용할 수 있다.</p>
<pre><code class="language-javascript">import styled from &quot;styled-components&quot;;

const Father = styled.div`
    display: flex;
`;
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;Father&gt;
      &lt;Box bgColor=&quot;teal&quot; /&gt; {/*bgColor는 props로 보낸다.*/}
      &lt;Circle bgColor=&quot;tomato&quot; /&gt;
    &lt;/Father&gt;
  );
}
export default App;</code></pre>
<p><code>const Circle = styled(Box)</code> styled. 뒤에 요소를 안넣고 괄호 안에 생성한 요소 스타일을 넣어 확장해서 사용할 수 있다.</p>
<h3 id="4-as">4. as</h3>
<p>예를 들어 Button 태그에 스타일을 적용했지만 Button 뿐만이 아닌 다른 태그에도 해당 스타일을 적용하고 싶을때 사용한다.
위의 예제처럼 styled() 해서 사용도 가능하겠지만 확장이 목적이 아닌 그대로 사용하려는 것이기에 사용하기에 적절하지 못하다.
이때 as에 태그명을 적어 props로 보내주면 된다.</p>
<pre><code class="language-javascript">import styled from &quot;styled-components&quot;;

const Father = styled.div`
  display: flex;
`;
const Btn = styled.button`
  color: white;
  background-color: tomato;
  border: 0;
  border-radius: 15px;
`;

function App() {
  return (
    &lt;Father&gt;
      &lt;Btn&gt;Log in&lt;/Btn&gt;
      &lt;Btn as=&quot;a&quot; href=&quot;/&quot;&gt;
        Log in
      &lt;/Btn&gt;
    &lt;/Father&gt;
  );
}
export default App;</code></pre>
<p><img src="https://images.velog.io/images/dev_space/post/18421403-615e-47cc-908c-32e850ce99c7/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-11%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%205.31.26.png" alt="">
button 태그에 적용한 스타일이 as를 사용함으로서 a태그로 바뀌는것을 볼 수 있다.</p>
<h3 id="5-attrs">5. attrs</h3>
<p>위의 방법들은 스타일을 적용하기 위해 사용되었는데 attrs를 사용하면 태그의 속성도 적용이 가능하다.</p>
<pre><code class="language-javascript">import styled from &quot;styled-components&quot;;

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

function App() {
  return (
    &lt;Father as=&quot;header&quot;&gt;
      &lt;Input /&gt;
      &lt;Input /&gt;
      &lt;Input /&gt;
      &lt;Input /&gt;
      &lt;Input /&gt;
    &lt;/Father&gt;
  );
}
export default App;</code></pre>
<p>Input에 required 속성을 모두 적용한 것이다.
<code>styled.input.attrs({ required: true, minLength: 10 })</code>
이런식으로 속성을 추가할 수 있다.</p>
<h3 id="6-animations">6. animations</h3>
<pre><code class="language-javascript">import styled, { keyframes } from &quot;styled-components&quot;;

const Wrapper = styled.div`
  display: flex;
`;
const rotationAnimation = keyframes`
  0% {
    transform:rotate(0deg);
    border-radius:0px;
  }
  50% {
    border-radius:100px;
  }
  100%{
    transform:rotate(360deg);
    border-radius:0px;
  }
`;

const Box = styled.div`
  height: 200px;
  width: 200px;
  background-color: tomato;
  display: flex;
  justify-content: center;
  align-items: center;
  animation: ${rotationAnimation} 1s linear infinite;
  span {
    font-size: 36px;
    &amp;:hover {
      font-size: 48px;
    }
    &amp;:active {
      opacity: 0;
    }
  }
`;

function App() {
  return (
    &lt;Wrapper&gt;
      &lt;Box&gt;
        &lt;span&gt;🤩&lt;/span&gt;
      &lt;/Box&gt;
    &lt;/Wrapper&gt;
  );
}
export default App;</code></pre>
<p>import를 해주고 keyframes를 통해 애니메이션을 줄 수 있다.(css의 @keyframes과 같음.)
그리고 scss처럼 <code>styled.div``</code> 안에 <code>span{}, &amp;:</code> 등과 같이 태그를 입력해서 스타일을 적용해줄 수 있다.</p>
<h3 id="7">7.</h3>
<p>위의 예제는 span과 같이 태그명에 의존해서 스타일을 적용한다. 태그명에 의존하고 싶지 않을때를 예로 들자.</p>
<pre><code class="language-javascript">import styled, { keyframes } from &quot;styled-components&quot;;

const Wrapper = styled.div`
  display: flex;
  height: 100vh;
  width: 100vw;
  justify-content: center;
  align-items: center;
`;
const rotationAnimation = keyframes`
  0% {
    transform:rotate(0deg);
    border-radius:0px;
  }
  50% {
    border-radius:100px;
  }
  100%{
    transform:rotate(360deg);
    border-radius:0px;
  }
`;

const Emoji = styled.span`
  font-size: 36px;
`;

const Box = styled.div`
  height: 200px;
  width: 200px;
  background-color: tomato;
  display: flex;
  justify-content: center;
  align-items: center;
  animation: ${rotationAnimation} 1s linear infinite;
  ${Emoji}:hover {
    font-size: 98px;
  }
`;

function App() {
  return (
    &lt;Wrapper&gt;
      &lt;Box&gt;
        &lt;Emoji&gt;🤩&lt;/Emoji&gt;
      &lt;/Box&gt;
      &lt;Emoji&gt;🔥&lt;/Emoji&gt;
    &lt;/Wrapper&gt;
  );
}
export default App;</code></pre>
<p><code>${Emoji}:hover</code> 와 같이 styled components 자체를 타겟팅 할 수 있다.
<code>&lt;Box&gt;</code> 안의 <code>&lt;Emoji&gt;</code>만 hover 가 적용된다. </p>
<h3 id="8-themes">8. themes</h3>
<p>다크모드를 구현할때 50% 정도를 담당한다고 한다. (나머지 50%는 local Estate Management)</p>
<pre><code class="language-javascript">//App.js
import styled from &quot;styled-components&quot;;

const Title = styled.h1`
  color: ${(props) =&gt; props.theme.textColor};
`;
const Wrapper = styled.div`
  display: flex;
  height: 100vh;
  width: 100vw;
  justify-content: center;
  align-items: center;
  background-color: ${(props) =&gt; props.theme.backgroundColor};
`;

function App() {
  return (
    &lt;Wrapper&gt;
      &lt;Title&gt;Hello&lt;/Title&gt;
    &lt;/Wrapper&gt;
  );
}
export default App;</code></pre>
<pre><code class="language-javascript">//index.js
import React from &quot;react&quot;;
import ReactDOM from &quot;react-dom&quot;;
import App from &quot;./App&quot;;
import { ThemeProvider } from &quot;styled-components&quot;;

const darkTheme = {
  textColor: &quot;whitesmoke&quot;,
  backgroundColor: &quot;#111&quot;,
};

const lightTheme = {
  textColor: &quot;#111&quot;,
  backgroundColor: &quot;whitesmoke&quot;,
};

ReactDOM.render(
  &lt;React.StrictMode&gt;
    &lt;ThemeProvider theme={darkTheme}&gt;
      &lt;App /&gt;
    &lt;/ThemeProvider&gt;
  &lt;/React.StrictMode&gt;,
  document.getElementById(&quot;root&quot;)
);</code></pre>
<p>위에서 보면 알수있듯이 <code>ThemeProvider</code>를 사용하면 App.js 에서 <code>${(props) =&gt; props.theme.backgroundColor}</code>를 사용하여 스타일을 일일이 바꿔줄 필요없이 <code>ThemeProvider theme={}</code> 에 지정한 object의 내용만 바꿔주면 알아서 적용이 된다.
<code>ThemeProvider theme={}</code> 에 lightTheme, darkTheme를 바꿔 넣어보면 바뀌는것을 알 수 있다.
property의 이름은 똑같아야된다.</p>
<h3 id="reference">Reference</h3>
<p><a href="https://dkje.github.io/2020/10/13/StyledComponents">https://dkje.github.io/2020/10/13/StyledComponents</a>
<a href="https://nomadcoders.co/react-masterclass">https://nomadcoders.co/react-masterclass</a>
<a href="https://blog.logrocket.com/benefits-using-styled-components-react">https://blog.logrocket.com/benefits-using-styled-components-react</a>
<a href="https://styled-components.com/docs/basics">https://styled-components.com/docs/basics</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[MVP 패턴]]></title>
            <link>https://velog.io/@dev_space/MVP-%ED%8C%A8%ED%84%B4</link>
            <guid>https://velog.io/@dev_space/MVP-%ED%8C%A8%ED%84%B4</guid>
            <pubDate>Wed, 08 Dec 2021 12:18:29 GMT</pubDate>
            <description><![CDATA[<h1 id="mvp-패턴-이란">MVP 패턴 이란?</h1>
<ul>
<li>Model View Presenter 로 MVC 패턴의 파생 패턴이다.</li>
<li>사용자 인터페이스를 개발하기 위해 대부분 사용된다.</li>
<li>Model, View 는 MVC 패턴과 동일하고, Controller 대신 Presenter가 존재한다.</li>
<li>View와 Model을 완전히 분리해서 사용하기 위해서 생긴 패턴이라는것 같다.
<img src="https://images.velog.io/images/dev_space/post/568001aa-1f32-4ae5-8356-9ea599f03f2d/image.png" alt=""><h2 id="model">Model</h2>
</li>
<li>모델은 모든 데이터가 저장되고 조작되는 부분이다.</li>
<li>View와 Presenter에 의존적이지 않은 독립적인 영역.<h2 id="view">View</h2>
</li>
<li>데이터를 표시하고 모든 명령을 발표자에게 다시 라우팅하는 수동 인터페이스이다.<h2 id="presenter">Presenter</h2>
</li>
<li>Presenter는 View와 Model에 대해 작동하며 Model과 View 모두에서 모든 정보를 검색하고 둘 사이에 정보를 보낸다.</li>
<li>Controller와 역할이 비슷하지만 Interface를 사용한다는 것의 차이가 있다.</li>
<li>이에 따라 MVC가 가진 테스트 가능성 문제와 함께 모듈화/유연성 문제 역시 해결할 수 있음</li>
<li>프리젠터(Presenter)의 역할을 한줄로 표현한다면 뷰(View)와 모델(Model) 사이에서 자료 전달 역할을 함</li>
</ul>
<p>본질적으로는 MVC의 컨트롤러와 같지만, 뷰에 연결되는 것이 아니라 그냥 인터페이스라는 점이 다르다. 이에 따라 MVC가 가진 테스트 가능성 문제와 함께 모듈화/유연성 문제 역시 해결한다. 사실 극단적으로 MVP를 따르는 사람들은 프리젠터가 절대로 어떤 안드로이드 API나 코드라도 참조해서는 안된다고 주장한다.</p>
<h2 id="동작">동작</h2>
<ol>
<li>사용자의 input이 View를 통해 들어온다.</li>
<li>View는 필요한 데이터를 Presenter에게 요청한다.</li>
<li>Presenter는 Model에게 데이터를 요청한다.</li>
<li>Model은 변경된 데이터를 Presenter에게 전달한다.</li>
<li>Presenter는 View에게 데이터를 전달한다.</li>
<li>View는 받은 데이터를 UI에 표현한다.<h2 id="장점">장점</h2>
</li>
</ol>
<ul>
<li>Presenter가 Model과 View의 중간다리 역할을 하기 때문에 Model과 View 사이의 의존성이 없다.</li>
<li>대부분의 책임을 Presenter와 Model이 가지고 있어 View는 출력만 하는 역할을 한다</li>
<li>Test할 때 View에 대한 책임이 분리되어 있기에 각 요소들을 독립적으로 테스팅할 수 있다<h2 id="단점">단점</h2>
Model과 View 사이의 의존성을 해결했지만, 역으로 Presenter와 View 사이가 1:1로 강한 의존성을 가진다.<h2 id="정리">정리</h2>
MVC의 Controller와 다르게 Presenter는 뷰에게 무언가를 표시하는 방법을 지시하는 대신, 표시할 내용만 전달한다.(보기를 구성하는 방법만 지정한다.)
그리고 인터페이스와 로직을 분리해서 관리할 수 있어 각 행동의 의도가 더 단순하고 명확해진다.
하지만 Controller 처럼 시간이 지남에 따라 추가 비즈니스 로직이 모이는 경향이 있어 문제가 발생하기 쉽고 분리하기 어려운 Presenter가 생겨서 유지보수에 어려움이 있다. 그리고 프로젝트가 커질 수록 Presenter의 자원이 많아질 수 있다.</li>
</ul>
<p>MVP는 애플리케이션을 모듈로 나눌 수 있다는 점에서 MVC보다 약간 우위에 있다. 따라서 지속적으로 뷰를 생성하지 않아도 된다. 즉, MVP는 뷰를 재사용 가능하게 만드는데 도움이 될 수 있다.</p>
<h3 id="reference">Reference</h3>
<p><a href="https://devscorch.com/?p=1460">https://devscorch.com/?p=1460</a>
<a href="https://ko.wikipedia.org/wiki/%EB%AA%A8%EB%8D%B8-%EB%B7%B0-%ED%94%84%EB%A6%AC%EC%A0%A0%ED%84%B0">https://ko.wikipedia.org/wiki/%EB%AA%A8%EB%8D%B8-%EB%B7%B0-%ED%94%84%EB%A6%AC%EC%A0%A0%ED%84%B0</a>
<a href="https://swimjiy.github.io/2019-05-28-web-mvc-mvp-mvvm">https://swimjiy.github.io/2019-05-28-web-mvc-mvp-mvvm</a>
<a href="https://cjw-awdsd.tistory.com/9">https://cjw-awdsd.tistory.com/9</a>
<a href="https://jhtop0419.tistory.com/20">https://jhtop0419.tistory.com/20</a>
<a href="https://academy.realm.io/kr/posts/eric-maxwell-mvc-mvp-and-mvvm-on-android/">https://academy.realm.io/kr/posts/eric-maxwell-mvc-mvp-and-mvvm-on-android/</a>
<a href="https://www.baeldung.com/mvc-vs-mvp-pattern">https://www.baeldung.com/mvc-vs-mvp-pattern</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[MVC 패턴]]></title>
            <link>https://velog.io/@dev_space/MVC-%ED%8C%A8%ED%84%B4</link>
            <guid>https://velog.io/@dev_space/MVC-%ED%8C%A8%ED%84%B4</guid>
            <pubDate>Wed, 08 Dec 2021 09:10:36 GMT</pubDate>
            <description><![CDATA[<h1 id="mvc-패턴이란">MVC 패턴이란?</h1>
<ul>
<li>model view controller 로 소프트웨어 공학에서 사용되는 소프트웨어 디자인 패턴이다.</li>
<li>이 패턴을 성공적으로 사용하면, 사용자 인터페이스로부터 비즈니스 로직을 분리하여 애플리케이션의 시각적 요소나 그 이면에서 실행되는 비즈니스 로직을 서로 영향 없이 쉽게 고칠 수 있는 애플리케이션을 만들 수 있다.</li>
<li>하나의 애플리케이션, 프로젝트를 구성할 때 그 구성요소를 세가지의 역할로 구분한 패턴이다.<img src="https://images.velog.io/images/dev_space/post/d117b7a0-f73d-4cd0-898f-19786e319c26/image.png" width="50%">
출처: [위키백과](https://ko.wikipedia.org/wiki/%EB%AA%A8%EB%8D%B8-%EB%B7%B0-%EC%BB%A8%ED%8A%B8%EB%A1%A4%EB%9F%AC)
>controller는 model을 통해서 데이터를 가져오고 그 정보를 바탕으로 시각적인 표현을 담당하는 view를 제어해서 사용자에게 전달한다.
## Model
모델은 앱이 포함해야할 데이터가 무엇인지를 정의합니다. 데이터의 상태가 변경되면 모델은 일반적으로 뷰에게 알리며 필요한대로 화면을 변경할 수 있다. 가끔 컨트롤러에게 알리기도 한다(업데이트된 뷰를 제거하기 위해 다른 로직이 필요한 경우).
## View
뷰는 앱의 데이터를 보여주는 방식을 정의한다.
항목이 사용자게에 보여지는 방식을 정의하며, 표시할 데이터를 모델로부터 받는다.
## Controller
컨트롤러는 앱의 사용자로부터의 입력에 대한 응답으로 모델 및/또는 뷰를 업데이트하는 로직을 포함한다.
예를 들어보면, 쇼핑 리스트는 항목을 추가하거나 제거할 수 있게 해주는 입력 폼과 버튼을 갖는다. 이러한 액션들은 모델이 업데이트되는 것이므로 입력이 컨트롤러에게 전송되고, 모델을 적당하게 처리한다음, 업데이트된 데이터를 뷰로 전송한다.
단순히 데이터를 다른 형태로 나타내기 위해 뷰를 업데이트하고 싶을 수도 있다(예를 들면, 항목을 알파벳순서로 정렬한다거나, 가격이 낮은 순서 또는 높은 순서로 정렬). 이런 경우에 컨트롤러는 모델을 업데이트할 필요 없이 바로 처리할 수 있다.
## 특징</li>
<li>Controller는 여러개의 View를 선택할 수 있는 1:n 구조이다.</li>
<li>Controller는 View를 선택할 뿐 직접 업데이트 하지 않는다.</li>
<li>View는  Controller를 알지 못한다.<h2 id="장점">장점</h2>
MVC 패턴의 장점은 널리 사용되고 있는 패턴이라는 점에 걸맞게 가장 단순하다. 단순하다 보니 보편적으로 많이 사용되는 디자인패턴이다.
사용자가 보는 페이지, 데이터처리, 그리고 이 2가지를 중간에서 제어하는 컨트롤, 이 3가지로 구성되는 하나의 애플리케이션을 만들면 각각 맡은바에만 집중을 할 수 있게 된다. 도메인을 작은 역할 단위로 분리하여 설계하는 것도 일종의 분업이라고 할 수 있지만 전체적인 구조에서도 MVC 패턴은 분업을 만들어 낼 수 있다.
서로 분리되어 각자의 역할에 집중할 수 있게끔하여 개발을 하고 그렇게 애플리케이션을 만든다면, 유지보수성, 애플리케이션의 확장성, 그리고 유연성이 증가하고, 중복코딩이라는 문제점 또한 사라지게 된다.<h2 id="단점">단점</h2>
MVC에서 View는 Controller에 연결되어 화면을 구성하는 단위요소이므로 다수의 View들을 가질 수 있다. 그리고 Model은 Controller를 통해서 View와 연결되어지지만, 이렇게 Controller를 통해서 하나의 View에 연결될 수 있는 Model도 여러개가 될 수 있다.
<code>View와 Model 사이의 의존성이 높다.</code>
즉, 화면에 복잡한 화면과 데이터의 구성 필요한 구성이라면, Controller에 다수의 Model과 View가 복잡하게 연결되어 있는 상황이 생길 수 있어 유지보수가 어렵게 만들 수 있다.
MVC 규모 자체가 너무 복잡하고 비대해져서, 새 기능을 추가할때마다 의존성을 일일이 해결해야해서 메소드 분석이나 테스트도 어렵게 된다. 이런 형태의 MVC를 Massive View Controller라고 부르는데, 이는 MVC의 한계를 표현한 용어이기도 하다.<h2 id="정리">정리</h2>
Model 은 어플리케이션이 무엇을 할 것인지를 <strong>정의</strong>. 내부 비지니스 로직을 처리하기 위한 역할을 한다.
Controller 는 모델을 <strong>어떻게</strong> 처리할 것인지를 알려주는 역할. 요청 내용을 분석해서 모델과 뷰에 업데이트 요청을 한다.
View 는 화면에 어떤걸 <strong>보여주기</strong> 위한 역할. 모델이나 컨트롤러가 보여주려고 하는 것들을 보여준다.</li>
</ul>
<p><strong>장점</strong>은 페이지, 데이터 처리, 중간에서 제어하는 컨트롤. 이 3가지로 구성해 하나의 애플리케이션을 만들면 분업을 만들어 낼 수 있어 각각 맡은바에 집중할 수 있게된다. 이렇게 서로 분리되어 각자의 역할에 집중할 수 있다면 유지보수, 확장성, 유연성이 증가한다.</p>
<blockquote>
<p>유지보수 : 이미 구축되어진 시스템을 운영 및 관리.
확장성 : 비즈니스 요구에 맞도록 시스템을 확장하는 기능.
유연성 : 상황, 이용자환경, 권한 등에 따른 효율적 업무 분산과 집중을 의미.</p>
</blockquote>
<p><strong>단점</strong>은 Massive View Controller가 될 수 있다. 복잡한 화면과 여러 데이터의 구성 필요한 경우 컨트롤러를 통해 하나의 뷰에 연결될 수 있는 모델이 여러개가 되어 뷰와 모델 사이의 의존성이 높아져 새로운 기능을 추가하거나 수정할 때 의존성을 일일이 해결해야돼서 유지보수와 테스트가 어렵게 된다.</p>
<h3 id="reference">reference</h3>
<p><a href="https://ko.wikipedia.org/wiki/%EB%AA%A8%EB%8D%B8-%EB%B7%B0-%EC%BB%A8%ED%8A%B8%EB%A1%A4%EB%9F%AC">https://ko.wikipedia.org/wiki/%EB%AA%A8%EB%8D%B8-%EB%B7%B0-%EC%BB%A8%ED%8A%B8%EB%A1%A4%EB%9F%AC</a>
<a href="https://m.blog.naver.com/jhc9639/220967034588">https://m.blog.naver.com/jhc9639/220967034588</a>
<a href="https://developer.mozilla.org/ko/docs/Glossary/MVC">https://developer.mozilla.org/ko/docs/Glossary/MVC</a>
<a href="https://beomy.tistory.com/43">https://beomy.tistory.com/43</a>
<a href="https://medium.com/@jang.wangsu/%EB%94%94%EC%9E%90%EC%9D%B8%ED%8C%A8%ED%84%B4-mvc-%ED%8C%A8%ED%84%B4%EC%9D%B4%EB%9E%80-1d74fac6e256">https://medium.com/@jang.wangsu/%EB%94%94%EC%9E%90%EC%9D%B8%ED%8C%A8%ED%84%B4-mvc-%ED%8C%A8%ED%84%B4%EC%9D%B4%EB%9E%80-1d74fac6e256</a>
<a href="https://velog.io/@ljinsk3/MVC-%ED%8C%A8%ED%84%B4">https://velog.io/@ljinsk3/MVC-%ED%8C%A8%ED%84%B4</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[소프트웨어 디자인 패턴]]></title>
            <link>https://velog.io/@dev_space/%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4-%EB%94%94%EC%9E%90%EC%9D%B8-%ED%8C%A8%ED%84%B4</link>
            <guid>https://velog.io/@dev_space/%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4-%EB%94%94%EC%9E%90%EC%9D%B8-%ED%8C%A8%ED%84%B4</guid>
            <pubDate>Wed, 08 Dec 2021 07:52:04 GMT</pubDate>
            <description><![CDATA[<p>개발의 경험이 쌓이다 보면 자신이 전에 사용했던 코드와 유사한 기능을 구현해야 해서 이전의 코드를 들여다 보게되는 경험을 하게 되는데 이때 전에 사용한 코드를 그대로 사용하기도 하고 변형해서 사용하기도 한다.
디자인 패턴은 설계자로 하여금 재사용이 가능한 설계는 선택하고, 재사용을 방해하는 설계는 배제하도록 도와준다. 또한 패턴을 쓰면 이미 만든 시스템의 유지보수나 문서화도 개선할 수 있고, 클래스의 명세도 정확하게 할 수 있으며, 객체 간의 상호작용 또는 설계 의도까지 명확하게 정의할 수 있다.</p>
<h1 id="software-design-pattern-이란">Software Design Pattern 이란?</h1>
<ul>
<li>소스나 기계 코드로 바로 전환될 수 있는 완성된 디자인은 아니며, 상황에 맞게 사용될 수 있는 문제들을 해결하는데에 쓰이는 서술이나 템플릿이다.</li>
<li>프로그래머가 어플리케이션이나 시스템을 디자인할 때 공통된 문제들을 해결하는데에 쓰이는 형식화 된 가장 좋은 관행이다.</li>
<li>과거의 소프트웨어 개발 과정에서 발견된 설계의 노하우를 축적하여 이름을 붙여, 이후에 재이용하기 좋은 형태로 특정의 규약을 묶어서 정리한 것이다. 알고리즘과 같이 프로그램 코드로 바로 변환될 수 있는 형태는 아니지만, 특정한 상황에서 구조적인 문제를 해결하는 방식을 설명해 준다.<h3 id="reference">Reference</h3>
<a href="https://ko.wikipedia.org/wiki/%EB%94%94%EC%9E%90%EC%9D%B8_%ED%8C%A8%ED%84%B4#%EC%BB%B4%ED%93%A8%ED%84%B0_%EA%B3%BC%ED%95%99%EC%97%90%EC%84%9C%EC%9D%98_%EB%94%94%EC%9E%90%EC%9D%B8_%ED%8C%A8%ED%84%B4">https://ko.wikipedia.org/wiki/%EB%94%94%EC%9E%90%EC%9D%B8_%ED%8C%A8%ED%84%B4#%EC%BB%B4%ED%93%A8%ED%84%B0_%EA%B3%BC%ED%95%99%EC%97%90%EC%84%9C%EC%9D%98_%EB%94%94%EC%9E%90%EC%9D%B8_%ED%8C%A8%ED%84%B4</a>
<a href="https://en.wikipedia.org/wiki/Software_design_pattern">https://en.wikipedia.org/wiki/Software_design_pattern</a>
<a href="https://readystory.tistory.com/114">https://readystory.tistory.com/114</a>
<a href="https://shoark7.github.io/programming/knowledge/what-is-design-pattern">https://shoark7.github.io/programming/knowledge/what-is-design-pattern</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Webpack]]></title>
            <link>https://velog.io/@dev_space/Webpack</link>
            <guid>https://velog.io/@dev_space/Webpack</guid>
            <pubDate>Wed, 13 Oct 2021 12:24:16 GMT</pubDate>
            <description><![CDATA[<h1 id="webpack-이란">Webpack 이란?</h1>
<p><img src="https://images.velog.io/images/dev_space/post/25e48e43-0a5f-445c-b44d-4f7c62718fc2/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-10-13%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%207.20.29.png" alt=""></p>
<ul>
<li>webpack 은 최신 JavaScript 애플리케이션을 위한 정적 모듈 번들러이다.</li>
<li>webpack 이 애플리케이션을 처리할 때 내부적으로 하나 이상의 진입점에서 종속성 그래프를 빌드한 다음 프로젝트에 필요한 모든 모듈을 하나 이상의 번들로 결합한다.</li>
<li>필요한 다수의 자바스크립트 파일을 하나의 자바 스크립트 파일로 만들어주는 것을 webpack 이라 한다.</li>
</ul>
<h1 id="webpack-을-사용하는-이유">Webpack 을 사용하는 이유</h1>
<ul>
<li>하나의 HTML 페이지에 여러개의 JavaScript 파일들이 포함되는데 연관되어 있는 JavaScript, 종속성이 있는 파일들을 하나의 파일로 묶어줘서 관리하기 편리하다.</li>
<li>파일을 컴파일 할 때, 여러 모듈들의 파일을 읽어오는데 시간이 오래 걸린다. 그 부분을 해결하기 위해 여러 파일을 하나의 파일로 번들링 해준다. (웹페이지 성능 최적화)</li>
</ul>
<h1 id="webpack-시작하기">Webpack 시작하기</h1>
<p>webpack은 Node.js 모듈중에 하나이기에 기본적으로 Node.js 가 설치되어 있어야 한다.</p>
<ol>
<li><code>npm init</code>
package.json 생성 해준다.<br></li>
<li><code>npm i -D webpack</code>
<code>-D</code>는 <code>--save-dev</code> 와 같다.<br></li>
<li><code>npm i -D webpack-cli</code>
만약 webpack v4 또는 이후 버전을 사용한다면, CLI도 설치한다.<br></li>
<li>webpack.config.js 파일을 생성해서 설정해준다.<pre><code class="language-javascript">//webpack.config.js (작성 예)
const path = require(&#39;path&#39;);
</code></pre>
</li>
</ol>
<p>module.exports = {
  entry: &#39;./path/to/my/entry/file.js&#39;,
  output: {
    path: path.resolve(__dirname, &#39;dist&#39;),
    filename: &#39;my-first-webpack.bundle.js&#39;,
  },
};</p>
<pre><code>file.js 파일을 빌드해서 dist 라는 폴더에 my-first-webpack.bundle.js 라는 파일로 생성한다.
`__dirname`: 디렉토리의 절대 경로를 나타낸다.&lt;br&gt;
5. `npx webpack`
터미널에 위의 명령어를 실행하면 빌드된 새로운 파일이 생성된것을 볼 수 있다.

&gt;**`-D` or `--save-dev`**
설치된 모듈이 package.json 의 devDependencies 에 표시된다.
dependencies는 프로젝트에 필요한것을 나타내고 devDependencies는 개발자에게 필요한것을 나타낸다고 한다. dependencies에 다 표시해도 상관은 없지만 어떤 패키지가 무슨 일을 하는지 알기 위한 우리를 위한 구분이다.

&gt;**webpack-cli**
- 개발자가 맞춤형 webpack 프로젝트를 설정할 때 속도를 높일 수 있는 유연한 명령 세트를 제공한다.
- webpack 버전 4부터 명령줄 인터페이스는 기본 패키지에서 제거되고 자체 리포지토리 및 패키지에 추가되었다.
위와 같은 이유로 webpack과 별도로 cli를 설치해야 한다.
CLI : 명령줄 인터페이스
webpack : 주요 기능&lt;br&gt;
&lt;https://www.npmjs.com/package/webpack-cli&gt;
&lt;https://stackoverflow.com/questions/51948057/install-webpack-vs-install-webpack-cli/51948245&gt;

## 알아야할 구조
- path : 파일의 경로를 다루고 변경하는 유틸리티
- output : build 결과를 저장할 경로
- entry : build의 대상이 될 파일
- Plug-In : build 된 bundle 파일을 동적으로 특정 html 페이지에 추가 할 수 있으며 build 시에 javscript, css, html 등의 파일을 난독화 및 압축을 진행할 수 있다.

## Loaders
기본적으로 webpack은 JavaScript 및 JSON 파일만 이해한다. Loader를 사용하면 webpack이 다른 유형의 파일을 처리하고 애플리케이션에서 사용하고 종속성 그래프에 추가할 수 있는 유효한 모듈로 변환할 수 있다.

&gt;**속성**
test: 어떤 파일이나 파일 속성 식별이 변화되어야한다.
use: 변형을 수행하는데 사용되어야하는 Loader를 나타낸다.

```javascript
//webpack.config.js (loader 사용 예)
const path = require(&#39;path&#39;);

module.exports = {
  entry: &#39;./path/to/my/entry/file.js&#39;,
  output: {
    path: path.resolve(__dirname, &#39;dist&#39;),
    filename: &#39;my-first-webpack.bundle.js&#39;,
  },
  module: {
    rules: [{
        test: /\.js$/,
        use: {
          loader: &quot;babel-loader&quot;,
          options: {
            presets: [[&quot;@babel/preset-env&quot;, { targets: &quot;defaults&quot; }]],
          },
        },
    }],
  },
};</code></pre><p>babel-loader 를 사용하는 예이다.</p>
<blockquote>
<p><strong>babel-loader</strong>
babel 및 webpack 을 사용하여 JavaScript 파일을 변환할 수 있다.
<a href="https://velog.io/@dev_space/Babel">Babel이란?</a>
<code>npm install -D babel-loader @babel/core @babel/preset-env</code>
babel-loader 를 사용하려면 관련 모듈을 설치해야된다.
<a href="https://github.com/babel/babel-loader">https://github.com/babel/babel-loader</a>
<a href="https://webpack.js.org/loaders/babel-loader/#root">https://webpack.js.org/loaders/babel-loader/#root</a></p>
</blockquote>
<h2 id="plugins">Plugins</h2>
<p>Loader 는 특정 유형의 모듈을 변환하는데 사용되지만 Plugin 은 번들 최적화, 자산 관리 및 환결 변수 주입과 같은 광범위한 작업을 수행하는데 활용될 수 있다.</p>
<ul>
<li>로더가 파일단위로 처리하는 반면 플러그인은 번들된 결과물을 처리한다.</li>
<li>번들된 자바스크립트를 난독화 한다거나 특정 텍스트를 추출하는 용도로 사용할 수 있다.</li>
</ul>
<pre><code class="language-javascript">//webpack.config.js (plugin &amp; loader 사용 예)
const MiniCssExtractPlugin = require(&quot;mini-css-extract-plugin&quot;);

module.exports = {
  plugins: [new MiniCssExtractPlugin()],
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: [MiniCssExtractPlugin.loader, &quot;css-loader&quot;],
      },
    ],
  },
};</code></pre>
<p>use에 입력된건 역순으로 적용된다.
css-loader 가 적용되고 MiniCssExtractPlugin 가 적용된다는 말이다.</p>
<p><a href="https://webpack.js.org/plugins/">Plugin 종류 보기</a></p>
<blockquote>
<p><strong>MiniCssExtractPlugin</strong>
CSS를 별도의 파일로 추출하는 Plugin이다.
CSS가 포함된 JS 파일별로 CSS 파일을 생성한다.
CSS 및 SourceMaps의 온디맨드 로딩을 지원한다.
<code>npm install --save-dev mini-css-extract-plugin</code>
plugin 을 설치해줘야 사용이 가능하다.
<a href="https://webpack.js.org/plugins/mini-css-extract-plugin/">MiniCssExtractPlugin</a></p>
</blockquote>
<h2 id="mode">mode</h2>
<ul>
<li>mode 구성 옵션을 제공하면 webpack이 그에 따라 내장 최적화를 사용하도록 지시한다.</li>
<li>설정하지 않으면 production이 기본값으로 설정된다.</li>
<li>옵션으로는 <code>development, production, none</code> 이 있다.</li>
</ul>
<pre><code class="language-javascript">//webpack.config.js
module.exports = {
  mode: &#39;development&#39;,
};</code></pre>
<p>또는 CLI 인수로 전달한다.
<code>webpack --mode=development</code></p>
<p><a href="https://webpack.js.org/configuration/mode/#root">webpack mode 자세히 보기</a></p>
<h1 id="추가">추가</h1>
<h2 id="watch">watch</h2>
<p>Webpack이 파일을 보고 변경될 때마다 자동으로 컴파일해준다.</p>
<pre><code class="language-javascript">//webpack.config.js
module.exports = {
  //...
  watch: true,
};</code></pre>
<p><a href="https://webpack.js.org/configuration/watch/">https://webpack.js.org/configuration/watch/</a></p>
<h2 id="outputclean">output.clean</h2>
<p>webpack은 파일을 생성하여 지정한 폴더에 넣지만 실제로 프로젝트에서 사용중인 파일은 추적하지 않는다. 그러면서 빌드된 파일들이 들어있는 폴더가 상당히 복잡해지는데 이를 해결하기 위해 <code>clean</code> 옵션을 사용한다.</p>
<ul>
<li>각 빌드 전에 폴더를 정리하여 사용된 파일만 생성한다.</li>
</ul>
<pre><code class="language-javascript">//webpack.config.js
module.exports = {
  //...
  output: {
      //...
    clean: true, // 내보내기 전에 output 디렉토리를 정리합니다.
  }
};</code></pre>
<p><a href="https://webpack.js.org/guides/output-management/">https://webpack.js.org/guides/output-management/</a>
<a href="https://webpack.kr/configuration/output/#outputclean">https://webpack.kr/configuration/output/#outputclean</a></p>
<h1 id="reference">Reference</h1>
<p><a href="https://webpack.js.org/api/">https://webpack.js.org/api/</a>
<a href="https://jusungpark.tistory.com/52">https://jusungpark.tistory.com/52</a>
<a href="https://velog.io/@yon3115/%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C-%ED%95%84%EC%88%98-Webpack%EC%9D%B4%EB%9E%80">https://velog.io/@yon3115/%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C-%ED%95%84%EC%88%98-Webpack%EC%9D%B4%EB%9E%80</a>
<a href="https://jusungpark.tistory.com/52">https://jusungpark.tistory.com/52</a>
<a href="https://devowen.com/288">https://devowen.com/288</a>
<a href="https://hipdizzy.tistory.com/91">https://hipdizzy.tistory.com/91</a>
<a href="https://hipdizzy.tistory.com/91">https://hipdizzy.tistory.com/91</a>
<a href="https://medium.com/@woody_dev/js-webpack-1-%EC%9B%B9%ED%8C%A9%EC%9D%B4%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80-f29ebca31da4">https://medium.com/@woody_dev/js-webpack-1-%EC%9B%B9%ED%8C%A9%EC%9D%B4%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80-f29ebca31da4</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[express]]></title>
            <link>https://velog.io/@dev_space/express</link>
            <guid>https://velog.io/@dev_space/express</guid>
            <pubDate>Wed, 06 Oct 2021 16:44:50 GMT</pubDate>
            <description><![CDATA[<h1 id="express-란">express 란?</h1>
<ul>
<li>node.js를 위한 빠르고 객관적이며 미니멀한 웹 프레임워크.</li>
<li>node.js를 사용하여 쉽게 서버를 구성할 수 있게 만든 클래스와 라이브러리의 집합체.</li>
<li>Express.js는 Node.js의 핵심 모듈인 http와 Connect 컴포넌트를 기반으로 하는 웹 프레임워크다. 그러한 컴포넌트를 미들웨어(middleware)라고 하며, 설정보다는 관례(convention over configuration)와 같은 프레임워크의 철학을 지탱하는 주춧돌에 해당한다. 즉, 개발자들은 특정 프로젝트에 필요한 라이브러리를 어떤 것이든 자유롭게 선택할 수 있으며, 이는 개발자들에게 유연함과 수준 높은 맞춤식 구성을 보장한다.</li>
<li>node.js에는 다양한 웹 프레임워크가 존재하지만 현재 가장 많이 사용되는 엔진이라고 한다.</li>
<li>express는 React, Angular, Vue와 같이 client-side의 프레임워크가 아니라 &quot;server-side&quot; 또는 &quot;back-end&quot;의 프레임워크이다.<blockquote>
<p>Express는 자체 기능이 최소화된 라우팅 및 미들웨어 웹 프레임워크이다. Express 애플리케이션은 본질적으로 일련의 미들웨어 기능 호출이다.</p>
</blockquote>
<h2 id="시작하기">시작하기</h2>
</li>
</ul>
<ol>
<li>프로젝트 파일에 들어가 <code>npm init</code> 을 해준다.</li>
<li><code>npm install express</code>
node_modules에 express를 설치한다.</li>
<li>js 파일을 생성해 코드를 작성해준다.<pre><code class="language-JavaScript">//server.js
const express = require(&quot;express&quot;);
const app = express();
</code></pre>
</li>
</ol>
<p>app.get(&#39;/&#39;, function (req, res) {
    console.log(&quot;Hello!&quot;);
});</p>
<p>app.listen(3000);</p>
<pre><code>4. 터미널에서 해당 프로젝트 폴더로 들어가 `node server.js` 입력
5. &lt;http://localhost:3000/&gt;
위의 주소를 들어가면 `node server.js`를 실행한 터미널에 &quot;Hello&quot; 가 출력된 것을 볼 수 있다.
## 내가 알고싶은 기능 및 옵션
- Routing
- middleware
- app.listen()
- (req, res, next)
- set()
- use()
- router.get()
- post()
- route()
- put()
- delete()
- render()
- redirect()
- send()
- express.urlencoded()

### Routing
라우팅 은 URI(또는 경로) 및 특정 HTTP 요청 방법(GET, POST 등)인 특정 끝점에 대한 클라이언트 요청에 애플리케이션이 응답하는 방식을 결정하는 것을 말한다.
&lt;https://expressjs.com/en/starter/basic-routing.html/&gt;

### middleware
미들웨어 기능은 애플리케이션의 요청-응답 주기 에서 요청 객체 (req), 응답 객체 (res), 다음 미들웨어 기능에 접근할 수 있는 기능이다. 다음 미들웨어 기능은 일반적으로 next 라는 변수로 표시됩니다.
- **유형**
    - 애플리케이션 수준 미들웨어
    - 라우터 수준 미들웨어
    - 오류 처리 미들웨어
    - 내장 미들웨어
    - 타사 미들웨어
&lt;http://expressjs.com/en/guide/using-middleware.html#using-middleware/&gt;

### listen()
1. UNIX 소켓을 시작하고 지정된 경로에서 연결을 수신한다.
**app.listen(path, [callback])**
```JavaScript
var express = require(&#39;express&#39;)
var app = express()
app.listen(&#39;/tmp/sock&#39;)</code></pre><ol start="2">
<li>지정된 호스트 및 포트에서 연결을 바인딩하고 수신 대기한다.
포트가 생략되거나 0이면 운영 체제는 사용되지 않는 임의의 포트를 할당하므로 자동화된 작업(테스트 등)과 같은 경우에 유용하다.</li>
</ol>
<p><strong>app.listen([port[, host[, backlog]]][, callback])</strong></p>
<pre><code class="language-JavaScript">var express = require(&#39;express&#39;)
var app = express()
app.listen(3000)</code></pre>
<h3 id="req-res-next">(req, res, next)</h3>
<ul>
<li>req(request) : HTTP 요청 인수</li>
<li>res(respone) : HTTP 응답 인수</li>
<li>next : 미들웨어 함수에 대한 콜백 인수<ul>
<li>함수내에 next()를 사용하면 다음 미들웨어 함수로 넘어간다.<blockquote>
<p>To skip the rest of the middleware functions from a router middleware stack, call next(&#39;route&#39;) to pass control to the next route. NOTE: next(&#39;route&#39;) will work only in middleware functions that were loaded by using the app.METHOD() or router.METHOD() functions.</p>
</blockquote>
</li>
</ul>
</li>
</ul>
<h3 id="router">Router()</h3>
<blockquote>
<p>router객체 미들웨어 및 경로의 고립 된 인스턴스입니다. 미들웨어 및 라우팅 기능만 수행할 수 있는 &quot;미니 애플리케이션&quot;으로 생각할 수 있습니다. 모든 Express 애플리케이션에는 앱 라우터가 내장되어 있습니다.
라우터는 미들웨어 자체처럼 작동하므로 app.use()에 대한 인수로 또는 다른 라우터의 use() 메서드에 대한 인수로 사용할 수 있습니다.<a href="http://expressjs.com/en/5x/api.html#router/">http://expressjs.com/en/5x/api.html#router/</a></p>
</blockquote>
<p><strong>사용예</strong></p>
<pre><code class="language-javascript">//server.js
import express from &quot;express&quot;;
import userRouter from &quot;userRouter&quot;;

const app = express();

app.use(&quot;/users&quot;, rootRouter);

app.listen(3000);</code></pre>
<pre><code class="language-javascript">//userRouter.js
import express from &quot;express&quot;;
import {
  getEdit,
  postEdit,
  logout,
} from &quot;userController&quot;;
import { protectorMiddleware } from &quot;middlewares&quot;;

const userRouter = express.Router();

userRouter.get(&quot;/logout&quot;, protectorMiddleware, logout);
userRouter.route(&quot;/edit&quot;).all(protectorMiddleware).get(getEdit).post(postEdit);

export default userRouter;</code></pre>
<p>URL 
<a href="http://localhost:3000/users/logout">http://localhost:3000/users/logout</a>
<a href="http://localhost:3000/users/edit">http://localhost:3000/users/edit</a>
을 각각 설정해 준것이다.
server.js 에서 app 으로</p>
<pre><code class="language-javascript">//server.js
...
app.get(&quot;/users/logout&quot;, protectorMiddleware, logout);
...</code></pre>
<p>위와 같은 식으로 <code>express.Router()</code> 를 사용하지 않고 해도 되지만, 코드 관리를 위해 라우터를 별도로 분리하는 것이다.
Router() 객체로 라우팅을 분리.</p>
<h3 id="set">set()</h3>
<p>name에 설정 value를 할당합니다. 원하는 값을 저장할 수 있지만 특정 이름을 사용하여 서버의 동작을 구성할 수 있습니다. <a href="http://expressjs.com/en/5x/api.html#app.settings.table">설정 표</a></p>
<p><strong>사용예</strong></p>
<pre><code class="language-javascript">//server.js
import express from &quot;express&quot;;
import userRouter from &quot;userRouter&quot;;

const app = express();

app.set(&quot;view engine&quot;, &quot;pug&quot;);
app.set(&quot;views&quot;, process.cwd() + &quot;/src/views&quot;);

app.use(&quot;/users&quot;, rootRouter);

app.listen(3000);</code></pre>
<p>PUG 를 설정해준것이다.
view engine 으로 기본 엔진을 pug 로 하고 views 디렉토리 경로를 설정해줬다.</p>
<blockquote>
<p>process.cwd()
현재 프로세스가 실행되는 위치(디렉토리)의 절대경로이다.</p>
</blockquote>
<blockquote>
<p>PUG 는 HTML 을 PUG 문법으로 작성하면 HTML 로 바꿔주는 기능을 한다.</p>
</blockquote>
<h3 id="use">use()</h3>
<p><strong>app.use([path,] callback [, callback...])</strong>
지정된 경로에 지정된 미들웨어 함수를 마운드 한다. 미들웨어 함수는 요청된 경로의 기준이 일치할 때 실행된다.
use 메서드는 모든 HTTP 메서드에 대해 요청 주소만 일치하면 실행되지만, get, post, put, patch, delete 같은 메서드는 주소 뿐만 아니라 HTTP 메서드까지 일치하는 요청일 때만 실행된다.
<a href="https://expressjs.com/en/api.html#app.use/">https://expressjs.com/en/api.html#app.use/</a></p>
<h3 id="routerget">router.get()</h3>
<ol>
<li>set으로 설정한 name으로 value 값을 반환한다.</li>
</ol>
<p><strong>app.get(name)</strong>
2. 지정된 콜백 함수를 사용하여 HTTP GET 요청을 지정된 경로로 라우팅한다.
<strong>app.get(path, callback [, callback ...])</strong>
<a href="https://expressjs.com/en/api.html#app.get/">https://expressjs.com/en/api.html#app.get/</a></p>
<h3 id="post">post()</h3>
<p><strong>app.post(path, callback [, callback ...])</strong>
지정된 콜백 함수를 사용하여 HTTP POST 요청을 지정된 경로로 라우팅한다.
<a href="https://expressjs.com/en/api.html#app.post.method/">https://expressjs.com/en/api.html#app.post.method/</a></p>
<h3 id="route">route()</h3>
<p><strong>app.route(path)</strong>
선택적인 미들웨어로 HTTP 동사를 처리하는 데 사용할 수 있는 단일 경로의 인스턴스를 반환한다. app.route()중복 경로 이름(오타 오류)을 방지하는 데 사용한다.</p>
<p><strong>사용예</strong></p>
<pre><code class="language-javascript">app.get(&quot;/edit&quot;, protectorMiddleware, getEdit);
app.post(&quot;/edit&quot;, protectorMiddleware, postEdit);</code></pre>
<pre><code class="language-javascript">app.route(&quot;/edit&quot;).all(protectorMiddleware).get(getEdit).post(postEdit);</code></pre>
<p>두 코드가 같은 역할을 하는데 route를 사용함으로 간결해지고 경로를 잘 못 써서 생기는 오류를 방지할 수 있다.
<a href="http://expressjs.com/en/guide/routing.html#app-route/">http://expressjs.com/en/guide/routing.html#app-route/</a></p>
<h3 id="put">put()</h3>
<p><strong>app.put(path, callback [, callback ...])</strong>
지정된 콜백 함수를 사용하여 HTTP PUT 요청을 지정된 경로로 라우팅한다.
데이터를 업데이트 할 때 사용되는 method 라고 한다.</p>
<h3 id="delete">delete()</h3>
<p><strong>app.delete(path, callback [, callback ...])</strong>
지정된 콜백 함수를 사용하여 HTTP DELETE 요청을 지정된 경로로 라우팅한다.
요청된 자원을 삭제할 것을 요청함.</p>
<h3 id="render">render()</h3>
<p><strong>res.render(view [, locals] [, callback])</strong>
a를 렌더링 view하고 렌더링된 HTML 문자열을 클라이언트에 보낸다.
view인수는 렌더링 할 뷰 파일의 파일 경로 문자열이다. 이것은 절대 경로이거나 views설정 에 대한 상대 경로일 수 있다. 경로에 파일 확장자가 없으면 view engine설정에 따라 파일 확장자가 결정된다.</p>
<p><strong>사용예</strong></p>
<pre><code class="language-javascript">export const getJoin = (req, res) =&gt;
  res.render(&quot;users/join&quot;, { pageTitle: &quot;Join&quot; });</code></pre>
<p>users 경로에 있는 join 뷰 파일을 렌더링한다.
{ pageTitle: &quot;Join&quot; } 식으로 오브젝트를 보내주면 해당 뷰파일에서 보낸 인자를 사용할 수 있다.
<a href="http://expressjs.com/en/5x/api.html#res.render/">http://expressjs.com/en/5x/api.html#res.render/</a></p>
<h3 id="redirect">redirect()</h3>
<p><strong>res.redirect([status,] path)</strong>
HTTP 상태 코드에 해당하는 양의 정수를 path지정 하여 지정된 URL에서 파생된 URL로 리디렉션한다. 지정하지 않으면 기본값은 302이다.
리디렉션은 다른 사이트로 리디렉션하기 위한 정규화된 URL일 수 있다.</p>
<pre><code class="language-javascript">res.redirect(&#39;/foo/bar&#39;)
res.redirect(&#39;http://example.com&#39;)
res.redirect(301, &#39;http://example.com&#39;)
res.redirect(&#39;../login&#39;)</code></pre>
<p><strong>사용예</strong></p>
<pre><code class="language-javascript">export const postLogin = async (req, res) =&gt; {
  const { username, password } = req.body;
  const pageTitle = &quot;Login&quot;;
  const user = await User.findOne({ username, socialOnly: false });
  if (!user) {
    return res.status(400).render(&quot;users/login&quot;, {
      pageTitle,
      errorMessage: &quot;An account with this username does not exists.&quot;,
    });
  }
  const ok = await bcrypt.compare(password, user.password);
  if (!ok) {
    return res.status(400).render(&quot;users/login&quot;, {
      pageTitle,
      errorMessage: &quot;Wrong password&quot;,
    });
  }
  req.session.loggedIn = true;
  req.session.user = user;
  return res.redirect(&quot;/&quot;);
};</code></pre>
<p>로그인 페이지에서 post메소드로 받을때 실행되는 코드이다.
로그인 실패시 render() 를 통해 에러 메시지와 함께 login 페이지로 이동하고 로그인 성공시 홈페이지로 리다이렉션 된다. 
<a href="http://expressjs.com/en/5x/api.html#res.redirect/">http://expressjs.com/en/5x/api.html#res.redirect/</a></p>
<h3 id="send">send()</h3>
<p><strong>res.send([body])</strong>
HTTP 응답을 보낸다.</p>
<pre><code class="language-javascript">res.send(Buffer.from(&#39;whoop&#39;))
res.send({ some: &#39;json&#39; })
res.send(&#39;&lt;p&gt;some html&lt;/p&gt;&#39;)
res.status(404).send(&#39;Sorry, we cannot find that!&#39;)
res.status(500).send({ error: &#39;something blew up&#39; })</code></pre>
<p><a href="http://expressjs.com/en/5x/api.html#res.send/">http://expressjs.com/en/5x/api.html#res.send/</a></p>
<h3 id="expressurlencoded">express.urlencoded()</h3>
<p><strong>express.urlencoded([options])</strong></p>
<ul>
<li>Parameter: The options parameter contains various property like extended, inflate, limit, verify etc.</li>
<li>Return Value: It returns an Object.</li>
</ul>
<p>Express에 내장된 미들웨어 기능이다. urlencoded 페이로드로 들어오는 요청을 구문 분석하고 body-parser를 기반으로 한다.</p>
<h4 id="옵션-extended">옵션 extended</h4>
<p>extended 는 중첩된 객체표현을 허용할지 말지를 정하는 것이다. 객체 안에 객체를 파싱할 수 있게하려면 true.</p>
<blockquote>
<p>이 옵션은 함께 URL 인코딩 된 데이터를 분석하는 사이에 선택할 수 있습니다 querystring라이브러리 ( false) 또는 qs라이브러리 ( true). &quot;확장된&quot; 구문을 사용하면 리치 개체 및 배열을 URL 인코딩 형식으로 인코딩할 수 있으므로 URL 인코딩을 통해 JSON과 같은 경험을 할 수 있습니다.</p>
</blockquote>
<p>참고해서 보자.
<a href="http://expressjs.com/en/5x/api.html#express.urlencoded">http://expressjs.com/en/5x/api.html#express.urlencoded</a>
<a href="https://joonsei.tistory.com/22">https://joonsei.tistory.com/22</a>
<a href="https://backback.tistory.com/336">https://backback.tistory.com/336</a>
<a href="https://velog.io/@yejinh/express-%EB%AF%B8%EB%93%A4%EC%9B%A8%EC%96%B4-bodyParser-%EB%AA%A8%EB%93%88">https://velog.io/@yejinh/express-%EB%AF%B8%EB%93%A4%EC%9B%A8%EC%96%B4-bodyParser-%EB%AA%A8%EB%93%88</a></p>
<p><strong>사용예</strong></p>
<pre><code class="language-javascript">app.use(express.urlencoded({ extended: true }));</code></pre>
<p><code>req.body</code> 를 사용하기 위해 해당코드를 사용하였다.
<a href="https://nodejs.dev/learn/get-http-request-body-data-using-nodejs/">https://nodejs.dev/learn/get-http-request-body-data-using-nodejs/</a></br></p>
<p>요청 본문에 제출 된 키-값 데이터 쌍을 포함한다. 기본적으로 이는 정의되어 있지 않으며 express.json(), express.urlencoded()와 같은 미들웨어를 사용해야한다.
req.body는 body-parser를 사용하기 전에는 default 값으로 Undefined 설정되기 때문에 body-parser를 사용하여 해결해야 오류를 뿜지 않는다.</p>
<p>Express 4.16.0버전 부터 body-parser의 일부 기능이 익스프레스에 내장되어 사용이 가능하다한다.
<a href="https://studyingych.tistory.com/34/">https://studyingych.tistory.com/34/</a></p>
<h1 id="reference">Reference</h1>
<p><a href="https://www.npmjs.com/package/express/">https://www.npmjs.com/package/express/</a>
<a href="https://developer.mozilla.org/ko/docs/Learn/Server-side/Express_Nodejs/Introduction/">https://developer.mozilla.org/ko/docs/Learn/Server-side/Express_Nodejs/Introduction/</a>
<a href="https://wikibook.co.kr/article/what-is-expressjs/">https://wikibook.co.kr/article/what-is-expressjs/</a>
<a href="https://velog.io/@madpotato1713/JAVASCRIPT-express%EB%9E%80/">https://velog.io/@madpotato1713/JAVASCRIPT-express%EB%9E%80/</a>
<a href="https://serendipity24.tistory.com/148/">https://serendipity24.tistory.com/148/</a>
<a href="https://stackoverflow.com/questions/29960764/what-does-extended-mean-in-express-4-0/45690436#45690436/">https://stackoverflow.com/questions/29960764/what-does-extended-mean-in-express-4-0/45690436#45690436/</a>
<a href="https://expressjs.com/en/guide/writing-middleware.html/">https://expressjs.com/en/guide/writing-middleware.html/</a>
<a href="https://expressjs.com/en/api.html/">https://expressjs.com/en/api.html/</a>
<a href="https://backback.tistory.com/341/">https://backback.tistory.com/341/</a>
<a href="https://javaplant.tistory.com/18/">https://javaplant.tistory.com/18/</a>
<a href="https://sjh836.tistory.com/154/">https://sjh836.tistory.com/154/</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Babel]]></title>
            <link>https://velog.io/@dev_space/Babel</link>
            <guid>https://velog.io/@dev_space/Babel</guid>
            <pubDate>Mon, 04 Oct 2021 07:38:22 GMT</pubDate>
            <description><![CDATA[<h1 id="babel이란">Babel이란?</h1>
<ul>
<li>JavaScript 컴파일러다.</li>
<li>최신 버전의 JavaScript로 코드를 작성하는데 도움이 되는 도구이다.</li>
<li>지원되는 환경이 특정 기능을 기본적으로 지원하지 않는 경우 Babel은 이러한 기능을 지원되는 버전으로 컴파일하는데 도움을 준다.</li>
<li>현재 및 이전 브라우저 또는 환경에서 ECMAScript 2015+ 코드를 이전 버전의 JavaScript로 변환하는 데 주로 사용되는 도구 체인이다.</li>
<li>크로스 브라우징 이슈를 해결하기 위해 생겨난 툴이다.</li>
<li>ES6+ 버전의 JavaScript나 TypeScript, JSX 등 다른 언어로 분류되는 언어들에 대해서도 모든 브라우저에서 동작할 수 있도록 호환성을 지켜준다.</li>
</ul>
<blockquote>
<p><strong>크로스 브라우징</strong>
다른 기종 혹은 플랫폼에 따라 달리 구현되는 기술을 비슷하게 만듦과 동시에 어느 한쪽에 최적화 되어 치우치지 않도록 공통 요소를 사용하여 웹 페이지를 제작하는 기법. 또한, 지원할 수 없는 다른 웹 브라우저를 위한 장치를 구현하여 모든 웹 브라우저 사용자가 방문했을 때 정보로서의 소외감을 느끼지 않도록 하는 방법론적 가이드를 의미하는 것이다.
<strong>브라우저마다 렌더링 엔진이 다르기 때문에 필요하다.</strong></p>
</blockquote>
<blockquote>
<p><strong>ES6+</strong>
ES는 ECMAScript의 줄임말이며 뒤에는 버전이라고 생각하면된다. ECMAScript2015를 ES6라고 하며, ES6 이후 버전을 통칭하여 “ES6+” 라고 한다. </p>
</blockquote>
<h2 id="정리">정리</h2>
<p>JavaScript의 버전업그레이드로 인한 최신 문법을 가진 ES6+ 코드를 런타임 환경인 브라우저가 인식하고 실행하는데 문제가 생김.
효율성과 유지보수등의 이유로 코드는 ES6+ 로 구현해야 하는데 실행환경인 모든 브라우저가 최신 문법을 다 지원하지 못하기에 버전 차이가 발생하게 된다. 이러한 문제를 해결해 주는게 Babel이다. ES6+ 로 작성된 코드를 브라우저가 인식할 수 있는 ES5로 변환시켜주는 Transpiler 이다.(TypeScript, JSX 는 아직 제대로 사용해보질 않아서 잘 모르겠다.)</p>
<blockquote>
<p><strong>Babel은 Compiler VS Transpiler?</strong>
공식사이트에는 컴파일러라고 나와있는데 찾다보니 트랜스파일러 라고도 나와있어 뭐가 맞는지 찾아봤는데 Babel은 트랜스파일러 이자 컴파일러 라고 한다.
컴파일은 작성된 코드를 컴퓨터의 저수준 실행 파일(일반적으로 기계어 코드)로 바꾸는 포괄적인 용어이며, 트랜스파일은 때때로 소스-투-소스 컴파일러 라고도 하므로 트랜스파일러가 컴파일러의 한 유형 이기 때문에 babel이 컴파일러라고 주장할 수 있다고 한다.
<a href="https://stackoverflow.com/questions/43968748/is-babel-a-compiler-or-transpiler/">https://stackoverflow.com/questions/43968748/is-babel-a-compiler-or-transpiler/</a>
<a href="https://dev.to/kealanparr/compiling-vs-transpiling-3h9i/">https://dev.to/kealanparr/compiling-vs-transpiling-3h9i/</a></p>
</blockquote>
<h2 id="사용하기">사용하기</h2>
<h3 id="nodejs-에서-babel">Node.js 에서 Babel</h3>
<p>Node.js 의 경우 최신 버전을 사용한다면 거의 왠만한 ES6 문법은 도입이 되어 있지만, 아직 CommonJS 기반 모듈 시스템을 사용하기 때문에 ES6의 <code>import</code>나 <code>export</code> 와 같은 키워드는 디폴트로 지원되지 않고 있다. (다른 방법도 있다고 함. <a href="https://nodejs.org/api/esm.html#esm_import_specifiers">ECMAScript modules</a>)
이러한 예외를 해결하기 위해 작성한 코드를 NodeJS 런타임이 실행가능한 형태로 변환해줘야 한다.</p>
<blockquote>
<p><strong>--save-dev</strong>
설치된 모듈이 package.json 의 devDependencies 에 표시된다.
dependencies는 프로젝트에 필요한것을 나타내고 devDependencies는 개발자에게 필요한것을 나타낸다고 한다. dependencies에 다 표시해도 상관은 없지만 어떤 패키지가 무슨 일을 하는지 알기 위한 우리를 위한 구분이다.</p>
</blockquote>
<ol>
<li><p><code>npm install --save-dev @babel/core</code>
Babel 핵심 패키지를 설치한다.</p>
</li>
<li><p>babel.config.json 구성 파일 생성</p>
<pre><code class="language-JSON">{
&quot;presets&quot;: [&quot;@babel/preset-env&quot;]
}</code></pre>
</li>
<li><p><code>npm install @babel/preset-env --save-dev</code>
Babel 설정은 여러 플러그인을 스스로 조합하거나 미리 준비된 프레셋을 사용할 수 있다. <code>env</code> 라는 가장 범용적으로 사용되는 프리셋을 사용하는데 이는 ES2015 이상의 최신 JavaScript 문법으로 작성된 코드를 해석할 수 있다. <a href="https://babeljs.io/docs/en/babel-preset-env">env 사전 설정</a></p>
<blockquote>
<p><strong>사용</strong>
<code>require(&quot;@babel/core&quot;).transform(&quot;code&quot;, {
presets: [&quot;@babel/preset-env&quot;],
});</code>
위와 같은 코드를 이용해서 사용할 수도 있지만, 추가로 모듈을 설치해 편리하게 사용하자.</p>
</blockquote>
</li>
<li><p><code>npm install @babel/node --save-dev</code>
<code>babel-node</code> 라는 명령어를 사용할 수 있게된다. nodeJS 가 실행될 때 babel도 같이 적용되서 실행이 된다.</p>
<h4 id="nodemon">nodemon</h4>
<p>우리가 만든 파일이 수정되는걸 감시해주는 패키지로 코드를 수정할 때마다 알아서 재시작을 해주어 수정할 때마다 node를 재실행해줘야 하는 불편함을 없애준다.
<code>npm install nodemon --save-dev</code>
설치 후
package.json 의 scripts 부분을 수정해준다.</p>
<pre><code class="language-JSON">&quot;scripts&quot;: {
 &quot;dev&quot;: &quot;nodemon --exec babel-node index.js&quot;
}</code></pre>
<p>이러면 <code>npm run dev</code> 명령어를 통해 nodemon 을 실행할 수 있다.
(다른 사용방법 : <a href="https://babeljs.io/setup#installation/">https://babeljs.io/setup#installation/</a>)</p>
</li>
</ol>
<h2 id="reference">Reference</h2>
<p><a href="https://babeljs.io/docs/en/index.html/">https://babeljs.io/docs/en/index.html/</a>
<a href="https://github.com/babel/babel/">https://github.com/babel/babel/</a>
<a href="https://velog.io/@seochanh/00003#:~:text=%ED%81%AC%EB%A1%9C%EC%8A%A4%20%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A7%95-,%ED%81%AC%EB%A1%9C%EC%8A%A4%20%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A7%95%EC%9D%B4%EB%9E%80%3F,%ED%95%98%EB%8A%94%20%EA%B8%B0%EB%B2%95%EC%9D%84%20%EB%A7%90%ED%95%98%EB%8A%94%20%EA%B2%83%EC%9D%B4%EB%8B%A4./">https://velog.io/@seochanh/00003#:~:text=%ED%81%AC%EB%A1%9C%EC%8A%A4%20%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A7%95-,%ED%81%AC%EB%A1%9C%EC%8A%A4%20%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A7%95%EC%9D%B4%EB%9E%80%3F,%ED%95%98%EB%8A%94%20%EA%B8%B0%EB%B2%95%EC%9D%84%20%EB%A7%90%ED%95%98%EB%8A%94%20%EA%B2%83%EC%9D%B4%EB%8B%A4./</a>
<a href="https://devowen.com/293/">https://devowen.com/293/</a>
<a href="https://mwoo526.tistory.com/32/">https://mwoo526.tistory.com/32/</a>
<a href="https://www.daleseo.com/js-babel-node//">https://www.daleseo.com/js-babel-node//</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Node.js]]></title>
            <link>https://velog.io/@dev_space/Node.js</link>
            <guid>https://velog.io/@dev_space/Node.js</guid>
            <pubDate>Sun, 03 Oct 2021 16:01:12 GMT</pubDate>
            <description><![CDATA[<h1 id="nodejs란">Node.js란?</h1>
<p>Node.js®는 Chrome의 V8 JavaScript 엔진을 기반으로 하는 JavaScript 런타임 입니다.
비동기식 이벤트 기반 JavaScript 런타임인 Node.js는 확장 가능한 네트워크 애플리케이션을 빌드하도록 설계되었다. -<a href="https://nodejs.org/en/">node.js</a>
Node.js는 확장성 있는 네트워크 애플리케이션(특히 서버 사이드) 개발에 사용되는 소프트웨어 플랫폼이다. 작성 언어로 자바스크립트를 활용하며 논블로킹(Non-blocking) I/O와 단일 스레드 이벤트 루프를 통한 높은 처리 성능을 가지고 있다.
내장 HTTP 서버 라이브러리를 포함하고 있어 웹 서버에서 아파치 등의 별도의 소프트웨어 없이 동작하는 것이 가능하며 이를 통해 웹 서버의 동작에 있어 더 많은 통제를 가능케 한다. -<a href="https://ko.wikipedia.org/wiki/Node.js">위키백과</a></p>
<h2 id="특징">특징</h2>
<h3 id="v8-javascript-엔진을-기반으로-하는-javascript-런타임">V8 JavaScript 엔진을 기반으로 하는 JavaScript 런타임</h3>
<h4 id="v8">V8</h4>
<p>V8은 웹 브라우저를 만드는 데 기반을 제공하는 오픈 소스 자바스크립트 엔진이다. 구글 크롬 브라우저와 안드로이드 브라우저에 탑재되어 있다. V8로 줄여 불리기도한다.
V8은 자바스크립트를 <a href="https://ko.wikipedia.org/wiki/%EB%B0%94%EC%9D%B4%ED%8A%B8%EC%BD%94%EB%93%9C">바이트코드</a>(bytecode)로 컴파일하고 실행하는 방식을 사용한다.추가적인 속도향상을 위해 인라인 캐싱(inline caching)과 같은 최적화 기법을 적용하였다. -<a href="https://ko.wikipedia.org/wiki/V8_(%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8_%EC%97%94%EC%A7%84)">위키백과</a>
구글에서 제작한 자바스크립트 엔진이다.</p>
<h4 id="런타임">런타임</h4>
<p>프로그래밍 언어가 구동되는 환경. 즉 &quot;어떤 프로그래밍 언어가 동작 할 수 있는 프로그램&quot;</p>
<h3 id="non-blocking-io-이벤트-기반-비동식-방식">non-blocking I/O 이벤트 기반 비동식 방식</h3>
<h4 id="논블로킹">논블로킹</h4>
<p>다른 주체의 작업과 관계없이 자신의 작업을 계속한다.</p>
<h4 id="비동기">비동기</h4>
<p>동시에 일어나지 않는다를 의미한다. 요청과 결과가 동시에 일어나지 않을거라는 약속이다.
노드 사이의 작업 처리 단위를 동시에 맞추지 않아도 된다.</p>
<ul>
<li>장점
결과가 주어지는데 시간이 걸리더라도 그 시간 동안 다른 작업을 할 수 있으므로 자원을 효율적으로 사용할 수 있다.</li>
<li>단점
동기보다 복잡하다.<h4 id="이벤트-루프">이벤트 루프</h4>
</li>
<li>이벤트 루프는 여러 이벤트가 동시에 발생했을 때 어떤 순서로 콜백함수를 호출 할지를 이벤트 루프가 판단한다.</li>
<li>노드는 이벤트가 종료될 때까지 이벤트 처리를 위한 작업을 반복하므로 루프 라고 부른다.</li>
<li>태스크가 들어오길 기다렸다가 태스크가 들어오면 이를 처리하고, 처리할 태스크가 없는 경우엔 잠드는, 끊임없이 돌아가는 자바스크립트 내 루프이다.</li>
</ul>
<p>글만 봐서는 이해가 잘 가지 않아 따로 정리를 해야겠다.</p>
<h3 id="단일-스레드">단일 스레드</h3>
<ul>
<li>하나의 프로세스에서 하나의 스레드 실행</li>
<li>하나의 레지스터와 스택으로 표현<blockquote>
<p><strong>단일 스레드 이벤트 루프 기반 비동기방식(Non-blocking)</strong>
하나의 스레드가 request를 받으면 바로 다음 처리에 요청을 보내놓고 다른 작업을 처리하다가 먼저 요청한 작업이 끝나면 이벤트를 받아서 응답을 보낸다.
동시 request가 오더라도 처리가 완료될때까지 기다리지 않아도 되기 때문에 서버 부하가 적다.</p>
</blockquote>
</li>
</ul>
<h2 id="장점">장점</h2>
<ul>
<li>자바스크립트를 동일하게 사용해서 서버단 로직을 처리할 수 있다.</li>
<li>Non-blocking I/O와 단일 스레드 이벤트 루프를 통한 높은 처리 성능</li>
<li>이벤트 기반 비동기방식이라 서버 무리가 적다.</li>
<li>다양한 모듈(패키지) 제공</li>
<li>npm 을 이용해 자신이 필요한 라이브러리와 패키지를 검색해서 설치하고 사용할 수 있어 효율성이 좋다.</li>
<li>구글이 만드는 JavaScript 엔진을 사용하는데 구글은 V8 엔진 성능 업그레이드를 계속 하고있다.</li>
<li>데이터를 실시간으로 다루는 애플리케이션이나 싱글페이지 애플리케이션, 입출력이 잦은 애플리케이션을 개발할 때 뛰어난 효율성을 발휘한다.<h2 id="단점">단점</h2>
</li>
<li>이벤트 기반 비동기방식이라 서버단 로직이 복잡한 경우 콜백함수의 늪에 빠질 수 있다.
예를 들어, 한번의 요청에 대해 DB에서 조회한 결과값에 따라 다른 로직을 처리해야 하며, 이런 로직이 여러개인 경우 콜백함수 늪 (Callback Hell) 에 빠진다.</li>
<li>단일 스레드이기 때문에 하나의 작업 자체가 시간이 많이 걸리면 전체 시스템의 성능이 아주 급격하게 나빠지므로 CPU사용률이 높은 애플리케이션에서 Node.js사용을 권장하지 않는다.</li>
<li>코드가 수행되어야 코드에 에러가 있는지 알 수 있으며, 에러가 날 경우 프로세스가 내려가기 때문에 테스트가 엄청 중요하다. 반드시 모든 케이스에 대해 소스코드를 검증해야 한다.<h2 id="주의">주의</h2>
</li>
<li>V8 엔진을 기반으로 하는데, 이 V8 엔진은 Garbage collection  기반의 메모리 관리를 하기 때문에, GC시 CPU 사용률이 Spike를 치면서 순간적으로 서버를 멈추게할 수 있다는 문제점을 가지고 있다.</li>
<li>node.js를 사용한 사람들에게서 들려오는 가장 많은 경험담은 자바스크립트 자체를 배우는 것보다는 프로그래밍 컨셉을 기존의 컨셉에서 Event 기반의 프로그래밍 컨셉으로 전환하는데 많은 시간이 걸렸다고 한다. 코드를 순차적으로 실행하는 것이 아니라, 비동기 방식으로 이벤트를 보내놓고, 그 응답에 대한 이벤트가 오면 핸들러를 통해서 처리 하는 형식이기 때문에, 기존 서버 프로그래밍 모델과는 많은 차이를 보인다.</li>
<li>개발 관점에서는 빠르고 쉬운 장점이 있지만, 반대로 운영 관점에서는 테스트, 장애 대응, 디버깅등에 대해서는 신경써야 할 부분이 훨씬 더 많다.</li>
<li><a href="https://bcho.tistory.com/876">조대협의 블로그</a><h2 id="정리">정리</h2>
</li>
<li>이전에는 JavaScript 런타임이 브라우저 밖에 없었지만, Node.js 라는 새로운 JavaScript 런타임이 나온것이다.JavaScript 가 브라우저가 아닌 곳에서 실행될 수 있으니, JavaScript 를 이용해서 웹페이지 뿐만 아니라 서버와 같은 다른 프로그램을 만들 수 있다.</li>
<li>Node.js는 백엔드, 웹 서버, 서버 사이드 스크립트 언어가 아니라 JavaScript 실행 환경에 불과하다.</li>
<li>다양한 모듈을 사용할 수 있고 간단한 로직과 빠른 개발을 할 수 있는 등 다양한 장점이 있지만, 운영 관점에서는 테스트, 장애 대응, 디버깅등 약점이 있다.<h1 id="reference">Reference</h1>
<a href="https://nodejs.org/en/about/">https://nodejs.org/en/about/</a>
<a href="https://ko.wikipedia.org/wiki/Node.js/">https://ko.wikipedia.org/wiki/Node.js/</a>
<a href="https://junspapa-itdev.tistory.com/3/">https://junspapa-itdev.tistory.com/3/</a>
<a href="https://ko.wikipedia.org/wiki/V8_(%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8_%EC%97%94%EC%A7%84)/">https://ko.wikipedia.org/wiki/V8_(%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8_%EC%97%94%EC%A7%84)/</a>
<a href="https://xhwogusxh.tistory.com/88/">https://xhwogusxh.tistory.com/88/</a>
<a href="https://perfectacle.github.io/2017/06/18/what-is-node-js/">https://perfectacle.github.io/2017/06/18/what-is-node-js/</a>
<a href="https://hanamon.kr/nodejs-%EA%B0%9C%EB%85%90-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0/">https://hanamon.kr/nodejs-%EA%B0%9C%EB%85%90-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0/</a>
<a href="https://meetup.toast.com/posts/89/">https://meetup.toast.com/posts/89/</a>
<a href="https://ko.javascript.info/event-loop/">https://ko.javascript.info/event-loop/</a>
<a href="https://private.tistory.com/24/">https://private.tistory.com/24/</a>
<a href="https://medium.com/@yeon22/node-js-node-js%EB%9E%80-410ae3749c56/">https://medium.com/@yeon22/node-js-node-js%EB%9E%80-410ae3749c56/</a>
<a href="https://deveric.tistory.com/99/">https://deveric.tistory.com/99/</a>
<a href="https://bcho.tistory.com/876/">https://bcho.tistory.com/876/</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[GRID]]></title>
            <link>https://velog.io/@dev_space/grid</link>
            <guid>https://velog.io/@dev_space/grid</guid>
            <pubDate>Thu, 30 Sep 2021 17:15:20 GMT</pubDate>
            <description><![CDATA[<p>flex box 로는 그리드 형태를 만들기 어렵다 그러므로 CSS grid 를 공부한다.</p>
<h2 id="distplay-grid">distplay: grid</h2>
<p>그리드를 사용할 요소의 부모 요소에 선언한다.</p>
<h2 id="grid-template">grid-template</h2>
<h3 id="columns">columns</h3>
<p>column 에 위치한 item 들의 위치를 잡아준다.</p>
<pre><code class="language-css">grid-template-columns: 250px 250px 250px;</code></pre>
<p>3 * 3 그리드를 만든다고 할때 부모 요소에 저렇듯 width 값을 설정해서 자리를 잡아줄 수 있다.
3개의 열을 설정한 것이다.</p>
<h3 id="rows">rows</h3>
<p>row 에 위치한 item 들의 위치를 잡아준다.</p>
<pre><code class="language-css">grid-template-rows: 100px 50px 300px;</code></pre>
<p>column 과 똑같은 방식으로 설정할 수 있다. 3 개의 행을 설정한 것이다.</p>
<h3 id="auto-repeat">auto, repeat()</h3>
<p>grid-template-rows 또는 grid-template-columns 은 크기를 한 라인씩 지정도 가능하지만 한번에 지정해줄 수도 있다.
repeat(), auto 가 그 역할을 하는데</p>
<pre><code class="language-css">grid-template-columns: repeat(4, 200px);
grid-template-rows: 100px repeat(2, 200px) 100px;</code></pre>
<p>우선 repeat() 이다. 괄호 안에 해당 설정을 지정해줄 라인 개수를 적고, 설정 값을 넣어준다.
위의 columns 의 경우 4 개의 열의 너비를 200px 로 정한것이다.
rows 는 
첫 번째 라인은 100px
두 번째, 세 번째 라인은 200px
네 번째 라인은 100px
로 부분적으로 공통된 값을 줄 수도 있다.</p>
<h4 id="auto">auto</h4>
<pre><code class="language-css">grid-template-columns: auto 200px;</code></pre>
<p>특정 값을 정해주면 창의 크기에 따라 빈공간도 생길텐데 auto 로 설정하면 자동으로 값을 변환한다.
위의 코드는 2번째 라인은 200px 로 하고 나머지를 auto 로 설정한 것이다.</p>
<h2 id="gap">gap</h2>
<p>각 item 간의 간격을 설정할 수 있다.</p>
<pre><code class="language-css">gap: 10px;</code></pre>
<p>item 들 간에 위 아래 간격이 10px 로 동일하게 맞춰진다.
위 아래 각각 맞춰줄 수도 있다.</p>
<h3 id="column-gap">column-gap</h3>
<p>column 방향의 item 들간의 간격을 설정한다.</p>
<pre><code class="language-css">column-gap: 10px;</code></pre>
<h3 id="row-gap">row-gap</h3>
<p>row 방향의 item 들간의 간격을 설정한다.</p>
<pre><code class="language-css">row-gap: 10px;</code></pre>
<h2 id="grid-template-areas">grid-template-areas</h2>
<p>그리드 영역의 셀을 수립하고 그들에게 이름을 할당한다.</p>
<pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
&lt;head&gt;
    &lt;link rel=&quot;stylesheet&quot; href=&quot;styles.css&quot;&gt;
    &lt;title&gt;(S)CSS Masterclass&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;div class=&quot;grid&quot;&gt;
        &lt;div class=&quot;header&quot;&gt;&lt;/div&gt;
        &lt;div class=&quot;content&quot;&gt;&lt;/div&gt;
        &lt;div class=&quot;nav&quot;&gt;&lt;/div&gt;
        &lt;div class=&quot;footer&quot;&gt;&lt;/div&gt;
    &lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre>
<pre><code class="language-css">.grid {
    display: grid;
    grid-template-columns: auto 200px;
    grid-template-rows: 100px repeat(2, 200px) 100px;
    grid-template-areas: 
    &quot;header header header header&quot;
    &quot;content content content nav&quot;
    &quot;content content content nav&quot;
    &quot;footer footer footer footer&quot;
    ;
}

.header {
    background-color: #2ecc71;
    grid-area: header;
}

.content {
    background-color: #3498db;
    grid-area: content;
}

.nav {
    background-color: #8e44ad;
    grid-area: nav;
}

.footer {
    background-color: #f38c12;
    grid-area: footer;
}</code></pre>
<p>grid-template-areas 속성으로 각 영역의 이름을 지정해주고
grid-area 속성을 사용하여 그리드 항목의 이름을 지정한 다음 grid-template-areas 속성의 이름을 참조할 수 있다.
이름을 지정하면 지정된 이름에 맞게 그리드 항목이 grid-template-areas 영역에 표시된다.
<img src="https://images.velog.io/images/dev_space/post/946863bb-0d3a-4b90-ad61-392aef7099fb/2021-09-11_5.35.29.png" alt=""></p>
<pre><code class="language-css">&quot;header header header header&quot;
&quot;content content . nav&quot;
&quot;content content . nav&quot;
&quot;footer footer footer footer&quot;</code></pre>
<p><img src="https://images.velog.io/images/dev_space/post/d05086bc-6c36-4317-9ff0-74c964c22672/2021-09-11_5.36.46.png" alt="">
. 을 넣으면 빈공간으로 된다.</p>
<h2 id="grid-column-start-grid-column-end">grid-column-start, grid-column-end</h2>
<p>그리드 항목의 가로 위치 및 영역을 지정해주는 속성이다. 
column 라인을 기준으로 지정하며 start 는 시작 지점을 end 는 끝 지점을 지정한다.
<img src="https://images.velog.io/images/dev_space/post/989b86d5-bd83-43e8-90ea-c65708b977ce/2021-09-11_5.57.14.png" alt=""></p>
<pre><code class="language-css">.header {
    background-color: #2ecc71;
    grid-column-start: 1;
    grid-column-end: 5;
}</code></pre>
<p>상단의 초록색 부분을 지정해준 코드다.</p>
<h2 id="grid-row-start-grid-row-end">grid-row-start, grid-row-end</h2>
<p>그리드 항목의 세로 위치 및 영역을 지정해주는 속성이다. 
row 라인을 기준으로 지정하며 start 는 시작 지점을 end 는 끝 지점을 지정한다.
<img src="https://images.velog.io/images/dev_space/post/1deeef74-2095-4646-abd5-c457646646b4/2021-09-11_6.00.38.png" alt=""></p>
<pre><code class="language-css">.content {
    background-color: #3498db;
    grid-column-start: 1;
    grid-column-end: 4;
    grid-row-start: 2;
    grid-row-end: 4;
}</code></pre>
<p>중앙의 파란색 영역을 지정해준것이다.</p>
<h2 id="grid-column-grid-row">grid-column, grid-row</h2>
<p>start 와 end 를 합춰놓은 것이라 할 수 있다.
grid-column start / end 형식이라 할 수 있다.
<img src="https://images.velog.io/images/dev_space/post/80b668d5-bd2a-439c-a79f-e42b4e02743c/2021-09-11_6.30.50.png" alt=""></p>
<pre><code class="language-css">.header {
    background-color: #2ecc71;
    grid-column: 1 / -1;
}</code></pre>
<p>맨 위 초록색 부분이다.</p>
<ol>
<li>grid-column-start: 1;
grid-column-end: 5;     </li>
<li>grid-column: 1 / 5; </li>
<li>grid-column: 1 / -1;
위 코드가 다 같다.</li>
</ol>
<p>-1 은 그리드의 끝 라인을 뜻한다. 라인의 끝에서 부터 차례대로 -1, -2, -3 에 해당한다.</p>
<pre><code class="language-css">.footer {
    background-color: #f38c12;
    grid-column: span 4;
}</code></pre>
<p>맨 아래 주황색 부분이다.
span 을 통해 cell 의 개수를 지정해서 나타낼 수 도 있다.
시작 위치를 지정해줄 필요가 있을때는 grid-column: 4 / span; 와 같은 형식으로도 사용할 수 있다.</p>
<h2 id="grid-area">grid-area</h2>
<p>/ 로 구분지어 grid-row-start, grid-column-start, grid-row-end, grid-column-end 순으로 입력이 가능하다.</p>
<h2 id="order">order</h2>
<p>그리드 요소들이 <strong><code>grid-area</code></strong>, <strong><code>grid-column</code></strong>, <strong><code>grid-row</code></strong>, 기타 등을 사용하지 않고, 표시될 경우 소스코드에 기입된 순서대로 표기됩니다. table 레이아웃에 비해 grid 시스템의 장점인 <strong><code>order</code></strong> 속성을 이용하면 이를 재정의가 가능하다.
기본적으로, 그리드의 모든 요소들은 <strong><code>order</code></strong>의 값이 0이지만, <strong><code>z-index</code></strong>와 같이 양수와 음수의 값 모두 설정이 가능하다.</p>
<h2 id="line-naming">Line Naming</h2>
<p>line 에 이름을 붙여서도 사용이 가능하다.</p>
<pre><code class="language-css">.grid {
    display: grid;
    gap: 10px;
    grid-template-columns: [first-line] 100px [second-line] 100px [third-line] 100px [fourth-line] 100px [fifth-line];
    grid-template-rows: repeat(4, 100px [kimchi-line]);
}</code></pre>
<p>colums 라인에 각각 이름을 준것이다.
row는 kimchi-line 으로 이름은 지정한 것인데, repeat 으로 지정할 경우 첫번째 라인은 지정이 안된다.
2번 라인 부터 kimchi-line 1 이 된다.
예</p>
<pre><code class="language-css">.content {
    background-color: #3498db;
    grid-column: first-line / fourth-line;
    grid-row: kimchi-line 1 / kimchi-line 3;
}</code></pre>
<p>중앙의 파란색 부분을 나타낸 코드이다.</p>
<h2 id="fr">fr</h2>
<p>px 나 % 와 같은 측정 단위이다.
할당된 범위 내에서의 비율을 나타낸다.
<img src="https://images.velog.io/images/dev_space/post/9a38db39-bc44-430f-a28b-ed9bb7f8de4f/2021-09-11_6.52.46.png" alt=""></p>
<pre><code class="language-css">.grid {
    display: grid;
    gap: 10px;
    grid-template-columns: 1fr 2fr 1fr 1fr;
    grid-template-rows: repeat(4, 100px);
}</code></pre>
<p>height 을 지정하지 않고 grid-template-rows 를 repeat(4, 1fr); 로 나타내면 할당된 범위가 없기에 아무것도 표시되지 않는 경우를 가져올 수 있다.</p>
<h2 id="grid-template-1">grid-template</h2>
<p>grid-template은 grid-template-rows와 grid-template-columns를 조합한 단축 속성이다.
예) grid-template: auto 50px / 20% 1fr;
아래와 같은 형식으로도 사용이 가능하다.</p>
<pre><code class="language-css">.grid {
    display: grid;
    gap: 10px;
    height: 50vh;
    grid-template: 
        &quot;header header header header&quot; 1fr
        &quot;content content content nav&quot; 2fr
        &quot;footer footer footer footer&quot; 1fr / 1fr 1fr 1fr 1fr
    ;
}</code></pre>
<p>각 그리드 항목에 grid-area 를 지정해주고 위와 같이 사용이 가능하다.
각 라인 끝에 지정한 수는 가로 길이이고, 마지막 / 뒤에 지정해주는 숫자는 세로 길이이다.</p>
<h2 id="jusify-items">jusify-items</h2>
<p>grid 각 항목들의 가로 위치를 잡아준다.
기본값은 stretch 이다. 부모의 범위만큼 grid 항목을 가로로 늘린다.</p>
<h2 id="align-items">align-items</h2>
<p>grid 각 항목들의 세로 위치를 잡아준다.
기본값은 stretch 이다. 부모의 범위만큼 grid 항목을 세로로 늘린다.</p>
<h2 id="place-items">place-items</h2>
<p>align-items, jusify-items 를 동시에 적용할 수 있다.
place-items: stretch center; (순서대로 align-items, jusify-items 를 의미한다.)
와 같은 형식으로 지정한다.</p>
<h2 id="justify-content-align-content">justify-content, align-content</h2>
<p>justify-items, align-items 는 각각의 grid 항목 내부에 적용되는 거라면 
justify-content, align-content 는 grid 전체를 움직인다.
<img src="https://images.velog.io/images/dev_space/post/685accb7-a076-410e-9a29-d05f6d036368/2021-09-12_1.10.08.png" alt="">
<img src="https://images.velog.io/images/dev_space/post/5e0e7abb-06ac-4867-96e9-9cbe1453b0fe/2021-09-12_1.12.12.png" alt="">
첫 번째 사진은 items
align-items: stretch;
justify-items: center;
두 번째는 content
align-content: space-between;
justify-content: space-between;</p>
<h2 id="place-content">place-content</h2>
<p>align-content, justify-content 를 동시에 적용할 수 있다.
place-items: end center; (순서대로 align-content, justify-content 를 의미한다.)
와 같은 형식으로 지정한다.</p>
<h2 id="justify-self-alingn-self">justify-self, alingn-self</h2>
<p>justify-items, align-items 와 같은 역할을 하는데 전체 적용이 아닌 그리드 항목에 개별적으로 적용이 가능하다.</p>
<h2 id="place-self">place-self</h2>
<p>align-self, justify-self 을 동시에 적용 가능
place-self: start end; (순서대로 align-self, jusify-self 를 의미한다.)
와 같은 형식으로 지정한다.</p>
<h2 id="grid-auto-rows-grid-auto-columns">grid-auto-rows, grid-auto-columns</h2>
<p>추가되는 content 가 몇개가 되든 지정해준 너비로 생성된다.
grid-template-rows 또는 grid-template-columns 와 같이 쓰게되면</p>
<pre><code class="language-css">grid-template-rows: repeat(4, 100px);
grid-auto-rows: 200px;</code></pre>
<p>repeat 으로 설정해준 4 라인 까지는 100px 가 적용되고 이후 생성되는 content 에 대해서는 200px 가 적용된다.</p>
<h2 id="grid-auto-flow">grid-auto-flow</h2>
<p>flex-direction 과 비슷한 역할을 한다.
grid 의 방향을 바꿔준다.
grid-auto-flow: row;
grid-auto-flow: column;</p>
<h2 id="minmax">minmax</h2>
<p>최소 최대값을 설정할 수 있다.
grid-template-columns: repeat(4, minmax(100px, 1fr));
위와 같이 사용하면 최소값은 100px 이면서 1fr 의 값을 갖는다.</p>
<h2 id="auto-fit">auto-fit</h2>
<p>부모의 크기만큼 block 들이 늘어난다.
grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
<img src="https://images.velog.io/images/dev_space/post/b479b6f4-1001-4f57-b158-52659cdb2e54/2021-09-12_7.43.59.png" alt="">
HTML 에 item 을 하나 추가하면 나머지 크기가 줄어들면서 추가된다.</p>
<h2 id="auto-fill">auto-fill</h2>
<p>주어진 크기로 부모의 크기만큼 grid block 공간들이 생성된다. 
grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
<img src="https://images.velog.io/images/dev_space/post/4c469b16-57a3-41f7-a78b-c3436485dd92/2021-09-12_7.38.18.png" alt="">
HTML 에 추가한 item 은 5개 뿐인데 나머지 공간이 일정한 크기의 빈공간으로 채워진다. </p>
<h2 id="max-content-min-content">max-content, min-content</h2>
<p><img src="https://images.velog.io/images/dev_space/post/7962eab4-7e84-4bcd-bca3-7155c9c8d454/2021-09-12_7.54.56.png" alt="">
grid-template-columns: max-content min-content;</p>
<h3 id="max-content">max-content</h3>
<p>content 가 필요한 만큼의 크기로 적용한다. (초록)</p>
<h3 id="min-content">min-content</h3>
<p>content 가 될 수 있는 최소한의 크기로 적용한다. (파랑)</p>
<h3 id="예">예</h3>
<p>grid-template-columns: repeat(5, minmax(max-content, 1fr));
최소값에 max-content 가 들어가서 box 의 최소 사이즈를 content size 로 만들 수 있다. 
grid-template-columns: repeat(auto-fit, minmax(20px, max-content));
최대값에 max-content 가 들어가서 box 를 content size 에 따라 만들 수 있다. </p>
<h2 id="grid-game">grid game</h2>
<p><a href="http://cssgridgarden.com/">http://cssgridgarden.com/</a></p>
<h1 id="reference">Reference</h1>
<p><a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout/Grid_Template_Areas">https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout/Grid_Template_Areas</a>
<a href="https://nomadcoders.co/css-layout-masterclass/lobby">https://nomadcoders.co/css-layout-masterclass/lobby</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[세션]]></title>
            <link>https://velog.io/@dev_space/%EC%84%B8%EC%85%98</link>
            <guid>https://velog.io/@dev_space/%EC%84%B8%EC%85%98</guid>
            <pubDate>Thu, 30 Sep 2021 17:08:16 GMT</pubDate>
            <description><![CDATA[<p>나는 세션을 살펴보면서 계속 의문을 느꼈다. 그래서 쿠키랑 다른게 뭐지? 이런생각이 들었다. 둘 다 HTTP의 기능을 효과적으로 사용하기 위해 있는것이고 접속자의 정보를 파악하기 위해 존재하는 것 아닌가? 세션은 쿠키를 기반으로 하고있다는데? 쿠키중 세션 쿠키도 브라우저에 저장되면서 세션과 같은 기능을 하는것 아닌가? 이런생각이 들었지만 계속 보다보니 비슷하지만 엄현히 다르다는것을 알게되었다.</p>
<h3 id="세션이란">세션이란?</h3>
<p>쿠키의 경우 컴퓨터의 로컬에 저장되고 세션은 서버에서 start시 아이디값을 부여해주고 브라우저가 종료될때까지 인증상태를 유지하고 종료시 그 값을 삭제한다. 로컬에 저장된 값이 아닌 서버에서 ID값을 부여해주는 것이기에 쿠키보다 보안에 우위에 있다고 한다.</p>
<h3 id="그럼-쿠키를-왜-사용하나">그럼 쿠키를 왜 사용하나?</h3>
<p>그 이유는 서버에서 불러들이는 것이기에 컴퓨터 내에 존재하는 쿠키보다 느리다고 한다. 그리고 접속자가 많을수록 서버에 과부하를 주게되어 성능 저하의 요인이 된다고 한다.</p>
<p>이러한 이유로 쿠키와 세션을 적절이 섞어서 사용하여 웹의 성능을 높이는 것이라한다.</p>
<h3 id="역할">역할</h3>
<p>세션의 경우 브라우저를 이용하면서 로그인 정보를 유지하는데 쓰이고 백엔드 쪽에서 데이터를 불러올때 불러들인 사용자가 그 데이터의 주인인가를 판별하는데 쓰이는것같다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[쿠키]]></title>
            <link>https://velog.io/@dev_space/%EC%BF%A0%ED%82%A4</link>
            <guid>https://velog.io/@dev_space/%EC%BF%A0%ED%82%A4</guid>
            <pubDate>Thu, 30 Sep 2021 17:01:44 GMT</pubDate>
            <description><![CDATA[<p>내가 생각하는 쿠키의 역할은 단순히 로그인 정보 저장 정도로만 생각했다. 하지만 그건 일부일 뿐이고 보이지 않는곳에서 많이 쓰인다는 것을 알았다.</p>
<h2 id="쿠키란">쿠키란?</h2>
<p>우선 쿠키의 기본 개념은 쿠키는 소프트웨어가 아니고 프로그램 처럼 실행되는 것이 아닌 문자열로 서버에 저장되며 웹 서버(HTTP)의 사용을 돕는 기능을 한다는것이다.</p>
<p>어떤식으로 돕느냐는 HTTP의 경우 자체적으로 요청만으로 접속자를 구분할 수 있는 수단이 없다고 한다. 그래서 접속자가 접속시 요청할 수 있는게 없이 새롭게 모든 활동을 시작해야 된다는것이다. 이러한 이유로 쿠키를 서버로 보내면서 접속자를 식별한다는 것이다. 그리고 사이트를 옮겨 다닐때마다 로그인이 유지되는 이유또한 쿠키로 인한것이란다. 쿠키의 유형중 하나인 세션 쿠키로 인한것인데 세션이 쿠키의 한 종류라는 것을 알게됐다.</p>
<p>그리고 접속자 정보를 식별하는 정보를 담고있기에 이 쿠키를 훔쳐 악의적으로 이용도 가능하다고 한다. 하지만 그건 스파이웨어 같은 악성 소프트웨어로 인한 것이고 쿠키만으로는 최대 4KB의 문자열을 옮기는 것이 다이기에 바이러스나 악성코드를 옮길 수는 없다고 한다.</p>
<h3 id="역할">역할</h3>
<p>그리고 접속자 식별의 경우 사용하는 유형으로는 로그인 정보 뿐만이 아닌 광고를 나타냄에 해당 접속자의 국적 정보를 파악한다거나 한다하고 검색하는 주체가 사람인지 어플리케이션인지 어떤 종류를 검색하는지, 많이 검색하는지, 시간 등의 정보를 볼 수 있다고 한다.</p>
<h3 id="정리">정리</h3>
<p>쿠키란, HTTP만으로 식별 불가능한 사용자의 정보를 식별하기 위해 사용되어 페이지 내의 많은 서비스를 누릴 수 있게 해주는 기능이라 말 할 수 있다.
최소한의 정보들을 가지고 사용자를 식별하여 편리성과 효율을 높혀주는 대단히 편리한 기술같다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[캐시]]></title>
            <link>https://velog.io/@dev_space/%EC%BA%90%EC%8B%9C</link>
            <guid>https://velog.io/@dev_space/%EC%BA%90%EC%8B%9C</guid>
            <pubDate>Thu, 30 Sep 2021 16:58:42 GMT</pubDate>
            <description><![CDATA[<p>나는 처음에 캐시가 캐싱과 비슷하고 캐시는 웹에서만 쓰이는 표현이줄 알았다. 하지만 캐싱과 캐시는 다른 의미를 갖고있고 웹에서의 캐시는 캐시의 역할 중 하나라는 것을 알게되었다.</p>
<h2 id="캐시란">캐시란?</h2>
<p>나온 배경은 프로세서 클럭속도는 올라가는데 메인 메모리는 그 속도를 못따라오고 용량만 키우는 방향으로 나아가게되어 클럭속도를 아무리 올려도 전체 시스템 성능이 증가하기 어렵게 되어 나왔다고 한다.
일반적으로 데이터나 값을 미리 복사해 놓는 임시 장소를 가르킨다. 그럼 캐시의 위치는 어디일까 찾아봤는데 캐시는 일부는 코어간에 공유되고 일부는 개별적이며 구현에 따라 다르다. 프로세서 내부라고 하면된다고 한다.</p>
<p>캐시는 CPU에서 쓰기에는 아까운 자원이고 다른 하드웨어에서 뽑아쓰자니 속도가 문제가 되는 자원을 CPU가까이에 위치해 놓고 사용하는것이다.</p>
<h3 id="ram과-같은건가">RAM과 같은건가?</h3>
<p>같은게 아니다. 내가 생각하는 RAM은 DRAM으로 캐시는 SRAM이다. 캐시의 경우 DRAM보다 훨씬 빠르고 CPU와 비슷한 속도를 가지고 있다고 한다. RAM의 경우에도 대체 못할 속도이기에 캐시라는 공간이 만들어진것같다. </p>
<h3 id="그럼-다-캐시로-채우면-되는거-아닌가">그럼 다 캐시로 채우면 되는거 아닌가?</h3>
<p>자료를 찾다보니 캐시는 비싸기에 확장시 효율이 좋지 못하다는 식으로 나온다. 나는 그 비싸다는 말이 저장하는데 큰 자원을 소모한다는 건가? 이런 생각을 하였다. 하지만 그게 아닌 진짜 말그대로 비싼거였다. 메인 메모리보다 빠르고 작고 매우 비싼 메모리로 소개되며 그 가격은 21세기 현대도 메모리 소자 중에서 가장 비싼 편이고, 지난 20년 동안 가격이 3%정도 떨어지는데 불과했다고 한다.</p>
<h3 id="웹에서-캐시의-역할은">웹에서 캐시의 역할은?</h3>
<p>웹에서의 캐시는 동적인 자원을 저장해주어 브라우저의 속도를 향상시키는 역할을 한다고 한다. 웹브라우저에 들어갈시 그 웹사이트의 자원을 우리는 캐시한다고 한다. 그 자원을 얼마나 저장할지는 웹사이트에 의해 결정된다고 하고 문제점으로는 기존에 저장된 자원으로 인해 오류가 생길 수 있다는 것인데 이것은 브라우저 내에 있는 캐시 삭제를 해주면 해결된다고 한다.</p>
<p>그러다 뭔지도 모르는 웹사이트 자원이 내 소중한 컴퓨터에? 그 자원에 어떤걸 숨겨올지 모르는것 아닌가? 이런 생각이 들었다. 하지만 이럼에도 불구하고 장점이 워낙 높기에 우리 컴퓨터 내의 보안을 강화하여 보완한다고 한다.</p>
<h3 id="정리">정리</h3>
<h4 id="하드웨어에서의-캐시">하드웨어에서의 캐시</h4>
<p>하드웨어에서 캐시는 느린 메인 메모리의 속도를 대체하기위해 CPU와 메인 메모리간의 소통을 도와주어 자원을 효율적으로 쓸 수 있게 해주는 메모리이고 사용자의 편리와 효율성 증대 시켜주는 아이.</p>
<h4 id="웹에서의-캐시">웹에서의 캐시</h4>
<p>웹에서의 캐시는 정적인 HTML, CSS, JS, 이미지 등의 자원을 저장해주는 역할을 통해 처음에만 로딩이 있지 그 이후는 더 빠르고 신속하게 이용할 수 있게 도와주는 역할을 하는 것이다.</p>
]]></description>
        </item>
    </channel>
</rss>