<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://hidokim.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://hidokim.github.io/" rel="alternate" type="text/html" /><updated>2026-01-30T19:23:08+09:00</updated><id>https://hidokim.github.io/feed.xml</id><title type="html">hidoKim’s blog</title><subtitle>히도의 블로그입니다</subtitle><author><name>김도연</name></author><entry><title type="html">[Node.js] 트랜젝션 vs Promise &amp;amp; 무한 스크롤</title><link href="https://hidokim.github.io/nodejs_study/study_prisma/" rel="alternate" type="text/html" title="[Node.js] 트랜젝션 vs Promise &amp;amp; 무한 스크롤" /><published>2026-01-30T00:00:00+09:00</published><updated>2026-01-30T00:00:00+09:00</updated><id>https://hidokim.github.io/nodejs_study/study_prisma</id><content type="html" xml:base="https://hidokim.github.io/nodejs_study/study_prisma/"><![CDATA[<h1 id="prisma-transaction-vs-promise">Prisma $transaction vs Promise</h1>

<h2 id="1️⃣-promise란-무엇인가요">1️⃣ Promise란 무엇인가요?</h2>

<p><code class="language-plaintext highlighter-rouge">Promise</code>는 자바스크립트에서 <strong>비동기 작업(Asynchronous)</strong>을 처리할 때 사용하는 도구입니다. 비동기 작업이란 “지금 요청하지만, 결과는 나중에 나오는 작업”(예: DB 조회, 파일 읽기)을 말합니다.</p>

<p>Promise는 세 가지 상태를 가집니다:</p>

<ol>
  <li><strong>Pending (대기)</strong>: 아직 작업이 진행 중인 상태.</li>
  <li><strong>Fulfilled (이행)</strong>: 작업이 성공적으로 끝난 상태 (<code class="language-plaintext highlighter-rouge">resolve</code>).</li>
  <li><strong>Rejected (거부)</strong>: 작업이 에러로 끝난 상태 (<code class="language-plaintext highlighter-rouge">reject</code>).</li>
</ol>

<h3 id="예시">예시</h3>

<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// 두 작업을 변수에 담으면 바로 실행이 시작됩니다. (직렬)</span>
<span class="kd">const</span> <span class="nx">countPromise</span> <span class="o">=</span> <span class="nx">prisma</span><span class="p">.</span><span class="nx">video</span><span class="p">.</span><span class="nx">count</span><span class="p">(...);</span>
<span class="kd">const</span> <span class="nx">listPromise</span> <span class="o">=</span> <span class="nx">prisma</span><span class="p">.</span><span class="nx">video</span><span class="p">.</span><span class="nx">findMany</span><span class="p">(...);</span>

<span class="c1">// Promise.all은 배열 안의 모든 작업이 끝날 때까지 동시에 기다립니다. (병렬)</span>
<span class="kd">const</span> <span class="p">[</span><span class="nx">totalCount</span><span class="p">,</span> <span class="nx">videos</span><span class="p">]</span> <span class="o">=</span> <span class="k">await</span> <span class="nb">Promise</span><span class="p">.</span><span class="nx">all</span><span class="p">([</span><span class="nx">countPromise</span><span class="p">,</span> <span class="nx">listPromise</span><span class="p">]);</span>
</code></pre></div></div>

<h2 id="2️⃣-prisma-vs-promise">2️⃣ Prisma vs Promise</h2>

<p>Prisma의 모든 함수(예: <code class="language-plaintext highlighter-rouge">count</code>, <code class="language-plaintext highlighter-rouge">findMany</code>)는 호출 즉시 결과를 주는 게 아니라, DB에 다녀올 때까지 시간이 걸리는 <strong>Promise 객체</strong>를 반환합니다.</p>

<ul>
  <li><strong>동기 방식 (직렬)</strong>: <code class="language-plaintext highlighter-rouge">count</code>가 끝날 때까지 기다렸다가, 그 다음 <code class="language-plaintext highlighter-rouge">findMany</code>를 실행합니다. 전체 시간이 더 오래 걸립니다.</li>
  <li><strong>Promise.all 방식 (병렬)</strong>: <code class="language-plaintext highlighter-rouge">count</code>와 <code class="language-plaintext highlighter-rouge">findMany</code>를 <strong>동시에</strong> DB에 요청합니다. 두 작업 중 더 오래 걸리는 작업의 시간만큼만 기다리면 되므로 훨씬 빠릅니다</li>
</ul>

<h3 id="️-주의할점">❗️ 주의할점</h3>

<p>Prisma는 내부적으로 커넥션 풀(Connection Pool)을 사용합니다. Promise.all로 너무 많은 쿼리를 한 번에 날리면 DB 연결 한도를 초과할 수 있으니, 2~3개의 연관된 쿼리를 묶을 때 사용하는 것이 가장 이상적입니다.</p>

<h3 id="️-결과결론">⭐️ 결과/결론</h3>

<ul>
  <li><code class="language-plaintext highlighter-rouge">Promise</code>는 비동기 작업의 결과표입니다.</li>
  <li><code class="language-plaintext highlighter-rouge">Promise.all</code>은 여러 작업을 동시에 처리해서 <strong>API 응답 속도를 높이기 위해</strong> 사용합니다.</li>
  <li>Prisma를 쓸 때 병렬 조회가 필요한 경우(예: 목록과 전체 개수 조회) 필수적인 기술입니다</li>
</ul>

<h2 id="3️⃣-transaction-vs-promise">3️⃣ $transaction vs Promise</h2>

<table>
  <thead>
    <tr>
      <th><strong>구분</strong></th>
      <th><strong>트랜잭션 ($transaction)</strong></th>
      <th><strong>병렬 처리 (Promise.all)</strong></th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><strong>핵심 목적</strong></td>
      <td><strong>데이터의 무결성</strong> (전부 성공하거나, 전부 취소되거나)</td>
      <td><strong>성능 최적화</strong> (여러 작업을 동시에 실행해서 응답 속도 단축)</td>
    </tr>
    <tr>
      <td><strong>주요 작업</strong></td>
      <td>생성, 수정, 삭제 (Write)</td>
      <td>단순 조회 (Read)</td>
    </tr>
    <tr>
      <td><strong>작동 방식</strong></td>
      <td>하나라도 실패하면 전체 롤백(Rollback)</td>
      <td>각각 독립적으로 실행 (하나가 실패해도 나머지에 직접 영향 없음)</td>
    </tr>
  </tbody>
</table>

<h3 id="promise를-사용하는-경우">Promise를 사용하는 경우</h3>

<ul>
  <li><strong>데이터 조회의 경우</strong>: 영상 개수(<code class="language-plaintext highlighter-rouge">count</code>)를 가져오는 것과 영상 목록(<code class="language-plaintext highlighter-rouge">findMany</code>)을 가져오는 것은 서로 독립적인 작업입니다. 굳이 하나가 실패했다고 해서 다른 하나를 취소(롤백)할 이유가 없습니다.</li>
  <li><strong>성능이 최우선</strong>: 영상 리스트를 불러올 때 사용자가 기다리는 시간을 최소화하는 것이 가장 중요하므로, 두 쿼리를 동시에 날리는 <code class="language-plaintext highlighter-rouge">Promise.all</code>이 가장 적합한 선택입니다.</li>
</ul>

<h2 id="transaction을-사용하는-경우">$transaction을 사용하는 경우</h2>

<p>트랜잭션은 <strong>“이 작업들이 한 묶음으로 처리되지 않으면 데이터가 꼬인다”</strong>라고 판단될 때 씁니다.</p>

<ul>
  <li><strong>예시</strong>: 사용자 계정 삭제 시
    <ol>
      <li><code class="language-plaintext highlighter-rouge">User</code> 테이블에서 사용자 삭제</li>
      <li>해당 사용자의 <code class="language-plaintext highlighter-rouge">Project</code>들 모두 삭제
        <ul>
          <li>만약 1번은 성공했는데 2번에서 서버가 꺼지면, 주인 없는 프로젝트 데이터가 남게 됩니다. 이럴 때 트랜잭션을 써서 둘 다 성공하거나, 아니면 아예 없었던 일로 만들어야 합니다.</li>
        </ul>
      </li>
    </ol>
  </li>
</ul>

<h3 id="️-결과결론-1">⭐️ 결과/결론</h3>

<ul>
  <li><strong>조회(Read)</strong> 작업에서 속도를 높이고 싶을 때는 *<em><code class="language-plaintext highlighter-rouge">Promise.all</code></em>을 씁니다.</li>
  <li><strong>수정/삭제(Write)</strong> 작업에서 데이터 안전을 보장하고 싶을 때는 *<em><code class="language-plaintext highlighter-rouge">$transaction</code></em>을 씁니다.</li>
</ul>]]></content><author><name>김도연</name></author><category term="NodeJS_study" /><category term="NodeJS_study" /><category term="study" /><summary type="html"><![CDATA[Prisma $transaction vs Promise]]></summary></entry><entry><title type="html">[AI] 트랜스포머 아키텍처 기반 모델</title><link href="https://hidokim.github.io/ai_study/study_AI_1/" rel="alternate" type="text/html" title="[AI] 트랜스포머 아키텍처 기반 모델" /><published>2025-11-05T00:00:00+09:00</published><updated>2025-11-05T00:00:00+09:00</updated><id>https://hidokim.github.io/ai_study/study_AI_1</id><content type="html" xml:base="https://hidokim.github.io/ai_study/study_AI_1/"><![CDATA[<h1 id="트랜스포머-아키텍처-기반-모델">트랜스포머 아키텍처 기반 모델</h1>

<hr />

<h1 id="-트랜스포머-아키텍처란">✅ 트랜스포머 아키텍처란?</h1>

<ul>
  <li>
    <p>트랜스포머(Transformer)는 Attention(어텐션) 메커니즘에 기반해 입력 시퀀스의 모든 요소 간 관계를 효과적으로 파악하고 처리하는 딥러닝 모델 구조.</p>
  </li>
  <li>
    <p>기존 RNN/LSTM 기반 seq2seq의 한계를 극복하고, 병렬 처리와 긴 문맥 포착이 뛰어남.</p>
  </li>
  <li>
    <p>대표적으로 자연어 처리(NLP) 분야에서 광범위하게 사용되고, 번역, 요약, 질의응답, 텍스트 생성 등 다양한 Task에 적용됨.</p>
  </li>
</ul>

<h2 id="1️⃣-인코더기반-디코더기반-인코더-디코더기반-모델-각각의-특징-및-비교">1️⃣ 인코더기반, 디코더기반, 인코더-디코더기반 모델 각각의 특징 및 비교</h2>

<h3 id="인코더-기반-">인코더 기반 📥</h3>

<p>입력 전체를 한 번에 받아 각 토큰의 상호관계를 양방향으로 인코딩함. “분석” 중심 작업에 특화</p>

<ul>
  <li>
    <p>대표 모델: BERT, RoBERTa, KoBERT(한국어).​</p>
  </li>
  <li>
    <p>주요 Task: 문장 분류, 감정 분석, 개체명 인식, 문맥 이해 등​</p>
  </li>
</ul>

<h3 id="디코더-기반-">디코더 기반 📤</h3>

<p>이전까지 생성된 출력만을 바탕으로 순차적으로 다음 토큰을 예측·생성함. “생성” 중심 작업에 특화</p>

<ul>
  <li>
    <p>대표 모델: GPT, KoGPT(한국어).​</p>
  </li>
  <li>
    <p>주요 Task: 텍스트 생성, 대화, 요약, 문장 완성 등</p>
  </li>
</ul>

<h3 id="인코더-디코더-기반--">인코더-디코더 기반 📥 📤</h3>

<p>인코더가 입력 정보를 벡터로 임베딩하면, 디코더가 이를 바탕으로 출력 시퀀스를 순차적으로 생성함. “입력과 출력이 모두 시퀀스인” 작업에 특화</p>

<ul>
  <li>
    <p>대표 모델: T5, BART, KoT5(한국어).​</p>
  </li>
  <li>
    <p>주요 Task: 기계 번역, 요약, 질의응답 등 ​</p>
  </li>
</ul>

<h3 id="주요-차이점을-중심으로-모델-비교">주요 차이점을 중심으로 모델 비교</h3>

<h4 id="정보-처리-방식의-차이">정보 처리 방식의 차이</h4>

<ul>
  <li>인코더 기반: 입력 전체 문맥을 양방향으로 파악하여 분석함.
    <ul>
      <li>입력 전체 병렬 처리 가능</li>
    </ul>
  </li>
  <li>디코더 기반: 이전 정보만 참고하여 단방향으로 생성함.
    <ul>
      <li>시퀀스 생성단계 순차 처리 필요</li>
    </ul>
  </li>
  <li>인코더-디코더 기반: 입력은 양방향으로 이해하고(인코더), 출력은 단방향으로 생성(디코더)하는 연속적인 변환 작업에 사용됨.
    <ul>
      <li>입력 인코딩은 병렬 가능, 출력 생성은 순차 처리 필요</li>
    </ul>
  </li>
</ul>

<h4 id="주요-task의-차이">주요 task의 차이</h4>

<ul>
  <li>인코더 기반: 분류, 질의응답(QA), 개체명 인식(NER), 문장 이해 등 자연어 이해 중심 태스크</li>
  <li>디코더 기반: 텍스트 생성, 대화, 요약 등 자연어 생성 중심 태스크</li>
  <li>인코더-디코더 기반: 번역, 요약, 질의응답 등 입력-출력 모두 시퀀스 형태인 복합 태스크</li>
</ul>

<h4 id="속도-및-효율의-차이">속도 및 효율의 차이</h4>

<ul>
  <li>인코더 기반: 빠른 학습/추론 가능, 출력 생성에는 불리함.</li>
  <li>디코더 기반: 생성 속도 상대 느림, 자연스러운 문장 생성 가능함.</li>
  <li>인코더-디코더 기반: 인코더-디코더 모두 병렬+순차 조합, 복합 태스크에 적합함.</li>
</ul>

<h3 id="장단점을-중심으로-모델-비교">장단점을 중심으로 모델 비교</h3>

<ul>
  <li>인코더 기반
    <ul>
      <li>장점: 문장 전체 의미와 관계 파악에 우수함.</li>
      <li>단점: 출력 생성을 직접 지원하기는 어려움.</li>
    </ul>
  </li>
  <li>디코더 기반
    <ul>
      <li>장점: 자연스러운 텍스트 생성에 우수함, 생성형 AI에 적합함.</li>
      <li>단점: 긴 문맥 예측 어려움, 출력 속도가 느림.</li>
    </ul>
  </li>
  <li>인코더-디코더 기반
    <ul>
      <li>장점: 입력-출력 모두 필요한 복잡한 태스크에서 높은 성능을 보임.</li>
      <li>단점: 구조가 복잡하고, 학습과 추론 시 자원 소모가 큼.</li>
    </ul>
  </li>
</ul>

<h1 id="-인코더-기반-모델-kobertkcbert-base">✅ 인코더 기반 모델: KoBERT(kcbert-base)</h1>

<h2 id="1️⃣-모델-조사">1️⃣ 모델 조사</h2>

<p>모델명: KoBERT(beomi/kcbert-base)</p>

<p>제공사: Beomi (개인 및 연구자 공개)</p>

<p>년도: 2022년경 (최초 공개)</p>

<p>모델 크기: 약 1.1억 파라미터 (BERT base 구조)</p>

<p>텍스트/이미지 지원: 텍스트 O / 이미지 X</p>

<p>지원 Task: 텍스트 분류, 감정 분석, 개체명 인식, 다중 분류 등</p>

<p>특징:</p>

<ul>
  <li>
    <p>네이버 뉴스 댓글 및 대댓글 데이터를 대규모로 수집하여 토크나이저와 BERT 구조를 처음부터 학습한 한국어 특화 사전학습 BERT 모델</p>
  </li>
  <li>
    <p>12개 레이어와 12개의 어텐션 헤드를 사용함</p>
  </li>
  <li>
    <p>자연어처리 실무에서 다양한 현장형 한국어 데이터 특성을 반영하여 설계됨</p>
  </li>
  <li>
    <p>한글 및 영어, 특수문자, 이모지 등 다양한 문자와 신조어까지 학습 대상에 포함함.</p>
  </li>
  <li>
    <p>PyTorch 기반 구현체로 다수의 downstream task에서 검증된 높은 성능을 제공함.</p>
  </li>
  <li>
    <p>옵티마이저, 손실함수, 학습 스케줄러 등으로 파인튜닝에 최적화됨.</p>
  </li>
</ul>

<p>출처: Hugging Face ([beomi/kcbert-base])</p>

<h2 id="2️⃣-모델-테스트-코드">2️⃣ 모델 테스트 코드</h2>

<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># 1. 환경 설정 및 라이브러리 설치
</span><span class="err">!</span><span class="n">pip</span> <span class="n">install</span> <span class="n">transformers</span> <span class="n">torch</span> <span class="n">scikit</span><span class="o">-</span><span class="n">learn</span> <span class="n">pandas</span>

<span class="c1"># 2. 라이브러리 임포트 및 모델 로드
</span><span class="kn">import</span> <span class="nn">torch</span>
<span class="kn">import</span> <span class="nn">pandas</span> <span class="k">as</span> <span class="n">pd</span>
<span class="kn">import</span> <span class="nn">numpy</span> <span class="k">as</span> <span class="n">np</span>
<span class="kn">from</span> <span class="nn">transformers</span> <span class="kn">import</span> <span class="n">AutoTokenizer</span><span class="p">,</span> <span class="n">AutoModelForSequenceClassification</span><span class="p">,</span> <span class="n">Trainer</span><span class="p">,</span> <span class="n">TrainingArguments</span>
<span class="kn">from</span> <span class="nn">sklearn.model_selection</span> <span class="kn">import</span> <span class="n">train_test_split</span>
<span class="kn">from</span> <span class="nn">sklearn.metrics</span> <span class="kn">import</span> <span class="n">accuracy_score</span>

<span class="c1"># --- 모델 설정 ---
# 파인튜닝된 감정 분류 모델 로드
</span><span class="n">model_name</span> <span class="o">=</span> <span class="s">"beomi/kcbert-base"</span>
<span class="n">tokenizer</span> <span class="o">=</span> <span class="n">AutoTokenizer</span><span class="p">.</span><span class="n">from_pretrained</span><span class="p">(</span><span class="n">model_name</span><span class="p">)</span>

<span class="c1"># num_labels=2 를 명시하여 출력 레이어를 2개로 재설정
</span><span class="n">model</span> <span class="o">=</span> <span class="n">AutoModelForSequenceClassification</span><span class="p">.</span><span class="n">from_pretrained</span><span class="p">(</span>
    <span class="n">model_name</span><span class="p">,</span>
    <span class="n">num_labels</span><span class="o">=</span><span class="mi">2</span><span class="p">,</span>
    <span class="n">ignore_mismatched_sizes</span><span class="o">=</span><span class="bp">True</span>
<span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"✅ 모델 로드 완료: </span><span class="si">{</span><span class="n">model_name</span><span class="si">}</span><span class="s"> (출력 클래스 2개로 재설정)"</span><span class="p">)</span>


</code></pre></div></div>

<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
<span class="c1"># 샘플 데이터셋
</span><span class="n">data</span> <span class="o">=</span> <span class="p">{</span>
    <span class="s">'text'</span><span class="p">:</span> <span class="p">[</span>
        <span class="s">"이번 주말 여행은 완벽했어요. 날씨도 좋고 숙소도 최고!"</span><span class="p">,</span>  <span class="c1"># 긍정 (1)
</span>        <span class="s">"기다렸던 공연인데, 사운드 문제가 심각해서 너무 실망했어요."</span><span class="p">,</span> <span class="c1"># 부정 (0)
</span>        <span class="s">"강의 내용이 체계적이고 알차서 많은 것을 배웠습니다."</span><span class="p">,</span>  <span class="c1"># 긍정 (1)
</span>        <span class="s">"문의 전화를 여러 번 했는데 응대가 불친절하고 느렸습니다."</span><span class="p">,</span> <span class="c1"># 부정 (0)
</span>        <span class="s">"이 책은 내용이 흥미롭고 문체가 아름다워 읽는 내내 행복했습니다."</span><span class="p">,</span>  <span class="c1"># 긍정 (1)
</span>        <span class="s">"주문한 상품에 하자가 있는데, 교환 절차가 너무 복잡하고 까다로웠습니다."</span><span class="p">,</span> <span class="c1"># 부정 (0)
</span>        <span class="s">"새로 추가된 기능이 사용자 편의성을 크게 높여준 것 같아요."</span><span class="p">,</span> <span class="c1"># 긍정 (1)
</span>        <span class="s">"결과가 기대치에 한참 못 미쳐서 프로젝트를 다시 해야 할 것 같습니다."</span> <span class="c1"># 부정 (0)
</span>    <span class="p">],</span>
    <span class="s">'label'</span><span class="p">:</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">]</span>  <span class="c1"># 1: 긍정, 0: 부정
</span><span class="p">}</span>
<span class="n">df</span> <span class="o">=</span> <span class="n">pd</span><span class="p">.</span><span class="n">DataFrame</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
<span class="n">train_df</span><span class="p">,</span> <span class="n">val_df</span> <span class="o">=</span> <span class="n">train_test_split</span><span class="p">(</span><span class="n">df</span><span class="p">,</span> <span class="n">test_size</span><span class="o">=</span><span class="mf">0.2</span><span class="p">,</span> <span class="n">random_state</span><span class="o">=</span><span class="mi">42</span><span class="p">)</span>

<span class="c1"># 데이터셋 클래스 정의
</span><span class="k">class</span> <span class="nc">SentimentDataset</span><span class="p">(</span><span class="n">torch</span><span class="p">.</span><span class="n">utils</span><span class="p">.</span><span class="n">data</span><span class="p">.</span><span class="n">Dataset</span><span class="p">):</span>
    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">texts</span><span class="p">,</span> <span class="n">labels</span><span class="p">,</span> <span class="n">tokenizer</span><span class="p">,</span> <span class="n">max_length</span><span class="o">=</span><span class="mi">128</span><span class="p">):</span>
        <span class="bp">self</span><span class="p">.</span><span class="n">texts</span> <span class="o">=</span> <span class="n">texts</span>
        <span class="bp">self</span><span class="p">.</span><span class="n">labels</span> <span class="o">=</span> <span class="n">labels</span>
        <span class="bp">self</span><span class="p">.</span><span class="n">tokenizer</span> <span class="o">=</span> <span class="n">tokenizer</span>
        <span class="bp">self</span><span class="p">.</span><span class="n">max_length</span> <span class="o">=</span> <span class="n">max_length</span>

    <span class="k">def</span> <span class="nf">__len__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">return</span> <span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">texts</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">__getitem__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">idx</span><span class="p">):</span>
        <span class="n">text</span> <span class="o">=</span> <span class="nb">str</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">texts</span><span class="p">.</span><span class="n">iloc</span><span class="p">[</span><span class="n">idx</span><span class="p">])</span>
        <span class="n">label</span> <span class="o">=</span> <span class="bp">self</span><span class="p">.</span><span class="n">labels</span><span class="p">.</span><span class="n">iloc</span><span class="p">[</span><span class="n">idx</span><span class="p">]</span>

        <span class="n">encoding</span> <span class="o">=</span> <span class="bp">self</span><span class="p">.</span><span class="n">tokenizer</span><span class="p">(</span>
            <span class="n">text</span><span class="p">,</span>
            <span class="n">truncation</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span>
            <span class="n">padding</span><span class="o">=</span><span class="s">'max_length'</span><span class="p">,</span>
            <span class="n">max_length</span><span class="o">=</span><span class="bp">self</span><span class="p">.</span><span class="n">max_length</span><span class="p">,</span>
            <span class="n">return_tensors</span><span class="o">=</span><span class="s">'pt'</span>
        <span class="p">)</span>

        <span class="k">return</span> <span class="p">{</span>
            <span class="s">'input_ids'</span><span class="p">:</span> <span class="n">encoding</span><span class="p">[</span><span class="s">'input_ids'</span><span class="p">].</span><span class="n">flatten</span><span class="p">(),</span>
            <span class="s">'attention_mask'</span><span class="p">:</span> <span class="n">encoding</span><span class="p">[</span><span class="s">'attention_mask'</span><span class="p">].</span><span class="n">flatten</span><span class="p">(),</span>
            <span class="s">'labels'</span><span class="p">:</span> <span class="n">torch</span><span class="p">.</span><span class="n">tensor</span><span class="p">(</span><span class="n">label</span><span class="p">,</span> <span class="n">dtype</span><span class="o">=</span><span class="n">torch</span><span class="p">.</span><span class="nb">long</span><span class="p">)</span>
        <span class="p">}</span>

<span class="c1"># 데이터셋 생성
</span><span class="n">train_dataset</span> <span class="o">=</span> <span class="n">SentimentDataset</span><span class="p">(</span><span class="n">train_df</span><span class="p">[</span><span class="s">'text'</span><span class="p">],</span> <span class="n">train_df</span><span class="p">[</span><span class="s">'label'</span><span class="p">],</span> <span class="n">tokenizer</span><span class="p">)</span>
<span class="n">val_dataset</span> <span class="o">=</span> <span class="n">SentimentDataset</span><span class="p">(</span><span class="n">val_df</span><span class="p">[</span><span class="s">'text'</span><span class="p">],</span> <span class="n">val_df</span><span class="p">[</span><span class="s">'label'</span><span class="p">],</span> <span class="n">tokenizer</span><span class="p">)</span>

<span class="c1"># 훈련 설정 및 트레이너 초기화
</span>
<span class="c1"># 훈련 인자 설정
</span><span class="n">training_args</span> <span class="o">=</span> <span class="n">TrainingArguments</span><span class="p">(</span>
    <span class="n">output_dir</span><span class="o">=</span><span class="s">'./results'</span><span class="p">,</span>
    <span class="n">num_train_epochs</span><span class="o">=</span><span class="mi">5</span><span class="p">,</span>
    <span class="n">per_device_train_batch_size</span><span class="o">=</span><span class="mi">8</span><span class="p">,</span>
    <span class="n">per_device_eval_batch_size</span><span class="o">=</span><span class="mi">8</span><span class="p">,</span>
    <span class="n">warmup_steps</span><span class="o">=</span><span class="mi">500</span><span class="p">,</span>
    <span class="n">weight_decay</span><span class="o">=</span><span class="mf">0.01</span><span class="p">,</span>
    <span class="n">logging_dir</span><span class="o">=</span><span class="s">'./logs'</span><span class="p">,</span>
    <span class="n">eval_strategy</span><span class="o">=</span><span class="s">"epoch"</span><span class="p">,</span>
    <span class="n">save_strategy</span><span class="o">=</span><span class="s">"epoch"</span><span class="p">,</span>
    <span class="n">load_best_model_at_end</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span>
<span class="p">)</span>

<span class="c1"># 평가 지표 함수
</span><span class="k">def</span> <span class="nf">compute_metrics</span><span class="p">(</span><span class="n">eval_pred</span><span class="p">):</span>
    <span class="n">predictions</span><span class="p">,</span> <span class="n">labels</span> <span class="o">=</span> <span class="n">eval_pred</span>
    <span class="n">predictions</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="n">argmax</span><span class="p">(</span><span class="n">predictions</span><span class="p">,</span> <span class="n">axis</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span>
    <span class="k">return</span> <span class="p">{</span><span class="s">'accuracy'</span><span class="p">:</span> <span class="n">accuracy_score</span><span class="p">(</span><span class="n">labels</span><span class="p">,</span> <span class="n">predictions</span><span class="p">)}</span>

<span class="c1"># 트레이너 초기화
</span><span class="n">trainer</span> <span class="o">=</span> <span class="n">Trainer</span><span class="p">(</span>
    <span class="n">model</span><span class="o">=</span><span class="n">model</span><span class="p">,</span>
    <span class="n">args</span><span class="o">=</span><span class="n">training_args</span><span class="p">,</span>
    <span class="n">train_dataset</span><span class="o">=</span><span class="n">train_dataset</span><span class="p">,</span>
    <span class="n">eval_dataset</span><span class="o">=</span><span class="n">val_dataset</span><span class="p">,</span>
    <span class="n">compute_metrics</span><span class="o">=</span><span class="n">compute_metrics</span>
<span class="p">)</span>

<span class="k">print</span><span class="p">(</span><span class="s">"✅ Trainer 초기화가 성공적으로 완료되었습니다. 이제 훈련을 시작할 수 있습니다."</span><span class="p">)</span>


</code></pre></div></div>

<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">os</span>
<span class="n">os</span><span class="p">.</span><span class="n">environ</span><span class="p">[</span><span class="s">"WANDB_DISABLED"</span><span class="p">]</span> <span class="o">=</span> <span class="s">"true"</span>
<span class="k">print</span><span class="p">(</span><span class="s">"✅ WandB 로깅 비활성화 설정 완료. 훈련을 시작합니다."</span><span class="p">)</span>

<span class="c1"># 모델 훈련
</span><span class="k">print</span><span class="p">(</span><span class="s">"</span><span class="se">\n</span><span class="s">모델 훈련을 시작합니다. 5 epoch 후 확신도가 높은 결과가 출력될 것입니다."</span><span class="p">)</span>
<span class="n">trainer</span><span class="p">.</span><span class="n">train</span><span class="p">()</span>


<span class="c1"># 3. 새로운 테스트 텍스트로 추론
</span><span class="n">new_test_texts</span> <span class="o">=</span> <span class="p">[</span>
    <span class="s">"어제 산 커피가 너무 맛있어서 하루 종일 기분이 좋았어요."</span><span class="p">,</span>  <span class="c1"># 긍정
</span>    <span class="s">"고객 센터 연결이 안 돼서 환불을 못 받았어요. 화가 납니다."</span><span class="p">,</span> <span class="c1"># 부정
</span>    <span class="s">"새로운 정책이 적용되었지만, 아직 장단점을 모르겠습니다."</span><span class="p">,</span>   <span class="c1"># 중립/불확실 (모델이 긍정 또는 부정 중 하나로 분류)
</span>    <span class="s">"와, 이 노트북 배터리 성능 정말 최고네요!"</span><span class="p">,</span> <span class="c1"># 긍정
</span>    <span class="s">"작업 결과가 기대에 훨씬 못 미쳤다."</span> <span class="c1"># 부정
</span><span class="p">]</span>

<span class="c1"># 토큰화 및 인코딩
</span><span class="n">encoded</span> <span class="o">=</span> <span class="n">tokenizer</span><span class="p">(</span><span class="n">new_test_texts</span><span class="p">,</span> <span class="n">padding</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span> <span class="n">truncation</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span> <span class="n">return_tensors</span><span class="o">=</span><span class="s">'pt'</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">"</span><span class="se">\n</span><span class="s">--- 토큰화 결과 (샘플) ---"</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"'</span><span class="si">{</span><span class="n">new_test_texts</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="si">}</span><span class="s">' -&gt; </span><span class="si">{</span><span class="n">tokenizer</span><span class="p">.</span><span class="n">tokenize</span><span class="p">(</span><span class="n">new_test_texts</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span><span class="si">}</span><span class="s">"</span><span class="p">)</span>

<span class="c1"># 4. 예측 함수 정의 및 추론
</span><span class="k">def</span> <span class="nf">predict_sentiment</span><span class="p">(</span><span class="n">text</span><span class="p">):</span>
    <span class="n">inputs</span> <span class="o">=</span> <span class="n">tokenizer</span><span class="p">(</span><span class="n">text</span><span class="p">,</span> <span class="n">return_tensors</span><span class="o">=</span><span class="s">'pt'</span><span class="p">,</span> <span class="n">padding</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span> <span class="n">truncation</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>

    <span class="c1"># GPU 사용 시 모델과 입력을 GPU로 이동
</span>    <span class="k">if</span> <span class="n">torch</span><span class="p">.</span><span class="n">cuda</span><span class="p">.</span><span class="n">is_available</span><span class="p">():</span>
        <span class="n">inputs</span> <span class="o">=</span> <span class="p">{</span><span class="n">k</span><span class="p">:</span> <span class="n">v</span><span class="p">.</span><span class="n">to</span><span class="p">(</span><span class="s">'cuda'</span><span class="p">)</span> <span class="k">for</span> <span class="n">k</span><span class="p">,</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">inputs</span><span class="p">.</span><span class="n">items</span><span class="p">()}</span>
        <span class="n">model</span><span class="p">.</span><span class="n">to</span><span class="p">(</span><span class="s">'cuda'</span><span class="p">)</span>

    <span class="k">with</span> <span class="n">torch</span><span class="p">.</span><span class="n">no_grad</span><span class="p">():</span>
        <span class="n">outputs</span> <span class="o">=</span> <span class="n">model</span><span class="p">(</span><span class="o">**</span><span class="n">inputs</span><span class="p">)</span>
        <span class="c1"># Softmax를 적용하여 확률로 변환
</span>        <span class="n">predictions</span> <span class="o">=</span> <span class="n">torch</span><span class="p">.</span><span class="n">nn</span><span class="p">.</span><span class="n">functional</span><span class="p">.</span><span class="n">softmax</span><span class="p">(</span><span class="n">outputs</span><span class="p">.</span><span class="n">logits</span><span class="p">,</span> <span class="n">dim</span><span class="o">=-</span><span class="mi">1</span><span class="p">)</span>

        <span class="n">predicted_class</span> <span class="o">=</span> <span class="n">torch</span><span class="p">.</span><span class="n">argmax</span><span class="p">(</span><span class="n">predictions</span><span class="p">,</span> <span class="n">dim</span><span class="o">=-</span><span class="mi">1</span><span class="p">).</span><span class="n">item</span><span class="p">()</span>
        <span class="n">confidence</span> <span class="o">=</span> <span class="n">predictions</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="n">predicted_class</span><span class="p">].</span><span class="n">item</span><span class="p">()</span>

    <span class="c1"># 이 모델은 클래스 1을 긍정, 클래스 0을 부정으로 분류할 가능성이 높다고 가정합니다.
</span>    <span class="n">sentiment</span> <span class="o">=</span> <span class="s">"긍정"</span> <span class="k">if</span> <span class="n">predicted_class</span> <span class="o">==</span> <span class="mi">1</span> <span class="k">else</span> <span class="s">"부정"</span>

    <span class="k">return</span> <span class="n">sentiment</span><span class="p">,</span> <span class="n">confidence</span>

<span class="k">print</span><span class="p">(</span><span class="s">"</span><span class="se">\n</span><span class="s">--- 새로운 테스트 결과 ---"</span><span class="p">)</span>
<span class="k">for</span> <span class="n">text</span> <span class="ow">in</span> <span class="n">new_test_texts</span><span class="p">:</span>
    <span class="n">sentiment</span><span class="p">,</span> <span class="n">confidence</span> <span class="o">=</span> <span class="n">predict_sentiment</span><span class="p">(</span><span class="n">text</span><span class="p">)</span>
    <span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"'</span><span class="si">{</span><span class="n">text</span><span class="si">}</span><span class="s">' -&gt; </span><span class="si">{</span><span class="n">sentiment</span><span class="si">}</span><span class="s"> (확신도: </span><span class="si">{</span><span class="n">confidence</span><span class="si">:</span><span class="p">.</span><span class="mi">2</span><span class="n">f</span><span class="si">}</span><span class="s">)"</span><span class="p">)</span>

</code></pre></div></div>

<h2 id="3️⃣-실행결과">3️⃣ 실행결과</h2>

<ul>
  <li>
    <p>KoBERT는 WordPiece 토크나이저를 사용하며, 실행 결과에서 볼 수 있듯 ‘커피가’를 [‘커피’, ‘##가’]처럼 의미 있는 단위를 분리하여 미등록 단어 문제에 효과적으로 대응한다.</p>
  </li>
  <li>
    <p>Validation Loss: 0.646 -&gt; 0.656 (증가)</p>

    <ul>
      <li>오버피팅(Overfitting)발생. 모델이 훈련 데이터에 너무 집중한 나머지, 일반적인 검증 데이터(Validation Data)에 대해서는 오히려 성능이 나빠지고 있음.</li>
    </ul>
  </li>
  <li>
    <p>Accuracy: 1.000(100%)</p>

    <ul>
      <li>검증 데이터가 너무 적기 때문에(1~2개 문장), 우연히 모두 맞춰도 100%가 나온다. 하지만 손실(Loss)이 증가하고 있으므로 모델이 의미 있는 학습을 하고 있다고 볼 수 없다.</li>
    </ul>
  </li>
  <li>
    <p>긍정(1)과 부정(0)을 구분하는 이진 분류에서 확신도 0.5는 “모델이 찍는 것과 다름없다”는 의미로, 모델이 긍정과 부정 중 무엇을 선택해야 할지 매우 혼란스러워하고 있다는 뜻이다.</p>
  </li>
  <li>
    <p>발생한 문제: 테스트한 언어 모델(beomi/kcbert-base)은 약 1.1억개의 파라미터를 가지고 있는데, 이 거대한 모델에게 6~7개의 샘플만 주고 학습을 시켰기 때문에, 모델은 일반적인 규칙을 배우지 못하고 주어진 7개의 샘플을 단순 암기하는(과적합)결과가 나왔다.</p>
    <ul>
      <li>훈련 샘플 수: 6~7개 (8개 샘플 중 20%를 검증 데이터로 나눔)</li>
    </ul>
  </li>
</ul>

<h1 id="-디코더-기반-모델-kogptko-gpt-trinity-12b-v05">✅ 디코더 기반 모델: KoGPT(ko-gpt-trinity-1.2B-v0.5)</h1>

<h2 id="1️⃣-모델-조사-1">1️⃣ 모델 조사</h2>

<p>모델명: KoGPT (skt/ko-gpt-trinity-1.2B-v0.5)</p>

<p>제공사: SK Telecom (SKT)</p>

<p>년도: 2022</p>

<p>모델 크기: 약 11.6억 파라미터</p>

<p>텍스트/이미지 지원: 텍스트 O / 이미지 X</p>

<p>지원 Task: 텍스트 생성, 대화, 요약, 문장 완성 등 다양하고 복합적인 생성형 Task</p>

<p>특징:</p>

<ul>
  <li>
    <p>SK텔레콤에서 공개한 오픈소스 한국어 GPT 계열 대형 트랜스포머 디코더(Decoder-only) 구조의 생성형 모델</p>
  </li>
  <li>GPT-2/3 아키텍처처럼 다음 토큰 예측(Next Token Prediction) 방식으로 학습되었음</li>
  <li>
    <p>대규모 한국어 코퍼스를 중심으로 사전훈련되어 한국어 자연어 생성, 문장 완성, 요약, 대화 등 다양한 자연어 생성 태스크에 활용가능.</p>
  </li>
  <li>
    <p>한국어 챗봇, 텍스트 생성, 문장 변환, 감성분석 등의 연구 및 실험적 용도에 적합</p>
  </li>
  <li>
    <p>내부적으로는 24레이어, 1920 임베딩, 16 어텐션 헤드를 사용하며, 모델 파일 크기는 약 4.7GB</p>
  </li>
  <li>공개 모델로 Hugging Face에서 사용 가능</li>
</ul>

<p>출처: Hugging Face ([skt/ko-gpt-trinity-1.2B-v0.5])</p>

<h2 id="2️⃣-테스트-코드">2️⃣ 테스트 코드</h2>

<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">transformers</span> <span class="kn">import</span> <span class="n">pipeline</span>

<span class="k">print</span><span class="p">(</span><span class="s">"SK텔레콤 KoGPT Trinity 모델을 로딩합니다..."</span><span class="p">)</span>
<span class="n">text_generator</span> <span class="o">=</span> <span class="n">pipeline</span><span class="p">(</span>
    <span class="s">"text-generation"</span><span class="p">,</span>
    <span class="n">model</span><span class="o">=</span><span class="s">"skt/ko-gpt-trinity-1.2B-v0.5"</span>
<span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">"모델 로딩이 완료되었습니다!"</span><span class="p">)</span>

<span class="c1"># 텍스트 생성 시작 문장
</span><span class="n">prompt</span> <span class="o">=</span> <span class="s">"자연어 처리 기술이 발전하면서"</span>

<span class="c1"># 텍스트 생성, max_length 조절, 3개의 서로 다른 생성문 출력
</span><span class="n">generated_texts</span> <span class="o">=</span> <span class="n">text_generator</span><span class="p">(</span>
    <span class="n">prompt</span><span class="p">,</span>
    <span class="n">max_length</span><span class="o">=</span><span class="mi">80</span><span class="p">,</span>
    <span class="n">num_return_sequences</span><span class="o">=</span><span class="mi">3</span>
<span class="p">)</span>

<span class="k">print</span><span class="p">(</span><span class="s">"</span><span class="se">\n</span><span class="s">"</span> <span class="o">+</span> <span class="s">"="</span><span class="o">*</span><span class="mi">50</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"시작 문장(Prompt): '</span><span class="si">{</span><span class="n">prompt</span><span class="si">}</span><span class="s">'"</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">"="</span><span class="o">*</span><span class="mi">50</span> <span class="o">+</span> <span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">)</span>

<span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">text</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">generated_texts</span><span class="p">):</span>
    <span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"--- [생성 결과 </span><span class="si">{</span><span class="n">i</span><span class="o">+</span><span class="mi">1</span><span class="si">}</span><span class="s">] ---"</span><span class="p">)</span>
    <span class="k">print</span><span class="p">(</span><span class="n">text</span><span class="p">[</span><span class="s">'generated_text'</span><span class="p">])</span>
    <span class="k">print</span><span class="p">(</span><span class="s">"</span><span class="se">\n</span><span class="s">"</span><span class="p">)</span>

</code></pre></div></div>

<h2 id="3️⃣-실행결과-1">3️⃣ 실행결과</h2>

<ul>
  <li>한국어가 자연스럽고 문법적 오류가 거의 없다.</li>
  <li>문장 간의 연결이 매우 매끄럽다.</li>
  <li>전문적인 형태나 블로그 형태의 문체도 잘 구현한다.</li>
  <li>세 가지 생성 결과가 각각 다른 주제와 다른 문체로 작성된다. 즉, 모델이 높은 다양성을 가지고 있다.</li>
</ul>

<h1 id="-인코더-디코더-기반-모델-kot5long-ke-t5-base-summarization_e10">✅ 인코더-디코더 기반 모델: KoT5(long-ke-t5-base-summarization_e10)</h1>

<h2 id="1️⃣-모델-조사-2">1️⃣ 모델 조사</h2>

<p>모델명: KoT5(KETI-AIR-Downstream/long-ke-t5-base-summarization_e10)</p>

<p>제공사: KETI-AIR (한국전자통신연구원 및 AI 연구팀)</p>

<p>년도: 2023</p>

<p>모델 크기: Base 기준 약 1.8억 파라미터 (T5-base 구조)</p>

<p>텍스트/이미지 지원: 텍스트 O / 이미지 X</p>

<p>지원 Task: 텍스트 요약, 번역, 질의응답(QA), 분류, 텍스트-투-텍스트 작업</p>

<p>특징:</p>

<ul>
  <li>
    <p>KETI-AIR의 long-ke-t5-base 모델을 기반으로 한국어 요약 데이터셋(jsonl_dataset_sum.py)에서 파인튜닝된 텍스트 요약용 모델</p>

    <ul>
      <li>“요약” 목적에 파인튜닝 되어있다.</li>
    </ul>
  </li>
  <li>
    <p>한국어와 영어 혼합 환경 대응에 최적화된 서브워드 토크나이저를 사용함.</p>
  </li>
  <li>
    <p>학습 시 하이퍼파라미터로는 학습률 0.001, 배치 사이즈 1, 총 10 에폭(epoch) 등이 사용됨.</p>
  </li>
  <li>
    <p>다중 GPU 환경에서 Adam 옵티마이저와 선형 학습률 스케줄러로 훈련됨.</p>
  </li>
  <li>
    <p>평가 결과는 Rouge 계열 지표에서 Rouge1 약 22, Rouge2 약 10, Rougel 약 21 정도를 기록하여 요약 성능을 어느 정도 입증함.</p>
  </li>
  <li>
    <p>구글의 T5(Text-to-Text Transfer Transformer) 아키텍처 기반 모델을 한국어 및 영어 비정형 데이터에 맞게 사전학습함</p>
  </li>
  <li>
    <p>최대 입력 길이 4096 토큰, 출력 길이 1024 토큰 지원</p>
  </li>
  <li>
    <p>공개 Hugging Face 저장소에서 사용 가능</p>
  </li>
</ul>

<p>출처:</p>

<ul>
  <li>Hugging Face ([KETI-AIR-Downstream/long-ke-t5-base-summarization_e10])</li>
</ul>

<h2 id="2️⃣-테스트-코드-1">2️⃣ 테스트 코드</h2>

<div class="language-py highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">transformers</span> <span class="kn">import</span> <span class="n">pipeline</span>
<span class="kn">import</span> <span class="nn">torch</span>

<span class="c1"># 1. KoT5 기반 한국어 장문 요약 모델 로드
</span><span class="k">print</span><span class="p">(</span><span class="s">"KETI의 long-ke-t5-base-summarization_e10 모델을 로딩합니다..."</span><span class="p">)</span>
<span class="n">pipe</span> <span class="o">=</span> <span class="n">pipeline</span><span class="p">(</span>
    <span class="s">"text2text-generation"</span><span class="p">,</span>
    <span class="n">model</span><span class="o">=</span><span class="s">"KETI-AIR-Downstream/long-ke-t5-base-summarization_e10"</span><span class="p">,</span>
    <span class="n">device_map</span><span class="o">=</span><span class="s">"auto"</span><span class="p">,</span>
    <span class="n">torch_dtype</span><span class="o">=</span><span class="n">torch</span><span class="p">.</span><span class="n">float16</span>
<span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">"모델 로딩 완료!"</span><span class="p">)</span>

<span class="c1"># 2. 요약할 긴 텍스트
</span><span class="n">long_text</span> <span class="o">=</span> <span class="p">(</span>
    <span class="s">"최근 국내 ICT 업계에서는 인공지능 기술을 이용한 다양한 서비스 개발이 빠르게 이루어지고 있습니다."</span>
    <span class="s">"인공지능 챗봇, 음성 인식, 의료 데이터 분석, 자동 번역 시스템 등 여러 분야에서 활용도가 높아지고 있음은 물론,"</span>
    <span class="s">"기존 업계의 경쟁구도 역시 크게 변화하고 있습니다. 특히 2025년 들어 대형 IT 기업들이 대규모 한국어 자연어처리"</span>
    <span class="s">"모델을 공개함으로써, 소상공인과 중소기업들도 비교적 저렴한 비용으로 첨단 서비스를 도입할 수 있게 되었습니다."</span>
    <span class="s">"전문가들은 향후 인공지능 기반 자동화 서비스가 금융, 법률, 교육 등 사회 전 영역으로 확산될 것으로 전망하고 있습니다. "</span>
    <span class="s">"다만 데이터 품질 관리, 개인정보보호, 편향 문제 등 추가 논의가 필요한 과제도 적지 않으며, 관련 법과 정책의 마련이 중요하다는"</span>
    <span class="s">"의견도 많습니다. 실제로 최근 논의된 국가 데이터댐 프로젝트와 AI 윤리 가이드라인은 산업 경쟁력 확보는 물론 사회적 신뢰 형성에"</span>
    <span class="s">"기여할 것으로 평가받고 있습니다. 이러한 변화 속에서 우리 사회가 기술의 효율성과 인간 중심"</span>
    <span class="s">"원칙 사이에서 균형을 어떻게 잡아 나갈지가 앞으로 주요 과제가 될 것입니다."</span>
<span class="p">)</span>


<span class="c1"># 3. 모델을 사용해 요약 생성
</span><span class="n">result</span> <span class="o">=</span> <span class="n">pipe</span><span class="p">(</span><span class="n">long_text</span><span class="p">,</span> <span class="n">max_length</span><span class="o">=</span><span class="mi">100</span><span class="p">,</span> <span class="n">num_return_sequences</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span>

<span class="k">print</span><span class="p">(</span><span class="s">"</span><span class="se">\n</span><span class="s">=== 원문 ==="</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">long_text</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">"</span><span class="se">\n</span><span class="s">=== 요약 결과 ==="</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">result</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="s">'generated_text'</span><span class="p">])</span>

</code></pre></div></div>

<h2 id="3️⃣-실행결과-2">3️⃣ 실행결과</h2>

<ul>
  <li>
    <p>가장 중요한 정보에 집중하여 간결한 요약을 작성했다.</p>
  </li>
  <li>
    <p>모델은 원문에 있는 문장을 그대로 사용하지 않고, 여러 문장의 핵심 구문과 단어를 재조합하여 새로운 문장을 만들었다.</p>
  </li>
  <li>
    <p>단순 추출 요약(Extractive)보다 발전된 추상 요약(Abstractive) 능력을 보여주었다.</p>
  </li>
</ul>

<h1 id="-모델-테스트-후-느낀점">💡 모델 테스트 후 느낀점</h1>

<p>이번 기계학습 프로그래밍 과제를 통해 트랜스포머 아키텍처 기반 모델을 직접 조사하고 실습해 보았다. Hugging Face 생태계를 활용하여 인코더, 디코더, 인코더-디코더 모델을 테스트하며 배운 점과 느낀 점을 정리한다.</p>

<h2 id="1-hugging-face-활용의-용이성과-접근성">1. Hugging Face 활용의 용이성과 접근성</h2>

<ul>
  <li>
    <p>처음에는 대규모 언어 모델(LLM)을 다루고 파인튜닝하는 일이 매우 복잡하고 어려울 것이라고 생각했지만, 실제로는 이미 파인튜닝된 모델을 가져와 준비한 데이터셋에 맞게 학습시키거나 바로 테스트하는 방법이여서 훨씬 간단했다. 괜히 겁을 먹었다는 생각이 들었다.</p>
  </li>
  <li>
    <p>모델을 로드하고 테스트 코드를 실행하는 시간이 오래 걸리지 않아 생각보다 빠르게 결과를 확인할 수 있었다.</p>
  </li>
</ul>

<h2 id="2-모델-탐색에서의-시간-투자">2. 모델 탐색에서의 시간 투자</h2>

<ul>
  <li>실제 실습 과정 중 가장 많은 시간이 소요된 부분은 적합한 파인튜닝 모델을 찾는 일이었다.</li>
  <li>hugging Face에 너무 많은 모델들이 있어서 원하는 작업에 최적화된 파인튜닝 모델을 찾는 과정에서 시간이 오래 걸렸다.</li>
</ul>

<h2 id="3-데이터와-과적합overfitting-경험">3. 데이터와 과적합(Overfitting) 경험</h2>

<p>인코더 기반 모델(KoBERT)의 감정 분류 파인튜닝 실습을 통해 데이터의 중요성을 경험했다.</p>

<ul>
  <li>
    <p>극단적 과적합 경험: 8개의 매우 작은 샘플 데이터셋으로 5 Epoch을 훈련했을 때, 모델이 일반적인 감정 규칙을 배우지 못하고 훈련 데이터에 <strong>과적합(Overfitting)</strong>되는 결과가 나왔다. 테스트 결과의 확신도가 0.5대에 머물러 모델이 예측을 포기하는 수준이었다.</p>
  </li>
  <li>
    <p>향후 과제: 다음 실습에서는 더 많은 데이터셋을 준비하고 적절한 Epoch 수로 훈련해서 과적합 문제를 해결하고 더 높은 확신도의 결과를 만들고싶다.</p>
  </li>
</ul>

<h2 id="4-인코더-디코더-모델의-뛰어난-성능">4. 인코더-디코더 모델의 뛰어난 성능</h2>

<p>인코더-디코더 기반 모델(KoT5)을 사용한 텍스트 요약 성능은 생각보다 더 좋았다.</p>

<ul>
  <li>KoT5 모델의 긴 문장의 핵심 내용을 파악하고 자연스러운 추상 요약 문장으로 출력하는 능력을 보고, 입력과 출력이 모두 시퀀스인 복잡한 작업(번역, 요약)에서 트랜스포머 아키텍처 모델의 강력함을 느꼈다.</li>
</ul>]]></content><author><name>김도연</name></author><category term="AI_study" /><category term="AI_study" /><category term="study" /><summary type="html"><![CDATA[트랜스포머 아키텍처 기반 모델]]></summary></entry><entry><title type="html">[MySQL] SQL 기본문법 : 서브쿼리</title><link href="https://hidokim.github.io/mysql_study/study_MySQL_5/" rel="alternate" type="text/html" title="[MySQL] SQL 기본문법 : 서브쿼리" /><published>2025-09-26T00:00:00+09:00</published><updated>2025-09-26T00:00:00+09:00</updated><id>https://hidokim.github.io/mysql_study/study_MySQL_5</id><content type="html" xml:base="https://hidokim.github.io/mysql_study/study_MySQL_5/"><![CDATA[<h1 id="sql-기본문법--서브쿼리">SQL 기본문법 : 서브쿼리</h1>

<p>https://snowple.tistory.com/360</p>

<p><a href="https://inpa.tistory.com/entry/MYSQL-%F0%9F%93%9A-%EC%84%9C%EB%B8%8C%EC%BF%BC%EB%A6%AC-%EC%A0%95%EB%A6%AC">https://inpa.tistory.com/entry/MYSQL-📚-서브쿼리-정리</a></p>

<p>위 블로그를 보고 작성한 글입니다.</p>

<h1 id="서브쿼리란-subquery">[서브쿼리란? (Subquery)]</h1>

<p>하나의 SQL문 안에 포함되어있는 또 다른 SQL문</p>

<blockquote>
  <p>다른 쿼리 내부에 포함되어 있는 SELECT 문</p>
</blockquote>

<ul>
  <li>서브쿼리는 메인쿼리가 서브쿼리를 포함하는 종속적인 관계</li>
  <li>Join은 조인에 참여하는 모든 테이블이 대등한 관계에 있기 때문에 조인에 참여하는 모든 테이블의 컬럼을 어느 위치에서라도 자유롭게 사용할 수 있다.</li>
  <li>서브쿼리는 메인쿼리의 컬럼을 모두 사용할 수 있지만, 메인쿼리는 서브쿼리의 칼럼을 사용할 수 없다.</li>
  <li>서브쿼리는 서브쿼리 레벨과는 상관없이 항상 메인쿼리 레벨로 결과 집합이 생성된다.</li>
  <li>서브쿼리를 포함하고 있는 쿼리를 외부쿼리(outer query)라고 부르며, 서브쿼리는 내부쿼리(inner query)라고 부른다.</li>
  <li>java 객체지향의 상속과 똑같은 개념.</li>
  <li>상속당한 자식 객체는 부모 객체의 인스턴스를 사용할 수 있고, 부모는 자식객체의 인스턴스를 사용할 수 없다.</li>
</ul>

<h2 id="서브쿼리-장점">서브쿼리 장점</h2>

<ol>
  <li>서브쿼리는 쿼리를 구조화시키므로, 쿼리의 각 부분을 명확히 구분할 수 있게 해준다.</li>
  <li>서브쿼리는 복잡한 JOIN이나 UNION과 같은 동작을 수행할 수 있는 또 다른 방법을 제공한다.</li>
  <li>서브쿼리는 가독성을 높혀준다.</li>
</ol>

<h2 id="서브쿼리의-위치에-따른-명칭">서브쿼리의 위치에 따른 명칭</h2>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="n">col1</span><span class="p">,</span> <span class="p">(</span><span class="k">SELECT</span> <span class="p">...)</span> <span class="c1">-- 스칼라 서브쿼리</span>
<span class="k">FROM</span> <span class="p">(</span><span class="k">SELECT</span> <span class="p">...)</span> <span class="c1">-- 인라인 뷰</span>
<span class="k">WHERE</span> <span class="n">col</span> <span class="o">=</span> <span class="p">(</span><span class="k">SELECT</span> <span class="p">..)</span> <span class="c1">-- 일반 서브쿼리</span>
</code></pre></div></div>

<h3 id="--스칼라-서브쿼리">- 스칼라 서브쿼리</h3>

<p>-&gt; 하나의 컬럼처럼 사용 (표현 용도)</p>

<h3 id="--인라인-뷰">- 인라인 뷰</h3>

<p>-&gt; 하나의 테이블처럼 사용 (테이블 대체 용도)</p>

<h3 id="--일반-서브쿼리">- 일반 서브쿼리</h3>

<p>-&gt; 하나의 변수(상수)처럼 사용 (서브쿼리의 결과에 따라 달라지는 조건절)</p>

<h2 id="서브쿼리-실행-순서">서브쿼리 실행 순서</h2>

<ol>
  <li>서브쿼리 실행</li>
  <li>메인(부모)쿼리 실행</li>
</ol>

<h2 id="사용방법">사용방법</h2>

<ul>
  <li>주의할 점
    <ul>
      <li>서브쿼리를 괄호로 감싸서 사용한다.</li>
      <li>서브쿼리는 단일 행 또는 복수 행 비교 연산자와 함께 사용 가능</li>
      <li>서부쿼리에서는 ORDER BY를 사용하지 못한다.</li>
      <li>SELECT 문으로만 작성가능.</li>
      <li>괄호가 끝나고 끝에 ;(세미콜론)을 쓰지 않는다.</li>
    </ul>
  </li>
  <li>사용 가능한 곳
    <ul>
      <li>SELECT</li>
      <li>FROM</li>
      <li>WHERE</li>
      <li>HAVING</li>
      <li>ORDER BY</li>
      <li>INSERT 문의 VALUES</li>
      <li>UPDATE 문의 SET</li>
    </ul>
  </li>
</ul>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="o">*</span>
<span class="k">FROM</span> <span class="n">db_table</span>
<span class="k">WHERE</span> <span class="n">table_fk</span> <span class="k">IN</span> <span class="p">(</span> <span class="k">SELECT</span> <span class="n">table_fk</span> <span class="k">FROM</span> <span class="n">db_table_other</span> <span class="k">WHERE</span> <span class="p">...</span> <span class="p">)</span>
</code></pre></div></div>

<h1 id="서브쿼리의-종류">[서브쿼리의 종류]</h1>

<h2 id="단일행-서브쿼리-single-row-subquery">단일행 서브쿼리 (Single Row Subquery)</h2>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="o">*</span>
<span class="k">FROM</span> <span class="n">Player</span>
<span class="k">WHERE</span> <span class="n">Team_ID</span> <span class="o">=</span> <span class="p">(</span>
		<span class="k">SELECT</span> <span class="n">Team_ID</span>
		<span class="k">FROM</span> <span class="n">Player</span>
		<span class="k">WHERE</span> <span class="n">Player_name</span> <span class="o">=</span> <span class="nv">"yonglae"</span>
		<span class="p">)</span>
<span class="k">ORDER</span> <span class="k">BY</span> <span class="n">Team_name</span><span class="p">;</span>
</code></pre></div></div>

<h2 id="다중행-서브쿼리-multiple-row-subquery">다중행 서브쿼리 (Multiple Row Subquery)</h2>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="o">*</span>
<span class="k">FROM</span> <span class="n">Team</span>
<span class="k">WHERE</span> <span class="n">Team_ID</span> <span class="k">IN</span> <span class="p">(</span>
		<span class="k">SELECT</span> <span class="n">Team_ID</span>
		<span class="k">FROM</span> <span class="n">Player</span>
		<span class="k">WHERE</span> <span class="n">Player_name</span> <span class="o">=</span> <span class="nv">"yonglae"</span>
		<span class="p">)</span>
<span class="k">ORDER</span> <span class="k">BY</span> <span class="n">Team_name</span><span class="p">;</span>
</code></pre></div></div>

<h2 id="다중컬럼-서브쿼리-multi-column-subquery">다중컬럼 서브쿼리 (Multi Column Subquery)</h2>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="o">*</span>
<span class="k">FROM</span> <span class="n">Player</span>
<span class="k">WHERE</span> <span class="p">(</span> <span class="n">Team_ID</span><span class="p">,</span> <span class="n">Height</span><span class="p">)</span> <span class="k">IN</span> <span class="p">(</span>
		<span class="k">SELECT</span> <span class="n">Team_ID</span><span class="p">,</span> <span class="k">MIN</span><span class="p">(</span><span class="n">Height</span><span class="p">)</span>
		<span class="k">FROM</span> <span class="n">Player</span>
		<span class="k">GROUP</span> <span class="k">BY</span> <span class="n">Team_ID</span>
		<span class="p">)</span>
<span class="k">ORDER</span> <span class="k">BY</span> <span class="n">Team_ID</span><span class="p">,</span> <span class="n">Player_name</span><span class="p">;</span>
</code></pre></div></div>

<h1 id="위치에-따라-사용되는-서브쿼리">[위치에 따라 사용되는 서브쿼리]</h1>

<h2 id="select-절에서-사용-스칼라-서브쿼리">SELECT 절에서 사용 (스칼라 서브쿼리)</h2>

<ul>
  <li>다른 테이블에서 어떠한 값을 가져올때 쓰임</li>
  <li>하나의 레코드만 리턴가능, 두개 이상의 레코드는 리턴할 수 없다.</li>
  <li>일치하는 데이터가 없더라도 NULL 값을 리턴할 수 있다.</li>
</ul>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="n">Player_name</span><span class="p">,</span> <span class="n">Height</span><span class="p">,</span> <span class="p">(</span>
	<span class="k">SELECT</span> <span class="k">AVG</span><span class="p">(</span><span class="n">Height</span><span class="p">)</span>
	<span class="k">FROM</span> <span class="n">Player</span> <span class="n">p</span>
	<span class="k">WHERE</span> <span class="n">p</span><span class="p">.</span><span class="n">Team_ID</span> <span class="o">=</span> <span class="n">x</span><span class="p">.</span><span class="n">Team_ID</span> <span class="k">as</span> <span class="n">AVG_Height</span>
	<span class="p">)</span>
<span class="k">FROM</span> <span class="n">Player</span> <span class="n">x</span>
</code></pre></div></div>

<h2 id="from-절에서-사용-인라인-뷰">FROM 절에서 사용 (인라인 뷰)</h2>

<ul>
  <li>FROM 절에서 사용되는 서브쿼리를 인라인 뷰(inline View)라고 한다.</li>
  <li>FROM 절에는 테이블 명이 오도록 되어있다. 그런데 서브쿼리가 FROM절에 사용되면 뷰(View)처럼 결과가 동적으로 생성된 테이블로 사용할 수 있다. 임시적인 뷰이기 때문에 데이터베이스에 저장되지는 않는다.</li>
  <li>인라인 뷰로 동적으로 생성된 테이블이여서 인라인 뷰의 칼럼은 자유롭게 참조가 가능하다.</li>
  <li>서브쿼리가 FROM 절에 사용되는 경우 무조건 AS별칭을 지정해 주어야함.</li>
</ul>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="n">t</span><span class="p">.</span><span class="n">Team_name</span><span class="p">,</span> <span class="n">p</span><span class="p">.</span><span class="n">Player_name</span><span class="p">,</span> <span class="n">p</span><span class="p">.</span><span class="n">Height</span>
<span class="k">FROM</span> <span class="n">Player</span> <span class="n">t</span><span class="p">,(</span>
		<span class="k">SELECT</span> <span class="n">Team_ID</span><span class="p">,</span> <span class="n">Player_name</span><span class="p">,</span> <span class="n">Back_no</span>
		<span class="k">FROM</span> <span class="n">Player</span>
		<span class="k">WHERE</span> <span class="k">Position</span> <span class="o">=</span> <span class="s1">'MF'</span>
		<span class="p">)</span> <span class="n">p</span>
<span class="k">WHERE</span> <span class="n">p</span><span class="p">.</span><span class="n">Team_ID</span> <span class="o">=</span> <span class="n">t</span><span class="p">.</span><span class="n">Team_ID</span><span class="p">;</span>
</code></pre></div></div>

<h2 id="where-절에서-사용-중첩-서브쿼리">WHERE 절에서 사용 (중첩 서브쿼리)</h2>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="n">Player_name</span>
<span class="k">FROM</span> <span class="n">Player</span>
<span class="k">WHERE</span> <span class="n">Team_ID</span> <span class="k">IN</span> <span class="p">(</span>
		<span class="k">SELECT</span> <span class="n">Team_ID</span>
		<span class="k">FROM</span> <span class="n">Team</span>
		<span class="k">WHERE</span> <span class="n">Team_country</span> <span class="o">=</span> <span class="s1">'KOR'</span>
		<span class="p">)</span>
</code></pre></div></div>]]></content><author><name>김도연</name></author><category term="MySQL_study" /><category term="MySQL_study" /><category term="study" /><summary type="html"><![CDATA[SQL 기본문법 : 서브쿼리]]></summary></entry><entry><title type="html">[MySQL] SQL 기본문법 : 페이지네이션</title><link href="https://hidokim.github.io/mysql_study/study_MySQL_6/" rel="alternate" type="text/html" title="[MySQL] SQL 기본문법 : 페이지네이션" /><published>2025-09-26T00:00:00+09:00</published><updated>2025-09-26T00:00:00+09:00</updated><id>https://hidokim.github.io/mysql_study/study_MySQL_6</id><content type="html" xml:base="https://hidokim.github.io/mysql_study/study_MySQL_6/"><![CDATA[<h1 id="sql-기본문법--페이지네이션">SQL 기본문법 : 페이지네이션</h1>

<p><a href="https://velog.io/@minsangk/%EC%BB%A4%EC%84%9C-%EA%B8%B0%EB%B0%98-%ED%8E%98%EC%9D%B4%EC%A7%80%EB%84%A4%EC%9D%B4%EC%85%98-Cursor-based-Pagination-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0">커서-기반-페이지네이션-Cursor-based-Pagination-구현하기</a></p>

<p>위 블로그를 보고 작성한 글입니다.</p>

<h1 id="-페이지네이션이란">✅ 페이지네이션이란?</h1>

<ul>
  <li>서버에서 데이터를 가져올 때 모든 데이터를 한번에 가져올 수 없기 때문에 <strong>특정한 정렬 기준에 따라 + 지정된 갯수</strong>의 데이터를 가져오는 것이 필요하다. 이를 <em>페이지네이션</em> 이라고 한다.</li>
</ul>

<h2 id="1-오프셋-기반-페이지네이션">1. 오프셋 기반 페이지네이션</h2>

<ul>
  <li>DB의 offset쿼리를 사용하여 ‘페이지’ 단위로 구분하여 요청/응답하게 구현</li>
</ul>

<h2 id="2-커서-기반-페이지네이션">2. 커서 기반 페이지네이션</h2>

<ul>
  <li>클라이언트가 가져간 마지막 row(행)의 순서상 다음 row들을 n개 요청/응답하게 구현</li>
</ul>

<h3 id="-오프셋-기반-페이지네이션-단점">🔴 오프셋 기반 페이지네이션 단점</h3>

<ol>
  <li>
    <p>각각의 페이지를 요청하는 사이에 데이터의 변화가 있을 경우 중복 데이터 노출</p>
  </li>
  <li>
    <p>대부분의 RDBMS에서 OFFSET 쿼리의 퍼포먼스 이슈</p>
  </li>
</ol>

<ul>
  <li>
    <p>DB는 모든 정렬 기준(ORDER BY)에 대해 해당 row가 몇번째 순서를 갖는지 모른다. 따라서 offset 값을 지정하여 쿼리를 한다고 했을 때 임시로 해당 쿼리의 모든 값들을 전부 만들어놓은 후 지정된 갯수만 순회해 자르는 방식을 사용한다.</p>
  </li>
  <li>
    <p>offset이 작으면 문제 없지만 row가 아주 많은 경우 offset이 커질 수록 쿼리의 퍼포먼스는 비례해 떨어진다.</p>
  </li>
</ul>

<blockquote>
  <p>offset기반 페이지네이션은 원하는 데이터가 ‘몇 번째’에 있다는 데에 집중하고 있다.</p>
</blockquote>

<blockquote>
  <p>cursor기반 페이지네이션은 원하는 데이터가 ‘어떤 데이터의 다음’에 있다는 데에 집중하고 있다.</p>
</blockquote>

<h1 id="-커서-기반-페이지네이션">✅ 커서 기반 페이지네이션</h1>

<h2 id="1️⃣-케이스-1-id-desc-정렬-시">1️⃣ 케이스 1: id DESC 정렬 시</h2>

<h3 id="첫번째-리스트-출력">첫번째 리스트 출력</h3>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="n">id</span> <span class="k">FROM</span> <span class="s1">'products'</span> <span class="k">ORDER</span> <span class="k">BY</span> <span class="n">id</span> <span class="k">DESC</span> <span class="k">LIMIT</span> <span class="mi">5</span>
</code></pre></div></div>

<h3 id="결과">결과</h3>

<table>
  <thead>
    <tr>
      <th>id</th>
      <th>title</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>1000</td>
      <td>상품#1000</td>
    </tr>
    <tr>
      <td>999</td>
      <td>상품#999</td>
    </tr>
    <tr>
      <td>998</td>
      <td>상품#998</td>
    </tr>
    <tr>
      <td>997</td>
      <td>상품#997</td>
    </tr>
    <tr>
      <td>996</td>
      <td>상품#996</td>
    </tr>
  </tbody>
</table>

<h3 id="여기서-cursor는-products-테이블의-id-996">여기서 cursor는 products 테이블의 id (996)</h3>

<h3 id="다음-리스트-출력">다음 리스트 출력</h3>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="n">id</span><span class="p">,</span> <span class="n">title</span>
		<span class="k">FROM</span> <span class="s1">'products'</span>
		<span class="k">WHERE</span> <span class="n">id</span> <span class="o">&lt;</span> <span class="mi">996</span>
		<span class="k">ORDER</span> <span class="k">BY</span> <span class="n">id</span> <span class="k">DESC</span>
		<span class="k">LIMIT</span> <span class="mi">5</span>
</code></pre></div></div>

<h2 id="2️⃣-케이스-2-price-asc-정렬시">2️⃣ 케이스 2: price ASC 정렬시</h2>

<h3 id="첫번째-리스트-출력-1">첫번째 리스트 출력</h3>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="n">id</span><span class="p">,</span> <span class="n">title</span><span class="p">,</span> <span class="n">price</span>
		<span class="k">FROM</span> <span class="s1">'products'</span>
		<span class="k">ORDER</span> <span class="k">BY</span> <span class="n">price</span> <span class="k">ASC</span>
		<span class="k">LIMIT</span> <span class="mi">5</span>
</code></pre></div></div>

<h3 id="결과-1">결과</h3>

<table>
  <thead>
    <tr>
      <th>id</th>
      <th>title</th>
      <th>price</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>242</td>
      <td>상품#242</td>
      <td>5800</td>
    </tr>
    <tr>
      <td>335</td>
      <td>상품#335</td>
      <td>5900</td>
    </tr>
    <tr>
      <td>798</td>
      <td>상품#798</td>
      <td>9500</td>
    </tr>
    <tr>
      <td>957</td>
      <td>상품#957</td>
      <td>13200</td>
    </tr>
    <tr>
      <td>446</td>
      <td>상품#446</td>
      <td>14100</td>
    </tr>
  </tbody>
</table>

<h3 id="여기서-cursor는-products-테이블의-price">여기서 cursor는 products 테이블의 price</h3>

<h3 id="다음-리스트-출력-asc니까-부등호-방향-반대">다음 리스트 출력 (ASC니까 부등호 방향 반대)</h3>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="n">id</span><span class="p">,</span> <span class="n">title</span><span class="p">,</span> <span class="n">price</span>
		<span class="k">FROM</span> <span class="s1">'products'</span>
		<span class="k">WHERE</span> <span class="n">price</span> <span class="o">&gt;</span> <span class="mi">14100</span>
		<span class="k">ORDER</span> <span class="k">BY</span> <span class="n">price</span> <span class="k">ASC</span>
		<span class="k">LIMIT</span> <span class="mi">5</span>
</code></pre></div></div>

<h3 id="-문제점">🔴 문제점</h3>

<p>id는 고유값이라 겹칠 일이 없지만 가격은 겹칠 수 있음</p>

<p>→ 때문에 커서 기반 페이지네이션을 위해서는 반드시 정렬 기준이 되는 필드 중 (적어도 하나는) 고유값이어야 함.</p>

<p>→ ORDER BY절에 id 필드를 두번째 정렬 기준으로 추가해봄</p>

<h2 id="3️⃣-케이스-3-price-asc-id-asc-정렬-시">3️⃣ 케이스 3: price ASC, id ASC 정렬 시</h2>

<h3 id="첫번째-리스트-출력-2">첫번째 리스트 출력</h3>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="n">id</span><span class="p">,</span> <span class="k">FROM</span> <span class="s1">'products'</span> <span class="k">ORDER</span> <span class="k">BY</span> <span class="n">price</span> <span class="k">ASC</span><span class="p">,</span> <span class="n">id</span> <span class="k">ASC</span> <span class="k">LIMIT</span> <span class="mi">5</span>
</code></pre></div></div>

<h3 id="다음-리스트-출력-1">다음 리스트 출력</h3>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="n">id</span><span class="p">,</span> <span class="n">title</span><span class="p">,</span> <span class="n">price</span>
		<span class="k">FROM</span> <span class="s1">'products'</span>
		<span class="k">WHERE</span> <span class="p">(</span><span class="n">price</span> <span class="o">&gt;</span> <span class="mi">14100</span> <span class="k">OR</span> <span class="p">(</span><span class="n">price</span> <span class="o">=</span> <span class="mi">14100</span> <span class="k">AND</span> <span class="n">id</span> <span class="o">&gt;</span> <span class="mi">446</span><span class="p">))</span>
		<span class="k">ORDER</span> <span class="k">BY</span> <span class="n">price</span> <span class="k">ASC</span><span class="p">,</span> <span class="n">id</span> <span class="k">ASC</span>
		<span class="k">LIMIT</span> <span class="mi">5</span>
</code></pre></div></div>

<h3 id="-or절-사용의-문제점">🔴 OR절 사용의 문제점</h3>

<ol>
  <li>대부분의 RDBMS는 WHERE절에 OR-clause를 사용하면 인덱싱을 못함.</li>
  <li>클라이언트가 ORDER BY에 있는 모든 필드를 알아야함 + 매 요청시마다 이 값들을 전부 보내야 함</li>
</ol>

<h2 id="4️⃣-케이스-4-price-desc-id-desc-커스텀-cursor-생성">4️⃣ 케이스 4: price DESC, id DESC (커스텀 cursor 생성)</h2>

<h2 id="concat">CONCAT</h2>

<ul>
  <li>MySQL 내장함수</li>
  <li>문자열을 합친다. (숫자인 경우 문자열로 자동 변환)</li>
</ul>

<h2 id="lpad">LPAD</h2>

<ul>
  <li>MySQL 내장함수</li>
  <li>문자열/숫자를 지정된 길이의 문자열로 채움(왼쪽)</li>
</ul>

<h3 id="--첫번째-리스트-출력">- 첫번째 리스트 출력</h3>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="n">id</span><span class="p">,</span> <span class="n">title</span><span class="p">,</span> <span class="n">price</span><span class="p">,</span>
			<span class="n">CONCAT</span><span class="p">(</span><span class="n">LPAD</span><span class="p">(</span><span class="n">price</span><span class="p">,</span> <span class="mi">10</span><span class="p">,</span> <span class="s1">'0'</span><span class="p">),</span> <span class="n">LPAD</span><span class="p">(</span><span class="n">id</span><span class="p">,</span> <span class="mi">10</span> <span class="p">,</span> <span class="s1">'0'</span><span class="p">))</span>
			<span class="k">as</span> <span class="s1">'cursor'</span>
			<span class="k">FROM</span> <span class="s1">'products'</span>
			<span class="k">ORDER</span> <span class="k">BY</span> <span class="n">price</span> <span class="k">DESC</span><span class="p">,</span> <span class="n">id</span> <span class="k">DESC</span>
			<span class="k">LIMIT</span> <span class="mi">5</span><span class="p">;</span>
</code></pre></div></div>

<h3 id="--결과">- 결과</h3>

<table>
  <thead>
    <tr>
      <th>id</th>
      <th>title</th>
      <th>price</th>
      <th>cursor</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>446</td>
      <td>상품#446</td>
      <td>14100</td>
      <td>00000<strong>14100</strong>0000000<strong>446</strong></td>
    </tr>
    <tr>
      <td>957</td>
      <td>상품#957</td>
      <td>13200</td>
      <td>00000<strong>13200</strong>0000000<strong>957</strong></td>
    </tr>
    <tr>
      <td>798</td>
      <td>상품#798</td>
      <td>9500</td>
      <td>000000<strong>9500</strong>0000000<strong>798</strong></td>
    </tr>
    <tr>
      <td>335</td>
      <td>상품#335</td>
      <td>5900</td>
      <td>000000<strong>5900</strong>0000000<strong>335</strong></td>
    </tr>
    <tr>
      <td>242</td>
      <td>상품#242</td>
      <td>5800</td>
      <td>000000<strong>5800</strong>0000000<strong>242</strong></td>
    </tr>
  </tbody>
</table>

<ol>
  <li>숫자값인 데이터를 LPAD를 이용해 10자 길이의 고정 문자열로 만들고</li>
  <li>이를 CONCAT으로 붙인다.</li>
  <li>10자인 이유: price, id 필드가 10자를 넘어가지 않을 거라는 확신 때문 (늘려도 무방)</li>
</ol>

<h3 id="--다음-리스트-출력">- 다음 리스트 출력</h3>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="n">id</span><span class="p">,</span> <span class="n">title</span><span class="p">,</span> <span class="n">price</span><span class="p">,</span>
			<span class="n">CONCAT</span><span class="p">(</span><span class="n">LPAD</span><span class="p">(</span><span class="n">price</span><span class="p">,</span> <span class="mi">10</span><span class="p">,</span> <span class="s1">'0'</span><span class="p">),</span> <span class="n">LPAD</span><span class="p">(</span><span class="n">id</span><span class="p">,</span> <span class="mi">10</span><span class="p">,</span> <span class="s1">'0'</span><span class="p">))</span>
			<span class="k">as</span> <span class="s1">'cursor'</span>
			<span class="k">FROM</span> <span class="s1">'products'</span>
			<span class="k">HAVING</span> <span class="s1">'cursor'</span> <span class="o">&lt;</span> <span class="s1">'0000005800000000242'</span>
			<span class="k">ORDER</span> <span class="k">BY</span> <span class="n">price</span> <span class="k">DESC</span><span class="p">,</span> <span class="n">id</span> <span class="k">DESC</span>
			<span class="k">LIMIT</span> <span class="mi">5</span>
</code></pre></div></div>

<p>🔴 HAVING절을 사용하면 인덱싱에 문제가 생김.</p>

<h2 id="5️⃣-케이스-5-price-asc-id-asc-커스텀-cursor-생성">5️⃣ 케이스 5: price ASC, id ASC (커스텀 cursor 생성)</h2>

<p>ASC가 섞여있을 경우, 두번째 리스트 쿼리에서 부등호 방향만 바꾸면 됨.</p>

<p>하지만 생성하는 cursor값을 일관되게 만드는 것이 더 좋음.</p>

<p>→ ASC/DESC가 섞여 있을때 대응도 쉽고 쿼리 생성하는 코드를 자동화 할 수 있기 때문</p>

<h2 id="pow">POW</h2>

<ul>
  <li>MySQL 내장함수</li>
  <li>제곱연산</li>
</ul>

<h3 id="--첫번째-리스트-출력-1">- 첫번째 리스트 출력</h3>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="n">id</span><span class="p">,</span> <span class="n">title</span><span class="p">,</span> <span class="n">price</span>
			<span class="n">CONCAT</span><span class="p">(</span><span class="n">LPAD</span><span class="p">(</span><span class="n">POW</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="mi">10</span><span class="p">)</span> <span class="o">-</span> <span class="n">price</span><span class="p">,</span> <span class="mi">10</span><span class="p">,</span> <span class="s1">'0'</span><span class="p">),</span> <span class="n">LPAD</span><span class="p">(</span><span class="n">POW</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="mi">10</span><span class="p">)</span> <span class="o">-</span> <span class="n">id</span><span class="p">,</span> <span class="mi">10</span><span class="p">,</span> <span class="s1">'0'</span><span class="p">))</span>
			<span class="k">as</span> <span class="s1">'cursor'</span>
			<span class="k">FROM</span> <span class="s1">'products'</span>
			<span class="k">ORDER</span> <span class="k">BY</span> <span class="n">price</span> <span class="k">ASC</span><span class="p">,</span> <span class="n">id</span> <span class="k">ASC</span>
			<span class="k">LIMIT</span> <span class="mi">5</span><span class="p">;</span>
</code></pre></div></div>

<h3 id="--결과-1">- 결과</h3>

<table>
  <thead>
    <tr>
      <th>id</th>
      <th>title</th>
      <th>price</th>
      <th>cursor</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>242</td>
      <td>상품#242</td>
      <td>5800</td>
      <td>99999942009999999758</td>
    </tr>
    <tr>
      <td>335</td>
      <td>상품#335</td>
      <td>5900</td>
      <td>99999941009999999665</td>
    </tr>
    <tr>
      <td>798</td>
      <td>상품#798</td>
      <td>9500</td>
      <td>99999905009999999202</td>
    </tr>
    <tr>
      <td>957</td>
      <td>상품#957</td>
      <td>13200</td>
      <td>99999868009999999043</td>
    </tr>
    <tr>
      <td>446</td>
      <td>상품#446</td>
      <td>14100</td>
      <td>99999859009999999554</td>
    </tr>
  </tbody>
</table>

<p>price → POW(10, 10) - price</p>

<p>id → POW(10, 10) - id</p>

<p>10**10 = 10,000,000,000</p>

<p>가장 낮은 price 값을 가진 상품이 가장 높음 cursor를 가지게 됨.</p>

<h3 id="--다음-리스트-출력ascdesc와-무관하게-동일함">- 다음 리스트 출력(ASC/DESC와 무관하게 동일함)</h3>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="n">id</span><span class="p">,</span> <span class="n">title</span><span class="p">,</span> <span class="n">price</span><span class="p">,</span>
			<span class="n">CONCAT</span><span class="p">(</span><span class="n">LPAD</span><span class="p">(</span><span class="n">POW</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="mi">10</span><span class="p">)</span> <span class="o">-</span> <span class="n">price</span><span class="p">,</span> <span class="mi">10</span> <span class="p">,</span> <span class="s1">'0'</span><span class="p">,</span>
			<span class="n">LPAD</span><span class="p">(</span><span class="n">POW</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span><span class="mi">10</span><span class="p">)</span> <span class="o">-</span> <span class="n">id</span><span class="p">,</span> <span class="mi">10</span><span class="p">,</span> <span class="s1">'0'</span><span class="p">)</span>
			<span class="p">)</span> <span class="k">as</span> <span class="s1">'cursor'</span>
			<span class="k">FROM</span> <span class="s1">'products'</span>
			<span class="k">HAVING</span> <span class="s1">'cursor'</span> <span class="o">&lt;</span> <span class="s1">'99999859009999999554'</span>
			<span class="k">ORDER</span> <span class="k">BY</span> <span class="n">price</span> <span class="k">ASC</span><span class="p">,</span> <span class="n">id</span> <span class="k">ASC</span>
			<span class="k">LIMIT</span> <span class="mi">5</span><span class="p">;</span>
</code></pre></div></div>

<p>이 쿼리는 alias를 HAVING 절에서 조건으로 쓰는 경우다.</p>

<p>이는 후처리 단계에서 동작하므로 인덱스 활용도 어렵고, MySQL은 이때 filesort 같은 임시 정렬 작업을 많이 하게 되어 퍼포먼스가 저하된다.</p>

<ul>
  <li>쿼리의 정렬 조건(<strong><code class="language-plaintext highlighter-rouge">ORDER BY price ASC, id ASC</code></strong>)에 사용된 컬럼들이 함수(<strong><code class="language-plaintext highlighter-rouge">CONCAT</code></strong>, <strong><code class="language-plaintext highlighter-rouge">LPAD</code></strong>, <strong><code class="language-plaintext highlighter-rouge">POW</code></strong>) 연산 결과로 만들어진 복합 표현식(<strong><code class="language-plaintext highlighter-rouge">cursor</code></strong>)과 연관되어 있어 인덱스 직접 사용이 어렵다.</li>
  <li>특히 <strong><code class="language-plaintext highlighter-rouge">CONCAT(LPAD(POW(10, 10) - price, 10 , '0'), LPAD(POW(10,10) - id, 10, '0'))</code></strong>는 컬럼 자체가 아니라 계산된 결과값이기 때문에 인덱스 컬럼이 아니다.</li>
</ul>

<h2 id="-using-filesort">🔴 Using Filesort</h2>

<ul>
  <li>인덱스를 이용한 정렬이 불가능할 때 MySQL이 임시 공간을 사용해 데이터를 정렬하는 방식</li>
  <li>성능에 부정적인 영향을 미친다.</li>
  <li>filesort는 메모리 버퍼에 데이터가 적재되지 않으면 임시 디스크 파일을 만들고 외부 정렬을 수행하여 디스크 I/O가 증가하고 CPU와 메모리 사용량 또한 늘어나 쿼리 실행 속도가 느려진다.</li>
</ul>

<h2 id="-having-대신-where-쓰기">🧩 HAVING 대신 WHERE 쓰기</h2>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="o">*</span> <span class="k">FROM</span> <span class="p">(</span>
    <span class="k">SELECT</span> <span class="n">id</span><span class="p">,</span> <span class="n">title</span><span class="p">,</span> <span class="n">price</span><span class="p">,</span>
        <span class="n">CONCAT</span><span class="p">(</span><span class="n">LPAD</span><span class="p">(</span><span class="n">POW</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="mi">10</span><span class="p">)</span> <span class="o">-</span> <span class="n">price</span><span class="p">,</span> <span class="mi">10</span> <span class="p">,</span> <span class="s1">'0'</span><span class="p">),</span>
        <span class="n">LPAD</span><span class="p">(</span><span class="n">POW</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span><span class="mi">10</span><span class="p">)</span> <span class="o">-</span> <span class="n">id</span><span class="p">,</span> <span class="mi">10</span><span class="p">,</span> <span class="s1">'0'</span><span class="p">)</span>
        <span class="p">)</span> <span class="k">as</span> <span class="s1">'cursor'</span>
    <span class="k">FROM</span> <span class="s1">'products'</span>
<span class="p">)</span> <span class="k">AS</span> <span class="n">sub</span>
<span class="k">WHERE</span> <span class="s1">'cursor'</span> <span class="o">&lt;</span> <span class="s1">'99999859009999999554'</span>
<span class="k">ORDER</span> <span class="k">BY</span> <span class="n">price</span> <span class="k">ASC</span><span class="p">,</span> <span class="n">id</span> <span class="k">ASC</span>
<span class="k">LIMIT</span> <span class="mi">5</span><span class="p">;</span>
</code></pre></div></div>

<p>WHERE 절로 바꾸면 alias를 직접 쓸 수 없으니 서브쿼리로 감싸서 alias를 생성한다.</p>

<p>외부 쿼리에서 WHERE로 필터링하는 방법을 쓰는 것이 일반적이며, 이 방법이 인덱스 활용과 쿼리 성능 개선에 도움된다.</p>]]></content><author><name>김도연</name></author><category term="MySQL_study" /><category term="MySQL_study" /><category term="study" /><summary type="html"><![CDATA[SQL 기본문법 : 페이지네이션]]></summary></entry><entry><title type="html">[MySQL] SQL 기본문법 : JOIN</title><link href="https://hidokim.github.io/mysql_study/study_MySQL_3/" rel="alternate" type="text/html" title="[MySQL] SQL 기본문법 : JOIN" /><published>2025-09-25T00:00:00+09:00</published><updated>2025-09-25T00:00:00+09:00</updated><id>https://hidokim.github.io/mysql_study/study_MySQL_3</id><content type="html" xml:base="https://hidokim.github.io/mysql_study/study_MySQL_3/"><![CDATA[<h1 id="sql-기본문법--join">SQL 기본문법 : JOIN</h1>

<p><a href="https://hongong.hanbit.co.kr/sql-%EA%B8%B0%EB%B3%B8-%EB%AC%B8%EB%B2%95-joininner-outer-cross-self-join/">sql-기본-문법</a></p>

<p><a href="https://velog.io/@wijoonwu/JOIN">JOIN</a></p>

<p><a href="https://inpa.tistory.com/entry/MYSQL-%F0%9F%93%9A-JOIN-%EC%A1%B0%EC%9D%B8-%EA%B7%B8%EB%A6%BC%EC%9C%BC%EB%A1%9C-%EC%95%8C%EA%B8%B0%EC%89%BD%EA%B2%8C-%EC%A0%95%EB%A6%AC">MYSQL-📚-JOIN-조인-그림으로-알기쉽게-정리</a></p>

<p>위 블로그를 보고 작성한 글입니다.</p>

<p>첨부한 이미지는 PPT로 직접 만들거나 Gemini를 이용해 만든 이미지 입니다.</p>

<h1 id="join-이란">JOIN 이란?</h1>

<ul>
  <li>두개의 테이블은 서로 묶어서 하나의 결과를 만들어 내는 것</li>
  <li>JOIN을 이용하면 두개의 테이블을 엮어서 원하는 데이터를 추출할 수 있음</li>
  <li>두 테이블의 조인을 위해서는 기본키와 외래키 관계로 맺어져야함
→ 일대다 관계</li>
</ul>

<h3 id="사용-예시">사용 예시</h3>

<p>인스타그램 댓글창처럼 유저의 아이디와 댓글의 내용을 동시에 보여줄때</p>

<ul>
  <li>서로다른 각각의 테이블(유저 아이디, 유저 댓글) 속 데이터를 동시에 보여주려 할때 사용하는 SQL</li>
</ul>

<p>→ INNER JOIN으로 가능</p>

<h2 id="join의-종류">JOIN의 종류</h2>

<h3 id="inner-join내부-조인">INNER JOIN(내부 조인)</h3>

<ul>
  <li>두 테이블을 조인할 때, 두 테이블에 모두 지정한 열의 데이터가 있어야 함.</li>
  <li>그냥 join 이라고 부르면 내부 조인임.</li>
  <li>
    <p>“,” 로 두 테이블은 이어주면 join임.</p>
  </li>
  <li>조인하는 테이블의 ON 절의 조건이 일치하는 결과만 출력</li>
  <li>표준 SQL과는 달리 MySQL에서는 <code class="language-plaintext highlighter-rouge">JOIN, INNER JOIN, CROSS JOIN</code>이 모두 같은 의미로 사용된다.</li>
  <li>inner join은 어느 테이블에서 기준으로 조인하든 조인 관계에 부합되는 레코드를 모두 가지게 된다. 그리고 조인에 부합되지 않는 레코드는 모두 삭제된다.</li>
</ul>

<h3 id="outer-join외부-조인">OUTER JOIN(외부 조인)</h3>

<ul>
  <li>두 테이블을 조인할 때, 1개의 테이블에만 데이터가 있어도 결과가 나온다.</li>
</ul>

<h3 id="cross-join상호-조인">CROSS JOIN(상호 조인)</h3>

<ul>
  <li>한쪽 테이블의 모든행과 다른쪽 테이블의 모든 행을 조인하는 기능</li>
  <li>카티션 곱(CARTESIAN PRODUCT)라고도 함</li>
</ul>

<h3 id="self-join자체-조인">SELF JOIN(자체 조인)</h3>

<ul>
  <li>자신이 자신과 조인, 1개의 테이블을 사용함.</li>
  <li>별도의 문법이 있는 것은 아니고 1개로 조인하면 자체 조인이 됨.</li>
  <li>예: 모든 사원에 대해 사원의 이름과 직속 상사의 이름을 검색
    <ul>
      <li>EMPNAME테이블에서 MANAGER의 번호와 EMPNO의 번호가 같으면 직속 상관 관계</li>
    </ul>
  </li>
</ul>

<h2 id="inner-join내부조인">INNER JOIN(내부조인)</h2>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="o">&lt;</span><span class="err">열</span> <span class="err">목록</span><span class="o">&gt;</span>
<span class="k">FROM</span> <span class="o">&lt;</span><span class="err">첫</span> <span class="err">번째</span> <span class="err">테이블</span><span class="o">&gt;</span>
		<span class="k">INNER</span> <span class="k">JOIN</span> <span class="o">&lt;</span><span class="err">두</span> <span class="err">번째</span> <span class="err">테이블</span><span class="o">&gt;</span>
		<span class="k">ON</span> <span class="o">&lt;</span><span class="err">조인</span> <span class="err">조건</span><span class="o">&gt;</span>
<span class="p">[</span><span class="k">WHERE</span> <span class="err">검색</span> <span class="err">조건</span><span class="p">]</span>
</code></pre></div></div>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="o">&lt;</span><span class="err">열</span> <span class="err">목록</span><span class="o">&gt;</span>
<span class="k">FROM</span> <span class="o">&lt;</span><span class="err">첫</span> <span class="err">번째</span> <span class="err">테이블</span><span class="o">&gt;</span>
		<span class="k">JOIN</span> <span class="o">&lt;</span><span class="err">두</span> <span class="err">번째</span> <span class="err">테이블</span><span class="o">&gt;</span>
		<span class="k">ON</span> <span class="o">&lt;</span><span class="err">조인</span> <span class="err">조건</span><span class="o">&gt;</span>
<span class="p">[</span><span class="k">WHERE</span> <span class="err">검색</span> <span class="err">조건</span><span class="p">]</span>
</code></pre></div></div>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="o">&lt;</span><span class="err">열</span> <span class="err">목록</span><span class="o">&gt;</span>
<span class="k">FROM</span> <span class="o">&lt;</span><span class="err">첫</span> <span class="err">번째</span> <span class="err">테이블</span><span class="o">&gt;</span><span class="p">,</span> <span class="o">&lt;</span><span class="err">두</span> <span class="err">번째</span> <span class="err">테이블</span><span class="o">&gt;</span>
		<span class="k">ON</span> <span class="o">&lt;</span><span class="err">조인</span> <span class="err">조건</span><span class="o">&gt;</span>
<span class="p">[</span><span class="k">WHERE</span> <span class="err">검색</span> <span class="err">조건</span><span class="p">]</span>
</code></pre></div></div>

<p><img src="/assets/images/innerJoin.png" style="width:400px; height:400px;" /></p>

<table>
  <thead>
    <tr>
      <th>users</th>
      <th> </th>
      <th> </th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>id</td>
      <td>nickname</td>
      <td>email</td>
    </tr>
    <tr>
      <td>1</td>
      <td>mingming</td>
      <td>ming01@naver.com</td>
    </tr>
    <tr>
      <td>2</td>
      <td>kim</td>
      <td>kim02@gmail.com</td>
    </tr>
    <tr>
      <td>3</td>
      <td>cutelee</td>
      <td>leesong03@naver.com</td>
    </tr>
  </tbody>
</table>

<table>
  <thead>
    <tr>
      <th>comments</th>
      <th> </th>
      <th> </th>
      <th> </th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>id</td>
      <td>body</td>
      <td>user_id</td>
      <td>photo_id</td>
    </tr>
    <tr>
      <td>1</td>
      <td>neow</td>
      <td>1</td>
      <td>1</td>
    </tr>
    <tr>
      <td>2</td>
      <td>냐옹</td>
      <td>2</td>
      <td>1</td>
    </tr>
    <tr>
      <td>3</td>
      <td>멍</td>
      <td>3</td>
      <td>2</td>
    </tr>
  </tbody>
</table>

<p>위와 같은 테이블이 있을때의 <code class="language-plaintext highlighter-rouge">INNER JOIN</code></p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span>
  <span class="n">comments</span><span class="p">.</span><span class="n">body</span><span class="p">,</span>
  <span class="n">users</span><span class="p">.</span><span class="n">nickname</span>
<span class="k">FROM</span>
  <span class="n">comments</span>
<span class="k">JOIN</span> <span class="n">users</span> <span class="k">ON</span>
  <span class="n">users</span><span class="p">.</span><span class="n">id</span> <span class="o">=</span> <span class="n">comments</span><span class="p">.</span><span class="n">user_id</span>
<span class="k">WHERE</span>
  <span class="n">comments</span><span class="p">.</span><span class="n">photo_id</span> <span class="o">=</span> <span class="mi">1</span>
<span class="p">;</span>
</code></pre></div></div>

<h2 id="outer-join외부조인">OUTER JOIN(외부조인)</h2>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="o">&lt;</span><span class="err">열</span> <span class="err">목록</span><span class="o">&gt;</span>
<span class="k">FROM</span> <span class="o">&lt;</span><span class="err">첫</span> <span class="err">번째</span> <span class="err">테이블</span><span class="p">(</span><span class="k">LEFT</span> <span class="err">테이블</span><span class="p">)</span><span class="o">&gt;</span>
		<span class="o">&lt;</span><span class="k">LEFT</span> <span class="o">|</span> <span class="k">RIGHT</span> <span class="o">|</span> <span class="k">FULL</span><span class="o">&gt;</span> <span class="k">OUTER</span> <span class="k">JOIN</span> <span class="o">&lt;</span><span class="err">두</span> <span class="err">번째</span> <span class="err">테이블</span><span class="p">(</span><span class="k">RIGHT</span> <span class="err">테이블</span><span class="p">)</span><span class="o">&gt;</span>
		<span class="k">ON</span> <span class="o">&lt;</span><span class="err">조인</span> <span class="err">조건</span><span class="o">&gt;</span>
<span class="p">[</span><span class="k">WHERE</span> <span class="err">검색</span> <span class="err">조건</span><span class="p">]</span>
</code></pre></div></div>

<h3 id="outer-join의-종류">OUTER JOIN의 종류</h3>

<ul>
  <li>LEFT OUTER JOIN : 왼쪽 테이블의 모든 값이 출력되는 조인 (가장 많이 사용됨)
    <ul>
      <li>두 테이블이 있을 경우 첫번째 테이블을 기준으로 두번째 테이블을 조합하는 join</li>
      <li>inner join과 다르게 조인하는 테이블의 순서가 중요함 (조인 순서에 따라 결과 테이블에 조회되는 행의 개수며 구성 등이 달라질 수 있음)</li>
      <li>따라서 가장 첫번째 테이블로 SELECT문에 가장 많은 열을 가져와야하는 테이블을 우선으로 적는다.</li>
      <li>조인을 여러번할때, LEFT JOIN으로 시작했으면 나머지 조인도 LEFT JOIN을 이어나간다. (갑자기 INNER JOIN등 다른 join을 쓰지 않는다.)</li>
    </ul>
  </li>
  <li>RIGHT OUTER JOIN : 오른쪽 테이블의 모든 값이 출력되는 조인</li>
  <li>FULL OUTER JOIN : 왼쪽 외부 조인과 오른쪽 외부 조인이 합쳐진 것 (성능상 거의 사용하지 않음)</li>
</ul>

<h3 id="left-outer-join">LEFT OUTER JOIN</h3>

<p><img src="/assets/images/leftOuterJoin.png" style="width:400px; height:400px;" /></p>
<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="o">*</span> <span class="k">FROM</span> <span class="n">TableA</span> <span class="n">a</span> <span class="k">LEFT</span> <span class="k">OUTER</span> <span class="k">JOIN</span> <span class="n">TableB</span> <span class="n">b</span> <span class="k">ON</span> <span class="n">a</span><span class="p">.</span><span class="k">KEY</span> <span class="o">=</span> <span class="n">b</span><span class="p">.</span><span class="k">KEY</span>
</code></pre></div></div>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="o">*</span> <span class="k">FROM</span> <span class="n">TableA</span> <span class="n">a</span> <span class="k">LEFT</span> <span class="k">OUTER</span> <span class="k">JOIN</span> <span class="n">TableB</span> <span class="n">b</span> <span class="k">ON</span> <span class="n">a</span><span class="p">.</span><span class="k">KEY</span> <span class="o">=</span> <span class="n">b</span><span class="p">.</span><span class="k">KEY</span> <span class="k">WHERE</span> <span class="n">b</span><span class="p">.</span><span class="k">KEY</span> <span class="k">IS</span> <span class="k">NULL</span>
</code></pre></div></div>

<h3 id="full-outer-join">FULL OUTER JOIN</h3>

<p><img src="/assets/images/fullOuterJoin.png" style="width:400px; height:400px;" /></p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="o">*</span> <span class="k">FROM</span> <span class="n">TableA</span> <span class="n">a</span> <span class="k">FULL</span> <span class="k">OUTER</span> <span class="k">JOIN</span> <span class="n">TableB</span> <span class="n">b</span> <span class="k">ON</span> <span class="n">a</span><span class="p">.</span><span class="k">KEY</span> <span class="o">=</span> <span class="n">b</span><span class="p">.</span><span class="k">KEY</span>
</code></pre></div></div>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="o">*</span> <span class="k">FROM</span> <span class="n">TableA</span> <span class="n">a</span> <span class="k">FULL</span> <span class="k">OUTER</span> <span class="k">JOIN</span> <span class="n">TableB</span> <span class="n">b</span> <span class="k">ON</span> <span class="n">a</span><span class="p">.</span><span class="k">KEY</span> <span class="o">=</span> <span class="n">b</span><span class="p">.</span><span class="k">KEY</span> <span class="k">WHERE</span> <span class="n">a</span><span class="p">.</span><span class="k">KEY</span> <span class="k">IS</span> <span class="k">NULL</span> <span class="k">OR</span> <span class="n">b</span><span class="p">.</span><span class="k">KEY</span> <span class="k">IS</span> <span class="k">NULL</span>
</code></pre></div></div>

<h3 id="right-outer-join">RIGHT OUTER JOIN</h3>

<p><img src="/assets/images/rightOuterJoin.png" style="width:400px; height:400px;" /></p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="o">*</span> <span class="k">FROM</span> <span class="n">TableA</span> <span class="n">a</span> <span class="k">RIGHT</span> <span class="k">OUTER</span> <span class="k">JOIN</span> <span class="n">TableB</span> <span class="n">b</span> <span class="k">ON</span> <span class="n">a</span><span class="p">.</span><span class="k">KEY</span> <span class="o">=</span> <span class="n">b</span><span class="p">.</span><span class="k">KEY</span>
</code></pre></div></div>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="o">*</span> <span class="k">FROM</span> <span class="n">TableA</span> <span class="n">a</span> <span class="k">RIGHT</span> <span class="k">OUTER</span> <span class="k">JOIN</span> <span class="n">TableB</span> <span class="n">b</span> <span class="k">ON</span> <span class="n">a</span><span class="p">.</span><span class="k">KEY</span> <span class="o">=</span> <span class="n">b</span><span class="p">.</span><span class="k">KEY</span> <span class="k">WHERE</span> <span class="n">a</span><span class="p">.</span><span class="k">KEY</span> <span class="k">IS</span> <span class="k">NULL</span>
</code></pre></div></div>

<h2 id="cross-join상호조인">CROSS JOIN(상호조인)</h2>

<p><img src="/assets/images/crossJoin.png" style="width:400px;" /></p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="o">*</span>
<span class="k">FROM</span> <span class="o">&lt;</span><span class="err">첫</span> <span class="err">번째</span> <span class="err">테이블</span><span class="o">&gt;</span>
		<span class="k">CROSS</span> <span class="k">JOIN</span> <span class="o">&lt;</span><span class="err">두</span> <span class="err">번째</span> <span class="err">테이블</span><span class="o">&gt;</span>
</code></pre></div></div>

<h2 id="self-join자체조인">SELF JOIN(자체조인)</h2>

<p><img src="/assets/images/selfJoin.png" style="width:400px; height:400px;" /></p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="o">&lt;</span><span class="err">열</span> <span class="err">목록</span><span class="o">&gt;</span>
<span class="k">FROM</span> <span class="o">&lt;</span><span class="err">테이블</span><span class="o">&gt;</span> <span class="err">별칭</span><span class="n">A</span>
		<span class="k">INNER</span> <span class="k">JOIN</span> <span class="o">&lt;</span><span class="err">테이블</span><span class="o">&gt;</span> <span class="err">별칭</span><span class="n">B</span>
<span class="p">[</span><span class="k">WHERE</span> <span class="err">검색</span> <span class="err">조건</span><span class="p">]</span>
</code></pre></div></div>

<hr />]]></content><author><name>김도연</name></author><category term="MySQL_study" /><category term="MySQL_study" /><category term="study" /><summary type="html"><![CDATA[SQL 기본문법 : JOIN]]></summary></entry><entry><title type="html">[MySQL] SQL 기본문법 : UNION, EXCLUSIVE, Distinct</title><link href="https://hidokim.github.io/mysql_study/study_MySQL_4/" rel="alternate" type="text/html" title="[MySQL] SQL 기본문법 : UNION, EXCLUSIVE, Distinct" /><published>2025-09-25T00:00:00+09:00</published><updated>2025-09-25T00:00:00+09:00</updated><id>https://hidokim.github.io/mysql_study/study_MySQL_4</id><content type="html" xml:base="https://hidokim.github.io/mysql_study/study_MySQL_4/"><![CDATA[<h1 id="sql-기본문법--union-exclusive-distinct">SQL 기본문법 : UNION, EXCLUSIVE, Distinct</h1>

<p><a href="https://hongong.hanbit.co.kr/sql-%EA%B8%B0%EB%B3%B8-%EB%AC%B8%EB%B2%95-joininner-outer-cross-self-join/">sql-기본-문법</a></p>

<p><a href="https://velog.io/@wijoonwu/JOIN">JOIN</a></p>

<p><a href="https://inpa.tistory.com/entry/MYSQL-%F0%9F%93%9A-JOIN-%EC%A1%B0%EC%9D%B8-%EA%B7%B8%EB%A6%BC%EC%9C%BC%EB%A1%9C-%EC%95%8C%EA%B8%B0%EC%89%BD%EA%B2%8C-%EC%A0%95%EB%A6%AC">MYSQL-📚-JOIN-조인-그림으로-알기쉽게-정리</a></p>

<p>위 블로그를 보고 작성한 글입니다.</p>

<h2 id="union">UNION</h2>

<ul>
  <li>여러개의 SELECT 문의 결과를 하나의 테이블이나 결과 집합으로 표현할 때 사용</li>
  <li>각각의 SELECT문으로 선택된 필드의 개수와 타입은 모두 같아야하며, 필드의 순서도 같아야한다.</li>
  <li>기본 집합 쿼리에는 (DISTINCT) 중복제거가 자동 포함되어 있다.</li>
</ul>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="err">필드이름</span> <span class="k">FROM</span> <span class="err">테이블이름</span>
<span class="k">UNION</span>
<span class="k">SELECT</span> <span class="err">필드이름</span> <span class="k">FROM</span> <span class="err">테이블이름</span>
</code></pre></div></div>

<h3 id="union-all">UNION ALL</h3>

<ul>
  <li>중복되는 레코드까지 모두 출력하고 싶을때 사용</li>
</ul>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="err">필드이름</span> <span class="k">FROM</span> <span class="err">테이블이름</span>
<span class="k">UNION</span> <span class="k">ALL</span>
<span class="k">SELECT</span> <span class="err">필드이름</span> <span class="k">FROM</span> <span class="err">테이블이름</span>
</code></pre></div></div>

<h2 id="exclusive-left-join">EXCLUSIVE LEFT JOIN</h2>

<ul>
  <li>어느 특정 테이블에 있는 레코드만 가져오는 것</li>
  <li>만약 테이블 두개를 JOIN 한다면 둘중 하나의 테이블에만 있는 데이터를 가져온다.</li>
  <li>별도의 EXCLUSIVE JOIN 함수가 있는 건 아니고 기존 LEFT JOIN과 Where절의 조건을 함께 사용하여 만든다.</li>
</ul>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="o">*</span>
<span class="k">FROM</span> <span class="n">tableA</span> <span class="n">A</span> <span class="k">LEFT</span> <span class="k">JOIN</span> <span class="n">tableB</span> <span class="n">B</span>
<span class="k">ON</span> <span class="n">A</span><span class="p">.</span><span class="n">ID_SEQ</span> <span class="o">=</span> <span class="n">B</span><span class="p">.</span><span class="n">ID_SEQ</span>
<span class="k">WHERE</span> <span class="n">B</span><span class="p">.</span><span class="n">ID_SEQ</span> <span class="k">IS</span> <span class="k">NULL</span> <span class="c1">--- 조인한 tableB의 값으로 null만 출력해라.</span>
</code></pre></div></div>

<h2 id="distinct-사용">Distinct 사용</h2>

<ul>
  <li>mysql에서 지원하는 distinct 문법을 사용</li>
  <li>중복 되는 데이터가 있을 때 하나만 카운트 하도록 함</li>
  <li>매우 쉬운 방법, 하지만 레코드 수가 많은 경우 성능이 느림</li>
</ul>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="k">DISTINCT</span> <span class="n">person</span><span class="p">.</span><span class="n">id</span><span class="p">,</span> <span class="n">person</span><span class="p">.</span><span class="n">name</span><span class="p">,</span> <span class="n">job</span><span class="p">.</span><span class="n">job_name</span>
<span class="k">FROM</span> <span class="n">person</span> <span class="k">INNER</span> <span class="k">JOIN</span> <span class="n">job</span>
<span class="k">ON</span> <span class="n">person</span><span class="p">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">job</span><span class="p">.</span><span class="n">person_name</span><span class="p">;</span>
</code></pre></div></div>

<h3 id="join-중복제거">JOIN 중복제거</h3>

<p>성능을 위해서는 JOIN 전에 중복을 제거하는 작업을 해줘야 함.</p>

<ul>
  <li>JOIN 전에 중복 제거는 조인할 테이블에 서브쿼리의 inline view를 사용해 distinct하고 조인하면 된다.</li>
</ul>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="n">A</span><span class="p">.</span><span class="n">name</span><span class="p">,</span> <span class="n">A</span><span class="p">.</span><span class="n">countryCode</span>
<span class="k">FROM</span> <span class="n">city</span> <span class="n">A</span>
<span class="k">LEFT</span> <span class="k">JOIN</span> <span class="p">(</span> <span class="k">select</span> <span class="k">distinct</span> <span class="n">name</span><span class="p">,</span> <span class="n">Code</span> <span class="n">form</span> <span class="n">country</span> <span class="p">)</span> <span class="k">as</span> <span class="n">B</span>
<span class="c1">-- 조인할 테이블에 먼저 distinct로 중복제거 후 select 문을 서브쿼리로 불러와</span>
<span class="c1">-- 임시 테이블로 만든뒤 조인</span>
<span class="k">on</span> <span class="n">A</span><span class="p">.</span><span class="n">countryCode</span> <span class="o">=</span> <span class="n">B</span><span class="p">.</span><span class="n">Code</span>
</code></pre></div></div>]]></content><author><name>김도연</name></author><category term="MySQL_study" /><category term="MySQL_study" /><category term="study" /><summary type="html"><![CDATA[SQL 기본문법 : UNION, EXCLUSIVE, Distinct]]></summary></entry><entry><title type="html">[MySQL] node.js + MySQL 자리 표시자 (Placeholder)</title><link href="https://hidokim.github.io/mysql_study/study_MySQL_2/" rel="alternate" type="text/html" title="[MySQL] node.js + MySQL 자리 표시자 (Placeholder)" /><published>2025-09-24T00:00:00+09:00</published><updated>2025-09-24T00:00:00+09:00</updated><id>https://hidokim.github.io/mysql_study/study_MySQL_2</id><content type="html" xml:base="https://hidokim.github.io/mysql_study/study_MySQL_2/"><![CDATA[<h1 id="자리-표시자-placeholder">자리 표시자 (Placeholder)</h1>

<h2 id="자리-표시자란">자리 표시자란?</h2>

<ul>
  <li>바인드 변수라고도 불리며, <code class="language-plaintext highlighter-rouge">?</code>로 표기한다.</li>
  <li>자리 표시자는 실제 값이 실행 시점에 동적으로 바인딩된다. (쿼리 내에서 나중에 입력될 값을 대체)
    <ul>
      <li>쿼리가 처음 만들어질 때는 고정된 값 없이 구조만 정의하고, 실행 시 실제 값은 별도로 전달되어 안전하고 동적인 쿼리 실행이 가능하도록 한다.</li>
    </ul>
  </li>
  <li>보통 Node.js, Python 등에서 DB 라이브러리 함수 호출 시 <strong><code class="language-plaintext highlighter-rouge">query(sql, [param1, param2, ...])</code></strong> 같은 방식으로 값을 배열 형태로 넘긴다.</li>
  <li>자리 표시자는 “빈 자리”나 “값 들어갈 위치”를 뜻하고,</li>
  <li>바인드 변수는 그 자리에 실제로 들어가는 “변수” 또는 “값”을 의미</li>
</ul>

<blockquote>
  <p>실제로 SQL과 DBMS에서는 구문 최적화와 성능향상을 위해 자리 표시자를 사용해 쿼리를 만든 후, 바인드 변수로 실제 값을 넣는 방식으로 동작한다.</p>
</blockquote>

<h2 id="사용이유">사용이유</h2>

<ul>
  <li>쿼리와 값이 분리되어 SQL 인젝션 공격 위험을 크게 줄이고 실행 효율도 높일 수 있다.</li>
  <li>SQL 실행 계획을 재활용할 수 있어 DB의 파싱 비용과 부하를 줄일 수 있다.</li>
</ul>

<h2 id="사용예시">사용예시</h2>

<ul>
  <li><strong><code class="language-plaintext highlighter-rouge">WHERE m.id = ?</code></strong> 구문은 실행할 때 <strong><code class="language-plaintext highlighter-rouge">?</code></strong> 자리에 특정 회원 ID가 들어가서 해당 회원만 조회하는 역할을 함.</li>
</ul>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span>
    <span class="n">m</span><span class="p">.</span><span class="n">nick_name</span><span class="p">,</span>
    <span class="n">m</span><span class="p">.</span><span class="n">email</span><span class="p">,</span>
    <span class="n">m</span><span class="p">.</span><span class="n">point</span><span class="p">,</span>
    <span class="n">p</span><span class="p">.</span><span class="n">phone_number</span><span class="p">,</span>
    <span class="n">p</span><span class="p">.</span><span class="n">is_certified</span>
<span class="k">FROM</span> <span class="n">member</span> <span class="n">m</span>
<span class="k">LEFT</span> <span class="k">JOIN</span> <span class="n">phone</span> <span class="n">p</span> <span class="k">ON</span> <span class="n">p</span><span class="p">.</span><span class="n">member_id</span> <span class="o">=</span> <span class="n">m</span><span class="p">.</span><span class="n">id</span> <span class="k">AND</span> <span class="n">p</span><span class="p">.</span><span class="n">is_deleted</span> <span class="o">=</span> <span class="mi">0</span>
<span class="k">WHERE</span> <span class="n">m</span><span class="p">.</span><span class="n">id</span> <span class="o">=</span> <span class="o">?</span><span class="p">;</span>
</code></pre></div></div>]]></content><author><name>김도연</name></author><category term="MySQL_study" /><category term="MySQL_study" /><category term="study" /><summary type="html"><![CDATA[자리 표시자 (Placeholder)]]></summary></entry><entry><title type="html">[MySQL] SQL 기본 문법: SELECT, WHERE, ORDER BY 등</title><link href="https://hidokim.github.io/mysql_study/study_MySQL_1/" rel="alternate" type="text/html" title="[MySQL] SQL 기본 문법: SELECT, WHERE, ORDER BY 등" /><published>2025-09-23T00:00:00+09:00</published><updated>2025-09-23T00:00:00+09:00</updated><id>https://hidokim.github.io/mysql_study/study_MySQL_1</id><content type="html" xml:base="https://hidokim.github.io/mysql_study/study_MySQL_1/"><![CDATA[<h1 id="sql-기본-문법-select-where-order-by-등">SQL 기본 문법: SELECT, WHERE, ORDER BY 등</h1>

<p><a href="https://rachel0115.tistory.com/entry/SQL-%EA%B8%B0%EB%B3%B8-%EB%AC%B8%EB%B2%95-%EC%A0%95%EB%A6%AC-SELECT-%EC%A0%88">SQL-기본-문법-정리-SELECT-절</a></p>

<p>위 블로그를 보고 작성한 글입니다.</p>

<h1 id="1-select-문의-기본-형식">1. SELECT 문의 기본 형식</h1>

<div class="language-jsx highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">SELECT</span> <span class="nx">열_이름</span>
		<span class="nx">FROM</span> <span class="nx">테이블_이름</span>
		<span class="nx">WHERE</span> <span class="nx">조건식</span>
		<span class="nx">GROUP</span> <span class="nx">BY</span> <span class="nx">열_이름</span>
		<span class="nx">HAVING</span> <span class="nx">조건식</span>
		<span class="nx">ORDER</span> <span class="nx">BY</span> <span class="nx">열_이름</span>
		<span class="nx">LIMIT</span> <span class="nx">숫자</span>
</code></pre></div></div>

<h1 id="2-sql-기본-문법">2. SQL 기본 문법</h1>

<h2 id="use---스키마db-선택">USE - 스키마(DB) 선택</h2>

<div class="language-jsx highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">USE</span> <span class="nx">user_db</span><span class="p">;</span>
</code></pre></div></div>

<ul>
  <li>SQL을 사용할 스키마(DB)를 지정</li>
</ul>

<h2 id="select---조회할-데이터컬럼-지정">SELECT - 조회할 데이터(컬럼) 지정</h2>

<div class="language-jsx highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">--</span> <span class="nx">SELECT</span> <span class="dl">'</span><span class="s1">컬럼명</span><span class="dl">'</span> <span class="nx">FROM</span> <span class="dl">'</span><span class="s1">테이블명</span><span class="dl">'</span>
<span class="nx">SELECT</span> <span class="nx">user_id</span><span class="p">,</span> <span class="nx">name</span> <span class="nx">FROM</span> <span class="nx">user</span><span class="p">;</span>

<span class="o">--</span> <span class="nx">SELECT</span> <span class="nx">와</span> <span class="nx">FROM</span> <span class="nx">사이에</span> <span class="o">*</span> <span class="nx">을</span> <span class="nx">적으면</span> <span class="nx">테이블의</span> <span class="nx">모든</span> <span class="nx">컬럼을</span> <span class="nx">조회한다</span><span class="p">.</span>
<span class="nx">SELECT</span> <span class="o">*</span> <span class="nx">FROM</span> <span class="nx">user</span><span class="p">;</span>

<span class="o">--</span> <span class="nx">아래</span> <span class="nx">두</span> <span class="nx">SQL은</span> <span class="nx">동일한</span> <span class="nx">기능을</span> <span class="nx">한다</span><span class="p">.</span>
<span class="nx">SELECT</span> <span class="o">*</span> <span class="nx">FROM</span> <span class="nx">user_db</span><span class="p">.</span><span class="nx">user</span><span class="p">;</span>
<span class="nx">SELECT</span> <span class="o">*</span> <span class="nx">FROM</span> <span class="nx">user</span><span class="p">;</span>
</code></pre></div></div>

<ul>
  <li>기본적으로 테이블이름은 <code class="language-plaintext highlighter-rouge">스키마명.테이블명</code>으로 표현한다.</li>
  <li>하지만 <code class="language-plaintext highlighter-rouge">USE</code>문으로 스키마지정을 했다면 테이블명만 명시해도 된다.</li>
</ul>

<h2 id="where---특정-조건만-조회하기">WHERE - 특정 조건만 조회하기</h2>

<div class="language-jsx highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">--</span> <span class="nx">user</span> <span class="nx">테이블에서</span> <span class="nx">user_num</span> <span class="nx">컬럼</span> <span class="nx">값이</span> <span class="mi">5</span> <span class="nx">이상인</span> <span class="nx">데이터</span> <span class="nx">조회</span>
<span class="nx">SELECT</span> <span class="o">*</span> <span class="nx">FROM</span> <span class="nx">user</span>
	<span class="nx">WHERE</span> <span class="nx">user_num</span> <span class="o">&gt;=</span> <span class="mi">5</span><span class="p">;</span>
</code></pre></div></div>

<ul>
  <li><code class="language-plaintext highlighter-rouge">WHERE</code>절을 사용해 특정 <strong>조건</strong>에 해당하는 데이터만 조회할 수 있다.</li>
  <li>관계연산자/논리연산자 사용가능</li>
</ul>

<h2 id="논리연산자-and-or-사용가능">논리연산자 AND, OR 사용가능</h2>

<div class="language-jsx highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">SELECT</span> <span class="nx">TRUE</span> <span class="nx">OR</span> <span class="nx">FALSE</span> <span class="nx">AND</span> <span class="nx">FALSE</span><span class="p">;</span> <span class="o">--</span> <span class="mi">1</span>

<span class="nx">SELECT</span> <span class="p">(</span><span class="nx">TRUE</span> <span class="nx">OR</span> <span class="nx">FALSE</span><span class="p">)</span> <span class="nx">AND</span> <span class="nx">FALSE</span><span class="p">;</span> <span class="o">--</span> <span class="mi">0</span>
</code></pre></div></div>

<ul>
  <li>여러 조건이 필요한 경우 논리 연산자를 사용한다.</li>
  <li><code class="language-plaintext highlighter-rouge">AND</code>가 <code class="language-plaintext highlighter-rouge">OR</code>보다 우선순위를 가진다.</li>
  <li>MySQL에서는 <code class="language-plaintext highlighter-rouge">&amp;&amp;</code>이나 <code class="language-plaintext highlighter-rouge">||</code>도 사용 가능하다.</li>
</ul>

<h2 id="between---범위표현식">BETWEEN - 범위표현식</h2>

<div class="language-jsx highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">--</span> <span class="nx">user</span> <span class="nx">테이블에서</span> <span class="nx">height</span> <span class="nx">컬럼</span> <span class="nx">값이</span> <span class="mi">160</span><span class="nx">이상</span> <span class="mi">165</span><span class="nx">이하인</span> <span class="nx">데이터</span> <span class="nx">조회</span>
<span class="nx">SELECT</span> <span class="o">*</span> <span class="nx">FROM</span> <span class="nx">user</span>
		<span class="nx">WHERE</span> <span class="nx">height</span> <span class="nx">between</span> <span class="mi">160</span> <span class="nx">and</span> <span class="mi">165</span><span class="p">;</span>
</code></pre></div></div>

<ul>
  <li><code class="language-plaintext highlighter-rouge">between</code> 연산자를 이용하여 특정 범위에 해당하는 데이터를 조회할 수 있다.</li>
  <li>하지만 인덱스를 사용할 수 없으므로 주의</li>
</ul>

<h2 id="in---여러-값-매칭">IN() - 여러 값 매칭</h2>

<div class="language-jsx highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">--</span> <span class="nx">addr</span> <span class="nx">컬럼값이</span> <span class="nx">경기</span><span class="p">,</span> <span class="nx">전남</span><span class="p">,</span> <span class="nx">경남인</span> <span class="nx">데이터</span> <span class="nx">조회</span>
<span class="nx">SELECT</span> <span class="o">*</span> <span class="nx">FROM</span> <span class="nx">user</span>
		<span class="nx">WHERE</span> <span class="nx">addr</span> <span class="nx">IN</span><span class="p">(</span><span class="dl">'</span><span class="s1">경기</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">전남</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">경남</span><span class="dl">'</span><span class="p">);</span>

<span class="o">--</span> <span class="nx">IN</span><span class="p">()</span><span class="nx">을</span> <span class="nx">사용하지</span> <span class="nx">않으면</span> <span class="nx">아래처럼</span> <span class="nx">조회</span><span class="p">.</span>
<span class="nx">SELECT</span> <span class="o">*</span> <span class="nx">FROM</span> <span class="nx">user</span>
		<span class="nx">WHERE</span> <span class="nx">addr</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">경기</span><span class="dl">'</span> <span class="nx">OR</span> <span class="nx">addr</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">전남</span><span class="dl">'</span> <span class="nx">OR</span> <span class="nx">addr</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">경남</span><span class="dl">'</span><span class="p">;</span>
</code></pre></div></div>

<ul>
  <li><code class="language-plaintext highlighter-rouge">IN()</code> 연산자를 이용하여 특정 값이 포함된 데이터를 조회할 수 있다.</li>
  <li><code class="language-plaintext highlighter-rouge">IN()</code> 연산자는 동등비교 ‘=’를 여러번 수행하는 효과를 가진다. 따라서 인덱스를 최적으로 활용할 수 있다.</li>
</ul>

<h2 id="like---문자열의-일부-글자-검색">LIKE - 문자열의 일부 글자 검색</h2>

<div class="language-jsx highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">--</span> <span class="nx">user_name</span> <span class="nx">컬럼</span> <span class="nx">값이</span> <span class="dl">'</span><span class="s1">블</span><span class="dl">'</span><span class="nx">로</span> <span class="nx">시작하는</span> <span class="mi">4</span><span class="nx">글자</span> <span class="nx">데이터</span> <span class="nx">조회</span>
<span class="nx">SELECT</span> <span class="o">*</span> <span class="nx">FROM</span> <span class="nx">user</span> <span class="nx">WHERE</span> <span class="nx">user_name</span> <span class="nx">LIKE</span> <span class="dl">'</span><span class="s1">블___</span><span class="dl">'</span><span class="p">;</span>

<span class="o">--</span> <span class="nx">user_name</span> <span class="nx">컬럼</span> <span class="nx">값이</span> <span class="dl">'</span><span class="s1">블</span><span class="dl">'</span><span class="nx">로</span> <span class="nx">시작하는</span> <span class="nx">모든</span> <span class="nx">데이터</span> <span class="nx">조회</span>
<span class="nx">SELECT</span> <span class="o">*</span> <span class="nx">FROM</span> <span class="nx">user</span> <span class="nx">WHERE</span> <span class="nx">user_name</span> <span class="nx">LIKE</span> <span class="dl">'</span><span class="s1">블%</span><span class="dl">'</span><span class="p">;</span>

<span class="o">--</span> <span class="nx">user_name</span> <span class="nx">컬럼</span> <span class="nx">값에</span> <span class="dl">'</span><span class="s1">블</span><span class="dl">'</span><span class="nx">이</span> <span class="nx">들어가는</span> <span class="nx">모든</span> <span class="nx">데이터</span> <span class="nx">조회</span>
<span class="nx">SELECT</span> <span class="o">*</span> <span class="nx">FROM</span> <span class="nx">user</span> <span class="nx">WHERE</span> <span class="nx">user_name</span> <span class="nx">LIKE</span> <span class="dl">'</span><span class="s1">%블%</span><span class="dl">'</span><span class="p">;</span>
</code></pre></div></div>

<ul>
  <li>문자열의 일부 글자 검색
    <ul>
      <li><code class="language-plaintext highlighter-rouge">_</code>: 한글자만 매치</li>
      <li><code class="language-plaintext highlighter-rouge">%</code>: 몇글자든 매치</li>
    </ul>
  </li>
</ul>

<h2 id="order-by---조회된-데이터를-정렬">ORDER BY - 조회된 데이터를 정렬</h2>

<div class="language-jsx highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">--</span> <span class="nx">debut_date</span> <span class="nx">값을</span> <span class="nx">기준으로</span> <span class="nx">정렬</span> <span class="p">(</span><span class="nx">기본</span> <span class="nx">ASC</span><span class="p">)</span>
<span class="nx">SELECT</span> <span class="o">*</span> <span class="nx">FROM</span> <span class="nx">user</span>
		<span class="nx">ORDER</span> <span class="nx">BY</span> <span class="nx">debut_date</span>
</code></pre></div></div>

<ul>
  <li><code class="language-plaintext highlighter-rouge">ASC(ascending order)</code>: 오름차순 - 생략시 기본값</li>
  <li><code class="language-plaintext highlighter-rouge">DESC(descending order)</code>: 내림차순</li>
  <li><code class="language-plaintext highlighter-rouge">ORDER BY</code>절은 데이터를 정렬한다.</li>
  <li><code class="language-plaintext highlighter-rouge">WHERE</code>절 다음에 나와야 한다.</li>
  <li><code class="language-plaintext highlighter-rouge">,</code>로 여러 정렬 조건 지정 가능</li>
</ul>

<div class="language-jsx highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">--</span> <span class="nx">height</span> <span class="nx">컬럼</span> <span class="nx">값이</span> <span class="mi">164</span> <span class="nx">이상인</span> <span class="nx">데이터</span> <span class="nx">조회</span>
<span class="o">--</span> <span class="nx">height</span> <span class="nx">값</span> <span class="nx">기준</span> <span class="nx">내림차순</span> <span class="nx">정렬</span><span class="p">,</span> <span class="nx">동일</span> <span class="nx">값이면</span> <span class="nx">debut_data</span> <span class="nx">기준</span> <span class="nx">오름차순</span>
<span class="nx">SELECT</span> <span class="o">*</span> <span class="nx">FROM</span> <span class="nx">USER</span>
		<span class="nx">WHRER</span> <span class="nx">height</span> <span class="o">&gt;=</span> <span class="mi">164</span>
		<span class="nx">ORDER</span> <span class="nx">BY</span> <span class="nx">height</span> <span class="nx">DESC</span><span class="p">,</span> <span class="nx">debut_data</span> <span class="nx">ASC</span><span class="p">;</span>
</code></pre></div></div>

<h2 id="limit---출력-개수-제한">LIMIT - 출력 개수 제한</h2>

<div class="language-jsx highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">SELECT</span> <span class="o">*</span> <span class="nx">FROM</span> <span class="nx">user</span>
		<span class="nx">LIMIT</span> <span class="mi">3</span><span class="p">;</span> <span class="o">--</span> <span class="nx">상위</span> <span class="mi">3</span><span class="nx">건만</span> <span class="nx">조회</span>

<span class="nx">SELECT</span> <span class="o">*</span> <span class="nx">FROM</span> <span class="nx">user</span>
		<span class="nx">LIMIT</span> <span class="mi">3</span><span class="p">,</span><span class="mi">2</span><span class="p">;</span> <span class="o">--</span> <span class="mi">3</span><span class="nx">번째</span> <span class="nx">데이터부터</span> <span class="mi">2</span><span class="nx">건만</span> <span class="nx">조회</span>
		<span class="nx">LIMIT</span> <span class="mi">2</span> <span class="nx">OFFSET</span> <span class="mi">3</span><span class="p">;</span> <span class="o">--</span> <span class="mi">3</span><span class="nx">번째</span> <span class="nx">데이터부터</span> <span class="mi">2</span><span class="nx">건만</span> <span class="nx">조회</span>
</code></pre></div></div>

<ul>
  <li><code class="language-plaintext highlighter-rouge">LIMIT</code> 시작, 개수</li>
  <li><code class="language-plaintext highlighter-rouge">LIMIT</code> 뒤에 하나의 숫자만 입력시 처음부터 N까지</li>
  <li><code class="language-plaintext highlighter-rouge">LIMIT</code>와 <code class="language-plaintext highlighter-rouge">OFFSET</code>조합으로도 출력 개수 제한가능</li>
</ul>

<h2 id="distinct---중복-데이터-제거">DISTINCT - 중복 데이터 제거</h2>

<div class="language-jsx highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">--</span> <span class="nx">addr의</span> <span class="nx">모든</span> <span class="nx">컬럼</span> <span class="nx">값을</span> <span class="nx">중복을</span> <span class="nx">제거하여</span> <span class="nx">조회</span>
<span class="nx">SELECT</span> <span class="nx">DISTINCT</span> <span class="nx">addr</span>
		<span class="nx">FROM</span> <span class="nx">user</span><span class="p">;</span>
</code></pre></div></div>

<ul>
  <li><code class="language-plaintext highlighter-rouge">DISTINCT</code>를 열 이름 앞에 붙이면 중복된 값은 1개만 출력됨.</li>
</ul>

<h2 id="group-by---그룹화">GROUP BY - 그룹화</h2>

<div class="language-jsx highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">--</span> <span class="nx">user_id가</span> <span class="nx">같은</span> <span class="nx">데이터를</span> <span class="nx">그룹으로</span> <span class="nx">묶음</span>
<span class="o">--</span> <span class="nx">그룹핑된</span> <span class="nx">데이터에서</span> <span class="nx">user_id와</span> <span class="nx">amount의</span> <span class="nx">합계를</span> <span class="nx">구함</span>
<span class="nx">SELECT</span> <span class="nx">user_id</span><span class="p">,</span> <span class="nx">SUM</span><span class="p">(</span><span class="nx">amount</span><span class="p">)</span> <span class="nx">AS</span> <span class="dl">"</span><span class="s2">합계</span><span class="dl">"</span>
		<span class="nx">FROM</span> <span class="nx">buy</span>
		<span class="nx">GROUP</span> <span class="nx">BY</span> <span class="nx">user_id</span>
		<span class="nx">ORDER</span> <span class="nx">BY</span> <span class="nx">user_id</span><span class="p">;</span>
</code></pre></div></div>

<ul>
  <li>컬럼이 같은 데이터를 그룹화 해주는 기능</li>
  <li>보통 집계 함수와 같이 쓰임</li>
</ul>

<div class="language-jsx highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">SELECT</span> <span class="nx">genre</span><span class="p">,</span> <span class="nx">AVG</span><span class="p">(</span><span class="nx">price</span><span class="p">)</span> <span class="nx">AS</span> <span class="dl">"</span><span class="s2">평균</span><span class="dl">"</span>
		<span class="nx">FROM</span> <span class="nx">library</span>
		<span class="nx">GROUP</span> <span class="nx">BY</span> <span class="nx">genre</span><span class="p">;</span>
</code></pre></div></div>

<ul>
  <li><code class="language-plaintext highlighter-rouge">GROUP BY</code>로 지정한 컬럼이 같은 데이터끼리 그룹화</li>
  <li>여러 컬럼 지정 가능</li>
</ul>

<h2 id="집계함수">집계함수</h2>

<ul>
  <li><code class="language-plaintext highlighter-rouge">SUM()</code>: 컬럼의 합계 반환</li>
  <li><code class="language-plaintext highlighter-rouge">AVG()</code>: 컬럼의 평균 반환</li>
  <li><code class="language-plaintext highlighter-rouge">MIN()</code>: 컬럼의 최소값 반환</li>
  <li><code class="language-plaintext highlighter-rouge">MAX()</code>: 컬럼의 최대값 반환</li>
  <li><code class="language-plaintext highlighter-rouge">COUNT()</code>: 행의 개수를 셈</li>
  <li><code class="language-plaintext highlighter-rouge">COUNT(DISTINCT)</code>: 고유 행의 개수를 셈 (중복, null 제외)</li>
</ul>

<div class="language-jsx highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">--</span> <span class="nx">집계함수</span> <span class="nx">안에서</span> <span class="nx">연산도</span> <span class="nx">가능</span>
<span class="nx">SELECT</span> <span class="nx">user_id</span><span class="p">,</span> <span class="nx">SUM</span><span class="p">(</span><span class="nx">amount</span><span class="o">*</span><span class="nx">price</span><span class="p">)</span> <span class="nx">AS</span> <span class="dl">"</span><span class="s2">총 금액</span><span class="dl">"</span>
		<span class="nx">FROM</span> <span class="nx">buy</span>
		<span class="nx">GROUP</span> <span class="nx">BY</span> <span class="nx">user_id</span>
		<span class="nx">ORDER</span> <span class="nx">BY</span> <span class="nx">user_id</span><span class="p">;</span>
</code></pre></div></div>

<h2 id="count">COUNT()</h2>

<div class="language-jsx highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">--</span> <span class="nx">user</span> <span class="nx">테이블의</span> <span class="nx">모든</span> <span class="nx">데이터</span> <span class="nx">개수를</span> <span class="nx">셈</span>
<span class="nx">SELECT</span> <span class="nx">COUNT</span><span class="p">(</span><span class="o">*</span><span class="p">)</span>
		<span class="nx">FROM</span> <span class="nx">user</span><span class="p">;</span>

<span class="o">--</span> <span class="nx">user</span> <span class="nx">테이블의</span> <span class="nx">phone_num</span> <span class="nx">컬럼이</span> <span class="nx">NULL인</span> <span class="nx">것을</span> <span class="nx">제외한</span> <span class="nx">모든</span> <span class="nx">데이터</span> <span class="nx">개수를</span> <span class="nx">셈</span>
<span class="nx">SELECT</span> <span class="nx">COUNT</span><span class="p">(</span><span class="nx">phone_num</span><span class="p">)</span>
		<span class="nx">FROM</span> <span class="nx">user</span><span class="p">;</span>
</code></pre></div></div>

<ul>
  <li><code class="language-plaintext highlighter-rouge">COUNT(\*)</code> 연산은 모든 행을 대상으로 이루어지기 때문에 <code class="language-plaintext highlighter-rouge">NULL</code> 값이 포함되어있어도 카운트됨</li>
  <li><code class="language-plaintext highlighter-rouge">COUNT(phone_num)</code> 연산은 <code class="language-plaintext highlighter-rouge">phone_num</code>값에 <code class="language-plaintext highlighter-rouge">NULL</code>이 있을 경우 카운트하지 않음</li>
</ul>

<h2 id="having---그룹-조건">HAVING - 그룹 조건</h2>

<div class="language-jsx highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">--</span> <span class="nx">user_id를</span> <span class="nx">기준으로</span> <span class="nx">그룹화</span>
<span class="o">--</span> <span class="nx">그룹화</span> <span class="nx">된</span> <span class="nx">데이터를</span> <span class="nx">기준으로</span> <span class="nx">amount</span> <span class="o">*</span> <span class="nx">price</span> <span class="nx">합계가</span> <span class="mi">1000</span><span class="nx">이상인</span> <span class="nx">그룹만</span> <span class="nx">남김</span>
<span class="o">--</span> <span class="nx">조건에</span> <span class="nx">걸러진</span> <span class="nx">그룹에서</span> <span class="nx">amount</span> <span class="o">*</span> <span class="nx">price</span> <span class="nx">합계를</span> <span class="nx">조회</span>
<span class="nx">SELECT</span> <span class="nx">SUM</span><span class="p">(</span><span class="nx">amount</span><span class="o">*</span><span class="nx">price</span><span class="p">)</span> <span class="nx">AS</span> <span class="dl">"</span><span class="s2">총 금액</span><span class="dl">"</span>
		<span class="nx">FROM</span> <span class="nx">buy</span>
		<span class="nx">GROUP</span> <span class="nx">BY</span> <span class="nx">user_id</span>
		<span class="nx">HAVING</span> <span class="nx">SUM</span><span class="p">(</span><span class="nx">amount</span><span class="o">*</span><span class="nx">price</span><span class="p">)</span> <span class="o">&gt;=</span> <span class="mi">1000</span><span class="p">;</span>
</code></pre></div></div>

<ul>
  <li>그룹화된 데이터에 대해 조건을 제한</li>
  <li>때문에 <code class="language-plaintext highlighter-rouge">GROUP BY</code> 뒤에 와야함</li>
</ul>]]></content><author><name>김도연</name></author><category term="MySQL_study" /><category term="MySQL_study" /><category term="study" /><summary type="html"><![CDATA[SQL 기본 문법: SELECT, WHERE, ORDER BY 등]]></summary></entry><entry><title type="html">[JAVA] 자바 객체 지향 프로그래밍 (OOP)</title><link href="https://hidokim.github.io/java_study/study_JAVA_2/" rel="alternate" type="text/html" title="[JAVA] 자바 객체 지향 프로그래밍 (OOP)" /><published>2025-09-18T00:00:00+09:00</published><updated>2025-09-18T00:00:00+09:00</updated><id>https://hidokim.github.io/java_study/study_JAVA_2</id><content type="html" xml:base="https://hidokim.github.io/java_study/study_JAVA_2/"><![CDATA[<h1 id="생활코딩-강의-정리">생활코딩 강의 정리</h1>

<h2 id="java-객체-지향-프로그래밍-oop">JAVA: 객체 지향 프로그래밍 (OOP)</h2>

<p>이 글은 아래의 강의를 보고 작성한 포스트 입니다.</p>

<ul>
  <li><a href="https://www.youtube.com/watch?v=uvYWAfZzb8k&amp;list=PLuHgQVnccGMAb-e41kXPSIpmoz1RvHyN4">Java : 객체 지향 프로그래밍</a></li>
</ul>

<h3 id="1-남의-클래스--남의-인스턴스">1. 남의 클래스 &amp; 남의 인스턴스</h3>

<h4 id="math-클래스">Math 클래스</h4>

<ul>
  <li>PI 변수</li>
  <li>floor()</li>
  <li>ceil()</li>
</ul>

<h4 id="filewriter-클래스">FileWriter 클래스</h4>

<ul>
  <li>write()</li>
  <li>close()</li>
</ul>

<h4 id="실습-코드">실습 코드</h4>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">package</span> <span class="nn">others</span><span class="o">;</span>

<span class="kn">import</span> <span class="nn">java.io.FileWriter</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.io.IOException</span><span class="o">;</span>

<span class="kd">public</span> <span class="kd">class</span> <span class="nc">OthersOOP</span> <span class="o">{</span>
    <span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="nc">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="kd">throws</span> <span class="nc">IOException</span> <span class="o">{</span> <span class="c1">//예외처리</span>
        <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="nc">Math</span><span class="o">.</span><span class="na">PI</span><span class="o">);</span>
        <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="nc">Math</span><span class="o">.</span><span class="na">floor</span><span class="o">(</span><span class="mf">1.8</span><span class="o">));</span> <span class="c1">//내림</span>
        <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="nc">Math</span><span class="o">.</span><span class="na">ceil</span><span class="o">(</span><span class="mf">1.8</span><span class="o">));</span> <span class="c1">//올림</span>

        <span class="nc">FileWriter</span> <span class="n">f1</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">FileWriter</span><span class="o">(</span><span class="s">"data.txt"</span><span class="o">);</span>
        <span class="n">f1</span><span class="o">.</span><span class="na">write</span><span class="o">(</span><span class="s">"hello world"</span><span class="o">);</span>
        <span class="n">f1</span><span class="o">.</span><span class="na">close</span><span class="o">();</span>

        <span class="nc">FileWriter</span> <span class="n">f2</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">FileWriter</span><span class="o">(</span><span class="s">"data2.txt"</span><span class="o">);</span>
        <span class="n">f2</span><span class="o">.</span><span class="na">write</span><span class="o">(</span><span class="s">"hello world"</span><span class="o">);</span>
        <span class="n">f2</span><span class="o">.</span><span class="na">close</span><span class="o">();</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<ul>
  <li>
    <p>Math의 PI와 floor는 일회성으로 이용, 내부 상태를 계속 유지할 필요가 없음</p>

    <p>-&gt; 메소드나 변수를 클래스에 있는 그대로 사용</p>
  </li>
  <li>
    <p>FileWriter의 write는 내부 상태를 계속 유지해야 함.</p>

    <p>-&gt; 클래스의 복제본을 만들어서 메소드나 변수를 사용</p>
  </li>
</ul>

<h3 id="2-클래스와-인스턴스">2. 클래스와 인스턴스</h3>

<h4 id="클래스">클래스</h4>

<ul>
  <li>객체를 정의한 틀</li>
  <li>객체를 만들기 위한 설계도 역할</li>
  <li>객체가 가져야 할 속성(필드)과 기능(메서드)을 미리 정의해 놓은 추상적 개념</li>
</ul>

<h4 id="인스턴스">인스턴스</h4>

<ul>
  <li>클래스라는 설계도를 바탕으로 만들어진 실제 객체</li>
  <li>클래스는 추상적이며 실제 메모리에 할당되지 않음. 인스턴스는 new 연산자를 통해 메모리에 생성되어 프로그램 내에서 동작하는 구체적인 존재</li>
</ul>

<h4 id="예시">예시</h4>

<p>클래스가 ‘사람’이라면 인스턴스는 ‘홍길동’이라는 사람</p>

<h4 id="생성자와-this">생성자와 this</h4>

<ul>
  <li>생성자: 클래스와 똑같은 이름의 메소드를 정의한 것</li>
  <li>자바는 생성자가 있으면 이를 먼저 호출함</li>
  <li>
    <p>가장 먼저 실행해야하는 코드를 생성자에 넣음</p>
  </li>
  <li>this: 현재 있는 인스턴스를 가리킴</li>
</ul>

<h4 id="실습코드">실습코드</h4>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">package</span> <span class="nn">others</span><span class="o">;</span>

<span class="kd">public</span> <span class="kd">class</span> <span class="nc">MyOOP</span> <span class="o">{</span>
    <span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="nc">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>
        <span class="nc">Print</span> <span class="n">p1</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Print</span><span class="o">(</span><span class="s">"----"</span><span class="o">);</span>
<span class="c1">//      p1.delimiter = "----";</span>
        <span class="n">p1</span><span class="o">.</span><span class="na">A</span><span class="o">();</span>
        <span class="n">p1</span><span class="o">.</span><span class="na">A</span><span class="o">();</span>
        <span class="n">p1</span><span class="o">.</span><span class="na">B</span><span class="o">();</span>
        <span class="n">p1</span><span class="o">.</span><span class="na">B</span><span class="o">();</span>

        <span class="nc">Print</span> <span class="n">p2</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Print</span><span class="o">(</span><span class="s">"****"</span><span class="o">);</span>
 <span class="c1">//     p2.delimiter = "****";</span>
        <span class="n">p2</span><span class="o">.</span><span class="na">A</span><span class="o">();</span>
        <span class="n">p2</span><span class="o">.</span><span class="na">A</span><span class="o">();</span>
        <span class="n">p2</span><span class="o">.</span><span class="na">B</span><span class="o">();</span>
        <span class="n">p2</span><span class="o">.</span><span class="na">B</span><span class="o">();</span>

        <span class="n">p1</span><span class="o">.</span><span class="na">A</span><span class="o">();</span>
        <span class="n">p2</span><span class="o">.</span><span class="na">A</span><span class="o">();</span>
        <span class="n">p1</span><span class="o">.</span><span class="na">A</span><span class="o">();</span>
        <span class="n">p2</span><span class="o">.</span><span class="na">A</span><span class="o">();</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">package</span> <span class="nn">others</span><span class="o">;</span>

<span class="kd">class</span> <span class="nc">Print</span><span class="o">{</span>

    <span class="kd">public</span> <span class="nc">String</span> <span class="n">delimiter</span> <span class="o">=</span> <span class="s">""</span><span class="o">;</span>

    <span class="c1">// 생성자(초기필수작업)</span>
    <span class="kd">public</span> <span class="nf">Print</span><span class="o">(</span><span class="nc">String</span> <span class="n">delimiter</span><span class="o">){</span>
        <span class="k">this</span><span class="o">.</span><span class="na">delimiter</span> <span class="o">=</span> <span class="n">delimiter</span><span class="o">;</span>
    <span class="o">}</span> <span class="c1">// this : 현재 인스턴스</span>
    <span class="kd">public</span> <span class="kt">void</span> <span class="nf">A</span><span class="o">()</span> <span class="o">{</span>
        <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="k">this</span><span class="o">.</span><span class="na">delimiter</span><span class="o">);</span>
        <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"A"</span><span class="o">);</span>
        <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"A"</span><span class="o">);</span>
    <span class="o">}</span>

    <span class="kd">public</span> <span class="kt">void</span> <span class="nf">B</span><span class="o">()</span> <span class="o">{</span>
        <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="k">this</span><span class="o">.</span><span class="na">delimiter</span><span class="o">);</span>
        <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"B"</span><span class="o">);</span>
        <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"B"</span><span class="o">);</span>
    <span class="o">}</span>
<span class="o">}</span>

</code></pre></div></div>

<h3 id="3-static">3. static</h3>

<h4 id="클래스-변수와-인스턴스-변수">클래스 변수와 인스턴스 변수</h4>

<ul>
  <li>클래스 변수를 바꾸면 클래스 변수를 공유하는 인스턴스 변수도 바뀐다.</li>
</ul>

<h4 id="실습코드-1">실습코드</h4>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">package</span> <span class="nn">staticTest</span><span class="o">;</span>

<span class="kd">class</span> <span class="nc">Foo</span> <span class="o">{</span>
    <span class="kd">public</span> <span class="kd">static</span> <span class="nc">String</span> <span class="n">classVar</span> <span class="o">=</span> <span class="s">"I class var"</span><span class="o">;</span><span class="c1">//클래스 변수</span>
    <span class="kd">public</span> <span class="nc">String</span> <span class="n">instanceVar</span> <span class="o">=</span> <span class="s">"I instance Var"</span><span class="o">;</span> <span class="c1">//인스턴스 변수</span>
    <span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">classMethod</span><span class="o">()</span> <span class="o">{</span> <span class="c1">//클래스 메소드</span>
        <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">classVar</span><span class="o">);</span> <span class="c1">//OK</span>
<span class="c1">//        System.out.println(instanceVar); //Error</span>
    <span class="o">}</span>
    <span class="kd">public</span> <span class="kt">void</span> <span class="nf">instanceMethod</span><span class="o">()</span> <span class="o">{</span> <span class="c1">//인스턴스 메소드</span>
        <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">classVar</span><span class="o">);</span>
        <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">instanceVar</span><span class="o">);</span>
    <span class="o">}</span>
<span class="o">}</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">StaticApp</span> <span class="o">{</span>
    <span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="nc">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>
        <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="nc">Foo</span><span class="o">.</span><span class="na">classVar</span><span class="o">);</span>
<span class="c1">//        System.out.println(Foo.instanceVar); //Error</span>

        <span class="nc">Foo</span><span class="o">.</span><span class="na">classMethod</span><span class="o">();</span>
<span class="c1">//        Foo.instanceMethod(); //Error</span>

        <span class="nc">Foo</span> <span class="n">f1</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Foo</span><span class="o">();</span>
        <span class="nc">Foo</span> <span class="n">f2</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Foo</span><span class="o">();</span>
        <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">f1</span><span class="o">.</span><span class="na">classVar</span><span class="o">);</span>
        <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">f1</span><span class="o">.</span><span class="na">instanceVar</span><span class="o">);</span>

        <span class="n">f1</span><span class="o">.</span><span class="na">classVar</span> <span class="o">=</span><span class="s">"changed by f1"</span><span class="o">;</span>
        <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="nc">Foo</span><span class="o">.</span><span class="na">classVar</span><span class="o">);</span>
        <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">f2</span><span class="o">.</span><span class="na">classVar</span><span class="o">);</span>

        <span class="n">f1</span><span class="o">.</span><span class="na">instanceVar</span> <span class="o">=</span><span class="s">"changed by f1"</span><span class="o">;</span>
        <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">f1</span><span class="o">.</span><span class="na">instanceVar</span><span class="o">);</span>
        <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">f2</span><span class="o">.</span><span class="na">instanceVar</span><span class="o">);</span>
    <span class="o">}</span>
<span class="o">}</span>

</code></pre></div></div>

<h3 id="4-활용">4. 활용</h3>

<h4 id="부가가치세를-계산하는-프로그램">부가가치세를 계산하는 프로그램</h4>

<h4 id="실습코드-2">실습코드</h4>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">package</span> <span class="nn">review</span><span class="o">;</span>
<span class="c1">// 클레스화</span>
<span class="kd">class</span> <span class="nc">Accounting</span><span class="o">{</span> <span class="c1">// 부가가치세와 관련된 변수/메소드만 존재</span>

    <span class="c1">// 공급가액</span>
    <span class="kd">public</span> <span class="kt">double</span> <span class="n">valueOfSupply</span><span class="o">;</span>
    <span class="kd">public</span> <span class="nf">Accounting</span><span class="o">(</span><span class="kt">double</span> <span class="n">valueOfSupply</span><span class="o">){</span> <span class="c1">// 부가가치세를 받아옴</span>
        <span class="k">this</span><span class="o">.</span><span class="na">valueOfSupply</span> <span class="o">=</span> <span class="n">valueOfSupply</span><span class="o">;</span>
    <span class="o">}</span>
    <span class="c1">// 부가가치세율</span>
    <span class="kd">public</span> <span class="kd">static</span> <span class="kt">double</span> <span class="n">vatRate</span> <span class="o">=</span> <span class="mf">0.1</span><span class="o">;</span> <span class="c1">// 변경될 일이 없음. static으로 두기.</span>

    <span class="kd">public</span> <span class="kt">double</span> <span class="nf">getVAT</span><span class="o">()</span> <span class="o">{</span> <span class="c1">// 부가가치세 계산</span>
        <span class="k">return</span> <span class="k">this</span><span class="o">.</span><span class="na">valueOfSupply</span> <span class="o">*</span> <span class="n">vatRate</span><span class="o">;</span>
    <span class="o">}</span>

    <span class="kd">public</span> <span class="kt">double</span> <span class="nf">getTotal</span><span class="o">()</span> <span class="o">{</span> <span class="c1">// 총 금액</span>
        <span class="k">return</span> <span class="k">this</span><span class="o">.</span><span class="na">valueOfSupply</span> <span class="o">+</span> <span class="n">getVAT</span><span class="o">();</span>
    <span class="o">}</span>
<span class="o">}</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">AccountingApp</span> <span class="o">{</span> <span class="c1">// 메인</span>

    <span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="nc">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>

        <span class="nc">Accounting</span> <span class="n">a1</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Accounting</span><span class="o">(</span><span class="mf">10000.0</span><span class="o">);</span> <span class="c1">// 인스턴스화</span>
        <span class="nc">Accounting</span> <span class="n">a2</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Accounting</span><span class="o">(</span><span class="mf">20000.0</span><span class="o">);</span>

        <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"Value of supply : "</span> <span class="o">+</span> <span class="n">a1</span><span class="o">.</span><span class="na">valueOfSupply</span><span class="o">);</span>
        <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"Value of supply : "</span> <span class="o">+</span> <span class="n">a2</span><span class="o">.</span><span class="na">valueOfSupply</span><span class="o">);</span>

        <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"VAT : "</span> <span class="o">+</span> <span class="n">a1</span><span class="o">.</span><span class="na">getVAT</span><span class="o">());</span>
        <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"VAT : "</span> <span class="o">+</span> <span class="n">a2</span><span class="o">.</span><span class="na">getVAT</span><span class="o">());</span>

        <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"Total : "</span> <span class="o">+</span> <span class="n">a1</span><span class="o">.</span><span class="na">getTotal</span><span class="o">());</span>
        <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"Total : "</span> <span class="o">+</span> <span class="n">a2</span><span class="o">.</span><span class="na">getTotal</span><span class="o">());</span>

    <span class="o">}</span>

<span class="o">}</span>

</code></pre></div></div>]]></content><author><name>김도연</name></author><category term="JAVA_study" /><category term="JAVA_study" /><category term="study" /><summary type="html"><![CDATA[생활코딩 강의 정리]]></summary></entry><entry><title type="html">[JAVA] 자바 collections framework</title><link href="https://hidokim.github.io/java_study/study_JAVA_1/" rel="alternate" type="text/html" title="[JAVA] 자바 collections framework" /><published>2025-09-05T00:00:00+09:00</published><updated>2025-09-05T00:00:00+09:00</updated><id>https://hidokim.github.io/java_study/study_JAVA_1</id><content type="html" xml:base="https://hidokim.github.io/java_study/study_JAVA_1/"><![CDATA[<h1 id="생활코딩-강의-정리">생활코딩 강의 정리</h1>

<h2 id="java-collections-frameworks">JAVA: Collections frameworks</h2>

<h3 id="1-arraylist의-사용법">1. ArrayList의 사용법</h3>

<p>이 글은 아래의 강의를 보고 작성한 포스트 입니다.</p>

<ul>
  <li><a href="https://www.youtube.com/watch?v=KaPbVAxi5LE&amp;list=PLuHgQVnccGMCeAy-2-llhw3nWoQKUvQck&amp;index=151">Java : Collections framework</a></li>
</ul>

<h4 id="arraylist">ArrayList</h4>

<ul>
  <li>배열은 정해진 크기 이상의 데이터를 넣으려고 하면 오류가 생김</li>
  <li>이 오류를 해결하기 위한 방법이 ArrayList</li>
</ul>

<h4 id="배열-vs-arraylist">배열 vs ArrayList</h4>

<ul>
  <li>.length == .size()</li>
  <li>obj[i] == .get(i)</li>
</ul>

<h4 id="arraylist-사용시-주의할-점">ArrayList 사용시 주의할 점</h4>

<ul>
  <li>ArrayList의 기본형은 object이기 때문에 genetic을 사용해서 형변환을 해야함.</li>
  <li>(String)를 이용해 형변환을 해도 됨 -&gt; 옛날 방식</li>
</ul>

<hr />

<h4 id="실습코드">실습코드</h4>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">package</span> <span class="nn">arrayTest</span><span class="o">;</span>

<span class="kn">import</span> <span class="nn">java.util.ArrayList</span><span class="o">;</span>

<span class="kd">public</span> <span class="kd">class</span> <span class="nc">ArrayListDemo</span> <span class="o">{</span>
    <span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="nc">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>
        <span class="nc">String</span><span class="o">[]</span> <span class="n">arrayObj</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">String</span><span class="o">[</span><span class="mi">2</span><span class="o">];</span>
        <span class="n">arrayObj</span><span class="o">[</span><span class="mi">0</span><span class="o">]</span> <span class="o">=</span> <span class="s">"one"</span><span class="o">;</span>
        <span class="n">arrayObj</span><span class="o">[</span><span class="mi">1</span><span class="o">]</span> <span class="o">=</span> <span class="s">"two"</span><span class="o">;</span>
        <span class="c1">//arrayObj[2] = "three"; // 오류가 발생한다.</span>

        <span class="k">for</span> <span class="o">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="o">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">arrayObj</span><span class="o">.</span><span class="na">length</span><span class="o">;</span> <span class="n">i</span><span class="o">++)</span> <span class="o">{</span>
            <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">arrayObj</span><span class="o">[</span><span class="n">i</span><span class="o">]);</span>
        <span class="o">}</span>

        <span class="nc">ArrayList</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">&gt;</span> <span class="n">al</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">ArrayList</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">&gt;();</span> <span class="c1">//&lt;&gt;는 genetic</span>
        <span class="n">al</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="s">"one"</span><span class="o">);</span> <span class="c1">// object Type</span>
        <span class="n">al</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="s">"two"</span><span class="o">);</span>
        <span class="n">al</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="s">"three"</span><span class="o">);</span>
        <span class="k">for</span> <span class="o">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="o">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">al</span><span class="o">.</span><span class="na">size</span><span class="o">();</span> <span class="n">i</span><span class="o">++)</span> <span class="o">{</span>
            <span class="nc">String</span> <span class="n">value</span> <span class="o">=</span> <span class="n">al</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="n">i</span><span class="o">);</span>
            <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">value</span><span class="o">);</span>
        <span class="o">}</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<h3 id="2-collections-framework-전체적인-구성">2. Collections framework 전체적인 구성</h3>

<p>이 글은 아래의 강의를 보고 작성한 포스트 입니다.</p>

<ul>
  <li><a href="https://www.youtube.com/watch?v=E_WMaPuY_oA&amp;t=21s">Java : Collections framework</a></li>
</ul>

<h4 id="collections-framework-란">collections framework 란?</h4>

<ul>
  <li>Collection
    <ul>
      <li>Set
        <ul>
          <li>HashSet</li>
          <li>LinkedHashSet</li>
          <li>TreeSet</li>
        </ul>
      </li>
      <li>List
        <ul>
          <li>ArrayList</li>
          <li>Vector</li>
          <li>LinkedList</li>
        </ul>
      </li>
      <li>Queue
        <ul>
          <li>PriorotyQueue</li>
        </ul>
      </li>
    </ul>
  </li>
  <li>Map
    <ul>
      <li>SortedMap
        <ul>
          <li>TreeMap</li>
        </ul>
      </li>
      <li>Hashtable</li>
      <li>LinkedHashMap</li>
      <li>HashMap</li>
    </ul>
  </li>
</ul>

<h3 id="3-list와-set의-차이점">3. List와 Set의 차이점</h3>

<p>이 글은 아래의 강의를 보고 작성한 포스트 입니다.</p>

<ul>
  <li><a href="https://www.youtube.com/watch?v=c_3CN5Chy54&amp;t=3s">Java : Collections framework</a></li>
</ul>

<h4 id="hashset">HashSet</h4>

<p>HashSet 사용법</p>

<ul>
  <li>HashSet에 1,2,3을 저장</li>
</ul>

<hr />

<h4 id="실습코드-1">실습코드</h4>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">package</span> <span class="nn">set</span><span class="o">;</span>

<span class="kn">import</span> <span class="nn">java.util.HashSet</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.util.Iterator</span><span class="o">;</span>

<span class="kd">public</span> <span class="kd">class</span> <span class="nc">SetDemo</span> <span class="o">{</span>
    <span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="nc">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>
        <span class="nc">HashSet</span><span class="o">&lt;</span><span class="nc">Integer</span><span class="o">&gt;</span> <span class="no">A</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">HashSet</span><span class="o">&lt;</span><span class="nc">Integer</span><span class="o">&gt;();</span>
        <span class="no">A</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="mi">1</span><span class="o">);</span>
        <span class="no">A</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="mi">2</span><span class="o">);</span>
        <span class="no">A</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="mi">3</span><span class="o">);</span>
        <span class="c1">// A HashSet안에 1,2,3 이라는 값이 들어감</span>

        <span class="nc">Iterator</span> <span class="n">hi</span> <span class="o">=</span> <span class="o">(</span><span class="nc">Iterator</span><span class="o">)</span> <span class="no">A</span><span class="o">.</span><span class="na">iterator</span><span class="o">();</span>
        <span class="k">while</span><span class="o">(</span><span class="n">hi</span><span class="o">.</span><span class="na">hasNext</span><span class="o">()){</span>
            <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">hi</span><span class="o">.</span><span class="na">next</span><span class="o">());</span> <span class="c1">// 1 2 3 출력됨</span>
        <span class="o">}</span>

    <span class="o">}</span>
<span class="o">}</span>

</code></pre></div></div>

<ul>
  <li>HashSet에 1,1,2,2,3,3을 저장</li>
</ul>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">package</span> <span class="nn">set</span><span class="o">;</span>

<span class="kn">import</span> <span class="nn">java.util.HashSet</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.util.Iterator</span><span class="o">;</span>

<span class="kd">public</span> <span class="kd">class</span> <span class="nc">SetDemo</span> <span class="o">{</span>
    <span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="nc">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>
        <span class="nc">HashSet</span><span class="o">&lt;</span><span class="nc">Integer</span><span class="o">&gt;</span> <span class="no">A</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">HashSet</span><span class="o">&lt;</span><span class="nc">Integer</span><span class="o">&gt;();</span>
        <span class="no">A</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="mi">1</span><span class="o">);</span>
        <span class="no">A</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="mi">1</span><span class="o">);</span>
        <span class="no">A</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="mi">2</span><span class="o">);</span>
        <span class="no">A</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="mi">2</span><span class="o">);</span>
        <span class="no">A</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="mi">3</span><span class="o">);</span>
        <span class="no">A</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="mi">3</span><span class="o">);</span>
        <span class="c1">// A HashSet안에 1,2,3 이라는 값이 들어감</span>

        <span class="nc">Iterator</span> <span class="n">hi</span> <span class="o">=</span> <span class="o">(</span><span class="nc">Iterator</span><span class="o">)</span> <span class="no">A</span><span class="o">.</span><span class="na">iterator</span><span class="o">();</span>
        <span class="k">while</span><span class="o">(</span><span class="n">hi</span><span class="o">.</span><span class="na">hasNext</span><span class="o">()){</span>
            <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">hi</span><span class="o">.</span><span class="na">next</span><span class="o">());</span> <span class="c1">// 1 2 3 출력됨</span>
        <span class="o">}</span>

    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<ul>
  <li>ArrayList에 1,1,2,2,3,3을 저장</li>
</ul>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">package</span> <span class="nn">set</span><span class="o">;</span>

<span class="kn">import</span> <span class="nn">java.util.ArrayList</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.util.HashSet</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.util.Iterator</span><span class="o">;</span>

<span class="kd">public</span> <span class="kd">class</span> <span class="nc">SetDemo</span> <span class="o">{</span>
    <span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="nc">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>
        <span class="nc">ArrayList</span><span class="o">&lt;</span><span class="nc">Integer</span><span class="o">&gt;</span> <span class="no">A</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">ArrayList</span><span class="o">&lt;&gt;();</span>
        <span class="no">A</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="mi">1</span><span class="o">);</span>
        <span class="no">A</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="mi">1</span><span class="o">);</span>
        <span class="no">A</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="mi">2</span><span class="o">);</span>
        <span class="no">A</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="mi">2</span><span class="o">);</span>
        <span class="no">A</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="mi">3</span><span class="o">);</span>
        <span class="no">A</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="mi">3</span><span class="o">);</span>
        <span class="c1">// A ArrayList안에 1,2,3 이라는 값이 들어감</span>

        <span class="nc">Iterator</span> <span class="n">hi</span> <span class="o">=</span> <span class="o">(</span><span class="nc">Iterator</span><span class="o">)</span> <span class="no">A</span><span class="o">.</span><span class="na">iterator</span><span class="o">();</span>
        <span class="k">while</span><span class="o">(</span><span class="n">hi</span><span class="o">.</span><span class="na">hasNext</span><span class="o">()){</span>
            <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">hi</span><span class="o">.</span><span class="na">next</span><span class="o">());</span> <span class="c1">// 1 1 2 2 3 3 출력됨</span>
        <span class="o">}</span>

    <span class="o">}</span>
<span class="o">}</span>

</code></pre></div></div>

<p><strong>HashSet</strong>은 중복저장이 불가하지만 <strong>ArrayList</strong>는 중복저장이 가능하다.</p>

<h3 id="4-set이란">4. Set이란?</h3>

<p>이 글은 아래의 강의를 보고 작성한 포스트 입니다.</p>

<ul>
  <li><a href="https://www.youtube.com/watch?v=if3ojZRsGXo">Java : Collections framework</a></li>
</ul>

<h4 id="집합과-set">집합과 Set</h4>

<ul>
  <li>수학의 집합과 Set은 동일하다.</li>
  <li>집합 안의 값들은 각각 고유하다.</li>
  <li>Set 안의 값들은 각각 고유하다.</li>
  <li>List는 순서대로 저장되지만 (순서가 보장되지만) Set은 순서가 보장되지 않는다.</li>
</ul>

<h4 id="containsall">containsAll()</h4>

<ul>
  <li>A.containsAll(B) -&gt; B는 A의 부분 집합이다. (A가 B의 모든 값을 가지고 있다)</li>
  <li>A.containsAll(C) -&gt; C는 A의 부분 집합이다. (A가 C의 모든 값을 가지고 있다)</li>
</ul>

<h4 id="addall">addAll()</h4>

<ul>
  <li>A.addAll(B) -&gt; A와 B의 합집합 (B를 A에 더한다)</li>
</ul>

<h4 id="retainall">retainAll()</h4>

<ul>
  <li>A.retainAll() -&gt; A와 B의 교집합 (A,B 모두에 있는 값)</li>
</ul>

<h4 id="removeall">removeAll()</h4>

<ul>
  <li>A.removeAll() -&gt; A와 B의 차집합 (A - B)</li>
</ul>

<hr />

<h4 id="실습코드-2">실습코드</h4>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">package</span> <span class="nn">set</span><span class="o">;</span>

<span class="kn">import</span> <span class="nn">java.util.HashSet</span><span class="o">;</span>

<span class="kd">public</span> <span class="kd">class</span> <span class="nc">SetDemo2</span> <span class="o">{</span>
    <span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="nc">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>
        <span class="nc">HashSet</span><span class="o">&lt;</span><span class="nc">Integer</span><span class="o">&gt;</span> <span class="no">A</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">HashSet</span><span class="o">&lt;&gt;();</span>
        <span class="no">A</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="mi">1</span><span class="o">);</span>
        <span class="no">A</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="mi">2</span><span class="o">);</span>
        <span class="no">A</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="mi">3</span><span class="o">);</span>
        <span class="c1">// A에 1, 2, 3 추가</span>

        <span class="nc">HashSet</span><span class="o">&lt;</span><span class="nc">Integer</span><span class="o">&gt;</span> <span class="no">B</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">HashSet</span><span class="o">&lt;&gt;();</span>
        <span class="no">B</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="mi">3</span><span class="o">);</span>
        <span class="no">B</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="mi">4</span><span class="o">);</span>
        <span class="no">B</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="mi">5</span><span class="o">);</span>
        <span class="c1">// B에 3, 4, 5 추가</span>

        <span class="nc">HashSet</span><span class="o">&lt;</span><span class="nc">Integer</span><span class="o">&gt;</span> <span class="no">C</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">HashSet</span><span class="o">&lt;&gt;();</span>
        <span class="no">C</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="mi">1</span><span class="o">);</span>
        <span class="no">C</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="mi">2</span><span class="o">);</span>
        <span class="c1">// C에 1, 2 추가</span>

        <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="no">A</span><span class="o">.</span><span class="na">containsAll</span><span class="o">(</span><span class="no">B</span><span class="o">));</span> <span class="c1">// false</span>
        <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="no">A</span><span class="o">.</span><span class="na">containsAll</span><span class="o">(</span><span class="no">C</span><span class="o">));</span> <span class="c1">// true</span>
</code></pre></div></div>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code>        <span class="no">A</span><span class="o">.</span><span class="na">addAll</span><span class="o">(</span><span class="no">B</span><span class="o">);</span> <span class="c1">// B를 A에 add</span>
        <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="no">A</span><span class="o">);</span> <span class="c1">// [1, 2, 3, 4, 5]가 출력됨</span>
</code></pre></div></div>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code>        <span class="no">A</span><span class="o">.</span><span class="na">retainAll</span><span class="o">(</span><span class="no">B</span><span class="o">);</span> <span class="c1">// A와 B의 교집합</span>
        <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="no">A</span><span class="o">);</span> <span class="c1">// [3]이 출력됨</span>
</code></pre></div></div>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code>        <span class="no">A</span><span class="o">.</span><span class="na">removeAll</span><span class="o">(</span><span class="no">B</span><span class="o">);</span> <span class="c1">// A - B (A와 B의 차집합)</span>
        <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="no">A</span><span class="o">)</span><span class="n">ㄴ</span><span class="o">;</span> <span class="c1">// [1, 2]가 출력됨</span>
    <span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>

<h3 id="5-collection-interface">5. Collection interface</h3>

<p>이 글은 아래의 강의를 보고 작성한 포스트 입니다.</p>

<ul>
  <li><a href="https://www.youtube.com/watch?v=rHPaEJmfa98">Java : Collections framework</a></li>
</ul>

<h4 id="컬렉션과-인터페이스">컬렉션과 인터페이스</h4>

<ul>
  <li>Collection, List, Set : 인터페이스</li>
  <li>HashSet, ArrayList : 클래스</li>
</ul>

<h4 id="index-api">index API</h4>

<ul>
  <li>
    <p><strong>List</strong>는 순서가 있음 -&gt; <strong>index</strong>(인덱스)를 이용해 접근가능</p>

    <ul>
      <li>Object get/set(int <strong>index</strong>)</li>
      <li>Object set(int <strong>index</strong>, Object element)</li>
      <li>void add(int <strong>index</strong>, Object element)</li>
    </ul>
  </li>
  <li>
    <p>반면에 <strong>Set</strong>은 순서가 없음 -&gt; 인덱스를 이용해 접근 불가</p>
    <ul>
      <li>위의 <strong>get/set/add</strong> 등을 사용하지 않음</li>
    </ul>
  </li>
</ul>

<h3 id="6-iterator">6. iterator</h3>

<p>이 글은 아래의 강의를 보고 작성한 포스트 입니다.</p>

<ul>
  <li><a href="https://www.youtube.com/watch?v=DQN32cBaUEE">Java : Collections framework</a></li>
</ul>

<h4 id="iterator">iterator()</h4>

<p>이터레이터 메소드: 반복자</p>

<ul>
  <li>이터레이터는 <strong>Collection 인터페이스</strong>
    <ul>
      <li>HashSet, ArrayList, Collection에서 모두 사용가능</li>
    </ul>
  </li>
</ul>

<h4 id="hasnext">hasNext()</h4>

<ul>
  <li>이터레이터 안에 값이 있는지 확인.</li>
  <li>있으면 <strong>True</strong> 없으면 <strong>False</strong></li>
</ul>

<h4 id="next">next()</h4>

<ul>
  <li>이터레이터 안의 값을 리턴 후 삭제.
    <ul>
      <li>이터레이터 안의 값이 삭제 되는 것.</li>
      <li>이터레이터 안의 값을 삭제한다고 해서 오리지날 값이 사라지는 것은 아님.</li>
    </ul>
  </li>
</ul>

<hr />

<h4 id="실습코드-3">실습코드</h4>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">package</span> <span class="nn">set</span><span class="o">;</span>

<span class="kn">import</span> <span class="nn">java.util.HashSet</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.util.Iterator</span><span class="o">;</span>

<span class="kd">public</span> <span class="kd">class</span> <span class="nc">SetDemo</span> <span class="o">{</span>
    <span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="nc">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>
        <span class="nc">HashSet</span><span class="o">&lt;</span><span class="nc">Integer</span><span class="o">&gt;</span> <span class="no">A</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">HashSet</span><span class="o">&lt;</span><span class="nc">Integer</span><span class="o">&gt;();</span>
<span class="c1">//        ArrayList&lt;Integer&gt; A = new ArrayList&lt;Integer&gt;(); // arrayList 가능</span>
<span class="c1">//        Collection&lt;Integer&gt; A = new HashSet&lt;Integer&gt;(); // collection 가능</span>
        <span class="no">A</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="mi">1</span><span class="o">);</span>
        <span class="no">A</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="mi">2</span><span class="o">);</span>
        <span class="no">A</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="mi">3</span><span class="o">);</span>

        <span class="nc">Iterator</span> <span class="n">hi</span> <span class="o">=</span> <span class="no">A</span><span class="o">.</span><span class="na">iterator</span><span class="o">();</span> <span class="c1">// hi라는 이터레이터 생성 후 A의 데이터를 hi에 저장</span>
        <span class="k">while</span><span class="o">(</span><span class="n">hi</span><span class="o">.</span><span class="na">hasNext</span><span class="o">()){</span> <span class="c1">// hi에 값이 있으면 실행</span>
            <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">hi</span><span class="o">.</span><span class="na">next</span><span class="o">());</span> <span class="c1">// 현재의 값을 출력 후 삭제하고 다음으로 넘어감</span>
        <span class="o">}</span>
    <span class="o">}</span>
<span class="o">}</span>

</code></pre></div></div>

<h3 id="7-map의-기본-사용법-12">7. Map의 기본 사용법 (1/2)</h3>

<p>이 글은 아래의 강의를 보고 작성한 포스트 입니다.</p>

<ul>
  <li><a href="https://www.youtube.com/watch?v=Jg7x2XlteWk">Java : Collections framework</a></li>
</ul>

<h4 id="map">Map</h4>

<p>중간 점검</p>

<ul>
  <li>List
    <ul>
      <li>데이터가 입력되면 순서대로 (0~n) 데이터가 추가됨</li>
    </ul>
  </li>
  <li>Set
    <ul>
      <li>데이터가 입력되면 데이터가 순서와 상관없이, 중복 없이 추가됨</li>
    </ul>
  </li>
  <li><strong>Map</strong>
    <ul>
      <li>데이터가 입력되면 “key : value” 형태로 추가됨</li>
    </ul>
  </li>
</ul>

<blockquote>
  <p>key 값은 중복될 수 없지만 value 값은 중복을 허용함</p>
</blockquote>

<h4 id="실습코드-4">실습코드</h4>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">package</span> <span class="nn">map</span><span class="o">;</span>

<span class="kn">import</span> <span class="nn">java.util.HashMap</span><span class="o">;</span>

<span class="kd">public</span> <span class="kd">class</span> <span class="nc">MapDemo</span> <span class="o">{</span>
    <span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="nc">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>
        <span class="nc">HashMap</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">,</span> <span class="nc">Integer</span><span class="o">&gt;</span> <span class="n">a</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">HashMap</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">,</span> <span class="nc">Integer</span><span class="o">&gt;();</span>
        <span class="c1">// genetic을 통해 key 값과 value 값의 데이터 타입을 지정</span>

        <span class="n">a</span><span class="o">.</span><span class="na">put</span><span class="o">(</span><span class="s">"one"</span><span class="o">,</span> <span class="mi">1</span><span class="o">);</span> <span class="c1">// key: "one", value: 1</span>
        <span class="n">a</span><span class="o">.</span><span class="na">put</span><span class="o">(</span><span class="s">"two"</span><span class="o">,</span> <span class="mi">2</span><span class="o">);</span>
        <span class="n">a</span><span class="o">.</span><span class="na">put</span><span class="o">(</span><span class="s">"three"</span><span class="o">,</span> <span class="mi">3</span><span class="o">);</span>
        <span class="n">a</span><span class="o">.</span><span class="na">put</span><span class="o">(</span><span class="s">"four"</span><span class="o">,</span> <span class="mi">4</span><span class="o">);</span>

        <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">a</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="s">"one"</span><span class="o">));</span> <span class="c1">// 1</span>
        <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">a</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="s">"two"</span><span class="o">));</span> <span class="c1">// 2</span>
        <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">a</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="s">"three"</span><span class="o">));</span> <span class="c1">// 3</span>

    <span class="o">}</span>
<span class="o">}</span>

</code></pre></div></div>

<h3 id="8-map의-기본-사용법-22">8. Map의 기본 사용법 (2/2)</h3>

<p>이 글은 아래의 강의를 보고 작성한 포스트 입니다.</p>

<ul>
  <li><a href="https://www.youtube.com/watch?v=7goT8ErUFgU">Java : Collections framework</a></li>
</ul>

<h4 id="map의-반복-처리방법-1">Map의 반복 처리방법 1</h4>

<p><strong>iteratorUsingForEach(a)</strong></p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    <span class="c1">// 반복 처리방법 1</span>
    <span class="kd">static</span> <span class="kt">void</span> <span class="nf">iteratorUsingForEach</span><span class="o">(</span><span class="nc">HashMap</span> <span class="n">map</span><span class="o">){</span> <span class="c1">// a가 map으로 들어옴</span>
        <span class="nc">Set</span><span class="o">&lt;</span><span class="nc">Map</span><span class="o">.</span><span class="na">Entry</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">,</span> <span class="nc">Integer</span><span class="o">&gt;&gt;</span> <span class="n">entries</span> <span class="o">=</span> <span class="n">map</span><span class="o">.</span><span class="na">entrySet</span><span class="o">();</span>
        <span class="k">for</span> <span class="o">(</span><span class="nc">Map</span><span class="o">.</span><span class="na">Entry</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">,</span> <span class="nc">Integer</span><span class="o">&gt;</span> <span class="n">entry</span> <span class="o">:</span> <span class="n">entries</span><span class="o">)</span> <span class="o">{</span>
            <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">entry</span><span class="o">.</span><span class="na">getKey</span><span class="o">()</span> <span class="o">+</span> <span class="s">" : "</span> <span class="o">+</span> <span class="n">entry</span><span class="o">.</span><span class="na">getValue</span><span class="o">());</span>
        <span class="o">}</span>
    <span class="o">}</span>

</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">Set&lt;Map.Entry&lt;String, Integer&gt;&gt; entries = map.entrySet();</code></p>

<ul>
  <li>
    <p><code class="language-plaintext highlighter-rouge">map.entrySet()</code></p>

    <ul>
      <li>map의 key, value 쌍 전체를 set 컨테이너(<code class="language-plaintext highlighter-rouge">Set&lt;Map.Entry&lt;K,V&gt;&gt;</code>) 형태로 반환</li>
    </ul>
  </li>
  <li>
    <p><code class="language-plaintext highlighter-rouge">Set&lt;Map.Entry&lt;String, Integer&gt;&gt; entries</code></p>

    <ul>
      <li>반환된 Set의 각 요소(Entry)는 key와 value를 담고 있는 Map.Entry 객체</li>
      <li>
        <p>Set 전체가 Map.Entry들의 집합</p>
      </li>
      <li>Entry 안의 getKey와 getValue가 Map의 Key, Value를 가져와서 entries 안에 저장
        <ul>
          <li>entries안의 데이터 타입은 Map.Entry</li>
          <li>entries의 테이터 타입은 Set</li>
        </ul>
      </li>
    </ul>
  </li>
</ul>

<p><code class="language-plaintext highlighter-rouge">for-each 문</code></p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">for (Map.Entry&lt;String, Integer&gt; entry : entries)</code>
    <ul>
      <li>entries (Set)에 담긴 각각의 key-value 쌍 (Map.Entry)에 대해 반복하며 루프를 돔</li>
    </ul>
  </li>
</ul>

<h4 id="map의-반복-처리방법-2">Map의 반복 처리방법 2</h4>

<p><strong>iteratorUsingIterator(a)</strong></p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code>     <span class="c1">// 반복 처리방법 2</span>
    <span class="kd">static</span> <span class="kt">void</span> <span class="nf">iteratorUsingIterator</span><span class="o">(</span><span class="nc">HashMap</span> <span class="n">map</span><span class="o">){</span>
        <span class="nc">Set</span><span class="o">&lt;</span><span class="nc">Map</span><span class="o">.</span><span class="na">Entry</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">,</span> <span class="nc">Integer</span><span class="o">&gt;&gt;</span> <span class="n">entries</span> <span class="o">=</span> <span class="n">map</span><span class="o">.</span><span class="na">entrySet</span><span class="o">();</span>
        <span class="nc">Iterator</span><span class="o">&lt;</span><span class="nc">Map</span><span class="o">.</span><span class="na">Entry</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">,</span> <span class="nc">Integer</span><span class="o">&gt;&gt;</span> <span class="n">i</span> <span class="o">=</span> <span class="n">entries</span><span class="o">.</span><span class="na">iterator</span><span class="o">();</span>
        <span class="k">while</span> <span class="o">(</span><span class="n">i</span><span class="o">.</span><span class="na">hasNext</span><span class="o">())</span> <span class="o">{</span>
            <span class="nc">Map</span><span class="o">.</span><span class="na">Entry</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">,</span> <span class="nc">Integer</span><span class="o">&gt;</span> <span class="n">entry</span> <span class="o">=</span> <span class="n">i</span><span class="o">.</span><span class="na">next</span><span class="o">();</span>
            <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">entry</span><span class="o">.</span><span class="na">getKey</span><span class="o">()</span> <span class="o">+</span> <span class="s">" : "</span> <span class="o">+</span> <span class="n">entry</span><span class="o">.</span><span class="na">getValue</span><span class="o">());</span>
        <span class="o">}</span>
    <span class="o">}</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">Iterator&lt;Map.Entry&lt;String, Integer&gt;&gt; i = entries.iterator();</code></p>

<ul>
  <li>entries는 Set이기 때문에 iterator()를 통해 반복할 수 있는 반복자를 얻어 낼 수 있음</li>
</ul>

<p><code class="language-plaintext highlighter-rouge">while (i.hasNext()) {</code></p>

<ul>
  <li>Iterator안에 반복할 데이터가 있는지 확인, 있으면 while문 시작</li>
</ul>

<p><code class="language-plaintext highlighter-rouge">Map.Entry&lt;String, Integer&gt; entry = i.next();</code></p>

<ul>
  <li>Iterator안에 저장되어있는 값을 하나씩 꺼내서 entry에 저장</li>
</ul>

<p><code class="language-plaintext highlighter-rouge">System.out.println(entry.getKey() + " : " + entry.getValue()); }</code></p>

<h4 id="실습코드-5">실습코드</h4>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">package</span> <span class="nn">map</span><span class="o">;</span>

<span class="kn">import</span> <span class="nn">java.util.HashMap</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.util.Iterator</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.util.Map</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.util.Set</span><span class="o">;</span>

<span class="kd">public</span> <span class="kd">class</span> <span class="nc">MapDemo2</span> <span class="o">{</span>
    <span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="nc">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>
        <span class="nc">HashMap</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">,</span> <span class="nc">Integer</span><span class="o">&gt;</span> <span class="n">a</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">HashMap</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">,</span> <span class="nc">Integer</span><span class="o">&gt;();</span>
        <span class="n">a</span><span class="o">.</span><span class="na">put</span><span class="o">(</span><span class="s">"one"</span><span class="o">,</span> <span class="mi">1</span><span class="o">);</span> <span class="c1">// key: "one", value: 1</span>
        <span class="n">a</span><span class="o">.</span><span class="na">put</span><span class="o">(</span><span class="s">"two"</span><span class="o">,</span> <span class="mi">2</span><span class="o">);</span>
        <span class="n">a</span><span class="o">.</span><span class="na">put</span><span class="o">(</span><span class="s">"three"</span><span class="o">,</span> <span class="mi">3</span><span class="o">);</span>
        <span class="n">a</span><span class="o">.</span><span class="na">put</span><span class="o">(</span><span class="s">"four"</span><span class="o">,</span> <span class="mi">4</span><span class="o">);</span>

        <span class="c1">// 반복 처리방법 1</span>
        <span class="n">iteratorUsingForEach</span><span class="o">(</span><span class="n">a</span><span class="o">);</span>

        <span class="c1">// 반복 처리방법 2</span>
        <span class="n">iteratorUsingIterator</span><span class="o">(</span><span class="n">a</span><span class="o">);</span>
    <span class="o">}</span>

    <span class="c1">// 반복 처리방법 1</span>
    <span class="kd">static</span> <span class="kt">void</span> <span class="nf">iteratorUsingForEach</span><span class="o">(</span><span class="nc">HashMap</span> <span class="n">map</span><span class="o">){</span> <span class="c1">// a가 map으로 들어옴</span>
        <span class="nc">Set</span><span class="o">&lt;</span><span class="nc">Map</span><span class="o">.</span><span class="na">Entry</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">,</span> <span class="nc">Integer</span><span class="o">&gt;&gt;</span> <span class="n">entries</span> <span class="o">=</span> <span class="n">map</span><span class="o">.</span><span class="na">entrySet</span><span class="o">();</span>
        <span class="k">for</span> <span class="o">(</span><span class="nc">Map</span><span class="o">.</span><span class="na">Entry</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">,</span> <span class="nc">Integer</span><span class="o">&gt;</span> <span class="n">entry</span> <span class="o">:</span> <span class="n">entries</span><span class="o">)</span> <span class="o">{</span>
            <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">entry</span><span class="o">.</span><span class="na">getKey</span><span class="o">()</span> <span class="o">+</span> <span class="s">" : "</span> <span class="o">+</span> <span class="n">entry</span><span class="o">.</span><span class="na">getValue</span><span class="o">());</span>
        <span class="o">}</span>
    <span class="o">}</span>

    <span class="c1">// 반복 처리방법 2</span>
    <span class="kd">static</span> <span class="kt">void</span> <span class="nf">iteratorUsingIterator</span><span class="o">(</span><span class="nc">HashMap</span> <span class="n">map</span><span class="o">){</span>
        <span class="nc">Set</span><span class="o">&lt;</span><span class="nc">Map</span><span class="o">.</span><span class="na">Entry</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">,</span> <span class="nc">Integer</span><span class="o">&gt;&gt;</span> <span class="n">entries</span> <span class="o">=</span> <span class="n">map</span><span class="o">.</span><span class="na">entrySet</span><span class="o">();</span>
        <span class="nc">Iterator</span><span class="o">&lt;</span><span class="nc">Map</span><span class="o">.</span><span class="na">Entry</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">,</span> <span class="nc">Integer</span><span class="o">&gt;&gt;</span> <span class="n">i</span> <span class="o">=</span> <span class="n">entries</span><span class="o">.</span><span class="na">iterator</span><span class="o">();</span>
        <span class="k">while</span> <span class="o">(</span><span class="n">i</span><span class="o">.</span><span class="na">hasNext</span><span class="o">())</span> <span class="o">{</span>
            <span class="nc">Map</span><span class="o">.</span><span class="na">Entry</span><span class="o">&lt;</span><span class="nc">String</span><span class="o">,</span> <span class="nc">Integer</span><span class="o">&gt;</span> <span class="n">entry</span> <span class="o">=</span> <span class="n">i</span><span class="o">.</span><span class="na">next</span><span class="o">();</span>
            <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">entry</span><span class="o">.</span><span class="na">getKey</span><span class="o">()</span> <span class="o">+</span> <span class="s">" : "</span> <span class="o">+</span> <span class="n">entry</span><span class="o">.</span><span class="na">getValue</span><span class="o">());</span>
        <span class="o">}</span>
    <span class="o">}</span>
<span class="o">}</span>

</code></pre></div></div>

<h3 id="9-collections의-사용법과-정렬">9. Collections의 사용법과 정렬</h3>

<p>이 글은 아래의 강의를 보고 작성한 포스트 입니다.</p>

<ul>
  <li><a href="https://www.youtube.com/watch?v=twTt4IN94X0">Java : Collections framework</a></li>
</ul>

<h4 id="데이터-정렬">데이터 정렬</h4>

<p>a.compareTo(b)</p>

<ul>
  <li>a가 크면 양수, 같으면 0, a가 작으면 음수</li>
</ul>

<h4 id="실습코드-6">실습코드</h4>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">package</span> <span class="nn">collections</span><span class="o">;</span>

<span class="kn">import</span> <span class="nn">java.util.ArrayList</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.util.Collections</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.util.Iterator</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.util.List</span><span class="o">;</span>

<span class="kd">class</span> <span class="nc">Computer</span> <span class="kd">implements</span> <span class="nc">Comparable</span> <span class="o">{</span>
    <span class="kt">int</span> <span class="n">serial</span><span class="o">;</span>
    <span class="nc">String</span> <span class="n">owner</span><span class="o">;</span>
    <span class="nc">Computer</span><span class="o">(</span><span class="kt">int</span> <span class="n">serial</span><span class="o">,</span> <span class="nc">String</span> <span class="n">owner</span><span class="o">)</span> <span class="o">{</span>
        <span class="k">this</span><span class="o">.</span><span class="na">serial</span> <span class="o">=</span> <span class="n">serial</span><span class="o">;</span>
        <span class="k">this</span><span class="o">.</span><span class="na">owner</span> <span class="o">=</span> <span class="n">owner</span><span class="o">;</span>
    <span class="o">}</span>

    <span class="kd">public</span> <span class="kt">int</span> <span class="nf">compareTo</span><span class="o">(</span><span class="nc">Object</span> <span class="n">o</span><span class="o">)</span> <span class="o">{</span> <span class="c1">// Comparable은 compareTo 메소드를 구현하도록 강제함</span>
        <span class="k">return</span> <span class="k">this</span><span class="o">.</span><span class="na">serial</span> <span class="o">-</span> <span class="o">((</span><span class="nc">Computer</span><span class="o">)</span><span class="n">o</span><span class="o">).</span><span class="na">serial</span><span class="o">;</span>
        <span class="c1">// Computer 객체와 현재의 객체를 비교</span>
        <span class="c1">// 같다면 0, 현재의 객체가 크면 양수, 작으면 음수</span>
        <span class="c1">// a.serial - b.serial : a와 b의 serial 값을 비교</span>
    <span class="o">}</span>
    <span class="kd">public</span> <span class="nc">String</span> <span class="nf">toString</span><span class="o">(){</span>
        <span class="k">return</span> <span class="n">serial</span><span class="o">+</span><span class="s">" "</span><span class="o">+</span><span class="n">owner</span><span class="o">;</span>
    <span class="o">}</span>
<span class="o">}</span>

<span class="kd">public</span> <span class="kd">class</span> <span class="nc">CollectionsDemo</span> <span class="o">{</span>
    <span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="nc">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>
        <span class="nc">List</span><span class="o">&lt;</span><span class="nc">Computer</span><span class="o">&gt;</span> <span class="n">computers</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">ArrayList</span><span class="o">&lt;</span><span class="nc">Computer</span><span class="o">&gt;();</span>
        <span class="n">computers</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="k">new</span> <span class="nc">Computer</span><span class="o">(</span><span class="mi">500</span><span class="o">,</span> <span class="s">"egoing"</span><span class="o">));</span>
        <span class="n">computers</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="k">new</span> <span class="nc">Computer</span><span class="o">(</span><span class="mi">200</span><span class="o">,</span> <span class="s">"leezche"</span><span class="o">));</span>
        <span class="n">computers</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="k">new</span> <span class="nc">Computer</span><span class="o">(</span><span class="mi">3233</span><span class="o">,</span> <span class="s">"graphittie"</span><span class="o">));</span>

        <span class="nc">Iterator</span> <span class="n">i</span> <span class="o">=</span> <span class="n">computers</span><span class="o">.</span><span class="na">iterator</span><span class="o">();</span>
        <span class="c1">// 정렬 전</span>
        <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"before"</span><span class="o">);</span>
        <span class="k">while</span><span class="o">(</span><span class="n">i</span><span class="o">.</span><span class="na">hasNext</span><span class="o">()){</span>
            <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">i</span><span class="o">.</span><span class="na">next</span><span class="o">());</span> <span class="c1">// arrayList의 순서대로 출력됨</span>
        <span class="o">}</span>

        <span class="nc">Collections</span><span class="o">.</span><span class="na">sort</span><span class="o">(</span><span class="n">computers</span><span class="o">);</span>
        <span class="c1">// 정렬 후</span>
        <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"\nafter"</span><span class="o">);</span>
        <span class="n">i</span> <span class="o">=</span> <span class="n">computers</span><span class="o">.</span><span class="na">iterator</span><span class="o">();</span>
        <span class="k">while</span><span class="o">(</span><span class="n">i</span><span class="o">.</span><span class="na">hasNext</span><span class="o">()){</span>
            <span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">i</span><span class="o">.</span><span class="na">next</span><span class="o">());</span> <span class="c1">// serial num이 작은 순으로 출력됨</span>
        <span class="o">}</span>
    <span class="o">}</span>
<span class="o">}</span>

</code></pre></div></div>]]></content><author><name>김도연</name></author><category term="JAVA_study" /><category term="JAVA_study" /><category term="study" /><summary type="html"><![CDATA[생활코딩 강의 정리]]></summary></entry></feed>