<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>keyboard_warrior.log</title>
        <link>https://velog.io/</link>
        <description>포기하지 않는 키보드 워리어</description>
        <lastBuildDate>Tue, 29 Oct 2024 11:13:16 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>keyboard_warrior.log</title>
            <url>https://velog.velcdn.com/images/k_warrior27/profile/5e6d744e-ac50-4193-aca5-41c5eb2dfae9/image.jpg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. keyboard_warrior.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/k_warrior27" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[react] Redux 사용하기 - 1. 리덕스 환경 구성]]></title>
            <link>https://velog.io/@k_warrior27/react-Redux-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0-1</link>
            <guid>https://velog.io/@k_warrior27/react-Redux-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0-1</guid>
            <pubDate>Tue, 29 Oct 2024 11:13:16 GMT</pubDate>
            <description><![CDATA[<p>오랜만의 블로그 글 작성이다.</p>
<p>취업은 여전히 어렵지만, 나는 키보드워리어 포기하지 않는다.</p>
<hr>
<h1 id="리덕스-사용법---리덕스-환경-구성">리덕스 사용법 - 리덕스 환경 구성</h1>
<p>오늘은 Redux 사용법 중 환경을 구성하는 방법을 정리하도록 하고, 로그인 등의 로직 설계는 다음 글에서 정리하도록 하겠다.</p>
<p>redux는 클라이언트에서 전역 상태를 관리하기 위해 사용되는 라이브러리로 props drilling 없이 필요한 상태값을 불러올 수 있는 도구이다.</p>
<hr>
<h3 id="redux-redux-toolkit-redux-persist-react-redux에-대한-요약">Redux, Redux Toolkit, Redux Persist, React-Redux에 대한 요약</h3>
<p><img src="https://velog.velcdn.com/images/k_warrior27/post/13687252-7033-42ad-b04c-b60754e85273/image.png" alt=""></p>
<p>우리는 redux에서 권장하는 @reduxjs/toolkit의 다양한 함수를 사용하여 전역 상태 관리 환경을 구성 할 예정이다.</p>
<hr>
<h3 id="redux-설치하기">redux 설치하기</h3>
<pre><code class="language-js">npm install redux react-redux @reduxjs/toolkit redux-persist</code></pre>
<hr>
<h2 id="1-slice-생성하기">1. Slice 생성하기</h2>
<blockquote>
<p><strong>slice란?</strong> Redux Toolkit에서 제공하는 개념으로, 특정 상태와 그에 관련된 액션 및 리듀서들을 하나로 묶은 것입니다. 각각의 슬라이스는 Redux 상태의 한 부분을 관리하며, Redux Toolkit의 createSlice 함수로 생성할 수 있습니다.</p>
</blockquote>
<p><strong>createSlice 함수로 slice를 생성하면 slice가 정의된 action에 따라 reducer(함수)를 실행하여 전역 상태 한가지를 제어한다고 생각하면 편할 듯 하다.</strong></p>
<h4 id="createslice-함수의-필수-항목">createSlice 함수의 필수 항목!!!</h4>
<ul>
<li>name : Redux 액션 타입에 사용되므로 고유한 이름을 설정!!</li>
<li>initialState : 초기 상태값!!</li>
<li>reducers : 상태를 변경할 액션 함수들을 정의!!</li>
<li>extraReducers : 비동기적 로직을 실행하는 액션에 대하여 정리!!</li>
</ul>
<pre><code class="language-js">import {createSlice} from &#39;@reduxjs/toolkit&#39;;

// 초기 상태값읠 정의
const initialSlice = {
  userData : {
    name : &#39;&#39;,
    id : &#39;&#39;,
    role : 0,
  },
  isAuth : false,
  isLoading : false,
  error : &#39;&#39;
}

const userSlice = createSlice({
  name : &#39;user&#39;,
  initialState,
  reducers : {},
  extraReducers : (builder)=&gt;{
    // builder 객체의 addCase메서드를 사용하여 비동기 로직을 정의한다.
    // ex) builder.addCase(비동기함수명.동작의상태 , (state, action)=&gt;{
    //       실행 할 로직을 작성
    //     })
  }
});

// slice의 reducer들을 모두 export 하여 다른 스크립트에서 사용한다!
export default userSlice.reducer;
</code></pre>
<hr>
<h2 id="2-store-생성하기">2. store 생성하기</h2>
<blockquote>
<p><strong>store란?</strong> : 전체 전역 상태를 보관하는 객체로, Redux 상태 관리의 핵심 역할을 합니다. 모든 상태, 액션, 리듀서가 스토어와 연결되어 있으며, React 컴포넌트는 스토어를 통해 상태를 조회하거나 액션을 디스패치하여 상태를 변경합니다.</p>
</blockquote>
<p><strong>말 그대로 전역 상태를 저장하는 저장소라고 생각하면 좋을 듯하다</strong></p>
<h3 id="store를-생성하고-조작하는데-유용하게-쓰이는-함수들">store를 생성하고 조작하는데 유용하게 쓰이는 함수들</h3>
<ul>
<li>combineReducers : 각각의 slice에 정의된 reducer들을 합치는 함수로 store의 여러 전역 상태값을 관리하기 위하여 사용한다.</li>
<li>persistReducer : 단일 reducer 혹은 합친 reducer를 지속시키기 위한 함수</li>
<li>configureStore : store를 생성하는 함수</li>
<li>persistStore : 정의된 store를 지속시키기 위한 함수</li>
</ul>
<h4 id="1-combinereducers-함수의-필수-항목">1. combineReducers 함수의 필수 항목!!!</h4>
<ul>
<li>{리듀서 키 : 리듀서}</li>
</ul>
<pre><code class="language-js">    // 예시
    import {combineReducers} from &#39;@reduxjs/toolkit&#39;;
    import userReducer from &#39;../slices/userSlice.js&#39;;

    const combinedReducer = combineReducers({ user : userReducer });</code></pre>
<h4 id="2-persistreducer-함수의-필수-항목">2. persistReducer 함수의 필수 항목!!!</h4>
<ul>
<li><p>persistConfig : 지속옵션을 선언</p>
</li>
<li><p>combinedReducer : 합쳐진 혹은 하나의 리듀서</p>
<pre><code class="language-js">  // 예시
  import {persistReducer} from &#39;redux-persist&#39;;
  import storage from &#39;redux-persist/lib/storage&#39;;

  // persistReducer 함수에 할당하기 위한 선언
  const persistConfig = {
    // 키 : 값
    // storage or cookie
      key : &#39;root-underdog&#39;,
      storage
  };

  // 
  const persistedReducer = persistReducer(persistConfig, combinedReducer);</code></pre>
</li>
</ul>
<h4 id="3-configuerstore-함수와-persiststore-함수의-필수-항목">3. configuerStore 함수와 persistStore 함수의 필수 항목!!!</h4>
<ol>
<li>configureStore</li>
</ol>
<ul>
<li>reducer : 지속옵션으로 선언된 리듀서</li>
<li>middleware : 미들웨어 함수 (getDefaultMiddleware)</li>
</ul>
<ol start="2">
<li>persistStore</li>
</ol>
<ul>
<li>생성된 스토어</li>
</ul>
<pre><code class="language-js">// 예시
import {configureStore} from &#39;@reduxjs/toolkit&#39;;
import {FLUSH, PAUSE, PERSIST, PURGE, REGISTER, REHYDRATE, persistStore} from &#39;redux-persist&#39;;

// 스토어 생성
export const store = configureStore({
  reducer : persistedReducer,
  middleware : (getDefaultMiddleware) =&gt; 
    getDefaultMiddleware({
      serializableCheck : {
        ignoreActions : [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER]
      }
    })
});

// 스토어를 영구화
export const persistor = persistStore(store);</code></pre>
<hr>
<h2 id="3-provider-와-persistgate로-전역-공간-정하기">3. Provider 와 PersistGate로 전역 공간 정하기</h2>
<blockquote>
<ol>
<li><strong>provider란?</strong> : 전역 공간을 적용하는 일종의 context와 같은 것으로 index.js에 하위 요소를 감싼다. PersistGate를 자식 요소로 둔다.<br /></li>
<li><strong>PersistGate란?</strong> : Redux 스토어의 상태를 로컬 스토리지(localStorage, sessionStorage 등)에 저장하여, 브라우저 새로고침이나 페이지 이동 시에도 상태가 유지되도록 한다.</li>
</ol>
</blockquote>
<blockquote>
<h3 id="-persistgate를-provider로-감싸야-하는-이유-">!!! PersistGate를 Provider로 감싸야 하는 이유 !!!</h3>
<p>PersistGate의 동작 방식: PersistGate는 스토어에서 데이터를 불러오는 작업이 완료될 때까지 컴포넌트 렌더링을 지연시킵니다. 즉, PersistGate 안에 있는 모든 컴포넌트는 데이터가 준비될 때까지 렌더링되지 않습니다.
Provider의 역할: Provider는 스토어를 제공하는 역할만 합니다. 스토어의 데이터가 언제 준비되는지에 대한 제어는 하지 않습니다.
위치에 따른 차이:
PersistGate를 Provider 바깥에 감싸면: 모든 컴포넌트가 데이터가 준비되기 전에 렌더링될 수 있습니다. 이는 데이터가 아직 없음에도 불구하고 UI가 렌더링되어 버리는 문제를 야기할 수 있습니다.
PersistGate를 Provider 안쪽에 감싸면: PersistGate가 데이터를 불러오는 동안 컴포넌트 렌더링이 지연되어, 데이터가 준비된 후에야 UI가 렌더링됩니다.</p>
</blockquote>
<pre><code class="language-javascript">// 예시
import {Provider} from &#39;react-redux&#39;;
import { persistor, store } from &#39;./store/store&#39;;
import { PersistGate } from &#39;redux-persist/integration/react&#39;;

const root = ReactDOM.createRoot(document.getElementById(&#39;root&#39;));
root.render(
  &lt;&gt;
    &lt;Provider store={store}&gt;
      &lt;PersistGate loading={null} persistor={persistor}&gt;
          &lt;App /&gt;
      &lt;/PersistGate&gt;
    &lt;/Provider&gt;
  &lt;/&gt;
);</code></pre>
<p>이렇게 redux 환경을 구성하는 방법을 정리했다. 다음 글에선 로그인 등의 로직을 적용하는 방법을 정리하도록 하겠다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[node] fs 모듈을 활용한 확장자별 파일 분류]]></title>
            <link>https://velog.io/@k_warrior27/node-fs-%EB%AA%A8%EB%93%88%EC%9D%84-%ED%99%9C%EC%9A%A9%ED%95%9C-%ED%99%95%EC%9E%A5%EC%9E%90%EB%B3%84-%ED%8C%8C%EC%9D%BC-%EB%B6%84%EB%A5%98</link>
            <guid>https://velog.io/@k_warrior27/node-fs-%EB%AA%A8%EB%93%88%EC%9D%84-%ED%99%9C%EC%9A%A9%ED%95%9C-%ED%99%95%EC%9E%A5%EC%9E%90%EB%B3%84-%ED%8C%8C%EC%9D%BC-%EB%B6%84%EB%A5%98</guid>
            <pubDate>Sun, 01 Sep 2024 08:34:25 GMT</pubDate>
            <description><![CDATA[<p>node의 fs 모듈을 공부하던 중 파일을 확장자별로 정리하는 스크립트를 작성해보았다.</p>
<hr>
<h2 id="fs-모듈이란">fs 모듈이란?</h2>
<p>fs는 FileSystem의 약자로, fs 모듈은 Node.js에서 파일 입출력 처리를 할 때 사용한다.</p>
<hr>
<h2 id="스크립트">스크립트</h2>
<pre><code class="language-js">const fs = require(&#39;fs&#39;).promises;
const path = require(&#39;path&#39;);

// 디렉토리의 모든 파일을 읽는 메서드 readdir
fs.readdir(__dirname)
  .then((files) =&gt; {

    // 각각의 파일명에 대하여 반복
    files.forEach((file) =&gt; {

      // 파일명을 확장자명과 분리한다.
      file = file.split(&#39;.&#39;);

      // 폴더의 경우 file.length 가 1이다
      if(file.length&gt;1){
        // js 파일인 경우는 건너뛴다
        if(file[1]===&#39;js&#39;){
        }else{

          // 확장자명을 폴더명으로 정하기 위한 변수 선언
          const dName = file[1];

          //  폴더가 없다면 폴더를 생성한다.
          const dirPath = path.join(__dirname,file[1]);
          fs.lstat(dirPath)
          .catch((error)=&gt;{
            fs.mkdir(dName).catch((error)=&gt;{return});
          })
          .finally(()=&gt;{
            // 폴더생성이 끝나면

            //파일명과 확장자명을 다시 합친다.
            file = file.join(&#39;.&#39;);

            // 이동시키기 위한 경로 + 파일명 변수를 만든다.
            const destination = path.join(__dirname,dName,file);

            // 이동시키기를 원하는 파일의 경로 변수를 만든다.
            const target = path.join(__dirname,file);

            // 이동시킬 파일과 이동될 위치를 설정하여 파일을 이동시킨다.
            fs.rename(target,destination)
            .then(()=&gt;{
              console.log(`${target} 가 ${destination}으로 이동!`);
            })
            .catch(console.error);

          })

        }

      }
    })
  })
  .catch(console.error)
  .finally(()=&gt;{
      // 모든 작업이 끝나면 해당 디렉토리에서 폴더 생성과 파일 이동 완료 콘솔을 출력한다.
    console.log(path.basename(__dirname) + &#39;에서 폴더 생성과 파일 이동이 완료되었습니다.&#39;);
  });
</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[React-Native] 개발 환경 구성]]></title>
            <link>https://velog.io/@k_warrior27/React-Native-%ED%95%84%EC%88%98-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8-%EC%A0%95%EB%A6%AC-1</link>
            <guid>https://velog.io/@k_warrior27/React-Native-%ED%95%84%EC%88%98-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8-%EC%A0%95%EB%A6%AC-1</guid>
            <pubDate>Tue, 11 Jun 2024 10:49:07 GMT</pubDate>
            <description><![CDATA[<p>React를 어느정도 익히고 나니 앱 개발에 대해서도 욕심이 생겼다.
하지만 취업 준비도 해야하고, 아직 React에 대해서도 공부가 더 필요한 까닭에 swift를 공부할 시간이 없었고, 그에 따라 관심은 react-native로 향하게 되었다.</p>
<h2 id="모임에서의-프로젝트-제안">모임에서의 프로젝트 제안</h2>
<p>타이밍 좋게도, 동네 지인들과 만든 모임에서 react-native로 앱 개발을 해보자고 제안을 받았고, 현재 앱 기획, 설계를 병행하며 RNa를 공부하고 있다.
이리저리 바쁘지만 학습한 내용을 기록하지 않으면 안될 것 같아 블로그에 작성해야겠다</p>
<h2 id="개발환경">개발환경</h2>
<p>react-native는 하이브리드 앱 개발을 위한 일종의 프레임워크로 React 컴포넌트를 Native 컴포넌트로 매핑해주는 기능을 제공한다, 런타임 환경은 node 의 v8 엔진이다.</p>
<ul>
<li>JSX 코드 작성: 개발자는 React와 같은 방식으로 JSX를 사용하여 컴포넌트를 작성합니다.</li>
<li>JavaScript 런타임 실행: 애플리케이션이 실행되면 JavaScript 런타임이 이 코드를 실행합니다.</li>
<li>브리지 통신: JavaScript 런타임은 네이티브 모듈과 통신하기 위해 브리지를 사용합니다.</li>
<li>네이티브 렌더링: 브리지 통해 전달된 명령에 따라 네이티브 컴포넌트가 렌더링되고, 사용자에게 표시됩니다.</li>
</ul>
<h3 id="개발-환경-구성하기">개발 환경 구성하기</h3>
<blockquote>
<p>Expo : react-native 개발을 도와주는 툴킷이자 플랫폼으로, 개발, 빌드, 배포를 모두 쉽게 할 수 있게 해주는 여러 도구와 서비스를 제공한다.</p>
</blockquote>
<p>개발 환경에서 직접 시뮬레이터(iOS - Xcode)와 에뮬레이터(Android - Android Studio)를 사용할 수 있으나 Expo를 사용해 개발하는것이 간편하기에 이것에 대해 먼저 공부하여 개발환경을 구성하였다.</p>
<ol>
<li><h4 id="expo-cli-설치하기">expo-cli 설치하기</h4>
<blockquote>
<p>npm install -g expo-cli
Mac 유저의 경우 sudo 명령어를 가장 앞에 붙여준다</p>
</blockquote>
</li>
<li><h4 id="expo-cli로-프로젝트-생성하기">expo-cli로 프로젝트 생성하기</h4>
<blockquote>
<p>expo init 프로젝트명</p>
</blockquote>
</li>
</ol>
<p>expo를 사용해 이렇게 간단하게 RNa 개발 환경을 구성할 수 있다.</p>
<hr>
<h2 id="내-모바일에-expo-앱-다운로드-받기">내 모바일에 expo 앱 다운로드 받기</h2>
<p>expo로 구성한 개발 환경의 결과를 확인할 수 있는 expo 앱을 다운받으면 내 모바일 환경에서 앱을 통해 개발된 내용을 앱처럼 확인할 수 있다.</p>
<blockquote>
<ul>
<li>iOS : expo go</li>
</ul>
</blockquote>
<ul>
<li>Android : expo</li>
</ul>
<h3 id="내-모바일에서-확인하기">내 모바일에서 확인하기</h3>
<p>개발중인 디렉토리에서 npm start 명령어를 입력하여 터미널에 나온 QR코드를 모바일로 인식시켜 개발 결과를 확인한다.</p>
<hr>
<h2 id="마치며">마치며</h2>
<p>사실 완벽한 개발환경은 아니지만 RNa를 쉽게 개발할 수 있는 환경을 구성해보았다.
필수 컴포넌트와 스타일 구조도 정리해보도록 하겠다 게으르지 않다면</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[React] Redux란?]]></title>
            <link>https://velog.io/@k_warrior27/React-Redux-%EC%82%AC%EC%9A%A9%EB%B2%95</link>
            <guid>https://velog.io/@k_warrior27/React-Redux-%EC%82%AC%EC%9A%A9%EB%B2%95</guid>
            <pubDate>Sun, 28 Jan 2024 09:55:37 GMT</pubDate>
            <description><![CDATA[<p>Redux에 대해 공부하고 Redux의 사용법에 대해 정리해보고자 한다.</p>
<p>&amp;nbsp</p>
<h2 id="redux란">redux란?</h2>
<blockquote>
<ul>
<li>Redux는 자바스크립트 전역 상태관리 라이브러리이다.</li>
</ul>
</blockquote>
<ul>
<li>Props drilling 이슈를 해결하고 전역 상태 저장소를 제공하여 상태관리를 쉽게 할 수 있도록 설계되었다.</li>
</ul>
<p>쉽게말해 어떤 컴포넌트든 state 값에 접근할 수 있도록 도와주는 전역 상태관리 라이브러리이다.</p>
<p><img src="https://velog.velcdn.com/images/k_warrior27/post/ed5ccedf-50f0-47e0-a7f1-4a7aba8fe8da/image.png" alt=""></p>
<h3 id="redux-설치">redux 설치</h3>
<blockquote>
<p>npm : npm install redux react-redux
yarn : yarn add redux react-redux
&amp;nbsp
 react-redux 추가 패키지도 설치한다.</p>
</blockquote>
<p>&amp;nbsp</p>
<h3 id="redux-환경의-세-가지-구성요소-action-reducer-store">redux 환경의 세 가지 구성요소 (action, reducer, store)</h3>
<ul>
<li><p><strong>action</strong> : data를 뜻하며 새로 할당될 상태값에 영향을 끼치는 정보(ex : login 정보)</p>
</li>
<li><p><strong>reducer</strong> : action을 받아 새로운 스테이트를 생성하는 함수</p>
</li>
<li><p><strong>store</strong> : 상태를 저장하고 상태변경을 감지해 클라이언트에 전송한다. <strong><em>새로고침 시 상태가 리셋된다</em></strong> =&gt; redux-persist로 문제를 해결할 수 있다.</p>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/k_warrior27/post/b8db5147-9779-4937-bdf2-c8e47f2d576d/image.png" alt="action, reducer, store"></p>
<p>&amp;nbsp</p>
<hr>
<h2 id="redux-toolkit이란">redux toolkit이란?</h2>
<blockquote>
<ul>
<li>Redux를 사용하여 상태 관리를 보다 간소하게 하기 위한 공식 라이브러리</li>
</ul>
</blockquote>
<p>&amp;nbsp</p>
<h3 id="redux-toolkit-설치">redux toolkit 설치</h3>
<blockquote>
<p>npm : npm install @reduxjs/toolkit
yarn : yarn add @reduxjs/toolkit</p>
</blockquote>
<p>&amp;nbsp</p>
<h3 id="redux-toolkit의-주요-기능">redux toolkit의 주요 기능</h3>
<blockquote>
<ul>
<li>configureStore() : Redux 개발자 도구와 같은 중요한 구성 요소를 자동으로 설정하여 store를 생성한다.</li>
</ul>
</blockquote>
<ul>
<li>createSlice() : 상태 및 리듀서를 정의하는 데 사용되는 함수로 초기 상태와 리듀서 함수를 입력으로 받아서 슬라이스를 생성하고, 해당 슬라이스에서 사용되는 액션 및 액션 생성자를 자동으로 생성한다.</li>
<li>immer를 사용 : immer 라이브러리를 사용하여 상태를 업데이트하는 데 있어서 불변성을 유지하면서도 더 간단한 구문을 사용할 수 있다.</li>
</ul>
<p>&amp;nbsp</p>
<hr>
<h2 id="redux-persist란">redux-persist란?</h2>
<blockquote>
<ul>
<li>Redux 상태를 지속적으로 유지하고 관리하기 위한 라이브러리</li>
</ul>
</blockquote>
<ul>
<li>Redux 스토어의 상태를 로컬 스토리지, 세션 스토리지 또는 기타 지속성 저장소에 저장하여, 사용자가 애플리케이션을 새로고침하거나 닫은 후에도 상태를 복원할 수 있다.</li>
</ul>
<p>&amp;nbsp</p>
<h3 id="redux-persist-설치">redux-persist 설치</h3>
<blockquote>
<p>npm : npm install redux-persist
yarn : yarn add redux-persist</p>
</blockquote>
<p>&amp;nbsp</p>
<hr>
<h2 id="마치며">마치며</h2>
<p>리덕스가 무엇인지 어떤 목적으로 사용하는지를 대략 알아보았다.</p>
<p>다음 포스팅은 리덕스를 활용해 간단한 로그인 로그아웃 기능을 구현해보도록 하겠다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JavaScript] HTTP 통신하기(fetch API) - 2]]></title>
            <link>https://velog.io/@k_warrior27/JavaScript-HTTP-%ED%86%B5%EC%8B%A0%ED%95%98%EA%B8%B0-2</link>
            <guid>https://velog.io/@k_warrior27/JavaScript-HTTP-%ED%86%B5%EC%8B%A0%ED%95%98%EA%B8%B0-2</guid>
            <pubDate>Thu, 28 Dec 2023 04:49:20 GMT</pubDate>
            <description><![CDATA[<p>JavaScript HTTP 통신 방법을 정리해보는 두 번째 시간이다.
fetch API에 대해 탐구해보도록 하겠다.</p>
<h2 id="필요한-배경지식">필요한 배경지식</h2>
<blockquote>
<ul>
<li>Promise 객체</li>
</ul>
</blockquote>
<ul>
<li>HTTP 에 대한 개념</li>
</ul>
<h2 id="fetch-란">fetch 란?</h2>
<blockquote>
<ul>
<li>HTTP 요청 전송 기능을 제공하는 클라이언트 사이드 WEB API이다.</li>
</ul>
</blockquote>
<ul>
<li>Promise를 반환하기 때문에 가독성이 떨어지는 콜백 헬을 방지할 수 있다.</li>
</ul>
<h2 id="fetch-함수">fetch() 함수</h2>
<blockquote>
<h3 id="fetchinput-init">fetch(input, init)</h3>
<ol>
<li>매개변수</li>
</ol>
</blockquote>
<ul>
<li>input : 요청 정보 혹은 url 경로를 전달한다.</li>
<li>init : 옵션 객체로, 요청에 대한 다양한 설정을 지정할 수 있다.<ul>
<li>method : HTTP 메서드를 지정할 수 있다.(기본값 : &#39;GET&#39;)</li>
<li>headers : 헤더를 나타내는 객체를 지정</li>
<li>body : 요청 바디에 포함될 데이터를 지정</li>
<li>mode: 크로스 오리진 요청 방식을 지정</li>
<li>credentials: 인증 정보를 어떻게 다룰 지 지정</li>
<li>cache: 캐시 사용 여부를 지정</li>
<li>redirect: 리다이렉트 처리 방법을 지정</li>
<li>referrer: Referer 헤더 처리를 지정<ol start="2">
<li>메서드(Promise)</li>
</ol>
</li>
</ul>
</li>
<li>then(res =&gt; {}) : HTTP 통신 성공 시 res 값을 받아 콜백함수를 실행한다.</li>
<li>catch(rej =&gt; {}) : HTTP 통신 실패 시 rej 값을 받아 콜백함수를 실행한다.</li>
</ul>
<h2 id="fetch-api를-이용한-http-통신">fetch API를 이용한 HTTP 통신</h2>
<pre><code class="language-js">    // url 경로 선언
      let num = 1;
      let url = `https://jsonplaceholder.typicode.com/todos/${num}`;
    let data = [];
  // fetch init 매개변수를 설정하지 않는 경우 기본값인 &#39;GET&#39; 메서드로 할당된다.
    fetch(url)
    .then((res) =&gt; {
    console.log(res);
    // HTTP 통신이 성공적인 경우 텍스트 형식의 데이터를 json() 메서드를 사용해 json 형식으로 변환해준다음 리턴한다.
    return res.json();
  })
    .then((res) =&gt; {
    // 리턴된 json 형식의 데이터를 활용해 요소를 조작한다.
    data = res;
    console.log(data);
    document.querySelector(&#39;h1&#39;).innerText = `${data.title}(${data.id})`;
  })
    .catch((rej) =&gt; console.log(rej));

  // btn01 클릭 시 url 매개변수를 조작하여 fetch 함수를 다시 실행한다.
  document.querySelector(&#39;.btn01&#39;).addEventListener(&#39;click&#39;,()=&gt;{
    num = parseInt(prompt(&#39;몇 번 데이터에 접근할까요?&#39;));
    while(isNaN(num)){
      num = parseInt(prompt(&#39;몇 번 데이터에 접근할까요?(숫자만 입력)&#39;));
    }
    url = `https://jsonplaceholder.typicode.com/todos/${num}`;
    fetch(url)
    .then((res) =&gt; res.json())
    .then(res =&gt; {
      data = res;
      document.querySelector(&#39;h1&#39;).innerText=`${data.title}(${data.id})`;
    })
    .catch((rej) =&gt; console.log(rej));
  });

    // btn02 클릭 시 url 매개변수를 조작하고, 데이터를 입력받은 뒤 fetch 함수를 다시 실행해 데이터를 서버로 전송한다.
  // POST 방식으로 데이터 추가하기
  document.querySelector(&#39;.btn02&#39;).addEventListener(&#39;click&#39;,()=&gt;{

    // prompt 창을 열어 데이터(title, useraId)를 입력받는다.
    const title = window.prompt(&#39;title을 입력해주세요&#39;);
    const userId = window.prompt(&#39;userId를 입력해주세요&#39;);

    // POST 전송할 url을 입력
    url = `https://jsonplaceholder.typicode.com/posts`;
    // init 객체에 POST 방식으로 전송할 데이터를 정의한다.
    fetch(url,{
      // method : HTTP 메서드 입력
      method: &#39;POST&#39;,
      // headers : HTTP 헤더 정의(통신할 데이터의 유형을 정의)
      headers: {
        &#39;Content-Type&#39;: &#39;application/json&#39;
      },
      // body : HTTP 통신으로 전송할 데이터를 JSON 문자열 형식으로 정의
      body: JSON.stringify({ title,
        body: &#39;bar&#39;,
        userId})
    })
    .then((res) =&gt; res.json())
    .then(res =&gt; {
      data = res;
      document.querySelector(&#39;h1&#39;).innerText=`${data.title}(${data.id})`;
    })
    .catch((rej) =&gt; console.log(rej));
  });
</code></pre>
<h2 id="결과">결과</h2>
<p><img src="https://velog.velcdn.com/images/k_warrior27/post/5374c0c8-52a7-434c-9538-7432132a34e0/image.gif" alt=""></p>
<h2 id="마치며">마치며</h2>
<p>fetch API를 활용한 HTTP 통신 방법에 대해 정리해보았다.
fetch API는 XMLHttpRequest 객체에 비해 사용 방법이 간단하고 코드 가독성이 좋지만, 브라우저에서 제공하는 API이기 때문에 node 환경에서는 동작하지 않는다는 점, 데이터가 응답되기만 하면 HTTP 통신 성공(200)으로 간주한다는 단점이 있다.
다음 포스팅은 fetch API의 단점을 보완할 수 있는 <strong>axios</strong> 라이브러리를 활용한 javascript HTTP 통신 방법에 대해 정리해 보도록 하겠다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JavaScript] HTTP 통신하기(XMLHttpRequest) - 1]]></title>
            <link>https://velog.io/@k_warrior27/JavaScript-HTTP-%ED%86%B5%EC%8B%A0%ED%95%98%EA%B8%B0-1</link>
            <guid>https://velog.io/@k_warrior27/JavaScript-HTTP-%ED%86%B5%EC%8B%A0%ED%95%98%EA%B8%B0-1</guid>
            <pubDate>Thu, 28 Dec 2023 03:34:27 GMT</pubDate>
            <description><![CDATA[<p>JavaScript HTTP 통신 방법을 정리해보는 첫 번째 시간이다.
<strong>XMLHttpRequest</strong> 객체를 부숴보자</p>
<h2 id="xmlhttprequest란">XMLHttpRequest란?</h2>
<blockquote>
<p>브라우저에서 제공하는 객체로, JavaScript를 사용하여 서버와 비동기 통신을 할 수 있으며, AJAX(Asynchronous JavaScript and XML) 기술을 구현할 수 있다.</p>
</blockquote>
<h2 id="xmlhttprequest-사용법">XMLHttpRequest 사용법</h2>
<ol>
<li><p>XMLHttpRequest 객체의 생성자 함수를 사용해 인스턴스를 생성한다.</p>
</li>
<li><p>생성된 인스턴스의 메서드를 사용해 통신을 정의하고 HTTP 통신을 요청한다.</p>
</li>
</ol>
<p>&amp;nbsp</p>
<h3 id="xmlhttprequest-객체의-주요-메서드와-프로퍼티">XMLHttpRequest 객체의 주요 메서드와 프로퍼티</h3>
<blockquote>
<ul>
<li>open(method, url, async) : XMLHttpRequest(이하 xhr) 객체의 메서드로, HTTP 요청을 초기화하고 전달인자에 메서드와 서버 경로, 통신방법을 정의한다.</li>
<li>send(data) : xhr 객체의 메서드로, open() 메서드에 정의된 방식으로 서버에 요청을 보낸다. POST 요청 시 data를 전달인자로 받는다.</li>
<li>setRequestHeader(header, value) : xhr 객체의 메서드로 open()과 send()사이에 작성하며 HTTP 헤더를 설정한다. 데이터 유형을 정의한다.</li>
</ul>
</blockquote>
<p>거두절미 하고 XMLHttpRequest로 간단한 코드를 작성해보도록 하겠다.
HTTP GET 통신으로 불러온 JSON 텍스트 데이터를 h1 태그로 랜더링하고 버튼 클릭 시 id 값을 하나씩 추가하여 비동기적으로 화면을 랜더링 하는 코드를 작성해 보도록 하겠다.</p>
<hr>
<pre><code class="language-js">  // url 경로 선언
      let num = 1;
      let url = `https://jsonplaceholder.typicode.com/todos/${num}`;

  // XMLHttpRequest 생성자 함수를 사용해 객체의 인스턴스를 생성한다.
    const xhr = new XMLHttpRequest();

    // 생성한 인스턴스의 open 메서드를 사용해 HTTP 요청을 초기화하고 메서드(동작)와 서버 경로를 정의한다.
    // open 메서드의 전달인자는 3개이다.
    // 1. method : 통신 유형 (&#39;GET&#39;, &#39;POST&#39; 등)
    // 2. url : 서버 경로
     // 3. async : 비동기 여부 (기본값 : true)
    xhr.open(&#39;GET&#39;, url);

    // serRequestHeader 메서드를 사용해 통신할 데이터의 유형을 정의한다.
    xhr.setRequestHeader(&#39;content-type&#39;,&#39;application/json&#39;);

    // send 메서드를 사용해 HTTP 통신을 요청한다.
    xhr.send();

    // onload 메서드를 사용하면 xhr 객체가 통신에 성공한 경우(200) 콜백함수를 실행한다.
    xhr.onload(()=&gt;{
        if(request.readyState !== XMLHttpRequest.DONE) return;

        // 통신을 성공(200)하면
          if(request.status === 200){
            console.log(JSON.parse(request.response));
              // JSON 문자열을 파싱하여 데이터로 저장한다.
            const data = JSON.parse(request.response);
            console.log(data[&#39;title&#39;]);
              // 요소에 데이터를 출력한다.
            document.querySelector(&#39;h1&#39;).innerText=`${data[&#39;title&#39;]}(${data[&#39;id&#39;]})`;
          }else{
            console.log(&#39;no&#39;);
          }
     });

    // 버튼 클릭 시 url 매개변수를 바꾸어 다시 요청한다.
    document.querySelector(&#39;.btn01&#39;).addEventListener(&#39;click&#39;,()=&gt;{
          num = num+1;
          url = `https://jsonplaceholder.typicode.com/todos/${num}`;
          console.log(url);
          // 오픈하고 =&gt; 데이터 요청 방식 정의
          request.open(&#39;GET&#39;,url);
          // 데이터 타입 정의
          request.setRequestHeader(&#39;content-type&#39;,&#39;application/json&#39;);
          // 요청 보내기
          request.send();
    });
</code></pre>
<p>&amp;nbsp</p>
<h2 id="결과">결과</h2>
<p><img src="https://velog.velcdn.com/images/k_warrior27/post/03220757-756b-41cd-9d1a-8a0534430de5/image.gif" alt=""></p>
<hr>
<h2 id="마치며">마치며</h2>
<p>XMLHttpRequest 객체를 활용해 간단한 HTTP 통신을 해 보았다.
다음 게시글은 fetch API를 활용한 HTTP 통신을 정리해보도록 하겠다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[HTTP란 무엇인가?]]></title>
            <link>https://velog.io/@k_warrior27/HTTP%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80</link>
            <guid>https://velog.io/@k_warrior27/HTTP%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80</guid>
            <pubDate>Wed, 27 Dec 2023 05:29:55 GMT</pubDate>
            <description><![CDATA[<h2 id="http란">HTTP란?</h2>
<blockquote>
<ul>
<li>HTTP(HyperText Transfer Protocol)는 W3에서 클라이언트와 서버 간에 데이터를 주고받기 위한 텍스트 기반의 통신 규약으로 인터넷에서 데이터를 주고받을 수 있는 프로토콜이다. 다양한 메서드(HTTP 동작)를 사용하여 특정 작업을 수행한다.</li>
</ul>
</blockquote>
<ul>
<li>여기서 오가는 데이터는 텍스트 형식이며, 대표적 데이터 형식은 HTML, JSON 데이터, XML 등이 있다.</li>
</ul>
<p>쉽게 말해 W3에서 클라이언트와 서버 사이의 데이터를 주고받기 위한 텍스트 기반 통신 규악이다.</p>
<h2 id="http-동작이란">HTTP 동작이란?</h2>
<blockquote>
<p>클라이언트 즉, 사용자가 브라우저를 통해서 어떠한 서비스를 url을 통하거나 다른 것을 통해서 요청(request)을 하면 서버에서는 해당 요청사항에 맞는 결과를 찾아서 사용자에게 응답(response)하는 형태로 동작한다.</p>
</blockquote>
<ul>
<li>요청(request) : 클라이언트 -&gt; 서버</li>
<li>응답(response) : 서버 -&gt; 클라이언트</li>
<li>요청 및 응답 메시지는 헤더와 본문으로 이루어져 있으며, 사람이 읽을 수 있는 형태로 표현된다.<blockquote>
</blockquote>
참고로 HTTP 메서드는 그 자체로 기능을 가지고 있는것이 아닌 통신 약속으로 서버 내에서 메서드에 걸맞는 기능을 코드로 구현해두어야 한다.</li>
</ul>
<h2 id="http-응답-코드">HTTP 응답 코드</h2>
<ul>
<li><p>1XX : 요청을 받았으며 작업을 계속한다.</p>
</li>
<li><p>2XX : 이 클래스의 상태 코드는 클라이언트가 요청한 동작을 수신하여 이해했고 승낙했으며 <strong>성공</strong>적으로 처리했음을 가리킨다.</p>
</li>
<li><p>3XX : 요청을 마치기 위해 클라이언트가 추가 동작을 취해야 한다.</p>
<ul>
<li>304(수정되지 않음): 마지막 요청 이후 요청한 페이지는 수정되지 않았다. 서버가 이 응답을 표시하면 페이지의 콘텐츠를 표시하지 않는다. 요청자가 마지막으로 페이지를 요청한 후 페이지가 변경되지 않으면 이 응답(If-Modified-Since HTTP 헤더라고 함)을 표시하도록 서버를 구성해야 한다.</li>
</ul>
</li>
<li><p>4XX : 클라이언트에 오류가 있음을 나타낸다. (요청오류, 클라이언트 오류)</p>
<ul>
<li>404(Not Found, 찾을 수 없음): 서버가 요청한 페이지(Resource)를 찾을 수 없다. 예를 들어 서버에 존재하지 않는 페이지에 대한 요청이 있을 경우 서버는 이 코드를 제공한다.</li>
<li>405(허용되지 않는 메소드): 요청에 지정된 방법을 사용할 수 없다. 예를 들어 POST 방식으로 요청을 받는 서버에 GET 요청을 보내는 경우, 또는 읽기 전용 리소스에 PUT 요청을 보내는 경우에 이 코드를 제공한다.</li>
<li>406(허용되지 않음): 요청한 페이지가 요청한 콘텐츠 특성으로 응답할 수 없다.</li>
</ul>
</li>
<li><p>5XX : 서버가 유효한 요청을 명백하게 수행하지 못했음을 나타낸다. (응답오류, 서버 오류)</p>
<ul>
<li>500(내부 서버 오류): 서버에 오류가 발생하여 요청을 수행할 수 없다.</li>
<li>501(구현되지 않음): 서버에 요청을 수행할 수 있는 기능이 없다. 예를 들어 서버가 요청 메소드를 인식하지 못할 때 이 코드를 표시한다.</li>
<li>502 (Bad Gateway, 불량 게이트웨이): 서버가 게이트웨이나 프록시 역할을 하고 있거나 또는 업스트림 서버에서 잘못된 응답을 받았다.</li>
</ul>
</li>
</ul>
<h3 id="주요-http-메서드">주요 HTTP 메서드</h3>
<ol>
<li><p>GET</p>
<ul>
<li>클라이언트에서 서버로 데이터를 요청 시 사용</li>
<li>주로 정보를 요청하는 데 사용되며, URL의 일부로 데이터를 전송</li>
<li>보통 캐시 가능하며, 브라우저에서는 주소 표시줄에 나타납니다.</li>
</ul>
</li>
<li><p>POST</p>
<ul>
<li>클라이언트에서 서버로 데이터를 전송 시 사용</li>
<li>주로 서버에 리소스를 제출하거나 업데이트할 때 사용되며, 데이터는 HTTP 본문에 담겨 전송</li>
<li>민감한 데이터 전송에 사용되며, 길이 제한이 없어 GET보다 많은 양의 데이터를 전송할 수 있음</li>
</ul>
</li>
<li><p>PUT</p>
<ul>
<li>클라이언트에서 서버로 데이터를 보내는데 사용</li>
<li>주로 리소스를 생성하거나 업데이트할 때 사용되며, 전송된 데이터는 요청된 리소스로 대체된다.</li>
</ul>
</li>
<li><p>DELETE</p>
<ul>
<li>클라이언트에서 서버로 데이터 삭제를 요청하는 데 사용</li>
<li>주로 지정된 리소스를 삭제하라는 의미이며, 실제로 리소스가 삭제되는 것은 서버에 따라 다르다.</li>
</ul>
</li>
</ol>
<hr>
<h2 id="javascript를-활용한-http-통신방법">JavaScript를 활용한 HTTP 통신방법</h2>
<p>JavaScript로 HTTP 통신을 수행하는 방법에는 크게 3가지가 있다.</p>
<ol>
<li>XMLHttpRequest 객체를 활용 : 브라우저에서 제공하는 객체로 비동기적인 HTTP 요청을 생성하고 처리하는 데 사용</li>
<li>fetch API 사용 : 웹 브라우저 환경에서 기본적으로 사용 가능한 API로 Promise를 반환하며, HTTP 요청 및 응답을 다룬다.</li>
<li>axios 라이브러리 사용 : 브라우저 및 Node.js에서 비동기 HTTP 요청과 응답을 수행한다. Axios는 Promises를 기반으로 한 API를 제공하며, JSON 데이터를 자동으로 파싱하는 기능을 제공한다.</li>
</ol>
<hr>
<h2 id="마치며">마치며</h2>
<p>http 통신 규약에 대한 정보를 알아봤다.
rest api에 대한 정보와 ajax에 대해서도 정리해 볼 필요가 있겠다.
다음 포스팅은 JavaScript를 활용한 http 통신 방법을 정리한 글을 게시하도록 하겠다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[npm이란 무엇인가?]]></title>
            <link>https://velog.io/@k_warrior27/npm%EC%9D%B4%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80</link>
            <guid>https://velog.io/@k_warrior27/npm%EC%9D%B4%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80</guid>
            <pubDate>Sun, 24 Dec 2023 07:51:11 GMT</pubDate>
            <description><![CDATA[<p>javascript를 node v8 런타임 환경에서 실행하면서도 정작 npm이 무엇인지 yarn과의 차이는 무엇인지를 알지 못했다.</p>
<p>이 기회에 정리해보도록 하겠다.</p>
<hr>
<p>두 패키지 매니저에 대해 알아보기 위해 ChatGPT를 적극적으로 활용했다.</p>
<h2 id="npm이란">npm이란?</h2>
<blockquote>
<p>JavaScript 프로젝트에서 패키지 관리를 위한 도구로 사용되는 node 패키지 툴입니다. 이 도구는 JavaScript 및 Node.js 기반의 프로젝트에서 외부 라이브러리 및 모듈을 손쉽게 관리할 수 있도록 도와줍니다. - ChatGPT</p>
</blockquote>
<p>쉽게말해 node 런타임 환경에서 javascript프로젝트 공식 패키지 관리 도구이다.</p>
<ul>
<li><p>기본 명령어</p>
<ol>
<li>npm install: 프로젝트에 필요한 패키지를 설치한다.<ol start="2">
<li>npm install <package-name>: 특정 패키지를 설치한다.</li>
<li>npm init: 프로젝트를 초기화한다.</li>
</ol>
</li>
</ol>
</li>
<li><p>package.json : 프로젝트의 구성 및 의존성 정보를 담고 있는 파일로, npm install 명령을 실행하면 이 파일에 명시된 패키지들이 설치된다.</p>
</li>
</ul>
<p>&amp;nbsp</p>
<h2 id="yarn이란">yarn이란?</h2>
<blockquote>
<p>Yarn은 Meta(Facebook)에서 개발한 패키지 매니저로, npm과 유사하지만 일부 기능에서 차이가 있습니다. 주로 패키지 설치 속도 및 보안 측면에서 성능 향상을 제공합니다. - ChatGPT</p>
</blockquote>
<ul>
<li><p>기본 명령어</p>
<ol>
<li>yarn install: 프로젝트에 필요한 패키지를 설치한다.<ol start="2">
<li>yarn add <package-name>: 특정 패키지를 설치한다.</li>
<li>yarn init: 프로젝트를 초기화합니다.</li>
</ol>
</li>
</ol>
</li>
<li><p>yarn.lock: 패키지의 정확한 버전 및 의존성 정보를 담고 있는 파일로, 이를 통해 프로젝트의 빌드 환경을 더 예측 가능하게 만든다.</p>
</li>
</ul>
<p>&amp;nbsp</p>
<h2 id="npm과-yarn의-차이점">npm과 yarn의 차이점</h2>
<ul>
<li><p>성능 및 속도: Yarn은 패키지 설치 및 의존성 해결에 있어서 npm보다 빠르다고 알려져 있습니다.</p>
</li>
<li><p>보안: Yarn은 패키지의 무결성을 보장하기 위해 checksum을 사용하여 보안 측면에서 강화되었습니다.</p>
</li>
<li><p>패키지 캐싱: Yarn은 이전에 설치한 패키지를 캐싱하여 중복 설치를 최소화하고 더 빠른 설치를 제공합니다.</p>
<p>&amp;nbsp</p>
</li>
</ul>
<hr>
<h2 id="-d란-무엇인가">-D란 무엇인가?</h2>
<p>  npm install 과 yarn add 명령어를 사용할 때 그냥 package-name을 입력하는 경우와 -D를 입력하는 경우의 차이에 대해 알아본다.</p>
<h3 id="1-그냥-설치하는-경우">1. 그냥 설치하는 경우</h3>
<ul>
<li><p>패키지를 프로젝트의 일반적인 의존성으로 추가, 프로덕션 환경 및 개발 환경에서 모두 필요한 경우에 사용한다. 예를들어, 프로젝트의 주요 기능을 담당하는 라이브러리나 모듈을 설치할 때 사용된다.</p>
</li>
<li><p>일반적인 패키지는 dependencies 섹션에 추가되어, 프로덕션 및 개발 환경 모두에서 필요로 한다.</p>
<p><img src="https://velog.velcdn.com/images/k_warrior27/post/f2ce394c-fea0-4dd9-b05a-e83a06ccf2c9/image.png" alt=""></p>
</li>
</ul>
<p>위는 package.json의 dependencies 데이터 부분을 캡쳐 한 사진이다.
  react-router-dom, use-immer 등이 설치된 것을 확인할 수 있다.</p>
<p>  &amp;nbsp</p>
<h3 id="2--d-또는---dev를-입력하는-경우">2. -D 또는 --dev를 입력하는 경우</h3>
<ul>
<li><p>패키지를 프로젝트의 <strong>개발</strong> 의존성으로 추가, 개발 의존성은 주로 코드 작성, 테스트, 빌드 등의 개발 과정에서만 필요한 패키지를 의미한다. 이러한 패키지는 프로덕션 환경에서는 필요하지 않을 수 있다.</p>
</li>
<li><p>패키지가 devDependencies 섹션에 추가되며, 프로덕션 환경에서 패키지가 필요하지 않다.</p>
<p><img src="https://velog.velcdn.com/images/k_warrior27/post/3056ff23-4d58-434a-b1a0-4b30781fd7f2/image.png" alt=""></p>
</li>
</ul>
<pre><code>  위는 package.json의 devDependencies 데이터 부분을 캡쳐 한 사진이다.</code></pre><p>   esline가 설치된 것을 확인할 수 있다.</p>
<p>  &amp;nbsp</p>
<hr>
<h2 id="마치며">마치며</h2>
<p>프로젝트 관리에 대한 정보를 직접 확인할 수 있는 지식을 얻을 수 있었다.
  더 내실있는 개발자가 되기 위해 코드에 관한 지식 뿐 아닌 개발 환경 및 툴 들에 대해서도 정리할 필요가 있겠다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[React] React-Router 사용법]]></title>
            <link>https://velog.io/@k_warrior27/React-React-Router-%EC%82%AC%EC%9A%A9%EB%B2%95-1</link>
            <guid>https://velog.io/@k_warrior27/React-React-Router-%EC%82%AC%EC%9A%A9%EB%B2%95-1</guid>
            <pubDate>Sun, 24 Dec 2023 06:28:02 GMT</pubDate>
            <description><![CDATA[<p>리액트 라우터 사용법을 정리해보고자 한다.</p>
<h2 id="리액트-라우터란">리액트 라우터란?</h2>
<ul>
<li>CSR(Client Side Routing)이 가능하게 해주는 라이브러리로 경로가 바뀌는 경우, 서버에 별다른 요청을 보내지 않고 클라언트의 브라우저 단에서만 여러 페이지를 바꾸며 방문하는 기능을 제공한다.</li>
<li>Single Page Application(SPA) 을 유지하면서 멀티 페이지의 장점을 그대로 사용할 수 있다.</li>
<li>history 를 이용할 수 있어 페이지를 다시 로드했을 때 원하는 컴포넌트를 볼 수 있다.</li>
</ul>
<blockquote>
<h3 id="라우팅이란">라우팅이란??</h3>
<p>네트워크에서 경로를 선택하는 프로세스로 새로운 url 경로를 입력하면 url에 해당하는 새로운 <strong><em>페이지를 서버에 요청해</em></strong> 새로운 HTML을 받아와 페이지 전체가 업데이트 되는 것을 의미한다.</p>
</blockquote>
<blockquote>
<p>Chat-gpt : React Router는 React 애플리케이션에서 네비게이션을 관리하기 위한 라이브러리입니다. react-router-dom은 React Router의 웹 애플리케이션을 위한 도메인을 처리하는 패키지입니다. 이 라이브러리를 사용하면 단일 페이지 애플리케이션(SPA)에서 여러 페이지로의 전환과 URL 변경에 대한 라우팅을 쉽게 처리할 수 있습니다.</p>
</blockquote>
<hr>
<h2 id="리액트-라우터에서-제공하는-라우터-제공자-컴포넌트-훅스">리액트 라우터에서 제공하는 라우터, 제공자, 컴포넌트, 훅스</h2>
<blockquote>
<ol>
<li>createBrowserRouter : 데이터 API를 지원하는 라우터 중 하나로 DOM History API를 사용하여 URL을 업데이트하고 기록 스택을 관리한다.</li>
<li>RouterProvider : 라우터 제공자 중 하나로 모든 데이터 라우팅 요소는 RouterProvider에 전달되어 앱을 렌더링하고 나머지 데이터 API를 활성화한다.</li>
<li>Outlet : 라우터 컴포넌트 중 하나로 RouterProvider의 요소 내에서 경로에 따라 컴포넌트를 랜더링 하는 컴포넌트이다.</li>
<li>Link : 라우터 컴포넌트 중 하나로 html요소 중 a태그와 같은 기능을 한다.</li>
<li>useParams : 라우터에서 제공하는 훅 중 하나로 url 매개변수의 key-value 쌍을 객체로 반환해준다.</li>
<li>useNavigate : 라우터에서 제공하는 훅 중 하나로 OM History API를 사용하여 URL을 업데이트하고 기록 스택을 관리한다.</li>
</ol>
</blockquote>
<hr>
<h2 id="리액트-라우터-설치하기">리액트 라우터 설치하기</h2>
<blockquote>
<p>npm : npm install react-router-dom
yarn : yarn add react-router-dom</p>
</blockquote>
<hr>
<h2 id="리액트-라우터-사용법">리액트 라우터 사용법</h2>
<h3 id="1-라우팅을-할-컴포넌트에-createbrowserrouter-함수로-router-객체를-생성">1. 라우팅을 할 컴포넌트에 createBrowserRouter 함수로 router 객체를 생성</h3>
<blockquote>
<ul>
<li>createBrowserRouter : 라우터 객체를 생성하며 라우팅 될 컴포넌트와 경로에 대한 정보들을 전달받는다.</li>
</ul>
</blockquote>
<ul>
<li>RouterProvider : 라우팅 요소를 보여주는 제공자로 router 속성에 생성된 라우터 객체를 할당받는다.</li>
</ul>
<pre><code class="language-js">    // react-router-dom 으로부터 createBrowserRouter, RouterProvider 를 불러온다.
    import {createBrowserRouter, RouterProvider} from &#39;react-router-dom&#39;;

    function app(){

      // createBrowserRouter 함수를 사용해 라우터 객체를 생성해준다.
      // createBrowserRouter 는 배열을 인자로 받으며 배열의 값은 객체 형식이다.
      const router = createBrowserRouter([
        {
          // 첫 번째 객체로 index 페이지를 설정해준다.
          path : &#39;/&#39;,
          element : &lt;Index /&gt;,
          // children 프로퍼티에 자손 경로와 컴포넌트를 입력해준다.
          children : [{
              // 인덱스 페이지에서 보일 컴포넌트의 경우 index 프로퍼티를 true로 할당해준다.
            index : true,
              element : &lt;Home /&gt;
             },
          {
            // 경로에 따라 컴포넌트를 라우팅 할 경우 path 프로퍼티에 경로를 문자열로 할당한다.
              path : &#39;/products&#39;,
            element : &lt;Products /&gt;
          },
          {
            // 컴포넌트에서 사용할 param 값을 경로 마지막 부분에 설정해줄 수 있다.
            path : &#39;/products/detail/:code&#39;,
            elemeht : &lt;ProductDetail /&gt;
          }  
          ]}
      ]);

      return (
          &lt;&gt;
            // RouterProvider 가 라우팅 될 컴포넌트들을 보여준다.
            &lt;RouterProvider router={router} /&gt;
          &lt;/&gt;);
    }

</code></pre>
<p>&emsp;</p>
<h3 id="2-useparams-와-usenavigate-사용하기">2. useParams 와 useNavigate 사용하기</h3>
<blockquote>
<ul>
<li>useParams : 라우터 객체에 작성된 url 매개변수를 객체로 구조분해할당 할 수 있다.</li>
</ul>
</blockquote>
<ul>
<li>useNavigate : navigate 객체를 생성해 경로를 이동할 수 있고, 저장된 이전 경로로 이동할 수 있다.</li>
</ul>
<pre><code class="language-js">    // useParams를 사용해 경로에 작성된 변수를 사용할 수 있다.
    // useNavigate를 사용해 경로를 설정할 수 있고, 이전 경로를 기억해 이동할 수 있다.
    import {useParams, useNavigate} from &#39;react-router-dom&#39;;

    function ProductDetail(props){

      // createBrowserRouter 함수에 작성해 둔 param 값을 객체로 할당받아 사용할 수 있다.
      const {code} = useParams();

      // useNavigate를 사용해 navigate 객체 생성
      const navigate = useNavigate();

      return (
        &lt;&gt;
            // 뒤로가기를 사용할 경우 navigate 객체에 -1을 전달한다.
            &lt;button onClick={()=&gt; navigate(-1)}&gt;뒤로가기&lt;/button&gt;
            {code} 번 상품입니다.
        &lt;/&gt;
      );
    }
    export default ProductDetail;</code></pre>
<p>&emsp;</p>
<h3 id="3-outlet으로-랜더링-될-컴포넌트를-레이아웃">3. Outlet으로 랜더링 될 컴포넌트를 레이아웃</h3>
<pre><code class="language-js">    import {Outlet} from &#39;react-router-com&#39;;

    function Index(props){

      return(
      &lt;&gt;
        // Header 는 경로가 바뀌어도 유지된다!!!
        &lt;Header /&gt;

        // 경로가 바뀌면 랜더링 되는 부분
        &lt;Outlet /&gt;
      &lt;/&gt;
      );
    }</code></pre>
<p>&emsp;</p>
<h3 id="4-link-태그-사용">4. Link 태그 사용</h3>
<pre><code class="language-js">    import React from &#39;react&#39;;
import {Link} from &#39;react-router-dom&#39;;

function Header(props) {

  const style = {
    flex : {
      display : &#39;flex&#39;,
      listStyle : &#39;none&#39;
    }
  }

  return (
    &lt;div&gt;
      헤더 입니다.
      &lt;ul style={style.flex}&gt;
        // 헤더 gnb로 클릭 시 경로가 이동되도록 한다.
        &lt;li&gt; &lt;Link to=&#39;/&#39;&gt;홈&lt;/Link&gt;&lt;/li&gt;
        &lt;li&gt; &lt;Link to=&#39;/products&#39;&gt;상품리스트&lt;/Link&gt;&lt;/li&gt;
      &lt;/ul&gt;
    &lt;/div&gt;
  );
}

export default Header;</code></pre>
<hr>
<h2 id="실행결과">실행결과</h2>
<p><img src="https://velog.velcdn.com/images/k_warrior27/post/debc3d7d-8f3c-4b56-a328-d90d36022bd8/image.gif" alt=""></p>
<p>헤더는 유지되고 아래의 아웃렛에 경로와 url매개변수(params)에 따라 랜더링 되는 컴포넌트가 다른 것을 확인할 수 있다.</p>
<hr>
<h2 id="마치며">마치며</h2>
<p>리액트 라우터에 대해 알아보았다.
리액트 라우터에 대해 이해하기 위해선 라우팅에 대한 개념과 라우터가 제공하는 여러 요소의 종류를 이해할 필요가 있겠다.</p>
<p><strong>리액트 라우터가 제공하는 기억해야 할 네 가지 요소들</strong></p>
<ul>
<li>라우터(Router) : 라우팅 객체</li>
<li>제공자(Provider) : 라우팅 객체를 전달받아 컴포넌트를 내보내는 객체</li>
<li>컴포넌트(Component) : 라우터에서 제공하는 컴포넌트</li>
<li>훅(Hook) : 라우터에서 제공하는 훅(함수)</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[React] useEffect 사용법]]></title>
            <link>https://velog.io/@k_warrior27/React-useEffect-%EC%82%AC%EC%9A%A9%EB%B2%95</link>
            <guid>https://velog.io/@k_warrior27/React-useEffect-%EC%82%AC%EC%9A%A9%EB%B2%95</guid>
            <pubDate>Sat, 02 Dec 2023 13:06:12 GMT</pubDate>
            <description><![CDATA[<p>useEffect 사용법을 정리해보겠다.</p>
<hr>
<h3 id="알아야-할-문법">알아야 할 문법</h3>
<blockquote>
<p>useState() 사용법
localStorage
JSON 객체와 정적메서드 stringify(), parse()</p>
</blockquote>
<hr>
<h3 id="useeffect-란">useEffect 란?</h3>
<ul>
<li>React 에서 제공하는 hook으로 특정 데이터가 변경되는 경우 컴포넌트를 랜더링하는 기능을 제공</li>
<li>React 생명주기에 맞춰 특정 컴포넌트를 랜더링 하는 기능을 제공</li>
</ul>
<h3 id="react-생명주기">React 생명주기</h3>
<ol>
<li>생성(마운트) : 컴포넌트가 생성되어 DOM 요소를 구성할 때</li>
<li>업데이트 : 컴포넌트의 props 나 state 가 변경될 때</li>
<li>해제(언마운트) : 컴포넌트가 DOM 요소에서 제거될 때</li>
</ol>
<hr>
<h3 id="useeffect-문법">useEffect 문법</h3>
<blockquote>
<p>useEffect( ()=&gt;{  }, [] );</p>
</blockquote>
<ol>
<li>첫 번째 전달인자는 콜백함수로 특정 상황에 실행할 코드를 작성한다.</li>
<li>두 번째 전달인자는 의존 배열로 배열에 특정 데이터를 명시하면 데이터가 변경될 때(업데이트) useEffect의 실행문이 실행된다. 배열이 빈 경우 컴포넌트가 생성(마운트)될때만 실행된다.</li>
<li>콜백함수에 return 문을 작성해주는 경우 컴포넌트가 해제(언마운트)될 때 코드가 실행된다.</li>
</ol>
<ul>
<li>주의할 점 : useEffect는 컴포넌트가 처음 마운트 될 때(DOM 요소 구성 직후에) 실행문을 실행하지만 useState는 함수형 컴포넌트의 return 문을 DOM 요소를 구성할 때 실행되기 때문에 state 값이 useEffect로 부터 값을 받아오기만 한다면 오류가 발생할 수 있다!
코드 순서 : useState =&gt; useEffect</li>
</ul>
<hr>
<h3 id="useeffect와-localstorage-객체를-사용해-데이터를-저장하기">useEffect와 localStorage 객체를 사용해 데이터를 저장하기</h3>
<blockquote>
<ol>
<li>localStorage에서 저장된 데이터를 가져오고</li>
<li>memos 가 변경될 때(업데이트) 마다 useEffect를 사용해 localStorage에 데이터를 저장</li>
</ol>
</blockquote>
<pre><code class="language-js">    // useEffect 를 react로 부터 import
    import React,{useState, useEffect} from &#39;react&#39;;


    // 메모 함수형 컴포넌트
    function Memo(props){

      // 로컬호스트로부터 데이터를 불러오는 함수
        const getMemosFromLocalHost = ()=&gt;{
          // 로컬호스트의 getItem 메서드를 사용해 데이터를 불러온다.
        const data = localStorage.getItem(&#39;memos-1234&#39;);

        // 로컬호스트에 &#39;memos-1234&#39;에 해당하는 값이 있다면 파싱하여 리턴
        // 해당하는 값이 없다면 선언해둔 initialMemos 변수를 리턴
        return data ? JSON.parse(data) : initialMemos;
        }

      // 미리 할당해둔 메모 초기값
      const initialMemos =[...]

      // memos 스테이트 값을 로컬호스트로부터 받아와 할당한다.
        const [memos, setMemos] = useState(()=&gt;getMemosFromLocalHost());

      // useEffect 사용
        useEffect(()=&gt;{

        // useEffect 가 실행문을 실행하는지 여부를 알아보기 위한 log
        console.log(&#39;useEffect 실행됨!!&#39;);

        // 로컬호스트의 setItem 메서드를 사용해 값을 로컬호스트에 저장
        // 첫 번째 전달인자는 key
        // 두 번째 전달인자는 JSON 객체의 stringify 정적 메서드를 사용해 직렬화 하여 작성
        localStorage.setItem(&#39;memos-1234&#39;,JSON.stringify(memos));

        // 아래의 의존 배열에 변경될 때 마다 useEffect를 실행할 데이터(memos state)를 명시해준다.
        },[memos]);

      // 요소 리턴
      return (...);

    }</code></pre>
<hr>
<h3 id="실행결과">실행결과</h3>
<p><img src="https://velog.velcdn.com/images/k_warrior27/post/fd4a33c1-852f-4fa6-b598-57cad5f3b8df/image.gif" alt=""></p>
<ul>
<li>useEffect 실행문은 컴포넌트가 처음 랜더링 될 때와 의존배열에 담긴 데이터가 변경될 때 마다 실행되는 것을 확인할 수 있다.</li>
<li>localStorage에 값을 저장하여 브라우저가 새로고침 되어도 데이터가 유지되는 것을 확인할 수 있다.</li>
</ul>
<hr>
<h3 id="마치며">마치며</h3>
<p>useEffect 를 사용하는 방법과 localhost를 이용하는 방법을 알아보았다.
다음시간엔 useQuery와 외부 api 데이터를 브라우저에서 업데이트하는 방법을 살펴보도록 하겠다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[코테 풀기] 문자열 내 p와 y의 개수(JS)]]></title>
            <link>https://velog.io/@k_warrior27/%EC%BD%94%ED%85%8C-%ED%92%80%EA%B8%B0-%EB%AC%B8%EC%9E%90%EC%97%B4-%EB%82%B4-p%EC%99%80-y%EC%9D%98-%EA%B0%9C%EC%88%98JS</link>
            <guid>https://velog.io/@k_warrior27/%EC%BD%94%ED%85%8C-%ED%92%80%EA%B8%B0-%EB%AC%B8%EC%9E%90%EC%97%B4-%EB%82%B4-p%EC%99%80-y%EC%9D%98-%EA%B0%9C%EC%88%98JS</guid>
            <pubDate>Sun, 26 Nov 2023 08:20:22 GMT</pubDate>
            <description><![CDATA[<p>오늘도 코테문제 풀어본다.
데이터 처리할 때 간과하기 쉬운 내용이 다뤄진 문제를 가져왔다.
언어는 javascript
문제는 <a href="https://school.programmers.co.kr/learn/courses/30/lessons/12916#">[Link] 프로그래머스</a> 에서 풀어볼 수 있다.</p>
<hr>
<blockquote>
<ul>
<li>문제 : 주어진 문자열에서 &#39;p&#39; 와 &#39;y&#39;의 개수가 같은 경우 true를 그렇지 않은 경우 false 를 리턴하는 함수를 제작, 두 문자가 모두 0 개라면 true를 출력한다.</li>
</ul>
</blockquote>
<hr>
<h3 id="해결-1---정규식과-옵셔널-체이닝">해결 1 - 정규식과 옵셔널 체이닝</h3>
<pre><code class="language-js">    const solution = (s) =&gt; {
      return s.toLowerCase().match(/p/g)?.length === s.toLowerCase().match(/y/g)?.length;
      // 문자열에 match 메서드를 사용해 정규식으로 특정 문자를 배열로 반환 받아 개수를 비교
      // 문자가 0 개인 경우 배열이 생성되지 않으므로 옵셔널 체이닝으로 두 값을 비교해준다.
    }</code></pre>
<blockquote>
<h3 id="옵셔널-체이닝-연산자란">옵셔널 체이닝 연산자(.?)란</h3>
</blockquote>
<ul>
<li>호출 대상이 undefined 또는 null 인 경우에 오류를 출력하지 않고 undefined 값을 반환하는 연산자</li>
<li>호출 데이터의 값을 예측할 수 없는 경우 사용한다.</li>
</ul>
<p>&nbsp;</p>
<h3 id="해결-2---split-메서드">해결 2 - split 메서드</h3>
<pre><code class="language-js">    const solution = (s) =&gt;{
        return s.toLowerCase().split(&#39;p&#39;).length === s.toLowerCase().split(&#39;y&#39;).length;
          // 생각의 전환으로 쉽게 풀 수 있다.
          // 심지어 가장 빠른 방법...
    }</code></pre>
<hr>
<h3 id="기억해야할-것">기억해야할 것</h3>
<ul>
<li>옵셔널 체이닝 연산자를 사용해 데이터의 형식이 불분명 할 때 안전하게 코드를 짤 수 있다.</li>
<li>match메서드는 조건이 맞지 않는 경우 빈 배열이 아닌 null 값이 리턴된다.</li>
<li>사고의 전환은 언제나 필요하다.</li>
</ul>
<hr>
<p>쉬운 문제라도 코테 풀기는 언제나 옳다.
<img src="https://velog.velcdn.com/images/k_warrior27/post/98b91a54-bb96-42b7-b217-c65d758cf60b/image.gif" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[코테 풀기] 369 게임(JS)]]></title>
            <link>https://velog.io/@k_warrior27/%EC%BD%94%ED%85%8C-%ED%92%80%EA%B8%B0-369-%EA%B2%8C%EC%9E%84JS</link>
            <guid>https://velog.io/@k_warrior27/%EC%BD%94%ED%85%8C-%ED%92%80%EA%B8%B0-369-%EA%B2%8C%EC%9E%84JS</guid>
            <pubDate>Wed, 22 Nov 2023 16:57:00 GMT</pubDate>
            <description><![CDATA[<p>코딩테스트 문제를 풀어보겠다
언어는 javascript
문제는 <a href="https://school.programmers.co.kr/learn/courses/30/lessons/120891">[Link] 프로그래머스</a> 에서 풀어볼 수 있다.</p>
<hr>
<blockquote>
<p>문제 : 주어진 숫자(정수)에 포함된 3, 6, 9 의 수 만큼 리턴</p>
</blockquote>
<hr>
<h3 id="해결-1---배열로-풀기">해결 1 - 배열로 풀기</h3>
<pre><code class="language-js">    const solution = (order) =&gt; (String(order).split(&#39;&#39;).filter((itm) =&gt; ( itm!==&#39;0&#39;&amp;&amp; Number(itm)%3===0)).length);
    // 숫자를 문자열로 바꾼 뒤 배열로 바꾼 뒤 3으로 나누어 떨어지는 값들을 필터링 한 다음 개수를 리턴
    // 단, 0은 제외해야 한다.</code></pre>
<h3 id="해결-2---정규표현식-사용하기-replaceall--matchall">해결 2 - 정규표현식 사용하기 (replaceAll / matchAll)</h3>
<pre><code class="language-js">    // 첫 번째 방법
    const solution = (order) =&gt; String(order).replaceAll(/0/g,&#39;&#39;).split(&#39;&#39;).filter(i =&gt; parseInt(i)%3===0).length;
    // 숫자 자료형을 문자로 바꾼 뒤 replaceAll 을 활용해 0을 찾아 없앤다.
    // 문자열을 배열로 바꾼 뒤 3으로 나누어 떨어지는 값들을 필터링 한 다음 개수를 리턴.


    // 두 번째 방법
    const solution = (order) =&gt; ([...String(order).matchAll(/[3|6|9]/g)].length);
    // 숫자를 문자로 바꾼 뒤 배열에 스프레딩한다.
    // matchAll 을 활용해 3 6 9 를 찾아 재정렬한 다음 리턴한다.
    // matchAll 은 배열에서 전달인자로 받은 값과 비교한 다음 배열로 리턴해준다.</code></pre>
<hr>
<p>(작은 수) % (큰 수) 의 결과는 언제나 (작은 수)가 나온다는 것을 기억하자.
정규식과 정규식을 활용한 메서드를 자주 활용해봐야겠다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[React] useState 사용법 - 3]]></title>
            <link>https://velog.io/@k_warrior27/React-useState-%EC%82%AC%EC%9A%A9%EB%B2%95-3</link>
            <guid>https://velog.io/@k_warrior27/React-useState-%EC%82%AC%EC%9A%A9%EB%B2%95-3</guid>
            <pubDate>Wed, 22 Nov 2023 16:38:47 GMT</pubDate>
            <description><![CDATA[<p>useState 사용법 3번째 글이다.
이번엔 form 태그와 input 태그로 참조형 스테이트를 제어하는 방법을 정리해보고자 한다.
간단한 메모 기능을 구현하며 정리해보겠다.</p>
<hr>
<blockquote>
<h3 id="알아야-할-javascript-문법">알아야 할 Javascript 문법</h3>
</blockquote>
<ul>
<li>useState() 기본 사용법</li>
<li>구조 분해 할당, 스프레드 연산자</li>
</ul>
<hr>
<h2 id="state-설계">state 설계</h2>
<blockquote>
<ul>
<li><h3 id="state-자료-구조">state 자료 구조</h3>
</li>
</ul>
<ol>
<li><strong>memos</strong> = [ { id, memo, isChecked }, { id, memo, isChecked }, ... ];
&ensp;&ensp;배열[ 객체1, 객체2, ... ] =&gt; 주요 메모 데이터</li>
</ol>
<p>&amp;nbsp
2. <strong>todo</strong> = &#39;문자열&#39; =&gt; memos에 추가될 객체의 memo 프로퍼티에 할당 될 데이터</p>
</blockquote>
<blockquote>
<ul>
<li><h3 id="setstate-호출-정리">setState 호출 정리</h3>
</li>
</ul>
</blockquote>
<ol>
<li><strong>setMemos</strong> : form 태그의 <strong>onSubmit</strong> 그리고 button 태그의 <strong>onClick</strong> 이벤트로 <strong>&#39;setMemos&#39;</strong> 함수 호출<blockquote>
<p>&amp;nbsp</p>
</blockquote>
</li>
<li><strong>setTodo</strong> : input 태그의 <strong>onChange</strong> 이벤트로 <strong>&#39;setTodo&#39;</strong> 함수 호출</li>
</ol>
<hr>
<h2 id="메모-기능-구현하기">메모 기능 구현하기</h2>
<h3 id="1-state-선언">&emsp; 1. state 선언</h3>
<pre><code class="language-js">    // 초기 데이터를 변수로 선언
    const initialMemos = [
      {
        id : 0,
        memo : &#39;돈벌기&#39;,
        isChecked : false
      },
      {
        id : 1,
        memo : &#39;주식 투자하기&#39;,
        isChecked : false
      },
      ...
    ];
    // &#39;memos&#39; state 할당.
    const [memos, setMemos] = useState( initialMemos );

    // &#39;todo&#39; state 할당
    const [todo ,setTodo] = useState(&#39;&#39;);</code></pre>
<p>&amp;nbsp</p>
<h3 id="2-요소-구현">&emsp; 2. 요소 구현</h3>
<pre><code class="language-js">    return (
    &lt;div style={style.div}&gt;
      // 체크되지 않은 메모 리스트 제목
      &lt;h1&gt;해야할 일&lt;/h1&gt;
      &lt;ol&gt;
        // &#39;memos&#39; state를 map 함수로 접근해 요소 랜더링
        {memos.map((item)=&gt; {
          if(!item.isChecked){
          // isChecked의 값이 false(체크되지 않은)인 객체인 경우
          // li 요소를 리턴
            return (&lt;li key={item.id}&gt;
                        // input=[checkbox]의 onChange =&gt; handleCheck 함수에 event 와 데이터 id 값 전달하여 호출
                      &lt;input id={`chk${item.id}`} type=&quot;checkbox&quot; value={true} onChange={(e)=&gt;handleCheck(e, item.id)} /&gt;
                      &lt;label htmlFor={`chk${item.id}`}&gt;{item.memo}&lt;/label&gt;
                    &lt;/li&gt;);
          }else{
          // isChecked의 값이 true(체크된)인 객체인 경우 display : none 속성을 부여한다.
          // 빈 값을 리턴하는 경우 li 요소 리턴이 아니기 때문에 경고 출력
          // 따라서 filter로 제한사항을 두거나 한 줄 삼항 연산자 사용 권장됨
            return (&lt;li key={item.id} style={style.none}&gt;&lt;/li&gt;);
          }
        })}
      &lt;/ol&gt;

      // input=[text] 태그의 onSubmit =&gt; handleSubmit 함수 호출
      &lt;form onSubmit={handleSubmit}&gt;
        // onChange =&gt; handleChangeTodo 함수 호출
        // input 요소의 value 속성을 &#39;todo&#39;(제어할 스테이트)로 할당해주어야 값 변경 가능!
        &lt;input type=&quot;text&quot; value={todo} onChange={handleChangeTodo} placeholder=&#39;추가할 메모를 적어주세요&#39; /&gt;
        &lt;button type=&quot;submit&quot;&gt; 메모 추가하기 &lt;/button&gt;

      &lt;/form&gt;

      // 체크된 메모 리스트 제목
      &lt;h2&gt;완료한 일&lt;/h2&gt;
      &lt;ul&gt;
        // isChecked의 값이 true(체크된)인 객체인 경우
        // li 요소를 리턴
        {memos.map((item) =&gt; (item.isChecked&amp;&amp;&lt;li key={item.id}&gt; {item.memo} &lt;/li&gt;))}
      &lt;/ul&gt;

    &lt;/div&gt;
  );
</code></pre>
<p>&amp;nbsp</p>
<h3 id="3-이벤트-핸들러-함수-구현">&emsp; 3. 이벤트 핸들러 함수 구현</h3>
<pre><code class="language-js">    // 1. input=[text] 태그의 onChange 이벤트로 호출되는 함수로 &#39;todo&#39;를 제어
    const handleChangeTodo = (e) =&gt; {
        // setTodo 호출하여 &#39;todo&#39; 변경!
          // input 태그에 값을 입력하면
        // 이벤트 target(input)의 value값을 &#39;todo&#39;에 할당
        setTodo(e.target.value);
      }

      // form 태그의 onSubmit 이벤트로 호출되는 함수로 &#39;memos&#39; 와 &#39;todo&#39;를 제어
      const handleSubmit = (e) =&gt; {
        // preventDefault() 메서드로 form 태그의 submit 이벤트를 막는다.
        e.preventDefault();

        // &#39;memos&#39;에 추가할 id 값과 객체를 구현한다. memo 프로퍼티의 value는 &#39;todo&#39;(state)값으로 할당한다.
          // 추가될 객체의 id 값은 memos의 길이로 할당한다.
        const id = parseInt(memos.length);
        const obj = {
              id,
              // memo 프로퍼티의 값은 &#39;todo&#39;(입력된 state) 값으로 할당
              memo : todo,
              isChecked : false
        }

        // setMemos 호출하여 &#39;memos&#39; 변경!
        // 이전 state(memos) 값에 객체를 추가해준 배열을 리턴
        setMemos((prev) =&gt; ( [ ...prev, {...obj} ] );

        // setTodo 호출하여 &#39;todo&#39; 변경!
        // &#39;todo&#39;(input태그의 value 속성값)를 빈 문자열로 할당한다.
        setTodo(&#39;&#39;);
      }

    // input=[checkbox] 태그의 onChange 이벤트로 호출되는 함수로 &#39;memos&#39;를 제어
     const handleCheck = (e, id) =&gt; {
          // setMemos 호출하여 &#39;memos&#39; 변경!
        setMemos((prev) =&gt; {
              // 이전 스테이트 값을 복사하여 변수로 할당
              const result = [...prev];
              // 일부(isChecked)값만 변화시킨다.
              result[id][&quot;isChecked&quot;] = e.target.value;
              // 수정 완료된 배열을 리턴해 &#39;memos&#39;스테이트에 할당
              return [ ...result ];
        });
      }</code></pre>
<hr>
<h3 id="4-결과">&emsp; 4. 결과</h3>
<p><img src="https://velog.velcdn.com/images/k_warrior27/post/9fe6245a-7bff-4778-b3c1-16c80a7a119b/image.gif" alt=""></p>
<hr>
<h2 id="마치며">마치며</h2>
<p>함수형 컴포넌트에서 state를 구현하는 방법을 정리해봤다.
더 자세한 state 사용 규칙도 정리할 필요가 있겠다.</p>
<p>다음 글은 useEffect를 정리해 보도록 하겠다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[코테 풀기] 귤 고르기 (JS)]]></title>
            <link>https://velog.io/@k_warrior27/%EC%BD%94%ED%85%8C-%ED%92%80%EA%B8%B0-%EA%B7%A4-%EA%B3%A0%EB%A5%B4%EA%B8%B0</link>
            <guid>https://velog.io/@k_warrior27/%EC%BD%94%ED%85%8C-%ED%92%80%EA%B8%B0-%EA%B7%A4-%EA%B3%A0%EB%A5%B4%EA%B8%B0</guid>
            <pubDate>Tue, 21 Nov 2023 06:34:16 GMT</pubDate>
            <description><![CDATA[<p>Lv.2 첫 번째 문제다.
이제부턴 효율성 까지 고려된 코드를 작성할 필요가 있다.
시간이 된다면 시간복잡도에 대해서도 공부한 뒤 블로그에 정리하도록 하겠다.
언어는 javascript
문제는 <a href="https://school.programmers.co.kr/learn/courses/30/lessons/138476">[Link] 프로그래머스</a> 에서 풀 수 있다.</p>
<hr>
<blockquote>
<p>문제 : 정수 배열과 정수k가 주어질 때 정수 배열에서 k개의 값을 모았을 때 서로다른 정수의 개수의 최소값을 리턴</p>
</blockquote>
<hr>
<h3 id="해결---외부-객체를-생성한-뒤-정렬">해결 - 외부 객체를 생성한 뒤 정렬</h3>
<pre><code class="language-js">    const solution = (k, tangerine) =&gt; {
          const obj = {};
          // 배열의 값 : 값의 개수 쌍을 담을 객체 생성

          // 배열을 순회한다.
          tangerine.forEach((n) =&gt; {
            // obj[n] 값이 있으면 1을 더한 값을
            // obj[n] 값이 없으면 1을 넣어준다.
            obj[n] = ++obj[n] || 1;
          });
          // 결과 ex) { &#39;1&#39;: 1, &#39;2&#39;: 2, &#39;3&#39;: 2, &#39;4&#39;: 1, &#39;5&#39;: 2}


          const nums = Object.values(obj).sort((a, b) =&gt; (b-a));
          // 객체 정적 메서드 Object.values()를 사용해 value(개수)만을 추출하고 내림차순으로 정렬
          // 가장 큰 수부터 차감해야 한다.
          // nums = [2, 2, 2, 1, 1]

          let result = 0;
          // 결과 변수 선언

        while(k &gt; 0){
        // 타겟넘버를 배열의 큰 값부터 감소시키며 반복한다.
            k = k - nums[result];
              // 배열의 값 하나씩 처리하면 한가지 크기의 귤이 담긴다.
            result = result+1;
              // 귤의 종류 수를 증가시킨다.
        }

        return result;
        // 결과 리턴
    }
</code></pre>
<hr>
<p>for, while 등 반복문 사용을 최소화 하며 코드를 작성할 필요가 있다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[React] useState 사용법 - 2]]></title>
            <link>https://velog.io/@k_warrior27/React-useState-%EC%82%AC%EC%9A%A9%EB%B2%95-2</link>
            <guid>https://velog.io/@k_warrior27/React-useState-%EC%82%AC%EC%9A%A9%EB%B2%95-2</guid>
            <pubDate>Tue, 21 Nov 2023 05:18:29 GMT</pubDate>
            <description><![CDATA[<p>useState 사용법 두 번째 게시글이다.
참조 자료형을 state로 관리하는 방법을 작성해보고자 한다.
버튼 클릭 시 배열 자료형 state를 바꾸는 로직을 작성해보겠다.</p>
<hr>
<blockquote>
<h3 id="알아야-할-javascript-문법">알아야 할 Javascript 문법</h3>
</blockquote>
<ul>
<li>구조 분해 할당(디스트럭처링)</li>
<li>참조 자료형 (객체, 배열)</li>
<li>배열 메서드(map, reduce)</li>
<li>스프레드 연산자</li>
<li>콜백함수</li>
</ul>
<hr>
<h2 id="참조-자료형배열-스테이트-제어하기">참조 자료형(배열) 스테이트 제어하기</h2>
<h3 id="1-state-선언">&emsp; 1. state 선언</h3>
<pre><code class="language-js">    const [array, setArray] = useState([
    {
      id : 1,
      product : &#39;한남 더 힐&#39;,
      theNumber : 0,
      price : 100
    },
    {
      id : 2,
      product : &#39;포르쉐 911&#39;,
      theNumber : 0,
      price : 2
    }
  ]);
    // 초기값을 배열로 할당</code></pre>
<p>&amp;nbsp</p>
<h3 id="2-요소-구현">&emsp; 2. 요소 구현</h3>
<pre><code class="language-js">    return (
    &lt;&gt;
      &lt;ol&gt;
        {array.map((item) =&gt; (&lt;li key={item.id}&gt;{item.product} : {item.theNumber} 개 소유&lt;/li&gt;))}
        // 배열 자료형을 UI로 구성할 땐 map 함수를 활용해 각각의 배열값에 따라 node를 리턴하는 로직을 작성해준다.
      &lt;/ol&gt;

      &lt;ul&gt;
        {array.map((item) =&gt; (&lt;li key={item.id}&gt; &lt;button onClick={()=&gt;handlePlus(item.id)}&gt;{item.product} 쁠렉스 하기 &lt;/button&gt; &lt;button onClick={()=&gt;handleMinus(item.id)}&gt; {item.product} 당근해버리기 &lt;/button&gt; &lt;/li&gt;) )}
        // 버튼 클릭 시 호출될 이벤트 핸들러 함수를 명시한다.
      &lt;/ul&gt;

      &lt;p&gt;{array.map((item) =&gt; (item.theNumber * item.price)).reduce((a,b) =&gt; a+b,0)}억 원 썼다 ㅋ&lt;/p&gt;

    &lt;/&gt;
  );</code></pre>
<p>&amp;nbsp</p>
<h3 id="3-이벤트-핸들러-함수-구현">&emsp;3. 이벤트 핸들러 함수 구현</h3>
<pre><code class="language-js">    // 상품을 구매하는 버튼 클릭 시 호출될 이벤트 핸들러
  const handlePlus = (productId) =&gt; {
    // id 값을 전달받아 배열의 인덱스 번호를 정한다.
    setArray((prev) =&gt;{
      // 이전 스테이트값을 전달받아 복사한다.
      const result = [...prev];
      result[productId-1][&quot;theNumber&quot;]++;
      // 값을 바꾼 뒤 setState 함수에 배열로 리턴한다.
      return [...result];
    });
  }

  // 상품을 판매하는 버튼 클릭 시 호출될 이벤트 핸들러
  const handleMinus = (productId) =&gt;{
    setArray((prev) =&gt;{
      const result = [...prev];
      if(result[productId-1][&quot;theNumber&quot;] &gt; 0) result[productId-1][&quot;theNumber&quot;]--;
      return [...result];
    });
  }
</code></pre>
<hr>
<h3 id="4-결과">&emsp; 4. 결과</h3>
<p><img src="https://velog.velcdn.com/images/k_warrior27/post/c7da0ebf-8640-4f6e-90d0-2a7d703622a2/image.gif" alt=""></p>
<hr>
<p>한남 더 힐과 포르쉐를 들고 이만 글을 마치겠다.</p>
<p>다음 글은 input, form 요소로 state 값을 제어하는 방법을 작성하겠다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[코테 풀기] 문자열 밀기 (JS)]]></title>
            <link>https://velog.io/@k_warrior27/%EC%BD%94%ED%85%8C-%ED%92%80%EA%B8%B0-%EB%AC%B8%EC%9E%90%EC%97%B4-%EB%B0%80%EA%B8%B0-JS</link>
            <guid>https://velog.io/@k_warrior27/%EC%BD%94%ED%85%8C-%ED%92%80%EA%B8%B0-%EB%AC%B8%EC%9E%90%EC%97%B4-%EB%B0%80%EA%B8%B0-JS</guid>
            <pubDate>Tue, 21 Nov 2023 03:28:18 GMT</pubDate>
            <description><![CDATA[<p>좋은 문제를 가져왔다.
언어는 javascript
일반적인 문제의 흐름에 따라 생각하면 코드가 매우 복잡해지지만 사고의 전환만 있다면 매우 쉽게 풀 수 있었던 문제다.
문제는 <a href="https://school.programmers.co.kr/learn/courses/30/lessons/120921#">[Link] 프로그래머스</a> 에서 풀 수 있다.</p>
<hr>
<blockquote>
<p>문제 : 주어진 문자열을 밀어 타겟과 일치하는 경우 최소한으로 미는 수 리턴</p>
</blockquote>
<hr>
<h3 id="해결---문자열-늘이기와-타겟-변경">해결 - 문자열 늘이기와 타겟 변경</h3>
<pre><code class="language-js">    const solution = (A,B) =&gt; ((B+B).indexOf(A));
    // A : hello
    // B : ohell

    // 밀려진 문자열을 타겟팅 하기 보단 온전한 문자열을 타겟으로 생각한 뒤 순서가 바뀐 문자열을 두 배로 늘린다.
    // ohellohell
    //  hello
    // 두 배로 늘린 문자열에서 hello의 인덱스 번호를 찾아 리턴한다.</code></pre>
<hr>
<p>문제 해결을 위한 사고의 전환이 중요하다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Swift] 기본 문법 - 변수와 자료형]]></title>
            <link>https://velog.io/@k_warrior27/Swift-%EA%B8%B0%EB%B3%B8-%EB%AC%B8%EB%B2%95-%EB%B3%80%EC%88%98%EC%99%80-%EC%9E%90%EB%A3%8C%ED%98%95</link>
            <guid>https://velog.io/@k_warrior27/Swift-%EA%B8%B0%EB%B3%B8-%EB%AC%B8%EB%B2%95-%EB%B3%80%EC%88%98%EC%99%80-%EC%9E%90%EB%A3%8C%ED%98%95</guid>
            <pubDate>Tue, 21 Nov 2023 02:33:52 GMT</pubDate>
            <description><![CDATA[<p>입사지원한 회사의 코딩 테스트를 본 뒤...
붕 떠버렸다. 남는게 시간인 만큼 평소 배우고 싶던 Swift 문법을 조금씩 공부해 보기로 했다.
내게 익숙한 언어는 javascript 이기 때문에 javascript와 비교하며 공부 할 계획이다.</p>
<hr>
<h2 id="swift란">Swift란?</h2>
<blockquote>
<p>Swift는 모든 Apple 플랫폼에서 사용할 수 있는 강력하고 직관적인 프로그래밍 언어입니다. 간결하면서도 표현력이 풍부한 구문과 현대적인 기능으로 사용하기가 간편합니다. Swift 코드는 안전하게 설계되었으며 빛의 속도로 빠르게 실행되는 소프트웨어를 제작할 수 있습니다.
- Apple 개발자 페이지 참조</p>
</blockquote>
<ul>
<li>Apple에서 만든 프로그래밍 언어로 Objective-C를 대체하는 차세대 언어</li>
<li>Mac, iOS 등 Apple 기기에서 Native 앱을 제작할 수 있는 언어</li>
<li>인터프리터 언어인 javascript와 달리 컴파일 언어</li>
</ul>
<hr>
<h4 id="내용은-swiftplayground의-내용을-참고했다">내용은 Swiftplayground의 내용을 참고했다.</h4>
<h2 id="변수">변수</h2>
<h3 id="1-변수-선언-키워드">1. 변수 선언 키워드</h3>
<ul>
<li>var : <strong>변수</strong>를 선언하는 키워드 / ES6 문법에서는 let</li>
<li>let : <strong>상수</strong>를 선언하는 키워드 / ES6 문법에서는 const</li>
</ul>
<h3 id="2-타입-명시">2. 타입 명시</h3>
<ul>
<li>동적 타입 추론 언어인 javascript와 달리 Swift는 기본적으로 정적 타입 언어이기에 변수에 타입을 명시할 수 있다.</li>
<li>또한 타입에 맞지 않는 자료형의 값을 변수에 할당할 수 없다.</li>
</ul>
<pre><code class="language-swift">    // 예문

    var num01 : Int = 3;
    // 키워드 변수명 : 타입 = 할당값;
    let num02 : Int = 15;
    // let 의 경우 상수로 값을 재할당 할 수 없다.
    _______________________________________________________________

    // 변수 값 할당과 자료형

    var again01 : String ;
    // 선언만 하고 할당을 뒤에서 하는 경우는 타입을 명시해줘야 한다.
    again01 = &quot;Hi Swift&quot;;
    // 문자 자료형은 큰따옴표(&quot;)로 감싼다.

    var again02 = 3;
    // 타입을 명시하지 않고 변수값을 할당할 수 있다 (타입이 할당값에 따라 확정)
    again02 = 5;
    // 기존 변수와 일치하는 타입의 자료형은 할당 가능하다.


    // 아래 코드는 오류구문 입니다.
    again02 = &#39;숫자&#39;;
    // again 변수의 자료형은 Int로 String 자료형의 값을 할당할 수 없다!!!

</code></pre>
<h3 id="3-기본-자료형">3. 기본 자료형</h3>
<ul>
<li><p>Int : 정수 자료형 64비트</p>
</li>
<li><p>Unit : 양의 정수 자료형 64비트</p>
</li>
<li><p>Float : 숫자(실수) 자료형 32비트</p>
</li>
<li><p>Double : 숫자(실수) 자료형 64비트</p>
</li>
<li><p>Bool : 불리언 자료형</p>
</li>
<li><p>Character : 길이가 1인 문자 자료형</p>
</li>
<li><p>String : 문자열 자료형</p>
</li>
</ul>
<hr>
<p>오랜만에 Swift를 공부하니 재미있다.
동적 타입 언어인 javascript와 달리 Swift는 타입에 엄격하다 보니 자료형의 종류가 많은 것이 신기하게 느껴진다.
다음 글은 Array 등의 컬렉션 타입에 대해 작성해 보도록 하겠다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[코테 풀기] 저주의 숫자 3 (JS)]]></title>
            <link>https://velog.io/@k_warrior27/%EC%BD%94%ED%85%8C-%ED%92%80%EA%B8%B0-%EC%A0%80%EC%A3%BC%EC%9D%98-%EC%88%AB%EC%9E%90-3-JS</link>
            <guid>https://velog.io/@k_warrior27/%EC%BD%94%ED%85%8C-%ED%92%80%EA%B8%B0-%EC%A0%80%EC%A3%BC%EC%9D%98-%EC%88%AB%EC%9E%90-3-JS</guid>
            <pubDate>Tue, 21 Nov 2023 01:48:50 GMT</pubDate>
            <description><![CDATA[<p>재미있는 문제를 가져와봤다.
언어는 javascript
문제는 <a href="https://school.programmers.co.kr/learn/courses/30/lessons/120871">[Link] 프로그래머스</a> 에서 풀 수 있다.</p>
<hr>
<blockquote>
<p>문제 : 주어진 숫자를 3의 배수인 숫자와 &#39;3&#39;을 포함한 숫자를 건너뛰어 연산하여 리턴
예) 9 =&gt; 14 / 10 =&gt; 16</p>
</blockquote>
<hr>
<h3 id="해결---반복문-continue">해결 - 반복문 continue</h3>
<pre><code class="language-js">    const solution = (n) =&gt; {
        let result = 1;
          // 결과 변수 초기값 1
        let target = 1;
          // n과 비교할 변수
        let num = 1;
          // result에 할당할 변수값
        while(target &lt;= n){
        // target 이 n 보다 작거나 같은 동안 반복
            if(num%3===0 || num.toString().includes(&#39;3&#39;)){
            //n이 3의 배수이거나 || n을 문자열로 바꾼 뒤 숫자 &#39;3&#39;이 포함되는 경우
                num++;
                  // num 값을 증가
                continue;
                  // 반복문 건너뛰기
            }
            result = num;
              // 피할 숫자가 아닌 경우 num 값을 result에 할당
            num++;
              // num 값을 증가
            target++;
              // target 값을 증가
        }
        return result;

    }</code></pre>
<hr>
<p>조건에 따라 반복문을 건너뛰는 로직을 기억하자</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[코테 풀기] 잘라서 배열로 저장하기 (JS)]]></title>
            <link>https://velog.io/@k_warrior27/%EC%BD%94%ED%85%8C-%ED%92%80%EA%B8%B0-%EC%9E%98%EB%9D%BC%EC%84%9C-%EB%B0%B0%EC%97%B4%EB%A1%9C-%EC%A0%80%EC%9E%A5%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@k_warrior27/%EC%BD%94%ED%85%8C-%ED%92%80%EA%B8%B0-%EC%9E%98%EB%9D%BC%EC%84%9C-%EB%B0%B0%EC%97%B4%EB%A1%9C-%EC%A0%80%EC%9E%A5%ED%95%98%EA%B8%B0</guid>
            <pubDate>Mon, 20 Nov 2023 09:53:10 GMT</pubDate>
            <description><![CDATA[<p>이번에도 문제를 혼내준다.
언어는 javascript
문제는 <a href="https://school.programmers.co.kr/learn/courses/30/lessons/120913">[Link] 프로그래머스</a> 에서 풀어볼 수 있다.</p>
<hr>
<blockquote>
<p>문제 : 주어진 문자열을 주어진 길이만큼 잘라 배열로 담아 리턴해야 한다.</p>
</blockquote>
<hr>
<h3 id="해결---slice-사용하기">해결 - slice 사용하기</h3>
<pre><code class="language-js">    const solution = (my_str,n)=&gt; {
        let result = [];
          // 결과 데이터를 배열로 선언

        for(let i = 0 ; i &lt; my_str.length ; i= i+n){
              // i 에 n 씩 더하며 반복한다.
            result.push(my_str.slice(i, i+n));
              // 결과 배열에 문자열을 i 번째 부터 i+n 번째까지 잘라 push 한다.
              // slice의 두 번째 인자도 인덱스 번호이다
              // 두 번째 인자의 인덱스 번호가 문자열의 길이보다 큰 경우 오류출력 없이 가장 마지막 문자를 자동으로 인덱싱한다
        }
        return result;
    }</code></pre>
<hr>
<p>slice 유용한데 잘 안쓰게 된다 좀 써보자</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[코테 풀기] 가까운 수 (JS)]]></title>
            <link>https://velog.io/@k_warrior27/%EC%BD%94%ED%85%8C-%ED%92%80%EA%B8%B0-%EA%B0%80%EA%B9%8C%EC%9A%B4-%EC%88%98</link>
            <guid>https://velog.io/@k_warrior27/%EC%BD%94%ED%85%8C-%ED%92%80%EA%B8%B0-%EA%B0%80%EA%B9%8C%EC%9A%B4-%EC%88%98</guid>
            <pubDate>Mon, 20 Nov 2023 09:45:56 GMT</pubDate>
            <description><![CDATA[<p>또 코푼다.
언어는 javascript
문제는 <a href="https://school.programmers.co.kr/learn/courses/30/lessons/120890">[Link] 프로그래머스</a> 에서 풀어볼 수 있다.</p>
<hr>
<blockquote>
<p>문제 : 주어진 배열의 수 중 주어진 정수와 가장 가까운 수를 리턴한다. 가까운 수가 두 개 이상인 경우 더 작은수를 리턴한다.</p>
</blockquote>
<hr>
<h3 id="해결---배열을-순회하여-차를-구한-뒤-리턴하기">해결 - 배열을 순회하여 차를 구한 뒤 리턴하기</h3>
<pre><code class="language-js">    const solution = (array, n) =&gt; {
        array.sort((a,b) =&gt; (a-b));
        // 정수 배열을 오름차순으로 정렬한다.

        let distance = Infinity;
          // 배열의 값과 타겟넘버 n 과의 차이를 담을 변수 선언
        let result = array[0];
          // 결과 변수 선언
        array.forEach((i) =&gt; {
              // 배열을 순회한다.
            if( Math.abs(n-i) &lt; distance ){
                  // 만약에 타겟넘버에서 값을 뺀 절댓값이 distance 보다 작다면
                  // (차이가 같은 경우는 초기화되지 않으므로 더 작은 수가 저장된다.)
                  // 차이가 가장 작은 값이기 때문에 결과값과 차이를 초기화 해야 한다.
                result = i;
                distance = Math.abs(n-i);
            }
        });
        return result;
          // 결과 리턴
    }</code></pre>
<hr>
<p>크기를 비교하는 방법을 잘 기억해두자</p>
]]></description>
        </item>
    </channel>
</rss>