<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>view_coding.log</title>
        <link>https://velog.io/</link>
        <description>꿈많은 개발자</description>
        <lastBuildDate>Tue, 25 Jun 2024 09:56:56 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>view_coding.log</title>
            <url>https://velog.velcdn.com/images/view_coding/profile/63073b5c-c41a-4aa9-a02a-5a1e5c985368/image.jpg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. view_coding.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/view_coding" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[React] 배열을 매핑할 때 중괄호 {}와 소괄호 () 차이점]]></title>
            <link>https://velog.io/@view_coding/React-%EB%B0%B0%EC%97%B4%EC%9D%84-%EB%A7%A4%ED%95%91%ED%95%A0-%EB%95%8C-%EC%A4%91%EA%B4%84%ED%98%B8-%EC%99%80-%EC%86%8C%EA%B4%84%ED%98%B8-%EC%B0%A8%EC%9D%B4%EC%A0%90</link>
            <guid>https://velog.io/@view_coding/React-%EB%B0%B0%EC%97%B4%EC%9D%84-%EB%A7%A4%ED%95%91%ED%95%A0-%EB%95%8C-%EC%A4%91%EA%B4%84%ED%98%B8-%EC%99%80-%EC%86%8C%EA%B4%84%ED%98%B8-%EC%B0%A8%EC%9D%B4%EC%A0%90</guid>
            <pubDate>Tue, 25 Jun 2024 09:56:56 GMT</pubDate>
            <description><![CDATA[<h3 id="1-">1. {}</h3>
<pre><code>{items.map((item, index) =&gt; {
  const processedItem = item.toUpperCase(); // 추가적인 로직
  return (
    &lt;div key={index}&gt;
      {processedItem}
    &lt;/div&gt;
  );
})}
</code></pre><p>중괄호 {}를 사용하는 방식은 함수 본문을 명시적으로 작성하고 명시적으로 return 키워드를 사용하여 값을 반환해야 합니다. 여러 줄의 코드를 작성하거나 복잡한 로직을 처리할 때 유용합니다.</p>
<h3 id="2-">2. ()</h3>
<pre><code>{items.map((item, index) =&gt; (
  &lt;div key={index}&gt;
    {item.toUpperCase()}
  &lt;/div&gt;
))}</code></pre><p>소괄호 ()를 사용하는 방식은 암시적으로 값을 반환하며, 주로 간단한 JSX를 반환할 때 사용됩니다. 코드가 간결하고 가독성이 좋아집니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[React] 라이프사이클]]></title>
            <link>https://velog.io/@view_coding/React-%EB%9D%BC%EC%9D%B4%ED%94%84%EC%82%AC%EC%9D%B4%ED%81%B4</link>
            <guid>https://velog.io/@view_coding/React-%EB%9D%BC%EC%9D%B4%ED%94%84%EC%82%AC%EC%9D%B4%ED%81%B4</guid>
            <pubDate>Sun, 09 Jun 2024 06:55:39 GMT</pubDate>
            <description><![CDATA[<p>React 라이프사이클은 컴포넌트가 생성되고 업데이트되며, 제거되는 일련의 단계를 의미합니다. 각 단계에서 특정 메서드가 호출되며, 이를 통해 컴포넌트의 상태나 다른 작업을 수행할 수 있습니다. </p>
<p><img src="https://velog.velcdn.com/images/view_coding/post/78e9b419-d4d9-4287-b898-3f7a3e3f9fcb/image.png" alt=""></p>
<h3 id="1-마운트mounting">1. 마운트(Mounting)</h3>
<p>마운트 단계는 컴포넌트가 처음 DOM에 삽입될 때(실행) 발생합니다. 이 단계에는 다음 네 가지 메서드가 호출됩니다.</p>
<ul>
<li>constructor()
컴포넌트가 생성될 때 호출됩니다.
초기 상태와 메서드 바인딩을 설정하는 데 사용됩니다.</li>
</ul>
<pre><code>constructor(props) {
  super(props);
  this.state = { count: 0 };
}</code></pre><ul>
<li>static getDerivedStateFromProps(props, state)
컴포넌트가 생성되거나 업데이트될 때 호출됩니다.
주어진 props로부터 상태를 업데이트해야 할 때 사용됩니다.</li>
</ul>
<pre><code>static getDerivedStateFromProps(props, state) {
  if (props.someValue !== state.someValue) {
    return { someValue: props.someValue };
  }
  return null;
}</code></pre><ul>
<li>render()
컴포넌트의 UI를 정의하는 메서드입니다.
이 메서드는 반드시 순수 함수여야 하며, 상태나 props를 변경하지 않아야 합니다.</li>
</ul>
<pre><code>render() {
  return &lt;div&gt;{this.state.count}&lt;/div&gt;;
}</code></pre><ul>
<li>componentDidMount()
컴포넌트가 처음 렌더링되고 난 후에 호출됩니다.
여기서 AJAX 요청이나 DOM 노드에 대한 직접적인 작업을 수행할 수 있습니다.</li>
</ul>
<pre><code>componentDidMount() {
  // 데이터 로드 또는 타이머 설정 등
}</code></pre><br />

<h3 id="2-업데이트updating">2. 업데이트(Updating)</h3>
<p>업데이트 단계는 컴포넌트가 새로운 props를 받거나 상태가 변경될 때 발생합니다. 이 단계에는 다음 여섯 가지 메서드가 호출될 수 있습니다.</p>
<ul>
<li><p>static getDerivedStateFromProps(props, state)
컴포넌트가 업데이트될 때도 호출됩니다.
props로부터 상태를 업데이트할 필요가 있을 때 사용됩니다.</p>
</li>
<li><p>shouldComponentUpdate(nextProps, nextState)
컴포넌트가 업데이트될지 여부를 결정합니다.
성능 최적화를 위해 사용할 수 있습니다.</p>
</li>
</ul>
<pre><code>shouldComponentUpdate(nextProps, nextState) {
  return nextState.count !== this.state.count;
}</code></pre><ul>
<li><p>render()
컴포넌트의 UI를 다시 정의합니다.</p>
</li>
<li><p>getSnapshotBeforeUpdate(prevProps, prevState)
DOM이 변경되기 직전에 호출됩니다.
여기서 반환된 값은 componentDidUpdate로 전달됩니다.</p>
</li>
</ul>
<pre><code>getSnapshotBeforeUpdate(prevProps, prevState) {
  if (prevState.count &lt; this.state.count) {
    return { scrollPosition: window.scrollY };
  }
  return null;
}</code></pre><ul>
<li>componentDidUpdate(prevProps, prevState, snapshot)
컴포넌트가 업데이트된 후에 호출됩니다.
getSnapshotBeforeUpdate에서 반환된 값에 접근할 수 있습니다.</li>
</ul>
<pre><code>componentDidUpdate(prevProps, prevState, snapshot) {
  if (snapshot !== null) {
    window.scrollTo(0, snapshot.scrollPosition);
  }
}</code></pre><br />

<h3 id="3-언마운트unmounting">3. 언마운트(Unmounting)</h3>
<p>언마운트 단계는 컴포넌트가 DOM에서 제거될 때 발생합니다. 이 단계에는 한 가지 메서드가 호출됩니다.</p>
<ul>
<li>componentWillUnmount()
컴포넌트가 DOM에서 제거되기 직전에 호출됩니다.
타이머 정리, 구독 해제 등의 작업을 수행합니다.</li>
</ul>
<pre><code>componentWillUnmount() {
  // 타이머 정리 또는 구독 해제 등
}</code></pre><br />
<hr>

<ul>
<li>라이프사이클 흐름
<code>constructor</code> -&gt; <code>render</code> -&gt; <code>componentDidMount</code> -&gt;
(번튼 누른 후) <code>increase function</code> -&gt; <code>render</code> -&gt; <code>componentDidUpdate</code>
(조건 충족) <code>increase function</code> -&gt; <code>render</code> -&gt; <code>end</code> -&gt; <code>componentDidUpdate</code><pre><code>import React, { Component } from &quot;react&quot;;
import { render } from &quot;@testing-library/react&quot;;
import BoxClass from &quot;./BoxClass&quot;;
</code></pre></li>
</ul>
<p>export default class AppClass extends Component {
  constructor(props) {
    super(props);</p>
<pre><code>// 상태를 한번에 선언
this.state = {
  count: 0,
  num: 1,
  value: 0,
};

console.log(&quot;constructor&quot;);</code></pre><p>  }</p>
<p>  increase = () =&gt; {
    this.setState((prevState) =&gt; ({
      count: prevState.count + 1,
      value: prevState.value + 2,
    }));
    console.log(&quot;increase function&quot;, this.state);
  };</p>
<p>  componentDidMount() {
    // api 콜
    console.log(&quot;componentDidMount&quot;);
  }</p>
<p>  componentDidUpdate() {
    console.log(&quot;componentDidUpdate&quot;, this.state);
  }</p>
<p>  render() {
    console.log(&quot;render&quot;);</p>
<pre><code>return (
  &lt;&gt;
    &lt;div&gt;state : {this.state.count}&lt;/div&gt;
    &lt;button onClick={this.increase}&gt;버튼&lt;/button&gt;

    {this.state.count &lt; 3 &amp;&amp; &lt;BoxClass num={this.state.value} /&gt;}
  &lt;/&gt;
);</code></pre><p>  }
}</p>
<pre><code></code></pre><p>import React, { Component } from &quot;react&quot;;</p>
<p>export default class BoxClass extends Component {
  componentWillUnmount() {
    console.log(&quot;end&quot;);
  }</p>
<p>  render() {
    return (
      <div>
        <div>value : {this.props.num}</div>
      </div>
    );
  }
}</p>
<p>```</p>
<hr>

<p>요약</p>
<blockquote>
<p>React 라이프사이클 메서드는 컴포넌트의 생성, 업데이트, 제거 단계에서 특정 작업을 수행할 수 있도록 도와줍니다. 이를 통해 컴포넌트의 상태를 관리하고, DOM과 상호작용하며, 성능을 최적화할 수 있습니다.</p>
</blockquote>
<p>이러한 메서드는 주로 클래스 컴포넌트에서 사용되지만, 함수형 컴포넌트에서는 React 훅스(Hooks)를 사용하여 비슷한 기능을 구현할 수 있습니다. 예를 들어, useEffect 훅은 componentDidMount, componentDidUpdate, componentWillUnmount를 결합한 역할을 합니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[React] 클래스 컴포넌트 vs 함수형 컴포넌트의 상태 및 메서드 접근 방식]]></title>
            <link>https://velog.io/@view_coding/React-%ED%81%B4%EB%9E%98%EC%8A%A4-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8-vs-%ED%95%A8%EC%88%98%ED%98%95-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8%EC%9D%98-%EC%83%81%ED%83%9C-%EB%B0%8F-%EB%A9%94%EC%84%9C%EB%93%9C-%EC%A0%91%EA%B7%BC-%EB%B0%A9%EC%8B%9D</link>
            <guid>https://velog.io/@view_coding/React-%ED%81%B4%EB%9E%98%EC%8A%A4-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8-vs-%ED%95%A8%EC%88%98%ED%98%95-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8%EC%9D%98-%EC%83%81%ED%83%9C-%EB%B0%8F-%EB%A9%94%EC%84%9C%EB%93%9C-%EC%A0%91%EA%B7%BC-%EB%B0%A9%EC%8B%9D</guid>
            <pubDate>Sun, 09 Jun 2024 05:53:21 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>class</p>
</blockquote>
<p>클래스 컴포넌트에는 반드시 render 메서드가 필요하며, 이 메서드는 컴포넌트의 JSX를 반환합니다.</p>
<pre><code>import React, { Component } from &#39;react&#39;;

class MyComponent extends Component {
  render() {
    return (
      &lt;div&gt;
        &lt;h1&gt;Hello, World!&lt;/h1&gt;
      &lt;/div&gt;
    );
  }
}

export default MyComponent;</code></pre><ul>
<li><p>생성자 (constructor):
상태 초기화 및 바인딩을 위해 사용됩니다.
props를 받아 super(props)를 호출하여 부모 클래스의 생성자를 호출합니다.</p>
</li>
<li><p>상태 (state):
컴포넌트의 내부 상태를 관리합니다.
상태가 변경되면 컴포넌트가 다시 렌더링됩니다.</p>
</li>
<li><p>생명주기 메서드 (Lifecycle Methods):
컴포넌트의 생성, 업데이트, 소멸 시점에 특정 작업을 수행할 수 있습니다.</p>
</li>
<li><p>렌더 메서드 (render):
JSX를 반환하여 컴포넌트의 UI를 정의합니다.</p>
</li>
</ul>
<br />

<p><strong>1. 클래스 정의</strong></p>
<pre><code>class Car {
  constructor(brand, model, year) {
    this.brand = brand;
    this.model = model;
    this.year = year;
  }

  start() {
    console.log(`${this.brand} ${this.model} is starting.`);
  }

  stop() {
    console.log(`${this.brand} ${this.model} is stopping.`);
  }
}</code></pre><p><strong>2. new 키워드로 인스턴스 생성</strong></p>
<pre><code>const car1 = new Car(&#39;Toyota&#39;, &#39;Corolla&#39;, 2020);
const car2 = new Car(&#39;Honda&#39;, &#39;Civic&#39;, 2019);

console.log(car1.brand); // &#39;Toyota&#39;
console.log(car2.model); // &#39;Civic&#39;

car1.start(); // &#39;Toyota Corolla is starting.&#39;
car2.stop();  // &#39;Honda Civic is stopping.&#39;</code></pre><p>new 키워드를 사용하여 클래스를 호출하면 <code>새로운 객체(인스턴스)</code>를 생성합니다. 이는 클래스의 생성자 메서드를 호출하고, 그 클래스에 정의된 속성과 메서드를 포함한 새로운 객체를 반환하는 과정입니다.</p>
<br />

<h3 id="--this">- this</h3>
<p>this 키워드를 사용하여 컴포넌트의 인스턴스에 접근합니다. 이는 클래스의 메서드에서 상태(state)와 속성(props)에 접근하기 위해 사용됩니다. 반면, 함수형 컴포넌트에서는 상태와 속성에 접근하기 위해 this를 사용하지 않고, 대신 훅스(Hooks)를 사용합니다.</p>
<p>클래스 컴포넌트에서 this는 컴포넌트 인스턴스를 가리킵니다. 따라서 <code>상태를 업데이트하거나 메서드를 호출할 때 this를 사용하여 컴포넌트 인스턴스의 속성에 접근</code>합니다. 이는 클래스의 특성상 필요한 접근 방식입니다.</p>
<pre><code>import React, { Component } from &#39;react&#39;;

class Counter extends Component {
  // 생성자에서 초기 상태를 설정합니다.
  constructor(props) {
    super(props);
    this.state = {
      count: 0
    };

    // 메서드 바인딩
    this.increment = this.increment.bind(this);
    this.decrement = this.decrement.bind(this);
  }

  increment() {
    this.setState((prevState) =&gt; ({
      count: prevState.count + 1
    }));
  }

  decrement() {
    this.setState((prevState) =&gt; ({
      count: prevState.count - 1
    }));
  }

  render() {
    return (
      &lt;div&gt;
        &lt;h1&gt;Counter: {this.state.count}&lt;/h1&gt;
        &lt;button onClick={this.increment}&gt;Increment&lt;/button&gt;
        &lt;button onClick={this.decrement}&gt;Decrement&lt;/button&gt;
      &lt;/div&gt;
    );
  }
}

export default Counter;</code></pre><h3 id="함수형-컴포넌트에서의-상태-관리">함수형 컴포넌트에서의 상태 관리</h3>
<p>함수형 컴포넌트는 React 훅스를 사용하여 상태와 사이드 이펙트를 관리합니다. useState 훅을 사용하여 상태를 관리하고, useEffect 훅을 사용하여 생명주기 메서드와 유사한 작업을 수행합니다. 함수형 컴포넌트에서는 this 키워드가 필요하지 않습니다.</p>
<pre><code>import React, { useState } from &#39;react&#39;;

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

  const increment = () =&gt; {
    setCount(prevCount =&gt; prevCount + 1);
  };

  const decrement = () =&gt; {
    setCount(prevCount =&gt; prevCount - 1);
  };

  return (
    &lt;div&gt;
      &lt;h1&gt;Counter: {count}&lt;/h1&gt;
      &lt;button onClick={increment}&gt;Increment&lt;/button&gt;
      &lt;button onClick={decrement}&gt;Decrement&lt;/button&gt;
    &lt;/div&gt;
  );
}

export default Counter;</code></pre><h3 id="왜-클래스-컴포넌트에서-this를-사용하는가">왜 클래스 컴포넌트에서 this를 사용하는가?</h3>
<p>클래스 문법: 클래스는 상태와 메서드를 포함하는 인스턴스를 생성합니다. this는 클래스 인스턴스를 가리키며, 이를 통해 인스턴스의 상태와 메서드에 접근합니다.</p>
<p>상태 관리: this.state를 통해 상태를 저장하고, this.setState를 통해 상태를 업데이트합니다.</p>
<p>메서드 바인딩: 클래스 메서드를 이벤트 핸들러로 사용할 때는 this가 올바르게 바인딩되도록 생성자에서 바인딩합니다.</p>
<br />

<h3 id="생명주기-메서드와-useeffect-비교">생명주기 메서드와 useEffect 비교</h3>
<ul>
<li><p>클래스 컴포넌트의 생명주기 메서드</p>
<pre><code>class MyComponent extends Component {
componentDidMount() {
  // 컴포넌트가 마운트된 후 실행
}

componentDidUpdate(prevProps, prevState) {
  // 컴포넌트가 업데이트된 후 실행
}

componentWillUnmount() {
  // 컴포넌트가 언마운트되기 직전에 실행
}

render() {
  return &lt;div&gt;My Component&lt;/div&gt;;
}
}</code></pre></li>
<li><p>함수형 컴포넌트의 useEffect</p>
<pre><code>import React, { useEffect } from &#39;react&#39;;
</code></pre></li>
</ul>
<p>function MyComponent() {
  useEffect(() =&gt; {
    // 컴포넌트가 마운트된 후 실행
    return () =&gt; {
      // 컴포넌트가 언마운트되기 직전에 실행
    };
  }, []); // 빈 배열을 두 번째 인수로 전달하여 마운트/언마운트 시점에만 실행</p>
<p>  useEffect(() =&gt; {
    // 컴포넌트가 업데이트될 때마다 실행
  });</p>
<p>  return <div>My Component</div>;
}
```</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[React] Api 키 및 토큰]]></title>
            <link>https://velog.io/@view_coding/React-Api-%ED%82%A4-%EB%B0%8F-%ED%86%A0%ED%81%B0</link>
            <guid>https://velog.io/@view_coding/React-Api-%ED%82%A4-%EB%B0%8F-%ED%86%A0%ED%81%B0</guid>
            <pubDate>Mon, 09 Oct 2023 07:37:33 GMT</pubDate>
            <description><![CDATA[<p>서버와 클라이언트 간의 안전한 통신 및 인증을 위한 중요한 구성 요소입니다.</p>
<h2 id="1-용도">1. 용도</h2>
<p>API Key: 주로 외부 서비스 또는 <code>API와 통신</code>할 때 사용됩니다. API 키는 서비스에 액세스하는 사용자나 애플리케이션을 고유하게 식별하고, API 사용량을 제한하거나 권한을 부여하는 데 사용됩니다.
Token: 주로 사용자 인증과 권한 관리에 사용됩니다. 사용자가 서비스에 로그인한 후에 발급되며, <code>사용자를 인증하고 권한을 관리</code>하는 데 사용됩니다.</p>
<br>

<h2 id="2-데이터-포함">2. 데이터 포함</h2>
<p><strong>API Key:</strong> API 키는 주로 공개적으로 공유되며, 민감한 정보를 포함하지 않는 것이 일반적입니다. API 키는 주로 HTTP 헤더나 쿼리 매개변수를 통해 전달되며, 서비스 제공 업체는 이를 사용하여 액세스를 관리합니다.
<strong>Token:</strong> 토큰은 사용자 인증 및 권한을 관리하는 데 사용되므로 민감한 정보를 포함할 수 있습니다. 주로 서버와 클라이언트 간의 안전한 통신을 위해 사용되며, HTTPS 및 토큰의 암호화를 통해 보안이 유지됩니다.</p>
<br>

<h2 id="3-보안">3. 보안</h2>
<p><strong>API Key:</strong>  API 키는 주로 공개적으로 공유되기 때문에, 노출될 경우 악용될 가능성이 있습니다. 따라서 API 키를 안전하게 보관하고 사용해야 합니다.
<strong>Token:</strong> 토큰은 사용자 인증 및 권한을 관리하는 데 사용되므로 더 많은 보안 기능을 제공합니다. JWT (JSON Web Token)와 같은 표준 형식을 사용하여 안전한 통신을 보장합니다.</p>
<br>

<h2 id="4-사용-예시">4. 사용 예시</h2>
<p><strong>API Key:</strong>  Google Maps API, Twitter API, GitHub API 등과 같이 외부 서비스나 API와 통신할 때 API 키를 사용합니다.
<strong>Token:</strong> 웹 애플리케이션에서 사용자 로그인 후에 발급되는 세션 토큰, OAuth 2.0을 통한 액세스 토큰, JSON Web Token (JWT) 등에서 토큰을 사용합니다.</p>
<br>

<blockquote>
<p>API 키는 주로 API 호출을 관리하고 API 사용량을 제한하는 데 사용되며, 토큰은 사용자 인증 및 권한 관리에 사용됩니다. 이러한 인증 및 보안 메커니즘은 웹 애플리케이션 및 웹 서비스의 안전한 운영을 위해 중요한 역할을 합니다.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[React] Promise & .get().then().catch() 비동기 작업]]></title>
            <link>https://velog.io/@view_coding/React-Promise-.get.then.catch-%EB%B9%84%EB%8F%99%EA%B8%B0-%EC%9E%91%EC%97%85</link>
            <guid>https://velog.io/@view_coding/React-Promise-.get.then.catch-%EB%B9%84%EB%8F%99%EA%B8%B0-%EC%9E%91%EC%97%85</guid>
            <pubDate>Mon, 09 Oct 2023 07:36:13 GMT</pubDate>
            <description><![CDATA[<p><code>.get</code>, <code>.then</code>, <code>.catch</code>는 JavaScript에서 프로미스(Promise)를 사용하여 <code>비동기 작업</code>을 다룰 때 사용되는 구조입니다. 비동기 작업은 일반적으로 네트워크 요청, 파일 읽기/쓰기, 데이터베이스 쿼리 등과 같이 시간이 오래 걸리거나 외부 리소스에 접근해야 하는 작업을 말합니다. </p>
<h2 id="1-get-메서드">1. .get 메서드</h2>
<pre><code>axios.get(url)</code></pre><ul>
<li>서버로부터 데이터를 가져오는데 사용됩니다.</li>
<li>주어진 URL로 GET <code>요청을 보내고, 서버에서 응답을 대기</code>합니다.</li>
</ul>
<br>

<h2 id="2-then-메서드">2. .then 메서드</h2>
<pre><code>axios.get(url)
  .then(response =&gt; {
    // 성공 시 실행할 코드
  })</code></pre><ul>
<li>프로미스 객체의 메서드로, 비동기 작업이 성공했을 때 <code>실행할 콜백 함수</code>를 등록하는데 사용됩니다.</li>
<li>비동기 작업이 완료되면 해당 작업의 <code>결과값을 인자로 받아 실행</code>합니다.</li>
<li>성공적인 작업 이후에 실행할 로직을 정의할 수 있습니다.</li>
</ul>
<br>

<h2 id="3-catch-메서드">3. .catch 메서드</h2>
<pre><code>axios.get(url)
  .then(response =&gt; {
    // 성공 시 실행할 코드
    console.log(&#39;데이터를 성공적으로 받다았습니다:&#39;, response.data);
  })
  .catch(error =&gt; {
    // 에러 시 실행할 코드
    console.error(&#39;요청 중 에러 발생:&#39;, error);
  })</code></pre><ul>
<li>프로미스 객체의 메서드로, 비동기 작업에서 에러가 발생했을 때 실행할 콜백 함수를 등록하는데 사용됩니다.</li>
<li>에러 처리 로직을 정의할 수 있습니다.</li>
<li>.then 체인 내에서 에러가 발생하면 .catch 블록으로 이동하여 에러를 처리합니다.</li>
</ul>
<br>
<hr>
<br>

<p><strong>※ 토큰을 사용하여 인증하고 GET 및 POST 요청을 보내는 예제 코드</strong></p>
<pre><code>import React, { useEffect, useState } from &#39;react&#39;;
import axios from &#39;axios&#39;;

function App() {
  const [data, setData] = useState([]);
  const [token, setToken] = useState(&#39;&#39;); // 토큰 상태

  useEffect(() =&gt; {
    // 서버에서 토큰을 발급하거나 저장된 토큰을 가져와서 설정합니다.
    // 로그인 또는 인증 후에 토큰을 설정하는 부분입니다.
    const userToken = &#39;your_jwt_token_here&#39;;
    setToken(userToken);

    // GET
    axios.get(&#39;https://api.example.com/data&#39;, {
      headers: {
        &#39;Authorization&#39;: `Bearer ${token}` // JWT 토큰을 헤더에 포함 (토큰 인증)
      }
    })
      .then(response =&gt; {
        setData(response.data);
      })
      .catch(error =&gt; {
        console.error(&#39;GET 요청 에러:&#39;, error);
      });

    // POST
    const postData = {
      username: &#39;example_user&#39;,
      password: &#39;example_password&#39;
    };

    axios.post(&#39;https://api.example.com/login&#39;, postData, {
      headers: {
        &#39;Authorization&#39;: `Bearer ${token}` // JWT 토큰을 헤더에 포함 (토큰 인증)
      }
    })
      .then(response =&gt; {
        console.log(&#39;로그인 결과:&#39;, response.data);
      })
      .catch(error =&gt; {
        console.error(&#39;POST 요청 에러:&#39;, error);
      });
  }, [token]);

  return (
    &lt;div className=&quot;App&quot;&gt;
      &lt;h1&gt;인증 및 API 요청 예제&lt;/h1&gt;
      &lt;ul&gt;
        {data.map(item =&gt; (
          &lt;li key={item.id}&gt;{item.name}&lt;/li&gt;
        ))}
      &lt;/ul&gt;
    &lt;/div&gt;
  );
}

export default App;</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[React] localStorage 브라우저에 데이터 저장하기 (로컬스토리지)]]></title>
            <link>https://velog.io/@view_coding/React-localStorage-%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80%EC%97%90-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%A0%80%EC%9E%A5%ED%95%98%EA%B8%B0-%EB%A1%9C%EC%BB%AC%EC%8A%A4%ED%86%A0%EB%A6%AC%EC%A7%80</link>
            <guid>https://velog.io/@view_coding/React-localStorage-%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80%EC%97%90-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%A0%80%EC%9E%A5%ED%95%98%EA%B8%B0-%EB%A1%9C%EC%BB%AC%EC%8A%A4%ED%86%A0%EB%A6%AC%EC%A7%80</guid>
            <pubDate>Sun, 27 Aug 2023 11:22:42 GMT</pubDate>
            <description><![CDATA[<h1 id="로컬-스토리지local-storage❓">로컬 스토리지(Local Storage)❓</h1>
<p><code>웹 브라우저에서 제공하는 클라이언트 측 데이터 저장소</code>입니다. 이 저장소는 도메인과 관련된 작은 데이터를 사용자의 브라우저 내에 지속적으로 저장할 수 있도록 해줍니다. 로컬 스토리지는 쿠키보다 더 많은 용량을 가지며, 서버로 데이터를 전송하지 않고도 웹 애플리케이션의 상태나 사용자 정보 등을 유지할 수 있습니다.</p>
<h3 id="1-용량">1. 용량</h3>
<p>:로컬 스토리지의 용량은 브라우저별로 다를 수 있지만, 일반적으로 <code>5MB</code> 정도의 용량을 가집니다.</p>
<h3 id="2-동일한-출처">2. 동일한 출처</h3>
<p>:로컬 스토리지는 동일 출처 정책에 따라 동일한 도메인(프로토콜, 도메인, 포트) 내에서만 접근할 수 있습니다.</p>
<h3 id="3-키-값-쌍-저장">3. 키-값 쌍 저장</h3>
<p>:로컬 스토리지는 <code>키(key)와 값(value)의 쌍으로 데이터를 저장</code>합니다. 모두 문자열 형태로 저장됩니다.</p>
<h3 id="4-세션과-관련-없음">4. 세션과 관련 없음</h3>
<p>:로컬 스토리지에 저장된 데이터는 브라우저 세션이 끝나더라도 유지됩니다.</p>
<h3 id="5-데이터-유형문자열-형태">5. 데이터 유형(문자열 형태)</h3>
<p>:로컬 스토리지에는 문자열 형태로만 데이터를 저장할 수 있습니다. <code>객체나 배열과 같은 복잡한 데이터 구조는 JSON 형식으로 변환하여 저장하고 다시 파싱하여 사용</code>해야 합니다.</p>
<h3 id="6-api">6. API</h3>
<p>:로컬 스토리지를 조작하기 위해 localStorage 객체를 사용합니다. localStorage.setItem(key, value)로 데이터를 저장하고, localStorage.getItem(key)로 데이터를 불러옵니다. localStorage.removeItem(key)로 데이터를 삭제할 수 있습니다.</p>
<p>로컬 스토리지는 간단한 데이터를 저장하거나 브라우저 상태를 관리하는 데 유용합니다. 예를 들어 <code>사용자 설정, 로그인 정보, 애플리케이션 상태</code> 등을 저장하고 유지할 수 있습니다. 하지만 <code>보안적인 이슈에 주의</code>해야 하며, 중요한 개인 정보나 보안에 민감한 데이터를 저장할 때는 보안 대책을 강구해야 합니다.</p>
<pre><code>// 복잡한 데이터 구조 생성
const user = {
  id: 123,
  name: &#39;John Doe&#39;,
  email: &#39;john@example.com&#39;
};

// 데이터를 문자열로 변환하여 로컬 스토리지에 저장
localStorage.setItem(&#39;user&#39;, JSON.stringify(user));

// 로컬 스토리지에서 데이터 불러오기 후 JSON 파싱
const storedUser = localStorage.getItem(&#39;user&#39;);
const parsedUser = JSON.parse(storedUser);
// &#39;JSON.parse()&#39; 함수를 사용하며, 이 함수는 문자열 형태의 JSON 데이터를 JavaScript 객체로 변환 -&gt; 객체의 속성을 통해 데이터에 접근하고 조작

console.log(parsedUser);
// 출력: { id: 123, name: &#39;John Doe&#39;, email: &#39;john@example.com&#39; }</code></pre><br>

<h3 id="✔️-할일-목록을-유지하고-관리하는-예시코드">✔️ 할일 목록을 유지하고 관리하는 예시코드</h3>
<p><strong>jsx 코드</strong></p>
<pre><code class="language-jsx">import React, { useState, useEffect } from &#39;react&#39;;

function TodoApp() {
  const [todos, setTodos] = useState([]);
  const [newTodo, setNewTodo] = useState(&#39;&#39;);

  useEffect(() =&gt; {
    const storedTodos = localStorage.getItem(&#39;todos&#39;);
    if (storedTodos) {
      setTodos(JSON.parse(storedTodos));
    }
  }, []);

  useEffect(() =&gt; {
    localStorage.setItem(&#39;todos&#39;, JSON.stringify(todos));
  }, [todos]);

  const addTodo = () =&gt; {
    if (newTodo.trim() !== &#39;&#39;) {
      setTodos([...todos, newTodo]);
      setNewTodo(&#39;&#39;);
    }
  };

  const removeTodo = index =&gt; {
    const updatedTodos = todos.filter((_, i) =&gt; i !== index);
    setTodos(updatedTodos);
  };

  return (
    &lt;div&gt;
      &lt;h1&gt;Todo List&lt;/h1&gt;
      &lt;ul&gt;
        {todos.map((todo, index) =&gt; (
          &lt;li key={index}&gt;
            {todo}
            &lt;button onClick={() =&gt; removeTodo(index)}&gt;Remove&lt;/button&gt;
          &lt;/li&gt;
        ))}
      &lt;/ul&gt;
      &lt;div&gt;
        &lt;input
          type=&quot;text&quot;
          value={newTodo}
          onChange={e =&gt; setNewTodo(e.target.value)}
          placeholder=&quot;Add a new todo&quot;
        /&gt;
        &lt;button onClick={addTodo}&gt;Add&lt;/button&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  );
}

export default TodoApp;</code></pre>
<p>useState 후크를 사용하여 할일 목록(todos)과 새로운 할일을 입력받을 때 사용되는 상태(newTodo)를 관리합니다. 또한 useEffect 후크를 사용하여 페이지 로드 시 로컬 스토리지에서 데이터를 불러오고, 할일 목록이 변경될 때마다 데이터를 저장합니다.</p>
<br>

<p><strong>tsx 코드</strong></p>
<pre><code class="language-tsx">import React, { useState, useEffect } from &#39;react&#39;;

interface Todo {
  id: number;
  text: string;
}

function TodoApp() {
  const [todos, setTodos] = useState&lt;Todo[]&gt;([]);
  const [newTodo, setNewTodo] = useState&lt;string&gt;(&#39;&#39;);

  useEffect(() =&gt; {
    const storedTodos = localStorage.getItem(&#39;todos&#39;);
    if (storedTodos) {
      setTodos(JSON.parse(storedTodos));
    }
  }, []);

  useEffect(() =&gt; {
    localStorage.setItem(&#39;todos&#39;, JSON.stringify(todos));
  }, [todos]);

  const addTodo = () =&gt; {
    if (newTodo.trim() !== &#39;&#39;) {
      const newId = todos.length &gt; 0 ? todos[todos.length - 1].id + 1 : 1;
      const newTodoItem: Todo = { id: newId, text: newTodo };
      setTodos([...todos, newTodoItem]);
      setNewTodo(&#39;&#39;);
    }
  };

  const removeTodo = (id: number) =&gt; {
    const updatedTodos = todos.filter(todo =&gt; todo.id !== id);
    setTodos(updatedTodos);
  };

  return (
    &lt;div&gt;
      &lt;h1&gt;Todo List&lt;/h1&gt;
      &lt;ul&gt;
        {todos.map(todo =&gt; (
          &lt;li key={todo.id}&gt;
            {todo.text}
            &lt;button onClick={() =&gt; removeTodo(todo.id)}&gt;Remove&lt;/button&gt;
          &lt;/li&gt;
        ))}
      &lt;/ul&gt;
      &lt;div&gt;
        &lt;input
          type=&quot;text&quot;
          value={newTodo}
          onChange={e =&gt; setNewTodo(e.target.value)}
          placeholder=&quot;Add a new todo&quot;
        /&gt;
        &lt;button onClick={addTodo}&gt;Add&lt;/button&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  );
}

export default TodoApp;</code></pre>
<br>
<br>

<h3 id="한줄-요약-👩🔧">한줄 요약 👩‍🔧</h3>
<blockquote>
<p>로컬 스토리지는 브라우저에서 제공하는 작은 데이터 저장소로, 웹 애플리케이션의 클라이언트 측에서 도메인과 관련된 데이터를 유지하며, key-value 쌍의 형태로 문자열 형태로 데이터를 저장하고 불러올 수 있습니다.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[React] axios 와 useQuery (api 통신)]]></title>
            <link>https://velog.io/@view_coding/React-axios-%EC%99%80-useQuery-api-%ED%86%B5%EC%8B%A0</link>
            <guid>https://velog.io/@view_coding/React-axios-%EC%99%80-useQuery-api-%ED%86%B5%EC%8B%A0</guid>
            <pubDate>Tue, 08 Aug 2023 06:16:49 GMT</pubDate>
            <description><![CDATA[<p>axios와 useQuery는 각각 다른 상황에 더 유용하게 사용할 수 있는 라이브러리 및 훅입니다.</p>
<h2 id="📌-axios">📌 axios</h2>
<ul>
<li><p>axios는 네트워크 요청을 처리하는 데 강력한 도구입니다.</p>
</li>
<li><p>주로 서버와의 통신, REST API 호출, 외부 데이터 요청 등에 사용됩니다.</p>
</li>
<li><p>복잡한 요청이나 다양한 상황에서 더 많은 제어를 필요로 할 때 유용합니다.</p>
</li>
<li><p>요청 및 응답의 인터셉트, 헤더 설정, 인증 처리 등을 수행할 수 있습니다.</p>
</li>
</ul>
</br>

<p><strong>axios를 사용한 TypeScript 코드</strong></p>
<pre><code class="language-tsx">import React, { useState, useEffect } from &#39;react&#39;;
import axios from &#39;axios&#39;;

interface User {
  id: number;
  name: string;
}

function UserListAxios() {
  const [users, setUsers] = useState&lt;User[]&gt;([]);

  useEffect(() =&gt; {
    async function fetchUsers() {
      try {
        const response = await axios.get&lt;User[]&gt;(&#39;https://api.example.com/users&#39;);
        setUsers(response.data);
      } catch (error) {
        console.error(&#39;Error fetching users:&#39;, error);
      }
    }

    fetchUsers();
  }, []);

  return (
    &lt;div&gt;
      &lt;h1&gt;User List using Axios&lt;/h1&gt;
      &lt;ul&gt;
        {users.map((user) =&gt; (
          &lt;li key={user.id}&gt;{user.name}&lt;/li&gt;
        ))}
      &lt;/ul&gt;
    &lt;/div&gt;
  );
}

export default UserListAxios;</code></pre>
</br>
<hr>
</br>

<h2 id="📌-usequery-react-query-라이브러리의-기능">📌 useQuery (React Query 라이브러리의 기능)</h2>
<ul>
<li><p>useQuery는 React Query 라이브러리에 내장된 훅으로, 데이터 관리 및 캐싱에 유용합니다.</p>
</li>
<li><p>주로 컴포넌트의 데이터 요청 및 캐싱 관리를 간편하게 할 때 사용됩니다.</p>
</li>
<li><p>빠른 데이터 갱신, 자동 재요청, 캐시 관리 등을 자동으로 처리합니다.</p>
</li>
<li><p>데이터를 가져오는 동안 로딩 및 에러 상태를 자동으로 관리합니다.</p>
</li>
</ul>
</br>

<p><strong>useQuery를 사용한 TypeScript 코드 (React Query)</strong></p>
<pre><code class="language-tsx">import React from &#39;react&#39;;
import { useQuery } from &#39;react-query&#39;;
import axios from &#39;axios&#39;;

interface User {
  id: number;
  name: string;
}

const UserListUseQuery: React.FC = () =&gt; {
  const { data: users, isLoading, isError } = useQuery&lt;User[]&gt;(&#39;users&#39;, async () =&gt; {
    try {
      const response = await axios.get&lt;User[]&gt;(&#39;https://api.example.com/users&#39;);
      return response.data;
    } catch (error) {
      throw new Error(&#39;Error fetching users&#39;);
    }
  });

  return (
    &lt;div&gt;
      &lt;h1&gt;User List using useQuery and Axios&lt;/h1&gt;
      {isLoading ? (
        &lt;p&gt;Loading...&lt;/p&gt;
      ) : isError ? (
        &lt;p&gt;Error fetching users&lt;/p&gt;
      ) : (
        &lt;ul&gt;
          {users.map((user) =&gt; (
            &lt;li key={user.id}&gt;{user.name}&lt;/li&gt;
          ))}
        &lt;/ul&gt;
      )}
    &lt;/div&gt;
  );
};

export default UserListUseQuery;</code></pre>
<p>외부 API에서 사용자 목록을 가져오고 표시하는 예시 코드로 두 예시 모두 데이터를 가져오지만, <code>useQuery</code>를 사용한 코드에서는 <code>데이터를 자동으로 캐싱하고 로딩 및 에러 상태를 관리</code>하는 부분을 라이브러리가 처리해주기 때문에 더 간결하고 편리합니다.</p>
<blockquote>
<p>useQuery는 내부적으로 useEffect를 사용하여 데이터를 가져오고 관리합니다. 따라서 별도로 useEffect를 사용하여 데이터를 가져올 필요가 없습니다. useQuery는 데이터를 관리하고 갱신하는 데에 더 간편한 방법을 제공합니다.</p>
</blockquote>
</br>

<h3 id="🧐-상황에-따라-유용한-라이브러리">🧐 상황에 따라 유용한 라이브러리</h3>
<ul>
<li><p>axios는 서버와의 복잡한 통신이 필요한 경우나 다양한 인증, 헤더 설정 등을 다룰 때 유용합니다.</p>
</li>
<li><p>useQuery는 컴포넌트 내에서 데이터를 가져오고 관리해야 할 때, 특히 UI와 상태 관리를 간편하게 하고자 할 때 유용합니다. React Query의 자동 캐싱 및 데이터 갱신 기능을 활용하면 데이터 관리를 효율적으로 할 수 있습니다.</p>
</li>
</ul>
</br>

<p>두 라이브러리는 상황에 따라 조합해서 사용할 수도 있습니다. 예를 들어, axios로 외부 데이터를 가져온 다음, 그 데이터를 useQuery로 관리하거나 캐싱할 수 있습니다. 상황과 프로젝트의 요구에 따라 적절한 라이브러리를 선택하여 사용하면 됩니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[typescript] 함수의 리턴 값 타입 지정 (Function Type)]]></title>
            <link>https://velog.io/@view_coding/typescript-%ED%95%A8%EC%88%98%EC%9D%98-%EB%A6%AC%ED%84%B4-%EA%B0%92-%ED%83%80%EC%9E%85-%EC%A7%80%EC%A0%95-Function-Type</link>
            <guid>https://velog.io/@view_coding/typescript-%ED%95%A8%EC%88%98%EC%9D%98-%EB%A6%AC%ED%84%B4-%EA%B0%92-%ED%83%80%EC%9E%85-%EC%A7%80%EC%A0%95-Function-Type</guid>
            <pubDate>Tue, 08 Aug 2023 05:47:53 GMT</pubDate>
            <description><![CDATA[<h2 id="1-리턴-타입-지정">1. 리턴 타입 지정</h2>
<h3 id="리턴값의-타입을-지정한-경우">리턴값의 타입을 지정한 경우</h3>
<pre><code class="language-ts">function calculateSum(numbers: number[]): number {
  return numbers.reduce((sum, num) =&gt; sum + num, 0);
}

const result: number = calculateSum([1, 2, 3, 4, 5]);
console.log(result); // Output: 15</code></pre>
</br>

<h3 id="리턴값의-타입을-지정하지-않은-경우">리턴값의 타입을 지정하지 않은 경우</h3>
<pre><code class="language-ts">function calculateSum(numbers: number[]) {
  return numbers.reduce((sum, num) =&gt; sum + num, 0);
}

const result = calculateSum([1, 2, 3, 4, 5]);
console.log(result); // Output: 15</code></pre>
</br>

<h3 id="🤔-차이점">🤔 차이점</h3>
<p><strong>리턴값의 타입을 지정한 경우:</strong> 함수가 number 타입의 값을 반환한다는 것을 명시적으로 나타냅니다. 코드를 읽는 사람들은 함수의 리턴값이 항상 숫자라는 것을 확신할 수 있습니다.</p>
<p><strong>리턴값의 타입을 지정하지 않은 경우:</strong> TypeScript는 배열의 숫자들을 더한 결과값을 타입 추론을 통해 결정합니다. 일반적으로는 결과값이 숫자로 추론될 것입니다. 그러나 <code>TypeScript가 확신을 가지지 못할 경우, 추론된 타입은 보다 일반적인 유니온 타입</code>이 될 수 있습니다.</p>
</br>

<p>따라서 대부분의 상황에서 TypeScript가 추론한 타입은 맞을 수 있지만, 가끔씩은 의도하지 않은 동작이 발생할 수 있습니다. 이는 TypeScript가 추론한 타입을 기반으로 코드를 분석하고 타입 검사를 수행하기 때문입니다. 따라서 <code>명시적인 타입 지정을 통해 의도하지 않은 동작을 방지하고 코드의 가독성을 높일 수 있습니다.</code></p>
<br>
<hr>
<br>

<h2 id="2-단일-객체의-타입과-여러-객체가-담긴-배열의-타입-지정">2. 단일 객체의 타입과 여러 객체가 담긴 배열의 타입 지정</h2>
<p><code>&lt;user&gt;</code>는 단일 객체 또는 값에 대한 타입을 지정하는 것을 나타냅니다. 예를 들어, 단일 사용자 정보를 표현하는 객체의 타입을 정의할 때 사용할 수 있습니다. </p>
<pre><code class="language-ts">type User = {
  id: number;
  name: string;
  age: number;
};</code></pre>
<p>&lt;/ br&gt;</p>
<p><code>&lt;user[]&gt;</code>는 배열에 포함된 여러 사용자 객체에 대한 타입을 지정하는 것을 나타냅니다. 배열 안에 여러 사용자 정보가 있는 경우에 사용됩니다.</p>
<pre><code class="language-ts">type User = {
  id: number;
  name: string;
  age: number;
};

const users: User[] = [
  { id: 1, name: &quot;Alice&quot;, age: 25 },
  { id: 2, name: &quot;Bob&quot;, age: 30 },
  // ...
];</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[typescript] 타입스크립트의 타입 정의 (인터페이스 | 타입 | 리터널 타입 | 유니온 타입 | 인터섹션 타입 | 열거형)]]></title>
            <link>https://velog.io/@view_coding/typescript-%ED%83%80%EC%9E%85%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EC%9D%98-%ED%83%80%EC%9E%85-%EC%A0%95%EC%9D%98-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4-%ED%83%80%EC%9E%85-%EB%A6%AC%ED%84%B0%EB%84%90-%ED%83%80%EC%9E%85-%EC%9C%A0%EB%8B%88%EC%98%A8-%ED%83%80%EC%9E%85-%EC%9D%B8%ED%84%B0%EC%84%B9%EC%85%98-%ED%83%80%EC%9E%85-%EC%97%B4%EA%B1%B0%ED%98%95</link>
            <guid>https://velog.io/@view_coding/typescript-%ED%83%80%EC%9E%85%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EC%9D%98-%ED%83%80%EC%9E%85-%EC%A0%95%EC%9D%98-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4-%ED%83%80%EC%9E%85-%EB%A6%AC%ED%84%B0%EB%84%90-%ED%83%80%EC%9E%85-%EC%9C%A0%EB%8B%88%EC%98%A8-%ED%83%80%EC%9E%85-%EC%9D%B8%ED%84%B0%EC%84%B9%EC%85%98-%ED%83%80%EC%9E%85-%EC%97%B4%EA%B1%B0%ED%98%95</guid>
            <pubDate>Thu, 03 Aug 2023 06:50:39 GMT</pubDate>
            <description><![CDATA[<p>타입스크립트에서 정의하는 타입에는 여러 가지가 있습니다. </p>
<h2 id="📌-인터페이스interface">📌 인터페이스(Interface)</h2>
<p>: <code>객체의 구조를 정의하는 타입</code>입니다. <code>확장이 가능</code>합니다.
특정 객체가 인터페이스의 구조를 따르도록 강제할 수 있으며, 코드의 가독성과 재사용성을 높입니다.</p>
<pre><code>interface Person {
  name: string;
  age: number;
}

const john: Person = { name: &quot;John&quot;, age: 30 };</code></pre></br>

<h2 id="📌-타입type">📌 타입(Type)</h2>
<p>: 인터페이스와 유사하게 객체의 구조를 정의하는 타입입니다. 인터페이스와의 주요 차이점은 <code>type은  객체, 유니온 타입, 튜플, 함수 등 여러 가지 형태의 타입을 정의할 수 있지만, interface는 더욱 객체에 특화</code>되어 있습니다.</p>
<pre><code>type Point = {
  x: number;
  y: number;
};

const origin: Point = { x: 0, y: 0 };</code></pre></br>

<h3 id="✔️인터페이스-vs-타입의-차이점🤔">✔️인터페이스 vs 타입의 차이점🤔</h3>
<p><strong>1. 확장(Extends) 기능</strong></p>
<pre><code>// interface
interface Shape {
  color: string;
}

interface Circle extends Shape {
  radius: number;
}

const circle: Circle = { color: &quot;red&quot;, radius: 5 };</code></pre><pre><code>// type
type ShapeType = {
  color: string;
};

type CircleType = ShapeType &amp; {
  radius: number;
};

const circle: CircleType = { color: &quot;red&quot;, radius: 5 };</code></pre><p><code>인터페이스는 extends</code> 키워드를 사용하여 다른 인터페이스를 확장할 수 있습니다. 반면, <code>타입은 인터섹션(&amp;)</code>을 사용하여 다른 타입과 결합하여 새로운 타입을 생성합니다.</p>
</br>

<p><strong>2. 선언 합치기</strong></p>
<pre><code>// interface
interface Fruit {
  name: string;
}

interface Fruit {
  color: string;
}

const apple: Fruit = { name: &quot;Apple&quot;, color: &quot;red&quot; };</code></pre><pre><code>// type
type Vegetable = {
  name: string;
};

type Vegetable = {
  color: string;
};

const carrot: Vegetable = { name: &quot;Carrot&quot;, color: &quot;orange&quot; };  // 오류</code></pre><p>인터페이스는 같은 이름으로 여러 번 선언될 때, 해당 이름의 인터페이스가 확장되어 합쳐집니다. 반면, 타입은 같은 이름으로 선언하면 오류가 발생합니다.</p>
</br>
<hr>
</br>

<h2 id="📌-리터널-타입literal-types">📌 리터널 타입(Literal Types)</h2>
<p>: 리터널 타입은 특정 값을 정확히 나타내기 위해 사용되는 타입으로, 문자열, 숫자, 불리언 등의 값들을 나타낼 수 있습니다.</p>
<pre><code>const myString: &quot;Hello&quot; = &quot;Hello&quot;; // 문자열 리터럴 타입
const myNumber: 42 = 42; // 숫자 리터럴 타입
const myBoolean: true = true; // 불리언 리터럴 타입</code></pre><p>리터널 타입은 특정 값을 지정할 수 있으므로, <code>해당 값 외에 다른 값은 할당할 수 없습니다</code>. 이러한 특성으로 오타를 방지하고 정확한 값을 보장할 수 있습니다.</p>
</br>
<hr>
</br>

<h2 id="📌-유니온-타입union-types">📌 유니온 타입(Union Types)</h2>
<p>: 유니온 타입은 <code>여러 개의 타입 중 하나를 허용</code>하는 타입으로, | 기호를 사용하여 정의합니다. 유니온 타입은 여러 타입의 조합을 표현하며, 해당 타입 중 하나의 값이 할당될 수 있습니다.</p>
<pre><code>let myVariable: number | string; // 유니온 타입

myVariable = 42; // 유효
myVariable = &quot;Hello&quot;; // 유효
myVariable = true; // 에러: boolean 타입은 허용되지 않음</code></pre><p>유니온 타입은 다양한 타입의 값들을 처리할 수 있으며, 각각의 타입을 따로 명시할 필요 없이 한 변수에서 다양한 타입을 처리할 수 있습니다.</p>
</br>

<h3 id="✔️리터널-타입-vs-유니온-타입의-차이점🤔">✔️리터널 타입 vs 유니온 타입의 차이점🤔</h3>
<p>리터널 타입은 특정 값을 정확하게 나타내기 위해 사용됩니다. 해당 값 외에 다른 값을 할당할 수 없습니다.
유니온 타입은 여러 개의 타입 중 하나를 허용하는 타입으로, 각각의 타입을 |로 연결하여 정의합니다. 다양한 타입의 값을 처리할 수 있습니다.</p>
</br>
<hr>
</br>

<h2 id="📌-인터섹션-타입intersection-types">📌 인터섹션 타입(Intersection Types)</h2>
<p>: <code>두 개 이상의 타입을 결합</code>하여 새로운 타입을 생성합니다. 인터페이스와 타입의 속성들을 합치는 데 사용됩니다.</p>
<pre><code>interface A {
  propA: number;
}

interface B {
  propB: string;
}

type CombinedType = A &amp; B;

const obj: CombinedType = { propA: 42, propB: &quot;Hello&quot; };</code></pre></br>
<hr>
</br>

<h2 id="📌-열거형enum">📌 열거형(Enum)</h2>
<p>: <code>특정 값에 이름을 부여</code>하는 것으로, 숫자 또는 문자열 값의 <code>집합</code>을 나타냅니다.</p>
<p>※숫자 기반 emum 예시</p>
<pre><code class="language-ts">enum Direction {
  Up, // 0
  Down, // 1
  Left, // 2
  Right, // 3
}

const move = (direction: Direction) =&gt; {
  if (direction === Direction.Up) {
    console.log(&quot;Moving up&quot;);
  } else if (direction === Direction.Down) {
    console.log(&quot;Moving down&quot;);
  } else if (direction === Direction.Left) {
    console.log(&quot;Moving left&quot;);
  } else if (direction === Direction.Right) {
    console.log(&quot;Moving right&quot;);
  } else {
    console.log(&quot;Invalid direction&quot;);
  }
};

move(Direction.Up); // 출력: &quot;Moving up&quot;
move(Direction.Right); // 출력: &quot;Moving right&quot;
move(2); // 출력: &quot;Moving left&quot; (숫자 기반 enum은 역참조도 가능합니다)</code></pre>
<p><code>숫자 기반 enum에서는 역참조(reverse mapping)가 지원되기 때문에 숫자 값을 사용</code>하여 enum 멤버를 참조할 수 있습니다.</p>
</br>

<p>※문자열 기반 enum 예시</p>
<pre><code class="language-ts">enum Color {
  Red = &quot;RED&quot;,
  Green = &quot;GREEN&quot;,
  Blue = &quot;BLUE&quot;,
}

const setColor = (color: Color) =&gt; {
  if (color === Color.Red) {
    console.log(&quot;Set color to red&quot;);
  } else if (color === Color.Green) {
    console.log(&quot;Set color to green&quot;);
  } else if (color === Color.Blue) {
    console.log(&quot;Set color to blue&quot;);
  } else {
    console.log(&quot;Invalid color&quot;);
  }
}

setColor(Color.Red); // 출력: &quot;Set color to red&quot;
setColor(&quot;GREEN&quot;); // 출력: &quot;Set color to green&quot; (문자열 기반 enum도 역참조 가능)</code></pre>
<p>문자열 기반 enum은 <code>각 멤버에 문자열 값을 직접 할당</code>합니다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[React] 미들웨어(middleware) : redux-thunk & redux-logger 란?]]></title>
            <link>https://velog.io/@view_coding/React-%EB%AF%B8%EB%93%A4%EC%9B%A8%EC%96%B4middleware%EB%9E%80</link>
            <guid>https://velog.io/@view_coding/React-%EB%AF%B8%EB%93%A4%EC%9B%A8%EC%96%B4middleware%EB%9E%80</guid>
            <pubDate>Thu, 20 Jul 2023 07:52:17 GMT</pubDate>
            <description><![CDATA[<h1 id="미들웨어란❓">미들웨어란❓</h1>
<p><img src="https://velog.velcdn.com/images/view_coding/post/ec34e52f-b702-4fc0-97b2-68f9b58f2717/image.png" alt=""></p>
<p>리덕스(또는 다른 상태 관리 라이브러리)에서 <code>액션이 디스패치(dispatch)되어서 리듀서에 도달하기 전에 가로채고 처리하는 함수</code>로 미들웨어는 액션과 리듀서 사이의 중간자라고 볼 수 있다.. 미들웨어는 액션과 상태 사이에서 동작하여 액션을 로깅하거나, 비동기 작업을 처리하거나, 특정 조건에 따라 액션을 수정하는 등의 기능을 추가적으로 수행할 수 있습니다.</p>
</br>

<h3 id="필요한-이유">필요한 이유?</h3>
<ul>
<li><p><strong>비동기 작업 처리</strong>: 네트워크 요청이나 데이터베이스 접근과 같은 비동기 작업을 처리할 수 있습니다. Redux에서는 기본적으로 동기적으로 작동하므로, 미들웨어를 사용하여 비동기 작업을 처리할 수 있게 됩니다.</p>
</li>
<li><p><strong>로깅</strong>: 액션을 디스패치할 때 미들웨어를 이용하여 액션의 정보를 로그에 남기는 등의 로깅 작업을 할 수 있습니다.</p>
</li>
<li><p><strong>예외 처리</strong>: 액션이나 상태 처리 중에 발생하는 예외를 캐치하여 처리할 수 있습니다.</p>
</li>
<li><p><strong>암호화 및 보안</strong>: 액션의 내용을 암호화하거나 보안을 강화하는 등의 작업을 할 수 있습니다.</p>
</li>
</ul>
</br>

<h3 id="사용하는-법">사용하는 법</h3>
<p>Redux 미들웨어를 사용하려면 <code>applyMiddleware</code> 함수를 사용하여 미들웨어를 스토어에 등록해주어야 합니다. 미들웨어는 createStore 함수의 세 번째 매개변수로 전달되어야 합니다.</p>
<pre><code class="language-tsx">import { createStore, applyMiddleware } from &#39;redux&#39;;
import thunkMiddleware from &#39;redux-thunk&#39;; // 예시로 redux-thunk 미들웨어를 사용

const store = createStore(reducer, applyMiddleware(thunkMiddleware));</code></pre>
</br>

<h2 id="🧐-대표적인-redux-middleware">🧐 대표적인 redux middleware</h2>
<h3 id="1-redux-thunk">1. Redux Thunk</h3>
<p>: 가장 널리 사용되는 Redux 미들웨어 중 하나입니다. 비동기 작업을 처리하기 위해 사용됩니다. Redux Thunk를 사용하면 액션 생성자 함수에서 일반 객체 대신 함수를 반환할 수 있습니다. <code>이 함수는 Redux 스토어의 dispatch 메서드를 사용하여 다른 액션을 디스패치하거나 비동기 작업을 수행</code>할 수 있습니다. 주로 네트워크 요청과 같은 비동기 작업을 처리할 때 유용합니다.</p>
<h3 id="2-redux-saga">2. Redux Saga</h3>
<p>: Redux 애플리케이션에서 비동기 작업을 처리하기 위한 미들웨어로, Generator 함수를 기반으로 동작합니다. Redux Saga는 <code>액션을 모니터링하고, 특정 액션이 발생했을 때 사가(Saga) 함수를 실행하여 비동기 작업을 처리</code>합니다. Redux Saga를 사용하면 비동기 작업의 흐름을 관리하기 쉽고, 복잡한 비동기 로직을 보다 간결하고 유지보수하기 쉽게 구현할 수 있습니다.</p>
<h3 id="3-redux-logger">3. Redux Logger</h3>
<p>: 개발 시 디버깅을 도와주는 미들웨어로, Redux의 액션과 상태에 대한 정보를 콘솔에 로깅합니다. 액션 디스패치 시점, 액션의 타입, 액션의 페이로드, 상태의 변화 등을 쉽게 추적하고 분석할 수 있습니다. 주로 개발 환경에서 사용되며, 배포할 때는 비활성화하여 성능에 영향을 미치지 않도록 합니다.</p>
<h3 id="4-redux-promise-middleware">4. Redux Promise Middleware</h3>
<p>: 비동기 작업을 처리하기 위한 미들웨어로, Redux Thunk와 유사한 방식으로 액션 생성자 함수에서 프로미스(Promise)를 반환하여 비동기 작업을 처리합니다. 프로미스가 완료될 때까지 액션을 대기하고, 프로미스가 성공하면 성공 액션을 디스패치하고, 실패하면 실패 액션을 디스패치합니다. Redux Thunk와 비교하여 간단한 사용법을 제공합니다.</p>
<h3 id="5-redux-persist">5. Redux Persist</h3>
<p>: 애플리케이션의 상태를 로컬 스토리지 또는 장치에 저장하는 미들웨어로, 새로고침이나 앱을 종료해도 상태가 유지되도록 합니다. 주로 사용자가 로그인 상태를 유지하거나, 앱의 설정과 같은 상태를 지속적으로 관리하는 데 사용됩니다.</p>
</br>

<p>이 외에도 많은 Redux 미들웨어들이 있으며, Redux 개발자들이 필요에 따라 커스텀 미들웨어를 작성하여 사용할 수도 있습니다. Redux 미들웨어는 Redux의 확장성과 유연성을 높여주는 중요한 기능이며, 다양한 비동기 작업과 기능들을 효율적으로 관리하는 데 도움을 줍니다.</p>
</br>
<hr>
</br>

<h2 id="📌-redux-logger-사용법❓">📌 Redux-Logger 사용법❓</h2>
<h3 id="1-미들웨어-등록">1. 미들웨어 등록</h3>
<pre><code class="language-tsx">import { createStore, applyMiddleware } from &#39;redux&#39;;
import loggerMiddleware from &#39;redux-logger&#39;; // redux-logger 미들웨어 임포트
import rootReducer from &#39;./reducers&#39;; // 리듀서 파일 임포트

const store = createStore(rootReducer, applyMiddleware(loggerMiddleware));</code></pre>
</br>

<h3 id="2-콘솔-로그-출력-설정">2. 콘솔 로그 출력 설정</h3>
<p>: 기본적으로 Redux Logger는 <code>모든 액션에 대한 로그를 출력</code>합니다. 하지만 필요에 따라 로그 출력을 조절할 수 있습니다.</p>
<ul>
<li><p>모든 로그 출력: loggerMiddleware를 등록하면 모든 액션에 대한 로그가 출력됩니다.</p>
</li>
<li><p>지정한 액션만 로그 출력: 특정 액션에 대해서만 로그를 출력하려면 <code>predicate</code> 옵션을 설정합니다.</p>
<pre><code class="language-tsx">import { createStore, applyMiddleware } from &#39;redux&#39;;
import loggerMiddleware from &#39;redux-logger&#39;; // redux-logger 미들웨어 임포트
import rootReducer from &#39;./reducers&#39;; // 리듀서 파일 임포트
</code></pre>
</li>
</ul>
<p>const loggerOptions = {
  predicate: (getState, action) =&gt; action.type === &#39;SOME_ACTION_TYPE&#39;,
};</p>
<p>const store = createStore(rootReducer, applyMiddleware(loggerMiddleware(loggerOptions)));</p>
<pre><code>
&lt;/br&gt;

### 3. 프로덕션(production) 환경에서 비활성화
개발 환경에서는 Redux Logger를 사용하여 디버깅을 용이하게 하지만, 프로덕션 환경에서는 성능에 영향을 미치지 않도록 비활성화하는 것이 좋습니다. 이를 위해서는 `process.env.NODE_ENV`를 검사하여 Redux Logger를 적용할지 말지를 결정합니다.

```tsx
import { createStore, applyMiddleware } from &#39;redux&#39;;
import loggerMiddleware from &#39;redux-logger&#39;; // redux-logger 미들웨어 임포트
import rootReducer from &#39;./reducers&#39;; // 리듀서 파일 임포트

const middlewares = []; // 미들웨어 배열 선언
// const middlewares = [thunkMiddleware, loggerMiddleware]; 

// &#39;development&#39;인 경우에만 Redux Logger를 등록
if (process.env.NODE_ENV === &#39;development&#39;) {
  middlewares.push(loggerMiddleware);
}

const store = createStore(rootReducer, applyMiddleware(...middlewares));</code></pre></br>

<h3 id="4-logger를-만들어서-redux-미들웨어-작동-방식-이해하기">4. Logger를 만들어서 Redux 미들웨어 작동 방식 이해하기</h3>
<pre><code>const loggerMiddleware = store =&gt; next =&gt; action =&gt; {
  console.group(action &amp;&amp; action.type); // 액션 타입을 그룹명으로 설정
  console.log(&#39;이전 상태&#39;, store.getState()); // 이전 상태 로깅
  console.log(&#39;액션&#39;, action); // 디스패치된 액션 로깅

  // 다음 미들웨어(또는 리듀서)에게 액션을 전달
  next(action);

  console.log(&#39;다음 상태&#39;, store.getState()); // 액션 처리 후의 상태 로깅
  console.groupEnd(); // 그룹 끝
};

export default loggerMiddleware;</code></pre><p>첫 번째 함수 (<strong>loggerMiddleware</strong>): 이 함수는 스토어 객체를 매개변수로 받습니다. 다음 함수를 반환하고 있습니다.</p>
<p>두 번째 함수 (<strong>next</strong>): 이 함수는 다음 미들웨어(또는 리듀서)를 가리키는 함수를 매개변수로 받습니다.</p>
<p>세 번째 함수 (<strong>action</strong>): 이 함수는 디스패치된 액션 객체를 매개변수로 받습니다. 여기서 실제 Logger 미들웨어의 로직이 실행됩니다. 액션을 콘솔에 출력한 후, 다음 미들웨어(또는 리듀서)에 액션을 전달하고, 처리된 상태를 콘솔에 출력한 후 마지막으로 다음 미들웨어(또는 리듀서)의 결과를 반환합니다.</p>
</br>

<h2 id="📌-redux-thunk-사용법❓">📌 redux-thunk 사용법❓</h2>
<ul>
<li><p><code>redux-thunk</code>는 가장 간단하고 쉽게 사용할 수 있는 <code>리덕스 미들웨어</code>입니다.
액션 크리에이터(Action Creator)에서 일반적인 객체 대신 함수를 반환할 수 있게 해줍니다. 이 함수는 디스패치(dispatch) 메서드를 인자로 받고, 해당 함수 내에서 비동기 작업을 수행하거나 조건에 따라 다른 액션을 디스패치할 수 있습니다.</p>
</li>
<li><p>redux-thunk를 사용하면 액션을 통해 비동기 작업을 시작하고, 비동기 작업이 완료되면 해당 결과를 다시 액션으로 디스패치하여 상태를 업데이트합니다.</p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[javascript] / 와 | , || , && 의 차이점 (비트, 논리 연산자)]]></title>
            <link>https://velog.io/@view_coding/javascript-%EC%99%80-%EC%9D%98-%EC%B0%A8%EC%9D%B4%EC%A0%90-%EC%97%B0%EC%82%B0%EC%9E%90</link>
            <guid>https://velog.io/@view_coding/javascript-%EC%99%80-%EC%9D%98-%EC%B0%A8%EC%9D%B4%EC%A0%90-%EC%97%B0%EC%82%B0%EC%9E%90</guid>
            <pubDate>Thu, 20 Jul 2023 06:25:07 GMT</pubDate>
            <description><![CDATA[<h2 id="1--슬래시">1. / (슬래시)</h2>
<p>: 자바스크립트에서 주로 정규 표현식을 작성하거나, 나눗셈 연산을 수행할 때 사용됩니다.
정규 표현식에서 /로 감싸진 패턴은 <code>해당 패턴과 일치하는 문자열을 찾거나 변형</code>하는 데 사용됩니다. 예를 들어, &#39;INCREMENT/DECREMENT&#39;는 슬래시를 사용하여 &#39;INCREMENT&#39;와 &#39;DECREMENT&#39; 두 가지 값을 표현하는 문자열입니다.</p>
<pre><code class="language-JSX">INCREASE = &#39;INCREMENT/DECREMENT&#39; // 문자열 분리 연산자</code></pre>
</br>

<h2 id="2--파이프">2. | (파이프)</h2>
<p>: 자바스크립트에서 비트 연산자로 사용되며, 비트 단위 OR 연산을 수행합니다.
이진수로 표현된 두 개의 비트열을 비교하여 대응하는 비트 위치에서 하나 이상의 비트가 1인 경우 1을 반환합니다. 예를 들어, 5 | 3은 이진수로 101 | 011를 계산하여 111을 반환합니다.
또한, |는 <code>타입스크립트에서 유니온 타입(Union Type)을 정의</code>할 때 사용됩니다. 유니온 타입은 둘 이상의 타입 중 하나를 나타내는 타입입니다. 예를 들어, type Action = IncreaseAction | SetUserAction에서 |는 Action 타입이 IncreaseAction 또는 SetUserAction 둘 중 하나를 가질 수 있음을 나타냅니다.</p>
<pre><code class="language-tsx">type Action = IncreaseAction | SetUserAction // &#39;IncreaseAction&#39; or &#39;SetUserActio&#39;</code></pre>
</br>

<h2 id="3--논리-or">3. || (논리 OR)</h2>
<p>: 논리 OR 연산자로, 논리적인 OR 연산을 수행합니다.
첫 번째 피연산자가 true로 평가되면, 두 번째 피연산자를 평가하지 않고 true를 반환합니다.
첫 번째 피연산자가 false로 평가되면, 두 번째 피연산자를 평가하고 그 결과를 반환합니다.</p>
<pre><code class="language-JSX">const name = &quot;&quot;;
const displayName = name || &quot;Anonymous&quot;;
console.log(displayName); // 출력 결과: &quot;Anonymous&quot;</code></pre>
</br>

<h2 id="4--논리-and">4. &amp;&amp; (논리 AND)</h2>
<p>: &amp;&amp;는 두 개의 피연산자 중 하나 이상이 false로 평가되면 false를 반환하고, 모든 피연산자가 true로 평가되면 true를 반환합니다.
첫 번째 피연산자가 false로 평가되면, 두 번째 피연산자는 평가하지 않고 false를 반환합니다.
&amp;&amp; 연산자는 조건문에서 주로 사용되며, 모든 조건이 참일 때만 실행해야 할 때 유용합니다.</p>
</br>

<p>&quot;/&quot; 는 분리 기호 및 나눗셈 연산자, &quot;|&quot; 는 비트 단위 OR 연산자 및 유니온 타입 정의에 사용되며, &quot;||&quot; 는 논리 OR 연산자로 논리적인 조건 평가에 사용됩니다. 이들 연산자는 각각 다른 목적과 사용 방식을 가지고 있으므로 올바른 문맥에서 사용되어야 합니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[React] Reducer 여러 개 사용하기 (combineReducer)]]></title>
            <link>https://velog.io/@view_coding/React-Reducer-%EC%97%AC%EB%9F%AC-%EA%B0%9C-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0-combineReducer</link>
            <guid>https://velog.io/@view_coding/React-Reducer-%EC%97%AC%EB%9F%AC-%EA%B0%9C-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0-combineReducer</guid>
            <pubDate>Thu, 20 Jul 2023 06:06:06 GMT</pubDate>
            <description><![CDATA[<h2 id="리듀서가-여러개일-경우❓">리듀서가 여러개일 경우❓</h2>
<blockquote>
<p><code>combineReducers</code>는 Redux에서 사용되는 여러 개의 리듀서(reducer)를 하나로 결합하는 함수입니다.</p>
</blockquote>
<p>Redux 애플리케이션에서는 하나 이상의 리듀서를 사용하여 각각의 상태를 관리하게 됩니다. combineReducers 함수는 이러한 리듀서들을 하나의 상위 리듀서로 결합하고, 각각의 리듀서가 관리하는 <code>상태들을 통합하여 전체 상태를 관리</code>하는 역할을 합니다.</p>
<pre><code class="language-ts">import { createStore, applyMiddleware, combineReducers, Store } from &#39;redux&#39;;
import { composeWithDevTools } from &#39;redux-devtools-extension&#39;;
import thunk from &#39;redux-thunk&#39;;

// RootState 애플리케이션의 전체 상태 구조를 정의
// ❗interface 는 객체의 구조를 정의하는 데 사용
interface RootState {
  counter: number;
  user: string | null;
}

// 액션 타입 정의
// ❗enum 열거형은 연관된 상수 값을 그룹화
enum ActionType {
  INCREASE = &#39;INCREASE&#39;,
  DECREASE = &#39;DECREASE&#39;,
  SET_USER = &#39;SET_USER&#39;,
}


// 액션 생성 함수 정의
interface IncreaseAction {
  type: ActionType.INCREASE;
}

interface DecreaseAction {
  type: ActionType.DECREASE;
}

interface SetUserAction {
  type: ActionType.SET_USER;
  payload: string | null;
}

type Action = IncreaseAction | DecreaseAction | SetUserAction;

// 초기 상태 정의
const initialState: RootState = {
  counter: 0,
  user: null,
};

// 리듀서 함수 정의 &quot;counter&quot;와 &quot;user&quot; 상태를 업데이트
const counterReducer = (state = initialState.counter, action: Action): number =&gt; {
  switch (action.type) {
    case ActionType.INCREASE:
      return state + 1;
    case ActionType.DECREASE:
      return state - 1;
    default:
      return state;
  }
};

const userReducer = (state = initialState.user, action: Action): string | null =&gt; {
  switch (action.type) {
    case ActionType.SET_USER:
      return action.payload;
    default:
      return state;
  }
};

// 루트 리듀서 정의
const rootReducer = combineReducers({
  // 키(key) : counter, user
  counter: counterReducer,
  user: userReducer,
});

// 스토어 타입 정의
export type AppStore = Store&lt;RootState, Action&gt;;

// 미들웨어 적용
const middleware = [thunk];
const enhancers = [applyMiddleware(...middleware)];

// 개발 환경에서 Redux DevTools 확장 기능 사용
if (process.env.NODE_ENV === &#39;development&#39;) {
  enhancers.push(composeWithDevTools());
}

// 스토어 생성
const store: AppStore = createStore(rootReducer, initialState, ...enhancers);

export default store;
</code></pre>
<blockquote>
<p>Redux 액션 타입은 <code>enum</code>으로 정의하는 것을 권장합니다.</p>
</blockquote>
<blockquote>
<p><code>payload</code> : 일반적으로 액션에서 전달되는 추가적인 데이터를 의미합니다. </p>
</blockquote>
<p>SetUserAction에서 payload가 string | null 타입으로 정의된 이유는 사용자 정보를 나타내는 문자열(string) 또는 사용자가 없음을 나타내는 null 값을 가질 수 있기 때문입니다.</p>
</br>

<hr>

<pre><code class="language-tsx">// CounterComponent.tsx
import { useSelector, useDispatch } from &#39;react-redux&#39;;
import { AppStore, IncreaseAction, DecreaseAction } from &#39;./store&#39;;

export const CounterComponent = () =&gt; {
  const dispatch = useDispatch();
  const counter = useSelector((state: AppStore) =&gt; state.counter);

  const increaseCounter = () =&gt; {
    const action: IncreaseAction = { type: ActionType.INCREASE };
    dispatch(action);
  };

  const decreaseCounter = () =&gt; {
    const action: DecreaseAction = { type: ActionType.DECREASE };
    dispatch(action);
  };

  return (
    &lt;div&gt;
      &lt;h2&gt;Counter: {counter}&lt;/h2&gt;
      &lt;button onClick={increaseCounter}&gt;Increase&lt;/button&gt;
      &lt;button onClick={decreaseCounter}&gt;Decrease&lt;/button&gt;
    &lt;/div&gt;
  );
};</code></pre>
<pre><code class="language-tsx">// UserComponent.tsx
import { useSelector, useDispatch } from &#39;react-redux&#39;;
import { AppStore, SetUserAction } from &#39;./store&#39;;

export const UserComponent = () =&gt; {
  const dispatch = useDispatch();
  const user = useSelector((state: AppStore) =&gt; state.user);

  const setUser = (username: string) =&gt; {
    const action: SetUserAction = {
      type: ActionType.SET_USER,
      payload: username,
    };
    dispatch(action);
  };

  return (
    &lt;div&gt;
      &lt;h2&gt;User: {user}&lt;/h2&gt;
      &lt;button onClick={() =&gt; setUser(&#39;John&#39;)}&gt;Set User&lt;/button&gt;
      &lt;button onClick={() =&gt; setUser(null)}&gt;Clear User&lt;/button&gt;
    &lt;/div&gt;
  );
};</code></pre>
</br>

<p><code>combineReducers</code> 함수를 사용하여 counterReducer와 userReducer를 합친 후, 각각의 리듀서가 관리하는 상태를 counter와 user라는 <code>키(key)</code>로 통합합니다. 이렇게 생성된 rootReducer는 전체 Redux 상태에서 각 리듀서가 담당하는 부분 상태를 관리합니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[javascript] 콜백함수]]></title>
            <link>https://velog.io/@view_coding/javascript-%EC%BD%9C%EB%B0%B1%ED%95%A8%EC%88%98</link>
            <guid>https://velog.io/@view_coding/javascript-%EC%BD%9C%EB%B0%B1%ED%95%A8%EC%88%98</guid>
            <pubDate>Tue, 18 Jul 2023 07:41:14 GMT</pubDate>
            <description><![CDATA[<h1 id="콜백함수❓">콜백함수❓</h1>
<p>콜백 함수는 <code>다른 함수에게 인자로 전달되어 나중에 호출되는 함수</code>를 의미합니다. 콜백 함수는 비동기적인 작업, 이벤트 처리, 타이머 등 다양한 상황에서 사용됩니다.</p>
<pre><code class="language-js">function callback() {
  // 콜백 함수의 내용
}

someFunction(callback); // 콜백 함수를 인자로 전달
someFunction(callback()); // xx </code></pre>
<h3 id="1-타이머">1. 타이머</h3>
<pre><code class="language-js">setTimeout(function() {
  console.log(&#39;타이머가 만료되었습니다.&#39;);
}, 1000);</code></pre>
<p>setTimeout 함수는 지정된 시간이 경과한 후 콜백 함수를 호출합니다.</p>
<h3 id="2-이벤트-핸들링">2. 이벤트 핸들링</h3>
<pre><code class="language-js">button.addEventListener(&#39;click&#39;, function() {
  console.log(&#39;버튼이 클릭되었습니다.&#39;);
});</code></pre>
<p>addEventListener 함수는 버튼 클릭 이벤트가 발생했을 때 콜백 함수를 호출합니다.</p>
<h3 id="3-비동기-작업">3. 비동기 작업</h3>
<pre><code class="language-js">ajax(url, function(response) {
  console.log(&#39;비동기 요청이 완료되었습니다.&#39;);
  console.log(response);
});</code></pre>
<p>ajax 함수는 비동기적으로 서버에 데이터를 요청하고, 요청이 완료되면 콜백 함수를 호출하여 응답 데이터를 처리합니다.</p>
<p>콜백 함수는 함수의 인자로 전달되므로, 콜백 함수의 매개변수를 통해 결과 데이터나 이벤트 정보 등을 전달받을 수 있습니다. 이를 통해 비동기적인 작업의 완료 여부를 감지하거나 결과를 처리할 수 있습니다.</p>
<hr>

<p><strong>1. setTimeout</strong>: 일정 시간이 지난 후에 콜백 함수를 한 번 실행하는 타이머입니다.</p>
<pre><code class="language-ts">setTimeout(function() {
  console.log(&#39;Hello, world!&#39;);
}, 2000);</code></pre>
<p><strong>2. setInterval</strong>: 일정한 시간 간격으로 콜백 함수를 반복해서 실행하는 타이머입니다. 
clearInterval 함수를 사용하여 중지할 때까지 계속 반복됩니다.</p>
<pre><code class="language-js">let count = 0;
const intervalId = setInterval(function() {
  console.log(count);
  count++;
  if (count === 5) {
    clearInterval(intervalId);
  }
}, 1000);</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[javscript] 일반함수와 화살표 함수의 this]]></title>
            <link>https://velog.io/@view_coding/javscript-%EC%9D%BC%EB%B0%98%ED%95%A8%EC%88%98%EC%99%80-%ED%99%94%EC%82%B4%ED%91%9C-%ED%95%A8%EC%88%98%EC%9D%98-this</link>
            <guid>https://velog.io/@view_coding/javscript-%EC%9D%BC%EB%B0%98%ED%95%A8%EC%88%98%EC%99%80-%ED%99%94%EC%82%B4%ED%91%9C-%ED%95%A8%EC%88%98%EC%9D%98-this</guid>
            <pubDate>Tue, 18 Jul 2023 06:56:47 GMT</pubDate>
            <description><![CDATA[<pre><code class="language-ts">const object = {
  name : &quot;developer&quot;,
  main: function () {
      console.log(this)
  },
  mainArrow : () =&gt; {
      console.log(this)
  }
};

object.main();
object.mainArror();</code></pre>
<h2 id="📌일반-함수this">📌일반 함수.this</h2>
<p>: 객체의 메서드 함수로써 더 적합니다.</p>
<ul>
<li><p>일반 함수는 자신이 호출되는 방식에 따라 <code>this 값을 동적으로 바인딩</code>합니다.</p>
</li>
<li><p>this는 함수가 호출될 때 호출 컨텍스트에 따라 결정됩니다. 호출 컨텍스트는 함수가 어떻게 호출되었는지에 따라 달라집니다.</p>
</li>
<li><p>일반 함수의 <code>this는 함수가 호출된 위치에서의 객체를 가리킬 수</code> 있습니다.</p>
</li>
<li><p>일반 함수는 call(), apply(), bind() 메서드를 사용하여 명시적으로 this 값을 변경할 수 있습니다.</p>
</li>
</ul>
</br>

<h2 id="📌화살표-함수this">📌화살표 함수.this</h2>
<p>: 함수가 선언된 위치에서 결정되며 선언된 위치에 따라 바뀌지 않습니다.
선언된 함수를 둘러싸는 scrope의 this를 그대로 가져와서 사용합니다.</p>
<ul>
<li><p>화살표 함수는 자체적인 this를 가지지 않고, <code>외부 스코프의 this 값을 상속</code>합니다.</p>
</li>
<li><p>화살표 함수는 함수가 정의된 위치에서의 상위 스코프의 this 값을 참조합니다.</p>
</li>
<li><p>화살표 함수는 call(), apply(), bind() 메서드를 사용하여 this 값을 변경할 수 없습니다.</p>
</li>
</ul>
<hr>

<h2 id="주요-차이점❓">주요 차이점❓</h2>
<ul>
<li><p>일반 함수는 호출 컨텍스트에 따라 this 값을 동적으로 바인딩하지만, 화살표 함수는 상위 스코프의 this 값을 상속합니다.</p>
</li>
<li><p>일반 함수는 this 값을 변경하기 위해 call(), apply(), bind() 메서드를 사용할 수 있지만, 화살표 함수는 이를 지원하지 않습니다.</p>
</li>
<li><p>화살표 함수는 자신만의 this 값을 가지지 않기 때문에, 객체의 메서드로 사용할 때 주의해야 합니다. 객체의 메서드로 사용될 경우 화살표 함수는 상위 스코프의 this 값을 참조하므로, 해당 객체를 가리키지 않을 수 있습니다.</p>
</li>
</ul>
<pre><code class="language-ts">const obj = {
  name: &#39;John&#39;,
  sayHello: function () {
    console.log(`Hello, ${this.name}!`);
  },
  sayHelloArrow: () =&gt; {
    console.log(`Hello, ${this.name}!`);
  },
};

obj.sayHello(); // &quot;Hello, John!&quot; (this는 obj를 가리킴)
obj.sayHelloArrow(); // &quot;Hello, undefined!&quot; (this는 상위 스코프인 전역 객체인 &quot;window&quot; 객체를 가리킴)</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[React] react-redux 사용법]]></title>
            <link>https://velog.io/@view_coding/React-react-redux-%EC%82%AC%EC%9A%A9%EB%B2%95</link>
            <guid>https://velog.io/@view_coding/React-react-redux-%EC%82%AC%EC%9A%A9%EB%B2%95</guid>
            <pubDate>Mon, 17 Jul 2023 09:57:30 GMT</pubDate>
            <description><![CDATA[<p>👩‍🔧 숫자를 증가시키거나 감소시키는 카운터 애플리케이션</p>
<h2 id="1-액션-타입action-types-정의하기">1. 액션 타입(Action Types) 정의하기</h2>
<pre><code class="language-ts">// actions.ts
export const INCREASE = &#39;INCREMENT/DECREMENT&#39;;</code></pre>
<p>액션 타입은 상수로 정의하고, 문자열 리터럴 타입으로 선언합니다.</p>
</br>
</br>

<h2 id="2-액션-생성자-함수-작성하기">2. 액션 생성자 함수 작성하기</h2>
<pre><code class="language-ts">// actions.ts
export interface IncreaseAction {
  type: typeof INCREASE; // typeof &quot;상수 문자열&quot; -&gt; ~type을 반환
  count: number;
}

// 액션 타입들을 하나로 묶어서 Union 타입을 구성하기 위해 사용
export type CounterAction = IncreaseAction;

export const increaseCount = (count: number): IncreaseAction =&gt; ({
  type: INCREASE,
  count, // payload 필드
});</code></pre>
<p>액션 크리에이터 함수를 작성하여 액션을 생성합니다. 액션 객체는 type 필드와 필요한 경우 추가적인 데이터를 가진 payload 필드로 구성됩니다.</p>
<p><code>INCREASE를 사용하여 타입을 제한</code>하고, <code>IncreaseAction 인터페이스로 액션의 타입을 지정</code>합니다.</p>
</br>

<h4 id="-typeof👩🔧">※ typeof👩‍🔧</h4>
<p>리덕스의 <code>액션 타입</code>을 정의할 때 <code>상수로 문자열을 선언한 경우 typeof를 사용</code>하여 타입의 안정성을 높일 수 있습니다.</p>
<p>스위치 문에서 action.type과 case의 타입이 정확히 일치하는지 확인할 수 있습니다. 따라서 action.type이 &#39;INCREMENT/DECREMENT&#39;가 아닌 다른 문자열을 갖게 된다면 컴파일러가 오류를 발생시킵니다.</p>
<h2 id="📌-action">📌 Action</h2>
<p>액션 객체를 나타내는 인자입니다. 액션 객체는 상태를 변경하는 데 필요한 정보를 포함하고 있으며, 해당 객체는 최소한 <code>type이라는 필드</code>를 가져야 합니다.</p>
<h4 id="-액션의-기본-구조👩🔧">※ 액션의 기본 구조👩‍🔧</h4>
<pre><code class="language-tsx">const increaseCount = (count: number) =&gt; ({
  type: INCREASE, // 액션의 타입
  count, // 추가 데이터 (예: 증가량)
});</code></pre>
</br>
</br>

<h2 id="3-초기-상태state-타입-정의하기">3. 초기 상태(State) 타입 정의하기</h2>
<pre><code class="language-ts">// store.ts
export interface RootState {
  count: number;
}</code></pre>
</br>
</br>

<h2 id="4-리듀서reducer-함수-작성하기">4. 리듀서(Reducer) 함수 작성하기</h2>
<pre><code class="language-ts">// store.ts
import { INCREASE, CounterAction } from &#39;./actions&#39;;

// 초기값 설정
const initialState: RootState = {
  count: 0,
};

// state: RootState -&gt; 타입스크립트가 상태의 구조와 속성을 추론하고,
// 잘못된 타입의 값이 상태에 할당되는 것을 방지

const counterReducer = (state: RootState = initialState, action: CounterAction): RootState =&gt; {
  // 앞의 RootState -&gt; 첫 번째 매개변수 타입지정, 뒤 RootState -&gt; RootState 타입의 객체
  switch (action.type) {
    case INCREASE:
      // { ...현재값, 액션 }; -&gt; 새로운 상태를 계산하고 반환
      return { ...state, count: action.count }; // count : count 속성 업데이트
    default:
      return state;
  }
};

export { RootState, counterReducer };</code></pre>
<blockquote>
<p>현재값을 <code>스프레드(spread)연산자(...)</code>를 사용하여 그대로 복제하기 때문에 <code>불변성을 유지</code>합니다.</p>
</blockquote>
<h2 id="📌-reducer">📌 Reducer</h2>
<p>리듀서는 변화를 일으키는 함수입니다. 액션을 만들어 발생시키려면 리듀서가 <code>현재 상태</code>와 전달받은 <code>액션 객체를 파라미터</code>로 받아 옵니다. 그리고 두 값을 참고하여 새로운 상태로 반환해 줍니다.</p>
<h4 id="-리듀서-기본-구조👩🔧">※ 리듀서 기본 구조👩‍🔧</h4>
<p>리듀서 함수는 현재 상태(state)와 액션(action)을 매개변수로 받고, 새로운 상태를 반환합니다.</p>
<p><strong>state</strong>
: 리듀서 함수가 <code>현재 상태를 나타내는 인자</code>입니다. 이 매개변수는 현재 상태를 변경하거나 새로운 상태를 반환하는 데 사용됩니다. 일반적으로 state 매개변수는 기본값을 가지며, 애플리케이션이 처음 실행될 때 이 기본값을 가진 상태로 초기화됩니다.</p>
<p><strong>action</strong>
: action 매개변수를 통해 <code>액션의 타입을 식별</code>하고, 해당 액션에 따라 상태를 변경합니다.</p>
<pre><code class="language-tsx">const initialState = {
  // 초기 상태를 정의합니다.
};

const reducerName = (state = initialState, action) =&gt; {
  // 액션 타입에 따라 상태를 처리하고 변경한 새로운 상태를 반환합니다.
  switch (action.type) {
    case &#39;ACTION_TYPE_1&#39;:
      // 처리 로직
      return {
        ...state,
        // 업데이트할 상태 속성들
      };
    case &#39;ACTION_TYPE_2&#39;:
      // 처리 로직
      return {
        ...state,
        // 업데이트할 상태 속성들
      };
    default:
      // 기본 동작 (액션이 처리되지 않을 때)
      return state;
  }
};

export default reducerName;</code></pre>
</br>
</br>

<h2 id="5-스토어store-생성하기">5. 스토어(Store) 생성하기</h2>
<pre><code class="language-ts">// store.ts
import { createStore } from &#39;redux&#39;;
import { counterReducer } from &#39;./store&#39;;

const store = createStore(counterReducer);</code></pre>
<h2 id="📌-store">📌 Store</h2>
<p>redux를 사용하기 위해서 store을 만듭니다. 1개의 프로젝트에는 1개의 store을 가질 수 있으며 store 안에는 현재 애플리케이션 상태와 reducer이 들어있습니다. <code>createStore</code> 함수를 사용하여 생성합니다.</p>
</br>
</br>

<h2 id="6-루트-리듀서root-reducer-생성하기-옵션">6. 루트 리듀서(Root Reducer) 생성하기 (옵션)</h2>
<p>루트 리듀서를 사용하는 경우, 여러 개의 리듀서를 결합합니다. 이는 프로젝트의 규모에 따라 다르며, 작은 프로젝트에서는 필요하지 않을 수 있습니다.</p>
</br>
</br>

<h2 id="7-미들웨어middleware-적용하기-옵션">7. 미들웨어(Middleware) 적용하기 (옵션)</h2>
<p>미들웨어를 적용하여 리덕스의 동작을 확장하거나 비동기 작업을 처리합니다. 미들웨어를 적용하는 방법은 다양합니다.</p>
</br>
</br>

<h2 id="8-스토어를-프로바이더provider로-감싸기">8. 스토어를 프로바이더(Provider)로 감싸기</h2>
<pre><code class="language-ts">// App.tsx
import React from &#39;react&#39;;
import { Provider } from &#39;react-redux&#39;;
import Counter from &#39;./Counter&#39;;


const App: React.FC = () =&gt; {
  return (
    // 만든 store를 앱 상위에 넣어줍니다.
    &lt;Provider store={store}&gt;
      &lt;Counter /&gt;
    &lt;/Provider&gt;
  );
};

export default App;</code></pre>
<h2 id="📌-provider">📌 Provider</h2>
<p>울타리 역할을 하며 props로 store을 지정해줘야 합니다.</p>
</br>
</br>

<h2 id="9-컴포넌트에서-스토어-사용하기">9. 컴포넌트에서 스토어 사용하기</h2>
<pre><code class="language-ts">// Counter.tsx
import React from &#39;react&#39;;
import { useSelector, useDispatch } from &#39;react-redux&#39;;
import { RootState } from &#39;./store&#39;;
import { increaseCount } from &#39;./actions&#39;;

const Counter: React.FC = () =&gt; {
  // store에 접근하여 state 가져오기
  // useSelector의 콜백 함수로 RootState의 타입을 지정하여 상태의 타입을 정의
  const count = useSelector((state: RootState) =&gt; state.count);

  // dispatch를 사용하기 위한 준비
  const dispatch = useDispatch();

  const handleIncrement = () =&gt; {
    // store에 있는 state 바꾸는 함수 실행
    dispatch(increaseCount(count + 1));
  };

  const handleDecrement = () =&gt; {
    dispatch(increaseCount(count - 1));
  };

  return (
    &lt;div&gt;
      &lt;h2&gt;Counter&lt;/h2&gt;
      &lt;p&gt;Count: {count}&lt;/p&gt;
      &lt;button onClick={handleIncrement}&gt;Increment&lt;/button&gt;
      &lt;button onClick={handleDecrement}&gt;Decrement&lt;/button&gt;
    &lt;/div&gt;
  );
};

export default Counter;</code></pre>
<p>컴포넌트에서 리덕스 스토어의 상태를 읽거나 액션을 디스패치하여 상태를 업데이트합니다. useSelector 훅을 사용하여 상태를 읽고, useDispatch 훅을 사용하여 액션을 디스패치합니다.</p>
<h2 id="📌-dispatch">📌 Dispatch</h2>
<p>디스패치는 스토어의 내장 함수 중 하나입니다. 쉽게 말해 <code>액션을 발생</code>시키는 역할을 합니다.
이 함수는 dispatch(action)과 같은 형태로 <code>액션 객체를 파라미터로 넣어서 호출</code>합니다. 이 함수가 호출되면 스토어는 리듀서 함수를 실행시켜서 새로운 상태를 만들어 줍니다.</p>
</br>

<h2 id="📌-useselector">📌 useSelector</h2>
<p>Store의 상태를 쉽게 선택할 수 있게 하는 함수로 이를 통해 컴포넌트에서 필요한 상태를 쉽게 조회할 수 있습니다.</p>
<hr>

<h2 id="리듀서가-여러개일-경우❓">리듀서가 여러개일 경우❓</h2>
<blockquote>
<p>combineReducers는 Redux에서 사용되는 여러 개의 리듀서(reducer)를 하나로 결합하는 함수입니다.</p>
</blockquote>
<p><a href="https://velog.io/@view_coding/React-Reducer-%EC%97%AC%EB%9F%AC-%EA%B0%9C-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0-combineReducer">바로가기 Click</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[typescript] 타입스크립트의 타입 지정]]></title>
            <link>https://velog.io/@view_coding/Typescript</link>
            <guid>https://velog.io/@view_coding/Typescript</guid>
            <pubDate>Sun, 16 Jul 2023 16:50:03 GMT</pubDate>
            <description><![CDATA[<h1 id="타입스크립트란❓">타입스크립트란❓</h1>
<p>타입스크립트는 Microsoft에서 개발한 오픈 소스 프로그래밍 언어입니다. 타입스크립트는 자바스크립트의 상위 집합으로, 자바스크립트 코드를 포함하면서 정적 타입 시스템을 추가합니다. 이는 개발자가 변수, 함수, 객체 등을 사용할 때 타입을 명시적으로 지정하고 검사할 수 있게 해줍니다.</p>
<p>타입스크립트는 정적 타입 검사를 제공하기 때문에 개발자가 <code>실수로 인한 버그를 사전에 감지하고 예방</code>할 수 있습니다. 이를 통해 <code>코드의 가독성, 유지 보수성, 안정성을 향상</code>시킬 수 있습니다. 또한, 개발자들 사이에서 코드의 의도를 명확하게 전달하고 문서화하는 데 도움을 줍니다.</p>
<p>타입스크립트는 자바스크립트와 호환되기 때문에 기존의 자바스크립트 코드를 그대로 사용하면서 점진적으로 타입스크립트로 전환할 수 있습니다. 이러한 특징은 대규모 프로젝트의 경우 특히 유용합니다.</p>
<p>타입스크립트는 다양한 개발 환경에서 사용할 수 있으며, 강력한 개발 도구와 풍부한 에코시스템을 제공합니다. 타입스크립트는 타입 정의, 제네릭, 인터페이스, 클래스, 모듈 등과 같은 고급 기능을 지원하여 개발자가 유연하고 확장 가능한 코드를 작성할 수 있게 합니다.</p>
<p>요약하자면, 타입스크립트는 <code>자바스크립트의 상위 집합으로 정적 타입 시스템을 추가한 프로그래밍 언어</code>입니다. 타입스크립트는 코드의 안정성과 가독성을 향상시키며 대규모 프로젝트에서 특히 유용합니다.</p>
<pre><code class="language-ts">function add(a: number, b: number): number {
  return a + b;
}

const result: number = add(3, 5);
console.log(result);</code></pre>
<p>타입스크립트는 함수의 매개변수와 반환값에 대한 타입을 명시적으로 지정하고 있습니다. 이를 통해 개발자는 함수를 사용할 때 <code>올바른 타입의 인수를 전달하고 반환값을 올바른 타입으로 처리</code>할 수 있습니다.</p>
</br>

<h2 id="📌변수의-타입-지정">📌변수의 타입 지정</h2>
<h3 id="1-타입-주석type-annotation">1. 타입 주석(Type Annotation)</h3>
<p>: 변수 선언 시 콜론(:) 뒤에 원하는 타입을 명시합니다. 예를 들어, let 키워드를 사용하여 변수를 선언하고 타입 주석을 추가할 수 있습니다.</p>
<pre><code class="language-ts">let age: number = 30;</code></pre>
<p>위의 예시에서 age 변수의 타입은 number로 명시되었습니다.</p>
<h3 id="2-타입-추론type-inference">2. 타입 추론(Type Inference)</h3>
<p>: 변수의 초기값을 할당하는 경우, 타입스크립트는 할당된 값의 형태를 기반으로 변수의 타입을 추론합니다. 변수의 타입을 명시적으로 지정하지 않아도 됩니다.</p>
<pre><code class="language-ts">let age = 30; // number 타입으로 추론됨</code></pre>
<p>위의 예시에서 age 변수의 타입은 초기값 30의 형태에 따라 number로 추론됩니다.</p>
<h3 id="3-타입-별칭type-alias">3. 타입 별칭(Type Alias)</h3>
<p>: 복잡한 타입을 간략하게 표현하기 위해 타입 별칭을 사용할 수 있습니다. type 키워드를 사용하여 타입 별칭을 선언하고, 해당 별칭을 변수의 타입으로 사용할 수 있습니다.</p>
<pre><code class="language-ts">type Point = {
  x: number;
  y: number;
};

let p: Point = { x: 0, y: 0 };</code></pre>
<p>위의 예시에서 Point는 { x: number, y: number } 형태의 타입 별칭입니다. 변수 p의 타입으로 Point를 사용하고 있습니다.</p>
<h3 id="4-유니온-타입union-type">4. 유니온 타입(Union Type)</h3>
<p>: 변수가 여러 가지 타입 중 하나일 수 있는 경우 유니온 타입을 사용하여 변수의 타입을 지정할 수 있습니다. | 기호를 사용하여 여러 타입을 연결합니다.</p>
<pre><code class="language-ts">let value: string | number = &quot;hello&quot;;
value = 10;</code></pre>
<p>위의 예시에서 value 변수는 문자열 또는 숫자 타입을 가질 수 있습니다.</p>
<h3 id="5-제네릭-타입generic-type">5. 제네릭 타입(Generic Type)</h3>
<p>: 변수가 다양한 타입을 가질 수 있지만, 특정 조건을 충족해야 할 때 제네릭 타입을 사용할 수 있습니다. 제네릭은 타입 매개변수를 사용하여 타입을 추상화하는 기능입니다.</p>
<pre><code class="language-ts">function identity&lt;T&gt;(value: T): T {
  return value;
}

let result = identity&lt;string&gt;(&quot;hello&quot;);</code></pre>
<p>위의 예시에서 identity 함수는 제네릭 타입 T를 가지고 있으며, 매개변수 value와 반환값의 타입이 동일합니다. result 변수는 identity 함수의 반환값에 타입을 명시적으로 지정한 예시입니다.</p>
<hr>

<h2 id="📌오브젝트와-배열의-타입-지정">📌오브젝트와 배열의 타입 지정</h2>
<h3 id="😯-객체object의-타입-지정">😯 객체(Object)의 타입 지정</h3>
<pre><code class="language-ts">let 이름 : { name? : string } = { name : &quot;민수&quot; };</code></pre>
<p>name? : name의 속성은 옵션</p>
<p>: 객체의 타입을 지정하기 위해 인터페이스(Interface)나 타입(Type)을 사용할 수 있습니다. 이를 통해 객체의 속성 이름과 해당 속성의 타입을 명시할 수 있습니다.</p>
<p><strong>인터페이스(Interface)를 사용한 객체 타입 지정 예시:</strong></p>
<pre><code class="language-ts">interface Person {
  name: string;
  age: number;
  address?: string;
}

const person: Person = {
  name: &quot;John&quot;,
  age: 30,
};</code></pre>
<pre><code class="language-ts">// object에 타입지정한 속성이 많을 경우
interface Person {
  [ key : string ] : string;
  age: number;
  address?: string;
}  // 글자로된 모든 object 속석의 타입은 : string
</code></pre>
<p>위의 예시에서 Person 인터페이스는 name과 age라는 필수 속성을 가지고 있습니다. 또한, address는 선택적 속성으로 지정되어 있습니다. person 변수는 Person 인터페이스를 따르는 객체로 선언되었습니다.</p>
</br>

<p><strong>타입(Type)을 사용한 객체 타입 지정 예시:</strong></p>
<pre><code class="language-ts">type Person = {
  name: string;
  age: number;
  address?: string;
};

const person: Person = {
  name: &quot;John&quot;,
  age: 30,
};</code></pre>
<p>인터페이스 대신 타입 별칭(Type Alias)을 사용하여도 동일한 결과를 얻을 수 있습니다.</p>
<h3 id="🤔-배열array의-타입-지정">🤔 배열(Array)의 타입 지정</h3>
<p>: 배열의 타입을 지정하기 위해 제네릭 타입(Generic Type)을 사용합니다. 제네릭 타입은 &lt;타입&gt; 형태로 배열의 원소 타입을 명시합니다.</p>
<pre><code class="language-ts">const numbers: number[] = [1, 2, 3, 4, 5];</code></pre>
<p>위의 예시에서 numbers 변수는 number 타입의 배열로 선언되었습니다. 배열의 각 원소는 숫자여야 합니다.</p>
<p>또는, Array&lt;타입&gt; 형태로 배열의 타입을 지정할 수도 있습니다.</p>
<pre><code class="language-ts">const names: Array&lt;string&gt; = [&quot;John&quot;, &quot;Jane&quot;, &quot;Smith&quot;];</code></pre>
<p>위의 예시에서 names 변수는 string 타입의 배열로 선언되었습니다. 배열의 각 원소는 문자열이어야 합니다.</p>
<p>타입스크립트는 배열의 타입과 길이를 체크하여 올바른 타입의 원소가 할당되고 접근되는지 확인합니다.</p>
<hr>

<h2 id="📌함수의-타입-지정">📌함수의 타입 지정</h2>
<p><strong>1. 함수 매개변수와 반환값에 타입 주석(Type Annotation)</strong>:
함수의 매개변수와 반환값에 타입을 지정하기 위해 콜론(:) 뒤에 원하는 타입을 명시합니다.</p>
<pre><code class="language-ts">function add(a: number, b: number): number {
  return a + b;
}</code></pre>
<p>위의 예시에서 add 함수는 number 타입의 a와 b 매개변수를 받으며, number 타입의 결과를 반환합니다.</p>
</br>

<p><strong>2. 함수 매개변수와 반환값에 타입 추론(Type Inference)</strong>:
함수의 매개변수에 초기값을 할당하거나 함수의 반환값이 있는 경우, 타입스크립트는 해당 값의 형태를 기반으로 타입을 추론할 수 있습니다.</p>
<pre><code class="language-ts">function multiply(a: number, b = 1) {
  return a * b;
}</code></pre>
<p>위의 예시에서 multiply 함수는 number 타입의 a와 b 매개변수를 받으며, b의 초기값은 1로 설정되어 있습니다. 반환값은 number 타입으로 추론됩니다.</p>
</br>

<p><strong>3. 함수 타입(Type of Function)</strong>:
함수에 타입을 지정할 때, 함수 타입을 사용하여 타입을 명시할 수 있습니다. 이는 함수를 변수에 할당하거나 다른 함수의 매개변수로 전달할 때 유용합니다.</p>
<pre><code class="language-ts">type Calculator = (a: number, b: number) =&gt; number;

const add: Calculator = (a, b) =&gt; a + b;</code></pre>
<p>위의 예시에서 Calculator는 number 타입의 a와 b 매개변수를 받고 number 타입의 결과를 반환하는 함수 타입입니다. add 함수는 Calculator 타입을 따르는 함수로 할당되어 있습니다.</p>
</br>

<p><strong>4. 제네릭 타입(Generic Type)</strong>:
제네릭 타입을 사용하여 함수 내부에서 사용되는 타입을 동적으로 처리할 수 있습니다.</p>
<pre><code class="language-ts">function identity&lt;T&gt;(value: T): T {
  return value;
}</code></pre>
<p>위의 예시에서 identity 함수는 제네릭 타입 T를 가지고 있으며, 매개변수 value와 반환값의 타입이 동일합니다. 이렇게 제네릭 타입을 사용하면 함수를 호출할 때 매개변수의 타입을 동적으로 결정할 수 있습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[React] react-redux 기본 원리]]></title>
            <link>https://velog.io/@view_coding/React-Redux%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%98%EB%8A%94%EB%B2%95</link>
            <guid>https://velog.io/@view_coding/React-Redux%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%98%EB%8A%94%EB%B2%95</guid>
            <pubDate>Sat, 08 Jul 2023 07:45:21 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>Redux는 JavaScript 애플리케이션의 상태 관리를 도와주는 도구입니다. </p>
</blockquote>
<h1 id="❓react에서-redux를-사용하는-이유">❓React에서 Redux를 사용하는 이유?</h1>
<h3 id="1-예측-가능한-상태-관리">1. 예측 가능한 상태 관리</h3>
<p>: Redux는 애플리케이션의 <code>상태를 일관되고 예측 가능한 방식으로 관리</code>합니다. 모든 상태 업데이트는 순수 함수인 리듀서를 통해 이루어지며, 이러한 특징은 코드 디버깅과 테스트를 훨씬 쉽게 만듭니다.</p>
<h3 id="2-상태-로깅">2. 상태 로깅</h3>
<p>: Redux 개발 도구는 상태 변화와 이에 대한 <code>디버깅 정보를 로깅하는 데 도움</code>이 됩니다. 이를 통해 개발자는 애플리케이션의 어느 시점에서든 상태를 검사하고, 이전 상태로 롤백하는 등의 작업을 할 수 있습니다.</p>
<h3 id="3-상태-퍼시스턴스">3. 상태 퍼시스턴스</h3>
<p>: Redux를 사용하면 <code>사용자 세션 간에 상태를 유지</code>하는 것이 간단해집니다. 이는 특히 페이지 새로고침이나 애플리케이션 재시작 같은 상황에서 유용합니다.</p>
<h3 id="4-컴포넌트-간-상태-공유">4. 컴포넌트 간 상태 공유</h3>
<p>: Redux는 애플리케이션의 전역 상태를 저장하므로, 깊은 계층에 있는 컴포넌트간에 상태를 쉽게 공유할 수 있습니다. 이는 <code>prop drilling이라는 문제를 해결</code>하는 데 도움이 됩니다.</p>
<h3 id="5-시간여행-디버깅">5. 시간여행 디버깅</h3>
<p>: Redux는 각 상태 변경을 기록하므로, &#39;시간여행&#39; 디버깅이 가능해집니다. 이는 애플리케이션의 이전 상태로 돌아가거나, 특정 액션을 취소하는 등의 작업을 가능하게 합니다.</p>
<h3 id="6-미들웨어-지원">6. 미들웨어 지원</h3>
<p>: Redux는 미들웨어를 지원하므로, <code>액션을 디스패치하기 전후에 추가적인 로직을 적용</code>할 수 있습니다. 이는 비동기 작업 처리, 로깅, 에러 리포팅 등에 유용합니다.</p>
<br/>

<p>하지만 Redux는 항상 필요한 것은 아닙니다. 작은 프로젝트에서는 종종 오버킬이 될 수 있으며, 복잡성과 관리 비용을 추가로 가져올 수 있습니다. 또한, <code>React의 Context API와 Hooks를 활용하면, 많은 경우에 Redux 없이도 상태 관리를 충분히 수행할 수 있습니다.</code> 따라서 애플리케이션의 규모, 복잡성, 요구사항 등을 고려하여 Redux의 사용 여부를 결정하는 것이 중요합니다.</p>
<hr/>

<h1 id="redux-기본-원리">Redux 기본 원리</h1>
<p><img src="https://velog.velcdn.com/images/view_coding/post/edeb3c5e-b39b-4f08-986e-7414ea8d5b00/image.png" alt=""></p>
<p>Redux의 기본 원리는 <code>상태 관리를 효율적이고 예측 가능하게 만드는 것</code>입니다.</p>
<h3 id="1-store">1. Store</h3>
<p>: Redux에서는 애플리케이션의 <code>모든 상태를 하나의 JavaScript 객체에 저장</code>합니다. 이 객체를 &quot;Store&quot;라고 부릅니다. Store는 <code>읽기 전용</code>이며, 직접 수정할 수 없습니다. Store의 상태를 변경하려면 액션을 발행해야 합니다.</p>
<h3 id="2-action">2. Action</h3>
<p>: 액션은 애플리케이션에서 발생하는 <code>모든 변경 사항을 나타내는 JavaScript 객체</code>입니다. 각 액션은 <code>type 필드를 반드시 포함</code>해야 하며, 이외에도 추가적인 정보를 담을 수 있는 다른 필드들을 가질 수 있습니다.</p>
<h3 id="3-reducer">3. Reducer</h3>
<p>: <code>Reducer는 상태 변경을 처리하는 순수 함수</code>입니다. Reducer는 현재의 상태와 액션을 인자로 받아, 새로운 상태를 반환합니다. Redux 애플리케이션에서는 여러개의 reducer를 가질 수 있으며, 각 reducer는 상태 트리의 특정 부분을 관리합니다.</p>
<br/>

<h3 id="📌-redux의-기본적인-흐름">📌 Redux의 기본적인 흐름</h3>
<p><code>사용자가 애플리케이션에서 인터랙션을 하면, 관련된 액션을 생성</code>
⬇️
<code>생성된 액션은 dispatch 함수를 통해 Redux store에 전달</code>
⬇️
<code>Redux store는 전달받은 액션을 알맞은 reducer에 전달</code>
⬇️
<code>Reducer는 현재 상태와 받은 액션을 바탕으로 새로운 상태를 생성</code>
⬇️
<code>Store는 이 새로운 상태를 현재 상태로 업데이트하고, 이 변경 사항을 애플리케이션에 전달 후 UI는 새로운 상태에 따라 업데이트</code></p>
<br/>

<p>Redux의 이러한 원리는 애플리케이션의 상태 변경을 투명하고 예측 가능하게 만듭니다.</p>
<hr/>

<h3 id="설치-방법">설치 방법</h3>
<blockquote>
<p>npm install @reduxjs/toolkit react-redux</p>
</blockquote>
<h1 id="🤷♀️사용하는-법">🤷‍♀️사용하는 법</h1>
<p><a href="https://velog.io/@view_coding/React-react-redux-%EC%82%AC%EC%9A%A9%EB%B2%95">바로 가기 Click</a></p>
<hr/>

<h1 id="❗redux-및-관련-개념에-대한-용어">❗Redux 및 관련 개념에 대한 용어</h1>
<h3 id="1-store-1">1. Store</h3>
<p>: Redux에서 <code>상태를 저장하는 객체</code>입니다. 이 Store는 애플리케이션의 전역 상태를 저장하고, <code>getState</code>를 사용하여 상태를 조회하거나 <code>dispatch</code>를 사용하여 액션을 발행할 수 있습니다.</p>
<h3 id="2-action-1">2. Action</h3>
<p>: 애플리케이션에서 일어난 변화를 나타내는 객체입니다. 각 액션은 <code>type 속성</code>을 필수로 가지며, 추가적으로 페이로드, 메타데이터 등을 가질 수 있습니다.
type 속성의 값은 일반적으로 <code>문자열</code>이며, 애플리케이션 내에서 유일(unique)해야 합니다.</p>
<p><strong>액션 타입</strong>(Action Type)과 <strong>액션 생성자 함수</strong>(Action Creator)는 리덕스에서 <code>상태 변화를 설명하고 실행</code>하기 위한 중요한 개념입니다.</p>
<h4 id="1-액션-타입action-type">1) 액션 타입(Action Type)</h4>
<p>액션 타입은 <code>상태 변화를 식별하기 위한 문자열 또는 상수 값</code>입니다.
보통 대문자와 밑줄(_)을 사용하여 작성하며, 스네이크 케이스(예: &#39;INCREMENT&#39;, &#39;DECREMENT&#39;)가 일반적입니다.
액션 타입은 액션을 고유하게 식별하는 역할을 하므로 중복되어서는 안됩니다.</p>
<pre><code class="language-js">Copy code
const INCREMENT = &#39;INCREMENT&#39;;
const DECREMENT = &#39;DECREMENT&#39;;</code></pre>
<h4 id="2-액션-생성자-함수action-creator">2) 액션 생성자 함수(Action Creator)</h4>
<p>액션 생성자 함수는 <code>액션 객체를 생성하여 반환하는 함수</code>입니다.
액션 객체는 반드시 type 속성을 가져야 하며, type은 액션 타입을 나타냅니다.
다른 속성들을 포함할 수 있으며, 이러한 속성들은 액션을 설명하고 데이터를 전달하는데 사용됩니다.</p>
<pre><code class="language-js">javascript
Copy code
function increment() {
  return {
    type: INCREMENT
  };
}

function decrement() {
  return {
    type: DECREMENT
  };
}</code></pre>
<p>이렇게 정의된 액션 생성자 함수를 호출하면 해당 액션 객체가 생성되고, 이 객체는 스토어에 디스패치(dispatch)되어 상태 변화를 트리거합니다.</p>
<p>액션 타입과 액션 생성자 함수는 리덕스에서 상태 변화를 예측 가능하고 일관되게 관리하는데 도움을 주는 중요한 구성 요소입니다. 이러한 구조를 사용하면 애플리케이션의 상태 관리를 보다 간결하고 효율적으로 할 수 있습니다.</p>
<h3 id="3-reducer-1">3. Reducer</h3>
<p>: 액션을 처리하는 함수입니다. Reducer는 이전 상태와 액션 객체를 인자로 받아 새로운 상태를 반환합니다. 이 함수는 <code>순수 함수여야 하며, 이전 상태를 직접 수정하면 안됩니다</code>.</p>
<h3 id="4-dispatch">4. Dispatch</h3>
<p>: Redux <code>store에 액션을 전달하는 메서드</code>입니다. Dispatch 메서드는 액션을 인자로 받아 reducer에게 전달하며, 이를 통해 상태를 변경할 수 있습니다.</p>
<h3 id="5-middleware">5. Middleware</h3>
<p>: Redux의 <code>액션 처리 과정 중간에 특정 작업</code>을 할 수 있게 해주는 확장 기능입니다. 예를 들어, 비동기 작업을 처리하거나 액션을 로깅하는 등의 작업을 수행할 수 있습니다.</p>
<h3 id="6-action-creator">6. Action Creator</h3>
<p>: <code>액션 객체를 생성하는 함수</code>입니다. 일반적으로 각 <code>액션 타입마다 하나의 액션 생성자</code>가 있으며, 이를 통해 코드를 간결하게 유지할 수 있습니다.</p>
<h3 id="7-slice">7. Slice</h3>
<p>: Redux Toolkit에서 제공하는 개념으로, <code>관련된 리듀서와 액션들을 한 군데에 모아놓은 것</code>을 말합니다. 이를 사용하면 기존 Redux에서 복잡하게 관리해야 했던 액션 타입, 액션 생성 함수, 리듀서를 한 번에 관리할 수 있습니다.</p>
<h3 id="8-selector">8. Selector</h3>
<p>: Store의 상태를 쉽게 선택할 수 있게 하는 함수입니다. 이를 통해 컴포넌트에서 필요한 상태를 쉽게 조회할 수 있습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[API 키를 사용하는 이유?]]></title>
            <link>https://velog.io/@view_coding/API-%ED%82%A4</link>
            <guid>https://velog.io/@view_coding/API-%ED%82%A4</guid>
            <pubDate>Sat, 08 Jul 2023 07:28:17 GMT</pubDate>
            <description><![CDATA[<p>API 키는 <code>클라이언트가 서버에 요청을 보낼 때 서버가 그 요청을 식별하고, 허가</code>하는 데 사용하는 수단입니다.</p>
<p><img src="https://velog.velcdn.com/images/view_coding/post/e1a69afa-ecea-41f8-a6d8-c2b91f83712c/image.png" alt=""></p>
<h3 id="1-인증">1. 인증</h3>
<p>: 서버는 API 키를 이용해 요청을 보낸 클라이언트를 식별합니다. 이를 통해 허용된 클라이언트만 API를 사용할 수 있게 됩니다.</p>
<h3 id="2-제한">2. 제한</h3>
<p>: API 키는 서비스 제공자가 클라이언트의 요청 수를 제한하는 데 사용됩니다. 이는 서비스의 공정한 사용을 보장하고, 과도한 트래픽으로 인해 서비스가 과부하되는 것을 방지합니다.</p>
<h3 id="3-추적">3. 추적</h3>
<p>: API 키는 서비스 제공자가 사용 패턴을 추적하고, 인기 있는 API, 사용량 등에 대한 통계를 제공하는 데 사용됩니다. 이 정보는 서비스를 개선하고 확장하는 데 도움이 됩니다.</p>
<h3 id="4-보안">4. 보안</h3>
<p>: API 키는 서버가 악의적인 사용자로부터 보호하는 데 도움이 됩니다. 서비스 제공자는 악용되는 키를 차단하거나, 특정 행동을 제한할 수 있습니다.</p>
<br/>

<p>따라서, API 키는 요청의 출처를 인증하고, 서비스의 사용을 제어하며, 사용 패턴을 분석하고, 서비스를 보호하는 중요한 역할을 합니다. 주의할 점은 API 키는 민감한 정보이므로 외부에 노출되지 않도록 주의해야 합니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[React] interface를 여러개 정의할경우]]></title>
            <link>https://velog.io/@view_coding/React-interface%EB%A5%BC-%EC%97%AC%EB%9F%AC%EA%B0%9C-%EC%A0%95%EC%9D%98%ED%95%A0%EA%B2%BD%EC%9A%B0</link>
            <guid>https://velog.io/@view_coding/React-interface%EB%A5%BC-%EC%97%AC%EB%9F%AC%EA%B0%9C-%EC%A0%95%EC%9D%98%ED%95%A0%EA%B2%BD%EC%9A%B0</guid>
            <pubDate>Fri, 23 Jun 2023 08:09:07 GMT</pubDate>
            <description><![CDATA[<h3 id="인터페이스를-여러-개로-나누어-관리하면-코드의-가독성을-높일-수-있습니다">인터페이스를 여러 개로 나누어 관리하면 코드의 가독성을 높일 수 있습니다.</h3>
<p>각 인터페이스는 해당 컴포넌트에서 수행하는 한 가지 주제나 목적에 대한 props를 관리하도록 할 수 있습니다.</p>
<pre><code class="language-ts">import React, { FC } from &#39;react&#39;;

// 사용자 정보를 위한 인터페이스
interface UserInfoProps {
  name: string;
  age: number;
}

// 관리자 권한 정보를 위한 인터페이스
interface AdminProps {
  isAdmin: boolean;
  adminCode: string;
}

// 위 두 인터페이스를 합친 인터페이스
interface MyComponentProps extends UserInfoProps, AdminProps {}

const MyComponent: FC&lt;MyComponentProps&gt; = ({ name, age, isAdmin, adminCode }) =&gt; (
  &lt;div&gt;
    My name is {name} and I am {age} years old.
    {isAdmin &amp;&amp; &lt;div&gt;I have admin code: {adminCode}&lt;/div&gt;}
  &lt;/div&gt;
);</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[React] 다크&라이트 모드 적용하기 (With. Styled-components, Theme, atom, globalStyle)]]></title>
            <link>https://velog.io/@view_coding/Styled-components-with-Theme</link>
            <guid>https://velog.io/@view_coding/Styled-components-with-Theme</guid>
            <pubDate>Mon, 05 Jun 2023 18:15:37 GMT</pubDate>
            <description><![CDATA[<h1 id="1-styled-components의-defaulttheme">1. &quot;styled-components&quot;의 &quot;DefaultTheme&quot;</h1>
<p>테마를 사용하는 경우, TypeScript가 테마의 타입을 알 수 있도록 해야 합니다. 이를 위해 보통 별도의 타입 정의 파일을 만들고, 이 파일에서 <code>DefaultTheme</code>을 확장합니다.</p>
<pre><code class="language-ts">// styled.d.ts

import &quot;styled-components&quot;;

// &quot;DefaultTheme&quot;으로 테마 정의를 확장
declare module &quot;styled-components&quot; {
  export interface DefaultTheme {
    // 테마에 대한 추가 타입 정의
    textColor: string;
    bgColor: string;
    accentColor: string;
  }
}</code></pre>
<p>: DefaultTheme이라는 인터페이스를 확장하여 bgColor, textColor, accentColor라는 프로퍼티를 추가</p>
<blockquote>
<p><code>declare module</code>은 기존 JavaScript 모듈에 대한 <code>타입 선언을 추가하거나 변경</code>할 때 사용하는 키워드입니다.</p>
</blockquote>
</br>

<h1 id="2-프로퍼티-값-지정">2. 프로퍼티 값 지정</h1>
<pre><code class="language-ts">// theme.ts

import { DefaultTheme } from &quot;styled-components&quot;;

export const darkTheme: DefaultTheme = {
  bgColor: &quot;#a29bfe&quot;,
  textColor: &quot;black&quot;,
  accentColor: &quot;#e17055&quot;,
};

export const lightTheme: DefaultTheme = {
  bgColor: &quot;whitesmoke&quot;,
  textColor: &quot;black&quot;,
  accentColor: &quot;#e17055&quot;,
};</code></pre>
<p>: 타입을 지정하고 프로퍼티에 값을 지정</p>
<blockquote>
<p>DefaultTheme으로 타입을 지정하고 프로퍼티에 값을 지정한다는 것은, 우리가 정의하는 테마 객체가 일정한 구조를 가지고, 그 구조에 따라 값을 가지도록 한다는 뜻입니다. 이를 통해 애플리케이션의 <code>스타일을 일관성 있게 유지</code>할 수 있습니다.</p>
</blockquote>
</br>

<h1 id="3-recoil에서-atom-상태관리">3. Recoil에서 atom (상태관리)</h1>
<blockquote>
<p>npm install recoil</p>
</blockquote>
<p><code>atom</code>은 <code>Recoil</code>의 기본 상태 단위로, 상태의 일부를 나타내는 값과 그 값을 변경하는 방법으로 구성됩니다. 각 atom은 <strong>고유한 키</strong>를 가지며, 이 키를 통해 컴포넌트에서 atom에 접근하고 해당 값을 사용하거나 변경할 수 있습니다.</p>
<pre><code class="language-js">// atom.ts

import { atom } from &quot;recoil&quot;;

export const isDarkAtom = atom({
  key: &quot;isDark&quot;, // 유니크한 ID(다른 atom/selector와 관련하여)
  default: false, // 기본값 (초기값)
});</code></pre>
]]></description>
        </item>
    </channel>
</rss>