<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>pyo-dev</title>
        <link>https://velog.io/</link>
        <description></description>
        <lastBuildDate>Tue, 18 Mar 2025 04:21:52 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>pyo-dev</title>
            <url>https://images.velog.io/images/pyo-dev/profile/5c8d00ee-c5ce-4295-af0d-0cf2ce939c3c/pyo-thum.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. pyo-dev. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/pyo-dev" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[Typescript 시작하기]]></title>
            <link>https://velog.io/@pyo-dev/Typescript-%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@pyo-dev/Typescript-%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0</guid>
            <pubDate>Tue, 18 Mar 2025 04:21:52 GMT</pubDate>
            <description><![CDATA[<h1 id="🚀-타입스크립트-시작하기">🚀 타입스크립트 시작하기</h1>
<h2 id="🎯-1-타입스크립트란">🎯 1. 타입스크립트란?</h2>
<p>타입스크립트는 자바스크립트의 슈퍼셋으로, 자바스크립트 코드에 정적 타입 검사를 추가하여 오류를 미리 발견하고 코드의 품질을 향상시킬 수 있게 합니다. 타입스크립트는 자바스크립트로 컴파일되어 실행되기 때문에 자바스크립트와 호환됩니다.</p>
<h3 id="✅-타입스크립트의-장점">✅ 타입스크립트의 장점</h3>
<p>정적 타입 검사: 코드를 작성하면서 타입 오류를 미리 발견할 수 있습니다.
IDE 자동 완성: IDE에서 타입 정보를 활용해 더 나은 자동 완성 기능을 제공합니다.
대규모 프로젝트 관리: 타입 시스템 덕분에 코드가 커져도 유지보수가 용이합니다.
ES6+ 기능 지원: 최신 자바스크립트 기능을 바로 사용할 수 있습니다.</p>
<h2 id="🎯-2-타입스크립트-설치">🎯 2. 타입스크립트 설치</h2>
<p>타입스크립트를 사용하려면 먼저 설치해야 합니다. 프로젝트 폴더에서 아래 명령어를 실행하여 타입스크립트를 설치합니다.</p>
<pre><code>npm install --save-dev typescript</code></pre><p>설치 후, tsconfig.json 파일을 생성하여 프로젝트의 타입스크립트 설정을 할 수 있습니다.</p>
<pre><code>npx tsc --init</code></pre><p>이 명령어는 기본적인 타입스크립트 설정 파일을 생성해줍니다.</p>
<h2 id="🎯-3-타입스크립트-기본-문법">🎯 3. 타입스크립트 기본 문법</h2>
<h3 id="✅-변수-선언-및-타입-지정">✅ 변수 선언 및 타입 지정</h3>
<p>타입스크립트에서는 변수에 타입을 지정할 수 있습니다. 타입 지정은 변수 선언 시 : 뒤에 타입을 작성합니다.</p>
<pre><code>let age: number = 30;
let name: string = &quot;John&quot;;
let isActive: boolean = true;</code></pre><h3 id="✅-배열">✅ 배열</h3>
<p>배열의 타입을 지정할 때는 number[], string[]처럼 배열의 원소 타입을 명시할 수 있습니다.</p>
<pre><code>let numbers: number[] = [1, 2, 3, 4];
let fruits: string[] = [&quot;apple&quot;, &quot;banana&quot;, &quot;cherry&quot;];</code></pre><h3 id="✅-튜플tuple">✅ 튜플(Tuple)</h3>
<p>튜플은 고정된 수의 원소를 가질 수 있으며, 각 원소의 타입도 지정할 수 있습니다.</p>
<pre><code>let person: [string, number] = [&quot;Alice&quot;, 25];</code></pre><h3 id="✅-객체object">✅ 객체(Object)</h3>
<p>객체의 속성 타입을 지정할 때는 객체 리터럴 타입을 사용합니다.</p>
<pre><code>let user: { name: string, age: number } = { name: &quot;Bob&quot;, age: 30 };</code></pre><h3 id="✅-함수function">✅ 함수(Function)</h3>
<p>함수의 매개변수와 반환값의 타입을 지정할 수 있습니다.</p>
<pre><code>function greet(name: string): string {
    return &quot;Hello, &quot; + name;
}</code></pre><h2 id="🎯-4-타입스크립트-고급-기능">🎯 4. 타입스크립트 고급 기능</h2>
<h3 id="✅-인터페이스interface">✅ 인터페이스(Interface)</h3>
<p>인터페이스는 객체의 구조를 정의하는 데 사용됩니다. 클래스가 특정 인터페이스를 구현하도록 강제할 수도 있습니다.</p>
<pre><code>interface Person {
    name: string;
    age: number;
}

let employee: Person = { name: &quot;Alice&quot;, age: 28 };</code></pre><h3 id="✅-클래스class와-상속inheritance">✅ 클래스(Class)와 상속(Inheritance)</h3>
<p>타입스크립트에서는 클래스에 타입을 지정하고, 상속을 통해 코드 재사용성을 높일 수 있습니다.</p>
<pre><code>class Animal {
    name: string;

    constructor(name: string) {
        this.name = name;
    }

    speak(): void {
        console.log(`${this.name} makes a noise.`);
    }
}

class Dog extends Animal {
    constructor(name: string) {
        super(name);
    }

    speak(): void {
        console.log(`${this.name} barks.`);
    }
}

let dog = new Dog(&quot;Buddy&quot;);
dog.speak();  // Buddy barks.</code></pre><h3 id="✅-제네릭generics">✅ 제네릭(Generics)</h3>
<p>제네릭을 사용하면 함수나 클래스가 다양한 타입을 처리할 수 있게 됩니다. 코드 재사용성을 높이고, 타입 안전성을 보장합니다.</p>
<pre><code>function identity&lt;T&gt;(arg: T): T {
    return arg;
}

let numberIdentity = identity(10);  // number
let stringIdentity = identity(&quot;Hello&quot;);  // string</code></pre><h2 id="🎯-5-타입스크립트-예제-프로젝트-간단한-todo-list">🎯 5. 타입스크립트 예제 프로젝트: 간단한 Todo List</h2>
<p>이제 타입스크립트를 사용하여 간단한 Todo List 애플리케이션을 만들어봅시다.</p>
<h3 id="✅-1-todoitem-인터페이스-정의">✅ 1. TodoItem 인터페이스 정의</h3>
<pre><code>interface TodoItem {
    id: number;
    task: string;
    completed: boolean;
}</code></pre><h3 id="✅-2-todo-list-클래스-작성">✅ 2. Todo List 클래스 작성</h3>
<pre><code>class TodoList {
    private todos: TodoItem[] = [];

    addTodo(task: string): void {
        const newTodo: TodoItem = {
            id: this.todos.length + 1,
            task: task,
            completed: false
        };
        this.todos.push(newTodo);
    }

    completeTodo(id: number): void {
        const todo = this.todos.find(todo =&gt; todo.id === id);
        if (todo) {
            todo.completed = true;
        }
    }

    getTodos(): TodoItem[] {
        return this.todos;
    }
}</code></pre><h3 id="✅-3-todolist-사용하기">✅ 3. TodoList 사용하기</h3>
<pre><code>const myTodoList = new TodoList();
myTodoList.addTodo(&quot;Learn TypeScript&quot;);
myTodoList.addTodo(&quot;Build a Todo app&quot;);

console.log(myTodoList.getTodos());

myTodoList.completeTodo(1);

console.log(myTodoList.getTodos());</code></pre><h3 id="✅-4-출력-결과">✅ 4. 출력 결과</h3>
<pre><code>[
    { id: 1, task: &quot;Learn TypeScript&quot;, completed: false },
    { id: 2, task: &quot;Build a Todo app&quot;, completed: false }
]
[
    { id: 1, task: &quot;Learn TypeScript&quot;, completed: true },
    { id: 2, task: &quot;Build a Todo app&quot;, completed: false }
]</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[Vite + React]]></title>
            <link>https://velog.io/@pyo-dev/Vite-React</link>
            <guid>https://velog.io/@pyo-dev/Vite-React</guid>
            <pubDate>Tue, 18 Mar 2025 04:10:34 GMT</pubDate>
            <description><![CDATA[<h1 id="🚀-react--vite-프로젝트-시작하기">🚀 React + Vite 프로젝트 시작하기</h1>
<h2 id="🎯-1-vite를-이용한-react-프로젝트-설치">🎯 1. Vite를 이용한 React 프로젝트 설치</h2>
<h3 id="✅-vite-프로젝트-생성">✅ Vite 프로젝트 생성</h3>
<p>Vite를 사용하면 빠르고 간편하게 React 프로젝트를 생성할 수 있습니다.</p>
<pre><code class="language-sh"># Vite 프로젝트 생성
npm create vite@latest my-react-app -- --template react

# 프로젝트 폴더로 이동
cd my-react-app

# 패키지 설치
npm install

# 개발 서버 실행
npm run dev</code></pre>
<ul>
<li><code>npm create vite@latest</code> : 최신 Vite를 사용하여 프로젝트 생성</li>
<li><code>--template react</code> : React 템플릿 적용</li>
<li><code>npm run dev</code> : 개발 서버 실행 (기본 포트: <code>http://localhost:5173</code>)</li>
</ul>
<h2 id="🎯-2-주요-폴더-및-파일-구조">🎯 2. 주요 폴더 및 파일 구조</h2>
<pre><code>my-react-app/
├── node_modules/     # 설치된 패키지
├── public/           # 정적 파일 (favicon, 이미지 등)
├── src/              # 주요 코드 폴더
│   ├── assets/       # 정적 자산
│   ├── components/   # 재사용 가능한 컴포넌트
│   ├── pages/        # 개별 페이지 컴포넌트
│   ├── App.jsx       # 메인 컴포넌트
│   ├── main.jsx      # React 진입점
├── .gitignore        # Git 제외 파일
├── index.html        # 메인 HTML 파일
├── package.json      # 프로젝트 설정 및 종속성 목록
├── vite.config.js    # Vite 설정 파일</code></pre><h2 id="🎯-3-기본-컴포넌트-구조">🎯 3. 기본 컴포넌트 구조</h2>
<h3 id="✅-appjsx">✅ <code>App.jsx</code></h3>
<pre><code class="language-jsx">import { useState } from &#39;react&#39;;
import &#39;./App.css&#39;;

function App() {
  const [count, setCount] = useState(0);

  return (
    &lt;div className=&quot;container&quot;&gt;
      &lt;h1&gt;React + Vite&lt;/h1&gt;
      &lt;p&gt;카운트: {count}&lt;/p&gt;
      &lt;button onClick={() =&gt; setCount(count + 1)}&gt;증가&lt;/button&gt;
    &lt;/div&gt;
  );
}

export default App;</code></pre>
<ul>
<li><code>useState</code>를 사용하여 상태를 관리합니다.</li>
<li>버튼을 클릭하면 <code>count</code> 상태가 증가합니다.</li>
</ul>
<h2 id="🎯-4-상태-관리-recoil">🎯 4. 상태 관리 (Recoil)</h2>
<h3 id="✅-recoil-설치">✅ Recoil 설치</h3>
<pre><code class="language-sh">npm install recoil</code></pre>
<h3 id="✅-storejs-recoil-상태-관리">✅ <code>store.js</code> (Recoil 상태 관리)</h3>
<pre><code class="language-jsx">import { atom } from &#39;recoil&#39;;

export const countState = atom({
  key: &#39;countState&#39;,
  default: 0,
});</code></pre>
<h3 id="✅-counterjsx-recoil-활용">✅ <code>Counter.jsx</code> (Recoil 활용)</h3>
<pre><code class="language-jsx">import { useRecoilState } from &#39;recoil&#39;;
import { countState } from &#39;../store&#39;;

function Counter() {
  const [count, setCount] = useRecoilState(countState);

  return (
    &lt;div&gt;
      &lt;p&gt;Recoil 카운트: {count}&lt;/p&gt;
      &lt;button onClick={() =&gt; setCount(count + 1)}&gt;Recoil 증가&lt;/button&gt;
    &lt;/div&gt;
  );
}

export default Counter;</code></pre>
<h2 id="🎯-5-react-router-설정">🎯 5. React Router 설정</h2>
<h3 id="✅-react-router-설치">✅ React Router 설치</h3>
<pre><code class="language-sh">npm install react-router-dom</code></pre>
<h3 id="✅-mainjsx에서-설정">✅ <code>main.jsx</code>에서 설정</h3>
<pre><code class="language-jsx">import React from &#39;react&#39;;
import ReactDOM from &#39;react-dom/client&#39;;
import { BrowserRouter } from &#39;react-router-dom&#39;;
import App from &#39;./App&#39;;

ReactDOM.createRoot(document.getElementById(&#39;root&#39;)).render(
  &lt;BrowserRouter&gt;
    &lt;App /&gt;
  &lt;/BrowserRouter&gt;
);</code></pre>
<h3 id="✅-appjsx에서-라우팅-설정">✅ <code>App.jsx</code>에서 라우팅 설정</h3>
<pre><code class="language-jsx">import { Routes, Route, Link } from &#39;react-router-dom&#39;;
import Home from &#39;./pages/Home&#39;;
import About from &#39;./pages/About&#39;;

function App() {
  return (
    &lt;div&gt;
      &lt;nav&gt;
        &lt;Link to=&quot;/&quot;&gt;홈&lt;/Link&gt; | &lt;Link to=&quot;/about&quot;&gt;소개&lt;/Link&gt;
      &lt;/nav&gt;
      &lt;Routes&gt;
        &lt;Route path=&quot;/&quot; element={&lt;Home /&gt;} /&gt;
        &lt;Route path=&quot;/about&quot; element={&lt;About /&gt;} /&gt;
      &lt;/Routes&gt;
    &lt;/div&gt;
  );
}

export default App;</code></pre>
<h2 id="🎯-6-api-통신-axios">🎯 6. API 통신 (Axios)</h2>
<h3 id="✅-axios-설치">✅ Axios 설치</h3>
<pre><code class="language-sh">npm install axios</code></pre>
<h3 id="✅-apijs-api-요청-설정">✅ <code>api.js</code> (API 요청 설정)</h3>
<pre><code class="language-jsx">import axios from &#39;axios&#39;;

const api = axios.create({
  baseURL: &#39;https://jsonplaceholder.typicode.com&#39;,
});

export default api;</code></pre>
<h3 id="✅-userlistjsx-api-호출-예제">✅ <code>UserList.jsx</code> (API 호출 예제)</h3>
<pre><code class="language-jsx">import { useEffect, useState } from &#39;react&#39;;
import api from &#39;../api&#39;;

function UserList() {
  const [users, setUsers] = useState([]);

  useEffect(() =&gt; {
    api.get(&#39;/users&#39;).then((response) =&gt; {
      setUsers(response.data);
    });
  }, []);

  return (
    &lt;ul&gt;
      {users.map((user) =&gt; (
        &lt;li key={user.id}&gt;{user.name}&lt;/li&gt;
      ))}
    &lt;/ul&gt;
  );
}

export default UserList;</code></pre>
<h2 id="🎯-7-스타일링-tailwind-css-적용">🎯 7. 스타일링 (Tailwind CSS 적용)</h2>
<h3 id="✅-tailwind-css-설치">✅ Tailwind CSS 설치</h3>
<pre><code class="language-sh">npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p</code></pre>
<h3 id="✅-tailwind-설정-tailwindconfigjs-수정">✅ Tailwind 설정 (<code>tailwind.config.js</code> 수정)</h3>
<pre><code class="language-js">/** @type {import(&#39;tailwindcss&#39;).Config} */
export default {
  content: [&#39;./index.html&#39;, &#39;./src/**/*.{js,ts,jsx,tsx}&#39;],
  theme: {
    extend: {},
  },
  plugins: [],
};</code></pre>
<h3 id="✅-indexcss에서-tailwind-적용">✅ <code>index.css</code>에서 Tailwind 적용</h3>
<pre><code class="language-css">@tailwind base;
@tailwind components;
@tailwind utilities;</code></pre>
<h3 id="✅-tailwind-활용-예제">✅ Tailwind 활용 예제</h3>
<pre><code class="language-jsx">function Button() {
  return (
    &lt;button className=&quot;bg-blue-500 text-white px-4 py-2 rounded-md&quot;&gt;
      Tailwind 버튼
    &lt;/button&gt;
  );
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[Vue3]]></title>
            <link>https://velog.io/@pyo-dev/Vue3</link>
            <guid>https://velog.io/@pyo-dev/Vue3</guid>
            <pubDate>Thu, 05 Oct 2023 07:56:20 GMT</pubDate>
            <description><![CDATA[<p>vue3 프로젝트 생성부터 활용까지 알아보도록 하자</p>
<hr>
<h2 id="🥠-project-생성">🥠 Project 생성</h2>
<blockquote>
<p>2023-10-18 <a href="https://vuejs.org/guide/quick-start.html">참조사이트</a>
전제 조건 : Node.js 버전 16.0 이상 설치</p>
</blockquote>
<p>최신 버전의 Node.js가 설치되어 있는지 확인한 다음 명령줄에 다음 명령을 실행합니다(&gt; 기호 제외):</p>
<pre><code>✔ npm init vue@latest</code></pre><p>이 명령은 공식 Vue 프로젝트 스캐폴딩 도구인 create-vue를 설치 및 실행합니다. TypeScript 및 테스트 지원과 같은 몇 가지 선택적 기능에 대한 프롬프트가 표시됩니다:</p>
<pre><code>✔ Project name: … &lt;your-project-name&gt;
✔ Add TypeScript? … No / Yes
✔ Add JSX Support? … No / Yes
✔ Add Vue Router for Single Page Application development? … No / Yes
✔ Add Pinia for state management? … No / Yes
✔ Add Vitest for Unit testing? … No / Yes
✔ Add Cypress for both Unit and End-to-End testing? … No / Yes
✔ Add ESLint for code quality? … No / Yes
✔ Add Prettier for code formatting? … No / Yes

Scaffolding project in ./&lt;your-project-name&gt;...
Done.</code></pre><p>옵션에 대해 확신이 서지 않는다면 일단 엔터키를 눌러 No를 선택하면 됩니다. 프로젝트가 생성되면 지침에 따라 종속 요소를 설치하고 개발 서버를 시작합니다:</p>
<pre><code>&gt; cd &lt;your-project-name&gt;
&gt; npm install
&gt; npm run dev</code></pre><pre><code>&gt; npm run build</code></pre><p>이렇게 하면 프로젝트의 ./dist 디렉터리에 프로덕션에 사용할 수 있는 앱 빌드가 생성됩니다.
프로덕션 <a href="https://vuejs.org/guide/best-practices/production-deployment.html">배포 가이드</a>를 확인하여 앱을 프로덕션에 배포하는 방법에 대해 자세히 알아보세요.</p>
<hr>
<h2 id="🥠-router-설정">🥠 Router 설정</h2>
<p>src/router/index.js</p>
<pre><code class="language-javascript">import { createRouter, createWebHistory } from &#39;vue-router&#39;

const router = createRouter({
    history: createWebHistory(import.meta.env.BASE_URL),

    routes: [

        // 404
        {
            path: &quot;/404&quot;,
            name: &quot;Page404&quot;,
            component: () =&gt; import(&#39;@/views/warning/Page404.vue&#39;),
            meta: {
                notCheckLogin: true,
            }
        },
        {
            path: &quot;/:pathMatch(.*)*&quot;,
            redirect: &quot;/404&quot;,
            meta: {
                notCheckLogin: true,
            }
        },
        //// 404

        {
            path: &#39;/&#39;,
            component: () =&gt; import(&#39;@/components/layout/Default.vue&#39;),
            children: [
                {
                    path: &#39;&#39;,
                    name: &#39;Home&#39;,
                    component: () =&gt; import(&#39;@/views/Home.vue&#39;),
                },
                {
                    path: &#39;mypage&#39;,
                    name: &#39;Mypage&#39;,
                    component: () =&gt; import(&#39;@/views/Mypage.vue&#39;),
                },
            ],
        },
        {
            path: &#39;/notice&#39;,
            component: () =&gt; import(&#39;@/components/layout/Full.vue&#39;),
            children: [
                {
                    path: &#39;&#39;,
                    name: &#39;NoticeList&#39;,
                    component: () =&gt; import(&#39;@/views/notice/Index.vue&#39;),
                },
                {
                    path: &#39;detail/:PO_NO&#39;,
                    name: &#39;NoticeDetail&#39;,
                    component: () =&gt; import(&#39;@/views/notice/Detail.vue&#39;),
                },
                {
                    path: &#39;write/:PO_NO?&#39;,
                    name: &#39;NoticeWrite&#39;,
                    component: () =&gt; import(&#39;@/views/notice/Write.vue&#39;),
                },
            ],
        },
    ]
})

export default router</code></pre>
<p>NoticeDetail &gt; :{params} 을 사용하면 필수값
NoticeWrite &gt; :{params}? 을 사용하면 선택값</p>
<p>view/*.vue</p>
<pre><code>&lt;script setup&gt;
import { computed } from &#39;vue&#39;
import { useRoute } from &#39;vue-router&#39;

const route = useRoute()

let PARAMS = computed(() =&gt; {
    return route.params
})
let PO_NO = computed(() =&gt; {
    return PARAMS.value.PO_NO
})

console.log(PARAMS.value.PO_NO);
console.log(PO_NO);
&lt;/script&gt;
&lt;template&gt;
    {{ PARAMS.PO_NO }}
    {{ PO_NO }}
&lt;/template&gt;</code></pre><hr>
<h2 id="🥠-lifecycle-hooks-살펴보기">🥠 Lifecycle Hooks 살펴보기</h2>
<p>각 Vue 컴포넌트 인스턴스는 생성될 때 일련의 초기화 단계를 거칩니다. 예를 들어, 데이터 감시를 설정하고, 템플릿을 컴파일하고, 인스턴스를 DOM에 마운트하고, 데이터가 변경되면 DOM을 업데이트해야 합니다. 그 과정에서 생명 주기 훅(lifecycle hooks)이라 불리는 함수도 실행하여, 특정 단계에서 개발자가 의도하는 로직이 실행될 수 있도록 합니다.</p>
<h3 id="🍩-생명-주기-훅-등록하기">🍩 생명 주기 훅 등록하기</h3>
<p>예를 들어 onMounted 훅은 컴포넌트가 초기 렌더링 및 DOM 노드 생성이 완료된 후 코드를 실행하는 데 사용할 수 있습니다:</p>
<pre><code>&lt;script setup&gt;
import { onMounted } from &#39;vue&#39;

onMounted(() =&gt; {
  console.log(`컴포넌트가 마운트 됐습니다.`)
})
&lt;/script&gt;</code></pre><p>인스턴스 생명 주기의 여러 단계에서 호출되는 다른 훅도 있으며, 가장 일반적으로 사용되는 것은 onMounted, onUpdated, onUnmounted가 있습니다.
onMounted를 호출하면, Vue는 등록된 콜백 함수를 현재 활성 컴포넌트 인스턴스와 자동으로 연결합니다. 이를 위해서는 컴포넌트 설정 중에 이러한 훅은 동기적으로 등록해야 합니다. 예를 들어 다음과 같이 하지 마십시오:</p>
<pre><code class="language-javascript">setTimeout(() =&gt; {
  onMounted(() =&gt; {
    // 작동하지 않습니다.
  })
}, 100)</code></pre>
<br/>

<h3 id="🍩-생명-주기-표">🍩 생명 주기 표</h3>
<p>다음은 인스턴스 생명 주기에 대한 표입니다. 지금 진행 중인 모든 것을 완전히 이해할 필요는 없지만, 더 많이 배우고 구축함에 따라 유용한 참고 자료가 될 것입니다.
<img src="https://velog.velcdn.com/images/pyo-dev/post/96267879-ba65-4cb0-9f3a-08b0be74fdc6/image.png" alt="">
생명 주기 훅의 모든 종류와 사용 사례에 대한 자세한 내용은 <a href="https://vuejs.org/api/composition-api-lifecycle.html">생명 주기 API</a>를 참조하세요.</p>
<hr>
<h2 id="🥠-composition-api-살펴보기">🥠 Composition API 살펴보기</h2>
<h3 id="🍩-컴포지션-api란">🍩 컴포지션 API란?</h3>
<p>컴포지션(Composition) API는 옵션을 선언하는 대신 import한 함수를 사용하여 Vue 컴포넌트를 작성할 수 있는 API 세트입니다. 이것은 아래 API를 다루는 포괄적인 용어입니다:</p>
<p>반응형(Reactivity) API: 예를 들어 ref() 및 reactive()를 사용하여 반응형 상태, 계산된 상태 및 감시자를 직접 생성할 수 있습니다.</p>
<p>생명주기 훅: 예를 들어 onMounted() 및 onUnmounted()를 사용하여 컴포넌트 생명주기에 프로그래밍 방식으로 연결할 수 있습니다.</p>
<p>의존성 주입(Dependency Injection): provide() 및 inject()를 사용하면 반응형 API를 사용하는 동안 Vue의 의존성 주입 시스템을 활용할 수 있습니다.</p>
<p>컴포지션 API는 Vue 3 및 Vue 2.7에 내장된 기능입니다. 이전 Vue 2 버전의 경우 공식적으로 유지 관리되는 @vue/composition-api 플러그인을 사용하십시오. Vue 3에서는 주로 싱글 파일 컴포넌트에서 <a href="https://vuejs.org/api/sfc-script-setup.html">&lt;스크립트 설정&gt;</a> 구문과 함께 사용되기도 합니다. 다음은 컴포지션 API를 사용하는 컴포넌트의 기본 예시입니다:</p>
<pre><code>&lt;script setup&gt;
import { ref, onMounted } from &#39;vue&#39;

// 반응형 상태
const count = ref(0)

// 상태를 변경하고 업데이트를 트리거하는 함수
function increment() {
  count.value++
}

// 생명주기 훅
onMounted(() =&gt; {
  console.log(`숫자를 세기 위한 초기값은 ${count.value} 입니다.`)
})
&lt;/script&gt;

&lt;template&gt;
  &lt;button @click=&quot;increment&quot;&gt;숫자 세기: {{ count }}&lt;/button&gt;
&lt;/template&gt;</code></pre><p>함수 구성에 기반한 API 스타일에도 불구하고 컴포지션 API는 함수형 프로그래밍이 아닙니다. 컴포지션 API는 Vue의 변경 가능하고 세분화된 반응성 패러다임을 기반으로 하는 반면 기능적 프로그래밍은 불변성을 강조합니다.</p>
<h3 id="🍩-왜-컴포지션-api인가요">🍩 왜 컴포지션 API인가요?</h3>
<h4 id="1-더-나은-로직-재사용성">1. 더 나은 로직 재사용성</h4>
<p>컴포지션 API의 가장 큰 장점은 컴포저블 함수의 형태로 깔끔하고 효율적인 로직 재사용이 가능하다는 것입니다. 옵션 API의 기본 로직 재사용 메커니즘인 믹스인의 모든 단점을 해결합니다.</p>
<p>컴포지션 API의 로직 재사용 기능은 컴포저블 유틸리티의 계속 성장하는 컬렉션인 VueUse와 같은 인상적인 커뮤니티 프로젝트를 탄생시켰습니다. 또한 상태 저장 타사 서비스 또는 라이브러리를 불변 데이터, 상태 머신 및 RxJS와 같은 Vue의 반응형 시스템에 쉽게 통합하기 위한 깔끔한 메커니즘 역할을 합니다.</p>
<h4 id="2-보다-유연한-코드-구성">2. 보다 유연한 코드 구성</h4>
<p>많은 사용자는 기본적으로 옵션 API를 사용하여 조직화된 코드를 작성하는 것을 좋아합니다. 그러나 옵션 API는 단일 컴포넌트의 논리가 특정 복잡성 임계값을 초과하는 경우 심각한 제한을 가집니다. 이 제한은 여러 프로덕션 Vue 2 앱에서 직접 목격한 여러 논리적 문제를 처리해야 하는 컴포넌트에서 특히 두드러집니다.</p>
<p>Vue CLI의 GUI에서 폴더 탐색기 컴포넌트를 예로 들어 보겠습니다. 이 컴포넌트는 다음과 같은 논리적 문제를 야기합니다:</p>
<ol>
<li>현재 폴더 상태 추적 및 내용 표시</li>
<li>폴더 탐색 처리(열기, 닫기, 새로 고침...)</li>
<li>새 폴더 생성 처리</li>
<li>즐겨찾기 폴더만 표시 전환</li>
<li>숨김 폴더 표시 전환</li>
<li>현재 작업 디렉터리 변경 처리</li>
</ol>
<p>동일한 논리적 문제와 관련된 코드가 어떻게 그룹화 되었는지 보십시오. 특정 논리적 문제를 해결하는 동안 더 이상 다른 옵션 블록 사이를 이동할 필요가 없습니다. 또한, 추출을 위해 더 이상 코드를 섞을 필요가 없기 때문에 최소한의 노력으로 코드 그룹을 외부 파일로 이동할 수 있습니다. 리팩토링을 위한 소모 시간 감소는 대규모 코드베이스에서 장기적인 유지 관리의 핵심입니다.
<img src="https://velog.velcdn.com/images/pyo-dev/post/04b6d3af-67e6-4ce7-a24c-62a5af420ea1/image.png" alt=""></p>
<hr>
<h2 id="🥠-script-setup-살펴보기">🥠 Script Setup 살펴보기</h2>
<p>Vue 3의 <code>&lt;script setup&gt;</code>은 컴포넌트의 로직을 보다 간결하게 작성할 수 있도록 도와주는 새로운 구문입니다. 기존 setup() 함수보다 직관적이며, 코드량을 줄이고 가독성을 높일 수 있습니다.</p>
<h3 id="🍩-기본-문법">🍩 기본 문법</h3>
<p>기존 setup() 함수를 사용할 경우:</p>
<pre><code>&lt;script&gt;
import { ref } from &#39;vue&#39;;

export default {
  setup() {
    const count = ref(0);
    function increment() {
      count.value++;
    }

    return { count, increment };
  },
};
&lt;/script&gt;

&lt;template&gt;
  &lt;button @click=&quot;increment&quot;&gt;숫자 세기: {{ count }}&lt;/button&gt;
&lt;/template&gt;</code></pre><p><code>&lt;script setup&gt;</code>을 사용하면 다음과 같이 더욱 간결하게 표현할 수 있습니다:</p>
<pre><code>&lt;script setup&gt;
import { ref } from &#39;vue&#39;;

const count = ref(0);
const increment = () =&gt; count.value++;
&lt;/script&gt;

&lt;template&gt;
  &lt;button @click=&quot;increment&quot;&gt;숫자 세기: {{ count }}&lt;/button&gt;
&lt;/template&gt;</code></pre><ul>
<li>export default 불필요</li>
<li>setup() 함수 선언 없이 바로 변수 및 함수를 정의</li>
<li>return 문이 필요 없음<h3 id="🍩-defineprops와-defineemits">🍩 defineProps와 defineEmits</h3>
<code>&lt;script setup&gt;</code>을 사용할 경우 defineProps()와 defineEmits()를 통해 props 및 이벤트를 선언할 수 있습니다.<pre><code>&lt;script setup&gt;
defineProps([&#39;title&#39;]);
defineEmits([&#39;customEvent&#39;]);
&lt;/script&gt;
</code></pre></li>
</ul>
<template>
  <h1>{{ title }}</h1>
</template>
```

<hr>
<h2 id="🥠-components-활용">🥠 Components 활용</h2>
<p>Vue에서는 컴포넌트를 활용하여 UI를 모듈화할 수 있습니다. <code>&lt;script setup&gt;</code>을 사용할 경우, 컴포넌트 등록이 더욱 간편해집니다.</p>
<h3 id="🍩-기본-컴포넌트-예제">🍩 기본 컴포넌트 예제</h3>
<p>HelloWorld.vue</p>
<pre><code>&lt;script setup&gt;
defineProps([&#39;msg&#39;]);
&lt;/script&gt;

&lt;template&gt;
  &lt;h1&gt;{{ msg }}&lt;/h1&gt;
&lt;/template&gt;</code></pre><p>App.vue에서 컴포넌트를 사용하려면:</p>
<pre><code>&lt;script setup&gt;
import HelloWorld from &#39;@/components/HelloWorld.vue&#39;;
&lt;/script&gt;

&lt;template&gt;
  &lt;HelloWorld msg=&quot;Hello Vue 3!&quot; /&gt;
&lt;/template&gt;</code></pre><hr>
<h2 id="🥠-props-활용">🥠 Props 활용</h2>
<p>부모 → 자식 컴포넌트 간 데이터를 전달하는 방법은 props를 사용하는 것입니다.</p>
<h3 id="🍩-기본적인-props-사용">🍩 기본적인 props 사용</h3>
<pre><code>&lt;script setup&gt;
defineProps({
  title: String,
  count: {
    type: Number,
    required: true,
  },
});
&lt;/script&gt;

&lt;template&gt;
  &lt;h1&gt;{{ title }}&lt;/h1&gt;
  &lt;p&gt;현재 숫자: {{ count }}&lt;/p&gt;
&lt;/template&gt;</code></pre><h3 id="🍩-props의-기본값-설정">🍩 Props의 기본값 설정</h3>
<pre><code>&lt;script setup&gt;
defineProps({
  message: {
    type: String,
    default: &#39;기본 메시지&#39;,
  },
});
&lt;/script&gt;

&lt;template&gt;
  &lt;p&gt;{{ message }}&lt;/p&gt;
&lt;/template&gt;</code></pre><hr>
<h2 id="🥠-state-managementpinia-활용">🥠 State Management(pinia) 활용</h2>
<p>Vue 3에서는 상태 관리를 위해 Vuex 대신 Pinia를 추천합니다.</p>
<h3 id="🍩-pinia-설치">🍩 Pinia 설치</h3>
<pre><code>npm install pinia</code></pre><h3 id="🍩-pinia-스토어-생성-storecounterjs">🍩 Pinia 스토어 생성 (store/counter.js)</h3>
<pre><code>import { defineStore } from &#39;pinia&#39;;
import { ref } from &#39;vue&#39;;

export const useCounterStore = defineStore(&#39;counter&#39;, () =&gt; {
  const count = ref(0);
  const increment = () =&gt; count.value++;

  return { count, increment };
});</code></pre><h3 id="🍩-pinia-사용-appvue">🍩 Pinia 사용 (App.vue)</h3>
<pre><code>&lt;script setup&gt;
import { useCounterStore } from &#39;@/store/counter&#39;;

const counter = useCounterStore();
&lt;/script&gt;

&lt;template&gt;
  &lt;button @click=&quot;counter.increment&quot;&gt;Count: {{ counter.count }}&lt;/button&gt;
&lt;/template&gt;</code></pre><ul>
<li>defineStore를 사용하여 스토어 생성</li>
<li>ref()로 반응형 상태 관리</li>
<li>useCounterStore()를 호출하여 상태 및 메서드 사용</li>
</ul>
<hr>
<h2 id="🥠-비동기통신axios-활용">🥠 비동기통신(axios) 활용</h2>
<p>Vue 3에서 axios를 사용하여 API 통신을 수행할 수 있습니다.</p>
<h3 id="🍩-axios-설치">🍩 axios 설치</h3>
<pre><code>npm install axios</code></pre><h3 id="🍩-api-호출-예제-apijs">🍩 API 호출 예제 (api.js)</h3>
<pre><code>import axios from &#39;axios&#39;;

const api = axios.create({
  baseURL: &#39;https://jsonplaceholder.typicode.com&#39;,
  timeout: 5000,
});

export default api;</code></pre><h3 id="🍩-api-데이터-가져오기-userlistvue">🍩 API 데이터 가져오기 (UserList.vue)</h3>
<pre><code>&lt;script setup&gt;
import { ref, onMounted } from &#39;vue&#39;;
import api from &#39;@/api&#39;;

const users = ref([]);

onMounted(async () =&gt; {
  try {
    const response = await api.get(&#39;/users&#39;);
    users.value = response.data;
  } catch (error) {
    console.error(&#39;Error fetching users:&#39;, error);
  }
});
&lt;/script&gt;

&lt;template&gt;
  &lt;ul&gt;
    &lt;li v-for=&quot;user in users&quot; :key=&quot;user.id&quot;&gt;
      {{ user.name }}
    &lt;/li&gt;
  &lt;/ul&gt;
&lt;/template&gt;</code></pre><ul>
<li>axios를 활용하여 API 요청</li>
<li>onMounted() 훅을 사용하여 컴포넌트가 마운트될 때 데이터를 가져옴</li>
<li>ref()를 사용하여 반응형 상태 관리</li>
</ul>
<hr>
]]></description>
        </item>
        <item>
            <title><![CDATA[css parents height]]></title>
            <link>https://velog.io/@pyo-dev/css-parents-height</link>
            <guid>https://velog.io/@pyo-dev/css-parents-height</guid>
            <pubDate>Fri, 17 Jul 2020 01:05:36 GMT</pubDate>
            <description><![CDATA[<p>얼마 전 element가 position absolute의 속성을 갖고 있을 경우 부모 element의 height를 자식 element의 height 만큼 적용 가능한지에 관한 질문이 질문이 하코사에 올라와 있었다.
그 방법에 대하여 알아보자</p>
<hr>
<p>하코사 질문 링크
<a href="https://cafe.naver.com/hacosa/274899">https://cafe.naver.com/hacosa/274899</a></p>
<hr>
<p>!codepen[pyo-dev/embed/gOPBReX?height=265&amp;theme-id=dark&amp;default-tab=html,result]</p>
<p>먼저 가능하다.</p>
<p>자식 요소의 비율을 계산해서 부모 요소에 padding-top 또는 padding-bottom을 주면 된다</p>
<p>가령 자식 요소가 positio absolute를 갖고 있고 
비율이 가로, 세로 100px, 50px라면 
paddin-top 또는 padding-bottom을 50%를 주면 된다.</p>
<p>다만 반응형 웹에 콘텐츠가 이미지가 아닌 텍스트로 height가 비율이 아닌 유기적으로 변동된다면 이는 css만으로는 불가능하다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[vanilla javascript slidetoggle]]></title>
            <link>https://velog.io/@pyo-dev/vanilla-javascript-slidetoggle</link>
            <guid>https://velog.io/@pyo-dev/vanilla-javascript-slidetoggle</guid>
            <pubDate>Wed, 15 Jul 2020 01:59:24 GMT</pubDate>
            <description><![CDATA[<p>vanilla javascript로 slideToggle구현 하기</p>
<p>!codepen[pyo-dev/embed/RwrYxaY?height=265&amp;theme-id=dark&amp;default-tab=html,result]</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[SASS란?]]></title>
            <link>https://velog.io/@pyo-dev/SASS%EB%9E%80</link>
            <guid>https://velog.io/@pyo-dev/SASS%EB%9E%80</guid>
            <pubDate>Thu, 02 Jul 2020 03:06:27 GMT</pubDate>
            <description><![CDATA[<hr>
<h2 id="🥠-sass란">🥠 SASS란?</h2>
<ul>
<li>CSS를 효율적으로 작성할 수 있도록 도와주는 전처리기( CSS Preprocessor) 입니다.</li>
<li>기존의 CSS의 유지보수의 불편함 등을 SASS를 사용하면 해결 할 수 있다.</li>
<li>위에서 언급한 CSS의 단점을 보완하기 위한 기술로, SASS 자체를 그대로 사용할수는 없고, SASS의 문법에 맞게 SASS파일을 만들면 컨버터를 이용해서 CSS를 생성한다.</li>
<li>즉, SASS문법에 맞게 CSS를 작성하고, SASS 컴파일러를 사용하여 HTML이 이해 할 수 있는 문법으로 변환합니다.</li>
</ul>
<hr>
<h2 id="🥠-sass-장점">🥠 SASS 장점</h2>
<ol>
<li>autoprefixer 를 제공한다.</li>
<li>코드중복을 줄일수 있다.</li>
<li>변수를 사용 할 수 있기 때문에 유지보수가 쉬워진다.</li>
<li>@import, @include, @mixin, @extend 등 다양한 함수 및 변수를 제공한다</li>
</ol>
<hr>
<h2 id="🥠-sass-compile">🥠 SASS compile</h2>
<ol>
<li>ruby를 활용하여 compile - <a href="https://sass-lang.com/documentation/cli/ruby-sass">https://sass-lang.com/documentation/cli/ruby-sass</a></li>
<li>번들러를 활용한 compile - <a href="https://d2.naver.com/helloworld/5644368">https://d2.naver.com/helloworld/5644368</a></li>
<li>에디터를 이용한 compile - vscode, brackets 등</li>
</ol>
<hr>
<h2 id="🥠-sass-vs-scss">🥠 SASS vs SCSS</h2>
<p>Sass(Syntactically Awesome Style Sheets)의 3버전에서 새롭게 등장한 SCSS는 CSS 구문과 완전히 호환되도록 새로운 구문을 도입해 만든 Sass의 모든 기능을 지원하는 CSS의 상위집합(Superset) 입니다.
즉, SCSS는 CSS와 거의 같은 문법으로 Sass 기능을 지원한다는 말입니다.
Sass는 선택자의 유효범위를 ‘들여쓰기’로 구분하고, SCSS는 {}로 범위를 구분합니다.</p>
<hr>
<blockquote>
<ol>
<li>sass 문법은 들여쓰기로 유호 범위를 구분하기 때문에 협업을하거나 유지보수 측면에서 스페이스로 인한 오류를 범하기 쉽다.</li>
</ol>
</blockquote>
<ol>
<li>scss 문법은 css 문법과 거의 동일하며 sass의 장점을 내포하고 있어 누구나 쉽게 접근이 가능하고 활용하기 좋다.</li>
</ol>
<p>--
SASS 참조 사이트
<a href="http://sass-lang.com/">http://sass-lang.com/</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[CSS 방법론[SMACSS, BEM, OOCSS]]]></title>
            <link>https://velog.io/@pyo-dev/CSS-%EB%B0%A9%EB%B2%95%EB%A1%A0</link>
            <guid>https://velog.io/@pyo-dev/CSS-%EB%B0%A9%EB%B2%95%EB%A1%A0</guid>
            <pubDate>Thu, 02 Jul 2020 02:59:39 GMT</pubDate>
            <description><![CDATA[<h2 id="🥠-공통-지향점">🥠 공통 지향점</h2>
<ol>
<li>코드의 재사용성 높이기</li>
<li>쉽게 유지보수 할 수 있도록 하기</li>
<li>확장 가능하게 하기</li>
<li>클래스명으로 무슨 의미인지 예측 가능하도록 하기</li>
</ol>
<hr>
<h2 id="🥠-smacssscalable--modular-architecture-for-css">🥠 SMACSS(Scalable &amp; Modular Architecture for CSS)</h2>
<ul>
<li>Class명을 통한 예측</li>
<li>재사용</li>
<li>쉬운 유지보수</li>
<li>확장</li>
</ul>
<ol>
<li><p>Base</p>
<ul>
<li>기본 스타일(Reset, Default .. )</li>
<li>기본 스타일에는 !important 사용할 필요가 없다.</li>
</ul>
</li>
<li><p>Layout</p>
<ul>
<li>레이아웃과 관련된 스타일 정의</li>
<li>class명에 &#39;l-&#39; suffix(접미사)를 붙인다.</li>
</ul>
</li>
<li><p>Module</p>
<ul>
<li>모듈과 관련된 스타일 정의</li>
<li>스타일 재사용을 위한 요소다</li>
<li>Block, Element, Module</li>
<li>재사용을 위해 ID와 element 사용 금지(element를 사용해야 한다면 자식 선택자를 사용한다)</li>
</ul>
</li>
<li><p>State</p>
<ul>
<li>상태를 나타내는 스타일 정의</li>
<li>hidden, expend, active, hover 등</li>
<li>class명에 &#39;s-&#39; suffix를 붙인다.</li>
</ul>
</li>
<li><p>Theme</p>
<ul>
<li>사이트의 전반적인 look과 feel 제어</li>
<li>색이나 이미지를 불변하는 스타일과 분리 → 기존의 스타일을 재선언 할 수 있다.</li>
<li>적용 점위가 넓으면 &#39;theme-&#39; suffix를 붙인다.</li>
</ul>
</li>
<li><p>유의사항</p>
<ul>
<li>파생된 선택자 사용 금지</li>
<li>ID 사용 금지</li>
<li>!important 사용 금지</li>
<li>class명은 의미있게</li>
<li>class명은 다른이가 이해할 수 있도록 선언</li>
</ul>
</li>
</ol>
<hr>
<h2 id="🥠-bemblock-element-modifier">🥠 BEM(Block Element Modifier)</h2>
<ul>
<li>Block, Element, Module 약자</li>
<li>ID는 사용할 수 없다.</li>
<li>오직 Class명만 사용한다.</li>
<li>ex) .header_navigation-secondary</li>
</ul>
<ol>
<li><p>Block</p>
<ul>
<li>문단 전체에 적용된 element 또는 element를 담고 있는 컨테이너</li>
<li>head block &gt; menu block, logo block, search block, auth block...</li>
</ul>
</li>
<li><p>Element</p>
<ul>
<li>block 안에서 특정 기능을 수행하는 컴포넌트</li>
<li>element는 상황에 따라 달라진다.</li>
<li>각 element는 두 개의 밑줄표시로 연결하여 block다음에 작성한다.</li>
<li>ex) .header__logo, .header__search, .header__menu, .header__login 등</li>
<li>block과 element명이 길면 &#39;-&#39;으로 연결한다.</li>
<li>ex) .block-name__element-name</li>
</ul>
</li>
<li><p>Modifiers(수식어, 접미사)</p>
<ul>
<li>block, element의 속성이다.</li>
<li>이 속성은 block, element의 외관과 상태를 변화시킨다.</li>
<li>class명은 &#39;-&#39; 추가하여 modifier 추가</li>
<li>class명은 구체적이고 명료해야 한다.</li>
<li>class명은 HTML 안에서도 읽기 쉬워야 한다.</li>
<li>class명은 무엇을 나타내는지 분명해야 한다.</li>
</ul>
</li>
</ol>
<hr>
<h2 id="🥠-oocssobject-oriented-css">🥠 OOCSS(Object Oriented CSS)</h2>
<ul>
<li>Object Oriented Css 약자</li>
<li>css를 모듈화하여 중복을 최소화 한다</li>
<li>구조와 외양을 분리한다.</li>
<li>결합하면 다양한 결과물을 얻을 수 있다.</li>
<li>외양 : .button, .box, .widget, .skin...</li>
<li>컨테이너와 컨텐츠 분리</li>
<li>ex) .globalwidth + .header-inside / .main / .footer-inside</li>
<li>ex) .btnbase + .twitter / .facebook</li>
<li>단점) 다중 클래스 사용으로 HTML코드가 복잡해 진다.</li>
<li>단점 ) non-semantic한 클래스 사용</li>
</ul>
<hr>
<p>참조 
<a href="https://github.com/hohoya33/css-methodologies">https://github.com/hohoya33/css-methodologies</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[javascript 함수 sort()]]></title>
            <link>https://velog.io/@pyo-dev/javascript-%ED%95%A8%EC%88%98-sort</link>
            <guid>https://velog.io/@pyo-dev/javascript-%ED%95%A8%EC%88%98-sort</guid>
            <pubDate>Mon, 29 Jun 2020 07:00:40 GMT</pubDate>
            <description><![CDATA[<p>javascript 함수 sort()에 대하여 알아보도록 하자.</p>
<hr>
<p>ASCII 문자 순서(오름차순)로 정렬된다.</p>
<h2 id="🥠-문자-정렬">🥠 문자 정렬</h2>
<pre><code class="language-javascript">let arr = [&#39;lg&#39;, &#39;samsung&#39;, &#39;apple&#39;];

arr.sort();
console.log(arr); // output [&quot;apple&quot;, &quot;lg&quot;, &quot;samsung&quot;]</code></pre>
<hr>
<h2 id="🥠-숫자-정렬">🥠 숫자 정렬</h2>
<pre><code class="language-javascript">let arr = [25, 2, 4, 12, 11, 1, 6];

arr.sort();
console.log(arr); // output [1, 11, 12, 2, 25, 4, 6]

arr.sort(function(a, b) { // 오름차순
    return a - b;
});
console.log(arr); // output [1, 2, 4, 6, 11, 12, 25]

arr.sort(function(a, b) { // 내림차순
    return b - a;
});
console.log(arr); // output [25, 12, 11, 6, 4, 2, 1]</code></pre>
<hr>
<h2 id="🥠-object-정렬">🥠 Object 정렬</h2>
<pre><code class="language-javascript">var obj = [
    { name : &quot;학근&quot;, age : 22},
    { name : &quot;수호&quot;, age : 100},
    { name : &quot;정민&quot;, age : 18},
    { name : &quot;승권&quot;, age : 2},
    { name : &quot;기준&quot;, age : 21},
    { name : &quot;동섭&quot;, age : 11},
    { name : &quot;명호&quot;, age : 14},
    { name : &quot;종호&quot;, age : 77}
]</code></pre>
<h3 id="🥠-이름-순서로-정렬">🥠 이름 순서로 정렬</h3>
<pre><code class="language-javascript">obj.sort(function(a, b) {
    return a.name &lt; b.name ? -1 : a.name &gt; b.name ? 1 : 0;
});

console.log(obj);
/**
output

0: {name: &quot;기준&quot;, age: 21}
1: {name: &quot;동섭&quot;, age: 11}
2: {name: &quot;명호&quot;, age: 14}
3: {name: &quot;수호&quot;, age: 100}
4: {name: &quot;승권&quot;, age: 2}
5: {name: &quot;정민&quot;, age: 18}
6: {name: &quot;종호&quot;, age: 77}
7: {name: &quot;학근&quot;, age: 22}
*/</code></pre>
<hr>
<h3 id="🥠-나이-순서로-정렬">🥠 나이 순서로 정렬</h3>
<pre><code class="language-javascript">obj.sort(function(a, b) { // 이름순 정렬
    return a.age &lt; b.age ? -1 : a.age &gt; b.age ? 1 : 0;
});

console.log(obj);
/**
output

0: {name: &quot;승권&quot;, age: 2}
1: {name: &quot;동섭&quot;, age: 11}
2: {name: &quot;명호&quot;, age: 14}
3: {name: &quot;정민&quot;, age: 18}
4: {name: &quot;기준&quot;, age: 21}
5: {name: &quot;학근&quot;, age: 22}
6: {name: &quot;종호&quot;, age: 77}
7: {name: &quot;수호&quot;, age: 100}
*/</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[JavaScript 배열 메소드 ( Array method )]]></title>
            <link>https://velog.io/@pyo-dev/JavaScript-%EB%B0%B0%EC%97%B4-%EB%A9%94%EC%86%8C%EB%93%9C-Array-method</link>
            <guid>https://velog.io/@pyo-dev/JavaScript-%EB%B0%B0%EC%97%B4-%EB%A9%94%EC%86%8C%EB%93%9C-Array-method</guid>
            <pubDate>Mon, 29 Jun 2020 05:11:53 GMT</pubDate>
            <description><![CDATA[<h2 id="🥠-arrayisarray">🥠 Array.isArray()</h2>
<p>인자에 들어가는 객체가 배열인지 확인할 때 사용
인자 - object</p>
<pre><code class="language-javascript">Array.isArray({ a: 1, b: 2}) /// false 
Array.isArray([1,2,3]) //true</code></pre>
<hr>
<h2 id="🥠-concat">🥠 concat()</h2>
<p>인자로 주어진 배열이나 값들을 기존 배열에 합쳐서 새 배열을 반환
인자 - item1, item2, …</p>
<pre><code class="language-javascript">const arr = [1,2,3]
arr.concat(4,5) // [1,2,3,4,5]
arr.concat([4,5]) // [1,2,3,4,5]
arr // [1,2,3] 원본이 바뀌지 않음</code></pre>
<hr>
<h2 id="🥠-every-some">🥠 every(), some()</h2>
<p>배열의 모든 원소가 제공한 함수를 통과하는지 테스트하는 메소드 every
배열의 원소중 하나라도 제공한 함수를 통과하는지 테스트하는 메소드 some
callback의 인자로는</p>
<ol>
<li>rrentValue - 현재 순회하는 원소 값</li>
<li>index - 순회하는 원소의 index</li>
<li>array - 순회되는 배열<pre><code class="language-javascript">const arr = [2,4,6,8]
arr.every( el =&gt; el % 2 === 0 ) // true
arr.some( el =&gt; el % 2 ) // true
arr // [2,4,6,8] 원본이 바뀌지 않음</code></pre>
</li>
</ol>
<hr>
<h2 id="🥠-fill">🥠 fill()</h2>
<p>배열의 시작 인덱스부터 끝 인덱스까지 정적 값으로 채우는 메소드
인자 - value, start(optional), end(optional)
start의 기본값은 0, end의 기본값은 배열의 길이</p>
<pre><code class="language-javascript">const arr = Array(3)
arr.fill(2) // [2,2,2]
arr // [2,2,2] 원본이 바뀜</code></pre>
<hr>
<h2 id="🥠-filter">🥠 filter()</h2>
<p>배열의 원소 중 제공된 함수를 통과하는 원소를 반환하는 메소드
인자 - callback</p>
<pre><code class="language-javascript">const arr = [1,2,3,4,5]
arr.filter( el =&gt; el &lt; 3 ) // [1,2]
arr // [1,2,3,4,5] 원본이 바뀌지 않음</code></pre>
<hr>
<h2 id="🥠-find">🥠 find()</h2>
<p>배열의 원소 중 제공된 함수를 통과하는 첫번째 원소를 반환하는 메소드
첫 번째 원소를 반환하면 해당 함수는 더 이상 loop를 반복하지 않는다
인자 - callback</p>
<pre><code class="language-javascript">const arr = [4, 15, 377, 395, 400, 1024, 3000];
arr.find( el =&gt; el % 5 == 0 ) // 15
arr // [1,2,3,4,5] 원본이 바뀌지 않음</code></pre>
<hr>
<h2 id="🥠-foreach">🥠 forEach()</h2>
<p>배열 원소마다 제공한 함수를 실행하는 메소드
인자 - callback
callback의 인자로는</p>
<ol>
<li>currentValue - 현재 순회하는 원소 값</li>
<li>index - 순회하는 원소의 index</li>
<li>array - 순회되는 배열<pre><code class="language-javascript">const arr = [1,2,3]
arr.forEach( el =&gt; console.log(el) )
// 1
// 2
// 3
arr // [1,2,3] 원본이 바뀌지 않음</code></pre>
</li>
</ol>
<hr>
<h2 id="🥠-includes">🥠 includes()</h2>
<p>배열에 특정 원소가 포함돼 있는지 여부를 확인해 true, false로 리턴
인자 - searchElement, fronIndex ( optional )</p>
<pre><code class="language-javascript">const arr = [1,2,3,4]
arr.includes(3) // true
arr.includes(1,1) // false
arr // [1,2,3,4] 원본이 바뀌지 않음</code></pre>
<hr>
<h2 id="🥠-indexof-lastindexof">🥠 indexOf(), lastIndexOf()</h2>
<p>배열에 특정 원소가 포함돼 있는지 여부를 확인해 있으면 해당 인덱스 만약 없다면 -1을 리턴
lastIndexOf는 반대 순서로 탐색
인자 - searchElement, fronIndex ( optional )</p>
<pre><code class="language-javascript">const arr = [1,2,3,4]
arr.indexOf(3) // 2
arr.indexOf(5) // -1
arr // [1,2,3,4] 원본이 바뀌지 않음</code></pre>
<hr>
<h2 id="🥠-join">🥠 join()</h2>
<p>모든 원소를 연결해 하나의 문자열로 만드는 메소드
인자 - separator</p>
<pre><code class="language-javascript">const arr = [1,2,3,4]
arr.join() // &quot;1,2,3,4&quot;
arr.join(&quot;..&quot;) // &quot;1..2..3..4&quot;
arr // [1,2,3,4] 원본이 바뀌지 않음</code></pre>
<hr>
<h2 id="🥠-map">🥠 map()</h2>
<p>배열 내의 모든 원소에 대하여 제공된 함수를 호출하고,
결과를 모아 새로운 배열을 리턴하는 메소드
인자 - callback
callback의 인자로는</p>
<ol>
<li>currentValue - 현재 순회하는 원소 값</li>
<li>index - 순회하는 원소의 index</li>
<li>array - 순회되는 배열<pre><code class="language-javascript">const arr = [1,2,3]
arr.map( el =&gt; el * 2 ) // [2,4,6]
arr // [1,2,3] 원본이 바뀌지 않음
</code></pre>
</li>
</ol>
<pre><code>
---
## 🥠 push(), pop() / unshift(), shift()
배열의 맨 뒤에 새로운 원소를 추가하는 메소드 push
인자 - item1, item2, …
배열의 맨 뒤 원소를 지우는 메소드 pop
인자 - X
배열의 맨 앞에 새로운 원소를 추가하는 메소드 unshift
인자 - item1, item2, …
배열의 맨 앞 원소를 지우는 메소드 shift
인자 - X
```javascript
const arr = [1,2,3]
arr.push(5) // 4 ( 배열의 길이 리턴 )
arr // [1,2,3,5] 원본이 바뀜
arr.pop() // 5 ( 삭제된 원소 리턴 )
arr // [1,2,3] 원본이 바뀜
arr.unshift(2) // 4 ( 배열의 길이 리턴 )
arr // [2,1,2,3] 원본이 바뀜
arr.shift() // 2 ( 삭제된 원소 리턴 )
arr // [1,2,3] 원본이 바뀜
</code></pre><hr>
<h2 id="🥠-reduce-reduceright">🥠 reduce(), reduceRight()</h2>
<p>배열의 원소마다 누적 계산값과 함께 함수를 적용해 하나의 값으로 리턴
reduce는 왼쪽부터, reduceRight는 오른쪽부터 수행
인자 - callback, initialValue ( optional )
callback의 인자로는</p>
<pre><code class="language-javascript">accumulator - 누적 계산값
currentValue - 현재 처리값
currentIndex - 현재 처리값의 index
array - 호출된 배열
const arr = [1,2,3,4]
arr.reduce( (a,b) =&gt; a+b ) // 10
arr.reduce( (a,b) =&gt; a+b, 10) // 20
arr // [1,2,3,4] 원본이 바뀌지 않음
</code></pre>
<p>단순히 값을 연산하는 용도 뿐만 아니라 여러가지 역할로 사용이 가능</p>
<hr>
<h2 id="🥠-reverse">🥠 reverse()</h2>
<p>인자: 없음
배열의 원소 순서를 반대로 정렬해 반환</p>
<pre><code class="language-javascript">const arr = [1,2,3]
arr.reverse() // [3,2,1]
arr // [3,2,1] 원본이 바뀜
</code></pre>
<hr>
<h2 id="🥠-slice">🥠 slice()</h2>
<p>배열의 start부터 end까지 shallow copy하는 메소드
인자 - start ( optional ), end ( optional )</p>
<pre><code class="language-javascript">const arr = [1,2,3,4,5]
arr.slice(2) // [3,4,5]
arr.slice(1, 3) // [2,3]
arr // [1,2,3,4,5] 원본이 바뀌지 않음
</code></pre>
<hr>
<h2 id="🥠-splice">🥠 splice()</h2>
<p>배열의 원소를 삭제하거나 새 원소를 추가하는 메소드
인자 - start, deleteCount, item1, item2, ..
start부터 deleteCount만큼 삭제되고
뒤로오는 인자들은 삭제된 위치에 추가되는 원소들</p>
<pre><code class="language-javascript">let arr = [1,2,3]
arr.splice(2) // [2,3] ( 삭제된 배열 리턴)
arr // [1] 원본이 바뀜

arr = [1,2,3]
arr.splice(1,1) // [2]
arr // [1,3] 원본이 바뀜

arr = [1,2,3]
arr.splice(1,1,3,4) // [2]
arr // [1,3,4,3] 원본이 바뀜
</code></pre>
<hr>
<h2 id="🥠-sort">🥠 sort()</h2>
<p>배열을 정렬하는데 사용된다.
인자를 넣지 않으면 기본적으로 ASCII 문자 순서로 정렬된다.
인자 - compareFuntion ( optional )</p>
<pre><code class="language-javascript">const arr = [3,20,12,1,4]
arr.sort() // [1, 12, 20, 3, 4]
arr // [1, 12, 20, 3, 4] 원본이 바뀜
</code></pre>
<hr>
<h2 id="🥠-tostring">🥠 toString</h2>
<p>배열의 원소를 문자열로 반환
인자 - X</p>
<pre><code class="language-javascript">const arr = [1,2,3] 
arr.toString() // &quot;1,2,3&quot; 
arr // [1,2,3] 원본이 바뀌지 않음
</code></pre>
<hr>
<p>출처</p>
<p><a href="https://takeuu.tistory.com/102">https://takeuu.tistory.com/102</a></p>
<hr>
<h2 id="🥠-object를-배열로-변환">🥠 Object를 배열로 변환</h2>
<h3 id="🥠-objectkeys">🥠 Object.keys</h3>
<p>object key 값을 배열로 반환
인자 - object</p>
<pre><code class="language-javascript">const arr = {
    pyo: &quot;first name&quot;,
    jung: &quot;middle name&quot;,
    min: &quot;last name&quot;
}
Object.keys(arr); // [&quot;pyo&quot;, &quot;jung&quot;, &quot;min&quot;]
arr // { pyo: &quot;first name&quot;, jung: &quot;middle name&quot;, min: &quot;last name&quot; } 원본이 바뀌지 않음</code></pre>
<hr>
<h3 id="🥠-objectentries">🥠 Object.entries</h3>
<p>object key, value 값을 묶어서 배열로 반환
인자 - object</p>
<pre><code class="language-javascript">const arr = {
    pyo: &quot;first name&quot;,
    jung: &quot;middle name&quot;,
    min: &quot;last name&quot;
}
Object.entries(arr); // [[&quot;pyo&quot;, &quot;first name&quot;], [&quot;jung&quot;, &quot;middle name&quot;], [&quot;min&quot;, &quot;last name&quot;]]
arr // { pyo: &quot;first name&quot;, jung: &quot;middle name&quot;, min: &quot;last name&quot; } 원본이 바뀌지 않음</code></pre>
<hr>
<p>참조</p>
<p><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/entries">https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/entries</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[JavaScript 클로저(Closure)]]></title>
            <link>https://velog.io/@pyo-dev/JavaScript-%ED%81%B4%EB%A1%9C%EC%A0%80Closure</link>
            <guid>https://velog.io/@pyo-dev/JavaScript-%ED%81%B4%EB%A1%9C%EC%A0%80Closure</guid>
            <pubDate>Fri, 19 Jun 2020 05:37:39 GMT</pubDate>
            <description><![CDATA[<p>JavaScript 클로저(Closure)에 대하여 알아보도록 하자.</p>
<h2 id="🥠-클로저closure란">🥠 클로저(Closure)란?</h2>
<p>MDN에서는 <code>함수와 함수가 선언된 어휘적 환경의 조합이다. 클로저를 이해하려면 자바스크립트가 어떻게 변수의 유효범위를 지정하는지(Lexical scoping)를 먼저 이해해야 한다</code>고 정의하고 있다.</p>
<hr>
<h2 id="🥠-정적-유효범위lexical-scope">🥠 정적 유효범위(Lexical scope)</h2>
<p>스코프(scope)는 함수를 호출할 때 결정되는 것이 아니라 함수를 선언할 때 정해진다.
아래 예제를 살펴보자</p>
<pre><code class="language-javascript">function makeFunc() {
  var name = &quot;pyo jung min&quot;;
  function displayName() {
    console.log(name);
  }
  return displayName;
}

var myFunc = makeFunc();
//myFunc변수에 displayName을 리턴함
//유효범위의 어휘적 환경을 유지
myFunc();
//리턴된 displayName 함수를 실행(name 변수에 접근)</code></pre>
<p>오류가 발생할 것 같지만 &#39;pyo jung min&#39;이 오류 없이 출력되는 것을 확인할 수 있다.
이는 함수 호출 이전에 함수 선언 시 이미 정적 유효범위(Lexical scope)가 정해져 있기 때문이다.</p>
<hr>
<h2 id="🥠-클로저-스코프-체인closure-scope-chain">🥠 클로저 스코프 체인(Closure scope chain)</h2>
<p>모든 클로저에는 세가지 스코프(범위)가 있다</p>
<ol>
<li>지역 범위 (Local Scope, Own scope)</li>
<li>외부 함수 범위 (Outer Functions Scope)</li>
<li>전역 범위 (Global Scope)</li>
</ol>
<p>따라서, 우리는 클로저에 대해 세가지 범위 모두 접근할 수 있지만, 중첩된 내부 함수가 있는 경우 종종 실수를 저지른다. 
아래 예제를 확인해보자</p>
<pre><code class="language-javascript">// 전역 범위 (global scope)
var e = 10;
function sum(a){
  return function(b){
    return function(c){
      // 외부 함수 범위 (outer functions scope)
      return function(d){
        // 지역 범위 (local scope)
        return a + b + c + d + e;
      }
    }
  }
}

console.log(sum(1)(2)(3)(4)); // log 20

// 익명 함수 없이 작성할 수도 있다.

// 전역 범위 (global scope)
var e = 10;
function sum(a){
  return function sum2(b){
    return function sum3(c){
      // 외부 함수 범위 (outer functions scope)
      return function sum4(d){
        // 지역 범위 (local scope)
        return a + b + c + d + e;
      }
    }
  }
}

var s = sum(1);
var s1 = s(2);
var s2 = s1(3);
var s3 = s2(4);
console.log(s3) //log 20</code></pre>
<p>위의 예제를 보면 일련의 중첩된 함수들을 확인할 수 있다. 이 함수들은 전부 외부 함수의 스코프에 접근할 수 있다. 그런데 문제는 즉각적인 외부 함수의 스코프만을 추측한다는 것이다. 이 문맥에서는 모든 클로저가 선언된 외부 함수의 스코프에 접근한다라고 말할 수 있다.</p>
<hr>
<h2 id="🥠-루프에서-클로저-생성하기-일반적인-실수">🥠 루프에서 클로저 생성하기: 일반적인 실수</h2>
<p>변수 선언을 var로 할시 클로저와 관련된 일반적인 문제는 루프 안에서 클로저가 생성되었을 때 발생한다.다음 예제를 보자.</p>
<p>!codepen[pyo-dev/embed/BajpdaQ?height=265&amp;theme-id=dark&amp;default-tab=js,result]</p>
<p>error case의 경우 루프에서 세 개의 클로저가 만들어졌지만 각 클로저는 값이 변하는 변수가 (item.help) 있는 같은 단일 환경을 공유한다. onfocus 콜백이 실행될 때 콜백의 환경에서 item 변수는 (세개의 클로저가 공유한다) helpText 리스트의 마지막 요소를 가리키고 있을 것이다.</p>
<p>이경우 해결 책은 아래와 같이 사용하면 된다.</p>
<ol>
<li>함수 팩토리 사용</li>
<li>익명 클로저를 사용</li>
<li>ES2015의 let 키워드를 사용</li>
</ol>
<hr>
<p>참조</p>
<p><a href="https://developer.mozilla.org/ko/docs/Web/JavaScript/Guide/Closures">https://developer.mozilla.org/ko/docs/Web/JavaScript/Guide/Closures</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[스코프(scope)와 호이스팅(hoisting)]]></title>
            <link>https://velog.io/@pyo-dev/scope%EC%8A%A4%EC%BD%94%ED%94%84%EC%99%80-hoisting%ED%98%B8%EC%9D%B4%EC%8A%A4%ED%8C%85</link>
            <guid>https://velog.io/@pyo-dev/scope%EC%8A%A4%EC%BD%94%ED%94%84%EC%99%80-hoisting%ED%98%B8%EC%9D%B4%EC%8A%A4%ED%8C%85</guid>
            <pubDate>Fri, 19 Jun 2020 00:54:11 GMT</pubDate>
            <description><![CDATA[<p>javascript의 스코프(scope)와 호이스팅(hoisting)에 대하여 알아보도록 하자.</p>
<hr>
<h2 id="🥠-스코프scope">🥠 스코프(scope)</h2>
<p>javascript에서 scope(스코프)란 변수의 유효범위 라고 할 수 있으며 var는 함수 스코프, let과 const는 블록스코프를 갖는다.</p>
<pre><code class="language-javascript">var a = 1;

function output() {
    var a = 2;
    console.log(a);
}

output(); // output : 2
console.log(a); // output : 1</code></pre>
<p>위의 예제에서 output라는 함수 안의 console.log(a);는 a를 출력하기위해 자신의 함수 스코프 안에서 변수 a가 있는지 확인하고 있을 경우 var a = 2;를 참조해 2를 출력하게 된다.
만약 output라는 함수 안의 var a = 2;가 없을경우 상위에 할당 되어 있는 var a = 1;를 참조하여 1을 출력하게 된다. 전역에 있는 console.log(a);는 전역 변수인  var a = 1;를 참조하여 1을 출력한다.</p>
<p>아래 예제를 살펴보자.</p>
<pre><code class="language-javascript">var a = 1;

function output() {
    var a = 2;
    function print(){
        console.log(a);
    }
    return print();
}

output(); // output : 2</code></pre>
<p>output함수 내부 함수인 print함수의 console.log(a);는 자신의 함수 스코프 안에서 a가 있는지 확인하고 없을경우 상위 함수인 output함수의 var a = 2;를 참조하여 2를 출력 하게 된다.
#</p>
<pre><code class="language-javascript">var pyo = &#39;jung min&#39;;
for (var pyo = 0; pyo &lt; 5; pyo++) {
    // loop
}

console.log(pyo); // output : 4</code></pre>
<p>위의 예제에서 4가 출력되는 것을 확인할 수 있다. 
var는 함수 스코프 단위로 유효하기 때문에 위와 같이 변수가 덮어씌워지는 문제가 발생한다 이를 해결하기 위해서는 아래와 같이 블록 스코프를 지원하는 let, const를 사용해야 한다</p>
<pre><code class="language-javascript">var pyo = &#39;jung min&#39;;
for (let pyo = 0; pyo &lt; 5; pyo++) {
    // loop
}

console.log(pyo); // output : jung min</code></pre>
<hr>
<h2 id="🥠-호이스팅hoisting">🥠 호이스팅(hoisting)</h2>
<p>호스팅(hoisting)은 변수의 선언문을 유효범위의 최상단으로 끌어올리기로 해석할 수 있다.</p>
<pre><code class="language-javascript">if (true) {
    var pyo = &#39;min&#39;;
}

output1(); // output : jung min
output2(); // output : 4
console.log(pyo); // output : min

function output1() {
    if (true) {
        var pyo = &quot;jung min&quot;;
    }
    console.log(pyo);
}

function output2() {
    for (var pyo = 0; pyo &lt; 5; pyo++) {
        // loop
    }
    console.log(pyo);
}


// 호이스팅으로 변환된 코드
var pyo;

function output1() {
      var pyo;
    if (true) {
        pyo = &quot;jung min&quot;;
    }
    console.log(pyo);
}

function output2() {
      var pyo;
    for (pyo = 0; pyo &lt; 5; pyo++) {
        // loop
    }
    console.log(pyo);
}

if (true) {
    pyo = &#39;min&#39;;
}

output1(); // output : jung min
output2(); // output : 5
console.log(pyo); // output : min</code></pre>
<p>위의 예제에서 확인할 수 있듯이 변수 및 함수를 유효범위 내부의 최상단으로 위치하게 됩니다.</p>
<h2 id="🥠-함수-선언식과-표현식에-따른-호이스팅hoisting">🥠 함수 선언식과 표현식에 따른 호이스팅(hoisting)</h2>
<h3 id="🥠-함수-선언식">🥠 함수 선언식</h3>
<pre><code class="language-javascript">output1(); // output : jung min
function output1() {
    console.log(&#39;jung min&#39;);
}


// 호이스팅으로 변환된 코드
function output1() {
    console.log(&#39;jung min&#39;);
}
output1(); // output : jung min</code></pre>
<p>선언식의 경우 호이스팅이 발생해 함수를 최상단으로 끌어올려 output1()을 먼저 호출하더라도 정상적으로 동작한다.</p>
<h3 id="🥠-함수-표현식">🥠 함수 표현식</h3>
<pre><code class="language-javascript">output1(); // Uncaught TypeError: output1 is not a function
var output1 = function() {
    console.log(&#39;jung min&#39;);
}


// 호이스팅으로 변환된 코드
var output1;

output1(); // Uncaught TypeError: output1 is not a function

output1 = function() {
    console.log(&#39;jung min&#39;);
}</code></pre>
<p>표현식의 경우 var output1;은 변수이기 때문에 선언과 할당의 분리가 발생한다.
output1 변수가 선언되고 output1();이 실행되고 그 이후에  output1에 함수가 정의되기 때문에 함수가 아니라는 오류메시지가 출력되는 것이다.</p>
<h3 id="🥠-변수와-함수의-호이스팅-우선순위">🥠 변수와 함수의 호이스팅 우선순위</h3>
<pre><code class="language-javascript">var pyo = &#39;jung min&#39;;

function pyo() {
    console.log(&#39;pyo&#39;);
}

function jung() {
    console.log(&#39;jung&#39;);
}

console.log(typeof pyo); // output : string
console.log(typeof jung); // output : function


// 호이스팅으로 변환된 코드
var pyo;

function pyo() {
    console.log(&#39;pyo&#39;);
}

function jung() {
    console.log(&#39;jung&#39;);
}

pyo = &#39;jung min&#39;;

console.log(typeof pyo); // output : string
console.log(typeof jung); // output : function</code></pre>
<p>위와 같이 호스팅 발생 시 함수 및 변수를 최상단으로 끌어올리고 그 이후에 할당되는 것을 확인할 수 있다.</p>
<blockquote>
<p>javascript 작성시에 스코프(scope)와 호이스팅(hoisting)의 관계를 잘 생각하여 작성 하도록 하자.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[var, let, const 차이]]></title>
            <link>https://velog.io/@pyo-dev/var-let-const-%EC%B0%A8%EC%9D%B4</link>
            <guid>https://velog.io/@pyo-dev/var-let-const-%EC%B0%A8%EC%9D%B4</guid>
            <pubDate>Thu, 18 Jun 2020 23:39:09 GMT</pubDate>
            <description><![CDATA[<p>Javascript에 변수 선언 방식인 var, let, const에 각각 차이점을 알아보도록 하자.</p>
<hr>
<h2 id="🥠-var">🥠 var</h2>
<p>var를 사용하면 변수 선언 및 할당이 유동적으로 변경될 수 있는 단점이 있다.</p>
<pre><code class="language-javascript">var pyo = &#39;jung min&#39;;
console.log(pyo); // output : jung min

var pyo = &#39;jung&#39;;
console.log(pyo); // output : jung

pyo = &#39;min&#39;;
console.log(pyo); // output : min</code></pre>
<p>위와 같이 변수 재선언 및 재할당을 하였는데도 에러가 나오지 않고 각각 다른 값이 출력 되는 것을 볼 수 있다.</p>
<p>이는 간단한 테스트에서는 편리할 수 있으나 코드량이 많아 지거나 복잡한 구조의 프로그래밍을 할 때는 디버깅 자체가 어려워진다.</p>
<p>그래서 ES6 이후, 이를 보완하기 위해 추가 된 변수 선언 방식이 <code>let</code> 과 <code>const</code> 이다.</p>
<hr>
<h2 id="🥠-let">🥠 let</h2>
<pre><code class="language-javascript">let pyo = &#39;jung min&#39;;
console.log(pyo); // output : jung min

let pyo = &#39;jung&#39;;
console.log(pyo); // Uncaught SyntaxError: Identifier &#39;pyo&#39; has already been declared

pyo = &#39;min&#39;;
console.log(pyo); // output : min</code></pre>
<p>let을 사용하면 재할당은 가능 하나 재선언을 하게 될 경우에는 <code>ncaught SyntaxError: Identifier &#39;pyo&#39; has already been declared</code>와 같이 이미 선언되어 있다는 에러 메시지가 출력된다.</p>
<hr>
<h2 id="🥠-const">🥠 const</h2>
<pre><code class="language-javascript">const pyo = &#39;jung min&#39;;
console.log(pyo); // output : jung min

const pyo = &#39;jung&#39;;
console.log(pyo); // Uncaught SyntaxError: Identifier &#39;pyo&#39; has already been declared

pyo = &#39;min&#39;;
console.log(pyo); // Uncaught TypeError: Assignment to constant variable.</code></pre>
<p>const의 경우 재선언 및 재 할당이 모두 불가능하다.</p>
<hr>
<h2 id="🥠-차이점">🥠 차이점</h2>
<table>
<thead>
<tr>
<th>Value</th>
<th align="center">재선언</th>
<th align="center">재할당</th>
</tr>
</thead>
<tbody><tr>
<td>var</td>
<td align="center">O</td>
<td align="center">O</td>
</tr>
<tr>
<td>let</td>
<td align="center">X</td>
<td align="center">O</td>
</tr>
<tr>
<td>const</td>
<td align="center">X</td>
<td align="center">X</td>
</tr>
<tr>
<td>&gt; var의 경우 버그 발생과 메모리 누수의 위험 등이 있기 때문에 var말고 let, const를 사용하시는 것이 좋습니다.</td>
<td align="center"></td>
<td align="center"></td>
</tr>
</tbody></table>
]]></description>
        </item>
        <item>
            <title><![CDATA[CSS Flex(Flexible Box)]]></title>
            <link>https://velog.io/@pyo-dev/CSS-FlexFlexible-Box</link>
            <guid>https://velog.io/@pyo-dev/CSS-FlexFlexible-Box</guid>
            <pubDate>Thu, 04 Jun 2020 05:45:57 GMT</pubDate>
            <description><![CDATA[<p>css flex에 대하여 알아보도록 하자.
codepen 예제들을 활용하여 연습해 보세요 실무에서 <code>복붙</code> 하려고 만들어 보았습니다. </p>
<hr>
<h2 id="🥠-display">🥠 display</h2>
<table>
<thead>
<tr>
<th>Value</th>
<th>Use</th>
<th>Default</th>
</tr>
</thead>
<tbody><tr>
<td>flex</td>
<td>block 특성의 flex container</td>
<td></td>
</tr>
<tr>
<td>inline-flex</td>
<td>inline, inline-block 특성의 flex container</td>
<td></td>
</tr>
<tr>
<td>!codepen[pyo-dev/embed/yLeLmLP?height=265&amp;theme-id=dark&amp;default-tab=html,result]</td>
<td></td>
<td></td>
</tr>
</tbody></table>
<hr>
<h2 id="🥠-flex-direction">🥠 flex-direction</h2>
<table>
<thead>
<tr>
<th>Value</th>
<th>Use</th>
<th align="center">Default</th>
</tr>
</thead>
<tbody><tr>
<td>row</td>
<td>flex-item을 수평으로 정렬</td>
<td align="center">row</td>
</tr>
<tr>
<td>row-reverse</td>
<td>flex-item을 수평의 반대축으로 정렬</td>
<td align="center"></td>
</tr>
<tr>
<td>column</td>
<td>flex-item을 수직으로 정렬</td>
<td align="center"></td>
</tr>
<tr>
<td>column-reverse</td>
<td>flex-item을 수직의 반대축으로 정렬</td>
<td align="center"></td>
</tr>
<tr>
<td>!codepen[pyo-dev/embed/MWKexNx?height=265&amp;theme-id=dark&amp;default-tab=html,result]</td>
<td></td>
<td align="center"></td>
</tr>
</tbody></table>
<hr>
<h2 id="🥠-flex-wrap">🥠 flex-wrap</h2>
<table>
<thead>
<tr>
<th>Value</th>
<th>Use</th>
<th align="center">Default</th>
</tr>
</thead>
<tbody><tr>
<td>nowrap</td>
<td>flex-item을 한줄로 정렬</td>
<td align="center">nowrap</td>
</tr>
<tr>
<td>wrap</td>
<td>flex-item을 여러줄로 정렬</td>
<td align="center"></td>
</tr>
<tr>
<td>wrap-reverse</td>
<td>flex-item을 여러줄의 역방향으로 정렬</td>
<td align="center"></td>
</tr>
<tr>
<td>!codepen[pyo-dev/embed/MWKeRWx?height=265&amp;theme-id=dark&amp;default-tab=html,result]</td>
<td></td>
<td align="center"></td>
</tr>
</tbody></table>
<hr>
<h2 id="🥠-justify-content">🥠 justify-content</h2>
<table>
<thead>
<tr>
<th>Value</th>
<th>Use</th>
<th align="center">Default</th>
</tr>
</thead>
<tbody><tr>
<td>flex-start</td>
<td>flex-item을 수평 시작점으로 정렬</td>
<td align="center">flex-start</td>
</tr>
<tr>
<td>flex-end</td>
<td>flex-item을 수평 끝점으로 정렬</td>
<td align="center"></td>
</tr>
<tr>
<td>center</td>
<td>flex-item을 수평 가운데 정렬</td>
<td align="center"></td>
</tr>
<tr>
<td>space-between</td>
<td>flex-item의 first는 수평 시작점 last는 수평 끝점 으로 하고 간격을 동일하게 정렬</td>
<td align="center"></td>
</tr>
<tr>
<td>space-around</td>
<td>flex-item의 수평 간격을 고르게 하여 정렬</td>
<td align="center"></td>
</tr>
<tr>
<td>!codepen[pyo-dev/embed/BajzENr?height=265&amp;theme-id=dark&amp;default-tab=html,result]</td>
<td></td>
<td align="center"></td>
</tr>
</tbody></table>
<hr>
<h2 id="🥠-align-content">🥠 align-content</h2>
<blockquote>
<p> flex-wrap 속석을 통해 flex-item이 두줄 이상일 경우만 사용 가능
flex-item이 한줄일 경우 align-items 사용</p>
</blockquote>
<table>
<thead>
<tr>
<th>Value</th>
<th>Use</th>
<th align="center">Default</th>
</tr>
</thead>
<tbody><tr>
<td>stretch</td>
<td>flex-wrap의 수직을 채우기 위해 flex-item을 늘림</td>
<td align="center">stretch</td>
</tr>
<tr>
<td>flex-start</td>
<td>flex-item을 수직 시작점으로 정렬</td>
<td align="center"></td>
</tr>
<tr>
<td>flex-end</td>
<td>flex-item을 수직 끝점으로 정렬</td>
<td align="center"></td>
</tr>
<tr>
<td>center</td>
<td>flex-item을 수직 가운데 정렬</td>
<td align="center"></td>
</tr>
<tr>
<td>space-between</td>
<td>flex-item의 first는 수직 시작점 last는 수직 끝점 으로 하고 간격을 동일하게 정렬</td>
<td align="center"></td>
</tr>
<tr>
<td>space-around</td>
<td>flex-item의 수직 간격을 고르게 하여 정렬</td>
<td align="center"></td>
</tr>
<tr>
<td>!codepen[pyo-dev/embed/YzwWMwV?height=265&amp;theme-id=dark&amp;default-tab=html,result]</td>
<td></td>
<td align="center"></td>
</tr>
</tbody></table>
<hr>
<h2 id="🥠-align-items">🥠 align-items</h2>
<blockquote>
<p>주의할 점은 flex-items이 flex-wrap을 속성에 의해 2줄 이상일 경우에는 align-content 속성이 우선합니다.
align-items를 사용하려면 align-content 속성을 기본값(stretch)으로 설정해야 합니다.</p>
</blockquote>
<table>
<thead>
<tr>
<th>Value</th>
<th>Use</th>
<th align="center">Default</th>
</tr>
</thead>
<tbody><tr>
<td>stretch</td>
<td>flex-wrap의 수직을 채우기 위해 flex-item을 늘림</td>
<td align="center">stretch</td>
</tr>
<tr>
<td>flex-start</td>
<td>flex-item을 각 줄의 수직 시작점으로 정렬</td>
<td align="center"></td>
</tr>
<tr>
<td>flex-end</td>
<td>flex-item을 각 줄의 수직 끝점으로 정렬</td>
<td align="center"></td>
</tr>
<tr>
<td>center</td>
<td>flex-item을 각 줄의 수직 가운데 정렬</td>
<td align="center"></td>
</tr>
<tr>
<td>baseline</td>
<td>flex-item의 각 줄의 문자 기준선에 정렬</td>
<td align="center"></td>
</tr>
<tr>
<td>!codepen[pyo-dev/embed/LYGZvrL?height=265&amp;theme-id=dark&amp;default-tab=html,result]</td>
<td></td>
<td align="center"></td>
</tr>
</tbody></table>
<hr>
<h2 id="🥠-align-self">🥠 align-self</h2>
<blockquote>
<p>align-items 속성보다 우선합니다.</p>
</blockquote>
<table>
<thead>
<tr>
<th>Value</th>
<th>Use</th>
<th align="center">Default</th>
</tr>
</thead>
<tbody><tr>
<td>auto</td>
<td>flex-wrap의 align-items 속성을 상속</td>
<td align="center">auto</td>
</tr>
<tr>
<td>stretch</td>
<td>flex-wrap의 수직을 채우기 위해 flex-item을 늘림</td>
<td align="center"></td>
</tr>
<tr>
<td>flex-start</td>
<td>flex-item을 각 줄의 수직 시작점으로 정렬</td>
<td align="center"></td>
</tr>
<tr>
<td>flex-end</td>
<td>flex-item을 각 줄의 수직 끝점으로 정렬</td>
<td align="center"></td>
</tr>
<tr>
<td>center</td>
<td>flex-item을 각 줄의 수직 가운데 정렬</td>
<td align="center"></td>
</tr>
<tr>
<td>baseline</td>
<td>flex-item의 각 줄의 문자 기준선에 정렬</td>
<td align="center"></td>
</tr>
<tr>
<td>!codepen[pyo-dev/embed/qBbqbEB?height=265&amp;theme-id=dark&amp;default-tab=html,result]</td>
<td></td>
<td align="center"></td>
</tr>
</tbody></table>
<hr>
<h2 id="🥠-order">🥠 order</h2>
<table>
<thead>
<tr>
<th>Value</th>
<th>Use</th>
<th align="center">Default</th>
</tr>
</thead>
<tbody><tr>
<td>number</td>
<td>flex-wrap의 순서 정렬</td>
<td align="center">0</td>
</tr>
<tr>
<td>!codepen[pyo-dev/embed/rNxLbQe?height=265&amp;theme-id=dark&amp;default-tab=html,result]</td>
<td></td>
<td align="center"></td>
</tr>
</tbody></table>
<hr>
<h2 id="🥠-flex">🥠 flex</h2>
<blockquote>
<p>flex: flex-grow , flex-shrink, flex-basis;
flex-grow를 제외한 개별 속성은 생략 가능 </p>
</blockquote>
<table>
<thead>
<tr>
<th>Value</th>
<th>Use</th>
<th align="center">Default</th>
</tr>
</thead>
<tbody><tr>
<td>flex-grow</td>
<td>flex-wrap의 증가 너비 비율을 설정</td>
<td align="center">0</td>
</tr>
<tr>
<td>flex-shrink</td>
<td>flex-wrap의 감소 너비 비율을 설정</td>
<td align="center">1</td>
</tr>
<tr>
<td>flex-basis</td>
<td>flex-wrap의 (공간 배분 전) 기본 너비 설정</td>
<td align="center">auto</td>
</tr>
<tr>
<td>!codepen[pyo-dev/embed/yLeVeZd?height=265&amp;theme-id=dark&amp;default-tab=css,result]</td>
<td></td>
<td align="center"></td>
</tr>
</tbody></table>
<hr>
<h2 id="🥠-ex-layout-1">🥠 ex) layout-1</h2>
<p>!codepen[pyo-dev/embed/JjGbXNy?height=265&amp;theme-id=dark&amp;default-tab=css,result]</p>
]]></description>
        </item>
    </channel>
</rss>