<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>ariul.archive</title>
        <link>https://velog.io/</link>
        <description>정성과 진심을 담아 흔적을 기록하자💡</description>
        <lastBuildDate>Fri, 02 May 2025 07:23:14 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>ariul.archive</title>
            <url>https://velog.velcdn.com/images/ariul-dev/profile/5124452e-dc2f-454b-b05e-e6914a11a952/image.JPG</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. ariul.archive. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/ariul-dev" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[🤔 비개발 직군도 소프트웨어 공학을 알아야 할까요?]]></title>
            <link>https://velog.io/@ariul-dev/%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4-%EA%B3%B5%ED%95%99-%EC%89%BD%EA%B2%8C-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@ariul-dev/%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4-%EA%B3%B5%ED%95%99-%EC%89%BD%EA%B2%8C-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0</guid>
            <pubDate>Fri, 02 May 2025 07:23:14 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p><strong>기술을 아는 것과, 누구나 이해할 수 있도록 전달하는 건 다르다</strong>는 걸 깨달았습니다.
이 시리즈는 <strong>‘기술을 쉽게 전달하는 방법’을 고민하며 쓰는 저의 학습 기록</strong>입니다.
컴퓨터공학이라는 거대한 분야를 처음 접했을 때, 저는 각 개념이 왜 등장했고 어떻게 연결되는지가 가장 궁금했습니다. 그래서 이 시리즈는 단순한 정의나 기능 설명보다 맥락 중심의 흐름과 구조적 이해에 집중했습니다.
비전공자도 부담 없이 읽을 수 있도록 가능한 쉬운 언어와 비유를 사용했지만, 그만큼 설명 방식에 부족한 점이 있을 수 있습니다. 혹시 더 좋은 설명이나 보완 아이디어가 있다면, 댓글로 자유롭게 피드백 남겨주세요! 😊</p>
</blockquote>
<hr>
<h2 id="🤔-비개발-직군도-소프트웨어-공학을-알아야-할까요">🤔 비개발 직군도 소프트웨어 공학을 알아야 할까요?</h2>
<p>하나의 제품이 완성되어 사용자에게 전달되기까지, 기획자, 디자이너, 마케터, 개발자, 운영 등 다양한 직무가 함께 협업합니다. 각자 역할과 전문성이 분리되어 있는 만큼, ‘비개발 직군인데 소프트웨어 구조까지 알아야 하나?’라는 생각이 드는 건 자연스러운 일이죠.</p>
<p>하지만 이러한 기술적 구조를 <strong>서로 조금씩만 더 공유하고 이해하고 있어도</strong> 협업 과정에서 발생하는 커뮤니케이션 충돌을 훨씬 줄일 수 있습니다.</p>
<blockquote>
<p>“왜 이 기능은 구현에 시간이 오래 걸릴까?”
“이건 왜 안 된다고 할까?”
“저게 무슨 말일까?” </p>
</blockquote>
<p>이런 질문들이 반복되는 이유는, 서로의 업무 방식과 흐름을 충분히 공유하지 못했기 때문입니다.</p>
<p>소프트웨어 공학은 바로 이 간극을 좁히는 데 도움을 주는 사고의 틀입니다. 개발자만을 위한 기술이 아니라, 협업 전체를 구조화하는 설계도이죠. 기획부터 유지보수까지 모든 단계를 아우르는 이 구조를 우리는 <strong>소프트웨어 개발 생명주기(SDLC: Software Development Life Cycle)</strong>라고 부릅니다.</p>
<hr>
<h2 id="🧭-소프트웨어는-어떻게-만들어지는가-sdlc">🧭 소프트웨어는 어떻게 만들어지는가? (SDLC)</h2>
<p>SDLC는 보통 다음과 같은 순서로 이루어집니다.</p>
<blockquote>
<p>① 계획 → ② 요구 분석 → ③ 설계 → ④ 구현 → ⑤ 테스트 → ⑥ 배포 → ⑦ 유지보수</p>
</blockquote>
<h3 id="①-계획-단계">① 계획 단계</h3>
<p>계획 단계에서는 제품의 방향과 문제 정의를 구체화합니다. 마케팅, 영업, 기획자, PM 등 다양한 직군이 참여할 수 있으며, <code>&quot;이 기능이 정말 필요한지&quot;, &quot;시장성과 ROI(Return On Investment; 투자 대비 수익률)는 충분한지&quot;</code>를 판단합니다. 이 단계가 부족하면, 만들어놓고도 사용자가 쓰지 않는 기능이 될 수 있습니다.</p>
<h3 id="②-요구-분석">② 요구 분석</h3>
<p>요구 분석 단계에서는 기획자, 개발자, QA, PM 등 다양한 이해관계자가 함께 기능의 범위와 기술적 가능성을 검토합니다. <code>&quot;구현 가능한가? 예외 상황은 어떻게 처리할 것인가?&quot;</code> 등의 질문들이 이 시점에 명확히 정리되지 않으면, 개발자가 오해한 기능이 구현되거나 불필요한 커뮤니케이션이 반복됩니다.</p>
<h3 id="③-설계">③ 설계</h3>
<p>설계 단계에서는 개발자가 시스템 구조, 데이터베이스, 인터페이스 등 기술적 설계를 주도하고, 디자이너가 UI/UX 흐름을 설계합니다. 기획자는 이 모든 요소들의 연결성과 우선순위를 조율합니다. 구조와 흐름이 명확히 문서화되지 않으면, 구현 중에 연동 오류나 흐름 불일치로 인한 재작업이 발생합니다.</p>
<h3 id="④-구현">④ 구현</h3>
<p>구현 단계에서는 프론트엔드와 백엔드 개발자가 각자의 역할을 나눠 기능을 만들고, API(기능 간 데이터를 주고받게 해주는 연결 장치)로 서로 연동합니다. 이때 설계가 불명확하거나 요구사항이 중간에 바뀌면, 일정 지연이나 충돌이 잦아집니다.</p>
<h3 id="⑤-테스트">⑤ 테스트</h3>
<p>테스트 단계에서는 QA가 테스트 케이스에 따라 기능을 점검하고, 기획자와 디자이너는 실제 사용 흐름에서 문제가 없는지 확인합니다. 개발자도 단위 테스트 등 다양한 테스트를 수행합니다. 의도한 대로 작동하는지 확인하는 과정이며, 오류를 놓치면 사용자 불만이나 브랜드 신뢰도 저하로 이어질 수 있습니다.</p>
<h3 id="⑥-배포">⑥ 배포</h3>
<p>배포(Deployment) 단계에서는 개발이 완료된 소프트웨어를 실제 운영 환경에 이관하고, 사용자에게 공개합니다. 이 과정에서 배포 자동화, 롤백 전략 등 안정적인 서비스 전환을 위한 다양한 활동이 이루어집니다.</p>
<h3 id="⑦-유지보수">⑦ 유지보수</h3>
<p>유지보수 단계에서는 개발팀이 중심이 되어 버그 수정, 기능 개선, 성능 최적화 등 소프트웨어의 정상적 운영을 위한 다양한 활동을 수행합니다. CS, 영업, 운영팀 등은 사용자 피드백을 수집하고, 분석가는 서비스 데이터를 모니터링하며 문제 발생 시 원인을 추적합니다. 이 단계가 소홀하면 원인 추적이 어려워지고, 같은 문제가 반복되기 쉽습니다.</p>
<p>유지보수 단계에서는 CS와 영업, 운영팀이 사용자 피드백을 수집하고, 분석가는 서비스 데이터를 모니터링하며 문제 발생 시 원인을 추적합니다. 기획자와 개발자는 이를 바탕으로 기능을 수정하거나 확장하죠. 이 단계가 소홀하면 원인 추적이 어려워지고, 같은 문제가 반복되기 쉽습니다.</p>
<blockquote>
<p>📌 <strong>SDLC 단계별 정리</strong></p>
</blockquote>
<table>
<thead>
<tr>
<th>단계</th>
<th>핵심 활동 내용</th>
<th>실무 질문</th>
<th>판단 기준</th>
<th>실패 시 발생 문제</th>
</tr>
</thead>
<tbody><tr>
<td><strong>계획</strong></td>
<td>마케팅과 영업은 시장 인사이트를 공유하고, 기획자는 문제 정의와 방향 설정</td>
<td>이 기능은 사용자가 필요로 하는가?</td>
<td>시장성과 ROI 근거</td>
<td>만들었지만 사용되지 않음</td>
</tr>
<tr>
<td><strong>요구 분석</strong></td>
<td>기획자와 개발자가 기능 범위와 기술 가능성을 검토</td>
<td>어떤 기능이 필요한가? 예외 상황은?</td>
<td>예외 상황 포함 명세</td>
<td>오해된 기능 구현</td>
</tr>
<tr>
<td><strong>설계</strong></td>
<td>디자이너는 UX 흐름을, 개발자는 시스템 구조와 데이터 흐름을 도식화</td>
<td>데이터는 어디서 어떻게 움직이나?</td>
<td>도식화된 설계 문서</td>
<td>연동 오류 발생</td>
</tr>
<tr>
<td><strong>구현</strong></td>
<td>프론트엔드와 백엔드 개발자가 기능을 구현하고 API로 연동</td>
<td>누가, 무엇을, 어떤 기술로 구현하나?</td>
<td>기술 스택과 일정 정의</td>
<td>충돌, 병목, 일정 지연</td>
</tr>
<tr>
<td><strong>테스트</strong></td>
<td>QA는 테스트 케이스로 검증하고, 기획자와 디자이너도 실제 흐름을 점검</td>
<td>의도한 대로 동작하는가?</td>
<td>사용자 기준 테스트</td>
<td>사용자 불만, 오류</td>
</tr>
<tr>
<td><strong>배포</strong></td>
<td>운영 환경으로 소프트웨어 이관</td>
<td>배포 절차와 롤백 전략은?</td>
<td>배포 자동화, 안정성</td>
<td>서비스 중단 위험</td>
</tr>
<tr>
<td><strong>유지보수</strong></td>
<td>피드백 수집 → 문제 대응 및 기능 수정·확장</td>
<td>문제가 생기면 누가 대응하나?</td>
<td>로그와 대응 체계</td>
<td>문제 추적 어려움</td>
</tr>
<tr>
<td>👉 이처럼 SDLC는 단순히 개발자가 기능을 만드는 과정이 아니라, 모든 직군이 함께 설계하고 정리하는 협업 구조입니다.</td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody></table>
<hr>
<h2 id="🧱-개발-방법론은-협업하는-방식">🧱 개발 방법론은 협업하는 방식</h2>
<p><strong>SDLC</strong>는 ‘무엇을 언제 할 것인가’를 정의하는 구조라면,
<strong>개발 방법론</strong>은 ‘어떻게 함께 일할 것인가’를 정하는 전략입니다.
팀의 특성과 프로젝트 성격에 따라 다양한 방법론을 사용할 수 있어요.</p>
<p>아래는 대표적인 예시들입니다.</p>
<h3 id="폭포수">폭포수</h3>
<p>가장 전통적인 방식인 폭포수 모델은 <code>기획 → 설계 → 구현 → 테스트를 순차적으로 진행</code>합니다. 요구사항이 명확하고 변경이 거의 없는 프로젝트, 예를 들면 계약 기반 외주나 공공기관 과제 등에서 주로 사용됩니다. 일정 예측이 쉬운 장점이 있지만, 설계 초기에 실수가 있으면 전체에 영향을 주고, 중간에 방향을 바꾸기 어렵습니다.</p>
<h3 id="애자일">애자일</h3>
<p>애자일 방식은 기능을 작게 나누어 반복적으로 개발하며, 사용자 피드백을 받아가며 점진적으로 개선해 나가는 유연한 방식입니다. 스타트업, B2C 서비스 같이 불확실성이 큰 환경에 적합하고, 릴리즈 속도가 빠르며 변경에 강합니다. 다만 피드백이 잦으면 일정이 흔들리고, 문서화가 부족해질 수 있습니다.</p>
<h3 id="나선형">나선형</h3>
<p>나선형 모델은 위험 요소를 식별하고 통제하면서 반복 개발을 진행하는 전략적인 방식입니다. 금융 시스템이나 보안, ERP 같은 대형 시스템에서 리스크를 최소화하는 데 유리하지만, 관리 비용이 크고 속도가 느릴 수 있습니다.</p>
<h3 id="프로토타이핑">프로토타이핑</h3>
<p>프로토타이핑은 먼저 간단한 시제품(Prototype)을 만들어 사용자 반응을 살펴보고, 그 결과를 반영해 정식 제품을 완성하는 방식입니다. UX 중심 기획이나 신사업 아이디어 검증에 자주 쓰이며, 빠르게 실험해볼 수 있는 장점이 있습니다.</p>
<p>참고: 프로토타이핑과 MVP(Minimum Viable Product)는 유사하지만, MVP는 최소 기능 제품을 시장에 출시해 반응을 검증하는 Lean Startup 개념이고, 프로토타이핑은 제품의 핵심 기능이나 UI/UX를 빠르게 실험하는 데 중점을 둡니다.</p>
<p>이 외에도 구조적 방법론, 객체지향 방법론, 컴포넌트 기반 방법론 등 다양한 개발 방법론이 존재합니다.</p>
<blockquote>
<p><strong>📌 개발 방법론 정리</strong></p>
</blockquote>
<table>
<thead>
<tr>
<th>방법론</th>
<th>핵심 개념</th>
<th>적합한 상황</th>
<th>장점</th>
<th>단점</th>
<th>실무 사례</th>
</tr>
</thead>
<tbody><tr>
<td><strong>폭포수</strong></td>
<td>계획→설계→구현→테스트의 순차적 개발</td>
<td>요구사항 명확, 변경 적음</td>
<td>일정 예측 쉬움, 문서 중심 협업</td>
<td>변경 어려움, 초기 실수 영향 큼</td>
<td>공공기관 과제, 외주</td>
</tr>
<tr>
<td><strong>애자일</strong></td>
<td>반복 개발, 빠른 피드백 기반 점진적 개선</td>
<td>불확실성이 크고 변화 많은 환경</td>
<td>빠른 릴리즈, 유연한 개선</td>
<td>문서 부족, 일정 혼란 가능성</td>
<td>스타트업, B2C</td>
</tr>
<tr>
<td><strong>나선형</strong></td>
<td>리스크 식별 및 통제 중심의 반복 개발</td>
<td>대형 시스템, 리스크 관리 필수</td>
<td>단계별 검토, 위험 최소화</td>
<td>도입 비용 크고 속도 느림</td>
<td>금융, 보안, ERP</td>
</tr>
<tr>
<td><strong>프로토타입</strong></td>
<td>시제품 제작 후 사용자 반응 기반 개선</td>
<td>초기 기획 검증, UX 중심</td>
<td>빠른 실험, 피드백 수렴</td>
<td>반복 낭비 위험</td>
<td>신사업 아이디어 검증, UI/UX 실험</td>
</tr>
</tbody></table>
<p>👉 개발 방법론은 단순히 개발자의 문제가 아니라 팀 전체의 리듬을 맞추는 장치입니다. “어떤 방식으로 함께 일할지”를 합의하는 기준이죠. </p>
<p>같은 기능이라도 애자일에서는 빠르게 출시하고 개선하는 데 의미를 두고, 폭포수에서는 처음부터 완성도 있게 마무리하는 데 초점을 둡니다. </p>
<p>따라서 팀이 어떤 방법론을 따르는지 명확히 공유하지 않고 공감대 없이 피드백만 주고받다 보면, 오히려 혼선과 갈등만 커질 수 있어요.</p>
<hr>
<h2 id="🧪-테스트는-qa만의-일이-아니다">🧪 테스트는 QA만의 일이 아니다</h2>
<p>기능이 완성됐다고 해서 끝난 게 아닙니다. 의도한 대로 작동하는지, 사용자 환경에서 문제가 없는지를 점검하는 <strong>테스트 단계</strong>가 필요합니다. 이 과정은 QA(Quality Assurance)만의 책임이 아니라, 기획자, 디자이너, 개발자, 마케터 등 모두가 함께 관여해야 합니다.</p>
<p>테스트 방식에도 종류가 있습니다.</p>
<p><strong>블랙박스 테스트</strong>는 코드 내부를 보지 않고 <strong>입력과 출력만 확인하는 방식</strong>으로, 사용자의 입장에서 “의도한 대로 동작하는지”를 확인합니다. 주로 QA가 주도하지만, 기획자나 개발자도 참여할 수 있습니다.</p>
<p>반면 <strong>화이트박스 테스트</strong>는 <strong>코드 흐름, 조건문, 반복문</strong> 등을 개발자가 직접 점검합니다. “이 if문이 정확히 작동할까?” 같은 <strong>로직 단위 확인</strong>이 중심입니다. 일부 조직에서는 자동화 도구를 활용해 QA가 일부 수행하기도 합니다.</p>
<p>또한, 최근에는 <strong>TDD (Test-Driven Development) 방식</strong>도 많이 논의됩니다. 기능 개발 전에 먼저 테스트 코드를 작성하고, 이를 통과할 수 있는 기능을 개발하는 방식입니다. 이 과정에서 테스트는 곧 기능 요구사항을 정의하는 문서 역할도 하게 되죠. TDD는 모든 조직에서 표준적으로 사용되는 것은 아니며, 팀의 문화와 프로젝트 특성에 따라 도입 여부가 달라집니다.</p>
<h3 id="🎯-실전-체크리스트-테스트는-누가-언제-무엇을">🎯 실전 체크리스트: 테스트는 누가, 언제, 무엇을?</h3>
<table>
<thead>
<tr>
<th>역할</th>
<th>책임</th>
</tr>
</thead>
<tbody><tr>
<td>기획자</td>
<td>기능 흐름 기준 테스트 항목 정리, 누락된 케이스 점검, 우선순위 조정</td>
</tr>
<tr>
<td>디자이너</td>
<td>인터랙션/상태 예외 상황 정의</td>
</tr>
<tr>
<td>개발자</td>
<td>단위 테스트, TDD 적용, 화이트박스 테스트</td>
</tr>
<tr>
<td>QA</td>
<td>전체 시나리오 기반 블랙박스 테스트</td>
</tr>
</tbody></table>
<hr>
<h2 id="🔧-유지보수는-기술이-아니라-지속-가능한-협업의-문제">🔧 유지보수는 ‘기술’이 아니라 ‘지속 가능한 협업’의 문제</h2>
<p>많은 사람들이 유지보수를 개발자만의 영역으로 생각하지만, 실제로는 조직 전체의 협업 전략이 더 중요합니다.</p>
<p>서비스가 오픈된 이후, 진짜 일은 그때부터 시작됩니다.</p>
<ul>
<li>CS팀은 사용자로부터 버그 제보를 받고,</li>
<li>분석가는 사용자 로그를 추적하며 문제를 파악하고,</li>
<li>마케터는 성과를 측정하고 유입 흐름을 분석하며,</li>
<li>기획자와 PM/PO는 피드백을 정리하고 우선순위를 다시 조정하죠.</li>
<li>개발팀은 실제 사용 상황을 반영해 기능을 수정하거나 확장합니다.</li>
</ul>
<h3 id="유지보수는-단순한-버그-수정이-아닙니다">유지보수는 단순한 ‘버그 수정’이 아닙니다.</h3>
<p>지속적인 협업, 문서화, 코드 일관성,그리고 사용자 피드백을 반영하는 체계까지 모두 포함돼요.</p>
<p>이걸 제대로 하지 않으면 이런 일이 반복됩니다</p>
<blockquote>
<p>“그 기능 고쳤는데, 왜 또 문제가 생기죠?”
“누가 수정했는지 모르겠어요.”
“왜 이 부분이 이렇게 되어 있는 거예요?”</p>
</blockquote>
<p>이런 문제들의 핵심 원인은 하나입니다.</p>
<p><strong>처음부터 유지보수를 고려한 구조가 아니었기 때문이에요.</strong></p>
<h3 id="🔍-유지보수에서-자주-발생하는-실무-문제들">🔍 유지보수에서 자주 발생하는 실무 문제들</h3>
<p>제품이 완성된 이후에도 소프트웨어는 계속 진화합니다.<br>하지만 아래와 같은 문제가 반복되는 경우가 많습니다.</p>
<table>
<thead>
<tr>
<th>상황</th>
<th>문제</th>
<th>원인</th>
</tr>
</thead>
<tbody><tr>
<td>기능 수정이 다른 기능 깨뜨림</td>
<td>의도치 않은 영향 발생</td>
<td>결합도 과다, 테스트 부족</td>
</tr>
<tr>
<td>버그 발생 후 원인 파악 어려움</td>
<td>추적 불가</td>
<td>로그/버전 관리 미비</td>
</tr>
<tr>
<td>같은 문제 반복 발생</td>
<td>개선 누적되지 않음</td>
<td>회고 및 문서화 부재</td>
</tr>
<tr>
<td>새 팀원 온보딩 비효율</td>
<td>설명 반복</td>
<td>문서 부족, 정리 안됨</td>
</tr>
</tbody></table>
<h3 id="✅-유지보수를-위한-핵심-협업-구조-5가지">✅ 유지보수를 위한 핵심 협업 구조 5가지</h3>
<p>지속 가능한 시스템 운영을 위해서는 아래와 같은 <strong>구조적 장치</strong>들이 필수입니다.</p>
<table>
<thead>
<tr>
<th>항목</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td><strong>문서화</strong></td>
<td>기능 정의서, API 명세, UI 흐름, DB 구조 등을 정리해 공유</td>
</tr>
<tr>
<td><strong>로그/모니터링</strong></td>
<td>문제 발생 지점을 추적할 수 있는 시스템 도입</td>
</tr>
<tr>
<td><strong>버전 관리 체계</strong></td>
<td>Git 브랜치 전략, 코드 리뷰와 Pull Request 기반 협업</td>
</tr>
<tr>
<td><strong>테스트 자동화</strong></td>
<td>코드 변경 시 자동 회귀 테스트로 릴리즈 안정성 확보</td>
</tr>
<tr>
<td><strong>정기 회고/이슈 공유</strong></td>
<td>문제 발생 원인과 개선 방안을 정리해 팀 전체에 공유 (Slack, Notion 등 활용)</td>
</tr>
</tbody></table>
<hr>
<h2 id="🏁-정리하며">🏁 정리하며</h2>
<p>앞서 살펴본 것처럼, 소프트웨어 공학은 요구분석, 설계, 구현, 테스트, 유지보수 등 소프트웨어의 전 생명주기를 체계적으로 다루는 학문입니다. </p>
<p>그래서 소프트웨어 공학은 개발자만을 위한 지식이 아니라,</p>
<p><strong>기획, 디자인, 개발, 마케팅, 데이터 분석, 운영 등 모든 직군이 같은 구조를 이해하고, 같은 방향을 바라보며 함께 일할 수 있도록</strong> 돕는 협업의 언어이자 설계도입니다.</p>
<p>누구나 자신의 역할에서 최선을 다하려면, 그 역할이 전체 흐름 안에서 어떤 위치에 있는지 알아야 하잖아요?</p>
<p>바로 그 구조적 사고의 틀이, 소프트웨어 공학인거죠.</p>
<hr>
<h2 id="➡️-next-데이터베이스-이야기로">➡️ Next: 데이터베이스 이야기로!</h2>
<p>기능을 설계하고 구현했다면,
이제는 그 기능이 데이터를 어떻게 저장하고, 꺼내고, 보호하는지 살펴볼 차례예요.</p>
<p>다음 편에서는 서비스의 심장, <strong>데이터베이스(Database)</strong> 에 대해 이야기해볼게요!😊</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[컴퓨터한테 말 거는 법]]></title>
            <link>https://velog.io/@ariul-dev/%EC%BB%B4%ED%93%A8%ED%84%B0%ED%95%9C%ED%85%8C-%EB%A7%90-%EA%B1%B0%EB%8A%94-%EB%B2%95</link>
            <guid>https://velog.io/@ariul-dev/%EC%BB%B4%ED%93%A8%ED%84%B0%ED%95%9C%ED%85%8C-%EB%A7%90-%EA%B1%B0%EB%8A%94-%EB%B2%95</guid>
            <pubDate>Thu, 10 Apr 2025 04:47:27 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p><strong>기술을 아는 것과, 누구나 이해할 수 있도록 전달하는 건 다르다</strong>는 걸 깨달았습니다.
이 시리즈는 <strong>‘기술을 쉽게 전달하는 방법’을 고민하며 쓰는 저의 학습 기록</strong>입니다.</p>
</blockquote>
<p>컴퓨터공학이라는 거대한 분야를 처음 접했을 때, 저는 각 개념이 왜 등장했고 어떻게 연결되는지가 가장 궁금했습니다. 그래서 이 시리즈는 단순한 정의나 기능 설명보다 맥락 중심의 흐름과 구조적 이해에 집중했습니다.</p>
<blockquote>
</blockquote>
<p>비전공자도 부담 없이 읽을 수 있도록 가능한 쉬운 언어와 비유를 사용했지만, 그만큼 설명 방식에 부족한 점이 있을 수 있습니다. 혹시 더 좋은 설명이나 보완 아이디어가 있다면, 댓글로 자유롭게 피드백 남겨주세요! 😊</p>
<hr>
<h2 id="💬-컴퓨터에게-어떻게-말을-걸-수-있을까">💬 컴퓨터에게 어떻게 말을 걸 수 있을까?</h2>
<p>– 기계어부터 파이썬까지, 프로그래밍 언어는 어떻게 사람 친화적으로 바뀌었을까?</p>
<p>우리는 컴퓨터에게 “이 문서 좀 열어줘”, “사진 저장해줘” 같은 명령을 내리면, 컴퓨터는 알아듣고 그대로 실행하죠.
하지만 사실 컴퓨터는 사람의 언어를 전혀 알아듣지 못합니다.
왜냐하면 컴퓨터는 오직 ‘켜짐(1)’과 ‘꺼짐(0)’이라는 전기 신호만 알아들을 수 있거든요.</p>
<p>이처럼 단순한 신호만 알아들을 수 있는 컴퓨터와, 
복잡한 언어를 사용하는 사람이 대화하기 위해선 서로를 이어주는 ‘언어’가 필요했습니다.
그리고 그 과정에서 프로그래밍 언어가 발전해왔습니다.</p>
<hr>
<h2 id="🤖-컴퓨터의-본래-언어-기계어">🤖 컴퓨터의 본래 언어, 기계어</h2>
<p>가장 처음에는 사람이 컴퓨터의 언어를 직접 배워야 했습니다.
그 언어의 이름은 바로 <strong>기계어(Machine Language)</strong>였죠.</p>
<p>기계어는 오직 0과 1로만 구성된 언어입니다.
프로그래머들은 <code>10110000 01100001</code>처럼 생긴 이진수 조합으로 컴퓨터에게 명령을 내려야 했어요.</p>
<p>이건 사실상 전기 회로에 직접 신호를 보내는 것과 비슷합니다.
“이 전선에 전기를 흐르게 해서 이 부품을 작동시켜라!” 같은 느낌이죠.</p>
<p>기계어는 컴퓨터 입장에서는 완벽했지만, 사람 입장에서는 너무 어렵고 비효율적이었어요.
한 줄의 명령을 작성하려면 수십 개의 0과 1을 손으로 입력해야 했고,
무엇보다 읽기도, 쓰기도, 유지하기도 너무 힘들었으니까요.</p>
<hr>
<h2 id="🔡-어셈블리어-사람이-조금-읽을-수-있게">🔡 어셈블리어: 사람이 조금 읽을 수 있게</h2>
<p>그래서 나온 것이 <strong>어셈블리어(Assembly Language)</strong>입니다.
기계어와 거의 1:1로 대응되지만, 0과 1 대신 사람이 이해할 수 있는 기호를 사용합니다.</p>
<p>예를 들어, <code>MOV A, 5</code>라고 쓰면 “A라는 공간에 숫자 5를 넣어라(MOV)”는 뜻이 되죠. 기계어보다는 훨씬 읽기 쉬운 ‘인간 친화적’ 기계어라고 할 수 있어요.</p>
<p>하지만 컴퓨터는 여전히 이걸 이해하지 못하기 때문에, <strong>어셈블러(Assembler)</strong>라는 프로그램이 필요합니다.</p>
<p>어셈블러는 어셈블리어 코드를 읽고, 컴퓨터가 이해할 수 있는 기계어로 변환합니다.
이 과정을 거쳐 실행 파일이 만들어지고, 우리가 프로그램을 실행하는 런타임(runtime) 시점에 운영체제를 통해 CPU가 이 파일을 받아 실행합니다.</p>
<p>런타임이란 말 그대로 프로그램이 실제로 ‘실행되고 있는 중’인 상태를 뜻해요.
예를 들어, 워드 파일을 더블클릭해서 열고 키보드로 글자를 입력하는 그 순간이 런타임입니다.</p>
<p>어셈블리어는 기계어보다 훨씬 사용하기 쉬워졌지만,
여전히 하드웨어 구조에 깊게 묶여 있는 저수준 언어였습니다.
컴퓨터마다 문법도 다르고, 하드웨어를 잘 이해하고 있어야 사용할 수 있었기 때문에
여전히 사람이 컴퓨터에 맞춰야 하는 언어였습니다.</p>
<hr>
<h2 id="🧑🏫-고급-언어-드디어-인간친화적으로">🧑‍🏫 고급 언어: 드디어 인간친화적으로</h2>
<p>그다음 등장한 것이 바로 <strong>고급 언어(High-Level Language)</strong>입니다.
이 언어들은 사람이 읽기 쉽게, 사람의 사고방식에 가깝게 설계된 언어예요.</p>
<p>고급 언어는 단순히 문법이 쉬운 걸 넘어서,
<strong>‘문제를 어떻게 바라보고 해결할지’</strong>에 대한 <strong>철학적 관점(패러다임)</strong>도 담고 있어요.
바로 이 패러다임에 따라 절차형, 객체지향, 함수형이라는 방식들이 등장했습니다.</p>
<h3 id="절차형-순서대로-하나씩">절차형: 순서대로 하나씩</h3>
<p>가장 오래된 방식인 절차형 프로그래밍은 문제 해결을 위해 작업 단계를 순서대로 작성합니다. 
“1단계 → 2단계 → 3단계”처럼 순차적으로 작업을 수행하는 구조죠.
이 방식은 구조가 단순하고 직관적이기 때문에 시스템의 기본을 다질 때 많이 사용되며, 대표적인 언어는 C 언어입니다.</p>
<blockquote>
<p><strong>💡 C 언어</strong></p>
</blockquote>
<p>하드웨어에 가까운 저수준 특성을 유지하면서도 사람이 논리적으로 구조화된 코드를 작성할 수 있게 만들어졌어요. 그래서 운영체제, 드라이버, 임베디드 시스템 같은 ‘시스템 가까이’에서 일하는 프로그램에 많이 사용됩니다.</p>
<hr>
<h3 id="객체지향-세상을-객체로-나누기">객체지향: 세상을 객체로 나누기</h3>
<p>복잡한 소프트웨어를 만들기 위해 등장한 개념이 바로 객체지향 프로그래밍입니다.</p>
<p>이 방식은 현실의 사물처럼 &#39;객체&#39; 단위로 프로그램을 구성합니다.
객체는 속성(데이터)과 행동(기능)을 함께 가지고 있고, 서로 간의 관계와 상호작용으로 프로그램이 구성돼요.</p>
<p>예를 들어 고양이 객체는 &#39;이름&#39;, &#39;색깔&#39; 같은 정보(속성)와 &#39;야옹하기&#39;, &#39;뛰기&#39; 같은 동작(행동)을 함께 가질 수 있어요.</p>
<p>현실을 코드로 표현하기 쉽고, 복잡한 프로그램도 명확하게 구조화할 수 있어서 협업, 유지보수, 대규모 시스템에 강한 설계 방식입니다.</p>
<p>Java나 Python은 이 방식을 잘 지원하는 대표적인 언어예요.</p>
<blockquote>
<p><strong>☕️ Java</strong></p>
</blockquote>
<p>Java는 &#39;한 번 작성하면 어디서나 실행된다&#39;는 철학으로 등장했습니다.
운영체제마다 실행 환경이 달랐던 문제를 JVM(Java Virtual Machine)이 해결해주면서, Java 프로그램은 Windows, Mac, Linux 등 어떤 환경에서도 동일하게 작동할 수 있게 되었습니다.</p>
<blockquote>
<p><strong>🐍 Python</strong></p>
</blockquote>
<p>Python은 문법이 매우 간결하고 직관적입니다. 코드를 보면 마치 영어 문장을 읽는 것 같아요.
덕분에 프로그래밍 입문자, 데이터 분석가, AI 연구자 등 다양한 분야에서 널리 쓰이고 있어요.
쉽지만 강력하고, 빠르게 실험하기 좋은 언어입니다.</p>
<hr>
<h3 id="함수형-입력이-같으면-결과도-같다">함수형: 입력이 같으면 결과도 같다</h3>
<p>마지막으로 소개할 패러다임은 함수형 프로그래밍입니다.
이 방식은 수학 함수처럼 입력이 같으면 항상 같은 결과가 나오는 구조를 따릅니다.</p>
<p>이 방식은 상태를 바꾸지 않고, 외부에 영향을 주지 않는 순수 함수로 구성되어 있어서 예측 가능성과 안정성이 필요한 분야에서 특히 강점을 가집니다.</p>
<p>JavaScript, Kotlin, Python 등도 함수형 스타일을 도입하고 있으며, 현대적인 소프트웨어 설계에서 점점 더 중요해지고 있어요.</p>
<hr>
<h3 id="🔄-어떻게-번역되냐에-따라-달라진다-컴파일-vs-인터프리트">🔄 어떻게 번역되냐에 따라 달라진다: 컴파일 vs 인터프리트</h3>
<p>이제 우리는 “출력해줘”, “계산해줘” 같은 일상 언어에 가까운 명령어로 프로그램을 작성할 수 있게 되었습니다. 하지만 이 코드들은 컴퓨터가 그대로는 이해할 수 없기 때문에,<br><strong>중간에서 이 코드를 기계어로 ‘번역’해주는 도구</strong>가 필요합니다. </p>
<p>그 도구가 바로 <strong>컴파일러</strong>와 <strong>인터프리터</strong>입니다.</p>
<p>컴파일(Compile) 방식은 전체 코드를 한꺼번에 기계어로 번역해서 하나의 실행 파일로 만들어줍니다. 대표적으로 C 언어가 이 방식을 따르며, 속도와 안정성에서 강점을 가집니다. 하지만 에러가 나면 전체를 다시 번역해야 해서 디버깅(debugging, 코드의 오류 또는 버그를 찾아서 수정하는 과정)이 불편할 수 있어요.</p>
<p>반면 인터프리트(Interpret) 방식은 코드를 한 줄씩 읽으면서 곧바로 실행합니다. Python이 대표적인 예인데요, 실험과 테스트에 유리하고 즉각적인 피드백을 받을 수 있다는 장점이 있습니다.<br>하지만 실행 속도는 컴파일 방식보다는 느릴 수 있죠.</p>
<blockquote>
<p><strong>✋ 여기서 잠깐</strong></p>
</blockquote>
<p>혹시 이 시리즈를 처음 보셨다면, 알려드릴 게 있어요.
우리는 <strong>컴퓨터를 하나의 회사</strong>, 그 중심에 있는 <strong>CPU를 CEO</strong>에 비유해 설명하고 있어요. CPU는 모든 계산과 실행을 지시하는 컴퓨터의 ‘두뇌’죠.</p>
<blockquote>
</blockquote>
<p>이 비유를 바탕으로 컴파일과 인터프리트를 다시 생각해보면,
<strong>컴파일은 설명서를 미리 인쇄해서 CEO 책상 위에 올려두는 방식</strong>이고,
<strong>인터프리트는 비서가 옆에서 실시간으로 읽어주는 방식</strong>이에요.</p>
<blockquote>
</blockquote>
<p>전자는 빠르고 안정적이며, 후자는 유연하고 즉각적인 반응이 가능하죠.</p>
<hr>
<h2 id="🏁-정리하며">🏁 정리하며</h2>
<p>프로그래밍 언어는 사람과 컴퓨터가 함께 일하기 위해 만들어진 공통 언어로 발전해왔어요.</p>
<p>처음엔 오직 전문가만 이해할 수 있는 <strong>기계어</strong>로 시작했고,<br>조금 더 읽을 수 있는 <strong>어셈블리어</strong>를 거쳐,<br>지금은 누구나 사용할 수 있는 <strong>인간 친화적인 고급 언어</strong>로 발전해 왔습니다.</p>
<p>그리고 이제 우리는 그 언어 위에 어떤 철학으로 문제를 풀고,
어떻게 협업하며 소프트웨어를 만들어나갈지를 함께 고민하게 되었습니다.</p>
<hr>
<h2 id="➡️-next-소프트웨어-공학-이야기로">➡️ Next: 소프트웨어 공학 이야기로!</h2>
<p>지금까지는 “컴퓨터에게 무엇을 시킬 수 있을까?”에 집중했다면,
이제는 “그 작업을 어떻게 함께 기획하고, 나눠서 만들고, 유지할 것인가?”를 살펴볼 차례입니다.</p>
<p><strong>소프트웨어 공학(Software Engineering)</strong>은
개발을 단순한 코딩이 아니라 기획, 협업, 설계, 품질관리까지 아우르는 하나의 종합 기술로 바라보는 분야입니다.</p>
<p>실제로 하나의 서비스가 어떤 기획 과정을 거쳐 탄생하고,
어떻게 팀원들이 나누어 개발하며,
문제가 생기면 어떻게 유지·보수하는지를 함께 알아볼 거예요.</p>
<p>다음 편도 기대해주세요! 😊</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[운영체제가 하는 일 쉽게 이해하기]]></title>
            <link>https://velog.io/@ariul-dev/%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C%EA%B0%80-%ED%95%98%EB%8A%94-%EC%9D%BC%EC%9D%84-%EC%89%BD%EA%B2%8C-%EC%9D%B4%ED%95%B4%ED%95%B4%EB%B3%B4%EC%9E%90</link>
            <guid>https://velog.io/@ariul-dev/%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C%EA%B0%80-%ED%95%98%EB%8A%94-%EC%9D%BC%EC%9D%84-%EC%89%BD%EA%B2%8C-%EC%9D%B4%ED%95%B4%ED%95%B4%EB%B3%B4%EC%9E%90</guid>
            <pubDate>Sat, 05 Apr 2025 13:40:11 GMT</pubDate>
            <description><![CDATA[<blockquote>
</blockquote>
<p><strong>기술을 아는 것과, 누구나 이해할 수 있도록 전달하는 건 다르다</strong>는 걸 깨달았습니다. 
이 시리즈는 <strong>‘기술을 쉽게 전달하는 방법’을 고민하며 쓰는 저의 학습 기록</strong>입니다.</p>
<blockquote>
</blockquote>
<p>컴퓨터공학이라는 거대한 분야를 처음 접했을 때, 저는 각 개념이 왜 등장했고 어떻게 연결되는지가 가장 궁금했습니다. 그래서 이 시리즈는 단순한 정의나 기능 설명보다 맥락 중심의 흐름과 구조적 이해에 집중했습니다.</p>
<blockquote>
</blockquote>
<p>비전공자도 부담 없이 읽을 수 있도록 가능한 쉬운 언어와 비유를 사용했지만, 그만큼 설명 방식에 부족한 점이 있을 수 있습니다. 혹시 더 좋은 설명이나 보완 아이디어가 있다면, 댓글로 자유롭게 피드백 남겨주세요! 😊</p>
<hr>
<h2 id="⚙️-컴퓨터는-부품만-있다고-작동하지-않는다">⚙️ 컴퓨터는 부품만 있다고 작동하지 않는다</h2>
<p><em>– 하드웨어만으론 안 되는 이유, 그리고 운영체제(전략기획실)의 등장</em></p>
<p>앞 장에서 살펴본 것처럼, 컴퓨터는 CPU, 메모리, 저장장치, 입출력 장치 등 여러 부품이 유기적으로 연결되어 작동합니다. 하지만 이 구성 요소들이 그냥 있다고 해서 협업이 자동으로 이루어지진 않아요.
각자 따로따로 움직인다면 자원 충돌이 생기고, 시스템은 엉망이 되죠.</p>
<p>예를 들어, 여러 프로그램이 동시에 프린터를 쓰려고 하거나,
하나의 프로그램이 메모리를 독점하려 들면 어떻게 될까요?
마치 회의실을 두 팀이 동시에 쓰겠다며 충돌하는 것처럼, 컴퓨터 내부에서도 비슷한 일이 일어납니다.</p>
<p>이런 상황을 막고, 자원을 배분하며, 사람과 컴퓨터가 소통할 수 있도록 돕는 총괄 조율자가 필요해요. 바로 이 역할을 맡는 것이 <strong>운영체제(Operating System)</strong>입니다.</p>
<p>앞서 1장에서 <strong>CPU</strong>를 <strong>회사 CEO</strong>에 비유했죠? 
그렇다면 <strong>운영체제</strong>는 컴퓨터 속에서 자원을 효율적으로 관리하고, 사용자와 컴퓨터 사이를 매끄럽게 이어주는 <strong>CEO 직속의 전략기획실</strong> 같은 존재예요. 
CPU(=CEO)가 계산에만 집중할 수 있도록 흐름을 정리하고, 자원 충돌을 미리 조율하며, 사용자와 내부 시스템 사이의 명령과 반응이 자연스럽게 오가도록 만들어줍니다.</p>
<hr>
<h2 id="👨💼-운영체제의-두-가지-핵심-역할">👨‍💼 운영체제의 두 가지 핵심 역할</h2>
<p>운영체제는 크게 두 가지 역할을 합니다.</p>
<blockquote>
<p><strong>첫째, 자원을 효율적으로 관리하는 것.</strong></p>
</blockquote>
<p>CPU, 메모리, 저장장치 등 컴퓨터 내부 자원은 한정돼 있고, 여러 프로그램이 동시에 이 자원들을 사용하려고 하죠. 운영체제는 이 자원들을 똑똑하게 나누고 충돌을 방지해, 컴퓨터가 여러 작업을 안정적으로 수행할 수 있게 도와줍니다.</p>
<blockquote>
<p><strong>둘째, 사용자와 컴퓨터가 매끄럽게 소통할 수 있도록 돕는 것.</strong></p>
</blockquote>
<p>우리는 아이콘을 클릭하거나 명령어를 입력하죠.
운영체제는 이런 사람의 행동을 컴퓨터가 이해할 수 있도록 바꿔주는 ‘통역사’ 역할을 합니다.</p>
<p>바탕화면, 창, 아이콘, 마우스 클릭처럼 우리가 보는 모든 화면 요소들은 운영체제가 제공하는 <code>‘사용자 인터페이스(UI)’</code>를 통해 동작하죠.</p>
<p>이 과정에서 운영체제는 장치를 연결하는 <strong>드라이버</strong>, 파일을 읽고 쓰는 <strong>파일 시스템</strong>, 키보드나 프린터 같은 장치를 다루는 <strong>입출력 제어 시스템</strong> 등을 내부적으로 활용합니다.</p>
<hr>
<h2 id="💎-운영체제의-첫번째-역할-자원관리와-실행-흐름-조율">💎 운영체제의 첫번째 역할: 자원관리와 실행 흐름 조율</h2>
<h3 id="🧵-프로그램이-실행될-때-프로세스와-스레드">🧵 프로그램이 실행될 때: 프로세스와 스레드</h3>
<p>우리가 워드를 켠다고 했을 때, 
그건 단순히 파일을 여는 게 아니라 
<strong><code>프로그램이 실행 가능한 상태로 변환되어 메모리에 올라가는 것</code></strong>입니다.</p>
<p>이걸 <strong><code>프로세스(Process)</code></strong>라고 합니다. 즉, 프로세스는 실행 중인 프로그램을 의미하죠.</p>
<p>프로세스는 서로 독립된 메모리 공간을 가지고 있고,
운영체제로부터 실행에 필요한 CPU 시간과 자원을 배정받습니다.</p>
<p>그런데 하나의 프로세스 안에서도 여러 작업이 동시에 이뤄질 수 있어요.
예를 들어, 워드에서는 글자를 치는 동시에 오타를 검사하거나 자동 저장이 되잖아요?</p>
<p>이처럼 프로세스 내부에서 병렬로 실행되는 작은 작업 단위를 <strong>스레드(Thread)</strong>라고 합니다.</p>
<p>정리하면, 
<strong>프로세스는 독립된 일하는 팀이고, 스레드는 그 팀 안에서 동시에 움직이는 팀원들</strong>이라고 볼 수 있습니다.</p>
<hr>
<h3 id="⏱️-한정된-cpu-누구부터-일하게-할까">⏱️ 한정된 CPU, 누구부터 일하게 할까?</h3>
<p>컴퓨터는 여러 작업을 동시에 수행하는 것처럼 보이지만, CPU가 한 순간에 처리할 수 있는 작업 수는 <strong>제한적</strong>입니다.</p>
<p>특히 단일 코어에서는 한 번에 하나의 작업만 처리할 수 있죠.
그래서 운영체제는 어떤 작업을 언제 처리할지 <strong>우선순위를 정해 조율해야 합니다.</strong></p>
<p>이걸 <strong>CPU 스케줄링</strong>이라고 해요.</p>
<p>대표적인 스케줄링 방식에는 다음과 같은 것들이 있습니다.</p>
<ul>
<li><strong>FCFS (First Come, First Served)</strong>: 먼저 요청한 작업부터 순서대로 처리</li>
<li><strong>SJF (Shortest Job First)</strong>: 처리 시간이 가장 짧은 작업부터 먼저 처리</li>
<li><strong>RR (Round Robin)</strong>: 모든 작업에 공평하게 일정 시간씩 나눠서 번갈아 처리</li>
</ul>
<p>작업을 전환할 때 운영체제는 <strong>문맥 교환(Context Switching)</strong>이라는 과정을 거쳐요.
지금까지 하던 작업의 상태를 저장하고, 다음 작업의 상태를 불러와 이어서 실행하는 거예요.</p>
<p>마치 여러 작업 창을 오가며 일할 때, 각 창의 작업 내용을 저장해두고 
다른 창으로 이동해 거기서 하던 일을 이어서 하는 것처럼요.</p>
<p>다만 문맥 교환이 너무 자주 일어나면 오히려 <strong>시간과 자원 낭비</strong>가 생기기 때문에, 운영체제는 최대한 효율적으로 스케줄링하려고 합니다.</p>
<hr>
<h3 id="👥-진짜-동시에-혹은-번갈아가며-병렬성과-동시성">👥 진짜 동시에? 혹은 번갈아가며?: 병렬성과 동시성</h3>
<p>운영체제가 여러 작업을 처리할 때는
<strong>동시성(Concurrency)</strong>과 <strong>병렬성(Parallelism)</strong>이라는 개념이 중요해집니다.</p>
<ul>
<li><strong>동시성: 하나의 CPU(또는 코어)가 여러 작업을 빠르게 번갈아가며 처리</strong>해서 겉보기에는 동시에 실행되는 것처럼 보이게 하는 방식이에요. 마치 한 사람이 이메일 확인, 전화 응대, 문서 작성을 번갈아 하는 것처럼요.</li>
<li><strong>병렬성</strong>: <strong>여러 개의 CPU(또는 코어)가 진짜로 동시에 각각 다른 작업을 처리</strong>하는 것이에요. 여러 사람이 각자 일을 하나씩 맡아 동시에 수행하는 것과 같죠.</li>
</ul>
<p>이와 관련된 실행 구조로는 <strong>멀티프로세싱</strong>과 <strong>멀티스레딩</strong>이 있습니다.</p>
<ul>
<li><strong>멀티프로세싱(Multiprocessing)</strong>: 여러 개의 CPU(또는 코어)가 서로 다른 프로세스를 동시에 실행하는 구조</li>
<li><strong>멀티스레딩(Multithreading)</strong>: 은 하나의 프로세스 안에서 여러 스레드가 병렬 혹은 번갈아 실행되는 구조
  → 단일 코어에서는 빠르게 번갈아 실행되고, 멀티코어에서는 실제로 동시에 실행되기도 해요!</li>
</ul>
<p>운영체제는 이런 다양한 실행 흐름을 <strong>안정적이고 효율적으로 관리</strong>하는 역할을 합니다.</p>
<blockquote>
<p>✅  <strong>동시성</strong> = 하나의 CPU가 빠르게 번갈아 작업
✅ <strong>병렬성</strong> = 여러 CPU가 실제로 동시에 각자 작업</p>
</blockquote>
<hr>
<h3 id="🔒-충돌을-막는-열쇠-세마포어와-동기화">🔒 충돌을 막는 열쇠: 세마포어와 동기화</h3>
<p>여러 작업이 동시에 진행되면,
<strong>같은 자원을 동시에 사용하려고 하면서 충돌</strong>이 발생할 수 있습니다.</p>
<p>예를 들어 두 스레드가 동시에 같은 프린터를 쓰거나 같은 파일을 동시에 수정하려 한다면, <strong>데이터 오류나 시스템 불안정</strong>이 생길 수 있는 거죠.</p>
<p>이런 문제를 막기 위해 운영체제는 <strong>동기화(Synchronization)</strong>를 사용합니다.</p>
<p>그중 대표적인 도구가 바로 <strong>세마포어(Semaphore)</strong>입니다.</p>
<p>세마포어는 <strong>자원에 접근할 수 있는 권한(열쇠)</strong>을 관리하는 방식입니다.
누군가 회의실을 사용하고 있다면, 다른 사람은 회의실이 빌 때까지 기다리는 것처럼 <strong>하나의 자원에 한 번에 하나의 작업만 접근하도록 제어</strong>합니다.</p>
<p>덕분에 컴퓨터는 자원 충돌 없이 <strong>안정적으로 여러 작업을 처리할 수 있게</strong> 되는 거죠.</p>
<hr>
<h3 id="🧠-좁은-메모리-넓게-쓰기-가상-메모리와-페이지-교체">🧠 좁은 메모리, 넓게 쓰기: 가상 메모리와 페이지 교체</h3>
<p>RAM은 빠르지만 용량이 한정되어 있어서 많은 프로그램을 동시에 실행하기엔 부족할 수 있습니다.
그래서 등장한 개념이 <strong>가상 메모리(Virtual Memory)</strong>입니다.</p>
<p>운영체제는 <strong>SSD(또는 HDD)의 일부 공간을 RAM처럼 사용해서</strong> <strong>없는 공간을 있는 것처럼 보여주고, 더 많은 작업을 가능하게</strong> 해줍니다.</p>
<p>이를 구현하기 위해 <strong>페이징(Paging)</strong>과 <strong>세그멘테이션(Segmentation)</strong> 같은 기법이 사용됩니다.</p>
<ul>
<li><strong>페이징(Paging)</strong>: 메모리를 같은 크기의 블록(Page)으로 잘라서 관리하는 방식</li>
<li><strong>세그멘테이션(Segmentation)</strong>: 메모리를 논리적인 용도 단위(코드, 데이터, 스택 등)로 나누어 관리하는 방식</li>
</ul>
<p>운영체제는 상황에 따라 두 가지 방식을 단독 또는 혼합해서 사용하기도 합니다.</p>
<p>또 RAM이 꽉 차면, 당장 필요하지 않은 데이터를 SSD나 HDD로 내보내는 작업이 필요한데, 이때 어떤 데이터를 내보낼지를 정하는 것이 <strong>페이지 교체 알고리즘</strong>입니다.</p>
<ul>
<li><strong>LRU(Least Recently Used)</strong>: 가장 오랫동안 사용되지 않은 데이터를 우선 제거</li>
<li><strong>FIFO(First In, First Out)ㅣ</strong> 가장 먼저 들어온 데이터를 먼저 제거</li>
</ul>
<p>운영체제는 이런 방식으로 <strong>RAM 공간을 효율적으로 확보</strong>하면서 전체 성능을 유지합니다.</p>
<hr>
<h3 id="🔄-기다릴까-딴-일할까-동기-vs-비동기">🔄 기다릴까, 딴 일할까: 동기 vs 비동기</h3>
<p>운영체제는 프로그램으로부터 요청을 받았을 때,
<strong>결과가 나올 때까지 기다릴지, 다른 일을 먼저 할지를 선택</strong>할 수 있습니다.</p>
<p>이를 <strong>동기(Synchronous)</strong>와 <strong>비동기(Asynchronous)</strong>라고 합니다.</p>
<ul>
<li><strong>동기 방식</strong>: 요청 결과가 나올 때까지 기다렸다가 다음 일을 처리하는 방식</li>
<li><strong>비동기 방식</strong>: 요청 결과를 기다리는 동안 다른 일을 먼저 수행하는 방식</li>
</ul>
<p>예를 들어 배달 음식을 주문했다고 할 때</p>
<ul>
<li><strong>동기</strong>는 문 앞에 서서 음식이 올 때까지 가만히 기다리는 것이고,</li>
<li><strong>비동기</strong>는 음식이 올 동안 설거지를 하거나 TV를 보는 거예요.</li>
</ul>
<p>요즘 앱이나 웹사이트는 대부분 비동기 방식을 적극적으로 활용해 <strong>끊김 없는 사용자 경험</strong>을 제공하고 있답니다.</p>
<h2 id="📡-운영체제의-두-번째-역할-사람과-컴퓨터의-소통을-연결하다">📡 운영체제의 두 번째 역할: 사람과 컴퓨터의 소통을 연결하다</h2>
<hr>
<h3 id="🤷-사람과-컴퓨터는-서로의-언어를-모른다">🤷 사람과 컴퓨터는 서로의 언어를 모른다?</h3>
<p>사람은 클릭하고, 타이핑하고, 드래그하면서 컴퓨터에게 무언가를 요청합니다.
&quot;이거 실행해줘&quot;, &quot;이 파일 저장해줘&quot;, &quot;이미지 보여줘&quot; 같은 거죠.</p>
<p>그런데 컴퓨터는 이걸 곧바로 알아들을 수 없습니다.
컴퓨터는 오직 <strong>0과 1로 된 신호만</strong> 이해하거든요.</p>
<p>이처럼 <strong>사람과 컴퓨터는 언어가 전혀 달라요.</strong>
그래서 이 둘이 소통하려면, <strong>중간에서 해석하고 연결해주는 존재</strong>가 꼭 필요합니다.</p>
<p>그게 바로 <strong>운영체제(Operating System)</strong>예요.</p>
<hr>
<h3 id="🧑💻-운영체제는-컴퓨터-안의-통역사">🧑‍💻 운영체제는 컴퓨터 안의 ‘통역사’</h3>
<p>운영체제는 사람이 내리는 명령을 컴퓨터가 이해할 수 있는 방식으로 바꿔주고,
컴퓨터가 처리한 결과를 다시 사람이 이해할 수 있는 형태로 보여줘요.</p>
<p>예를 들어, 마우스로 &#39;워드 파일&#39; 아이콘을 클릭하면 운영체제는 이렇게 일합니다.</p>
<blockquote>
<p>① “이 사용자가 클릭한 건 어떤 좌표고, 무슨 의미일까?”
② “그 좌표에 있는 아이콘은 워드 파일이네?”
③ “그럼 하드디스크에서 그 파일을 찾아서…”
④ “메모리에 올리고, CPU가 실행하도록 연결해줘야겠다.”</p>
</blockquote>
<p><strong>사람은 클릭 한 번으로</strong>, <strong>컴퓨터는 복잡한 과정을 통해</strong>,
그리고 <strong>운영체제가 가운데서 조율하면서 이 모든 흐름이 매끄럽게 이어지는</strong> 거예요.</p>
<hr>
<h3 id="🖼️-사람과-운영체제의-접점-gui와-cli">🖼️ 사람과 운영체제의 접점: GUI와 CLI</h3>
<p>운영체제는 사람이 <strong>더 쉽게</strong> 컴퓨터를 쓸 수 있도록 <strong>GUI</strong>와 <strong>CLI</strong> 같은 사용자 인터페이스 환경을 <strong>구성하거나 지원</strong>합니다.</p>
<ul>
<li><p><strong>GUI (Graphical User Interface)</strong></p>
<p>  아이콘, 버튼, 창을 클릭하는 우리가 익숙한 방식이에요.</p>
<p>  초보자도 쉽게 사용할 수 있고, 대부분의 OS(윈도우, 맥 등)에서 기본으로 제공돼요.</p>
</li>
<li><p><strong>CLI (Command Line Interface)</strong></p>
<p>  터미널에 직접 명령어를 입력하는 방식이에요.</p>
<p>  익숙해지면 더 빠르고 유연하지만, 처음엔 어렵게 느껴질 수 있어요.</p>
</li>
</ul>
<p>운영체제는 이 인터페이스를 통해 ‘<strong>사람이 무엇을 원하는지’를 파악</strong>하고, 
그걸 컴퓨터가 수행할 수 있도록 <strong>정확한 작업으로 바꿔주는 다리</strong> 역할을 하는 거예요.</p>
<hr>
<h3 id="📲-그런데-그-명령은-실제로-어디로-가는-걸까">📲 그런데, 그 명령은 실제로 어디로 가는 걸까?</h3>
<p>우리가 클릭하거나 입력한 명령은 결국 하드웨어(하드디스크, 프린터 등)까지 가야 해요.
하지만 하드웨어는 제조사마다 동작 방식이 다르고, 언어도 제각각입니다.</p>
<p>운영체제가 이 모든 장치의 동작 방식을 미리 알 수는 없기 때문에,
<strong>운영체제와 장치 간의 연결을 도와주는 ‘번역기’가 필요합니다.</strong></p>
<p>그게 바로 <strong>드라이버(driver)</strong>예요.</p>
<ul>
<li>키보드 드라이버 → 타이핑된 문자를 운영체제가 읽을 수 있도록 전달</li>
<li>하드디스크 드라이버 → 저장 명령을 하드디스크가 이해하게 변환</li>
<li>프린터 드라이버 → 출력 요청을 프린터가 이해하도록 전달</li>
</ul>
<p><strong>운영체제는 이 드라이버들을 통해 수많은 장치들과 원할히 소통할 수 있습니다</strong>.</p>
<hr>
<h3 id="🧠-인터럽트-장치의-손들기">🧠 인터럽트: 장치의 손들기</h3>
<p>프린터, USB, 마우스 같은 장치들은 운영체제에게 <strong>“지금 나 좀 봐줘요!”</strong> 하고 알려야 할 때가 있습니다.</p>
<p>이럴 때 사용하는 게 바로 <strong>인터럽트(Interrupt)</strong>라는 신호입니다.</p>
<ul>
<li>마우스를 움직이면 → 마우스 인터럽트</li>
<li>프린터가 인쇄를 마치면 → 프린터 인터럽트</li>
<li>USB를 꽂으면 → USB 인터럽트</li>
</ul>
<p>운영체제는 이 신호를 받고 <strong>지금 하던 작업을 잠시 멈추거나 순서를 조정</strong>해 <strong>장치들과 끊김 없이 상호작용할 수 있게 조율</strong>합니다.</p>
<blockquote>
<p>✅ <strong>정리</strong></p>
</blockquote>
<ul>
<li>사용자는 클릭이나 입력으로 “요청”을 전달</li>
<li>운영체제는 그걸 <strong>GUI/CLI → 드라이버 → 하드웨어</strong>로 해석해 전달</li>
<li>장치가 작업을 요청하면 <strong>인터럽트</strong>를 통해 흐름을 조정</li>
</ul>
<hr>
<h2 id="🏢-마무리">🏢 마무리</h2>
<p>컴퓨터 시스템을 하나의 회사로 비유하고 CPU가 그 회사의 CEO라면,</p>
<p>운영체제는 부서 간 충돌을 막고, 회의실(자원)을 효율적으로 나눠주며,
외부 요청과 내부 시스템 간의 흐름을 매끄럽게 이어주는
<strong>조직 전체의 컨트롤 타워이자 조율자</strong>예요.</p>
<p>운영체제가 잘 작동해야</p>
<ul>
<li>CPU는 계산에만 집중하고,</li>
<li>메모리는 효율적으로 쓰이고,</li>
<li>입출력 장치와 사용자 간 소통도 자연스럽게 이어질 수 있어요.</li>
</ul>
<p>👉 결국, <strong>운영체제가 있어야 컴퓨터는 &#39;사람이 원하는 방식&#39;으로 부드럽고 질서 있게 작동하는 시스템이 됩니다.</strong></p>
<hr>
<h2 id="➡️-next">➡️ Next</h2>
<p>다음은 이 시스템 안에서 사람이 <strong>컴퓨터에게 직접 ‘명령’을 내릴 수 있게 도와주는 또 다른 발명</strong>, 
바로 <strong>프로그래밍 언어의 발전</strong>에 대해 이야기해보겠습니다.</p>
<p>컴퓨터와 사람은 점점 더 자연스럽게 대화할 수 있게 됩니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[컴퓨터 구조 쉽게 이해하기]]></title>
            <link>https://velog.io/@ariul-dev/%EC%BB%B4%ED%93%A8%ED%84%B0%EB%8A%94-%EC%96%B4%EB%96%BB%EA%B2%8C-%EB%98%91%EB%98%91%ED%95%9C-%EA%B8%B0%EA%B3%84%EA%B0%80-%EB%90%98%EC%97%88%EC%9D%84%EA%B9%8C</link>
            <guid>https://velog.io/@ariul-dev/%EC%BB%B4%ED%93%A8%ED%84%B0%EB%8A%94-%EC%96%B4%EB%96%BB%EA%B2%8C-%EB%98%91%EB%98%91%ED%95%9C-%EA%B8%B0%EA%B3%84%EA%B0%80-%EB%90%98%EC%97%88%EC%9D%84%EA%B9%8C</guid>
            <pubDate>Wed, 02 Apr 2025 07:45:59 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p><strong>기술을 아는 것과, 누구나 이해할 수 있도록 전달하는 건 다르다</strong>는 걸 깨달았습니다.
이 시리즈는 <strong>‘기술을 쉽게 전달하는 방법’을 고민하며 쓰는 저의 학습 기록</strong>입니다.</p>
</blockquote>
<p>컴퓨터공학이라는 거대한 분야를 처음 접했을 때, 저는 각 개념이 왜 등장했고 어떻게 연결되는지가 가장 궁금했습니다. 그래서 이 시리즈는 단순한 정의나 기능 설명보다 맥락 중심의 흐름과 구조적 이해에 집중했습니다.</p>
<blockquote>
</blockquote>
<p>비전공자도 부담 없이 읽을 수 있도록 가능한 쉬운 언어와 비유를 사용했지만, 그만큼 설명 방식에 부족한 점이 있을 수 있습니다. 혹시 더 좋은 설명이나 보완 아이디어가 있다면, 댓글로 자유롭게 피드백 남겨주세요! 😊</p>
<hr>
<h2 id="컴퓨터는-처음부터-똑똑했을까">컴퓨터는 처음부터 똑똑했을까?</h2>
<p><em>– 계산기에서 만능 기계로, 컴퓨터를 컴퓨터답게 만든 구조 이야기</em></p>
<p><img src="https://velog.velcdn.com/images/ariul-dev/post/720a8c16-9490-4101-a592-7b6181a6f5d5/image.png" alt=""></p>
<p>오늘날의 컴퓨터는 영상 편집, 문서 작업, 게임, 인공지능까지 다 해내는 똑똑한 기계처럼 보이지만, 처음 등장했을 땐 단지 0과 1만 구분할 줄 아는 단순한 계산기였습니다.</p>
<p>그런데 이 단순한 기계가 지금처럼 다양한 일을 처리할 수 있는 다재다능한 시스템으로 발전할 수 있었던 건 바로 <strong>‘폰 노이만 구조’</strong>라는 개념 덕분입니다.</p>
<hr>
<h2 id="폰-노이만-구조란">폰 노이만 구조란?</h2>
<p>폰 노이만 구조는 이렇게 제안했습니다.</p>
<blockquote>
<p>계산을 담당하는 장치(CPU)와 데이터를 저장하는 장치(메모리)를 따로 두자.
그리고 실행할 프로그램(명령어)도 데이터를 다루듯 메모리에 저장하자.
그럼 CPU가 메모리를 순서대로 읽으면서 알아서 실행하면 되지 않을까!?</p>
</blockquote>
<p>이건 정말 획기적인 생각이었습니다.
왜냐하면 예전 컴퓨터는 어떤 작업을 하려면 그 작업 전용 회로를 <strong>직접 꽂거나 연결</strong>해야 했거든요.
덧셈을 하려면 덧셈 회로, 뺄셈을 하려면 또 다른 회로를 물리적으로 바꿔야 했어요.</p>
<p><strong>작업을 바꿀 때마다 기계를 조립하듯 다시 설정해야 했던 거죠.</strong></p>
<p>하지만 폰 노이만 구조에서는,
그냥 실행하고 싶은 프로그램을 메모리에 저장해두기만 하면 CPU가 그걸 꺼내서 처리해줍니다.
이제는 기계를 바꾸지 않아도, <strong>소프트웨어만 바꾸면 컴퓨터가 완전히 다른 일을 수행할 수 있게 된 것이에요.</strong></p>
<hr>
<h2 id="cpu-컴퓨터의-두뇌">CPU: 컴퓨터의 두뇌</h2>
<p>컴퓨터에서 가장 중심이 되는 부품은 바로 <strong>CPU(Central Processing Unit)</strong>예요.
모든 계산, 판단, 명령 실행이 이곳에서 이루어지죠. 그래서 흔히 컴퓨터의 두뇌라고 불립니다.</p>
<h3 id="⏱️-클럭clock-cpu의-리듬">⏱️ 클럭(clock): CPU의 리듬</h3>
<p>CPU는 일을 할 때 ‘클럭(clock)’이라는 일정한 리듬에 맞춰 움직입니다. 마치 &quot;하나, 둘, 셋&quot; 하고 박자를 맞춰 일하는 느낌이에요.</p>
<p>이 클럭 속도는 <strong>헤르츠(Hz)</strong>라는 단위로 표현되는데,
예를 들어 3GHz라고 하면 1초에 30억 번 박자를 세며 일을 한다는 뜻이에요.</p>
<p><strong>클럭 속도가 높을수록, CPU가 일을 처리할 수 있는 잠재적인 속도는 더 빨라져요.</strong>
(물론, 클럭 속도 외에도 CPU의 구조나 명령 처리 방식도 성능에 큰 영향을 준답니다!)</p>
<h3 id="🧮-alu와-레지스터-계산과-초고속-기억">🧮 ALU와 레지스터: 계산과 초고속 기억</h3>
<p>CPU 내부에는 실제 계산을 담당하는 <strong>ALU(산술논리연산장치)</strong>가 있고,
명령어나 숫자를 잠깐 담아두는 <strong>레지스터(Register)</strong>라는 초고속 기억 공간이 있습니다.</p>
<p>레지스터는 CPU 바로 안에 있어서 속도는 정말 빠르지만, 너무 작기 때문에 <strong>당장 필요한 데이터만 잠깐 저장</strong>하는 용도로 쓰입니다.</p>
<hr>
<h2 id="기억-장치-계층-구조-얼마나-빠르고-얼마나-오래-기억하는가">기억 장치 계층 구조: 얼마나 빠르고, 얼마나 오래 기억하는가</h2>
<p>CPU는 일을 할 때 다양한 기억장치들과 협력해요.
그 이유는 각 장치마다 속도, 용량, 유지 기간이 다르기 때문이에요.</p>
<h3 id="⚡️-캐시cache-cpu의-즐겨찾기-메모장">⚡️ 캐시(Cache): CPU의 즐겨찾기 메모장</h3>
<p>레지스터만 가지고는 당연히 부족하겠죠. CPU가 실제 작업을 하려면 더 넓은 기억 공간이 필요한데, 그 사이를 효율적으로 이어주는 게 바로 <strong>캐시(Cache)</strong>입니다.</p>
<p>캐시는 CPU와 RAM 사이에 위치한 <strong>고속 기억 공간</strong>입니다.
CPU는 최근에 사용한 데이터나 명령어를 캐시에 미리 저장해두고, 다시 필요할 때 훨씬 빠르게 꺼내 쓸 수 있습니다.</p>
<p>RAM까지 가지 않아도 되니, 속도가 훨씬 빨라지죠.
<strong>캐시는 마치 책상 위에 꺼내 둔 자주 쓰는 파일처럼</strong>, CPU가 손 뻗으면 바로 닿는 위치에 있습니다.</p>
<p>캐시는 속도와 용량에 따라 L1, L2, L3 단계로 나뉘기도 합니다. 
L1은 CPU에 가장 가까워서 제일 빠르지만 작고, L3는 비교적 느리지만 더 많은 데이터를 저장할 수 있죠.</p>
<h3 id="📂-ramrandom-access-memory-작업-중인-공간">📂 RAM(Random Access Memory): 작업 중인 공간</h3>
<p>그럼에도 불구하고 캐시도 용량이 작기 때문에, 우리가 실행 중인 프로그램이나 파일 전체를 담기엔 부족합니다. 그래서 컴퓨터는 더 넓은 작업 공간인 <strong>RAM(Random Access Memory)</strong>을 사용합니다.</p>
<p><strong>RAM</strong>은 우리가 프로그램을 실행할 때 데이터를 임시로 저장하는 공간입니다.
예를 들어 워드 파일을 열면 그 내용이 RAM에 올라가고, 수정한 내용도 일단 RAM에 임시 저장됩니다.
전원을 끄면 사라지는 <code>휘발성 메모리지만, 속도가 빠르기 때문에 실시간 작업에 아주 적합</code>합니다.</p>
<h3 id="🔐-romread-only-memory-꼭-필요한-고정-정보">🔐 ROM(Read Only Memory): 꼭 필요한 고정 정보</h3>
<p>반대로 컴퓨터가 부팅할 때처럼 절대 잊어버리면 안 되는 정보도 있죠.
그건 <strong>ROM(Read Only Memory)</strong>에 저장됩니다.</p>
<p>ROM은 컴퓨터가 켜질 때 반드시 필요한 기본 명령을 담고 있고, 전원이 꺼져도 남아 있는 <code>비휘발성 메모리</code>입니다.</p>
<h3 id="🗄️-ssd와-hdd-오래도록-보관하는-저장소">🗄️ SSD와 HDD: 오래도록 보관하는 저장소</h3>
<p>RAM은 임시 공간이니 사진, 영상, 문서처럼 <strong>오래도록 보관해야 하는 데이터</strong>는 따로 저장해야겠죠?</p>
<p>그걸 맡는 게 <strong>보조 기억 장치</strong>, 즉 <strong>HDD</strong>와 <strong>SSD</strong>입니다.</p>
<p><strong>HDD(Hard Disk Drive)</strong>는 회전하는 디스크에 자석을 이용해 데이터를 저장하는 방식이에요. 저렴하고 용량은 크지만 속도는 느리고 충격에도 약해요.</p>
<p><strong>SSD(Solid State Drive)</strong>는 전자식 저장 장치로, 소음도 없고 훨씬 빠르게 작동합니다. 요즘은 거의 모든 노트북과 스마트폰이 SSD를 쓰고 있어요.</p>
<blockquote>
<p>💡 <code>ROM</code>도 전원을 꺼도 내용이 사라지지 않는 <code>비휘발성 메모리</code>지만, 저장 용량이 워낙 작아서 주로 부팅 시 필요한 기본 명령만 담고 있어요. 우리가 자주 저장하거나 불러오는 사진, 영상, 프로그램 등은 SSD나 HDD에 저장돼요.</p>
</blockquote>
<h3 id="🔁-기억-장치는-계층-구조로-연결된다">🔁 기억 장치는 계층 구조로 연결된다</h3>
<p>이렇게 보면, 컴퓨터 안에는 다양한 종류의 기억 장치가 계층 구조로 연결되어 있습니다.
<strong>레지스터 → 캐시 → RAM → SSD/HDD</strong> 순으로
속도는 느려지지만 저장 용량은 커지고, 정보 보존 기간도 길어집니다.</p>
<p>CPU는 이 여러 저장소를 상황에 따라 골라서 사용하면서, 빠르고 효율적인 작업을 가능하게 합니다.</p>
<hr>
<h2 id="입출력-장치-사람과-컴퓨터를-이어주는-창구">입출력 장치: 사람과 컴퓨터를 이어주는 창구</h2>
<p>이제 마지막으로, 컴퓨터는 사람과 소통해야 의미가 있겠죠?
그래서 사람이 데이터를 입력하고, 결과를 받아보는 <strong>입출력 장치</strong>가 필요합니다.</p>
<p><strong>입력 장치</strong>는 우리가 정보를 컴퓨터에 ‘넣는’ 수단입니다. 키보드, 마우스, 마이크처럼요.
<strong>출력 장치</strong>는 컴퓨터가 작업 결과를 우리에게 &#39;보여주는&#39; 수단입니다. 모니터, 프린터, 스피커 같은 것들이죠.</p>
<hr>
<h2 id="하나의-완성된-컴퓨터-시스템">하나의 완성된 컴퓨터 시스템</h2>
<p>이제 <code>CPU가 계산</code>하고, 
<code>레지스터와 캐시가 자주 쓰는 정보를 기억</code>하고,
<code>RAM이 작업 중인 데이터</code>를 저장하고, <code>SSD가 장기 보관 데이터를 저장</code>하며,
<code>입출력 장치가 사람과 정보를 주고받는</code> 구조가 완성됐습니다.</p>
<p>이 모든 걸 가능하게 만든 출발점이 바로 <strong>폰 노이만 구조</strong>였던 거예요.
이 구조 덕분에 우리는 지금처럼 <strong>하나의 기계로 다양한 작업을 할 수 있게 된</strong> 거죠.</p>
<hr>
<h2 id="컴퓨터를-하나의-회사로-본다면">컴퓨터를 하나의 회사로 본다면?</h2>
<p>조금 더 쉽게 상상해볼까요?</p>
<p>이 컴퓨터 시스템을 하나의 <strong>회사</strong>🏢로 비유해보면, 각 부품들은 명확한 역할을 가진 <strong>팀원</strong>🕴️처럼 이해할 수 있습니다.</p>
<ul>
<li><strong>CPU</strong>는 이 회사의 <strong>CEO(최고 경영자)</strong>예요. 자신의 집무실에서 실시간으로 결정을 내리는 역할을 하죠. 수많은 정보를 순식간에 판단하고 실행하지만, 직접 많은 문서를 오래 기억하진 않아요.</li>
<li><strong>레지스터</strong>는 <strong>CEO의 머릿속에 있는 작은 메모장</strong>입니다. 지금 당장 필요한 숫자 몇 개만 아주 잠깐 기억할 수 있죠.</li>
<li><strong>캐시(Cache)</strong>는 <strong>CEO 바로 옆 비서가 들고 있는 자주 쓰는 문서철</strong>입니다. 최근에 자주 본 자료를 손 뻗으면 닿을 거리에서 빠르게 전달해줘요.</li>
<li><strong>RAM</strong>은 <strong>업무가 활발히 벌어지는 대회의실 테이블</strong>입니다. 오늘 처리해야 할 모든 문서와 자료들이 이곳에 펼쳐져 있어요. 실시간으로 수정되고 교체되며, 다양한 부서의 사람들이 와서 함께 작업하는 공간이에요.</li>
<li><strong>SSD나 HDD</strong>는 <strong>자료보관실</strong>입니다. 오래된 계약서, 백업 자료, 문서들이 차곡차곡 저장돼 있는 곳이에요. 필요할 땐 꺼내지만, 평소엔 손이 잘 안 가요.</li>
<li><strong>입출력 장치</strong>는 외부와 연결된 창구예요. 전화 받고, 보고서를 전송하는 창 같은 거죠.</li>
</ul>
<p>이렇게 보면, 컴퓨터는 단순한 기계가 아니라 <code>각기 다른 역할을 가진 부품들이 유기적으로 협력하는 하나의 조직</code>처럼 보이지 않나요?</p>
<hr>
<h2 id="➡️-next">➡️ Next</h2>
<p>다음 장에서는 컴퓨터 속에서 이 조직을 총괄 지휘하고 조율하는 역할을 하는 존재, 즉 <strong>운영체제(OS)</strong>가 어떻게 등장했는지를 알아볼 거예요.</p>
<p>회사로 치면 전략기획실 같은 존재랍니다! 궁금하지 않나요?</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[CPU는 어떻게 동작할까?]]></title>
            <link>https://velog.io/@ariul-dev/CPU%EB%8A%94-%EC%96%B4%EB%96%BB%EA%B2%8C-%EB%8F%99%EC%9E%91%ED%95%A0%EA%B9%8C</link>
            <guid>https://velog.io/@ariul-dev/CPU%EB%8A%94-%EC%96%B4%EB%96%BB%EA%B2%8C-%EB%8F%99%EC%9E%91%ED%95%A0%EA%B9%8C</guid>
            <pubDate>Thu, 11 May 2023 13:35:52 GMT</pubDate>
            <description><![CDATA[<h2 id="cpu중앙-처리-장치란">CPU(중앙 처리 장치)란?</h2>
<ul>
<li>Central Processing Unit</li>
<li>컴퓨터 시스템을 통제하고 프로그램의 연산을 실행·처리하는 가장 핵심적인 컴퓨터의 제어 장치, 혹은 그 기능을 내장한 칩</li>
<li>역할<ul>
<li>기계어로 쓰인 컴퓨터 프로그램의 명령어를 해석하여 실행한다.</li>
<li>CPU는 프로그램에 따라 외부에서 정보를 입력받아,이를 기억하고, 연산하며, 결과를 외부로 출력한다.</li>
</ul>
</li>
</ul>
<hr>
<h2 id="cpu의-구성">CPU의 구성</h2>
<h3 id="1-레지스터register">1. 레지스터(Register)</h3>
<ul>
<li>CPU 내부에서 데이터를 일시적으로 저장하는 장치로, 속도가 가장 빠른 메모리이다</li>
<li>레지스터 종류<ul>
<li><code>프로그램 카운터(PC)</code>: 다음번에 수행할 메모리의 주소가 들어있다</li>
<li><code>메모리 주소 레지스터(MAR)</code>: 프로그램 카운터에서 수행할 주소를 넘겨 받은 다음에 그 주소를 찾아가 데이터를 가져오는 역할을 한다</li>
<li><code>메모리 버퍼 레지스터(MBR)</code>: 메모리 주소 레지스터가 가져온 데이터나 명령들을 일시적으로 저장한다<ul>
<li>메모리 버퍼 레지스터에 저장된 내용 중 명령은 명령어 레지스터로 이동한다.<ul>
<li>메모리 버퍼 레지스터에 저장된 내용 중 연산에 사용될 데이터는 누산기 레지스터로 이동한다.</li>
</ul>
</li>
</ul>
</li>
<li><code>명령어 레지스터(IR)</code>: 명령에 관한 데이터가 저장된다.</li>
<li><code>누산기 레지스터(AC)</code>: 연산의 결과 값이나 중간 값을 일시적으로 저장한다. 최종 결과는 메모리 버퍼 레지스터를 통해 메모리로 전송된다.</li>
</ul>
</li>
</ul>
<h3 id="2-제어장치control-unit">2. 제어장치(Control Unit)</h3>
<ul>
<li>명령어 레지스터에 있는 명령어를 받아 해석하고, 해석된 명령을 각 시스템이 수행하도록 지시한다. </li>
</ul>
<h3 id="3-산술-논리-장치arithmetic-logic-unit-alu">3. 산술 논리 장치(Arithmetic Logic Unit, ALU)</h3>
<ul>
<li>산술 논리 연산을 실행한다<ul>
<li><code>산술</code>: 더하기 빼기 등 산수를 계산한다</li>
<li><code>논리 연산</code> : AND나 OR 같은 논리를 연산한다</li>
</ul>
</li>
<li>논리게이트를 이용해서 산술 논리 장치(ALU)를 만든다</li>
</ul>
<blockquote>
<p><strong>논리게이트(AND, OR, XOR, NOT)</strong></p>
</blockquote>
<table>
<thead>
<tr>
<th>In A</th>
<th>In B</th>
<th>AND</th>
<th>OR</th>
<th>XOR</th>
<th>NOT A</th>
</tr>
</thead>
<tbody><tr>
<td>0 (Off)</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>1</td>
</tr>
<tr>
<td>1 (On)</td>
<td>0</td>
<td>0</td>
<td>1</td>
<td>1</td>
<td>0</td>
</tr>
<tr>
<td>0</td>
<td>1</td>
<td>0</td>
<td>1</td>
<td>1</td>
<td>1</td>
</tr>
<tr>
<td>1</td>
<td>1</td>
<td>1</td>
<td>1</td>
<td>0</td>
<td>0</td>
</tr>
</tbody></table>
<hr>
<h2 id="cpu의-연산">CPU의 연산</h2>
<p><strong><code>명령어 사이클</code> : 인출 → 해석 → 실행 → (메모리) → 저장</strong></p>
<h3 id="fetch인출">Fetch(인출)</h3>
<p><img src="https://velog.velcdn.com/images/ariul-dev/post/aeffadef-8b63-417b-8f11-3734c29562d9/image.png" alt=""></p>
<ul>
<li>프로그램 카운터(PC)에 저장된 주소를 메모리 주소 레지스터(MAR)로 전달한다.</li>
<li>메모리 주소 레지스터(MAR)에 저장된 주소를 찾아서 명령어를 인출한다.</li>
<li>인출한 명령어를 메모리 버퍼 레지스터(MBR)에 저장한다.</li>
<li>다음 명령어를 인출하기 위해 프로그램 카운터(PC)의 값을 증가시킨다.</li>
<li>메모리 버퍼 레지스터(MBR)에 저장된 내용을 명령어 레지스터(IR)에 전달한다.<h3 id="decode해석">Decode(해석)</h3>
<img src="https://velog.velcdn.com/images/ariul-dev/post/ebefdb76-b886-47cb-a462-df9cd7e8d746/image.png" alt=""></li>
<li>명령어 레지스터(IR)에 있는 명령어는 제어장치로 이동되어 해석된다.</li>
<li>명령어를 해석하여 명령어 내의 데이터 정보와 연산 정보를 추출한 뒤, CPU 내의 각 장치에 적절한 제어 신호를 보내 연산, 처리에 대한 준비를 한다.</li>
</ul>
<h3 id="execute실행">Execute(실행)</h3>
<p><img src="https://velog.velcdn.com/images/ariul-dev/post/8bd3aa72-34fa-40da-9dba-a762ce643caf/image.png" alt=""></p>
<ul>
<li>명령어에서 추출한 두 데이터와 연산 정보를 이용해 실제로 연산을 실행한다.</li>
<li>명령어 레지스터(IR)의 내용을 메모리 주소 레지스터(MAR)로 전달한다.</li>
<li>메모리에 저장된 데이터 값을 메모리 버퍼 레지스터(MBR)에 저장한다.</li>
<li>누산기(AC)에 저장된 값에 연산을 실행한다.</li>
</ul>
<h3 id="memory메모리">Memory(메모리)</h3>
<ul>
<li>실행 단계의 연산 결과가 다음 명령어에 바로 사용되지 않는다면, 결과를 메모리에 저장한다.</li>
</ul>
<h3 id="write-back저장">Write Back(저장)</h3>
<ul>
<li>실행 단계의 연산 결과가 다음 명령어의 입력 데이터로 사용될 경우, 계산 결과를 레지스터에 다시 저장한다.</li>
</ul>
<hr>
<h2 id="reference">Reference</h2>
<ul>
<li><a href="https://www.youtube.com/watch?v=Fg00LN30Ezg">CPU는 어떻게 작동할까?</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[ChatGPT와 함께 알아본 String 에 관한 궁금증]]></title>
            <link>https://velog.io/@ariul-dev/ChatGPT%EC%99%80-%ED%95%A8%EA%BB%98-%EC%95%8C%EC%95%84%EB%B3%B8-String-%EC%97%90-%EA%B4%80%ED%95%9C-%EA%B6%81%EA%B8%88%EC%A6%9D</link>
            <guid>https://velog.io/@ariul-dev/ChatGPT%EC%99%80-%ED%95%A8%EA%BB%98-%EC%95%8C%EC%95%84%EB%B3%B8-String-%EC%97%90-%EA%B4%80%ED%95%9C-%EA%B6%81%EA%B8%88%EC%A6%9D</guid>
            <pubDate>Sat, 11 Feb 2023 11:58:30 GMT</pubDate>
            <description><![CDATA[<p>자바 프로그래밍에서 문자를 다룰 때, 기본형(Primitive type) <code>char</code> 과 참조형(Reference type) <code>String</code> 을 사용하곤 합니다.</p>
<p>문득 이런 궁금증이 생겼습니다.</p>
<blockquote>
</blockquote>
<p><code>문자열</code>은 <code>문자 배열</code>을 뜻하는 거 아닌가?
<code>문자열</code>을 다루는 String 과 <code>문자 배열</code>인 char[] 의 차이점이 뭘까..? 😮</p>
<p>그래서 String에 관한 궁금증을 ChatGPT에게 물어봤습니다. </p>
<hr>
<h2 id="1-char-vs-string-에-관한-질문">1. char[] vs String 에 관한 질문</h2>
<h3 id="🙋♀️-자바에서-char-array랑-string-차이점이-뭐야">🙋‍♀️ 자바에서 char array랑 String 차이점이 뭐야?</h3>
<p><img src="https://velog.velcdn.com/images/ariul-dev/post/5826114e-df61-414d-9a8d-6acb7f32825d/image.png" alt=""></p>
<p>자바에서 char[] 이랑 String 차이점이 무엇인지 물어보았더니, 다음과 같이 설명해 주었습니다.</p>
<h3 id="🤖💬">🤖💬</h3>
<p>Java에서 <code>char[]</code> 과 <code>String</code> 은 문자 또는 문자 시퀀스를 저장하는 데 사용되는 두 가지 데이터 유형이야.</p>
<p><code>char[]</code> 는 문자 배열이며, 배열의 각 요소는 단일 문자야.</p>
<pre><code>char[] chars = {&#39;H&#39;, &#39;e&#39;, &#39;l&#39;, &#39;l&#39;, &#39;o&#39;};</code></pre><p><code>String</code> 은 문자 시퀀스를 나타내는 Java의 내장 데이터 타입이야. 
다음과 같은 방법으로 생성할 수 있어.</p>
<pre><code>String greeting = &quot;Hello&quot;;
String greeting = new String(&quot;Hello&quot;);</code></pre><p><strong>Java에서 <code>char[]</code> 과 <code>String</code> 의 주요 차이점</strong></p>
<blockquote>
</blockquote>
<ol>
<li>불변성: String은 불변 객체야. 즉, 생성된 후에 값을 변경할 수 없지. 반면에 char[]은 값을 변경할 수 있어.</li>
<li>길이: String의 길이는 <code>length()</code> 메서드로 얻을 수 있고, char[]의 길이는 <code>length</code> 필드로 알 수 있어.</li>
<li>병합: String의 경우, <code>+</code> 연산자 또는 <code>concat()</code> 메서드를 이용해서 두 개의 String 객체를 쉽게 병합할 수 있어. 반면, 두 개의 char[]을 병합하려면 새 배열을 만들고 두 배열의 요소를 여기에 복사해야 해.</li>
<li>메서드: String의 경우에는, <code>substring()</code>, <code>replace()</code>, <code>toUpperCase()</code> 등과 같이 문자열을 조작하는 여러 메서드를 제공하는데, char[]에 사용할 수 있는 메서드는 없어.</li>
</ol>
<p>일반적으로 <code>String</code> 은 사용하기 쉽고 문자 조작할 때 편리한 메서드를 제공하고,
<code>char[]</code> 은 개별 문자를 자주 수정해야 하는 경우에 더 유연하고 효율적이야.</p>
<p><img src="https://velog.velcdn.com/images/ariul-dev/post/d38ce897-faaf-4e13-a154-bc52ffa93f38/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/ariul-dev/post/940ebe57-5d92-4b84-ba90-eeca740227cf/image.png" alt=""></p>
<h3 id="🙋♀️-그럼-string이랑-비교했을-때-char-쓰는-장점은-뭐야-언제-사용해">🙋‍♀️ 그럼 String이랑 비교했을 때, char[] 쓰는 장점은 뭐야? 언제 사용해?</h3>
<p><img src="https://velog.velcdn.com/images/ariul-dev/post/33b3fd20-dce3-4efc-af54-b5322a5f85ef/image.png" alt=""></p>
<h3 id="🤖💬-1">🤖💬</h3>
<p>String 보다 char[]을 사용하는 게 더 좋은 상황들이 있지.</p>
<blockquote>
</blockquote>
<ol>
<li>가변성: char[]은 가변 객체야. 즉, 배열이 생성된 후에도 내용을 변경할 수 있지. 반면, String은 불변 객체라 생성된 후에는 내용을 변경할 수 없어. 만약 문자열의 내용을 자주 수정해야 하는 경우라면 char[]을 사용하는 게 더 좋겠지.</li>
<li>성능: 앞서 말했다시피, char[]은 변경이 가능하기 때문에 새로운 객체를 만들지 않고도 내용을 수정할 수 있어. 그러니까 내용이 수정될 때마다 새로운 객체를 만드는 String에 비해서, 더 나은 성능을 얻을 수 있는 상황도 있지.</li>
<li>메모리 사용: char[]은 길이나 해시 코드처럼 문자열에 대한 추가 정보를 저장하지 않기 때문에 String에 비해 메모리 효율성이 더 높을 수 있어.</li>
<li>보안: char[]은 사용하고 나서 깨끗이 지울 수 있기 때문에 민감한 정보가 사용되는 경우라면 String 보다 안전할 수 있지.</li>
</ol>
<p>String을 쓸지, char[]을 쓸지는 애플리케이션의 요구 사항에 따라 달라.
일반적으로 문자열의 내용을 자주 수정할 필요가 없고, 메모리 사용이나 보안에 대해 걱정하지 않는 경우에는 String을 사용하지. 반면, 내용을 자주 수정해야 하거나 메모리 사용이나 보안이 걱정되거나, 성능을 최적화해야 한다면 char[]을 사용하는 게 좋겠지?
<img src="https://velog.velcdn.com/images/ariul-dev/post/1d80458c-d9f0-4cfa-9397-eb2a80844de6/image.png" alt=""></p>
<hr>
<h2 id="2-string에-관한-질문">2. String에 관한 질문</h2>
<h3 id="🙋♀️-아까-double-quotes랑-new-연산자로-string-객체를-만들-수-있다고-했잖아-그-둘의-차이는-뭔데">🙋‍♀️ 아까 double quotes(&quot;&quot;)랑 new 연산자로 String 객체를 만들 수 있다고 했잖아. 그 둘의 차이는 뭔데?</h3>
<p><img src="https://velog.velcdn.com/images/ariul-dev/post/1313bbd4-2af2-48ff-b9bb-ef5898702589/image.png" alt=""></p>
<h3 id="🤖💬-2">🤖💬</h3>
<p>double quotes(&quot;&quot;)를 사용하는 것과 new 연산자를 사용하는 것은 String 객체가 만들어지고 메모리에 어떻게 저장되는지에 따라 달라.</p>
<p><code>String greeting = &quot;Hello&quot;;</code>
이렇게 String 객체를 만들 때는, string pool이라고 부르는 특수한 메모리 영역에 이미 <code>Hello</code>가 있는지 없는지 확인해. 이미 존재하는 경우라면, Java는 string pool에 있는 기존 객체에 대한 참조를 반환해. 만약 없는 경우라면, Java는 string pool에 새로운 객체를 만들고 해당 객체에 대한 참조를 반환하지.</p>
<p><code>String greeting = new String(&quot;Hello&quot;);</code>
반면 new 연산자로 String 객체를 만들 때는, 힙 영역에 새로운 객체가 생성되고 해당 객체에 대한 참조가 반환되는 거야. new 연산자로 만든 String 객체는 string pool에 저장되지 않아.</p>
<p>일반적으로 전자의 방식이 후자의 방식보다 더 효율적이야. string pool을 사용하고, 힙 영역에 계속 새로운 객체를 생성하는 오버헤드를 피할 수 있거든. 하지만 다른 객체와 구별되는 참조를 사용하기 위해 새 객체를 만들어야 하는 경우에는 new 연산자를 사용해야 할 수도 있지.</p>
<p>두 방식의 차이점을 보여줄게.</p>
<pre><code>String s1 = &quot;Hello&quot;;
String s2 = &quot;Hello&quot;;
String s3 = new String(&quot;Hello&quot;);
String s4 = new String(&quot;Hello&quot;);

System.out.println(s1 == s2); // true
System.out.println(s1 == s3); // false
System.out.println(s3 == s4); // false</code></pre><p>여기서 s1과 s2는 string pool에 있는 동일한 String 객체에 대한 참조니까 <code>s1 == s2</code>의 결과는 true야.
반면, s3와 s4는 힙 영역에 있는 두 개의 개별 객체에 대한 참조니까 <code>s3 == s4</code>의 결과는 false지.</p>
<p><img src="https://velog.velcdn.com/images/ariul-dev/post/6eafdb42-f5e9-4b9f-99fe-e4325f5bb316/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/ariul-dev/post/928741af-6add-4c18-b8d5-2d109ee45b1e/image.png" alt=""></p>
<h3 id="🙋♀️-string-pool이랑-heap이-달라-string-pool은-어디에-있는데">🙋‍♀️ string pool이랑 heap이 달라? string pool은 어디에 있는데?</h3>
<p><img src="https://velog.velcdn.com/images/ariul-dev/post/5d522def-8389-4a30-beed-0f44dfd8ea39/image.png" alt=""></p>
<h3 id="🤖💬-3">🤖💬</h3>
<p>string pool이랑 heap은 다른 메모리 영역이야.</p>
<p><strong>string pool</strong>은 객체가 저장되는 <code>힙 영역 내의 특수 메모리 영역</code>이야. string pool의 목적은 String 객체 스토리지를 최적화하고, String 객체에 의해 사용되는 메모리 양을 줄이는 거야.</p>
<p>반면, <strong>heap 영역</strong>은 String 객체를 포함한 <code>모든 객체가 저장되는 Java의 일반 메모리 영역</code>이야.</p>
<p>유의할 점은 string pool과 heap 영역 모두 JVM(Java Virtual Machine) 메모리의 일부라는 것!
JVM 메모리는 용도에 따라 여러 영역으로 나뉘고, string pool은 이런 영역 중 하나야.</p>
<p><img src="https://velog.velcdn.com/images/ariul-dev/post/85f04d52-96b9-4814-be60-dcad7f6d4fc4/image.png" alt=""></p>
<p>JVM 메모리와 관련해서 더 자세히 알려달라고 했는데, 위에서 말한 거랑 비슷한 내용이네요.
<img src="https://velog.velcdn.com/images/ariul-dev/post/e0361bc1-db45-47e7-95a4-0ed819b2c82e/image.png" alt=""></p>
<p>정리하자면,</p>
<blockquote>
</blockquote>
<p><strong>1) double quotes(&quot;&quot;)로 String 객체 생성</strong>
string pool에 이미 동일한 String 객체가 있는지 확인합니다. 있다면, 새로 객체를 생성하지 않고 이미 있는 객체에 대한 참조를 반환하므로 String 객체에 사용되는 메모리 양을 줄일 수 있는 것입니다.</p>
<blockquote>
</blockquote>
<p><strong>2) new 연산자로 String 객체 생성</strong>
new 연산자로 만든 String 객체는 string pool에 저장되지 않습니다. 힙 영역에 새로운 객체가 생성되고 해당 객체에 대한 참조가 반환됩니다. 즉, new 연산자로 생성된 각 객체는 메모리에서 별도의 물리적 객체이므로 String 객체에 사용되는 메모리 양이 증가하는 것입니다.</p>
<blockquote>
</blockquote>
<p>string pool은 JVM의 선택적 기능이므로 일부 JVM은 String pool을 구현하지 않을 수도 있습니다. 하지만 대부분의 JVM에서 string pool이 지원되며 Java 플랫폼의 표준으로 간주됩니다.</p>
<h3 id="🙋♀️-string이-string-pool에-있는지-자바가-어떻게-확인해-동작-원리가-뭐야">🙋‍♀️ String이 string pool에 있는지 자바가 어떻게 확인해? 동작 원리가 뭐야?</h3>
<h3 id="🤖💬-4">🤖💬</h3>
<p>double quotes(&quot;&quot;)로 String 객체를 만들 때, Java는 string pool에 String 객체가 이미 있는지 확인한다고 했지? 이건 <code>interning</code> 이라고 부르는 프로세스로 수행되는 거야. <code>interning</code> 은 JVM이 string pool에 있는 각 String 객체의 복사본이 오직 하나만 있다는 것을 보장하려고 사용하는 기술이야.</p>
<p>interning 프로세스를 살펴보면,</p>
<blockquote>
</blockquote>
<ol>
<li>double quotes(&quot;&quot;)를 사용하여 String 객체가 생성되면, JVM은 string pool에 이미 존재하는지 확인한다.</li>
<li>string pool에 이미 있는 경우, JVM은 string pool에 있는 기존 String 객체에 대한 참조를 반환한다.</li>
<li>string pool에 없는 경우, JVM은 heap 영역에 새로운 String 객체를 만들고 이를 string pool에 추가한다.</li>
<li>그러고 나면, JVM이 string pool에 있는 새로운 String 객체에 대한 참조를 반환한다.</li>
</ol>
<p>interning 프로세스는 해시 테이블로 구현됐는데, 그래서 JVM은 string pool 조회를 효율적으로 할 수 있지. 해시 테이블은 조회에 최적화되어 있어서 interning 프로세스를 빠르고 효율적으로 할 수 있어.</p>
<p><img src="https://velog.velcdn.com/images/ariul-dev/post/8e1421c0-6060-4a91-8a83-56d5d0af8b1e/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/ariul-dev/post/52c4a1cf-1fed-4f68-837c-f6ef480644e7/image.png" alt=""></p>
<h3 id="🙋♀️-interning-process-가-해시-테이블로-구현된다고-그게-뭔데">🙋‍♀️ interning process 가 해시 테이블로 구현된다고? 그게 뭔데?</h3>
<h3 id="🤖💬-5">🤖💬</h3>
<p>interning process는 해시 테이블을 사용해서 구현되는데, </p>
<p><strong>해시 테이블</strong>이란, <code>배열의 인덱스에 키를 매핑하기 위해서 해시 함수를 사용하는 데이터 구조</code>야.
해시 함수는 입력(키)을 받고, 그것에 대해 몇 가지 계산을 수행한 뒤 배열의 인덱스를 반환해.
해시 테이블의 기본 개념은 해시 함수를 사용해서 배열에서 특정 키의 위치를 빠르게 찾아내는 거야.</p>
<p>string pool의 경우, 해시 테이블은 String 객체를 string pool을 나타내는 배열의 인덱스에 매핑해. 해시 함수는 String 입력을 받고 배열의 인덱스를 반환하고. 해시 함수는 인덱스 전체에 키를 균등하게 분배하도록 설계되어서 해시 테이블의 조회가 빠르고 효율적이야.</p>
<p>JVM interning 프로세스는 string pool에 String 객체가 이미 있는지 확인할 때, 해시 함수를 사용하여 배열에 있는 String의 인덱스를 계산해. String 객체가 이미 string pool에 있는 경우라면, JVM은 계산된 인덱스에서 이를 찾고, 없다면 JVM이 배열에 추가하는 거지.</p>
<p>해시 테이블은 조회 시간이 빠르기 때문에 컴퓨터 과학에서 널리 사용되는데, 일반적으로 배열에서 요소를 검색하거나 사전에서 값을 찾는 것과 같은 작업에 사용되지. 해시 테이블은 JVM(Java Virtual Machine)에서 string pool을 구현하기 위한 효율적인 데이터 구조야.
<img src="https://velog.velcdn.com/images/ariul-dev/post/a619851f-ab2b-4eb5-a58d-b6f790970688/image.png" alt=""></p>
<hr>
<h2 id="번외-chatgpt-나-너-믿어도-되니">번외) ChatGPT, 나 너 믿어도 되니?</h2>
<p>꼬리에 꼬리를 물고 실컷 질문해놓고(;;) 
갑자기 얘(ChatGPT)를 어디까지 믿어도 될지 의심이 들어 물어봤습니다.</p>
<p><del>블로그 포스팅에 잘못된 정보를 쓰면 안 되니까 ,,🤭</del></p>
<h4 id="너가-말하는-거-100-확신해-나-너-믿는다">너가 말하는 거 100% 확신해? 나 너 믿는다?</h4>
<p><img src="https://velog.velcdn.com/images/ariul-dev/post/19136b89-85a8-4ab5-a94d-ea51b2632945/image.png" alt=""></p>
<p>어머 역시 똑똑도 하여라,
가능한 가장 정확한 정보를 제공하기 위해 노력하지만 모든 경우에 100% 정확성을 보장할 수는 없으니 cross-check 하라고 합니다.</p>
<p>근데 나의 cross-check은 구글링 아니면 개발 서적인데..? 싶어 다시 물었습니다.</p>
<h4 id="내가-구글에서-찾을-수-있는-내용들로-학습했니">내가 구글에서 찾을 수 있는 내용들로 학습했니?</h4>
<p><img src="https://velog.velcdn.com/images/ariul-dev/post/0ec555a2-b57b-4925-9052-a8c1b9d5fdbc/image.png" alt=""></p>
<p>오 구글, 책, 뉴스 기사, 과학 논문 같은 소스들로 교육받은 ChatGPT~
근데 2021년까지의 데이터들이라, 최근 정보는 반영되어 있지 않다고 하네요.</p>
<p>이 부분은 유의해서 사용해야겠습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[차근차근 알아보는 Java 프로그램 실행 과정]]></title>
            <link>https://velog.io/@ariul-dev/%EC%B0%A8%EA%B7%BC%EC%B0%A8%EA%B7%BC-%EC%95%8C%EC%95%84%EB%B3%B4%EB%8A%94-Java-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%A8-%EC%8B%A4%ED%96%89-%EA%B3%BC%EC%A0%95</link>
            <guid>https://velog.io/@ariul-dev/%EC%B0%A8%EA%B7%BC%EC%B0%A8%EA%B7%BC-%EC%95%8C%EC%95%84%EB%B3%B4%EB%8A%94-Java-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%A8-%EC%8B%A4%ED%96%89-%EA%B3%BC%EC%A0%95</guid>
            <pubDate>Thu, 02 Feb 2023 09:55:07 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/ariul-dev/post/4a635dce-3d25-43c4-8b14-fb2fed0e7226/image.png" alt=""></p>
<p><a href="https://d2.naver.com/helloworld/1230">네이버 기술 블로그의 JVM Internal</a> 을 읽던 중 그만 정신을 잃고 말았습니다.
아아.. 선생님 무슨 말인지 모르겠어요
.
.
.</p>
<p>수많은 레퍼런스를 찾아본 끝에, 
이제 조금은 정신이 드는 것 같아 정리해 보는 Java 프로그램 실행 과정!</p>
<hr>
<h1 id="🔍-한눈에-알아보기">🔍 한눈에 알아보기</h1>
<p><img src="https://velog.velcdn.com/images/ariul-dev/post/a05af3c6-88b9-4d5f-bccc-c8022aa7abfe/image.png" alt=""></p>
<h2 id="compile-time-환경">Compile Time 환경</h2>
<p>① <strong>자바 소스 코드 파일(.java)</strong>을 생성합니다.
② 이 파일을 <strong>자바 컴파일러(javac.exe)</strong>를 통해 <strong>자바 바이트 코드 파일(.class)</strong>로 컴파일합니다. </p>
<h2 id="runtime-환경">Runtime 환경</h2>
<p>③ 컴파일된 자바 바이트 코드 파일(.class)을 Runtime으로 가져가는 시점에 <strong>클래스 로더(Class Loader)</strong>가 동작합니다.
④ 클래스 로더(Class Loader)가 <strong>동적 로딩(Dynamic Loading)</strong>을 통해 자바 바이트 코드를 <strong>런타임 데이터 영역(Runtime Data Areas)</strong>, 즉 JVM의 메모리에 로드합니다.
⑤ <strong>실행 엔진(Execution Engine)</strong>은 JVM 메모리에 적재된 바이트 코드들을 명령어 단위로 읽어서 실행합니다.</p>
<blockquote>
<h4 id="💡-compile-time-runtime">💡 Compile Time? Runtime?</h4>
<p><strong>컴파일 타임(Compile Time)</strong>
컴퓨터는 0과 1로 이루어진 기계어만 이해할 수 있기 때문에 개발자가 작성한 소스 코드를 기계어로 변환해 주어야 합니다. 이 역할을 하는 것이 컴파일러이며, 이를 통해 실행 가능한 프로그램이 되는 과정을 컴파일 타임이라고 합니다.</p>
</blockquote>
<p>[주의📌] Java의 경우, C나 C++이 컴파일하면 생성되는 기계어와 동일하게 생각하면 안 됩니다. 자바 언어를 컴파일 하면 바이트 코드(중간 코드)가 생성되는데, 이는 컴퓨터가 이해할 수 없기 때문입니다. 자바가 컴파일한 언어를 이해할 수 있는 기계는 컴퓨터가 아니라 JVM(Java Virtual Machine)입니다.</p>
<blockquote>
</blockquote>
<p><strong>런타임(Runtime)</strong>
컴파일 과정을 마친 프로그램이 사용자에 의해 실행되는 때를 의미합니다.</p>
<hr>
<h1 id="how-is-java-platform-independent">How is Java platform-independent?</h1>
<blockquote>
<h4 id="💡-플랫폼platform이란">💡 플랫폼(Platform)이란?</h4>
<p>운영체제(OS) + CPU 아키텍처</p>
</blockquote>
<p>C/C++ 등의 컴파일러는 고수준 언어를 기계어, 즉 직접적인 CPU 명령으로 변환합니다. 따라서 컴파일러가 생성한 <code>.exe</code> 파일은 플랫폼마다 다르고, 다른 플랫폼과 호환되지 않습니다. 즉, 컴파일 플랫폼과 타겟 플랫폼이 다르면 프로그램이 동작하지 않으며, 이를 <code>플랫폼에 종속적</code>이라고 합니다.</p>
<p>이와 달리, Java 컴파일러(javac)는 개발자가 이해하는 자바 언어를 직접적인 CPU 명령이 아니라 <strong><code>JVM(Java Virtual Machine)이 이해하는 자바 바이트 코드(.class)</code></strong>로 변환합니다. 자바 바이트 코드는 플랫폼에 의존적인 코드가 없기 때문에 JVM이 설치된 장비라면 CPU나 운영체제가 다르더라도 실행될 수 있으며, 이를 <strong><code>플랫폼에 독립적</code></strong>이라고 합니다. </p>
<h3 id="jvmjava-virtual-machine">JVM(Java Virtual Machine)</h3>
<p>JVM은 <strong>자바 바이트 코드 파일(.class)을 읽어 실행할 수 있는 Virtual Machine</strong>을 의미합니다.</p>
<p>Virtual Machine을 더 풀어 설명해 보겠습니다. </p>
<blockquote>
</blockquote>
<p><strong>Virtual</strong> : 물리적인 형태가 아닌 소프트웨어로서 <code>하나의 개념</code>으로 존재하며,
<strong>Machine</strong> : <code>독자적으로 작동할 수 있는 메커니즘과 구조</code>를 가지고 있어 하나의 축약된 컴퓨터와 같은 의미인 것 </p>
<p>따라서, JVM 명세(The Java Virtual Machine Specification)를 따르기만 하면 어떤 벤더든 JVM을 개발하여 제공할 수 있습니다. 대표적인 Oracle의 Hotspot JVM 외에도 IBM JVM을 비롯한 다양한 JVM이 존재합니다. </p>
<blockquote>
<h4 id="💡-jvm-개념에-대한-나의-오해">💡 JVM 개념에 대한 나의 오해</h4>
</blockquote>
<p>처음에 JVM에 대한 레퍼런스를 읽으면서 혼란스러웠던 기억이 납니다. 똑같이 JVM의 구성 요소에 대해 설명하고 있는데, 어떤 레퍼런스에는 없는 내용이 다른 레퍼런스에는 있고, 같은 기능을 다른 이름으로 표기하는 등 레퍼런스마다 제공하는 정보가 달랐기 때문입니다. <code>다 같은 JVM 아닌가? 왜 설명이 다 다르지?</code> 라고 생각했는데 정말 다 다른 JVM이었습니다.😅 </p>
<hr>
<h1 id="compile-time">Compile Time</h1>
<p><img src="https://velog.velcdn.com/images/ariul-dev/post/93196696-60a5-4d12-afa9-bf03e857ad37/image.png" alt=""></p>
<p>자, 이제 <code>🔍 한눈에 알아보기</code>의 내용들을 하나씩 설명해 보겠습니다.</p>
<p>먼저, 개발자가 <strong>자바 소스 코드 파일(.java)을 생성</strong>하고, <strong>자바 컴파일러(javac.exe)</strong>가 이 소스 코드 파일을 <strong>자바 바이트 코드 파일(.class)로 컴파일</strong>한다고 했습니다. </p>
<p>그리고 이 모든 일은 JDK(Java Development Kit)에서 이루어집니다. </p>
<h2 id="jdkjava-development-kit">JDK(Java Development Kit)</h2>
<p>JDK는 자바 개발 키트(Java Development Kit)의 약자로 개발자들이 자바로 개발하는 데 사용되는 SDK 키트라 생각하면 됩니다.</p>
<p>그래서 JDK 안에는 자바를 개발할 때 필요한 라이브러리들과 컴파일러, 디버거 등의 개발 도구들이 포함되어 있고, 개발을 하려면 자바 프로그램을 실행도 시켜줘야 하기 때문에 뒤에서 배울 JRE(Java Runtime Environment)도 함께 포함되어 있습니다.</p>
<p>정리하면, JDK로 소스 코드를 작성하고 이를 컴파일하며, 그 결과물인 바이트 코드(.class)를 JRE에게 전달합니다. </p>
<blockquote>
<h4 id="💡-jdk와-jre이-차이는">💡 JDK와 JRE이 차이는?</h4>
<p><strong>JRE(Java Runtime Environment)</strong>
Java 응용 프로그램을 실행하는 데 필요한 최소 환경입니다. 여기에는 클래스 라이브러리, JVM(Java Virtual Machine) 및 배포 도구가 포함됩니다. 이러한 소프트웨어 구성 요소를 사용하여 모든 디바이스에서 바이트 코드를 실행합니다.</p>
</blockquote>
<p><strong>JDK(Java Development Kit)</strong>
Java 애플리케이션을 개발하고 실행하는 데 사용되는 완전한 개발 환경입니다. JRE와 개발 도구를 모두 포함합니다.</p>
<blockquote>
</blockquote>
<p>정리하면, 자바 개발 도구인 JDK를 이용해 개발된 프로그램은 JRE에 의해 가상의 컴퓨터인 JVM 상에서 구동됩니다. </p>
<hr>
<h1 id="runtime">Runtime</h1>
<p>앞서, 컴파일된 자바 바이트 코드 파일(.class)을 Runtime으로 가져가는 시점에 클래스 로더(Class Loader)가 동작한다고 했습니다. </p>
<p>컴파일된 자바 바이트 코드 파일(.class)을 Runtime으로 가져가는 시점, 즉 자바 애플리케이션을 실행하는 시점은 <code>java</code> 명령어를 입력할 때입니다. </p>
<p><code>java</code> 명령어는 먼저 JRE(Java Runtime Environment)를 시작하고,
인자로 지정된 클래스(static main() 메서드를 포함하고 있는 클래스)를 로딩하며, main() 메서드를 호출합니다.</p>
<p>이 과정을 알아보겠습니다.</p>
<h2 id="class-loader">Class Loader</h2>
<p>자바 컴파일러를 통해 <code>.class</code> 확장자를 가지게 된 클래스 파일들은 각 디렉터리에 흩어져 있습니다. 또한, 기본적인 라이브러리의 클래스 파일들도 $JAVAHOME_ 내부 경로에 존재합니다. 이렇게 흩어져 있는 각각의 클래스 파일들을 찾아서 <strong>동적 로딩(Dynamic Loading) 방식으로 런타임 데이터 영역(Runtime Data Areas), 즉 JVM의 메모리에 탑재해 주는 것이 바로 클래스 로더(Class Loader)의 역할</strong>입니다.</p>
<blockquote>
<h4 id="💡--동적-로딩dynamic-loading이란">💡  동적 로딩(Dynamic Loading)이란?</h4>
<p>프로세스가 시작될 때 그 프로세스의 주소 공간 전체를 메모리에 올려놓는 것이 아니라, 필요한 루틴이 호출될 때 해당 루틴을 메모리에 적재하는 방식을 말합니다. 즉, 필요한 시점에만 올리니까 메모리를 좀 더 효율적으로 사용할 수 있습니다.</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/ariul-dev/post/cf5f3bbc-3b8d-424f-88d3-97bed06e2e5b/image.png" alt=""></p>
<p>클래스 로더는 크게 <code>Loading</code>, <code>Linking</code>, 그리고 <code>Initialization</code> 3가지 역할을 맡습니다. 
<code>Loading</code>은 클래스 파일을 탑재하는 과정이고, <code>Linking</code>은 클래스 파일을 사용하기 위해 검증하고, 기본 값으로 초기화하는 과정입니다. <code>Initialization</code>은 정적 필드(static field)의 값들을 코드 상에서 정의한 값으로 초기화하는 과정입니다.</p>
<h3 id="❶-loading">❶ Loading</h3>
<p>컴파일된 클래스(.class)를 메모리에 로드하는 것은 클래스 로더의 주요 작업입니다. 일반적으로 클래스 로드 프로세스는 메인 클래스(즉, static main() 메서드 선언이 있는 클래스)를 로드하는 것부터 시작합니다. 이때, 클래스 로더들은 아래 4가지 원칙들을 지키며 클래스를 로드합니다. </p>
<h4 id="①-delegation-hierarchy-principle위임-계층-원칙">① Delegation Hierarchy Principle(위임 계층 원칙)</h4>
<p>클래스 로더는 아래 그림과 같이 계층 구조로 이루어져 있습니다. 
<img src="https://velog.velcdn.com/images/ariul-dev/post/3928804d-752d-4c04-8858-c70085bd693b/image.png" alt=""></p>
<ul>
<li><p><strong>Bootstrap Class Loader</strong>
  JVM을 기동할 때 생성되며, Object 클래스들을 비롯하여 자바 API들을 로드합니다. 다른 클래스 로더와 달리 자바가 아니라 네이티브 코드로 구현되어 있습니다.</p>
</li>
<li><p><strong>Extension Class Loader</strong>(Java 9부터는 Platform Class Loader)
  기본 자바 API를 제외한 확장 클래스들을 로드합니다. 다양한 보안 확장 기능 등을 여기에서 로드하게 됩니다.</p>
</li>
<li><p><strong>Application Class Loader</strong>(Java 9부터 System Class Loader)
  부트스트랩 클래스 로더와 익스텐션 클래스 로더가 JVM 자체의 구성 요소들을 로드하는 것이라 한다면, 애플리케이션 클래스 로더는 애플리케이션의 클래스들을 로드한다고 할 수 있습니다. 사용자가 지정한 $CLASSPATH 내의 클래스들을 로드합니다.</p>
<blockquote>
<h4 id="💡-java-9-이후-변화">💡 Java 9 이후 변화</h4>
<p>Java 9 에서도 기본 클래스 로더의 3계층 구조와 3가지 원칙은 유효합니다. 다만 모듈 시스템 도입에 맞춰 이름과 범위, 구현 내용 등이 바뀌었습니다.</p>
</blockquote>
</li>
</ul>
<p>클래스 로더가 클래스 로드를 요청받으면, 클래스 로더 캐시, 상위 클래스 로더, 자기 자신의 순서로 해당 클래스가 있는지 확인합니다. 즉, 이전에 로드된 클래스인지 클래스 로더 캐시를 확인하고, 없으면 상위 클래스 로더를 거슬러 올라가며 확인합니다. 부트스트랩 클래스 로더까지 확인해도 없으면 요청받은 클래스 로더가 파일 시스템에서 해당 클래스를 찾습니다.</p>
<h4 id="②-visibility-principle가시성-원칙">② Visibility Principle(가시성 원칙)</h4>
<p>가시성 원칙은 하위 클래스 로더는 상위 클래스 로더가 로딩한 클래스를 볼 수 있지만, 상위 클래스 로더는 하위 클래스 로더가 로딩한 클래스를 볼 수 없다는 원칙입니다.</p>
<h4 id="③-uniqueness-principle유일성-원칙">③ Uniqueness Principle(유일성 원칙)</h4>
<p>유일성 원칙은 상위 클래스 로더에 의해 로드된 클래스가 하위 클래스 로더에 의해 다시 로드되지 않게 하여 유일성을 보장(<code>중복된 클래스 로드 X</code>)하는 원착압니다.</p>
<p>이러한 유일성을 지키기 위해서 Visibility Principle 이외에도 Class Binary name을 이용하는데, 이를 FQCN, Fully Qualified Class Name이라고 합니다. 이미 로드된 클래스인지 확인하기 위해서는 네임스페이스(Namespace)에 보관된 FQCN을 기준으로 클래스를 찾아보고, 없다면 위임 모델을 통해서 클래스를 로드합니다.</p>
<blockquote>
<h4 id="💡-namespace-fqcn">💡 Namespace? FQCN?</h4>
<p><strong>FQCN</strong>
패키지명 + 클래스명</p>
</blockquote>
<p><strong>네임스페이스(Namespace)</strong>
각 클래스 로더마다 가지고 있으며, 로드된 클래스를 보관하는 공간입니다. 클래스를 로드할 때 위임 모델을 통해서 상위 클래스 로더들을 확인하는데, 그 때 확인하는 공간이 네임스페이스입니다.</p>
<blockquote>
</blockquote>
<p>클래스 로더마다 각자 네임스페이스를 가지고 있기 때문에, FQCN이 같은 클래스라도 네임스페이스가 다르면 다른 클래스로 간주합니다.</p>
<h4 id="④-no-unloading-principle언로드-금지-원칙">④ No Unloading Principle(언로드 금지 원칙)</h4>
<p>클래스 로더는 클래스를 로드할 수 있지만 로드된 클래스를 언로드할 수 없습니다. 언로드하는 대신 현재 클래스 로더를 삭제하고 새 클래스 로더를 만들 수 있습니다.</p>
<h3 id="❷-linking">❷ Linking</h3>
<p><code>Linking</code>은 로드된 클래스 파일들을 검증하고, 사용할 수 있게 준비하는 과정을 의미합니다. Linking 또한 <code>Verification</code>, <code>Preparation</code>, 그리고 <code>Resolution</code>이라는 세 가지 단계로 이루어져 있습니다.</p>
<h4 id="①-verification">① Verification</h4>
<p>클래스 로더가 <code>.class</code> 파일의 바이트 코드를 자바 언어 명세(Java Language Specification)에 따라서 제대로 잘 작성했는지, JVM 규격에 따라 검증된 컴파일러에서 <code>.class</code> 파일이 생성되는지 등을 확인하여 <code>.class</code> 파일의 정확성을 확인하는 단계입니다. 내부적으로 바이트 코드 검증기(Bytecode verifier)가 이 과정을 담당합니다. 이 과정은 클래스를 로드하는 과정 중 가장 복잡한 테스트 과정이며, 가장 오랜 시간이 걸립니다. 링크로 인해 클래스를 로드하는 과정이 느려지지만 바이트 코드를 실행할 때 이런 검사를 여러 번 수행할 필요가 없기 때문에 전반적으로 효율적이며 효과적입니다. 바이트코드 검증기는 검증이 실패하면 런타임 에러(java.lang.VerifyError)를 발생시킵니다. </p>
<h4 id="②-preparation">② Preparation</h4>
<p>이 단계에서는 메서드 테이블 같이 JVM에서 쓰이는 자료구조나 static storage을 위해 메모리를 할당합니다. 또한, 이 단계에서 정적 필드(static field)가 만들어지고 기본값으로 초기화됩니다. 코드에 작성한 원래 값은 Initialization(초기화) 단계에서 할당되므로 아직은 초기화 블록이나 초기화 코드가 실행되지 않습니다.</p>
<h4 id="③-resolution">③ Resolution</h4>
<p>이 단계에서는 JVM 메모리 구성 요소인 Method Area 내의 런타임 상수 풀(run-time constant pool)에 있는 <code>심볼릭 참조(symbolic reference)</code>를 <code>직접 참조(direct reference)</code>로 대체합니다. 다시 말해서, 추상적인 기호를 구체적인 값으로 동적으로 결정하는 과정이라고 할 수 있습니다. JVM 명령인 anewarray, checkcast, getfield, getstatic, instanceof, invokedynamic, invokeinterface, invokespecial, invokestatic, invokevirtual, ldc, ldc_w, multianewarray, new, putfield, putstatic은 런타임 상수 풀에 있는 심볼릭 참조를 사용합니다.</p>
<blockquote>
<h4 id="💡-심볼릭-참조symbolic-reference와-직접-참조direct-reference">💡 심볼릭 참조(symbolic reference)와 직접 참조(direct reference)</h4>
<p>심볼릭 참조(symbolic reference)란 우리가 코드를 작성하면서 사용한 class, field, method의 이름을 지칭합니다. Resolution 단계는 class, field, method 그리고 constant pool의 symbolic references를 실제 메모리 주소로 변환합니다. </p>
</blockquote>
<h3 id="❸-initialization">❸ Initialization</h3>
<p>Linking 과정을 거치면 Initialization 단계에서 클래스 파일의 코드를 읽게 됩니다. 이 단계는 코드에 명시된 원래 값이 정적 변수에 할당되고, 정적 초기화 블록이 실행되는 클래스 로딩의 마지막 과정입니다. 이 작업은 클래스의 위에서 아래로 실행되며, 클래스 계층 구조에서는 부모에서 자식까지 한 줄씩 실행됩니다. 클래스 로더를 통한 클래스 탑재 과정이 끝나면 본격적으로 JVM에서 클래스 파일을 구동시킬 준비를 마치게 됩니다.</p>
<hr>
<h2 id="runtime-data-areas">Runtime Data Areas</h2>
<p>JVM은 프로그램의 실행에 사용되는 메모리를 <strong>런타임 데이터 영역(Runtime Data Areas)</strong>이라고 부르는 몇 가지 영역으로 나눠서 관리합니다.
<img src="https://velog.velcdn.com/images/ariul-dev/post/9dedc0fa-85e2-4164-a199-5dfe85100b0f/image.png" alt=""></p>
<p><code>JVM 단위</code>에 속하는 <strong>힙과 메서드 영역</strong>은 JVM이 시작될 때 생성되고, JVM이 종료될 때 소멸되며, JVM 하나에 힙과 메서드 영역이 하나씩가 생성됩니다. 즉, 모든 JVM 스레드는 동일한 힙 영역과 메서드 영역을 공유합니다.</p>
<p>마찬가지로 <code>클래스 단위</code>에 속하는 <strong>런타임 상수 풀</strong>은 클래스가 생성/소멸될 때 함께 생성/소멸되며, 클래스 하나에 런타임 상수 풀도 하나가 생성 됩니다.</p>
<p><code>스레드 단위</code>에 속하는 <strong>PC 레지스터, JVM 스택, 네이티브 메서드 스택</strong>도 스레드가 생성/소멸될 때 함께 생성/소멸되며, PC 레지스터, JVM 스택, 네이티브 메서드 스택은 스레드 당 각각 하나씩 생성됩니다.</p>
<h3 id="method-area스레드-간-공유">Method Area(스레드 간 공유)</h3>
<p><code>Method Area</code>에는 <u>인스턴스 생성을 위한 객체 구조, 생성자, 필드 등이 저장</u>됩니다. <u>런타임 상수 풀(Runtime Constant Pool)과 정적(static) 변수, 그리고 메서드 데이터와 같은 클래스 데이터들도 이곳에서 관리</u>됩니다. 이 영역은 JVM 당 하나만 생성되는데, 인스턴스 생성에 필요한 정보도 존재하기 때문에 <strong>JVM의 모든 스레드들이 Method Area를 공유</strong>하게 됩니다. 그리고 JVM의 다른 메모리 영역에서 해당 정보에 대한 요청이 오면, 실제 물리 메모리 주소로 변환해서 전달해줍니다. Method Area는 기초 역할을 하므로 JVM이 구동될 때 생성되며, 종료될 때까지 유지되는 공통 영역입니다.</p>
<h3 id="heap스레드-간-공유">Heap(스레드 간 공유)</h3>
<p><code>Heap 영역</code>에는 <u>Java로 구성된 객체 및 JRE 클래스들이 탑재</u>됩니다. 이곳에는 <u>문자열에 대한 정보를 가진 String Pool 뿐만 아니라, 실제 데이터를 가진 인스턴스, 배열 등이 저장</u>됩니다. Heap 영역 역시 JVM 당 하나만 생성되고, <strong>해당 영역이 가진 데이터는 모든 JVM Stack 영역에서 참조되어, 스레드 사이에서 공유됩니다.</strong> 그리고 Heap 영역이 가득 차게 되면 OutOfMemoryError를 발생시키게 됩니다.</p>
<h3 id="jvm-stacks스레드-별-할당">JVM Stacks(스레드 별 할당)</h3>
<p>스레드가 시작되면 메서드 호출을 저장하기 위해 별도의 <code>런타임 스택</code>이 생성됩니다. 모든 메서드 호출에 대해 하나의 엔트리가 생성되고 런타임 스택의 맨 위에 추가(push)되는데, 이러한 엔트리를 <code>스택 프레임(Stack Frame)</code>이라고 합니다.</p>
<p><u>각 스택 프레임은 실행 중인 메서드가 속한 클래스의 로컬 변수 배열(Local Variable Array), 피연산자 스택(Operand Stack) 및 런타임 상수 풀에 대한 참조(Reference to Constant Pool)를 가지고 있습니다.</u> 로컬 변수 배열은 메서드 안의 지역 변수들을 가지고 있습니다. 피연산자 스택은 메서드 내 연산을 위해서 바이트 코드 명령문들이 들어있는 공간입니다. 상수 풀에 대한 참조는 Constant Pool 참조를 위한 공간입니다. 이렇게 구성된 <strong>JVM Stack에는 메서드가 호출될 때마다 프레임(Frame)이 쌓이게 됩니다.</strong> 그리고 메서드가 정상적으로 반환되거나 메서드 호출 중에 예외가 발생하면 프레임이 제거(pop)됩니다. </p>
<h3 id="pcprogram-counter-registers스레드-별-할당">PC(Program Counter) Registers(스레드 별 할당)</h3>
<p>자바에서 스레드는 각자의 메서드를 실행합니다. 이때, 스레드 별로 동시에 실행하는 환경이 보장되어야 하므로 현재 실행 중인 JVM에서는 명령어 주소 값(Method Area의 메모리 주소)을 저장할 공간이 필요합니다. 이 부분을 PC Registers 영역이 관리하여 추적하며, 스레드들은 각각 자신만의 PC Registers를 가지고 있습니다. 
만약 실행했던 메서드가 네이티브하다면 undefined가 기록됩니다. 실행했던 메서드가 네이티브하지 않다면, PC Registers는 JVM에서 사용된 명령의 주소 값을 저장하게 됩니다. 실행이 완료되면 PC 레지스터는 다음 명령의 주소로 업데이트됩니다.</p>
<h3 id="native-method-stacks스레드-별-할당">Native Method Stacks(스레드 별 할당)</h3>
<p>자바로 작성된 프로그램을 실행할 때, 순수하게 자바로 구성된 코드만을 사용할 수 없는 시스템의 자원이나 API가 존재합니다. 다른 프로그래밍 언어로 작성된 메서드들을 Native Method라고 하며, Native Method Stacks는 자바로 작성되지 않은 메서드 정보를 저장하는 영역입니다. 각각의 스레드들이 생성되면 Native Method Stacks도 스레드 별로 생성됩니다. 또한 앞의 JVM Stacks 영역처럼, Native Method가 실행되면 Stack에 해당 메서드가 쌓이게 됩니다.</p>
<hr>
<h2 id="execution-engine">Execution Engine</h2>
<p><strong>실행 엔진(Execution Engine)</strong>은 위의 <u>런타임 데이터 영역에 할당된 데이터를 읽어 바이트 코드의 명령을 한 줄씩 실행합니다.</u> 그런데 자바 바이트 코드는 기계가 바로 수행할 수 없기 때문에, 실행 엔진은 JVM 내부에서 2가지 방식을 통해 자바 바이트 코드를 기계가 실행할 수 있는 형태로 변경합니다. </p>
<p><img src="https://velog.velcdn.com/images/ariul-dev/post/8efef971-d7a5-4a00-9223-e2d07dfe8d18/image.png" alt=""></p>
<h3 id="interpreter">Interpreter</h3>
<p><code>인터프리터</code>는 바이트 코드 명령어를 하나씩 읽어서 해석하고 실행합니다. 하나씩 해석하고 실행하기 때문에 바이트 코드 하나하나의 해석은 빠르지만, 해석된 결과의 실행은 느리다는 단점을 가지고 있습니다. 이는 흔히 얘기하는 인터프리터 언어의 단점을 그대로 가지는 것입니다. 즉, 바이트 코드라는 &#39;언어&#39;는 기본적으로 인터프리터 방식으로 동작합니다.</p>
<h3 id="jitjust-in-time-컴파일러">JIT(Just-In-Time) 컴파일러</h3>
<p>만약 인터프리터만 사용할 수 있는 경우라면, 하나의 메서드가 여러 번 호출될 때마다 인터프리터를 작동해야 합니다. 
이런 인터프리터의 단점을 보완하기 위해 도입된 것이 <code>JIT 컴파일러</code>입니다. 인터프리터 방식으로 실행하다가 적절한 시점에 바이트코드 전체를 컴파일하여 네이티브 코드로 변경하고, 이후에는 해당 메서드를 더 이상 인터프리팅하지 않고 네이티브 코드로 직접 실행하는 방식입니다. 네이티브 코드를 실행하는 것이 하나씩 인터프리팅하는 것보다 빠르고, 네이티브 코드는 캐시에 보관하기 때문에 한 번 컴파일된 코드는 계속 더 빨리 실행할 수 있습니다.</p>
<p>그러나 JIT 컴파일러의 경우에도 단점이 있습니다. JIT 컴파일러가 컴파일하는 과정은 인터프리터가 바이트 코드를 하나씩 해석하는 것보다 훨씬 오래 걸리기 때문입니다. 그래서 만약 한 번만 실행되는 코드라면, 컴파일하지 않고 인터프리팅하는 것이 훨씬 좋습니다. 또한 네이티브 코드는 캐시에 저장되는데, 이는 비싼 자원입니다.
따라서, JIT 컴파일러를 사용하는 JVM들은 내부적으로 해당 메서드가 얼마나 자주 수행되는지 체크하고, 일정 정도를 넘을 때에만 컴파일을 수행합니다.</p>
<h4 id="jit-컴파일러-동작-과정">JIT 컴파일러 동작 과정</h4>
<ul>
<li><strong>JIT 컴파일러의 중간 코드 생성기(Intermediate Representation Generator)</strong>
  일단 바이트 코드를 중간 단계의 표현인 IR(Intermediate Representation)로 변환합니다.</li>
<li><strong>Code Optimizer</strong>
  위에서 생성된 중간 코드를 최적화하는 역할을 합니다.</li>
<li><strong>타겟 코드 생성기(Target Code Generator)</strong>
  네이티브 코드(즉, 기계 코드) 생성을 담당합니다.</li>
<li><strong>Profiler</strong>
  &#39;핫스팟&#39;(ex. 하나의 메서드를 여러 번 호출하는 인스턴스)과 같은 성능 병목 현상을 찾는 특수 구성 요소입니다.</li>
</ul>
<h3 id="runtime-정리">Runtime 정리</h3>
<blockquote>
<p>클래스 로더(Class Loader)가 컴파일된 자바 바이트 코드를 런타임 데이터 영역(Runtime Data Areas)에 로드하고, 실행 엔진(Execution Engine)이 자바 바이트 코드를 실행한다.</p>
</blockquote>
<hr>
<blockquote>
<p>📌 이 글은 Java 프로그램 실행 과정에 대해 학습한 내용을 정리한 글입니다. <strong>잘못된 내용은 피드백 부탁드립니다!</strong></p>
</blockquote>
<h2 id="reference">Reference</h2>
<ul>
<li><a href="https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-2.html">Chapter 2. The Structure of the Java Virtual Machine</a></li>
<li><a href="https://d2.naver.com/helloworld/1230">JVM Internal</a></li>
<li><a href="https://homoefficio.github.io/2018/10/13/Java-%ED%81%B4%EB%9E%98%EC%8A%A4%EB%A1%9C%EB%8D%94-%ED%9B%91%EC%96%B4%EB%B3%B4%EA%B8%B0/">Java ClassLoader 훑어보기</a></li>
<li><a href="https://blog.hexabrain.net/397">JVM. 클래스로더 서브시스템(Class Loader Subsystem)</a></li>
<li><a href="https://medium.com/platform-engineer/understanding-jvm-architecture-22c0ddf09722">Understanding JVM Architecture</a></li>
<li><a href="https://tecoble.techcourse.co.kr/post/2021-07-15-jvm-classloader/">JVM에 관하여 - Part 2, ClassLoader</a></li>
<li><a href="https://tecoble.techcourse.co.kr/post/2021-08-09-jvm-memory/">JVM에 관하여 - Part 3, Run-Time Data Area</a></li>
<li><a href="https://12bme.tistory.com/382">[JVM Internal] JVM 메모리 구조</a></li>
<li><a href="https://inpa.tistory.com/entry/JAVA-%E2%98%95-JDK-JRE-JVM-%EA%B0%9C%EB%85%90-%EA%B5%AC%EC%84%B1-%EC%9B%90%EB%A6%AC-%F0%9F%92%AF-%EC%99%84%EB%B2%BD-%EC%B4%9D%EC%A0%95%EB%A6%AC">[JAVA] ☕ JDK / JRE / JVM 개념 &amp; 구성 원리 💯 완벽 총정리
</a></li>
<li><a href="https://www.youtube.com/watch?v=UzaGOXKVhwU">[10분 테코톡] 🎅무민의 JVM Stack &amp; Heap</a></li>
<li><a href="https://www.youtube.com/watch?v=6reapO0gLPs">[10분 테코톡] 🎹 김김의 JVM Specification</a></li>
</ul>
<h2 id="다시-읽어야-하는-문서">다시 읽어야 하는 문서</h2>
<ul>
<li><a href="https://homoefficio.github.io/2019/01/31/Back-to-the-Essence-Java-%EC%BB%B4%ED%8C%8C%EC%9D%BC%EC%97%90%EC%84%9C-%EC%8B%A4%ED%96%89%EA%B9%8C%EC%A7%80-1/">Back to the Essence - Java 컴파일에서 실행까지 - (1)</a></li>
<li><a href="https://homoefficio.github.io/2019/01/31/Back-to-the-Essence-Java-%EC%BB%B4%ED%8C%8C%EC%9D%BC%EC%97%90%EC%84%9C-%EC%8B%A4%ED%96%89%EA%B9%8C%EC%A7%80-2/">Back to the Essence - Java 컴파일에서 실행까지 - (2)</a></li>
<li><a href="https://code-run.tistory.com/61">[Java] Java의 실행원리 Deep Dive
</a></li>
<li><a href="https://d2.naver.com/helloworld/1230">JVM Internal</a></li>
<li><a href="https://velog.io/@youngerjesus/%EC%9E%90%EB%B0%94-JIT-%EC%BB%B4%ED%8C%8C%EC%9D%BC%EB%9F%AC">자바 JIT 컴파일러</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Git Commit Message Conventions]]></title>
            <link>https://velog.io/@ariul-dev/Convention-Git-Commit-Message-Conventions</link>
            <guid>https://velog.io/@ariul-dev/Convention-Git-Commit-Message-Conventions</guid>
            <pubDate>Sat, 05 Nov 2022 12:27:00 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p><strong><a href="https://gist.github.com/stephenparish/9941e89d80e2bc58a153">AngularJS Git Commit Message Conventions</a></strong>를 정리한 포스팅입니다.</p>
</blockquote>
<h1 id="커밋-메시지-컨벤션">커밋 메시지 컨벤션</h1>
<h2 id="목표">목표</h2>
<ul>
<li>스크립트로 <a href="http://CHANGELOG.md">CHANGELOG.md</a> 생성할 수 있다.</li>
<li><code>git bisect</code>로 중요하지 않은 커밋을 무시할 수 있다.<ul>
<li>git bisect : 커밋 히스토리를 이진 탐색 방법으로 좁혀 주기 때문에 이슈와 관련된 커밋을 최대한 빠르게 찾아낼 수 있도록 도와준다.</li>
<li>출처: <a href="https://git-scm.com/book/ko/v2/Git-%EB%8F%84%EA%B5%AC-Git%EC%9C%BC%EB%A1%9C-%EB%B2%84%EA%B7%B8-%EC%B0%BE%EA%B8%B0">https://git-scm.com/book/ko/v2/Git-도구-Git으로-버그-찾기</a></li>
</ul>
</li>
<li>커밋 히스토리를 볼 때 더 좋은 정보를 제공한다.</li>
</ul>
<hr>
<h3 id="1-changelogmd-생성"><strong>1. <a href="http://CHANGELOG.md">CHANGELOG.md</a> 생성</strong></h3>
<ul>
<li><p>변경 내역에는 다음 세 가지 내용이 포함된다.<br>  1) 새로운 기능</p>
<p>  2) 버그 수정</p>
<p>  3) 주요 변경 사항</p>
</li>
</ul>
<ul>
<li>관련 커밋에 대한 링크와 함께 배포 시 스크립트로 위 내용들을 생성할 수 있다.</li>
<li>물론 실제 배포 전에 이 변경 내역을 수정할 수 있다.</li>
</ul>
<p><strong>마지막 배포 이후의 모든 커밋 제목(커밋 메시지 첫 줄) 목록</strong></p>
<pre><code class="language-java">git log &lt;last tag&gt; HEAD --pretty=format:%s</code></pre>
<p><strong>이번 배포의 새로운 기능 조회</strong></p>
<pre><code class="language-java">git log &lt;last release&gt; HEAD --grep feature</code></pre>
<h3 id="2-중요하지-않은-커밋-무시"><strong>2. 중요하지 않은 커밋 무시</strong></h3>
<ul>
<li><p>아래와 같이 로직의 변화가 없는 커밋은 무시할 수 있다</p>
<ul>
<li>포맷 변화 (공백이나 빈 줄의 추가, 제거, 들여쓰기)</li>
<li>세미 콜론 누락</li>
<li>주석</li>
</ul>
</li>
<li><p><code>git bisect</code> 명령어를 이용해서 무시한다.</p>
<pre><code class="language-java">  git bisect skip $(git rev-list --grep irrelevant &lt;good place&gt; HEAD)</code></pre>
</li>
</ul>
<h3 id="3-커밋-히스토리를-볼-때-더-좋은-정보-제공"><strong>3. 커밋 히스토리를 볼 때 더 좋은 정보 제공</strong></h3>
<ul>
<li><p>일종의 “문맥” 정보를 추가하는 것이 좋다.</p>
</li>
<li><p>어떤 변경이 있었는지는 알 수 있지만 <strong>일관된 형식으로 작성하지 않은 경우</strong></p>
<pre><code class="language-java">  Fix small typo in docs widget (tutorial instructions)
  Fix test for scenario.Application - should remove old iframe
  docs - various doc fixes
  docs - stripping extra new lines
  Replaced double line break with single when text is fetched from Google
  Added support for properties in documentation</code></pre>
</li>
<li><p><strong>어디에 변경이 있는지 알 수 없는 경우</strong></p>
<pre><code class="language-java">  fix comment stripping
  fixing broken links
  Bit of refactoring
  Check whether links do exist and throw exception
  Fix sitemap include (to work on case sensitive linux)</code></pre>
</li>
</ul>
<hr>
<h2 id="커밋-메시지-포맷">커밋 메시지 포맷</h2>
<pre><code class="language-java">&lt;type&gt;(&lt;scope&gt;): &lt;subject&gt;
&lt;BLANK LINE&gt;
&lt;body&gt;
&lt;BLANK LINE&gt;
&lt;footer&gt;</code></pre>
<p>커밋 메시지의 각 줄은 100자를 넘기지 않아야 한다. 그래야 GitHub 등의  도구에서 읽기 쉽다.</p>
<h3 id="subject-line--헤더">Subject line : 헤더</h3>
<ul>
<li><p>변경 사항에 대한 간결한 설명을 포함한다.</p>
</li>
<li><p><strong>Allowed <code>&lt;type&gt;</code></strong></p>
<pre><code class="language-java">  feat : 새로운 기능 추가
  fix : 버그 수정
  docs : 문서 관련
  style : 스타일 변경 (포매팅 수정, 누락된 세미 콜론 추가, 들여쓰기 추가, …)
  refactor : 코드 리팩토링
  test : 테스트 관련 코드
  chore : 그 외 자잘한 수정 // 새로운 Angular 9 규약에서 삭제

  // 새로운 Angular 9 규약에 추가
  build : 빌드 관련 파일 수정
  ci : CI 설정 파일 수정
  perf : 성능 개선</code></pre>
</li>
<li><p><strong>Allowed <code>&lt;scope&gt;</code></strong></p>
<ul>
<li>어디를 수정했는지 작성한다.</li>
<li>ex. $location, $browser, $compile, $rootScope, ngHref, ngClick, ngView 등</li>
</ul>
</li>
<li><p><strong><code>&lt;subject&gt;</code> text</strong></p>
<ul>
<li>명령문, 현재 시제로 작성한다.<ul>
<li>예를 들어, 변경되었으면 : “change”를 사용한다.</li>
<li>“changed”나 “changes”를 사용하지 않는다.</li>
</ul>
</li>
<li>첫 글자를 대문자로 쓰지 않는다. 소문자로 쓴다.</li>
<li>마지막에 마침표(.)를 붙이지 않는다.</li>
</ul>
</li>
</ul>
<h3 id="message-body--메세지-내용">Message body : 메세지 내용</h3>
<ul>
<li>명령문, 현재 시제로 작성한다.</li>
<li>변경한 이유와 변경 전과의 차이점을 설명한다.</li>
</ul>
<h3 id="message-footer--메세지-하단">Message footer : 메세지 하단</h3>
<h4 id="주요-변경-사항"><strong>주요 변경 사항</strong></h4>
<ul>
<li>모든 주요 변경 사항들은 하단에 언급한다.</li>
<li>무엇을 고쳤는지, 왜 고쳤는지, 마이그레이션은 어떻게 해야 하는지 설명한다.</li>
</ul>
<pre><code class="language-java">BREAKING CHANGE: isolate scope bindings definition has changed and
    the inject option for the directive controller injection was removed.

    To migrate the code follow the example below:

    Before:

    scope: {
      myAttr: &#39;attribute&#39;,
      myBind: &#39;bind&#39;,
      myExpression: &#39;expression&#39;,
      myEval: &#39;evaluate&#39;,
      myAccessor: &#39;accessor&#39;
    }

    After:

    scope: {
      myAttr: &#39;@&#39;,
      myBind: &#39;@&#39;,
      myExpression: &#39;&amp;&#39;,
      // myEval - usually not useful, but in cases where the expression is assignable, you can use &#39;=&#39;
      myAccessor: &#39;=&#39; // in directive&#39;s template change myAccessor() to myAccessor
    }

    The removed `inject` wasn&#39;t generaly useful for directives so there should be no code using it.</code></pre>
<h4 id="해결된-이슈"><strong>해결된 이슈</strong></h4>
<ul>
<li>해결된 이슈는 커밋 메시지 하단에 <code>Closes #&lt;이슈번호&gt;</code> 와 같이 기록한다.</li>
<li>해결된 이슈가 여러 개인 경우에는 <code>Closes #123, #245, #992</code> 와 같이 기록한다.</li>
</ul>
<hr>
<h2 id="예시">예시</h2>
<pre><code class="language-java">feat($browser): onUrlChange event (popstate/hashchange/polling)

Added new event to $browser:
- forward popstate event if available
- forward hashchange event if popstate not available
- do polling when neither popstate nor hashchange available

Breaks $browser.onHashChange, which was removed (use onUrlChange instead)</code></pre>
<pre><code class="language-java">fix($compile): couple of unit tests for IE9

Older IEs serialize html uppercased, but IE9 does not...
Would be better to expect case insensitive, unfortunately jasmine does
not allow to user regexps for throw expectations.

Closes #392
Breaks foo.bar api, foo.baz should be used instead</code></pre>
<pre><code class="language-java">feat(directive): ng:disabled, ng:checked, ng:multiple, ng:readonly, ng:selected

New directives for proper binding these attributes in older browsers (IE).
Added coresponding description, live examples and e2e tests.

Closes #351</code></pre>
<pre><code class="language-java">style($location): add couple of missing semi colons</code></pre>
<pre><code class="language-java">docs(guide): updated fixed docs from Google Docs

Couple of typos fixed:
- indentation
- batchLogbatchLog -&gt; batchLog
- start periodic checking
- missing brace</code></pre>
<pre><code class="language-java">feat($compile): simplify isolate scope bindings

Changed the isolate scope binding options to:
  - @attr - attribute binding (including interpolation)
  - =model - by-directional model binding
  - &amp;expr - expression execution binding

This change simplifies the terminology as well as
number of choices available to the developer. It
also supports local name aliasing from the parent.

BREAKING CHANGE: isolate scope bindings definition has changed and
the inject option for the directive controller injection was removed.

To migrate the code follow the example below:

Before:

scope: {
  myAttr: &#39;attribute&#39;,
  myBind: &#39;bind&#39;,
  myExpression: &#39;expression&#39;,
  myEval: &#39;evaluate&#39;,
  myAccessor: &#39;accessor&#39;
}

After:

scope: {
  myAttr: &#39;@&#39;,
  myBind: &#39;@&#39;,
  myExpression: &#39;&amp;&#39;,
  // myEval - usually not useful, but in cases where the expression is assignable, you can use &#39;=&#39;
  myAccessor: &#39;=&#39; // in directive&#39;s template change myAccessor() to myAccessor
}

The removed `inject` wasn&#39;t generaly useful for directives so there should be no code using it.</code></pre>
<hr>
<h2 id="intellij-플러그인-사용하기">IntelliJ 플러그인 사용하기</h2>
<p><img src="https://velog.velcdn.com/images/ariul-dev/post/551c6c2d-539b-4399-a126-3755444818fb/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Beautiful LIFE] 몰입, 최고의 나를 만나다 | 황농문 교수]]></title>
            <link>https://velog.io/@ariul-dev/Beautiful-LIFE-%EB%AA%B0%EC%9E%85-%EC%B5%9C%EA%B3%A0%EC%9D%98-%EB%82%98%EB%A5%BC-%EB%A7%8C%EB%82%98%EB%8B%A4-%ED%99%A9%EB%86%8D%EB%AC%B8-%EA%B5%90%EC%88%98</link>
            <guid>https://velog.io/@ariul-dev/Beautiful-LIFE-%EB%AA%B0%EC%9E%85-%EC%B5%9C%EA%B3%A0%EC%9D%98-%EB%82%98%EB%A5%BC-%EB%A7%8C%EB%82%98%EB%8B%A4-%ED%99%A9%EB%86%8D%EB%AC%B8-%EA%B5%90%EC%88%98</guid>
            <pubDate>Tue, 25 Oct 2022 17:03:38 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>기술 컨퍼런스, 기술 블로그, 아티클, 강의 등 다양한 자료로 학습한 내용과 인사이트를 기록하는 시리즈입니다. </p>
</blockquote>
<hr>
<h1 id="후회-없는-삶을-위한-조건">후회 없는 삶을 위한 조건</h1>
<ul>
<li>인생을 낭비했다는 뒤늦은 후회는 죽음보다 더 무서운 것</li>
<li><code>&quot;어떻게 살아야 죽을 때 후회하지 않을까?&quot;</code></li>
<li>중요한 것은 &#39;무엇을 하느냐&#39;가 아닌 &#39;어떻게 하느냐&#39;</li>
<li><code>잠재력을 100% 사용한 사람은 후회 없는 삶을 살 수 있다</code></li>
<li>나의 일을 사랑하는 방법 = 몰입</li>
</ul>
<h2 id="1-몰입이란-무엇인가">1. 몰입이란 무엇인가</h2>
<ul>
<li><p>수동적 몰입
⇒ 위기감, 절실함 등으로 인해 수동적으로 혼신의 힘을 다하는 상태
ex. 암벽 등반</p>
</li>
<li><p>능동적 몰입
⇒ 적절한 순간에 잠재력을 발휘하는 능력 = 몰입
ex. 운동 경기
⇒ 뇌가 어떠한 활동에 대해 중요하다고 판단하면 몰입 가능</p>
</li>
<li><p>몰입의 원리: 뇌를 속여라!</p>
</li>
<li><p><code>slow thinking</code></p>
<ul>
<li>결과에 집착하지 않고 여유를 갖는 몰입법</li>
<li>신체의 나머지 부분은 휴식을 취하고 학습에 필요한 뇌 부위만 100% 집중하는 상태</li>
</ul>
</li>
</ul>
<h2 id="2-몰입의-실제-활용-사례">2. 몰입의 실제 활용 사례</h2>
<ul>
<li>수험공부를 위한 의도적인 몰입<ul>
<li>부족하지 않은 수면 (6~7시간)</li>
<li>깨어있는 시간 1초도 쉬지 않음 ⇒ 목숨을 건다고 인식.</li>
<li>규칙적인 운동 (30~40분, 충분한 땀)</li>
<li>한 과목을 최소 1주일 이상</li>
<li>슬로우싱킹 ⇒ 이완된 집중</li>
<li>이해 위주, 생각 위주 ⇒ 진도를 천천히 나가더라도 완벽히 소화</li>
<li>미지의 문제 스스로 해결 (객관식 ⇒ 주관식화)</li>
<li>결과보다는 과정 ⇒ 진인사대천명</li>
<li>선택과 집중 (명확한 목표)</li>
<li>무한 반복 기능의 활용</li>
<li>구동력 만들기</li>
</ul>
</li>
</ul>
<h2 id="3-어떻게-살아야-하는가">3. 어떻게 살아야 하는가?</h2>
<ul>
<li>어떻게 살아야 하는가?<ul>
<li>절대로 성장하는 것을 포기하지 마라!</li>
<li>깊이 생각하는 것은 삶을 발전시키는 도전</li>
<li>인간은 도전과 응전에 의해서만 발달한다</li>
</ul>
</li>
<li>승자 효과 (Winner Effect)<ul>
<li>도전과 성공을 반복하면 사람이 바뀐다!</li>
</ul>
</li>
<li>죽음을 의식하는 삶<ul>
<li>외부의 기대, 각종 자부심과 자만심, 수치스러움과 실패에 대한 두려움들은 &#39;죽음&#39;을 직면해서는 모두 떨어져 나가고 오직 진실로 중요한 것들만이 남는다 by 스티브 잡스</li>
<li>죽음을 의식하고 사는 사람은 더욱 가치 있는 삶을 추구</li>
</ul>
</li>
</ul>
<hr>
<h2 id="배우고-느낀-점-인사이트">배우고 느낀 점, 인사이트</h2>
<ul>
<li><code>결과보다는 과정에 집중하라</code><ul>
<li>어릴 때부터 많이 들어왔고, 스스로도 많이 했던 다짐인데 잘되지 않았었다.</li>
<li>항상 목표를 정해두고 그걸 이루기 위한 학습을 해왔기 때문이다. (ex. 성적, 자격증, 수상 등)</li>
<li>근데 지금은 이 말이 가슴에 와닿는다. </li>
<li>&quot;와! 가슴에 와닿을 만큼 찐한 전달력을 가진 강의!&quot;라는 말이 아니라😅(물론 매우 좋은 강의임) 개발 공부를 한 뒤로 생긴 변화인 것 같다.</li>
<li>개발 공부를 한 지 그렇게 오래되지 않았다. 그런데 그 짧은 시간 만에 알 수 있었다. 이건 이때까지 내가 해 온 공부랑 많이 다르구나. 더욱 달라지겠구나.</li>
<li>실력을 증명하거나 수치화할 수 있는 목표를 정할 수 없다. 성적? 수상? 자격증? 알고리즘 저지 사이트 레벨? 진정한 실력을 증명할 수 있는 지표가 아니니까. 
그래서 <code>과정에 최선을 다하면 그에 대한 결과를 얻을 수 있을 것!</code>이라는 방향으로 마인드가 바뀌었다.</li>
<li>은연중에 느끼고 있던 변화였는데, 이 강의를 통해 다시 한번 생각을 정리할 수 있었다. 
이제 나의 태도는 <code>나는 최선을 다하고, 결과는 하늘에 맡긴다.</code></li>
</ul>
</li>
</ul>
<hr>
<h2 id="출처">출처</h2>
<p>👉 <a href="https://www.youtube.com/watch?v=CICJ4FRAGWY">[Beautiful LIFE] 몰입, 최고의 나를 만나다_ 황농문 교수</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[최종 발표했다고 프로젝트 끝-!? 이 아니었습니다.]]></title>
            <link>https://velog.io/@ariul-dev/%EC%B5%9C%EC%A2%85-%EB%B0%9C%ED%91%9C%ED%96%88%EB%8B%A4%EA%B3%A0-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EB%81%9D-%EC%9D%B4-%EC%95%84%EB%8B%88%EC%97%88%EC%8A%B5%EB%8B%88%EB%8B%A4</link>
            <guid>https://velog.io/@ariul-dev/%EC%B5%9C%EC%A2%85-%EB%B0%9C%ED%91%9C%ED%96%88%EB%8B%A4%EA%B3%A0-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EB%81%9D-%EC%9D%B4-%EC%95%84%EB%8B%88%EC%97%88%EC%8A%B5%EB%8B%88%EB%8B%A4</guid>
            <pubDate>Tue, 25 Oct 2022 14:16:59 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>6주 동안 실전 프로젝트를 진행하면서 학습한 내용을 기록하고, 팀의 리더로서 프로젝트 매니징 경험을 기록하는 시리즈입니다. </p>
</blockquote>
<hr>
<h1 id="what-why-how">WHAT, WHY, HOW</h1>
<p>우아콘을 보던 중 머리가 띵-! 했던 질문이 있었다.
Q. <code>유저들의 사용성 분석</code>은 어떻게 하고 있는가?</p>
<p>그에 대한 CPO 님의 답변은
A. <code>디자인 리서치 팀/프로덕트 리서치 팀</code>에서 한다 ... (중략)</p>
<p>특허 검색 서비스를 만들 때 <a href="https://velog.io/@ariul-dev/%EC%82%AC%EC%9A%A9%EC%9E%90-%EA%B2%BD%ED%97%98%EC%9D%84-%EC%9C%84%ED%95%9C-%EA%B3%A0%EB%AF%BC-%EC%96%B4%EB%94%94%EA%B9%8C%EC%A7%80-%ED%95%B4%EB%B4%A4%EB%8B%88"><strong>사용자를 위한 고민</strong></a>은 치열하게 했지만, 이를 많은 사용자에게 보이진 않았다.
<del>캠프 크루원들 + 멘토님들의 피드백을 받긴 했지만 사용자 입장에서 받은 자세한 피드백은 아님</del></p>
<p>와아.. 나는 어떻게 모든 사용자가 내가 한 고민들에 대해 만족할 거라는 기고만장한 생각을 했지..?😵</p>
<p>반성과 함께 사용자 만족도 조사를 하는 방법을 찾았다.
바로 설문조사를 만들었고, 지인들께 설문조사 참여를 부탁드렸다.
👉 <a href="https://forms.gle/AKReqVUwnzxUYTM1A">[안녕, 특허] 사용자 만족도 조사</a></p>
<p>진짜 사용자의 의견을 듣는다는 취지로 진행한 결과, </p>
<p>Q. [안녕, 특허]의 전반적인 사용 경험에 점수를 매겨주세요 (1은 불만족😢, 5는 매우 만족😄)
<img src="https://velog.velcdn.com/images/ariul-dev/post/ba0ae897-5956-41fc-9ff0-b0c01434981e/image.png" alt=""></p>
<p>Q. 1번 답변에 대한 이유는 무엇인가요?
<img src="https://velog.velcdn.com/images/ariul-dev/post/c97bf267-82fa-4943-a5df-6b8d26383401/image.png" alt=""></p>
<p>Q. &#39;특허 검색 서비스&#39;를 떠올렸을 때 기대했던 부분과 같나요?
<img src="https://velog.velcdn.com/images/ariul-dev/post/96c45271-ac6e-4365-8671-cd473452bc71/image.png" alt=""></p>
<p>Q. 원하는 검색 결과를 얻으셨나요? 검색 결과 정확도에 대한 점수를 매겨주세요  (1은 불만족😢, 5는 매우 만족😄)
<img src="https://velog.velcdn.com/images/ariul-dev/post/a6683f09-c90d-4d8d-8f0d-a758c7ae6604/image.png" alt=""></p>
<p>Q.검색의 속도는 어떠셨나요? 검색 결과 반환 속도에 대한 점수를 매겨주세요  (1은 불만족😢, 5는 매우 만족😄)
<img src="https://velog.velcdn.com/images/ariul-dev/post/3016b77b-d0e4-4610-ba4c-617d92fd33a8/image.png" alt=""></p>
<p>Q. [안녕, 특허] 서비스는 &#39;포함검색&#39; 기능과 &#39;제외검색&#39; 기능을 통해 검색 결과 내에서 원하는 키워드를 반드시 포함하거나 제외한 검색 결과를 반환합니다. 이 기능에 대한 점수를 매겨주세요  (1은 불만족😢, 5는 매우 만족😄)
<img src="https://velog.velcdn.com/images/ariul-dev/post/24ebb1a5-0e89-4f47-a9e5-02bc2384d4e2/image.png" alt=""></p>
<p>Q.[안녕, 특허] 서비스는 &#39;권리구분&#39;, &#39;행정상태&#39;, &#39;국가&#39;로 검색 결과를 필터링할 수 있습니다. 이 기능에 대한 점수를 매겨주세요  (1은 불만족😢, 5는 매우 만족😄)
<img src="https://velog.velcdn.com/images/ariul-dev/post/5b336579-b455-4e0e-8302-082f6d96e250/image.png" alt=""></p>
<hr>
<h1 id="느낀-점">느낀 점</h1>
<ul>
<li><p>오와 리서치도 진짜 쉽지 않은 일이구나... 왜 전문 리서치 팀이 결성되어 있는지 알겠군...</p>
</li>
<li><p>충격적인 사실은 야심 차게 준비한 <code>직관적 검색 기능</code>을 2점짜리 기능이라 생각한 사용자도 있다는 것이다. 이 일을 계기로 <code>왜 애자일로 개발하고, 사용자 반응 보면서 디벨롭 하는지 깨달았다.</code> 만약 이게 실 서비스였고, 우리가 야심 차게 준비한 기능에 대해 많은 사용자가 전혀 효용성을 느끼지 못한다면..? 그리고 그것을 배포 후에 알았다면..!? (끔찍)</p>
</li>
<li><p>점수에 대한 이유를 묻는 문항을 다 배치했어야 했는데, 그걸 너무 늦게 깨달아서 아쉽다. 왜 검색 기능을 2점이라 생각했을까.. 왜 ..? Why..? 무엇이 부족했나요 ..? <del>아니 무서워하지 말고 얘기해봐여 그냥 진짜 궁금해서 그래여🤭</del></p>
</li>
<li><p>총 응답은 7개로 쏘큩..한 결과지만 진짜 사용자의 의견을 들을 수 있었던 값진 경험이었다.</p>
</li>
<li><p>혼자 진행한 거라 그 흔한 &#39;추첨을 통해 커피 쿠폰을 드립니다&#39; 이런 것도 없었는데🥲
다들 흔쾌히 참여해 주시고 자세한 피드백 주셔서 감사한 마음이다..💖</p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[DEVIEW 2020] 일본어 까막눈이 만드는 일본주소검색 | 네이버 검색 엔지니어 조재용]]></title>
            <link>https://velog.io/@ariul-dev/DEVIEW-2020-%EC%9D%BC%EB%B3%B8%EC%96%B4-%EA%B9%8C%EB%A7%89%EB%88%88%EC%9D%B4-%EB%A7%8C%EB%93%9C%EB%8A%94-%EC%9D%BC%EB%B3%B8%EC%A3%BC%EC%86%8C%EA%B2%80%EC%83%89-%EB%84%A4%EC%9D%B4%EB%B2%84-%EA%B2%80%EC%83%89-%EC%97%94%EC%A7%80%EB%8B%88%EC%96%B4-%EC%A1%B0%EC%9E%AC%EC%9A%A9</link>
            <guid>https://velog.io/@ariul-dev/DEVIEW-2020-%EC%9D%BC%EB%B3%B8%EC%96%B4-%EA%B9%8C%EB%A7%89%EB%88%88%EC%9D%B4-%EB%A7%8C%EB%93%9C%EB%8A%94-%EC%9D%BC%EB%B3%B8%EC%A3%BC%EC%86%8C%EA%B2%80%EC%83%89-%EB%84%A4%EC%9D%B4%EB%B2%84-%EA%B2%80%EC%83%89-%EC%97%94%EC%A7%80%EB%8B%88%EC%96%B4-%EC%A1%B0%EC%9E%AC%EC%9A%A9</guid>
            <pubDate>Sun, 23 Oct 2022 08:54:34 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>기술 컨퍼런스, 기술 블로그, 아티클, 강의 등 다양한 자료로 학습한 내용과 인사이트를 기록하는 시리즈입니다. </p>
</blockquote>
<hr>
<h1 id="검색-서비스-정의">검색 서비스 정의</h1>
<h2 id="11-검색-요구사항-특징">1.1 검색 요구사항 특징</h2>
<ul>
<li>검색의 목표<ul>
<li>사용자 쿼리(검색어)를 입력으로 받아서, 사용자가 의도한 검색 결과를 최상위에 노출하는 것</li>
</ul>
</li>
<li>주요 기능도 1개, 주요 입력도 1개</li>
<li>대부분의 검색 스펙은 어떤 타입의 쿼리까지 지원하는 가에 있다.</li>
</ul>
<h2 id="12-검색-요구사항의-예">1.2 검색 요구사항의 예</h2>
<ul>
<li>음차변환</li>
<li>오타교정 (간남역 → 강남역)</li>
<li>유의어 검색 (US → 미국)</li>
<li>부분쿼리 검색</li>
<li>다국어 쿼리 검색</li>
<li>카테고리 검색</li>
</ul>
<h2 id="13-검색-데이터-분석">1.3 검색 데이터 분석</h2>
<ul>
<li>검색 엔지니어 업무에서 가장 많은 시간을 차지<ul>
<li>양질의 데이터와 데이터의 양은 검색 품질과 직결된다.</li>
<li>저품질 데이터는 양질의 데이터로 정제해야 한다.</li>
<li>데이터의 품질이 개발 난이도를 결정한다.</li>
</ul>
</li>
<li>분석해야 할 검색 데이터<ul>
<li>사용자 쿼리: 어떤 타입의 사용자 쿼리가 많이 요구되는지, 어떤 쿼리들이 들어올 수 있는지</li>
<li>검색 대상이 되는 문서: 국내 특허, 해외 특허</li>
</ul>
</li>
</ul>
<h1 id="검색-서비스-원리">검색 서비스 원리</h1>
<h2 id="221-인덱스텀-추출term-extraction">2.2.1 인덱스텀 추출(term extraction)</h2>
<ul>
<li>적절한 인덱스텀이 없으면, 예상되는 쿼리에 대해서 검색이 되지 않는다.</li>
<li>적절한 인덱스텀이란?<ul>
<li>문서의 언어와 문자 환경에 적합 (한국어 체계에 맞게)</li>
<li>예상되는 사용자 쿼리의 특징에 적합</li>
<li>검색 결과를 구성하기에 적합</li>
</ul>
</li>
<li>텀을 추출하는 방법<ul>
<li>공백 단위 구분 추출</li>
<li>n-gram 추출<ul>
<li>Edge n-gram 추출</li>
<li>min: 2, max:4, sep: “” 일 때, [서울, 서울에, 서울에서, 부산, 부산가, 부산가는]</li>
</ul>
</li>
<li>형태소 분석기 추출<ul>
<li>형태소 분석기의 종류나 설정에 따라서 결과가 다름</li>
<li>품사에 따른 분리 또는 사전 기반에 따른 분리가 가능(텀, 품사, 사전)</li>
</ul>
</li>
<li>NLU를 사용한 추출</li>
</ul>
</li>
<li>적절한 인덱스텀 추출의 중요성<ul>
<li>공백 분리: “서울에서 부산가는”은 되는데, “서울 부산”은 안 된다.</li>
<li>형태소 분석기: “서울에서 부산까지”와 “서울 부산”이 모두 된다.</li>
</ul>
</li>
</ul>
<h2 id="222-inverted-file-생성">2.2.2 Inverted File 생성</h2>
<ul>
<li>Inverted File<ul>
<li>인덱스텀과 인덱스텀이 존재하는 문서의 DocId 목록 매핑의 집합</li>
</ul>
</li>
<li>Lexicon<ul>
<li>인덱스텀을 빨리 찾을 수 있도록 텀들의 목록을 모아서 관리하는 사전</li>
<li>빠른 탐색에 최적화되어야 함</li>
</ul>
</li>
<li>Posting<ul>
<li>인덱스텀이 위치하는 문서 식별자(DocId) 1개</li>
<li>메모리와 보조기억장치를 최대한 효율적으로 사용</li>
</ul>
</li>
</ul>
<h2 id="23-쿼리-처리query-processing">2.3 쿼리 처리(query processing)</h2>
<ul>
<li>쿼리의 종류<ul>
<li>Boolean 쿼리, 근접(Proximity) 쿼리, 자연어 쿼리 등이 있다.</li>
<li><strong>대부분의 사용자들은 알아서 처리해주는 자연어 쿼리</strong>를 원한다.</li>
</ul>
</li>
<li>쿼리 처리 단계<ol>
<li>쿼리텀 추출(Term Extraction)</li>
<li>추출된 쿼리텀으로 Inverted File에서 포스팅 찾기</li>
<li>쿼리 연산 수행 및 검색 결과 목록 생성</li>
<li>문서 점수화 및 정렬</li>
</ol>
</li>
</ul>
<h2 id="231-쿼리텀-추출">2.3.1 쿼리텀 추출</h2>
<ul>
<li><strong>인덱스텀 추출과 거의 유사한 기준으로 추출해야 한다.</strong><ul>
<li>다른 기준으로 텀을 추출하면 문서와 동일한 쿼리로 검색해도 검색이 안 될 수 있다.</li>
</ul>
</li>
<li>“경기 성남시 정자동”의 예<ul>
<li>인덱스텀은 형태소 분석기로 분리해서 “경기”, “성남”, “정자”로 생성</li>
<li>쿼리텀은 공백으로 분리해서 “경기”, “성남시”, “정자동”으로 생성</li>
<li>이 경우, “경기 성남시 정자동”으로 검색해도 해당 문서가 검색되지 않는다.</li>
</ul>
</li>
</ul>
<h2 id="232-포스팅-찾기">2.3.2 포스팅 찾기</h2>
<ul>
<li>Inverted File에서 각 쿼리텀에 대한 포스팅을 찾는다.</li>
<li>inverted File은 메모리에 있고, 탐색 속도가 매우 빠르다.</li>
</ul>
<h2 id="233-쿼리-연산">2.3.3 쿼리 연산</h2>
<ul>
<li>쿼리텀에 매칭되는 포스팅으로 쿼리 연산을 수행한다.<ul>
<li>Boolean 쿼리, 근접 쿼리 등 각 쿼리의 성격에 따라서 다른 연산 과정을 수행한다.</li>
<li>일반적으로 자연어 쿼리는 모든 쿼리텀을 AND 검색한 문서를 찾는다.</li>
</ul>
</li>
<li>최적화된 쿼리 처리<ul>
<li>한 개의 쿼리텀에 대한 포스팅 리스트의 크기는 최악의 경우 전체 문서의 집합의 크기와 같다. 이 경우, 쿼리 처리 속도가 급격하게 느려진다.</li>
<li>메모리 사용과 수행 속도를 최적화한 쿼리 처리가 중요하다.</li>
</ul>
</li>
</ul>
<h2 id="234-점수화-및-정렬">2.3.4 점수화 및 정렬</h2>
<ul>
<li>Relevancy (정확도)<ul>
<li>입력된 쿼리텀들과 문서가 얼마나 일치하는 지를 나타내는 함수</li>
<li>Relevancy를 구하는 알고리즘은 검색의 특성이나 도메인에 따라서 다양하다.</li>
<li>기본적인 Relevancy 알고리즘으로는 문서 유사도를 구하는 TF-IDF와 BM25가 있다.</li>
<li>이외에도 벡터 모델, 확률 모델 등이 있따.</li>
</ul>
</li>
<li>랭킹 모델링<ul>
<li>Relevancy 점수를 계산하는 방법을 정하는 과정이 랭킹 모델링이다.</li>
<li>사용자의 의도에 가장 근접한 점수를 모델에 반영하기 위해서 가지고 있는 데이터를 최대한 활용한다.</li>
</ul>
</li>
<li>지도 장소검색 랭킹 모델의 예<ul>
<li>베이지언 확률을 기반으로 한 모델을 사용한다.</li>
<li>텀-문서 유사도, 장소 인기도, 사용자의 위치와 대상 장소의 거리</li>
</ul>
</li>
</ul>
<h2 id="235-tf-idf-bm25">2.3.5 TF-IDF, BM25</h2>
<ul>
<li>TF (Term Frequency)<ul>
<li>문서에 인덱스텀이 포함된 개수.</li>
<li>문서에 매칭된 텀의 개수가 많을수록 사용자가 원하는 문서일 가능성이 높다.</li>
<li>TF가 높을수록 높은 점수를 준다.</li>
</ul>
</li>
<li>IDF (Inverse Document Frequency)<ul>
<li>인덱스텀이 포함된 문서의 개수다. (포스팅 리스트의 크기)</li>
<li>매칭된 텀이 희소할수록, 특정 문서를 잘 대표할 것이다.</li>
<li>IDF가 낮을수록 높은 점수를 준다.</li>
</ul>
</li>
<li>Field Lenght<ul>
<li>문서의 길이다.</li>
<li>문서의 길이가 짧은 필드에 매칭된 텀일수록 사용자의 의도에 더 부합하는 문서일 것이다.</li>
<li>예를 들어 쿼리텀이 문서의 내용 필드보다는 길이가 짧은 제목 필드에 매칭될수록 높은 점수를 준다.</li>
<li>Field Length가 낮을수록 높은 점수를 준다.</li>
</ul>
</li>
<li>BM25 계산식
<img src="https://velog.velcdn.com/images/ariul-dev/post/824b5703-b86e-4a06-92bf-30e8da0a8b27/image.png" alt=""></li>
</ul>
<h1 id="일본-주소검색-서비스-개발">일본 주소검색 서비스 개발</h1>
<h2 id="31-기술-스택">3.1 기술 스택</h2>
<ul>
<li>검색 엔진: <strong>Lucene</strong></li>
<li>검색 프레임워크: <strong>Elasticsearch</strong>. Solr</li>
<li>데이터베이스: PostgreSQL, MongoDB 등</li>
<li>대용량 처리: Hadoop + Spark + Scala, pandas 등</li>
<li>형태소 분석기<ul>
<li>한국어: <strong>nori,</strong> …</li>
<li>일본어: <strong>kuromoji …</strong></li>
</ul>
</li>
<li>API 서비스: <strong>spring boot</strong> 2 + kotlin</li>
<li>검색 인프라: ncc(docker + kubernetes)</li>
</ul>
<h2 id="32-데이터-파이프라인-구축">3.2 데이터 파이프라인 구축</h2>
<ul>
<li>원본 데이터 준비</li>
<li>데이터 추출/변환/적재(ETL)<ul>
<li>추출: 원본 데이터에서 필요한 데이터만 뽑아서 저장</li>
<li>변환: 추출된 데이터를 인덱스를 만들기에 적절한 형태로 가공</li>
<li>적재: 생성된 인덱스를 검색 엔진에 로딩</li>
</ul>
</li>
<li>모든 작업에 사람의 개입을 최소화</li>
<li>데이터의 최신성 목표에 따른 구축</li>
</ul>
<h1 id="검색-품질-측정-및-개선">검색 품질 측정 및 개선</h1>
<h2 id="41-테스트-데이터와-정답셋">4.1 테스트 데이터와 정답셋</h2>
<ul>
<li>데이터가 많을수록 검색 품질이 향상된다.</li>
<li>양질의 테스트 데이터<ul>
<li>경험에 기반한 쿼리 타입 추출</li>
<li>검색 로그</li>
<li>서비스되고 있는 검색과 비교(우리 서비스의 경우, 키프리스)</li>
<li>클릭 로그: 사용자가 어떤 쿼리를 날렸고, 그 쿼리에 따라서 우리가 제공한 데이터 중에 어떤 것을 선택했는지에 대한 로그</li>
</ul>
</li>
<li>확보된 데이터는 주기적으로 생성되도록 자동화하는 것<ul>
<li>지원되지 않는 쿼리 타입을 중심으로 개선점을 도출하는데 사용</li>
<li>A/B 테스트, 회귀 테스트 등 검색 품질 측정에 활용</li>
<li>학습 데이터로 활용해서 검색 품질 개선을 자동화</li>
</ul>
</li>
</ul>
<h2 id="42-품질-측정-기준-지표kpi-정의">4.2 품질 측정 기준 지표(KPI) 정의</h2>
<ul>
<li>검색 품질을 평가하기 위한 기준 지표를 만든다.<ul>
<li>검색 품질을 개선하려면, 평가할 수 있어야 한다.</li>
<li>매일/매주/매달 KPI 지표를 뽑을 수 있는 파이프라인을 구축한다.</li>
<li>KPI를 통해서 검색 품질 개선점을 도출한다.</li>
</ul>
</li>
<li>품질 측정 기준 지표의 예<ul>
<li>사용자 클릭 비율</li>
<li>검색어 삭제 및 재검색 비율</li>
<li>사용자가 상위랭크를 클릭한 비율 점수화</li>
<li>검색결과 없음 비율</li>
<li>클릭이 발생한 시점에 검색어의 길이</li>
</ul>
</li>
</ul>
<h2 id="43-ab-테스트-구축">4.3 A/B 테스트 구축</h2>
<ul>
<li>AS-IS 서비스를 A, TO-BE 서비스를 B로 한다.</li>
<li>출시 전 A/B 테스트<ul>
<li>준비된 정답셋으로 A와 B를 직접 실행해서 비교한다.</li>
<li>A보다 B의 점수가 낮으면, 출시하지 않는다.</li>
</ul>
</li>
<li>출시 후 A/B 테스트<ul>
<li>서비스의 일부만 부분배포할 수 있는 매커니즘이 필요하다</li>
<li>실서비스에 B를 부분배포한 후, 품질 측정 기준 지표로 비교한다.</li>
</ul>
</li>
</ul>
<h2 id="44-검색-품질-개선ing">4.4 검색 품질 개선(…ing)</h2>
<ul>
<li>출시 전 개선<ul>
<li>키프리스 등의 서비스와 품질을 비교하면서, 부족한 부분을 보완</li>
</ul>
</li>
<li>출시 후 개선<ul>
<li>사용자 쿼리/클릭 로그를 기반으로 검색 품질이 자동 개선되도록 구축</li>
<li>랭킹 모델에 인기도 반영</li>
</ul>
</li>
</ul>
<hr>
<h2 id="배우고-느낀-점-인사이트">배우고 느낀 점, 인사이트</h2>
<ul>
<li>검색 기본적인 요구사항 <code>오타교정</code></li>
<li>쿼리텀은 인덱스텀 추출과 거의 유사한 기준으로 추출해야 한다</li>
<li>검색 품질 개선 방법</li>
</ul>
<hr>
<h2 id="출처">출처</h2>
<p>👉 <a href="https://tv.naver.com/v/16970970">일본어 까막눈이 만드는 일본 주소검색</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[우아콘 2022] 푸드와 커머스를 아우르는 슈퍼앱으로의 전환 | 우아한형제들 CPO 김용훈]]></title>
            <link>https://velog.io/@ariul-dev/%EC%9A%B0%EC%95%84%EC%BD%98-2022-%ED%91%B8%EB%93%9C%EC%99%80-%EC%BB%A4%EB%A8%B8%EC%8A%A4%EB%A5%BC-%EC%95%84%EC%9A%B0%EB%A5%B4%EB%8A%94-%EC%8A%88%ED%8D%BC%EC%95%B1%EC%9C%BC%EB%A1%9C%EC%9D%98-%EC%A0%84%ED%99%98-%EC%9A%B0%EC%95%84%ED%95%9C%ED%98%95%EC%A0%9C%EB%93%A4-CPO-%EA%B9%80%EC%9A%A9%ED%9B%88</link>
            <guid>https://velog.io/@ariul-dev/%EC%9A%B0%EC%95%84%EC%BD%98-2022-%ED%91%B8%EB%93%9C%EC%99%80-%EC%BB%A4%EB%A8%B8%EC%8A%A4%EB%A5%BC-%EC%95%84%EC%9A%B0%EB%A5%B4%EB%8A%94-%EC%8A%88%ED%8D%BC%EC%95%B1%EC%9C%BC%EB%A1%9C%EC%9D%98-%EC%A0%84%ED%99%98-%EC%9A%B0%EC%95%84%ED%95%9C%ED%98%95%EC%A0%9C%EB%93%A4-CPO-%EA%B9%80%EC%9A%A9%ED%9B%88</guid>
            <pubDate>Fri, 21 Oct 2022 16:56:26 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>기술 컨퍼런스, 기술 블로그, 아티클, 강의 등 다양한 자료로 학습한 내용과 인사이트를 기록하는 시리즈입니다. </p>
</blockquote>
<hr>
<h2 id="슈퍼앱">슈퍼앱?</h2>
<ul>
<li><p>슈퍼앱: 많은 기능들을 하나의 앱으로 처리할 수 있음</p>
</li>
<li><p>중국, 동남아 중심으로 슈퍼앱 문화가 발전해 옴 </p>
</li>
<li><p>모바일을 선점한 신생 플랫폼들이 고객의 일상에 깊숙이 투입됨</p>
</li>
<li><p>슈퍼앱의 구성
<img src="https://velog.velcdn.com/images/ariul-dev/post/28818302-db4f-4cde-9795-39f62dc2b7ef/image.png" alt=""></p>
</li>
</ul>
<h2 id="why-superapp">Why SuperApp?</h2>
<ul>
<li>큰 꿈을 담기 위해 더 큰 그릇을 준비하는 것.</li>
<li>슈퍼앱으로의 전환을 위해 3개의 레이어가 필요하다.</li>
</ul>
<h3 id="1-traffic">1. Traffic</h3>
<ul>
<li>슈퍼앱은 더 많은 방문자를 가져가야 한다. (현재는 2000만의 사용자)</li>
<li>앱 내에서 많은 시간을 보내야 한다. (콘텐츠와 커뮤니티)</li>
<li>배달이라는 목적 중심의 어플리케이션에서 다양한 방문 기회를 갖게 만드는 것! </li>
<li>기존의 사용자 동선 구석구석에 잘 녹아들어서 고객이 좀 더 배민에서 풍성한 경험을 하게 만드는 것! </li>
<li>새로 들어온 비즈니스 모델이 기존에 배민을 익숙하게 이용하고 있는 사람들로부터 충분히 트래픽 전이가 일어나야 한다.</li>
<li>그렇지 않으면 슈퍼앱으로의 전이가 불필요함</li>
<li>큰 트래픽을 어떻게 필요한 곳으로 구석구석 잘 전달할 수 있을 것인가</li>
</ul>
<h3 id="2-flow">2. Flow</h3>
<ul>
<li>다양한 기회와 콘텐츠와 커머스 등의 재미를 사용자가 기민하고 재밌게 탐색할 수 있는 구조로 만들어 두는 것</li>
<li>사용자의 제한된 호기심을 어떻게 하면 필요한 곳에, 더 유의미한 곳으로 전달시켜서 그런 것들에 기쁨과 가치를 느낄 수 있게 만들지 </li>
<li>푸드 딜리버리라는 하나의 목적에 최적화된 유스케이스를 가지고 있는 앱에서 다양한  유스 케이스들을 가지고 있는 프로덕트로 바꿔나가는 데 있어 프로덕트 측면에서의 변화</li>
</ul>
<h3 id="3-integration">3. Integration</h3>
<ul>
<li>A 서비스 만들 때 만든 기능을 B 만들 때 또 만드는 등의 케이스가 점철되어 있다.</li>
<li>앞으로 많은 서비스들을 만들텐데 그 때마다 지금까지 해온 것처럼 무언가를 또 만드는 것은 비효율적이고 비생산적임</li>
<li>기존에 가지고 있던 여러 기능들을 플랫폼화 하는 것</li>
<li>쉽게 adaptation 할 수 있게 구조화 해두고 성장성 있게 지속 가능한 구조로 만들어 가기 </li>
</ul>
<h2 id="배달의-민족--선택의-연속">배달의 민족 = 선택의 연속!</h2>
<p>현재 동선
<img src="https://velog.velcdn.com/images/ariul-dev/post/437ec10d-bfdb-4bcc-b8d5-7cc3f176d86c/image.png" alt=""></p>
<p>음식을 고를 때는 불편하지 않은 동선이다</p>
<p>하지만 커머스는 플로우 구조가 달라져야 한다.
<img src="https://velog.velcdn.com/images/ariul-dev/post/247fee6e-86ab-4042-8266-96df11e57e86/image.png" alt=""></p>
<ul>
<li><p>음식을 고르는 것과 커머스에서 내가 필요한 아이템을 고르는 것은 매우 다르다</p>
</li>
<li><p>온라인 상에서의 커머스 = 목적 중심의 테스크일 수밖에 없다.</p>
<ul>
<li>단계별 탐색이 아니라 추천이 이뤄져야 하고, 추천이 만족스럽지 않다면 검색부터 시작해야 한다. </li>
</ul>
</li>
<li><p>복잡성의 문제를 해결해야 한다.</p>
<ul>
<li>배달의 민족이라는 앱에 사용자가 투영하는 호기심과 관심은 줄어들 수밖에 없다.</li>
<li>반면, 앞으로 서비스와 기능이 늘어나면서 서비스의 구조나 복잡성은 증가할 수밖에 없다.</li>
<li>‘낮아지는 사용자의 호기심과 높아지는 서비스의 복잡성 사이를 어떻게 극복할 수 있을까’ = 프로덕트가 해결해야 하는 문제</li>
</ul>
</li>
<li><p>고객이 많은 서비스와 많은 상품 사이를 헤매게 하는 것이 아니라, 어떻게 하면 이 고객이 필요한 적합한 물건과 음식을 필요한 타이밍에 제안할 수 있을까? 어떻게 하면 그런 프로덕트 구조를 만들 수 있을까?가 배민의 고민  </p>
</li>
<li><p>AI가 제너레이션 해주는 시대</p>
<ul>
<li>사용자의 의도를 매우 높은 수준으로 예측할 수 있다.</li>
<li>좋은 사용자의 반응에 적절한 피드백을 제공하며 과업의 성공을 이끈다.</li>
</ul>
</li>
</ul>
<hr>
<h2 id="qa"><strong>Q&amp;A</strong></h2>
<p>Q1. 프로덕트와 조직이 앞으로 나아가야 할 방향을 설정할 때 어떻게 의사결정을 내리시는지 궁금합니다.</p>
<p>A1. </p>
<ul>
<li>사용자의 경험의 변화(인식의 변화)</li>
<li>시장의 변화 (경쟁 상황, 테크의 변화 등)</li>
</ul>
<p>우리가 어느 지점에 서있고, 어떤 부분을 보강하고 어떤 부분을 극복해야 하는지 등을 많이 논의함</p>
<ul>
<li><p>배달의 민족 검색 불편하다?
⇒ 동시대의 다른 검색 경험들이 훨씬 좋아졌다 (구글 등의 다른 서비스)
⇒ 이걸 쓰다 배민을 쓰면 이상하고 불편하게 느껴짐
⇒ 고객들의 계속 높아지는 만족도를 캐치업 하기 위해서 우리의 부족한 부분들 체크하고, 우선순위 결정하면서 이런 것을 극복해가는 결정들을 한다.</p>
</li>
<li><p>거시적인 부분부터 미시적인 부분까지 우선순위가 리스트업되고, 단기적으로 해결해야 하는 것과 중장기적으로 해결해야 하는 것들의 우선순위가 나뉘고 백로그에 넣고 하는 등의 작업들이 꽤 기민하게 이뤄지고 있다.</p>
</li>
<li><p>그런 것들의 총합이 로드맵일 수도 있고, 분기 단위 월 단위 과제 계획일 수도 있는 것. </p>
</li>
</ul>
<p>Q2. 유저들의 사용성 분석은 어떻게 하고 있는가?
A2. 디자인 리서치 팀 / 프로덕트 리서치 팀</p>
<p>Q3. 기능이 많아질수록 무거워질 수밖에 없는데, 가벼운 기능만 사용하는 사용자에게는 불편하게 다가올 수도 있을 것 같다.
A3. </p>
<ul>
<li>아이템, 서비스가 많아질수록 당연히 화면에 노출되는 정보가 많아질 수밖에 없고, 고객이 그걸 누르려면 내가 지금 뭘 누르려는 지에 대한 이해가 분명히 있어야 클릭이 발생한다.</li>
<li>전국별미가 무엇이고 쇼핑라이브가 무엇인지에 대한 이해가 있어야 그걸 누르고 거기에 대한 트래픽이 생기는데, 이해가 없으면 관심이 생기지 않는다.</li>
<li>그런 복잡도의 문제에 이미 직면해 있다.</li>
<li>어떻게 하면 좁혀나가고 줄여나갈 수 있을까에 대한 고민<ul>
<li>스킨 같은 것을 바꿀까, 모드를 바꿔볼까 </li>
<li>설정에서 라이트 모드를 누르면 필요없는 것들을 보지 않고 쉽게 탐색할 수 있게 한다거나, 서비스적인 해결안도 있을 것이고 기술적인 해결안도 있을 것이다.</li>
<li>참 치열하게 고민해야 하는 지점이고, 프로덕트 팀이 가장 집중하고 있는 문제</li>
</ul>
</li>
</ul>
<p>Q4. PM과 개발자의 협업! PM으로서 개발자에게 기대하는 부분이 있다면?
A4. 
예전에 워터풀 방식으로 일할 때와 달리, 지금은 목적 중심의 조직에서 애자일하게 협업을 하고 있기 때문에 PM과 개발자가 경계를 갖고 있다고 느끼진 않는다.</p>
<ul>
<li>좀 덜 경직된 협업 태도</li>
<li>요구사항을 상세히</li>
</ul>
<hr>
<h2 id="배우고-느낀-점-인사이트">배우고 느낀 점, 인사이트</h2>
<ul>
<li>내가 컨퍼런스를 좋아하는 이유
  ⇒ 새로운 지식을 얻을 수도 있지만, 발표하시는 분들을 보고 내가 생각하는 이상적인 리더상을 정립할 수 있기 때문!<ul>
<li>중학생 때부터 <code>부드러운 카리스마</code>를 꿈꿔왔는데 김용훈 CPO 님이 내가 꿈꿔온 리더상에 가장 부합하신 것 같다.
(물론 대화를 나눠본 적도, 함께 일해본 적도, 길 가다 마주친 적도 없음. 아무것도 없음. 그냥 화면을 뚫고 나오는 분위기가 그렇다는 의미..🙄)</li>
<li>말의 속도나 높낮이, 말투도 내가 생각하는 이상적인 모습!</li>
<li>위트 있고 부드러운 느낌도! </li>
<li>카리스마는 24년이라는 경력과 CPO라는 직책이 방증하는 실력에서 비롯된 것이겠죠. </li>
<li>그냥 다 너무 좋은데요(?) 안 되겠습니다. 저랑 같이 일해보셔야겠습니다. 제가 얼른 커서 뵈러 가겠습니다.</li>
</ul>
</li>
</ul>
<hr>
<h2 id="출처">출처</h2>
<p>👉 <a href="https://www.youtube.com/watch?v=0jnA6Rm1Oh4">[우아콘2022] 푸드와 커머스를 아우르는 슈퍼앱으로의 전환</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[우아콘 2020] 배달의민족 마이크로서비스 여행기 | 우아한형제들 배민서비스개발팀 김영한]]></title>
            <link>https://velog.io/@ariul-dev/%EC%9A%B0%EC%95%84%EC%BD%98-2020-%EB%B0%B0%EB%8B%AC%EC%9D%98%EB%AF%BC%EC%A1%B1-%EB%A7%88%EC%9D%B4%ED%81%AC%EB%A1%9C%EC%84%9C%EB%B9%84%EC%8A%A4-%EC%97%AC%ED%96%89%EA%B8%B0-%EC%9A%B0%EC%95%84%ED%95%9C%ED%98%95%EC%A0%9C%EB%93%A4-%EB%B0%B0%EB%AF%BC%EC%84%9C%EB%B9%84%EC%8A%A4%EA%B0%9C%EB%B0%9C%ED%8C%80-%EA%B9%80%EC%98%81%ED%95%9C</link>
            <guid>https://velog.io/@ariul-dev/%EC%9A%B0%EC%95%84%EC%BD%98-2020-%EB%B0%B0%EB%8B%AC%EC%9D%98%EB%AF%BC%EC%A1%B1-%EB%A7%88%EC%9D%B4%ED%81%AC%EB%A1%9C%EC%84%9C%EB%B9%84%EC%8A%A4-%EC%97%AC%ED%96%89%EA%B8%B0-%EC%9A%B0%EC%95%84%ED%95%9C%ED%98%95%EC%A0%9C%EB%93%A4-%EB%B0%B0%EB%AF%BC%EC%84%9C%EB%B9%84%EC%8A%A4%EA%B0%9C%EB%B0%9C%ED%8C%80-%EA%B9%80%EC%98%81%ED%95%9C</guid>
            <pubDate>Fri, 21 Oct 2022 16:55:32 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>기술 컨퍼런스, 기술 블로그, 아티클, 강의 등 다양한 자료로 학습한 내용과 인사이트를 기록하는 시리즈입니다. </p>
</blockquote>
<hr>
<h1 id="배민서비스-역사">배민서비스 역사</h1>
<h3 id="2015">2015</h3>
<ul>
<li>히루 주문수 5만 이하</li>
<li>MS SQL + PHP, ASP</li>
<li>대부분 루비DB(MS SQL) 스토어드 프로시저 방식 사용</li>
<li>루비DB 장애시 전체 서비스 장애</li>
<li>테이블 700개, stored procedure 4000개😮 - 굉장히 거대한 모놀리틱 시스템</li>
</ul>
<h3 id="2015---단일-서비스">2015 - 단일 서비스</h3>
<p><img src="https://s3.us-west-2.amazonaws.com/secure.notion-static.com/68379a19-6166-4659-be76-38a5a6a75157/Untitled.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=AKIAT73L2G45EIPT3X45%2F20221024%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20221024T043831Z&X-Amz-Expires=86400&X-Amz-Signature=a9e1cb42b0d236c69544bd60c4d5a5d4e7efd21a22cd5795f93a2897d07628d2&X-Amz-SignedHeaders=host&response-content-disposition=filename%20%3D%22Untitled.png%22&x-id=GetObject" alt="Untitled"></p>
<p>⇒ 리뷰가 장애가 나더라도 고객이 주문하는 데 아무런 영향이 없어야 하는데, 당시에는 루비 데이터베이스가 죽는 순간, 전체 데이터 마비되는 구조</p>
<h3 id="2016">2016</h3>
<ul>
<li><p>하루 주문수 10만 돌파</p>
</li>
<li><p>PHP → 자바 언어</p>
<ul>
<li>자바 언어를 선택한 이유
  1) 자바가 안정적으로 대용량 트래픽에 대응 가능<br>  2) 개발자 수급 (국내에 자바 언어로 대용량 트래픽 처리 경험있는 개발자 많이 있기 때문)</li>
</ul>
</li>
<li><p><strong>마이크로서비스</strong> 도전 시작</p>
</li>
<li><p>결제, 주문중계 독립</p>
</li>
<li><p>IDC → AWS 클라우드 인프라로 이전 시작</p>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/ariul-dev/post/1f02874d-5a0d-4cf9-b7db-2835db74b023/image.png" alt=""> ⇒ DB(마리아 DB)까지 분리! 
결제가 장애가 나도, 배달의민족은 최악의 경우에 전화 주문을 할 수 있다</p>
<p><img src="https://velog.velcdn.com/images/ariul-dev/post/309abe90-25ba-4367-9050-37c75201e763/image.png" alt="">
주문중계: 사장님들이 PC, 앱, 단말기로도 주문 접수를 받을 수 있다. 중간 Gateway 서비스</p>
<p>⇒ 가볍게 node js로 만들면 좋겠다 판단
⇒ 메인 기술은 자바지만 다른 기술들도 비즈니스 상황에 맞게 만들면 사용할 수 있다고 판단
⇒ 서비스가 성장함에 따라 지금은 자바로 변경한 상태</p>
<h3 id="2017">2017</h3>
<ul>
<li>하루 주문수 20만 돌파</li>
<li>대 장애의 시대: 트래픽은 계속 느는데, 시스템은 레거시. 스케일할 수 있는 구조가 아니다</li>
<li>메뉴, 정산, 가게 목록 시스템 독립</li>
</ul>
<p>장애가 한번 나면 전국민의 역적이 된다. 생존을 위해 마이크로서비스로 전환해야 한다
<img src="https://velog.velcdn.com/images/ariul-dev/post/e5f1f3e1-bf37-4590-848b-eb50b922cd3a/image.png" alt="">
 가게 목록 + 검색을 루비에서 분리해서 엘라스틱서치로 떼어냄
⇒ 루비 DB로 가는 부하 줄어들게</p>
<h3 id="2018-상반기">2018 상반기</h3>
<ul>
<li>전사적으로 의사결정: 배달의민족의 1순위 과제는 시스템 안전성</li>
<li>N 광고 폭파 → 장애대응 TF 창설<ul>
<li>기존에는 하나의 가게가 하나의 광고만 할 수 있었음</li>
</ul>
</li>
<li>가게상세 재개발(주요 장애 포인트)</li>
<li>쿠폰, 포인트 탈루비</li>
<li>오프라인 모드 적용</li>
</ul>
<h3 id="2018-하반기">2018 하반기</h3>
<ul>
<li>주문 탈루비<ul>
<li>주문은 모든 시스템과 다 엮인다. 결제, 포인트, 쿠폰 등</li>
</ul>
</li>
<li>리뷰 탈루비</li>
</ul>
<h3 id="프로젝트-먼데이">프로젝트 먼데이</h3>
<ul>
<li><p>기술적으로 마이크로 서비스로 가려면 프로젝트를 3~4달 중단시켜야 한다</p>
</li>
<li><p>회사는 비즈니스를 해야 함</p>
</li>
<li><p>하나의 가게가 여러 개의 광고를 하려면 이 프로젝트를 해야 한다. 시스템 기반 안정화가 필요하니 이 프로젝트에만 집중할 수 있게 개발팀을 도와주기로 의사결정
<img src="https://velog.velcdn.com/images/ariul-dev/post/281b9061-ce99-4d37-acb5-05be91bb540f/image.png" alt=""></p>
<ul>
<li>가게노출 시스템: 서비스 조회용 가게 데이터를 가지고 있는 쿼리 모델</li>
<li>광고용 시스템</li>
<li>검색용 시스템</li>
</ul>
</li>
</ul>
<h3 id="먼데이-아키텍처">먼데이 아키텍처</h3>
<p>고려 사항</p>
<ol>
<li>성능<ul>
<li>대용량 트래픽 대응</li>
<li>메인, 가게 리스트, 가게 상세 API는 초당 15,000회 호출<ul>
<li>모든 시스템이 대용량 트래픽을 감당하기는 어려움</li>
</ul>
</li>
</ul>
</li>
<li>장애 격리<ul>
<li>가게, 광고 같은 내부 서비스나 DB에 장애가 발생해도</li>
<li>고객 서비스를 유지하고 주문도 가능 해야 함</li>
</ul>
</li>
<li>데이터 동기화<ul>
<li>데이터가 분산되어 있음</li>
</ul>
</li>
</ol>
<p>대안) API 조회 형식</p>
<p>⇒ 장애 문제가 있다. 광고 시스템 장애가 생기면, 광고 시스템 API를 호출하는 모든 시스템에 연쇄적 장애 발생</p>
<p>⇒ 고성능 조회-트래픽 전파. 대량의 트래픽이 순간적으로 몰려오는데, API 호출 방식을 사용하면 이 트래픽이 모든 시스템에 다 퍼진다.</p>
<p>광고, 가게/업주의 경우에는 트래픽을 잘 해결하는 것보다, 정확하고 안정적인 시스템 운영이 훨씬 중요하다</p>
<p><img src="https://velog.velcdn.com/images/ariul-dev/post/246f1327-57ee-4147-9257-8226dd57a292/image.png" alt=""></p>
<hr>
<h2 id="배우고-느낀-점-인사이트">배우고 느낀 점, 인사이트</h2>
<ul>
<li>서비스 안정화</li>
<li>아키텍처 설계의 중요성</li>
<li>기능 추가 하나가 왜 쉬운 일이 아닌지</li>
</ul>
<hr>
<h2 id="출처">출처</h2>
<p>👉 <a href="https://www.youtube.com/watch?v=BnS6343GTkY">[우아콘2020] 배달의민족 마이크로서비스 여행기</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[우아콘 2022] 문 앞으로 배달되는 일상의 행복 | 우아한형제들 CEO 김범준]]></title>
            <link>https://velog.io/@ariul-dev/%EC%9A%B0%EC%95%84%EC%BD%98-2022-%EB%AC%B8-%EC%95%9E%EC%9C%BC%EB%A1%9C-%EB%B0%B0%EB%8B%AC%EB%90%98%EB%8A%94-%EC%9D%BC%EC%83%81%EC%9D%98-%ED%96%89%EB%B3%B5-%EC%9A%B0%EC%95%84%ED%95%9C%ED%98%95%EC%A0%9C%EB%93%A4-CEO-%EA%B9%80%EB%B2%94%EC%A4%80</link>
            <guid>https://velog.io/@ariul-dev/%EC%9A%B0%EC%95%84%EC%BD%98-2022-%EB%AC%B8-%EC%95%9E%EC%9C%BC%EB%A1%9C-%EB%B0%B0%EB%8B%AC%EB%90%98%EB%8A%94-%EC%9D%BC%EC%83%81%EC%9D%98-%ED%96%89%EB%B3%B5-%EC%9A%B0%EC%95%84%ED%95%9C%ED%98%95%EC%A0%9C%EB%93%A4-CEO-%EA%B9%80%EB%B2%94%EC%A4%80</guid>
            <pubDate>Fri, 21 Oct 2022 16:48:04 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>기술 컨퍼런스, 기술 블로그, 아티클, 강의 등 다양한 자료로 학습한 내용과 인사이트를 기록하는 시리즈입니다. </p>
</blockquote>
<hr>
<h2 id="우아한-형제들-회사의-비전-미션">우아한 형제들 회사의 비전, 미션</h2>
<p><code>문 앞으로 배달되는 일상의 행복</code></p>
<p>⇒ 내가 정말 필요로 하는 것이 문 앞에 배달될 때 소비자가 행복을 느낀다</p>
<h2 id="convenience-economy">Convenience Economy</h2>
<ul>
<li><p>고객이 어떤 것에 가치를 느끼고 돈을 지불할거냐, 혹은 본인의 수고로움을 감수하고 서비스를 이용하는 의지를 표명할 것이냐</p>
</li>
<li><p>고객들이 편의라고 하는 것에 가치를 두고 시간, 돈을 들여 서비스를 이용한다</p>
</li>
</ul>
<h2 id="고객들의-일상의-행복을-위한-키워드들">고객들의 일상의 행복을 위한 키워드들</h2>
<ul>
<li><p><code>리뷰이미지 검수</code> : 가끔 이상한 사진들이 올라올 때가 있다. 이미지를 판별하는 머신러닝 알고리즘을 써서 판별함. 기계가 판별한 소수의 이미지를 직원이 수작업으로 검수함</p>
</li>
<li><p><code>99.97 %</code> : 도전 목표 서비스 가용률. 단순히 시간만 의미하는 게 아니라, 주문 유실률을 목표로 함.</p>
<ul>
<li>똑같은 장애라도 시간대 별로 다르다(새벽 4시 VS 오후 피크타임)</li>
<li>피크타임 1시간만 장애가 나더라도 도전하는 기대 목표를 달성할 수 없을 것.</li>
<li>음식을 주문하는 고객과 사장님들을 위해 서비스 안정화는 매우 중요하다</li>
</ul>
</li>
<li><p><code>300만 TPS</code>: 2019년도 한 이벤트에서 1초에 300만 건의 리퀘스트 발생. 피크타임 트랜잭션도 처리할 수 있는 시스템이 필요하다 </p>
</li>
<li><p><code>배달예상시간 고도화</code> : 머신러닝 알고리즘을 이용해서 다양한 변수들을 고려해서 최대한 고객에게 안내한 시간에 정확히 도착할 수 있도록 함</p>
</li>
<li><p><code>라이더배차 효율화</code> : </p>
<ul>
<li>라이더 입장) 같은 시간대에 과속 운전을 하지 않고서도 주문이 딱딱 맞춰서 들어온다면 안정적인 운전을 하면서도 많은 수익을 올릴 수 있다.  </li>
<li>사장님 입장) 음식 식지 않는 게 중요</li>
</ul>
</li>
<li><p><code>쿠폰타겟팅 고도화</code></p>
</li>
<li><p><code>배달대행사 연동</code> : </p>
<ul>
<li>DLL 연동 방식: 주문 접수를 받는 배민 프로그램과 배달 대행 프로그램이 서로 연동을 하되, 배민이 공식적으로 제공하는 채널을 통해서만 연동된다. 그래서 더이상 고객 개인 정보를 볼 수 없게 처리함</li>
<li>서버 to 서버</li>
</ul>
</li>
</ul>
<h3 id="공공배달앱도-있는데-배달앱-만들기-쉽지-않나요">공공배달앱도 있는데, 배달앱 만들기 쉽지 않나요?</h3>
<p>⇒ 얼마나 사장님들이 편하게, 또 고객들의 개인정보 유출 피해가 없도록 보호를 할 것이냐?</p>
<p>⇒ 보안 관점, 시스템 안정성, 가용성 관점, 최적화 관점 등 많은 기술적 문제를 풀어야 하는 것</p>
<h2 id="개발문화가-중요한-회사">개발문화가 중요한 회사</h2>
<p><code>트래픽이 커져감에도 불구하고 얼마나 안정적으로 시스템을 제공할 수 있는가?</code></p>
<ul>
<li>single point of failure(단일 장애점, SPOF)를 줄이는 것이 되게 중요하다</li>
</ul>
<ul>
<li><p>단순히 동작하게 하는 것은 쉽다. 하지만 어떤 한 부분이 안 되더라도 그 대안이 준비되어 있는가 혹은 이 시스템이 실패하더라도 다른 시스템이 동작하도록 할 수 있는가</p>
</li>
<li><p>이런 것들에 대한 사전적인 고려와 &#39;실제로 문제가 발생했을 때 실행할 수 있는 체계와 프로세스가 구축되어 있는가&#39; 가 중요하다.</p>
</li>
</ul>
<h3 id="2015년-9월-기술부채">2015년 9월 기술부채</h3>
<ul>
<li><p>그동안 서비스를 급하고 빠르게 발전시켜오느라 시스템 관점에서 볼 때 우리가 해결해야 하는 문제들이 많이 쌓여 있다</p>
</li>
<li><p>적정 부채만 관리를 한다면 부채는 문제가 아니다</p>
</li>
<li><p><code>오늘 우리가 바라보는 레거시는 사실 어제까지의 최선이었다</code></p>
</li>
<li><p>결국 우리는 적절한 시점에 시장의 발전 속도와 기대 속도에 만족하기 위해서 부채를 감수하고서 빠르게 발전한 것뿐이다. 부채를 적정 수준에서 관리하는 것이 핵심. 이 회사의 시스템이 이상하거나 문제가 많다고 생각하기 보다는 전반적으로 어떻게 관리할 지를 생각하면 좋겠다.</p>
</li>
<li><p>모든 서비스 로직과 비즈니스 로직이 하나의 DBMS 위에서 돌아가고 있었다. WAS는 Web Server로만 동작을 하고 있었다.</p>
</li>
</ul>
<pre><code>→ 리퀘스트들을 받고, 리퀘스트에 건너온 파라미터들을 그대로 다 DBMS로 전달

→ DBMS에서는 Stored procedure

→ DBMS에서 만에 하나 어떤 프로그램 코드가 장애를 일으킨다면, DBMS 전체가 부하가 걸리고 DBMS 전체가 먹통이 됨

→ 전체 시스템 장애로 연결됨</code></pre><blockquote>
<p>보통은 서비스별로도 WAS 그룹들이 여러 개 존재한다</p>
</blockquote>
<p>WAS 그룹들이 리퀘스트를 받으면 비즈니스 로직이나 서비스 로직을 처리하고, 서비스 로직에서 결과로 바뀌는 데이터는 데이터 베이스에 저장을 하고, 필요한 데이터는 가지고 옴</p>
<h3 id="2015년-11월">2015년 11월</h3>
<ul>
<li><p>$2,380 = 이틀 연속 장애가 있었는데, 그때 당시 배상했던 금액을 구성원 수로 나눈 것</p>
</li>
<li><p><code>장애는 언제든지 날 수 있다. 장애가 문제가 아니라 우리가 장애 모니터링을 충분히 했는가?</code></p>
</li>
<li><p><code>장애를 통해서 우리는 배우는가 못 배우는가?</code></p>
</li>
<li><p><code>우리가 배워서 개선을 했는가 못 했는가?</code></p>
</li>
</ul>
<p>⇒ 마이크로 서비스 아키텍처로 가겠다. 스프링, 자바로 가겠다</p>
<h3 id="2016년-3월-pg-시스템-분리">2016년 3월 PG 시스템 분리</h3>
<ul>
<li><p>자바, 스프링 프레임워크로 바꾸고, DBMS도 분리함</p>
</li>
<li><p>조직이 변화하는 데 있어서 중요한 것은 작은 성공의 기쁨</p>
</li>
<li><p>실제로 조직이 변화하려면 성공의 맛을 여러 번 보는 것이 굉장히 중요하다.</p>
</li>
</ul>
<h3 id="2016년-5월-aws-첫-이전">2016년 5월 AWS 첫 이전</h3>
<ul>
<li>조직에서 또 중요한 것은 비전을 보여주고, 우리가 그 방향으로 나아가고 있다는 것을 보여주는 것. 비전을 향한 발걸음</li>
</ul>
<h3 id="2016년-6월-기술블로그-시작">2016년 6월 기술블로그 시작</h3>
<ul>
<li><p>많은 회사의 기술 블로그를 보면 굉장히 깊은 내용들을 다루고 있어서 논문 수준처럼 느껴졌다.</p>
</li>
<li><p>우아한 형제들은 어떠한 포지션을 가지고 가야 할까?</p>
</li>
<li><p>변화하려고 하는 의지를 가지고 있는 사람</p>
</li>
<li><p>누구나 다 알고 있지 않을까? 싶은 것들부터 작성하기</p>
</li>
<li><p>초급자 수준에 머물러 있는 게 창피한 게 아니라 5년 후에 변화가 없는 것이 창피한 것.</p>
</li>
</ul>
<h3 id="2017년-우아한테크캠프">2017년 우아한테크캠프</h3>
<ul>
<li><p>인턴 두 달을 할 때 적절한 프로그램을 주는 게 힘들다</p>
</li>
<li><p>좋은 경험을 가져갔으면 좋겠다는 생각에 교육 과정을 만들어서 운영함</p>
</li>
</ul>
<h3 id="20182019년-우아한-테크-세미나">2018~2019년 우아한 테크 세미나</h3>
<h3 id="2019년-4월-먼데이-프로젝트">2019년 4월 먼데이 프로젝트</h3>
<ul>
<li><p>모든 시스템 전체가 마이크로 서비스 아키텍처로 옮겨가는 과정 마무리</p>
</li>
<li><p>항상 밸런스가 중요하다</p>
</li>
<li><p>시장과 사업의 발전을 따라가는 것과 개발 관점에서 3년 후, 5년 후를 대비했을 때 우리가 무엇을 할 것인가 하는 그 밸런스가 되게 중요하다</p>
</li>
</ul>
<h3 id="2019년-우아한-테크코스">2019년 우아한 테크코스</h3>
<h3 id="2019년-11월-루비-셧다운">2019년 11월 루비 셧다운</h3>
<ul>
<li>문화는 강제할 수 없는 것</li>
</ul>
<h2 id="qa">Q&amp;A</h2>
<ul>
<li><p>질문을 어떻게 디벨롭하고 이뤄나가는가?</p>
<ul>
<li>좋은 질문을 위한 프레임워크는 없다</li>
<li>바보 같은 질문이라는 생각이 들더라도 질문할 수 있는 분위기, 환경 마련</li>
<li>이것이 중요하다</li>
</ul>
</li>
<li><p>지난 2~3년 간 배달앱 이용자가 상당히 많았는데, 앞으로의 배달시장의 미래는 어떨까?</p>
<ul>
<li>convenience economy</li>
<li>내가 사업을 잘 하고 싶으면 10년 뒤에도 변하지 않을 것을, 경쟁력을 갖출 것을 생각해야 한다.</li>
<li>우리는 일상 생활에서도 편의에 돈을 지불한다.</li>
</ul>
</li>
<li><p>적정 수준의 기술부채는 어떻게 측정하고 그 기준은 무엇일까?</p>
<ul>
<li>수치로 얘기하는 게 중요하다기 보다, 구성원들이 어떻게 바라보는 가가 중요하다. 지금 우리가 이런 상황인데, 우리는 이렇게 나아갈거야. 우리가 어떤 것을 선택해서 나아갈까, 새로운 요구사항들이 들어올 때 이걸 할까말까</li>
<li>애자일도 계속 피드백도</li>
<li>피드백 사이클이 잘 동작하는 조직이 기술부채에 대해 잘 대처하는 조직</li>
</ul>
</li>
<li><p>우아한형제들이 생각하는 기존 배달 시스템에 기여한 혁신이란?</p>
<ul>
<li>배민원(구 배민라이더스) 비전: 문 앞으로 배달되는 일상의 행복 이전, 좋은 음식을 먹고 싶은 곳에서, 정보 기술을 활용하여 배달 산업을 혁신시키자.</li>
<li>배달을 하지 않는 곳으로 찾아갔다. 멕시코 음식점으로</li>
<li>통화 필요없이, 배달대행 시스템으로까지 자동화, 사장님은 요리만 하면 된다. 본인의 사업에 기본이 되는 요리에만 집중할 수 있도록</li>
<li>배민라이더스 - 운전하는 도중에는 요청이 가지 않는다.</li>
</ul>
</li>
</ul>
<hr>
<h2 id="배우고-느낀-점-인사이트">배우고 느낀 점, 인사이트</h2>
<ul>
<li><code>오늘 우리가 바라보는 레거시는 사실 어제까지의 최선이었다</code></li>
<li>문화는 강제할 수 없는 것</li>
<li>초급자 수준에 머물러 있는 게 창피한 게 아니라 5년 후에 변화가 없는 것이 창피한 것.</li>
<li>조직에서 또 중요한 것은 비전을 보여주고, 우리가 그 방향으로 나아가고 있다는 것을 보여주는 것. 비전을 향한 발걸음</li>
</ul>
<hr>
<h2 id="출처">출처</h2>
<p>👉 <a href="https://www.youtube.com/watch?v=Dak27J_VVTc">[우아콘2022] 문 앞으로 배달되는 일상의 행복</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[최종 발표 및 최종 회고 ]]></title>
            <link>https://velog.io/@ariul-dev/%EC%B5%9C%EC%A2%85-%EB%B0%9C%ED%91%9C-%EB%B0%8F-%EC%B5%9C%EC%A2%85-%ED%9A%8C%EA%B3%A0</link>
            <guid>https://velog.io/@ariul-dev/%EC%B5%9C%EC%A2%85-%EB%B0%9C%ED%91%9C-%EB%B0%8F-%EC%B5%9C%EC%A2%85-%ED%9A%8C%EA%B3%A0</guid>
            <pubDate>Thu, 20 Oct 2022 16:35:17 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>6주 동안 실전 프로젝트를 진행하면서 학습한 내용을 기록하고, 팀의 리더로서 프로젝트 매니징 경험을 기록하는 시리즈입니다. </p>
</blockquote>
<hr>
<h1 id="최종-발표">최종 발표</h1>
<p><img src="https://velog.velcdn.com/images/ariul-dev/post/6f65ca0e-258b-47c0-a4a6-3dfe05e4c2eb/image.png" alt=""> <strong>👉</strong> <strong><a href="http://hellopatent.site/">안녕, 특허 방문하기</a></strong> </p>
<p><strong>👉</strong> <strong><a href="https://github.com/coogle-yoriking-joriking/hello-patent">안녕, 특허 GitHub 방문하기</a></strong></p>
<h2 id="1-기획-배경-및-시연-영상">1. 기획 배경 및 시연 영상</h2>
<p><img src="https://velog.velcdn.com/images/ariul-dev/post/41a0e519-4769-4d01-9b74-9c181a2ff1dc/image.png" alt=""> 특허정보 검색의 필요성에 따라 많은 사람들이 특허 검색 서비스를 찾고 있고, 정부에서도 대국민 특허정보검색서비스(KIPRIS)를 운영하고 있습니다.</p>
<p>그런데 직접 키프리스를 사용해 본 결과, 다음과 같은 불편함이 있었습니다.</p>
<h3 id="①-너무-많은-검색-기능과-세분화된-분류">① <strong>너무 많은 검색 기능</strong>과 <strong>세분화된 분류</strong> <img src="https://velog.velcdn.com/images/ariul-dev/post/fad9e524-0de3-48b5-b1e2-20f5956f43de/image.png" alt=""></h3>
<h3 id="②-복잡한-ui와-부가-정보">② <strong>복잡한 UI</strong>와 <strong>부가 정보</strong><img src="https://velog.velcdn.com/images/ariul-dev/post/c2a0eca8-f3f4-42f6-8ba7-7dc6045ef399/image.png" alt=""></h3>
<h3 id="③-어려운-연산자-조합-검색">③ 어려운 <strong>연산자 조합 검색</strong> <img src="https://velog.velcdn.com/images/ariul-dev/post/7faab33c-0ddf-4190-a5bd-08538665995f/image.png" alt=""></h3>
<p>이로 인해 특허 검색의 진입 장벽이 높다고 판단하였고, 
<code>비전문가나 초보이용자도 쉽게 이용할 수 있는 특허 검색 서비스</code>를 기획하였습니다.
<img src="https://velog.velcdn.com/images/ariul-dev/post/35c80311-0943-4a71-a41b-9dd4604da582/image.png" alt=""></p>
<p><strong>👉</strong> <strong><a href="https://youtu.be/E6LSRgEePyg">안녕, 특허 시연 영상 보러가기</a></strong> (자막과 함께 시청해 주세요~!🔛)</p>
<hr>
<h2 id="2-아키텍처-및-기술-도입-배경">2. 아키텍처 및 기술 도입 배경</h2>
<p><img src="https://velog.velcdn.com/images/ariul-dev/post/eb72e09e-2936-49ed-894b-047120773fc3/image.png" alt=""></p>
<h3 id="logstash-도입-이유">Logstash 도입 이유</h3>
<blockquote>
<ol>
<li>요구사항<ul>
<li>대용량 csv 데이터의 빠르고 안정된 업로드</li>
<li>간단한 데이터 전처리</li>
</ul>
</li>
<li>대안<ul>
<li>Filebeat</li>
<li>Logstash ✅</li>
</ul>
</li>
<li>도입 이유<ul>
<li>필터 기능 ⇒ Filebeat는 기능이 제한적</li>
<li>데이터 업로드 속도 ⇒ worker thread를 통한 데이터 업로드의 병렬 처리 가능</li>
</ul>
</li>
</ol>
</blockquote>
<p>파일비트는 로그스태시에 비해 리소스를 적게 쓰는 장점이 있습니다.</p>
<p>하지만 로그스태시는 다양한 필터기능을 갖추고 있고, worker thread를 통한 데이터 업로드의 병렬처리가 가능하다는 장점이 있습니다.</p>
<p>따라서 대량의 csv데이터를 가공하여 엘라스틱서치에 업로드하는 데는 로그스태시가 적합하다고 판단하여 채택하였습니다.</p>
<p><img src="https://velog.velcdn.com/images/ariul-dev/post/ce701b9f-b49c-48b1-b89f-5d43e8f8a8d9/image.png" alt=""></p>
<h3 id="elasticsearch-도입-이유">Elasticsearch 도입 이유</h3>
<blockquote>
<ol>
<li>요구사항<ul>
<li>검색 결과 1초 내 반환 목표</li>
<li>8000만 건의 대용량 데이터 운용</li>
</ul>
</li>
<li>대안<ul>
<li>RDB vs NoSQL</li>
<li>Search Engine(Elasticsearch) ✅</li>
</ul>
</li>
<li>도입 이유<ul>
<li>전문 검색 기능 ⇒ 분석기 커스터마이즈 + 역인덱싱으로 검색 정확도 향상</li>
<li>역인덱싱 ⇒ 검색 데이터 양에 구애받지 않고, 키워드 검색 시 O(1)의 시간 효율성으로 조회 가능</li>
</ul>
</li>
</ol>
</blockquote>
<p>안녕 특허 서비스의 목표는 데이터 조회 시 결괏값을 1초 내로 반환하는 것과,
대용량의 데이터 운용, 사용자의 검색 편의성과 정확도의 개선입니다.</p>
<p>엘라스틱서치는 여러 플러그인을 이용한 전문 검색 기능을 갖추어 검색 정확도를 높이는데 적합합니다.
또한, RDB에서의 색인 기능과 다른 역색인 기능과 캐싱 기능을 제공합니다.
그에 따라 검색 데이터양과 상관없이 시간 복잡도를 O(1)로 관리할 수 있는 장점이 있습니다.</p>
<p>이러한 이유로 저희 서비스에 최적화된 기술은 엘라스틱서치라고 판단하여 도입하였습니다. </p>
<hr>
<h2 id="3-기술적-도전과-배움">3. 기술적 도전과 배움</h2>
<h3 id="elasticsearch-메모리-설정-문제">Elasticsearch 메모리 설정 문제</h3>
<p>자세한 내용을 담은 블로그 포스팅입니다.😊</p>
<p>👉 <a href="https://velog.io/@ariul-dev/%EC%82%AC%EC%9A%A9%EC%9E%90-%EC%A0%95%EC%9D%98-%EC%82%AC%EC%A0%84-%EC%A0%81%EC%9A%A9-%EC%8B%A4%ED%8C%A8">Elasticsearch GC Overhead 문제로 사용자 정의 사전 적용 실패</a></p>
<h3 id="오타-교정-기능--검색-결과-정확도-개선-문제">오타 교정 기능 + 검색 결과 정확도 개선 문제</h3>
<p>자세한 내용을 담은 블로그 포스팅입니다.😊
👉<a href="https://velog.io/@ariul-dev/%EC%98%A4%ED%83%80-%EA%B5%90%EC%A0%95-%EA%B8%B0%EB%8A%A5-%EC%A0%81%EC%9A%A9-%EC%9D%B4%ED%9B%84-%EA%B2%80%EC%83%89-%EA%B2%B0%EA%B3%BC-%EC%A0%95%ED%99%95%EB%8F%84-%ED%96%A5%EC%83%81%EC%9D%84-%EC%9C%84%ED%95%9C-%EC%9D%B8%EB%8D%B1%EC%8A%A4-%EB%A7%A4%ED%95%91-%EB%B3%80%EA%B2%BD-%EA%B3%BC%EC%A0%95-">오타 교정 기능 적용 이후 검색 결과 정확도 향상을 위한 인덱스 매핑 변경 과정-①</a>
👉<a href="https://velog.io/@ariul-dev/%EC%98%A4%ED%83%80-%EA%B5%90%EC%A0%95-%EA%B8%B0%EB%8A%A5-%EC%A0%81%EC%9A%A9-%EC%9D%B4%ED%9B%84-%EA%B2%80%EC%83%89-%EA%B2%B0%EA%B3%BC-%EC%A0%95%ED%99%95%EB%8F%84-%ED%96%A5%EC%83%81%EC%9D%84-%EC%9C%84%ED%95%9C-%EC%9D%B8%EB%8D%B1%EC%8A%A4-%EB%A7%A4%ED%95%91-%EB%B3%80%EA%B2%BD-%EA%B3%BC%EC%A0%95-bidk0fjz">오타 교정 기능 적용 이후 검색 결과 정확도 향상을 위한 인덱스 매핑 변경 과정-②</a></p>
<h2 id="4-앞으로의-계획">4. 앞으로의 계획</h2>
<ol>
<li><p>사용자 정의 사전 적용
로컬환경에서는 사용자 정의 사전을 사용했지만 EC2에서는 OOM 문제로 인해 적용하지 못했는데요, 
EC2 업그레이드 이후 사용자 정의 사전을 적용해 볼 예정입니다</p>
</li>
<li><p>새롭게 추가되는 데이터 수집
키프리스에서 새롭게 추가되는 특허 데이터들을 주기적으로 서버에 저장하는 데이터 파이프라인을 구상할 예정입니다.</p>
</li>
<li><p>사용자 클릭 로그 확보
사용자들의 클릭에 대한 로그 정보를 확보하여 검색 결과 정확도 향상의 분석 자료로 활용해 보는 시간을 가질 것입니다.</p>
</li>
</ol>
<hr>
<p><code>🚨 여기서부터는 저만의 기록이기 때문에 경어체를 쓰지 않겠습니다..!</code></p>
<h2 id="피드백-및-느낀-점">피드백 및 느낀 점</h2>
<pre><code>- 기술 선택 근거가 명확하고, 개선하려고 엄청 고민하고 행동한 흔적이 잘 보인다.
- 완성도가 높아서 신기하다.</code></pre><p>생각하고 걱정했던 것보다 더더욱 좋은 피드백들을 받았다.
특히 검색 정확도와 검색 속도 관련해서 긍정적인 피드백을 받을 때마다 진짜 보람차고 뿌듯해서 날아갈 뻔 🤭💨</p>
<p>멘토님들께서 피드백과 더불어 여러 방향의 질문을 하셨다. 
데이터 정형화 쉽지 않았을텐데 전처리는 어떻게 했는지,
ELK 처음 설정할 때 어떤 문제가 있었는지,
트래픽은 어떻게 분산했고 왜 그렇게 했는지 등등 확인을 위한 질문이었다.</p>
<p>모든 질문에 최선을 다해 답변을 드렸지만, 아직 부족한 느낌이 들고 만족스럽지 않았다.
최대한 구체적으로 답변할 수 있게 프로젝트를 다시 돌아보고 정리해 봐야겠다.</p>
<hr>
<h1 id="최종-회고">최종 회고</h1>
<h2 id="무엇을-배웠나">무엇을 배웠나</h2>
<h3 id="1-프로그래밍을-대하는-자세">1. 프로그래밍을 대하는 자세</h3>
<blockquote>
<p>기술을 활용할 때는 <strong><code>공식 문서</code></strong>부터 본다</p>
</blockquote>
<p>⇒ 기술은 버전별로 내용과 기능이 많이 다르기 때문이다 </p>
<p>사실 이 프로젝트 하기 전부터 공식 문서의 중요성은 익히 들어왔다. 회고 글이나 공부법을 소개하는 글에서 공식 문서의 중요성을 얘기하는 사람들이 많았기 때문이다. 하지만 나는 별 감흥이 없었다. 
그때 당시 마인드는,</p>
<pre><code>ㅇㅖ ..? 한국어로 적혀 있어도 어렵운데 이걸 영어로 보라구요 ? 
나름 영어 가까이하면서 살아왔는데도 이건.. 어우.. 너무 어려운 걸요🥲</code></pre><p>근데 많은 우여곡절 끝에 이런 변화가 생겼다
포스팅을 똑! 같! 이! 따라 해도 나만 안 되는 경우가 너무 많아 ~ 근데 이유도 각양각색 ~ </p>
<p>블로그로 쉽게 이해하려고 하다 시간이랑 노력 많이 날아갔다..... <del>아주 호되게 당했다🤭</del>
그제야 왜 많은 선배님들이 공식 문서의 중요성을 설파하셨는지 조금 알 것 같았다.</p>
<p>사실 일반 블로그 포스팅들도 여전히 많이 본다. 아주 많이 본다. 
좋은 정보를 잘 정리해 주신 분들이 너무 많아서 항상 감사한 마음으로 챙겨봄..ㅎㅎ
근데 순서를 좀 바꿔서 이제는<code>공식 문서부터</code> 보는 습관을 가지려고 노력한다.</p>
<blockquote>
<p>IT 기업에서 운영하는 기술 블로그, 컨퍼런스 챙겨보기</p>
</blockquote>
<p>개발 공부를 시작한 지 얼마 안 됐을 때도 보기는 봤었다. 
워낙 여기저기 기웃거리면서 신기한 정보 듣는 거 좋아해서 기술 컨퍼런스는 자주 신청했었고(그렇다고 제대로 이해했다는 소리는 아님), IT 기업 기술 블로그도 구글링 하다가 몇 번 보곤 했다.</p>
<p>근데 그때는 흰색은 바탕이오~ 검은색은 글자로다~ 이런 경우가 대부분이었는데,
시간이 지날수록 포스팅을 보고 이해하는 게 점점 많아져서 짜릿하다</p>
<p>실제로 학습한 내용을 프로젝트에 적용하기도 했었다.</p>
<ul>
<li>우아콘에서 마이크로서비스로의 전환기를 보면서 아키텍처 설계와 서비스 안정화의 중요성을 깨달았다. 이걸 보고 확장성을 늘 고려해야 한다고 판단하였기 때문에 기획 단계에서부터 MVP 이후 확장 가능성이 있는 기능들을 정리했다. 아키텍처 설계의 경우, 서버 부하를 줄이고 성능을 개선하기 위해 메인 서버를 스케일 업하였고, 대용량 데이터를 엘라스틱서치에 넣기 위한 데이터 파이프라인 서버를 새로 구축했다.</li>
<li>검색 기능 개발할 때는 정말 많은 IT 기술 블로그를 봤다. 배민부터 무신사, 당근마켓, 브랜디, 오늘의 집, 다나와 등등 <code>검색</code>이 안 들어가는 서비스가 없다 보니 관련 자료를 많이 찾을 수 있었다. 원래는 우리 특허 서비스에 사용자 정의 사전을 적용하지 않을 생각이었다. 기업들은 다 ML팀에서 만들어 준다며.. 우리는 누가 뭘 키워드로 검색할 줄 알고 그걸 만들어.. 했는데 기술 블로그 글들을 보고 사용자 정의 사전을 어떻게든 찾아내야겠다는 결심을 했다. 다들 기본적으로 쓰고 있는데 우리도 실 서비스 못지않은 퀄리티 내려면 무조건 써야지! 이런 생각을 했기 때문..ㅎㅎ 어쨌든 결국 찾아냈고 정확도 문제도 해결했다~!</li>
<li>네이버 컨퍼런스(DEVIEW)도 검색 서비스의 전체 사이클을 이해하는 데 많은 도움이 됐다. 특히 검색 결과 정확도 개선할 때 아주 핵심적인 힌트를 얻었다. 인덱스 텀과 쿼리 텀 일치시키기! 아주아주 당연한 건데 왜 놓치고 있었을까요🥲 DEVIEW 덕분에 해결했슴다 (하하)</li>
</ul>
<p>솔직히 여전히 많이 많이 어렵다. 학습한 자료들도 A부터 Z까지 제대로 이해했다고 자신할 만한 정도도 아니고.. 하지만 이 자료들을 내 개발 공부의 지표로 삼고 꾸준히 챙겨 볼 예정이다. 
<code>이해하는 게 많아진다 = 실무에 가까워지고 있다!</code> 이렇게 생각하기 때문이다.</p>
<h3 id="2-무엇이든-할-수-있다는-자신감">2. 무엇이든 할 수 있다는 자신감</h3>
<p>역시 언제나 그랬듯이 <code>끈질기게 매달리면 결국 할 수 있다!</code> 또 한 번 깨달았다.</p>
<p>사실 기우제처럼 
끈질기게 매달렸더니 해결됐다(❌)
해결할 때까지 끈질기게 매달렸다(⭕)</p>
<p>이거지만..🤭</p>
<p>프로젝트하면서 소통 문제부터 기능적 문제까지 매 순간이 트러블 슈팅이었다.
하지만 진심으로 모든 문제를 잘 해결하고 싶어서 다각도로 많이 고민했다.
가장 놀랐던 점, 중학생 때 전교회장하면서 했던 고민을 똑같이 하고 있더라. 그때도 혼자서 다 챙기려다 힘들어했었는데.. 여전히 그걸 못 고치고 또 힘들어하고 있었다.   </p>
<p>그때처럼 리더십에 관한 책을 사서 읽고, 부모님께 지혜를 배웠다.
아버지는 그때와 똑같은 가르침을 주셨다.
<code>혼자서 다 하는 건 진정한 리더십이 아니다. 모두가 조직에 대해 오너십을 갖게 해야 한다.</code>
이걸 잊고 살다가 다시 한번 리더십에 대해 고민하고 깨달음을 얻었다.
이번엔 조직에 관한 아티클도 읽고 유튜브 명강의도 찾아 들었다. </p>
<p>모든 채널에서 얻은 좋은 리더와 좋은 조직에 대한 핵심은 이거였다.
&quot;모든 구성원들이 조직에 대해 오너십을 갖도록 하기&quot;
&quot;심리적 안전감이 드는 조직 분위기를 형성하기&quot; </p>
<p>일의 체계와 명확성을 갖도록 역할을 분배하고, 각자 맡은 역할을 잘 수행할 수 있게 매일 스크럼으로 확인했다. 
문제가 생길 땐 내 일, 네 일이 아니라 우리 모두의 일이 되도록 했다. 실수하거나 일정에 차질이 생기더라도 <code>괜찮아요 우린 함께라서 결국 해낼 수 있어요</code> 를 피력하려고 많이 노력했다. </p>
<p>이렇게 문제가 생길 때마다 치열하게 고민했기에 큰 프로젝트를 무사히 잘 마무리할 수 있었다고 생각한다.
근데 다 떠나서 가장 중요한 건 좋은 팀원들을 만났기 때문, 함께 성장하고자 열정 넘치는 팀원들과 함께였기 때문에 가능했던 일이라고 생각한다.  </p>
<h3 id="3-많은-사람들의-도움이-있었기에-가능했던-일--이타적인-자세">3. 많은 사람들의 도움이 있었기에 가능했던 일 + 이타적인 자세</h3>
<p>6주 내내 입에 달고 살았던 말이 있다. <code>Shout out to XXX ~~!~!!!</code>
shout out shout out ~! 장난처럼 말했지만
진심으로 shout out 할 분들이 많다.</p>
<h2 id="thanks-to">Thanks to.</h2>
<p>실전 프로젝트 첫날, 팀원들과 그라운드 룰을 정하면서 “이 시기를 되돌아봤을 때, 스스로 후회하지 않을 만큼 치열한 6주를 보내고 싶다.”라는 이야기를 나눴습니다.</p>
<p>6주가 지난 지금, 스스로 생각하기에 치열하게 보냈다고 자신할 수 있어 뿌듯합니다.</p>
<p>어느 것 하나 쉬웠던 적이 없던 프로젝트였습니다.</p>
<p>2주 차 때는 기획 변경 후 mvp 개발하느라 스파르타로 진행되었고,
3주 차 때는 서비스를 위한 ELK 구축 자체가 막막했고,
4주 차 때는 지금 가는 방향이 맞는지, 기한 내 완성은 될는지, 프로젝트 일정을 어디까지 잡아놔야 할지 등으로 걱정이 가득했고,
5주 차 때는 오타 교정 기능에 따른 검색 결과 정확도를 개선하느라 잠을 이루지 못했습니다.</p>
<p>매주 새로운 어려움을 마주했지만, 모든 걸 이겨내고 계속 나아갈 수 있었던 건 각자의 역할에 최선을 다하고 열정 넘쳤던 팀원들 덕분이라고 생각합니다.</p>
<p>마지막까지 최선을 다 한 우리 팀원들 덕분에
이번 6주 차는 “행복”, “뿌듯함”, “성취”라는 키워드로 기억될 것 같습니다.</p>
<p>프로젝트 시작부터 마무리까지 아낌없는 조언과 가르침 주신 멘토님 너무 감사드립니다. 길을 잃은 느낌이 들 때마다 멘토링 사전 노트에 질문을 썼는데,  멘토님의 가르침 덕분에 길을 찾고 다시 나아갈 수 있었습니다.</p>
<p>프로젝트 진행에 어려움이 없도록 살펴주시고 도와주신 매니저님께도 감사의 말씀을 드립니다.</p>
<p>어려움이 생겨 도움을 요청했을 때마다 자신의 프로젝트처럼 같이 해결법을 고민하고 열심히 도와주신 스프링팀 1조 팀원분들! 진심으로 감사합니다</p>
<p>단순히 ‘새로운 기술을 사용했다!’에서 그치지 않고
새로운 기술을 왜 사용했는지, 어떻게 사용했는지, 어떤 어려움이 있었고 어떻게 해결했는지를 설명할 수 있는 프로젝트를 진행한 것 같습니다.</p>
<p>이 경험이 앞으로 있을 많은 프로젝트 진행에 큰 도움이 될 것 같습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[사용자 경험 개선을 위한 고민들]]></title>
            <link>https://velog.io/@ariul-dev/%EC%82%AC%EC%9A%A9%EC%9E%90-%EA%B2%BD%ED%97%98%EC%9D%84-%EC%9C%84%ED%95%9C-%EA%B3%A0%EB%AF%BC-%EC%96%B4%EB%94%94%EA%B9%8C%EC%A7%80-%ED%95%B4%EB%B4%A4%EB%8B%88</link>
            <guid>https://velog.io/@ariul-dev/%EC%82%AC%EC%9A%A9%EC%9E%90-%EA%B2%BD%ED%97%98%EC%9D%84-%EC%9C%84%ED%95%9C-%EA%B3%A0%EB%AF%BC-%EC%96%B4%EB%94%94%EA%B9%8C%EC%A7%80-%ED%95%B4%EB%B4%A4%EB%8B%88</guid>
            <pubDate>Thu, 20 Oct 2022 16:32:55 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>6주 동안 실전 프로젝트를 진행하면서 학습한 내용을 기록하고, 팀의 리더로서 프로젝트 매니징 경험을 기록하는 시리즈입니다. </p>
</blockquote>
<hr>
<h2 id="🤔어떻게-하면-사용자가-편리하게-서비스를-이용할-수-있을까">🤔어떻게 하면 사용자가 편리하게 서비스를 이용할 수 있을까?</h2>
<p>우리 서비스는 <strong>직접 선행기술조사를 하는 비전문가</strong>나 비교적 간단한 정보가 필요한 <strong>초보 이용자</strong>를 위한 특허 검색 서비스입니다.</p>
<p>기존의 특허 검색 서비스는 다음과 같은 이유로 초보자가 이용하기에 불편하다고 생각했습니다. <img src="https://velog.velcdn.com/images/ariul-dev/post/c1387879-d559-4ec5-b2b2-afa4f68dbce9/image.png" alt=""></p>
<p>타깃 유저를 고려하여 편의성을 고민하였고, 수많은 회의를 통해 다음과 같은 결정을 내렸습니다.</p>
<ul>
<li>연산자 조합 검색 대신 <code>직관적인 검색</code>이 가능하도록 한다.</li>
<li><code>가볍고 직관적인 인터페이스</code>를 만든다.</li>
<li>사용자가 <code>서비스를 쉽게 이해할 수 있도록 장치</code>를 마련한다.</li>
<li>검색 결과를 <code>빠르고 정확하게</code> 반환한다.</li>
</ul>
<hr>
<h2 id="1-직관적인-검색-기능">1. 직관적인 검색 기능</h2>
<h3 id="🙅❌-너무-많은-검색-기능과-세분화된-분류">🙅‍❌ 너무 많은 검색 기능과 세분화된 분류</h3>
<p><img src="https://velog.velcdn.com/images/ariul-dev/post/0c38ed1a-283a-4461-a62d-1bd97d793144/image.png" alt="">
너무 많은 검색 기능과 세분화된 분류로 인해 특허권 검색에 대한 피로도가 높다고 생각하였습니다. 따라서 검색에 필수적으로 필요한 분류 값들을 드롭 다운 형식으로 묶어 검색 편의성을 높이고자 하였습니다. </p>
<h3 id="🙆⭕-드롭-다운-형식으로-해결">🙆‍⭕ 드롭 다운 형식으로 해결</h3>
<p><img src="https://velog.velcdn.com/images/ariul-dev/post/3bc4f678-9632-464a-8b2a-ff745de59bc2/image.png" alt=""> <strong>전체</strong>: 찾고 싶은 키워드 자유 검색
<strong>제목(명칭)</strong>: 특허 명칭에서 찾고 싶은 키워드 검색
<strong>요약</strong>: 요약에서 찾고 싶은 키워드 검색
<strong>번호정보</strong>: 출원번호/공고번호/공개번호/등록번호에서 찾고 싶은 번호 검색
<strong>연도</strong>: 찾고 싶은 연도 검색
<strong>IPC/CPC분류</strong>: 찾고 싶은 IPC/CPC 검색
<strong>출원인</strong>: 찾고 싶은 출원인 검색</p>
<hr>
<h3 id="🙅❌-연산자와-키워드를-조합한-검색-기능">🙅‍❌ 연산자와 키워드를 조합한 검색 기능</h3>
<p><img src="https://velog.velcdn.com/images/ariul-dev/post/1e840b5a-e51d-413b-9a9c-ec3a961793c1/image.png" alt=""></p>
<p>또한 키워드랑 연산자를 조합해야 하는 검색 기능은 특허 검색 서비스에 대한 진입 장벽을 높인다고 생각했습니다. 따라서 직관적인 &#39;포함검색&#39;과 &#39;제외검색&#39; 기능을 개발하여 검색식이 없어도 사용자가 다양한 검색을 할 수 있도록 하였습니다. </p>
<h3 id="🙆⭕-연산자를-사용하지-않는-직관적-검색-기능">🙆‍⭕ 연산자를 사용하지 않는 직관적 검색 기능</h3>
<p><img src="https://velog.velcdn.com/images/ariul-dev/post/11f40794-45b5-42e2-8e0d-51869d8e3861/image.png" alt=""></p>
<p><strong>기본검색</strong>: 기존 검색 내용을 삭제하고 새로 검색하는 기능
<strong>포함검색</strong>: 검색 결과 내에서 해당 키워드를 반드시 포함하는 특허 데이터를 반환하는 기능
<strong>제외검색</strong>: 검색 결과 내에서 해당 키워드를 가진 특허 데이터를 제외하는 기능</p>
<hr>
<h2 id="2-가볍고-직관적인-인터페이스">2. 가볍고 직관적인 인터페이스</h2>
<h3 id="🙅❌-너무-많은-정보와-부가-서비스가-담긴-검색-결과-페이지">🙅‍❌ 너무 많은 정보와 부가 서비스가 담긴 검색 결과 페이지</h3>
<p><img src="https://velog.velcdn.com/images/ariul-dev/post/35525dec-f311-4388-b72c-dc2c036382e0/image.png" alt=""></p>
<p>검색 결과 페이지에 너무 많은 정보와 부가서비스가 담겨 있어 사용하기에 복잡하다고 판단하였습니다. 따라서 검색 결과 페이지에는 핵심 정보와 핵심 기능만 담아 가볍고 직관적인 인터페이스를 구축하였습니다. </p>
<h3 id="🙆⭕-핵심-정보와-핵심-기능만-갖춘-검색-결과-페이지">🙆‍⭕ 핵심 정보와 핵심 기능만 갖춘 검색 결과 페이지</h3>
<p><img src="https://velog.velcdn.com/images/ariul-dev/post/e79c05c9-a0af-4bb9-97fb-23a5e8172d6e/image.png" alt=""></p>
<h3 id="-서비스를-관통하는-키워드로-색상-선정">+ 서비스를 관통하는 키워드로 색상 선정</h3>
<p>서비스를 대표하는 색상을 선정할 때도 많은 회의를 거쳤습니다.
대체로 공공기관이나 금융 서비스 등에 파란색이 사용됩니다. 파란색은 스마트한 첨단의 느낌을 주면서도 전통적으로 &#39;신뢰감&#39;을 상징하는 가장 대표적인 색상이기 때문입니다.
레퍼런스 서비스인 키프리스도 대표 색으로 파란색을 선택했습니다.</p>
<p>저희도 특허 <strong>&#39;데이터&#39;</strong>를 다루는 서비스이니 만큼 <strong>&#39;신뢰감을 줄 수 있는가?&#39;</strong>를 가장 먼저 고려하였습니다. 하지만 보편적인 파란색은 자칫하면 타켓 유저인 초보 이용자에게 딱딱하고 차가운 느낌을 줄 수 있다고 판단하여 <strong>&#39;초보 이용자가 편안하게 사용할 수 있는가?&#39;</strong>도 고려하여 색을 선정하였습니다. </p>
<p><strong>신뢰할 수 있지만 딱딱하거나 어렵지 않은 서비스</strong>라는 이미지를 구축하기 위해 서비스를 대표하는 색상으로 <code>#82C5F1</code>를 선택하였습니다.</p>
<hr>
<h2 id="3-사용자가-서비스를-쉽게-이해할-수-있도록-돕는-장치">3. 사용자가 서비스를 쉽게 이해할 수 있도록 돕는 장치</h2>
<h3 id="특허-용어-설명-모달창">특허 용어 설명 모달창</h3>
<p><code>IPC</code>, <code>CPC</code>, <code>번호정보</code> 등의 특허 용어는 처음 접하면 이해하기 어렵다고 판단하였습니다. 
따라서 특허 용어를 설명하는 모달창을 만들어 특허 검색 서비스 초보 이용자도 원하는 정보를 쉽게 검색할 수 있도록 하였습니다.<br><img src="https://velog.velcdn.com/images/ariul-dev/post/1f2cf0cc-daaa-4fb3-b443-4d204ff24f98/image.png" alt=""> </p>
<h3 id="hover-시-검색-기능에-대한-설명">hover 시 검색 기능에 대한 설명</h3>
<p>연산자 조합 검색 기능 대신 개발한 직관적인 검색 기능을 사용자가 쉽게 사용할 수 있도록 기능에 대한 설명을 추가하였습니다.
<img src="https://velog.velcdn.com/images/ariul-dev/post/e0db7a83-5280-4b3f-9179-4708c103ba96/image.png" alt=""> <img src="https://velog.velcdn.com/images/ariul-dev/post/1d3975ab-04e0-444f-a005-e5427b4f4a77/image.png" alt=""> <img src="https://velog.velcdn.com/images/ariul-dev/post/514a8921-d97c-409d-9a97-3f4f688550a3/image.png" alt=""></p>
<hr>
<h2 id="4-정확한-검색-결과를-빠르게-반환">4. 정확한 검색 결과를 빠르게 반환</h2>
<h3 id="검색-결과-반환-속도">검색 결과 반환 속도</h3>
<p>특허 데이터이니만큼 &quot;invention&quot; 키워드를 포함한 검색 결과가 많을 것이라 판단하여 검색해 보았습니다.</p>
<p><code>약 1700만 건의 데이터</code>를 <code>약 400 ms 만에 반환</code>한 것을 확인할 수 있습니다. <img src="https://velog.velcdn.com/images/ariul-dev/post/d720ff48-d051-4313-8276-4c2900395dbb/image.png" alt=""></p>
<h3 id="검색-결과-정확도">검색 결과 정확도</h3>
<p>오타 교정 검색 기능 적용 이후 검색 결과 정확도 향상을 위한 과정을 자세히 담은 블로그 포스팅입니다.😊
👉<a href="https://velog.io/@ariul-dev/%EC%98%A4%ED%83%80-%EA%B5%90%EC%A0%95-%EA%B8%B0%EB%8A%A5-%EC%A0%81%EC%9A%A9-%EC%9D%B4%ED%9B%84-%EA%B2%80%EC%83%89-%EA%B2%B0%EA%B3%BC-%EC%A0%95%ED%99%95%EB%8F%84-%ED%96%A5%EC%83%81%EC%9D%84-%EC%9C%84%ED%95%9C-%EC%9D%B8%EB%8D%B1%EC%8A%A4-%EB%A7%A4%ED%95%91-%EB%B3%80%EA%B2%BD-%EA%B3%BC%EC%A0%95-">오타 교정 기능 적용 이후 검색 결과 정확도 향상을 위한 인덱스 매핑 변경 과정-①</a>
👉<a href="https://velog.io/@ariul-dev/%EC%98%A4%ED%83%80-%EA%B5%90%EC%A0%95-%EA%B8%B0%EB%8A%A5-%EC%A0%81%EC%9A%A9-%EC%9D%B4%ED%9B%84-%EA%B2%80%EC%83%89-%EA%B2%B0%EA%B3%BC-%EC%A0%95%ED%99%95%EB%8F%84-%ED%96%A5%EC%83%81%EC%9D%84-%EC%9C%84%ED%95%9C-%EC%9D%B8%EB%8D%B1%EC%8A%A4-%EB%A7%A4%ED%95%91-%EB%B3%80%EA%B2%BD-%EA%B3%BC%EC%A0%95-bidk0fjz">오타 교정 기능 적용 이후 검색 결과 정확도 향상을 위한 인덱스 매핑 변경 과정-②</a></p>
<p>검색 품질을 검증하기 위해 레퍼런스 사이트와 비교 테스트를 진행해 보았습니다. 
원문 키워드 검색, 띄어쓰기 조절 검색의 경우, 비슷한 품질의 데이터를 반환했습니다.</p>
<p>오타 교정 검색의 경우에는, 저희 서비스가 더 좋은 품질의 데이터를 반환하는 경우도 있었습니다.</p>
<p>오타를 낸 &#39;어일저장탱크&#39;로 검색했을 때 &#39;오일저장탱크&#39;를 반환하는지 테스트한 결과,
키프리스는 원하는 결과를 반환하지 않는 것을 알 수 있습니다.
그에 반해 저희 서비스는 사용자가 원하는 결과를 반환하였습니다.</p>
<p>이를 통해, 오타 교정 기능과 검색 결과 정확도 문제가 개선되었다는 것을 확인할 수 있었습니다.</p>
<h4 id="레퍼런스-사이트-⇒-사용자가-원하는-결과를-반환하지-않음">레퍼런스 사이트 ⇒ 사용자가 원하는 결과를 반환하지 않음</h4>
<p><img src="https://velog.velcdn.com/images/ariul-dev/post/52f5d2dc-5479-4173-afca-49fa56e869c2/image.png" alt=""></p>
<h4 id="안녕-특허-⇒-사용자가-원하는-결과를-반환함">안녕, 특허 ⇒ 사용자가 원하는 결과를 반환함</h4>
<p><img src="https://velog.velcdn.com/images/ariul-dev/post/c97cf086-1fed-4437-9583-a27833669f7a/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[8000만 건의 특허 데이터를 수집한 과정]]></title>
            <link>https://velog.io/@ariul-dev/8000%EB%A7%8C-%EA%B1%B4%EC%9D%98-%ED%8A%B9%ED%97%88-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%A5%BC-%EC%88%98%EC%A7%91%ED%95%9C-%EA%B3%BC%EC%A0%95</link>
            <guid>https://velog.io/@ariul-dev/8000%EB%A7%8C-%EA%B1%B4%EC%9D%98-%ED%8A%B9%ED%97%88-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%A5%BC-%EC%88%98%EC%A7%91%ED%95%9C-%EA%B3%BC%EC%A0%95</guid>
            <pubDate>Mon, 17 Oct 2022 05:49:05 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>6주 동안 실전 프로젝트를 진행하면서 학습한 내용을 기록하고, 팀의 리더로서 프로젝트 매니징 경험을 기록하는 시리즈입니다. </p>
</blockquote>
<hr>
<h2 id="요구-사항">요구 사항</h2>
<ul>
<li>레퍼런스 사이트(Kipris)의 특허 데이터 8000만 건 수집하기</li>
<li>국내 특허 데이터 (<strong>Total 5,022,553</strong>)<img src="https://velog.velcdn.com/images/ariul-dev/post/0fcea6ff-2ce0-40b4-866d-8611d7ee0707/image.png" alt=""></li>
<li>해외 특허 데이터 (Total 75,868,149)
<img src="https://velog.velcdn.com/images/ariul-dev/post/e366bace-b686-4f15-9961-36f9ca00bd06/image.png" alt=""></li>
</ul>
<hr>
<h2 id="크롤링을-어떻게-할-것인가">크롤링을 어떻게 할 것인가?</h2>
<p><img src="https://velog.velcdn.com/images/ariul-dev/post/5a2693bc-1b12-4362-b01f-ff62d84af971/image.png" alt=""></p>
<h4 id="1-jsoup이나beautifulsoup을-이용해-html-태그에서-원하는-정보를-빼와서-저장하는-방식">1) Jsoup이나BeautifulSoup을 이용해 html 태그에서 원하는 정보를 빼와서 저장하는 방식</h4>
<p>⇒ 데이터가 너무 많아서 이러한 방식으로는 시간이 너무 오래 걸릴 것이라 판단하였습니다.</p>
<h4 id="2-kipris의-온라인-다운로드-기능-사용1회-최대-다운로드-5000건">2) Kipris의 온라인 다운로드 기능 사용(1회 최대 다운로드 5000건)</h4>
<p>⇒ 다운로드를 할 때 URL로 Payload를 담아서 Post 요청을 하면 xls파일을 반환합니다.
<img src="https://velog.velcdn.com/images/ariul-dev/post/babf769d-f499-45b8-86d1-5c9ddffd23aa/image.png" alt=""></p>
<h4 id="3-2를-자동화하는-자바-수집기-개발-✅">3) 2)를 자동화하는 자바 수집기 개발 ✅</h4>
<hr>
<h2 id="process">Process</h2>
<h3 id="1-담아야-할-정보들을-payload에-담아서-kipris-사이트에게-요청한다"><strong>1. 담아야 할 정보들을 Payload에 담아서 Kipris 사이트에게 요청한다.</strong></h3>
<h3 id="2-kipris가-response로-xls-파일을-보내준다"><strong>2. Kipris가 Response로 xls 파일을 보내준다.</strong></h3>
<p><strong>Kipris에서 받아온 데이터</strong> <img src="https://velog.velcdn.com/images/ariul-dev/post/3471ee6d-ab52-4af3-bd9b-d57112aab716/image.png" alt=""> ⇒ 불필요한 부분(1행~7행)은 자바의 poi 라이브러리를 이용해 제거</p>
<h3 id="3-받은-xls-파일을-로그스태시로-엘라스틱서치-서버에-보내기-위해-csv로-변환한다"><strong>3. 받은 xls 파일을 로그스태시로 엘라스틱서치 서버에 보내기 위해 csv로 변환한다.</strong></h3>
<hr>
<h2 id="트러블-슈팅">트러블 슈팅</h2>
<h3 id="문제-상황">문제 상황</h3>
<p>csv 데이터를 키바나에 업로드하면 파싱 에러 발생하였습니다.</p>
<h3 id="문제-원인">문제 원인</h3>
<p>csv 데이터는 콤마(,)를 구분자로 데이터 항목들을 구분하는데, 받아온 특허 데이터 안에 콤마(,)나 인용문(” “)이 포함되어 있어서 제대로 변환되지 않았습니다.</p>
<h3 id="해결-방안">해결 방안</h3>
<p>콤마(,)와 인용문(&quot;&quot;)을 따로 처리하는 코드를 추가하였습니다.</p>
<ul>
<li>콤마(,) 처리 코드</li>
</ul>
<pre><code class="language-java"> data.append(&quot;\&quot;&quot;+cell.getStringCellValue()+&quot;\&quot;&quot;+&quot;,&quot;);</code></pre>
<p>⇒ 전체를 <code>“ “</code> 로 감싸준다.</p>
<ul>
<li>인용문(&quot;&quot;) 처리 코드</li>
</ul>
<pre><code class="language-java"> data.append(&quot;\&quot;&quot;).append(cell.getStringCellValue().replaceAll(&quot;\&quot;&quot;, &quot;\&quot;\&quot;&quot;)).append(&quot;\&quot;,&quot;);</code></pre>
<p>⇒ <code>“ “”인용문“” “</code> 처럼 쌍따옴표를 한번 더 감싸주고 전체를 다시 감싸준다.</p>
<hr>
<h2 id="국내-데이터-수집-방법과-해외-데이터-수집-방법의-차이">국내 데이터 수집 방법과 해외 데이터 수집 방법의 차이</h2>
<h3 id="국내-데이터-수집-방법">국내 데이터 수집 방법</h3>
<ol>
<li>팀원들(5명)이 각자의 로컬에서 자바 파일을 돌려서 100만 건의 국내 데이터 수집</li>
<li>Filezilla를 이용해 500만 건의 데이터를 EC2로 옮김</li>
</ol>
<p>⇒ 많은 시간이 소요되고 비효율적인 방법이라 판단하여 해외 데이터는 실제 데이터를 보내는 로그스태시 서버(데이터 파이프라인 서버)에서 수집하였습니다.</p>
<h3 id="해외-데이터-수집-방법">해외 데이터 수집 방법</h3>
<ol>
<li>자바를 실행하는데 필요한 라이브러리 설치
<img src="https://velog.velcdn.com/images/ariul-dev/post/2a390d7a-a43b-4726-a1e7-7def9a01d4ac/image.png" alt=""></li>
<li>데이터를 얼마만큼 받을지 숫자 설정 후, 자바 파일을 최대 5개씩 실행
<img src="https://velog.velcdn.com/images/ariul-dev/post/83192fbc-7719-432c-b264-73dc7099755f/image.png" alt=""></li>
<li>7,500만 건의 해외 데이터 수집 완료</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[Elasticsearch GC Overhead 문제로 사용자 정의 사전 적용 실패]]></title>
            <link>https://velog.io/@ariul-dev/%EC%82%AC%EC%9A%A9%EC%9E%90-%EC%A0%95%EC%9D%98-%EC%82%AC%EC%A0%84-%EC%A0%81%EC%9A%A9-%EC%8B%A4%ED%8C%A8</link>
            <guid>https://velog.io/@ariul-dev/%EC%82%AC%EC%9A%A9%EC%9E%90-%EC%A0%95%EC%9D%98-%EC%82%AC%EC%A0%84-%EC%A0%81%EC%9A%A9-%EC%8B%A4%ED%8C%A8</guid>
            <pubDate>Mon, 17 Oct 2022 02:09:40 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>6주 동안 실전 프로젝트를 진행하면서 학습한 내용을 기록하고, 팀의 리더로서 프로젝트 매니징 경험을 기록하는 시리즈입니다. </p>
</blockquote>
<hr>
<h2 id="요구-사항">요구 사항</h2>
<p><strong>한국특허정보원에서 개발한 언어모델 KorPatELECTRA 사용자 정의 사전을 적용해야 한다.</strong></p>
<ol>
<li>서버 구축</li>
</ol>
<p>1) EC2 인스턴스 생성 </p>
<table>
<thead>
<tr>
<th align="center">인스턴스 크기</th>
<th align="center">vCPU</th>
<th align="center">메모리(GiB)</th>
</tr>
</thead>
<tbody><tr>
<td align="center">t2.xlarge</td>
<td align="center">4</td>
<td align="center">16</td>
</tr>
</tbody></table>
<p>2) 엘라스틱서치의 힙메모리 설정은 전체 메모리의 50%를 넘게 되면 메모리 오버헤드로 인해 실행이 되지 않는 것을 확인했습니다. 따라서 엘라스틱서치의 힙메모리는 다음과 같이 정하였습니다.</p>
<ul>
<li>Elasticsearch: 8GB, Kibana(키바나)-1.4GB</li>
</ul>
<p>3) 노드 역할별 분리</p>
<ul>
<li>데이터의 무결성 확보와 검색 속도 성능 개선을 위해 노드를 마스터노드 1개와 데이터 노드 2개로 분리하였습니다.</li>
</ul>
<p>4) KorPatELECTRA 사용자 정의 사전을 적용하기 위해 노드별로 pat_dic_v3.txt파일을 저장했습니다
<img src="https://velog.velcdn.com/images/ariul-dev/post/162ccc22-217b-41b7-9532-58b9c37f867a/image.png" alt=""></p>
<hr>
<h2 id="문제-상황">문제 상황</h2>
<p>로컬에서는 사용자 정의 사전을 적용하여도 인덱스 생성에 문제가 없었습니다. 그래서 사용자 정의 사전을 적용하여 테스트를 진행했는데, 서비스 배포용 EC2 서버에서는 인덱스 생성시 메모리의 오버헤드 문제가 발생하였기 때문에 기존 메모리 설정을 조정해야 했습니다.
현재 Elasticsearch의 사용자 계정인 patent의 limits.conf 설정은 다음과 같습니다.
<img src="https://velog.velcdn.com/images/ariul-dev/post/b1e472c3-6d55-400a-8250-4cadd87e66bd/image.png" alt=""></p>
<hr>
<h2 id="선택지">선택지</h2>
<h3 id="1안">1안</h3>
<blockquote>
<p>인덱싱을 담당하는 마스터 노드의 힙메모리 설정을 높인다.</p>
</blockquote>
<ul>
<li><p>EC2 xlarge 인스턴스의 메모리는 16GiB</p>
</li>
<li><p>기존) 마스터노드- 1GB , 데이터노드1- 3GB, 데이터노드2- 3GB 
→ GC Overhead → shard의 배치가 false가 된다. unsigned node에 배치가 실패한 샤드들이 생김</p>
<p>인덱스 설정 리퀘스트 결과: <img src="https://velog.velcdn.com/images/ariul-dev/post/3d2248fd-fe32-44bc-9921-eafa59f8768a/image.png" alt="인덱스 설정 리퀘스트 결과"></p>
</li>
<li><p>변경 1) 마스터노드- 2GB, 데이터노드1,2- 3GB → 같은 문제로 실패하였습니다</p>
</li>
<li><p>변경 2) 마스터노드- 4GB, 데이터노드1,2- 2GB → 같은 문제로 실패하였습니다.</p>
<h3 id="2안">2안</h3>
<blockquote>
<p>레플리카 샤드의 수를 0으로 인덱스를 생성한 뒤 인덱스 설정을 1로 변경한다. </p>
</blockquote>
</li>
</ul>
<p>→ 한번에 들어가는 프로세스를 줄이기 위한 목적.</p>
<ul>
<li><p>마스터노드의 힙메모리 설정 최대치인 4GB인 상태에서 프라이머리 샤드 값만 3으로 해서 인덱스를 생성합니다.
<img src="https://velog.velcdn.com/images/ariul-dev/post/d60017c6-e11d-4737-a116-63802d476ae3/image.png" alt="생성시 프라이머리 샤드가 만들어졌지만 배치가 하나의 노드로 몰린다">
→ 생성시 프라이머리 샤드가 만들어졌지만 배치가 하나의 노드로 몰립니다.
→ 레플리카 샤드의 설정을 1로 재설정합니다.</p>
<p>  Put/korea-patents
  {</p>
<pre><code>&quot;settings&quot;: {
  &quot;index&quot;: {
    &quot;number_of_replicas&quot;: 1
  }
  }</code></pre><p>  }</p>
</li>
</ul>
<p> → 1안과 같은 문제로 실패하였습니다.</p>
<h3 id="3안">3안</h3>
<blockquote>
<p>korea-patents 인덱스만 프라이머리 샤드의 수를 1개로 줄여서 생성한다.</p>
</blockquote>
<ul>
<li><p>2안과 같은 에러로 인해 실패하였습니다.</p>
<h3 id="4안">4안</h3>
<blockquote>
<p>EC2 인스턴스의 메모리 용량을 업그레이드</p>
</blockquote>
</li>
<li><p>프로젝트 마감기한이 임박하여 테스트를 하지 못했습니다.</p>
</li>
</ul>
<hr>
<h2 id="의견-조율">의견 조율</h2>
<ul>
<li>1안 - 실패</li>
<li>2안 - 실패</li>
<li>3안<ul>
<li>샤드의 수가 늘어날수록 검색 소요 시간 성능이 늘어나는 것을 확인했지만 리소스의 한계로 검색 정확도 성능의 개선을 못하는 상황</li>
<li>프라이머리 샤드의 수를 1로 줄이고 레플리카를 1개로 설정하여 인덱스 생성</li>
<li>pat_dic_v3.txt 사전 설정을 뒤로 미루고 기존에 작성한 인덱스 매핑 정의와 쿼리를 개선하여 정확도를 더 높이는 방법</li>
</ul>
</li>
<li>4안<ul>
<li>테스트를 하기에 시간이 부족한 상황</li>
</ul>
</li>
</ul>
<h2 id="의견-결정">의견 결정</h2>
<ul>
<li><strong>인덱스 매핑 정의와 쿼리 개선을 통한 검색 정확도 향상</strong>으로 선택</li>
</ul>
<p>→ 테스트 완료 : 사용자 정의 사전을 적용하지 않은 상태에서도 적용한 것과 동일한 검색 결과 정확도를 얻을 수 있었기 때문에 사용자 정의 사전을 적용하지 않기로 결정하였습니다. </p>
<p>테스트 과정 확인👉 <a href="https://velog.io/@ariul-dev/%EC%98%A4%ED%83%80-%EA%B5%90%EC%A0%95-%EA%B8%B0%EB%8A%A5-%EC%A0%81%EC%9A%A9-%EC%9D%B4%ED%9B%84-%EA%B2%80%EC%83%89-%EA%B2%B0%EA%B3%BC-%EC%A0%95%ED%99%95%EB%8F%84-%ED%96%A5%EC%83%81%EC%9D%84-%EC%9C%84%ED%95%9C-%EC%9D%B8%EB%8D%B1%EC%8A%A4-%EB%A7%A4%ED%95%91-%EB%B3%80%EA%B2%BD-%EA%B3%BC%EC%A0%95-bidk0fjz">오타 교정 기능 적용 이후 검색 결과 정확도 향상을 위한 인덱스 매핑 변경 과정-②</a></p>
<ul>
<li>추후 인스턴스 업그레이드를 통해 사용자 정의 사전을 적용해 보기로 하였습니다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[오타 교정 기능 적용 이후 검색 결과 정확도 향상을 위한 인덱스 매핑 변경 과정-②]]></title>
            <link>https://velog.io/@ariul-dev/%EC%98%A4%ED%83%80-%EA%B5%90%EC%A0%95-%EA%B8%B0%EB%8A%A5-%EC%A0%81%EC%9A%A9-%EC%9D%B4%ED%9B%84-%EA%B2%80%EC%83%89-%EA%B2%B0%EA%B3%BC-%EC%A0%95%ED%99%95%EB%8F%84-%ED%96%A5%EC%83%81%EC%9D%84-%EC%9C%84%ED%95%9C-%EC%9D%B8%EB%8D%B1%EC%8A%A4-%EB%A7%A4%ED%95%91-%EB%B3%80%EA%B2%BD-%EA%B3%BC%EC%A0%95-bidk0fjz</link>
            <guid>https://velog.io/@ariul-dev/%EC%98%A4%ED%83%80-%EA%B5%90%EC%A0%95-%EA%B8%B0%EB%8A%A5-%EC%A0%81%EC%9A%A9-%EC%9D%B4%ED%9B%84-%EA%B2%80%EC%83%89-%EA%B2%B0%EA%B3%BC-%EC%A0%95%ED%99%95%EB%8F%84-%ED%96%A5%EC%83%81%EC%9D%84-%EC%9C%84%ED%95%9C-%EC%9D%B8%EB%8D%B1%EC%8A%A4-%EB%A7%A4%ED%95%91-%EB%B3%80%EA%B2%BD-%EA%B3%BC%EC%A0%95-bidk0fjz</guid>
            <pubDate>Mon, 10 Oct 2022 16:39:39 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>6주 동안 실전 프로젝트를 진행하면서 학습한 내용을 기록하고, 팀의 리더로서 프로젝트 매니징 경험을 기록하는 시리즈입니다. </p>
</blockquote>
<hr>
<h1 id="v3-nori--jamo--n-gram--사용자-사전">v3. Nori + Jamo + N-gram + 사용자 사전</h1>
<h2 id="인덱스-매핑-정의">인덱스 매핑 정의</h2>
<pre><code>PUT user-dic-ngram
{
  &quot;settings&quot;: {
    &quot;analysis&quot;: {
      &quot;char_filter&quot;: { // 1️⃣ 캐릭터 필터
        &quot;special_character_filter&quot;: {
          &quot;pattern&quot;: &quot;[\\p{Alpha}\\p{Digit}]&quot;,
          &quot;type&quot;: &quot;pattern_replace&quot;,
          &quot;replacement&quot;: &quot;&quot;
        },
        &quot;blank_filter&quot;: {
          &quot;pattern&quot;: &quot;[\\p{Blank}]&quot;,
          &quot;type&quot;: &quot;pattern_replace&quot;,
          &quot;replacement&quot;: &quot;&quot;
        }
      },
      &quot;tokenizer&quot;: { // 2️⃣ 토크나이저
        &quot;korean_nori_tokenizer&quot;: {
          &quot;type&quot;: &quot;nori_tokenizer&quot;,
          &quot;decompound_mode&quot;: &quot;mixed&quot;,
          &quot;user_dictionary&quot;: &quot;user_dic/pat_dic_v3.txt&quot;
        }
      }, 
      &quot;filter&quot;: { // 3️⃣ 토큰 필터
        &quot;nori_posfilter&quot;: {
          &quot;type&quot;: &quot;nori_part_of_speech&quot;,
          &quot;stoptags&quot;: [&quot;J&quot;,&quot;E&quot;,&quot;NNB&quot;,&quot;MAJ&quot;,&quot;MM&quot;,&quot;XSV&quot;,&quot;XSA&quot;,&quot;VCP&quot;,&quot;SE&quot;,&quot;XSN&quot;,&quot;VCN&quot;,&quot;SP&quot;,&quot;NA&quot;,&quot;UNA&quot;,&quot;VSV&quot;,&quot;XPN&quot;,&quot;IC&quot;,&quot;VV&quot;]
        },
        &quot;ngram2_filter&quot;: {
          &quot;type&quot;: &quot;ngram&quot;,
          &quot;min_gram&quot;: 3,
          &quot;max_gram&quot;: 3
        }
      },
      &quot;analyzer&quot;: { // 4️⃣ 애널라이저
        &quot;nori_analyzer&quot;: {
          &quot;type&quot;: &quot;custom&quot;,
          &quot;tokenizer&quot;: &quot;korean_nori_tokenizer&quot;,
          &quot;filter&quot; : [
            &quot;lowercase&quot;, 
            &quot;nori_posfilter&quot;
          ]
        },
        &quot;ngram_analyzer&quot; : {
          &quot;type&quot; : &quot;custom&quot;,
          &quot;char_filter&quot; : [
            &quot;blank_filter&quot;,
            &quot;special_character_filter&quot;
            ],
          &quot;tokenizer&quot; : &quot;standard&quot;,
          &quot;filter&quot; : [
            &quot;ngram2_filter&quot;
          ]
        },
        &quot;sum_ngram_analyzer&quot; : {
          &quot;type&quot; : &quot;custom&quot;,
          &quot;char_filter&quot; : [
            &quot;special_character_filter&quot;
            ],
          &quot;tokenizer&quot; : &quot;standard&quot;,
          &quot;filter&quot; : [
            &quot;ngram2_filter&quot;
          ]
        },
        &quot;jamo_index_analyzer&quot;: {
          &quot;type&quot;: &quot;custom&quot;,
          &quot;char_filter&quot;: [
            &quot;special_character_filter&quot;
          ],
          &quot;tokenizer&quot;: &quot;standard&quot;,
          &quot;filter&quot; : [
            &quot;jamo&quot;
          ]
        },
        &quot;jamo_search_analyzer&quot;: {
          &quot;type&quot;: &quot;custom&quot;,
          &quot;char_filter&quot;: [
            &quot;blank_filter&quot;,
            &quot;special_character_filter&quot;        
          ],
          &quot;tokenizer&quot;: &quot;standard&quot;,
          &quot;filter&quot;: [
            &quot;jamo&quot;
          ]
        },
        &quot;jamo_live_blank_search_analyzer&quot;: {
          &quot;type&quot;: &quot;custom&quot;,
          &quot;char_filter&quot;: [
            &quot;special_character_filter&quot;
            ],
          &quot;tokenizer&quot;: &quot;standard&quot;,
          &quot;filter&quot;: [
            &quot;jamo&quot;
          ]
        },
        &quot;number_analyzer&quot; : {
          &quot;type&quot; : &quot;pattern&quot;,
          &quot;pattern&quot; :&quot;[.]&quot;
        }
      }
    }
  },
  &quot;mappings&quot;: { // 5️⃣ 필드에 데이터 타입 매핑
    &quot;properties&quot;: {
      &quot;발명의명칭&quot;: {
        &quot;type&quot;: &quot;text&quot;,
        &quot;analyzer&quot;: &quot;jamo_index_analyzer&quot;,
        &quot;search_analyzer&quot;: &quot;jamo_search_analyzer&quot;,
        &quot;fields&quot;: {
          &quot;nori&quot; : {
            &quot;type&quot; : &quot;text&quot;,
            &quot;analyzer&quot; : &quot;nori_analyzer&quot;
          },
          &quot;ngram&quot; : {
            &quot;type&quot; : &quot;text&quot;,
            &quot;analyzer&quot; : &quot;ngram_analyzer&quot;
          },
          &quot;lblank&quot; : {
            &quot;type&quot; : &quot;text&quot;,
            &quot;analyzer&quot; : &quot;jamo_index_analyzer&quot;,
            &quot;search_analyzer&quot;: &quot;jamo_live_blank_search_analyzer&quot;
          }
        }
      },
      &quot;요약&quot;: {
        &quot;type&quot;: &quot;text&quot;,
        &quot;analyzer&quot;: &quot;jamo_index_analyzer&quot;,
        &quot;search_analyzer&quot; : &quot;jamo_search_analyzer&quot;,
        &quot;fields&quot;: {
          &quot;nori&quot; : {
            &quot;type&quot; : &quot;text&quot;,
            &quot;analyzer&quot; : &quot;nori_analyzer&quot;
          },
          &quot;ngram&quot;: {
            &quot;type&quot;: &quot;text&quot;,
            &quot;analyzer&quot;: &quot;sum_ngram_analyzer&quot;
          },
          &quot;lblank&quot; : {
            &quot;type&quot; : &quot;text&quot;,
            &quot;analyzer&quot; : &quot;jamo_index_analyzer&quot;,
            &quot;search_analyzer&quot; : &quot;jamo_live_blank_search_analyzer&quot;
          }
        }
      },    
      &quot;출원인&quot;: {
        &quot;type&quot;: &quot;text&quot;,
        &quot;analyzer&quot;: &quot;jamo_index_analyzer&quot;,
        &quot;search_analyzer&quot; : &quot;jamo_search_analyzer&quot;,
        &quot;fields&quot;: {
          &quot;nori&quot; : {
            &quot;type&quot; : &quot;text&quot;,
            &quot;analyzer&quot; : &quot;nori_analyzer&quot;
          },
          &quot;ngram&quot; : {
            &quot;type&quot; : &quot;text&quot;,
            &quot;analyzer&quot; : &quot;ngram_analyzer&quot;
          },
          &quot;lblank&quot; : {
            &quot;type&quot; : &quot;text&quot;,
            &quot;analyzer&quot; : &quot;jamo_index_analyzer&quot;,
            &quot;search_analyzer&quot; : &quot;jamo_live_blank_search_analyzer&quot;
          }
        }
      },
      &quot;CPC분류&quot;: {
        &quot;type&quot;: &quot;text&quot;    
      },
      &quot;IPC분류&quot;: {
        &quot;type&quot;: &quot;text&quot;    
      },
      &quot;event&quot;: {
        &quot;properties&quot;: {
          &quot;original&quot;: {
            &quot;type&quot;: &quot;text&quot;,
            &quot;fields&quot;: {
              &quot;keyword&quot;: {
                &quot;type&quot;: &quot;keyword&quot;,
                &quot;ignore_above&quot;: 256
              }
            }
          }
        }
      },
      &quot;log&quot;: {
        &quot;properties&quot;: {
          &quot;file&quot;: {
            &quot;properties&quot;: {
              &quot;path&quot;: {
                &quot;type&quot;: &quot;text&quot;,
                &quot;fields&quot;: {
                  &quot;keyword&quot;: {
                    &quot;type&quot;: &quot;keyword&quot;,
                    &quot;ignore_above&quot;: 256
                  }
                }
              }
            }
          }
        }
      },
      &quot;공개번호&quot;: {
        &quot;type&quot;: &quot;keyword&quot;      
      },
      &quot;공고번호&quot;: {
        &quot;type&quot;: &quot;keyword&quot;
      },
      &quot;등록번호&quot;: {
       &quot;type&quot;: &quot;keyword&quot;
      },
      &quot;법적상태&quot;: {
        &quot;type&quot;: &quot;keyword&quot; 
      },
      &quot;출원번호&quot;: {
        &quot;type&quot;: &quot;text&quot;,
        &quot;fields&quot;: {
          &quot;keyword&quot; : {
            &quot;type&quot; : &quot;keyword&quot;,
            &quot;ignore_above&quot;: &quot;256&quot;
          }
        } 
      },
      &quot;출원일자&quot;: {
        &quot;type&quot;: &quot;text&quot;,
        &quot;analyzer&quot;: &quot;number_analyzer&quot;,
        &quot;fields&quot;: {
          &quot;keyword&quot; : {
            &quot;type&quot; : &quot;keyword&quot;,
            &quot;ignore_above&quot; : 256
          }
        }
      }
    }
  }
}</code></pre><h2 id="1-character-filter">1. Character Filter</h2>
<h3 id="11-pattern-replace-character-filter">1.1. Pattern Replace Character Filter</h3>
<p>정규 표현식을 사용하여 해당 문자들을 특정 문자열로 대체합니다.</p>
<p><strong>pattern replace character filter</strong>가 제공하는 옵션은 다음과 같습니다.</p>
<ul>
<li>pattern : 자바 정규 표현식</li>
</ul>
<pre><code>| 표현식 | 의미 |
| --- | --- |
| \p{Alpha} | 문자 |
| \p{Digit} | 숫자 |
| \{Blank} | space 또는 tab |</code></pre><ul>
<li>replacement : 대체 문자열<ul>
<li>special_character_filter:  문자와 숫자를 대체</li>
<li>blank_filter: 공백을 대체</li>
</ul>
</li>
</ul>
<h2 id="2-tokenizer">2. Tokenizer</h2>
<h3 id="21-nori-tokenizer">2.1. Nori Tokenizer</h3>
<p><strong>nori_tokenizer</strong>가 제공하는 옵션은 다음과 같습니다. </p>
<ul>
<li><p><strong>user_dictionary</strong> : 사용자 정의 사전</p>
<p>  ⇒ v1에서는 특허 검색 서비스에서 사용자 정의 사전을 설정하기 어렵다고 판단하여 배제하였습니다. 하지만 지속적으로 서치한 결과, 한국특허정보원에서 개발한 언어모델을 통해 600만 건의 용어가 있는 사용자 사전을 얻을 수 있었고 v2부터는 이를 적용하였습니다.</p>
</li>
<li><p><strong>decompound_mode</strong> : 복합 명사를 토크나이저가 처리하는 방식을 결정</p>
<p>  ⇒ 분리된 복합 명사와 원본 데이터 모두 유지하기 위해 mixed로 설정하였습니다.</p>
</li>
</ul>
<h2 id="3-token-filter">3. Token Filter</h2>
<h3 id="31-nori_part_of_speech">3.1. nori_part_of_speech</h3>
<p><strong>nori_part_of_speech</strong> 토큰 필터를 이용해서 제거할 <strong>품사(POS - Part Of Speech) 코드입니다.</strong></p>
<p>⇒ “J&quot;,&quot;E&quot;,&quot;NNB&quot;,&quot;MAJ&quot;,&quot;MM&quot;,&quot;XSV&quot;,&quot;XSA&quot;,&quot;VCP&quot;,&quot;SE&quot;,&quot;XSN&quot;,&quot;VCN&quot;,&quot;SP&quot;,&quot;NA&quot;,&quot;UNA&quot;,&quot;VSV&quot;,&quot;XPN&quot;,&quot;IC&quot;,&quot;VV&quot;</p>
<h3 id="32-ngram">3.2. ngram</h3>
<p><strong>ngram token filter</strong>가 제공하는 옵션은 다음과 같습니다. </p>
<ul>
<li>min_gram: 그램의 최소 글자 수</li>
<li>max_gram: 그램의 최대 글자 수</li>
</ul>
<h2 id="4-analyzer">4. Analyzer</h2>
<h3 id="41-nori_analyzer">4.1. nori_analyzer</h3>
<p>[발명의명칭], [출원인], [요약] 필드를 멀티 필드로 두고 <strong>.nori 필드</strong>에 한글 형태소 분석기(Nori)를 적용하였습니다. </p>
<h3 id="42-ngram_analyzer">4.2. ngram_analyzer</h3>
<p>[발명의명칭], [출원인] 필드를 멀티 필드로 두고 <strong>.ngram 필드</strong>에 커스텀 애널라이저를 적용하였습니다. </p>
<p>이 커스텀 애널라이저는 캐릭터 필터를 통해 문자, 숫자, 공백을 제거하고 standard 토크나이저와 n-gram 필터를 사용합니다. </p>
<h3 id="43-sum_ngram_analyzer">4.3. sum_ngram_analyzer</h3>
<p>[요약] 필드를 멀티 필드로 두고 <strong>.ngram 필드</strong>에 커스텀 애널라이저를 적용하였습니다. </p>
<p>이 커스텀 애널라이저는 캐릭터 필터를 통해 문자, 숫자를 제거하고 standard 토크나이저와 n-gram 필터를 사용합니다. </p>
<h3 id="44-jamo_index_analyzer">4.4. jamo_index_analyzer</h3>
<p>[발명의명칭], [요약], [출원인] 필드를 멀티 필드로 두고 <strong>.lblank 필드</strong>에 커스텀 애널라이저를 적용하였습니다. </p>
<p>이 커스텀 애널라이저는 캐릭터 필터를 통해 문자, 숫자를 제거하고 standard 토크나이저와 jamo 필터를 사용합니다. </p>
<h3 id="45-jamo_search_analyzer">4.5. jamo_search_analyzer</h3>
<p>jamo_index_analyzer로 색인된 용어들을 잘 찾기 위해 검색 시에 search analyzer를 적용하였습니다.</p>
<p>이 커스텀 애널라이저는 캐릭터 필터를 통해 문자, 숫자, 공백을 제거하고 standard 토크나이저와 jamo 필터를 사용합니다. </p>
<h3 id="46-jamo_live_blank_search_analyzer">4.6. jamo_live_blank_search_analyzer</h3>
<p>jamo_index_analyzer로 색인된 용어들을 잘 찾기 위해 검색 시에 search analyzer를 적용하였습니다.</p>
<p>이 커스텀 애널라이저는 캐릭터 필터를 통해 문자, 숫자를 제거하고 standard 토크나이저와 jamo 필터를 사용합니다. </p>
<h3 id="47-number_analyzer">4.7. number_analyzer</h3>
<p>[출원일자] 필드의 데이터는 ‘2022.09.21’의 형태를 가집니다.</p>
<p>그 중에서 연도(2022)만 추출하기 위해  패턴 “[.]”을 기준으로 텍스트를 분리하는 패턴 애널라이저를 적용했습니다.</p>
<h2 id="5-필드에-데이터-타입-매핑">5. 필드에 데이터 타입 매핑</h2>
<ul>
<li>[출원번호] : text, keyword</li>
<li>[출원일자] : text, keyword</li>
<li>[발명의명칭] : text</li>
<li>[출원인] text</li>
<li>[IPC분류]  text</li>
<li>[CPC분류]  text</li>
<li>[공고번호]  keyword</li>
<li>[공개번호]  keyword</li>
<li>[등록번호]  keyword</li>
<li>[법적상태] keyword</li>
<li>[요약] text</li>
</ul>
<h2 id="개선점">개선점</h2>
<ul>
<li>v2와 달리, 오타가 있어도 원하는 결과를 얻을 수 있었습니다.<ul>
<li>검색한 키워드: <code>어일저장탱크</code></li>
<li>예상 반환 결과:<img src="https://velog.velcdn.com/images/ariul-dev/post/f3b0f654-3a43-4a8f-a93f-b04de48f5551/image.png" alt=""></li>
</ul>
</li>
</ul>
<pre><code>- 실제 반환 결과: 3 hits

    ```
    {
      &quot;took&quot;: 175,
      &quot;timed_out&quot;: false,
      &quot;_shards&quot;: {
        &quot;total&quot;: 1,
        &quot;successful&quot;: 1,
        &quot;skipped&quot;: 0,
        &quot;failed&quot;: 0
      },
      &quot;hits&quot;: {
        &quot;total&quot;: {
          &quot;value&quot;: 3,
          &quot;relation&quot;: &quot;eq&quot;
        },
        &quot;max_score&quot;: 25.401136,
        &quot;hits&quot;: [
          {
            &quot;_index&quot;: &quot;user-dic-plus-ngram&quot;,
            &quot;_id&quot;: &quot;TJa6l4MBM1ppetunmW-v&quot;,
            &quot;_score&quot;: 25.401136,
            &quot;_source&quot;: {
              &quot;요약&quot;: &quot;본 고안은 오일저장탱크를 갖춘 차량용 브레이크의 마스터실린더에 관한 것으로, 그 목적은 오일감지장치의 플로트가 오일저장탱크의 천정면에 접착되는 것을 방지하는 것이다. 본 고안에 따른 오일저장탱크를 갖춘 차량용 브레이크의 마스터실린더는 오일저장탱크(20) 내에 마련되는 플로트(31)의 상면에 다수개의 돌기(33)를 형성하여 오일의 점성 및 표면장력에 의해 탱크(20)의 천정면에 달라붙는 것을 방지하였다. 따라서 플로트(31)는 항상 오일의 액면상에 떠있게 되어 본 기능을 원활하게 수행하며, 이의 전체적인 신뢰성이 향상되는 이점이 있다.&quot;,
              &quot;발명의명칭&quot;: &quot;오일저장탱크를 갖춘 차량용 브레이크의 마스터실린더()&quot;
            }
          },
          {
            &quot;_index&quot;: &quot;user-dic-plus-ngram&quot;,
            &quot;_id&quot;: &quot;Kpa6l4MBM1ppetunq3W-&quot;,
            &quot;_score&quot;: 19.633049,
            &quot;_source&quot;: {
              &quot;요약&quot;: &quot;본 발명은 용기(1)와, 용기의 상부 일 측에 파이프에 연결 설치되어 오일이 유입되는 오일저장탱크(2)와, 상기 용기(1)의 다른 상부 일 측에 파이프에 연결 설치되며 용기내의 압력을 감압시키는 진공펌프(4)와, 상기 용기(1)의 하부 일 측에 파이프에 연결 설치되어 오존을 용기(1)내에 유입된 오일(7)에 용해시키도록 공급하는 오존발생장치(3)와, 상기 용기(1)내의 하부 다른 일 측에 설치된 배출구(5)와, 용기(1)내의 몸체에 중앙부에 설치된 관찰창(6)과, 용기(1)의 하부에 설치된 진동장치(8)로 구성된 저농도 오존을 함유하는 오일제제 제조장치 및 그 제법. 저농도 오존화 오일제제 제조장치. 저농도 오존화 오일제제 제법. 진공펌프. 오존발생장치. 진동장치.&quot;,
              &quot;발명의명칭&quot;: &quot;저농도 오존을 함유하는 오일제제 제조장치 및 그 제법(Production method and apparatus for ozonized oil)&quot;
            }
          },
          {
            &quot;_index&quot;: &quot;user-dic-plus-ngram&quot;,
            &quot;_id&quot;: &quot;IZa6l4MBM1ppetuncFuQ&quot;,
            &quot;_score&quot;: 18.078995,
            &quot;_source&quot;: {
              &quot;요약&quot;: &quot;본 발명은 음식물 쓰레기 처리장치에 관한 것으로서 그 기술적인 수단은, 본체부(1)의 상부 일측면에 쓰레기 투입구(7)가 설치되고, 상기 본체부(1)의 내측에 형성되는 몸체(13)의 저면에 스크류 컨베이어(11) (11´) (11˝)로 이루어진 분쇄수단(14)이 설치되며, 상기 분쇄수단(14)의 상측에 중공의 회전축(15)에 연결되는 다수의 패들(16)로서 구성되는 교반기(17)가 설치되고, 상기 회전축(15)에 다수의 에어홀(34)이 형성한다. 또한, 상기 몸체(13)의 측면 상, 하에 전동기(18) (19)를 각각 설치하여 그 상측의 전동기(18)를 교반기(17)에 체인(22) 연결하고, 상기 하측의 전동기(19)를 스크류 컨베이어(11) 결합되는 스프로킷(23)에 체인(24) 연결하며, 상기 스크류 컨베이어(11)와 그 일측의 스크류 컨베이어(11´)는 기어 (25) (26) 결합되고, 상기 스크류 컨베이어(11)와 그 타측의 스크류 컨베이어(11˝)는 체인(27) 연결되며, 상기 몸체(13)의 외 측면 하부에 오일 저장탱크(29)를 설치하고, 상기 오일저장탱크(29)의 외 측면 저부에 히터장치(30)를 설치하며, 상기 히터장치(30)의 일 측에 송풍기 (31)를 설치하여 회전축(15)에 형성되는 에어 홀(34)에 에어를 공급토록 연결하고, 상기 몸체(13)의 일측에 결로장치(32)를 설치하는 것을 요지로 한다.&quot;,
              &quot;발명의명칭&quot;: &quot;음식물 쓰레기 처리장치()&quot;
            }
          }
        ]
      }
    }
    ```

- “explain”: **true**

    ```
    &quot;max_score&quot;: 25.401136,
    ...
    &quot;_explanation&quot;: {
              &quot;value&quot;: 25.401136,
              &quot;description&quot;: &quot;sum of:&quot;,
              &quot;details&quot;: [
                {
                  &quot;value&quot;: 9.521341,
                  &quot;description&quot;: &quot;max of:&quot;,
                  &quot;details&quot;: [
                    {
                      &quot;value&quot;: 9.521341,
                      &quot;description&quot;: &quot;weight(요약.lblank:ㅇㅗㅇㅣㄹㅈㅓㅈㅏㅇㅌㅐㅇㅋㅡ in 2585) [PerFieldSimilarity], result of:&quot;, ...
                    }, ...
                {
                  &quot;value&quot;: 15.879795,
                  &quot;description&quot;: &quot;max of:&quot;,
                  &quot;details&quot;: [
                    {
                      &quot;value&quot;: 15.879795,
                      &quot;description&quot;: &quot;weight(Synonym(**발명의명칭.ngram:어일저 발명의명칭.ngram:일저장 발명의명칭.ngram:장탱크 발명의명칭.ngram:저장탱**) in 2585) [PerFieldSimilarity], result of:&quot;, ...
                    }, ...

    ```</code></pre><hr>
<h1 id="v4-nori--jamo--n-gram">v4. Nori + Jamo + N-gram</h1>
<ul>
<li><p>v4. 인덱스 매핑 정의</p>
<pre><code>  PUT no-user-dic-ngram
  {
    &quot;settings&quot;: {
      &quot;analysis&quot;: {
        &quot;char_filter&quot;: { // 1️⃣ 캐릭터 필터
          &quot;special_character_filter&quot;: {
            &quot;pattern&quot;: &quot;[\\p{Alpha}\\p{Digit}]&quot;,
            &quot;type&quot;: &quot;pattern_replace&quot;,
            &quot;replacement&quot;: &quot;&quot;
          },
          &quot;blank_filter&quot;: {
            &quot;pattern&quot;: &quot;[\\p{Blank}]&quot;,
            &quot;type&quot;: &quot;pattern_replace&quot;,
            &quot;replacement&quot;: &quot;&quot;
          }
        },
        &quot;tokenizer&quot;: { // 2️⃣ 토크나이저
          &quot;korean_nori_tokenizer&quot;: {
            &quot;type&quot;: &quot;nori_tokenizer&quot;,
            &quot;decompound_mode&quot;: &quot;mixed&quot;
          }
        }, 
        &quot;filter&quot;: { // 3️⃣ 토큰 필터
          &quot;nori_posfilter&quot;: {
            &quot;type&quot;: &quot;nori_part_of_speech&quot;,
            &quot;stoptags&quot;: [&quot;J&quot;,&quot;E&quot;,&quot;NNB&quot;,&quot;MAJ&quot;,&quot;MM&quot;,&quot;XSV&quot;,&quot;XSA&quot;,&quot;VCP&quot;,&quot;SE&quot;,&quot;XSN&quot;,&quot;VCN&quot;,&quot;SP&quot;,&quot;NA&quot;,&quot;UNA&quot;,&quot;VSV&quot;,&quot;XPN&quot;,&quot;IC&quot;,&quot;VV&quot;]
          },
          &quot;ngram2_filter&quot;: {
            &quot;type&quot;: &quot;ngram&quot;,
            &quot;min_gram&quot;: 3,
            &quot;max_gram&quot;: 3
          }
        },
        &quot;analyzer&quot;: { // 4️⃣ 애널라이저
          &quot;nori_analyzer&quot;: {
            &quot;type&quot;: &quot;custom&quot;,
            &quot;tokenizer&quot;: &quot;korean_nori_tokenizer&quot;,
            &quot;filter&quot; : [
              &quot;lowercase&quot;, 
              &quot;nori_posfilter&quot;
            ]
          },
          &quot;ngram_analyzer&quot; : {
            &quot;type&quot; : &quot;custom&quot;,
            &quot;char_filter&quot; : [
              &quot;blank_filter&quot;,
              &quot;special_character_filter&quot;
              ],
            &quot;tokenizer&quot; : &quot;standard&quot;,
            &quot;filter&quot; : [
              &quot;ngram2_filter&quot;
            ]
          },
          &quot;sum_ngram_analyzer&quot; : {
            &quot;type&quot; : &quot;custom&quot;,
            &quot;char_filter&quot; : [
              &quot;special_character_filter&quot;
              ],
            &quot;tokenizer&quot; : &quot;standard&quot;,
            &quot;filter&quot; : [
              &quot;ngram2_filter&quot;
            ]
          },
          &quot;jamo_index_analyzer&quot;: {
            &quot;type&quot;: &quot;custom&quot;,
            &quot;char_filter&quot;: [
              &quot;special_character_filter&quot;
            ],
            &quot;tokenizer&quot;: &quot;standard&quot;,
            &quot;filter&quot; : [
              &quot;jamo&quot;
            ]
          },
          &quot;jamo_search_analyzer&quot;: {
            &quot;type&quot;: &quot;custom&quot;,
            &quot;char_filter&quot;: [
              &quot;blank_filter&quot;,
              &quot;special_character_filter&quot;        
            ],
            &quot;tokenizer&quot;: &quot;standard&quot;,
            &quot;filter&quot;: [
              &quot;jamo&quot;
            ]
          },
          &quot;jamo_live_blank_search_analyzer&quot;: {
            &quot;type&quot;: &quot;custom&quot;,
            &quot;char_filter&quot;: [
              &quot;special_character_filter&quot;
              ],
            &quot;tokenizer&quot;: &quot;standard&quot;,
            &quot;filter&quot;: [
              &quot;jamo&quot;
            ]
          },
          &quot;number_analyzer&quot; : {
            &quot;type&quot; : &quot;pattern&quot;,
            &quot;pattern&quot; :&quot;[.]&quot;
          }
        }
      }
    },
    &quot;mappings&quot;: { // 5️⃣ 필드에 데이터 타입 매핑
      &quot;properties&quot;: {
        &quot;발명의명칭&quot;: {
          &quot;type&quot;: &quot;text&quot;,
          &quot;analyzer&quot;: &quot;jamo_index_analyzer&quot;,
          &quot;search_analyzer&quot;: &quot;jamo_search_analyzer&quot;,
          &quot;fields&quot;: {
            &quot;nori&quot; : {
              &quot;type&quot; : &quot;text&quot;,
              &quot;analyzer&quot; : &quot;nori_analyzer&quot;
            },
            &quot;ngram&quot; : {
              &quot;type&quot; : &quot;text&quot;,
              &quot;analyzer&quot; : &quot;ngram_analyzer&quot;
            },
            &quot;lblank&quot; : {
              &quot;type&quot; : &quot;text&quot;,
              &quot;analyzer&quot; : &quot;jamo_index_analyzer&quot;,
              &quot;search_analyzer&quot;: &quot;jamo_live_blank_search_analyzer&quot;
            }
          }
        },
        &quot;요약&quot;: {
          &quot;type&quot;: &quot;text&quot;,
          &quot;analyzer&quot;: &quot;jamo_index_analyzer&quot;,
          &quot;search_analyzer&quot; : &quot;jamo_search_analyzer&quot;,
          &quot;fields&quot;: {
            &quot;nori&quot; : {
              &quot;type&quot; : &quot;text&quot;,
              &quot;analyzer&quot; : &quot;nori_analyzer&quot;
            },
            &quot;ngram&quot;: {
              &quot;type&quot;: &quot;text&quot;,
              &quot;analyzer&quot;: &quot;sum_ngram_analyzer&quot;
            },
            &quot;lblank&quot; : {
              &quot;type&quot; : &quot;text&quot;,
              &quot;analyzer&quot; : &quot;jamo_index_analyzer&quot;,
              &quot;search_analyzer&quot; : &quot;jamo_live_blank_search_analyzer&quot;
            }
          }
        },    
        &quot;출원인&quot;: {
          &quot;type&quot;: &quot;text&quot;,
          &quot;analyzer&quot;: &quot;jamo_index_analyzer&quot;,
          &quot;search_analyzer&quot; : &quot;jamo_search_analyzer&quot;,
          &quot;fields&quot;: {
            &quot;nori&quot; : {
              &quot;type&quot; : &quot;text&quot;,
              &quot;analyzer&quot; : &quot;nori_analyzer&quot;
            },
            &quot;ngram&quot; : {
              &quot;type&quot; : &quot;text&quot;,
              &quot;analyzer&quot; : &quot;ngram_analyzer&quot;
            },
            &quot;lblank&quot; : {
              &quot;type&quot; : &quot;text&quot;,
              &quot;analyzer&quot; : &quot;jamo_index_analyzer&quot;,
              &quot;search_analyzer&quot; : &quot;jamo_live_blank_search_analyzer&quot;
            }
          }
        },
        &quot;CPC분류&quot;: {
          &quot;type&quot;: &quot;text&quot;    
        },
        &quot;IPC분류&quot;: {
          &quot;type&quot;: &quot;text&quot;    
        },
        &quot;event&quot;: {
          &quot;properties&quot;: {
            &quot;original&quot;: {
              &quot;type&quot;: &quot;text&quot;,
              &quot;fields&quot;: {
                &quot;keyword&quot;: {
                  &quot;type&quot;: &quot;keyword&quot;,
                  &quot;ignore_above&quot;: 256
                }
              }
            }
          }
        },
        &quot;log&quot;: {
          &quot;properties&quot;: {
            &quot;file&quot;: {
              &quot;properties&quot;: {
                &quot;path&quot;: {
                  &quot;type&quot;: &quot;text&quot;,
                  &quot;fields&quot;: {
                    &quot;keyword&quot;: {
                      &quot;type&quot;: &quot;keyword&quot;,
                      &quot;ignore_above&quot;: 256
                    }
                  }
                }
              }
            }
          }
        },
        &quot;공개번호&quot;: {
          &quot;type&quot;: &quot;keyword&quot;      
        },
        &quot;공고번호&quot;: {
          &quot;type&quot;: &quot;keyword&quot;
        },
        &quot;등록번호&quot;: {
         &quot;type&quot;: &quot;keyword&quot;
        },
        &quot;법적상태&quot;: {
          &quot;type&quot;: &quot;keyword&quot; 
        },
        &quot;출원번호&quot;: {
          &quot;type&quot;: &quot;text&quot;,
          &quot;fields&quot;: {
            &quot;keyword&quot; : {
              &quot;type&quot; : &quot;keyword&quot;,
              &quot;ignore_above&quot;: &quot;256&quot;
            }
          } 
        },
        &quot;출원일자&quot;: {
          &quot;type&quot;: &quot;text&quot;,
          &quot;analyzer&quot;: &quot;number_analyzer&quot;,
          &quot;fields&quot;: {
            &quot;keyword&quot; : {
              &quot;type&quot; : &quot;keyword&quot;,
              &quot;ignore_above&quot; : 256
            }
          }
        }
      }
    }
  }</code></pre></li>
</ul>
<h2 id="1-character-filter-1">1. Character Filter</h2>
<h3 id="11-pattern-replace-character-filter-1">1.1. Pattern Replace Character Filter</h3>
<p>정규 표현식을 사용하여 해당 문자들을 특정 문자열로 대체합니다.</p>
<p><strong>pattern replace character filter</strong>가 제공하는 옵션은 다음과 같습니다.</p>
<ul>
<li>pattern : 자바 정규 표현식</li>
</ul>
<pre><code>| 표현식 | 의미 |
| --- | --- |
| \p{Alpha} | 문자 |
| \p{Digit} | 숫자 |
| \{Blank} | space 또는 tab |</code></pre><ul>
<li>replacement : 대체 문자열<ul>
<li>special_character_filter:  문자와 숫자를 대체</li>
<li>blank_filter: 공백을 대체</li>
</ul>
</li>
</ul>
<h2 id="2-tokenizer-1">2. Tokenizer</h2>
<h3 id="21-nori-tokenizer-1">2.1. Nori Tokenizer</h3>
<p><strong>nori_tokenizer</strong>가 제공하는 옵션은 다음과 같습니다. </p>
<ul>
<li><p><strong>user_dictionary</strong> : 사용자 정의 사전</p>
<p>  ⇒ v1에서는 특허 검색 서비스에서 사용자 정의 사전을 설정하기 어렵다고 판단하여 배제하였습니다. 하지만 지속적으로 서치한 결과, 한국특허정보원에서 개발한 언어모델을 통해 600만 건의 용어가 있는 사용자 사전을 얻을 수 있었고 v2부터는 이를 적용하였습니다.</p>
<p>  ⇒ 로컬에서는 사용자 정의 사전을 적용하여도 인덱스 생성에 문제가 없었습니다. 그래서 v3까지 사용자 정의 사전을 적용하여 테스트를 진행했는데, 서비스 배포용 EC2 서버에서는 메모리 GC Overhead 문제로 인해 인덱스 생성에 실패하여 사용자 정의 사전을 적용하지 못했습니다. 이에 따라 <strong>v4에서는 사용자 정의 사전을 적용하지 않기로 결정</strong>하였습니다.</p>
<p>  ⇒ <a href="https://velog.io/@ariul-dev/%EC%82%AC%EC%9A%A9%EC%9E%90-%EC%A0%95%EC%9D%98-%EC%82%AC%EC%A0%84-%EC%A0%81%EC%9A%A9-%EC%8B%A4%ED%8C%A8">Elasticsearch GC Overhead 문제로 사용자 정의 사전 적용 실패</a> </p>
</li>
<li><p><strong>decompound_mode</strong> : 복합 명사를 토크나이저가 처리하는 방식을 결정</p>
<p>  ⇒ 분리된 복합 명사와 원본 데이터 모두 유지하기 위해 mixed로 설정하였습니다.</p>
</li>
</ul>
<h2 id="3-token-filter-1">3. Token Filter</h2>
<h3 id="31-nori_part_of_speech-1">3.1. nori_part_of_speech</h3>
<p><strong>nori_part_of_speech</strong> 토큰 필터를 이용해서 제거할 <strong>품사(POS - Part Of Speech) 코드입니다.</strong></p>
<p>⇒ “J&quot;,&quot;E&quot;,&quot;NNB&quot;,&quot;MAJ&quot;,&quot;MM&quot;,&quot;XSV&quot;,&quot;XSA&quot;,&quot;VCP&quot;,&quot;SE&quot;,&quot;XSN&quot;,&quot;VCN&quot;,&quot;SP&quot;,&quot;NA&quot;,&quot;UNA&quot;,&quot;VSV&quot;,&quot;XPN&quot;,&quot;IC&quot;,&quot;VV&quot;</p>
<h3 id="32-ngram-1">3.2. ngram</h3>
<p><strong>ngram token filter</strong>가 제공하는 옵션은 다음과 같습니다. </p>
<ul>
<li>min_gram: 그램의 최소 글자 수</li>
<li>max_gram: 그램의 최대 글자 수</li>
</ul>
<h2 id="4-analyzer-1">4. Analyzer</h2>
<h3 id="41-nori_analyzer-1">4.1. nori_analyzer</h3>
<p>[발명의명칭], [출원인], [요약] 필드를 멀티 필드로 두고 <strong>.nori 필드</strong>에 한글 형태소 분석기(Nori)를 적용하였습니다. </p>
<h3 id="42-ngram_analyzer-1">4.2. ngram_analyzer</h3>
<p>[발명의명칭], [출원인] 필드를 멀티 필드로 두고 <strong>.ngram 필드</strong>에 커스텀 애널라이저를 적용하였습니다. </p>
<p>이 커스텀 애널라이저는 캐릭터 필터를 통해 문자, 숫자, 공백을 제거하고 standard 토크나이저와 n-gram 필터를 사용합니다. </p>
<h3 id="43-sum_ngram_analyzer-1">4.3. sum_ngram_analyzer</h3>
<p>[요약] 필드를 멀티 필드로 두고 <strong>.ngram 필드</strong>에 커스텀 애널라이저를 적용하였습니다. </p>
<p>이 커스텀 애널라이저는 캐릭터 필터를 통해 문자, 숫자를 제거하고 standard 토크나이저와 n-gram 필터를 사용합니다. </p>
<h3 id="44-jamo_index_analyzer-1">4.4. jamo_index_analyzer</h3>
<p>[발명의명칭], [요약], [출원인] 필드를 멀티 필드로 두고 <strong>.lblank 필드</strong>에 커스텀 애널라이저를 적용하였습니다. </p>
<p>이 커스텀 애널라이저는 캐릭터 필터를 통해 문자, 숫자를 제거하고 standard 토크나이저와 jamo 필터를 사용합니다. </p>
<h3 id="45-jamo_search_analyzer-1">4.5. jamo_search_analyzer</h3>
<p>jamo_index_analyzer로 색인된 용어들을 잘 찾기 위해 검색 시에 search analyzer를 적용하였습니다.</p>
<p>이 커스텀 애널라이저는 캐릭터 필터를 통해 문자, 숫자, 공백을 제거하고 standard 토크나이저와 jamo 필터를 사용합니다. </p>
<h3 id="46-jamo_live_blank_search_analyzer-1">4.6. jamo_live_blank_search_analyzer</h3>
<p>jamo_index_analyzer로 색인된 용어들을 잘 찾기 위해 검색 시에 search analyzer를 적용하였습니다.</p>
<p>이 커스텀 애널라이저는 캐릭터 필터를 통해 문자, 숫자를 제거하고 standard 토크나이저와 jamo 필터를 사용합니다. </p>
<h3 id="47-number_analyzer-1">4.7. number_analyzer</h3>
<p>[출원일자] 필드의 데이터는 ‘2022.09.21’의 형태를 가집니다.</p>
<p>그 중에서 연도(2022)만 추출하기 위해  패턴 “[.]”을 기준으로 텍스트를 분리하는 패턴 애널라이저를 적용했습니다.</p>
<h2 id="5-필드에-데이터-타입-매핑-1">5. 필드에 데이터 타입 매핑</h2>
<ul>
<li>[출원번호] : text, keyword</li>
<li>[출원일자] : text, keyword</li>
<li>[발명의명칭] : text</li>
<li>[출원인] text</li>
<li>[IPC분류]  text</li>
<li>[CPC분류]  text</li>
<li>[공고번호]  keyword</li>
<li>[공개번호]  keyword</li>
<li>[등록번호]  keyword</li>
<li>[법적상태] keyword</li>
<li>[요약] text</li>
</ul>
<hr>
<h2 id="테스트">테스트</h2>
<blockquote>
<p>🤔 <strong>사용자 정의 사전이 없어도 v3 만큼의 검색 결과 정확도를 얻을 수 있는가?</strong></p>
</blockquote>
<h3 id="📌-테스트-환경">📌 테스트 환경</h3>
<p>⇒ <strong>동일한 데이터 25000 건</strong>에서 <strong>동일한 검색 키워드</strong>를 선정하여 <strong>동일한 쿼리</strong>를 날렸을 때의 결과를 비교합니다.</p>
<h3 id="📌-테스트-시나리오">📌 테스트 시나리오</h3>
<ol>
<li>원문 키워드 검색 시 검색 결과를 반환한다.</li>
<li>띄어쓰기 변화 시에도 검색 결과를 반환한다.</li>
<li>오타 교정 검색 결과를 반환한다.</li>
</ol>
<ul>
<li>원문 키워드 검색<ul>
<li>검색한 키워드: <code>오일저장탱크</code></li>
<li>예상 반환 결과:<img src="https://velog.velcdn.com/images/ariul-dev/post/616646ff-8a73-447f-89f2-c60b5b7e8552/image.png" alt=""></li>
</ul>
</li>
</ul>
<pre><code>- 실제 반환 결과: 6095 hits

    ```
    {
      &quot;took&quot;: 144,
      &quot;timed_out&quot;: false,
      &quot;_shards&quot;: {
        &quot;total&quot;: 1,
        &quot;successful&quot;: 1,
        &quot;skipped&quot;: 0,
        &quot;failed&quot;: 0
      },
      &quot;hits&quot;: {
        &quot;total&quot;: {
          &quot;value&quot;: 6095,
          &quot;relation&quot;: &quot;eq&quot;
        },
        &quot;max_score&quot;: 36.344376,
        &quot;hits&quot;: [
          {
            &quot;_index&quot;: &quot;user-dic-ngram&quot;,
            &quot;_id&quot;: &quot;hthRooMBQdjb45lRFuL1&quot;,
            &quot;_score&quot;: 36.344376,
            &quot;_source&quot;: {
              &quot;요약&quot;: &quot;본 고안은 **오일저장탱크**를 갖춘 차량용 브레이크의 마스터실린더에 관한 것으로, 그 목적은 오일감지장치의 플로트가 오일저장탱크의 천정면에 접착되는 것을 방지하는 것이다. 본 고안에 따른 오일저장탱크를 갖춘 차량용 브레이크의 마스터실린더는 오일저장탱크(20) 내에 마련되는 플로트(31)의 상면에 다수개의 돌기(33)를 형성하여 오일의 점성 및 표면장력에 의해 탱크(20)의 천정면에 달라붙는 것을 방지하였다. 따라서 플로트(31)는 항상 오일의 액면상에 떠있게 되어 본 기능을 원활하게 수행하며, 이의 전체적인 신뢰성이 향상되는 이점이 있다.&quot;,
              &quot;발명의명칭&quot;: &quot;**오일저장탱크**를 갖춘 차량용 브레이크의 마스터실린더()&quot;
            }
          },
          {
            &quot;_index&quot;: &quot;user-dic-ngram&quot;,
            &quot;_id&quot;: &quot;yNhQooMBQdjb45lRE4WZ&quot;,
            &quot;_score&quot;: 20.760996,
            &quot;_source&quot;: {
              &quot;요약&quot;: &quot;본 발명은 용기(1)와, 용기의 상부 일 측에 파이프에 연결 설치되어 오일이 유입되는 **오일저장탱크**(2)와, 상기 용기(1)의 다른 상부 일 측에 파이프에 연결 설치되며 용기내의 압력을 감압시키는 진공펌프(4)와, 상기 용기(1)의 하부 일 측에 파이프에 연결 설치되어 오존을 용기(1)내에 유입된 오일(7)에 용해시키도록 공급하는 오존발생장치(3)와, 상기 용기(1)내의 하부 다른 일 측에 설치된 배출구(5)와, 용기(1)내의 몸체에 중앙부에 설치된 관찰창(6)과, 용기(1)의 하부에 설치된 진동장치(8)로 구성된 저농도 오존을 함유하는 오일제제 제조장치 및 그 제법. 저농도 오존화 오일제제 제조장치. 저농도 오존화 오일제제 제법. 진공펌프. 오존발생장치. 진동장치.&quot;,
              &quot;발명의명칭&quot;: &quot;저농도 오존을 함유하는 오일제제 제조장치 및 그 제법(Production method and apparatus for ozonized oil)&quot;
            }
          },
          {
            &quot;_index&quot;: &quot;user-dic-ngram&quot;,
            &quot;_id&quot;: &quot;dthQooMBQdjb45lR5s0R&quot;,
            &quot;_score&quot;: 20.754087,
            &quot;_source&quot;: {
              &quot;요약&quot;: &quot;본 발명은 음식물 쓰레기 처리장치에 관한 것으로서 그 기술적인 수단은, 본체부(1)의 상부 일측면에 쓰레기 투입구(7)가 설치되고, 상기 본체부(1)의 내측에 형성되는 몸체(13)의 저면에 스크류 컨베이어(11) (11´) (11˝)로 이루어진 분쇄수단(14)이 설치되며, 상기 분쇄수단(14)의 상측에 중공의 회전축(15)에 연결되는 다수의 패들(16)로서 구성되는 교반기(17)가 설치되고, 상기 회전축(15)에 다수의 에어홀(34)이 형성한다. 또한, 상기 몸체(13)의 측면 상, 하에 전동기(18) (19)를 각각 설치하여 그 상측의 전동기(18)를 교반기(17)에 체인(22) 연결하고, 상기 하측의 전동기(19)를 스크류 컨베이어(11) 결합되는 스프로킷(23)에 체인(24) 연결하며, 상기 스크류 컨베이어(11)와 그 일측의 스크류 컨베이어(11´)는 기어 (25) (26) 결합되고, 상기 스크류 컨베이어(11)와 그 타측의 스크류 컨베이어(11˝)는 체인(27) 연결되며, 상기 몸체(13)의 외 측면 하부에 오일 저장탱크(29)를 설치하고, 상기 **오일저장탱크**(29)의 외 측면 저부에 히터장치(30)를 설치하며, 상기 히터장치(30)의 일 측에 송풍기 (31)를 설치하여 회전축(15)에 형성되는 에어 홀(34)에 에어를 공급토록 연결하고, 상기 몸체(13)의 일측에 결로장치(32)를 설치하는 것을 요지로 한다.&quot;,
              &quot;발명의명칭&quot;: &quot;음식물 쓰레기 처리장치()&quot;
            }
          },
          {
            &quot;_index&quot;: &quot;user-dic-ngram&quot;,
            &quot;_id&quot;: &quot;eNhQooMBQdjb45lRiKRq&quot;,
            &quot;_score&quot;: 20.164345,
            &quot;_source&quot;: {
              &quot;요약&quot;: &quot;본 발명은, 밸런스 샤프트가 오일 팬에 저장된 오일에 잠겨서 회전되는 것으로 인한 블로바이 증가 및 과다한 오일 배출을 방지할 수 있는 보조 오일 탱크를 가지는 자동차의 오일 팬에 관한 것이다. 오일 팬은, 엔진의 하부에 설치된 밸런스 샤프트와 오일 유면 사이에 일정 차이를 유지하기 위하여, 오일 팬 내에 저장된 오일의 유면을 감지하도록 오일 팬의 한 쪽 측부에 설치되는 오일 레벨 게이지와; 연결관을 통하여 오일 팬에 부족 오일을 공급하도록 오일을 수용하는 보조 오일 탱크와; 연결관에 설치되어, 보조 오일 탱크로부터 오일 팬으로 오일을 공급하도록 오일 레벨 게이지에 의하여 감지된 신호에 따라서 작동되는 솔레노이드 밸브와; 오일 레벨 게이지와 솔레노이드 밸브를 접속하는 피드백 라인을 포함한다.&quot;,
              &quot;발명의명칭&quot;: &quot;보조오일탱크를가지는자동차의오일팬(OIL FAN OF A VEHICLE HAVING AN AUXILIARY OIL TANK FOR PREVENTING INCREMENT OF BLOW-BY BY SUPPLYING OIL TO THE OIL FAN THROUGH THE AUXILIARY OIL TANK)&quot;
            }
          },
          {
            &quot;_index&quot;: &quot;user-dic-ngram&quot;,
            &quot;_id&quot;: &quot;X9hQooMBQdjb45lRiqeK&quot;,
            &quot;_score&quot;: 18.98133,
            &quot;_source&quot;: {
              &quot;요약&quot;: &quot;본 고안은 자동차의 엔진 오일 비산 탱크 구조에 관한 것으로서, 보다 상세하게는 비산 탱크와 메인 베어링 캡을 일체로 하여 동시에 조립 및 분해할 수 있도록 함으로써 작업성을 향상시킬 수 있는 자동차의 엔진 오일 비산 탱크 구조에 관한 것이다. 본 고안의 자동차의 엔진 오일 비산 탱크 구조는 커넥팅 로드(5)의 디퍼(3)에 의하여 비산되는 오일을 저장하는 비산 탱크(7)를 각각의 커넥팅 로드(5)의 하부에 배치시키고 각 비산 탱크(7)의 양측에 메인 베어링 캡(9)을 설치하되 이 메인 베어링 캡(9)과 비산 탱크(7)를 일체로 고정시키고, 상기 비산탱크(7)의 저면에 오일이 유입되는 장공(11)을 형성한 것을 특징으로 한다.&quot;,
              &quot;발명의명칭&quot;: &quot;자동차의 엔진 오일 비산 탱크 구조(TANK STRUCTURE FOR DISPERSING ENGINE OIL)&quot;
            }
          },
          {
            &quot;_index&quot;: &quot;user-dic-ngram&quot;,
            &quot;_id&quot;: &quot;ONhQooMBQdjb45lRp63K&quot;,
            &quot;_score&quot;: 17.853107,
            &quot;_source&quot;: {
              &quot;요약&quot;: &quot;본 고안은 주유소등 유류저장 시설에 있어서, 배관용 파이프의 관이음 구조에 관한 것으로 더 상세하게는 유류탱크와 배관용 파이프의 관이음 구조체에 관한 것으로, 본 고안의 목적은 가스회수관(1), 송유관(2) 등을 유류저장탱크(T)에 설치함에 있어 용접이음 방법이 아닌 나사식 관이음 구조체를 사용하므로서 이음부분에서 우려되는 부식발생을 최소화하면서 유류저장탱크(T)와 상기 가스회수관(1), 송유관(2)등의 접속을 용이하게 하는데 그 특징이 있는 것인데, 유류저장탱크(T)의 상부측에 관통구(H)를 형성하고 관이음구조체(400)의 커버체(410)의 원통상 몸체를 탱크(T)의 내측에서 외측으로 관통시키어 커버체(410)의 팔각플랜지(410f)가 유류저장탱크(T)의 내측으로 관통구(H)의 가장자리에 걸리도록 하는데 이때 커버체(410)의 8각 플랜지(410f)의 상부면에 밀착되면서 끼워진 하나의 하부측 오링(450&#39;)이 유류저장탱크(T)에 형성된 관통구(H)의 저면측 가장자리에 밀착되게 하고 또하나의 상부측오링(450)이 상기 관통구(H)의 표면측 가장자리에 밀착되게 한다. 이와같이 2개의 물결형 오링(450, 450&#39;)이 유류저장탱크(T)에 형성된 관통구(H)의 가장자리를 클램핑 하게 되므로 커버체(410)가 유류저장탱크(T)의 관통구(H)에 설치되는 것이며, 상기 물결형 오링(450, 450&#39;)의 두께가 일측은 두껍고 일측은 얇게 되어 있는 이유는 일반적으로 유류저장탱크(T) 가 라운딩된 원통상을 하고 있기 때문이다. 따라서 유류저장탱크(T)에 형성된 관통구(H)에 형성된 관통구(H)의 가장자리 형태에 따라 상기 물결형 오링(450, 450&#39;)의 형태가 달라질 것이다. 그리고 상부측 물결형 오링(450)의 상부측으로 너트형 조림링(430)을 구루빙 써클(430G) 쪽을 하향하여 커버체(410)의 몸통 외주면에 형성된 너트부(410N)에 치합시켜 조립하여 그루빙써클(430G)이 상부측 물결형오링(450)의 돌출링(450L)에 끼워지면서 조림링(430)이 상부측 물결형오링(450)을 밀착하면서 조이게 되면 커버체(410)가 유류저장탱크(T)의 관통구(H)에 설치되는 것이다. 이와같이 커버체(410)가 유류저장탱크(T)의 관통구(H)에 설치한후, 파이프소켓(420)의 송유관삽입구(422)와 가스회수관삽입구(421)에 각각 송유관(2)과 가스회수관(1)을 끼워 조립한 후 파이프소켓(420)을 플랜지(420f)가 상부측으로 하여 커버체(410)의 내측공간에 삽입하며 파이프소켓(420)의 플랜지(420f)가 커버체(410)의 상단부에 걸리게하여 설치하고, 너트형 커버캡(440)을 커버체(410) 상부측에서 커버체(410)의 너트부(410N)에 치합 조립하면 송유관(2)과 가스회수관(1)을 끼운 파이프소켓(420)이 커버체(410)와 너트형커버캡(440)에 의해 고정 조립되는 것임.&quot;,
              &quot;발명의명칭&quot;: &quot;유류저장 탱크에 있어서 관이음 구조체()&quot;
            }
          },
          {
            &quot;_index&quot;: &quot;user-dic-ngram&quot;,
            &quot;_id&quot;: &quot;bthQooMBQdjb45lRqq4P&quot;,
            &quot;_score&quot;: 16.867306,
            &quot;_source&quot;: {
              &quot;요약&quot;: &quot;본 고안은 전자렌지의 가습장치에 관한 것으로서 종래에는 조리물이 딱딱해지는 것을 방지하기 위한 별도의 기능을 가진 가습장치가 부설되어 있지 않고 분무기를 이용하여 조리시에 조리물에 수분을 공급하여 사용하였는데 이는 사용자에게 수작업을 요하기 때문에 불편한 문제점이 발생하였다. 따라서 본 고안은 조리실 상부에 위치한 저장탱크와, 상기 저장탱크의 일측에 위치하여 끝단에는 피스톤이 부설되고 구동모터의 구동으로 전후왕복 운동하는 랙크와, 상기 저장탱크의 타측에 위치한 노즐에 볼부재를 삽입 위치시켜 조리물에 적당량의 수분을 분무할 수 있도록 구성된 고안인 것이다.&quot;,
              &quot;발명의명칭&quot;: &quot;전자렌지의 가습장치()&quot;
            }
          },
          {
            &quot;_index&quot;: &quot;user-dic-ngram&quot;,
            &quot;_id&quot;: &quot;e9hQooMBQdjb45lRsrBb&quot;,
            &quot;_score&quot;: 15.895706,
            &quot;_source&quot;: {
              &quot;요약&quot;: &quot;본 발명은 브레이크 오일부족 방지장치에 관한 것으로, 오일을 공급하거나 저장하는 브레이크 리저버 탱크(30)와, 상기 브레이크 리저버 탱크(30)에 오일이 부족한 상태를 운전자가 파악할 수 있도록 하는 경고수단(40)과, 상기 브레이크 리저버 탱크(30)와 클러치 마스터 실린더(20)가 통할 수 있도록 연결시키는 호스1, 2와 연결되는 밸브(70)를 포함하여 구성되는 것을 특징으로 하며, 브레이크 오일이 부족한 것을 브레이크 리저버 탱크(30) 내의 접점에 의해 전기적 신호가 표시등(45)으로 인가되어 운전자가 파악을 할 수 있게 되어 브레이크 오일의 부족으로 인한 대형사고를 미연에 방지할 수 있는 효과를 가져온다.&quot;,
              &quot;발명의명칭&quot;: &quot;브레이크 오일부족 방지장치(Brake oil shirtage protection device)&quot;
            }
          },
          {
            &quot;_index&quot;: &quot;user-dic-ngram&quot;,
            &quot;_id&quot;: &quot;NdhQooMBQdjb45lRsa_3&quot;,
            &quot;_score&quot;: 15.780823,
            &quot;_source&quot;: {
              &quot;요약&quot;: &quot;본 발명은 엔진의 윤활 장치에 관한 것으로서, 실린더 헤드에 마련된 보조오일탱크(1)와, 오일펌프(2)로부터 상기 보조오일탱크(1)로 오일이 제공되는 방향의 유로를 개방하는 체크밸브(3)와, 엔진의 작동상태를 감지하는 운전감지수단과, 상기 운전감지수단이 제공하는 신호에 따라 상기 보조오일탱크(1)로부터 윤활부위로 향하는 유로(7)를 단속하는 유로단속수단으로 구성된 엔진의 윤활장치를 제공하여, 엔진의 시동초기에 오일펌프(2)로부터의 압송 오일이 각 윤활부에 도달하기까지 지연되는 시간동안 상기 보조오일탱크(1)의 오일이 우선적으로 제공되어 윤활작용을 수행하도록 함으로써, 시동초기에도 엔진 각 부위의 원활한 윤활작용을 확보할 수 있어 엔진의 내구성을 크게 향상시키도록 할 수 있다.&quot;,
              &quot;발명의명칭&quot;: &quot;엔진의 윤활구조(LUBRICATION STRUCTURE OF AN ENGINE)&quot;
            }
          },
          {
            &quot;_index&quot;: &quot;user-dic-ngram&quot;,
            &quot;_id&quot;: &quot;FthQooMBQdjb45lRz8Hp&quot;,
            &quot;_score&quot;: 15.675247,
            &quot;_source&quot;: {
              &quot;요약&quot;: &quot;본 발명은 정수기의 수위센서 오동작 방지방법에 관한 것으로서, 더욱 구체적으로는 정수기의 저장탱크에서 콕크를 통하여 정수를 빼낼 때 저장탱크 내부의 기압차에 의하여 발생되는 수위에 기인한 수위센서의 오동작을 감지하여 정상적으로 수위를 제어하는 정수기의 수위센서 오동작 방지방법에 관한 것이다. 본 발명의 정수기의 수위센서 오동작 방지방법은, 여과된 정수를 저장하며 외부와 밀폐된 저장탱크(2)의 수위를 측정하기 위하여 하부가 연통되고 저장탱크(2)의 측면에 위치하며 수위를 감지하기 위한 리드스위치(102,104.106,108)가 설치된 수위센서부(10)를 포함하는 정수기에 있어서, 수위센서부(10)를 통하여 미리 측정된 실제저장데이타(k)를 저장하고 현재측정데이타(k+1)를 지속적으로 측정하는 제1단계; 실제저장데이타(k)와 현재측정데이타(k+1)를 비교하는 제2단계; 비교결과 실제저장데이타(k)와 현재측정데이타(k+1)가 동일값을 가지면 정상상태로 인식하며 동일값이 아니면 소정시간동안 측정을 지연시키는 제3단계; 및 소정시간이 경과하는 동안에 실제저장데이타(k)와 현재측정데이타(k+1)가 동일값을 가지면 정상상태로 인식하고 현재측정데이타(k+1)를 새로운 실제저장데이타로 설정하며 동일값이 아니면 동일값에 도달할 때 까지 수위단계별로 보정을 수행하는 제4단계로 구성됨을 특징으로 한다.&quot;,
              &quot;발명의명칭&quot;: &quot;정수기의 수위센서 오동작 방지방법(FLOATING-SENSOR MALFUNCTION PREVENTION METHOD FOR WATER PURIFIER)&quot;
            }
          }
        ]
      }
    }
    ```</code></pre><ul>
<li><p>띄어쓰기 변화 검색</p>
<ul>
<li><p>검색한 키워드: <code>오일 저장 탱크</code></p>
</li>
<li><p>예상 반환 결과:<img src="https://velog.velcdn.com/images/ariul-dev/post/616646ff-8a73-447f-89f2-c60b5b7e8552/image.png" alt=""></p>
</li>
<li><p>실제 반환 결과: 6399 hits</p>
<pre><code>  {
    &quot;took&quot;: 57,
    &quot;timed_out&quot;: false,
    &quot;_shards&quot;: {
      &quot;total&quot;: 1,
      &quot;successful&quot;: 1,
      &quot;skipped&quot;: 0,
      &quot;failed&quot;: 0
    },
    &quot;hits&quot;: {
      &quot;total&quot;: {
        &quot;value&quot;: 6399,
        &quot;relation&quot;: &quot;eq&quot;
      },
      &quot;max_score&quot;: 36.344376,
      &quot;hits&quot;: [
        {
          &quot;_index&quot;: &quot;user-dic-ngram&quot;,
          &quot;_id&quot;: &quot;hthRooMBQdjb45lRFuL1&quot;,
          &quot;_score&quot;: 36.344376,
          &quot;_source&quot;: {
            &quot;요약&quot;: &quot;본 고안은 **오일저장탱크**를 갖춘 차량용 브레이크의 마스터실린더에 관한 것으로, 그 목적은 오일감지장치의 플로트가 오일저장탱크의 천정면에 접착되는 것을 방지하는 것이다. 본 고안에 따른 오일저장탱크를 갖춘 차량용 브레이크의 마스터실린더는 오일저장탱크(20) 내에 마련되는 플로트(31)의 상면에 다수개의 돌기(33)를 형성하여 오일의 점성 및 표면장력에 의해 탱크(20)의 천정면에 달라붙는 것을 방지하였다. 따라서 플로트(31)는 항상 오일의 액면상에 떠있게 되어 본 기능을 원활하게 수행하며, 이의 전체적인 신뢰성이 향상되는 이점이 있다.&quot;,
            &quot;발명의명칭&quot;: &quot;**오일저장탱크**를 갖춘 차량용 브레이크의 마스터실린더()&quot;
          }
        },
        {
          &quot;_index&quot;: &quot;user-dic-ngram&quot;,
          &quot;_id&quot;: &quot;X9hQooMBQdjb45lRiqeK&quot;,
          &quot;_score&quot;: 36.26282,
          &quot;_source&quot;: {
            &quot;요약&quot;: &quot;본 고안은 자동차의 엔진 오일 비산 탱크 구조에 관한 것으로서, 보다 상세하게는 비산 탱크와 메인 베어링 캡을 일체로 하여 동시에 조립 및 분해할 수 있도록 함으로써 작업성을 향상시킬 수 있는 자동차의 엔진 오일 비산 탱크 구조에 관한 것이다. 본 고안의 자동차의 엔진 오일 비산 탱크 구조는 커넥팅 로드(5)의 디퍼(3)에 의하여 비산되는 오일을 저장하는 비산 탱크(7)를 각각의 커넥팅 로드(5)의 하부에 배치시키고 각 비산 탱크(7)의 양측에 메인 베어링 캡(9)을 설치하되 이 메인 베어링 캡(9)과 비산 탱크(7)를 일체로 고정시키고, 상기 비산탱크(7)의 저면에 오일이 유입되는 장공(11)을 형성한 것을 특징으로 한다.&quot;,
            &quot;발명의명칭&quot;: &quot;자동차의 엔진 오일 비산 탱크 구조(TANK STRUCTURE FOR DISPERSING ENGINE OIL)&quot;
          }
        },
        {
          &quot;_index&quot;: &quot;user-dic-ngram&quot;,
          &quot;_id&quot;: &quot;eNhQooMBQdjb45lRiKRq&quot;,
          &quot;_score&quot;: 30.079277,
          &quot;_source&quot;: {
            &quot;요약&quot;: &quot;본 발명은, 밸런스 샤프트가 오일 팬에 저장된 오일에 잠겨서 회전되는 것으로 인한 블로바이 증가 및 과다한 오일 배출을 방지할 수 있는 보조 오일 탱크를 가지는 자동차의 오일 팬에 관한 것이다. 오일 팬은, 엔진의 하부에 설치된 밸런스 샤프트와 오일 유면 사이에 일정 차이를 유지하기 위하여, 오일 팬 내에 저장된 오일의 유면을 감지하도록 오일 팬의 한 쪽 측부에 설치되는 오일 레벨 게이지와; 연결관을 통하여 오일 팬에 부족 오일을 공급하도록 오일을 수용하는 보조 오일 탱크와; 연결관에 설치되어, 보조 오일 탱크로부터 오일 팬으로 오일을 공급하도록 오일 레벨 게이지에 의하여 감지된 신호에 따라서 작동되는 솔레노이드 밸브와; 오일 레벨 게이지와 솔레노이드 밸브를 접속하는 피드백 라인을 포함한다.&quot;,
            &quot;발명의명칭&quot;: &quot;보조오일탱크를가지는자동차의오일팬(OIL FAN OF A VEHICLE HAVING AN AUXILIARY OIL TANK FOR PREVENTING INCREMENT OF BLOW-BY BY SUPPLYING OIL TO THE OIL FAN THROUGH THE AUXILIARY OIL TANK)&quot;
          }
        },
        {
          &quot;_index&quot;: &quot;user-dic-ngram&quot;,
          &quot;_id&quot;: &quot;A9hQooMBQdjb45lRy7_k&quot;,
          &quot;_score&quot;: 30.037743,
          &quot;_source&quot;: {
            &quot;요약&quot;: &quot;본 발명은 증기압 및 수분흡수성이 높은 용액을 저장하는 저장 탱크 및 밀봉 탱크에 관한 것으로, 더욱 상세히는 저장 탱크외에 밀봉 탱크 A와 B내에 수분흡수성이 높은 용액을 넣은 밀봉 탱크를 장치함으로서, 저장 탱크내의 압력이 증가할 경우 연결관(N-1,N-2)을 통하여 밀봉 탱크 A 및 B에 증기가 이송되고 다시 이송된 증기는 통기구(N-3,N-4)를 통하여 대기로 방출되며, 저장 탱크내의 압력이 감소할 경우 대기의 공기가 연결관(N-3,N-4)를 통해 밀봉 탱크 A, B를 거쳐 수분을 제거시킨 후 연결관(N-1,N-2)를 통하여 수분이 거의 함유되지 않은 공기가 저장 탱크로 연속적으로 이송됨으로서, 저장 탱크내의 일정한 압력을 유지하고 수분흡수성이 높은 용액을 안정하게 보관할 수 있는 저장 탱크 시스템에 관한 것이다. 또한 이때 운전압력 범위에 따라 딥파이프(Dip Pipe)의 길이를 조절할 수 있으며 (N-1,N-2), (N-3,N-4)는 운전압력에 따라 순차적으로 열려 탱크내의 압력을 유지시킬 수 있도록 되어 있다.&quot;,
            &quot;발명의명칭&quot;: &quot;증기압 및 수분흡수성이 높은 용액의 저장 시스템(A SOLUTION STORAGE SYSTEM FOR HIHG STEAM PRESSURE AND HYGROSCOPIC SOLUTION)&quot;
          }
        },
        {
          &quot;_index&quot;: &quot;user-dic-ngram&quot;,
          &quot;_id&quot;: &quot;uthQooMBQdjb45lRt7MR&quot;,
          &quot;_score&quot;: 26.775936,
          &quot;_source&quot;: {
            &quot;요약&quot;: &quot;본 고안은 차량의 파워 스티어링 오일부족 경고장치에 관한 것으로, 파워 스티어링 펌프(10), 리저버 탱크(20), 파워 스티어링 기어박스(40)가 구비된 파워 스티어링 시스템에 있어, 리저버 탱크(20)에 오일감지센서(70)를 부착하여 오일의 레벨을 상시 감지하도록 하고, 오일감지센서(70)를 E.C.U(80)의 입력단에 연결하여 감지신호를 인가함과 동시에 E.C.U(80)로부터 사전설정된 기준값과 현재의 감지된 측정값을 비교하도록 하며, 또한 미터 세트(90)의 일측에 파워 스티어링 오일 레벨을 표시할 수 있는 오일계(91)를 구비하고, 오일계(91)를 E.C.U(80)의 출력단에 연결하여 오일의 양을 확인할 수 있도록 하며, E.C.U(80)의 다른 출력단에는 경고수단(100)을 연결하여 오일부족시 경고할 수 있도록 한 것인 바, 오일부족시 이를 경고함과 동시에 운전자로 하여금 오일 레벨을 항시 적정상태로 보충, 유지하도록 할 수 있는 것은 물론 파워 스티어링 시스템의 성능을 최상을 유지할 수 있고, 또한 항시 파워 스티어링 오일의 양을 확인할 수 있어 스티어링이 시스템의 고장을 예방할 수 있도록 된 것이다.&quot;,
            &quot;발명의명칭&quot;: &quot;차량의 파워 스티어링 오일부족 경고장치()&quot;
          }
        },
        {
          &quot;_index&quot;: &quot;user-dic-ngram&quot;,
          &quot;_id&quot;: &quot;g9hQooMBQdjb45lR2sXT&quot;,
          &quot;_score&quot;: 26.18729,
          &quot;_source&quot;: {
            &quot;요약&quot;: &quot;본 고안은 오일 주입장비의 노즐에 관한 것으로, 탱크(100)내부의 공기를 빼내기 위한 진공밸브(20)가 설치된 진공라인(21)과, 오일을 주입하기 위한 주입밸브(30)가 설치된 주입라인(31)으로 구성되어 있는 오일 주입장비의 노즐(10)에 있어서, 상기 진공라인(21)과 상기 주입라인(31)이 서로 소정의 단차가 져있되, 상기 진공라인(21)이 상기 주입라인(31)에 비해 상대적으로 길이가 짧은 구조로 되어, 탱크에 오일을 주입하기 위한 노즐에 갖춰져 있는 진공라인과 주입라인이 서로 간섭되지 않게 되어 진공작업 및 주입작업은 물론 탑오프작업을 정확히 수행할 수 있게 되고, 또한 상기 진공라인에 오일이 묻지 않게 되어 진공펌프로 오일이 유입되는 것을 방지함으로써, 진공도를 항상 일정하게 유지할 수 있는 효과가 있다.&quot;,
            &quot;발명의명칭&quot;: &quot;오일 주입장비의 노즐()&quot;
          }
        },
        {
          &quot;_index&quot;: &quot;user-dic-ngram&quot;,
          &quot;_id&quot;: &quot;e9hQooMBQdjb45lRsrBb&quot;,
          &quot;_score&quot;: 25.00283,
          &quot;_source&quot;: {
            &quot;요약&quot;: &quot;본 발명은 브레이크 오일부족 방지장치에 관한 것으로, 오일을 공급하거나 저장하는 브레이크 리저버 탱크(30)와, 상기 브레이크 리저버 탱크(30)에 오일이 부족한 상태를 운전자가 파악할 수 있도록 하는 경고수단(40)과, 상기 브레이크 리저버 탱크(30)와 클러치 마스터 실린더(20)가 통할 수 있도록 연결시키는 호스1, 2와 연결되는 밸브(70)를 포함하여 구성되는 것을 특징으로 하며, 브레이크 오일이 부족한 것을 브레이크 리저버 탱크(30) 내의 접점에 의해 전기적 신호가 표시등(45)으로 인가되어 운전자가 파악을 할 수 있게 되어 브레이크 오일의 부족으로 인한 대형사고를 미연에 방지할 수 있는 효과를 가져온다.&quot;,
            &quot;발명의명칭&quot;: &quot;브레이크 오일부족 방지장치(Brake oil shirtage protection device)&quot;
          }
        },
        {
          &quot;_index&quot;: &quot;user-dic-ngram&quot;,
          &quot;_id&quot;: &quot;ldhQooMBQdjb45lRe6L9&quot;,
          &quot;_score&quot;: 24.656528,
          &quot;_source&quot;: {
            &quot;요약&quot;: &quot;본 고안은 샤프트의 선단부에 장착 회전되어 원심력을 발생하는 임펠러와 오일을 저장 공급하기 위한 오일러와 상기 샤프트의 회전 운동을 보조하는 베어링을 부착하여 상기 오일러로부터 공급되는 오일을 유입하기 위한 베어링 하우스등을 포함하여 이루어지는 원심 펌프의 베어링 오일 공급 구조에 관한 것으로, 내부의 기압을 조정하기 위한 공기 구멍을 내며, 압력에 따라 오일을 주입 또는 차단하기 위한 받침판을 하부에 부착하고, 내부의 대기압이 증가하면 압력에 의한 오일 누출을 제어하여 오일의 불필요한 유출을 방지하는 받침판과, 상기 받침판의 하부에 부착되어 압력에 따라 연동하여 수축 또는 팽창되는 스프링과, 상기 스프링을 하부에서 지지하는 지지봉과, 상기 스프링과 지지봉의 작동에 연동하여 상승 또는 하강되는 공기 주머니를 갖는 오일러를 구비하여 이루어지기 때문에 구조가 간단해지며 오일의 누유를 방지할 수 있을 뿐만 아니라 분해 조립이 용이하게 되기 때문에 오일 보충을 간단하게 실시할 수 있는 효과가 있다.&quot;,
            &quot;발명의명칭&quot;: &quot;원심펌프의 베어링 오일 공급구조()&quot;
          }
        },
        {
          &quot;_index&quot;: &quot;user-dic-ngram&quot;,
          &quot;_id&quot;: &quot;CthQooMBQdjb45lRiKQR&quot;,
          &quot;_score&quot;: 24.061008,
          &quot;_source&quot;: {
            &quot;요약&quot;: &quot;본 발명은 회전시 발생하는 오일 누출분을 보충하는 동압유체 축수의 오일 저장장치에 관한 것이다. 본 발명에 따른 동압유체 축수의 오일 저장장치는 모터의 구동력으로 회전하는 회전자부와, 회전자부에 형성되어 회전자부의 회전에 따른 압력변화에 오일이 공급되는 제 1그루브와, 제 1그루브의 양단에 위치하여 제 1그루브에서 오일의 증발 및 누출에 따라 오일이 공급되도록 하는 제 2그루브를 구비한다. 이러한 구성에 의하여, 본 발명의 동압유체 축수의 오일 저장장치는 오일 누설에 의해 발생하는 축수 수명을 연장시키고 소형화, 박형화될 수 있다.&quot;,
            &quot;발명의명칭&quot;: &quot;동압유체 축수의 오일 저장장치(OIL STORAGE APPARATUS OF A FLUID DYNAMIC BEARING FOR EXTENDING LIFE TIME OF THE BEARING BY FORMING FIRST AND SECOND GROOVES)&quot;
          }
        },
        {
          &quot;_index&quot;: &quot;user-dic-ngram&quot;,
          &quot;_id&quot;: &quot;nNhQooMBQdjb45lRwbfJ&quot;,
          &quot;_score&quot;: 23.593327,
          &quot;_source&quot;: {
            &quot;요약&quot;: &quot;차량에 사용되는 오일 스트레이너의 재질 및 제작공정을 변경하여 상기 오일 스트레이너의 제품단가를 낮추고 제품의 경량화를 도모하는 오일 스트레이너에 관한 것이다. 상기 차량의 오일 스트레이너는 오일이 유동하는 제1구멍의 양측면에 나사가 관통하는 제2구멍을 갖는 플랜지와, 상기 제1구멍에 연장되며 하단면이 개구된 내부 공간을 갖는 직육면체의 상부 하우징과, 상기 상부 하우징과 결합되며 상단면이 개구된 내부 공간과 하단면의 일부가 개구된 직육면체의 하부 하우징과, 상기 상부 하우징과 하부 하우징의 내부에 결합되는 내부 공간을 갖는 직육면체의 오일 여과망을 포함하여 구성한다. 상기 차량의 오일 스트레이너는 종래의 오일 스트레이너를 제작하는데 있어서 복잡한 공정을 개선함으로써 제품단가를 낮출 수 있으며 상기 오일 스트레이너의 무게를 낮추어 제품의 경량화를 도모할 수 있는 효과가 있다.&quot;,
            &quot;발명의명칭&quot;: &quot;차량의 오일 스트레이너()&quot;
          }
        }
      ]
    }
  }</code></pre></li>
</ul>
</li>
</ul>
<ul>
<li><p>오타 교정 검색</p>
<ul>
<li><p>검색한 키워드: <code>어일저장탱크</code></p>
</li>
<li><p>예상 반환 결과:<img src="https://velog.velcdn.com/images/ariul-dev/post/616646ff-8a73-447f-89f2-c60b5b7e8552/image.png" alt=""></p>
</li>
<li><p>실제 반환 결과: 5456 hits</p>
<pre><code>  {
    &quot;took&quot;: 30,
    &quot;timed_out&quot;: false,
    &quot;_shards&quot;: {
      &quot;total&quot;: 1,
      &quot;successful&quot;: 1,
      &quot;skipped&quot;: 0,
      &quot;failed&quot;: 0
    },
    &quot;hits&quot;: {
      &quot;total&quot;: {
        &quot;value&quot;: 5456,
        &quot;relation&quot;: &quot;eq&quot;
      },
      &quot;max_score&quot;: 29.355354,
      &quot;hits&quot;: [
        {
          &quot;_index&quot;: &quot;user-dic-ngram&quot;,
          &quot;_id&quot;: &quot;hthRooMBQdjb45lRFuL1&quot;,
          &quot;_score&quot;: 29.355354,
          &quot;_source&quot;: {
            &quot;요약&quot;: &quot;본 고안은 **오일저장탱크**를 갖춘 차량용 브레이크의 마스터실린더에 관한 것으로, 그 목적은 오일감지장치의 플로트가 오일저장탱크의 천정면에 접착되는 것을 방지하는 것이다. 본 고안에 따른 오일저장탱크를 갖춘 차량용 브레이크의 마스터실린더는 오일저장탱크(20) 내에 마련되는 플로트(31)의 상면에 다수개의 돌기(33)를 형성하여 오일의 점성 및 표면장력에 의해 탱크(20)의 천정면에 달라붙는 것을 방지하였다. 따라서 플로트(31)는 항상 오일의 액면상에 떠있게 되어 본 기능을 원활하게 수행하며, 이의 전체적인 신뢰성이 향상되는 이점이 있다.&quot;,
            &quot;발명의명칭&quot;: &quot;**오일저장탱크**를 갖춘 차량용 브레이크의 마스터실린더()&quot;
          }
        },
        {
          &quot;_index&quot;: &quot;user-dic-ngram&quot;,
          &quot;_id&quot;: &quot;yNhQooMBQdjb45lRE4WZ&quot;,
          &quot;_score&quot;: 19.633049,
          &quot;_source&quot;: {
            &quot;요약&quot;: &quot;본 발명은 용기(1)와, 용기의 상부 일 측에 파이프에 연결 설치되어 오일이 유입되는 **오일저장탱크**(2)와, 상기 용기(1)의 다른 상부 일 측에 파이프에 연결 설치되며 용기내의 압력을 감압시키는 진공펌프(4)와, 상기 용기(1)의 하부 일 측에 파이프에 연결 설치되어 오존을 용기(1)내에 유입된 오일(7)에 용해시키도록 공급하는 오존발생장치(3)와, 상기 용기(1)내의 하부 다른 일 측에 설치된 배출구(5)와, 용기(1)내의 몸체에 중앙부에 설치된 관찰창(6)과, 용기(1)의 하부에 설치된 진동장치(8)로 구성된 저농도 오존을 함유하는 오일제제 제조장치 및 그 제법. 저농도 오존화 오일제제 제조장치. 저농도 오존화 오일제제 제법. 진공펌프. 오존발생장치. 진동장치.&quot;,
            &quot;발명의명칭&quot;: &quot;저농도 오존을 함유하는 오일제제 제조장치 및 그 제법(Production method and apparatus for ozonized oil)&quot;
          }
        },
        {
          &quot;_index&quot;: &quot;user-dic-ngram&quot;,
          &quot;_id&quot;: &quot;dthQooMBQdjb45lR5s0R&quot;,
          &quot;_score&quot;: 18.078995,
          &quot;_source&quot;: {
            &quot;요약&quot;: &quot;본 발명은 음식물 쓰레기 처리장치에 관한 것으로서 그 기술적인 수단은, 본체부(1)의 상부 일측면에 쓰레기 투입구(7)가 설치되고, 상기 본체부(1)의 내측에 형성되는 몸체(13)의 저면에 스크류 컨베이어(11) (11´) (11˝)로 이루어진 분쇄수단(14)이 설치되며, 상기 분쇄수단(14)의 상측에 중공의 회전축(15)에 연결되는 다수의 패들(16)로서 구성되는 교반기(17)가 설치되고, 상기 회전축(15)에 다수의 에어홀(34)이 형성한다. 또한, 상기 몸체(13)의 측면 상, 하에 전동기(18) (19)를 각각 설치하여 그 상측의 전동기(18)를 교반기(17)에 체인(22) 연결하고, 상기 하측의 전동기(19)를 스크류 컨베이어(11) 결합되는 스프로킷(23)에 체인(24) 연결하며, 상기 스크류 컨베이어(11)와 그 일측의 스크류 컨베이어(11´)는 기어 (25) (26) 결합되고, 상기 스크류 컨베이어(11)와 그 타측의 스크류 컨베이어(11˝)는 체인(27) 연결되며, 상기 몸체(13)의 외 측면 하부에 오일 저장탱크(29)를 설치하고, 상기 **오일저장탱크**(29)의 외 측면 저부에 히터장치(30)를 설치하며, 상기 히터장치(30)의 일 측에 송풍기 (31)를 설치하여 회전축(15)에 형성되는 에어 홀(34)에 에어를 공급토록 연결하고, 상기 몸체(13)의 일측에 결로장치(32)를 설치하는 것을 요지로 한다.&quot;,
            &quot;발명의명칭&quot;: &quot;음식물 쓰레기 처리장치()&quot;
          }
        },
        {
          &quot;_index&quot;: &quot;user-dic-ngram&quot;,
          &quot;_id&quot;: &quot;ONhQooMBQdjb45lRp63K&quot;,
          &quot;_score&quot;: 15.053638,
          &quot;_source&quot;: {
            &quot;요약&quot;: &quot;본 고안은 주유소등 유류저장 시설에 있어서, 배관용 파이프의 관이음 구조에 관한 것으로 더 상세하게는 유류탱크와 배관용 파이프의 관이음 구조체에 관한 것으로, 본 고안의 목적은 가스회수관(1), 송유관(2) 등을 유류저장탱크(T)에 설치함에 있어 용접이음 방법이 아닌 나사식 관이음 구조체를 사용하므로서 이음부분에서 우려되는 부식발생을 최소화하면서 유류저장탱크(T)와 상기 가스회수관(1), 송유관(2)등의 접속을 용이하게 하는데 그 특징이 있는 것인데, 유류저장탱크(T)의 상부측에 관통구(H)를 형성하고 관이음구조체(400)의 커버체(410)의 원통상 몸체를 탱크(T)의 내측에서 외측으로 관통시키어 커버체(410)의 팔각플랜지(410f)가 유류저장탱크(T)의 내측으로 관통구(H)의 가장자리에 걸리도록 하는데 이때 커버체(410)의 8각 플랜지(410f)의 상부면에 밀착되면서 끼워진 하나의 하부측 오링(450&#39;)이 유류저장탱크(T)에 형성된 관통구(H)의 저면측 가장자리에 밀착되게 하고 또하나의 상부측오링(450)이 상기 관통구(H)의 표면측 가장자리에 밀착되게 한다. 이와같이 2개의 물결형 오링(450, 450&#39;)이 유류저장탱크(T)에 형성된 관통구(H)의 가장자리를 클램핑 하게 되므로 커버체(410)가 유류저장탱크(T)의 관통구(H)에 설치되는 것이며, 상기 물결형 오링(450, 450&#39;)의 두께가 일측은 두껍고 일측은 얇게 되어 있는 이유는 일반적으로 유류저장탱크(T) 가 라운딩된 원통상을 하고 있기 때문이다. 따라서 유류저장탱크(T)에 형성된 관통구(H)에 형성된 관통구(H)의 가장자리 형태에 따라 상기 물결형 오링(450, 450&#39;)의 형태가 달라질 것이다. 그리고 상부측 물결형 오링(450)의 상부측으로 너트형 조림링(430)을 구루빙 써클(430G) 쪽을 하향하여 커버체(410)의 몸통 외주면에 형성된 너트부(410N)에 치합시켜 조립하여 그루빙써클(430G)이 상부측 물결형오링(450)의 돌출링(450L)에 끼워지면서 조림링(430)이 상부측 물결형오링(450)을 밀착하면서 조이게 되면 커버체(410)가 유류저장탱크(T)의 관통구(H)에 설치되는 것이다. 이와같이 커버체(410)가 유류저장탱크(T)의 관통구(H)에 설치한후, 파이프소켓(420)의 송유관삽입구(422)와 가스회수관삽입구(421)에 각각 송유관(2)과 가스회수관(1)을 끼워 조립한 후 파이프소켓(420)을 플랜지(420f)가 상부측으로 하여 커버체(410)의 내측공간에 삽입하며 파이프소켓(420)의 플랜지(420f)가 커버체(410)의 상단부에 걸리게하여 설치하고, 너트형 커버캡(440)을 커버체(410) 상부측에서 커버체(410)의 너트부(410N)에 치합 조립하면 송유관(2)과 가스회수관(1)을 끼운 파이프소켓(420)이 커버체(410)와 너트형커버캡(440)에 의해 고정 조립되는 것임.&quot;,
            &quot;발명의명칭&quot;: &quot;유류저장 탱크에 있어서 관이음 구조체()&quot;
          }
        },
        {
          &quot;_index&quot;: &quot;user-dic-ngram&quot;,
          &quot;_id&quot;: &quot;V9hQooMBQdjb45lRd583&quot;,
          &quot;_score&quot;: 15.053638,
          &quot;_source&quot;: {
            &quot;요약&quot;: &quot;[청구범위에 기재된 발명이 속한 기술분야] 본 발명은 액화연료 저장탱크 내의 유입노즐에 관한 것으로, 저장탱크에서의 물성치가 다른 액화연료간의 혼합을 활성케하는 유입노즐에 관한 것이다. [발명이 해결하려고 하는 기술적 과제] 종래 형상의 노즐로서는 유압가스에 의한 난동효과가 적어 가스간의 혼합이 용이하지 않게 되고 롤-오버 현상 및 성층현상을 일으키게 되어 이때 야기되는 발생열량이 저장탱크의 설계압력이상으로 작용하는 문제점이 있음. [발명의 해결방법의 요지] 유입노즐의 출구를 2개로 나누어 상향노즐과 부가노즐의 중심축이 이루는 각도를 수평방향으로 엇각이 되도록 구성한 본 발명에 의해 해결됨. [발명의 중요한 용도] 탱크내부의 잔존가스에, 유입되는 새로운 가스와의 효율적인 혼합작용을 발생시켜 혼합불량으로 인한 각종 현상을 미리 방지할 수 있는 효과가 있음.&quot;,
            &quot;발명의명칭&quot;: &quot;액화연료 저장탱크 내의 유압노즐(DRAW IN NOZZLE IN LIQUID FUEL TANK)&quot;
          }
        },
        {
          &quot;_index&quot;: &quot;user-dic-ngram&quot;,
          &quot;_id&quot;: &quot;6dhQooMBQdjb45lRoKvU&quot;,
          &quot;_score&quot;: 15.053638,
          &quot;_source&quot;: {
            &quot;요약&quot;: &quot;본 발명은 그 내부에 채워지는 화공액체의 누수와 그 화공액체들로 인한 구조물 내부의 부식을 효율적으로 방지하면서도 그 내부에 채워지는 화공액체의 하중을 충분히 감당하는 화공액체용 저장탱크에 관한 것으로, 강도가 매우 높은 것으로 알려진 F.R.P와 화학적 안정성이 탁월한 것으로 알려진 폴리에틸렌수지를 복합적으로 접착시켜서 화학적인 안정성이 확보되어서 내부식성이 크게 향상되면서도 강도도 우수해지도록 하기 위하여, 그 기술을 바닥에 놓여지는 바닥판부(10)와, 상기 바닥판부에 그 하단부가 고정되어서 그 내부가 비는 통체의 형상으로 세워지는 F.R.P통체부(20)와, 상기 통체부의 상부를 덮는 상판부(30)로 구성되는 것에 있어서, 상기 F.R.P통체부(20)는 F.R.P로 제작되는 F.R.P통부(21)의 내벽면에 내벽폴리에틸렌시이트(22)를 일체로 접착시키며, 상기 바닥판부(10)의 상면에는 상면폴리에틸렌시이트(22)를 일체로 접착시키켜서 제작되는 것으로 구성한 것이다.&quot;,
            &quot;발명의명칭&quot;: &quot;화공액체용 저장탱크(LIQUID STORAGE TANK)&quot;
          }
        },
        {
          &quot;_index&quot;: &quot;user-dic-ngram&quot;,
          &quot;_id&quot;: &quot;P9hQooMBQdjb45lR79Dg&quot;,
          &quot;_score&quot;: 15.053638,
          &quot;_source&quot;: {
            &quot;요약&quot;: &quot;본 발명은 태양열 난방장치의 집열기로부터 태양열을 흡수한 열전달유체의 열을 저장하는 열저장탱크에서 효과적으로 열을 발열 시스템으로 방출하도록 하는 효과적으로 열을 저장하고 열저장탱크의 열교환 시스템 구조에 관한 것으로, 본 발명의 목적은 열저장탱크의 열교환 시스템 구조를 변경하여 열전달유체(L)와 물(W)사이의 열교환을 3단계로 나누어 단계적으로 열교환이 일어나도록 하므로서 열교환 능률을 배가하도록 하는데 있다. 본 발명에 따른 열교환시스템 구조를 갖는 열저장탱크는 태양열 난방장치의 열저장탱크에 있어서, 통 형태의 열저장탱크(2)내부를 2개의 경판(21,21&#39;)에 의하여 구획을 지어 1차열교환공간(S1), 2차열교환공간(S2), 3차열교환공간(S3),을 형성하도록 하고 물(W)이 흐르는 수로관부(200)와 열전달유체(L)가 흐르는 열전달유체 유입파이프(IP)와 열전달유체 유출파이프(OP)를 형성시키는데 수로관부(200)는 1차열교환공간(S1)과 급수원을 연결하는 냉수유입파이프(200C)와 2차열교환공간(S2)에 코일상으로 절곡되어 형성되고, 그 일측단부가 경판(21)을 관통하여 1차열교환공간(S1)의 상부측에 형성되도록 하고 타단부는 경판(21&#39;)을 관통하여 3차열교환공간(S3)의 하부측에 형성되도록 한 열교환파이프(200E), 그리고 방열시스템과 연결되어 열저장탱크(2)의 일측면을 관통하여 1차열교환공간(S1), 2차열교환공간(S2)을 차례로 거쳐 3차열교환공간의 상부측에 그 자유단부가 형성되도록 한 온수유출파이프(200H)로 구성되고, 열전달유체 유입파이프(IP)와 열전달유체 유출파이프(OP)는 각각 대향하여 그 자유단부가 2차열교환공간에 형성되도록 하고 각각의 타단부는 집열기에 연결되도록 한 것이다.&quot;,
            &quot;발명의명칭&quot;: &quot;태양열 난방장치에 있어 열저장탱크의 열교환시스템구조(HEAT EXCHANGE SYSTEM STRUCTURE)&quot;
          }
        },
        {
          &quot;_index&quot;: &quot;user-dic-ngram&quot;,
          &quot;_id&quot;: &quot;qdhQooMBQdjb45lRWZe-&quot;,
          &quot;_score&quot;: 15.053638,
          &quot;_source&quot;: {
            &quot;요약&quot;: &quot;본 고안은 급격한 열팽창 및 수축에 의한 피로 하중을 효과적으로 방지할 수 있는 태양열 온수기용 온수 저장 탱크에 관한 것으로, 온수 저장 탱크의 동체의 원주 방향으로 형성되는 적어도 하나 이상의 비이드부를 구비함으로써, 열팽창, 열수축에 따른 내압 및 응력 증가를 비이드의 변형 에너지화하여 피로에 의한 용접 부위 등의 손상 또는 파손을 효과적으로 방지함과 동시에, 팽창 탱크를 온수 저장탱크를 이루는 단열재 내부에 설치함으로써 팽창 탱크를 통한 열손실을 최소화 함과 동시에 태양열 온수기 현장 설치시의 번잡한 배관 작업을 경감시킴으로써 태양열 온수기 전체의 설치 비용을 절감되고, 또한 팽창 탱크가 배관상에 돌출되지 않음으로 인해 외관을 미려하게 할 수 있게 된다.&quot;,
            &quot;발명의명칭&quot;: &quot;태양열온수기용온수저장탱크()&quot;
          }
        },
        {
          &quot;_index&quot;: &quot;user-dic-ngram&quot;,
          &quot;_id&quot;: &quot;xNhQooMBQdjb45lRaZs_&quot;,
          &quot;_score&quot;: 15.053638,
          &quot;_source&quot;: {
            &quot;요약&quot;: &quot;본 고안은 철강 코일 탈지설비 또는 이와 유사한 설비에 사용되는 탈지용액을 보관하여 사용하는 탈지용액 저장탱크 내부의 탈지 슬러지를 제거하기 위해 사용되는 탈지 슬러지 제거장치가 부착된 탈지용액 저장탱크에 관한 것으로, 탈지용액 공급펌프와 탈지용액 회수관이 부착되고, 양측면에 맨홀이 설치된 탈지용액 저장탱크를 슬러지가 탈지용액 저장탱크 저부의 중심부에 모일 수 있도록 바닥면을 &amp;quot;V&amp;quot;자 형상으로 형성하고, 중앙에 슬러지 분리막을 설치하여 작업탱크와 클린탱크로 구분한후, 구동력을 전달하기 위한 모터와, 원통형의 파이프 상부를 절단하여 탈지 슬러지를 내부에 모을수 있게 형성하여 구성된 슬러지 이동로와, 상기 모터에 연결된 상태에서 상기 슬러지 이동로에 삽입되는 스크루축과, 상기 슬러지 이동로에 연결되어 이동된 슬러지를 외부로 배출하는 슬러지 배출관과, 상기 슬러지 배출관의 하부에 위치하여 배출되는 슬러지를 수용하는 슬러지박스로 구성된 탈지 슬러지 제거장치를 각각의 작업탱크와 클린탱크의 저면에 부착하여 구성되어, 탈지용액의 과도한 소모를 방지하고 작업인력의 낭비를 방지할 수 있는 효과가 있다.&quot;,
            &quot;발명의명칭&quot;: &quot;탈지 슬러지 제거장치가 부착된 탈지용액 저장탱크()&quot;
          }
        },
        {
          &quot;_index&quot;: &quot;user-dic-ngram&quot;,
          &quot;_id&quot;: &quot;0thQooMBQdjb45lR5csx&quot;,
          &quot;_score&quot;: 13.974718,
          &quot;_source&quot;: {
            &quot;요약&quot;: &quot;본 고안은 가습기에 관한 것으로서, 본체 케이스내에 살균 및 정수작용을 하는 필터부재를 내설하여 가습용수에 포함된 각종 불순물과 세균 등을 제거함으로써 사용자의 건강을 보호할 수 있는 살균·정수필터가 내장된 가습기를 제공함에 그 목적이 있다. 이를 위해 본 고안은 가습용수가 저장되는 물탱크와, 물탱크가 안착되는 본체 케이스와, 물탱크내로부터 유입된 가습용수가 저장되도록 본체 케이스의 일측에 형성된 수조를 구비하는 가습기에 있어서, 물탱크내의 가습용수가 살균 및 정수되어 상기 수조내로 유입되도록 상기 본체 케이스의 일측에 필터부재가 마련되어 구성된다.&quot;,
            &quot;발명의명칭&quot;: &quot;살균.정수필터가 내장된 가습기()&quot;
          }
        }
      ]
    }
  }</code></pre></li>
</ul>
</li>
</ul>
<h3 id="결론">결론</h3>
<p>사용자 정의 사전을 적용하지 않은 결과, 반환 되는 개수(hit)가 크게 증가하는 것을 알 수 있었습니다. <strong>개수 차이는 있지만, 사용자 정의 사전을 적용한 v3 만큼의 검색 결과 정확도를 얻을 수 있다고 판단하였고, v4를 서비스에 적용하기로 결정하였습니다.</strong></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[오타 교정 기능 적용 이후 검색 결과 정확도 향상을 위한 인덱스 매핑 변경 과정-①]]></title>
            <link>https://velog.io/@ariul-dev/%EC%98%A4%ED%83%80-%EA%B5%90%EC%A0%95-%EA%B8%B0%EB%8A%A5-%EC%A0%81%EC%9A%A9-%EC%9D%B4%ED%9B%84-%EA%B2%80%EC%83%89-%EA%B2%B0%EA%B3%BC-%EC%A0%95%ED%99%95%EB%8F%84-%ED%96%A5%EC%83%81%EC%9D%84-%EC%9C%84%ED%95%9C-%EC%9D%B8%EB%8D%B1%EC%8A%A4-%EB%A7%A4%ED%95%91-%EB%B3%80%EA%B2%BD-%EA%B3%BC%EC%A0%95-</link>
            <guid>https://velog.io/@ariul-dev/%EC%98%A4%ED%83%80-%EA%B5%90%EC%A0%95-%EA%B8%B0%EB%8A%A5-%EC%A0%81%EC%9A%A9-%EC%9D%B4%ED%9B%84-%EA%B2%80%EC%83%89-%EA%B2%B0%EA%B3%BC-%EC%A0%95%ED%99%95%EB%8F%84-%ED%96%A5%EC%83%81%EC%9D%84-%EC%9C%84%ED%95%9C-%EC%9D%B8%EB%8D%B1%EC%8A%A4-%EB%A7%A4%ED%95%91-%EB%B3%80%EA%B2%BD-%EA%B3%BC%EC%A0%95-</guid>
            <pubDate>Wed, 05 Oct 2022 16:59:16 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>6주 동안 실전 프로젝트를 진행하면서 학습한 내용을 기록하고, 팀의 리더로서 프로젝트 매니징 경험을 기록하는 시리즈입니다. </p>
</blockquote>
<hr>
<h1 id="오타-교정-기능-적용">오타 교정 기능 적용</h1>
<p>검색 서비스의 기본 요구 사항 중 하나는 ‘오타 교정’ 기능입니다. 심지어 초보자를 위한 특허 검색 서비스라면 ‘오타 교정’ 기능이 필수적이라 생각하여 기능을 추가하였습니다. </p>
<h2 id="문제-발생">문제 발생</h2>
<p>하지만 &#39;오타 교정&#39; 기능을 구현한 뒤로 검색 결과 정확도가 저하되거나 검색 결과가 누락되는 문제가 있었습니다. </p>
<h2 id="문제-원인">문제 원인</h2>
<ol>
<li>Nori 애널라이저에 fuzziness 적용</li>
<li>인덱스 텀과 쿼리 텀의 불일치</li>
</ol>
<h2 id="문제-해결">문제 해결</h2>
<ol>
<li>660만 개의 용어가 담긴 사용자 정의 사전 적용</li>
<li>필드별 색인, 검색 애널라이저 분리</li>
<li>Edge n-gram 애널라이저를 Ngram 애널라이저로 변경</li>
</ol>
<h2 id="v1-v2-v3-v4-한눈에-비교하기">v1, v2, v3, v4 한눈에 비교하기</h2>
<table>
<thead>
<tr>
<th></th>
<th>v1. Nori + Jamo 필터 +edge-Ngram 필터</th>
<th>v2. Nori, Jamo, Edge n-gram+ 사용자 사전</th>
<th>v3. Nori + Jamo + N-gram + 사용자 사전</th>
<th>v4. Nori + Jamo + N-gram</th>
</tr>
</thead>
<tbody><tr>
<td>storage size</td>
<td>56.87mb</td>
<td>65.47mb</td>
<td>70.9mb</td>
<td>69.1mb</td>
</tr>
<tr>
<td>추가  및 변경 사항</td>
<td></td>
<td>1) 필드별 색인 애널라이저 분리 2) 필드별 검색 애널라이저 분리 3) 사용자 정의 사전 추가</td>
<td>1) Edge n-gram 애널라이저를 Ngram 애널라이저로 변경</td>
<td>1) 사용자 정의 사전을 적용하지 않음</td>
</tr>
<tr>
<td>원문 키워드 검색 시 결과 반환</td>
<td>❌</td>
<td>⭕</td>
<td>⭕</td>
<td>⭕</td>
</tr>
<tr>
<td>띄어쓰기 변화 시 결과 반환</td>
<td>⭕</td>
<td>⭕</td>
<td>⭕</td>
<td>⭕</td>
</tr>
<tr>
<td>오타 교정 결과 반환</td>
<td>❌</td>
<td>❌ (결과 누락)</td>
<td>⭕</td>
<td>⭕</td>
</tr>
</tbody></table>
<p>다음은 사용자 정의 사전 적용 과정 및 4단계의 인덱스 정의 테스트 과정을 자세히 담은 내용입니다. </p>
<hr>
<h1 id="v1-nori--jamo-필터--edge-ngram-필터">v1. Nori + Jamo 필터 + edge-Ngram 필터</h1>
<h2 id="인덱스-매핑-정의">인덱스 매핑 정의</h2>
<pre><code>PUT nori-plus-jamo-edge-filters
{
  &quot;settings&quot;: {
    &quot;analysis&quot;: {
      &quot;char_filter&quot;: { // 1️⃣ 캐릭터 필터
        &quot;special_character_filter&quot;: {
          &quot;pattern&quot;: &quot;[\\p{Alpha}\\p{Digit}\\p{Blank}]&quot;,
          &quot;type&quot;: &quot;pattern_replace&quot;,
          &quot;replacement&quot;: &quot;&quot;
        }
      },
      &quot;tokenizer&quot;: { // 2️⃣ 토크나이저
        &quot;korean_nori_tokenizer&quot;: {
          &quot;type&quot;: &quot;nori_tokenizer&quot;,
          &quot;decompound_mode&quot;: &quot;mixed&quot;
        }
      },
      &quot;filter&quot;: { // 3️⃣ 토큰 필터
        &quot;nori_posfilter&quot;: {
          &quot;type&quot;: &quot;nori_part_of_speech&quot;,
          &quot;stoptags&quot;: [&quot;J&quot;,&quot;E&quot;,&quot;NNB&quot;,&quot;MAJ&quot;,&quot;MM&quot;,&quot;XSV&quot;,&quot;XSA&quot;,&quot;VCP&quot;,&quot;SE&quot;,&quot;XSN&quot;,&quot;VCN&quot;,&quot;SP&quot;,&quot;NA&quot;,&quot;UNA&quot;,&quot;VSV&quot;,&quot;XPN&quot;,&quot;IC&quot;,&quot;VV&quot;]
        },
        &quot;ngram2_filter&quot;: {
          &quot;type&quot;: &quot;edge_ngram&quot;,
          &quot;min_gram&quot;: 2,
          &quot;max_gram&quot;: 15
        }
      },
      &quot;analyzer&quot;: { // 4️⃣ 애널라이저
        &quot;nori_analyzer&quot;: {
          &quot;type&quot;: &quot;custom&quot;,
          &quot;tokenizer&quot;: &quot;korean_nori_tokenizer&quot;,
          &quot;filter&quot; : [
            &quot;lowercase&quot;, 
            &quot;nori_posfilter&quot;
          ]
        },
        &quot;jamo_index_analyzer&quot;: {
          &quot;type&quot;: &quot;custom&quot;,
          &quot;char_filter&quot;: [
            &quot;special_character_filter&quot;
          ],
          &quot;tokenizer&quot;: &quot;korean_nori_tokenizer&quot;,
          &quot;filter&quot;: [
            &quot;nori_posfilter&quot;,
            &quot;jamo&quot;,
            &quot;ngram2_filter&quot;
          ]
        },
        &quot;jamo_search_analyzer&quot;: {
          &quot;type&quot;: &quot;custom&quot;,
          &quot;char_filter&quot;: [
            &quot;special_character_filter&quot;
          ],
          &quot;tokenizer&quot;: &quot;standard&quot;,
          &quot;filter&quot;: [
            &quot;jamo&quot;
          ]
        },
        &quot;number_analyzer&quot; : {
          &quot;type&quot; : &quot;pattern&quot;,
          &quot;pattern&quot; :&quot;[.]&quot;
        }
      }
    }
  },
  &quot;mappings&quot;: { // 5️⃣ 필드에 데이터 타입 매핑
    &quot;properties&quot;: {
      &quot;발명의명칭&quot;: {
        &quot;type&quot;: &quot;text&quot;,
        &quot;analyzer&quot;: &quot;nori_analyzer&quot;,
        &quot;fields&quot;: {
          &quot;raw&quot;: {
            &quot;type&quot;: &quot;keyword&quot;,
            &quot;ignore_above&quot;: 256
          },
          &quot;spell&quot;: {
            &quot;type&quot;: &quot;text&quot;,
            &quot;analyzer&quot;: &quot;jamo_index_analyzer&quot;,
            &quot;search_analyzer&quot;: &quot;jamo_search_analyzer&quot;
          }
        }
      },
      &quot;요약&quot;: {
        &quot;type&quot;: &quot;text&quot;,
        &quot;analyzer&quot;: &quot;nori_analyzer&quot;,
        &quot;fields&quot;: {
          &quot;spell&quot;: {
            &quot;type&quot;: &quot;text&quot;,
            &quot;analyzer&quot;: &quot;jamo_index_analyzer&quot;,
            &quot;search_analyzer&quot;: &quot;jamo_search_analyzer&quot;
          }
        }
      },
      &quot;출원인&quot;: {
        &quot;type&quot;: &quot;text&quot;,
        &quot;analyzer&quot;: &quot;nori_analyzer&quot;,
        &quot;fields&quot;: {
          &quot;raw&quot;: {
            &quot;type&quot;: &quot;keyword&quot;,
            &quot;ignore_above&quot;: 256
          },
          &quot;spell&quot;: {
            &quot;type&quot;: &quot;text&quot;,
            &quot;analyzer&quot;: &quot;jamo_index_analyzer&quot;,
            &quot;search_analyzer&quot;: &quot;jamo_search_analyzer&quot;
          }
        }
      },
      &quot;CPC분류&quot;: {
        &quot;type&quot;: &quot;text&quot;    
      },
      &quot;IPC분류&quot;: {
        &quot;type&quot;: &quot;text&quot;    
      },
      &quot;event&quot;: {
        &quot;properties&quot;: {
          &quot;original&quot;: {
            &quot;type&quot;: &quot;text&quot;,
            &quot;fields&quot;: {
              &quot;keyword&quot;: {
                &quot;type&quot;: &quot;keyword&quot;,
                &quot;ignore_above&quot;: 256
              }
            }
          }
        }
      },
      &quot;log&quot;: {
        &quot;properties&quot;: {
          &quot;file&quot;: {
            &quot;properties&quot;: {
              &quot;path&quot;: {
                &quot;type&quot;: &quot;text&quot;,
                &quot;fields&quot;: {
                  &quot;keyword&quot;: {
                    &quot;type&quot;: &quot;keyword&quot;,
                    &quot;ignore_above&quot;: 256
                  }
                }
              }
            }
          }
        }
      },
      &quot;공개번호&quot;: {
        &quot;type&quot;: &quot;keyword&quot;      
      },
      &quot;공고번호&quot;: {
        &quot;type&quot;: &quot;keyword&quot;
      },
      &quot;등록번호&quot;: {
       &quot;type&quot;: &quot;keyword&quot;
      },
      &quot;법적상태&quot;: {
        &quot;type&quot;: &quot;keyword&quot; 
      },
      &quot;출원번호&quot;: {
        &quot;type&quot;: &quot;text&quot;,
        &quot;fields&quot;: {
          &quot;keyword&quot; : {
            &quot;type&quot; : &quot;keyword&quot;,
            &quot;ignore_above&quot;: &quot;256&quot;
          }
        } 
      },
      &quot;출원일자&quot;: {
        &quot;type&quot;: &quot;text&quot;,
        &quot;analyzer&quot;: &quot;number_analyzer&quot;,
        &quot;fields&quot;: {
          &quot;keyword&quot; : {
            &quot;type&quot; : &quot;keyword&quot;,
            &quot;ignore_above&quot; : 256
          }
        }
      }
    }
  }
}</code></pre><h2 id="1-character-filter">1. Character Filter</h2>
<h3 id="11-pattern-replace-character-filter">1.1. Pattern Replace Character Filter</h3>
<p>정규 표현식을 사용하여 해당 문자들을 특정 문자열로 대체합니다.</p>
<p><strong>pattern replace character filter</strong>가 제공하는 옵션은 다음과 같습니다.</p>
<ul>
<li>pattern : 자바 정규 표현식</li>
</ul>
<pre><code>| 표현식 | 의미 |
| --- | --- |
| \p{Alpha} | 문자 |
| \p{Digit} | 숫자 |
| \{Blank} | space 또는 tab |</code></pre><ul>
<li><p>replacement : 대체 문자열</p>
<p>  ⇒ 문자, 숫자, 공백이 사라지게 됩니다.</p>
</li>
</ul>
<h2 id="2-tokenizer">2. Tokenizer</h2>
<h3 id="21-nori-tokenizer">2.1. Nori Tokenizer</h3>
<p><strong>nori_tokenizer</strong>가 제공하는 옵션은 다음과 같습니다. </p>
<ul>
<li><p><strong>user_dictionary</strong> : 사용자 정의 사전</p>
<p>  ⇒ 특허 검색 서비스의 경우, 사용자 정의 사전은 설정하기 어렵다고 판단하여 배제하였습니다.</p>
</li>
<li><p><strong>decompound_mode</strong> : 복합 명사를 토크나이저가 처리하는 방식을 결정</p>
<p>  ⇒ 분리된 복합 명사와 원본 데이터 모두 유지하기 위해 mixed로 설정하였습니다.</p>
</li>
</ul>
<h2 id="3-token-filter">3. Token Filter</h2>
<h3 id="31-nori_part_of_speech">3.1. nori_part_of_speech</h3>
<p><strong>nori_part_of_speech</strong> 토큰 필터를 이용해서 제거할 <strong>품사(POS - Part Of Speech) 코드입니다.</strong></p>
<table>
<thead>
<tr>
<th>태그</th>
<th>설명</th>
<th>태그</th>
<th>설명</th>
<th>태그</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>E</td>
<td>어미</td>
<td>IC</td>
<td>감탄사</td>
<td>J</td>
<td>조사</td>
</tr>
<tr>
<td>MAJ</td>
<td>접속 부사</td>
<td>MM</td>
<td>한정사</td>
<td>NA</td>
<td>알 수 없음</td>
</tr>
<tr>
<td>NNB</td>
<td>의존명사</td>
<td>SE</td>
<td>줄임표</td>
<td>SP</td>
<td>공백</td>
</tr>
<tr>
<td>UNA</td>
<td>알 수 없음</td>
<td>VCN</td>
<td>부정 지정사</td>
<td>VCP</td>
<td>긍정 지정사</td>
</tr>
<tr>
<td>VSV</td>
<td>알 수 없음</td>
<td>XPN</td>
<td>접두사</td>
<td>XSA</td>
<td>형용사 파생 접미사</td>
</tr>
<tr>
<td>XSN</td>
<td>명사 파생 접미사</td>
<td>XSV</td>
<td>동사 파생 접미사</td>
<td>VV</td>
<td>동사</td>
</tr>
</tbody></table>
<h3 id="32-edge_ngram">3.2. edge_ngram</h3>
<p><strong>edge-ngram token filter</strong>가 제공하는 옵션은 다음과 같습니다. </p>
<ul>
<li>min_gram: 그램의 최소 글자 수</li>
<li>max_gram: 그램의 최대 글자 수</li>
</ul>
<h2 id="4-analyzer">4. Analyzer</h2>
<h3 id="41-nori_analyzer">4.1. nori_analyzer</h3>
<p>[발명의명칭], [출원인], [요약] 필드의 데이터에 한글 형태소 분석기(Nori)를 적용하였습니다. </p>
<h3 id="42-jamo_index_analyzer">4.2. jamo_index_analyzer</h3>
<p>[발명의명칭], [요약], [출원인] 필드를 멀티 필드로 두고 .spell 필드에 커스텀 애널라이저를 적용하였습니다. </p>
<p>이 커스텀 애널라이저는 캐릭터 필터를 통해 문자, 숫자, 공백을 제거하고 nori 토크나이저와 jamo, edge n-gram 필터를 사용합니다. </p>
<h3 id="43-jamo_search_analyzer">4.3. jamo_search_analyzer</h3>
<p>jamo_index_analyzer로 색인된 용어들을 잘 찾기 위해 검색 시에 search analyzer를 적용하였습니다.</p>
<p>이 커스텀 애널라이저는 캐릭터 필터를 통해 문자, 숫자, 공백을 제거하고 standard 토크나이저와 jamo 필터를 사용합니다. </p>
<h3 id="44-number_analyzer">4.4. number_analyzer</h3>
<p>[출원일자] 필드의 데이터는 ‘2022.09.21’의 형태를 가집니다.</p>
<p>그 중에서 연도(2022)만 추출하기 위해  패턴 “[.]”을 기준으로 텍스트를 분리하는 패턴 애널라이저를 적용했습니다.</p>
<h2 id="5-필드에-데이터-타입-매핑">5. 필드에 데이터 타입 매핑</h2>
<ul>
<li>[출원번호] : text, keyword</li>
<li>[출원일자] : text, keyword</li>
<li>[발명의명칭] : text, keyword</li>
<li>[출원인] text, keyword</li>
<li>[IPC분류]  text</li>
<li>[CPC분류]  text</li>
<li>[공고번호]  keyword</li>
<li>[공개번호]  keyword</li>
<li>[등록번호]  keyword</li>
<li>[법적상태] keyword</li>
<li>[요약] text</li>
</ul>
<h2 id="문제점">문제점</h2>
<ul>
<li><p>Nori가 품사를 잘못 정의하고 잘라내는 문제</p>
<ul>
<li><p>검색한 키워드: <code>오일저장탱크</code></p>
</li>
<li><p>예상 반환 결과: <img src="https://velog.velcdn.com/images/ariul-dev/post/dbab804f-214b-4620-8337-4b25b5ff113e/image.png" alt=""></p>
</li>
<li><p>실제 반환 결과: 검색 결과 없음</p>
<pre><code>  {
    &quot;took&quot;: 5,
    &quot;timed_out&quot;: false,
    &quot;_shards&quot;: {
      &quot;total&quot;: 1,
      &quot;successful&quot;: 1,
      &quot;skipped&quot;: 0,
      &quot;failed&quot;: 0
    },
    &quot;hits&quot;: {
      &quot;total&quot;: {
        &quot;value&quot;: 0,
        &quot;relation&quot;: &quot;eq&quot;
      },
      &quot;max_score&quot;: null,
      &quot;hits&quot;: []
    }
  }</code></pre></li>
<li><p>검색 결과가 없는 이유: Nori가 품사를 잘못 정의하여 <code>오일</code> 을 <code>오</code> 와 <code>일</code> 로 잘라내기 때문</p>
<p>  <img src="https://velog.velcdn.com/images/ariul-dev/post/4dc4b3b1-8fd7-477b-845a-6fc49b9441ab/image.png" alt=""></p>
</li>
</ul>
</li>
<li><p>인덱스텀과 쿼리텀이 일치하지 않는 문제</p>
<ul>
<li>jamo_index_analyzer로 만든 인덱스텀<ul>
<li><code>ㅇㅗ</code> , <code>ㅇㅣ</code> , <code>ㅇㅣㄹ</code></li>
</ul>
</li>
<li>jamo_search_analyzer로 만든 쿼리텀<ul>
<li><code>ㅇㅗㅇㅣㄹㅈㅓㅈㅏㅇㅌㅐㅇㅋㅡㄹㅡㄹ</code></li>
</ul>
</li>
</ul>
</li>
</ul>
<h2 id="해결-방법-및-대안">해결 방법 및 대안</h2>
<ul>
<li>Nori 사용하지 않고 jamo 필터와 edge-Ngram 필터로만 매핑 시도<ul>
<li>Nori가 품사를 잘못 정의하는 문제는 저희가 해결할 수 없는 문제라고 판단하여 Nori를 jamo 필터와 edge-Ngram 필터로만 매핑했습니다.</li>
<li>그 결과, storage size가 2배 이상 증가한다는 것을 확인하였습니다.<ul>
<li><code>storage size: 56.87mb → 133.64mb</code></li>
</ul>
</li>
</ul>
</li>
<li>Nori를 사용하지 않으면 POS 토큰 필터로 무수히 많은 불용어를 제거할 수 있는 이점을 취할 수 없었습니다.</li>
<li>Nori의 POS 토큰 필터의 효과를 얻음과 동시에 side effect를 줄이기 위해서는 사용자 정의 사전 사용이 필수적이라 판단하였습니다.</li>
<li>지속적으로 서치한 결과 한국특허정보원에서 개발한 언어모델 KorPatELECTRA를 찾을 수 있었고, 신청을 통해 사용 허가를 받은 후 사용자 정의 사전을 적용하였습니다. 👉 <a href="https://github.com/kipi-ai/korpatbert">kipi-ai/korpatbert</a>
<img src="https://velog.velcdn.com/images/ariul-dev/post/1b9cf8f0-f337-4858-b80d-4c3fede3ef4f/image.png" alt=""><img src="https://velog.velcdn.com/images/ariul-dev/post/7c8ef52f-915d-4f65-bc56-879b00448901/image.png" alt=""></li>
</ul>
<hr>
<h1 id="v2-nori--jamo--edge-n-gram--사용자-사전">v2. Nori + Jamo + Edge n-gram + 사용자 사전</h1>
<h2 id="인덱스-매핑-정의-1">인덱스 매핑 정의</h2>
<pre><code>PUT user-dic-plus
{
  &quot;settings&quot;: {
    &quot;analysis&quot;: {
      &quot;char_filter&quot;: { // 1️⃣ 캐릭터 필터
        &quot;special_character_filter&quot;: {
          &quot;pattern&quot;: &quot;[\\p{Alpha}\\p{Digit}]&quot;,
          &quot;type&quot;: &quot;pattern_replace&quot;,
          &quot;replacement&quot;: &quot;&quot;
        },
        &quot;blank_filter&quot;: {
          &quot;pattern&quot;: &quot;[\\p{Blank}]&quot;,
          &quot;type&quot;: &quot;pattern_replace&quot;,
          &quot;replacement&quot;: &quot;&quot;
        }
      },
      &quot;tokenizer&quot;: { // 2️⃣ 토크나이저
        &quot;korean_nori_tokenizer&quot;: {
          &quot;type&quot;: &quot;nori_tokenizer&quot;,
          &quot;user_dictionary&quot;: &quot;user_dic/pat_dic_v3.txt&quot;,
          &quot;decompound_mode&quot;: &quot;mixed&quot;
        }
      },
      &quot;filter&quot;: { // 3️⃣ 토큰 필터
        &quot;nori_posfilter&quot;: {
          &quot;type&quot;: &quot;nori_part_of_speech&quot;,
          &quot;stoptags&quot;: [&quot;J&quot;,&quot;E&quot;,&quot;NNB&quot;,&quot;MAJ&quot;,&quot;MM&quot;,&quot;XSV&quot;,&quot;XSA&quot;,&quot;VCP&quot;,&quot;SE&quot;,&quot;XSN&quot;,&quot;VCN&quot;,&quot;SP&quot;,&quot;NA&quot;,&quot;UNA&quot;,&quot;VSV&quot;,&quot;XPN&quot;,&quot;IC&quot;,&quot;VV&quot;]
        },
        &quot;ngram2_filter&quot;: {
          &quot;type&quot;: &quot;edge_ngram&quot;,
          &quot;min_gram&quot;: 2,
          &quot;max_gram&quot;: 20
        }
      },
      &quot;analyzer&quot;: { // 4️⃣ 애널라이저
        &quot;nori_analyzer&quot;: {
          &quot;type&quot;: &quot;custom&quot;,
          &quot;tokenizer&quot;: &quot;korean_nori_tokenizer&quot;,
          &quot;filter&quot; : [
            &quot;lowercase&quot;, 
            &quot;nori_posfilter&quot;
          ]
        },
        &quot;ngram_analyzer&quot;: {
          &quot;type&quot;: &quot;custom&quot;,
          &quot;char_filter&quot;: [
            &quot;special_character_filter&quot;
          ],
          &quot;tokenizer&quot;: &quot;standard&quot;,
          &quot;filter&quot; : [
            &quot;ngram2_filter&quot; 
          ]
        },
        &quot;jamo_index_analyzer&quot;: {
          &quot;type&quot;: &quot;custom&quot;,
          &quot;char_filter&quot;: [
            &quot;special_character_filter&quot;
          ],
          &quot;tokenizer&quot;: &quot;standard&quot;,
          &quot;filter&quot;: [
            &quot;jamo&quot;
          ]
        },
        &quot;jamo_search_analyzer&quot;: {
          &quot;type&quot;: &quot;custom&quot;,
          &quot;char_filter&quot;: [
            &quot;blank_filter&quot;,
            &quot;special_character_filter&quot;
          ],
          &quot;tokenizer&quot;: &quot;standard&quot;,
          &quot;filter&quot;: [
            &quot;jamo&quot;
          ]
        },
        &quot;jamo_live_blank_search_analyzer&quot;: {
          &quot;type&quot;: &quot;custom&quot;,
          &quot;char_filter&quot;: [
            &quot;special_character_filter&quot;
          ],
          &quot;tokenizer&quot;: &quot;standard&quot;,
          &quot;filter&quot;: [
            &quot;jamo&quot;
          ]
        },
        &quot;number_analyzer&quot; : {
          &quot;type&quot; : &quot;pattern&quot;,
          &quot;pattern&quot; :&quot;[.]&quot;
        }
      }
    }
  },
  &quot;mappings&quot;: { // 5️⃣ 필드에 데이터 타입 매핑
    &quot;properties&quot;: {
      &quot;발명의명칭&quot;: {
        &quot;type&quot;: &quot;text&quot;,
        &quot;analyzer&quot;: &quot;jamo_index_analyzer&quot;,
        &quot;search_analyzer&quot;: &quot;jamo_search_analyzer&quot;,
        &quot;fields&quot;: {
          &quot;lblank&quot;: {
            &quot;type&quot;: &quot;text&quot;,
            &quot;analyzer&quot;: &quot;jamo_index_analyzer&quot;,
            &quot;search_analyzer&quot;: &quot;jamo_live_blank_search_analyzer&quot;
          },
          &quot;ngram&quot;: {
            &quot;type&quot;: &quot;text&quot;,
            &quot;analyzer&quot;: &quot;ngram_analyzer&quot;
          },
          &quot;nori&quot;: {
            &quot;type&quot;: &quot;text&quot;,
            &quot;analyzer&quot;: &quot;nori_analyzer&quot;
          }
        }
      },
      &quot;요약&quot;: {
        &quot;type&quot;: &quot;text&quot;,
        &quot;analyzer&quot;: &quot;jamo_index_analyzer&quot;,
        &quot;search_analyzer&quot;: &quot;jamo_search_analyzer&quot;,
        &quot;fields&quot;: {
          &quot;lblank&quot;: {
            &quot;type&quot;: &quot;text&quot;,
            &quot;analyzer&quot;: &quot;jamo_index_analyzer&quot;,
            &quot;search_analyzer&quot;: &quot;jamo_live_blank_search_analyzer&quot;
          },
          &quot;ngram&quot;: {
            &quot;type&quot;: &quot;text&quot;,
            &quot;analyzer&quot;: &quot;ngram_analyzer&quot;
          },
          &quot;nori&quot;: {
            &quot;type&quot;: &quot;text&quot;,
            &quot;analyzer&quot;: &quot;nori_analyzer&quot;
          }
        }
      },
      &quot;출원인&quot;: {
        &quot;type&quot;: &quot;text&quot;,
        &quot;analyzer&quot;: &quot;jamo_index_analyzer&quot;,
        &quot;search_analyzer&quot;: &quot;jamo_search_analyzer&quot;,
        &quot;fields&quot;: {
          &quot;lblank&quot;: {
            &quot;type&quot;: &quot;text&quot;,
            &quot;analyzer&quot;: &quot;jamo_index_analyzer&quot;,
            &quot;search_analyzer&quot;: &quot;jamo_live_blank_search_analyzer&quot;
          },
          &quot;ngram&quot;: {
            &quot;type&quot;: &quot;text&quot;,
            &quot;analyzer&quot;: &quot;ngram_analyzer&quot;
          },
          &quot;nori&quot;: {
            &quot;type&quot;: &quot;text&quot;,
            &quot;analyzer&quot;: &quot;nori_analyzer&quot;
          }
        }
      },
      &quot;CPC분류&quot;: {
        &quot;type&quot;: &quot;text&quot;    
      },
      &quot;IPC분류&quot;: {
        &quot;type&quot;: &quot;text&quot;    
      },
      &quot;event&quot;: {
        &quot;properties&quot;: {
          &quot;original&quot;: {
            &quot;type&quot;: &quot;text&quot;,
            &quot;fields&quot;: {
              &quot;keyword&quot;: {
                &quot;type&quot;: &quot;keyword&quot;,
                &quot;ignore_above&quot;: 256
              }
            }
          }
        }
      },
      &quot;log&quot;: {
        &quot;properties&quot;: {
          &quot;file&quot;: {
            &quot;properties&quot;: {
              &quot;path&quot;: {
                &quot;type&quot;: &quot;text&quot;,
                &quot;fields&quot;: {
                  &quot;keyword&quot;: {
                    &quot;type&quot;: &quot;keyword&quot;,
                    &quot;ignore_above&quot;: 256
                  }
                }
              }
            }
          }
        }
      },
      &quot;공개번호&quot;: {
        &quot;type&quot;: &quot;keyword&quot;      
      },
      &quot;공고번호&quot;: {
        &quot;type&quot;: &quot;keyword&quot;
      },
      &quot;등록번호&quot;: {
       &quot;type&quot;: &quot;keyword&quot;
      },
      &quot;법적상태&quot;: {
        &quot;type&quot;: &quot;keyword&quot; 
      },
      &quot;출원번호&quot;: {
        &quot;type&quot;: &quot;text&quot;,
        &quot;fields&quot;: {
          &quot;keyword&quot; : {
            &quot;type&quot; : &quot;keyword&quot;,
            &quot;ignore_above&quot;: &quot;256&quot;
          }
        } 
      },
      &quot;출원일자&quot;: {
        &quot;type&quot;: &quot;text&quot;,
        &quot;analyzer&quot;: &quot;number_analyzer&quot;,
        &quot;fields&quot;: {
          &quot;keyword&quot; : {
            &quot;type&quot; : &quot;keyword&quot;,
            &quot;ignore_above&quot; : 256
          }
        }
      }
    }
  }
}</code></pre><h2 id="1-character-filter-1">1. Character Filter</h2>
<h3 id="11-pattern-replace-character-filter-1">1.1. Pattern Replace Character Filter</h3>
<p>정규 표현식을 사용하여 해당 문자들을 특정 문자열로 대체합니다.</p>
<p><strong>pattern replace character filter</strong>가 제공하는 옵션은 다음과 같습니다.</p>
<ul>
<li>pattern : 자바 정규 표현식</li>
</ul>
<pre><code>| 표현식 | 의미 |
| --- | --- |
| \p{Alpha} | 문자 |
| \p{Digit} | 숫자 |
| \{Blank} | space 또는 tab |</code></pre><ul>
<li>replacement : 대체 문자열<ul>
<li>special_character_filter:  문자와 숫자를 대체</li>
<li>blank_filter: 공백을 대체</li>
</ul>
</li>
</ul>
<h2 id="2-tokenizer-1">2. Tokenizer</h2>
<h3 id="21-nori-tokenizer-1">2.1. Nori Tokenizer</h3>
<p><strong>nori_tokenizer</strong>가 제공하는 옵션은 다음과 같습니다. </p>
<ul>
<li><p><strong>user_dictionary</strong> : 사용자 정의 사전</p>
<p>  ⇒ v1에서는 특허 검색 서비스에서 사용자 정의 사전을 설정하기 어렵다고 판단하여 배제하였습니다. 하지만 지속적으로 서치한 결과, 한국특허정보원에서 개발한 언어모델을 통해 600만 건의 용어가 있는 사용자 사전을 얻을 수 있었고 v2에는 이를 적용하였습니다.</p>
</li>
<li><p><strong>decompound_mode</strong> : 복합 명사를 토크나이저가 처리하는 방식을 결정</p>
<p>  ⇒ 분리된 복합 명사와 원본 데이터 모두 유지하기 위해 mixed로 설정하였습니다.</p>
</li>
</ul>
<h2 id="3-token-filter-1">3. Token Filter</h2>
<h3 id="31-nori_part_of_speech-1">3.1. nori_part_of_speech</h3>
<p><strong>nori_part_of_speech</strong> 토큰 필터를 이용해서 제거할 <strong>품사(POS - Part Of Speech) 코드입니다.</strong></p>
<p>⇒ “J&quot;,&quot;E&quot;,&quot;NNB&quot;,&quot;MAJ&quot;,&quot;MM&quot;,&quot;XSV&quot;,&quot;XSA&quot;,&quot;VCP&quot;,&quot;SE&quot;,&quot;XSN&quot;,&quot;VCN&quot;,&quot;SP&quot;,&quot;NA&quot;,&quot;UNA&quot;,&quot;VSV&quot;,&quot;XPN&quot;,&quot;IC&quot;,&quot;VV&quot;</p>
<h3 id="32-edge_ngram-1">3.2. edge_ngram</h3>
<p><strong>edge-ngram token filter</strong>가 제공하는 옵션은 다음과 같습니다. </p>
<ul>
<li>min_gram: 그램의 최소 글자 수</li>
<li>max_gram: 그램의 최대 글자 수</li>
</ul>
<h2 id="4-analyzer-1">4. Analyzer</h2>
<h3 id="41-nori_analyzer-1">4.1. nori_analyzer</h3>
<p>[발명의명칭], [출원인], [요약] 필드를 멀티 필드로 두고 <strong>.nori 필드</strong>에 한글 형태소 분석기(Nori)를 적용하였습니다. </p>
<h3 id="42-ngram_analyzer">4.2. ngram_analyzer</h3>
<p>[발명의명칭], [출원인], [요약] 필드를 멀티 필드로 두고 <strong>.ngram 필드</strong>에 커스텀 애널라이저를 적용하였습니다. </p>
<p>이 커스텀 애널라이저는 캐릭터 필터를 통해 문자, 숫자를 제거하고 standard 토크나이저와 edge n-gram 필터를 사용합니다. </p>
<h3 id="43-jamo_index_analyzer">4.3. jamo_index_analyzer</h3>
<p>[발명의명칭], [요약], [출원인] 필드를 멀티 필드로 두고 <strong>.lblank 필드</strong>에 커스텀 애널라이저를 적용하였습니다. </p>
<p>이 커스텀 애널라이저는 캐릭터 필터를 통해 문자, 숫자를 제거하고 standard 토크나이저와 jamo 필터를 사용합니다. </p>
<h3 id="44-jamo_search_analyzer">4.4. jamo_search_analyzer</h3>
<p>jamo_index_analyzer로 색인된 용어들을 잘 찾기 위해 검색 시에 search analyzer를 적용하였습니다.</p>
<p>이 커스텀 애널라이저는 캐릭터 필터를 통해 문자, 숫자, 공백을 제거하고 standard 토크나이저와 jamo 필터를 사용합니다. </p>
<h3 id="45-jamo_live_blank_search_analyzer">4.5. jamo_live_blank_search_analyzer</h3>
<p>jamo_index_analyzer로 색인된 용어들을 잘 찾기 위해 검색 시에 search analyzer를 적용하였습니다.</p>
<p>이 커스텀 애널라이저는 캐릭터 필터를 통해 문자, 숫자를 제거하고 standard 토크나이저와 jamo 필터를 사용합니다. </p>
<h3 id="46-number_analyzer">4.6. number_analyzer</h3>
<p>[출원일자] 필드의 데이터는 ‘2022.09.21’의 형태를 가집니다.</p>
<p>그 중에서 연도(2022)만 추출하기 위해  패턴 “[.]”을 기준으로 텍스트를 분리하는 패턴 애널라이저를 적용했습니다.</p>
<h2 id="5-필드에-데이터-타입-매핑-1">5. 필드에 데이터 타입 매핑</h2>
<ul>
<li>[출원번호] : text, keyword</li>
<li>[출원일자] : text, keyword</li>
<li>[발명의명칭] : text</li>
<li>[출원인] text</li>
<li>[IPC분류]  text</li>
<li>[CPC분류]  text</li>
<li>[공고번호]  keyword</li>
<li>[공개번호]  keyword</li>
<li>[등록번호]  keyword</li>
<li>[법적상태] keyword</li>
<li>[요약] text</li>
</ul>
<h2 id="개선점">개선점</h2>
<ul>
<li><p>v1과 달리, 키워드를 검색하면 원하는 결과를 얻을 수 있었습니다.</p>
<ul>
<li><p>검색한 키워드: <code>오일저장탱크</code></p>
</li>
<li><p>예상 반환 결과:<img src="https://velog.velcdn.com/images/ariul-dev/post/dbab804f-214b-4620-8337-4b25b5ff113e/image.png" alt=""></p>
</li>
<li><p>실제 반환 결과: 3 hits</p>
<pre><code>  {
    &quot;took&quot;: 59,
    &quot;timed_out&quot;: false,
    &quot;_shards&quot;: {
      &quot;total&quot;: 1,
      &quot;successful&quot;: 1,
      &quot;skipped&quot;: 0,
      &quot;failed&quot;: 0
    },
    &quot;hits&quot;: {
      &quot;total&quot;: {
        &quot;value&quot;: 3,
        &quot;relation&quot;: &quot;eq&quot;
      },
      &quot;max_score&quot;: 26.637434,
      &quot;hits&quot;: [
        {
          &quot;_index&quot;: &quot;user-dic-plus&quot;,
          &quot;_id&quot;: &quot;52ulk4MBvrSsT3SDS3_T&quot;,
          &quot;_score&quot;: 26.637434,
          &quot;_source&quot;: {
            &quot;요약&quot;: &quot;본 고안은 오일저장탱크를 갖춘 차량용 브레이크의 마스터실린더에 관한 것으로, 그 목적은 오일감지장치의 플로트가 오일저장탱크의 천정면에 접착되는 것을 방지하는 것이다. 본 고안에 따른 오일저장탱크를 갖춘 차량용 브레이크의 마스터실린더는 오일저장탱크(20) 내에 마련되는 플로트(31)의 상면에 다수개의 돌기(33)를 형성하여 오일의 점성 및 표면장력에 의해 탱크(20)의 천정면에 달라붙는 것을 방지하였다. 따라서 플로트(31)는 항상 오일의 액면상에 떠있게 되어 본 기능을 원활하게 수행하며, 이의 전체적인 신뢰성이 향상되는 이점이 있다.&quot;,
            &quot;발명의명칭&quot;: &quot;오일저장탱크를 갖춘 차량용 브레이크의 마스터실린더()&quot;
          }
        },
        {
          &quot;_index&quot;: &quot;user-dic-plus&quot;,
          &quot;_id&quot;: &quot;SGulk4MBvrSsT3SDioXv&quot;,
          &quot;_score&quot;: 18.489084,
          &quot;_source&quot;: {
            &quot;요약&quot;: &quot;본 발명은 용기(1)와, 용기의 상부 일 측에 파이프에 연결 설치되어 오일이 유입되는 오일저장탱크(2)와, 상기 용기(1)의 다른 상부 일 측에 파이프에 연결 설치되며 용기내의 압력을 감압시키는 진공펌프(4)와, 상기 용기(1)의 하부 일 측에 파이프에 연결 설치되어 오존을 용기(1)내에 유입된 오일(7)에 용해시키도록 공급하는 오존발생장치(3)와, 상기 용기(1)내의 하부 다른 일 측에 설치된 배출구(5)와, 용기(1)내의 몸체에 중앙부에 설치된 관찰창(6)과, 용기(1)의 하부에 설치된 진동장치(8)로 구성된 저농도 오존을 함유하는 오일제제 제조장치 및 그 제법. 저농도 오존화 오일제제 제조장치. 저농도 오존화 오일제제 제법. 진공펌프. 오존발생장치. 진동장치.&quot;,
            &quot;발명의명칭&quot;: &quot;저농도 오존을 함유하는 오일제제 제조장치 및 그 제법(Production method and apparatus for ozonized oil)&quot;
          }
        },
        {
          &quot;_index&quot;: &quot;user-dic-plus&quot;,
          &quot;_id&quot;: &quot;wmukk4MBvrSsT3SDxGpH&quot;,
          &quot;_score&quot;: 15.39892,
          &quot;_source&quot;: {
            &quot;요약&quot;: &quot;본 발명은 음식물 쓰레기 처리장치에 관한 것으로서 그 기술적인 수단은, 본체부(1)의 상부 일측면에 쓰레기 투입구(7)가 설치되고, 상기 본체부(1)의 내측에 형성되는 몸체(13)의 저면에 스크류 컨베이어(11) (11´) (11˝)로 이루어진 분쇄수단(14)이 설치되며, 상기 분쇄수단(14)의 상측에 중공의 회전축(15)에 연결되는 다수의 패들(16)로서 구성되는 교반기(17)가 설치되고, 상기 회전축(15)에 다수의 에어홀(34)이 형성한다. 또한, 상기 몸체(13)의 측면 상, 하에 전동기(18) (19)를 각각 설치하여 그 상측의 전동기(18)를 교반기(17)에 체인(22) 연결하고, 상기 하측의 전동기(19)를 스크류 컨베이어(11) 결합되는 스프로킷(23)에 체인(24) 연결하며, 상기 스크류 컨베이어(11)와 그 일측의 스크류 컨베이어(11´)는 기어 (25) (26) 결합되고, 상기 스크류 컨베이어(11)와 그 타측의 스크류 컨베이어(11˝)는 체인(27) 연결되며, 상기 몸체(13)의 외 측면 하부에 오일 저장탱크(29)를 설치하고, 상기 오일저장탱크(29)의 외 측면 저부에 히터장치(30)를 설치하며, 상기 히터장치(30)의 일 측에 송풍기 (31)를 설치하여 회전축(15)에 형성되는 에어 홀(34)에 에어를 공급토록 연결하고, 상기 몸체(13)의 일측에 결로장치(32)를 설치하는 것을 요지로 한다.&quot;,
            &quot;발명의명칭&quot;: &quot;음식물 쓰레기 처리장치()&quot;
          }
        }
      ]
    }
  }</code></pre></li>
</ul>
</li>
</ul>
<ul>
<li>인덱스텀과 쿼리텀 불일치 문제 해결<ul>
<li>jamo_search_analyzer는 캐릭터 필터에서 공백을 제거하고, jamo_live_blank_search_analyzer는 캐릭터 필터에서 공백을 제거하지 않았습니다.</li>
<li>두 개의 search_analyzer를 통해 인덱스텀과 쿼리텀이 일치하지 않는 문제를 해결했습니다.<ul>
<li>jamo_index_analyzer로 만든 인덱스텀<ul>
<li><code>ㅇㅗㅇㅣㄹㅈㅓㅈㅏㅇㅌㅐㅇㅋㅡㄹㅡㄹ</code> ✅</li>
</ul>
</li>
<li>jamo_search_analyzer로 만든 쿼리텀<ul>
<li><code>ㅇㅗㅇㅣㄹㅈㅓㅈㅏㅇㅌㅐㅇㅋㅡㄹㅡㄹㄱㅏㅈㅊㅜㄴㅊㅏㄹㅑㅇㅇㅛㅇㅂㅡㄹㅔㅇㅣㅋㅡㅇㅡㅣㅁㅏㅅㅡㅌㅓㅅㅣㄹㄹㅣㄴㄷㅓ</code></li>
</ul>
</li>
<li>jamo_live_blank_search_analyzer로 만든 쿼리텀<ul>
<li><code>ㅇㅗㅇㅣㄹㅈㅓㅈㅏㅇㅌㅐㅇㅋㅡㄹㅡㄹ</code> ✅</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<h2 id="문제점-1">문제점</h2>
<ul>
<li><p>검색 키워드에 오타가 있을 때 검색 결과 정확도가 떨어지는 문제</p>
<ul>
<li><p>검색한 키워드:  <code>어일저장탱크</code></p>
</li>
<li><p>예상 반환 결과:<img src="https://velog.velcdn.com/images/ariul-dev/post/dbab804f-214b-4620-8337-4b25b5ff113e/image.png" alt=""></p>
</li>
<li><p>실제 반환 결과: 예상 반환 데이터 누락</p>
<pre><code>  {
    &quot;took&quot;: 8,
    &quot;timed_out&quot;: false,
    &quot;_shards&quot;: {
      &quot;total&quot;: 1,
      &quot;successful&quot;: 1,
      &quot;skipped&quot;: 0,
      &quot;failed&quot;: 0
    },
    &quot;hits&quot;: {
      &quot;total&quot;: {
        &quot;value&quot;: 2,
        &quot;relation&quot;: &quot;eq&quot;
      },
      &quot;max_score&quot;: 14.601166,
      &quot;hits&quot;: [
        {
          &quot;_index&quot;: &quot;user-dic-plus&quot;,
          &quot;_id&quot;: &quot;wmukk4MBvrSsT3SDxGpH&quot;,
          &quot;_score&quot;: 14.601166,
          &quot;_source&quot;: {
            &quot;요약&quot;: &quot;본 발명은 음식물 쓰레기 처리장치에 관한 것으로서 그 기술적인 수단은, 본체부(1)의 상부 일측면에 쓰레기 투입구(7)가 설치되고, 상기 본체부(1)의 내측에 형성되는 몸체(13)의 저면에 스크류 컨베이어(11) (11´) (11˝)로 이루어진 분쇄수단(14)이 설치되며, 상기 분쇄수단(14)의 상측에 중공의 회전축(15)에 연결되는 다수의 패들(16)로서 구성되는 교반기(17)가 설치되고, 상기 회전축(15)에 다수의 에어홀(34)이 형성한다. 또한, 상기 몸체(13)의 측면 상, 하에 전동기(18) (19)를 각각 설치하여 그 상측의 전동기(18)를 교반기(17)에 체인(22) 연결하고, 상기 하측의 전동기(19)를 스크류 컨베이어(11) 결합되는 스프로킷(23)에 체인(24) 연결하며, 상기 스크류 컨베이어(11)와 그 일측의 스크류 컨베이어(11´)는 기어 (25) (26) 결합되고, 상기 스크류 컨베이어(11)와 그 타측의 스크류 컨베이어(11˝)는 체인(27) 연결되며, 상기 몸체(13)의 외 측면 하부에 오일 저장탱크(29)를 설치하고, 상기 오일저장탱크(29)의 외 측면 저부에 히터장치(30)를 설치하며, 상기 히터장치(30)의 일 측에 송풍기 (31)를 설치하여 회전축(15)에 형성되는 에어 홀(34)에 에어를 공급토록 연결하고, 상기 몸체(13)의 일측에 결로장치(32)를 설치하는 것을 요지로 한다.&quot;,
            &quot;발명의명칭&quot;: &quot;음식물 쓰레기 처리장치()&quot;
          }
        },
        {
          &quot;_index&quot;: &quot;user-dic-plus&quot;,
          &quot;_id&quot;: &quot;SGulk4MBvrSsT3SDioXv&quot;,
          &quot;_score&quot;: 14.172298,
          &quot;_source&quot;: {
            &quot;요약&quot;: &quot;본 발명은 용기(1)와, 용기의 상부 일 측에 파이프에 연결 설치되어 오일이 유입되는 오일저장탱크(2)와, 상기 용기(1)의 다른 상부 일 측에 파이프에 연결 설치되며 용기내의 압력을 감압시키는 진공펌프(4)와, 상기 용기(1)의 하부 일 측에 파이프에 연결 설치되어 오존을 용기(1)내에 유입된 오일(7)에 용해시키도록 공급하는 오존발생장치(3)와, 상기 용기(1)내의 하부 다른 일 측에 설치된 배출구(5)와, 용기(1)내의 몸체에 중앙부에 설치된 관찰창(6)과, 용기(1)의 하부에 설치된 진동장치(8)로 구성된 저농도 오존을 함유하는 오일제제 제조장치 및 그 제법. 저농도 오존화 오일제제 제조장치. 저농도 오존화 오일제제 제법. 진공펌프. 오존발생장치. 진동장치.&quot;,
            &quot;발명의명칭&quot;: &quot;저농도 오존을 함유하는 오일제제 제조장치 및 그 제법(Production method and apparatus for ozonized oil)&quot;
          }
        }
      ]
    }
  }</code></pre></li>
<li><p>검색 결과가 없는 이유: 쿼리텀에 일치하는 인덱스텀이 존재하지 않음</p>
<ul>
<li>nori_analyzer<ul>
<li>인덱스텀: <code>오일저장탱크</code> <code>차량</code> <code>브레이크</code> <code>마스터실린더</code></li>
<li>쿼리텀: <code>일</code> <code>저장탱크</code></li>
</ul>
</li>
<li>ngram_analyzer<ul>
<li>인덱스텀: <code>오일</code> <code>오일저</code> <code>오일저장</code> <code>오일저장탱</code> <code>오일저장탱크</code> <code>오일저장탱크를</code> …</li>
<li>쿼리텀: <code>어일</code> <code>어일저</code> <code>어일저장</code> <code>어일저장탱</code> <code>어일저장탱크</code></li>
</ul>
</li>
<li>jamo_index_analyzer로 만든 인덱스텀<ul>
<li><code>ㅇㅗㅇㅣㄹㅈㅓㅈㅏㅇㅌㅐㅇㅋㅡㄹㅡㄹ</code> <code>ㄱㅏㅈㅊㅜㄴ</code> <code>ㅊㅏㄹㅑㅇㅇㅛㅇ</code> …</li>
</ul>
</li>
<li>jamo_search_analyzer로 만든 쿼리텀<ul>
<li><code>ㅇㅓㅇㅣㄹㅈㅓㅈㅏㅇㅌㅐㅇㅋㅡ</code></li>
</ul>
</li>
<li>jamo_live_blank_search_analyzer로 만든 쿼리텀<ul>
<li><code>ㅇㅓㅇㅣㄹㅈㅓㅈㅏㅇㅌㅐㅇㅋㅡ</code></li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<h2 id="해결-방법-및-대안-1">해결 방법 및 대안</h2>
<ul>
<li>Edge n-gram 애널라이저를 Ngram 애널라이저로 변경 시도<ul>
<li>Edge n-gram은 키워드의 시작부터 min_gram과 max_gram 옵션에 따라 토큰을 나누기 때문에 단어의 맨 앞 글자부터 오타가 있으면 원하는 검색 결과를 얻을 수 없었습니다.</li>
<li>쿼리텀과 일치하는 부분을 많이 생성하고자 Edge n-gram 애널라이저를 Ngram 애널라이저로 변경하기로 결정하였습니다.</li>
</ul>
</li>
</ul>
]]></description>
        </item>
    </channel>
</rss>