<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>오늘도 개발</title>
    <link>https://sue-is-programming.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Fri, 22 May 2026 22:40:04 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>Sueeeeeee</managingEditor>
    <item>
      <title>리액트 컴포넌트와 state, props</title>
      <link>https://sue-is-programming.tistory.com/313</link>
      <description>&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;1. 컴포넌트&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;재사용 가능한 UI 단위(=레고 블럭).&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;컴포넌트를 사용하는 이유&lt;/b&gt;&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. 유지보수가 쉬움&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 페이지 구성 파악 쉬움&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;컴포넌트 생성 방식&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;- 함수 컴포넌트 : 초기에 state를 관리할 수 없어서 잘 사용하지 않았으나,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;16.8 버전에서 hooks가 추가되며 state를 관리할 수 있게 되며 많이 사용하게 됨.&lt;/p&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;2.   props(=properties)&lt;/b&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;읽기 전용 값이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;부모 컴포넌트에서 props를 전달받아 원하는 컴포넌트에서 사용한다. (함수의 파라미터와 비슷)&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;pre id=&quot;code_1703057731276&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function Child(props) {
  console.log(props); // {titleColor: 'red'}
  return (
    &amp;lt;div&amp;gt;
      &amp;lt;h1 style={{ color: props.titleColor }}&amp;gt;Child Component&amp;lt;/h1&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}

function Parent() {
  return (
    &amp;lt;div&amp;gt;
      &amp;lt;h1&amp;gt;Parent&amp;lt;/h1&amp;gt;
      &amp;lt;Child titleColor=&quot;red&quot; /&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예시2) props로 자식 컴포넌트에게 이벤트 핸들러 전달하기&lt;/p&gt;
&lt;pre id=&quot;code_1703059021276&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function Child(props) {
  return (
    &amp;lt;div&amp;gt;
      &amp;lt;h1 style={{ color: props.titleColor }}&amp;gt;Child Component&amp;lt;/h1&amp;gt;
      &amp;lt;button onClick={props.changeColor}&amp;gt;Click&amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}

function Signup() {
  const [color, setColor] = useState(&quot;red&quot;);

  return (
    &amp;lt;div&amp;gt;
      &amp;lt;h1&amp;gt;Parent&amp;lt;/h1&amp;gt;
      &amp;lt;Child titleColor={color} changeColor={() =&amp;gt; setColor(&quot;blue&quot;)} /&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}&lt;/code&gt;&lt;/pre&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;3.   state&lt;/b&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;업데이트 할 수 있는 값이다.&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;예시 1)&lt;/p&gt;
&lt;pre id=&quot;code_1703054502162&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React, { useState } from &quot;react&quot;;

function Greet() {
// useState 함수는 [상태값(state)을 저장하는 변수, 상태값을 갱신하는 함수]를 배열로 반환한다.
// useState에 인자로 넣은 값이 상태값(count)의 초깃값이 된다.
  const [color, setColor] = useState('blue'); 

  return (
    &amp;lt;div&amp;gt;
      &amp;lt;h1 style={{ color: color }} &amp;gt;Hello&amp;lt;/h1&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}

export default Greet;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예시 2) Event&lt;/p&gt;
&lt;pre id=&quot;code_1703055429435&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React, { useState } from &quot;react&quot;;

function Greet() {
  let [color, setColor] = useState(&quot;red&quot;);

  return (
    &amp;lt;div&amp;gt;
      &amp;lt;h1 style={{ color: color }}&amp;gt;hello&amp;lt;/h1&amp;gt;
      &amp;lt;button onClick={() =&amp;gt; setColor(&quot;blue&quot;)}&amp;gt;Click&amp;lt;/button&amp;gt; 
      // 버튼 클릭 시 color 변수의 값을 blue로 바꿈
    &amp;lt;/div&amp;gt;
  );
}

export default Greet;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>웹 프로그래밍/Javascript</category>
      <author>Sueeeeeee</author>
      <guid isPermaLink="true">https://sue-is-programming.tistory.com/313</guid>
      <comments>https://sue-is-programming.tistory.com/313#entry313comment</comments>
      <pubDate>Wed, 20 Dec 2023 16:13:35 +0900</pubDate>
    </item>
    <item>
      <title>리액트 Hook</title>
      <link>https://sue-is-programming.tistory.com/312</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Hook이란?&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;함수 컴포넌트에서 state를 사용할 수 있게 해주는 기능.&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;Hook 도입 전에는 클래스 컴포넌트에서만 state를 사용할 수 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클래스는 함수보다 작성이 까다롭기 때문에, Hook 등장 이후로는 거의 사용하지 않는다.&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;클래스형 컴포넌트 VS 함수 컴포넌트&lt;/b&gt;&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;함수는 한 번 호출되면 메모리 상에서 사라지기 때문에, state를 가질 수 없었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;=&amp;gt; 클로저를 사용하면 함수도 state를 가질 수 있다. 이를 이용해서 Hook이 등장했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Hook 사용 규칙&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. 최상위 레벨에서만 Hook을 호출해야 한다.&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반복문, 조건문, 중첩 함수 내에서 호출하면 오류가 난다.&lt;/p&gt;
&lt;pre id=&quot;code_1703053504045&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React, { useState } from &quot;react&quot;

function Hooks(props) {
  if (!props.isExist) {
    const [state, setState] = useState(); // Error!
  }

  const [state2, setState2] = useState(); // 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;b&gt;2. React 함수 컴포넌트 내에서만 Hook을 호출해야 한다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반 js 함수에서는 호출할 수 없다.&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;b&gt;참고&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;a href=&quot;https://legacy.reactjs.org/docs/hooks-overview.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;React 공식문서 - Hooks at a Glance&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.w3schools.com/react/react_hooks.asp#:~:text=Hooks%20were%20added%20to%20React,to%20remove%20classes%20from%20React.&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;w3schools - React Hooks&lt;/a&gt;&lt;/p&gt;</description>
      <category>웹 프로그래밍/Javascript</category>
      <author>Sueeeeeee</author>
      <guid isPermaLink="true">https://sue-is-programming.tistory.com/312</guid>
      <comments>https://sue-is-programming.tistory.com/312#entry312comment</comments>
      <pubDate>Wed, 20 Dec 2023 15:26:30 +0900</pubDate>
    </item>
    <item>
      <title>react-router 사용하기</title>
      <link>https://sue-is-programming.tistory.com/311</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;1. SPA란?&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Single Page Application. 즉, 페이지가 하나인 애플리케이션.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리액트 프로젝트에서 html 파일 개수는 1개이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한 개의 html을 사용해서 여러 개의 페이지를 보여주려면 routing이 필요하다.&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;2. Routing이란?&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;url 경로에 따라 다른 화면을 보여주는 것.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리액트에는 라우팅 기능이 없으므로 라우팅을 지원하는 라이브러리를 사용해야 한다.&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;3. react-router&lt;/b&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1) 설치&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1703027631562&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;npm install react-router-dom&lt;/code&gt;&lt;/pre&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;src/pages/Login.js&lt;/p&gt;
&lt;pre id=&quot;code_1703029851305&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React from &quot;react&quot;;
import { Link } from &quot;react-router-dom&quot;;

function Login() {
  return (
    &amp;lt;div&amp;gt;
      &amp;lt;Link to=&quot;/signup&quot;&amp;gt;회원가입&amp;lt;/Link&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}

export default Login;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;src/pages/Signup.js&lt;/p&gt;
&lt;pre id=&quot;code_1703030130602&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React from &quot;react&quot;;

function Signup() {
  return &amp;lt;h1&amp;gt;Signup&amp;lt;/h1&amp;gt;;
}

export default Signup;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3) Router 컴포넌트 만들기&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;src/Router.js&lt;/p&gt;
&lt;pre id=&quot;code_1703029775985&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React from &quot;react&quot;;
import { BrowserRouter, Routes, Route } from &quot;react-router-dom&quot;;

import Login from &quot;./pages/Login&quot;;
import Signup from &quot;./pages/Signup&quot;;

function Router() {
  return (
    &amp;lt;BrowserRouter&amp;gt;
      &amp;lt;Routes&amp;gt;
        &amp;lt;Route path=&quot;/login&quot; element={&amp;lt;Login /&amp;gt;} /&amp;gt;
        &amp;lt;Route path=&quot;/signup&quot; element={&amp;lt;Signup /&amp;gt;} /&amp;gt;
      &amp;lt;/Routes&amp;gt;
    &amp;lt;/BrowserRouter&amp;gt;
  );
}

export default Router;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;4) index.js에 App 대신 Router 넣기&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1703030189803&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React from 'react';
import ReactDOM from 'react-dom/client';
import Router from './Router';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  &amp;lt;React.StrictMode&amp;gt;
    &amp;lt;Router /&amp;gt;
  &amp;lt;/React.StrictMode&amp;gt;
);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;* 라우트 이동하는 방법&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1) &amp;lt;Link&amp;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; 프로젝트 내에서 페이지 전환할 때 사용.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; DOM에서 &amp;lt;a&amp;gt; 태그로 변환됨.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; ex) 썸네일 클릭 시 상세페이지로 이동&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) useNavigate 훅 사용하기&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; ex) 로그인 버튼 클릭 시, 입력 정보에 따라 인증/인가 처리 후 각기 다른 페이지로 이동&lt;/p&gt;
&lt;pre id=&quot;code_1703030824815&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React from &quot;react&quot;;
import { Link, Navigate } from &quot;react-router-dom&quot;;
import { useNavigate } from &quot;react-router-dom&quot;;

function Login() {
  const navigate = useNavigate();
  const goToSignup = () =&amp;gt; {
    alert(&quot;회원가입을 해주세요&quot;);
    navigate('/signup');
  }
  return (
    &amp;lt;div&amp;gt;
      &amp;lt;button className=&quot;loginBtn&quot; onClick={goToSignup}&amp;gt;로그인&amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;
  )
}

export default Login;&lt;/code&gt;&lt;/pre&gt;</description>
      <category>웹 프로그래밍/Javascript</category>
      <author>Sueeeeeee</author>
      <guid isPermaLink="true">https://sue-is-programming.tistory.com/311</guid>
      <comments>https://sue-is-programming.tistory.com/311#entry311comment</comments>
      <pubDate>Wed, 20 Dec 2023 09:07:15 +0900</pubDate>
    </item>
    <item>
      <title>JSX란</title>
      <link>https://sue-is-programming.tistory.com/310</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;JSX(Javascript Syntax Extension)&lt;/b&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;js와 html을 합쳐놓은 것 같은 형태.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;jsx 코드는 자바스크립트가 인식할 수 없는 문법이므로, Babel로 변환해야 함.&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;1. html 태그를 그대로 사용할 수 있음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. html 마크업과 js 로직을 같이 구현 가능&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. js 문법을 이용해서 html 생성 가능(별도의 html 파일이 필요 없음)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. DOM과 Event를 사용하는 기존 방식보다 작성 편리&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;1. 모든 jsx는 하나의 부모태그를 가져야 함.&lt;/p&gt;
&lt;pre id=&quot;code_1702971787160&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// GOOD
function Hello() {
   return &amp;lt;h1&amp;gt;Hello&amp;lt;/h1&amp;gt;
}

// GOOD
function Hello() {
   return (
   &amp;lt;&amp;gt;
     &amp;lt;h1&amp;gt;Hello&amp;lt;/h1&amp;gt;
     &amp;lt;h2&amp;gt;Hello2&amp;lt;/h2&amp;gt;
   &amp;lt;/&amp;gt;
   )
}

// 오류 발생
function Hi(){
   return &amp;lt;h1&amp;gt;hi&amp;lt;/h1&amp;gt;&amp;lt;h2&amp;gt;hihi&amp;lt;/h2&amp;gt;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 모든 태그는 self closing이 가능함&lt;/p&gt;
&lt;pre id=&quot;code_1702972812398&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function Login() {
   return &amp;lt;div /&amp;gt;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. camelCase만 사용&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. JSX 내에서 자바스크립트 동작 가능&lt;/p&gt;</description>
      <category>웹 프로그래밍/Javascript</category>
      <author>Sueeeeeee</author>
      <guid isPermaLink="true">https://sue-is-programming.tistory.com/310</guid>
      <comments>https://sue-is-programming.tistory.com/310#entry310comment</comments>
      <pubDate>Tue, 19 Dec 2023 17:01:33 +0900</pubDate>
    </item>
    <item>
      <title>리액트 개요</title>
      <link>https://sue-is-programming.tistory.com/309</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;1. 프론트엔드 기술의 변천&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1세대&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HTML, CSS, Javascript, DOM, Event&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2세대&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;jQuery - 자바스크립트를 간단하게 작성하기 위해 등장&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;BUT 웹이 복잡해지면서 한계에 도달(DOM을 조작하는 단계에서 멈춤)&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;3세대&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프레임워크 : Angular, Vue&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;라이브러리 : React&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;2. 프레임워크 VS 라이브러리&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;프레임워크&lt;/b&gt;&lt;/p&gt;
&lt;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;(ex. 냄비, 국자, 라면이 구비된 부엌)&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;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;도구&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(ex. 냄비)&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 style=&quot;color: #000000;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;3. 리액트란?&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2013년 페이스북에서 개발한 라이브러리.&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;특징&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자 수가 가장 많음 =&amp;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;React Native를 사용하면 웹이 아닌 플랫폼에서도 사용 가능.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Angular, Vue와 달리 자바스크립트 문법 그대로 사용 =&amp;gt; 러닝커브 낮음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Angular, Vue와 달리 View만 담당 =&amp;gt; 내장된 기능이 부족하므로 보통 다른 라이브러리와 함께 사용&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;선언적&lt;/span&gt;인 개발이 가능함(UI를 자동으로 업데이트 해 줌).&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;UI를 자동으로 업데이트하며 &lt;span style=&quot;color: #ee2323;&quot;&gt;VirtualDOM&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;b&gt;절차적 개발 &lt;b&gt;VS &lt;/b&gt;&lt;b&gt;선언적 개발&lt;/b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;방 청소를 예시로 들면,&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;절차적 개발은 어떻게(How) 목적을 이룰 것인지, 절차에 신경을 써야 한다.&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. 청소기를 돌린다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 걸레질을 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;선언적 개발 이룰 목적(What)이 무엇인지에만 신경을 쓰면 된다.&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. 로봇에게 그림을 전달한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자는 How가 아니라 What에만 신경을 쓰면 된다.&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;VirtualDOM&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;/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;VirtualDOM을 사용하지 않는 경우,&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;/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;VirtualDOM을 사용하는 경우,&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;브라우저는 우리가 DOM을 조작할 때마다 레이아웃을 변경하고, 색을 칠하는 과정을 반복한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;VirtualDOM을 사용하면, 필요한 변경사항을 가상의 DOM에 적용했다가 실제 DOM에 한 번에 반영한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2023-12-19 오후 1.43.42.png&quot; data-origin-width=&quot;1220&quot; data-origin-height=&quot;826&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oBH0b/btsB7VWNFlV/q9EHxX3PKg63WC7tNMYkik/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oBH0b/btsB7VWNFlV/q9EHxX3PKg63WC7tNMYkik/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oBH0b/btsB7VWNFlV/q9EHxX3PKg63WC7tNMYkik/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoBH0b%2FbtsB7VWNFlV%2Fq9EHxX3PKg63WC7tNMYkik%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;266&quot; height=&quot;180&quot; data-filename=&quot;스크린샷 2023-12-19 오후 1.43.42.png&quot; data-origin-width=&quot;1220&quot; data-origin-height=&quot;826&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;4. Node&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Node&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;/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;NPM(Node Package Manager)&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;NPM : Node에서 사용할 수 있는 여러 프로그램을 관리하는 프로그램.&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;CRA(Create-React-App)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리액트 개발환경을 구축해주는 도구(toolchain)&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;위코드 [React] 학습자료&lt;/p&gt;</description>
      <category>웹 프로그래밍/Javascript</category>
      <author>Sueeeeeee</author>
      <guid isPermaLink="true">https://sue-is-programming.tistory.com/309</guid>
      <comments>https://sue-is-programming.tistory.com/309#entry309comment</comments>
      <pubDate>Tue, 19 Dec 2023 14:02:13 +0900</pubDate>
    </item>
    <item>
      <title>비교 연산자 ==와 ===</title>
      <link>https://sue-is-programming.tistory.com/308</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;1. 일치 연산자 ===&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;엄격한 비교.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;값과 타입이 모두 일치해야 True.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;2. 동등 연산자 ==&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;느슨한 비교.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;값만 일치하면 True.&lt;/p&gt;
&lt;pre id=&quot;code_1701740183969&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&quot;5&quot; === 5 // false
&quot;5&quot; == 5 // true&lt;/code&gt;&lt;/pre&gt;</description>
      <category>웹 프로그래밍/Javascript</category>
      <author>Sueeeeeee</author>
      <guid isPermaLink="true">https://sue-is-programming.tistory.com/308</guid>
      <comments>https://sue-is-programming.tistory.com/308#entry308comment</comments>
      <pubDate>Tue, 5 Dec 2023 10:36:28 +0900</pubDate>
    </item>
    <item>
      <title>Postgres 실행중인 쿼리 보기/취소하기</title>
      <link>https://sue-is-programming.tistory.com/306</link>
      <description>&lt;div&gt;&lt;b data-stringify-type=&quot;bold&quot;&gt;실행중인 쿼리 확인하기&lt;/b&gt;&lt;/div&gt;
&lt;pre class=&quot;pgsql&quot; data-stringify-type=&quot;pre&quot;&gt;&lt;code&gt;SELECT *
FROM pg_stat_activity
--where state='idle' 상태가 idle인 것만 보기
--ORDER BY query_start ASC; 최근에 실행된 쿼리 순으로 정렬&lt;/code&gt;&lt;/pre&gt;
&lt;div&gt;&lt;b data-stringify-type=&quot;bold&quot;&gt;실행중인 쿼리 취소하기&lt;/b&gt;&lt;/div&gt;
&lt;pre class=&quot;pgsql&quot; data-stringify-type=&quot;pre&quot;&gt;&lt;code&gt;SELECT pg_terminate_backend(&amp;lt;pid of the process&amp;gt;)&lt;/code&gt;&lt;/pre&gt;</description>
      <category>웹 프로그래밍/DB</category>
      <author>Sueeeeeee</author>
      <guid isPermaLink="true">https://sue-is-programming.tistory.com/306</guid>
      <comments>https://sue-is-programming.tistory.com/306#entry306comment</comments>
      <pubDate>Mon, 6 Mar 2023 19:13:12 +0900</pubDate>
    </item>
    <item>
      <title>update와 bulk_update</title>
      <link>https://sue-is-programming.tistory.com/302</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Writer 인스턴스의 id가 2, 4, 6, 8, 10인 것만 policy=True로 설정된 상태.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;policy 필드가 True인 인스턴스의 policy_second 필드도 True로 업데이트하는 상황 가정.&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;1. iteration과 save 사용&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;업데이트 대상이 100개라면 UPDATE문이 100번 실행됨.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실행 속도가 느리고, 첫줄에서부터 save()를 실행할 때 까지 데이터에 변경이 일어날 수 있다는 것이 단점.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;수많은 row에 한꺼번에 락을 걸지 않는다는 것이 장점.&lt;/p&gt;
&lt;pre id=&quot;code_1677477956624&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;writers = Writer.objects.filter(policy=True)
for writer in writers:
   writer.policy_second = True
   writer.save()&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1677478129339&quot; class=&quot;sql&quot; data-ke-language=&quot;sql&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;SELECT &quot;writers&quot;.&quot;id&quot;, &quot;writers&quot;.&quot;description&quot;, &quot;writers&quot;.&quot;policy&quot;, &quot;writers&quot;.&quot;policy_second&quot; FROM &quot;writers&quot; WHERE &quot;writers&quot;.&quot;policy&quot;; args=(); alias=default
UPDATE &quot;writers&quot; SET &quot;description&quot; = 'abc', &quot;policy&quot; = 1, &quot;policy_second&quot; = 1 WHERE &quot;writers&quot;.&quot;id&quot; = 2; args=('abc', True, True, 2); alias=default
UPDATE &quot;writers&quot; SET &quot;description&quot; = 'abc', &quot;policy&quot; = 1, &quot;policy_second&quot; = 1 WHERE &quot;writers&quot;.&quot;id&quot; = 4; args=('abc', True, True, 4); alias=default
UPDATE &quot;writers&quot; SET &quot;description&quot; = 'abc', &quot;policy&quot; = 1, &quot;policy_second&quot; = 1 WHERE &quot;writers&quot;.&quot;id&quot; = 6; args=('abc', True, True, 6); alias=default
UPDATE &quot;writers&quot; SET &quot;description&quot; = 'abc', &quot;policy&quot; = 1, &quot;policy_second&quot; = 1 WHERE &quot;writers&quot;.&quot;id&quot; = 8; args=('abc', True, True, 8); alias=default
UPDATE &quot;writers&quot; SET &quot;description&quot; = 'abc', &quot;policy&quot; = 1, &quot;policy_second&quot; = 1 WHERE &quot;writers&quot;.&quot;id&quot; = 10; args=('abc', True, True, 10); alias=default&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;2. update 사용&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;UPDATE.. WHERE..문이 한 번만 실행됨.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;WHERE로 잡힌 업데이트 대상이 100개라면 100개에 락이 걸림.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실행 속도가 빠르고 실행 중 데이터가 변경될 염려 없음.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;업데이트 대상이 되는 row의 개수가 적을 때만 추천.&lt;/p&gt;
&lt;pre id=&quot;code_1677478258952&quot; class=&quot;sql&quot; data-ke-language=&quot;sql&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Writer.objects.filter(policy=True).update(policy_second=True)&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1677478381477&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;UPDATE &quot;writers&quot; SET &quot;policy_second&quot; = 1 WHERE &quot;writers&quot;.&quot;policy&quot;; args=(True,); alias=default&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;3. bulk_update 사용&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1, 2번 절충 가능.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;batch_size로 한 번에 업데이트할 row의 개수 지정할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;업데이트 대상이 100개이고 batch_size를 20으로 지정하면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- 20개 row에 락을 걸고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- UPDATE를 실행하고&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;과정을 5번 반복한다.&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;(Queryset.update()에는 트랜잭션이 적용된다.)&lt;/p&gt;
&lt;pre id=&quot;code_1677481538057&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;writers = Writer.objects.filter(policy=True)
writers_to_update = []

for writer in writers:
    writer.policy_second = True
    writers_to_update.append(writer)
    
Writer.objects.bulk_update(writers, ['policy_second'], batch_size=2)
# writer 인스턴스를 2개씩 끊어 업데이트&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;for writer in writers 시 호출&lt;/p&gt;
&lt;pre id=&quot;code_1677482796794&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;SELECT &quot;writers&quot;.&quot;id&quot;, &quot;writers&quot;.&quot;description&quot;, &quot;writers&quot;.&quot;policy&quot;, &quot;writers&quot;.&quot;policy_second&quot; FROM &quot;writers&quot; WHERE &quot;writers&quot;.&quot;policy&quot;; args=(); alias=default&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Writer.objects.bulk_update(writers_to_update, ['policy_second'], batch_size=2) 시 호출&lt;/p&gt;
&lt;pre id=&quot;code_1677483560064&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;(0.000) BEGIN; args=None; alias=default
(0.000) UPDATE &quot;writers&quot; SET &quot;policy_second&quot; = CASE WHEN (&quot;writers&quot;.&quot;id&quot; = 2) THEN 1 WHEN (&quot;writers&quot;.&quot;id&quot; = 4) THEN 1 ELSE NULL END WHERE &quot;writers&quot;.&quot;id&quot; IN (2, 4); args=(2, True, 4, True, 2, 4); alias=default
(0.000) UPDATE &quot;writers&quot; SET &quot;policy_second&quot; = CASE WHEN (&quot;writers&quot;.&quot;id&quot; = 6) THEN 1 WHEN (&quot;writers&quot;.&quot;id&quot; = 8) THEN 1 ELSE NULL END WHERE &quot;writers&quot;.&quot;id&quot; IN (6, 8); args=(6, True, 8, True, 6, 8); alias=default
(0.000) UPDATE &quot;writers&quot; SET &quot;policy_second&quot; = CASE WHEN (&quot;writers&quot;.&quot;id&quot; = 10) THEN 1 ELSE NULL END WHERE &quot;writers&quot;.&quot;id&quot; IN (10); args=(10, True, 10); alias=default&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>웹 프로그래밍/Django</category>
      <author>Sueeeeeee</author>
      <guid isPermaLink="true">https://sue-is-programming.tistory.com/302</guid>
      <comments>https://sue-is-programming.tistory.com/302#entry302comment</comments>
      <pubDate>Mon, 27 Feb 2023 15:43:50 +0900</pubDate>
    </item>
    <item>
      <title>모델 필드 추가 시 default 값 설정</title>
      <link>https://sue-is-programming.tistory.com/297</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1d1c1d;&quot;&gt;모델에 새로운 필드를 추가할 때 default 값을 지정한 후 마이그레이션하면, &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1d1c1d;&quot;&gt;기존에 있던 데이터의 새 필드에도 알아서 default 값을 채워준다.&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;b&gt;예)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 기존 모델&lt;/p&gt;
&lt;pre class=&quot;python&quot; data-stringify-type=&quot;pre&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;class User(models.Model):
   accept_notification = models.BooleanField()

User.objects.all()
# &amp;lt;User: User object (1)&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;div&gt;2. 필드 추가&lt;/div&gt;
&lt;pre class=&quot;python&quot; data-stringify-type=&quot;pre&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;class User(models.Model):
   accept_notification = models.BooleanField()
   accept_email_notification = models.BooleanField(default=False, null=True)&lt;/code&gt;&lt;/pre&gt;
&lt;div&gt;3. 마이그레이션&lt;/div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1676712337986&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;python manage.py makemigrations
python manage.py migrate​&lt;/code&gt;&lt;/pre&gt;
&lt;br /&gt;4. 기존 데이터의 새 필드 값 확인&lt;/div&gt;
&lt;pre class=&quot;python&quot; data-stringify-type=&quot;pre&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;User.objects.get(id=1).is_accept_email_notification 
# False&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;유의할 점&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;장고가 DB에 마이그레이션 할 때 DB 테이블에 락이 걸린다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터 개수가 10만개 이상인 큰 테이블을 위의 방식으로 작업한다면( = migration으로 자동으로 default 값 채워주기),&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;락이 걸리는 시간이 길어지므로 다운타임이 길어지는 문제가 발생한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;큰 테이블에 디폴트 값이 있어야 하는 필드를 추가할 때는 아래의 방식을 사용하는 것이 더 낫다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 필드 추가 : default 없이 null=True 옵션만 적용&lt;/p&gt;
&lt;pre id=&quot;code_1676712822255&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class User(models.Model):
   accept_notification = models.BooleanField()
   accept_email_notification = models.BooleanField(null=true)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 마이그레이션&lt;/p&gt;
&lt;pre id=&quot;code_1676712920627&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;python manage.py makemigrations
python manage.py migrate​&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 쉘이나 주피터 노트북으로 디폴트 값 삽입&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존에 있던 User 오브젝트의 accept_email_notification 필드에 디폴트 값 False를 쉘을 이용하여 수동으로 채워준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 추가된 필드에 디폴트 값 추가&lt;/p&gt;
&lt;pre id=&quot;code_1676713002346&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class User(models.Model):
   accept_notification = models.BooleanField()
   accept_email_notification = models.BooleanField(null=true, default=False)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. 마이그레이션&lt;/p&gt;
&lt;pre id=&quot;code_1676713010317&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;python manage.py makemigrations
python manage.py migrate​&lt;/code&gt;&lt;/pre&gt;</description>
      <category>웹 프로그래밍/Django</category>
      <author>Sueeeeeee</author>
      <guid isPermaLink="true">https://sue-is-programming.tistory.com/297</guid>
      <comments>https://sue-is-programming.tistory.com/297#entry297comment</comments>
      <pubDate>Sat, 18 Feb 2023 18:36:57 +0900</pubDate>
    </item>
    <item>
      <title>merge conflict 터미널에서 한 번에 해결하기</title>
      <link>https://sue-is-programming.tistory.com/296</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #1d1c1d;&quot;&gt;accept incoming change&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #1d1c1d;&quot;&gt;경로의 모든 conflicts에 대해 accept incoming change 적용&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1676712226138&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;git checkout --theirs &amp;lt;경로&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;span style=&quot;color: #1d1c1d;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #1d1c1d;&quot;&gt;&lt;b&gt;accept current change&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #1d1c1d;&quot;&gt;경로의 모든 conflicts에 대해 accept current change 적용&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1676712268585&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;git checkout --ours &amp;lt;경로&amp;gt;&lt;/code&gt;&lt;/pre&gt;</description>
      <category>웹 프로그래밍/Git</category>
      <author>Sueeeeeee</author>
      <guid isPermaLink="true">https://sue-is-programming.tistory.com/296</guid>
      <comments>https://sue-is-programming.tistory.com/296#entry296comment</comments>
      <pubDate>Sat, 18 Feb 2023 18:24:35 +0900</pubDate>
    </item>
  </channel>
</rss>