<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>코딩배우는 학생 </title>
    <link>https://blue-boy.tistory.com/</link>
    <description>완전 연소한 불은 재를 남기지않는다
: 코딩배우는학생   
</description>
    <language>ko</language>
    <pubDate>Sat, 8 Aug 2026 06:31:11 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>Blue___</managingEditor>
    <image>
      <title>코딩배우는 학생 </title>
      <url>https://tistory1.daumcdn.net/tistory/3451347/attach/7247cd74b70b49dc919a3917c857baeb</url>
      <link>https://blue-boy.tistory.com</link>
    </image>
    <item>
      <title>chapter 01</title>
      <link>https://blue-boy.tistory.com/256</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;컴퓨터가 이해하는 코드는 바보도 작성할 수 있다.&lt;br /&gt;사람이 이해하도록 작성하는 프로그래머가 진정한 실력자다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;1. 리팩토링하기전에는 테스트 부터&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;분량이 방대한 코드를 리팩토링하다보면 잘 돌아가던 코드도 안되는 경우가 빈번하게 생기기 마련이다. 때문에 지속적으로 눈으로 보며 기능이 정상적으로 동작하는지 확인하는 과정이 필요하다. 이를 리팩토링 - 기능검사 순으로 반복적으로 수행하다보면 너무나 비효율적이고 검수에 너무나 많은 시간이 소요될 것이다. 이를 위해서 테스트 작성에 시간이 걸리더라도 신경 써서 만들어두면 디버깅 시간이 줄어 전체 작업시간은 줄어드는 효과를 얻을 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;2. 기능 쪼개기&amp;nbsp;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;긴 함수의 리팩토링을 맞닥뜨렸을 때 당황하지말고 기능쪼개기부터하자. 본문에서 발췌한 다음과 같은 코드를 보자.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1662447608960&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function statement(invoice, plays){
	let totalAmount = 0;
    let volumeCredits = 0;
    let result = `청구내역 ${invoice.customer}`;
    
    for(let perf of invoice.performances){
    	const play = plays[perf.playId];
        let thisAmount = 0;
        
        switch(play.type){
        	case 'tragedy':
            	thisAmount = 40000;
                if(perf.audience &amp;gt; 30){
                	thisAmount += 1000 * (perf.audience -30);
                }
                break;
           	case 'comedy':
            	this.Amount = 30000;
                if(perf.audience &amp;gt;20)
                	this.Amount += 10000 + 500 * (perf.audience -20);
                this.Amount += 300 * perf.audience;
                break;
            default:
            	throw new Error('알수 없는 장르: ${play.type}')
        }
        
        volumeCredits += Math.max(perf.audience -30, 0);
        if('comedy' === play.type) volumeCredits += Math.floor(perf.audience / 5);
        
        result += `${play.name}: ${format(thisAmount/100)} ${perf.audience}석`;
        result += `적립 포인트: ${volumeCredits}점`
        return result;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;switch 문에 있는 로직은 지금 당장은 짧아서 무슨 기능을 하는지 명시적으로 알수 있지만, 코드가 길어 질 수록 해당 부분은 휘발성으로 작성자의 머릿속에만 남아있는 로직이 되어 버릴 것이다. 다른 문제점으로는 장르를 추가했을 때 코드를 일일히 뜯어내서 필요한 부분에 로직을 추가해주어야 된다. 좋은 코드는 '누가 보더라도 얼마나 수정하기 쉬운가'에 달려있다고 봐도 무방하다. 그런 관점에서 이 코드는 복잡하고 단번에 알기 어렵다. 누구든지 코드를 봤을 때 디버깅이 쉬워야 한다. 이를위해 코드 자신이 하는일을 추출해서 반영할 필요가 있다. 그리고 perf 같은 알아보기 힘든 변수명도 명시적으로 치환해 주어야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;2-1 임시변수를 질의 함수로 바꾸기 , 변수 인라인하기&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;위의 코드에서 plays[perf.playId]는 plays에서 가져오기 때문에 굳이 매개변수를 둘 필요가 없다. 이를&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1662448264184&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function playFor(aPerformance){
	return plays[aPerformance.playId];
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;로 추출해주면 const play = playFor(perf)로 표현될 수 있으며 let thisAmount = amountFor(perf, playFor(perf))로 인라인으로 처리해 줄 수도 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;2-2 임시 변수는 최대한 제거하라&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;임시변수는 나중에 문제를 일으킬 수 있다. 임시 변수는 자신이 속한 곳에서만 의미를 가지며 복잡성을 증대시킨다. 때문에 최대한 변수를 인라인하고 함수를 직접 선언해 사용하는 것이 좋다. 예를들어 getter나 computed속성으로 처리되는 부분들같은 경우가 그 예이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;2-3 반복문 쪼개기&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;한 반복문안에 성능을 위해 여러 로직을 우겨넣었다면, 이는 동일한 기능을 하는 로직끼리 묶어 반복문을 쪼개주는 것이 좋다. 물론 2개로 나뉘면 성능면에서 걱정할 우려도 있다. 하지만 이는 굉장히 미미하며, 이 부분을 수정한다해도 대부분의 경우는 성능 차이를 체감하기 어렵다. 일단 리팩토링 후 성능 이슈가 생긴다면 그 때 판단해도 오히려 리팩토링 되어 빠르게 디버깅해서 이를 개선할 수 있을 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;2-4 반복문을 파이프라인으로 바꾸기&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;for문은 최대한 고차함수를 이용해서 치환해준다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1662449595398&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;return data.performances.reduce((total,p) =&amp;gt; total + p.amount ,0);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;3. 변수명 짓기&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;이 책에 서술된 내용 1장에는 변수명에 다음과 같은 규칙을 준다고 한다.&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;1. 함수의 반환 값에는 항상 result 를 사용한다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;2. 매개변수의 역할이 뚜렷하지 않을 때에는 부정관사(a/an)을 붙인다.&lt;br /&gt;* 이름이 좋으면 함수 본문을 읽지 않고도 무슨 일을 하는 함수인지 알 수 있다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;4. 단계 쪼개기&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;위의 경우 statement()에 필요한 데이터를 처리하고 이후 텍스트를 렌더하는 과정을 거친다. 이를 하나의 메소드에 표현하고 있는데, 확실하게 단계적으로 구분 짓는 것이 좋아보인다. 데이터 처리를 1단계, 출력 2단계로 나누어 준다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1662449327391&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function statement(invoice, plays){
	const statement = {};
    statementData.customer = invoice.customer;
    statementData.performances = invoice.performances.map(enrichPerformance);
    return renderPlainText(statementData, plays);
    
    function enrichPerformance(aPerformance){
    	const result = Object.assign({}, aPerformance);
        result.play = playFor(result);
        return result;
    }
    function playFor(aPerformance){
    	return plays[aPerformance.playId];
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;* mutable한 데이터는 금방 상하기 때문에 얕은복사를 통해&amp;nbsp;최대한 immutable하게 다뤄준다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;5. 다형성을 이용한 코드 재구성 / 생성자를 팩토리 패턴으로 바꾸기&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;위의 공연료 계산을 performanceCalculater클래스로 코드를 이전하고 공연 종류에 따라 다른 조건부 로직들을 다형성을 활용해 재구성해줄 수 있다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1662451251559&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function createPerformanceCalculator(aPerformance, aPlay){
	switch(aPlay.type){
    	case 'tragedy': return new TragedyCalculator(aPerformance, aPlay);
        case 'comedy': return new ComedyCalculator(aPerformance, aPlay);
        default: throw new Error();
    }
}

class TragedyCalculator extends PerformanceCalculator{}
class ComedyCalculator extends PerformanceCalculator{}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;공통 로직은 PerformanceCalculator 슈퍼클래스에 정의하고 오버라이드해 사용해주면 중복코드를 방지할 수 있다. 일반적인 슈퍼셋을 슈퍼클래스에 남겨두고 예외적인 부분을 필요할 때 오버라이드하게 만드는 것이 좋다. 위의 경우 포인트 계산 방식이 조금 다른 코미디 처리 로직을 해당 서브클래스로 내리는 것이 좋다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;2장에서 계속..&lt;/span&gt;&lt;/p&gt;</description>
      <category>북리뷰/리팩토링 2판</category>
      <category>javascript</category>
      <category>js</category>
      <category>refactoring</category>
      <category>리팩토링</category>
      <category>리팩토링 2판</category>
      <author>Blue___</author>
      <guid isPermaLink="true">https://blue-boy.tistory.com/256</guid>
      <comments>https://blue-boy.tistory.com/256#entry256comment</comments>
      <pubDate>Tue, 6 Sep 2022 17:07:52 +0900</pubDate>
    </item>
    <item>
      <title>2022 디프만 11기 FE 활동 회고</title>
      <link>https://blue-boy.tistory.com/255</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;edited_edited_edited_스크린샷 2022-08-08 오후 10.47.11.png&quot; data-origin-width=&quot;620&quot; data-origin-height=&quot;185&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eed3CB/btrJcEUKZr1/TR7swbJJs0JnMfijKvuLH1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eed3CB/btrJcEUKZr1/TR7swbJJs0JnMfijKvuLH1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eed3CB/btrJcEUKZr1/TR7swbJJs0JnMfijKvuLH1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Feed3CB%2FbtrJcEUKZr1%2FTR7swbJJs0JnMfijKvuLH1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;620&quot; height=&quot;185&quot; data-filename=&quot;edited_edited_edited_스크린샷 2022-08-08 오후 10.47.11.png&quot; data-origin-width=&quot;620&quot; data-origin-height=&quot;185&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;약 반년간 진행된 디프만 활동이 파이널 발표를 마침표로 끝이 났다. 기존 DDD, 오픈소스 컨트리뷰톤 활동을 통해서 스스로 채찍질할 수 있기도 하고 개발자 네트워킹 및 협업을 통해서 1년 반동안 많은 성장을 이뤘다고 생각한다. 이후 이직을 고민하고, BE에서 FE로 전향하게 되면서 현재 현업에서 쌓을 수 없는 리액트 프로젝트 경험이라던가 퍼블리셔가 맡는 파이를 가져오고 싶어서 디프만 11기 FE로 약 반년간 프로젝트를 진행하게 되었다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;면접 그리고 프로젝트&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;감사하게도 높은 경쟁률을 뚫고 11기로 활동할 수 있게 되었다.(한 10:1은 되었던 것 같다.) 그 동안 쌓아온 MBC 프로젝트 포트폴리오와 개발에 대한 열정을 높게 사주신 것 같다. 서류심사 이후에는 비대면 면접이 진행되었다. 일반 기업 수준의 기술면접은 아니니 긴장하지 않아도 될 것 같다. 실제로 나 같은 경우 React 경험은 전무하고 기술 질문도 2-3개에 그쳤었다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;i&gt;내로라하는 개발자들과 마크업 경험없이 협업할 수 있을까? &lt;/i&gt;라는 생각에 걱정이 앞서기도 했지만, 평소에 닥치면 어떻게든 할 수 있다는 생각으로 참여했던 것 같다. 기존에 회사에서 Vue 기반 개발을 약 반년간 진행했던 경험으로 프로젝트 개발을 시작했다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;다양한 플랫폼의 웹툰을 모아서 주식 양식을 더한 덕질 플랫폼으로 주제를 정하고 기술 스택을 정하였다. &lt;b&gt;Next.js&lt;/b&gt; 를 통해 기존 CSR의 단점인 &lt;b&gt;SEO&lt;/b&gt; 문제를 극복하고 &lt;b&gt;React Query&lt;/b&gt;로 데이터 패칭을, &lt;b&gt;Recoil&lt;/b&gt;로 전역 state를 관리하였다. 이외에도 &lt;u&gt;Hotjar, Mixpanel, Sentry, Storybook&lt;/u&gt;등 다양한 기술에 대한 접근 및 시도가 있었다.&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;FE 배포는 한번도 경험하지 못했었는데, 팀원의 많은 기여로 아래와 같은 구조가 짜여졌다. Github action으로 dev, staging, live 환경별로 serverless를 통해 배포하고 있다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;AWS ClounFront, AWS 람다엣지&lt;/b&gt;를 주로 사용한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/by6S8P/btrJfo4YYTe/JxYlmJaCgXGi6GVsZy2iPk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/by6S8P/btrJfo4YYTe/JxYlmJaCgXGi6GVsZy2iPk/img.png&quot; data-is-animation=&quot;false&quot; data-origin-width=&quot;649&quot; data-origin-height=&quot;356&quot; data-filename=&quot;edited_edited_edited_스크린샷 2022-08-08 오후 10.59.11.png&quot; width=&quot;638&quot; height=&quot;350&quot; data-widthpercent=&quot;50.22&quot; style=&quot;width: 49.6349%; margin-right: 10px;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/by6S8P/btrJfo4YYTe/JxYlmJaCgXGi6GVsZy2iPk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fby6S8P%2FbtrJfo4YYTe%2FJxYlmJaCgXGi6GVsZy2iPk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;649&quot; height=&quot;356&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/HIoFm/btrJget3y02/M7tocxT4E0KkIA5V6F5SK1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/HIoFm/btrJget3y02/M7tocxT4E0KkIA5V6F5SK1/img.png&quot; data-origin-width=&quot;506&quot; data-origin-height=&quot;280&quot; data-is-animation=&quot;false&quot; data-filename=&quot;edited_edited_edited_스크린샷 2022-08-08 오후 11.02.35.png&quot; width=&quot;638&quot; height=&quot;353&quot; data-widthpercent=&quot;49.78&quot; style=&quot;width: 49.2023%;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/HIoFm/btrJget3y02/M7tocxT4E0KkIA5V6F5SK1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHIoFm%2FbtrJget3y02%2FM7tocxT4E0KkIA5V6F5SK1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;506&quot; height=&quot;280&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;중간발표 자료  &amp;zwj; ️&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;프로젝트를 시작할 때 특히 팀원들과 많이 고민한 부분은 바로 바로 아키택쳐 패턴이다. 이전에 MBC APP을 할때도 같은 고민을 하게 되었는데, &lt;u&gt;&lt;i&gt;어떤 디렉토리 구조를 가지는게 효율적이고 가장 공통화를 잘 할 수 있을까&lt;/i&gt; &lt;/u&gt;하는 고민이었다. 많이 하는 방식으로 우리팀도 assets, components, context, apis, hooks, pages, utils등 목적을 가지는 디렉토리로 분리하였다. 특히 hooks를 통해 재사용 가능한 커스텀 훅으로 뺄 수 있는 부분은 최대한 이를 이용하려고 노력하였다. 더해서 완전 아토믹 적인 구조는 아니더라도 components에는 Molecule 레벨의 컴포넌트를 배치하고 domains에는 Organisms 레벨의 컴포넌트를 배치해 좀더 컴포넌트를 세분화하였다. 이는 공통 디자인을 최대한 재활용하기 위한 방법이었다. 프로젝트가 끝나고 난 이후에는 이런 경계가 좀 흐려지는 악효과도 있었는데, 이는 명확할 수록 좋다. 조금 더 확장성있고 큰 프로젝트를 진행하게 된다면 아토믹을 적용해봐도 좋겠다는 생각을 하게되었다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;edited_edited_스크린샷 2022-08-08 오후 11.12.33.png&quot; data-origin-width=&quot;206&quot; data-origin-height=&quot;392&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/chO84T/btrJfZw3CUP/Bkd3iYRjDsoEHaHCQYuuI1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/chO84T/btrJfZw3CUP/Bkd3iYRjDsoEHaHCQYuuI1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/chO84T/btrJfZw3CUP/Bkd3iYRjDsoEHaHCQYuuI1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FchO84T%2FbtrJfZw3CUP%2FBkd3iYRjDsoEHaHCQYuuI1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;206&quot; height=&quot;392&quot; data-filename=&quot;edited_edited_스크린샷 2022-08-08 오후 11.12.33.png&quot; data-origin-width=&quot;206&quot; data-origin-height=&quot;392&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;피그마 vs 포토샵&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;현업에서는 포토샵을 계속 사용했었는데 이번 프로젝트는 피그마를 통해 진행되었다. 피그마를 쓰면서 가장 편리했던 것은 바로 디자이너가 직접 구축해둔 디자인 시스템의 사용이었다. 기존에는 화면 단위의 작업으로 진행되었다면 지금은 컴포넌트 단위로 디자인이 존재하고 이를 활용해 화면을 구성함으로써 디자이너의 작업량, FE 작업량이 현저하게 줄었다고 생각한다. 또한 UI적으로 통일된 화면을 보여줌으로써 통일성을 주는 것이 가장 큰 강점이라고 생각한다. 모던 JS 프레임워크의 컴포넌트 단위 개발과 시너지를 내며 각광받고 있다고 생각한다. 실제로 사용하는 러닝커브도 높지 않아 긍정적 경험으로 이어졌다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이직&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;중간발표가 끝나고 그동안 준비해왔던 알고리즘 공부 및 CS 기술면접 준비가 끝이 났다. FE개발로 전향하기 위해서 시작한 디프만이 끝나기도 전에 FE로 이직을 성공하게 된 것이다. 그동안 열심히 준비한 것도 있지만, 운도 많이 따랐던 것 같다. 무엇보다 이번 프로젝트를 하면서 마크업의 중요성을 깨닫게 되었다. 구현부터 테스트, 성능 측면에서 실제로 프로덕트를 서비스하기 위해 유저관점에서 생각하게 되면서 느꼈던 점, 트러블 슈팅 경험, A to Z 쌓아온 개발 경험은 이직에 하나의 무기가 되었다고 생각한다. 디프만 활동을 하지 않았더라면 이런 경험은 당장 쉽게 경험하지 못했을 것이다.&amp;nbsp; 만약 디프만 지원을 고민하고 있다면 주저없이 도전해 보는 것을 추천한다.&amp;nbsp; &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Light House 성능 최적화&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 첫 주안점으로 둔 포인트는 TTI(Time to Interactive) 였다. 개인적으로 생각했을 때 유저가 가장 이탈율이 크고 불편하다고 생각하는 부분이 로드 속도 인데, 첫 상호작용이 답답하도록 느리다면 그 앱은 실패했다고 생각하기 때문이다. 이를 위해 리소스 크기를 줄이고 댓글 뷰포트 기반으로 무한스크롤을 적용하고 이미지도 LazyLoad되도록 적용해 주었다. 그리고 렌더 블록 요소를 제거하는 작업을 지속적으로 해주었다(현재 0밀리초). 이외에도 웹 접근성을 고려하여 다음과 같은 요소를 인지하고 100%는 아니어도 최대한 적용해 주었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;대체텍스트 제공&lt;/li&gt;
&lt;li&gt;Bypass block&lt;/li&gt;
&lt;li&gt;표의 캡션&lt;/li&gt;
&lt;li&gt;키보드 초점이동&lt;/li&gt;
&lt;li&gt;언어 명시&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;남은 작업으로는 폰트 내재화 및 렌더 스피너를 스켈레톤 UI로 대체함으로써 CLS(Comulative Layout Shift)를 최소화하고 API response를 받아오는 속도가 너무 너무 너무 느린데 이를 개선할 방안을 마련하고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/2643h/btrJaW88g2T/qlGkBvcXchLt2L8xDxIUX1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/2643h/btrJaW88g2T/qlGkBvcXchLt2L8xDxIUX1/img.png&quot; data-is-animation=&quot;false&quot; data-origin-width=&quot;377&quot; data-origin-height=&quot;869&quot; data-filename=&quot;edited_edited_스크린샷 2022-08-09 오전 12.02.58.png&quot; data-widthpercent=&quot;30.75&quot; style=&quot;width: 30.3972%; margin-right: 10px;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/2643h/btrJaW88g2T/qlGkBvcXchLt2L8xDxIUX1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F2643h%2FbtrJaW88g2T%2FqlGkBvcXchLt2L8xDxIUX1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;377&quot; height=&quot;869&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/24noR/btrJeqILKgi/pJ0wvnfK7SIKJS7JcMmHw1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/24noR/btrJeqILKgi/pJ0wvnfK7SIKJS7JcMmHw1/img.png&quot; data-is-animation=&quot;false&quot; data-origin-width=&quot;589&quot; data-origin-height=&quot;603&quot; data-filename=&quot;edited_edited_스크린샷 2022-08-09 오전 12.03.12.png&quot; data-widthpercent=&quot;69.25&quot; style=&quot;width: 68.44%;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/24noR/btrJeqILKgi/pJ0wvnfK7SIKJS7JcMmHw1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F24noR%2FbtrJeqILKgi%2FpJ0wvnfK7SIKJS7JcMmHw1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;589&quot; height=&quot;603&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;A/B 투표페이지 Light House 성능 측정&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;최종발표 그리고 수상&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;저&lt;/span&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;번 DDD 6기를 진행하면서는 혼자서 서버를 맡았기 때문에 주위 개발자들에게 자극받거나 협업의 느낌이 강하게 들지 못했었었는데, 이번 프로젝트를 하면서 느끼는 점이 정말 많았다&lt;span&gt; &lt;/span&gt;. 어느정도 개발공부를 했다 생각이 들면서도 세상에는 더 잘하는 사람들도 많다는 생각과 함께 더 잘하고 싶다고 생각하게 되었다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;그렇게 다같이 노력하며 약 3개월간 1,2차에 걸친 MVP를 수립하고 전날까지 개발하게 되었고 최종발표에서 우수상을 수상하는 영예를 안게 되었다. 특별히 뭔가 주어지는 것은 아니지만 FE 개발자로서의 출발선상에 서서 3개월을 돌아봤을 때 그동안의 노력에 대한 결실이라는 생각에 스스로 뿌듯했다. 현업에서 느낄 수 없는 퀀텀 점프를 경험했던 3개월 이었고 앞으로도 지속적으로 참여하고 싶다.  &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bk82O0/btrJgd9GARP/CW0bG32csXcxvBXIiK4UmK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bk82O0/btrJgd9GARP/CW0bG32csXcxvBXIiK4UmK/img.png&quot; data-is-animation=&quot;false&quot; data-origin-width=&quot;1170&quot; data-origin-height=&quot;1145&quot; data-filename=&quot;edited_edited_edited_KakaoTalk_Photo_2022-08-08-23-44-47 001.jpeg&quot; width=&quot;300&quot; height=&quot;294&quot; data-widthpercent=&quot;50.26&quot; style=&quot;width: 49.6762%; margin-right: 10px;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bk82O0/btrJgd9GARP/CW0bG32csXcxvBXIiK4UmK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbk82O0%2FbtrJgd9GARP%2FCW0bG32csXcxvBXIiK4UmK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1170&quot; height=&quot;1145&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bEPyC7/btrJeqhGogW/Z1RT0VotcqCm4pPMbsOTak/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bEPyC7/btrJeqhGogW/Z1RT0VotcqCm4pPMbsOTak/img.png&quot; data-is-animation=&quot;false&quot; data-origin-width=&quot;1170&quot; data-origin-height=&quot;1157&quot; data-filename=&quot;edited_edited_edited_KakaoTalk_Photo_2022-08-08-23-44-48 003.jpeg&quot; width=&quot;300&quot; height=&quot;297&quot; data-widthpercent=&quot;49.74&quot; style=&quot;width: 49.161%;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bEPyC7/btrJeqhGogW/Z1RT0VotcqCm4pPMbsOTak/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbEPyC7%2FbtrJeqhGogW%2FZ1RT0VotcqCm4pPMbsOTak%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1170&quot; height=&quot;1157&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bGNVRF/btrJfoX8nmv/HwYO7GtYpIGJl6QkklowZ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bGNVRF/btrJfoX8nmv/HwYO7GtYpIGJl6QkklowZ1/img.png&quot; data-is-animation=&quot;false&quot; data-origin-width=&quot;1170&quot; data-origin-height=&quot;1165&quot; data-filename=&quot;edited_edited_edited_KakaoTalk_Photo_2022-08-08-23-44-47 002.jpeg&quot; width=&quot;300&quot; height=&quot;299&quot; data-widthpercent=&quot;49.26&quot; style=&quot;width: 48.6868%; margin-right: 10px; margin-top: 10px;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bGNVRF/btrJfoX8nmv/HwYO7GtYpIGJl6QkklowZ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbGNVRF%2FbtrJfoX8nmv%2FHwYO7GtYpIGJl6QkklowZ1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1170&quot; height=&quot;1165&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bjAEQN/btrJhkAwZMU/76EJwIRRRsDxumL20vrvlk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bjAEQN/btrJhkAwZMU/76EJwIRRRsDxumL20vrvlk/img.png&quot; data-is-animation=&quot;false&quot; data-origin-width=&quot;1170&quot; data-origin-height=&quot;1131&quot; data-filename=&quot;edited_edited_edited_KakaoTalk_Photo_2022-08-08-23-44-48 006.jpeg&quot; width=&quot;300&quot; height=&quot;290&quot; data-widthpercent=&quot;50.74&quot; style=&quot;width: 50.1504%; margin-top: 10px;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bjAEQN/btrJhkAwZMU/76EJwIRRRsDxumL20vrvlk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbjAEQN%2FbtrJhkAwZMU%2F76EJwIRRRsDxumL20vrvlk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1170&quot; height=&quot;1131&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cyRiXC/btrJhiJskPA/ZslMIeUQ5X26jLqNhulbJK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cyRiXC/btrJhiJskPA/ZslMIeUQ5X26jLqNhulbJK/img.png&quot; data-is-animation=&quot;false&quot; data-origin-width=&quot;1170&quot; data-origin-height=&quot;1159&quot; data-filename=&quot;edited_edited_edited_KakaoTalk_Photo_2022-08-08-23-44-48 005.jpeg&quot; width=&quot;300&quot; height=&quot;297&quot; data-widthpercent=&quot;50.11&quot; style=&quot;width: 49.525%; margin-right: 10px; margin-top: 10px;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cyRiXC/btrJhiJskPA/ZslMIeUQ5X26jLqNhulbJK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcyRiXC%2FbtrJhiJskPA%2FZslMIeUQ5X26jLqNhulbJK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1170&quot; height=&quot;1159&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dGgrZt/btrI9lVHQKr/KghZNoOr7AGzonWXMSOSGK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dGgrZt/btrI9lVHQKr/KghZNoOr7AGzonWXMSOSGK/img.png&quot; data-is-animation=&quot;false&quot; data-origin-width=&quot;1170&quot; data-origin-height=&quot;1164&quot; data-filename=&quot;edited_edited_edited_KakaoTalk_Photo_2022-08-08-23-44-48 004.jpeg&quot; width=&quot;300&quot; height=&quot;298&quot; data-widthpercent=&quot;49.89&quot; style=&quot;width: 49.3122%; margin-top: 10px;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dGgrZt/btrI9lVHQKr/KghZNoOr7AGzonWXMSOSGK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdGgrZt%2FbtrI9lVHQKr%2FKghZNoOr7AGzonWXMSOSGK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1170&quot; height=&quot;1164&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt; &lt;a href=&quot;https://github.com/depromeet/antoon_web&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;개미는 툰툰 깃허브&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt; &lt;a href=&quot;https://antoon.fun/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;개미는 툰툰 사이트&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;</description>
      <category>이모저모</category>
      <category>frontend</category>
      <category>js</category>
      <category>React</category>
      <category>개발</category>
      <category>동아리</category>
      <category>디프만</category>
      <category>웹툰</category>
      <category>코딩배우는 학생</category>
      <category>프로젝트</category>
      <category>프론트엔드</category>
      <author>Blue___</author>
      <guid isPermaLink="true">https://blue-boy.tistory.com/255</guid>
      <comments>https://blue-boy.tistory.com/255#entry255comment</comments>
      <pubDate>Tue, 9 Aug 2022 00:18:57 +0900</pubDate>
    </item>
    <item>
      <title>첫 이직 회고</title>
      <link>https://blue-boy.tistory.com/254</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;첫 회사&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;방송사와는 전혀 연관이 없을 줄 알았는데 어쩌다보니 개발자로써 첫 사회생활을 디지털미디어시티에서 하게되었다. 사실 생각해본적도 없고 C#이라는 난생 처음보는 언어로 서버개발을 한다는데, 그동안 해왔던 건 java와 스크립트 뿐이었다. 졸업하고 취준 2개월만에 그렇게 풀스택(?) 개발자로써 첫 발을 내딛게 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-size=&quot;size16&quot; data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이직에 대한 고민&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫 회사에 입사하고 이전과는 비교도 할 수 없는 &lt;b&gt;성장&lt;/b&gt;을 하게되었다. 그래도 부족하다고 생각하지만 1년 반 이전의 나와 비교한다면 그렇다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히 재직하며 MBC 앱을 네이티브에서 웹뷰로의 전환 이슈로 혼자 처음부터 모래성을 쌓아올리듯 개발한 경험이나, 대선, 올림픽과 같은 이벤트 사이트 개발, 각종 관리자 페이지 개발은 재미도 있었고 서비스가 배포되는 뿌듯함을 느낄 수 있었던 프로젝트들이었다. 1년 반이라는 짧은 시간이었지만 개인적으로 역량에 비해 큰 프로젝트를 여러 개 런칭하고 유지보수하면서 개발자로써 인정받으며 베이스를 다질 수 있었다. (나름 좋았다 )&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1년 반의 첫 직장생활을 뒤로하고 이직을 결정하기 까지 수많은 걱정과 할 수 있을까라는 고민을 많이 했었던 것 같다. 개발자로써 IT 회사에서 치열하게 개발에 몰두하는 경험을 하고 싶었고, 판교 라이프를 막연하게 꿈꿨었다. 사실 첫 회사도 그럭저럭 만족하고 다녔었고 주니어 개발자로써 커리어도 쌓을 수 있었다. 무엇보다 팀원들, 회사 동기들도 더할나위 없었다. 다만 어느부턴가 업무가 익숙해지며 &lt;b&gt;정체&lt;/b&gt;되어 있다는 생각이 나를 괴롭혔던 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;mbcApp.png&quot; data-origin-width=&quot;1084&quot; data-origin-height=&quot;791&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/3fC7s/btrG8Q3ePnZ/i7NTJ6aA7s5Lkirhi5BPKK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/3fC7s/btrG8Q3ePnZ/i7NTJ6aA7s5Lkirhi5BPKK/img.png&quot; data-alt=&quot;MBC앱&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/3fC7s/btrG8Q3ePnZ/i7NTJ6aA7s5Lkirhi5BPKK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F3fC7s%2FbtrG8Q3ePnZ%2Fi7NTJ6aA7s5Lkirhi5BPKK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;512&quot; height=&quot;791&quot; data-filename=&quot;mbcApp.png&quot; data-origin-width=&quot;1084&quot; data-origin-height=&quot;791&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;MBC앱&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히 이때 가만히 못 있고 개발에 한참 재미가 붙어서 닥치는대로 여러 활동을 병행해서 시작했는데 그 중 오픈소스 컨트리뷰톤, DDD, 디프만과 같은 대외활동, 해커톤등을 쉬는날 없이 가리지 않고 시작했다. 거기에 각종 CS 스터디와 사이드 프로젝트를 덧붙여 진행하게 되었다. 개발이 정말 순전히 재밌어서 퇴근 후에도 새벽까지 매일 서버, 프론트 가리지 않고 개발을 했는데 어느 정도 시간이 지나고 더 나아가 앞선 고민에 더해 진로에 대한 고민을 덧붙여 하게 되었다. 바로 &lt;b&gt;전문성&lt;/b&gt;에 대한 고민이었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;회사에서 서버, 프론트 가리지 않고 정말로 '웹' 개발자로 일을 했었는데 시간이 지나면서 서버/프론트 둘 중 하나에 몰두해 전문성을 가지고 싶었다. 당시 서버를 주로 닷넷을 써서 커리어에 강점이 크게 없다고 생각했고, 무엇보다 사용자에게 보여지는 UI개발에 더 흥미가 있었기 때문에 프론트 개발로 최종 선택하게 되었다. 사실 회사에서 진행한 프로젝트가 대부분 프론트에 강점인 프로젝트가 많은 것도 결정에 큰 부분을 차지했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&amp;nbsp;이직과정&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;기존 서버개발에서 프론트로 전향한지 1년정도 밖에 안되기도하고&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;경력 기간도 2년이 채 되지 않았기 때문에 이직에 있어서 막연한 두려움이 있었던 것은 사실이다. 이미 1년 정도 준비를 했었고 사실 2년정도의 기간 이후에 이직을 하려고 마음을 먹었었는데, 여러 개발 커뮤니티 모임을 해서 그런지 몰라도 이직에 대해 조금 더 가볍게 생각하려고 노력했던 것 같다.(그리고 주위 개발자 분들이 용기도 많이 주셨다.. ) 그래서 주저없이 여러 회사에 지원하게 되었다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 이직준비 과정에서 기술면접보다도 갈수록 어려워지는 코딩테스트 난이도가 힘들게 했는데, 프론트 개발자도 예외는 아니었다. 과제전형이 오히려 더 나을정도로 따로 공부하지 않으면 어려운 난이도가 드물지 않게 있었다. 코딩테스트는 이론 공부를 끝내고 최대한 많은 문제를 풀어보았다. 이론적인 부분은 개인적으로 강의를 하나 사서 듣는 방법이 제일 효과가 좋았던 것 같다.(글이 너무 어려워서 이해하기 힘든 부분들이 개인적으로 많았다). 이 부분이 이직준비에서 큰 난관이었다면 난관이었고, 기술면접은 크게 벗어나지 않는 cs 수준에서 나왔던 거 같아 무난하게 봤다고 생각한다. 다만 경력이 짧아 이 부분에 있어서 검증하는 시간을 가지기도 했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;첫 이직 마무리&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그동안 배포된 프로젝트들을 항상 포트폴리오와 깃헙에 정리해두었는데 이게 강점이 되었는지 감사하게도 여러 IT회사의 면접을 보게되었고, 개인적으로 제일 관심있는 분야의 회사에 프론트 개발자로 입사하게 되었다. 수준 높은 면접 질문이라던가 라이브코딩, 산출물 등 여러 요인을 보고 결정했는데 입사한지 한달 지난 지금까지 이전과는 다른 업무환경과 고수 선배들 사이에서 너무 만족하며 다니고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;edited_스크린샷 2022-07-12 오후 11.24.53.png&quot; data-origin-width=&quot;518&quot; data-origin-height=&quot;89&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/k5ZBb/btrG6Xh3nUN/e3gx62uwkx1QXNG5u7akcK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/k5ZBb/btrG6Xh3nUN/e3gx62uwkx1QXNG5u7akcK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/k5ZBb/btrG6Xh3nUN/e3gx62uwkx1QXNG5u7akcK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fk5ZBb%2FbtrG6Xh3nUN%2Fe3gx62uwkx1QXNG5u7akcK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;518&quot; height=&quot;89&quot; data-filename=&quot;edited_스크린샷 2022-07-12 오후 11.24.53.png&quot; data-origin-width=&quot;518&quot; data-origin-height=&quot;89&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;짧은 기간 동안 첫 직장에서 이직을 하게 되었는데, 첫 직장에서 여러 서비스를 개발하고 런칭한 경험이 큰 도움이 되었다고 생각한다. 여기서 멈추지 않고 더 공부해서 이 회사에서 이름있는 개발자로 성장하고 싶다.&lt;/p&gt;</description>
      <category>이모저모/잡담</category>
      <category>MBC</category>
      <category>NC</category>
      <category>개발자</category>
      <category>엔씨소프트</category>
      <category>이직</category>
      <category>코딩배우는학생</category>
      <author>Blue___</author>
      <guid isPermaLink="true">https://blue-boy.tistory.com/254</guid>
      <comments>https://blue-boy.tistory.com/254#entry254comment</comments>
      <pubDate>Tue, 12 Jul 2022 23:47:35 +0900</pubDate>
    </item>
    <item>
      <title>[BOJ 11053] 가장 긴 증가하는 부분 수열(javascript): DP LIS</title>
      <link>https://blue-boy.tistory.com/253</link>
      <description>&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;문제 설명&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;수열 A가 주어졌을 때, 가장 긴 증가하는&amp;nbsp;부분&amp;nbsp;수열을 구하는 프로그램을 작성하시오.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어, 수열 A = {10, 20, 10, 30, 20, 50} 인 경우에 가장 긴 증가하는 부분&amp;nbsp;수열은&amp;nbsp;A = {&lt;b&gt;10&lt;/b&gt;,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;20&lt;/b&gt;, 10,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;30&lt;/b&gt;, 20,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;50&lt;/b&gt;} 이고, 길이는 4이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1647918415928&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;let n = 8;
let arr = [5, 3, 7, 8, 6, 2, 9, 4];
 
console.log(solution(n, arr));
 
function solution(n, arr){
  if (n === 1) return 1;
  let dp = Array.from({length: n}, () =&amp;gt; 0);
  let answer = 0;
 
  dp[0]=1;
  for (let i=1; i&amp;lt;n; i++){
    let max=0;
    for (let j=i-1; j&amp;gt;=0; j--){
      if (arr[i] &amp;gt; arr[j] &amp;amp;&amp;amp; dp[j] &amp;gt; max) max = dp[j]
    }
    dp[i]=max+1;
    answer = Math.max(answer, dp[i]);
    console.log(dp);
  }
  return answer;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Algorithms/BOJ[Java]</category>
      <category>11053</category>
      <category>dp</category>
      <category>javascript</category>
      <category>LIS</category>
      <category>백준</category>
      <category>코딩배우는 학생</category>
      <author>Blue___</author>
      <guid isPermaLink="true">https://blue-boy.tistory.com/253</guid>
      <comments>https://blue-boy.tistory.com/253#entry253comment</comments>
      <pubDate>Tue, 22 Mar 2022 12:07:23 +0900</pubDate>
    </item>
    <item>
      <title>[Programmers level3] 섬 연결하기(javascript) : 그루스칼 알고리즘</title>
      <link>https://blue-boy.tistory.com/252</link>
      <description>&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;문제 설명&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;n개의 섬 사이에 다리를 건설하는 비용(costs)이 주어질 때, 최소의 비용으로 모든 섬이 서로 통행 가능하도록 만들 때 필요한 최소 비용을 return 하도록 solution을 완성하세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다리를 여러 번 건너더라도, 도달할 수만 있으면 통행 가능하다고 봅니다. 예를 들어 A 섬과 B 섬 사이에 다리가 있고, B 섬과 C 섬 사이에 다리가 있으면 A 섬과 C 섬은 서로 통행 가능합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;제한사항&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;섬의 개수 n은 1 이상 100 이하입니다.&lt;/li&gt;
&lt;li&gt;costs의 길이는&lt;span&gt;&amp;nbsp;&lt;/span&gt;((n-1) * n) / 2이하입니다.&lt;/li&gt;
&lt;li&gt;임의의 i에 대해, costs[i][0] 와 costs[i] [1]에는 다리가 연결되는 두 섬의 번호가 들어있고, costs[i] [2]에는 이 두 섬을 연결하는 다리를 건설할 때 드는 비용입니다.&lt;/li&gt;
&lt;li&gt;같은 연결은 두 번 주어지지 않습니다. 또한 순서가 바뀌더라도 같은 연결로 봅니다. 즉 0과 1 사이를 연결하는 비용이 주어졌을 때, 1과 0의 비용이 주어지지 않습니다.&lt;/li&gt;
&lt;li&gt;모든 섬 사이의 다리 건설 비용이 주어지지 않습니다. 이 경우, 두 섬 사이의 건설이 불가능한 것으로 봅니다.&lt;/li&gt;
&lt;li&gt;연결할 수 없는 섬은 주어지지 않습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;입출력 예&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 60.3488%; height: 67px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;n&lt;/td&gt;
&lt;td&gt;costs&lt;/td&gt;
&lt;td&gt;return&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;[[0,1,1],[0,2,2],[1,2,5],[1,3,1],[2,3,8]]&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;입출력 예 설명&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;costs를 그림으로 표현하면 다음과 같으며, 이때 초록색 경로로 연결하는 것이 가장 적은 비용으로 모두를 통행할 수 있도록 만드는 방법입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;822&quot; data-origin-height=&quot;748&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/DWs75/btrwJvPzZmx/dd6ytMwjNqqSbZwot1UEzK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/DWs75/btrwJvPzZmx/dd6ytMwjNqqSbZwot1UEzK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/DWs75/btrwJvPzZmx/dd6ytMwjNqqSbZwot1UEzK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDWs75%2FbtrwJvPzZmx%2Fdd6ytMwjNqqSbZwot1UEzK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;220&quot; height=&quot;200&quot; data-origin-width=&quot;822&quot; data-origin-height=&quot;748&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;풀이&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MST를 구하는 간단한 문제&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://m.blog.naver.com/ndb796/221230994142&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://m.blog.naver.com/ndb796/221230994142&lt;/a&gt;&amp;nbsp;참고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1647911340239&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const getParent = (parent, x) =&amp;gt; {
    if(parent[x] === x) return x;
    return parent[x] = getParent(parent, parent[x]);
  }
  
  const unionParent = (parent, a, b) =&amp;gt; {
    const n1 = getParent(parent, a);
    const n2 = getParent(parent, b);
    if(n1 &amp;lt; n2) return parent[n2] = n1;
    else return parent[n1] = n2;
  }
  
  const findParent = (parent, a, b) =&amp;gt; {
    const n1 = getParent(parent, a);
    const n2 = getParent(parent, b);
    if(n1 === n2) return true;
    else return false;
  }
  
  function solution(n, costs) {
    let answer = 0;
    const parent = [];
    for(let i = 0; i &amp;lt; n; i++)
      parent.push(i);
    
    costs.sort((a, b) =&amp;gt; a[2] - b[2]);
    
    for(const cost of costs) {
      if(!findParent(parent, cost[0], cost[1])) {
        answer += cost[2];
        unionParent(parent, cost[0], cost[1]);
      }
    }
    
    return answer;
  }&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Algorithms/Programmers[Java]</category>
      <category>그루스칼</category>
      <category>섬 연결하기</category>
      <category>코딩배우는 학생</category>
      <category>프로그래머스</category>
      <author>Blue___</author>
      <guid isPermaLink="true">https://blue-boy.tistory.com/252</guid>
      <comments>https://blue-boy.tistory.com/252#entry252comment</comments>
      <pubDate>Tue, 22 Mar 2022 10:09:29 +0900</pubDate>
    </item>
    <item>
      <title>[Programmers level 3] 이중우선순위 큐 Javascript</title>
      <link>https://blue-boy.tistory.com/251</link>
      <description>&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;문제 설명&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이중 우선순위 큐는 다음 연산을 할 수 있는 자료구조를 말합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;명령어수신 탑(높이)&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;I 숫자&lt;/td&gt;
&lt;td&gt;큐에 주어진 숫자를 삽입합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;D 1&lt;/td&gt;
&lt;td&gt;큐에서 최댓값을 삭제합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;D -1&lt;/td&gt;
&lt;td&gt;큐에서 최솟값을 삭제합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이중 우선순위 큐가 할 연산 operations가 매개변수로 주어질 때, 모든 연산을 처리한 후 큐가 비어있으면 [0,0] 비어있지 않으면 [최댓값, 최솟값]을 return 하도록 solution 함수를 구현해주세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제한사항&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;operations는 길이가 1 이상 1,000,000 이하인 문자열 배열입니다.&lt;/li&gt;
&lt;li&gt;operations의 원소는 큐가 수행할 연산을 나타냅니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;원소는 &amp;ldquo;명령어 데이터&amp;rdquo; 형식으로 주어집니다.- 최댓값/최솟값을 삭제하는 연산에서 최댓값/최솟값이 둘 이상인 경우, 하나만 삭제합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;빈 큐에 데이터를 삭제하라는 연산이 주어질 경우, 해당 연산은 무시합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;입출력예&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 37.2093%; height: 83px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 74.4186%;&quot;&gt;operations&lt;/td&gt;
&lt;td style=&quot;width: 25.4651%;&quot;&gt;return&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 74.4186%;&quot;&gt;[&quot;I 16&quot;,&quot;D 1&quot;]&lt;/td&gt;
&lt;td style=&quot;width: 25.4651%;&quot;&gt;[0,0]&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 74.4186%;&quot;&gt;[&quot;I 7&quot;,&quot;I 5&quot;,&quot;I -5&quot;,&quot;D -1&quot;]&lt;/td&gt;
&lt;td style=&quot;width: 25.4651%;&quot;&gt;[7,5]&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;입출력 예 설명&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;16을 삽입 후 최댓값을 삭제합니다. 비어있으므로 [0,0]을 반환합니다.&lt;br /&gt;7,5,-5를 삽입 후 최솟값을 삭제합니다. 최대값 7, 최소값 5를 반환합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;풀이&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단순 배열로 풀면 쉬운 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시간 복잡도 O(N), 힙 사용하면 O(logN)가능 하긴 한데 직접 힙 PriorityQueue 구현체 구현하기가 좀 ㅇㅅㅇ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1647850820768&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function solution(operations) {
    const pq = [];
    
    operations.forEach(operation =&amp;gt; {
        let [command, num] = operation.split(' '); //I. 16
        num = parseInt(num);
        switch(command){
            case 'I':
                pq.unshift(num);
                break;
            case 'D':
                if(pq.length == 0) break;
                if(num ==1) pq.sort((a,b) =&amp;gt; b - a);
                else if(num == -1) pq.sort((a,b) =&amp;gt; a - b);
                pq.shift();
                break;
        }
    });

    if(!pq.length) return [0,0];

    pq.sort((a,b) =&amp;gt; b - a);
    return [pq[0], pq[pq.length - 1]];
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Algorithms/Programmers[Java]</category>
      <category>javascript</category>
      <category>js</category>
      <category>level3</category>
      <category>이중우선순위큐</category>
      <category>코딩배우는 학생</category>
      <category>프로그래머스</category>
      <author>Blue___</author>
      <guid isPermaLink="true">https://blue-boy.tistory.com/251</guid>
      <comments>https://blue-boy.tistory.com/251#entry251comment</comments>
      <pubDate>Mon, 21 Mar 2022 17:22:02 +0900</pubDate>
    </item>
    <item>
      <title>[Programmers Level 3] 디스크 컨트롤러 (javascript)</title>
      <link>https://blue-boy.tistory.com/250</link>
      <description>&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;문제 설명&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하드디스크는 한 번에 하나의 작업만 수행할 수 있습니다. 디스크 컨트롤러를 구현하는 방법은 여러 가지가 있습니다. 가장 일반적인 방법은 요청이 들어온 순서대로 처리하는 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를들어&lt;/p&gt;
&lt;div&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;- 0ms 시점에 3ms가 소요되는 A작업 요청
- 1ms 시점에 9ms가 소요되는 B작업 요청
- 2ms 시점에 6ms가 소요되는 C작업 요청
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;와 같은 요청이 들어왔습니다. 이를 그림으로 표현하면 아래와 같습니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;341&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bEQCDg/btrwJvgI5WU/pmqkjYQRn9FlGhbgdGotEK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bEQCDg/btrwJvgI5WU/pmqkjYQRn9FlGhbgdGotEK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bEQCDg/btrwJvgI5WU/pmqkjYQRn9FlGhbgdGotEK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbEQCDg%2FbtrwJvgI5WU%2FpmqkjYQRn9FlGhbgdGotEK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1280&quot; height=&quot;341&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;341&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;한 번에 하나의 요청만을 수행할 수 있기 때문에 각각의 작업을 요청받은 순서대로 처리하면 다음과 같이 처리 됩니다.&lt;/p&gt;
&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1256&quot; data-origin-height=&quot;438&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cMFfDj/btrwKGvjagV/iCaCKqnSkOMtYk16PPSKjK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cMFfDj/btrwKGvjagV/iCaCKqnSkOMtYk16PPSKjK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cMFfDj/btrwKGvjagV/iCaCKqnSkOMtYk16PPSKjK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcMFfDj%2FbtrwKGvjagV%2FiCaCKqnSkOMtYk16PPSKjK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1256&quot; height=&quot;438&quot; data-origin-width=&quot;1256&quot; data-origin-height=&quot;438&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;div&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;- A: 3ms 시점에 작업 완료 (요청에서 종료까지 : 3ms)
- B: 1ms부터 대기하다가, 3ms 시점에 작업을 시작해서 12ms 시점에 작업 완료(요청에서 종료까지 : 11ms)
- C: 2ms부터 대기하다가, 12ms 시점에 작업을 시작해서 18ms 시점에 작업 완료(요청에서 종료까지 : 16ms)
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 때 각 작업의 요청부터 종료까지 걸린 시간의 평균은 10ms(= (3 + 11 + 16) / 3)가 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 A &amp;rarr; C &amp;rarr; B 순서대로 처리하면&lt;/p&gt;
&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;437&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dhqz9D/btrwGj80lpg/0N1DPTomAwZCaJBz2KuUd0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dhqz9D/btrwGj80lpg/0N1DPTomAwZCaJBz2KuUd0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dhqz9D/btrwGj80lpg/0N1DPTomAwZCaJBz2KuUd0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdhqz9D%2FbtrwGj80lpg%2F0N1DPTomAwZCaJBz2KuUd0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1280&quot; height=&quot;437&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;437&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;div&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;- A: 3ms 시점에 작업 완료(요청에서 종료까지 : 3ms)
- C: 2ms부터 대기하다가, 3ms 시점에 작업을 시작해서 9ms 시점에 작업 완료(요청에서 종료까지 : 7ms)
- B: 1ms부터 대기하다가, 9ms 시점에 작업을 시작해서 18ms 시점에 작업 완료(요청에서 종료까지 : 17ms)
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 A &amp;rarr; C &amp;rarr; B의 순서로 처리하면 각 작업의 요청부터 종료까지 걸린 시간의 평균은 9ms(= (3 + 7 + 17) / 3)가 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 작업에 대해 [작업이 요청되는 시점, 작업의 소요시간]을 담은 2차원 배열 jobs가 매개변수로 주어질 때, 작업의 요청부터 종료까지 걸린 시간의 평균을 가장 줄이는 방법으로 처리하면 평균이 얼마가 되는지 return 하도록 solution 함수를 작성해주세요. (단, 소수점 이하의 수는 버립니다)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;제한 사항&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;jobs의 길이는 1 이상 500 이하입니다.&lt;/li&gt;
&lt;li&gt;jobs의 각 행은 하나의 작업에 대한 [작업이 요청되는 시점, 작업의 소요시간] 입니다.&lt;/li&gt;
&lt;li&gt;각 작업에 대해 작업이 요청되는 시간은 0 이상 1,000 이하입니다.&lt;/li&gt;
&lt;li&gt;각 작업에 대해 작업의 소요시간은 1 이상 1,000 이하입니다.&lt;/li&gt;
&lt;li&gt;하드디스크가 작업을 수행하고 있지 않을 때에는 먼저 요청이 들어온 작업부터 처리합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;b&gt;입출력 예&lt;/b&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 30.2936%; height: 80px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;jobs&lt;/td&gt;
&lt;td&gt;return&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;[[0, 3], [1, 9], [2, 6]]&lt;/td&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;입출력 예 설명&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제에 주어진 예와 같습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;0ms 시점에 3ms 걸리는 작업 요청이 들어옵니다.&lt;/li&gt;
&lt;li&gt;1ms 시점에 9ms 걸리는 작업 요청이 들어옵니다.&lt;/li&gt;
&lt;li&gt;2ms 시점에 6ms 걸리는 작업 요청이 들어옵니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;풀이&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Java로 풀면 PriorityQueue 구현체를 통해 풀어주면 되지만 자바스크립트로는 아쉽게도 구현체를 직접 적용해 풀어야 하는 문제.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단순 배열로 풀어주면 NlogN의 시간복잡도를 가지며 Heap을 통한 PriorityQueue 구현체를 통해 풀 경우 logN의 시간복잡도를 평균적으로 도출할 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;규칙을 찾아보면 먼저 jobs를 [idx][1]를 기준으로 오름차순 한뒤 priorityQueue에 모든 값을 offer해줘서 정렬해준뒤, 제시된 문제에 맞게 연산하면 된다. ㅇㅅㅇ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1647848693269&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function PriorityQueue(callback){
    this.queue = [];
    this.length = this.queue.length;
    this.callback = callback;
}

PriorityQueue.prototype.sort = function(callback){
    Array.prototype.sort.call(this.queue, this.callback || callback);
};

PriorityQueue.prototype.offer = function(value){
    this.queue.push(value);
    this.length = this.queue.length;
    this.sort();
};

PriorityQueue.prototype.add = function(value){
    try{
        this.offer(value);
        return true;
    }catch(Exception){
        throw Error('IllegalStateException');
    }
};

PriorityQueue.prototype.poll = function(){
    var result;
    
    if( this.queue.length &amp;gt; 0 )
        result = this.queue.shift();
    else
        result = null;
    
    this.length = this.queue.length;
    return result;
};

PriorityQueue.prototype.remove = function(){
    this.poll();
};

PriorityQueue.prototype.clear = function(){
    this.queue = [];
    this.length = 0;
};

function solution(jobs) {
    let answer = 0;    
    
    jobs.sort((a, b)=&amp;gt;a[0] - b[0]);
    
    let now,total,index = 0;    
    
    const priorityQueue = new PriorityQueue((a, b) =&amp;gt; a[1]-b[1]);

    while( index &amp;lt; jobs.length || priorityQueue.length &amp;gt; 0 ){
        if( index &amp;lt; jobs.length &amp;amp;&amp;amp; now &amp;gt;= jobs[index][0] ){
            priorityQueue.offer(jobs[index]);
            index = index + 1;
            continue;
        }
        
        if( !priorityQueue.length ){
            now = jobs[index][0];
        }else{
            const data = priorityQueue.poll();   
            now = now + data[1];    
            total = now - data[0];
            answer = answer + total;
        }
    }

    answer = parseInt(answer / jobs.length);
    return answer;
}

const jobs = [[0, 3], [1, 9], [2, 6]];
console.log(solution(jobs)); //9&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Algorithms/Programmers[Java]</category>
      <author>Blue___</author>
      <guid isPermaLink="true">https://blue-boy.tistory.com/250</guid>
      <comments>https://blue-boy.tistory.com/250#entry250comment</comments>
      <pubDate>Mon, 21 Mar 2022 16:47:24 +0900</pubDate>
    </item>
    <item>
      <title>[BOJ/1987번] 알파벳</title>
      <link>https://blue-boy.tistory.com/249</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;문제&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;세로 R칸, 가로 C칸으로 된 표 모양의 보드가 있다. 보드의 각 칸에는 대문자 알파벳이 하나씩 적혀 있고, 좌측 상단 칸 (1행 1열) 에는 말이 놓여 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;말은 상하좌우로 인접한 네 칸 중의 한 칸으로 이동할 수 있는데, 새로 이동한 칸에 적혀 있는 알파벳은 지금까지 지나온 모든 칸에 적혀 있는 알파벳과는 달라야 한다. 즉, 같은 알파벳이 적힌 칸을 두 번 지날 수 없다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;좌측 상단에서 시작해서, 말이 최대한 몇 칸을 지날 수 있는지를 구하는 프로그램을 작성하시오. 말이 지나는 칸은 좌측 상단의 칸도 포함된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;입력값&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #555555; font-family: 'Noto Sans Light';&quot;&gt;첫째 줄에 R과 C가 빈칸을 사이에 두고 주어진다. (1 &amp;le; R,C &amp;le; 20) 둘째 줄부터 R개의 줄에 걸쳐서 보드에 적혀 있는 C개의 대문자 알파벳들이 빈칸 없이 주어진다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;Input&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1644673417972&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;3 6
HFDFFB
AJHGDH
DGAGEH&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;Output&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1644673417972&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;6&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;Input&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1644673286250&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;5 5
IEFCJ
FHFKC
FFALF
HFGCF
HMCHH&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;Output&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1644673286252&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;10&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;풀이&lt;/span&gt;&lt;/blockquote&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;백트래킹을 이용한 DFS문제.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;Set에 지나온 알파벳을 저장하고 포함여부로 조건을 확인한다. 조건이 모두 종료되는 시점의 max값을 도출하는 문제.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1644673286253&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.io.*;
import java.util.*;

class Main {
    static int n = 3;
    static int m = 3;
    static int[][] dirs = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
    static int max =1;
	public static void main(String[] args) throws Exception {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 
        StringTokenizer st = new StringTokenizer(br.readLine());   
        n = Integer.parseInt(st.nextToken()); 
        m = Integer.parseInt(st.nextToken()); 
        
        char[][]arr = new char[n][m];
        for(int i=0;i&amp;lt;n;i++){
            String temp = br.readLine();
            for(int j=0;j&amp;lt;m;j++){
                arr[i][j] = temp.charAt(j);
            }
        }
        int[] start ={0,0};
        Set&amp;lt;Character&amp;gt; set = new HashSet&amp;lt;&amp;gt;();
        set.add(arr[0][0]);
        int cnt =1;
        dfs(arr,start, set,cnt);
        System.out.println(max);
    }
    private static void dfs(char[][]arr, int[]start, Set&amp;lt;Character&amp;gt;set,int cnt){
        max = Math.max(max,cnt);     

        for(int[] dir: dirs){
            int nx = start[0] + dir[0];
            int ny = start[1] + dir[1];
            if(nx&amp;gt;=0 &amp;amp;&amp;amp; nx&amp;lt;n &amp;amp;&amp;amp; ny&amp;gt;=0 &amp;amp;&amp;amp; ny&amp;lt;m &amp;amp;&amp;amp; !set.contains(arr[nx][ny])){
                set.add(arr[nx][ny]);
                dfs(arr,new int[]{nx,ny},set,cnt+1);
                set.remove(arr[nx][ny]);
            }
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/1987&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://www.acmicpc.net/problem/1987&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1644673617096&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;1987번: 알파벳&quot; data-og-description=&quot;세로 R칸, 가로 C칸으로 된 표 모양의 보드가 있다. 보드의 각 칸에는 대문자 알파벳이 하나씩 적혀 있고, 좌측 상단 칸 (1행 1열) 에는 말이 놓여 있다. 말은 상하좌우로 인접한 네 칸 중의 한 칸으&quot; data-og-host=&quot;www.acmicpc.net&quot; data-og-source-url=&quot;https://www.acmicpc.net/problem/1987&quot; data-og-url=&quot;https://www.acmicpc.net/problem/1987&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/clD47K/hyNn0LXBhw/wuUIVdJPKSLBshnw4cuyn0/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/1987&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.acmicpc.net/problem/1987&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/clD47K/hyNn0LXBhw/wuUIVdJPKSLBshnw4cuyn0/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;1987번: 알파벳&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;세로 R칸, 가로 C칸으로 된 표 모양의 보드가 있다. 보드의 각 칸에는 대문자 알파벳이 하나씩 적혀 있고, 좌측 상단 칸 (1행 1열) 에는 말이 놓여 있다. 말은 상하좌우로 인접한 네 칸 중의 한 칸으&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.acmicpc.net&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Algorithms/BOJ[Java]</category>
      <category>1987</category>
      <category>1987번</category>
      <category>baekjoon 1987</category>
      <category>dfs</category>
      <category>Java</category>
      <category>깊이 우선 탐색</category>
      <category>백준</category>
      <category>백트래킹</category>
      <category>자바</category>
      <category>코딩배우는 학생</category>
      <author>Blue___</author>
      <guid isPermaLink="true">https://blue-boy.tistory.com/249</guid>
      <comments>https://blue-boy.tistory.com/249#entry249comment</comments>
      <pubDate>Sat, 12 Feb 2022 22:47:50 +0900</pubDate>
    </item>
    <item>
      <title>[Git] private config 설정 정보 submodule로 관리하기</title>
      <link>https://blue-boy.tistory.com/248</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;git submodule 도입 배경&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;개발 진행시 배포 과정에서 설정파일 같은 private한 파일의 경우 레포지토리에서 누락되고, 직접 서버에서 config 파일을 배포하는 경우가 발생하게 됩니다. 이에따라 개발과정에서도 공통된 설정파일을 이용할 수 없는 문제점이 발생하거나 멀티 모듈 방식을 이용할 경우 여러 곳에서 공통된 설정파일을 요할 수 있습니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;서브모듈을 통해 설정파일 디렉토리만&amp;nbsp; private 하게 가져가고 앞에 언급한 문제점을 해소하고자 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;git submodule이란?&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;하나의 레퍼지토리 안에 있는 또 다른 별개의 서브 레퍼지토리로 서브모듈만 별도로 private하게 가져갈 수 있는 장점이 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;서브모듈 레퍼지토리 생성후 기존 레포지토리에 다음과 같이 추가해주면 생성 가능합니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1644672379212&quot; class=&quot;armasm&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;git submodule add [git레퍼지토리 url] [folder이름설정]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;초기 생성시 업데이트를 해줘야합니다. 이후 git submodule update로 업데이트 가능.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1644672503491&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;git submodule update --init --recursive&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;다음과 같이 반영됨. 이를 통해 원하는 디렉토리만 private하게 가져갈 수 있게 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1256&quot; data-origin-height=&quot;338&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bjBeYy/btrs22jT7m4/zEGxN2gYFTRl2gUdfkOuC0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bjBeYy/btrs22jT7m4/zEGxN2gYFTRl2gUdfkOuC0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bjBeYy/btrs22jT7m4/zEGxN2gYFTRl2gUdfkOuC0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbjBeYy%2Fbtrs22jT7m4%2FzEGxN2gYFTRl2gUdfkOuC0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1256&quot; height=&quot;338&quot; data-origin-width=&quot;1256&quot; data-origin-height=&quot;338&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>Git</category>
      <author>Blue___</author>
      <guid isPermaLink="true">https://blue-boy.tistory.com/248</guid>
      <comments>https://blue-boy.tistory.com/248#entry248comment</comments>
      <pubDate>Sat, 12 Feb 2022 22:38:47 +0900</pubDate>
    </item>
    <item>
      <title>고차 컴포넌트 패턴(HOC)과 믹스인(Mixins)</title>
      <link>https://blue-boy.tistory.com/247</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;하이오더컴포넌트는 리액트 진영에서 기반한 컴포넌트 개발 패턴이다. 컴포넌트의 로직을 훼손하지 않고 재사용성을 최대로 끌어올리는 것에 장점이 있지만, 중간 컴포넌트가 하나 추가되므로 depth가 깊어질 수록 컴포넌트 구조가 복잡해지는 단점이 존재한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;반대로 믹스인의 경우 HOC에 비해 쉽고 고차 컴포넌트에 대한 생각을 안해도 되지만, SOC(관심사 분리), 컴포넌트 테스트 측면에서 HOC에 비해 불리하다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;때문에 둘의 패턴을 적절히 활용해 반복되는 코드의 역할을 단일화시키며 재활용이 용이하게, 외부 종속성을 최소화 하는 것을 유의하며 적용해야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;img.png&quot; data-origin-width=&quot;731&quot; data-origin-height=&quot;262&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/brGWlQ/btro7hc88ls/K9uMm5XSMFHxQgTsjfX8GK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/brGWlQ/btro7hc88ls/K9uMm5XSMFHxQgTsjfX8GK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/brGWlQ/btro7hc88ls/K9uMm5XSMFHxQgTsjfX8GK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbrGWlQ%2Fbtro7hc88ls%2FK9uMm5XSMFHxQgTsjfX8GK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;731&quot; height=&quot;262&quot; data-filename=&quot;img.png&quot; data-origin-width=&quot;731&quot; data-origin-height=&quot;262&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;믹스인(Mixins)&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt; 글로벌 믹스인(Global Mixins)&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;믹스인은 여러 Vue 컴포넌트에서 기능을 재사용하는 방법이다. 컴포넌트가 믹스인을 사용하면 모든 옵션과 기능이 컴포넌트 자체 옵션에 &quot;혼합&quot;되거나 &quot;병합&quot;된다. 글로벌 믹스인은 mixin 속성을 사용하여 Vue 인스턴스에서 사용되며&amp;nbsp; 사용하는 모든 컴포넌트에서 옵션을 사용할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1640678677579&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;new Vue({
  el: '#demo',
  mixins: [MyMixin]
});&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;예를들어 만약 매우 간단한 Translate 서비스를 구현하려고 한다면 모든 컴포넌트가 번역 문자열을 조회할 수 있도록 번역 기능을 제공해야 한다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1640678721364&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;new Vue({
  el: '#demo',
  mixins: [Translate],
  data: {
    locale: &quot;en&quot;
  }
});&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;Translate 믹스인은 다음과 같다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1640678748936&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// some example translations of two languages
const TRANSLATIONS = {
  en: {
    firstName: &quot;Firstname&quot;,
    age: &quot;Age&quot;
  },
  de: {
    firstName: &quot;Vorname&quot;,
    age: &quot;Alter&quot;
  }
};

const Translate = Vue.mixin({
  methods: {
    translate(key) {
      return TRANSLATIONS[this.$root.locale][key];
    }
  },
  ready() {
    // default locale set to &quot;en&quot;
    this.$root.$set(&quot;locale&quot;, &quot;en&quot;);
  }
});&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;Translate 기능은 Vue 인스턴스와 키로 구성된 로케일을 사용하여 번역된 문자열을 찾는다. Vue 인스턴스가 로케일을 설정하지 않는 경우 준비된 LifeCycle Hook를 사용하여 직접 설정한다. &lt;/span&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;Translate 믹스인을 Vue 인스턴스와 혼합하여 이제 다른 컴포넌트에서 번역(key) 함수를 호출할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;이제 이름과 나이를 렌더링하는 작은 카드 컴포넌트를 작성하겠다.&lt;/span&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1640678879335&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Vue.component(&quot;card-profile&quot;, {
  template: &quot;#card-profile-template&quot;,
  props: {
    firstName: String,
    age: String
  }
});&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1640678907238&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;template id=&quot;card-profile-template&quot;&amp;gt;  
  &amp;lt;div&amp;gt;
    &amp;lt;h2&amp;gt;My Profile&amp;lt;/h2&amp;gt;
    &amp;lt;div&amp;gt;
      : 
    &amp;lt;/div&amp;gt;
    &amp;lt;div&amp;gt;
      : 
    &amp;lt;/div&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;컴포넌트를 정의했고 이제 이를 렌더링 할 수 있을 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1640678960871&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;div id=&quot;demo&quot;&amp;gt;
  &amp;lt;card-profile first-name=&quot;Michael&quot; age=&quot;30&quot; /&amp;gt;
  &amp;lt;card-profile first-name=&quot;Lana&quot; age=&quot;32&quot; /&amp;gt;
&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;글로벌 믹스인의 모든 옵션은 모든 컴포넌트에 혼합되어 빠르게 사용할 수 없게 되므로 왠만하면 사용하지 않아야 한다. 이런 경우 로컬 믹스인을 사용할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt; 로컬믹스인(Local Mixins)&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;로컬 믹스인의 옵션은 해당 믹스인을 사용하는 컴포넌트요소에만 적용되며 Global에 비해서 더 쉽게 관리할 수 있다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1640679224140&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const DataLoader = Vue.mixin({
  data() {
    return {
      loading: false,
      response: null
    }
  },
  methods: {
    load(url) {
      this.loading = true;
      return axios.get(url)
        .then(response =&amp;gt; {
          this.response = response.data;
          this.loading = false;
        })
    }
  }
});&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;axios를 다시 사용하여 원격 URL에서 일부 데이터를 가져오는 로드 방법을 제공하며&amp;nbsp; 로드 및 응답 데이터가 제공된다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;이제 컴포넌트에서 이 믹스인을 사용해 보겠다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1640679267776&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Vue.component(&quot;article-card&quot;, {
  mixins: [DataLoader],
  template: &quot;#article-card-template&quot;,
  created() {
    this.load(&quot;https://jsonplaceholder.typicode.com/posts/1&quot;)
  }
});&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;믹스인 옵션을 사용하여 DataLoader를 사용하고 생성된 라이프사이클 Hooks에서 믹스인이 제공하는 로드 기능을 호출한다. &lt;/span&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;article-card 컴포넌트의 템플릿은 로드 상태에 따라 데이터를 표시한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1640679375796&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;template id=&quot;article-card-template&quot;&amp;gt;  
  &amp;lt;div&amp;gt;
    &amp;lt;span v-if=&quot;loading&quot;&amp;gt;Loading...&amp;lt;/span&amp;gt;
    &amp;lt;div v-else&amp;gt;
      &amp;lt;h2&amp;gt;&amp;lt;/h2&amp;gt;
      
    &amp;lt;/div&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;실제로 컴포넌트에 자체 상태 로드 또는 응답이 있는 경우 믹스인 상태와 충돌하고 확실히 혼동을 일으킬 것이다. 메서드, 컴포넌트 및 지시문 옵션도 마찬가지다. 컴포넌트에는 항상 우선 순위가 있고 LifeCycle 메서드에 관해서는 둘 다 호출되지만 mixin의 메서드가 먼저 호출된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-size=&quot;size16&quot; data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;컴포넌트 확장(Extending Components)&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;컴포넌트 확장으로 Vue.js에서 코드를 재사용할 수도 있다. 바로 extends를 활용하는 것이다.&amp;nbsp; extends를 활용해 원래 컴포넌트의 대부분의 코드를 재사용하는 새 컴포넌트를 빌드해 보도록 하겠다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1640679672365&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const BaseArticleCard = Vue.component(&quot;base-article-card&quot;, {
  props: [&quot;id&quot;],
  template: &quot;#base-article-card-template&quot;,
  data() {
    return {
      loading: false,
      title: &quot;&quot;,
      body: &quot;&quot;,
      userId: &quot;&quot;
    }
  },
  computed: {
    articleTitle() {
      return `Article: ${this.title}`;
    }
  },
  methods: {
    load(id) {
      this.loading = true;
      return axios.get(`https://jsonplaceholder.typicode.com/posts/${id}`)
        .then(response =&amp;gt; {
          this.title = response.data.title;
          this.body = response.data.body;
          this.userId = response.data.userId;
          this.loading = false;
        });
    }
  },
  created() {
    this.load(this.id);
  }
});&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;로드 메서드를 통해 생성된 hooks에서 axios 요청을 통해 데이터를 가져오기 위해 유사한 코드를 재사용했다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1640679770326&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;template id=&quot;base-article-card-template&quot;&amp;gt;  
  &amp;lt;div class=&quot;article-card&quot;&amp;gt;
    &amp;lt;div v-if=&quot;loading&quot;&amp;gt;Loading...&amp;lt;/div&amp;gt;
    &amp;lt;div v-else&amp;gt;
      &amp;lt;h2&amp;gt;Vue.js Mixins, extending components and High Order Components&amp;lt;/h2&amp;gt;
      
    &amp;lt;/div&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;만약 이같은 형식을 반복한다고 했을 때 상속처럼 간단히 확장할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1640679841777&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Vue.component(&quot;advanced-article-card&quot;, {
  extends: BaseArticleCard,
  template: &quot;#advanced-article-card-template&quot;
});&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;그리고 템플릿에 적용해 보겠다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1640679880303&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;template id=&quot;advanced-article-card-template&quot;&amp;gt;  
  &amp;lt;div class=&quot;article-card&quot;&amp;gt;
    &amp;lt;div v-if=&quot;loading&quot;&amp;gt;Loading...&amp;lt;/div&amp;gt;
    &amp;lt;div v-else&amp;gt;
      &amp;lt;h2&amp;gt;&amp;lt;/h2&amp;gt;
      &amp;lt;p&amp;gt;Written by User ID: &amp;lt;/p&amp;gt;
      
    &amp;lt;/div&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;개인적으로 확장을 사용하는 것은 믹스인과 유사해보이며, 믹스인이 더 합리적이라는 생각이 든다. 상속을 받아 컴포넌트를 재정의할 필요없이 좀 더 직관적으로 믹스인을 받아 재정의하는 것이 합당한 것 같다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-size=&quot;size16&quot; data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;하이 오더 컴포넌트(HOC)&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;같은 방식으로 데이터 로딩 컴포넌트를 구성해 보겠다. 데이터를 가져오고 props를 통해 데이터를 컴포넌트와 함께 전달하는 HOC로 이전 예제의 카드 컴포넌트를 확장해보겠다. Vue-cli를 통해 SFC 환경에서 구성해보겠다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1640680109029&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// our component
import ArticleCard from &quot;./components/ArticleCard.vue&quot;;
// the HOC function
import withLoader from &quot;./withLoader&quot;;
// our combined resulting component
const ArticleCardWithLoader = withLoader(ArticleCard);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;ArticleCard 컴포넌트를 입력으로 가져오고 확장 컴포넌트 ArticleCardWithLoader를 반환한다. 보통 위와 같이 사용하거나 라우터에서 코드스플리팅으로 적용해 사용해보았는데 확실히 컴포넌트 depth가 깊어져 복잡해지는 문제점이 있었다. 컴포넌트가 아닌 js로 작성합니다. React의 구성과 유사하다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1640680222039&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// withLoader.js
import Vue from &quot;vue&quot;;
import axios from &quot;axios&quot;;

const withLoader = component =&amp;gt; {
  return Vue.component(&quot;with-loader&quot;, {
    render(createElement) {
      return createElement(component, {
        props: {
          loading: this.loading,
          title: this.title,
          body: this.body
        }
      });
    },
    props: [&quot;id&quot;],
    data() {
      return {
        loading: false,
        title: &quot;&quot;,
        body: &quot;&quot;,
      }
    },
    methods: {
      load(id) {
        this.loading = true;
        return axios.get(`https://jsonplaceholder.typicode.com/posts/${id}`)
          .then(response =&amp;gt; {
            this.title = response.data.title;
            this.body = response.data.body;
            this.loading = false;
          });
      }
    },
    created() {
      this.load(this.id);
    }
  });
};

export default withLoader;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;상위와 하위 컴포넌트 사이에 HOC가 위치해 하위 컴포넌트를 래핑하는 모양을 가지고 있다. 렌더 함수의 로딩, 제목 및 본문등을 전달하는 새 컴포넌트를 반환한다. 그리고 반환된 컴포넌트 자체만으로는 HOC 컴포넌트에 의해 래핑된다는 것을 알 수 없다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1640680367836&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;template&amp;gt;
  &amp;lt;div class=&quot;article-card&quot;&amp;gt;
    &amp;lt;div v-if=&quot;loading&quot;&amp;gt;Loading...&amp;lt;/div&amp;gt;
    &amp;lt;div v-else&amp;gt;
      &amp;lt;h2&amp;gt;Vue.js Mixins, extending components and High Order Components&amp;lt;/h2&amp;gt;
      
    &amp;lt;/div&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;script&amp;gt;
export default {
  props: {
    loading: Boolean,
    title: String,
    body: String
  }
};
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;이는 props를 상위에서 하위로 전달하기 위해서는 HOC 컴포넌트를 변경하지 않고는 추가 props를 전달할 수 없다. 하지만 덜 의존적이고 SOC 측면에서 믹스인보다 유리하다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-size=&quot;size16&quot; data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;결론&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;Vue.js 공식 레퍼런스에서는 HOC 대신 믹스인과 scoped-slot을 통한 구성을 선호하고 있다. 하지만 아직까지 지속적으로 토론 중인 주제이고 개인적으로도 개인의 성향과 사용여부에 따라 크게 상관없이 사용하면 된다고 생각한다.&amp;nbsp; 개인적으로 다음 프로젝트에 앞서 기존 앱을 리팩토링하면서 지속적으로 사용 중인데, 후에 사용 후기를 남길 예정이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;출처: &lt;a href=&quot;https://fdietz.de/posts/vue.js-mixins-extending-components-and-high-order-components/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://fdietz.de/posts/vue.js-mixins-extending-components-and-high-order-components/ &lt;/a&gt;&lt;/span&gt;&lt;/p&gt;</description>
      <category>Web/Vue</category>
      <category>component</category>
      <category>HOC</category>
      <category>mixins</category>
      <category>SFC</category>
      <category>VUE</category>
      <category>vue-cli</category>
      <category>고차</category>
      <category>뷰</category>
      <category>컴포넌트</category>
      <category>코딩배우는 학생</category>
      <author>Blue___</author>
      <guid isPermaLink="true">https://blue-boy.tistory.com/247</guid>
      <comments>https://blue-boy.tistory.com/247#entry247comment</comments>
      <pubDate>Tue, 28 Dec 2021 17:40:48 +0900</pubDate>
    </item>
  </channel>
</rss>