<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>won_gee.log</title>
        <link>https://velog.io/</link>
        <description>새싹 개발자 지렁이의 벨로그입니다.</description>
        <lastBuildDate>Thu, 30 Jan 2025 13:09:44 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>won_gee.log</title>
            <url>https://velog.velcdn.com/images/won_gee/profile/a263dd60-6327-4472-b5fd-2b14ccf897b9/image.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. won_gee.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/won_gee" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[SQL 파싱 / 실행 계획]]></title>
            <link>https://velog.io/@won_gee/SQL-%ED%8C%8C%EC%8B%B1-%EC%8B%A4%ED%96%89-%EA%B3%84%ED%9A%8D</link>
            <guid>https://velog.io/@won_gee/SQL-%ED%8C%8C%EC%8B%B1-%EC%8B%A4%ED%96%89-%EA%B3%84%ED%9A%8D</guid>
            <pubDate>Thu, 30 Jan 2025 13:09:44 GMT</pubDate>
            <description><![CDATA[<h2 id="1-sql-파싱">1. SQL 파싱</h2>
<h3 id="1-1-sql-파싱이란">1-1. SQL 파싱이란?</h3>
<p><img src="https://velog.velcdn.com/images/won_gee/post/f616bf7c-0a96-40dd-ae25-2a7e138c4e41/image.png" alt=""></p>
<h3 id="1-2-파싱의-종류">1-2. 파싱의 종류</h3>
<ul>
<li>소프트 파싱(Soft Parsing) : sql 구문이 문법적으로 맞는지 기본적인 체크 과정</li>
<li>하드 파싱(Hard Parsing) : 실행 계획(풀스캔 할 지, 인덱스 태울 건지 등 ...)</li>
</ul>
<h2 id="2-실행계획">2. 실행계획</h2>
<h3 id="2-1-실행계획의-종류">2-1. 실행계획의 종류</h3>
<ul>
<li>Execution Plan : 실행 전 계획</li>
<li>Trace : 실제 실행 과정</li>
</ul>
<h3 id="2-2-insert-into-과정-살펴보기">2-2. INSERT INTO 과정 살펴보기</h3>
<h4 id="1-sql-구문-분석-parsing">1. SQL 구문 분석 (Parsing)</h4>
<p>사용자가 실행한 INSERT INTO 구문 분석(SQL Parsing)</p>
<ul>
<li>구문의 문법이 올바른지 검사</li>
<li>테이블과 컬럼이 존재하는지 확인</li>
</ul>
<h4 id="2-쿼리-최적화-optimization">2. 쿼리 최적화 (Optimization)</h4>
<p>SQL Optimizer가 INSERT를 최적화</p>
<ul>
<li>인덱스가 적용되어 있는 경우, 어떤 방식으로 데이터를 입력할지 결정</li>
<li>병렬 처리(Parallel Execution)가 가능한지 분석</li>
</ul>
<h4 id="3-데이터-잠금-locking">3. 데이터 잠금 (Locking)</h4>
<p>INSERT INTO를 실행하기 전, 데이터 무결성을 보장하기 위해 해당 테이블 또는 행(Row)에 대해 적절한 <strong>잠금(Lock)</strong> 설정</p>
<ul>
<li>Table-Level Lock: 테이블 전체를 잠그는 방식</li>
<li>Row-Level Lock: 특정 행만 잠그는 방식</li>
</ul>
<h4 id="4-데이터-저장-및-버퍼링-buffering">4. 데이터 저장 및 버퍼링 (Buffering)</h4>
<p>데이터를 저장하기 전 버퍼 풀(Buffer Pool) 또는 트랜잭션 로그(Transaction Log)에 기록</p>
<ul>
<li>실제 테이블에 쓰이기 전에 <strong>Redo Log (변경 로그)</strong>와 <strong>Undo Log (롤백 로그)</strong>에 먼저 저장<ul>
<li>Redo Log: 장애 발생 시 복구를 위해 기록되는 로그</li>
<li>Undo Log: 트랜잭션 롤백을 위해 이전 데이터를 기록하는 로그</li>
</ul>
</li>
<li>데이터를 버퍼 풀에 임시로 저장하여 디스크 쓰기 부하를 줄임</li>
</ul>
<h4 id="5-트랜잭션-관리-transaction-management">5. 트랜잭션 관리 (Transaction Management)</h4>
<p>INSERT INTO 문이 실행될 때, 트랜잭션이 활성화되어 있다면 데이터는 즉시 반영되지 않고, 트랜잭션 로그에 기록</p>
<ul>
<li>COMMIT을 실행하면 데이터가 확정(Commit)되고, ROLLBACK을 실행하면 데이터가 취소됨</li>
<li>AUTO_COMMIT=ON 상태라면 INSERT INTO가 실행되자마자 반영</li>
</ul>
<h4 id="6-인덱스-업데이트-index-update">6. 인덱스 업데이트 (Index Update)</h4>
<p>테이블에 인덱스가 있는 경우, INSERT된 데이터가 인덱스 구조에도 반영됨</p>
<ul>
<li>B-Tree 인덱스 또는 Hash 인덱스를 업데이트하여 새로운 데이터가 검색될 수 있도록 만듬</li>
<li>다중 인덱스가 있는 경우, 각 인덱스에 맞춰 업데이트가 발생</li>
</ul>
<h4 id="7-데이터-저장-disk-write">7. 데이터 저장 (Disk Write)</h4>
<p>실제 데이터는 메모리와 캐시를 거친 후 <strong>디스크(스토리지)</strong>에 저장됨</p>
<ul>
<li>일반적으로 INSERT된 데이터는 바로 디스크에 저장되지 않고, 특정 시점(Checkpoint)이 되거나 버퍼 풀 공간이 부족할 때 디스크에 기록됨</li>
</ul>
<h4 id="8-변경-사항-반영-및-로그-정리">8. 변경 사항 반영 및 로그 정리</h4>
<p>COMMIT이 실행되면, 변경 사항이 영구적으로 반영됨</p>
<ul>
<li>INSERT INTO를 실행한 후, 일정 시간이 지나면 Redo Log 및 Undo Log가 정리됨</li>
<li>데이터가 디스크에 저장되면 CheckPoint가 발생하여 로그를 삭제하고 시스템 리소스를 관리함</li>
</ul>
<h4 id="9-트리거trigger-및-이벤트-처리">9. 트리거(Trigger) 및 이벤트 처리</h4>
<p>테이블에 <strong>트리거(Trigger)</strong>가 설정된 경우, INSERT INTO 실행 후 자동으로 추가 작업이 실행될 수 있음</p>
<ul>
<li>AFTER INSERT 트리거가 설정된 경우, 새로운 데이터가 입력된 후 다른 테이블을 업데이트하거나 추가 연산을 수행할 수 있음</li>
</ul>
<h4 id="10-결과-반환">10. 결과 반환</h4>
]]></description>
        </item>
        <item>
            <title><![CDATA[세그먼트 / 오브젝트]]></title>
            <link>https://velog.io/@won_gee/%EC%84%B8%EA%B7%B8%EB%A8%BC%ED%8A%B8-%EC%98%A4%EB%B8%8C%EC%A0%9D%ED%8A%B8</link>
            <guid>https://velog.io/@won_gee/%EC%84%B8%EA%B7%B8%EB%A8%BC%ED%8A%B8-%EC%98%A4%EB%B8%8C%EC%A0%9D%ED%8A%B8</guid>
            <pubDate>Thu, 30 Jan 2025 12:21:47 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/won_gee/post/22bc5793-2d0b-4386-949c-b641b863602b/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[데이터베이스]]></title>
            <link>https://velog.io/@won_gee/%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4</link>
            <guid>https://velog.io/@won_gee/%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4</guid>
            <pubDate>Wed, 29 Jan 2025 12:43:38 GMT</pubDate>
            <description><![CDATA[<h2 id="1-데이터베이스-메모리">1. 데이터베이스 메모리</h2>
<p><img src="https://velog.velcdn.com/images/won_gee/post/38288a5b-fdc0-4b31-843d-57c94267a834/image.png" alt=""></p>
<h2 id="2-백그라운드-프로세스">2. 백그라운드 프로세스</h2>
<p>: DB 당 1개씩 존재 &gt; DB의 핵심 연산, 프로세싱 작업들을 하는 중요한 프로세스</p>
<ul>
<li>Smon<ul>
<li>ora_smon</li>
</ul>
</li>
<li>Pmon<ul>
<li>ora_pmon</li>
</ul>
</li>
</ul>
<h2 id="3-리스너-sql-통신">3. 리스너, SQL 통신</h2>
<p><img src="https://velog.velcdn.com/images/won_gee/post/8b5160cf-39e8-4928-a0fc-b61a041fb0cf/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[How to WEB work]]></title>
            <link>https://velog.io/@won_gee/How-to-WEB-work</link>
            <guid>https://velog.io/@won_gee/How-to-WEB-work</guid>
            <pubDate>Sat, 23 Mar 2024 06:19:44 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/won_gee/post/6c9d8499-7441-48a1-877b-71bba365e5e0/image.png" alt=""></p>
<h2 id="web-동작-방식">WEB 동작 방식</h2>
<p><em>1. client에서 요청을 보낸다</em>
<em>2. Web Server는 요청에 맞는 응답을 보낸다</em>
<em>2-1. 이 과정에서 동적인 처리는 WAS를 통해 처리한다</em>
<em>2-2. 요청이 많을 경우, Load Balancer를 통해 부하가 적은 WAS에 처리를 요청한다</em>
<em>2-3. Database 조회 및 가공이 필요할 경우 연결하여 처리한다</em></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Redux Saga 파헤치기]]></title>
            <link>https://velog.io/@won_gee/Redux-Saga-%ED%8C%8C%ED%97%A4%EC%B9%98%EA%B8%B0</link>
            <guid>https://velog.io/@won_gee/Redux-Saga-%ED%8C%8C%ED%97%A4%EC%B9%98%EA%B8%B0</guid>
            <pubDate>Sun, 17 Sep 2023 12:55:51 GMT</pubDate>
            <description><![CDATA[<h1 id="시작하며">시작하며</h1>
<p>SortingBars 프로젝트를 진행하면서 랜덤한 값을 모아놓은 배열 데이터에 대한 상태를 한번 다뤄본게 Redux에 대한 최초의 경험이었다. </p>
<p>이후 데이터를 다루는 과정에서 비동기적으로 API 요청을 통해 처리해야하는 일들이 대다수였고 이러한 작업을 좀 더 정확하고 유용하게 만들어주는 Redux Saga Middleware에 대해 공부하게 되었다.</p>
<h1 id="1-saga-작동-방식">1. Saga 작동 방식</h1>
<p>Redux Saga 작동로직에 대한 이미지를 찾아보며 아래와 같이 보기 쉽게 정리해보았다.</p>
<pre><code>1 &amp; 2: UI event 발생
3: Redux Action 작동
4: dispatch Action
5 &amp; 6: API Call
7: 상태값 Store 저장
8: 상태값 업데이트 및 UI 업데이트</code></pre><p><img src="https://velog.velcdn.com/images/won_gee/post/192b2928-90d8-4f71-a5da-f3f6da05c1e3/image.png" alt=""></p>
<h1 id="2-예시-코드">2. 예시 코드</h1>
<p>React와 Redux Saga를 이용하여 만들었던 서버에 데이터를 요청하는 fetchData에 대한 예시를 소개해보고자 한다.</p>
<h3 id="코드-작동방식">코드 작동방식</h3>
<pre><code>1. UI의 특정 이벤트(예: 첫 화면 렌더링)로 인한 액션 dispatch
2. Saga 액션 감지 (take/takeLatest 등)
3. Saga에서의 비동기 작업(예: API 호출) 수행
4. 비동기 작업 완료 후, Saga의 새로운 액션 dispatch(예:put)를 통한 Redux store 업데이트
5. 해당 액션에 응답하여 Reducer 실행되어 상태가 업데이트 됨
6. 상태가 변경됨에 따른 React 컴포넌트 리렌더링</code></pre><ul>
<li>App.js<pre><code class="language-js">import React, { useState, useEffect } from &quot;react&quot;;
import { useDispatch, useSelector } from &quot;react-redux&quot;;
import {
fetchData,
} from &quot;./redux/actions/data;
import ContentList from &quot;./components/ContentList&quot;;
</code></pre>
</li>
</ul>
<p>function App() {
  const dispatch = useDispatch();
  const dataList = useSelector((state) =&gt; state.data.dataList);
  // 생략...</p>
<p>  useEffect(() =&gt; {
    dispatch(fetchData());
  }, []);</p>
<p>  return (
    &lt;&gt;
      // 생략...
      <ContentList
        dataList={dataList}
      />
    &lt;/&gt;
  );
}</p>
<pre><code>
- dataActions.js
```js
// Action Types
export const FETCH_DATA = &quot;FETCH_DATA&quot;;
export const SET_DATA = &quot;SET_DATA&quot;;
export const API_ERROR = &quot;API_ERROR&quot;;

// Action Creators
export const fetchData = () =&gt; ({
  type: FETCH_DATA,
});

export const setData = (data) =&gt; ({
  type: SET_DATA,
  payload: data,
});

export const apiError = (error) =&gt; ({
  type: API_ERROR,
  payload: error,
});</code></pre><ul>
<li>dataReducer.js<pre><code class="language-js">import {
SET_DATA,
API_ERROR,
} from &quot;../../actions/data&quot;;
</code></pre>
</li>
</ul>
<p>const initialState = {
  dataList: [],
  error: null,
};</p>
<p>const dataReducer = (state = initialState, action) =&gt; {
  switch (action.type) {
    case SET_DATA:
      return { ...state, dataList: action.payload };
    case API_ERROR:
      return { ...state, error: action.payload };
    default:
      return state;
  }
};</p>
<p>export default dataReducer;</p>
<pre><code>
- dataSagas.js
```js
import { call, put, takeLatest } from &quot;redux-saga/effects&quot;;
import axios from &quot;axios&quot;;
import {
  FETCH_DATA,
  setData,
  apiError,
  fetchData,
} from &quot;../../actions/data&quot;;

function* fetchDataSaga() {
  try {
    const response = yield call(axios.get, &#39;fetchdata_server_url&#39;, {
      headers: {
        &quot;Content-Type&quot;: &quot;application/json&quot;,
      }
    });

    yield put(setData(response.data));
  } catch (error) {
    yield put(apiError(error));
  }
}

export default function* dataWatcher() {
  yield takeLatest(FETCH_DATA, fetchDataSaga);
}</code></pre><h1 id="마치며">마치며</h1>
<p>이로써 비동기 작업을 진행할 때 좀 더 유용하고 명확한 방식으로 상태관리를 하는법에 대해 한발짝 더 다가가게 되었다. </p>
<p>다만 모든 방법들이 그렇듯 완벽한 방법은 없고 프로젝트와 상황에 맞게 더 효율적인 방법을 끊임없이 연구 해봐야한다. 그래도 직접 상태관리를 다뤄볼 경험이 그동안은 많지 않았는데, 직접 경험해보며 점점 익숙해져 나가는 것부터 의의를 두는 중이다.</p>
<p>비동기 통신과 상태관리를 마스터하는 그날까지 포스팅을 보는 분들이 도움이 되시길 바라며...
모든 코린이 분들 화이팅! </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[CI/CD로 프로젝트 배포하기]]></title>
            <link>https://velog.io/@won_gee/CICD%EB%A1%9C-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EB%B0%B0%ED%8F%AC%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@won_gee/CICD%EB%A1%9C-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EB%B0%B0%ED%8F%AC%ED%95%98%EA%B8%B0</guid>
            <pubDate>Sat, 16 Sep 2023 06:57:48 GMT</pubDate>
            <description><![CDATA[<p>Gitlab Runner를 이용하여 프로젝트를 배포한 경험을 공유해보고자 한다.</p>
<h1 id="기술스택">기술스택</h1>
<ul>
<li>Gitlab Runner</li>
<li>Vercel</li>
</ul>
<h1 id="진행-과정">진행 과정</h1>
<h2 id="1-gitlab-runner-등록하기">1. Gitlab Runner 등록하기</h2>
<p>Gitlab Project &gt; Settings &gt; CI/CD 의 경로로 진입하여 Runner를 등록해야 한다.
나는 이미 등록되어있는 Shared Runner를 이용하여 배포를 진행했기 때문에, 이 부분은 생략 예정이다.</p>
<h2 id="2-vercel--gitlab-환경설정">2. Vercel &amp; Gitlab 환경설정</h2>
<h3 id="1-vercel-token-project-id-org-id-설정등록">1) Vercel Token, Project id, Org id 설정/등록</h3>
<p>Vercel을 배포 작업을 위해서는 Token을 인증 후, 배포를 원하는 Project의 project id/org id 연결이 필요하다.</p>
<h4 id="1-1-token-발급">1-1) Token 발급</h4>
<p>로그인 후 Settings &gt; Tokens 경로에서 토큰을 발급한다.
<img src="https://velog.velcdn.com/images/won_gee/post/6de60199-a53c-4bf3-a4be-c9a407a65a3d/image.png" alt=""></p>
<h4 id="1-2-project-org-id-확인">1-2) Project, Org ID 확인</h4>
<p>VERCEL CLI 로그인 후 vercel link 명령어를 통해 프로젝트와 연결하면 .vercel &gt; project.json에서 확인 가능하다.</p>
<ul>
<li><p>Vercel Login - Project link  
<img src="https://velog.velcdn.com/images/won_gee/post/7763518a-d351-4be2-ac82-c789ab5eacf5/image.png" alt=""></p>
</li>
<li><p>.vercel &gt; project.json</p>
<pre><code class="language-js">// 예시
{
  &quot;projectId&quot;:&quot;your project id&quot;,
    &quot;orgId&quot;: &quot;your org id&quot;
}</code></pre>
</li>
</ul>
<h3 id="2-variable-등록">2) Variable 등록</h3>
<h4 id="2-1-vercel">2-1) Vercel</h4>
<p>Project &gt; Settings &gt; Environment Variables
상기 경로로 프로젝트에 사용중인 .env나 사용하는 변수들을 등록해준다.</p>
<h4 id="2-2-gitlab">2-2) Gitlab</h4>
<p>Project &gt; Settings &gt; CI/CD &gt; Variables
상기 경로로 위에서 발급한 Vercel Token, Project id, Org id를 등록해준다.
(yaml 배포 작업 진행 시 로그인과 프로젝트를 연결하는 역할)</p>
<h3 id="3-gitlab-ciyml-작성하기">3. gitlab-ci.yml 작성하기</h3>
<p>Runner를 사용하여 진행하려는 작업은 다음과 같았다.</p>
<p>1) 브랜치(Dev / Main) 별로 Push나 Merge가 발생하면 작업이 수행되도록 한다.</p>
<p>2) Vercel로 각각 연결된 프로젝트에 배포 작업을 진행한다.</p>
<ul>
<li>Runner의 환경설정에 따라 리눅스에 맞춰 작성하였다.</li>
<li>node LTS 버젼(18.17.0)을 사용한다.</li>
<li>브랜치마다 적용되어야하는 now.json(현 vercel.json)을 적용하여 배포를 진행한다.</li>
</ul>
<pre><code class="language-yml">default:
  image: node:18.17.0

stages:
- deploy

# Vercel 배포(예: dev branch)
deploy_dev:
# 수행하는 작업이 무엇인지 입력해준다.
  stage: deploy
  # 사용하는 Gitlab Runner 이름을 입력해준다.
  tags:
    - wongee-runner
  # 본 작업을 수행하기 전, 수행해야하는 작업을 입력해준다.
  before_script:
      # nvm 설치 후 LTS 버젼 사용
    - curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.38.0/install.sh | bash
    - source ~/.nvm/nvm.sh
    - nvm install 18.17.0
    - nvm use 18.17.0
    # 제대로 설치되었는지 버젼 확인
    - node -v
    - npm -v
  # 수행해야 하는 본 작업을 입력해준다.
  script:
      # Vercel 배포를 위한 vercel 설치
    - npm install -g vercel@latest
    # 브랜치 별로 적용해야하는 now.json(vercel.json) 파일 지정 - main branch 생략 가능
    - rm -rf now.json
    - cp now.wongee.json now.json
    - rm -rf .vercel
    - mkdir -p .vercel
    # VERCEL TOKEN을 사용하여 프로젝트 빌드/배포
    - VERCEL_DEBUG=1 vercel pull --yes --environment=production --token=&quot;$VERCEL_TOKEN_DEV&quot;
    - NODE_OPTIONS=&quot;--max-old-space-size=4096&quot; vercel build --prod --token=&quot;$VERCEL_TOKEN_DEV&quot;
    - vercel deploy --prebuilt --prod --token=&quot;$VERCEL_TOKEN_DEV&quot;

# 배포가 이루어질 브랜치 지정
  only:
    - dev</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[NextJS 9 프로젝트 개발환경 구축하기(2023)]]></title>
            <link>https://velog.io/@won_gee/NextJS-9-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EA%B0%9C%EB%B0%9C%ED%99%98%EA%B2%BD-%EA%B5%AC%EC%B6%95%ED%95%98%EA%B8%B02023</link>
            <guid>https://velog.io/@won_gee/NextJS-9-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EA%B0%9C%EB%B0%9C%ED%99%98%EA%B2%BD-%EA%B5%AC%EC%B6%95%ED%95%98%EA%B8%B02023</guid>
            <pubDate>Tue, 15 Aug 2023 10:05:36 GMT</pubDate>
            <description><![CDATA[<p>회사에 입사하고 처음으로 맡은 임무는 5년전에 구축된 NextJS 프로젝트의 개발환경을 구축하는 것이었다.
아주 오래전에 만들어져서 그 이후로 유지보수가 이루어지지 않은 한마디로 죽은(?) 상태의 프로젝트였다.
5년전 환경설정에 모든것이 맞추어져 있고 그 이후로 아무도 손대지 않은 한마디로 고대 유물같은...(OMG)
당연하게도 현재 그 시절 설정 그대로 배포를 돌리면 오류가 나서 아무도 손을 못대고 있던 그런 상황이었다. ㅠ_ㅠ
혹시라도 저 같은 상황에 있는 분들이 있다면 도움이 될까 회고 겸 글을 써봅니다..</p>
<h2 id="기술-스택">기술 스택</h2>
<ul>
<li>NextJS 9</li>
<li>Node 12</li>
<li>Vercel</li>
</ul>
<h2 id="개발환경-구축">개발환경 구축</h2>
<h3 id="1-node-업데이트">1) Node 업데이트</h3>
<p>우선 해당 프로젝트에서는 node 12버전을 쓰고 있었다. 프로젝트가 돌아가게 하려면 필히 이 부분을 업데이트 할 필요가 있었다. 게다가 Vercel에서 2023년 이후부터는 node 14,16을 더이상 지원하지 않는다고 하였다. (14,16도 지원 안한다는데 12는 진즉에 에러나는게 당연한 상황이었다...) </p>
<ul>
<li>관련 글<blockquote>
<p><a href="https://vercel.com/changelog/node-js-14-and-16-are-being-deprecated">https://vercel.com/changelog/node-js-14-and-16-are-being-deprecated</a></p>
</blockquote>
</li>
</ul>
<p>따라서 23년도 현재 LTS버전인 18버전(18.17.0)을 기준으로 업데이트 하기로 하였다. nvm을 이용하여 node 18을 설치하고 적용한 뒤 충돌이 일어나는 나머지 dependency들을 손봐주었다.</p>
<h3 id="2-충돌되는-dependecies-업데이트제거">2) 충돌되는 dependecies 업데이트/제거</h3>
<ul>
<li>&quot;dependencies&quot;의 0.x 버전 캐럿 제거<blockquote>
<p><a href="https://blog.outsider.ne.kr/1041">https://blog.outsider.ne.kr/1041</a></p>
</blockquote>
</li>
<li>axios 업데이트</li>
<li>zeit/next-less 제거</li>
</ul>
<h3 id="3-node_options--openssl-legacy-provider">3) NODE_OPTIONS=--openssl-legacy-provider</h3>
<p>node의 환경변수 설정 충돌과 OpenSSL 오류를 막기 위해 package.json의 build script에 해당 옵션을 넣어주었다.</p>
<pre><code class="language-js"> &quot;scripts&quot;: {
        &quot;dev&quot;: &quot;NODE_OPTIONS=--openssl-legacy-provider next dev&quot;,
        &quot;build&quot;: &quot;NODE_OPTIONS=--openssl-legacy-provider next build&quot;,
       ...</code></pre>
<h2 id="마무리하며">마무리하며</h2>
<p>정리된 내용들을 보면 별거 아닌 것들이 많지만 아무래도 개발 1개월차(^_ㅠ) 코린이어서 그런가 삽질한 시간들이 너무 길게 느껴졌다. 토이 프로젝트를 진행할때도 Vercel을 많이 이용했는데, 아무래도 실무에서는 Gitlab을 연동해서 배포하는 것이 아니라 CLI를 통해 배포를 하다보니 이것저것 새로운 것들이 많았다.</p>
<p>다음에는 Gitlab Runner를 이용하여 CI/CD 파이프라인을 구축했던 내용을 공유해보고자 한다.
코린이 시기엔 개발환경 구축 프로세스를 A-Z까지 경험해 보는 것이 참 중요하고 소중함 경험이다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[최빈값 구하기]]></title>
            <link>https://velog.io/@won_gee/%EC%B5%9C%EB%B9%88%EA%B0%92-%EA%B5%AC%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@won_gee/%EC%B5%9C%EB%B9%88%EA%B0%92-%EA%B5%AC%ED%95%98%EA%B8%B0</guid>
            <pubDate>Thu, 20 Apr 2023 14:10:02 GMT</pubDate>
            <description><![CDATA[<h3 id="최빈값-구하기">최빈값 구하기</h3>
<h4 id="문제">문제</h4>
<p>배열 내 최빈값을 리턴해야 함. 단, 최빈값이 여러개면 -1을 리턴해야 함</p>
<ul>
<li><p>나의 풀이</p>
<pre><code class="language-js">function solution(array) {

  if (array.length === 1) {
    return array[0];
  }

    // map 형식으로 key와 빈도수를 저장
  let obj = {};
    // value 배열
  let values = [];

  for (let el of array) {
      if (obj[el]) {
          obj[el]++;
      } else {
          obj[el] = 1;
      }
  }
  // key 배열
  const keys = Object.keys(obj).map(el =&gt; parseInt(el));

  for (let i = 0; i &lt; keys.length; i++) {
      if (obj.hasOwnProperty(keys[i])) {
          values.push(obj[keys[i]]);
      }
  }

    // 최빈값 
  const max = Math.max(...values);

  let mode = [];
  for (let key in obj) {
      if (obj.hasOwnProperty(key) &amp;&amp; obj[key] === max) {
          mode.push(parseInt(key));
      }
  }

  if (mode.length &gt; 1) {
      return -1;
  } else {
      return mode[0];
  }
}</code></pre>
</li>
<li><p>다른 풀이
: 3항 연산자를 이용한 깔끔한 풀이가 인상깊다... 계속 공부하자</p>
<pre><code class="language-js">function solution(array) {
  let m = new Map();
  for (let n of array) m.set(n, (m.get(n) || 0)+1);
  m = [...m].sort((a,b)=&gt;b[1]-a[1]);
  return m.length === 1 || m[0][1] &gt; m[1][1] ? m[0][0] : -1;
}</code></pre>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[게임 맵 최단거리]]></title>
            <link>https://velog.io/@won_gee/%EA%B2%8C%EC%9E%84-%EB%A7%B5-%EC%B5%9C%EB%8B%A8%EA%B1%B0%EB%A6%AC</link>
            <guid>https://velog.io/@won_gee/%EA%B2%8C%EC%9E%84-%EB%A7%B5-%EC%B5%9C%EB%8B%A8%EA%B1%B0%EB%A6%AC</guid>
            <pubDate>Sat, 01 Apr 2023 15:22:22 GMT</pubDate>
            <description><![CDATA[<h3 id="게임-맵-최단거리">게임 맵 최단거리</h3>
<h4 id="문제">문제</h4>
<p>게임 맵의 상태 maps가 매개변수로 주어질 때, 캐릭터가 상대 팀 진영에 도착하기 위한 최단거리를 리턴해야 함. 다만 목적지에 도착이 불가능할 경우, -1을 리턴해야 함.</p>
<ul>
<li>조건
```</li>
<li>maps는 n x m 크기의 게임 맵의 상태가 들어있는 2차원 배열로, n과 m은 각각 1 이상 100 이하의 자연수입니다.</li>
<li>n과 m은 서로 같을 수도, 다를 수도 있지만, n과 m이 모두 1인 경우는 입력으로 주어지지 않습니다.</li>
<li>maps는 0과 1로만 이루어져 있으며, 0은 벽이 있는 자리, 1은 벽이 없는 자리를 나타냅니다.</li>
<li>처음에 캐릭터는 게임 맵의 좌측 상단인 (1, 1) 위치에 있으며, 상대방 진영은 게임 맵의 우측 하단인 (n, m) 위치에 있습니다.<pre><code></code></pre></li>
</ul>
<h4 id="문제의-핵심">문제의 핵심</h4>
<ul>
<li><strong>BFS(Breadth-First Search)</strong>
너비 우선 탐색을 통해 노드에서 인접한 노드를 먼저 탐색하여 최단거리를 알아 낼 수 있다!</li>
</ul>
<p>예시) map = [[1,0,1,1,1],[1,0,1,0,1],[1,0,1,1,1],[1,1,1,0,1],[0,0,0,0,1]]<br><img src="https://velog.velcdn.com/images/won_gee/post/3f710227-e61d-4576-84d2-979b12d81d40/image.png" alt=""></p>
<pre><code class="language-js">function solution(maps) {

    // maps 구조 = [Y좌표][X좌표]
    const yLen = maps.length;
    const xLen = maps[0].length;

    // 목적지 좌표 설정
    const destY = yLen - 1;
    const destX = xLen - 1;

    // 한 칸씩 이동할 수 있는 X, Y 배열 셋팅
    const mY = [0, 0, 1, -1];
    const mX = [-1, 1, 0, 0];

    // 현재 위치(Y, X) &amp; 이동거리를 저장할 수 있는 queue 셋팅
    let queue = [[0, 0, 1]];

    while(queue.length) {

        // 현재 위치(Y, X) &amp; 이동거리
        let [curY, curX, move] = queue.shift();

        // 현재 위치가 목적지와 같을 때 이동거리 출력
        if(curY === destY &amp;&amp; curX === destX) return move;

        // mY, mX 순환
        for(let i = 0; i &lt; 4; i++){

            // 현재 방문 중인 위치(Y,X)
            let visitedY = curY + mY[i];
            let visitedX = curX + mX[i];

            // 방문 위치가 좌표 안에 있는지 &amp;&amp; 위치가 갈 수 있는 길인지
            if(visitedY &gt;= 0 &amp;&amp; visitedY &lt; yLen &amp;&amp; visitedX &gt;= 0 &amp;&amp; visitedX &lt; xLen &amp;&amp; maps[visitedY][visitedX] === 1) {
                queue.push([visitedY, visitedX, move + 1]);
                // 방문 처리
                maps[visitedY][visitedX] = 0;
            }
        }
    }
    return -1;
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[피로도]]></title>
            <link>https://velog.io/@won_gee/%ED%94%BC%EB%A1%9C%EB%8F%84</link>
            <guid>https://velog.io/@won_gee/%ED%94%BC%EB%A1%9C%EB%8F%84</guid>
            <pubDate>Tue, 28 Mar 2023 14:53:03 GMT</pubDate>
            <description><![CDATA[<h3 id="피로도">피로도</h3>
<h4 id="문제">문제</h4>
<p>유저의 현재 피로도 k와 각 던전별 &quot;최소 필요 피로도&quot;, &quot;소모 피로도&quot;가 담긴 2차원 배열 dungeons가 매개변수로 주어질 때, 유저가 탐험할수 있는 최대 던전 수를 리턴해야 함 </p>
<h4 id="문제의-핵심">문제의 핵심</h4>
<p>1) DFS를 통해 모든 경로를 탐색한 후, 그에 따른 탐험 가능한 던전 수를 count해야 함.
2) 모든 count에서 최대값을 리턴한다.</p>
<p>예시) k = 80, dungeons = [[80, 20], [50, 40], [30, 10]]
<img src="https://velog.velcdn.com/images/won_gee/post/f6936f85-6143-45b7-a5bb-f5a9ad8ccf76/image.png" alt=""></p>
<pre><code class="language-js">function solution(k, dungeons) {

    let answer = [];
    let visited = Array(dungeons.length).fill(false);

    function dfs(count, k) {

        // answer에 count 넣어주기
        answer.push(count);

        for (let i = 0; i &lt; dungeons.length; i++) {

            // 비교 대상인 던전에 대한 i번째 배열 설정하기
            let current = dungeons[i];

            // 체력 &gt;= 최소 필요 피로도 이고 i번째 노드가 방문하지 않은 상태라면 실행하기
            if (k &gt;= current[0] &amp;&amp; !visited[i]) {

                // 방문 등록처리 해주기
                visited[i] = 1;

                // count에 1을 더해주고, 체력-소모피로도를 dfs에 넣어 실행하기
                dfs(count + 1, k - current[1]);

                visited[i] = 0;
            }
        }
    }

  dfs(0, k);

  return Math.max(...answer);
}</code></pre>
<h4 id="생각해-볼-문제">생각해 볼 문제</h4>
<ul>
<li>순열과 DFS에 대해 더 자세하게 공부해 볼 필요가 있음.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[카펫]]></title>
            <link>https://velog.io/@won_gee/%EC%B9%B4%ED%8E%AB</link>
            <guid>https://velog.io/@won_gee/%EC%B9%B4%ED%8E%AB</guid>
            <pubDate>Mon, 27 Mar 2023 03:27:56 GMT</pubDate>
            <description><![CDATA[<h3 id="카펫">카펫</h3>
<h4 id="문제">문제</h4>
<p>다음과 같이 카펫의 노란색, 갈색 격자의 갯수가 주어졌을 때 가로와 세로의 길이를 리턴해야 함.</p>
<ul>
<li>조건
```</li>
<li>중앙에는 노란색으로 칠해져 있고 테두리 1줄은 갈색으로 칠해져 있는 격자 모양 카펫</li>
<li>갈색 격자의 수 brown은 8 이상 5,000 이하인 자연수입니다.</li>
<li>노란색 격자의 수 yellow는 1 이상 2,000,000 이하인 자연수입니다.</li>
<li>카펫의 가로 길이는 세로 길이와 같거나, 세로 길이보다 깁니다.<pre><code>![](https://velog.velcdn.com/images/won_gee/post/89127fd7-378f-4578-a773-dafc685578e9/image.png)
</code></pre></li>
</ul>
<h4 id="문제의-핵심">문제의 핵심</h4>
<ul>
<li>나의 풀이
1) 노란 격자의 수 = (가로 - 2) * (세로 - 2)
2) 세로의 최솟값 = 3</li>
</ul>
<pre><code class="language-js">function solution(brown, yellow) {

    let height = 0;
    let width = 0;

    for(height = 3; height &lt;= (brown + yellow)/height; height++){
        width = Math.floor((brown + yellow)/height);
        if(yellow === (width - 2)*(height - 2)){
            break;
        }
    }
    return [width, height];
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[소수 찾기]]></title>
            <link>https://velog.io/@won_gee/%EC%86%8C%EC%88%98-%EC%B0%BE%EA%B8%B0</link>
            <guid>https://velog.io/@won_gee/%EC%86%8C%EC%88%98-%EC%B0%BE%EA%B8%B0</guid>
            <pubDate>Tue, 21 Mar 2023 10:21:03 GMT</pubDate>
            <description><![CDATA[<h3 id="소수-찾기">소수 찾기</h3>
<h4 id="문제">문제</h4>
<p>숫자로 이루어진 문자열 numbers가 주어졌을 때 (ex. &#39;17&#39;) numbers에 해당하는 숫자들의 조합으로 만들 수 있는 숫자 중 소수의 갯수를 리턴해야 함 (ex.7, 17, 71)</p>
<h4 id="문제의-핵심">문제의 핵심</h4>
<p>1) 숫자들의 조합을 만들어 리턴하는 함수 생성(<strong>getPermutations</strong>)
: 숫자를 조합할 때 순서도 영향을 미치기 때문에 <strong>순열 함수</strong>를 만든다 (ex. 17, 71은 다른 숫자임)</p>
<p>2) 소수를 판별하는 함수 생성(<strong>isPrime</strong>)</p>
<ul>
<li><p>나의 풀이</p>
<pre><code class="language-js">function solution(numbers) {

    // numbers를 한자릿 수로 분리
  const numbersArr = numbers.split(&#39;&#39;);
    // 1가지를 조합하여 만들 수 있는 경우의 수를 미리 넣어둠
  let primesArr = [...numbersArr];
    // 만들 수 있는 수들의 조합을 넣는 배열 선언
  let combiNums = [];
    // 조합의 갯수를 count할 answer변수 선언
  let answer = 0;

    // numbersArr와 요소를 선택할 갯수인 selectNumber를 인자로 받아 순열을 리턴하는 함수
  const getPermutations = function(arr, selectNumber){
      const result = [];
      if(selectNumber === 1) return arr.map((el) =&gt; el);

      arr.forEach((fixed, index, origin) =&gt; {
          const rest = [...origin.slice(0, index), ...origin.slice(index + 1)];
          const permutations = getPermutations(rest, selectNumber - 1);
          const attached = permutations.map((el) =&gt; fixed + el);
          result.push(...attached);
      })
      return result;
  }

  // 소수판별 함수
  const isPrime = function(num){
    // num === 0,1인 경우 예외 처리
      if(num &lt;= 1){
      return false;
  }
  // num의 제곱근까지 반복문을 돌림으로써 코드 효율성 개선  
  for(let j = 2; j &lt;= Math.sqrt(num); j++){
      if(num % j === 0){
          return false;
      }
  }
  return true;
  }

  // 만들 수 있는 모든 순열의 갯수를 구하기 위해 반복문을 돌며 getPermutations 실행하여 primesArr에 넣음
  for(let i = 2; i &lt;= numbersArr.length; i++){
      combiNums = getPermutations(numbersArr, i);
      primesArr.push(...combiNums);
  }

    // primesArr 요소 숫자로 변횐
  primesArr = primesArr.map((el) =&gt; parseInt(el));
    // Set를 이용한 중복 숫자 제거
  primesArr = [...new Set(primesArr)];

    // primesArr 요소들이 소수인지 판별하여 answer 카운트
  for(el of primesArr){
      if(isPrime(el)){
          answer++;
      }
  }
  return answer;
}</code></pre>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[모의고사]]></title>
            <link>https://velog.io/@won_gee/%EB%AA%A8%EC%9D%98%EA%B3%A0%EC%82%AC</link>
            <guid>https://velog.io/@won_gee/%EB%AA%A8%EC%9D%98%EA%B3%A0%EC%82%AC</guid>
            <pubDate>Sun, 19 Mar 2023 05:31:07 GMT</pubDate>
            <description><![CDATA[<h3 id="모의고사">모의고사</h3>
<h4 id="문제">문제</h4>
<p>학생 1,2,3이 문제를 찍는 방식이 아래와 같이 주어지고 정답 배열 answers가 주어졌을 때 가장 많이 정답을 맞춘 학생을 리턴해야 함.</p>
<pre><code>1번 수포자가 찍는 방식: 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, ...
2번 수포자가 찍는 방식: 2, 1, 2, 3, 2, 4, 2, 5, 2, 1, 2, 3, 2, 4, 2, 5, ...
3번 수포자가 찍는 방식: 3, 3, 1, 1, 2, 2, 4, 4, 5, 5, 3, 3, 1, 1, 2, 2, 4, 4, 5, 5, ...</code></pre><h4 id="문제의-핵심">문제의 핵심</h4>
<p>1) 학생마다 반복되는 기본패턴을 배열에 넣는다
2) 반복되는 패턴이 종료되면 나머지 연산자(%)를 통해 처음으로 돌아갈 수 있도록 함</p>
<ul>
<li><p>나의 풀이</p>
<pre><code class="language-js">function solution(answers) {
  let arr1 = [1,2,3,4,5];
  let arr2 = [2,1,2,3,2,4,2,5];
  let arr3 = [3,3,1,1,2,2,4,4,5,5];
  let result = [0,0,0];
  let answer = [];

  for(let i = 0; i &lt; answers.length; i++){
      if(answers[i] === arr1[i % arr1.length]){
          result[0]++
      }
      if(answers[i] === arr2[i % arr2.length]){
          result[1]++
      }
      if(answers[i] === arr3[i % arr3.length]){
          result[2]++
      }
  }

  const max = Math.max(...result);
  for(let k = 0; k &lt; result.length; k++){
      if(result[k] === max){
          answer.push(k+1);
      }
  }
  return answer;
}</code></pre>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Sorting Bars 프로젝트 회고]]></title>
            <link>https://velog.io/@won_gee/SortingBars</link>
            <guid>https://velog.io/@won_gee/SortingBars</guid>
            <pubDate>Sun, 12 Mar 2023 03:58:15 GMT</pubDate>
            <description><![CDATA[<blockquote>
<h1 id="1-프로젝트-시작-계기">1. 프로젝트 시작 계기</h1>
</blockquote>
<p>부트캠프가 끝나고.. 알고리즘 공부를 열심히 하던 중 유튜브에서 정렬 알고리즘에 대한 프로젝트를 접하게 되었다. </p>
<p><strong>출처</strong>: <a href="https://www.youtube.com/watch?v=pFXYym4Wbkc&amp;feature=share">https://www.youtube.com/watch?v=pFXYym4Wbkc&amp;feature=share</a></p>
<p>특히 부트캠프에서 진행했던 프로젝트에서는 다뤄보지 못했던 상태관리 라이브러리도 다뤄보고 렌더링에 대한 공부도 다시 할 겸, &#39;Sorting Bars&#39;라는 프로젝트를 진행하게 되었다.</p>
<p>진행했던 프로젝트 내용에 대한 전반적인 설명은 아래 Github에서 확인 가능하다.</p>
<p><strong>Github</strong> : <a href="https://github.com/wongee93/sorting_bars">https://github.com/wongee93/sorting_bars</a></p>
<blockquote>
<h1 id="2-프로젝트를-진행하며">2. 프로젝트를 진행하며</h1>
</blockquote>
<h2 id="1-사용한-기술-스택">1) 사용한 기술 스택</h2>
<h3 id="redux-toolkit">redux-toolkit</h3>
<p>app.js의 구조는 정렬 알고리즘을 실행하는 버튼 컴포넌트와 바차트 컴포넌트로 구성하였기 때문에 20개의 랜덤한 높이의 bar들로 이루어진 배열을 다루기 위해서는 앞서 얘기했듯이 전역에서 상태를 관리할 필요가 있었다. redux-toolkit을 이용하여 상태를 관리해 주기로 했다.</p>
<h2 id="2-구현-기능">2) 구현 기능</h2>
<h3 id="reset">Reset</h3>
<p>바차트를 생성하기 위해 랜덤으로 중복되지 않는 20개의 숫자들을 랜덤하게 생성해내는 함수를 작성하였다. </p>
<h3 id="sort">Sort</h3>
<p><strong>사용한 정렬 알고리즘</strong></p>
<ul>
<li><p>Bubble Sort
: 인접한 두 요소를 비교하여 정렬하는 방법. 배열 전체를 순회하며 비교하기 때문에 시간복잡도는 O(n²)이며 배열 하나만 사용하기 때문에 공간복잡도는 O(n)이다.</p>
</li>
<li><p>Merge Sort
: 배열을 2등분하여 정렬한 후, 병합하여 다시 정렬하는 방법. 시간복잡도는 O(nlogn)이며 공간복잡도는 O(n)이다.</p>
</li>
</ul>
<h2 id="3-문제점">3) 문제점</h2>
<p>정렬이 진행되는 동안의 과정을 화면에 모두 렌더링하기 위해 어떻게 하면 좋을까 생각하며 많이 삽질(?)했었다. 처음에 랜덤 배열을 생성하고 정렬 로직을 적용했더니 정렬 후의 결과만 화면에 출력되어서 이를 위해선 어떻게 해야하나 고민하게 되었다. </p>
<h2 id="4-해결-방안">4) 해결 방안</h2>
<p>화면에 정렬 과정을 모두 출력하기 위해서는 각 Bar들의 상태를 기록할 필요가 있었다. 따라서 stateQueue 배열을 선언하여 그 안에 Bar의 상태를 기록하는 operation 객체를 넣었다. </p>
<p>operation 객체 안에는 1) 선택된 요소(selectedIdx) 2) 비교되는 요소(compareIdx) 3) 교체되는 요소(swapIdx) 4) 기존 요소(defaultIdx)로 상태를 기록하였다.</p>
<ul>
<li><p>bubbleSort 예시</p>
<pre><code class="language-js">const bubbleSort = (randomArray) =&gt; {
  const array = [...randomArray];
  const stateQueue = [];

  for (let i = 0; i &lt; array.length; i++) {
      for (let j = 0; j &lt; array.length - (i + 1); j++) {
          // 선택되는 index
          let operations = { selectedIdx: j };
          stateQueue.push(operations);

          // 비교하는 두 index 중, 이전 index 값이 더 클때(swap)
          if (array[j].value &gt; array[j + 1].value) {
              operations = { selectedIdx: j, compareIdx: j + 1 };
              stateQueue.push(operations);
              operations = { selectedIdx: j, swapIdx: j + 1 };
              stateQueue.push(operations);

              let temp = array[j];
              array[j] = array[j + 1];
              array[j + 1] = temp;
          }
          // 모든 비교를 마쳤을 때
          if (j === array.length - (i + 2)) {
              operations = { selectedIdx: j + 1, defaultIdx: j };
              stateQueue.push(operations);
          } else {
              operations = { defaultIdx: j };
              stateQueue.push(operations);
          }
      }
  }
  stateQueue.push({ selectedIdx: 0 });
  return stateQueue;
};</code></pre>
</li>
</ul>
<p>이처럼 stateQueue에 Bar들의 상태를 담아준 후 setTimeout을 이용하여 각 상태(selectedIdx, compareIdx, swapIdx, defaultIdx)에 따른 색상코드를 달리 주어 화면에 표시하도록 하였다.</p>
<blockquote>
<h1 id="3-느낀점">3. 느낀점</h1>
</blockquote>
<p>리덕스를 이용해서 프로젝트를 해본적은 처음이었는데, 확실히 리덕스를 왜 쓰는지 체감되었던 것 같다. 컴포넌트를 단 3개만 쓰는 프로젝트였음에도 불구하고 리덕스를 쓰지 않았더라면 어떻게 구현해야할지 생각만으로도 막막하다..</p>
<p>그리고 이번 프로젝트를 진행하면서 렌더링에 대한 이해도 높일 수 있었다고 생각한다. 단순히 알고리즘 뿐 아니라 브라우저 구동 원리라던가 전반적인 웹 구동 과정에 대해서도 꾸준히 공부할 필요가 있음을 느끼게 되는 프로젝트였다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[프린터]]></title>
            <link>https://velog.io/@won_gee/%ED%94%84%EB%A6%B0%ED%84%B0</link>
            <guid>https://velog.io/@won_gee/%ED%94%84%EB%A6%B0%ED%84%B0</guid>
            <pubDate>Wed, 08 Mar 2023 09:34:26 GMT</pubDate>
            <description><![CDATA[<h3 id="프린터">프린터</h3>
<h4 id="문제">문제</h4>
<p>프린터의 작업순서 priorities와 출력하고 싶은 작업물의 location을 받아 location에 해당하는 작업물이 아래 규칙에 따랐을 때, 몇 번째로 출력되는지 리턴해야 함.</p>
<pre><code>1. 인쇄 대기목록의 가장 앞에 있는 문서(J)를 대기목록에서 꺼냅니다.
2. 나머지 인쇄 대기목록에서 J보다 중요도가 높은 문서가 한 개라도 존재하면 J를 대기목록의 가장 마지막에 넣습니다.
3. 그렇지 않으면 J를 인쇄합니다.</code></pre><h4 id="문제의-핵심">문제의 핵심</h4>
<p>** * queue 활용**</p>
<p>1) priorities에서 가장 큰 요소가 배열의 맨 앞에 오도록 배치 함
2) 그 상태에서의 location을 기록해 둠
3) 이후 priorities를 queue의 형식으로 앞 요소부터 빼주고(shift()), rank를 +1, location을 -1 해주며 작업을 진행함
4) location &lt; 0 이 되면 rank를 리턴함</p>
<pre><code class="language-js">function solution(priorities, location) {
    let rank = 1;
    while(priorities.length){
        if(priorities[0] &lt; Math.max(...priorities)){
            if(--location &lt; 0){
                location = priorities.length - 1;    
            }
            priorities.push(priorities.shift());
        } else {
            if(--location &lt; 0){
                return rank;
            }
            priorities.shift();
            rank++;
        }
    }
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[올바른 괄호]]></title>
            <link>https://velog.io/@won_gee/%EC%98%AC%EB%B0%94%EB%A5%B8-%EA%B4%84%ED%98%B8</link>
            <guid>https://velog.io/@won_gee/%EC%98%AC%EB%B0%94%EB%A5%B8-%EA%B4%84%ED%98%B8</guid>
            <pubDate>Wed, 08 Mar 2023 06:14:36 GMT</pubDate>
            <description><![CDATA[<h3 id="올바른-괄호">올바른 괄호</h3>
<h4 id="문제">문제</h4>
<p>문자열 s가 올바른 괄호로 이루어져 있는지 판단하여 true/false 리턴해야 함</p>
<h4 id="문제의-핵심">문제의 핵심</h4>
<ul>
<li>나의 풀이</li>
<li><em>stack 활용*</em>
1) 반복문으로 s를 돌면서 s[i] 값이 &#39;(&#39;라면 stack에 push 하기
2) s[i]값이 &#39;)&#39;라면 bracket으로 stack.pop()과 짝이 맞는지 확인하여 pop으로 stack 요소 빼내기
3) stack.length가 0 이고 left와 right값이 같은지 확인하여 값 리턴하기</li>
</ul>
<pre><code class="language-js">function solution(s){
    let stack = [];
    let left = 0;
    let right = 0;

    let bracket = (right) =&gt; {
        if(right === &#39;)&#39;){
            return &#39;(&#39;;
        }
    }

    if(s[0] === &#39;)&#39;){
        return false;
    }

    for(let i = 0; i &lt; s.length; i++){
        if(s[i] === &#39;(&#39;){
            stack.push(s[i]);
            left++;
        } else if(stack.pop() === bracket(s[i])){
            right++;
        }
    }

    if(stack.length === 0 &amp;&amp; left === right){
        return true;
    } else {
        return false;
    }
}</code></pre>
<ul>
<li>다른 풀이 방법
1) 모든 값을 더한 상태값인 cum 선언하기
2) &#39;(&#39; 값을 +1, &#39;)&#39; 값을 -1 로 치환하기
3) &#39;)&#39; 갯수가 &#39;(&#39; 보다 많을 시 바로 false 리턴하기
4) cum이 0 인지 판단하여 값 리턴하기<pre><code class="language-js">function solution(s){
  let cum = 0
  for (let paren of s) {
      cum += paren === &#39;(&#39;? 1: -1
      if(cum &lt; 0) {
          return false
      }
  }
  return cum === 0? true: false;
}</code></pre>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Generate Parentheses]]></title>
            <link>https://velog.io/@won_gee/Generate-Parentheses</link>
            <guid>https://velog.io/@won_gee/Generate-Parentheses</guid>
            <pubDate>Thu, 02 Mar 2023 12:41:28 GMT</pubDate>
            <description><![CDATA[<h3 id="generate-parentheses">Generate Parentheses</h3>
<h4 id="문제">문제</h4>
<p>주어지는 n쌍 만큼의 유효한 괄호쌍 &#39;()&#39; 에 대한 경우의 수를 모두 담은 배열을 리턴해야 함</p>
<h4 id="문제의-핵심">문제의 핵심</h4>
<ul>
<li>DFS(Depth For Search)를 활용해야 함</li>
</ul>
<pre><code class="language-js">var generateParenthesis = function(n) {
    let answer = [];

    function DFS(str, left, right){
        if(str.length === 2*n){
            answer.push(str);
        } else {
            if(left &lt; n){
                DFS(str + &#39;(&#39;, left+1, right);
            }
            if(left &gt; right){
                DFS(str + &#39;)&#39;, left, right+1);
            }
        }
    }

    DFS(&#39;&#39;,0,0);

    return answer;
};</code></pre>
<ul>
<li>이해를 위한 DFS 알고리즘 도식
<img src="https://velog.velcdn.com/images/won_gee/post/fc0771be-9eaa-430d-b33a-fdecbf82a341/image.png" alt=""></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Valid Parentheses]]></title>
            <link>https://velog.io/@won_gee/Valid-Parentheses</link>
            <guid>https://velog.io/@won_gee/Valid-Parentheses</guid>
            <pubDate>Thu, 02 Mar 2023 05:17:22 GMT</pubDate>
            <description><![CDATA[<h3 id="valid-parentheses">Valid Parentheses</h3>
<h4 id="문제">문제</h4>
<p>주어지는 문자열 s의 괄호가 올바르게 닫혔는지 판별하여 true/false를 리턴해야 함</p>
<h4 id="문제의-핵심">문제의 핵심</h4>
<ul>
<li>stack을 활용하여 괄호의 짝이 맞는지 확인하면서 그 외 예외처리를 해주어야 함
1) 열린 괄호로 시작하며 s.length가 홀수가 아닌지
2) 열린 괄호와 닫힌 괄호의 갯수가 일치하는지</li>
</ul>
<pre><code class="language-js">var isValid = function(s) {
    let stack = [];
    let openCount = 0;
    let closedCount = 0;

    const bracketMap = (open) =&gt; {
        if(open === &#39;(&#39;){
            return &#39;)&#39;;
        } 
        else if(open === &#39;{&#39;){
            return &#39;}&#39;;
        } 
        else {
            return &#39;]&#39;;
        }
    }

    if(s[0] === &#39;)&#39; || s[0] === &#39;}&#39; || s[0] === &#39;]&#39; || s.length % 2 === 1){
        return false;
    }

    for(let i = 0; i &lt; s.length; i++){
        if(s[i] === &#39;(&#39; || s[i] === &#39;{&#39; || s[i] === &#39;[&#39;){
            stack.push(s[i]);
            openCount++;
        } 
        else {
            if(bracketMap(stack.pop()) === s[i]){
                closedCount++;
                continue;
            }
            return false;
        }
    }
    if(openCount === closedCount){
        return true
    }
    return false
};</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[실행 컨텍스트]]></title>
            <link>https://velog.io/@won_gee/%EC%8B%A4%ED%96%89-%EC%BB%A8%ED%85%8D%EC%8A%A4%ED%8A%B8</link>
            <guid>https://velog.io/@won_gee/%EC%8B%A4%ED%96%89-%EC%BB%A8%ED%85%8D%EC%8A%A4%ED%8A%B8</guid>
            <pubDate>Wed, 11 Jan 2023 14:41:50 GMT</pubDate>
            <description><![CDATA[<h3 id="단계">단계</h3>
<p>** 1) Pharsing**
: 실행할 Context에 대해 분석하는 단계</p>
<p>** 2) Execution** 
: 순차적으로 Context를 실행하는 단계</p>
<hr>
<h3 id="실행-순서">실행 순서</h3>
<ul>
<li><p>Global object를 생성한다. 
window : global object</p>
</li>
<li><p>&#39;this&#39;를 생성한다
this : window</p>
</li>
<li><p>변수와 함수를 할당할 메모리 공간을 만든다.</p>
</li>
<li><p><strong>Hoisting</strong> 
메모리에 함수선언을 할당하는 동안 변수를 초기화해준다. (기본값인 &#39;undefined&#39;로 설정)</p>
</li>
<li><p>함수가 실행되면, 함수 Context에서 동일한 절차를 진행한다.
전역 Context와 다른 점은 함수에 대한 argument(인수)가 별도로 등록된다.</p>
</li>
</ul>
<hr>
<h3 id="콜스택">콜스택</h3>
<p>실행 컨텍스트의 실행 순서를 관리하는 개념</p>
<p>전역 실행 컨텍스트 &gt; 전역실행 컨텍스트 + 함수실행 컨텍스트 &gt; 전역실행 컨텍스트</p>
<ul>
<li>3단계는 함수 컨텍스트가 실행된 뒤 전역 코드로 다시 돌아오는 것을 의미한다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Valid Anagram]]></title>
            <link>https://velog.io/@won_gee/Valid-Anagram</link>
            <guid>https://velog.io/@won_gee/Valid-Anagram</guid>
            <pubDate>Wed, 21 Dec 2022 06:55:29 GMT</pubDate>
            <description><![CDATA[<h3 id="valid-anagram">Valid Anagram</h3>
<h4 id="문제">문제</h4>
<p>주어지는 문자열 s,t를 받아 둘의 관계가 Anagram이면 true를 아니라면 false를 리턴해야 함</p>
<p><strong>Anagram이란?</strong>
단어나 문장을 구성하고 있는 문자의 순서를 바꾸어 다른 단어나 문장을 만드는 것</p>
<h4 id="문제의-핵심">문제의 핵심</h4>
<ul>
<li><p>중복 찾기 문제와 마찬가지로 sort()를 이용하여 오름차순으로 문자열을 재정렬하여 두개의 값이 같은지 아닌지를 비교하였음</p>
<pre><code class="language-js">var isAnagram = function(s, t) {
  let sWord = s.split(&#39;&#39;).sort().join(&#39;&#39;);
  let tWord = t.split(&#39;&#39;).sort().join(&#39;&#39;);

  if(sWord === tWord){
      return true;
  }
  return false;
};</code></pre>
</li>
</ul>
<h4 id="결과">결과</h4>
<p><img src="https://velog.velcdn.com/images/won_gee/post/11023137-246c-4a5d-999f-8ed0cf0e90e0/image.png" alt=""></p>
]]></description>
        </item>
    </channel>
</rss>