<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title> 도비의 개발일지</title>
    <link>https://dobbyyo.tistory.com/</link>
    <description> FrontEnd, BackEnd, Dev 개발 일지 및 취미~</description>
    <language>ko</language>
    <pubDate>Thu, 10 Sep 2026 09:41:43 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>dobbyyo</managingEditor>
    <image>
      <title> 도비의 개발일지</title>
      <url>https://tistory1.daumcdn.net/tistory/5924194/attach/b2b1b001fbd04d9685f07c4da8b4430b</url>
      <link>https://dobbyyo.tistory.com</link>
    </image>
    <item>
      <title>왕초보를 위한 자바스크립트 독학 로드맵 2026: 완벽한 공부 순서와 계획</title>
      <link>https://dobbyyo.tistory.com/entry/%EC%99%95%EC%B4%88%EB%B3%B4%EB%A5%BC-%EC%9C%84%ED%95%9C-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EB%8F%85%ED%95%99-%EB%A1%9C%EB%93%9C%EB%A7%B5-2026-%EC%99%84%EB%B2%BD%ED%95%9C-%EA%B3%B5%EB%B6%80-%EC%88%9C%EC%84%9C%EC%99%80-%EA%B3%84%ED%9A%8D</link>
      <description>&lt;div style=&quot;line-height: 1.8; max-width: 900px; margin: 0 auto; padding: 20px; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Noto Sans KR', sans-serif; color: #333; background-color: #ffffff; min-height: 100vh;&quot;&gt;
&lt;div style=&quot;background: linear-gradient(135deg, #e5faf7 0%, #f0fdfc 100%); color: #015249; border-left: 4px solid #00897b; padding: 24px 28px; margin: 32px 0; border-radius: 8px; box-shadow: 0 4px 12px rgba(0, 137, 123, 0.1);&quot;&gt;
&lt;p style=&quot;font-size: 16px !important; line-height: 1.8; margin-bottom: 16px;&quot; data-ke-size=&quot;size16&quot;&gt;2026년, 코딩의 세계에 입문하는 가장 확실하고 빠른 방법은 단연 자바스크립트(JavaScript) 학습입니다. 이 글에서는 왕초보를 위한 가장 효율적인 &lt;b&gt;자바스크립트 독학 로드맵&lt;/b&gt;을 제시하여, 여러분의 &lt;b&gt;초보 코딩 공부 계획&lt;/b&gt; 수립을 완벽하게 돕겠습니다. 자바스크립트는 웹 프론트엔드는 물론, 서버(Node.js), 모바일 앱(React Native), 데스크톱 앱(Electron)까지 하나의 언어로 모두 개발할 수 있는 압도적인 범용성을 자랑합니다. 즉, '가성비' 최고의 언어인 셈이죠.&lt;/p&gt;
&lt;p style=&quot;font-size: 16px !important; line-height: 1.8; margin-bottom: 16px;&quot; data-ke-size=&quot;size16&quot;&gt;많은 분이 '비전공자인데 독학으로 가능할까?' 걱정하지만, 이 로드맵만 따라온다면 충분히 취업 가능한 수준에 도달할 수 있습니다. 웹의 기초인 HTML/CSS부터 순수 자바스크립트(Vanilla JS) 마스터, 최신 React 프레임워크 활용, 그리고 자신만의 포트폴리오 프로젝트 완성까지, 이 글 하나로 모든 과정을 끝낼 수 있도록 안내해 드리겠습니다.&lt;/p&gt;
&lt;/div&gt;
&lt;br style=&quot;display: none;&quot; /&gt;
&lt;h2 style=&quot;font-weight: bold; font-size: 22px; border-left: 4px solid #00897b; border-radius: 4px; padding: 16px 20px; margin-top: 40px; margin-bottom: 24px; background: linear-gradient(to right, rgba(0, 137, 123, 0.05), transparent); color: #015249;&quot; data-ke-size=&quot;size26&quot;&gt;목차&lt;/h2&gt;
&lt;ul style=&quot;list-style: disc; margin-left: 40px; margin-bottom: 24px;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;color: #333 !important; font-size: 16px !important; margin-bottom: 12px; line-height: 1.7;&quot;&gt;&lt;a style=&quot;color: #00897b; text-decoration: none; transition: color 0.2s;&quot; href=&quot;#section-1&quot;&gt;섹션 1: 모든 길은 웹으로 통한다 - 선수 지식 (HTML/CSS)&amp;lt;/a &amp;gt; &lt;/a&gt;&lt;/li&gt;
&lt;li style=&quot;color: #333 !important; font-size: 16px !important; margin-bottom: 12px; line-height: 1.7;&quot;&gt;&lt;a style=&quot;color: #00897b;&quot; href=&quot;#section-2&quot;&gt;섹션 2: 자바스크립트 공부 순서 - 기초 체력 다지기 (Vanilla JS)&amp;lt;/a &amp;gt; &lt;/a&gt;&lt;/li&gt;
&lt;li style=&quot;color: #333 !important; font-size: 16px !important; margin-bottom: 12px; line-height: 1.7;&quot;&gt;&lt;a style=&quot;color: #00897b;&quot; href=&quot;#section-3&quot;&gt;섹션 3: 최신 기술 트렌드 따라잡기 (모던 JS - ES6+)&amp;lt;/a &amp;gt; &lt;/a&gt;&lt;/li&gt;
&lt;li style=&quot;color: #333 !important; font-size: 16px !important; margin-bottom: 12px; line-height: 1.7;&quot;&gt;&lt;a style=&quot;color: #00897b;&quot; href=&quot;#section-4&quot;&gt;섹션 4: 개발 효율을 200% 높이는 필수 도구들&lt;/a&gt;&lt;/li&gt;
&lt;li style=&quot;color: #333 !important; font-size: 16px !important; margin-bottom: 12px; line-height: 1.7;&quot;&gt;&lt;a style=&quot;color: #00897b;&quot; href=&quot;#section-5&quot;&gt;섹션 5: 다음 스텝 - 프레임워크 &amp;amp; 라이브러리 선택 가이드&amp;lt;/a &amp;gt; &lt;/a&gt;&lt;/li&gt;
&lt;li style=&quot;color: #333 !important; font-size: 16px !important; margin-bottom: 12px; line-height: 1.7;&quot;&gt;&lt;a style=&quot;color: #00897b;&quot; href=&quot;#section-6&quot;&gt;섹션 6: 지식을 진짜 '내 것'으로 만드는 실전 프로젝트 제안&amp;lt;/a &amp;gt; &lt;/a&gt;&lt;/li&gt;
&lt;li style=&quot;color: #333 !important; font-size: 16px !important; margin-bottom: 12px; line-height: 1.7;&quot;&gt;&lt;a style=&quot;color: #00897b;&quot; href=&quot;#section-7&quot;&gt;섹션 7: 성장을 멈추지 않기 위한 추천 학습 자료&lt;/a&gt;&lt;/li&gt;
&lt;li style=&quot;color: #333 !important; font-size: 16px !important; margin-bottom: 12px; line-height: 1.7;&quot;&gt;&lt;a style=&quot;color: #00897b;&quot; href=&quot;#faq&quot;&gt;자주 묻는 질문 (FAQ) 및 마지막 조언&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;br style=&quot;display: none;&quot; /&gt;
&lt;h2 id=&quot;section-1&quot; style=&quot;font-weight: bold; font-size: 22px; border-left: 4px solid #00897b; border-radius: 4px; padding: 16px 20px; margin-top: 40px; margin-bottom: 24px; background: linear-gradient(to right, rgba(0, 137, 123, 0.05), transparent); color: #015249;&quot; data-ke-size=&quot;size26&quot;&gt;섹션 1: 모든 길은 웹으로 통한다 - 선수 지식 (HTML/CSS)&lt;/h2&gt;
&lt;p style=&quot;color: #333 !important; font-size: 16px !important; line-height: 1.8; margin-bottom: 20px;&quot; data-ke-size=&quot;size16&quot;&gt;자바스크립트는 웹페이지에 생명을 불어넣는 언어입니다. 따라서 웹의 뼈대를 만드는 HTML과 디자인을 입히는 CSS를 모르면 자바스크립트의 능력을 10%도 활용할 수 없습니다. 건물을 지을 때 골조(HTML)를 세우고 인테리어(CSS)를 해야 자동문이나 엘리베이터(JavaScript) 같은 기능을 넣을 수 있는 것과 같은 이치입니다. 이 단계는 여러분의 &lt;b&gt;초보 코딩 공부 계획&lt;/b&gt;에서 가장 먼저 수행해야 할 필수 과정입니다.&lt;/p&gt;
&lt;div style=&quot;text-align: center; margin: 32px 0; border-radius: 8px; overflow: hidden;&quot;&gt;&lt;img style=&quot;max-width: 100%; height: auto; border-radius: 8px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);&quot; src=&quot;https://files.dobbyblog.kr/view/772f905c-ef68-4569-9f57-d4ee7fdcc288.png&quot; alt=&quot;초보 학습자를 위한 웹의 기초인 HTML과 CSS 코드가 보이는 노트북 화면과 공부 환경&quot; /&gt;&lt;/div&gt;
&lt;p style=&quot;color: #333 !important; font-size: 16px !important; line-height: 1.8; margin-bottom: 20px;&quot; data-ke-size=&quot;size16&quot;&gt;본격적인 자바스크립트 학습에 앞서 약 2주간 아래 내용을 먼저 익히는 것을 추천합니다.&lt;/p&gt;
&lt;ul style=&quot;list-style: disc; margin-left: 40px; margin-bottom: 24px;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;color: #333 !important; font-size: 16px !important; margin-bottom: 12px; line-height: 1.7;&quot;&gt;&lt;b&gt;HTML (학습 기간: 1주):&lt;/b&gt; 단순히 글자를 보여주는 태그를 넘어, 웹 페이지의 의미를 부여하는 시맨틱 태그( &lt;code style=&quot;background: #f5f5f5; padding: 2px 6px; border-radius: 3px; font-size: 13px; color: #d63384; font-family: 'Courier New', monospace;&quot;&gt;header&lt;/code&gt;, &lt;code style=&quot;background: #f5f5f5; padding: 2px 6px; border-radius: 3px; font-size: 13px; color: #d63384; font-family: 'Courier New', monospace;&quot;&gt;nav&lt;/code&gt;, &lt;code style=&quot;background: #f5f5f5; padding: 2px 6px; border-radius: 3px; font-size: 13px; color: #d63384; font-family: 'Courier New', monospace;&quot;&gt;section&lt;/code&gt;, &lt;code style=&quot;background: #f5f5f5; padding: 2px 6px; border-radius: 3px; font-size: 13px; color: #d63384; font-family: 'Courier New', monospace;&quot;&gt;article&lt;/code&gt;, &lt;code style=&quot;background: #f5f5f5; padding: 2px 6px; border-radius: 3px; font-size: 13px; color: #d63384; font-family: 'Courier New', monospace;&quot;&gt;footer&lt;/code&gt;)의 중요성을 이해해야 합니다. 특히 사용자의 입력을 받는 &lt;code style=&quot;background: #f5f5f5; padding: 2px 6px; border-radius: 3px; font-size: 13px; color: #d63384; font-family: 'Courier New', monospace;&quot;&gt;form&lt;/code&gt; 태그와 다양한 &lt;code style=&quot;background: #f5f5f5; padding: 2px 6px; border-radius: 3px; font-size: 13px; color: #d63384; font-family: 'Courier New', monospace;&quot;&gt;input&lt;/code&gt; 타입은 자바스크립트와 직접적으로 상호작용하므로 반드시 익혀두어야 합니다.&lt;/li&gt;
&lt;li style=&quot;color: #333 !important; font-size: 16px !important; margin-bottom: 12px; line-height: 1.7;&quot;&gt;&lt;b&gt;CSS (학습 기간: 1주):&lt;/b&gt; 원하는 요소를 정확히 선택하는 선택자(Selector), 웹 페이지 레이아웃의 핵심인 박스 모델(margin, padding, border) 개념은 기본 중의 기본입니다. 나아가 현대적인 웹 레이아웃을 위한 Flexbox와 Grid, 그리고 다양한 기기에서 화면이 깨지지 않도록 하는 반응형 웹의 기초, 미디어 쿼리(&lt;code style=&quot;background: #f5f5f5; padding: 2px 6px; border-radius: 3px; font-size: 13px; color: #d63384; font-family: 'Courier New', monospace;&quot;&gt;@media&lt;/code&gt;)까지는 반드시 학습해야 합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;color: #333 !important; font-size: 16px !important; line-height: 1.8; margin-bottom: 20px;&quot; data-ke-size=&quot;size16&quot;&gt;가장 정확한 정보의 원천은 MDN Web Docs입니다. 모르는 개념이 생길 때마다 아래 공식 문서를 참고하는 습관을 들이세요.&lt;/p&gt;
&lt;ul style=&quot;list-style: disc; margin-left: 40px; margin-bottom: 24px;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;color: #333 !important; font-size: 16px !important; margin-bottom: 12px; line-height: 1.7;&quot;&gt;&lt;b&gt;추천 학습처:&lt;/b&gt;
&lt;ul style=&quot;list-style: disc; margin-left: 40px; margin-bottom: 24px;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;color: #333 !important; font-size: 16px !important; margin-bottom: 12px; line-height: 1.7;&quot;&gt;MDN Web Docs (HTML): &lt;a style=&quot;color: #00897b; text-decoration: none; border-bottom: 1px solid #00897b;&quot; href=&quot;https://developer.mozilla.org/ko/docs/Web/HTML&quot;&gt;https://developer.mozilla.org/ko/docs/Web/HTML&amp;lt;/a &amp;gt; &lt;/a&gt;&lt;/li&gt;
&lt;li style=&quot;color: #333 !important; font-size: 16px !important; margin-bottom: 12px; line-height: 1.7;&quot;&gt;MDN Web Docs (CSS): &lt;a style=&quot;color: #00897b;&quot; href=&quot;https://developer.mozilla.org/ko/docs/Web/CSS&quot;&gt;https://developer.mozilla.org/ko/docs/Web/CSS&amp;lt;/a &amp;gt; &lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;br style=&quot;display: none;&quot; /&gt;
&lt;h2 id=&quot;section-2&quot; style=&quot;font-weight: bold; font-size: 22px; border-left: 4px solid #00897b; border-radius: 4px; padding: 16px 20px; margin-top: 40px; margin-bottom: 24px; background: linear-gradient(to right, rgba(0, 137, 123, 0.05), transparent); color: #015249;&quot; data-ke-size=&quot;size26&quot;&gt;섹션 2: 자바스크립트 공부 순서 - 기초 체력 다지기 (Vanilla JS)&lt;/h2&gt;
&lt;p style=&quot;color: #333 !important; font-size: 16px !important; line-height: 1.8; margin-bottom: 20px;&quot; data-ke-size=&quot;size16&quot;&gt;React, Vue와 같은 프레임워크나 라이브러리는 결국 순수 자바스크립트(Vanilla JS)를 더 편리하게 사용하기 위해 만들어진 '도구'에 불과합니다. 기초 없이 도구부터 배우는 것은 구구단 없이 인수분해를 하려는 것과 같습니다. 탄탄한 기초는 어려운 문제를 만났을 때 해결의 실마리를 제공하고, 새로운 기술을 더 빠르게 습득하는 원동력이 됩니다. 이 &lt;b&gt;자바스크립트 공부 순서&lt;/b&gt;는 여러분의 개발자 커리어 전체를 지탱할 가장 중요한 단계입니다.&lt;/p&gt;
&lt;div style=&quot;text-align: center; margin: 32px 0; border-radius: 8px; overflow: hidden;&quot;&gt;&lt;img style=&quot;max-width: 100%; height: auto; border-radius: 8px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);&quot; src=&quot;https://files.dobbyblog.kr/view/5b31d8c5-a984-4e18-881f-91c6a12c0818.png&quot; alt=&quot;기본 문법부터 비동기 처리까지 자바스크립트 핵심 개념 학습을 보여주는 컴퓨터 화면&quot; /&gt;&lt;/div&gt;
&lt;p style=&quot;color: #333 !important; font-size: 16px !important; line-height: 1.8; margin-bottom: 20px;&quot; data-ke-size=&quot;size16&quot;&gt;아래 4단계 학습 순서를 따라 약 4주간 집중적으로 기초 체력을 길러보세요.&lt;/p&gt;
&lt;ul style=&quot;list-style: disc; margin-left: 40px; margin-bottom: 24px;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;color: #333 !important; font-size: 16px !important; margin-bottom: 12px; line-height: 1.7;&quot;&gt;&lt;b&gt;Step 1: 기본 문법 및 데이터 구조 (1주):&lt;/b&gt;
&lt;ul style=&quot;list-style: disc; margin-left: 40px; margin-bottom: 24px;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;color: #333 !important; font-size: 16px !important; margin-bottom: 12px; line-height: 1.7;&quot;&gt;프로그래밍의 가장 기초적인 단위인 변수 선언부터 시작합니다. 과거에 사용되던 &lt;code style=&quot;background: #f5f5f5; padding: 2px 6px; border-radius: 3px; font-size: 13px; color: #d63384; font-family: 'Courier New', monospace;&quot;&gt;var&lt;/code&gt;의 문제점을 이해하고, 왜 이제는 &lt;code style=&quot;background: #f5f5f5; padding: 2px 6px; border-radius: 3px; font-size: 13px; color: #d63384; font-family: 'Courier New', monospace;&quot;&gt;let&lt;/code&gt;과 &lt;code style=&quot;background: #f5f5f5; padding: 2px 6px; border-radius: 3px; font-size: 13px; color: #d63384; font-family: 'Courier New', monospace;&quot;&gt;const&lt;/code&gt;를 사용해야 하는지 명확히 알아야 합니다. 이후 데이터 타입, 연산자, 조건문, 반복문 등 기본적인 프로그래밍 개념을 익히고, 데이터를 담는 그릇인 배열과 객체의 기본 사용법을 실습합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li style=&quot;color: #333 !important; font-size: 16px !important; margin-bottom: 12px; line-height: 1.7;&quot;&gt;&lt;b&gt;Step 2: 함수와 핵심 개념 (1주):&lt;/b&gt;
&lt;ul style=&quot;list-style: disc; margin-left: 40px; margin-bottom: 24px;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;color: #333 !important; font-size: 16px !important; margin-bottom: 12px; line-height: 1.7;&quot;&gt;코드의 재사용성을 높이는 함수(Function)에 대해 깊이 있게 학습합니다. 함수 선언문과 표현식의 차이를 이해하고, 변수의 유효 범위를 결정하는 스코프(Scope)와 자바스크립트의 강력한 특징인 클로저(Closure) 개념을 예제를 통해 확실히 이해해야 합니다. 특히 배열 데이터를 다룰 때 필수로 사용되는 내장 메서드( &lt;code style=&quot;background: #f5f5f5; padding: 2px 6px; border-radius: 3px; font-size: 13px; color: #d63384; font-family: 'Courier New', monospace;&quot;&gt;map&lt;/code&gt;, &lt;code style=&quot;background: #f5f5f5; padding: 2px 6px; border-radius: 3px; font-size: 13px; color: #d63384; font-family: 'Courier New', monospace;&quot;&gt;filter&lt;/code&gt;, &lt;code style=&quot;background: #f5f5f5; padding: 2px 6px; border-radius: 3px; font-size: 13px; color: #d63384; font-family: 'Courier New', monospace;&quot;&gt;reduce&lt;/code&gt;, &lt;code style=&quot;background: #f5f5f5; padding: 2px 6px; border-radius: 3px; font-size: 13px; color: #d63384; font-family: 'Courier New', monospace;&quot;&gt;forEach&lt;/code&gt;)는 반드시 직접 코드를 짜보며 손에 익혀야 합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li style=&quot;color: #333 !important; font-size: 16px !important; margin-bottom: 12px; line-height: 1.7;&quot;&gt;&lt;b&gt;Step 3: 웹 페이지 조작 (DOM) &amp;amp; 이벤트 (1주):&lt;/b&gt;
&lt;ul style=&quot;list-style: disc; margin-left: 40px; margin-bottom: 24px;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;color: #333 !important; font-size: 16px !important; margin-bottom: 12px; line-height: 1.7;&quot;&gt;자바스크립트로 웹 페이지를 제어하는 방법을 배웁니다. HTML 문서를 객체 모델로 표현한 DOM(Document Object Model)이 무엇인지 이해하고, &lt;code style=&quot;background: #f5f5f5; padding: 2px 6px; border-radius: 3px; font-size: 13px; color: #d63384; font-family: 'Courier New', monospace;&quot;&gt;querySelector&lt;/code&gt;와 &lt;code style=&quot;background: #f5f5f5; padding: 2px 6px; border-radius: 3px; font-size: 13px; color: #d63384; font-family: 'Courier New', monospace;&quot;&gt;querySelectorAll&lt;/code&gt;을 이용해 원하는 HTML 요소를 선택하고, &lt;code style=&quot;background: #f5f5f5; padding: 2px 6px; border-radius: 3px; font-size: 13px; color: #d63384; font-family: 'Courier New', monospace;&quot;&gt;textContent&lt;/code&gt;나 &lt;code style=&quot;background: #f5f5f5; padding: 2px 6px; border-radius: 3px; font-size: 13px; color: #d63384; font-family: 'Courier New', monospace;&quot;&gt;classList&lt;/code&gt; 등으로 내용을 변경하고 스타일을 조작하는 방법을 학습합니다. 또한, 사용자의 클릭이나 키보드 입력 같은 행동에 반응하는 이벤트 리스너(&lt;code style=&quot;background: #f5f5f5; padding: 2px 6px; border-radius: 3px; font-size: 13px; color: #d63384; font-family: 'Courier New', monospace;&quot;&gt;addEventListener&lt;/code&gt;) 사용법을 익힙니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li style=&quot;color: #333 !important; font-size: 16px !important; margin-bottom: 12px; line-height: 1.7;&quot;&gt;&lt;b&gt;Step 4: 비동기 처리 (1주):&lt;/b&gt;
&lt;ul style=&quot;list-style: disc; margin-left: 40px; margin-bottom: 24px;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;color: #333 !important; font-size: 16px !important; margin-bottom: 12px; line-height: 1.7;&quot;&gt;서버에 데이터를 요청하고 받아오는 등 시간이 걸리는 작업을 처리하는 비동기 방식은 현대 웹 개발의 필수 요소입니다. 비동기 처리의 발전 과정인 콜백(Callback) -&amp;gt; &lt;code style=&quot;background: #f5f5f5; padding: 2px 6px; border-radius: 3px; font-size: 13px; color: #d63384; font-family: 'Courier New', monospace;&quot;&gt;Promise&lt;/code&gt;(.then, .catch) -&amp;gt; &lt;code style=&quot;background: #f5f5f5; padding: 2px 6px; border-radius: 3px; font-size: 13px; color: #d63384; font-family: 'Courier New', monospace;&quot;&gt;async/await&lt;/code&gt; 순서로 개념을 이해하면 흐름을 파악하기 쉽습니다. 마지막으로 &lt;code style=&quot;background: #f5f5f5; padding: 2px 6px; border-radius: 3px; font-size: 13px; color: #d63384; font-family: 'Courier New', monospace;&quot;&gt;fetch&lt;/code&gt; API를 사용해 외부 서버에서 데이터를 가져오는 간단한 실습을 통해 비동기 통신을 직접 경험해 보세요.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;br style=&quot;display: none;&quot; /&gt;
&lt;h2 id=&quot;section-3&quot; style=&quot;font-weight: bold; font-size: 22px; border-left: 4px solid #00897b; border-radius: 4px; padding: 16px 20px; margin-top: 40px; margin-bottom: 24px; background: linear-gradient(to right, rgba(0, 137, 123, 0.05), transparent); color: #015249;&quot; data-ke-size=&quot;size26&quot;&gt;섹션 3: 최신 기술 트렌드 따라잡기 (모던 JS - ES6+)&lt;/h2&gt;
&lt;p style=&quot;color: #333 !important; font-size: 16px !important; line-height: 1.8; margin-bottom: 20px;&quot; data-ke-size=&quot;size16&quot;&gt;2015년 이후 발표된 ES6(ECMAScript 2015) 이후의 자바스크립트 문법, 통칭 '모던 자바스크립트'는 이제 선택이 아닌 필수입니다. 현업에서는 거의 모든 프로젝트가 ES6+ 문법을 기반으로 작성되며, 코드의 가독성과 생산성을 극적으로 향상시켜줍니다. 여러분의 &lt;b&gt;자바스크립트 공부 순서&lt;/b&gt;에서 이 과정을 빠뜨린다면, 다른 개발자들의 코드를 이해하기조차 어려울 것입니다.&lt;/p&gt;
&lt;div style=&quot;text-align: center; margin: 32px 0; border-radius: 8px; overflow: hidden;&quot;&gt;&lt;img style=&quot;max-width: 100%; height: auto; border-radius: 8px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);&quot; src=&quot;https://files.dobbyblog.kr/view/dce400b6-fdc0-4ba6-ba23-dfdff7bd83c7.png&quot; alt=&quot;모던 자바스크립트 문법과 기존 코드의 비교를 보여주는 개발자 모니터 화면&quot; /&gt;&lt;/div&gt;
&lt;p style=&quot;color: #333 !important; font-size: 16px !important; line-height: 1.8; margin-bottom: 20px;&quot; data-ke-size=&quot;size16&quot;&gt;초보자가 반드시 알아야 할 ES6+의 핵심 기능들을 아래 표로 정리했습니다.&lt;/p&gt;
&lt;table style=&quot;width: 100%; border-collapse: collapse; border: 1px solid #e0e0e0; margin: 24px 0; border-radius: 8px; overflow: hidden; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th style=&quot;color: #015249 !important; font-size: 15px !important; font-weight: 600; border: 1px solid #e0e0e0; padding: 12px 16px; text-align: left; background: linear-gradient(to bottom, #e5faf7, #f0fdfc);&quot;&gt;기능&lt;/th&gt;
&lt;th style=&quot;color: #015249 !important; font-size: 15px !important; font-weight: 600; border: 1px solid #e0e0e0; padding: 12px 16px; text-align: left; background: linear-gradient(to bottom, #e5faf7, #f0fdfc);&quot;&gt;설명 및 간단한 예제&lt;/th&gt;
&lt;th style=&quot;color: #015249 !important; font-size: 15px !important; font-weight: 600; border: 1px solid #e0e0e0; padding: 12px 16px; text-align: left; background: linear-gradient(to bottom, #e5faf7, #f0fdfc);&quot;&gt;왜 필수인가?&lt;/th&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;color: #333 !important; font-size: 15px !important; border: 1px solid #e0e0e0; padding: 12px 16px; line-height: 1.6;&quot;&gt;&lt;b&gt;화살표 함수&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;color: #333 !important; font-size: 15px !important; border: 1px solid #e0e0e0; padding: 12px 16px; line-height: 1.6;&quot;&gt;&lt;code style=&quot;background: #f5f5f5; padding: 4px 8px; border-radius: 4px; font-size: 14px; color: #d63384; font-family: 'Courier New', monospace;&quot;&gt;const add = (a, b) =&amp;gt; a + b;&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;color: #333 !important; font-size: 15px !important; border: 1px solid #e0e0e0; padding: 12px 16px; line-height: 1.6;&quot;&gt;코드를 매우 간결하게 만들고, 복잡한 &lt;code style=&quot;background: #f5f5f5; padding: 2px 6px; border-radius: 3px; font-size: 13px; color: #d63384; font-family: 'Courier New', monospace;&quot;&gt;this&lt;/code&gt; 바인딩 문제를 해결해 줍니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;color: #333 !important; font-size: 15px !important; border: 1px solid #e0e0e0; padding: 12px 16px; line-height: 1.6;&quot;&gt;&lt;b&gt;&lt;code style=&quot;background: #f5f5f5; padding: 2px 6px; border-radius: 3px; font-size: 13px; color: #d63384; font-family: 'Courier New', monospace;&quot;&gt;let&lt;/code&gt;, &lt;code style=&quot;background: #f5f5f5; padding: 2px 6px; border-radius: 3px; font-size: 13px; color: #d63384; font-family: 'Courier New', monospace;&quot;&gt;const&lt;/code&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;color: #333 !important; font-size: 15px !important; border: 1px solid #e0e0e0; padding: 12px 16px; line-height: 1.6;&quot;&gt;블록 &lt;code style=&quot;background: #f5f5f5; padding: 2px 6px; border-radius: 3px; font-size: 13px; color: #d63384; font-family: 'Courier New', monospace;&quot;&gt;{}&lt;/code&gt; 스코프를 가지는 변수 선언&lt;/td&gt;
&lt;td style=&quot;color: #333 !important; font-size: 15px !important; border: 1px solid #e0e0e0; padding: 12px 16px; line-height: 1.6;&quot;&gt;&lt;code style=&quot;background: #f5f5f5; padding: 2px 6px; border-radius: 3px; font-size: 13px; color: #d63384; font-family: 'Courier New', monospace;&quot;&gt;var&lt;/code&gt;가 가진 호이스팅 및 스코프 문제를 원천적으로 방지해 버그 발생 가능성을 크게 줄입니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;color: #333 !important; font-size: 15px !important; border: 1px solid #e0e0e0; padding: 12px 16px; line-height: 1.6;&quot;&gt;&lt;b&gt;템플릿 리터럴&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;color: #333 !important; font-size: 15px !important; border: 1px solid #e0e0e0; padding: 12px 16px; line-height: 1.6;&quot;&gt;&lt;code style=&quot;background: #f5f5f5; padding: 4px 8px; border-radius: 4px; font-size: 14px; color: #d63384; font-family: 'Courier New', monospace;&quot;&gt;`Hello, ${name}!`&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;color: #333 !important; font-size: 15px !important; border: 1px solid #e0e0e0; padding: 12px 16px; line-height: 1.6;&quot;&gt;백틱(`) 기호를 이용해 문자열 안에 변수나 표현식을 쉽게 삽입할 수 있어 가독성이 향상됩니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;color: #333 !important; font-size: 15px !important; border: 1px solid #e0e0e0; padding: 12px 16px; line-height: 1.6;&quot;&gt;&lt;b&gt;구조 분해 할당&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;color: #333 !important; font-size: 15px !important; border: 1px solid #e0e0e0; padding: 12px 16px; line-height: 1.6;&quot;&gt;&lt;code style=&quot;background: #f5f5f5; padding: 4px 8px; border-radius: 4px; font-size: 14px; color: #d63384; font-family: 'Courier New', monospace;&quot;&gt;const { name, age } = user;&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;color: #333 !important; font-size: 15px !important; border: 1px solid #e0e0e0; padding: 12px 16px; line-height: 1.6;&quot;&gt;객체나 배열의 속성을 쉽고 직관적으로 추출하여 변수에 할당할 수 있습니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;color: #333 !important; font-size: 15px !important; border: 1px solid #e0e0e0; padding: 12px 16px; line-height: 1.6;&quot;&gt;&lt;b&gt;스프레드 문법&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;color: #333 !important; font-size: 15px !important; border: 1px solid #e0e0e0; padding: 12px 16px; line-height: 1.6;&quot;&gt;&lt;code style=&quot;background: #f5f5f5; padding: 4px 8px; border-radius: 4px; font-size: 14px; color: #d63384; font-family: 'Courier New', monospace;&quot;&gt;const newArr = [...oldArr, newItem];&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;color: #333 !important; font-size: 15px !important; border: 1px solid #e0e0e0; padding: 12px 16px; line-height: 1.6;&quot;&gt;&lt;code style=&quot;background: #f5f5f5; padding: 2px 6px; border-radius: 3px; font-size: 13px; color: #d63384; font-family: 'Courier New', monospace;&quot;&gt;...&lt;/code&gt;을 이용해 배열이나 객체를 쉽게 복사하고 합칠 수 있어 불변성 관리에 매우 유용합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;color: #333 !important; font-size: 15px !important; border: 1px solid #e0e0e0; padding: 12px 16px; line-height: 1.6;&quot;&gt;&lt;b&gt;모듈 시스템&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;color: #333 !important; font-size: 15px !important; border: 1px solid #e0e0e0; padding: 12px 16px; line-height: 1.6;&quot;&gt;&lt;code style=&quot;background: #f5f5f5; padding: 4px 8px; border-radius: 4px; font-size: 14px; color: #d63384; font-family: 'Courier New', monospace;&quot;&gt;import / export&lt;/code&gt;&lt;/td&gt;
&lt;td style=&quot;color: #333 !important; font-size: 15px !important; border: 1px solid #e0e0e0; padding: 12px 16px; line-height: 1.6;&quot;&gt;코드를 기능별 파일로 분리(모듈화)하여 재사용성을 높이고 프로젝트 관리를 용이하게 합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;color: #333 !important; font-size: 16px !important; line-height: 1.8; margin-bottom: 20px;&quot; data-ke-size=&quot;size16&quot;&gt;모던 자바스크립트의 각 기능에 대한 상세한 설명과 예제는 'Modern JavaScript Tutorial' 사이트에서 무료로 학습할 수 있습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style: disc; margin-left: 40px; margin-bottom: 24px;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;color: #333 !important; font-size: 16px !important; margin-bottom: 12px; line-height: 1.7;&quot;&gt;&lt;b&gt;추천 학습처:&lt;/b&gt; &lt;a style=&quot;color: #00897b; text-decoration: none; border-bottom: 1px solid #00897b;&quot; href=&quot;https://ko.javascript.info/&quot;&gt;https://ko.javascript.info/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;br style=&quot;display: none;&quot; /&gt;
&lt;h2 id=&quot;section-4&quot; style=&quot;font-weight: bold; font-size: 22px; border-left: 4px solid #00897b; border-radius: 4px; padding: 16px 20px; margin-top: 40px; margin-bottom: 24px; background: linear-gradient(to right, rgba(0, 137, 123, 0.05), transparent); color: #015249;&quot; data-ke-size=&quot;size26&quot;&gt;섹션 4: 개발 효율을 200% 높이는 필수 도구들&lt;/h2&gt;
&lt;p style=&quot;color: #333 !important; font-size: 16px !important; line-height: 1.8; margin-bottom: 20px;&quot; data-ke-size=&quot;size16&quot;&gt;훌륭한 목수는 연장을 탓하지 않지만, 좋은 연장은 작업 효율을 극적으로 높여줍니다. 개발자에게도 코딩 실력만큼이나 중요한 것이 바로 개발 도구를 잘 다루는 능력입니다. 지금 소개하는 도구들은 여러분의 학습과 개발 효율을 200% 이상 끌어올려 줄 필수 장비와도 같습니다.&lt;/p&gt;
&lt;div style=&quot;text-align: center; margin: 32px 0; border-radius: 8px; overflow: hidden;&quot;&gt;&lt;img style=&quot;max-width: 100%; height: auto; border-radius: 8px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);&quot; src=&quot;https://files.dobbyblog.kr/view/826897d0-6fce-4331-be0c-a9a1ce9b0357.png&quot; alt=&quot;VS Code와 GitHub, Node.js, npm 같은 필수 개발 도구들이 놓인 개발자 책상 풍경&quot; /&gt;&lt;/div&gt;
&lt;ul style=&quot;list-style: disc; margin-left: 40px; margin-bottom: 24px;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;color: #333 !important; font-size: 16px !important; margin-bottom: 12px; line-height: 1.7;&quot;&gt;&lt;b&gt;버전 관리 시스템: Git &amp;amp; GitHub&lt;/b&gt;
&lt;ul style=&quot;list-style: disc; margin-left: 40px; margin-bottom: 24px;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;color: #333 !important; font-size: 16px !important; margin-bottom: 12px; line-height: 1.7;&quot;&gt;&lt;b&gt;설명:&lt;/b&gt; Git은 코드의 변경 이력을 사진 찍듯 저장하고 관리하는 '버전 관리' 도구이며, GitHub는 Git으로 관리하는 프로젝트를 다른 사람과 공유하고 협업할 수 있는 웹 서비스입니다. &lt;code style=&quot;background: #f5f5f5; padding: 2px 6px; border-radius: 3px; font-size: 13px; color: #d63384; font-family: 'Courier New', monospace;&quot;&gt;clone&lt;/code&gt;, &lt;code style=&quot;background: #f5f5f5; padding: 2px 6px; border-radius: 3px; font-size: 13px; color: #d63384; font-family: 'Courier New', monospace;&quot;&gt;add&lt;/code&gt;, &lt;code style=&quot;background: #f5f5f5; padding: 2px 6px; border-radius: 3px; font-size: 13px; color: #d63384; font-family: 'Courier New', monospace;&quot;&gt;commit&lt;/code&gt;, &lt;code style=&quot;background: #f5f5f5; padding: 2px 6px; border-radius: 3px; font-size: 13px; color: #d63384; font-family: 'Courier New', monospace;&quot;&gt;push&lt;/code&gt;, &lt;code style=&quot;background: #f5f5f5; padding: 2px 6px; border-radius: 3px; font-size: 13px; color: #d63384; font-family: 'Courier New', monospace;&quot;&gt;pull&lt;/code&gt;과 같은 기본 명령어를 익히고, 작은 토이 프로젝트라도 GitHub에 꾸준히 올리는 습관을 들이세요. 이는 여러분의 성실한 학습 과정을 보여주는 최고의 포트폴리오가 됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li style=&quot;color: #333 !important; font-size: 16px !important; margin-bottom: 12px; line-height: 1.7;&quot;&gt;&lt;b&gt;코드 에디터: Visual Studio Code (VS Code)&lt;/b&gt;
&lt;ul style=&quot;list-style: disc; margin-left: 40px; margin-bottom: 24px;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;color: #333 !important; font-size: 16px !important; margin-bottom: 12px; line-height: 1.7;&quot;&gt;&lt;b&gt;설명:&lt;/b&gt; 현재 전 세계 개발자들이 가장 많이 사용하는 압도적인 1위 코드 에디터입니다. 강력한 기능과 풍부한 확장 프로그램을 통해 개발 환경을 자신에게 맞게 최적화할 수 있습니다.&lt;/li&gt;
&lt;li style=&quot;color: #333 !important; font-size: 16px !important; margin-bottom: 12px; line-height: 1.7;&quot;&gt;&lt;b&gt;추천 확장 프로그램:&lt;/b&gt;
&lt;ul style=&quot;list-style: disc; margin-left: 40px; margin-bottom: 24px;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;color: #333 !important; font-size: 16px !important; margin-bottom: 12px; line-height: 1.7;&quot;&gt;&lt;b&gt;Prettier:&lt;/b&gt; 코드를 저장할 때마다 정해진 규칙에 따라 자동으로 정렬해줘 항상 깔끔한 코드를 유지하게 돕습니다.&lt;/li&gt;
&lt;li style=&quot;color: #333 !important; font-size: 16px !important; margin-bottom: 12px; line-height: 1.7;&quot;&gt;&lt;b&gt;ESLint:&lt;/b&gt; 코드에서 잠재적인 오류나 스타일 규칙 위반을 실시간으로 찾아내 버그를 사전에 예방합니다.&lt;/li&gt;
&lt;li style=&quot;color: #333 !important; font-size: 16px !important; margin-bottom: 12px; line-height: 1.7;&quot;&gt;&lt;b&gt;Live Server:&lt;/b&gt; HTML/CSS/JS 파일을 저장하는 순간, 브라우저가 자동으로 새로고침되어 변경 사항을 즉시 확인할 수 있습니다.&lt;/li&gt;
&lt;li style=&quot;color: #333 !important; font-size: 16px !important; margin-bottom: 12px; line-height: 1.7;&quot;&gt;&lt;b&gt;GitLens:&lt;/b&gt; VS Code 내에서 Git의 변경 이력을 시각적으로 편리하게 추적할 수 있도록 도와줍니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li style=&quot;color: #333 !important; font-size: 16px !important; margin-bottom: 12px; line-height: 1.7;&quot;&gt;&lt;b&gt;패키지 매니저: Node.js &amp;amp; npm&lt;/b&gt;
&lt;ul style=&quot;list-style: disc; margin-left: 40px; margin-bottom: 24px;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;color: #333 !important; font-size: 16px !important; margin-bottom: 12px; line-height: 1.7;&quot;&gt;&lt;b&gt;설명:&lt;/b&gt; 본래 자바스크립트는 브라우저 안에서만 실행 가능했지만, Node.js는 브라우저 밖(예: 내 컴퓨터)에서도 자바스크립트를 실행할 수 있게 해주는 환경입니다. npm은 Node.js를 설치할 때 함께 설치되는 '패키지 매니저'로, 전 세계 개발자들이 만들어 놓은 유용한 코드(패키지)들을 명령어 한 줄로 쉽게 설치하고 관리할 수 있게 해줍니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;color: #333 !important; font-size: 16px !important; line-height: 1.8; margin-bottom: 20px;&quot; data-ke-size=&quot;size16&quot;&gt;2024년의 자바스크립트 트렌드를 살펴보면, 이러한 개발 도구 생태계의 중요성은 더욱 커지고 있습니다. 최신 동향을 파악하는 것은 꾸준한 성장을 위해 필수적입니다. (참고: 요즘IT - 2024년 자바스크립트 트렌드 돌아보기 &lt;a style=&quot;color: #00897b; text-decoration: none; border-bottom: 1px solid #00897b;&quot; href=&quot;https://yozm.wishket.com/magazine/detail/2961/&quot;&gt;https://yozm.wishket.com/magazine/detail/2961/&amp;lt;/a &amp;gt;) &lt;/a&gt;&lt;/p&gt;
&lt;br style=&quot;display: none;&quot; /&gt;
&lt;h2 id=&quot;section-5&quot; style=&quot;font-weight: bold; font-size: 22px; border-left: 4px solid #00897b; border-radius: 4px; padding: 16px 20px; margin-top: 40px; margin-bottom: 24px; background: linear-gradient(to right, rgba(0, 137, 123, 0.05), transparent); color: #015249;&quot; data-ke-size=&quot;size26&quot;&gt;섹션 5: 다음 스텝 - 프레임워크 &amp;amp; 라이브러리 선택 가이드&lt;/h2&gt;
&lt;p style=&quot;color: #333 !important; font-size: 16px !important; line-height: 1.8; margin-bottom: 20px;&quot; data-ke-size=&quot;size16&quot;&gt;순수 자바스크립트로 기초를 탄탄히 다졌다면, 이제 더 복잡하고 규모가 큰 애플리케이션을 효율적으로 만들기 위해 프레임워크를 배울 차례입니다. 프레임워크는 자주 사용되는 기능들을 미리 만들어 놓은 '뼈대'와 같아서, 개발자가 비즈니스 로직에만 집중할 수 있도록 도와줍니다. 2026년 현재, 채용 시장과 기술 생태계를 종합적으로 고려했을 때 최고의 선택지를 알려드립니다. 이 단계는 여러분의 &lt;b&gt;자바스크립트 독학 로드맵&lt;/b&gt;에서 실무 역량을 갖추는 중요한 전환점이 될 것입니다.&lt;/p&gt;
&lt;div style=&quot;text-align: center; margin: 32px 0; border-radius: 8px; overflow: hidden;&quot;&gt;&lt;img style=&quot;max-width: 100%; height: auto; border-radius: 8px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);&quot; src=&quot;https://files.dobbyblog.kr/view/beddac2b-a440-4a29-bc5d-6b7e9203b664.png&quot; alt=&quot;2026년 자바스크립트 프레임워크 선택을 위한 React와 Vue의 로고와 인기 통계 차트&quot; /&gt;&lt;/div&gt;
&lt;p style=&quot;color: #333 !important; font-size: 16px !important; line-height: 1.8; margin-bottom: 20px;&quot; data-ke-size=&quot;size16&quot;&gt;매년 전 세계 자바스크립트 개발자들을 대상으로 실시하는 설문조사 'State of JS'의 최신 데이터를 보면 기술 트렌드를 명확히 파악할 수 있습니다. 이를 바탕으로 2026년 최고의 프레임워크 Top 2를 비교해 보겠습니다.&lt;/p&gt;
&lt;table style=&quot;width: 100%; border-collapse: collapse; border: 1px solid #e0e0e0; margin: 24px 0; border-radius: 8px; overflow: hidden; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th style=&quot;color: #015249 !important; font-size: 15px !important; font-weight: 600; border: 1px solid #e0e0e0; padding: 12px 16px; text-align: left; background: linear-gradient(to bottom, #e5faf7, #f0fdfc);&quot;&gt;구분&lt;/th&gt;
&lt;th style=&quot;color: #015249 !important; font-size: 15px !important; font-weight: 600; border: 1px solid #e0e0e0; padding: 12px 16px; text-align: left; background: linear-gradient(to bottom, #e5faf7, #f0fdfc);&quot;&gt;React&lt;/th&gt;
&lt;th style=&quot;color: #015249 !important; font-size: 15px !important; font-weight: 600; border: 1px solid #e0e0e0; padding: 12px 16px; text-align: left; background: linear-gradient(to bottom, #e5faf7, #f0fdfc);&quot;&gt;Vue&lt;/th&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;color: #333 !important; font-size: 15px !important; border: 1px solid #e0e0e0; padding: 12px 16px; line-height: 1.6;&quot;&gt;&lt;b&gt;개발 주체&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;color: #333 !important; font-size: 15px !important; border: 1px solid #e0e0e0; padding: 12px 16px; line-height: 1.6;&quot;&gt;메타(구 페이스북)&lt;/td&gt;
&lt;td style=&quot;color: #333 !important; font-size: 15px !important; border: 1px solid #e0e0e0; padding: 12px 16px; line-height: 1.6;&quot;&gt;에반 유 (개인)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;color: #333 !important; font-size: 15px !important; border: 1px solid #e0e0e0; padding: 12px 16px; line-height: 1.6;&quot;&gt;&lt;b&gt;핵심 특징&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;color: #333 !important; font-size: 15px !important; border: 1px solid #e0e0e0; padding: 12px 16px; line-height: 1.6;&quot;&gt;컴포넌트 기반 아키텍처, 방대한 생태계&lt;/td&gt;
&lt;td style=&quot;color: #333 !important; font-size: 15px !important; border: 1px solid #e0e0e0; padding: 12px 16px; line-height: 1.6;&quot;&gt;점진적인 학습 곡선, 쉽고 직관적인 문법&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;color: #333 !important; font-size: 15px !important; border: 1px solid #e0e0e0; padding: 12px 16px; line-height: 1.6;&quot;&gt;&lt;b&gt;장점&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;color: #333 !important; font-size: 15px !important; border: 1px solid #e0e0e0; padding: 12px 16px; line-height: 1.6;&quot;&gt;압도적인 채용 공고 수, 가장 큰 커뮤니티, 풍부한 학습 자료&lt;/td&gt;
&lt;td style=&quot;color: #333 !important; font-size: 15px !important; border: 1px solid #e0e0e0; padding: 12px 16px; line-height: 1.6;&quot;&gt;공식 문서가 매우 친절하고 배우기 쉬움&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;color: #333 !important; font-size: 15px !important; border: 1px solid #e0e0e0; padding: 12px 16px; line-height: 1.6;&quot;&gt;&lt;b&gt;추천 대상&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;color: #333 !important; font-size: 15px !important; border: 1px solid #e0e0e0; padding: 12px 16px; line-height: 1.6;&quot;&gt;취업을 최우선으로 고려하는 사람, 안정적이고 검증된 기술 스택을 선호하는 사람&lt;/td&gt;
&lt;td style=&quot;color: #333 !important; font-size: 15px !important; border: 1px solid #e0e0e0; padding: 12px 16px; line-height: 1.6;&quot;&gt;React보다 조금 더 쉽고 직관적인 것을 선호하는 사람, 개인 프로젝트에 적합&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;color: #333 !important; font-size: 16px !important; line-height: 1.8; margin-bottom: 20px;&quot; data-ke-size=&quot;size16&quot;&gt;&quot;그래서 둘 중 어떤 것을 먼저 배워야 하나요?&quot;라는 질문에 대한 답은 명확합니다. 채용 시장의 규모, 커뮤니티의 활성도, 그리고 참고할 수 있는 자료의 양을 종합적으로 고려했을 때, 첫 프레임워크로는 &lt;b&gt;React&lt;/b&gt; 학습을 가장 강력하게 추천합니다. React를 먼저 익히면 다른 프레임워크를 배우는 것도 훨씬 수월해집니다.&lt;/p&gt;
&lt;ul style=&quot;list-style: disc; margin-left: 40px; margin-bottom: 24px;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;color: #333 !important; font-size: 16px !important; margin-bottom: 12px; line-height: 1.7;&quot;&gt;&lt;b&gt;참고 자료:&lt;/b&gt; State of JS (&lt;a style=&quot;color: #00897b; text-decoration: none; border-bottom: 1px solid #00897b;&quot; href=&quot;https://stateofjs.com/ko-KR&quot;&gt;https://stateofjs.com/ko-KR&amp;lt;/a &amp;gt;) &lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;br style=&quot;display: none;&quot; /&gt;
&lt;h2 id=&quot;section-6&quot; style=&quot;font-weight: bold; font-size: 22px; border-left: 4px solid #00897b; border-radius: 4px; padding: 16px 20px; margin-top: 40px; margin-bottom: 24px; background: linear-gradient(to right, rgba(0, 137, 123, 0.05), transparent); color: #015249;&quot; data-ke-size=&quot;size26&quot;&gt;섹션 6: 지식을 진짜 '내 것'으로 만드는 실전 프로젝트 제안&lt;/h2&gt;
&lt;p style=&quot;color: #333 !important; font-size: 16px !important; line-height: 1.8; margin-bottom: 20px;&quot; data-ke-size=&quot;size16&quot;&gt;강의를 듣고 책을 읽는 이론 학습만으로는 절대 실력이 늘지 않습니다. 수영하는 법을 책으로만 배울 수 없듯이, 코딩도 직접 만들어보는 과정을 통해 비로소 지식이 '내 것'이 됩니다. 작은 장난감이라도 괜찮으니, 배운 내용을 활용해 직접 무언가를 만들어보는 프로젝트 경험은 여러분의 &lt;b&gt;초보 코딩 공부 계획&lt;/b&gt;에서 가장 핵심적인 부분입니다.&lt;/p&gt;
&lt;div style=&quot;text-align: center; margin: 32px 0; border-radius: 8px; overflow: hidden;&quot;&gt;&lt;img style=&quot;max-width: 100%; height: auto; border-radius: 8px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);&quot; src=&quot;https://files.dobbyblog.kr/view/689a5cdd-b26c-4bfb-bc71-911f79dd6602.png&quot; alt=&quot;실전 프로젝트를 통해 배우는 초보 개발자의 열정적인 코딩 모습&quot; /&gt;&lt;/div&gt;
&lt;p style=&quot;color: #333 !important; font-size: 16px !important; line-height: 1.8; margin-bottom: 20px;&quot; data-ke-size=&quot;size16&quot;&gt;자신의 수준에 맞는 프로젝트를 선택하여 도전해 보세요.&lt;/p&gt;
&lt;ul style=&quot;list-style: disc; margin-left: 40px; margin-bottom: 24px;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;color: #333 !important; font-size: 16px !important; margin-bottom: 12px; line-height: 1.7;&quot;&gt;&lt;b&gt;초급 (Vanilla JS, DOM/이벤트 연습):&lt;/b&gt;
&lt;ul style=&quot;list-style: disc; margin-left: 40px; margin-bottom: 24px;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;color: #333 !important; font-size: 16px !important; margin-bottom: 12px; line-height: 1.7;&quot;&gt;&lt;b&gt;투두 리스트(Todo List):&lt;/b&gt; 할 일을 입력받아 목록에 추가하고, 완료된 항목을 체크하거나 삭제하는 기능을 구현합니다. 기본적인 DOM 조작과 이벤트 리스너 사용법을 마스터하기에 가장 좋은 프로젝트입니다.&lt;/li&gt;
&lt;li style=&quot;color: #333 !important; font-size: 16px !important; margin-bottom: 12px; line-height: 1.7;&quot;&gt;&lt;b&gt;간단한 계산기:&lt;/b&gt; 버튼 클릭 이벤트를 처리하고, 입력된 숫자를 바탕으로 사칙연산을 수행하는 로직을 구현하며 자바스크립트의 기본 로직 흐름을 연습합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li style=&quot;color: #333 !important; font-size: 16px !important; margin-bottom: 12px; line-height: 1.7;&quot;&gt;&lt;b&gt;중급 (API 연동, 비동기 처리 연습):&lt;/b&gt;
&lt;ul style=&quot;list-style: disc; margin-left: 40px; margin-bottom: 24px;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;color: #333 !important; font-size: 16px !important; margin-bottom: 12px; line-height: 1.7;&quot;&gt;&lt;b&gt;영화 정보 검색 사이트:&lt;/b&gt; 무료 영화 데이터베이스 API(예: &lt;a style=&quot;color: #00897b; text-decoration: none; border-bottom: 1px solid #00897b;&quot; href=&quot;http://www.omdbapi.com/&quot;&gt;OMDB API&lt;/a&gt;)를 활용하여 영화를 검색하고 상세 정보를 화면에 보여주는 웹 앱을 만듭니다. &lt;code style=&quot;background: #f5f5f5; padding: 2px 6px; border-radius: 3px; font-size: 13px; color: #d63384; font-family: 'Courier New', monospace;&quot;&gt;fetch&lt;/code&gt;와 &lt;code style=&quot;background: #f5f5f5; padding: 2px 6px; border-radius: 3px; font-size: 13px; color: #d63384; font-family: 'Courier New', monospace;&quot;&gt;async/await&lt;/code&gt;를 사용해 비동기 통신을 실제로 경험할 수 있습니다.&lt;/li&gt;
&lt;li style=&quot;color: #333 !important; font-size: 16px !important; margin-bottom: 12px; line-height: 1.7;&quot;&gt;&lt;b&gt;날씨 앱:&lt;/b&gt; &lt;a style=&quot;color: #00897b; text-decoration: none; border-bottom: 1px solid #00897b;&quot; href=&quot;https://openweathermap.org/api&quot;&gt;OpenWeatherMap API&lt;/a&gt;를 사용하여 현재 위치나 특정 도시의 날씨 정보를 API로 받아와 보여줍니다. API 데이터를 가공하여 사용자에게 유용한 정보로 보여주는 방법을 연습할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li style=&quot;color: #333 !important; font-size: 16px !important; margin-bottom: 12px; line-height: 1.7;&quot;&gt;&lt;b&gt;고급 (프레임워크 활용):&lt;/b&gt;
&lt;ul style=&quot;list-style: disc; margin-left: 40px; margin-bottom: 24px;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;color: #333 !important; font-size: 16px !important; margin-bottom: 12px; line-height: 1.7;&quot;&gt;&lt;b&gt;블로그 포트폴리오:&lt;/b&gt; React를 사용하여 자신을 소개하는 블로그 형태의 포트폴리오 사이트를 만듭니다. 페이지 이동(라우팅)과 코드 재사용(컴포넌트화) 등 프레임워크의 핵심 개념을 연습하기에 좋습니다.&lt;/li&gt;
&lt;li style=&quot;color: #333 !important; font-size: 16px !important; margin-bottom: 12px; line-height: 1.7;&quot;&gt;&lt;b&gt;쇼핑몰 장바구니:&lt;/b&gt; 상품 목록 데이터를 화면에 보여주고, '담기' 버튼을 누르면 장바구니에 상품이 추가되고 수량과 총액이 변경되는 기능을 구현합니다. 복잡한 상태를 관리하는 방법을 익힐 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;br style=&quot;display: none;&quot; /&gt;
&lt;h2 id=&quot;section-7&quot; style=&quot;font-weight: bold; font-size: 22px; border-left: 4px solid #00897b; border-radius: 4px; padding: 16px 20px; margin-top: 40px; margin-bottom: 24px; background: linear-gradient(to right, rgba(0, 137, 123, 0.05), transparent); color: #015249;&quot; data-ke-size=&quot;size26&quot;&gt;섹션 7: 성장을 멈추지 않기 위한 추천 학습 자료&lt;/h2&gt;
&lt;p style=&quot;color: #333 !important; font-size: 16px !important; line-height: 1.8; margin-bottom: 20px;&quot; data-ke-size=&quot;size16&quot;&gt;개발 생태계는 하루가 다르게 변화하고 발전합니다. 따라서 꾸준한 학습은 개발자에게 선택이 아닌 생존의 문제입니다. 아래에 소개하는 자료들을 브라우저에 북마크해두고, 필요할 때마다 혹은 꾸준히 방문하여 지식을 업데이트하는 습관을 들이세요.&lt;/p&gt;
&lt;div style=&quot;text-align: center; margin: 32px 0; border-radius: 8px; overflow: hidden;&quot;&gt;&lt;img style=&quot;max-width: 100%; height: auto; border-radius: 8px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);&quot; src=&quot;https://files.dobbyblog.kr/view/cacbe153-f65b-4e14-aaf3-0f5463a44440.png&quot; alt=&quot;꾸준한 성장을 위한 자바스크립트 추천 학습 자료 웹사이트들의 화면 모음&quot; /&gt;&lt;/div&gt;
&lt;ul style=&quot;list-style: disc; margin-left: 40px; margin-bottom: 24px;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;color: #333 !important; font-size: 16px !important; margin-bottom: 12px; line-height: 1.7;&quot;&gt;&lt;b&gt;공식 문서 (가장 정확한 정보의 원천):&lt;/b&gt;
&lt;ul style=&quot;list-style: disc; margin-left: 40px; margin-bottom: 24px;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;color: #333 !important; font-size: 16px !important; margin-bottom: 12px; line-height: 1.7;&quot;&gt;&lt;b&gt;MDN Web Docs (&lt;a style=&quot;color: #00897b; text-decoration: none; border-bottom: 1px solid #00897b;&quot; href=&quot;https://developer.mozilla.org/ko/&quot;&gt;https://developer.mozilla.org/ko/&amp;lt;/a &amp;gt;):&amp;lt;/strong &amp;gt; 자바스크립트를 포함한 모든 웹 기술의 바이블입니다. 개념이 헷갈리거나 특정 기능의 정확한 사용법이 궁금할 때 가장 먼저 찾아봐야 할 곳입니다. &lt;/a&gt;&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li style=&quot;color: #333 !important; font-size: 16px !important; margin-bottom: 12px; line-height: 1.7;&quot;&gt;&lt;b&gt;무료 온라인 강의 &amp;amp; 튜토리얼 (체계적인 학습):&lt;/b&gt;
&lt;ul style=&quot;list-style: disc; margin-left: 40px; margin-bottom: 24px;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;color: #333 !important; font-size: 16px !important; margin-bottom: 12px; line-height: 1.7;&quot;&gt;&lt;b&gt;freeCodeCamp (&lt;a style=&quot;color: #00897b; text-decoration: none; border-bottom: 1px solid #00897b;&quot; href=&quot;https://www.freecodecamp.org/&quot;&gt;https://www.freecodecamp.org/&amp;lt;/a &amp;gt;):&amp;lt;/strong &amp;gt; 'JavaScript Algorithms and Data Structures' 과정을 통해 수백 시간 분량의 실습 기반 커리큘럼을 모두 무료로 제공합니다. 전 세계 수많은 개발자가 이 과정을 통해 커리어를 시작했습니다. &lt;/a&gt;&lt;/b&gt;&lt;/li&gt;
&lt;li style=&quot;color: #333 !important; font-size: 16px !important; margin-bottom: 12px; line-height: 1.7;&quot;&gt;&lt;b&gt;노마드 코더 (Nomad Coders) (&lt;a style=&quot;color: #00897b; text-decoration: none; border-bottom: 1px solid #00897b;&quot; href=&quot;https://nomadcoders.co/&quot;&gt;https://nomadcoders.co/&amp;lt;/a &amp;gt;):&amp;lt;/strong &amp;gt; '바닐라 JS로 크롬 앱 만들기' 같은 클론 코딩 프로젝트를 통해 실전 기술을 재미있게 배울 수 있는 최고의 한국어 유튜브 채널 및 강의 사이트입니다. &lt;/a&gt;&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li style=&quot;color: #333 !important; font-size: 16px !important; margin-bottom: 12px; line-height: 1.7;&quot;&gt;&lt;b&gt;개발자 커뮤니티 (문제 해결 및 트렌드 파악):&lt;/b&gt;
&lt;ul style=&quot;list-style: disc; margin-left: 40px; margin-bottom: 24px;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;color: #333 !important; font-size: 16px !important; margin-bottom: 12px; line-height: 1.7;&quot;&gt;&lt;b&gt;Stack Overflow:&lt;/b&gt; '개발자들의 지식인'과 같은 곳입니다. 개발하다 막히는 문제가 생겼을 때, 에러 메시지를 그대로 검색하면 거의 모든 해답을 이곳에서 찾을 수 있습니다.&lt;/li&gt;
&lt;li style=&quot;color: #333 !important; font-size: 16px !important; margin-bottom: 12px; line-height: 1.7;&quot;&gt;&lt;b&gt;Velog:&lt;/b&gt; 국내의 대표적인 기술 블로그 서비스입니다. 다른 개발자들이 어떤 것을 공부하고, 문제를 어떻게 해결했는지 경험을 공유하며 함께 성장할 수 있는 좋은 공간입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;br style=&quot;display: none;&quot; /&gt;
&lt;h2 id=&quot;faq&quot; style=&quot;font-weight: bold; font-size: 22px; border-left: 4px solid #00897b; border-radius: 4px; padding: 16px 20px; margin-top: 40px; margin-bottom: 24px; background: linear-gradient(to right, rgba(0, 137, 123, 0.05), transparent); color: #015249;&quot; data-ke-size=&quot;size26&quot;&gt;마무리: FAQ 및 성공적인 독학을 위한 마지막 조언&lt;/h2&gt;
&lt;p style=&quot;color: #333 !important; font-size: 16px !important; line-height: 1.8; margin-bottom: 20px;&quot; data-ke-size=&quot;size16&quot;&gt;이 긴 로드맵을 완주하기 위해 가장 중요한 단 하나의 키워드를 꼽으라면 바로 '꾸준함'입니다. 마지막으로 독학 과정에서 많은 분이 궁금해하는 질문에 답해드리고, 지치지 않고 꾸준히 나아갈 수 있는 몇 가지 팁을 드리며 글을 마무리하겠습니다.&lt;/p&gt;
&lt;div style=&quot;text-align: center; margin: 32px 0; border-radius: 8px; overflow: hidden;&quot;&gt;&lt;img style=&quot;max-width: 100%; height: auto; border-radius: 8px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);&quot; src=&quot;https://files.dobbyblog.kr/view/d0bf39df-8bd2-4f9a-a678-e2a9c8f73a91.png&quot; alt=&quot;꾸준한 학습과 문제 해결 노력을 상징하는 개발자와 시간, 에러 메시지 이미지&quot; /&gt;&lt;/div&gt;
&lt;p style=&quot;color: #333 !important; font-size: 16px !important; line-height: 1.8; margin-bottom: 20px;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;FAQ (자주 묻는 질문):&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style: disc; margin-left: 40px; margin-bottom: 24px;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;color: #333 !important; font-size: 16px !important; margin-bottom: 12px; line-height: 1.7;&quot;&gt;&lt;b&gt;Q1: 자바스크립트 독학, 현실적으로 얼마나 걸릴까요?&amp;lt;/strong &amp;gt;&lt;br /&gt;A: 하루 2~3시간 꾸준히 투자한다는 전제하에, 이 로드맵의 기초 문법부터 React 프로젝트까지 완수하는 데 평균적으로 약 3~6개월이 소요됩니다. 하지만 기간 자체보다 중요한 것은 매일 30분이라도 코드를 들여다보는 '습관'을 만드는 것입니다. &lt;/b&gt;&lt;/li&gt;
&lt;li style=&quot;color: #333 !important; font-size: 16px !important; margin-bottom: 12px; line-height: 1.7;&quot;&gt;&lt;b&gt;Q2: 초보자들이 가장 많이 하는 실수는 무엇인가요?&amp;lt;/strong &amp;gt;&lt;br /&gt;A: 크게 세 가지입니다. 첫째, 기초를 소홀히 하고 최신 프레임워크로 바로 넘어가는 것. 둘째, 강의를 눈으로만 보고 직접 코드를 타이핑해보지 않는 것. 셋째, 에러가 발생했을 때 고민 없이 바로 정답을 찾아보는 것입니다. 에러는 성장의 기회입니다. 최소 10분은 스스로 원인을 파악하려 노력하는 습관을 들이세요. &lt;/b&gt;&lt;/li&gt;
&lt;li style=&quot;color: #333 !important; font-size: 16px !important; margin-bottom: 12px; line-height: 1.7;&quot;&gt;&lt;b&gt;Q3: 모르는 것이 나올 때 가장 효과적으로 해결하는 방법은?&amp;lt;/strong &amp;gt;&lt;br /&gt;A: '에러 메시지를 그대로 복사해서 구글에 검색하기'가 90%의 문제를 해결해 줍니다. 만약 커뮤니티에 질문을 올릴 때는, '내가 무엇을 하려 했는지', '어떤 코드를 시도했는지', 그리고 '어떤 에러가 발생했는지'를 구체적으로 작성해야 양질의 답변을 빠르게 얻을 수 있습니다. &lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;color: #333 !important; font-size: 16px !important; line-height: 1.8; margin-bottom: 20px;&quot; data-ke-size=&quot;size16&quot;&gt;이 &lt;b&gt;자바스크립트 독학 로드맵&lt;/b&gt;이 여러분의 성공적인 개발자 커리어의 단단한 첫걸음이 되기를 진심으로 바랍니다. 조급해하지 말고, 어제의 나보다 조금 더 성장한다는 마음으로 포기하지 말고 꾸준히 나아가세요. 여러분의 도전을 응원합니다&lt;/p&gt;
&lt;/div&gt;</description>
      <category>Language/JavaScript</category>
      <category>자바스크립트</category>
      <category>초보자</category>
      <category>코딩공부</category>
      <category>프로그래밍</category>
      <category>학습로드맵</category>
      <author>dobbyyo</author>
      <guid isPermaLink="true">https://dobbyyo.tistory.com/34</guid>
      <comments>https://dobbyyo.tistory.com/entry/%EC%99%95%EC%B4%88%EB%B3%B4%EB%A5%BC-%EC%9C%84%ED%95%9C-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EB%8F%85%ED%95%99-%EB%A1%9C%EB%93%9C%EB%A7%B5-2026-%EC%99%84%EB%B2%BD%ED%95%9C-%EA%B3%B5%EB%B6%80-%EC%88%9C%EC%84%9C%EC%99%80-%EA%B3%84%ED%9A%8D#entry34comment</comments>
      <pubDate>Mon, 5 Jan 2026 09:54:40 +0900</pubDate>
    </item>
    <item>
      <title>2026년 업데이트: 최고의 자바스크립트 독학 추천 강의 TOP 4 (+ 책/교재 완벽 가이드)</title>
      <link>https://dobbyyo.tistory.com/entry/2026%EB%85%84-%EC%97%85%EB%8D%B0%EC%9D%B4%ED%8A%B8-%EC%B5%9C%EA%B3%A0%EC%9D%98-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EB%8F%85%ED%95%99-%EC%B6%94%EC%B2%9C-%EA%B0%95%EC%9D%98-TOP-4-%EC%B1%85%EA%B5%90%EC%9E%AC-%EC%99%84%EB%B2%BD-%EA%B0%80%EC%9D%B4%EB%93%9C</link>
      <description>&lt;div style=&quot;line-height: 1.6; max-width: 1200px; margin: 0 auto;&quot;&gt;
&lt;div style=&quot;background: #e5faf7; color: #015249; border: 1px solid #c4e1dc; padding: 30px; margin: 30px 0; border-radius: 20px; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);&quot;&gt;
&lt;p style=&quot;font-size: 18px !important;&quot; data-ke-size=&quot;size16&quot;&gt;수많은 자바스크립트 강의와 책들 앞에서 어떤 것부터 시작해야 할지 막막하신가요? 잘못된 자료를 선택해 시간을 낭비할까 걱정되시나요? 괜찮습니다. 그 고민을 해결해 드리기 위해 이 글을 준비했습니다.&lt;/p&gt;
&lt;p style=&quot;font-size: 18px !important;&quot; data-ke-size=&quot;size16&quot;&gt;이 글에서는 2026년 최신 정보를 기준으로, 여러분의 소중한 시간을 아껴줄 최고의 &lt;b&gt;자바스크립트 독학 추천 강의&lt;/b&gt;와 학습 효율을 극대화할 책(교재)을 완벽하게 분석해 드립니다. 단순히 유명한 자료를 나열하는 것이 아닙니다. 각 자료의 핵심 특징, 장단점, 가격, 그리고 어떤 유형의 학습자에게 가장 적합한지에 대한 심층적인 정보를 제공할 것을 약속합니다. 이 글 하나만으로 자신에게 맞는 최적의 학습 자료를 선택하고, 구체적인 학습 계획까지 세울 수 있게 될 것입니다.&lt;/p&gt;
&lt;/div&gt;
&lt;br /&gt;&lt;br /&gt;
&lt;h2 style=&quot;font-weight: bold; border: 2px solid #c4e1dc; border-radius: 10px; padding: 15px; margin-top: 30px; margin-bottom: 30px;&quot; data-ke-size=&quot;size26&quot;&gt;목차&lt;/h2&gt;
&lt;ul style=&quot;list-style: disc; margin-left: 40px;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;margin-bottom: 5px; color: #222222 !important; font-size: 16px !important;&quot;&gt;&lt;a style=&quot;color: #00897b;&quot; href=&quot;#section-1&quot;&gt;자바스크립트 독학, 실패하지 않는 학습 자료 선택 기준&lt;/a&gt;&lt;/li&gt;
&lt;li style=&quot;margin-bottom: 5px; color: #222222 !important; font-size: 16px !important;&quot;&gt;&lt;a style=&quot;color: #00897b;&quot; href=&quot;#section-2&quot;&gt;2026년 검증된 BEST 자바스크립트 독학 추천 강의 TOP 4&lt;/a&gt;&lt;/li&gt;
&lt;li style=&quot;margin-bottom: 5px; color: #222222 !important; font-size: 16px !important;&quot;&gt;&lt;a style=&quot;color: #00897b;&quot; href=&quot;#section-3&quot;&gt;강의와 시너지 UP! 자바스크립트 독학 책 추천 TOP 2&lt;/a&gt;&lt;/li&gt;
&lt;li style=&quot;margin-bottom: 5px; color: #222222 !important; font-size: 16px !important;&quot;&gt;&lt;a style=&quot;color: #00897b;&quot; href=&quot;#section-4&quot;&gt;결론: 나만의 최적의 조합 찾고 지금 바로 시작하기&lt;/a&gt;&lt;/li&gt;
&lt;li style=&quot;margin-bottom: 5px; color: #222222 !important; font-size: 16px !important;&quot;&gt;&lt;a style=&quot;color: #00897b;&quot; href=&quot;#faq&quot;&gt;자주 묻는 질문 (FAQ)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;&lt;br /&gt;
&lt;div style=&quot;text-align: center; margin: 20px 0;&quot;&gt;&lt;img style=&quot;max-width: 100%; height: auto;&quot; src=&quot;https://files.dobbyblog.kr/view/a4de0e52-f937-447b-b6a4-ff417b3ce7e2.png&quot; alt=&quot;2026년 최신 자바스크립트 학습을 위한 현대적 데스크톱 작업 공간&quot; /&gt;&lt;/div&gt;
&lt;h2 id=&quot;section-1&quot; style=&quot;font-weight: bold; border: 2px solid #c4e1dc; border-radius: 10px; padding: 15px; margin-top: 30px; margin-bottom: 30px;&quot; data-ke-size=&quot;size26&quot;&gt;자바스크립트 독학, 실패하지 않는 학습 자료 선택 기준&lt;/h2&gt;
&lt;p style=&quot;color: #222222 !important; font-size: 16px !important;&quot; data-ke-size=&quot;size16&quot;&gt;좋은 강의와 책을 무작정 따라가기 전에, 스스로 좋은 학습 자료를 판단하는 기준을 아는 것이 중요합니다. 이 기준들을 알고 있다면 앞으로 다른 언어를 공부할 때도 큰 도움이 될 것입니다. 좋은 &lt;code&gt;자바스크립트 독학 교재&lt;/code&gt;는 아래 4가지 기준을 충족해야 합니다.&lt;/p&gt;
&lt;div style=&quot;text-align: center; margin: 20px 0;&quot;&gt;&lt;img style=&quot;max-width: 100%; height: auto;&quot; src=&quot;https://files.dobbyblog.kr/view/870da313-53a4-4ded-b53a-bb5aab4f706f.png&quot; alt=&quot;자바스크립트 독학 학습 자료 선택 기준을 보여주는 인포그래픽 이미지&quot; /&gt;&lt;/div&gt;
&lt;ul style=&quot;list-style: disc; margin-left: 40px;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;margin-bottom: 5px; color: #222222 !important; font-size: 16px !important;&quot;&gt;&lt;b&gt;최신 ECMAScript(ES6+) 표준 반영 여부&lt;/b&gt;&lt;br /&gt;현업에서는 &lt;code&gt;var&lt;/code&gt; 대신 &lt;code&gt;let&lt;/code&gt;, &lt;code&gt;const&lt;/code&gt;를 사용하고, 화살표 함수, Promise, async/await 같은 모던 자바스크립트 문법을 사용합니다. 구식 문법만 배우면 최신 프레임워크나 라이브러리를 다루기 어렵습니다. 개발자 로드맵에서도 HTML, CSS 다음으로 가장 중요한 것이 바로 최신 표준(ES6+)을 반영한 자바스크립트 학습임을 강조합니다.&lt;/li&gt;
&lt;li style=&quot;margin-bottom: 5px; color: #222222 !important; font-size: 16px !important;&quot;&gt;&lt;b&gt;이론과 실습의 균형&lt;/b&gt;&lt;br /&gt;클로저, 프로토타입 같은 어려운 이론만 계속 배우면 쉽게 지칩니다. 반대로 실습만 따라 하면 원리를 이해하지 못해 응용이 불가능합니다. 개념을 배운 뒤, 곧바로 투두리스트나 간단한 게임 같은 작은 프로젝트를 만들어보며 지식을 체화할 수 있는 커리큘럼인지 반드시 확인해야 합니다.&lt;/li&gt;
&lt;li style=&quot;margin-bottom: 5px; color: #222222 !important; font-size: 16px !important;&quot;&gt;&lt;b&gt;Q&amp;amp;A 및 커뮤니티 활성화&lt;/b&gt;&lt;br /&gt;독학의 가장 큰 적은 '막혔을 때 물어볼 곳이 없는 것'입니다. 질의응답 게시판이 활발하게 운영되는지, 수강생들이 서로 돕는 커뮤니티가 있는지 확인하세요. 사소한 오류 하나를 해결하기 위해 며칠을 허비하는 비효율을 막아줍니다.&lt;/li&gt;
&lt;li style=&quot;margin-bottom: 5px; color: #222222 !important; font-size: 16px !important;&quot;&gt;&lt;b&gt;자신의 학습 스타일에 맞는 포맷 선택&lt;/b&gt;&lt;br /&gt;학습 자료의 형태는 학습 효율에 직접적인 영향을 미칩니다. 어떤 방식이 나에게 맞는지 비교해보고 선택하는 것이 좋습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;div style=&quot;display: flex; justify-content: center; margin: 20px 0;&quot;&gt;
&lt;table style=&quot;border-collapse: collapse; width: 80%;&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&quot;border: 1px solid #ddd; padding: 8px; color: #222222 !important; font-size: 16px !important; text-align: left;&quot;&gt;포맷&lt;/th&gt;
&lt;th style=&quot;border: 1px solid #ddd; padding: 8px; color: #222222 !important; font-size: 16px !important; text-align: left;&quot;&gt;장점&lt;/th&gt;
&lt;th style=&quot;border: 1px solid #ddd; padding: 8px; color: #222222 !important; font-size: 16px !important; text-align: left;&quot;&gt;단점&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 8px; color: #222222 !important; font-size: 16px !important;&quot;&gt;&lt;b&gt;영상 강의&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 8px; color: #222222 !important; font-size: 16px !important;&quot;&gt;시각적인 자료로 이해가 쉽고, 강사의 코드를 그대로 따라 하며 배울 수 있음&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 8px; color: #222222 !important; font-size: 16px !important;&quot;&gt;전체 흐름을 파악하기 어렵고, 특정 부분만 다시 찾아보기 번거로움&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 8px; color: #222222 !important; font-size: 16px !important;&quot;&gt;&lt;b&gt;책/교재&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 8px; color: #222222 !important; font-size: 16px !important;&quot;&gt;깊이 있는 원리 설명이 많고, 필요할 때마다 사전처럼 찾아보기 용이함&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 8px; color: #222222 !important; font-size: 16px !important;&quot;&gt;글과 그림만으로 이해해야 해서 초보자에게는 다소 지루할 수 있음&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;h2 id=&quot;section-2&quot; style=&quot;font-weight: bold; border: 2px solid #c4e1dc; border-radius: 10px; padding: 15px; margin-top: 30px; margin-bottom: 30px;&quot; data-ke-size=&quot;size26&quot;&gt;2026년 검증된 BEST 자바스크립트 독학 추천 강의 TOP 4&lt;/h2&gt;
&lt;p style=&quot;color: #222222 !important; font-size: 16px !important;&quot; data-ke-size=&quot;size16&quot;&gt;전 세계 수많은 강의들 중, 2026년 현재 가장 좋은 평가를 받으며 다양한 수준의 학습자를 만족시키는 최고의 &lt;b&gt;자바스크립트 독학 추천 강의&lt;/b&gt; 5개를 엄선했습니다.&lt;/p&gt;
&lt;h3 style=&quot;border-left: 8px solid #002b36; border-bottom: 1px solid #002b36; padding-left: 16px; padding-bottom: 10px; font-size: 25px; margin-top: 20px;&quot; data-ke-size=&quot;size23&quot;&gt;1. [입문/무료] 노마드코더 - 바닐라 JS로 크롬 앱 만들기&lt;/h3&gt;
&lt;div style=&quot;text-align: center; margin: 20px 0;&quot;&gt;&lt;img style=&quot;max-width: 100%; height: auto;&quot; src=&quot;https://d1telmomo28umc.cloudfront.net/media/public/thumbnails/jsThumb.jpg&quot; alt=&quot;노마드코더 무료 초보자 자바스크립트 강의 현장 이미지&quot; /&gt;&lt;/div&gt;
&lt;ul style=&quot;list-style: disc; margin-left: 40px;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;margin-bottom: 5px; color: #222222 !important; font-size: 16px !important;&quot;&gt;&lt;b&gt;한 줄 요약:&lt;/b&gt; 코딩의 'ㅋ'자도 모르는 왕초보가 흥미를 잃지 않고 결과물을 만들며 JS와 친해질 수 있는 최고의 무료 강의.&lt;/li&gt;
&lt;li style=&quot;margin-bottom: 5px; color: #222222 !important; font-size: 16px !important;&quot;&gt;&lt;b&gt;특징:&lt;/b&gt; HTML, CSS에 대한 아주 기초적인 지식만 있다면 누구나 따라 할 수 있습니다. 복잡한 이론 설명 대신, 시계, 투두리스트, 날씨 API 연동 등 눈에 보이는 결과물을 빠르게 만들어내며 성취감을 느낄 수 있도록 구성되어 있습니다. 순수 자바스크립트(바닐라 JS)만을 사용해 웹 브라우저를 직접 제어하는 경험을 통해 자바스크립트의 본질적인 역할을 재미있게 배울 수 있습니다.&lt;/li&gt;
&lt;li style=&quot;margin-bottom: 5px; color: #222222 !important; font-size: 16px !important;&quot;&gt;&lt;b&gt;장점:&lt;/b&gt; 완전 무료, 짧고 간결한 강의 구성, 매일 눈에 보이는 결과물로 인한 높은 학습 동기 부여.&lt;/li&gt;
&lt;li style=&quot;margin-bottom: 5px; color: #222222 !important; font-size: 16px !important;&quot;&gt;&lt;b&gt;단점:&lt;/b&gt; 자바스크립트의 깊이 있는 원리(스코프, 실행 컨텍스트 등)에 대한 설명은 거의 다루지 않아, 이 강의만으로는 부족합니다.&lt;/li&gt;
&lt;li style=&quot;margin-bottom: 5px; color: #222222 !important; font-size: 16px !important;&quot;&gt;&lt;b&gt;추천 대상:&lt;/b&gt; 프로그래밍이 완전 처음인 비전공자, 자바스크립트에 대한 흥미를 먼저 붙이고 싶은 학습자.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 style=&quot;border-left: 8px solid #002b36; border-bottom: 1px solid #002b36; padding-left: 16px; padding-bottom: 10px; font-size: 25px; margin-top: 20px;&quot; data-ke-size=&quot;size23&quot;&gt;2. [종합/글로벌] Udemy - The Complete JavaScript Course 2026: From Zero to Expert!&lt;/h3&gt;
&lt;div style=&quot;text-align: center; margin: 20px 0;&quot;&gt;&lt;img style=&quot;max-width: 100%; height: auto;&quot; src=&quot;https://img-c.udemycdn.com/course/750x422/5638532_1c7a.jpg&quot; alt=&quot;Udemy 자바스크립트 종합 강의 콘텐츠와 실전 프로젝트를 보여주는 이미지&quot; /&gt;&lt;/div&gt;
&lt;ul style=&quot;list-style: disc; margin-left: 40px;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;margin-bottom: 5px; color: #222222 !important; font-size: 16px !important;&quot;&gt;&lt;b&gt;한 줄 요약:&lt;/b&gt; 자바스크립트의 모든 것을 담아낸, 전 세계적으로 가장 많이 팔린 베스트셀러 강의.&lt;/li&gt;
&lt;li style=&quot;margin-bottom: 5px; color: #222222 !important; font-size: 16px !important;&quot;&gt;&lt;b&gt;특징:&lt;/b&gt; 68시간이 넘는 방대한 분량에 걸쳐 자바스크립트 기초 문법부터 비동기 처리(Asynchronous JS), 객체지향 프로그래밍(OOP), 모듈 번들러(Webpack, Parcel) 등 최신 개발 생태계까지 거의 모든 주제를 다룹니다. 특히 'Bankist'라는 가상 은행 애플리케이션이나 지도에 운동 기록을 표시하는 'Mapty' 프로젝트 등 실무와 유사한 대규모 프로젝트를 여러 개 진행하는 것이 특징입니다.&lt;/li&gt;
&lt;li style=&quot;margin-bottom: 5px; color: #222222 !important; font-size: 16px !important;&quot;&gt;&lt;b&gt;장점:&lt;/b&gt; 이 강의 하나로 JS 마스터 가능, 퀄리티 높은 실전 프로젝트 포함, 최신 기술 스택을 반영한 꾸준한 업데이트.&lt;/li&gt;
&lt;li style=&quot;margin-bottom: 5px; color: #222222 !important; font-size: 16px !important;&quot;&gt;&lt;b&gt;단점:&lt;/b&gt; 수강 시간이 매우 길어 완강에 대한 의지가 중요하며, 한글 자막의 번역 품질이 가끔 아쉬울 때가 있습니다.&lt;/li&gt;
&lt;li style=&quot;margin-bottom: 5px; color: #222222 !important; font-size: 16px !important;&quot;&gt;&lt;b&gt;추천 대상:&lt;/b&gt; 시간을 투자해서라도 자바스크립트를 제대로 끝장내고 싶은 학습자, 해외 취업까지 고려하는 개발자 지망생.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 style=&quot;border-left: 8px solid #002b36; border-bottom: 1px solid #002b36; padding-left: 16px; padding-bottom: 10px; font-size: 25px; margin-top: 20px;&quot; data-ke-size=&quot;size23&quot;&gt;3. [한국어/입문] 인프런 - 생활코딩 WEB2 - JavaScript&lt;/h3&gt;
&lt;div style=&quot;text-align: center; margin: 20px 0;&quot;&gt;&lt;img style=&quot;max-width: 100%; height: auto;&quot; src=&quot;https://cdn.inflearn.com/wp-content/uploads/web2-js-1.png&quot; alt=&quot;이고잉 강사의 친절하고 쉬운 한국어 자바스크립트 입문 강의 이미지&quot; /&gt;&lt;/div&gt;
&lt;ul style=&quot;list-style: disc; margin-left: 40px;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;margin-bottom: 5px; color: #222222 !important; font-size: 16px !important;&quot;&gt;&lt;b&gt;한 줄 요약:&lt;/b&gt; 비전공자들의 코딩 선생님, '이고잉'님의 가장 친절하고 쉬운 자바스크립트 입문 강의.&lt;/li&gt;
&lt;li style=&quot;margin-bottom: 5px; color: #222222 !important; font-size: 16px !important;&quot;&gt;&lt;b&gt;특징:&lt;/b&gt; 프로그래밍을 전혀 모르는 사람의 눈높이에 맞춰, 자바스크립트가 웹 브라우저를 제어하는 '클라이언트 사이드 스크립트'로서 어떤 역할을 하는지에 초점을 맞춥니다. 문법 하나하나를 실생활의 예시에 비유하여 설명하기 때문에, 어려운 프로그래밍 용어에 대한 거부감 없이 자연스럽게 개념을 이해할 수 있습니다.&lt;/li&gt;
&lt;li style=&quot;margin-bottom: 5px; color: #222222 !important; font-size: 16px !important;&quot;&gt;&lt;b&gt;장점:&lt;/b&gt; 완전 무료 또는 매우 저렴한 가격, 어려운 개념을 세상에서 가장 쉽게 풀어내는 독보적인 설명 방식.&lt;/li&gt;
&lt;li style=&quot;margin-bottom: 5px; color: #222222 !important; font-size: 16px !important;&quot;&gt;&lt;b&gt;단점:&lt;/b&gt; 최신 ES6+ 문법보다는 웹의 동작 원리를 이해하는 데 필요한 전통적인 핵심 기능 위주로 설명될 수 있습니다.&lt;/li&gt;
&lt;li style=&quot;margin-bottom: 5px; color: #222222 !important; font-size: 16px !important;&quot;&gt;&lt;b&gt;추천 대상:&lt;/b&gt; 컴퓨터와 친하지 않은 완전 초보자, 어려운 프로그래밍 용어에 거부감이 있는 학습자.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 style=&quot;border-left: 8px solid #002b36; border-bottom: 1px solid #002b36; padding-left: 16px; padding-bottom: 10px; font-size: 25px; margin-top: 20px;&quot; data-ke-size=&quot;size23&quot;&gt;4. [무료/커리큘럼] FreeCodeCamp - JavaScript Algorithms and Data Structures&lt;/h3&gt;
&lt;div style=&quot;text-align: center; margin: 20px 0;&quot;&gt;&lt;img style=&quot;max-width: 100%; height: auto;&quot; src=&quot;https://global.discourse-cdn.com/freecodecamp/optimized/3X/e/f/ef30bda561911177eff003d6a3635866cd41e8c6_2_1024x793.png&quot; alt=&quot;FreeCodeCamp 자바스크립트 알고리즘과 자료구조 체계적인 학습 화면 이미지&quot; /&gt;&lt;/div&gt;
&lt;ul style=&quot;list-style: disc; margin-left: 40px;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;margin-bottom: 5px; color: #222222 !important; font-size: 16px !important;&quot;&gt;&lt;b&gt;한 줄 요약:&lt;/b&gt; 기초부터 알고리즘, 자료구조까지 체계적인 커리큘럼에 따라 학습하고 인증서까지 받을 수 있는 글로벌 무료 교육 플랫폼.&lt;/li&gt;
&lt;li style=&quot;margin-bottom: 5px; color: #222222 !important; font-size: 16px !important;&quot;&gt;&lt;b&gt;특징:&lt;/b&gt; 읽기 자료, 코드 에디터, 테스트 케이스가 한 화면에 통합된 환경에서 학습이 진행됩니다. 'Basic JavaScript'로 기초를 다지고, 'ES6', '정규표현식', '디버깅'을 거쳐 '기본 자료구조'와 '기본 알고리즘 스크립팅'까지 수백 개의 작은 챌린지를 해결하며 나아가는 방식입니다. 이 과정을 통해 문제 해결 능력을 체계적으로 기를 수 있습니다.&lt;/li&gt;
&lt;li style=&quot;margin-bottom: 5px; color: #222222 !important; font-size: 16px !important;&quot;&gt;&lt;b&gt;장점:&lt;/b&gt; 완전 무료, 체계적인 커리큘럼, 학습 완료 시 포트폴리오에 추가할 수 있는 공신력 있는 인증서 발급.&lt;/li&gt;
&lt;li style=&quot;margin-bottom: 5px; color: #222222 !important; font-size: 16px !important;&quot;&gt;&lt;b&gt;단점:&lt;/b&gt; 모든 콘텐츠가 영어로 되어있어 기본적인 영어 독해 능력이 필요합니다.&lt;/li&gt;
&lt;li style=&quot;margin-bottom: 5px; color: #222222 !important; font-size: 16px !important;&quot;&gt;&lt;b&gt;추천 대상:&lt;/b&gt; 영어에 부담이 없고, 정해진 커리큘럼에 따라 꾸준히 학습하는 것을 선호하는 학습자, 코딩 테스트 준비를 시작하려는 사람.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;section-3&quot; style=&quot;font-weight: bold; border: 2px solid #c4e1dc; border-radius: 10px; padding: 15px; margin-top: 30px; margin-bottom: 30px;&quot; data-ke-size=&quot;size26&quot;&gt;강의와 시너지 UP! 자바스크립트 독학 책 추천 TOP 2&lt;/h2&gt;
&lt;p style=&quot;color: #222222 !important; font-size: 16px !important;&quot; data-ke-size=&quot;size16&quot;&gt;영상 강의는 따라 하기 쉽지만, 개념을 깊이 있게 파고들거나 필요할 때마다 특정 내용을 찾아보기에는 책이 더 효율적입니다. 아래 두 권의 책은 여러분의 학습을 더욱 단단하게 만들어 줄 것입니다.&lt;/p&gt;
&lt;h3 style=&quot;border-left: 8px solid #002b36; border-bottom: 1px solid #002b36; padding-left: 16px; padding-bottom: 10px; font-size: 25px; margin-top: 20px;&quot; data-ke-size=&quot;size23&quot;&gt;1. [입문서] 혼자 공부하는 자바스크립트 (윤인성 저)&lt;/h3&gt;
&lt;div style=&quot;text-align: center; margin: 20px 0;&quot;&gt;&lt;img style=&quot;max-width: 100%; height: auto;&quot; src=&quot;https://contents.kyobobook.co.kr/sih/fit-in/458x0/pdt/9791162243671.jpg&quot; alt=&quot;윤인성 저자가 쓴 자바스크립트 입문서 '혼자 공부하는 자바스크립트' 책 표지 이미지&quot; /&gt;&lt;/div&gt;
&lt;ul style=&quot;list-style: disc; margin-left: 40px;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;margin-bottom: 5px; color: #222222 !important; font-size: 16px !important;&quot;&gt;&lt;b&gt;한 줄 요약:&lt;/b&gt; 독학 학습자를 위해 모든 것을 떠먹여 주는, 가장 친절하고 직관적인 입문용 필독서.&lt;/li&gt;
&lt;li style=&quot;margin-bottom: 5px; color: #222222 !important; font-size: 16px !important;&quot;&gt;&lt;b&gt;특징:&lt;/b&gt; 1:1 과외를 받는 듯한 친절한 존댓말 설명과 풍부한 그림/도표가 특징입니다. '자료와 변수' 같은 기초부터 'DOM 조작', '이벤트' 등 웹 개발에 필수적인 내용까지 입문자가 꼭 알아야 할 핵심을 체계적으로 다룹니다. 각 장 끝의 '마무리 문제'와 '도전 문제'를 통해 학습 내용을 스스로 점검하고 응용력을 기를 수 있습니다.&lt;/li&gt;
&lt;li style=&quot;margin-bottom: 5px; color: #222222 !important; font-size: 16px !important;&quot;&gt;&lt;b&gt;어떤 강의와 함께 보면 좋은가?:&lt;/b&gt; 노마드코더나 생활코딩처럼 실습 위주 강의를 들으며 부족하다고 느낀 이론적 배경을 채우기에 최고의 &lt;b&gt;자바스크립트 독학 교재&lt;/b&gt;입니다.&lt;/li&gt;
&lt;li style=&quot;margin-bottom: 5px; color: #222222 !important; font-size: 16px !important;&quot;&gt;&lt;b&gt;추천 대상:&lt;/b&gt; 비전공자, 코딩을 책으로 차근차근 배우고 싶은 입문자.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 style=&quot;border-left: 8px solid #002b36; border-bottom: 1px solid #002b36; padding-left: 16px; padding-bottom: 10px; font-size: 25px; margin-top: 20px;&quot; data-ke-size=&quot;size23&quot;&gt;2. [바이블] 모던 자바스크립트 Deep Dive (이웅모 저)&lt;/h3&gt;
&lt;div style=&quot;text-align: center; margin: 20px 0;&quot;&gt;&lt;img style=&quot;max-width: 100%; height: auto;&quot; src=&quot;https://contents.kyobobook.co.kr/sih/fit-in/458x0/pdt/9791158392239.jpg&quot; alt=&quot;이웅모 저자의 심도 깊은 자바스크립트 바이블 교재 '모던 자바스크립트 Deep Dive' 책 이미지&quot; /&gt;&lt;/div&gt;
&lt;ul style=&quot;list-style: disc; margin-left: 40px;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;margin-bottom: 5px; color: #222222 !important; font-size: 16px !important;&quot;&gt;&lt;b&gt;한 줄 요약:&lt;/b&gt; 자바스크립트 개발자라면 누구나 책상에 한 권쯤은 꽂아둬야 할, JS의 모든 것을 담은 백과사전.&lt;/li&gt;
&lt;li style=&quot;margin-bottom: 5px; color: #222222 !important; font-size: 16px !important;&quot;&gt;&lt;b&gt;특징:&lt;/b&gt; 900페이지가 넘는 방대한 분량에 걸쳐 자바스크립트의 기본 개념부터 데이터 타입, 실행 컨텍스트, 클로저, 프로토타입, 비동기 프로그래밍의 동작 원리까지 매우 상세하게 서술되어 있습니다. 단순한 문법 나열이 아닌, '왜?'라는 질문에 답하며 자바스크립트 엔진의 동작 원리까지 파고드는 깊이가 이 책의 핵심 가치입니다.&lt;/li&gt;
&lt;li style=&quot;margin-bottom: 5px; color: #222222 !important; font-size: 16px !important;&quot;&gt;&lt;b&gt;어떤 강의와 함께 보면 좋은가?:&lt;/b&gt; 모든 강의의 보조 교재로 완벽합니다. 특히 특정 개념(예: this 바인딩, 이벤트 루프)이 궁금할 때마다 사전처럼 해당 챕터를 찾아보는 용도로 활용하는 것이 가장 효과적입니다. 이것이야말로 진정한 의미의 &lt;b&gt;자바스크립트 독학 책 추천&lt;/b&gt; 필독서입니다.&lt;/li&gt;
&lt;li style=&quot;margin-bottom: 5px; color: #222222 !important; font-size: 16px !important;&quot;&gt;&lt;b&gt;추천 대상:&lt;/b&gt; 주니어 개발자, 자바스크립트의 깊이를 알고 싶은 모든 학습자, 기술 면접을 완벽하게 준비하고 싶은 취업 준비생.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;section-4&quot; style=&quot;font-weight: bold; border: 2px solid #c4e1dc; border-radius: 10px; padding: 15px; margin-top: 30px; margin-bottom: 30px;&quot; data-ke-size=&quot;size26&quot;&gt;결론: 나만의 최적의 조합 찾고 지금 바로 시작하기&lt;/h2&gt;
&lt;p style=&quot;color: #222222 !important; font-size: 16px !important;&quot; data-ke-size=&quot;size16&quot;&gt;지금까지 소개한 &lt;b&gt;자바스크립트 독학 추천 강의&lt;/b&gt;와 &lt;b&gt;자바스크립트 독학 책 추천&lt;/b&gt; 목록을 바탕으로, 자신에게 맞는 최적의 학습 조합을 찾아보세요.&lt;/p&gt;
&lt;div style=&quot;text-align: center; margin: 20px 0;&quot;&gt;&lt;img style=&quot;max-width: 100%; height: auto;&quot; src=&quot;https://files.dobbyblog.kr/view/e6242d33-6783-411a-9e4f-09c797e61688.png&quot; alt=&quot;자바스크립트 독학 학습자 유형별 추천 강의 및 책 조합을 보여주는 개념도&quot; /&gt;&lt;/div&gt;
&lt;div style=&quot;display: flex; justify-content: center; margin: 20px 0;&quot;&gt;
&lt;table style=&quot;border-collapse: collapse; width: 90%;&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style=&quot;border: 1px solid #ddd; padding: 8px; color: #222222 !important; font-size: 16px !important; text-align: left;&quot;&gt;학습자 유형&lt;/th&gt;
&lt;th style=&quot;border: 1px solid #ddd; padding: 8px; color: #222222 !important; font-size: 16px !important; text-align: left;&quot;&gt;추천 강의&lt;/th&gt;
&lt;th style=&quot;border: 1px solid #ddd; padding: 8px; color: #222222 !important; font-size: 16px !important; text-align: left;&quot;&gt;추천 책&lt;/th&gt;
&lt;th style=&quot;border: 1px solid #ddd; padding: 8px; color: #222222 !important; font-size: 16px !important; text-align: left;&quot;&gt;특징&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 8px; color: #222222 !important; font-size: 16px !important;&quot;&gt;&lt;b&gt;완전 왕초보&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 8px; color: #222222 !important; font-size: 16px !important;&quot;&gt;노마드코더 or 생활코딩&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 8px; color: #222222 !important; font-size: 16px !important;&quot;&gt;혼자 공부하는 자바스크립트&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 8px; color: #222222 !important; font-size: 16px !important;&quot;&gt;무료+쉽고 친절한 설명으로 흥미를 붙이며 시작하는 최고의 조합&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 8px; color: #222222 !important; font-size: 16px !important;&quot;&gt;&lt;b&gt;CS/코딩 기초 O&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 8px; color: #222222 !important; font-size: 16px !important;&quot;&gt;Udemy 올인원 강의&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 8px; color: #222222 !important; font-size: 16px !important;&quot;&gt;혼자 공부하는 자바스크립트&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 8px; color: #222222 !important; font-size: 16px !important;&quot;&gt;체계적인 커리큘럼의 강의와 친절한 책으로 기초를 탄탄하게 다지는 조합&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 8px; color: #222222 !important; font-size: 16px !important;&quot;&gt;&lt;b&gt;JS 마스터 지망생&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 8px; color: #222222 !important; font-size: 16px !important;&quot;&gt;Udemy 올인원 강의&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 8px; color: #222222 !important; font-size: 16px !important;&quot;&gt;모던 자바스크립트 Deep Dive&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 8px; color: #222222 !important; font-size: 16px !important;&quot;&gt;전 세계 베스트셀러 강의와 국내 최고의 심화 서적으로 깊이를 더하는 조합&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 8px; color: #222222 !important; font-size: 16px !important;&quot;&gt;&lt;b&gt;면접/이직 준비&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 8px; color: #222222 !important; font-size: 16px !important;&quot;&gt;인프런 Deep Dive 강의&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 8px; color: #222222 !important; font-size: 16px !important;&quot;&gt;모던 자바스크립트 Deep Dive&lt;/td&gt;
&lt;td style=&quot;border: 1px solid #ddd; padding: 8px; color: #222222 !important; font-size: 16px !important;&quot;&gt;저자 직강과 바이블 교재를 통해 JS 내부 동작 원리를 완벽히 정복하는 조합&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #222222 !important; font-size: 16px !important;&quot; data-ke-size=&quot;size16&quot;&gt;완벽한 정답은 없습니다. 왕초보라면 '노마드코더 강의 + 혼공자 책' 조합으로 흥미롭게 시작하고, 개발 경험이 있다면 'Udemy 강의 + Deep Dive 책' 조합으로 깊이를 더하는 등 자신만의 로드맵을 만드세요.&lt;/p&gt;
&lt;p style=&quot;color: #222222 !important; font-size: 16px !important;&quot; data-ke-size=&quot;size16&quot;&gt;가장 좋은 공부는 지금 당장 코드 한 줄을 쳐보는 것입니다. 망설이지 마세요.&lt;/p&gt;
&lt;br /&gt;&lt;br /&gt;
&lt;h2 id=&quot;faq&quot; style=&quot;font-weight: bold; border: 2px solid #c4e1dc; border-radius: 10px; padding: 15px; margin-top: 30px; margin-bottom: 30px;&quot; data-ke-size=&quot;size26&quot;&gt;자주 묻는 질문 (FAQ)&lt;/h2&gt;
&lt;p style=&quot;color: #222222 !important; font-size: 16px !important;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Q: 비전공자인데 어떤 강의부터 시작하는 게 좋을까요?&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222 !important; font-size: 16px !important;&quot; data-ke-size=&quot;size16&quot;&gt;A: 프로그래밍이 완전 처음이시라면 '노마드코더 - 바닐라 JS로 크롬 앱 만들기'나 '생활코딩 WEB2 - JavaScript'처럼 무료이고 흥미 위주로 진행되는 강의로 시작하시는 것을 추천합니다. 이를 통해 먼저 코딩에 대한 재미를 붙이는 것이 중요합니다.&lt;/p&gt;
&lt;p style=&quot;color: #222222 !important; font-size: 16px !important;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Q: 강의만 들으면 되나요? 책도 꼭 봐야 하나요?&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222 !important; font-size: 16px !important;&quot; data-ke-size=&quot;size16&quot;&gt;A: 강의는 흐름을 따라가며 실습하기에 좋지만, 깊이 있는 원리를 이해하고 필요할 때마다 개념을 찾아보기에는 책이 더 효율적입니다. '혼자 공부하는 자바스크립트' 같은 입문서나 '모던 자바스크립트 Deep Dive' 같은 심화 서적을 강의와 병행하시면 학습 효과가 극대화됩니다.&lt;/p&gt;
&lt;p style=&quot;color: #222222 !important; font-size: 16px !important;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Q: 유료 강의를 듣기 전에 맛보기로 할 만한 게 있을까요?&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222 !important; font-size: 16px !important;&quot; data-ke-size=&quot;size16&quot;&gt;A: 네, FreeCodeCamp는 체계적인 커리큘럼을 모두 무료로 제공하며, 각 단계를 통과하며 성취감을 느낄 수 있어 좋습니다. 또한, 대부분의 유료 강의 플랫폼(Udemy, 인프런 등)은 미리보기 기능을 제공하므로, 결제 전에 강사의 스타일이 나와 맞는지 꼭 확인해보는 것을 권장합니다.&lt;/p&gt;
&lt;/div&gt;</description>
      <category>Language/JavaScript</category>
      <author>dobbyyo</author>
      <guid isPermaLink="true">https://dobbyyo.tistory.com/33</guid>
      <comments>https://dobbyyo.tistory.com/entry/2026%EB%85%84-%EC%97%85%EB%8D%B0%EC%9D%B4%ED%8A%B8-%EC%B5%9C%EA%B3%A0%EC%9D%98-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EB%8F%85%ED%95%99-%EC%B6%94%EC%B2%9C-%EA%B0%95%EC%9D%98-TOP-4-%EC%B1%85%EA%B5%90%EC%9E%AC-%EC%99%84%EB%B2%BD-%EA%B0%80%EC%9D%B4%EB%93%9C#entry33comment</comments>
      <pubDate>Sun, 4 Jan 2026 18:51:02 +0900</pubDate>
    </item>
    <item>
      <title>정보처리기사 실기 - 통합 구현</title>
      <link>https://dobbyyo.tistory.com/entry/%EC%A0%95%EB%B3%B4%EC%B2%98%EB%A6%AC%EA%B8%B0%EC%82%AC-%EC%8B%A4%EA%B8%B0-%ED%86%B5%ED%95%A9-%EA%B5%AC%ED%98%84</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. 연계 서버 / 송&amp;middot;수신 시스템&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;연계 서버&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;데이터를 전송 형식에 맞게 변환하고 송&amp;middot;수신을 수행하는 등 송&amp;middot;수신과 관련된 모든 처리 수행&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;송신 시스템&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;인터페이스 테이블 또는 파일의 데이터를 전송 형식에 맞도록 변환 및 송신을 수행하는 시스템&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;수신 시스템&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;수신 데이터를 인터페이스 테이블이나 파일로 생성하는 시스템&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. XML&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;특수한 목적을 갖는 마크업 언어를 만드는 데 사용되는 다목적 마크업 언어&lt;/li&gt;
&lt;li&gt;웹브라우저 간 HTML 문법이 호환되지 않는 문제와 SGML의 복잡함을 해결하기 위하여 개발됨&lt;/li&gt;
&lt;li&gt;사용자가 직접 문서의 태그를 정의할 수 있고, 다른 사용자가 정의한 태그를 사용할 수 있음&lt;/li&gt;
&lt;li&gt;트리 구조로 구성됨&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. SOAP(Simple Object Access Protocol)&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;컴퓨터 네트워크 상에서 HTTP/HTTPS, SMTP 등을 이용하여 XML을 교환하기 위한 통신 규약&lt;/li&gt;
&lt;li&gt;최근에는 무거운 구조의 SOAP 대신 RESTful 프로토콜을 사용하기도 함&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;4. WSDL(Web Services Description Language)&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;웹 서비스와 관련된 서식이나 프로토콜 등을 표준적인 방법으로 기술하고 게시하기 위한 언어&lt;/li&gt;
&lt;li&gt;XML로 작성되며, UDDI의 기초가 됨&lt;/li&gt;
&lt;li&gt;SOAP, XML, 스키마와 결합하여 인터넷에서 웹 서비스를 제공하기 위해 사용&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>정보처리기사</category>
      <author>dobbyyo</author>
      <guid isPermaLink="true">https://dobbyyo.tistory.com/32</guid>
      <comments>https://dobbyyo.tistory.com/entry/%EC%A0%95%EB%B3%B4%EC%B2%98%EB%A6%AC%EA%B8%B0%EC%82%AC-%EC%8B%A4%EA%B8%B0-%ED%86%B5%ED%95%A9-%EA%B5%AC%ED%98%84#entry32comment</comments>
      <pubDate>Mon, 20 Oct 2025 21:24:07 +0900</pubDate>
    </item>
    <item>
      <title>정보처리기사 실기 - 데이터 입.출력 구현</title>
      <link>https://dobbyyo.tistory.com/entry/%EC%A0%95%EB%B3%B4%EC%B2%98%EB%A6%AC%EA%B8%B0%EC%82%AC-%EC%8B%A4%EA%B8%B0-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%9E%85%EC%B6%9C%EB%A0%A5-%EA%B5%AC%ED%98%84</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. 스키마&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&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;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;종류&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;내용&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;외부 스키마&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;사용자나 응용 프로그래머가 각 개인의 입장에서 필요로 하는 데이터베이스의 논리적 구조를 정의한 것&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;개념 스키마&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;데이터베이스의 전체적인 논리적 구조, 하나만 존재&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;내부 스키마&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;물리적 저장장치의 입장에서 본 데이터베이스 구조&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. 데이터베이스 설계 순서&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;요구조건 분석&lt;span&gt;&amp;nbsp;&lt;/span&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;개념적 설계&lt;span&gt;&amp;nbsp;&lt;/span&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;논리적 설계&lt;span&gt;&amp;nbsp;&lt;/span&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;물리적 설계&lt;span&gt;&amp;nbsp;&lt;/span&gt;-&lt;span&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;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. 개념적 설계&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;정보의 구조를 얻기 위해서 현실 세계의 무한성과 계속성을 이해하고, 다른 사람과 통신하기 위하여 현실 세계에 대한 인식을 추상적 개념으로 표현하는 과정&lt;/li&gt;
&lt;li&gt;개념 스키마 모델링과 트랜잭션 모델링을 병행 수행&lt;/li&gt;
&lt;li&gt;ERD 작성&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;4. 논리적 설계&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;현실 세계에서 발생하는 자료를 컴퓨터가 이해하고 처리할 수 있는 물리적 저장장치에 저장할 수 있도록 변환하기 위해 특정 DBMS가 지원하는 논리적 자료 구조로 변환시키는 과정&lt;/li&gt;
&lt;li&gt;개념 스키마를 평가 및 정제, DBMS에 따라 서로 다른 논리적 스키마를 설계&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;5. 물리적 설계&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;논리적 설계에서 논리적 구조로 표현된 데이터를 디스크 등의 물리적 저장장치에 저장할 수 있는 물리적 구조의 데이터로 변환하는 과정&lt;/li&gt;
&lt;li&gt;저장 레코드의 형식, 순서, 접근 경로 등의 정보를 사용하여 데이터가 컴퓨터에 저장되는 방법을 묘사&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;6. 데이터 모델&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;현실 세계의 정보들을 컴퓨터에 표현하기 위해서 단순화, 추상화하여 체계적으로 표현한 개념적 모형&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;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;요소&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;내용&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;구조&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;논리적으로 표현된 개체 타입들 간의 관계&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;연산&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;데이터베이스에 저장된 실제 데이터를 처리하는 작업에 대한 명세&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;제약 조건&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;데이터베이스에 저장될 수 있는 실제 데이터의 논리적인 제약 조건&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;7. E-R 다이어그램&lt;/b&gt;&lt;/p&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;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;기호&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;의미&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;사각형&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;개체 타입&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;마름모&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;관계 타입&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;타원&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;속성&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;이중 타원&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;다중 값 속성&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;밑줄 타원&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;기본키 속성&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;복수 타원&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;복합 속성&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;관계&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;1:1 등의 개체 간 관계에 대한 대응 수를 선 위에 표시&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;선, 링크&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;개체 타입과 속성을 연결&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;8. 관계형 데이터베이스의 릴레이션 구조&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;릴레이션: 데이터들을 표의 형태로 표현한 것으로, 구조를 나타내는 릴레이션 스키마와 실제 값들인 릴레이션 인스턴스로 구성&lt;/li&gt;
&lt;li&gt;릴레이션 인스턴스: 데이터 개체를 구성하고 있는 속성들에 데이터 타입이 정의되어 구체적인 데이터 값을 가진 것&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-10-20 오후 8.46.27.png&quot; data-origin-width=&quot;729&quot; data-origin-height=&quot;341&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cwS0kl/dJMb9YiWCP7/206nqQaK0tcol20cajTDN0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cwS0kl/dJMb9YiWCP7/206nqQaK0tcol20cajTDN0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cwS0kl/dJMb9YiWCP7/206nqQaK0tcol20cajTDN0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcwS0kl%2FdJMb9YiWCP7%2F206nqQaK0tcol20cajTDN0%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;729&quot; height=&quot;341&quot; data-filename=&quot;스크린샷 2025-10-20 오후 8.46.27.png&quot; data-origin-width=&quot;729&quot; data-origin-height=&quot;341&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;9. 튜플&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;릴레이션을 구성하는 각각의 행&lt;/li&gt;
&lt;li&gt;튜플의 수를&lt;span&gt;&amp;nbsp;&lt;/span&gt;카디널리티&lt;span&gt;&amp;nbsp;&lt;/span&gt;또는&lt;span&gt;&amp;nbsp;&lt;/span&gt;기수,&lt;span&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;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;10. 속성&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;데이터베이스를 구성하는 가장 작은 논리적 단위&lt;/li&gt;
&lt;li&gt;개체의 특성을 기술&lt;/li&gt;
&lt;li&gt;속성의 수를&lt;span&gt;&amp;nbsp;&lt;/span&gt;디그리&lt;span&gt;&amp;nbsp;&lt;/span&gt;또는&lt;span&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;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;11. 도메인&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;하나의 애트리뷰트가 취할 수 있는 같은 타입의 원자값들의 집합&lt;/li&gt;
&lt;li&gt;실제 애트리뷰트 값이 나타날 때 그 값의 합법 여부를 시스템이 검사하는 데에도 이용&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;12. 후보키&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;릴레이션을 구성하는 속성들 중에서 튜플을 유일하게 식별하기 위해 사용되는 속성들의 부분집합&lt;/li&gt;
&lt;li&gt;기본키로 사용할 수 있는 속성들&lt;/li&gt;
&lt;li&gt;유일성과 최소성을 모두 만족시켜야 함&lt;/li&gt;
&lt;li&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;유일성&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;하나의 키 값으로 하나의 튜플만을 유일하게 식별할 수 있어야 한다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;최소성&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;키를 구성하는 속성 하나를 제거하면 유일하게 식별할 수 없도록 꼭 필요한 최소의 속성으로 구성되어야 한다&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;13. 기본키(PK)&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;후보키 중에서 특별히 선정된 주키&lt;/li&gt;
&lt;li&gt;중복된 값 금지, NULL 값 금지&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;14. 대체키(보조키)&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;후보키가 둘 이상일 때 기본키를 제외한 나머지 후보키&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;15. 슈퍼키&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;한 릴레이션 내에 있는 속성들의 집합으로 구성된 키&lt;/li&gt;
&lt;li&gt;릴레이션을 구성하는 모든 튜플 중 슈퍼키로 구성된 속성의 집합과 동일한 값은 나타나지 않음&lt;/li&gt;
&lt;li&gt;모든 튜플에 대해 유일성은 만족하지만 최소성은 만족하지 못함&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;16. 외래키(FK)&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;다른 릴레이션의 기본키를 참조하는 속성 또는 속성들의 집합&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;17. 무결성&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;데이터베이스에 저장된 데이터 값과 그것이 표현하는 현실 세계의 실제값이 일치하는 정확성&lt;/li&gt;
&lt;li&gt;&amp;nbsp;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;개체 무결성&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;기본 테이블의 기본키를 구성하는 어떤 속성도 Null 값이나 중복값을 가질 수 없다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;참조 무결성&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;릴레이션은 참조할 수 없는 외래키 값을 가질 수 없다&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;18. 관계 대수&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;관계형 데이터베이스에서 원하는 정보와 그 정보를 검색하기 위해서 어떻게 유도하는가를 기술하는 절차적인 언어&lt;/li&gt;
&lt;li&gt;릴레이션을 처리하기 위해 연산자와 연산 규칙을 제공하며, 피연산자와 연산 결과가 모두 릴레이션&lt;/li&gt;
&lt;li&gt;질의에 대한 해를 구하기 위해 수행해야 할 연산의 순서를 명시&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;19. 순수 관계 연산자&lt;/b&gt;&lt;/p&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;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 14.2512%;&quot;&gt;&lt;b&gt;이름&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 79.3478%;&quot;&gt;설명&lt;/td&gt;
&lt;td style=&quot;width: 6.28019%;&quot;&gt;기호&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td style=&quot;width: 14.2512%;&quot;&gt;&lt;b&gt;Select(수평 연산)&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 79.3478%;&quot;&gt;릴레이션에 존재하는 튜플 중에서 선택 조건을 만족하는 튜플의 부분집합을 구하여 새로운 릴레이션을 만드는 연산&lt;/td&gt;
&lt;td style=&quot;width: 6.28019%;&quot;&gt;&amp;sigma;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td style=&quot;width: 14.2512%;&quot;&gt;&lt;b&gt;Project(수직 연산자)&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 79.3478%;&quot;&gt;주어진 릴레이션에서 속성 리스트에 제시된 속성 값만을 추출하여 새로운 릴레이션을 만드는 연산&lt;/td&gt;
&lt;td style=&quot;width: 6.28019%;&quot;&gt;&amp;pi;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td style=&quot;width: 14.2512%;&quot;&gt;&lt;b&gt;Join&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 79.3478%;&quot;&gt;공통 속성을 중심으로 두 개의 릴레이션을 하나로 합쳐서 새로운 릴레이션을 만드는 연산&lt;/td&gt;
&lt;td style=&quot;width: 6.28019%;&quot;&gt;⋈&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td style=&quot;width: 14.2512%;&quot;&gt;&lt;b&gt;Division&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 79.3478%;&quot;&gt;Y가 X의 부분집합인 두 개의 릴레이션 R(X)와 S(Y)가 있을 때, R의 속성이 S의 속성값을 모두 가진 튜플에서 S가 가진 속성을 제외한 속성만을 구하는 연산&lt;/td&gt;
&lt;td style=&quot;width: 6.28019%;&quot;&gt;&amp;divide;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;20. 일반 집합 연산자&lt;/b&gt;&lt;/p&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;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 17.029%;&quot;&gt;&lt;b&gt;이름&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 76.3285%;&quot;&gt;설명&lt;/td&gt;
&lt;td style=&quot;width: 6.52174%;&quot;&gt;기호&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td style=&quot;width: 17.029%;&quot;&gt;&lt;b&gt;Union(합집합)&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 76.3285%;&quot;&gt;두 릴레이션에 존재하는 튜플의 합집합을 구하되, 결과로 생성된 릴레이션에서 중복되는 튜플은 제거되는 연산&lt;/td&gt;
&lt;td style=&quot;width: 6.52174%;&quot;&gt;&amp;cup;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td style=&quot;width: 17.029%;&quot;&gt;&lt;b&gt;Intersection(교집합)&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 76.3285%;&quot;&gt;두 릴레이션에 존재하는 튜플의 교집합을 구하는 연산&lt;/td&gt;
&lt;td style=&quot;width: 6.52174%;&quot;&gt;&amp;cap;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td style=&quot;width: 17.029%;&quot;&gt;&lt;b&gt;Difference(차집합)&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 76.3285%;&quot;&gt;두 릴레이션에 존재하는 튜플의 차집합을 구하는 연산&lt;/td&gt;
&lt;td style=&quot;width: 6.52174%;&quot;&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td style=&quot;width: 17.029%;&quot;&gt;&lt;b&gt;Cartesian Product(교차곱)&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 76.3285%;&quot;&gt;두 릴레이션에 있는 튜플들의 순서쌍을 구하는 연산, 교차곱의 디그리는 두 릴레이션의 디그리를 더한 것과 같고, 카디널리티는 두 릴레이션의 카디널리티를 곱한 것과 같음&lt;/td&gt;
&lt;td style=&quot;width: 6.52174%;&quot;&gt;x&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;21. 관계해석&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;관계 데이터의 연산을 표현하는 방법&lt;/li&gt;
&lt;li&gt;원하는 정보가 무엇이라는 것만 정의하는 비절차적 특성을 지님&lt;/li&gt;
&lt;li&gt;원하는 정보를 정의할 때는 계산 수식을 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;22. 이상(Anomaly)&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;데이터베이스 내에 데이터들이 불필요하게 중복되어 릴레이션 조작 시 예기치 않게 발생하는 곤란한 현상&lt;/li&gt;
&lt;li&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;삽입 이상&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;의도와는 상관없이 원하지 않은 값들로 인해 테이블에 데이터를 삽입할 수 없게 되는 현상&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;삭제 이상&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;테이블에서 튜플을 삭제할 때 의도와는 상관없는 값들이 연쇄 삭제되는 현상&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;갱신 이상&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;테이블에서 튜플에 있는 속성 값을 갱신할 때 일부 튜플의 정보만 갱신되어 정보에 불일치성이 생기는 현상&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;23. 함수적 종속&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;함수적 종속(Functional Dependency)&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;속성 X의 값 각각에 대해 항상 속성 Y의 값이 오직 하나만 연관되어있을 때 Y는 X에 함수적 종속된다고 함, X &amp;rarr; Y&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;완전 함수적 종속(Full &quot;)&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;속성 집합 X 전체에 대해 함수적 종속이면서 X의 다른 진부분 집합 중 어떤 집합에도 함수적 종속이 아닐 때를 말함&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;부분 함수적 종속(Partial &quot;)&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;완전 함수적 종속과 다르게 전체에 종속이면서 일부에도 함수적 종속일 때를 말함&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;이행적 함수적 종속(Transitive &quot;)&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;X &amp;rarr; Y 이고, Y &amp;rarr; Z일 때, X &amp;rarr; Z를 만족하는 관계&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;24. 정규화&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;테이블의 속성들이 상호 종속적인 관계를 갖는 특성을 이용하여 테이블을 무손실 분해하는 과정&lt;/li&gt;
&lt;li&gt;가능한 한 중복을 제거하여 이상 발생 가능성을 줄이는 것을 목표로 함&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;25. 정규화 과정&lt;/b&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;제 1 정규형: 테이블의 모든 속성 값이 원자 값으로만 되어 있는 정규형&lt;/li&gt;
&lt;li&gt;제 2 정규형: 테이블이 제 1 정규형이고, 기본키가 아닌 모든 속성이 기본키에 대하여 완전 함수적 종속을 만족하는 정규형&lt;/li&gt;
&lt;li&gt;제 3 정규형: 테이블이 제 2 정규형이고, 기본키가 아닌 모든 속성이 기본키에 대해 이행적 함수적 종속을 만족하지 않는 정규형&lt;/li&gt;
&lt;li&gt;BCNF: 테이블에서 모든 결정자가 후보키인 정규형, 제 3 정규형에 후보키가 여러 개 존재하고, 이러한 후보키들이 서로 중첩되어 나타나는 경우에 적용 가능&lt;/li&gt;
&lt;li&gt;제 4 정규형: 테이블에&lt;span&gt;&amp;nbsp;&lt;/span&gt;다중 값 종속&lt;span&gt;&amp;nbsp;&lt;/span&gt;A &amp;rarr;&amp;rarr; B가 존재할 경우 테이블의 모든 속성이 A에 함수적 종속 관계를 만족하는 정규형&lt;/li&gt;
&lt;li&gt;제 5 정규형: 테이블의 모든&lt;span&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;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;26. 정규화 과정 정리(도부이결다조)&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;비정규 릴레이션&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;rarr;&lt;span&gt;&amp;nbsp;&lt;/span&gt;1NF&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;rarr;&lt;span&gt;&amp;nbsp;&lt;/span&gt;2NF&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;rarr;&lt;span&gt;&amp;nbsp;&lt;/span&gt;3NF&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;rarr;&lt;span&gt;&amp;nbsp;&lt;/span&gt;BCNF&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;rarr;&lt;span&gt;&amp;nbsp;&lt;/span&gt;4NF&lt;span&gt;&amp;nbsp;&lt;/span&gt;&amp;rarr;&lt;span&gt;&amp;nbsp;&lt;/span&gt;5NF&lt;/li&gt;
&lt;li&gt;도메인이 원자값 &amp;rarr;&lt;span&gt;&amp;nbsp;&lt;/span&gt;부분적 함수 종속 제거 &amp;rarr;&lt;span&gt;&amp;nbsp;&lt;/span&gt;이행적 함수 종속 제거 &amp;rarr;&lt;span&gt;&amp;nbsp;&lt;/span&gt;결정자이면서 후보키가 아닌 것 제거 &amp;rarr;&lt;span&gt;&amp;nbsp;&lt;/span&gt;다치 종속 제거 &amp;rarr;&lt;span&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;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;27. 반정규화&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;시스템의 성능을 향상하고 개발 및 운영의 편의성 등을 높이기 위해 정규화 된 데이터 모델을 의도적으로 통합, 중복, 분리하여 정규화 원칙을 위배하는 행위&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;28. 시스템 카탈로그&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;시스템 그 자체에 관련이 있는 다양한 객체에 관한 정보를 포함하는 시스템 데이터베이스&lt;/li&gt;
&lt;li&gt;시스템 카탈로그 내의 각 테이블은 사용자를 포함하여 DBMS에서 지원하는 모든 데이터 객체에 대한 정의나 명세에 관한 정보를 유지 관리하는 시스템 테이블임&lt;/li&gt;
&lt;li&gt;카탈로그들이 생성되면 데이터 사전에 저장되기 때문에 좁은 의미로 카탈로그를 데이터 사전이라고 함&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;29. 트랜잭션&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;데이터베이스의 상태를 변환시키는 하나의 논리적 기능을 수행하기 위한 작업의 단위 또는 한꺼번에 모두 수행되어야 할 일련의 연산들&lt;/li&gt;
&lt;li&gt;데이터베이스 시스템에서 병행 제어 및 회복 작업 시 처리되는 작업의 논리적 단위로 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;30. 트랜잭션의 특성(원일독영)&lt;/b&gt;&lt;/p&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;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;특성&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;의미&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;원자성&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;트랜잭션의 연산은 데이터베이스에 모두 반영되도록 완료되든지 아니면 복구되어야 함&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;일관성&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;트랜잭션이 그 실행을 성공적으로 완료하면 언제나 일관성 있는 데이터베이스 상태로 변환함&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;독립성, 격리성, 순차성&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;둘 이상의 트랜잭션이 동시에 병행 실행되는 경우 어느 하나의 트랜잭션 실행 중에 다른 트랜잭션의 연산이 끼어들 수 없음&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;영속성, 지속성&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;성공적으로 완료된 트랜잭션의 결과는 시스템이 고장나더라도 영구적으로 반영되어야 함&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;31. CRUD 분석&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로세스와 테이블 간에 CRUD 매트릭스를 만들어서 트랜잭션을 분석하는 것&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;32. 인덱스&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;데이터 레코드를 빠르게 접근하기 위해 &amp;lt;키 값, 포인터&amp;gt; 쌍으로 구성되는 데이터 구조&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;33. 뷰&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;사용자에게 접근이 허용된 자료만을 제한적으로 보여주기 위해 하나 이상의 기본 테이블로부터 유도된, 이름을 가지는 가상 테이블&lt;/li&gt;
&lt;li&gt;뷰가 정의된 기본 테이블이나 뷰를 삭제하면 그 테이블이나 뷰를 기초로 정의된 다른 뷰도 자동으로 삭제됨&lt;/li&gt;
&lt;li&gt;정의할 때는&lt;span&gt;&amp;nbsp;&lt;/span&gt;CREATE, 제거할 때는&lt;span&gt;&amp;nbsp;&lt;/span&gt;DROP&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;34. 파티션의 종류&lt;/b&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;범위 분할&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;지정한 열의 값을 기준으로 분할&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;해시 분할&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;해시 함수를 적용한 결과 값에 따라 데이터를 분할&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;조합 분할&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;범위 분할로 분할한 다음 해시 함수를 적용하여 다시 분할하는 방식&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;35. 분산 데이터베이스의 목표(위중병장)&lt;/b&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;위치 투명성&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;액세스하려는 데이터베이스의 실제 위치를 알 필요 없이 단지 데이터베이스의 논리적인 명칭만으로 액세스할 수 있음&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;중복 투명성&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;동일 데이터가 여러 곳에 중복되어 있더라도 사용자는 마치 하나의 데이터만 존재하는 것처럼 사용하고, 시스템은 자동으로 여러 자료에 대한 작업을 수행&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;병행 투명성&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;분산 데이터베이스와 관련된 다수의 트랜잭션들이 동시에 실현되더라도 그 트랜잭션의 결과는 영향을 받지 않음&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;장애 투명성&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;트랜잭션, DBMS, 네트워크, 컴퓨터 장애에도 불구하고 트랜잭션을 정확하게 처리함&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;36. RTO/RPO&lt;/b&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;RTO(목표 복구 시간)&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;비상사태 또는 업무 중단 시점으로부터 복구되어 가동될 때까지의 소요 시간&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;RPO(목표 복구 시점)&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;비상사태 또는 업무 중단 시점으로부터 데이터를 복구할 수 있는 기준점&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;37. 임의 접근통제(DAC)&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;데이터에 접근하는 사용자의 신원에 따라 접근 권한을 부여하는 방식&lt;/li&gt;
&lt;li&gt;데이터 소유자가 접근통제 권한을 지정하고 제어함&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;38. 강제 접근통제(MAC)&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;주체와 객체의 등급을 비교하여 접근 권한을 부여하는 방식&lt;/li&gt;
&lt;li&gt;시스템이 접근통제 권한을 지정&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;39. 역할기반 접근통제(RBAC)&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;사용자의 역할에 따라 접근 권한을 부여하는 방식&lt;/li&gt;
&lt;li&gt;중앙관리자가 접근통제 권한을 지정&lt;/li&gt;
&lt;li&gt;다른 두 접근통제 기법의 단점을 보완하고 다중 프로그래밍 환경에 최적화됨&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;40. DAS(Direct Attached Storage)&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;서버와 저장장치를 전용 케이블로 직접 연결하는 방식&lt;/li&gt;
&lt;li&gt;직접 연결 방식이므로 다른 서버에서 접근하거나 파일을 공유할 수 없음&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;41. NAS(Network Attached Storage)&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;서버와 저장장치를 네트워크를 통해 연결하는 방식&lt;/li&gt;
&lt;li&gt;이더넷 스위치를 통해 다른 서버에서도 스토리지에 접근할 수 있어 파일 공유가 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;42. SAN(Storage Area Network)&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;DAS의 빠른 처리와&lt;span&gt;&amp;nbsp;&lt;/span&gt;NAS의 파일 공유 장점을 혼합한 방식으로, 서버와 저장장치를 연결하는 전용 네트워크를 별도로 구성하는 방식&lt;/li&gt;
&lt;li&gt;파이버 채널 스위치를 이용하여 네트워크를 구성, 서버들이 저장장치 및 파일을 공유할 수 있다.&lt;/li&gt;
&lt;li&gt;광케이블로 연결하므로 처리 속도가 빠름&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;43. 자료 구조의 분루&lt;/b&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 13.3721%;&quot;&gt;선형 구조&lt;/td&gt;
&lt;td style=&quot;width: 86.6279%;&quot;&gt;배열, 선형 리스트, 스택, 큐, 데크&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 13.3721%;&quot;&gt;비선형 구조&lt;/td&gt;
&lt;td style=&quot;width: 86.6279%;&quot;&gt;트리, 그래프&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;44. 스택&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;리스트의 한쪽 끝으로만 자료의 삽입, 삭제 작업이 이루어지는 자료 구조&lt;/li&gt;
&lt;li&gt;LIFO(Last In First Out)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;45. 데크&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;삽입과 삭제가 리스트의 양쪽 끝에서 모두 발생할 수 있는 자료 구조&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;46. 방향/무방향 그래프의 최대 간선 수&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;방향 그래프 최대 간선 수: n(n-1)&lt;/li&gt;
&lt;li&gt;무방향 그래프에서 최대 간선 수: n(n-1)/2&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;47. 트리 관련 용어&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-10-20 오후 9.10.48.png&quot; data-origin-width=&quot;741&quot; data-origin-height=&quot;367&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ezLrTw/dJMb9aqahCy/TQ6VQ1mZZK0dtkmKDFs5Ik/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ezLrTw/dJMb9aqahCy/TQ6VQ1mZZK0dtkmKDFs5Ik/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ezLrTw/dJMb9aqahCy/TQ6VQ1mZZK0dtkmKDFs5Ik/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FezLrTw%2FdJMb9aqahCy%2FTQ6VQ1mZZK0dtkmKDFs5Ik%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;741&quot; height=&quot;367&quot; data-filename=&quot;스크린샷 2025-10-20 오후 9.10.48.png&quot; data-origin-width=&quot;741&quot; data-origin-height=&quot;367&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;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 19.4186%;&quot;&gt;&lt;span&gt;&lt;b&gt;구분&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 49.0698%;&quot;&gt;&lt;span&gt;&lt;b&gt;설명&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 31.5116%;&quot;&gt;&lt;span&gt;&lt;b&gt;예시&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 19.4186%;&quot;&gt;&lt;span&gt;&lt;b&gt;Node&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 49.0698%;&quot;&gt;&lt;span&gt;트리를&lt;span&gt; &lt;/span&gt;구성하는&lt;span&gt; &lt;/span&gt;기본&lt;span&gt; &lt;/span&gt;원소&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 31.5116%;&quot;&gt;&lt;span&gt;&lt;span&gt;예&lt;/span&gt;) A,B,C,D,E,F,G,H,I,J&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 19.4186%;&quot;&gt;&lt;span&gt;&lt;b&gt;Root node&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;b&gt;(&lt;/b&gt;&lt;/span&gt;&lt;b&gt;뿌리&lt;/b&gt;&lt;span&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;b&gt;노드&lt;/b&gt;&lt;span&gt;&lt;b&gt;)&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 49.0698%;&quot;&gt;&lt;span&gt;&lt;span&gt;(&lt;/span&gt;뿌리&lt;span&gt;)&lt;/span&gt;부모가&lt;span&gt; &lt;/span&gt;없는&lt;span&gt; &lt;/span&gt;최상위&lt;span&gt; &lt;/span&gt;루트&lt;span&gt; &lt;/span&gt;노드&lt;/span&gt;&lt;br /&gt;&lt;span&gt;트리는&lt;span&gt; &lt;/span&gt;하나의&lt;span&gt; &lt;/span&gt;루트&lt;span&gt; &lt;/span&gt;노드만을&lt;span&gt; &lt;/span&gt;가진다&lt;span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 31.5116%;&quot;&gt;&lt;span&gt;&lt;span&gt;예&lt;/span&gt;) A&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 19.4186%;&quot;&gt;&lt;span&gt;&lt;b&gt;Leaf&amp;nbsp;node&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;b&gt;(&lt;/b&gt;&lt;/span&gt;&lt;b&gt;잎&lt;/b&gt;&lt;span&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;b&gt;노드&lt;/b&gt;&lt;span&gt;&lt;b&gt;)&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 49.0698%;&quot;&gt;&lt;span&gt;자식이&lt;span&gt; &lt;/span&gt;없는&lt;span&gt; &lt;/span&gt;노드&lt;span&gt; (&lt;/span&gt;맨&lt;span&gt; &lt;/span&gt;마지막&lt;span&gt; &lt;/span&gt;끝&lt;span&gt; &lt;/span&gt;노드&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 31.5116%;&quot;&gt;&lt;span&gt;&lt;span&gt;예&lt;/span&gt;) H, I, J, F, G&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 19.4186%;&quot;&gt;&lt;span&gt;&lt;b&gt;Internal&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;b&gt;(&lt;/b&gt;&lt;/span&gt;&lt;b&gt;내부&lt;/b&gt;&lt;span&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;b&gt;노드&lt;/b&gt;&lt;span&gt;&lt;b&gt;)&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 49.0698%;&quot;&gt;&lt;span&gt;Leaf node &lt;span&gt;가&lt;/span&gt; &lt;span&gt;아닌&lt;/span&gt; &lt;span&gt;노드&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 31.5116%;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 19.4186%;&quot;&gt;&lt;span&gt;&lt;b&gt;Edge/Branch/Link&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;b&gt;(&lt;/b&gt;&lt;/span&gt;&lt;b&gt;관계&lt;/b&gt;&lt;span&gt;&lt;b&gt;,&lt;/b&gt;&lt;/span&gt;&lt;b&gt;가지&lt;/b&gt;&lt;span&gt;&lt;b&gt;,&lt;/b&gt;&lt;/span&gt;&lt;b&gt;분기&lt;/b&gt;&lt;span&gt;&lt;b&gt;)&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 49.0698%;&quot;&gt;&lt;span&gt;&lt;span&gt;노드를&lt;/span&gt; &lt;span&gt;연결하는&lt;/span&gt; &lt;span&gt;선&lt;/span&gt; , &lt;span&gt;뿌리&lt;/span&gt;(root)&lt;span&gt;와&lt;/span&gt; &lt;span&gt;잎&lt;/span&gt;(leaf)&lt;span&gt;사이의&lt;/span&gt; &lt;span&gt;모든&lt;/span&gt; &lt;span&gt;노드&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 31.5116%;&quot;&gt;&lt;span&gt;&lt;span&gt;예&lt;/span&gt;) A, B, C, D, E&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 19.4186%;&quot;&gt;&lt;span&gt;&lt;b&gt;Degree&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;b&gt;(&lt;/b&gt;&lt;/span&gt;&lt;b&gt;노드의&lt;/b&gt;&lt;span&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;b&gt;차수&lt;/b&gt;&lt;span&gt;&lt;b&gt;)&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 49.0698%;&quot;&gt;&lt;span&gt;하위&lt;span&gt; &lt;/span&gt;트리개수&lt;span&gt; / &lt;/span&gt;각&lt;span&gt; &lt;/span&gt;노드가&lt;span&gt; &lt;/span&gt;지닌&lt;span&gt; &lt;/span&gt;가지의&lt;span&gt; &lt;/span&gt;수&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;(&lt;/span&gt;연결된자식&lt;span&gt; &lt;/span&gt;노드의&lt;span&gt; &lt;/span&gt;수&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 31.5116%;&quot;&gt;&lt;span&gt;&lt;span&gt;예&lt;/span&gt;) A&lt;span&gt;의&lt;/span&gt; Degree = 2&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 19.4186%;&quot;&gt;&lt;span&gt;&lt;b&gt;Order&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;b&gt;(&lt;/b&gt;&lt;/span&gt;&lt;b&gt;계수&lt;/b&gt;&lt;span&gt;&lt;b&gt;/&lt;/b&gt;&lt;/span&gt;&lt;b&gt;차수&lt;/b&gt;&lt;span&gt;&lt;b&gt;)&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 49.0698%;&quot;&gt;&lt;span&gt;자식&lt;span&gt; &lt;/span&gt;노드들&lt;span&gt; &lt;/span&gt;중&lt;span&gt; &lt;/span&gt;최대&lt;span&gt; &lt;/span&gt;개수&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 31.5116%;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 19.4186%;&quot;&gt;&lt;span&gt;&lt;b&gt;Depth&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;b&gt;(&lt;/b&gt;&lt;/span&gt;&lt;b&gt;노드의&lt;/b&gt;&lt;span&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;b&gt;깊이&lt;/b&gt;&lt;span&gt;&lt;b&gt;)&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 49.0698%;&quot;&gt;&lt;span&gt;루트에서&lt;span&gt; &lt;/span&gt;어떤&lt;span&gt; &lt;/span&gt;노드에&lt;span&gt; &lt;/span&gt;도달하기&lt;span&gt; &lt;/span&gt;위해&lt;span&gt; &lt;/span&gt;거쳐야&lt;span&gt; &lt;/span&gt;하는&lt;span&gt; &lt;/span&gt;간선의&lt;span&gt; &lt;/span&gt;수&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 31.5116%;&quot;&gt;&lt;span&gt;&lt;span&gt;예&lt;/span&gt;) D &lt;span&gt;의&lt;/span&gt; &lt;span&gt;경로&lt;/span&gt; &lt;span&gt;깊이&lt;/span&gt; 2&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 19.4186%;&quot;&gt;&lt;span&gt;&lt;b&gt;Level&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;b&gt;(&lt;/b&gt;&lt;/span&gt;&lt;b&gt;노드의&lt;/b&gt;&lt;span&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;b&gt;레벨&lt;/b&gt;&lt;span&gt;&lt;b&gt;)&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 49.0698%;&quot;&gt;&lt;span&gt;특정&lt;span&gt; &lt;/span&gt;깊이를&lt;span&gt; &lt;/span&gt;가지는&lt;span&gt; &lt;/span&gt;노드의&lt;span&gt; &lt;/span&gt;집합&lt;span&gt; (&lt;/span&gt;같은&lt;span&gt; &lt;/span&gt;깊이&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 31.5116%;&quot;&gt;&lt;span&gt;&lt;span&gt;예&lt;/span&gt;) A&lt;span&gt;의&lt;/span&gt; &lt;span&gt;레벨&lt;/span&gt; : &lt;span&gt;레벨&lt;/span&gt;0&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 19.4186%;&quot;&gt;&lt;span&gt;&lt;b&gt;Height&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;b&gt;(&lt;/b&gt;&lt;/span&gt;&lt;b&gt;높이&lt;/b&gt;&lt;span&gt;&lt;b&gt;)&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 49.0698%;&quot;&gt;&lt;span&gt;루트&lt;span&gt; &lt;/span&gt;노드에서&lt;span&gt; &lt;/span&gt;가장&lt;span&gt; &lt;/span&gt;깊숙히&lt;span&gt; &lt;/span&gt;있는&lt;span&gt; &lt;/span&gt;노드의&lt;span&gt; &lt;/span&gt;깊이&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 31.5116%;&quot;&gt;&lt;span&gt;&lt;span&gt;예&lt;/span&gt;) &lt;span&gt;가장&lt;/span&gt; &lt;span&gt;긴&lt;/span&gt; &lt;span&gt;깊이&lt;/span&gt; : 4&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 19.4186%;&quot;&gt;&lt;span&gt;&lt;b&gt;Size&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;b&gt;(&lt;/b&gt;&lt;/span&gt;&lt;b&gt;크기&lt;/b&gt;&lt;span&gt;&lt;b&gt;)&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 49.0698%;&quot;&gt;&lt;span&gt;특정&lt;span&gt; &lt;/span&gt;노드가&lt;span&gt; &lt;/span&gt;자신을&lt;span&gt; &lt;/span&gt;포함한&lt;span&gt; &lt;/span&gt;자손의&lt;span&gt; &lt;/span&gt;수&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 31.5116%;&quot;&gt;&lt;span&gt;&lt;span&gt;예&lt;/span&gt;) &lt;span&gt;노드&lt;/span&gt; B&lt;span&gt;의&lt;/span&gt; &lt;span&gt;크기&lt;/span&gt; : 6&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 19.4186%;&quot;&gt;&lt;span&gt;&lt;b&gt;Parent node&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;b&gt;(&lt;/b&gt;&lt;/span&gt;&lt;b&gt;부모&lt;/b&gt;&lt;span&gt;&lt;b&gt;)&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 49.0698%;&quot;&gt;&lt;span&gt;&lt;span&gt;선조&lt;/span&gt;( ancestor ) : &lt;span&gt;부모&lt;/span&gt; &lt;span&gt;노드와&lt;/span&gt; &lt;span&gt;그의&lt;/span&gt; &lt;span&gt;부모들&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 31.5116%;&quot;&gt;&lt;span&gt;&lt;span&gt;예&lt;/span&gt;) D, E&lt;span&gt;의&lt;/span&gt; &lt;span&gt;부모노드는&lt;/span&gt; B&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 19.4186%;&quot;&gt;&lt;span&gt;&lt;b&gt;Child node&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;b&gt;(&lt;/b&gt;&lt;/span&gt;&lt;b&gt;자식&lt;/b&gt;&lt;span&gt;&lt;b&gt;)&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 49.0698%;&quot;&gt;&lt;span&gt;&lt;span&gt;자손&lt;/span&gt;( descendant ) : &lt;span&gt;자식&lt;/span&gt; &lt;span&gt;노드와&lt;/span&gt; &lt;span&gt;그&lt;/span&gt; &lt;span&gt;자식들&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 31.5116%;&quot;&gt;&lt;span&gt;&lt;span&gt;예&lt;/span&gt;) B&lt;span&gt;의&lt;/span&gt; &lt;span&gt;자식노드는&lt;/span&gt; D, E&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 19.4186%;&quot;&gt;&lt;span&gt;&lt;b&gt;Sibling node&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;b&gt;(&lt;/b&gt;&lt;/span&gt;&lt;b&gt;형제&lt;/b&gt;&lt;span&gt;&lt;b&gt;)&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 49.0698%;&quot;&gt;&lt;span&gt;같은&lt;span&gt; &lt;/span&gt;부모를&lt;span&gt; &lt;/span&gt;가지는&lt;span&gt; &lt;/span&gt;노드&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 31.5116%;&quot;&gt;&lt;span&gt;예&lt;span&gt;) D, E&lt;/span&gt;는&lt;span&gt; &lt;/span&gt;같은&lt;span&gt; &lt;/span&gt;부모를&lt;span&gt; &lt;/span&gt;갖는&lt;span&gt; &lt;/span&gt;형제노드&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 19.4186%;&quot;&gt;&lt;span&gt;&lt;b&gt;Subtree&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;span&gt;&lt;b&gt;(&lt;/b&gt;&lt;/span&gt;&lt;span&gt;&lt;b&gt;서브트리&lt;/b&gt;&lt;/span&gt;&lt;span&gt;&lt;b&gt;)&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 80.5814%;&quot; colspan=&quot;2&quot;&gt;&lt;span&gt;&lt;span&gt;A&lt;/span&gt;를&lt;span&gt; &lt;/span&gt;기준으로&lt;span&gt; B&lt;/span&gt;를&lt;span&gt; &lt;/span&gt;루트로&lt;span&gt; &lt;/span&gt;하면&lt;span&gt; &lt;/span&gt;왼쪽&lt;span&gt; &lt;/span&gt;서브트리&lt;span&gt;, C&lt;/span&gt;를&lt;span&gt; &lt;/span&gt;루트로&lt;span&gt; &lt;/span&gt;하면&lt;span&gt; &lt;/span&gt;오른쪽&lt;span&gt; &lt;/span&gt;서브트리라고&lt;span&gt; &lt;/span&gt;한다&lt;span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;48.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;하단은 예시를 보며 직접 푸는 것을 추천&amp;nbsp;&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Preorder, Inoredr, Postorder 운행법&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Infix, PostIfix, Prefix&lt;/li&gt;
&lt;li&gt;삽입, 선택, 버블, 퀵, 힙, 2-Way 합병 정렬&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>정보처리기사</category>
      <author>dobbyyo</author>
      <guid isPermaLink="true">https://dobbyyo.tistory.com/31</guid>
      <comments>https://dobbyyo.tistory.com/entry/%EC%A0%95%EB%B3%B4%EC%B2%98%EB%A6%AC%EA%B8%B0%EC%82%AC-%EC%8B%A4%EA%B8%B0-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%9E%85%EC%B6%9C%EB%A0%A5-%EA%B5%AC%ED%98%84#entry31comment</comments>
      <pubDate>Mon, 20 Oct 2025 21:21:29 +0900</pubDate>
    </item>
    <item>
      <title>정보처리기사 실기 - 요구사항 확인</title>
      <link>https://dobbyyo.tistory.com/entry/%EC%A0%95%EB%B3%B4%EC%B2%98%EB%A6%AC%EA%B8%B0%EC%82%AC-%EC%8B%A4%EA%B8%B0-%EC%9A%94%EA%B5%AC%EC%82%AC%ED%95%AD-%ED%99%95%EC%9D%B8</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. 나선형 모형(점진적 모형)&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;여러 번의 소프트웨어 개발 과정을 거쳐 점진적으로 완벽한 최종 소프트웨어를 개발하는 모형&lt;/li&gt;
&lt;li&gt;계획 수립&lt;span&gt;&amp;nbsp;&lt;/span&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;위험 분석&lt;span&gt;&amp;nbsp;&lt;/span&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;개발 및 검증&lt;span&gt;&amp;nbsp;&lt;/span&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;고객 평가&lt;span&gt;&amp;nbsp;&lt;/span&gt;순으로 반복&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;623&quot; data-origin-height=&quot;219&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/buN96a/dJMb9QywqnQ/LaQbRBs2EsLhzetkJDXNQk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/buN96a/dJMb9QywqnQ/LaQbRBs2EsLhzetkJDXNQk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/buN96a/dJMb9QywqnQ/LaQbRBs2EsLhzetkJDXNQk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbuN96a%2FdJMb9QywqnQ%2FLaQbRBs2EsLhzetkJDXNQk%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;623&quot; height=&quot;219&quot; data-origin-width=&quot;623&quot; data-origin-height=&quot;219&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. 폭포수 모형(고전적 생명 주기 모형)&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이전 단계로 돌아갈 수 없다는 전제하에 각 단계를 확실히 매듭짓고 그 결과를 철저하게 검토하여 승인 과정을 거친 후에 다음 단계를 진행하는 개발 방법론&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. 애자일 모형&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;고객의 요구사항 변화에 유연하게 대응할 수 있도록 일정한 주기를 반복하면서 개발하는 모형&lt;/li&gt;
&lt;li&gt;특정 개발 방법론이 아니라 고객과의 소통에 초점을 맞춘 방법론을 통칭&lt;/li&gt;
&lt;li&gt;스크럼,&lt;span&gt;&amp;nbsp;&lt;/span&gt;XP,&lt;span&gt;&amp;nbsp;&lt;/span&gt;칸반,&lt;span&gt;&amp;nbsp;&lt;/span&gt;Lean,&lt;span&gt;&amp;nbsp;&lt;/span&gt;기능 중심 개발(FDD)&lt;span&gt;&amp;nbsp;&lt;/span&gt;등&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;4. 애자일 개발 4가지 핵심 가치&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로세스와 도구보다는 개인과 상호작용에 더 가치를 둔다.&lt;/li&gt;
&lt;li&gt;방대한 문서보다는 실행되는 SW에 더 가치를 둔다.&lt;/li&gt;
&lt;li&gt;계약 협상보다는 고객과 협업에 더 가치를 둔다.&lt;/li&gt;
&lt;li&gt;계획을 따르기 보다는 변화에 반응하는 것에 더 가치를 둔다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;5. 소프트웨어 공학&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;소프트웨어의 위기를 극복하기 위한 방안으로 연구된 학문&lt;/li&gt;
&lt;li&gt;&lt;b&gt;소프트웨어 공학의 기본 원칙&lt;/b&gt;&lt;br /&gt;1) 현대적인 프로그래밍 기술을 계속적으로 적용해야한다.&lt;br /&gt;2) 개발된 소프트웨어의 품질이 유지되도록 지속적으로 검증해야한다.&lt;br /&gt;3) 소프트웨어 개발 관련 사항 및 결과에 대한 명확한 기록을 유지해야한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;6. 스크럼 개발 프로세스&lt;/b&gt;&lt;/p&gt;
&lt;table style=&quot;background-color: #ffffff; color: #212529; text-align: start; border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;프로세스&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;내용&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;스프린트 계획 회의&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;제품 백로그 중 이번 스프린트에서 수행할 작업을 대상으로 단기 일정을 수립하는 회의&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;스프린트&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;실제 개발 작업을 진행하는 과정으로, 보통 2~4주 정도의 기간 내에서 진행&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;일일 스크럼 회의&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;모든 팀원이 매일 약속된 시간에 약 15분 동안 진행 상황을 점검하는 회의, 남은 작업 시간은 번다운 차트에 표시&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;스프린트 검토 회의&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;부분 또는 전체 완성 제품이 요구사항에 잘 부합하는지 테스팅하는 회의&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;스프린트 회고&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;정해놓은 규칙 준수 여부 및 개선할 점을 확인하고 기록하는 것&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;7. XP(eXtreme Programming)&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;수시로 발생하는 고객의 요구사항에 유연하게 대응하기 위해 고객의 참여와 개발 과정의 반복을 극대화하여 개발 생산성을 향상시키는 방법&lt;/li&gt;
&lt;li&gt;5가지 핵심 가치(의단용존피)
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;의사소통&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;단순성&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;용기&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;존중&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;피드백&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;8. XP의 주요 실천 방법&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1) Pair Programming(짝 프로그래밍)&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;다른 사람과 함께 프로그래밍을 수행함으로써 개발에 대한 책임을 공동으로 나눠 갖는 환경을 조성한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2)&lt;span&gt;&amp;nbsp;&lt;/span&gt;Collective Ownership(공동 코드 소)&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;개발 코드에 대한 권한과 책임을 공동으로 소유한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3)&lt;span&gt;&amp;nbsp;&lt;/span&gt;Test-Driven Development(테스트 주도 개발)&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;개발자가 실제 코드를 작성하기 전에 테스트 케이스를 먼저 작성하므로 자신이 무엇을 해야할지를 정확히 파악한다.&lt;/li&gt;
&lt;li&gt;테스트가 지속적으로 진행될 수 있도록 자동화된 테스팅 구조(구조, 프레임워크)를 사용한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4)&lt;span&gt;&amp;nbsp;&lt;/span&gt;Whole Team(전체 팀)&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;개발에 참여하는 모든 구성원들은 각자 자신의 역할이 있고 그 역할에 대한 책임을 가져야 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5)&lt;span&gt;&amp;nbsp;&lt;/span&gt;Continuous Integration(CI) (계속적인 통합)&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;모듈 단위로 나눠서 개발된 코드들은 하나의 작업이 마무리될 때마다 지속적으로 통합된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;6)&lt;span&gt;&amp;nbsp;&lt;/span&gt;Refactoring(리팩토링)&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로그램을 쉽게 이해하고 쉽게 수정하여 빠르게 개발할 수 있도록 하기 위해 프로그램의 기능의 변경 없이 시스템을 재구성한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;7)&lt;span&gt;&amp;nbsp;&lt;/span&gt;Small Relesases(소규모 릴리즈)&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;릴리즈 기간을 짧게 반복함으로써 고객의 요구 변화에 신속히 대응할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;9. 기능 요구사항&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;시스템이 무엇을 하는지, 어떤 기능을 하는지 등의 기능이나 수행과 관련된 요구사항&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;시스템의 입력이나 출력으로 무엇이 포함되어야 하는 지에 대한 사항&lt;/li&gt;
&lt;li&gt;시스템이 어떤 데이터를 저장하거나 연산을 수행해야 하는지에 대한 사항&lt;/li&gt;
&lt;li&gt;시스템이 반드시 수행해야하는 기능&lt;/li&gt;
&lt;li&gt;사용자가 시스템을 통해 제공받기를 원하는 기능&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;10. 비기능 요구사항&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;품질이나 제약사항과 관련된 요구사항&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;시스템 장비 구성 요구사항&lt;/li&gt;
&lt;li&gt;성능 요구사항&lt;/li&gt;
&lt;li&gt;인터페이스 요구사항&lt;/li&gt;
&lt;li&gt;데이터를 구축하기 위해 필요한 요구사항&lt;/li&gt;
&lt;li&gt;테스트 요구사항&lt;/li&gt;
&lt;li&gt;보안 요구사항&lt;/li&gt;
&lt;li&gt;제약사항&lt;/li&gt;
&lt;li&gt;프로젝트 관리 요구사항&lt;/li&gt;
&lt;li&gt;프로젝트 자원 요구사항&lt;/li&gt;
&lt;li&gt;품질 요구사항:&lt;span&gt;&amp;nbsp;&lt;/span&gt;가용성,&lt;span&gt;&amp;nbsp;&lt;/span&gt;정합성,&lt;span&gt;&amp;nbsp;&lt;/span&gt;대응성,&lt;span&gt;&amp;nbsp;&lt;/span&gt;보안성,&lt;span&gt;&amp;nbsp;&lt;/span&gt;상호 호환성,&lt;span&gt;&amp;nbsp;&lt;/span&gt;이식성,&lt;span&gt;&amp;nbsp;&lt;/span&gt;확장성&lt;span&gt;&amp;nbsp;&lt;/span&gt;등&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;11. 요구사항 분석&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;소프트웨어 개발의 실제적인 첫 단계로, 개발 대상에 대한 사용자의 요구사항을 이해하고 문서화하는 활동&lt;/li&gt;
&lt;li&gt;사용자 요구의 타당성을 조사하고 비용과 일정에 대한 제약을 설정&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;12. 자료 흐름도(DFD) - C등급&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;요구사항 분석에서 자료의 흐름 및 변환 과정과 기능을 도형 중심으로 기술하는 방법&lt;/li&gt;
&lt;li&gt;자료 흐름 그래프, 버블 차트라고도 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;13. 자료 흐름도의 구성 요소(프자자단)&lt;/b&gt;&lt;/p&gt;
&lt;table style=&quot;background-color: #ffffff; color: #212529; text-align: start; border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;기호&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;의미&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;프로세스&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;자료를 변환시키는 시스템의 한 부분을 나타내며 처리, 기능, 변환, 버블이라고도 함&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;자료 흐름&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;자료의 이동이나 연관관계를 나타냄&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;자료 저장소&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;시스템에서의 자료 저장소(파일, 데이터베이스)를 나타냄&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;단말&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;시스템과 교신하는 외부 개체로, 입력 데이터가 만들어지고 출력 데이터를 받음&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;14. 자료 사전(메타 데이터)&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&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;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;기호&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;의미&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;=&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;자료의 정의: ~로 구성되어 있다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;+&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;자료의 연결: 그리고&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;()&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;자료의 생략: 생략 가능한 자료&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;[]&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;자료의 선택: 또는&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;{}&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;자료의 반복: Iteration of&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;* *&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;자료의 설명: 주석&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;15. HIPO&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;시스템의 분석 및 설계, 또는 문서화에 사용되는 기법&lt;/li&gt;
&lt;li&gt;시스템 실행 과정인 입력/처리/출력의 기능을 표현한 것&lt;/li&gt;
&lt;li&gt;하향식 소프트웨어 개발을 위한 문서화 도구&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;16. 집합 관계&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;하나의 사물이 다른 사물에 포함되어 있는 관계&lt;/li&gt;
&lt;li&gt;포함하는 쪽과 포함되는 쪽은 서로 독립적이다.&lt;/li&gt;
&lt;li&gt;포함되는 쪽에서 포함하는 쪽으로 속이 빈 마름모를 연결하여 표현&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;438&quot; data-origin-height=&quot;350&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/s0u7c/dJMb8Vs0oNw/iUqeJdgInZAcnlU5lnTuDK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/s0u7c/dJMb8Vs0oNw/iUqeJdgInZAcnlU5lnTuDK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/s0u7c/dJMb8Vs0oNw/iUqeJdgInZAcnlU5lnTuDK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fs0u7c%2FdJMb8Vs0oNw%2FiUqeJdgInZAcnlU5lnTuDK%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;438&quot; height=&quot;350&quot; data-origin-width=&quot;438&quot; data-origin-height=&quot;350&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;17. 포함 관계 - C등급&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;포함하는 사물의 변화가 포함되는 사물에게 영향을 미치는 관계&lt;/li&gt;
&lt;li&gt;포함하는 쪽과 포함되는 쪽은 서로 독립될 수 없고 생명주기를 함께한다.&lt;/li&gt;
&lt;li&gt;집합 관계와 다르게 속이 채워진 마름모를 연결하여 표현&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;396&quot; data-origin-height=&quot;332&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Yojy0/dJMb9WZJgCG/4oChNCjdZkxpSYN06juaA0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Yojy0/dJMb9WZJgCG/4oChNCjdZkxpSYN06juaA0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Yojy0/dJMb9WZJgCG/4oChNCjdZkxpSYN06juaA0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FYojy0%2FdJMb9WZJgCG%2F4oChNCjdZkxpSYN06juaA0%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;396&quot; height=&quot;332&quot; data-origin-width=&quot;396&quot; data-origin-height=&quot;332&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;18. 일반화 관계&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;하나의 사물이 다른 사물에 비해 더 일반적이거나 구체적인 관계&lt;/li&gt;
&lt;li&gt;일반적인 개념을 상위 혹은 부모라고 부르고 더 구체적인 개념을 하위 혹은 자식이라고 부른다.&lt;/li&gt;
&lt;li&gt;하위에서 상위 쪽으로 빈 화살표를 연결하여 표현&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;410&quot; data-origin-height=&quot;340&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bjnEjl/dJMb9PzCnKL/9OfzzQvd5ppt9kgVu9Ndy1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bjnEjl/dJMb9PzCnKL/9OfzzQvd5ppt9kgVu9Ndy1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bjnEjl/dJMb9PzCnKL/9OfzzQvd5ppt9kgVu9Ndy1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbjnEjl%2FdJMb9PzCnKL%2F9OfzzQvd5ppt9kgVu9Ndy1%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;410&quot; height=&quot;340&quot; data-origin-width=&quot;410&quot; data-origin-height=&quot;340&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;19. 의존 관계&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;연관 관계와 같이 사물 사이에 서로 연관은 있으나 필요에 의해 서로에게 영향을 주는 짧은 시간 동안만 연관을 유지하는 관계&lt;/li&gt;
&lt;li&gt;하나의 사물과 다른 사물이 소유 관계는 아니지만 사물의 변화가 다른 사물에도 영향을 미치는 관계&lt;/li&gt;
&lt;li&gt;영향을 주는 사물이 영향을 받는 사물 쪽으로 점선 화살표를 연결하여 표현&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;532&quot; data-origin-height=&quot;160&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bCmICL/dJMb9N9Du98/XmWfYXfAKIUCqzXmTEFfJ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bCmICL/dJMb9N9Du98/XmWfYXfAKIUCqzXmTEFfJ0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bCmICL/dJMb9N9Du98/XmWfYXfAKIUCqzXmTEFfJ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbCmICL%2FdJMb9N9Du98%2FXmWfYXfAKIUCqzXmTEFfJ0%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;532&quot; height=&quot;160&quot; data-origin-width=&quot;532&quot; data-origin-height=&quot;160&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;20. 실체화 관계 - C등급&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;사물이 할 수 있거나 해야하는 기능, 서로를 그룹화 할 수 있는 관계&lt;/li&gt;
&lt;li&gt;한 객체가 다른 객체에게 오퍼레이션을 수행하도록 지정하는 의미적 관계&lt;/li&gt;
&lt;li&gt;사물에서 기능 쪽으로 속이 빈 점선 화살표를 연결하여 표현&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;412&quot; data-origin-height=&quot;346&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zzG1p/dJMb9PzCnK3/qi70dhUTI9UdpV8KwbJee0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zzG1p/dJMb9PzCnK3/qi70dhUTI9UdpV8KwbJee0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zzG1p/dJMb9PzCnK3/qi70dhUTI9UdpV8KwbJee0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzzG1p%2FdJMb9PzCnK3%2Fqi70dhUTI9UdpV8KwbJee0%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;412&quot; height=&quot;346&quot; data-origin-width=&quot;412&quot; data-origin-height=&quot;346&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;21. 다이어그램&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;사물과 관계를 도형으로 표현한 것&lt;/li&gt;
&lt;li&gt;여러 관점에서 시스템을 가시화한 뷰를 제공하여 의사소통에 도움을 줌&lt;/li&gt;
&lt;li&gt;정적 모델링에서는 구조적 다이어그램을, 동적 모델링에서는 행위 다이어그램을 주로 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;22. 구조적 다이어그램의 종류 (클객컴배복패)&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;1)&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;클래스 다이어그램&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;클래스와 클래스가 가지는 속성, 클래스 사이의 관계를 표현&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;2)&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;객체 다이어그램&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;클래스에 속한 객체들(인스턴스)을 특정 시점의 객체와 객체 사이의 관계로 표현&lt;/li&gt;
&lt;li&gt;럼바우 객체지향 분석 기법에서 객체 모델링에 활용&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;3)&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;컴포넌트 다이어그램&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;실제 구현 모듈인 컴포넌트 간의 관계나 컴포넌트 간의 인터페이스를 표현&lt;/li&gt;
&lt;li&gt;구현 단계에서 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;4)&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;배치 다이어그램&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;결과물, 프로세스, 컴포넌트 등 물리적 요소들의 위치를 표현&lt;/li&gt;
&lt;li&gt;구현 단계에서 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;5)&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;복합체 구조 다이어그램&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;클래스나 컴포넌트가 복합 구조를 갖는 경우 그 내부 구조를 표현&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;6)&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;패키지 다이어그램&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;유스케이스나 클래스 등의 모델 요소들을 그룹화한 패키지들의 관계를 표현&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;23. 행위 다이어그램의 종류 (유순커상활상타)&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;1)&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;유스케이스 다이어그램&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;사용자의 요구를 분석하는 것으로, 기능 모델링 작업에 사용&lt;/li&gt;
&lt;li&gt;사용자와 사용 사례로 구성&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;2)&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;순차 다이어그램&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;상호작용하는 시스템이나 객체들이 주고받는 메시지를 표현&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;3)&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;커뮤니케이션 다이어그램&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;동작에 참여하는 객체들이 주고받는 메시지와 객체들 간의 연관 관계를 표현&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;4)&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;상태 다이어그램&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;하나의 객체가 자신이 속한 클래스의 상태 변화 혹은 다른 객체와의 상호작용에 따라 상태가 어떻게 변화하는 지를 표현&lt;/li&gt;
&lt;li&gt;럼바우 객체지향 분석 기법에서 동적 모델링에 활용&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5)&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;활동 다이어그램&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;시스템이 어떤 기능을 수행하는지 객체의 처리 로직이나 조건에 따른 처리의 흐름을 순서에 따라 표현&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;6)&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;상호작용 개요 다이어그램&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;상호작용 다이어그램 간의 제어 흐름을 표현&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;7)&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;타이밍 다이어그램&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;객체 상태 변화와 시간 제약을 명시적으로 표현&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;24. 스테레오 타입&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;UML에서 표현하는 기능 외에 추가적인 기능을 표현하는 것&lt;/li&gt;
&lt;li&gt;길러멧이라고 부르는 겹화살괄호(《》) 사이에 표현할 형태를 기술한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;25. 유스케이스 다이어그램&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&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;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;구성 요소&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;내용&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;시스템/시스템 범위&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;시스템 내부의 유스케이스들을 사각형으로 묶어 시스템의 범위를 표현한 것&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;액터&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;시스템과 상호작용을 하는 모든 외부 요소로 주로 사람이나 외부 시스템을 의미&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;유스케이스&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;사용자가 보는 관점에서 시스템이 액터에게 제공하는 서비스나 기능을 표현한 것&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;관계&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;액터와 유스케이스, 유스케이스와 유스케이스 사이에서 나타날 수 있으며&lt;span&gt;&amp;nbsp;&lt;/span&gt;포함 관계,&lt;span&gt;&amp;nbsp;&lt;/span&gt;확장 관계,&lt;span&gt;&amp;nbsp;&lt;/span&gt;일반화 관계로 나뉨&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;812&quot; data-origin-height=&quot;494&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tnJZX/dJMb83EztIx/BbhwNxF3BadMtrFbL3mxHK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tnJZX/dJMb83EztIx/BbhwNxF3BadMtrFbL3mxHK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tnJZX/dJMb83EztIx/BbhwNxF3BadMtrFbL3mxHK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtnJZX%2FdJMb83EztIx%2FBbhwNxF3BadMtrFbL3mxHK%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;812&quot; height=&quot;494&quot; data-origin-width=&quot;812&quot; data-origin-height=&quot;494&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;26. 활동 다이어그램 - C등급&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;사용자의 관점에서 시스템이 수행하는 기능을 처리 흐름에 따라 순서대로 표현한 것&lt;/li&gt;
&lt;li&gt;구성 요소내용&amp;nbsp;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 17.3913%;&quot;&gt;&lt;b&gt;구성 요소&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 82.4879%;&quot;&gt;내용&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td style=&quot;width: 17.3913%;&quot;&gt;&lt;b&gt;액션/액티비티&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 82.4879%;&quot;&gt;각각 더 이상 분해할 수 없는 단일 작업과 몇 개의 액션으로 분리될 수 있는 작업을 의미&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td style=&quot;width: 17.3913%;&quot;&gt;&lt;b&gt;시작 노드&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 82.4879%;&quot;&gt;액션이나 액티비티가 시작됨을 표현한 것&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td style=&quot;width: 17.3913%;&quot;&gt;&lt;b&gt;종료 노드&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 82.4879%;&quot;&gt;액티비티 안의 모든 흐름이 종료됨을 표현한 것&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td style=&quot;width: 17.3913%;&quot;&gt;&lt;b&gt;조건(판단) 노드&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 82.4879%;&quot;&gt;조건에 따라 제어의 흐름이 분리됨을 표현한 것, 들어오는 제어 흐름은 한 개이고 나가는 제어 흐름은 여러 개&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td style=&quot;width: 17.3913%;&quot;&gt;&lt;b&gt;병합 노드&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 82.4879%;&quot;&gt;여러 경로의 흐름이 하나로 합쳐짐을 표현한 것, 들어오는 제어 흐름은 여러 개이고 나가는 제어 흐름은 한 개&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td style=&quot;width: 17.3913%;&quot;&gt;&lt;b&gt;포크(Fork) 노드&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 82.4879%;&quot;&gt;액티비티의 흐름이 분리되어 수행됨을 표현한 것, 들어오는 액티비티 흐름은 한 개이고 나가는 액티비티 흐름은 여러 개&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td style=&quot;width: 17.3913%;&quot;&gt;&lt;b&gt;조인(Join) 노드&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 82.4879%;&quot;&gt;분리되어 수행되던 액티비티의 흐름이 다시 합쳐짐을 표현한 것, 들어오는 액티비티 흐름은 여러 개이고 나가는 액티비티 흐름은 한 개&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td style=&quot;width: 17.3913%;&quot;&gt;&lt;b&gt;스윔레인&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 82.4879%;&quot;&gt;액티비티 수행을 담당하는 주체를 구분하는 선, 가로 또는 세로 실선&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;27. 클래스 다이어그램&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&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;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 13.5266%;&quot;&gt;&lt;b&gt;구성 요서&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 86.3527%;&quot;&gt;내용&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td style=&quot;width: 13.5266%;&quot;&gt;&lt;b&gt;클래스&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 86.3527%;&quot;&gt;각각의 객체들이 갖는 속성과 오퍼레이션을 표현한 것, 이름과 속성, 오퍼레이션으로 3개의 구획을 나눔&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td style=&quot;width: 13.5266%;&quot;&gt;&lt;b&gt;제약 조건&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 86.3527%;&quot;&gt;속성에 입력될 값에 대한 제약 조건이나 오퍼레이션 수행 전후에 지정해야 할 조건이 있다면 이를 적으며 클래스 안에 기술할 때는 중괄호를 이용&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td style=&quot;width: 13.5266%;&quot;&gt;&lt;b&gt;관계&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 86.3527%;&quot;&gt;클래스와 클래스 사이의 연관성을 표현,&lt;span&gt;&amp;nbsp;&lt;/span&gt;연관,&lt;span&gt;&amp;nbsp;&lt;/span&gt;집합,&lt;span&gt;&amp;nbsp;&lt;/span&gt;포함,&lt;span&gt;&amp;nbsp;&lt;/span&gt;일반화,&lt;span&gt;&amp;nbsp;&lt;/span&gt;의존&lt;span&gt;&amp;nbsp;&lt;/span&gt;관계가 있음&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;28. 연관 클래스 - C등급&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;연관 관계에 있는 두 클래스에 추가적으로 표현해야 할 속성이나 오퍼레이션이 있는 경우 생성하는 클래스&lt;/li&gt;
&lt;li&gt;두 클래스의 연관 관계를 나타내는 선의 가운데로부터 점선을 연관 클래스로 이어 표시&lt;/li&gt;
&lt;li&gt;연관 클래스의 이름은 연관 관계의 이름을 이용해 지정&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;29. 순차 다이어그램&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&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;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;구성 요소&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;내용&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;액터&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;시스템으로부터 서비스를 요청하는 외부 요소로, 사람이나 외부 시스템을 의미&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;객체&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;메시지를 주고받는 주체&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;생명선&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;객체가 메모리에 존재하는 기간으로 객체 아래쪽에 점선을 그어 표현, 객체 소멸(X)이 표현된 기간까지 존재&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;실행 상자(활성 상자)&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;객체가 메시지를 주고받으며 구동되고 있음을 표현&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;메시지&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;객체가 상호 작용을 위해 주고받는 메시지&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;객체 소멸&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;해당 객체가 더 이상 메모리에 존재하지 않음을 표현한 것&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;프레임&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;다이어그램의 전체 또는 일부를 묶어 표현한 것&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;30. 커뮤니케이션 다이어그램 - C등급&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&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;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;구성 요소&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;내용&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;액터&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;시스템으로부터 서비스를 요청하는 외부 요소로, 사람이나 외부 시스템을 의미&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;객체&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;메시지를 주고받는 주체&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;링크&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;객체들 간의 관계를 표현한 것, 액터와 객체, 객체와 객체 간에 실선을 그어 표현&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;메시지&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;객체가 상호작용을 위해 주고받는 내용, 화살표의 방향은 메시지를 받는 쪽으로 향하게 표현&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;31. 상태 다이어그램 - C등급&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;객체들 사이에서 발생하는 이벤트에 의한 객체들의 상태 변화를 그림으로 표현한 것&lt;/li&gt;
&lt;li&gt;&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;table style=&quot;background-color: #ffffff; color: #212529; text-align: start; border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;구성 요소&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;내용&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;상태&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;객체의 상태를 표현한 것&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;시작 상태&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;상태의 시작을 표현한 것&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;종료 상태&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;상태의 종료를 표현한 것&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;상태 전환&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;상태 사이의 흐름, 변화를 화살표로 표현한 것&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;이벤트&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;상태에 변화를 주는 현상,&lt;span&gt;&amp;nbsp;&lt;/span&gt;조건,&lt;span&gt;&amp;nbsp;&lt;/span&gt;외부 신호,&lt;span&gt;&amp;nbsp;&lt;/span&gt;시간의 흐름&lt;span&gt;&amp;nbsp;&lt;/span&gt;등이 있음&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;프레임&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;span style=&quot;background-color: #f8f9fa; color: #212529; text-align: start;&quot;&gt;상태 다이어그램의 범위를 표현한 것&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;32. 패키지 다이어그램&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&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;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 9.78261%;&quot;&gt;&lt;b&gt;구성 요소&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 90.0966%;&quot;&gt;내용&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td style=&quot;width: 9.78261%;&quot;&gt;&lt;b&gt;패키지&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 90.0966%;&quot;&gt;객체들을 그룹화한 것, 패키지 이름만 표현하는 단순 표기법과 요소까지 표현하는 확장 표기법이 있다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td style=&quot;width: 9.78261%;&quot;&gt;&lt;b&gt;객체&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 90.0966%;&quot;&gt;유스케이스, 클래스, 인터페이스, 테이블 등 패키지에 포함될 수 있는 다양한 요소들&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td style=&quot;width: 9.78261%;&quot;&gt;&lt;b&gt;의존 관계&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 90.0966%;&quot;&gt;패키지와 패키지, 패키지와 객체 간을 점선 화살표로 연결하여 표현, 의존 관계의 표현 형태는 사용자가 임의로 작성할 수 있으며 대표적으로&lt;span&gt;&amp;nbsp;&lt;/span&gt;import와&lt;span&gt;&amp;nbsp;&lt;/span&gt;access를 사용&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;33. 컴포넌트 기반 방법론&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;기존의 시스템이나 소프트웨어를 구성하는 컴포넌트를 조합하여 하나의 새로운 애플리케이션을 만드는 방법론&lt;/li&gt;
&lt;li&gt;컴포넌트의 재사용이 가능하여 시간과 노력을 절감할 수 있음&lt;/li&gt;
&lt;li&gt;개발 준비&lt;span&gt;&amp;nbsp;&lt;/span&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;분석&lt;span&gt;&amp;nbsp;&lt;/span&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;설계&lt;span&gt;&amp;nbsp;&lt;/span&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;구현&lt;span&gt;&amp;nbsp;&lt;/span&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;테스트&lt;span&gt;&amp;nbsp;&lt;/span&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;전개&lt;span&gt;&amp;nbsp;&lt;/span&gt;-&lt;span&gt;&amp;nbsp;&lt;/span&gt;인도&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;34. CASE(Computer Aided Software Engineering)&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;소프트웨어 개발 과정에서 사용되는 요구 분석, 설계, 구현, 검사 및 디버깅 과정 전체 또는 일부를 컴퓨터와 전용 소프트웨어 도구를 사용하여 자동화하는 것&lt;/li&gt;
&lt;li&gt;&lt;b&gt;주요 기능&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;소프트웨어 생명 주기 전 단계의 연결&lt;/li&gt;
&lt;li&gt;다양한 소프트웨어 개발 모형 지원&lt;/li&gt;
&lt;li&gt;그래픽 지원&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;35. LOC 기법&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;소프트웨어 각 기능의 원시 코드 라인 수의 비관치, 낙관치, 기대치를 측정하여 예측치를 구하고 이를 이용하여 비용을 산정하는 기법&lt;/li&gt;
&lt;li&gt;&lt;b&gt;산정 공식&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;노력(인월)&lt;span&gt;&amp;nbsp;&lt;/span&gt;=&lt;span&gt;&amp;nbsp;&lt;/span&gt;개발 기간&lt;span&gt;&amp;nbsp;&lt;/span&gt;X&lt;span&gt;&amp;nbsp;&lt;/span&gt;투입 인원&lt;span&gt;&amp;nbsp;&lt;/span&gt;=&lt;span&gt;&amp;nbsp;&lt;/span&gt;LOC&lt;span&gt;&amp;nbsp;&lt;/span&gt;/&lt;span&gt;&amp;nbsp;&lt;/span&gt;1인당 월평균 생산 코드 라인 수&lt;/li&gt;
&lt;li&gt;개발 비용&lt;span&gt;&amp;nbsp;&lt;/span&gt;=&lt;span&gt;&amp;nbsp;&lt;/span&gt;노력(인월)&lt;span&gt;&amp;nbsp;&lt;/span&gt;X&lt;span&gt;&amp;nbsp;&lt;/span&gt;단위 비용(1인당 월평균 인건비)&lt;/li&gt;
&lt;li&gt;개발 기간&lt;span&gt;&amp;nbsp;&lt;/span&gt;=&lt;span&gt;&amp;nbsp;&lt;/span&gt;노력(인월)&lt;span&gt;&amp;nbsp;&lt;/span&gt;X&lt;span&gt;&amp;nbsp;&lt;/span&gt;투입 인원&lt;/li&gt;
&lt;li&gt;생산성&lt;span&gt;&amp;nbsp;&lt;/span&gt;=&lt;span&gt;&amp;nbsp;&lt;/span&gt;LOC&lt;span&gt;&amp;nbsp;&lt;/span&gt;/&lt;span&gt;&amp;nbsp;&lt;/span&gt;노력(인월)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;36. 수학적 산정 기법&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;상향식 비용 산정 기법으로, 개발 비용 산정의 자동화를 목표로 함&lt;/li&gt;
&lt;li&gt;경험적,&lt;span&gt;&amp;nbsp;&lt;/span&gt;실험적 추정 모형&lt;span&gt;&amp;nbsp;&lt;/span&gt;이라고도 함&lt;/li&gt;
&lt;li&gt;COCOMO 모형,&lt;span&gt;&amp;nbsp;&lt;/span&gt;Putnam 모형,&lt;span&gt;&amp;nbsp;&lt;/span&gt;기능 점수(FP) 모형&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;37. COCOMO 모형&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;원시 프로그램의 규모인&lt;span&gt;&amp;nbsp;&lt;/span&gt;LOC에 의한 비용 산정 기법&lt;/li&gt;
&lt;li&gt;개발할 소프트웨어의 규모(LOC)를 예측한 후 이를 소프트웨어 종류에 따라 다르게 책정되는 비용 산정 방정식에 대입하여 비용을 산정함&lt;/li&gt;
&lt;li&gt;비용 산정 결과는 프로젝트를 완성하는 데 필요한 노력(Man-Month)으로 나타남&lt;/li&gt;
&lt;li&gt;보헴이 제안&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;38. COCOMO의 소프트웨어 개발 유형&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;조직형&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;기관 내부에서 개발된 중 내부에서 개발된 중&amp;middot;소 규모의 소프트웨어&lt;/li&gt;
&lt;li&gt;일괄 자료 처리나 과학기술 계산용, 비즈니스 자료 처리용 등의 5만 라인 이하의 소프트웨어를 개발하는 유형&lt;/li&gt;
&lt;li&gt;사무 처리용, 업무용, 과학용 응용 소프트웨어 개발에 적합&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;반분리형&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;조직형과 내장형의 중간형 소프트웨어&lt;/li&gt;
&lt;li&gt;트랜잭션 처리 시스템이나 운영체제, 데이터베이스 관리 시스템 등의 30만 라인 이하의 소프트웨어를 개발하는 유형&lt;/li&gt;
&lt;li&gt;컴파일러, 인터프리터와 같은 유틸리티 개발에 적합&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;내장형&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;초대형 규모의 소프트웨어&lt;/li&gt;
&lt;li&gt;트랜잭션 처리 시스템이나 운영체제 등의 30만 라인 이상의 소프트웨어를 개발하는 유형&lt;/li&gt;
&lt;li&gt;신호기 제어 시스템, 미사일 유도 시스템, 실시간 처리 시스템 등의 시스템 프로그램 개발에 적합&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;39. Putnam 모형(생명 주기 예측 모형)&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;소프트웨어 생명 주기의 전 과정 동안에 사용될 노력의 분포를 예상하는 모형&lt;/li&gt;
&lt;li&gt;시간에 따른 함수로 표현되는&lt;span&gt;&amp;nbsp;&lt;/span&gt;Rayleigh-Norden 곡선의 노력 분포도를 기초로 함&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;40. CPM (계산)&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로젝트 완성에 필요한 작업을 나열하고 작업에 필요한 소요 기간을 예측하는데 사용하는 기법&lt;/li&gt;
&lt;li&gt;노드와 간선으로 구성된 네트워크로 노드는 작업을, 간선은 작업 사이의 전후 의존 관계를 나타냄.&lt;/li&gt;
&lt;li&gt;최장 경로를 임계 경로라고 하며, 예시에서는 붉은 선으로 표시함.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;41. CMMI&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;소프트웨어 개발 조직의 업무 능력 및 조직의 성숙도를 평가하는 모델&lt;/li&gt;
&lt;li&gt;프로세스 성숙도를 단계별로 나눈다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;(초관정정최)&lt;/li&gt;
&lt;li&gt;단계특징&amp;nbsp;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;초기&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;작업자 능력에 따라 성공 여부 결정&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;관리&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;특정한 프로젝트 내의 프로세스 정의 및 수행&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;정의&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;조직의 표준 프로세스를 활용하여 업무 수행&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;정량적 관리&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;프로젝트를 정량적으로 관리 및 통제&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;background-color: #f8f9fa;&quot;&gt;
&lt;td&gt;&lt;b&gt;최적화&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;프로세스 역량 향상을 위해 지속적인 프로세스 개선&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;42. SPICE(ISO/IEC 15504)&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;정보 시스템 분야에서 소프트웨어의 품질 및 생산성 향상을 위해 소프트웨어 프로세스를 평가 및 개선하는 국제 표준&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;43. 소프트웨어 개발 프레임워크&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;소프트웨어 개발에 공통적으로 사용되는 구성 요소와 아키텍처를 일반화하여 손쉽게 구현할 수 있도록 여러가지 기능들을 제공해주는 반제품 형태의 소프트웨어 시스템&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;44. 소프트웨어 개발 프레임워크의 특성&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;모듈화: 프레임워크는 캡슐화를 통해 모듈화를 강화하고 설계 및 구현의 변경에 따른 영향을 최소화함으로써 소프트웨어의 품질을 향상시킨다.&lt;/li&gt;
&lt;li&gt;재사용성: 프레임워크는 재사용 가능한 모듈들을 제공함으로써 예산 절감, 생산성 향상, 품질 보증이 가능하다.&lt;/li&gt;
&lt;li&gt;확장성: 프레임워크는 다형성을 통한 인터페이스 확장이 가능하여 다양한 형태와 기능을 가진 애플리케이션 개발이 가능하다.&lt;/li&gt;
&lt;li&gt;제어의 역흐름: 개발자가 관리하고 통제해야하는 객체들의 제어를 프레임워크에 넘김으로써 생산성을 향상시킨다.&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>정보처리기사</category>
      <author>dobbyyo</author>
      <guid isPermaLink="true">https://dobbyyo.tistory.com/30</guid>
      <comments>https://dobbyyo.tistory.com/entry/%EC%A0%95%EB%B3%B4%EC%B2%98%EB%A6%AC%EA%B8%B0%EC%82%AC-%EC%8B%A4%EA%B8%B0-%EC%9A%94%EA%B5%AC%EC%82%AC%ED%95%AD-%ED%99%95%EC%9D%B8#entry30comment</comments>
      <pubDate>Sun, 19 Oct 2025 22:29:03 +0900</pubDate>
    </item>
    <item>
      <title>JavaScript 리팩토링이란?</title>
      <link>https://dobbyyo.tistory.com/entry/JavaScript-%EB%A6%AC%ED%8C%A9%ED%86%A0%EB%A7%81%EC%9D%B4%EB%9E%80</link>
      <description>&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;1. 코드 동작이 변하지 않는다는 것을 어떻게 보장할 수 있을까?&lt;br /&gt;&lt;br /&gt;코드 안정성은 소프트웨어 개발에서 매우 중요한 요소입니다. 코드가 예상치 못하게 변경되면, 기존 기능이 손상되거나 새로운 버그가 발생할 수 있습니다. 따라서 코드의 안정성을 보장하는 방법에 대해 알아보겠습니다.&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;코드 안정성의 중요성&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;코드 안정성은 소프트웨어의 신뢰성과 직결됩니다. 안정적인 코드는 사용자에게 일관된 경험을 제공하며, 개발자에게는 유지보수의 용이함을 보장합니다. 특히, 대규모 프로젝트에서는 코드의 변경이 전체 시스템에 미치는 영향을 최소화하는 것이 필수적입니다.&lt;/blockquote&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;버전 관리의 필요성&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;버전 관리는 코드의 변경 이력을 추적하고 관리하는 데 필수적입니다. 이를 통해 개발자는 이전 버전으로 쉽게 되돌아갈 수 있으며, 팀원 간의 협업도 원활하게 진행됩니다. 예를 들어, Git과 같은 도구를 사용하면 각 변경 사항을 기록하고, 필요할 때마다 특정 시점으로 롤백할 수 있습니다. 이는 코드의 안정성을 높이는 데 큰 도움이 됩니다.&lt;/blockquote&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;리팩토링과 코드 품질&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;리팩토링은 코드의 구조를 개선하여 가독성과 유지보수성을 높이는 과정입니다. Martin Fowler의 원칙에 따르면, 리팩토링을 통해 코드의 품질을 향상시키는 것이 가능합니다. 그러나 리팩토링 과정에서 코드의 기능이 변경되지 않도록 주의해야 합니다. 이를 위해서는 충분한 테스트가 필요하며, 리팩토링 후에는 반드시 기존 테스트를 통과해야 합니다.&lt;/blockquote&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;자동화된 테스트의 역할&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;자동화된 테스트는 코드 변경 사항이 기존 기능에 영향을 미치지 않도록 신속하게 검증할 수 있는 방법입니다. 테스트를 통해 코드의 품질을 유지하고, 새로운 기능이 추가될 때마다 기존 기능이 정상적으로 작동하는지 확인할 수 있습니다. 특히, 단위 테스트와 통합 테스트는 코드 안정성을 보장하는 데 중요한 역할을 합니다.&lt;/blockquote&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;코드 안정성을 위한 베스트 프랙티스&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;일관된 코딩 스타일 유지&lt;/b&gt;&amp;nbsp;: 팀 내에서 일관된 코딩 스타일을 유지하면 코드의 가독성이 높아지고, 유지보수가 용이해집니다.&lt;br /&gt;&lt;b&gt;자동화된 코드 분석 도구 활용&lt;/b&gt;: 코드 품질을 자동으로 분석하는 도구를 사용하여 코드의 문제점을 사전에 발견할 수 있습니다.&lt;br /&gt;&lt;b&gt;철저한 테스트 전략 수립&lt;/b&gt;: 다양한 테스트를 통해 코드의 안정성을 확보해야 합니다. 단위 테스트, 통합 테스트, 시스템 테스트 등을 포함해야 합니다.&lt;br /&gt;&lt;b&gt;정기적인 코드 리뷰&lt;/b&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: 'Noto Serif KR';&quot;&gt;2. 품질이란 무엇이며 리팩토링과 어떤 관련이 있을까?&lt;/span&gt;&lt;/blockquote&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;품질의 정의&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;품질은 일반적으로 제품이나 서비스가 고객의 요구를 얼마나 잘 충족하는지를 나타내는 개념입니다. 소프트웨어 품질은 코드의 기능적 요구사항을 충족하는 것뿐만 아니라, 유지보수성, 성능, 보안 등 다양한 측면에서 평가됩니다. 소프트웨어가 잘 작동하더라도, 코드가 복잡하고 이해하기 어려운 경우에는 품질이 낮다고 할 수 있습니다.&lt;/blockquote&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;소프트웨어 품질의 중요성&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;소프트웨어 품질은 개발 비용과 시간에 직접적인 영향을 미칩니다. 품질이 높은 소프트웨어는 유지보수가 용이하고, 버그가 적으며, 사용자 경험이 향상됩니다. 반면, 품질이 낮은 소프트웨어는 수정과 개선에 많은 시간과 비용이 소요됩니다. 따라서, 품질을 높이는 것은 소프트웨어 개발의 핵심 목표 중 하나입니다.&lt;/blockquote&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;리팩토링의 개념&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;리팩토링은 기존 코드를 개선하여 코드의 구조를 변경하는 과정을 의미합니다. 이 과정에서 기능은 변경되지 않지만, 코드의 가독성과 유지보수성이 향상됩니다. 리팩토링은 지속적인 소프트웨어 개발 과정에서 필수적인 활동으로, 코드의 품질을 높이는 데 기여합니다.&lt;/blockquote&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;리팩토링과 품질의 관계&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;리팩토링은 소프트웨어 품질을 높이는 데 중요한 역할을 합니다. 코드가 복잡해지면, 버그가 발생할 확률이 높아지고, 새로운 기능을 추가하는 것이 어려워집니다. 리팩토링을 통해 코드를 정리하고, 불필요한 부분을 제거함으로써 품질을 향상시킬 수 있습니다. 예를 들어, SOLID, DRY, KISS와 같은 원칙을 적용하여 코드를 개선할 수 있습니다. 이러한 원칙들은 코드의 가독성을 높이고, 유지보수를 용이하게 합니다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;리팩토링의 원칙&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;리팩토링을 할 때는 몇 가지 원칙을 따르는 것이 좋습니다. SOLID 원칙은 객체 지향 프로그래밍에서의 설계 원칙으로, 코드의 유연성과 재사용성을 높이는 데 도움을 줍니다. DRY 원칙은 &quot;Don't Repeat Yourself&quot;의 약자로, 중복 코드를 피하는 것을 강조합니다. KISS 원칙은 &quot;Keep It Simple, Stupid&quot;의 약자로, 복잡성을 줄이고 간단한 코드를 작성하는 것을 목표로 합니다. 이러한 원칙들은 리팩토링 과정에서 코드 품질을 높이는 데 큰 도움이 됩니다.&lt;/blockquote&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;테스트와 리팩토링&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;리팩토링을 진행할 때는 테스트가 필수적입니다. 테스트는 코드의 기능이 정상적으로 작동하는지를 확인하는 방법으로, 리팩토링 후에도 기존 기능이 유지되는지를 검증하는 데 중요합니다. 테스트 주도 개발(TDD) 방법론을 활용하면, 리팩토링 과정에서 발생할 수 있는 문제를 사전에 예방할 수 있습니다.&lt;/blockquote&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;3. 어떤 것이 리팩토링이고 어떤 것이 아닐까?&lt;/span&gt;&lt;/blockquote&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;리팩토링과 관련된 활동&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;리팩토링에는 여러 가지 활동이 포함됩니다. 예를 들어, 코드의 중복을 제거하거나, 함수의 이름을 더 명확하게 바꾸는 것 등이 있습니다. 또한, 코드의 구조를 개선하여 더 나은 디자인 패턴을 적용할 수도 있습니다. &lt;br /&gt;&lt;br /&gt;리팩토링의 예시로는 다음과 같은 것들이 있습니다. 기존의 복잡한 조건문을 간단한 함수로 분리하거나, 긴 메서드를 여러 개의 작은 메서드로 나누는 작업이 있습니다. 이러한 작업을 통해 코드의 가독성을 높이고, 유지보수성을 향상시킬 수 있습니다.&lt;/blockquote&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;리팩토링을 위한 도구&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;리팩토링을 도와주는 다양한 도구들이 있습니다. 예를 들어, IDE(통합 개발 환경)에서는 자동으로 리팩토링을 지원하는 기능이 많이 있습니다. 이러한 도구를 활용하면 수작업으로 진행하는 것보다 훨씬 효율적으로 리팩토링을 할 수 있습니다.&lt;/blockquote&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;리팩토링의 주의사항&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;리팩토링을 진행할 때는 몇 가지 주의사항이 있습니다. 첫째, 리팩토링을 너무 자주 하거나, 불필요한 리팩토링을 시도하면 오히려 코드의 품질이 떨어질 수 있습니다. 둘째, 팀원들과의 소통이 중요합니다. 리팩토링을 진행하기 전에 팀원들과 충분히 논의하고, 동의를 얻는 것이 좋습니다.&lt;/blockquote&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;리팩토링은 개발에서 필수적인 과정입니다. 이를 통해 코드의 품질을 높이고, 유지보수성을 향상시킬 수 있습니다. 여러분도 리팩토링을 통해 더 나은 코드를 작성해 보세요!!!&amp;nbsp;&lt;/span&gt;&lt;/blockquote&gt;</description>
      <category>Language/JavaScript</category>
      <author>dobbyyo</author>
      <guid isPermaLink="true">https://dobbyyo.tistory.com/29</guid>
      <comments>https://dobbyyo.tistory.com/entry/JavaScript-%EB%A6%AC%ED%8C%A9%ED%86%A0%EB%A7%81%EC%9D%B4%EB%9E%80#entry29comment</comments>
      <pubDate>Wed, 5 Mar 2025 16:37:20 +0900</pubDate>
    </item>
    <item>
      <title>React에서 URL 공유하기: Web Share API 활용</title>
      <link>https://dobbyyo.tistory.com/entry/React%EC%97%90%EC%84%9C-URL</link>
      <description>&lt;h3 data-pm-slice=&quot;1 3 []&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;React에서 URL 공유하기: Web Share API 활용&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;현대 웹 애플리케이션에서 URL 공유 기능은 사용자 경험을 향상시키는 중요한 요소입니다. React 애플리케이션에서 이 기능을 구현하는 방법 중 하나는 &lt;/span&gt;&lt;span&gt;&lt;b&gt;Web Share API&lt;/b&gt;&lt;/span&gt;&lt;span&gt;를 활용하는 것입니다. 이 글에서는 Web Share API를 이용해 URL을 공유하는 방법과 React 환경에서의 통합 사례를 살펴보겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;&lt;hr data-ke-style=&quot;style1&quot; /&gt;&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;Web Share API란?&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Web Share API는 사용자가 현재 페이지의 URL, 텍스트, 또는 이미지 등을 공유할 수 있도록 네이티브 공유 인터페이스를 제공합니다. 이를 통해 모바일과 데스크톱 환경 모두에서 쉽게 공유 기능을 구현할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;Web Share API의 주요 메서드&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;navigator.share()&lt;/b&gt;&lt;/span&gt;&lt;span&gt;: 공유 작업을 수행하는 메서드로, 브라우저의 기본 공유 대화 상자를 호출합니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;Web Share API 지원 여부 확인&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Web Share API는 모든 브라우저에서 지원되지 않습니다. 따라서 사용하기 전에 API 지원 여부를 확인해야 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1737110633014&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;if (navigator.share) {
  console.log('Web Share API를 지원합니다.');
} else {
  console.error('Web Share API를 지원하지 않습니다.');
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;React에서 URL 공유 기능 구현&lt;br /&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;h4 data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;1. Web Share API 유틸리티 함수 작성&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;URL 공유 기능을 별도의 유틸리티 함수로 작성하여 재사용성을 높일 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1737110948927&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const shareUsingWebAPI = async (shareUrl: string) =&amp;gt; {
  if (navigator.share) {
    try {
      await navigator.share({
        title: '공유할 제목',
        text: '이 페이지를 확인해보세요!',
        url: shareUrl,
      });
      console.log('공유 성공');
    } catch (error) {
      console.error('공유 실패 또는 취소:', error);
    }
  } else {
    alert('이 브라우저는 공유 기능을 지원하지 않습니다.');
  }
};

export default shareUsingWebAPI;&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;2. React 컴포넌트에 통합&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;공유 버튼을 포함한 React 컴포넌트를 작성하여 Web Share API를 호출합니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;import { Link } from 'react-router-dom';
import ResponsiveImage from './ResponsiveImage';

const NavBar = ({
  onShare,
}: {
  onShare?: () =&amp;gt; void;
}) =&amp;gt; {
 

  return (
    &amp;lt;div className=&quot;navbar w-full flex items-center relative h-[40px] sm:h-[100px]&quot;&amp;gt;
      &amp;lt;button onClick={onShare} className=&quot;w-[20px] h-[20px] sm:w-[30px] sm:h-[30px] flex items-center justify-center&quot;&amp;gt;
        &amp;lt;ResponsiveImage
          webpSrc=&quot;/tarot/webp/sharing.webp&quot;
          pngSrc=&quot;/tarot/png/sharing.png&quot;
          alt=&quot;Share&quot;
          className=&quot;w-full h-full object-cover&quot;
        /&amp;gt;
      &amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;
  );
};

export default NavBar;&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;3. React Query와의 연동&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;React Query를 활용하면 서버와의 상호작용을 통해 URL 공유를 처리할 수도 있습니다. 아래는 React Query를 사용하여 URL을 생성하고 공유하는 예제입니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;export const useTarotCardShareMutation = () =&amp;gt; {
  const setLoading = useSetRecoilState(loadingState);
  const setError = useSetRecoilState(errorState);
  const setShared = useSetRecoilState(tarotSharedState);

  return useMutation&amp;lt;
    ApiTarotCardSharedResponse,
    Error,
    {
      payload: TarotSharePayload;
    }
  &amp;gt;({
    mutationKey: ['tarotCardShare'],
    mutationFn: async ({ payload }: { payload: TarotSharePayload }) =&amp;gt; {
      setLoading(true);
      const response = await tarotCardShare(payload);

      return response;
    },
    onSuccess: async (response) =&amp;gt; {
      const { currentUrl } = config;

      const { shareCards } = response.data;
      const newShareId = shareCards.id;

      setShared(newShareId);

      const shareUrl = `${currentUrl}/tarot/result/share/${newShareId}`;

      try {
        await shareUsingWebAPI(shareUrl);
      } catch (error) {
        console.error(error);
      } finally {
        setLoading(false);
      }
    },
    onSettled: () =&amp;gt; {
      setLoading(false);
    },
    onError: (error) =&amp;gt; {
      console.error('공유 링크 생성 실패:', error);
      alert('공유 링크 생성에 실패했습니다.');
      setLoading(false);
      setError(true);
    },
  });
};&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;4. React Query를 활용한 컴포넌트&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1737111246478&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const TarotResult = () =&amp;gt; {
  const {
    title: metaTitle,
    description: metaDescription,
    keywords,
    canonical,
    ogTitle,
    ogDescription,
  } = tarotMetaData.tarotResult;

  ...
  const { mutate: shareTarotCards } = useTarotCardShareMutation();

  const createPayload = () =&amp;gt; ({
    mainTitle: '오늘의 타로',
    cards: tarotCards.map((card) =&amp;gt; ({
      cardId: card.id,
      subTitle: card.subTitle,
      isReversed: card.isReversed,
      cardInterpretation: card.interpretation.interpretation,
    })),
  });

  const onShare = () =&amp;gt; {
    shareTarotCards({ payload: createPayload() });
  };

  return (
    &amp;lt;&amp;gt;
      &amp;lt;MetaTag
        title={metaTitle}
        description={metaDescription}
        keywords={keywords}
        canonical={canonical}
        ogTitle={ogTitle}
        ogDescription={ogDescription}
      /&amp;gt;
      &amp;lt;div className=&quot;flex flex-col items-center justify-center h-auto&quot;&amp;gt;
        {onShare &amp;amp;&amp;amp; &amp;lt;NavBar
          onShare={onShare}
        /&amp;gt;}

        &amp;lt;div className=&quot;baseStyle&quot;&amp;gt;
          {tarotCards.map((card) =&amp;gt; (
            &amp;lt;TarotResultLists key={card.id} card={card} /&amp;gt;
          ))}
        &amp;lt;/div&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/&amp;gt;
  );
};

export default TarotResult;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;5. 실제 적용한 화면 페이지&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;548&quot; data-origin-height=&quot;720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/YS70Q/btsLQZVUUTy/3pFw0oIiObutWF0asV19VK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/YS70Q/btsLQZVUUTy/3pFw0oIiObutWF0asV19VK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/YS70Q/btsLQZVUUTy/3pFw0oIiObutWF0asV19VK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FYS70Q%2FbtsLQZVUUTy%2F3pFw0oIiObutWF0asV19VK%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;548&quot; height=&quot;720&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;548&quot; data-origin-height=&quot;720&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;카카오나, 트위터 등 다른 곳에 공유하려면 해당 하는 플랫폼에 API를 적용해야합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 장에 카카오 API를 통해 적용하는 방법을 소개해드리겠습니다.&lt;/p&gt;</description>
      <category>Front-End/React</category>
      <author>dobbyyo</author>
      <guid isPermaLink="true">https://dobbyyo.tistory.com/28</guid>
      <comments>https://dobbyyo.tistory.com/entry/React%EC%97%90%EC%84%9C-URL#entry28comment</comments>
      <pubDate>Fri, 17 Jan 2025 20:00:18 +0900</pubDate>
    </item>
    <item>
      <title>20019 카카오 개발자 겨울 인턴심 - 크레인 인형뽑기 게임</title>
      <link>https://dobbyyo.tistory.com/entry/20019-%EC%B9%B4%EC%B9%B4%EC%98%A4-%EA%B0%9C%EB%B0%9C%EC%9E%90-%EA%B2%A8%EC%9A%B8-%EC%9D%B8%ED%84%B4%EC%8B%AC-%ED%81%AC%EB%A0%88%EC%9D%B8-%EC%9D%B8%ED%98%95%EB%BD%91%EA%B8%B0-%EA%B2%8C%EC%9E%84</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;URL: &lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/64061&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://school.programmers.co.kr/learn/courses/30/lessons/64061&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1737102020997&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;SW개발자를 위한 평가, 교육, 채용까지 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프&quot; data-og-host=&quot;programmers.co.kr&quot; data-og-source-url=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/64061&quot; data-og-url=&quot;https://programmers.co.kr/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/eEVf1n/hyX4wlbxgh/JDmJfcegKoUOJCumvRS7x1/img.png?width=1920&amp;amp;height=960&amp;amp;face=0_0_1920_960,https://scrap.kakaocdn.net/dn/bMB6Ki/hyX0yrpKmc/wFqvIYDVEZOUqmJFv3Qqa1/img.png?width=1920&amp;amp;height=960&amp;amp;face=0_0_1920_960&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/64061&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/64061&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/eEVf1n/hyX4wlbxgh/JDmJfcegKoUOJCumvRS7x1/img.png?width=1920&amp;amp;height=960&amp;amp;face=0_0_1920_960,https://scrap.kakaocdn.net/dn/bMB6Ki/hyX0yrpKmc/wFqvIYDVEZOUqmJFv3Qqa1/img.png?width=1920&amp;amp;height=960&amp;amp;face=0_0_1920_960');&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;SW개발자를 위한 평가, 교육, 채용까지 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;733&quot; data-origin-height=&quot;610&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/djziu8/btsLSTsQk00/iJLh3tUK6p33sO8AJhVo5k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/djziu8/btsLSTsQk00/iJLh3tUK6p33sO8AJhVo5k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/djziu8/btsLSTsQk00/iJLh3tUK6p33sO8AJhVo5k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdjziu8%2FbtsLSTsQk00%2FiJLh3tUK6p33sO8AJhVo5k%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;733&quot; height=&quot;610&quot; data-origin-width=&quot;733&quot; data-origin-height=&quot;610&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;문제 요점 파악&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. 크레인의 동작 구현&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;moves에 따라 각 열에서 가장 위의 인형(값이 0이 아닌 첫 번째 값)을 선택.&lt;/li&gt;
&lt;li&gt;선택된 인형은 board에서 제거하고, drawList라는 스택에 추가.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. 인형 제거 조건&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;스택(drawList)의 마지막 인형과 새로 추가되는 인형이 동일한 경우:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;두 인형을 제거.&lt;/li&gt;
&lt;li&gt;제거된 인형의 수만큼 점수(answer)를 증가.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;다르면 스택에 인형을 추가.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. 반복 처리&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;moves에 있는 모든 동작을 처리.&lt;/li&gt;
&lt;li&gt;board가 업데이트되고, drawList와 answer가 계속 변경됨.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;풀제 풀이&lt;/p&gt;
&lt;pre id=&quot;code_1737103617520&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function solution(board, moves) {
  var answer = 0;
  let drawList = [];

  for (let move of moves) {
    // 현재 열에서 가장 위의 아이템을 찾기
    let column = Number(move) - 1;
    for (let row = 0; row &amp;lt; board.length; row++) {
      if (board[row][column] !== 0) {
        let pickedItem = board[row][column];
        board[row][column] = 0; // 아이템을 뽑으면 해당 위치를 0으로 변경

        // 스택(drawList) 처리
        if (
          drawList.length &amp;gt; 0 &amp;amp;&amp;amp;
          drawList[drawList.length - 1] === pickedItem
        ) {
          drawList.pop(); // 같은 아이템일 경우 제거
          answer += 2; // 제거된 아이템 2개 카운트
        } else {
          drawList.push(pickedItem); // 다른 아이템일 경우 추가
        }
        break; // 해당 열에서 아이템을 뽑았으니 다음 move로 이동
      }
    }
  }

  return answer;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Algorithm</category>
      <author>dobbyyo</author>
      <guid isPermaLink="true">https://dobbyyo.tistory.com/27</guid>
      <comments>https://dobbyyo.tistory.com/entry/20019-%EC%B9%B4%EC%B9%B4%EC%98%A4-%EA%B0%9C%EB%B0%9C%EC%9E%90-%EA%B2%A8%EC%9A%B8-%EC%9D%B8%ED%84%B4%EC%8B%AC-%ED%81%AC%EB%A0%88%EC%9D%B8-%EC%9D%B8%ED%98%95%EB%BD%91%EA%B8%B0-%EA%B2%8C%EC%9E%84#entry27comment</comments>
      <pubDate>Fri, 17 Jan 2025 17:47:18 +0900</pubDate>
    </item>
    <item>
      <title>프로그래머스 - 2022 KAKAO BLIND RECRUITMENT (신고 결과 받기)</title>
      <link>https://dobbyyo.tistory.com/entry/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-2022-KAKAO-BLIND-RECRUITMENT-%EC%8B%A0%EA%B3%A0-%EA%B2%B0%EA%B3%BC-%EB%B0%9B%EA%B8%B0</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;URL: &lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/92334&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://school.programmers.co.kr/learn/courses/30/lessons/92334&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1737089461510&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;SW개발자를 위한 평가, 교육, 채용까지 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프&quot; data-og-host=&quot;programmers.co.kr&quot; data-og-source-url=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/92334&quot; data-og-url=&quot;https://programmers.co.kr/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bkgOUq/hyX4AgMy9y/HonM1rA78gi30Dnh0E4Q90/img.png?width=1920&amp;amp;height=960&amp;amp;face=0_0_1920_960,https://scrap.kakaocdn.net/dn/daa76Y/hyX4uOootA/1C8T1VhfxPXOGiVeJoA2q0/img.png?width=1920&amp;amp;height=960&amp;amp;face=0_0_1920_960&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/92334&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/92334&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bkgOUq/hyX4AgMy9y/HonM1rA78gi30Dnh0E4Q90/img.png?width=1920&amp;amp;height=960&amp;amp;face=0_0_1920_960,https://scrap.kakaocdn.net/dn/daa76Y/hyX4uOootA/1C8T1VhfxPXOGiVeJoA2q0/img.png?width=1920&amp;amp;height=960&amp;amp;face=0_0_1920_960');&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;SW개발자를 위한 평가, 교육, 채용까지 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프&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;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;710&quot; data-origin-height=&quot;351&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/E1m38/btsLQqFRcOU/VxaONBHVu8pcUzdoeJDuCk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/E1m38/btsLQqFRcOU/VxaONBHVu8pcUzdoeJDuCk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/E1m38/btsLQqFRcOU/VxaONBHVu8pcUzdoeJDuCk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FE1m38%2FbtsLQqFRcOU%2FVxaONBHVu8pcUzdoeJDuCk%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;710&quot; height=&quot;351&quot; data-origin-width=&quot;710&quot; data-origin-height=&quot;351&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;h3 data-ke-size=&quot;size23&quot;&gt;문제 요점 파악&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. 중복 신고 처리&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;동일한 유저가 같은 유저를 여러 번 신고한 경우, 이를 1회로 처리해야 합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. 신고 당한 횟수 계산&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;각 유저가 신고한 유저 중 &quot;정지된 유저&quot;가 몇 명인지 계산&amp;nbsp;&lt;/li&gt;
&lt;li&gt;누적된 횟수 중 k 이상인 유저를 정지된 유저로 판단&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. 메일 발송 조건&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;각 유저가 신고한 유저 중 &quot;정지된 유저&quot;가 몇 명인지 계산&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;풀이 코드&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1737089664851&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function solution(id_list, report, k) {
  const reportObj = new Map(); // 신고한 유저 Map
  const reportCount = new Map(); // 신고 당한 횟수 Map

  // 초기 세팅
  for (let id of id_list) {
    reportObj.set(id, []);
    reportCount.set(id, 0);
  }

  // 신고 처리
  for (let rep of report) {
    const [reporter, reported] = rep.split(&quot; &quot;);
    if (!reportObj.get(reporter).includes(reported)) {
      // 이미 해당 유저를 신고 안한 사용자만 조건문에 참유무 판단
      reportObj.get(reporter).push(reported); // 누구를 신고했는지 Map에 Push
      reportCount.set(reported, reportCount.get(reported) + 1); // 신고 당한사람 카운트 횟수
    }
  }

  // 결과 메일 계산
  const answer = [];
  for (let id of id_list) {
    let mailCount = 0;
    for (let reportedUser of reportObj.get(id)) {
      if (reportCount.get(reportedUser) &amp;gt;= k) {
        mailCount++;
      }
    }
    answer.push(mailCount);
  }

  return answer;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;깨닭은 점&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;기존에 Map을 사용해 신고 데이터를 관리하려 했지만, 중복을 제거하는 단순한 목적이라면 Set이 더 적합하다는 것을 깨달음.&lt;/li&gt;
&lt;li&gt;Set은 고유한 값을 자동으로 관리해주기 때문에 &lt;b&gt;중복 제거 로직을 따로 작성할 필요가 없음&lt;/b&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Algorithm</category>
      <author>dobbyyo</author>
      <guid isPermaLink="true">https://dobbyyo.tistory.com/26</guid>
      <comments>https://dobbyyo.tistory.com/entry/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-2022-KAKAO-BLIND-RECRUITMENT-%EC%8B%A0%EA%B3%A0-%EA%B2%B0%EA%B3%BC-%EB%B0%9B%EA%B8%B0#entry26comment</comments>
      <pubDate>Fri, 17 Jan 2025 14:01:00 +0900</pubDate>
    </item>
    <item>
      <title>프로그래머스 - 숫자 짝궁</title>
      <link>https://dobbyyo.tistory.com/entry/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EC%88%AB%EC%9E%90-%EC%A7%9D%EA%B6%81</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;문제&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;URL:&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/131128&quot;&gt;https://school.programmers.co.kr/learn/courses/30/lessons/131128&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-11-28 오후 12.45.24.png&quot; data-origin-width=&quot;663&quot; data-origin-height=&quot;811&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/buDj7N/btsKYXxBtWw/zf3SW3WWgLD4rk6ozxBdT0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/buDj7N/btsKYXxBtWw/zf3SW3WWgLD4rk6ozxBdT0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/buDj7N/btsKYXxBtWw/zf3SW3WWgLD4rk6ozxBdT0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbuDj7N%2FbtsKYXxBtWw%2Fzf3SW3WWgLD4rk6ozxBdT0%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;663&quot; height=&quot;811&quot; data-filename=&quot;스크린샷 2024-11-28 오후 12.45.24.png&quot; data-origin-width=&quot;663&quot; data-origin-height=&quot;811&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;h2 data-ke-size=&quot;size26&quot;&gt;핵심 파악&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;1. X, Y의 공통된 숫자 찾기&amp;nbsp;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;숫자가 중복될 수 있으므로, 한 번 찾은 숫자는 다시 사용할 수 없도록 개발 필요.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;2. 공통 숫자를 내림차순으로 결과 생성
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;숫자가 없으면 -1 반환&lt;/li&gt;
&lt;li&gt;공통 숫자가 모두 0이면 0으로 반환&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;3. 긴 테이터가 나올 경우 효율적은 시간 복잡도 생각하여 개발
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Map, Object를 사용하여 개발&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;CODE&lt;/h2&gt;
&lt;pre id=&quot;code_1732765577939&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function solution(X, Y) {
  let answer = &quot;&quot;;

  const countY = new Map();
  for (let char of Y) {
    countY[char] = (countY[char] || 0) + 1;
  }

  const common = [];
  for (const char of X) {
    if (countY[char]) {
      common.push(char);
      countY[char]--;
    }
  }

  if (common.length === 0) {
    answer = &quot;-1&quot;;
  } else {
    common.sort((a, b) =&amp;gt; b - a);
    answer = common.join(&quot;&quot;);
    if (Number(answer) === 0) answer = &quot;0&quot;;
  }

  return answer;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Algorithm</category>
      <author>dobbyyo</author>
      <guid isPermaLink="true">https://dobbyyo.tistory.com/25</guid>
      <comments>https://dobbyyo.tistory.com/entry/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EC%88%AB%EC%9E%90-%EC%A7%9D%EA%B6%81#entry25comment</comments>
      <pubDate>Thu, 28 Nov 2024 12:51:39 +0900</pubDate>
    </item>
    <item>
      <title>Nest.js: ERROR  Exception: Error: secretOrPrivateKey must have a value</title>
      <link>https://dobbyyo.tistory.com/entry/Nestjs-ERROR-Exception-Error-secretOrPrivateKey-must-have-a-value</link>
      <description>&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;백앤드에서 JWT관련 설정을 하던 도중 &lt;span style=&quot;color: #ee2323;&quot;&gt;&amp;nbsp;ERROR&amp;nbsp;&amp;nbsp;Exception: Error: secretOrPrivateKey must have a value&lt;/span&gt; 해당 Error가 나왔습니다.&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;b&gt;확인 과정&amp;nbsp;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫 번째로 확인해야 할 것이&amp;nbsp; JWT의 &lt;b&gt;jwtSecret가 .env파일에서 제대로 전달이 되는 확인&lt;/b&gt;이 필요합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Jwt secret 전달 확인 코드&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;auth.module.ts&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1730694617120&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Module({
  imports: [
    UsersModule,
    PassportModule.register({ defaultStrategy: 'jwt' }),
    JwtModule.registerAsync({
      imports: [ConfigModule],
      inject: [ConfigService],
      useFactory: async (configService: ConfigService) =&amp;gt; {
        const jwtSecret = configService.get&amp;lt;string&amp;gt;('app.JWT_SECRET');
        console.log('JWT_SECRET:', jwtSecret); // 출력 확인
        return {
          secret: jwtSecret,
          signOptions: { expiresIn: '2h' },
        };
      },
    }),
    forwardRef(() =&amp;gt; UsersModule),
    ConfigModule,
  ],
  controllers: [AuthController],
  providers: [AuthService, JwtService, RedisService, JwtStrategy],
  exports: [AuthService, JwtModule, PassportModule], 
})
export class AuthModule {}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;br /&gt;&lt;b&gt;jwt-strategt.ts&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1730694698273&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
  constructor(
    private readonly authService: AuthService,
    @Inject(appConfig.KEY) private config: ConfigType&amp;lt;typeof appConfig&amp;gt;,
  ) {
    console.log('jwt-strateg 값:', config.JWT_SECRET); // 값 확인

    super({
      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
      secretOrKey: config.JWT_SECRET,
    });
  }

  async validate(payload: JwtPayloadType) {
    return { userId: payload.sub, email: payload.email };
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;br /&gt;&lt;b&gt;app.module.ts&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1730694733925&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Module({
  imports: [
    ConfigModule.forRoot({
      cache: true, 
      isGlobal: true, 
      envFilePath: `.env.${process.env.NODE_ENV}`, 
      load: [appConfig, dbConfig, awsConfig, redisConfig],
    }),&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;b&gt;그래도 에러가 나온다면?ㅠ.ㅠ&lt;/b&gt;&lt;br /&gt;만약에 위처럼 설정이 되어있고 값이 잘나오는 것을 확인 후에도 똑같은 에러가 발생 시 다른 문제일 경우가 있습니다.&amp;nbsp;&lt;br /&gt;찾아본 결과 해결 방법으로 &lt;b&gt;auth.module.ts에서 JwtService를 Providers에 추가하면 안됩니다&lt;/b&gt;.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드는 아래와 같습니다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1730694926646&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Module({
  imports: [
    UsersModule,
    PassportModule.register({ defaultStrategy: 'jwt' }),
    JwtModule.registerAsync({
      imports: [ConfigModule],
      inject: [ConfigService],
      useFactory: async (configService: ConfigService) =&amp;gt; {
        const jwtSecret = configService.get&amp;lt;string&amp;gt;('app.JWT_SECRET');
        console.log('JWT_SECRET:', jwtSecret); // 값이 올바르게 출력되는지 확인
        return {
          secret: jwtSecret,
          signOptions: { expiresIn: '2h' },
        };
      },
    }),
    forwardRef(() =&amp;gt; UsersModule),
    ConfigModule,
  ],
  controllers: [AuthController],
  providers: [AuthService, RedisService, JwtStrategy],
  exports: [AuthService, JwtModule, PassportModule], // 해당 부분에 JwtService 추가 X
})
export class AuthModule {}&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;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;원인&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;JwtModule을 imports에 추가하면 NestJS는 JwtService를 자동으로 주입하도록 설정됩니다. &lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그러나 providers 배열에 JwtService를 다시 추가하면 NestJS가 JwtService를 두 번 정의하려고 시도하면서 충돌이 발생할 수 있습니다. 이는 JwtService가 두 번 이상 초기화되는 문제를 일으키고, secretOrPrivateKey must have a value 오류가 발생하게 됩니다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;해결&amp;nbsp;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-11-04 오후 1.42.05.png&quot; data-origin-width=&quot;1358&quot; data-origin-height=&quot;182&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bmaxAY/btsKwtbgtTu/NRgxSPdcYLO2QlfDXHiin1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bmaxAY/btsKwtbgtTu/NRgxSPdcYLO2QlfDXHiin1/img.png&quot; data-alt=&quot;JWT 토큰&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bmaxAY/btsKwtbgtTu/NRgxSPdcYLO2QlfDXHiin1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbmaxAY%2FbtsKwtbgtTu%2FNRgxSPdcYLO2QlfDXHiin1%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;1358&quot; height=&quot;182&quot; data-filename=&quot;스크린샷 2024-11-04 오후 1.42.05.png&quot; data-origin-width=&quot;1358&quot; data-origin-height=&quot;182&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;JWT 토큰&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위처럼 스웨거에서 토큰을 잘 발급 받는 것을 확인 할 수 있습니다.&lt;/p&gt;</description>
      <category>Back-End/Error</category>
      <author>dobbyyo</author>
      <guid isPermaLink="true">https://dobbyyo.tistory.com/24</guid>
      <comments>https://dobbyyo.tistory.com/entry/Nestjs-ERROR-Exception-Error-secretOrPrivateKey-must-have-a-value#entry24comment</comments>
      <pubDate>Mon, 4 Nov 2024 17:51:57 +0900</pubDate>
    </item>
    <item>
      <title>2019 KAKAO BLIND RECRUITMENT 실패율</title>
      <link>https://dobbyyo.tistory.com/entry/2019-KAKAO-BLIND-RECRUITMENT-%EC%8B%A4%ED%8C%A8%EC%9C%A8</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 문제&amp;nbsp;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;URL: &lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/42889&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://school.programmers.co.kr/learn/courses/30/lessons/42889&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1728960551295&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;코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.&quot; data-og-host=&quot;programmers.co.kr&quot; data-og-source-url=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/42889&quot; data-og-url=&quot;https://programmers.co.kr/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bHUoQO/hyXhQFtE2O/6hfjctMNIEy8QoWekeNcX0/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/MDFPd/hyXhWMsRBn/pDBRIDrA3QrclocsG4lHNk/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/42889&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/42889&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bHUoQO/hyXhQFtE2O/6hfjctMNIEy8QoWekeNcX0/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/MDFPd/hyXhWMsRBn/pDBRIDrA3QrclocsG4lHNk/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;프로그래머스&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.&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;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-10-15 오전 11.49.29.png&quot; data-origin-width=&quot;1034&quot; data-origin-height=&quot;729&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Q9CYt/btsJ6i2MZKN/PMIucWNjfssy51A5JVk8Gk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Q9CYt/btsJ6i2MZKN/PMIucWNjfssy51A5JVk8Gk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Q9CYt/btsJ6i2MZKN/PMIucWNjfssy51A5JVk8Gk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQ9CYt%2FbtsJ6i2MZKN%2FPMIucWNjfssy51A5JVk8Gk%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;1034&quot; height=&quot;729&quot; data-filename=&quot;스크린샷 2024-10-15 오전 11.49.29.png&quot; data-origin-width=&quot;1034&quot; data-origin-height=&quot;729&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;br /&gt;2. 문제 핵식 파악&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;실패율의 정의&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;실패율&lt;/b&gt;은 해당 스테이지에 도달했지만 아직 클리어하지 못한 사람의 수를, 그 스테이지에 도달한 전체 사람의 수로 나누는 비율입니다.&lt;/li&gt;
&lt;li&gt;실패율을 정확하게 계산하기 위해서는:
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;각 스테이지마다 도달한 유저 수를 계산해야 합니다.&lt;/li&gt;
&lt;li&gt;스테이지를 클리어하지 못한 유저 수를 파악해야 합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. &lt;b&gt;도달한 유저와 머물러 있는 유저의 구분&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;도달한 유저&lt;/b&gt;: 해당 스테이지에 도전 중이거나 더 높은 스테이지로 넘어간 유저.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;머물러 있는 유저&lt;/b&gt;: 현재 해당 스테이지를 아직 클리어하지 못한 유저.&lt;/li&gt;
&lt;li&gt;이를 구분해서 stages 배열을 분석해야 정확한 실패율을 구할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. &lt;b&gt;정렬 기준&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;실패율을 기준으로 &lt;b&gt;내림차순 정렬&lt;/b&gt;해야 합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;실패율이 같은 경우에는 스테이지 번호가 작은 것부터&lt;/b&gt; 오도록 정렬해야 합니다. 즉, 실패율이 같다면 스테이지 번호를 오름차순으로 정렬해야 합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. 코드&amp;nbsp;&lt;/h2&gt;
&lt;pre id=&quot;code_1728961135967&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function solution(N, stages) {
  let people_length = stages.length;
  let failRate = new Map();

  for (let i = 1; i &amp;lt;= N; i++) {
    const people = stages.filter((n) =&amp;gt; i === n).length; // 현재 스테이지에 있는 사람 수 필터

    let rate = people / people_length; // 실패율 계산

    failRate.set(i, rate); // Map에 저장
    people_length -= people; // 남은 수 계산
  }

  let sortRate = [...failRate].sort((a, b) =&amp;gt; {
    if (b[1] === a[1]) {
      return a[0] - b[0]; // 실패율이 같을 경우 스테이지 번호 오름차순
    }
    return b[1] - a[1]; // 실패율 내림차순
  });

  return sortRate.map((v) =&amp;gt; v[0]);
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Algorithm</category>
      <author>dobbyyo</author>
      <guid isPermaLink="true">https://dobbyyo.tistory.com/23</guid>
      <comments>https://dobbyyo.tistory.com/entry/2019-KAKAO-BLIND-RECRUITMENT-%EC%8B%A4%ED%8C%A8%EC%9C%A8#entry23comment</comments>
      <pubDate>Tue, 15 Oct 2024 11:59:10 +0900</pubDate>
    </item>
    <item>
      <title>프론트엔드 성능 최적화 4편 - 이미지 지연, 레이아웃 이동 피하기, 병목 코드 최적화</title>
      <link>https://dobbyyo.tistory.com/entry/%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C-%EC%84%B1%EB%8A%A5-%EC%B5%9C%EC%A0%81%ED%99%94-4%ED%8E%B8-%EC%9D%B4%EB%AF%B8%EC%A7%80-%EC%A7%80%EC%97%B0-%EB%A0%88%EC%9D%B4%EC%95%84%EC%9B%83-%EC%9D%B4%EB%8F%99-%ED%94%BC%ED%95%98%EA%B8%B0-%EB%B3%91%EB%AA%A9-%EC%BD%94%EB%93%9C-%EC%B5%9C%EC%A0%81%ED%99%94</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 이미지 지연 로딩&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전 장에서 했던 이미지 지연 로딩 기법(Intersection Observer API)가 아닌 라이브러리를 통해 사용해보겠습니다.&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;URL: &lt;a href=&quot;https://www.npmjs.com/package/react-lazyload&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.npmjs.com/package/react-lazyload&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1728885897459&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;react-lazyload&quot; data-og-description=&quot;Lazyload your components, images or anything where performance matters.. Latest version: 3.2.1, last published: 7 months ago. Start using react-lazyload in your project by running &amp;#96;npm i react-lazyload&amp;#96;. There are 452 other projects in the npm registry usi&quot; data-og-host=&quot;www.npmjs.com&quot; data-og-source-url=&quot;https://www.npmjs.com/package/react-lazyload&quot; data-og-url=&quot;https://www.npmjs.com/package/react-lazyload&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/c012ee/hyXhZoBtSG/9I0w9iNpC86Ic7gnDrMi20/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/react-lazyload&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.npmjs.com/package/react-lazyload&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/c012ee/hyXhZoBtSG/9I0w9iNpC86Ic7gnDrMi20/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;react-lazyload&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Lazyload your components, images or anything where performance matters.. Latest version: 3.2.1, last published: 7 months ago. Start using react-lazyload in your project by running `npm i react-lazyload`. There are 452 other projects in the npm registry usi&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;pre id=&quot;code_1728885871649&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;npm install --save react-lazyload&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1728886033126&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import LazyLoad from 'react-lazyload';

function PhotoItem({ photo: { urls, alt } }) {
  const dispatch = useDispatch();

  const openModal = () =&amp;gt; {
    dispatch(showModal({ src: urls.full, alt }));
  };

  return (
    &amp;lt;ImageWrap&amp;gt;
      &amp;lt;LazyLoad offset={1000}&amp;gt;
        &amp;lt;Image src={urls.small + '&amp;amp;t=' + new Date().getTime()} alt={alt} onClick={openModal} /&amp;gt;
      &amp;lt;/LazyLoad&amp;gt;
    &amp;lt;/ImageWrap&amp;gt;
  );
}

const ImageWrap = styled.div`
  width: 160px;
  aspect-ratio: 16 / 9;
`;

const Image = styled.img`
  width: 100%;
  height: 100%;
`;

export default PhotoItem;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;offset옵션&lt;/b&gt;을 설정해야합니다. 안그러면 스크롤을 내려 화면에 이미지가 들어올 때 이미지를 로드하기 떄문에 처음에는 이미지가 보이자 않고 시간이 지나야 이미지가 보인다는 현상이 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;offset&lt;/b&gt;: 얼마나 미리 이미지를 로드할지 픽셀 값으로 넣어 줍니다. ex) offset을 100으로 설정하면 화면에 들어오기 100px 전에 이미지를 로드합니다.&lt;/blockquote&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. 레이아웃 이동 피하기&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;레이아웃 이동이란?&amp;nbsp;&lt;/b&gt;&lt;br /&gt;화면상의 요소 변화로 레이아웃이 갑자기 밀리는 현상을 말합니다.&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-10-12 오후 4.38.40.png&quot; data-origin-width=&quot;348&quot; data-origin-height=&quot;89&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/2eEl7/btsJ3KyEAzw/FTibOknKlrmPBdkjvOrcL1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/2eEl7/btsJ3KyEAzw/FTibOknKlrmPBdkjvOrcL1/img.png&quot; data-alt=&quot;Lighthouse를 이용한 분석&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/2eEl7/btsJ3KyEAzw/FTibOknKlrmPBdkjvOrcL1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F2eEl7%2FbtsJ3KyEAzw%2FFTibOknKlrmPBdkjvOrcL1%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;348&quot; height=&quot;89&quot; data-filename=&quot;스크린샷 2024-10-12 오후 4.38.40.png&quot; data-origin-width=&quot;348&quot; data-origin-height=&quot;89&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Lighthouse를 이용한 분석&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 사진처럼 Cumulative Layout Shift를 확인하면 현재 내가 만든 웹의 레이아웃 이동이 얼마나 최적화 비율을 알수가있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-10-12 오후 4.45.18.png&quot; data-origin-width=&quot;1432&quot; data-origin-height=&quot;240&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bPTWOB/btsJ4rFb2Nb/DD4H5OaD7wGsKJN0tapbkK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bPTWOB/btsJ4rFb2Nb/DD4H5OaD7wGsKJN0tapbkK/img.png&quot; data-alt=&quot;Performance패널을 통한 레이아웃 이동 분석&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bPTWOB/btsJ4rFb2Nb/DD4H5OaD7wGsKJN0tapbkK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbPTWOB%2FbtsJ4rFb2Nb%2FDD4H5OaD7wGsKJN0tapbkK%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;1432&quot; height=&quot;240&quot; data-filename=&quot;스크린샷 2024-10-12 오후 4.45.18.png&quot; data-origin-width=&quot;1432&quot; data-origin-height=&quot;240&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Performance패널을 통한 레이아웃 이동 분석&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Layout Shifs를 자세히 보면 막대가 표시되는데, 이것은 해당 시간에 레이아웃 이동이 발생하였다는 의미입니다.&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;레이아웃 원인&amp;nbsp;&lt;/b&gt;&lt;br /&gt;흔히 발생하는 원인은 &lt;b&gt;4 가지&lt;/b&gt; 정도가 있습니다.&lt;br /&gt;- 사이즈가 미리 정의되지 않은 이미지 요소&lt;br /&gt;- 사이즈가 미리 정의되지 않은 광고 요소&lt;br /&gt;- 동적으로 삽입된 콘텐츠&lt;br /&gt;- 웹 폰트(FOIT, FOUT)&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보통 이런 것중 발생하는 큰 원인은 사이즈를 미리 정의를 하지 않고 이미지가 로드되면 높이가 해당 이미지의 높이로 변경되면서 그만큼 다른 요소들을 밀어내는 것입니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 간단하게 해결을 할 수 있습니다. 즉&lt;b&gt;, 해당 요소의 사이즈를 미리 예측할 수 있다면 또는 이미 알고있다면 해당 사이즈만큼 공간을 확보해 놓는 것입니다&lt;/b&gt;. 또한, 단순히 너비와 높이를 고정하는 것이 아니라 이미지의 너비, 높이 비율로 공간을 잡아 두면 됩니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이미지 크기를 비율로 설정하는 방법은 크게 두 가지가 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Padding을 이용하여 박스를 만든 뒤, 그 안에 이미지를 absolute로 띄우는 방식&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-10-14 오전 10.41.23.png&quot; data-origin-width=&quot;387&quot; data-origin-height=&quot;240&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/KMncU/btsJ3NCxaB6/mMdpBr95ESnltAkc8pCpKK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/KMncU/btsJ3NCxaB6/mMdpBr95ESnltAkc8pCpKK/img.png&quot; data-alt=&quot;Elements 패널에서 Intrinsic aspect ratio 비율 확인&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/KMncU/btsJ3NCxaB6/mMdpBr95ESnltAkc8pCpKK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FKMncU%2FbtsJ3NCxaB6%2FmMdpBr95ESnltAkc8pCpKK%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;387&quot; height=&quot;240&quot; data-filename=&quot;스크린샷 2024-10-14 오전 10.41.23.png&quot; data-origin-width=&quot;387&quot; data-origin-height=&quot;240&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Elements 패널에서 Intrinsic aspect ratio 비율 확인&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. Elements 패널에서 Intrinsic aspect ratio 비율을 확인해야합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 비율 확인후 비율과 맞게 padding을 주면 됩니다.&lt;/p&gt;
&lt;pre id=&quot;code_1728870338285&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function PhotoItem({ photo: { urls, alt } }) {
  const dispatch = useDispatch();

  const openModal = () =&amp;gt; {
    dispatch(showModal({ src: urls.full, alt }));
  };

  return (
    &amp;lt;ImageWrap&amp;gt;
      &amp;lt;Image src={urls.small + '&amp;amp;t=' + new Date().getTime()} alt={alt} onClick={openModal} /&amp;gt;
    &amp;lt;/ImageWrap&amp;gt;
  );
}

const ImageWrap = styled.div`
  position: relative;
  width: 160px;
  padding-top: 56.25%; /* 16:9 */
`;

const Image = styled.img`
  cursor: pointer;
  width: 100%;
  height: 100%;
  position: absolute;
  top: 0;
  left: 0;
`;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 하면 wrapper의 너비인 160px의 56.25%만큼 상단 여백이 설정됩니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 너비는 160px이 되고 높이는 90%이 됩니다. 이 상태에서 이미지를 absolute로 넣어 주면 부모 요소인 div와 사이즈가 동일하게 맞춰집니다. 만약 1:1 비율로 표시해야한다면 padding-top을 100%로 설정합니다.&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;- aspect-ratio라는 속성을 이용하는 방식&lt;/h4&gt;
&lt;pre id=&quot;code_1728885194205&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function PhotoItem({ photo: { urls, alt } }) {
  const dispatch = useDispatch();

  const openModal = () =&amp;gt; {
    dispatch(showModal({ src: urls.full, alt }));
  };

  return (
    &amp;lt;ImageWrap&amp;gt;
      &amp;lt;Image src={urls.small + '&amp;amp;t=' + new Date().getTime()} alt={alt} onClick={openModal} /&amp;gt;
    &amp;lt;/ImageWrap&amp;gt;
  );
}

const ImageWrap = styled.div`
  width: 160px;
  aspect-ratio: 16 / 9;
`;

const Image = styled.img`
  width: 100%;
  height: 100%;
`;

export default PhotoItem;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;padding을 이용한 방법과 달리 코드가 간단합니다. aspect-ratio 속성에 비율만 명시해 주면 됩니다. 하지만 언제나 그렇듯 최신 기술에는 호환성 문제가 있습니다. 그래서 최신 기술을 적용할때는 MDN에서 호환을 찾아보고 적용하면 될 것 같습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. 병목 코드 최적화&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 병목 코드를 최적화하기 전 Performance를 통해 느린 시점을 파악해야합니다. 먼저 여기서는&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-10-14 오후 3.28.35.png&quot; data-origin-width=&quot;1382&quot; data-origin-height=&quot;1148&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dj8BbV/btsJ5zKdV9x/30LuTvkEAZWwQkvjri6GpK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dj8BbV/btsJ5zKdV9x/30LuTvkEAZWwQkvjri6GpK/img.png&quot; data-alt=&quot;Performance 패널을 통한 분석&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dj8BbV/btsJ5zKdV9x/30LuTvkEAZWwQkvjri6GpK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdj8BbV%2FbtsJ5zKdV9x%2F30LuTvkEAZWwQkvjri6GpK%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;1382&quot; height=&quot;1148&quot; data-filename=&quot;스크린샷 2024-10-14 오후 3.28.35.png&quot; data-origin-width=&quot;1382&quot; data-origin-height=&quot;1148&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Performance 패널을 통한 분석&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;분석을 해보면 getAverageColorOfImage라는 함수가 느리게 실행되는것을 분석할 수가 있습니다.&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;함수를 최적화하는 방법은 두가지로 나눌수 있습니다.&amp;nbsp;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1. 메모이제이션으로 코드 최적화&lt;/h4&gt;
&lt;pre id=&quot;code_1728887720967&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const cache = {};

export function getAverageColorOfImage(imgElement) {
  if (cache.hasOwnProperty(imgElement.src)) {
    // 설명: 이미지의 src가 cache에 존재하면 해당 이미지의 평균 색상을 반환
    return cache[imgElement.src];
  }

	 ...(추가 코드 생략)

  cache[imgElement.src] = averageColor; // 설명: 이미지의 src를 key로 하여 cache에 평균 색상을 저장

  return averageColor;
}&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;blockquote data-ke-style=&quot;style2&quot;&gt;성능이 빨라지는 것을 확인이 가능합니다. 하지만 여전히 단점은 존재합니다. 메모이제이션은 값을 저장하여 재활용하기 떄문에 두번째 실행부터는 성능이 대폭 향상 그러나 첫 번째 실행에서는 여전히 느리다는 것입니다. 오히려 메모리만 잡아먹는 골칫거리가 될 뿐입니다. 따라서 메모이제이션을 적용할 때는 &lt;b&gt;해당 로직이 동일한 조건에서 충분히 반복 실행되는지 먼처 체크하고 적용&lt;/b&gt;해야합니다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2. 함수 자체의 로직 개선&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 코드를 분석하면 생상을 정할떄 이미지 사이즈에 따라 작업량이 결정됩니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;즉, 이미지가 작으면 캔버스에 그리는 이미지의 사이즈도 작아져 더 빠르게 처리할 수 있으며, 필셀 수도 줄어들어 반목문의 실행 횟수도 줄어들것입니다.&lt;br /&gt;즉, 지금은 원본 이미지로 배경색을 계산하고 있지만 섬네일 이미지로 배경 색을 계산하게 한다면 작업량이 많이 단축될 것입니다.&amp;nbsp;&lt;/blockquote&gt;
&lt;pre id=&quot;code_1728888159693&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function PhotoItem({ photo: { urls, alt } }) {
  const dispatch = useDispatch();

  const openModal = e =&amp;gt; {
    dispatch(showModal({ src: urls.full, alt }));

    const averageColor = getAverageColorOfImage(e.target);
    dispatch(setBgColor(averageColor));
  };

  return (
    &amp;lt;ImageWrap&amp;gt;
      &amp;lt;LazyLoad offset={1000}&amp;gt;
        &amp;lt;Image
          src={urls.small + '&amp;amp;t=' + new Date().getTime()}
          alt={alt}
          onClick={openModal}
          crossOrigin=&quot;*&quot; // 설명: 이미지를 다른 도메인에서 가져오는 경우 CORS 정책에 의해 이미지를 다운로드할 때 CORS 문제가 발생할 수 있음. 이를 해결하기 위해 crossOrigin 속성을 사용하여 이미지를 다운로드할 때 CORS 문제를 해결
        /&amp;gt;
      &amp;lt;/LazyLoad&amp;gt;
    &amp;lt;/ImageWrap&amp;gt;
  );
}

const ImageWrap = styled.div`
  width: 160px;
  aspect-ratio: 16 / 9;
`;

const Image = styled.img`
  width: 100%;
  height: 100%;
`;

export default PhotoItem;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 같이 적용하면 이미지가 아닌 섬네일 이미지로 색상을 계산하기 떄문에 더욱 빠르고, 원본 이미지가 다운로드 되지 않아도 배경 색을 설정 할 수있기때문에 병렬적으로 배경 색이 설정됩니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;병목 코드를 최소화하기 전에 먼저 파악해야 할 점으로는 다음을 언급할 수 있습니다:&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;문제 발생 영역 분석&lt;/b&gt;: 우선 애플리케이션에서 성능이 저하되는 부분을 파악해야 합니다. 이를 위해 성능 모니터링 도구(예: Chrome Developer Tools, Lighthouse, Webpack Analyzer 등)를 사용해 문제 지점을 찾는 것이 중요합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;시간과 리소스 소모 분석&lt;/b&gt;: 특정 코드가 CPU, 메모리, 네트워크 자원을 과도하게 사용하거나 응답 시간을 지연시키는지를 분석합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;경합 조건 확인&lt;/b&gt;: 멀티스레드 환경에서는 경합 조건으로 인해 병목 현상이 발생할 수 있습니다. 공유 자원에 대한 접근을 확인하고 필요한 경우 동기화를 고려해야 합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;데이터베이스 쿼리 최적화&lt;/b&gt;: 많은 애플리케이션에서 데이터베이스 접근이 성능에 큰 영향을 미칩니다. 쿼리 실행 시간, 인덱싱, 캐시 활용 여부 등을 점검합니다&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;
&lt;div data-message-model-slug=&quot;gpt-4o&quot; data-message-id=&quot;c8cff90c-8d0d-486b-a42b-87204d5453af&quot; data-message-author-role=&quot;assistant&quot;&gt;
&lt;div&gt;
&lt;div&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Front-End</category>
      <author>dobbyyo</author>
      <guid isPermaLink="true">https://dobbyyo.tistory.com/22</guid>
      <comments>https://dobbyyo.tistory.com/entry/%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C-%EC%84%B1%EB%8A%A5-%EC%B5%9C%EC%A0%81%ED%99%94-4%ED%8E%B8-%EC%9D%B4%EB%AF%B8%EC%A7%80-%EC%A7%80%EC%97%B0-%EB%A0%88%EC%9D%B4%EC%95%84%EC%9B%83-%EC%9D%B4%EB%8F%99-%ED%94%BC%ED%95%98%EA%B8%B0-%EB%B3%91%EB%AA%A9-%EC%BD%94%EB%93%9C-%EC%B5%9C%EC%A0%81%ED%99%94#entry22comment</comments>
      <pubDate>Mon, 14 Oct 2024 18:06:25 +0900</pubDate>
    </item>
    <item>
      <title>프론트엔드 성능 최적화 3편 - 이미지 (지연 로딩 / 사이즈 최적화), 폰트 / 캐시 최적화, 불필요한 CSS 제거</title>
      <link>https://dobbyyo.tistory.com/entry/%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C-%EC%84%B1%EB%8A%A5-%EC%B5%9C%EC%A0%81%ED%99%94-3%ED%8E%B8-%EC%9D%B4%EB%AF%B8%EC%A7%80-%EC%A7%80%EC%97%B0-%EB%A1%9C%EB%94%A9-%EC%82%AC%EC%9D%B4%EC%A6%88-%EC%B5%9C%EC%A0%81%ED%99%94-%ED%8F%B0%ED%8A%B8-%EC%BA%90%EC%8B%9C-%EC%B5%9C%EC%A0%81%ED%99%94-%EB%B6%88%ED%95%84%EC%9A%94%ED%95%9C-CSS-%EC%A0%9C%EA%B1%B0</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&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;/li&gt;
&lt;li&gt;이미지 사이즈 최적화&lt;/li&gt;
&lt;li&gt;동영상 최적화&lt;/li&gt;
&lt;li&gt;폰트 최적화&lt;/li&gt;
&lt;li&gt;캐시 최적화&lt;/li&gt;
&lt;li&gt;불필요한 CSS 제거&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 이미지 지연 로딩&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이미지 지연로딩을 적용해야할 시점은 예로 첫 페이지 진입시 사진이 있는 부분은 스크롤을 내려야 보이는 경우 맨처음에는 다른 것이 보여할 경우입니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 첫 페이지 진입시 더욱 더 빠르게 보여지기 위해 이미지를 지연 로딩하는 방법을 공유하려고합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;뷰포트에 이미지가 표시될 위치까지 스크롤되었을 때 이미지를 로드할지 말지 판단할 수있습니다. 그런데 문제가 있습니다. 스크롤이 이동했을 때 해당 뷰포트에 이미지를 보이게 할지 판단해야하는데 스크롤 이벤트에 이 로직을 넣으면 스크롤할때 마다 해당 로직이 너무 많이 실행이 됩니다.&lt;/p&gt;
&lt;pre id=&quot;code_1727849807853&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;window.addEventListener('scroll', () =&amp;gt; console.log(&quot;이벤트 실행&quot;));&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-10-02 오후 3.18.15.png&quot; data-origin-width=&quot;1426&quot; data-origin-height=&quot;59&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qq4yP/btsJUhbyjFl/U4MHxKO91I9b5iyPZMSoD1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qq4yP/btsJUhbyjFl/U4MHxKO91I9b5iyPZMSoD1/img.png&quot; data-alt=&quot; 해당 구문 적용 후 콘솔&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qq4yP/btsJUhbyjFl/U4MHxKO91I9b5iyPZMSoD1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fqq4yP%2FbtsJUhbyjFl%2FU4MHxKO91I9b5iyPZMSoD1%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;1426&quot; height=&quot;59&quot; data-filename=&quot;스크린샷 2024-10-02 오후 3.18.15.png&quot; data-origin-width=&quot;1426&quot; data-origin-height=&quot;59&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt; 해당 구문 적용 후 콘솔&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 스크립트를 실행하고 스크롤해 보면 엄청나게 많은 로그가 찍힙니다. 이러면 브라우저의 메인 스레드에 무리가 갑니다. 성능을 향상시키려다가 오히려 약화를 시키게 되는 꼴이 됩니다..ㅠㅠ (상황에 따라 이벤트가 좋을 떄도 존재)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론, &lt;b&gt;lodash의 throttle과&lt;/b&gt; 같은 방식으로 처리할 수 있겠지만, 근본적인 해결 방법이 될 수는 없습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;throttle이란 짧은 시간에 여러번 발생하는 연산(함수)을 일정 시간 동안 한 번만 실행하도록하는 기술&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 같은 문제를 해결하기 위해서는 &lt;b&gt;Intersection Observer&lt;/b&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;b&gt;Intersection Observer&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 브라우저에서 제공하는 API 웹 페이지의 특정 요소를 관찰하면 &lt;b&gt;페이지 스크롤 시, 해당 요소가 화면에 들어왔는지 아닌지 알려&lt;/b&gt;줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉 요소가 화면에 들어왔을 때만 함수를 호출하는 것입니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MDN 주소: &lt;a href=&quot;https://developer.mozilla.org/ko/docs/Web/API/Intersection_Observer_API&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://developer.mozilla.org/ko/docs/Web/API/Intersection_Observer_API&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;Intersection Observer 간단하게 코드&lt;/u&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1728483306521&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const options = {
	root: null, // 설명: 뷰포트 기준으로 설정 (null: 뷰포트, document.querySelector('.container'): 특정 요소)
	rootMargin: '0px', // 설명: 뷰포트와 요소 사이의 여백 (음수: 요소가 뷰포트 안에 있을 때, 양수: 요소가 뷰포트 밖에 있을 때)
	threshold: '1.0', // 설명: 0.0 ~ 1.0 사이의 값 (0.0: 요소가 뷰포트에 들어왔을 때, 1.0: 요소가 완전히 보일 때)
  }
  const callback = (entries, observer) =&amp;gt; {
	console.log(&quot;Entries&quot;, entries); 
  }

  const observer = new IntersectionObserver(callback, options); // IntersectionObserver 생성 (콜백 함수와 옵션을 인자로 전달)

  observer.observe(document.querySelector('#target1')); // 관찰 대상 요소를 지정
  observer.observe(document.querySelector('#target2')); // 관찰 대상 요소를 지정&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;options는 이름 그래도 Intersection Observer의 옵션입니다. (자세한 설명은 위 코드를 보시면 됩니다.)&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;root: 대상 객체의 가시성을 확인할 때 사용되는 뷰포트 요소. (null 설정 시 브라우저의 뷰포트 요소)&lt;/li&gt;
&lt;li&gt;rootMargin: root 요소의 여백&lt;/li&gt;
&lt;li&gt;threshold: 가시성 펀센티지 (대상 요소가 어느 정도로 보일때 콜백을 실행할지 결정)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;new IntersectionsObserver 생성하면 이 인스턴스를 이용하여 원하는 요소를 관찰할 수 있습니다.&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;pre id=&quot;code_1728486032117&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function Card(props) {
  const imgRef = useRef(null);

  useEffect(() =&amp;gt; {
    const options = {};
    const callback = (entries, observer) =&amp;gt; {
      entries.forEach((entry) =&amp;gt; {
        if (entry.isIntersecting) {
          // 설명: entry.isIntersecting는 entry.target이 화면에 보이는지 여부를 나타냅니다.
          console.log(&quot;is intersecting&quot;, entry.target.dataset.src);
          entry.target.src = entry.target.dataset.src;
          observer.unobserve(entry.target); // 설명: observer.unobserve(entry.target)는 entry.target을 관찰 대상에서 제외합니다.
        }
      });
    };
    const observer = new IntersectionObserver(callback, options);

    observer.observe(imgRef.current); // 설명: observer.observe(imgRef.current)는 imgRef.current를 관찰 대상으로 추가합니다.

    return () =&amp;gt; observer.disconnect(); // 설명: observer.disconnect()는 observer를 해제합니다.
  }, []);

  return (
    &amp;lt;div className=&quot;Card text-center&quot;&amp;gt;
      &amp;lt;img data-src={props.image} ref={imgRef} /&amp;gt;
      &amp;lt;div className=&quot;p-5 font-semibold text-gray-700 text-xl md:text-lg lg:text-xl keep-all&quot;&amp;gt;{props.children}&amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}

export default Card;&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;b&gt;data-src&lt;/b&gt;를 사용하는 이유 src값이 할당되지 않기 때문에 해당 이미지를 로드하지 않습니다. 그리고 주소를 data-src에 넣은 이유는 나중에 이미지가 뷰포트에 들어왔을 때, data-src에 있는 값을 src로 옮겨 이미지를 로드하기 위해서입니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-10-10 오전 12.02.27.png&quot; data-origin-width=&quot;1411&quot; data-origin-height=&quot;67&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b3B8lr/btsJ0fdTlgj/oxENMRW2FV5Tp8Lge8AcIk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b3B8lr/btsJ0fdTlgj/oxENMRW2FV5Tp8Lge8AcIk/img.png&quot; data-alt=&quot;네트워크 콘솔로그 확인&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b3B8lr/btsJ0fdTlgj/oxENMRW2FV5Tp8Lge8AcIk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb3B8lr%2FbtsJ0fdTlgj%2FoxENMRW2FV5Tp8Lge8AcIk%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;1411&quot; height=&quot;67&quot; data-filename=&quot;스크린샷 2024-10-10 오전 12.02.27.png&quot; data-origin-width=&quot;1411&quot; data-origin-height=&quot;67&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;네트워크 콘솔로그 확인&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최초 페이지 로딩 시에는 main(1,2,3) 이미지들이 로드되지 않고 스크롤이 이미지 영역에 도달하면 콜백에서 작성한 코드로 인하여 세 이미지가 로드되는 것을 볼 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 최초 페이지 로딩 시에는 보이지 않는 이미지가 우선순위가 높은 콘텐츠의 로딩을 방해하지 않고 나중에 필요할 때 로드되는 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. 이미지 사이즈 최적화&amp;nbsp;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-10-10 오전 12.07.22.png&quot; data-origin-width=&quot;1379&quot; data-origin-height=&quot;68&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/coyxW2/btsJZj9he8G/IlehazkH6MqzefuGEr3Lv1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/coyxW2/btsJZj9he8G/IlehazkH6MqzefuGEr3Lv1/img.png&quot; data-alt=&quot;이미지 사이즈 확인&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/coyxW2/btsJZj9he8G/IlehazkH6MqzefuGEr3Lv1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcoyxW2%2FbtsJZj9he8G%2FIlehazkH6MqzefuGEr3Lv1%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;1379&quot; height=&quot;68&quot; data-filename=&quot;스크린샷 2024-10-10 오전 12.07.22.png&quot; data-origin-width=&quot;1379&quot; data-origin-height=&quot;68&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;이미지 사이즈 확인&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이미지가 현재 로딩되는 속도가 느립니다. 네트워크 패널로 확인한 결과 사이즈가 큰 것을 확인할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이미지 사이즈 최적화란 가로, 세로 사이즈를 줄여 이미지 용량을 줄이고 그만큼 더 빠르게 다운로드하는 기법입니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그전에 알아야할 것 이 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이미지(비트맵 이미지) 포맷 종류는 대표적으로 3가지가 있습니다. (SVG와 같은 벡터 이미지 제외)&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;- &lt;b&gt;Png&lt;/b&gt;: 무손실 압축 방식으로 원본을 훼손 없이 압축하여 알파 채널을 지원하는 이미지 포맷 (알파 채널이란 투명도)&lt;br /&gt;- &lt;b&gt;JPG(JPEG)&lt;/b&gt;: 압축 과정에서 정보 손실이 발생, 하지만 그만큼 이미지를 더 작은 사이즈로 줄일 수 있습니다.일반적으로 웹에서 이미지를 사용할 때는 고화질이어야 하거나 투명도 정보가 필요한 게 아니라면 JPG를 사용&lt;br /&gt;- &lt;b&gt;Webp&lt;/b&gt;: 무손실 압축과 손실 압축을 모두 제공하는 최신 이미지 포멧, 하지만 브라우저 호환성 생각하여 사용할지 결정 (요즘은 그냥 해도 될듯 합니다 많이 지원해서)&lt;br /&gt;&lt;br /&gt;- 사이즈: PNG &amp;gt; JPG &amp;gt; WebP&lt;br /&gt;- 화질: PNG = WEBp &amp;gt; JPG&lt;br /&gt;- 호환성: PNG = JPG &amp;gt; Webp&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Squoosh를 사용하여 이미지 변환&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JPG 또는 PNG 포맷의 이미지를 WebP 포맷으로 변환하여 고화질, 저용량의 이미지로 최적화 방법&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Squoosh란 이미지를 변환해 주는 컨버터입니다. (구글에서 만듬)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;URL: &lt;a href=&quot;https://squoosh.app/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://squoosh.app/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1728536220028&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;Squoosh&quot; data-og-description=&quot;Simple Open your image, inspect the differences, then save instantly. Feeling adventurous? Adjust the settings for even smaller files.&quot; data-og-host=&quot;squoosh.app&quot; data-og-source-url=&quot;https://squoosh.app/&quot; data-og-url=&quot;https://squoosh.app/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/dyozxJ/hyXedg5Y2j/XN189FehB2CmZRQO9gVgS0/img.png?width=1024&amp;amp;height=1024&amp;amp;face=0_0_1024_1024&quot;&gt;&lt;a href=&quot;https://squoosh.app/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://squoosh.app/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/dyozxJ/hyXedg5Y2j/XN189FehB2CmZRQO9gVgS0/img.png?width=1024&amp;amp;height=1024&amp;amp;face=0_0_1024_1024');&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;Squoosh&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Simple Open your image, inspect the differences, then save instantly. Feeling adventurous? Adjust the settings for even smaller files.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;squoosh.app&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;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-10-10 오후 2.53.35.png&quot; data-origin-width=&quot;318&quot; data-origin-height=&quot;915&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/6L6PM/btsJ1OtmWbX/vcUjltrhZ8jhh4bH1QUrbK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/6L6PM/btsJ1OtmWbX/vcUjltrhZ8jhh4bH1QUrbK/img.png&quot; data-alt=&quot;Squoosh 사용&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/6L6PM/btsJ1OtmWbX/vcUjltrhZ8jhh4bH1QUrbK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F6L6PM%2FbtsJ1OtmWbX%2FvcUjltrhZ8jhh4bH1QUrbK%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;318&quot; height=&quot;915&quot; data-filename=&quot;스크린샷 2024-10-10 오후 2.53.35.png&quot; data-origin-width=&quot;318&quot; data-origin-height=&quot;915&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Squoosh 사용&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 그림처럼 변환할수가있습니다. width, height를 600으로 설정한 것은 화면에 보이는 이미지의 사이즈가 300 * 300px 이므로 그 두배인 600 * 600px으로 설정한것입니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Quality가 너무 작으면 화질이 많이 떨어지고, 너무 크면 용량이 커지므로 70~80이 적당합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결과적으로 14.7KB로 압축되며 원본대미 매우 작아서 100%로 표시되고있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-10-10 오후 2.58.42.png&quot; data-origin-width=&quot;1427&quot; data-origin-height=&quot;68&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dfjwOz/btsJ1c2BqQn/XEWoKrgjXfDtbhnLThwRjk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dfjwOz/btsJ1c2BqQn/XEWoKrgjXfDtbhnLThwRjk/img.png&quot; data-alt=&quot;빨라진 사진 로딩&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dfjwOz/btsJ1c2BqQn/XEWoKrgjXfDtbhnLThwRjk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdfjwOz%2FbtsJ1c2BqQn%2FXEWoKrgjXfDtbhnLThwRjk%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;1427&quot; height=&quot;68&quot; data-filename=&quot;스크린샷 2024-10-10 오후 2.58.42.png&quot; data-origin-width=&quot;1427&quot; data-origin-height=&quot;68&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;빨라진 사진 로딩&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결과적으로 많이 빨라졌습니다. 하지만 아직 문제점이 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;문제점: &lt;b&gt;WebP는 호환성 문제&lt;/b&gt;가 있습니다. 특정 브라우저에서 제대로 렌더링되지 않을 수도 있습니다.&lt;br /&gt;해결방법: &lt;b&gt;picutre 태그&lt;/b&gt;를 사용하여 다양한 타입의 이미지를 렌더링하는 컨테이너로 사용&lt;/blockquote&gt;
&lt;pre id=&quot;code_1728547186183&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React, { useRef, useEffect } from &quot;react&quot;;

function Card(props) {
  const imgRef = useRef(null);

  useEffect(() =&amp;gt; {
    const options = {};
    const callback = (entries, observer) =&amp;gt; {
      entries.forEach((entry) =&amp;gt; {
        if (entry.isIntersecting) {
          const target = entry.target; // 설명: entry의 target을 target에 할당합니다.
          const previousSibling = target.previousElementSibling; // 설명: target의 이전 형제 요소를 previousSibling에 할당합니다.

          target.src = target.dataset.src; // 설명: 는 target의 src 속성에 target의 data-src 속성을 할당합니다.
          previousSibling.srcset = previousSibling.dataset.srcset; // 설명:  previousSibling의 srcset 속성에 previousSibling의 data-srcset 속성을 할당합니다.
          observer.unobserve(target);
        }
      });
    };
    const observer = new IntersectionObserver(callback, options);

    observer.observe(imgRef.current); // 설명: imgRef.current를 관찰 대상으로 추가합니다.

    return () =&amp;gt; observer.disconnect(); // 설명: observer를 해제합니다.
  }, []);

  return (
    &amp;lt;div className=&quot;Card text-center&quot;&amp;gt;
      &amp;lt;picture&amp;gt;
        &amp;lt;source data-srcset={props.webp} type=&quot;image/webp&quot; /&amp;gt;
        &amp;lt;img data-src={props.image} ref={imgRef} /&amp;gt;
      &amp;lt;/picture&amp;gt;
      &amp;lt;div className=&quot;p-5 font-semibold text-gray-700 text-xl md:text-lg lg:text-xl keep-all&quot;&amp;gt;{props.children}&amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}

export default Card;&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;위 코드 같이 picutre태그 안에 source, img 태그로 작성하면 webp가 지원 안하는 브라우저일 경우 jpg 이미지를 사용하게 됩니다.&lt;/blockquote&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;3. 동영상 최적화&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-10-10 오후 5.03.27.png&quot; data-origin-width=&quot;256&quot; data-origin-height=&quot;151&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BiyYS/btsJ0Bvf73s/x3glM3kT87B8MpvVaT8akK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BiyYS/btsJ0Bvf73s/x3glM3kT87B8MpvVaT8akK/img.png&quot; data-alt=&quot;동영상 크기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BiyYS/btsJ0Bvf73s/x3glM3kT87B8MpvVaT8akK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBiyYS%2FbtsJ0Bvf73s%2Fx3glM3kT87B8MpvVaT8akK%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;256&quot; height=&quot;151&quot; data-filename=&quot;스크린샷 2024-10-10 오후 5.03.27.png&quot; data-origin-width=&quot;256&quot; data-origin-height=&quot;151&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;동영상 크기&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;몇몇 웹에서 페이지 진입시 동영상이 보이는 웹사이트가 종종 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 위 사진을 보듯이 54MB인 것을 알 수 있습니다. 웹에서 사용하기에는 너무 큽니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;동영상 압축: 도영상의 가로와 세로 사이즈를 줄이고, 압축 방식을 변경하여 동영상의 용량을 줄이는 것입니다.&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Media.io를 사용하여 압축을 진행하는 방법을 알아보겠습니다.&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;URL: &lt;a href=&quot;https://www.media.io/apps/converter/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.media.io/apps/converter/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1728547752887&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;Online Video, Audio, and Image Converter with Batch Processing | Media.io Converter&quot; data-og-description=&quot;&quot; data-og-host=&quot;www.media.io&quot; data-og-source-url=&quot;https://www.media.io/apps/converter/&quot; data-og-url=&quot;https://www.media.io/apps/converter/&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://www.media.io/apps/converter/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.media.io/apps/converter/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&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;Online Video, Audio, and Image Converter with Batch Processing | Media.io Converter&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.media.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-10-10 오후 7.42.35.png&quot; data-origin-width=&quot;1055&quot; data-origin-height=&quot;585&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/NRPwA/btsJ144hTw5/5TC9HLGIBsAOC7zAahcmbK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/NRPwA/btsJ144hTw5/5TC9HLGIBsAOC7zAahcmbK/img.png&quot; data-alt=&quot;압축 방법&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/NRPwA/btsJ144hTw5/5TC9HLGIBsAOC7zAahcmbK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FNRPwA%2FbtsJ144hTw5%2F5TC9HLGIBsAOC7zAahcmbK%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;1055&quot; height=&quot;585&quot; data-filename=&quot;스크린샷 2024-10-10 오후 7.42.35.png&quot; data-origin-width=&quot;1055&quot; data-origin-height=&quot;585&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;압축 방법&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 URL에서 동영상을 WebM으로 압축을 한다면&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-10-10 오후 7.47.26.png&quot; data-origin-width=&quot;254&quot; data-origin-height=&quot;134&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/DoKgG/btsJ1eftAw1/Vh37jci48j1FEZRYyyuu90/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/DoKgG/btsJ1eftAw1/Vh37jci48j1FEZRYyyuu90/img.png&quot; data-alt=&quot;압축 적용&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/DoKgG/btsJ1eftAw1/Vh37jci48j1FEZRYyyuu90/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDoKgG%2FbtsJ1eftAw1%2FVh37jci48j1FEZRYyyuu90%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;254&quot; height=&quot;134&quot; data-filename=&quot;스크린샷 2024-10-10 오후 7.47.26.png&quot; data-origin-width=&quot;254&quot; data-origin-height=&quot;134&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;압축 적용&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;크기가 54.5MB에서 16.2MB까지 압축된 것을 확인 할 수 있습니다.&amp;nbsp; 코드로 적용한다면 마찬가지로 WebM파일을 지원하지 않는 부라우저를 위해 video 태그를 사용하여 코드를 작성하면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1728557504690&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;video
  className=&quot;absolute translateX--1/2 h-screen max-w-none min-w-screen -z-1 bg-black min-w-full min-h-screen&quot;
  autoPlay
  loop
  muted
&amp;gt;
  &amp;lt;source src={videoWebm} type=&quot;video/webm&quot; /&amp;gt;
  &amp;lt;source src={video} type=&quot;video/mp4&quot; /&amp;gt;
&amp;lt;/video&amp;gt;&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;style3&quot;&gt;Performance 패널로 분석해 보면 동영상이 이전과 달리 매우 빠르게 로드되고 재생되는 것을 확인할 수 있습니다.&amp;nbsp;&lt;br /&gt;하지만 압축 후 화질은 많이 저하되었습니다. 몇가지 방법이 있습니다.&lt;br /&gt;1. 패턴과 필터를 이용: 동영상이 패턴이나 필터에 가려져서 사용자는 도영상의 화질이 좋지 않음을 쉽게 인자 할 수 없습니다.&amp;nbsp;&amp;nbsp;&lt;br /&gt;상황에 맞게 압축 사용 여부 및 화질의 중요성을 따져가면서 적용하면 될 것 같습니다.&amp;nbsp;&lt;/blockquote&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4. 폰트 최적화&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;폰트 최적화를 하기전 &lt;b&gt;FOUT, FOIT&lt;/b&gt;를 알아야 합니다.&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;FOUT(Flash of Unstyled Text)&lt;/b&gt;:&amp;nbsp; Edge 브라우저에서 사용하는 방식, 폰트의 다운로드 여부와 상관없이 &lt;b&gt;먼저 텍스트를 보여준 후 폰트가 다운로드되면 그때 폰트를 적용하는 방식&lt;/b&gt;&lt;br /&gt;&lt;b&gt;FOIT(Flash of Invisible Text)&lt;/b&gt;: 크롬, 사파리, 파이어폭스 등에서 사용하는 방식, &lt;b&gt;폰트가 완전히 다운로드되기 전까지 텍스트 자체를 보여 주지 않고 다운로드가 완료되면 텍스트를 보여줍니다.&lt;/b&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;폰트 최적화 방법&lt;/b&gt;&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;폰트를 최적화하는 방법은 크게 두 가지가 있습니다.&lt;br /&gt;1. 폰트 적용 시점을 제어하는 방법&amp;nbsp;&lt;br /&gt;2. 폰트 사이즈를 줄이는 방법&lt;/blockquote&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;b&gt;fontfaceobserver 라이브러리를&lt;/b&gt; 설치해야합니다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1728558353825&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;npm i --save fontfaceobserver
npm i --save-dev @types/fontfaceobserver&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1728558666255&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import FontFaceObserver from &quot;fontfaceobserver&quot;;
const font = new FontFaceObserver(&quot;BMYEONSUNG&quot;);

function BannerVideo() {
  const [isFontLoaded, setIsFontLoaded] = useState(false);

  useEffect(() =&amp;gt; {
    font.load(null, 20000).then(function () {
      // 설명: 20000ms(20초) 동안 폰트가 로드되지 않으면 then() 함수가 실행됩니다.
      console.log(&quot;BMYEONSUNG is available now.&quot;);
      setIsFontLoaded(true);
    });
  }, []);

  return (
    &amp;lt;div className=&quot;BannerVideo w-full h-screen overflow-hidden relative bg-texture&quot;&amp;gt;
      &amp;lt;div className=&quot;absolute h-screen w-full left-1/2&quot;&amp;gt;
        &amp;lt;video
          className=&quot;absolute translateX--1/2 h-screen max-w-none min-w-screen -z-1 bg-black min-w-full min-h-screen&quot;
          autoPlay
          loop
          muted
        &amp;gt;
          &amp;lt;source src={videoWebm} type=&quot;video/webm&quot; /&amp;gt;
          &amp;lt;source src={video} type=&quot;video/mp4&quot; /&amp;gt;
        &amp;lt;/video&amp;gt;
      &amp;lt;/div&amp;gt;
      &amp;lt;div
        className=&quot;w-full h-full flex justify-center items-center&quot;
        // 설명: isFontLoaded가 true이면 opacity를 1로 설정하고, false이면 0으로 설정합니다.
        style={{ opacity: isFontLoaded ? 1 : 0, transform: &quot;opacity 0.3s ease&quot; }}
      &amp;gt;
        &amp;lt;div className=&quot;text-white text-center&quot;&amp;gt;
          &amp;lt;div className=&quot;text-6xl leading-none font-semibold&quot;&amp;gt;KEEP&amp;lt;/div&amp;gt;
          &amp;lt;div className=&quot;text-6xl leading-none font-semibold&quot;&amp;gt;CALM&amp;lt;/div&amp;gt;
          &amp;lt;div className=&quot;text-3xl leading-loose&quot;&amp;gt;AND&amp;lt;/div&amp;gt;
          &amp;lt;div className=&quot;text-6xl leading-none font-semibold&quot;&amp;gt;RIDE&amp;lt;/div&amp;gt;
          &amp;lt;div className=&quot;text-5xl leading-tight font-semibold&quot;&amp;gt;LONGBOARD&amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}

export default BannerVideo;&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;style3&quot;&gt;위 코드처럼 적용하게 된다면 opacity를 폰트 로드 상태에 따라 0에서 1로 바꿔주고 transition 속성을 설정하면 폰트가 로드될 때 애니메이션 효과와 함께 나타날 것 입니다.&amp;nbsp;&lt;/blockquote&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;흔히 많이 사용하는 폰트의 포멧은 TFF 입니다. 매번 리소르르 다운로드해야 하는 웹 환경에서는 적절하지 않습니다. 그래서 나온 것이 WOFF입니다. 하지만 이것도 마찬가지로 호환성에 문제가 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;파일 크기를 비교하자면 아래와 같습니다.&amp;nbsp;&lt;br /&gt;EOT &amp;gt; TFF/OTF &amp;gt; WOFF &amp;gt; WOFF2&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;폰트의 포맷을 변경하기 위해서는 아래 링크에서 변경할 수가 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;URL: &lt;a href=&quot;https://transfonter.org/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://transfonter.org/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1728558974222&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;Online @font-face generator&quot; data-og-description=&quot;The @font-face CSS rule allows web developers to specify online fonts to display text on their web pages. By allowing authors to provide their own fonts, @font-face eliminates the need to depend on the limited number of fonts users have installed on their &quot; data-og-host=&quot;transfonter.org&quot; data-og-source-url=&quot;https://transfonter.org/&quot; data-og-url=&quot;https://transfonter.org&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/HDMnq/hyXhTadjEq/4E4IsNr6d3h4TKE04vBtj0/img.png?width=600&amp;amp;height=315&amp;amp;face=0_0_600_315&quot;&gt;&lt;a href=&quot;https://transfonter.org/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://transfonter.org/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/HDMnq/hyXhTadjEq/4E4IsNr6d3h4TKE04vBtj0/img.png?width=600&amp;amp;height=315&amp;amp;face=0_0_600_315');&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;Online @font-face generator&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;The @font-face CSS rule allows web developers to specify online fonts to display text on their web pages. By allowing authors to provide their own fonts, @font-face eliminates the need to depend on the limited number of fonts users have installed on their&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;transfonter.org&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;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;edited_스크린샷 2024-10-10 오후 8.16.49.png&quot; data-origin-width=&quot;810&quot; data-origin-height=&quot;503&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cFP4WR/btsJ18eu2n6/G0yWQ10muEK0NTBKgC6QJ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cFP4WR/btsJ18eu2n6/G0yWQ10muEK0NTBKgC6QJ0/img.png&quot; data-alt=&quot;폰트 포맷 변경&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cFP4WR/btsJ18eu2n6/G0yWQ10muEK0NTBKgC6QJ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcFP4WR%2FbtsJ18eu2n6%2FG0yWQ10muEK0NTBKgC6QJ0%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;810&quot; height=&quot;503&quot; data-filename=&quot;edited_스크린샷 2024-10-10 오후 8.16.49.png&quot; data-origin-width=&quot;810&quot; data-origin-height=&quot;503&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;폰트 포맷 변경&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이것도 마찬가지로 호환성에 문제가 있습니다. 이 부분을 코드로 호환이 불가능할 때 기존 포맷을 이용하도록 만들면 됩니다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1728559302161&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@font-face {
  font-family: BMYEONSUNG;
  src: url(&quot;./assets/fonts/BMYEONSUNG.woff2&quot;) format(&quot;woff2&quot;), 
  	   url(&quot;./assets/fonts/BMYEONSUNG.woff&quot;) format(&quot;woff&quot;),
       url(&quot;./assets/fonts/BMYEONSUNG.ttf&quot;) format(&quot;truetype&quot;);
       font-display: block;
}&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;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;5. 캐시 최적화&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;웹에서 사용하는 캐시는 크게 두 가지로 구분할 수 있습니다.&amp;nbsp;&lt;br /&gt;- &lt;b&gt;메모리 캐시&lt;/b&gt;: 메모리에 저장하는 방식. (RAM)&lt;br /&gt;- &lt;b&gt;디스크 캐시&lt;/b&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;브라우저가 캐시를 하기 위해서는 &lt;b&gt;Cache-Control&lt;/b&gt; 헤더가 응답 헤더에 있어야합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;Cache-Control&lt;/b&gt;: 리소스의 응답 헤더에 설정되는 헤더. 브라우저는 서버에서 이 헤더를 통해 캐시를 어떻게, 얼마나 적용해야 하는지 판단. 대표적으로 5가지 값이 조합되어 들어갑니다.&lt;br /&gt;1. &lt;b&gt;no-cache&lt;/b&gt;: 캐시를 사용하기 전 서버에 검사 후 사용&lt;br /&gt;2.&lt;b&gt; no-store&lt;/b&gt;: 캐시 사용 안함&lt;br /&gt;3. &lt;b&gt;public&lt;/b&gt;: 모든 환경에서 캐시 사용 가능&lt;br /&gt;4. &lt;b&gt;private&lt;/b&gt;: 브라우저 환경에서만 캐시 사용, 외부 캐시 서버에서는 사용 불가&lt;br /&gt;5. &lt;b&gt;max-age&lt;/b&gt;: 캐시의 유효 시간&lt;/blockquote&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;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 모든 리소스에 동일한 캐시 설정은 효율적이지가 않습니다. 왜냐 리소스마다 사용이나 변경 빈도가 달라 캐시의 유효 시간도 달라져야하기 떄문입니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 일반적으로 HTML파일에는 no-cache를 설정합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- JS, CSS는 사전에 빌드되어 파일명에 해시를 함께 가지고 있습니다. 즉, 코드가 변경되면 해시도 변경되어 완전히 다른파일이 되어 버립니다. 따라서 캐시를 아무리 오래 적용해도 HTML만 최산 상태라면 JS, CSS파일은 당연히 최신 리소스를 로드합니다. 이미지도 마찬가지입니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;캐시 적용 방법&lt;/h4&gt;
&lt;pre id=&quot;code_1728561480978&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const header = {
  setHeaders: (res, path) =&amp;gt; {
    if (path.endsWith(&quot;.html&quot;)) {
      res.setHeader(&quot;Cache-Control&quot;, &quot;no-cache&quot;); // 설명: html 파일은 캐시하지 않습니다.
    } else if (path.endsWith(&quot;.js&quot;) || path.endsWith(&quot;.css&quot;) || path.endsWith(&quot;.webp&quot;)) {
      res.setHeader(&quot;Cache-Control&quot;, &quot;public, max-age=31536000&quot;); // 설명: 다른 파일들은 1년 동안 캐시합니다.
    } else {
      res.setHeader(&quot;Cache-Control&quot;, &quot;no-store&quot;); // 설명: 다른 파일들은 캐시하지 않습니다.
    }
  },
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드처럼 파일마다 캐시를 지정할 수 가 있습니다. 이를 잘 활용하여 캐시도 잘 사용하면 좋을 것 같습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;6. 불필요한 css 제거&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Coverage&lt;/b&gt; 패널을 이용해 CSS를 분석해봅시다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-10-10 오후 9.45.44.png&quot; data-origin-width=&quot;1435&quot; data-origin-height=&quot;46&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cHQ3x5/btsJ0iiKBLz/BKwLRc9jTn9l6ym1Kj2lHK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cHQ3x5/btsJ0iiKBLz/BKwLRc9jTn9l6ym1Kj2lHK/img.png&quot; data-alt=&quot;Coverage 패널&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cHQ3x5/btsJ0iiKBLz/BKwLRc9jTn9l6ym1Kj2lHK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcHQ3x5%2FbtsJ0iiKBLz%2FBKwLRc9jTn9l6ym1Kj2lHK%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;1435&quot; height=&quot;46&quot; data-filename=&quot;스크린샷 2024-10-10 오후 9.45.44.png&quot; data-origin-width=&quot;1435&quot; data-origin-height=&quot;46&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Coverage 패널&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-10-10 오후 9.46.58.png&quot; data-origin-width=&quot;337&quot; data-origin-height=&quot;427&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dVNVcH/btsJ11mrhVn/iArKwl97fJbK3W72cqTGNK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dVNVcH/btsJ11mrhVn/iArKwl97fJbK3W72cqTGNK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dVNVcH/btsJ11mrhVn/iArKwl97fJbK3W72cqTGNK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdVNVcH%2FbtsJ11mrhVn%2FiArKwl97fJbK3W72cqTGNK%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;337&quot; height=&quot;427&quot; data-filename=&quot;스크린샷 2024-10-10 오후 9.46.58.png&quot; data-origin-width=&quot;337&quot; data-origin-height=&quot;427&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;분석한 내용을 보면 99%가 사용이 안되는 것을 확인할 수 잇습니다. 더 자세히 보기위해 해당 분석한 내용을 클릭하면  와 같이 나옵니다&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;PurgeCss를 이용해서 불필요한 CSS를 제거해봅시다.&amp;nbsp;&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;PurgeCss&lt;/b&gt;: 파일에 들어 있는 모든 키워드를 추출하여 해당 키워드를 이름으로 갖는 CSS클래스만 보존하고 나머지 매칭되지 않은 클래스는 모두 지우는 방식&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용하기위해 라이브러리를 설치해줍시다.&lt;/p&gt;
&lt;pre id=&quot;code_1728564589200&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;npm i --save-dev purgecss&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;그다음 키워드를 추출하고자 하는 파일과 불필요한 클래스를 제거할 CSS파일을 지정하면 됩니다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1728564949368&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;  &quot;scripts&quot;: {
    &quot;start&quot;: &quot;npm run build:style &amp;amp;&amp;amp; react-scripts start&quot;,
    &quot;build&quot;: &quot;npm run build:style &amp;amp;&amp;amp; react-scripts build&quot;,
    &quot;build:style&quot;: &quot;postcss src/tailwind.css -o src/styles.css&quot;,
    &quot;serve&quot;: &quot;node ./server/server.js&quot;,
    &quot;server&quot;: &quot;node ./node_modules/json-server/lib/cli/bin.js --watch ./server/database.json -c ./server/config.json&quot;,
    &quot;purge&quot;: &quot;purgecss --css ./build/static/css/*.css 
    		  --output ./build/static/css/ 
              --content ./build/index.html ./build/static/js/*.js 
              --config ./purgecss.config.js&quot;
  },&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;package.json에 purge를 지정하고 위 코드를 작성해줍니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;purgecss&lt;/b&gt;: 이 도구는 HTML, JS 등의 파일을 분석하여 사용되지 않는 CSS를 찾아 제거합니다. 웹 애플리케이션의 성능을 개선하기 위해 사용됩니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;--css ./build/static/css/*.css&lt;/b&gt;: 빌드된 CSS 파일들을 대상으로 사용되지 않는 스타일을 제거하겠다는 뜻입니다. ./build/static/css/ 폴더 내에 있는 모든 .css 파일이 대상입니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;--output ./build/static/css/&lt;/b&gt;: 제거된 결과물(CSS 파일들)을 같은 폴더인 ./build/static/css/에 저장하겠다는 의미입니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;--content ./build/index.html ./build/static/js/*.js&lt;/b&gt;: 어떤 파일들을 분석해서 사용되지 않는 CSS를 찾을지 지정합니다. 여기서는 ./build/index.html과 ./build/static/js/ 폴더 내의 모든 JavaScript 파일이 분석 대상입니다. 이 파일들에 실제로 사용되는 CSS만 남기고, 나머지를 제거합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;주의&amp;nbsp;&lt;br /&gt;PurgeCSS는 콜론(:) 문자를 하나의 키워드로 인식하지 못하고 잘라내서 lg:m-8이 lg와 m-8이라는 각각 다른 키워드로 인식합니다. 그렇기에 purgecss.config.js에 옵션을 추가 설정해줘야합니다.&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1728565257434&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;module.exports = {
  defaultExtractor: (content) =&amp;gt; content.match(/[\w-/:]+(?&amp;lt;!:)/g) || [],
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-10-10 오후 10.03.22.png&quot; data-origin-width=&quot;1319&quot; data-origin-height=&quot;27&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dD7VvY/btsJ1IOdvGk/a3s0yAxDu9k76RM3v7our0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dD7VvY/btsJ1IOdvGk/a3s0yAxDu9k76RM3v7our0/img.png&quot; data-alt=&quot;적용 후 비율&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dD7VvY/btsJ1IOdvGk/a3s0yAxDu9k76RM3v7our0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdD7VvY%2FbtsJ1IOdvGk%2Fa3s0yAxDu9k76RM3v7our0%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;1319&quot; height=&quot;27&quot; data-filename=&quot;스크린샷 2024-10-10 오후 10.03.22.png&quot; data-origin-width=&quot;1319&quot; data-origin-height=&quot;27&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;적용 후 비율&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;적용 후 다시 Coverage 패널을 통해 확인하면 많이 불필요한 CSS가 제거된것을 확인할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;다음 장에서&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;- 라이브러리를 통해 최적화하는 이미지 지연 로딩&lt;br /&gt;- 레이아웃 이동 피하기&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;- 리덕스 렌더링 최적화&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;- 병목 코드 최적화&amp;nbsp;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Front-End</category>
      <author>dobbyyo</author>
      <guid isPermaLink="true">https://dobbyyo.tistory.com/21</guid>
      <comments>https://dobbyyo.tistory.com/entry/%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C-%EC%84%B1%EB%8A%A5-%EC%B5%9C%EC%A0%81%ED%99%94-3%ED%8E%B8-%EC%9D%B4%EB%AF%B8%EC%A7%80-%EC%A7%80%EC%97%B0-%EB%A1%9C%EB%94%A9-%EC%82%AC%EC%9D%B4%EC%A6%88-%EC%B5%9C%EC%A0%81%ED%99%94-%ED%8F%B0%ED%8A%B8-%EC%BA%90%EC%8B%9C-%EC%B5%9C%EC%A0%81%ED%99%94-%EB%B6%88%ED%95%84%EC%9A%94%ED%95%9C-CSS-%EC%A0%9C%EA%B1%B0#entry21comment</comments>
      <pubDate>Thu, 10 Oct 2024 22:24:15 +0900</pubDate>
    </item>
    <item>
      <title>2022 KAKAO TECH INTERNSHIP - 성격 유형 검사하기</title>
      <link>https://dobbyyo.tistory.com/entry/2022-KAKAO-TECH-INTERNSHIP-%EC%84%B1%EA%B2%A9-%EC%9C%A0%ED%98%95-%EA%B2%80%EC%82%AC%ED%95%98%EA%B8%B0</link>
      <description>&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;문제&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;URL:&amp;nbsp; &lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/118666&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://school.programmers.co.kr/learn/courses/30/lessons/118666&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1728370784554&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;코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.&quot; data-og-host=&quot;programmers.co.kr&quot; data-og-source-url=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/118666&quot; data-og-url=&quot;https://programmers.co.kr/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/crna0p/hyXeesWWwP/bz3MVXsPzYzKoGpvT5cmN0/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/cNI09z/hyXedOkTs5/Wre9Bu0BLbwldKCD4GMzqK/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/118666&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/118666&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/crna0p/hyXeesWWwP/bz3MVXsPzYzKoGpvT5cmN0/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/cNI09z/hyXedOkTs5/Wre9Bu0BLbwldKCD4GMzqK/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;프로그래머스&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-10-08 오후 4.00.04.png&quot; data-origin-width=&quot;824&quot; data-origin-height=&quot;644&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bWpx68/btsJZrei0Lu/fRttrcKdJpHK2eCUlab8o0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bWpx68/btsJZrei0Lu/fRttrcKdJpHK2eCUlab8o0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bWpx68/btsJZrei0Lu/fRttrcKdJpHK2eCUlab8o0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbWpx68%2FbtsJZrei0Lu%2FfRttrcKdJpHK2eCUlab8o0%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;824&quot; height=&quot;644&quot; data-filename=&quot;스크린샷 2024-10-08 오후 4.00.04.png&quot; data-origin-width=&quot;824&quot; data-origin-height=&quot;644&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-10-08 오후 4.00.16.png&quot; data-origin-width=&quot;823&quot; data-origin-height=&quot;825&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cyeLjC/btsJZd1G1Ii/V6na700KCMexBGGIVQCoUK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cyeLjC/btsJZd1G1Ii/V6na700KCMexBGGIVQCoUK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cyeLjC/btsJZd1G1Ii/V6na700KCMexBGGIVQCoUK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcyeLjC%2FbtsJZd1G1Ii%2FV6na700KCMexBGGIVQCoUK%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;823&quot; height=&quot;825&quot; data-filename=&quot;스크린샷 2024-10-08 오후 4.00.16.png&quot; data-origin-width=&quot;823&quot; data-origin-height=&quot;825&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;h2 data-ke-size=&quot;size26&quot;&gt;문제 요점 파악&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;점수 계산과 선택지의 관계&lt;/b&gt;: 각 질문마다 선택한 답에 따라 성격 유형 점수가 달라지며, 선택지의 중앙값(4)이 기준이 되어 점수가 계산됩니다. 동의 선택지는 우측 성격 유형에, 비동의 선택지는 좌측 성격 유형에 점수를 부여하는 방식으로, 선택지가 클수록 동의 성향이, 작을수록 비동의 성향이 반영됩니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;성격 유형 쌍의 점수 비교&lt;/b&gt;: 성격 유형은 4개의 지표로 나뉘며, 각 지표에서 두 성격 유형 중 점수가 더 높은 쪽이 최종 결과로 선택됩니다. 만약 점수가 같다면 사전 순으로 빠른 성격 유형이 선택됩니다.&lt;/li&gt;
&lt;/ul&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;/h2&gt;
&lt;pre id=&quot;code_1728373764570&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function solution(survey, choices) {
  let answer = &quot;&quot;;

  // 초기 점수 객체 생성
  const surveyResObj = {
    R: 0,
    T: 0,
    C: 0,
    F: 0,
    J: 0,
    M: 0,
    A: 0,
    N: 0,
  };
  const mbtis = [&quot;RT&quot;, &quot;CF&quot;, &quot;JM&quot;, &quot;AN&quot;];

  for (let i = 0; i &amp;lt; choices.length; i++) {
    if (choices[i] === 4) {
      // 3일 경우 점수 없으므로 반복문 바로 반복
      continue;
    } else if (choices[i] &amp;gt; 4) {
      // 4보다 클경우 동의 (어피치형)

      const surveyType = survey[i][1];
      surveyResObj[surveyType] += choices[i] - 4;
    } else if (choices[i] &amp;lt; 4) {
      // 4보다 작을경우 비동의 (네오형)

      const surveyType = survey[i][0];
      surveyResObj[surveyType] += 4 - choices[i];
    }
  }

  for (let mbti of mbtis) {
    // const leftType = mbti[0][0];
    // const rightType = mbti[1][0];
    const [leftType, rightType] = mbti;

    if (surveyResObj[leftType] &amp;lt; surveyResObj[rightType]) {
      answer += rightType;
    } else {
      answer += leftType;
    }
  }

  return answer;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Algorithm</category>
      <category>카카오 인턴십</category>
      <category>코테</category>
      <author>dobbyyo</author>
      <guid isPermaLink="true">https://dobbyyo.tistory.com/20</guid>
      <comments>https://dobbyyo.tistory.com/entry/2022-KAKAO-TECH-INTERNSHIP-%EC%84%B1%EA%B2%A9-%EC%9C%A0%ED%98%95-%EA%B2%80%EC%82%AC%ED%95%98%EA%B8%B0#entry20comment</comments>
      <pubDate>Tue, 8 Oct 2024 18:50:58 +0900</pubDate>
    </item>
    <item>
      <title>[카카오 인턴] 키패드 누르기</title>
      <link>https://dobbyyo.tistory.com/entry/%EC%B9%B4%EC%B9%B4%EC%98%A4-%EC%9D%B8%ED%84%B4-%ED%82%A4%ED%8C%A8%EB%93%9C-%EB%88%84%EB%A5%B4%EA%B8%B0</link>
      <description>&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;문제&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;URL: &lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/67256&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://school.programmers.co.kr/learn/courses/30/lessons/67256&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1728368109898&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;코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.&quot; data-og-host=&quot;programmers.co.kr&quot; data-og-source-url=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/67256&quot; data-og-url=&quot;https://programmers.co.kr/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/d4xF6g/hyXegK4Y6l/Ikcuz0Ek3e4bJE8vWNI0PK/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/csmWrV/hyXeefr1bD/CfHyAhvXrPeopXMUkRceM0/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/67256&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/67256&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/d4xF6g/hyXegK4Y6l/Ikcuz0Ek3e4bJE8vWNI0PK/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/csmWrV/hyXeefr1bD/CfHyAhvXrPeopXMUkRceM0/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;프로그래머스&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-10-08 오후 3.12.44.png&quot; data-origin-width=&quot;536&quot; data-origin-height=&quot;969&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cmFC9C/btsJY8zixrP/rgK5XQXVuMJBAhjcsCrYNK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cmFC9C/btsJY8zixrP/rgK5XQXVuMJBAhjcsCrYNK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cmFC9C/btsJY8zixrP/rgK5XQXVuMJBAhjcsCrYNK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcmFC9C%2FbtsJY8zixrP%2FrgK5XQXVuMJBAhjcsCrYNK%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;536&quot; height=&quot;969&quot; data-filename=&quot;스크린샷 2024-10-08 오후 3.12.44.png&quot; data-origin-width=&quot;536&quot; data-origin-height=&quot;969&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;문제 파악&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;1. &lt;b&gt;키패드 좌표 설정 및 손가락 위치 관리&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;키패드의 각 숫자를 &lt;b&gt;2차원 좌표&lt;/b&gt;로 변환해 손가락의 이동을 쉽게 계산할 수 있어야 합니다.&lt;/li&gt;
&lt;li&gt;왼손은 * 키에서, 오른손은 # 키에서 시작하므로 이들의 초기 위치를 설정하고, 각 숫자를 누를 때마다 손가락의 위치를 업데이트하는 것이 중요합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;2. &lt;b&gt;&amp;nbsp;거리 계산&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;가운데 열&lt;/b&gt;(2, 5, 8, 0)의 숫자를 누를 때는 왼손과 오른손의 거리를 비교해야 합니다. 이때 &lt;b&gt;맨해튼 거리&lt;/b&gt;를 사용하여 각각의 손가락이 키패드에서 얼마나 떨어져 있는지 계산합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;3. &lt;b&gt;왼쪽, 오른쪽 열의 숫자에 대한 규칙 적용&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;왼쪽 열&lt;/b&gt;(1, 4, 7)은 항상 왼손이 사용되며, &lt;b&gt;오른쪽 열&lt;/b&gt;(3, 6, 9)은 항상 오른손이 사용됩니다. 이를 구분해서 처리해야 합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;4. &lt;b&gt;손잡이의 우선순위 적용&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;거리가 같을 때&lt;/b&gt;, 사용자가 &lt;b&gt;왼손잡이&lt;/b&gt;인지 &lt;b&gt;오른손잡이&lt;/b&gt;인지에 따라 어떤 손가락을 사용할지를 결정해야 합니다. 이를 위해 주어진 hand 값을 확인하여 거리 계산 후 거리가 같다면 손잡이에 따라 결정합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style5&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;멘해튼 거리 공식이란&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;맨해튼 거리(Manhattan Distance)는 두 점 사이의 거리를 계산할 때&amp;nbsp;직선 거리가 아니라 축을 따라 이동하는 거리를 계산하는 방식입니다. 이 방식은 주로&amp;nbsp;격자형 좌표계에서 사용됩니다.&lt;/li&gt;
&lt;li&gt;맨해튼 거리 공식: 맨해튼 거리=∣x1​&amp;minus;x2​∣+∣y1​&amp;minus;y2​∣&lt;/li&gt;
&lt;/ul&gt;
&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;언제 사용하면 좋은가?&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;- 격자형 환경에서 상하좌우로 이동할 때 거리 계산이 필요할 때.&lt;br /&gt;- 장애물이 없고 축을 따라 이동하는 상황에서는 매우 직관적이고 효율적입니다.&lt;/blockquote&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;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;코드&lt;/h2&gt;
&lt;pre id=&quot;code_1728368641278&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function solution(numbers, hand) {
  let answer = &quot;&quot;;

  const keyPad = {
    1: [0, 0],
    2: [0, 1],
    3: [0, 2],
    4: [1, 0],
    5: [1, 1],
    6: [1, 2],
    7: [2, 0],
    8: [2, 1],
    9: [2, 2],
    &quot;*&quot;: [3, 0],
    0: [3, 1],
    &quot;#&quot;: [3, 2],
  };

  let leftRes = keyPad[&quot;*&quot;];
  let rightRes = keyPad[&quot;#&quot;];

  //  거리 계산 함수 (멘해튼 거리 공식) 알고 있으면 편안하다 
  const getDis = (p1, p2) =&amp;gt; {
    return Math.abs(p1[0] - p2[0]) + Math.abs(p1[1] - p2[1]);
  };

  for (let number of numbers) {
    // 1, 4, 7일 경우 왼손
    if ([1, 4, 7].includes(number)) {
      answer += &quot;L&quot;;
      leftRes = keyPad[number];
      // 3,6,9일 경우 오른손
    } else if ([3, 6, 9].includes(number)) {
      answer += &quot;R&quot;;
      rightRes = keyPad[number];
    } else {
      // 2,5,8,0일 경우
      const leftDis = getDis(leftRes, keyPad[number]);
      const rightDis = getDis(rightRes, keyPad[number]);

      if (leftDis &amp;gt; rightDis) {
        // 오른손이 가까울 경우
        answer += &quot;R&quot;;
        rightRes = keyPad[number];
      } else if (leftDis &amp;lt; rightDis) {
        // 왼손이 가까울 경우
        answer += &quot;L&quot;;
        leftRes = keyPad[number];
      } else {
        // 거리가 같을 경우 주 손잡이
        if (hand === &quot;right&quot;) {
          answer += &quot;R&quot;;
          rightRes = keyPad[number];
        } else if (hand === &quot;left&quot;) {
          answer += &quot;L&quot;;
          leftRes = keyPad[number];
        }
      }
    }
  }

  return answer;
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Algorithm</category>
      <category>알고리즘</category>
      <category>카카오 인턴</category>
      <category>코딩테스트</category>
      <author>dobbyyo</author>
      <guid isPermaLink="true">https://dobbyyo.tistory.com/19</guid>
      <comments>https://dobbyyo.tistory.com/entry/%EC%B9%B4%EC%B9%B4%EC%98%A4-%EC%9D%B8%ED%84%B4-%ED%82%A4%ED%8C%A8%EB%93%9C-%EB%88%84%EB%A5%B4%EA%B8%B0#entry19comment</comments>
      <pubDate>Tue, 8 Oct 2024 18:24:24 +0900</pubDate>
    </item>
    <item>
      <title>로또의 최고 순위와 최저 순위</title>
      <link>https://dobbyyo.tistory.com/entry/%EB%A1%9C%EB%98%90%EC%9D%98-%EC%B5%9C%EA%B3%A0-%EC%88%9C%EC%9C%84%EC%99%80-%EC%B5%9C%EC%A0%80-%EC%88%9C%EC%9C%84</link>
      <description>&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;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/77484&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;URL: https://school.programmers.co.kr/learn/courses/30/lessons/77484&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-10-02 오전 10.56.20.png&quot; data-origin-width=&quot;1580&quot; data-origin-height=&quot;786&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kTB9c/btsJRzrx5gz/KoL28pxfaWWVA88i54XLv1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kTB9c/btsJRzrx5gz/KoL28pxfaWWVA88i54XLv1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kTB9c/btsJRzrx5gz/KoL28pxfaWWVA88i54XLv1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkTB9c%2FbtsJRzrx5gz%2FKoL28pxfaWWVA88i54XLv1%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;1580&quot; height=&quot;786&quot; data-filename=&quot;스크린샷 2024-10-02 오전 10.56.20.png&quot; data-origin-width=&quot;1580&quot; data-origin-height=&quot;786&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-10-02 오전 10.56.31.png&quot; data-origin-width=&quot;513&quot; data-origin-height=&quot;356&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/X7LsD/btsJSmygKFV/g6IkHKsCKIKsytK8rt3KlK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/X7LsD/btsJSmygKFV/g6IkHKsCKIKsytK8rt3KlK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/X7LsD/btsJSmygKFV/g6IkHKsCKIKsytK8rt3KlK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FX7LsD%2FbtsJSmygKFV%2Fg6IkHKsCKIKsytK8rt3KlK%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;513&quot; height=&quot;356&quot; data-filename=&quot;스크린샷 2024-10-02 오전 10.56.31.png&quot; data-origin-width=&quot;513&quot; data-origin-height=&quot;356&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;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;문제 요점 파악&lt;/b&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1. &lt;b&gt;0의 역할 파악&lt;/b&gt;:&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;lottos 배열에서 0은 알아볼 수 없는 숫자를 의미하며, 이것은 &lt;b&gt;맞을 수도 있고 틀릴 수도 있는 숫자&lt;/b&gt;를 나타냅니다. 따라서, 0의 개수를 파악하는 것이 중요합니다. 0은 &lt;b&gt;최고 순위&lt;/b&gt;를 계산할 때 맞춘 숫자로 취급되고, &lt;b&gt;최저 순위&lt;/b&gt;를 계산할 때는 틀린 숫자로 취급됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2. &lt;b&gt;현재 맞춘 숫자 파악&lt;/b&gt;:&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;lottos 배열에서 당첨 번호(win_nums)와 일치하는 숫자의 개수를 세는 것이 중요합니다. 이 숫자는 &lt;b&gt;최저 순위&lt;/b&gt;를 계산할 때 사용됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3. &lt;b&gt;최대와 최소 순위 계산&lt;/b&gt;:&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;최고 순위: 0의 개수와 맞춘 숫자 개수를 더해서 계산합니다. 즉, 0을 모두 맞췄다고 가정한 경우가 최고 순위입니다.&lt;/li&gt;
&lt;li&gt;최저 순위: 현재 맞춘 숫자만을 기준으로 계산합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;코드&lt;/b&gt;&amp;nbsp;&lt;/h3&gt;
&lt;pre id=&quot;code_1727834371267&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function solution(lottos, win_nums) {
  let answer = [];
  const win_set = new Set(win_nums);
  // 맞은 갯수 has를 사용하기 우해 new Set을 사용
  const corretc_count = lottos.filter((num) =&amp;gt; win_set.has(num)).length;
  // 조커숫자인 0 개수 가져오기
  const zero_count = lottos.filter((num) =&amp;gt; num === 0).length;

  // 화살표 함수로 순위 계산
  const getRank = (n) =&amp;gt; {
    if (n &amp;lt;= 1) {
      return 6;
    }
    return 7 - n;
  };

  const maxWin = getRank(corretc_count + zero_count);
  const minWin = getRank(corretc_count);

  answer = [maxWin, minWin];
  return answer;
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Algorithm</category>
      <author>dobbyyo</author>
      <guid isPermaLink="true">https://dobbyyo.tistory.com/18</guid>
      <comments>https://dobbyyo.tistory.com/entry/%EB%A1%9C%EB%98%90%EC%9D%98-%EC%B5%9C%EA%B3%A0-%EC%88%9C%EC%9C%84%EC%99%80-%EC%B5%9C%EC%A0%80-%EC%88%9C%EC%9C%84#entry18comment</comments>
      <pubDate>Wed, 2 Oct 2024 18:30:42 +0900</pubDate>
    </item>
    <item>
      <title>프론트엔드 성능 최적화 2편 - 애니메이션, 컴포넌트(지연,사전)로딩, 이미지 사전 로딩</title>
      <link>https://dobbyyo.tistory.com/entry/%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C-%EC%84%B1%EB%8A%A5-%EC%B5%9C%EC%A0%81%ED%99%94-2%ED%8E%B8-%EC%95%A0%EB%8B%88%EB%A9%94%EC%9D%B4%EC%85%98-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8%EC%A7%80%EC%97%B0%EC%82%AC%EC%A0%84%EB%A1%9C%EB%94%A9-%EC%9D%B4%EB%AF%B8%EC%A7%80-%EC%82%AC%EC%A0%84-%EB%A1%9C%EB%94%A9</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 컴포넌트 지연 로딩&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;지연 로딩(Lazy Loading)&lt;/b&gt;&lt;/span&gt;은 웹 애플리케이션의 성능을 최적화하기 위해 &lt;b&gt;컴포넌트 단위로 코드를 분할&lt;/b&gt;하고, 컴포넌트가 실제로 필요할 때 로드하는 방식입니다. 이는 페이지 전체 코드를 한꺼번에 불러오는 대신, &lt;b&gt;사용자가 상호작용하는 순간에만 해당 컴포넌트를 로드&lt;/b&gt;하기 때문에 불필요한 리소스 낭비를 줄일 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어, 초기 화면에 필요하지 않은 모달이나 비동기 데이터를 표시하는 컴포넌트는 페이지가 처음 로드될 때 불러올 필요가 없습니다. 이럴 때 지연 로딩을 적용하면, &lt;b&gt;최초 로딩 속도&lt;/b&gt;를 크게 개선할 수 있습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. 컴포넌트 사전 로딩&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지연 로딩을 사용하면 초기 로딩 속도는 빨라지지만, &lt;b&gt;사용 중인 페이지에서 컴포넌트를 처음 호출할 때 추가 다운로드&lt;/b&gt;가 발생해 사용자 경험이 떨어질 수 있습니다. 이런 문제를 해결하기 위한 방법이 &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;컴포넌트 사전 로딩(Prefetching)&lt;/span&gt;&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사전 로딩은 &lt;b&gt;컴포넌트가 필요하기 전에 미리 코드를 로드&lt;/b&gt;하여, 사용자가 해당 기능을 요청했을 때 &lt;b&gt;즉시 컴포넌트를 사용할 수 있도록 준비&lt;/b&gt;하는 방식입니다. 예를 들어, 사용자가 특정 버튼에 마우스를 올리면 그때 미리 컴포넌트를 로드하여 클릭할 때 &lt;b&gt;지연 없이 컴포넌트를 보여줄 수 있습니다&lt;/b&gt;. 이를 통해 지연 로딩으로 발생할 수 있는 &lt;b&gt;첫 로딩 지연을 최소화&lt;/b&gt;할 수 있습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. 이미지 사전 로딩&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이미지&lt;/b&gt;도 컴포넌트처럼 지연 로딩을 적용할 수 있습니다. 사용자가 페이지를 탐색하는 과정에서 필요한 시점에 이미지를 로드하면, 그동안 이미지가 로드되는 시간을 기다려야 하기 때문에 사용자가 &lt;b&gt;불편함&lt;/b&gt;을 느낄 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이미지 사전 로딩은 &lt;b&gt;필요한 이미지가 실제로 사용되기 전 미리 로드&lt;/b&gt;하여, 사용자가 이미지를 요청하는 시점에 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;즉시 이미지를 보여줄 수 있는 기법&lt;/b&gt;&lt;/span&gt;입니다. 특히 &lt;b&gt;고해상도 이미지&lt;/b&gt;나 &lt;b&gt;대용량 이미지&lt;/b&gt;가 많을 경우, 사전 로딩을 통해 시각적 요소의 지연을 줄여 사용자 경험을 개선할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;사례: 이미지 로딩 속도 문제&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-09-24 오후 5.03.43.png&quot; data-origin-width=&quot;852&quot; data-origin-height=&quot;387&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/orGhO/btsJLe0jwng/8tEQMO4935afgoMbDrNq2k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/orGhO/btsJLe0jwng/8tEQMO4935afgoMbDrNq2k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/orGhO/btsJLe0jwng/8tEQMO4935afgoMbDrNq2k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2ForGhO%2FbtsJLe0jwng%2F8tEQMO4935afgoMbDrNq2k%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;852&quot; height=&quot;387&quot; data-filename=&quot;스크린샷 2024-09-24 오후 5.03.43.png&quot; data-origin-width=&quot;852&quot; data-origin-height=&quot;387&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-09-24 오후 5.03.52.png&quot; data-origin-width=&quot;687&quot; data-origin-height=&quot;613&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cfZJAb/btsJJJ15Vku/kNSDyMXU93kciiw5M7Oykk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cfZJAb/btsJJJ15Vku/kNSDyMXU93kciiw5M7Oykk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cfZJAb/btsJJJ15Vku/kNSDyMXU93kciiw5M7Oykk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcfZJAb%2FbtsJJJ15Vku%2FkNSDyMXU93kciiw5M7Oykk%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;687&quot; height=&quot;613&quot; data-filename=&quot;스크린샷 2024-09-24 오후 5.03.52.png&quot; data-origin-width=&quot;687&quot; data-origin-height=&quot;613&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 예시 이미지에서 볼 수 있듯이, &lt;b&gt;이미지 로딩이 느리면 사용자가 콘텐츠를 볼 때까지 기다려야 하며&lt;/b&gt; 이는 &lt;b&gt;웹 서비스에 부정적인 영향을 미칠 수 있습니다&lt;/b&gt;. 이 경우, 이미지 파일이 너무 크거나, 압축이 잘 이루어지지 않았을 가능성이 있습니다. &lt;b&gt;이미지 최적화&lt;/b&gt;는 서비스 성능에 직접적인 영향을 미치므로, 반드시 해결해야 하는 문제입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;코드&lt;/span&gt;&lt;/h4&gt;
&lt;div style=&quot;background-color: #263238; color: #eeffff;&quot;&gt;
&lt;div&gt;&lt;span style=&quot;color: #82aaff;&quot;&gt;&lt;span style=&quot;color: #82aaff;&quot;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;pre id=&quot;code_1727699367362&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function App() {
const [showModal, setShowModal] = useState(false)

return (
  &amp;lt;div className=&quot;App&quot;&amp;gt;
      &amp;lt;Header /&amp;gt;
      &amp;lt;InfoTable /&amp;gt;
      &amp;lt;ButtonModal onClick={() =&amp;gt; { setShowModal(true) }}&amp;gt;올림픽 사진 보기&amp;lt;/ButtonModal&amp;gt;
      &amp;lt;SurveyChart /&amp;gt;
      &amp;lt;Footer /&amp;gt;
      {showModal ? &amp;lt;ImageModal closeModal={() =&amp;gt; { setShowModal(false) }} /&amp;gt; : null}
  &amp;lt;/div&amp;gt;
)
}

const ButtonModal = styled.button`
    border-radius: 30px;
    border: 1px solid #999;
    padding: 12px 30px;
    background: none;
    font-size: 1.1em;
    color: #555;
    outline: none;
    cursor: pointer;
`

export default App&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div style=&quot;background-color: #263238; color: #eeffff;&quot;&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1727699382044&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const ImageModal = (props) =&amp;gt; {
const images = [
  {
    original: 'https://stillmed.olympic.org/media/Photos/2016/08/20/part-1/20-08-2016-Football-Men-01.jpg?interpolation=lanczos-none&amp;amp;resize=*:800',
    thumbnail: 'https://stillmed.olympic.org/media/Photos/2016/08/20/part-1/20-08-2016-Football-Men-01.jpg?interpolation=lanczos-none&amp;amp;resize=*:150',
  },
  {
    original: 'https://stillmed.olympic.org/media/Photos/2016/08/12/12-08-2016-archery-individual-men-03.jpg?interpolation=lanczos-none&amp;amp;resize=*:800',
    thumbnail: 'https://stillmed.olympic.org/media/Photos/2016/08/12/12-08-2016-archery-individual-men-03.jpg?interpolation=lanczos-none&amp;amp;resize=*:150',
  },
    ...
]

return (
  &amp;lt;ImageModalWrapper&amp;gt;
    &amp;lt;ImageModalContainer&amp;gt;
      &amp;lt;BtnClose src={btnClose} onClick={props.closeModal} /&amp;gt;
      &amp;lt;ModalHeader&amp;gt;올림픽 사진&amp;lt;/ModalHeader&amp;gt;
      &amp;lt;Modalbody&amp;gt;
        &amp;lt;ImageGallery items={images} /&amp;gt;
      &amp;lt;/Modalbody&amp;gt;
    &amp;lt;/ImageModalContainer&amp;gt;
  &amp;lt;/ImageModalWrapper&amp;gt;
)
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;외부 라이브러리를 사용하는 경우, &lt;span style=&quot;color: #ee2323;&quot;&gt;해당 라이브러리의 크기만큼 최종 번들 파일 크기가 커지며, 이는 JS 파일 로드 시간이 증가하는 문제를 야기할 수 있습니다.&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;style2&quot;&gt;React에서 이미지를 갤러리 형식으로 보여주는 react-image-gallery 라이브러리는 강력하지만, 사이즈가 커서 서비스 첫 화면에 로드할 필요가 없는 경우가 많습니다. 예를 들어, 이 라이브러리는 사진 갤러리를 표시하는 모달 창을 띄울 때만 필요합니다. 이럴 때는, 지연 로딩(Lazy Loading)을 적용해 성능을 최적화할 수 있습니다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;이전 장에서 소개한 cra-bundle-analyzer 도구를 사용해 번들 크기를 분석할 수 있습니다. 실제로 분석해보면, Image-gallery.js가 약 26.24 KB의 크기를 차지하고 있음을 확인할 수 있습니다.&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-09-24 오후 5.14.17.png&quot; data-origin-width=&quot;1435&quot; data-origin-height=&quot;1278&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cIjpQD/btsJJJAYYZu/5fW5dj9u4lGNFtPgJP6lfK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cIjpQD/btsJJJAYYZu/5fW5dj9u4lGNFtPgJP6lfK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cIjpQD/btsJJJAYYZu/5fW5dj9u4lGNFtPgJP6lfK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcIjpQD%2FbtsJJJAYYZu%2F5fW5dj9u4lGNFtPgJP6lfK%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;1435&quot; height=&quot;1278&quot; data-filename=&quot;스크린샷 2024-09-24 오후 5.14.17.png&quot; data-origin-width=&quot;1435&quot; data-origin-height=&quot;1278&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 이 라이브러리는 서비스 &lt;b&gt;첫 화면에서 필요하지 않으며&lt;/b&gt;, &lt;b&gt;사진 갤러리 모달 창&lt;/b&gt;을 띄울 때만 사용됩니다. 따라서, 이 라이브러리를 &lt;b&gt;코드 분할&lt;/b&gt;하고 &lt;b&gt;지연 로딩&lt;/b&gt;을 적용하면 서비스 성능을 크게 개선할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;4. 지연 로딩 적용&lt;/span&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Step 1: Lazy와 Suspense 사용하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;React에서 &lt;b&gt;lazy&lt;/b&gt; 함수와 &lt;b&gt;Suspense&lt;/b&gt; 컴포넌트를 사용해 &lt;b&gt;모달 코드&lt;/b&gt;를 분리하고, 모달이 실제로 필요한 시점에만 해당 코드를 불러오는 방식으로 설정할 수 있습니다. 아래 코드는 이를 구현한 예시입니다:&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Step 2: 코드 분할 효과&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드에서 ImageModal과 그 안에서 사용하는 &lt;b&gt;react-image-gallery&lt;/b&gt; 라이브러리는 &lt;b&gt;지연 로딩&lt;/b&gt;되며, 사용자가 모달을 열 때만 해당 코드가 &lt;b&gt;동적 청크&lt;/b&gt;로 분리되어 로드됩니다. 이로 인해 첫 화면 로딩 시 번들 파일 크기가 줄어들고, &lt;b&gt;JS 로딩 시간이 단축&lt;/b&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;/h4&gt;
&lt;pre id=&quot;code_1727700084241&quot; class=&quot;javascript&quot; style=&quot;letter-spacing: 0px;&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// import ImageModal from './components/ImageModal'
const LazyImageModal = lazy(()=&amp;gt; import('./components/ImageModal'))

function App() {
  const [showModal, setShowModal] = useState(false)

  return (
    &amp;lt;div className=&quot;App&quot;&amp;gt;
      &amp;lt;Header /&amp;gt;
      &amp;lt;InfoTable /&amp;gt;
      &amp;lt;ButtonModal onClick={() =&amp;gt; { setShowModal(true) }}&amp;gt;올림픽 사진 보기&amp;lt;/ButtonModal&amp;gt;
      &amp;lt;SurveyChart /&amp;gt;
      &amp;lt;Footer /&amp;gt;
      {showModal ? &amp;lt;LazyImageModal closeModal={() =&amp;gt; { setShowModal(false) }} /&amp;gt; : null}
    &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;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-09-30 오후 4.56.41.png&quot; data-origin-width=&quot;1351&quot; data-origin-height=&quot;43&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kI7Wq/btsJQ2tlF2F/Waww5pkiOVc6vbtEvdd95k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kI7Wq/btsJQ2tlF2F/Waww5pkiOVc6vbtEvdd95k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kI7Wq/btsJQ2tlF2F/Waww5pkiOVc6vbtEvdd95k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkI7Wq%2FbtsJQ2tlF2F%2FWaww5pkiOVc6vbtEvdd95k%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;1351&quot; height=&quot;43&quot; data-filename=&quot;스크린샷 2024-09-30 오후 4.56.41.png&quot; data-origin-width=&quot;1351&quot; data-origin-height=&quot;43&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;지연 로딩은 React에서 성능 최적화를 위해 널리 사용하는 기법입니다. 이번에는 실제로 react-image-gallery 라이브러리와 ImageModal 컴포넌트를 지연 로딩한 후 그 결과를 확인해보겠습니다.&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;우선 Network 패널에서 모달 버튼을 클릭해보면, 모달이 뜨는 순간 &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;Network 패널에 새로운 청크 파일이 두 개 로드&lt;/span&gt;&lt;/b&gt;되는 것을 확인할 수 있습니다. &lt;b&gt;이 두 파일은 ImageModal 컴포넌트와 react-image-gallery 라이브러리 파일&lt;/b&gt;입니다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 npx cra-bundle-analyzer를 다시 사용해 번들 구성을 분석해보면, 다음과 같은 결과를 볼 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-09-30 오후 4.54.56.png&quot; data-origin-width=&quot;1428&quot; data-origin-height=&quot;1234&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ck4f1V/btsJQBprA3R/eKQTWflMa5y4JK3S3RkGcK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ck4f1V/btsJQBprA3R/eKQTWflMa5y4JK3S3RkGcK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ck4f1V/btsJQBprA3R/eKQTWflMa5y4JK3S3RkGcK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fck4f1V%2FbtsJQBprA3R%2FeKQTWflMa5y4JK3S3RkGcK%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;1428&quot; height=&quot;1234&quot; data-filename=&quot;스크린샷 2024-09-30 오후 4.54.56.png&quot; data-origin-width=&quot;1428&quot; data-origin-height=&quot;1234&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;blockquote data-ke-style=&quot;style3&quot;&gt;위 그림에서 확인할 수 있듯이, react-image-gallery 라이브러리가 분리되어 있으며, 아래의 하늘색 블록이 ImageModal 컴포넌트입니다. 덕분에 &lt;span style=&quot;color: #ee2323;&quot;&gt;초기 번들에 포함되었던 총 52KB가 분할되어, 초기 로딩에 영향을 미치지 않게 되었습니다&lt;/span&gt;.&lt;br /&gt;지금은 모달 코드가 크지 않아서 성능 차이가 크게 느껴지지 않을 수 있지만, 추후 모달 안에 더 많은 콘텐츠나 라이브러리가 추가된다면, 이번에 적용한 컴포넌트 지연 로딩 기법이&amp;nbsp;의미 있는 최적화로 작용할 것입니다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;단점은 없을까?&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;물론, 지연 로딩이&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;모든 상황에서 장점만 있는 것&lt;/b&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;은 아닙니다. 예를 들어, 초기 로딩 시간에는 확실히 이점을 제공하지만,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;모달을 띄우는 시점에서는 단점&lt;/b&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;이 드러날 수 있습니다. 모달 코드를 분리한 덕분에,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;모달을 띄울 때 네트워크 요청을 통해 코드를 새로 로드&lt;/b&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;해야 하며, 로드가 완료되기 전까지 모달이 뜨지 않습니다. 이로 인해&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;모달이 뜨기까지 약간의 지연&lt;/b&gt;이 발생할 수 있습니다.&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;지연 로딩 장점&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;초기 로딩 시간 단축&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;지연 로딩은 사용자가 즉시 볼 필요가 없는 컴포넌트를 나중에 로드하기 때문에, 페이지의 초기 로딩 시간을 크게 줄일 수 있습니다. 특히, 대형 애플리케이션에서 유용합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;번들 크기 축소&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;컴포넌트를 필요할 때만 로드함으로써 번들 파일을 더 작게 유지할 수 있습니다. 이렇게 하면 다운로드할 자바스크립트 파일의 크기가 줄어들어 페이지 로드 성능이 향상됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;효율적인 리소스 사용&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;필요하지 않은 컴포넌트를 로드하지 않기 때문에 메모리와 네트워크 리소스를 효율적으로 사용할 수 있습니다. 사용자가 특정 페이지나 기능을 사용할 때만 해당 리소스를 불러오기 때문에 전반적인 성능이 개선됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;코드 분할 (Code Splitting)&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;지연 로딩을 사용하면 Webpack과 같은 번들러가 애플리케이션을 여러 개의 청크로 나누어 효율적으로 관리할 수 있습니다. 코드 분할은 성능을 더욱 향상시키는 데 기여합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;지연 로딩 단점&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;첫 로드 시 지연&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;지연 로딩된 컴포넌트가 필요할 때마다 추가 네트워크 요청이 발생하므로, 해당 컴포넌트가 처음 로드될 때 약간의 지연이 생길 수 있습니다. 특히 네트워크 상태가 좋지 않을 때 눈에 띄는 지연이 발생할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;추가 복잡성&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;지연 로딩을 설정하고 관리하는 과정이 복잡할 수 있습니다. 특히 로딩 상태를 처리해야 하거나, 여러 동적 경로를 갖는 경우 로직이 더 복잡해질 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;사용자 경험 저하 가능성&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;로딩이 느려지면 사용자는 페이지 내에서 클릭 후 바로 콘텐츠를 보지 못할 수 있습니다. 이를 해결하기 위해서는 로딩 중 상태를 잘 처리해야 하며, 부드러운 사용자 경험을 제공하는 것이 중요합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;SEO 문제&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;서버 사이드 렌더링(SSR)을 사용하지 않는 경우, 검색 엔진이 모든 지연 로딩된 컴포넌트를 크롤링하지 못할 수 있습니다. 이는 SEO에 부정적인 영향을 미칠 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&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;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;5. 사전 로딩&lt;/b&gt;&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;이제 &lt;b&gt;사전 로딩(Prefetching)&lt;/b&gt;을 적용해보겠습니다. &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;사전 로딩은 사용자가 특정 리소스를 클릭하거나 요청하기 전에 미리 데이터를 불러와 준비하는 기법으로, 성능 최적화에 매우 효과적&lt;/span&gt;&lt;/b&gt;입니다. 이번에는 사용자가 모달을 클릭하기 전에 마우스가 버튼 위에 올라왔을 때 데이터를 미리 요청하는 방식으로 사전 로딩을 구현해보겠습니다.&lt;/blockquote&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;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;마우스가 모달 오픈 버튼 위에 있을 때&lt;/b&gt;: 이 시점에 &lt;b&gt;컴포넌트와 데이터를 미리 요청&lt;/b&gt;하여 로딩 시간을 줄입니다. 이는 사전 로딩의 대표적인 적용 방식입니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;버튼을 클릭했을 때&lt;/b&gt;: 클릭 시 이미 필요한 데이터가 &lt;b&gt;사전 로드&lt;/b&gt;되어 있으므로 &lt;b&gt;즉시 모달이 열리며&lt;/b&gt;, 지연 로딩을 사용해 컴포넌트를 보여줍니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;5-1. 마우스 오버 시 사전 로딩 구현&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;React에서 &lt;b&gt;onMouseEnter&lt;/b&gt; 이벤트를 사용하여 마우스가 버튼 위에 올라왔을 때 데이터를 미리 로드하는 방식입니다. 이 방법은 사용자가 버튼을 클릭하기 전 &lt;b&gt;약간의 시간을 활용해 데이터를 미리 불러와&lt;/b&gt;, 모달이 열릴 때 지연 없이 콘텐츠를 표시할 수 있습니다.&lt;/blockquote&gt;
&lt;div style=&quot;background-color: #263238; color: #eeffff;&quot;&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1727701065658&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const LazyImageModal = lazy(() =&amp;gt; import(&quot;./components/ImageModal&quot;));

function App() {
  const [showModal, setShowModal] = useState(false);

  useEffect(() =&amp;gt; {
    // eslint-disable-next-line no-unused-expressions
    import(&quot;./components/ImageModal&quot;);
  }, []);

  return (
    &amp;lt;div className=&quot;App&quot;&amp;gt;
      &amp;lt;Header /&amp;gt;
      &amp;lt;InfoTable /&amp;gt;
      &amp;lt;ButtonModal
        onClick={() =&amp;gt; {
          setShowModal(true);
        }}
      &amp;gt;
        올림픽 사진 보기
      &amp;lt;/ButtonModal&amp;gt;
      &amp;lt;SurveyChart /&amp;gt;
      &amp;lt;Footer /&amp;gt;

      &amp;lt;Suspense fallback={false}&amp;gt;
        {showModal ? (
          &amp;lt;LazyImageModal
            closeModal={() =&amp;gt; {
              setShowModal(false);
            }}
          /&amp;gt;
        ) : null}
      &amp;lt;/Suspense&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-09-30 오후 4.56.41.png&quot; data-origin-width=&quot;1351&quot; data-origin-height=&quot;43&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kI7Wq/btsJQ2tlF2F/Waww5pkiOVc6vbtEvdd95k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kI7Wq/btsJQ2tlF2F/Waww5pkiOVc6vbtEvdd95k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kI7Wq/btsJQ2tlF2F/Waww5pkiOVc6vbtEvdd95k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkI7Wq%2FbtsJQ2tlF2F%2FWaww5pkiOVc6vbtEvdd95k%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;1351&quot; height=&quot;43&quot; data-filename=&quot;스크린샷 2024-09-30 오후 4.56.41.png&quot; data-origin-width=&quot;1351&quot; data-origin-height=&quot;43&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;적용 후&amp;nbsp;&amp;nbsp;마우스위에 마우스를 올리면&amp;nbsp;모달 버튼을 클릭 시 해당 두 파일이 불러오는 것을 Network 탭에서 확인 가능합니다.&amp;nbsp;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;5-2. 컴포넌트가 마운트된 후 사전 로딩&lt;/b&gt;&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;만약 모달의 크기나 &lt;b&gt;데이터가 커서 로드하는 데 시간이 오래 걸린&lt;/b&gt;다면, &lt;b&gt;컴포넌트가 마운트된 후 사전 로딩을 진행할 수도 있습니다&lt;/b&gt;. 이 방법은 &lt;span style=&quot;color: #ee2323;&quot;&gt;useEffect&lt;/span&gt; 훅을 사용하여, 페이지가 처음 로드된 후 특정 시점에 사전 로딩을 진행하는 방식입니다.&lt;/blockquote&gt;
&lt;div style=&quot;background-color: #263238; color: #eeffff;&quot;&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1727701259798&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;useEffect(() =&amp;gt; {
  import(&quot;./components/ImageModal&quot;);
}, []);&lt;/code&gt;&lt;/pre&gt;
&lt;span style=&quot;color: #89ddff;&quot;&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;동작 방식:&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;useEffect&lt;/b&gt;는 컴포넌트가 처음 마운트될 때 한 번 실행됩니다. 이때 &lt;b&gt;모달 컴포넌트를 미리 로드&lt;/b&gt;하여, 나중에 사용자가 모달을 열 때 &lt;b&gt;네트워크 요청 없이 즉시 로드&lt;/b&gt;가 가능해집니다.&lt;/li&gt;
&lt;li&gt;모달 크기가 크거나 복잡한 경우, &lt;b&gt;페이지가 처음 로드될 때&lt;/b&gt; 사전 로딩을 하는 것이 더 적합할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 같은 형태로 사전 로딩을 할 수 있습니다. 이 뿐 만이 아니라 여러 방법이 있습니다. 서비스나 기능의 특성에 따라 다양한 방법을 적용할 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div data-message-id=&quot;6d703068-aaef-40a4-b912-407e116f519b&quot; data-message-author-role=&quot;assistant&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;지연 로딩(Lazy Loading)과 사전 로딩(Prefetching)을 함께 사용하는 이유&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;지연 로딩&lt;/b&gt;은 웹 애플리케이션의 초기 로딩 성능을 최적화하는 기법입니다. 처음 페이지가 로드될 때 불필요한 자원을 미리 불러오지 않음으로써&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;초기 로딩 시간을 단축&lt;/b&gt;시킵니다. 하지만 지연 로딩된 컴포넌트는 사용자가 요청하는 순간 로드되기 때문에&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;첫 로딩 시 약간의 지연&lt;/b&gt;이 발생할 수 있습니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;반면,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;사전 로딩&lt;/b&gt;은 사용자가 특정 컴포넌트를 필요로 하기 전에&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;미리 리소스를 로드&lt;/b&gt;하여, 실제로 컴포넌트가 필요할 때 즉시 제공할 수 있도록 준비하는 방식입니다. 이를 통해 지연 로딩의 단점인&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;첫 로딩 시의 지연을 보완&lt;/b&gt;할 수 있습니다.&lt;/p&gt;
&lt;b&gt;&lt;/b&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 156px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;height: 20px; width: 12.5581%;&quot;&gt;&lt;b&gt;장점&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 37.4419%; height: 20px;&quot;&gt;&lt;b&gt;지연 로딩&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 20px;&quot;&gt;&lt;b&gt;사전 로딩&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;width: 12.5581%; height: 18px;&quot;&gt;&lt;b&gt;초기 로딩 속도 개선&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 37.4419%; height: 18px;&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;필요 없는 컴포넌트를 로드하지 않으므로&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;초기 로딩 시간이 단축&lt;/b&gt;됩니다.&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 18px;&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;페이지가 필요하지 않은 리소스를 미리 로드하여,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;즉시 제공&lt;/b&gt;할 수 있습니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;width: 12.5581%; height: 18px;&quot;&gt;&lt;b&gt;번들 크기 축소&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 37.4419%; height: 18px;&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;초기 번들 크기를 작게 유지하여&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;네트워크 성능이 향상&lt;/b&gt;됩니다.&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 18px;&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;네트워크 상태가 좋을 때 미리 리소스를 로드해,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;빠르게 사용할 준비&lt;/b&gt;가 됩니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;width: 12.5581%; height: 18px;&quot;&gt;&lt;b&gt;리소스 사용 효율성&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 37.4419%; height: 18px;&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;사용자가 필요로 할 때만 리소스를 로드하여&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;불필요한 자원 낭비를 방지&lt;/b&gt;합니다.&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 18px;&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;미리 로드하여&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;사용자가 느끼는 지연을 최소화&lt;/b&gt;할 수 있습니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&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;table style=&quot;border-collapse: collapse; width: 100%; height: 82px;&quot; border=&quot;1&quot; data-ke-style=&quot;style12&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;width: 12.5581%; height: 18px;&quot;&gt;&lt;b&gt;단점&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 37.4419%; height: 18px;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 18px;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;width: 12.5581%; height: 18px;&quot;&gt;&lt;b&gt;첫 로드 지연&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 37.4419%; height: 18px;&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;처음 로드 시&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;네트워크 요청으로 인한 지연&lt;/b&gt;이 발생할 수 있습니다.&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 18px;&quot;&gt;&lt;b&gt;불필요한 리소스를 미리 로드&lt;/b&gt;하여, 네트워크 자원을 낭비할 가능성이 있습니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;width: 12.5581%; height: 18px;&quot;&gt;&lt;b&gt;네트워크 의존성&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 37.4419%; height: 18px;&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;컴포넌트 로드가&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;네트워크 상태에 영향을 받을 수&lt;/b&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;있으며, 느린 네트워크에서는 첫 로딩 지연이 두드러질 수 있습니다.&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 18px;&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;네트워크 상태가 불안정하면 미리 로드된 리소스가&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;낭비&lt;/b&gt;될 수 있습니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 10px;&quot;&gt;
&lt;td style=&quot;width: 12.5581%; height: 10px;&quot;&gt;&lt;b&gt;구현 복잡성&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 37.4419%; height: 10px;&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;구현이 비교적 쉬우나,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;로딩 상태 처리&lt;/b&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;같은 추가적인 UI 처리가 필요할 수 있습니다.&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 10px;&quot;&gt;&lt;b&gt;미리 로드할 시점&lt;/b&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;을 결정하고 이를 관리하는 데&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;복잡성이&lt;/b&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;따를 수 있습니다.&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;width: 12.5581%; height: 18px;&quot;&gt;&lt;b&gt;SEO 문제&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 37.4419%; height: 18px;&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;서버 사이드 렌더링(SSR)이 없으면,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;지연 로딩된 콘텐츠가 검색 엔진에 인덱싱되지 않을 수&lt;/b&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;있습니다.&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 18px;&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;검색 엔진에는 큰 영향을 미치지 않으나,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;잘못된 리소스를 미리 로드&lt;/b&gt;하면 불필요한 로딩이 발생할 수 있습니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&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;6. 이미지 사전 로딩&lt;/b&gt;&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;웹 페이지에서 이미지가 늦게 로드되면서 화면에 이상하게 표시되는 문제는 사용자 경험을 저하시킬 수 있습니다. 이러한 문제를 해결하기 위해&amp;nbsp;이미지 사전 로딩을 활용할 수 있습니다. 이미지 사전 로딩을 통해&amp;nbsp;이미지를 미리 로드하여, 사용자가 이미지를 요청할 때&amp;nbsp;즉시 표시할 수 있게 합니다.&lt;br /&gt;&lt;b&gt;이미지 로딩 방식&lt;/b&gt;&lt;br /&gt;일반적으로 &lt;b&gt;이미지는 HTML 또는 CSS에서 호출되는 시점에 로드&lt;/b&gt;됩니다. 그러나&amp;nbsp;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;JavaScript로 직접 이미지 로드를 제어할 수 있으며, 이를 통해 이미지가 사용되기 전에 미리 불러올 수 있습니다.&amp;nbsp;JavaScript Image 객체를 사용하여 이미지를 미리 로드&lt;/span&gt;&lt;/b&gt;하는 방법은 다음과 같습니다:&lt;/blockquote&gt;
&lt;pre id=&quot;code_1727702548526&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const img = new Image(); 
img.src = '{이미지 주소}';&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;div style=&quot;background-color: #263238; color: #eeffff;&quot;&gt;
&lt;div&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;&lt;/span&gt;&lt;/span&gt;
&lt;pre id=&quot;code_1727702579688&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;useEffect(() =&amp;gt; {
	import(&quot;./components/ImageModal&quot;);

	const img = new Image();

	img.src =
		&quot;https://stillmed.olympic.org/media/Photos/2016/08/20/part-1/20-08-2016-Football-Men-01.jpg?interpolation=lanczos-none&amp;amp;resize=*:800&quot;;
}, []);&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드에서는 &lt;b&gt;ImageModal 컴포넌트&lt;/b&gt;와 &lt;b&gt;이미지&lt;/b&gt;를 사전에 로드하여, 사용자가 해당 이미지를 보려는 시점에 &lt;b&gt;지연 없이 즉시 표시&lt;/b&gt;될 수 있도록 준비합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-09-30 오후 9.07.15.png&quot; data-origin-width=&quot;1142&quot; data-origin-height=&quot;70&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cOEzhH/btsJRcpsFuV/rUAp6PhCqWJ2kTkXgfq5S0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cOEzhH/btsJRcpsFuV/rUAp6PhCqWJ2kTkXgfq5S0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cOEzhH/btsJRcpsFuV/rUAp6PhCqWJ2kTkXgfq5S0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcOEzhH%2FbtsJRcpsFuV%2FrUAp6PhCqWJ2kTkXgfq5S0%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;1142&quot; height=&quot;70&quot; data-filename=&quot;스크린샷 2024-09-30 오후 9.07.15.png&quot; data-origin-width=&quot;1142&quot; data-origin-height=&quot;70&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;Network 탭을 확인해 보면, 해당 이미지가 사전에 불러와지는 것을 확인할 수 있습니다. 나중에는 API에서 받은 이미지 주소를 파라미터로 넘겨서 사전 로딩을 활용할 수도 있습니다.&lt;br /&gt;하지만 단점도 있습니다. 사전 로딩을 하는 순간 브라우저의 리소스를 그만큼 많이 사용하기 떄문에 다른 성능 문제를 야기할 수 있습니다.&amp;nbsp;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;이미지 사전 로딩의 장점&lt;/b&gt;&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;사용자 경험 향상&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이미지를 미리 로드하면 사용자가 이미지 요청 시 &lt;b&gt;지연 없이 즉시 표시&lt;/b&gt;됩니다. 이는 페이지의 로딩 속도를 빠르게 느끼게 하여 &lt;b&gt;사용자 만족도를 크게 향상&lt;/b&gt;시킵니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;페이지 반응성 증가&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;중요한 요소들을 미리 로드하여, 사용자가 상호작용할 때 &lt;b&gt;빠른 응답성&lt;/b&gt;을 제공합니다. 특히 동적 콘텐츠가 많을 경우 사전 로딩은 큰 이점을 제공합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;네트워크 병목 최소화&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;사용자가 페이지를 처음 방문할 때 주요 리소스를 미리 불러와, &lt;b&gt;네트워크 병목&lt;/b&gt;을 줄일 수 있습니다. 예를 들어, 모달을 열 때 이미 로드된 이미지가 즉시 표시되어 네트워크 요청으로 인한 대기 시간이 없어집니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;이미지 사전 로딩의 단점&lt;/b&gt;&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;불필요한 리소스 낭비&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;사전 로딩된 이미지나 컴포넌트가 실제로 사용되지 않으면, &lt;b&gt;네트워크 자원과 메모리&lt;/b&gt;가 낭비됩니다. 사용자가 해당 콘텐츠를 보지 않는다면, 불필요하게 데이터를 다운로드한 것이 됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;초기 로딩 속도 저하&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;사전 로딩할 리소스가 많으면 &lt;b&gt;초기 로딩 시간이 길어질 수&lt;/b&gt; 있습니다. 페이지가 보이지 않는 상태에서 백그라운드로 여러 자원을 로드하기 때문에 네트워크 부하가 발생할 수 있습니다. 특히, &lt;b&gt;저사양 장치&lt;/b&gt;나 &lt;b&gt;느린 네트워크 환경&lt;/b&gt;에서는 사전 로딩이 과도하면 성능 저하로 이어질 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;캐시 문제&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이미지를 사전 로드해도 브라우저가 이를 &lt;b&gt;캐시하지 않거나 캐시 정책이 잘못 설정&lt;/b&gt;되면, 나중에 다시 이미지를 로드해야 할 수 있습니다. 이로 인해 사전 로딩의 장점을 충분히 활용하지 못할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;모바일 환경에서 데이터 사용 증가&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;사전 로딩은 &lt;b&gt;모바일 데이터 사용량&lt;/b&gt;을 증가시킬 수 있습니다. 특히 사용자가 보지 않을 리소스를 미리 로드하면 &lt;b&gt;데이터 소모가 많아지며&lt;/b&gt;, 사용자에게 불편을 줄 수 있습니다. &lt;b&gt;데이터 요금제&lt;/b&gt;에 민감한 사용자들에게는 특히 문제가 될 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;7. &lt;b&gt;애니메이션 최적화&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;애니메이션 최적화를 제대로 적용하려면, 먼저 &lt;b&gt;브라우저 렌더링 과정&lt;/b&gt;에 대한 기본적인 이해가 필요합니다. 브라우저는 다음과 같은 단계를 통해 화면을 렌더링합니다:&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;DOM + CSSOM&lt;/b&gt; (HTML과 CSS 분석)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;렌더 트리&lt;/b&gt; (렌더링에 필요한 요소들만 추려서 생성)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;레이아웃&lt;/b&gt; (화면에 배치될 위치 계산)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;페인트&lt;/b&gt; (각 요소들을 화면에 그리기)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;컴포지트&lt;/b&gt; (최종적으로 화면에 렌더링)&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;애니메이션 작업은 이 &lt;b&gt;렌더링 경로 중 일부를 다시 실행하면서 발생하는데, 이를 &lt;span style=&quot;color: #ee2323;&quot;&gt;리플로우(Reflow)&lt;/span&gt; 또는 &lt;span style=&quot;color: #ee2323;&quot;&gt;리페인트(Repaint)&lt;/span&gt;&lt;/b&gt;라고 합니다. 특히 &lt;b&gt;width, height, color와 같은 속성 변경&lt;/b&gt;은 &lt;b&gt;리플로우나 리페인트를 유발하여 성능 저하&lt;/b&gt;를 초래할 수 있습니다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;하드웨어 가속(GPU 가속) 적용하기&lt;/b&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;하드웨어 가속을 사용하면 &lt;b&gt;CPU가 처리하는 레이아웃과 페인트 단계를 생략&lt;/b&gt;하고, GPU가 &lt;b&gt;transform과 opacity 속성을 처리할 수 있습니다&lt;/b&gt;. 이를 통해 애니메이션 성능을 크게 향상시킬 수 있습니다. &lt;br /&gt;애니메이션 성능을 높이기 위해 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;transform이나 opacity&amp;nbsp;속성을 사용해 GPU에 위임하는 방법이 더 효율적&lt;/b&gt;&lt;/span&gt;입니다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;그러면 애니메이션 최적화를 시작해볼까요 (참고로 styled-component를 사용중입니다. )&lt;/h4&gt;
&lt;div style=&quot;background-color: #263238; color: #eeffff;&quot;&gt;
&lt;div&gt;&lt;span style=&quot;color: #c792ea;&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt;BarGraph&lt;/span&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt;styled&lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color: #c3e88d;&quot;&gt;`&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #b2ccd6;&quot;&gt;position&lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt; absolute&lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #b2ccd6;&quot;&gt;left&lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #f78c6c;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #b2ccd6;&quot;&gt;top&lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #f78c6c;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #b2ccd6;&quot;&gt;width&lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;${&lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;({&lt;/span&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt;width&lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;})&lt;/span&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #c792ea;&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt;width&lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt;%&lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #b2ccd6;&quot;&gt;transition&lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #b2ccd6;&quot;&gt;width&lt;/span&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #f78c6c;&quot;&gt;1.5s&lt;/span&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt; ease&lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #b2ccd6;&quot;&gt;height&lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #f78c6c;&quot;&gt;100%&lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #b2ccd6;&quot;&gt;background&lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;${&lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;({&lt;/span&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt;isSelected&lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;})&lt;/span&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #c792ea;&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt;isSelected&lt;/span&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;?&lt;/span&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;'&lt;/span&gt;&lt;span style=&quot;color: #c3e88d;&quot;&gt;rgba(126, 198, 81, 0.7)&lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;'&lt;/span&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;'&lt;/span&gt;&lt;span style=&quot;color: #c3e88d;&quot;&gt;rgb(198, 198, 198)&lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;'&lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;};&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #b2ccd6;&quot;&gt;z-index&lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #f78c6c;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #c3e88d;&quot;&gt;`&lt;/span&gt;&lt;span style=&quot;color: #c3e88d;&quot;&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하드웨어 가속을 적용하면 다음과 같이 &lt;b&gt;transform&lt;/b&gt; 속성을 사용하여 애니메이션을 GPU에서 처리할 수 있습니다:&lt;/p&gt;
&lt;div style=&quot;background-color: #263238; color: #eeffff;&quot;&gt;
&lt;div&gt;&lt;span style=&quot;color: #c792ea;&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt;BarGraph&lt;/span&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt;styled&lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt;div&lt;/span&gt;&lt;span style=&quot;color: #c3e88d;&quot;&gt;`&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #b2ccd6;&quot;&gt;position&lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt; absolute&lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #b2ccd6;&quot;&gt;left&lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #f78c6c;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #b2ccd6;&quot;&gt;top&lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #f78c6c;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #b2ccd6;&quot;&gt;width&lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #f78c6c;&quot;&gt;100%&lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #b2ccd6;&quot;&gt;transform&lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #82aaff;&quot;&gt;scaleX&lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt;${&lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt;{ &lt;/span&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt;width&lt;/span&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt; }&lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt; =&amp;gt; &lt;/span&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt;width&lt;/span&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt; / &lt;/span&gt;&lt;span style=&quot;color: #f78c6c;&quot;&gt;100&lt;/span&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;);&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #b2ccd6;&quot;&gt;transform-origin&lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt; center left&lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #b2ccd6;&quot;&gt;transition&lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #b2ccd6;&quot;&gt;transform&lt;/span&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #f78c6c;&quot;&gt;1.5s&lt;/span&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt; ease&lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #b2ccd6;&quot;&gt;height&lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #f78c6c;&quot;&gt;100%&lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #b2ccd6;&quot;&gt;background&lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;${&lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;({&lt;/span&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt;isSelected&lt;/span&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;})&lt;/span&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #c792ea;&quot;&gt;=&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt;isSelected&lt;/span&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;?&lt;/span&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color: #c3e88d;&quot;&gt;rgba(126, 198, 81, 0.7)&lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color: #c3e88d;&quot;&gt;rgb(198, 198, 198)&lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;};&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #b2ccd6;&quot;&gt;z-index&lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color: #eeffff;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #f78c6c;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;&lt;span style=&quot;color: #c3e88d;&quot;&gt;`&lt;/span&gt;&lt;span style=&quot;color: #89ddff;&quot;&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 코드에서는 &lt;b&gt;width&lt;/b&gt; 대신 &lt;b&gt;transform: scaleX()&lt;/b&gt; 속성을 사용하여 애니메이션을 적용합니다. 이 방식은 GPU를 사용해 &lt;b&gt;레이아웃&lt;/b&gt;과 &lt;b&gt;페인트&lt;/b&gt; 단계를 생략하고, &lt;b&gt;더 나은 성능&lt;/b&gt;을 제공합니다.&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;실제로 퍼포먼스를 측정하면, 작업 속도가 빨라진 것을 확인할 수 있습니다. 하드웨어 가속은 렌더링 속도를 높이고, CPU 부하를 줄여 &lt;b&gt;부드러운 애니메이션&lt;/b&gt;을 구현할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;다음 장에서 다룰 최적화 기법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;애니메이션 최적화 외에도 여러 가지 성능 최적화 기법이 있습니다. 다음 장에서는 아래와 같은 &lt;b&gt;다양한 최적화 기법&lt;/b&gt;을 소개할 예정입니다:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;이미지 지연 로딩 (Lazy Loading)&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;이미지 사이즈 최적화&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;폰트 최적화&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;캐시 최적화&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;불필요한 CSS 제거&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Front-End</category>
      <author>dobbyyo</author>
      <guid isPermaLink="true">https://dobbyyo.tistory.com/17</guid>
      <comments>https://dobbyyo.tistory.com/entry/%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C-%EC%84%B1%EB%8A%A5-%EC%B5%9C%EC%A0%81%ED%99%94-2%ED%8E%B8-%EC%95%A0%EB%8B%88%EB%A9%94%EC%9D%B4%EC%85%98-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8%EC%A7%80%EC%97%B0%EC%82%AC%EC%A0%84%EB%A1%9C%EB%94%A9-%EC%9D%B4%EB%AF%B8%EC%A7%80-%EC%82%AC%EC%A0%84-%EB%A1%9C%EB%94%A9#entry17comment</comments>
      <pubDate>Mon, 30 Sep 2024 23:53:05 +0900</pubDate>
    </item>
    <item>
      <title>[PCCP 기출문제] 2번 / 석유 시추</title>
      <link>https://dobbyyo.tistory.com/entry/PCCP-%EA%B8%B0%EC%B6%9C%EB%AC%B8%EC%A0%9C-2%EB%B2%88-%EC%84%9D%EC%9C%A0-%EC%8B%9C%EC%B6%94</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;문제&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-09-30 오후 4.33.25.png&quot; data-origin-width=&quot;794&quot; data-origin-height=&quot;860&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bEhaKf/btsJSLcuqJz/RzZlgelR94viKAZJyYt6U0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bEhaKf/btsJSLcuqJz/RzZlgelR94viKAZJyYt6U0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bEhaKf/btsJSLcuqJz/RzZlgelR94viKAZJyYt6U0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbEhaKf%2FbtsJSLcuqJz%2FRzZlgelR94viKAZJyYt6U0%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;794&quot; height=&quot;860&quot; data-filename=&quot;스크린샷 2024-09-30 오후 4.33.25.png&quot; data-origin-width=&quot;794&quot; data-origin-height=&quot;860&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-09-30 오후 4.33.37.png&quot; data-origin-width=&quot;778&quot; data-origin-height=&quot;998&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/PephB/btsJRcWYbmv/2ObVcgML8kPYvKSA1YuQPk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/PephB/btsJRcWYbmv/2ObVcgML8kPYvKSA1YuQPk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/PephB/btsJRcWYbmv/2ObVcgML8kPYvKSA1YuQPk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FPephB%2FbtsJRcWYbmv%2F2ObVcgML8kPYvKSA1YuQPk%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;778&quot; height=&quot;998&quot; data-filename=&quot;스크린샷 2024-09-30 오후 4.33.37.png&quot; data-origin-width=&quot;778&quot; data-origin-height=&quot;998&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;h3 data-ke-size=&quot;size23&quot;&gt;문제 파악&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. &lt;b&gt;연결된 석유 덩어리 탐색&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;문제의 본질은 2차원 배열에서 상하좌우로 연결된 &lt;b&gt;석유 덩어리&lt;/b&gt;(1로 표시된 부분)를 찾아내는 것입니다. 이 덩어리들의 크기를 계산하고, 각 열에 시추관을 설치했을 때 얻을 수 있는 석유량을 파악하는 것이 핵심입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. &lt;b&gt;DFS 또는 BFS를 이용한 탐색&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;DFS(깊이 우선 탐색)&lt;/b&gt; 또는 &lt;b&gt;BFS(너비 우선 탐색)&lt;/b&gt;을 사용하여 2차원 배열에서 서로 연결된 석유 덩어리를 탐색합니다. 이 과정에서 이미 방문한 곳은 다시 탐색하지 않도록 방문 처리를 해야 합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. &lt;b&gt;열별로 석유 덩어리 합산&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;각 열에 시추관을 설치했을 때, 그 열을 통과하는 석유 덩어리들의 크기를 합산해야 합니다. 이를 위해 각 덩어리가 포함된 열 정보를 저장하고, 열별로 석유량을 계산하는 과정이 필요합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. &lt;b&gt;중복 탐색 방지 및 효율성 개선&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이미 탐색된 석유 덩어리를 다시 계산하지 않도록 &lt;b&gt;visited 배열&lt;/b&gt;을 통해 방문 여부를 기록합니다.&lt;/li&gt;
&lt;li&gt;각 열에 대해 중복 연산을 최소화하는 방식으로 석유량을 계산하여 효율성을 높이는 것이 중요합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;코드&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1727682115296&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function dfs(land, visited, x, y) {
  const directions = [
    [0, 1],
    [1, 0],
    [0, -1],
    [-1, 0],
  ];

  const stack = [[x, y]]; // 스택을 사용하여 탐색
  visited[x][y] = true;

  console.log(stack);
  console.log(visited);

  let size = 1;
  let cols = new Set(); // 총 오일 집합? 열을 기록할 집합
  cols.add(y); // 현재 위치의 열 추가

  // 스택을 이용한 DFS 탐색
  while (stack.length &amp;gt; 0) {
    const [x, y] = stack.pop();

    for (let [dx, dy] of directions) {
      let nx = x + dx;
      let ny = y + dy;

      if (nx &amp;gt;= 0 &amp;amp;&amp;amp; ny &amp;gt;= 0 &amp;amp;&amp;amp; nx &amp;lt; land.length &amp;amp;&amp;amp; ny &amp;lt; land[0].length &amp;amp;&amp;amp; !visited[nx][ny] &amp;amp;&amp;amp; land[nx][ny] === 1) {
        visited[nx][ny] = true;
        stack.push([nx, ny]);
        size += 1;
        cols.add(ny); // 열 추가
      }
    }
  }

  return [size, cols]; // 덩어리의 크기와 포함된 열 반환
}

function solution(land) {
  let answer = 0;
  let visited = Array.from({ length: land.length }, () =&amp;gt; Array(land[0].length).fill(false));

  let clusters = [];

  // 전체 배열 탐색하며 석유 덩어리 크기 계산
  for (let i = 0; i &amp;lt; land.length; i++) {
    for (let j = 0; j &amp;lt; land[0].length; j++) {
      if (land[i][j] === 1 &amp;amp;&amp;amp; !visited[i][j]) {
        let [size, cols] = dfs(land, visited, i, j); // 새로운 덩어리 발견 시 DFS 실행
        clusters.push({ size, cols }); // 각 덩어리의 크기와 열 정보 저장
      }
    }
  }

  for (let col = 0; col &amp;lt; land[0].length; col++) {
    let totalOil = 0;

    clusters.forEach(({ size, cols }) =&amp;gt; {
      if (cols.has(col)) {
        totalOil += size;
      }
    });
    answer = Math.max(answer, totalOil);
  }

  return answer;
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Algorithm</category>
      <author>dobbyyo</author>
      <guid isPermaLink="true">https://dobbyyo.tistory.com/16</guid>
      <comments>https://dobbyyo.tistory.com/entry/PCCP-%EA%B8%B0%EC%B6%9C%EB%AC%B8%EC%A0%9C-2%EB%B2%88-%EC%84%9D%EC%9C%A0-%EC%8B%9C%EC%B6%94#entry16comment</comments>
      <pubDate>Mon, 30 Sep 2024 18:30:06 +0900</pubDate>
    </item>
    <item>
      <title>PCCP 기출문제 3번 / 출동위험 찾기</title>
      <link>https://dobbyyo.tistory.com/entry/PCCP-%EA%B8%B0%EC%B6%9C%EB%AC%B8%EC%A0%9C-3%EB%B2%88-%EC%B6%9C%EB%8F%99%EC%9C%84%ED%97%98-%EC%B0%BE%EA%B8%B0</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;문제&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-09-23 오후 11.51.19.png&quot; data-origin-width=&quot;1072&quot; data-origin-height=&quot;1102&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Zs1TK/btsJIrfVmOy/PdS1Z2Z3M29fNomfLkMIJ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Zs1TK/btsJIrfVmOy/PdS1Z2Z3M29fNomfLkMIJ0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Zs1TK/btsJIrfVmOy/PdS1Z2Z3M29fNomfLkMIJ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZs1TK%2FbtsJIrfVmOy%2FPdS1Z2Z3M29fNomfLkMIJ0%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;1072&quot; height=&quot;1102&quot; data-filename=&quot;스크린샷 2024-09-23 오후 11.51.19.png&quot; data-origin-width=&quot;1072&quot; data-origin-height=&quot;1102&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;h3 data-ke-size=&quot;size23&quot;&gt;문제 핵심 파악&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. 로봇의 이동 경로 시뮬레이션:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;로봇은 주어진 경로를 따라 이동하며, 항상 최단 경로로 이동해야 합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;이동 시 r 좌표를 먼저 맞추고, 이후 c 좌표를 맞추는 규칙&lt;/span&gt;&lt;/b&gt;을 따릅니다. 이는 일관된 최단 경로를 유지하기 위한 중요한 규칙입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. 시간과 위치의 정확한 추적:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;모든 로봇은 동시에 출발하여 매초 r 또는 c 좌표를 1씩 이동합니다. 따라서 각 로봇의 이동 중 시간과 위치를 정확하게 추적해야 합니다.&lt;/li&gt;
&lt;li&gt;Map이나 객체를 사용해 각 시간대별로 특정 위치에 방문한 로봇의 수를 기록하는 것이 중요합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. 충돌 상황 감지:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;여러 로봇이 같은 시간대에 동일한 위치에 도달할 경우, 중복된 충돌로 여러 번 계산되지 않도록 주의해야 합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;4. 시작 위치에서의 충돌 포함:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;각 로봇의 시작 위치에서도 충돌이 발생할 수 있으므로, 로봇이 경로를 이동하기 전에 첫 위치에서의 충돌 가능성도 고려해야 합니다.&lt;/li&gt;
&lt;/ul&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;/h3&gt;
&lt;pre id=&quot;code_1727104160605&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function solution(points, routes) {
  let timeMap = new Map(); // 각 시간대(한번 이동 시 +1) 에 각 좌표를 방문한 로봇 수를 기록하기 위한 맵

  // 각 로봇의 경로를 시뮬레이션
  for (let robot of routes) {
    let [currentR, currentC] = points[robot[0] - 1]; // 첫 번째 포인트에서 시작
    let time = 0;

    // 시작 위치도 충돌 가능성에 포함하기 위해 기록
    const startKey = `${time}-${currentR}-${currentC}`;

    if (!timeMap.has(startKey)) {
      timeMap.set(startKey, 0);
    }
    timeMap.set(startKey, timeMap.get(startKey) + 1);

    // 각 로봇의 경로를 순차적으로 방문
    for (let i = 1; i &amp;lt; robot.length; i++) {
      let [targetR, targetC] = points[robot[i] - 1]; // 목표 포인트의 좌표를 설정

      // 로봇이 목표 지점에 도달할 때까지 반복적으로 이동
      while (currentR !== targetR || currentC !== targetC) {
        if (currentR !== targetR) {
          currentR += targetR &amp;gt; currentR ? 1 : -1; // r 좌표를 먼저 맞춤
        } else if (currentC !== targetC) {
          currentC += targetC &amp;gt; currentC ? 1 : -1; // c 좌표를 맞춤
        }

        time++; // 시간 증가
        const key = `${time}-${currentR}-${currentC}`; // 시간과 좌표를 결합한 키 생성

        // 해당 시간과 좌표에 방문한 로봇 수 기록
        if (!timeMap.has(key)) {
          timeMap.set(key, 0);
        }
        timeMap.set(key, timeMap.get(key) + 1);
      }
    }
  }

  // 충돌 횟수 계산
  let collisionCount = 0;
  for (let count of timeMap.values()) {
    if (count &amp;gt; 1) {
      collisionCount++;
    }
  }

  return collisionCount;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Algorithm</category>
      <author>dobbyyo</author>
      <guid isPermaLink="true">https://dobbyyo.tistory.com/15</guid>
      <comments>https://dobbyyo.tistory.com/entry/PCCP-%EA%B8%B0%EC%B6%9C%EB%AC%B8%EC%A0%9C-3%EB%B2%88-%EC%B6%9C%EB%8F%99%EC%9C%84%ED%97%98-%EC%B0%BE%EA%B8%B0#entry15comment</comments>
      <pubDate>Tue, 24 Sep 2024 00:09:55 +0900</pubDate>
    </item>
    <item>
      <title>PCCP 기출문제 2번 / 퍼즐 게임 챌린지</title>
      <link>https://dobbyyo.tistory.com/entry/PCCP-%EA%B8%B0%EC%B6%9C%EB%AC%B8%EC%A0%9C-2%EB%B2%88-%ED%8D%BC%EC%A6%90-%EA%B2%8C%EC%9E%84-%EC%B1%8C%EB%A6%B0%EC%A7%80</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;문제&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;URL: &lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/340212&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://school.programmers.co.kr/learn/courses/30/lessons/340212&lt;/a&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-09-19 오후 4.35.41.png&quot; data-origin-width=&quot;1244&quot; data-origin-height=&quot;894&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eMGGUP/btsJGyYViF7/etMkRjLKqHIc18mgabpSL0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eMGGUP/btsJGyYViF7/etMkRjLKqHIc18mgabpSL0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eMGGUP/btsJGyYViF7/etMkRjLKqHIc18mgabpSL0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeMGGUP%2FbtsJGyYViF7%2FetMkRjLKqHIc18mgabpSL0%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;1244&quot; height=&quot;894&quot; data-filename=&quot;스크린샷 2024-09-19 오후 4.35.41.png&quot; data-origin-width=&quot;1244&quot; data-origin-height=&quot;894&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&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;JavaScript에서 &lt;span style=&quot;color: #ee2323;&quot;&gt;Math.max와 스프레드 연산자로 인한 런타임 에러 해결&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드를 작성하던 중, 채점 과정에서 15번부터 20번까지 런타임 에러가 발생하는 문제를 겪었습니다. 문제는 아래 코드에서 발생했습니다:&lt;/p&gt;
&lt;div style=&quot;background-color: #263238; color: #eeffff;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1726731286491&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;let left = 1;
let right = Math.max(...diffs);

let mid = Math.floor((left + right) / 2); // 중간값 설정&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;위 코드는 Math.max(...diffs) 부분에서 에러를 유발합니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;스프레드 연산자&lt;/b&gt;는 배열을 개별 요소로 분해하여 호출 스택에 올리는데, 배열의 길이가 매우 길 경우 JavaScript 호출 &lt;span style=&quot;color: #ee2323;&quot;&gt;스택의 한계를 초과하여 런타임 에러가&lt;/span&gt; 발생할 수 있습니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;해결 방법: &lt;span style=&quot;color: #ee2323;&quot;&gt;reduce()로 최대값&lt;/span&gt; 찾기&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 문제를 해결하기 위해 스프레드 연산자 대신 &lt;b&gt;reduce()&lt;/b&gt; 메서드를 활용하여 배열의 최대값을 구했습니다. reduce()는 호출 스택에 배열을 모두 분해하지 않고 순차적으로 최대값을 계산하기 때문에 훨씬 안전합니다. 다음과 같이 변경하였습니다:&lt;/p&gt;
&lt;div style=&quot;background-color: #263238; color: #eeffff;&quot;&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1726731256252&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;let right = diffs.reduce((acc, cur) =&amp;gt; Math.max(acc, cur), -Infinity); // 최대값 찾기&lt;/code&gt;&lt;/pre&gt;
&lt;span style=&quot;color: #c792ea;&quot;&gt;&lt;/span&gt;&lt;span style=&quot;color: #11dfbc;&quot;&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 방식으로 배열의 최대값을 안전하게 구할 수 있었으며, 런타임 에러 없이 코드가 정상적으로 작동함을 확인할 수 있었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;/h3&gt;
&lt;pre id=&quot;code_1726731230591&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 난이도 diff
// 현재 퍼즐의 소요시간 time_cur
// 이전 퍼즐의 소요 시간 time_prev
// 숙련도 level

// diff &amp;le; level이면 퍼즐을 틀리지 않고 time_cur만큼의 시간을 사용하여 해결합니다.
// diff &amp;gt; level이면, 퍼즐을 총 diff - level번 틀립니다. 퍼즐을 틀릴 때마다,
// time_cur만큼의 시간을 사용하며, 추가로 time_prev만큼의 시간을 사용해 이전 퍼즐을 다시 풀고 와야 합니다.
// 이전 퍼즐을 다시 풀 때는 이전 퍼즐의 난이도에 상관없이 틀리지 않습니다.
// diff - level번 틀린 이후에 다시 퍼즐을 풀면 time_cur만큼의 시간을 사용하여 퍼즐을 해결합니다.

function isPossible(level, diffs, times, limit) {
  let totalTime = 0; // 푸는데 총 걸린 시간
  let previousTime = 0; // 이전 문제 푸는데 걸린 시간

  for (let i = 0; i &amp;lt; diffs.length; i++) {
    const curTime = times[i];
    // 레벨이 낮은경우
    if (diffs[i] &amp;gt; level) {
      const diff = diffs[i] - level;
      totalTime += diff * (curTime + previousTime) + curTime;
    } else if (diffs[i] &amp;lt;= level) {
      // 레벨이 같거나 큰 경우
      totalTime += curTime;
    }

    previousTime = curTime;

    // totalTime이 limit보다 큰경우 false 반환
    if (totalTime &amp;gt; limit) {
      return false;
    }
  }

  return true;
}

function solution(diffs, times, limit) {
  let left = 1;
  // let right = Math.max(...diffs);
  let right = diffs.reduce((acc, cur) =&amp;gt; Math.max(acc, cur), -Infinity); // 최대값 찾기

  // 이분 탐색 시작
  while (left &amp;lt;= right) {
    let mid = Math.floor((left + right) / 2); // 중간값 설정
    if (isPossible(mid, diffs, times, limit)) {
      right = mid - 1;
    } else {
      left = mid + 1;
    }
  }

  return left;
}

console.log(solution([1, 5, 3], [2, 4, 7], 30)); //3
console.log(solution([1, 4, 4, 2], [6, 3, 8, 2], 59)); //2
console.log(solution([1, 328, 467, 209, 54], [2, 7, 1, 4, 3], 1723)); //294
console.log(solution([1, 99999, 100000, 99995], [9999, 9001, 9999, 9001], 3456789012)); //39354&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;background-color: #263238; color: #eeffff;&quot;&gt;&amp;nbsp;&lt;/div&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>
      <author>dobbyyo</author>
      <guid isPermaLink="true">https://dobbyyo.tistory.com/14</guid>
      <comments>https://dobbyyo.tistory.com/entry/PCCP-%EA%B8%B0%EC%B6%9C%EB%AC%B8%EC%A0%9C-2%EB%B2%88-%ED%8D%BC%EC%A6%90-%EA%B2%8C%EC%9E%84-%EC%B1%8C%EB%A6%B0%EC%A7%80#entry14comment</comments>
      <pubDate>Thu, 19 Sep 2024 16:41:04 +0900</pubDate>
    </item>
    <item>
      <title>프론트엔드 성능 최적화 1편 - 최적화는 왜 필요할까? 웹 성능 분석</title>
      <link>https://dobbyyo.tistory.com/entry/%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C-%EC%84%B1%EB%8A%A5-%EC%B5%9C%EC%A0%81%ED%99%94-1%ED%8E%B8-%EC%B5%9C%EC%A0%81%ED%99%94%EB%8A%94-%EC%99%9C-%ED%95%84%EC%9A%94%ED%95%A0%EA%B9%8C-%EC%9B%B9-%EC%84%B1%EB%8A%A5-%EB%B6%84%EC%84%9D</link>
      <description>&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1. 프론트엔드 성능 최적화는 왜 필요할까?&lt;/b&gt;&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;웹 페이지의 성능은 사용자 경험에 큰 영향을 미칩니다. 특히&amp;nbsp;&lt;b&gt;페이지 표시 시간&lt;/b&gt;이 증가하면 사용자 이탈률이 급격히 증가하게 됩니다. 예를 들어:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;페이지 표시 시간이 1초에서 3초로 느려질 경우&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;이탈률이&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;32%&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;증가&lt;/li&gt;
&lt;li&gt;&lt;b&gt;1초에서 5초로 느려질 경우&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;이탈률이&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;90%&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;증가&lt;/li&gt;
&lt;li&gt;&lt;b&gt;1초에서 6초로 느려질 경우&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;이탈률이&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;106%&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;증가&lt;/li&gt;
&lt;li&gt;&lt;b&gt;1초에서 10초로 느려질 경우&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;이탈률이&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;123%&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;증가&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이처럼 페이지 로딩 속도는 사용자 유지에 매우 중요한 요소입니다.&amp;nbsp;&lt;b&gt;많은 사용자를 유입&lt;/b&gt;하고&amp;nbsp;&lt;b&gt;이탈률을 줄이기 위해&lt;/b&gt;&amp;nbsp;프론트엔드 성능 최적화는 필수적입니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;2. 성능 최적화는 어떻게 이루어질까?&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;프론트엔드 성능은 크게 두 가지로 나눌 수 있습니다:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;로딩 성능&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;렌더링 성능&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- 로딩 성능:&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;로딩 성능은&amp;nbsp;&lt;b&gt;웹페이지의 HTML, CSS, JavaScript 파일의 크기&lt;/b&gt;와&amp;nbsp;&lt;b&gt;서버 응답 시간&lt;/b&gt;에 따라 결정됩니다. 파일 크기가 클수록 첫 화면을 표시하는 데 시간이 더 걸립니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- 렌더링 성능:&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;렌더링 성능은 브라우저가&amp;nbsp;&lt;b&gt;HTML, CSS, JavaScript를 해석&lt;/b&gt;해 화면을 구성하는 속도를 의미합니다.&amp;nbsp;&lt;b&gt;DOM 구조&lt;/b&gt;가 복잡하거나 코드가 최적화되지 않았을 경우 성능이 저하될 수 있습니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;최적화를 통해 이 두 가지 성능 요소를 개선하면 사용자는 더 빠르고 매끄러운 웹 경험을 할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-09-12 오후 11.56.33.png&quot; data-origin-width=&quot;1006&quot; data-origin-height=&quot;509&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/opmh7/btsJzOpe64t/KnXPjb9ezOG0HNoReykqc1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/opmh7/btsJzOpe64t/KnXPjb9ezOG0HNoReykqc1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/opmh7/btsJzOpe64t/KnXPjb9ezOG0HNoReykqc1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fopmh7%2FbtsJzOpe64t%2FKnXPjb9ezOG0HNoReykqc1%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;1006&quot; height=&quot;509&quot; data-filename=&quot;스크린샷 2024-09-12 오후 11.56.33.png&quot; data-origin-width=&quot;1006&quot; data-origin-height=&quot;509&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div data-message-author-role=&quot;assistant&quot; data-message-id=&quot;0d75f095-3415-43f4-8b65-01e07442e4a8&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;3. 최적화를 위한 분석 도구 및 방법&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 다양한&amp;nbsp;&lt;b&gt;성능 최적화&lt;/b&gt;&amp;nbsp;방법을 살펴보겠습니다. 아래 도구들을 통해 현재 성능 문제를 분석하고 개선할 수 있습니다:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Lighthouse 패널&lt;/b&gt;: 웹사이트의 성능을 측정하고, 개선이 필요한 부분을 구체적으로 제안해 주는 도구입니다. 성능, 접근성, SEO 등 다양한 측면을 종합적으로 평가합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;크롬 개발자 도구 Performance 패널&lt;/b&gt;: 페이지가 로드될 때 실행되는 모든 작업을 시각적으로 확인할 수 있습니다. 이를 통해 어떤 JavaScript 코드가 느린지 분석할 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Network 패널&lt;/b&gt;: 네트워크 요청이 어떻게 이루어지는지 분석할 수 있으며, 대기 시간, 리소스 크기 등을 확인해 페이지 로딩 성능을 개선할 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Webpack-bundle-analyzer&lt;/b&gt;: 번들 파일을 분석하여 불필요하게 큰 모듈이나 중복된 라이브러리를 찾아 제거할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;4. Lighthouse&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;툴을 이용한 페이지 검사&lt;/h3&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-09-13 오후 3.38.22.png&quot; data-origin-width=&quot;1432&quot; data-origin-height=&quot;318&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dNQlSq/btsJBs7hAWV/AZDAocsyUM5LI1LwMsET0K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dNQlSq/btsJBs7hAWV/AZDAocsyUM5LI1LwMsET0K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dNQlSq/btsJBs7hAWV/AZDAocsyUM5LI1LwMsET0K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdNQlSq%2FbtsJBs7hAWV%2FAZDAocsyUM5LI1LwMsET0K%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;1432&quot; height=&quot;318&quot; data-filename=&quot;스크린샷 2024-09-13 오후 3.38.22.png&quot; data-origin-width=&quot;1432&quot; data-origin-height=&quot;318&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;Mode (모드):&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Navigation (Default)&lt;/b&gt;: 웹 페이지를 새로 고침하여 전체 로딩 과정을 분석합니다. 성능, 접근성, 모범 사례, SEO 등을 종합적으로 평가하며 가장 일반적으로 사용되는 모드입니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Timespan&lt;/b&gt;: 특정 시간 동안 발생하는 이벤트를 기록하여 그 구간 동안의 성능을 분석합니다. 동적 페이지나 애니메이션이 많은 웹사이트를 평가할 때 유용합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Snapshot&lt;/b&gt;: 현재 페이지 상태를 그대로 스냅샷 찍어 분석합니다. 페이지가 이미 로드된 후에도 성능 상태를 빠르게 평가할 수 있는 간단한 분석 방법입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;Device (장치):&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Mobile&lt;/b&gt;: 모바일 환경에서의 웹 페이지 성능을 분석합니다. 실제 모바일 기기 환경을 모방해 로딩 시간, 반응성, 레이아웃 이동 등을 평가합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Desktop&lt;/b&gt;: 데스크톱 환경에서의 웹 페이지 성능을 분석합니다. 데스크톱 브라우저 기준으로 성능을 평가하며, 데스크톱 사용자 경험을 개선하는 데 초점을 맞춥니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;Categories (카테고리):&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Performance (성능)&lt;/b&gt;: 웹 페이지의 로딩 속도와 전반적인 성능을 평가합니다. 주요 지표로는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;First Contentful Paint (FCP)&lt;/b&gt;,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;Largest Contentful Paint (LCP)&lt;/b&gt;,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;Cumulative Layout Shift (CLS)&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;등이 있으며, 페이지가 얼마나 빠르게 사용자에게 콘텐츠를 보여주는지와 그 안정성을 평가합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Accessibility (접근성)&lt;/b&gt;: 다양한 사용자, 특히 장애가 있는 사용자가 페이지를 쉽게 이용할 수 있는지 평가합니다. 색상 대비, 폰트 크기, 이미지 대체 텍스트 등 다양한 접근성 요소를 점검합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Best Practices (모범 사례)&lt;/b&gt;: 보안 및 성능에 관한 웹 개발 모범 사례를 따르고 있는지 확인합니다. 예를 들어,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;HTTPS&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;사용 여부, 안전한 리소스 로드, 최신 웹 기술을 사용하는지 등을 평가합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;SEO (검색 엔진 최적화)&lt;/b&gt;: 검색 엔진이 웹 페이지를 잘 인식할 수 있는지를 평가합니다. 적절한 메타 태그, 제목 구조, URL 최적화, 콘텐츠 구성이 검색 엔진에서 잘 노출될 수 있도록 설계되었는지 점검합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;anlaze 버튼 클릭 후 결과 페이지를 한번 봐보자&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-09-13 오후 3.42.41.png&quot; data-origin-width=&quot;718&quot; data-origin-height=&quot;629&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ZGYj5/btsJCES6p08/hpiSHe4GiRWiwOgn2vgmv1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ZGYj5/btsJCES6p08/hpiSHe4GiRWiwOgn2vgmv1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ZGYj5/btsJCES6p08/hpiSHe4GiRWiwOgn2vgmv1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZGYj5%2FbtsJCES6p08%2FhpiSHe4GiRWiwOgn2vgmv1%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;718&quot; height=&quot;629&quot; data-filename=&quot;스크린샷 2024-09-13 오후 3.42.41.png&quot; data-origin-width=&quot;718&quot; data-origin-height=&quot;629&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;Metrics (세부 성능 지표)&lt;/h3&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;1.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;First Contentful Paint (FCP)&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;FCP&lt;/b&gt;는 페이지에서&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;처음으로 텍스트나 이미지 같은 콘텐츠가 화면에 표시되는 시점&lt;/b&gt;을 측정합니다. 이는 사용자가 페이지가 로드되기 시작했다고 인식하는 순간으로,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;FCP가 빠를수록 사용자 경험이 개선&lt;/b&gt;됩니다. 일반적으로 FCP가&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;1.1초&lt;/b&gt;면, 첫 번째 콘텐츠가 빠르게 나타난다는 것을 의미합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;2.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;Largest Contentful Paint (LCP)&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;LCP&lt;/b&gt;는 페이지에서&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;가장 큰 콘텐츠(주로 이미지나 텍스트 블록)가 완전히 화면에 표시되는 시간&lt;/b&gt;을 측정합니다. 사용자가 페이지가 거의 로드되었다고 느끼는 시점으로,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;LCP가 짧을수록 페이지의 주요 콘텐츠가 더 빠르게 표시&lt;/b&gt;됩니다. 페이지의 사용자 경험을 평가할 때 중요한 지표 중 하나입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;3.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;Total Blocking Time (TBT)&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;TBT&lt;/b&gt;는 페이지가 로드되는 동안&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;메인 스레드가 차단된 총 시간&lt;/b&gt;을 나타냅니다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;차단 시간이 길수록&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;사용자가 페이지와 상호작용하기 어렵습니다. 즉, 페이지가 완전히 로드되기 전까지&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;버튼 클릭&lt;/b&gt;이나&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;스크롤&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;같은 동작이 지연될 수 있습니다. TBT를 줄이면 페이지가 더 빠르고 응답성이 좋아집니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;4.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;Speed Index&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Speed Index&lt;/b&gt;는 페이지가&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;얼마나 빠르게 시각적으로 로드되는지&lt;/b&gt;를 측정하는 지표입니다. 이 값이 낮을수록 사용자가 빠르게 콘텐츠를 볼 수 있으며,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;초기 로딩 성능&lt;/b&gt;을 개선할 때 중요한 역할을 합니다. 빠른 로딩을 통해 사용자가 페이지를 빨리 이용할 수 있게 하는 것이 목표입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;5.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;Cumulative Layout Shift (CLS)&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;CLS&lt;/b&gt;는 페이지가 로드되는 동안&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;레이아웃이 얼마나 많이 변경되는지&lt;/b&gt;를 측정합니다. 예상치 못한 레이아웃 이동은 사용자 경험에 부정적인 영향을 미치며, 버튼 클릭 시 페이지 요소가 이동하는 현상 등이 그 예입니다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;CLS 값이 낮을수록&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;페이지의 레이아웃이 안정적이고, 사용자가 불편함 없이 웹 페이지를 이용할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-09-13 오후 3.59.39.png&quot; data-origin-width=&quot;720&quot; data-origin-height=&quot;604&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cWCrNY/btsJBmMZQMx/9XdlvKoGW2m3ZHmiBFmTk0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cWCrNY/btsJBmMZQMx/9XdlvKoGW2m3ZHmiBFmTk0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cWCrNY/btsJBmMZQMx/9XdlvKoGW2m3ZHmiBFmTk0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcWCrNY%2FbtsJBmMZQMx%2F9XdlvKoGW2m3ZHmiBFmTk0%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;720&quot; height=&quot;604&quot; data-filename=&quot;스크린샷 2024-09-13 오후 3.59.39.png&quot; data-origin-width=&quot;720&quot; data-origin-height=&quot;604&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;또한 DIAGNOSTICS부분을 보고 불필요한 부분을 찾아 병목코드 최소화, 적절한 이미지 사이즈등 최적화를 적용해야한다.&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;5. Performance 패널을 활용한 성능 분석&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-09-13 오후 4.02.54.png&quot; data-origin-width=&quot;1358&quot; data-origin-height=&quot;988&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yCIZs/btsJBNwOYb8/RrTenLZXvYYMDm2Nh2Cotk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yCIZs/btsJBNwOYb8/RrTenLZXvYYMDm2Nh2Cotk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yCIZs/btsJBNwOYb8/RrTenLZXvYYMDm2Nh2Cotk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FyCIZs%2FbtsJBNwOYb8%2FRrTenLZXvYYMDm2Nh2Cotk%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;1358&quot; height=&quot;988&quot; data-filename=&quot;스크린샷 2024-09-13 오후 4.02.54.png&quot; data-origin-width=&quot;1358&quot; data-origin-height=&quot;988&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;1.&amp;nbsp;&lt;b&gt;CPU 차트&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;CPU 사용량&lt;/b&gt;을 나타내며, 페이지가 로드되는 동안 CPU가 얼마나 바쁘게 일하는지를 보여줍니다.&lt;/li&gt;
&lt;li&gt;CPU 사용률이 높으면&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;복잡한 작업&lt;/b&gt;을 수행하거나&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;무거운 스크립트&lt;/b&gt;를 실행하고 있음을 의미합니다.&lt;/li&gt;
&lt;li&gt;최적화된 웹 페이지는 CPU 사용을 최소화해&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;브라우저가 원활하게 실행&lt;/b&gt;될 수 있도록 해야 합니다. CPU 사용량이 높으면 페이지가 사용자 상호작용에&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;느리게 반응&lt;/b&gt;할 수 있으므로 성능 최적화를 통해 CPU 부하를 줄이는 것이 중요합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;2.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;Network 타임라인&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;네트워크 타임라인은 페이지 로드 중&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;네트워크 요청이 언제 발생&lt;/b&gt;하고, 각 요청이&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;얼마나 오래 걸렸는지&lt;/b&gt;를 시각적으로 보여줍니다.&lt;/li&gt;
&lt;li&gt;이를 통해&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;리소스 로드 순서&lt;/b&gt;,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;병렬 다운로드 여부&lt;/b&gt;,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;대기 시간&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;등을 확인할 수 있습니다.&lt;/li&gt;
&lt;li&gt;네트워크 타임라인을 분석하면&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;느린 로딩의 원인&lt;/b&gt;을 파악하고,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;리소스 압축&lt;/b&gt;이나&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;캐싱&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;등을 통해 성능을 개선할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;3.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;Frames (프레임)&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;프레임 차트(FPS)&lt;/b&gt;는 초당 렌더링되는 프레임 수를 나타냅니다. 페이지가 스크롤되거나 애니메이션이 실행되는 동안 프레임 속도가 얼마나 일정한지를 보여줍니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;FPS&lt;/b&gt;가 낮거나 불안정하면 페이지가 끊기거나 느리게 표시될 수 있습니다. 일반적으로&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;60프레임&lt;/b&gt;을 유지하는 것이 목표이며, FPS가 떨어지면 사용자 경험이 저하될 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;4.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;Timings (타이밍)&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;타이밍 차트는 페이지 로딩 과정에서 발생하는 주요 이벤트의&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;발생 시점&lt;/b&gt;과&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;시간 간격&lt;/b&gt;을 표시합니다.&lt;/li&gt;
&lt;li&gt;예를 들어&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;First Contentful Paint (FCP)&lt;/b&gt;,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;Largest Contentful Paint (LCP)&lt;/b&gt;,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;Time to Interactive&lt;/b&gt;와 같은 중요한 이벤트가 언제 발생했는지를 확인할 수 있습니다.&lt;/li&gt;
&lt;li&gt;이 데이터를 기반으로 페이지 로딩 성능을&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;세밀하게 분석&lt;/b&gt;하고, 각 부분을 최적화할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;5.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;Layout Shifts (레이아웃 이동)&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Layout Shifts 차트&lt;/b&gt;는 페이지 로딩 중&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;Cumulative Layout Shift (CLS)&lt;/b&gt;를 시각적으로 나타냅니다. 페이지의 요소가 갑작스럽게 이동할 때 발생하며, 사용자 경험에 부정적인 영향을 미칩니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;CLS&lt;/b&gt;가 높을수록 사용자가&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;예상치 못한 레이아웃 변경&lt;/b&gt;으로 인해 불편을 겪을 수 있습니다. CLS를 줄여 페이지의 안정성을 높이는 것이 중요합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;6.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;Main (메인 스레드)&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;메인 스레드는 브라우저가 페이지를 로드하고&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;렌더링&lt;/b&gt;하는 데 사용하는 주요 프로세스입니다. 메인 스레드가 차단되면 페이지의 다른 작업(예: 사용자 상호작용)이&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;지연&lt;/b&gt;될 수 있습니다.&lt;/li&gt;
&lt;li&gt;메인 스레드 차트는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;스레드가 얼마나 바쁘게 일하는지&lt;/b&gt;를 보여줍니다. 이를 통해 자바스크립트 실행이나 DOM 처리 중&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;병목 현상&lt;/b&gt;이 발생하는 부분을 파악할 수 있습니다. 성능 최적화를 위해 메인 스레드의 작업을 줄이는 것이 중요합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;7.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;Thread Pool (스레드 풀)&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;스레드 풀은 브라우저가 페이지 로드를 처리하기 위해&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;병렬로 여러 스레드&lt;/b&gt;를 사용하는 방식을 나타냅니다. 여러 스레드를 통해 로딩 시간을 단축할 수 있지만, 스레드가 많아지면&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;CPU 부하&lt;/b&gt;가 커질 수 있습니다.&lt;/li&gt;
&lt;li&gt;각 스레드가 어떤 작업을 수행하는지, 그리고 성능에 어떻게 기여하는지 분석해 최적화를 진행할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;8.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;GPU&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;GPU 차트&lt;/b&gt;는 페이지가 로딩될 때 &lt;b&gt;그래픽 처리 장치(GPU)&lt;/b&gt;가 얼마나 사용되는지를 나타냅니다. 주로 애니메이션이나&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;그래픽적으로 복잡한 작업&lt;/b&gt;(예: WebGL, CSS 애니메이션 등)을 처리할 때 GPU가 사용됩니다.&lt;/li&gt;
&lt;li&gt;GPU 사용이 많으면&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;그래픽 성능&lt;/b&gt;에 영향을 미치며, 최적화되지 않은 그래픽 처리로 인해 GPU에 과부하가 발생할 수 있습니다. GPU 사용량을 최소화하는 것이 부드러운 그래픽 렌더링과 성능 최적화에 중요합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-09-16 오후 10.43.42.png&quot; data-origin-width=&quot;352&quot; data-origin-height=&quot;216&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wxYIR/btsJDXkXKeo/AOMOTgROE2sofybGxAE71K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wxYIR/btsJDXkXKeo/AOMOTgROE2sofybGxAE71K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wxYIR/btsJDXkXKeo/AOMOTgROE2sofybGxAE71K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwxYIR%2FbtsJDXkXKeo%2FAOMOTgROE2sofybGxAE71K%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;352&quot; height=&quot;216&quot; data-filename=&quot;스크린샷 2024-09-16 오후 10.43.42.png&quot; data-origin-width=&quot;352&quot; data-origin-height=&quot;216&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이 이미지는&amp;nbsp;&lt;b&gt;크롬 디버거 툴&lt;/b&gt;의&amp;nbsp;&lt;b&gt;Summary&lt;/b&gt;(요약) 탭에서 성능 분석을 시각화한 도넛 차트입니다. 각 부분이 페이지 로딩 중 다양한 작업에 소요된 시간을 나타냅니다. 각각의 항목에 대한 설명은 다음과 같습니다:&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;Summary (요약)&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;각 부분이 페이지 로딩 중 다양한 작업에 소요된 시간을 나타냅니다.&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;Breakdown (세부 항목 분석)&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;Loading (파란색)&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;리소스(HTML, CSS, JavaScript 등)를 다운로드하고, 브라우저에서 초기화 작업을 하는 데 걸린 시간입니다.&lt;/li&gt;
&lt;li&gt;리소스 로딩에 시간이 거의 걸리지 않았다는 것은 네트워크 성능이 양호하거나 캐시된 리소스를 사용한 경우일 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Scripting (노란색)&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;자바스크립트 코드가 실행되는 데 걸린 시간입니다. 자바스크립트 파일의 크기나 복잡성에 따라 시간이 많이 소요될 수 있습니다.&lt;/li&gt;
&lt;li&gt;자바스크립트 코드 최적화를 고려할 필요가 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Rendering (보라색)&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;브라우저가 DOM을 구성하고 CSS 스타일을 적용하여 페이지의 시각적 구조를 만드는 데 걸린 시간입니다.&lt;/li&gt;
&lt;li&gt;페이지 렌더링에 소요된 시간은 적당한 수준이지만, 복잡한 페이지에서는 시간이 더 길어질 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Painting (초록색)&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;페이지의 픽셀을 실제로 화면에 그리는 과정입니다. 레이아웃이 완성된 후 브라우저가 내용을 화면에 그리는 작업을 의미합니다.&lt;/li&gt;
&lt;li&gt;화면에 시각적 요소를 빠르게 그리는 데 문제가 없음을 나타냅니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;System (회색)&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;시스템 레벨에서의 작업 처리에 소요된 시간입니다. 브라우저가 시스템 자원을 사용하거나 시스템이 다른 작업을 처리하는 데 사용된 시간을 의미합니다.&lt;/li&gt;
&lt;li&gt;시스템 작업에서 소모된 시간은 크지 않음을 보여줍니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Idle (검정색)&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;메인 스레드가 대기하고 있던 시간입니다. 즉, 브라우저가 아무 작업도 하지 않은 시간으로, 주로 다른 리소스를 기다리거나 로딩 후의 상태를 나타냅니다.&lt;/li&gt;
&lt;li&gt;불필요한 대기 시간을 줄이는 것이 성능 개선에 중요할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;6. webpack-bundle을 이용해서 분석 해보자&amp;nbsp;&lt;/b&gt;&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;cra-bundle-analyzer와 webpack-bundle-analyzer는 모두 번들 크기를 분석하는 도구이지만, 사용하는 환경과 설정 과정에 차이가 있습니다. 아래에서 두 도구의 차이를 설명하겠습니다.&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div data-message-author-role=&quot;assistant&quot; data-message-id=&quot;3132cbb9-baad-4928-b197-c1ed3798e3e8&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;1. cra-bundle-analyzer&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;cra-bundle-analyzer는&amp;nbsp;&lt;b&gt;Create React App (CRA)&lt;/b&gt;&amp;nbsp;프로젝트에서 사용하도록 설계된&amp;nbsp;&lt;b&gt;번들 분석 도구&lt;/b&gt;입니다.&amp;nbsp;&lt;b&gt;Webpack 설정 파일을 직접 수정할 필요 없이&lt;/b&gt;, CRA 환경에서 쉽게 번들 크기와 구조를 분석할 수 있게 만들어졌습니다. CRA는 Webpack 설정을 기본적으로 숨기기 때문에, 복잡한 설정 없이 번들 분석을 실행하고 싶을 때 유용합니다.&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;주요 특징:&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;설정 간소화&lt;/b&gt;: webpack.config.js 파일을 수정하지 않고 번들 분석을 실행할 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;제한 사항&lt;/b&gt;:&amp;nbsp;&lt;b&gt;Create React App 프로젝트&lt;/b&gt;에서만 사용할 수 있으며, Webpack 설정을 커스터마이징한 프로젝트에서는 사용할 수 없습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;단점:&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;유연성 제한&lt;/b&gt;: CRA 외의 환경에서는 사용할 수 없으며, Webpack 설정을 세부적으로 커스터마이징할 수 없는 점이 단점입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;2. webpack-bundle-analyzer&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;webpack-bundle-analyzer는&amp;nbsp;&lt;b&gt;Webpack&lt;/b&gt;에서 제공하는&amp;nbsp;&lt;b&gt;번들 분석 도구&lt;/b&gt;로, Webpack 설정 파일을 직접 수정하여 사용하는 방식입니다. Create React App뿐만 아니라,&amp;nbsp;&lt;b&gt;모든 Webpack 기반 프로젝트에서 사용 가능&lt;/b&gt;하며, 더 다양한 기능과 설정을 제공합니다.&lt;/p&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;주요 특징:&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;광범위한 사용&lt;/b&gt;:&amp;nbsp;&lt;b&gt;Webpack 기반 모든 프로젝트&lt;/b&gt;에서 사용할 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;세부 설정&lt;/b&gt;: 다양한 Webpack 설정과 함께 사용할 수 있어, 특정 청크나 모듈 단위로 분석이 가능합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;커스터마이징&lt;/b&gt;: Webpack 설정을 완전히 제어하고 커스터마이징할 수 있어, 복잡한 빌드 과정을 상세히 분석할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;장점:&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;유연성&lt;/b&gt;: Webpack 설정을 커스터마이징할 수 있어 더 다양한 프로젝트에서 유연하게 사용할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;단점:&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;설정 복잡성&lt;/b&gt;: cra-bundle-analyzer에 비해 설정 과정이 다소 복잡하며, Webpack 설정에 익숙하지 않은 개발자에게는 초기 설정이 어려울 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;요약&lt;/h3&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;대상&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;Create React App (CRA) 프로젝트&lt;/td&gt;
&lt;td&gt;Webpack 기반 모든 프로젝트&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;설정 편의성&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;Webpack 설정 없이 쉽게 실행 가능&lt;/td&gt;
&lt;td&gt;Webpack 설정을 직접 수정해야 함&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;사용 범위&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;CRA 프로젝트에만 사용 가능&lt;/td&gt;
&lt;td&gt;Webpack이 적용된 모든 프로젝트에서 사용 가능&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;유연성&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;제한적&lt;/td&gt;
&lt;td&gt;Webpack 설정을 완전히 제어하고 커스터마이징 가능&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;설정 방법&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;명령어: npx cra-bundle-analyzer&lt;/td&gt;
&lt;td&gt;Webpack 플러그인으로 설정 필요&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;필자는 cra-bundle-analyzer를 사용했습니다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;여기서 패키지 설치후 npx cra-bundle-analyzer를 실행 시키면&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-09-18 오후 6.33.48.png&quot; data-origin-width=&quot;1431&quot; data-origin-height=&quot;988&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bpUbu2/btsJFrr7Dt0/3Izc6BiVyQ2JdKcatwfxok/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bpUbu2/btsJFrr7Dt0/3Izc6BiVyQ2JdKcatwfxok/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bpUbu2/btsJFrr7Dt0/3Izc6BiVyQ2JdKcatwfxok/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbpUbu2%2FbtsJFrr7Dt0%2F3Izc6BiVyQ2JdKcatwfxok%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;1431&quot; height=&quot;988&quot; data-filename=&quot;스크린샷 2024-09-18 오후 6.33.48.png&quot; data-origin-width=&quot;1431&quot; data-origin-height=&quot;988&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;위 이미지 처럼 나올 것입니다. 이 것을 통해서 어떤 패키지가 어는 정도의 용량을 차지하고 있는지도 쉽게 알 수 있습니다 .&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-09-18 오후 6.35.08.png&quot; data-origin-width=&quot;466&quot; data-origin-height=&quot;717&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cqegFA/btsJDYLd7BE/PXWfaU4uOWiQKJf0DYmmHK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cqegFA/btsJDYLd7BE/PXWfaU4uOWiQKJf0DYmmHK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cqegFA/btsJDYLd7BE/PXWfaU4uOWiQKJf0DYmmHK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcqegFA%2FbtsJDYLd7BE%2FPXWfaU4uOWiQKJf0DYmmHK%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;466&quot; height=&quot;717&quot; data-filename=&quot;스크린샷 2024-09-18 오후 6.35.08.png&quot; data-origin-width=&quot;466&quot; data-origin-height=&quot;717&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;위에 같은 여러 툴을 사용하여 어떤 소스가 시간이 걸리는지 파악하여 리팩토링 및 최적화를 진행하면 됩니다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;다음 장에는 실제로 최적하 기법을 작성하려고합니다&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- css 애니메이션 최적화&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- 컴포넌트 지연 로딩&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- 컴포넌트 사전 로딩&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- 이미지 사전 로딩&lt;/p&gt;</description>
      <category>Front-End</category>
      <author>dobbyyo</author>
      <guid isPermaLink="true">https://dobbyyo.tistory.com/13</guid>
      <comments>https://dobbyyo.tistory.com/entry/%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C-%EC%84%B1%EB%8A%A5-%EC%B5%9C%EC%A0%81%ED%99%94-1%ED%8E%B8-%EC%B5%9C%EC%A0%81%ED%99%94%EB%8A%94-%EC%99%9C-%ED%95%84%EC%9A%94%ED%95%A0%EA%B9%8C-%EC%9B%B9-%EC%84%B1%EB%8A%A5-%EB%B6%84%EC%84%9D#entry13comment</comments>
      <pubDate>Wed, 18 Sep 2024 23:07:36 +0900</pubDate>
    </item>
    <item>
      <title>2023 KAKAO BLIND RECRUITMENT 개인정보 수집 유효기간</title>
      <link>https://dobbyyo.tistory.com/entry/2023-KAKAO-BLIND-RECRUITMENT-%EA%B0%9C%EC%9D%B8%EC%A0%95%EB%B3%B4-%EC%88%98%EC%A7%91-%EC%9C%A0%ED%9A%A8%EA%B8%B0%EA%B0%84</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;문제&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-09-12 오후 5.58.17.png&quot; data-origin-width=&quot;535&quot; data-origin-height=&quot;1006&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cvtP2a/btsJz1aqGHD/e56kCYp4uiTJ2taTmZ1Jbk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cvtP2a/btsJz1aqGHD/e56kCYp4uiTJ2taTmZ1Jbk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cvtP2a/btsJz1aqGHD/e56kCYp4uiTJ2taTmZ1Jbk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcvtP2a%2FbtsJz1aqGHD%2Fe56kCYp4uiTJ2taTmZ1Jbk%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;535&quot; height=&quot;1006&quot; data-filename=&quot;스크린샷 2024-09-12 오후 5.58.17.png&quot; data-origin-width=&quot;535&quot; data-origin-height=&quot;1006&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-09-12 오후 5.58.30.png&quot; data-origin-width=&quot;536&quot; data-origin-height=&quot;988&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Jiuo9/btsJAHoSd5V/CUYVUzPkYgLClPLcvmnfKK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Jiuo9/btsJAHoSd5V/CUYVUzPkYgLClPLcvmnfKK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Jiuo9/btsJAHoSd5V/CUYVUzPkYgLClPLcvmnfKK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJiuo9%2FbtsJAHoSd5V%2FCUYVUzPkYgLClPLcvmnfKK%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;536&quot; height=&quot;988&quot; data-filename=&quot;스크린샷 2024-09-12 오후 5.58.30.png&quot; data-origin-width=&quot;536&quot; data-origin-height=&quot;988&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;h3 data-ke-size=&quot;size23&quot;&gt;요점파악&lt;/h3&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;1. &lt;b&gt;날짜 계산 방식&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;개인정보가 수집된 날짜와 약관에 따른 유효기간이 주어졌을 때, 이를 정확히 &lt;b&gt;일 단위로 계산&lt;/b&gt;해야 합니다. 모든 달이 28일까지 있다고 가정하므로, 날짜를 연도, 월, 일 단위로 각각 &lt;b&gt;일수로 변환&lt;/b&gt;해 비교할 수 있어야 합니다.&lt;/li&gt;
&lt;li&gt;예를 들어, 2022.05.19는 (2022년 * 12 * 28) + (5월 * 28) + 19일로 계산하여 일수로 변환할 수 있습니다. 마찬가지로 각 개인정보가 수집된 날짜도 동일하게 처리해야 합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;2. &lt;b&gt;약관 유효기간 적용&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;약관에 따른 &lt;b&gt;유효기간을 일 단위로 변환&lt;/b&gt;해 주어야 합니다. 각 약관은 월 단위로 유효기간이 주어지며, 이를 &lt;b&gt;28일을 기준으로&lt;/b&gt; 변환한 후 비교해야 합니다.&lt;/li&gt;
&lt;li&gt;예를 들어, 유효기간이 6개월인 약관은 6 * 28일로 계산됩니다. 개인정보 수집일에 이 유효기간을 더한 후 만료일을 구할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;3. &lt;b&gt;파기 조건 판단&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;오늘 날짜와 각 개인정보의 수집일, 유효기간을 일 단위로 변환한 후, &lt;b&gt;오늘 날짜가 유효기간이 끝나는 날을 초과했는지&lt;/b&gt; 판단해야 합니다.&lt;/li&gt;
&lt;li&gt;즉, 개인정보 수집일에 해당 약관의 유효기간을 더한 후, 오늘 날짜가 이를 초과하는지 확인하여 파기 여부를 결정합니다. 파기 대상은 &quot;오늘 날짜가 만료일보다 크면&quot; 해당 개인정보를 파기 대상으로 판단합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;코드&lt;/h3&gt;
&lt;pre id=&quot;code_1726132024858&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 계산 편안하게 일로 변경 함수 생성
function caluteDate(date) {
  return date
    .split(&quot;.&quot;)
    .map((v, i) =&amp;gt; {
      if (i === 0) {
        return Number(v) * 28 * 12;
      } else if (i === 1) {
        return Number(v) * 28;
      } else {
        return Number(v);
      }
    })
    .reduce((acc, cur) =&amp;gt; acc + cur, 0);
}

function solution(today, terms, privacies) {
  let answer = [];
  const termsDic = {};

  // 현재 날짜 일로 변경 함수에 적용
  const todayCur = caluteDate(today);

  // 기간도 일로 바꾸기
  terms.forEach((a) =&amp;gt; {
    const [alpha, month] = a.split(&quot; &quot;);
    termsDic[alpha] = Number(month) * 28;
  });

  // 개인정보 수집 유호기간 판단하여 answer에 삽입
  privacies.map((v, i) =&amp;gt; {
    const [registerDay, alpha] = v.split(&quot; &quot;);
    let registerDayCur = caluteDate(registerDay);

    // (현재 날짜) 비교 (등록기간 + 유효기간)
    if (todayCur &amp;gt; registerDayCur + termsDic[alpha] - 1) {
      answer.push(i + 1);
    }
  });

  return answer;
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Algorithm</category>
      <author>dobbyyo</author>
      <guid isPermaLink="true">https://dobbyyo.tistory.com/12</guid>
      <comments>https://dobbyyo.tistory.com/entry/2023-KAKAO-BLIND-RECRUITMENT-%EA%B0%9C%EC%9D%B8%EC%A0%95%EB%B3%B4-%EC%88%98%EC%A7%91-%EC%9C%A0%ED%9A%A8%EA%B8%B0%EA%B0%84#entry12comment</comments>
      <pubDate>Thu, 12 Sep 2024 18:08:02 +0900</pubDate>
    </item>
    <item>
      <title>PCCP 기출문제 1번 / 동영상 재생기</title>
      <link>https://dobbyyo.tistory.com/entry/PCCP-%EA%B8%B0%EC%B6%9C%EB%AC%B8%EC%A0%9C-1%EB%B2%88-%EB%8F%99%EC%98%81%EC%83%81-%EC%9E%AC%EC%83%9D%EA%B8%B0</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;문제 및 제한사항&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;544&quot; data-origin-height=&quot;602&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cMqxRe/btsJz1Agawg/qyQkAznnxBQ6Je3gElmViK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cMqxRe/btsJz1Agawg/qyQkAznnxBQ6Je3gElmViK/img.png&quot; data-alt=&quot;ㅇ&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cMqxRe/btsJz1Agawg/qyQkAznnxBQ6Je3gElmViK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcMqxRe%2FbtsJz1Agawg%2FqyQkAznnxBQ6Je3gElmViK%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;544&quot; height=&quot;602&quot; data-origin-width=&quot;544&quot; data-origin-height=&quot;602&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;ㅇ&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;540&quot; data-origin-height=&quot;502&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bhCgQj/btsJArZGNxR/DfOUnTrwAQ6M3EjKDQSU6k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bhCgQj/btsJArZGNxR/DfOUnTrwAQ6M3EjKDQSU6k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bhCgQj/btsJArZGNxR/DfOUnTrwAQ6M3EjKDQSU6k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbhCgQj%2FbtsJArZGNxR%2FDfOUnTrwAQ6M3EjKDQSU6k%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;502&quot; data-origin-width=&quot;540&quot; data-origin-height=&quot;502&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;h3 data-ke-size=&quot;size23&quot;&gt;요점 파악&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;재생 위치 이동: commands에 따라 Next, Prev에 따라 비디오 재생 위치를 앞뒤로 이동.&lt;/li&gt;
&lt;li&gt;오프닝 구간 건너뛰기: 현재위치가 오프닝에 있을 경우,&amp;nbsp; 그 구간을 자동으로 건너뛰어 오프닝 끝으로 이동&lt;/li&gt;
&lt;li&gt;경계값 처리: 재생 위치가 0미만이거나 video_len의 길이를 넘지 않도록 경계값 처리&lt;/li&gt;
&lt;li&gt;초와 분 변환: MM:SS를 초로 변환하여 비교 -&amp;gt; 결과값은 다시 MM:SS로 변경&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1726109404449&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function timeToTimeStamp(timeStr) {
  const [minutes, seconds] = timeStr.split(&quot;:&quot;).map(Number);

  return Number(minutes * 60 + seconds);
}

function secondsToMinuteSecond(totalSeconds) {
  const minutes = Math.floor(totalSeconds / 60);

  const seconds = totalSeconds % 60;

  const formattedMinutes = String(minutes).padStart(2, &quot;0&quot;);
  const formattedSeconds = String(seconds).padStart(2, &quot;0&quot;);

  return `${formattedMinutes}:${formattedSeconds}`;
}

function solution(video_len, pos, op_start, op_end, commands) {
  let answer = &quot;&quot;;

  const change_video_len = timeToTimeStamp(video_len);
  let change_op_pos = timeToTimeStamp(pos);
  const change_op_start = timeToTimeStamp(op_start);
  const change_op_end = timeToTimeStamp(op_end);

  // 현재 시점이 오프닝일 경우 건너뛰기 적용
  if (change_op_start &amp;lt;= change_op_pos &amp;amp;&amp;amp; change_op_pos &amp;lt;= change_op_end) {
    change_op_pos = change_op_end;
  }

  for (let command of commands) {
    // 명령어가 next일 경우
    if (command === &quot;next&quot;) {
      change_op_pos += 10;
    }
    // 명령어가 prev일 경우
    else if (command === &quot;prev&quot;) {
      change_op_pos -= 10;
    }
    // 현재 시간이 비디오 길이를 총 넣어갔을 경우
    if (change_video_len &amp;lt; change_op_pos) {
      change_op_pos = change_video_len;
    }
    // 현재 시간이 비디오 길이 최소일 경우
    else if (change_op_pos &amp;lt; 0) {
      change_op_pos = 0;
    }
    // 현재 시점이 오프닝일 경우 건너뛰기 적용
    if (change_op_start &amp;lt;= change_op_pos &amp;amp;&amp;amp; change_op_pos &amp;lt;= change_op_end) {
      change_op_pos = change_op_end;
    }
  }

  answer = secondsToMinuteSecond(change_op_pos);

  return answer;
}

console.log(solution(&quot;34:33&quot;, &quot;13:00&quot;, &quot;00:55&quot;, &quot;02:55&quot;, [&quot;next&quot;, &quot;prev&quot;])); //&quot;13:00&quot;
console.log(solution(&quot;10:55&quot;, &quot;00:05&quot;, &quot;00:15&quot;, &quot;06:55&quot;, [&quot;prev&quot;, &quot;next&quot;, &quot;next&quot;])); //&quot;06:55&quot;
console.log(solution(&quot;07:22&quot;, &quot;04:05&quot;, &quot;00:15&quot;, &quot;04:07&quot;, [&quot;next&quot;])); //&quot;04:17&quot;&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Algorithm</category>
      <category>코딩테스트</category>
      <author>dobbyyo</author>
      <guid isPermaLink="true">https://dobbyyo.tistory.com/11</guid>
      <comments>https://dobbyyo.tistory.com/entry/PCCP-%EA%B8%B0%EC%B6%9C%EB%AC%B8%EC%A0%9C-1%EB%B2%88-%EB%8F%99%EC%98%81%EC%83%81-%EC%9E%AC%EC%83%9D%EA%B8%B0#entry11comment</comments>
      <pubDate>Thu, 12 Sep 2024 11:50:40 +0900</pubDate>
    </item>
    <item>
      <title>PCCP 기출문제 1번 / 붕대 감기</title>
      <link>https://dobbyyo.tistory.com/entry/PCCP-%EA%B8%B0%EC%B6%9C%EB%AC%B8%EC%A0%9C-1%EB%B2%88-%EB%B6%95%EB%8C%80-%EA%B0%90%EA%B8%B0</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;547&quot; data-origin-height=&quot;660&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qitPU/btsJyGQatWk/RKMQuUu4d7oqmdKb51ahH1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qitPU/btsJyGQatWk/RKMQuUu4d7oqmdKb51ahH1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qitPU/btsJyGQatWk/RKMQuUu4d7oqmdKb51ahH1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqitPU%2FbtsJyGQatWk%2FRKMQuUu4d7oqmdKb51ahH1%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;547&quot; height=&quot;660&quot; data-origin-width=&quot;547&quot; data-origin-height=&quot;660&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;538&quot; data-origin-height=&quot;738&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cmvxZ0/btsJxE6EZ5u/klC3p7fWWAAqLcveprZITk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cmvxZ0/btsJxE6EZ5u/klC3p7fWWAAqLcveprZITk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cmvxZ0/btsJxE6EZ5u/klC3p7fWWAAqLcveprZITk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcmvxZ0%2FbtsJxE6EZ5u%2FklC3p7fWWAAqLcveprZITk%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;538&quot; height=&quot;738&quot; data-origin-width=&quot;538&quot; data-origin-height=&quot;738&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;푼 코드&amp;nbsp;&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1725945090947&quot; class=&quot;javascript&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;function solution(bandage, health, attacks) {
  let answer = 0;

  const min = attacks[attacks.length - 1][0];
  let successNum = 0;
  let currentHealth = health;

  for (let i = 1; i &amp;lt;= min; i++) {
    // 공격 정보 가져오기
    const attackNum = attacks.find((v) =&amp;gt; {
      return v[0] === i;
    });

    //  공격이 존재 시
    if (attackNum) {
      currentHealth -= attackNum[1];
      successNum = 0;
      // 현재 체력이 0 이하일시 -1 반환
      if (currentHealth &amp;lt;= 0) {
        return -1;
      }
    } else {
      successNum++;
      // 최대 회복 카운터 일 경우
      if (successNum === bandage[0]) {
        successNum = 0;
        currentHealth += bandage[1] + bandage[2];
      } else {
        // 현재 체력에 회복 플러스 및 최대 체력
        currentHealth === health ? currentHealth : (currentHealth += bandage[1]);
      }
      // 현재 체력이 제한 체력보다 더 높을 제한 체력으로 제한
      if (currentHealth &amp;gt; health) {
        currentHealth = health;
      }
    }
  }
  answer = currentHealth;
  return answer;
}&lt;/code&gt;&lt;/pre&gt;
&lt;h4 style=&quot;color: #000000;&quot; data-ke-size=&quot;size20&quot;&gt;문제점&amp;nbsp;&lt;/h4&gt;
&lt;div&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size16&quot;&gt;1.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;체력 회복 처리의 모호성&lt;/b&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1725945090948&quot; class=&quot;routeros&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;currentHealth === health ? currentHealth : (currentHealth += bandage[1]);​&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 부분에서 currentHealth === health 조건을 체크하고 있지만, 조건이 참일 때 아무 동작도 하지 않기 때문에 불필요한 비교가 발생하고 있습니다. 만약 체력이 최대일 경우 그냥 넘어가면 되는데, 조건문을 작성해 가독성을 떨어뜨리고 있습니다. 또한, ===는 비교 연산자이므로 이 부분은 의도대로 동작하지 않을 가능성이 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;개선 방안&lt;/b&gt;: 체력이 최대일 때는 회복을 하지 않으면 되므로 불필요한 비교를 제거하는 것이 좋습니다. 최대 체력 초과 여부는 회복 후에 한 번만 확인하면 충분합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size16&quot;&gt;2.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;find 함수 사용으로 인한 비효율성&lt;/b&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1725945090948&quot; class=&quot;coffeescript&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;const attackNum = attacks.find((v) =&amp;gt; { return v[0] === i; });&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;매 반복마다 attacks 배열에서 공격 시간을 찾아내기 위해 find를 사용하고 있는데, find는 배열을 순회하며 값을 찾기 때문에 매 루프마다 배열을 다시 순회하게 됩니다. 이는 attacks 배열이 커질 경우 성능 문제를 발생 시킬 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;개선 방안&lt;/b&gt;: attacks 배열이 오름차순으로 정렬되어 있기 때문에, 배열을 한 번만 순회하며 각 공격 시간에 맞춰 처리할 수 있습니다. 이렇게 하면 성능을 크게 개선할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size16&quot;&gt;3.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;successNum 관리 방식의 문제&lt;/b&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1725945090949&quot; class=&quot;angelscript&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;successNum = 0;
if (successNum === bandage[0]) { 
	successNum = 0; currentHealth += bandage[1] + bandage[2]; 
    } 
    else { 
    	successNum++; 
   }&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;successNum을 초기화하고 다시 증가시키는 방식이 헷갈릴 수 있습니다. 특히 공격을 받았을 때와 붕대 감기가 성공했을 때의 처리가 직관적이지 않습니다. 이 부분은 성공 시점과 회복 시점을 좀 더 명확히 구분할 수 있도록 수정하는 것이 좋습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;개선 방안&lt;/b&gt;: 붕대 감기의 성공 시간을 관리할 때 공격을 받으면 무조건 초기화하고, 공격이 없을 때는 성공 시간을 증가시키는 방식으로 처리하는 것이 직관적입니다. 그리고 성공 시간과 체력 회복은 별도로 처리해 코드 흐름을 간결하게 만들 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size16&quot;&gt;4.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;체력 초과 처리의 중복&lt;/b&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1725945090949&quot; class=&quot;routeros&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;if (currentHealth &amp;gt; health) { 
	currentHealth = health; 
   }&lt;/code&gt;&lt;/pre&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;개선 방안&lt;/b&gt;: 매 루프마다 체력이 최대 체력을 넘는지 확인하는 대신, 체력을 회복하는 시점에만 이를 확인하는 것으로 충분합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size16&quot;&gt;5.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;리턴 위치의 모호성&lt;/b&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1725945090949&quot; class=&quot;angelscript&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;if (currentHealth &amp;lt;= 0) { 
	return -1; 
   }&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공격을 받았을 때 체력이 0 이하가 되면 바로 -1을 리턴하도록 되어 있는데, 이는 정상적인 흐름이지만 코드의 흐름상 위치가 다소 중간에 있어 흐름을 방해할 수 있습니다. 이 부분은 더 직관적인 위치로 옮기는 것이 좋습니다.&lt;/p&gt;
&lt;/div&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;b&gt;변경 코드&amp;nbsp;&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1725945061955&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function solution(bandage, health, attacks) {
  let currentHealth = health; // 현재 체력
  let successTime = 0; // 붕대 감기 연속 성공 시간

  for (let i = 1; i &amp;lt;= attacks[attacks.length - 1][0]; i++) {
    // i초에 공격이 있는지 확인
    const attack = attacks.find((v) =&amp;gt; v[0] === i);

    if (attack) {
      // 공격이 있을 경우 체력 감소
      currentHealth -= attack[1];
      successTime = 0; // 붕대 감기 초기화
      if (currentHealth &amp;lt;= 0) return -1; // 체력이 0 이하이면 사망
    } else {
      // 공격이 없을 경우 붕대 감기 시전
      successTime++;
      currentHealth += bandage[1]; // 매초 체력 회복

      // t초 연속으로 성공 시 추가 회복
      if (successTime === bandage[0]) {
        currentHealth += bandage[2];
        successTime = 0; // 추가 회복 후 성공 시간 초기화
      }

      // 체력이 최대 체력을 넘지 않도록 조정
      if (currentHealth &amp;gt; health) currentHealth = health;
    }
  }

  return currentHealth;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Algorithm</category>
      <author>dobbyyo</author>
      <guid isPermaLink="true">https://dobbyyo.tistory.com/10</guid>
      <comments>https://dobbyyo.tistory.com/entry/PCCP-%EA%B8%B0%EC%B6%9C%EB%AC%B8%EC%A0%9C-1%EB%B2%88-%EB%B6%95%EB%8C%80-%EA%B0%90%EA%B8%B0#entry10comment</comments>
      <pubDate>Tue, 10 Sep 2024 16:47:10 +0900</pubDate>
    </item>
    <item>
      <title>React - Hooks</title>
      <link>https://dobbyyo.tistory.com/entry/React-Hooks</link>
      <description>&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;hooks란&lt;br /&gt;리액트 v16.8에 새로 도입된 기능으로 함수 컴포넌트에서도 상태관리를 할 수있는 hooks들이다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #009a87;&quot;&gt;1. useState&lt;/span&gt;&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;함수 컴포넌트에서 가변적인 상태를 지닐 수 있게 해줄 수 있는 hook입니다.&amp;nbsp;&lt;br /&gt;즉, 상태관리를 할 수 있게 만들어준다.&amp;nbsp;&lt;/blockquote&gt;
&lt;pre id=&quot;code_1709812359447&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React, { useState } from &quot;react&quot;;

//  useState를 활용한 컴포넌트 상태 관리
function App() {
  const [count, setCount] = useState(0);
  return (
    &amp;lt;div&amp;gt;
      &amp;lt;p&amp;gt;현재 카운트: {count}&amp;lt;/p&amp;gt;
      &amp;lt;button onClick={() =&amp;gt; setCount(count + 1)}&amp;gt;증가&amp;lt;/button&amp;gt;
      &amp;lt;button onClick={() =&amp;gt; setCount(count - 1)}&amp;gt;감소&amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}

export default App;&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;useState 상태에 기본값을 지정할 수있습니다. 여기서는 0을 지정했지만 다른 형대도 저장이 가능합니다&amp;nbsp;&lt;br /&gt;- Number&lt;br /&gt;- String&lt;br /&gt;- Boolean&lt;br /&gt;- Array&lt;br /&gt;- Object&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;'set'이 붙은 함수를 이용해서 상태를 업데이트 하는 방식의 장점은 아래와 같다&lt;br /&gt;- 불변성 유지: 상태를 직접 변경하게 되면 React가 상태 변경을 감지하지 못하고, UI가 업데이트가 안 될 수 있다.&lt;br /&gt;- 상태 업데이트 일관성&lt;br /&gt;- 비동기 상태 업데이트&lt;br /&gt;- 상태 업데이트 로직의 재사용성&lt;br /&gt;등 여러개가 있을 수 있다 여기까지 내가 생각한 장점이다&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #009a87;&quot;&gt;2. useEffect&lt;/span&gt;&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;리액트 컴포넌트가 렌더링될 때마다 특정 작업을 수행하도록 설정할 수 있는 Hook&lt;br /&gt;이전 블로그 라이프사이클에서 componentDidMount와 componentDidUpdate를 합친 형태라고 생각해도 된다.&lt;/blockquote&gt;
&lt;pre id=&quot;code_1709813941299&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// useEffect를 이용한 예제
import React, { useState, useEffect } from &quot;react&quot;;

function App() {
  const [count, setCount] = useState(0);

  useEffect(() =&amp;gt; {
    console.log(count);
  }, []);

  return (
    &amp;lt;div&amp;gt;
      &amp;lt;p&amp;gt;You clicked {count} times&amp;lt;/p&amp;gt;
      &amp;lt;button onClick={() =&amp;gt; setCount(count + 1)}&amp;gt;Click me&amp;lt;/button&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;pre id=&quot;code_1709814056015&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;useEffect(() =&amp;gt; {
  console.log(count);
}, []); // 해당 부분 &quot;[]&quot; 이부분이 빈 배열일 시 브라우저 진입 시 만 실행

useEffect(() =&amp;gt; {
  console.log(count);
}, [count]); // 해당 부분 &quot;[count]&quot;일 시 count의 값이 변경될 때 마다 실행&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #009a87;&quot;&gt;3. useReducer&lt;/span&gt;&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;useState보다 더 다양한 컴포넌트 상황에 따라 다양한 상태를 다른 값으로 업데이트해 주고 싶을 떄 사용된다.&lt;br /&gt;리듀서는 현재 상태, 액션(업데이트를 위해 필요한 정보를 담은 것)을 받아 새로운 상태를 반환하는 함수입니다.&amp;nbsp;&lt;/blockquote&gt;
&lt;pre id=&quot;code_1709814734274&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React, { useReducer } from &quot;react&quot;;
import &quot;./App.css&quot;;

// 리듀서 함수 정의
function reducer(state, action) {
  switch (action.type) {
    case &quot;increment&quot;:
      return { count: state.count + 1 };
    case &quot;decrement&quot;:
      return { count: state.count - 1 };
    default:
      throw new Error();
  }
}

function App() {
  const [state, dispatch] = useReducer(reducer, { count: 0 });

  return (
    &amp;lt;div&amp;gt;
      Count: {state.count}
      &amp;lt;button onClick={() =&amp;gt; dispatch({ type: &quot;decrement&quot; })}&amp;gt;-&amp;lt;/button&amp;gt;
      &amp;lt;button onClick={() =&amp;gt; dispatch({ type: &quot;increment&quot; })}&amp;gt;+&amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}

export default App;&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;useReducer의 첫 번째 파라미터에는 리듀서 함수를 넣고, 두번째 파라미터는 해당 리듀서의 기본값을 넣어준다.&amp;nbsp;&lt;br /&gt;이 Hook을 사용하면 state 값과 dispatch ㅘㅁ수를 받아온다 (state는 현재 가르키고 있는 상태, dispatch는 액션을 발생시키는 함수)&lt;/blockquote&gt;
&lt;pre id=&quot;code_1709815054295&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React, { useReducer } from &quot;react&quot;;
import &quot;./App.css&quot;;

// input이 많을 경우 useReducer를 사용하면 코드가 깔끔해진다.

const reducer = (state, action) =&amp;gt; {
  return {
    ...state,
    [action.name]: action.value,
  };
};

function App() {
  const [state, dispatch] = useReducer(reducer, {
    name: &quot;&quot;,
    nickname: &quot;&quot;,
  });
  const { name, nickname } = state;
  const onChange = (e) =&amp;gt; {
    dispatch(e.target);
  };

  return (
    &amp;lt;div&amp;gt;
      &amp;lt;div&amp;gt;
        &amp;lt;input name=&quot;name&quot; value={name} onChange={onChange} /&amp;gt;
        &amp;lt;input name=&quot;nickname&quot; value={nickname} onChange={onChange} /&amp;gt;
      &amp;lt;/div&amp;gt;
      &amp;lt;div&amp;gt;
        &amp;lt;div&amp;gt;
          &amp;lt;b&amp;gt;이름:&amp;lt;/b&amp;gt; {name}
        &amp;lt;/div&amp;gt;
        &amp;lt;div&amp;gt;
          &amp;lt;b&amp;gt;닉네임:&amp;lt;/b&amp;gt; {nickname}
        &amp;lt;/div&amp;gt;
      &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;&amp;nbsp;위 예제로 input이 많을 경우 useReducer을 사용하면 가독성이 좋은 것을 확인할 수 있다.&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;color: #009a87;&quot;&gt;4. useMemo&lt;/span&gt;&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;함수 컴포넌트 내부에서 발생하는 연산을 최적화할 수 있습니다.&amp;nbsp;&lt;/blockquote&gt;
&lt;pre id=&quot;code_1709815498587&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React, { useReducer, useState } from &quot;react&quot;;
import &quot;./App.css&quot;;

// useMeno 예제  - 렌더링 최적화

const getAverage = (num) =&amp;gt; {
  console.log(&quot;평균값 계산 중..&quot;);
  if (num.length === 0) return 0; // 배열이 비어있을때 0 반환
  const sum = num.reduce((a, b) =&amp;gt; a + b); // 배열의 합계 계산
  return sum / num.length;
};

function App() {
  const [list, setList] = useState([]);
  const [number, setNumber] = useState(&quot;&quot;);

  const onChange = (e) =&amp;gt; {
    setNumber(e.target.value);
  };

  const onInsert = (e) =&amp;gt; {
    const nextList = list.concat(parseInt(number)); // parseInt : 문자열을 정수로 변환후 concat 으로 배열에 추가
    setList(nextList); // 배열 업데이트
    setNumber(&quot;&quot;); // input 초기화
  };

  const avg = getAverage(list); // 배열의 평균값 계산

  return (
    &amp;lt;div&amp;gt;
      &amp;lt;input value={number} onChange={onChange} /&amp;gt;
      &amp;lt;button onClick={onInsert}&amp;gt;등록&amp;lt;/button&amp;gt;
      &amp;lt;ul&amp;gt;
        {list.map((value, index) =&amp;gt; (
          &amp;lt;li key={index}&amp;gt;{value}&amp;lt;/li&amp;gt;
        ))}
      &amp;lt;/ul&amp;gt;
      &amp;lt;div&amp;gt;
        &amp;lt;b&amp;gt;평균값:&amp;lt;/b&amp;gt; {avg}
      &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;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;주석으로 해당 줄이 어떤 역할 하는지 적어 났습니다.&amp;nbsp;&lt;br /&gt;위 코드를 실행 시키면 input을 적을 때마다 console.log(&quot;평균값 계산 중..&quot;)이 실행이 된다.&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-03-07 오후 9.48.39.png&quot; data-origin-width=&quot;272&quot; data-origin-height=&quot;147&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b84UKV/btsFE1wZ5cV/3UdLWGqhN4M3kcfZDdjB91/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b84UKV/btsFE1wZ5cV/3UdLWGqhN4M3kcfZDdjB91/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b84UKV/btsFE1wZ5cV/3UdLWGqhN4M3kcfZDdjB91/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb84UKV%2FbtsFE1wZ5cV%2F3UdLWGqhN4M3kcfZDdjB91%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;272&quot; height=&quot;147&quot; data-filename=&quot;스크린샷 2024-03-07 오후 9.48.39.png&quot; data-origin-width=&quot;272&quot; data-origin-height=&quot;147&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1709815862345&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;  const avg = useMemo(() =&amp;gt;
    getAverage(list)
  ,[list]); // 배열의 평균값 계산&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;위처럼 useMemo hook 사용 시 리스트가 변경될때만 로그가 찍히는 것을 확인 할 수 있다.&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-03-07 오후 9.50.15.png&quot; data-origin-width=&quot;271&quot; data-origin-height=&quot;84&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bsqU0q/btsFE32EBMV/oqvRSdQaqoJgTBZkA5q2Q1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bsqU0q/btsFE32EBMV/oqvRSdQaqoJgTBZkA5q2Q1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bsqU0q/btsFE32EBMV/oqvRSdQaqoJgTBZkA5q2Q1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbsqU0q%2FbtsFE32EBMV%2FoqvRSdQaqoJgTBZkA5q2Q1%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;271&quot; height=&quot;84&quot; data-filename=&quot;스크린샷 2024-03-07 오후 9.50.15.png&quot; data-origin-width=&quot;271&quot; data-origin-height=&quot;84&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #009a87;&quot;&gt;5. useCallback&lt;/span&gt;&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;useMemo와 상당히 비슷한 함수이다.&amp;nbsp;&lt;br /&gt;주로 렌더링 성능을 최적화해야 하는 상황에서 사용한다. 즉 만들어 놨던 함수를 재 사용할수 있다.&lt;br /&gt;방금 위에서 했던 예제를 보자 onChange와 onInsert 함수는 컴포넌트가 리렌더링 될때마다 새로 만들어진 함수를 사용하게 된다&amp;nbsp;&lt;/blockquote&gt;
&lt;pre id=&quot;code_1709816092122&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt; const onChange = useCallback((e) =&amp;gt; {
    setNumber(e.target.value);
  }, []); // 컴포넌트가 처음 렌더링 될때만 함수 생성

  const onInsert = useCallback(
    (e) =&amp;gt; {
      const nextList = list.concat(parseInt(number));
      setList(nextList);
      setNumber(&quot;&quot;);
    },
    [number, list]
  ); // number 혹은 list 가 바뀌었을때만 함수 생성&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;위와 같이 첫번째 파라미터에는 생성하고 싶은 함수를 넣고, 두번째 파라미터에는 배열을 넣으면된다 (어떤 값이 바뀌었을 떄 함수를 새로 생성 해야하는지 명시해야한다.)&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #009a87;&quot;&gt;6. useRef&amp;nbsp;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전에 업로드한 ref가 있어 아래 링크로 대체하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://dobbyyo.tistory.com/entry/React-ref-DOM&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://dobbyyo.tistory.com/entry/React-ref-DOM&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1709816252598&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;React - ref: DOM&quot; data-og-description=&quot;2024.03.07 - [Front-End/React] - React - Event Handling React - Event Handling 이벤트 핸들링이란 웹 브라우저에서 DOM 요소들과 상호 작용하는 것을 이벤트 라고 한다. 시작 전 리액트에서 이벤트를 사용 시 주의&quot; data-og-host=&quot;dobbyyo.tistory.com&quot; data-og-source-url=&quot;https://dobbyyo.tistory.com/entry/React-ref-DOM&quot; data-og-url=&quot;https://dobbyyo.tistory.com/entry/React-ref-DOM&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/tLJkc/hyVukPZTzY/Y0fDKBlok6RJJvwAoCZQWK/img.png?width=213&amp;amp;height=204&amp;amp;face=0_0_213_204,https://scrap.kakaocdn.net/dn/QAKgw/hyVxoJZMJu/GKm7NCHMg8Bgrnu2hKR7F1/img.png?width=213&amp;amp;height=204&amp;amp;face=0_0_213_204&quot;&gt;&lt;a href=&quot;https://dobbyyo.tistory.com/entry/React-ref-DOM&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://dobbyyo.tistory.com/entry/React-ref-DOM&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/tLJkc/hyVukPZTzY/Y0fDKBlok6RJJvwAoCZQWK/img.png?width=213&amp;amp;height=204&amp;amp;face=0_0_213_204,https://scrap.kakaocdn.net/dn/QAKgw/hyVxoJZMJu/GKm7NCHMg8Bgrnu2hKR7F1/img.png?width=213&amp;amp;height=204&amp;amp;face=0_0_213_204');&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 - ref: DOM&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;2024.03.07 - [Front-End/React] - React - Event Handling React - Event Handling 이벤트 핸들링이란 웹 브라우저에서 DOM 요소들과 상호 작용하는 것을 이벤트 라고 한다. 시작 전 리액트에서 이벤트를 사용 시 주의&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;dobbyyo.tistory.com&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Front-End/React</category>
      <category>hooks</category>
      <category>React</category>
      <author>dobbyyo</author>
      <guid isPermaLink="true">https://dobbyyo.tistory.com/9</guid>
      <comments>https://dobbyyo.tistory.com/entry/React-Hooks#entry9comment</comments>
      <pubDate>Thu, 7 Mar 2024 22:06:23 +0900</pubDate>
    </item>
    <item>
      <title>React - Lifecycle Method</title>
      <link>https://dobbyyo.tistory.com/entry/React-Lifecycle-Method</link>
      <description>&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;라이프 사이클이란&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;text-align: start;&quot;&gt;LifeCycle은&amp;nbsp;&lt;/span&gt;컴포넌트가 브라우저 상에 나타나고, 업데이트되고, 사라지게 되는 과정&lt;span style=&quot;text-align: start;&quot;&gt;이다. 컴포넌트의 수명은 보통 페이지에서 렌더링되기 전인 준비 과정에서 시작하여 페이지에서 사라질때 끝이 난다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;참고&amp;nbsp;&lt;/span&gt;&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;LifeCycle은 클래스형 에서 사용된다&lt;br /&gt;함수 컴포넌트에서는 사용이 불가능한데 그 대신 hooks 기능을 통해 사용하면 된다.&amp;nbsp;&lt;br /&gt;기업에서 레거시 코드가 있으면 볼 수 있으니 정의를 알 고 있으면 편안하다&amp;nbsp;&lt;br /&gt;작성자는 회사에서 Vue를 사용하는데 라이프사이클을 알 고있어야 기능을 만들기 수월하다. 그러므로 정의는 알 고 있는 것이 좋다.&amp;nbsp;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #009a87;&quot;&gt;라이프 사이클 메서드의 이해&lt;/span&gt;&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;라이프사이클은 총 3가지의 카테고리로 나누어진다. &lt;b&gt;마운트, 업데이트, 언마운트&lt;/b&gt;이다&amp;nbsp;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-03-07 오후 4.12.47.png&quot; data-origin-width=&quot;644&quot; data-origin-height=&quot;473&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bExv2A/btsFC24mJOU/qzHJakwOhMrgMmLuTG3nVK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bExv2A/btsFC24mJOU/qzHJakwOhMrgMmLuTG3nVK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bExv2A/btsFC24mJOU/qzHJakwOhMrgMmLuTG3nVK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbExv2A%2FbtsFC24mJOU%2FqzHJakwOhMrgMmLuTG3nVK%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;644&quot; height=&quot;473&quot; data-filename=&quot;스크린샷 2024-03-07 오후 4.12.47.png&quot; data-origin-width=&quot;644&quot; data-origin-height=&quot;473&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;1. 마운트&amp;nbsp;&lt;/span&gt;&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;DOM이 생성되고 웹 브라우저상에 나타나는 것을 마운트라고 한다.&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-03-07 오후 4.26.07.png&quot; data-origin-width=&quot;393&quot; data-origin-height=&quot;442&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ZsYQK/btsFEiZXiEK/7sxKymNv4fh1S8Z40n2pg1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ZsYQK/btsFEiZXiEK/7sxKymNv4fh1S8Z40n2pg1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ZsYQK/btsFEiZXiEK/7sxKymNv4fh1S8Z40n2pg1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZsYQK%2FbtsFEiZXiEK%2F7sxKymNv4fh1S8Z40n2pg1%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;393&quot; height=&quot;442&quot; data-filename=&quot;스크린샷 2024-03-07 오후 4.26.07.png&quot; data-origin-width=&quot;393&quot; data-origin-height=&quot;442&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;blockquote data-ke-style=&quot;style2&quot;&gt;- constructor: 컴포넌트를 새로 만들 때마다 호출되는 클래스 생성자 메서드&lt;br /&gt;- getDerivedStateFromProps props에 있는 값을 state에 넣을 때 사용&lt;br /&gt;- render: 코딩한 UI를 렌더링하는 메서드&lt;br /&gt;- componentDidMount: 컴포넌트가 웹 브라우저상에 나타난 후 호출&lt;/blockquote&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;2. 업데이트&lt;/span&gt;&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;컴포넌트 다음과 같이 네 가지 경우에 업데이트&lt;br /&gt;- props가 변경&lt;br /&gt;- state가 변경&lt;br /&gt;- 부모 컴포넌트가 리렌더링&lt;br /&gt;- this.forceUpdate로 강제로 렌더링을 트리거할 때&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-03-07 오후 4.38.03.png&quot; data-origin-width=&quot;424&quot; data-origin-height=&quot;535&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/buUPH0/btsFCeYotEF/GJX8QCpYcR6xAEnulvQ7PK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/buUPH0/btsFCeYotEF/GJX8QCpYcR6xAEnulvQ7PK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/buUPH0/btsFCeYotEF/GJX8QCpYcR6xAEnulvQ7PK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbuUPH0%2FbtsFCeYotEF%2FGJX8QCpYcR6xAEnulvQ7PK%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;424&quot; height=&quot;535&quot; data-filename=&quot;스크린샷 2024-03-07 오후 4.38.03.png&quot; data-origin-width=&quot;424&quot; data-origin-height=&quot;535&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;- getDerivedStateFromProps:props의 변화에따라 state 값에도 변화를 주고 싶을 때 사용합니다.&amp;nbsp;&lt;br /&gt;- shouldComponentUpdate: 컴포넌트가 리렌더링을 해야 할지 말아야 할지를 결정하는 메서드 (true, false) 반환&lt;br /&gt;- render: 컴포넌트를 리렌더링&lt;br /&gt;- getSnapshotBeforeUpdate: 컴포넌트 변화를 DOM에 반영하기 바로 직전에 호출&lt;br /&gt;- componentDidUpdate: 컴포넌트의 업데이트 작업이 끝난 후 호출&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;3. 언마운트&lt;/span&gt;&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;컴포넌트를 DOM에서 제거하는 과정&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-03-07 오후 4.41.04.png&quot; data-origin-width=&quot;388&quot; data-origin-height=&quot;235&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/elYBIQ/btsFAwyQvaa/HpzPPgqALcy5Q49wiDyKTk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/elYBIQ/btsFAwyQvaa/HpzPPgqALcy5Q49wiDyKTk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/elYBIQ/btsFAwyQvaa/HpzPPgqALcy5Q49wiDyKTk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FelYBIQ%2FbtsFAwyQvaa%2FHpzPPgqALcy5Q49wiDyKTk%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;388&quot; height=&quot;235&quot; data-filename=&quot;스크린샷 2024-03-07 오후 4.41.04.png&quot; data-origin-width=&quot;388&quot; data-origin-height=&quot;235&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;componentWillUnmount: 컴포넌트가 웹 브라우저상에서 사라지기 전에 호출&lt;br /&gt;즉 정리를 하면 아래와 같다&amp;nbsp; https://projects.wojtekmaj.pl/react-lifecycle-methods-diagram/&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-03-07 오후 4.44.55.png&quot; data-origin-width=&quot;1147&quot; data-origin-height=&quot;432&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/61vDq/btsFCzajad3/AXNSIg9kNkEezysSdEKi51/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/61vDq/btsFCzajad3/AXNSIg9kNkEezysSdEKi51/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/61vDq/btsFCzajad3/AXNSIg9kNkEezysSdEKi51/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F61vDq%2FbtsFCzajad3%2FAXNSIg9kNkEezysSdEKi51%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;1147&quot; height=&quot;432&quot; data-filename=&quot;스크린샷 2024-03-07 오후 4.44.55.png&quot; data-origin-width=&quot;1147&quot; data-origin-height=&quot;432&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 예제로 알아보자&lt;/p&gt;
&lt;pre id=&quot;code_1709805143397&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React, { Component } from &quot;react&quot;;
import &quot;./App.css&quot;;

class App extends Component {
  state = {
    hidden: false,
    disableButton: false, // 버튼 비활성화 상태 추가
  };

  componentDidMount() {
    console.log(&quot;componentDidMount&quot;);
  }

  componentDidUpdate(prevProps, prevState) {
    console.log(&quot;componentDidUpdate&quot;);
  }

  componentWillUnmount() {
    console.log(&quot;componentWillUnmount&quot;);
  }

  onClickButton = () =&amp;gt; {
    this.setState({ hidden: true, disableButton: true });
  };

  render() {
    return (
      &amp;lt;div&amp;gt;
        &amp;lt;span&amp;gt;
          저는 {this.props.lang} 전문 {this.props.name}입니다!
        &amp;lt;/span&amp;gt;
        {!this.state.hidden &amp;amp;&amp;amp; &amp;lt;span&amp;gt;{this.props.birth}년에 태어났습니다.&amp;lt;/span&amp;gt;}
        &amp;lt;button onClick={this.onClickButton} ref=&quot;hide&quot;&amp;gt;
          숨기기
        &amp;lt;/button&amp;gt;
        &amp;lt;button onClick={() =&amp;gt; this.props.history.goBack()}&amp;gt;뒤로&amp;lt;/button&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;blockquote data-ke-style=&quot;style2&quot;&gt;브라우저 진입 시&lt;br /&gt;componentDidMount&lt;br /&gt;&lt;br /&gt;숨기기 클릭 시&amp;nbsp;&lt;br /&gt;componentDidUpdate&lt;br /&gt;&lt;br /&gt;Dom이 사라질때&amp;nbsp;&lt;br /&gt;componentWillUnmount&lt;/blockquote&gt;</description>
      <category>Front-End/React</category>
      <category>lifecycle</category>
      <category>React</category>
      <author>dobbyyo</author>
      <guid isPermaLink="true">https://dobbyyo.tistory.com/8</guid>
      <comments>https://dobbyyo.tistory.com/entry/React-Lifecycle-Method#entry8comment</comments>
      <pubDate>Thu, 7 Mar 2024 19:01:33 +0900</pubDate>
    </item>
    <item>
      <title>React - ref: DOM</title>
      <link>https://dobbyyo.tistory.com/entry/React-ref-DOM</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://dobbyyo.tistory.com/entry/React-Event-Handling&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2024.03.07 - [Front-End/React] - React - Event Handling&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1709785440542&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;React - Event Handling&quot; data-og-description=&quot;이벤트 핸들링이란 웹 브라우저에서 DOM 요소들과 상호 작용하는 것을 이벤트 라고 한다. 시작 전 리액트에서 이벤트를 사용 시 주의사항이다 1. 이벤트 이름은 카멜 표기법으로 작성 2. 이벤트 &quot; data-og-host=&quot;dobbyyo.tistory.com&quot; data-og-source-url=&quot;https://dobbyyo.tistory.com/entry/React-Event-Handling&quot; data-og-url=&quot;https://dobbyyo.tistory.com/entry/React-Event-Handling&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/eF06w/hyVxxmzwAv/2riN2EWxWXd77XPfk1xjBk/img.png?width=213&amp;amp;height=204&amp;amp;face=0_0_213_204,https://scrap.kakaocdn.net/dn/bd24eG/hyVxr7Ixu2/T6QmZiI7ceag8igWSs127k/img.png?width=213&amp;amp;height=204&amp;amp;face=0_0_213_204&quot;&gt;&lt;a href=&quot;https://dobbyyo.tistory.com/entry/React-Event-Handling&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://dobbyyo.tistory.com/entry/React-Event-Handling&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/eF06w/hyVxxmzwAv/2riN2EWxWXd77XPfk1xjBk/img.png?width=213&amp;amp;height=204&amp;amp;face=0_0_213_204,https://scrap.kakaocdn.net/dn/bd24eG/hyVxr7Ixu2/T6QmZiI7ceag8igWSs127k/img.png?width=213&amp;amp;height=204&amp;amp;face=0_0_213_204');&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 - Event Handling&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;이벤트 핸들링이란 웹 브라우저에서 DOM 요소들과 상호 작용하는 것을 이벤트 라고 한다. 시작 전 리액트에서 이벤트를 사용 시 주의사항이다 1. 이벤트 이름은 카멜 표기법으로 작성 2. 이벤트&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;dobbyyo.tistory.com&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;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;ref이란 &lt;br /&gt;reference의 준말이다.&amp;nbsp;&lt;br /&gt;&lt;/span&gt;DOM 요소에 이름을 (id) 붙이는 경우 ref을 사용한다.&amp;nbsp;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;주의사항 리액트 안에서 직접 id를 사용하면 안 되나?&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;리액트 컴포넌트 안에서도 id를 사용할 수 있습니다. 하지만 id는 유일해야 하는데, 이런 상황에서는 중복 id를 가진 DOM이 여러 개 생길 수 있으니 잘못된 사용 방식입니다.&amp;nbsp;&lt;br /&gt;하지만 ref는 전역적으로 작동하지 않고 컴포넌트 내부에서만 작동하기 때문에 이런 문제가 발생하지 않습니다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #009a87;&quot;&gt;1. ref는 어떤 상황에서 사용해야 할까?&lt;/span&gt;&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;보통의 경우 ref를 사용 안 해서 대부분 기능은 개발이 가능합니다 하지만,&amp;nbsp;특정 DOM을 꼭 직접적으로 연결해서 개발을 해야 할 경우 사용됩니다.&lt;br /&gt;&lt;br /&gt;- 특정 input에 포커스 주기&lt;br /&gt;- 스크롤 박스 조작하기&lt;br /&gt;- canvas 요소에 그림 그리기 등&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #009a87;&quot;&gt;2. 예제로 확인하자&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;2-1 input foucs 예제&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;1. myInputRef에 useRef hook을 지정해 주자&amp;nbsp;&lt;br /&gt;2. input 속성에 ref에 만든 훅을 지정한다. (그러면 이제 우리는 해당 input을 사용할 수 있게 된다)&lt;br /&gt;3. 브라우저 진입 시 useEffect를 통해 해당 Input에 focus가 된다.&lt;br /&gt;4. 버튼 클릭 시 해당 input에 foucs가 된다&amp;nbsp;&lt;/blockquote&gt;
&lt;pre id=&quot;code_1709788381539&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const App = () =&amp;gt; {
  const myInfputRef = useRef();
  
  useEffect(() =&amp;gt; {
    myInfputRef.current.focus();
  }, []);
  
  return (
    &amp;lt;div&amp;gt;
      &amp;lt;input ref={myInfputRef} /&amp;gt;
      &amp;lt;button onClick={() =&amp;gt; myInfputRef.current.focus()} /&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;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-03-07 오후 2.13.20.png&quot; data-origin-width=&quot;338&quot; data-origin-height=&quot;112&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/XZ8vZ/btsFCZ7t9ua/zg1Efmk854LksKOjD78hFk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/XZ8vZ/btsFCZ7t9ua/zg1Efmk854LksKOjD78hFk/img.png&quot; data-alt=&quot;위 예제를 실행한거다. 해당 페이지 진입시 useEffect를 통해 초기 focus를 설정해준다 또한 버튼을 클릭 시 또한 foucs가 적용이 된다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/XZ8vZ/btsFCZ7t9ua/zg1Efmk854LksKOjD78hFk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FXZ8vZ%2FbtsFCZ7t9ua%2Fzg1Efmk854LksKOjD78hFk%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;356&quot; height=&quot;118&quot; data-filename=&quot;스크린샷 2024-03-07 오후 2.13.20.png&quot; data-origin-width=&quot;338&quot; data-origin-height=&quot;112&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;위 예제를 실행한거다. 해당 페이지 진입시 useEffect를 통해 초기 focus를 설정해준다 또한 버튼을 클릭 시 또한 foucs가 적용이 된다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;2-2 scroller box 에제&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;scrollTop: 요소의 스크롤바가 수직으로 얼마나 스크롤되었는지를 나타내는 값입니다. 예를 들어, scrollTop 값이 0이면 스크롤바가 맨 위에 위치해 있음을 의미하고, 값이 커질수록 사용자가 더 아래로 스크롤했음을 나타냅니다. &lt;b&gt;즉, 이 값은 &quot;현재 보고 있는 위치&quot;라기보다는 &quot;스크롤바가 상단에서 얼마나 떨어져 있는가&quot;를 나타내는 값입니다.&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;scrollHeight: 요소의 콘텐츠 높이를 포함하는 값입니다. 이 값은 스크롤바를 포함하지 않은 내부 콘텐츠의 전체 높이를 나타냅니다. &lt;b&gt;즉, 사용자가 스크롤을 통해 볼 수 있는 콘텐츠 영역의 전체 높이입니다.&lt;/b&gt; 이 값은 요소의 실제 보이는 높이(offsetHeight) 보다 클 수 있으며, 이 경우 스크롤바가 생깁니다.&lt;/blockquote&gt;
&lt;pre id=&quot;code_1709789532966&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React, { useRef, useEffect } from &quot;react&quot;;
import &quot;./App.css&quot;;

const App = () =&amp;gt; {
  const scrollBoxRef = useRef(null);

  // 스크롤 박스를 특정 위치(여기서는 맨 아래)로 스크롤하는 함수입니다.
  const scrollToBottom = () =&amp;gt; {
    const { current } = scrollBoxRef;
    if (current) {
      current.scrollTop = current.scrollHeight;
    }
  };

  // 스크롤 박스를 특정 위치(여기서는 맨 위)로 스크롤하는 함수입니다.
  const scrollToTop = () =&amp;gt; {
    const { current } = scrollBoxRef;
    if (current) {
      current.scrollTop = 0;
    }
  };

  return (
    &amp;lt;div&amp;gt;
      &amp;lt;div
        ref={scrollBoxRef}
        style={{
          width: &quot;300px&quot;,
          height: &quot;100px&quot;,
          overflow: &quot;auto&quot;,
          margin: &quot;0 auto&quot;,
          border: &quot;1px solid black&quot;,
        }}
      &amp;gt;
        &amp;lt;div style={{ height: &quot;500px&quot; }}&amp;gt;스크롤해 보세요!&amp;lt;/div&amp;gt;
      &amp;lt;/div&amp;gt;
      &amp;lt;button onClick={scrollToTop}&amp;gt;맨 위로&amp;lt;/button&amp;gt;
      &amp;lt;button onClick={scrollToBottom}&amp;gt;맨 아래로&amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;
  );
};

export default App;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-03-07 오후 2.35.32.png&quot; data-origin-width=&quot;378&quot; data-origin-height=&quot;178&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bzYPzH/btsFzaCT159/kukEH9kSYxzIJUjh27PnFK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bzYPzH/btsFzaCT159/kukEH9kSYxzIJUjh27PnFK/img.png&quot; data-alt=&quot;맨 위로 버튼 클릭시 스크롤은 맨 위로&amp;amp;amp;nbsp; / 맨 아래로 버튼 클릭시 스크롤은 맨 아래로 이동 한다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bzYPzH/btsFzaCT159/kukEH9kSYxzIJUjh27PnFK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzYPzH%2FbtsFzaCT159%2FkukEH9kSYxzIJUjh27PnFK%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;378&quot; height=&quot;178&quot; data-filename=&quot;스크린샷 2024-03-07 오후 2.35.32.png&quot; data-origin-width=&quot;378&quot; data-origin-height=&quot;178&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;맨 위로 버튼 클릭시 스크롤은 맨 위로&amp;amp;nbsp; / 맨 아래로 버튼 클릭시 스크롤은 맨 아래로 이동 한다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>Front-End/React</category>
      <category>React</category>
      <category>REF</category>
      <author>dobbyyo</author>
      <guid isPermaLink="true">https://dobbyyo.tistory.com/7</guid>
      <comments>https://dobbyyo.tistory.com/entry/React-ref-DOM#entry7comment</comments>
      <pubDate>Thu, 7 Mar 2024 14:39:33 +0900</pubDate>
    </item>
    <item>
      <title>React - Event Handling</title>
      <link>https://dobbyyo.tistory.com/entry/React-Event-Handling</link>
      <description>&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이벤트 핸들링이란&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;웹 브라우저에서 DOM 요소들과 &lt;b&gt;상호 작용&lt;/b&gt;하는 것을 이벤트 라고 한다.&amp;nbsp;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;시작 전 리액트에서 이벤트를 사용 시 주의사항이다&lt;/span&gt;&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;1. 이벤트 이름은 카멜 표기법으로 작성&amp;nbsp;&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;2. 이벤트 실행할 자바스크립트 코드를 전달하는 것이 아니라, 함수 형태의 값을 전달해야한다.&amp;nbsp;&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;3. DOM 요소에만 이벤트를 설정할 수 있다.&amp;nbsp;&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;- 예로 div, button, input 등 DOM 요소에는 이벤트를 설정할 수 있지만, 우리가 직접 만든 컴포넌트에는 이벤트를 자체적으로 설정할 수 없습니다.&lt;br /&gt;- 이벤트를 컴포넌트에 Porps로 넘겨 사용하는 것은 가능합니다.&lt;/blockquote&gt;
&lt;pre id=&quot;code_1709783248923&quot; class=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;// 부모
const sayDobby = () =&amp;gt; {
  console.log(&quot;Dobby is free&quot;);
};

&amp;lt;MyComeponent sayDobby={sayDobby} /&amp;gt;;

// MyComeponent
const MyComeponent = ({ sayDobby }) =&amp;gt; {
  return &amp;lt;button onClick={sayDobby}&amp;gt;Click me&amp;lt;/button&amp;gt;;
};

export default MyComeponent;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #009a87;&quot;&gt;1. 이벤트 종류 (&lt;a style=&quot;color: #009a87;&quot; href=&quot;https://legacy.reactjs.org/docs/events.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://legacy.reactjs.org/docs/events.html&lt;/a&gt;)&lt;/span&gt;&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;ClipBboard, Touch, Composition 등등 많다. 이것은 외우는 것이 아니라 필요할때 사이트를 방문에 참고하는 것 이 편안하다.&amp;nbsp;&lt;br /&gt;나중에는 자주 사용하는 것은 외워진다.!&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #009a87;&quot;&gt;2. 이벤트 핸들링 예제&lt;/span&gt;&lt;/h4&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;&lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;2-1. onChange&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;onChange 는  DOM요소에서 값이 바뀔 때마다 발생하는 이벤트로, 이벤트가 발생하면&amp;nbsp; 함수가 작동된다&lt;br /&gt;아래는 이벤트 객체에 담긴&amp;nbsp; input 값을 useState의 setText&amp;nbsp;를 통해 새로운 state 로 갱신한다.&lt;/blockquote&gt;
&lt;pre id=&quot;code_1709783948114&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// onChange 예제
const App = () =&amp;gt; {
  const [text, setText] = useState(&quot;&quot;);
  const onChange = (e) =&amp;gt; {
    setText(e.target.value);
  };
  return (
    &amp;lt;div&amp;gt;
      &amp;lt;input value={text} onChange={onChange} /&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;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;2-2. onClick&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;onClick은 이름과 같이 클릭하면 발생하는 이벤트이다.&lt;/blockquote&gt;
&lt;pre id=&quot;code_1709783974353&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// onClick 예제
const App = () =&amp;gt; {
  const onClick = () =&amp;gt; {
    console.log(&quot;Button is clicked&quot;);
  };
  return &amp;lt;button onClick={onClick}&amp;gt;Click me&amp;lt;/button&amp;gt;;
};
export default App;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;2-3 가독성 좋은 코드&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;예로 Input이 많은 경우가 있을 거다, 그럴 경우에는 어떤 방식으로 짜는것이 코드 가독성이 좋아질까 아래 코드를 예로 보자&amp;nbsp;&lt;/blockquote&gt;
&lt;pre id=&quot;code_1709784227523&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// input이 여러개일 때
const App = () =&amp;gt; {
  const [inputs, setInputs] = useState({
    username: &quot;&quot;,
    email: &quot;&quot;,
  });
  const { username, email } = inputs;
  const onChange = (e) =&amp;gt; {
    const { name, value } = e.target;
    setInputs({
      ...inputs,
      [name]: value,
    });
  };
  const onClick = () =&amp;gt; {
    console.log(username, email);
  };
  return (
    &amp;lt;div&amp;gt;
      &amp;lt;input name=&quot;username&quot; value={username} onChange={onChange} /&amp;gt;
      &amp;lt;input name=&quot;email&quot; value={email} onChange={onChange} /&amp;gt;
      &amp;lt;button onClick={onClick}&amp;gt;Click me&amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;
  );
};
export default App;&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;한 눈에 봐도 해당 함수들이 어떤 기능들을 하는 것인지 파악하기가 쉽다&amp;nbsp;&lt;br /&gt;장점: input이 여러개일 때, useState를 여러번 사용하지 않아도 된다!!&lt;/blockquote&gt;</description>
      <category>Front-End/React</category>
      <category>Event Handling</category>
      <category>React</category>
      <author>dobbyyo</author>
      <guid isPermaLink="true">https://dobbyyo.tistory.com/6</guid>
      <comments>https://dobbyyo.tistory.com/entry/React-Event-Handling#entry6comment</comments>
      <pubDate>Thu, 7 Mar 2024 13:16:33 +0900</pubDate>
    </item>
    <item>
      <title>일센스 (정리하며 일하기)</title>
      <link>https://dobbyyo.tistory.com/entry/%EC%9D%BC%EC%84%BC%EC%8A%A4-%EC%A0%95%EB%A6%AC%ED%95%98%EB%A9%B0-%EC%9D%BC%ED%95%98%EA%B8%B0</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthContent&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/AZWs6/btrVUxVGP2z/kXJkjjSDnYZejiRydgE0i1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/AZWs6/btrVUxVGP2z/kXJkjjSDnYZejiRydgE0i1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/AZWs6/btrVUxVGP2z/kXJkjjSDnYZejiRydgE0i1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FAZWs6%2FbtrVUxVGP2z%2FkXJkjjSDnYZejiRydgE0i1%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;1200&quot; height=&quot;600&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;600&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;#1 파일은 반드시 딱 맞는 이름의 풀더에 담는다&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;#2 헤매기 싫다면 MECE하고 단순하게&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;제 1원칙. MECE하게&lt;br /&gt;- ME는 (서로 중복 없이)&lt;br /&gt;- CE는 (전체적으로 누락 없이)&lt;br /&gt;&lt;br /&gt;제 2원칙. 단순하게&lt;br /&gt;- 단순할수록 MECE에 맞추기도. 내가 만든 기준에 그대로 지키기도 쉽다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;#3 한번 따르면 멈출 수 없는 6가지 폴더 생성 규칙&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;1. 풀더 순선느 대분류부터 정렬&lt;br /&gt;2. 최상위에 업무 외 풀더 생성&lt;br /&gt;3. 풀더명 앞은 숫자로 정리&lt;br /&gt;4. 주기별 작업 문서는 기간순 정리&lt;br /&gt;5. 조회 수가 높은 폴더는 상단에 위치&lt;br /&gt;6. 임시폴더는 삭제 주기를 두고 관리&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;#4 한눈에 들어오는 파일 네이밍 규칙&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;원제목을 기준으로 접두사와 접두미사를 활용 (ex001_신입사워_연수_프로그램_기획안_v1.0)&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;#5 손메모 습관&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;1. 단순한 기록이 아니라 생각하는 과정을 거친 짜임새있는 정보&lt;br /&gt;2. 내용을 효과적으로 자유롭게 표현할 수 있다.&lt;br /&gt;3. 물리적으로 항상 내 곁에 둘 수 있다.&lt;/blockquote&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;#6 적어만 놓고 안 할 거면 일 목록을 왜 쓰니&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;1. 월간 일 목록&lt;br /&gt;2. 주간 일 목록&lt;br /&gt;3. 일일 일 목록&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;#7 산더미 같은 일 목록을 빠르게 처리하는 법 (FIFO/LIFO)&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;1. FIFO - 먼저 들어온 일을 먼저 처리&lt;br /&gt;2. LIFO - 나중에 들어온 걸 먼저 처리&lt;br /&gt;상황에 맞게 사용하자.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>ETC</category>
      <category>일센스</category>
      <author>dobbyyo</author>
      <guid isPermaLink="true">https://dobbyyo.tistory.com/2</guid>
      <comments>https://dobbyyo.tistory.com/entry/%EC%9D%BC%EC%84%BC%EC%8A%A4-%EC%A0%95%EB%A6%AC%ED%95%98%EB%A9%B0-%EC%9D%BC%ED%95%98%EA%B8%B0#entry2comment</comments>
      <pubDate>Tue, 10 Jan 2023 23:01:03 +0900</pubDate>
    </item>
    <item>
      <title>일센스 (이메일 중심으로 일하기)</title>
      <link>https://dobbyyo.tistory.com/entry/%ED%99%98%EC%98%81%ED%95%A9%EB%8B%88%EB%8B%A4</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;#1 이메일 중심으로 일하기&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthContent&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/drhkU6/btrVI7jCNEg/mgr9yApqk2F8Ne1I7gMA5k/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/drhkU6/btrVI7jCNEg/mgr9yApqk2F8Ne1I7gMA5k/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/drhkU6/btrVI7jCNEg/mgr9yApqk2F8Ne1I7gMA5k/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdrhkU6%2FbtrVI7jCNEg%2Fmgr9yApqk2F8Ne1I7gMA5k%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;1200&quot; height=&quot;600&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;600&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;메일에는 크게 네 가지 요소가 있다.&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;수신자, 참조자&lt;/li&gt;
&lt;li&gt;제목&lt;/li&gt;
&lt;li&gt;본문&lt;/li&gt;
&lt;li&gt;첨부파일&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;수신자, 참조자&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;수신자 - 행위 대상자&lt;br /&gt;참조자 - 해당 메일을 인지해야 하는 대상자&lt;br /&gt;&lt;br /&gt;-- 조직도상 상위 부서일수록, 직급이 높을수록 먼저 입력하자 --&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;제목&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;1. 제목은 전체 내용을 함축하는가?&lt;br /&gt;2. 말머리를 이용하자 &lt;span style=&quot;color: #ee2323;&quot;&gt;[요청], [중요], [안내], [공유]&lt;/span&gt; 등등&lt;br /&gt;3. (처리 기한이 있는 경우) 제목에 기한 필수 포함&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;본문&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;1. 본인 소속과 이름을 밝히는 인사로 시작&lt;br /&gt;2. 인사 바로 다음 목적을 밝히자&lt;br /&gt;3. 말보다는 양식형태로 표현&lt;br /&gt;4. 중요한 내용은 강조(색, bold) 등&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;첨부파일&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;1. 첨부파일을 본문에 언급하자&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;회신과 전달, 전체 회신&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;1. 답장할 땐 모든 참조자를 포함해 '전체 회신' 하자.&lt;br /&gt;2. 전달은 해당 내용을 다른 대상자에게 공유하는 용도로 많이 사용.&lt;/blockquote&gt;</description>
      <category>ETC</category>
      <category>일센스</category>
      <author>dobbyyo</author>
      <guid isPermaLink="true">https://dobbyyo.tistory.com/1</guid>
      <comments>https://dobbyyo.tistory.com/entry/%ED%99%98%EC%98%81%ED%95%A9%EB%8B%88%EB%8B%A4#entry1comment</comments>
      <pubDate>Mon, 9 Jan 2023 21:46:54 +0900</pubDate>
    </item>
  </channel>
</rss>