<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>개발 블로그</title>
    <link>https://limjisang1115.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Wed, 8 Apr 2026 23:43:18 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>tero1115</managingEditor>
    <item>
      <title>[React] CSS Modules</title>
      <link>https://limjisang1115.tistory.com/214</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;CSS Modules는 &lt;b&gt;CSS 클래스 이름을 컴포넌트 단위로 고유하게 만들어주는 방식&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;다음과 같은 CSS가 있다고 가정&lt;/p&gt;
&lt;pre id=&quot;code_1773308164764&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;.btn {
  color: white;
  background: tomato;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-end=&quot;424&quot; data-start=&quot;384&quot; data-ke-size=&quot;size16&quot;&gt;빌드 후 실제 브라우저에서 사용되는 클래스 이름은 이런 형태로 바뀜&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;div&gt;&lt;span&gt;Button_btn__3X7a9&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;사용방법&lt;/h4&gt;
&lt;p data-end=&quot;531&quot; data-start=&quot;515&quot; data-section-id=&quot;i0j892&quot; data-ke-size=&quot;size18&quot;&gt;1. CSS 파일 생성&lt;/p&gt;
&lt;p data-end=&quot;575&quot; data-start=&quot;533&quot; data-ke-size=&quot;size16&quot;&gt;CSS Module은 파일 이름에 .module.css를 붙여야함&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;div&gt;&lt;span&gt;Button.module.css&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1773308292232&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;.btn {
    color: white;
    background: tomato;
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;688&quot; data-start=&quot;668&quot; data-section-id=&quot;msfpj&quot; data-ke-size=&quot;size18&quot;&gt;2. 컴포넌트에서 import&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;pre id=&quot;code_1773308327251&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import styles from &quot;./Button.module.css&quot;;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;789&quot; data-start=&quot;751&quot; data-ke-size=&quot;size16&quot;&gt;여기서 styles는 CSS 클래스 이름을 담고 있는 객체&lt;/p&gt;
&lt;p data-end=&quot;789&quot; data-start=&quot;751&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;889&quot; data-start=&quot;869&quot; data-section-id=&quot;f2ibe2&quot; data-ke-size=&quot;size18&quot;&gt;3. className에 적용&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;pre id=&quot;code_1773308390068&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;button className={styles.btn}&amp;gt;
	버튼
&amp;lt;/button&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;976&quot; data-start=&quot;950&quot; data-ke-size=&quot;size16&quot;&gt;실제로 브라우저에서는 다음과 같이 렌더링됨&lt;/p&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;pre id=&quot;code_1773308479698&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;button class=&quot;Button_btn__3X7a9&quot;&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-end=&quot;1044&quot; data-start=&quot;1031&quot; data-section-id=&quot;sd0oqm&quot; data-ke-size=&quot;size26&quot;&gt;일반 CSS와 차이&lt;/h2&gt;
&lt;h3 data-end=&quot;1056&quot; data-start=&quot;1046&quot; data-section-id=&quot;evm10h&quot; data-ke-size=&quot;size23&quot;&gt;일반 CSS&lt;/h3&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;pre id=&quot;code_1773308559165&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import &quot;./Button.css&quot;;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1773308565067&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;button className=&quot;btn&quot;&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;1139&quot; data-start=&quot;1137&quot; data-ke-size=&quot;size16&quot;&gt;특징&lt;/p&gt;
&lt;p data-end=&quot;1139&quot; data-start=&quot;1137&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- CSS가 &lt;b&gt;전역(Global)&lt;/b&gt; 으로 적용됨&lt;/p&gt;
&lt;p data-end=&quot;1139&quot; data-start=&quot;1137&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- 같은 클래스 이름이 있으면 충돌 가능&lt;/p&gt;
&lt;h3 data-end=&quot;1214&quot; data-start=&quot;1199&quot; data-section-id=&quot;1ge1bak&quot; data-ke-size=&quot;size23&quot;&gt;CSS Modules&lt;/h3&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;pre id=&quot;code_1773308605046&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import styles from &quot;./Button.module.css&quot;;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;pre id=&quot;code_1773308608606&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;button className={styles.btn}&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;1323&quot; data-start=&quot;1321&quot; data-ke-size=&quot;size16&quot;&gt;특징&lt;/p&gt;
&lt;p data-end=&quot;1323&quot; data-start=&quot;1321&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- 클래스 이름을&amp;nbsp;&lt;b&gt;자동으로 고유하게 생성&lt;/b&gt;&lt;/p&gt;
&lt;p data-end=&quot;1323&quot; data-start=&quot;1321&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- 컴포넌트 단위 스타일 관리 가능&lt;/p&gt;
&lt;p data-end=&quot;1323&quot; data-start=&quot;1321&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- CSS 충돌 방지&lt;/p&gt;</description>
      <category>프론트엔드/React</category>
      <author>tero1115</author>
      <guid isPermaLink="true">https://limjisang1115.tistory.com/214</guid>
      <comments>https://limjisang1115.tistory.com/214#entry214comment</comments>
      <pubDate>Thu, 12 Mar 2026 22:13:18 +0900</pubDate>
    </item>
    <item>
      <title>[JavaScript] classList</title>
      <link>https://limjisang1115.tistory.com/213</link>
      <description>&lt;p data-end=&quot;163&quot; data-start=&quot;95&quot; data-ke-size=&quot;size16&quot;&gt;HTML 요소에 CSS 클래스를 추가, 제거, 확인할 때 자주 쓰는 것이 &lt;b&gt;classList&lt;/b&gt;&lt;/p&gt;
&lt;p data-end=&quot;163&quot; data-start=&quot;95&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;163&quot; data-start=&quot;95&quot; data-ke-size=&quot;size16&quot;&gt;자주 사용하는 메소드&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;410&quot; data-start=&quot;197&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;268&quot; data-start=&quot;197&quot;&gt;&lt;b&gt;classList.contains('클래스명')&lt;/b&gt; : 특정 클래스가 있는지 확인 (true / false 반환)&lt;/li&gt;
&lt;li data-end=&quot;309&quot; data-start=&quot;269&quot;&gt;&lt;b&gt;classList.add('클래스명')&lt;/b&gt; : 클래스 추가&lt;/li&gt;
&lt;li data-end=&quot;353&quot; data-start=&quot;310&quot;&gt;&lt;b&gt;classList.remove('클래스명')&lt;/b&gt; : 클래스 제거&lt;/li&gt;
&lt;li data-end=&quot;410&quot; data-start=&quot;354&quot;&gt;&lt;b&gt;classList.toggle('클래스명')&lt;/b&gt; : 클래스가 있으면 제거, 없으면 추가&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;toggle로 간단하게&lt;/p&gt;
&lt;pre id=&quot;code_1757392497339&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;div class=&quot;box&quot; id=&quot;box&quot;&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;button id=&quot;btn&quot;&amp;gt;토글&amp;lt;/button&amp;gt;

&amp;lt;script&amp;gt;
  const box = document.getElementById('box');
  const btn = document.getElementById('btn');

  btn.addEventListener('click', () =&amp;gt; {
    box.classList.toggle('active'); // 한 줄로 끝!
  });
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;contains + add/remove로 toggle 구현&lt;/p&gt;
&lt;pre id=&quot;code_1757392646401&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;div class=&quot;box&quot; id=&quot;box&quot;&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;button id=&quot;btn&quot;&amp;gt;토글&amp;lt;/button&amp;gt;

&amp;lt;script&amp;gt;
  const box = document.getElementById('box');
  const btn = document.getElementById('btn');

  btn.addEventListener('click', () =&amp;gt; {
    if (box.classList.contains('active')) {
      box.classList.remove('active'); // 있으면 제거
    } else {
      box.classList.add('active');    // 없으면 추가
    }
  });
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;toggle을 사용하면 편하지만 contains + add/remove로도 구현이 가능하다.&lt;/p&gt;</description>
      <category>프로그래밍 언어와 기술/JavaScript</category>
      <author>tero1115</author>
      <guid isPermaLink="true">https://limjisang1115.tistory.com/213</guid>
      <comments>https://limjisang1115.tistory.com/213#entry213comment</comments>
      <pubDate>Tue, 9 Sep 2025 13:40:03 +0900</pubDate>
    </item>
    <item>
      <title>쿠키(Cookie), 세션(Session), 그리고 로컬 스토리지(Local Storage)</title>
      <link>https://limjisang1115.tistory.com/98</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;웹 개발을 하다 보면 &lt;b&gt;쿠키(Cookie)&lt;/b&gt;, &lt;b&gt;세션(Session)&lt;/b&gt;, &lt;b&gt;로컬 스토리지(Local Storage)&lt;/b&gt;를 사용하는 경우가 많습니다. 이 세 가지는 모두 클라이언트와 서버 간의 상태를 유지하거나 데이터를 저장하는 방식이지만, 각기 다른 특성과 사용 목적이 있습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 쿠키(Cookie)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;쿠키&lt;/b&gt;는 &lt;b&gt;웹사이트가 사용자의 브라우저에 저장하는 작은 데이터 조각&lt;/b&gt;입니다. 서버가 사용자 브라우저에 쿠키를 생성해 저장하면, 이후 요청마다 브라우저는 해당 쿠키를 함께 전송하여 사용자를 식별할 수 있습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;주요 특징&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;주로 &lt;b&gt;로그인 정보&lt;/b&gt;나 사용자 선호 설정 등을 저장합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;만료 시간&lt;/b&gt;을 설정할 수 있으며, 지정된 시간이 지나면 자동으로 삭제됩니다.&lt;/li&gt;
&lt;li&gt;용량이 작으며, 브라우저당 약 4KB로 제한됩니다.&lt;/li&gt;
&lt;li&gt;HTTP 요청마다 쿠키가 자동으로 전송되기 때문에 보안과 성능에 주의가 필요합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;사용 예시&lt;/b&gt;: 로그인 상태 유지, 사용자 맞춤 설정 유지, 장바구니 정보 저장 등.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. 세션(Session)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;세션&lt;/b&gt;은 &lt;b&gt;서버에 사용자 정보를 저장&lt;/b&gt;하여 사용자가 웹사이트를 방문하는 동안 특정 상태를 유지하도록 하는 방식입니다. 세션은 &lt;b&gt;클라이언트가 서버에 접속한 동안만 유지&lt;/b&gt;되며, 브라우저를 닫거나 일정 시간이 지나면 자동으로 만료됩니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;주요 특징&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;서버에서 관리&lt;/b&gt;되는 데이터이기 때문에 보안성이 높습니다.&lt;/li&gt;
&lt;li&gt;쿠키와 달리 클라이언트가 직접 접근할 수 없어 &lt;b&gt;민감한 정보 관리에 유리&lt;/b&gt;합니다.&lt;/li&gt;
&lt;li&gt;세션 ID만 클라이언트 측에 저장하고, 실제 데이터는 서버에 저장됩니다.&lt;/li&gt;
&lt;li&gt;일정 시간 동안 사용자 활동이 없으면 세션이 만료될 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;사용 예시&lt;/b&gt;: 로그인 인증 상태, 장바구니 관리, 사용자 정보 유지 등.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. 로컬 스토리지(Local Storage)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;로컬 스토리지&lt;/b&gt;는 &lt;b&gt;브라우저에 영구적으로 데이터를 저장&lt;/b&gt;할 수 있는 공간입니다. 한 번 저장된 데이터는 사용자가 브라우저 데이터를 지우기 전까지 지속됩니다. 로컬 스토리지는 클라이언트 측에서만 접근할 수 있어 &lt;b&gt;서버와의 통신 없이 데이터를 저장&lt;/b&gt;할 때 유용합니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;주요 특징&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;용량이 크다&lt;/b&gt;: 브라우저마다 다르지만, 일반적으로 약 5MB 이상의 데이터를 저장할 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;유효 기간이 없다&lt;/b&gt;: 사용자가 직접 삭제하기 전까지 데이터가 유지됩니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;동기적 처리&lt;/b&gt;: 로컬 스토리지는 동기적으로 작동하므로 대량의 데이터를 저장하거나 호출할 때 성능에 주의해야 합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;보안에 주의&lt;/b&gt;: 브라우저에서 직접 접근 가능하므로, &lt;b&gt;민감한 정보는 암호화 없이 저장하지 않는 것이 중요&lt;/b&gt;합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;사용 예시&lt;/b&gt;: 사용자 설정 저장(테마, 언어 등), 캐싱 데이터, 애플리케이션 상태 저장 등.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;쿠키, 세션, 로컬 스토리지 비교&lt;/h3&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;특징&lt;/th&gt;
&lt;th&gt;쿠키(Cookie)&lt;/th&gt;
&lt;th&gt;세션(Session)&lt;/th&gt;
&lt;th&gt;로컬 스토리지(Local Storage)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;저장 위치&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;클라이언트(브라우저)&lt;/td&gt;
&lt;td&gt;서버&lt;/td&gt;
&lt;td&gt;클라이언트(브라우저)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;데이터 유효 기간&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;설정 가능&lt;/td&gt;
&lt;td&gt;브라우저 종료 또는 일정 시간 후 만료&lt;/td&gt;
&lt;td&gt;사용자가 삭제할 때까지&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;주요 목적&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;로그인 상태, 사용자 식별&lt;/td&gt;
&lt;td&gt;로그인 인증 상태, 민감 데이터 관리&lt;/td&gt;
&lt;td&gt;설정 저장, 캐싱 데이터&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;용량&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;약 4KB&lt;/td&gt;
&lt;td&gt;제한 없음(서버에 저장)&lt;/td&gt;
&lt;td&gt;약 5MB 이상&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;보안성&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;낮음&lt;/td&gt;
&lt;td&gt;상대적으로 높음&lt;/td&gt;
&lt;td&gt;낮음&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;서버 요청 시 전송&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;자동으로 포함&lt;/td&gt;
&lt;td&gt;서버가 직접 참조&lt;/td&gt;
&lt;td&gt;전송되지 않음&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;언제 사용해야 할까?&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;쿠키&lt;/b&gt;: 로그인 상태나 사용자 식별이 필요할 때 주로 사용합니다. 다만, 보안에 주의해야 합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;세션&lt;/b&gt;: 민감한 데이터가 포함된 인증 정보나 사용자 상태를 서버에서 관리하고자 할 때 유리합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;로컬 스토리지&lt;/b&gt;: 사용자 설정을 유지하거나, 서버와 상관없이 브라우저에 데이터를 저장할 때 좋습니다. 하지만 보안에 주의해야 합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;마무리&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쿠키, 세션, 로컬 스토리지는 각기 다른 특성과 목적을 가지고 있습니다. 웹 애플리케이션에서 데이터를 저장하거나 인증을 관리할 때 상황에 맞게 잘 선택하여 사용하는 것이 중요합니다. 예를 들어, &lt;b&gt;로그인 인증&lt;/b&gt;에는 보안이 중요한 세션을, &lt;b&gt;사용자 맞춤 설정&lt;/b&gt;에는 로컬 스토리지를, 그리고 &lt;b&gt;상태 식별&lt;/b&gt;에는 쿠키를 사용할 수 있습니다.&lt;/p&gt;</description>
      <category>도구 및 기타/개발상식</category>
      <author>tero1115</author>
      <guid isPermaLink="true">https://limjisang1115.tistory.com/98</guid>
      <comments>https://limjisang1115.tistory.com/98#entry98comment</comments>
      <pubDate>Wed, 13 Nov 2024 11:35:22 +0900</pubDate>
    </item>
    <item>
      <title>DNS (Domain Name System)</title>
      <link>https://limjisang1115.tistory.com/208</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;DNS(Domain Name System)란?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인터넷을 사용하다 보면 누구나 www.example.com 같은 도메인 이름을 입력하게 됩니다. 그런데 컴퓨터는 이런 도메인 이름을 이해하지 못하고, 실제로는 IP 주소를 통해 통신합니다. 여기서 &lt;b&gt;DNS(Domain Name System)&lt;/b&gt;는 도메인 이름을 IP 주소로 변환해주는 시스템입니다. 쉽게 말해, 사람이 이해하기 쉬운 도메인 이름을 입력하면, DNS는 해당 서버의 IP 주소로 변환해 줍니다. DNS는 우리가 인터넷을 쉽게 사용할 수 있게 도와주는 핵심적인 역할을 합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;DNS의 주요 역할&lt;/h2&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;도메인 이름을 IP 주소로 변환&lt;/b&gt;: 사용자가 브라우저에 www.example.com을 입력하면, DNS는 이를 해당 서버의 IP 주소(예: 192.168.1.1)로 변환합니다. 이 덕분에 사용자는 복잡한 숫자 대신 도메인 이름만 기억하면 됩니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;네트워크 경로 최적화&lt;/b&gt;: DNS는 사용자가 위치한 지역에 따라 가장 가까운 서버의 IP 주소로 연결해 줍니다. 이를 통해 사용자는 더 빠르고 효율적인 연결을 경험할 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;부하 분산&lt;/b&gt;: 대형 웹사이트의 경우 여러 서버를 운영하며, DNS를 통해 부하를 분산시켜 서버 성능을 최적화할 수 있습니다. 이를 통해 사이트의 안정성과 속도를 유지할 수 있습니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;DNS의 동작 방식&lt;/h2&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;사용자가 도메인 입력&lt;/b&gt;: 사용자가 브라우저에 www.example.com을 입력하면, 브라우저는 먼저 로컬 DNS 캐시에서 IP 주소를 찾습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;로컬 DNS 서버 문의&lt;/b&gt;: 캐시에 정보가 없으면, 로컬 DNS 서버에 도메인 이름의 IP 주소를 요청하게 됩니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;DNS 계층 탐색&lt;/b&gt;: 로컬 DNS 서버가 해당 주소를 모르면, 최상위 도메인 서버(TLD, 예: .com)로 요청을 전달하며, 점차적으로 정확한 IP 주소를 찾습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;결과 반환 및 접속&lt;/b&gt;: 최종적으로 IP 주소가 반환되면, 브라우저는 이 IP 주소로 해당 서버에 연결하여 웹사이트를 표시합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;DNS의 구성 요소&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;도메인 네임(Domain Name)&lt;/b&gt;: 사람이 읽기 쉬운 주소입니다. 예를 들어, example.com이 도메인 네임입니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;IP 주소&lt;/b&gt;: 실제 서버 위치를 나타내는 주소입니다. 예를 들어, 192.168.1.1과 같은 숫자가 IP 주소입니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;네임서버(Name Server)&lt;/b&gt;: 도메인 이름과 IP 주소를 매칭하는 서버로, DNS 질의에 응답합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;DNS 레코드&lt;/b&gt;: 도메인과 연결된 정보입니다. A 레코드(IPv4), AAAA 레코드(IPv6), CNAME(별칭), MX(메일 서버) 등 다양한 유형이 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;DNS 캐싱&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DNS는 검색 속도를 높이기 위해 &lt;b&gt;캐싱&lt;/b&gt;을 사용합니다. 한 번 조회한 도메인-IP 정보는 일정 시간 동안 로컬에 저장됩니다. 이렇게 하면 같은 요청이 있을 때 빠르게 응답할 수 있습니다. 그러나 이 캐시 때문에 도메인 정보를 변경한 후, 새로운 정보가 모든 네트워크에 퍼지기까지 시간이 걸릴 수 있는데, 이를 &lt;b&gt;DNS 전파 시간&lt;/b&gt;이라 부릅니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;DNS 사용 시 주의할 점&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;DNS 전파 시간&lt;/b&gt;: 도메인 정보가 변경되면 모든 네트워크에 새로운 정보가 퍼지기까지 시간이 걸립니다. 이 때문에 도메인이나 서버 IP를 변경할 때 잠시 동안 구버전 정보로 접속될 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;DNS 보안&lt;/b&gt;: DNS를 변조하는 공격(DNS 스푸핑)으로 인해 사용자가 악의적인 사이트로 연결될 위험이 있습니다. 이를 방지하기 위해 &lt;b&gt;DNSSEC&lt;/b&gt; 같은 보안 기술을 사용할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>도구 및 기타/개발상식</category>
      <author>tero1115</author>
      <guid isPermaLink="true">https://limjisang1115.tistory.com/208</guid>
      <comments>https://limjisang1115.tistory.com/208#entry208comment</comments>
      <pubDate>Tue, 12 Nov 2024 16:55:41 +0900</pubDate>
    </item>
    <item>
      <title>CSR(Client-Side Rendering)과 SSR(Server-Side Rendering)</title>
      <link>https://limjisang1115.tistory.com/206</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;CSR(Client-Side Rendering)이란?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CSR은 클라이언트(사용자의 브라우저)에서 웹페이지를 렌더링하는 방식입니다. 웹사이트에 처음 접속하면 빈 HTML 파일과 JavaScript 파일을 다운로드한 후, JavaScript가 브라우저에서 실행되면서 콘텐츠를 화면에 그리게 됩니다. 대표적으로 &lt;b&gt;React&lt;/b&gt;나 &lt;b&gt;Vue&lt;/b&gt;와 같은 프론트엔드 프레임워크들이 CSR 방식을 사용합니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;작동 방식&lt;/b&gt;: 서버에서 기본 HTML 파일과 필요한 JavaScript를 보내고, 클라이언트에서 JavaScript가 실행되면서 데이터를 받아 페이지를 구성합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;예시&lt;/b&gt;: SPA(Single Page Application) 구조의 웹앱이 대표적인 CSR 방식입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;CSR의 장점&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;빠른 상호작용&lt;/b&gt;: 페이지를 처음 로드한 이후에는 브라우저 내에서 페이지 간 전환이 일어나기 때문에 사용자 경험이 빠르고 매끄럽습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;서버 부하 감소&lt;/b&gt;: 대부분의 렌더링 작업이 클라이언트에서 이루어지기 때문에 서버에 대한 부하가 줄어듭니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;CSR의 단점&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;SEO 최적화 어려움&lt;/b&gt;: 초기에는 빈 HTML만 제공되기 때문에 검색 엔진이 페이지를 제대로 크롤링하기 어려워 SEO에 불리합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;초기 로딩 시간 증가&lt;/b&gt;: JavaScript 파일을 다운로드하고 데이터를 가져와 렌더링해야 하므로 초기 로딩 속도가 느릴 수 있습니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;SSR(Server-Side Rendering)이란?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SSR은 서버에서 웹 페이지를 렌더링한 후, 완성된 HTML을 클라이언트에게 보내주는 방식입니다. 사용자가 웹사이트에 접속하면 서버에서 콘텐츠를 포함한 HTML을 생성해 브라우저로 전달하므로, 사용자는 즉시 콘텐츠를 확인할 수 있습니다. 대표적으로 &lt;b&gt;Next.js&lt;/b&gt;가 SSR을 지원하는 프레임워크입니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;작동 방식&lt;/b&gt;: 서버에서 HTML을 생성해 사용자에게 전달하고, 브라우저는 이 HTML을 받아 즉시 렌더링합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;예시&lt;/b&gt;: 전통적인 다중 페이지 애플리케이션(MPA)이나, SSR을 지원하는 Next.js 같은 React 프레임워크가 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;SSR의 장점&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;SEO 친화적&lt;/b&gt;: 서버에서 생성된 HTML에 모든 콘텐츠가 포함되어 있어 검색 엔진이 페이지를 쉽게 크롤링할 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;빠른 초기 렌더링&lt;/b&gt;: 서버에서 HTML을 완성하여 보내므로 사용자는 더 빠르게 콘텐츠를 볼 수 있습니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;SSR의 단점&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;서버 부하 증가&lt;/b&gt;: 모든 요청마다 서버가 HTML을 생성해야 하므로 트래픽이 많을 경우 서버에 큰 부하가 걸릴 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;상호작용 지연&lt;/b&gt;: JavaScript가 로드되기 전까지는 단순한 HTML만 보여주기 때문에 초기 상호작용이 지연될 수 있습니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;CSR과 SSR의 비교&lt;/h2&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;특징&lt;/th&gt;
&lt;th&gt;CSR(Client-Side Rendering)&lt;/th&gt;
&lt;th&gt;SSR(Server-Side Rendering)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;렌더링 위치&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;클라이언트(브라우저)&lt;/td&gt;
&lt;td&gt;서버&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;초기 로딩 속도&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;상대적으로 느림&lt;/td&gt;
&lt;td&gt;빠름&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;SEO 적합성&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;낮음&lt;/td&gt;
&lt;td&gt;높음&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;페이지 전환 속도&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;빠름&lt;/td&gt;
&lt;td&gt;느릴 수 있음&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;사용 예&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;SPA(React, Vue)&lt;/td&gt;
&lt;td&gt;MPA(다중 페이지), Next.js&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;CSR과 SSR의 혼합: 하이브리드 렌더링&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최근에는 &lt;b&gt;SSR과 CSR을 혼합한 하이브리드 렌더링&lt;/b&gt; 방식도 많이 사용됩니다. 예를 들어, &lt;b&gt;Next.js&lt;/b&gt;는 초기 페이지 로딩 시에는 서버에서 렌더링하고, 이후에는 클라이언트에서 필요한 부분을 동적으로 렌더링하는 방식으로 초기 속도, SEO, 상호작용성을 모두 최적화할 수 있습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;언제 CSR, SSR을 선택할까?&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;SEO가 중요한 경우&lt;/b&gt;: 블로그나 전자상거래 사이트처럼 검색 엔진 노출이 중요한 경우 SSR이 유리합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;복잡한 사용자 인터페이스&lt;/b&gt;: 대시보드나 관리 도구처럼 빠르고 상호작용이 많은 페이지는 CSR이 더 적합합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;혼합이 필요한 경우&lt;/b&gt;: SEO와 사용자 상호작용 모두 중요한 경우에는 하이브리드 렌더링 방식을 고려할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CSR과 SSR은 각각 장단점이 있으므로, 프로젝트의 특성과 필요에 맞게 선택하는 것이 중요합니다. 웹사이트의 성능과 SEO 최적화, 사용자 경험을 향상시키기 위해 이 두 가지 렌더링 방식의 특성을 잘 이해하고 사용하는 것이 좋습니다.&lt;/p&gt;</description>
      <category>도구 및 기타/개발상식</category>
      <author>tero1115</author>
      <guid isPermaLink="true">https://limjisang1115.tistory.com/206</guid>
      <comments>https://limjisang1115.tistory.com/206#entry206comment</comments>
      <pubDate>Mon, 11 Nov 2024 18:52:20 +0900</pubDate>
    </item>
    <item>
      <title>지연 로딩 ( Lazy Loading )</title>
      <link>https://limjisang1115.tistory.com/205</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Lazy Loading이란?&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Lazy Loading은 웹 페이지에서 화면에 나타나기 전까지 이미지나 비디오 같은 리소스 로딩을 지연시키는 기술입니다. 이 기법은 처음부터 페이지의 모든 리소스를 불러오는 대신 사용자가 스크롤할 때 필요한 리소스만 불러오기 때문에 페이지 로딩 속도가 빨라지고, 사용자 경험이 개선됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Lazy Loading의 장점&lt;/span&gt;&lt;/h2&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;빠른 페이지 로딩&lt;/b&gt;: 초기 로딩 시 필요한 리소스만 불러오기 때문에 페이지 로딩 속도가 빨라집니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;데이터 절감&lt;/b&gt;: 사용자가 보지 않는 리소스는 로딩되지 않기 때문에 불필요한 데이터 사용을 줄일 수 있습니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;사용자 경험 개선&lt;/b&gt;: 빠른 페이지 로딩은 이탈률을 줄이고 사용자 경험을 향상시킵니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;구현 방법&lt;/span&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;1. HTML 속성 활용&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;HTML5의 loading=&quot;lazy&quot; 속성으로 간단하게 이미지나 iframe에 Lazy Loading을 적용할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1731312047365&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;img src=&quot;example.jpg&quot; alt=&quot;Example&quot; loading=&quot;lazy&quot;&amp;gt;
&amp;lt;iframe src=&quot;https://www.example.com&quot; loading=&quot;lazy&quot;&amp;gt;&amp;lt;/iframe&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;2. JavaScript로 구현&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Intersection Observer API를 사용하여 지연 로딩을 더욱 세밀하게 제어할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1731311903913&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const images = document.querySelectorAll(&quot;img.lazy&quot;);

const lazyLoad = (entries, observer) =&amp;gt; {
  entries.forEach(entry =&amp;gt; {
    if (entry.isIntersecting) {
      const img = entry.target;
      img.src = img.dataset.src; // data-src에 실제 이미지 경로 저장
      img.classList.remove(&quot;lazy&quot;);
      observer.unobserve(img);
    }
  });
};

const observer = new IntersectionObserver(lazyLoad);

images.forEach(img =&amp;gt; {
  observer.observe(img);
});&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;SEO와 Lazy Loading&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Lazy Loading은 페이지 로딩 속도를 개선하기 때문에 SEO 성능을 높이는 데 도움이 됩니다. 그러나 모든 콘텐츠를 지연 로딩할 경우 검색엔진 최적화(SEO)에 부정적인 영향을 미칠 수 있습니다. 검색엔진 크롤러는 화면을 스크롤하지 않기 때문에 중요한 콘텐츠가 지연 로딩되면 탐색되지 않을 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 SEO 관점에서 중요한 사항은 다음과 같습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;핵심 콘텐츠는 Lazy Loading 피하기&lt;/b&gt;: 페이지의 중요한 텍스트 콘텐츠나 주요 키워드가 포함된 요소는 일반 로딩 방식을 사용해야 합니다. 예를 들어, 헤더나 메인 콘텐츠는 반드시 즉시 로딩하여 검색엔진이 빠르게 탐색할 수 있도록 해야 합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;이미지 Alt 태그 사용&lt;/b&gt;: 지연 로딩한 이미지에도 Alt 태그를 포함하여 검색엔진이 이미지의 의미를 이해할 수 있게 돕습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Schema 및 Meta 태그 활용&lt;/b&gt;: 검색엔진이 페이지의 내용을 잘 이해할 수 있도록 Schema 태그나 Meta 태그를 포함하여 페이지를 최적화합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;결론&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Lazy Loading은 웹 페이지의 성능을 높이기 위해 꼭 필요한 기술입니다. 다만 SEO 최적화를 위해 주요 콘텐츠는 지연 로딩하지 않는 것이 중요합니다. 이로써 페이지 속도와 SEO 성능을 모두 높일 수 있습니다.&lt;/p&gt;</description>
      <category>도구 및 기타/개발상식</category>
      <author>tero1115</author>
      <guid isPermaLink="true">https://limjisang1115.tistory.com/205</guid>
      <comments>https://limjisang1115.tistory.com/205#entry205comment</comments>
      <pubDate>Mon, 11 Nov 2024 17:06:42 +0900</pubDate>
    </item>
    <item>
      <title>트랜잭션 (Transaction)</title>
      <link>https://limjisang1115.tistory.com/126</link>
      <description>&lt;h3 data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;트랜잭션이란?&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;트랜잭션은 데이터베이스에서 이루어지는 일련의 작업들을 하나의 단위로 묶어주는 것을 의미합니다. &lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;여기서 중요한 개념은 트랜잭션이 &quot;&lt;/span&gt;&lt;b&gt;모두 성공하거나, 모두 실패해야 한다&lt;/b&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&quot;는 것입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;즉, 트랜잭션의 모든 단계가 성공했을 때만 최종적으로 커밋(commit)되어 데이터베이스에 반영되고, 중간에 문제가 발생하면 트랜잭션 시작 전으로 되돌아가(롤백, rollback) 데이터의 일관성을 유지합니다.&lt;/span&gt;&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;size16&quot;&gt;&lt;span&gt;친구에게 500원을 송금하는 과정을 예로 들어 설명해 보겠습니다.&lt;/span&gt;&lt;span&gt;&lt;/span&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;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;내 계좌에서 500원 감소&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;친구 계좌에서 500원 추가&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;트랜잭션 완료 후 커밋&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이 과정에서 트랜잭션은 내 계좌에서 500원을 감소시키고 친구의 계좌에 500원을 더하는 모든 작업이 완벽히 이루어졌을 때만 완료됩니다.&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;중간에 문제가 생기면?&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;그런데 만약 이 작업 도중에 정전이 발생했다고 가정해 봅시다.&lt;/span&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&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;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;내 계좌에서 500원 감소&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;정전 발생!&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이 상태에서 서버가 갑자기 꺼진다면 어떻게 될까요? 친구의 계좌에는 500원이 추가되지 않았지만, 내 계좌에서는 이미 500원이 빠져나간 상황일 수 있습니다. 이 경우 데이터베이스는 트랜잭션의 특성 덕분에 작업을 &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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;트랜잭션의 ACID 특성&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;트랜잭션은 데이터의 무결성을 보장하기 위해 &lt;/span&gt;&lt;span&gt;&lt;b&gt;ACID&lt;/b&gt;&lt;/span&gt;&lt;span&gt;라는 네 가지 중요한 특성을 만족해야 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;Atomicity(원자성)&lt;/b&gt;&lt;/span&gt;&lt;span&gt;: 트랜잭션 내의 모든 작업이 완전히 실행되거나, 전혀 실행되지 않아야 합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;Consistency(일관성)&lt;/b&gt;&lt;/span&gt;&lt;span&gt;: 트랜잭션이 성공적으로 완료되면 데이터베이스는 일관성 있는 상태로 유지되어야 합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;Isolation(고립성)&lt;/b&gt;&lt;/span&gt;&lt;span&gt;: 동시에 실행되는 트랜잭션들이 서로 영향을 미치지 않도록 보장해야 합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;Durability(지속성)&lt;/b&gt;&lt;/span&gt;&lt;span&gt;: 트랜잭션이 완료된 후에는 시스템 오류가 발생하더라도 그 결과가 데이터베이스에 영구적으로 반영되어야 합니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;결론&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;트랜잭션은 우리가 일상적으로 사용하는 금융 서비스나 온라인 쇼핑 등 다양한 시스템에서 데이터의 일관성과 무결성을 보장하는 중요한 역할을 합니다. 정전과 같은 예기치 않은 상황에서도 데이터를 안전하게 보호하기 위해 트랜잭션의 원리와 ACID 특성을 잘 이해하는 것이 중요합니다.&lt;/span&gt;&lt;/p&gt;</description>
      <category>도구 및 기타/개발상식</category>
      <author>tero1115</author>
      <guid isPermaLink="true">https://limjisang1115.tistory.com/126</guid>
      <comments>https://limjisang1115.tistory.com/126#entry126comment</comments>
      <pubDate>Thu, 7 Nov 2024 18:01:40 +0900</pubDate>
    </item>
    <item>
      <title>[CSS] 그리드 레이아웃 ( Grid Layout )</title>
      <link>https://limjisang1115.tistory.com/204</link>
      <description>&lt;pre id=&quot;code_1730450917584&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;article&amp;gt;
    &amp;lt;header&amp;gt;헤더&amp;lt;/header&amp;gt;
    &amp;lt;nav&amp;gt;메뉴&amp;lt;/nav&amp;gt;
    &amp;lt;main&amp;gt;본문&amp;lt;/main&amp;gt;
    &amp;lt;footer&amp;gt;푸터&amp;lt;/footer&amp;gt;
&amp;lt;/article&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1730450938433&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;article {
  color: #fff;
  height: 300px;
  display: grid;
  grid-template-areas:
    &quot;header header&quot;
    &quot;nav    main&quot;
    &quot;nav    footer&quot;;
  grid-template-columns: 150px 1fr;
  grid-template-rows: 50px 1fr 50px;
}

header {
  background: #24c0a5;
  grid-area: header;
}

nav {
  background: #4011c5;
  grid-area: nav;
}

main {
  background: #b42809;
  grid-area: main;
}

footer {
  background: #24c0a5;
  grid-area: footer;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1403&quot; data-origin-height=&quot;378&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eghOjC/btsKt7mgt2Q/pYeZfiS5KKI3kkRWiKYEz0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eghOjC/btsKt7mgt2Q/pYeZfiS5KKI3kkRWiKYEz0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eghOjC/btsKt7mgt2Q/pYeZfiS5KKI3kkRWiKYEz0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeghOjC%2FbtsKt7mgt2Q%2FpYeZfiS5KKI3kkRWiKYEz0%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;1403&quot; height=&quot;378&quot; data-origin-width=&quot;1403&quot; data-origin-height=&quot;378&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;위 예제에서는 &lt;/span&gt;&lt;span&gt;&lt;b&gt;article&lt;/b&gt;&lt;/span&gt;&lt;span&gt; 요소가 웹페이지 전체 레이아웃의 컨테이너 역할을 수행합니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;display: grid&lt;/span&gt;&lt;span&gt;를 사용하여 해당 요소를 그리드 컨테이너로 지정하고, 내부의 &lt;/span&gt;&lt;span&gt;&lt;b&gt;header&lt;/b&gt;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&lt;b&gt;nav&lt;/b&gt;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&lt;b&gt;main&lt;/b&gt;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&lt;b&gt;footer&lt;/b&gt;&lt;/span&gt;&lt;span&gt; 요소들이 각자의 그리드 영역을 차지하도록 설정합니다.&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h3 data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Grid Template&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;b&gt;grid-template-areas&lt;/b&gt;&lt;/span&gt;&lt;span&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt; 속성은 그&lt;/span&gt;리드 내 각 요소의 배치 영역을 명시적으로 정의하는 기능을 제공합니다.&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1730451188057&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;article {
    display: grid;
    grid-template-areas:
        &quot;header header&quot;
        &quot;nav    main&quot;
        &quot;nav    footer&quot;;
    grid-template-columns: 200px 1fr;
    grid-template-rows: 50px 1fr 50px;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img id=&quot;image-hover-icon&quot; style=&quot;position: absolute; width: 25px; height: 25px; cursor: pointer; left: 13px; top: 1032.69px; display: none; opacity: 0.7;&quot; src=&quot;chrome-extension://pbhpcbdjngblklnibanbkgkogjmbjeoe/src/public/images/128px.png&quot; /&gt;&lt;/p&gt;
&lt;p data-pm-slice=&quot;1 3 []&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;위 코드에서 &lt;/span&gt;&lt;span&gt;grid-template-areas&lt;/span&gt;&lt;span&gt;는 각 요소가 레이아웃에서 차지하는 위치를 명시적으로 정의합니다.&lt;/span&gt;&lt;/p&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;b&gt;header&lt;/b&gt;&lt;/span&gt;&lt;span&gt;가 두 열을 차지합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;두 번째 행에는 &lt;/span&gt;&lt;span&gt;&lt;b&gt;nav&lt;/b&gt;&lt;/span&gt;&lt;span&gt;와 &lt;/span&gt;&lt;span&gt;&lt;b&gt;main&lt;/b&gt;&lt;/span&gt;&lt;span&gt;이 각각 배치됩니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;세 번째 행에는 &lt;/span&gt;&lt;span&gt;&lt;b&gt;nav&lt;/b&gt;&lt;/span&gt;&lt;span&gt;와 &lt;/span&gt;&lt;span&gt;&lt;b&gt;footer&lt;/b&gt;&lt;/span&gt;&lt;span&gt;가 나란히 배치됩니다.&lt;br /&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-pm-slice=&quot;1 3 []&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-pm-slice=&quot;1 3 []&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span&gt;grid-template-columns&lt;/span&gt;&lt;/b&gt;&lt;span&gt;와 &lt;/span&gt;&lt;b&gt;&lt;span&gt;grid-template-rows&lt;/span&gt;&lt;/b&gt;&lt;span&gt;를 사용하여 그리드의 열과 행의 크기를 지정할 수 있습니다.&lt;/span&gt;&lt;/p&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;200px&lt;/span&gt;&lt;span&gt;과 &lt;/span&gt;&lt;span&gt;1fr&lt;/span&gt;&lt;span&gt;로 설정되어 있습니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;행은 첫 번째와 세 번째가 고정 크기 &lt;/span&gt;&lt;span&gt;50px&lt;/span&gt;&lt;span&gt;이고, 중간 행은 &lt;/span&gt;&lt;span&gt;1fr&lt;/span&gt;&lt;span&gt;로 나머지 공간을 차지합니다&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;Grid Area 설정&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;각 하위 요소는 &lt;/span&gt;&lt;span&gt;grid-area&lt;/span&gt;&lt;span&gt; 속성을 통해 그리드의 특정 영역에 배치됩니다. &lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;css&quot; data-ke-language=&quot;css&quot;&gt;&lt;code&gt;header {
    grid-area: header;
}

nav {
    grid-area: nav;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이처럼 각 요소에 &lt;/span&gt;&lt;span&gt;grid-area&lt;/span&gt;&lt;span&gt;를 명시함으로써 그리드에서 배치 위치를 명확하게 정의할 수 있습니다.&lt;/span&gt;&lt;/p&gt;</description>
      <category>프론트엔드/html css</category>
      <author>tero1115</author>
      <guid isPermaLink="true">https://limjisang1115.tistory.com/204</guid>
      <comments>https://limjisang1115.tistory.com/204#entry204comment</comments>
      <pubDate>Fri, 1 Nov 2024 17:56:29 +0900</pubDate>
    </item>
    <item>
      <title>[DB] OFFSET과 LIMIT을 이용한 Pagination(페이징 처리)</title>
      <link>https://limjisang1115.tistory.com/202</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;OFFSET과 LIMIT을 사용한 SQL 페이징 예제&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터베이스에서 많은 양의 데이터를 한 번에 가져오는 것은 비효율적일 수 있습니다. 이를 해결하기 위해 페이징(paging) 기법을 사용하여 필요한 만큼의 데이터만 가져오도록 할 수 있습니다. 이번 포스트에서는 OFFSET과 LIMIT을 사용하여 페이징을 구현하는 방법을 설명하겠습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;페이징의 기본 개념&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;페이징은 데이터를 여러 페이지로 나누어 한 페이지에 일정 개수의 데이터만 보여주는 방식입니다. 이를 통해 데이터베이스에 과부하를 줄이고, 사용자에게 더 나은 경험을 제공합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;OFFSET과 LIMIT의 역할&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;LIMIT: 한 번에 가져올 데이터의 최대 개수를 설정합니다. 예를 들어, 한 페이지에 10개의 데이터를 보여주고 싶다면 LIMIT 10을 사용합니다.&lt;/li&gt;
&lt;li&gt;OFFSET: 가져올 데이터의 시작 위치를 설정합니다. 예를 들어, 첫 페이지는 처음 10개의 데이터를 가져오고, 두 번째 페이지는 그 다음 10개의 데이터를 가져와야 합니다. 이를 위해 OFFSET을 사용하여 시작 위치를 지정합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;SQL 페이징 예제&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음은 OFFSET과 LIMIT을 사용하여 페이징을 구현하는 예제입니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;예제: 직원 목록 페이징&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가정: 직원(employee) 테이블에서 직원 목록을 10개씩 페이지로 나누어 가져오고 싶습니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;첫 번째 페이지&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;LIMIT 10 OFFSET 0: 처음 10개의 데이터를 가져옵니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;div&gt;&lt;span&gt;sql&lt;/span&gt;
&lt;div&gt;&lt;span data-state=&quot;closed&quot;&gt;코드 복사&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&lt;span&gt;SELECT&lt;/span&gt; &lt;span&gt;*&lt;/span&gt; &lt;span&gt;FROM&lt;/span&gt; employee LIMIT &lt;span&gt;10&lt;/span&gt; &lt;span&gt;OFFSET&lt;/span&gt; &lt;span&gt;0&lt;/span&gt;;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;두 번째 페이지&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;LIMIT 10 OFFSET 10: 11번째 데이터부터 20번째 데이터까지 가져옵니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;div&gt;&lt;span&gt;sql&lt;/span&gt;
&lt;div&gt;&lt;span data-state=&quot;closed&quot;&gt;코드 복사&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&lt;span&gt;SELECT&lt;/span&gt; &lt;span&gt;*&lt;/span&gt; &lt;span&gt;FROM&lt;/span&gt; employee LIMIT &lt;span&gt;10&lt;/span&gt; &lt;span&gt;OFFSET&lt;/span&gt; &lt;span&gt;10&lt;/span&gt;;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;세 번째 페이지&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;LIMIT 10 OFFSET 20: 21번째 데이터부터 30번째 데이터까지 가져옵니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;div&gt;&lt;span&gt;sql&lt;/span&gt;
&lt;div&gt;&lt;span data-state=&quot;closed&quot;&gt;코드 복사&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&lt;span&gt;SELECT&lt;/span&gt; &lt;span&gt;*&lt;/span&gt; &lt;span&gt;FROM&lt;/span&gt; employee LIMIT &lt;span&gt;10&lt;/span&gt; &lt;span&gt;OFFSET&lt;/span&gt; &lt;span&gt;20&lt;/span&gt;;&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;PHP 코드에서의 페이징 구현&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래는 PHP 코드에서 페이지 번호와 한 페이지당 데이터 개수를 사용하여 OFFSET 값을 계산하고, 이를 SQL 쿼리에 적용하는 예제입니다.&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1721794537282&quot; class=&quot;php&quot; data-ke-language=&quot;php&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;?php
// 데이터베이스 연결
$DB = new mysqli('localhost', 'username', 'password', 'database');

// 현재 페이지 번호와 페이지당 데이터 개수 설정
$page = isset($_GET['page']) ? (int)$_GET['page'] : 1;
$items_per_page = 10;
$offset = ($page - 1) * $items_per_page;

// 전체 직원 수 조회
$total_sql = &quot;SELECT COUNT(*) as total FROM employee&quot;;
$total_result = $DB-&amp;gt;query($total_sql);
$total_row = $total_result-&amp;gt;fetch_assoc();
$total_count = $total_row['total'];
$total_pages = ceil($total_count / $items_per_page);

// 현재 페이지의 직원 목록 조회
$sql = &quot;SELECT * FROM employee LIMIT $items_per_page OFFSET $offset&quot;;
$result = $DB-&amp;gt;query($sql);

// 결과 출력
$employees = [];
while ($row = $result-&amp;gt;fetch_assoc()) {
    $employees[] = $row;
}

// JSON 형식으로 출력
$output = [
    'current_page' =&amp;gt; $page,
    'total_pages' =&amp;gt; $total_pages,
    'employees' =&amp;gt; $employees,
];

header('Content-Type: application/json');
echo json_encode($output);
?&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 이 PHP 코드는 page 파라미터에 따라 직원 목록을 페이지별로 잘라서 가져옵니다. 예를 들어, http://example.com/employees.php?page=2로 요청하면 두 번째 페이지의 직원 목록을 JSON 형식으로 반환합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;결론&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OFFSET과 LIMIT을 사용하여 페이징을 구현하면 대용량 데이터를 효율적으로 처리하고, 사용자에게 필요한 만큼의 데이터만 제공할 수 있습니다&lt;/p&gt;</description>
      <category>백엔드/DB</category>
      <author>tero1115</author>
      <guid isPermaLink="true">https://limjisang1115.tistory.com/202</guid>
      <comments>https://limjisang1115.tistory.com/202#entry202comment</comments>
      <pubDate>Wed, 24 Jul 2024 13:15:52 +0900</pubDate>
    </item>
    <item>
      <title>[JPA] 중간테이블</title>
      <link>https://limjisang1115.tistory.com/200</link>
      <description>&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;User와 Role테이블이 있다고 가정&lt;/span&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;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;User는 id, username, password&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Role은 id, name&lt;/span&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;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;User는 여러 Role을 가질 수 있고 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;Role&lt;/span&gt;은 여러 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;User&lt;/span&gt;를 가질 수 있으니 Many-to-Many관계이다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1717116648292&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    private String username;
    private String password;

    @ManyToMany(fetch = FetchType.EAGER)
    @JoinTable(
        name = &quot;user_role&quot;,
        joinColumns = @JoinColumn(name = &quot;user_id&quot;),
        inverseJoinColumns = @JoinColumn(name = &quot;role_id&quot;)
    )
    private Set&amp;lt;Role&amp;gt; roles;

}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1717116655102&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Entity
public class Role {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    private String name;

    @ManyToMany(mappedBy = &quot;roles&quot;)
    private Set&amp;lt;User&amp;gt; users;

}&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;중간테이블&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;span style=&quot;&quot;&gt;JPA가&lt;span style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot;&gt;&amp;nbsp;&lt;/span&gt;user_role이&lt;span style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot;&gt;라는 중간 테이블을 생성하여 User와 Role 간의 Many-to-Many 관계를 관리한다. &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;span style=&quot;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot;&gt;이 중간 테이블에는 &lt;/span&gt;user_id&lt;span style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot;&gt;와 &lt;/span&gt;role_id&lt;span style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot;&gt; 컬럼이 포함되어 있다.&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;span style=&quot;&quot;&gt;User 테이블&lt;/span&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;id&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;username&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;password&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;1&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;user1&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;password1&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;2&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;user2&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;password2&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;Role 테이블&lt;/span&gt;&lt;/h4&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 63px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 21px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;id&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 21px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;name&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 21px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;1&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 21px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;ROLE_USER&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 21px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;2&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 21px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;ROLE_ADMIN&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;user_role 중간 테이블&lt;/span&gt;&lt;/h4&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;user_id&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;role_id&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;1&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;1&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;1&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;2&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;2&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 50%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;1&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot;&gt;이 예시에서 &lt;/span&gt;user1&lt;span style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot;&gt;은 &lt;/span&gt;ROLE_USER&lt;span style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot;&gt;와 &lt;/span&gt;ROLE_ADMIN&lt;span style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot;&gt; 역할을 모두 가지며, &lt;/span&gt;user2&lt;span style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot;&gt;는 &lt;/span&gt;ROLE_USER&lt;span style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot;&gt; 역할을 가진다.&lt;/span&gt; &lt;/span&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;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt; &lt;span style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot;&gt; JPA를 사용하면 중간 테이블을 직접 정의할 필요는 없고, 어노테이션을 통해 JPA가 자동으로 생성 및 관리하게 할 수 있다.&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;중간 테이블을 위한 JoinTable 설정&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;JPA의 &lt;b&gt;@ManyToMany&lt;/b&gt;와 &lt;b&gt;@JoinTable&lt;/b&gt; 어노테이션을 사용하여 중간 테이블을 자동으로 생성하고 관리한다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;중간 테이블 이름은 user_roles로 정의되고, user_id와 role_id가 외래 키로 사용된다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;각 엔티티에 ManyToMany 관계를 설정하면 JPA가 자동으로 user_roles 중간 테이블을 생성한다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이 테이블은 사용자가 역할을 갖는 관계를 관리한다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;따라서, User와 Role 엔티티만 정의해주면 JPA가 나머지 작업을 처리한다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #0d0d0d; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;이렇게 하면 데이터베이스에 필요한 세 가지 테이블이 생성되고, 각각의 관계가 올바르게 설정된다.&lt;/span&gt;&lt;/p&gt;</description>
      <category>백엔드/JPA</category>
      <author>tero1115</author>
      <guid isPermaLink="true">https://limjisang1115.tistory.com/200</guid>
      <comments>https://limjisang1115.tistory.com/200#entry200comment</comments>
      <pubDate>Fri, 31 May 2024 10:44:07 +0900</pubDate>
    </item>
  </channel>
</rss>