<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>yuvnn BLOG</title>
    <link>https://yuvnn.tistory.com/</link>
    <description>파이팅!</description>
    <language>ko</language>
    <pubDate>Tue, 26 May 2026 14:48:58 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>yuvnn</managingEditor>
    <image>
      <title>yuvnn BLOG</title>
      <url>https://tistory1.daumcdn.net/tistory/7784075/attach/176d6395f8de4830b9b595ed8dc65e80</url>
      <link>https://yuvnn.tistory.com</link>
    </image>
    <item>
      <title>[React] Context API</title>
      <link>https://yuvnn.tistory.com/entry/React-Context-API</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;&lt;b&gt;☁️충북대 구름톤 유니브 4기 스터디 일부 내용&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;React를 사용하다 보면 로그인 정보, 다크 모드 같은 테마, 언어 설정처럼 여러 컴포넌트에서 공통으로 사용하는 데이터가 생깁니다. 이런 데이터는 매번 props로 넘겨주기보다는, Context API를 활용해서 컴포넌트 트리 전체에 쉽게 전달할 수 있어요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 글에서는 Context API의 기본 개념부터 사용법, 주의할 점까지 하나씩 정리해보도록 하겠습니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. Context란 무엇인가요?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Context는 컴포넌트 트리를 통해 데이터(상태)를 전역적으로 공유할 수 있게 해주는 React의 기능입니다.&lt;br /&gt;기본적으로 props를 일일이 전달하지 않아도, 트리 하위에 있는 모든 컴포넌트가 원하는 데이터를 사용할 수 있게 해줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 로그인 상태, UI 테마, 현재 언어 같은 정보에 적합합니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. 기본 사용법&lt;/h2&gt;
&lt;pre class=&quot;ada&quot;&gt;&lt;code&gt;const ThemeContext = React.createContext('light');

function App() {
  return (
    &amp;lt;ThemeContext.Provider value=&quot;dark&quot;&amp;gt;
      &amp;lt;Toolbar /&amp;gt;
    &amp;lt;/ThemeContext.Provider&amp;gt;
  );
}

function Toolbar() {
  return &amp;lt;ThemedButton /&amp;gt;;
}

function ThemedButton() {
  return (
    &amp;lt;ThemeContext.Consumer&amp;gt;
      {value =&amp;gt; &amp;lt;Button theme={value} /&amp;gt;}
    &amp;lt;/ThemeContext.Consumer&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;React.createContext('light'): 기본값을 지정합니다.&lt;/li&gt;
&lt;li&gt;ThemeContext.Provider: value를 통해 하위 컴포넌트에 데이터를 제공합니다.&lt;/li&gt;
&lt;li&gt;ThemeContext.Consumer: 트리 어디서든 value를 사용할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. useContext() 훅 사용하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보다 간결한 방법으로는 useContext 훅을 사용할 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;import { useContext } from 'react';

function ThemedButton() {
  const theme = useContext(ThemeContext);
  return &amp;lt;Button theme={theme} /&amp;gt;;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 방식은 Consumer를 직접 사용하는 것보다 코드가 훨씬 간단하고 가독성도 좋습니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4. Context 사용할 때 주의할 점&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Context는 편리하지만, 무조건 사용하는 건 좋은 방법이 아닐 수 있어요. 다음 사항을 고려해보세요.&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;재사용성이 떨어질 수 있습니다.&lt;/b&gt;&lt;br /&gt;특정 Context에 의존하는 컴포넌트는 다른 곳에서 재사용하기 어려워집니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;불필요한 렌더링이 발생할 수 있습니다.&lt;/b&gt;&lt;br /&gt;Provider의 value가 바뀌면 하위의 모든 Consumer가 다시 렌더링됩니다. 이를 방지하려면 useMemo 등을 활용해서 value가 불필요하게 바뀌지 않도록 관리해야 합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;모든 상태를 Context로 관리할 필요는 없습니다.&lt;/b&gt;&lt;br /&gt;컴포넌트 간 깊이가 깊지 않거나 단방향으로만 전달되면, props가 더 명확하고 효율적일 수 있습니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;5. 여러 개의 Context 사용하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여러 종류의 전역 상태를 관리해야 할 때는 Context를 분리해서 사용하는 것이 좋습니다. 예를 들어 로그인 정보, 언어 설정, 테마 등을 각각 따로 관리할 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;xml&quot;&gt;&lt;code&gt;&amp;lt;AuthContext.Provider value={user}&amp;gt;
  &amp;lt;LanguageContext.Provider value={lang}&amp;gt;
    &amp;lt;ThemeContext.Provider value={theme}&amp;gt;
      &amp;lt;App /&amp;gt;
    &amp;lt;/ThemeContext.Provider&amp;gt;
  &amp;lt;/LanguageContext.Provider&amp;gt;
&amp;lt;/AuthContext.Provider&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 중첩 구조를 만들 수도 있지만, 지나치게 많아지면 &lt;b&gt;Context nesting&lt;/b&gt; 문제가 생기므로 주의해야 합니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;6. 마무리하며&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Context API는 전역 상태를 간단하게 관리할 수 있도록 도와주는 매우 유용한 기능입니다.&lt;br /&gt;하지만 &lt;b&gt;무분별한 사용은 오히려 유지보수를 어렵게 만들 수 있기 때문에&lt;/b&gt;, props로 해결 가능한 경우는 그대로 두고, &lt;b&gt;진짜 전역이 필요한 경우에만&lt;/b&gt; Context를 도입하는 것이 좋습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금까지 React Context API에 대해 정리해보았습니다. 직접 예제를 만들어보면서 감을 익혀보는 걸 추천드립니다.&lt;/p&gt;</description>
      <category>FrontEnd/React</category>
      <author>yuvnn</author>
      <guid isPermaLink="true">https://yuvnn.tistory.com/8</guid>
      <comments>https://yuvnn.tistory.com/entry/React-Context-API#entry8comment</comments>
      <pubDate>Tue, 20 May 2025 19:13:08 +0900</pubDate>
    </item>
    <item>
      <title>[React] Controlled Components, Lifting State Up, Composition vs Inheritance</title>
      <link>https://yuvnn.tistory.com/entry/React-Controlled-Components-Lifting-State-Up-Composition-vs-Inheritance</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;&lt;b&gt;☁️충북대 구름톤 유니브 4기&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. React의 Form&lt;/h2&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1.1 Controlled Components&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;값이 React의 state에 의해 제어되는 폼 요소를 말합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1429&quot; data-origin-height=&quot;706&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bdwB8J/btsNTBRHT8q/k312ogrmt0Tkv11RPKG0v0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bdwB8J/btsNTBRHT8q/k312ogrmt0Tkv11RPKG0v0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bdwB8J/btsNTBRHT8q/k312ogrmt0Tkv11RPKG0v0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbdwB8J%2FbtsNTBRHT8q%2Fk312ogrmt0Tkv11RPKG0v0%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;1429&quot; height=&quot;706&quot; data-origin-width=&quot;1429&quot; data-origin-height=&quot;706&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1.1.1 예시&lt;/h4&gt;
&lt;pre class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;// input 태그
&amp;lt;input type=&quot;text&quot; value={value} onChange={handleChange} /&amp;gt;

// textarea 태그
&amp;lt;textarea value={value} onChange={handleChange} /&amp;gt;

// select 태그
&amp;lt;select value={value} onChange={handleChange}&amp;gt;
  &amp;lt;option value=&quot;apple&quot;&amp;gt;사과&amp;lt;/option&amp;gt;
  &amp;lt;option value=&quot;banana&quot;&amp;gt;바나나&amp;lt;/option&amp;gt;
  &amp;lt;option value=&quot;grape&quot;&amp;gt;포도&amp;lt;/option&amp;gt;
  &amp;lt;option value=&quot;watermelon&quot;&amp;gt;수박&amp;lt;/option&amp;gt;
&amp;lt;/select&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1.2 textarea 태그&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;긴 텍스트 입력을 받기 위한 태그입니다.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;import React, { useState } from 'react';

function RequestForm() {
  const [value, setValue] = useState('요청사항을 입력하세요.');

  const handleChange = (event) =&amp;gt; {
    setValue(event.target.value);
  };

  const handleSubmit = (event) =&amp;gt; {
    alert('입력한 요청사항: ' + value);
    event.preventDefault();
  };

  return (
    &amp;lt;form onSubmit={handleSubmit}&amp;gt;
      &amp;lt;label&amp;gt;
        요청사항:
        &amp;lt;textarea value={value} onChange={handleChange} /&amp;gt;
      &amp;lt;/label&amp;gt;
      &amp;lt;button type=&quot;submit&quot;&amp;gt;제출&amp;lt;/button&amp;gt;
    &amp;lt;/form&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1.3 select 태그&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;드롭다운 형태로 옵션을 선택할 수 있는 태그입니다.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;import React, { useState } from 'react';

function FruitSelect() {
  const [selectedFruit, setSelectedFruit] = useState('grape');

  const handleChange = (event) =&amp;gt; {
    setSelectedFruit(event.target.value);
  };

  return (
    &amp;lt;form&amp;gt;
      &amp;lt;label&amp;gt;
        과일 선택:
        &amp;lt;select value={selectedFruit} onChange={handleChange}&amp;gt;
          &amp;lt;option value=&quot;apple&quot;&amp;gt;사과&amp;lt;/option&amp;gt;
          &amp;lt;option value=&quot;banana&quot;&amp;gt;바나나&amp;lt;/option&amp;gt;
          &amp;lt;option value=&quot;grape&quot;&amp;gt;포도&amp;lt;/option&amp;gt;
          &amp;lt;option value=&quot;watermelon&quot;&amp;gt;수박&amp;lt;/option&amp;gt;
        &amp;lt;/select&amp;gt;
      &amp;lt;/label&amp;gt;
      &amp;lt;p&amp;gt;선택한 과일: {selectedFruit}&amp;lt;/p&amp;gt;
    &amp;lt;/form&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1.3.1 다중 선택 예시&lt;/h4&gt;
&lt;pre class=&quot;xml&quot;&gt;&lt;code&gt;&amp;lt;select multiple={true} value={selectedOptions} onChange={handleChange} /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;const selected = Array.from(event.target.selectedOptions, (option) =&amp;gt; option.value);
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1.4 file input 태그&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자가 파일을 선택할 수 있도록 하는 태그입니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;파일 입력은 읽기 전용으로, &lt;b&gt;uncontrolled component&lt;/b&gt;입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;import React, { useState } from 'react';

function FileUploadExample() {
  const [fileName, setFileName] = useState('');

  const handleFileChange = (event) =&amp;gt; {
    const file = event.target.files[0];
    if (file) {
      setFileName(file.name);
    }
  };

  return (
    &amp;lt;form&amp;gt;
      &amp;lt;label&amp;gt;
        파일 업로드:
        &amp;lt;input type=&quot;file&quot; onChange={handleFileChange} /&amp;gt;
      &amp;lt;/label&amp;gt;
      &amp;lt;p&amp;gt;선택된 파일: {fileName}&amp;lt;/p&amp;gt;
    &amp;lt;/form&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1.5 여러 개의 상태 선언 및 입력 처리&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여러 입력 필드가 있을 경우, 각각의 useState를 사용하여 상태를 관리합니다.&lt;/p&gt;
&lt;pre class=&quot;stata&quot;&gt;&lt;code&gt;import React, { useState } from 'react';

function Reservation() {
  const [haveBreakfast, setHaveBreakfast] = useState(true);
  const [numberOfGuest, setNumberOfGuest] = useState(2);

  const handleSubmit = (event) =&amp;gt; {
    alert(`아침식사 여부: ${haveBreakfast}, 방문객 수: ${numberOfGuest}`);
    event.preventDefault();
  };

  return (
    &amp;lt;form onSubmit={handleSubmit}&amp;gt;
      &amp;lt;label&amp;gt;
        아침식사 여부:
        &amp;lt;input
          type=&quot;checkbox&quot;
          checked={haveBreakfast}
          onChange={(e) =&amp;gt; setHaveBreakfast(e.target.checked)}
        /&amp;gt;
      &amp;lt;/label&amp;gt;
      &amp;lt;br /&amp;gt;
      &amp;lt;label&amp;gt;
        방문객 수:
        &amp;lt;input
          type=&quot;number&quot;
          value={numberOfGuest}
          onChange={(e) =&amp;gt; setNumberOfGuest(e.target.value)}
        /&amp;gt;
      &amp;lt;/label&amp;gt;
      &amp;lt;br /&amp;gt;
      &amp;lt;button type=&quot;submit&quot;&amp;gt;제출&amp;lt;/button&amp;gt;
    &amp;lt;/form&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1.6 input에 null을 넘기면?&lt;/h3&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;&amp;lt;input value={null} /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;value={null}을 설정하면 React는 해당 input을 &lt;b&gt;uncontrolled component&lt;/b&gt;로 간주합니다.&lt;/li&gt;
&lt;li&gt;이후에는 사용자가 자유롭게 입력할 수 있게 됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. Lifting State Up&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여러 컴포넌트가 &lt;b&gt;같은 상태를 공유&lt;/b&gt;해야 할 경우, 상태를 공통 부모 컴포넌트로 끌어올립니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1420&quot; data-origin-height=&quot;718&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/emwgs3/btsNUcqsthb/0Hu1jdOEbEpI99Fnkb3rEk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/emwgs3/btsNUcqsthb/0Hu1jdOEbEpI99Fnkb3rEk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/emwgs3/btsNUcqsthb/0Hu1jdOEbEpI99Fnkb3rEk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Femwgs3%2FbtsNUcqsthb%2F0Hu1jdOEbEpI99Fnkb3rEk%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;1420&quot; height=&quot;718&quot; data-origin-width=&quot;1420&quot; data-origin-height=&quot;718&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre class=&quot;fortran&quot;&gt;&lt;code&gt;function Parent() {
  const [value, setValue] = useState('');

  return (
    &amp;lt;&amp;gt;
      &amp;lt;ChildA value={value} onChange={setValue} /&amp;gt;
      &amp;lt;ChildB value={value} /&amp;gt;
    &amp;lt;/&amp;gt;
  );
}

function ChildA({ value, onChange }) {
  return (
    &amp;lt;input value={value} onChange={(e) =&amp;gt; onChange(e.target.value)} /&amp;gt;
  );
}

function ChildB({ value }) {
  return &amp;lt;p&amp;gt;입력값: {value}&amp;lt;/p&amp;gt;;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2.1 언제 써야 할까?&lt;/h3&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;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. Composition vs Inheritance&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1417&quot; data-origin-height=&quot;754&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yT1pH/btsNTHqGrFC/bTDn2OL10HHbBJGW77gw00/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yT1pH/btsNTHqGrFC/bTDn2OL10HHbBJGW77gw00/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yT1pH/btsNTHqGrFC/bTDn2OL10HHbBJGW77gw00/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FyT1pH%2FbtsNTHqGrFC%2FbTDn2OL10HHbBJGW77gw00%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;1417&quot; height=&quot;754&quot; data-origin-width=&quot;1417&quot; data-origin-height=&quot;754&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;React는 상속보다 &lt;b&gt;합성(Composition)&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;3.1 Composition&lt;span&gt; - &lt;/span&gt;Containment&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하위 컴포넌트를 포함하는 형태의 합성 방법&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;sidebar, dialog 같은 box형태의 컴포넌트는 자신의 하위 컴포넌트를 미리 알 수 없다.&lt;/li&gt;
&lt;li&gt;childen 이라는 props를 사용해서 조합.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;function SplitPane(props) {
  return (
    &amp;lt;div className=&quot;SplitPane&quot;&amp;gt;
      &amp;lt;div className=&quot;SplitPane-left&quot;&amp;gt;{props.left}&amp;lt;/div&amp;gt;
      &amp;lt;div className=&quot;SplitPane-right&quot;&amp;gt;{props.right}&amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}

function App() {
  return (
    &amp;lt;SplitPane left={&amp;lt;Contacts /&amp;gt;} right={&amp;lt;Chat /&amp;gt;} /&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3.2 Composition - Specialization&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;범용적인 개념을 구별이 되도록 구체화하는 것&lt;/p&gt;
&lt;/blockquote&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;pre class=&quot;javascript&quot;&gt;&lt;code&gt;function Dialog(props) {
  return (
    &amp;lt;FancyBorder color=&quot;blue&quot;&amp;gt;
      &amp;lt;h1 className=&quot;Dialog-title&quot;&amp;gt;{props.title}&amp;lt;/h1&amp;gt;
      &amp;lt;p className=&quot;Dialog-message&quot;&amp;gt;{props.message}&amp;lt;/p&amp;gt;
    &amp;lt;/FancyBorder&amp;gt;
  );
}

function WelcomeDialog() {
  return (
    &amp;lt;Dialog
      title=&quot;어서 오세요&quot;
      message=&quot;우리 사이트에 방문하신 것을 환영합니다!&quot;
    /&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3.3 상속보다 합성을 추천하는 이유&lt;/h3&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;필요한 컴포넌트들을 조합해서 유연하게 UI를 구성할 수 있기 때문입니다.&lt;/li&gt;
&lt;li&gt;&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>FrontEnd/React</category>
      <author>yuvnn</author>
      <guid isPermaLink="true">https://yuvnn.tistory.com/7</guid>
      <comments>https://yuvnn.tistory.com/entry/React-Controlled-Components-Lifting-State-Up-Composition-vs-Inheritance#entry7comment</comments>
      <pubDate>Mon, 12 May 2025 11:43:18 +0900</pubDate>
    </item>
    <item>
      <title>[React] useState와 useEffect</title>
      <link>https://yuvnn.tistory.com/entry/React-useState%EC%99%80-useEffect</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;React에서 함수형 컴포넌트를 사용할 때 상태 관리와 생명주기 관리가 필요하다면? 바로 &lt;b&gt;Hook&lt;/b&gt;을 사용해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글에서는 가장 기본이자 필수인 Hook인 useState와 useEffect의 개념과 사용법, 그리고 주의할 점까지 정리해보겠습니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. useState()&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴포넌트에서 상태(state)를 관리하기 위한 Hook&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;✅ 기본 문법&lt;/h3&gt;
&lt;pre class=&quot;actionscript&quot;&gt;&lt;code&gt;const [변수명, set함수명] = useState(초기값);
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  예시&lt;/h3&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;import React, { useState } from &quot;react&quot;;

function Counter() {
  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;/div&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&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;숫자 증가/감소 카운터 만들 때&lt;/li&gt;
&lt;li&gt;폼 입력 상태 관리할 때&lt;/li&gt;
&lt;li&gt;토글 상태 관리할 때 (예: on/off, show/hide)&lt;/li&gt;
&lt;/ul&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;상태가 변경되면 컴포넌트가 &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;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;setCount(prevCount =&amp;gt; prevCount + 1);
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. useEffect()&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴포넌트에서 Side Effect(부수 효과)를 처리하기 위한 Hook&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  Side Effect란?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;렌더링 외의 작업으로, 컴포넌트 외부(브라우저, 서버 등)에 영향을 주는 작업들을 말합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;API 요청 (fetch 등)&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;h3 data-ke-size=&quot;size23&quot;&gt;✅ 기본 문법&lt;/h3&gt;
&lt;pre class=&quot;arcade&quot;&gt;&lt;code&gt;useEffect(() =&amp;gt; {
  // 실행할 코드
  return () =&amp;gt; {
    // cleanup 함수 (선택 사항)
  };
}, [의존성1, 의존성2]);
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  예시&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;예시1. API요청 ( 특정 유저가 온라인인지 아닌지를 구독)&lt;/h4&gt;
&lt;pre class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;import React, { useState, useEffect } from &quot;react&quot;;

function UserStatus({ user }) {
	//사용자의 현재 상태(온라인/오프라인) 를 저장하기 위한 상태 변수
  const [isOnline, setIsOnline] = useState(null); 
  
  useEffect(() =&amp;gt; {
    function handleStatusChange(status) {
      setIsOnline(status.isOnline);
    }
    
  //해당 유저의 온라인 상태를 실시간으로 구독함
    ServerAPI.subscribeUserStatus(user.id, handleStatusChange);
    
    return () =&amp;gt; {
      ServerAPI.unsubscribeUserStatus(user.id, handleStatusChange);
    };
  }, [user.id]);

  if (isOnline === null) return &quot;대기 중...&quot;;
  return isOnline ? &quot;온라인&quot; : &quot;오프라인&quot;;
}&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;예시2. 타이머&lt;/h4&gt;
&lt;pre id=&quot;code_1744245531322&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React, { useState, useEffect } from &quot;react&quot;;

function Timer() {
  const [seconds, setSeconds] = useState(0);

  useEffect(() =&amp;gt; {
    const timer = setInterval(() =&amp;gt; {
      setSeconds(prev =&amp;gt; prev + 1); // 상태 업데이트
    }, 1000);

    return () =&amp;gt; clearInterval(timer); // 언마운트 시 타이머 정리
  }, []);

  return &amp;lt;div&amp;gt;{seconds}초&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;h4 data-ke-size=&quot;size20&quot;&gt;예시2-1. 타이머 잘못된 예시&lt;/h4&gt;
&lt;pre id=&quot;code_1744245514098&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React, { useState, useEffect } from &quot;react&quot;;

function Timer() {
  const [seconds, setSeconds] = useState(0);
  
  const timer = setInterval(() =&amp;gt; {
    setSeconds(prev =&amp;gt; prev + 1); // 상태 업데이트
  }, 1000);

  return &amp;lt;div&amp;gt;{seconds}초&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-end=&quot;285&quot; data-start=&quot;245&quot; data-ke-size=&quot;size16&quot;&gt;⚠️ 그런데 React 컴포넌트는 상태가 바뀌면 다시 렌더링됩니다.&lt;/p&gt;
&lt;p data-end=&quot;316&quot; data-start=&quot;286&quot; data-ke-size=&quot;size16&quot;&gt;다시 렌더링되면 Timer() 함수가 또 실행되죠.&lt;/p&gt;
&lt;p data-end=&quot;329&quot; data-start=&quot;318&quot; data-ke-size=&quot;size16&quot;&gt;그럼 어떻게 될까요?&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;445&quot; data-start=&quot;331&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;373&quot; data-start=&quot;331&quot;&gt;매 렌더링마다 setInterval()이 &lt;b&gt;계속해서 새로 실행&lt;/b&gt;됨&lt;/li&gt;
&lt;li data-end=&quot;407&quot; data-start=&quot;374&quot;&gt;즉, &lt;b&gt;1초마다 증가하는 게 아니라, 점점 빨라짐!&lt;/b&gt;&lt;/li&gt;
&lt;li data-end=&quot;445&quot; data-start=&quot;408&quot;&gt;결국 메모리에 쌓이고, 브라우저가 느려지고, 원하는 동작이 아님&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;그래서 useEffect를 사용해서 &lt;b&gt;한 번만&lt;/b&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt; setInterval()을 설정할 수 있도록 하는 것!&lt;/span&gt;&lt;/u&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;h3 data-ke-size=&quot;size23&quot;&gt;  의존성 배열 (dependency array) 설명&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;[]: 컴포넌트 &lt;b&gt;mount/unmount 시 단 1번만 실행&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;/ul&gt;
&lt;pre class=&quot;coffeescript&quot;&gt;&lt;code&gt;useEffect(() =&amp;gt; {
  console.log(&quot;매 렌더링마다 실행&quot;);
});

useEffect(() =&amp;gt; {
  console.log(&quot;처음 한 번만 실행&quot;);
}, []);

useEffect(() =&amp;gt; {
  console.log(&quot;특정 값 변경될 때 실행&quot;);
}, [count]);
&lt;/code&gt;&lt;/pre&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;의존성 배열을 정확하게 설정하지 않으면 &lt;b&gt;불필요한 렌더링&lt;/b&gt; 또는 &lt;b&gt;버그&lt;/b&gt;가 발생할 수 있음&lt;/li&gt;
&lt;li&gt;비동기 함수(async)는 useEffect 바로 안에서 사용할 수 없음 &amp;rarr; &lt;b&gt;즉시 실행 함수(IIFE)&lt;/b&gt;나 별도 함수로 처리해야 함&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;useEffect(() =&amp;gt; {
  async function fetchData() {
    const res = await fetch(&quot;/api/data&quot;);
    const json = await res.json();
    console.log(json);
  }
  fetchData();
}, []);
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. 정리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Hook 역할 사용 시점 주의할 점&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;useState&lt;/td&gt;
&lt;td&gt;상태 관리&lt;/td&gt;
&lt;td&gt;상태가 필요한 모든 컴포넌트&lt;/td&gt;
&lt;td&gt;set함수 호출 시 렌더링 발생&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;useEffect&lt;/td&gt;
&lt;td&gt;부수 효과 처리&lt;/td&gt;
&lt;td&gt;API 호출, 타이머, 구독 등 필요할 때&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;</description>
      <category>FrontEnd/React</category>
      <author>yuvnn</author>
      <guid isPermaLink="true">https://yuvnn.tistory.com/6</guid>
      <comments>https://yuvnn.tistory.com/entry/React-useState%EC%99%80-useEffect#entry6comment</comments>
      <pubDate>Thu, 10 Apr 2025 10:10:15 +0900</pubDate>
    </item>
    <item>
      <title>[React] REACT란? / JSX란? / Element란?</title>
      <link>https://yuvnn.tistory.com/entry/React-REACT%EB%9E%80-JSX%EB%9E%80-Element%EB%9E%80</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #7e98b1;&quot;&gt;&lt;b&gt;* 충북대 구름톤 유니브 FE스터디 필기노트&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h1&gt;REACT란?&lt;/h1&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Javascript&amp;nbsp;UI&amp;nbsp;라이브러리&lt;/p&gt;
&lt;/blockquote&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;h2 data-ke-size=&quot;size26&quot;&gt;장점&lt;/h2&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;virtual DOM&lt;/b&gt; 을 사용 &amp;rarr; &lt;b&gt;빠른 업데이트&lt;/b&gt; &amp;amp; 렌더링 속도 *&lt;b&gt;DOM&lt;/b&gt; (Document object model) : 웹 페이지를 정의하는 하나의 객체&lt;/li&gt;
&lt;li&gt;&lt;b&gt;component-based&lt;/b&gt; &amp;rarr; &lt;b&gt;재사용성&lt;/b&gt; (Reusability)
&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;/li&gt;
&lt;li&gt;React native &amp;rarr; 앱 개발도 가능&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;단점&lt;/h2&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;버전 업데이트 &amp;rarr; 뭔가 계속 바뀜&amp;hellip; 개발자의 숙명임&lt;/li&gt;
&lt;li&gt;높은 상태관리 복잡도&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;리액트 연동하는 법&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 일반 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 기존 html에 &lt;b&gt;dom container&lt;/b&gt; 추가 (Root DOM node)&lt;/p&gt;
&lt;pre id=&quot;code_1743664637817&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;div id=&quot;root&quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2.&amp;nbsp;리액트 가져오기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 리액트 컴포넌트 가져오기&lt;/p&gt;
&lt;pre id=&quot;code_1743664619570&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;body&amp;gt;
    &amp;lt;div id=&quot;root&quot;&amp;gt;&amp;lt;/div&amp;gt;

    &amp;lt;!-- 리액트 가져오기 --&amp;gt;
    &amp;lt;script src=&quot;https://unpkg.com/react@17/umd/react.development.js&quot; crossorigin&amp;gt;&amp;lt;/script&amp;gt;
    &amp;lt;script src=&quot;https://unpkg.com/react-dom@17/umd/react-dom.development.js&quot; crossorigin&amp;gt;&amp;lt;/script&amp;gt;

    &amp;lt;!-- 리액트 컴포넌트 가져오기 --&amp;gt;
    &amp;lt;script src=&quot;MyButton.js&quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;/body&amp;gt;&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;2. create-react-app (편리한 방법)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;필요
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;node.js 14.0.0이상&lt;/li&gt;
&lt;li&gt;npm v6.14.0 이상&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;npx명령어로 실행&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1743664723911&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;npx create-react-app mypjt
cd mypjt
npm start&lt;/code&gt;&lt;/pre&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;h1&gt;JSX란?&lt;/h1&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JavaSciprt + XML/HTML&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;REACT에서는 &lt;b&gt;React.createElement()&lt;/b&gt; 함수를 통해 JSX를 JS로 변환
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&amp;nbsp;&lt;b&gt;React.createElement() : 자바 스트립트 객체 생성&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;JSX는 JS보다 더 간결하고 가독성이 높음&lt;/b&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;장점 (JS 아닌 JSX 권장하는 이유)&lt;/h2&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;Injection Attacks 방어&lt;/li&gt;
&lt;/ol&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;중간에 &lt;b&gt;JS사용하고 싶으면 {}(중괄호)&lt;/b&gt; 로 묶어줌
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;태그의 속성(attribute)에 값을 넣는 등&amp;hellip;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;HTML 대입 하며 사용
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;children 정의 등.. html 문법을 따름&lt;/li&gt;
&lt;/ul&gt;
&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;h1&gt;Elements란?&lt;/h1&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리액트 앱을 구성하는 가장 작은 블록들&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;element는 화면에서 보이는 것들을 기술함&lt;/li&gt;
&lt;li&gt;react element는 자바스크립트 객체 형태로 존재&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1743665678502&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;React.crateElement(
	type,
    [props],
    [...children]
)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;type: &lt;b&gt;html&lt;/b&gt; or &lt;b&gt;react component&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;props: element의 속성&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;children: element의 자식&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;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;immutable (불변성)
&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;에는 children 이나 attributes를 바꿀 수 없다&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;새로운 element를 만들어 기존 element가 연결되어 있는 부분에 달면 됨&lt;/li&gt;
&lt;li&gt;state change &amp;rarr; compute diff &amp;rarr; re-render&lt;/li&gt;
&lt;li&gt;&lt;b&gt;re-render (얼마나 자주 갱신) 성능에 큰 영향을 줌 !&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/ol&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;element rendering&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;최상단 노드에 rendering&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1284&quot; data-origin-height=&quot;722&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tLVib/btsM8d5b0YL/u5pSw9RRu0ilmHiEgL3te1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tLVib/btsM8d5b0YL/u5pSw9RRu0ilmHiEgL3te1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tLVib/btsM8d5b0YL/u5pSw9RRu0ilmHiEgL3te1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtLVib%2FbtsM8d5b0YL%2Fu5pSw9RRu0ilmHiEgL3te1%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;453&quot; height=&quot;722&quot; data-origin-width=&quot;1284&quot; data-origin-height=&quot;722&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #d44c47;&quot; data-token-index=&quot;0&quot;&gt;reactDOM에서 rendering 하는 과정 === 가상돔 &amp;rarr; 실제돔으로 이동!&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot; data-token-index=&quot;0&quot;&gt;e.g.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1743665952925&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const element = &amp;lt;h1&amp;gt; 안녕, 리액트! &amp;lt;/h1&amp;gt;
ReactDOM.render(element, document.getElementById('root'));&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>FrontEnd/React</category>
      <author>yuvnn</author>
      <guid isPermaLink="true">https://yuvnn.tistory.com/5</guid>
      <comments>https://yuvnn.tistory.com/entry/React-REACT%EB%9E%80-JSX%EB%9E%80-Element%EB%9E%80#entry5comment</comments>
      <pubDate>Thu, 3 Apr 2025 16:39:42 +0900</pubDate>
    </item>
    <item>
      <title>엑셀에서 구글 드라이브 링크로 이미지 일괄 다운하는 법 (원하는 이름으로 다운 가능) - requeset라이브러리 / gdown라이브러리</title>
      <link>https://yuvnn.tistory.com/entry/%EC%97%91%EC%85%80%EC%97%90%EC%84%9C-%EA%B5%AC%EA%B8%80-%EB%93%9C%EB%9D%BC%EC%9D%B4%EB%B8%8C-%EB%A7%81%ED%81%AC%EB%A1%9C-%EC%9D%BC%EA%B4%84-%EB%8B%A4%EC%9A%B4%ED%95%98%EB%8A%94-%EB%B2%95-%EC%9B%90%ED%95%98%EB%8A%94-%EC%9D%B4%EB%A6%84%EC%9C%BC%EB%A1%9C-%EB%8B%A4%EC%9A%B4-%EA%B0%80%EB%8A%A5-requeset%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC-gdown%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;서론&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;동아리 임원직을 맡게 되면서,&lt;br /&gt;구글폼에 작성된 사진 데이터를 일괄적으로 다운로드 해야하는 일이 생겼다.&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;허나 구글 드라이브에 들어가보면 파일명 이름이 다 제각각이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;163&quot; data-origin-height=&quot;144&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cuL8lZ/btsMYJxj1Cd/UeAfk87vEGP6VG8eDoGIvk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cuL8lZ/btsMYJxj1Cd/UeAfk87vEGP6VG8eDoGIvk/img.png&quot; data-alt=&quot;이런식으로 제각각&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cuL8lZ/btsMYJxj1Cd/UeAfk87vEGP6VG8eDoGIvk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcuL8lZ%2FbtsMYJxj1Cd%2FUeAfk87vEGP6VG8eDoGIvk%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;163&quot; height=&quot;144&quot; data-origin-width=&quot;163&quot; data-origin-height=&quot;144&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;br /&gt;나는 '{성명}_학생증.png'이런 형식으로&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;이름을 통일하여 다운받고 싶었기에 &lt;/b&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;b&gt;쉬운 일괄 다운로드 방법을 찾아 헤매었다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여러분들은 시간낭비 하지마시라고 방법을 공유한다.&lt;br /&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;(그냥 이름 상관없이 다운로드만 하고 싶으면 아래 링크처럼 더 쉬운 방법이 많다)&lt;/span&gt;&lt;br /&gt;&lt;a href=&quot;http://xn--comfortable1000-jr85d.tistory.com/17&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;http://xn--comfortable1000-jr85d.tistory.com/17&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;엑셀에서&amp;nbsp;구글&amp;nbsp;드라이브&amp;nbsp;링크로&amp;nbsp;일괄&amp;nbsp;다운하는&amp;nbsp;법&amp;nbsp;&lt;/h2&gt;
&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;widthOrigin&quot; data-origin-width=&quot;803&quot; data-origin-height=&quot;124&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lSUI9/btsMYo1n8fE/dB4L34TQ34Q1xOwDQ3YYek/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lSUI9/btsMYo1n8fE/dB4L34TQ34Q1xOwDQ3YYek/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lSUI9/btsMYo1n8fE/dB4L34TQ34Q1xOwDQ3YYek/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlSUI9%2FbtsMYo1n8fE%2FdB4L34TQ34Q1xOwDQ3YYek%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;803&quot; height=&quot;124&quot; data-origin-width=&quot;803&quot; data-origin-height=&quot;124&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: center;&quot;&gt; &lt;b&gt;sheets에서 보기&lt;/b&gt;에서 확인 가능 &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1293&quot; data-origin-height=&quot;63&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bOaZ4C/btsMYxcHASq/dKMZU9pa6puE5UbDc1QO6K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bOaZ4C/btsMYxcHASq/dKMZU9pa6puE5UbDc1QO6K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bOaZ4C/btsMYxcHASq/dKMZU9pa6puE5UbDc1QO6K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbOaZ4C%2FbtsMYxcHASq%2FdKMZU9pa6puE5UbDc1QO6K%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;1293&quot; height=&quot;63&quot; data-origin-width=&quot;1293&quot; data-origin-height=&quot;63&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기 이 구글스프레드 시트데이터를&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;481&quot; data-origin-height=&quot;67&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/XEvdy/btsMZkjvMsy/zDc4GZ1ZGKItmUkVg0su9k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/XEvdy/btsMZkjvMsy/zDc4GZ1ZGKItmUkVg0su9k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/XEvdy/btsMZkjvMsy/zDc4GZ1ZGKItmUkVg0su9k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FXEvdy%2FbtsMZkjvMsy%2FzDc4GZ1ZGKItmUkVg0su9k%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;481&quot; height=&quot;67&quot; data-origin-width=&quot;481&quot; data-origin-height=&quot;67&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런식으로 주르륵 옮겨주세요&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. 구글 드라이브 엑세스 권한 풀기&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;818&quot; data-origin-height=&quot;314&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kAykk/btsMZs9AMgI/fpimiSIjEAmwYNC9NVxzM1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kAykk/btsMZs9AMgI/fpimiSIjEAmwYNC9NVxzM1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kAykk/btsMZs9AMgI/fpimiSIjEAmwYNC9NVxzM1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkAykk%2FbtsMZs9AMgI%2FfpimiSIjEAmwYNC9NVxzM1%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;818&quot; height=&quot;314&quot; data-origin-width=&quot;818&quot; data-origin-height=&quot;314&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt; 오른쪽 하단 &lt;b&gt;폴더 보기&lt;/b&gt;에서 사진 전체 확인 가능&lt;/span&gt;&lt;br /&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;811&quot; data-origin-height=&quot;356&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b2MnLl/btsMX0fueSv/gKym36hKvOFu14dbbEos3K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b2MnLl/btsMX0fueSv/gKym36hKvOFu14dbbEos3K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b2MnLl/btsMX0fueSv/gKym36hKvOFu14dbbEos3K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb2MnLl%2FbtsMX0fueSv%2FgKym36hKvOFu14dbbEos3K%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;811&quot; height=&quot;356&quot; data-origin-width=&quot;811&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;br /&gt;구글 드라이브에 들어가서&lt;br /&gt;ctrl+a로 전체 선택 후&lt;br /&gt;다음 사진처럼 &lt;b&gt;점 세게 &amp;gt; 공유 &amp;gt; 공유&lt;/b&gt;&lt;br /&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;869&quot; data-origin-height=&quot;118&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/STkDi/btsMZaH6bco/FMOuVRC66W3K47WNsMljaK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/STkDi/btsMZaH6bco/FMOuVRC66W3K47WNsMljaK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/STkDi/btsMZaH6bco/FMOuVRC66W3K47WNsMljaK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FSTkDi%2FbtsMZaH6bco%2FFMOuVRC66W3K47WNsMljaK%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;869&quot; height=&quot;118&quot; data-origin-width=&quot;869&quot; data-origin-height=&quot;118&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br /&gt;일반 액세스를 '링크가 있는 모든 사용자'로 바꾸어&lt;br /&gt;사진에 대한 권한을 일괄적으로 열어줌&lt;br /&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. 코드 실행&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 자기 상황에 맞춰서 &lt;br /&gt;경로, 파일 이름등의 변수 설정하고 코드 돌리면 됩니다.&lt;br /&gt;&amp;nbsp;&lt;br /&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;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href=&quot;https://drive.google.com/open?id=16Jzh3iTMuNho-p8QyCFmQ8X7DQqv2i6S&quot; target=&quot;_self&quot;&gt;&lt;span&gt;https://drive.google.com/open?id=xxxxx&lt;/span&gt;&lt;/a&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;다운이 가능한&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;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href=&quot;https://drive.google.com/open?id=xxxxx&quot; target=&quot;_self&quot;&gt;&lt;span&gt;https://drive.google.com/uc?id=xxxxx&lt;/span&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 형태로 바꾸어 다운로드를 받고 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;링크의 구조 따라 알맞게 수정하여 실행하세요&lt;br /&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드는 어떤 라이브러리를 사용하느냐에 따라 두가지 방법이 있음. (gdown라이브러리 or request라이브러리)&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;&lt;b&gt;설치 귀찮으면 request , 설치하더라도 다운로드 진행사항 보고 싶으면 gdown&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;다만 request 방식에서&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Google Drive는 일정 시간 동안 너무 많은 요청이 들어오면&lt;span&gt;&amp;nbsp;&lt;/span&gt;일시적으로 오류가 발생할 수 있기 때문에, &lt;/b&gt;&lt;br /&gt;&lt;b&gt;일정 시간이 지나야 다시 다운로드 가능합니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;gdown방식은 Google Drive 공유 설정을&amp;nbsp; '공개'로 변경하고 진행하세요.&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;3-1. gdown라이브러리&lt;/h3&gt;
&lt;pre class=&quot;python&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;import pandas as pd
import gdown
import os

'''
여기를 자신의 상황에 맞게 바꾸세요
'''
file_path = ''&amp;nbsp;&amp;nbsp;# 엑셀 파일 경로
sheet_name = ''&amp;nbsp;&amp;nbsp;# 엑셀 시트 이름
save_folder = '' # 사진 저장 경로
output_filename = '' #저장 시 이름 (밑에서 행에 따라 다르게 저장도 가능)

df = pd.read_excel(file_path, sheet_name=sheet_name)
if not os.path.exists(save_folder):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;os.makedirs(save_folder)

for index, row in df.iterrows():
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;name = row['성명']
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;file_url = row['사진']

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;# 'id=' 이후 부분이 파일 ID
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;file_id = file_url.split('id=')[-1]&amp;nbsp;&amp;nbsp;

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;# Google Drive에서 다운로드 링크 생성
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;download_url = f'https://drive.google.com/uc?id={file_id}'
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if file_id:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;# output_filename = f&quot;{name}_모바일 학생증.jpg&quot; #여기서 행에 따라 다르게 변경도 가능
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;output_path = os.path.join(save_folder, output_filename)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;try:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;gdown.download(download_url, output_path, quiet=False)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&quot;✅ {output_filename} 다운로드 완료!&quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;except Exception as e:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&quot;❌ {name}의 파일 다운로드 실패: {e}&quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&quot;❌ {name}의 유효한 구글 드라이브 링크를 찾을 수 없음.&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3-2. requeset라이브러리&lt;/h3&gt;
&lt;pre class=&quot;python&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;import pandas as pd
import os
import requests

'''
여기를 자신의 상황에 맞게 바꾸세요
'''
file_path = ''&amp;nbsp;&amp;nbsp;# 엑셀 파일 경로
sheet_name = ''&amp;nbsp;&amp;nbsp;# 엑셀 시트 이름
save_folder = ''&amp;nbsp;&amp;nbsp;# 사진 저장 경로
output_filename = '' #저장 시 이름 (밑에서 행에 따라 다르게 저장도 가능)

df = pd.read_excel(file_path, sheet_name=sheet_name)
if not os.path.exists(save_folder):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;os.makedirs(save_folder)

for index, row in df.iterrows():
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;name = row['성명'] 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;file_url = row['사진']

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;# 'id=' 이후 부분이 파일 ID
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;file_id = file_url.split('id=')[-1]&amp;nbsp;&amp;nbsp;# 'id=' 이후 부분이 파일 ID

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;# Google Drive에서 다운로드 링크 생성
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;download_url = f'https://drive.google.com/uc?id={file_id}&amp;amp;export=download'

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;save_name = f&quot;{name}_모바일 학생증.jpg&quot;&amp;nbsp;&amp;nbsp;# 저장할 파일명
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;output_filename = os.path.join(save_folder, save_name)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if file_id:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;# output_filename = f&quot;{name}_모바일 학생증.jpg&quot; #여기서 행에 따라 다르게 변경도 가능
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;output_path = os.path.join(save_folder, output_filename)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;try:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;response = requests.get(download_url)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;with open(output_filename, 'wb') as file:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;file.write(response.content)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&quot;✅ {output_filename} 다운로드 완료!&quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;except Exception as e:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&quot;❌ {name}의 파일 다운로드 실패: {e}&quot;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;print(f&quot;❌ {name}의 유효한 구글 드라이브 링크를 찾을 수 없음.&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4. 결과&lt;/h3&gt;
&lt;p 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-origin-width=&quot;576&quot; data-origin-height=&quot;132&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Dz6Nb/btsMZDRIAq9/Qtv1T0bdk9HfZ8fKxUCrJk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Dz6Nb/btsMZDRIAq9/Qtv1T0bdk9HfZ8fKxUCrJk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Dz6Nb/btsMZDRIAq9/Qtv1T0bdk9HfZ8fKxUCrJk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDz6Nb%2FbtsMZDRIAq9%2FQtv1T0bdk9HfZ8fKxUCrJk%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;576&quot; height=&quot;132&quot; data-origin-width=&quot;576&quot; data-origin-height=&quot;132&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;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>ML, Machine Learning</category>
      <author>yuvnn</author>
      <guid isPermaLink="true">https://yuvnn.tistory.com/4</guid>
      <comments>https://yuvnn.tistory.com/entry/%EC%97%91%EC%85%80%EC%97%90%EC%84%9C-%EA%B5%AC%EA%B8%80-%EB%93%9C%EB%9D%BC%EC%9D%B4%EB%B8%8C-%EB%A7%81%ED%81%AC%EB%A1%9C-%EC%9D%BC%EA%B4%84-%EB%8B%A4%EC%9A%B4%ED%95%98%EB%8A%94-%EB%B2%95-%EC%9B%90%ED%95%98%EB%8A%94-%EC%9D%B4%EB%A6%84%EC%9C%BC%EB%A1%9C-%EB%8B%A4%EC%9A%B4-%EA%B0%80%EB%8A%A5-requeset%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC-gdown%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC#entry4comment</comments>
      <pubDate>Fri, 28 Mar 2025 17:26:11 +0900</pubDate>
    </item>
    <item>
      <title>[자료구조] python 공식문서 heapq.heapify()로 알아보는 최소 힙 (min heap)의 동작</title>
      <link>https://yuvnn.tistory.com/entry/%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0-python-%EA%B3%B5%EC%8B%9D%EB%AC%B8%EC%84%9C-heapqheapify%EB%A1%9C-%EC%95%8C%EC%95%84%EB%B3%B4%EB%8A%94-%EC%B5%9C%EC%86%8C-%ED%9E%99-min-heap%EC%9D%98-%EB%8F%99%EC%9E%91</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 최소힙이란&lt;/h2&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;✅ &lt;b&gt;완전 이진 트리(Complete Binary Tree)&lt;/b&gt; 여야 함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;✅&amp;nbsp; 부모 노드가 항상 자식보다 작거나 같아야 함&lt;/b&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;652&quot; data-origin-height=&quot;560&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cd97Vi/btsMVzUJfZM/xZae9HVjLgmIk6qapqysu0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cd97Vi/btsMVzUJfZM/xZae9HVjLgmIk6qapqysu0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cd97Vi/btsMVzUJfZM/xZae9HVjLgmIk6qapqysu0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcd97Vi%2FbtsMVzUJfZM%2FxZae9HVjLgmIk6qapqysu0%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;323&quot; height=&quot;277&quot; data-origin-width=&quot;652&quot; data-origin-height=&quot;560&quot;/&gt;&lt;/span&gt;&lt;/figure&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;pos의 자식노드의 index&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;table style=&quot;border-collapse: collapse; width: 32.7907%; height: 99px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style4&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 50%; text-align: center; height: 20px;&quot;&gt;left 자식노드&lt;/td&gt;
&lt;td style=&quot;width: 46.4286%; text-align: center; height: 20px;&quot;&gt;right 자식노드&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 17px; text-align: center;&quot;&gt;&lt;b&gt;2*pos + 1&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 46.4286%; height: 17px; text-align: center;&quot;&gt;&lt;b&gt; 2*pos + 2&lt;/b&gt;&lt;br /&gt;&lt;b&gt;즉, left+1&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. python 공식문서 코드&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2-1. heapq.heapify(heap)&lt;/h3&gt;
&lt;pre id=&quot;code_1742800708278&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def heapify(x): #리스트를 힙으로 변환
    n = len(x)
    for i in reversed(range(n//2)):
        _siftup(x, i)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1782&quot; data-origin-height=&quot;634&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bH06Sd/btsMVTSWTaN/fugzq8e55bSK7cLmUcaqM0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bH06Sd/btsMVTSWTaN/fugzq8e55bSK7cLmUcaqM0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bH06Sd/btsMVTSWTaN/fugzq8e55bSK7cLmUcaqM0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbH06Sd%2FbtsMVTSWTaN%2Ffugzq8e55bSK7cLmUcaqM0%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;436&quot; height=&quot;634&quot; data-origin-width=&quot;1782&quot; data-origin-height=&quot;634&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;revesed(range(n//2))&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 style=&quot;color: #006dd7;&quot;&gt;e.g. [1,6,7,2,3,4,5] 일 때,&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;n//2 == 3&lt;/li&gt;
&lt;li&gt;즉, i=2 &amp;rarr; i=1 &amp;rarr; i=0 순서로 실행&lt;/li&gt;
&lt;/ul&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;h3 data-ke-size=&quot;size23&quot;&gt;2-2. _shiftup(heap,pos)&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;주석x + 설명&lt;/h4&gt;
&lt;pre class=&quot;python&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;def _siftup(heap, pos):
    endpos = len(heap)
    startpos = pos
    newitem = heap[pos]

    childpos = 2 * pos + 1

    while childpos &amp;lt; endpos:
        rightpos = childpos + 1
        if rightpos &amp;lt; endpos and not heap[childpos] &amp;lt; heap[rightpos]:
            childpos = rightpos

        heap[pos] = heap[childpos]
        pos = childpos
        childpos = 2 * pos + 1

    heap[pos] = newitem
    _siftdown(heap, startpos, pos)&lt;/code&gt;&lt;/pre&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;힙에서 &lt;b&gt;특정 위치(pos)&lt;/b&gt;의 요소를 선택&lt;/li&gt;
&lt;li&gt;현재 &lt;b&gt;요소의 값을 저장&lt;/b&gt;하고, 해당 위치를 기준으로 &lt;b&gt;왼쪽 자식 노드의 위치를 계산&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;자식 노드가 존재하는 동안&lt;span style=&quot;color: #9d9d9d;&quot;&gt;&lt;b&gt;(len(heap) &amp;lt; childpos)&lt;/b&gt; &lt;/span&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 style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;현재 요소를 선택한 자식 노드의 값으로 교체&lt;/b&gt;&lt;/span&gt;하고,&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt; 현재 위치를 자식 노드 위치로 이동&lt;/b&gt;&lt;/span&gt;시킨다.&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;/li&gt;
&lt;li&gt;&lt;b&gt;삽입한 요소가 부모보다 작아야 하는 경우를 대비해 _siftdown 함수&lt;/b&gt;를 호출하여 최종 위치를 조정한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1106&quot; data-origin-height=&quot;404&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/LtiOe/btsMVyIrjxM/Tp0DLQkd1PG39U2LeFx6q1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/LtiOe/btsMVyIrjxM/Tp0DLQkd1PG39U2LeFx6q1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/LtiOe/btsMVyIrjxM/Tp0DLQkd1PG39U2LeFx6q1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLtiOe%2FbtsMVyIrjxM%2FTp0DLQkd1PG39U2LeFx6q1%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;652&quot; height=&quot;238&quot; data-origin-width=&quot;1106&quot; data-origin-height=&quot;404&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;주석o&lt;/b&gt;&lt;/h4&gt;
&lt;pre class=&quot;python&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;def _siftup(heap, pos):
    &quot;&quot;&quot; 
    힙의 특정 위치(pos)에서 아래로 내려가며 적절한 위치를 찾도록 조정하는 함수.
    (부모 노드를 내려보내는 역할)

    heap: 힙 리스트
    pos: 조정을 시작할 노드의 위치
    &quot;&quot;&quot;
    
    endpos = len(heap)  # 힙의 길이 (마지막 인덱스 초과 값)
    startpos = pos  # 시작 위치 저장 (추후 _siftdown 호출을 위해)
    newitem = heap[pos]  # 현재 위치의 값 저장

    childpos = 2 * pos + 1  # 왼쪽 자식 노드의 인덱스 계산

    # 자식 노드가 존재하는 동안 반복
    while childpos &amp;lt; endpos:  
        rightpos = childpos + 1  # 오른쪽 자식 노드의 인덱스 (left + 1)

        # 오른쪽 자식이 존재하고, 왼쪽보다 작다면 오른쪽 선택
        if rightpos &amp;lt; endpos and not heap[childpos] &amp;lt; heap[rightpos]:  
            childpos = rightpos  

        # 자식 노드를 부모 위치로 이동 (부모를 아래로 내림)
        heap[pos] = heap[childpos]  
        pos = childpos  # 현재 위치를 내려간 자식 노드 위치로 변경
        childpos = 2 * pos + 1  # 새로운 왼쪽 자식 노드 위치 계산

    # 최종적으로 newitem이 들어갈 위치에 삽입
    heap[pos] = newitem  

    # 만약 newitem이 위로 올라가야 할 경우 _siftdown 호출
    _siftdown(heap, startpos, pos)&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;h3 data-ke-size=&quot;size23&quot;&gt;2-3. _shiftdown()&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;주석x + 설명&lt;/h4&gt;
&lt;pre class=&quot;hsp&quot;&gt;&lt;code&gt;def _siftdown(heap, startpos, pos): #자식 노드를 올림
    newitem = heap[pos]
    while pos &amp;gt; startpos:
        parentpos = (pos - 1) &amp;gt;&amp;gt; 1
        parent = heap[parentpos]
        if newitem &amp;lt; parent:
            heap[pos] = parent
            pos = parentpos
            continue
        break
    heap[pos] = newitem
    print('index : ',startpos,'| _shiftdown이후',heap)
&lt;/code&gt;&lt;/pre&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;현재 비교할 노드의 값을 newitem&lt;/b&gt;에 저장&lt;/li&gt;
&lt;li&gt;노드가 루트까지 도달하지 않은 경우, &lt;b&gt;부모 노드와 비교를 계속&lt;/b&gt;함&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;현재 노드가 부모 노드보다 작으면, 부모 노드를 현재 위치로 내리고, 현재 노드는 부모의 위치로 이동&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;부모와 비교하여 작은 값을 위로 올리며 반복. &lt;b&gt;부모보다 작지 않으면 비교를 종료&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;더 이상 부모와 비교할 필요가 없으면,&lt;b&gt; newitem을 최종 위치에 배치하여 완료&lt;/b&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1272&quot; data-origin-height=&quot;474&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dfmwkf/btsMUmWiKPY/AXw9k3WDbtV0zrDczqcyzK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dfmwkf/btsMUmWiKPY/AXw9k3WDbtV0zrDczqcyzK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dfmwkf/btsMUmWiKPY/AXw9k3WDbtV0zrDczqcyzK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdfmwkf%2FbtsMUmWiKPY%2FAXw9k3WDbtV0zrDczqcyzK%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;667&quot; height=&quot;249&quot; data-origin-width=&quot;1272&quot; data-origin-height=&quot;474&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;주석ｏ&lt;/h4&gt;
&lt;pre class=&quot;python&quot;&gt;&lt;code&gt;def _siftdown(heap, startpos, pos):
    ''' 
    값이 올라가야 하는 경우, 힙의 적절한 위치로 이동시키는 함수.

    heap: 힙 리스트
    startpos: 힙화 시작 위치 (부모 노드의 위치)
    pos: 조정을 시작할 노드의 위치'
    '''

    newitem = heap[pos]  # 현재 위치에 있는 값을 newitem에 저장 (나중에 위로 올릴 값)

    # pos가 startpos보다 크면, 즉 아직 루트까지 도달하지 않았다면 반복
    while pos &amp;gt; startpos:
        parentpos = (pos - 1) &amp;gt;&amp;gt; 1  # 부모 노드의 인덱스를 계산 (현재 노드의 부모는 (pos-1) // 2)
        parent = heap[parentpos]  # 부모 노드의 값

        # 만약 newitem이 부모보다 작다면, 부모 노드를 현재 위치로 내려주고 계속 비교
        if newitem &amp;lt; parent:
            heap[pos] = parent  # 부모를 현재 위치로 내림
            pos = parentpos  # 현재 위치를 부모 위치로 업데이트
            continue  # 부모와 계속 비교하여 더 이상 교환할 것이 없을 때까지 반복

        break  # 부모보다 크거나 같으면, 더 이상 내려갈 필요 없으므로 반복 종료

    heap[pos] = newitem  # 최종적으로 newitem이 들어갈 위치에 저장 (부모보다 작은 경우 위로 올라옴)
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2-4. 코드 실행화면&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1214&quot; data-origin-height=&quot;955&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/2UhXL/btsMTjzsEzR/V6WEFNAo2IWhSZt5TyFd10/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/2UhXL/btsMTjzsEzR/V6WEFNAo2IWhSZt5TyFd10/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/2UhXL/btsMTjzsEzR/V6WEFNAo2IWhSZt5TyFd10/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F2UhXL%2FbtsMTjzsEzR%2FV6WEFNAo2IWhSZt5TyFd10%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;1214&quot; height=&quot;955&quot; data-origin-width=&quot;1214&quot; data-origin-height=&quot;955&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;초기 :&amp;nbsp;&amp;nbsp;[1&lt;span style=&quot;color: #000000;&quot;&gt;, 6, 7, 2, 3, 4, 5] &lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;index&amp;nbsp;:&amp;nbsp;&amp;nbsp;2&amp;nbsp;|&amp;nbsp;_shiftup이후&amp;nbsp;[1,&amp;nbsp;6,&amp;nbsp;4,&amp;nbsp;2,&amp;nbsp;3,&amp;nbsp;7,&amp;nbsp;&lt;/span&gt;5] &lt;br /&gt;index&amp;nbsp;:&amp;nbsp;&amp;nbsp;2&amp;nbsp;|&amp;nbsp;_shiftdown이후&amp;nbsp;[1,&amp;nbsp;6,&amp;nbsp;4,&amp;nbsp;2,&amp;nbsp;3,&amp;nbsp;7,&amp;nbsp;5] &lt;br /&gt;index&amp;nbsp;:&amp;nbsp;&amp;nbsp;1&amp;nbsp;|&amp;nbsp;_shiftup이후&amp;nbsp;[1,&amp;nbsp;2,&amp;nbsp;4,&amp;nbsp;6,&amp;nbsp;3,&amp;nbsp;7,&amp;nbsp;5] &lt;br /&gt;index&amp;nbsp;:&amp;nbsp;&amp;nbsp;1&amp;nbsp;|&amp;nbsp;_shiftdown이후&amp;nbsp;[&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;1&lt;/span&gt;&lt;/b&gt;,&amp;nbsp;2,&amp;nbsp;4,&amp;nbsp;6,&amp;nbsp;3,&amp;nbsp;7,&amp;nbsp;5] &lt;br /&gt;index&amp;nbsp;:&amp;nbsp;&amp;nbsp;0&amp;nbsp;|&amp;nbsp;_shiftup이후&amp;nbsp;[2,&amp;nbsp;3,&amp;nbsp;4,&amp;nbsp;6,&amp;nbsp;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;1&lt;/b&gt;&lt;/span&gt;, 7, 5] &lt;span style=&quot;color: #ee2323;&quot;&gt;//자식노드가 있는 한, 끝까지 내림&lt;/span&gt;&lt;br /&gt;index&amp;nbsp;:&amp;nbsp;&amp;nbsp;0&amp;nbsp;|&amp;nbsp;_shiftdown이후&amp;nbsp;[&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;1&lt;/b&gt;&lt;/span&gt;, 2, 4, 6, 3, 7, 5]&lt;span style=&quot;color: #ee2323;&quot;&gt; //자식노드(1)이 부모노드 보다 작기 때문에 올려줌&lt;/span&gt;&lt;br /&gt;최종&amp;nbsp;:&amp;nbsp;&amp;nbsp;[1,&amp;nbsp;2,&amp;nbsp;4,&amp;nbsp;6,&amp;nbsp;3,&amp;nbsp;7,&amp;nbsp;5]&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;참고&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/python/cpython/blob/main/Lib/heapq.py#L170&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/python/cpython/blob/main/Lib/heapq.py#L170&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/python/cpython/blob/main/Lib/heapq.py#L260&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/python/cpython/blob/main/Lib/heapq.py#L260&lt;/a&gt;&lt;/p&gt;</description>
      <category>CS fundamental/data structure</category>
      <author>yuvnn</author>
      <guid isPermaLink="true">https://yuvnn.tistory.com/3</guid>
      <comments>https://yuvnn.tistory.com/entry/%EC%9E%90%EB%A3%8C%EA%B5%AC%EC%A1%B0-python-%EA%B3%B5%EC%8B%9D%EB%AC%B8%EC%84%9C-heapqheapify%EB%A1%9C-%EC%95%8C%EC%95%84%EB%B3%B4%EB%8A%94-%EC%B5%9C%EC%86%8C-%ED%9E%99-min-heap%EC%9D%98-%EB%8F%99%EC%9E%91#entry3comment</comments>
      <pubDate>Mon, 24 Mar 2025 17:41:38 +0900</pubDate>
    </item>
    <item>
      <title>[git] SSH를 사용하여 원격 저장소에 연결하기</title>
      <link>https://yuvnn.tistory.com/entry/git-SSH%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%98%EC%97%AC-%EC%9B%90%EA%B2%A9-%EC%A0%80%EC%9E%A5%EC%86%8C%EC%97%90-%EC%97%B0%EA%B2%B0%ED%95%98%EA%B8%B0</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;서론&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;랩실 서버를 사용하여 프로젝트를 진행하던 중,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Git에 기록을 남기기 위해&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로젝트를 원격저장소에 remote, push하다가 오류가 발생했다.&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; error: RPC 실패; HTTP 400 curl 22 The requested URL returned &lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;error: 400 fatal: the remote end hung up unexpectedly&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;&lt;span style=&quot;background-color: #ffffff; color: #9d9d9d; text-align: start;&quot;&gt; 오류: RPC 실패; HTTP 400 컬 22 요청된 URL 반환 &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;오류: 400 &lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;치명적입니다: 원격 끝이 예기치 않게 끊겼습니다&lt;/span&gt; &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이유는 모르겠으나,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;span style=&quot;color: #9d9d9d; text-align: start;&quot;&gt;(인증오류, 푸시크기제한이 이유일 수 있음)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;https 방식의 원격연결이 불가능하다는 내용의 오류로 추정되기에&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SSH 방식의 연결을 시도해 보았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 과정을 공유해보겠다 !  &lt;/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;&amp;nbsp;SSH를&amp;nbsp;사용하여&amp;nbsp;원격&amp;nbsp;저장소에&amp;nbsp;연결하기&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 키 확인&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;.ssh 디렉토리 내에 id_rsa 또는 id_ed25519 같은 키 파일이 있다면, 이미 SSH 키가 있는 것입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1742200950080&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;ls -al ~/.ssh&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. ssh 키 생성&lt;/h3&gt;
&lt;pre id=&quot;code_1742200684600&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;ssh-keygen -t rsa -b 4096 -C &quot;your_email@example.com&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 alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;495&quot; data-origin-height=&quot;70&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rh3qM/btsMOrh3Q1o/zm16143kKmLK1PRs5cUKt1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rh3qM/btsMOrh3Q1o/zm16143kKmLK1PRs5cUKt1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rh3qM/btsMOrh3Q1o/zm16143kKmLK1PRs5cUKt1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Frh3qM%2FbtsMOrh3Q1o%2Fzm16143kKmLK1PRs5cUKt1%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;431&quot; height=&quot;61&quot; data-origin-width=&quot;495&quot; data-origin-height=&quot;70&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;1. 어디에 키를 생성할 것인지&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. passphrase를 생성할 것인지&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;*passphrase : SSH 키를 사용할 때 추가적인 보안을 제공하기 위해 설정하는 비밀번호 &amp;nbsp;&lt;/span&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;/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;3. SSH 공개 키 복사&lt;/h3&gt;
&lt;pre id=&quot;code_1742200988695&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cat ~/.ssh/id_rsa.pub&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4. GitHub에 SSH 키 추가&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-end=&quot;887&quot; data-start=&quot;826&quot;&gt;GitHub에 로그인 후, &lt;b&gt;Settings&lt;/b&gt; &amp;gt; &lt;b&gt;SSH and GPG keys&lt;/b&gt;로 이동&lt;/li&gt;
&lt;li data-end=&quot;917&quot; data-start=&quot;888&quot;&gt;&lt;b&gt;New SSH key&lt;/b&gt; 버튼을 클릭&lt;/li&gt;
&lt;li data-end=&quot;972&quot; data-start=&quot;918&quot;&gt;&lt;b&gt;Title&lt;/b&gt;에 적당한 이름을 넣고, &lt;b&gt;Key&lt;/b&gt;에 복사한 공개 키를 붙여넣기&amp;nbsp;&lt;/li&gt;
&lt;li data-end=&quot;1010&quot; data-start=&quot;973&quot;&gt;&lt;b&gt;Add SSH key&lt;/b&gt; 버튼을 클릭하여 키를 추가&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1903&quot; data-origin-height=&quot;694&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/beGWL9/btsMNpSPMDN/Kvy15oiBVsoOXfbXQe09ZK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/beGWL9/btsMNpSPMDN/Kvy15oiBVsoOXfbXQe09ZK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/beGWL9/btsMNpSPMDN/Kvy15oiBVsoOXfbXQe09ZK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbeGWL9%2FbtsMNpSPMDN%2FKvy15oiBVsoOXfbXQe09ZK%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;1903&quot; height=&quot;694&quot; data-origin-width=&quot;1903&quot; data-origin-height=&quot;694&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;완료되면 이런식으로 SSH Keys에 추가가 된 모습을 확인할 수 있다.&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;5. SSH 연결 테스트&lt;/h3&gt;
&lt;pre id=&quot;code_1742201282615&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;ssh -T git@github.com&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 alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;630&quot; data-origin-height=&quot;25&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/l2cBD/btsMNgaNGAL/p0bqULc4n2UzL3uPVb3vPk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/l2cBD/btsMNgaNGAL/p0bqULc4n2UzL3uPVb3vPk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/l2cBD/btsMNgaNGAL/p0bqULc4n2UzL3uPVb3vPk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fl2cBD%2FbtsMNgaNGAL%2Fp0bqULc4n2UzL3uPVb3vPk%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;730&quot; height=&quot;29&quot; data-origin-width=&quot;630&quot; data-origin-height=&quot;25&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음과같은 메세지가 출력된다&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;6. Git 원격 URL 변경&lt;/h3&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;b&gt; HTTPS&lt;/b&gt;로 설정되어 있다면, SSH 방식으로 변경해야 한다.&lt;/p&gt;
&lt;pre id=&quot;code_1742201369223&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;git remote set-url origin git@github.com:username/repository.git&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&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;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;+) SSH이란?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;참고&lt;/b&gt; &lt;a href=&quot;https://jibinary.tistory.com/114#SSH%C2%A0%EA%B5%AC%EC%84%B1%EC%9A%94%EC%86%8C%C2%A0(Public%C2%A0Key%C2%A0%26%C2%A0Private%C2%A0Key)-1&quot;&gt;[네트워크] SSH, SFTP, FTP 아주 쉽게 개념 정리 &amp;amp; 설명 (feat. AWS) &amp;mdash; 아주 쉽게 정리한 블로그&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;span style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot;&gt;SSH는&amp;nbsp;&quot;Secure&amp;nbsp;S&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot;&gt;hell&quot;의&amp;nbsp;약자로,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;원격으로 호스트&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; color: #353638; text-align: left;&quot;&gt;에&amp;nbsp;접속하기&amp;nbsp;위해&amp;nbsp;사용되는&amp;nbsp;&lt;/span&gt;&lt;b&gt;보안 프로토콜&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #353638; text-align: left; background-color: #faf4c0;&quot;&gt; 즉, 원격으로 다른 컴퓨터에 접속하고 싶을 때 SSH를 사용&lt;/span&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;우리가&amp;nbsp;&lt;b&gt;나의 컴퓨터로&amp;nbsp;다른 컴퓨터를 접속&lt;/b&gt; 할 때,&amp;nbsp;&lt;b&gt;나의 컴퓨터에서 Public Key와 Private Key를 생성 &lt;/b&gt;&lt;/li&gt;
&lt;li&gt;이를 통해 통신을 위한&amp;nbsp;나의 컴퓨터의 신원을 암호화 할 수 있다.&lt;/li&gt;
&lt;li&gt;이 때, Public Key는 나의 컴퓨터의 신원을 암호화 한 것이고, &lt;br /&gt;Private Key는 암호화 된 나의 컴퓨터의 신원을 복호화 하는 역할&lt;/li&gt;
&lt;li&gt;그렇기 때문에&amp;nbsp;다른 컴퓨터에 Public Key를 저장해야한다.&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>git</category>
      <author>yuvnn</author>
      <guid isPermaLink="true">https://yuvnn.tistory.com/2</guid>
      <comments>https://yuvnn.tistory.com/entry/git-SSH%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%98%EC%97%AC-%EC%9B%90%EA%B2%A9-%EC%A0%80%EC%9E%A5%EC%86%8C%EC%97%90-%EC%97%B0%EA%B2%B0%ED%95%98%EA%B8%B0#entry2comment</comments>
      <pubDate>Mon, 17 Mar 2025 17:56:01 +0900</pubDate>
    </item>
    <item>
      <title>git에 프로젝트 올리기</title>
      <link>https://yuvnn.tistory.com/entry/git%EC%97%90-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EC%98%AC%EB%A6%AC%EA%B8%B0</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;몇 번을 해도 계속 헷갈리는&amp;nbsp;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt; git에 프로젝트 올리는 법 정리해보자&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p 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;&lt;b&gt;1. 로컬 파일에 코드 등이 이미 존재&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. 깃에서 새로운 레포지토리 생성완료&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이럴때 괜히 쉽게 하겠다고 &lt;b&gt;파일경로 확인 안하고 클론하면 파일을 날려먹는 수가 있다&lt;span style=&quot;color: #9d9d9d;&quot;&gt; (유경험자)&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 로컬 폴더에서 레포지토리 초기화&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;.git 파일 생성&lt;/p&gt;
&lt;pre id=&quot;code_1742196139088&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;git init&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. .gitignore 파일 생성&lt;/h3&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;⭐ add 전에 대용량 파일 있는지 확인&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;git은 한번에 100MB이상의 파일을 업로드 할 수 없음.&lt;/li&gt;
&lt;li&gt;확인 안하고 &lt;span style=&quot;color: #333333; text-align: left;&quot;&gt;add, commit&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt; 바로 했다가 대용량 데이터가 스테이지에 올라가면 귀찮아짐. 그러니까 잘 확인하자&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1742196835694&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;touch .gitignore&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;기초적인 .gitignore문법&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 style=&quot;color: #006dd7;&quot;&gt; e.g. folder/&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;*는 모든 파일이라는 뜻 &lt;span style=&quot;color: #006dd7;&quot;&gt;e.g. *.csv == csv확장자를 사진 모든 파일&lt;/span&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;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. 파일 추가 (Add)&lt;/h3&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;(커밋 준비 상태)&lt;/p&gt;
&lt;pre id=&quot;code_1742196268181&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;git add .&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4. github 레포지토리 원격 주소 설정&lt;/h3&gt;
&lt;pre id=&quot;code_1742197033307&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;git remote add origin https://github.com/username/repository-name.git&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;remote 확인&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1742197127432&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;git remote -v&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5. 브랜치 설정 (필요 시)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본적으로 &lt;b&gt;로컬 git 레포지토리는 main 브랜치&lt;/b&gt;에서 작업을 하지만,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;githbu 레포지토리가 master 브랜지를 사용하고 있다면&lt;/b&gt; 로컬 브랜치를 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;master로&lt;/span&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;branch 확인&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1742197409452&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;git branch&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;branch master로 변경&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1742197312432&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;git branch -M master&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;6. 커밋 (commit) 및 푸시&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;git commit : 로컬 저장소에 커밋&lt;/b&gt;을 기록&lt;/li&gt;
&lt;li&gt;&lt;b&gt;git push : 원격 저장소&lt;/b&gt;에 반영&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1742197490481&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;git commit -m &quot;init&quot;
git push -u origin master&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;+) 기타 branch 관련 명령어&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;git branch -m 'master' 'main'&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;브랜치명 변경&lt;/li&gt;
&lt;li&gt;&lt;b&gt;git branch [브랜치명]&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;브랜치를 생성&lt;/li&gt;
&lt;li&gt;&lt;b&gt;git checkout [브랜치명]&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;해당 브랜치로 이동&lt;/li&gt;
&lt;li&gt;&lt;b&gt;git branch [브랜치명]&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;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;</description>
      <category>git</category>
      <author>yuvnn</author>
      <guid isPermaLink="true">https://yuvnn.tistory.com/1</guid>
      <comments>https://yuvnn.tistory.com/entry/git%EC%97%90-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EC%98%AC%EB%A6%AC%EA%B8%B0#entry1comment</comments>
      <pubDate>Mon, 17 Mar 2025 16:54:21 +0900</pubDate>
    </item>
  </channel>
</rss>