<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>  dev-ruby</title>
    <link>https://juyami.tistory.com/</link>
    <description>FE-Developer</description>
    <language>ko</language>
    <pubDate>Thu, 20 Aug 2026 19:39:25 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>ruby_s</managingEditor>
    <image>
      <title>  dev-ruby</title>
      <url>https://tistory1.daumcdn.net/tistory/4883707/attach/37f527bd401b417582143af307ae588c</url>
      <link>https://juyami.tistory.com</link>
    </image>
    <item>
      <title>TypeScript로 npm package에 배포하기 | React Custom hook 배포</title>
      <link>https://juyami.tistory.com/123</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;이번에 WebRTC 관련 hook을 만들었는데, 공부하면서 구현하기까지 시간이 &lt;span&gt;꽤&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;걸렸던 것 같다. 그래서 내가 만든 훅을 npm package에 올려서 다른 분들이 도움을 받을 수 있으면 좋지 않을까! 라는 생각에 처음으로! 올려봤다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.npmjs.com/package/@ruby-s/use-rtc&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://www.npmjs.com/package/@ruby-s/use-rtc&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1672401169017&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;@ruby-s/use-rtc&quot; data-og-description=&quot;React hook to connect to WebRTC. Latest version: 1.1.8, last published: 19 hours ago. Start using @ruby-s/use-rtc in your project by running &amp;#96;npm i @ruby-s/use-rtc&amp;#96;. There are no other projects in the npm registry using @ruby-s/use-rtc.&quot; data-og-host=&quot;www.npmjs.com&quot; data-og-source-url=&quot;https://www.npmjs.com/package/@ruby-s/use-rtc&quot; data-og-url=&quot;https://www.npmjs.com/package/@ruby-s/use-rtc&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bhd8Tg/hyQ5zXYgu2/XpPgvRIxBN9G6c6A7XFoqK/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630&quot;&gt;&lt;a href=&quot;https://www.npmjs.com/package/@ruby-s/use-rtc&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.npmjs.com/package/@ruby-s/use-rtc&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bhd8Tg/hyQ5zXYgu2/XpPgvRIxBN9G6c6A7XFoqK/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;@ruby-s/use-rtc&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;React hook to connect to WebRTC. Latest version: 1.1.8, last published: 19 hours ago. Start using @ruby-s/use-rtc in your project by running `npm i @ruby-s/use-rtc`. There are no other projects in the npm registry using @ruby-s/use-rtc.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.npmjs.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1. npm 가입&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;npm에 패키지를 등록하기 위해서&amp;nbsp;&lt;a title=&quot;npm 공식 홈페이지&quot; href=&quot;https://www.npmjs.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://www.npmjs.com/&lt;/a&gt;에서 가입하자.&lt;b&gt;&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2. package.json 파일 생성&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1672398746476&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;npm init -y&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-y 옵셥으로 바로 기본적인 &lt;b&gt;pakage.json&amp;nbsp;&lt;/b&gt;&lt;span style=&quot;color: #555555;&quot;&gt;파일을 생성해줍니다.&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #555555;&quot;&gt;이제 내 패키지에 맞게 설정해줍니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1672397994338&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;{
  &quot;name&quot;: &quot;@ruby-s/use-rtc&quot;,
  &quot;version&quot;: &quot;1.0.0&quot;,
  &quot;description&quot;: &quot;React hook to connect to WebRTC&quot;,
  &quot;main&quot;: &quot;dist/index.js&quot;,
  &quot;types&quot;: &quot;dist/index.d.ts&quot;,
  &quot;scripts&quot;: {
    &quot;build&quot;: &quot;tsc&quot;
  },
  &quot;repository&quot;: {
    &quot;type&quot;: &quot;git&quot;,
    &quot;url&quot;: &quot;git+https://github.com/juyeong-s/RTC.git&quot;
  },
  &quot;author&quot;: &quot;juyeong-s&quot;,
  &quot;license&quot;: &quot;MIT&quot;,
  &quot;keywords&quot;: [
    &quot;React&quot;,
    &quot;Hook&quot;,
    &quot;WebRTC&quot;,
    &quot;useRTC&quot;
  ],
  &quot;bugs&quot;: {
    &quot;url&quot;: &quot;https://github.com/juyeong-s/RTC/issues&quot;
  },
  &quot;homepage&quot;: &quot;https://github.com/juyeong-s/RTC#readme&quot;,
  &quot;dependencies&quot;: {
    &quot;socket.io-client&quot;: &quot;^4.5.4&quot;,
    &quot;typescript&quot;: &quot;^4.9.3&quot;
  },
  &quot;peerDependencies&quot;: {
    &quot;react&quot;: &quot;&amp;gt;=16.8.0&quot;,
    &quot;react-dom&quot;: &quot;&amp;gt;=16.8.0&quot;
  },
  &quot;devDependencies&quot;: {
    &quot;@types/node&quot;: &quot;^18.11.18&quot;,
    &quot;@types/react&quot;: &quot;^18.0.26&quot;
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;name&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;고유한 패키지명입니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;version&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;패키지 버전입니다. 업데이트할 때마다 버전을 다르게 설정해주어야 합니다. 기존의 버전으로 다시 올리려고 할 경우 에러가 나므로 조심할 것.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;description&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;패키지 설명입니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span&gt;main&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;프로젝트에서 기본 진입 파일을 지정한다.&lt;br /&gt;TypeScript의 경우 ts 파일을 빌드한 후 생성된 js 파일이 있는 위치로 지정해주어야 한다.&lt;br /&gt;나 같은 경우, tsconfig.json 파일에 빌드된 파일이 &lt;span&gt;dist폴더 안에&lt;span&gt; 생성되도록 지정해주었으므로 main에 dist/index.js로 지정했다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1672399655683&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// tsconfig.json
{
  &quot;compilerOptions&quot;: {
    &quot;target&quot;: &quot;es5&quot;,
    &quot;module&quot;: &quot;commonjs&quot;,
    &quot;declaration&quot;: true,
    &quot;outDir&quot;: &quot;./dist&quot;,
    &quot;strict&quot;: true
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;npm run build -&amp;gt; dist 폴더 안에 js 파일들 생성됨 -&amp;gt; 처음 진입할 파일을 main에 지정&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span&gt;types&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이 속성을 TypeScript를 사용했을 경우에 필요하다. 위와 마찬가지로 build를 하면 dist폴더에 js 파일과 .d.ts 파일이 함께 생성된다.&lt;br /&gt;이때 .d.ts 위치를 지정해주면 된다.&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span&gt;scripts&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이 속성은 TypeScript를 사용했을 경우 build할 필요가 있기 때문에 쓰일 것 같다. build 명령어로 tsc 커맨드를 지정해서 ts파일을 컴파일하도록 한다.&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span&gt;repository&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #34495e;&quot;&gt;코드가 존재하는 주소를 지정하면 된다. npm docs로 패키지 저장소를 찾을 수 있게 해준다. 다음과 같이 npm 패키지 오른편에 보인다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-12-30 오후 8.37.47.png&quot; data-origin-width=&quot;300&quot; data-origin-height=&quot;66&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cfj3Xl/btrU2KHFRms/Q2HN9MaAOd3P4lxo6px3EK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cfj3Xl/btrU2KHFRms/Q2HN9MaAOd3P4lxo6px3EK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cfj3Xl/btrU2KHFRms/Q2HN9MaAOd3P4lxo6px3EK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcfj3Xl%2FbtrU2KHFRms%2FQ2HN9MaAOd3P4lxo6px3EK%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;300&quot; height=&quot;66&quot; data-filename=&quot;스크린샷 2022-12-30 오후 8.37.47.png&quot; data-origin-width=&quot;300&quot; data-origin-height=&quot;66&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span&gt;author&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;패키지 제작자의 이름을 지정한다. 이름만 해도 되고, 다음과 같이 해주어도 된다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1672400088549&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;{
  &quot;author&quot;: {
    &quot;name&quot;: &quot;juyeong-s&quot;,
    &quot;email&quot;: &quot;happyu9986@gmail.com&quot;,
    &quot;url&quot;: &quot;http://juyeong-s.com&quot;
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span&gt;license&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #34495e;&quot;&gt;라이센스를 지정한다.&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span&gt;keywords&lt;/span&gt;&lt;/b&gt;&lt;span&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;패키지를 나타내는 대표적인 키워드들을 배열의 원소들로 설정해줍니다. 다음과 같이 하단에 보입니다.&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-12-30 오후 8.20.31.png&quot; data-origin-width=&quot;647&quot; data-origin-height=&quot;101&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cgn4bs/btrU1NEDQxp/jxWPVVtGtopXjkssITLuOk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cgn4bs/btrU1NEDQxp/jxWPVVtGtopXjkssITLuOk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cgn4bs/btrU1NEDQxp/jxWPVVtGtopXjkssITLuOk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcgn4bs%2FbtrU1NEDQxp%2FjxWPVVtGtopXjkssITLuOk%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;647&quot; height=&quot;101&quot; data-filename=&quot;스크린샷 2022-12-30 오후 8.20.31.png&quot; data-origin-width=&quot;647&quot; data-origin-height=&quot;101&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;bug&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;패키지에 문제나 버그가 있을 경우 보고할 수 있도록 URL을 지정한다. 보통 깃허브 이슈를 올리는 것 같다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span&gt;homepage&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #34495e;&quot;&gt;프로젝트 홈페이지로 연결되는 URL을 지정한다. 다음과 같이 &lt;span style=&quot;background-color: #ffffff; color: #34495e;&quot;&gt;npm &lt;/span&gt;패키지의 오른편에 보인다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-12-30 오후 8.37.26.png&quot; data-origin-width=&quot;295&quot; data-origin-height=&quot;71&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/LJgin/btrU0uMcb4T/64K8aKVmAKmHJEErDWftkK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/LJgin/btrU0uMcb4T/64K8aKVmAKmHJEErDWftkK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/LJgin/btrU0uMcb4T/64K8aKVmAKmHJEErDWftkK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLJgin%2FbtrU0uMcb4T%2F64K8aKVmAKmHJEErDWftkK%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;295&quot; height=&quot;71&quot; data-filename=&quot;스크린샷 2022-12-30 오후 8.37.26.png&quot; data-origin-width=&quot;295&quot; data-origin-height=&quot;71&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span&gt;dependencies&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #34495e;&quot;&gt;패키지의 배포 시 포함될 의존성 모듈을 지정한다.&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span&gt;peerDependencies&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #34495e;&quot;&gt;패키지의 호환성 모듈을 지정한다.&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span&gt;devDependencies&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;패키지의 직접 동작과 관련은 없지만, 이름 그대로 개발할 때 필요한 라이브러리를 지정한다. 보통 테스팅 라이브러리나 type관련 모듈들이 여기 들어간다.&lt;br /&gt;개발에 필요한 라이브러리이기 때문에 배포할 때는 포함되지 않는다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span&gt;3. &lt;/span&gt;&lt;span&gt;.npmignore 파일 설정&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;패키지에 배포하지 않을 파일이나 폴더를 지정해준다.&lt;br /&gt;나는 ts로 작성했기 때문에 ts파일이 있는 폴더는 ignore해주고, js만 올리도록 했다.&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1672400702696&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// .npmignore
src/&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;.gitignore에는 빌드된 js는 제외하고 ts파일만 올리도록 했다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1672400865912&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// .gitignore
node_modules
.env
dist/&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;b&gt;&lt;span&gt;4. npm에 올리기&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;package.json 파일을 모두 설정해주었고, 배포할 hook파일도 모두 포함시켰다면 이제 npm 패키지에 올릴 준비가 되었다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;js로 작성했을 경우 &lt;b&gt;npm publish&lt;/b&gt;로 바로 배포하면 되고,&lt;br /&gt;ts로 작성했을 경우 npm run build 후 js 파일을 생성해 준 후 &lt;span&gt;&lt;b&gt;npm publish&lt;/b&gt;로 배포해주면 된다!&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>custom hook</category>
      <category>npm</category>
      <category>Package</category>
      <category>TypeScript</category>
      <category>배포</category>
      <author>ruby_s</author>
      <guid isPermaLink="true">https://juyami.tistory.com/123</guid>
      <comments>https://juyami.tistory.com/123#entry123comment</comments>
      <pubDate>Fri, 30 Dec 2022 20:49:36 +0900</pubDate>
    </item>
    <item>
      <title>[React + socket] 렌더링마다 socket.io 커넥션이 재생성되는 이슈 해결</title>
      <link>https://juyami.tistory.com/121</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;socket을 사용할 때마다 socket 객체를 전역에 선언해서 사용해야 할 지 컴포넌트 내에 선언해서 지역적으로 사용해야 할 지 항상 고민이였다..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전역으로 사용하면 리액트에 앱에 접속 시, 바로 소켓에 커넥션되기 때문에 너무 불편했다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇다고 지역적으로 사용하려니까 커넥션이 렌더링될 때마다 생성되길래 렌더링이 자주 일어나는 서비스일 경우 부하가 심할 것이고, 실제로 WebRTC 화상 회의 구현을 하면서 엄청난 렉과 마주했다..&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;pre id=&quot;code_1670233578447&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function App() {
  const socket = io(env.SERVER_PATH + `namespace`);

  return (
    &amp;lt;div&amp;gt;
    // 어쩌고
    &amp;lt;/div&amp;gt;
  );
}

export default App;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;App 컴포넌트가 렌더링될 때마다 소켓 객체가 생성될 것이다.. 내가 만들고 있는 실시간 성 서비스에서는 매우 치명적이였다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 내린 결론 useMemo를 사용하기!&lt;/p&gt;
&lt;pre id=&quot;code_1670233657225&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function App() {
  const socket = useMemo(() =&amp;gt; io(env.SERVER_PATH + `namespace`), []);

  return (
    &amp;lt;div&amp;gt;
    // 어쩌고
    &amp;lt;/div&amp;gt;
  );
}

export default App;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&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;+ 추가로, socket을 선언 후 하위 컴포넌트에 props로 깊은 depth로 넘겨야 된다면 props drilling이 야기되고, 어디서 선언된 소켓인지 헷갈릴 수 있다&lt;br /&gt;이럴 경우 소켓을 전역 상태로 관리하여 사용하는 방법도 좋다고 생각한다.&lt;/p&gt;</description>
      <category>React</category>
      <author>ruby_s</author>
      <guid isPermaLink="true">https://juyami.tistory.com/121</guid>
      <comments>https://juyami.tistory.com/121#entry121comment</comments>
      <pubDate>Mon, 5 Dec 2022 18:50:12 +0900</pubDate>
    </item>
    <item>
      <title>[WebRTC] React+TypeScript+WebRTC 개념정리 + 구현하기</title>
      <link>https://juyami.tistory.com/120</link>
      <description>&lt;p data-ke-size=&quot;size18&quot;&gt;부스트캠프 웹모바일 멤버십 그룹 프로젝트에서 WebRTC를 다루게 됐다. 본격적인 작업에 들어가기 앞서 WebRTC에 대해 무지한 상태였기에 미리 학습을 해보았다&lt;br /&gt;처음 학습할 때는 진짜 이게 뭐지 싶었다.. 그래서 이해 못한 채 일단 개념이라도 마구 적어놨다&lt;br /&gt;MDN 문서를 하나씩 살펴보고, 블로그 자료를 엄청 찾아 돌아 댕기다보니 어느정도 정리가 됐다&lt;br /&gt;하단에 참고한 문서들 적어놨어요  &lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;WebRTC(Web Real Time Communication)란??&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;브라우저와 모바일 애플리케이션에서 별도의 소프트웨어 없이 음성, 영상 미디어, 텍스, 파일과 같은 데이터들을 실시간 통신(RTC)으로 주고 받을 수 있게 해주는 기술이다.&lt;br /&gt;Peer To Peer 방식으로 전송하며, 시그널링 서버 하나만 있으면 된다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;시그널링 서버는 뭔데?&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;서로 다른 네트워크에 있는 디바이스들끼리 통신하기 위해서는 각자의 위치를 알고, 미디어 포맷을 맞출 수 있어야 한다. 이러한 과정을 시그널링 이라고 부른다.&lt;br /&gt;각 디바이스들은 서버로 본인의 정보를 보내고, 시그널링 서버는 받은 네트워크 정보를 그대로 상대 디바이스에게 전달해준다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;실시간이라면 웹소켓과 무슨 차이죠?&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;웹소켓은 클라이언트가 서버를 통해 정보들을 전달받는다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;320&quot; data-origin-height=&quot;250&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bMnWbj/btrSaIT7H35/5mtMCUz0lqQvBqNVqQzfW0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bMnWbj/btrSaIT7H35/5mtMCUz0lqQvBqNVqQzfW0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bMnWbj/btrSaIT7H35/5mtMCUz0lqQvBqNVqQzfW0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbMnWbj%2FbtrSaIT7H35%2F5mtMCUz0lqQvBqNVqQzfW0%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;540&quot; height=&quot;422&quot; data-origin-width=&quot;320&quot; data-origin-height=&quot;250&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;그러나 WebRTC는 시그널링 서버를 통해 서로의 네트워크 정보들을 받는다. (시그너링 서버는 단순히 클라이언트의 네트워크 정보를 전달해주는 매개자 역할을 한다.)&lt;br /&gt;클라이언트는 상대 클라이언트의 네트워크 정보를 받고 &amp;ldquo;너 거기 있구나?&amp;rdquo; 를 알게 되면 그때부터 클라이언트끼리 연결을 할 수 있게 되는 것이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;320&quot; data-origin-height=&quot;250&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/JUKBT/btrSa6ObozE/xC0Y9auz0RI1hUBnLO96mK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/JUKBT/btrSa6ObozE/xC0Y9auz0RI1hUBnLO96mK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/JUKBT/btrSa6ObozE/xC0Y9auz0RI1hUBnLO96mK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJUKBT%2FbtrSa6ObozE%2FxC0Y9auz0RI1hUBnLO96mK%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;552&quot; height=&quot;431&quot; data-origin-width=&quot;320&quot; data-origin-height=&quot;250&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;STUN과 TURN&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;이 개념을 알기 전에 NAT이라는 개념을 먼저 알아야 한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;NAT(network Address Translation)이란?&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;사설 IP를 공인 IP로 변경하는데 필요한 주소 변환 서비스이다.&lt;br /&gt;&amp;rarr; 라우터 등의 장비를 사용하여 다수의 사설 IP를 공인 IP 주소로 변환하게 된다.&lt;br /&gt;무슨 말이냐면,&lt;br /&gt;회사망/내부망(LAN) 은 Private IP이기 때문에 다른 네트워크에서는 통용되지 않는다.&lt;br /&gt;그렇기 때문에 우리가 네트워크에서 데이터를 주고받기 위해서는 Public IP 가 필요한데, NAT는 Private IP를 Public IP로 1대1 대응시켜 변환하는 장치다.&lt;br /&gt;그렇다면 STUN, TURN은 뭘까&lt;br /&gt;P2P로 연결하기 위해서도 역시 상대방의 Public IP 주소가 필요하다. 하지만 클라이언트는 보통 방화벽이나 NAT 뒤에서 보호받고 있기 때문에 Public IP 주소를 알기 어렵다.&lt;br /&gt;그래서 WebRTC에서는 STUN 서버 사용을 권장하고 있다.&lt;br /&gt;서로간의 연결을 위한 정보를 공유하여 P2P 통신을 가능하게 해주는 것이 &lt;b&gt;Stun/Turn Server&lt;/b&gt;이다.&lt;br /&gt;&lt;br /&gt;STUN은 클라이언트-서버 프로토콜이다. STUN 클라이언트는 사설망(private network)에 위치하고, STUN 서버는 인터넷망에 위치한다. STUN 클라이언트는 자신의 공인 IP 주소를 확인하기 위해 STUN 서버에게 요청하고, STUN 서버는 STUN 클라이언트가 사용하는 공인 IP 주소를 응답한다.&lt;br /&gt;&lt;br /&gt;TURN 서버는 아직 확실하게 이해가&lt;br /&gt;되지 않아서 하단에 첨부된 노션 상에만 적어놨고, 여기엔 적지 않겠다. 궁금하면 노션으로 타고 들어가서 볼 수 있어요&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;사설망(private network): 인터넷 어드레싱 아키텍처에서 사설 IP 주소 공간을 이용하는 네트워크&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;어느 정도 용어 정리는 된 것 같으니 본격적으로 시그널링 과정을 설명해보겠다&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;711&quot; data-origin-height=&quot;504&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/baxwwp/btrR9uhWQxY/dlP9Al4M1L8godSC8Aiau1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/baxwwp/btrR9uhWQxY/dlP9Al4M1L8godSC8Aiau1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/baxwwp/btrR9uhWQxY/dlP9Al4M1L8godSC8Aiau1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbaxwwp%2FbtrR9uhWQxY%2FdlP9Al4M1L8godSC8Aiau1%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;711&quot; height=&quot;504&quot; data-origin-width=&quot;711&quot; data-origin-height=&quot;504&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;처음에 텍스트로만 적혀진 글을 보고 공부했었는데, 이 사진을 보니까 흐름이 어느 정도 이해가 됐었다&lt;/p&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;1. Session Descriptions 교환하기&lt;/b&gt;&lt;/h2&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;먼저, Peer A가 이미 접속해 있었다고 가정해보자.&lt;/li&gt;
&lt;li&gt;그 후 Peer B가 들어오면, B가 A에게 &amp;ldquo;나 들어왔어~&amp;rdquo; 라고 알린다.&lt;/li&gt;
&lt;li&gt;그럼 A는 createOffer()를 통해 offer를 만든다. 이 offer는 위에서 말한 SDP를 의미한다.&lt;/li&gt;
&lt;li&gt;내 SDP를 setLocalDescription을 통해 로컬 SDP로 설정해주어야 한다.&lt;/li&gt;
&lt;li&gt;생성한 SDP를 상대 B에게 시그널링 서버를 통해 보내준다.&lt;/li&gt;
&lt;li&gt;B는 전달받은 SDP를 setRemoteDescription을 통해 RemoteDescription 으로 설정해야 한다.&lt;/li&gt;
&lt;li&gt;B는 리모트에 A의 SDP를 설정하고 나면 createAnswer()를 통해 A에게 보낼 SDP를 똑같이 생성한다.
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;위에서 생성한 createOffer와 같은 과정이다.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;마찬가지로 A에게 Answer를 보내주고, A는 받은 answer를 RemoteDescription 으로 설정하게 된다&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;2. Ice Candidate 교환하기&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;SDP를 서로 교환한 후에, 두 피어들은 &lt;b&gt;ICE candidate&lt;/b&gt; (ICE 후보)들을 교환하기 시작한다.&lt;br /&gt;상대와 통신할 수 있는 candidate를 찾기 시작하는 과정이다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;각 클라이언트는 현재 내 네트워크 정보가 확보되면 실행될 callback을 onicecandidate 핸들러에게 전달한다. 두가지 방법이 있다.&lt;/li&gt;
&lt;/ol&gt;
&lt;pre id=&quot;code_1669492384550&quot; class=&quot;coffeescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;peerConnection.addEventListener('icecandidate', (e) =&amp;gt; {});
peerConnection.onicecandidate = (e) =&amp;gt; {};&lt;/code&gt;&lt;/pre&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;내 네트워크 정보가 확보되면 시그널링 서버를 통해 상대 Peer에게 내 ice candidate를 전송한다.&lt;/li&gt;
&lt;li&gt;상대 Peer의 ice candidate가 도착하면, 클라이언트에 저장해두었던 상대 Peer Connection을 찾아서 상대의 addIceCandidate() 로 candidate를 설정해주어야 한다.
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이 작업은 서로가 모든 IceCandidate를 교환할 때까지 진행된다.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;IceCandidate를 모두 교환하고 나면, addEventListener의 track 이벤트를 통해 상대의 stream을 받아올 수 있다.&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;typescript&quot;&gt;&lt;code&gt;peerConnection.addEventListener('track', (e) =&amp;gt; {});
peerConnection.ontrack = (e) =&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;size18&quot;&gt;흐름은 여기까지! 이제 실전으로 들어가서 코드를 작성해보자.&lt;br /&gt;사실 흐름만 읽었을 때는 이게 무슨 말인가 싶을수도 있는데, 역시 직접 코드를 작성해보면서 배우는게 좋은 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Server 코드&lt;/b&gt;&lt;/h2&gt;
&lt;pre class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot;&gt;&lt;code&gt;import { Server } from 'socket.io';

function signalingSocketServer(io: Server) {
  const signaling = io.of('namespace');

  signaling.on('connection', (socket) =&amp;gt; {
    socket.on('join', () =&amp;gt; {
      const senderId = socket.id;
      socket.broadcast.emit('join', senderId);
    });

    // senderId : offer를 보내기 시작한 사람의 id, receiveId : offer를 받는 사람의 id
    socket.on('offer', ({ receiveId, offer }) =&amp;gt; {
      const senderId = socket.id;
      socket.to(receiveId).emit('offer', { senderId, offer });
    });

    socket.on('answer', ({ receiveId, answer }) =&amp;gt; {
      const senderId = socket.id;
      socket.to(receiveId).emit('answer', { senderId, answer });
    });

    socket.on('ice-candidate', ({ receiveId, candidate }) =&amp;gt; {
      const senderId = socket.id;
      socket.to(receiveId).emit('ice-candidate', { senderId, candidate });
    });

    socket.on('disconnect', () =&amp;gt; {
      const senderId = socket.id;
      socket.broadcast.emit('disconnected', senderId);
    });
  });
}

export default signalingSocketServer;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;위와 마찬가지로 A가 있는 상황에서 B가 들어온다고 가정하자.&lt;br /&gt;&lt;u&gt;&lt;b&gt;join&lt;/b&gt;&lt;/u&gt;&lt;br /&gt;B가 들어오면 socket.broadcast를 통해 이전이 이미 접속해 있던 멤버들에게 B의 소켓 아이디를 알려준다.&lt;br /&gt;socket.broadcast : 나 자신을 제외한 모두에게 이벤트를 보냄&lt;br /&gt;&lt;span&gt; &lt;/span&gt;&lt;a href=&quot;https://socket.io/docs/v3/broadcasting-events/&quot;&gt;https://socket.io/docs/v3/broadcasting-events/&lt;/a&gt;&lt;br /&gt;&lt;u&gt;&lt;b&gt;&lt;/b&gt;&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;u&gt;&lt;b&gt;offer&lt;/b&gt;&lt;/u&gt;&lt;br /&gt;A가 B에게 보낸 offer를 받아서 socket.to 를 통해 B에게만 offer를 전달해준다.&lt;br /&gt;클라이언트에서 받을 사람의 Id를 보내주어야 한다.&lt;br /&gt;&lt;u&gt;&lt;b&gt;&lt;/b&gt;&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;u&gt;&lt;b&gt;answer&lt;/b&gt;&lt;/u&gt;&lt;br /&gt;B가 생성한 answer를 받아서 socket.to 를 통해 A에게만 보내준다.&lt;br /&gt;마찬가지로 클라이언트에서 받을 사람의 Id를 보내주어야 한다.&lt;br /&gt;&lt;u&gt;&lt;b&gt;&lt;/b&gt;&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;u&gt;&lt;b&gt;ice-candidate&lt;/b&gt;&lt;/u&gt;&lt;br /&gt;이 과정은 A와 B 모두 보내게 된다. icecandidate 이벤트로 등록해놓은 이벤트 핸들러 안에서 이 소켓 이벤트가 발생할 것이다. 마찬가지로 전달받은 candidate를 각각 상대방에게 보낸다.&lt;br /&gt;서버는 단지 시그널링을 위한 용도이기 때문에 매우 간단하다.&lt;/p&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style4&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Client 코드&lt;/b&gt;&lt;/h2&gt;
&lt;pre class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot;&gt;&lt;code&gt;const socket = io(env.SERVER_PATH + 'namespace');

const [participants, setParticipants] = useState&amp;lt;Map&amp;lt;string, MediaStream&amp;gt;&amp;gt;(new Map(),);
const myStreamRef = useRef&amp;lt;MediaStream | null&amp;gt;(null);
const myVideoRef = useRef&amp;lt;HTMLVideoElement | null&amp;gt;(null);
const peerConnectionRef = new Map();

const setMyStream = async () =&amp;gt; {
  const stream = await navigator.mediaDevices.getUserMedia({
    video: true,
  });
  myStreamRef.current = stream;

  if (myVideoRef.current) {
    myVideoRef.current.srcObject = myStreamRef.current;
  }
};

/**
 * Peer와 연결하기
 * @param peerId 연결할 피어의 Id
 * @returns 새로 생성한 peerConnection 객체
 */
const setPeerConnection = (peerId: string) =&amp;gt; {
  const peerConnection = new RTCPeerConnection({
	iceServers: [
	  {
	    urls: ['stun:stun.l.google.com:19302'],
	  },
	],
  });

  /* 이벤트 핸들러: Peer에게 candidate를 전달 할 필요가 있을때 마다 발생 */
  peerConnection.addEventListener('icecandidate', (e) =&amp;gt; {
    const candidate = e.candidate;
    if (!candidate) return;

    socket.emit(RTC_MESSAGE.ICE_CANDIDATE, {
      receiveId: peerId,
      candidate,
    });
  });

  /* 이벤트 핸들러: peerConnection에 새로운 트랙이 추가됐을 경우 호출됨 */
  peerConnection.addEventListener('track', (e) =&amp;gt; {
    if (participants.has(peerId)) {
      return;
    }

    const [peerStream] = e.streams;

    // 새로운 peer를 참여자에 추가
    setParticipants((prev) =&amp;gt; {
      const newState = new Map(prev);
      newState.set(peerId, peerStream);
      return newState;
    });
  });

  myStreamRef.current?.getTracks().forEach((track) =&amp;gt; {
    if (!myStreamRef.current) return;

    // 다른 유저에게 전달해주기 위해 내 미디어를 peerConnection 에 추가한다.
    // track이 myStreamRef.current(내 스트림)에 추가됨
    peerConnection.addTrack(track, myStreamRef.current);
  });

  return peerConnection;
};

useEffect(() =&amp;gt; {
  setMyStream();

  /* 유저 join */
  socket.emit(RTC_MESSAGE.JOIN);

  /* 새로 들어온 유저의 socketId를 받음 */
  socket.on(RTC_MESSAGE.JOIN, async (socketId) =&amp;gt; {
    const peerConnection = setPeerConnection(socketId);

    peerConnectionRef.set(socketId, peerConnection);

    const offer = await peerConnection.createOffer();
    await peerConnection.setLocalDescription(offer);

    socket.emit(RTC_MESSAGE.OFFER, {
      receiveId: socketId,
      offer,
    });
  });

  /* offer 받기 */
  socket.on(RTC_MESSAGE.OFFER, async ({ senderId, offer }) =&amp;gt; {
    const peerConnection = setPeerConnection(senderId);

    peerConnectionRef.set(senderId, peerConnection);

    await peerConnection.setRemoteDescription(offer);

    const answer = await peerConnection.createAnswer();
    await peerConnection.setLocalDescription(answer);

    /* answer 전송 */
    socket.emit(RTC_MESSAGE.ANSWER, { receiveId: senderId, answer });
  });

  /* answer 받기 */
  socket.on(RTC_MESSAGE.ANSWER, async ({ senderId, answer }) =&amp;gt; {
    const peerConnection = peerConnectionRef.get(senderId);
    if (!peerConnection) {
      return console.log('Peer Connection does not exist');
    }

    await peerConnection.setRemoteDescription(answer);
  });

  /* ice candidate */
  socket.on(RTC_MESSAGE.ICE_CANDIDATE, ({ senderId, candidate }) =&amp;gt; {
    const peerConnection = peerConnectionRef.get(senderId);
    if (!peerConnection) {
      return console.log('Peer Connection does not exist');
    }

    peerConnection.addIceCandidate(candidate);
  });

  /* disconnected */
  socket.on(RTC_MESSAGE.DISCONNECTED, (senderId) =&amp;gt; {
    peerConnectionRef.delete(senderId);

    setParticipants((prev) =&amp;gt; {
      const newState = new Map(prev);
      newState.delete(senderId);
      return newState;
    });
  });

  return () =&amp;gt; {
    socket.off(RTC_MESSAGE.JOIN);
    socket.off(RTC_MESSAGE.OFFER);
    socket.off(RTC_MESSAGE.ANSWER);
    socket.off(RTC_MESSAGE.ICE_CANDIDATE);
    socket.off(RTC_MESSAGE.DISCONNECTED);
  };
}, []);

const streams = Array.from(participants.values());

return (
    &amp;lt;ul&amp;gt;
      {streams.map((stream) =&amp;gt; (
        &amp;lt;li key={stream.id}&amp;gt;
           &amp;lt;Video stream={stream} /&amp;gt;
        &amp;lt;/li&amp;gt;
      ))}
    &amp;lt;/ul&amp;gt;
);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모듈화는 잘 안돼있는데 리팩토링을 다시 해야한다 ㅎㅎ..&lt;br /&gt;사실 이 코드는 버그가 좀 있다.. 현재 버그가 발생한 위치는 찾았으나 원인은 찾지 못한 상황이다. offer, answer, candidate 과정을 통해 SDP를 모두 설정은 해주었으나 &lt;u&gt;peerConnection.addEventListener('track', (e) =&amp;gt; {})&lt;/u&gt; 이 부분이 호출되지 않는 것을 발견했다..&lt;br /&gt;내가 이해한 바로는 track 이벤트는 peerConnection.addTrack 가 실행될 때 발생하는 것이다. 상대방이 peerConnection 에 본인의 새로운 track을 추가하게 되면 track 이벤트가 발생하게 되고, 핸들러가 실행되면서 상대의 stream을 가져올 수 있는 것이다.&lt;br /&gt;하지만 track이 올바르게 추가된 것을 확인했으나 가끔 핸들러에 들어가지 않는 경우가 있더라.. 만약 버그를 발견하신 분이 있다면 댓글로 꼭꼭 알려주세요 ㅠㅠ  &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;아무튼 버그가 있더라도 흐름은 맞으니까 다시 설명으로 돌아가서..&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;setMyStream&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내 비디오 스트림을 설정하는 함수다. myStreamRef 에는 MediaStream 타입인 스트림을 걸어주고&lt;br /&gt;myVideoRef 에는 myVideoRef.current.srcObject 에 myStreamRef의 스트림을 넣어주면, video 태그에 아래처럼 걸어주면 내 비디오를 볼 수 있다.&lt;/p&gt;
&lt;pre class=&quot;xml&quot;&gt;&lt;code&gt;&amp;lt;video ref={myVideoRef} /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;setPeerConnection&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Peer Connection을 설정해주는 함수다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;먼저, new RTCPeerConnection 로 새로운 피어 객체를 생성해주고, 스턴 서버를 설정해준다. 구글에서 제공해주는 서버를 사용하면 되는 것 같다.&lt;/li&gt;
&lt;li&gt;icecandidate 이벤트를 등록해준다. 이 이벤트리스너는 peer connection이 candidate를 전달해야 할 필요가 있다고 판단될 때마다 발생하게 된다.
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;e.candidate 로 candidate를 받아온 후, 소켓 emit 이벤트를 걸어준다. 내 candidate를 상대에게 보내는 과정이다.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;track 이벤트를 등록해준다. 이 이벤트 리스너는 위에서 말했던 것처럼 상대방이 peerConnection 에 본인의 새로운 track을 추가하게 되면 발생하게 된다.
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;e.streams로 상대의 stream을 받아온 후, UI에 뿌려주기 위해 useState로 관리중인 participants에 새로운 스트림으로 추가해준다.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;getTracks() : 종류에 관계없이 스트림의 트랙 set에 있는 모든 MediaStreamTrack 객체를 반환한다.
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;다른 유저에게 내 스크림을 전달해주기 위해 peerConnection에 내 스트림을 addTrack으로 담는다.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;이제 useEffect 안으로 들어와보자.&lt;/b&gt;&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;먼저 setMyStream 을 호출해 내 미디어를 먼저 설정해준다.&lt;/li&gt;
&lt;li&gt;join 이벤트로 내가 들어왔다는 것을 이미 접속해 있던 모든 유저들에게 알린다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;socket.on(RTC_MESSAGE.JOIN)&lt;/b&gt; : 그럼 누군가는 이 이벤트를 받게 될 것이다.
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;누군가 들어왔으니 새로운 peer connection을 생성해주어야 한다.&lt;/li&gt;
&lt;li&gt;peerConnectionRef에 socketId를 키 값으로 peer connection을 저장해두자. socketId의 상대와 맺은 connection이 이거다! 라는 것을 구분해주기 위함이다.&lt;/li&gt;
&lt;li&gt;answer와 candidate를 받을 때, 상대와 맺은 peer connection에 받은 answer와 candidate를 추가해주어야 하기 때문에 peerConnection을 저장해둘 필요가 있다.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;socket.on(RTC_MESSAGE.OFFER)&lt;/b&gt; : 상대방의 offer를 받는 부분이다.
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;여기서 중요한 것은, offer를 받으면 새로운 peerConnection을 생성해야 한다는 것이다.&lt;/li&gt;
&lt;li&gt;Join할 때 생성한 peer connection은 A의 것이고, offer를 받는 이벤트는 B가 받을 것이므로 B도 peerConnection을 생성해야 한다
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&amp;rarr; Peer는 1대1로 맺는 거기 때문에 A,B,C가 있을 때 A-B, A-C, B-C 이렇게 Peer Connection이 생성되어야 한다. Peer Connection 객체는 사실 상 6개인 셈이다.&lt;/li&gt;
&lt;li&gt;각자의 Peer Connection에 상대의 정보를 저장해두어야 하므로..&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;이제, setRemoteDescription 로 받은 offer 를 리모트에 넣어둔다.&lt;/li&gt;
&lt;li&gt;이제 전달해줄 answer를 생성하고 answer는 내 것이므로 local description에 설정 후 socket의 answer 이벤트로 보내준다.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;socket.on(RTC_MESSAGE.ANSWER)&lt;/b&gt; : 상대방의 answer를 받는 부분이다.
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;파라미터로 보낸 사람의 socketId를 받아야 한다. 기존에 on(&amp;rsquo;join&amp;rsquo;) 에서 저장해두었던 peer connection에서 socketId를 기준으로 누구와 맺은 커넥션인지 찾은 후, 그 커넥션에 리모트로 answer를 추가해준다.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;socket.on(RTC_MESSAGE.ICE_CANDIDATE)&lt;/b&gt; : 상대방의 candidate를 받는 부분이다.
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;마찬가지로 파라미터로 보낸 사람의 socketId를 받고, 누구와 맺은 커넥션 인지 찾은 후 addIceCandidate 로 candidate를 추가해준다.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;socket.on(RTC_MESSAGE.DISCONNECTED)&lt;/b&gt; : 상대방이 나갔을 경우 peer connection과 participants에서 상대방을 삭제한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;내가 이해한 내용으로 주저리주저리 정리해보았는데 나만 아는 언어로 정리할 거 같기도 하고.. 나름 나중에 봐도 쉽게 이해할 수 있도록 자세하게 적어놨다 ..! &lt;br /&gt;노션에 정리한 링크도 첨부한다.&lt;br /&gt;&lt;a href=&quot;https://saber-ash-4ab.notion.site/React-TypeScript-WebRTC-1defea4ed489417fb4ce9c7a047291f7&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span&gt;https://saber-ash-4ab.notion.site/React-TypeScript-WebRTC-1defea4ed489417fb4ce9c7a047291f7&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;figure data-ke-type=&quot;opengraph&quot; data-og-title=&quot;React+TypeScript+WebRTC 구현하기&quot; data-ke-align=&quot;alignCenter&quot; data-og-description=&quot;부스트캠프 웹모바일 멤버십 그룹 프로젝트에서 WebRTC를 다루게 됐다. 본격적인 작업에 들어가기 앞서 WebRTC에 대해 전혀 무지한 상태였기에 미리 학습을 해보았다&quot; data-og-host=&quot;saber-ash-4ab.notion.site&quot; data-og-source-url=&quot;https://saber-ash-4ab.notion.site/React-TypeScript-WebRTC-1defea4ed489417fb4ce9c7a047291f7&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/boq4on/hyQHUnj83j/Vm5wiwlINeIE4A1dacqKNK/img.png?width=2000&amp;amp;height=1563&amp;amp;face=0_0_2000_1563,https://scrap.kakaocdn.net/dn/klh0Y/hyQHV0OpPg/gCC7dfB6QhBWEnmk7exoBK/img.png?width=2000&amp;amp;height=1563&amp;amp;face=0_0_2000_1563&quot; data-og-url=&quot;https://saber-ash-4ab.notion.site/1defea4ed489417fb4ce9c7a047291f7&quot;&gt;&lt;a href=&quot;https://saber-ash-4ab.notion.site/1defea4ed489417fb4ce9c7a047291f7&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://saber-ash-4ab.notion.site/React-TypeScript-WebRTC-1defea4ed489417fb4ce9c7a047291f7&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/boq4on/hyQHUnj83j/Vm5wiwlINeIE4A1dacqKNK/img.png?width=2000&amp;amp;height=1563&amp;amp;face=0_0_2000_1563,https://scrap.kakaocdn.net/dn/klh0Y/hyQHV0OpPg/gCC7dfB6QhBWEnmk7exoBK/img.png?width=2000&amp;amp;height=1563&amp;amp;face=0_0_2000_1563');&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;React+TypeScript+WebRTC 구현하기&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;부스트캠프 웹모바일 멤버십 그룹 프로젝트에서 WebRTC를 다루게 됐다. 본격적인 작업에 들어가기 앞서 WebRTC에 대해 전혀 무지한 상태였기에 미리 학습을 해보았다&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;saber-ash-4ab.notion.site&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;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;레퍼런스&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://dareun.github.io/webRTC&quot; target=&quot;_self&quot;&gt;&lt;span&gt;https://dareun.github.io/webRTC&lt;/span&gt;&lt;/a&gt;&lt;a href=&quot;https://dareun.github.io/webRTC%E1%84%85%E1%85%B3%E1%86%AF-%E1%84%8B%E1%85%B5%E1%84%8B%E1%85%AD%E1%86%BC%E1%84%92%E1%85%A1%E1%86%AB-%E1%84%92%E1%85%AA%E1%84%89%E1%85%A1%E1%86%BC%E1%84%92%E1%85%AC%E1%84%8B%E1%85%B4-%E1%84%80%E1%85%A2%E1%84%87%E1%85%A1%E1%86%AF&quot; target=&quot;_self&quot;&gt;&lt;span&gt;를-이용한-화상회의-개발&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;&lt;a href=&quot;https://velog.io/@gojaegaebal/210307-개발일지90일차-정글-나만의-무기-프로젝트-WebRTC란-무엇인가2-ICE-SDP-Signalling&quot; target=&quot;_self&quot;&gt;&lt;span&gt;https://velog.io/@gojaegaebal/210307-개발일지90일차-정글-나만의-무기-프로젝트-WebRTC란-무엇인가2-ICE-SDP-Signalling&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;&lt;a href=&quot;https://medium.com/@hyun.sang/webrtc-webrtc란-43df68cbe511&quot; target=&quot;_self&quot;&gt;&lt;span&gt;https://medium.com/@hyun.sang/webrtc-webrtc란-43df68cbe511&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;&lt;a href=&quot;https://kbs77.tistory.com/102&quot; target=&quot;_self&quot;&gt;&lt;span&gt;https://kbs77.tistory.com/102&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;&lt;a href=&quot;https://surprisecomputer.tistory.com/14&quot; target=&quot;_self&quot;&gt;&lt;span&gt;https://surprisecomputer.tistory.com/14&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;&lt;a href=&quot;https://chuun92.tistory.com/39&quot; target=&quot;_self&quot;&gt;&lt;span&gt;https://chuun92.tistory.com/39&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;&lt;a href=&quot;https://web.dev/webrtc-infrastructure/&quot; target=&quot;_self&quot;&gt;&lt;span&gt;https://web.dev/webrtc-infrastructure/&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;</description>
      <category>WebRTC</category>
      <category>icecandidate</category>
      <category>React</category>
      <category>RTC</category>
      <category>signaling</category>
      <category>socket</category>
      <category>STUN</category>
      <category>Turn</category>
      <category>TypeScript</category>
      <category>WebRTC</category>
      <category>websocket</category>
      <author>ruby_s</author>
      <guid isPermaLink="true">https://juyami.tistory.com/120</guid>
      <comments>https://juyami.tistory.com/120#entry120comment</comments>
      <pubDate>Sun, 27 Nov 2022 04:49:20 +0900</pubDate>
    </item>
    <item>
      <title>[부스트캠프] 부스트 컨퍼런스 후기</title>
      <link>https://juyami.tistory.com/119</link>
      <description>&lt;p data-ke-size=&quot;size18&quot;&gt;10월 20일 목요일에 네이버 1784로 부스트 컨퍼런스를 다녀왔다 내가 네이버 신사옥을 가보다니 .. 이런 경험을 또 언제 해볼까 너무 설렜다 ㅎㅎ&lt;br /&gt;사실 후기 이런거 진짜 못쓴다ㅠ 글이라곤 쓸 줄 모른다.. 한정판 굿즈를 준다는 소식에 한번 아무말이나 끄적여보려고 한다 :)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;1440&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rcT4X/btrPgLtUnb0/KFNvQikF1k7M7qCSa0KMjK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rcT4X/btrPgLtUnb0/KFNvQikF1k7M7qCSa0KMjK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rcT4X/btrPgLtUnb0/KFNvQikF1k7M7qCSa0KMjK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrcT4X%2FbtrPgLtUnb0%2FKFNvQikF1k7M7qCSa0KMjK%2Fimg.jpg&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;1440&quot; height=&quot;1440&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;1440&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;br /&gt;점심시간에 같은 청주 사시는 경연님과 &quot;그라도&quot; 라는 이태리 식당에 방문했다 마스터 조은님이 추천해주신 맛집이라 궁금해서 가봤는데, 저 매콤 살라미 파스타? 가 엄청 맛있었따 뭔가 특유의 맛이 났는데 되게 비싸서 가끔 먹을 수 있을 것 같다 ㅎㅎ &lt;br /&gt;언젠가 네이버로 간다면 자주 가야지&lt;br /&gt;길을 헤매서 주변 분들에게 여쭤봐서 겨우겨우 찾아간 맛집이었는데, 동네 분들은 다들 아시는 맛집인 것 같더라!&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1086&quot; data-origin-height=&quot;816&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cg4cO4/btrPgEBpagg/weaUgPq3BkHugksrbgBmPk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cg4cO4/btrPgEBpagg/weaUgPq3BkHugksrbgBmPk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cg4cO4/btrPgEBpagg/weaUgPq3BkHugksrbgBmPk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcg4cO4%2FbtrPgEBpagg%2FweaUgPq3BkHugksrbgBmPk%2Fimg.jpg&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;764&quot; height=&quot;574&quot; data-origin-width=&quot;1086&quot; data-origin-height=&quot;816&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;br /&gt;들어가서 방문증을 겟! 했당 방문증을 목에 거니까 뭔가 사원이라도 된 느낌이었다 ㅎ 왠지 멋있길래 빠르게 사진 4장 찍었당&lt;br /&gt;사실 바로 전날도 네이버 1784 방문했었다 ~3~ 커넥트재단 홍보영상에 출연자로 선정돼서 영광스럽게도 이틀 연속 신사옥에 방문했다 .. 꺅 그래서 덕분에 외롭지 않았다 전날 같이 촬영했던 분들이랑 인사도 하고, 챌린지 멤버십 하면서 만났던 분들도 꽤 만났다&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/tfsBb/btrPg0xHgUf/k1NsTQGJNlpzlGgWaK0Dsk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tfsBb/btrPg0xHgUf/k1NsTQGJNlpzlGgWaK0Dsk/img.jpg&quot; data-origin-width=&quot;886&quot; data-origin-height=&quot;886&quot; style=&quot;width: 49.4186%;&quot; data-is-animation=&quot;false&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tfsBb/btrPg0xHgUf/k1NsTQGJNlpzlGgWaK0Dsk/img.jpg&quot; alt=&quot;&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtfsBb%2FbtrPg0xHgUf%2Fk1NsTQGJNlpzlGgWaK0Dsk%2Fimg.jpg&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;886&quot; height=&quot;886&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bwcehY/btrPjkWrGu8/JMEMsH7GLKO9hBlkhAh5Sk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bwcehY/btrPjkWrGu8/JMEMsH7GLKO9hBlkhAh5Sk/img.jpg&quot; data-origin-width=&quot;886&quot; data-origin-height=&quot;886&quot; style=&quot;width: 49.4186%;&quot; data-is-animation=&quot;false&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bwcehY/btrPjkWrGu8/JMEMsH7GLKO9hBlkhAh5Sk/img.jpg&quot; alt=&quot;&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbwcehY%2FbtrPjkWrGu8%2FJMEMsH7GLKO9hBlkhAh5Sk%2Fimg.jpg&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;886&quot; height=&quot;886&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b9FUZW/btrPgF1lKPS/ybfVNynJoOC2sQ0fnLpnHk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b9FUZW/btrPgF1lKPS/ybfVNynJoOC2sQ0fnLpnHk/img.jpg&quot; data-origin-width=&quot;886&quot; data-origin-height=&quot;886&quot; style=&quot;width: 49.4186%;&quot; data-is-animation=&quot;false&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b9FUZW/btrPgF1lKPS/ybfVNynJoOC2sQ0fnLpnHk/img.jpg&quot; alt=&quot;&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb9FUZW%2FbtrPgF1lKPS%2FybfVNynJoOC2sQ0fnLpnHk%2Fimg.jpg&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;886&quot; height=&quot;886&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zKzG0/btrPp3MGiWJ/K7Y8xxDkUkMwvfBUXk8UQK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zKzG0/btrPp3MGiWJ/K7Y8xxDkUkMwvfBUXk8UQK/img.jpg&quot; data-origin-width=&quot;886&quot; data-origin-height=&quot;886&quot; style=&quot;width: 49.4186%;&quot; data-is-animation=&quot;false&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zKzG0/btrPp3MGiWJ/K7Y8xxDkUkMwvfBUXk8UQK/img.jpg&quot; alt=&quot;&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzKzG0%2FbtrPp3MGiWJ%2FK7Y8xxDkUkMwvfBUXk8UQK%2Fimg.jpg&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;886&quot; height=&quot;886&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;br /&gt;와서 명찰?을 달고 간식 선물을 겟또했다 :) 집에 들고가서 엄청 맛있게 묵었따 다른 분들이랑도 기념으로 명찰 사진 !!&lt;br /&gt;명찰에 보면 알파벳 스티커가 하나씩 붙어있는데 첨에 뭔지도 모르고 내이름이 신씨니까 그냥 S 찾아 붙였는데 알고보니 알파벳 별로 네트워킹 시간에 팀이 나뉘는 거였다 ..!&lt;br /&gt;알파벳이 S라서 Swift 분들이 많았다 되게 재밌는 분들이 많았다 ㅋㅋㅋㅋㅋ 최근 내돈내산한 물건을 공유해보는 시간이었는데 한분이 쿠팡에서 산 고추장을 추천해주셔서 너무 웃겼다 ㅋㅋㅋㅋㅋㅎㅎ&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/cE1Xmh/btrPpWGMVtT/cv2qv1BVGevWl09iCISQk1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cE1Xmh/btrPpWGMVtT/cv2qv1BVGevWl09iCISQk1/img.jpg&quot; data-origin-width=&quot;886&quot; data-origin-height=&quot;886&quot; style=&quot;width: 49.4186%;&quot; data-is-animation=&quot;false&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cE1Xmh/btrPpWGMVtT/cv2qv1BVGevWl09iCISQk1/img.jpg&quot; alt=&quot;&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcE1Xmh%2FbtrPpWGMVtT%2Fcv2qv1BVGevWl09iCISQk1%2Fimg.jpg&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;886&quot; height=&quot;886&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yKGcg/btrPhoygTFO/0Gjp3YFI0H2bBXjRKWfr3K/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yKGcg/btrPhoygTFO/0Gjp3YFI0H2bBXjRKWfr3K/img.jpg&quot; data-origin-width=&quot;886&quot; data-origin-height=&quot;886&quot; style=&quot;width: 49.4186%;&quot; data-is-animation=&quot;false&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yKGcg/btrPhoygTFO/0Gjp3YFI0H2bBXjRKWfr3K/img.jpg&quot; alt=&quot;&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FyKGcg%2FbtrPhoygTFO%2F0Gjp3YFI0H2bBXjRKWfr3K%2Fimg.jpg&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;886&quot; height=&quot;886&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;br /&gt;2시 반부터 6시까지 알차게 연사도 듣고, 테크톡도 들으면서 쉬는시간에는 아는 분들이랑 인사도 나누고 알차게 보냈다&lt;br /&gt;명찰 뒷면에 조은님의 싸인도 받았다 ㅎㅎ 취뽀기원이라는 멘트를 적어주셔서 기운이 너무너무 좋다 !!&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;886&quot; data-origin-height=&quot;886&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bssuoo/btrPk9z8vM6/ikE4UOx36vDNSzZ0ssmvAK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bssuoo/btrPk9z8vM6/ikE4UOx36vDNSzZ0ssmvAK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bssuoo/btrPk9z8vM6/ikE4UOx36vDNSzZ0ssmvAK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbssuoo%2FbtrPk9z8vM6%2FikE4UOx36vDNSzZ0ssmvAK%2Fimg.jpg&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;522&quot; height=&quot;522&quot; data-origin-width=&quot;886&quot; data-origin-height=&quot;886&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;br /&gt;로봇들도 만나고 마스터님과 사진도 찍고 마지막으로 캠퍼들이랑 셀카도 찍으면서 마무리 :) 집와서 보니까 생각보다 사진이 얼마 없었다ㅠ&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/bRRoX2/btrPkqIU1a2/vonKsuP3gK5Fnp8esyuwK1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bRRoX2/btrPkqIU1a2/vonKsuP3gK5Fnp8esyuwK1/img.jpg&quot; data-origin-width=&quot;886&quot; data-origin-height=&quot;886&quot; style=&quot;width: 33.9667%;&quot; data-is-animation=&quot;false&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bRRoX2/btrPkqIU1a2/vonKsuP3gK5Fnp8esyuwK1/img.jpg&quot; alt=&quot;&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbRRoX2%2FbtrPkqIU1a2%2FvonKsuP3gK5Fnp8esyuwK1%2Fimg.jpg&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;886&quot; height=&quot;886&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/4R3TV/btrPh8hFZE1/LmSEhDw1POzF3P2K3oU1pK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/4R3TV/btrPh8hFZE1/LmSEhDw1POzF3P2K3oU1pK/img.jpg&quot; data-origin-width=&quot;960&quot; data-origin-height=&quot;856&quot; style=&quot;width: 38.0935%;&quot; data-is-animation=&quot;false&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/4R3TV/btrPh8hFZE1/LmSEhDw1POzF3P2K3oU1pK/img.jpg&quot; alt=&quot;&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F4R3TV%2FbtrPh8hFZE1%2FLmSEhDw1POzF3P2K3oU1pK%2Fimg.jpg&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;960&quot; height=&quot;856&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dFndBz/btrPkqvlWRD/4qgk13TIj7A8MB4myECGBk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dFndBz/btrPkqvlWRD/4qgk13TIj7A8MB4myECGBk/img.jpg&quot; data-origin-width=&quot;828&quot; data-origin-height=&quot;1098&quot; style=&quot;width: 25.6142%;&quot; data-is-animation=&quot;false&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dFndBz/btrPkqvlWRD/4qgk13TIj7A8MB4myECGBk/img.jpg&quot; alt=&quot;&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdFndBz%2FbtrPkqvlWRD%2F4qgk13TIj7A8MB4myECGBk%2Fimg.jpg&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;828&quot; height=&quot;1098&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;br /&gt;후기 이렇게 쓰는거 맞는지 모르겠다 ㅎ 아무튼 재밌었다ㅎ&lt;/p&gt;</description>
      <category>부스트 캠프</category>
      <category>부스트캠프웹모바일</category>
      <category>부스트컨퍼런스</category>
      <author>ruby_s</author>
      <guid isPermaLink="true">https://juyami.tistory.com/119</guid>
      <comments>https://juyami.tistory.com/119#entry119comment</comments>
      <pubDate>Sun, 23 Oct 2022 21:45:16 +0900</pubDate>
    </item>
    <item>
      <title>네이버 부스트캠프 웹/모바일 7기 자소서 &amp;amp; 코테 최종 합격 후기</title>
      <link>https://juyami.tistory.com/117</link>
      <description>&lt;p data-ke-size=&quot;size18&quot;&gt;부스트캠프 최종 합격까지 기나긴 여정이였다.. 하루에 백준 3~4문제씩 풀며 부스트캠프 준비에만 매달렸다&lt;br&gt;백준 문제 레벨은 &lt;span style=&quot;color: #1b711d;&quot;&gt;&lt;u&gt;&lt;b&gt;골드 4-5 ~ 실버 1-2&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 정도로 꾸준히 풀었다&lt;br&gt;물론 프로그래머스도 풀었다 프로그래머스는 Lv.1 ~ 2문제는 이미 다 풀어둔 상태라 풀었던 문제를 다시 풀면서 준비했다&lt;br&gt;지난 기수나 지지난 기수 후기를 보면 코테 문제가 그리 어렵지 않고 CS가 요구된다는 후기가 대부분이라 CS공부도 조금(?)했다&lt;br&gt;사실 CS가 너무 광범위하기도 하고 1차 코테가 인터넷 검색이 가능했기 때문에 cs50? 강의 한 두번씩 훑어보는 정도로만 공부했다&lt;/p&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot;&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;자소서&lt;/b&gt;&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;지원 질문 &lt;/b&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;(&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;공백 포함&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;400&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;자 내외&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;)&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;1. 왜 개발자가 되고 싶은지 부캠에서 이루고자 하는 목표와 함께 서술&lt;br&gt;2. &lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;소프트웨어 개발을 더 잘하고 싶어서 시도했던 경험과 그 과정에서 어떤 노력을 기울였는지 서술&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3. 자기주도적으로 사고하고 행동한 구체적인 과정과 그 경험이 현재 나에게 미친 영향을 중심으로 서술&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;4. 열린 사고로 동료와 협력한 경험을 구체적인 과정과 그 경험이 현재 나에게 미친 영향을 중심으로 서술&lt;/span&gt;&lt;/span&gt;&lt;br&gt;자소서 문항은 4문항이였고, 어떻게 풀어썼는지 1번 문항부터 팁을 공유해보도록 하겠다&lt;br&gt;&lt;b&gt;1번&lt;/b&gt;은 내 멋쟁이 사자처럼 활동을 엮었다. 그때 프론트엔드에 관심이 생김을 시작으로 이유와 그 이유로 인해 어떤 개발자로 성장하고 싶다!&lt;br&gt;이런식으로 총 3개의 개발자로서의 목표?를 나열하며 그 목표를 부캠에서 어떻게 이루고 싶은지 표현했다&lt;br&gt;2&lt;b&gt;번&lt;/b&gt;은 알고리즘 문제를 풀면서 성장한 환경을 풀어썼다. 그냥 알고리즘을 푼게 아니라 코드리뷰나 공부한 방식을 말하면서 최종적인 결과물? 성취?를 뽐내며 작성했다.&lt;br&gt;코드 리뷰에서는 뭘 얻었고, 이런 공부하는 방식이 뭐가 좋은지 등 문장마다 그 근거를 덧붙여 썼다.&lt;br&gt;&lt;b&gt;3번&lt;/b&gt;은 현재 참여하고 있는 프로젝트가 굉장히 성장에 있어 많은 영향을 준 프로젝트라 그 내용을 작성했다. 거기서 사용한 기술을 어떻게 접근했고 분석했는지, 그 과정에서 발생한 이슈를 예로 들면서 어떻게 해결했는지, 최종적으로 어떤 사고방식을 가질 수 있었는지&lt;br&gt;이렇게 작성했당&lt;br&gt;&lt;b&gt;4번&lt;/b&gt;도 현재 참여하고 있는 프로젝트를 중심으로 풀어냈다. 협업 과정과, 그 과정을 통해 얻은 것, 성장한 것을 중심으로 작성했다.&lt;br&gt;&lt;br&gt;&lt;/p&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt; &lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;1차 코딩 테스트&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1차 코테는 CS 10문제 알고리즘 2문제로 출제되었다. 후기에도 그렇듯 예상했다.&lt;br&gt;시간은 100분이 주어졌고, 중간중간 문제 사정 상 시간이 추가되기도 했다. cs를 먼저 풀었고 한 40분을 cs 푸는데 시간을 썼고 나머지 1시간 동안 알고리즘을 풀어야 했다.&lt;br&gt;cs가 생각보다 어려웠고, 전공자임에도 인터넷 검색이 참 고마웠다.. 아는 문제도 있긴 했지만, 알던 것도 막상 답으로 선택하려니 망설여져서 인터넷 검색을 무조건 했다..&lt;br&gt;&lt;br&gt;알고리즘은 와우..! WOW ..! &lt;br&gt;분명 후기를 보면,, 백준 기준 난이도 실버 3 ~ 4이거나 프로그래머스 Lv.2 중에서도 쉬운 편으로 나왔다고 했다.. 그랬다고 ..!!!!!!!!!!!&lt;br&gt;일단 1번 문제는 나름 풀만 했다.. 한 30분? 안에 푼것 같다. 근데 절대 실버 정도의 문제는 아니고 골드 5? 정도로 보면 될 거같다. 근데 제출을 하니까 테케 하나가 틀렸다 ㅠ&lt;br&gt;그래서 0.9솔..&lt;br&gt;사실 1차 끝나고 5일 뒤 2차 코테라 문제를 회고할 틈도 없이 준비하냐고 1번 문제가 뭐였는지 기억이 잘 안난다..ㅎ 2번 문제는 아예 손도 못댔다.. 문자열로 고통받는 문제였다 애초에 문제 이해가 안되서 하아아아안참 생각하다 보니까 시간이 다 갔더라..&lt;br&gt;그래서 그냥 1번이라도 제대로 풀자 하는 마음에 2번을 과감히 버리고 1번 예외 처리를 위해 시간을 쏟았다.&lt;br&gt;하지만 결국 0.9솔로 제출했다ㅠㅠ&lt;br&gt;&lt;br&gt;그래도 다행히 합격 메일을 주셨다 ㅠㅠㅠㅠㅠㅠ cs를 전부 맞은걸까..?&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;256&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bjjvOF/btrHulOHquf/ZLckzCRm9qLZOpibpnmDw1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bjjvOF/btrHulOHquf/ZLckzCRm9qLZOpibpnmDw1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bjjvOF/btrHulOHquf/ZLckzCRm9qLZOpibpnmDw1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbjjvOF%2FbtrHulOHquf%2FZLckzCRm9qLZOpibpnmDw1%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;661&quot; height=&quot;282&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;256&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt; &lt;/p&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot;&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;2차 코딩 테스트&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2차는 알고리즘 3문제에 서술형 2문제였다.. 안내 메일을 받고 흠칫했다 서술형이요 •••?!&lt;br&gt;한번도 서술형을 낸 적이 없던 것 같은데 진짜 예상치 못한 상황이였다..&lt;br&gt;아무튼 1번 문제는 나에게 가혹한 문제였다.. 다른 분들 후기를 들어보니 1번은 쉬웠다고 했다&lt;br&gt;하지만 내가 매우 약한 유형의 문제였다.. 이 문제도 문자열이다. 분명 내가 보기에도 쉬웠다 .. 쉬웠는데.. 시도조차 못해봤다&lt;br&gt;1번에서 거의 1시간을 썼지만 아무리해도 방법이 생각나지 않았고 그때부터 직감했다.. 이번 코테는 날라갔구나~&lt;br&gt;그래도 포기를 이르니까 2번을 풀자 ! 하고 파이팅있게 2번 문제를 본 순간 아 이건 탈주해야하나? 이 생각이 들었다 ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ&lt;br&gt;쌩구현 문제였다 이 문제도 1차 코테처럼 문자열로 괴롭히는 문제다. 코드가 200줄이 그냥 넘어갔다 내가 작성하면서도 이게 맞아..? 탈주할까..? 이 생각이 수십번 들었다&lt;br&gt;&lt;br&gt;물론 생각만하지. 쫄보라 탈주같은거 못한다.&lt;br&gt;&lt;br&gt;그래도 난 열심히 풀었다.. 3번 문제를 갔더니 ..? 그 문제도 200줄이 넘어가네 ..? 난 이미 망함을 직감했지만 개같은 코드라도 제출하자. 내 열정을 알아주겠지..ㅋㅋㅋㅋㅋㅋ&lt;br&gt;테케가 자꾸 틀렸지만 남은 시간은 5분이였다..&lt;br&gt;그냥 서술형 몇자라도 끄적이자 하는 마음으로 서술형으로 넘어갔다..&lt;br&gt;서술형은 앞의 문제를 토대로 한 유형의 문제였다. 근데 서술형을 처음 본 순간 남은 시간은 5분이였다. 하지만 3번 문제에 대한 미련을 버릴 수가 없었다.. 분명 로직이 맞는데 이상했다.&lt;br&gt;그래서 또 서술형을 버리고 ㅋㅋㅋㅋㅋㅋ 3번을 다시 제대로 보기로 했다. 다행히도 원인을 찾았고 결국 테케 전부 맞은 채로 &lt;b&gt;2솔&lt;/b&gt;? 로 최종 제출을 했다.&lt;br&gt;코테가 끝난 후 다른 분들 후기를 들어보니 다들 200줄이 넘어갔다고 하더라..&lt;br&gt;&lt;b&gt;최종 결과, 대략 10대 1의 경쟁률을 뚫고 합격 !!&lt;/b&gt;&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;598&quot; data-origin-height=&quot;278&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c0WYct/btrHuTYG1or/WKkZwBvVPNrtnjJXQn35DK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c0WYct/btrHuTYG1or/WKkZwBvVPNrtnjJXQn35DK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c0WYct/btrHuTYG1or/WKkZwBvVPNrtnjJXQn35DK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc0WYct%2FbtrHuTYG1or%2FWKkZwBvVPNrtnjJXQn35DK%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;703&quot; height=&quot;327&quot; data-origin-width=&quot;598&quot; data-origin-height=&quot;278&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt; &lt;/p&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot;&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;이번 코테 준비까지 합치면 거진 270문제 정도 풀었다.. ㅎ&lt;br&gt;난 멍청하기 때문에 무조건 많이 풀고 깔끔하게 다시 리팩토링 하면서 머리에 익히는게 답이라고 생각했다 ㅋㅎ&lt;br&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/AFyuS/btrHrNd2xMH/eIbN13J7bmBiRsb2ubpR81/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/AFyuS/btrHrNd2xMH/eIbN13J7bmBiRsb2ubpR81/img.png&quot; data-origin-width=&quot;243&quot; data-origin-height=&quot;108&quot; style=&quot;width: 40.6645%;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/AFyuS/btrHrNd2xMH/eIbN13J7bmBiRsb2ubpR81/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FAFyuS%2FbtrHrNd2xMH%2FeIbN13J7bmBiRsb2ubpR81%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;243&quot; height=&quot;108&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/HTHZW/btrHoOE4jjo/VluDjwfGlXOk4OVrMRUlrK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/HTHZW/btrHoOE4jjo/VluDjwfGlXOk4OVrMRUlrK/img.png&quot; data-origin-width=&quot;103&quot; data-origin-height=&quot;32&quot; style=&quot;width: 58.1728%;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/HTHZW/btrHoOE4jjo/VluDjwfGlXOk4OVrMRUlrK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHTHZW%2FbtrHoOE4jjo%2FVluDjwfGlXOk4OVrMRUlrK%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;103&quot; height=&quot;32&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;왼: 프로그래머스, 우: 백준&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br&gt;앞으로 부캠 포스팅을 자주 기록해놓을 생각이다.. 바빠서 잘 될 지 모르겠지만 값진 기회를 얻었으니 한번 죽기살기로 해봐야겠다&lt;br&gt;열심히 하겠습니다  &lt;br&gt;&lt;br&gt;&lt;/p&gt;</description>
      <category>부스트 캠프</category>
      <category>7기</category>
      <category>개발자</category>
      <category>부스트캠프</category>
      <category>부캠</category>
      <category>웹모바일</category>
      <category>이제 시작</category>
      <category>자소서</category>
      <category>코테</category>
      <category>합격</category>
      <category>화이팅</category>
      <author>ruby_s</author>
      <guid isPermaLink="true">https://juyami.tistory.com/117</guid>
      <comments>https://juyami.tistory.com/117#entry117comment</comments>
      <pubDate>Sun, 17 Jul 2022 00:20:00 +0900</pubDate>
    </item>
    <item>
      <title>[실리콘 밸리 인턴십] 1주차 회고</title>
      <link>https://juyami.tistory.com/116</link>
      <description>&lt;figure contenteditable=&quot;false&quot; data-ke-type=&quot;emoticon&quot; data-ke-align=&quot;alignCenter&quot; data-emoticon-type=&quot;niniz&quot; data-emoticon-name=&quot;001&quot; data-emoticon-isanimation=&quot;false&quot; data-emoticon-src=&quot;https://t1.daumcdn.net/keditor/emoticon/niniz/large/001.gif&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/keditor/emoticon/niniz/large/001.gif&quot; width=&quot;150&quot; /&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;6월 27일&amp;nbsp; - 7월 1일까지 첫째주 실리콘 밸리 인턴십을 시작했다&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음 배정 받은 팀을 확인했더니 내가 리더였다..! 하지만 첫날 팀원 2명이 탈주하게 되고.. 남은 4명이서 구현이 힘들 것 같아 라이언 멘토님께 문의를 드렸더니 팀 조정이 필요한 것 같다고 말씀하셨다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결국 팀 D와 같이 작업을 하게 되었고 우리는 총 8명으로 이루어진 대규모 팀이다 ..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나와 다른 한 분이 프론트엔드 개발을 맡았고, 백엔드 3명, AI 3명 이렇게 나눠졌다.&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;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;유저 시나리오&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 유저가 사진을 업로드한다.&lt;br /&gt;2. 선호하는 장르를 하나 선택한다.&lt;br /&gt;3. 사진과 장르를 조합한 어울리는 노래 추천 결과를 조회한다.&lt;br /&gt;4. 원하는 음악을 선택한다.&lt;br /&gt;4-1. 선택한 음악을 재생한다&lt;br /&gt;4-2. 선택한 음악을 마이 플레이 리스트에 저장한다. -&amp;gt; 단, 로그인 시에만 이용 가능&lt;br /&gt;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;나는 첫주에 메인 페이지 쪽 작업을 맡았고, 이미지 업로드 기능과 노래 결과가 조회되는 테이블을 만들고, 선택 재생, 전체 선택/해제, 플레이 리스트 저장 기능을 구현했다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;현재까지 구현된 작업물&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;800&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cffc1c/btrHkp4w0E8/MENtt7BaEqSiN4k3f9omUk/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cffc1c/btrHkp4w0E8/MENtt7BaEqSiN4k3f9omUk/img.gif&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cffc1c/btrHkp4w0E8/MENtt7BaEqSiN4k3f9omUk/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/cffc1c/btrHkp4w0E8/MENtt7BaEqSiN4k3f9omUk/img.gif&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;800&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;800&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;800&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bqfqFK/btrHiYtkxmu/jffL8Z5kBA8vWL9FIxNHtk/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bqfqFK/btrHiYtkxmu/jffL8Z5kBA8vWL9FIxNHtk/img.gif&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bqfqFK/btrHiYtkxmu/jffL8Z5kBA8vWL9FIxNHtk/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/bqfqFK/btrHiYtkxmu/jffL8Z5kBA8vWL9FIxNHtk/img.gif&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;800&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;800&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이거 GIF 파일인데 이미지로만 보이네..&lt;/p&gt;</description>
      <category>실리콘 밸리</category>
      <category>뮤직 플레이어</category>
      <category>실리콘 밸리</category>
      <category>인턴십</category>
      <author>ruby_s</author>
      <guid isPermaLink="true">https://juyami.tistory.com/116</guid>
      <comments>https://juyami.tistory.com/116#entry116comment</comments>
      <pubDate>Thu, 14 Jul 2022 18:23:03 +0900</pubDate>
    </item>
    <item>
      <title>넥스터즈 21기 면접 후기</title>
      <link>https://juyami.tistory.com/114</link>
      <description>&lt;p data-ke-size=&quot;size18&quot;&gt;오늘 2022년 6월 4일 토요일. 넥스터즈 면접을 봤다 !! 30-35분 정도 진행이 됐고 그룹 면접인데 나 포함 2명이였다. 3명 정도는 될 줄 알았는데 면접자 2 면접관 3 이라 놀랐다 &lt;br /&gt;사실 난 대학교 올 때도 6교과로 와서 인생에 면접을 본 경험이 없다 그냥.. 없어 그냥..&lt;br /&gt;이번에 처음으로 제대로 준비해서 면접을 봤는데 잘 본건지는 모르겠다 ㅎ 말을 버벅였다ㅠ 근데 사실 예상 질문만 38개를 뽑았는데 그 중 하나? 둘? 그정도 나온듯 ㅋ.. 한번쯤 생각해볼만한 질문인데 예상 못한 질문들이 많았다.. 생각나는 질문들을 정리해보자면&lt;/p&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;u&gt;&lt;b&gt;1. &lt;/b&gt;&lt;/u&gt;&lt;u&gt;&lt;b&gt;Uiux에 관심이 많다고 하셨는데 디자이너와 의견조율이 절대 되지 않는다면 어떻게 할 것인지?&lt;/b&gt;&lt;/u&gt;&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;➡️ 처음에는 왜 그렇게 생각하시는 지 디자이너 분의 의견을 물어보고 납득이 간다면 합의를 볼 거 같다고 답변을 했는데, 그래도 절대로 조율이 되지 않는다는 전제 하에 말씀을 해달라고 하셨다. 고민을 좀 하다가.. 그럼 다른 팀원들의 의견도 있을테니 그 사람들 의견도 물어보고, 그외 관련없는 사람들에게도 물어봐서 합의점을 찾아야 될 것 같다. 라고 답변했다. 나름 괜찮게 대답한 것 같다.&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;u&gt;&lt;b&gt;&lt;/b&gt;&lt;/u&gt;&lt;u&gt;&lt;b&gt;2&lt;/b&gt;&lt;/u&gt;&lt;u&gt;&lt;b&gt;. 넥스터즈에서 프로젝트 외에 따로 도전해보고 싶은 것이 있는지&lt;/b&gt;&lt;/u&gt;&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;➡️ 타입스크립트나 리액트쿼리, 그래프 큐엘 등등 주제를 딱 정해서 스터디를 하고싶다. 는 식으로 답변함&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;u&gt;&lt;b&gt;3. 본인이 의도치않게 팀에 불이익을 주는 사람이 됐다면 어떻게 할 것인지&lt;/b&gt;&lt;/u&gt;&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;➡️ 내 질문이 아니였음.&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;u&gt;&lt;b&gt;4. 다양한 프레임워크를 사용해 본 것 같은데, 뷰나 장고의 장점에 대해 말해 줄 수 있냐&lt;/b&gt;&lt;/u&gt;&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;➡️ 리액트는 라이브러리고. 뷰는 프레임워크라 커스텀의 자유도가 떨어지긴 하지만, 러닝커브가 낮다. 자바스크립트를 잘 몰라도 뷰 문법으로 잘 구현할 수 있기 때문에 장점이다. 장고는 사실 제가 프론트 엔드다 보니까 집중적으로 공부하진 않아서 잘 모르겠다.. 라고 답변했는데 사실 장고는 백엔드에서 다루다보니까 깊이있게 공부를 하진 않았다.. 나는 그때 프론트엔드도 잘 못했었으니까..&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;u&gt;&lt;b&gt;5. 넥스터즈에서 본인이 어떤 강점이 될 거같냐&lt;/b&gt;&lt;/u&gt;&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;➡️ 다른 사람 의견을 많이 듣는 것을 좋아함. 많이 듣고 반영해서 리팩토링 하는 것을 좋아한다. 아까도 말했다시피 코드리뷰를 그래서 좋아하는 것 같다. 는 식으로 답변했다. 처음에 자기소개할 때 코드리뷰를 좋아한다고 말했었는데 그걸 엮어봤다.&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;u&gt;&lt;b&gt;6. 기술스택을 정할 때 따로 정하는 기준이 있냐&lt;/b&gt;&lt;/u&gt;&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;➡️ 주로 리액트를 썼었는데, 도전을 좋아하는 편이라 뷰가 어떤 점이 리액트에 비해 좋은지 이런게 궁금해서 써보는 편이다. 이렇게 답변을 했는데 생각해보니까 약간 팀원들의 기술스택을 고려해서 결정을 한다. 이런 식의 답변을 원했던 게 아니였나 이제서야 생각이 든다..&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;u&gt;&lt;b&gt;7. 살면서 실패한 경험 말해달라&lt;/b&gt;&lt;/u&gt;&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;➡️ 데베시 수업에서 했던 프로젝트를 말해봤다. 백엔드 측에서 연동이 잘 안돼서 제가 그걸 수정을 해서 알려주었다. 프로젝트가 시간적 제한이 있다보니까 완성을 해야되지만 완벽하진 못해서 안되는 부분을 mock데이터로 구현을 할 수 밖에 없던 경험이 있다. &lt;br /&gt;라고 했더니 &lt;br /&gt;➡️ 그럼 본인이 너무 주가 돼서 힘들지 않냐는 질문이 들어옴 &lt;br /&gt;그래도 프로젝트는 완성을 해야하기 때문에 제가 좀 할 것 같다. 그리고 저는 오히려 그걸 즐긴다. 새로운 것을 배우는 데서 성장도 할 것이고. 뭐 이런식으로 답변했다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;딱 이정도만 생각난다. 만족스러운 면접은 아니였다 ㅠ 준비한 예상질문들이 안나와서 내가 넥스터즈에서 뭘 하고싶은지 이런 강점을 많이 표출하지 못한 것 같다.. 결과는 일주일 뒤 금요일이나 토요일에 바로 알려주신다고 한다 좋은 결과있길  &lt;/p&gt;</description>
      <category>넥스터즈</category>
      <category>면접</category>
      <category>후기</category>
      <author>ruby_s</author>
      <guid isPermaLink="true">https://juyami.tistory.com/114</guid>
      <comments>https://juyami.tistory.com/114#entry114comment</comments>
      <pubDate>Sun, 5 Jun 2022 01:36:08 +0900</pubDate>
    </item>
    <item>
      <title>[백준-2502] 떡 먹는 호랑이 | node.js | silver1</title>
      <link>https://juyami.tistory.com/113</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;문제&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/2502&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://www.acmicpc.net/problem/2502&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1654150830183&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;2502번: 떡 먹는 호랑이&quot; data-og-description=&quot;첫줄에 첫 날에 준 떡의 개수 A를 출력하고 그 다음 둘째 줄에는 둘째 날에 준 떡의 개수 B를 출력한다. 이 문제에서 주어진 D, K에 대해서는 항상 정수 A, B (1&amp;le; A &amp;le; B)가 존재한다.&amp;nbsp;&quot; data-og-host=&quot;www.acmicpc.net&quot; data-og-source-url=&quot;https://www.acmicpc.net/problem/2502&quot; data-og-url=&quot;https://www.acmicpc.net/problem/2502&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bks7N7/hyOCEs5BBc/f24D8LbSGogq8On29qFQq1/img.png?width=2834&amp;amp;height=1480&amp;amp;face=0_0_2834_1480&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/2502&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.acmicpc.net/problem/2502&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bks7N7/hyOCEs5BBc/f24D8LbSGogq8On29qFQq1/img.png?width=2834&amp;amp;height=1480&amp;amp;face=0_0_2834_1480');&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;2502번: 떡 먹는 호랑이&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;첫줄에 첫 날에 준 떡의 개수 A를 출력하고 그 다음 둘째 줄에는 둘째 날에 준 떡의 개수 B를 출력한다. 이 문제에서 주어진 D, K에 대해서는 항상 정수 A, B (1&amp;le; A &amp;le; B)가 존재한다.&amp;nbsp;&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;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;풀이&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1654150840687&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function solve() {
  const aDp = [1, 0];
  const bDp = [0, 1];

  for (let i = 2; i &amp;lt; d; i++) {
    aDp[i] = aDp[i - 1] + aDp[i - 2];
    bDp[i] = bDp[i - 1] + bDp[i - 2];
  }
  const aCoef = aDp[d - 1];
  const bCoef = bDp[d - 1];

  for (let i = 1; i &amp;lt;= k; i++) {
    const remain = k - aCoef * i;
    if (remain % bCoef === 0) {
      console.log(`${i}\n${remain / bCoef}`);
      break;
    }
  }
}

const filePath =
  process.platform === &quot;linux&quot; ? &quot;/dev/stdin&quot; : &quot;백준/silver/2502/testcase.txt&quot;;
const input = require(&quot;fs&quot;)
  .readFileSync(filePath)
  .toString()
  .trim()
  .split(&quot;\n&quot;);
let [d, k] = input[0].split(&quot; &quot;).map((el) =&amp;gt; +el);
solve();&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;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이 문제는 그냥 수학식이다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;처음 두 값이 &lt;b&gt;A&lt;/b&gt;, &lt;b&gt;B&lt;/b&gt;니까 &lt;b&gt;두&lt;/b&gt;번째 값은 &lt;b&gt;A+B&lt;/b&gt;, &lt;b&gt;세&lt;/b&gt;번째 값은 B+A+B =&amp;gt; &lt;b&gt;A+2B&lt;/b&gt;, &lt;b&gt;네&lt;/b&gt;번째 값은 &lt;b&gt;2A+3B&lt;/b&gt;, &lt;b&gt;다섯&lt;/b&gt;번째 값은 &lt;b&gt;3A+5B&lt;/b&gt; &amp;bull;&amp;bull;&amp;bull;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이 로직을 &lt;b&gt;dp&lt;/b&gt;를 이용해서 구하면 마지막 &lt;b&gt;D번째에 오는 숫자들이 각각 A와 B의 계수&lt;/b&gt;가 될 것이다. 그럼 여기서부터 &lt;b&gt;A값에 1부터 쭉 대입&lt;/b&gt;해보면서 B값이 올바른 정수로 나올 경우 답을 출력하고 break로 종료하면 끝!&lt;/span&gt;&lt;/p&gt;</description>
      <category>백준</category>
      <category>DP</category>
      <category>Nodejs</category>
      <category>백준</category>
      <category>자바스크립트</category>
      <author>ruby_s</author>
      <guid isPermaLink="true">https://juyami.tistory.com/113</guid>
      <comments>https://juyami.tistory.com/113#entry113comment</comments>
      <pubDate>Thu, 2 Jun 2022 15:29:30 +0900</pubDate>
    </item>
    <item>
      <title>디바운싱과 쓰로틀링</title>
      <link>https://juyami.tistory.com/112</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;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;디바운싱과 쓰로틀링은 디바이스에 무리를 주지 않기 위해 사용하는 프로그래밍 기법이다. 일종의 최적화라고 보면된다. 그렇다면 각각의 의미를 알아보자.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;디바운싱(debouncing)&lt;/b&gt; : 연이어 발생한 이벤트를 하나의 그룹으로 묶어서 처리하는 방식이다. 주로, 그룹에서 처음이나 마지막으로 실행된 함수를 처리하는 방식으로 사용된다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;쓰로틀링(throttling)&lt;/b&gt; : 연이어 발생한 이벤트에 대해, 일정한 &lt;i&gt;delay&lt;/i&gt;를 포함시켜 연속적으로 발생한 이벤트는 무시하는 방식을 뜻한다. 즉, &lt;i&gt;delay&lt;/i&gt;시간동안 호출된 함수는 무시하는 방식이다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;디바운싱&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;예시를 들어 쉽게 설명해보겠다. 식당에서 주문을 할 때,&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;첫번째 방법&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;1. 고객: 콜라 주문이요!&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;2. 직원: 콜라 주문넣기&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;3. 고객: 파스타 주문이요!&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;4. 직원: 파스타 주문넣기&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;5. 고객: 스테이크 주문이요!&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;6. 직원: 스테이크 주문넣기&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;두번째 방법&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;1. 고객: 콜라, 파스타, 스테이크 주문이요!&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;2. 직원: 콜라, 파스타, 스테이크 주문넣기&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;br /&gt;당연히 두번째 방법이 훨씬 효율적이다. 이렇게 주문이 끝날 때까지 듣고 있다가 마지막 요청이 완료된 후 주문을 넣는 것이 디바운싱의 원리이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;디바운싱 사용예시&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;스크롤 이벤트로 예시를 들어보겠다. 먼저 디바운싱 기법을 사용하지 않았을 때 예시를 보자.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;&lt;i&gt;디바운싱 적용 X 코드&lt;/i&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1654083615584&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
  &amp;lt;body&amp;gt;
    &amp;lt;div id=&quot;main&quot; style=&quot;height: 300vh&quot;&amp;gt;
      &amp;lt;div style=&quot;position: fixed&quot;&amp;gt;
        &amp;lt;h3&amp;gt;아무 처리도 하지 않았을 경우&amp;lt;/h3&amp;gt;
        &amp;lt;div&amp;gt;
          &amp;lt;label&amp;gt;이벤트 발생 : &amp;lt;/label&amp;gt;
          &amp;lt;span id=&quot;count&quot;&amp;gt;0&amp;lt;/span&amp;gt;
        &amp;lt;/div&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
  &amp;lt;/body&amp;gt;
  &amp;lt;script&amp;gt;
    window.addEventListener(&quot;scroll&quot;, function (e) {
      console.log(&quot;스크롤 이벤트 발생&quot;);
      const count = document.getElementById(&quot;count&quot;);
      count.innerText = parseInt(count.innerText) + 1;
    });
  &amp;lt;/script&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1430&quot; data-origin-height=&quot;1494&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bfS1Bb/btrDIo28qIl/dLyMF3l8oDznMinbOvSbNk/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bfS1Bb/btrDIo28qIl/dLyMF3l8oDznMinbOvSbNk/img.gif&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bfS1Bb/btrDIo28qIl/dLyMF3l8oDznMinbOvSbNk/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/bfS1Bb/btrDIo28qIl/dLyMF3l8oDznMinbOvSbNk/img.gif&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;594&quot; height=&quot;621&quot; data-origin-width=&quot;1430&quot; data-origin-height=&quot;1494&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;스크롤 이벤트가 발생하는 모든 순간마다 함수가 호출되고 count가 계속 늘어나게 된다. 만약 이 함수가 좀 더 무거운 작업을 하게 된다면 스크롤을 할 때마다 렌더링이 되고 성능 이슈로 이어질 수 있다. 그렇다면 디바운싱 기법을 적용한 코드를 보자.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;i&gt;&lt;b&gt;디바운싱 적용 O 코드&lt;/b&gt;&lt;/i&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1654089643265&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
  &amp;lt;body&amp;gt;
    &amp;lt;div id=&quot;main&quot; style=&quot;height: 300vh&quot;&amp;gt;
      &amp;lt;div style=&quot;position: fixed&quot;&amp;gt;
        &amp;lt;h3&amp;gt;Debouncing 적용&amp;lt;/h3&amp;gt;
        &amp;lt;div&amp;gt;
          &amp;lt;label&amp;gt;이벤트 발생 : &amp;lt;/label&amp;gt;
          &amp;lt;span id=&quot;count&quot;&amp;gt;0&amp;lt;/span&amp;gt;
        &amp;lt;/div&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
  &amp;lt;/body&amp;gt;
  &amp;lt;script&amp;gt;
    let debouncer;
    window.addEventListener(&quot;scroll&quot;, function (e) {
      if (debouncer) {
        clearTimeout(debouncer);
      }

      debouncer = setTimeout(function () {
        console.log(&quot;스크롤 이벤트 발생&quot;);
        const count = document.getElementById(&quot;count&quot;);
        count.innerText = parseInt(count.innerText) + 1;
      }, 300);
    });
  &amp;lt;/script&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1430&quot; data-origin-height=&quot;1494&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/T4n6F/btrDHFKhZp8/rwO3OpXLKvHJ68l7ZnCOLK/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/T4n6F/btrDHFKhZp8/rwO3OpXLKvHJ68l7ZnCOLK/img.gif&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/T4n6F/btrDHFKhZp8/rwO3OpXLKvHJ68l7ZnCOLK/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/T4n6F/btrDHFKhZp8/rwO3OpXLKvHJ68l7ZnCOLK/img.gif&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;612&quot; height=&quot;639&quot; data-origin-width=&quot;1430&quot; data-origin-height=&quot;1494&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;debouncer라는 변수에 delay 300ms를 걸어준 setTimeout 함수를 대입한다. 여기에 클로저 개념이 쓰였다고 볼 수 있다. 만약 현재 발생한 스크롤 이벤트가 이전에 발생한 스크롤 이벤트보다 300ms내에(보다 빨리) 발생했다면, 이전 이벤트에 기록된 setTimeout이 대입된 debouncer에 다시 새로운 setTimeout을 대입시킨다. 이때 debouncer에 값이 들어있다면 clearTimeout으로 해당 타이머를 취소해야 한다. 그래야 이전 타이머가 지워지고 새로운 타이머가 대입된다.&amp;nbsp;&lt;br /&gt;&lt;b&gt;결과적으로 마지막으로 발생한 이벤트에 대해서만 300ms가 지난 후 setTimeout안의 로직이 수행되어 카운트가 적절히 변하게 되는 것이다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;쓰로틀링&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;쓰로틀링은 보통 성능 문제 때문에 많이 사용하게 된다. 쓰로틀링은 실행 횟수에 제한을 거는 것이라고 보면 된다.&lt;br /&gt;스크롤 이벤트가 발생할 때마다 이벤트가 발생하지 않고, 몇 초에 한 번 또는 몇 밀리초에 한 번씩만 실행되도록 제한을 두는 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;i&gt;&lt;b&gt;쓰로틀링 적용 O 코드&lt;/b&gt;&lt;/i&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1654091534822&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
  &amp;lt;body&amp;gt;
    &amp;lt;div id=&quot;main&quot; style=&quot;height: 300vh&quot;&amp;gt;
      &amp;lt;div style=&quot;position: fixed&quot;&amp;gt;
        &amp;lt;h3&amp;gt;Throttling 적용&amp;lt;/h3&amp;gt;
        &amp;lt;div&amp;gt;
          &amp;lt;label&amp;gt;이벤트 발생 : &amp;lt;/label&amp;gt;
          &amp;lt;span id=&quot;count&quot;&amp;gt;0&amp;lt;/span&amp;gt;
        &amp;lt;/div&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
  &amp;lt;/body&amp;gt;
  &amp;lt;script&amp;gt;
    let throttler;
    window.addEventListener(&quot;scroll&quot;, function (e) {
      if (throttler) {
        return;
      }
      throttler = setTimeout(function () {
        console.log(&quot;스크롤 이벤트 발생&quot;);
        const count = document.getElementById(&quot;count&quot;);
        count.innerText = parseInt(count.innerText) + 1;
        throttler = null;
      }, 200);
    });
  &amp;lt;/script&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1430&quot; data-origin-height=&quot;1494&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bOFJhY/btrDHducvw4/t0Sdu80DyAVCruuxTSCzB1/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bOFJhY/btrDHducvw4/t0Sdu80DyAVCruuxTSCzB1/img.gif&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bOFJhY/btrDHducvw4/t0Sdu80DyAVCruuxTSCzB1/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/bOFJhY/btrDHducvw4/t0Sdu80DyAVCruuxTSCzB1/img.gif&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;638&quot; height=&quot;667&quot; data-origin-width=&quot;1430&quot; data-origin-height=&quot;1494&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;실행 결과, 스크롤을 천천히 움직여도, 엄청 빠르게 움직여도 일정하게 &lt;i&gt;count&lt;/i&gt;가 변하는 것을 볼 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;여기서 디바운스와 다른 점은 &lt;i&gt;throttler&lt;/i&gt;에 타이머가 설정되어 있을 경우 &lt;i&gt;clearTimeout&lt;/i&gt;으로 타이머를 취소해주는 것이 아닌 return으로 그냥 종료 시키는 것이다. 그렇게 되면 이전에 대입되었던 &lt;b&gt;타이머가 취소되지 않고, 타이머가 설정이 된 이후로부터 300ms내에 실행&lt;/b&gt;되게 될 것이다. &lt;i&gt;throttler&lt;/i&gt;에 타이머가 설정되고 난 후 &lt;b&gt;300ms동안은 &lt;i&gt;throttler&lt;/i&gt;가 이벤트를 쥐고 있는 것&lt;/b&gt;이다. &lt;b&gt;이벤트를 쥐고 있는 300ms동안 1번의 이벤트만 발생하게 된다.&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;또한, 로직이 실행되고 난 후 &lt;b&gt;&lt;i&gt;throttler&lt;/i&gt;를 null로 초기화&lt;/b&gt; 시켜주면서 throttler에 값이 없다는 것 알려주어야 다음 스크롤 이벤트 발생 시 return 되지 않고 &lt;b&gt;&lt;i&gt;setTimeout&lt;/i&gt;을 다시 걸어줄 수 있을 것&lt;/b&gt;이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;콘솔로 확인해보니 &lt;i&gt;setTimeout&lt;/i&gt;이 양의 정수값을 리턴하는데, 300ms후 로직이 전부 끝나고 나서는 1을 출력하는 것을 확인했다. 우리는 &lt;i&gt;clearTimeout&lt;/i&gt;으로 타이머를 초기화시켜주지 않았으므로 null로 값이 없다는 것을 알려주어야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;레퍼런스&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://developer.mozilla.org/ko/docs/Web/API/setTimeout&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://developer.mozilla.org/ko/docs/Web/API/setTimeout&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/clearTimeout&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://developer.mozilla.org/en-US/docs/Web/API/clearTimeout&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://velog.io/@yujuck/Javascript-%EB%94%94%EB%B0%94%EC%9A%B4%EC%8A%A4%EC%99%80-%EC%93%B0%EB%A1%9C%ED%8B%80%EB%A7%81&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://velog.io/@yujuck/Javascript-%EB%94%94%EB%B0%94%EC%9A%B4%EC%8A%A4%EC%99%80-%EC%93%B0%EB%A1%9C%ED%8B%80%EB%A7%81&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://programming119.tistory.com/241&quot;&gt;https://programming119.tistory.com/241&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>디바운싱</category>
      <category>쓰로틀링</category>
      <category>웹</category>
      <category>최적화</category>
      <author>ruby_s</author>
      <guid isPermaLink="true">https://juyami.tistory.com/112</guid>
      <comments>https://juyami.tistory.com/112#entry112comment</comments>
      <pubDate>Wed, 1 Jun 2022 23:18:02 +0900</pubDate>
    </item>
    <item>
      <title>[백준-11497] 통나무 건너뛰기 | node.js | silver1</title>
      <link>https://juyami.tistory.com/111</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;문제&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/11497&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://www.acmicpc.net/problem/11497&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1653749466676&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;11497번: 통나무 건너뛰기&quot; data-og-description=&quot;남규는 통나무를 세워 놓고 건너뛰기를 좋아한다. 그래서 N개의 통나무를 원형으로 세워 놓고 뛰어놀려고 한다. 남규는 원형으로 인접한 옆 통나무로 건너뛰는데, 이때 각 인접한 통나무의 높이&quot; data-og-host=&quot;www.acmicpc.net&quot; data-og-source-url=&quot;https://www.acmicpc.net/problem/11497&quot; data-og-url=&quot;https://www.acmicpc.net/problem/11497&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cq6HJ8/hyOzU94lVu/vfH0f3V116KArorYOpY2T0/img.png?width=2834&amp;amp;height=1480&amp;amp;face=0_0_2834_1480,https://scrap.kakaocdn.net/dn/gQCu6/hyOyodSrGs/nlfT83TQ0C1hxLwLKtdCw1/img.png?width=548&amp;amp;height=536&amp;amp;face=0_0_548_536&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/11497&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.acmicpc.net/problem/11497&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cq6HJ8/hyOzU94lVu/vfH0f3V116KArorYOpY2T0/img.png?width=2834&amp;amp;height=1480&amp;amp;face=0_0_2834_1480,https://scrap.kakaocdn.net/dn/gQCu6/hyOyodSrGs/nlfT83TQ0C1hxLwLKtdCw1/img.png?width=548&amp;amp;height=536&amp;amp;face=0_0_548_536');&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;11497번: 통나무 건너뛰기&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;남규는 통나무를 세워 놓고 건너뛰기를 좋아한다. 그래서 N개의 통나무를 원형으로 세워 놓고 뛰어놀려고 한다. 남규는 원형으로 인접한 옆 통나무로 건너뛰는데, 이때 각 인접한 통나무의 높이&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;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;풀이&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1653749494375&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function solve(n, tree) {
  tree.sort((a, b) =&amp;gt; a - b);
  let maxLen = 0;
  for (let i = 2; i &amp;lt; n; i++) {
    maxLen = Math.max(maxLen, Math.abs(tree[i] - tree[i - 2]));
  }
  return maxLen;
}

const filePath =
  process.platform === &quot;linux&quot;
    ? &quot;/dev/stdin&quot;
    : &quot;백준/silver/11497/testcase.txt&quot;;
const input = require(&quot;fs&quot;)
  .readFileSync(filePath)
  .toString()
  .trim()
  .split(&quot;\n&quot;);
for (let i = 1; i &amp;lt; input.length - 1; ) {
  const n = +input[i];
  const tree = input[i + 1].split(&quot; &quot;).map((el) =&amp;gt; +el);
  i += 2;
  console.log(solve(n, tree));
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;이 문제는 예를 들어서 설명해보겠다.&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;1, 3, 5, 7, 9, 12, 14, 16, 18, 20&lt;/b&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;다음과 같이 있다고 가정했을 때, 아래와 같이 배치 했을 때 난이도의 최소값이 나오게 된다. 이때 난이도는 &lt;b&gt;5&lt;/b&gt;가 된다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;1, 5, 9, 14, 18, 20, 16, 12, 7,&amp;nbsp; 3&lt;/b&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;주어진 배열을 오름차순으로 정렬한 뒤 순서대로 양끝에 배치시킨 것이다. 그 이유는 &lt;b&gt;1, 2 , 3, 100, 101, &amp;bull;&amp;bull;&amp;bull;&lt;/b&gt;를 예로 들어서 설명하겠다. 3과 100을 인접시켜야만 난이도의 최소값이 나올 것 같지만 그렇지 않다. 3과 100을 인접시킬 경우,&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;만약, &lt;b&gt;3의 왼쪽에 1이나 2중 하나&lt;/b&gt;가 나온다면 그 1이나 2는 100보다 큰 어떤 값들과 인접될 수 밖에 없을 것이다. 그렇다면 3과 100의 차이보다 더 큰 차이값이 나오게 되므로 난이도의 최소값을 올바르게 도출할 수 없다.&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;만약, &lt;b&gt;3의 왼쪽에 100보다 큰 값이 인접&lt;/b&gt;하게 된다면 3과 100의 차이보다 3과 왼쪽에 인접한 그 값과의 차이가 더 커지기 때문에 3과 100이 최대 난이도가 아니게 된다. 따라서 오름차순된 배열을 작은 값부터 양 끝에서부터 번갈아가며 배치해야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;&lt;b&gt;1 =&amp;gt; 1, 3 =&amp;gt; 1, 5, 3 =&amp;gt; 1, 5, 7, 3 =&amp;gt; &amp;bull;&amp;bull;&amp;bull; =&amp;gt; 1, 5, 9, 14, 18, 20, 16, 12, 7, 3&lt;/b&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&amp;nbsp;결국, 통나무를 오름차순으로 정렬한 뒤 &lt;i&gt;&lt;b&gt;i&lt;/b&gt;&lt;/i&gt;번째 값과&lt;i&gt;&lt;b&gt; i-2&lt;/b&gt;&lt;/i&gt;번째 값을 비교한 것과 같은 로직이다.&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;1, 3, 5, 7, &amp;bull;&amp;bull;&amp;bull;&amp;nbsp; =&amp;gt; 1과 5비교, 3과 7비교, &amp;bull;&amp;bull;&amp;bull;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>백준</category>
      <category>11497</category>
      <category>Node.js</category>
      <category>백준</category>
      <category>자바스크립트</category>
      <category>통나무 건너뛰기</category>
      <author>ruby_s</author>
      <guid isPermaLink="true">https://juyami.tistory.com/111</guid>
      <comments>https://juyami.tistory.com/111#entry111comment</comments>
      <pubDate>Sun, 29 May 2022 01:10:15 +0900</pubDate>
    </item>
    <item>
      <title>[백준-1946] 신입사원 | node.js | silver1</title>
      <link>https://juyami.tistory.com/110</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;문제&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/1946&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://www.acmicpc.net/problem/1946&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1653527365476&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;1946번: 신입 사원&quot; data-og-description=&quot;첫째 줄에는 테스트 케이스의 개수 T(1 &amp;le; T &amp;le; 20)가 주어진다. 각 테스트 케이스의 첫째 줄에 지원자의 숫자 N(1 &amp;le; N &amp;le; 100,000)이 주어진다. 둘째 줄부터 N개 줄에는 각각의 지원자의 서류심사 성&quot; data-og-host=&quot;www.acmicpc.net&quot; data-og-source-url=&quot;https://www.acmicpc.net/problem/1946&quot; data-og-url=&quot;https://www.acmicpc.net/problem/1946&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/ce90OE/hyOxrBau34/4lEL5BlAZ9CkkjkKZo5de0/img.png?width=2834&amp;amp;height=1480&amp;amp;face=0_0_2834_1480&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/1946&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.acmicpc.net/problem/1946&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/ce90OE/hyOxrBau34/4lEL5BlAZ9CkkjkKZo5de0/img.png?width=2834&amp;amp;height=1480&amp;amp;face=0_0_2834_1480');&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;1946번: 신입 사원&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;첫째 줄에는 테스트 케이스의 개수 T(1 &amp;le; T &amp;le; 20)가 주어진다. 각 테스트 케이스의 첫째 줄에 지원자의 숫자 N(1 &amp;le; N &amp;le; 100,000)이 주어진다. 둘째 줄부터 N개 줄에는 각각의 지원자의 서류심사 성&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;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;풀이&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1653527380801&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function solve(n, ranking) {
  ranking.sort((a, b) =&amp;gt; a[0] - b[0]);

  let answer = 1;
  let minRank = ranking[0][1];
  for (let i = 1; i &amp;lt; n; i++) {
    const rank = ranking[i][1];
    if (rank &amp;lt; minRank) {
      minRank = rank;
      answer++;
    }
  }
  return answer;
}

const filePath =
  process.platform === &quot;linux&quot; ? &quot;/dev/stdin&quot; : &quot;백준/silver/1946/testcase.txt&quot;;
const input = require(&quot;fs&quot;)
  .readFileSync(filePath)
  .toString()
  .trim()
  .split(&quot;\n&quot;);
for (let i = 1; i &amp;lt; input.length; ) {
  const n = +input[i];
  console.log(
    solve(n, input.slice(i + 1, i + 1 + n).map((rank) =&amp;gt; rank.split(&quot; &quot;).map((num) =&amp;gt; +num)))
  );
  i += n + 1;
}&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;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;문제 이해가 안돼서 헤맸다.. 주어진 숫자는 점수가 아닌 등수이다. 아래처럼 순위가 돼있다고 했을 때, 서류의 순위는 변동되지 않고 면접에 따라 뽑힐 지 말지가 결정된다. 왜냐하면 둘 중 하나라도 다른 사람보다 높은 등수일 경우 뽑히는 정책이기 때문에 서류를 오름차순으로 정렬하면 서류는 무조건 통과한다는 전제하에 면접 등수를 체크하는&amp;nbsp; 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;b&gt;&amp;nbsp;서류&amp;nbsp; 면접&lt;/b&gt;&lt;br /&gt;&lt;b&gt;A&lt;/b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;1&amp;nbsp; &amp;nbsp; &amp;nbsp; 4&lt;br /&gt;&lt;b&gt;B&lt;/b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;2&amp;nbsp; &amp;nbsp; &amp;nbsp;3&lt;br /&gt;&lt;b&gt;C&lt;/b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;3&amp;nbsp; &amp;nbsp; &amp;nbsp;2&lt;br /&gt;&lt;b&gt;D&lt;/b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;4&amp;nbsp; &amp;nbsp; &amp;nbsp;1&lt;br /&gt;&lt;b&gt;E&lt;/b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;5&amp;nbsp; &amp;nbsp; &amp;nbsp;5&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;먼저 &lt;b&gt;A&lt;/b&gt;의 면접 등수를 최소 등수로 두고 &lt;b&gt;B&lt;/b&gt;부터 비교를 시작한다. &lt;b&gt;B&lt;/b&gt;의 면접 등수가 현재 최소 등수보다 높을 경우 &lt;b&gt;B&lt;/b&gt;는 선발된다.&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;그럼 현재 최소 등수는 &lt;b&gt;B&lt;/b&gt;의 등수인 &lt;b&gt;3&lt;/b&gt;일 될 것이고, &lt;b&gt;C&lt;/b&gt;를 비교한다. &lt;b&gt;C&lt;/b&gt;의 면접 등수는 &lt;b&gt;2&lt;/b&gt;이므로 현재 최소 등수보다 높다. 따라서 &lt;b&gt;C&lt;/b&gt;도 선발된다. 이런식으로 비교하다보면 &lt;b&gt;E&lt;/b&gt;를 비교했을 때, 최소 등수인 &lt;b&gt;1&lt;/b&gt;보다 낮으므로 &lt;b&gt;E&lt;/b&gt;빼고 모두가 선발되게 된다.&lt;/span&gt;&lt;/p&gt;</description>
      <category>백준</category>
      <category>1946</category>
      <category>Node.js</category>
      <category>백준</category>
      <category>신입사원</category>
      <category>자바스크립트</category>
      <author>ruby_s</author>
      <guid isPermaLink="true">https://juyami.tistory.com/110</guid>
      <comments>https://juyami.tistory.com/110#entry110comment</comments>
      <pubDate>Thu, 26 May 2022 10:18:51 +0900</pubDate>
    </item>
    <item>
      <title>[백준-1541] 잃어버린 괄호 | node.js | silver2</title>
      <link>https://juyami.tistory.com/109</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;문제&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/1541&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://www.acmicpc.net/problem/1541&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1653523912776&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;1541번: 잃어버린 괄호&quot; data-og-description=&quot;첫째 줄에 식이 주어진다. 식은 &amp;lsquo;0&amp;rsquo;~&amp;lsquo;9&amp;rsquo;, &amp;lsquo;+&amp;rsquo;, 그리고 &amp;lsquo;-&amp;rsquo;만으로 이루어져 있고, 가장 처음과 마지막 문자는 숫자이다. 그리고 연속해서 두 개 이상의 연산자가 나타나지 않고, 5자리보다 &quot; data-og-host=&quot;www.acmicpc.net&quot; data-og-source-url=&quot;https://www.acmicpc.net/problem/1541&quot; data-og-url=&quot;https://www.acmicpc.net/problem/1541&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/tT80l/hyOxk22QdN/GFkOPXXnHrHSp1rSch2tdk/img.png?width=2834&amp;amp;height=1480&amp;amp;face=0_0_2834_1480&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/1541&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.acmicpc.net/problem/1541&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/tT80l/hyOxk22QdN/GFkOPXXnHrHSp1rSch2tdk/img.png?width=2834&amp;amp;height=1480&amp;amp;face=0_0_2834_1480');&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;1541번: 잃어버린 괄호&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;첫째 줄에 식이 주어진다. 식은 &amp;lsquo;0&amp;rsquo;~&amp;lsquo;9&amp;rsquo;, &amp;lsquo;+&amp;rsquo;, 그리고 &amp;lsquo;-&amp;rsquo;만으로 이루어져 있고, 가장 처음과 마지막 문자는 숫자이다. 그리고 연속해서 두 개 이상의 연산자가 나타나지 않고, 5자리보다&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;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;풀이&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1653523926612&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function solve() {
  let arr = [];
  for (let splited of input.split(&quot;-&quot;)) {
    let cnt = 0;
    let s = splited.split(&quot;+&quot;);

    for (const op of s) {
      cnt += +op;
    }
    arr.push(cnt);
  }

  return arr[0] + arr.slice(1).reduce((acc, curr) =&amp;gt; acc - curr, 0);
}

const filePath =
  process.platform === &quot;linux&quot; ? &quot;/dev/stdin&quot; : &quot;백준/silver/1541/testcase.txt&quot;;
const input = require(&quot;fs&quot;)
  .readFileSync(filePath)
  .toString()
  .trim()
  .split(&quot;\n&quot;)[0];
console.log(solve());&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;55-50+40-30+90&lt;/b&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;로 예시를 들어 설명하겠다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;i&gt;arr&lt;/i&gt;에 모두 푸시한 후 값을 살펴보면 &lt;i&gt;[55, 90, 120]&lt;/i&gt; 이 들어있다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;-&lt;/b&gt;(마이너스)를 기준으로 다음 &lt;b&gt;- &lt;/b&gt;가 나올때까지 arr에 그 사이의 값을 더해서 푸시해준다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;결국 &lt;i&gt;55, 50+40, 30+90&lt;/i&gt; 이렇게 3개의 요소가 들어가게 되는 것이다. 그런 후 맨 처음 값 &lt;i&gt;55 &lt;/i&gt;에서 뒤에 값들을 쭉 빼주면 -를 기준으로 괄호를 친 셈이 된다. 그 값이 최솟값이 될 것이다.&lt;/span&gt;&lt;/p&gt;</description>
      <category>백준</category>
      <category>1541</category>
      <category>Node.js</category>
      <category>그리디</category>
      <category>백준</category>
      <category>자바스크립트</category>
      <author>ruby_s</author>
      <guid isPermaLink="true">https://juyami.tistory.com/109</guid>
      <comments>https://juyami.tistory.com/109#entry109comment</comments>
      <pubDate>Thu, 26 May 2022 09:19:15 +0900</pubDate>
    </item>
    <item>
      <title>[VanillaJS] 프로그래머스 과제 테스트를 연습하면서 배운 웹 페이지 구조</title>
      <link>https://juyami.tistory.com/108</link>
      <description>&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이번에 우테캠 5기 2차 과제테스트를 준비하기 위해 프로그래머스에 고양이 사진첩 애플리케이션 이라는 과제테스트를 풀어보았다. 지난번에 고양이 사진 검색하기를 했었는데 그때 바닐라JS가 처음이라 진짜 아무것도 모르고 이것저것 뒤지면서 구현했더니 머리에 남아있는게 없다.. 바닐라 JS자체가 너무 재미없어서 꾸역꾸역 해서 그런것도 있는 것 같다 ㅎ&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;뭐 쨋든 서론은 이만하고,&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이번 포스팅에서는 과제테스트를 딱 열었을 때 아무것도 없는 생 파일에 어떻게 구조를 구성해나가면 될 지 알아볼 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;먼저 처음엔 index.html이 있을 것이다. 자바스크립트를 구현하면서 해당 파일안에 요소가 계속 추가 될 것이다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;html파일에서 할 일은 js파일을 연결해주면 된다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1652239517764&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;html&amp;gt;
  &amp;lt;head&amp;gt;
    &amp;lt;title&amp;gt;고양이 사진첩!&amp;lt;/title&amp;gt;
    &amp;lt;link rel=&quot;stylesheet&quot; href=&quot;./src/styles/style.css&quot; /&amp;gt;
  &amp;lt;/head&amp;gt;
  &amp;lt;body&amp;gt;
    &amp;lt;h1&amp;gt;고양이 사진첩&amp;lt;/h1&amp;gt;
    &amp;lt;main class=&quot;App&quot;&amp;gt;&amp;lt;/main&amp;gt;
    &amp;lt;script src=&quot;src/js/index.js&quot; type=&quot;module&quot;&amp;gt;&amp;lt;/script&amp;gt;
  &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;script태그는 &amp;lt;head&amp;gt;안에 넣어도, &amp;lt;body&amp;gt;안에 넣어도, &amp;lt;html&amp;gt;안에 넣어도 상관 없다. 다만, html의 body태그보다 js파일일 먼저 컴파일될 시 js파일은 body안의 태그들을 읽지 못할 것이다. 우리가 DOM을 조절하려면 조절할 요소들보다 아래 쪽에 script를 연결해줘야 한다.&lt;br /&gt;여기서 또 중요한 게 있다. &lt;b&gt;script태그&lt;/b&gt;의 속성에 보면 &lt;b&gt;type=&quot;module&quot;&lt;/b&gt;이 보인다.&lt;b&gt; export/import&lt;/b&gt;방식으로 구현하고 싶다면 이 속성을 꼭 추가해줘야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이제 js파일을 하나씩 생성해보자. 나는 아래처럼 파일구조를 구성했다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-05-11 오후 12.27.55.png&quot; data-origin-width=&quot;342&quot; data-origin-height=&quot;442&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/s9MMY/btrBMhluayn/Q7xkcaPkpJo9uc8zPwlj10/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/s9MMY/btrBMhluayn/Q7xkcaPkpJo9uc8zPwlj10/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/s9MMY/btrBMhluayn/Q7xkcaPkpJo9uc8zPwlj10/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fs9MMY%2FbtrBMhluayn%2FQ7xkcaPkpJo9uc8zPwlj10%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;342&quot; height=&quot;442&quot; data-filename=&quot;스크린샷 2022-05-11 오후 12.27.55.png&quot; data-origin-width=&quot;342&quot; data-origin-height=&quot;442&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;컴포넌트 분리는 선택이 아닌 필수다 !&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;1. index.js&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1652239881029&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import App from &quot;./App.js&quot;;
new App(document.querySelector(&quot;.App&quot;));&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;가장 먼저 해야 할일은 메인 자바스크립트 파일(App,js)에 DOM요소를 연결해주는 것이다. import로 App을 가져온 후, new 연산자로 App객체안 에 최상단의 App DOM요소를 넣어주면 된다.&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;2. api.js&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1652239743033&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const API_END_POINT =
  &quot;https://zl3m4qq0l9.execute-api.ap-northeast-2.amazonaws.com/dev&quot;;

export const request = async (nodeId) =&amp;gt; {
  try {
    const response = await fetch(`${API_END_POINT}/${nodeId || &quot;&quot;}`, {
      method: &quot;GET&quot;,
    });
    if (response.ok) return response.json();
    else throw new Error(&quot;error&quot;);
  } catch (e) {
    throw new Error(&quot;error&quot;);
  }
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;한번 구현해보니까 api를 요청하는 부분을 처음에 구현해놓는 것이 편한 것 같다고 느꼈다. 그래서 다음은 api를 요청하는 파일이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;공통 url은 전역변수로 두었다. 네이밍(API_END_POINT)은 다른 사람들 코드를 참고했다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;기본적으로 api요청 함수는 &lt;b&gt;async await&lt;/b&gt;함수로 구현하자. &lt;b&gt;try catch&lt;/b&gt;문으로 예외 처리도 해주자.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;Promise가 올바르게 전달 받아졌다면 &lt;b&gt;response를 json으로 리턴&lt;/b&gt;해주자.&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;(에러를 뱉을 때는 throw로 뱉어줄 것)&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;3. App.js&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1652240671683&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import { request } from &quot;../api/api.js&quot;;
import Breadcrumb from &quot;./Breadcrumb.js&quot;;
import Nodes from &quot;./Nodes.js&quot;;
import ImageView from &quot;./ImageView.js&quot;;
import Loading from &quot;./Loading.js&quot;;

const cache = {};

export default function App($app) {
    this.state = {
        isRoot: true,
        nodes: [],
        depthStack: [],
        currentPath: null,
        selectedFilePath: null,
        isLoading: true,
    };
  
    this.setState = (nextState) =&amp;gt; {
        this.state = nextState;
    };
  
    this.init = async () =&amp;gt; {
        try {
            const rootNodes = await request(null);
            this.setState({
            ...this.state,
            nodes: rootNodes,
            });
        } catch (e) {
            throw new Error(e);
        }
    };
    this.init();
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;초기 App이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;this.state:&lt;/b&gt;&lt;i&gt; `this.${변수명}&lt;/i&gt;`이런 방식으로 지역변수를 선언해주면 된다. state안에 필요한 요소들을 하나씩 추가해주는 방식으로 구현한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;this.setState: &lt;/b&gt;지역변수들이 변경될 때마다 각 컴포넌트에 변경사항을 반영해주기 위해 생성한 함수이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;this.init:&lt;/b&gt; 첫 초기 화면을 구성하기 위해 만든 함수이다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;1. await request()로 api요청을 받아온다.&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;2. this.setState()로 변경사항을 반영해준다. -&amp;gt;&lt;b&gt; ...this.state&lt;/b&gt;: 기존 state는 그대로 반영하고 &lt;b&gt;nodes&lt;/b&gt;는 &lt;b&gt;rootNodes&lt;/b&gt;로 변경하도록.&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;4. Nodes.js&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1652241064418&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;export default function Nodes({ $app, state, onClick, onBackClick }) {
  this.state = state;
  this.onClick = onClick;
  this.onBackClick = onBackClick;

  this.setState = (nextState) =&amp;gt; {
    this.state = nextState;
    this.render();
  };

  const nodes = document.createElement(&quot;div&quot;);
  nodes.className = &quot;Nodes&quot;;

  this.render = () =&amp;gt; {
    const template = this.state.nodes
      .map((node) =&amp;gt; {
        return `
        &amp;lt;div class=&quot;Node&quot; data-node-id=&quot;${node.id}&quot;&amp;gt;
          &amp;lt;img src=&quot;./assets/${node.type.toLowerCase()}.png&quot;
          data-node-id=&quot;${node.id}&quot;/&amp;gt;
          &amp;lt;div&amp;gt;${node.name}&amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;
      `;
      })
      .join(&quot;&quot;);

    const backTemplate = `
      &amp;lt;div class=&quot;Node&quot;&amp;gt;
        &amp;lt;img src=&quot;./assets/prev.png&quot; /&amp;gt;
      &amp;lt;/div&amp;gt;`;

    nodes.innerHTML = this.state.isRoot
      ? template
      : `
      ${backTemplate}
      ${template}
    `;

    $app.appendChild(nodes);
  };

  nodes.addEventListener(&quot;click&quot;, (e) =&amp;gt; {
    const { nodeId } = e.target.closest(&quot;.Node&quot;).dataset;
    if (nodeId) {
      const selectedNode = this.state.nodes.find((node) =&amp;gt; node.id === nodeId);
      if (selectedNode) {
        this.onClick(selectedNode);
      }
    } else {
      this.onBackClick();
    }
  });

  this.render();
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;그냥 최종 코드를 붙이겠다 이 컴포넌트도 마찬가지로 상단에 this.${변수명}으로 필요한 변수들을 정의한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;여기서 컴포넌트 의존도를 줄이기 위해 매개변수로 받아온 $app, state 같은 변수들을 this.state = state 처럼 지역변수로 만들어 주도록 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;여기도 &lt;b&gt;this.setState&lt;/b&gt;가 보이는데, Nodes의 setState는 App.js에서 호출된다. App.js의 setState안에서 호출된다. App에서 상태가 변경되면 setState가 호출되고 그 안에서 &lt;b&gt;nodes.setState({변경된 변수})&lt;/b&gt; 이렇게 호출된다. 그럼Nodes의 지역변수인 this.state에 App에서 변경되었던 nextState가 반영된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;아래 참고.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1652241252272&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;  this.setState = (nextState) =&amp;gt; {
    this.state = nextState;
    nodes.setState({
      isRoot: this.state.isRoot,
      nodes: this.state.nodes,
      currentPath: this.state.currentPath,
    });
  };&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;그리고 꼭 컴포넌트 안의 지역변수가 변경되었다면 this.render()를 다시 호출해줘야 html에 반영이 된다. 따라서 this.setState에서 변경사항이 다 반영된 후 render()를 호출해주도록 한다. 아 그리고 변경되었을 때만 호출 되는게 아니라 초기에도 호출이 필요하기 때문에 최하단에 &lt;b&gt;&lt;span style=&quot;font-size: 16px; letter-spacing: 0px; color: #e5c07b;&quot;&gt;this&lt;/span&gt;&lt;span style=&quot;font-size: 16px; letter-spacing: 0px; color: #abb2bf;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;font-size: 16px; letter-spacing: 0px; color: #61afef;&quot;&gt;render&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;font-size: 16px; letter-spacing: 0px; color: #abb2bf;&quot;&gt;&lt;b&gt;();&lt;/b&gt; &lt;span style=&quot;color: #000000;&quot;&gt;도 추가해줘야 한다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1652241525595&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;  this.setState = (nextState) =&amp;gt; {
    this.state = nextState;
    this.render();
  };&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;render에서는 해당 컴포넌트에 관련된 추가해줘야 할 요소들을 조작한다. 조작만 하면 안된다. 우리는 new App안에 $app으로 최상단 DOM요소를 전달 받았기 때문에 각 컴포넌트마다 $app을 전달해줄 필요가 있다. $app에 추가해줄 요소들을 appendChild로 추가해준다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1652241624703&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$app.appendChild(nodes);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이벤트 리스너의 경우 웬만하면 render함수 안에 정의하지 말고 밖에 정의하도록 하자. -&amp;gt; &lt;b&gt;이벤트 최적화&lt;br /&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1652241725871&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;nodes.addEventListener(&quot;click&quot;, (e) =&amp;gt; {
    const { nodeId } = e.target.closest(&quot;.Node&quot;).dataset;
    if (nodeId) {
      const selectedNode = this.state.nodes.find((node) =&amp;gt; node.id === nodeId);
      if (selectedNode) {
        this.onClick(selectedNode);
      }
    } else {
      this.onBackClick();
    }
  });&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이런식으로 다른 컴포넌트들도 구성하면 된다 ! 아래에 전체 코드를 첨부하겠다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;index.js&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1652241935402&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import App from &quot;./App.js&quot;;
new App(document.querySelector(&quot;.App&quot;));&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;api.js&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1652241979884&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const API_END_POINT =
  &quot;https://zl3m4qq0l9.execute-api.ap-northeast-2.amazonaws.com/dev&quot;;

export const request = async (nodeId) =&amp;gt; {
  try {
    const response = await fetch(`${API_END_POINT}/${nodeId || &quot;&quot;}`, {
      method: &quot;GET&quot;,
    });
    if (response.ok) return response.json();
    else throw new Error(&quot;error&quot;);
  } catch (e) {
    throw new Error(&quot;error&quot;);
  }
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;App.js&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1652241896628&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import { request } from &quot;../api/api.js&quot;;
import Breadcrumb from &quot;./Breadcrumb.js&quot;;
import Nodes from &quot;./Nodes.js&quot;;
import ImageView from &quot;./ImageView.js&quot;;
import Loading from &quot;./Loading.js&quot;;

const cache = {};

export default function App($app) {
  this.state = {
    isRoot: true,
    nodes: [],
    depthStack: [],
    currentPath: null,
    selectedFilePath: null,
    isLoading: true,
  };

  const loading = new Loading({ $app, initialState: this.state.isLoading });

  const breadcrumb = new Breadcrumb({
    $app,
    state: this.state.depthStack,
    onClick: (index) =&amp;gt; {
      // 루트 노드를 선택한 경우
      if (index === null) {
        this.setState({
          ...this.state,
          isRoot: true,
          depthStack: [],
          nodes: cache[&quot;root&quot;],
          selectedFilePath: null,
        });
        return;
      }

      // 현재 path를 선택한 경우
      if (index === this.state.depthStack.length) {
        return;
      }

      // 그 외
      const depthStack = this.state.depthStack.slice(0, index + 1);

      this.setState({
        ...this.state,
        depthStack: depthStack,
        nodes: cache[depthStack[depthStack.length - 1]].id,
        selectedFilePath: null,
      });
    },
  });

  const nodes = new Nodes({
    $app,
    state: this.state,
    onClick: async (node) =&amp;gt; {
      try {
        this.setState({
          ...this.state,
          isLoading: true,
        });
        if (node.type === &quot;DIRECTORY&quot;) {
          if (cache[node.id]) {
            this.setState({
              ...this.state,
              isRoot: false,
              depthStack: [...this.state.depthStack, node],
              nodes: cache[node.id],
            });
          } else {
            const nextNodes = await request(node.id);
            this.setState({
              ...this.state,
              isRoot: false,
              depthStack: [...this.state.depthStack, node],
              nodes: nextNodes,
            });
            cache[node.id] = nextNodes;
          }
        } else if (node.type === &quot;FILE&quot;) {
          this.setState({
            ...this.state,
            selectedFilePath: node.filePath,
          });
        }
      } catch (e) {
        throw new Error(e.message);
      } finally {
        this.setState({
          ...this.state,
          isLoading: false,
        });
      }
    },
    onBackClick: async () =&amp;gt; {
      try {
        this.setState({
          ...this.state,
          isLoading: true,
        });
        this.state.depthStack.pop();
        const prevId = this.state.depthStack.length
          ? this.state.depthStack[this.state.depthStack.length].id
          : null;

        if (prevId === null) {
          this.setState({
            isRoot: true,
            nodes: cache[&quot;root&quot;],
            depthStack: this.state.depthStack,
          });
        } else {
          this.setState({
            ...this.state,
            isRoot: false,
            nodes: cache[prevId],
            selectedFilePath: null,
            depthStack: this.state.depthStack,
          });
        }
      } catch (e) {
        throw new Error(e.message);
      } finally {
        this.setState({
          ...this.state,
          isLoading: false,
        });
      }
    },
  });

  const imageView = new ImageView({ $app, state: this.state.selectedFilePath });

  this.setState = (nextState) =&amp;gt; {
    this.state = nextState;
    nodes.setState({
      isRoot: this.state.isRoot,
      nodes: this.state.nodes,
      currentPath: this.state.currentPath,
    });
    breadcrumb.setState(this.state.depthStack);
    imageView.setState(this.state.selectedFilePath);
    loading.setState(this.state.isLoading);
  };

  this.init = async () =&amp;gt; {
    try {
      const rootNodes = await request(null);

      this.setState({
        ...this.state,
        nodes: rootNodes,
      });
      cache[&quot;root&quot;] = rootNodes;
    } catch (e) {
      throw new Error(e);
    } finally {
      this.setState({
        ...this.state,
        isLoading: false,
      });
    }
  };
  this.init();
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;Nodes.js&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1652242000738&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;export default function Nodes({ $app, state, onClick, onBackClick }) {
  this.state = state;
  this.onClick = onClick;
  this.onBackClick = onBackClick;

  this.setState = (nextState) =&amp;gt; {
    this.state = nextState;
    this.render();
  };

  const nodes = document.createElement(&quot;div&quot;);
  nodes.className = &quot;Nodes&quot;;

  this.render = () =&amp;gt; {
    const template = this.state.nodes
      .map((node) =&amp;gt; {
        return `
        &amp;lt;div class=&quot;Node&quot; data-node-id=&quot;${node.id}&quot;&amp;gt;
          &amp;lt;img src=&quot;./assets/${node.type.toLowerCase()}.png&quot;
          data-node-id=&quot;${node.id}&quot;/&amp;gt;
          &amp;lt;div&amp;gt;${node.name}&amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;
      `;
      })
      .join(&quot;&quot;);

    const backTemplate = `
      &amp;lt;div class=&quot;Node&quot;&amp;gt;
        &amp;lt;img src=&quot;./assets/prev.png&quot; /&amp;gt;
      &amp;lt;/div&amp;gt;`;

    nodes.innerHTML = this.state.isRoot
      ? template
      : `
      ${backTemplate}
      ${template}
    `;

    $app.appendChild(nodes);
  };

  nodes.addEventListener(&quot;click&quot;, (e) =&amp;gt; {
    const { nodeId } = e.target.closest(&quot;.Node&quot;).dataset;
    if (nodeId) {
      const selectedNode = this.state.nodes.find((node) =&amp;gt; node.id === nodeId);
      if (selectedNode) {
        this.onClick(selectedNode);
      }
    } else {
      this.onBackClick();
    }
  });

  this.render();
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;Breadcrumb.js&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1652242011919&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;export default function Breadcrumb({ $app, state, onClick }) {
  this.state = state;
  this.onClick = onClick;
  this.setState = (nextState) =&amp;gt; {
    this.state = nextState;
    this.render();
  };

  this.$target = document.createElement(&quot;nav&quot;);
  this.$target.className = &quot;Breadcrumb&quot;;
  $app.appendChild(this.$target);

  this.render = () =&amp;gt; {
    if (this.state.length) {
      this.$target.innerHTML = `&amp;lt;div class=&quot;nav-item&quot;&amp;gt;root&amp;lt;/div&amp;gt;
    ${this.state
      .map(
        (node, index) =&amp;gt;
          `&amp;lt;div class=&quot;nav-item&quot; data-index=&quot;${index + 1}&quot;&amp;gt;${node.name}&amp;lt;/div&amp;gt;`
      )
      .join(&quot;&quot;)}`;
    } else {
      this.$target.innerHTML = `&amp;lt;div&amp;gt;root&amp;lt;/div&amp;gt;`;
    }
  };

  this.$target.addEventListener(&quot;click&quot;, (e) =&amp;gt; {
    const { index } = e.target.closest(&quot;.nav-item&quot;).dataset;
    this.onClick(parseInt(index, 10) || null);
  });

  this.render();
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;ImageView.js&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1652242020682&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const IMAGE_PATH_PREFIX = `https://fe-dev-matching-2021-03-serverlessdeploymentbuck-t3kpj3way537.s3.ap-northeast-2.amazonaws.com/public`;

export default function ImageView({ $app, initialState }) {
  this.state = initialState;
  this.setState = (nextState) =&amp;gt; {
    this.state = nextState;
    this.render();
  };

  this.$target = document.createElement(&quot;div&quot;);
  this.$target.className = &quot;Modal ImageViewer&quot;;

  this.render = () =&amp;gt; {
    this.$target.innerHTML = `
      &amp;lt;div class=&quot;content&quot;&amp;gt;
      ${this.state ? `&amp;lt;img src=&quot;${IMAGE_PATH_PREFIX}${this.state}&quot; /&amp;gt;` : &quot;&quot;}
      &amp;lt;/div&amp;gt;
    `;
    this.$target.style.display = this.state ? &quot;block&quot; : &quot;none&quot;;
  };

  this.$target.addEventListener(&quot;click&quot;, (e) =&amp;gt; {
    e.target === this.$target[&quot;Modal&quot;]
      ? this.$target.classList.remove(&quot;ImageViewer&quot;)
      : false;
    this.$target.innerHTML = &quot;&quot;;
    this.$target.style.display = &quot;none&quot;;
  });

  this.render();
  $app.appendChild(this.$target);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;Loading.js&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1652242031642&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;export default function Loading({ $app, initialState }) {
  this.state = initialState;

  this.$target = document.createElement(&quot;div&quot;);
  this.$target.className = &quot;Loading Modal&quot;;
  $app.appendChild(this.$target);

  this.setState = (nextState) =&amp;gt; {
    this.state = nextState;
    this.render();
  };

  this.render = () =&amp;gt; {
    this.$target.innerHTML = `
        &amp;lt;div class=&quot;content&quot;&amp;gt;
            &amp;lt;img src=&quot;./assets/nyan-cat.gif&quot;/&amp;gt;
        &amp;lt;/div&amp;gt;
    `;

    if (this.state) this.$target.style.display = &quot;block&quot;;
    else this.$target.style.display = &quot;none&quot;;
  };
  this.render();
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>javascript</category>
      <category>VanillaJS</category>
      <category>과제테스트</category>
      <category>바닐라JS</category>
      <category>자바스크립트</category>
      <category>프로그래머스</category>
      <author>ruby_s</author>
      <guid isPermaLink="true">https://juyami.tistory.com/108</guid>
      <comments>https://juyami.tistory.com/108#entry108comment</comments>
      <pubDate>Wed, 11 May 2022 13:07:25 +0900</pubDate>
    </item>
    <item>
      <title>[HTML/JS] dataset활용하기 (data-*)</title>
      <link>https://juyami.tistory.com/107</link>
      <description>&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;어느&lt;b&gt; Element&lt;/b&gt;에나 &lt;b&gt;data-&lt;/b&gt;로 시작하는 속성을 사용할 수 있다. 화면에는 렌더링 되지 않게 정보를 엘리먼트에 담아놓을 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;사용법&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1652191990395&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
  class=&quot;item&quot;
  data-node-id=&quot;1&quot;
  data-columns=&quot;3&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;Javascript에서 접근하기&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;자바스크립트에서 &lt;b&gt;dataset&lt;/b&gt;객체를 통해서 data속성을 가져올 수 있다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이때&amp;nbsp; 접두사인 &lt;b&gt;data-&lt;/b&gt;가 제거되고, 모든 대문자는 소문자로 변환된다. 그리고 &lt;b&gt;data-&lt;/b&gt;다음에 오는 속성명은 &lt;b&gt;-(dash)&lt;/b&gt;를 제거하고&amp;nbsp;&lt;b&gt;camelCase&lt;/b&gt;로 변환된다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;예를 들면, data-node-id -&amp;gt; nodeId 로 변환.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;따라서, 아래처럼 사용할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1652192368836&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const { nodeId } = e.target.dataset;
e.target.dataset.nodeId;
e.target.dataset['nodeId'];&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;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;i&gt;&lt;b&gt;in&lt;/b&gt;&lt;/i&gt; 연산자로 해당 속성이 존재하는지 확인할 수도 있다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1652192482541&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;'nodeId' in e.target.dataset&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>javascript</category>
      <author>ruby_s</author>
      <guid isPermaLink="true">https://juyami.tistory.com/107</guid>
      <comments>https://juyami.tistory.com/107#entry107comment</comments>
      <pubDate>Tue, 10 May 2022 23:21:38 +0900</pubDate>
    </item>
    <item>
      <title>net::ERR_ABORTED 404 (Not Found) 에러 해결</title>
      <link>https://juyami.tistory.com/106</link>
      <description>&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;프로그래머스 고양이 사진첩 과제를 구현하던 중 위와 같은 에러를 만났다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;먼저 html에 아래와 같이 스크립트를 연결해줬다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1652159437933&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;script src=&quot;src/js/index.js&quot; type=&quot;module&quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;export, import&lt;/b&gt;를 사용 할 것이기 때문에&lt;b&gt;&lt;i&gt; type=&quot;module&quot;&lt;/i&gt;&lt;/b&gt;이 필요하다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;u&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;i&gt;index.js&lt;/i&gt;&lt;/span&gt;&lt;/u&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1652159506163&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import App from &quot;./App&quot;;
new App(document.querySelector(&quot;.App&quot;));&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;import해줄 것이기 때문에 다른 js파일들은 html에 연결해주지 않아도 된다. &lt;u&gt;index.js&lt;/u&gt;에서 App을 import 후 &lt;i&gt;querySelector&lt;/i&gt;로 앱을 전달해줬는데..! 아래와 같은 에러가 뜬 것이다. App이라는 파일을 찾을 수 없나보다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1652159626287&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;net::ERR_ABORTED 404 (Not Found)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;난 스크립트 태그의 순서에 문제가 있나 했더니.. 파일 확장자를 붙여주지 않아서 웹이 해당 파일을 읽을 수 없던 거다 ㅎㅎ&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1652159695209&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import App from &quot;./App.js&quot;;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;i&gt;import&lt;/i&gt; 시 &lt;b&gt;&lt;i&gt;.js&lt;/i&gt;&lt;/b&gt;를 꼭 붙여주도록 하쟝&lt;/span&gt;&lt;/p&gt;</description>
      <category>javascript</category>
      <author>ruby_s</author>
      <guid isPermaLink="true">https://juyami.tistory.com/106</guid>
      <comments>https://juyami.tistory.com/106#entry106comment</comments>
      <pubDate>Tue, 10 May 2022 14:16:02 +0900</pubDate>
    </item>
    <item>
      <title>[백준] 5052 - 전화번호 목록 | Gold4 | node.js 자바스크립트</title>
      <link>https://juyami.tistory.com/105</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;문제&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/5052&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://www.acmicpc.net/problem/5052&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1651939453768&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;5052번: 전화번호 목록&quot; data-og-description=&quot;첫째 줄에 테스트 케이스의 개수 t가 주어진다. (1 &amp;le; t &amp;le; 50) 각 테스트 케이스의 첫째 줄에는 전화번호의 수 n이 주어진다. (1 &amp;le; n &amp;le; 10000) 다음 n개의 줄에는 목록에 포함되어 있는 전화번호가 &quot; data-og-host=&quot;www.acmicpc.net&quot; data-og-source-url=&quot;https://www.acmicpc.net/problem/5052&quot; data-og-url=&quot;https://www.acmicpc.net/problem/5052&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/0Nxgs/hyOi1922DO/aM9dxJCtP44IynT0sBBr4K/img.png?width=2834&amp;amp;height=1480&amp;amp;face=0_0_2834_1480&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/5052&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.acmicpc.net/problem/5052&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/0Nxgs/hyOi1922DO/aM9dxJCtP44IynT0sBBr4K/img.png?width=2834&amp;amp;height=1480&amp;amp;face=0_0_2834_1480');&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;5052번: 전화번호 목록&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;첫째 줄에 테스트 케이스의 개수 t가 주어진다. (1 &amp;le; t &amp;le; 50) 각 테스트 케이스의 첫째 줄에는 전화번호의 수 n이 주어진다. (1 &amp;le; n &amp;le; 10000) 다음 n개의 줄에는 목록에 포함되어 있는 전화번호가&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;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;코드&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1651939461683&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function solve(phoneNumList) {
  phoneNumList.sort();

  for (let i = 1; i &amp;lt; phoneNumList.length; i++) {
    const prevNum = phoneNumList[i - 1];
    const currNum = phoneNumList[i];
    if (currNum.startsWith(prevNum)) return &quot;NO&quot;;
  }
  return &quot;YES&quot;;
}

const filePath =
  process.platform === &quot;linux&quot; ? &quot;/dev/stdin&quot; : &quot;백준/gold/5052/testcase.txt&quot;;
const input = require(&quot;fs&quot;)
  .readFileSync(filePath)
  .toString()
  .trim()
  .split(&quot;\n&quot;);
for (let i = 1; i &amp;lt; input.length; ) {
  const n = +input[i];
  console.log(solve(input.slice(i + 1, i + 1 + n)));
  i += n + 1;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;처음엔&amp;nbsp; 전화번호의 자릿수가 작은 순으로 오름차순 정렬을 하고 선형 탐색으로 풀었으나 역시나 시간초과 ..!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;생각해보니 문자열 정렬은 &quot;&lt;b&gt;976 &amp;gt; 911867&quot;&lt;/b&gt; 이런식으로 판단을 하기 때문에 그냥 &lt;b&gt;&lt;i&gt;sort&lt;/i&gt;&lt;/b&gt;만 써도 된다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;아래 예제의 경우를 보면,&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;예제 입력 1&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;/div&gt;
&lt;pre id=&quot;sample-input-1&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;976
97625999
91125426&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;예제 출력 1&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;/div&gt;
&lt;pre id=&quot;sample-output-1&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;NO&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;정렬하면 &lt;b&gt;[&quot;91125426&quot;, &quot;976&quot;, &quot;97625999&quot;]&lt;/b&gt; 이렇게 된다. 따라서 i의 현재 값과 다음 값만 비교해줘도 정답이 나온다. 굳이 선형탐색으로 하나하나 비교를 다 안해줘도 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;어리석은 나 반성해라 &lt;/span&gt;&lt;/blockquote&gt;</description>
      <category>백준</category>
      <author>ruby_s</author>
      <guid isPermaLink="true">https://juyami.tistory.com/105</guid>
      <comments>https://juyami.tistory.com/105#entry105comment</comments>
      <pubDate>Sun, 8 May 2022 01:10:08 +0900</pubDate>
    </item>
    <item>
      <title>[프로그래머스] 양과 늑대 | 자바스크립트 | Lv.3 | 2022 KAKAO BLIND RECRUITMENT | DFS</title>
      <link>https://juyami.tistory.com/104</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;문제&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;a href=&quot;https://programmers.co.kr/learn/courses/30/lessons/92343&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://programmers.co.kr/learn/courses/30/lessons/92343&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1651808097702&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;코딩테스트 연습 - 양과 늑대&quot; data-og-description=&quot;[0,0,1,1,1,0,1,0,1,0,1,1] [[0,1],[1,2],[1,4],[0,8],[8,7],[9,10],[9,11],[4,3],[6,5],[4,6],[8,9]] 5 [0,1,0,1,1,0,1,0,0,1,0] [[0,1],[0,2],[1,3],[1,4],[2,5],[2,6],[3,7],[4,8],[6,9],[9,10]] 5&quot; data-og-host=&quot;programmers.co.kr&quot; data-og-source-url=&quot;https://programmers.co.kr/learn/courses/30/lessons/92343&quot; data-og-url=&quot;https://programmers.co.kr/learn/courses/30/lessons/92343&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/dpVWrT/hyOhvRjZpl/CKtKuxeG7HKk4nGa2faX30/img.jpg?width=626&amp;amp;height=626&amp;amp;face=0_0_626_626,https://scrap.kakaocdn.net/dn/cKfW1s/hyOhxByY2G/wh2cvSnyoIKliH2yak52ok/img.jpg?width=626&amp;amp;height=626&amp;amp;face=0_0_626_626,https://scrap.kakaocdn.net/dn/dbPKHt/hyOhzF87hm/S6Aj1q16oBuXCkgmlESKRk/img.png?width=1000&amp;amp;height=1000&amp;amp;face=0_0_1000_1000&quot;&gt;&lt;a href=&quot;https://programmers.co.kr/learn/courses/30/lessons/92343&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://programmers.co.kr/learn/courses/30/lessons/92343&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/dpVWrT/hyOhvRjZpl/CKtKuxeG7HKk4nGa2faX30/img.jpg?width=626&amp;amp;height=626&amp;amp;face=0_0_626_626,https://scrap.kakaocdn.net/dn/cKfW1s/hyOhxByY2G/wh2cvSnyoIKliH2yak52ok/img.jpg?width=626&amp;amp;height=626&amp;amp;face=0_0_626_626,https://scrap.kakaocdn.net/dn/dbPKHt/hyOhzF87hm/S6Aj1q16oBuXCkgmlESKRk/img.png?width=1000&amp;amp;height=1000&amp;amp;face=0_0_1000_1000');&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;코딩테스트 연습 - 양과 늑대&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;[0,0,1,1,1,0,1,0,1,0,1,1] [[0,1],[1,2],[1,4],[0,8],[8,7],[9,10],[9,11],[4,3],[6,5],[4,6],[8,9]] 5 [0,1,0,1,1,0,1,0,0,1,0] [[0,1],[0,2],[1,3],[1,4],[2,5],[2,6],[3,7],[4,8],[6,9],[9,10]] 5&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;programmers.co.kr&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;풀이&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1651808115841&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function solution(info, edges) {
  const tree = Array.from({ length: info.length }, () =&amp;gt; []);
  for (const [parent, child] of edges) tree[parent].push(child);

  let answer = 0;
  function dfs(node, sheep, wolf, possible) {
    answer = Math.max(answer, sheep);
    if (sheep &amp;lt;= wolf) return;

    const possibleNode = [...possible, ...tree[node]];
    possibleNode.splice(possibleNode.indexOf(node), 1);

    for (const next of possibleNode) {
      if (info[next]) dfs(next, sheep, wolf + 1, possibleNode);	// 늑대일 경우
      else dfs(next, sheep + 1, wolf, possibleNode);	// 양일 경우
    }
  }
  dfs(0, 1, 0, [0]);

  return answer;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이 문제 너무 어려웠다.. 그냥 dfs로 하면 이전에 방문했던 곳을 어떻게 또 방문하지 ..? 싶었다..&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;하나씩 풀이해보면, 먼저 parent의 인덱스에 각각 [왼쪽, 오른쪽] 자식을 넣어준다. -&amp;gt; tree&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;아래 예시 사진으로 설명하겠다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;1000&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vb9zX/btrBo12UdCZ/eAu0QlCJpkxkYJKlOVJLO0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vb9zX/btrBo12UdCZ/eAu0QlCJpkxkYJKlOVJLO0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vb9zX/btrBo12UdCZ/eAu0QlCJpkxkYJKlOVJLO0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fvb9zX%2FbtrBo12UdCZ%2FeAu0QlCJpkxkYJKlOVJLO0%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;708&quot; height=&quot;708&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;1000&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;위에서 보면&amp;nbsp; &lt;/span&gt;&lt;b&gt;0 -&amp;gt; 1 -&amp;gt; 8 -&amp;gt; 7 -&amp;gt; 9 -&amp;gt; 4 -&amp;gt; 6 -&amp;gt; 5&lt;/b&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt; 이 순서대로 가야 양의 최대값이 나온다.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1651808460676&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function dfs(node, sheep, wolf, possible) {
    answer = Math.max(answer, sheep);
    if (sheep &amp;lt;= wolf) return;

    const possibleNode = [...possible, ...tree[node]];
    possibleNode.splice(possibleNode.indexOf(node), 1);

    for (const next of possibleNode) {
      if (info[next]) dfs(next, sheep, wolf + 1, possibleNode);
      else dfs(next, sheep + 1, wolf, possibleNode);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;i&gt;dfs&lt;/i&gt;를 들어오면 &lt;i&gt;sheep&lt;/i&gt;개수를 계속해서 반영해준다. 만약 &lt;i&gt;sheep&lt;/i&gt;보다 &lt;i&gt;wolf&lt;/i&gt;의 개수가 크거나 같으면 리턴한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이제 매개변수로 들어온 &lt;i&gt;possible&lt;/i&gt;과 현재 &lt;i&gt;node&lt;/i&gt;의 자식노드들을 합쳐줄 것이다. &lt;i&gt;possible&lt;/i&gt;은 말 그대로 아직까진 방문할 수 있는 노드들을 뜻한다. 만약 2노드를 들어갔다 왔어도 &lt;i&gt;wolf&lt;/i&gt;의 개수가 많아서 종료됐다면 2는 아직 방문의 가능성이 있는 노드가 된다. -&amp;gt; &lt;i&gt;possibleNode&lt;/i&gt;를 반복문 돈다고 해서 꼭 노드가 사라지는게 아님. (나의 큰 착각이였음. &lt;i&gt;dfs&lt;/i&gt;를 들어갔다오면 각 노드가 꼭 사라진다고 인지해버렸다.&lt;i&gt; if (sheep &amp;lt;= wolf) return;&lt;/i&gt; 이 조건에 걸리면 안사라짐.)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;앞서 가능성 있는 노드들과 현재 &lt;i&gt;node&lt;/i&gt;의 자식노드를 합친 다음, 현재 &lt;i&gt;node&lt;/i&gt;는 방문을 했으므로 &lt;i&gt;possibleNode&lt;/i&gt;에서 제거한다.(&lt;b&gt;&lt;i&gt;splice&lt;/i&gt;&lt;/b&gt;) 그리곤 양일 경우와 늑대일 경우를 나눠서 카운트를 조절해주면 된다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;방문한 현재 node와 possibleNode를 순차적으로 보는게 사실 이해가 빠르다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1651809058115&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// console.log(node, possibleNode)
0, [ 1, 8 ]
1, [ 8, 2, 4 ]
8, [ 2, 4, 7, 9 ]
2
4
7, [ 2, 4, 9 ]
2, [ 4, 9 ]
4
9, [ 4, 10, 11 ]
4, [ 10, 11, 3, 6 ]
10
11
3
6&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;0:&lt;/b&gt; 1, 8의 자식노드가 방문 가능한 노드이다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;1:&lt;/b&gt; 본인 1은 제거하고 전달받은 8과 본인의 자식노드 2, 4가 가능성 있는 노드이다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;8:&lt;/b&gt; 본인 8은 제거하고 전달받은 2, 4와 본인의 자식노드 7, 9가 가능성 있는 노드이다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;2:&lt;/b&gt; wolf가 더 커지거나 같으므로 바로 리턴된다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;4:&lt;/b&gt; 마찬가지.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;7:&lt;/b&gt; 본인 7은 제거하고, 8번째 노드에서 그대로 전달받은 2, 4, 9가 가능성 있는 노드이다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;2:&lt;/b&gt; 위의 2와 다르게 sheep의 개수가 늘어서 왔으므로 2도 방문할 수 있다. 본인2는 제거하고, 7에서 전달받은 4, 9가 가능성 있는 노드이다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;4:&lt;/b&gt; return&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;9:&lt;/b&gt; 본인 9는 제거하고, 2에서 전달받은 4와 본인의 자식노드 10, 11이 가능성 있는 노드이다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;4:&lt;/b&gt; 여기서부터 생략 ...&lt;/span&gt;&lt;/blockquote&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: 'Nanum Gothic';&quot;&gt;다음부터는 쉽게 풀었으면 한다.. 난 사실 아직도 재귀가 익숙치 않다 ..ㅎ; 평생 친해지고 싶지 않은 친구다.&lt;/span&gt;&lt;/blockquote&gt;</description>
      <category>프로그래머스</category>
      <category>dfs</category>
      <category>알고리즘</category>
      <category>양과늑대</category>
      <category>자바스크립트</category>
      <category>카카오</category>
      <category>코딩테스트</category>
      <category>프로그래머스</category>
      <author>ruby_s</author>
      <guid isPermaLink="true">https://juyami.tistory.com/104</guid>
      <comments>https://juyami.tistory.com/104#entry104comment</comments>
      <pubDate>Fri, 6 May 2022 12:58:21 +0900</pubDate>
    </item>
    <item>
      <title>[프로그래머스] 길 찾기 게임 | 자바스크립트(js) | Lv.3 | 이진트리 | 2019 KAKAO BLIND RECRUITMENT</title>
      <link>https://juyami.tistory.com/103</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;문제&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;a href=&quot;https://programmers.co.kr/learn/courses/30/lessons/42892&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://programmers.co.kr/learn/courses/30/lessons/42892&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1651761699938&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;코딩테스트 연습 - 길 찾기 게임&quot; data-og-description=&quot;[[5,3],[11,5],[13,3],[3,5],[6,1],[1,3],[8,6],[7,2],[2,2]] [[7,4,6,9,1,8,5,2,3],[9,6,5,8,1,4,3,2,7]]&quot; data-og-host=&quot;programmers.co.kr&quot; data-og-source-url=&quot;https://programmers.co.kr/learn/courses/30/lessons/42892&quot; data-og-url=&quot;https://programmers.co.kr/learn/courses/30/lessons/42892&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/HLB4f/hyOhBQYJCx/qCIAYPK8iHJJ3OnWNK6OTk/img.jpg?width=626&amp;amp;height=626&amp;amp;face=0_0_626_626,https://scrap.kakaocdn.net/dn/c0YQBp/hyOhENHQmh/fKihZAokBlhLsUVhaqu2Kk/img.jpg?width=626&amp;amp;height=626&amp;amp;face=0_0_626_626&quot;&gt;&lt;a href=&quot;https://programmers.co.kr/learn/courses/30/lessons/42892&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://programmers.co.kr/learn/courses/30/lessons/42892&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/HLB4f/hyOhBQYJCx/qCIAYPK8iHJJ3OnWNK6OTk/img.jpg?width=626&amp;amp;height=626&amp;amp;face=0_0_626_626,https://scrap.kakaocdn.net/dn/c0YQBp/hyOhENHQmh/fKihZAokBlhLsUVhaqu2Kk/img.jpg?width=626&amp;amp;height=626&amp;amp;face=0_0_626_626');&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;코딩테스트 연습 - 길 찾기 게임&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;[[5,3],[11,5],[13,3],[3,5],[6,1],[1,3],[8,6],[7,2],[2,2]] [[7,4,6,9,1,8,5,2,3],[9,6,5,8,1,4,3,2,7]]&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;programmers.co.kr&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;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;풀이&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1651761717785&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function solution(nodeinfo) {
  const sorted = nodeinfo
    .map((el, index) =&amp;gt; [...el, index + 1])
    .sort((a, b) =&amp;gt; (a[1] === b[1] ? a[0] - b[0] : b[1] - a[1]));

  function order(sorted, preAnswer, postAnswer) {
    const [x, y, node] = sorted[0];
    const leftChild = [];
    const rightChild = [];

    for (let i = 1; i &amp;lt; sorted.length; i++) {
      const row = sorted[i];
      if (row[0] &amp;lt; x) leftChild.push(row);
      else rightChild.push(row);
    }

    preAnswer.push(node);
    if (leftChild.length) order(leftChild, preAnswer, postAnswer);
    if (rightChild.length) order(rightChild, preAnswer, postAnswer);
    postAnswer.push(node);
  }

  const preAnswer = [];
  const postAnswer = [];
  order(sorted, preAnswer, postAnswer);
  return [preAnswer, postAnswer];
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이 문제는 각 노드마다 x와 y좌표가 주어진다. 이진트리이기 때문에 자식 노드는 최대 2개만 가질 수 있다. 처음에는 무작정 Y값이 현재 노드보다 작은 것을 탐색하고 그 중 X값이 작으면 왼쪽에 배치, X값이 크면 오른쪽에 배치 하려고 했으나..! 그렇게 하면 아래 그림에서 예외가 발생한다.&lt;br /&gt;2노드의 왼쪽 아래에 1이 존재하지만, 1은 2의 자식노드는 아니다. 따라서 단순히 x, y좌표로만 판단해서는 안된다..&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;350&quot; data-origin-height=&quot;174&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dmwFEj/btrBhBdQZfm/Nmhu7RwDGdpAJDp1rIHO0k/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dmwFEj/btrBhBdQZfm/Nmhu7RwDGdpAJDp1rIHO0k/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dmwFEj/btrBhBdQZfm/Nmhu7RwDGdpAJDp1rIHO0k/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdmwFEj%2FbtrBhBdQZfm%2FNmhu7RwDGdpAJDp1rIHO0k%2Fimg.jpg&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;410&quot; height=&quot;204&quot; data-origin-width=&quot;350&quot; data-origin-height=&quot;174&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;div&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;const&lt;span style=&quot;color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #e5c07b;&quot;&gt;sorted&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #56b6c2;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;nodeinfo&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #abb2bf;&quot;&gt;&amp;nbsp; .&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #61afef;&quot;&gt;map&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #abb2bf;&quot;&gt;((&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #e06c75;&quot;&gt;el&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #abb2bf;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #e06c75;&quot;&gt;index&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #abb2bf;&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #c678dd;&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #abb2bf;&quot;&gt; [...&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #e06c75;&quot;&gt;el&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #abb2bf;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #e06c75;&quot;&gt;index&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #56b6c2;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #d19a66;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #abb2bf;&quot;&gt;])&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;&amp;nbsp; .&lt;/span&gt;&lt;span style=&quot;color: #61afef;&quot;&gt;sort&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;((&lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;b&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color: #c678dd;&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color: #d19a66;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color: #56b6c2;&quot;&gt;===&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;b&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color: #d19a66;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color: #c678dd;&quot;&gt;?&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color: #d19a66;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color: #56b6c2;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;b&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color: #d19a66;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color: #c678dd;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;b&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color: #d19a66;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color: #56b6c2;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color: #d19a66;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;]));&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/blockquote&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;먼저 y를 기준으로 정렬을 해줘야 한다. 그 전에 해당 노드의 인덱스를 기억할 필요가 있으므로 마지막 원소에 index를 추가해준다. 왼쪽부터 탐색할 것이기 때문에 y값이 같다면 x값을 기준으로 오름차순으로 정렬해준다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이제 순회 함수를 보자.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;function&lt;span style=&quot;color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #61afef;&quot;&gt;order&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;sorted&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;preAnswer&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;postAnswer&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;) {&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #c678dd;&quot;&gt;&amp;nbsp; &amp;nbsp;const&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color: #e5c07b;&quot;&gt;x&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color: #e5c07b;&quot;&gt;y&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color: #e5c07b;&quot;&gt;node&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color: #56b6c2;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;sorted&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color: #d19a66;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;];&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #c678dd;&quot;&gt;&amp;nbsp; &amp;nbsp;const&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #e5c07b;&quot;&gt;leftChild&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #56b6c2;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; [];&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #c678dd;&quot;&gt;&amp;nbsp; &amp;nbsp;const&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #e5c07b;&quot;&gt;rightChild&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #56b6c2;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; [];&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #c678dd;&quot;&gt;&amp;nbsp; &amp;nbsp;for&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color: #c678dd;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;i&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #56b6c2;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #d19a66;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;i&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #56b6c2;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;sorted&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;length&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;i&lt;/span&gt;&lt;span style=&quot;color: #56b6c2;&quot;&gt;++&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;) {&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #c678dd;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; const&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #e5c07b;&quot;&gt;row&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #56b6c2;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;sorted&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;i&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;];&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #c678dd;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; if&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color: #e5c07b;&quot;&gt;row&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color: #d19a66;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color: #56b6c2;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #e5c07b;&quot;&gt;x&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color: #e5c07b;&quot;&gt;leftChild&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #61afef;&quot;&gt;push&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #e5c07b;&quot;&gt;row&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;);&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #c678dd;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; else&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #e5c07b;&quot;&gt;rightChild&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #61afef;&quot;&gt;push&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #e5c07b;&quot;&gt;row&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;);&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #abb2bf; letter-spacing: 0px;&quot;&gt;&amp;nbsp; &amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;&amp;nbsp; &amp;nbsp;preAnswer&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #61afef;&quot;&gt;push&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #e5c07b;&quot;&gt;node&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;);&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #c678dd;&quot;&gt;&amp;nbsp; &amp;nbsp;if&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color: #e5c07b;&quot;&gt;leftChild&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;length&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color: #61afef;&quot;&gt;order&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #e5c07b;&quot;&gt;leftChild&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;preAnswer&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;postAnswer&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;);&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #c678dd;&quot;&gt;&amp;nbsp; &amp;nbsp;if&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color: #e5c07b;&quot;&gt;rightChild&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;length&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;) &lt;/span&gt;&lt;span style=&quot;color: #61afef;&quot;&gt;order&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #e5c07b;&quot;&gt;rightChild&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;preAnswer&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;postAnswer&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;);&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;&amp;nbsp; &amp;nbsp;postAnswer&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #61afef;&quot;&gt;push&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #e5c07b;&quot;&gt;node&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;)&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #abb2bf; letter-spacing: 0px;&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/blockquote&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;i&gt;sorted&lt;/i&gt;의 상위노드를 꺼내준다. 해당 상위 노드는 &lt;i&gt;answer&lt;/i&gt;에 하나씩 &lt;i&gt;push&lt;/i&gt;할 &lt;i&gt;node&lt;/i&gt;이다.&lt;br /&gt;순회를 시작하기 전에 &lt;i&gt;answer&lt;/i&gt;에 &lt;i&gt;push&lt;/i&gt;하면 &lt;b&gt;전위순회&lt;/b&gt;, 순휘가 끝난 후 뒤에서부터 &lt;i&gt;push&lt;/i&gt;하면 &lt;b&gt;후위순회&lt;/b&gt;가 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;여기서 주목해야 할 것은 반복문의 i는 1부터 시작한다는 것이다. 이미 정렬이 돼있는 배열이므로, 상위노드의 아래 노드들을 쭉 탐색한다.&lt;br /&gt;상위노드의 x값보다 작다면 &lt;b&gt;왼쪽 서브 트리&lt;/b&gt;를 구성하는 노드이므로 &lt;b&gt;&lt;i&gt;leftChild&lt;/i&gt;&lt;/b&gt;에 넣어주고, 상위노드의 x값보다 크다면 &lt;b&gt;오른쪽 서브트리&lt;/b&gt;를 구성하는 노드이므로 &lt;b&gt;&lt;i&gt;rightChild&lt;/i&gt;&lt;/b&gt;에 넣어준다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;i&gt;preAnswer&lt;/i&gt;에는 상위노드를 순차적으로 저장하면 되고, 왼쪽 자식과 오른쪽 자식이 있을 경우, 각각 &lt;b&gt;왼쪽 순회&lt;/b&gt;와 &lt;b&gt;오른쪽 순회&lt;/b&gt;를 돌게 된다. 만약 &lt;b&gt;왼쪽 자식(leftChild)&lt;/b&gt;과 &lt;b&gt;오른쪽 자식(rightChild)&lt;/b&gt;이 모두 없다면 &lt;b&gt;순회는 끝났다&lt;/b&gt;. 이제 맨 하단의 노드부터 재귀를 끝내면서 &lt;i&gt;postAnswer&lt;/i&gt;에 저장될 것이다.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;/span&gt;&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;</description>
      <category>프로그래머스</category>
      <category>js</category>
      <category>길 찾기 게임</category>
      <category>알고리즘</category>
      <category>이진트리</category>
      <category>자바스크립트</category>
      <category>전위순회</category>
      <category>카카오</category>
      <category>코딩테스트</category>
      <category>프로그래머스</category>
      <category>후위순회</category>
      <author>ruby_s</author>
      <guid isPermaLink="true">https://juyami.tistory.com/103</guid>
      <comments>https://juyami.tistory.com/103#entry103comment</comments>
      <pubDate>Fri, 6 May 2022 00:01:38 +0900</pubDate>
    </item>
    <item>
      <title>[프로그래머스] 표 편집 | 자바스크립트 | 2021 카카오 채용연계형 인턴십 | Lv.3</title>
      <link>https://juyami.tistory.com/102</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;문제&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;a href=&quot;https://programmers.co.kr/learn/courses/30/lessons/81303&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://programmers.co.kr/learn/courses/30/lessons/81303&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1651622849385&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;코딩테스트 연습 - 표 편집&quot; data-og-description=&quot;8 2 [&amp;quot;D 2&amp;quot;,&amp;quot;C&amp;quot;,&amp;quot;U 3&amp;quot;,&amp;quot;C&amp;quot;,&amp;quot;D 4&amp;quot;,&amp;quot;C&amp;quot;,&amp;quot;U 2&amp;quot;,&amp;quot;Z&amp;quot;,&amp;quot;Z&amp;quot;] &amp;quot;OOOOXOOO&amp;quot; 8 2 [&amp;quot;D 2&amp;quot;,&amp;quot;C&amp;quot;,&amp;quot;U 3&amp;quot;,&amp;quot;C&amp;quot;,&amp;quot;D 4&amp;quot;,&amp;quot;C&amp;quot;,&amp;quot;U 2&amp;quot;,&amp;quot;Z&amp;quot;,&amp;quot;Z&amp;quot;,&amp;quot;U 1&amp;quot;,&amp;quot;C&amp;quot;] &amp;quot;OOXOXOOO&amp;quot;&quot; data-og-host=&quot;programmers.co.kr&quot; data-og-source-url=&quot;https://programmers.co.kr/learn/courses/30/lessons/81303&quot; data-og-url=&quot;https://programmers.co.kr/learn/courses/30/lessons/81303&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bhfWpX/hyOgqIMj2p/IXC1K4rhowte5fmpPPlAF1/img.jpg?width=626&amp;amp;height=626&amp;amp;face=0_0_626_626,https://scrap.kakaocdn.net/dn/biltj7/hyOgwvteKV/Cs9AKov98ydsZA6duUPzE1/img.jpg?width=626&amp;amp;height=626&amp;amp;face=0_0_626_626,https://scrap.kakaocdn.net/dn/bfng6P/hyOgmTV3XD/5opmsTKMhP8ebJafZyaheK/img.png?width=520&amp;amp;height=400&amp;amp;face=0_0_520_400&quot;&gt;&lt;a href=&quot;https://programmers.co.kr/learn/courses/30/lessons/81303&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://programmers.co.kr/learn/courses/30/lessons/81303&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bhfWpX/hyOgqIMj2p/IXC1K4rhowte5fmpPPlAF1/img.jpg?width=626&amp;amp;height=626&amp;amp;face=0_0_626_626,https://scrap.kakaocdn.net/dn/biltj7/hyOgwvteKV/Cs9AKov98ydsZA6duUPzE1/img.jpg?width=626&amp;amp;height=626&amp;amp;face=0_0_626_626,https://scrap.kakaocdn.net/dn/bfng6P/hyOgmTV3XD/5opmsTKMhP8ebJafZyaheK/img.png?width=520&amp;amp;height=400&amp;amp;face=0_0_520_400');&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;코딩테스트 연습 - 표 편집&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;8 2 [&quot;D 2&quot;,&quot;C&quot;,&quot;U 3&quot;,&quot;C&quot;,&quot;D 4&quot;,&quot;C&quot;,&quot;U 2&quot;,&quot;Z&quot;,&quot;Z&quot;] &quot;OOOOXOOO&quot; 8 2 [&quot;D 2&quot;,&quot;C&quot;,&quot;U 3&quot;,&quot;C&quot;,&quot;D 4&quot;,&quot;C&quot;,&quot;U 2&quot;,&quot;Z&quot;,&quot;Z&quot;,&quot;U 1&quot;,&quot;C&quot;] &quot;OOXOXOOO&quot;&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;programmers.co.kr&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;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;풀이&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1651622901619&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function solution(n, k, cmd) {
  const stack = [];
  const answer = Array.from({ length: n }, () =&amp;gt; &quot;O&quot;);
  const list = Array.from({ length: n }, (_, index) =&amp;gt; [index - 1, index + 1]);
  list[n - 1][1] = -1;

  function upNode(k, row) {
    for (let i = 0; i &amp;lt; row; i++) k = list[k][0];
    return k;
  }

  function downNode(k, row) {
    for (let i = 0; i &amp;lt; row; i++) k = list[k][1];
    return k;
  }

  function deleteNode(k) {
    const [prev, next] = list[k];
    stack.push([k, prev, next]);
    answer[k] = &quot;X&quot;;

    if (next === -1) {
      if (prev !== -1) list[prev][1] = next;
      k = prev;
    } else {
      list[next][0] = prev;
      if (prev !== -1) list[prev][1] = next;
      k = next;
    }
    return k;
  }

  function restoreNode() {
    const [node, prev, next] = stack.pop();
    if (prev !== -1) list[prev][1] = node;
    if (next !== -1) list[next][0] = node;
    answer[node] = &quot;O&quot;;
  }

  for (const item of cmd) {
    const [direct, row] = item.split(&quot; &quot;);
    switch (direct) {
      case &quot;D&quot;:
        k = downNode(k, +row);
        break;
      case &quot;U&quot;:
        k = upNode(k, +row);
        break;
      case &quot;C&quot;:
        k = deleteNode(k);
        break;
      case &quot;Z&quot;:
        restoreNode();
        break;
    }
  }
  return answer.join(&quot;&quot;);
}&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이 문제는 양방향 연결 리스트를 사용해야 효율성까지 통과하는 문제인 것 같다..&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1651622975282&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function upNode(k, row) {
    for (let i = 0; i &amp;lt; row; i++) k = list[k][0];
    return k;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;k의 위치를 위로 올리는 함수부터 보자. row에는 얼만큼 올려야 하는 지 숫자가 들어온다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;예를 들어 3만큼 올리려면, 3번 반복하면서 현재 k위치가 가리키는 prev를 k에 대입해준다. 그렇게 3번 반복하면 k의 현재 위치는 3번째 위에 있는 노드가 될 것이다. &lt;span style=&quot;color: #61afef;&quot;&gt;downNode&lt;span style=&quot;color: #000000;&quot;&gt; 함수도 이와 같은 방식이다.&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #61afef;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;중요한 것은 &lt;span style=&quot;color: #61afef;&quot;&gt;deleteNode&lt;span style=&quot;color: #000000;&quot;&gt;와&lt;/span&gt; &lt;span style=&quot;color: #61afef;&quot;&gt;restoreNode&lt;span style=&quot;color: #000000;&quot;&gt; 함수이다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1651623218326&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function deleteNode(k) {
    const [prev, next] = list[k];
    stack.push([k, prev, next]);
    answer[k] = &quot;X&quot;;

    if (next === -1) {
      if (prev !== -1) list[prev][1] = next;
      k = prev;
    } else {
      list[next][0] = prev;
      if (prev !== -1) list[prev][1] = next;
      k = next;
    }
    return k;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;next가 1인 경우는 마지막 행을 뜻하므로 k를 이전 행으로 변경해준다. 그리고 prev가 -1이 아닌 경우 (행이 한개인 경우가 아닐 경우), 이전 행의 next는 -1이 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;next가 1이 아닌 경우는 마지막 행이 아닐 때이다. next가 가리키는 prev를 현재의 prev로 변경해주고, prev의 다음 값이 현재의 next가 되도록 변경해준다. 그리고 k를 다음 행으로 넘긴다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이제 restoreNode함수를 보자.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1651624174055&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function restoreNode() {
    const [node, prev, next] = stack.pop();
    if (prev !== -1) list[prev][1] = node;
    if (next !== -1) list[next][0] = node;
    answer[node] = &quot;O&quot;;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;가장 최신의 행을 스택에서 pop한다. if으로 모두 예외 처리를 해주고, prev의 다음 값을 현재 행으로, next의 이전 값을 현재 행으로 바꿔주고 answer의 node위치를 O로 변경해준다 !&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;자료구조 때 배웠던 양방향 연결 리스트를 다시 한번 복습했다.. &lt;/span&gt;&lt;/blockquote&gt;</description>
      <category>프로그래머스</category>
      <category>알고리즘</category>
      <category>양방향 연결 리스트</category>
      <category>카카오</category>
      <category>코딩테스트</category>
      <category>프로그래머스</category>
      <author>ruby_s</author>
      <guid isPermaLink="true">https://juyami.tistory.com/102</guid>
      <comments>https://juyami.tistory.com/102#entry102comment</comments>
      <pubDate>Wed, 4 May 2022 09:34:19 +0900</pubDate>
    </item>
    <item>
      <title>[프로그래머스] 징검다리 건너기 | 자바스크립트 | Lv.3 | 2019 카카오 개발자 겨울 인턴십</title>
      <link>https://juyami.tistory.com/101</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;문제&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;a href=&quot;https://programmers.co.kr/learn/courses/30/lessons/64062&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://programmers.co.kr/learn/courses/30/lessons/64062&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1651495867845&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;코딩테스트 연습 - 징검다리 건너기&quot; data-og-description=&quot;[2, 4, 5, 3, 2, 1, 4, 2, 5, 1] 3 3&quot; data-og-host=&quot;programmers.co.kr&quot; data-og-source-url=&quot;https://programmers.co.kr/learn/courses/30/lessons/64062&quot; data-og-url=&quot;https://programmers.co.kr/learn/courses/30/lessons/64062&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bCUbYO/hyOffOCbQa/Sv5f2bW8j0idXLdstjfOrK/img.jpg?width=626&amp;amp;height=626&amp;amp;face=0_0_626_626,https://scrap.kakaocdn.net/dn/gYOUP/hyOfgmsYcN/lOPHnOPakkp5zGjZYTFBo1/img.jpg?width=626&amp;amp;height=626&amp;amp;face=0_0_626_626&quot;&gt;&lt;a href=&quot;https://programmers.co.kr/learn/courses/30/lessons/64062&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://programmers.co.kr/learn/courses/30/lessons/64062&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bCUbYO/hyOffOCbQa/Sv5f2bW8j0idXLdstjfOrK/img.jpg?width=626&amp;amp;height=626&amp;amp;face=0_0_626_626,https://scrap.kakaocdn.net/dn/gYOUP/hyOfgmsYcN/lOPHnOPakkp5zGjZYTFBo1/img.jpg?width=626&amp;amp;height=626&amp;amp;face=0_0_626_626');&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;코딩테스트 연습 - 징검다리 건너기&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;[2, 4, 5, 3, 2, 1, 4, 2, 5, 1] 3 3&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;programmers.co.kr&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;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;풀이&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;정확성O, 효율성X 코드&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1651496035937&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function solution2(stones, k) { // 정확성만 통과
  let start = 1,
    end = Math.max(...stones);
  while (start &amp;lt;= end) {
    const mid = Math.floor((start + end) / 2);
    const temp = stones.map((num) =&amp;gt; num - mid);
    let count = 0;
    for (const num of temp) {
      if (num &amp;lt;= 0) count++;
      else count = 0;
      if (count &amp;gt;= k) break;
    }
    if (count &amp;gt;= k) end = mid - 1;
    else {
      start = mid + 1;
    }
  }
  return start;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;&lt;b&gt;정확성O, 효율성O&lt;/b&gt;&amp;nbsp;통과 코드&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1651496649673&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function solution1(stones, k) { // 효율성 통과
  let start = 1,
    end = 200000000;
  while (start &amp;lt;= end) {
    const mid = Math.floor((start + end) / 2);
    let count = 0;
    for (const num of stones) {
      if (num - mid &amp;lt;= 0) count++;
      else count = 0;
      if (count &amp;gt;= k) break;
    }
    if (count &amp;gt;= k) end = mid - 1;
    else {
      start = mid + 1;
    }
  }
  return start;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;수의 범위가 20만까지 가기 때문에 단순히 반복문만 돌려서 하기엔 시간 초과가 날 거라는 걸 알 수 있다. 그렇기 때문에 딱 봤을 때 &lt;b&gt;이분탐색&lt;/b&gt;을 사용해야 할 것 같았다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;stones배열 원소들의 범위는&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt; 1 이상 200,000,000 이하&lt;/b&gt;인 자연수라고 주어졌기 때문에 start를 1로, end를 200,000,000으로 두고stones를 한번 돌때마다 mid값을 갱신한다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1651496674780&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;for (const num of stones) {
  if (num - mid &amp;lt;= 0) count++;
  else count = 0;
  if (count &amp;gt;= k) break;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;이 부분은 연속된 0의 최대 개수를 구하는 로직이다. stones의 각 원소에 mid를 뺀값이 0보다 작거나 같을 경우 mid가 해당 원소보다 크거나 같다는 뜻이다. 1부터 200,000,000사이를 범위로 해서 mid를 계속 갱신해서 stones에 반영해보고 mid의 왼쪽 범위를 탐색해야 할 지 오른쪽 범위를 탐색해야 할지 선택하는 방식이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt; count가 k보다 클 경우, end를 mid - 1로 왼쪽(아래) 값을 탐색하도록하고, &lt;span style=&quot;color: #000000;&quot;&gt;count가 k보다 작을 경우, start를 mid + 1로 오른쪽(위) 값을 탐색하도록 한다.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: 'Nanum Gothic';&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;아래 예제를 통해 알아보자.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;입출력 예 #1&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;첫 번째 친구는 다음과 같이 징검다리를 건널 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;135&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/PvJf9/btrA7aMzvMZ/WXbG8KJcQvgpMdT88eGV2k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/PvJf9/btrA7aMzvMZ/WXbG8KJcQvgpMdT88eGV2k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/PvJf9/btrA7aMzvMZ/WXbG8KJcQvgpMdT88eGV2k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FPvJf9%2FbtrA7aMzvMZ%2FWXbG8KJcQvgpMdT88eGV2k%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;500&quot; height=&quot;135&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;135&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;첫 번째 친구가 징검다리를 건넌 후 디딤돌에 적힌 숫자는 아래 그림과 같습니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;두 번째 친구도 아래 그림과 같이 징검다리를 건널 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;136&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/5HqVW/btrA7OP2Lxa/K5ibsGQvkMVXsNOyrgDT31/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/5HqVW/btrA7OP2Lxa/K5ibsGQvkMVXsNOyrgDT31/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/5HqVW/btrA7OP2Lxa/K5ibsGQvkMVXsNOyrgDT31/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F5HqVW%2FbtrA7OP2Lxa%2FK5ibsGQvkMVXsNOyrgDT31%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;500&quot; height=&quot;136&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;136&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;두 번째 친구가 징검다리를 건넌 후 디딤돌에 적힌 숫자는 아래 그림과 같습니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;세 번째 친구도 아래 그림과 같이 징검다리를 건널 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;501&quot; data-origin-height=&quot;136&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b4uu9Q/btrA6zy4x6Q/JUl3MepttIeFmWU22NibH0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b4uu9Q/btrA6zy4x6Q/JUl3MepttIeFmWU22NibH0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b4uu9Q/btrA6zy4x6Q/JUl3MepttIeFmWU22NibH0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb4uu9Q%2FbtrA6zy4x6Q%2FJUl3MepttIeFmWU22NibH0%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;501&quot; height=&quot;136&quot; data-origin-width=&quot;501&quot; data-origin-height=&quot;136&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;세 번째 친구가 징검다리를 건넌 후 디딤돌에 적힌 숫자는 아래 그림과 같습니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;네 번째 친구가 징검다리를 건너려면, 세 번째 디딤돌에서 일곱 번째 디딤돌로 네 칸을 건너뛰어야 합니다. 하지만 k = 3 이므로 건너뛸 수 없습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;501&quot; data-origin-height=&quot;135&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/x6iDS/btrA54zidbW/mP36Q2y3AHzfslenhsmI2K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/x6iDS/btrA54zidbW/mP36Q2y3AHzfslenhsmI2K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/x6iDS/btrA54zidbW/mP36Q2y3AHzfslenhsmI2K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fx6iDS%2FbtrA54zidbW%2FmP36Q2y3AHzfslenhsmI2K%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;501&quot; height=&quot;135&quot; data-origin-width=&quot;501&quot; data-origin-height=&quot;135&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;따라서 최대 3명이 디딤돌을 모두 건널 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style4&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;만약 mid가 200,000,000부터 계속 1/2씩 줄여와서 5가 됐다고 치자. 그럼 num - mid가 &amp;lt;= 0인 연속적인 부분의 최대 길이는 전체 길이가 될거다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;여기서 다시 end를 5 - 1 = 4 로 갱신하면 mid는 2가 된다. 그럼 num - mid가 &amp;lt;= 0인 연속적인 부분의 최대 길이는 5번째의&lt;b&gt; 2 1&lt;/b&gt; 이 부분일거다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;2 &amp;lt; k이므로 start = mid + 1 = 3으로 갱신하면 mid는 3이 된다. 그럼 num - mid가 &amp;lt;= 0인 연속적인 부분의 최대 길이는 4번째의&lt;b&gt; 3 2 1&lt;/b&gt;&amp;nbsp;이 부분일거다. 3 &amp;gt;= k이므로 end를 mid - 1 = 2로 갱신되고 start &amp;lt;= end를 만족하지 못해 while문을 빠져나오게 된다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;나는 이분탐색을 인덱스에서 활용하는 법만 알았는데 이런식으로 원소들의 최대 최소값을 기준으로 탐색할 수도 있다는 걸 알았다. 다음에 요런 문제 나오면 제대로 활용해봐야지 ..&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>프로그래머스</category>
      <category>알고리즘</category>
      <category>이분탐색</category>
      <category>자바스크립트</category>
      <category>징검다리 건너기</category>
      <category>카카오</category>
      <category>프로그래머스</category>
      <author>ruby_s</author>
      <guid isPermaLink="true">https://juyami.tistory.com/101</guid>
      <comments>https://juyami.tistory.com/101#entry101comment</comments>
      <pubDate>Mon, 2 May 2022 22:30:11 +0900</pubDate>
    </item>
    <item>
      <title>[백준][브루트포스]치킨 배달 - node.js | javascript | gold5</title>
      <link>https://juyami.tistory.com/100</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;문제&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/15686&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://www.acmicpc.net/problem/15686&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1651106865097&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;15686번: 치킨 배달&quot; data-og-description=&quot;크기가 N&amp;times;N인 도시가 있다. 도시는 1&amp;times;1크기의 칸으로 나누어져 있다. 도시의 각 칸은 빈 칸, 치킨집, 집 중 하나이다. 도시의 칸은 (r, c)와 같은 형태로 나타내고, r행 c열 또는 위에서부터 r번째 칸&quot; data-og-host=&quot;www.acmicpc.net&quot; data-og-source-url=&quot;https://www.acmicpc.net/problem/15686&quot; data-og-url=&quot;https://www.acmicpc.net/problem/15686&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/GOCAs/hyOczldOGj/yeSxpvm6vQoRGlllIaQIIK/img.png?width=2834&amp;amp;height=1480&amp;amp;face=0_0_2834_1480&quot;&gt;&lt;a href=&quot;https://www.acmicpc.net/problem/15686&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.acmicpc.net/problem/15686&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/GOCAs/hyOczldOGj/yeSxpvm6vQoRGlllIaQIIK/img.png?width=2834&amp;amp;height=1480&amp;amp;face=0_0_2834_1480');&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;15686번: 치킨 배달&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;크기가 N&amp;times;N인 도시가 있다. 도시는 1&amp;times;1크기의 칸으로 나누어져 있다. 도시의 각 칸은 빈 칸, 치킨집, 집 중 하나이다. 도시의 칸은 (r, c)와 같은 형태로 나타내고, r행 c열 또는 위에서부터 r번째 칸&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;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;b&gt;풀이&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1651106421332&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function solve() {
  const twoIdxList = [],
    oneIdxList = [];
  for (let i = 0; i &amp;lt; n; i++) {
    for (let j = 0; j &amp;lt; n; j++) {
      if (city[i][j] === 2) twoIdxList.push([i, j]);
      else if (city[i][j] === 1) oneIdxList.push([i, j]);
    }
  }

  function getCombination(arr, num) {
    const result = [];
    if (num === 1) return arr.map((el) =&amp;gt; [el]);

    arr.forEach((fixed, index, origin) =&amp;gt; {
      const rest = origin.slice(index + 1);
      const combination = getCombination(rest, num - 1);
      const attached = combination.map((el) =&amp;gt; [fixed, ...el]);
      result.push(...attached);
    });
    return result;
  }

  function getMinDistance(chickenIdx) {
    let sum = 0;
    for (const [oneX, oneY] of oneIdxList) {
      let distance = Infinity;
      for (const [twoX, twoY] of chickenIdx) {
        distance = Math.min(
          distance,
          Math.abs(oneX - twoX) + Math.abs(oneY - twoY)
        );
      }
      sum += distance;
    }
    return sum;
  }

  const combination = getCombination(twoIdxList, m);

  let answer = Infinity;
  for (const indexs of combination) {
    answer = Math.min(answer, getMinDistance(indexs));
  }
  return answer;
}

const filePath =
  process.platform === &quot;linux&quot; ? &quot;/dev/stdin&quot; : &quot;백준/gold/15686/testcase.txt&quot;;
const input = require(&quot;fs&quot;)
  .readFileSync(filePath)
  .toString()
  .trim()
  .split(&quot;\n&quot;)
  .map((row) =&amp;gt; row.split(&quot; &quot;).map((el) =&amp;gt; +el));
const [n, m] = input[0];
const city = input.slice(1);
console.log(solve());&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;이 문제는 조합만 쓰면 쉽게 푸는 문제다.&lt;br /&gt;조합으로 치킨 집(2) 중 폐업 시키지 않을 인덱스 조합들을 만들고, 집(1)에서부터 치킨 집까지의 거리를 쭉 반복문 돌려서 구하면 된다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #e5c07b;&quot;&gt;Math&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #61afef;&quot;&gt;min &lt;/span&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; font-size: 1.12em; letter-spacing: 0px;&quot;&gt;으로 계속해서 최소값을 반영해주면 풀이 끝 !&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;좀 더 쉬운 풀이를 아시거나 고쳐야 할 코드가 있다면 댓글로 알려주세요 !  &lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>백준</category>
      <category>Node.js</category>
      <category>백준</category>
      <category>브루트포스</category>
      <category>알고리즘</category>
      <category>자바스크립트</category>
      <category>코딩테스트</category>
      <author>ruby_s</author>
      <guid isPermaLink="true">https://juyami.tistory.com/100</guid>
      <comments>https://juyami.tistory.com/100#entry100comment</comments>
      <pubDate>Thu, 28 Apr 2022 09:46:18 +0900</pubDate>
    </item>
    <item>
      <title>[RN] 수많은 오류(에러) 해결..</title>
      <link>https://juyami.tistory.com/99</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;진짜 공식 문서만 주의깊게 읽어도 나지 않을 에러들이 많은 것 같다..ㅎ&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1. Could not find proper version of cocoapods (1.11.3) in any of the sources Run `bundle install` to install missing gems.&lt;/b&gt;&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
  왜 그런지 모르겠다만.. pod install 을 하면 자꾸만 저 에러가 난다. 그럴 경우 하라는 대로 하면된다. 
 &lt;br&gt;$ bundle install 을 실행후 pod install 을 하면 잘된다. 
&lt;/blockquote&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt; &lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2. Command failed: ./gradlew app:installDebug -PreactNativeDevServerPort=8081&lt;/b&gt;&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
  이건 어이없는 오류 ㅎ 
 &lt;br&gt;이미 실행 중인 포트가 있는 거다. 터미널에서 뭐가 돌아가고 있는지 주의 깊게 보자.. 종료하고 실행하면 잘 될거다 
&lt;/blockquote&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt; &lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;3. mac jdk Android Gradle plugin requires Java 11 to run. You are currently using Java 1.8.&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;1. Android - Preferences에 들어간다. (mac기준) - 윈도우는 File - setting일거다.&lt;br&gt;&lt;br&gt;2. Build, Execution, Deployment - Build tools - Gradle 에 들어가면 아래와 같은 화면이 보인다.&lt;br&gt;- 단, 내가 작업하고 있는 폴더의 android 폴더로 프로젝트를 열어 준 뒤 들어가야 한다.&lt;br&gt;난 그것도 모르고 시작화면에서 Gradle projects가 안보여서 헤맸다&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2188&quot; data-origin-height=&quot;1680&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cGjWG2/btryc7GFuU6/6KaCDMyONFMRpzi3KC1Ep1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cGjWG2/btryc7GFuU6/6KaCDMyONFMRpzi3KC1Ep1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cGjWG2/btryc7GFuU6/6KaCDMyONFMRpzi3KC1Ep1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcGjWG2%2Fbtryc7GFuU6%2F6KaCDMyONFMRpzi3KC1Ep1%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;2188&quot; height=&quot;1680&quot; data-origin-width=&quot;2188&quot; data-origin-height=&quot;1680&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size18&quot;&gt;여기서 Gradle JDK를 11버전으로 맞춰주자.&lt;br&gt;안드로이드를 처음 깐 경우 JDK가 없는 것 같다. 그래서 나는 아래 링크에서 다운로드 받았다.&lt;br&gt;&lt;a href=&quot;https://www.oracle.com/kr/java/technologies/javase/jdk11-archive-downloads.html&quot; target=&quot;_blank&quot;&gt;&lt;span&gt;https://www.oracle.com/kr/java/technologies/javase/jdk11-archive-downloads.html&lt;/span&gt;&lt;/a&gt;&lt;br&gt;다운로드 받고 Add JDK로 다운받은 파일을 넣어주면 된다~!&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1586&quot; data-origin-height=&quot;618&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cZwn4h/btryg3pQljX/KLTJRBDeMbGblJfGieJFJk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cZwn4h/btryg3pQljX/KLTJRBDeMbGblJfGieJFJk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cZwn4h/btryg3pQljX/KLTJRBDeMbGblJfGieJFJk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcZwn4h%2Fbtryg3pQljX%2FKLTJRBDeMbGblJfGieJFJk%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;1586&quot; height=&quot;618&quot; data-origin-width=&quot;1586&quot; data-origin-height=&quot;618&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;h3 data-ke-size=&quot;size23&quot;&gt; &lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;4. Requiring unknown module 'undefined' ~&lt;/b&gt;&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
  1. node_module 폴더 및 yarn.lock 파일 삭제 
 &lt;br&gt;2. $ yarn 
 &lt;br&gt;3. $ yarn cache clean 
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt; &lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;5. adb reverse ENOENT&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;환경변수가 잘못 설정되어서 나는 오류다.&lt;/span&gt;&lt;br&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;해결법(macOS 기준)&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;br&gt;&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;1. bash_profile을 열어준다.&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;br&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot;&gt;&lt;code&gt;$ open ~/.bash_profile&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;2. 다음 환경변수를 맨 아래에 넣어주자. 참고로 open명령어는 메모장처럼 마우스로 조작이 가능하다.&lt;/b&gt;&lt;/p&gt;
&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot;&gt;&lt;code&gt;export ANDROID_SDK=/Users/&amp;lt;your_computer_name&amp;gt;/Library/Android/sdk
export PATH=/Users/&amp;lt;your_computer_name&amp;gt;/Library/Android/sdk/platform-tools:$PATH&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;3. 저장 후 닫기&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;br&gt;&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;4. 변경사항 컴파일하기&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;br&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot;&gt;&lt;code&gt;source ~/.bash_profile&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt; &lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;6. Error while waiting for device: AVD Pixel_2_API_28_2 is already running. If that is not the case, delete the files at C:\Users\UserName\.android\avd/Pixel_2_API_28_2.avd/*.lock and try again.&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;에뮬레이터를 비정상적으로 종료했을 때 뜨는 오류다. 이상하게 종료 버튼을 눌렀는데 종료가 되지 않았다. 그래서 강제 종료를 하려고 하였으나 그것조차 먹지 않았다..&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;br&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. 해당 Virtual Device를 삭제한다. 디바이스의 오른쪽에 점 3개 버튼을 누르면 Delete 할 수 있다.&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;br&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. 종료할 때는 에뮬레이터에서 탭의 x버튼을 눌러 지워주면 된다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt; &lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;7. The following build commands failed: CompileC /Users/ ••• main.m normal x86_64 objective-c com.apple.compilers.llvm.clang.1_0.compiler&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이럴 경우 pod를 재설치 해주면 된다. 아마 라이브러리를 install 했다가 삭제한 경우 ios와 android에 반영되는 문제 때문에 발생한 것같다.&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
  $ cd ios -&amp;gt; ios 폴더로 이동 
 &lt;br&gt;$ pod deintegrate -&amp;gt; pod 삭제 
 &lt;br&gt;$ pod update -&amp;gt; 최신버전으로 업데이트 
 &lt;br&gt;$ pod install -&amp;gt; Podfile의 라이브러리 재설치 
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Podfile에 여러 라이브러리가 들어있는 상태에서 install &amp;amp; update하면 라이브러리들이 설치된다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;추가로 아래 명령어를 사용하면 문제가 있는 부분을 진단해준다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot;&gt;&lt;code&gt;$ npx @react-native-community/cli doctor&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt; &lt;/p&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot;&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;참고&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;react-native android 세팅&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;br&gt;&lt;/span&gt;&lt;a href=&quot;https://reactnative.dev/docs/environment-setup#installing-dependencies&quot; target=&quot;_blank&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;https://reactnative.dev/docs/environment-setup#installing-dependencies&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;figure data-ke-type=&quot;opengraph&quot; data-og-title=&quot;Setting up the development environment · React Native&quot; data-ke-align=&quot;alignCenter&quot; data-og-description=&quot;This page will help you install and build your first React Native app.&quot; data-og-host=&quot;reactnative.dev&quot; data-og-source-url=&quot;https://reactnative.dev/docs/environment-setup#installing-dependencies&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cmm6I2/hyNTt71bB2/mEbikKKnqTUKP76zdfUY8k/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/biCIL0/hyNUwB4TqK/sz0SdZF612rYnCMiuA1BWK/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/mUH1i/hyNTqXK9i1/Jv5w8zNgVIg5xQcNUTYdVk/img.png?width=1724&amp;amp;height=1158&amp;amp;face=0_0_1724_1158&quot; data-og-url=&quot;https://reactnative.dev/docs/environment-setup&quot;&gt;
 &lt;a href=&quot;https://reactnative.dev/docs/environment-setup&quot; target=&quot;_blank&quot; data-source-url=&quot;https://reactnative.dev/docs/environment-setup#installing-dependencies&quot;&gt;
  &lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cmm6I2/hyNTt71bB2/mEbikKKnqTUKP76zdfUY8k/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/biCIL0/hyNUwB4TqK/sz0SdZF612rYnCMiuA1BWK/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/mUH1i/hyNTqXK9i1/Jv5w8zNgVIg5xQcNUTYdVk/img.png?width=1724&amp;amp;height=1158&amp;amp;face=0_0_1724_1158')&quot;&gt; 
  &lt;/div&gt;
  &lt;div class=&quot;og-text&quot;&gt;
   &lt;p class=&quot;og-title&quot;&gt;Setting up the development environment · React Native&lt;/p&gt;
   &lt;p class=&quot;og-desc&quot;&gt;This page will help you install and build your first React Native app.&lt;/p&gt;
   &lt;p class=&quot;og-host&quot;&gt;reactnative.dev&lt;/p&gt;
  &lt;/div&gt;&lt;/a&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.npmjs.com/package/react-native-image-crop-picker?activeTab=versions&quot; target=&quot;_self&quot;&gt;&lt;span&gt;https://www.npmjs.com/package/react-native-image-crop-picker?activeTab=versions&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;figure data-ke-type=&quot;opengraph&quot; data-og-title=&quot;react-native-image-crop-picker&quot; data-ke-align=&quot;alignCenter&quot; data-og-description=&quot;Select single or multiple images, with cropping option. Latest version: 0.37.3, last published: 2 months ago. Start using react-native-image-crop-picker in your project by running `npm i react-native-image-crop-picker`. There are 57 other projects in the n&quot; data-og-host=&quot;www.npmjs.com&quot; data-og-source-url=&quot;https://www.npmjs.com/package/react-native-image-crop-picker?activeTab=versions&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bsR87M/hyNTnGJ0QG/dSff54x8XpllcxbHnrBmqK/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/2yz0I/hyNUxudB5w/dCQPULCvA6k9f5v4ad7z2K/img.png?width=828&amp;amp;height=1792&amp;amp;face=0_0_828_1792,https://scrap.kakaocdn.net/dn/c6xzAe/hyNUsfnpsE/AYKMWQIeIKRfwfp3vn9Z4k/img.png?width=828&amp;amp;height=1792&amp;amp;face=0_0_828_1792&quot; data-og-url=&quot;https://www.npmjs.com/package/react-native-image-crop-picker&quot;&gt;
 &lt;a href=&quot;https://www.npmjs.com/package/react-native-image-crop-picker&quot; target=&quot;_blank&quot; data-source-url=&quot;https://www.npmjs.com/package/react-native-image-crop-picker?activeTab=versions&quot;&gt;
  &lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bsR87M/hyNTnGJ0QG/dSff54x8XpllcxbHnrBmqK/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/2yz0I/hyNUxudB5w/dCQPULCvA6k9f5v4ad7z2K/img.png?width=828&amp;amp;height=1792&amp;amp;face=0_0_828_1792,https://scrap.kakaocdn.net/dn/c6xzAe/hyNUsfnpsE/AYKMWQIeIKRfwfp3vn9Z4k/img.png?width=828&amp;amp;height=1792&amp;amp;face=0_0_828_1792')&quot;&gt; 
  &lt;/div&gt;
  &lt;div class=&quot;og-text&quot;&gt;
   &lt;p class=&quot;og-title&quot;&gt;react-native-image-crop-picker&lt;/p&gt;
   &lt;p class=&quot;og-desc&quot;&gt;Select single or multiple images, with cropping option. Latest version: 0.37.3, last published: 2 months ago. Start using react-native-image-crop-picker in your project by running `npm i react-native-image-crop-picker`. There are 57 other projects in the n&lt;/p&gt;
   &lt;p class=&quot;og-host&quot;&gt;www.npmjs.com&lt;/p&gt;
  &lt;/div&gt;&lt;/a&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/ivpusic/react-native-image-crop-picker&quot; target=&quot;_self&quot;&gt;&lt;span&gt;https://github.com/ivpusic/react-native-image-crop-picker&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;figure data-ke-type=&quot;opengraph&quot; data-og-title=&quot;GitHub - ivpusic/react-native-image-crop-picker: iOS/Android image picker with support for camera, video, configurable compressi&quot; data-ke-align=&quot;alignCenter&quot; data-og-description=&quot;iOS/Android image picker with support for camera, video, configurable compression, multiple images and cropping - GitHub - ivpusic/react-native-image-crop-picker: iOS/Android image picker with supp...&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/ivpusic/react-native-image-crop-picker&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/gbtCD/hyNUr8CmBB/wg2pwriKjfrAYMm9mQbqz0/img.png?width=1200&amp;amp;height=600&amp;amp;face=984_118_1045_185&quot; data-og-url=&quot;https://github.com/ivpusic/react-native-image-crop-picker&quot;&gt;
 &lt;a href=&quot;https://github.com/ivpusic/react-native-image-crop-picker&quot; target=&quot;_blank&quot; data-source-url=&quot;https://github.com/ivpusic/react-native-image-crop-picker&quot;&gt;
  &lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/gbtCD/hyNUr8CmBB/wg2pwriKjfrAYMm9mQbqz0/img.png?width=1200&amp;amp;height=600&amp;amp;face=984_118_1045_185')&quot;&gt; 
  &lt;/div&gt;
  &lt;div class=&quot;og-text&quot;&gt;
   &lt;p class=&quot;og-title&quot;&gt;GitHub - ivpusic/react-native-image-crop-picker: iOS/Android image picker with support for camera, video, configurable compressi&lt;/p&gt;
   &lt;p class=&quot;og-desc&quot;&gt;iOS/Android image picker with support for camera, video, configurable compression, multiple images and cropping - GitHub - ivpusic/react-native-image-crop-picker: iOS/Android image picker with supp...&lt;/p&gt;
   &lt;p class=&quot;og-host&quot;&gt;github.com&lt;/p&gt;
  &lt;/div&gt;&lt;/a&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt; &lt;/p&gt;</description>
      <category>React Native</category>
      <author>ruby_s</author>
      <guid isPermaLink="true">https://juyami.tistory.com/99</guid>
      <comments>https://juyami.tistory.com/99#entry99comment</comments>
      <pubDate>Sun, 3 Apr 2022 02:25:51 +0900</pubDate>
    </item>
    <item>
      <title>[오류로그]React-native - yarn ios 실행 시 발생하는 오류 해결</title>
      <link>https://juyami.tistory.com/98</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;나는 MacOS M1칩을 사용중이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번에 React-native로 사진첩에 접근할 필요가 있어서 초기 설정을 하는중에 개발인생 중 가장 많은 오류를 만났다..ㅎ 이래서 앱은 정말 골치아프다&lt;br /&gt;우선 책을 보고 셋팅을 했기 때문에 순서대로 Xcode, cocoapods를 설치했다. (XCode는 앱스토어에서 설치 )&lt;/p&gt;
&lt;pre id=&quot;code_1648262629314&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo gem install -g cocoapods&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설치 완료후 &lt;i&gt;&lt;b&gt;react-native init&lt;/b&gt;&lt;/i&gt;명령어로 프로젝트를 만들고 &lt;b&gt;ios폴더에 &lt;i&gt;cd&lt;/i&gt;&lt;/b&gt;로 들어가&lt;i&gt;&lt;b&gt; yarn ios&lt;/b&gt;&lt;/i&gt;를 실행했더니 .. 아래와 같은 오류를 만났다.&lt;/p&gt;
&lt;pre id=&quot;code_1648262743504&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;export GENERATE_INFOPLIST_FILE\=NO
    export GENERATE_MASTER_OBJECT_FILE\=NO
    export GENERATE_PKGINFO_FILE\=NO
    export GENERATE_PROFILING_CODE\=NO
    export GENERATE_TEXT_BASED_STUBS\=NO
    export GID\=20
    export GROUP\=staff
    export HEADERMAP_INCLUDES_FLAT_ENTRIES_FOR_TARGET_BEING_BUILT\=YES
    export HEADERMAP_INCLUDES_FRAMEWORK_ENTRIES_FOR_ALL_PRODUCT_TYPES\=YES
    export HEADERMAP_INCLUDES_NONPUBLIC_NONPRIVATE_HEADERS\=YES
    export HEADERMAP_INCLUDES_PROJECT_HEADERS\=YES
    export HEADERMAP_USES_FRAMEWORK_PREFIX_ENTRIES\=YES
    export HEADERMAP_USES_VFS\=NO
    export HEADER_SEARCH_PATHS\=/Users/happy/Library/Developer/Xcode/DerivedData/reactProject-delykgxnkgwfzvfpjeouqgcoawyh/Build/Products/Debug-iphonesimulator/FBReactNativeSpec/include\ \ \&quot;/Users/happy/Desktop/reactProject/ios/Pods/Headers/Private\&quot;\ \&quot;/Users/happy/Desktop/reactProject/ios/Pods/Headers/Private/FBReactNativeSpec\&quot;\ \&quot;/Users/happy/Desktop/reactProject/ios/Pods/Headers/Public\&quot;\ \&quot;/Users/happy/Desktop/reactProject/ios/Pods/Headers/Public/DoubleConversion\&quot;\ \&quot;/Users/happy/Desktop/reactProject/ios/Pods/Headers/Public/FBLazyVector\&quot;\ \&quot;/Users/happy/Desktop/reactProject/ios/Pods/Headers/Public/FBReactNativeSpec\&quot;\ \&quot;/Users/happy/Desktop/reactProject/ios/Pods/Headers/Public/RCT-Folly\&quot;\ \&quot;/Users/happy/Desktop/reactProject/ios/Pods/Headers/Public/RCTRequired\&quot;\ \&quot;/Users/happy/Desktop/reactProject/ios/Pods/Headers/Public/RCTTypeSafety\&quot;\ \&quot;/Users/happy/Desktop/reactProject/ios/Pods/Headers/Public/React-Core\&quot;\ \&quot;/Users/happy/Desktop/reactProject/ios/Pods/Headers/Public/React-callinvoker\&quot;\ \&quot;/Users/happy/Desktop/reactProject/ios/Pods/Headers/Public/React-cxxreact\&quot;\ \&quot;/Users/happy/Desktop/reactProject/ios/Pods/Headers/Public/React-jsi\&quot;\ \&quot;/Users/happy/Desktop/reactProject/ios/Pods/Headers/Public/React-jsiexecutor\&quot;\ \&quot;/Users/happy/Desktop/reactProject/ios/Pods/Headers/Public/React-jsinspector\&quot;\ \&quot;/Users/happy/Desktop/reactProject/ios/Pods/Headers/Public/React-logger\&quot;\ \&quot;/Users/happy/Desktop/reactProject/ios/Pods/Headers/Public/React-perflogger\&quot;\ \&quot;/Users/happy/Desktop/reactProject/ios/Pods/Headers/Public/React-runtimeexecutor\&quot;\ \&quot;/Users/happy/Desktop/reactProject/ios/Pods/Headers/Public/ReactCommon\&quot;\ \&quot;/Users/happy/Desktop/reactProject/ios/Pods/Headers/Public/Yoga\&quot;\ \&quot;/Users/happy/Desktop/reactProject/ios/Pods/Headers/Public/fmt\&quot;\ \&quot;/Users/happy/Desktop/reactProject/ios/Pods/Headers/Public/glog\&quot;\ \&quot;/Users/happy/Desktop/reactProject/ios/Pods/../../node_modules/react-native/React/FBReactNativeSpec/React/FBReactNativeSpec\&quot;\ \&quot;/Users/happy/Desktop/reactProject/ios/Pods/RCT-Folly\&quot;
    export HIDE_BITCODE_SYMBOLS\=YES
    export HOME\=/Users/happy
    export ICONV\=/usr/bin/iconv
    export INFOPLIST_EXPAND_BUILD_SETTINGS\=YES
    export INFOPLIST_OUTPUT_FORMAT\=binary
    export INFOPLIST_PREPROCESS\=NO
    export INLINE_PRIVATE_FRAMEWORKS\=NO
    export INSTALLHDRS_COPY_PHASE\=NO
    export INSTALLHDRS_SCRIPT_PHASE\=NO
    export INSTALL_DIR\=/tmp/Pods.dst/usr/local/lib
    export INSTALL_GROUP\=staff
    export INSTALL_MODE_FLAG\=u+w,go-w,a+rX
    export INSTALL_OWNER\=happy
    export INSTALL_PATH\=/usr/local/lib
    export INSTALL_ROOT\=/tmp/Pods.dst
    export IPHONEOS_DEPLOYMENT_TARGET\=11.0
    export JAVAC_DEFAULT_FLAGS\=-J-Xms64m\ -J-XX:NewSize\=4M\ -J-Dfile.encoding\=UTF8
    export JAVA_APP_STUB\=/System/Library/Frameworks/JavaVM.framework/Resources/MacOS/JavaApplicationStub
    export JAVA_ARCHIVE_CLASSES\=YES
    export JAVA_ARCHIVE_TYPE\=JAR
    export JAVA_COMPILER\=/usr/bin/javac
    export JAVA_FRAMEWORK_RESOURCES_DIRS\=Resources
    export JAVA_JAR_FLAGS\=cv
    export JAVA_SOURCE_SUBDIR\=.
    export JAVA_USE_DEPENDENCIES\=YES
    export JAVA_ZIP_FLAGS\=-urg
    export JIKES_DEFAULT_FLAGS\=+E\ +OLDCSO
    export KEEP_PRIVATE_EXTERNS\=NO
    export LD_DEPENDENCY_INFO_FILE\=/Users/happy/Library/Developer/Xcode/DerivedData/reactProject-delykgxnkgwfzvfpjeouqgcoawyh/Build/Intermediates.noindex/Pods.build/Debug-iphonesimulator/FBReactNativeSpec.build/Objects-normal/undefined_arch/FBReactNativeSpec_dependency_info.dat
    export LD_GENERATE_MAP_FILE\=NO
    export LD_MAP_FILE_PATH\=/Users/happy/Library/Developer/Xcode/DerivedData/reactProject-delykgxnkgwfzvfpjeouqgcoawyh/Build/Intermediates.noindex/Pods.build/Debug-iphonesimulator/FBReactNativeSpec.build/FBReactNativeSpec-LinkMap-normal-undefined_arch.txt
    export LD_NO_PIE\=NO
    export LD_QUOTE_LINKER_ARGUMENTS_FOR_COMPILER_DRIVER\=YES
    export LEGACY_DEVELOPER_DIR\=/Applications/Xcode.app/Contents/PlugIns/Xcode3Core.ideplugin/Contents/SharedSupport/Developer
    export LEX\=lex
    export LIBRARY_DEXT_INSTALL_PATH\=/Library/DriverExtensions
    export LIBRARY_FLAG_NOSPACE\=YES
    export LIBRARY_FLAG_PREFIX\=-l
    export LIBRARY_KEXT_INSTALL_PATH\=/Library/Extensions
    export LIBRARY_SEARCH_PATHS\=/Users/happy/Library/Developer/Xcode/DerivedData/reactProject-delykgxnkgwfzvfpjeouqgcoawyh/Build/Products/Debug-iphonesimulator/FBReactNativeSpec\ 
    export LINKER_DISPLAYS_MANGLED_NAMES\=NO
    export LINK_FILE_LIST_normal_x86_64\=/Users/happy/Library/Developer/Xcode/DerivedData/reactProject-delykgxnkgwfzvfpjeouqgcoawyh/Build/Intermediates.noindex/Pods.build/Debug-iphonesimulator/FBReactNativeSpec.build/Objects-normal/x86_64/FBReactNativeSpec.LinkFileList
    export LINK_WITH_STANDARD_LIBRARIES\=YES
    export LLVM_TARGET_TRIPLE_OS_VERSION\=ios11.0
    export LLVM_TARGET_TRIPLE_SUFFIX\=-simulator
    export LLVM_TARGET_TRIPLE_VENDOR\=apple
    export LOCALIZATION_EXPORT_SUPPORTED\=YES
    export LOCALIZED_STRING_MACRO_NAMES\=NSLocalizedString\ CFCopyLocalizedString
    export LOCALIZED_STRING_SWIFTUI_SUPPORT\=YES
    export LOCAL_ADMIN_APPS_DIR\=/Applications/Utilities
    export LOCAL_APPS_DIR\=/Applications
    export LOCAL_DEVELOPER_DIR\=/Library/Developer
    export LOCAL_LIBRARY_DIR\=/Library
    export LOCROOT\=/Users/happy/Desktop/reactProject/ios/Pods
    export LOCSYMROOT\=/Users/happy/Desktop/reactProject/ios/Pods
    export MACH_O_TYPE\=staticlib
    export MAC_OS_X_PRODUCT_BUILD_VERSION\=21E230
    export MAC_OS_X_VERSION_ACTUAL\=120300
    export MAC_OS_X_VERSION_MAJOR\=120000
    export MAC_OS_X_VERSION_MINOR\=120300
    export METAL_LIBRARY_FILE_BASE\=default
    export METAL_LIBRARY_OUTPUT_DIR\=/Users/happy/Library/Developer/Xcode/DerivedData/reactProject-delykgxnkgwfzvfpjeouqgcoawyh/Build/Products/Debug-iphonesimulator/FBReactNativeSpec/
    export MODULE_CACHE_DIR\=/Users/happy/Library/Developer/Xcode/DerivedData/ModuleCache.noindex
    export MTL_ENABLE_DEBUG_INFO\=INCLUDE_SOURCE
    export MTL_FAST_MATH\=YES
    export NATIVE_ARCH\=x86_64
    export NATIVE_ARCH_32_BIT\=i386
    export NATIVE_ARCH_64_BIT\=x86_64
    export NATIVE_ARCH_ACTUAL\=x86_64
    export NO_COMMON\=YES
    export OBJC_ABI_VERSION\=2
    export OBJECT_FILE_DIR\=/Users/happy/Library/Developer/Xcode/DerivedData/reactProject-delykgxnkgwfzvfpjeouqgcoawyh/Build/Intermediates.noindex/Pods.build/Debug-iphonesimulator/FBReactNativeSpec.build/Objects
    export OBJECT_FILE_DIR_normal\=/Users/happy/Library/Developer/Xcode/DerivedData/reactProject-delykgxnkgwfzvfpjeouqgcoawyh/Build/Intermediates.noindex/Pods.build/Debug-iphonesimulator/FBReactNativeSpec.build/Objects-normal
    export OBJROOT\=/Users/happy/Library/Developer/Xcode/DerivedData/reactProject-delykgxnkgwfzvfpjeouqgcoawyh/Build/Intermediates.noindex
    export ONLY_ACTIVE_ARCH\=YES
    export OS\=MACOS
    export OSAC\=/usr/bin/osacompile
    export OTHER_CFLAGS\=\ -fmodule-map-file\=\&quot;/Users/happy/Desktop/reactProject/ios/Pods/Headers/Public/React/React-Core.modulemap\&quot;\ -fmodule-map-file\=\&quot;/Users/happy/Desktop/reactProject/ios/Pods/Headers/Public/yoga/Yoga.modulemap\&quot;
    export OTHER_CPLUSPLUSFLAGS\=\ -fmodule-map-file\=\&quot;/Users/happy/Desktop/reactProject/ios/Pods/Headers/Public/React/React-Core.modulemap\&quot;\ -fmodule-map-file\=\&quot;/Users/happy/Desktop/reactProject/ios/Pods/Headers/Public/yoga/Yoga.modulemap\&quot;
    export PACKAGE_TYPE\=com.apple.package-type.static-library
    export PASCAL_STRINGS\=YES
    export PATH\=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin:/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/local/bin:/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/libexec:/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/usr/bin:/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/usr/local/bin:/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin:/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/usr/local/bin:/Applications/Xcode.app/Contents/Developer/usr/bin:/Applications/Xcode.app/Contents/Developer/usr/local/bin:/var/folders/x4/kwk1qfsj3sndq6fgfc5_83vh0000gn/T/yarn--1648226174070-0.3699977193943793:/Users/happy/Desktop/reactProject/node_modules/.bin:/Users/happy/.config/yarn/link/node_modules/.bin:/usr/local/libexec/lib/node_modules/npm/bin/node-gyp-bin:/usr/local/lib/node_modules/npm/bin/node-gyp-bin:/usr/local/bin/node_modules/npm/bin/node-gyp-bin:/Users/happy/opt/anaconda3/bin:/Users/happy/opt/anaconda3/condabin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Library/Apple/usr/bin:/Users/happy/.rvm/bin:/Users/happy/.yarn/bin
    export PATH_PREFIXES_EXCLUDED_FROM_HEADER_DEPENDENCIES\=/usr/include\ /usr/local/include\ /System/Library/Frameworks\ /System/Library/PrivateFrameworks\ /Applications/Xcode.app/Contents/Developer/Headers\ /Applications/Xcode.app/Contents/Developer/SDKs\ /Applications/Xcode.app/Contents/Developer/Platforms
    export PER_ARCH_OBJECT_FILE_DIR\=/Users/happy/Library/Developer/Xcode/DerivedData/reactProject-delykgxnkgwfzvfpjeouqgcoawyh/Build/Intermediates.noindex/Pods.build/Debug-iphonesimulator/FBReactNativeSpec.build/Objects-normal/undefined_arch
    export PER_VARIANT_OBJECT_FILE_DIR\=/Users/happy/Library/Developer/Xcode/DerivedData/reactProject-delykgxnkgwfzvfpjeouqgcoawyh/Build/Intermediates.noindex/Pods.build/Debug-iphonesimulator/FBReactNativeSpec.build/Objects-normal
    export PKGINFO_FILE_PATH\=/Users/happy/Library/Developer/Xcode/DerivedData/reactProject-delykgxnkgwfzvfpjeouqgcoawyh/Build/Intermediates.noindex/Pods.build/Debug-iphonesimulator/FBReactNativeSpec.build/PkgInfo
    export PLATFORM_DEVELOPER_APPLICATIONS_DIR\=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/Applications
    export PLATFORM_DEVELOPER_BIN_DIR\=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin
    export PLATFORM_DEVELOPER_LIBRARY_DIR\=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/Library
    export PLATFORM_DEVELOPER_SDK_DIR\=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs
    export PLATFORM_DEVELOPER_TOOLS_DIR\=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/Tools
    export PLATFORM_DEVELOPER_USR_DIR\=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/usr
    export PLATFORM_DIR\=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform
    export PLATFORM_DISPLAY_NAME\=iOS\ Simulator
    export PLATFORM_FAMILY_NAME\=iOS
    export PLATFORM_NAME\=iphonesimulator
    export PLATFORM_PREFERRED_ARCH\=x86_64
    export PLATFORM_PRODUCT_BUILD_VERSION\=19E239
    export PLIST_FILE_OUTPUT_FORMAT\=binary
    export PODS_BUILD_DIR\=/Users/happy/Library/Developer/Xcode/DerivedData/reactProject-delykgxnkgwfzvfpjeouqgcoawyh/Build/Products
    export PODS_CONFIGURATION_BUILD_DIR\=/Users/happy/Library/Developer/Xcode/DerivedData/reactProject-delykgxnkgwfzvfpjeouqgcoawyh/Build/Products/Debug-iphonesimulator
    export PODS_ROOT\=/Users/happy/Desktop/reactProject/ios/Pods
    export PODS_TARGET_SRCROOT\=/Users/happy/Desktop/reactProject/ios/Pods/../../node_modules/react-native/React/FBReactNativeSpec
    export PODS_XCFRAMEWORKS_BUILD_DIR\=/Users/happy/Library/Developer/Xcode/DerivedData/reactProject-delykgxnkgwfzvfpjeouqgcoawyh/Build/Products/Debug-iphonesimulator/XCFrameworkIntermediates
    export PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR\=YES
    export PRECOMP_DESTINATION_DIR\=/Users/happy/Library/Developer/Xcode/DerivedData/reactProject-delykgxnkgwfzvfpjeouqgcoawyh/Build/Intermediates.noindex/Pods.build/Debug-iphonesimulator/FBReactNativeSpec.build/PrefixHeaders
    export PRESERVE_DEAD_CODE_INITS_AND_TERMS\=NO
    export PRODUCT_BUNDLE_IDENTIFIER\=org.cocoapods.FBReactNativeSpec
    export PRODUCT_MODULE_NAME\=FBReactNativeSpec
    export PRODUCT_NAME\=FBReactNativeSpec
    export PRODUCT_SETTINGS_PATH\=
    export PRODUCT_TYPE\=com.apple.product-type.library.static
    export PROFILING_CODE\=NO
    export PROJECT\=Pods
    export PROJECT_DERIVED_FILE_DIR\=/Users/happy/Library/Developer/Xcode/DerivedData/reactProject-delykgxnkgwfzvfpjeouqgcoawyh/Build/Intermediates.noindex/Pods.build/DerivedSources
    export PROJECT_DIR\=/Users/happy/Desktop/reactProject/ios/Pods
    export PROJECT_FILE_PATH\=/Users/happy/Desktop/reactProject/ios/Pods/Pods.xcodeproj
    export PROJECT_NAME\=Pods
    export PROJECT_TEMP_DIR\=/Users/happy/Library/Developer/Xcode/DerivedData/reactProject-delykgxnkgwfzvfpjeouqgcoawyh/Build/Intermediates.noindex/Pods.build
    export PROJECT_TEMP_ROOT\=/Users/happy/Library/Developer/Xcode/DerivedData/reactProject-delykgxnkgwfzvfpjeouqgcoawyh/Build/Intermediates.noindex
    export RECURSIVE_SEARCH_PATHS_FOLLOW_SYMLINKS\=YES
    export REMOVE_CVS_FROM_RESOURCES\=YES
    export REMOVE_GIT_FROM_RESOURCES\=YES
    export REMOVE_HEADERS_FROM_EMBEDDED_BUNDLES\=YES
    export REMOVE_HG_FROM_RESOURCES\=YES
    export REMOVE_SVN_FROM_RESOURCES\=YES
    export REZ_COLLECTOR_DIR\=/Users/happy/Library/Developer/Xcode/DerivedData/reactProject-delykgxnkgwfzvfpjeouqgcoawyh/Build/Intermediates.noindex/Pods.build/Debug-iphonesimulator/FBReactNativeSpec.build/ResourceManagerResources
    export REZ_EXECUTABLE\=YES
    export REZ_OBJECTS_DIR\=/Users/happy/Library/Developer/Xcode/DerivedData/reactProject-delykgxnkgwfzvfpjeouqgcoawyh/Build/Intermediates.noindex/Pods.build/Debug-iphonesimulator/FBReactNativeSpec.build/ResourceManagerResources/Objects
    export REZ_SEARCH_PATHS\=/Users/happy/Library/Developer/Xcode/DerivedData/reactProject-delykgxnkgwfzvfpjeouqgcoawyh/Build/Products/Debug-iphonesimulator/FBReactNativeSpec\ 
    export SCAN_ALL_SOURCE_FILES_FOR_INCLUDES\=NO
    export SCRIPT_INPUT_FILE_0\=/Users/happy/Desktop/reactProject/node_modules/react-native/Libraries/ActionSheetIOS/NativeActionSheetManager.js
    export SCRIPT_INPUT_FILE_1\=/Users/happy/Desktop/reactProject/node_modules/react-native/Libraries/Alert/NativeAlertManager.js
    export SCRIPT_INPUT_FILE_10\=/Users/happy/Desktop/reactProject/node_modules/react-native/Libraries/Components/AccessibilityInfo/NativeAccessibilityInfo.js
    export SCRIPT_INPUT_FILE_11\=/Users/happy/Desktop/reactProject/node_modules/react-native/Libraries/Components/AccessibilityInfo/NativeAccessibilityManager.js
    export SCRIPT_INPUT_FILE_12\=/Users/happy/Desktop/reactProject/node_modules/react-native/Libraries/Components/Clipboard/NativeClipboard.js
    export SCRIPT_INPUT_FILE_13\=/Users/happy/Desktop/reactProject/node_modules/react-native/Libraries/Components/DatePickerAndroid/NativeDatePickerAndroid.js
    export SCRIPT_INPUT_FILE_14\=/Users/happy/Desktop/reactProject/node_modules/react-native/Libraries/Components/Keyboard/NativeKeyboardObserver.js
    export SCRIPT_INPUT_FILE_15\=/Users/happy/Desktop/reactProject/node_modules/react-native/Libraries/Components/Sound/NativeSoundManager.js
    export SCRIPT_INPUT_FILE_16\=/Users/happy/Desktop/reactProject/node_modules/react-native/Libraries/Components/StatusBar/NativeStatusBarManagerAndroid.js
    export SCRIPT_INPUT_FILE_17\=/Users/happy/Desktop/reactProject/node_modules/react-native/Libraries/Components/StatusBar/NativeStatusBarManagerIOS.js
    export SCRIPT_INPUT_FILE_18\=/Users/happy/Desktop/reactProject/node_modules/react-native/Libraries/Components/ToastAndroid/NativeToastAndroid.js
    export SCRIPT_INPUT_FILE_19\=/Users/happy/Desktop/reactProject/node_modules/react-native/Libraries/Core/NativeExceptionsManager.js
    export SCRIPT_INPUT_FILE_2\=/Users/happy/Desktop/reactProject/node_modules/react-native/Libraries/Animated/NativeAnimatedHelper.js
    export SCRIPT_INPUT_FILE_20\=/Users/happy/Desktop/reactProject/node_modules/react-native/Libraries/Core/SegmentFetcher/NativeSegmentFetcher.js
    export SCRIPT_INPUT_FILE_21\=/Users/happy/Desktop/reactProject/node_modules/react-native/Libraries/Core/Timers/NativeTiming.js
    export SCRIPT_INPUT_FILE_22\=/Users/happy/Desktop/reactProject/node_modules/react-native/Libraries/EventEmitter/NativeEventEmitter.js
    export SCRIPT_INPUT_FILE_23\=/Users/happy/Desktop/reactProject/node_modules/react-native/Libraries/EventEmitter/__mocks__/NativeEventEmitter.js
    export SCRIPT_INPUT_FILE_24\=/Users/happy/Desktop/reactProject/node_modules/react-native/Libraries/HeapCapture/NativeJSCHeapCapture.js
    export SCRIPT_INPUT_FILE_25\=/Users/happy/Desktop/reactProject/node_modules/react-native/Libraries/Image/NativeImageEditor.js
    export SCRIPT_INPUT_FILE_26\=/Users/happy/Desktop/reactProject/node_modules/react-native/Libraries/Image/NativeImageLoaderAndroid.js
    export SCRIPT_INPUT_FILE_27\=/Users/happy/Desktop/reactProject/node_modules/react-native/Libraries/Image/NativeImageLoaderIOS.js
    export SCRIPT_INPUT_FILE_28\=/Users/happy/Desktop/reactProject/node_modules/react-native/Libraries/Image/NativeImagePickerIOS.js
    export SCRIPT_INPUT_FILE_29\=/Users/happy/Desktop/reactProject/node_modules/react-native/Libraries/Image/NativeImageStoreAndroid.js
    export SCRIPT_INPUT_FILE_3\=/Users/happy/Desktop/reactProject/node_modules/react-native/Libraries/Animated/NativeAnimatedModule.js
    export SCRIPT_INPUT_FILE_30\=/Users/happy/Desktop/reactProject/node_modules/react-native/Libraries/Image/NativeImageStoreIOS.js
    export SCRIPT_INPUT_FILE_31\=/Users/happy/Desktop/reactProject/node_modules/react-native/Libraries/Interaction/NativeFrameRateLogger.js
    export SCRIPT_INPUT_FILE_32\=/Users/happy/Desktop/reactProject/node_modules/react-native/Libraries/Linking/NativeIntentAndroid.js
    export SCRIPT_INPUT_FILE_33\=/Users/happy/Desktop/reactProject/node_modules/react-native/Libraries/Linking/NativeLinkingManager.js
    export SCRIPT_INPUT_FILE_34\=/Users/happy/Desktop/reactProject/node_modules/react-native/Libraries/Modal/NativeModalManager.js
    export SCRIPT_INPUT_FILE_35\=/Users/happy/Desktop/reactProject/node_modules/react-native/Libraries/NativeComponent/NativeComponentRegistry.js
    export SCRIPT_INPUT_FILE_36\=/Users/happy/Desktop/reactProject/node_modules/react-native/Libraries/NativeModules/specs/NativeAnimationsDebugModule.js
    export SCRIPT_INPUT_FILE_37\=/Users/happy/Desktop/reactProject/node_modules/react-native/Libraries/NativeModules/specs/NativeDevMenu.js
    export SCRIPT_INPUT_FILE_38\=/Users/happy/Desktop/reactProject/node_modules/react-native/Libraries/NativeModules/specs/NativeDevSettings.js
    export SCRIPT_INPUT_FILE_39\=/Users/happy/Desktop/reactProject/node_modules/react-native/Libraries/NativeModules/specs/NativeDeviceEventManager.js
    export SCRIPT_INPUT_FILE_4\=/Users/happy/Desktop/reactProject/node_modules/react-native/Libraries/Animated/NativeAnimatedTurboModule.js
    export SCRIPT_INPUT_FILE_40\=/Users/happy/Desktop/reactProject/node_modules/react-native/Libraries/NativeModules/specs/NativeDialogManagerAndroid.js
    export SCRIPT_INPUT_FILE_41\=/Users/happy/Desktop/reactProject/node_modules/react-native/Libraries/NativeModules/specs/NativeLogBox.js
    export SCRIPT_INPUT_FILE_42\=/Users/happy/Desktop/reactProject/node_modules/react-native/Libraries/NativeModules/specs/NativeRedBox.js
    export SCRIPT_INPUT_FILE_43\=/Users/happy/Desktop/reactProject/node_modules/react-native/Libraries/NativeModules/specs/NativeSourceCode.js
    export SCRIPT_INPUT_FILE_44\=/Users/happy/Desktop/reactProject/node_modules/react-native/Libraries/Network/NativeNetworkingAndroid.js
    export SCRIPT_INPUT_FILE_45\=/Users/happy/Desktop/reactProject/node_modules/react-native/Libraries/Network/NativeNetworkingIOS.js
    export SCRIPT_INPUT_FILE_46\=/Users/happy/Desktop/reactProject/node_modules/react-native/Libraries/Performance/NativeJSCSamplingProfiler.js
    export SCRIPT_INPUT_FILE_47\=/Users/happy/Desktop/reactProject/node_modules/react-native/Libraries/PermissionsAndroid/NativePermissionsAndroid.js
    export SCRIPT_INPUT_FILE_48\=/Users/happy/Desktop/reactProject/node_modules/react-native/Libraries/PushNotificationIOS/NativePushNotificationManagerIOS.js
    export SCRIPT_INPUT_FILE_49\=/Users/happy/Desktop/reactProject/node_modules/react-native/Libraries/ReactNative/NativeHeadlessJsTaskSupport.js
    export SCRIPT_INPUT_FILE_5\=/Users/happy/Desktop/reactProject/node_modules/react-native/Libraries/AppState/NativeAppState.js
    export SCRIPT_INPUT_FILE_50\=/Users/happy/Desktop/reactProject/node_modules/react-native/Libraries/ReactNative/NativeI18nManager.js
    export SCRIPT_INPUT_FILE_51\=/Users/happy/Desktop/reactProject/node_modules/react-native/Libraries/ReactNative/NativeUIManager.js
    export SCRIPT_INPUT_FILE_52\=/Users/happy/Desktop/reactProject/node_modules/react-native/Libraries/Settings/NativeSettingsManager.js
    export SCRIPT_INPUT_FILE_53\=/Users/happy/Desktop/reactProject/node_modules/react-native/Libraries/Share/NativeShareModule.js
    export SCRIPT_INPUT_FILE_54\=/Users/happy/Desktop/reactProject/node_modules/react-native/Libraries/Storage/NativeAsyncLocalStorage.js
    export SCRIPT_INPUT_FILE_55\=/Users/happy/Desktop/reactProject/node_modules/react-native/Libraries/Storage/NativeAsyncSQLiteDBStorage.js
    export SCRIPT_INPUT_FILE_56\=/Users/happy/Desktop/reactProject/node_modules/react-native/Libraries/TurboModule/samples/NativeSampleTurboModule.js
    export SCRIPT_INPUT_FILE_57\=/Users/happy/Desktop/reactProject/node_modules/react-native/Libraries/Utilities/NativeAppearance.js
    export SCRIPT_INPUT_FILE_58\=/Users/happy/Desktop/reactProject/node_modules/react-native/Libraries/Utilities/NativeDevLoadingView.js
    export SCRIPT_INPUT_FILE_59\=/Users/happy/Desktop/reactProject/node_modules/react-native/Libraries/Utilities/NativeDevSplitBundleLoader.js
    export SCRIPT_INPUT_FILE_6\=/Users/happy/Desktop/reactProject/node_modules/react-native/Libraries/BatchedBridge/NativeModules.js
    export SCRIPT_INPUT_FILE_60\=/Users/happy/Desktop/reactProject/node_modules/react-native/Libraries/Utilities/NativeDeviceInfo.js
    export SCRIPT_INPUT_FILE_61\=/Users/happy/Desktop/reactProject/node_modules/react-native/Libraries/Utilities/NativeJSDevSupport.js
    export SCRIPT_INPUT_FILE_62\=/Users/happy/Desktop/reactProject/node_modules/react-native/Libraries/Utilities/NativePlatformConstantsAndroid.js
    export SCRIPT_INPUT_FILE_63\=/Users/happy/Desktop/reactProject/node_modules/react-native/Libraries/Utilities/NativePlatformConstantsIOS.js
    export SCRIPT_INPUT_FILE_64\=/Users/happy/Desktop/reactProject/node_modules/react-native/Libraries/Vibration/NativeVibration.js
    export SCRIPT_INPUT_FILE_65\=/Users/happy/Desktop/reactProject/node_modules/react-native/Libraries/WebSocket/NativeWebSocketModule.js
    export SCRIPT_INPUT_FILE_7\=/Users/happy/Desktop/reactProject/node_modules/react-native/Libraries/Blob/NativeBlobModule.js
    export SCRIPT_INPUT_FILE_8\=/Users/happy/Desktop/reactProject/node_modules/react-native/Libraries/Blob/NativeFileReaderModule.js
    export SCRIPT_INPUT_FILE_9\=/Users/happy/Desktop/reactProject/node_modules/react-native/Libraries/BugReporting/NativeBugReporting.js
    export SCRIPT_INPUT_FILE_COUNT\=66
    export SCRIPT_INPUT_FILE_LIST_COUNT\=0
    export SCRIPT_OUTPUT_FILE_0\=/Users/happy/Library/Developer/Xcode/DerivedData/reactProject-delykgxnkgwfzvfpjeouqgcoawyh/Build/Intermediates.noindex/Pods.build/Debug-iphonesimulator/FBReactNativeSpec.build/DerivedSources/codegen-FBReactNativeSpec.log
    export SCRIPT_OUTPUT_FILE_1\=/Users/happy/Desktop/reactProject/ios/Pods/\ /Users/happy/Desktop/reactProject/node_modules/react-native/React/FBReactNativeSpec/FBReactNativeSpec/FBReactNativeSpec.h
    export SCRIPT_OUTPUT_FILE_2\=/Users/happy/Desktop/reactProject/ios/Pods/\ /Users/happy/Desktop/reactProject/node_modules/react-native/React/FBReactNativeSpec/FBReactNativeSpec/FBReactNativeSpec-generated.mm
    export SCRIPT_OUTPUT_FILE_COUNT\=3
    export SCRIPT_OUTPUT_FILE_LIST_COUNT\=0
    export SDKROOT\=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator15.4.sdk
    export SDK_DIR\=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator15.4.sdk
    export SDK_DIR_iphonesimulator\=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator15.4.sdk
    export SDK_DIR_iphonesimulator15_4\=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator15.4.sdk
    export SDK_NAME\=iphonesimulator15.4
    export SDK_NAMES\=iphonesimulator15.4
    export SDK_PRODUCT_BUILD_VERSION\=19E239
    export SDK_VERSION\=15.4
    export SDK_VERSION_ACTUAL\=150400
    export SDK_VERSION_MAJOR\=150000
    export SDK_VERSION_MINOR\=150400
    export SED\=/usr/bin/sed
    export SEPARATE_STRIP\=NO
    export SEPARATE_SYMBOL_EDIT\=NO
    export SET_DIR_MODE_OWNER_GROUP\=YES
    export SET_FILE_MODE_OWNER_GROUP\=NO
    export SHALLOW_BUNDLE\=NO
    export SHARED_DERIVED_FILE_DIR\=/Users/happy/Library/Developer/Xcode/DerivedData/reactProject-delykgxnkgwfzvfpjeouqgcoawyh/Build/Products/Debug-iphonesimulator/FBReactNativeSpec/DerivedSources
    export SHARED_PRECOMPS_DIR\=/Users/happy/Library/Developer/Xcode/DerivedData/reactProject-delykgxnkgwfzvfpjeouqgcoawyh/Build/Intermediates.noindex/PrecompiledHeaders
    export SKIP_INSTALL\=YES
    export SOURCE_ROOT\=/Users/happy/Desktop/reactProject/ios/Pods
    export SRCROOT\=/Users/happy/Desktop/reactProject/ios/Pods
    export STRINGSDATA_DIR\=/Users/happy/Library/Developer/Xcode/DerivedData/reactProject-delykgxnkgwfzvfpjeouqgcoawyh/Build/Intermediates.noindex/Pods.build/Debug-iphonesimulator/FBReactNativeSpec.build/Objects-normal/undefined_arch
    export STRINGSDATA_ROOT\=/Users/happy/Library/Developer/Xcode/DerivedData/reactProject-delykgxnkgwfzvfpjeouqgcoawyh/Build/Intermediates.noindex/Pods.build/Debug-iphonesimulator/FBReactNativeSpec.build
    export STRINGS_FILE_INFOPLIST_RENAME\=YES
    export STRINGS_FILE_OUTPUT_ENCODING\=binary
    export STRIP_BITCODE_FROM_COPIED_FILES\=NO
    export STRIP_INSTALLED_PRODUCT\=NO
    export STRIP_STYLE\=debugging
    export STRIP_SWIFT_SYMBOLS\=YES
    export SUPPORTED_DEVICE_FAMILIES\=1,2
    export SUPPORTED_PLATFORMS\=iphoneos\ iphonesimulator
    export SUPPORTS_TEXT_BASED_API\=NO
    export SWIFT_ACTIVE_COMPILATION_CONDITIONS\=DEBUG\ 
    export SWIFT_EMIT_LOC_STRINGS\=NO
    export SWIFT_OPTIMIZATION_LEVEL\=-Onone
    export SWIFT_PLATFORM_TARGET_PREFIX\=ios
    export SWIFT_RESPONSE_FILE_PATH_normal_x86_64\=/Users/happy/Library/Developer/Xcode/DerivedData/reactProject-delykgxnkgwfzvfpjeouqgcoawyh/Build/Intermediates.noindex/Pods.build/Debug-iphonesimulator/FBReactNativeSpec.build/Objects-normal/x86_64/FBReactNativeSpec.SwiftFileList
    export SWIFT_VERSION\=5.0
    export SYMROOT\=/Users/happy/Library/Developer/Xcode/DerivedData/reactProject-delykgxnkgwfzvfpjeouqgcoawyh/Build/Products
    export SYSTEM_ADMIN_APPS_DIR\=/Applications/Utilities
    export SYSTEM_APPS_DIR\=/Applications
    export SYSTEM_CORE_SERVICES_DIR\=/System/Library/CoreServices
    export SYSTEM_DEMOS_DIR\=/Applications/Extras
    export SYSTEM_DEVELOPER_APPS_DIR\=/Applications/Xcode.app/Contents/Developer/Applications
    export SYSTEM_DEVELOPER_BIN_DIR\=/Applications/Xcode.app/Contents/Developer/usr/bin
    export SYSTEM_DEVELOPER_DEMOS_DIR\=/Applications/Xcode.app/Contents/Developer/Applications/Utilities/Built\ Examples
    export SYSTEM_DEVELOPER_DIR\=/Applications/Xcode.app/Contents/Developer
    export SYSTEM_DEVELOPER_DOC_DIR\=/Applications/Xcode.app/Contents/Developer/ADC\ Reference\ Library
    export SYSTEM_DEVELOPER_GRAPHICS_TOOLS_DIR\=/Applications/Xcode.app/Contents/Developer/Applications/Graphics\ Tools
    export SYSTEM_DEVELOPER_JAVA_TOOLS_DIR\=/Applications/Xcode.app/Contents/Developer/Applications/Java\ Tools
    export SYSTEM_DEVELOPER_PERFORMANCE_TOOLS_DIR\=/Applications/Xcode.app/Contents/Developer/Applications/Performance\ Tools
    export SYSTEM_DEVELOPER_RELEASENOTES_DIR\=/Applications/Xcode.app/Contents/Developer/ADC\ Reference\ Library/releasenotes
    export SYSTEM_DEVELOPER_TOOLS\=/Applications/Xcode.app/Contents/Developer/Tools
    export SYSTEM_DEVELOPER_TOOLS_DOC_DIR\=/Applications/Xcode.app/Contents/Developer/ADC\ Reference\ Library/documentation/DeveloperTools
    export SYSTEM_DEVELOPER_TOOLS_RELEASENOTES_DIR\=/Applications/Xcode.app/Contents/Developer/ADC\ Reference\ Library/releasenotes/DeveloperTools
    export SYSTEM_DEVELOPER_USR_DIR\=/Applications/Xcode.app/Contents/Developer/usr
    export SYSTEM_DEVELOPER_UTILITIES_DIR\=/Applications/Xcode.app/Contents/Developer/Applications/Utilities
    export SYSTEM_DEXT_INSTALL_PATH\=/System/Library/DriverExtensions
    export SYSTEM_DOCUMENTATION_DIR\=/Library/Documentation
    export SYSTEM_KEXT_INSTALL_PATH\=/System/Library/Extensions
    export SYSTEM_LIBRARY_DIR\=/System/Library
    export TAPI_ENABLE_PROJECT_HEADERS\=NO
    export TAPI_VERIFY_MODE\=ErrorsOnly
    export TARGETED_DEVICE_FAMILY\=1,2
    export TARGETNAME\=FBReactNativeSpec
    export TARGET_BUILD_DIR\=/Users/happy/Library/Developer/Xcode/DerivedData/reactProject-delykgxnkgwfzvfpjeouqgcoawyh/Build/Products/Debug-iphonesimulator/FBReactNativeSpec
    export TARGET_DEVICE_IDENTIFIER\=3149D368-C4AE-4C76-89F8-3FB0493C196F
    export TARGET_DEVICE_MODEL\=iPhone14,5
    export TARGET_DEVICE_OS_VERSION\=15.4
    export TARGET_DEVICE_PLATFORM_NAME\=iphonesimulator
    export TARGET_NAME\=FBReactNativeSpec
    export TARGET_TEMP_DIR\=/Users/happy/Library/Developer/Xcode/DerivedData/reactProject-delykgxnkgwfzvfpjeouqgcoawyh/Build/Intermediates.noindex/Pods.build/Debug-iphonesimulator/FBReactNativeSpec.build
    export TEMP_DIR\=/Users/happy/Library/Developer/Xcode/DerivedData/reactProject-delykgxnkgwfzvfpjeouqgcoawyh/Build/Intermediates.noindex/Pods.build/Debug-iphonesimulator/FBReactNativeSpec.build
    export TEMP_FILES_DIR\=/Users/happy/Library/Developer/Xcode/DerivedData/reactProject-delykgxnkgwfzvfpjeouqgcoawyh/Build/Intermediates.noindex/Pods.build/Debug-iphonesimulator/FBReactNativeSpec.build
    export TEMP_FILE_DIR\=/Users/happy/Library/Developer/Xcode/DerivedData/reactProject-delykgxnkgwfzvfpjeouqgcoawyh/Build/Intermediates.noindex/Pods.build/Debug-iphonesimulator/FBReactNativeSpec.build
    export TEMP_ROOT\=/Users/happy/Library/Developer/Xcode/DerivedData/reactProject-delykgxnkgwfzvfpjeouqgcoawyh/Build/Intermediates.noindex
    export TEST_FRAMEWORK_SEARCH_PATHS\=\ /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/Library/Frameworks\ /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator15.4.sdk/Developer/Library/Frameworks
    export TEST_LIBRARY_SEARCH_PATHS\=\ /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/usr/lib
    export TOOLCHAINS\=com.apple.dt.toolchain.XcodeDefault
    export TOOLCHAIN_DIR\=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain
    export TREAT_MISSING_BASELINES_AS_TEST_FAILURES\=NO
    export UID\=501
    export UNSTRIPPED_PRODUCT\=NO
    export USER\=happy
    export USER_APPS_DIR\=/Users/happy/Applications
    export USER_LIBRARY_DIR\=/Users/happy/Library
    export USE_DYNAMIC_NO_PIC\=YES
    export USE_HEADERMAP\=YES
    export USE_HEADER_SYMLINKS\=NO
    export USE_LLVM_TARGET_TRIPLES\=YES
    export USE_LLVM_TARGET_TRIPLES_FOR_CLANG\=YES
    export USE_LLVM_TARGET_TRIPLES_FOR_LD\=YES
    export USE_LLVM_TARGET_TRIPLES_FOR_TAPI\=YES
    export USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES\=YES
    export VALIDATE_DEVELOPMENT_ASSET_PATHS\=YES_ERROR
    export VALIDATE_PRODUCT\=NO
    export VALIDATE_WORKSPACE\=YES_ERROR
    export VALID_ARCHS\=arm64\ arm64e\ i386\ x86_64
    export VERBOSE_PBXCP\=NO
    export VERSION_INFO_BUILDER\=happy
    export VERSION_INFO_FILE\=FBReactNativeSpec_vers.c
    export VERSION_INFO_STRING\=\&quot;@\(\#\)PROGRAM:FBReactNativeSpec\ \ PROJECT:Pods-\&quot;
    export WRAP_ASSET_PACKS_IN_SEPARATE_DIRECTORIES\=NO
    export XCODE_APP_SUPPORT_DIR\=/Applications/Xcode.app/Contents/Developer/Library/Xcode
    export XCODE_PRODUCT_BUILD_VERSION\=13E113
    export XCODE_VERSION_ACTUAL\=1330
    export XCODE_VERSION_MAJOR\=1300
    export XCODE_VERSION_MINOR\=1330
    export XPCSERVICES_FOLDER_PATH\=/XPCServices
    export YACC\=yacc
    export arch\=undefined_arch
    export variant\=normal
    /bin/sh -c /Users/happy/Library/Developer/Xcode/DerivedData/reactProject-delykgxnkgwfzvfpjeouqgcoawyh/Build/Intermediates.noindex/Pods.build/Debug-iphonesimulator/FBReactNativeSpec.build/Script-5F4C70EF7D90A5A5BDAEB404279F232A.sh
N/A: version &quot;default -&amp;gt; N/A&quot; is not yet installed.

You need to run &quot;nvm install default&quot; to install it before using it.
Command PhaseScriptExecution failed with a nonzero exit code


2022-03-26 01:47:02.744 xcodebuild[41720:229409] Requested but did not find extension point with identifier Xcode.IDEKit.ExtensionSentinelHostApplications for extension Xcode.DebuggerFoundation.AppExtensionHosts.watchOS of plug-in com.apple.dt.IDEWatchSupportCore
2022-03-26 01:47:02.744 xcodebuild[41720:229409] Requested but did not find extension point with identifier Xcode.IDEKit.ExtensionPointIdentifierToBundleIdentifier for extension Xcode.DebuggerFoundation.AppExtensionToBundleIdentifierMap.watchOS of plug-in com.apple.dt.IDEWatchSupportCore
** BUILD FAILED **


The following build commands failed:
        PhaseScriptExecution [CP-User]\ Generate\ Specs /Users/happy/Library/Developer/Xcode/DerivedData/reactProject-delykgxnkgwfzvfpjeouqgcoawyh/Build/Intermediates.noindex/Pods.build/Debug-iphonesimulator/FBReactNativeSpec.build/Script-5F4C70EF7D90A5A5BDAEB404279F232A.sh (in target 'FBReactNativeSpec' from project 'Pods')
(1 failure)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쭉 잘 실행되다가 마지막쯤에 보면 &lt;i&gt;PhaseScriptExecution&lt;/i&gt; 이런 에러가 보인다&lt;br /&gt;그 위에 보면 nvm install default를 하라고 돼있길래 했더니 또 다음과 같은 오류가 발생했다.&lt;/p&gt;
&lt;pre id=&quot;code_1648262841155&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Version 'default' not found - try `nvm ls-remote` to browse available versions.&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;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;$ &lt;b&gt;nvm install node&lt;/b&gt;&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;$ &lt;b&gt;node --version&lt;/b&gt;&lt;br /&gt;$ v17.8.0&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;$ &lt;b&gt;which node&lt;/b&gt;&lt;br /&gt;$ /Users/happy/.nvm/versions/node/v17.8.0/bin/node&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;$ &lt;b&gt;nvm ls-remote&lt;/b&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;br /&gt;결과: 아래처럼 설치할 수 있는 버전들이 쭉 출력된다.&lt;/p&gt;
&lt;pre id=&quot;code_1648262971311&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;v0.1.14
        v0.1.15
        v0.1.16
        v0.1.17
        v0.1.18
        v0.1.19
        v0.1.20
        v0.1.21
        v0.1.22
        v0.1.23
        v0.1.24
        v0.1.25
        v0.1.26
        v0.1.27
        v0.1.28
        v0.1.29
        v0.1.30
        v0.1.31
        v0.1.32
        v0.1.33
        v0.1.90
        v0.1.91
        v0.1.92
        v0.1.93
        v0.1.94
        v0.1.95
        v0.1.96
        v0.1.97
        v0.1.98
        v0.1.99
       v0.1.100
       v0.1.101
       v0.1.102
       v0.1.103
       v0.1.104
         v0.2.0
         v0.2.1
         v0.2.2
         v0.2.3
         v0.2.4
         v0.2.5
         v0.2.6
         v0.3.0
         v0.3.1
         v0.3.2
         v0.3.3
         v0.3.4
         v0.3.5
         v0.3.6
         v0.3.7
         v0.3.8
         v0.4.0
         v0.4.1
         v0.4.2
         v0.4.3
         v0.4.4
         v0.4.5
         v0.4.6
         v0.4.7
         v0.4.8
         v0.4.9
        v0.4.10
        v0.4.11
        v0.4.12
         v0.5.0
         v0.5.1
         v0.5.2
         v0.5.3
         v0.5.4
         v0.5.5
         v0.5.6
         v0.5.7
         v0.5.8
         v0.5.9
        v0.5.10
         v0.6.0
         v0.6.1
         v0.6.2
         v0.6.3
         v0.6.4
         v0.6.5
         v0.6.6
         v0.6.7
         v0.6.8
         v0.6.9
        v0.6.10
        v0.6.11
        v0.6.12
        v0.6.13
        v0.6.14
        v0.6.15
        v0.6.16
        v0.6.17
        v0.6.18
        v0.6.19
        v0.6.20
        v0.6.21
         v0.7.0
         v0.7.1
         v0.7.2
         v0.7.3
         v0.7.4
         v0.7.5
         v0.7.6
         v0.7.7
         v0.7.8
         v0.7.9
         ...
         
         v17.7.2
-&amp;gt;       v17.8.0&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;$ nvm install v4&lt;/blockquote&gt;
&lt;pre id=&quot;code_1648263006760&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Downloading and installing node v4.9.1...
Downloading https://nodejs.org/dist/v4.9.1/node-v4.9.1-darwin-x64.tar.xz...
#################################################### 100.0%
Computing checksum with sha256sum
Checksums matched!
Now using node v4.9.1 (npm v2.15.11)&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;$ nvm alias default system&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #3d3d3f;&quot;&gt;alias 옵션으로 기본 노드 버전을 변경한다. 이미 OS에 설치해 놓은 system 버전을 기본(default)으로 변경해 보자.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1648263027898&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;default -&amp;gt; system&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;$ nvm use v17.8.0&lt;/blockquote&gt;
&lt;pre id=&quot;code_1648263063249&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Now using node v17.8.0 (npm v8.5.5)&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;$ yarn ios&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;성공 ..! 결국 노드 버전 차이 였던 거.. &lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-03-26 오전 11.51.24.png&quot; data-origin-width=&quot;944&quot; data-origin-height=&quot;1848&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ba64PS/btrxid8J2NU/FyhkYn6CiP4RKjvDiy0zA1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ba64PS/btrxid8J2NU/FyhkYn6CiP4RKjvDiy0zA1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ba64PS/btrxid8J2NU/FyhkYn6CiP4RKjvDiy0zA1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fba64PS%2Fbtrxid8J2NU%2FFyhkYn6CiP4RKjvDiy0zA1%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;459&quot; height=&quot;898&quot; data-filename=&quot;스크린샷 2022-03-26 오전 11.51.24.png&quot; data-origin-width=&quot;944&quot; data-origin-height=&quot;1848&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;참고&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://jeonghwan-kim.github.io/2016/08/10/nvm.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://jeonghwan-kim.github.io/2016/08/10/nvm.html&lt;/a&gt;&lt;/p&gt;</description>
      <author>ruby_s</author>
      <guid isPermaLink="true">https://juyami.tistory.com/98</guid>
      <comments>https://juyami.tistory.com/98#entry98comment</comments>
      <pubDate>Sat, 26 Mar 2022 11:57:33 +0900</pubDate>
    </item>
    <item>
      <title>[오류로그]npm install -global로 설치 시 command not found 해결법</title>
      <link>https://juyami.tistory.com/97</link>
      <description>&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;나는 &lt;b&gt;macOS M1&lt;/b&gt;을 사용중이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;터미널에서&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1648216178226&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;npm install -global yarn&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;명령어로 &lt;b&gt;yarn&lt;/b&gt;을 설치 했다. 터미널에서 &lt;b&gt;yarn -v&lt;/b&gt; 로 버전을 확인해보면 올바르게 출력되었다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-03-25 오후 10.50.17.png&quot; data-origin-width=&quot;526&quot; data-origin-height=&quot;54&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b8wVC6/btrxkfY3iNe/BRZc8PNOXkkusuv0YEuDK1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b8wVC6/btrxkfY3iNe/BRZc8PNOXkkusuv0YEuDK1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b8wVC6/btrxkfY3iNe/BRZc8PNOXkkusuv0YEuDK1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb8wVC6%2FbtrxkfY3iNe%2FBRZc8PNOXkkusuv0YEuDK1%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;526&quot; height=&quot;54&quot; data-filename=&quot;스크린샷 2022-03-25 오후 10.50.17.png&quot; data-origin-width=&quot;526&quot; data-origin-height=&quot;54&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;하지만 VSCode터미널에서는 계속해서 다음과 같은 오류가 발생했다.. &lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1648216262738&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;zsh: command not found: yarn&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;오류를 해결하려는 순서대로 적겠다.(해결 X는 저 방법으로 해결되지 않은것.)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;1. 해결X&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1648216342731&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;brew uninstall yarn
npm uninstall yarn
npm install -global yarn&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;2. 해결X&lt;br /&gt;&lt;i&gt;&lt;span style=&quot;background-color: #ffffff; color: #232629;&quot;&gt;You should add&lt;/span&gt;&lt;/i&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1648216439107&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;export PATH=&quot;$PATH:$(yarn global bin)&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;i&gt;&lt;span style=&quot;background-color: #ffffff; color: #232629;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #232629;&quot;&gt;to your&amp;nbsp;&lt;/span&gt;~/.bash_profile&lt;/i&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;3. 해결O&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;a href=&quot;https://realapril.tistory.com/27&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://realapril.tistory.com/27&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1648216524922&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;npm설치한 프로그램이 뭘해도 command not found가 뜰때&quot; data-og-description=&quot;mac, 리눅스 공통 npm global 설치한후 실행시 계속 command not found 가 뜰때 보통 경로문제다. 하지만 .bash 파일을 수정하다 잘돌아가던것까지 박살나기 쉽다. 우회하자. 터미널에서 경로 세팅을 다시&quot; data-og-host=&quot;realapril.tistory.com&quot; data-og-source-url=&quot;https://realapril.tistory.com/27&quot; data-og-url=&quot;https://realapril.tistory.com/27&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/ca2NFa/hyNOygYpoa/JfjvfYlWo0lj00WCXvykUK/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/jjxXy/hyNOuljOhI/5T87IBNoV7PgoZKZS4Uje1/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800&quot;&gt;&lt;a href=&quot;https://realapril.tistory.com/27&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://realapril.tistory.com/27&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/ca2NFa/hyNOygYpoa/JfjvfYlWo0lj00WCXvykUK/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/jjxXy/hyNOuljOhI/5T87IBNoV7PgoZKZS4Uje1/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800');&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;npm설치한 프로그램이 뭘해도 command not found가 뜰때&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;mac, 리눅스 공통 npm global 설치한후 실행시 계속 command not found 가 뜰때 보통 경로문제다. 하지만 .bash 파일을 수정하다 잘돌아가던것까지 박살나기 쉽다. 우회하자. 터미널에서 경로 세팅을 다시&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;realapril.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;위와 같이 경로 설정 문제였다.. 대신 아래 명령어처럼 경로를 설정해줬다면&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1648216579272&quot; class=&quot;shell&quot; data-ke-language=&quot;shell&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;npm config set prefix /usr/local&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;npm 으로 설치할 때 sudo npm install로 설치를 해야한다. 로컬 파일이 숨김파일이기 때문인 것 같다.&lt;/span&gt;&lt;/p&gt;</description>
      <author>ruby_s</author>
      <guid isPermaLink="true">https://juyami.tistory.com/97</guid>
      <comments>https://juyami.tistory.com/97#entry97comment</comments>
      <pubDate>Fri, 25 Mar 2022 22:57:15 +0900</pubDate>
    </item>
    <item>
      <title>[백준] 퇴사 - silver3 | node.js | 다이나믹 프로그래밍 | 브루트포스</title>
      <link>https://juyami.tistory.com/95</link>
      <description>&lt;div&gt;
&lt;div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;문제 &lt;/b&gt;(&lt;a href=&quot;https://www.acmicpc.net/problem/14501&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://www.acmicpc.net/problem/14501&lt;/a&gt;)&lt;/h2&gt;
&lt;/div&gt;
&lt;div id=&quot;problem_description&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상담원으로 일하고 있는 백준이는 퇴사를 하려고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오늘부터 N+1일째 되는 날 퇴사를 하기 위해서, 남은 N일 동안 최대한 많은 상담을 하려고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;백준이는 비서에게 최대한 많은 상담을 잡으라고 부탁을 했고, 비서는 하루에 하나씩 서로 다른 사람의 상담을 잡아놓았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각각의 상담은 상담을 완료하는데 걸리는 기간 Ti와 상담을 했을 때 받을 수 있는 금액 Pi로 이루어져 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;N = 7인 경우에 다음과 같은 상담 일정표를 보자.&lt;/p&gt;
&lt;br /&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style3&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 5.69767%;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 12.3256%;&quot;&gt;&lt;b&gt;1일&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 13.0233%;&quot;&gt;&lt;b&gt;2일&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 13.1395%;&quot;&gt;&lt;b&gt;3일&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 13.2558%;&quot;&gt;&lt;b&gt;4일&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 14.4186%;&quot;&gt;&lt;b&gt;&amp;nbsp;5일&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 13.1395%;&quot;&gt;&lt;b&gt;6일&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 14.8837%;&quot;&gt;&lt;b&gt;7일&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 5.69767%;&quot;&gt;&lt;b&gt;Ti&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 12.3256%;&quot;&gt;3&lt;/td&gt;
&lt;td style=&quot;width: 13.0233%;&quot;&gt;5&lt;/td&gt;
&lt;td style=&quot;width: 13.1395%;&quot;&gt;1&lt;/td&gt;
&lt;td style=&quot;width: 13.2558%;&quot;&gt;1&lt;/td&gt;
&lt;td style=&quot;width: 14.4186%;&quot;&gt;2&lt;/td&gt;
&lt;td style=&quot;width: 13.1395%;&quot;&gt;4&lt;/td&gt;
&lt;td style=&quot;width: 14.8837%;&quot;&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 5.69767%;&quot;&gt;&lt;b&gt;Pi&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 12.3256%;&quot;&gt;10&lt;/td&gt;
&lt;td style=&quot;width: 13.0233%;&quot;&gt;20&lt;/td&gt;
&lt;td style=&quot;width: 13.1395%;&quot;&gt;10&lt;/td&gt;
&lt;td style=&quot;width: 13.2558%;&quot;&gt;20&lt;/td&gt;
&lt;td style=&quot;width: 14.4186%;&quot;&gt;15&lt;/td&gt;
&lt;td style=&quot;width: 13.1395%;&quot;&gt;40&lt;/td&gt;
&lt;td style=&quot;width: 14.8837%;&quot;&gt;200&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1일에 잡혀있는 상담은 총 3일이 걸리며, 상담했을 때 받을 수 있는 금액은 10이다. 5일에 잡혀있는 상담은 총 2일이 걸리며, 받을 수 있는 금액은 15이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상담을 하는데 필요한 기간은 1일보다 클 수 있기 때문에, 모든 상담을 할 수는 없다. 예를 들어서 1일에 상담을 하게 되면, 2일, 3일에 있는 상담은 할 수 없게 된다. 2일에 있는 상담을 하게 되면, 3, 4, 5, 6일에 잡혀있는 상담은 할 수 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한, N+1일째에는 회사에&amp;nbsp;없기 때문에, 6, 7일에 있는 상담을 할 수 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;퇴사 전에 할 수 있는 상담의 최대 이익은 1일, 4일, 5일에 있는 상담을 하는 것이며, 이때의 이익은 10+20+15=45이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상담을 적절히 했을 때, 백준이가 얻을 수 있는 최대 수익을 구하는 프로그램을 작성하시오.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;입력&lt;/b&gt;&lt;/h2&gt;
&lt;/div&gt;
&lt;div id=&quot;problem_input&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫째 줄에 N (1 &amp;le; N &amp;le; 15)이 주어진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;둘째 줄부터 N개의 줄에 Ti와 Pi가 공백으로 구분되어서 주어지며, 1일부터 N일까지 순서대로 주어진다. (1 &amp;le; Ti&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;le; 5, 1 &amp;le; Pi&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;le;&amp;nbsp;1,000)&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;출력&lt;/b&gt;&lt;/h2&gt;
&lt;/div&gt;
&lt;div id=&quot;problem_output&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫째 줄에 백준이가 얻을 수 있는 최대 이익을 출력한다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;예제 입력 1&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;/div&gt;
&lt;pre id=&quot;sample-input-1&quot; class=&quot;basic&quot;&gt;&lt;code&gt;7
3 10
5 20
1 10
1 20
2 15
4 40
2 200
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;예제 출력 1&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;/div&gt;
&lt;pre id=&quot;sample-output-1&quot; class=&quot;angelscript&quot;&gt;&lt;code&gt;45
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;예제 입력 2&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;/div&gt;
&lt;pre id=&quot;sample-input-2&quot; class=&quot;basic&quot;&gt;&lt;code&gt;10
1 1
1 2
1 3
1 4
1 5
1 6
1 7
1 8
1 9
1 10
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;예제 출력 2&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;/div&gt;
&lt;pre id=&quot;sample-output-2&quot; class=&quot;angelscript&quot;&gt;&lt;code&gt;55
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;예제 입력 3&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;/div&gt;
&lt;pre id=&quot;sample-input-3&quot; class=&quot;basic&quot;&gt;&lt;code&gt;10
5 10
5 9
5 8
5 7
5 6
5 10
5 9
5 8
5 7
5 6
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;예제 출력 3&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;/div&gt;
&lt;pre id=&quot;sample-output-3&quot; class=&quot;angelscript&quot;&gt;&lt;code&gt;20
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;예제 입력 4&lt;/b&gt;&lt;/h2&gt;
&lt;/div&gt;
&lt;pre id=&quot;sample-input-4&quot; class=&quot;basic&quot;&gt;&lt;code&gt;10
5 50
4 40
3 30
2 20
1 10
1 10
2 20
3 30
4 40
5 50
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;예제 출력 4&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;/div&gt;
&lt;pre id=&quot;sample-output-4&quot; class=&quot;angelscript&quot;&gt;&lt;code&gt;90&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;내가 푼 풀이&lt;/b&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1647784887748&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function solve(){
    const dp = Array.from({ length: N+1 },() =&amp;gt; 0);
    let max = 0;
    for(let i = 0; i &amp;lt; N; i++){
        const [t, p] = consult[i];
        max = Math.max(max, dp[i]);

        if(i + t &amp;lt;= N){
            dp[i+t] = Math.max(dp[i+t], max + p);
        }
    }
    return Math.max(...dp);
}

const filePath = process.platform === 'linux'? '/dev/stdin' : '백준/silver/14501/testcase.txt';
const input = require('fs').readFileSync(filePath).toString().trim().split('\n');
const N = +input[0];
const consult = input.slice(1).map((date)=&amp;gt; date.split(' ').map(Number));
console.log(solve());&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;현재 날짜&amp;nbsp;&lt;b&gt;i&lt;/b&gt;에서 걸리는 시간인 &lt;b&gt;t&lt;/b&gt;만큼 간 곳에 최댓값을 반영해주는 방식으로 풀었다.&lt;br /&gt;&lt;b&gt;기존에 저장되어 있던 값&lt;/b&gt;(dp[i+t])과 &lt;b&gt;현재의 최대값 + 현재의 이득 값&lt;/b&gt;(max + p)을 비교하여 최댓값으로 반영해준다.&lt;/p&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #c678dd;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;i&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #56b6c2;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #e5c07b;&quot;&gt;t&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #56b6c2;&quot;&gt;&amp;lt;=&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #e5c07b;&quot;&gt;N&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;)&lt;span style=&quot;color: #000000;&quot;&gt; : 현재 날짜(i)에서 t만큼 갔을때 퇴사 기간이 넘으면 판단하지 않음&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>백준</category>
      <category>DP</category>
      <category>JavaScript</category>
      <category>js</category>
      <category>Node.js</category>
      <category>백준</category>
      <category>브루트포스</category>
      <category>자바스크립트</category>
      <category>퇴사</category>
      <author>ruby_s</author>
      <guid isPermaLink="true">https://juyami.tistory.com/95</guid>
      <comments>https://juyami.tistory.com/95#entry95comment</comments>
      <pubDate>Sun, 20 Mar 2022 23:09:12 +0900</pubDate>
    </item>
    <item>
      <title>[프로그래머스]입국심사 - 자바스크립트 | 이분탐색 | Lv.3</title>
      <link>https://juyami.tistory.com/94</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;문제&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;a href=&quot;https://programmers.co.kr/learn/courses/30/lessons/43238&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://programmers.co.kr/learn/courses/30/lessons/43238&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1644671198265&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;코딩테스트 연습 - 입국심사&quot; data-og-description=&quot;n명이 입국심사를 위해 줄을 서서 기다리고 있습니다. 각 입국심사대에 있는 심사관마다 심사하는데 걸리는 시간은 다릅니다. 처음에 모든 심사대는 비어있습니다. 한 심사대에서는 동시에 한 &quot; data-og-host=&quot;programmers.co.kr&quot; data-og-source-url=&quot;https://programmers.co.kr/learn/courses/30/lessons/43238&quot; data-og-url=&quot;https://programmers.co.kr/learn/courses/30/lessons/43238&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cw9tor/hyNn0ZrpeN/QY2Jwl9bYsuCeof12UFmG1/img.jpg?width=626&amp;amp;height=626&amp;amp;face=0_0_626_626,https://scrap.kakaocdn.net/dn/cgcTZl/hyNpbE3YdX/S1tkBAG2OT08qfF8IYQ83K/img.jpg?width=626&amp;amp;height=626&amp;amp;face=0_0_626_626&quot;&gt;&lt;a href=&quot;https://programmers.co.kr/learn/courses/30/lessons/43238&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://programmers.co.kr/learn/courses/30/lessons/43238&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cw9tor/hyNn0ZrpeN/QY2Jwl9bYsuCeof12UFmG1/img.jpg?width=626&amp;amp;height=626&amp;amp;face=0_0_626_626,https://scrap.kakaocdn.net/dn/cgcTZl/hyNpbE3YdX/S1tkBAG2OT08qfF8IYQ83K/img.jpg?width=626&amp;amp;height=626&amp;amp;face=0_0_626_626');&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;코딩테스트 연습 - 입국심사&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;n명이 입국심사를 위해 줄을 서서 기다리고 있습니다. 각 입국심사대에 있는 심사관마다 심사하는데 걸리는 시간은 다릅니다. 처음에 모든 심사대는 비어있습니다. 한 심사대에서는 동시에 한&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;programmers.co.kr&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;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;풀이&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1644671212987&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function solution(n, times) {
    times.sort((a, b) =&amp;gt; a - b);
    let min = times[0];
    let max = n * times[times.length -1];

    while(min &amp;lt;= max){
        const mid = Math.floor((min + max) / 2);
        const count = times.reduce((acc, curr) =&amp;gt; acc + Math.floor(mid / curr), 0); // 한 사람당 몇명 할 수 있는지
        console.log(min, max, mid, count);
        count &amp;gt;= n ? max = mid - 1 : min = mid + 1;
    }
    return min;
}&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;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;1.&lt;/b&gt; 이분탐색을 위해서는 정렬된 배열이 필요하다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1644671259425&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;times.sort((a, b) =&amp;gt; a - b);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;2.&lt;/b&gt; 가장 최소로 걸리는 시간(&lt;span style=&quot;color: #e06c75; letter-spacing: 0px;&quot;&gt;min&lt;/span&gt;)과 최대로 걸리는 시간(&lt;span style=&quot;color: #e06c75; letter-spacing: 0px;&quot;&gt;max&lt;/span&gt;)를 먼저 구해준다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1644671313165&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;let min = times[0];
let max = n * times[times.length -1];&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;3.&lt;/b&gt; &lt;u&gt;&lt;b&gt;(최소+최대)/2&lt;/b&gt;&lt;/u&gt;로 시간의 중간값(&lt;span style=&quot;color: #e06c75;&quot;&gt;mid&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;)을 구한다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1644671369023&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const mid = Math.floor((min + max) / 2);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;4. &lt;/b&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;times&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;를 돌면서 각 심사관 한 사람당 &lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;mid&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt; 시간동안 몇명을 심사할 수 있는지 계산&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;(Math.floor(&lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;mid&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&amp;nbsp;/&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;curr&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;))&lt;/span&gt;해서&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&amp;nbsp;총합을 구한다. (&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #e06c75;&quot;&gt;acc&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;에 누적해줌)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1644671513637&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const count = times.reduce((acc, curr) =&amp;gt; acc + Math.floor(mid / curr), 0);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;5.&lt;/b&gt; 만약, &lt;span style=&quot;color: #e06c75;&quot;&gt;mid&lt;/span&gt;시간 동안 검사할 수 있는 인원의 총 수(&lt;span style=&quot;color: #e06c75;&quot;&gt;count&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;)가 주어진 &lt;b&gt;n명&lt;/b&gt;보다 많거나 같을 경우,&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;max&lt;/span&gt;를 &lt;span style=&quot;color: #e06c75;&quot;&gt;mid&lt;/span&gt; 이전으로 만들어 &lt;b&gt;왼쪽 공간&lt;/b&gt;을 탐색 공간으로 정한다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;n명&lt;/b&gt;보다 적을 경우,&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;min&lt;/span&gt;을 &lt;span style=&quot;color: #e06c75;&quot;&gt;mid&lt;/span&gt; 다음으로 만들어 &lt;b&gt;오른쪽 공간&lt;/b&gt;을 탐색 공간으로 정한다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1644671591536&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;count &amp;gt;= n ? max = mid - 1 : min = mid + 1;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그럼 최종 &lt;span style=&quot;color: #e06c75;&quot;&gt;min&lt;/span&gt;값이 &lt;b&gt;n명&lt;/b&gt;을 심사하는 데 걸리는 최소 시간이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;느낀점&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이분탐색을 그냥 왼쪽 오른쪽 조절해서 탐색하는 용, 배열에 있는 값에서 찾고자 하는 값만 찾는 알고리즘이라고 생각했었는데, 이 문제로 이분탐색을 어떻게 활용하면 되는지 알 것 같다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;처음에는 times 배열만으로 어떻게 왼쪽 오른쪽 탐색 공간을 잡을 지 생각해봤는데..&lt;/span&gt;&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;무조건 주어진 배열에서 mid값을 구해서위치만 조절하는 것이 아닌, 문제를 활용해서 내가 직접 최소값과 최대값을 지정해주고 탐색할 공간의 범위를 생각해보자. 그렇게 내가 정한 공간에서 중간값을 변경하면서 조건을 따져보는 식으로 풀면 될거다..!&lt;/span&gt;&lt;/blockquote&gt;</description>
      <category>프로그래머스</category>
      <category>JavaScript</category>
      <category>알고리즘</category>
      <category>이분탐색</category>
      <category>입국심사</category>
      <category>자바스크립트</category>
      <category>프로그래머스</category>
      <author>ruby_s</author>
      <guid isPermaLink="true">https://juyami.tistory.com/94</guid>
      <comments>https://juyami.tistory.com/94#entry94comment</comments>
      <pubDate>Sat, 12 Feb 2022 22:21:18 +0900</pubDate>
    </item>
    <item>
      <title>[백준][BOJ] 카드 구매하기 - silver.1 | 자바스크립트 | 동적계획법 (Dynamic progrmming, DP)</title>
      <link>https://juyami.tistory.com/93</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;문제&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-01-27 오전 12.00.53.png&quot; data-origin-width=&quot;1434&quot; data-origin-height=&quot;1308&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yPQHM/btrrOcObi88/9CyJyE66Iw5E4x2H2mPNAk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yPQHM/btrrOcObi88/9CyJyE66Iw5E4x2H2mPNAk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yPQHM/btrrOcObi88/9CyJyE66Iw5E4x2H2mPNAk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FyPQHM%2FbtrrOcObi88%2F9CyJyE66Iw5E4x2H2mPNAk%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;569&quot; height=&quot;1308&quot; data-filename=&quot;스크린샷 2022-01-27 오전 12.00.53.png&quot; data-origin-width=&quot;1434&quot; data-origin-height=&quot;1308&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;a title=&quot;https://www.acmicpc.net/problem/11052&quot; href=&quot;https://www.acmicpc.net/problem/11052&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://www.acmicpc.net/problem/11052&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1643208138254&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;11052번: 카드 구매하기&quot; data-og-description=&quot;첫째 줄에 민규가 구매하려고 하는 카드의 개수 N이 주어진다.&amp;nbsp;(1 &amp;le; N &amp;le; 1,000) 둘째 줄에는 Pi가 P1부터 PN까지 순서대로 주어진다. (1 &amp;le; Pi &amp;le; 10,000)&quot; data-og-host=&quot;www.acmicpc.net&quot; data-og-source-url=&quot;https://www.acmicpc.net/problem/11052&quot; data-og-url=&quot;https://www.acmicpc.net/problem/11052&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/sUaxP/hyNdqpYKU5/8fb8F3eKMjmo5nsaWh8ngk/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/11052&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.acmicpc.net/problem/11052&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/sUaxP/hyNdqpYKU5/8fb8F3eKMjmo5nsaWh8ngk/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;11052번: 카드 구매하기&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;첫째 줄에 민규가 구매하려고 하는 카드의 개수 N이 주어진다.&amp;nbsp;(1 &amp;le; N &amp;le; 1,000) 둘째 줄에는 Pi가 P1부터 PN까지 순서대로 주어진다. (1 &amp;le; Pi &amp;le; 10,000)&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;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;풀이&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1643208159370&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function solution(N, price){
    let dp = [0, ...price];
    for(let i = 2; i &amp;lt;= N; i++){
        for(let j = 1; j &amp;lt; i; j++)
            dp[i] = Math.max(dp[i], dp[j] + dp[i - j]); // j + (i-j) = i이기 때문에, i 개의 카드를 뽑기 위한 조합 별로 j를 증가시켜서 최댓값을 계속 업데이트해준다.
    }
    return dp[N];
}

const fs = require('fs');
const input = fs.readFileSync('/dev/stdin').toString().trim().split('\n');
const N = +input[0];
const price = [...input[1].split(' ')].map((el) =&amp;gt; +el);
console.log(solution(N, price))&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;처음에 일일이 N개를 뽑을 수 있는 조합의 경우 수를 다 구했는데, 아무리봐도 좀 더 쉽게 풀 수 있을 것 같았다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;위 코드는 각 i마다 i개씩 뽑을 수 있는 경우의 수 별로 &lt;b&gt;최댓값을 계속 업데이트&lt;/b&gt; 해주는 방법이다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;i = 2일 때, j는 1로 한번 반복될 수 있고(조건이 j &amp;lt; i 이기 때문) 기존의 원래 값( &lt;span style=&quot;letter-spacing: 0px; color: #e06c75;&quot;&gt;dp&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #abb2bf;&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #e06c75;&quot;&gt;i&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #abb2bf;&quot;&gt;] &lt;span style=&quot;color: #000000;&quot;&gt;)&lt;/span&gt; &lt;span style=&quot;color: #000000;&quot;&gt;보다&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #abb2bf;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #e06c75;&quot;&gt;dp&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #abb2bf;&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #e06c75;&quot;&gt;j&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #abb2bf;&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #56b6c2;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #e06c75;&quot;&gt;dp&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #abb2bf;&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #e06c75;&quot;&gt;i&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #56b6c2;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #e06c75;&quot;&gt;j&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #abb2bf;&quot;&gt;]&lt;span style=&quot;color: #000000;&quot;&gt; 가 더 크다면 업데이트 된다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR'; letter-spacing: 0px; color: #abb2bf;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;br /&gt;입력 배열(price)의 1번째 인덱스에는 1장 짜리 카드의 금액이 들어있고, 2번째에는 2장&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;짜리&lt;/span&gt; 카드의 금액, 3번째에는 3장&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;짜리&lt;/span&gt; 카드의 금액 &amp;bull;&amp;bull;&amp;bull;&amp;nbsp; 쭉쭉 들어있는데,&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;i&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #56b6c2;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #d19a66;&quot;&gt;3 &lt;/span&gt;&lt;span style=&quot;font-family: 'Noto Serif KR'; letter-spacing: 0px; color: #abb2bf;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;일때는 j가 1, 2 로 2번 반복되고, &lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;dp&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;j&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;]&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #56b6c2;&quot;&gt;+&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;dp&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;i&lt;/span&gt;&lt;span style=&quot;color: #56b6c2;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;j&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #abb2bf;&quot;&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 에서 보면&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; letter-spacing: 0px; color: #e06c75;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&quot;&lt;/span&gt;&lt;/b&gt; j&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #56b6c2;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #d19a66;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;font-family: 'Noto Serif KR'; letter-spacing: 0px; color: #abb2bf;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;letter-spacing: 0px; color: #abb2bf;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt; : 1번째 + 2(3-1)번째 더한 값,&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;&amp;nbsp; j&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #56b6c2;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;&lt;span style=&quot;color: #d19a66;&quot;&gt;2&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family: 'Noto Serif KR'; letter-spacing: 0px; color: #abb2bf;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;letter-spacing: 0px; color: #abb2bf;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt; : 2번째 + 1(3-2)번째 더한 값&lt;b&gt; &quot;&lt;/b&gt; 을 각각 기존 값과 비교해서 더 큰 경우 업데이트 해주게 된다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR'; letter-spacing: 0px; color: #abb2bf;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;letter-spacing: 0px; color: #abb2bf;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;결국, i 개 반복마다 j 반복에서 맨 처음인 1부터 &lt;b&gt;높은 인덱스 방향으로 올라가는 값&lt;/b&gt;과 &lt;b&gt;i에서 j씩 빼주면서 낮은 인덱스 방향으로 내려오는 값&lt;/b&gt;을 &lt;b&gt;더하면&lt;/b&gt; &lt;b&gt;그 둘은 합이 i개&lt;/b&gt;가 되기 때문에 &quot;2개를 뽑는 경우 최댓값, 3개를 뽑는 경우 최댓값 &amp;bull;&amp;bull;&amp;bull; N개를 뽑는 경우 최댓값&quot; 이 쭉쭉 계산돼서 &lt;b&gt;dp[N]에는 N개를 뽑을 때 최댓값&lt;/b&gt;이 들어가게 된다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;dp[1] : 1개를 뽑을 때 최댓값&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;dp[2] : 2개를 뽑을 때 최댓값&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&amp;bull;&amp;bull;&amp;bull;&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;dp[N] : N개를 뽑을 때 최댓값&lt;/span&gt;&lt;/blockquote&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;</description>
      <category>백준</category>
      <category>BOJ</category>
      <category>DP</category>
      <category>동적계획법</category>
      <category>백준</category>
      <category>알고리즘</category>
      <category>자바스크립트</category>
      <author>ruby_s</author>
      <guid isPermaLink="true">https://juyami.tistory.com/93</guid>
      <comments>https://juyami.tistory.com/93#entry93comment</comments>
      <pubDate>Wed, 26 Jan 2022 23:59:11 +0900</pubDate>
    </item>
    <item>
      <title>[알고리즘] 이진 탐색 (이분 탐색, Binary Search)</title>
      <link>https://juyami.tistory.com/92</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;400&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ZBuBB/btrrJt3dUTP/rHapwrJrpztlJK2QNCJ2hK/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ZBuBB/btrrJt3dUTP/rHapwrJrpztlJK2QNCJ2hK/img.gif&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ZBuBB/btrrJt3dUTP/rHapwrJrpztlJK2QNCJ2hK/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/ZBuBB/btrrJt3dUTP/rHapwrJrpztlJK2QNCJ2hK/img.gif&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;600&quot; height=&quot;400&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;400&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;이진&amp;nbsp;탐색&amp;nbsp;(이분&amp;nbsp;탐색,&amp;nbsp;Binary&amp;nbsp;Search)&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이진 탐색&amp;nbsp;알고리즘은&amp;nbsp;&lt;b&gt;정렬되어 있는 리스트에서&lt;/b&gt; &lt;b&gt;탐색 범위를 절반씩 좁혀가며 데이터를 탐색&lt;/b&gt;하는 방법이다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이진 탐색은&lt;span style=&quot;font-size: 1.12em; letter-spacing: 0px;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;배열의 데이터가 정렬되어 있어야만 사용할 수 있는&lt;/b&gt;&lt;span style=&quot;font-size: 1.12em; letter-spacing: 0px;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-size: 1.12em; letter-spacing: 0px;&quot;&gt;알고리즘이다.&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;변수 3개(start, mid, end)를 사용하여 탐색한다.&lt;br /&gt;&lt;b&gt;찾고자하는 데이터와 배열의 중간(mid) 위치에 있는 데이터를 반복적으로 비교해서 원하는 데이터를 찾는 것&lt;/b&gt;이&amp;nbsp;이진 탐색이다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&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;style4&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;이진 탐색(Binary Search)의 탐색 과정&lt;/span&gt;&lt;span style=&quot;color: #8c8c8c;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; color: #222222;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;338&quot; data-origin-height=&quot;79&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dGZuN6/btrrJTAD7KV/n3njt3EKFgmdGbUbredC50/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dGZuN6/btrrJTAD7KV/n3njt3EKFgmdGbUbredC50/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dGZuN6/btrrJTAD7KV/n3njt3EKFgmdGbUbredC50/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdGZuN6%2FbtrrJTAD7KV%2Fn3njt3EKFgmdGbUbredC50%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;338&quot; height=&quot;79&quot; data-origin-width=&quot;338&quot; data-origin-height=&quot;79&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;위의 데이터 집합에서 8이란 데이터를 탐색하도록 하자. 우선 첫번째로 배열의 중간 요소를 선택한다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;span style=&quot;letter-spacing: 0px; color: #e06c75;&quot;&gt;mid&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #56b6c2;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #d19a66;&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #abb2bf;&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;338&quot; data-origin-height=&quot;79&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ckPdvt/btrrJuA5Kqx/82KGBMumYRND4rsOYN1jP1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ckPdvt/btrrJuA5Kqx/82KGBMumYRND4rsOYN1jP1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ckPdvt/btrrJuA5Kqx/82KGBMumYRND4rsOYN1jP1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FckPdvt%2FbtrrJuA5Kqx%2F82KGBMumYRND4rsOYN1jP1%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;338&quot; height=&quot;79&quot; data-origin-width=&quot;338&quot; data-origin-height=&quot;79&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;두번째로는 중간 값과 찾으려는 값을 서로 비교한다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;만약 찾으려는 값이 중간 값보다 작다면 중앙 요소의 왼쪽에서 중간 값을 다시 택하고, 찾으려는 값이 중간 값보다 크다면 오른쪽에서 중간 값을 다시 택하게 된다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그리곤 다시 이진 탐색(Binary Search)과정을 거치는 것이다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;위의 경우, 찾으려는 값인 8이 중간값 7보다 크므로 중간 값 왼쪽에 있는 데이터는 비교할 필요가 없는 것이다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이제, 중간 값 7의 오른편에서 중간 값을 다시 택한다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;338&quot; data-origin-height=&quot;79&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/3eDeS/btrrF5B78cZ/k7MJ4K6fA8ATW7eNK1dT80/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/3eDeS/btrrF5B78cZ/k7MJ4K6fA8ATW7eNK1dT80/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/3eDeS/btrrF5B78cZ/k7MJ4K6fA8ATW7eNK1dT80/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F3eDeS%2FbtrrF5B78cZ%2Fk7MJ4K6fA8ATW7eNK1dT80%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;338&quot; height=&quot;79&quot; data-origin-width=&quot;338&quot; data-origin-height=&quot;79&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이제는 중간 값이 9이고, 다시 찾으려는 값과 중간 값을 비교하게 됩니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;찾으려는 값 8, &lt;span style=&quot;letter-spacing: 0px; color: #e06c75;&quot;&gt;mid&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #56b6c2;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #d19a66;&quot;&gt;9&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #abb2bf;&quot;&gt;;&lt;br /&gt;&lt;/span&gt;8이 9보다 작으므로 중간 값 왼편에서 데이터를 찾아야  한다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;338&quot; data-origin-height=&quot;79&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bGm32E/btrrLNmpfbg/KKiqlk20e2UpVEkkX6xWN1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bGm32E/btrrLNmpfbg/KKiqlk20e2UpVEkkX6xWN1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bGm32E/btrrLNmpfbg/KKiqlk20e2UpVEkkX6xWN1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbGm32E%2FbtrrLNmpfbg%2FKKiqlk20e2UpVEkkX6xWN1%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;338&quot; height=&quot;79&quot; data-origin-width=&quot;338&quot; data-origin-height=&quot;79&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그럼 다시 왼쪽에서 중간 값을 선택한다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;span style=&quot;letter-spacing: 0px; color: #e06c75;&quot;&gt;mid&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #56b6c2;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #d19a66;&quot;&gt;8&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #abb2bf;&quot;&gt;;&lt;br /&gt;&lt;/span&gt;남은 데이터 8이 중간 값으로 택해지게 되는데 찾으려는 데이터와 일치하므로 탐색을 끝마친다.&lt;/span&gt;&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;style4&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;이진 탐색 코드 (JavaScript)&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;: 자바스크립트로 구현한 이진탐색 코드이다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1643171976978&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function binarySearch(sortedArray, target) {
    let start = 0;
    let end = sortedArray.length - 1;
  
    while (start &amp;lt; end) {
      const mid = start + Math.floor((start + end) / 2);

      if (sortedArray[mid] === target)
        return mid;

      if (sortedArray[mid] &amp;lt; target)
        start = mid + 1;
      else
        end = mid - 1;
    }
  
    return -1;
}
  
const nums = [10, 40, 70, 50, 30, 90, 80, 20, 60];
const sortedNums = nums.sort();

console.log(binarySearch(sortedNums, 40));
&amp;gt; 3

console.log(binarySearch(sortedNums, 100));
&amp;gt; -1&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&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;</description>
      <category>algorithm</category>
      <category>Algorithm</category>
      <category>binary search</category>
      <category>알고리즘</category>
      <category>이분탐색</category>
      <category>이진탐색</category>
      <category>자바스크립트</category>
      <author>ruby_s</author>
      <guid isPermaLink="true">https://juyami.tistory.com/92</guid>
      <comments>https://juyami.tistory.com/92#entry92comment</comments>
      <pubDate>Wed, 26 Jan 2022 13:41:41 +0900</pubDate>
    </item>
    <item>
      <title>[개발환경 구축하기] babel과 Webpack</title>
      <link>https://juyami.tistory.com/91</link>
      <description>&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #222426; font-family: 'Noto Serif KR';&quot;&gt;웹 프로젝트를 새로 시작하기 위해서는 라이브러리를 받아와 개발환경을 구축하는 일부터 시작해야 한다.&lt;br /&gt;처음에는 CRA(create-react-app)으로 개발환경을 구축했지만 &quot;CRA 없이 개발환경을 구축해보기&quot; 공부를 하기 위해 작성해본다.&lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;1-packagejson-생성&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;1. package.json 생성&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;첫 번째는 package.json 파일부터 생성해야한다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;span style=&quot;color: #24292e;&quot;&gt;&lt;span style=&quot;color: #222426;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;npm&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;init&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #56b6c2;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;y &lt;/span&gt;&lt;span style=&quot;color: #222426; font-size: 1.12em; letter-spacing: 0px;&quot;&gt;&lt;span style=&quot;color: #222426; font-size: 1.12em; letter-spacing: 0px;&quot;&gt;명령어를 사용하여 package.json를 생성하자. &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;yarn&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;init&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #56b6c2;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;y&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #24292e; font-size: 1.12em;&quot;&gt;&amp;nbsp;을 사용해도 된다.&lt;/span&gt;&lt;span style=&quot;color: #24292e;&quot;&gt;&lt;span style=&quot;color: #222426;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;npm&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;init &lt;/span&gt;&lt;span style=&quot;font-size: 1.12em; letter-spacing: 0px;&quot;&gt;만 입력하게 되면 사용자에게 package.json파일의 name이나 version, license등을 묻는데, -y 명령을 붙이면 npm의 package.json 기본값에 따라 파일이 생성된다.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;자세한 내용은 &lt;a href=&quot;https://docs.npmjs.com/cli/v8/commands/npm-init&quot;&gt;npm init docs&lt;/a&gt;에서 확인하자.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;npm&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;init&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #56b6c2;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;y &lt;/span&gt;&lt;span style=&quot;font-size: 1.12em; letter-spacing: 0px;&quot;&gt;로 생성된 파일은 아래와 같다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;pre class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;//package.json

{
  &quot;name&quot;: &quot;babel-webpack-practice&quot;,
  &quot;version&quot;: &quot;1.0.0&quot;,
  &quot;description&quot;: &quot;&quot;,
  &quot;main&quot;: &quot;index.js&quot;,
  &quot;scripts&quot;: {
    &quot;test&quot;: &quot;echo \&quot;Error: no test specified\&quot; &amp;amp;&amp;amp; exit 1&quot;
  },
  &quot;keywords&quot;: [],
  &quot;author&quot;: &quot;&quot;,
  &quot;license&quot;: &quot;ISC&quot;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이제 필요한 라이브러리를 붙여나가면 된다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 id=&quot;2-babel-설치&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;2. babel 설치&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;span style=&quot;color: #222426;&quot;&gt;babel 라이브러리를 설치하기 위해서 &lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;npm&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;install&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;설치할&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;라이브러리&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #222426; font-size: 1.12em;&quot;&gt;&amp;nbsp;명령어를 입력하자.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;span style=&quot;color: #222426;&quot;&gt;우선 설치해야 할 라이브러리는 @babel/core, @babel/cli이다.&lt;br /&gt;&lt;span style=&quot;color: #222426;&quot;&gt;&lt;b&gt;@babel/core &lt;/b&gt;는 babel이 트랜스파일을 할 수 있게 해주는 역할이고,&lt;br /&gt;&lt;b&gt;@babel/cli &lt;/b&gt;는 CLI(Command Line Interface, git bash나 cmd 같은 거임)에서 babel을 실행할 수 있게 해주는 역할이다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #222426;&quot;&gt;나는 &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;npm&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;install&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #56b6c2;&quot;&gt;--&lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;save&lt;/span&gt;&lt;span style=&quot;color: #56b6c2;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;dev&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; @&lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;babel&lt;/span&gt;&lt;span style=&quot;color: #56b6c2;&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;core&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; @&lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;babel&lt;/span&gt;&lt;span style=&quot;color: #56b6c2;&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;cli&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #222426; font-size: 1.12em;&quot;&gt;&amp;nbsp;명령어를 사용했다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #222426; font-family: 'Noto Serif KR';&quot;&gt;&lt;span style=&quot;color: #222426;&quot;&gt;&lt;b&gt;--save-dev(줄여서 -D)&lt;/b&gt;&lt;span style=&quot;color: #222426;&quot;&gt;&amp;nbsp;명령어는 이 라이브러리들을 개발단계에서만 사용하겠다는 뜻이다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #222426; font-family: 'Noto Serif KR';&quot;&gt;&lt;span style=&quot;color: #222426;&quot;&gt;&lt;span style=&quot;color: #222426;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;b&gt;-D&lt;/b&gt;&lt;span style=&quot;color: #222426;&quot;&gt;&amp;nbsp;명령어를 쓰지 않고 라이브러리를 설치하면 &lt;b&gt;package.json의 dependencies 객체&lt;/b&gt;에 라이브러리의 이름이 추가된다. &lt;span style=&quot;color: #222426;&quot;&gt;이 패키지가 배포되어서 설치됐을 때 dependencies 객체에 포함된 라이브러리들이 같이 설치된다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #222426; font-family: 'Noto Serif KR';&quot;&gt;&lt;span style=&quot;color: #222426;&quot;&gt;&lt;span style=&quot;color: #222426;&quot;&gt;&lt;span style=&quot;color: #222426;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;b&gt;-D&lt;/b&gt;&lt;span style=&quot;color: #222426;&quot;&gt;&amp;nbsp;명령어를 사용하고 라이브러리를 설치하면 devDependencies &lt;b&gt;객체에&lt;/b&gt; 라이브러리가 추가되고, 이 라이브러리들은 배포된 패키지에 포함되지 않는다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;span style=&quot;color: #222426;&quot;&gt;babel은 상위 ES 문법이 사용된 js파일을 하위 ES 문법인 js파일로 변환시켜주는 라이브러리이기 때문에 개발단계에서만 사용한다. 그렇기 때문에&amp;nbsp;&lt;/span&gt;-D&lt;span style=&quot;color: #222426;&quot;&gt;&amp;nbsp;명령어를 사용해서 설치하자.&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;// pacakage.json

{
  &quot;name&quot;: &quot;babel-webpack-practice&quot;,
  &quot;version&quot;: &quot;1.0.0&quot;,
  &quot;description&quot;: &quot;&quot;,
  &quot;main&quot;: &quot;index.js&quot;,
  &quot;scripts&quot;: {
    &quot;test&quot;: &quot;echo \&quot;Error: no test specified\&quot; &amp;amp;&amp;amp; exit 1&quot;
  },
  &quot;keywords&quot;: [],
  &quot;author&quot;: &quot;&quot;,
  &quot;license&quot;: &quot;ISC&quot;,
  &quot;devDependencies&quot;: {
    &quot;@babel/cli&quot;: &quot;^7.16.8&quot;,
    &quot;@babel/core&quot;: &quot;^7.16.12&quot;
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이렇게 devDependencies에 설치한 라이브러리가 추가되었다.&lt;br /&gt;하지만 이것만으로 babel을 사용할 수는 없고 plugin이 필요하다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style4&quot; /&gt;
&lt;h3 id=&quot;21-plugin과-preset&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;2-1. plugin과 preset&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;span style=&quot;color: #222426;&quot;&gt;babel의 plugin은 실제로 코드를 변환시키는 기능을 담당한다.&lt;br /&gt;&lt;/span&gt;&lt;u&gt;&lt;a href=&quot;https://babeljs.io/docs/en/plugins&quot;&gt;babel plugin Docs&lt;/a&gt;&lt;/u&gt;를 보면 plugin이 세세하게 나뉘어져 있어 설치하는 것이 번거롭고, 내가 필요한 plugin을 하나하나 찾는 것도 힘들다.&lt;br /&gt;&lt;span style=&quot;color: #222426;&quot;&gt;(예를 들면, 내가 ES6의 화살표 함수 문법을 사용했다면, 이를 변환시키기 위해 @babel/plugin-transform-arrow-functions 라이브러리의 설치가 필요하고,&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #222426; font-family: 'Noto Serif KR';&quot;&gt;블럭 스코프를 사용했다면 @babel/plugin-transform-block-scoping 라이브러리의 설치가 필요하다.)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그래서 preset이 등장하게 된다.&lt;br /&gt;preset은 목적에 따라 plugin들을 모아놓은 라이브러리다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;preset도 여러가지가 있는데, 그 중에서도 @babel/preset-env 라이브러리가 targets 옵션을 이용해서 어떤 브라우저에도 유연하게 대응할 수 있기 때문에 가장 자주 쓰인다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그럼 @babel/preset-env을 설치해서 사용해보자!&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;npm&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;install&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #56b6c2;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #e5c07b;&quot;&gt;D&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; @&lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;babel&lt;/span&gt;&lt;span style=&quot;color: #56b6c2;&quot;&gt;/&lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;preset&lt;/span&gt;&lt;span style=&quot;color: #56b6c2;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;env &lt;/span&gt;&lt;span style=&quot;font-size: 1.12em; letter-spacing: 0px;&quot;&gt;로 설치한다. 그 다음 babel.config.js 파일을 만들어서 내가 preset을 사용하겠다는 것을 선언하자.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;pre class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;// babel.config.js

const presets = [
  [
    &quot;@babel/preset-env&quot;,
    {
      targets: {
        chrome: &quot;87&quot;,
      },
      useBuiltIns: &quot;usage&quot;,
      corejs: &quot;3.6.4&quot;,
    },
  ],
];

module.exports = { presets };&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;옵션 중, &lt;b&gt;useBuiltIns&lt;/b&gt;는 polyfill을 사용할 것인지 아닌지를 선택할 수 있는 옵션이다.&lt;br /&gt;useBuiltIns 옵션은 &quot;usage&quot; | &quot;entry&quot; | false 중 하나를 선택할 수 있고 &lt;b&gt;default는 false&lt;/b&gt;다.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&quot;usage&quot;&lt;/b&gt;는 내 코드를 분석해서 필요한 polyfill plugin만을 적용시킨다.&lt;br /&gt;&lt;b&gt;&quot;entry&quot;&lt;/b&gt;는 targets 브라우저에 필요한 polyfill plugin을 모두 적용시킨다.&lt;br /&gt;&lt;b&gt;false&lt;/b&gt;는 polyfill을 사용하지 않는다는 뜻이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;br /&gt;&lt;b&gt;corejs&lt;/b&gt; 옵션은 polyfill을 사용할 때 삽입되는 corejs의 버전을 선택하는 옵션이다.&lt;br /&gt;useBuiltIns 옵션이 활성화되어 있을 때 적용가능하다.&lt;br /&gt;2, 3 혹은 { version: 2 | 3, proposals: boolean } 중 하나를 선택할 수 있고 &lt;b&gt;default는 2&lt;/b&gt;다.&lt;br /&gt;2는 업데이트가 중단되어서 3을 사용하는 것이 좋다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;@babel/preset-env의 옵션들과 자세한 정보는&amp;nbsp;&lt;u&gt;&lt;a href=&quot;https://babeljs.io/docs/en/babel-preset-env&quot;&gt;@babel/preset-env Docs&lt;/a&gt;&lt;/u&gt;에서 확인하자.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이렇게 preset 옵션 배열을 module.exports 해주면 preset 적용이 완료된다.&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 id=&quot;3-webpack&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;3. webpack&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;webpack은 entry파일을 지정해서 entry파일이 의존성을 띄고 있는 모듈들을 모두 하나로 묶어내는 라이브러리다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;npm&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;install&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #56b6c2;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #e5c07b;&quot;&gt;D&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;webpack&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;webpack&lt;/span&gt;&lt;span style=&quot;color: #56b6c2;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;cli&lt;/span&gt;&lt;span style=&quot;font-size: 1.12em; letter-spacing: 0px;&quot;&gt;&amp;nbsp;명령어로 webpack과 webpack-cli를 설치한다.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이제 번들링할 js파일을 만든다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;// src/index.js

const pow = function (a) {
  const result = a * a;
  return result;
};

console.log(pow(3));&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그리고 webpack.config.js 파일을 만들어서 옵션을 설정한다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;// webpack.config.js

const path = require(&quot;path&quot;);

module.exports = {
  entry: &quot;./src/index.js&quot;,
  output: {
    path: path.resolve(__dirname, &quot;dist/js&quot;),
    filename: &quot;bundle.js&quot;,
  },
  devtool: &quot;inline-source-map&quot;,
  mode: &quot;development&quot;,
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;entry 옵션&lt;/b&gt;은 번들링의 시작점이 될 파일을 설정하는 옵션이다. 배열이나 객체의 형태로 여러 개의 entry를 지정할 수도 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;output 옵션&lt;/b&gt;은 번들링이 완료된 파일에 대한 옵션이다.&lt;br /&gt;&lt;b&gt;output.path&lt;/b&gt;는 번들링된 파일이 저장될 위치이고, &lt;b&gt;output.filename&lt;/b&gt;은 번들링된 파일의 이름이다.&lt;br /&gt;(위의 예시에서는 dist/js/bundle.js 경로로 파일이 생성될 것이다.)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;devtool 옵션&lt;/b&gt;에는 여러 종류의 &lt;b&gt;source-map&lt;/b&gt; 중 하나를 입력할 수 있다. source-map은 &lt;b&gt;번들링 된 코드의 원본 위치를 알려주는 역할&lt;/b&gt;을 한다.&lt;br /&gt;아래 사진의 맨 오른쪽을 보면 index.js:6이라고 써있는데, index.js 파일의 6번째 줄에서 콘솔에 실행됐음을 알 수 있다.&lt;br /&gt;뭐 .. 이런 역할을 한다. 우리가 주로 개발하면서 많이 참고했던 것들인데, 이렇게 환경 구축에 따라 달라질 수도 있음을 느낀다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-01-25 오후 4.33.54.png&quot; data-origin-width=&quot;944&quot; data-origin-height=&quot;362&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/5o305/btrrB5Cnk12/CXfaRRMKFW2sUgo1l4xPN1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/5o305/btrrB5Cnk12/CXfaRRMKFW2sUgo1l4xPN1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/5o305/btrrB5Cnk12/CXfaRRMKFW2sUgo1l4xPN1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F5o305%2FbtrrB5Cnk12%2FCXfaRRMKFW2sUgo1l4xPN1%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;598&quot; height=&quot;228&quot; data-filename=&quot;스크린샷 2022-01-25 오후 4.33.54.png&quot; data-origin-width=&quot;944&quot; data-origin-height=&quot;362&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;mode옵션&lt;/b&gt;은 &quot;production&quot; | &quot;development&quot;&amp;nbsp; 두 가지 옵션이 있다. 목적에 맞게 코드를 최적화시켜주는 역할을 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이제 &lt;span style=&quot;color: #e06c75;&quot;&gt;npx&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;webpack&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&amp;nbsp;명령어로 webpack을 실행하자.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그럼 dist/js/bundle.js 이 생성된다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;bundle.js가 제대로 작동하는지 확인하기 위해 index.html 을 만들어서 bundle.js를 script로 불러온다.&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;html xml&quot; data-ke-language=&quot;html&quot;&gt;&lt;code&gt;// index.html

&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;body&amp;gt;
  &amp;lt;script src=&quot;./dist/js/bundle.js&quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그리고 index.html을 브라우저에 띄워 보면 (그냥 클릭해서 띄움) 위의 사진처럼 콘솔에 9가 찍히게 된다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;span style=&quot;color: #222426;&quot;&gt;&lt;b&gt;source-map&lt;/b&gt; 덕분에 이 console.log가 index.js:6에서 발생했다는 것도 알 수 있다.&lt;br /&gt;&lt;/span&gt;여기까지가 webpack의 기본적인 기능이다. 이제 webpack의 엄청난 기능들에 대해 알아보자.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style4&quot; /&gt;
&lt;h3 id=&quot;31-loader&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;3-1. loader&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;webpack은 entry 파일이 의존성을 띄고 있는 모든 것을 모듈로 받아들여 묶어낸다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;내가 React를 쓰고 있고, app 컴포넌트가 css나 scss를 import하거나 혹은 TypeScript를 사용해서 js가 아닌 ts나 tsx를 사용한다면?&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;궁금해졌으니 css 파일을 entry로 지정해서 webpack을 사용해보자.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;css&quot; data-ke-language=&quot;css&quot;&gt;&lt;code&gt;/* src/css/main.css */

@import url(&quot;./background.css&quot;);

/* src/css/background.css */

body {
  background-color: thistle;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;아래는 webpack.config.js 설정이다. entry에 ./src/css/main.css 를 추가해줬다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;dts&quot;&gt;&lt;code&gt;// webpack.config.js

const path = require(&quot;path&quot;);

module.exports = {
  entry: [&quot;./src/js/main.js&quot;, &quot;./src/css/main.css&quot;],
  output: {
    path: path.resolve(__dirname, &quot;dist/js&quot;),
    filename: &quot;bundle.js&quot;,
  },
  devtool: &quot;source-map&quot;,
  mode: &quot;development&quot;,
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이 상태에서 webpack을 작동시키면 에러가 난다. &lt;span style=&quot;color: #222426;&quot;&gt;이 유형의 파일을 처리하려면 loader가 필요할 것이며, 현재 이 파일에 대한 loader가 설정되어있지 않다는 설명과 함께.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style4&quot; /&gt;
&lt;h3 id=&quot;311-css-loader&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;3-1-1. css loader&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그럼 css에는 어떤 loader가 필요할까? css를 처리하기 위해서는 css-loader와 style-loader가 필요하다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;npm&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;install&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #56b6c2;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #e5c07b;&quot;&gt;D&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;css&lt;/span&gt;&lt;span style=&quot;color: #56b6c2;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;loader&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;style&lt;/span&gt;&lt;span style=&quot;color: #56b6c2;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;loader&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; font-size: 1.12em;&quot;&gt; 로 설치한 뒤 적용해보자.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;// webpack.config.js

const path = require(&quot;path&quot;);

module.exports = {
  entry: [&quot;./src/js/main.js&quot;, &quot;./src/css/main.css&quot;],
  output: {
    path: path.resolve(__dirname, &quot;dist/js&quot;),
    filename: &quot;bundle.js&quot;,
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [&quot;style-loader&quot;, &quot;css-loader&quot;],
      },
    ],
  },
  devtool: &quot;source-map&quot;,
  mode: &quot;development&quot;,
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;loader를 적용하려면&lt;/b&gt; &lt;b&gt;module 객체안에 rules 배열&lt;/b&gt;을 두어야한다. rules 배열 안에는 객체들이 들어있고, 객체는 필수적으로 test와 use를 가져야 한다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;test&lt;/b&gt;는 loader를 적용시킬 &lt;b&gt;파일 확장자의 정규표현식&lt;/b&gt;이고,&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;use&lt;/b&gt;는 test 확장자명을 가진 &lt;b&gt;파일에 적용시킬 loader&lt;/b&gt;다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;use는 배열을 사용해서 하나 이상의 loader를 적용시킬 수 있고, &lt;b&gt;배열의 오른쪽에 있는 loader부터 적용&lt;/b&gt;된다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;결국, 이 옵션은 .css로 끝나는 파일에 1. css-loader 2. style-loader 순서로 loader를 적용시키겠다는 뜻이다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;css-loader는 css 스타일시트를 JS로 변환시켜주고, style-loader는 JS로 변환된 css 스타일시트를 DOM에 동적으로 추가시켜준다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이제 다시 webpack을 실행시킨다. (&lt;span style=&quot;color: #e06c75;&quot;&gt;npx&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;webpack&lt;/span&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그럼 배경화면 색상이 바뀐 것을 확인할 수 있다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-01-25 오후 4.54.54.png&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;1508&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/caIp1o/btrrJu1eLqK/8XMPCAFXrZJuccrDfNXUn1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/caIp1o/btrrJu1eLqK/8XMPCAFXrZJuccrDfNXUn1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/caIp1o/btrrJu1eLqK/8XMPCAFXrZJuccrDfNXUn1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcaIp1o%2FbtrrJu1eLqK%2F8XMPCAFXrZJuccrDfNXUn1%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;484&quot; height=&quot;711&quot; data-filename=&quot;스크린샷 2022-01-25 오후 4.54.54.png&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;1508&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style4&quot; /&gt;
&lt;h3 id=&quot;312-babel-loader&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;3-1-2. babel loader&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이제 webpack으로 묶어낼 때 js에 babel을 적용시키기 위해 babel-loader를 사용하겠다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;span style=&quot;color: #222426;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;npm&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;install&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #56b6c2;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #e5c07b;&quot;&gt;D&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;babel&lt;/span&gt;&lt;span style=&quot;color: #56b6c2;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;loader&lt;/span&gt;&lt;span style=&quot;color: #222426; font-size: 1.12em; letter-spacing: 0px;&quot;&gt;&amp;nbsp;명령어를 사용하고 webpack.config.js에서 babel-loader를 적용시키자.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;pre id=&quot;code_1643097606261&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// webpack.config.js

const path = require(&quot;path&quot;);

module.exports = {
  entry: [&quot;./src/index.js&quot;, &quot;./src/css/main.css&quot;],
  output: {
    path: path.resolve(__dirname, &quot;dist/js&quot;),
    filename: &quot;bundle.js&quot;,
  },
  module: {
    rules: [{
        test: /\.js$/,
        use: [
            {
                loader: &quot;babel-loader&quot;,
                options: {
                    presets: [
                        [
                            &quot;@babel/preset-env&quot;,
                            {
                                useBuiltIns: &quot;usage&quot;,
                                corejs: &quot;3.6.4&quot;,
                                targets: {
                                chrome: &quot;87&quot;,
                                },
                            },
                        ],
                    ],
                },
            },
        ],
        exclude: /node_modules/,
      },
      {
        test: /\.css$/,
        use: [&quot;style-loader&quot;, &quot;css-loader&quot;],
      },
    ],
  },
  devtool: &quot;inline-source-map&quot;,
  mode: &quot;development&quot;,
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;br /&gt;&lt;span style=&quot;color: #222426; font-family: 'Noto Serif KR';&quot;&gt;rules 배열에 새 객체가 생겼다.&lt;br /&gt;&lt;span style=&quot;color: #222426;&quot;&gt;1. 먼저 &lt;b&gt;test&lt;/b&gt;는 .js 파일 확장자를 가진 파일들을 대상으로 하고 있다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #222426;&quot;&gt;2. &lt;b&gt;use&lt;/b&gt;는 css-loader를 사용할 때와는 다른 형태다. use 배열안에 객체가 들어있다. 이것은 babel-loader의 option을 설정하기 위해서다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;span style=&quot;color: #222426;&quot;&gt;&lt;span style=&quot;color: #222426;&quot;&gt;이 객체를 살펴보면,&lt;br /&gt;&lt;span style=&quot;color: #222426;&quot;&gt;3. &lt;b&gt;loader&lt;/b&gt;에는 적용할 loader인 &quot;babel-loader&quot;가 들어있다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #222426;&quot;&gt;4. &lt;b&gt;options&lt;/b&gt;는 babel-loader의 옵션을 담는 객체다. presets 배열에 사용할 preset들을 입력한다.&lt;br /&gt;나는 @babel/preset-env를 사용할 것이다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #222426;&quot;&gt;이외에도 plugin과 preset-env의 polyfill 기능도 설정할 수도 있다.&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #222426;&quot;&gt;5. &lt;b&gt;exclude&lt;/b&gt;는 webpack의 번들에서 제외할 폴더나 파일이다.&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #222426;&quot;&gt;node_modules 폴더에는 수 십 수 백개의 라이브러리들이 들어있기 때문에 보통 node_modules는 .js 확장자에 적용시킬 loader에서 제외시킨다.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;u&gt;&lt;a href=&quot;https://webpack.js.org/loaders/&quot;&gt;webpack loaders Docs&lt;/a&gt;&lt;/u&gt;&lt;span style=&quot;color: #222426;&quot;&gt;에서 더 자세히 살펴볼 수 있다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style4&quot; /&gt;
&lt;h3 id=&quot;32-plugin&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;3-2. plugin&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;plugin은 webpack의 편의성을 높여준다. 그 중에서 편리하다고 생각되는 것 몇 개만 적용시켜 보자.&lt;/span&gt;&lt;/p&gt;
&lt;h3 id=&quot;321-htmlwebpackplugin&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;3-2-1. HtmlWebpackPlugin&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;HtmlWebpackPlugin은 webpack을 실행한 뒤 번들링 된 js파일을 포함한 &lt;b&gt;html을 자동으로 생성&lt;/b&gt;해준다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이전에 bundle.js 파일을 webpack으로 생성한 뒤, index.html 파일을 직접 만들어서 bundle.js를 포함시켰다. 이 과정을 자동으로 해주는 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;npm&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;install&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #56b6c2;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #e5c07b;&quot;&gt;D&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;html&lt;/span&gt;&lt;span style=&quot;color: #56b6c2;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;webpack&lt;/span&gt;&lt;span style=&quot;color: #56b6c2;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;plugin &lt;/span&gt;&lt;span style=&quot;font-size: 1.12em; letter-spacing: 0px;&quot;&gt;명령어로 설치한 뒤 적용시킨다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;pre id=&quot;code_1643098207643&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// webpack.config.js

const path = require(&quot;path&quot;);
const HtmlWebpackPlugin = require(&quot;html-webpack-plugin&quot;);

module.exports = {
  entry: [&quot;./src/index.js&quot;, &quot;./src/css/main.css&quot;],
  output: {
    path: path.resolve(__dirname, &quot;dist/js&quot;),
    filename: &quot;bundle.js&quot;,
  },
  module: {
    rules: [{
        test: /\.js$/,
        use: [
            {
                loader: &quot;babel-loader&quot;,
                options: {
                    presets: [
                        [
                            &quot;@babel/preset-env&quot;,
                            {
                                useBuiltIns: &quot;usage&quot;,
                                corejs: &quot;3.6.4&quot;,
                                targets: {
                                chrome: &quot;87&quot;,
                                },
                            },
                        ],
                    ],
                },
            },
        ],
        exclude: /node_modules/,
      },
      {
        test: /\.css$/,
        use: [&quot;style-loader&quot;, &quot;css-loader&quot;],
      },
    ],
  },
  plugins: [new HtmlWebpackPlugin()],
  devtool: &quot;inline-source-map&quot;,
  mode: &quot;development&quot;,
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;두번째 줄의&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;span style=&quot;color: #c678dd;&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #e5c07b;&quot;&gt;HtmlWebpackPlugin&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #56b6c2;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #61afef;&quot;&gt;require&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #98c379;&quot;&gt;&quot;html-webpack-plugin&quot;&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;과 plugins 를 추가해주었다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;plugins&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;: [&lt;/span&gt;&lt;span style=&quot;color: #c678dd;&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #e5c07b;&quot;&gt;HtmlWebpackPlugin&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt;()],&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이제 또 npx webpack을 실행시켜주면, &lt;span style=&quot;color: #222426;&quot;&gt;output 경로 안에 index.htm 이 자동으로 생성된다.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;u&gt;&lt;a href=&quot;https://github.com/jantimon/html-webpack-plugin&quot;&gt;HtmlWebpackPlugin Docs&lt;/a&gt;&lt;/u&gt;&lt;span style=&quot;color: #222426;&quot;&gt;에서 옵션에 대해 자세히 볼 수 있다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h3 id=&quot;322-cleanwebpackplugin&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;3-2-2 CleanWebpackPlugin&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;webpack을 사용하다 보면 이전에 번들링했던 결과물이 계속 남아있어 불편한 때가 있다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;CleanWebpacPlugin&lt;/b&gt;은 새로 번들링했을 때 이전에 번들링한 결과물을 없애준다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 id=&quot;33-webpackdevserver&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;3-3. WebpackDevServer&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;방금 webpack으로 실습을 하면서 계속 반복중인 것이 있다.&lt;/span&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;webpack.config.js 설정 수정&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;webpack을 실행&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;번들된 js파일을 index.html에 적용시킨 후 확인&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이 과정을 계속 반복중이다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;불편함을 개선하기 위해 &lt;span style=&quot;color: #222426;&quot;&gt;webpack 자체에서 실시간으로 코드의 변경을 반영해주는 &lt;b&gt;WebpackDevServer&lt;/b&gt;라는 기능을 제공하고 있다.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #222426; font-family: 'Noto Serif KR';&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;npm&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;install&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #56b6c2;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #e5c07b;&quot;&gt;D&lt;/span&gt;&lt;span style=&quot;color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;webpack&lt;/span&gt;&lt;span style=&quot;color: #56b6c2;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;dev&lt;/span&gt;&lt;span style=&quot;color: #56b6c2;&quot;&gt;-&lt;/span&gt;&lt;span style=&quot;color: #e06c75;&quot;&gt;server&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #222426;&quot;&gt;&lt;span style=&quot;letter-spacing: 0px; color: #222426;&quot;&gt; 명령어로 webpack-dev-server 를 설치 후, &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #e06c75;&quot;&gt;npx&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #e06c75;&quot;&gt;webpack&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #abb2bf;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #e06c75;&quot;&gt;serve&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px; color: #222426;&quot;&gt;&amp;nbsp;명령어로 webpack을 실행하면 번들된 js 파일이 자동으로 index.html에 삽입되어 localhost에서 실행된다.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;a href=&quot;https://webpack.js.org/configuration/dev-server/&quot;&gt;&lt;u&gt;WebpackDevServer Docs&lt;/u&gt;&lt;/a&gt;&lt;span style=&quot;color: #222426;&quot;&gt;에서 자세한 설명을 보도록 하자!&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;여기까지 babel, webpack 에 대해 알아봤다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;정말 개발은 쉽지않다..ㅎ 이런거 하나 하나 공부할게 너무 많은 것 같다.&lt;/span&gt;&lt;/blockquote&gt;</description>
      <category>개발환경구축</category>
      <category>Babel</category>
      <category>Loader</category>
      <category>plugin</category>
      <category>Preset</category>
      <category>webpack</category>
      <author>ruby_s</author>
      <guid isPermaLink="true">https://juyami.tistory.com/91</guid>
      <comments>https://juyami.tistory.com/91#entry91comment</comments>
      <pubDate>Tue, 25 Jan 2022 15:49:39 +0900</pubDate>
    </item>
    <item>
      <title>[자바스크립트] 문자열 중 몇개가 다른 문자인지 개수 세기 | 문자열 비교</title>
      <link>https://juyami.tistory.com/90</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;reduce 활용하기&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1643089906253&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const adj = [];
const difIdx = [...el].reduce((acc, curr, idx) =&amp;gt; curr !== word[idx] ? acc += 1 : acc, 0);
if(difIdx === 1) adj.push(el);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;간단하게 for문을 돌려서 카운트를 증가시키면 비교하고자 하는 문자열과 몇개의 문자가 다른지 알 수 있지만, reduce를 활용할 수도 있다!&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;위의 예시에서 보면, &lt;span style=&quot;background-color: #dddddd;&quot;&gt;&lt;u&gt;difIdx&lt;/u&gt;&lt;/span&gt; 는 다른 문자의 개수가 저장될 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;예를 들어, word = 'apple', el = 'appel'일 경우&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;뒤에 2문자가 다르므로 difIdx = 2가 된다.&lt;/span&gt;&lt;/p&gt;</description>
      <category>javascript</category>
      <category>JavaScript</category>
      <category>reduce</category>
      <category>문자열</category>
      <category>문자열 비교</category>
      <category>자바스크립트</category>
      <author>ruby_s</author>
      <guid isPermaLink="true">https://juyami.tistory.com/90</guid>
      <comments>https://juyami.tistory.com/90#entry90comment</comments>
      <pubDate>Tue, 25 Jan 2022 14:56:46 +0900</pubDate>
    </item>
  </channel>
</rss>