<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>hun.log</title>
        <link>https://velog.io/</link>
        <description>과정을 적는 곳</description>
        <lastBuildDate>Sat, 27 Jan 2024 05:44:50 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>hun.log</title>
            <url>https://images.velog.io/images/jae-hun-e/profile/daf7bb57-68f2-4294-9e1c-b85e24a97722/KakaoTalk_20211227_155115617.jpg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. hun.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/jae-hun-e" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[나는 왜 함수형 프로그래밍이 궁금할까?]]></title>
            <link>https://velog.io/@jae-hun-e/%EB%82%98%EB%8A%94-%EC%99%9C-%ED%95%A8%EC%88%98%ED%98%95-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D%EC%9D%B4-%EA%B6%81%EA%B8%88%ED%95%A0%EA%B9%8C</link>
            <guid>https://velog.io/@jae-hun-e/%EB%82%98%EB%8A%94-%EC%99%9C-%ED%95%A8%EC%88%98%ED%98%95-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D%EC%9D%B4-%EA%B6%81%EA%B8%88%ED%95%A0%EA%B9%8C</guid>
            <pubDate>Sat, 27 Jan 2024 05:44:50 GMT</pubDate>
            <description><![CDATA[<h2 id="intro">Intro</h2>
<p>나는 수학이 좋았다. 수학과에 대한 미련을 접고 난 후 갈 곳을 잃었다. 그 당시 재수학원 원장님께 상담결과 ‘너는 프로그래밍이랑 잘 맞을 것 같은데?’ 이 한마디에 그래서 20살까지 독수리타법을 치던 내가 아무것도 모른채 컴공과를 가게되었다.(너무 너무 감사합니다🙏)</p>
<p>하지만 내가 생각하던 프로그래밍과 학교에서 배우는 수업은 조금 달랐고 생각보다 흥미가 있지 않았다. 코딩을 하며 흥미를 느낀 것은 의외로 FE개발을 접해보면서였고, 여러 고민끝에 FE로 진로를 정하게 되었다. </p>
<p>하지만 FE 엔지니어가 되어야겠다 생각을 하며 공부를 하였지만 수학 관련된 생각을 한 적이 없었다. </p>
<p>다시 나를 돌아보니 내가 수학을 좋아하는 이유는 ‘증명’ 때문이었다. </p>
<p>가능한 모든 케이스 검증을 통한 증명이 아닌, 이미 증명된 공리를 이용한 새로운 증명 때문이었다. </p>
<p>이를 프로그래밍에 대입해보면 선배들의 경험적으로 발생하는 케이스들을 체크한 후 가장 좋은 방법이되었던 best practice가 아닌 </p>
<p>이미 테스트 완료된 된 것들을 이용해서 새로운 것을 만들면 테스트 통과를 한 효과를 지닌다는 것이고, 이는 아주 명쾌하게 다가왔다. (이는 순수함수로 인해 불변성이 보장되기 때문에 발생하는 부수효과라고 생각한다.)</p>
<p>구글의 정보의 늪에서 허우적거리다가 함수형 프로그래밍을 대수적 관점으로 설명해준 글을 보게되었고 배워보고 싶은 욕망이 아주 강하게 들었다. </p>
<p>프로그래밍이 어려운 이유는 예상치 못한 에러를 마주하기 때문이라고 생각한다. </p>
<p>내가 수학을 좋아했던 이유, 프로그래밍을 하면서 마음 한켠에 찝찝함이 남아있던 이유를 함수형 프로그래밍 패러다임을 공부해보며 답을 찾을 수 있을 것 같다는 기대감이 들었다. </p>
<h2 id="정리">정리</h2>
<p>아래내용은 아주아주아주 얕은 내 지식으로 여러 글들을 읽으며 정리해본 내용이다.</p>
<blockquote>
<p>아주 얕은 지식으로 작성된 글이며 반박 시 여러분 말이 95%확률로 맞으며 언제든지 환영합니다.</p>
</blockquote>
<p>객체지향 프로그래밍과 함수형 프로그래밍의 가장 큰 차이는 무엇이 중심인가 라고 생각한다. </p>
<ul>
<li>객체지향 : 객체가 중심</li>
<li>함수형 : 행동이 중심</li>
</ul>
<p>내가 생각한 함수형 프로그래밍의 핵심은 작게 나누고 작은 단위가 증명되었다면 그것들을 이용해 합성한 것도 보장된다는 것이다. (지지고 볶으며 패배한 아토믹 디자인 패턴과도 결이 맞는 느낌쓰?)</p>
<ul>
<li>A, B함수가 테스트를 성공한다면(증명이 되었다면)</li>
<li>A와 B를 이용해서 만든 C함수의 성공이 보장된다 (A, B는 C에게 공리가 된다.)</li>
</ul>
<p>이다. </p>
<p>이를 통해 구현된 프로그램은 예외 케이스를 만들지 않고 에러가 사라질 것이라고 생각했다.(물론 100%에러가 없다는건 말이 안되겠지만..)</p>
<p>물론 모든 경우의 함수를 합칠 수 있는 건 아니다. 함수를 합성하기 위해서는 정의역(x)값과 공역(y)값이 일치해야 한다. </p>
<p>이는 수학에서의 합성함수와 동일한 이론이다. </p>
<p><img src="https://velog.velcdn.com/images/jae-hun-e/post/4558a18b-ea85-4dfc-892d-95d2e684bbf4/image.png" alt="수학에서 **합성 함수**는 한 함수의 공역이 다른 함수의 정의역과 일치하는 경우, 두 함수를 이어 하나의 함수로 만드는 연산이다.**- 위키백과**"></p>
<p>수학에서의 정의역, 공역의 범위로 될 수 있는 것들은 정수, 유리수, 무리수, 허수 등 의 범주가 있다.</p>
<p>이를 프로그래밍 세계로 가져와보면 정의역 공역의 범위로 될 수 있는 것이 바로 타입이다. </p>
<p>이게 프로그래밍을 대수관점으로 바라볼 수 있게되는 핵심이라고 생각하다.</p>
<p>타입과 수학과의 표기 차이를 보면 
<img src="https://velog.velcdn.com/images/jae-hun-e/post/e53ad10c-e779-4307-a758-586c13d8a88a/image.png" alt=""></p>
<p><a href="https://moonsupport.oopy.io/post/30">출처</a></p>
<p>이렇게 나타내진다. </p>
<p>이런 제약조건들로 모든 것을 순수함수의 합성을 만들 수 있는 것은 아니다. 또한 이러한 순수 함수의 합성들로 구성되어있다고 해도 모든 경우를 커버할 수 없다. </p>
<p>그래서 펑터, 모다드, 어플리케이티드 펑더 등의 개념이 필요해진것이다. </p>
<p><strong><a href="https://evan-moon.github.io/2020/01/27/safety-function-composition/">어떻게 하면 안전하게 함수를 합성할 수 있을까?</a></strong> 의 글에서의 예시를 빌리자면 </p>
<pre><code class="language-tsx">function getFirstLetter (s: string): string {
  return s[0];
}</code></pre>
<p>이러한 순수함수가 있을 때 </p>
<pre><code class="language-tsx">getStringLength(getFirstLetter(&#39;&#39;));</code></pre>
<p>처럼 빈문자열을 넣어준다면 에러가 나게되고 이것도 하나의 사이트 이펙트이다 라고 설명하고 있다. </p>
<p>사실 <code>getFirstLetter</code> 의 공역은 <code>string</code>이 아니라 <code>string | undefined</code> 이기 때문이라고 설명해주며 이와 같은 경우를 위해</p>
<pre><code class="language-tsx">function getFirstLetter (s: string): string|undefined {
  return s[0];
}
function getStringLength (s: string|undefined): number {
  if (!s) {
    return -1;
  }
  return s.length;
}

// 위의 방식을 우아하게 하면 
function safety &lt;T, U&gt;(x: T|undefined, fn: (x: T) =&gt; U) {
  return x ? fn(x) : x;
}

safety&lt;string, number&gt;(getFirstLetter(&#39;Hi&#39;), getStringLength);
safety&lt;string, number&gt;(getFirstLetter(&#39;&#39;), getStringLength);</code></pre>
<p>처럼 예외 처리를 통해 해결할 수 있다고 설명해주었다.</p>
<p>이글을 보고 이런 생각이 들었다.</p>
<blockquote>
<p>수학에서의 함수를 생각해보면 정의역에 들어가는 값에 제한이 붙는다.
f(x) = 2/x 이런 함수를 생각해보면 뒤에 항상 (단, x는 0이 아님)</p>
</blockquote>
<p>빈문자열이 들어가는 경우는 ‘단, x는 0이 아님’ 과 같은 경우 아닐까? 이런 조건이 있는 경우 함수 내부에서 판단해주는 것이 아닌 함수에 값을 넣는 내가 0이 아닐 때만 넣어줘야한다. </p>
<p>이를 프로그래밍 세계에 대입해보면 함수 내부에서 처리해주는게 아닌 사용하는 곳에서 이런 경우를 배제하고 보내주는게 맞지 않을까? 생각이 들었다. </p>
<p>하지만 이는 명령형 프로그래밍에 가깝고 함수형 프로그래밍의 상위 개념인 선언형이라는 맞지 않다는 생각이 들었다…</p>
<p>그리고 <code>펑터</code> 라는 개념을 설명해주셨다. (슈뢰딩거의 고양이 느낌 같기도 하고..?)</p>
<p>내가 이해하기로는 순수함수를 감싸 예외처리를 해주는 역할이라고 까지만 이해가 되었다,,, 어려워ㅠ </p>
<h2 id="찍먹-후기">찍먹 후기</h2>
<blockquote>
<p>순수함수는 그냥 우리가 수학에서 배우던 수학적인 함수이다.</p>
</blockquote>
<blockquote>
<p>즉, 수학에서의 함수를 프로그래밍에 그대로 적용하면 순수한 함수의 특성인 “함수의 결과는 함수의 인자에만 영향을 받는다”라는 조건과 “함수 외부의 상태를 변경하거나 영향을 받아선 안된다”라는 조건이 자연스럽게 충족되는 것이다. 
⇒ 불변성</p>
</blockquote>
<p>이 두문장에 가장 함수형 프로그램을 공부하는데 가장 잘 와닿았다.</p>
<p>함수형 프로그래밍의 장점은 순수함수를 사용함으로 따라오는 것들이고, 순수함수의 장점은 불변성이라고 생각한다.</p>
<p>그러면 항상 함수형 프로그래밍이 OOP보다 좋은것이냐? 이건 절대 아니다. </p>
<p>순수함수에서 불변성이 지키기 위해서는 비용이든다. </p>
<p>Array, Object같은 자료형은 태생 부터가 상태값 변경을 위해 생성되었다. 이런 태생을 거스르고 불변성을 유지하기 위해서는 비용을 내야한다. 기존의 상태값을 복사해서 변경하는 것이다. </p>
<p>만약 기존의 상태값에 많은 정보가 담겨져 있다면 불변성을 유지하는 비용으로 상태를 복사하는 값을 많이 치뤄야 한다. 이는 퍼포먼스가 중요한 서비스에서는 맞지 않는 방법이다. </p>
<p>데브코스 1차 멘토님의 말씀이 생각났다. </p>
<blockquote>
<p>대부분 많은경우에서 퍼포먼스보다 중요시되는 것은 가독성과 일관성이다.</p>
</blockquote>
<p>비슷한 논리로 발전된 하드웨어 덕분에 퍼포먼스에대한 고민을 내려놓고 유지보수 측면에서본다면 함수형 프로그래밍이 두각을 나타내는 부분이 분명있을 꺼라고 생각한다. </p>
<p>이번에 함수형 프로그래밍을 공부해 보면서 스스로 목표는 함수형 프로그래밍의 패러다임을 이해하고 비용을 치루면서라도 불변성이 더 중요한 부분을 리팩토링해보는 것을 목표로 정했다. </p>
<p>데나무숲 v2 리팩토링 가즈아ㅏ</p>
<hr>
<h3 id="참고">참고</h3>
<p>대수로 다룬 함수형 프로그래밍 : <a href="https://moonsupport.oopy.io/post/30">https://moonsupport.oopy.io/post/30</a></p>
<p>함수형 사고 : <a href="https://moonsupport.oopy.io/post/30">https://moonsupport.oopy.io/post/30</a></p>
<p>순수 함수 : <a href="https://evan-moon.github.io/2019/12/29/about-pure-functions/">https://evan-moon.github.io/2019/12/29/about-pure-functions/</a>
불변성 : <a href="https://evan-moon.github.io/2020/01/05/what-is-immutable/">https://evan-moon.github.io/2020/01/05/what-is-immutable/</a></p>
<p>안전한 합성 함수 : <a href="https://evan-moon.github.io/2020/01/27/safety-function-composition/">https://evan-moon.github.io/2020/01/27/safety-function-composition/</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[프론트엔드 데브코스 5기  MIL(2023.12~2024.01)]]></title>
            <link>https://velog.io/@jae-hun-e/%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C-%EB%8D%B0%EB%B8%8C%EC%BD%94%EC%8A%A4-5%EA%B8%B0-MIL2023.122024.01</link>
            <guid>https://velog.io/@jae-hun-e/%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C-%EB%8D%B0%EB%B8%8C%EC%BD%94%EC%8A%A4-5%EA%B8%B0-MIL2023.122024.01</guid>
            <pubDate>Tue, 23 Jan 2024 06:16:01 GMT</pubDate>
            <description><![CDATA[<h1 id="프로젝트-총평">프로젝트 총평</h1>
<p>한달간 팀프로젝트가 마무리 되었습니다. 너무 시원 섭섭하군요...</p>
<p>지금까지 여러번의 프로젝트를 했지만 한 프로젝트에 이렇게 많은 프론트엔드가 있었던 적은 처음이여서 놀랍고 신선하며 재밌었어요. 
무엇보다 이번 팀원들의 개발 실력이 다들 뛰어나셔서 많은걸 배울 수 있었고 해보고싶은 것도 마음껏 해볼 수 있었습니다.</p>
<p>각자의 역할에 충실하며 책임감 있게 개발한 덕분에 프로젝트를 성공적으로 완성할 수 있었고 몇가지 이슈와 개선점들이 남아있지만 정상적으로 운용할 수 있었습니다.</p>
<p>기존에 하던 작업의 숙련도도 올릴 수 있었고, 처음해보는 작업을 하며 새로운 지식도 습득할 수 있는 행복한 시간이었어요🤗🤗</p>
<p>또한 개발 하는 과정내에서 여러 트러블 슈팅 경험을 만날 수 있었고 까먹지 않기 위해 기록을 했습니다.</p>
<p>이번 MIL에서는 팀프로젝트 내에서 경험하고 해결한 <a href="https://jae-hun-2.notion.site/a15aa184967c41f79ba246e6ceedd427?pvs=4">트러블 슈팅 기록 링크</a>를 공유하는 것으로 마무리 해보겠습니다.
(velog에는 토글 기능이 없어서 보기가 힘들어 노션 링크로 첨부할게요🥲)</p>
<hr>
<p>팀프로젝트 기간동안 함께해준 은수팀원분들, 은수 멘토님 너무너무너무 감사드리고 다들 조망간 또 만나요✋✋</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[프론트엔드 데브코스 회고 5기 MIL - 11.19~12.18]]></title>
            <link>https://velog.io/@jae-hun-e/%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C-%EB%8D%B0%EB%B8%8C%EC%BD%94%EC%8A%A4-%ED%9A%8C%EA%B3%A0-5%EA%B8%B0-MIL-11.1912.18</link>
            <guid>https://velog.io/@jae-hun-e/%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C-%EB%8D%B0%EB%B8%8C%EC%BD%94%EC%8A%A4-%ED%9A%8C%EA%B3%A0-5%EA%B8%B0-MIL-11.1912.18</guid>
            <pubDate>Fri, 29 Dec 2023 01:47:23 GMT</pubDate>
            <description><![CDATA[<p>프로그래머스 FE 데브코스를 시작한지 벌써 3개월이 지났다.(절반이나..!)
시간이 참 빠른것 같다. 이번 기간에는 강의를 통해 배우는 것보다 팀원들과 개인 프로젝트를 하면서 배운 것들이 많은 시간이었다. </p>
<p>강의 내에서는 박영웅 강사님의 Vue, 이선협 강사님의 React, storybook, graphQL 등을 배웠다. 
Vue는 사실 맛만 본 느낌이다 하지만 박영웅 강사님이 자세히 알려주시고 예시를 잘 보여주셔서 어렵지 않게 따라갈 수 있었고 성공적으로 과제를 마무리할 수 있었다. (어디가서 vue했다고는 못하지만 찍먹해봤다 말할 수 있을 정도..??)</p>
<h2 id="강의--과제">강의 + 과제</h2>
<p>사실 react 강의는 프로그래머스 강의내에서 가장 기대가 되었던 강의이다. 개인마다 코드 스타일이 달라서 무조건 맞다고는 할 수 없지만 나보다 훨씬 잘하시는 개발자들은 어떤식으로 작성하는지를 볼 수 있는 기회였고 storybook의 사용이유에 대해서도 조금은 회의적이었는데 강의를 듣고 여러 아티클들을 같이 찾아보면서 어떤 경우에 storybook을 사용하는게 좋을지 나만의 기존이 조금은 정해졌다.</p>
<p>그리고 react 과제를 할 때도 항상 라이브러리를 가져와 사용하던 것을 직접 구현하는 기회가 되었고, 다른 팀원들의 react 코드를 보면서 많이 배울 수 있었다. 가장 인상 깊었던 것은 팀원중 김성빈님의 코드였는데 그냥 어플리케이션을 구현한게 아니라 react-navigate같은 라이브러리로 구현하신게 신기하고 놀라웠다. </p>
<p>그래서 조금 용기를 얻어서 미루고 미뤄왔던 모노레포로 나만의 디자인 시스템을 만들어 npm에 올릴 계획을 하게되었다!!!!!(데브코스 끝나기 전까지는 꼭 완성해야지...!!)</p>
<h2 id="팀프로젝트">팀프로젝트</h2>
<p>지금까지 적지않은 팀프로젝트를 해봤지만 FE가 이렇게 많은 적은 처음이다. 사실 지금까지의 팀프로젝트에서 FE는 거의 혼자였다고 볼 수 있는데 여러명의 FE가 팀프로젝트를 할 수 있는 경험을 얻은것도 매우 좋다. 
덕분에 안해본 많은것들을 할 수 있었다.
이전까지는 마음대로 하던 것들에 대해서 협의를 하고 컨벤션을 맞췄다. 
<a href="https://www.notion.so/git-559b4b5960f54c75ab7f8373b494a2bd?pvs=4">git 컨벤션</a> 
<a href="https://www.notion.so/6f40ea4ef8b14997b07aeda67f43b8cc?pvs=4">개발 컨벤션</a></p>
<p>또한 각자의 선호도와 배우고싶은 것, 우리의 환경에 맞는지의 기준점을 토대로 <a href="https://docs.google.com/spreadsheets/d/1N2pev2P9CwRjcJA7uGDTMUDXvoXaDK5bPgiPBLvZVBg/edit#gid=0">기술 스택</a>도 정했다.</p>
<p>국밥인 것들, 요즘 핫 한것들 조합해서 사용을 해보기로 하였으며 멘토님과의 커피챗에서도 힙하다(?)라는 평을 받아서 내심 기분이 좋았다ㅎㅎㅎ </p>
<p>분명 이것저것 사건이 많았던 한달이었는데 기록이 습관화가 되지 않아서 휘발되어버린게 너무 아쉽다... 다음 MIL에서는 많은 내용을 담고 정리할 수 있도록 MIL 소스 메모장을 하나 정하고 날짜/키워드/감정을 간단하게라도 적어놔야겠다!! 팀프로젝트를 하면서 다음 MIL에서는 적을게 많을 것 같다ㅎㅎ</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[프론트엔드 데브코스 회고 5기 WIL - 10.19~11.18]]></title>
            <link>https://velog.io/@jae-hun-e/%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C-%EB%8D%B0%EB%B8%8C%EC%BD%94%EC%8A%A4-%ED%9A%8C%EA%B3%A0-5%EA%B8%B0-WIL-10.1911.18</link>
            <guid>https://velog.io/@jae-hun-e/%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C-%EB%8D%B0%EB%B8%8C%EC%BD%94%EC%8A%A4-%ED%9A%8C%EA%B3%A0-5%EA%B8%B0-WIL-10.1911.18</guid>
            <pubDate>Tue, 21 Nov 2023 03:43:00 GMT</pubDate>
            <description><![CDATA[<h1 id="이렇게-또-한달이">이렇게 또 한달이...</h1>
<p>빠르다 빨라,,, 세상 빠른 한달이 지나갔다. 배운 것도 많고 느낀 것도 많지만 지금 내 머리속에 가장 크게 자리잡아있는 것은 어떻게 하면 재사용성을 높히며 생성성을 높힐수 있는 구조로 컴포넌트를 짤까이다. 가장 유명하고 핫했던 &#39;아토믹 디자인 패턴&#39;을 제대로 사용하보는게 가장 큰 관심사이다. 그래서 이번 회고에서는 아토믹 디자인 패턴에 대한 내용이 대부분 들어가게되었다...ㅎㅎ 이 패턴을 맹신한다는 느낌보다는 이 패턴을 욕하기 위해서는 내가 직접 제대로 써보고 단점과 장점을 느껴야지 말할 수 있다고 생각하기 때문에 제대로 한번 써보려고 한다. </p>
<h3 id="keep">Keep</h3>
<p>이전부터 끈질기게 멘토님께 하나의 주제에 대해서 계속 물어보았다. 아토믹 디자인 패턴을 검색하면 가장 위에 뜬 글의 주인이 멘토님이셔서 빨대를 아주 깊게 꽂아야겠다는 생각으로ㅎㅎㅎㅎㅎ 아토믹 디자인 패턴을 제대로 경험해보기 위해서 노션 클로닝 과제부터 아토믹 디자인 패턴에 맞게끔 설계를 해보고있다. </p>
<p>이렇게 경험 해본 후 개인 프로젝트에 도입하여 조금 더 복잡한 프로젝트를 할 때 어떻게 사용하는게 좋은지, 컴포넌트를 나누는 기준은 어떻게 하는게 좋을 지, 재사용성을 향상하기 위해서 어떤식으로 설계해야하는지 공부중이다. </p>
<blockquote>
<p>아토믹 디자인 패턴 (+ compound component 패턴)</p>
</blockquote>
<p>정말 많은 글들과 많은 기업들의 레퍼런스를 찾아보며 한가지 확실해진 것은 brad frost의 아토믹 디자인 패턴은 하나의 가이드이고 은색탄환이 아니다. 자신의 상황에 맞게 변경하며 기준을 세워 사용하는 것을 알 수 있었다. (한가지 예시로 Line에서는 5단계가 아닌 atom, molecule, page 이렇게 나눠서 사용한다.)</p>
<p>또한 아토믹 디자인 만으로 사용하면 효과가 미미하고 복잡하기만 하다는 느낌을 받았다. 그래서 개발에 앞서 간단하게라도 피그마를 이용하서 디자인을 하고 storybook을 이용해서 디자인 시스템을 먼저 구축할 것이다. <a href="https://velog.io/@velopert/design-system-using-typescript-and-storybook">벨로그의 주인장 글</a>을 보며 따라가볼 예정이다. </p>
<p>그렇게 완전한 사이클을 겪어본 후 정말 재사용성과 생산성이 상승하였는지 몸으로 느껴볼 것이다. </p>
<h3 id="problem">Problem</h3>
<ol>
<li><p>처음 도입해보는 개념을 한번에 우르르 사용하다보니 여기저기에서 브레이크가 걸린다. 이번 프로젝트의 목표를 뽀족하게 정해야겠다.</p>
<p> 현재 새롭게 사용하고 있는 스팩들 중요도 순 </p>
<ul>
<li>아토믹 디자인 패턴에 맞게 구조설계</li>
<li>Next.js v13</li>
<li>MongoDB</li>
<li>S3</li>
<li>Tiny에디터<ul>
<li>⇒ 여기서 이미지 처리를 하느라 너무 많은 삽질과 시간을 보냈다. 일단 보류하고 우선순위대로 개발을 해보자</li>
</ul>
</li>
</ul>
</li>
<li><p>개인 프로젝트들을 하다보니 데브코스의 커리큘럼에 투자하던 시간이 저번달에 비해 많이 줄었다.. </p>
</li>
<li><p>요즘 알고리즘 문풀을 안한다…</p>
<ul>
<li>지금내가 가장 하고싶은거는?? 개인 프로젝트가 재밌다. 이거부터 하다보니 다른 걸 안한다ㅋㅋ,,</li>
</ul>
</li>
</ol>
<h3 id="try">Try</h3>
<ol>
<li>개인 프로젝트는 어떻게 이어나갈 것인가? <ol>
<li>storybook을 사용해서 디자인 시스템 컴포넌트들을 문서화한다.</li>
<li>Figma를 이용해서 화면설계를 먼저하고 컴포넌트들을 나눈 후 구현을 시작한다</li>
<li>material-UI를 참고하여 Atoms에 들어갈 컴포넌트와 디자인들을 구현한다 </li>
<li>Organism컴포넌트를 나누는 기준은 UI가 아닌 사용하는 데이터(모델) 단위로 나눈다</li>
<li>컨텍스트가 포함되어있지 않으면 Molecule로 분류하며 범용적인 네이밍을 사용한다</li>
<li>컨텍스트가 포함되어있으면 Organism으로 분류하며 네이밍에 포함한다</li>
<li>Layout은 외부에서 주입, UI가 조금씩 변경되야하는 컴포넌트는 compound component로 구현한다 </li>
</ol>
</li>
</ol>
<p>이런식으로 구성할 것이다. </p>
<ol>
<li><p>데브코스와의 비율을 어느정도로 둘 것인가? </p>
<ul>
<li>개인 공부는 일단 제쳐두고 코어시간에는 당일 강의부터 다 듣자! 실습을 다 따라하지 않더라도!!</li>
<li>그리고 남는 시간에 개인 공부를 하자!!!</li>
</ul>
</li>
<li><p>하고싶은 거를 뒤로 미루고 해야하는 거를 먼저하자!</p>
<p> 하루 일과를 아래와 같이 변경</p>
<ul>
<li>기상 ~ 코어시간 전 : 내가 하고싶은거</li>
<li>오늘 강의부터 다 듣고 정리</li>
<li>코딩 테스트 1문제 &amp;&amp; 1시간 이상</li>
<li>개인 프로젝트</li>
</ul>
</li>
</ol>
<p>생각지 못한 인턴, 신입 공고들이 종종 나오고 있다... 물론 자소서와 포폴도 중요하지만 흔들리지말고 내가 해보고싶은 것부터 완성하자!!(그냥 코테 연습느낌으로 보고오자~)</p>
<p>아자아자!! </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[블로그 뭐로 만들까?( Gatsby VS Next )]]></title>
            <link>https://velog.io/@jae-hun-e/%EB%B8%94%EB%A1%9C%EA%B7%B8-%EB%AD%90%EB%A1%9C-%EB%A7%8C%EB%93%A4%EA%B9%8C-Gatsby-VS-Next</link>
            <guid>https://velog.io/@jae-hun-e/%EB%B8%94%EB%A1%9C%EA%B7%B8-%EB%AD%90%EB%A1%9C-%EB%A7%8C%EB%93%A4%EA%B9%8C-Gatsby-VS-Next</guid>
            <pubDate>Wed, 01 Nov 2023 07:42:28 GMT</pubDate>
            <description><![CDATA[<p>기술 블로그를 만들때 가장 많이 쓰는 두 프레임워크를 비교하고 내가 뭐로 쓸 지 정할 거다!</p>
<h2 id="공통점">공통점</h2>
<ul>
<li>react 기반</li>
<li>JAMStack기반의 정적사이트 생성기 : Javascript와 HTML Markup된 정적인 페이지만을 제공한 후 필요하다면 API 호출해서 데이터 주입 ⇒ SEO해결</li>
</ul>
<h2 id="장단점">장단점</h2>
<table>
<thead>
<tr>
<th></th>
<th>Gatsby</th>
<th>Next</th>
</tr>
</thead>
<tbody><tr>
<td>렌더링 방식</td>
<td>SSG</td>
<td>SSG, SSR, CSR</td>
</tr>
<tr>
<td>API 호출 방식</td>
<td>GraphQL</td>
<td>마음대로</td>
</tr>
<tr>
<td>생태계</td>
<td>블로그에 필요한 플러그인 풍부</td>
<td>기본 플러그인이 비교적 부족</td>
</tr>
<tr>
<td>성능</td>
<td>- SSG성능이 더 높음</td>
<td></td>
</tr>
<tr>
<td>- 파일을 다 가지고 있어야 해서 커질 수록 불편함</td>
<td>- SSG성능이 더 낮음</td>
<td></td>
</tr>
<tr>
<td>- 파일 DB, S3에 저장하고 불러오기 쌉가능</td>
<td></td>
<td></td>
</tr>
</tbody></table>
<h2 id="내가-기술-블로그를-만드는-이유">내가 기술 블로그를 만드는 이유</h2>
<ol>
<li>FE개발자라면 내가 직접 만든 블로그 하나쯤은 있어야지?? <ol>
<li>만드는 속도 gatsby 승! </li>
<li>만드는 편의성 gatsby 승!</li>
</ol>
</li>
<li>계속 유지보수 하며 살을 붙여나갈 꺼야!<ol>
<li>추가 하고 싶은 기능이 많아질수록 플러그인의 의존도가 낮고 자유도가 높은 next 승!</li>
<li>데이터가 변경될 경우가 많아짐 next 승!</li>
</ol>
</li>
<li>포스터뿐만 아니라 이력서, 사이드 프로젝트 등 연습한 프로젝트들을 모두 담을 것이다 <ol>
<li>최종적으로는 모노레포로 할꺼야! next 승! </li>
<li>내가 앞으로 공부할게 뭐야? next 승!</li>
</ol>
</li>
</ol>
<p>2:4로 Next당첨! (사실 가장 큰 이유는 SSR…)</p>
<p>Next로 블로그 만들기는 next…</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[프론트엔드 데브코스 5기 WIL - 9.20~10.20 ]]></title>
            <link>https://velog.io/@jae-hun-e/%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C-%EB%8D%B0%EB%B8%8C%EC%BD%94%EC%8A%A4-5%EA%B8%B0-WIL-9.2010.20</link>
            <guid>https://velog.io/@jae-hun-e/%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C-%EB%8D%B0%EB%B8%8C%EC%BD%94%EC%8A%A4-5%EA%B8%B0-WIL-9.2010.20</guid>
            <pubDate>Sat, 21 Oct 2023 12:13:26 GMT</pubDate>
            <description><![CDATA[<h1 id="치트키다">치트키다..!</h1>
<p>정말 솔직히 말해서 프로그래머스 데브코스를 지원하기 전에는 국비지원에 대한 약간의 안좋은 감정과 불신이 있었다. </p>
<p>내가 국비지원에서 코치로 일했음에도 이러한 생각이 들었던 것은 수강생들의 이해도와는 별개로 너무 방대한 양을 빠르게 알려주기 때문에 제대로 이해하고 넘어가는 학생이 반도 안된다고 생각을 했기 때문이다. </p>
<p>&#39;프로그래머스 데브코스는 이해도를 체크하고 넘어가냐?&#39; 라고 묻는다면 그건 아니다. 라고 답할 것이다. 다른 국비 지원과 마찬가지로 내가 제대로 이해했는지 아닌지는 온전히 수강생들의 몫이다. </p>
<p>하지만 타 국비지원과의 차이점은 방향이라고 생각한다. 다양한 여러분야를 얕게 알려주기보단 트랙을 정해서 딱 그길에 필요한 정보를 더 딥하게 알려준다고 생각한다. </p>
<p>데브코스를 지원한 가장 큰 이유는 실무에 계신 훌륭하신 멘토님들과의 커피챗이었다. 데브코스에서 제공해주는 강의에 대한 기대치가 그리 높지는 않았었다. 수업을 듣으며 점점 생각이 바뀌었다. 
강의를 찍으신 강사님도 실무에서 많은 경험이 있으신 분들로써 간간히 실무에서 사용하는 팁, 어떤 코드가 좋은 코드이고 어떤 코드가 안좋은 코드인지에 대한 논리적인 생각 등 아주 주옥같은 팁들을 들을 수 있었다. </p>
<p>한 달이라는 짧은 기간 동안 배운 내용들이 혼자서 독학 할 때 스스로 고민하며 결론 짓지 못하던 문제들에 답을 찾게 해주었고, 어느 방향으로 가야 답을 찾을 수 있는지 이정표를 제공해주었다. </p>
<h2 id="강의에서-새로-배운-내용">강의에서 새로 배운 내용</h2>
<h3 id="의존성-낮추기">의존성 낮추기</h3>
<p>에를들어 버튼을 클릭했을 때 발생하는 행동을 컴포넌트 내부에서 정의하는것이 아닌 외부로부터 주입받아 사용하는 것이다.
이렇게 되면 컴포넌트는 버튼이 클릭되었을때 이벤트를 트리거 역할만 할 뿐 안에서 어떤일이 발생하는지는 알지 못하며 발생하는일은 이 컴포넌트를 호출한 곳에서 정의해준다 
이렇게 의존성을 줄인다. </p>
<p>프론트엔드에서 사용하는 DI로 볼 수 있지 않을까..?</p>
<h3 id="이벤트-델리게이션">이벤트 델리게이션</h3>
<p>이벤트 버블링, 캡처링 개념은 알았지만 딱히 써먹어본적은 없었다. 토스 Next23에서 과제문제를 풀면서 이벤트 캡처링은 이용해야하는 구현을 마주쳤을때의 당혹감이란...
이벤트 델리게이션이란 상위 태그에 이벤트를 걸고 이벤트 버블링을 이용해서 클릭이벤트에 대한 분기처리를 하는 방식이다. 
이를 통해 각 태그에 이벤트를 걸어줄 필요없이 한 곳에서 이벤트를 처리 할 수 있다는 장점고 미래에 생길 자식 태그까지 처리 할 수 있다는 장점이 있다. </p>
<h3 id="커스텀-이벤트">커스텀 이벤트</h3>
<p>이런게 있다는 것도 몰랐다.... 우왕,,,내가 필요한 이벤트를 직접 만들어서 등록해줄 수 있다니... 오호,,,</p>
<p>이를 사용하는 방법은 커스텀 이벤트를 만들어주고 이벤트가 실행됬으면 곳에서 dispatchEvent에서 new CustomEvent을 통해 커스텀 이벤트를 호출하는 식으로 사용할 수 있다. </p>
<pre><code class="language-javascript">export const initRouter = (onRoute) =&gt; {
  window.addEventListener(ROUTE_CHANGE_EVENT_NAME, (e) =&gt; {
    const { nextUrl } = e.detail;
    if (!nextUrl) return;
    history.pushState(null, null, nextUrl);

    onRoute();
  });
};

export const push = (nextUrl) =&gt; {
  window.dispatchEvent(
    new CustomEvent(ROUTE_CHANGE_EVENT_NAME, { detail: { nextUrl } })
  );
};</code></pre>
<p>이렇게 하면 의존성을 외부로 부터 주입받는 경우 여러depth를 통하면 props drill이 생기는 것을 막고 상단에 커스텀 이벤트를 만들고 자식들이 사용시 dispatchEvent를 이용해서 호출할 수 있다. (동작을 전역 상태로 관리하는 느낌..!)</p>
<h3 id="단반향-데이터-흐름">단반향 데이터 흐름</h3>
<p>단방향 데이터 흐름인 Flux패턴을 기반으로 한 redux, recoil, contextAPI 모두 사용해 보았지만 바닐라JS로 이를 단방향 데이터 흐름을 생각해본적은 없었다. 
정말 단순하게 생각하면 데이터를 다르는 상위 컴포넌트를 정하고 하위 컴포넌트에서는 트리거 역할만 하며 
데이터를 처리하는 로직은 상위 컴포넌트가 담고있다.
이를 통해 하위 컴포넌트에서는 상위의 데이터를 변경하지 않도록 하여 
상위에서 변경된 데이터를 하위로 내려주는 형태인 단방향 데이터 흐름을 만들 수 있다. </p>
<h2 id="커피챗으로-삼행시-조지겠습니다">커피챗으로 삼행시 조지겠습니다.</h2>
<p>정말 기대 이상 이었다...!!! 내가 공부하며 이해가 안되는 것들, 고민이 되는 것들을 현업에서는 어떻게 풀어나가고 있는지를 들을 수 있었으며 
가장 소오오오름이 돋았던 것은 지난 학기 소프트웨어 공학 수업에서 프로젝트의 FE팀장 역할을 맡으며 구조를 잡을 때 아주 애먹으며 가장 많이 참고했던 카카오페이지 기술블로그의 아토믹 디자인 패턴 글을 쓰신 분이 나의 멘토님이셨다...!!!!!!!!</p>
<p>멘토님께 질문을 하며 멘토님과 멘토님의 팀원분들도 나와 같은 고민들을 하셨었구나, 그리고 이런식으로 해결을 했구나 등을 배울 수 있는 시간이었다. 빨리 프로젝트를 하며 실제로 마주치는 문제들로 멘토님께 더 많이 물어보고 더 많이 배우고 싶다ㅎㅎ </p>
<p>커 : 커피 한 잔의 여유...❤️
피 : 피가 되고 살이 되는 나의 멘토...❤️
챗 : 챗지피티.</p>
<p>장난입니다. </p>
<p>멘토님 너무 감사해요ㅜㅜ 하나라도 더 알려주시려고 하시는 멘토님의 열정에 학구열이 불타며 멘토님같은 사수를 만날 수 있도록 더욱 노력해야겠다는 생각이 들었습니다ㅎㅎ</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[백준  14248 JS 풀이]]></title>
            <link>https://velog.io/@jae-hun-e/%EB%B0%B1%EC%A4%80-14248-JS-%ED%92%80%EC%9D%B4</link>
            <guid>https://velog.io/@jae-hun-e/%EB%B0%B1%EC%A4%80-14248-JS-%ED%92%80%EC%9D%B4</guid>
            <pubDate>Thu, 17 Aug 2023 05:05:38 GMT</pubDate>
            <description><![CDATA[<h2 id="구하는-값">구하는 값</h2>
<p>범위 내에서 자리 값만큼 점프하며 방문할 수 있는 자리 수 </p>
<h2 id="핵심-아이디어">핵심 아이디어</h2>
<p>dfs, bfs로 탐색함</p>
<p>3가지 방식으로 풀어봤음</p>
<h2 id="bfs-array-코드">BFS-array 코드</h2>
<pre><code class="language-jsx">const input = require(&quot;fs&quot;).readFileSync(&quot;dev/stdin&quot;).toString().trim().split(&quot;\n&quot;);

const n = Number(input[0]);
const graph = [0, ...input[1].split(&quot; &quot;).map(Number)];
const str = Number(input[2]);
const visited = new Array(n + 1).fill(false);

// bfs 풀이 - array
const que = [];
que.push(str);
visited[str] = true;

while (que.length) {
    const cur = que.shift();

    for (const d of [-1, 1]) {
        const next = cur + d * graph[cur];

        if (next &lt;= 0 || next &gt; n) continue;
        if (!visited[next]) {
            que.push(next);
            visited[next] = true;
        }
    }
}
console.log(visited.filter((v) =&gt; v).length);</code></pre>
<h2 id="bfs-que-코드">BFS-que 코드</h2>
<pre><code class="language-jsx">const input = require(&quot;fs&quot;).readFileSync(&quot;dev/stdin&quot;).toString().trim().split(&quot;\n&quot;);

const n = Number(input[0]);
const graph = [0, ...input[1].split(&quot; &quot;).map(Number)];
const str = Number(input[2]);
const visited = new Array(n + 1).fill(false);

// bfs 풀이 - que
class Que {
    q = [];
    h = 0;
    t = 0;
    push(v) {
        this.q[this.t++] = v;
    }
    shift() {
        const v = this.q[this.h];
        delete this.q[this.h++];
        return v;
    }
    length() {
        return this.t - this.h;
    }
}
const que = new Que();
que.push(str);
visited[str] = true;

while (que.length()) {
    const cur = que.shift();

    for (const d of [-1, 1]) {
        const next = cur + d * graph[cur];

        if (next &lt;= 0 || next &gt; n) continue;
        if (!visited[next]) {
            que.push(next);
            visited[next] = true;
        }
    }
}
console.log(visited.filter((v) =&gt; v).length);</code></pre>
<h2 id="dfs-코드">DFS 코드</h2>
<pre><code class="language-jsx">const input = require(&quot;fs&quot;).readFileSync(&quot;dev/stdin&quot;).toString().trim().split(&quot;\n&quot;);

const n = Number(input[0]);
const graph = [0, ...input[1].split(&quot; &quot;).map(Number)];
const str = Number(input[2]);
const visited = new Array(n + 1).fill(false);

// dfs 풀이
const dfs = (cur) =&gt; {
    visited[cur] = true;

    for (const d of [-1, 1]) {
        const next = cur + d * graph[cur];

        if (next &lt;= 0 || next &gt; n) continue;
        if (!visited[next]) dfs(next);
    }
};
dfs(str);
console.log(visited.filter((v) =&gt; v).length);</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[백준 2178 JS 풀이]]></title>
            <link>https://velog.io/@jae-hun-e/%EB%B0%B1%EC%A4%80-2178-JS-%ED%92%80%EC%9D%B4</link>
            <guid>https://velog.io/@jae-hun-e/%EB%B0%B1%EC%A4%80-2178-JS-%ED%92%80%EC%9D%B4</guid>
            <pubDate>Thu, 17 Aug 2023 05:05:28 GMT</pubDate>
            <description><![CDATA[<h2 id="구하는-값">구하는 값</h2>
<p>(0,0)에서 길따라 (n,m)까지 가는 최단거리</p>
<h2 id="핵심-아이디어">핵심 아이디어</h2>
<p>간선 같은 최단거리 ⇒ BFS</p>
<p>graph에 방문하면 0으로 바꿔주면서 방문체크 </p>
<p>que에 좌표랑 dep 같이 저장</p>
<h2 id="코드">코드</h2>
<pre><code class="language-jsx">const input = require(&quot;fs&quot;).readFileSync(&quot;dev/stdin&quot;).toString().trim().split(&quot;\n&quot;);

const [n, m] = input[0].split(&quot; &quot;).map(Number);
const graph = [];
for (let i = 1; i &lt;= n; i++) graph.push(input[i].split(&quot;&quot;).map(Number));

const queue = [];
queue.push([0, 0, 0]);
graph[0][0] = 0;

const dx = [-1, 1, 0, 0],
    dy = [0, 0, -1, 1];

let cnt = 0;
while (queue.length &gt; 0) {
    const [y, x, cur] = queue.shift();

    if (y === n - 1 &amp;&amp; x === m - 1) {
        console.log(cur + 1);
        break;
    }
    for (let i = 0; i &lt; 4; i++) {
        const nx = x + dx[i],
            ny = y + dy[i];

        if (nx &lt; 0 || nx &gt;= m || ny &lt; 0 || ny &gt;= n) continue;

        if (graph[ny][nx]) {
            queue.push([ny, nx, cur + 1]);
            graph[ny][nx] = 0;
        }
    }
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[백준 24444 JS 풀이]]></title>
            <link>https://velog.io/@jae-hun-e/%EB%B0%B1%EC%A4%80-24444-JS-%ED%92%80%EC%9D%B4</link>
            <guid>https://velog.io/@jae-hun-e/%EB%B0%B1%EC%A4%80-24444-JS-%ED%92%80%EC%9D%B4</guid>
            <pubDate>Tue, 15 Aug 2023 05:22:48 GMT</pubDate>
            <description><![CDATA[<h2 id="구하는-값">구하는 값</h2>
<p>bfs로 접근하는 노드 순서</p>
<h2 id="핵심-아이디어">핵심 아이디어</h2>
<p>bfs 기초^^ 주의할점은 인접리스트 오름차순정렬부터 해야함</p>
<h2 id="코드">코드</h2>
<pre><code class="language-jsx">const input = require(&quot;fs&quot;).readFileSync(&quot;dev/stdin&quot;).toString().trim().split(&quot;\n&quot;);

const [n, m, r] = input[0].split(&quot; &quot;).map(Number);
const graph = Array.from({ length: n + 1 }, () =&gt; []);
for (let i = 1; i &lt;= m; i++) {
    const [a, b] = input[i].split(&quot; &quot;).map(Number);
    graph[a].push(b);
    graph[b].push(a);
}
graph.forEach((line) =&gt; line.sort((a, b) =&gt; a - b));
// console.log(graph);
const visited = new Array(n + 1).fill(0);

const queue = [];
queue.push(r);
visited[r] = 1;

let step = 1;
while (queue.length) {
    const cur = queue.shift();

    for (const next of graph[cur]) {
        if (!visited[next]) {
            queue.push(next);
            visited[next] = ++step;
        }
    }
}

console.log(visited.slice(1).join(&quot;\n&quot;));</code></pre>
<p>class로 구현이 훨씬 빠름</p>
<h2 id="코드-1">코드</h2>
<pre><code class="language-jsx">const input = require(&quot;fs&quot;).readFileSync(&quot;dev/stdin&quot;).toString().trim().split(&quot;\n&quot;);

class Que {
    q = [];
    h = 0;
    t = 0;
    enque(v) {
        this.q[this.t++] = v;
    }
    deque() {
        const v = this.q[this.h];
        delete this.q[this.h++];
        return v;
    }
    size() {
        return this.t - this.h;
    }
}

const [n, m, r] = input[0].split(&quot; &quot;).map(Number);
const graph = Array.from({ length: n + 1 }, () =&gt; []);
for (let i = 1; i &lt;= m; i++) {
    const [a, b] = input[i].split(&quot; &quot;).map(Number);
    graph[a].push(b);
    graph[b].push(a);
}
graph.forEach((line) =&gt; line.sort((a, b) =&gt; a - b));
// console.log(graph);
const visited = new Array(n + 1).fill(0);

const queue = new Que();
queue.enque(r);
visited[r] = 1;

let step = 1;
while (queue.size()) {
    const cur = queue.deque();

    for (const next of graph[cur]) {
        if (!visited[next]) {
            queue.enque(next);
            visited[next] = ++step;
        }
    }
}

console.log(visited.slice(1).join(&quot;\n&quot;));</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[백준 1389 JS 풀이]]></title>
            <link>https://velog.io/@jae-hun-e/%EB%B0%B1%EC%A4%80-1389-JS-%ED%92%80%EC%9D%B4</link>
            <guid>https://velog.io/@jae-hun-e/%EB%B0%B1%EC%A4%80-1389-JS-%ED%92%80%EC%9D%B4</guid>
            <pubDate>Tue, 15 Aug 2023 05:22:39 GMT</pubDate>
            <description><![CDATA[<h2 id="구하는-값">구하는 값</h2>
<p>케빈 베이컨 단계 합의 최소값</p>
<h2 id="핵심-아이디어">핵심 아이디어</h2>
<ol>
<li>양방향 인접리스트를 만듬</li>
<li>길이 n+1의 visited 배열을 -1로 초기화하고 각 자리에 방문시 몇번째로 방문했는지 기록할거임</li>
<li>1~n까지 각각 bfs를 돌며 visited배열을 만들어주고 배열의 총합 -1을 sumArr에 기록</li>
<li>sumArr의 최소값을 가지는 첫번째 idx 출력</li>
</ol>
<h2 id="코드">코드</h2>
<pre><code class="language-jsx">const input = require(&#39;fs&#39;).readFileSync(&#39;dev/stdin&#39;).toString().trim().split(&#39;\n&#39;)

class Que {
    q = [];
    h = 0;
    t = 0;
    enque(v) {
        this.q[this.t++] = v;
    }
    deque() {
        const v = this.q[this.h];
        delete this.q[this.h++];
        return v;
    }
    size() {
        return this.t - this.h;
    }
}

const [n, m] = input[0].split(&quot; &quot;).map(Number);
const graph = Array.from({ length: n + 1 }, () =&gt; []);
for (let i = 1; i &lt;= m; i++) {
    const [a, b] = input[i].split(&quot; &quot;).map(Number);
    graph[a].push(b);
    graph[b].push(a);
}
// console.log(graph);

const sumArr = [1e9];
function bfs(str, visited) {
    const que = new Que();
    que.enque(str);
    visited[str] = 0;

    while (que.size()) {
        const cur = que.deque();

        for (const next of graph[cur]) {
            if (visited[next] === -1) {
                que.enque(next);
                visited[next] = visited[cur] + 1;
            }
        }
    }
    // console.log(&quot;visited&quot;, visited);
    return visited.reduce((a, b) =&gt; (a += b), 0) + 1;
}

for (let i = 1; i &lt;= n; i++) {
    const visited = new Array(n + 1).fill(-1);
    sumArr.push(bfs(i, visited));
}

// console.log(sumArr);

const min = Math.min(...sumArr);
console.log(sumArr.findIndex((v) =&gt; v === min));</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[백준 5014 JS 풀이]]></title>
            <link>https://velog.io/@jae-hun-e/%EB%B0%B1%EC%A4%80-5014-JS-%ED%92%80%EC%9D%B4</link>
            <guid>https://velog.io/@jae-hun-e/%EB%B0%B1%EC%A4%80-5014-JS-%ED%92%80%EC%9D%B4</guid>
            <pubDate>Mon, 14 Aug 2023 11:03:57 GMT</pubDate>
            <description><![CDATA[<h2 id="구하는-값">구하는 값</h2>
<p>원하는 층까지 이동하는데 걸리는 횟수</p>
<h2 id="핵심-아이디어">핵심 아이디어</h2>
<ol>
<li>F+1길이의 arr를 만들어서 각 자리에 몇번째에 방문했는지 기록 초기값은 -1로 해서 방문하지 않았으면 -1 그대로임</li>
<li>bfs를 통해 시작점에서부터  +U, -D 두가지 경우로 다음 층으로 이동</li>
<li>arr[g]가 -1이면 방문하지 못한거고 아니면 arr[g]에 몇번째 방문인지 기록되어있을테니 출력</li>
</ol>
<h2 id="코드">코드</h2>
<pre><code class="language-jsx">const input = require(&#39;fs&#39;).readFileSync(&#39;dev/stdin&#39;).toString().trim().split(&#39;\n&#39;)

class Que {
    q = [];
    h = 0;
    t = 0;
    enque(v) {
        this.q[this.t++] = v;
    }
    deque() {
        const v = this.q[this.h];
        delete this.q[this.h++];
        return v;
    }
    size() {
        return this.t - this.h;
    }
}

const [f, s, g, u, d] = input[0].split(&quot; &quot;).map(Number);
const visited = new Array(f + 1).fill(-1);
const que = new Que();
que.enque(s);
visited[s] = 0;

while (que.size()) {
    const cur = que.deque();

    for (const action of [u, d]) {
        const next = action === u ? cur + u : cur - d;

        if (next &lt; 1 || next &gt; f) continue;
        if (visited[next] === -1) {
            que.enque(next);
            visited[next] = visited[cur] + 1;
        }
    }
}

console.log(visited[g] &lt; 0 ? &quot;use the stairs&quot; : visited[g]);</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[백준 11060 JS 풀이]]></title>
            <link>https://velog.io/@jae-hun-e/%EB%B0%B1%EC%A4%80-11060-JS-%ED%92%80%EC%9D%B4</link>
            <guid>https://velog.io/@jae-hun-e/%EB%B0%B1%EC%A4%80-11060-JS-%ED%92%80%EC%9D%B4</guid>
            <pubDate>Mon, 14 Aug 2023 11:03:49 GMT</pubDate>
            <description><![CDATA[<h2 id="구하는-값">구하는 값</h2>
<p>점프해서 원하는 곳 까지 몇번만에 가는지</p>
<h2 id="핵심-아이디어">핵심 아이디어</h2>
<p>que에 idx와 step을 같이 넣어서 bfs로 돌림</p>
<h2 id="코드">코드</h2>
<pre><code class="language-jsx">const input = require(&#39;fs&#39;).readFileSync(&#39;/dev/stdin&#39;).toString().trim().split(&#39;\n&#39;)

class Que {
    q = [];
    h = 0;
    t = 0;
    enque(v) {
        this.q[this.t++] = v;
    }
    deque() {
        const v = this.q[this.h];
        delete this.q[this.h++];
        return v;
    }
    size() {
        return this.t - this.h;
    }
}

const n = Number(input[0]);
const arr = [0, ...input[1].split(&quot; &quot;).map(Number)];
const visited = new Array(n + 1).fill(false);
// console.log(arr);

const que = new Que();
que.enque([1, 0]);
visited[1] = true;

let ans = -1;
while (que.size()) {
    const [cur, dep] = que.deque();

    if (cur === n) {
        ans = dep;
        break;
    }
    if (cur &gt; n || arr[cur] === 0) continue;

    for (let i = 1; i &lt;= arr[cur]; i++) {
        if (!visited[cur + i]) {
            que.enque([cur + i, dep + 1]);
            visited[cur + i] = true;
        }
    }
}

console.log(ans);</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[백준 16948 JS 풀이]]></title>
            <link>https://velog.io/@jae-hun-e/%EB%B0%B1%EC%A4%80-16948-JS-%ED%92%80%EC%9D%B4</link>
            <guid>https://velog.io/@jae-hun-e/%EB%B0%B1%EC%A4%80-16948-JS-%ED%92%80%EC%9D%B4</guid>
            <pubDate>Sun, 13 Aug 2023 06:50:42 GMT</pubDate>
            <description><![CDATA[<h2 id="구하는-값">구하는 값</h2>
<p>데스 나이트로 갈 수 있음?</p>
<h2 id="핵심-아이디어">핵심 아이디어</h2>
<p>데스 나이트 이동경로를 array로 만들고 상하좌우 돌릴때랑 똑같이 하면됨</p>
<p>(주의, y,x 주의할 것)</p>
<h2 id="코드">코드</h2>
<pre><code class="language-jsx">const input = require(&#39;fs&#39;).readFileSync(&#39;/dev/stdin&#39;).toString().trim().split(&#39;\n&#39;)

class Que {
    q = [];
    h = 0;
    t = 0;
    enque(v) {
        this.q[this.t++] = v;
    }
    deque() {
        const v = this.q[this.h];
        delete this.q[this.h++];
        return v;
    }
    size() {
        return this.t - this.h;
    }
}

const dx = [-2, -2, 0, 0, 2, 2],
    dy = [-1, 1, -2, 2, -1, 1];

const n = Number(input[0]);
const [r1, c1, r2, c2] = input[1].split(&quot; &quot;).map(Number);
const graph = Array.from({ length: n }, () =&gt; new Array(n).fill(false));
let ans = -1;

const bfs = () =&gt; {
    const que = new Que();
    que.enque([c1, r1, 0]);
    graph[c1][r1] = true;
    while (que.size()) {
        const [y, x, dep] = que.deque();
        // console.log(&quot;y,x&quot;, y, x);
        if (y === c2 &amp;&amp; x === r2) {
            ans = dep;
            break;
        }

        for (let i = 0; i &lt; 6; i++) {
            const nx = x + dx[i],
                ny = y + dy[i];

            if (nx &lt; 0 || nx &gt;= n || ny &lt; 0 || ny &gt;= n) continue;

            if (!graph[ny][nx]) {
                que.enque([ny, nx, dep + 1]);
                graph[ny][nx] = true;
            }
        }
    }
};

bfs();
console.log(ans);</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[백준 1003 JS 풀이]]></title>
            <link>https://velog.io/@jae-hun-e/%EB%B0%B1%EC%A4%80-1003-JS-%ED%92%80%EC%9D%B4</link>
            <guid>https://velog.io/@jae-hun-e/%EB%B0%B1%EC%A4%80-1003-JS-%ED%92%80%EC%9D%B4</guid>
            <pubDate>Sun, 13 Aug 2023 06:50:34 GMT</pubDate>
            <description><![CDATA[<h2 id="구하는-값">구하는 값</h2>
<p>피보나치 구할 때 0, 1 번째 값 몇번 사용하는지</p>
<h2 id="핵심-아이디어">핵심 아이디어</h2>
<p>피보나치 1,2,3,4,5 하다보면 규칙이 보임</p>
<p>fibo[1] = fibo[1] , fibo[2] = fibo[0] + fibo[1] 이고 그 이후는 이전 값을 사용하기 때문에 </p>
<p>피보나치 n을 구할 때 0번째 값은 fibo[n-1]의 값과 동일하고, 1번째 값은 fibo[n]의 값과 동일함 </p>
<p>따라서 0, 1 번째가 사용된 횟수는 fibo[n-1],  fibo[n]값을 구해주면 됨</p>
<h2 id="코드">코드</h2>
<pre><code class="language-jsx">const input = require(&quot;fs&quot;).readFileSync(&quot;dev/stdin&quot;).toString().trim().split(&quot;\n&quot;);

let ts = input[0] * 1;
let line = 1;
while (ts--) {
    const n = input[line++] * 1;

    if (n === 0) {
        console.log(1, 0);
        continue;
    }

    const d = new Array(n).fill(0);

    d[0] = 0;
    d[1] = 1;

    for (let i = 2; i &lt;= n; i++) {
        d[i] = d[i - 1] + d[i - 2];
    }
    console.log(d[n - 1], d[n]);
}</code></pre>
<p>처음엔 재귀를 사용해서 하향식을 썼지만 시간초과뜸 그래서 반복문 형태인 상향식으로 바꿈</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[백준 1904 JS 풀이]]></title>
            <link>https://velog.io/@jae-hun-e/%EB%B0%B1%EC%A4%80-1904-JS-%ED%92%80%EC%9D%B4</link>
            <guid>https://velog.io/@jae-hun-e/%EB%B0%B1%EC%A4%80-1904-JS-%ED%92%80%EC%9D%B4</guid>
            <pubDate>Fri, 11 Aug 2023 15:12:26 GMT</pubDate>
            <description><![CDATA[<h2 id="구하는-값">구하는 값</h2>
<p>00, 1 을 이용해서 표현할 수 있는 n자릿수의 2진수 개수</p>
<h2 id="핵심-아이디어">핵심 아이디어</h2>
<p>n에 1,2,3,4,5, … 넣다보면 규칙이보임 이거 피보나치다..!</p>
<p>그 뒤는 스무스하게 피보나치 구현</p>
<h2 id="코드">코드</h2>
<pre><code class="language-jsx">const input = require(&#39;fs&#39;).readFileSync(&#39;dev/stdin&#39;).toString().trim().split(&quot;\n&quot;)

const n = input[0] * 1;

// 점화식이 피보나치랑 동일

const d = new Array(n + 1).fill(0);
d[1] = 1;
d[2] = 2;

for (let i = 3; i &lt;= n; i++) {
    d[i] = (d[i - 1] + d[i - 2]) % 15746;
}
console.log(d[n]);</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[백준 2156 JS 풀이]]></title>
            <link>https://velog.io/@jae-hun-e/%EB%B0%B1%EC%A4%80-2156-JS-%ED%92%80%EC%9D%B4</link>
            <guid>https://velog.io/@jae-hun-e/%EB%B0%B1%EC%A4%80-2156-JS-%ED%92%80%EC%9D%B4</guid>
            <pubDate>Fri, 11 Aug 2023 15:12:17 GMT</pubDate>
            <description><![CDATA[<h2 id="구하는-값">구하는 값</h2>
<p>포도주 가장 많이 마시는 방법 </p>
<p>근데 연속해서 3개는 마실 수 없다는 조건이 있음</p>
<h2 id="핵심-아이디어">핵심 아이디어</h2>
<p>점화식을 구해보면 </p>
<p>n번째 포도주에 도달할 수 있는 경우의 수는 3가지로 그 중 가장 큰 값이 DPtable[n]이 된다.</p>
<ol>
<li>n번째를 안마시는 경우 → n-1번째 도달한 경우중 가장 큰 값 d[n-1]</li>
<li>n번째를 마시는데 n-1번째를 마시는 경우 → n과 n-1을 마시는 경우이므로 n-3번째에 도달 한 경우 중 가장 큰값 d[n-3]에 n, n-1번째 값을 더한 값 </li>
<li>n번째를 마시는데 n-2번째를 마시는 경우 → n과 n-2을 마시는 경우이므로 n-3번째에 도달 한 경우 중 가장 큰값 d[n-2]에 n번째 값을 더한 값 </li>
</ol>
<p>즉 <code>d[i] = Math.max(d[i - 1], d[i - 2] + graph[i], d[i - 3] + graph[i] + graph[i - 1])</code> 가 됨 </p>
<p>초기값을 3개 구해주고 DP ㄱㄱ</p>
<h2 id="코드">코드</h2>
<pre><code class="language-jsx">const input = require(&quot;fs&quot;).readFileSync(&quot;dev/stdin&quot;).toString().trim().split(&quot;\n&quot;);

const n = input[0] * 1;
const d = new Array(n).fill(0);

const graph = [];
for (let i = 1; i &lt;= n; i++) graph.push(input[i] * 1);
// console.log(&quot;graph&quot;, graph);

d[0] = graph[0];
d[1] = graph[0] + graph[1];
d[2] = Math.max(graph[0] + graph[1], graph[0] + graph[2], graph[1] + graph[2]);

// console.log(d);
for (let i = 3; i &lt; n; i++) {
    // 점화식 -&gt; n 칸 도달하는 경우 3가지 중 가장 큰값
    d[i] = Math.max(d[i - 1], d[i - 2] + graph[i], d[i - 3] + graph[i] + graph[i - 1]);
}

console.log(d[n - 1]);</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[백준 2670 JS 풀이]]></title>
            <link>https://velog.io/@jae-hun-e/%EB%B0%B1%EC%A4%80-2670-JS-%ED%92%80%EC%9D%B4</link>
            <guid>https://velog.io/@jae-hun-e/%EB%B0%B1%EC%A4%80-2670-JS-%ED%92%80%EC%9D%B4</guid>
            <pubDate>Thu, 10 Aug 2023 09:26:30 GMT</pubDate>
            <description><![CDATA[<h2 id="구하는-값">구하는 값</h2>
<p>한개 이상의 연속된 수들의 곱의 최대값</p>
<h2 id="핵심-아이디어">핵심 아이디어</h2>
<p>dp[i]를 i를 마지막 인덱스로 하는 연속곱의 최대값이라 정의하자</p>
<p>주의할 점은 i번째 인덱스 값을 무시하고 넘어갈 수 없다.</p>
<p>즉, d[i-1], d[i-1] * arr[i], arr[i] 를 비교하는게 아니라 </p>
<p><strong>d[i-1] * arr[i], arr[i]</strong> 를 비교하는거다!!!!!!!!</p>
<p>이거 때문에 실버 4문제가지고 1시간 넘게 맞왜틀 해버렸다…</p>
<p>문제를 잘 파악하자ㅠㅠ </p>
<p>저거를 토대로 점화식을 세우면 </p>
<p>d[i] = Math.max(d[i-1] * arr[i], d[i]) 가 된다. </p>
<h2 id="코드">코드</h2>
<pre><code class="language-jsx">const input = require(&quot;fs&quot;).readFileSync(&quot;dev/stdin&quot;).toString().trim().split(&quot;\n&quot;);

const n = input[0] * 1;
const d = input.slice(1).map(Number);

for (let i = 1; i &lt; n; i++) {
    d[i] = Math.max(d[i], d[i - 1] * d[i]);
}

console.log(Math.max(...d).toFixed(3));</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[백준 2302 JS 풀이]]></title>
            <link>https://velog.io/@jae-hun-e/%EB%B0%B1%EC%A4%80-2302-JS-%ED%92%80%EC%9D%B4</link>
            <guid>https://velog.io/@jae-hun-e/%EB%B0%B1%EC%A4%80-2302-JS-%ED%92%80%EC%9D%B4</guid>
            <pubDate>Thu, 10 Aug 2023 09:26:20 GMT</pubDate>
            <description><![CDATA[<h2 id="구하는-값">구하는 값</h2>
<p>VIP좌석을 기준으로 나눠져있는 좌석에 인원 배치하는 경우의 수</p>
<h2 id="핵심-아이디어">핵심 아이디어</h2>
<p>각 그룹의 묶음의 경우의수를 곱해주면 됨</p>
<p>근데 이 묶음의 경우의수가 피보나치 수랑 동일함 </p>
<h2 id="코드">코드</h2>
<pre><code class="language-jsx">const input = require(&quot;fs&quot;).readFileSync(&quot;dev/stdin&quot;).toString().trim().split(&quot;\n&quot;);

const n = input[0] * 1;
const cnt = input[1] * 1;

// 점화식 피보나치
const d = new Array(n).fill(0);

d[0] = 1;
d[1] = 1;

for (let i = 2; i &lt;= n; i++) {
    d[i] = d[i - 1] + d[i - 2];
}

const pick = [0];
for (let i = 2; i &lt; cnt + 2; i++) pick.push(input[i] * 1);
pick.push(n + 1);

let total = 1;

for (let i = 0; i &lt;= cnt; i++) {
    total *= d[pick[i + 1] - pick[i] - 1];
}

console.log(total);</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[백준 7576 JS 풀이]]></title>
            <link>https://velog.io/@jae-hun-e/%EB%B0%B1%EC%A4%80-7576-JS-%ED%92%80%EC%9D%B4</link>
            <guid>https://velog.io/@jae-hun-e/%EB%B0%B1%EC%A4%80-7576-JS-%ED%92%80%EC%9D%B4</guid>
            <pubDate>Wed, 09 Aug 2023 15:31:20 GMT</pubDate>
            <description><![CDATA[<h2 id="구하는-값">구하는 값</h2>
<p>토마토 다 익을때까지 걸리는 시간</p>
<h2 id="핵심-아이디어">핵심 아이디어</h2>
<p>익은 토마토를 que에 넣고 bfs를 돌린 후 가장 마지막 dep를 출력</p>
<p>만약 0이 남아있다면 0을 출력</p>
<h2 id="코드">코드</h2>
<pre><code class="language-jsx">const input = require(&quot;fs&quot;).readFileSync(&quot;dev/stdin&quot;).toString().trim().split(&quot;\n&quot;);

class Que {
    q = [];
    h = 0;
    t = 0;
    enque(v) {
        this.q[this.t++] = v;
    }
    deque() {
        const v = this.q[this.h];
        delete this.q[this.h++];
        return v;
    }
    size() {
        return this.t - this.h;
    }
}

const [m, n] = input[0].split(&quot; &quot;).map(Number);
const graph = [];
const que = new Que();

for (let i = 1; i &lt;= n; i++) {
    const line = input[i].split(&quot; &quot;).map(Number);
    line.forEach((v, j) =&gt; {
        if (v === 1) que.enque([i - 1, j, 0]);
    });
    graph.push(line);
}
// console.log(graph, que);

const dx = [-1, 1, 0, 0],
    dy = [0, 0, -1, 1];

let ans = 0;
while (que.size()) {
    const [y, x, d] = que.deque();
    ans = d;

    for (let i = 0; i &lt; 4; i++) {
        const nx = x + dx[i],
            ny = y + dy[i];

        if (nx &lt; 0 || nx &gt;= m || ny &lt; 0 || ny &gt;= n) continue;
        if (!graph[ny][nx]) {
            que.enque([ny, nx, d + 1]);
            graph[ny][nx] = 1;
        }
    }
}

outer: for (let i = 0; i &lt; n; i++) {
    for (let j = 0; j &lt; m; j++) {
        if (!graph[i][j]) {
            ans = -1;
            break outer;
        }
    }
}
console.log(ans);</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[백준 7569 JS 풀이]]></title>
            <link>https://velog.io/@jae-hun-e/%EB%B0%B1%EC%A4%80-7569-JS-%ED%92%80%EC%9D%B4</link>
            <guid>https://velog.io/@jae-hun-e/%EB%B0%B1%EC%A4%80-7569-JS-%ED%92%80%EC%9D%B4</guid>
            <pubDate>Wed, 09 Aug 2023 15:31:11 GMT</pubDate>
            <description><![CDATA[<h2 id="구하는-값">구하는 값</h2>
<p>3차원 창고에서 토마토가 다 익는데 걸리는 시간</p>
<h2 id="핵심-아이디어">핵심 아이디어</h2>
<p>que안에 익은 토마토를 넣어놓고 상하좌우위아래로 bfs를 돌림 </p>
<h2 id="코드1">코드1</h2>
<pre><code class="language-jsx">const input = require(&#39;fs&#39;).readFileSync(&#39;dev/stdin&#39;).toString().trim().split(&#39;\n&#39;)

class Que {
    q = [];
    h = 0;
    t = 0;
    push(v) {
        this.q[this.t++] = v;
    }
    shift() {
        const v = this.q[this.h];
        delete this.q[this.h++];
        return v;
    }
    length() {
        return this.t - this.h;
    }
}

const [m, n, h] = input[0].split(&quot; &quot;).map(Number);

const graph = Array.from({ length: h }, () =&gt; Array.from({ length: n }, () =&gt; []));
// console.log(graph);

const que = new Que();
let k = h;
while (k--) {
    for (let i = 0; i &lt; n; i++) {
        const line = input[k * n + i + 1].split(&quot; &quot;).map(Number);
        line.forEach((v, j) =&gt; {
            if (v === 1) que.push([k, i, j, 1]);
        });
        graph[k][i].push(...line);
    }
}

// console.log(graph); // z,y,x
// console.log(que);

const dx = [-1, 1, 0, 0, 0, 0],
    dy = [0, 0, -1, 1, 0, 0],
    dz = [0, 0, 0, 0, -1, 1];

let max = 0;
const bfs = () =&gt; {
    while (que.length()) {
        const [z, y, x, d] = que.shift();

        max = Math.max(d, max);

        for (let i = 0; i &lt; 6; i++) {
            const nx = x + dx[i],
                ny = y + dy[i],
                nz = z + dz[i];

            if (nx &lt; 0 || nx &gt;= m || ny &lt; 0 || ny &gt;= n || nz &lt; 0 || nz &gt;= h) continue;
            // console.log(&quot;nz,ny,nx&quot;, nz, ny, nx);
            if (!graph[nz][ny][nx]) {
                graph[nz][ny][nx] = d;
                que.push([nz, ny, nx, d + 1]);
            }
        }
    }
};

bfs();
// console.log(graph);

outer: for (let i = 0; i &lt; n; i++) {
    for (let j = 0; j &lt; m; j++) {
        for (let z = 0; z &lt; h; z++) {
            if (!graph[z][i][j]) {
                max = 0;
                break outer;
            }
        }
    }
}

console.log(max - 1);</code></pre>
<h2 id="코드2">코드2</h2>
<pre><code class="language-jsx">const input = require(&#39;fs&#39;).readFileSync(&#39;dev/stdin&#39;).toString().trim().split(&#39;\n&#39;)

class Que {
    q = [];
    h = 0;
    t = 0;
    push(v) {
        this.q[this.t++] = v;
    }
    shift() {
        const v = this.q[this.h];
        delete this.q[this.h++];
        return v;
    }
    length() {
        return this.t - this.h;
    }
}

const [m, n, h] = input[0].split(&quot; &quot;).map(Number);

const graph = Array.from({ length: h }, () =&gt; Array.from({ length: n }, () =&gt; []));
// console.log(graph);

const que = new Que();
let k = h;
let total = m * n * h;
while (k--) {
    for (let i = 0; i &lt; n; i++) {
        const line = input[k * n + i + 1].split(&quot; &quot;).map(Number);
        line.forEach((v, j) =&gt; {
            if (v === 1) {
                que.push([k, i, j, 1]);
                total--;
            }
            if (v === -1) total--;
        });
        graph[k][i].push(...line);
    }
}

// console.log(graph); // z,y,x
// console.log(que);

const dx = [-1, 1, 0, 0, 0, 0],
    dy = [0, 0, -1, 1, 0, 0],
    dz = [0, 0, 0, 0, -1, 1];

let max = 0;
const bfs = () =&gt; {
    while (que.length()) {
        const [z, y, x, d] = que.shift();

        max = Math.max(d, max);

        for (let i = 0; i &lt; 6; i++) {
            const nx = x + dx[i],
                ny = y + dy[i],
                nz = z + dz[i];

            if (nx &lt; 0 || nx &gt;= m || ny &lt; 0 || ny &gt;= n || nz &lt; 0 || nz &gt;= h) continue;
            // console.log(&quot;nz,ny,nx&quot;, nz, ny, nx);
            if (!graph[nz][ny][nx]) {
                total--;
                graph[nz][ny][nx] = d;
                que.push([nz, ny, nx, d + 1]);
            }
        }
    }
};

bfs();

console.log(total ? -1 : max - 1);</code></pre>
<p>3차원을 다루는 방법을 처음해봤다. 시험때만나면 당황했을듯..</p>
<p>그리고 처음방법으로 삼중for문은 너무 역해서 다른 방법을 찾다 graph만들때 순회를하니깐 그때 전체개수에서 1, -1의 개수를빼주고 bfs를 돌며 -1씩해주면 전체개수가 0이 아니라면 안익은 토마토가 남아있다는 뜻이므로 삼중for문 없이 판단할 수 있다.</p>
]]></description>
        </item>
    </channel>
</rss>