<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>jw_99.log</title>
        <link>https://velog.io/</link>
        <description>꾸준함에 도전하는 중</description>
        <lastBuildDate>Sat, 29 Nov 2025 06:05:35 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>jw_99.log</title>
            <url>https://velog.velcdn.com/images/jw_99/profile/e15ae134-3f67-433d-a4ac-ce99875df032/social_profile.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. jw_99.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/jw_99" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[토스 모의고사 후기 (feat. Frontend Fundamentals)]]></title>
            <link>https://velog.io/@jw_99/%ED%86%A0%EC%8A%A4-%EB%AA%A8%EC%9D%98%EA%B3%A0%EC%82%AC-%ED%9B%84%EA%B8%B0-feat.-Frontend-Fundamentals</link>
            <guid>https://velog.io/@jw_99/%ED%86%A0%EC%8A%A4-%EB%AA%A8%EC%9D%98%EA%B3%A0%EC%82%AC-%ED%9B%84%EA%B8%B0-feat.-Frontend-Fundamentals</guid>
            <pubDate>Sat, 29 Nov 2025 06:05:35 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/jw_99/post/12cd44d5-f4ed-4726-9773-cd2d138499bd/image.png" alt=""></p>
<h1 id="행사-프로세스">행사 프로세스</h1>
<pre><code class="language-js">1. Frontend Fundamentals 디스코드 채널 입장 (선착순 마감)
2. 실제 토스에서 진행했던 과제를 직접 풀고 Pull Request로 과제 제출
3. 풀어본 과제를 포함한 다양한 주제에 대해 github Discussion 공간을 활용하여 토론 진행
4. 유튜브 라이브에서 라이브 코딩을 통하여 토스의 과제 출제의도 설명 및 질의응답</code></pre>
<h1 id="참여하게-된-계기">참여하게 된 계기</h1>
<p>회사에 다니면서 프론트엔드 코드를 작성하는 게 일상이 되었지만 항상 코드에 바람이 솔솔 통하는 허전한 구멍이 있다는 느낌을 버릴 수 없었다. 코드에는 정답이 없다는 핑계? 아닌 핑계로 그 구멍을 채워 왔지만 결국은 더 큰 구멍으로 되돌아왔다. </p>
<p>우연히 토스에서 실제 채용에 사용되었던 과제를 모의고사 형식으로 풀어보며 <strong>그들이 코드를 대하는 방식</strong>에 대해 공유하고 더 나아가 <strong>토스 개발자?</strong>로 일하고 싶은 사람들에게 과제 전형에 어떻게 대처해야 하는지에 대한 가이드라인을 제공하는 행사를 알게 되었고 구멍을 메울 수 있을 것 같다는 생각에 참여하기로 결심했다.</p>
<h1 id="과제-풀이">과제 풀이</h1>
<pre><code class="language-js">주제: 적금 계산기 (적금 상품 추천)
제한시간: 2시간
구현 포인트: 추상화와 확장성 있는 구현</code></pre>
<p>처음 과제 노션 페이지를 열었을 때 시험이라는 것을 볼 때 어김없이 느껴지는 <strong>새로운 것에 대한 어색함?</strong>이 내 생각회로를 가로막기 시작했다.</p>
<p>글이 잘 읽히지 않자 곧바로 코드를 보기 위해 개발서버를 띄우고 localhost에 접속해 1번부터 풀기 시작했다. 회사에서 작성하는 익숙한 구조로 코드를 나누고 유틸함수 구현에는 AI(코파일럿)을 적극 활용했다.</p>
<p>제한시간 안에 모든 내용을 구현하지 못했지만 현재 나의 실력과 코딩 스타일을 재확인 해볼 수 있는 시간이었다. </p>
<p><img src="https://velog.velcdn.com/images/jw_99/post/b495eded-0d83-4d0e-9124-ce9e5c8d7d4d/image.png" alt=""></p>
<h1 id="토론의-시간">토론의 시간</h1>
<p>사실 가장 기대한 시간 중 하나였다. github Discussions에서 여러 주제로 토론이 이어졌고 좋은 코드에 대해 진심인 분들이 많다는 것을 느꼈다. 정말 좋은 주제들이 많이 올라왔고 각자 자신의 생각을 자유롭게 공유해주셨다. 특히, 토스측 관계자분들의 인사이트 꽉찬 댓글들이 인상 깊었다.</p>
<h1 id="라이브-코딩">라이브 코딩</h1>
<p>토스측 관계자분들이 과제 응시생의 입장에서 직접 과제를 풀어보며 출제의도를 설명하고 중간중간 댓글로 올라오는 질문에 답변해주시는 시간이었다. 이번 행사의 꽃이라고 생각이 들어 말 하나하나 놓치지 않으려고 정말 집중해서 들었던 기억이 난다.</p>
<h1 id="내게-남은-것">내게 남은 것</h1>
<ol>
<li><strong>네트워킹 공간</strong>: 좋은 코드에 관심 있는 사람들의 모임이 생긴 느낌이라 좋았다.</li>
<li><strong>추상화와 확장성에 관한 인사이트</strong>: 기본과 본질에 대해 항상 생각해야 한다는 생각이 들었다.</li>
<li><strong>리팩토링이 필요한 코드</strong>: 눈으로 보기만 해서 모든 게 내 것이 되었다는 착각을 해서는 안된다. 행사를 통해 얻은 인사이트를 바탕으로 코드를 개선해 나아갈 필요가 있다.</li>
</ol>
<h1 id="기억에-남는-말">기억에 남는 말</h1>
<ol>
<li>옵셔널과 null은 전염된다.</li>
<li>input은 input답게.</li>
<li>비즈니스 로직은 내가 바꾸면 큰 일 나는거.</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[크리에이티브 코딩 밋업 (feat. Generator)]]></title>
            <link>https://velog.io/@jw_99/%ED%81%AC%EB%A6%AC%EC%97%90%EC%9D%B4%ED%8B%B0%EB%B8%8C-%EC%BD%94%EB%94%A9-%EB%B0%8B%EC%97%85-feat.-Generator</link>
            <guid>https://velog.io/@jw_99/%ED%81%AC%EB%A6%AC%EC%97%90%EC%9D%B4%ED%8B%B0%EB%B8%8C-%EC%BD%94%EB%94%A9-%EB%B0%8B%EC%97%85-feat.-Generator</guid>
            <pubDate>Sat, 08 Nov 2025 10:01:55 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/jw_99/post/0aca8f69-fa6e-4452-9fa3-5a74ae471c38/image.png" alt=""></p>
<blockquote>
<p>UX 엔지니어를 위한 첫 발걸음</p>
</blockquote>
<p>요즘 회사가 많이 바빠서 주말 출근길, 2호선 지하철이 양화대교 근처를 지날 즈음 우연히 인스타를 보다가 재미있는 작업 영상이 눈에 들어왔다.</p>
<p>크리에이티브, 인터랙티브를 항상 마음에만 품고 정확한 뜻이 뭔지도 모르는 그 어중간한 상태에서 그 영상을 봤는데, 아! 이게 진정한 크리에이티브이고 인터랙티브한 무언가가 아닐까하는 생각에 크리에이티브 코더인 &quot;정효&quot;님의 밋업 행사 참여 신청을 곧바로 넣었다.<img src="https://velog.velcdn.com/images/jw_99/post/96568d14-2d83-4244-9dc8-961744d03e2b/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/jw_99/post/624dc6be-da14-43ca-aca3-66fc0cfe2ad1/image.png" alt=""></p>
<blockquote>
<p>회사 업무로 늦참 문의드린 메일...! 따뜻하신 &quot;정효&quot;님 감사합니다!</p>
</blockquote>
<p>처음 참여해보는 네트워킹 행사였고 과연 내가 기대하는 만큼 의미있는 시간일까에 대한 고민도 있었던건 사실이다. </p>
<p><strong>결론부터 말하자면, 좋았다..!</strong></p>
<p>처음 밋업 장소에 도착하여 흐르는 땀을 닦고 (더 늦을까봐 뛰었던 나 ㅋㅋ) 새로운 장소와 새로운 사람들의 어색함을 푸는 과정이 지나고 행사에 본격적으로 빠져들었을 때 비로소 내가 여기에 온 이유를 생각하면서 더 의미있는 시간으로 바뀌었다.</p>
<p>행사는 컴퓨터 아트에 조금 더 초점이 맞춰져 있었다고 생각하는데 나는 이걸 어떻게 UX로 연결지어 서비스를 더욱 사용자 친화적이게 만들 수 있을지에 대해 계속 생각했다. </p>
<p><strong>절차적 생성 (Generator)</strong>은 사람이 직접 일일이 모든걸 만들어내는 작업을 넘어 알고리즘을 기반으로 어떤 패턴이나 자연현상을 표현하기 위해 고안된 일종의 도구?라는 느낌을 받았다. 나는 <strong>이 도구(코딩으로 구현할 수 있는)를 사용하여 결과물을 만들어내는 것을 크리에이티브 코딩</strong>이라고 정의했고 알고리즘에 사용되는 <strong>여러 변수들을 조절할 수 있게 만들어 누구나 결과물을 커스텀할 수 있는 과정을 인터랙티브</strong>라고 정의했다.</p>
<h3 id="행사에서-소개된-몇가지-유용한-툴과-결과물들">행사에서 소개된 몇가지 유용한 툴과 결과물들</h3>
<p><a href="https://processing.org/">https://processing.org/</a>
<a href="https://www.sojamo.de/libraries/controlP5/#examples">https://www.sojamo.de/libraries/controlP5/#examples</a>
<a href="https://vvvv.org/">https://vvvv.org/</a>
<a href="https://p5js.org/">https://p5js.org/</a>
<a href="https://fonts.studiofeixen.ch/editor/">https://fonts.studiofeixen.ch/editor/</a>
<a href="https://tools.dia.tv/">https://tools.dia.tv/</a>
<a href="https://spacetypegenerator.com/">https://spacetypegenerator.com/</a>
<a href="https://schultzschultz.com/tools/">https://schultzschultz.com/tools/</a></p>
<p><em><strong>정말 멋진걸 만드는 사람들이 많다는 걸 느꼈다.</strong></em>
<em><strong>&quot;나도 하나 만들어서 배포해봐야지&quot;라는 목표가 생겼다.</strong></em></p>
<hr>
<p>2부에는 행사 참여자들끼리 네트워킹할 수 있는 시간이었다. 사실 디자인쪽 계열 사람들이 많이 참여했을거라 생각했는데 의외로 컴퓨터쪽에 종사하시는 분들이 많았다..! 학생분들도 계셨는데 벌써부터 내가 뭘 좋아하는지 알고 그쪽으로 노력하는 모습이 대단하고 부럽다고 느꼈다.</p>
<p>각자 어떤 이유로 크리에이티브/인터랙티브에 관심을 가지고 스스로가 추구하는 방향을 여러 형태로 표현해낸 결과물들을 소개하고 이야기 나눌 수 있는 시간이었다.</p>
<h3 id="아쉬움이-남는-시간은-내게-의미있는-시간이다">&quot;아쉬움이 남는 시간은 내게 의미있는 시간이다.&quot;</h3>
<p>내가 가지고 있는 신념에 딱 맞는 시간이었고 이 신념이 깨질 때까지는 꾸준히 참여하고 싶은 그런 밋업이었다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[개발 블로그 개발기 (2)]]></title>
            <link>https://velog.io/@jw_99/%EA%B0%9C%EB%B0%9C-%EB%B8%94%EB%A1%9C%EA%B7%B8-%EA%B0%9C%EB%B0%9C%EA%B8%B0-2</link>
            <guid>https://velog.io/@jw_99/%EA%B0%9C%EB%B0%9C-%EB%B8%94%EB%A1%9C%EA%B7%B8-%EA%B0%9C%EB%B0%9C%EA%B8%B0-2</guid>
            <pubDate>Tue, 21 Oct 2025 15:27:42 GMT</pubDate>
            <description><![CDATA[<h1 id="요구사항-및-유저스토리">요구사항 및 유저스토리</h1>
<blockquote>
<p>입사하고 보니 기획까지..?</p>
</blockquote>
<p>사실 기획까지 하게 될 줄은 몰랐고 나의 업무 범위를 넘어선다는 생각도 많이 했지만 _<strong>피할 수 없으면 즐겨라</strong>_는 말이 있지 않은가. 않은가...? 아닌가..? 😭</p>
<p>기본 요구사항과 유저스토리는 노션으로 작성했다.</p>
<p><img src="https://velog.velcdn.com/images/jw_99/post/0686782c-0c2e-45c8-9e4e-f99ca81c5848/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/jw_99/post/4b17be75-e993-4aac-adb4-7d29c042ca80/image.png" alt=""></p>
<p>분명 누락된 것들이 많이 있겠지만 초반에 문서화를 해 놓으니 뭘 해야하는지가 명확해졌고 자연스럽게 개발 속도도 빨라졌다.</p>
<blockquote>
<p>잠깐 회사 이야기를 해보자면...</p>
</blockquote>
<p>회사에서는 노션으로 작성된 요구사항과 유저스토리를 각 서비스 담당자들이 정독 후 궁금한 점이나 추가/수정이 필요한 부분을 자유롭게 공유한다.
정돈된 요구사항과 유저스토리를 기반으로 프론트인 나는 mock 데이터를 기반으로 UI와 UX를 설계한다. 나는 개인적으로 이 기간을 제일 좋아한다. 프론트의 고유한 강점이자 경쟁력인 사용자 인터페이스와 사용자 경험을 고민할 수 있는 시간이기 때문이다. 레퍼런스를 뒤져보고 스타일링 코드를 주무르며 실험하기도 한다.</p>
<p><strong>반면, 이 기간이 지나면 고통의 시작이다.</strong></p>
<p> <img src="https://velog.velcdn.com/images/jw_99/post/523a0c26-67d8-4d48-91af-3955be5417f1/image.png" alt=""></p>
<p>아직 주니어라 그런지 몰라도, 프론트는 <strong>1. 타이트한 개발 일정</strong>과 <strong>2. 기획의 수정</strong> 그리고 심지어는 <strong>3. 백엔드 에러</strong>까지 커버해야하는 강한 멘탈이 필요한 것 같다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[자바스크립트 - 프로미스]]></title>
            <link>https://velog.io/@jw_99/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%ED%94%84%EB%A1%9C%EB%AF%B8%EC%8A%A4</link>
            <guid>https://velog.io/@jw_99/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%ED%94%84%EB%A1%9C%EB%AF%B8%EC%8A%A4</guid>
            <pubDate>Wed, 15 Oct 2025 14:28:28 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/jw_99/post/55eed1b1-532e-40ab-aeb7-f639e060e0f1/image.webp" alt=""></p>
<blockquote>
<p>꼭<del>꼭</del> 약속해~</p>
</blockquote>
<p>자바스크립트에서 <strong>Promise(프로미스)</strong>는 어떤 작업이 완료된 후 그 결과를 응답하겠다는 &quot;약속&quot;을 표현하는 객체입니다. 단어의 뜻(<code>promise: 약속, 약속하다</code>)과 아주 찰떡인 것 같습니다. </p>
<pre><code class="language-js">new Promise(executor)</code></pre>
<p>프로미스는 위와 같이 생성하는데, <code>Promise</code> 객체는 내부에 선언함과 동시에 즉시 실행되는 <strong>executor 함수</strong>를 받습니다.</p>
<pre><code class="language-js">new Promise((resolve, reject) =&gt; {
  // 비동기 작업 실행
  // 작업 성공 → resolve()
  // 작업 실패 → reject()
});</code></pre>
<p><strong>executor 함수</strong>는 <code>(resolve, reject) =&gt; {}</code> 로 표현되는데,</p>
<p>여기서 중요한 포인트:</p>
<ul>
<li><code>executor</code> 함수는 <code>resolve</code>와 <code>reject</code>라는 두 가지 콜백 함수를 인자로 받습니다.</li>
<li>비동기 작업이 성공하면 <code>resolve()</code>를 호출해 약속을 <strong>이행(fulfilled)</strong>합니다.</li>
<li>오류가 발생하면 <code>reject()</code>를 호출해 약속을 <strong>거부(rejected)</strong>합니다.</li>
</ul>
<p>예를 들어 서버로부터 데이터를 받는 비동기 통신을 한다고 가정해보자. </p>
<pre><code>1. 비동기 통신을 위해 Promise 객체가 선언되고 선언됨과 동시에 executor 함수가 실행된다.
2. executor 함수 안에 있는 서버와 통신하는 비동기 작업이 실행된다.
3. 비동기 작업이 성공하면 resolve(), 실패하면 reject()가 호출된다.</code></pre><p>비동기 통신의 대표인 fetch 함수를 보면 이해하기 쉽다.</p>
<pre><code class="language-js">function fetch(url, options) {
  return new Promise((resolve, reject) =&gt; { // Promise 객체가 선언되고 executor 함수가 즉시 실행된다.
    const xhr = new XMLHttpRequest();
    xhr.open(options?.method || &quot;GET&quot;, url); // 비동기 작업

    // 성공 (resolve 호출)
    xhr.onload = () =&gt; {
      resolve(new Response(xhr.responseText, { status: xhr.status }));
    };

    // 실패 (reject 호출)
    xhr.onerror = () =&gt; {
      reject(new TypeError(&quot;Network request failed&quot;));
    };

    xhr.send(options?.body || null);
  });
}
</code></pre>
<hr>
<h3 id="🚀-주요-promise-고급-기능-정리">🚀 주요 Promise 고급 기능 정리</h3>
<ol>
<li><code>Promise.all()</code> - 여러 Promise를 병렬 실행하고, 전부 완료될 때까지 기다림.</li>
<li><code>Promise.allSettled()</code> - 성공/실패 상관없이 모든 Promise의 결과를 배열로 반환    실패가 있어도 멈추지 않음.</li>
<li><code>Promise.race()</code> - 가장 먼저 완료된 Promise의 결과만 반환    여러 요청 중 가장 빠른 응답만 사용</li>
<li><code>Promise.any()</code> - 여러 Promise 중 첫 번째로 성공한 것만 반환. (실패는 무시)</li>
<li><code>Promise.resolve() / Promise.reject()</code> - 즉시 resolve/reject된 Promise 생성.</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[개발 블로그 개발기 (1)]]></title>
            <link>https://velog.io/@jw_99/%EA%B0%9C%EB%B0%9C-%EB%B8%94%EB%A1%9C%EA%B7%B8-%EA%B0%9C%EB%B0%9C%EA%B8%B0-1</link>
            <guid>https://velog.io/@jw_99/%EA%B0%9C%EB%B0%9C-%EB%B8%94%EB%A1%9C%EA%B7%B8-%EA%B0%9C%EB%B0%9C%EA%B8%B0-1</guid>
            <pubDate>Tue, 14 Oct 2025 14:50:51 GMT</pubDate>
            <description><![CDATA[<h1 id="기술스택-선정">기술스택 선정</h1>
<blockquote>
<p>회사에서 보내는 시간이 헛되지 않게</p>
</blockquote>
<p>개발자로 일한다는 건, 성과를 보여줘야 하는 매우 머리 아픈 일이다. 성과에 집중하며 달리다보면 남는 것은 &#39;성과&#39;뿐이라는 생각이 많이 든다. 실제 나의 성장은 과정에 있었지만 쉽게 잊혀졌다. 이번 기회에 처음으로 되돌아와 그 과정을 반복하려고 한다.</p>
<p>기술스택은 회사에서 사용하는 것들 위주로 꾸려보았다.</p>
<h3 id="🖥️-프론트엔드">🖥️ 프론트엔드</h3>
<ul>
<li><p><strong>Next.js</strong>
서버 컴포넌트는 아직 조심스럽지만, SSR이 기본이라 나름 SEO도 챙길 수 있어 좋다.</p>
</li>
<li><p><strong>Tailwind CSS</strong>
진짜 손에 익으면 다른 CSS 프레임워크는 못 쓰겠다.
클래스 이름 하나로 다 되니까 넘 편하다 😎</p>
</li>
<li><p><strong>TypeScript</strong>
JS의 안전벨트. 에러는 빨리 알수록 좋다.</p>
</li>
<li><p><strong>TanStack Query</strong>
회사에서는 SWR을 쓰지만, 이번엔 TanStack Query를 한 번 써볼 생각이다.
다양한 기능이 내장돼 있어서 학습 겸 경험 삼아 써보고 싶다.</p>
</li>
<li><p><strong>shadcn/ui</strong>
회사에선 daisyUI를 쓰는데, 개인적으로 마음에 안든다.
shadcn이 훨씬 깔끔하고 커스터마이징도 편한 느낌.</p>
</li>
</ul>
<h3 id="💾-백엔드--데이터베이스">💾 백엔드 &amp; 데이터베이스</h3>
<ul>
<li><p><strong>FastAPI</strong>
AI 회사라 그런지 Python을 많이 쓰게 되는데,
자연스럽게 FastAPI에도 익숙해졌다.
Swagger도 자동으로 되고, 참 매력적이다.</p>
</li>
<li><p><strong>PostgreSQL</strong>
회사에서도 쓰고 있고, 안정성과 기능성 면에서 마음에 든다.
근데 아직 DB에는 자신이 없어서, 이번 기회에 공부 제대로 할 계획.</p>
</li>
</ul>
<hr>
<h3 id="🧠-ai도-같이-씁니다">🧠 AI도 같이 씁니다</h3>
<blockquote>
<p>저는 GitHub 학생팩 덕분에 2년 동안은 돈이 굳었네요
개인적으로 코파일럿 좋아하는데, 무료?!
관심 있으신 분들은 <a href="https://education.github.com/pack">여기로</a> (정말 유용한 것들을 무료로 사용할 수 있습니다)</p>
</blockquote>
<ul>
<li><p><strong>디자인 초안</strong>: <strong>Claude Sonnet 4</strong>가 꽤 잘 뽑는다.
Claude 4.5도 나왔지만 아직 체감되는 변화는 크진 않은 느낌?</p>
</li>
<li><p><strong>로직 개발</strong>: <strong>Gemini Pro 2.5</strong>가 꽤 쓸만합니다.</p>
</li>
<li><p><strong>빠른 수정</strong>: 간단한 코드 수정이나 약간의 포맷 변경은 <strong>Grok</strong>이 빠르게 처리해줘서 좋습니다.</p>
</li>
</ul>
<p>저는 웹이 더 편한 경우도 있어서 ChatGPT는 항상 띄워두고 작업 많이 합니다ㅎㅎ</p>
<hr>
<h3 id="🌏-인프라">🌏 인프라</h3>
<p>회사에 와서 가장 큰 변화? 배운 거라고 하면 <strong>Docker</strong>를 잘 활용하는 방법이지 않을까 싶습니다. 익숙해지니 이것만큼 좋은 기술이 있을까 싶네요..! Docker 관련 글은 따로 작성해보겠습니다.</p>
<p>배포를 위한 VM은 <strong>DigitalOcean</strong>이란 서비스를 써볼건데, 이유는 사실 Github 학생팩에 200달러 무료 크레딧이 포함되어 있어서 서비스 만드는데 최대한 돈을 아껴보려고 합니다..! </p>
<p><em><strong>또 있을까요??</strong></em></p>
<p><del>생각나면 수정하러 오겠습니다.</del></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[개발 블로그 개발기 (프롤로그)]]></title>
            <link>https://velog.io/@jw_99/%EA%B0%9C%EB%B0%9C-%EB%B8%94%EB%A1%9C%EA%B7%B8-%EA%B0%9C%EB%B0%9C%EA%B8%B0-%ED%94%84%EB%A1%A4%EB%A1%9C%EA%B7%B8</link>
            <guid>https://velog.io/@jw_99/%EA%B0%9C%EB%B0%9C-%EB%B8%94%EB%A1%9C%EA%B7%B8-%EA%B0%9C%EB%B0%9C%EA%B8%B0-%ED%94%84%EB%A1%A4%EB%A1%9C%EA%B7%B8</guid>
            <pubDate>Mon, 13 Oct 2025 05:35:00 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>이대로는 안되겠다..!</p>
</blockquote>
<p>25년 추석연휴가 꽤 길었다. 
무려.. 연차까지해서 <strong>10일</strong>..!
<img src="https://velog.velcdn.com/images/jw_99/post/173e0908-36d9-475e-a0a3-d7f97adec14d/image.jpg" alt=""></p>
<p>예전부터 개발 블로그의 필요성을 느꼈지만 막상 시작하기가 어려웠다.. (시간적 여유가 없었다는건 핑계?)</p>
<p>문득 좋아하는 유튜버의 말이 떠올랐다.</p>
<blockquote>
<p>핑계를 조건문으로 바꾸고 그 조건문을 뒤집었을때 참이라면 그 원인을 해결하면 된다.</p>
</blockquote>
<p>즉, <strong>시간적 여유가 없다 =&gt; 개발 블로그를 시작할 수 없다.</strong></p>
<p>이걸</p>
<p><strong>시간적 여유가 생기면 =&gt; 개발 블로그를 시작할 수 있다.</strong></p>
<p>이번에도 안하면 너는 루저~🫵👎</p>
<blockquote>
<p>근데 왜 블로그?</p>
</blockquote>
<p>마침 회사에서도 게시판 작업을 했었고 (까먹기 전에 내꺼 뭐라도 남겨놔야지..) 짧은 기간에 <em><strong>츄라이</strong></em> 해보기에도 좋아보여서~</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[React useMemo와 useCallback]]></title>
            <link>https://velog.io/@jw_99/React-useMemo%EC%99%80-useCallback</link>
            <guid>https://velog.io/@jw_99/React-useMemo%EC%99%80-useCallback</guid>
            <pubDate>Sun, 11 Aug 2024 08:46:57 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/jw_99/post/9ac3a80f-9ef5-448a-8bad-fc3ccd71ad14/image.png" alt=""></p>
<blockquote>
<p>메모이제이션 hook인 useMemo와 useCallback에 대해서 알아보자</p>
</blockquote>
<h1 id="usememo">useMemo</h1>
<h3 id="메모이제이션된-값을-반환">메모이제이션된 값을 반환</h3>
<ul>
<li>언제 사용하나요?</li>
<li><blockquote>
<p>특정 값이 변할 경우에만 연산을 실행할 수 있도록 useMemo를 사용해 특정 변수에 의존하도록 등록해요.</p>
</blockquote>
</li>
</ul>
<pre><code class="language-js">import React, { useState, useMemo } from &quot;react&quot;;

export default function App() {
  const [countOne, setCountOne] = useState(0);
  const [countTwo, setCountTwo] = useState(0);

  console.log(countOne); 

  return (
    &lt;&gt;
      &lt;button onClick={() =&gt; setCountOne(cur =&gt; cur + 1)}&gt;one&lt;/button&gt;
      &lt;button onClick={() =&gt; setCountTwo(cur =&gt; cur + 1)}&gt;two&lt;/button&gt;
    &lt;/&gt;
  );
}</code></pre>
<p>-&gt; 위 상황을 가정해보면, console.log(countOne);은 <strong>상태가 바뀌면 리렌더링되는 컴포넌트 리렌더링 조건 때문에</strong> 버튼 one을 클릭할때 뿐만 아니라 버튼 two를 클릭할때도 실행된다.</p>
<p><strong>useMemo 사용</strong></p>
<pre><code class="language-js">import React, { useState, useMemo } from &quot;react&quot;;

export default function App() {
  const [countOne, setCountOne] = useState(0);
  const [countTwo, setCountTwo] = useState(0);

  // useMemo 사용하기
  useMemo(() =&gt; {console.log(countOne)}, [countOne]);

  return (
    &lt;&gt;
      &lt;button onClick={() =&gt; setCountOne(cur =&gt; cur + 1)}&gt;one&lt;/button&gt;
      &lt;button onClick={() =&gt; setCountTwo(cur =&gt; cur + 1)}&gt;two&lt;/button&gt;
    &lt;/&gt;
  );
}</code></pre>
<h1 id="usecallback">useCallback</h1>
<h3 id="메모이제이션된-함수를-반환">메모이제이션된 함수를 반환</h3>
<ul>
<li>언제 사용하나요?
1) 자식 컴포넌트에 props로 함수를 전달할 경우 
2) 외부에서 값을 가져오는 api를 호출하는 경우</li>
</ul>
<pre><code class="language-js">import React, { useState } from &#39;react&#39;;
import Info from &#39;./Info&#39;;

export default const App = () =&gt; {
  const [address, setAddress] = useState(&#39;&#39;);
  const onSave = () =&gt; {};

  return (
    &lt;div className=&quot;App&quot;&gt;
      &lt;input
        type=&quot;text&quot;
        value={address}
        onChange={(e) =&gt; setAddress(e.target.value)}
      /&gt;
      &lt;Info onSave={onSave} /&gt; // Info 컴포넌트 리렌더링 발생
    &lt;/div&gt;
  );
}</code></pre>
<blockquote>
<p>onChange 함수로 address가 변경되어 리렌더링이 발생하면 onSave함수가 새로 만들어지고, Info 컴포넌트의 props로 onSave함수가 새로 전달된다.</p>
</blockquote>
<p>이때 Info 컴포넌트에서 이전 onSave와 이후 onSave가 다른 함수가 되어버리기 때문에 리렌더링이 일어난다.</p>
<p><strong>useCallback 사용</strong></p>
<pre><code class="language-js">import React, { useState, useCallback } from &#39;react&#39;;
import Info from &#39;./Info&#39;;

export default const App = () =&gt; {
  const [address, setAddress] = useState(&#39;&#39;);
  const onSave = useCallback(() =&gt; {}, [address]);

  return (
    &lt;div className=&quot;App&quot;&gt;
      &lt;input
        type=&quot;text&quot;
        value={address}
        onChange={(e) =&gt; setAddress(e.target.value)}
      /&gt;
      &lt;Info onSave={onSave} /&gt; // Info 컴포넌트 리렌더링 방지
    &lt;/div&gt;
  );
}</code></pre>
<h1 id="추가-reactmemo">(추가) React.memo</h1>
<blockquote>
<p>컴포넌트 자체를 메모이제이션하는 방법</p>
</blockquote>
<h2 id="컴포넌트-리렌더링-조건">컴포넌트 리렌더링 조건</h2>
<ol>
<li>자신의 상태가 변했을때</li>
<li>부모 컴포넌트로부터 받은 props가 변했을때</li>
<li>부모 컴포넌트가 리렌더링될때 -&gt; React.memo는 요경우에 최적화</li>
</ol>
<h3 id="즉-부모-컴포넌트가-리렌더링될-때-자식-컴포넌트는-리렌더링하지-않음">즉, 부모 컴포넌트가 리렌더링될 때 자식 컴포넌트는 리렌더링하지 않음.</h3>
]]></description>
        </item>
        <item>
            <title><![CDATA[[자료구조] 스택, 큐, 해시테이블 사용법]]></title>
            <link>https://velog.io/@jw_99/%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0-%EC%8A%A4%ED%83%9D-%ED%81%90-%ED%95%B4%EC%8B%9C%ED%85%8C%EC%9D%B4%EB%B8%94</link>
            <guid>https://velog.io/@jw_99/%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0-%EC%8A%A4%ED%83%9D-%ED%81%90-%ED%95%B4%EC%8B%9C%ED%85%8C%EC%9D%B4%EB%B8%94</guid>
            <pubDate>Sun, 11 Aug 2024 06:30:27 GMT</pubDate>
            <description><![CDATA[<h1 id="1-스택">1. 스택</h1>
<p><img src="https://velog.velcdn.com/images/jw_99/post/83a548db-e7c6-48f3-a767-3cd171280027/image.png" alt=""></p>
<blockquote>
<p>LIFO(<strong>L</strong>ast <strong>I</strong>n <strong>F</strong>irst <strong>O</strong>ut) 자료구조</p>
</blockquote>
<h2 id="구현-및-사용방법-배열">구현 및 사용방법 (배열)</h2>
<pre><code class="language-js">const array = [];

const stackPush = (value) =&gt; {
    array.push(value);
}

const stackPop = () =&gt; {
    return array.pop();
}

stackPush(1); // [1]
stackPush(2); // [1, 2]
stackPop(); // [1]</code></pre>
<h1 id="2-큐">2. 큐</h1>
<p><img src="https://velog.velcdn.com/images/jw_99/post/cf691e60-c2b4-4f0d-a092-25621db92d27/image.png" alt=""></p>
<blockquote>
<p>FIFO(<strong>F</strong>irst <strong>I</strong>n <strong>F</strong>irst <strong>O</strong>ut) 자료구조</p>
</blockquote>
<h2 id="구현-및-사용방법-배열-연결리스트">구현 및 사용방법 (배열, 연결리스트)</h2>
<h3 id="1-배열">1. 배열</h3>
<pre><code class="language-js">class Queue {
    constructor() {
          this.queue = [];
        this.front = 0;
          this.rear = 0;
    }

      enqueue(value) {
        this.queue[this.rear++] = value;
    }

      dequeue() {
        const value = this.queue[this.front];
          delete this.queue[this.front];
          this.front++;
          return value;
    }

      peek() {
        return this.queue[this.front];
    }

      size() {
        return this.rear - this.front;
    }
}

const queue = new Queue();

queue.enqueue(1); // [1]
queue.enqueue(2); // [1, 2]
queue.peek(); // 1
queue.size(); // 2
queue.dequeue(); // [1] 2</code></pre>
<h3 id="2-연결리스트">2. 연결리스트</h3>
<pre><code class="language-js">class Node {
    constructor(value) {
        this.value = value;
          this.next = null;
    }
}

class Queue {
    constructor() {
        this.front = null;
          this.rear = null;
          this.size = 0;
    }

      enqueue(value) {
        const newNode = new Node(value);
          this.size++;
          if (this.front === null) {
            this.front = newNode;
              this.rear = newNode;
        } else {
            this.rear.next = newNode;
              this.rear = newNode;
        }
    }

      dequeue() {
        const value = this.front.value;
          this.front = this.front.next;
          if (this.front === null) {
            this.rear = null;
        }
          this.size--;
          return value;
    }

      peek() {
        return this.front.value;
    }

      size() {
        return this.size;
    }    
}</code></pre>
<h1 id="3-해시테이블">3. 해시테이블</h1>
<p><img src="https://velog.velcdn.com/images/jw_99/post/5d4bdaec-78ca-43b5-a5d3-e689e6d3b71e/image.png" alt=""></p>
<blockquote>
<p>키(key)를 해싱하여 나온 index에 값(value)을 저장하는 자료구조</p>
</blockquote>
<h2 id="구현-및-사용방법-object-map-set">구현 및 사용방법 (Object, Map, Set)</h2>
<h3 id="1-object">1. Object</h3>
<pre><code class="language-js">const table = {};

table[&#39;key1&#39;] = 100;
table[&#39;key2&#39;] = &quot;Hello&quot;;
console.log(table[&#39;key1&#39;]); // 100
delete table[&#39;key1&#39;];</code></pre>
<h3 id="2-map-set-get-사용">2. Map (set(), get() 사용)</h3>
<pre><code class="language-js">const table = new Map();

table.set(&#39;key1&#39;, 100);
table.set(&#39;key2&#39;, &quot;Hello&quot;);
console.log(table.get[&#39;key1&#39;]); // 100

const object = { a : 1 };

table.set(object, &quot;A1&quot;); // 객체를 key로 사용가능!
console.log(table.get(object)); // &quot;A1&quot;</code></pre>
<h3 id="3-set-key와-value가-동일">3. Set (key와 value가 동일)</h3>
<pre><code class="language-js">const table = new Set();

table.add(&#39;key1&#39;); // {&#39;key1&#39;}
table.add(&#39;key2&#39;); // {&#39;key1&#39;, &#39;key2&#39;}
table.keys(); // {&#39;key1&#39;, &#39;key2&#39;}
table.values(); // {&#39;key1&#39;, &#39;key2&#39;}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[React 렌더링 과정]]></title>
            <link>https://velog.io/@jw_99/React-%EB%A0%8C%EB%8D%94%EB%A7%81-%EA%B3%BC%EC%A0%95</link>
            <guid>https://velog.io/@jw_99/React-%EB%A0%8C%EB%8D%94%EB%A7%81-%EA%B3%BC%EC%A0%95</guid>
            <pubDate>Wed, 31 Jul 2024 12:38:43 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>React.js의 렌더링 방식 살펴보기 - 이정환 | 2023 NE(O)RDINARY CONFERENCE (링크 - <a href="https://www.youtube.com/watch?v=N7qlk_GQRJU">https://www.youtube.com/watch?v=N7qlk_GQRJU</a>)</p>
</blockquote>
<h1 id="react-렌더링-프로세스">React 렌더링 프로세스</h1>
<h3 id="1-1-웹-브라우저-동작-원리-critical-rendering-path">1-1. 웹 브라우저 동작 원리 (Critical Rendering Path)</h3>
<p><img src="https://velog.velcdn.com/images/jw_99/post/a97f2fc1-0d52-49c4-b2ee-7ca71ea14f07/image.png" alt=""></p>
<ol>
<li>HTML과 CSS를 브라우저가 해석하기 편한 방식으로 DOM과 CSSOM를 만든다.</li>
<li>DOM과 CSSOM를 합쳐 Render Tree(청사진)를 만든다.</li>
<li>Render Tree를 기반으로 Layout을 잡는다.</li>
<li>화면에 그려준다.</li>
</ol>
<h3 id="1-2-업데이트는-어떻게-이뤄질까">1-2. 업데이트는 어떻게 이뤄질까?</h3>
<blockquote>
<p>자바스크립트 언어로 DOM을 직접 조작 -&gt; 변경된 DOM으로 렌더링 과정을 2번부터 다시 거친다..! 즉, <strong>Reflow</strong>와 <strong>Repainting</strong> 작업이 반복된다..!</p>
</blockquote>
<p>코드 예제 (비효율적인 방법)</p>
<pre><code>&lt;script&gt;
    function onClick() {
        const $ul = document.getElementById(&quot;ul&quot;);
        for (let i = 0; i &lt; 3000; i++) {
            $ul.innerHTML += `&lt;li&gt;${i}&lt;/li&gt;`; // Reflow와 Repainting 3000번 실행
        }
    }
&lt;/script&gt;
&lt;body&gt;
    &lt;button onclick=&quot;onClick()&quot;&gt;리스트 추가하기&lt;/button&gt;
    &lt;ul id=&quot;ul&quot;&gt;&lt;/ul&gt;
&lt;/body&gt;</code></pre><p>코드 예제 (효율적인 방법)</p>
<pre><code>&lt;script&gt;
    function onClick() {
        const $ul = document.getElementById(&quot;ul&quot;);
        let list = &quot;&quot;;
        for (let i = 0; i &lt; 3000; i++) {
            list += `&lt;li&gt;${i}&lt;/li&gt;`;
        }
        $ul.innerHTML = list; // Reflow와 Repainting 1번 실행
    }
&lt;/script&gt;
&lt;body&gt;
    &lt;button onclick=&quot;onClick()&quot;&gt;리스트 추가하기&lt;/button&gt;
    &lt;ul id=&quot;ul&quot;&gt;&lt;/ul&gt;
&lt;/body&gt;</code></pre><h3 id="효율적인-방법을-react에서-자동으로-해주고-있다"><em>효율적인 방법을 React에서 자동으로 해주고 있다..!</em></h3>
<h3 id="2-1-react-렌더링-프로세스">2-1. React 렌더링 프로세스</h3>
<p><img src="https://velog.velcdn.com/images/jw_99/post/e1749c37-4c6b-4262-8b18-9b9543916bf2/image.png" alt=""></p>
<blockquote>
<p>Render Phase + Commit Phase로 나뉨</p>
</blockquote>
<h3 id="2-2-render-phase">2-2. Render Phase</h3>
<blockquote>
<p>컴포넌트를 계산하고 업데이트 사항을 파악하는 단계</p>
</blockquote>
<h4 id="render-phase-1---컴포넌트를-호출해-결과값을-계산-컴포넌트를-react-element로-변환하는-과정">Render Phase 1 - 컴포넌트를 호출해 결과값을 계산 (컴포넌트를 React Element로 변환하는 과정)</h4>
<h4 id="render-phase-2---react-element들을-모아-virtual-dom-생성">Render Phase 2 - React Element들을 모아 Virtual DOM 생성</h4>
<h3 id="2-3-commit-phase">2-3. Commit Phase</h3>
<blockquote>
<p>변경사항을 실제 DOM에 반영하는 단계</p>
</blockquote>
<p>Virtual DOM -&gt; Actual DOM 반영 -&gt; 자바스크립트가 DOM을 수정하면 동작하는 과정 수행!</p>
<h1 id="이렇게-복잡한-이유가-뭐야">이렇게 복잡한 이유가 뭐야!</h1>
<p>.
..
...
....
.....
DOM 수정을 최소화하기 위해서...!</p>
<blockquote>
<p>그럼 React에서 업데이트가 일어나면 어떻게 되나요?</p>
</blockquote>
<p>같은 렌더링 프로세스를 거쳐 <strong>Next Virtual DOM</strong>을 생성하고 <strong>Prev Virtual DOM</strong>과 비교하여 수정된 부분을 Actual DOM에 반영 -&gt; 이러한 과정을 <strong>Reconciliation(재조정)</strong>이라 부른다...</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[React 컴포넌트]]></title>
            <link>https://velog.io/@jw_99/React-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8</link>
            <guid>https://velog.io/@jw_99/React-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8</guid>
            <pubDate>Wed, 31 Jul 2024 00:53:35 GMT</pubDate>
            <description><![CDATA[<h1 id="컴포넌트란">컴포넌트란?</h1>
<p><img src="https://velog.velcdn.com/images/jw_99/post/3cc0234b-2147-4230-84f7-546ab84cea7b/image.jpeg" alt=""></p>
<blockquote>
<p>하나의 기능을 담당하는 코드 조각</p>
</blockquote>
<h2 id="특징">특징</h2>
<ol>
<li>HTML, Style, JavaScript, Event, State를 가질 수 있다.</li>
<li>트리 구조로 이뤄져있다. =&gt; 컴포넌트끼리 데이터와 메시지를 주고 받을 수 있다. (데이터는 상위에서 하위로만 전달된다. == 단방향)</li>
<li>컴포넌트 = 함수
<img src="https://velog.velcdn.com/images/jw_99/post/abb29e92-a7ae-48fc-85d8-e4d375febe8f/image.jpeg" alt=""></li>
</ol>
<h2 id="재사용-가능한-컴포넌트-만들기">재사용 가능한 컴포넌트 만들기</h2>
<h3 id="1-ui를-추상적으로-바라보기-공통점-찾기"><strong><em>1. UI를 추상적으로 바라보기 (공통점 찾기)</em></strong></h3>
<h3 id="2-컴포넌트-분류하기"><strong><em>2. 컴포넌트 분류하기</em></strong></h3>
<pre><code>- 도메인으로 분류하기
ex) User, Product...

- 역할로 분류하기
ex) Header, Nav, List, Tag...

- 크기로 분류하기
ex) Organism, Molecule, Atom...
참고 사이트 - [링크텍스트](https://kciter.so/posts/effective-atomic-design)</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[React 시작하기]]></title>
            <link>https://velog.io/@jw_99/React-%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@jw_99/React-%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0</guid>
            <pubDate>Wed, 31 Jul 2024 00:27:28 GMT</pubDate>
            <description><![CDATA[<h1 id="react란">React란?</h1>
<p><img src="https://velog.velcdn.com/images/jw_99/post/983d35df-bac8-430a-a348-21073beabe78/image.png" alt=""></p>
<blockquote>
<p>facebook에서 만든 오픈 소스 라이브러리</p>
</blockquote>
<h2 id="왜-쓰나요">왜 쓰나요?</h2>
<ol>
<li>github 17만개의 star수 =&gt; 많은 개발자들로부터 사랑을 받는 중</li>
<li>한글을 제공하는 공식문서</li>
<li>약 800만 개의 Stack Overflow 많은 양의 데이터</li>
</ol>
<h2 id="특징">특징</h2>
<ol>
<li>Reactive Programming =&gt; 데이터(상태)가 변하면 반응하는 방식</li>
<li>MVC 패턴에서 컴포넌트 시스템을 활용하여 View만을 관리한다.</li>
<li>가상 돔(virtual DOM)을 사용하여 필요한 부분만 한 번에 렌더링한다.</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[[코딩테스트] 배열에서 문자열 대소문자 변환하기]]></title>
            <link>https://velog.io/@jw_99/%EC%BD%94%EB%94%A9%ED%85%8C%EC%8A%A4%ED%8A%B8-%EB%B0%B0%EC%97%B4%EC%97%90%EC%84%9C-%EB%AC%B8%EC%9E%90%EC%97%B4-%EB%8C%80%EC%86%8C%EB%AC%B8%EC%9E%90-%EB%B3%80%ED%99%98%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@jw_99/%EC%BD%94%EB%94%A9%ED%85%8C%EC%8A%A4%ED%8A%B8-%EB%B0%B0%EC%97%B4%EC%97%90%EC%84%9C-%EB%AC%B8%EC%9E%90%EC%97%B4-%EB%8C%80%EC%86%8C%EB%AC%B8%EC%9E%90-%EB%B3%80%ED%99%98%ED%95%98%EA%B8%B0</guid>
            <pubDate>Mon, 06 May 2024 11:35:47 GMT</pubDate>
            <description><![CDATA[<h1 id="인트로">인트로</h1>
<p><img src="https://velog.velcdn.com/images/jw_99/post/4af0fb3a-cdcc-43e6-b48b-00452bdfbb2f/image.PNG" alt=""></p>
<p>문제를 처음보고 홀수/짝수 번째 인덱스 배열을 돌며 <strong>toLowerCase()</strong>와 <strong>toUpperCase()</strong> 문자열 메소드를 사용하면 될 것 같다는 생각이 들었다. </p>
<p><img src="https://velog.velcdn.com/images/jw_99/post/9201cec7-0bbf-484d-b620-598ee8a4d899/image.PNG" alt=""></p>
<p>제한 사항을 준 이유에 대해서 생각해봤는데,</p>
<ol>
<li>배열의 길이가 길어지면 문제가 되나?</li>
<li>숫자/한글은 대소문자 구분이 없으니 알파벳으로 이루어진 배열이라는 제한을 두었구나.</li>
</ol>
<p>우선, 배열의 길이가 0이면 안되는 거니까 1보다 크거나 같다는 인정! 20보다 작거나 같다는 의미는 무엇일까? -&gt; 결국 찾지 못함.</p>
<p>검색하다가 우연히 발견한 배열에 관한 내용
<a href="https://velog.io/@redjen/%EB%8B%B9%EC%8B%A0%EC%9D%98-%EB%B0%B0%EC%97%B4%EC%9D%80-%EA%B4%9C%EC%B0%AE%EC%9D%80%EA%B0%80%EC%9A%94">https://velog.io/@redjen/%EB%8B%B9%EC%8B%A0%EC%9D%98-%EB%B0%B0%EC%97%B4%EC%9D%80-%EA%B4%9C%EC%B0%AE%EC%9D%80%EA%B0%80%EC%9A%94</a></p>
<h1 id="스토리">스토리</h1>
<h3 id="초기-코드">초기 코드</h3>
<pre><code>function solution(strArr) {
    let answer = [];
    for (let i = 0; i &lt; strArr.length; i++) {
        if (i % 2 === 0) {
            answer.push(strArr.toLowerCase());
        } else {
            answer.push(strArr.toUpperCase());
        }
    }
    return answer;
}</code></pre><p><strong>에러 발생!</strong></p>
<pre><code>answer.push(strArr.toLowerCase());
                               ^
TypeError: strArr.toLowerCase is not a function</code></pre><p>엥? 아! strArr에 인덱스 값을 안줬구나! ㅋㅋㅋ</p>
<h3 id="수정-코드">수정 코드</h3>
<pre><code>function solution(strArr) {
    let answer = [];
    for (let i = 0; i &lt; strArr.length; i++) {
        if (i % 2 === 0) {
            answer.push(strArr[i].toLowerCase());
        } else {
            answer.push(strArr[i].toUpperCase());
        }
    }
    return answer;
}</code></pre><p><strong>모두 통과!</strong>
<img src="https://velog.velcdn.com/images/jw_99/post/0b8ada4b-36bb-4a7c-9bf7-009e27bdb361/image.PNG" alt=""></p>
<p><img src="https://velog.velcdn.com/images/jw_99/post/c44ad2ef-30ea-42a8-aaf7-bdcade0d47e0/image.PNG" alt=""></p>
<blockquote>
<p>파란색이 아주 보기 좋구만유~!</p>
</blockquote>
<h1 id="결과">결과</h1>
<h3 id="사용한-개념">사용한 개념</h3>
<ol>
<li>반복문</li>
<li>나머지 판별 연산자 &#39;%&#39;</li>
<li>문자열 메소드</li>
<li>배열 요소 추가 메소드</li>
</ol>
<h1 id="번외">번외</h1>
<p>다른 방법으로 더 쉽게? 더 짧게? 풀 수 있을까?!</p>
<h3 id="방법1-map">방법1 map()</h3>
<p><strong>개념</strong>
<a href="https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Array/map">https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Array/map</a></p>
<p><strong>풀이</strong></p>
<pre><code>const solution = (strArr) =&gt; strArr.map((currValue, index) =&gt; index % 2 === 0 ? currValue.toLowerCase() : currValue.toUpperCase());</code></pre><br/>
<br/>

<h3 id="방법2-reduce">방법2 reduce()</h3>
<p><strong>개념</strong>
<a href="https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce">https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce</a></p>
<p><strong>풀이</strong></p>
<pre><code>const solution = (strArr) =&gt; strArr.reduce(
    (acc, cur, index) =&gt; [...acc, index % 2 === 0 ? cur.toLowerCase() : cur.toUpperCase()], []
)</code></pre><br/>
<br/>

<h3 id="방법3-foreach">방법3 forEach()</h3>
<p><strong>개념</strong>
<a href="https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach">https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach</a></p>
<p><strong>풀이</strong></p>
<pre><code>const solution = (strArr) =&gt; {
    let answer = [];
    strArr.forEach((arr, index) =&gt; {
        if (index % 2 == 0) {
            answer.push(arr.toLowerCase());
        } else {
            answer.push(arr.toUpperCase());
        }
    });
    return answer;
}</code></pre>]]></description>
        </item>
    </channel>
</rss>