<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>cool_kim.log</title>
        <link>https://velog.io/</link>
        <description>FE developer</description>
        <lastBuildDate>Sat, 31 Jul 2021 13:49:49 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>cool_kim.log</title>
            <url>https://images.velog.io/images/cool_kim/profile/60fec8c4-5974-4e7d-9e1d-c136128e3e08/KakaoTalk_20210707_130430786.jpg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. cool_kim.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/cool_kim" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[자바스크립트/Javascript] 렉시컬 스코프]]></title>
            <link>https://velog.io/@cool_kim/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8Javascript-%EB%A0%89%EC%8B%9C%EC%BB%AC-%EC%8A%A4%EC%BD%94%ED%94%84</link>
            <guid>https://velog.io/@cool_kim/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8Javascript-%EB%A0%89%EC%8B%9C%EC%BB%AC-%EC%8A%A4%EC%BD%94%ED%94%84</guid>
            <pubDate>Sat, 31 Jul 2021 13:49:49 GMT</pubDate>
            <description><![CDATA[<p>📌 스코프가 작동하는 두가지 방식</p>
<ol>
<li>렉시컬 스코프  </li>
<li>동적 스코프</li>
</ol>
<br>

<h1 id="💡-렉스-타임">💡 렉스 타임</h1>
<p>렉시컬 스코프 : 개발자가 코드를 짤 때 변수와 스코프 블록을 어디서 작성하는가에 기초하여 렉서가 처리할 때 확정</p>
<pre><code class="language-jsx">//1
function foo() {
    //2
    var b = a * 2;
    function bar(c); {
        //3
        console.log( a, b, c);
    }
    bar( b * 3 )&#39;
}
foo( 2 ); // 2, 4, 12</code></pre>
<p>⇒ 3개의 중첩 스코프</p>
<ul>
<li>1 : 글로벌 스코프, foo 확인자</li>
<li>2 : foo 스코프, a, bar, b 확인자</li>
<li>3 : bar 스코프, c 확인자</li>
</ul>
<p>📍 어떤 함수의 버블도 동시에 다른 두 스코프 버블 안에 존재할 수 없음
<br>
<br></p>
<h2 id="✅-검색">✅ 검색</h2>
<p>: 엔진이 <strong>스코프 버블의 구조</strong>와 <strong>상대적 위치</strong>를 통해 어디를 검색해야하는지에 대한 정보</p>
<p>📍 스코프 : 목표와 일치하는 대상을 찾는 즉시 검색 중단
📍 섀도잉 : 여러 중첩 스코프 층에 걸쳐 같은 확인자 이름 정의
📍 렉시컬 스코프는 함수가 선언된 위치에 따라 정의
<br></p>
<h2 id="✅-렉시컬-속이기">✅ 렉시컬 속이기</h2>
<h3 id="eval">eval()</h3>
<p>: 인자로 문자열을 받아 런타임에 문자열 내용을 코드의 일부분처럼 처리
→ 호출된 위치에 있는 렉시컬 스코프 수정</p>
<h3 id="with">with</h3>
<p>: 한 객체의 여러 속성을 참조할 때 객체 참조를 매번 반복하지 않기 위해 사용하는 속기법</p>
<pre><code class="language-jsx">function foo(obj) {
    with (obj) {
        a=2;
    }
}

var o1 = {
    a: 2
};

var o2 = {
    b: 3
};

foo( o1 );
console.log( o1.a ); //2

foo( o2 );
console.log( o2.a ); // undefined
console.log( a ); // 2--0ops, leaked global!</code></pre>
<p>⇒ with 문은 o1이라는 스코프를 선언하고 그 스코프는 o1.a 속성에 해당하는 확인자를 가짐</p>
<p>⚠️ eval과 with모두 권장하지 않는 문이다
하지만 코드에 이 두개가 있다면 최적화 없이는 코드가 느리게 동작할거 라는 것 명심!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[React] 리덕스]]></title>
            <link>https://velog.io/@cool_kim/React-%EB%A6%AC%EB%8D%95%EC%8A%A4</link>
            <guid>https://velog.io/@cool_kim/React-%EB%A6%AC%EB%8D%95%EC%8A%A4</guid>
            <pubDate>Wed, 28 Jul 2021 10:23:45 GMT</pubDate>
            <description><![CDATA[<h1 id="📌리덕스">📌리덕스</h1>
<p>: 컴포넌트 코드로부터 상태관리 코드를 분리 가능
: 미들웨어 활용한 다양한 기능 추가 가능
    - 강력한 미들웨어 라이브러리 (redux-saga)
    - 로컬 스토리지에 데이터 저장하기 및 불러오기
: SSR시 데이터 전달 간편
: 리액트 콘텍스트보다 효율적인 렌더링 가능
<br></p>
<h2 id="context-api">context API</h2>
<pre><code class="language-cpp">import React, { userContext, createContext, useReducer } from &#39;react&#39;;

// 컨텍스트
const AppContext = createContext({});
const DispatchContext = createContext(() =&gt; {});

// 루트 컴포넌트
export default function App() {
  const [state, dispatch] = useReducer(reducer, INITIAL_STATE);
  return(
    &lt;&gt;
      &lt;AppContext.Provider value={state}&gt;
        &lt;DispatchContext.Provider value={dispatch}&gt;
          &lt;User /&gt;
          &lt;Product /&gt;
        &lt;/DispatchContext.Provider&gt;
      &lt;/AppContext.Provider&gt;
    &lt;/&gt;
  );
}

// 리듀서
const INITIAL_STATE = {
  user: {name: &#39;mike&#39;},
  produce: {name: &#39;iphone&#39;},
}
function reducer(state, action) {
  switch (action.type) {
    case &#39;setUserName&#39;:
      return {
        ...state, 
        user: {...state.user, name: action.name}};
            default:
                return state;
  }
}</code></pre>
<ul>
<li>하나의 context로 관리하게 되면 상태값이 하나만 바뀌어도 모두 다 렌더링 됨</li>
</ul>
<br>
<br>

<h2 id="리덕스">리덕스</h2>
<ol>
<li>뷰에서 상태값을 변경하고 싶을 때 액션 발생</li>
<li>미들웨어가 액션 처리</li>
<li>리듀서에서 해당 액션에 의해 상태값이 변경되어 출력</li>
<li>스토어가 새로운 상태값을 저장</li>
<li>옵저버에게 데이터의 변경 사실을 알려 뷰 바꾸기<br>

</li>
</ol>
<p>📍 뷰 → 액션 → 미들웨어 → 리듀서 → 스토어 → 뷰
<br></p>
<h3 id="✅-액션">✅ 액션</h3>
<ul>
<li>dispatch : 리액트에서 액션이 발생했다는 것을 리덕스에게 알려주는 함수</li>
</ul>
<pre><code class="language-jsx">//일반적이지 않은 예
store.dispatch({ type: &#39;todo/ADD&#39;, title: &#39;영화 보기&#39;, priority: &#39;high&#39; });
store.dispatch({ type: &#39;todo/REMOVE&#39;, id: 123 });
store.dispatch({ type: &#39;todo/REMOVE_ALL&#39; });

//일반적인 예
function addTodo({ title, priority }) {
    return { type: &#39;todo/ADD&#39;, title, priority };
}
store.dispatch(addTodo({ title: &#39;영화 보기&#39;, priority: &#39;high&#39; }));</code></pre>
<p>✔️ type 속성값 : 액션 구분해줌 → 유니크 해야함
    - 상수 변수로 만드는 것이 좋음
✔️ action creator : 각 액션 구조를 일관성 있게 만들기 위함
<br>
<br></p>
<h3 id="✅-미들웨어">✅ 미들웨어</h3>
<pre><code class="language-jsx">const myMiddleware = store =&gt; next =&gt; action =&gt; next(action);</code></pre>
<p>⇒ 미들웨어의 모양
<br></p>
<p>📍 상태값을 가져오는 코드</p>
<pre><code class="language-jsx">const printLog = store =&gt; next =&gt; action =&gt; {
  console.log(`prev state = ${JSON.stringify(store.getState())}`);
  const result = next(action);
  console.log(`next state = ${JSON.stringify(store.getState())}`);
  return result;
}</code></pre>
<br>

<p>📍딜레이 후에 리듀서가 실행되게 하는 코드</p>
<pre><code class="language-jsx">const delayAction = store =&gt; next =&gt; action =&gt; {
    const delay = action.meta?.delay;
    if(!delay) {
        return next(action);
    }
    const timoutId = setTimeout(() =&gt; next(action), delay);
    return function cancel() {
        clearTimout(timeoutId);
    };
};

const myReducer - [state = {name: &#39;mike&#39; }, action} =&gt; {
    console.log(&#39;myReducer&#39;);
    if(action.type === &#39;someAction&#39;) {
        return { name: &#39;mike2&#39; };
    }
    return state;
};

const store = createStore(myReducer, applyMiddleware(delayAction)};
const cancle = store.dispatch({type: &#39;someAction&#39;, meta: {delay: 3000 }});
cancel();

export default function App() {
    return &lt;div&gt;실전 리액트&lt;/div&gt;;
}</code></pre>
<br>

<p>📍 로컬 스토리지에 저장해주는 코드</p>
<pre><code class="language-jsx">const saveToLocalStorage = store =&gt; next =&gt; action =&gt; {
  if (action.meta?.localStorageKey) {
    localStorage.setItem(action.meta?.loaclStorageKey, JSON.stringify(action));
  }
  return next(action);
}

const myReducer = (state = { name: &#39;mike&#39; }, action) =&gt; {
  console.log(&#39;myReducer&#39;);
  switch(action.type) {
    case &#39;someAction&#39;:
      return {...state, name:&#39;mike2&#39;}
    default:
      return state;
  }
  return state;
}

const store = createStore(myReducer, applyMiddleware(saveToLocalStorage));

store.dispatch({ 
  type: &#39;someAction&#39;,
  title: &#39;asdf&#39;,
  meta: { localStorageKey: &#39;myKey&#39; } 
});</code></pre>
<br>
<br>

<h3 id="✅-리듀서">✅ 리듀서</h3>
<p>: 액션이 발생했을 때 새로운 상태값을 만드는 함수
상태값 변경 → 액션 객체와 함께 dispatch 메소드 호출</p>
<pre><code class="language-jsx">function reducer(state = INITIAL_STATE, action) {
//...
  switch (action.type) {
    case REMOVE_ALL:
      return {
        ...state,
        todos: [],
      };
    case REMOVE:
      return {
        ...state,
        todos: state.todos.filter(todo =&gt; todo.id !== action.id),
      };
    default:
      return state;
  }
}

const INITIAL_STATE = { todos: [] }</code></pre>
<br>

<p>⚠️ 반환되는 state 값은 불변객체로 관리 해야함
⇒ 이전 상태랑 다음 상태를 <code>===</code> 로 단순 비교가 가능함
<br></p>
<p>📌 immer패키지
: 전개 연산자 대신 불변객체로 관리해주는 라이브러리</p>
<pre><code class="language-jsx">import produce from &#39;immer&#39;;

const person = { name: &#39;mike&#39;, age: 22 };
const newPerson = produce(person, draft =&gt; {
  draft.age = 32
})

//다른 파일내의 코드
function reducer(state = INITIAL_STATE, action) {
  return produce(state, draft =&gt; {
    switch (action.type) {
      case SET_SELECTED_PEOPLE:
        draft.selectedPeople = draft.peopleList.find(
          item =&gt; item.id === action.id,
        );
        break;
      case EDIT_PEOPLE_NAME:
        const people = draft.peopleList.find(
          item =&gt; item.id === action.id,
        );
        people.name = action.name;
        break;
    }
  })
}</code></pre>
<br>

<p>⚠️ 리듀서 코드 작성시 주의해야할 점</p>
<ol>
<li>객체를 가르킬 시 객체의 레퍼런스가 아닌 고유한 아이디 값 이용</li>
<li>리듀서는 순수 함수로 작성해야함<em>(입력이 같을 때 같은 출력을 해야함, 부수효과 없어야 함)</em></li>
</ol>
<br>
<br>

<h4 id="🔸-리듀서-생성함수">🔸 리듀서 생성함수</h4>
<p>📍createReducer사용</p>
<pre><code class="language-jsx">import produce from &#39;immer&#39;;

function createReducer(initialState, handlerMap) {
  return function(state = initialState, action) {
    return produce(state, draft =&gt; {
      const handler = handlerMap[action.type];
      if (handler) {
        handler(draft, action);
      }
    })
  }
}

const reducer = createReducer(INITIAL_STATE, {
  [ADD]: (state, action) =&gt; state.todos.push(action.todo),
  [REMOVE_ALL]: state =&gt; (state.todos = []),
  [REMOVE]: (state, action) =&gt; state.todos.filter(todo =&gt; todo.id !== action.id),
});</code></pre>
<br>
<br>

<h4 id="🔸-스토어-생성">🔸 스토어 생성</h4>
<p>📍createStore사용</p>
<pre><code class="language-jsx">const store = createStore(reducer);

let prevState;
store.subscribe(() =&gt; {
  const state = store.getState();
  if (state === prevState) {
    console.log(&#39;상태값 같음&#39;);
  } else {
    console.log(&#39;상태값 변경됨&#39;);
  }
  prevState = state;
});</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[자바스크립트/Javascript] 문법(2), 스코프 이해하기]]></title>
            <link>https://velog.io/@cool_kim/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8Javascript-%EB%AC%B8%EB%B2%952-%EC%8A%A4%EC%BD%94%ED%94%84-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@cool_kim/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8Javascript-%EB%AC%B8%EB%B2%952-%EC%8A%A4%EC%BD%94%ED%94%84-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0</guid>
            <pubDate>Fri, 23 Jul 2021 15:45:35 GMT</pubDate>
            <description><![CDATA[<h1 id="5-2-문법">5-2 문법</h1>
<h2 id="5-함수-인자">5. 함수 인자</h2>
<h3 id="디폴트-인자">디폴트 인자</h3>
<p>: 함수에 인자를 넘기지 않거나 undefined를 전달했을 때 적용</p>
<ul>
<li>undefined받았을 때<ul>
<li>arguments배열에도 값이 undefined인 원소가 추가<br></li>
</ul>
</li>
<li>아무것도 넘기지 않았을 때<ul>
<li>arguments 배열에 원소가 하나도 없음</li>
</ul>
</li>
</ul>
<p>📍 요즘은 arguments 대신에 레스트인자( ...) 을 많이 쓰는 추세
<br><br></p>
<h2 id="6-try--finally">6. try ... finally</h2>
<p>📍 try이후에는 catch, finally 중 하나만 필수! (하지만 둘다 같이 써도 상관 없음)</p>
<p>🔹 finally : 어떤일이 있어도 반드시 실행되는 코드</p>
<ul>
<li>finally 절에서 예외가 던져지면 이전의 실행 결과는 모두 무시 ( continue, break와 같은 비선형 제어문도 비슷하게 작동)</li>
</ul>
<pre><code class="language-jsx">function foo() {
    try {
        return 42;
    }
    finally {
        console.log( &quot;Hello&quot; );
    }
    console.log( &quot;실행될 리 없지!&quot; );
}

console.log( foo() );
//Hello
//42</code></pre>
<pre><code class="language-jsx">for (var i = 0; i&lt;10; i++) {
    try {
        continue;
    }
    finally {
        console.log( i );
    }
}
// 0 1 2 3 4 5 6 7 8 9</code></pre>
<p>⇒  continue문 때문에 console.log(i)문은 루프 순회 끝 부분에서 실행,
⇒  그러나 <code>i++</code> 로 인덱스가 수정되기 직전까지 꾸준히 실행되므로 0—9가 콘솔창에 표시
<br></p>
<p>📍 finally절의 return은 그 이전에 실행된 try나 catch 절의 return을 덮어쓰는 특출한 능력이 있음.
<em>(단, 반드시 명시적으로 return문을 써야함)</em>
<br><br></p>
<h2 id="7-switch">7. switch</h2>
<p>switch 표현식과 case 표현식 간의 매치 과정은 <code>===</code> 알고리즘과 똑같음
⇒ 강제변환이 일어나는 동등 비교 <code>==</code>를 이용할 때 논리 연산자 주의</p>
<ul>
<li>분명히 표현식의 결과가 true/false로 떨어지게 작성해야함</li>
</ul>
<pre><code class="language-jsx">var a = 10;

switch (a) {
    case 1:
    case 2:
        //절대 들어오지 않음
    default:
        console.log(&quot;default&quot;);
    case 3:
        console.log(&quot;3&quot;)
    case 4:
        console.log(&quot;4&quot;);
}
//default
//3</code></pre>
<p><br><br><br></p>
<h1 id="6장-스코프">6장 스코프</h1>
<h2 id="1-컴파일러-이론">1. 컴파일러 이론</h2>
<p>자바스크립트 : 컴파일러 언어
<br></p>
<h3 id="토크나이징렉싱">토크나이징/렉싱</h3>
<p>: 문자열을 나누어 토큰이라는 의미 있는 조각으로 만드는 과정
<code>var a = 2;</code> 를 토큰으로 나누면
⇒ var, a, =, 2, ; 로 나뉘게 됨
<em>(빈칸은 의미가 있느냐 없느냐에 따라 포함될 때가 있고 안될 때가 있음)</em>
<br></p>
<h3 id="파싱">파싱</h3>
<p>: 토큰 배열을 프로그램의 문법 구조를 반영하여 중첩 원소를 갖는 트리 형태로 바꾸는 과정
<br></p>
<p>📍 AST : 파싱의 결과로 만들어진 트리</p>
<ul>
<li>최상위 노드 : 변수선언 (<code>var a=2</code>)</li>
<li>자식 노드 : 확인자(<code>a</code>), 대입 수식</li>
<li>대입 수식노드의 자식노드 : 숫자 리터럴 (<code>2</code>)<br>

</li>
</ul>
<h3 id="코드-생성">코드 생성</h3>
<p>: AST를 컴포터에서 실행 코드로 바꾸는 과정
<br><br></p>
<h2 id="2-스코프-이해하기">2. 스코프 이해하기</h2>
<h3 id="1-출연진">1) 출연진</h3>
<ul>
<li>엔진 : 컴파일레이션의 시작부터 끝까지 전 과정과 자바스크립트 프로그램 실행을 책임</li>
<li>컴파일러 : 엔진의 친구로, 파싱과 코드 생성의 모든 잡일을 함</li>
<li>엔진의 또 다른 친구로, 선언된 모든 확인자 검색 목록을 작성하고 유지한다. 또한 엄격한 규칙을 강제하여 현재 실행 콛에서 확인자의 적용 방식을 정함<br>

</li>
</ul>
<h3 id="2-앞과-뒤">2) 앞과 뒤</h3>
<p><code>var a=2</code>에 엔진이 어떻게 접근할까?</p>
<ol>
<li>컴파일러가 렉싱을 통해 구문을 토큰으로 쪼갬</li>
<li>토큰을 파싱해 트리 구조를 만듬</li>
<li>컴파일러가 <code>var a</code>를 만나면 스코프에게 변수 a가 특정한 스코프 컬렉션 안에 있는지 물음</li>
<li>변수 a가 이미 있다면 컴파일러는 선언 무시 그렇지 않으면 새로운 변수 a를 스코프 컬렉션 내에 선언하라고 요청</li>
<li><code>a=2</code> 대입문을 처리하기 위해 나중에 엔진이 실행할 수 있는 코드 생성</li>
<li>엔진이 실행하는 코드는 먼저 스코프에게 a라 부르는 변수가 현재 스코프 컬렉션 내에서 접근할 수 있는지 확인</li>
<li>가능하면 엔진은 변수 a를 사용, 아니면 엔진은 다른 곳을 살핌<br>

</li>
</ol>
<h3 id="3-컴파일러체">3) 컴파일러체</h3>
<ul>
<li>LHS검색 : 변수가 대입 연산자의 왼쪽에 있을 때 수행<ul>
<li>값을 넣어야 하므로 변수 컨테이너 자체를 찾음</li>
<li><code>a = 2</code></li>
</ul>
</li>
<li>RHS검색 : 변수가 대입 연산자의 오른쪽에 있을 때 수행<ul>
<li>특정 변수의 값을 찾는 것과 다를 바 없음</li>
<li><code>console.log(a)</code></li>
</ul>
</li>
</ul>
<br>

<p>📍 LHS검색과 RHS검색 모두 수행</p>
<pre><code class="language-cpp">function foo(a) {
    console.log( a ); //2
{
foo( a ); </code></pre>
<ol>
<li>마지막 줄에서 foo()함수를 호출하는 데 RHS검색</li>
<li>코드 속에 내재된 <code>a=2</code> 가 LHS검색<br>
<br>


</li>
</ol>
<h2 id="3-중첩-스코프">3. 중첩 스코프</h2>
<p>중첩 스코프 탐사 시 사용하는 규칙</p>
<ul>
<li>엔진은 현재 스코프에서 변수를 찾기 시작하고, 찾지 못하면 한 단계씩 올라감</li>
<li>최상위 글로벌 스코프에 도달하면 변수를 찾았든, 못 찾았든 검색을 멈춤<br>
<br>

</li>
</ul>
<h2 id="4-오류">4. 오류</h2>
<ul>
<li>RHS검색이 중첩 스코프 안 어디에서도 변수를 찾을 수 없으면 <code>ReferenceError</code> 발생</li>
<li>RHS검색이 변수를 찾았지만 그 값을 가지고 불가능한 일을 할 경우 <code>TypeError</code> 발생</li>
<li>LHS검색을 수행해 변수를 찾지 못하고 최상위 층에 도착할 때 → 새로운 변수 생성</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[React] useEffect활용, 렌더링 최적화]]></title>
            <link>https://velog.io/@cool_kim/React-useEffect%ED%99%9C%EC%9A%A9-%EB%A0%8C%EB%8D%94%EB%A7%81-%EC%B5%9C%EC%A0%81%ED%99%94</link>
            <guid>https://velog.io/@cool_kim/React-useEffect%ED%99%9C%EC%9A%A9-%EB%A0%8C%EB%8D%94%EB%A7%81-%EC%B5%9C%EC%A0%81%ED%99%94</guid>
            <pubDate>Sun, 18 Jul 2021 16:37:38 GMT</pubDate>
            <description><![CDATA[<h1 id="📌-useeffect-활용하기">📌 useEffect 활용하기</h1>
<pre><code class="language-jsx">function Profile({userId}) {
    const [user, setUser] = useState();
    useEffect(() =&gt; {
        fetchUser(userId).then(data =&gt; setUser(data));
    }, [userId]);
}</code></pre>
<p>⇒ 마운트 된 후 한번만 호출할 수 있도록 useEffect 의존성 배열에 <strong>빈배열</strong> 입력할 수 있지만 좋은 방법 ❌
⇒  userId가 바뀔때 렌더링 할 수 있도록 의존성 배열에  <strong>userId</strong>를 입력해 줘야함
<br></p>
<p>💡 마운트 되었을 때만 실행되게 하려면 별도의 훅을 사용하는 것이 더 좋음</p>
<pre><code class="language-jsx">function Profile({ userId }) {
  const [user, setUser] = useState();
  useOnMounted(() =&gt; fetchUser(userId).then(data =&gt; setUser(data)))
}</code></pre>
<br>

<p>💡 useEffect에서 async await함수를 사용하고 싶을 때
<em>(async await함수는 Promise객체를 반환하기 때문에 useEffect에서 사용할 수 없음. useEffect는 함수만 반환 가능)</em></p>
<pre><code class="language-jsx">function Profile({ userId }) {
    const [user, setUser] = useState();
    useEffect(() =&gt; {
        async function fetchAndSetUser(needDetail) {
            const data = await fetchUser(userId, needDetail);
            setUser(data);
    }
    fetchAndSetUser(false);
}, [userId]);</code></pre>
<p>⇒ 위 코드에서 userId가 변경될 때만 useEffect함수가 렌더 되게 하려면 useCallback훅 사용
<br></p>
<p>✔️ 의존성 배열은 되도록 사용하지 않는것이 좋음(∴ 관리하는데에 많은 시간과 노력 필요)
<br>
<br></p>
<p>💡 여러 상태값을 참조하면서 값 변경할 때 → <strong>useReducer훅 사용</strong></p>
<pre><code class="language-jsx">function Timer({ initialTotalSeconds }) {
  const [state, dispatch] = useReducer(reducer, {
    hour: initialTotalSeconds / 3600
    minute: (initialTotalSeconds % 3600) / 60
    second: initialTotalSeconds % 60
  });
  const { hour, minute, second } = state;
  useEffect(() =&gt; {
    const id = setInterval(dispatch, 1000);
    return () =&gt; clearInterval(id);
  });
  //...
}

function reducer(state) {
  const { hour, minute, second } = state;
  if(second) {
    return { ..state, second: second - 1 };
  } else if(second) {
    return { ..state, minute: minute - 1, second: 59 };
  } else if(second) {
    return { ..state, hour: hour - 1, minute: 59, second: 59 };
  } else {
    return state;
  }
}</code></pre>
<p>→ dispatch함수는 변경되지 않는 값이므로 의존성 배열에 입력하지 않아도 됨
<br></p>
<p>💡 의존성 배열을 관리하는데에 마땅한 해결책이 생각나지 않는 경우 → useRef 훅 사용</p>
<pre><code class="language-jsx">function MyComponent({ onClick }) {
  const onClickRef = useRef();

  // concurrent mode를 위한 작성법
  useEffect(() =&gt; {
    onClickRef.current = onClick;
  });

  useEffect(() =&gt; {
    window.addEventListener(&#39;click&#39;, () =&gt; {
      onClickRef.current();
      // ...
    })
    // ...
  });
  // ...
}</code></pre>
<p>→ ref객체는 컴포넌트 안에서 직접 수정하면 안됨! (concurrent mode 때문)</p>
<br>
<br>
<br>

<h1 id="📌-렌더링-속도-올리는-최적화-방법">📌 렌더링 속도 올리는 최적화 방법</h1>
<p>리액트의 대부분의 연산 : 컴포넌트 함수의 실행 &amp; 가상돔에서 발생
<br></p>
<p>📍 React.memo사용시
memo로 감싼 컴포넌트에 두번째 인자로 비교함수를 넣어주면 그 값을 토대로 돔에 반영함</p>
<pre><code class="language-jsx">function MyComponent(props) {
  // ...
}
function isEqual(prefProps, nextProps) {
  // true 또는 false를 반환
}
React.memo(MyComponent, isEqual)</code></pre>
<p>(두번째 인자로 비교 연산을 하지 않아도 되지만 넣어주면 렌더링 속도가 빨라짐)
<br>
<br></p>
<p>❓ 이전 값과 현재값이 다르다는 것을 어떻게 비교
➡️ <code>===</code> 연산자로 비교! (객체를 <strong>불변 객체</strong>로 관리)
<code>prevProps.todos === nextProps.todos</code>
<br>
<br></p>
<h3 id="속성값-관리">속성값 관리</h3>
<p>💡 useCallback훅 사용</p>
<pre><code class="language-jsx">//...
const onChangeFruit = useCallback(fruit =&gt; {
    setSelectedFruit(fruit);
    sendLog({ type: &#39;fruit change&#39;, value: fruit });
}, []);
//...
    &lt;SelectFruit selected={selectedFruit} onchange={onchangeFruit} /&gt;</code></pre>
<br>
<br>


<h3 id="속성값이-변경되어야-하는데-변경하지-않는-경우">속성값이 변경되어야 하는데 변경하지 않는 경우</h3>
<p>💡상태값의 레퍼런스가 변경되지 않기 때문
⇒ 상태값을 불변객체로 관리 해야함</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[자바스크립트/Javascript] 문법(1)]]></title>
            <link>https://velog.io/@cool_kim/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8Javascript-%EB%AC%B8%EB%B2%951</link>
            <guid>https://velog.io/@cool_kim/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8Javascript-%EB%AC%B8%EB%B2%951</guid>
            <pubDate>Sat, 17 Jul 2021 16:01:58 GMT</pubDate>
            <description><![CDATA[<h1 id="51-문과-표현식">5.1 문과 표현식</h1>
<p>🔹 문(Statement)
🔹 표현식(Expression)</p>
<ul>
<li>단일한, 특정한 결괏값으로 계산<br>

</li>
</ul>
<p>✔️ 모든 문은 완료 값(Completion Value)을 가진다
✔️ 표현식의 부수효과</p>
<ul>
<li>증가, 감소 연산자를 후위 연산자로 사용시</li>
<li>delete함수</li>
<li>할당 표현식 ( = )<br>

</li>
</ul>
<h2 id="콘텍스트-규칙">콘텍스트 규칙</h2>
<h3 id="1-중괄호">1) 중괄호</h3>
<ol>
<li><p>객체 리터럴
 <code>var a = { foo: bar() };</code></p>
</li>
<li><p>레이블
 <code>{ foo: bar() }</code>
 ➕ 레이블 점프 : <code>continue</code> &amp; <code>break</code></p>
<br>

</li>
</ol>
<h3 id="2-블록">2) 블록</h3>
<pre><code class="language-jsx">[] + {}; //&quot;[object Object]&quot;
{} + []; // 0</code></pre>
<ol>
<li>윗 줄에서 엔진은 + 연산자 표현식의 {}를 실제 값으로 해석 → []는 &quot; &quot; 로 강제 변환 → <code>&quot;[object Object]&quot;</code> 로 강제변환</li>
<li>아랫 줄의 {}는 동떨어진 빈 블록으로 간주 → <code>+ []</code> 표현식에서 명시적으로 [] 를 숫자 0으로 강제변환<br>


</li>
</ol>
<h3 id="3-객체-분해">3) 객체 분해</h3>
<p>: 객체 분해 시 { } 사용</p>
<pre><code class="language-jsx">function getData() {
    // ...
    return {
        a: 42,
        b: &quot;foo&quot;
    };
}

var { a, b } = getData();
console.log( a, b ); // 42 &quot;foo&quot;</code></pre>
<br>



<h3 id="4-else-if와-선택적-블록">4) else if와 선택적 블록</h3>
<p>📍 자바스크립트 문법에 else if같은 것은 없음
정확한 문법은 다음과 같음</p>
<pre><code class="language-jsx">if(a) {
    //...
}
else {
    if (b) {
        //...
    }
    else {
        //...
    }
}</code></pre>
<br>
<br>


<h1 id="52-연산자-우선순위">5.2 연산자 우선순위</h1>
<pre><code class="language-jsx">var a = 42, b;
b = ( a++, a );
a; // 43
b; // 43

var a = 42, b;
b = a++, a;
a; // 43
b; //42</code></pre>
<p>💡 <code>,</code> 연산자가 <code>=</code> 연산자보다 우선순위가 낮아서 값이 달라짐
<br></p>
<pre><code class="language-jsx">if(str &amp;&amp; (matches = str.match( /[aeiou]/g ))) {
    //...
}</code></pre>
<p>💡 &amp;&amp;가 =보다 우선순위가 높으므로 ()로 묶지 않으면 달라짐
<br></p>
<pre><code class="language-jsx">true || false &amp;&amp; false; //true

(true || false) &amp;&amp; false; // false
true || (false &amp;&amp; false); // true</code></pre>
<p>💡 좌측 → 우측 연산이라고 생각하지만 &amp;&amp;가 || 보다 우선하여 처리됨!!
<br>
<br></p>
<h3 id="단락-평가">단락 평가</h3>
<p>: &amp;&amp;, || 연산자는 좌측 피연산자의 평가 결과만으로 전체 결과가 이미 결정될 경우 우측 피연산자의 평가를 건너뜀
ex) <code>a &amp;&amp; b</code> 에서 a가 falsy면 b는 쳐다보지 않음
<br></p>
<p>📌 <code>&amp;&amp; &gt; || &gt; ? :</code> 순으로 우선순위 높음</p>
 <br>


<h3 id="결합성">결합성</h3>
<p>대부분 좌측 결합성을 가지지만 예외 연산자가 있음</p>
<ul>
<li><code>? :</code> : 우측 결합성을 가짐</li>
<li><code>=</code> : 우측 결합성을 가짐</li>
</ul>
<p>💡 정확히 하고자 () 로 그룹핑해주면 햇갈일 일 없다!
<br>
<br></p>
<h1 id="53-세미콜론-자동-삽입">5.3 세미콜론 자동 삽입</h1>
<p>ASI : 자바스크립트 프로그램의 세미콜론이 누락된 곳에 엔진이 자동으로 ;를 삽입</p>
<p>💡 break, continue, return, yield 키워드에서 활약
<br>
<br></p>
<h1 id="54-에러">5.4 에러</h1>
<p>: 자바스크립트에는 하위 에러 타입 뿐만 아니라 일부 에러는 컴파일 시점에 발생하도록 문법적으로 정의되어 있음
<br></p>
<p>📍 정규 표현식 리터럴 내부의 구문</p>
<pre><code class="language-jsx">var a = /+foo/; //에러</code></pre>
<br>

<p>📍 식별자가 아닌 것에 할당</p>
<pre><code class="language-jsx">var a;
42 = a; //에러</code></pre>
<br>

<p>📍 엄격 모드에서 함수 인자명 중복</p>
<pre><code class="language-jsx">function foo(a, b, a) {} //정상실행
function bar(a, b, a) { &quot;use strict&quot;; } //에러</code></pre>
<br>

<p>📍 동일한 이름의 프로퍼티가 여러개 있는 객체 리터럴</p>
<pre><code class="language-jsx">(function() {
    &quot;use strict&quot;;
    var a = {
        b: 42,
        b: 43
    }; //에러
})();</code></pre>
<br>

<p>💡 임시 데드 존(TDZ) : 아직 초기화를 하지 않아 변수를 참조할 수 없는 코드 영역</p>
<pre><code class="language-jsx">a = 2; //ReferenceError
let a;</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[React] 리액트 코드 작성법]]></title>
            <link>https://velog.io/@cool_kim/React-%EB%A6%AC%EC%95%A1%ED%8A%B8-%EC%BD%94%EB%93%9C-%EC%9E%91%EC%84%B1%EB%B2%95</link>
            <guid>https://velog.io/@cool_kim/React-%EB%A6%AC%EC%95%A1%ED%8A%B8-%EC%BD%94%EB%93%9C-%EC%9E%91%EC%84%B1%EB%B2%95</guid>
            <pubDate>Thu, 15 Jul 2021 16:38:07 GMT</pubDate>
            <description><![CDATA[<h1 id="효율적인-컴포넌트-파일-작성">효율적인 컴포넌트 파일 작성</h1>
<pre><code class="language-jsx">//가장 상단에 속성값의 타입 정의
MyComponenet.propTypes = {
    //...객체입력
}

//컴포넌트 학수 작성 시 함수에 이름을 부여해주어야함
//컴포넌트 매개변수는 명명된 매개변수 문법으로 작성
export default function MyComponent({ prop1, prop2 }) {
    //...
}

const COLUMNES = [
    { id: 1, name: &#39;phoneNumber&#39;, width: 2100, color: &quot;white&quot; },
    { id: 1, name: &#39;city&#39;, width: 100, color: &quot;grey&quot; },
    //...
];

const URL_PRODUCT_LIST = &#39;/api/products&#39;;
function getTotalPrice({ price, total }) {
    //...
}</code></pre>
<p>🔹 가장 상단에 속성값 타입 정의 : 컴포넌트 사용 시 속성값을 입력해야함. 편리할 수 있도록 가장 상단에 적어주는 것이 좋음
🔹 함수 이름 정의 : 이름 정의 하지 않으면 리액트 개발자 도구에서 디버깅이 힘듬
🔹 명명된 매개변수 문법으로 작성 : 불필요한 코드 발생
🔹 컴포넌트 밖의 변수와 함수는 파일 가장 밑에 정의
🔹 외부 변수 명은 대문자로 작성 : 변하지 않는 값이라는 걸 시각적으로 보여줌
🔹 매우 큰 객체 생성은 컴포넌트 밖에서 처리하는 것이 좋음
<br></p>
<p>📍 컴포넌트 내부에서 서로 연관된 코드는 한 곳으로 모아 관리하는 것이 좋음
⇒ useState 따로 모으고 useEffect모으고 보다는 관련된 훅끼리 묶어 작성
⇒ 커스텀 훅으로 분리할 때도 편함
<br>
<br></p>
<h1 id="속성값-타입-정의-prop-types">속성값 타입 정의: prop-types</h1>
<pre><code class="language-jsx">User.propTypes = {
    male : PropTypes.bool.isRequired,
    age: PropTypes.number,
    type: PropTypes.oneOf([&#39;gold&#39;, &#39;silver&#39;, &#39;bronze&#39;]),
    onChangeName: PropTypes.func,
    onChangeTitle: PropTypes.func.isRequired,
};</code></pre>
<p>🔹 isRequired : 필수값 
🔹 oneOf : 입력해 준 값 중에 하나만 받을 수 있음
<br></p>
<p>🔺 함수의 매개변수, 반환값에 대한 타입 정보 정의할 수 없음</p>
<ul>
<li>주석으로 자세한 타입 적어주기!<br>

</li>
</ul>
<pre><code class="language-jsx">MyComponent.propTypes = {
    menu: PropTypes.element,
    description: PropTypes.node,
    message: PropTypes.instanceOf(Message),
    name: PropTypes.oneOf([&#39;jone&#39;, &#39;mike&#39;]).
    width: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
    ages: PropTypes.arrayOf(PropTypes.number),
    info: PropTypes.shape({
        color: PropTypes.string,
        weight: PropTypes.number,
    }),
    infos: PropTypes.objectOf(PropTypes.number),
}</code></pre>
<p>🔹 element : 리액트 요소
🔹 node : 리액트 요소 뿐 아니라 리액트 컴포넌트가 반환할 수 있는 모든 값
🔹 instanceOf() : 특정 클래스의 객체인지 검사
🔹 oneOfType() : 타입을 배열로 입력 → 입력해 준 값 모두 참
🔹 arrayOf() : 매개변수로 넘겨준 타입으로 이루어진 배열
🔹 shape() : 객체 타입
🔹 objectOf() :  각 속성의 value 타입이 매개변수로 넘겨준 타입이다.</p>
<br>
<br>

<h1 id="가독성-높이는-조건부-렌더링">가독성 높이는 조건부 렌더링</h1>
<pre><code class="language-jsx">//if문 사용
function Greeting({ isLogin, name }) {
    if (isLogin) {
        return &lt;p&gt;{`${anme}님 안녕하세요.`}&lt;/p&gt;
    }
}

//삼항 연산자 사용
function GreetingB({ isLogin, name }) {
    return &lt;p&gt;{isLogin ? `${name}님 안녕하세요.` : `권한이 없습니다.`}&lt;/p&gt;
}</code></pre>
<p>📍 삼항 연산자를 사용하는게 대부분 좋음</p>
<p>🔹 jsx부분에서 삼항 연산자를 사용하여 특정 부분을 가리고 싶을 때 : &amp;&amp; 기호를 쓰면 끝에 null을 붙이지 않아도 됨</p>
<br>
<br>

<h1 id="재사용성을-고려한-컴포넌트-구분법">재사용성을 고려한 컴포넌트 구분법</h1>
<p>관심사의 분리 : 복잡한 코드를 비슷한 기능을 하는 코드끼리 모아 별도로 관리</p>
<ul>
<li>UI처리 코드 &amp;&amp; api호출 코드 &amp;&amp; DB 관리 코드 ⇒ 같은 파일에서 관리 x<br>

</li>
</ul>
<p>💡 코드가 복잡해지고 있다! → 관심사의 분리 필요함
<br></p>
<p>🔹 연관된 컴포넌트끼리 폴더를 만들어 관리해야함
🔹 상태값의 중복 : 자식 컴포넌트에서 부모의 데이터를 별도의 상태값으로 관리하는 것은 좋지 않음</p>
<ul>
<li>상태값은 일부 컴포넌트로 한정하여 관리하는 것이 좋음</li>
</ul>
<p>🔹 컴포넌트가 비지니스 로직 &amp;&amp; 상태값을 가지고 있으면 재사용성 떨어짐</p>
<ul>
<li>비지니스 로직과 상태값의 유무로 컴포넌트 분리하는 것이 좋음</li>
</ul>
<br>

<p>📌 재사용성이 좋은 컴포넌트 : 비지니스 로직이 없다, 상탯값이 없다.<em>(마우스 오버와 값은 UI 효과를 위한 상태값 제외)</em></p>
<br>

<p>✔️ component 폴더 : 재사용성이 높은 컴포넌트 파일
✔️ container 폴더 : 재사용성이 낮은 컴포넌트 파일</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[자바스크립트/Javascript] 강제변환(2)]]></title>
            <link>https://velog.io/@cool_kim/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8Javascript-%EA%B0%95%EC%A0%9C%EB%B3%80%ED%99%982</link>
            <guid>https://velog.io/@cool_kim/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8Javascript-%EA%B0%95%EC%A0%9C%EB%B3%80%ED%99%982</guid>
            <pubDate>Wed, 14 Jul 2021 15:12:07 GMT</pubDate>
            <description><![CDATA[<h1 id="44-암시적-변환">4.4 암시적 변환</h1>
<p>: 부수 효과가 명확하지 않게 숨겨진 형태로 일어나는 타입변환
📍 불필요한 상세 구현 줄이는게 목표
<br></p>
<h2 id="암시적">암시적?</h2>
<p>임의의 타입 → Sometype 타입 변환</p>
<ul>
<li>엄격한 타입 언어의 강제 변환 : 원래 타입 → Another 타입 → Sometype타입</li>
<li>암시적 타입 언어의 강제 변환 : 원래 타입 → Sometype타입<ul>
<li>지저분한 코드를 감출 수 있음</li>
</ul>
</li>
</ul>
<p>⚠️ 명시적 강제변환이 물론 좋지만 무조건적으로 암시적 강제변환이 나쁜건 아니다.
<br></p>
<h2 id="문자열-↔️-숫자">문자열 ↔️ 숫자</h2>
<p>🔹 + 연산자 : 숫자의 덧셈 or 문자열 접합으로 오버로드 → 어떻게 두개의 연산을 구분?</p>
<ol>
<li><ul>
<li>알고리즘은 한쪽 피연산자가 문자열이거나 문자열 표현형으로 나타낼 수 있으면 문자열 붙이기 수행</li>
<li>ToPrimitive 추상 연산을 수행</li>
<li>ToPrimitive 는 number 콘텍스트 힌트를 넘겨 [[DefaultValue]] 알고리즘 호출
⇒ ToNumber 추상 연산이 객체를 다루는 방법과 일치❗</li>
</ul>
</li>
<li><code>a + &quot;&quot;</code> : 숫자를 문자열로 강제 변환하는 관용코드 <strong>(암시적 강제변환임)</strong>
 ⚠️ 평범한 원시 숫자 값이 아닌 개체라면 문자열이 달라질 수 있음 <br>


</li>
</ol>
<p>🔹 - 연산자 : 숫자 뺄셈 기능이 전부</p>
<ol>
<li><code>a - 0</code> : a 값을 숫자로 강제변환
 → <em>곱하기, 나누기 연산도 마찬가지</em></li>
<li>객체 값에 - 연산 : + 연산과 비슷<ul>
<li>배열은 모두 문자열로 강제변환 뒤 숫자로 강제변환 그후, - 연산<br>

</li>
</ul>
</li>
</ol>
<h2 id="불리언-➡️-숫자">불리언 ➡️ 숫자</h2>
<p>👍 복잡한 형태의 불리언 로직을 숫자 덧셈 형태로 단순화 할 때 편리함</p>
<p>🔹 <code>!!arguments[i]</code> : true/false로 강제 변환</p>
<ul>
<li>true / truthy : 1</li>
<li>false / falsy : 0<br>


</li>
</ul>
<h2 id="-➡️-불리언">* ➡️ 불리언</h2>
<p>🔹 <code>if ()</code> 문의 조건 표현식
🔹 <code>for (  ;  ;  )</code> 에서 두 번째 조건 표현식
🔹 <code>while ()</code> 및 <code>do ... while()</code> 루프의 조건 표현식
🔹 <code>? :</code> 상항 연산 시 첫 번째 조건 표현식
🔹 <code>||</code> 및 <code>&amp;&amp;</code> 의 좌측 피연산자</p>
<p>📍 콘텍스트에서 불리언이 아닌 값이 사용되면 일단 불리언 값으로 암시적 강제변환 됨.</p>
<br>

<h2 id="와--연산자"><code>&amp;&amp;</code> 와 <code>||</code> 연산자</h2>
<p>💡 자바스크립트에서 두 연산자는 다른 언어와 달리 실제로 결괏값이 논리 값이 아님!!
⇒ <code>&amp;&amp;</code> 또는 <code>||</code> 연산자의 결괏값이 반드시 불리언 타입이어야 하는 것은 아니며 항상 <strong>두 피연산자 표현식 중 어느 한쪽 값으로 귀결</strong>됨</p>
<pre><code class="language-jsx">a || b;
a ? a : b; //위와 같은 코드

a &amp;&amp; b;
a ? b : a; //위와 같은 코드</code></pre>
<p>⚠️ <code>&quot; &quot;</code> 값은 falsy값임
<br></p>
<p>🔹 <code>||</code> 연산자</p>
<ul>
<li>falsy값은 무조건 건너 뛸 경우에만 사용해야함</li>
<li>아닐 경우 조건 평가식을 삼항 연산자로 더 명시적으로 지정해야함</li>
</ul>
<p>🔹 <code>&amp;&amp;</code> 연산자</p>
<ul>
<li>가드 연산자 : 첫번째 피연산자의 평가 결과가 truthy일 때에만 두번째 피연산자 선택<br>

</li>
</ul>
<p>📍 복합 논리 표현식의 작동 방식</p>
<ul>
<li>복합 표현식 평가 → 불리언으로 암시적 강제 변환</li>
</ul>
<br>

<h2 id="심벌-강제변환">심벌 강제변환</h2>
<p>: <code>심벌 -&gt; 문자열</code> 명시정 강제변환은 👌, 암시적 강제변환은 ❌
<br></p>
<p>🖐️ <strong>BUT!</strong> 불리언 값으로는 명시적/암시적 모두 강제변환 가능
<br>
<br>
<br></p>
<h1 id="45-느슨한엄격한-동등-비교">4.5 느슨한/엄격한 동등 비교</h1>
<p>🔹 느슨한 동등 비교 : <code>==</code> ➡️ 강제변환 ⭕</p>
<p>🔹 엄격한 동등 비교 : <code>===</code> ➡️ 강제변환 ❌</p>
<p>📌 강제 변환이 필요하다면 <code>==</code> 필요하지 않다면 <code>===</code> 사용</p>
<h2 id="추상-동등-비교">추상 동등 비교</h2>
<p>: <code>==</code> 연산자 로직은 추상적 동등 비교 알고리즘</p>
<ul>
<li>비교할 두 값이 같은 타입이면 값을 보고 식별</li>
<li>NaN은 그 자신과도 동등하지 않음</li>
<li>+0과 -0은 동등하지 않음<br>

</li>
</ul>
<p>📍 객체의 느슨한 동등 비의 경우 정확히 똑같은 값에 대한 레퍼런스일 경우에만 동등 ➡️ 강제변환 일어나지 않음!
<br></p>
<h3 id="문자열-➡️-숫자">문자열 ➡️ 숫자</h3>
<pre><code class="language-jsx">var a = 42;
var b = &quot;42&quot;;

a === b; // false
a == b; // true</code></pre>
<p>🔹 <code>===</code>는 강제 변환이 안되므로 <code>false</code>
🔹 <code>==</code> 는 피연산자의 타입이 다르면 비교알고리즘에 의해 피연산자 값이 암시적으로 강제변환되어 <code>true</code></p>
<br>

<h3 id="-➡️-불리언-1">* ➡️ 불리언</h3>
<pre><code class="language-jsx">var x = true;
var y = &quot;42&quot;;

x == y; //false</code></pre>
<ol>
<li>Type( x ) 는 불리언이므로 ToNumber(x) → 1 로 강제변환</li>
<li>1 == &quot;42&quot;가 되는데 타입이 다르므로 알고리즘 수행</li>
<li>&quot;42&quot;는 42로 바뀌어 1 == 42 → false가 됨</li>
</ol>
<p>📍 <code>== true</code> or <code>== false</code> 와 같은 코드는 안쓰는 것이 좋음
<code>===</code> 는 괜찮아요!</p>
<br>

<h3 id="null-➡️-undefined">null ➡️ undefined</h3>
<p>🔹 null과 undefined를 느슨한 동등 비교하면 강제변환
🔹 이 강제변환은 안전하고 예측 가능하며, 어떤 다른 값도 비교 결과 긍정 오류를 할 가능성이 없음</p>
<br>

<h3 id="객체-➡️-비객체">객체 ➡️ 비객체</h3>
<pre><code class="language-jsx">var a = &quot;abc&quot;;
var b = Object( a );

a === b; //false
a == b; //true

var x = null;
var y = Object( x );
x == y; // false

var c = undefined;
var d = Object( c ); 
c == d; //false

var e = NaN;
var f = Object( e );
e == f; //false</code></pre>
<ul>
<li>b는 ToPrimitive연산으로 &quot;abc&quot;라는 단순 스칼라 원시값으로 강제변환되어 a == b가 true 맞음</li>
<li>a == b 는 true가 맞음</li>
<li>null과 undefined는 객체 래퍼가 따로 없어 박싱할 수 없음</li>
<li>NaN은 해당 객체 래퍼인 Number로 박싱되지만 결국 조건식은 <code>NaN == NaN</code>이 되어 false가 됨</li>
</ul>
<br>
<br>

<h2 id="희귀-사례">희귀 사례</h2>
<h3 id="falsy비교">falsy비교</h3>
<pre><code class="language-jsx">&quot;0&quot; == false; //true
false == 0; //true
false == &quot;&quot;; //true
false == []; //true
&quot;&quot; == 0; //true
&quot;&quot; == []; //true
0 == []; //true</code></pre>
<p>➡️ 긍정 오류 </p>
<br>

<h3 id="다양한-오류">다양한 오류</h3>
<pre><code class="language-jsx">[] == ![] //true

2 == [2]; //true
&quot;&quot; == [null]; //true

0 == &quot;\n&quot;; //true</code></pre>
<br>
<br>
<br>

<h1 id="46-추상-관계-비교">4.6 추상 관계 비교</h1>
<p>:  a &lt; b 비교 과정
<br></p>
<p>🔹 피연산자 모두 문자열일 때</p>
<ul>
<li>각 문자를 단순 어휘로 비교(알파벳 순서로)<br>

</li>
</ul>
<p>🔹 그 외의 경우</p>
<ul>
<li>어느 한쪽이라도 문자열이 아닐 경우 양 쪽 모두 ToNumber로 강제변환하여 비교</li>
</ul>
<br>

<p>📍 자바스크립트 엔진은 <code>&lt;=</code> 를 &#39;더 크지 않은&#39;(<code>!(a &gt; b) → !(b &lt; a)</code>)의 의미로 해석</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[React] 리액트 context, ref, 훅]]></title>
            <link>https://velog.io/@cool_kim/React-%EB%A6%AC%EC%95%A1%ED%8A%B8-context-ref-%ED%9B%85</link>
            <guid>https://velog.io/@cool_kim/React-%EB%A6%AC%EC%95%A1%ED%8A%B8-context-ref-%ED%9B%85</guid>
            <pubDate>Mon, 12 Jul 2021 12:09:41 GMT</pubDate>
            <description><![CDATA[<h1 id="리액트-context">리액트 context</h1>
<p>하위 컴포넌트가 상위 컴포넌트에서 상당히 멀리 떨어져 있을때 사용</p>
<p>📍 기계적으로 속성값을 전달하는 코드</p>
<pre><code class="language-jsx">export default function App() {
    return (
        &lt;div&gt;
            &lt;div&gt;상단 메뉴&lt;/div&gt;
            &lt;Profile username=&quot;mike&quot; /&gt;
            &lt;div&gt;하단 메뉴&lt;/div&gt;
        &lt;/div&gt;
    );
}

function Profile({ usename }) {
    return (
        &lt;div&gt;
            **&lt;Greeting username={username} /&gt;**
            {/* ... */}
        &lt;/div&gt;
    );
}

function Greeting({ username }) {
    return &lt;p&gt;{`${username}님 안녕하세요`}&lt;/p&gt;;
}</code></pre>
<p>📍 context 사용시</p>
<pre><code class="language-jsx">import React, { createContext } from &#39;react&#39;

const UserContext = createContext(&#39;unknown&#39;);

export default function App() {
    return (
        &lt;div&gt;
            &lt;UserContext.Provider value=&quot;mike&quot;&gt;
                &lt;div&gt;상단 메뉴&lt;/div&gt;
                &lt;Profile username=&quot;mike&quot; /&gt;
                &lt;div&gt;하단 메뉴&lt;/div&gt;
            &lt;/UserContext.Provider&gt;
        &lt;/div&gt;
    );
}

function Profile({ usename }) {
    return (
        &lt;div&gt;
            **&lt;Greeting/&gt;**
            {/* ... */}
        &lt;/div&gt;
    );
}

function Greeting({ username }) {
//...이 부분에서 username 사용할 수 없음
//사용 하고 싶으면 다음 코드 작성
    const username = useContext(UserContext);
    return (
        &lt;UserContext.Consumer&gt;        
            {username =&gt; &lt;p&gt;{`${username}님 안녕하세요`}&lt;/p&gt;}
        &lt;/UserContext.Consumer&gt;
    );
}</code></pre>
<p>✔️ Provider에서 value값을 넘겨 주면 Consumer에서 그 값을 받아 처리 가능</p>
<ul>
<li>Provider 컴포넌트의 값이 변경 되면 하위 모든 Consumer 컴포넌트 다시 렌더링<br>

</li>
</ul>
<p>👍 데이터의 종류별로 Context를 나누면 렌더링 성능에 좋음
<br><br></p>
<p>📍 하위 컴포넌트에서 데이터 수정하기</p>
<pre><code class="language-jsx">const UserContext = createContext({ username: &#39;unknown&#39;, helloCount: 0 });
const setUserContext = createContext(() =&gt; {});

export default fuction App() {
    const [user, setUser] = userState({ username: &#39;mike&#39;, helloCount: 0 });
    return (
      &lt;div&gt;
            &lt;setUserContext.Provider value={setUser}&gt;
                &lt;UserContext.Provider value={user}&gt;
                    &lt;Profile /&gt;
                &lt;/UserContext.Provider&gt;
            &lt;/setUserContext.Provider&gt;
        &lt;/div&gt;
    );
}</code></pre>
<p>⚠️ context 사용 시 주의할 점</p>
<ol>
<li>Provider value값이 변경 되지 않아도 매번 불필요하게 렌더링 될 수 있음</li>
<li>Provider 컴포넌트 밖에서 자식 컴포넌트를 렌더링 되면 상태값이 변하지 않음
<br><br></li>
</ol>
<h1 id="ref">ref</h1>
<p>: 자식 요소에 직접 접근하기</p>
<p>📍 useRef훅 : 함수형 컴포넌트에서는 사용 불가능</p>
<pre><code class="language-jsx">export default function App() {
    const inputRef = useRef();
    useEffect(() =&gt; {
        inputRef.current.focus();
    }, []);

    return (
        &lt;div&gt;
            &lt;input type=&quot;text&quot; ref={inputRef} /&gt;
            &lt;Box ref={inputRef} /&gt;
            &lt;button&gt;저장&lt;/button&gt;
        &lt;/div&gt;
    );
}</code></pre>
<p>⇒ current 함수는 실제 돔 요소를 가리키게 됨
📍 useImperativeHandel훅 사용하면 함수형 컴포넌트에서도 사용 가능
<br></p>
<p>📍 forwardRef</p>
<pre><code class="language-jsx">const Button = React.forwardRef(function ({ onClick }, ref ) {
    return (
        &lt;button onClick={onClick} ref={ref}&gt;저장&lt;/button&gt;
    );
}</code></pre>
<p>📍 useRef 시용하지 않고 ref속성값에 함수 입력하기
→ 이 함수는 해당 요소가 생성되거나 사라질 때 한번 씩 호출</p>
<pre><code class="language-jsx">ref={ref =&gt; ref &amp;&amp; setText(INITIAL_TEXT)}</code></pre>
<p>⚠️ useCallback훅 사용해서 함수 고정시키기</p>
<pre><code class="language-jsx">const setInetialText = useCallback(ref =&gt; ref &amp;&amp; setText(INITIAL_TEXT), []);</code></pre>
<p>📍 접근하고자 하는 돔 요소의 개수가 많을 때</p>
<pre><code class="language-jsx">const boxListRef = useRef({});

{BOX_LIST.map(item =&gt; {
    &lt;div
        key={item.id}
        ref={ref =&gt; {boxListRef.current[item.id] = ref}}
        style={{
            flex: &#39;0 0 auto&#39;,
        }}
    &gt;{`box_${iteml.id}`}&lt;/div&gt;
))}</code></pre>
<p>⚠️ 조건부 렌더링에 사용된 요소의 ref객체는 current속성을 검사하는 코드 필요
<br><br></p>
<h1 id="리액트-내장-훅">리액트 내장 훅</h1>
<ul>
<li><p>useState</p>
</li>
<li><p>useEffect</p>
</li>
<li><p>useContext</p>
</li>
<li><p>useRef</p>
<ul>
<li>렌더링과 상관없는 값을 저장할 때 유용하게 사용 (setTimeout)</li>
</ul>
</li>
<li><p>useMemo</p>
<ul>
<li>메모이제이션 기능 제공</li>
<li>계산량이 많은 함수의 반환값을 재활용하는 용도</li>
<li><code>const value = useMemo(() =&gt; renExpensiceJob(v1, v2), [v1, v2]);</code></li>
</ul>
</li>
<li><p>useCallback</p>
<ul>
<li>메모이제이션 기능 제공 ( 함수 메모이제이션에 특화 )</li>
<li>불필요하게 렌더링 되는 현상을 막기 위해 사용</li>
<li><code>const onSave = useCallback(() =&gt; saveToServer(name, age), [name, age])</code></li>
</ul>
</li>
<li><p>useReducer</p>
<ul>
<li>여러개의 상태값을 하나의 훅으로 관리</li>
<li>반환 값 : 상태값 &amp; dispatch함수</li>
<li><code>const [state, dispatch] = useReducer(reducer, INITIAL_STATE);</code></li>
<li>context의 Provider를 사용해서 dispatch 함수 내려 보내 줄 수 있음</li>
</ul>
</li>
<li><p>useImperativeHandle</p>
<ul>
<li>함수가 반환하는 값이 부모의 ref객체가 참조하는 값이 됨</li>
</ul>
</li>
<li><p>useLayoutEffect</p>
<ul>
<li>부수효과 함수를 동기로 호출 → 렌더링 결과가 돔에 반영된 직후에 바로 호출</li>
<li>이 훅 안에서 연산을 많이 하면 브라우저 먹통이 될 수 있음</li>
</ul>
</li>
<li><p>useDebugValue</p>
<ul>
<li><p>리액트 개발자 도구에 좀 더 풍부한 정보 제공 가능(디버깅할 때 편리)</p>
<pre><code class="language-jsx">useDebugValue(
  state === STATE_START
      ? &#39;start&#39;
      : state === STATE_RUNNING
      ? &#39;running&#39;
      : &#39;stop&#39;,
};</code></pre>
<p>📍결과</p>
</li>
</ul>
</li>
</ul>
<p><img src="https://images.velog.io/images/cool_kim/post/7bd6abb7-f736-4034-8648-4fcddbbeb537/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[자바스크립트/Javascript] 강제변환(1)]]></title>
            <link>https://velog.io/@cool_kim/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8Javascript-%EA%B0%95%EC%A0%9C%EB%B3%80%ED%99%981</link>
            <guid>https://velog.io/@cool_kim/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8Javascript-%EA%B0%95%EC%A0%9C%EB%B3%80%ED%99%981</guid>
            <pubDate>Sun, 11 Jul 2021 16:37:46 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>강제변환은 마법? 아니면 사악??</p>
</blockquote>
<h1 id="41-값변환">4.1 값변환</h1>
<p>강제 변환 : 어떤 값을 다른 타입의 값으로 암시적으로 바꿈
→ 강제 변환 시 객체, 함수 같은 합성 값 타입으로 변환될 수 없음</p>
<ul>
<li>암시적 강제변환 : 다른 작업 도중 불분명한 부수 효과로부터 발생하는 타입 변환</li>
<li>명시적 강제변환 : 의도적인 타입변환</li>
</ul>
<pre><code class="language-jsx">var a = 42;
var b = a + &quot;&quot;; //암시적 강제변환
var c = String( a ); //명시적 강제변환</code></pre>
<p><br><br></p>
<h1 id="42-추상-연산">4.2 추상 연산</h1>
<h2 id="tostring">ToString</h2>
<p>: 문자열이 아닌 값 → 문자열 변환 작업</p>
<ul>
<li><p>숫자
숫자 : 문자열 반환
너무 작거나 큰 값 : 지수 형태 문자열로 반환</p>
</li>
<li><p>일반 객체
특별히 지정하지 않으면 기본적으로 내부 [[Class]] 반환 <code>ex) [object Object]</code></p>
</li>
<li><p>배열
모든 원소 값이 콤마(,)로 분리된 형태로 반롼 <code>ex) &quot;1,2,3&quot;</code></p>
</li>
<li><p>JSON
✔️ <code>JSON.stringfy()</code> : 어떤 값을 JSON 문자열로 직렬화
→ 강제변환과 똑같지 않지만 ToString 규칙과 관련됨</p>
<ol>
<li><p>JSON 안전 값(JSON으로 확실히 나타낼 수 있는 값)은 모두 JSON.stringfy()로 문자열화 가능</p>
</li>
<li><p>JSON 안전 값이 아닌 것들은 자동으로 누락시키며 이런 값이 배열에 들어있으면 null로 바꿈</p>
<pre><code class="language-javascript">JSON.stringfy( undefined ); //undefined
JSON.stringfy( function(){} ); //undefined

JSON.stringfy(
[1,undefined,function(){},4]
); // &quot;[1,null,null,4]&quot;

JSON.stringfy(
{ a:2, b:function(){} }
); //&quot;{&quot;a&quot;:2}&quot;</code></pre>
</li>
</ol>
</li>
</ul>
<ol start="3">
<li><p>JSON.stringfy()에 환형 참조 객체(프로퍼티 참조가 무한 순환되는 구조의 객체)를 넘기면 에러 발생</p>
</li>
<li><p>JSON.stringfy()의 세번째 인자는 &#39;스페이스&#39; : 들여 쓰기를 할 빈 공간의 개수를 숫자로 지정하거나 문자열을 지정하여 각 들여쓰기 수준에 사용</p>
<pre><code class="language-javascript"> var a = {
     b: 42,
     c: &quot;42&quot;,
     d: [1,2,3]
 };

 JSON.stringfy( a, null, 3 );
 // &quot;{
 //    &quot;b&quot;: 42,
 //    &quot;c&quot;: &quot;42&quot;,
 //    &quot;d&quot;: [
 //       1,
 //       2,
 //       3
 //    ]
 // ]&quot;

 JSON.stringfu( a, null, &quot;-----&quot; );
 // &quot;{
 // -----&quot;b&quot;: 42,
 // -----&quot;c&quot;: &quot;42&quot;,
 // -----&quot;d&quot;: [
 // ----------1,
 // ----------2,
 // ----------3
 // -----]
 // }&quot;</code></pre>
</li>
</ol>
<p>✔️ toJSON() : 해당 객체의 JSON 안전 버전 반환
→ JSON문자열로 바꾸는 것이 아님</p>
<pre><code class="language-javascript">var a = {
    val: [1,2,3],
    toJSON: function() {
        return this.val.slice( 1 );
    }
};

var b = {
    val: [1,2,3],
    toJSON: function(){
        return &quot;[&quot; +
            this.val.slice( 1 ).join() +
        &quot;]&quot;;
    }
};

JSON.stringfy(a); // &quot;[2,3]&quot;
JSON.stringfy(b); // &quot;&quot;[2,3]&quot;&quot;</code></pre>
<pre><code class="language-javascript">var a = {
    val: [1,2,3],
    toJSON: function() {
        return this.val.slice( 1 );
    }
};

var b = {
    val: [1,2,3],
    toJSON: function(){
        return &quot;[&quot; +
            this.val.slice( 1 ).join() +
        &quot;]&quot;;
    }
};

JSON.stringfy(a); // &quot;[2,3]&quot;
JSON.stringfy(b); // &quot;&quot;[2,3]&quot;&quot;</code></pre>
<ul>
<li>b는 배열 자체가 아니라 반환된 문자열을 다시 문자열화 함</li>
</ul>
<ol>
<li><p>대체자가 배열 </p>
<ul>
<li><p>전체 원소는 문자열이어야함</p>
</li>
<li><p>각 원소는 객체 직렬화의 대상 프로퍼티명</p>
<pre><code class="language-jsx">var a = {
  b: 42,
  c: &quot;42&quot;,
  d: [1,2,3]
};

JSON.stringfy(a, [&quot;b&quot;,&quot;c&quot;] ); // &quot;b{&quot;b&quot;:42,&quot;c&quot;:&quot;42&quot;}&quot;</code></pre>
</li>
</ul>
</li>
<li><p>대체자가 함수 </p>
<ul>
<li><p>키와 값 두 인자를 전달</p>
</li>
<li><p>처음 한 번은 객체 자신, 다음은 각 개체 프로퍼티별로 한번씩 실행</p>
</li>
<li><p>직렬화 과정에서 해당 키를 건너뛰려면 undefined, 그외엔 해당 값 반환</p>
<pre><code class="language-jsx">var a = {
  b: 42,
  c: &quot;42&quot;,
  d: [1,2,3]
};

JSON.stringfy( a, function(k,v) {
  if (k !== &quot;c&quot;) return v;
});
// &quot;{&quot;b&quot;:42,&quot;d&quot;:[1,2,3]}&quot;</code></pre>
</li>
</ul>
</li>
</ol>
<blockquote>
<p>JSON.stringfy()은 직접적인 강제 변환의 형식은 아니지만 두 가지 이유로 ToString 강제 변환과 연관 됨</p>
</blockquote>
<ol>
<li>문자열, 숫자, 불리언, null 값이 JSON으로 문자열화하는 방식은 ToStirng 추상 연산의 규칙에 따라 문자열 값으로 강제변환되는 방식과 동일</li>
<li>JSON.stirngfy()에 전달한 객체가 자체 toJSON()메서드를 갖고 있다면 문자열화 전 toJSON()가 자동 호출되어 JSON 안전 값으로 강제변환 됨</li>
</ol>
<h2 id="tonumber">ToNumber</h2>
<p>: 숫자 아닌 값 → 수식 연산이 가능한 숫자 변환</p>
<ul>
<li><p>true  → 1</p>
</li>
<li><p>false → 0</p>
</li>
<li><p>undefined → NaN</p>
</li>
<li><p>null → 0</p>
</li>
<li><p>문자열 → 숫자 리터럴 규칙/구문 or NaN</p>
</li>
<li><p><strong>0이 앞에 붙은 8진수 → 8진수로 처리하지 않음(일반 10진수로 처리</strong></p>
</li>
<li><p>객체(배열) → 동등한 원시 값으로 변환 후 그 결곽값을 ToNumber 규칙에 의해 강제변환</p>
<ul>
<li>추상 연산 과정에서 동등한 원시값으로 바꾸기 위해 valueOf() 메서드를 구현했는지 확인</li>
<li>어떻게 해도 원시 값으로 바꿀 수 없을 떄는 TyprError 오류 반환</li>
</ul>
</li>
<li><p>Object.create(null) : 강제변환이 불가능한 객체 생성</p>
</li>
</ul>
<h2 id="toboolean">ToBoolean</h2>
<ol>
<li><p>falsy 값</p>
<ul>
<li><p>undefined</p>
</li>
<li><p>null</p>
</li>
<li><p>false</p>
</li>
<li><p>+0, -0, NaN</p>
</li>
<li><p>&quot;&quot;</p>
<p>📍 falsy 객체
: 겉보기에는 평범한 객체처럼 작동할 것 같지만 불리언으로 강제변환하면 false</p>
<pre><code class="language-jsx">var a = new Boolean( false );
var b = new Number( 0 );
var c = new String( &quot;&quot; );

var d = Boolean( a&amp;&amp; b &amp;&amp; c );
d; // true</code></pre>
</li>
</ul>
</li>
<li><p>truthy 값</p>
<ul>
<li>falsy 값 목록에 없는 값</li>
</ul>
</li>
</ol>
<p>📌 헷갈리지 않으려면 falsy 값을 외워두는 것이 좋음!
<br><br></p>
<h2 id="명시적-강제-변환">명시적 강제 변환</h2>
<p>: 분명하고 확실한 타입변환</p>
<h3 id="문자열-↔-숫자">문자열 ↔ 숫자</h3>
<p>: String(), Number() 사용</p>
<p>⚠️ 앞에 new 키워드가 붙지 않기 때문에 객체 래퍼 생성하는 것이 아님</p>
<ul>
<li><p><code>toString()</code></p>
<p>  : 겉보기에는 명시적이지만 암시적인 요소 감춰져 있음</p>
<p>  → 원시값 42에는 toStirng() 메소드가 없으므로 엔진은 toStirng을 자용 할 수 있게 자동으로 42를 객체 래퍼로 &#39;박싱&#39;함</p>
</li>
<li><p><code>+c</code></p>
<p>  : 단한 연산자로 덧ㅅ겜을 하는게 아니라 피연산자 c를 숫자로 하는 명시적 강제변환</p>
<pre><code class="language-jsx">  var c = &quot;3.14&quot;;
  var d = 5+ +c;
  d; // 8.14</code></pre>
<p>  ⚠️ <code>var d = 5+ +c;</code> 두 부호 사이에 띄어 쓰기를 하지 않으면 증감 연산자가 되어버리니 조심!</p>
  <br>


</li>
</ul>
<h3 id="날짜-➡️-숫자">날짜 ➡️ 숫자</h3>
<p>: + 단항 연산자 사용</p>
<pre><code class="language-jsx">var d = new Date( &quot;Mon, 18 Aug 2014 08:53:06 CDT&quot; );
+d; // 1408369986000 (유닉스 타임스탬프 표현형)</code></pre>
<p>📍 현재 시각을 타임스탬프로 바꿀 때 : <code>var timestamp = +new Date();</code>
📍 강제변환 없이 Date 객체로부터 타임스탬프 얻기</p>
<pre><code class="language-jsx">var timestamp = new Date().getTime();
//var timestamp = (new Date()).getTime();
//var timestamp = (new Date).getTime();

var timestamp = Date.now();</code></pre>
<br>


<h3 id="틸드">틸드(~)</h3>
<p>: 보수로 변환</p>
<ol>
<li>32비트 숫자로 강제 변환</li>
<li>NOT연산</li>
</ol>
<p><code>~x</code> 는 <code>-(x+1)</code>과 같음</p>
<pre><code class="language-jsx">~42; // -(42+1) ==&gt; -43</code></pre>
<p>✔️ -(x+1)을 0으로 만드는 값은 -1이다.
 → -1이면 falsy한 0, 그 외에는 truthy한 숫자 값이 산출</p>
<p>📍 여기서 -1과 같은 성질의 값은 &#39;경계값&#39;이라고 함
    - 경계값 : 동일 타입의 더 확장된 값의 집합 내에서 임의의 어떤 의미를 부여한 값
    ex) indexOf() 에서 인덱스를 발견하지 못했을 경우 -1을 반환</p>
<pre><code class="language-jsx">var a = &quot;Hello World&quot;;

~a.indexOf( &quot;lo&quot; ); // -4 &lt;-- truthy
if(~a.indexOf( &quot;lo&quot; )) { // true
    //찾음
}

~a.indexOf( &quot;ol&quot; ); // 0 &lt;-- falsy
!~a.indexOf( &quot;ol&quot; ); // 0 &lt;-- true

if(!~a.indexOf( &quot;ol&quot; )) { // true
    //못찾음
}</code></pre>
<p><strong>더블 틸드(~~)</strong></p>
<p>: 숫자의 소수점 이상 부분 잘라내기</p>
<ol>
<li>맨 앞의 ~는 ToInt32 강제변환을 적용</li>
<li>각 비트를 거꾸로 함</li>
<li>두번째 ~는 비트를 또 한 번 뒤집음</li>
<li>원상태로 되돌림
⇒ ToInt32 강제변환만 하는 셈</li>
</ol>
<p>⚠️ 음수에서는 Math.floor()과 결과값이 다름</p>
<pre><code class="language-jsx">~~1E20 / 10; //166199296
1E20 | 0 /10; //1661992960 
(1E20 | 0) / 10; //166199296</code></pre>
<br>

<h3 id="숫자-형태의-문자열-파싱">숫자 형태의 문자열 파싱</h3>
<p>: 문자열 → 숫자 강제 변환과 결과가 비슷하지만 비숫자형 문자를 허용함</p>
<pre><code class="language-jsx">var a = &quot;42&quot;;
var b = &quot;42px&quot;;

Number( a ); //42
parseInt( a ); //42

Number( b ); //NaN
parseInt( b ); //42</code></pre>
<br>


<h3 id="→불리언">*→불리언</h3>
<p>: 비불리언 → 불리언 강제변환
: Boolean(), !! 로 강제 변환
<br></p>
<p>📍 삼항 연산자</p>
<pre><code class="language-jsx">var b = a ? true : false;</code></pre>
<p> ✔️삼항 연산자보다 Boolean(a)나 !!a같은 명시적 강제변환이 더 좋음</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[React] 리액트 훅]]></title>
            <link>https://velog.io/@cool_kim/React-%EB%A6%AC%EC%95%A1%ED%8A%B8-%ED%9B%85</link>
            <guid>https://velog.io/@cool_kim/React-%EB%A6%AC%EC%95%A1%ED%8A%B8-%ED%9B%85</guid>
            <pubDate>Sat, 10 Jul 2021 12:25:23 GMT</pubDate>
            <description><![CDATA[<h1 id="훅">훅</h1>
<p>: 컴포넌트에 기능을 추가할 때 사용하는 함수
ex) 컴포넌트에 상탯값 추가 or 자식 요소에 접근</p>
<ul>
<li>클래스형 컴포넌트보다 장점이 많으며 리액트 팀에서도 훅에 집중함<br>

</li>
</ul>
<p>대표적인 리액트 훅</p>
<ol>
<li>useState : 상탯값 추가</li>
<li>useEffect : 부수효과 처리(서버 API호출, 이벤트 핸들러 등록 등)</li>
</ol>
<h2 id="usestate">useState</h2>
<p><code>const [count, setCount] = useState(0);</code></p>
<ol>
<li><p>초기값을 넣어 호출</p>
</li>
<li><p>배열 반환 : 첫번째 아이템에는 <strong>상태값</strong>, 두번째 아이템에는 <strong>상태값 변경 함수</strong></p>
</li>
<li><p>상태값 변경 함수는 <strong>비동기</strong>이면서 <strong>배치(batch)</strong>로 처리됨</p>
<ul>
<li>만약 동기로 처리되면 하나의 상태값 변경 함수가 호출될 때마다 화면을 다시 그리기 때문에 성능 이슈가 생김</li>
<li>상태값 변경 함수를 동기로 처리하고 매번 화면을 다시 그리지 않는다면 UI데이터와 화면간의 불일치가 발생하여 혼란</li>
<li>동기로 처리하려면 상태값 변경 함수 안에 함수를 입력 <code>setCount(v =&gt; v + 1);</code>
  → 처리되기 직전의 상태값을 매개변수로 받기 때문에 잘 동작함</li>
<li>리액트에서 관리하지 않는 외부에서 호출하는 경우에는 배치로 동작하지 않음
  ex) <code>window.addEventListener(&#39;click&#39;, onclick);</code>
  → 상태값 변경 함수를 호출할 때마다 렌더링 발생<ul>
<li>외부에서 처리 될 때도 배치로 처리되게 하기
  → ubstable_batchedUpdates() 사용<pre><code class="language-jsx">  function onClick() {
      ReactDOM.unstable_batchedUpdates(() =&gt; {
          setCount(v =&gt; v + 1);
          setCount(v =&gt; v + 1);
      });
  }</code></pre>
</li>
</ul>
</li>
</ul>
</li>
<li><p>상태값 변경 함수는 호출한 순서대로 적용됨</p>
</li>
<li><p>여러개의 상태값을 하나의useState로 관리 할 수 있음(객체 이용)
 <code>const [state, setState] = useState({ name: &#39;&#39;, age: 0 });</code>
 상태값 변경 함수를 호출할 때는 전체 객체를 새로 입력해 줘야함
 <code>onChange={e =&gt; setState({ ...state, name: e.target.value })}</code>
 📍 어러 상태값을 관리할 때는 useState보다는 useReducer가 더 적합</p>
<p> <br><br></p>
</li>
</ol>
<h2 id="useeffect">useEffect</h2>
<p><em>모든 부수 효과는 useEffect훅에서 처리하는게 좋음</em></p>
<pre><code class="language-jsx">useEffect(() =&gt; {
    document.title = `업데이트 횟수: ${count}`;
});</code></pre>
<ol>
<li><p>첫번째 매개변수에 함수 작성(부수효과 함수) → 함수는 렌더링 결과가 실제 돔에 반영되고 비동기로 호출</p>
<p> ✔️ userId를 속성값으로 받아 api를 호출해 해당 유저의 정보를 가져온 다음, user 상태값을 변경</p>
<pre><code class="language-jsx">export default function Profile({ userId }) {
 const [user, setUser] = useState(null);

 //userId가 변경될 때만 부수효과함수 실행
 useEffect(() =&gt; {
     getUserApi(userId).then(data =&gt; setUser(data));
 }, [userId]);
 return (
     &lt;div&gt;
         {!user &amp;&amp; &lt;p&gt;사용자 정보를 가져오는 중...&lt;/p&gt;}
         {user &amp;&amp; (
             &lt;&gt;
                 &lt;p&gt;{`name is ${user.name}`}&lt;/p&gt;
                 &lt;p&gt;{`age is ${user.age}`}&lt;/p&gt;
             &lt;/&gt;
         )}
     &lt;/div&gt;
 );
}
</code></pre>
</li>
</ol>
<p>const USER1 = { name: &quot;mike&quot;, age: 23 };
const USER2 = { name: &quot;jane&quot;, age: 31 };</p>
<p>//userId가 홀수일때 USER1리턴 짝수일때 USER2리턴
function getUserApi(userId) {
    return new Promise[res =&gt; {
        setTimeout(() =&gt; {
            res(userId % 2 ? USER1 : USER2);
        }, 500);
    });
}</p>
<pre><code>
2. 두번째 매개변수로 배열 입력(**의존성 배열**) 
    - 이 배열에 있는 값이 변경될 때만 부수효과 함수 실행
    - 의존성 배열에 빈배열을 입력하면 부수 효과 함수는 마운트 된 이후에 한번만 호출
    - 부수효과 함수에서 사용한 변수(_컴포넌트의 상태값, 속성값, 컴포넌트 내부에서 정의된 지역변수, 지역함수_)  → 의존성 배열에 작성해 줘야함
    📍 `const [user, setUser] = useState(null);` 의 `setUser` 값(상태값 변경 함수)은 변하지 않기 때문에 배열에 추가 안해도 됨.
    - 의존성 배열의 값이 항상 변경될 때는 useCallback훅을 이용해 메모리에이션 기능 이용
    - 꼭 필요한 경우에만 입력해야함
    &lt;br&gt;
3. 부수효과 함수 반환값
    - useEffect에서 새로운 함수가 반환 될때는 다음 부수효과 함수가 호출되기 직전에 호출 or 컴포넌트가 사라지기(unmount) 직전에 호출 → 적어도 한번은 호출
    &lt;br&gt;

📍 이벤트 핸들러를 등록할 때 useEffect 부수효과 함수로 작성
📍 이벤트 핸들러 해제할 때 useEffect 반환 함수로 작성
```jsx
useEffect(() =&gt; {
    window.addEventListener(&#39;resize&#39;, onResize);
    return() =&gt; {
        window.removeEventListener(&#39;resize&#39;, onResize);
    };
}, []);</code></pre><p><br><br></p>
<h3 id="커스텀-훅-만들기">커스텀 훅 만들기</h3>
<ul>
<li><p>훅의 이름은 use로 시작하는 것이 좋음</p>
<pre><code class="language-jsx">export default function useUser(userId) {
  const[user, setUser] = userState(null);

  useEffect(() =&gt; {
      getUserApi(userId).then(data =&gt; setUser(data));
  }, [userId]);
  return user;
}
</code></pre>
</li>
</ul>
<p>//사용할때
const user = useUser(userId);</p>
<pre><code>⇒ userId가 변경되면 훅 내부에서 자동으로 api를 호출해서 사용자 데이터 가져올 것

👍 비동기 방식으로 동기 방식처럼 사용 가능!</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[React] 리액트 가상돔]]></title>
            <link>https://velog.io/@cool_kim/React-%EB%A6%AC%EC%95%A1%ED%8A%B8-%EA%B0%80%EC%83%81%EB%8F%94</link>
            <guid>https://velog.io/@cool_kim/React-%EB%A6%AC%EC%95%A1%ED%8A%B8-%EA%B0%80%EC%83%81%EB%8F%94</guid>
            <pubDate>Sat, 10 Jul 2021 12:16:11 GMT</pubDate>
            <description><![CDATA[<h1 id="가상돔">가상돔</h1>
<p>: 메모리에 가상돔을 올려놓고 이전과 이후의 가상돔 비교하여 변경된 부분만 실제 돔에 반영
: 실제돔을 만들 수 있는 리액트 요소 트리</p>
<h4 id="컴포넌트-리액트-요소">컴포넌트 리액트 요소</h4>
<pre><code class="language-jsx">//jsx
function Title({ title, color }) {
    return &lt;style ={{ color}}&gt; {titlee} &lt;/p&gt;
}
const element = &lt;Title title =&quot;안녕하세여&quot; color = &quot;blue&quot; /&gt;
cosole.log(element);

// 리액트 요소
const consoleLogResult = {
    type: Title,
    props: {title: &#39;안녕하세요&#39;, color: &#39;blue&#39; },
};</code></pre>
<p>-&gt; 리액트 요소는 불변객체이기 때문에 변경하려고 하면 에러 발생</p>
<ul>
<li>컴포넌트 추가 : mount</li>
<li>컴포넌트 삭제 : unmount</li>
</ul>
<p>✔️ 컴포넌트에 키 값을 주게 되고 이 키값이 계속 변하게 되면 컴포넌트는 키가 변경 될 때마다 unmount와 mount를 계속 하게 됨.
 =&gt; 조건부 렌더링으로도 비슷한 효과를 볼 수 있음</p>
<p>✔️ 하나의 리액트 요소 트리는 시간에 따라 변화하는 화면의 한 순간을 나타냄</p>
<h3 id="데이터-변경에-의한-화면-업데이트">데이터 변경에 의한 화면 업데이트</h3>
<ol>
<li>렌더 단계 -&gt; 실제 돔에 반영할 변경사항을 파악(가상돔 이용)</li>
<li>커밋 단계 -&gt; 파악된 변경사항을 실제 돔에 반영(실제돔 이용)</li>
</ol>
<p>📍 실행할 jsx 코드</p>
<pre><code class="language-jsx">function Todo({ title, desc }) {
    const [priority, setPriority] = useState(&quot;high&quot;);
    function onClick() {
        setPriority(priority === &#39;high&#39; ? &#39;low&#39; : &#39;high&#39;);
    }
    return (
        &lt;div&gt;
            &lt;Title title={title}/&gt;
            &lt;p&gt;{desc}&lt;/p&gt;
            &lt;p&gt;{priority === &#39;high&#39; ? &quot;우선순위 높음&quot; : &quot;우선순위 낮음&quot;}&lt;/p&gt;
        &lt;/div&gt;
    );
}

const Title = React.memp(({title}) =&gt; {
    return &lt;p style={{color: &#39;blue&#39; }}&gt;{title}&lt;/p&gt;;
});

ReactDom.render(
    &lt;Todo title=&quot;리액트 공부하기&quot; desc=&quot;실전 리액트 프로그래밍을 공부한다&quot; /&gt;,
    document.getElementById(&#39;root&#39;);
);</code></pre>
<p>📍 Todo 컴포넌트로 만들어지는 리액트 요소</p>
<pre><code class="language-jsx">const intialElementTree = {
    type: Todo,
    props: {
        title: &quot;리액트 공부하기&quot;,
        desc: &quot;실전 리액트 프로그래밍을 공부한다&quot;,
    },
    ...
};</code></pre>
<p>📍 Todo컴포넌트 함수의 렌더링 결과</p>
<pre><code class="language-jsx">const elementTree = {
    type: &quot;div&quot;,
    props: {
        children: [
            {
                type: Title,
                props: { title: &#39;리액트 공부하기&#39; },
                //...
            },
            {
                type: &#39;p&#39;,
                props: { children: &#39;실전 리액트 프로그래밍을 공부한다&#39; },
                //...
            },
            {
                type: &#39;p&#39;,
                props: { children: &#39;우선순위 높음&#39; },
                //...
            },
            {
                type: &#39;button&#39;,
                props: {
                    onClick: function () {
                        /* Todo 컴포넌트의 onClick함수 */
                    }
                    children: &#39;우선순위 변경&#39;,
                },
                //...
            }
        ],
    },
//...
};</code></pre>
<p>→ Title 컴포넌트가 존재하기 때문에 이 리액트 요소 트리를 실제 돔으로 만들 수 없음
 ✔️리액트 요소 트리가 실제 돔으로 만들어지기 위해서는 모든 리액트 요소의 타입 속성값이 <strong>문자열</strong>이어야함</p>
<p>📍 Title 컴포넌트 함수의 렌더링 결과</p>
<pre><code class="language-jsx">const elementTree = {
    type: &quot;div&quot;,
    props: {
        children: [
            {
                type: &#39;p&#39;,
                props: { 
                    style: { color: &#39;blue&#39; },
                    children: &#39;리액트 공부하기&#39;,
                },
                //...
            },
            {
                type: &#39;p&#39;,
                props: { children: &#39;실전 리액트 프로그래밍을 공부한다&#39; },
                //...
            },
            {
                type: &#39;p&#39;,
                props: { children: &#39;우선순위 높음&#39; },
                //...
            },
            {
                type: &#39;button&#39;,
                props: {
                    onClick: function () {
                        /* Todo 컴포넌트의 onClick함수 */
                    }
                    children: &#39;우선순위 변경&#39;,
                },
                //...
            }
        ],
    },
//...
};</code></pre>
<p>→ 실제 돔 만들 수 있음</p>
<blockquote>
<p>✔️ 렌더 단계 : 최초의 리액트 요소 트리로부터 가상돔을 만들고 이전 가상돔과 비교하여 실제 돔에 반영할 내용을 결정하는 단계</p>
</blockquote>
<h3 id="상태값-변경-함수에-의해-수행되는-렌더-단계">상태값 변경 함수에 의해 수행되는 렌더 단계</h3>
<ol>
<li>버튼을 클릭하면 priority 상태값이 변경됨 → 렌더 단계 시작</li>
<li>Todo 컴포넌트의 priority 상태값이 변경되면 Todo컴포넌트 함수가 호출됨</li>
<li>리액트 요소 트리 렌더링 결과 재사용</li>
<li>변경된 부분만 업데이트</li>
</ol>
<p>📍 Todo컴포넌트 함수의 렌더링 결과</p>
<pre><code class="language-jsx">const elementTree = {
    type: &quot;div&quot;,
    props: {
        children: [
            {
                type: Title,
                props: { title: &#39;리액트 공부하기&#39; },
                //...
            },
            {
                type: &#39;p&#39;,
                props: { children: &#39;실전 리액트 프로그래밍을 공부한다&#39; },
                //...
            },
            {
                type: &#39;p&#39;,
                props: { children: &#39;우선순위 낮음&#39; },
                //...
            },
            {
                type: &#39;button&#39;,
                props: {
                    onClick: function () {
                        /* Todo 컴포넌트의 onClick함수 */
                    }
                    children: &#39;우선순위 변경&#39;,
                },
                //...
            }
        ],
    },
//...
};</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[자바스크립트/Javascript] 네이티브]]></title>
            <link>https://velog.io/@cool_kim/Javascript-%EB%84%A4%EC%9D%B4%ED%8B%B0%EB%B8%8C</link>
            <guid>https://velog.io/@cool_kim/Javascript-%EB%84%A4%EC%9D%B4%ED%8B%B0%EB%B8%8C</guid>
            <pubDate>Fri, 09 Jul 2021 11:08:51 GMT</pubDate>
            <description><![CDATA[<h1 id="네이티브">네이티브</h1>
<p>: 특정 환경(브라우저 등의 클라이언트 프로그램)에 종속되지 않은 ECMAScript 명세의 내장 객체</p>
<h4 id="네이티브-종류">네이티브 종류</h4>
<ul>
<li>String()</li>
<li>Number()</li>
<li>Boolean()</li>
<li>Array()</li>
<li>Object()</li>
<li>Function()</li>
<li>RegExp()</li>
<li>Date()</li>
<li>Error()</li>
<li>Symbol() - ES6에서 추가됨</li>
</ul>
<pre><code class="language-javascript">var a = new String(&quot;abc&quot;);
typeof a; // &quot;object&quot;
a instance of String; // true
Object.prototype.toString.call(a); //&quot;[object String]&quot; </code></pre>
<h2 id="31-내부-class">3.1 내부 [[Class]]</h2>
<p>: typeof가 &#39;object&#39;인 값에 붙는 내부 프로퍼티</p>
<ul>
<li>이 프로퍼티는 직접 접근할 수 없고 Object.prototype.toString()라는 메서드에 값을 넣어 호출함으로써 존재를 알 수 있음<pre><code class="language-jsx">Object.prototype.toString.call( [1,2,3] ); //&quot;[object String]&quot;
Object.prototype.toString.call( /regex-literal/i ); //&quot;[object RegExp]&quot;</code></pre>
</li>
</ul>
<p>✔️ 내부 [[class]]값이 배열은 &quot;Array&quot;, 정규식은 &quot;RegExp&quot;
✔️ 대부분 내부 [[Class]]는 해당 값과 관련된 내장 네이티브 생성자를 가리키지만, 그렇지 않을 때도 있음
✔️ null과 undefined도 내부 [[Class]]값 있음</p>
<pre><code class="language-jsx">Object.prototype.toString.call( null ); //&quot;[object Null]&quot;
Object.prototype.toString.call( undefined ); //&quot;[object Undefined]&quot;</code></pre>
<p>📍 하지만 문자열, 숫자, 불리언 같은 단순 원시 값은 자동 <strong>&#39;박싱 과정&#39;</strong>을 거쳐 내부 [[Class]] 값 표시</p>
<p><br><br></p>
<h2 id="32-래퍼-박싱하기">3.2 래퍼 박싱하기</h2>
<p>자바스크립트는 원시 값을 알아서 박싱(라핑)하므로 원시 값에 .length나 .toString()으로 접근 할 수 있음.</p>
<p>✔️원시 값을 사용하는게 좋지만 객체 래퍼를 사용해야 한다면 boolean값은 수동 박싱해야함
✔️수동으로 원시 값을 박싱하기 위해서는 Object()함수를 이용</p>
<pre><code class="language-jsx">var a = new Boolean( false ); // false가 아닌 falsy가 됨.
if(!a) {
    console.log( &quot;Oops&quot; );  // 실행 되지 않음
}

var a = &quot;abc&quot;;
var b = new String( a );
var c = Object( a );

typeof a; //&quot;string&quot;
typeof b; //&quot;object&quot;
typeof c; //&quot;object&quot;

b instanceof String; //true
c instanceof String; //true

//수동 박싱
Object.prototype.toString.call( b ); //&quot;[object String]&quot;
Object.prototype.toString.call( c ); //&quot;[object String]&quot;</code></pre>
<p><br><br></p>
<h2 id="33-언박싱">3.3 언박싱</h2>
<p>객체 래퍼 원시 값은 valueOf() 메소드로 추출</p>
<ul>
<li>암시적인 언박싱 일어남</li>
</ul>
<p><br><br></p>
<h2 id="34-네이티브-나는-생성자다">3.4 네이티브, 나는 생성자다</h2>
<h3 id="array">Array()</h3>
<p>: 배열의 크기를 미리 정함</p>
<pre><code class="language-jsx">var a = new Array(3);
a.length; //3
a; // [ undefined x 3 ]</code></pre>
<p>→ 슬롯 자체가 존재하지 않아 배열 슬롯에 undefined값을 밀어 넣은 것</p>
<pre><code class="language-jsx">var a = new Array(3);
var b = [ undefined, undefined, undefined ];
var c = [];
c.length = 3;

a; //[ undefined x 3 ]
b; //[ undefined, undefined, undefined ]
c; //[ undefined x 3 ]</code></pre>
<p>🙁 map() : a에 슬롯이 없기 때문에 함수가 순회할 원소가 없다.
🙁 join() : 슬롯이 있다는 가정하에 length만큼 루프를 반목한다.</p>
<p>📍 빈 슬롯 말고 진짜 undefined 값 원소로 채워진 배열 생성하기</p>
<p><code>var a = Array.apply( null, { length:3 } )</code></p>
<p>📌 apply()는 모든 함수에서 사용 가능, 첫번째 인자는 객체 바인딩 두번째 인자는 인자의 배열로 이안에 포함된 원소들이 펼쳐져 함수의 인자로 전달됨</p>
<ol>
<li>0에서 length 직전까지 루프 순회 </li>
<li>인덱스 별로 객체에서 키를 가져옴</li>
<li>함수 내부에서 배열 객체 인자를 arr라고 명명한다면 프로퍼티는 arr[0], arr[1], arr[2]로 접근</li>
<li>세 프로퍼티 모두 { length : 3 } 객체에는 존재하지 않기 때문에 모두 undefined를 반환</li>
<li>결국 빈슬롯이 아닌, undefined로 채워진 배열 탄생</li>
</ol>
<br>

<h3 id="object-function-and-regexp">Object(), Function(), and RegExp()</h3>
<p>: 어떤 분명한 의도가 아니라면 사용하지 않는 편이 좋음</p>
<ul>
<li>Object() : 사실상 사용할 일이 없음, 리터럴 형태로 한 번에 여러 프로퍼티를 지정할 수 있는데 굳이 한 번에 하나씩 일일이 프로퍼티를 지정하는 벙법으로 돌아갈 필요 없음</li>
<li>Function() : 함수의 인자나 내용을 동적으로 정의해야 하는 매우 드문 경우에 한해 유용</li>
<li>RegExp() : 정규 표현식 패텅을 동적으로 정의할 경우 의미 있는 유틸리티</li>
</ul>
<br>

<h3 id="date-and-error">Date() and Error()</h3>
<p>: 리터럴 형식이 없기 떄문에 다른 네이티브에 비해 유용</p>
<ol>
<li><p>Date()</p>
<ul>
<li>new Date()로 생성</li>
<li>날짜/시각을 인자로 받음</li>
<li>유닉스 타임스탬프 값을 얻는 용도로 가장 많이 쓰임</li>
<li>data객체의 인스턴스로부터 getTime()을 호출 → Data.now() 가 더 쉬움</li>
</ul>
</li>
<li><p>Error()</p>
<ul>
<li>앞에 new가 있든 없든 결과가 같음</li>
<li>현재의 실행 스택 콘텍스트(Execution Stack Context)를 포착하여 객체에 담는 용도</li>
<li>실행 스택 콘택스트는 함수 호출 스택, error 객체가 만들어진 줄 번호 등 디버깅에 도움 될 만한 정보들을 담고 있음</li>
<li>error객체는 보통 throw 연산자와 함께 쓰임</li>
</ul>
</li>
</ol>
<br>

<h3 id="symbol">Symbol()</h3>
<p>: ES6에서 처음 선보인, 새로운 원시 값 타입
: 충돌 염려 없이 객체 프로퍼티로 사용 가능한, 특별한 &#39;유일 값&#39;</p>
<p>📍 심벌 정의하기</p>
<pre><code class="language-jsx">var mysym = Symbol( &quot;my own symbol&quot; );
mysym; //Symbol(my own symbol);
mysym.toString(); //&quot;Symbol(my own symbol)&quot;
typeof mysym; //&quot;symbol&quot;

vat a = {};
a[mysym] = &quot;foobar&quot;;

object.getOwnPropertySymbols( a ); //[ Symbol(my own symbol) ]</code></pre>
<ul>
<li>private 속성은 아니지만 본래의 사용 목적에 맞게 대부분 전용 혹은 특별한 속성으로 사용</li>
</ul>
<br>

<h3 id="네이티브-프로토타입">네이티브 프로토타입</h3>
<p>: 해당 객체의 하위 타입별로 고유한 로직이 담겨 있음</p>
<ul>
<li>String#indexOf() : 문자열에서 특정 문자의 위치를 검색</li>
<li>Stirng#charAt() : 문자열에서 특정 위치의 문자를 반환</li>
<li>Stirng#substr(), String#substring(), String#slice() : 문자열의 일부를 새로운 문자열로 추출</li>
<li>Stirng#tpUpperCase(), String#toLowerCase() : 대문자/소문자로 변환된 새로운 문자열 생성</li>
<li>String#trim() : 앞/뒤의 공란이 제거된 새로운 문자열 생성</li>
</ul>
<p>✔️ 프로토타입 위임 덕분에 모든 문자열이 이 메소드를 같이 쓸 수 있음</p>
<ul>
<li>Function.prototype : 함수</li>
<li>RegExp.prototype : 정규표현식</li>
<li>Array.prototype : 배열</li>
</ul>
<pre><code class="language-jsx">typeof Function.prototype; //&quot;function&quot;
Function.prototype(); //빈 함수

RegExp.prototype.toStirng(); // 빈 정규표현식
&quot;abc&quot;.match( RegExp.prototype ); // [&quot;&quot;]

Array.isArray( Array.prototype ); //true
Array.prototype.push( 1,2,3 ); // 3
Arrat.prototype; // [1,2,3]

Array.prototype.length = 0; // 배열 비우기</code></pre>
<p>📌 프로토타입은 모두 디폴트 값이다</p>
<ul>
<li>프로토타입으로 디폴트 값을 세팅하면 단 한 번만 생성된다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[React] 리액트 상태값, 속성값, 반환값]]></title>
            <link>https://velog.io/@cool_kim/React-%EB%A6%AC%EC%95%A1%ED%8A%B8-%EC%83%81%ED%83%9C%EA%B0%92-%EC%86%8D%EC%84%B1%EA%B0%92-%EB%B0%98%ED%99%98%EA%B0%92</link>
            <guid>https://velog.io/@cool_kim/React-%EB%A6%AC%EC%95%A1%ED%8A%B8-%EC%83%81%ED%83%9C%EA%B0%92-%EC%86%8D%EC%84%B1%EA%B0%92-%EB%B0%98%ED%99%98%EA%B0%92</guid>
            <pubDate>Wed, 07 Jul 2021 17:26:39 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>무작위로 필요한 문제만 검색해서 개발했던 리액트였기 때문에 기본기를 다지고자 개념부터 차근차근 정리하면서 공부하는 포스팅입니다😄</p>
</blockquote>
<p>같은 동작을 하는 코드를 HTML과 js로 짰을 때와 리액트로 짰을 때를 비교해 봅시다.</p>
<ul>
<li><p>HTML + js</p>
<pre><code class="language-html">&lt;html&gt;
  &lt;body&gt;
      &lt;div class =&quot;todo&quot;&gt;
          &lt;h3&gt;할 일 목록&lt;/h3&gt;
          &lt;ul class=&quot;list&gt;&lt;/ul&gt;
          &lt;input class=&quot;desc&quot; type=&quot;text&quot; /&gt;
          &lt;button onclick=&quot;onAdd()&quot;&gt;추가&lt;/button&gt;
          &lt;button onclick=&quot;onSaveToServer()&quot;&gt;서버에 저장&lt;/button&gt;
      &lt;/div&gt;
      &lt;script&gt;
          let currentId = 1;
          const todoList = [];
          function onAdd() {
              const descEl = document.querySelector(&#39;.todo .desc&#39;);
              const todo = { id : currentId++, desc: descEl.value };
              todoList.push(todo);
              const listEl = document.querySelector(&#39;.todo .list&#39;);
              const todoEl = makeTodoElement(todo);
              list.appendChild(todoEl);
          }
          /* 생략 */
      &lt;/script&gt;
   &lt;/body&gt;
&lt;/html&gt;  </code></pre>
</li>
<li><p>React.js</p>
<pre><code class="language-javascript">import React, { useState } from &#39;react&#39;;
</code></pre>
</li>
</ul>
<p>export default function App() {
    const [todoList, setTodoList] = useState([]);
    const [currentId, setCurrentId] = useState(1);
    const [desc, setDesc] = useState(&#39;&#39;);
    function onAdd() {
        const todo = { id: currentId, desc };
        setCurrentId(currentId + 1);
        setTodoList([...todoList, todo]);
    }
    function onDelete(e) {
        const id = Number(e.target.dataset.id);
        const newTodoList = todoList.filter(todo =&gt; todo.id !== id);
        setTodoList(newTodoList);
    }
    function onSaveToServer() {}
    return (
        <div>
            <h3>할 일 목록</h3>
            <ul>
                {todoList.map(todo =&gt; {
                    <li key={todo.id}>
                        <span>{todo.id}</span>
                        <button data-id = {todo.id} onClick={onDelete}>
                            삭제
                        </button>
                    </li>
                ))}
            </ul>
            &lt;input type=&quot;text&quot; value={desc} onChange={e =&gt; setDesc(e.target.value)} /&gt;
            <button onClick={onAdd}>추가</button>
            <button onClick={onSaveToServer}>서버에 저장</button>
        </div>
    );
}</p>
<pre><code>html은 **명령형 프로그래밍** -&gt; dom api 사용해야 요소 접근 할 수 있음
리액트는 **선언형 프로그래밍** -&gt; 가상 돔 사용

&lt;br&gt;&lt;br&gt;

### useState
- 컴포넌트에 상태값을 추가할 수 있음
- 매개변수는 상태값의 초기값을 의미
- 배열을 반환
`const [todoList, setTodoList] = useState([]);`
=&gt; 배열 비구조화 문법


&lt;br&gt;&lt;br&gt;

### 리액트의 속성값 그리고 상태값
1. 상태값으로 관리
: 불변 변수 아님, 하지만 불변 변수로 관리 하는 것이 좋음
    - 불변 변수로 관리하면 코드의 복잡도가 낮아짐
        ** **전개 연산자**를 사용하여 불변변수로 사용할 수 있음
        `setCount({ ...count, value: count.value + 1 });`
```javascript
const [color, setColor] = useState(&quot;red&quot;);
function onClick() {
    setColor(&#39;blue&quot;);
}
return (
    &lt;button style={{ backgroundColor: color }} onclick = {onClick}&gt;좋아요&lt;/button&gt;
);</code></pre><p>: 컴포넌트 내에 변경 가능한 데이터 저장소로 가변값임
: 같은 컴포넌트가 여러개 쓰이더라도 상태값을 위한 자신만의 메모리가 있어 각자의 상태값을 유지함</p>
<ol start="2">
<li>속성값으로 관리
: 불변변수 (값을 변경하려 하면 에러 발생) </li>
</ol>
<p>Title.js</p>
<pre><code class="language-javascript">export default function Title({ tite }) {
    return &lt;p&gt;{title}&lt;/p&gt;
}</code></pre>
<p>Counter.js</p>
<pre><code class="language-javascript">export default function Counter() {
    const [count, setCount] = useState(0);
    function onClick() {
        setCount(count + 1);
    }
    return (
        &lt;div&gt;
        &lt;Title title={`현재 카운트 : ${count}` /&gt;
        &lt;button onClick={onClick}&gt;증가&lt;/button&gt;
        &lt;/div&gt;
    );
}</code></pre>
<p>카운터 컴포넌트에서 타이틀 컴포넌트를 사용,
부모컴포넌트가 렌더링 될 때마다 자식 컴포넌트가 같이 렌더링 됨.</p>
<h4 id="reactmemo">React.memo</h4>
<p>: 속성값이 변경 될 때만 컴포넌트가 렌더링 되게 하기 위한 라이브러리
: 자식 컴포넌트의 속성값에 변경이 있을 경우에만 렌더링 됨</p>
<p>Title.js</p>
<pre><code class="language-javascript">function Title({ tite }) {
    return &lt;p&gt;{title}&lt;/p&gt;
}
export default React.memo(Title);</code></pre>
<p>같은 컴포넌트가 여러개 쓰이더라도 상태값을 위한 자신만의 메모리가 있어 각자의 상태값을 유지함
<br><br></p>
<p>📍 리액트는 상태값 변경 유무를 이전값과의 단순 비교로 하는데 객체의 참조값은 변하지 않고 단순히 내부의 속성값만 변경이 된 상태라면 리액트 입장에서는 값이 변경되지 않았다고 판단함. 아래 코드는 화면이 변하지 않음</p>
<pre><code class="language-javascript">export default function Counter() {
    const [count, setCount] = useState({ value : 0 });
    function onClick() {
        count.value += 1; //여기서 값 직접 수정
        setCount(count);
    }
    return (
        &lt;div&gt;
            &lt;Title title={`현재 카운트 : ${count}` /&gt;
            &lt;button onClick={onClick}&gt;증가&lt;/button&gt;
        &lt;/div&gt;
    );
}</code></pre>
<p><br><br></p>
<h3 id="반환값">반환값</h3>
<p>리액트는 컴포넌트 함수의 반환값으로 다음과 같은 값을 반환 할 수 있다.</p>
<ul>
<li>html 요소</li>
<li>문자열</li>
<li>컴포넌트</li>
<li>숫자</li>
<li>배열<ul>
<li>리액트 요소가 <strong>key</strong>를 가지고 있어야 함 (가상돔에서 연산을 효율적으로 할 수 있음)</li>
</ul>
</li>
<li>리액트 portal<ul>
<li>html에서 root엘리먼트 말고 다른 멀리 떨어진 엘리먼트에 렌더링 하고 싶을 때 사용(모달 코딩을 위해 많이 사용됨)</li>
</ul>
</li>
</ul>
<h4 id="fragment">Fragment</h4>
<p>: &lt;&gt;&lt;/&gt;태그
✔ 키를 입력하지 않아도 에러가 나지 않음
✔ 여러개의 요소를 반환할 때 유용하게 사용됨
✔ 실제 돔에는 반영되지 않고 에러 나지 않고 반환할 수 있음
✔ {null}, {false} 조건부 출력 때 유용하게 사용</p>
<h4 id="조건부-렌더링">조건부 렌더링</h4>
<p><code>{ count.value === 0 &amp;&amp; &lt;Title title={</code>현재 카운트: ${count.value}<code>/&gt;}</code></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[자바스크립트/Javascript] 타입, 값]]></title>
            <link>https://velog.io/@cool_kim/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8Javascript-%ED%83%80%EC%9E%85-%EA%B0%92</link>
            <guid>https://velog.io/@cool_kim/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8Javascript-%ED%83%80%EC%9E%85-%EA%B0%92</guid>
            <pubDate>Tue, 06 Jul 2021 12:35:37 GMT</pubDate>
            <description><![CDATA[<h2 id="chapter1-타입">Chapter1 타입</h2>
<blockquote>
<p>동적언어인 자바스크립트는 타입의 개념이 없다고 생각할 수 있지만 존재한다.</p>
</blockquote>
<h3 id="12-내장-타입">1.2 내장 타입</h3>
<p>✔ 자바스크립트의 내장 타입(7가지)</p>
<ul>
<li>null</li>
<li>undefined</li>
<li>boolean</li>
<li>number</li>
<li>string</li>
<li>object</li>
<li>symbol</li>
</ul>
<p>📍 typeof 연산자를 통해 값 타입 확인 가능</p>
<pre><code class="language-javascript">typeof undefined === &quot;undefined&quot;; // true
typeof true === &quot;boolean&quot;; // true
typeof 42 === &quot;number&quot;; // true
typeof &quot;42&quot; === &quot;string&quot;; // true
typeof { life : 42 } === &quot;object&quot;; // true
typeof Symbol() === &quot;symbol&quot;; // true
typeof function a(){ /* ... */ } === &quot;function&quot;; // true
typeof [1, 2, 3] === &quot;object&quot;; //true
typeof null === &quot;object&quot;; // true</code></pre>
<p>✔ null은 typeof로 반환했을 때 &quot;null&quot;을 반환하지 않는다.</p>
<p>📍 null값을 정확히 확인하기 위한 코드</p>
<pre><code class="language-javascript">var a = null;
(!a &amp;&amp; typeof a === &quot;object&quot;); // true</code></pre>
<p></br></br></p>
<h3 id="13-값은-타입을-가진다">1.3 값은 타입을 가진다</h3>
<p>✔ 값은 타입이 있지만, 변수에는 따로 타입이 없다.
<code>42는 내장된 숫자 타입, &quot;42&quot;는 문자열 타입이지만 숫자 42에서 생성 가능</code></p>
<pre><code class="language-javascript">var a = 42;
typeof a; // &quot;number&quot;

a = true;
typeof a; // &quot;boolean&quot;

typeof typeof 42; // &quot;string&quot;</code></pre>
</br>

<p>✔ 값이 없는 변수의 값은 undefined, typeof의 결과는 &quot;undefined&quot;
<em>자바스크립트에서 undefined와 undeclared는 완전히 다른 개념이다.</em></p>
<ul>
<li>undefined : 접근 가능한 범위에 변수가 서언되어 있으나 아무 값도 할당되지 않은 상태</li>
<li>undeclared : 접근 가능한 범위에 변수 자체가 선언조차 되지 않은 상태</li>
</ul>
<p><span style="color:red">하지만,</span> typeof의 결과는 두개 모두 <strong>&quot;undefined&quot;</strong>이다.
 --&gt; typeof의 안전가드(safety guard) 때문
 </br></p>
<p> ✔ typeof의 안전 가드 없이 전역 변수를 체크하는 방법
<span style="color:gray">DEBUG 변수가 최상위 전역 스코프에 true로 선언되어있다.</span></br></p>
<ol>
<li><p><code>if( typeof DEBUG !== &quot;undefined&quot; )</code> 조건문 사용</p>
</li>
<li><p><code>if( window.DEBUG )</code> 조건문 사용</p>
<p>두 가지가 있지만 window 객체를 통한 전역 변수 참조는 삼가는 것이 좋음.</p>
</br>
✔ 오픈소스 코드를 자신의 코드에 붙여야 할때 오픈소스 코트에 특정 변숫값이 정의되어 있는지 확인해야할 때<br><br>

<p>첫번째 방법</p>
<pre><code class="language-javascript">function doSomethingCool() {
var helper = 
    (typeof FeatureXYZ !== &quot;undefined&quot;) ?
    FeatureXYZ :
    function() { /* 기본 XYZ 기능 */ };

var val = helper();
}</code></pre>
</li>
</ol>
<p>두번째 방법</p>
<pre><code class="language-javascript">//즉시 호출 함수 표현식
(function() {
    function FeatureXYZ() { /* 나의 XYZ 기능 */ }

    function doSomethindCool() {
        var helper = 
            (typeof FeatureXYZ !== &quot;undefined&quot;) ?
            FeatureXYZ :
            function() { /* 기본 XYZ 기능 */ };
        var val = helper();
       }
    doSomethingCool();
})();</code></pre>
<p>세번째 방법 (의존성 주입(Dependency Injection))</p>
<pre><code class="language-javascript">function doSomethingCool(FeatureXYZ) {
    var helper = FeatureXYZ ||
            function() { /* 기본 XYZ 기능 */ };
    var val = helper();</code></pre>
<p><br><br><br></p>
<h2 id="chapter2-값">Chapter2 값</h2>
<h3 id="21-배열">2.1 배열</h3>
<blockquote>
<p>자바스크립트의 배열은 타입이 다른 문자열, 숫자, 객체, 심지어 다른 배열이나 어떤 타입의 값을 함께 담을 수 있다.</p>
</blockquote>
<p><code>var a = [ 1, &quot;2&quot;, [3]]</code></p>
<p>✔ 배열의 크기는 미리 정하지 않고 선언 가능, 원하는 값 추가 가능</p>
<p>📍 구멍난 배열</p>
<pre><code class="language-javascript">var a = [];

a[0] = 1;
a[2] = [3];

a[1]; // undefined

a.length; // 3</code></pre>
<p>위 코드에서 a[1]은 undefined이긴 하지만 a[1] = undefined로 세팅한것과 똑같지는 않다.</p>
<ol>
<li>배열 인텍스는 기본적으로 숫자이지만, 키/프로퍼티 문자열을 추가 할 수 있다. 
<code>a[&quot;foobar&quot;] = 2;</code></li>
<li>하지만 배열의 길이는 증가하지 않는다.</li>
<li>키로 넣은 문자열 값이 표준 10진수 숫자로 들어가게 되면 숫자 키를 사용한 것과 같이 된다.
<code>a[&quot;13&quot;] = 42; a.length; // 14</code></li>
</ol>
<p>🔸 배열 원소의 인덱스는 확실히 숫자만 사용하는 것이 좋다.
<br></p>
<p>✔ 유사 배열 값을 진짜 배열로 바꾸고 싶을 때</p>
<ul>
<li>배열 유틸리티 함수(indexOf(), concat(), forEach())를 사용하여 해결</li>
<li>slice() 함수의 기능 차용 -&gt; ES6부터는 Array.from() 사용<pre><code class="language-javascript">function foo() {
  var arr = Array.prototype.slice.call( arguments );
  arr.push( &quot;bam&quot; );
  console.log( arr );
}
</code></pre>
</li>
</ul>
<p>foo( &quot;bar&quot;, &quot;baz&quot; ); // [&quot;bar&quot;, &quot;baz&quot;, &quot;bam&quot;]</p>
<pre><code>&lt;br&gt;&lt;br&gt;

### 2.2 문자열
&gt; 문자의 배열이라고 생각하지만 실제로는 생김새만 비슷할 뿐 문자 배열과 같지 않다.(유사배열)

📍 문자열은 불변 값, 배열은 가변 값이다

```javascript
var a = &quot;foo&quot;;
var b = [&quot;f&quot;, &quot;o&quot;, &quot;o&quot;];

a.length; //3
b.length; //3

a.indexOf(&quot;o&quot;); //1
b.indexOf(&quot;o&quot;); //1

var c = a.concat(&quot;bar&quot;); //&quot;foobar&quot;
var d = b.concat([&quot;b&quot;, &quot;a&quot;, &quot;r&quot;]); //[&quot;f&quot;, &quot;o&quot;, &quot;o&quot;, &quot;b&quot;, &quot;a&quot;, &quot;r&quot;]

a === c; //false
b === d; //false

a; //&quot;foo&quot;
b; //[&quot;f&quot;, &quot;o&quot;, &quot;o&quot;]</code></pre><p>배열에서는 b[1]처럼 접근하는 것이 맞지만, 문자열은 <code>a.charAt(1);</code>로 접근해야 맞다.</p>
<p>📍 문자열은 불변 값이기 떄문에 내용을 바로 변경하지 않고 새로운 문자열을 생성한 후 반환하한다.</p>
<pre><code class="language-javascript">c = a.toUpperCase();
a === c; //false
a; // &quot;foo&quot;
c; // &quot;FOO&quot;</code></pre>
<p>✔ 대부분의 배열 메소드는 문자열에 쓸 수 없지만 문자열에 대해 불변 배열 메소드를 빌려 쓸 수 있다.
<code>var c = Array.prototype.join.call(a, &#39;-&#39;);</code></p>
<p>✔ reverse()함수는 배열의 가변 메소드이기 때문에 문자열에서 빌려 쓸 수 없다. 해결책은 다음과 같다.
<code>var c = a.split(&quot;&quot;).reverse().join(&quot;&quot;);</code></p>
<p><br><br></p>
<h3 id="23-숫자">2.3 숫자</h3>
<p>✔ 0.1 + 0.2 === 0.3; //false
 -&gt; 이러한 미세한 오차를 &#39;머신 입실론&#39;이라고 한다.
 ES6에는 Number.EPSILON이 미리 정의 되어 있다.
 이전 브라우저 폴리필은 다음과 같다</p>
<pre><code class="language-javascript">if(!Number.EPSILON) {
    Number.EPSILON = Math.pow(2,-52);
}

function numbersCloseEnoughToEqual( n1, n2 ) {
    return Math.abs( n1 - n2 ) &lt; Number.EPISLON;
}

var a = 0.1 + 0.2;
var b = 0.3;

numbersCloseEnoughToEqual( a, b ); //true</code></pre>
<p>✔ 정수인지 확인
ES6부터는 Number.isInteger()로 확인 가능
이전 브라우저 폴리필</p>
<pre><code class="language-javascript">if(!Number.isInteger) {
    Number.isInteger = function(num) {
        return typeof num == &quot;number&quot; &amp;&amp; num % 1 == 0;
    };
}</code></pre>
<p><br><br></p>
<h3 id="24-특수-값">2.4 특수 값</h3>
<p>✔ 값 아닌 값</p>
<ul>
<li>undefined타입의 값은 undefined 뿐</li>
<li>null타입의 값은 null 뿐<br></li>
<li>null은 식별자가 아닌 특별한 키워드로 null변수에 뭔가 할당 할 수 없음</li>
<li>undefined는 식별자로 쓸 수 있음</li>
</ul>
<p>✔ undefined</p>
<ul>
<li>느슨한 모드에서는 전역 스코프에서 undefined란 식별자에 값 할당 가능</li>
<li>모드에 상관없이 undefined란 이름을 가진 지역 변수 생성 가능</li>
</ul>
<p>✔ void</p>
<ul>
<li>어떤 값이든 무효로 만들어 항상 결괏값을 undefined로 만듬</li>
<li>기존 값은 건드리지 않고 연산 후 값은 복구할 수 없다.</li>
</ul>
<p><br><br></p>
<h3 id="25-특수-숫자">2.5 특수 숫자</h3>
<p>✔ NaN(Not a Number)</p>
<ul>
<li>숫자 아님 보다는 유효하지 않은 숫자, 실패한 숫자, 몹쓸 숫자라고 하는게 정확</li>
</ul>
<pre><code class="language-javascript">var a = 2 / &quot;foo&quot;; //NaN
typeof a === &quot;number&quot; //true</code></pre>
<p>???????숫자 아님의 typeof는 숫자다???????
-&gt; NaN은 경계 값(Sentinel Value)의 일종으로 숫자 집합 내에서 특별한 종류의 에러 상황을 나타낸다.
  NaN은 다른 어떤 NaN과도 동등하지 않다. ∴ NaN !== NaN</p>
<p>📍 NaN여부 확인하기</p>
<ul>
<li><p>isNaN()함수</p>
<pre><code class="language-javascript">var a = 2 / &quot;foo&quot;;
isNaN(a); //true</code></pre>
<p>isNaN()함수는 인자 값이 숫자인지 여부를 평가하는 기능이 전부</p>
</li>
<li><p>Number.isNaN()함수</p>
</li>
<li><blockquote>
<p>ES6이전 폴리필(1)</p>
</blockquote>
<pre><code class="language-javascript">if(!Number.isNaN) {
   Number.isNaN = function(n) {
       return (
           typeof n === &quot;number&quot; &amp;&amp;
           window.isNaN(n)
       );
   };
}
</code></pre>
</li>
</ul>
<p>var a = 2 / &quot;foo&quot;;
var b = &quot;foo&quot;;</p>
<p>Number.isNaN(a); //true
Number.isNaN(b); //false</p>
<pre><code>-&gt; ES6이전 폴리필(2)
```javascript
if(!Number.isNaN) {
    Number.isNaN = function(n) {
        return n !== n;
    };
}</code></pre><br>

<p>✔ 무한대</p>
<ul>
<li>자바스크립트는 0으로 나누기 연산이 잘되어 있어 <code>var a= 1 / 0;</code>연산을 해도 에러 없이 Infinity값이 나옴</li>
<li>무한을 무한으로 나누면 NaN값.</li>
</ul>
<br>

<p>✔ 0(영)</p>
<ul>
<li>음의 영(-0)</li>
<li>양의 영(+0)</li>
</ul>
<p>ES6부터는 두 값이 절대적으로 동등한지 확인하는 새로운 유틸리티 Object.is()를 지원
-&gt; 특이한 동등비교에 사용</p>
<pre><code class="language-javascript">var a = 2 / &quot;foo&quot;;
var b = -3 * 0;

Object.is( a, NaN ); //true
Object.is( b, -0 ); //true
Object.is( b, 0 ); //false</code></pre>
<p>폴리필</p>
<pre><code class="language-javascript">if(!Object.is) {
    Object.if = function(v1, v2) {
        //&#39;-0&#39; 테스트
        if( v1 === 0 &amp;&amp; v2 === 0 ) {
            return 1 / v1 === 1 / v2;
        }
        //&#39;NaN&#39; 테스트
        if( v1 !== v1 ) {
            return v2 !== v2;
        }
        //기타
        return v1 === v2;
    };
}</code></pre>
<p><br><br></p>
<h3 id="26-값-vs-레퍼런스">2.6 값 vs 레퍼런스</h3>
<ul>
<li>null, undefined, string, number, boolean, symbol과 같은 단순 값은 항상 <strong>값-복사</strong> 방식</li>
<li>객체, 함수 등 합성 값은 항상 <strong>레퍼런스-복사</strong> 방식</li>
</ul>
<ol>
<li>배열</li>
</ol>
<pre><code class="language-javascript">var a = [1,2,3];
var b = a;

a; //[1,2,3]
b; //[1,2,3]

b = [4,5,6];

a; //[1,2,3]
b; //[4,5,6]</code></pre>
<ol start="2">
<li><p>함수 인자</p>
<pre><code class="language-javascript">function foo(x) {
 x.push( 4 );
 x; //[1,2,3,4]

 x = [4,5,6];
 x.push( 7 );
 x; //[4,5,6,7]
}
</code></pre>
</li>
</ol>
<p>var a = [1,2,3];
foo(a);</p>
<p>a; //[1,2,3,4]</p>
<pre><code>&lt;span style=&quot;color:red&quot;&gt;하지만,&lt;/span&gt; `x = [4,5,6]; x.push( 7 );` 대신 `x.length = 0; x.push(4,5,6,7);`으로 코드를 코치면 a는 [4,5,6,7]이 된다.
-&gt; `x.length = 0; x.push(4,5,6,7);`은 새배열을 생성하는 코드가 아니라 이미 두 변수가 공유한 배열을 변겅하는 코드기 때문.

✔ 인자없이 slice()를 호출하면 전혀 새로운 배열의 사본을 만든다. 그렇게 복사한 사본만을 가리키는 레퍼런스를 전달하니 foo()는 a의 내용을 건드릴 수 없다.

- 스칼라 원시 값을 레퍼런스처럼 바뀐 값이 바로바로 반영되도록 넘기기 위해서는 원시 값을 다른 합성 값(객체, 배열)으로 감싸야한다.
- 스칼라 원시 값을 Number 객체 래퍼로 감싸면 Number 객체의 레퍼런스 사본이 함수에 전달되는 것은 맞지만 자동으로 공유된 원시 값을 변경하지 못한다.
 -&gt; Number객체에서 자동 언박싱되므로 바깥의 원시값은 변경되지 않은 불변의 원본 Number 객체를 참조한다.


</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[백준] #1463 1로 만들기]]></title>
            <link>https://velog.io/@cool_kim/%EB%B0%B1%EC%A4%80-1463-1%EB%A1%9C-%EB%A7%8C%EB%93%A4%EA%B8%B0</link>
            <guid>https://velog.io/@cool_kim/%EB%B0%B1%EC%A4%80-1463-1%EB%A1%9C-%EB%A7%8C%EB%93%A4%EA%B8%B0</guid>
            <pubDate>Sun, 25 Apr 2021 12:43:25 GMT</pubDate>
            <description><![CDATA[<p><img src="https://images.velog.io/images/cool_kim/post/f2211d8f-9535-41b5-8d1e-43922052cf92/image.png" alt="">
<strong>BOJ #1463</strong>
<a href="https://www.acmicpc.net/problem/1463">https://www.acmicpc.net/problem/1463</a></p>
<h2 id="📃-문제">📃 문제</h2>
<p>정수 X에 사용할 수 있는 연산은 다음과 같이 세 가지 이다.</p>
<ol>
<li>X가 3으로 나누어 떨어지면, 3으로 나눈다.</li>
<li>X가 2로 나누어 떨어지면, 2로 나눈다.</li>
<li>1을 뺀다.
정수 N이 주어졌을 때, 위와 같은 연산 세 개를 적절히 사용해서 1을 만들려고 한다. 연산을 사용하는 횟수의 최솟값을 출력하시오.</li>
</ol>
<h2 id="📥-입력">📥 입력</h2>
<p>첫째 줄에 1보다 크거나 같고, 106보다 작거나 같은 정수 N이 주어진다.</p>
<h2 id="📤-출력">📤 출력</h2>
<p>첫째 줄에 연산을 하는 횟수의 최솟값을 출력한다.</p>
<h2 id="💡-접근">💡 접근</h2>
<li>DP를 사용하면 쉽게 풀 수 있을 거라고 생각</li>
<li>큰 수 부터 나눠주면 될거라고 생각했는데 그렇지 않았음..</li>
    <ul style="list-style-type: circle;">
    <li>10/2 -> 5/2 -> 4/2 -> 2-1 = 1</li>
      <li>10-1 -> 9/3 -> 3/3 = 1</li>
      </ul>


<h2 id="📍-코드">📍 코드</h2>
<pre><code>import java.io.*;

public class B1463 {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int n = Integer.parseInt(br.readLine());
        int d[] = new int[n+1];
        d[0] = 0;
        d[1] = 0;
        for (int i = 2; i &lt;= n; i++){
            d[i] = d[i-1] + 1;
            if (i % 2 == 0) d[i] = Math.min(d[i], d[i/2] + 1);
            if (i % 3 == 0) d[i] = Math.min(d[i], d[i/3] + 1);
        }
        System.out.println(d[n]);
        br.close();

     }
}</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[백준] #10816 숫자 카드2]]></title>
            <link>https://velog.io/@cool_kim/%EB%B0%B1%EC%A4%80-10816-%EC%88%AB%EC%9E%90-%EC%B9%B4%EB%93%9C2</link>
            <guid>https://velog.io/@cool_kim/%EB%B0%B1%EC%A4%80-10816-%EC%88%AB%EC%9E%90-%EC%B9%B4%EB%93%9C2</guid>
            <pubDate>Tue, 20 Apr 2021 15:51:07 GMT</pubDate>
            <description><![CDATA[<p><img src="https://images.velog.io/images/cool_kim/post/3344eeb0-ec83-4b48-a28a-c77622b1fb49/image.png" alt="">
<strong>BOJ #10816</strong>
<a href="https://www.acmicpc.net/problem/10816">https://www.acmicpc.net/problem/10816</a></p>
<h2 id="📃-문제">📃 문제</h2>
<p>숫자 카드는 정수 하나가 적혀져 있는 카드이다. 상근이는 숫자 카드 N개를 가지고 있다. 정수 M개가 주어졌을 때, 이 수가 적혀있는 숫자 카드를 상근이가 몇 개 가지고 있는지 구하는 프로그램을 작성하시오.</p>
<h2 id="📥-입력">📥 입력</h2>
<p>첫째 줄에 상근이가 가지고 있는 숫자 카드의 개수 N(1 ≤ N ≤ 500,000)이 주어진다. 둘째 줄에는 숫자 카드에 적혀있는 정수가 주어진다. 숫자 카드에 적혀있는 수는 -10,000,000보다 크거나 같고, 10,000,000보다 작거나 같다.</p>
<p>셋째 줄에는 M(1 ≤ M ≤ 500,000)이 주어진다. 넷째 줄에는 상근이가 몇 개 가지고 있는 숫자 카드인지 구해야 할 M개의 정수가 주어지며, 이 수는 공백으로 구분되어져 있다. 이 수도 -10,000,000보다 크거나 같고, 10,000,000보다 작거나 같다.</p>
<h2 id="📤-출력">📤 출력</h2>
<p>첫째 줄에 입력으로 주어진 M개의 수에 대해서, 각 수가 적힌 숫자 카드를 상근이가 몇 개 가지고 있는지를 공백으로 구분해 출력한다.</p>
<h2 id="💡-접근">💡 접근</h2>
<li>어찌됐건 배열에서 같은 수 찾는 것이니까 이분탐색</li>
<li>문제는 같은 수가 있다는 것.</li>
    <ul style="list-style-type: circle;">
    <li>오름차순 정렬하면 일단 같은 수는 모여있을 것이기 때문에 시작 인덱스 값과 끝 인덱스 값을 구해서 서로 빼주면 같은 수가 나올 것</li>
      </ul>

<p>그렇게 아래와 같이 코드를 짰다.</p>
<pre><code>import java.util.*;

public class B10816 {
    public static void main(String args[]) throws Exception {
        Scanner sc = new Scanner(System.in);

        int n = sc.nextInt();
        int a[] = new int[n];
        for(int i=0; i&lt;n; i++) a[i] = sc.nextInt();

        Arrays.sort(a);

        int m = sc.nextInt();
        int b[] = new int[m];
        int result[] = new int[m];
        for(int i=0; i&lt;m; i++){ 
            b[i] = sc.nextInt();
            result[i] = find(a, b[i], n);
        }

        for(int i = 0; i&lt;result.length-1; i++) {
            System.out.print(result[i]+ &quot; &quot;);
        }
        System.out.print(result[m-1]);
        sc.close();
    }

    private static int find(int[] a, int n, int length) {
        int left = findLeft(a, 0, length, n);
        int right = findRight(a, 0, length, n);
        return right - left;
    }

    private static int findLeft(int[] a, int left, int right, int num) {
        int index = (left + right) / 2;
        if(left &gt;= right) {
            return index;
        }
        if(a[index] &gt;= num) {
            return findLeft(a, left, index, num);
        }else {
            return findLeft(a, index+1, right, num);
        }
    }

    private static int findRight(int[] a, int left, int right, int num) {
        int index = (left + right) / 2;
        if(left &gt;= right) {
            return index;
        }
        if(a[index] &lt;= num) {
            return findRight(a, index+1, right, num);
        }else {
            return findRight(a, left, index, num);
        }
    }
}</code></pre><p>처음에 이렇게 짜서 제출했는데 시간초과가 났다...
대체 왜,,,????? Scanner를 BufferReader로 바꾸고 해도 시간초과 난다....
아,,,,,,,, 어디서 잘못된거지,,
했는데</p>
<p>출력할 때 StringBuilder로 바꿔줬는데 됐다..🙄</p>
<h2 id="📍-코드">📍 코드</h2>
<pre><code>import java.util.*;
import java.io.*;

public class B10816 {
    public static void main(String args[]) throws Exception {
        BufferedReader rd = new BufferedReader(new InputStreamReader(System.in));

        int n = Integer.parseInt(rd.readLine());
        String[] prea = rd.readLine().split(&quot; &quot;);

        int m = Integer.parseInt(rd.readLine());
        String[] preb = rd.readLine().split(&quot; &quot;);

        int a[] = new int[n];
        int b[] = new int[m];

        for(int i=0; i&lt;prea.length;i++) a[i] = Integer.parseInt(prea[i]);
        for(int i=0; i&lt;preb.length;i++) b[i] = Integer.parseInt(preb[i]);

        Arrays.sort(a);
        StringBuilder sb = new StringBuilder();
        for (int num : b) {
            sb.append(find(a, num, n)).append(&quot; &quot;);
        }
        System.out.println(sb.toString());
    }

    private static int find(int[] a, int n, int length) {
        int left = findLeft(a, 0, length, n);
        int right = findRight(a, 0, length, n);
        return right - left;
    }

    private static int findLeft(int[] a, int left, int right, int num) {
        int index = (left + right) / 2;
        if(left &gt;= right) {
            return index;
        }
        if(a[index] &gt;= num) {
            return findLeft(a, left, index, num);
        }else {
            return findLeft(a, index+1, right, num);
        }
    }

    private static int findRight(int[] a, int left, int right, int num) {
        int index = (left + right) / 2;
        if(left &gt;= right) {
            return index;
        }
        if(a[index] &lt;= num) {
            return findRight(a, index+1, right, num);
        }else {
            return findRight(a, left, index, num);
        }
    }
}</code></pre><p>역시 DP는 Bottom up이 편하다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준] #1920 수 찾기]]></title>
            <link>https://velog.io/@cool_kim/%EB%B0%B1%EC%A4%80-1920-%EC%88%98-%EC%B0%BE%EA%B8%B0</link>
            <guid>https://velog.io/@cool_kim/%EB%B0%B1%EC%A4%80-1920-%EC%88%98-%EC%B0%BE%EA%B8%B0</guid>
            <pubDate>Tue, 20 Apr 2021 10:41:49 GMT</pubDate>
            <description><![CDATA[<p><img src="https://images.velog.io/images/cool_kim/post/81ba05f5-e127-4d48-a25a-c2c698e50705/image.png" alt="">
<strong>BOJ #1920</strong>
<a href="https://www.acmicpc.net/problem/1920">https://www.acmicpc.net/problem/1920</a></p>
<h2 id="📃-문제">📃 문제</h2>
<p>N개의 정수 A[1], A[2], …, A[N]이 주어져 있을 때, 이 안에 X라는 정수가 존재하는지 알아내는 프로그램을 작성하시오.</p>
<h2 id="📥-입력">📥 입력</h2>
<p>첫째 줄에 자연수 N(1 ≤ N ≤ 100,000)이 주어진다. 다음 줄에는 N개의 정수 A[1], A[2], …, A[N]이 주어진다. 다음 줄에는 M(1 ≤ M ≤ 100,000)이 주어진다. 다음 줄에는 M개의 수들이 주어지는데, 이 수들이 A안에 존재하는지 알아내면 된다. 모든 정수의 범위는 -231 보다 크거나 같고 231보다 작다.</p>
<h2 id="📤-출력">📤 출력</h2>
<p>M개의 줄에 답을 출력한다. 존재하면 1을, 존재하지 않으면 0을 출력한다.</p>
<h2 id="💡-접근">💡 접근</h2>
<li>배열 안에 특정 숫자를 찾는 알고리즘은 binary search!</li>
<li>binary search는 sort가 먼저 되어있어야 함.</li>

<h2 id="📍-코드">📍 코드</h2>
<pre><code>import java.util.Scanner;
import java.util.Arrays;

class Main {
    public static void main(String args[]) throws Exception {
        Scanner sc = new Scanner(System.in);

        int n = sc.nextInt();
        int a[] = new int[n];

        for(int i = 0; i&lt;n; i++ ) {
            a[i] = sc.nextInt();
        }

        Arrays.sort(a);

        int m = sc.nextInt();
        int b[] = new int[m];

        for (int i = 0; i&lt;m; i++) {
            b[i] = sc.nextInt();
            System.out.println(binarySearch(a, b[i]));
        }
        sc.close();
    }

    private static int binarySearch(int[] a, int n) {
        int first = 0;
        int last = a.length -1;
        int mid = 0;

        while (first &lt;= last) {
            mid = (first + last) /2;

            if (n == a[mid]) return 1;
            else {
                if (n &lt; a[mid]) last = mid -1;
                else first = mid + 1;
            } 
        }
        return 0;
    }
}</code></pre><blockquote>
<p>어렵지 않게 풀었다 룰루~!</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백준] #2206 벽 부수고 이동하기]]></title>
            <link>https://velog.io/@cool_kim/%EB%B0%B1%EC%A4%80-2206-%EB%B2%BD-%EB%B6%80%EC%88%98%EA%B3%A0-%EC%9D%B4%EB%8F%99%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@cool_kim/%EB%B0%B1%EC%A4%80-2206-%EB%B2%BD-%EB%B6%80%EC%88%98%EA%B3%A0-%EC%9D%B4%EB%8F%99%ED%95%98%EA%B8%B0</guid>
            <pubDate>Sun, 11 Apr 2021 10:09:59 GMT</pubDate>
            <description><![CDATA[<p><img src="https://images.velog.io/images/cool_kim/post/177cb2a9-4673-44c1-b29c-4e9b3030f64a/image.png" alt=""></p>
<p><strong>BOJ #2206</strong>
<a href="https://www.acmicpc.net/problem/2206">https://www.acmicpc.net/problem/2206</a></p>
<h2 id="📃-문제">📃 문제</h2>
<p>N×M의 행렬로 표현되는 맵이 있다. 맵에서 0은 이동할 수 있는 곳을 나타내고, 1은 이동할 수 없는 벽이 있는 곳을 나타낸다. 당신은 (1, 1)에서 (N, M)의 위치까지 이동하려 하는데, 이때 최단 경로로 이동하려 한다. 최단경로는 맵에서 가장 적은 개수의 칸을 지나는 경로를 말하는데, 이때 시작하는 칸과 끝나는 칸도 포함해서 센다.</p>
<p>만약에 이동하는 도중에 한 개의 벽을 부수고 이동하는 것이 좀 더 경로가 짧아진다면, 벽을 한 개 까지 부수고 이동하여도 된다.</p>
<p>한 칸에서 이동할 수 있는 칸은 상하좌우로 인접한 칸이다.</p>
<p>맵이 주어졌을 때, 최단 경로를 구해 내는 프로그램을 작성하시오.</p>
<h2 id="📥-입력">📥 입력</h2>
<p>첫째 줄에 N(1 ≤ N ≤ 1,000), M(1 ≤ M ≤ 1,000)이 주어진다. 다음 N개의 줄에 M개의 숫자로 맵이 주어진다. (1, 1)과 (N, M)은 항상 0이라고 가정하자.</p>
<h2 id="📤-출력">📤 출력</h2>
<p>첫째 줄에 최단 거리를 출력한다. 불가능할 때는 -1을 출력한다.</p>
<h2 id="💡-접근">💡 접근</h2>
<li>일단 가중치 없는 최단 경로 이동이니까 bfs로 풀자.</li>
<li>모든 벽을 부수는 것은 시간초과될 것</li>

<h2 id="📍-코드">📍 코드</h2>
<pre><code>import java.util.Scanner;
import java.util.LinkedList;
import java.util.Queue;

class Main {
    static int n, m;
    static char[][] map;

    static int result;

    static int dx[] = { -1, 1, 0, 0 };
    static int dy[] = { 0, 0, 1, -1 };

    public static void main(String[] args) throws Exception {
        Scanner sc = new Scanner(System.in);

        n = sc.nextInt();
        m = sc.nextInt();

        map = new char[n][m];

        for(int i = 0; i&lt;n; i++) {
            String arr = sc.next();
            for (int j = 0; j&lt;m; j++) {
                map[i][j] = arr.charAt(j);
            }
        } //배열 생성

        result = -1;
        bfs();
        System.out.println(result);
        sc.close();
    }

    static void bfs() {
        boolean visit[][][] = new boolean[2][n][m];

        Queue&lt;int[]&gt; q = new LinkedList&lt;&gt;();
        q.offer(new int[] { 0,0,0,1 });
        visit[0][0][0] = true;

        while (!q.isEmpty()) {
            int[] now = q.poll();

            if (now[0] == n-1 &amp;&amp; now[1] == m-1) {
                result = now[3];
                break;
            }

            for (int i = 0; i&lt;4; i++) {
                int x = now[0] + dx[i];
                int y = now[1] + dy[i];

                if(0 &lt;= x &amp;&amp; x &lt; n &amp;&amp; 0 &lt;= y &amp;&amp; y &lt; m &amp;&amp; !visit[now[2]][x][y]) {
                    if(map[x][y] == &#39;0&#39;) {
                        visit[now[2]][x][y] = true;
                        q.offer(new int[] { x, y, now[2], now[3] + 1});
                    }
                    else if (now[2] == 0) {
                        visit[1][x][y] = true;
                        q.offer(new int[] {x, y, 1, now[3] + 1});
                    }
                }
            }

        }

    }
};</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[React] fullcalendar에 MongoDB Json데이터 바로 넣기]]></title>
            <link>https://velog.io/@cool_kim/React-fullcalendar%EB%A1%9C-MongoDB-Json%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%B0%94%EB%A1%9C-%EB%84%A3%EA%B8%B0</link>
            <guid>https://velog.io/@cool_kim/React-fullcalendar%EB%A1%9C-MongoDB-Json%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%B0%94%EB%A1%9C-%EB%84%A3%EA%B8%B0</guid>
            <pubDate>Sun, 11 Apr 2021 08:19:25 GMT</pubDate>
            <description><![CDATA[<p><img src="https://images.velog.io/images/cool_kim/post/abe5c4a0-cd0c-4392-ae2e-40a95973523d/React_fullcalendar.jpg" alt="">
졸업작품이 마무리 되었는데 velog를 시작한지 얼마 안돼서
지금부터 차근차근 졸업작품 코드를 올려보려고 한다!😬</p>
<li>이 프로젝트는 사용자가 운동을 끝내면 운동 시간이 몽고디비에 저장되고
<li>값이 캘린더에 들어가야 한다.

<p>그래서 내가 생각한 방법은 다음과 같다.</p>
<blockquote>
<ol>
<li>fullcalendar에 넣고 싶은 MongoDB 데이터 필드를 title, date로 명시한다.</li>
<li>MongoDB 데이터를 그대로 Redux Saga에 부른다.</li>
<li>Useselector로 데이터를 불러온다.</li>
<li>fullcalendar events에 3번의 데이터를 넣는다.</li>
</ol>
</blockquote>
<p><del>되게 간단한 과정인데
이렇게 생각하는 것도 오래걸렸다...ㅋㅋㅋ</del></p>
<h3 id="1-fullcalendar에-넣고-싶은-mongodb-데이터-필드를-title-date로-명시한다">1. fullcalendar에 넣고 싶은 MongoDB 데이터 필드를 title, date로 명시한다.</h3>
<p>이 작업은 백엔드 작업이다.</p>
<p>모델 스키마를 생성하여 필드 이름을 명시할 때,
fullcalendar에서 events항목에 들어갈 수 있는 object명으로 미리 설정해 놓는 단계이다.
더 많은 event object는 아래 주소에서 확인 할 수 있다.
<a href="https://fullcalendar.io/docs/event-object">https://fullcalendar.io/docs/event-object</a></p>
<pre><code>const ExerciseSchema = new Schema({
  title : Number,
  date: {
    type: Date,
    default: Date.now,
  }
}); //fullcalendar에 events로 넣을 스키마

const UserSchema = new Schema({
    username: String,
    hashedPassword: String,
    totalTime : Number,
    level : String,
    exercises: [ExerciseSchema]
}); </code></pre><p>이 코드는 분 단위로 된 시간 값을 title에 넣고, 이 데이터가 저장 된 시간을 date로 넣은 것이다.</p>
<p>이렇게 하면 불러오기 위한 구조는 완성되었다.</p>
<h3 id="2-mongodb-데이터를-그대로-redux-saga에-부른다">2. MongoDB 데이터를 그대로 Redux Saga에 부른다.</h3>
<p>MongoDB에 저장 된 데이터를 프론트로 가져오기 위한 미들웨어 작업이다.</p>
<p>이 작업은 리덕스에 더 초점이 맞춰져 있으므로 넘어가도록 하겠다.
리덕스는 구글링하면 워낙 많이 나오기 때문에,,,</p>
<h3 id="3-useselector로-데이터를-불러온다">3. Useselector로 데이터를 불러온다.</h3>
<p>2번과 같이 모든 작업이 끝난다면, 리덕스에 이런 식으로 들어와 있을 것이다.</p>
<p><img src="https://images.velog.io/images/cool_kim/post/c3c4b5fa-5c4d-4977-9d15-9e0b8e24fd8f/image.png" alt="">
이미지의 json 구조가 user안에 user가 있고,
그 user안에 exercise필드가 있다.</p>
<p>우리가 사용하고 싶은 data는 exercise필드이므로 user.user를 불러온다.</p>
<pre><code>const { user } = useSelector(({ user }) =&gt; ({
    user: user.user
}));</code></pre><h3 id="4-fullcalendar-events에-3번의-데이터를-넣는다">4. fullcalendar events에 3번의 데이터를 넣는다.</h3>
<p>대망의 데이터 넣는 작업이다.</p>
<p>우선 코드 먼저 보자.</p>
<pre><code>const Calendar = () =&gt; {
  const { user } = useSelector(({ user }) =&gt; ({
    user: user.user
  }));
    return  (
         &lt;FullCalendar
            plugins={[ dayGridPlugin ]}
            initialView = &#39;dayGridMonth&#39;
            events = {user.exercises}
            dayMaxEvents = {true}
            moreLinkClick = &quot;popover&quot;
            contentHeight = &quot;800px&quot;
            eventDisplay = &#39;block&#39;
            eventBackgroundColor = &quot;#1864ab&quot;
         /&gt;
    );
};</code></pre><p>그냥 events에 원하는 데이터 필드를 넣어주면 끝난다!</p>
<blockquote>
<p>사실 fullcalendar 라이브러리가 js으로 검색하면 많이 나오는데 react 라이브러리가 많이 안나와서 좀 애를 먹었지만! 조금 삽질 하고 난 뒤에 풀려서 다행이다!</p>
</blockquote>
<p>이렇게 코드를 짜서 아래 사진 처럼 잘 나오면 진짜 끝이다!
<img src="https://images.velog.io/images/cool_kim/post/0d7853a4-de53-426b-98cf-ade4fe650a3e/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Velog 처음 시작하기]]></title>
            <link>https://velog.io/@cool_kim/Velog-%EC%B2%98%EC%9D%8C-%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@cool_kim/Velog-%EC%B2%98%EC%9D%8C-%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0</guid>
            <pubDate>Mon, 15 Mar 2021 16:25:06 GMT</pubDate>
            <description><![CDATA[<h2 id="velog를-사용하게-된-계기">Velog를 사용하게 된 계기</h2>
<hr>
<p>고학년이 되고 점점 프로젝트하는 일이 많아졌고,,
혼자 개발하기에 많이 부족하기에 개발을 하면서 여러 기술 블로그를 많이 찾아봤었다.
디자인은 하나도 모르면서 디자인에 진심인 나는 티스토리가 너무 어려웠고,
velog는 보기에 너무 편안했고, 섹션이 나눠지는게 좋았다.</p>
<p>그래서 궁금했고, 벨로파트 선생님이 쓰신 책으로 리액트를 배웠는데
그 선생님이 만드신 블로그라고 해서 velog를 쓰기로 결정했다!!😁</p>
<p>파워 P형인 내가,
얼마나 자주 쓰고 얼마나 괜찮은 글을 쓸지 잘 모르겠지만 시작해보려고 한다.😎</p>
<h2 id="블로그에-올리게-될-것">블로그에 올리게 될 것</h2>
<hr>
<ul>
<li>리액트</li>
<li>HTML, CSS</li>
<li>백준 알고리즘 문제 풀이</li>
<li><em>딥러닝</em></li>
</ul>
<p>우선순위 순으로 정렬한 건데,,
딥러닝은 아직 잘 모르기도하고 내가 많이 공부할 수 있을 지도 잘 모르겠으니까,, 
그냥 써둬야지ㅎㅎ</p>
<blockquote>
<p>아직 마크다운 작성법 보면서 쓰는 중이니까 다음엔 마크다운 정리를 해보는 것도 좋을 것 같다!✌</p>
</blockquote>
]]></description>
        </item>
    </channel>
</rss>