<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>yujenius 님의 블로그</title>
    <link>https://yujenius.tistory.com/</link>
    <description>대학생의개발공부일지입니다</description>
    <language>ko</language>
    <pubDate>Tue, 11 Aug 2026 16:18:48 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>yujenius</managingEditor>
    <image>
      <title>yujenius 님의 블로그</title>
      <url>https://tistory1.daumcdn.net/tistory/7634575/attach/ab9058a7b3e241bfa78c5150bacfc703</url>
      <link>https://yujenius.tistory.com</link>
    </image>
    <item>
      <title>[UMC] 나의 두번째 React Hook (useContext)</title>
      <link>https://yujenius.tistory.com/entry/UMC-%EB%82%98%EC%9D%98-%EB%91%90%EB%B2%88%EC%A7%B8-React-Hook-useContext</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;982&quot; data-origin-height=&quot;604&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/r5Bam/btsMUQB97zr/hkH7KzuGbrfBa4K0ullJQK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/r5Bam/btsMUQB97zr/hkH7KzuGbrfBa4K0ullJQK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/r5Bam/btsMUQB97zr/hkH7KzuGbrfBa4K0ullJQK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fr5Bam%2FbtsMUQB97zr%2FhkH7KzuGbrfBa4K0ullJQK%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;525&quot; height=&quot;323&quot; data-origin-width=&quot;982&quot; data-origin-height=&quot;604&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최근에 umc 활동을 하면서 React의 여러 가지 개념을 배우고 있는데, 이번에는 useContext에 대해 공부했다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음에는 props drilling 이 왜 문제인지 정확히 와닿지 않았는데, 직접 코드를 작성하고 나니&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;useContext의 필요성을 확실히 깨달을 수 있었다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글에서는 props drilling의 문제를 알아보고, 이를 해결하는 방법으로 useContext를 사용하는 방법을 정리해보려고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Props drilling 문제 이해하기&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;React에서 &lt;b&gt;부모 &amp;rarr; 자식 &amp;rarr; 손자&lt;/b&gt;로 데이터를 전달하려면 props를 계속 내려줘야 한다.&lt;br /&gt;이 과정에서 중간에 위치한 컴포넌트가 실제로는 데이터를 사용하지 않지만,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단순히 props를 전달하기 위해 존재해야 하는 문제가 발생한다.&lt;br /&gt;이런 현상을 &lt;b&gt;props drilling(프롭 드릴링) &lt;/b&gt;이라고 한다.&lt;/p&gt;
&lt;pre id=&quot;code_1742749031208&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import { useState } from 'react';
import ButtonGroup from './components/ButtonGroup';

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

  const handleIncrement = () =&amp;gt; setCount(count + 1);
  const handleDecrement = () =&amp;gt; setCount(count - 1);

  return (
    &amp;lt;&amp;gt;
      &amp;lt;h1&amp;gt;{count}&amp;lt;/h1&amp;gt;
      &amp;lt;ButtonGroup handleIncrement={handleIncrement} handleDecrement={handleDecrement} /&amp;gt;
    &amp;lt;/&amp;gt;
  );
}

export default App;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;ButtonGroup.tsx&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1742749061805&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;interface ButtonGroupProps {
  handleIncrement: () =&amp;gt; void;
  handleDecrement: () =&amp;gt; void;
}

const ButtonGroup = ({ handleIncrement, handleDecrement }: ButtonGroupProps) =&amp;gt; {
  return (
    &amp;lt;div&amp;gt;
      &amp;lt;button onClick={handleIncrement}&amp;gt;+1 증가&amp;lt;/button&amp;gt;
      &amp;lt;button onClick={handleDecrement}&amp;gt;-1 감소&amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;
  );
};

export default ButtonGroup;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 코드에서는 App 컴포넌트에서 ButtonGroup을 거쳐 Button 까지 props 를 계속 전달해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 ButtonGroup 자체는 count 값을 사용하지 않으므로 불필요한 props 전달이 발생하는 것이 문제였다.&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;useContext&lt;/b&gt;를 사용할 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;props drilling 해결하기 (useContext 사용하기)&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;React의 useContext를 활용하면 중간 컴포넌트를 거치지 않고 필요한 곳에서 바로 데이터를 사용할 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1742749267133&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import { createContext, useContext, useState, ReactNode } from 'react';

//Context 생성
const CountContext = createContext&amp;lt;{ count: number; setCount: (value: number) =&amp;gt; void } | undefined&amp;gt;(undefined);

//Provider 생성
const CountProvider = ({ children }: { children: ReactNode }) =&amp;gt; {
  const [count, setCount] = useState(0);

  return &amp;lt;CountContext.Provider value={{ count, setCount }}&amp;gt;{children}&amp;lt;/CountContext.Provider&amp;gt;;
};

//Custom Hook 생성(useContext를 쉽게 사용하도록)
const useCount = () =&amp;gt; {
  const context = useContext(CountContext);
  if (!context) throw new Error('useCount must be used within a CountProvider');
  return context;
};

export { CountProvider, useCount };&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;App.tsx&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1742749294578&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import { CountProvider } from './context/CountContext';
import Counter from './components/Counter';

function App() {
  return (
    &amp;lt;CountProvider&amp;gt;
      &amp;lt;Counter /&amp;gt;
    &amp;lt;/CountProvider&amp;gt;
  );
}

export default App;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Counter.tsx&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1742749312192&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import { useCount } from '../context/CountContext';
import ButtonGroup from './ButtonGroup';

const Counter = () =&amp;gt; {
  const { count } = useCount();
  return (
    &amp;lt;&amp;gt;
      &amp;lt;h1&amp;gt;{count}&amp;lt;/h1&amp;gt;
      &amp;lt;ButtonGroup /&amp;gt;
    &amp;lt;/&amp;gt;
  );
};

export default Counter;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;ButtonGroup.tsx&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1742749338960&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import { useCount } from '../context/CountContext';
import Button from './Button';

const ButtonGroup = () =&amp;gt; {
  const { setCount } = useCount();

  return (
    &amp;lt;div&amp;gt;
      &amp;lt;Button onClick={() =&amp;gt; setCount(prev =&amp;gt; prev + 1)} text='+1 증가' /&amp;gt;
      &amp;lt;Button onClick={() =&amp;gt; setCount(prev =&amp;gt; prev - 1)} text='-1 감소' /&amp;gt;
    &amp;lt;/div&amp;gt;
  );
};

export default ButtonGroup;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;마무리&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번에 공부하면서 props drilling 이 왜 문제가 되는지 직접 경험해 보고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 해결하는 방법으로 useContext를 활용할 수 있다는 걸 배웠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론 처음 써보기에 내가 익숙하게 잘 쓴다는 생각이 들지는 않았지만 여러번 활용해보면 그만큼 언제 Context API를 사용해야 하는지 알 수 있겠다는 생각이 들었다. 앞으로 React 프로젝트를 할 때, 언제 Context API를 사용해야 하는지 고민하면서 적용해봐야겠다.&lt;/p&gt;</description>
      <category>프론트엔드/React</category>
      <category>context</category>
      <category>props drilling</category>
      <category>react</category>
      <category>UMC</category>
      <category>web</category>
      <author>yujenius</author>
      <guid isPermaLink="true">https://yujenius.tistory.com/11</guid>
      <comments>https://yujenius.tistory.com/entry/UMC-%EB%82%98%EC%9D%98-%EB%91%90%EB%B2%88%EC%A7%B8-React-Hook-useContext#entry11comment</comments>
      <pubDate>Mon, 24 Mar 2025 02:05:12 +0900</pubDate>
    </item>
    <item>
      <title>[React]React 의존성 충돌 해결</title>
      <link>https://yujenius.tistory.com/entry/ReactReact-%EC%9D%98%EC%A1%B4%EC%84%B1-%EC%B6%A9%EB%8F%8C-%ED%95%B4%EA%B2%B0</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;235&quot; data-origin-height=&quot;188&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ESHIi/btsMhSnuC2L/bDyLbkV9VZ2iBWZANJTwt1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ESHIi/btsMhSnuC2L/bDyLbkV9VZ2iBWZANJTwt1/img.jpg&quot; data-alt=&quot;외 않되&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ESHIi/btsMhSnuC2L/bDyLbkV9VZ2iBWZANJTwt1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FESHIi%2FbtsMhSnuC2L%2FbDyLbkV9VZ2iBWZANJTwt1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;377&quot; height=&quot;302&quot; data-origin-width=&quot;235&quot; data-origin-height=&quot;188&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;React 프로젝트 생성 중에 에러가 발생했다.!!!!!!!!!!!!!!!!&lt;/p&gt;
&lt;pre id=&quot;code_1739426392000&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Installing template dependencies using npm...
npm ERR! code ERESOLVE
npm ERR! ERESOLVE unable to resolve dependency tree
npm ERR! 
npm ERR! While resolving: reactstudy@0.1.0
npm ERR! Found: react@19.0.0
npm ERR! node_modules/react
npm ERR!   react@&quot;^19.0.0&quot; from the root project
npm ERR! 
npm ERR! Could not resolve dependency:
npm ERR! peer react@&quot;^18.0.0&quot; from @testing-library/react@13.4.0
npm ERR! node_modules/@testing-library/react
npm ERR!   @testing-library/react@&quot;^13.4.0&quot; from the root project
npm ERR! 
npm ERR! Fix the upstream dependency conflict, or retry
npm ERR! this command with --force or --legacy-peer-deps
npm ERR! to accept an incorrect (and potentially broken) dependency resolution.
npm ERR! 
npm ERR!&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;내가 생각했을 때는 평소에는 그냥 생성하던 것을 template 옵션을 추가해서 생긴 에러같은데,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 내가 말하는 template은 대멋사 제공 필요없는 파일을 다 제거한 기본적으로 개발하기 위해 남기는 초기 상태의 필수적인 파일만 남은 basic한 상태를 말하는 데 혹시나 시도해보고 싶은 사람에게는&lt;/p&gt;
&lt;pre id=&quot;code_1739426504365&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 &amp;lt;프로젝트명&amp;gt; --template basic-react&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;react@19.0.0을 사용하고 있는데, @testing-library/react@13.4.0이 React 18을 요구하면서 의존성 충돌이 발생했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇게 해결하는 데에 큰 이슈가 발생하지 않았지만 이에 대한 해결책은&lt;/p&gt;
&lt;pre id=&quot;code_1739426589914&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;npm install --legacy-peer-deps&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 옵션은 peerDependencies 충돌을 무시하고 설치해준다. 무시라는 단어가 자극적이긴 하지만 제일 .. 간단하고 안전한 해결법이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이게 불안하면 버전을 다운그레이드해서 버전을 맞춘다음 하는 법이 있긴 하다 .&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇지만 그렇게 하기 위해서는 삭제하고 다시 설치하고의 복잡한 해결이기에. 위와 같은 방법으로 되지 않는 다면,, 해보시길&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 또 하나의 에러가 났다.&lt;/p&gt;
&lt;pre id=&quot;code_1739426707300&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;npm ERR! code ENOENT
npm ERR! syscall open
npm ERR! path /Users/jiyujin/package.json
npm ERR! errno -2
npm ERR! enoent ENOENT: no such file or directory, open '/Users/jiyujin/package.json'
npm ERR! enoent This is related to npm not being able to find a file.
npm ERR! enoent&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;npm install --legacy-peer-deps를 실행했지만, &lt;b&gt;현재 경로 (/Users/jiyujin/)에 package.json이 없어서&lt;/b&gt; 에러가 발생했다.&lt;br /&gt;즉, 프로젝트 폴더가 아닌 &lt;b&gt;홈 디렉터리 (~ 또는 /Users/jiyujin/)에서 명령어를 실행한 것&lt;/b&gt;&amp;nbsp;이다.&lt;/p&gt;
&lt;pre id=&quot;code_1739426757677&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cd ~/내_프로젝트_폴더
ls&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;꼭 내가 생성한 프로젝트 폴더 안에서&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1739426779942&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;npm install --legacy-peer-deps&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;pre id=&quot;code_1739426818076&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;removed 5 packages, and audited 1473 packages in 1s

272 packages are looking for funding
  run npm fund for details

9 vulnerabilities (3 moderate, 6 high)

Some issues need review, and may require choosing
a different dependency.

Run npm audit for details.&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이와 같은 에러가 난다면.. 설치는 성공했으나 몇가지의 경고 warning 사항을 알려준다.&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;258&quot; data-start=&quot;120&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;188&quot; data-start=&quot;120&quot;&gt;272 packages are looking for funding &amp;rarr; 무시해도 됨 (오픈소스 후원 관련 메시지)&lt;/li&gt;
&lt;li data-end=&quot;258&quot; data-start=&quot;189&quot;&gt;9 vulnerabilities (3 moderate, 6 high) &amp;rarr; &lt;b&gt;보안 취약점이 있는 패키지가 있음&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;보안은 그래도 중요하니까..&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보안 취약점 자동 수정 명령어를 실행&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1739426886343&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;npm audit fix&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 다음&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1739426925811&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;npm start&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로 잘 실행되는 지 확인하자!!!&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;잘 실행된다면 문제 해결 완료!!!&lt;/p&gt;</description>
      <category>프론트엔드/React</category>
      <category>react</category>
      <category>개발공부</category>
      <category>리액트</category>
      <category>의존성충돌</category>
      <author>yujenius</author>
      <guid isPermaLink="true">https://yujenius.tistory.com/10</guid>
      <comments>https://yujenius.tistory.com/entry/ReactReact-%EC%9D%98%EC%A1%B4%EC%84%B1-%EC%B6%A9%EB%8F%8C-%ED%95%B4%EA%B2%B0#entry10comment</comments>
      <pubDate>Thu, 13 Feb 2025 15:10:40 +0900</pubDate>
    </item>
    <item>
      <title>[React] State 맘대로 변경하는 법</title>
      <link>https://yujenius.tistory.com/entry/React-State-%EB%A7%98%EB%8C%80%EB%A1%9C-%EB%B3%80%EA%B2%BD%ED%95%98%EB%8A%94-%EB%B2%95</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;736&quot; data-origin-height=&quot;589&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bZYZjt/btsMceyNsHX/g6dGbnkkRjLNzbo3inOl41/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bZYZjt/btsMceyNsHX/g6dGbnkkRjLNzbo3inOl41/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bZYZjt/btsMceyNsHX/g6dGbnkkRjLNzbo3inOl41/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbZYZjt%2FbtsMceyNsHX%2Fg6dGbnkkRjLNzbo3inOl41%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;494&quot; height=&quot;395&quot; data-origin-width=&quot;736&quot; data-origin-height=&quot;589&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;React에서는 useState를 사용하여 상태를 관리한다. 하지만 직접 state를 변경하면 React의 상태 관리 흐름을 깨트려 버린다. 난 이 부분이 React를 공부하면서 헷갈리고 어려웠던 개념이기에 정리를 통한 완벽 학습을 목적으로 글을 써보려한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt; ❌ 직접 변경하면 안 되는 이유&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;React에서는 state가 변경될 대마다 컴포넌트를 다시 렌더링한다. 하지만 state를 직접 수정하면 이를 감지하지 못해 렌더링이 일어나지 않거나, 예상치 못한 동작이 발생할 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1739206637456&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const [count, setCount] = useState(0);

// ❌ 이렇게 하면 안 됨!
count = count + 1; // 상태 직접 변경 (React가 감지하지 못함)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그냥 쉽게 이해하도록 설명한다면.. 자료형이 const 인 상태라고 생각했을 때 그 값을 바꾸려고 한다고 생각하면 좀 더 이해하기 쉽다. 그럼 어떻게 변경해줘야 할까?&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt; ✅ 올바르게 변경하는 방법&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;React에서 state를 변경할 때는 항상 setState 함수를 사용한다. 물론 요즘은 아니다. 그치만 소개하겠다.&lt;/p&gt;
&lt;pre id=&quot;code_1739206722408&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const [count, setCount] = useState(0);

const handleClick = () =&amp;gt; {
  setCount(count + 1); // ✅ 올바른 방법
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쉽게 기초 내용을 코드로 살펴 보게 되면,&lt;/p&gt;
&lt;pre id=&quot;code_1739206992976&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;let [데이터, 데이터변경] = useState(['모시기','모시기1', '모시기2']);

function 데이터바꾸기(){
	데이터변경(['1','2','3']); //state를 아예 대체해주는 함수
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터변경에 해당하는 함수로만 state 값을 변경해줄 수 있다고 생각하는 것이 이해하기 편할 것이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러나, 이런식으로 배열일 경우에 하드코딩 하는 법 말고 좀 더 개발자 스럽게 한다면&lt;/p&gt;
&lt;pre id=&quot;code_1739207215652&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;let [데이터, 데이터변경] = useState(['모시기','모시기1', '모시기2']);

function 데이터바꾸기(){
	var newArray = 데이터;
    	newArray[0] = '1';
	데이터변경(newArray);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;수정된[데이터]를 만드는데, state의 복사복을 만들어서 수정하는 법으로 가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러나 이렇게 하면 안되고, deep copy 를 해야한다. 위와 같은 경우는 복사가 아니라 값 공유를 하게된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서,&lt;/p&gt;
&lt;pre id=&quot;code_1739207381912&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;let [데이터, 데이터변경] = useState(['모시기','모시기1', '모시기2']);

function 데이터바꾸기(){
	var newArray = [...데이터];
    	newArray[0] = '1';
	데이터변경(newArray);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;object 의 경우 []를 {}로 바꿔주고 똑같이 spread operator(...)을 사용해주면 된다.&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;b&gt;마무리&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;state를 변경하려면 변경함수를 써야한다, 변경함수(대체할 데이터)&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;state는 직접 건들지말자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;deep copy를 하고 그것을 건들자!&amp;nbsp;&lt;/p&gt;</description>
      <category>프론트엔드/React</category>
      <author>yujenius</author>
      <guid isPermaLink="true">https://yujenius.tistory.com/9</guid>
      <comments>https://yujenius.tistory.com/entry/React-State-%EB%A7%98%EB%8C%80%EB%A1%9C-%EB%B3%80%EA%B2%BD%ED%95%98%EB%8A%94-%EB%B2%95#entry9comment</comments>
      <pubDate>Tue, 11 Feb 2025 02:12:27 +0900</pubDate>
    </item>
    <item>
      <title>[React] JSX 란?!</title>
      <link>https://yujenius.tistory.com/entry/JSX-%EB%9E%80</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;735&quot; data-origin-height=&quot;589&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uXEN0/btsMcrdDRqQ/wNWDcIQk94uBC1k73J8Be1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uXEN0/btsMcrdDRqQ/wNWDcIQk94uBC1k73J8Be1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uXEN0/btsMcrdDRqQ/wNWDcIQk94uBC1k73J8Be1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuXEN0%2FbtsMcrdDRqQ%2FwNWDcIQk94uBC1k73J8Be1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;599&quot; height=&quot;480&quot; data-origin-width=&quot;735&quot; data-origin-height=&quot;589&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;얼마 전까지 Vanila JS 만을 고수하던 나이기에 React를 시작할 때 JSX 언어는 너무 생소했다&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;새로운 개념을 다시 적립한다는 것이 받아들이기 힘든 현실이지만 JSX 는 React 를 하기 위해서 필수적인 개념이기에 이번 글에서 다뤄보려한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;JSX는 Javascript 내에서 XML 과 유사한 문법을 사용할 수 있도록 도와준다. 그렇지만 사용하다 보니 생소한 문법과 사용법이 미묘하게 다르기에 이 글에서는 React 비기너들을 위해 !!&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;JSX의 기본 개념과 꼭 지켜야 하는 주요 문법에 대해서 정리해보도록 하겠다.&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;b&gt;JSX의 기본 개념&lt;/b&gt;&amp;nbsp;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;JSX는 JavaScript 코드 내에서 HTML과 유사한 구조를 작성할 수 있는 문법 확장이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. UI를 선언적으로 표현할 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1739204395924&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;Hello, JSX!&amp;lt;/h1&amp;gt;;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. JSX 코드는 Babel에 의해 JavaScript 코드로 변환된다.&lt;/p&gt;
&lt;pre id=&quot;code_1739204456688&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const element = React.createElement(&quot;h1&quot;, null, &quot;Hello, JSX!&quot;);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;JSX의 주요 문법&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1. 반드시 하나의 부모 요소로 감싸야 함&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;JSX에서는 여러 요소를 반환할 경우 반드시 하나의 부모 요소를 감싸야 한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;❌ 오류 발생 코드:&lt;/p&gt;
&lt;pre id=&quot;code_1739204596404&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;return (
    &amp;lt;h1&amp;gt;Hello&amp;lt;/h1&amp;gt;
    &amp;lt;p&amp;gt;JSX&amp;lt;/p&amp;gt;
);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span&gt;✅ 올바른 코드:&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1739204678828&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;return (
    &amp;lt;div&amp;gt;
        &amp;lt;h1&amp;gt;Hello&amp;lt;/h1&amp;gt;
        &amp;lt;p&amp;gt;JSX&amp;lt;/p&amp;gt;
    &amp;lt;/div&amp;gt;
);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;또는 React의 Fragment를 사용할 수도 있다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1739204755224&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;return (
    &amp;lt;&amp;gt;
        &amp;lt;h1&amp;gt;Hello&amp;lt;/h1&amp;gt;
        &amp;lt;p&amp;gt;JSX&amp;lt;/p&amp;gt;
    &amp;lt;/&amp;gt;
);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;2.JavaScript 표현식 사용&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;중괄호 {} 를 사용하여 JavaScript 표현식을 JSX 내부에 삽입할 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1739204876441&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const name = &quot;React&quot;;
const element = &amp;lt;h1&amp;gt;Hello, {name}! &amp;lt;/h1&amp;gt;;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;보통 데이터 바인딩의 경우 {} 를 꼭 사용해주어야 한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;여기서 &lt;b&gt;데이터 바인딩(Data Binding)&lt;/b&gt;이란?&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;데이터 바인딩(Data Binding) 은 프로그래밍에서 &lt;b&gt;UI(사용자 인터페이스)&lt;/b&gt;와 &lt;b&gt;데이터(모델)&lt;/b&gt;를 연결하는 기술이다. 이를 통해 데이터가 변경되면 UI도 자동으로 업데이트되도록 만들 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;3. 속성(Attribute) 적용&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;JSX에서는 HTML 속성과 유사하지만, camelCase 표기법을 사용해야 한다.&lt;/p&gt;
&lt;pre id=&quot;code_1739205161691&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;button onClick={handleClick}&amp;gt;Click me&amp;lt;/button&amp;gt;;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;class -&amp;gt; className&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;for -&amp;gt; htmlFor&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;그리고 JSX 문법에서는 JavaScript와 다른 점이 class 는 className , for 는 htmlFor 로 써줘야만 한다.&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;size18&quot;&gt;&lt;b&gt;4. 조건부 렌더링 **&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;JSX 에서는 조건부 렌더링을 위해 삼항 연산자 또는 &amp;amp;&amp;amp; 연산자를 사용할 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1739205338604&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cont isLoggedIn = true;
const element = isLoggedIn ? &amp;lt;h1&amp;gt;Welcome&amp;lt;/h1&amp;gt; : &amp;lt;h1&amp;gt;Please log in&amp;lt;/h1&amp;gt;;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;amp;&amp;amp; 연산자를 사용하면 조건이 true 일 때만 특정 요소를 렌더링할 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1739205389909&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const message = isLoggedIn &amp;amp;&amp;amp; &amp;lt;h1&amp;gt;Welcome&amp;lt;/h1&amp;gt;;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;5. 리스트 렌더링&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;배열의 map()을 사용하여 리스트를 동적으로 생성할 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1739205619101&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const items = [&quot;Apple&quot;, &quot;Banana&quot;, &quot;Cherry&quot;];
const list = (
    &amp;lt;ul&amp;gt;
        {items.map((item, index) =&amp;gt; &amp;lt;li key={index}&amp;gt;{item}&amp;lt;/li&amp;gt;)}
    &amp;lt;/ul&amp;gt;
);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;여기서 주의해야 할 점은 key 속성을 부여하여 React가 각 항목을 고유하게 식별할 수 있도록 해야한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;6.인라인 스타일 적용&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;JSX에서는 스타일을 객체 형태로 작성하며, CamelCase를 사용한다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1739205726333&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const style = {
    color: &quot;blue&quot;,
    fontSize: &quot;20px&quot;
};

const element = &amp;lt;h1 style={style}&amp;gt;Styled Text&amp;lt;/h1&amp;gt;;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;본래의 JavaScript에서는 font-size 였던 것이 fontSize가 된 것을 확인해 볼 수 있다.&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;size18&quot;&gt;&lt;b&gt;7. 이벤트 처리&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;React에서 이벤트 핸들러는 onClick, onChange 등의 속성을 사용하며, 함수 참조를 전달해야 한다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1739205839377&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function handleClick() {
    alert(&quot;Button clicked!&quot;);
}

const button = &amp;lt;button onClick={handleClick}&amp;gt;Click me&amp;lt;/button&amp;gt;;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;마무리&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 글에서는 JSX 의 문법에 대해서 자세하게 알아보았다. JSX는 React의 핵심적인 요소이며, 이를 잘 활용하면 가독성이 좋은 UI 코드를 작성할 수 있으니 개념부터 잘 다지고 문법들을 하나 둘 공부하고 React에서 활용할 수 있는 개념들을 학습해나가면 좀 더 편하게 멋있는 프로그램들을 개발할 수 있을 것이다. React 마스터 까지. 화이팅.&lt;/p&gt;</description>
      <category>프론트엔드/React</category>
      <category>jsx</category>
      <category>react</category>
      <category>react 기초</category>
      <category>리액트</category>
      <author>yujenius</author>
      <guid isPermaLink="true">https://yujenius.tistory.com/8</guid>
      <comments>https://yujenius.tistory.com/entry/JSX-%EB%9E%80#entry8comment</comments>
      <pubDate>Tue, 11 Feb 2025 01:50:27 +0900</pubDate>
    </item>
    <item>
      <title>[Python] Code up 4060: 전광판 전구 조작</title>
      <link>https://yujenius.tistory.com/entry/Python-Code-up-4060-%EC%A0%84%EA%B4%91%ED%8C%90-%EC%A0%84%EA%B5%AC-%EC%A1%B0%EC%9E%91</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://codeup.kr/problem.php?id=4060&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://codeup.kr/problem.php?id=4060&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1738998083704&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;전광판 전구 조작&quot; data-og-description=&quot;첫째 줄에 전광판의 크기를 나타내는 세로 길이 $M$과 가로 길이 $N$이 입력된다. ($2&amp;lt;=M,N&amp;lt;=100$인 자연수) 둘째줄 부터 $M$줄에 걸쳐 $N$열 만큼의 전구들의 상태가 주어진다. 이때 켜진 상태는 $1$, 꺼&quot; data-og-host=&quot;codeup.kr&quot; data-og-source-url=&quot;https://codeup.kr/problem.php?id=4060&quot; data-og-url=&quot;https://codeup.kr/problem.php?id=4060&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://codeup.kr/problem.php?id=4060&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://codeup.kr/problem.php?id=4060&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;전광판 전구 조작&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;첫째 줄에 전광판의 크기를 나타내는 세로 길이 $M$과 가로 길이 $N$이 입력된다. ($2&amp;lt;=M,N&amp;lt;=100$인 자연수) 둘째줄 부터 $M$줄에 걸쳐 $N$열 만큼의 전구들의 상태가 주어진다. 이때 켜진 상태는 $1$, 꺼&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;codeup.kr&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;438&quot; data-origin-height=&quot;257&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/brucCv/btsMbzhNr8v/AKRQIG9MIn2S079V7Wi6Mk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/brucCv/btsMbzhNr8v/AKRQIG9MIn2S079V7Wi6Mk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/brucCv/btsMbzhNr8v/AKRQIG9MIn2S079V7Wi6Mk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbrucCv%2FbtsMbzhNr8v%2FAKRQIG9MIn2S079V7Wi6Mk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;438&quot; height=&quot;257&quot; data-origin-width=&quot;438&quot; data-origin-height=&quot;257&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-pm-slice=&quot;1 3 []&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span&gt;문제 설명&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;전광판에는 켜져 있는 전구(1)와 꺼져 있는 전구(0)가 있습니다. 전구를 조작하면 해당 전구와 상하좌우로 연결된 같은 상태의 전구들이 모두 바뀌는 특징이 있습니다. 이러한 규칙을 따라 모든 전구를 &lt;/span&gt;&lt;span&gt;&lt;b&gt;켜는 최소 조작 횟수&lt;/b&gt;&lt;/span&gt;&lt;span&gt;와 &lt;/span&gt;&lt;span&gt;&lt;b&gt;끄는 최소 조작 횟수&lt;/b&gt;&lt;/span&gt;&lt;span&gt;를 구하는 문제입니다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span&gt;입력&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;첫째 줄: 전광판의 크기 &lt;/span&gt;&lt;span&gt;M N&lt;/span&gt;&lt;span&gt; (2 &amp;le; M, N &amp;le; 100)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;둘째 줄부터 &lt;/span&gt;&lt;span&gt;M&lt;/span&gt;&lt;span&gt;개의 줄에 걸쳐 &lt;/span&gt;&lt;span&gt;N&lt;/span&gt;&lt;span&gt;개의 전구 상태가 주어짐 (켜진 상태: &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;, 꺼진 상태: &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span&gt;출력&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;모든 전구를 켜기 위한 최소 조작 횟수와 모두 끄기 위한 최소 조작 횟수를 공백으로 구분하여 출력&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&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;710&quot; data-origin-height=&quot;377&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/982hC/btsMa6f78SY/1As6uF5Sp2BSOsrjZEBYR0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/982hC/btsMa6f78SY/1As6uF5Sp2BSOsrjZEBYR0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/982hC/btsMa6f78SY/1As6uF5Sp2BSOsrjZEBYR0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F982hC%2FbtsMa6f78SY%2F1As6uF5Sp2BSOsrjZEBYR0%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;610&quot; height=&quot;377&quot; data-origin-width=&quot;710&quot; data-origin-height=&quot;377&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-pm-slice=&quot;1 5 []&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span&gt;해결 접근법&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이 문제는 DFS(깊이 우선 탐색)을 활용하여 해결할 수 있었습니다.&lt;/span&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-spread=&quot;true&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;연결된 그룹 찾기&lt;/b&gt;&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;같은 상태(0 또는 1)로 연결된 전구 그룹을 찾습니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;DFS 를 사용하여 전구 그룹을 탐색합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;한 그룹을 한 번의 조작으로 변환할 수 있으므로 그룹의 개수가 최소 조작 횟수가 됩니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;모든 전구를 켜기 위한 최소 조작 횟수&lt;/b&gt;&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;으로 이루어진 연결 요소(그룹)의 개수를 셉니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;모든 전구를 끄기 위한 최소 조작 횟수&lt;/b&gt;&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;으로 이루어진 연결 요소(그룹)의 개수를 셉니다.&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span&gt;소스 코드&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;pre id=&quot;code_1738998605417&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def dfs(y,x):
    if y &amp;lt; 0 or y &amp;gt;= m or x &amp;lt; 0 or x&amp;gt;=n:
        return
    if grid[y][x]== &quot;0&quot;:
        return   
    grid[y][x] = &quot;0&quot; #방문한 1을 0으로 변경하여 중복 방문 방지
    for d in range(4): # 상하좌우 탐색 
        dfs(y+dy[d],x+dx[d])

def dfs1(y,x):
    if y &amp;lt; 0 or y &amp;gt;= m or x &amp;lt; 0 or x&amp;gt;=n:
        return
    if grid2[y][x]== &quot;1&quot;:
        return
    grid2[y][x] = &quot;1&quot; # 방문한 0을 1로 변경하여 중복 방문 방지
    for d in range(4):
        dfs1(y+dy[d],x+dx[d])


m,n = map(int, input().split()) 
grid = []
grid2 = []
for i in range(m):
    row = list(input().split())
    grid.append(row)
    grid2.append(row.copy()) #grid2는 grid의 복사본 (독립적 사용)
    #print(' '.join(map[i]))

dy = [1, -1, 0, 0] #상, 하, 좌, 우 4방향
dx = [0, 0, 1, -1]

cnt = 0 
cnt2 = 0
for i in range(m):
    for j in range(n):
        if grid[i][j] == &quot;1&quot;: #1인 경우 DFS 실행 (꺼지는 그룹 찾기)
            dfs(i,j)
            cnt += 1
for i in range(m):
    for j in range(n):
        if grid2[i][j] == &quot;0&quot;: #0인 경우 DFS 실행(켜지는 그룹 찾기)
            dfs1(i,j)
            cnt2 += 1
            
print(f'%d %d'%(cnt2,cnt))&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;저번에 소개한 DFS 기반 알고리즘과 비슷한 개념이지만, 이번 문제는 두 가지 개수를 찾아 출력해야 한다는 점에서 차이가 있습니다. 이를 독립적으로 해결하기 위해 두 개의 DFS 함수를 만들어 각각의 경우를 탐색하도록 구현했습니다. 다만, BFS를 활용하면 탐색을 더욱 효율적으로 진행할 수 있어 해결이 더 쉬워질 것 같습니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;마무리&lt;/b&gt;&lt;/h2&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;DFS로 그룹을 찾고 조작 횟수를 계산하는 개념을 익힐 수 있는 좋은 문제!&lt;/li&gt;
&lt;li&gt;BFS 공부를 통해 좀 더 개선된 코드 짜보기&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>알고리즘/Python</category>
      <category>dfs</category>
      <category>python</category>
      <category>알고리즘공부</category>
      <category>코드업</category>
      <author>yujenius</author>
      <guid isPermaLink="true">https://yujenius.tistory.com/7</guid>
      <comments>https://yujenius.tistory.com/entry/Python-Code-up-4060-%EC%A0%84%EA%B4%91%ED%8C%90-%EC%A0%84%EA%B5%AC-%EC%A1%B0%EC%9E%91#entry7comment</comments>
      <pubDate>Sat, 8 Feb 2025 16:14:50 +0900</pubDate>
    </item>
    <item>
      <title>[Python] Code up 4024: 호수의 수 구하기</title>
      <link>https://yujenius.tistory.com/entry/Python-Code-up-4024-%ED%98%B8%EC%88%98%EC%9D%98-%EC%88%98-%EA%B5%AC%ED%95%98%EA%B8%B0</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://codeup.kr/problem.php?id=4024&amp;amp;rid=0&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://codeup.kr/problem.php?id=4024&amp;amp;rid=0&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1738951748440&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;호수의 수 구하기&quot; data-og-description=&quot;첫째 줄에 두 정수 W, H가 주어진다. (단, 4 &amp;lt;= W, H &amp;lt;= 100) 지도는 직사각형으로 이루어지며, W는 지도의 너비를 의미하고, H는 지도의 높이를 의미한다.&amp;nbsp; 두 번째 줄부터 H + 1번째 줄까지 각 줄 마다 '&quot; data-og-host=&quot;codeup.kr&quot; data-og-source-url=&quot;https://codeup.kr/problem.php?id=4024&amp;amp;rid=0&quot; data-og-url=&quot;https://codeup.kr/problem.php?id=4024&amp;amp;rid=0&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://codeup.kr/problem.php?id=4024&amp;amp;rid=0&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://codeup.kr/problem.php?id=4024&amp;amp;rid=0&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;호수의 수 구하기&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;첫째 줄에 두 정수 W, H가 주어진다. (단, 4 &amp;lt;= W, H &amp;lt;= 100) 지도는 직사각형으로 이루어지며, W는 지도의 너비를 의미하고, H는 지도의 높이를 의미한다.&amp;nbsp; 두 번째 줄부터 H + 1번째 줄까지 각 줄 마다 '&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;codeup.kr&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div id=&quot;pro2&quot; style=&quot;color: #212529; text-align: left;&quot;&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;문제 설명&lt;/b&gt;&amp;nbsp;&lt;/h3&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CodeUp 4024번 문제는 'L' 과 '.' 으로 구성된 지도를 통해 호수의 개수를 구하는 문제입니다. 이때 'L'은 호수를 의미하고 '.'은 비호수 지역을 의미합니다. 호수는 상, 하, 좌, 우, 대각선으로 연결된 모든 'L' 을 하나의 호수로 간주합니다.&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;717&quot; data-origin-height=&quot;566&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bc6wGh/btsMa7lDkr1/sUrlFJljNrUiKG5AwOUdb0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bc6wGh/btsMa7lDkr1/sUrlFJljNrUiKG5AwOUdb0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bc6wGh/btsMa7lDkr1/sUrlFJljNrUiKG5AwOUdb0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbc6wGh%2FbtsMa7lDkr1%2FsUrlFJljNrUiKG5AwOUdb0%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;519&quot; height=&quot;410&quot; data-origin-width=&quot;717&quot; data-origin-height=&quot;566&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;해결 접근법&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 이 문제를 마주했을 때, DFS 알고리즘을 활용해야겠다는 생각이 들었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DFS는 한 지점에서 시작해 갈 수 있는 모든 경로를 탐색하기 때문에 호수의 모든 연결 요소를 방문하는 데 적합하다고 생각했기 때문입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;소스코드&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1738951959594&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import sys
sys.setrecursionlimit(10**6) #기본 재귀 깊이 제한을 늘려주기 10의 6제곱으로 

def dfs(y,x): #dfs 함수 선언
    if y &amp;lt; 0 or y &amp;gt;= h or x &amp;lt; 0 or x &amp;gt;= w: #높이 와 너비보다 크거나 0 보다 작으면
        return
    if lake[y][x]==&quot;.&quot;: #.을 만나면
        return
    if lake[y][x]==&quot;L&quot;: # L을 만나면
        lake[y][x]=&quot;.&quot; # L을 . 으로 바꿔주고
        for d in range(8): #8방향 상, 하 , 좌 , 우 , 대각선 
            dfs(y+dy[d], x+dx[d])
        
w,h = map(int, input().split())
lake = []
for i in range(h):
    row = list(input().split()) #한 줄에 입력 받으려면 list로 
    lake.append(row)#lake 에 append(추가) 해주기

dx = [1, 1, 1, 0, 0, -1, -1, -1] #x좌표
dy = [-1, 0, 1, 1, -1, 0, 1, -1] #y좌표


cnt = 0 #호수의 개수 변수
for i in range(h):# 모든 좌표를 순회하면서 DFS 실행 
    for j in range(w):
        if lake[i][j] == &quot;L&quot;:
            dfs(i,j)
            cnt+=1
            
print(cnt)&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;제 코드는 순회하면서 돌다가 'L'을 발견하면 DFS 를 시작하고 연결된 모든 'L'을 방문 처리 합니다. 재귀함수로 만들어준 DFS 함수는 다음 미방문 'L'을 찾아 위 과정을 반복하게되고 ,&amp;nbsp; DFS 가 끝날때마다 호수의 개수를 증가시키게 해주었습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;또 다른 풀이법&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1738952260242&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 입력 받기
W, H = map(int, input().split())
map_data = [input().split() for _ in range(H)]

# 방향 벡터 (상, 하, 좌, 우, 대각선)
directions = [(-1, -1), (-1, 0), (-1, 1), (0, -1), (0, 1), (1, -1), (1, 0), (1, 1)]

# DFS 함수 정의
def dfs(x, y):
    # 현재 위치를 방문 처리
    map_data[x][y] = '.'
    for dx, dy in directions:
        nx, ny = x + dx, y + dy
        if 0 &amp;lt;= nx &amp;lt; H and 0 &amp;lt;= ny &amp;lt; W and map_data[nx][ny] == 'L':
            dfs(nx, ny)

lake_count = 0

# 모든 좌표를 순회하며 DFS 실행
for i in range(H):
    for j in range(W):
        if map_data[i][j] == 'L':
            dfs(i, j)
            lake_count += 1

print(lake_count)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;추가학습&lt;/b&gt;&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;BFS 개념 공부 및 관련 알고리즘 문제 풀이&lt;/li&gt;
&lt;li&gt;연결 요소 문제: 백준 4963 (섬의 개수), 2667(단지 번호 붙이기) 등의 문제 풀기&lt;/li&gt;
&lt;/ol&gt;</description>
      <category>알고리즘/Python</category>
      <category>python</category>
      <category>알고리즘공부</category>
      <category>알고리즘문제</category>
      <category>코드업</category>
      <category>호수의 수 구하기</category>
      <author>yujenius</author>
      <guid isPermaLink="true">https://yujenius.tistory.com/6</guid>
      <comments>https://yujenius.tistory.com/entry/Python-Code-up-4024-%ED%98%B8%EC%88%98%EC%9D%98-%EC%88%98-%EA%B5%AC%ED%95%98%EA%B8%B0#entry6comment</comments>
      <pubDate>Sat, 8 Feb 2025 03:22:35 +0900</pubDate>
    </item>
    <item>
      <title>깊이 우선 탐색 (DFS)</title>
      <link>https://yujenius.tistory.com/entry/%EA%B9%8A%EC%9D%B4-%EC%9A%B0%EC%84%A0-%ED%83%90%EC%83%89-DFS</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;DFS는 알고리즘 문제를 풀다 보면 꼭 마주하는 개념인 거 같은데요&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Code up 문제들을 풀면서 마주한 그래프 문제들을 DFS 문제들로 많이 해결해 왔기에&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오늘은 깊이 우선 탐색(DFS)에 대해 알아보고 어떤 상황에 활용하는 게 좋은지 정리해보려 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;DFS란 무엇인가?&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DFS(Depth-First Search) 는 그래프 탐색 알고리즘 중 하나로, 특정 경로를 끝까지 탐색한 후 다른 경로를 탐색하는 방식입니다. 스택 자료구조를 기반으로 동작하며, 재귀(Recursion) 또는 명시적 스택(Stack)을 사용하여 두 가지 방법으로 구현할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;DFS를 알아야 하는 이유&lt;/b&gt;&lt;/h4&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;DFS는 그래프 탐색의 기본적인 방법 중 하나로, 여러 가지 문제에서 응용 됩니다. 미로 탐색, 네트워크 연결확인, 퍼즐 문제 등 다양한 곳에서 사용됩니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. 백트래킹(Backtraking)의 핵심&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DFS는 백트래킹 기법을 사용할 때 기본적으로 활용됩니다. 백트래킹을 이해하려면 DFS를 숙지하는 것이 필수적입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. 효율적인 탐색&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;BFS(너비 우선 탐색)와 함께 DFS는 탐색 문제 해결의 핵심 도구로 활용되며, 문제의 특성에 따라 DFS를 선택하는 것이 효율적인 경우가 많습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;DFS의 동작 방식&lt;/b&gt;&lt;/h4&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;3. 더 이상 방문할 노드가 없다면 이전 노드로 되돌아가기&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;4. 모든 노드를 방문할 때까지 이 과정을 반복&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1974&quot; data-origin-height=&quot;1529&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bhmAPU/btsMbBsYOvG/RuLGHgeXLgLGtV09JphS11/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bhmAPU/btsMbBsYOvG/RuLGHgeXLgLGtV09JphS11/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bhmAPU/btsMbBsYOvG/RuLGHgeXLgLGtV09JphS11/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbhmAPU%2FbtsMbBsYOvG%2FRuLGHgeXLgLGtV09JphS11%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;504&quot; height=&quot;390&quot; data-origin-width=&quot;1974&quot; data-origin-height=&quot;1529&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;DFS 활용 예시&lt;/b&gt;&lt;/h4&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;DFS를 이용하면 미로에서 출구를 찾거나 특정 경로를 탐색할 수 있다.&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;N - Queen 문제, 순열 생성, 조합 문제 등 경우의 수를 모두 탐색해야 하는 문제에서 DFS를 활용할 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. 위상 정렬&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;방향 그래프에서 선행 관계가 있는 작업을 정렬하는 데 사용된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;4. 연결 요소 찾기&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래프에서 서로 연결된 그룹을 찾을 때 DFS를 활용할 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;마무리&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;DFS&lt;/b&gt;는 그래프 탐색에서 가장 기본적이고 중요한 알고리즘이다. 다양한 문제 해결에 활용되므로, 재귀와 스택을 활용한 구현 방법을 숙달하는 것이 중요하다. 앞으로 백트래킹, 위상 정렬, 경로 탐색 문제를 풀 때 DFS를 적극적으로 활용해 볼 계획이다.&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;다음 포스트에서는 DFS를 활용한 문제들 어떻게 풀었는지 소개하도록 하겠습니다.&lt;/p&gt;</description>
      <category>알고리즘</category>
      <category>dfs</category>
      <category>깊이우선탐색</category>
      <category>알고리즘</category>
      <category>알고리즘공부</category>
      <author>yujenius</author>
      <guid isPermaLink="true">https://yujenius.tistory.com/5</guid>
      <comments>https://yujenius.tistory.com/entry/%EA%B9%8A%EC%9D%B4-%EC%9A%B0%EC%84%A0-%ED%83%90%EC%83%89-DFS#entry5comment</comments>
      <pubDate>Sat, 8 Feb 2025 03:02:03 +0900</pubDate>
    </item>
    <item>
      <title>HTTP란?</title>
      <link>https://yujenius.tistory.com/entry/HTTP%EB%9E%80</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;736&quot; data-origin-height=&quot;552&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/crN1b9/btsL9ta3Okh/39F9o20IC04TxacAOulJc1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/crN1b9/btsL9ta3Okh/39F9o20IC04TxacAOulJc1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/crN1b9/btsL9ta3Okh/39F9o20IC04TxacAOulJc1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcrN1b9%2FbtsL9ta3Okh%2F39F9o20IC04TxacAOulJc1%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;546&quot; height=&quot;410&quot; data-origin-width=&quot;736&quot; data-origin-height=&quot;552&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 data-ke-size=&quot;size16&quot;&gt;또는 API 요청이 어떻게 이루어지는 궁금할 때가 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 모든 과정의 핵심에는 HTTP가 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오늘은 웹 개발의 기본이 되는 HTTP란 무엇인지, 그리고 어떤 원리로 동작하는지에 대해 알아보겠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;HTTP의 개념과 특징&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;353&quot; data-origin-height=&quot;143&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yrrHY/btsL9oU18Sv/dciNMfQkCzVMUIYySr08h0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yrrHY/btsL9oU18Sv/dciNMfQkCzVMUIYySr08h0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yrrHY/btsL9oU18Sv/dciNMfQkCzVMUIYySr08h0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FyrrHY%2FbtsL9oU18Sv%2FdciNMfQkCzVMUIYySr08h0%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;427&quot; height=&quot;173&quot; data-origin-width=&quot;353&quot; data-origin-height=&quot;143&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;HTTP 란 HyperText Transfer Protocol&lt;/b&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;HTTP 는 WWW(World Wide Web) 상에서 데이터를 주고 받기 위한 프로토콜로&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서버 간의 &lt;span style=&quot;background-color: #ffc1c8; color: #ee2323;&quot;&gt;요청(request) 과 응답(response)&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;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;HTTP의 특징에는 &lt;b&gt;비연결, 무상태&lt;/b&gt; 두가지가 존재한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1.&lt;b&gt; 비연결&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HTTP는 비연결 방식이기 때문에 요청 , 응답 과정이 끝나면 서버와의 연결을 종료한다&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;이를 &lt;b&gt;Keep-Alive&lt;/b&gt; 옵션 추가로 하나의 연결을 유지하면서 여러 개의 요청을 처리할 수 있도록 개선되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2.&lt;b&gt; 무상태&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HTTP는 무상태 방식이므로, 서버는 클라이언트의 이전 요청 정보를 저장하지 않는다.&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;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;쿠키(Cookie): 클라이언트에 저장된 데이터(자동 전송됨)&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;세션(Session): 서버에 저장된 데이터 (세션 ID를 쿠키로 관리)&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;JWT(JSON Web Token): 토큰 기반 인증 방식 (서버 부담을 줄이면서 보안 유지 가능)&lt;/b&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음에 더 자세히 소개하도록 하겠다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;HTTP의 단점&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 HTTP는 단점이 있다 .&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;물론 이를 해결하기 위해 나온 것이 HTTPS(Hypertext Transfer Protocol Secure)다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HTTP에 SSL(Secure Socket Layer) 와 TLS(Transport Layer Security) 프로토콜을 통해 암호화된 상태로 전송이 가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;**HTTP 요청 메서드**&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메서드들은 api 통신을 위해 반드시 알아둬야 하는 개념들이다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;GET : 정보를 요청하기 위한 (조회)&lt;/li&gt;
&lt;li&gt;POST : 서버에 데이터를 전송할 떄 사용 (등록)&lt;/li&gt;
&lt;li&gt;PUT: 정보를 업데이트(갱신)하기 위해 사용, 정보 변경(수정)&lt;/li&gt;
&lt;li&gt;DELETE: 정보를 삭제하기 위해 사용 (삭제)&lt;/li&gt;
&lt;li&gt;PATCH: 리소스의 일부분을 수정&lt;/li&gt;
&lt;li&gt;OPTIONS: 서버에서 지원하는 HTTP 메서드의 목록을 요청할 때 사용&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본적으로 가장 많이 사용하는 메서드는 &lt;b&gt;GET, POST, PUT, DELETE&lt;/b&gt; 가 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 포스트에서 이어서 자세하게 소개하도록 하겠다.&lt;/p&gt;</description>
      <category>네트워크</category>
      <category>HTTP</category>
      <category>t|l</category>
      <category>개발공부</category>
      <category>네트워크</category>
      <category>웹기초</category>
      <author>yujenius</author>
      <guid isPermaLink="true">https://yujenius.tistory.com/4</guid>
      <comments>https://yujenius.tistory.com/entry/HTTP%EB%9E%80#entry4comment</comments>
      <pubDate>Fri, 7 Feb 2025 03:00:33 +0900</pubDate>
    </item>
    <item>
      <title>React에서 API 통신: fetch API vs axios 무엇을 선택할까?</title>
      <link>https://yujenius.tistory.com/entry/React%EC%97%90%EC%84%9C-API-%ED%86%B5%EC%8B%A0-fetch-API-vs-axios-%EB%AC%B4%EC%97%87%EC%9D%84-%EC%84%A0%ED%83%9D%ED%95%A0%EA%B9%8C</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;278&quot; data-origin-height=&quot;206&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cS15cO/btsL8fj0KNg/fgKm1ysutCG0ZqgWYO7ON0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cS15cO/btsL8fj0KNg/fgKm1ysutCG0ZqgWYO7ON0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cS15cO/btsL8fj0KNg/fgKm1ysutCG0ZqgWYO7ON0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcS15cO%2FbtsL8fj0KNg%2FfgKm1ysutCG0ZqgWYO7ON0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;278&quot; height=&quot;206&quot; data-origin-width=&quot;278&quot; data-origin-height=&quot;206&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;React 개발을 하면서 서버와 데이터를 주고 받는 기능은 필수적이다&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;API 요청을 보낼 때 대표적으로 사용되는 방법으로는 &lt;b&gt;fetch API&lt;/b&gt; 와 &lt;b&gt;axios&lt;/b&gt; 가 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;나는 개발을 하면서 두 방법 중 어떤 것이 더 나을까? 라는 고민이 있었다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;이 글에서는 fetch API 와 axios를 비교하고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;React 프로젝트에서&amp;nbsp;어떤 상황에서&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;어떤 방법을 선택해야 하는지 알아보도록 하겠다.&amp;nbsp;&lt;/p&gt;
&lt;h2 data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span&gt;fetch API vs axios 비교&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. fetch API&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1738824066549&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const fetchData = async () =&amp;gt; {
  try {
    const response = await fetch('https://example.com/api', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({ key: 'value' })
    });

    if (!response.ok) throw new Error(`HTTP error! Status: ${response.status}`);

    const data = await response.json();
    console.log('Fetch API Response:', data);
  } catch (error) {
    console.error('Fetch API Error:', error);
  }
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span&gt;2. axios&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1738824099001&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import axios from 'axios';

const fetchData = async () =&amp;gt; {
  try {
    const response = await axios.post('https://example.com/api', {
      key: 'value'
    });
    console.log('Axios Response:', response.data);
  } catch (error) {
    console.error('Axios Error:', error);
  }
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 가지 방법의 장점을 비교해 보았을 때,&lt;/p&gt;
&lt;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;fetch API 의 장점&lt;/b&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-pm-slice=&quot;3 1 []&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;추가 라이브러리 없이 사용 가능&lt;/b&gt;&lt;/span&gt;&lt;span&gt;: 브라우저에 내장된 API로 가볍게 사용 가능&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;Promise 기반&lt;/b&gt;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;async/await&lt;/span&gt;&lt;span&gt;을 활용하여 비동기 처리 가능&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;최신 웹 표준&lt;/b&gt;&lt;/span&gt;&lt;span&gt;: 브라우저에서 최적화되어 동작&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span&gt;axios 의 장점&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-pm-slice=&quot;3 3 []&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;자동 JSON 변환&lt;/b&gt;&lt;/span&gt;&lt;span&gt;: 응답 데이터를 JSON으로 자동 변환&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;타임아웃 설정 가능&lt;/b&gt;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;fetch&lt;/span&gt;&lt;span&gt;는 기본 타임아웃이 없지만, &lt;/span&gt;&lt;span&gt;axios&lt;/span&gt;&lt;span&gt;는 &lt;/span&gt;&lt;span&gt;timeout&lt;/span&gt;&lt;span&gt; 옵션 제공&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;요청 및 응답 인터셉터 지원&lt;/b&gt;&lt;/span&gt;&lt;span&gt;: 요청 및 응답을 가로채서 변형할 수 있음&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;더 나은 오류 처리&lt;/b&gt;&lt;/span&gt;&lt;span&gt;: HTTP 오류(404, 500 등)를 예외로 처리 가능&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;각각의 장점에 맞게&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;b&gt;fetch API&lt;/b&gt; 의 경우에는 추가 라이브러리 없이 가볍게 사용하거나 &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;브라우저 내장 기능을 활용하여 최소한의 의존성으로 개발하고 싶을 때 사용하는 것이 좋고&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;b&gt;axios&lt;/b&gt; 의 경우에는 JSON 자동 변환, 타임아웃, 인터셉터 등 추가 기능이 필요하거나 &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;async/await 기반의 간결한 코드 작성을 원할 때&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;React 프로젝트에서 API 호출을 많이 사용해야 할 때 사용하는 것이 좋을 것이다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span&gt;결론&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;React에서 API 호출을 할 때 fetch API 와 axios 는 각각의 장점이 있다 &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;React 프로젝트에서 API 통신을 효율적으로 관리하고 싶다면, 두 방법의 활용도 그리고 장단점을 잘 이해하여 프로젝트에 맞게 선택하여 개발하는 것이 가장 좋은 방법 같다 &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>프론트엔드/React</category>
      <category>api 통신</category>
      <category>axios</category>
      <category>fetch api</category>
      <category>react</category>
      <category>개발 공부</category>
      <author>yujenius</author>
      <guid isPermaLink="true">https://yujenius.tistory.com/3</guid>
      <comments>https://yujenius.tistory.com/entry/React%EC%97%90%EC%84%9C-API-%ED%86%B5%EC%8B%A0-fetch-API-vs-axios-%EB%AC%B4%EC%97%87%EC%9D%84-%EC%84%A0%ED%83%9D%ED%95%A0%EA%B9%8C#entry3comment</comments>
      <pubDate>Thu, 6 Feb 2025 15:56:41 +0900</pubDate>
    </item>
    <item>
      <title>돔(DOM) 과 가상돔(Virtual DOM)</title>
      <link>https://yujenius.tistory.com/entry/%EB%8F%94DOM-%EA%B3%BC-%EA%B0%80%EC%83%81%EB%8F%94Virtual-DOM</link>
      <description>&lt;p data-ke-size=&quot;size18&quot;&gt;프론트 엔드 공부를 시작하면 가장 많이 마주하게 되는 게 DOM 이라고 생각한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;특히, 리액트 와 같은 라이브러리를 사용할 때,&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;가장 큰 차이점은 Virtual DOM 을 사용한다는 것이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;이번 글에서는 DOM 과 가상 DOM의 차이점, 그리고 실제 개발에서 이를 어떻게 활용하면 좋을지 살펴보겠다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;DOM (Document Object Model) 이란?&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;DOM 은 HTML 문서를 브라우저가 해석하여 생성하는 트리 구조의 객체 모델이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;즉 웹페이지의 요소들을 JavaScript를 통해 조작할 수 있도록 해주는 역할을 해준다.&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;1280&quot; data-origin-height=&quot;554&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rR8Hl/btsL9a9mAIN/vnGhBnke0o9Tv1kKsObvjk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rR8Hl/btsL9a9mAIN/vnGhBnke0o9Tv1kKsObvjk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rR8Hl/btsL9a9mAIN/vnGhBnke0o9Tv1kKsObvjk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrR8Hl%2FbtsL9a9mAIN%2FvnGhBnke0o9Tv1kKsObvjk%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;698&quot; height=&quot;302&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;554&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;그러나 본래의 DOM 은 몇가지의 단점이 존재한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;DOM의 경우 변경이 많아질수록 브라우저의 렌더링 성능이 떨어진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;이는 비효율적인 업데이트를 하기 떄문인데,&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;요소 하나를 변경할 때마다 전체 레이아웃이 다시 계산되기 때문에 성능이 현저히 떨어진다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;특히 이러한 단점들이 큰 규모의 프로그램을 개발하게 된다면 그만큼 업데이트가 잦아지기 때문에&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;효율적이지 못하게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;바로 이러한 문제를 해결하기 위해 등장한 개념이 바로 &lt;b&gt;가상 DOM(Virtual DOM)&lt;/b&gt; 이다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;가상 DOM(Virtual DOM) 이란?&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;가상 DOM은 실제 DOM을 조작하기 전에, 메모리상에 존재하는 가상의 DOM을 먼저 변경하고, 최적화된 변경 사항만 실제 DOM에 반영하는 방식을 의미한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;React 로 예를 든다면,&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;React는 상태가 변경될 때마다 가상 DOM을 생성하고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;기존 가상 DOM과 비교하여 변경된 부분만 실제 DOM에 적용한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;이러한 방식은 DOM을 죄소한으로 조작 하여 처리 횟수를 최소화한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1173&quot; data-origin-height=&quot;785&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/QFN8m/btsL9LgZMod/cmI6LQWqM5tNZseuV5SW41/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/QFN8m/btsL9LgZMod/cmI6LQWqM5tNZseuV5SW41/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/QFN8m/btsL9LgZMod/cmI6LQWqM5tNZseuV5SW41/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQFN8m%2FbtsL9LgZMod%2FcmI6LQWqM5tNZseuV5SW41%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;785&quot; data-origin-width=&quot;1173&quot; data-origin-height=&quot;785&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;그래서 리액트에서는 상태가 변경되면,&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1. 새로운 가상 DOM 을 생성하고&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;2. 이전 가상 DOM 과 새로운 가상 DOM 을 비교하여 변경된 부분을 찾고&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;3. 변경된 부분만 실제 DOM에 반영한다&lt;/b&gt;.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;이 과정을 거치게 되면 불필요한 DOM 조작을 줄이고, 성능을 향상시킬 수 있다.&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;size18&quot;&gt;DOM 과 가상 DOM 을 이해하는 것은 단순히 개념을 아는 것을 넘어서, 실제 프로젝트에서 최적화된 성능을 내기 위해 필수적이다. 가상 DOM 을 사용헀다고 하여서 성능이 좋아지는 것은 아니지만 작은 규모의 프로젝트에서는 직접 DOM을 조작하는 것이 더 빠를 수도 있고, React 와 같은 라이브러리를 사용할 때도 불필요한 렌더링을 줄이는 것이 중요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>프론트엔드/React</category>
      <category>react</category>
      <category>돔(dom) 과 가상돔(virtual dom)</category>
      <category>리액트</category>
      <author>yujenius</author>
      <guid isPermaLink="true">https://yujenius.tistory.com/2</guid>
      <comments>https://yujenius.tistory.com/entry/%EB%8F%94DOM-%EA%B3%BC-%EA%B0%80%EC%83%81%EB%8F%94Virtual-DOM#entry2comment</comments>
      <pubDate>Thu, 6 Feb 2025 02:54:02 +0900</pubDate>
    </item>
  </channel>
</rss>