<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>kyuuu_ul.log</title>
        <link>https://velog.io/</link>
        <description></description>
        <lastBuildDate>Fri, 29 Mar 2024 04:11:59 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>kyuuu_ul.log</title>
            <url>https://velog.velcdn.com/images/kyuuu_ul/profile/d0bfc9ac-c319-40b3-ab8b-dcf659beaf4e/image.jpg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. kyuuu_ul.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/kyuuu_ul" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[Nvm  Linter Prettier]]></title>
            <link>https://velog.io/@kyuuu_ul/Nvm-Linter-Prettier</link>
            <guid>https://velog.io/@kyuuu_ul/Nvm-Linter-Prettier</guid>
            <pubDate>Fri, 29 Mar 2024 04:11:59 GMT</pubDate>
            <description><![CDATA[<h2 id="nvm">Nvm</h2>
<blockquote>
<p>nvm is a version manager for node.js
<a href="https://github.com/nvm-sh/nvm">https://github.com/nvm-sh/nvm</a></p>
</blockquote>
<h4 id="node-버전-지정해서-설치하기">node 버전 지정해서 설치하기</h4>
<blockquote>
<p>$ nvm install 10.16.3
$ nvm install 10 // 10.x 의 마지막 버전</p>
</blockquote>
<h4 id="node-최신버전-설치">node 최신버전 설치</h4>
<blockquote>
</blockquote>
<p>$ nvm install node
$ nvm install --lts // lts 최신버전</p>
<h4 id="설치된-nodejs-목록-확인하기">설치된 node.js 목록 확인하기</h4>
<blockquote>
<p>$ nvm ls</p>
</blockquote>
<h4 id="설치할-수-있는-모든-node-버전-조회">설치할 수 있는 모든 node 버전 조회</h4>
<blockquote>
<p>$ nvm ls-remote</p>
</blockquote>
<h4 id="특정-버전의-node-사용하기">특정 버전의 node 사용하기</h4>
<blockquote>
<p>$ nvm use <version>
$ nvm current // 현재 사용중인 버전 확인하기
$ nvm uninstall <version> // 필요없는 node 버전 삭제하기</p>
</blockquote>
<h4 id="설치되어-있는-가장-최신버전의-node를-디폴트로-사용하기">설치되어 있는 가장 최신버전의 node를 디폴트로 사용하기</h4>
<blockquote>
<p>$ nvm alias default node
$ nvm alias default 10.16.3</p>
</blockquote>
<h4 id="nodejs-설치-경로-확인하기">node.js 설치 경로 확인하기</h4>
<blockquote>
<p>$ which node</p>
</blockquote>
<h2 id="linter">Linter</h2>
<blockquote>
<p>Formatting rules, Code quality rules
<a href="https://eslint.org/">https://eslint.org/</a></p>
</blockquote>
<h2 id="prettier">Prettier</h2>
<blockquote>
<p>An opinionated code formatter
<a href="https://prettier.io/">https://prettier.io/</a></p>
</blockquote>
<h4 id="setup">setup</h4>
<blockquote>
<p> vscode 마켓 플레이스에서 eslint, prettier 플러그인 설치
  npm install --save-dev eslint-config-prettier eslint-plugin-prettier</p>
</blockquote>
<h4 id="root-폴더에-eslintrcjs-생성">root 폴더에 .eslintrc.js 생성</h4>
<blockquote>
</blockquote>
<pre><code class="language-javascript">  module.exports = {
  parserOptions: {
    ecmaVersion: &quot;latest&quot;,
  },
  env: {
    browser: true,
    node: true,
  },
  extends: [&quot;eslint:recommended&quot;, &quot;plugin:prettier/recommended&quot;],
};</code></pre>
<h4 id="root-폴더에-prettierrc-생성">root 폴더에 .prettierrc 생성</h4>
<blockquote>
</blockquote>
<pre><code>{
  &quot;printWidth&quot;: 120,
  &quot;tabWidth&quot;: 2,
  &quot;useTabs&quot;: false,
  &quot;semi&quot;: true, 
  &quot;singleQuote&quot;: true, 
  &quot;trailingComma&quot;: &quot;all&quot;, 
  &quot;bracketSpacing&quot;: true, 
  &quot;arrowParens&quot;: &quot;avoid&quot;, 
  &quot;proseWrap&quot;: &quot;never&quot;, 
  &quot;endOfLine&quot;: &quot;auto&quot;
}</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[JavaScript This]]></title>
            <link>https://velog.io/@kyuuu_ul/JavaScript-This</link>
            <guid>https://velog.io/@kyuuu_ul/JavaScript-This</guid>
            <pubDate>Thu, 21 Mar 2024 08:40:16 GMT</pubDate>
            <description><![CDATA[<h2 id="1-전역-this">1. 전역 This</h2>
<h3 id="입력">입력</h3>
<pre><code class="language-javascript">console.log(this)</code></pre>
<h3 id="출력">출력</h3>
<p><img src="https://velog.velcdn.com/images/kyuuu_ul/post/fc5d20dc-71f6-4236-8c01-a16cb29b7144/image.JPG" alt=""></p>
<h3 id="window-객체">Window 객체</h3>
<p><img src="https://velog.velcdn.com/images/kyuuu_ul/post/9ccfce96-c720-4b8b-a413-4fb839d0542c/image.JPG" alt=""></p>
<p>this값은 기본적으로는 window 객체입니다.
window는 모든 전역변수, 함수, DOM을 보관하고 관리하는 전역객체이다.</p>
<h2 id="2-함수-this">2. 함수 This</h2>
<h3 id="입력-1">입력</h3>
<pre><code class="language-javascript">function main() {
  console.log(this);
}

main();</code></pre>
<h3 id="출력-1">출력</h3>
<p><img src="https://velog.velcdn.com/images/kyuuu_ul/post/bdc1b518-c36a-48c0-8abc-df1b952af843/image.JPG" alt=""></p>
<p>this값은 함수를 호출한 객체이기에 전역에서와 마찬가지로
Window를 출력한다.</p>
<h3 id="strict-mode">strict mode</h3>
<pre><code class="language-javascript">&quot;use strict&quot;;

function main() {
  console.log(this);
}

main();</code></pre>
<h3 id="출력-2">출력</h3>
<p><img src="https://velog.velcdn.com/images/kyuuu_ul/post/abd0d80d-be11-4bb0-8cc7-2cb323fa3e8a/image.JPG" alt=""></p>
<p>strict mode는 자바스크립트 코드를 실행할 때 발생하는 일부 문제를 잡고 오류를 줄이기 위한 특별한 모드이다.</p>
<p>정상 출력을 원하면 window.main()을 사용해야 한다.</p>
<h2 id="3-객체-메소드-this">3. 객체 메소드 This</h2>
<h3 id="입력-2">입력</h3>
<pre><code class="language-javascript">const object = {
  name: &#39;객체&#39;,
  main: function () {
    console.log(this);
  },
};

object.main()</code></pre>
<h3 id="출력-3">출력</h3>
<p><img src="https://velog.velcdn.com/images/kyuuu_ul/post/3d066c84-d6f0-407c-8f17-a0785e4a14fb/image.JPG" alt=""></p>
<p>this값은 함수를 호출한 객체이기에 main함수를 호출한 object객체를 출력한다.</p>
<h3 id="입력2">입력2</h3>
<pre><code class="language-javascript">function main() {
    console.log(this);
}

const object = {
  name: &#39;객체&#39;,
  subObject: {
    name: &#39;하위객체&#39;,
    main,
  }
};

object.subObject.main();</code></pre>
<h3 id="출력-4">출력</h3>
<p><img src="https://velog.velcdn.com/images/kyuuu_ul/post/6c263f0a-f6b0-4849-8406-d6d50e2e3ea7/image.JPG" alt=""></p>
<h2 id="4-이벤트-핸들러-this">4. 이벤트 핸들러 This</h2>
<h3 id="입력-3">입력</h3>
<pre><code class="language-javascript">const btn = document.querySelector(&quot;#btn&quot;);
btn.addEventListener(&quot;click&quot;, function () {
  console.log(this);
});</code></pre>
<h3 id="출력-5">출력</h3>
<p><img src="https://velog.velcdn.com/images/kyuuu_ul/post/d1dbfc17-819a-46a2-993b-ea8990ed9b60/image.JPG" alt=""></p>
<p>이벤트 핸들러에서 this는 이벤트를 받는 HTML 요소를 가리킨다.</p>
<h2 id="5-화살표함수-this">5. 화살표함수 This</h2>
<h3 id="입력-4">입력</h3>
<pre><code class="language-javascript">const object = {
  name: &#39;객체&#39;,
  showTime(s) {
   setTimeout(()=&gt;{
    console.log(this.name);
   }, s);
  }
};

object.showTime(10);</code></pre>
<h3 id="출력-6">출력</h3>
<blockquote>
<p>객체</p>
</blockquote>
<p>화살표함수에서의 this는 상위 실행컨텍스트의 this를 가리킨다. setTimeout의 상위 실행컨텍스트는 showTime이다. showTime은 객체 메소드 에서 사용되었기에 this는 object를 가리킨다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[StoryBook]]></title>
            <link>https://velog.io/@kyuuu_ul/StoryBook</link>
            <guid>https://velog.io/@kyuuu_ul/StoryBook</guid>
            <pubDate>Fri, 08 Mar 2024 05:04:23 GMT</pubDate>
            <description><![CDATA[<h2 id="storybook">StoryBook</h2>
<blockquote>
<p>Storybook is a frontend workshop for building UI components and pages in isolation. Thousands of teams use it for UI development, testing, and documentation. It’s open source and free.</p>
</blockquote>
<p>스토리북은 UI 구성 컴포넌트와 페이지를 개별적으로 구축하기 위한 프론트엔드 개발도구이다.</p>
<h2 id="advantage">advantage</h2>
<blockquote>
<ol>
<li>독립적인 환경에서 컴포넌트를 다룰 수 있다.</li>
<li>컴포넌트 문서화, 테스트가 가능하다</li>
<li>figma 연동이 가능해 디자이너와 커뮤니케이션에 효율적이다.</li>
</ol>
</blockquote>
<h3 id="1-setup-and-start">1. Setup and Start</h3>
<blockquote>
<ul>
<li>npx storybook@latest init</li>
</ul>
</blockquote>
<ul>
<li>npm run storybook</li>
</ul>
<p><img src="https://velog.velcdn.com/images/kyuuu_ul/post/254b261e-b2e3-43e6-b6d1-837d25baba90/image.png" alt=""></p>
<h3 id="2-guide">2. Guide</h3>
<h4 id="1-maints">1. main.ts</h4>
<pre><code>import type { StorybookConfig } from &quot;@storybook/react-vite&quot;;

const config: StorybookConfig = {
  stories: [&quot;../src/**/*.mdx&quot;, &quot;../src/**/*.stories.@(js|jsx|mjs|ts|tsx)&quot;],
  addons: [
    &quot;@storybook/addon-links&quot;,
    &quot;@storybook/addon-essentials&quot;,
    &quot;@storybook/addon-onboarding&quot;,
    &quot;@storybook/addon-interactions&quot;,
  ],
  framework: {
    name: &quot;@storybook/react-vite&quot;,
    options: {},
  },
  docs: {
    autodocs: &quot;tag&quot;,
  },
};
export default config;
</code></pre><h4 id="2previewts">2.preview.ts</h4>
<pre><code>import type { Preview } from &quot;@storybook/react&quot;;

// global하게 적용되는 포맷을 설정할 수 있다.
const preview: Preview = {
  parameters: {
    actions: { argTypesRegex: &quot;^on[A-Z].*&quot; },
    controls: {
      matchers: {
        color: /(background|color)$/i,
        date: /Date$/i,
      },
    },
  },
};

export default preview;
</code></pre><h4 id="3examplestoriestsx">3.example.stories.tsx</h4>
<pre><code>import type { Meta, StoryObj } from &#39;@storybook/react&#39;;

import { YourComponent } from &#39;./YourComponent&#39;;

//👇 This default export determines where your story goes in the story list
const meta: Meta&lt;typeof YourComponent&gt; = {
  component: YourComponent,
  title: &quot;Title&quot;
};

export default meta;
type Story = StoryObj&lt;typeof YourComponent&gt;;

export const FirstStory: Story = {
  args: {
    color:&quot; black&quot;
    size: &quot;small&quot;
  },
};</code></pre><blockquote>
<p>공식문서 <a href="https://storybook.js.org/docs/get-started/why-storybook">https://storybook.js.org/docs/get-started/why-storybook</a>
리액트번역 문서 <a href="https://storybook.js.org/tutorials/design-systems-for-developers/react/ko/introduction/">https://storybook.js.org/tutorials/design-systems-for-developers/react/ko/introduction/</a></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[2018] 프런트엔드 성능 최적화 (NHN) 리뷰
]]></title>
            <link>https://velog.io/@kyuuu_ul/2018-%ED%94%84%EB%9F%B0%ED%8A%B8%EC%97%94%EB%93%9C-%EC%84%B1%EB%8A%A5-%EC%B5%9C%EC%A0%81%ED%99%94-NHN-%EB%A6%AC%EB%B7%B0</link>
            <guid>https://velog.io/@kyuuu_ul/2018-%ED%94%84%EB%9F%B0%ED%8A%B8%EC%97%94%EB%93%9C-%EC%84%B1%EB%8A%A5-%EC%B5%9C%EC%A0%81%ED%99%94-NHN-%EB%A6%AC%EB%B7%B0</guid>
            <pubDate>Tue, 13 Feb 2024 07:34:50 GMT</pubDate>
            <description><![CDATA[<h2 id="프론트엔드-성능--로딩--렌더링"><strong>프론트엔드 성능 = 로딩 + 렌더링</strong></h2>
<h3 id="로딩">로딩</h3>
<p>프론트 단에서 중요한건 Load, Proccesing Event 최적화
HTML -&gt; CSS -&gt; Javascript 순으로 parsing
(Dom Tree + CSSOM Tree) + Render Tree</p>
<hr>
<p>*<em>브라우저 기준 최적화 *</em></p>
<p>방법 1
스크립트 head태그 -&gt; body태그 or async+head태그</p>
<p>방법 2
css 외부 스타일 -&gt; inline 스타일</p>
<hr>
<p><strong>사용자 기준 최적화</strong></p>
<p>방법 1
SSR 고려</p>
<p>방법 2
PWA 고려</p>
<hr>
<h3 id="렌더링">렌더링</h3>
<p>방법 1
강제 동기 레이아웃
(레이아웃 과정이 끝나기 전에 자바크스립트 파일에서 DOM 요소의 위치나 크기값을 변경 후 바로 가져오려 하면 강제로 레이아웃을 발생시킴)</p>
<p>강제동기 레이아웃 유발 코드는 한번만 사용 후 캐싱</p>
<p>방법 2
Dom 변경을 최소화(virtual Dom 사용)</p>
<p>방법 3
worker-loader 사용 (wep pack)</p>
<hr>
<p>[출처] <a href="https://www.youtube.com/watch?v=G1IWq2blu8c&amp;t=2093s">https://www.youtube.com/watch?v=G1IWq2blu8c&amp;t=2093s</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[TanStack-Query (React-Query)]]></title>
            <link>https://velog.io/@kyuuu_ul/TanStack-Query-React-Query</link>
            <guid>https://velog.io/@kyuuu_ul/TanStack-Query-React-Query</guid>
            <pubDate>Tue, 13 Feb 2024 05:50:51 GMT</pubDate>
            <description><![CDATA[<h2 id="react-query">React-Query</h2>
<p>리액트 쿼리란? 
it makes fetching, caching, synchronizing and updating server state in your web applications a breeze.
현재 TanStack Query라는 명칭으로 변경되었으며 v5버젼까지 업데이트 되었다.
매번 업데이트마다 자주 변경되니 공식문서를 자주 참고하면 좋다.</p>
<hr>
<h3 id="install">Install</h3>
<pre><code>$ npm i @tanstack/react-query
# or
$ pnpm add @tanstack/react-query
# or
$ yarn add @tanstack/react-query</code></pre><hr>
<h4 id="queryclient">QueryClient</h4>
<h4 id="queryclientprovider">QueryClientProvider</h4>
<p>QueryClient가 인스턴스를 생성, QueryClientProvider를 통해 앱 전체에서 생성한 QueryClient에 접근 가능하도록 해준다.</p>
<pre><code>import {
  QueryClient,
  QueryClientProvider,
} from &#39;@tanstack/react-query&#39;
import { getTodos, postTodo } from &#39;../my-api&#39;

// Create a client
const queryClient = new QueryClient()

function App() {
  return (
    // Provide the client to your App
    &lt;QueryClientProvider client={queryClient}&gt;
      &lt;Todos /&gt;
    &lt;/QueryClientProvider&gt;
  )
}</code></pre><hr>
<h4 id="usequery">UseQuery</h4>
<p>데이터 fetching시 사용</p>
<p><strong>queryKey</strong>
v4 이후로는 배열로 선언, 쿼리의 고유 키 애플리케이션 전체에서 쿼리를 다시 가져오고, 캐싱하고, 공유하는 데 내부적으로 사용됩니다.</p>
<p><strong>queryFn</strong>
data fetching 하는 함수</p>
<p><strong>status</strong>
isPending: 쿼리에 아직 데이터가 없습니다.
isError: 쿼리에 오류가 발생했습니다.
isSuccess: 쿼리가 성공했고 데이터를 사용할 수 있습니다.</p>
<pre><code>import { useQuery } from &#39;@tanstack/react-query&#39;

function Todos() {
  const { isPending, isError, data, error } = useQuery({
    queryKey: [&#39;todos&#39;],
    queryFn: fetchTodoList,
  })

  if (isPending) {
    return &lt;span&gt;Loading...&lt;/span&gt;
  }

  if (isError) {
    return &lt;span&gt;Error: {error.message}&lt;/span&gt;
  }

  // We can assume by this point that `isSuccess === true`
  return (
    &lt;ul&gt;
      {data.map((todo) =&gt; (
        &lt;li key={todo.id}&gt;{todo.title}&lt;/li&gt;
      ))}
    &lt;/ul&gt;
  )
}</code></pre><hr>
<h4 id="usemutation">UseMutation</h4>
<p>서버의 데이터를 변경할 때 사용 HTTP POST, PUT, DELETE 요청 가능.</p>
<pre><code>import { useMutation } from &#39;@tanstack/react-query&#39;

 const mutation = useMutation({
    mutationFn: postTodo,
    onSuccess: () =&gt; {
        console.log(&#39;Success&#39;)
        onError: () =&gt; { console.error(&#39;Error&#39;) },
          onSettled: () =&gt; { console.log(&#39;Settled&#39;) } //결과와 상관없이 실행
    },
  })</code></pre><hr>
<h2 id="devtools">DevTools</h2>
<hr>
<h3 id="install-1">Install</h3>
<pre><code>$ npm i @tanstack/react-query-devtools
# or
$ pnpm add @tanstack/react-query-devtools
# or
$ yarn add @tanstack/react-query-devtools</code></pre><hr>
<h3 id="setup">Setup</h3>
<pre><code>import { ReactQueryDevtools } from &#39;@tanstack/react-query-devtools&#39;

function App() {
  return (
    &lt;QueryClientProvider client={queryClient}&gt;
      {/* The rest of your application */}
      &lt;ReactQueryDevtools initialIsOpen={false} /&gt;
    &lt;/QueryClientProvider&gt;
  )
}</code></pre><hr>
<h4 id="react-query-guide">React Query Guide</h4>
<p><a href="https://tanstack.com/query/latest">https://tanstack.com/query/latest</a>
<a href="https://github.com/ssi02014/react-query-tutorial">https://github.com/ssi02014/react-query-tutorial</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[인프콘 리뷰 "안타깝게도 오늘의  TDD는 실패한 것 같군요. 내일은 가능할지도...?"]]></title>
            <link>https://velog.io/@kyuuu_ul/%EC%9D%B8%ED%94%84%EC%BD%98-%EB%A6%AC%EB%B7%B0-%EC%95%88%ED%83%80%EA%B9%9D%EA%B2%8C%EB%8F%84-%EC%98%A4%EB%8A%98%EC%9D%98-TDD%EB%8A%94-%EC%8B%A4%ED%8C%A8%ED%95%9C-%EA%B2%83-%EA%B0%99%EA%B5%B0%EC%9A%94.-%EB%82%B4%EC%9D%BC%EC%9D%80-%EA%B0%80%EB%8A%A5%ED%95%A0%EC%A7%80%EB%8F%84</link>
            <guid>https://velog.io/@kyuuu_ul/%EC%9D%B8%ED%94%84%EC%BD%98-%EB%A6%AC%EB%B7%B0-%EC%95%88%ED%83%80%EA%B9%9D%EA%B2%8C%EB%8F%84-%EC%98%A4%EB%8A%98%EC%9D%98-TDD%EB%8A%94-%EC%8B%A4%ED%8C%A8%ED%95%9C-%EA%B2%83-%EA%B0%99%EA%B5%B0%EC%9A%94.-%EB%82%B4%EC%9D%BC%EC%9D%80-%EA%B0%80%EB%8A%A5%ED%95%A0%EC%A7%80%EB%8F%84</guid>
            <pubDate>Tue, 30 Jan 2024 10:42:08 GMT</pubDate>
            <description><![CDATA[<p>TDD에 최근에 관심을 많이 가지고 있었는데, 인프콘에서 좋은 강의를 보고 요약해보려 한다.</p>
<p>개발자들은 문제 해결을 하는 직업이라 많이 표현한다. 그렇다면 문제라는 것은 무엇인가?</p>
<p>&quot;문제란 바라는 것과 인식한 것의 차이. 문제를 해결한다는 것은 바라는 것과 인식한 것을 일치시키는 것.&quot;</p>
<p>그렇다면 문제를 해결할려면?</p>
<h3 id="다양한-문제를-많이-풀어봐야-한다"><strong>다양한 문제를 많이 풀어봐야 한다.</strong></h3>
<h2 id="문제">문제)</h2>
<p>9L의 물통과 4L의 물통이 있을 때, 6L의 물을 정확히 만들려면 어떻게 해야하는가? (물의 양은 무제한이라 가정한다.)</p>
<p><img src="https://velog.velcdn.com/images/kyuuu_ul/post/d1c858d1-28ac-4a4f-bc86-892f70d808a2/image.png" alt=""></p>
<p>한번 해결을 해보고 내려주세요 !
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br></p>
<h2 id="풀이">풀이)</h2>
<ol>
<li><p>먼저 요구하고 있는 것으로부터 시작해서 그것을 이미 찾은 것 처럼 가정하자L의 물이 차있다고 생각해보자.
<img src="https://velog.velcdn.com/images/kyuuu_ul/post/465671e9-8317-4bfc-95b6-cd082e35356c/image.png" alt=""></p>
</li>
<li><p>원하는 결과는 어떤 전제로부터 이끌어 낼 수 있는지 질문한다. 즉 4L의 물통에 1L만 물을 덜어낸다면 3L의 물을 뺀 6L의 물을 남길 수 있을것이다.
<img src="https://velog.velcdn.com/images/kyuuu_ul/post/ee34ee7d-5428-4e73-b66e-5577e4bd1554/image.png" alt=""></p>
</li>
<li><p>9-4-4를 하면 1L의 물이 남는다 1L의 물만남는다면 앞서 생각 한 것처럼 3L는 만들수 있게 된다.
<img src="https://velog.velcdn.com/images/kyuuu_ul/post/f1529ff5-ecfd-4c0b-b275-d7cd4cc43572/image.png" alt=""></p>
</li>
</ol>
<p>이러한 해결방법을 &quot;거꾸로 연구하기&quot; 라고 칭한다.</p>
<h4 id="거꾸로-연구하기">거꾸로 연구하기</h4>
<pre><code>1. 요구하고 있는 것으로부터 시작해서 그것을 이미 찾은 것처럼 가정한다.
2. 원하는 결과는 어떤 전제로부터 이끌어 낼 수 있는지 질문한다.</code></pre><p>이 방법을 테스트 코드 작성에 적용하면,</p>
<pre><code>1. 실패하는 테스트를 작성한다. (요구하고 있는 것)
2. 테스트를 통과시킨다. (이미 찾은것 처럼 가정)
3. 리펙토링 한다. (어떤 전제로부터 이끌어 낼 수 있는지 질문)</code></pre><p>TDD 첫 테스트 작성에 막막하다면, 이 단계를 따르면 도움이 될 것 같다.</p>
<p>내가 강의를보고 느낀점은 TDD가 단순 프로젝트에서의 에러 해결뿐 아니라 프로젝트의 진행방향, 코드의 가독성 및 퍼포먼스, 코드작성의 아이디어 등에서 도움이 된다고 많이 느꼈다. 다음 프로젝트에선 TDD를 고려해봐야지..</p>
<p>[출저] 인프콘2023 안타깝게도 오늘의 TDD는 실패한 것 같군요. 내일은 가능할지도...? (한윤석)</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[이벤트 루프]]></title>
            <link>https://velog.io/@kyuuu_ul/%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EB%A3%A8%ED%94%84</link>
            <guid>https://velog.io/@kyuuu_ul/%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EB%A3%A8%ED%94%84</guid>
            <pubDate>Tue, 30 Jan 2024 10:11:43 GMT</pubDate>
            <description><![CDATA[<p>자바스크립트는 어떤 언어인가요?
논블로킹(Non-blocking) : 코드의 실행이 다른 코드의 실행을 막지 않는다.
싱글스레드(single thred) : 하나의 프로세스에서 오직 하나의 스레드로만 실행.</p>
<p>자바스크립트 = 논블로킹, 싱글스레드 언어</p>
<p><img src="https://velog.velcdn.com/images/kyuuu_ul/post/3722acf3-d851-42dc-a63a-a43414ab4808/image.png" alt=""></p>
<p><strong>Call Stack</strong>: 자바스크립트 엔진이 코드실행을 위해 사용하는 스택 메모리 구조</p>
<p>(LIFO, Last In First Out)을 따른다.
<br>
<strong>Memory Heap</strong>: 동적으로 할당된 변수, 함수 등이 저장되는 공간
<br>
<strong>Wep Apis</strong>: 브라우저에서 제공하는 API들, 비동기적으로 실행되는 작업 관리</p>
<p>자바스크립트 엔진이 아닌 브라우저에서 제공해준다.
<br>
<strong>Callback Queue</strong>: 비동기적으로 실행된 함수들이 대기하는 공간</p>
<p>Task(Macro) Queue : setTimeout, setInterval, fetch, addEventListener 와 같이 비동기로 처리되는 함수들의 콜백 함수가 들어가는 큐</p>
<p>Microtask Queue : promise.then, process.nextTick, MutationObserver 와 같이 우선적으로 비동기로 처리되는 함수들의 콜백 함수가 들어가는 큐 (처리 우선순위가 높음)
<br>
<strong>Event Loop</strong>: 브라우저의 동작 타이밍을 관리해주는 관리자 역할</p>
<p>Call Stack이 비면 Callback Queue의 첫번째 콜백을 Call stack에 넣는다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[CSR SSR SSG ISR]]></title>
            <link>https://velog.io/@kyuuu_ul/CSR-SSR-SSG-ISR</link>
            <guid>https://velog.io/@kyuuu_ul/CSR-SSR-SSG-ISR</guid>
            <pubDate>Sat, 27 Jan 2024 02:57:11 GMT</pubDate>
            <description><![CDATA[<h2 id="browser-rendering">Browser Rendering</h2>
<p><img src="https://velog.velcdn.com/images/kyuuu_ul/post/35d5e47a-5548-4ca9-b54d-693e080e2247/image.png" alt="">
DOM + CSSOM =&gt; Render Tree</p>
<h2 id="csrclien-side-rendering">CSR(Clien Side Rendering)</h2>
<p><strong>클라이언트에서 HTML파일 렌더링을 진행한다.</strong></p>
<p>장점</p>
<ul>
<li>첫 페이지 이후 로딩속도가 빠르다.</li>
<li>페이지 이동시 화면이 깜빡임이 없어 좋은 사용자 경험을 제공한다.</li>
</ul>
<p>단점</p>
<ul>
<li>첫 페이지 로딩 속도가 느리다.</li>
<li>SEO에서 단점을 가진다.</li>
</ul>
<h2 id="ssrsever-side-rendering">SSR(Sever Side Rendering)</h2>
<p>*<em>서버에서 HTML파일을 렌더링을 진행한다.
*</em>
장점</p>
<ul>
<li>첫 페이지 로딩 속도가 빠르다.</li>
<li>SEO에서 이점을 가진다.</li>
</ul>
<p>단점</p>
<ul>
<li>서버 부하가 높아진다.</li>
<li>페이지 이동시 화면이 깜빡여 사용자 경험이 저하된다.</li>
</ul>
<h2 id="ssgstatic-side-genetation">SSG(Static Side Genetation)</h2>
<p>*<em>빌드하는 순간 기점으로 서버에서 HTML 렌더링 된 정적 페이지
*</em>
장점</p>
<ul>
<li>SSR는 빌드시 HTML이 생성되고 요청마다 재사용한다.</li>
<li>CDN 캐시, SEO, 페이지 로딩 등의 이점</li>
</ul>
<p>단점</p>
<ul>
<li>정적 페이지기에 동적 데이터가 제한 된다.</li>
<li>사용자별로 달라지는 정보 제공이 어렵다. (ex: mypage)
<img src="https://velog.velcdn.com/images/kyuuu_ul/post/99296238-ff8c-4bab-a1da-a63c31f3e0c8/image.png" alt=""></li>
</ul>
<h2 id="isrincremental-static-regenetation">ISR(Incremental Static Regenetation)</h2>
<p>** SSG와 비슷하지만 서버에서 정적 페이지를 정기적으로 다시 빌드한다.
**
장점</p>
<ul>
<li>개인페이지, 블로그등의 자주 변경되지 않는 동적 페이지에 효율적</li>
<li>CDN 캐시, SEO, 페이지 로딩 등의 이점</li>
</ul>
<p>단점</p>
<ul>
<li>정기적으로 빌드를 하지만 여전히 최신 데이터를 로드하지 못한다.</li>
<li>여전히 사용자별로 달라지는 정보 제공이 어렵다. (ex: mypage)</li>
</ul>
<p>-사용자 경험이 중요하며 클라이언트의 상태 변경이 잦은 경우 CSR
-첫 페이지 로딩 속도, SEO가 중요한 경우 SSR
-컨텐츠 내용이 변하지 않고, 빠른 HTML가 필요한 경우 SSG
-컨텐츠가 동적이지만 자주 변경되지 않는 경우 ISR</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Javascript Timestamp]]></title>
            <link>https://velog.io/@kyuuu_ul/Javascript-Timestamp</link>
            <guid>https://velog.io/@kyuuu_ul/Javascript-Timestamp</guid>
            <pubDate>Thu, 28 Dec 2023 07:45:52 GMT</pubDate>
            <description><![CDATA[<h3 id="new-date">new Date()</h3>
<pre><code>var today = new Date();
console.log(today);
// 결과 : Thu May 16 2019 17:22:10 GMT+0900 (한국 표준시)</code></pre><p>Date 객체는 생성자 함수이다.
Date 생성자 함수는 날짜와 시간을 가지는 인스턴스를 생성한다.
생성된 인스턴스는 기본적으로 현재 날짜와 시간을 나타내는 값을 가진다.
현재 날짜와 시간이 아닌 다른 날짜와 시간을 다루고 싶은 경우, 
Date 생성자 함수에 명시적으로 해당 날짜와 시간 정보를 인수로 지정한다.</p>
<h3 id="현재-날짜-출력">현재 날짜 출력</h3>
<pre><code>var today = new Date();

var year = today.getFullYear();
var month = (&quot;0&quot; + (today.getMonth() + 1)).slice(-2);
var day = (&quot;0&quot; + today.getDate()).slice(-2);

var dateString = year + &quot;-&quot; + month + &quot;-&quot; + day;

console.log(dateString);
// 결과 : 2023-12-28</code></pre><p>getMonth()함수는 0~11월을 출력하기에 +1을 해줘야함.
0을 붙이고 slice(-2)를 해줌으로서 뒤에서 2개만 필터링 되기에,
6월이 아닌 06월이 출력된다.</p>
<h3 id="현재-시간-출력">현재 시간 출력</h3>
<pre><code>var today = new Date();   

var hours = (&#39;0&#39; + today.getHours()).slice(-2); 
var minutes = (&#39;0&#39; + today.getMinutes()).slice(-2);
var seconds = (&#39;0&#39; + today.getSeconds()).slice(-2); 

var timeString = hours + &#39;:&#39; + minutes  + &#39;:&#39; + seconds;

console.log(timeString);
// 결과 : 16:37:51</code></pre><p>시간 또한 마찬가지로 0을 붙이고 slice(-2)를 해줌으로서 뒤에서 2개만 필터링 되기에,
앞에 0을 붙여줄 수 있다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Cookie vs Sesion  vs JWT]]></title>
            <link>https://velog.io/@kyuuu_ul/Cookie-vs-Sesion-vs-JWT</link>
            <guid>https://velog.io/@kyuuu_ul/Cookie-vs-Sesion-vs-JWT</guid>
            <pubDate>Mon, 18 Dec 2023 09:03:56 GMT</pubDate>
            <description><![CDATA[<p><strong>http Protocol</strong>은 <strong>stateless</strong> 한 특징을 가지고 있다. 로그인을 한다면 누가 로그인 중인지 기억하기 위해 쿠키,세션,토큰 등을 사용한다. </p>
<h1 id="cookie">cookie</h1>
<p>웹에 접속할 때 생성되는 정보를 담고 있는 임시 파일이다. 서버를 대신해 사용자의 웹 브라우저에 정보를 저장한다.</p>
<h1 id="sesion">sesion</h1>
<p>쿠키와 반대로 웹 브라우저가 아닌 서버의 메모리에 세션 ID를 저장한다. </p>
<h1 id="jwt">JWT</h1>
<p>Json format으로 사용자에 대한 정보를 저장할 수 있는 웹토큰. 서버에서 클라이언트에게 인증이 되면 토큰을 부여한다.</p>
<h1 id="cookie--session-vs-jwt"><strong>Cookie &amp; Session vs JWT</strong></h1>
<p><strong>Cookie &amp; Session</strong></p>
<ol>
<li><p>사용자가 서버에 로그인을 요청한다.</p>
</li>
<li><p>서버에서 사용자를 확인한 후 사용자의 고유한 Id를 부여하여 세션 저장소에 저장한 후 이와 연결된 세션Id를 발급한다.</p>
</li>
<li><p>사용자는 서버에서 해당 세션Id를 받아 쿠키에 저장한 후, 인증이 필요한 요청마다 쿠키를 헤더에 실어 보낸다.</p>
</li>
<li><p>서버는 쿠키를 받아 세션 저장소에서 대조 후 대응되는 정보를 가져온다.</p>
</li>
<li><p>인증이 완료되면 서버는 사용자에 맞는 데이터를 보내준다.</p>
</li>
</ol>
<p>장점</p>
<ul>
<li>서버쪽에서 Session 통제가 가능하다.</li>
<li>네트워크 부하가 낮다.</li>
</ul>
<p>단점</p>
<ul>
<li>서버에서 세션 저장소를 사용하기에 요청이 많아지는 경우 서버에 부하가 심해진다.</li>
</ul>
<p><strong>JWT</strong></p>
<ol>
<li><p>사용자가 서버에 로그인을 요청한다.</p>
</li>
<li><p>서버측에서 사용자에게 유일한 토큰을 발급한다.</p>
</li>
<li><p>클라이언트는 서버측에서 전달받은 토큰을 쿠키나 스토리지에 저장해두고, 서버에 요청을 할 때마다 해당 토큰을 HTTP요청 헤더에 포함시켜 전달한다.</p>
</li>
<li><p>서버는 전달받은 토큰을 검증하고 요청에 응답한다. 토큰에는 요청한 사람의 정보가 담겨있어서 서버는 DB를 조회하지않고 누가 요청했는지 알 수 있다.</p>
</li>
</ol>
<p>장점</p>
<ul>
<li>hearder와 payload를 지니기에 데이터 위변조 막을수있다.</li>
<li>별도의 저장소가 필요하지 않다.</li>
</ul>
<p>단점</p>
<ul>
<li>요청이 많아지면 토큰의 길이가 길기에 네트워크 부하가 심해진다.</li>
<li>토큰 탈취시 대응이 어렵다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[JavaScript Naming]]></title>
            <link>https://velog.io/@kyuuu_ul/JavaScript-Naming</link>
            <guid>https://velog.io/@kyuuu_ul/JavaScript-Naming</guid>
            <pubDate>Thu, 14 Dec 2023 07:59:25 GMT</pubDate>
            <description><![CDATA[<p><strong>1. Camel Case(카멜 케이스)</strong></p>
<blockquote>
<pre><code>let isCamelCase;</code></pre><p>두번째 단어부터 대문자로 시작하여 구분</p>
</blockquote>
<p><strong>2. Snake Case(스네이크 케이스)</strong></p>
<blockquote>
<pre><code>let is_my_name;</code></pre><p>단어와 단어 사이를 _를 이용하여 구분</p>
</blockquote>
<p><strong>3. Pascal Case(파스칼 케이스)</strong></p>
<blockquote>
<pre><code>let IsPascalCase;</code></pre><p>모든 단어의 시작을 대문자로 작성하여 구분</p>
</blockquote>
<p><strong>파일 확장자</strong></p>
<ul>
<li><p>소문자로 작성한다.</p>
<pre><code>helloword.png
busan.pdf</code></pre><p><strong>변수 및 함수</strong></p>
<ul>
<li>변수 및 함수는 CamelCase를 사용한다.</li>
</ul>
</li>
</ul>
<pre><code>let helloNumber;
function isButton()</code></pre><p><strong>상수</strong></p>
<ul>
<li>상수는 PascalCase, SnakeCase를 사용한다.</li>
</ul>
<pre><code>const MY_ROLE;</code></pre><p><strong>클래스</strong></p>
<ul>
<li>클래스 및 생성자는 PascalCase를 사용한다.</li>
</ul>
<pre><code>class User {
  constructor(options) {
    this.name = options.name;
  }
}

const good = new User({
  name: &#39;yup&#39;,
});</code></pre><p>** 에어비엔비 자바스크립트 스타일 가이드**
<a href="https://github.com/airbnb/javascript">https://github.com/airbnb/javascript</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[자바스크립트 호이스팅(hoisting)]]></title>
            <link>https://velog.io/@kyuuu_ul/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%ED%98%B8%EC%9D%B4%EC%8A%A4%ED%8C%85hoisting</link>
            <guid>https://velog.io/@kyuuu_ul/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%ED%98%B8%EC%9D%B4%EC%8A%A4%ED%8C%85hoisting</guid>
            <pubDate>Mon, 04 Dec 2023 13:03:02 GMT</pubDate>
            <description><![CDATA[<h2 id="호이스팅">호이스팅</h2>
<p>변수나 함수의 호출 코드가 선언 코드보다 아래쪽에 있음에도 불구하고 에러가 발생하지 않고, 마치 선언 코드가 호출 코드보다 더 위에 선언된 것과 같이 동작하는 특성을 호이스팅(Hoisting) 이라고 한다.</p>
<p>자바스크립트에서 변수(variable)는 3가지 단계를 걸쳐 생성된다.</p>
<h4 id="선언-단계">선언 단계</h4>
<p>변수를 실행 컨텍스트의 변수 객체에 등록하는 단계이다.
이 변수 객체는 스코프가 참고하는 대상이 된다.</p>
<h4 id="초기화-단계">초기화 단계</h4>
<p>실행 컨텍스트에 존재하는 변수 객체에 선언 단계에서 생성된 변수를 위한 메모리를 만드는 단계이다.
이 단계에서 할당된 메모리에 undefined 를 할당한다.</p>
<h4 id="할당-단계">할당 단계</h4>
<p>초기화 단계에서 undefined로 초기화된 메모리에 다른 값을 할당하는 단계이다.</p>
<pre><code>console.log(a); // undefined
var a = 3;</code></pre><p><strong>var</strong>를 이용하여 선언한 변수는 선언과 동시에 초기화 단계가 진행된다. 그러므로 자바스크립트 내부적으로 실행 콘텍스트의 변수 객채에 변수를 등록하는 동시에 메모리를 undefined로 만들어버린다. 그렇기 때문에 변수에 값이 할당되기 전에 호출해도 Reference 에러가 발생하지 않고, undefined가 리턴된다.</p>
<pre><code>console.log(a); // ReferenceError: Cannot access &#39;greeting&#39; before initialization
let a = 3;</code></pre><pre><code>console.log(a); // ReferenceError: Cannot access &#39;greeting&#39; before initialization=
const a = 3;</code></pre><p>반면 <strong>let, const</strong>를 이용하여 선언한 변수는 var와 다르게 선언 단계와 초기화 단계가 분리되어 진행된다. 실행 컨텍스트의 변수 객체에 변수를 등록했지만, 메모리에 할당되지 않아 접근할 수 없다. 그래서 Reference Error: Cannot access before initialization 에러 문구가 나오는 것이다. 즉, 호이스팅 되지 않는 것이 아니라, 호이스팅은 되었으나 메모리가 할당되지 않아 접근할 수 없는 것이다. 이때 등장하는 개념이 TDZ 이다.</p>
<h4 id="tdz">TDZ</h4>
<p>한글로 직역하자면 일시적인 사각지대이다.
스코프 시작 지점 에서 초기화 시작 지점 까지를 TDZ(Temporal Dead Zone) 라고 한다.
<img src="https://velog.velcdn.com/images/kyuuu_ul/post/1994143f-242e-4b78-a01c-862660e41006/image.JPG" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[JavaScirpt와 Python 부등식 차이점]]></title>
            <link>https://velog.io/@kyuuu_ul/JavaScirpt%EC%99%80-Python-%EB%B6%80%EB%93%B1%EC%8B%9D-%EC%B0%A8%EC%9D%B4%EC%A0%90</link>
            <guid>https://velog.io/@kyuuu_ul/JavaScirpt%EC%99%80-Python-%EB%B6%80%EB%93%B1%EC%8B%9D-%EC%B0%A8%EC%9D%B4%EC%A0%90</guid>
            <pubDate>Mon, 27 Nov 2023 13:45:42 GMT</pubDate>
            <description><![CDATA[<p>최근 자바스크립트로 알고리즘 문제를 풀던중 graph 탐색 문제에서 이상한 점을 발견했다.
평상시 4방향 문제 알고리즘을 해결할때 파이썬으로 다음과 같이 해결했다.</p>
<pre><code class="language-python">dx = [-1,1,0,0]
dy = [0,0,-1,1]
for i in range(4):
    nx = x + dx[i]
    ny = y + dy[i]

       if (0&lt;= nx &lt; w and 0&lt;= ny &lt; h):
           dfs(nx, ny)
</code></pre>
<p>자바스크립트로 graph를 처음 풀어봐 파이썬과 동일하도록 이렇게 구현했었다.</p>
<pre><code class="language-javascript">const dx = [-1,1,0,0]
const dy = [0,0,-1,1]

for(let i =0; i&lt;4; i++){
    nx = x + dx[i]
    ny = y + dy[i]
}

if (0&lt;= nx &lt; w &amp;&amp; 0&lt;= ny &lt; h){
      dfs(nx, ny)
}</code></pre>
<pre><code>(0&lt;= nx &lt; w &amp;&amp; 0&lt;= ny &lt; h)</code></pre><p>이부분에서 파이썬과 동일하게 동작하지 않아 이유를 찾아보니..</p>
<p>자바스크립트에서는 비교 연산자인 &quot;&lt;&quot;를 연속해서 사용하여 여러 개의 비교식을 연결할 수 없다고 한다.</p>
<p>결국 &quot;0 &lt;= nx &lt; w &amp;&amp; 0 &lt;= ny &lt; h&quot;와 같은 표현은 자바스크립트에서 예상한 대로 동작하지 않는다.</p>
<pre><code class="language-javascript">if (0&lt;= nx &amp;&amp; nx &lt; w &amp;&amp; 0&lt;= ny &amp;&amp; ny &lt; h){
      dfs(nx, ny)
}</code></pre>
<p>따라서 다음과 같이 사용해야 한다.</p>
]]></description>
        </item>
    </channel>
</rss>