<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>ziyoung_room.log</title>
        <link>https://velog.io/</link>
        <description>저의 공간에 오신 걸 환영해요 ☺️</description>
        <lastBuildDate>Sat, 28 Dec 2024 07:27:16 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>ziyoung_room.log</title>
            <url>https://velog.velcdn.com/images/ziyoung_room/profile/7b7a0cd7-8146-4733-832d-9a10b637a1fc/image.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. ziyoung_room.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/ziyoung_room" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[PageBrothers :: monorepo 구성하기]]></title>
            <link>https://velog.io/@ziyoung_room/PageBrothers-monorepo-%EA%B5%AC%EC%84%B1%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@ziyoung_room/PageBrothers-monorepo-%EA%B5%AC%EC%84%B1%ED%95%98%EA%B8%B0</guid>
            <pubDate>Sat, 28 Dec 2024 07:27:16 GMT</pubDate>
            <description><![CDATA[<h2 id="🧐-monorepo-를-구성하게-된-계기">🧐 MonoRepo 를 구성하게 된 계기</h2>
<p>현재 개발 중인 프로젝트는 사용자가 모바일 청첩장을 만들어 공유 가능하도록 하는 서비스이고, 사용자가 청첩장을 생성하는 페이지와 완성본이 공유되는 청첩장 페이지, 그리고 Admin 페이지 이렇게 세가지 도메인으로 이루어져 있다. </p>
<p>www - static 간의 공유되는 디자인 컴포넌트들이 많기도 했고, prettier와 ESLint 와 같은 설정들을 공유하면 관리 및 유지/보수하기 좋을 것 같아 모노레포로 구성하기로 했다.</p>
<h2 id="🔍-monorepo-란-">🔍 MonoRepo 란 ?</h2>
<p>한 개의 Repository 안에서 다수의 프로젝트를 관리하는 소프트웨어 개발전략.</p>
<h3 id="monorepo-의-장점-✨"><strong>MonoRepo 의 장점 ✨</strong></h3>
<p>✔️ 다수의 프로젝트 컨벤션의 일관성 유지가 용이.</p>
<p>✔️ 프로젝트 간 중복되는 코드를 감소시킴으로써 코드 재사용성 향상.</p>
<p>✔️ 다수의 프로젝트 간의 의존성을 쉽게 관리할 수 있고 유지 보수가 용이.</p>
<h3 id="monorepo-의-단점-❓︎"><strong>MonoRepo 의 단점 ❓︎</strong></h3>
<p>✔️ Repository 가 지나치게 무거워질 수 있다.</p>
<p>✔️ 빌드 및 테스트 시간이 길어질 수 있다.</p>
<p>✔️ 저장소 관리가 복잡해질 우려가 있다.</p>
<p>따라서 빌드와 테스트 시간을 단축하기 위해 CI/CD 파이프라인을 최적화시킬 필요가 있다.</p>
<h2 id="🛠︎-monorepo-도구"><strong>🛠︎</strong> MonoRepo 도구</h2>
<h3 id="nx-✨">NX <strong>✨</strong></h3>
<p>복잡한 의존성을 가진 대규모 프로젝트에 유리.</p>
<p>러닝커브가 높으며 설정이 비교적 복잡한 편이다.</p>
<h3 id="lerna-✨">Lerna <strong>✨</strong></h3>
<p>패키지들의 버전 동기화 및 독립적으로 관리 가능.</p>
<p>빌드 최적화 기능이 부족 &amp; 상대적으로 오래된 도구.</p>
<p>yarn 과 조합이 좋음.</p>
<h3 id="yarn-✨">Yarn <strong>✨</strong></h3>
<p>Next.js의 Vercel 배포가 Yarn Berry에서는 잘 동작하지 않는다.</p>
<h3 id="turborepo-✨">TurboRepo <strong>✨</strong></h3>
<p>빌드 최적화에 중점. 병렬 빌드 가능. 러닝커브가 비교적 낮음.</p>
<p>로컬 컴퓨팅 캐싱 및 로컬 작업 오케스트레이션 제공.</p>
<p>영향을 받는 패키지를 감지하는 기능 제공.</p>
<p>vercel에서 개발하고 있다.</p>
<p><img src="https://velog.velcdn.com/images/ziyoung_room/post/a6996f79-c747-424d-b843-c687337c772b/image.png" alt=""></p>
<h2 id="🔍-turborepo-란-">🔍 TurboRepo 란 ?</h2>
<p>Javascript / Typescript 기반의 monorepo 를 위한 고성능 빌드 시스템.</p>
<h3 id="turborepo-의-장점-✨">TurboRepo <strong>의 장점 ✨</strong></h3>
<p><img src="https://velog.velcdn.com/images/ziyoung_room/post/8a81a978-eef3-41af-8941-449b31e08cdc/image.png" alt=""></p>
<p>✔️ 로컬 캐싱을 통해 한번 빌드된 내용은 다시 빌드 X.</p>
<p>✔️ 병렬적으로 작업을 수행하여 멀티태스킹 능력을 극대화.</p>
<h2 id="⚙️-turborepo-설치">⚙️ TurboRepo 설치</h2>
<pre><code class="language-tsx">pnpm dlx create-turbo@latest --example with-tailwind</code></pre>
<p>✔️ tailwind css 설정을 포함한 monorepo 생성.</p>
<h2 id="🔧-initial-settings"><strong>🔧 Initial Settings</strong></h2>
<pre><code class="language-markdown">📦.turbo
📦node_modules
📦apps
 ┣ 📂admin
 ┣ 📂www
 ┗ 📂invitation
📦packages
 ┣ 📂config-tailwind
 ┣ 📂config-eslint
 ┣ 📂config-typescript
 ┗ 📂shared
📜.prettierrc
📜.gitignore
📜 package.json
📜.pnpm-lock.yaml
📜.pnpm-workspace.yaml
📜turbo.json
📜.npmrc</code></pre>
<p>TurboRepo로 생성 시, apps 폴더 내부에 <code>web</code> <code>docs</code> 존재.</p>
<p>✔️ <code>web &gt; admin</code> <code>docs &gt; www</code> 로 폴더명 변경.</p>
<p>✔️ 폴더를 복사해서 1개 더 생성 후에 <code>invitation</code> 으로 변경.</p>
<p>✔️ 각 폴더 내에 존재하는 <code>package.json</code> 의 name 을 폴더명으로 설정.</p>
<p>✔️ port 번호는 3000 으로 통일.</p>
<p>✔️ root에 존재하는 <code>package.json</code> 에서 dev 설정 변경.</p>
<pre><code class="language-json">// filter 된 파일만 실행.
&quot;scripts&quot;: {
    &quot;dev&quot;: &quot;turbo dev --filter www&quot;,
  },</code></pre>
<p>TurboRepo로 생성 시, packages 폴더 내에 <code>ui</code> 폴더 존재.</p>
<p>✔️ <code>ui &gt; shared</code> 로 폴더명 변경.</p>
<p>→ UI 컴포넌트 외에도  types constants 파일을 공유.</p>
<p>✔️ <code>shared</code> 내부 src 폴더에 components types constants 폴더 생성.</p>
<p>✔️ 폴더명이 변경됨에 따라, 전체 레포 내에 있는 모든 파일들의 <code>ui</code> 폴더명을 <code>shared</code> 로 변경해주었다 😇</p>
<h2 id="💥-error-해결">💥 Error 해결</h2>
<pre><code class="language-tsx">// page.tsx
import { Card } from &#39;@repo/shared/components&#39;;
// layout.tsx
import &#39;@repo/shared/styles.css&#39;;</code></pre>
<p>✔️ 각 폴더 내에 있는 <code>page.tsx</code> <code>layout.tsx</code> 에서 import 에러 발생.</p>
<p>✔️ Card 컴포넌트 <code>command + I</code> 를 통해 import 불가능.</p>
<p>→ 경로를 찾지 못하는 듯 했다.. 🤦🏻‍♀️</p>
<h2 id="💡-part-1-">💡 Part 1 .</h2>
<pre><code class="language-json">// packages/shared/package.json
&quot;exports&quot;: {
    &quot;./styles.css&quot;: &quot;./src/styles.css&quot;,
    &quot;./components&quot;: &quot;./src/components/index.ts&quot;
  },</code></pre>
<p>처음에는 해당 exports 문을 삭제 후, 에러가 발생했던 import 문에 <code>/src</code> 를 추가.</p>
<p>더 이상 에러는 발생하지 않았지만,,</p>
<p><strong>문제 1 ❓︎</strong> <code>command + I</code> 를 통한 자동 import 불가.
<strong>문제 2❓︎</strong> 모든 경로에 **** <code>/src</code> 를 추가해야했다 🤯</p>
<h2 id="💡-part-2-">💡 Part 2 .</h2>
<pre><code class="language-tsx">// shared/src/components/index.ts
export { Card } from &#39;./card&#39;;</code></pre>
<p>✔️ <code>shared/src/components</code> 폴더 내에 <code>index.ts</code> 파일 생성.</p>
<p>✔️ <code>index.ts</code> 파일에 생성한 component 파일 export 문을 추가.</p>
<pre><code class="language-json">// packages/shared/package.json
&quot;main&quot;: &quot;./src/components/index.ts&quot;,</code></pre>
<p>✔️  <code>package.json</code> 파일에서 해당 파일을 main으로 내보내기 !</p>
<pre><code class="language-tsx">// page.tsx
import { Card } from &#39;@repo/shared&#39;;</code></pre>
<p>✔️  <code>command + I</code> <strong>를 통한 자동 import 가능 + 아주 깔끔해졌다 ✨✨</strong></p>
<h2 id="🧐-monorepo---storybook">🧐 MonoRepo - Storybook</h2>
<p>모노레포에 storybook을 도입해보기로 하면서 storybook 설치 위치에 대해서 많은 고민을 했다..</p>
<p>각 레포마다 storybook을 설치하는 방안도 있었지만, turborepo 공식문서에 나와있는대로 storybook 레포를 따로 구성해서 진행하기로 했다.</p>
<pre><code class="language-markdown">📦apps
 ┣ 📂admin
 ┣ 📂www
 ┣ 📂invitation
 ┗ 📂storybook</code></pre>
<p>이런 방식으로 구성하면, storybook을 독립적으로 운영할 수 있고 문서화된 페이지를 배포해서 볼 수 있다는 장점이 있다.</p>
<h2 id="⚙️-storybook-설치">⚙️ StoryBook 설치</h2>
<pre><code class="language-tsx">// apps/storybook
pnpm dlx storybook@latest init</code></pre>
<p>✔️  apps 내부에 <code>storybook</code> 폴더를 생성한 후, <code>storybook</code> 폴더 내에서 설치.</p>
<h2 id="🔧-의존성-추가">🔧 의존성 추가</h2>
<pre><code class="language-json">// apps/storybook/package.json
&quot;dependencies&quot;: {
    &quot;@repo/shared&quot;: &quot;workspace:*&quot;,
  },</code></pre>
<p>✔️  설치한 폴더 내 <code>package.json</code> 파일에 코드 추가.</p>
<h2 id="⚙️-storybook-추가-설치">⚙️ StoryBook 추가 설치</h2>
<pre><code class="language-tsx">pnpm install @repo/shared --filter=storybook</code></pre>
<p>✔️ 경험담인데 의존성 추가안하면 설치 안됩니다..😉</p>
<h2 id="📁-storybook-static-관련-설정">📁 Storybook-static 관련 설정</h2>
<pre><code class="language-tsx">// turbo.json
{
  &quot;tasks&quot;: {
    &quot;build&quot;: {
      &quot;outputs&quot;: [
+       &quot;storybook-static/**&quot;
      ]
    }
  }
}</code></pre>
<p>✔️ <code>turbo.json</code> 파일에 build 내 outputs 에 storybook-static 을 추가.</p>
<p>→ 빌드를 실행할 때 파일 출력이 캐시되도록 하기 위해</p>
<pre><code class="language-tsx">// .gitignore
+ storybook-static</code></pre>
<p>✔️ <code>.gitignore</code> 파일에 storybook-static 을 추가.</p>
<p>→ storybook에 대한 build 의 output을 소스 제어에 커밋되지 않게 하기 위해</p>
<h2 id="📄-출처">📄 출처</h2>
<p>Storybook 설정 관련 내용은 모두 <a href="https://turbo.build/repo/docs/guides/tools/storybook">turborepo 공식문서</a> 를 참조했습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[⚠️ Error :: Service Key is not registered error.]]></title>
            <link>https://velog.io/@ziyoung_room/Error-Service-Key-is-not-registered-error</link>
            <guid>https://velog.io/@ziyoung_room/Error-Service-Key-is-not-registered-error</guid>
            <pubDate>Sat, 20 Jul 2024 16:06:19 GMT</pubDate>
            <description><![CDATA[<h1 id="service-key-is-not-registered">Service Key is not registered..</h1>
<hr>
<h2 id="🔍️-공공-데이터-api-호출-방법">🔍️ 공공 데이터 API 호출 방법</h2>
<h3 id="url--queryparameter--endpoint"><strong>&quot; url + queryParameter + endPoint &quot;</strong></h3>
<p><strong><code>query Parameter</code></strong> 부분에 <code>Service Key</code>를 key로, 발급받은 개인 Service Key 를 value 로 넣어주고 이외의 필요한 Key , Value 값도 추가.</p>
<p>공공 데이터 포털에서 개인 Service Key를 발급받으면, <strong><code>인코딩 키 (Encoding Key)</code></strong> 와 <strong><code>디코딩 키 (Decoding Key)</code></strong> 두 가지 종류로 발급되고 홈페이지에서도 필요에 따라 확인해보고 사용하라고 나온다..</p>
<p>두 가지의 Service Key를 모두 사용해본 결과, 인코딩 여부 관계 없이 위의 <em><code>Service Key is not regitered Error</code></em> 이라는 에러 발생.</p>
<h2 id="📌-error-발생-이유">📌 Error 발생 이유</h2>
<h4 id="①-service-key-가-정말-등록이-안된-경우">① Service Key 가 정말 등록이 안된 경우</h4>
<p>심의유형이 자동승인이 경우에도 Service Key 는 발급받은 이후 30분에서 1시간 이후에 사용가능하다고 한다.</p>
<p>또한, 심의유형이 심의승인인 경우에는 담당자가 활용승인해야 사용할 수 있으니 확인해 볼 필요가 있다.</p>
<p><strong>② Service Key의 인코딩 or 디코딩이 제대로 안된 경우</strong></p>
<p>간혹 찾아보면 Service Key를 인코딩 or 디코딩을 다시해서 넣으면 제대로 작동한다는 후기를 발견할 수 있었다. </p>
<p><strong>③ Service Key 에 문제있는 경우 🤬</strong></p>
<h2 id="📌-error-해결">📌 Error 해결</h2>
<p>결론적으로, 처음<code>Service Key</code> 를 발급한 지 1시간이 지나고 디코딩과 인코딩을 모두 해봤지만 어느 것도 되지 않았다.</p>
<p>코드로 호출했을 경우에만 해당 에러가 뜬게 아니라, 공공 데이터 포털에서 제공하는 미리보기에서도 같은 에러가 발생했다.</p>
<p>그래서 코드 문제가 아니라 <code>Service Key</code> 자체에 문제가 있다고 판단했고, 마지막으로 <code>Service Key</code> 를 재발급 받은 후 1시간이 지난 뒤에 API를 호출해봤더니 <strong><em><code>Status: 200 ResultMsg: Normal Service</code></em></strong> 가 나왔다 ..😇</p>
<p>재발급 받았더니 제대로 작동해서 조금 화가 났지만 ..
<strong>Service Key에 문제가 있는 경우가 있으니 재발급도 받아보세요 🙏🏻</strong></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[⚠️ Error :: NextRouter was not mounted.]]></title>
            <link>https://velog.io/@ziyoung_room/Error-NextRouter-was-not-mounted</link>
            <guid>https://velog.io/@ziyoung_room/Error-NextRouter-was-not-mounted</guid>
            <pubDate>Sat, 20 Jul 2024 16:04:10 GMT</pubDate>
            <description><![CDATA[<h1 id="nextrouter-was-not-mounted">NextRouter was not mounted.</h1>
<hr>
<p>컴포넌트 내부에서 <strong><code>useRouter</code></strong> 를 호출해서 사용하고자 하는 과정에서 <em><code>NextRouter was not mounted.</code></em> 라는 에러가 발생.</p>
<h2 id="📌-error-발생-원인">📌 Error 발생 원인</h2>
<p><code>client component</code> 에서 <strong><code>useRouter</code></strong> 를 <code>Next/Router</code> 모듈에서 import 해서 사용한 부분이 문제가 되었다.</p>
<h2 id="📌-error-해결">📌 Error 해결</h2>
<p>Next JS 13 ver. 부터는 <strong>&quot;use client&quot;</strong> 를 사용해서 컴포넌트를<code>client component</code> 로 사용하고자 한 경우, <strong><code>useRouter</code></strong> 를 <code>Next/Navigation</code> 모듈에서 import 해야 한다.</p>
<p>전에 들었던 부분인데도 불구하고 막상 사용할 때는 잊어버렸다 😮‍💨</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[React :: redux ➀ 기본 Setting]]></title>
            <link>https://velog.io/@ziyoung_room/React-redux</link>
            <guid>https://velog.io/@ziyoung_room/React-redux</guid>
            <pubDate>Sat, 13 Jul 2024 07:08:25 GMT</pubDate>
            <description><![CDATA[<h1 id="redux">Redux</h1>
<hr>
<p><code>Redux</code> 는 <strong>중앙 state 관리소에서 state를 관리할 수 있도록 도와주는 전역 상태관리 라이브러리.</strong> 이다. </p>
<p><strong>💡  성능 최적화</strong>
 : 상태 변경 시 관련된 컴포넌트만 선택적으로 업데이트 가능.</p>
<p><strong>💡  상태 로직의 중앙화와 일관성</strong>
 : 상태 로직이 중앙에서 관리되어 일관성 있고 예측 가능한 상태 변경이 가능.</p>
<p><strong>💡 강력한 미들웨어와 개발 도구</strong>
: 다양한 미들웨어를 지원하여 비동기 작업, 로깅, 상태 변경에 대한 추가 처리 등 복잡한 기능 구현 가능.</p>
<h2 id="🧸-redux-setting">🧸 Redux Setting</h2>
<p><strong>➀  redux 설치</strong></p>
<pre><code>yarn : yarn add redux react-redux
npm : npm install redux react-redux</code></pre><p><strong>➁  폴더 구조 setting</strong></p>
<pre><code>src 폴더 &gt; redux 폴더 &gt; config 폴더 &gt; configStore.js
src 폴더 &gt; redux 폴더 &gt; modules 폴더 &gt; stateName.js</code></pre><p> ✔️ <code>modules</code> 폴더 내부에 관리할 state 파일 생성.</p>
<p><strong>③  configStore.js 파일 setting</strong></p>
<pre><code class="language-jsx">import { createStore } from &quot;redux&quot;;
import { combineReducers } from &quot;redux&quot;;

const rootReducer = combineReducers({}); 
const store = createStore(rootReducer); 

export default store;
</code></pre>
<p> ✔️ <code>createStore()</code> : 리덕스의 가장 핵심이 되는 스토어를 만드는 메서드.
  ✔️ <code>combineReducers()</code> : 여러 개의 독립적인 reducer의 반환 값을 하나의 상태 객체로 생성.</p>
<p>  <strong>④ main.jsx 파일에 setting</strong></p>
<pre><code class="language-jsx">import React from &quot;react&quot;;
import ReactDOM from &quot;react-dom/client&quot;;
import App from &quot;./App&quot;;
import store from &quot;./redux/config/configStore&quot;;
import { Provider } from &quot;react-redux&quot;;

const root = ReactDOM.createRoot(document.getElementById(&quot;root&quot;));
root.render(
    &lt;React.StrictMode&gt;
        &lt;Provider store={store}&gt; 
        &lt;App /&gt;
        &lt;/Provider&gt;
    &lt;/React.StrictMode&gt;
);</code></pre>
<p>✔️ App을 Provider로 감싸주고, configStore에서 export default 한 store를 넣어줍니다.</p>
<h2 id="🧸-module-생성-및-연결">🧸 Module 생성 및 연결</h2>
<p><strong>➀  module 생성하기</strong></p>
<pre><code class="language-js">Modules 폴더 &gt; counter.js 파일 생성

const initialState = {
  number: 0,
};

// 리듀서
const counter = (state = initialState, action) =&gt; {
  switch (action.type) {
    default:
      return state;
  }
};

export default counter;</code></pre>
<p>✔️ <code>initialState</code> : state의 초기 상태값 .
✔️ <code>Reducer</code> : 변화를 일으키는 함수 .
✔️ 모듈파일에서는 리듀서를 export default 한다.</p>
<p><strong>➁  module 연결하기</strong></p>
<pre><code class="language-js">/src/redux/config/configStore.js

import { createStore } from &quot;redux&quot;;
import { combineReducers } from &quot;redux&quot;;
import counter from &quot;../modules/counter&quot;;

const rootReducer = combineReducers({
  counter: counter
});
const store = createStore(rootReducer);

export default store;</code></pre>
<p>✔️ 생성한 module 파일 import 해주기.
✔️ combineReducers 에 생성한 module 파일의 reducer 추가해주기. </p>
<h2 id="🧸-store의-state-값-조회">🧸 Store의 State 값 조회</h2>
<pre><code class="language-jsx">/src/App.js

import React from &quot;react&quot;;
import { useSelector } from &quot;react-redux&quot;;

const App = () =&gt; {
  // const counterStore = useSelector((state) =&gt; state);
  // { counter : {number : 0} }
  const number = useSelector((state) =&gt; state.counter.number); 
  // 0

  return &lt;div&gt;&lt;/div&gt;;
}

export default App;</code></pre>
<p>✔️ 사용할 component 에서 <code>useSelector</code> 훅을 사용하여 store 조회.</p>
<h2 id="🧸-state-값-변경">🧸 State 값 변경</h2>
<p><strong>➀  Reducer가 state값 변경</strong></p>
<pre><code class="language-js">/src/modules/counter.js

const initialState = {number: 0};

const counter = (state = initialState, action) =&gt; {
  switch (action.type) {
    case &quot;PLUS_ONE&quot;:
      return {
        number: state.number + 1,
      };
    default:
      return state;
 }};

export default counter;</code></pre>
<p>✔️ dispatch 로부터 전달받은 action의 type 이 &quot;PLUS_ONE&quot; 일 때 <code>state + 1</code> 실행.</p>
<p><strong>➁  dispatch 통해서 액션객체 전송</strong></p>
<pre><code class="language-js">/src/App.js

import React from &quot;react&quot;;
import { useDispatch, useSelector } from &quot;react-redux&quot;;

const App = () =&gt; {
  const dispatch = useDispatch();

  const number = useSelector((state) =&gt; state.counter.number); 

  return (
    &lt;div&gt;
      {number}
      &lt;button onClick={() =&gt; {dispatch({ type: &quot;PLUS_ONE&quot; });}}&gt;
        + 1
      &lt;/button&gt;
    &lt;/div&gt;
  );
};

export default App;</code></pre>
<p>✔️ <code>useDispatch()</code> 통해서 dispatch 생성한 후 dispatch 로 액션 객체 전송.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[React :: useEffect ]]></title>
            <link>https://velog.io/@ziyoung_room/React-useEffect</link>
            <guid>https://velog.io/@ziyoung_room/React-useEffect</guid>
            <pubDate>Thu, 27 Jun 2024 16:28:27 GMT</pubDate>
            <description><![CDATA[<h1 id="useeffect">useEffect</h1>
<hr>
<p><code>useEffect</code> : React Component가 재렌더링 될 때마다 특정 작업 ( side effect ) 을 수행하도록 하는 React Hook으로, 컴포넌트의 최상위 또는 커스텀 훅 ( Hook ) 에서만 사용.</p>
<h2 id="🔍-컴포넌트의-life-cycle-이란-">🔍 컴포넌트의 Life-cycle 이란 ?</h2>
<p><strong>💡 Mount</strong>
컴포넌트 내에서 DOM이 생성되고 웹 브라우저 상에 나타나는 것.</p>
<p>*<em>💡 Update *</em>
컴포넌트 내에서 변화가 발생하였을때 .</p>
<p><strong>💡 Unmount</strong>
컴포넌트 내에서 DOM이 제거되고 웹 브라우저 상에서 사라지는 것.</p>
<p>📌 <strong>useEffect 를 통해 생명주기에 따라 특정 작업을 수행 가능.</strong></p>
<h2 id="🧸-useeffect">🧸 useEffect</h2>
<pre><code class="language-jsx">useEffect(callbackFn, dependancyArray)</code></pre>
<p>✔︎ <code>callbackFn</code> : 실행할 로직을 작성.
✔︎ <code>dependancyArray</code> : 의존성 배열으로, 로직을 실행할 시기를 결정.</p>
<h2 id="🧸-의존성-배열">🧸 의존성 배열</h2>
<p><strong>➀ 의존성 배열이 빈 배열인 경우</strong></p>
<pre><code class="language-jsx">import React, { useEffect } from &#39;react&#39;

const App = () =&gt; {
    useEffect(()=&gt;{
      // 실행할 로직
    },[])
  return &lt;&gt;&lt;/&gt;;
}</code></pre>
<p>✔︎ 컴포넌트가 마운트 ( mount ) 될 때만 로직이 실행.
✔︎ 배열 내에 상태를 체크할 변수를 설정하지 않았기 때문에, <strong>useEffect는 최초 렌더링 이후 딱 한번만 실행.</strong></p>
<p><strong>➁ 의존성 배열에 값이 있는 경우</strong></p>
<pre><code class="language-jsx">import React, { useState, useEffect } from &#39;react&#39;

const App = () =&gt; {
      const [state, setState] = useState(&#39;&#39;);

    useEffect(()=&gt;{
      // 실행할 로직
    },[state])

  return &lt;&gt;&lt;/&gt;;
}</code></pre>
<p>✔︎ 의존성 배열에 넣어준 값인 <code>state</code> 에 변화가 감지될 때마다 실행.
✔︎ 같은 페이지 내부에서 <code>setState( )</code> 가 실행될 때마다 설정한 로직이 실행된다는 것을 의미.</p>
<p><strong>📌 Caution.</strong>
의존성 배열 자체를 설정하지 않거나 값을 잘못 설정한 경우, <strong><code>useEffect</code> 내부 로직이 무한루프로 실행</strong>되니 주의.</p>
<p><em>Example.</em></p>
<pre><code class="language-jsx">import React, { useState, useEffect } from &#39;react&#39;

const App = () =&gt; {
      const [state, setState] = useState(&#39;&#39;);

    useEffect(()=&gt;{
      setState(state + 1)
    },[state])

  return &lt;&gt;&lt;/&gt;;
}</code></pre>
<p>✔︎ 컴포넌트가 마운트되고 <code>setState()</code> 가 실행되면서 state 값 변경
 → state 값의 변화를 감지하고 useEffect 내부 로직 실행 ... <strong>~ 무한루프 ~</strong></p>
<p>🔗 useEffect 무한 루프에 대한 좋은 글을 공유해주셔서 참조했습니다.
<strong>🔗 Reference :</strong> <a href="https://velog.io/@summereuna/%EB%A6%AC%EC%95%A1%ED%8A%B8-useEffect-%EB%AC%B4%ED%95%9C-%EB%A3%A8%ED%94%84-%ED%83%88%EC%B6%9C%ED%95%98%EA%B8%B0">useEffect 무한루프에 관한 글</a></p>
<p>*<em>📌 !important. *</em>
의존성 배열을 항상 빈 배열로 세팅한 후 필요에 따라 값을 설정해주기.</p>
<h2 id="🧸-clean-up-함수">🧸 Clean Up 함수</h2>
<p>*<em>➀ 페이지를 이동할 경우 *</em></p>
<pre><code class="language-jsx">import React, { useEffect } from &#39;react&#39;
import { useNavigate } from &quot;react-router-dom&quot;;

const App = () =&gt; {
  const navigate = useNavigate()

  useEffect(()=&gt;{
        return ()=&gt;{
          // unmount 되었을 때 실행할 로직 =cleanup
        }
    }, [])

  return &lt;button onClick={()=&gt;{navigate(&#39;/&#39;}}&gt; → &lt;/button&gt;;
}</code></pre>
<p>✔︎ 컴포넌트가 언마운트 ( unmount ) 되었을 때 로직이 실행.
✔︎ 버튼을 클릭하면 페이지가 이동되면서 즉, <strong>브라우저 상에서 컴포넌트가 사라지면서</strong> 로직이 실행.</p>
<p>*<em>➁ 타이머 함수 *</em></p>
<pre><code class="language-jsx">useEffect(()=&gt;{ 
  let a = setTimeout(()=&gt;{ alert(&#39;시간이 다됐어요 !&#39;) }, 10000)
  return ()=&gt;{
    clearTimeout(a)
  }
}, [])</code></pre>
<p>✔︎ 기존에 있던 타이머 함수를 지우고 그 후에 타이머 함수를 새로 실행시켜 준다는 의미.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[React :: useContext]]></title>
            <link>https://velog.io/@ziyoung_room/React-useContext</link>
            <guid>https://velog.io/@ziyoung_room/React-useContext</guid>
            <pubDate>Wed, 26 Jun 2024 06:01:18 GMT</pubDate>
            <description><![CDATA[<h1 id="context-api">Context API</h1>
<hr>
<p><strong><code>Context API</code></strong> :  React에서 제공하는 전역적으로 데이터를 공유할 수 있게 해주는 기능.</p>
<p><strong><code>useState</code></strong> 를 사용했을 때, 불필요하게 props - drilling 형태로 내려줘야하는 경우가 발생한다. 이는 코드 복잡성을 증가시켜 가독성이 떨어지고 유지 보수를 어렵게 한다.</p>
<p><strong><code>Props - drilling</code></strong> : 해당 props를 사용하지 않는 컴포넌트라고 할지라도 중첩된 여러 계층의 컴포넌트에게 props를 전달해 주는 것을 의미. </p>
<h2 id="🧸-createcontext">🧸 createContext</h2>
<pre><code class="language-js">// src folder &gt; context folder &gt; NameContext.js 생성
import {createContext} from &quot;react&quot;

export const NameContext = createContext(기본값);</code></pre>
<p>✔️ <code>createContext</code> 를 이용해 context 를 생성.
✔️ context 가 없을 경우 출력될 기본값 설정 가능.</p>
<h2 id="🧸-contextprovider">🧸 Context.Provider</h2>
<pre><code class="language-jsx">// 최상위 파일 - App.jsx
import React, { useState } from &quot;react&quot;;
import { NameContext } from &quot;../context/NameContext&quot;;

function App() {
  const [state, setState] = useState(&#39;&#39;);

  return (
    &lt;NameContext.Provider value={{state, setState}}&gt;
      &lt;Router/&gt;
    &lt;/NameContext.Provider&gt;
  );
}

export default App;</code></pre>
<p>✔️ <code>Provider</code> 로 context 를 하위 컴포넌트에 전달.
✔️ context 로 전달할 변수 또는 함수를 value에 객체 형태로 넣기. </p>
<h2 id="🧸-usecontext--">🧸 useContext ( )</h2>
<pre><code class="language-jsx">// context 를 사용할 파일.
import React, { useContext } from &quot;react&quot;;
import { NameContext } from &quot;../context/NameContext&quot;;

function Name() {
  const {state, setState} = useContext(NameContext);

  return;
}

export default Name;</code></pre>
<p>✔️ <code>useContext</code> 를 이용해 context 를 구독하면 컴포넌트 내에서 context 로 전달된 변수 또는 함수를 사용 가능.</p>
<p><strong>📌 Caution.</strong>
Provider 에서 제공한 value 의 값이 달라질 경우, useContext 를 통해 context 를 구독하고 있는 모든 컴포넌트가 리렌더링된다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[React :: useState 
- 하나의 state로 여러가지  값 관리하기]]></title>
            <link>https://velog.io/@ziyoung_room/React-useState-%ED%95%98%EB%82%98%EC%9D%98-state%EB%A1%9C-%EC%97%AC%EB%9F%AC%EA%B0%80%EC%A7%80-%EA%B0%92-%EA%B4%80%EB%A6%AC%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@ziyoung_room/React-useState-%ED%95%98%EB%82%98%EC%9D%98-state%EB%A1%9C-%EC%97%AC%EB%9F%AC%EA%B0%80%EC%A7%80-%EA%B0%92-%EA%B4%80%EB%A6%AC%ED%95%98%EA%B8%B0</guid>
            <pubDate>Tue, 25 Jun 2024 07:42:40 GMT</pubDate>
            <description><![CDATA[<h1 id="usestate">useState</h1>
<hr>
<h3 id="🧸-state를-객체-형태로-관리해주기">🧸 state를 객체 형태로 관리해주기</h3>
<pre><code class="language-jsx">import {useState} from &#39;react&#39;

const [values, setValues] = useState({
  title: &#39;&#39;,
  content: &#39;&#39;,
  image: &#39;&#39;,
  brand: &#39;오리온&#39;,
  flavor: &#39;딸기&#39;,
  type: &#39;콘&#39;
});</code></pre>
<p>✔️ state 로 관리해주려고 했던 값들을 객체 형태 [ key - value ] 로 묶어서 관리.</p>
<h3 id="🧸-input-요소에-name--value-값-지정해주기">🧸 input 요소에 name &amp; value 값 지정해주기</h3>
<pre><code class="language-jsx">&lt;input type=&quot;text&quot; name=&quot;title&quot; value={values.title} onChange={onChangeHandler} /&gt;</code></pre>
<p>✔️ <code>name</code> - state의 key 값 
✔️ <code>value</code> - state.key </p>
<h3 id="🧸-name--value-값-이용하여-handler-함수-생성">🧸 name &amp; value 값 이용하여 Handler 함수 생성</h3>
<pre><code class="language-jsx">const onChangeHandler = (event) =&gt; {
  const { name, value } = event.target;
  setValues((prev) =&gt; {
  ...prev,
  [name]: value
  });
};</code></pre>
<p>✔️ <code>name</code> &amp; <code>value</code> 를 각각 구조분해할당을 이용해 변수로 받기.
✔️ setState 함수를 사용하여, 객체 내의 <code>name</code>이라는 key를 가진 value를 input 의 <code>value</code> 값으로 변경.</p>
<p><strong>📌 !important.</strong>
여러 Input을 각각의 state로 관리하게 되면, 이후 가독성 저하로 인해 유지 보수하기 힘들어진다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[React  :: useState ]]></title>
            <link>https://velog.io/@ziyoung_room/React-useState-913vras0</link>
            <guid>https://velog.io/@ziyoung_room/React-useState-913vras0</guid>
            <pubDate>Mon, 24 Jun 2024 16:58:11 GMT</pubDate>
            <description><![CDATA[<h1 id="usestate">useState</h1>
<hr>
<p><strong><code>State</code></strong> 란, 컴포넌트 내부에서 바뀔 수 있는 값을 의미.</p>
<p><strong><code>useState( )</code></strong> 는 React 에서 제공하는 훅 (Hook)으로, state를 생성해주는 기능을 가지고 있다.</p>
<h3 id="🧸-usestate-setting">🧸 useState Setting</h3>
<pre><code class="language-js">import { useState } from &quot;react&quot;

const [state, setState] = useState(초기값);</code></pre>
<p>✔️ 구조분해할당 문법을 사용하여, 배열 안에 각각 state의 이름과 set + state의 이름으로 <code>useState( )</code> 훅을 생성.</p>
<p>✔️ <code>useState( )</code> 의 인자에는 state의 초기값을 설정.</p>
<h3 id="🧸-state--setstate">🧸 state &amp; setState</h3>
<p> ➀  <code>state</code> 란, 상태의 할당된 값이 담긴 변수로 set함수가 사용됨에 따라 값이 변경.</p>
<p> ➁ <code>setState</code> 란, state의 할당된 값을 변화시키는 함수.</p>
<p> ✔️ state의 이름은 변수에 할당할 값에 따라 유동적으로 변경 가능.</p>
<h3 id="🧸-state-변경">🧸 state 변경</h3>
<pre><code class="language-js">import { useState } from &quot;react&quot;

const [state, setState] = useState(&#39;&#39;);
setState(&#39;Hello World !&#39;);

console.log(state); // Hello World !</code></pre>
<p>✔️ <code>setState( )</code> 함수로 인해, state에 &#39;Hello World !&#39; 가 할당되어 출력.
✔️ <code>setState( )</code> 함수를 event 핸들러와 연결하는 방식으로, state에 할당시키는 시점을 조절 가능.</p>
<p><strong>📌 Caution.</strong>
<code>setState()</code> 함수로 값을 할당했더라도, 해당 값이 어딘가에 저장되어 있지 않기 때문에 브라우저를 새로고침하면 다시 초기값으로 변경. </p>
<h3 id="🧸-state-에-객체를-할당할-경우----불변성">🧸 state 에 객체를 할당할 경우  :  불변성</h3>
<p><strong>➀ 배열 Array</strong> </p>
<pre><code class="language-js">import { useState } from &quot;react&quot;

const [state, setState] = useState([{name: &#39;모찌&#39;, species: &#39;말티즈&#39;}]);
setState((prev)=&gt;[...prev, {name: &#39;뭉치&#39;, species: &#39;리트리버&#39;}] );

console.log(state); 
// [{name: &#39;모찌&#39;, species: &#39;말티즈&#39;}, {name: &#39;뭉치&#39;, species: &#39;리트리버&#39;}] </code></pre>
<p><strong>➁ 객체 Object</strong> </p>
<pre><code class="language-js">import { useState } from &quot;react&quot;

const [state, setState] = useState([{name: &#39;모찌&#39;, species: &#39;말티즈&#39;}]);
setState((prev)=&gt;{
  return {...prev, age: 8}
} );

console.log(state); 
// { name: &#39;모찌&#39;, species: &#39;말티즈&#39;, age:8 }</code></pre>
<p>✔️ 새로운 객체를 생성하고 이전 state 값을 복사한 후, 변경된 값을 <code>setState( )</code>의 인수로 할당.</p>
<p><strong>📌 Caution.</strong>
<code>&quot; 불변성을 지킨다 &quot;</code> : 메모리 영역에서 값을 변경할 수 없게 한다.</p>
<p><strong>1) 리액트의 state 변화 감지 기준은 &quot;콜스택의 주소값&quot;이다.</strong>
: state를 빠르게 감지할 수 있게 하지만 불변성을 유지해야 하는 이유이기도 하다.</p>
<p>참조 타입의 값을 변경할 경우, 
콜스택의 주소값은 변경이 없어 react는 state의 변경이 없다고 감지하기 때문에 변경된 state는 재랜더링되지 않는다.</p>
<p><strong>2) 불변성을 지킴으로서 사이드 이펙트와 복잡한 코드를 방지할 수 있다.</strong>
: 기존 메모리 영역의 값이 변경할 경우, 기존 메모리 영역의 값을 사용하는 다른 코드에서 발생할 수 있는 오류를 사전에 방지 가능.</p>
<p><code>🧷 Reference</code>    <a href="https://velog.io/@badahertz52/%EC%B0%B8%EC%A1%B0%ED%83%80%EC%9E%85%EA%B3%BC-React%EC%9D%98-%EB%B6%88%EB%B3%80%EC%84%B1">- 참조한 글 바로가기 </a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[React :: Props]]></title>
            <link>https://velog.io/@ziyoung_room/React-Props</link>
            <guid>https://velog.io/@ziyoung_room/React-Props</guid>
            <pubDate>Thu, 23 May 2024 09:19:52 GMT</pubDate>
            <description><![CDATA[<h1 id="props">Props</h1>
<hr>
<p><code>Component</code>란 , UI를 구성하는 재사용이 가능한 독립적인 모듈을 말한다.</p>
<p><code>Props</code>란 , 컴포넌트끼리의 정보 교환 방식으로 ,  데이터를 부모 Component -&gt; 자식 Component 로 보내는 방법을 말한다. 여러 요소를 담은 하나의 객체 형태로 구성되어 있다.</p>
<h3 id="🧸-함수형-컴포넌트">🧸 함수형 컴포넌트</h3>
<pre><code class="language-jsx">function WelcomeFunc(props){
  return &lt;div&gt;Hello, {props.name}&lt;/div&gt;
}</code></pre>
<p>✔️ javascript 함수 형식으로 작성한 Component.</p>
<h3 id="🧸-클래스형-컴포넌트">🧸 클래스형 컴포넌트</h3>
<pre><code class="language-jsx">class WelcomeClass extends React.Component {
  render() {
    return &lt;div&gt;Hello, {this.props.name}&lt;/div&gt;;
  }
}</code></pre>
<p>✔️ <code>ES6 Class</code> 를 사용하여 정의한 Component.</p>
<p>📌 <strong>Caution.</strong>
Component 이름은 <code>PascalCase</code> , 폴더 이름은 <code>camelCase</code> 사용.</p>
<h3 id="🧸-component-보는-방법">🧸 Component 보는 방법</h3>
<pre><code class="language-jsx">// import : 내가 필요한 파일을 가져오는 영역
import React from &quot;react&quot;

function Ex() {
  // 자바스크립트 문법을 쓸 수 있는 영역
  return 
  &lt;div&gt;{/* JSX 를 쓸 수 있는 영역 */}&lt;/div&gt;;
}

// 내가 만든 컴포넌트를 밖으로 내보내는 영역
export default Ex;</code></pre>
<h3 id="🧸-props">🧸 Props</h3>
<pre><code class="language-jsx">function App() {
  return &lt;Father /&gt;;
} // 내 이름은 류선재입니다.

function Father() {
  const lastName = &quot;류&quot;;
  return &lt;Child lastName={lastName} /&gt;;
}

function Child(props) {
  const name = &quot;선재&quot;;
  return (
    &lt;div&gt;
      &lt;p&gt;{`내 이름은 ${props.lastName}${name}입니다.`}&lt;/p&gt;
    &lt;/div&gt; 
  );
}</code></pre>
<p>✔️ <code>부모 Component -&gt; 자식 Component</code> :  단방향 
✔️ 반드시 읽기전용으로 취급하며 변경 X.</p>
<p>📌 <strong>Caution.</strong>
인수로 받은 props 는 하나의 객체 형태로 전달되며, props 자리의 여러 변수가 주어질 경우 에러를 반환.</p>
<h3 id="🧸-props--구조분해할당">🧸 Props : 구조분해할당</h3>
<pre><code class="language-jsx">const App = () =&gt; {
  const title = &quot;[선재 업고 튀어]&quot;;
  const character = { name: &quot;류선재&quot;, age: 18, job: &quot;수영선수&quot; };

  return (
    &lt;div&gt;
      &lt;Introduction title={title} character={character} /&gt;
    &lt;/div&gt; 
  );// [선재 업고 튀어]
};  // 내 이름은 류선재이고, 18살이야.

const Introduction = ({ title = &quot;드라마&quot;, character }) =&gt; {
  const { name, age, job } = character;
  return (
    &lt;div&gt;
      &lt;h3&gt;{title}&lt;/h3&gt;
      {`내 이름은 ${name}이고, ${age}살이야.`}
    &lt;/div&gt;
  );
};</code></pre>
<p>✔️ props 객체에 값이 없을 경우, 출력할 초기값도 세팅 가능.
✔️ 객체 구조분해할당을 이용하여 props 속성을 바로 변수에 할당 가능.</p>
<h3 id="🧸-props--함수">🧸 Props : 함수</h3>
<pre><code class="language-jsx">const App = () =&gt; {
  const title = &quot;[Todo List]&quot;;
    const isDone = () =&gt; {
      console.log(&quot;Done!&quot;)
    }
  return (
    &lt;div&gt;
      &lt;Todo title={title} isDone={isDone} /&gt;
    &lt;/div&gt;
  );
};

const Todo = ({ title, isDone }) =&gt; {
  return (
    &lt;div&gt;
      &lt;h3&gt;{title}&lt;/h3&gt;
        React 공부하기
        &lt;button onClick={isDone} &gt;Click&lt;/button&gt;
    &lt;/div&gt;
  );
};</code></pre>
<p>✔️ props로 함수를 전달하여 자식 Component에서 사용 가능.</p>
<p>📌 <strong>Caution.</strong>
<code>functionName()</code> 형태로 전달할 경우, 함수 선언부가 아닌 함수 실행한 결과를 전달하게 된다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[backjoon :: 킹, 퀸, 룩, 비숍, 나이트, 폰]]></title>
            <link>https://velog.io/@ziyoung_room/backjoon-%ED%82%B9-%ED%80%B8-%EB%A3%A9-%EB%B9%84%EC%88%8D-%EB%82%98%EC%9D%B4%ED%8A%B8-%ED%8F%B0</link>
            <guid>https://velog.io/@ziyoung_room/backjoon-%ED%82%B9-%ED%80%B8-%EB%A3%A9-%EB%B9%84%EC%88%8D-%EB%82%98%EC%9D%B4%ED%8A%B8-%ED%8F%B0</guid>
            <pubDate>Fri, 10 May 2024 09:18:50 GMT</pubDate>
            <description><![CDATA[<h3 id="문제">문제</h3>
<hr>
<p>동혁이는 오래된 창고를 뒤지다가 낡은 체스판과 피스를 발견했다.</p>
<p>체스판의 먼지를 털어내고 걸레로 닦으니 그럭저럭 쓸만한 체스판이 되었다. 하지만, 검정색 피스는 모두 있었으나, 흰색 피스는 개수가 올바르지 않았다.</p>
<p>체스는 총 16개의 피스를 사용하며, 킹 1개, 퀸 1개, 룩 2개, 비숍 2개, 나이트 2개, 폰 8개로 구성되어 있다.</p>
<p>동혁이가 발견한 흰색 피스의 개수가 주어졌을 때, 몇 개를 더하거나 빼야 올바른 세트가 되는지 구하는 프로그램을 작성하시오.</p>
<h3 id="입력">입력</h3>
<hr>
<p>첫째 줄에 동혁이가 찾은 흰색 킹, 퀸, 룩, 비숍, 나이트, 폰의 개수가 주어진다. 이 값은 0보다 크거나 같고 10보다 작거나 같은 정수이다.</p>
<h3 id="출력">출력</h3>
<hr>
<p>첫째 줄에 입력에서 주어진 순서대로 몇 개의 피스를 더하거나 빼야 되는지를 출력한다. 만약 수가 양수라면 동혁이는 그 개수 만큼 피스를 더해야 하는 것이고, 음수라면 제거해야 하는 것이다.</p>
<h3 id="입출력-예">입출력 예</h3>
<hr>
<table>
<thead>
<tr>
<th align="center">input</th>
<th align="center">output</th>
</tr>
</thead>
<tbody><tr>
<td align="center">0 1 2 2 2 7</td>
<td align="center">1 0 0 0 0 1</td>
</tr>
<tr>
<td align="center">2 1 2 1 2 1</td>
<td align="center">-1 0 0 1 0 7</td>
</tr>
</tbody></table>
<h3 id="문제-풀이">문제 풀이</h3>
<hr>
<p><strong>:: Code ::</strong></p>
<pre><code class="language-js">const fs = require(&#39;fs&#39;);
const input = fs.readFileSync(0, &#39;utf8&#39;).toString().split(&#39; &#39;).map(Number);

const chess = [1, 1, 2, 2, 2, 8];
const answer = chess.map((x,index)=&gt;x-input[index])

console.log(answer.join(&#39; &#39;))</code></pre>
<p>✔️ <code>Array.map()</code> 에서 인덱스를 받아와 해당 요소와 인덱스가 일치하는 요소끼리 계산하여 반환.</p>
<p>📌 <code>Array.map(n, index)</code> 
: 배열의 각 요소에 대해 실행한 callback의 결과를 모은 새로운 배열을 반환.
📌 <strong>Caution.</strong>
두번째 인수는 선택적 요소로,배열에서 꺼내오는 요소의 인덱스를 받을 수 있다.</p>
<p>📎  <strong>Note.</strong> 
처음 풀이했을 때는, input의 인덱스를 설정하여 꺼내오기 위해 for 문 안에 map을 사용한 코드를 작성하였다. 
이중 반복문으로 chess 의 마지막 원소인 8이 input의 모든 원소의 값과 계산되는 결과가 도출되었다.
<code>Array.map( )</code> 메소드에서 index 값이 주어진다는 사실을 기억해두자.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[javascript :: Destructuring assignment]]></title>
            <link>https://velog.io/@ziyoung_room/javascript-%EA%B5%AC%EC%A1%B0%EB%B6%84%ED%95%B4%ED%95%A0%EB%8B%B9</link>
            <guid>https://velog.io/@ziyoung_room/javascript-%EA%B5%AC%EC%A1%B0%EB%B6%84%ED%95%B4%ED%95%A0%EB%8B%B9</guid>
            <pubDate>Thu, 09 May 2024 07:40:31 GMT</pubDate>
            <description><![CDATA[<h1 id="destructuring-assignment">Destructuring assignment</h1>
<hr>
<p><code>구조분해 할당 (Destructuring assignment)</code> 은 구조화된 이터러블 또는 객체를 비구조화하여 1개 이상의 변수에 개별적으로 할당하는 것이다. 
이터러블 또는 객체 리터럴에서 필요한 값만 추출하여 변수에 할당할 때 유용하다.</p>
<h3 id="🧸-배열의-구조분해-할당">🧸 배열의 구조분해 할당</h3>
<pre><code class="language-js">const fruits = [&#39;Apple&#39;,&#39;Banana&#39;,&#39;Cherry&#39;]

const [a,b,c,d] = fruits
console.log(a,b,c,d); // Apple Banana Cherry undefined

const [,b] = fruits
console.log(b) // Banana

const [, ,b] = fruits
console.log(b) // Cherry</code></pre>
<p>✔️ 중간에 위치한 값만 추출하여 할당할 경우에는 쉼표 사용.
✔️ 쉼표 개수에 따라 2번째 값 or 3번째 값 등 선택하여 추출하는 것도 가능.</p>
<pre><code class="language-js">const fruits = [&#39;Apple&#39;,&#39;Banana&#39;,&#39;Cherry&#39;]

let [a, b, c, d] = fruits;
console.log(d) // undefined

let [w, x, y, z = &#39;kiwi&#39;] = fruits;
console.log(z) // kiwi</code></pre>
<p>✔️ 기존 배열보다 변수의 개수가 많을 경우, 해당 변수는 undefined.
✔️ 초기 값이 세팅되어 있으면 초기값으로 출력되며, 할당할 값이 있으면 대체.</p>
<h3 id="🧸-객체의-구조분해-할당">🧸 객체의 구조분해 할당</h3>
<pre><code class="language-js">const user = {
    name: &#39;Jiyoung&#39;,
    age: 26,
    email: &#39;jiyoung990602@gmail.com&#39;
}

const {name, age, email, address} = user
// E.g. user.address

console.log(`사용자의 이름은 ${name}입니다.`)
console.log(`${name}의 나이는 ${age}입니다.`)
console.log(`${name}의 이메일 주소는 ${email}입니다.`)
console.log(address) // undefined</code></pre>
<p>✔️ user 내에 있는 속성을 각각의 변수로 만들어서 사용 가능. 
✔️ 필요한 변수들만 선택적으로 만들어서도 사용 가능.</p>
<pre><code class="language-js">const user = {
    name: &#39;Jiyoung&#39;,
    age: 26,
    email: &#39;jiyoung990602@gmail.com&#39;,
    address: &#39;USA&#39;
}

const {name : jiyoung, age, email, address = &#39;Korea&#39;} = user 
// E.g. user.address

console.log(`사용자의 이름은 ${jiyoung}입니다.`)
console.log(`${jiyoung}의 나이는 ${age}입니다.`)
console.log(`${jiyoung}의 이메일 주소는 ${user.email}입니다.`)
console.log(address) // USA</code></pre>
<p>✔️ address 값이 없는 경우, 출력될 기본값 설정 가능. 
✔️ 콜론 뒤에 다른 이름으로 지정 시, 다른 이름의 변수로도 사용 가능.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[programmers :: 제곱수 판별하기]]></title>
            <link>https://velog.io/@ziyoung_room/programmers-%EC%A0%9C%EA%B3%B1%EC%88%98-%ED%8C%90%EB%B3%84%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@ziyoung_room/programmers-%EC%A0%9C%EA%B3%B1%EC%88%98-%ED%8C%90%EB%B3%84%ED%95%98%EA%B8%B0</guid>
            <pubDate>Thu, 02 May 2024 12:16:45 GMT</pubDate>
            <description><![CDATA[<h3 id="문제-설명">문제 설명</h3>
<hr>
<p>어떤 자연수를 제곱했을 때 나오는 정수를 제곱수라고 합니다. 정수 n이 매개변수로 주어질 때, n이 제곱수라면 1을 아니라면 2를 return하도록 solution 함수를 완성해주세요.</p>
<h3 id="제한사항">제한사항</h3>
<hr>
<p>1 ≤ n ≤ 1,000,000</p>
<h3 id="입출력-예">입출력 예</h3>
<hr>
<table>
<thead>
<tr>
<th align="center">n</th>
<th align="center">result</th>
</tr>
</thead>
<tbody><tr>
<td align="center">144</td>
<td align="center">1</td>
</tr>
<tr>
<td align="center">976</td>
<td align="center">2</td>
</tr>
</tbody></table>
<h3 id="문제-풀이">문제 풀이</h3>
<hr>
<p><strong>:: Code ::</strong></p>
<pre><code class="language-js">function solution(n) {
    for(let i=1; i&lt;n; i++){
        if(i**2 === n){
            return 1;
            break;
        }
    }
    return 2;   
}</code></pre>
<p><strong>:: 🧷 Code 🧷 ::</strong></p>
<pre><code class="language-js">function solution(n) {
  return Number.isInteger(Math.sqrt(n)) ? 1 : 2;
}</code></pre>
<p>✔️ <code>Matj.sqrt( )</code> 
: 매개변수의 제곱근 반환. 음수일 경우에는 NaN으로 반환.
✔️ <code>Number.isInteger( )</code> 
: 매개변수가 정수인지 판별하여 Boolean값으로 반환.</p>
<p>📌 <code>Math.pow(숫자,지수)</code>
: 받아온 숫자를 지수만큼 제곱하여 반환.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[programmers :: 배열 자르기]]></title>
            <link>https://velog.io/@ziyoung_room/programmers-%EB%B0%B0%EC%97%B4-%EC%9E%90%EB%A5%B4%EA%B8%B0</link>
            <guid>https://velog.io/@ziyoung_room/programmers-%EB%B0%B0%EC%97%B4-%EC%9E%90%EB%A5%B4%EA%B8%B0</guid>
            <pubDate>Wed, 01 May 2024 10:23:03 GMT</pubDate>
            <description><![CDATA[<h3 id="문제-설명">문제 설명</h3>
<hr>
<p>정수 배열 numbers와 정수 num1, num2가 매개변수로 주어질 때, numbers의 num1번 째 인덱스부터 num2번째 인덱스까지 자른 정수 배열을 return 하도록 solution 함수를 완성해보세요.</p>
<h3 id="제한사항">제한사항</h3>
<hr>
<p>2 ≤ numbers의 길이 ≤ 30
0 ≤ numbers의 원소 ≤ 1,000
0 ≤ num1 &lt; num2 &lt; numbers 의 길이</p>
<h3 id="입출력-예">입출력 예</h3>
<hr>
<table>
<thead>
<tr>
<th align="center">numbers</th>
<th align="center">num1</th>
<th align="center">num2</th>
<th align="center">result</th>
</tr>
</thead>
<tbody><tr>
<td align="center">[1, 2, 3, 4, 5]</td>
<td align="center">1</td>
<td align="center">3</td>
<td align="center">[2, 3, 4]</td>
</tr>
<tr>
<td align="center">[1, 3, 5]</td>
<td align="center">1</td>
<td align="center">2</td>
<td align="center">[3, 5]</td>
</tr>
</tbody></table>
<h3 id="문제-풀이">문제 풀이</h3>
<hr>
<p><strong>:: Code ::</strong></p>
<pre><code class="language-js">function solution(numbers, num1, num2) {
    return numbers.slice(num1,num2+1)
}</code></pre>
<p>✔️ <code>Array.prototype.slice(startIndex, endIndex+1)</code></p>
<p><strong>:: 🧷 Code 🧷 ::</strong></p>
<pre><code class="language-js">function solution(numbers, num1, num2) {
    return numbers.splice(num1, num2-num1+1);
}</code></pre>
<p>✔️ <code>Array.prototype.splice(startIndex, 삭제할 개수)</code></p>
<p>📌** Caution.** - array.slice 와 array.splice 의 차이점</p>
<p><code>Array.prototype.slice( )</code> 
 : 시작인덱스와 끝인덱스 +1 값을 받아 자른 배열을 반환한다.</p>
<p><code>Array.prototype.splice( )</code>
 : 시작인덱스와 시작인덱스부터 삭제할 개수를 받아 자른 배열을 반환한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[programmers :: 배열의 유사도]]></title>
            <link>https://velog.io/@ziyoung_room/programmers-%EB%B0%B0%EC%97%B4%EC%9D%98-%EC%9C%A0%EC%82%AC%EB%8F%84</link>
            <guid>https://velog.io/@ziyoung_room/programmers-%EB%B0%B0%EC%97%B4%EC%9D%98-%EC%9C%A0%EC%82%AC%EB%8F%84</guid>
            <pubDate>Tue, 30 Apr 2024 09:38:30 GMT</pubDate>
            <description><![CDATA[<h3 id="문제-설명">문제 설명</h3>
<hr>
<p>두 배열이 얼마나 유사한지 확인해보려고 합니다. 
문자열 배열 s1과 s2가 주어질 때 같은 원소의 개수를 return하도록 solution 함수를 완성해주세요.</p>
<h3 id="제한사항">제한사항</h3>
<hr>
<p>1 ≤ s1, s2의 길이 ≤ 100
1 ≤ s1, s2의 원소의 길이 ≤ 10</p>
<p>s1과 s2의 원소는 알파벳 소문자로만 이루어져 있습니다
s1과 s2는 각각 중복된 원소를 갖지 않습니다.</p>
<h3 id="입출력-예">입출력 예</h3>
<hr>
<table>
<thead>
<tr>
<th align="center">s1</th>
<th align="center">s2</th>
<th align="center">result</th>
</tr>
</thead>
<tbody><tr>
<td align="center">[&quot;a&quot;, &quot;b&quot;, &quot;c&quot;]</td>
<td align="center">[&quot;com&quot;, &quot;b&quot;, &quot;d&quot;, &quot;p&quot;, &quot;c&quot;]</td>
<td align="center">2</td>
</tr>
<tr>
<td align="center">[&quot;n&quot;, &quot;omg&quot;]</td>
<td align="center">[&quot;m&quot;, &quot;dot&quot;]</td>
<td align="center">0</td>
</tr>
</tbody></table>
<h3 id="문제-풀이">문제 풀이</h3>
<hr>
<p><strong>:: Code ::</strong></p>
<pre><code class="language-js">function solution(s1, s2) {
    let count = 0;
    for (let a of s1){
        for (let b of s2){
            if(a === b){count += 1;}
        }
    }
    return count;
}</code></pre>
<p>✔️ 2중 for 문을 사용하여 배열의 원소를 비교.</p>
<p><strong>:: 🧷 Code 🧷 ::</strong></p>
<pre><code class="language-js">function solution(s1, s2) {
    const intersection = s1.filter((x) =&gt; s2.includes(x));
    return intersection.length;
}</code></pre>
<p>✔️ <code>Array.prototype.filter( )</code> : 설정한 조건에 부합하는 원소로 이루어진 새로운 배열을 반환.</p>
<p>🏷 <strong>매개변수</strong>
<code>element</code> : 배열에서 처리 중인 현재 요소.</p>
<p><code>index</code> : 배열에서 처리 중인 현재 요소의 인덱스.</p>
<p><code>array</code> : filter( )가 호출된 배열.</p>
<p>📌 <strong>Caution.</strong>
<code>Array.prototype.map( )</code> 과 달리, 반환하는 배열의 길이가 원본 배열의 길이와 다를 가능성을 가진다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[javascript :: Dom API]]></title>
            <link>https://velog.io/@ziyoung_room/javascript-Dom-API</link>
            <guid>https://velog.io/@ziyoung_room/javascript-Dom-API</guid>
            <pubDate>Mon, 29 Apr 2024 12:19:28 GMT</pubDate>
            <description><![CDATA[<h1 id="dom-api">DOM API</h1>
<hr>
<p><code>DOM (Digital Object Model)</code> 은 HTML 문서의 계층적 구조와 저보를 표현하며 이를 제어할 수 있는 API, 즉 프로퍼티와 메서드를 제공하는 트리 자료구조이다.</p>
<h3 id="🧸-id를-이용한-요소-노드-취득">🧸 ID를 이용한 요소 노드 취득</h3>
<p> <code>&gt; Document.prototype.getElementById Method</code></p>
<pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html&gt;
  &lt;body&gt;
    &lt;ul&gt;
      &lt;li id=&quot;apple&quot;&gt;Apple&lt;/li&gt;
      &lt;li id=&quot;banana&quot;&gt;Banana&lt;/li&gt;
      &lt;li id=&quot;orange&quot;&gt;Orange&lt;/li&gt;
    &lt;/ul&gt;
    &lt;script&gt;
      // ID 값이 banana 인 요소 노드 탐색하여 반환.
      const el = document.getElementById(&#39;banana&#39;);

      // 취득한 요소 노드의 style.color 프로퍼티 값 변경.
      el.style.color = &#39;red&#39;;
    &lt;/script&gt;
  &lt;/body&gt;
&lt;/html&gt;</code></pre>
<p>✔️ 단 하나의 요소 노드만 반환.
 : Html내에 중복된 id 값을 갖는 여러 요소가 존재하더라도 전달된 id 요소 값을 가진 첫번째 노드만 반환.</p>
<p>✔️ 만약 인수로 전달된 id 값을 갖는 Html 요소가 존재하지 않을 경우 <em>null</em> 반환.</p>
<h3 id="🧸-tag-name을-이용한-요소-노드-취득">🧸 Tag Name을 이용한 요소 노드 취득</h3>
<p><code>&gt; Document.prototype.getElementsByTagName Method</code></p>
<pre><code class="language-html">&lt;html&gt;
  &lt;body&gt;
    &lt;ul&gt;
      &lt;li class=&quot;apple&quot;&gt;Apple&lt;/li&gt;
      &lt;li class=&quot;banana&quot;&gt;Banana&lt;/li&gt;
      &lt;li class=&quot;orange&quot;&gt;Orange&lt;/li&gt;
    &lt;/ul&gt;
    &lt;script&gt;
      // 태그 이름이 li인 요소 노드 모두 탐색하여 반환.
      const els = document.getElementsByTagName(&#39;li&#39;);

      // 취득한 모든 요소의 class 값 추가
      [...els].forEach(el =&gt;{el.classList.add(&#39;fruits&#39;);}
    &lt;/script&gt;
  &lt;/body&gt;
&lt;/html&gt;</code></pre>
<p>✔️ 인수로 주어진 태그 이름과 일치하는 모든 요소를 반환.
✔️ <code>HtmlCollection 객체</code>로 반환.
 : 여러 개의 노드 객체를 갖는 DOM 컬렉션 객체. </p>
<h3 id="🧸-class를-이용한-요소-노드-취득">🧸 Class를 이용한 요소 노드 취득</h3>
<p><code>&gt; Document.prototype.getElementByClassName Method</code></p>
<pre><code class="language-html">&lt;html&gt;
  &lt;body&gt;
    &lt;ul&gt;
      &lt;li class=&quot;fruits apple&quot;&gt;Apple&lt;/li&gt;
      &lt;li class=&quot;fruits banana&quot;&gt;Banana&lt;/li&gt;
      &lt;li class=&quot;fruits orange&quot;&gt;Orange&lt;/li&gt;
    &lt;/ul&gt;
    &lt;script&gt;
      // Class 값이 fruits 인 요소 노드 탐색하여 반환.
      const els = document.getElementsByClassName(&#39;fruits&#39;);

      // 취득한 모든 요소의 style.color 값 변경
      [...els].forEach(el=&gt;{el.style.color(&#39;red&#39;);});
    &lt;/script&gt;
  &lt;/body&gt;
&lt;/html&gt;</code></pre>
<p>✔️ 인수로 전달된 class 값과 일치하는 모든 요소 노드 취득.
✔️ 인수로 전달할 class 값은 공백으로 구분하여 여러 class 값 지정 가능.</p>
<h3 id="🧸-css-선택자를-이용한-요소-노드-취득">🧸 CSS 선택자를 이용한 요소 노드 취득</h3>
<p><code>&gt; Css 선택자</code></p>
<pre><code class="language-css">/* 전체 선택자 : 모든 요소를 선택 */
*{...}

/* 태그 선택자 : p 태그 요소를 선택 */
p{...}

/* ID 선택자 : id 값이 foo 인 요소 선택 */
#foo{...}

/* Class 선택자 : class 값이 foo 인 요소 선택 */
.foo{...}

/* 후손 선택자 : div의 후손 요소 중 p 요소 선택 */
div p{...}

/* 자식 선택자 : div 요소의 자식 요소 중 p 요소 선택 */
div &gt; p{...}</code></pre>
<p><code>&gt; Document.prototype.querySelector Method</code></p>
<pre><code class="language-html">&lt;html&gt;
  &lt;body&gt;
    &lt;ul&gt;
      &lt;li class=&quot;fruits apple&quot;&gt;Apple&lt;/li&gt;
      &lt;li class=&quot;fruits banana&quot;&gt;Banana&lt;/li&gt;
      &lt;li clas=&quot;fruits orange&quot;&gt;Orange&lt;/li&gt;
    &lt;/ul&gt;
    &lt;script&gt;
      // Class 값이 banana 인 요소 노드 탐색하여 반환.
      const el = document.querySelector(&#39;.banana&#39;);

      // Html 요소에 적용할 수 있는 메소드
      // 1. 이벤트 Event : 상황
      el.addEventListner(&#39;click&#39;,2);

      // 2. 핸들러 Handler : 실행할 함수
      el.addEventListner(&#39;click&#39;,function(){
      console.log(&#39;click!&#39;)};

    &lt;/script&gt;
  &lt;/body&gt;
&lt;/html&gt;</code></pre>
<p>✔️ Css의 class 선택자 <code>.</code>를 사용해서 같은 class 값을 가진 요소 노드 반환.
✔️ 인수로 전달한 Css 선택자를 만족하는 요소가 여러 개일 경우 <em>첫번째 요소 노드</em> 만 반환. 존재하지 않을 경우 <em>null</em> 반환.</p>
<p><code>&gt; Document.prototype.querySelectorAll Method</code></p>
<pre><code class="language-html">&lt;html&gt;
  &lt;body&gt;
    &lt;ul&gt;
      &lt;li class=&quot;fruits apple&quot;&gt;Apple&lt;/li&gt;
      &lt;li class=&quot;fruits banana&quot;&gt;Banana&lt;/li&gt;
      &lt;li clas=&quot;fruits orange&quot;&gt;Orange&lt;/li&gt;
    &lt;/ul&gt;
    &lt;script&gt;
      // Class 값이 banana 인 요소 노드 탐색하여 반환.
      const fruitEls = document.querySelectorAll(&#39;.banana&#39;);

      // 찾은 요소들 반복해서 함수 실행
      // 첫번째 매개변수 boxEl : 반복중인 요소 
      // 두번째 매개변수 index : 반복중인 번호
      fruitEls.forEach(function(fruitEl,index){})
    &lt;/script&gt;
  &lt;/body&gt;
&lt;/html&gt;</code></pre>
<p>✔️ 인수로 전달한 Css 선택자를 만족하는 모든 요소 반환.
✔️ 인수로 전달한 Css 선택자를 만족하는 요소가 존재하지 않을 경우 빈 NodeList 객체 반환.</p>
<p>💡 <strong>HTMl 내에 모든 요소 노드 취득</strong></p>
<pre><code class="language-js">const all = document.querySelectorAll(&#39;*&#39;);
// OR
const $all = document.getElementsByTagName(&#39;*&#39;);</code></pre>
<h3 id="🧸-노드-탐색">🧸 노드 탐색</h3>
<p><code>&gt; 자식 노드 탐색</code></p>
<pre><code class="language-html">&lt;html&gt;
  &lt;body&gt;
    &lt;ul id =&quot;fruits&quot;&gt;
      &lt;li class=&quot;apple&quot;&gt;Apple&lt;/li&gt;
      &lt;li class=&quot;banana&quot;&gt;Banana&lt;/li&gt;
      &lt;li clas=&quot;orange&quot;&gt;Orange&lt;/li&gt;
    &lt;/ul&gt;
    &lt;script&gt;
      const $fruits = document.getElementById(&#39;fruits&#39;);

      // #fruits 요소의 모든 자식 노드 탐색. 
      // Node.prototype.childNodes [요소 노드 + 텍스트 노드]
      console.log(#fruits.childNodes); 
      // NodeList(7) [text, li.apple, text, li.banana, text, li.orange, text]

      // Element.prototype.children [요소노드]
      console.log(#fruits.children);
      // HTML Collection(3) [li.apple, li.banana, li.orange]

      // #fruits 요소의 첫번째 자식노드 반환
      // Node.prototype.firstChild [요소 노드 + 텍스트 노드]
      console.log(#fruits.firstChild) 
      // #text

      // Element.prototype.firstElementChild [요소노드]
      console.log(#fruits.firstElementChild);
      // li.apple

      // #fruits 요소의 마지막 자식노드 반환
      // Node.prototype.lastChild [요소 노드 + 텍스트 노드]
      console.log(#fruits.lastChild) 
      // #text

      // Element.prototype.lastElementChild [요소노드]
      console.log(#fruits.lastElementChild);
      // li.orange

    &lt;/script&gt;
  &lt;/body&gt;
&lt;/html&gt;</code></pre>
<p>✔️ <code>Node.prototype. Method</code> : 요소노드 + 텍스트 노드
✔️ <code>Element.prototype. Method</code> : 요소노드</p>
<p><code>&gt; 부모 노드 탐색</code></p>
<pre><code class="language-html">&lt;html&gt;
  &lt;body&gt;
    &lt;ul id =&quot;fruits&quot;&gt;
      &lt;li class=&quot;apple&quot;&gt;Apple&lt;/li&gt;
      &lt;li class=&quot;banana&quot;&gt;Banana&lt;/li&gt;
      &lt;li clas=&quot;orange&quot;&gt;Orange&lt;/li&gt;
    &lt;/ul&gt;
    &lt;script&gt;
      const $banana = document.querySelector(&#39;.banana&#39;);
      console.log($banana.parentNode); // ul#fruits
    &lt;/script&gt;
  &lt;/body&gt;
&lt;/html&gt;</code></pre>
<p>✔️ <code>Node.prototype.parentNode</code> </p>
<h3 id="🧸-요소-노드를-통한-텍스트-조작">🧸 요소 노드를 통한 텍스트 조작</h3>
<pre><code class="language-js">const boxEl = document.querySelector(&#39;.box&#39;);

// Getter 
console.log(boxEl.textContent); // Box!!

// Setter 
boxEl.textContent = &#39;HEROPY?!&#39;;
console.log(boxEl.textContent); // HEROPY?!</code></pre>
<p>✔️ <code>Getter</code> : 값을 얻는 용도
✔️ <code>Setter</code> : 값을 지정하는 용도</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[javascript :: primitive type - object]]></title>
            <link>https://velog.io/@ziyoung_room/javascript-primitive-type-object</link>
            <guid>https://velog.io/@ziyoung_room/javascript-primitive-type-object</guid>
            <pubDate>Fri, 26 Apr 2024 11:16:00 GMT</pubDate>
            <description><![CDATA[<h1 id="primitive-type---object">primitive type - object</h1>
<hr>
<p>📌 *<em>원시 데이터  *</em> 
 : <em>String, Number, Boolean, undefined, null</em></p>
<p>📌 *<em>참조형 데이터 *</em> 
: <em>Object, Array, Function</em></p>
<h3 id="🧸-원시-데이터--primitive-type">🧸 원시 데이터 : Primitive Type</h3>
<p><code>원시 값 (Primitive Type)</code> 은 변경 불가능한 값, 읽기 전용 값이다.</p>
<p>🏷 ** 데이터 불변성 -  Immutability ** 
: 불변성을 갖는 원시 값을 할당한 변수는 재할당 이외에 값을 변경할 수 없다.</p>
<pre><code class="language-js">   |      1      |      4      |      7      |      

let a = 1;
let b = 4;
console.log(a,b, a === b) // 1 4 false

a = 7
console.log(a,b, a === b) // 7 4 false</code></pre>
<p>✔️  a에 7을 할당하면서 새로운 메모리 주소를 가리킨다.</p>
<pre><code class="language-js">        |     1     |      4      |   

let a = 1;
let b = 4;

b = a
console.log(a,b, a === b) // 1 1 true</code></pre>
<p>✔️ 원시 데이터는 내용이 일치하면 메모리 주소 또한 일치한다.
1에 대해 새로운 메모리 주소가 생성되는 것이 아닌, 기존의 1이 저장되어 있던 메모리 주소로 향한다.</p>
<h3 id="🧸-참조형-데이터--객체-object">🧸 참조형 데이터 : 객체 Object</h3>
<p><code>참조형 데이터</code> 는 변경 가능한 값으로, 재할당없이 프로퍼티를 동적으로 추가하거나 값을 갱신할 수 있으며 프로퍼티 자체를 삭제 가능하다.</p>
<p>🏷 <strong>가변성</strong>
: 참조형 데이터들은 새로운 값을 만들 때마다 새로운 메모리 주소를 할당.</p>
<pre><code class="language-js">        |    {k : 1}    |    {k : 1}     |   

let a = {k : 1};
let b = {k : 1};

console.log(a, b, a === b) // {k : 1} {k : 1} false</code></pre>
<pre><code class="language-js">        |    {k : 7}    |    {k : 1}     |     

let a = {k : 1};
let b = {k : 1};

a.k = 7
b = a
console.log(a, b, a === b) // {k : 7} {k : 7} true</code></pre>
<p>✔️ 같은 메모리 주소를 가리키게 되면 같은 값으로 나온다.</p>
<pre><code class="language-js">        |    {k : 2}    |    {k : 1}     |     

let a = {k : 1};
let b = {k : 1};

b = a
a.k = 2
console.log(a, b, a === b) // {k : 2} {k : 2} true</code></pre>
<p>✔️ 같은 메모리 주소를 가지면 하나만 수정해도 값이 같이 변경.</p>
<h3 id="🧸-얕은-복사--shallow-copy">🧸 얕은 복사 : Shallow Copy</h3>
<pre><code class="language-js">const user = {
    name: &#39;Jiyoung&#39;,
    age: 26,
    emails: [&#39;jiyoung990602@gmail.com&#39;]
}

const copyUser = user
console.log(copyUser === user) // true

user.age = 22

console.log(&#39;user&#39;,user) 
// {name: &#39;Jiyoung&#39;, age: 22, emails: [&#39;jiyoung990602@gmail.com&#39;]}

console.log(&#39;copyUser&#39;,copyUser) 
// {name: &#39;Jiyoung&#39;, age: 22, emails: [&#39;jiyoung990602@gmail.com&#39;]}</code></pre>
<p>✔️ 의도치 않은 부분이 수정될 수 있는 위험성이 존재.
같은 메모리 주소를 바라보기 때문에, user 을 변경할 경우 copyUser도 함께 변경.</p>
<p>🏷 <strong>Object.assign</strong> : 대상 객체에 출처 객체를 복사.</p>
<pre><code class="language-js">const user = {
    name: &#39;Jiyoung&#39;,
    age: 26,
    emails: [&#39;jiyoung990602@gmail.com&#39;]
}
const copyUser = Object.assign({}, user)
console.log(copyUser === user)

user.age = 22
user.emails.push(&#39;neo@zillinks.com&#39;)

console.log(&#39;user&#39;,user) 
// {name: &#39;Jiyoung&#39;, age: 22, emails: [&#39;jiyoung990602@gmail.com&#39;], &#39;neo@zillinks.com&#39;]}

console.log(&#39;copyUser&#39;,copyUser) 
// {name: &#39;Jiyoung&#39;, age: 26, emails: [&#39;jiyoung990602@gmail.com&#39;], &#39;neo@zillinks.com&#39;]}</code></pre>
<p>✔️ user 데이터만 수정 가능. 내부 참조형 데이터는 복사 X.
emails 는 참조형 데이터인 Array에 해당하기 때문이다.</p>
<p>🏷 <strong>전개 연산자</strong> : 객체를 새로 생성. </p>
<pre><code class="language-js">const user = {
    name: &#39;Jiyoung&#39;,
    age: 26,
    emails: [&#39;jiyoung990602@gmail.com&#39;]
}
const copyUser = (...user)
console.log(copyUser === user)

user.age = 22
user.emails.push(&#39;neo@zillinks.com&#39;)

console.log(&#39;user&#39;,user) 
// {name: &#39;Jiyoung&#39;, age: 22, emails: [&#39;jiyoung990602@gmail.com&#39;, &#39;neo@zillinks.com&#39;]}

console.log(&#39;copyUser&#39;,copyUser) 
// {name: &#39;Jiyoung&#39;, age: 26, emails: [&#39;jiyoung990602@gmail.com&#39;, &#39;neo@zillinks.com&#39;]}</code></pre>
<p>✔️  user 데이터만 수정 가능. 내부 참조형 데이터는 복사 X.
emails 는 참조형 데이터인 Array에 해당하기 때문이다.</p>
<h3 id="🧸-깊은-복사--deep-copy">🧸 깊은 복사 : Deep Copy</h3>
<p>🏷 <strong>cloneDeep _lodash</strong> : 재귀적으로 복사하는 메소드.</p>
<pre><code class="language-js">import _ from &#39;lodash&#39;

const user = {
    name: &#39;Jiyoung&#39;,
    age: 26,
    emails: [&#39;jiyoung990602@gmail.com&#39;]
}
const copyUser = _.cloneDeep(user)
console.log(copyUser === user)

user.age = 22
user.emails.push(&#39;neo@zillinks.com&#39;)

console.log(&#39;user&#39;,user) 
// {name: &#39;Jiyoung&#39;, age: 22, emails: [&#39;jiyoung990602@gmail.com&#39;, &#39;neo@zillinks.com&#39;]}

console.log(&#39;copyUser&#39;,copyUser) 
// {name: &#39;Jiyoung&#39;, age: 26, emails: [&#39;jiyoung990602@gmail.com&#39;]}</code></pre>
<p>✔️ 내부에 있는 참조형 데이터까지 깊은 복사 가능. 
참조형 데이터 내부에 또 다른 참조형 데이터가 존재할 경우, 깊은 복사하는 것을 고려할 필요가 있다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[programmers :: 삼각형의 완성 조건①]]></title>
            <link>https://velog.io/@ziyoung_room/programmers-%EC%82%BC%EA%B0%81%ED%98%95%EC%9D%98-%EC%99%84%EC%84%B1-%EC%A1%B0%EA%B1%B4</link>
            <guid>https://velog.io/@ziyoung_room/programmers-%EC%82%BC%EA%B0%81%ED%98%95%EC%9D%98-%EC%99%84%EC%84%B1-%EC%A1%B0%EA%B1%B4</guid>
            <pubDate>Thu, 25 Apr 2024 11:23:37 GMT</pubDate>
            <description><![CDATA[<h3 id="문제-설명">문제 설명</h3>
<hr>
<p>선분 세 개로 삼각형을 만들기 위해서는 다음과 같은 조건을 만족해야 합니다.</p>
<p>가장 긴 변의 길이는 다른 두 변의 길이의 합보다 작아야 합니다.
삼각형의 세 변의 길이가 담긴 배열 sides이 매개변수로 주어집니다. 세 변으로 삼각형을 만들 수 있다면 1, 만들 수 없다면 2를 return하도록 solution 함수를 완성해주세요.</p>
<h3 id="제한사항">제한사항</h3>
<hr>
<p>sides의 원소는 자연수입니다.
sides의 길이는 3입니다.</p>
<p>1 ≤ sides의 원소 ≤ 1,000</p>
<h3 id="입출력-예">입출력 예</h3>
<hr>
<table>
<thead>
<tr>
<th align="center">sides</th>
<th align="center">result</th>
</tr>
</thead>
<tbody><tr>
<td align="center">[1, 2, 3]</td>
<td align="center">2</td>
</tr>
<tr>
<td align="center">[3, 6, 2]</td>
<td align="center">2</td>
</tr>
<tr>
<td align="center">[199, 72, 222]</td>
<td align="center">1</td>
</tr>
</tbody></table>
<h3 id="문제-풀이">문제 풀이</h3>
<hr>
<p>*<em>:: Code :: *</em></p>
<pre><code class="language-js">function solution(sides) {
    sides = sides.sort((a,b)=&gt;a-b);
    const [x,y,z] = [...sides]
    return z &lt; x+y ? 1:2;
}</code></pre>
<p>✔️ <code>Array.sort((a,b)=&gt;a-b)</code> : 배열 오름차순 정렬. </p>
<p>📌 <strong>Caution.</strong>
구조 분해 할당 시, let 또는 const 로 변수 선언해주어야 한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[javascript :: variable scope]]></title>
            <link>https://velog.io/@ziyoung_room/javascript-variable-scope</link>
            <guid>https://velog.io/@ziyoung_room/javascript-variable-scope</guid>
            <pubDate>Wed, 24 Apr 2024 11:14:30 GMT</pubDate>
            <description><![CDATA[<h1 id="variable-scope">Variable Scope</h1>
<hr>
<h3 id="🧸-변수의-유효범위">🧸 변수의 유효범위</h3>
<pre><code class="language-js">let x = 10;

function printX(){
    console.log(x);
}

console.log(x); 
printX(); </code></pre>
<p>✔️ <code>전역 변수</code> : 전체 영역에 영향을 미치는 변수.</p>
<pre><code class="language-js">function printX(){
    let x = 10;
    console.log(x);
}

// console.log(x); // Error : x is not defined...
printX(); // 10</code></pre>
<p>✔️ <code>지역 변수</code> : 함수 내부에만 영향을 미치는 변수.</p>
<h3 id="🧸-var-키워드">🧸 Var 키워드</h3>
<pre><code class="language-js">function scope() {
    console.log(a)
    if (true) {
        var a = 123
    }
}
scope() // Undefined</code></pre>
<p>✔️ <strong>함수 레벨의 유효범위</strong><br>: 함수 내라면 어디서든 사용가능. 함수 외부에서 선언할 경우, 전역 변수. </p>
<p>① 변수 중복선언 가능. ② 변수 재할당 가능</p>
<p>📌 *<em>Caution *</em> 
의도하지 않은 범위에서 사용 가능하여 메모리 누수 발생 위험 → 사용권장 X.</p>
<h3 id="🧸-const-키워드">🧸 const 키워드</h3>
<pre><code class="language-js">function scope() {
    if (true) {
        const a = 123
    }
    console.log(a)
}
scope() 
// Uncaught ReferenceError : a is not defined..</code></pre>
<p>✔️ <strong>블럭 레벨의 유효범위</strong>
 : 모든 코드 블럭 [ 함수 / if 문 / for 문 ... ] 을 지역 스코프로 인정 .</p>
<p>① 변수 중복 선언 불가   ② 변수 재할당 금지  ③ 선언과 동시에 초기화
  그러나 변수에 객체를 할당한 경우, 값을 변경할 수 있다.</p>
<h3 id="🧸-let-키워드">🧸 let 키워드</h3>
<pre><code class="language-js">function scope() {
    if (true) {
        let a; 
        a = 123; 
    }
    console.log(a)
}
scope() 
// Uncaught ReferenceError : a is not defined..</code></pre>
<p>✔️ <strong>블럭 레벨의 유효범위</strong>
 : 모든 코드 블럭 [ 함수 / if 문 / for 문 ... ] 을 지역 스코프로 인정 .</p>
<p>① 변수 중복 선언 불가 ② 변수 재할당 가능</p>
<p>📌 *<em>Caution *</em> 
주로 재할당이 필요한 경우에만 let 키워드를 사용하며, 일반적으로는 const 키워드를 사용한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[programmers :: 모음 제거]]></title>
            <link>https://velog.io/@ziyoung_room/programmers-%EB%AA%A8%EC%9D%8C-%EC%A0%9C%EA%B1%B0</link>
            <guid>https://velog.io/@ziyoung_room/programmers-%EB%AA%A8%EC%9D%8C-%EC%A0%9C%EA%B1%B0</guid>
            <pubDate>Tue, 23 Apr 2024 11:58:35 GMT</pubDate>
            <description><![CDATA[<h3 id="문제-설명">문제 설명</h3>
<hr>
<p>영어에선 a, e, i, o, u 다섯 가지 알파벳을 모음으로 분류합니다. 문자열 my_string이 매개변수로 주어질 때 모음을 제거한 문자열을 return하도록 solution 함수를 완성해주세요.</p>
<h3 id="제한사항">제한사항</h3>
<hr>
<p>my_string은 소문자와 공백으로 이루어져 있습니다.</p>
<p>1 ≤ my_string의 길이 ≤ 1,000</p>
<h3 id="입출력-예">입출력 예</h3>
<hr>
<table>
<thead>
<tr>
<th align="center">my_string</th>
<th align="center">result</th>
</tr>
</thead>
<tbody><tr>
<td align="center">&quot;bus&quot;</td>
<td align="center">&quot;bs&quot;</td>
</tr>
<tr>
<td align="center">&quot;nice to meet you&quot;</td>
<td align="center">&quot;nc t mt y&quot;</td>
</tr>
</tbody></table>
<h3 id="문제-풀이">문제 풀이</h3>
<hr>
<p><strong>:: Code ::</strong></p>
<pre><code class="language-js">function solution(my_string) {
    const arr = [&#39;a&#39;,&#39;e&#39;,&#39;i&#39;,&#39;o&#39;,&#39;u&#39;];
    arr.forEach(el=&gt;{
        my_string = my_string.replaceAll(el,&#39;&#39;);
    })
    return my_string;
}</code></pre>
<p>✔️ <code>string.replace(str,&#39;&#39;)</code> : string에서 처음 조회되는 str을 대체.
✔️ <code>string.replaceAll(str,&#39;&#39;)</code> : 조회가능한 모든 str 을 대체.</p>
<p><strong>:: 🧷 Code 🧷 ::</strong></p>
<pre><code class="language-js">function solution(my_string) {
    return my_string.replace(/[aeiou]/g, &#39;&#39;);
}</code></pre>
<p>✔️ 정규표현식 사용하여 문자열 검색.</p>
<p>📌  <strong>RegExp :  정규표현식</strong></p>
<p><strong>Pattern</strong> - <code>[abc]</code> : a 또는 b 또는 c<br><strong>Option</strong> - <code>g</code> : 일치하는 모든 것을 검색. <code>= global</code></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[javascript :: function]]></title>
            <link>https://velog.io/@ziyoung_room/javascript-function</link>
            <guid>https://velog.io/@ziyoung_room/javascript-function</guid>
            <pubDate>Mon, 22 Apr 2024 11:39:40 GMT</pubDate>
            <description><![CDATA[<h1 id="function">Function</h1>
<hr>
<p><code>함수(Function)</code>는 일련의 과정을 문으로 구현하고 코드 블록으로 감싸서 하나의 실행 단위로 정의한 것이다.
함수 내부로 입력을 전달받는 변수를 <code>매개변수(parameter)</code> , <code>인수(argument)</code> ,<code>반환값(return value)</code> 이라고 부른다.</p>
<h3 id="🧸-함수-정의--function-definition">🧸 함수 정의 : function definition</h3>
<p>💡 <strong>함수 선언문</strong></p>
<pre><code class="language-js">function sum(a,b) { 
 return a + b;
}

// 함수 호출
console.log(sum(1,1)) 

// 함수 재사용
let a = sum(1,1)
console.log(a); // 2</code></pre>
<p><code>매개변수 (parameter) &gt;</code> x y<br><code>반환값 &gt;</code> x + y
<code>인수 (arguments) &gt;</code> 1 </p>
<p>✔️ 함수 이름을 생략 불가. 
함수를 다른 식별자에 할당하여 사용할 경우, 식별자로 호출.</p>
<p>💡 <strong>함수 표현식</strong></p>
<pre><code class="language-js">let sum = function(a,b){
  return a + b;
}

console.log(sum(1,1)) // 2</code></pre>
<p>✔️ 함수 이름 생략 가능.
기명(이름이 있는) 함수이더라도, 함수 이름이 아닌 식별자로 호출.</p>
<h3 id="🧸-함수-호이스팅-현상">🧸 함수 호이스팅 현상</h3>
<pre><code class="language-js">const a = 7

double() // 14

function double() {
    console.log(a * 2)
} </code></pre>
<p>✔️ 함수 선언부가 유효범위 최상단으로 끌어올려지는 현상. 함수 선언문에만 해당.</p>
<h3 id="🧸-화살표-함수-----⇒--">🧸 화살표 함수 :  ( ) ⇒ { }</h3>
<pre><code class="language-js">const double = function (x) {
    return x * 2 }
console.log(&#39;double: &#39;, double(7))

const doubleArrow = x =&gt; x * 2
console.log(&#39;doubleArrow&#39;, doubleArrow(7))</code></pre>
<p>✔️ 화살표 함수를 사용하게되면 <code>{ }</code>와 <code>return</code> 키워드를 생략 가능.</p>
<h3 id="🧸-iife--즉시실행함수">🧸 IIFE : 즉시실행함수</h3>
<pre><code class="language-js">const a = 7;

(function() {
console.log(a * 2)
}());</code></pre>
<p>✔️ <code>( )</code> 로 감싸줘야 정상적으로 작동.
함수 정의와 동시에 호출되는 함수로, 단 한번만 호출되며 다시 호출 불가.</p>
<h3 id="🧸-타이머-함수">🧸 타이머 함수</h3>
<pre><code class="language-js">setTimeout() =&gt; {
    console.log(&#39;Jiyoung&#39;)
}, 3000)  // 3초 후에 콘솔 출력.

const h1El = document.querySelector(&#39;h1&#39;)
h1El.addEventListener(&#39;click&#39;,()=&gt;{
    cleartimeout(timer);
})  // 3초 전에 클릭하면, 콘솔에 출력되지 않는다.</code></pre>
<p>✔️ <code>setTimeout (함수, 시간)</code> : 일정 시간 후 함수 실행.
✔️ <code>cleartimeout( )</code> : 설정된 timeout 함수를 종료.</p>
<pre><code class="language-js">const timer = setInterval(() =&gt; {
    console.log(&#39;jiyoung&#39;);
},3000);

const h1El = document.querySelector(&#39;h1&#39;);
h1El.addEventListener(&#39;click&#39;,()=&gt;{
    clearInterval(timer);
})</code></pre>
<p>✔️ <code>setInterval (함수, 시간)</code> : 시간 간격마다 함수 반복 실행.
✔️ <code>clearInterval( )</code> : 설정된 interval 함수를 종료.</p>
<h3 id="🧸-재귀-함수--recursive-function">🧸 재귀 함수 : recursive function</h3>
<pre><code class="language-js">// function countdown(n) {
//   for (let i = n; i &gt;= 0; i--) console.log(i);
// }
// countdown(10);

function countdown(n) {
  if (n&lt;0) return;
  console.log(n);
  countdown(n-1); // 재귀호출
}

countdown(10);</code></pre>
<p>✔️ <code>재귀 호출</code> : 자기자신을 호출하는 행위. 반복되는 처리를 반복문 없이 구현 가능.</p>
<h3 id="🧸-콜백-함수--callback-function">🧸 콜백 함수 : callback function</h3>
<pre><code class="language-js">function repeat(n, f) {
  for (let i = 0; i &lt; n; i++){
    f(i);}
}

const logAll = function(i) {
  console.log(i);
};

// 반복 호출할 함수를 인수로 전달.
repeat(5, logAll); // 0 1 2 3 4</code></pre>
<p>✔️ <code>콜백 함수</code> : 함수의 매개변수를 통해 다른 함수의 내부로 전달되는 함수.
✔️ <code>고차 함수</code> : 매개변수를 통해 함수의 외부에서 콜백 함수를 전달받은 함수.</p>
]]></description>
        </item>
    </channel>
</rss>