<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>im-p0ssible.log</title>
        <link>https://velog.io/</link>
        <description></description>
        <lastBuildDate>Mon, 16 Jun 2025 14:46:21 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>im-p0ssible.log</title>
            <url>https://velog.velcdn.com/images/im-p0ssible/profile/9ad65fed-d2c8-406f-ab47-ecec62718acc/image.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. im-p0ssible.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/im-p0ssible" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[React] React hook]]></title>
            <link>https://velog.io/@im-p0ssible/React-React-hook</link>
            <guid>https://velog.io/@im-p0ssible/React-React-hook</guid>
            <pubDate>Mon, 16 Jun 2025 14:46:21 GMT</pubDate>
            <description><![CDATA[<h1 id="hook">Hook</h1>
<ul>
<li>컴포넌트의 최상위 수준이나 커스텀 훅 내부에서만 사용 가능 (조건문, 반복문, 일반 함수 블럭 {} 내부에서 사용 불가능)</li>
</ul>
<h2 id="usestate">useState</h2>
<ul>
<li>컴포넌트에 state 변수를 추가할 수 있는 리액트 훅.</li>
</ul>
<h3 id="usestate-1">useState()</h3>
<ul>
<li>상태값(컴포넌트에서 관리하는 데이터)를 추가하기 위한 훅</li>
<li>컴포넌트가 렌더링 되는 동안에만 사용할 수 있는 특별한 함수</li>
<li>useState가 호출되는 순서대로 배열에 순서대로 저장되므로 리렌더링 될때에도 순서가 정확히 지켜져야 한다.</li>
<li>state로 만든 변수는 컴포넌트가 여러번 사용돼도 각각의 값을 따로 관리<pre><code class="language-jsx">const [state, setState] = useState(initialState);</code></pre>
</li>
<li><em>매개변수*</em></li>
<li>initialState: 상태값의 초기값(초기 렌더링에 사용되고 리렌더링때는 무시됨)</li>
<li><em>리턴값*</em></li>
<li>state: 저장된 상태값</li>
<li>setState: 상태값을 변경하는 setter함수. setter를 통해 상태가 변경되면 해당 컴포넌트는 다시 렌더링됨<pre><code class="language-jsx">const [count, setCount] = useState(0);
</code></pre>
</li>
</ul>
<p>const handleChange = () =&gt; {
  // setter 함수를 이용하여 상태값 변경
  setCount(count + 1);
}</p>
<pre><code>
## useEffect
- 컴포넌트 생명주기 이벤트를 등록하기 위한 훅
- 컴포넌트가 렌더링 이후에 수행해야 할 일을 부여하는 훅 -&gt; 렌더링 이후(DOM 업데이트 수행 후) 매번 수행
- 컴포넌트가 리턴이 된 후(화면 렌더링 이후) 실행되는 것과 같은 효과

```jsx
useEfect(setup, dependencies?);</code></pre><p><strong>매개변수</strong></p>
<ul>
<li>setup: Effect 로직이 포함된 함수<ul>
<li>cleanup: setup 함수가 리턴한 함수로 컴포넌트가 업데이트 되거나(setup 함수 재실행될 때) 언마운트 될 때 호출
  setup 함수를 사용하면 렌더링이 될 때 이전에 남은 함수가 실행되기 때문에 이런 메모리 누수를 막기 위해 cleanup 함수 사용</li>
</ul>
</li>
<li>dependencies (선택사항): setup 함수 코드 내부에서 참조되는 모든 반응형 값들이 포함된 배열 -&gt; 검사하고자 하는 값으로, 해당 배열 속 하나라도 수정되었을 경우 setup 함수 호출됨<ul>
<li>빈 배열 <code>\[]</code> 을 지정하면 마운트 된 후 setup 함수 <strong>한번만</strong> 호출</li>
<li>dependencies를 지정하지 않으면 컴포넌트가 업데이트 될 때 항상 setup 함수 호출</li>
</ul>
</li>
</ul>
<p><strong>리턴값</strong></p>
<ul>
<li>undefined    </li>
</ul>
<pre><code class="language-jsx">useEffect(() =&gt; {
  // setup 함수 호출
  const timer = setInterval(() =&gt; {
    ...
  }, 1000);

  // cleanup 함수 호출
  return () =&gt; {
    clearInterval(timer)
  };
});</code></pre>
<h2 id="usereducer">useReducer</h2>
<ul>
<li>useState와 같은 상태 업데이트 훅으로, <strong>컴포넌트 외부</strong>에서 상태관리를 하고 싶을 때 사용</li>
<li>reducer 함수는 순수 함수여야한다.<pre><code class="language-jsx">const [state, dispatch] = useReducer(reducer, initialArg, init?);</code></pre>
</li>
<li><em>매개변수*</em></li>
<li>initialArg: state에 전달 할 초기 값</li>
<li>init(선택사항): 초기 state를 반환하는 초기화 함수<ul>
<li>할당되었을 경우 초기 state는 initialArg를 인자로 받아 호출한 결과가 할당</li>
<li>할당되지 않았을 경우 초기 state는 initialArg로 설정</li>
</ul>
</li>
<li><em>반환값*</em></li>
<li>두개의 엘리먼트로 구성된 배열 반환<ol>
<li>state: 상태값이 저장된 getter -&gt; 컴포넌트에서 사용될 상태</li>
<li>dispatch: 상태값을 변경하는 setter 함수로, dispatch에 전달된 인자값이 reducer의 두번째 인자값 (action)으로 전달됨<pre><code class="language-jsx">function reducer(state, action){...}</code></pre>
</li>
</ol>
</li>
<li><em>매개변수*</em></li>
<li>reducer: <code>state</code>와 <code>action</code>을 인자로 받아 새로운 <code>state</code>를 반환하는 함수<ul>
<li>state: 리듀서에 전달되는 상태값</li>
<li>action: <code>dispatch</code>에 전달한 인자값으로 수행할 작업의 종류와 필요한 인자값을 포함한 동작을 정의한 <strong>객체*</strong>
  일반적으로 type 속성에 동작, value 속성에 값을 지정<pre><code class="language-jsx">interface CounterAction {
type: &#39;UP&#39; | &#39;DOWN&#39; | &#39;RESET&#39;;
value: number;
}
</code></pre>
</li>
</ul>
</li>
</ul>
<p>// counterReducer 함수 정의
// counterReducer 함수가 현재 상태(state), action을 받아와서
// action의 type에 따라 상태를 변경하고 새로운 상태를 반환
function counterReducer(state: number, action: CounterAction): number {
  let newState = state;</p>
<p>  ...
  // action으로 전달 받은 동작(type: UP, DOWN, RESET)과 값(value)으로 state를 변경
  ...</p>
<p>  // 변경된 state 반환
  return newState
}</p>
<p>function App(){
  // useReducer를 사용하여 상태 관리
  // counterReducer 함수에 initCount를 전달하고
  // useReducer은 현재 상태(count)와 상태를 변경하는 함수(countDispatch)를 반환하여 상태 관리
  const [count, countDispatch] = useReducer(counterReducer, initCount);
  ...</p>
<p>  return (
    // 버튼 컴포넌트에서 countDispatch 함수 사용
    &lt;Button onClick{ () =&gt; countDicpatch({type: &#39;UP&#39;, value: initCount}) }&gt;UP</Button>
}</p>
<pre><code>
## useRef
- 컴포넌트가 다시 렌더링되어도 기존 상태값을 유지하는 변수 생성
- 함수 내부에 정의하는 지역변수는 컴포넌트가 리렌더링 되면 값이 초기화되는데, 이를 막기 위해 사용
```jsx
const ref = useRef(initialValue);</code></pre><p><strong>매개변수</strong></p>
<ul>
<li>initialValue: 초기값</li>
<li><em>리턴값*</em></li>
<li>{current: initialValue} 객체 반환
  -ref.current 형식으로 사용<pre><code class="language-jsx">// useRef 훅을 사용하여 리렌더링 되어도 값이 유지되는 stepRef를 생성하여 저장
const stepRef = useRef(initCount);
</code></pre>
</li>
</ul>
<p>function handleChange(e: React.ChangeEvent<HTMLInputElement>) {
  const newStep = Number(e.target.value);
  // stepRef의 current에 새로운 값 지정
  stepRef.current = newStep
}</p>
<p>return (
  &lt;input defaultValue={ stepRef.current } onChange={ handleChange } /&gt;
  }</p>
<pre><code>
- JSX 태그에 `ref` 속성을 추가하면 브라우저 DOM 엘리먼트에 직접 접근 가능
```jsx
const refElem = useRef&lt;DOM Type&gt;(null);</code></pre><p><strong>매개변수</strong></p>
<ul>
<li>null: 초기값</li>
<li><em>리턴값*</em></li>
<li>DOM 요소가 있는 속성 하나가 정의된 객체<pre><code class="language-jsx">// useRef 훅을 사용하여 초기값이 null인 ref 객체 선언
const stepElem = useRef&lt;HTMLInputElement&gt;(null);
</code></pre>
</li>
</ul>
<p>function handleChange() {
  // input에 접근에 focus()와 같은 메서드 호출
  stepElem.current?.focus();
}</p>
<p>// ref 속성으로 조작하려는 DOM 노드의 JSX에 전달
return (
  &lt;input ref={ stepElem } ... /&gt;
)</p>
<pre><code>
### useState useRef 차이점
- `useState`: 리액트에서 직접 상태 관리하는 제어 컴포넌트
    -&gt; 값이 변경되면 즉시 리렌더링
- `useRef`: 브라우저에서 입력값을 관리하는 비제어 컴포넌트
    -&gt; 값이 변경되어도 리렌더링이 필요 없을 때 사용


## useMemo
- 지정한 **함수**를 호출하여 반환받은 결과값을 내부에 저장(캐싱)하는 함수
- 마지막으로 렌더링된 결과를 메모이제이션한다.
```jsx
const calculateValue = function(){..};
const cachedValue = useMemo(calculateValue, [dependencies]);</code></pre><p><strong>매개변수</strong></p>
<ul>
<li>calculateValue: 캐싱할 값을 계산하여 반환하는 <strong>순수 함수</strong></li>
<li>dependencies: 의존 객체 배열<ul>
<li>calculateValue 코드 내에서 참조된 모든 반응형 값들의 목록(props, state, 컴포넌트 바디에 직접 선언된 모든 변수와 함수 포함)</li>
<li>배열의 값 중 하나라도 변경되면 calculateValue 함수 재호출</li>
<li>하나도 변경되지 않으면 캐시된 값 반환 -&gt; 재사용</li>
<li>빈 배열 지정시 매번 캐시된 값을 반환</li>
</ul>
</li>
<li><em>리턴값*</em></li>
<li>calculateValue 함수를 호출한 결과값
  다음 렌더링중에 dependencies가 변경되지 않으면 캐시된 결과 반환
  변경되었으면 calculateValue 함수를 재호출한 결과값</li>
</ul>
<pre><code class="language-jsx">const isPrime = function(num: number){
  ...

  return prime;
};

// 리렌더링 되었을 때 이전 num값과 비교하여 num이 바뀔 경우에만 isPrime 함수를 재호출
// 리렌더링 되었을 때 이전 num값과 비교하여 num이 바뀌지 않을 경우 메모이제이션 된 값 반환
const prime = useMemo(() =&gt; isPrime(num), [num])</code></pre>
<h3 id="reactmemo">React.memo</h3>
<ul>
<li><p><strong>컴포넌트</strong>를 메모이제이션 해준다</p>
</li>
<li><p>컴포넌트를 memoize한 후 리렌더링 될 때 props가 변경되지 않으면 memoize된 컴포넌트 반환</p>
</li>
<li><p>리렌더링 될 때 눈에 띄게 지연이 발생하는 경우 사용</p>
</li>
<li><p>리렌더링 될 때 props가 자주 변경되지 않는 컴포넌트에 사용</p>
<pre><code class="language-jsx">const MemoizedComponent = React.memo(SomeComponent, arePropsEqual?)</code></pre>
</li>
<li><p><em>매개변수*</em></p>
</li>
<li><p>SomeConponent: memoize할 컴포넌트</p>
</li>
<li><p>arePropsEqual?: memoize된 컴포넌트를 반환할지, 컴포넌트를 다시 호출할지 결정하는 함수</p>
<ul>
<li>컴포넌트의 이전 props 및 새로운 props를 인자로 받는 함수</li>
<li>true: memoize된 컴포넌트 사용</li>
<li>false: 컴포넌트를 다시 호출한 결과값 아요</li>
<li>생략 시 이전 props와 새로운 props를 얕은 비교하여 같으면 true, 다르면 false를 반환</li>
</ul>
</li>
<li><p><em>리턴값*</em></p>
</li>
<li><pre><code class="language-jsx">// 컴포넌트 export할 때 사용
export default React.memo(Component);</code></pre>
</li>
<li><p>부모가 정의한 이벤트 리스터를 자식에게 props로 전달할 때 부모가 리렌더링 되는 경우 자식도 리렌더링 되지만, 이때 props가 바뀌지 않으면 자식은 기존 DOM을 재사용하도록 메모이제이션 할 수 있음</p>
<ul>
<li>이벤트 리스터를 컴포넌트 내부에서 정의하면 부모가 리렌더링될 때 리스너 함수도 새로 생성되므로 자식에 전달하는 props가 바뀌어 메모이제이션 되지 않고 자식도 리렌더링 발생</li>
<li>useCallback을 사용하면 부모 컴포넌트가 재호출되어도 리스너가 수정되지 않고 유지되므로 자식도 기존 DOM을 재사용하여 성능이 향상됨</li>
</ul>
</li>
</ul>
<h2 id="usecallback">useCallback</h2>
<ul>
<li>컴포넌트 내부에서 정의한 함수를 캐시</li>
<li>컴포넌트가 다시 렌더링되어도 함수가 다시 생성되지 않고 캐시된 함수 사용</li>
<li>useCallback을 사용하면 부모 컴포넌트가 재호출되어도 리스너가 수정되지 않고 유지되므로 자식도 기존 DOM을 재사용하여 성능이 향상됨<pre><code class="language-jsx">const cachedFn = useCallback(fn, dependencies);</code></pre>
</li>
<li><em>매개변수*</em></li>
<li>fn: 캐싱할 함수</li>
<li>dependencies: 의존 객체 배열<ul>
<li>fn내에서 참조되는 모든 반응형 값(proprs, state, 컴포넌트 안에서 직접 선언된 모든 변수와 함수)</li>
<li>dependencies의 값이 바뀌면 새로운 함수를 생성하여 반환</li>
<li>빈 배열 지정시 매번 캐시된 함수를 반환</li>
</ul>
</li>
<li><em>리턴값*</em></li>
<li>최초에는 fn 함수 반환</li>
<li>다음 렌더링부터는 dependencies가 변하지 않았다면 이전에 캐시된 함수 반환</li>
<li>dependencies가 변했다면 새로 생성된 fn함수 반환<pre><code class="language-jsx">const handlePayment = useCallback(() =&gt; {
alert(`배송비 ${shippingFees}원이 추가됩니다. 상품을 결제하시겠습니까?`);
}, [shippingFees]);</code></pre>
</li>
</ul>
<h2 id="usememo-vs-reactmemo-vs-usecallback">useMemo vs. React.memo vs. useCallback</h2>
<h3 id="usememo">useMemo</h3>
<p><strong>함수</strong>를 인자로 전달하고, 전달된 함수의 <strong>실행 결과(리턴값)</strong>를 memoize</p>
<h3 id="reactmemo-1">React.memo</h3>
<p><strong>컴포넌트</strong>를 인자로 전달하고, 전달된 <strong>컴포넌트</strong>를 memoize </p>
<h3 id="usecallback-1">useCallback</h3>
<p><strong>함수</strong>를 인자로 전달하고, 전달된 <strong>함수</strong>를 memoize </p>
<blockquote>
<p>차이점: 함수의 리턴 값 vs. 컴포넌트 vs. 함수 자체</p>
</blockquote>
<h2 id="리액트-컴파일러">리액트 컴파일러</h2>
<ul>
<li>자동 메모이제이션
  useMemo, useCallback, React.memo를 사용하지 않아도 최적화된 코드 생성해줌 </li>
<li>정밀한 의존성 추척
  객체 전체가 아닌 실제 사용되는 속성만 추적</li>
<li>JSX 레벨 최적화
  JSX 요소들을 개별적으로 캐싱</li>
</ul>
<p>설치</p>
<pre><code class="language-node">npm i -D babel-plugin-react-compiler@rc</code></pre>
<p>Vite 설정 - <code>vite.config.ts</code></p>
<pre><code class="language-ts">import { defineConfig } from &#39;vite&#39;;
import react from &#39;@vitejs/plugin-react&#39;;

export default defineConfig({
  plugins: [
    react({
      babel: {
        plugins: [
          [&quot;babel-plugin-react-compiler&quot;, {
            // React 17, 18 사용 시
            runtimeModule: &quot;react-compiler-runtime&quot;
          }]
        ]
      }
    })
  ],
  // ...
});</code></pre>
<h4 id="use-no-memo">use no memo</h4>
<ul>
<li>메모이제이션을 사용하고 싶지 않을 경우 명시<pre><code class="language-jsx">function Product({ ... }) {
&quot;use noe memo&quot;;
...
}</code></pre>
</li>
</ul>
<h3 id="eslint">ESLint</h3>
<ul>
<li>리액트 컴파일러를 사용하기 위해서는 리액트 규칙을 준수해야한다</li>
<li>따라서 ESLint 규칙을 추가해서 사용</li>
</ul>
<p>설치</p>
<pre><code class="language-node">npm install -D eslint-plugin-react-hooks@^6.0.0-rc.1</code></pre>
<p>Eslint 설정 - <code>esline.config.js</code></p>
<pre><code class="language-js">// eslint.config.js
import * as reactHooks from &#39;eslint-plugin-react-hooks&#39;;
// ...

export default tseslint.config(
  // ...
  {
    // ...
    plugins: {
      &#39;react-hooks&#39;: reactHooks,
      // ...
    },
    rules: {
      ...reactHooks.configs.recommended.rules,
      // ...
    },
  },
)</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[React] 리액트 기초]]></title>
            <link>https://velog.io/@im-p0ssible/React-%EB%A6%AC%EC%95%A1%ED%8A%B8-%EA%B8%B0%EC%B4%88</link>
            <guid>https://velog.io/@im-p0ssible/React-%EB%A6%AC%EC%95%A1%ED%8A%B8-%EA%B8%B0%EC%B4%88</guid>
            <pubDate>Mon, 02 Jun 2025 08:57:55 GMT</pubDate>
            <description><![CDATA[<h1 id="react">React</h1>
<ul>
<li>SPA를 개발하기 위해 리액트를 사용한다</li>
<li>React 는 <strong>컴포넌트</strong> 기반의 프론트엔드 라이브러리</li>
<li>React 컴포넌트 이름은 항상 대문자로 시작</li>
<li><code>export</code> <code>import</code>를 통해 모듈로 사용 
  모듈을 사용하려면 <code>&lt;script&gt;</code> 태그에 <code>type=&quot;module&quot;</code> 속성 추가</li>
<li>순수함수를 기반으로 만들어진다<ul>
<li>동일한 props를 전달하면 항상 결과가 동일해야 함</li>
<li><code>&lt;StrictMode&gt;</code>로 순수함수인지 확인</li>
</ul>
</li>
</ul>
<h2 id="가상-dom">가상 DOM</h2>
<ul>
<li>상태 변경 시 뷰를 리렌더링할 때, 브라우저 DOM에 바로 적용하지 않고 가상 DOM을 먼저 수정</li>
<li>수정 전후의 가상 DOM을 비고하여 <strong>바뀐 부분만</strong> 실제 브라우저 DOM에 반영 -&gt; 성능 최적화</li>
</ul>
<h2 id="jsx">JSX</h2>
<ul>
<li>HTML과 유사한 마크업을 작성할 수 있게 해주는 자바스크립트 확장 구문</li>
<li>Balel, ESBuild 같은 변환 도구로 자바스크립트 코드로 변환됨</li>
</ul>
<ul>
<li>단일 루트 요소를 반환해야한다 -&gt; 두개 이상의 태그는 무조건 하나의 태그로 감싸져있어야 한다.<ul>
<li>Fragment 사용 <code>&lt;Fragment&gt;...&lt;/Fragment&gt;</code> </li>
<li>약어 사용 <code>&lt;&gt;...&lt;/&gt;</code><pre><code class="language-jsx">&lt;&gt;
&lt;h1&gt;제목&lt;/h1&gt;
&lt;p&gt;내용 입력&lt;/p&gt;
&lt;/&gt;</code></pre>
</li>
</ul>
</li>
<li>모든 태그는 꼭 닫아야한다.<pre><code class="language-jsx">&lt;&gt;
&lt;input id=&quot;1&quot; type=&quot;text&quot; name=&quot;1&quot;/&gt;
&lt;br/&gt;
&lt;/&gt;</code></pre>
</li>
<li>요소의 속성명은 카멜 표기법을 준수<ul>
<li>예약어 충돌을 위한 속성명이 바뀐 경우<ul>
<li><code>class</code> -&gt; <code>className</code></li>
<li><code>for</code> -&gt; <code>htmlFor</code><pre><code class="language-jsx">&lt;&gt;
&lt;button onClick={ handleUp } className=&quot;upBtn&quot;&gt;+&lt;/button&gt;
&lt;/&gt;</code></pre>
</li>
</ul>
</li>
</ul>
</li>
<li>보간법 사용할 때 표현식 사용<ul>
<li><code>{}</code> 안에는 변수값, 메서드 리턴값 등 값만 사용 가능</li>
<li>if문, for문 등 사용 불가능 </li>
<li><blockquote>
<p>if문 대신 삼항 연산자 사용, for문 대신 forEach(), map()등 사용</p>
</blockquote>
</li>
</ul>
</li>
<li>보간법 안에 중괄호 <code>{ {} }</code> -&gt; 자바스크립트 객체(JSON 형태) 사용</li>
</ul>
<h2 id="props속성">props(속성)</h2>
<ul>
<li><p><strong>부모</strong> 컴포넌트에서 <strong>자식</strong> 컴포넌트로 데이터를 전달</p>
</li>
<li><p>props로 객체를 전달 받을 때는 주소가 전달되는데, 자식 컴포넌트가 그 값을 직접 변경하는 것은 권장 X</p>
<pre><code class="language-jsx">function App(){
const list = [
  { _id: 1, title: &#39;React 공부&#39;, done: false},
  { _id: 2, title: &#39;Javascript 프로젝트&#39;, done: true},
  { _id: 3, title: &#39;Javascript 공부&#39;, done: true},
];

return (
  &lt;div id=&quot;app&quot;&gt;
    &lt;div&gt;
      &lt;Title /&gt;
      &lt;Title titleName=&quot;타이틀&quot; /&gt;
      &lt;TodoList list={ list } /&gt;
    &lt;/div&gt;
  &lt;/div&gt;
);
}
</code></pre>
</li>
</ul>
<p>// App()에서 title이 없을 경우 기본값으로 &#39;Todo List&#39; 매개변수 사용 - 기본값 매개변수
function Title({ titleName = &#39;Todo List&#39; }){
  return (
    <div>
      <h1>{ title }</h1>
      <hr />
    </div>
  );
}</p>
<p>// 함수에 데이터 전달
function TodoList({ list }){
  const itemList = list.map(item =&gt; {
    return (
      &lt;li key={ item._id }&gt;{ item.title } - { item.done ? &#39;완료&#39; : &#39;진행중&#39; }</li>
    );
  });</p>
<p>  return (
    <ul className="todolist">
      { itemList }
    </ul>
  )
}</p>
<pre><code>
- 함수에 데이터를 전달할 때 인수를 사용하듯 컴포넌트에 데이터를 전달할 때 props 사용
```jsx
&lt;TodoList list={ list } /&gt;</code></pre><ul>
<li><p>부모 컴포넌트가 전달한 여러 속성이 자식 컴포넌트에는 하나의 Props 객체로 전달되므로 주로 구조 분해 할당을 이용해서 필요한 속성을 바로 꺼내서 사용</p>
<pre><code class="language-jsx">function TodoList({ list }){
....
}</code></pre>
</li>
<li><p>자신이 전달받은 <strong>props 전체</strong>를 자식 컴포넌트에 전달하고 싶을 때는 전개 연산자 사용</p>
<pre><code class="language-jsx">function Profile(props) {
return (
  &lt;div&gt;
    &lt;Avatar { ...props } /&gt;
  &lt;/div&gt;
);
}</code></pre>
</li>
<li><p><strong>기본값 매개변수</strong>를 사용하면 props가 전달되지 않거나 undefined가 명시적으로 전달될 때 적용</p>
<pre><code class="language-jsx">function Title({ titleName = &#39;Todo List&#39; }){
....
}</code></pre>
</li>
<li><p>컴포넌트에 속성을 넣어서 전달</p>
</li>
<li><p>props의 타입은 interface로 지정</p>
<pre><code class="language-jsx">functuin App() {
....
return (
  &lt;div id=&quot;counter&quot;&gt;
    &lt;Button color=&quot;pink&quot; onClick={handleDown}&gt;-&lt;/Button&gt;
    &lt;Button type=&quot;button&quot; color=&quot;lightgray&quot; onClick={(event) =&gt; handleReset(event)}&gt;0&lt;/Button&gt;
    &lt;Button type=&quot;button&quot; color=&quot;skyblue&quot; onClick={handleUp}&gt;+&lt;/Button&gt;
    &lt;span&gt;{ count }&lt;/span&gt;
  &lt;/div&gt;
)
}
</code></pre>
</li>
</ul>
<p>// props 타입 지정
interface ButtonProps {
  children: string;
  type?: &#39;button&#39;| &#39;reset&#39; | &#39;submit&#39;;
  color?: &#39;pink&#39; | &#39;lightgray&#39; | &#39;skyblue&#39;;
  onClick: (event: React.MouseEvent) =&gt; void;
}</p>
<p>// children으로 &lt;Button ...&gt; </Button> 사이의 내용 사용
function Button ({children, type=&quot;button&quot;, color, onClick: handleClick}: ButtonProps){
  return (
    &lt;button 
      type={ type } 
      onClick={ handleClick } 
      style={{ backgroundColor: color }} 
      className=&quot;rounded-button&quot;
    &gt;{ children }</button>
  )
}</p>
<pre><code>
#### children
- 부모 컴포넌트에서 호출하는 자식 컴포넌트 태그 사이에 전달할 데이터를 입력하는 방식
- 컴포넌트의 여는 태그와 닫는 태그 사이의 내용 포함
```jsx
function App() {
  return (
      &lt;Title&gt;Hello&lt;/Title&gt;
  )
}

function Title({ children }) {
  return (
    &lt;p&gt;{ children }&lt;/p&gt;
  )
}</code></pre><h2 id="state">State</h2>
<ul>
<li>시간이 지남에 따라 변하는 데이터</li>
<li>상태가 변경되면 해당 컴포넌트와 자식 컴포넌트가 리렌더링 됨</li>
</ul>
<h3 id="usestate">useState()</h3>
<ul>
<li>상태값(컴포넌트에서 관리하는 데이터)를 추가하기 위한 훅</li>
<li>컴포넌트가 렌더링 되는 동안에만 사용할 수 있는 특별한 함수</li>
<li>컴포넌트의 최상위 수준이나 커스텀 훅 내부에서만 사용 가능 (조건문, 반복문, 일반 함수 블럭 {} 내부에서 사용 불가능)</li>
<li>useState가 호출되는 순서대로 배열에 순서대로 저장되므로 리렌더링 될때에도 순서가 정확히 지켜져야 한다.</li>
<li>state로 만든 변수는 컴포넌트가 여러번 사용돼도 각각의 값을 따로 관리</li>
</ul>
<p><strong>매개변수</strong></p>
<ul>
<li>initialState: 상태값의 초기값(초기 렌더링에 사용되고 리렌더링때는 무시됨)</li>
<li><em>리턴값*</em></li>
<li>state: 저장된 상태값</li>
<li>setState: 상태값을 변경하는 setter함수. setter를 통해 상태가 변경되면 해당 컴포넌트는 다시 렌더링됨<pre><code class="language-jsx">const [state, setState] = useState(initialState);
</code></pre>
</li>
</ul>
<p>const handleChange = () =&gt; {
  setState(state + 1);
}</p>
<pre><code>
#### 상태의 불변성
- 한번 정의한 상태는 그 값이 바뀌지 않도록 한다
    -&gt; 객체나 배열의 내부 속성을 직접 변경해도 참조 주소는 바뀌지 않기에 원본의 값이 바뀐다
    -&gt; 새로운 상태로 바꿀 때 기존 상태값을 수정하지 않고 새로운 상태값으로 교체해야 리렌더링 발생
- 배열의 불변성을 위한 메서드
    - 추가: concat(), \[ ...arr ]
    - 삭제: filter(), slice()
    - 수정: map()
    - 정렬: 배열 복사 후 reverse(), sort()

##### immer 라이브러리
- [immer](https://immerjs.github.io/immer/)
- 객체를 불변성으로 만들어주는 라이브러리

- 설치
```jsx
npm i immer</code></pre><ul>
<li><code>produce(원본 객체, 콜백 함수)</code></li>
<li><code>draft</code>: 복사한 새로운 객체, draft의 값을 수정한다<pre><code class="language-jsx">const [ user, setUser ] = useState({
  .... // 중첩 객체
});
</code></pre>
</li>
</ul>
<p>function handleChange = (event: React.ChangeEvent<HTMLInputElement>) =&gt; {
  // user를 복사한 새로운 객체를 만들어서 콜백함수의 인자로 전달
  const newUser = produce(user, (draft)=&gt;{
    const address = draft.extra.addressBook.find(address =&gt; address.id === Number(event.target.id))
    address!.value = event.target.value;
  });
  setUser(newUser);
}
```</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TS] 내장 함수]]></title>
            <link>https://velog.io/@im-p0ssible/TS-%EB%82%B4%EC%9E%A5-%ED%95%A8%EC%88%98</link>
            <guid>https://velog.io/@im-p0ssible/TS-%EB%82%B4%EC%9E%A5-%ED%95%A8%EC%88%98</guid>
            <pubDate>Wed, 30 Apr 2025 08:40:29 GMT</pubDate>
            <description><![CDATA[<h3 id="parseint">parseInt</h3>
<p><code>parseInt(string: string, radix?: number): number</code></p>
<pre><code>- 지정한 문자열을 정수로 변환
- stirng: 숫자로 변환할 문자열
- radix: 2진수부터 36진수까지 변환할 진법(기본 10진수)
- 리턴값: 변환된 숫자
- 소수의 경우 소수는 버린다</code></pre><pre><code class="language-ts">console.log(parseInt(&#39;100&#39;)); // 100 출력
console.log(parseInt(&#39;99.876&#39;)); // 99 출력</code></pre>
<h3 id="parsefloat">parseFloat</h3>
<p><code>parseFloat(string: string) number</code></p>
<pre><code>- 지정한 문자열을 부동소수점 방식의 숫자로 변환
- string: 숫자로 변환할 문자열
- 리턴값: 변환된 숫자</code></pre><pre><code class="language-ts">console.log(parseFloat(&#39;99.876&#39;)); // 99.876 출력</code></pre>
<h3 id="settimeout">setTimeout</h3>
<p><code>setTimeout(handler: TimerHandler, timeout?: number, ...arguments): number</code></p>
<pre><code>- 지정된 시간이 지난 후 특정 코드로 한 번 실행하도록 예약
- 비동기 방식으로 호출되므로 setTimeout 이후의 코드가 먼저 실행
- delay값이 0이어도 현재 실행중인 함수의 코드가 먼저 실행된 후 실행
- 함수 내부 코드의 수행이 끝난 후부터 타이머가 시작되므로 딜레이가 생긴다
- handler: 지연 후 실행될 코드나 콜백 함수
  (type TimeHandler = string | Function)
- timeout: 대기 시간(밀리초 단위, 1초 = 1000)
- arguments: 콜백 함수에 전달될 추가 인자값들
- 리턴값: 예약을 중지할 때 사용하는 타이버 id(정수)</code></pre><h3 id="cleartimeout">clearTimeout</h3>
<p><code>clearTimeout(id: number | undefined): void</code></p>
<pre><code>- 취소할 타이머 id(setTimeout()의 리턴값)
- id가 undefined일 경우 타이머 취소가 무시됨</code></pre><pre><code class="language-ts">// 1
console.log(&#39;시작&#39;);

// 2
const timerId = setTimeout((a: number, b:number) =&gt; {
  // 4
  console.log(&#39;3초 후에 실행됩니다.&#39;, a + b)
}, 1000*3, 10, 20); // a = 10, b = 20

// 3
console.log(&#39;종료&#39;);


// timeout 작업 취소
clearTimeout(timerId);</code></pre>
<h3 id="setinterval">setInterval</h3>
<p><code>setInterval(handler: TimeHandler, timeout?:number, ...arguments): number</code></p>
<pre><code>- 지정된 시간 간격으로 특정 코드를 계속 실행하도록 예약
- handler: 지연 후 실행될 코드나 콜백 함수
  (type TimeHandler = string | Function)
- timeout: 대기 시간(밀리초 단위, 1초 = 1000)
- arguments: 콜백 함수에 전달될 추가 인자값들
- 리턴값: 예약을 중지할 때 사용하는 타이버 id(정수)</code></pre><h3 id="clearinterval">clearInterval</h3>
<p><code>clearInterval(id: number | undefined): void</code></p>
<pre><code>- 취소할 타이머 id(setInterval()의 리턴값)
- id기 undefined일 경우 타이머 취소가 무시됨</code></pre><pre><code class="language-ts">console.log(&#39;시작&#39;);

const timerId = setInterval((a: number, b:number) =&gt; {
  console.log(&#39;3초 후에 실행됩니다.&#39;, a + b, new Date())
}, 1000*3, 10, 20);

console.log(&#39;종료&#39;);

// timeout 작업 취소
clearInterval(timerId);</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TS] 인터페이스]]></title>
            <link>https://velog.io/@im-p0ssible/TS-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4</link>
            <guid>https://velog.io/@im-p0ssible/TS-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4</guid>
            <pubDate>Mon, 28 Apr 2025 08:59:41 GMT</pubDate>
            <description><![CDATA[<h1 id="인터페이스">인터페이스</h1>
<pre><code>- 객체의 속성명과 속성값의 타입을 지정
- 변수, 함수의 매개변수, 함수의 리턴 타입에 사용
- 속성은 `;` 또는 `,`로 구문
- interface 키워드로 선언하는 사용자 정의 타입
- 인터페이스를 타입으로 지정한 객체는 해당 인터페이스에 정의된 속성명과 타입을 준수해야함
- JS로 컴파일하면 제거됨</code></pre><h2 id="인터페이스를-객체의-타입으로-지정">인터페이스를 객체의 타입으로 지정</h2>
<pre><code class="language-ts">interface User {
  name: string;
  age: number;
};

const u1: User = {
  name: &#39;kim&#39;,
  age: 5,
};</code></pre>
<h2 id="함수의-리턴-타입으로-인터페이스-지정">함수의 리턴 타입으로 인터페이스 지정</h2>
<pre><code class="language-ts">interface User {
  name: string;
  age: number;
};

const createUser = function(name: string, age: number): User {
  return { name, age }
}

const u3: User = createUser(&#39;lee&#39;, 20);</code></pre>
<h2 id="함수의-매개변수-타입으로-인터페이스-지정">함수의 매개변수 타입으로 인터페이스 지정</h2>
<pre><code class="language-ts">interface User {
  name: string;
  age: number;
};

const u1: User = {
  name: &#39;kim&#39;,
  age: 5,
};

function getAge(user: User): number{
  return user.age;
}

console.log(getAge(u1)); </code></pre>
<h2 id="클래스에서-인터페이스-사용">클래스에서 인터페이스 사용</h2>
<pre><code>-클래스의 타입 지정
- 클래스명 뒤에 `implements` 추가
- 인터페이스를 타입으로 지정한 클래스의 멤버 변수와 메서드는 인터페이스에 정의된 속성과 속성의 타입을 준수해야 함
- 인터페이스에 타입을 선언하면 타입 규칙을 지정해주는 것
- class 선언 시 인터페이스에 지정한 규칙을 따르지 않으면 타입 에러 발생</code></pre><pre><code class="language-ts">// 인터페이스 선언
interface Score {
  kor: number;
  eng: number;
  sum(): number;
  avg(): number;
}

// 클래스를 선언하며 인터페이스 지정
class HighSchool implements Score {
  kor: number;
  eng: number;
  constructor(kor: number, eng: number) {
    this.kor = kor;
    this.eng = eng;
  }
  sum(): number {
    return this.kor + this.engl
  }
  // 타입을 생략할 경우 타입 추론에 의해 리턴값을 파악하여 적절한 타입 추론
  avg() {
    return this.sum() / 2;
  }
}

// 총점과 평균 출력하는 함수
function printScore(score: Score) {
  console.log(score.sum(), score.avg());
}

const myScore = new HighSchool(100, 80);
printScore(myScore);</code></pre>
<h2 id="선택적-프로퍼티-optional-property">선택적 프로퍼티 (optional property)</h2>
<pre><code>- 객체의 속성을 선택적으로 부여하고 싶을 때 인터페이스 속셩명 뒤에 `?` 추가</code></pre><pre><code class="language-ts">interface Todo {
  id: number;
  title: string;
  content: string;
  done?: boolean
}

const todo1: Todo = {
  id: 1,
  title: &#39;할일1&#39;,
  content: &#39;내용1&#39;,
  done: false,
}

const todo2: Todo = {
  id: 2,
  title: &#39;할일2&#39;,
  content: &#39;내용2&#39;,
}</code></pre>
<h2 id="readonly">readonly</h2>
<pre><code>-     객체 생성시에 값을 할당하면 생성한 후에는 수정이 불가능한 속성을 만들 때 사용
- 인터페이스의 속성명 앞에 `readonly` 추가</code></pre><pre><code class="language-ts">interface Todo {
  readonly id: number;
  title: string;
  content: string;
  done?: boolean
}

const todo1: Todo = {
  id: 1,
  title: &#39;할일1&#39;,
  content: &#39;내용1&#39;,
  done: false,
}

todo1.id = 2 // 컴파일 에러 =&gt; readonly 이므로 수정 불가</code></pre>
<h2 id="인터페이스-상속">인터페이스 상속</h2>
<pre><code>- 부모 인터페이스의 속성과 메서드 정의를 자식 인터페이스가 물려 받고 확장
- 기존에 쓰던 타입 별칭에서, 기존의 타입 별칭을 유지하며 또 다른 속성을 추가하고 싶을 때 사용
- interface 선언부의 `extends` 를 추가하고 뒤에 상속 받을 부모 인터페이스 지정</code></pre><pre><code class="language-ts">// 인터페이스 선언
interface TodoRegist {
  title: string;
  content: string;
}

// TodoInfo는 title, content, id, done 속성을 가짐
interface TodoInfo extends TodoRegist {
  id: number;
  done: boolean;
}

const todo1: TodoRegist = {
  title: &#39;할일1&#39;,
  content: &#39;내용1&#39;,
}

const todo2: TodoInfo = {
  id: 1,
  title: &#39;할일1&#39;,
  content: &#39;내용1&#39;,
  done: false,
}</code></pre>
<h3 id="계층-구조로-상속">계층 구조로 상속</h3>
<pre><code>- 인터페이스 상속은 여러 단계의 게층 구조로 상속 가능</code></pre><pre><code class="language-ts">interface TodoRegist {
  title: string;
  content: string;
}

// TodoInfo는 title, content, id, done 속성을 가짐
intergace TodoInfo extends TodoRegist {
  id: number;
  done: boolean;
}

// TodInfoWithDate는 title, content, id, done, createdAt, updatedAt 속성을 가짐
interface TodoInfoWithDate extends TodoInfo {
  createdAt : Date;
  updatedAt : Date;
}</code></pre>
<h3 id="다중-상속">다중 상속</h3>
<pre><code>- 둘 이상의 인터페이스를 상속 받을 수 있음
- 부모 인터페이스에서 속셩이 겹칠 경우 타입이 동일해야한다.</code></pre><pre><code class="language-ts">  interface TodoRegist {
    title: string;
    content: string;    -  
  }

  interface TodoList {
    id: number;
    title: string;
    done: boolean;
  }

  // 다중 상속
  // TodoInfo는 title, content, id, done, createdAt, updatedAt 속성을 가짐
  interface TodoInfo extends TodoRegist, TodoList{
    createAt: Date;
    updatedAt: Date;
}</code></pre>
<h2 id="인터페이스-재선언선언-병합">인터페이스 재선언(선언 병합)</h2>
<pre><code>- 동일한 이름의 인터페이스를 중복으로 선언
- 기존 인터페이스에 없는 속성을 추가
- 같은 이름의 속성을 재선언 할 경우 타입이 동일해야하며, 다른 경우 never 타입이 되기때문에 값을 넣을 때 에러 발생
- 기존의 인터페이스를 변경할 수 없는 경우(외부 라이브러리)에 사용</code></pre><pre><code class="language-ts">interface Todo {
  id: string;
  title: string;
  content: string;
}

// 재선언
interface Todo {
  // id: number; // 동일한 속성을 지정하려면 type이 같아야함
  title: string; // type이 같다면 동잃한 속성도 상관 없음
  done: boolean;
  createdAt: Date;
}</code></pre>
<h1 id="타입별칭과-인터페이스의-차이점">타입별칭과 인터페이스의 차이점</h1>
<pre><code>- 타입 별칭은 거의 모든 것을 정의 할 수 있다
- 인터페이스는 객체, 클래스의 타입을 정의할 수 있다
- 따라서 객체와 클래스를 정의할 때는 인터페이스를 사용하는 것을 추천</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[TS] 타입 별칭]]></title>
            <link>https://velog.io/@im-p0ssible/TS-%ED%83%80%EC%9E%85-%EB%B3%84%EC%B9%AD</link>
            <guid>https://velog.io/@im-p0ssible/TS-%ED%83%80%EC%9E%85-%EB%B3%84%EC%B9%AD</guid>
            <pubDate>Mon, 28 Apr 2025 08:21:47 GMT</pubDate>
            <description><![CDATA[<h1 id="타입-별칭">타입 별칭</h1>
<pre><code>- 유니언 타입 같은 복잡한 타입에 의미 있는 이름을 붙여서 변수에 저장해서 사용
- type 키워드로 선언하는 사용자 정의 타입
- JS로 컴파일 하면 제거됨
- PascalCase(대문자로 시작)를 사용하며, 명사형으로 변수 설정</code></pre><p>기존 타입 지정(유니언 타입)</p>
<pre><code class="language-ts">function log(msg: number | string):void {
  console.log(msg);
}

const msg2: Message = &#39;world&#39;;
const msg3: Message = 123

log(msg2);
log(msg3);</code></pre>
<p>타입 별칭 사용</p>
<pre><code class="language-ts">// 타입 별칭 추가
type Message = string | number;

function log(msg: Message):void {
  console.log(msg);
}

const msg2: Message = &#39;world&#39;;
const msg3: Message = 123;

log(msg2);
log(msg3);</code></pre>
<h2 id="타입-별칭으로-객체-타입-선언">타입 별칭으로 객체 타입 선언</h2>
<pre><code>- 객체의 속성명과 속성값의 타입 지정
- 속성 구분은 `;`를 권장한다
- 타입 별칭을 타입으로 지정한 객체는 타입 별칭에 정의된 속성명과 속성의 타입을 준수해야한다.</code></pre><pre><code class="language-ts">// 타입 별칭 생성
type User = {
  name: string;
  age: number;
};

const u1: User = {
  name: &#39;kim&#39;,
  age: 10,
};

const u2: User = {
  name: &#39;lee&#39;,
  age: &#39;13&#39;, // 타입 에러
}

const u3: User = {
  name: &#39;lee&#39;,
  userAge: 20,
  // age 속성이 없기 때문에 타입 에러
}

console.log(u1.age, u1.name);</code></pre>
<h1 id="인터섹션-타입">인터섹션 타입</h1>
<pre><code>- 타입 여러개를 하나로 합치기 위해 `&amp;`(AND 연산자)로 연결한 타입
- 타입 별칭을 확장할 때 사용
- 기존에 쓰던 타입 별칭에서, 기존의 타입 별칭을 유지하며 또 다른 속성을 추가하고 싶을 때 사용
- 동일한 속성을 인터섹션 타입으로 추가할 때 타입이 다르면 never 타입이 되어 해당 속성은 사용 불가</code></pre><pre><code class="language-ts">// 기존 타입 별칭
type TodoRegist = {
  title: string;
  content: string;
};

// TodoRegist 타입을 확장
type TodoInfo = TodoRegist &amp; {
  id: number;
  done: boolean;
};

const todo1: TodoRegist = {
  title: &quot;타입스크립트&quot;;
  content: &quot;기존의 속성 사용&quot;;
};

const todo2: TodoInfo = {
  id: 1,
  title: &quot;인터섹션 타입&quot;,
  content: &quot;기존 속성과 확장된 속성 둘 다 사용 가능&quot;,
  done: false,
};</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TS] 타입 지정]]></title>
            <link>https://velog.io/@im-p0ssible/TS-%ED%83%80%EC%9E%85-%EC%A7%80%EC%A0%95</link>
            <guid>https://velog.io/@im-p0ssible/TS-%ED%83%80%EC%9E%85-%EC%A7%80%EC%A0%95</guid>
            <pubDate>Mon, 28 Apr 2025 07:58:21 GMT</pubDate>
            <description><![CDATA[<h1 id="ts">TS</h1>
<pre><code>- 자바스크립트와 달리 함수 매개변수의 타입과 개수가 정확히 일치해야한다
- 매개 변수의 타입과 개수가 일치하지 않으면 타입 에러 발생(VSCode 상 빨간 밑줄)</code></pre><h2 id="함수에-타입-지정">함수에 타입 지정</h2>
<h3 id="매개-변수의-타입-지정">매개 변수의 타입 지정</h3>
<pre><code>- 매개 변수명 뒤에 지정</code></pre><pre><code class="language-ts">const name: string = &#39;kim&#39;;
name = 123 // 타입 에러

const age: number = 20;</code></pre>
<h3 id="리턴-타입-지정">리턴 타입 지정</h3>
<pre><code>- 매개 변수 선언부 뒤에 지정
- 리턴 값이 없는 경우 void 지정</code></pre><pre><code class="language-ts">function fn(name: string): string{
  return &#39;Hello &#39; + name;
}

console.log(hello(&#39;TypeScript));</code></pre>
<h2 id="선택적-파라미터">선택적 파라미터</h2>
<pre><code>- 함수의 매개 변수를 선택적으로 전달 받을 때 사용
- 매개 변수명 뒤에 `?` 추가
- 전달하지 않을 경우 undefined을 전달한다
- 지정한 타입 | undefined 로 설정된다</code></pre><pre><code class="language-ts">// age는 전달 해도, 안해도 된다.
function user(name: string, age?: number){
  console.log(name, age)
}

user(&#39;kim&#39;, 5);
user(&#39;lee&#39;); // age는 undefined 전달

const job?: string = &#39;job&#39;; // string | undefined 

console.log(job.toUpperCase()); // 타입 에러 발생
console.log(job?.toUpperCase()); // 정상 출력</code></pre>
<h2 id="유니언-타입">유니언 타입</h2>
<pre><code>- 여러 종류의 타입을 허용하기 위해 |(OR 연산자)로 연결한 타입
- | 연산자로 연결된 타입 중 하나를 허용</code></pre><pre><code class="language-ts">// msg의 타입이 string OR number 중 하나여야한다.
function log(msg: string | number){
  console.log(msg);
}

log(&#39;hello&#39;);
log(123);</code></pre>
<h2 id="타입-가드">타입 가드</h2>
<pre><code>- 타입을 체크하기 위한 코드
- unknown의 경우 꺼낼 때 타입체크가 필요</code></pre><pre><code class="language-ts">// userName2 가 string 타입인지 체크
if(typeof userName2 === &#39;string&#39;){
  console.log(userName2.toUpperCase()); 
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JS] 클로저]]></title>
            <link>https://velog.io/@im-p0ssible/JS-%ED%81%B4%EB%A1%9C%EC%A0%80-6wf15xdt</link>
            <guid>https://velog.io/@im-p0ssible/JS-%ED%81%B4%EB%A1%9C%EC%A0%80-6wf15xdt</guid>
            <pubDate>Sat, 26 Apr 2025 14:04:19 GMT</pubDate>
            <description><![CDATA[<h1 id="closure">closure</h1>
<pre><code>- 실행이 끝난 외부함수의 변수에 접근할 수 있는 내부함수
- 함수가 리턴된 후에도 언제든지 해당 함수 내부에서 선언된 지역변수나 함수를 호출할 수 있는 것
- 내부함수를 접근하는 것이기 때문에 함수 안에 내부함수가 있어야하고, 내부함수가 외부함수를 참조하는 상태여야 한다.</code></pre><pre><code class="language-js">const topLevel = &#39;최상위 변수&#39;;

function outer(){
  const innerVal = &#39;outer의 지역변수&#39;;
  console.log(topLevel); // 하위 Scope에서 접근 가능
  console.log(innerVal); // 지역변수는 선언한 함수내에서만 접근 가능

  const fn = function(){
    console.log(innerVal);
  };

  return fn; // 내부 함수 리턴
}

const returnFn = outer(); // 내부 함수 fn을 변수로 받음
console.log(topLevel); // 같은 Scope 내에서 접근 가능
returnFn(); // &#39;outer의 지역변수&#39; 출력</code></pre>
<p><strong>closure가 만들어지는 조건</strong></p>
<ol>
<li>함수 내부에서 함수를 생성 (중첩함수, 내부함수)</li>
<li>내부함수가 외부함수의 지역변수를 참조</li>
</ol>
<h1 id="클로저-용법">클로저 용법</h1>
<h2 id="캡슐화">캡슐화</h2>
<pre><code>- 함수 내부에서 선언한 지역변수를 외부에서 접근하지 못하게 하는 것</code></pre><pre><code class="language-js">const Counter = function(){
  // this.count 대신 let count로 선언하여 접근을 막는다.
  let count = 0;
  this.getCount = function(){
    return count;
  }
  this.ride = function(){
    if(count &lt; 40){
      count++;
    }else{
      console.log(&#39;정원이 초과되었습니다.&#39;);
    }
  }
};

const c = new Counter();
c.ride();
c.ride();

// 접근 불가능
c.count += 40; 

console.log(&#39;전체 탑승자&#39;, c.getCount());</code></pre>
<h2 id="콜백과-타이머">콜백과 타이머</h2>
<pre><code>- 지정된 함수들의 임의의 시간 뒤에 비동기적으로 호출될 때 외부의 데이터에 접근하는 경우</code></pre><pre><code class="language-js">function setTimer(){
  const inner = 100;
  setTimeout(() =&gt; {
    console.log(inner);
  }, 1000);
}

setTimer(); // 1초 뒤에 inner 함수 출력</code></pre>
<h2 id="currying">Currying</h2>
<pre><code>- 여러개의 인자를 받는 함수를 단일 인자를 받는 함수의 체인으로 호출하도록 바꾸는 함수형 프로그래밍 기법 중 하나
- 매개변수를 나눠서 동작하도록 한다.
- 마지막 인자가 입력될 떄 까지 함수 실행 타이밍을 조절할 수 있다.
- lodash의 _.curry() 함수 사용</code></pre><pre><code class="language-html">// html 파일에 해당 라이브러리 추가
&lt;script src=&quot;https://unpkg.com/lodash@4.17.21/lodash.js&quot;&gt;&lt;/script&gt;</code></pre>
<pre><code class="language-js">const sum = function(x, y){
  return x + y;
}

// lodash의 curry 함수를 사용해서 sum을 커링
const currySum = _.curry(sum);
console.log(currySum(30)(40));</code></pre>
<h2 id="partial-application">Partial application</h2>
<pre><code>- 부분 적용 함수로, 기존 함수의 매개변수 중 일부를 미리 채워둔 상태의 함수
- 커링된 함수를 일부 단계까지만 호출한 후 반환받은 함수를 나중에 나머지 인자를 전달해서 실행
- lodash 의 _.partial() 함수 사용</code></pre><pre><code class="language-html">// html 파일에 해당 라이브러리 추가
&lt;script src=&quot;https://unpkg.com/lodash@4.17.21/lodash.js&quot;&gt;&lt;/script&gt;</code></pre>
<pre><code class="language-js">const sum = function(x, y){
  return x + y;
}

const sum100 = _.partial(sum, 100); // sum 함수의 x에 100을 미리 넣어둔다
console.log(sum100(10));  // sum 함수에 나머지 인자를 전달

// y에 값을 미리 넣어두고 싶은 경우
const sum100 = _.partial(sum, _, 100)</code></pre>
<h3 id="bind">bind</h3>
<pre><code>- lodash의 _.partial() 함수와 비슷하나 미리 전달하는 인자에 this도 지정하는 기능이 추가됨</code></pre><h2 id="메모이제이션">메모이제이션</h2>
<pre><code>- 이전의 계산 결과를 기억하는 함수
- 함수의 속성값으로 계산 결과를 캐시한다
- 공통 함수로 사용하는 것이 좋다</code></pre><pre><code class="language-js">Function.prototype.memo = function(key){
  // 캐시를 위한 코드
  this._cache = this._cache || {};
  if(this._cache[key] !== undefined){ 
    return this._cache[key];
  }else{
    return this._cache[key] = this(key);
  }
};</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JS] class]]></title>
            <link>https://velog.io/@im-p0ssible/JS-class</link>
            <guid>https://velog.io/@im-p0ssible/JS-class</guid>
            <pubDate>Thu, 24 Apr 2025 09:02:00 GMT</pubDate>
            <description><![CDATA[<h1 id="class">class</h1>
<pre><code>- class는 함수이며, 선언문과 표현식 방식으로 사용
- 생성자 함수를 쉽게 기술해주고, 객체를 생성하고 prototype 기반의 상속을 보다 명료하게 표현
- class 선언문은 호이스팅이 되지만, TDZ 제한으로 인해 초기화 전에 호출하면 에러 발생</code></pre><h2 id="class-선언문">class 선언문</h2>
<pre><code class="language-js">class ClassName {
  ...
}</code></pre>
<h2 id="class-표현식">class 표현식</h2>
<pre><code class="language-js">const ClassName = class {
  ...
}</code></pre>
<h2 id="class-메서드-정의">class 메서드 정의</h2>
<pre><code>- 멤버 변수의 초기화는 constructor 메서드에 정의
- class의 바디에는 클래스 멤버변수(속성)와 메서드 정의</code></pre><h3 id="constructor-메서드">constructor 메서드</h3>
<pre><code>- 객체를 생성하고 초기화하는 메서드(생략 가능)
- 하나만 작성 가능
- super()로 부모의 생성자 호출 가능</code></pre><pre><code class="language-js">class HighSchool{
  constructor(kor, eng){
    this.kor = kor;
    this.eng = eng;
  }
}

const s1 = new HighSchool(100, 91);</code></pre>
<h3 id="prototype-메서드-정의">prototype 메서드 정의</h3>
<pre><code>- 클래스 내부에 생성
- 클래서 인스턴스 생성 후 인스턴스.메서드명()으로 호출</code></pre><pre><code class="language-js">class HighSchool{
  constructor(kor, eng){
    this.kor = kor;
    this.eng = eng;
  }

  // prototype 메서드 정의
  sum() {
    return this.kor + this.eng;
  }
  avg() {
    return Math.round(this.sum() / 2);
  }
}

const s1 = new HighSchool(100, 91);
console.log(s1.sum());
console.log(s1.avg());</code></pre>
<h2 id="class-상속">class 상속</h2>
<h3 id="extends">extends</h3>
<pre><code>- 상속을 통해 자식 클래스 정의
- class 자식클래스명 extends 부모클래스명 {}</code></pre><pre><code class="language-js">class HighSchool{
  constructor(kor, eng){
    this.kor = kor;
    this.eng = eng;
  }
  sum() {
    return this.kor + this.eng;
  }
  avg() {
    return Math.round(this.sum() / 2);
  }
}

const s1 = new HighSchool(100, 91);
console.log(s1.sum());
console.log(s1.avg());


class College extends HighSchool{
  constructor(kor, eng){
    super(kor, eng); // 부모(HighSchool)의 생성자 호출
  }

  // 자식 함수에서 메서드 추가 가능
  grade(){
    let level = &#39;F&#39;;
    const avg = this.avg();
    if(avg &gt;= 90){
      level = &#39;A&#39;;
    }else if(avg &gt;= 80){
      level = &#39;B&#39;;
    }else if(avg &gt;= 70){
      level = &#39;C&#39;;
    }else if(avg &gt;= 60){
      level = &#39;D&#39;;
    }
    return level;
  }
}

const c1 = new College(80, 99);
console.log(c1.sum());
console.log(c1.avg());
console.log(c1.grade());</code></pre>
<ul>
<li>자식 함수에서 constructor를 생략할 경우 자동으로 constructor가 생성되며 부모의 생성자 함수를 가져오게 된다.</li>
<li>constructor를 생성하고 super()를 생략할 경우 에러가 발생한다.<pre><code class="language-js">// constructior()를 생략할 경우 자동으로 추가
constructor(...args){
  super(...args);
}</code></pre>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JS] 함수 호출과 this]]></title>
            <link>https://velog.io/@im-p0ssible/JS-%ED%95%A8%EC%88%98-%ED%98%B8%EC%B6%9C%EA%B3%BC-this</link>
            <guid>https://velog.io/@im-p0ssible/JS-%ED%95%A8%EC%88%98-%ED%98%B8%EC%B6%9C%EA%B3%BC-this</guid>
            <pubDate>Wed, 23 Apr 2025 11:36:58 GMT</pubDate>
            <description><![CDATA[<h1 id="함수-호출">함수 호출</h1>
<h2 id="함수로-호출">함수로 호출</h2>
<pre><code>- 함수명()
- this는 window 객체로, window 객체는 어디서나 참조 가능하므로 this를 사용할 필요 없음</code></pre><pre><code class="language-js">function f1(){
  console.log(this); // window 객체 출력
  this.console.log(&#39;hello&#39;); // this가 window 객체이기 때문에 hello 출력
  window.console.log(&#39;hi&#39;); // hi 출력
  console.log(&#39;window 생략&#39;); // window 생략 출략
};
const f2 = function(){
  console.log(this); // window 객체 출력
};

// 함수로 호출
f1();
f2();

console.log(this); // window 객체 출력</code></pre>
<h2 id="메서드로-호출">메서드로 호출</h2>
<pre><code>- 객체에 정의된 메서드를 호출할 때
- 객체.메서드명()
- this는 메서드를 정의한 객체
- 함수를 하나만 정의하고 여러 객체에서 메서드로 사용</code></pre><pre><code class="language-js">const getPingName = function(){
  return this.name;
}

const baro = new Object();
baro.name = &#39;바로핑&#39;;
baro.age = 9;
baro.getName = getPingName;

const rara = {
  name: &#39;라라핑&#39;,
  age: 8,
  getName: getPingName
};

// 메서드로 호출
console.log(baro.age, baro.getName()); // getName()의 this는 baro, 9 바로핑 호출
console.log(rara.age, rara.getName()); // getName()의 this는 rara, 8 라라핑 호출</code></pre>
<h2 id="화살표-함수-호출">화살표 함수 호출</h2>
<pre><code>- 일반 함수나 메서드와 동일하게 호출하지만 함수 내부에 arguments나 this가 생성되지 않고 상위 컨텍스트의 arguments, this 사용</code></pre><pre><code class="language-js">const getPingName = () =&gt; {
  return this.name; // 상위 Scope this를 찾는다 (window)
}

const baro = new Object();
baro.name = &#39;바로핑&#39;;
baro.age = 9;
baro.getName = getPingName;

const rara = {
  name: &#39;라라핑&#39;,
  age: 8,
  getName: getPingName
};

console.log(baro.age, baro.getName()); // getName()의 this는 global, 9 undefined 출력
console.log(rara.age, rara.getName()); // getName()의 this는 global, 8 undefined 출력
// 전역변수로 name이 선언되어있지 않기 때문에 undefined 출력 </code></pre>
<h2 id="apply-call-메서드로-호출">apply(), call() 메서드로 호출</h2>
<pre><code>- 함수에 정의된 메서드
- 함수명.apply() , 함수명.call()
- this는 apply(), call() 메서드의 첫번째 인자로 전달되는 객체
- this를 명시적으로 지정할 수 있음
- 콜백 함수 호출 시 주로 사용</code></pre><pre><code class="language-js">function add(a, b){
  console.log(this);
  const result = a + b;
  return result;
}

console.log(add.apply({name: &#39;어플&#39;}, [50, 60])); // 110, this = {name: &#39;어플&#39;}
console.log(add.call({name: &#39;콜&#39;}, 30, 40)); // 70, this = {name: &#39;콜&#39;}</code></pre>
<h3 id="applyp1-p2">apply(p1, p2)</h3>
<pre><code>- 두개의 매개변수를 가짐
- 첫 번째 매개변수(p1): this로 사용할 객체 전달
- 두 번째 매개변수(p2): 함수에 전달할 인자값 배열</code></pre><h3 id="callp1-p2-p3-">call(p1, p2, p3, ...)</h3>
<pre><code>- 여러개의 매개변수를 가짐
- 첫 번째 매개변수(p1): this로 사용할 객체 전달
- 두 번째 이후의 매개변수(p2, p2, p3, ...): 함수에 전달할 인자값을 차례대로 지정</code></pre><h3 id="배열의-push-메서드를-이용하여-객체를-배열처럼-동작시키기">배열의 push 메서드를 이용하여 객체를 배열처럼 동작시키기</h3>
<pre><code>- this로 지정된 Array 객체의 length 속성값에 해당하는 속성을 만들고 지정한 요소를 저장한 후 length를 하나 증가시킨다
- Array.prototype.push.call(객체, 추가할 요소)</code></pre><pre><code class="language-js">const arr = { 
  length: 3,
  0: &#39;orange&#39;,
  1: &#39;yellow&#39;,
  2: &#39;green&#39;,
  push: function(elem){
    Array.prototype.push.call(this, elem);
  }
};

arr.push(&#39;black&#39;)
arr.push(&#39;white&#39;);
</code></pre>
<h3 id="배열-데이터를-각각의-매개변수로-분리하여-전달">배열 데이터를 각각의 매개변수로 분리하여 전달</h3>
<pre><code class="language-js">function smallest(nums){
  const min = Math.min.apply(...nums) // 전개 구문
  return min;
}

console.log(smallest([10,100]));  // 10
console.log(smallest([200,100,50,60,80,30]));  //30
console.log(smallest([100,20,60,50,70]));  // 20</code></pre>
<h2 id="생성자-함수">생성자 함수</h2>
<pre><code>- new 함수명(), 함수명은 대문자로 시작
- this는 생성자를 통해 생성된 객체
- 생성자로 호출된 함수는 비어있는 객체를 새로 생성
- 새로 생성된 객체는 this 매개변수로 생성자 함수에 전달
- 명시적으로 반환하는 객체가 없다면 생성된 객체를 반환</code></pre><pre><code class="language-js">function Ping(name, age){
  this.age = age;
  this.name = name;
  this.getName = function(){
  return this.name 
  };
}

const baro = new Ping(&#39;바로핑&#39;, 9); 
const rara = new Ping(&#39;라라핑&#39;, 8);
const copyPing = new Ping(&#39;카피핑&#39;, 12);

baro.age++;
baro.height = 120;

console.log(baro.age, baro.getName()); 
console.log(rara.age, rara.getName()); 
console.log(copyPing.age, copyPing.getName());</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JS] prototype]]></title>
            <link>https://velog.io/@im-p0ssible/JS-%ED%94%84%EB%A1%9C%ED%86%A0%ED%83%80%EC%9E%85</link>
            <guid>https://velog.io/@im-p0ssible/JS-%ED%94%84%EB%A1%9C%ED%86%A0%ED%83%80%EC%9E%85</guid>
            <pubDate>Wed, 23 Apr 2025 08:09:18 GMT</pubDate>
            <description><![CDATA[<h1 id="프로토타입">프로토타입</h1>
<pre><code>- 모든 함수가 기본으로 가지고 있는 속성으로 빈 객체로 생성된다
- prototype에 추가한 속성은 해당 함수가 생성자로 사용될 때 생성된 인스턴스 내부 링크로 참조되어 사용된다
- 생성자 함수를 통해 생성되는 인스턴스의 메서드를 정의하는 역할</code></pre><pre><code class="language-js">const Score = function(kor, eng){
  this.kor = kor;
  this.eng = eng;
  // 생성자 내부에 메서드 정의
  this.sum = function(){
    return this.kor + this.eng;
  }
};
// 프로토타입에 메서드 정의 (함수 외부에 정의)
Score.prototype.avg = function(){ 
  return this.sum() / 2;
}

// 생성자 함수로 객체 생성
const s1 = new Score(90, 80);</code></pre>
<p><strong>생성자 함수 내부에 메서드를 정의할 경우</strong></p>
<ul>
<li>새로운 객체를 생성할 때 마다 sum 함수가 새로 생성되고 -&gt; 각 객체마다 메서드 복사</li>
<li>메모리 관리에 비효율적</li>
</ul>
<p><strong>프로토타입에 메서드를 정의하는 경우</strong></p>
<ul>
<li>모든 인스턴스를 공유하기 때문에 같은 함수를 사용한다. -&gt; 동일한 메서드 사용</li>
<li>메모리 관리에 효율적</li>
</ul>
<h3 id="프로토타입-체인">프로토타입 체인</h3>
<pre><code>- 모든 함수는 프로토타입 객체를 갖고있다.
- 모든 객체는 해당 객체를 만드는데 사용된 생성자를 참조하는 constructor 속성의 객체가 정의되어 있다.
- constructor 속성은 객체 생성 시 자동으로 연결되며, 객체와 생성자 함수 사이의 참조 링크를 제공한다.
- 프로퍼티는 해당 객체에서 먼저 찾고 실패했을 때 프로토타입을 확인한다

1. 객체에 해당 프로퍼티가 있으면 사용
2. 객체에 연결된 프로토타입에 해당 프로퍼티가 있으면 사용
3. 프로토타입에도 해당 프로퍼티가 없으면 연결된 프로토타입에서 찾는다
... 찾을 때 까지 반복
4. 최상위 프로토타입인 Object까지 찾아서 해당 프로퍼티가 없으면 그 값은 undefined</code></pre><p><strong>위 코드의 프로토타입 체인</strong></p>
<pre><code>1. s1 객체(Score 함수)에서 avg 메서드 탐색
2. s1의 프로토타입(Score.prototype)에서 avg 메서드 탐색
3. 찾으면 해당 메서드 실행</code></pre><h4 id="프로토타입-체인의-마지막-객체">프로토타입 체인의 마지막 객체</h4>
<pre><code>- 모든 객체의 프로토타입 체인 마지막 객체는 Object이다.
- Array, String, Number, Data, Function 등 내장 객체와 Score, Ping 등 사용자가 정의한 객체는 모두 프로토타입 체인에 의해 자동으로 Object의 메서드를 사용할 수 있다.</code></pre><h4 id="내장된-생성자-함수의-프로토타입">내장된 생성자 함수의 프로토타입</h4>
<pre><code>- Object, Array, Function, Data 등
- 내장된 생성자 함수도 프로토타입 속성이 있으므로 해당 함수에 속성, 메서드를 추가해서 네이티브 객체의 기능을 확장할 수 있다.</code></pre><h3 id="typeof">typeof</h3>
<pre><code>- 객체의 타입을 반환
- 기본 데이터 타입과 함수를 제외한 모든 인스턴스에 대해 object로 반환</code></pre><h3 id="instanceof">instanceof</h3>
<pre><code>- 객체가 지정한 생성자를 통해 생성되었는지 판단
- 직접 생성된 생성자가 아니더라도 프로토타입 체인에 있는 생성자라면 true 반환</code></pre><h2 id="프로토타입-체인을-이용한-상속">프로토타입 체인을 이용한 상속</h2>
<pre><code>- 하위 생성자(자식)의 프로토타입을 상위 생성자(부모)의 객체로 지정
- 상위 생성자의 모든 속성을 물려받아 사용할 수 있음
- Object.create(): 지정한 prototype 객체를 참조하는 인스턴스 생성</code></pre><pre><code class="language-js">// HighSchool
function HighSchool(kor, eng){
  this.kor = kor;
  this.eng = eng;
}

HighSchool.prototype.sum = function(){
  return this.kor + this.eng;
}

HighSchool.prototype.avg = function(){
  return Math.round(this.sum() / 2);
}


const s1 = new HighSchool(100, 91);
console.log(s1.sum());
console.log(s1.avg());

// College
function College(kor, eng){
  HighSchool.call(this, kor, eng)
}

// 상속 함수 불러오기
inherite(HighSchool, College)

// Child가 Parent를 상속받는다
function inherite(Parent, Child){
Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child; 
}


College.prototype.grade = function(){
  let level = &#39;F&#39;;
  const avg = this.avg();
  if(avg &gt;= 90){
    level = &#39;A&#39;;
  }else if(avg &gt;= 80){
    level = &#39;B&#39;;
  }else if(avg &gt;= 70){
    level = &#39;C&#39;;
  }else if(avg &gt;= 60){
    level = &#39;D&#39;;
  }
  return level;
}

const c1 = new College(80, 99);
console.log(c1.sum());
console.log(c1.avg());
console.log(c1.grade());

console.log(College.prototype)</code></pre>
<blockquote>
<p>생성자 함수와 객체를 생성하고 prototype의 복잡함을 해결하기 위해 ES6에서 추가된 class 키워드를 사용하면 상속을 더 쉽게 사용할 수 있습니다.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JS] 이벤트 핸들러]]></title>
            <link>https://velog.io/@im-p0ssible/JS-%EC%9D%B4%EB%B2%A4%ED%8A%B8</link>
            <guid>https://velog.io/@im-p0ssible/JS-%EC%9D%B4%EB%B2%A4%ED%8A%B8</guid>
            <pubDate>Tue, 15 Apr 2025 08:50:58 GMT</pubDate>
            <description><![CDATA[<h2 id="이벤트">이벤트</h2>
<pre><code>- 브라우저에서 어떤 일이 일어났음을 알려주는 신호
- 클릭, 키보드 입력, 마우스 이동, 스크롤등의 작업</code></pre><h3 id="마우스-이벤트">마우스 이벤트</h3>
<pre><code>- click: 해당 element를 클릭(눌렀다 떼기)했을 때 발생
- dbclick: 해당 element를 더블 클릭했을 때 발생
- mousemove: 해당 element에서 마우스를 움직였을 때 발생
- mouseover: 마우스를 해당 element 바깥에서 안으로 옮겼을 때 발생
- moustout: 마우스를 해당 element 안에서 바깥으로 옮겼을 때 발생
- mousedown: 해당 element에서 마우스 버튼을 눌렀을 때 발생
- mouseup: 해당 element에서 눌렀던 마우스 버튼을 떼었을 때 발생
- contextmenu: 마우스 오른쪽 버튼을 눌렀을 때 발생</code></pre><h3 id="키보드-이벤트">키보드 이벤트</h3>
<pre><code>- keydown: 키가 눌렸을 때 발생
- keyup: 키가 올라갔을 때 발생</code></pre><h3 id="폼-이벤트">폼 이벤트</h3>
<pre><code>- focus: 해당 element에 포커스 되었을 때 발생
- blur: 해당 element에서 포커스를 잃을 때 발생
- input: 값을 수정할 때마다 발생
- change: element 변경이 끝나면 발생
- submit: form이 서버로 전송될 때 발생</code></pre><h3 id="스크롤-이벤트">스크롤 이벤트</h3>
<pre><code>- scroll: 스크롤바를 조작하면 발생</code></pre><h3 id="문서-로딩-이벤트">문서 로딩 이벤트</h3>
<pre><code>- load: HTML로 DOM 트리를 만드는 게 완성되었을 뿐만 아니라 이미지, 스타일시트 같은 외부 자원도 모두 불러오는 것이 끝났을 때 발생
- DOMContentLoaded: 브라우저가 HTML을 전부 읽고 DOM 트리를 완성하는 즉시 발생
- beforeunload: 사용자가 사이트를 떠나려 할 때, 변경되지 않은 사항들을 저장했는지 확인시켜줄 때 발생
- unload: 사용자가 진짜 떠나기 전에 사용자 분석 정보를 담은 통계자료를 전송하고자 할 때</code></pre><pre><code class="language-js">window.addEventListner(&#39;load&#39;, function(){
  // 코드 작성
});</code></pre>
<pre><code>- &#39;load&#39; 보다 사용자에게 더 빠르고 정상적인 동작을 제공하기에 DOM 관련 스크립트에서 유리하다</code></pre><pre><code class="language-js">document.addEventListener(&#39;DOMContentLoaded&#39;, function(){
  // 코드 작성
});</code></pre>
<h2 id="onevent">on&lt;event&gt;</h2>
<pre><code>- DOM Level 0 방식(비표준)
- HTML 태그에 인라인으로 직접 작성할 수 있다.
- 요소 노드의 on&lt;event\&gt;속성에 이벤트 핸들러를 등록하면 &lt;event\&gt;가 발생했을 때 등록한 핸들러가 호출됨
- `onclick`, `onmousemove`, `onkeydown`등</code></pre><h3 id="html">HTML</h3>
<pre><code>- HTML 요소의 `on&lt;event&gt;` 속성의 값으로 이벤트 발생시 실행할 코드를 등록</code></pre><pre><code class="language-html">&lt;button onclick=&quot;addContent();console.log(&#39;추가 완료&#39;);&quot;&gt;추가&lt;/button&gt;</code></pre>
<h3 id="script">Script</h3>
<pre><code>- `elem.on&lt;event&gt;` 속성에 이벤트 핸들러 추가</code></pre><pre><code class="language-js">&lt;script&gt;
const btn1 = document.querySelector(&#39;div &gt; button&#39;);
btn1.onclick = function(){
  // 코드 작성
});
&lt;/script&gt;</code></pre>
<h4 id="onclick-중첩">onclick 중첩</h4>
<pre><code>- HTML과 script에 같은 함수가 생성되거나 script 내에서 같은 함수를 여러개 생성하는 경우 기존값이 사라지고 후위에 생성된 함수만 남기때문에 나중에 생성된 코드만 실행된다.</code></pre><pre><code class="language-html">&lt;button onclick=&quot;console.log(&#39;누름 1&#39;);&quot;&gt;눌러봐&lt;/button&gt;</code></pre>
<pre><code class="language-js">&lt;script&gt;
const btn = document.querySelector(&#39;button&#39;);
btn.onclick = function(){
  console.log(&#39;누름 2&#39;);
}
btn.onclick = function(){
  console.log(&#39;누름 3&#39;);
}
&lt;/script&gt;
// 실행 결과 &#39;누름 3&#39;만 출력된다.</code></pre>
<h2 id="addeventlistener">addEventListener</h2>
<pre><code>- DOM Level 2 방식(표준)    
- 요소 노드에 event 발생시 실행할 handler 함수 등록
- `elem.addEventListener(event, handler, [useCapture])`
    - event: 이벤트 이름(`click`, `mousemove`, `keydown` 등)
    - handler: 핸들러 함수
    - useCapture: 캡처링 단계의 이벤트 캐치 여부, false가 기본값이고 버블링 단계의 이벤트를 캐치</code></pre><pre><code class="language-js">btn1.addEventListener(&#39;click&#39;, function(){
  // 코드 작성
});</code></pre>
<h3 id="addeventlistener-중첩">addEventListener 중첩</h3>
<pre><code>- script 내에서 같은 함수를 여러개 생성하는 경우 기존 함수가 사라지지 않고 추가되는 방식이라 모든 함수를 출력한다.</code></pre><pre><code class="language-js">btn.addEventListener(&#39;click&#39;, function(){
  console.log(&#39;누름 1&#39;);
});
btn.addEventListener(&#39;click&#39;, function(){
  console.log(&#39;누름 2&#39;);
});

// 실행 결과 &#39;누름 1&#39;, &#39;누름 2&#39; 둘 다 출력된다.</code></pre>
<h2 id="removeeventlistener">removeEventListener</h2>
<pre><code>- 요소 노드에 event 발생시 실행할 handler 함수를 제거
- 핸들러를 등록할 때 지정했던 매개변수와 동일한 인자값의 핸들러가 삭제
- `fucntion 함수명()` 으로 선언해야만 제거된다.</code></pre><pre><code class="language-js">// 제거 안되는 예시
const btn = document.querySelector(&#39;button&#39;);
btn.addEventListner(&#39;click&#39;, function(){
  console.log(&#39;버튼 클릭&#39;);
});
btn.removeEventListener(&#39;click&#39;, function(){
  console.log(&#39;버튼 클릭&#39;);
});

// 제거되는 예시
const btn = document.querySelector(&#39;button);
function handleClick(){
  console.log(&#39;버튼 클릭&#39;);
}
btn.addEventListener(&#39;click&#39;, handleClick, true);
btn.removeEventListener(&#39;click&#39;, handleClick, true);</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JS] 노드 생성, 추가, 삽입, 삭제, 복사]]></title>
            <link>https://velog.io/@im-p0ssible/JS-%EB%85%B8%EB%93%9C-%EC%83%9D%EC%84%B1-%EC%B6%94%EA%B0%80-%EC%82%BD%EC%9E%85-%EC%82%AD%EC%A0%9C-%EB%B3%B5%EC%82%AC</link>
            <guid>https://velog.io/@im-p0ssible/JS-%EB%85%B8%EB%93%9C-%EC%83%9D%EC%84%B1-%EC%B6%94%EA%B0%80-%EC%82%BD%EC%9E%85-%EC%82%AD%EC%A0%9C-%EB%B3%B5%EC%82%AC</guid>
            <pubDate>Tue, 15 Apr 2025 07:41:15 GMT</pubDate>
            <description><![CDATA[<h1 id="노드-생성">노드 생성</h1>
<ul>
<li><code>createElement(nodeName)</code>: 지정한 태그명으로 요소 노드 생성</li>
<li><code>createTextNode(nodeValue)</code>: 지정한 내용으로 텍스트 노드 생성</li>
<li><code>createAttribute(attributeName)</code>: 지정한 이름으로 속성 노드 생성<pre><code class="language-js">// 요소 노드 &lt;li&gt; 태그 생성
const newLi = document.createElement(&#39;li&#39;);
</code></pre>
</li>
</ul>
<p>// 텍스트 노드 &#39;우유&#39; 생성
const newTxt = document.createTextNode(&#39;우유&#39;);</p>
<pre><code>
# 노드 추가
- `요소노드.appendChild(childNode)`: 지정한 노드`(childNode)`를 노드요소의 마지막 자식 노드로 추가
- 이미 DOM에 존재하는 노드를 추가하면 원래 위치에서 해당 노드를 제거하고 새 위치에 추가한다
```js
// newLi 노드 마지막에 newTxt 노드 추가
// &lt;li&gt;우유&lt;/li&gt;
newLi.appendChild(newTxt);

// shoppingList 노드 마지막에 newLi 노드 추가
shoppingList.appendChild(newLi);</code></pre><h1 id="노드-삽입">노드 삽입</h1>
<ul>
<li><code>요소노드.inserBefore(newNode, targetNode)</code>: 지정한 노드<code>(newNode)</code>를 <code>targetNode</code> 앞에 삽입<pre><code class="language-js">// shoppingList의 firstChild 노드 앞에 newli를 추가
shoppingList.insertBefore(newLi, shoppingList.firstChild);</code></pre>
</li>
</ul>
<h1 id="노드-삭제">노드 삭제</h1>
<ul>
<li><code>요소노드.remocChild(childNode)</code>: 지정한 노드<code>(childNode)</code>를 삭제한다</li>
<li>이 방법보다는 보편적으로 <code>요소노드.remove()</code>를 사용한다.<pre><code class="language-js">// targetList[i] 노드의 firstLi 노드를 삭제한다.
targetList[i].removeChild(firstLi);</code></pre>
</li>
</ul>
<h1 id="노드-복사">노드 복사</h1>
<ul>
<li><code>노드.colneNode(haveChild)</code>: 지정한 노드<code>(haveChild)</code>를 노드 맨 마지막으로 복사한다.</li>
<li><code>haveChild</code>가 true면 하위모든 노드를 같이 복사하고, false면 지정한 노드만 복사한다.
```js
// 노드 복사
const cloneLi = shoppingList.firstElementChild.cloneNode(true);
// 복사한 노드 추가
shoppingList.appenChild(cloneLi);</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JS] 노드 찾기]]></title>
            <link>https://velog.io/@im-p0ssible/JS-%EB%85%B8%EB%93%9C-%EC%B0%BE%EA%B8%B0</link>
            <guid>https://velog.io/@im-p0ssible/JS-%EB%85%B8%EB%93%9C-%EC%B0%BE%EA%B8%B0</guid>
            <pubDate>Mon, 14 Apr 2025 08:36:53 GMT</pubDate>
            <description><![CDATA[<h1 id="노드">노드</h1>
<ul>
<li>DOM 트리구조의 객체 하나하나를 노드라고 한다.</li>
<li>문서 노드, 요소 노드(태그), 속성 노드(요소의 속성), 텍스트 노드(요소의 내용) 등</li>
</ul>
<h2 id="노드-찾기">노드 찾기</h2>
<pre><code class="language-html">&lt;ul id=&quot;purchases&quot; class=&quot;list&quot;&gt;
    &lt;li&gt;두부&lt;/li&gt;
    &lt;li&gt;계란&lt;/li&gt;
    &lt;li&gt;라면&lt;/li&gt;
&lt;/ul&gt;</code></pre>
<h3 id="태그의-id-이용">태그의 id 이용</h3>
<ul>
<li><code>document.getElementById(id)</code></li>
<li>id 속성값에 해당하는 노드 객체를 반환<pre><code class="language-js">// id가 &quot;purchases&quot;인 요소 노드 찾기
const shoppingList = document.getElementById(&quot;purchases&quot;);
// ul 반환</code></pre>
</li>
</ul>
<h3 id="태그의-class-이용">태그의 class 이용</h3>
<ul>
<li><code>document.getElementsByClassName(className)</code></li>
<li>class 속성값에 해당하는 노드의 목록을 반환</li>
<li>배열 형태로 반환되므로 인덱스 지정 필요<pre><code class="language-js">const shoppingList = document.getElementsByClassName(&#39;list&#39;)[0];
// ul 반환
</code></pre>
</li>
</ul>
<pre><code>
### 태그명 이용
- `요소노드.getElementsByTagName(tagName)`
- 유사 배열 객체로 반환
- 인덱스 지정 가능
```js
// 태그명이 &quot;li&quot;인 요소 노드 찾기
const liList = shoppingList.getElementsByTagName(&#39;li&#39;);
// // [li, li, li] 반환

const secondLi = movies.getElementsByTagName(&#39;li&#39;)[1];</code></pre><h3 id="트리구조-이용">트리구조 이용</h3>
<h4 id="부모자식-노드-찾기">부모/자식 노드 찾기</h4>
<p>요소 노드의 속성 | 설명
|----|----|
childNodes|자식 노드가 배열 형태로 저장
firstChild|첫번째 자식 노드(요소, 텍스트, 주석)
firstElementChild|첫번째 자식 요소 노트
lastChild|마지막 자식 노드(요소, 텍스트, 주석)
lastElementChild|마지막 자식 요소 노드
parentNode|부모 노드</p>
<pre><code class="language-js">const firstItem = shoppingList.firstChild;
// 요소, 텍스트, 주소 등 모든 노드를 찾기 때문에 \n(줄바꿈) 반환

const firstItem = shoppingList.firstElementChild 
// &lt;li&gt;두부&lt;/li&gt; 반환</code></pre>
<h4 id="형제-노드-찾기">형제 노드 찾기</h4>
<p>요소 노드의 속성 | 설명
|---|----|
previousSibling|바로 앞의 형제 노드(요소, 텍스트, 주석)
previousElementSibling|바로 앞의 형제 노드
nextSibling|바로 뒤의 형제 노드(요소, 텍스트, 주석)
nextElementSbling|바로 뒤의 형제 요소 노드</p>
<pre><code class="language-js">const secondItem = firstItem.previousElementSibling;
// &lt;li&gt;계란&lt;/li&gt; 반환</code></pre>
<h2 id="css-셀렉터-이용">CSS 셀렉터 이용</h2>
<ul>
<li>지정한 selector 구문에 매칭되는 노드 목록 중 첫번째 노드 반환
<code>document.querySelector(selector)</code></li>
<li>지정한 selector 구문에 매칭되는 노드 목록 반환
<code>document.querySelectorAll(selector)</code><pre><code class="language-js">const lastItem = document.querySelector(&#39;#purchases &gt; li:last-child&#39;).firstChild.nodeValue;
// 라면 반환</code></pre>
</li>
</ul>
<h2 id="nodevalue">nodeValue</h2>
<ul>
<li>노드 찾기를 하면 객체를 출력한다 ex) <li>두부</li></li>
<li>따라서 노드의 텍스트 값만 반환하기 위해 <code>nodeValue</code> 사용<pre><code class="language-js">// lastElementChild &gt; shoppingList의 마지막 자식: &lt;li&gt;라면&lt;/li&gt;
// firstChild &gt; &lt;li&gt;라면&lt;/li&gt;의 첫번째 노드 객체 선택: &quot;라면&quot;
// nodeValue &gt; 실제 텍스트 값 반환: 라면
const lastItem = shoppingList.lastElementChild.firstChild.nodeValue
// 라면 반환</code></pre>
</li>
</ul>
<pre><code class="language-js">// nodeValue를 사용하여 텍스트 내용 수정
firstTextNode.nodeValue = &#39;양파&#39;;</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JS] 변수 스코프]]></title>
            <link>https://velog.io/@im-p0ssible/JS-%EB%B3%80%EC%88%98-%EC%8A%A4%EC%BD%94%ED%94%84</link>
            <guid>https://velog.io/@im-p0ssible/JS-%EB%B3%80%EC%88%98-%EC%8A%A4%EC%BD%94%ED%94%84</guid>
            <pubDate>Fri, 11 Apr 2025 07:55:27 GMT</pubDate>
            <description><![CDATA[<h1 id="변수">변수</h1>
<h2 id="var">var</h2>
<ul>
<li>함수 단위의 유효범위를 갖는 변수 선언문</li>
<li><strong>사용하지 않는 것을 권한다.</strong></li>
</ul>
<h2 id="let">let</h2>
<ul>
<li>블록 단위의 유효범위를 갖는 변수 선언문</li>
</ul>
<h2 id="const">const</h2>
<ul>
<li>블록 단위의 유효범위를 갖는 상수 선언문</li>
<li>const는 변수의 재할당을 막는다</li>
</ul>
<h1 id="전역-변수">전역 변수</h1>
<ul>
<li>함수 외부에서 선언한 변수</li>
<li>스크립트 내 어디에서나 접근 가능</li>
<li>페이지가 로딩될 때 한번 생성하여 값이 유지</li>
<li>브라우저 환경에서sms window 객체의 속성으로 지정됨</li>
<li><strong>사용하지 않는 것이 좋다</strong></li>
</ul>
<h1 id="지역-변수">지역 변수</h1>
<ul>
<li>함수 내부에서 선언한 변수</li>
<li>해당 함수 내부에서만 접근 가능</li>
<li>함수가 호출될 때마다 새로 생성하여 값이 초기화</li>
<li>함수 내부에서 선언하지 않고 바로 사용하는 변수는 전역 변수로 동작</li>
</ul>
<pre><code>const num1 = 20; // 전역 변수

function max(n1, n2){ // 지역 변수
  let result; // 지역 변수
  if(n1 &gt; n2){
    result = n1;
  }else{
    result = n2;
  }
  return result;
}
console.log(max(10, num1)); // 20
console.log(max(200, num1)); // 200</code></pre><h2 id="변수-우선순위">변수 우선순위</h2>
<ul>
<li>가까운 곳부터 찾는다</li>
<li>지역 변수 영역에서 먼저 찾고, 없을 경우 전역 변수에서 찾는다</li>
</ul>
<h2 id="지역변수-유효-범위">지역변수 유효 범위</h2>
<ul>
<li>자바스크립트에서의 var로 선언한 변수는 함수 단위의 유효범위를 갖는다</li>
<li>let과 const는 블록 단위의 유효범위를 갖는다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JS] 배열]]></title>
            <link>https://velog.io/@im-p0ssible/JS-%EB%B0%B0%EC%97%B4</link>
            <guid>https://velog.io/@im-p0ssible/JS-%EB%B0%B0%EC%97%B4</guid>
            <pubDate>Thu, 10 Apr 2025 08:23:43 GMT</pubDate>
            <description><![CDATA[<h1 id="배열">배열</h1>
<ul>
<li>하나의 변수에 여러개의 값을 지정하는 데이터 구조</li>
<li>순서정보 index는 0부터 시작한다.</li>
<li>크기를 미리 지정하지 않는다.</li>
<li>배열명[index]</li>
</ul>
<h2 id="배열-생성-및-초기화">배열 생성 및 초기화</h2>
<pre><code>// Array 클래스로 배열 생성 및 초기화
const arr = new Array(1, 2, 3);

// JSON 표기법으로 배열 생성 및 초기화
const arr = [ 1, 2, 3 ];</code></pre><h2 id="요소-추가">요소 추가</h2>
<ul>
<li>push(): 배열의 메서드로, 일반 object에서는 사용이 불가능
배열의 마지막에 요소 추가<pre><code>// 지정한 배열의 마지막에 요소를 추가
arr.push(10); // [ 1, 2, 3, 10 ]
arr[arr.length] = 300; [ 1, 2, 3, 10, 300 ]
</code></pre></li>
</ul>
<p>arr[5] = 20; // [ 1, 2, 3, 10, 300, 20 ]
arr[6] = 30; // [ 1, 2, 3, 10, 300, 20, 30 ]</p>
<p>// 중간 인덱스를 건너띄고 요소 추가
// 비어있는 배열은 undefined 값을 가짐
arr[10] = 200; // [ 1, 2, 3, 10, 300, 20, 30, , , , 200 ]</p>
<pre><code>
## 요소 갱신</code></pre><p>// 기존 값을 변경
arr[1] = 100; // [ 1, 100, 3, 10, 20, 30, , , , 200 ]</p>
<pre><code>
## 배열 출력</code></pre><p>console.log(arr);
// 출력 결과: [ 1, 100, 3, 10, 300, 20, 30, &lt;3 empty items&gt;, 200 ]</p>
<p>// 배열의 길이 출력
console.log(arr.length);
// 출력 결과: 11</p>
<p>// 배열의 마지막 값 출력
console.log(arr[arr.length-1]);
// 출력 결과: 200</p>
<pre><code>
## 배열의 모든 요소 접근</code></pre><p>// 배열 생성
const arr = [4, 1, 3, 8];</p>
<pre><code>### for문</code></pre><p>for(let i = 0; i&lt;arr.length; i++){
  const elem = arr[i];
  console.log(i, elem);
}
// 출력 결과: 0 4
1 1
2 3
3 8</p>
<pre><code>
### for-of문
- index 사용 없이 배열 요소의 값만 꺼내서 사용</code></pre><p>for(let elem of arr){
  console.log(elem);
}
// 출력 결과: 4
1
3
8</p>
<pre><code>
## 2차원 배열

### 2차원 배열 생성</code></pre><p>const numbers = [
  [2, 4, 6, 8],
  [3, 6, 9, 12],
  [4, 8, 12, 16],
  [5, 10, 15, 20]
];</p>
<pre><code>
### 2차원 배열 출력</code></pre><p>console.log(numbers[1]); 
// 출력 결과: [3, 6, 9, 12]
console.log(numbers[2]); 
// 출력 결과: [4, 8, 12, 16]</p>
<p>console.log(numbers[0][2]);
// 출력 결과:  6
console.log(numbers[3][2]); 
// 출력 결과: 15</p>
<pre><code>
### 2차원 배열 접근 

#### for문</code></pre><p>let sum = 0;
for (let i =0; i&lt;numbers.length; i++){
  for(let k = 0; k&lt;numbers[i].length; k++){
    sum += numbers[i][k];
  }
}
console.log(sum);
// 출력 결과: 140</p>
<pre><code>
#### for-of문</code></pre><p>let sum = 0;
for(rowArr of numbers){
  for(elem of rowArr){
    sum += elem 
  }
}
console.log(sum);
// 출력 결과: 140</p>
<pre><code>

# 유사 배열 객체
- 배열과 비슷하게 사용할 수 있는 객체
- length 속성 사용 가능, index를 통한 접근 가능, push 메서드 사용 불가능
- 읽기를 목적으로 사용된다
- 적은 비용으로 생성 가능

## 유사 배열 생성</code></pre><p>const arr = { 
  length: 3, // length 속성에 크기를 지정하고
  0: &#39;orange&#39;, // 0부터 증가하는 객체를 지정
  1: &#39;yellow&#39;,
  2: &#39;green&#39;,
  }
};</p>
<pre><code></code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[JS] 함수 - Function]]></title>
            <link>https://velog.io/@im-p0ssible/JS-%ED%95%A8%EC%88%98-Function</link>
            <guid>https://velog.io/@im-p0ssible/JS-%ED%95%A8%EC%88%98-Function</guid>
            <pubDate>Thu, 03 Apr 2025 08:52:36 GMT</pubDate>
            <description><![CDATA[<h1 id="함수">함수</h1>
<pre><code>- 명령어의 묶음으로 특정 기능을 재사용하고 싶을 때 작성
- 두번 이상 사용할 일이 있다면 함수로 만드는 것이 좋다.
- 함수를 선언해도 호출하지 않으면 실행하지 않는다.
- 매개변수는 필수가 아니다.</code></pre><ul>
<li><strong>자바스크립트의 함수는 일급 객체이다. 함수 == (호출 + 객체)</strong><pre><code class="language-js">// 형식
function 함수명 (매개변수) {
실행할 구문;
...
return 반환값
}
</code></pre>
</li>
</ul>
<p>// 함수 호출
const result = 함수명(인자값)</p>
<pre><code>
## 일급 객체
    - 변수, 배열 엘리먼트, 다른 객체의 프로퍼티에 할당될 수 있다
    - 함수의 인자로 전달될 수 있다
    - 함수의 결과 값으로 반환될 수 있다
    - 리터럴로 생성될 수 있다
    - 동적으로 생성된 프로퍼티를 가질 수 있다
    - 콜백 함수, 고차 함수, 클로저 가능

### 콜백 함수
    - 매개변수로 함수 객체를 전달해서 호출 함수 내에서 매개변수 함수를 실행하는 것
    - 특정한 상황이 되거나(이벤트 발생) 지정한 시간이 흐르면(timeout) 또는 특정 작업의 수행이 끝나면 호출하도록 지정한 함수
    - 익명함수 사용
```js
function sayHello(name, callback){
  const words = &#39;안녕하세요 저는 &#39; + name + &#39; 입니다&#39;;

  callback(words);
}

sayHello(&quot;이름&quot;, function (name){
  console.log(name);
});</code></pre><h3 id="고차-함수">고차 함수</h3>
<pre><code>- 함수를 인자로 받거나 함수를 반환하는 함수
- `.map()`, `.filter()` 등
- Currying(함수를 반환), Partial application(함수를 인자로 받고 함수를 반환)</code></pre><h3 id="클로저">클로저</h3>
<pre><code>- 내부 함수가 외부 함수의 스코프에 접근할 수 있게 하며 외부 함수의 실행이 끝난 후에도 외부 함수의 변수에 접근할 수 있게 한다</code></pre><h2 id="함수-생성">함수 생성</h2>
<h3 id="선언문">선언문</h3>
<pre><code>- function 키워드로 시작하는 함수 정의
- 함수 이름: 생략 가능(익명함수, 기명함수)
- 매개변수 목록: 쉼표로 구분, 생략 가능, 괄호 필수
- 함구 본문: 생략 가능, 중괄호 필수</code></pre><pre><code class="language-js">// 기명함수
function sayHello () {
  console.log(&#39;안녕 Function!&#39;);
}

// 함수 호출
sayHello();</code></pre>
<h3 id="표현식">표현식</h3>
<pre><code>- 함수 정의를 변수에 할당하여 변수명을 함수명처럼 사용
- 주로 익명함수 사용</code></pre><h4 id="익명함수">익명함수</h4>
<pre><code>- 변수에 익명함수 지정</code></pre><pre><code class="language-js">const add = function(x, y){
  const result = x + y;
  return result;
}
console.log(add(10, 20));</code></pre>
<h4 id="기명-함수">기명 함수</h4>
<pre><code>- 변수에 기명함수 지정
- 변수명을 함수명처럼 사용
- 함수명을 통한 접근은 해당 함수 내부에서만 사용 가능(재귀함수)</code></pre><pre><code class="language-js">const add = function sum(x, y){
  const result = x + y;
  return result;
}

console.log(add(10, 20));
console.log(sum(10, 20)); // 에러 발생

// 함수명을 통한 접근 예시 (재귀함수)
const f = function factorial(n){
    if (n===1) return 1;
  return n * factorial(n-1);
};

console.log(f(5));
console.log(factorial(5)); // 에러 발생</code></pre>
<h3 id="new-function-생성자-함수">new Function 생성자 함수</h3>
<pre><code>- `new`를 붙아고 대문자로 시작
- `functionBody`를 생성할 때 매개변수 괄호의 맨 끝에 적는다
- 가독성이 떨어져서 잘 사용 안함</code></pre><pre><code class="language-js">const add = new Function(&#39;x&#39;, &#39;y&#39;, &#39;const result = x + y; return result;&#39;)

console.log(add(10, 20));</code></pre>
<h3 id="화살표-함수">화살표 함수</h3>
<pre><code>- 함수 표현식의 대안으로 익명함수로만 정의 가능
- 실행할 코드가 하나만 있다면 함수 본문의 중괄호 생략 가능
- 매개변수가 하나만 있다면 매개변수의 괄호 생략 가능
- 매개변수가 없는 경우 빈 괄호 필수
- 선언문 방식에는 사용 불가능(익명함수로만 정의 가능하기 때문에)</code></pre><pre><code class="language-js">// 기존 함수
let add10 = function(x) {
  return x + 10;
};

// 화살표 함수
add10 = x =&gt; {
  return x + 10;
}

// 화살표 함수 축약
add10 = x =&gt; x + 10;</code></pre>
<h2 id="참조-타입">참조 타입</h2>
<h3 id="call-by-value---값에-의한-호출">Call by Value - 값에 의한 호출</h3>
<pre><code>- 기본 데이터 타입은 실제 데이터를 저장하고 다룸
- 값을 복사하여 전달하기 때문에 함수 안에서 변경한 값이 함수 밖에서는 유지되지 않음</code></pre><h3 id="call-by-reference---참조에-의한-호출">Call by Reference - 참조에 의한 호출</h3>
<pre><code>- 참조형 데이터 타입은 실제 데이터가 있는 위치의 주소를 저장하고 다룸
- 주소를 전달하기 때문에 함수 안에서 변경한 값이 함수 밖에서도 유지됨</code></pre><pre><code class="language-js">function add10(data1, data2) {
  data1 += 10;
  data2[0] += 10;
  console.log(&#39;함수 내부&#39;, data1, data2[0]); // 90 90
}

let d1 = 80; // 원시타입 - number
let d2 = [ 80 ]; // 참조 타입 - array(object)

console.log(&#39;함수 호출 이전&#39;, d1, d2[0]); // 80 80

add10(d1, d2);

console.log(&#39;함수 호출 이후&#39;, d1, d2[0]); // 80 90</code></pre>
<h2 id="매개변수와-인자의-수">매개변수와 인자의 수</h2>
<pre><code>- 자바스크립트는 약형언어이기 때문에 매개변수와 함수 호출에 사용되는 인자의 수가 달라도 에러가 발생하지 않는다.
- </code></pre><h3 id="매개변수--인자">매개변수 &gt; 인자</h3>
<pre><code>- 부족한 인자에 대한 매개변수에는 undefine가 지정</code></pre><pre><code class="language-js">function add(x, y, z)
  console.log(z); // undefined 출력
  return x + y;
}
console.log(add(3, 4)); // 7 출력</code></pre>
<h3 id="매개변수--인자-1">매개변수 &lt; 인자</h3>
<pre><code>- 남는 인자에 대해서는 처리할 매개변수가 없기 때문에 무시됨</code></pre><pre><code class="language-js">function add(x, y)
  return x + y;
}
console.log(add(3, 4, 5)); // 7 출력</code></pre>
<h3 id="암묵적-매개변수">암묵적 매개변수</h3>
<pre><code>- 모든 함우세어 명시적으로 선언하지 않고 암묵적으로 사용할 수 있는 매개변수
- arguments, this</code></pre><h4 id="arguments">arguments</h4>
<pre><code>- 함수 내에서 arguments 변수로 접근 가능
- 유사 배열 객체로 length 속성과 indexfh rkr dlswkdp wjqrms rksmd
- arguments 대신 나머지 매개변수(...) 사용 권장</code></pre><pre><code class="language-js">function fn(n1, n2){
  let sum = 0;
  for(let i=0; i&lt;arguments.length; i++){
    sum += arguments[i];
  }
  console.log(&#39;합계&#39;, sum);
}</code></pre>
<p>나머지 매개변수(...)</p>
<pre><code class="language-js">function fn(n1=0, n2=0, ...nums){
  var sum = n1 + n2;
  for(var i=0; i&lt;nums.length; i++){
    sum += nums[i];
  }
  console.log(&#39;합계&#39;, sum);
}</code></pre>
<h4 id="this">this</h4>
<pre><code>- 함수 내에서 this 키워드로 접근 가능
- 함수 컨텍스트 객체
- 함수를 호출한 객체에 대한 참조</code></pre><h3 id="순수-함수">순수 함수</h3>
<pre><code>- 동일한 입력값에 대해서 항상 동일한 출력을 하는 함수
- Side Effect가 없는 함수 -&gt; 외부값에 영향을 주거나 받지 않는 함수</code></pre><h2 id="즉시-실행-함수-iife-패턴">즉시 실행 함수 (IIFE 패턴)</h2>
<pre><code>- 함수 선언 후 곧바로 스스로를 호출하여 실행되는 함수
- 함수를 생성하고 호출하면 함수 내부에 선언된 변수는 사용하지 못하며 함수는 폐기된다.
- 외부에서 접근할 수 없는 독립적인 공간을 확보할 수 있음
- 코드를 함수로 감싸고 호출하면 해당 코드의 유표범위가 함수로 제한
- 함수 내에서 사용하는 변수는 외부에 노출되지 않으므로 외부 변수와 충돌이 발생하지 않는다.,</code></pre><p><code>(() =&gt; {...})();</code></p>
<pre><code class="language-js">(() =&gt; {
  var alert = &#39;즉시 실행 함수&#39;;
  console.log(alert);
})();

// 즉시 실행 함수로 alert를 선언했기 때문에 같은 이름의 변수를 사용해도 충돌이 발생하지 않는다
alert(&#39;작업 완료&#39;);</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JS] 객체 - Object]]></title>
            <link>https://velog.io/@im-p0ssible/JS-%EA%B0%9D%EC%B2%B4-Object</link>
            <guid>https://velog.io/@im-p0ssible/JS-%EA%B0%9D%EC%B2%B4-Object</guid>
            <pubDate>Thu, 03 Apr 2025 08:29:18 GMT</pubDate>
            <description><![CDATA[<h1 id="object">Object</h1>
<ul>
<li>연관있는 데이터를 하나의 객체로 만들어서 데이터 관리</li>
<li>객체(Object): 속성(데이터)와 기능(그 데이터 주체가 하는 일들)을 모은 단위</li>
<li>객체의 속성과 기능에 접근할 때는 dot 연산자(객체.속성)을 이용하거나 [&#39;속성명&#39;] 표기(객체[&#39;속성명&#39;] 사용<pre><code>// 몰라핑 회원의 속성(객체, Object)
const user1 = new Object();
user1.userName = &#39;이00&#39;;
user1.userNo = 3;
user1.userGender = &#39;male&#39;;
user1.userLevel = &#39;diamond&#39;
user1.userPassword = &#39;1234&#39;;
user1.userAge = &#39;24&#39;;
user1.userEmail = &#39;asdfg@gmail.com&#39;;

</code></pre></li>
</ul>
<p>// 호정핑 회원의 속성(객체, Object)
const user2 = new Object();
user2.userName = &#39;김00&#39;;
user2.userNo = 4;
user2.userGender = &#39;male&#39;;
user2.userLevel = &#39;gold&#39;
user2.userPassword = &#39;1234&#39;;
user2.userAge = &#39;30&#39;;
user2.userEmail = &#39;qwert@gmail.com&#39;;</p>
<pre><code>
## JSON 표기법</code></pre><p>const foo = {
  name: &#39;김00&#39;,
  age: 20,
  job: &#39;학생&#39;,
  married: true
};</p>
<pre><code>
### 객체 내부에 함수 생성</code></pre><p>const score = {
  userName: &#39;박00&#39;,
  kor: 100,
  eng: 90,
  math: 85,
  sum: function(){ // 총점 반환
    // this = score, 메서드 내부에서 this가 사용될 때 this는 메서드를 가진 객체를 가리킴
    // 객체의 메서드가 자신의 속성을 접근할 때 this 사용
    // this, score 둘 다 동일하게 사용 가능
    // return score.kor + score.eng + score.math;<br>    return this.kor + this.eng + this.math; 
  },
  avg: function(){ // 평균 반환
    return this.sum() / 3;
  }
};</p>
<p>console.log(score.kor, score.eng, score[&#39;math&#39;])
console.log(&#39;총점&#39;, score.sum()); // 함수 호출
console.log(&#39;평균&#39;, score.avg());</p>
<pre><code>
## 객체 속성 관리</code></pre><p>const foo = {
  name: &quot;김00&quot;,
  mainJob: &quot;magician&quot;
};</p>
<pre><code>### 객체 속성 읽기
- 정의되지 않은 속성은 undefined로 출력</code></pre><p>console.log(foo.name, foo[&quot;mainJob&quot;], foo.subJob);
// 김00 magician undefined 출력</p>
<pre><code>
### 객체 속성 갱신</code></pre><p>foo.mainJob = &quot;fairy&quot;;</p>
<p>console.log(foo.name, foo[&quot;mainJob&quot;], foo.subJob);
// 출력 결과: 김00 fairy undefined</p>
<pre><code>
### 객체 속성 동적 생성</code></pre><p>foo.subJob = &quot;celeb&quot;;</p>
<p>console.log(foo.name, foo[&quot;mainJob&quot;], foo.subJob);
// 출력 결과: 김00 fairy celeb</p>
<pre><code>
### 객체 속성 삭제
- 여러개 한번에 삭제 불가능</code></pre><p>delete foo.mainJob;</p>
<p>console.log(foo.name, foo[&quot;mainJob&quot;], foo.subJob);
// 출력 결과: 푸푸핑 undefined celeb</p>
<pre><code>
### 객체의 모든 속성 읽기 (for-in)</code></pre><p>for (let prop in foo) {
  console.log(prop, foo[prop]);
}
// 출력 결과: name 푸푸핑
subJob celeb</p>
<p>// 속성명 출력
for (let prop in foo) {
  console.log(prop);
}
// 출력 결과: name
subJob</p>
<p>// 속성값만 출력
for (let prop in foo) {
  console.log(foo[prop]);
}
// 출력 결과: 푸푸핑
celeb
```</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JS] 반복문]]></title>
            <link>https://velog.io/@im-p0ssible/JS-%EB%B0%98%EB%B3%B5%EB%AC%B8</link>
            <guid>https://velog.io/@im-p0ssible/JS-%EB%B0%98%EB%B3%B5%EB%AC%B8</guid>
            <pubDate>Wed, 02 Apr 2025 08:05:45 GMT</pubDate>
            <description><![CDATA[<h1 id="while">while</h1>
<ul>
<li>지정한 조건식이 참일 경우 조건이 거짓이 될 때까지 해당 블럭을 반복하여 수행</li>
<li>반복 횟수가 불확실하거나 특정 조건이 충족할 때까지 계속 실행해야 할 때 사용<pre><code>let sum = 0;
let i = 1; 
</code></pre></li>
</ul>
<p>while(i &lt;= 10){
  sum += i;
  i++;
}</p>
<p>console.log(sum);</p>
<p>// 55 출력</p>
<pre><code>
## do-while
- 조건이 맞지 않으면 아예 실행하지 않는 while문과 달리 처음에 한번 무조건 코드를 실행하고 그 다음부터 while문의 조건에 따라 실행
- 최소 한번은 실행해야하는 코드에 사용</code></pre><p>do{
  // 반복할 구문;
} while (조건);</p>
<p>let i = 1;
let sum = 0;</p>
<p>do{
  sum += i;
  i++;
} while (i &lt;= 10);</p>
<pre><code>

# for
- 지정한 횟수만큼 반복적인 작업을 할 경우 사용
- 배열을 순회할 때 사용
- 초기화: 조건식에 사용되는 변수를 초기화
- 조건식: 반복문을 실행할지 체크
- 증감식: 조건식에 사용되는 변수값을 증감</code></pre><p>for(초기화; 조건식; 증감식) {
    // 반복할 구문;
}</p>
<p>// 1부터 10까지의 모든 수릐 합계를 출력
let sum = 0;</p>
<p>for (let i = 1; i &lt;= 10; i++) {
  sum += i; //실행할 코드
}</p>
<p>console.log(sum);</p>
<p>// 1부터 10까지 홀수의 합계 출력. 25
sum = 0;</p>
<p>for(let i = 1; i &lt;= 10; i+=2){
  sum += i;
}</p>
<p>console.log(sum);</p>
<pre><code>
# break
- 반복문이나 switch문을 즉시 종료해주는 명령어
- 자신과 가까운 반복문을 빠져나간다.
- 특별한 경우 아니면 잘 사용하지 않는다</code></pre><p>// n ~ m 까지의 정수중에서 첫번째 짝수를 찾아서 출력하세요.
const n = 1;
const m = 10;</p>
<p>for(let i = n; i &lt;= m; i++){
  if(i % 2 === 0){
    console.log(i);
    break;
  }
}</p>
<pre><code>
# continue
- 반복문 내에서 남아있는 코드를 건너뛰고 다음 반복으로 실행이 넘어감
- 특별한 경우 아니면 잘 사용하지 않는다</code></pre><p>// n부터 m까지 홀수만 출력하세요
const n = 1;
const m = 10;</p>
<p>for(let i = n; i&lt;=m; i++){
  if(i%2 !== 0){
    console.log(<code>${ i } 는 홀수</code>);
    continue // i++ 로 돌아간다.
  }
  console.log(<code>${ i} 는 짝수</code>);</p>
<p>}</p>
<pre><code></code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[JS] 조건문]]></title>
            <link>https://velog.io/@im-p0ssible/JS-%EC%A1%B0%EA%B1%B4%EB%AC%B8</link>
            <guid>https://velog.io/@im-p0ssible/JS-%EC%A1%B0%EA%B1%B4%EB%AC%B8</guid>
            <pubDate>Tue, 01 Apr 2025 07:56:47 GMT</pubDate>
            <description><![CDATA[<h1 id="if문">if문</h1>
<ul>
<li>지정한 조건식이 true일 경우 해당 구문 수행<pre><code>const age = 25;
// age가 20 이상이면 &quot;성인&quot; 출력
if (age &gt;=20) {
console.log(&#39;성인&#39;);
}
// age가 20 미만이면 &quot;미성년자&quot; 출력
if (age &lt; 20) {
console.log(&#39;미성년자&#39;);
}
</code></pre></li>
</ul>
<p>// 성인 출력</p>
<pre><code>
# if ~ else
- 지정한 조건식이 참일 경우와 거짓일 경우 각각 해당 구문 수행</code></pre><p>const age = 19;
// age가 20 이상이면 &quot;성인&quot; 출력하고 그렇지 않으면 &quot;미성년자&quot; 출력
if (age &gt;=20) {
  console.log(&#39;성인&#39;);
} else {
  console.log(&#39;미성년자&#39;);
}</p>
<p>// 미성년자 출력</p>
<pre><code>
# if ~ else if
- 지정한 조건식이 참일 경우 해당 구문을 수행하고 거짓일 경우 else if 문의 조건식을 순차적으로 비교하여 참에 해당하는 구문 수행</code></pre><p>const num = -4;
// num이 양수이면 &quot;양수&quot; 출력
if (num &gt; 0){
  console.log(&#39;양수&#39;);
}else if (num &lt; 0){
  console.log(&#39;음수&#39;);
}else{
  console.log(0);
}</p>
<p>// 음수 출력</p>
<pre><code>
# switch
- switch에 지정한 비교값과 매칭되는(===) case 구문 실행
- break 구문을 만날 때. ㅏ지 또는 마지막 case 구문까지 실행</code></pre><p>/* 
1 ~ 12 사이의 월을 받아서 계절을 출력하는 프로그램
봄: 4월, 여름: 5<del>10월, 가을 11, 겨울: 12</del>3
1 ~ 12 사이의 숫자가 아닐 경우 &quot;잘못된 입력&quot; 출력 
*/</p>
<p>const month = 6;</p>
<p>switch (month) {
  case 4:
    console.log(&quot;봄&quot;);
    break;
  case 5:
  case 6:
  case 7:
  case 8:
  case 9:
  case 10:
    console.log(&quot;여름&quot;);
    break;
  case 11:
    console.log(&quot;가을&quot;);
    break;
  case 12:
  case 1:
  case 2:
  case 3:
    console.log(&quot;겨울&quot;);
    break;
  default:
    console.log(&quot;잘못된 입력&quot;);
}</p>
<p>// 여름 출력</p>
<pre><code></code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[JS] 연산자]]></title>
            <link>https://velog.io/@im-p0ssible/JS-%EC%97%B0%EC%82%B0%EC%9E%90</link>
            <guid>https://velog.io/@im-p0ssible/JS-%EC%97%B0%EC%82%B0%EC%9E%90</guid>
            <pubDate>Mon, 31 Mar 2025 08:53:46 GMT</pubDate>
            <description><![CDATA[<h1 id="연산자">연산자</h1>
<h2 id="산술-연산자">산술 연산자</h2>
<pre><code>// 덧셈
const sum = 1 + 2; // 3
// 뺄셈
const sum = 2 - 1; // 1
// 곱셈
const sum = 3 * 4; // 12
// 나눗셈
const sum = 4 / 2; // 2
// 나머지
const sum = 5 % 2; // 1
// 거듭제곱
const sum = 2 ** 3; //8
// 결합
const age = 20;
const result = &quot;저는 &quot; + age + &quot;살 입니다.&quot;;
console.log(`저는 ${ age }살 입니다.`);</code></pre><h2 id="대입-연산자">대입 연산자</h2>
<pre><code>// 기본 대입 연산자
const a = 3;
const b = 2;
// 덧셈 후 대입
a += b; // a = a + b
// 뺄셈 후 대입
a -+ b; // a = a - b
// 나눗셈 푸 대입
a /= b; // a = a / b
// 나머지 연산 후 대입
a %= b; // a = a % b
// 거듭제곱 후 대입
a **= b; // a = a ** b</code></pre><h2 id="증감-연산자">증감 연산자</h2>
<h3 id="후위형">후위형</h3>
<ul>
<li>현재의 값을 먼저 사용한 후 값을 증가 또는 감소<pre><code>const count = 0;
count++; // 1 
count--; // 0</code></pre></li>
</ul>
<h3 id="전위형">전위형</h3>
<ul>
<li>값을 먼저 증가 또는 감소한 후 변경된 값을 사용
```
const count = 0;</li>
<li>+count; // 1 </li>
<li>-count; // 0<pre><code></code></pre></li>
</ul>
<h3 id="예시">예시</h3>
<pre><code>var x = 5;
var y = x++ + ++x + x++ - x--; 
// y = 5 + 7 + 7 - 8 = 11
// x = 7</code></pre><h2 id="비교-연산자">비교 연산자</h2>
<ul>
<li>두 항을 비교하여 참이면 true, 거짓이면 false 반환</li>
</ul>
<pre><code>var a = 5;
var b = 10;
var c = &#39;5&#39;;
var d = 5;

// &gt; (크다)
console.log(a &gt; b);

// &lt; (작다)
console.log(a &lt; b);

// &gt;= (크거나 같다)
console.log(a &gt;= d);

// &lt;= (작거나 같다)
console.log(a &lt;= d);

// 문자열 비교
console.log(a == c); // 동등, 5 = &#39;5&#39; = 5 == 5 = true
console.log(a === c); // 일치, 5 === &#39;5&#39; = number === string = false

console.log(&#39;ch05&#39; &gt; &#39;ch01&#39;); //사전순으로 비교, true
console.log(&#39;ch15&#39; &gt; &#39;ch2&#39;); //사전순으로 비교, 컴퓨터는 한글자씩 비교한다, false
// ch05, ch12, ch2, ch01 오름차순 정렬 순서
// ch01, ch05, ch12, ch2</code></pre><h3 id="일치-연산자-">일치 연산자 (===)</h3>
<ul>
<li>두 데이터의 타입과 값을 모두 비교하여 값이 같아도 타입이 다르면 false<pre><code>console.log(a === c); // 일치, 5 === &#39;5&#39; = number === string = false
null === null // true
undefined === undefined // true
null === undefined // false</code></pre></li>
</ul>
<h3 id="동등-연산자-">동등 연산자 (==)</h3>
<ul>
<li>두 데이터의 타입이 다르면 형 변환 후 일치 비교하여 타입이 달라도 값이 같으면 true<pre><code>console.log(a == c); // 동등, 5 = &#39;5&#39; = 5 == 5 = true
null == undefined // true</code></pre></li>
</ul>
<h2 id="논리-연산자">논리 연산자</h2>
<ul>
<li>falsy: number 0, string &#39;&#39;, boolean false, null, undefined</li>
<li>truthy: 100, &#39; &#39;, &#39;hello&#39;, true, {}, []</li>
</ul>
<h3 id="--논리합-or">|| : 논리합 (OR)</h3>
<ul>
<li>피연산자 둘 중 하나라도 true일 경우 true</li>
<li>둘 다 false일 경우 false</li>
<li>앞의 값이 ture면 앞의 값을 반환</li>
<li>앞의 값이 false이면 뒤의 값을 반환<pre><code>console.log(&#39;hello&#39; || &#39;world&#39;); // 둘 다 true, hello
console.log(90 || 30); //둘 다 true, 90
console.log(null || &#39;world&#39;); // world
console.log(undefined || &#39;hello&#39;); // hello
console.log(0 || 100); // 100
console.log(&#39;&#39; || &#39;hello&#39;); // hello
</code></pre></li>
</ul>
<p>var id = &#39;hongf&#39;;
var invalidId = id.length &lt; 4 || id.length &gt; 12;
var invalidId = !(id.length &gt;= 4 &amp;&amp; id.length &lt;= 12);
console.log(&#39;id 입력 조건에 맞지 않음&#39;, invalidId); // false</p>
<pre><code>
### &amp;&amp; : 논리곱 (AND)
- 피연산자 둘 다 true일 경우 true
- 둘 중 하나라도 false일 경우 false
- 앞의 값이 true면 뒤의 값을 반환
- 앞의 값이 false면 앞의 값을 반환</code></pre><p>console.log(true &amp;&amp; true); // ture
console.log(true &amp;&amp; false); // false
console.log(false &amp;&amp; true); // false
console.log(false &amp;&amp; false); // false</p>
<pre><code>
### ! : 부정 (NOT)
- true면 false, false면 true</code></pre><p>var id = &#39;hongf&#39;;
var invalidId = !(id.length &gt;= 4 &amp;&amp; id.length &lt;= 12);
console.log(invalidId); // false</p>
<pre><code>

## 삼항 연산자
- 조건에 따라 값을 선택
- {조건} ? {참일 때의 값} : {거짓일 때의 값};</code></pre><p>let num = 9;
let result = num % 2 === 0 ? &#39;짝수&#39; : &#39;홀수&#39;;
console.log(<code>${num}은 ${result}입니다.</code>); // 9은 홀수입니다.</p>
<p>```</p>
<h2 id="연산자-우선순위">연산자 우선순위</h2>
<ol>
<li>괄호: ()</li>
<li>단항 연산자: +, -, ++(전위형), --(전위형), !, typeof, delete</li>
<li>산술 연산자: *, /, %, +, -</li>
<li>비교 연산자: &gt;, &lt;, &gt;=, &lt;=, ==, ===, !=, !==</li>
<li>논리 연산자: &amp;&amp;, ||</li>
<li>삼항 연산자</li>
<li>증감 연산자(후위형): ++, --</li>
</ol>
<ul>
<li>산술, 비교, 논리, 대입 연산자의 순서는 꼭 기억하라.</li>
<li>우선 순위가 헷갈리면 괄호 사용을 권장.</li>
</ul>
]]></description>
        </item>
    </channel>
</rss>