<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>소니 스토리 (Sony Story)</title>
    <link>https://isony.tistory.com/</link>
    <description>Sony Story
나의 소니 스토리
(BTS 성지 탐방, 공연, 예배)</description>
    <language>ko</language>
    <pubDate>Mon, 27 Jul 2026 05:26:07 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>isony</managingEditor>
    <image>
      <title>소니 스토리 (Sony Story)</title>
      <url>https://tistory1.daumcdn.net/tistory/6567966/attach/c330ff73c83d4cff866b7ffe09ebe12b</url>
      <link>https://isony.tistory.com</link>
    </image>
    <item>
      <title>[Claude 시리즈 8편] Claude로 코딩하기 - 비개발자도 가능한 자동화와 도구 만들기</title>
      <link>https://isony.tistory.com/entry/Claude-%EC%8B%9C%EB%A6%AC%EC%A6%88-8%ED%8E%B8-Claude%EB%A1%9C-%EC%BD%94%EB%94%A9%ED%95%98%EA%B8%B0-%EB%B9%84%EA%B0%9C%EB%B0%9C%EC%9E%90%EB%8F%84-%EA%B0%80%EB%8A%A5%ED%95%9C-%EC%9E%90%EB%8F%99%ED%99%94%EC%99%80-%EB%8F%84%EA%B5%AC-%EB%A7%8C%EB%93%A4%EA%B8%B0</link>
      <description>&lt;h1&gt;[Claude 시리즈 8편] Claude로 코딩하기 - 비개발자도 가능한 자동화와 도구 만들기&lt;/h1&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;테스트 환경&lt;/b&gt;: Claude Sonnet 5 / Opus 4.8 (2026년 7월 기준)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;코딩은 개발자만 하는 거 아닌가요?&quot;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2026년의 답은 &lt;b&gt;&quot;아니오&quot;&lt;/b&gt; 입니다. Claude를 쓰면 프로그래밍을 배운 적 없어도 &lt;b&gt;엑셀 매크로, 파일 정리 스크립트, 간단한 웹 도구&lt;/b&gt;를 만들 수 있습니다. 코드를 직접 쓰는 게 아니라, &lt;b&gt;원하는 것을 설명하면 Claude가 코드를 만들고 실행&lt;/b&gt;해줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글에서는 다음을 다룹니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;비개발자가 코딩을 활용할 수 있는 영역&lt;/li&gt;
&lt;li&gt;Artifact로 즉석 도구 만들기&lt;/li&gt;
&lt;li&gt;실전 예제 5가지 (복붙 가능)&lt;/li&gt;
&lt;li&gt;코드를 이해하지 못해도 안전하게 쓰는 법&lt;/li&gt;
&lt;li&gt;다음 단계 (개발자로 나아가기)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글은 &lt;a href=&quot;https://www.whodo.net/category/AI%20%28Claude%20%ED%99%9C%EC%9A%A9%29/Claude%20%EC%8B%A4%EB%AC%B4%28%ED%99%9C%EC%9A%A9%29&quot;&gt;Phase 2&lt;/a&gt;의 네 번째 글입니다. &lt;b&gt;코딩 경험이 전혀 없어도&lt;/b&gt; 따라올 수 있습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;비개발자가 코딩으로 할 수 있는 것&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;코딩&quot;이라고 하면 앱이나 웹사이트를 떠올리지만, 실무에서 유용한 건 &lt;b&gt;작은 자동화&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;영역 예시 절약 시간&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;파일 정리&lt;/td&gt;
&lt;td&gt;수백 개 파일 이름 일괄 변경&lt;/td&gt;
&lt;td&gt;시간 &amp;rarr; 초&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;데이터 변환&lt;/td&gt;
&lt;td&gt;Excel &amp;rarr; CSV &amp;rarr; JSON 변환&lt;/td&gt;
&lt;td&gt;반복 작업 제거&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;텍스트 처리&lt;/td&gt;
&lt;td&gt;문서에서 특정 패턴 추출&lt;/td&gt;
&lt;td&gt;수동 검색 제거&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;계산 도구&lt;/td&gt;
&lt;td&gt;맞춤 계산기 만들기&lt;/td&gt;
&lt;td&gt;반복 계산 자동화&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;웹 도구&lt;/td&gt;
&lt;td&gt;간단한 입력 폼, 대시보드&lt;/td&gt;
&lt;td&gt;즉석 제작&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 것들은 &lt;b&gt;파이썬 몇 줄&lt;/b&gt;이면 되는데, 그 몇 줄을 Claude가 만들어줍니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;방법 1: Artifact로 즉석 도구 만들기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 쉬운 방법입니다. Claude가 &lt;b&gt;실제로 동작하는 도구&lt;/b&gt;를 대화창 옆에 만들어줍니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;계산기 만들기&lt;/h3&gt;
&lt;pre class=&quot;asciidoc&quot;&gt;&lt;code&gt;대출 이자 계산기를 만들어주세요.
- 입력: 대출 원금, 연이율, 기간(년)
- 출력: 월 상환액, 총 이자, 총 상환액
- 입력하면 바로 계산되게
- 보기 좋은 디자인으로
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude가 실제 작동하는 계산기를 Artifact로 만듭니다. 숫자를 입력하면 바로 계산됩니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;입력 폼 만들기&lt;/h3&gt;
&lt;pre class=&quot;asciidoc&quot;&gt;&lt;code&gt;간단한 설문 폼을 만들어주세요.
- 이름, 이메일, 만족도(1~5), 의견
- 제출하면 입력 내용을 정리해서 보여주기
- 깔끔한 디자인
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;시각화 도구&lt;/h3&gt;
&lt;pre class=&quot;asciidoc&quot;&gt;&lt;code&gt;BMI 계산기를 만들어주세요.
- 키, 몸무게 입력
- BMI 계산 + 저체중/정상/과체중 판정
- 결과를 시각적 게이지로 표시
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;중요&lt;/b&gt;: Artifact는 대화 세션 안에서만 동작합니다. 계속 쓰려면 코드를 저장해서 본인 환경에 옮겨야 합니다(아래 참고).&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;방법 2: 파일&amp;middot;데이터 작업 자동화&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude가 Python을 실행해서 실제 파일 작업을 해줍니다. Code execution을 켜세요.&lt;/p&gt;
&lt;pre class=&quot;apache&quot;&gt;&lt;code&gt;Settings &amp;rarr; Capabilities &amp;rarr; Code execution &amp;rarr; ON
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;파일 변환&lt;/h3&gt;
&lt;pre class=&quot;prolog&quot;&gt;&lt;code&gt;[Excel 파일 첨부]

이 엑셀 파일을 CSV로 변환해주세요.
그리고 날짜 컬럼을 YYYY-MM-DD 형식으로 
통일해주세요.
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;데이터 정리&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;[지저분한 데이터 첨부]

이 데이터를 정리해주세요:
1. 중복 행 제거
2. 빈 값이 있는 행 표시
3. 이름 컬럼의 앞뒤 공백 제거
4. 정리된 파일로 다운로드 가능하게
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;여러 파일 합치기&lt;/h3&gt;
&lt;pre class=&quot;asciidoc&quot;&gt;&lt;code&gt;[여러 CSV 첨부]

이 파일들을 하나로 합쳐주세요.
- 같은 컬럼 구조입니다
- 어느 파일에서 왔는지 출처 컬럼 추가
- 합친 결과를 다운로드 가능하게
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;★ 실전 예제 5가지&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;예제 1: 이메일 주소 추출&lt;/h3&gt;
&lt;pre class=&quot;prolog&quot;&gt;&lt;code&gt;[텍스트 또는 문서 첨부]

이 문서에서 모든 이메일 주소를 
추출해서 목록으로 만들어주세요.
중복은 제거하고 알파벳 순으로 정렬해주세요.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;수백 페이지 문서에서도 순식간에 추출합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;예제 2: 파일명 일괄 변경 규칙&lt;/h3&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;제 폴더에 다음과 같은 파일들이 있습니다:
IMG_001.jpg, IMG_002.jpg ... (100개)

이걸 &quot;2026여행_01.jpg&quot; 형식으로 바꾸는 
방법을 알려주세요. 
- Windows에서 실행할 수 있는 방법
- 프로그래밍 모르는 사람도 따라할 수 있게
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude가 실행 방법을 단계별로 안내하거나, 스크립트를 만들어줍니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;예제 3: 맞춤 대시보드&lt;/h3&gt;
&lt;pre class=&quot;asciidoc&quot;&gt;&lt;code&gt;[매출 CSV 첨부]

이 데이터로 인터랙티브 대시보드를 만들어주세요.
- 상단: 총매출, 평균, 성장률 카드
- 월별 추세 차트
- 카테고리별 비중 파이 차트
- 필터 기능 (기간 선택)

HTML로 만들어서 바로 볼 수 있게 해주세요.
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;예제 4: 반복 문서 생성&lt;/h3&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;아래 명단으로 각자에게 보낼 
맞춤 안내문을 만들어주세요.

명단:
[이름, 부서, 날짜]

템플릿:
&quot;안녕하세요 [이름]님, [부서]의 [날짜] 
교육 일정을 안내드립니다...&quot;

각 사람별로 완성된 안내문을 만들어주세요.
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;예제 5: 간단한 웹 페이지&lt;/h3&gt;
&lt;pre class=&quot;asciidoc&quot;&gt;&lt;code&gt;우리 팀 소개 페이지를 만들어주세요.
- 팀 이름: [이름]
- 팀원 5명 (이름, 역할)
- 팀 소개 문구
- 연락처

깔끔하고 모던한 디자인으로, 
HTML 한 파일로 만들어주세요.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;완성된 HTML을 받아서 그대로 쓸 수 있습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;코드를 이해 못 해도 안전하게 쓰는 법&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비개발자가 가장 걱정하는 부분입니다. 안전 수칙을 정리했습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 코드가 뭘 하는지 물어보기&lt;/h3&gt;
&lt;pre class=&quot;erlang&quot;&gt;&lt;code&gt;방금 만든 코드가 정확히 무슨 일을 하는지 
비개발자도 이해할 수 있게 설명해주세요.
위험한 작업(파일 삭제 등)이 있나요?
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. 원본은 항상 백업&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파일을 다루는 스크립트를 실행하기 전에 &lt;b&gt;원본 파일을 반드시 복사&lt;/b&gt;해두세요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. 작은 것부터 테스트&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;100개 파일에 적용하기 전에, 
먼저 2~3개로 테스트하는 방법을 알려주세요.
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4. 위험한 명령 확인&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파일 삭제, 덮어쓰기, 시스템 변경 같은 작업은 실행 전에 Claude에게 위험성을 물어보세요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5. 모르면 실행하지 않기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이해 못 하는 코드를 중요한 데이터에 실행하지 마세요. Claude에게 충분히 설명을 듣고, 안전을 확인한 후에만 실행하세요.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Artifact 코드를 실제로 쓰려면&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Artifact는 대화 세션에서만 동작합니다. 계속 쓰려면:&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;HTML 도구의 경우&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;1. Artifact 우측 하단 다운로드 또는 복사
2. 텍스트 파일로 저장, 확장자를 .html로
3. 더블클릭하면 브라우저에서 실행
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Python 스크립트의 경우&lt;/h3&gt;
&lt;pre class=&quot;1c&quot;&gt;&lt;code&gt;Claude에게 물어보세요:
&quot;이 스크립트를 제 컴퓨터에서 실행하려면 
어떻게 해야 하나요? Python 설치부터 
단계별로 알려주세요.&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude가 환경 설정부터 실행까지 안내합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;더 나아가고 싶다면&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반복적으로 코딩을 활용하게 되면 &lt;b&gt;Claude Code&lt;/b&gt;를 고려하세요. 터미널에서 Claude가 직접 파일을 다루고 코드를 실행합니다. (본 블로그의 &lt;a href=&quot;https://www.whodo.net/category/AI%20%28Claude%20%ED%99%9C%EC%9A%A9%29&quot;&gt;Claude Code 시리즈&lt;/a&gt; 참고)&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;자주 하는 실수와 주의사항&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;실수 1: 이해 없이 실행&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 위험합니다. 특히 파일을 삭제&amp;middot;변경하는 코드는 반드시 이해하고 백업 후 실행.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;실수 2: 원본 백업 안 함&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터 처리 스크립트는 원본을 망칠 수 있습니다. 항상 복사본으로 작업.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;실수 3: 대량 적용 전 테스트 생략&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2~3개로 먼저 테스트하고 결과를 확인한 후 전체 적용.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;실수 4: 민감 데이터를 코드에 포함&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비밀번호, API 키, 개인정보를 코드에 그대로 넣지 마세요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;실수 5: Artifact가 영구 저장된다고 착각&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Artifact는 세션용입니다. 계속 쓸 도구는 코드를 저장해서 본인 환경으로 옮기세요.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;다음 글 예고&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 글은 &lt;b&gt;[Claude 시리즈 9편] Claude Projects 활용 완벽 가이드&lt;/b&gt; 입니다. Phase 2의 마지막 글로, 지금까지 배운 활용법을 Projects로 체계화하는 방법을 다룹니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;마무리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비개발자가 Claude로 코딩을 활용하는 핵심은:&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;작은 자동화부터&lt;/b&gt; (파일 정리, 데이터 변환)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Artifact로 즉석 도구&lt;/b&gt; 만들기&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Code execution으로 실제 파일 작업&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;코드가 뭘 하는지 물어보고 이해&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;원본 백업 + 작은 테스트 후 적용&lt;/b&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로그래밍을 배우지 않아도 그 효용을 누릴 수 있는 시대입니다. 다만 &quot;이해하지 못하는 코드를 중요한 데이터에 실행하지 않는다&quot;는 원칙만은 꼭 지키세요. 안전하게 시작해서 점점 영역을 넓혀가시길 바랍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코딩 경험이 없으셨다면, 오늘 위 예제 중 하나(계산기나 파일 변환)를 시도해보세요. 생각보다 쉽다는 걸 느끼실 겁니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;본인이 만든 유용한 도구나 자동화 사례가 있다면 댓글로 공유해주세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>AI (Claude 활용)/Claude 실무(활용)</category>
      <category>Claude Artifact</category>
      <category>Claude Prompt</category>
      <category>Claude Python</category>
      <category>Claude 웹도구</category>
      <category>claude 자동화</category>
      <category>Claude 코딩</category>
      <category>Claude 파이썬</category>
      <category>Claude 파일정리</category>
      <category>비개발자 코딩</category>
      <category>소니스토리</category>
      <author>isony</author>
      <guid isPermaLink="true">https://isony.tistory.com/360</guid>
      <comments>https://isony.tistory.com/entry/Claude-%EC%8B%9C%EB%A6%AC%EC%A6%88-8%ED%8E%B8-Claude%EB%A1%9C-%EC%BD%94%EB%94%A9%ED%95%98%EA%B8%B0-%EB%B9%84%EA%B0%9C%EB%B0%9C%EC%9E%90%EB%8F%84-%EA%B0%80%EB%8A%A5%ED%95%9C-%EC%9E%90%EB%8F%99%ED%99%94%EC%99%80-%EB%8F%84%EA%B5%AC-%EB%A7%8C%EB%93%A4%EA%B8%B0#entry360comment</comments>
      <pubDate>Mon, 27 Jul 2026 03:15:27 +0900</pubDate>
    </item>
    <item>
      <title>2026년07월26일 주일예배 (이재훈목사님) - 1부</title>
      <link>https://isony.tistory.com/entry/2026%EB%85%8407%EC%9B%9426%EC%9D%BC-%EC%A3%BC%EC%9D%BC%EC%98%88%EB%B0%B0-%EC%9D%B4%EC%9E%AC%ED%9B%88%EB%AA%A9%EC%82%AC%EB%8B%98-1%EB%B6%80</link>
      <description>&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;2026년07월26일 주일예배 (이재훈목사님) - 1부&lt;/h2&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;주의 말씀 : 나를 따르라&amp;nbsp; (11)&lt;/h2&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;여러분의 구원을 이루십시오&lt;/h2&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;성경 :&amp;nbsp; 빌립보서(Phillippians) 2:12 ~ 18 말씀 (출처:우리말성경)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&amp;lt; 성경 &amp;gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;2:12 그러므로 내 사랑하는 사람들이여, 여러분이 항상 순종했던 것처럼 내가 여러분과 함께 있을 때뿐 아니라 지금 내가 없을 때도 두렵고 떨리는 마음으로 여러분의 구원을 이루십시오.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;2:13 여러분 안에서 하나님의 기쁘신 뜻에 따라 결단하게 하시고 행동하게 하시는 분은 하나님이시기 때문입니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;2:14 무슨 일을 하든지 여러분은 불평이나 분쟁 없이 하십시오.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;2:15 이는 여러분이 흠 없고 순전한 사람들이 돼 뒤틀리고 타락한 세대 가운데서 책망받을 것이 없는 하나님의 자녀들로서 세상에서 하늘의 별들처럼 빛나게 하려는 것입니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;2:16 생명의 말씀을 꼭 붙들어 그리스도의 날에 내게 자랑이 되게 하십시오. 이는 내가 헛되게 달음질하거나 헛되게 수고한 것이 아니기 때문입니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;2:17 이제 내가 여러분의 믿음의 제사와 예배에 내 피를 붓는 일이 있을지라도 나는 기뻐하고 여러분 모두와 함께 기뻐할 것입니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;2:18 여러분도 함께 기뻐하고 나와 함께 기뻐하십시오.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&amp;lt; 예배 영상 &amp;gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;a href=&quot;https://youtu.be/quE3hrdR_nI&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://youtu.be/quE3hrdR_nI&lt;/a&gt;&lt;/b&gt;&lt;/p&gt;
&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignCenter&quot; data-video-host=&quot;youtube&quot; data-video-url=&quot;https://www.youtube.com/watch?v=quE3hrdR_nI&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/G657c/dJMb81f6dTB/UboJmARrBVf13Dyk6qSkKk/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=564_134_712_294,https://scrap.kakaocdn.net/dn/dhNJ6y/dJMb87OaurI/i2Fui0FbttOSBKQwrWOqNK/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=564_134_712_294,https://scrap.kakaocdn.net/dn/cvYEby/dJMb88fel4I/TJZ9qR4si739nMsA7bAKBk/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=564_134_712_294&quot; data-video-width=&quot;860&quot; data-video-height=&quot;484&quot; data-video-origin-width=&quot;860&quot; data-video-origin-height=&quot;484&quot; data-ke-mobilestyle=&quot;widthContent&quot; data-video-title=&quot;주일예배2026 07 26&quot; data-original-url=&quot;&quot;&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/quE3hrdR_nI&quot; width=&quot;860&quot; height=&quot;484&quot; frameborder=&quot;&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;figcaption style=&quot;display: none;&quot;&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&quot;당신이 명하신 것을 (행할 수 있도록) 주시고, 원하시는 바를 명하소서.&quot;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;(Give what You command, and&amp;nbsp; command what You will.)&lt;/b&gt;&lt;/p&gt;</description>
      <category>성경과 QT/주일예배(온누리교회)</category>
      <category>CGNTV</category>
      <category>구원을 이루십시오</category>
      <category>나를 따르라</category>
      <category>빌립보서 2장</category>
      <category>소니스토리</category>
      <category>여러분의 구원</category>
      <category>예배영상</category>
      <category>우리말성경</category>
      <category>이재훈목사</category>
      <category>주일예배</category>
      <author>isony</author>
      <guid isPermaLink="true">https://isony.tistory.com/359</guid>
      <comments>https://isony.tistory.com/entry/2026%EB%85%8407%EC%9B%9426%EC%9D%BC-%EC%A3%BC%EC%9D%BC%EC%98%88%EB%B0%B0-%EC%9D%B4%EC%9E%AC%ED%9B%88%EB%AA%A9%EC%82%AC%EB%8B%98-1%EB%B6%80#entry359comment</comments>
      <pubDate>Sun, 26 Jul 2026 08:04:54 +0900</pubDate>
    </item>
    <item>
      <title>[Claude 시리즈 7편] Claude로 회의록 요약과 액션 아이템 추출 - 회의 시간을 절반으로</title>
      <link>https://isony.tistory.com/entry/Claude-%EC%8B%9C%EB%A6%AC%EC%A6%88-7%ED%8E%B8-Claude%EB%A1%9C-%ED%9A%8C%EC%9D%98%EB%A1%9D-%EC%9A%94%EC%95%BD%EA%B3%BC-%EC%95%A1%EC%85%98-%EC%95%84%EC%9D%B4%ED%85%9C-%EC%B6%94%EC%B6%9C-%ED%9A%8C%EC%9D%98-%EC%8B%9C%EA%B0%84%EC%9D%84-%EC%A0%88%EB%B0%98%EC%9C%BC%EB%A1%9C</link>
      <description>&lt;h1&gt;[Claude 시리즈 7편] Claude로 회의록 요약과 액션 아이템 추출 - 회의 시간을 절반으로&lt;/h1&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;테스트 환경&lt;/b&gt;: Claude Sonnet 5 / Opus 4.8 (2026년 7월 기준)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;회의는 끝났는데 &lt;b&gt;&quot;그래서 누가 뭘 하기로 했지?&quot;&lt;/b&gt; 가 남습니다. 회의록을 정리하는 데 또 30분, 그마저도 며칠 지나면 흐지부지됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude는 &lt;b&gt;긴 대화에서 핵심을 추출&lt;/b&gt;하는 데 강합니다. 두서없는 회의 메모나 녹취록을 넣으면, 결정 사항과 액션 아이템을 담당자&amp;middot;기한과 함께 정리해줍니다. 200K 컨텍스트라 몇 시간짜리 회의록도 한 번에 처리합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글에서 다룰 내용입니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;회의록 정리의 기본 프롬프트&lt;/li&gt;
&lt;li&gt;상황별 회의 유형 프롬프트 (5가지)&lt;/li&gt;
&lt;li&gt;녹취록 &amp;rarr; 회의록 변환&lt;/li&gt;
&lt;li&gt;액션 아이템 추적 시스템 만들기&lt;/li&gt;
&lt;li&gt;회의 전&amp;middot;중&amp;middot;후 Claude 활용법&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글은 &lt;a href=&quot;https://www.whodo.net/category/AI%20%28Claude%20%ED%99%9C%EC%9A%A9%29/Claude%20%EC%8B%A4%EB%AC%B4%28%ED%99%9C%EC%9A%A9%29&quot;&gt;Phase 2&lt;/a&gt;의 세 번째 글입니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;기본: 회의록 정리 프롬프트&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 기본이 되는 프롬프트입니다. 이것만 알아도 충분합니다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;아래 회의 내용을 정리해주세요.

&amp;lt;meeting_notes&amp;gt;
[회의 메모 또는 녹취록 붙여넣기]
&amp;lt;/meeting_notes&amp;gt;

다음 형식으로:
1. 회의 개요 (일시, 참석자, 안건)
2. 주요 논의 사항 (핵심만)
3. 결정 사항 (확정된 것만)
4. 액션 아이템 (표: 담당자 | 할 일 | 기한)
5. 다음 회의 안건 (있으면)

주의: 논의만 되고 결정 안 된 것은 3번이 아니라 
     2번이나 5번에 넣어주세요.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;핵심 포인트&lt;/b&gt;: &quot;결정된 것&quot;과 &quot;논의만 된 것&quot;을 구분하라고 명시하는 부분입니다. 이걸 안 하면 Claude가 애매한 것도 결정 사항으로 넣을 수 있습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;★ 상황별 회의 유형 프롬프트&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 프로젝트 회의&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;&amp;lt;meeting_notes&amp;gt;
[붙여넣기]
&amp;lt;/meeting_notes&amp;gt;

프로젝트 회의록으로 정리해주세요:
1. 진행 현황 요약
2. 완료된 마일스톤
3. 블로커/이슈 (심각도 표시)
4. 액션 아이템 (담당자, 기한)
5. 리스크 및 다음 단계

특히 블로커는 눈에 띄게 강조해주세요.
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. 브레인스토밍 회의&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;&amp;lt;meeting_notes&amp;gt;
[붙여넣기]
&amp;lt;/meeting_notes&amp;gt;

브레인스토밍 결과를 정리해주세요:
1. 나온 아이디어 전체 목록 (판단 없이)
2. 카테고리별 그룹핑
3. 논의에서 지지받은 아이디어
4. 추가 검토가 필요한 아이디어
5. 다음 단계 제안

아이디어를 함부로 버리지 말고 모두 기록해주세요.
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. 의사결정 회의&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;&amp;lt;meeting_notes&amp;gt;
[붙여넣기]
&amp;lt;/meeting_notes&amp;gt;

의사결정 회의록으로 정리해주세요:
1. 결정해야 했던 안건
2. 검토된 선택지들과 각각의 장단점
3. 최종 결정과 그 근거
4. 반대 의견 (있었다면 기록)
5. 결정에 따른 액션 아이템

결정 근거를 명확히 남겨주세요. 
나중에 &quot;왜 그렇게 결정했지?&quot;에 답할 수 있게.
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4. 고객&amp;middot;외부 미팅&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;&amp;lt;meeting_notes&amp;gt;
[붙여넣기]
&amp;lt;/meeting_notes&amp;gt;

고객 미팅 기록으로 정리해주세요:
1. 미팅 목적과 참석자
2. 고객 요구사항/피드백
3. 우리가 약속한 것 (중요!)
4. 후속 조치 (담당자, 기한)
5. 다음 접촉 계획

우리가 약속한 사항은 빠짐없이 기록해주세요.
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5. 1:1 미팅&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;&amp;lt;meeting_notes&amp;gt;
[붙여넣기]
&amp;lt;/meeting_notes&amp;gt;

1:1 미팅 노트로 정리해주세요:
1. 논의 주제
2. 상대의 관심사/고민
3. 합의 사항
4. 내가 후속 조치할 것
5. 다음 1:1에서 확인할 것
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;녹취록 &amp;rarr; 회의록 변환&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요즘은 회의를 녹음하고 자동 전사(transcription)하는 경우가 많습니다. 이 두서없는 녹취록을 정리하는 프롬프트입니다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;아래는 회의 녹취록입니다. 자동 전사라 
말투가 정리 안 되어 있고 중복이 많습니다.

&amp;lt;transcript&amp;gt;
[녹취록 붙여넣기]
&amp;lt;/transcript&amp;gt;

이걸 깔끔한 회의록으로 변환해주세요:
1. 잡담과 반복 제거
2. 핵심 논의만 추출
3. 발언자별 주요 입장 (필요시)
4. 결정 사항과 액션 아이템
5. 표준 회의록 형식으로

원래 없던 내용을 지어내지 말고, 
녹취록에 있는 내용만 정리해주세요.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;주의&lt;/b&gt;: 마지막 문장(&quot;지어내지 말라&quot;)이 중요합니다. 녹취록이 불완전하면 Claude가 빈칸을 추측으로 채울 수 있는데, 이를 방지합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;★ 액션 아이템 추적 시스템&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;회의록의 진짜 가치는 &lt;b&gt;액션 아이템이 실제로 실행되는 것&lt;/b&gt;입니다. 추적 시스템을 만들어봅시다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;액션 아이템 표 만들기&lt;/h3&gt;
&lt;pre class=&quot;gherkin&quot;&gt;&lt;code&gt;&amp;lt;meeting_notes&amp;gt;
[붙여넣기]
&amp;lt;/meeting_notes&amp;gt;

이 회의의 액션 아이템만 추출해서 
추적용 표로 만들어주세요:

컬럼: 번호 | 할 일 | 담당자 | 기한 | 우선순위 | 상태

- 우선순위는 높음/중간/낮음
- 상태는 모두 &quot;미착수&quot;로 초기화
- 기한이 명시 안 된 것은 &quot;미정&quot;으로 표시하고 
  기한 설정이 필요하다고 표시
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;여러 회의 통합 추적&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Projects를 활용하면 여러 회의의 액션 아이템을 누적 관리할 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;prolog&quot;&gt;&lt;code&gt;[Projects에 이전 액션 아이템 표 업로드]

새 회의록입니다:
&amp;lt;meeting_notes&amp;gt;
[붙여넣기]
&amp;lt;/meeting_notes&amp;gt;

기존 액션 아이템 표에 이번 회의 항목을 추가하고,
이전 항목 중 이번 회의에서 언급된 것은 
상태를 업데이트해주세요.
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;액션 아이템을 Artifact 대시보드로&lt;/h3&gt;
&lt;pre class=&quot;asciidoc&quot;&gt;&lt;code&gt;아래 액션 아이템들을 관리 대시보드로 만들어주세요.

[액션 아이템 목록]

- 담당자별로 그룹핑
- 기한 임박 순 정렬
- 상태별 색상 구분
- HTML로 보기 좋게

기한이 지난 항목은 빨간색으로 강조해주세요.
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;회의 전&amp;middot;중&amp;middot;후 Claude 활용법&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;회의록 정리는 회의 &quot;후&quot;의 활용입니다. 전과 중에도 Claude를 쓸 수 있습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;회의 전: 안건 준비&lt;/h3&gt;
&lt;pre class=&quot;asciidoc&quot;&gt;&lt;code&gt;다음 주제로 회의를 하려고 합니다: [주제]
참석자: [누구]
목표: [무엇을 결정/논의]

효과적인 회의 안건(아젠다)을 만들어주세요:
- 시간 배분 포함
- 사전 준비 사항
- 논의 순서
- 결정해야 할 핵심 질문
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;회의 중: 실시간 정리&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;회의 중 메모를 Claude에 실시간으로 던지면 즉석 정리도 가능합니다. 다만 회의에 집중하는 게 우선이니, 보통은 회의 후 정리를 권합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;회의 후: 후속 조치&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;[정리된 회의록]

이 회의록을 바탕으로:
1. 참석자들에게 보낼 요약 이메일 초안
2. 각 담당자에게 보낼 개별 액션 아이템 알림
3. 상급자 보고용 3줄 요약

각각 만들어주세요.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 하면 회의 &amp;rarr; 정리 &amp;rarr; 공유 &amp;rarr; 후속까지 한 번에 처리됩니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;자주 하는 실수와 해결&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;실수 1: &quot;결정&quot;과 &quot;논의&quot;를 안 나눔&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude에게 이 둘을 구분하라고 명시하지 않으면 애매한 것도 결정으로 처리됩니다. 프롬프트에 항상 명시하세요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;실수 2: 담당자&amp;middot;기한 누락&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;액션 아이템에 담당자와 기한이 없으면 실행이 안 됩니다. &quot;명시 안 된 것은 표시하라&quot;고 요청해서 빈칸을 드러내세요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;실수 3: 녹취록의 빈칸을 추측으로 채움&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;불완전한 녹취록은 Claude가 추측할 수 있습니다. &quot;있는 내용만 정리하라&quot;를 꼭 넣으세요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;실수 4: 민감한 회의 내용 그대로 업로드&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인사 평가, 기밀 전략, 개인 신상 등이 담긴 회의록은 주의하세요. 민감 부분은 제거하거나 일반화하세요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;실수 5: 정리만 하고 공유 안 함&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정리된 회의록은 &lt;b&gt;당일 공유&lt;/b&gt;가 생명입니다. Claude로 요약 이메일까지 만들어서 바로 보내세요.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;다음 글 예고&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 글은 &lt;b&gt;[Claude 시리즈 8편] Claude로 코딩하기 - 비개발자도 가능&lt;/b&gt; 입니다. 개발자가 아니어도 간단한 자동화와 도구를 만드는 방법을 다룹니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;마무리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;회의록 정리에 Claude를 활용하는 핵심은:&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;&quot;결정&quot;과 &quot;논의&quot;를 구분&lt;/b&gt;하도록 명시&lt;/li&gt;
&lt;li&gt;&lt;b&gt;액션 아이템은 담당자&amp;middot;기한과 함께&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;녹취록은 &quot;있는 내용만&quot; 정리&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Projects로 여러 회의 누적 추적&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;정리 후 당일 공유&lt;/b&gt; (요약 이메일까지 Claude로)&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;회의의 가치는 회의 자체가 아니라 &lt;b&gt;실행되는 액션 아이템&lt;/b&gt;에 있습니다. Claude로 정리 시간을 줄인 만큼, 그 시간을 실제 실행에 쓰시길 바랍니다. 다만 민감한 회의 내용은 늘 조심스럽게 다루세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;본인의 회의록 정리 노하우나 유용했던 프롬프트가 있다면 댓글로 공유해주세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>AI (Claude 활용)/Claude 실무(활용)</category>
      <category>ai 회의록</category>
      <category>Claude 녹취록</category>
      <category>Claude 액션 아이템</category>
      <category>Claude 정리</category>
      <category>claude 활용법</category>
      <category>Claude 회의록</category>
      <category>Claude 회의정리</category>
      <category>Claude 회의추출</category>
      <category>소니스토리</category>
      <category>액션 아이템</category>
      <author>isony</author>
      <guid isPermaLink="true">https://isony.tistory.com/358</guid>
      <comments>https://isony.tistory.com/entry/Claude-%EC%8B%9C%EB%A6%AC%EC%A6%88-7%ED%8E%B8-Claude%EB%A1%9C-%ED%9A%8C%EC%9D%98%EB%A1%9D-%EC%9A%94%EC%95%BD%EA%B3%BC-%EC%95%A1%EC%85%98-%EC%95%84%EC%9D%B4%ED%85%9C-%EC%B6%94%EC%B6%9C-%ED%9A%8C%EC%9D%98-%EC%8B%9C%EA%B0%84%EC%9D%84-%EC%A0%88%EB%B0%98%EC%9C%BC%EB%A1%9C#entry358comment</comments>
      <pubDate>Fri, 24 Jul 2026 06:49:12 +0900</pubDate>
    </item>
    <item>
      <title>[Claude 시리즈 6편] Claude로 데이터 분석하기 - Excel&amp;middot;CSV 완벽 활용 (비전공자도 가능)</title>
      <link>https://isony.tistory.com/entry/Claude-%EC%8B%9C%EB%A6%AC%EC%A6%88-6%ED%8E%B8-Claude%EB%A1%9C-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%B6%84%EC%84%9D%ED%95%98%EA%B8%B0-Excel%C2%B7CSV-%EC%99%84%EB%B2%BD-%ED%99%9C%EC%9A%A9-%EB%B9%84%EC%A0%84%EA%B3%B5%EC%9E%90%EB%8F%84-%EA%B0%80%EB%8A%A5</link>
      <description>&lt;h1&gt;[Claude 시리즈 6편] Claude로 데이터 분석하기 - Excel&amp;middot;CSV 완벽 활용 (비전공자도 가능)&lt;/h1&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;테스트 환경&lt;/b&gt;: Claude Sonnet 5 / Opus 4.8 (2026년 7월 기준)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;엑셀 데이터는 있는데 분석할 줄을 모르겠어요.&quot; &quot;피벗 테이블, VLOOKUP... 매번 검색하기 지쳤어요.&quot;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터 분석은 전문가의 영역처럼 보이지만, Claude를 쓰면 &lt;b&gt;함수를 몰라도, 파이썬을 몰라도&lt;/b&gt; 데이터에서 인사이트를 뽑아낼 수 있습니다. 파일을 올리고 질문만 하면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글에서는 다음을 다룹니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Claude에 데이터 올리는 법 (Excel, CSV)&lt;/li&gt;
&lt;li&gt;분석 프롬프트 패턴 (기초 &amp;rarr; 심화)&lt;/li&gt;
&lt;li&gt;차트&amp;middot;시각화 만들기 (Artifact 활용)&lt;/li&gt;
&lt;li&gt;실전 분석 시나리오 5가지&lt;/li&gt;
&lt;li&gt;자주 하는 실수와 주의사항&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글은 &lt;a href=&quot;https://www.whodo.net/category/AI%20%28Claude%20%ED%99%9C%EC%9A%A9%29/Claude%20%EC%8B%A4%EB%AC%B4%28%ED%99%9C%EC%9A%A9%29&quot;&gt;Phase 2&lt;/a&gt;의 두 번째 글입니다. 코딩 지식 없이 따라올 수 있게 구성했습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Claude에 데이터 올리기&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;지원 형식&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;형식 지원 비고&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Excel (.xlsx)&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;여러 시트 가능&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CSV&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;가장 안정적&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TSV&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;탭 구분&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;붙여넣기&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;소량 데이터&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;올리는 방법&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;1. 대화창 하단 + 버튼 또는 클립 아이콘
2. 파일 선택
3. 질문 입력
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;팁&lt;/b&gt;: 데이터가 크면 CSV로 변환해서 올리는 것이 가장 안정적입니다. Excel의 복잡한 서식은 오히려 방해될 수 있습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Code execution 켜기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정확한 계산과 차트를 위해 코드 실행을 켜세요.&lt;/p&gt;
&lt;pre class=&quot;apache&quot;&gt;&lt;code&gt;Settings &amp;rarr; Capabilities &amp;rarr; Code execution &amp;rarr; ON
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이걸 켜면 Claude가 실제로 Python을 실행해서 정확히 계산합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;분석 프롬프트 - 기초편&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;데이터 개요 파악&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 먼저 할 일은 데이터가 어떻게 생겼는지 파악하는 것입니다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;[파일 첨부]

이 데이터의 개요를 알려주세요:
1. 행과 열의 수
2. 각 컬럼의 의미와 데이터 타입
3. 결측치(빈 값) 여부
4. 눈에 띄는 특이사항
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;기초 통계&lt;/h3&gt;
&lt;pre class=&quot;asciidoc&quot;&gt;&lt;code&gt;[파일 첨부]

다음 통계를 알려주세요:
- 숫자 컬럼별 평균, 중앙값, 최대, 최소
- 범주형 컬럼별 빈도
- 이상치로 보이는 값
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;조건 필터링&lt;/h3&gt;
&lt;pre class=&quot;prolog&quot;&gt;&lt;code&gt;[파일 첨부]

다음 조건에 맞는 데이터만 보여주세요:
- [조건 1: 예. 매출 1000만원 이상]
- [조건 2: 예. 서울 지역]

결과를 표로, 매출 높은 순으로 정렬해주세요.
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;그룹별 집계&lt;/h3&gt;
&lt;pre class=&quot;prolog&quot;&gt;&lt;code&gt;[파일 첨부]

[컬럼 A]별로 [컬럼 B]의 합계와 평균을 
구해주세요. 표로 정리하고 큰 순서로 정렬해주세요.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이건 엑셀의 피벗 테이블을 대체합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;분석 프롬프트 - 심화편&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;트렌드 분석&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;[파일 첨부]

이 데이터에서 시간에 따른 트렌드를 분석해주세요:
1. 전체적인 증가/감소 추세
2. 계절성이나 주기성
3. 특이한 변화 시점과 가능한 원인
4. 라인 차트로 시각화
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;상관관계 분석&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;[파일 첨부]

다음을 분석해주세요:
1. 어떤 변수들이 서로 관련 있는가
2. [변수 A]와 [변수 B]의 관계
3. 상관관계가 인과관계는 아니라는 점 고려해서 해석
4. 산점도로 시각화
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;세그먼트 분석&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;[파일 첨부]

고객(또는 항목)을 의미 있는 그룹으로 나눠주세요:
1. 어떤 기준으로 나누면 좋을지 제안
2. 각 그룹의 특징
3. 그룹별 규모와 비중
4. 실무 시사점
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;이상치 탐지&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;[파일 첨부]

이 데이터에서 이상치를 찾아주세요:
1. 통계적으로 벗어난 값
2. 그 값이 오류인지 실제 특이 케이스인지 판단 근거
3. 처리 방법 제안 (제거/보정/유지)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;예측&amp;middot;추정&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;[파일 첨부]

이 데이터를 기반으로:
1. 다음 기간 값을 추정 (단순 추세 기준)
2. 추정의 근거와 가정
3. 신뢰할 수 있는 범위
4. 주의할 점 (이 예측의 한계)
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;★ 차트&amp;middot;시각화 만들기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude는 Artifact로 실제 차트를 그려줍니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;차트 요청 방법&lt;/h3&gt;
&lt;pre class=&quot;prolog&quot;&gt;&lt;code&gt;[파일 첨부]

[컬럼 A]별 [컬럼 B]를 막대 차트로 만들어주세요.
- 큰 순서로 정렬
- 값 레이블 표시
- 색상은 파란색 계열
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;차트 종류별 용도&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;차트 용도 프롬프트 키워드&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;막대&lt;/td&gt;
&lt;td&gt;항목 비교&lt;/td&gt;
&lt;td&gt;&quot;막대 차트로&quot;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;라인&lt;/td&gt;
&lt;td&gt;시간 추세&lt;/td&gt;
&lt;td&gt;&quot;라인 차트로&quot;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;파이&lt;/td&gt;
&lt;td&gt;비중&lt;/td&gt;
&lt;td&gt;&quot;파이 차트로&quot;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;산점도&lt;/td&gt;
&lt;td&gt;상관관계&lt;/td&gt;
&lt;td&gt;&quot;산점도로&quot;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;히트맵&lt;/td&gt;
&lt;td&gt;밀도&amp;middot;패턴&lt;/td&gt;
&lt;td&gt;&quot;히트맵으로&quot;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;대시보드 만들기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여러 차트를 한 번에:&lt;/p&gt;
&lt;pre class=&quot;asciidoc&quot;&gt;&lt;code&gt;[파일 첨부]

이 데이터로 대시보드를 만들어주세요:
- 상단: 핵심 지표 3개 (총합, 평균, 성장률)
- 좌측: 카테고리별 막대 차트
- 우측: 시간별 추세 라인 차트

HTML로 보기 좋게 구성해주세요.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude가 인터랙티브 대시보드를 Artifact로 만들어줍니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;★ 실전 시나리오 5가지&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;시나리오 1: 매출 데이터 분석&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;[매출 CSV 첨부]

우리 회사 매출 데이터입니다. 다음을 분석해주세요:
1. 월별 매출 추세
2. 제품별 기여도 (상위 5개)
3. 지역별 분포
4. 전년 대비 성장률
5. 주목할 인사이트 3가지

각 항목을 차트로 시각화하고, 
마지막에 실행 가능한 제안을 해주세요.
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;시나리오 2: 설문 결과 정리&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;[설문 응답 CSV 첨부]

설문 결과입니다:
1. 각 문항별 응답 분포
2. 주요 발견 사항
3. 응답자 그룹별 차이
4. 종합 결론

시각화 포함해서 보고서 형태로 정리해주세요.
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;시나리오 3: 재고&amp;middot;운영 데이터&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;[재고 데이터 첨부]

재고 데이터를 분석해주세요:
1. 회전율 낮은 항목 (과잉 재고)
2. 부족 위험 항목
3. ABC 분석 (중요도 분류)
4. 발주 권장 사항
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;시나리오 4: 로그 데이터 분석 (IT)&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;[로그 CSV 첨부]

서버 로그입니다:
1. 에러 발생 패턴 (시간대별)
2. 가장 빈번한 에러 TOP 10
3. 이상 징후 시점
4. 우선 조치가 필요한 항목
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이건 IT 운영자에게 특히 유용합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;시나리오 5: 두 데이터 비교&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;[파일 2개 첨부]

작년과 올해 데이터를 비교해주세요:
1. 주요 지표 변화 (증감률)
2. 개선된 부분과 악화된 부분
3. 변화의 가능한 원인
4. 비교 차트로 시각화
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;자주 하는 실수와 해결&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;실수 1: 데이터를 그대로 붙여넣기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;수백 행을 텍스트로 붙여넣으면 오류가 납니다. &lt;b&gt;파일로 첨부&lt;/b&gt;하세요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;실수 2: 계산을 눈으로 검증 안 함&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude가 계산을 대부분 정확히 하지만, &lt;b&gt;중요한 숫자는 검증&lt;/b&gt;하세요. Code execution을 켜면 정확도가 올라갑니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;실수 3: 맥락 없이 질문&lt;/h3&gt;
&lt;pre class=&quot;1c&quot;&gt;&lt;code&gt;❌ &quot;이거 분석해줘&quot;
✅ &quot;이건 3월 매출 데이터야. 전월 대비 
   급감했는데 원인이 될 만한 패턴을 찾아줘&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터의 의미와 분석 목적을 알려주면 훨씬 유용한 답이 나옵니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;실수 4: 민감 데이터 그대로 업로드&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;고객 이름, 연락처, 주민번호 등이 포함된 데이터는 &lt;b&gt;익명화 후&lt;/b&gt; 업로드하세요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;실수 5: 결과를 맹신&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude의 분석은 &lt;b&gt;출발점&lt;/b&gt;입니다. 특히 예측이나 인과 해석은 참고용으로만 쓰고, 중요한 결정은 추가 검증하세요.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;데이터 분석 시 보안 체크리스트&lt;/h2&gt;
&lt;pre class=&quot;less&quot;&gt;&lt;code&gt;[ ] 고객 개인정보 익명화했는가
[ ] 회사 기밀 매출/계약 정보 제거했는가
[ ] 학습 옵트아웃 설정했는가 (Settings &amp;rarr; Privacy)
[ ] 업로드 전 파일에 숨은 시트/메모 확인했는가
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;업무 데이터는 특히 신중하게. 익명화하거나 샘플/일반화한 데이터로 작업하는 것이 안전합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;다음 글 예고&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 글은 &lt;b&gt;[Claude 시리즈 7편] Claude로 회의록 요약과 액션 아이템 추출&lt;/b&gt; 입니다. 긴 회의록을 실행 가능한 형태로 정리하는 실전 방법을 다룹니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;마무리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude로 데이터를 분석하는 핵심은:&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;파일로 첨부&lt;/b&gt; (붙여넣기 아님)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Code execution 켜기&lt;/b&gt; (정확한 계산)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;데이터 맥락과 목적 알려주기&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Artifact로 시각화&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;중요 숫자는 검증, 민감 정보는 익명화&lt;/b&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;함수나 파이썬을 몰라도 데이터에서 인사이트를 뽑을 수 있는 시대입니다. 다만 결과를 맹신하지 말고 검증하는 습관, 그리고 민감 정보를 조심하는 습관을 함께 기르시길 권합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;본인이 자주 분석하는 데이터 유형이나 유용했던 프롬프트가 있다면 댓글로 공유해주세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>AI (Claude 활용)/Claude 실무(활용)</category>
      <category>AI 데이터 분석</category>
      <category>AI 엑셀분석</category>
      <category>Claude CSV</category>
      <category>Claude CSV 첨부</category>
      <category>Claude Excel</category>
      <category>Claude 데이터 검증</category>
      <category>Claude 데이터분석</category>
      <category>Claude 스킬</category>
      <category>Claude 파일첨부</category>
      <category>소니스토리</category>
      <author>isony</author>
      <guid isPermaLink="true">https://isony.tistory.com/357</guid>
      <comments>https://isony.tistory.com/entry/Claude-%EC%8B%9C%EB%A6%AC%EC%A6%88-6%ED%8E%B8-Claude%EB%A1%9C-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%B6%84%EC%84%9D%ED%95%98%EA%B8%B0-Excel%C2%B7CSV-%EC%99%84%EB%B2%BD-%ED%99%9C%EC%9A%A9-%EB%B9%84%EC%A0%84%EA%B3%B5%EC%9E%90%EB%8F%84-%EA%B0%80%EB%8A%A5#entry357comment</comments>
      <pubDate>Wed, 22 Jul 2026 08:03:58 +0900</pubDate>
    </item>
    <item>
      <title>[Claude 시리즈 5편] Claude로 이메일&amp;middot;보고서 쓰기 - 직장인 실전 프롬프트 20개 (복사/붙여넣기 가능)</title>
      <link>https://isony.tistory.com/entry/Claude-%EC%8B%9C%EB%A6%AC%EC%A6%88-5%ED%8E%B8-Claude%EB%A1%9C-%EC%9D%B4%EB%A9%94%EC%9D%BC%C2%B7%EB%B3%B4%EA%B3%A0%EC%84%9C-%EC%93%B0%EA%B8%B0-%EC%A7%81%EC%9E%A5%EC%9D%B8-%EC%8B%A4%EC%A0%84-%ED%94%84%EB%A1%AC%ED%94%84%ED%8A%B8-20%EA%B0%9C-%EB%B3%B5%EC%82%AC%EB%B6%99%EC%97%AC%EB%84%A3%EA%B8%B0-%EA%B0%80%EB%8A%A5</link>
      <description>&lt;h1&gt;[Claude 시리즈 5편] Claude로 이메일&amp;middot;보고서 쓰기 - 직장인 실전 프롬프트 20개 (복사/붙여넣기 가능)&lt;/h1&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;테스트 환경&lt;/b&gt;: Claude Sonnet 5 / Opus 4.8 (2026년 7월 기준)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;직장인이 하루에 이메일과 문서 작성에 쓰는 시간은 평균 &lt;b&gt;2~3시간&lt;/b&gt;입니다. 이 시간을 절반으로 줄일 수 있다면 어떨까요?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude는 &lt;b&gt;뉘앙스 있는 글쓰기&lt;/b&gt;가 강점입니다. 특히 이메일과 보고서처럼 &lt;b&gt;톤과 정확성이 중요한 문서&lt;/b&gt;에서 진가를 발휘합니다. 이 글에서는 그대로 복사해서 쓸 수 있는 실전 프롬프트 20개를 상황별로 정리했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글은 &lt;a href=&quot;https://www.whodo.net/category/AI%20%28Claude%20%ED%99%9C%EC%9A%A9%29/Claude%20%EC%9E%85%EB%AC%B8&quot;&gt;Phase 1(입문)&lt;/a&gt;을 마친 분들을 위한 &lt;b&gt;Phase 2(실무 활용)의 첫 글&lt;/b&gt;입니다. 프롬프트 원칙은 &lt;a href=&quot;https://www.whodo.net/category/AI%20%28Claude%20%ED%99%9C%EC%9A%A9%29/Claude%20%EC%9E%85%EB%AC%B8&quot;&gt;4편&lt;/a&gt;에서 다뤘으니, 이번엔 바로 실전으로 들어갑니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;바쁘신 분은 원하는 상황으로 바로 이동하세요: &lt;b&gt;&lt;u&gt;이메일&lt;/u&gt;&lt;/b&gt; / &lt;b&gt;&lt;u&gt;보고서&lt;/u&gt;&lt;/b&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;시작 전: 이메일&amp;middot;문서 작성의 기본 원칙&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude에게 문서를 맡길 때 결과를 좌우하는 3가지입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 관계와 맥락을 알려주기&lt;/h3&gt;
&lt;pre class=&quot;1c&quot;&gt;&lt;code&gt;❌ &quot;거절 이메일 써줘&quot;
✅ &quot;3년 거래한 협력사의 단가 인상 요청을 
   관계를 해치지 않으면서 거절하는 이메일&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. 핵심 메시지를 먼저 정하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude에게 맡기기 전에 &lt;b&gt;&quot;이 문서로 상대가 무엇을 하길 바라는가&quot;&lt;/b&gt; 를 명확히 하세요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. 톤을 명시하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정중함, 단호함, 친근함, 격식 &amp;mdash; 원하는 톤을 구체적으로 지정하면 결과가 확 달라집니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  이메일 프롬프트 10개&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 정중한 거절&lt;/h3&gt;
&lt;pre class=&quot;prolog&quot;&gt;&lt;code&gt;다음 상황의 거절 이메일을 작성해주세요.

상황: [누가 무엇을 요청했는지]
관계: [상대와의 관계, 거래 기간 등]
거절 이유: [실제 이유]
유지하고 싶은 것: 관계, 향후 협업 가능성

톤: 정중하되 명확하게. 여지를 남기지 않되 
    상대가 무안하지 않게.
분량: 200자 이내
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. 단호한 독촉&lt;/h3&gt;
&lt;pre class=&quot;makefile&quot;&gt;&lt;code&gt;다음 건에 대한 독촉 이메일을 작성해주세요.

상황: [무엇이 지연되고 있는지]
경과: [언제 약속했고 얼마나 지났는지]
목표: 빠른 조치 유도, 단 관계는 유지

톤: 정중하지만 더 이상 미룰 수 없다는 단호함이 
    느껴지게. 3번째 독촉이라는 느낌.
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. 사과 이메일&lt;/h3&gt;
&lt;pre class=&quot;prolog&quot;&gt;&lt;code&gt;다음 실수에 대한 사과 이메일을 작성해주세요.

실수 내용: [무엇이 잘못됐는지]
영향: [상대에게 어떤 영향]
조치: [이미 한 것과 앞으로 할 것]

톤: 변명하지 않되 과도하게 굽신거리지도 않게.
    책임은 인정하고 해결에 집중.
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4. 나쁜 소식 전달&lt;/h3&gt;
&lt;pre class=&quot;prolog&quot;&gt;&lt;code&gt;다음 나쁜 소식을 전하는 이메일을 작성해주세요.

소식: [전달할 내용]
대상: [누구에게]
완충 필요도: [높음/중간/낮음]

톤: 솔직하되 배려 있게. 나쁜 소식을 
    빙빙 돌리지 말고 명확히, 하지만 
    다음 단계를 함께 제시.
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5. 협조 요청&lt;/h3&gt;
&lt;pre class=&quot;prolog&quot;&gt;&lt;code&gt;다음 협조를 구하는 이메일을 작성해주세요.

요청: [무엇을 부탁하는지]
상대 입장: [상대에게 어떤 부담/이익]
기한: [언제까지]

톤: 상대의 바쁨을 인정하면서, 왜 이 일이 
    중요한지와 상대에게 어떤 도움이 되는지 
    명확히. 강요 아닌 협조 요청.
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;6. 첫 인사 (콜드 메일)&lt;/h3&gt;
&lt;pre class=&quot;makefile&quot;&gt;&lt;code&gt;처음 연락하는 상대에게 보내는 이메일을 작성해주세요.

목적: [무엇을 위해 연락]
나: [내 소개, 왜 이 사람에게]
상대: [상대에 대해 아는 것]

톤: 예의 있되 장황하지 않게. 첫 3줄 안에 
    &quot;왜 연락했는지&quot;가 드러나게.
분량: 150자 이내
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;7. 회신 (여러 질문에 답변)&lt;/h3&gt;
&lt;pre class=&quot;prolog&quot;&gt;&lt;code&gt;아래 받은 이메일에 회신해주세요.

받은 메일:
[붙여넣기]

내 답변 요지:
- 질문 1 &amp;rarr; [답]
- 질문 2 &amp;rarr; [답]
- 질문 3 &amp;rarr; [답]

톤: 명확하고 구조적으로. 각 질문에 
    빠짐없이 답하되 간결하게.
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;8. 일정 조율&lt;/h3&gt;
&lt;pre class=&quot;prolog&quot;&gt;&lt;code&gt;회의 일정을 조율하는 이메일을 작성해주세요.

목적: [무슨 회의]
참석자: [누구누구]
내 가능 시간: [옵션들]
소요 시간: [예상]

톤: 효율적으로. 상대가 답하기 쉽게 
    선택지를 명확히 제시.
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;9. 감사 인사&lt;/h3&gt;
&lt;pre class=&quot;prolog&quot;&gt;&lt;code&gt;다음에 대한 감사 이메일을 작성해주세요.

받은 도움: [무엇을]
그 영향: [어떤 도움이 됐는지 구체적으로]

톤: 진심이 느껴지되 과하지 않게. 
    형식적이지 않고 구체적인 감사.
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;10. 소개 이메일 (제3자 연결)&lt;/h3&gt;
&lt;pre class=&quot;prolog&quot;&gt;&lt;code&gt;두 사람을 연결하는 소개 이메일을 작성해주세요.

A: [사람 A 소개]
B: [사람 B 소개]
연결 이유: [왜 둘이 만나면 좋은지]

톤: 양쪽 모두를 존중하며, 왜 이 연결이 
    서로에게 가치 있는지 명확히.
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  보고서 프롬프트 10개&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;11. 주간 업무 보고&lt;/h3&gt;
&lt;pre class=&quot;prolog&quot;&gt;&lt;code&gt;아래 내용으로 주간 업무 보고를 작성해주세요.

이번 주 한 일:
[나열]

다음 주 계획:
[나열]

이슈:
[있으면]

형식: 상급자가 5초 안에 파악할 수 있게.
     완료/진행중/이슈를 구분. 불릿으로 간결하게.
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;12. 프로젝트 현황 보고&lt;/h3&gt;
&lt;pre class=&quot;prolog&quot;&gt;&lt;code&gt;프로젝트 현황 보고서를 작성해주세요.

프로젝트: [이름, 목표]
진행률: [%, 주요 마일스톤]
완료 사항: [나열]
리스크: [있으면]
필요 지원: [있으면]

형식: 경영진 대상. 핵심 지표 먼저, 
     상세는 뒤에. 표 활용.
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;13. 장애 보고서 (포스트모템)&lt;/h3&gt;
&lt;pre class=&quot;prolog&quot;&gt;&lt;code&gt;장애 보고서를 작성해주세요.

장애: [무슨 일이]
발생 시각: [언제~언제]
영향: [범위, 규모]
원인: [근본 원인]
조치: [대응 과정]
재발 방지: [계획]

형식: 사실 기반, 비난 없이. 시간순 정리 후 
     원인 분석. 재발 방지에 집중.
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;14. 제안서 초안&lt;/h3&gt;
&lt;pre class=&quot;prolog&quot;&gt;&lt;code&gt;다음 제안서 초안을 작성해주세요.

제안: [무엇을 제안]
배경: [왜 필요한지]
기대 효과: [정량/정성]
비용: [예상]
일정: [단계별]

형식: 의사결정자 대상. 문제 &amp;rarr; 해결책 &amp;rarr; 
     효과 &amp;rarr; 실행 순. 설득력 있게.
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;15. 회의 결과 정리&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;아래 회의 내용을 보고용으로 정리해주세요.

회의 메모:
[붙여넣기]

형식:
1. 회의 개요 (일시, 참석자, 안건)
2. 주요 논의 사항
3. 결정 사항
4. 액션 아이템 (담당자, 기한)
5. 다음 회의 안건
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;16. 데이터 요약 보고&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;아래 데이터를 보고서로 요약해주세요.

데이터:
[숫자, 표 붙여넣기]

형식:
1. 핵심 요약 (숫자 3개로)
2. 주요 발견 (트렌드, 이상치)
3. 시사점
4. 권고 사항

차트가 필요하면 Artifact로 만들어주세요.
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;17. 기획안&lt;/h3&gt;
&lt;pre class=&quot;prolog&quot;&gt;&lt;code&gt;다음 기획안을 작성해주세요.

기획: [무엇을]
목적: [왜]
타겟: [누구를 위해]
핵심 내용: [무엇을 할지]
성공 지표: [어떻게 측정]

형식: 실행 가능하게. 추상적 표현 대신 
     구체적 액션. 5W1H 명확히.
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;18. 검토 의견서&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;아래 문서에 대한 검토 의견서를 작성해주세요.

검토 대상:
[문서 붙여넣기]

검토 관점: [무엇을 봐야 하는지]

형식:
1. 종합 의견
2. 항목별 지적 (근거 포함)
3. 개선 제안
4. 결론 (승인/보완/반려 의견)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;19. 이슈 트래킹&lt;/h3&gt;
&lt;pre class=&quot;gherkin&quot;&gt;&lt;code&gt;현재 이슈들을 정리한 보고서를 작성해주세요.

이슈 목록:
[나열: 이슈, 상태, 담당]

형식: 심각도 순으로 표. 
     컬럼: 이슈 | 영향 | 상태 | 담당 | 예상 해결일
     블로커는 별도로 강조.
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;20. 분기 성과 정리&lt;/h3&gt;
&lt;pre class=&quot;prolog&quot;&gt;&lt;code&gt;분기 성과 보고서를 작성해주세요.

목표 대비 실적:
[숫자]

주요 성과:
[나열]

미달 항목과 이유:
[있으면]

다음 분기 계획:
[방향]

형식: 경영진 대상. 정량 지표 중심. 
     잘한 것과 개선할 것을 균형 있게.
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;★ 실전 활용 워크플로우&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프롬프트를 더 효과적으로 쓰는 방법입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;초안 &amp;rarr; 다듬기 흐름&lt;/h3&gt;
&lt;pre class=&quot;lsl&quot;&gt;&lt;code&gt;1. 위 프롬프트로 초안 생성
2. &quot;이 부분을 더 [강하게/부드럽게] 해줘&quot;
3. &quot;너무 길어, 3문장으로 줄여줘&quot;
4. &quot;이 표현은 오해 소지 있어, 바꿔줘&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한 번에 완벽을 노리지 말고 &lt;b&gt;대화형으로 다듬는 것&lt;/b&gt;이 핵심입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;본인 스타일 학습시키기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자주 쓰는 문서라면 본인이 과거에 쓴 잘된 이메일 2~3개를 보여주세요.&lt;/p&gt;
&lt;pre class=&quot;prolog&quot;&gt;&lt;code&gt;아래는 제가 평소 쓰는 이메일 스타일입니다.
[예시 2~3개]

이 스타일을 유지하면서 다음 이메일을 써주세요.
[요청]
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Projects로 표준화&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반복되는 문서(주간 보고 등)는 Projects에 템플릿과 지침을 저장하면 매번 형식을 설명할 필요가 없습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;주의사항&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 회사 기밀&amp;middot;개인정보 금지&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;고객 정보, 미공개 실적, 계약 조건 같은 민감 정보는 입력하지 마세요. 익명화하거나 일반화해서 사용하세요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. 최종 검토는 본인 몫&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude가 만든 문서는 &lt;b&gt;초안&lt;/b&gt;입니다. 발송 전 반드시 사실관계, 숫자, 톤을 본인이 확인하세요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. 톤이 본인과 맞는지&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude의 기본 톤이 본인 스타일과 다를 수 있습니다. 어색하면 &quot;더 간결하게&quot;, &quot;덜 격식 있게&quot; 등으로 조정하세요.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;다음 글 예고&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 글은 &lt;b&gt;[Claude 시리즈 6편] Claude로 데이터 분석하기 - Excel&amp;middot;CSV 활용&lt;/b&gt; 입니다. 숫자 데이터를 Claude로 분석하고 차트까지 만드는 실전 방법을 다룹니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;마무리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이메일&amp;middot;보고서 작성에 Claude를 활용하는 핵심은:&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;관계와 맥락을 알려주기&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;핵심 메시지를 먼저 정하기&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;톤을 구체적으로 지정하기&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;대화형으로 다듬기&lt;/b&gt; (한 번에 완벽 노리지 말 것)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;최종 검토는 본인이&lt;/b&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 20개 프롬프트를 본인 상황에 맞게 저장해두면, 문서 작성 시간이 확실히 줄어듭니다. 특히 자주 쓰는 것 5개 정도는 Projects나 메모에 템플릿으로 저장하시길 권합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;본인이 자주 쓰는 이메일&amp;middot;보고서 유형이나 효과 좋았던 프롬프트가 있다면 댓글로 공유해주세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>AI (Claude 활용)/Claude 실무(활용)</category>
      <category>AI 이메일</category>
      <category>Claude 보고서</category>
      <category>Claude 보고서 쓰기</category>
      <category>Claude 실무</category>
      <category>Claude 실무활용</category>
      <category>Claude 이메일</category>
      <category>Claude 이메일 작성</category>
      <category>Claude 프롬프트</category>
      <category>보고서 AI</category>
      <category>소니스토리</category>
      <author>isony</author>
      <guid isPermaLink="true">https://isony.tistory.com/356</guid>
      <comments>https://isony.tistory.com/entry/Claude-%EC%8B%9C%EB%A6%AC%EC%A6%88-5%ED%8E%B8-Claude%EB%A1%9C-%EC%9D%B4%EB%A9%94%EC%9D%BC%C2%B7%EB%B3%B4%EA%B3%A0%EC%84%9C-%EC%93%B0%EA%B8%B0-%EC%A7%81%EC%9E%A5%EC%9D%B8-%EC%8B%A4%EC%A0%84-%ED%94%84%EB%A1%AC%ED%94%84%ED%8A%B8-20%EA%B0%9C-%EB%B3%B5%EC%82%AC%EB%B6%99%EC%97%AC%EB%84%A3%EA%B8%B0-%EA%B0%80%EB%8A%A5#entry356comment</comments>
      <pubDate>Mon, 20 Jul 2026 07:06:45 +0900</pubDate>
    </item>
    <item>
      <title>2026년07월19일 주일예배 (이재훈목사님) - 1부</title>
      <link>https://isony.tistory.com/entry/2026%EB%85%8407%EC%9B%9419%EC%9D%BC-%EC%A3%BC%EC%9D%BC%EC%98%88%EB%B0%B0-%EC%9D%B4%EC%9E%AC%ED%9B%88%EB%AA%A9%EC%82%AC%EB%8B%98-1%EB%B6%80</link>
      <description>&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;2026년07월19일 주일예배 (이재훈목사님) - 1부&lt;/h2&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;주의 말씀 : 나를 따르라&amp;nbsp; (10)&lt;/h2&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;곁에 계시던 분이 이제 안에 계십니다.&lt;/h2&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;성경 :&amp;nbsp; 요한복음 14:15 ~ 21 말씀 (출처:우리말성경)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&amp;lt; 성경 &amp;gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;14:15 너희가 나를 사랑한다면 내 계명을 지킬 것이다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;14:16 내가 아버지께 구할 것이니 아버지께서 너희에게 다른 보혜사를 보내셔서 너희와 영원히 함께 있도록 하실 것이다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;14:17 그분은 진리의 영이시다. 세상은 그분을 볼 수도 없고 알 수도 없기 때문에 그분을 받아들일 수가 없다. 그러나 너희는 그분을 안다. 그분이 너희와 함께 계시고 또 너희 안에 계실 것이기 때문이다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;14:18 나는 너희를 고아처럼 내버려 두지 않고 너희에게 다시 오겠다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;14:19 조금 있으면 세상은 나를 보지 못하겠지만 너희는 나를 볼 것이다. 내가 살아 있고 너희도 살 것이기 때문이다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;14:20 그날에 너희는 내가 내 아버지 안에 있고 너희가 내 안에 있으며 내가 너희 안에 있음을 알게 될 것이다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;14:21 누구든지 내 계명을 가지고 지키는 사람은 나를 사랑하는 사람이다. 나를 사랑하는 사람은 내 아버지의 사랑을 받을 것이고 나 또한 그 사람을 사랑하고 그 사람에게 나를 나타낼 것이다.&amp;rdquo;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&amp;lt; 예배 영상 &amp;gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;a href=&quot;https://youtu.be/77iitNso53M&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://youtu.be/77iitNso53M&lt;/a&gt;&lt;/b&gt;&lt;/p&gt;
&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignCenter&quot; data-video-host=&quot;youtube&quot; data-video-url=&quot;https://www.youtube.com/watch?v=77iitNso53M&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/fBw0N/dJMb8QMoZBK/wooNhcKkH7euCNpagVnQYk/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=574_138_744_324,https://scrap.kakaocdn.net/dn/js2py/dJMb8TCmENN/j93vktHEzvk2OBz1YD2rkk/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=574_138_744_324,https://scrap.kakaocdn.net/dn/hDxvw/dJMb8RR4IVO/DffAi2QSLZrxfGVfFiEXak/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=574_138_744_324&quot; data-video-width=&quot;860&quot; data-video-height=&quot;484&quot; data-video-origin-width=&quot;860&quot; data-video-origin-height=&quot;484&quot; data-ke-mobilestyle=&quot;widthContent&quot; data-video-title=&quot;주일예배2026 07 19&quot; data-original-url=&quot;&quot;&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/77iitNso53M&quot; width=&quot;860&quot; height=&quot;484&quot; frameborder=&quot;&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;figcaption style=&quot;display: none;&quot;&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1. 성령은 그리스도의 말씀을 생각나게 하십니다. (요한복음 14:26)&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2. 성령님은 하나님의 사랑을 부어 주시는 분입니다. (로마서 5:5)&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3. 성령님은 육체의 욕심을 이루지 않도록 능력을 주십니다. (갈라디아서 5:16, 갈라디아서 5:24-25)&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>성경과 QT/주일예배(온누리교회)</category>
      <category>CGNTV</category>
      <category>곁에 계시던 분</category>
      <category>나를 따르라</category>
      <category>로마서 5장</category>
      <category>소니스토리</category>
      <category>예배영상</category>
      <category>요한복음 14장</category>
      <category>우리말성경</category>
      <category>이재훈목사</category>
      <category>주일예배</category>
      <author>isony</author>
      <guid isPermaLink="true">https://isony.tistory.com/355</guid>
      <comments>https://isony.tistory.com/entry/2026%EB%85%8407%EC%9B%9419%EC%9D%BC-%EC%A3%BC%EC%9D%BC%EC%98%88%EB%B0%B0-%EC%9D%B4%EC%9E%AC%ED%9B%88%EB%AA%A9%EC%82%AC%EB%8B%98-1%EB%B6%80#entry355comment</comments>
      <pubDate>Sun, 19 Jul 2026 08:06:09 +0900</pubDate>
    </item>
    <item>
      <title>[Claude 시리즈 4편] Claude 프롬프트 잘 쓰는 법 - 실무자 관점 실전 팁 (XML 태그 활용법 포함)</title>
      <link>https://isony.tistory.com/entry/Claude-%EC%8B%9C%EB%A6%AC%EC%A6%88-4%ED%8E%B8-Claude-%ED%94%84%EB%A1%AC%ED%94%84%ED%8A%B8-%EC%9E%98-%EC%93%B0%EB%8A%94-%EB%B2%95-%EC%8B%A4%EB%AC%B4%EC%9E%90-%EA%B4%80%EC%A0%90-%EC%8B%A4%EC%A0%84-%ED%8C%81-XML-%ED%83%9C%EA%B7%B8-%ED%99%9C%EC%9A%A9%EB%B2%95-%ED%8F%AC%ED%95%A8</link>
      <description>&lt;h1&gt;[Claude 시리즈 4편] Claude 프롬프트 잘 쓰는 법 - 실무자 관점 실전 팁 (XML 태그 활용법 포함)&lt;/h1&gt;
&lt;h1&gt;&lt;b&gt;- 테스트 환경&lt;/b&gt;&lt;span style=&quot;color: #333333; font-size: 16px; letter-spacing: 0px;&quot;&gt;: Claude Sonnet 5 / Opus 4.8 (2026년 7월 기준)&lt;/span&gt;&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;같은 Claude를 쓰는데 어떤 사람은 &quot;그저 그렇다&quot;고 하고, 어떤 사람은 &quot;없으면 일을 못 한다&quot;고 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;차이는 &lt;b&gt;프롬프트&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프롬프트 엔지니어링이라고 하면 거창해 보이지만, 실무에서는 &lt;b&gt;몇 가지 원칙과 패턴만 알면 결과가 확 달라집니다&lt;/b&gt;. 특히 Claude는 &lt;b&gt;XML 태그를 인식하도록 훈련&lt;/b&gt;되어 있어서, 이 특성을 활용하면 다른 AI보다 훨씬 정밀한 제어가 가능합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글에서 다룰 내용입니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;좋은 프롬프트의 &lt;b&gt;5가지 원칙&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;★ Claude 고유의 XML 태그 활용법&lt;/b&gt; (다른 AI에는 없는 강점)&lt;/li&gt;
&lt;li&gt;실무자용 &lt;b&gt;프롬프트 패턴 10개&lt;/b&gt; (복붙 가능)&lt;/li&gt;
&lt;li&gt;실패 프롬프트 &lt;b&gt;Before/After 비교&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;프롬프트를 개선하는 3단계 방법&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글은 &lt;b&gt;&lt;u&gt;시리즈 1~3편&lt;/u&gt;&lt;/b&gt;의 마지막이자, &lt;b&gt;Phase 1(입문)의 완결편&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;바쁘신 분은 &lt;b&gt;&lt;u&gt;5가지 원칙&lt;/u&gt;&lt;/b&gt;부터 보세요.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;먼저: 프롬프트를 쓰기 전에 할 일&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 흔한 실수는 &lt;b&gt;성공 기준 없이 프롬프트부터 쓰는 것&lt;/b&gt;입니다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;❌ 나쁜 접근:
   일단 물어보고 &amp;rarr; 결과 보고 &amp;rarr; 마음에 안 들면 다시 물어보고 &amp;rarr; 반복

✅ 좋은 접근:
   1. 원하는 결과를 구체적으로 정의 (&quot;무엇이 성공인가&quot;)
   2. 그 결과를 얻을 프롬프트 작성
   3. 결과 평가 &amp;rarr; 프롬프트 개선
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;예시&lt;/b&gt;:&lt;/p&gt;
&lt;pre class=&quot;1c&quot;&gt;&lt;code&gt;막연함: &quot;회의록 정리해줘&quot;
성공 기준 있음: &quot;회의록에서 액션 아이템만 뽑아서, 
                 담당자와 기한이 명시된 표로 만들어줘.
                 결정되지 않은 사항은 별도 목록으로.&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;성공 기준이 명확하면 프롬프트는 자연스럽게 좋아집니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;좋은 프롬프트의 5가지 원칙&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;원칙 1: 구체적으로, 상세하게&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude는 &lt;b&gt;정보가 많을수록 정확&lt;/b&gt;합니다. 사람에게 일을 시킬 때처럼 배경을 설명하세요.&lt;/p&gt;
&lt;pre class=&quot;1c&quot;&gt;&lt;code&gt;❌ &quot;이 SQL 최적화해줘&quot;

✅ &quot;이 SQL을 최적화해주세요.

환경: Oracle 19c, 테이블 3천만 건
현재: 실행에 45초 소요
목표: 5초 이내
제약: 인덱스 추가는 가능, 테이블 구조 변경은 불가

[SQL 붙여넣기]&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;핵심&lt;/b&gt;: 환경, 현재 상태, 목표, 제약사항. 이 4가지를 주면 답변 품질이 확연히 달라집니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;원칙 2: 예시를 보여주세요 (Multishot)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;말로 설명하는 것보다 &lt;b&gt;예시 1~2개&lt;/b&gt;가 훨씬 효과적입니다.&lt;/p&gt;
&lt;pre class=&quot;markdown&quot;&gt;&lt;code&gt;다음 형식으로 에러 로그를 정리해주세요.

예시:
입력: &quot;ORA-12541: TNS:no listener&quot;
출력:
  - 에러: ORA-12541
  - 분류: 접속 에러
  - 우선순위: 높음
  - 첫 조치: lsnrctl status

이제 아래 로그를 같은 형식으로 정리해주세요.
[로그 붙여넣기]
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;고급 팁&lt;/b&gt;: 좋은 예시와 &lt;b&gt;나쁜 예시를 함께&lt;/b&gt; 주면 더 정확해집니다.&lt;/p&gt;
&lt;pre class=&quot;gcode&quot;&gt;&lt;code&gt;좋은 예: &quot;ORA-12541 발생 시 lsnrctl status로 리스너 상태 확인&quot;
나쁜 예: &quot;리스너 문제인 것 같습니다&quot; (모호함, 조치 없음)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;원칙 3: 단계별로 생각하게 하세요&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;복잡한 문제는 &lt;b&gt;사고 과정을 요청&lt;/b&gt;하면 결과가 크게 좋아집니다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;이 장애의 원인을 분석해주세요.

먼저 &amp;lt;thinking&amp;gt; 태그 안에서 단계별로 추론해주세요:
1. 증상에서 알 수 있는 것
2. 가능한 원인들
3. 각 원인의 가능성 평가

그 다음 &amp;lt;answer&amp;gt; 태그 안에 결론을 정리해주세요.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;왜 효과적인가&lt;/b&gt;: Claude가 답을 먼저 내고 근거를 붙이는 게 아니라, &lt;b&gt;근거를 쌓아서 답에 도달&lt;/b&gt;하게 됩니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;원칙 4: 출력 형식을 지정하세요&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원하는 형식을 명확히 말하지 않으면 Claude가 알아서 정합니다.&lt;/p&gt;
&lt;pre class=&quot;haml&quot;&gt;&lt;code&gt;❌ &quot;정리해줘&quot;

✅ &quot;다음 형식으로 정리해주세요:
   - 마크다운 표로
   - 컬럼: 원인 | 진단 방법 | 해결 방법 | 소요 시간
   - 우선순위 높은 순으로 정렬
   - 각 셀은 30자 이내&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;원칙 5: &quot;모르면 모른다고 해&quot; 명시&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이건 &lt;b&gt;환각(hallucination)을 줄이는 강력한 방법&lt;/b&gt;입니다.&lt;/p&gt;
&lt;pre class=&quot;prolog&quot;&gt;&lt;code&gt;아래 문서를 기반으로만 답변해주세요.
문서에 없는 내용은 &quot;문서에 명시되지 않음&quot;이라고 말해주세요.
추측하지 마세요.

[문서 붙여넣기]

질문: [질문]
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude는 원래 정직성이 높지만, 이렇게 명시하면 더 확실해집니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;★ Claude 고유의 XML 태그 활용법&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 부분이 다른 AI와의 &lt;b&gt;결정적 차이&lt;/b&gt;입니다. Claude는 훈련 과정에서 XML 태그를 인식하도록 학습되어 있습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;왜 XML 태그인가&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프롬프트가 길어지면 Claude가 &lt;b&gt;어디까지가 지시고 어디부터가 데이터인지&lt;/b&gt; 헷갈릴 수 있습니다. XML 태그는 이 경계를 명확히 합니다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;❌ 태그 없음 (경계 모호):
이 로그를 분석해줘 2026-07-01 10:23:45 ERROR ORA-04031
unable to allocate 4096 bytes 그리고 원인별로 정리해줘

✅ 태그 사용 (경계 명확):
&amp;lt;instructions&amp;gt;
아래 로그를 분석하고 원인별로 정리해주세요.
&amp;lt;/instructions&amp;gt;

&amp;lt;log&amp;gt;
2026-07-01 10:23:45 ERROR ORA-04031
unable to allocate 4096 bytes
&amp;lt;/log&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;자주 쓰는 태그 6가지&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;태그 용도&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&amp;lt;instructions&amp;gt;&lt;/td&gt;
&lt;td&gt;지시사항&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&amp;lt;context&amp;gt;&lt;/td&gt;
&lt;td&gt;배경 정보&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&amp;lt;data&amp;gt;&lt;/td&gt;
&lt;td&gt;분석할 데이터&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&amp;lt;examples&amp;gt;&lt;/td&gt;
&lt;td&gt;예시&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&amp;lt;thinking&amp;gt;&lt;/td&gt;
&lt;td&gt;사고 과정&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&amp;lt;answer&amp;gt;&lt;/td&gt;
&lt;td&gt;최종 답변&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;중요&lt;/b&gt;: 태그 이름은 &lt;b&gt;자유롭게 지어도 됩니다&lt;/b&gt;. &amp;lt;log&amp;gt;, &amp;lt;sql&amp;gt;, &amp;lt;meeting_notes&amp;gt; 같이 내용을 설명하는 이름이면 Claude가 이해합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;실전 XML 프롬프트 예시&lt;/h3&gt;
&lt;pre class=&quot;xml&quot;&gt;&lt;code&gt;&amp;lt;context&amp;gt;
저는 Oracle 19c 운영 DBA입니다.
환경: Oracle Linux 8, CDB/PDB 구성
운영 DB: PRODDB (24시간 무중단)
&amp;lt;/context&amp;gt;

&amp;lt;task&amp;gt;
아래 AWR 리포트에서 성능 병목을 찾아주세요.
&amp;lt;/task&amp;gt;

&amp;lt;awr_report&amp;gt;
[리포트 내용 붙여넣기]
&amp;lt;/awr_report&amp;gt;

&amp;lt;instructions&amp;gt;
1. &amp;lt;thinking&amp;gt; 태그에서 단계별로 분석
2. &amp;lt;answer&amp;gt; 태그에 다음 형식으로 결론:
   - 병목 TOP 3 (심각도 순)
   - 각각의 근거 (AWR 수치 인용)
   - 조치 방법 (운영 중 적용 가능 여부 명시)
&amp;lt;/instructions&amp;gt;

&amp;lt;constraints&amp;gt;
- 운영 DB 재시작 불가
- ALTER SYSTEM은 DBA 승인 필요
&amp;lt;/constraints&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 구조화하면 &lt;b&gt;복잡한 요청도 정확히 처리&lt;/b&gt;됩니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;★ 실무자용 프롬프트 패턴 10개&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;바로 복사해서 쓸 수 있는 패턴입니다. [대괄호] 부분만 본인 상황에 맞게 수정하세요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;패턴 1: 에러 진단&lt;/h3&gt;
&lt;pre class=&quot;xml&quot;&gt;&lt;code&gt;&amp;lt;context&amp;gt;
환경: [OS, DB 버전 등]
상황: [언제, 무엇을 하다가]
&amp;lt;/context&amp;gt;

&amp;lt;error&amp;gt;
[에러 메시지 전문]
&amp;lt;/error&amp;gt;

&amp;lt;instructions&amp;gt;
다음 순서로 답해주세요:
1. 가능성 높은 원인 3가지 (확률 순)
2. 각 원인의 진단 방법 (실행 가능한 명령어)
3. 원인별 해결 방법
4. 재발 방지 팁
&amp;lt;/instructions&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;패턴 2: 코드 리뷰&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;&amp;lt;code language=&quot;[언어]&quot;&amp;gt;
[코드 붙여넣기]
&amp;lt;/code&amp;gt;

&amp;lt;instructions&amp;gt;
다음 관점에서 리뷰해주세요:
1. 잠재적 버그
2. 성능 이슈
3. 보안 취약점
4. 가독성
5. 개선 제안 (수정 코드 포함)

각 지적사항에 심각도(높음/중간/낮음)를 표시해주세요.
&amp;lt;/instructions&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;패턴 3: 문서 요약&lt;/h3&gt;
&lt;pre class=&quot;dts&quot;&gt;&lt;code&gt;&amp;lt;document&amp;gt;
[문서 붙여넣기 또는 파일 첨부]
&amp;lt;/document&amp;gt;

&amp;lt;instructions&amp;gt;
다음 형식으로 요약해주세요:
- 핵심 3줄 요약
- 주요 쟁점 3가지
- 놓치기 쉬운 세부사항
- 추가 확인이 필요한 부분

문서에 없는 내용은 추측하지 말고 
&quot;문서에 명시되지 않음&quot;이라고 해주세요.
&amp;lt;/instructions&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;패턴 4: 이메일 초안 (톤 3종)&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;&amp;lt;situation&amp;gt;
[상황 설명: 누구에게, 왜, 어떤 관계]
&amp;lt;/situation&amp;gt;

&amp;lt;key_points&amp;gt;
- [전달할 핵심 1]
- [전달할 핵심 2]
&amp;lt;/key_points&amp;gt;

&amp;lt;instructions&amp;gt;
아래 3가지 톤으로 각각 작성해주세요:
1. 정중하되 단호한 톤
2. 친근하되 전문적인 톤
3. 격식 있는 공식 톤

각 200자 이내.
&amp;lt;/instructions&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;패턴 5: 데이터 분석&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;&amp;lt;data&amp;gt;
[CSV 또는 파일 첨부]
&amp;lt;/data&amp;gt;

&amp;lt;context&amp;gt;
이 데이터는 [출처, 기간, 의미]입니다.
&amp;lt;/context&amp;gt;

&amp;lt;instructions&amp;gt;
1. 데이터 개요 (행 수, 컬럼, 결측치)
2. 주요 패턴 3가지
3. 이상치나 특이사항
4. 시각화 (차트를 Artifact로)
5. 실행 가능한 인사이트
&amp;lt;/instructions&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;패턴 6: 비교 분석&lt;/h3&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;&amp;lt;options&amp;gt;
A: [옵션 A 설명]
B: [옵션 B 설명]
&amp;lt;/options&amp;gt;

&amp;lt;criteria&amp;gt;
- [평가 기준 1]
- [평가 기준 2]
- [평가 기준 3]
&amp;lt;/criteria&amp;gt;

&amp;lt;instructions&amp;gt;
1. 기준별 비교표
2. 각 옵션의 트레이드오프
3. 어떤 상황에 무엇이 맞는지
4. 제 상황([상황])에서의 추천과 근거
&amp;lt;/instructions&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;패턴 7: 스크립트 작성&lt;/h3&gt;
&lt;pre class=&quot;markdown&quot;&gt;&lt;code&gt;&amp;lt;requirements&amp;gt;
목적: [무엇을 하는 스크립트]
환경: [OS, 셸 버전]
입력: [무엇을 받나]
출력: [무엇을 만드나]
&amp;lt;/requirements&amp;gt;

&amp;lt;constraints&amp;gt;
- 에러 처리 필수
- 로그 기록 필수
- [기타 제약]
&amp;lt;/constraints&amp;gt;

&amp;lt;instructions&amp;gt;
1. 스크립트 작성 (주석 포함)
2. 사용법 설명
3. 테스트 방법
4. 주의사항
&amp;lt;/instructions&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;패턴 8: 회의록 정리&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;&amp;lt;meeting_notes&amp;gt;
[회의록 붙여넣기]
&amp;lt;/meeting_notes&amp;gt;

&amp;lt;instructions&amp;gt;
다음 3가지로 분리해주세요:

1. 결정 사항 (확정된 것만)
2. 액션 아이템 (표: 담당자 | 내용 | 기한)
3. 미결 사항 (다음 회의 안건)

논의만 되고 결정 안 된 것은 
1번이 아니라 3번으로 분류해주세요.
&amp;lt;/instructions&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;패턴 9: 학습&amp;middot;이해&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;&amp;lt;material&amp;gt;
[학습할 문서/논문/코드]
&amp;lt;/material&amp;gt;

&amp;lt;my_background&amp;gt;
저는 [배경, 알고 있는 것, 모르는 것]
&amp;lt;/my_background&amp;gt;

&amp;lt;instructions&amp;gt;
1. 핵심 개념 5개 (제 배경 수준에 맞춰 설명)
2. 실무 적용 인사이트 3가지
3. 제가 더 공부해야 할 선행 지식
4. 이해했는지 확인할 질문 3개
&amp;lt;/instructions&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;패턴 10: 문제 해결 프레임워크&lt;/h3&gt;
&lt;pre class=&quot;xml&quot;&gt;&lt;code&gt;&amp;lt;problem&amp;gt;
[문제 상황 상세히]
&amp;lt;/problem&amp;gt;

&amp;lt;what_i_tried&amp;gt;
- [시도 1] &amp;rarr; [결과]
- [시도 2] &amp;rarr; [결과]
&amp;lt;/what_i_tried&amp;gt;

&amp;lt;constraints&amp;gt;
[시간, 예산, 기술적 제약]
&amp;lt;/constraints&amp;gt;

&amp;lt;instructions&amp;gt;
&amp;lt;thinking&amp;gt; 태그에서 단계별로 분석한 후,
&amp;lt;answer&amp;gt; 태그에 다음을 정리해주세요:
1. 문제의 근본 원인 가설
2. 검증 방법
3. 해결 방안 3가지 (난이도/효과 표시)
4. 추천 순서
&amp;lt;/instructions&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Before / After - 실패 프롬프트 고치기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제로 자주 보는 실패 사례와 개선 버전입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;사례 1: 너무 막연함&lt;/h3&gt;
&lt;pre class=&quot;dts&quot;&gt;&lt;code&gt;❌ Before:
&quot;DB 느린데 어떻게 해?&quot;

✅ After:
&amp;lt;context&amp;gt;
Oracle 19c, 테이블 5천만 건
&amp;lt;/context&amp;gt;

&amp;lt;symptom&amp;gt;
특정 조회 쿼리가 평소 2초 &amp;rarr; 현재 40초
어제 오후부터 발생
다른 쿼리는 정상
&amp;lt;/symptom&amp;gt;

&amp;lt;what_i_checked&amp;gt;
- CPU/메모리: 정상
- 통계 정보: 3일 전 수집
&amp;lt;/what_i_checked&amp;gt;

&amp;lt;instructions&amp;gt;
가능성 높은 원인 3가지와 각각의 진단 SQL을 알려주세요.
&amp;lt;/instructions&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;결과 차이&lt;/b&gt;: Before는 일반론, After는 본인 상황에 맞는 진단 SQL.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;사례 2: 출력 형식 미지정&lt;/h3&gt;
&lt;pre class=&quot;1c&quot;&gt;&lt;code&gt;❌ Before:
&quot;이 에러들 정리해줘&quot;
&amp;rarr; Claude가 알아서 산문으로 정리 (활용하기 어려움)

✅ After:
&quot;이 에러들을 마크다운 표로 정리해주세요.
컬럼: 시각 | 에러코드 | 심각도 | 첫 조치
심각도 높은 순 정렬&quot;
&amp;rarr; 바로 보고서에 붙여넣을 수 있는 표
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;사례 3: 검증 없이 신뢰&lt;/h3&gt;
&lt;pre class=&quot;markdown&quot;&gt;&lt;code&gt;❌ Before:
&quot;운영 DB에서 이 작업 하는 SQL 줘&quot;
&amp;rarr; 받은 SQL을 바로 실행 (위험)

✅ After:
&quot;운영 DB에서 이 작업을 하려고 합니다.

&amp;lt;instructions&amp;gt;
1. 실행할 SQL
2. 이 SQL의 영향 범위
3. 롤백 SQL
4. 테스트 환경 검증 방법
5. 주의사항
&amp;lt;/instructions&amp;gt;&quot;
&amp;rarr; 안전하게 검증 후 적용
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;프롬프트 개선 3단계&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한 번에 완벽한 프롬프트는 없습니다. 개선하는 방법입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1단계: 결과 평가&lt;/h3&gt;
&lt;pre class=&quot;markdown&quot;&gt;&lt;code&gt;&amp;gt; 방금 답변을 스스로 평가해주세요.
  제 요청 대비 부족한 부분이 무엇인가요?
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude에게 자기 답변을 평가시키면 개선점이 나옵니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2단계: 프롬프트 개선 요청&lt;/h3&gt;
&lt;pre class=&quot;prolog&quot;&gt;&lt;code&gt;&amp;gt; 제가 쓴 프롬프트를 개선해주세요.
  어떤 정보가 더 있으면 좋은 답변이 나올까요?
  
  제 프롬프트:
  [원본 붙여넣기]
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3단계: 템플릿화&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;잘 작동한 프롬프트는 &lt;b&gt;템플릿으로 저장&lt;/b&gt;하세요.&lt;/p&gt;
&lt;pre class=&quot;asciidoc&quot;&gt;&lt;code&gt;저장 위치 옵션:
- Projects의 Custom instructions
- 메모 앱에 프롬프트 모음
- Claude Code라면 CLAUDE.md
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;팁&lt;/b&gt;: 자주 쓰는 프롬프트 5~10개를 템플릿으로 만들어두면 매번 새로 쓰는 시간이 사라집니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;자주 하는 실수 5가지&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;실수 1: 한 프롬프트에 너무 많은 요청&lt;/h3&gt;
&lt;pre class=&quot;gcode&quot;&gt;&lt;code&gt;❌ &quot;이 코드 리뷰하고 리팩터링하고 테스트 짜고 문서화해줘&quot;
✅ 하나씩 나눠서 요청 (품질이 훨씬 좋아짐)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;실수 2: 부정 표현만 사용&lt;/h3&gt;
&lt;pre class=&quot;1c&quot;&gt;&lt;code&gt;❌ &quot;장황하게 쓰지 마&quot;
✅ &quot;각 항목을 2줄 이내로 간결하게&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;원하는 것&lt;/b&gt;을 말하는 게 &lt;b&gt;원하지 않는 것&lt;/b&gt;을 말하는 것보다 효과적입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;실수 3: 컨텍스트 없이 이어서 질문&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;새 대화창에서 &quot;아까 그거 말인데...&quot;는 통하지 않습니다. Memory나 Projects를 쓰거나, 컨텍스트를 다시 주세요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;실수 4: 예시 없이 형식만 설명&lt;/h3&gt;
&lt;pre class=&quot;lsl&quot;&gt;&lt;code&gt;❌ &quot;표 형식으로 정리해줘&quot;
✅ 원하는 표의 예시를 1줄이라도 보여주기
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;실수 5: 첫 답변에서 포기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫 답변이 마음에 안 들면 &lt;b&gt;&quot;이 부분을 이렇게 바꿔줘&quot;&lt;/b&gt; 라고 이어가세요. 대화형으로 다듬는 게 처음부터 완벽한 프롬프트를 쓰는 것보다 빠릅니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Phase 1 마무리 - 지금까지 배운 것&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글로 &lt;b&gt;Phase 1(입문)이 완결&lt;/b&gt;되었습니다. 4편을 통해 다룬 내용을 정리하면:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;편 핵심&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;1편&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;Claude는 Constitutional AI 기반의 안전&amp;middot;정직 중심 AI&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;2편&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;95% 사용자는 Pro가 정답, 업그레이드 신호 5가지&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;3편&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;5분 세팅 + Projects가 게임 체인저&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;4편&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;XML 태그 + 5가지 원칙 + 패턴 10개&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 4가지를 익히셨다면 &lt;b&gt;Claude를 도구가 아니라 동료로 쓰실 수 있는 수준&lt;/b&gt;입니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;마무리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프롬프트 엔지니어링의 핵심을 다시 정리하면:&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;성공 기준을 먼저 정의&lt;/b&gt; &amp;mdash; 무엇이 좋은 결과인가&lt;/li&gt;
&lt;li&gt;&lt;b&gt;구체적으로, 상세하게&lt;/b&gt; &amp;mdash; 환경, 현재, 목표, 제약&lt;/li&gt;
&lt;li&gt;&lt;b&gt;★ XML 태그 활용&lt;/b&gt; &amp;mdash; Claude 고유의 강점&lt;/li&gt;
&lt;li&gt;&lt;b&gt;예시를 보여주기&lt;/b&gt; &amp;mdash; 설명보다 예시 1개가 강력&lt;/li&gt;
&lt;li&gt;&lt;b&gt;템플릿화&lt;/b&gt; &amp;mdash; 잘 된 프롬프트는 재사용&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 중요한 것은 &lt;b&gt;완벽한 프롬프트를 처음부터 쓰려고 하지 않는 것&lt;/b&gt;입니다. 대화형으로 다듬어가는 게 훨씬 빠르고, 그 과정에서 본인만의 패턴입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;본인이 자주 쓰는 프롬프트 패턴이나, 효과가 좋았던 표현이 있다면 서로 공유해 사용하는것도 좋겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;공식 링크&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.claude.com/en/docs/build-with-claude/prompt-engineering/overview&quot;&gt;Anthropic 프롬프트 엔지니어링 가이드&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.claude.com/en/resources/prompt-library/library&quot;&gt;Anthropic 프롬프트 라이브러리&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>AI (Claude 활용)/Claude 입문</category>
      <category>Claude Code 프롬프트</category>
      <category>Claude thinking 태그</category>
      <category>Claude XML 태그</category>
      <category>Claude 프롬프트</category>
      <category>Claude 프롬프트 예시</category>
      <category>Claude 프롬프트 작성법</category>
      <category>소니스토리</category>
      <category>에러 진단 프롬프트</category>
      <category>프롬프트 엔지니어링</category>
      <category>회의록정리 프롬프트</category>
      <author>isony</author>
      <guid isPermaLink="true">https://isony.tistory.com/354</guid>
      <comments>https://isony.tistory.com/entry/Claude-%EC%8B%9C%EB%A6%AC%EC%A6%88-4%ED%8E%B8-Claude-%ED%94%84%EB%A1%AC%ED%94%84%ED%8A%B8-%EC%9E%98-%EC%93%B0%EB%8A%94-%EB%B2%95-%EC%8B%A4%EB%AC%B4%EC%9E%90-%EA%B4%80%EC%A0%90-%EC%8B%A4%EC%A0%84-%ED%8C%81-XML-%ED%83%9C%EA%B7%B8-%ED%99%9C%EC%9A%A9%EB%B2%95-%ED%8F%AC%ED%95%A8#entry354comment</comments>
      <pubDate>Fri, 17 Jul 2026 06:52:16 +0900</pubDate>
    </item>
    <item>
      <title>[Claude 시리즈 3편] Claude 처음 사용법 완벽 가이드 - 5분 안에 마스터하는 7가지 기능</title>
      <link>https://isony.tistory.com/entry/Claude-%EC%8B%9C%EB%A6%AC%EC%A6%88-3%ED%8E%B8-Claude-%EC%B2%98%EC%9D%8C-%EC%82%AC%EC%9A%A9%EB%B2%95-%EC%99%84%EB%B2%BD-%EA%B0%80%EC%9D%B4%EB%93%9C-5%EB%B6%84-%EC%95%88%EC%97%90-%EB%A7%88%EC%8A%A4%ED%84%B0%ED%95%98%EB%8A%94-7%EA%B0%80%EC%A7%80-%EA%B8%B0%EB%8A%A5</link>
      <description>&lt;h1&gt;[Claude 시리즈 3편] Claude 처음 사용법 완벽 가이드 - 5분 안에 마스터하는 7가지 기능&lt;/h1&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;테스트 환경&lt;/b&gt;: Claude Sonnet 5 / Opus 4.8 (2026년 7월 기준)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude 계정을 만들고 대화창을 열었습니다. 그런데 &lt;b&gt;&quot;이제 뭘 해야 하지?&quot;&lt;/b&gt; 싶습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대부분의 사람이 여기서 ChatGPT처럼 질문 몇 개 던져보고 &quot;비슷하네&quot; 하고 끝냅니다. &lt;b&gt;Claude의 진짜 힘은 대화창 밖에 있는데&lt;/b&gt; 그걸 모르고 지나갑니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글에서는 다음을 다룹니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;계정 만들기 실전 (한국 사용자 기준)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;첫 5분 안에 반드시 켜야 할 설정 5가지&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;알아야 할 핵심 기능 7가지 (Projects, Artifacts, Memory 등)&lt;/li&gt;
&lt;li&gt;초보자가 자주 하는 실수 5가지&lt;/li&gt;
&lt;li&gt;첫 주 사용 로드맵&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글은 &lt;a href=&quot;https://www.whodo.net/entry/Claude-%EC%8B%9C%EB%A6%AC%EC%A6%88-1%ED%8E%B8-Claude%EA%B0%80-%EB%AD%90%EA%B3%A0-%EC%99%9C-%EC%8D%A8%EC%95%BC-%ED%95%A0%EA%B9%8C-ChatGPT%EC%99%80%EC%9D%98-%EC%A7%84%EC%A7%9C-%EC%B0%A8%EC%9D%B4-%EC%8B%A4%EB%AC%B4%EC%9E%90-%EA%B4%80%EC%A0%90&quot;&gt;시리즈 1편(Claude란)&lt;/a&gt;, &lt;a href=&quot;https://www.whodo.net/entry/Claude-%EC%8B%9C%EB%A6%AC%EC%A6%88-2%ED%8E%B8-Claude-%EB%AC%B4%EB%A3%8C-vs-%EC%9C%A0%EB%A3%8C-Pro-Max-Team-%EC%96%B4%EB%96%A4-%EA%B1%B8-%EC%8D%A8%EC%95%BC-%ED%95%A0%EA%B9%8C-2026-%EC%8B%A4%EC%A0%84-%EA%B2%B0%EC%A0%95-%EA%B0%80%EC%9D%B4%EB%93%9C&quot;&gt;2편(플랜 선택)&lt;/a&gt;의 후속입니다. Claude를 이미 결제하셨거나 무료로 시작하신 분들이 &lt;b&gt;실제로 잘 쓰는 법&lt;/b&gt;을 다룹니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;바쁘신 분은 &lt;u&gt;&lt;b&gt;5분 세팅&lt;/b&gt;&lt;/u&gt;부터 보세요.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;계정 만들기 (3분)&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Step 1: 가입&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;1. https://claude.ai 접속
2. &quot;Continue with Google&quot; 또는 이메일 입력
3. 이메일 인증 코드 입력
4. 전화번호 인증 (한국 번호 정상 지원)
5. 이름과 사용 목적 입력
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전화번호 인증은 어뷰징 방지용이며 한국 번호(+82)가 정상 작동합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Step 2: 앱 설치 (선택이지만 권장)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;플랫폼 특징 추천도&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;웹 (claude.ai)&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;모든 기능 사용 가능, 기본&lt;/td&gt;
&lt;td&gt;★★★★★&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;데스크톱 앱&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;Cowork 사용, 로컬 파일 접근&lt;/td&gt;
&lt;td&gt;★★★★☆&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;iOS / Android&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;이동 중 사용, 음성 입력&lt;/td&gt;
&lt;td&gt;★★★☆☆&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;중요&lt;/b&gt;: iOS 앱에서 결제하면 약 30% 마크업이 붙습니다. &lt;b&gt;결제는 반드시 웹에서&lt;/b&gt; 하고 앱은 로그인만 하세요.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;★ 5분 세팅 - 지금 바로 켜야 할 설정 5가지&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 부분이 이 글의 핵심입니다. 대부분의 사용자가 기본 설정 그대로 쓰다가 Claude의 절반도 활용 못 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Settings &amp;rarr; Capabilities로 이동해서 다음을 켜세요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. Memory (기억) ★★★★★&lt;/h3&gt;
&lt;pre class=&quot;stata&quot;&gt;&lt;code&gt;Settings &amp;rarr; Capabilities &amp;rarr; Memory &amp;rarr; ON
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude가 대화 사이에 본인의 이름, 직무, 선호 스타일을 기억합니다. 2026년 3월부터 &lt;b&gt;무료 tier에도 제공&lt;/b&gt;됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;왜 중요한가&lt;/b&gt;: 매번 &quot;저는 Oracle DBA인데요...&quot;를 설명할 필요가 없어집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;투명성&lt;/b&gt;: 저장된 모든 기억을 조회&amp;middot;편집&amp;middot;삭제할 수 있습니다. 언제든 확인하세요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. Search and reference chats (과거 대화 검색) ★★★★☆&lt;/h3&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;Settings &amp;rarr; Capabilities &amp;rarr; Search chats &amp;rarr; ON
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;지난주에 논의한 배치 스크립트 얘기 찾아줘&quot; 같은 요청이 가능해집니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. Artifacts (산출물 패널) ★★★★★&lt;/h3&gt;
&lt;pre class=&quot;apache&quot;&gt;&lt;code&gt;Settings &amp;rarr; Capabilities &amp;rarr; Artifacts &amp;rarr; ON
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드, 문서, 차트를 &lt;b&gt;별도 패널에 렌더링&lt;/b&gt;해서 보여줍니다. Claude의 가장 강력한 기능 중 하나입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4. Web search (웹 검색) ★★★★☆&lt;/h3&gt;
&lt;pre class=&quot;coq&quot;&gt;&lt;code&gt;대화창 하단 + 버튼 &amp;rarr; Web Search 토글
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최신 정보가 필요할 때 켜세요. 기본적으로 Claude는 학습 시점까지의 지식만 갖고 있습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5. Code execution &amp;amp; File creation (코드 실행&amp;middot;파일 생성) ★★★★☆&lt;/h3&gt;
&lt;pre class=&quot;apache&quot;&gt;&lt;code&gt;Settings &amp;rarr; Capabilities &amp;rarr; Code execution &amp;rarr; ON
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude가 실제로 Python을 실행하고 Word, Excel, PDF 파일을 만들어줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;5분이면 다 켭니다.&lt;/b&gt; 이 5가지만 켜도 Claude 활용도가 2~3배 올라갑니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;★ 알아야 할 핵심 기능 7가지&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;기능 1: Projects (프로젝트) &amp;mdash; 가장 중요&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;무엇인가&lt;/b&gt;: 관련 대화를 하나의 작업 공간으로 묶고, &lt;b&gt;공유 파일과 지침&lt;/b&gt;을 설정하는 기능.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;설정 방법&lt;/b&gt;:&lt;/p&gt;
&lt;pre class=&quot;markdown&quot;&gt;&lt;code&gt;1. 좌측 사이드바 &amp;rarr; Projects &amp;rarr; Create Project
2. 프로젝트 이름 입력 (예: &quot;Oracle 운영 문서&quot;)
3. Project knowledge에 파일 업로드
   - 사내 표준 문서
   - 자주 쓰는 스크립트
   - 아키텍처 설명서
4. Custom instructions 작성
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Custom instructions 예시 (DBA용)&lt;/b&gt;:&lt;/p&gt;
&lt;pre class=&quot;asciidoc&quot;&gt;&lt;code&gt;저는 Oracle 19c 운영 환경의 DBA입니다.

환경:
- OS: Oracle Linux 8
- DB: PRODDB (운영), TESTDB (테스트)
- 멀티테넌트 사용 (CDB/PDB)

응답 규칙:
- SQL 키워드는 대문자, 객체명은 소문자
- 운영 DB 변경 시 반드시 ROLLBACK SQL도 함께 제시
- 위험한 명령어는 실행 전 영향 범위 설명
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 설정하면 &lt;b&gt;프로젝트 내 모든 대화에 자동 적용&lt;/b&gt;됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;왜 강력한가&lt;/b&gt;: 매번 환경 설명을 반복할 필요가 없고, 답변이 본인 환경에 맞춰집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;참고&lt;/b&gt;: Projects는 무료 tier에서도 사용 가능합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;기능 2: Artifacts (산출물)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;무엇인가&lt;/b&gt;: Claude가 만든 코드&amp;middot;문서&amp;middot;차트를 &lt;b&gt;대화창 옆 패널에 실제로 렌더링&lt;/b&gt;하는 기능.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;지원 형식&lt;/b&gt;:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;HTML / CSS / JavaScript (실제 동작하는 웹 페이지)&lt;/li&gt;
&lt;li&gt;React 컴포넌트&lt;/li&gt;
&lt;li&gt;SVG 다이어그램&lt;/li&gt;
&lt;li&gt;Mermaid 플로우차트&lt;/li&gt;
&lt;li&gt;Markdown 문서&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;해보기&lt;/b&gt;:&lt;/p&gt;
&lt;pre class=&quot;shell&quot;&gt;&lt;code&gt;&amp;gt; Oracle CDB/PDB 구조를 SVG 다이어그램으로 그려줘.
  CDB$ROOT, PDB$SEED, 사용자 PDB 2개를 포함해서.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우측 패널에 실제 다이어그램이 그려집니다. 수정 요청도 대화로 가능합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;한계&lt;/b&gt;: 서버 사이드 코드는 실행 안 됩니다. 외부 네트워크 요청도 제한됩니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;기능 3: Memory (기억)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Projects와의 차이&lt;/b&gt;가 헷갈리기 쉬운데 명확합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;항목 Memory Projects&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;대상&lt;/td&gt;
&lt;td&gt;&lt;b&gt;나 자신&lt;/b&gt; (이름, 직무, 선호)&lt;/td&gt;
&lt;td&gt;&lt;b&gt;특정 작업&lt;/b&gt; (파일, 지침)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;생성&lt;/td&gt;
&lt;td&gt;대화에서 자동 추출&lt;/td&gt;
&lt;td&gt;직접 설정&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;범위&lt;/td&gt;
&lt;td&gt;모든 대화에 적용&lt;/td&gt;
&lt;td&gt;해당 프로젝트만&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;예시&lt;/td&gt;
&lt;td&gt;&quot;이 사람은 DBA다&quot;&lt;/td&gt;
&lt;td&gt;&quot;이 프로젝트는 Oracle 19c다&quot;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;수동으로 기억시키기&lt;/b&gt;:&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;&amp;gt; 나는 15년차 Oracle DBA이고, 
  Oracle Linux 8 환경에서 19c를 운영한다는 걸 기억해줘.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;기억 확인&amp;middot;삭제&lt;/b&gt;:&lt;/p&gt;
&lt;pre class=&quot;stata&quot;&gt;&lt;code&gt;Settings &amp;rarr; Capabilities &amp;rarr; Memory &amp;rarr; View memories
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;기능 4: Styles (스타일)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;무엇인가&lt;/b&gt;: Claude의 글쓰기 톤을 커스터마이징하는 기능.&lt;/p&gt;
&lt;pre class=&quot;asciidoc&quot;&gt;&lt;code&gt;대화창 하단 &amp;rarr; Style 선택
- Normal (기본)
- Concise (간결)
- Explanatory (설명형)
- Formal (격식)
- Custom (직접 만들기)
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Custom Style 만들기&lt;/b&gt;: 본인이 쓴 글 몇 편을 업로드하면 Claude가 그 스타일을 학습합니다. 블로그 운영자에게 특히 유용합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;기능 5: Extended Thinking (확장 사고)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;무엇인가&lt;/b&gt;: 복잡한 문제에 대해 Claude가 &lt;b&gt;더 오래 생각하도록&lt;/b&gt; 하는 기능.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;언제 켜나&lt;/b&gt;:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;복잡한 아키텍처 설계&lt;/li&gt;
&lt;li&gt;다단계 논리 추론&lt;/li&gt;
&lt;li&gt;어려운 디버깅&lt;/li&gt;
&lt;li&gt;수학&amp;middot;과학 문제&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;언제 끄나&lt;/b&gt;:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;단순 질문&lt;/li&gt;
&lt;li&gt;빠른 답변 필요&lt;/li&gt;
&lt;li&gt;사용량 절약 필요 (토큰 더 씀)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;기능 6: 파일 업로드와 분석&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude는 다양한 파일을 직접 읽습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파일 형식 가능 여부 활용 예&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;PDF&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;계약서, 논문 분석&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Word (.docx)&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;문서 검토&amp;middot;편집&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Excel (.xlsx)&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;데이터 분석&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CSV&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;통계 처리&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;이미지 (PNG/JPG)&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;스크린샷, 에러 화면&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;코드 파일&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;리뷰, 리팩터링&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;실무 팁&lt;/b&gt;: 에러 화면을 스크린샷으로 찍어서 그냥 붙여넣으세요. Claude가 읽고 분석합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;기능 7: Connectors (연동)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Google Drive, Gmail, Google Calendar 같은 외부 서비스와 연결합니다.&lt;/p&gt;
&lt;pre class=&quot;nginx&quot;&gt;&lt;code&gt;Settings &amp;rarr; Connectors &amp;rarr; 원하는 서비스 연결
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;연결하면 &quot;내 드라이브에서 지난달 보고서 찾아줘&quot; 같은 요청이 가능합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;첫 주 사용 로드맵&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;무엇부터 해야 할지 막막하다면 이 순서를 따라 해보세요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Day 1: 설정과 첫 대화&lt;/h3&gt;
&lt;pre class=&quot;less&quot;&gt;&lt;code&gt;[ ] 5분 세팅 완료 (Memory, Artifacts, Web search 등)
[ ] Memory에 본인 소개 입력
[ ] 간단한 질문 3개 던져보기
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Day 2: 파일 업로드 체험&lt;/h3&gt;
&lt;pre class=&quot;cs&quot;&gt;&lt;code&gt;[ ] 업무 문서 하나 업로드 &amp;rarr; 요약 요청
[ ] 에러 스크린샷 업로드 &amp;rarr; 원인 분석 요청
[ ] Excel 파일 업로드 &amp;rarr; 데이터 분석 요청
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Day 3: Artifacts 체험&lt;/h3&gt;
&lt;pre class=&quot;cs&quot;&gt;&lt;code&gt;[ ] 다이어그램 하나 그려달라고 요청
[ ] 간단한 HTML 페이지 만들어달라고 요청
[ ] 결과물 수정 요청해보기
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Day 4~5: Projects 구축&lt;/h3&gt;
&lt;pre class=&quot;cs&quot;&gt;&lt;code&gt;[ ] 본인 업무 영역으로 Project 1개 생성
[ ] 자주 쓰는 문서 3개 업로드
[ ] Custom instructions 작성
[ ] 프로젝트 안에서 대화해보고 차이 체감
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Day 6~7: 반복 업무 자동화&lt;/h3&gt;
&lt;pre class=&quot;cs&quot;&gt;&lt;code&gt;[ ] 매일 하는 작업 1가지 선정
[ ] 그 작업용 프롬프트 템플릿 만들기
[ ] 실제로 써보고 시간 절약 측정
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1주일이면 Claude가 도구에서 동료로 바뀝니다.&lt;/b&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;★ 초보자가 자주 하는 실수 5가지&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;실수 1: ChatGPT처럼만 쓰기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;증상&lt;/b&gt;: 대화창에 질문만 던지고 끝. Projects, Artifacts 안 씀.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;해결&lt;/b&gt;: 위의 7가지 기능을 하나씩 체험. 특히 &lt;b&gt;Projects&lt;/b&gt;가 게임 체인저입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;실수 2: 컨텍스트 없이 질문&lt;/h3&gt;
&lt;pre class=&quot;1c&quot;&gt;&lt;code&gt;❌ &quot;이 에러 어떻게 고쳐?&quot;
✅ &quot;Oracle 19c, Oracle Linux 8 환경입니다. 
   배치 작업 중 ORA-01555가 발생했습니다.
   에러 전문: [붙여넣기]
   UNDO 설정: [현재 값]&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude는 정보가 많을수록 정확해집니다. &lt;b&gt;환경, 배경, 제약사항&lt;/b&gt;을 함께 주세요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;실수 3: 한 대화창에 모든 걸 몰아넣기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;증상&lt;/b&gt;: 하나의 대화가 100 메시지 넘게 이어짐. 응답이 느려지고 사용량이 폭증.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;해결&lt;/b&gt;: &lt;b&gt;주제가 바뀌면 새 대화를 시작&lt;/b&gt;하세요. 대화가 길어질수록 매번 전체 히스토리를 다시 읽으므로 토큰을 많이 씁니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;실수 4: 검증 없이 그대로 사용&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;증상&lt;/b&gt;: Claude가 준 SQL이나 명령어를 운영 환경에 바로 실행.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;해결&lt;/b&gt;: &lt;b&gt;반드시 테스트 환경에서 검증&lt;/b&gt;하세요. Claude는 정확도가 높지만 본인 환경의 모든 조건을 알지 못합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;실수 5: 학습 옵트아웃 안 함&lt;/h3&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;Settings &amp;rarr; Privacy &amp;rarr; Data usage &amp;rarr; OFF
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본 설정에서 대화가 모델 개선에 활용될 수 있습니다. 업무용으로 쓴다면 반드시 확인하세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;그리고 어떤 설정이든 상관없이&lt;/b&gt;: 주민번호, 카드번호, 회사 기밀은 절대 입력 금지.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;실전 프롬프트 템플릿 3개&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;바로 복사해서 쓸 수 있는 템플릿입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;템플릿 1: 문서 분석&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;아래 문서를 분석해주세요.

[파일 첨부 또는 텍스트]

다음 형식으로 정리해주세요:
1. 핵심 내용 3줄 요약
2. 주요 쟁점 3가지
3. 놓치기 쉬운 세부사항
4. 추가 확인이 필요한 부분
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;템플릿 2: 에러 진단&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;다음 에러를 진단해주세요.

환경: [OS, 버전, DB 등]
상황: [언제, 무엇을 하다가]
에러 전문:
[에러 메시지 붙여넣기]

다음 순서로 답해주세요:
1. 가능성 높은 원인 3가지 (확률 순)
2. 각 원인의 진단 방법 (실행 가능한 명령어)
3. 원인별 해결 방법
4. 재발 방지 팁
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;템플릿 3: 문서 작성&lt;/h3&gt;
&lt;pre class=&quot;prolog&quot;&gt;&lt;code&gt;[주제]에 대한 [문서 종류]를 작성해주세요.

대상 독자: [누구]
목적: [무엇을 달성]
톤: [격식/친근/기술적]
분량: [길이]
반드시 포함할 것: [핵심 내용]
피해야 할 것: [금지 사항]
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;다음 글 예고&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 시리즈의 다음 글은 &lt;b&gt;[Claude 시리즈 4편] Claude 프롬프트 잘 쓰는 법 - 실무자 관점 실전 팁&lt;/b&gt; 입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 글에서 다룰 내용:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;좋은 프롬프트의 5가지 원칙&lt;/li&gt;
&lt;li&gt;실무자용 프롬프트 패턴 10개&lt;/li&gt;
&lt;li&gt;프롬프트를 개선하는 3단계 방법&lt;/li&gt;
&lt;li&gt;자주 실패하는 프롬프트와 수정법&lt;/li&gt;
&lt;li&gt;Claude 특유의 프롬프트 팁&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;마무리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude를 잘 쓰는 핵심을 다시 정리하면:&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;5분 세팅 먼저&lt;/b&gt; &amp;mdash; Memory, Artifacts, Web search는 필수&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Projects가 게임 체인저&lt;/b&gt; &amp;mdash; 매번 설명하는 시간이 사라집니다&lt;/li&gt;
&lt;li&gt;&lt;b&gt;컨텍스트를 충분히&lt;/b&gt; &amp;mdash; 환경, 배경, 제약을 함께 제공&lt;/li&gt;
&lt;li&gt;&lt;b&gt;주제 바뀌면 새 대화&lt;/b&gt; &amp;mdash; 사용량 절약과 품질 향상&lt;/li&gt;
&lt;li&gt;&lt;b&gt;검증은 본인 몫&lt;/b&gt; &amp;mdash; 특히 운영 환경 명령어&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 흔한 실수는 &lt;b&gt;&quot;ChatGPT처럼만 쓰는 것&quot;&lt;/b&gt; 입니다. Claude의 진짜 가치는 Projects와 Artifacts에 있습니다. 오늘 5분만 투자해서 설정을 마치고, 이번 주에 Project 하나만 만들어보세요. 확실히 다른 경험을 하실 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude를 쓰면서 발견한 팁이나 막히는 부분이 있다면 댓글로 공유해주세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>AI (Claude 활용)/Claude 입문</category>
      <category>Claude AI 사용법</category>
      <category>Claude Artifacts 뭐야</category>
      <category>Claude Excel 분석</category>
      <category>Claude Memory 설정</category>
      <category>Claude Styles 기능</category>
      <category>Claude 가입방법</category>
      <category>claude 사용법</category>
      <category>Claude 설정추천</category>
      <category>Claude 파일 업로드</category>
      <category>소니스토리</category>
      <author>isony</author>
      <guid isPermaLink="true">https://isony.tistory.com/353</guid>
      <comments>https://isony.tistory.com/entry/Claude-%EC%8B%9C%EB%A6%AC%EC%A6%88-3%ED%8E%B8-Claude-%EC%B2%98%EC%9D%8C-%EC%82%AC%EC%9A%A9%EB%B2%95-%EC%99%84%EB%B2%BD-%EA%B0%80%EC%9D%B4%EB%93%9C-5%EB%B6%84-%EC%95%88%EC%97%90-%EB%A7%88%EC%8A%A4%ED%84%B0%ED%95%98%EB%8A%94-7%EA%B0%80%EC%A7%80-%EA%B8%B0%EB%8A%A5#entry353comment</comments>
      <pubDate>Wed, 15 Jul 2026 08:31:59 +0900</pubDate>
    </item>
    <item>
      <title>[Claude 시리즈 2편] Claude 무료 vs 유료 (Pro / Max / Team) - 어떤 걸 써야 할까 (2026 실전 결정 가이드)</title>
      <link>https://isony.tistory.com/entry/Claude-%EC%8B%9C%EB%A6%AC%EC%A6%88-2%ED%8E%B8-Claude-%EB%AC%B4%EB%A3%8C-vs-%EC%9C%A0%EB%A3%8C-Pro-Max-Team-%EC%96%B4%EB%96%A4-%EA%B1%B8-%EC%8D%A8%EC%95%BC-%ED%95%A0%EA%B9%8C-2026-%EC%8B%A4%EC%A0%84-%EA%B2%B0%EC%A0%95-%EA%B0%80%EC%9D%B4%EB%93%9C</link>
      <description>&lt;h1&gt;[Claude 시리즈 2편] Claude 무료 vs 유료 (Pro / Max / Team) - 어떤 걸 써야 할까 (2026 실전 결정 가이드)&lt;/h1&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;테스트 환경&lt;/b&gt;: 2026년 7월 기준 Claude 플랜, Opus 4.8 / Sonnet 5 / Haiku 4.5&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude를 처음 써보고 마음에 든 다음 반드시 부딪히는 질문입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&quot;Free로도 충분한데 유료가 필요할까?&quot;&lt;/b&gt; &lt;b&gt;&quot;Pro로 갈까, Max로 갈까?&quot;&lt;/b&gt; &lt;b&gt;&quot;팀에 도입하려면 Team이 맞을까?&quot;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한국어 자료로 검색해보면 답이 서로 다르고, 많은 정보가 &lt;b&gt;2026년 5월 이전 기준&lt;/b&gt;입니다. Anthropic이 5월 6일 rate limit을 2배로 올렸는데 이 변화가 반영 안 된 글이 대부분입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글에서는 2026년 7월 기준 최신 정확한 정보로 다음을 다룹니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;5개 플랜의 진짜 차이&lt;/b&gt; (Free / Pro / Max 5x / Max 20x / Team)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;어떤 신호가 나타나면 업그레이드해야 하나&lt;/b&gt; (구체적 판단 기준)&lt;/li&gt;
&lt;li&gt;시간 절약 대비 비용 계산 (진짜 가치 관점)&lt;/li&gt;
&lt;li&gt;한국 사용자 특별 고려사항&lt;/li&gt;
&lt;li&gt;최종 추천 매트릭스&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글은 &lt;a href=&quot;https://www.whodo.net/entry/Claude-%EC%8B%9C%EB%A6%AC%EC%A6%88-1%ED%8E%B8-Claude%EA%B0%80-%EB%AD%90%EA%B3%A0-%EC%99%9C-%EC%8D%A8%EC%95%BC-%ED%95%A0%EA%B9%8C-ChatGPT%EC%99%80%EC%9D%98-%EC%A7%84%EC%A7%9C-%EC%B0%A8%EC%9D%B4-%EC%8B%A4%EB%AC%B4%EC%9E%90-%EA%B4%80%EC%A0%90&quot;&gt;시리즈 1편&lt;/a&gt;의 후속으로, Claude를 이미 이해하신 분들이 실제 결제로 넘어가는 결정을 도와줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;바쁘신 분은 &lt;b&gt;&lt;u&gt;30초 요약&lt;/u&gt;&lt;/b&gt;으로 이동하세요.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;30초 요약 - 상황별 정답&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;바쁜 분들을 위한 결론입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 상황이라면 추천 플랜 월 비용&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;가끔 씀, 취미&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;하루 2~3시간 사용, 대부분 개인&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;Pro&lt;/b&gt; ★&lt;/td&gt;
&lt;td&gt;$20&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;Pro 한도를 자주 채움&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;Max 5x&lt;/td&gt;
&lt;td&gt;$100&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;Claude Code 상시 실행, 개발 전업&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;Max 20x&lt;/td&gt;
&lt;td&gt;$200&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;팀 5명 이상 도입, 관리 필요&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;Team Standard&lt;/td&gt;
&lt;td&gt;$25/석&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;팀 + 개별 헤비 사용자&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;Team Premium&lt;/td&gt;
&lt;td&gt;$125/석&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;규제 산업, 감사&amp;middot;SSO 필요&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;Enterprise&lt;/td&gt;
&lt;td&gt;맞춤&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;한 줄 요약&lt;/b&gt;: &lt;b&gt;95%의 개인 사용자는 Pro가 정답입니다. 나머지 5%가 Max 이상 필요.&lt;/b&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Claude 플랜 이해의 핵심 - 이중 제한 구조&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;플랜 비교 전에 반드시 알아야 할 개념입니다. Claude는 &lt;b&gt;5시간 rolling window + 7일 weekly cap&lt;/b&gt; 이중 구조로 사용량을 제한합니다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;┌─ 5시간 rolling window ──┐
│ 첫 메시지부터 5시간 후 리셋 │
│ 하루에 여러 window 가능    │
└────────────────────────┘
           +
┌─ 7일 weekly cap ────────┐
│ 첫 메시지부터 7일 후 리셋  │
│ Opus는 별도 주간 한도     │
└────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;의미&lt;/b&gt;: 한 번에 몰아서 쓰면 5시간 window로 제한되고, 매일 조금씩 써도 7일 cap에 걸릴 수 있습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2026년 5월 6일 중요 업데이트&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Anthropic이 &lt;b&gt;모든 유료 플랜의 5시간 rate limit을 2배로 상향&lt;/b&gt;했습니다. 그리고 이전에 있던 peak hours 제한을 제거했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이건 매우 실질적인 변화입니다. &lt;b&gt;옛 리뷰나 한국어 자료가 다루는 사용량 수치는 대부분 낡은 정보&lt;/b&gt;입니다. 이 글은 이 업데이트를 반영한 최신 수치를 사용합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;각 플랜 상세 프로필&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  Free 플랜 - 탐색용&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;포함 내용:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Claude Sonnet 5 접근 (2026년 6월 30일부터 업그레이드)&lt;/li&gt;
&lt;li&gt;5시간당 약 15~40 메시지 (메시지 길이에 따라 다름)&lt;/li&gt;
&lt;li&gt;Cowork 데스크톱 에이전트 접근&lt;/li&gt;
&lt;li&gt;웹, iOS, Android, 데스크톱 앱&lt;/li&gt;
&lt;li&gt;웹 검색, Artifacts, 코드 실행&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;미포함:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Claude Code ❌&lt;/li&gt;
&lt;li&gt;Opus 4.8 ❌ (Pro부터 제한적 접근)&lt;/li&gt;
&lt;li&gt;Fable 5 ❌&lt;/li&gt;
&lt;li&gt;Research 모드 ❌&lt;/li&gt;
&lt;li&gt;Projects ❌&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;적합한 사용자:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Claude를 처음 시도해보는 사람&lt;/li&gt;
&lt;li&gt;하루 30분~1시간 내외 사용&lt;/li&gt;
&lt;li&gt;특정 목적 없이 탐색 중&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;한계 신호:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;오전에 시작해서 오후에 &quot;한도 도달&quot; 메시지 자주 봄&lt;/li&gt;
&lt;li&gt;프로젝트 컨텍스트를 매번 재입력해야 하는 답답함&lt;/li&gt;
&lt;li&gt;&quot;이거 유료면 되는데&quot; 하는 생각이 자주 듦&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Free에서 위 신호가 나타나면 &lt;b&gt;Pro 업그레이드 시점&lt;/b&gt;입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  Pro ($20/월) - 개인 표준&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;월 $20 ($17/월 연간)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;포함 내용:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Sonnet 5 무제한에 가까움&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Opus 4.8 제한적 접근&lt;/b&gt; (충분히 실용적)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Claude Code&lt;/b&gt; (터미널 기반 코딩 에이전트) ★&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Cowork&lt;/b&gt; (데스크톱 에이전트)&lt;/li&gt;
&lt;li&gt;Projects (프로젝트 컨텍스트 유지)&lt;/li&gt;
&lt;li&gt;Research 모드&lt;/li&gt;
&lt;li&gt;파일 생성, 코드 실행&lt;/li&gt;
&lt;li&gt;5시간당 약 &lt;b&gt;45 메시지&lt;/b&gt; (2026년 5월 이전 대비 2배)&lt;/li&gt;
&lt;li&gt;Google Workspace 통합&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;의미 있는 사용량 (실무 기준):&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;하루 2~3시간 집중 사용 가능&lt;/li&gt;
&lt;li&gt;회의록 요약, 이메일 초안, 코드 리뷰 등 30~50건/일&lt;/li&gt;
&lt;li&gt;5시간 window 2~3회 활용 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;적합한 사용자:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;대부분의 개인 실무자&lt;/li&gt;
&lt;li&gt;하루 몇 시간 사용하는 지식 근로자&lt;/li&gt;
&lt;li&gt;개발자, 작가, 기획자, 마케터&lt;/li&gt;
&lt;li&gt;학생 (많은 학교가 별도 라이선스 미제공 시)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;한 줄 평&lt;/b&gt;: &quot;고민된다면 이걸로.&quot;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Anthropic 창립 이래 Pro는 &lt;b&gt;가장 가성비 좋은 플랜&lt;/b&gt;입니다. Claude Code + Cowork가 포함된 $20는 다른 서비스 대비 압도적입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  Max 5x ($100/월) - 헤비 사용자&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;월 $100, Pro의 5배 사용량&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;추가 혜택 (Pro 대비):&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;5시간당 약 &lt;b&gt;225 메시지&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;Opus 4.8 접근 확대&lt;/li&gt;
&lt;li&gt;새 모델&amp;middot;기능 우선 접근&lt;/li&gt;
&lt;li&gt;Peak time 서비스 우선순위&lt;/li&gt;
&lt;li&gt;확장 컨텍스트 접근 (일부)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Claude Code 특별 혜택:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;주간 140~280시간 (Sonnet 기준)&lt;/li&gt;
&lt;li&gt;Opus 4.8에서 1M 컨텍스트 자동 지원 (2026년 3월 이후)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;적합한 사용자:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Pro에서 &lt;b&gt;매일&lt;/b&gt; 한도에 도달하는 사용자&lt;/li&gt;
&lt;li&gt;코딩 프로젝트를 상시 진행하는 개발자&lt;/li&gt;
&lt;li&gt;여러 클라이언트 작업을 병행하는 프리랜서&lt;/li&gt;
&lt;li&gt;Claude를 &lt;b&gt;주 도구&lt;/b&gt;로 사용하는 실무자&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;언제 필요한가:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&quot;한도 도달&quot; 알림을 주 3회 이상 봄&lt;/li&gt;
&lt;li&gt;오후에 반드시 Claude가 필요한데 못 씀&lt;/li&gt;
&lt;li&gt;Claude Code로 대규모 프로젝트 진행 중&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  Max 20x ($200/월) - 헤비 오브 헤비&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;월 $200, Pro의 20배 사용량&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;추가 혜택 (Max 5x 대비):&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;5시간당 약 &lt;b&gt;900 메시지&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;Claude Code 주간 240~480시간&lt;/li&gt;
&lt;li&gt;실질적 &quot;무제한&quot;에 가까움&lt;/li&gt;
&lt;li&gt;최우선 서비스 접근&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;적합한 사용자:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Claude Code를 하루 8시간+ 사용&lt;/li&gt;
&lt;li&gt;AI 기반 회사&amp;middot;에이전시 운영&lt;/li&gt;
&lt;li&gt;다중 프로젝트 동시 진행&lt;/li&gt;
&lt;li&gt;Claude 없이 업무 불가능한 상태&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;언제 필요한가:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Max 5x에서도 한도 부딪힘&lt;/li&gt;
&lt;li&gt;팀에게 배포하기엔 아직 초기 단계&lt;/li&gt;
&lt;li&gt;&quot;돈 아까울 수 있지만 없으면 안 됨&quot; 상태&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;계산 팁&lt;/b&gt;: Max 20x는 $200 = 시간당 약 $6.7 (30일 기준). 시간당 $30 이상 버는 실무자라면 시간 절약 관점에서 확실히 남습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  Team Standard ($25/석/월) - 팀 5명 이상&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;월 $25/석 ($20 연간), 최소 5석&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;추가 혜택 (Pro 대비):&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Team Projects (공유 프로젝트)&lt;/li&gt;
&lt;li&gt;관리자 콘솔&lt;/li&gt;
&lt;li&gt;중앙 결제&lt;/li&gt;
&lt;li&gt;사용량 통계&lt;/li&gt;
&lt;li&gt;5시간당 Pro와 유사한 한도&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;사용량&lt;/b&gt;: 개별 시트는 Pro 수준&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;적합한 사용자:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;5명 이상 팀 도입&lt;/li&gt;
&lt;li&gt;공유 지식&amp;middot;프로젝트가 필요한 조직&lt;/li&gt;
&lt;li&gt;중앙 관리 원함&lt;/li&gt;
&lt;li&gt;예산 관리 중요&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt; ⭐ Team Premium ($125/석/월) - 팀 + 헤비 사용자&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;월 $125/석 ($100 연간)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;추가 혜택 (Team Standard 대비):&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;시트당 Max 5x와 유사한 사용량 (~225 msg/5h)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Claude Code 팀 통합&lt;/b&gt; ★&lt;/li&gt;
&lt;li&gt;확장 컨텍스트 자동 (Opus에서 1M)&lt;/li&gt;
&lt;li&gt;우선 지원&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;적합한 사용자:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;팀 협업 + 개별 헤비 사용&lt;/li&gt;
&lt;li&gt;개발팀에서 Claude Code 표준 도입&lt;/li&gt;
&lt;li&gt;5석 이상 필요하지만 각자 Max 20x보다 저렴 원함&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;핵심 통찰&lt;/b&gt;: 팀 개발자 5명이 각자 Max 20x ($200)를 사면 $1,000/월. Team Premium 5석은 $625/월 ($500 연간). 팀 관리 도구까지 포함해서 훨씬 유리합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  Enterprise (맞춤 가격)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;추가 혜택:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;SSO, 감사 로그&lt;/li&gt;
&lt;li&gt;확장 컨텍스트 (500K~1M)&lt;/li&gt;
&lt;li&gt;데이터 보존 정책 설정&lt;/li&gt;
&lt;li&gt;SLA 보장&lt;/li&gt;
&lt;li&gt;HIPAA 컴플라이언스&lt;/li&gt;
&lt;li&gt;전담 지원&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;적합한 사용자:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;규제 산업 (금융, 의료, 법률)&lt;/li&gt;
&lt;li&gt;대기업 컴플라이언스 요구&lt;/li&gt;
&lt;li&gt;데이터 거버넌스 필요&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;★ 업그레이드 신호 - 언제 다음 플랜으로 넘어갈까&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 부분이 이 글의 핵심입니다. 막연히 &quot;많이 쓰면&quot;이 아니라 &lt;b&gt;명확한 신호&lt;/b&gt;로 판단합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Free &amp;rarr; Pro 업그레이드 신호 (5개)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 중 &lt;b&gt;3개 이상 해당되면 Pro 시점&lt;/b&gt;입니다.&lt;/p&gt;
&lt;pre class=&quot;lsl&quot;&gt;&lt;code&gt;[ ] 1. 주 3회 이상 &quot;한도 도달&quot; 알림을 봄
[ ] 2. 오후에 Claude가 필요한데 자주 못 씀
[ ] 3. 같은 정보를 매번 다시 설명해야 함 (Projects 필요)
[ ] 4. Claude Code를 써보고 싶음 (개발자)
[ ] 5. 웹 검색이나 파일 생성 기능이 자주 필요함
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;계산&lt;/b&gt;: Pro $20/월 = 하루 $0.67. 커피 한 잔값도 안 됩니다. 위 신호 3개면 즉시 업그레이드가 정답입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Pro &amp;rarr; Max 5x 업그레이드 신호 (5개)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 중 &lt;b&gt;3개 이상 해당되면 Max 5x 시점&lt;/b&gt;입니다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;[ ] 1. Pro에서 주 3회 이상 한도 도달
[ ] 2. Claude Code를 하루 2시간 이상 사용
[ ] 3. Opus 4.8을 자주 사용하고 싶음 (Pro는 제한적)
[ ] 4. 여러 프로젝트를 병행하는 프리랜서&amp;middot;컨설턴트
[ ] 5. Claude 없으면 업무 진행 안 됨
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;계산&lt;/b&gt;: Max 5x $100 = Pro $20 &amp;times; 5. 사용량이 5배가 되지 않으면 낭비입니다. 실제로 사용량 로그를 보고 결정하세요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Max 5x &amp;rarr; Max 20x 업그레이드 신호 (3개)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 중 &lt;b&gt;2개 이상 해당되면 Max 20x 시점&lt;/b&gt;입니다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;[ ] 1. Max 5x에서도 한도 부딪힘 (Claude Code 위주)
[ ] 2. AI 기반 자동화&amp;middot;에이전시 사업 운영
[ ] 3. 프로젝트가 대규모라 1M 컨텍스트 상시 필요
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;계산&lt;/b&gt;: Max 20x $200 = 시간당 $6.7. 시간당 수입 $30 이상 실무자에게 유리합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;개인 &amp;rarr; Team 전환 신호 (3개)&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;[ ] 1. 팀원 5명 이상이 각자 개인 Pro 결제 중
[ ] 2. 팀 공유 프로젝트&amp;middot;지식 관리 필요
[ ] 3. 중앙 결제&amp;middot;관리자 통제 원함
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3개 모두 해당되면 Team으로 전환 검토.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Team Standard &amp;rarr; Team Premium 신호 (2개)&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;[ ] 1. 팀 내 개발자들이 Claude Code 상시 사용
[ ] 2. 각자 Max 20x 결제 검토 중 (총 비용 낭비)
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;시간 절약 대비 비용 계산 (진짜 가치)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude의 진짜 가치는 &lt;b&gt;시간 절약&lt;/b&gt;입니다. 이걸 정확히 계산해봅니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;실무자의 하루 절약 시간&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;작업 Claude 없이 Claude 사용 절약&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;이메일 초안&lt;/td&gt;
&lt;td&gt;15분&lt;/td&gt;
&lt;td&gt;5분&lt;/td&gt;
&lt;td&gt;10분&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;회의록 요약&lt;/td&gt;
&lt;td&gt;30분&lt;/td&gt;
&lt;td&gt;10분&lt;/td&gt;
&lt;td&gt;20분&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;코드 리뷰&lt;/td&gt;
&lt;td&gt;60분&lt;/td&gt;
&lt;td&gt;20분&lt;/td&gt;
&lt;td&gt;40분&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;문서 검토&lt;/td&gt;
&lt;td&gt;90분&lt;/td&gt;
&lt;td&gt;30분&lt;/td&gt;
&lt;td&gt;60분&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;데이터 분석&lt;/td&gt;
&lt;td&gt;90분&lt;/td&gt;
&lt;td&gt;40분&lt;/td&gt;
&lt;td&gt;50분&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;하루 합계&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;4시간 45분&lt;/td&gt;
&lt;td&gt;1시간 45분&lt;/td&gt;
&lt;td&gt;&lt;b&gt;3시간&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하루 3시간 &amp;times; 22 영업일 = &lt;b&gt;월 66시간 절약&lt;/b&gt;.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;시간당 비용 관점&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;Pro ($20/월):
   $20 &amp;divide; 66시간 = 시간당 $0.30
   시간당 수입 $10 이상이면 무조건 이익

Max 5x ($100/월):
   Pro의 5배 사용, 사용량 병목 없음
   시간당 수입 $30 이상이면 유리

Max 20x ($200/월):
   실질 무제한 사용
   시간당 수입 $50 이상 또는 팀 통합 시 유리
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;결론&lt;/b&gt;: 개인 실무자의 시간 가치를 고려하면 Pro는 &lt;b&gt;거의 무조건 이익&lt;/b&gt;입니다. 커피 한 잔값에 시간을 살 수 있습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;다른 도구 대비 가성비&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;도구 조합 월 비용 포함 기능&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Claude Pro만&lt;/td&gt;
&lt;td&gt;$20&lt;/td&gt;
&lt;td&gt;Claude + Claude Code + Cowork&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ChatGPT Plus만&lt;/td&gt;
&lt;td&gt;$20&lt;/td&gt;
&lt;td&gt;ChatGPT (Code Interpreter 별도)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ChatGPT Plus + GitHub Copilot&lt;/td&gt;
&lt;td&gt;$30&lt;/td&gt;
&lt;td&gt;챗봇 + IDE 자동완성&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;Claude Pro + GitHub Copilot&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;$30&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;Claude Code + IDE 자동완성&lt;/b&gt; (★ 개발자 최강)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Claude Pro + ChatGPT Plus&lt;/td&gt;
&lt;td&gt;$40&lt;/td&gt;
&lt;td&gt;Claude 깊이 + ChatGPT 만능&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude Pro가 단독으로도 Claude Code + Cowork를 포함하므로 &lt;b&gt;가성비 1위&lt;/b&gt;입니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  한국 사용자 특별 고려사항&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 결제 방식과 실질 비용&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;웹 결제 (권장): $20 그대로 (약 27,000~28,000원)
iOS 앱스토어 결제: 약 30% 마크업 &amp;rarr; 30,000원+
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;팁&lt;/b&gt;: 반드시 &lt;a href=&quot;https://claude.ai&quot;&gt;https://claude.ai&lt;/a&gt; 웹에서 결제하세요. iOS 앱은 로그인만 하고 결제는 웹에서.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. 연간 결제 할인&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Pro 기준 $17/월 연간 vs $20/월 월간. 연간 $36 절약 (약 5만원).&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude를 3개월 이상 사용할 확신이 있다면 &lt;b&gt;연간 결제&lt;/b&gt;가 유리합니다. 다만 첫 사용자는 월간으로 3개월 써본 후 연간 전환 권장.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. 학생&amp;middot;교육 기관 할인&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Anthropic Education 플랜이 있습니다. 대학교나 연구 기관이 참여하고 있다면 무료 또는 대폭 할인 접근 가능합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;확인 방법: 소속 IT 부서에 &quot;Anthropic Education 참여 여부&quot; 문의.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4. 회사 지원 검토&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;많은 IT 회사들이 개발자 대상으로 Claude Pro 또는 Max를 지원하기 시작했습니다. 회사 정책 확인해보시기 바랍니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5. 팀 도입 시 최소 시트&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Team 플랜은 &lt;b&gt;최소 5석&lt;/b&gt;입니다. 4명 팀은 각자 Pro가 정답. 5명부터 Team 검토.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;최종 추천 매트릭스&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;본인 상황을 5초 안에 판단하는 표입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;개인 사용자&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;  Free: 초기 탐색 1~2주
  Pro: 대부분 사용자 정답 (95%)
  Max 5x: 헤비 사용자 (Pro 한도 부딪힘)
   Max 20x: 초헤비 사용자 (극소수)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;개발자&amp;middot;엔지니어&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;  Pro + GitHub Copilot ($30/월): 최강 가성비
  Max 5x + GitHub Copilot ($110/월): 헤비 개발
   Max 20x: 풀타임 AI 활용
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;회사 팀 도입&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;1~4명 팀: 각자 Pro
5~10명 표준 사용: Team Standard
5~10명 개발팀: Team Premium
규제 산업 / 대기업: Enterprise
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;자주 발생하는 실수 5가지&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;실수 1: Free로 무리하다가 결정 미루기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Free의 한도가 잦으면 이미 유료가 필요한 상태입니다. 매일 좌절하며 무료 지속은 시간 낭비.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;실수 2: Pro 없이 Max 5x로 바로 감&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Max 5x는 Pro가 부족한 사람을 위한 것. Pro도 안 써봤다면 낭비. 반드시 Pro &amp;rarr; Max 순으로 검증.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;실수 3: 팀원 각자 Pro인데 4명&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5명 이상 없이 Team 시도 &amp;rarr; 실패. 4명은 각자 Pro가 정답.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;실수 4: iOS 앱에서 결제&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;30% 마크업 손해. 반드시 웹에서 결제.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;실수 5: 한도 도달 시 즉시 업그레이드&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한 번의 한도 도달로 업그레이드하지 마세요. &lt;b&gt;일주일 사용 패턴&lt;/b&gt;을 관찰하고 결정.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;다음 글 예고&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 시리즈의 다음 글은 &lt;b&gt;[Claude 시리즈 3편] Claude 처음 사용법 완벽 가이드 - 5분 안에 마스터&lt;/b&gt; 입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 글에서 다룰 내용:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;계정 만들기 실전 (한국 사용자 기준)&lt;/li&gt;
&lt;li&gt;첫 5분 안에 익혀야 할 기능 5가지&lt;/li&gt;
&lt;li&gt;Projects 활용법 (Pro 이상)&lt;/li&gt;
&lt;li&gt;웹, 모바일, 데스크톱 앱 각각의 특징&lt;/li&gt;
&lt;li&gt;자주 하는 실수와 팁&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;마무리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude 플랜 선택의 핵심을 다시 정리하면:&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;95%의 개인 사용자는 Pro가 정답&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;업그레이드 신호는 명확한 3~5개 기준으로 판단&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;시간 가치를 계산하면 Pro는 거의 무조건 이익&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;웹 결제 필수&lt;/b&gt;, iOS 앱 결제 손해&lt;/li&gt;
&lt;li&gt;&lt;b&gt;팀 5명 미만은 각자 Pro&lt;/b&gt;, 이상은 Team 검토&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 흔한 실수는 &lt;b&gt;&quot;고민만 하고 결정 안 하는 것&quot;&lt;/b&gt; 입니다. Free에서 답답함을 자주 느끼신다면 Pro 한 달 사용해보는 것이 정답입니다. 안 맞으면 취소하면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;본인의 Claude 사용 패턴이 어떤지, 어떤 플랜에서 어떤 만족을 얻으셨는지 댓글로 공유해주세요. 다른 실무자들의 결정에 도움이 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가격과 사용량 정책은 자주 업데이트됩니다. 정확한 최신 정보는 &lt;a href=&quot;https://claude.com/pricing&quot;&gt;claude.com/pricing&lt;/a&gt; 에서 확인 필요힘..&lt;/p&gt;</description>
      <category>AI (Claude 활용)/Claude 입문</category>
      <category>Claude Premium 사용법</category>
      <category>Claude Pro Max 차이</category>
      <category>Claude Pro 가격</category>
      <category>Claude Team</category>
      <category>Claude 무료 vs 유료</category>
      <category>Claude 사용량한도</category>
      <category>Claude 요금제</category>
      <category>Claude 학생할인</category>
      <category>Claude 회사도입</category>
      <category>소니스토리</category>
      <author>isony</author>
      <guid isPermaLink="true">https://isony.tistory.com/352</guid>
      <comments>https://isony.tistory.com/entry/Claude-%EC%8B%9C%EB%A6%AC%EC%A6%88-2%ED%8E%B8-Claude-%EB%AC%B4%EB%A3%8C-vs-%EC%9C%A0%EB%A3%8C-Pro-Max-Team-%EC%96%B4%EB%96%A4-%EA%B1%B8-%EC%8D%A8%EC%95%BC-%ED%95%A0%EA%B9%8C-2026-%EC%8B%A4%EC%A0%84-%EA%B2%B0%EC%A0%95-%EA%B0%80%EC%9D%B4%EB%93%9C#entry352comment</comments>
      <pubDate>Mon, 13 Jul 2026 07:41:39 +0900</pubDate>
    </item>
    <item>
      <title>2026년07월12일 주일예배 (이재훈목사님) - 1부</title>
      <link>https://isony.tistory.com/entry/2026%EB%85%8407%EC%9B%9412%EC%9D%BC-%EC%A3%BC%EC%9D%BC%EC%98%88%EB%B0%B0-%EC%9D%B4%EC%9E%AC%ED%9B%88%EB%AA%A9%EC%82%AC%EB%8B%98-1%EB%B6%80</link>
      <description>&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;2026년07월12일 주일예배 (이재훈목사님) - 1부&lt;/h2&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;주의 말씀 : 나를 따르라&amp;nbsp; (9)&lt;/h2&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;읽어버림으로 찾은 목숨&lt;/h2&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;성경 :&amp;nbsp; 마태복음(Matthew) 16:24 ~ 26 말씀 (출처:우리말성경)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&amp;lt; 성경 &amp;gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;16:24 그때에 예수께서 제자들에게 말씀하셨습니다. &amp;ldquo;누구든지 나를 따르려거든 자기를 부인하고 자기 십자가를 지고 따라야 한다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;16:25 누구든지 자기 목숨을 구하려는 사람은 잃을 것이요 누구든지 나를 위해 목숨을 잃는 사람은 얻게 될 것이다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;16:26 사람이 온 세상을 다 얻고도 자기 목숨을 잃으면 무슨 소용이 있겠느냐? 사람이 자기 목숨을 무엇과 맞바꾸겠느냐?&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&amp;lt; 예배 영상 &amp;gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;a href=&quot;https://youtu.be/acIDAuwOb7s&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://youtu.be/acIDAuwOb7s&lt;/a&gt;&lt;/b&gt;&lt;/p&gt;
&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignCenter&quot; data-video-host=&quot;youtube&quot; data-video-url=&quot;https://www.youtube.com/watch?v=acIDAuwOb7s&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/cSzBu4/dJMb86PdNOe/CgVRJR4HBkuOkN6MKAA3l1/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=540_140_680_292,https://scrap.kakaocdn.net/dn/eMwd2/dJMb85W5pqA/3rIeM1XDoEV8KZCUoz4sr1/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=540_140_680_292,https://scrap.kakaocdn.net/dn/skkYj/dJMb85W5pqz/CUT2fERzpfalWhwupUAFBK/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=540_140_680_292&quot; data-video-width=&quot;860&quot; data-video-height=&quot;484&quot; data-video-origin-width=&quot;860&quot; data-video-origin-height=&quot;484&quot; data-ke-mobilestyle=&quot;widthContent&quot; data-video-title=&quot;주일예배2026 07 12&quot; data-original-url=&quot;&quot;&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/acIDAuwOb7s&quot; width=&quot;860&quot; height=&quot;484&quot; frameborder=&quot;&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;figcaption style=&quot;display: none;&quot;&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>성경과 QT/주일예배(온누리교회)</category>
      <category>CGNTV</category>
      <category>나를 따르라</category>
      <category>마태복음</category>
      <category>소니스토리</category>
      <category>온누리교회</category>
      <category>온누리교회 주일예배</category>
      <category>우리말셩경</category>
      <category>이재훈목사</category>
      <category>이재훈목사 주일예배</category>
      <category>주일예배</category>
      <author>isony</author>
      <guid isPermaLink="true">https://isony.tistory.com/351</guid>
      <comments>https://isony.tistory.com/entry/2026%EB%85%8407%EC%9B%9412%EC%9D%BC-%EC%A3%BC%EC%9D%BC%EC%98%88%EB%B0%B0-%EC%9D%B4%EC%9E%AC%ED%9B%88%EB%AA%A9%EC%82%AC%EB%8B%98-1%EB%B6%80#entry351comment</comments>
      <pubDate>Sun, 12 Jul 2026 08:03:58 +0900</pubDate>
    </item>
    <item>
      <title>[Claude 시리즈 1편] Claude가 뭐고 왜 써야 할까 - ChatGPT와의 진짜 차이 (실무자 관점)</title>
      <link>https://isony.tistory.com/entry/Claude-%EC%8B%9C%EB%A6%AC%EC%A6%88-1%ED%8E%B8-Claude%EA%B0%80-%EB%AD%90%EA%B3%A0-%EC%99%9C-%EC%8D%A8%EC%95%BC-%ED%95%A0%EA%B9%8C-ChatGPT%EC%99%80%EC%9D%98-%EC%A7%84%EC%A7%9C-%EC%B0%A8%EC%9D%B4-%EC%8B%A4%EB%AC%B4%EC%9E%90-%EA%B4%80%EC%A0%90</link>
      <description>&lt;h1&gt;[Claude 시리즈 1편] Claude가 뭐고 왜 써야 할까 - ChatGPT와의 진짜 차이 (실무자 관점)&lt;/h1&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;테스트 환경&lt;/b&gt;: Claude Opus 4.8, Sonnet 5 (2026년 7월 기준)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&quot;Claude를 써봤는데 ChatGPT랑 뭐가 다른지 모르겠어요.&quot;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude를 처음 접한 분들에게 자주 듣는 말입니다. 겉으로 보기엔 둘 다 대화창에 질문하면 답변이 나오는 챗봇이니 큰 차이가 안 느껴집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 실제로는 &lt;b&gt;훈련 철학, 응답 스타일, 제품 전략&lt;/b&gt; 모두가 근본적으로 다릅니다. 그리고 이 차이를 이해하는 순간 &quot;왜 Claude를 써야 하는가&quot;가 명확해집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글은 &lt;a href=&quot;https://www.whodo.net/entry/AI-%EB%8F%84%EA%B5%AC-%EB%B9%84%EA%B5%90-Claude-vs-ChatGPT-vs-Gemini-vs-Copilot-2026-%EC%B5%9C%EC%8B%A0-%EC%99%84%EB%B2%BD-%EB%B9%84%EA%B5%90-%EC%8B%A4%EB%AC%B4%EC%9E%90-%EA%B4%80%EC%A0%90&quot;&gt;시리즈 오프닝(4대장 비교)&lt;/a&gt; 이후의 첫 심화 편입니다. Claude에 집중해서 다음을 다룹니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Claude는 누가, 왜 만들었나 (Anthropic 이야기)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Constitutional AI&lt;/b&gt;란 무엇이며 왜 이게 실무에서 중요한가&lt;/li&gt;
&lt;li&gt;ChatGPT와의 &lt;b&gt;3가지 진짜 차이&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;어떤 사람이 Claude를 써야 하나&lt;/li&gt;
&lt;li&gt;무료로 시작하는 법&lt;/li&gt;
&lt;li&gt;실무자를 위한 첫 프롬프트 5개&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시리즈 첫 글이라 개념 위주지만, &lt;b&gt;1편 끝나면 Claude가 왜 특별한지 명확히 이해&lt;/b&gt;하실 수 있게 정리했습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Claude를 만든 회사 - Anthropic 이야기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude를 이해하려면 만든 회사부터 알아야 합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;OpenAI에서 갈라져 나온 안전주의자들&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Anthropic&lt;/b&gt;은 2021년 설립된 AI 회사입니다. 창립자는 &lt;b&gt;다리오 아모데이(Dario Amodei)&lt;/b&gt; 와 &lt;b&gt;다니엘라 아모데이(Daniela Amodei)&lt;/b&gt; 남매를 포함한 7명의 전 OpenAI 임원&amp;middot;연구자들입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이들이 OpenAI를 떠난 이유는 명확했습니다. &lt;b&gt;&quot;AI가 너무 빠르게 발전하는데 안전성 연구가 뒤처지고 있다&quot;&lt;/b&gt; 는 우려였습니다. 그래서 Anthropic의 창립 미션은 &lt;b&gt;&quot;안전한 AI를 만드는 것&quot;&lt;/b&gt; 이 되었습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;핵심 투자자&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Anthropic은 다음의 대형 투자를 받으며 성장했습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Google (2023년 5억 달러)&lt;/li&gt;
&lt;li&gt;Amazon (2023~2024년 총 40억 달러)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;2026년 2월: 시리즈 G $300억 달러 조달 (기업가치 $3,800억)&lt;/b&gt; &amp;mdash; 테크 역사상 두 번째 규모의 민간 자금 라운드&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, Claude는 OpenAI를 잘 아는 사람들이 &lt;b&gt;&quot;우리는 다르게 만들자&quot;&lt;/b&gt; 라는 명확한 방향성을 가지고 만든 AI입니다. 이 배경을 이해하면 Claude의 응답 스타일이 왜 그런지 자연스럽게 이해됩니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;★ Constitutional AI - 이게 실무에서 왜 중요한가&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude를 이해하는 핵심 키워드는 &lt;b&gt;Constitutional AI (헌법적 AI)&lt;/b&gt; 입니다. 이건 단순한 마케팅 용어가 아니라 실제 훈련 방법론입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;다른 AI와의 근본적 차이&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반적인 AI 안전 접근:&lt;/p&gt;
&lt;pre class=&quot;&quot;&gt;&lt;code&gt;AI가 답변 생성 &amp;rarr; 필터가 위험한 답변 걸러냄 &amp;rarr; 사용자에게 전달
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Constitutional AI 접근:&lt;/p&gt;
&lt;pre class=&quot;&quot;&gt;&lt;code&gt;AI가 답변 생성 &amp;rarr; 자체 원칙에 비춰 스스로 검토 &amp;rarr; 필요시 수정 &amp;rarr; 사용자에게 전달
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;차이의 핵심&lt;/b&gt;: 안전이 &lt;b&gt;바깥에 붙은 필터&lt;/b&gt;가 아니라 &lt;b&gt;AI 자체의 사고 과정&lt;/b&gt;에 들어가 있습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2026년 1월 새 Constitution&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Anthropic은 2026년 1월 22일 &lt;b&gt;완전히 새로운 Constitution&lt;/b&gt;을 발표했습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;분량: 약 &lt;b&gt;23,000 단어, 84 페이지&lt;/b&gt; (2023년 초기 버전은 2,700 단어에 불과했음)&lt;/li&gt;
&lt;li&gt;라이선스: Creative Commons CC0 (누구나 자유 사용)&lt;/li&gt;
&lt;li&gt;공식 URL: &lt;a href=&quot;https://www.anthropic.com/constitution&quot;&gt;anthropic.com/constitution&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 문서의 특징은 &lt;b&gt;&quot;규칙&quot;이 아닌 &quot;원칙과 이유&quot;&lt;/b&gt; 를 담고 있다는 것입니다. 예를 들면:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;❌ 옛 방식: &quot;인종 차별적 답변을 하지 마라&quot;&lt;/li&gt;
&lt;li&gt;✅ 새 방식: &quot;인간의 존엄성이 왜 중요한지, 이런 답변이 왜 해가 되는지&quot;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4단계 우선순위 체계&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;새 Constitution은 명확한 우선순위를 제시합니다.&lt;/p&gt;
&lt;pre class=&quot;markdown&quot;&gt;&lt;code&gt;1순위: 안전성 (Safety)
       - 인간의 감독 능력 보존
       - 재앙적 결과 방지

2순위: 윤리 (Ethics)  
       - 정직, 해악 회피
       - 존엄성 존중

3순위: 규정 준수 (Compliance)
       - Anthropic의 특정 가이드라인
       - 법적&amp;middot;규제적 요구사항

4순위: 도움 (Helpfulness)
       - 사용자에게 유용한 답변 제공
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 순서가 왜 중요할까요? 4순위(도움)가 3순위(규정)와 충돌할 때 &lt;b&gt;Claude는 도움을 포기&lt;/b&gt;합니다. 그래서 가끔 &quot;왜 이걸 안 해주지?&quot; 하는 순간이 있는데, 이게 우연이 아니라 설계된 결과입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;실무자 관점의 의미&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Constitutional AI가 실무에서 의미하는 것은 다음과 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. 예측 가능한 행동&lt;/b&gt; Claude가 언제 어떻게 거절할지 상대적으로 일관됩니다. 회사 워크플로우에 통합할 때 이 예측 가능성이 큰 자산입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. 정직한 응답&lt;/b&gt; Claude는 모르는 것을 &quot;모른다&quot;고 말합니다. 확실하지 않을 때 확실한 척하지 않습니다. 이건 팩트 체크 부담을 줄여줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. 규제 대응 유리&lt;/b&gt; EU AI Act 같은 규제와 잘 부합하도록 설계되어 있어 규제 산업(금융, 의료, 법률)에서 우선 도입되고 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한 마디로 &lt;b&gt;&quot;믿을 수 있는 답변을 주는 AI&quot;&lt;/b&gt; 를 목표로 만들어졌다는 것입니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;★ ChatGPT와의 3가지 진짜 차이&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 본론입니다. 매일 쓰는 사용자 관점에서 실제로 체감되는 차이 3가지입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;차이 1: 응답 스타일 - 뉘앙스와 정직성&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;같은 질문에 두 AI의 응답:&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;질문: &quot;제 새 사업 아이디어인데 어떻게 생각하세요? (아이디어 설명)&quot;&lt;/p&gt;
&lt;pre class=&quot;gcode&quot;&gt;&lt;code&gt;ChatGPT (경향):
&quot;훌륭한 아이디어네요! 다음의 강점이 있습니다...&quot;
&amp;rarr; 긍정적 톤 기본, 격려 위주

Claude (경향):
&quot;이 아이디어의 흥미로운 부분은 X입니다. 
다만 Y와 Z가 우려됩니다. A는 이미 시장에 있고...&quot;
&amp;rarr; 균형 잡힌 평가, 우려도 솔직히 언급
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude는 &lt;b&gt;&quot;사용자가 듣고 싶어 하는 말&quot;보다 &quot;사용자에게 실제로 도움이 되는 말&quot;&lt;/b&gt; 을 우선합니다. 처음에는 차갑게 느껴질 수 있지만, 실제 결정에 도움이 되는 답변을 원하는 사용자에게는 이게 큰 장점입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;차이 2: 긴 문서와 복잡한 코드 처리&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude는 &lt;b&gt;긴 문서와 복잡한 코드&lt;/b&gt;에서 특히 강점을 보입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;항목 Claude Opus 4.8 GPT-5.2&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;기본 컨텍스트&lt;/td&gt;
&lt;td&gt;200K 토큰&lt;/td&gt;
&lt;td&gt;128K 토큰&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;확장 컨텍스트&lt;/td&gt;
&lt;td&gt;1M (베타)&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;코딩 벤치마크 (SWE-bench)&lt;/td&gt;
&lt;td&gt;최상위&lt;/td&gt;
&lt;td&gt;뒤짐&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;긴 문서 요약&lt;/td&gt;
&lt;td&gt;세부사항 유지&lt;/td&gt;
&lt;td&gt;핵심만&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;실무에서 의미하는 것&lt;/b&gt;:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;100페이지 계약서 분석 &amp;rarr; Claude 유리&lt;/li&gt;
&lt;li&gt;대규모 코드베이스 리팩터링 &amp;rarr; Claude 유리&lt;/li&gt;
&lt;li&gt;여러 문서 교차 참조 &amp;rarr; Claude 유리&lt;/li&gt;
&lt;li&gt;이미지 생성 &amp;rarr; ChatGPT 유리 (Claude는 불가)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;차이 3: 제품 전략 - Claude Code, Cowork, Skills&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 부분이 한국어 자료에서 잘 다루지 않는 영역인데, &lt;b&gt;개발자&amp;middot;실무자 관점에서 결정적 차이&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude Pro ($20/월)에 포함된 것:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Claude Code (터미널 기반 코딩 에이전트)&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;shell&quot;&gt;&lt;code&gt;$ claude
&amp;gt; 이 프로젝트에 새 기능 추가해줘
[Claude가 파일 탐색, 코드 작성, 테스트 실행까지 모두 처리]
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Cowork (데스크톱 에이전트)&lt;/b&gt; 파일 관리, 문서 정리 같은 반복 작업을 백그라운드에서 자동 수행.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Skills (자동화 스킬)&lt;/b&gt; 반복 작업을 스킬로 저장해서 재사용.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 3가지 도구가 &lt;b&gt;$20에 모두 포함&lt;/b&gt;됩니다. ChatGPT Plus에는 이런 종류의 도구가 없거나 별도 결제입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, &lt;b&gt;개발자&amp;middot;자동화에 관심 있는 실무자&lt;/b&gt;에게 Claude Pro는 압도적 가성비입니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;어떤 사람이 Claude를 써야 할까&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5가지 사용자 프로필별 추천도입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;프로필 1: 개발자&amp;middot;엔지니어 (★★★★★)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude는 &lt;b&gt;최우선 선택&lt;/b&gt;입니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;SWE-bench 코딩 벤치마크 최상위&lt;/li&gt;
&lt;li&gt;Claude Code로 CLI 자동화&lt;/li&gt;
&lt;li&gt;대규모 리팩터링, 아키텍처 이해에 강함&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;프로필 2: 작가&amp;middot;기획자&amp;middot;마케터 (★★★★★)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude가 &lt;b&gt;뉘앙스 있는 글쓰기&lt;/b&gt;에 강점이 큽니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;자연스러운 문장&lt;/li&gt;
&lt;li&gt;사용자 스타일 학습&lt;/li&gt;
&lt;li&gt;200K 컨텍스트로 긴 글도 안정적&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;프로필 3: 연구자&amp;middot;학생 (★★★★☆)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude가 &lt;b&gt;팩트 정확성과 심층 분석&lt;/b&gt;에 유리합니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;모르는 것을 &quot;모른다&quot;고 말함&lt;/li&gt;
&lt;li&gt;복잡한 논증도 정확히 파악&lt;/li&gt;
&lt;li&gt;다만 실시간 검색은 Perplexity 조합 권장&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;프로필 4: 일반 사용자&amp;middot;비전문가 (★★★☆☆)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;ChatGPT가 더 편할 수 있습니다.&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이미지 생성 (DALL-E)&lt;/li&gt;
&lt;li&gt;Voice Mode (음성 대화)&lt;/li&gt;
&lt;li&gt;서드파티 통합 압도적으로 많음&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude가 근본적으로 더 낫지만 &lt;b&gt;일반 소비자용 재미 요소&lt;/b&gt;는 ChatGPT가 우위.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;프로필 5: 회사 도입 검토자 (★★★★★)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Claude가 최우선입니다.&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Constitutional AI로 규제 대응 유리&lt;/li&gt;
&lt;li&gt;예측 가능한 행동&lt;/li&gt;
&lt;li&gt;정보 보안 신뢰도 높음&lt;/li&gt;
&lt;li&gt;Team/Enterprise 플랜 잘 짜여 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;무료로 시작하는 법 (5분)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude를 처음 시도하는 데 비용이 들지 않습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Step 1: 계정 만들기&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;1. https://claude.ai 접속
2. 이메일 또는 Google 계정으로 가입
3. 인증 완료 (전화번호 확인)
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전화번호 인증이 필요하지만 한국 번호도 정상 지원됩니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Step 2: Free tier 상태 확인&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2026년 6월 30일 이후 Free tier는 &lt;b&gt;Sonnet 5&lt;/b&gt;에 접근할 수 있습니다. 이건 유료의 Sonnet과 동일 모델입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;제한사항:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;5시간 rolling window (하루 종일이 아니라 5시간마다 리셋)&lt;/li&gt;
&lt;li&gt;Opus 4.8은 제한적 접근&lt;/li&gt;
&lt;li&gt;Claude Code, Research 등 일부 기능은 유료 전용&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반 사용자라면 무료로 상당한 작업이 가능합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Step 3: 첫 대화 시도&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로그인 후 대화창에 아래 5가지 프롬프트 중 하나를 입력해보세요.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;★ 실무자를 위한 첫 프롬프트 5개&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude의 실력을 느끼기 좋은 프롬프트입니다. 그대로 복사해서 사용해보세요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;프롬프트 1: 문서 정리 (모든 직군)&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;아래 회의록을 다음 3가지로 정리해줘:
1. 핵심 결정 사항 (3개 이내)
2. 액션 아이템 (담당자, 기한 명시)
3. 다음 회의 안건

[회의록 붙여넣기]
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude가 회의록의 노이즈를 걸러내고 실행 가능한 형태로 만드는 능력을 볼 수 있습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;프롬프트 2: 이메일 톤 조정 (직장인)&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;아래 이메일을 다음 3가지 톤으로 각각 다시 써줘:
1. 정중하되 단호한 톤
2. 친근하되 전문적인 톤
3. 사과하지 않으면서 사과처럼 들리는 톤

원문:
[이메일 붙여넣기]
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude의 뉘앙스 감각을 확인할 수 있는 프롬프트입니다. ChatGPT와 확연한 차이가 느껴집니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;프롬프트 3: 코드 리뷰 (개발자)&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;아래 코드를 리뷰해줘. 다음 관점에서:
1. 잠재적 버그
2. 성능 이슈
3. 코드 가독성
4. 보안 취약점
5. 개선 제안 (구체적 코드 포함)

[코드 붙여넣기]
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude의 코딩 실력을 직접 체감할 수 있는 프롬프트입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;프롬프트 4: 학습 요약 (모든 직군)&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;[전문 문서 또는 논문 붙여넣기]

위 내용을 3가지 관점으로 정리해줘:
1. 핵심 개념 5개 (각 2줄로)
2. 실무에 적용할 수 있는 인사이트 3개
3. 이해하지 못했다면 무엇을 더 찾아봐야 할지
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude의 정직성이 잘 드러나는 프롬프트입니다. 모르는 부분은 &quot;이 부분은 더 확인이 필요합니다&quot; 라고 말합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;프롬프트 5: 문제 해결 (범용)&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;저는 지금 [상황 설명] 문제를 겪고 있습니다.

다음 순서로 도와주세요:
1. 이 문제의 근본 원인 3가지 후보
2. 각 원인의 진단 방법
3. 원인별 해결 방법
4. 재발 방지 팁

배경: [환경, 제약사항]
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시리즈 톤인 &quot;원인별 분류&quot; 접근을 Claude에게 시켜보는 프롬프트입니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Claude 사용 시 주의사항&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude가 좋은 도구지만 완벽하진 않습니다. 반드시 알아야 할 한계입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 이미지 생성 불가&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이미지나 비디오를 만들어달라는 요청은 처리할 수 없습니다. 이 경우 ChatGPT의 DALL-E 또는 Gemini를 병행 사용하세요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. 실시간 정보 제한&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본 상태에서는 최신 뉴스나 실시간 정보 접근이 제한적입니다. 웹 검색 도구를 켜거나, Perplexity와 조합해서 사용하세요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. 학습 옵트아웃 필수&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본 설정에서 대화가 모델 개선에 활용될 수 있습니다. 설정에서 옵트아웃하세요.&lt;/p&gt;
&lt;pre class=&quot;apache&quot;&gt;&lt;code&gt;Settings &amp;rarr; Privacy &amp;rarr; &quot;Help improve Claude&quot; &amp;rarr; OFF
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4. 회사 기밀은 절대 금지&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이건 어떤 AI에도 해당되지만 Claude에도 마찬가지입니다. 개인정보&amp;middot;기밀 정보는 입력 금지.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5. 정보의 정확성 자체 검증 필요&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Constitutional AI가 정직성을 강조하지만 여전히 오류가 발생할 수 있습니다. 중요한 결정은 반드시 자체 검증을 거치세요.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;다음 글 예고&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 시리즈의 다음 글은 &lt;b&gt;[Claude 시리즈 2편] Claude 무료 vs 유료 (Pro/Max) - 어떤 걸 써야 할까&lt;/b&gt; 입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 글에서 다룰 내용:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;무료 tier로 어디까지 가능한가&lt;/li&gt;
&lt;li&gt;Pro ($20)가 필요한 시점&lt;/li&gt;
&lt;li&gt;Max ($100/$200)가 필요한 시점&lt;/li&gt;
&lt;li&gt;Team 플랜 검토 기준&lt;/li&gt;
&lt;li&gt;각 플랜별 진짜 가치 비교&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;마무리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude는 단순히 &quot;또 다른 챗봇&quot;이 아닙니다. &lt;b&gt;AI 안전성을 최우선하는 회사가 만든, 근본적으로 다른 접근의 AI&lt;/b&gt; 입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;핵심을 다시 정리하면:&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;Anthropic은 OpenAI 출신들이 안전성을 위해 창립&lt;/b&gt;한 회사&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Constitutional AI&lt;/b&gt;로 안전을 훈련 과정에 내장 (필터가 아님)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;뉘앙스 있는 응답, 긴 문서 처리, 코딩&lt;/b&gt;에서 강점&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Claude Code, Cowork, Skills&lt;/b&gt;가 $20에 포함&lt;/li&gt;
&lt;li&gt;&lt;b&gt;개발자&amp;middot;작가&amp;middot;연구자&amp;middot;회사 도입에 최우선 선택&lt;/b&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude가 &quot;왜 특별한가&quot;가 이제 명확해지셨기를 바랍니다. 다음 편에서는 실제 결제까지 이어지는 &lt;b&gt;플랜 선택 기준&lt;/b&gt;을 다룹니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude를 처음 써보시고 든 인상, 또는 ChatGPT와 다르게 느낀 부분이 있다면 댓글로 공유해주세요. 다른 분들의 첫 사용 경험도 함께 정리해가면 좋겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>AI (Claude 활용)/Claude 입문</category>
      <category>Anthropic 창립자</category>
      <category>Claude AI 사용법</category>
      <category>Claude Cowork</category>
      <category>Claude Skills</category>
      <category>Claude 안정성</category>
      <category>Claude 이메일 작성</category>
      <category>Claude 프롬프트 예시</category>
      <category>개발자 Claude vs ChatGPT</category>
      <category>기업 ai 도입</category>
      <category>소니스토리</category>
      <author>isony</author>
      <guid isPermaLink="true">https://isony.tistory.com/350</guid>
      <comments>https://isony.tistory.com/entry/Claude-%EC%8B%9C%EB%A6%AC%EC%A6%88-1%ED%8E%B8-Claude%EA%B0%80-%EB%AD%90%EA%B3%A0-%EC%99%9C-%EC%8D%A8%EC%95%BC-%ED%95%A0%EA%B9%8C-ChatGPT%EC%99%80%EC%9D%98-%EC%A7%84%EC%A7%9C-%EC%B0%A8%EC%9D%B4-%EC%8B%A4%EB%AC%B4%EC%9E%90-%EA%B4%80%EC%A0%90#entry350comment</comments>
      <pubDate>Fri, 10 Jul 2026 07:42:17 +0900</pubDate>
    </item>
    <item>
      <title>[AI 도구 비교] Claude vs ChatGPT vs Gemini vs Copilot - 2026 최신 완벽 비교 (실무자 관점)</title>
      <link>https://isony.tistory.com/entry/AI-%EB%8F%84%EA%B5%AC-%EB%B9%84%EA%B5%90-Claude-vs-ChatGPT-vs-Gemini-vs-Copilot-2026-%EC%B5%9C%EC%8B%A0-%EC%99%84%EB%B2%BD-%EB%B9%84%EA%B5%90-%EC%8B%A4%EB%AC%B4%EC%9E%90-%EA%B4%80%EC%A0%90</link>
      <description>&lt;h1&gt;[AI 도구 비교] Claude vs ChatGPT vs Gemini vs Copilot - 2026 최신 완벽 비교 (실무자 관점)&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2026년 현재, AI 어시스턴트 시장은 &lt;b&gt;4대장&lt;/b&gt;이 경쟁하고 있습니다. &lt;b&gt;ChatGPT (OpenAI), Claude (Anthropic), Gemini (Google), Copilot (Microsoft)&lt;/b&gt;. 어느 것을 써야 할지 검색해봐도 결과는 서로 다르고, 대부분 반년 이상 오래된 정보 기준입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저는 15년차 IT 실무자로서 네 가지를 모두 실제 업무에 사용하고 있습니다. 이 글에서는 2026년 7월 기준 최신 버전으로:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;각 AI의 &lt;b&gt;진짜 강점과 약점&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;5가지 실무 시나리오&lt;/b&gt;별 어떤 걸 써야 할까&lt;/li&gt;
&lt;li&gt;&lt;b&gt;가격과 무료 tier&lt;/b&gt; 정확한 비교&lt;/li&gt;
&lt;li&gt;한국 사용자 관점의 특별 고려사항&lt;/li&gt;
&lt;li&gt;최종 추천 매트릭스&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5초 안에 답을 원하시는 분은 &lt;b&gt;&lt;u&gt;30초 요약&lt;/u&gt;&lt;/b&gt;으로 이동하세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글은 앞으로 &lt;b&gt;총 15편&lt;/b&gt;의 Claude 시리즈의 오프닝입니다. 시리즈 전체 안내는 &lt;b&gt;&lt;u&gt;글 하단&lt;/u&gt;&lt;/b&gt;에 있습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;30초 요약 - 상황별 정답&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;바쁘신 분들을 위한 결론입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 사용자라면 추천 AI 이유&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;개발자&amp;middot;DBA&amp;middot;엔지니어&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;Claude Opus 4.8&lt;/td&gt;
&lt;td&gt;SWE-bench 코딩 벤치마크 최상위, Claude Code CLI 무료 포함&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;글쓰기&amp;middot;문서 작업 중심&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;Claude Sonnet 5&lt;/td&gt;
&lt;td&gt;자연스러운 문장, 200K 컨텍스트, 뉘앙스 강함&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;Microsoft Office 사용자&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;Copilot&lt;/td&gt;
&lt;td&gt;Word/Excel/PPT 네이티브 통합&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;Google Workspace 사용자&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;Gemini&lt;/td&gt;
&lt;td&gt;Gmail/Docs 네이티브 통합, 무료 tier 관대&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;만능&amp;middot;다양한 작업&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;ChatGPT&lt;/td&gt;
&lt;td&gt;이미지 생성, Sora 비디오, 광범위 도구&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;긴 문서 분석 (수백 페이지)&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;Gemini 3 Pro&lt;/td&gt;
&lt;td&gt;1M 컨텍스트 (Big 4 중 최대)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;연구&amp;middot;리서치&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;Perplexity + Claude 조합&lt;/td&gt;
&lt;td&gt;출처 인용 + 심층 분석&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;가장 저렴한 코딩 도구&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;GitHub Copilot&lt;/td&gt;
&lt;td&gt;$10/월 최저가&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;한 줄 요약&lt;/b&gt;: &lt;b&gt;Claude는 깊이, ChatGPT는 만능, Gemini는 통합, Copilot은 Office 워크플로우&lt;/b&gt;.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;각 AI 상세 프로필&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  ChatGPT (OpenAI) - 만능형&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2026년 현재 상태:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;모델: GPT-5.2 (일반), GPT-5.4 (Pro)&lt;/li&gt;
&lt;li&gt;시장 점유율: &lt;b&gt;약 68%&lt;/b&gt; (Big 4 중 1위)&lt;/li&gt;
&lt;li&gt;주간 사용자: &lt;b&gt;800M+&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;컨텍스트: 128K 토큰&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;강점:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;가장 익숙하고 대중적 (거의 표준)&lt;/li&gt;
&lt;li&gt;이미지 생성 (DALL-E), 비디오 생성 (Sora)&lt;/li&gt;
&lt;li&gt;Advanced Voice, Custom GPTs, Agent Mode&lt;/li&gt;
&lt;li&gt;서드파티 통합 압도적으로 많음&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;약점:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;무료 tier에 광고 도입 (미국 기준, 2026년 도입)&lt;/li&gt;
&lt;li&gt;특정 분야 심화는 Claude에게 밀림&lt;/li&gt;
&lt;li&gt;코딩 벤치마크에서 Claude Opus 대비 뒤짐&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;가격 (2026년 7월 기준):&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;Free: GPT-5.2 (일부 제한)
Go: $8/월 (신흥국 대상)
Plus: $20/월 (개인 표준)
Pro: $100/월 (신모델 우선 접근, 5배 사용량)
Business: $25/석/월 (팀용)
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;한 줄 평&lt;/b&gt;: &quot;확신이 없다면 이걸로 시작하세요.&quot;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  Claude (Anthropic) - 깊이형&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2026년 현재 상태:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;모델: &lt;b&gt;Opus 4.8&lt;/b&gt; (플래그십), &lt;b&gt;Sonnet 5&lt;/b&gt; (밸런스), &lt;b&gt;Haiku 4.5&lt;/b&gt; (빠름), Fable 5 (API 전용)&lt;/li&gt;
&lt;li&gt;특화: &lt;b&gt;코딩 벤치마크 최상위&lt;/b&gt; (SWE-bench)&lt;/li&gt;
&lt;li&gt;컨텍스트: 200K (기본), 1M (베타)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Claude Code&lt;/b&gt;: 터미널 기반 코딩 에이전트 (Pro부터 무료 포함)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Cowork&lt;/b&gt;: 데스크톱 에이전트 (모든 플랜 포함)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;강점:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;코딩과 긴 문서 처리에서 압도적&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;자연스럽고 뉘앙스 있는 글쓰기&lt;/li&gt;
&lt;li&gt;사실성 높음 (환각률 낮은 편)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Claude Code, Cowork 모두 Pro에 포함&lt;/b&gt; &amp;mdash; 별도 결제 없음&lt;/li&gt;
&lt;li&gt;안전성&amp;middot;정확성 중시&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;약점:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이미지 생성 불가 (텍스트 중심)&lt;/li&gt;
&lt;li&gt;서드파티 통합이 ChatGPT보다 적음&lt;/li&gt;
&lt;li&gt;Voice 모드 등 멀티모달 상대적으로 제한적&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;가격 (2026년 7월 기준):&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;Free: Sonnet 5 접근 (5시간 rolling window, 6월 30일 이후 업그레이드)
Pro: $20/월 ($17/월 annual) &amp;mdash; Claude Code + Cowork 포함
Max 5x: $100/월 (Pro의 5배 사용량)
Max 20x: $200/월 (Pro의 20배)
Team Standard: $25/석/월 ($20 annual)
Team Premium: $125/석/월 ($100 annual) &amp;mdash; Claude Code 포함
Enterprise: 맞춤 (SSO, 감사, 확장 컨텍스트)
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;한 줄 평&lt;/b&gt;: &quot;깊이 있는 작업이 필요하면 이걸로.&quot;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;참고&lt;/b&gt;: 정확한 최신 가격은 &lt;a href=&quot;https://claude.com/pricing&quot;&gt;claude.com/pricing&lt;/a&gt; 에서 확인하세요. Anthropic 요금제는 자주 조정됩니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  Gemini (Google) - 통합형&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2026년 현재 상태:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;모델: Gemini 3 Pro (표준), 3.1 Pro (최신)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;LMArena 상위권&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;컨텍스트: &lt;b&gt;1M 토큰&lt;/b&gt; (Big 4 중 최대)&lt;/li&gt;
&lt;li&gt;Google Workspace 완전 통합&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;강점:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;1M 컨텍스트 윈도우&lt;/b&gt; (수백 페이지 문서 분석 가능)&lt;/li&gt;
&lt;li&gt;Gmail, Docs, Drive, Sheets 네이티브 통합&lt;/li&gt;
&lt;li&gt;&lt;b&gt;무료 tier가 가장 관대함&lt;/b&gt; (Deep Research 포함)&lt;/li&gt;
&lt;li&gt;GPQA Diamond 벤치마크 최상위 (과학&amp;middot;수학 특화)&lt;/li&gt;
&lt;li&gt;Deep Think 모드 (심층 추론)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;약점:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Google 계정 필수&lt;/li&gt;
&lt;li&gt;특정 분야는 ChatGPT/Claude 대비 뒤짐&lt;/li&gt;
&lt;li&gt;인터페이스가 직관적이지 않다는 평&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;가격 (2026년 7월 기준):&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;Free: Gemini 3 Pro 접근 (Deep Research 포함)
AI Pro: $20/월
AI Ultra: $100/월 (개발자용)
AI Ultra 20x: $200/월
Gemini Business (Workspace): $20/사용자/월
Gemini Enterprise: $30~36/사용자/월
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;한 줄 평&lt;/b&gt;: &quot;Google 사용자라면 안 쓸 이유가 없다.&quot;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  Microsoft Copilot - Office형&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2026년 현재 상태:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;엔진: &lt;b&gt;OpenAI GPT-5.1&lt;/b&gt; (라이선싱)&lt;/li&gt;
&lt;li&gt;통합: Windows 11, Microsoft 365, Teams, Edge&lt;/li&gt;
&lt;li&gt;&lt;b&gt;GitHub Copilot&lt;/b&gt;은 별개 제품 (코딩 특화)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;강점:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Word, Excel, PowerPoint 안에서 직접 사용&lt;/li&gt;
&lt;li&gt;Microsoft 365 데이터 (이메일, 캘린더, 팀즈) 통합&lt;/li&gt;
&lt;li&gt;엔터프라이즈 보안&amp;middot;컴플라이언스 강력&lt;/li&gt;
&lt;li&gt;GitHub Copilot은 IDE 인라인 완성 여전히 강력&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;약점:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Microsoft 생태계 밖에서는 매력 부족&lt;/li&gt;
&lt;li&gt;GPT-5.1 기반이라 ChatGPT보다 반 발자국 뒤짐&lt;/li&gt;
&lt;li&gt;개인 사용자 대상 매력도 상대적으로 낮음&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;가격 (2026년 7월 기준):&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;stata&quot;&gt;&lt;code&gt;GitHub Copilot: $10/월 ★ 가장 저렴한 코딩 AI
GitHub Copilot Pro+: $39/월 (Claude Opus 등 접근)
Copilot Pro (개인): $20/월
Microsoft 365 Premium: $19.99/월 (Copilot 포함)
Copilot Business: $30/사용자/월
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;한 줄 평&lt;/b&gt;: &quot;Office 없이 살 수 없다면 필수.&quot;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;★ 5가지 실무 시나리오별 비교&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반론 비교는 이미 인터넷에 많으니, &lt;b&gt;실제 실무 상황&lt;/b&gt;에서 어떤 걸 써야 하는지 정리했습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;시나리오 1: 개발자&amp;middot;DBA의 코딩 작업&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;우승: Claude (Claude Code)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI 강점 단점&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;Claude Opus 4.8&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;SWE-bench 최상위, 아키텍처 이해, 대규모 리팩터링&lt;/td&gt;
&lt;td&gt;이미지 생성 없음&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GitHub Copilot&lt;/td&gt;
&lt;td&gt;IDE 인라인 완성 최강, $10/월 최저가&lt;/td&gt;
&lt;td&gt;복잡한 추론 약함&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GPT-5.4&lt;/td&gt;
&lt;td&gt;다목적 활용&lt;/td&gt;
&lt;td&gt;Claude 대비 코딩 벤치마크 뒤짐&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gemini 3.1 Pro&lt;/td&gt;
&lt;td&gt;긴 코드베이스 이해 (1M 컨텍스트)&lt;/td&gt;
&lt;td&gt;실무 프레임워크 상대적 약함&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;추천 조합&lt;/b&gt;: &lt;b&gt;GitHub Copilot ($10/월) + Claude Pro ($20/월)&lt;/b&gt; = 총 $30/월&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Copilot으로 IDE 자동완성 (반복 코드)&lt;/li&gt;
&lt;li&gt;Claude Code로 복잡한 리팩터링과 아키텍처&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 조합이 개발자&amp;middot;DBA에게 최고의 가성비입니다. 저 역시 이 조합으로 사용하고 있습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;시나리오 2: 글쓰기&amp;middot;문서 작업&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;우승: Claude&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이건 대부분의 전문 작가&amp;middot;에디터가 동의합니다. Claude는:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;톤과 뉘앙스를 가장 잘 살림&lt;/li&gt;
&lt;li&gt;사용자의 스타일을 학습해서 일관성 유지&lt;/li&gt;
&lt;li&gt;200K 컨텍스트로 긴 문서도 안정적&lt;/li&gt;
&lt;li&gt;Projects 기능으로 스타일 가이드 지속 적용&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;avrasm&quot;&gt;&lt;code&gt;ChatGPT: 편리하지만 뉘앙스 약함
Claude: 자연스러움 최강 (★ 추천)
Gemini: NotebookLM은 좋음, 일반 글쓰기는 평범
Copilot: Word 안에서만 강점
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;시나리오 3: 데이터 분석&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;우승: 상황에 따라 다름&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;도구 강점 적합한 상황&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;ChatGPT&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;Code Interpreter, 시각화&lt;/td&gt;
&lt;td&gt;CSV/Excel 분석, 그래프 생성&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;Claude&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;정확한 계산, 코드 리뷰&lt;/td&gt;
&lt;td&gt;Python&amp;middot;SQL 분석, 복잡한 로직&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;Gemini&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;Sheets 통합, 1M 컨텍스트&lt;/td&gt;
&lt;td&gt;Google Sheets 분석, 대용량&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;Copilot&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;Excel 네이티브 통합&lt;/td&gt;
&lt;td&gt;Excel 안에서 직접 분석&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Excel/Google Sheets를 이미 쓰고 있다면 그 생태계의 AI가 편리합니다. 독립적 분석은 ChatGPT의 Code Interpreter가 강력합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;시나리오 4: 이메일&amp;middot;업무 문서&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;우승: 회사 이메일 시스템에 따라&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;less&quot;&gt;&lt;code&gt;Gmail 사용 &amp;rarr; Gemini (Gmail 안에서 직접 초안)
Outlook 사용 &amp;rarr; Copilot (Outlook 안에서 직접 초안)
독립 사용 &amp;rarr; Claude 또는 ChatGPT (복붙)
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한국 대기업은 대부분 Outlook + Microsoft 365 환경이라 &lt;b&gt;Copilot이 자연스러운 선택&lt;/b&gt;입니다. 스타트업&amp;middot;개인은 Gmail 기반이 많아 &lt;b&gt;Gemini&lt;/b&gt;가 유리합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;시나리오 5: 학습&amp;middot;연구&amp;middot;리서치&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;우승: Perplexity + Claude 조합&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 시나리오만큼은 Big 4 중에서만 고를 필요 없습니다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;1. Perplexity: 실시간 검색 + 출처 인용 (팩트 확인)
2. Claude: Perplexity 결과를 심층 분석&amp;middot;해석
3. Gemini Deep Research: 긴 리서치 자동화 (백그라운드 실행)
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;학술 논문&amp;middot;리서치 보고서 작성 시 이 조합이 가장 강력합니다. ChatGPT는 만능이지만 이 특정 시나리오에서는 위 조합 대비 약간 밀립니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  가격 비교 - $20 tier 정리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 대중적인 $20/월 tier의 실제 가치를 비교합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;항목 ChatGPT Plus Claude Pro Gemini AI Pro Copilot Pro&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;가격&lt;/td&gt;
&lt;td&gt;$20/월&lt;/td&gt;
&lt;td&gt;$20/월 ($17 annual)&lt;/td&gt;
&lt;td&gt;$20/월&lt;/td&gt;
&lt;td&gt;$20/월&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;핵심 모델&lt;/td&gt;
&lt;td&gt;GPT-5.2&lt;/td&gt;
&lt;td&gt;Opus 4.8 (제한), Sonnet 5&lt;/td&gt;
&lt;td&gt;Gemini 3 Pro&lt;/td&gt;
&lt;td&gt;GPT-5.1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;컨텍스트&lt;/td&gt;
&lt;td&gt;128K&lt;/td&gt;
&lt;td&gt;200K&lt;/td&gt;
&lt;td&gt;1M&lt;/td&gt;
&lt;td&gt;제한&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;이미지 생성&lt;/td&gt;
&lt;td&gt;✅ DALL-E&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;비디오 생성&lt;/td&gt;
&lt;td&gt;✅ Sora&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;부분&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;코딩 CLI&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅ Claude Code 포함&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;데스크톱 에이전트&lt;/td&gt;
&lt;td&gt;Agent Mode&lt;/td&gt;
&lt;td&gt;✅ Cowork 포함&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Office 통합&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Voice Mode&lt;/td&gt;
&lt;td&gt;✅ 최강&lt;/td&gt;
&lt;td&gt;제한적&lt;/td&gt;
&lt;td&gt;✅ Live&lt;/td&gt;
&lt;td&gt;제한&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;개인 사용자 관점의 가성비 순위:&lt;/b&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;Claude Pro&lt;/b&gt; &amp;mdash; Claude Code + Cowork 포함해서 $20는 헐값&lt;/li&gt;
&lt;li&gt;&lt;b&gt;ChatGPT Plus&lt;/b&gt; &amp;mdash; 이미지/비디오/음성 다 되는 만능&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Gemini AI Pro&lt;/b&gt; &amp;mdash; Google 사용자면 압도적&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Copilot Pro&lt;/b&gt; &amp;mdash; Office 사용자 아니면 매력도 낮음&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  한국 사용자 관점의 특별 고려사항&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한국어 사용자 입장에서 반드시 알아야 할 5가지입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 한국어 품질&lt;/h3&gt;
&lt;pre class=&quot;avrasm&quot;&gt;&lt;code&gt;Claude: 매우 자연스러움 ★
ChatGPT: 자연스러움 (거의 동급)
Gemini: 자연스럽지만 가끔 어색
Copilot: ChatGPT와 동일 엔진 기반
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한국어 글쓰기는 Claude가 근소하게 우위입니다. 다만 큰 차이는 아니고, 사용 패턴에 따라 체감 차이가 있을 수 있습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. 결제 방식&lt;/h3&gt;
&lt;pre class=&quot;avrasm&quot;&gt;&lt;code&gt;Claude: 카드 결제 (웹), 앱스토어 결제 (iOS)
ChatGPT: 카드 결제
Gemini: Google Play 통합, 카드
Copilot: Microsoft 계정 결제
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;주의&lt;/b&gt;: 애플 앱스토어 결제 시 약 30% 마크업이 붙어서 실제 $20 &amp;rarr; 30,000원+가 됩니다. 웹에서 직접 카드 결제가 저렴합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. 한국 서비스 통합&lt;/h3&gt;
&lt;pre class=&quot;ldif&quot;&gt;&lt;code&gt;카카오톡, 네이버 등: 대부분 미지원
Google Workspace 사용자: Gemini 강력
Microsoft Office: Copilot 강력
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한국 SaaS(카톡, 국내 협업 도구 등)와 직접 통합은 아직 부족합니다. 이 부분은 향후 확장될 여지가 있습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4. 학교&amp;middot;기관 라이선스&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일부 대학교는 이미 ChatGPT 또는 Gemini 라이선스를 학생에게 무료 제공하고 있습니다. Anthropic도 Education 플랜을 대학&amp;middot;기관 대상으로 제공하니, 소속 기관에서 참여 여부를 확인하시면 무료 또는 할인 접근이 가능할 수 있습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5. 개인정보&lt;/h3&gt;
&lt;pre class=&quot;asciidoc&quot;&gt;&lt;code&gt;❌ 절대 입력하지 말 것:
- 주민등록번호
- 신용카드 번호
- 회사 기밀 정보
- 고객 개인정보

⚠️ 각 서비스의 학습 옵트아웃 설정 확인 필수
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude와 ChatGPT는 학습 옵트아웃 옵션을 제공합니다. Gemini는 Google 계정 설정에서 제어할 수 있습니다. 회사 기밀 정보는 어떤 AI에도 입력하지 않는 것이 안전합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  최종 추천 매트릭스&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;본인 상황에 맞는 최적 조합입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;개인 사용자&lt;/h3&gt;
&lt;pre class=&quot;markdown&quot;&gt;&lt;code&gt;  최우선: Claude Pro ($20/월)
        - 글쓰기, 코딩, 분석 모두 강력
        - Claude Code + Cowork 포함

  두 번째: ChatGPT Plus ($20/월)
        - 이미지/비디오 필요 시
        - Voice Mode 자주 쓸 때

  조합용: Gemini 무료 tier + Claude Pro
        - 리서치는 Gemini 무료로 커버
        - 심층 작업은 Claude Pro
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;직장인 (Microsoft 환경)&lt;/h3&gt;
&lt;pre class=&quot;stata&quot;&gt;&lt;code&gt;  Copilot Pro ($20/월) - 필수
  Claude Pro ($20/월) - 심층 작업용

합계 $40/월 = 강력한 조합
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;직장인 (Google 환경)&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;  Gemini 무료 또는 Business - Workspace 통합
  Claude Pro ($20/월) - 심층 작업

합계 $20~40/월
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;개발자&amp;middot;DBA&lt;/h3&gt;
&lt;pre class=&quot;stata&quot;&gt;&lt;code&gt;  Claude Pro ($20/월) - Claude Code CLI
  GitHub Copilot ($10/월) - IDE 자동완성

합계 $30/월 = 최강 조합
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;리서치&amp;middot;학습&lt;/h3&gt;
&lt;pre class=&quot;stata&quot;&gt;&lt;code&gt;  Perplexity Pro ($20/월) - 출처 인용
  Claude Pro ($20/월) - 심층 분석

합계 $40/월
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;마무리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2026년 AI 도구 시장은 &quot;하나만 쓰는 시대&quot;에서 &lt;b&gt;&quot;조합해서 쓰는 시대&quot;&lt;/b&gt; 로 넘어갔습니다. 각 도구가 명확한 강점을 갖고 있고, $10~40 조합으로 각자의 워크플로우를 최적화할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;저의 최종 추천 순서&lt;/b&gt;입니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;무료 tier로 3~4개 모두 사용&lt;/b&gt;해보기 (1주일)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;본인 워크플로우에 가장 잘 맞는 것 하나 선택&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;부족한 부분을 다른 도구로 보완&lt;/b&gt;하는 조합 완성&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개인에 취향에 맞는걸 찾고 활용하면서 기능별로 조금씩 다른 AI를 사용해보는것도 좋습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>AI (Claude 활용)</category>
      <category>ChatGPT Plus vs Claude Pro</category>
      <category>Claude ChatGPT 차이</category>
      <category>Claude vs CharGPT</category>
      <category>Claude 사용</category>
      <category>Claude 요금제</category>
      <category>microsoft 365 copilot</category>
      <category>개발자 ai 도구</category>
      <category>소니스토리</category>
      <category>직장인 AI 도구</category>
      <category>한국어 AI 비교</category>
      <author>isony</author>
      <guid isPermaLink="true">https://isony.tistory.com/349</guid>
      <comments>https://isony.tistory.com/entry/AI-%EB%8F%84%EA%B5%AC-%EB%B9%84%EA%B5%90-Claude-vs-ChatGPT-vs-Gemini-vs-Copilot-2026-%EC%B5%9C%EC%8B%A0-%EC%99%84%EB%B2%BD-%EB%B9%84%EA%B5%90-%EC%8B%A4%EB%AC%B4%EC%9E%90-%EA%B4%80%EC%A0%90#entry349comment</comments>
      <pubDate>Wed, 8 Jul 2026 06:52:16 +0900</pubDate>
    </item>
    <item>
      <title>의약품 반품 보상 프로그램 만들기 &amp;mdash; 단계별 강의 (3편 &amp;middot; 완성)</title>
      <link>https://isony.tistory.com/entry/%EC%9D%98%EC%95%BD%ED%92%88-%EB%B0%98%ED%92%88-%EB%B3%B4%EC%83%81-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%A8-%EB%A7%8C%EB%93%A4%EA%B8%B0-%E2%80%94-%EB%8B%A8%EA%B3%84%EB%B3%84-%EA%B0%95%EC%9D%98-3%ED%8E%B8-%C2%B7-%EC%99%84%EC%84%B1</link>
      <description>&lt;h1&gt;의약품 반품 보상 프로그램 만들기 &amp;mdash; 단계별 강의 (3편 &amp;middot; 완성)&lt;/h1&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1편에서 &quot;두뇌&quot;(파싱&amp;middot;대조&amp;middot;보상), 2편에서 &quot;눈&quot;(바코드 디코드)을 만들었다. 3편은 **사람이 쓰는 화면(WinForms)**을 붙여 완성한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;완성 후 기능: 이미지 &lt;b&gt;여러 장 불러오기&lt;/b&gt; &amp;rarr; 자동 판독 &amp;rarr; &lt;b&gt;미리보기 + 파란 박스/번호 라벨&lt;/b&gt; &amp;rarr; &lt;b&gt;확대/축소&amp;middot;이동&lt;/b&gt; &amp;rarr; &lt;b&gt;영역 드래그 재판독&lt;/b&gt; &amp;rarr; 흐린 코드 &lt;b&gt;가독문자 OCR 보완&lt;/b&gt; &amp;rarr; &lt;b&gt;그리드 편집 + 보상 계산 + 총액&lt;/b&gt; &amp;rarr; &lt;b&gt;배포(설치 파일)&lt;/b&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 편도 설명을 자세히 넣었다. WinForms가 처음이어도 따라올 수 있게 개념부터 짚는다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;들어가기 전에 &amp;mdash; WinForms 핵심 개념 5가지&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3편 내내 쓰는 개념이라 먼저 한 번에 정리한다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;Form(폼)&lt;/b&gt; = 창 하나. MainForm : Form이 우리 메인 창이다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Control(컨트롤)&lt;/b&gt; = 창 안의 부품. 버튼(Button), 표(DataGridView), 그림판(Panel) 등.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Dock(도킹)&lt;/b&gt; = 부품을 창의 어느 변에 &quot;붙일지&quot;. Dock = DockStyle.Top이면 위쪽에 가로로 꽉 차게, Fill이면 남은 공간을 다 채움. 좌표를 일일이 안 줘도 창 크기에 맞춰 배치된다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;이벤트(Event)&lt;/b&gt; = &quot;버튼이 눌리면 이 함수를 실행&quot;. button.Click += OnClick;처럼 함수를 **연결(구독)**한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;그리기(OnPaint)&lt;/b&gt; = 부품이 화면을 다시 그릴 때 호출되는 함수. 우리가 직접 이미지&amp;middot;박스를 그릴 때 여기에 코드를 넣는다.&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;  우리는 화면을 &lt;b&gt;코드로&lt;/b&gt; 만든다(디자이너 끌어다 놓기 대신). 코드로 만들면 무엇이 왜 배치되는지 명확히 보이고, 복습&amp;middot;수정이 쉽다. 디자이너(.Designer.cs)는 쓰지 않는다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전체 화면 구성(완성형):&lt;/p&gt;
&lt;pre class=&quot;markdown&quot;&gt;&lt;code&gt;┌───────────────────────────────────────────────┐
│ [파일 불러오기][보상 계산]  상태문구            │  &amp;larr; top (Dock=Top)
├──────────────────────────┬────────────────────┤
│                          │                    │
│      이미지 미리보기       │     결과 그리드     │  &amp;larr; split(좌:캔버스 / 우:표)
│   (파란 박스 + 라벨)       │  (편집&amp;middot;결과)        │
│                          │                    │
│ [◀][1/5][▶][&amp;minus;][+][맞춤]   │                    │  &amp;larr; navBar (캔버스 아래)
│ [영역판독][OCR]  힌트      │                    │
├──────────────────────────┴────────────────────┤
│ 총 보상 금액: 0 원                              │  &amp;larr; bottom (Dock=Bottom)
└───────────────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Lesson 8 &amp;mdash; WinForms 골격: 파일 열기 + 그리드 + 보상&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  목표&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;콘솔을 &lt;b&gt;WinForms 앱&lt;/b&gt;으로 바꾸고, 이미지를 여러 장 골라 &amp;rarr; 자동 판독 &amp;rarr; 표에 채우고 &amp;rarr; 보상 계산까지 하는 &lt;b&gt;최소 동작 화면&lt;/b&gt;을 만든다. (미리보기&amp;middot;줌&amp;middot;OCR은 다음 Lesson에서 추가)&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  개념: 프로젝트 종류 바꾸기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금까지는 콘솔(OutputType=Exe, net8.0)이었다. WinForms로 바꾸려면 .csproj를 수정한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;OutputType &amp;rarr; &lt;b&gt;WinExe&lt;/b&gt;(창 앱, 콘솔 검은 창 안 뜸)&lt;/li&gt;
&lt;li&gt;TargetFramework &amp;rarr; &lt;b&gt;net8.0-windows&lt;/b&gt;(윈도우 전용 기능 사용)&lt;/li&gt;
&lt;li&gt;UseWindowsForms &amp;rarr; &lt;b&gt;true&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  코드 (8-1) .csproj&lt;/h3&gt;
&lt;pre class=&quot;xml&quot;&gt;&lt;code&gt;&amp;lt;Project Sdk=&quot;Microsoft.NET.Sdk&quot;&amp;gt;
  &amp;lt;PropertyGroup&amp;gt;
    &amp;lt;OutputType&amp;gt;WinExe&amp;lt;/OutputType&amp;gt;
    &amp;lt;TargetFramework&amp;gt;net8.0-windows&amp;lt;/TargetFramework&amp;gt;
    &amp;lt;UseWindowsForms&amp;gt;true&amp;lt;/UseWindowsForms&amp;gt;
    &amp;lt;ImplicitUsings&amp;gt;enable&amp;lt;/ImplicitUsings&amp;gt;
    &amp;lt;Nullable&amp;gt;enable&amp;lt;/Nullable&amp;gt;
    &amp;lt;RootNamespace&amp;gt;PharmaReturn&amp;lt;/RootNamespace&amp;gt;
    &amp;lt;Platforms&amp;gt;x64&amp;lt;/Platforms&amp;gt;
    &amp;lt;PlatformTarget&amp;gt;x64&amp;lt;/PlatformTarget&amp;gt;
  &amp;lt;/PropertyGroup&amp;gt;

  &amp;lt;ItemGroup&amp;gt;
    &amp;lt;PackageReference Include=&quot;ZXingCpp&quot; Version=&quot;0.5.1&quot; /&amp;gt;
    &amp;lt;PackageReference Include=&quot;ZXing.Net&quot; Version=&quot;0.16.10&quot; /&amp;gt;
    &amp;lt;PackageReference Include=&quot;SixLabors.ImageSharp&quot; Version=&quot;2.1.9&quot; /&amp;gt;
  &amp;lt;/ItemGroup&amp;gt;

  &amp;lt;ItemGroup&amp;gt;
    &amp;lt;None Include=&quot;data\**\*&quot; CopyToOutputDirectory=&quot;PreserveNewest&quot; /&amp;gt;
  &amp;lt;/ItemGroup&amp;gt;
&amp;lt;/Project&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Tesseract(OCR) 패키지는 Lesson 11에서 추가한다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  코드 (8-2) Program.cs &amp;mdash; 진입점&lt;/h3&gt;
&lt;pre class=&quot;cs&quot;&gt;&lt;code&gt;using System;
using System.Windows.Forms;

namespace PharmaReturn;

internal static class Program
{
    [STAThread]                                   // ① 윈도우 UI는 STA 스레드에서 시작
    private static void Main()
    {
        Application.EnableVisualStyles();         // ② 요즘 윈도우 테마 적용
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new MainForm());          // ③ 메인 창을 띄우고 대기
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;  [STAThread]는 WinForms 필수 표시(클립보드&amp;middot;파일 대화상자 등이 단일 스레드 아파트 모델을 요구). 빼면 일부 대화상자가 예외를 던진다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  코드 (8-3) MainForm.cs &amp;mdash; 최소 버전&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 미리보기 없이, 파일 열기 + 표 + 보상만 되는 최소 화면을 만든다. (다음 Lesson에서 이 파일을 키운다.)&lt;/p&gt;
&lt;pre class=&quot;cs&quot;&gt;&lt;code&gt;using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Windows.Forms;

namespace PharmaReturn;

public sealed class MainForm : Form
{
    private readonly Button _btnLoad = new() { Text = &quot;파일 불러오기 (여러 개)&quot;, AutoSize = true, Margin = new Padding(4) };
    private readonly Button _btnCalc = new() { Text = &quot;보상 계산&quot;, AutoSize = true, Margin = new Padding(4) };
    private readonly Label _lblStatus = new() { AutoSize = true, Margin = new Padding(12, 10, 4, 4), Text = &quot;이미지를 불러오세요.&quot; };
    private readonly Label _lblTotal = new() { AutoSize = true, Text = &quot;총 보상 금액: 0 원&quot; };

    private readonly DataGridView _dgv = new()
    {
        Dock = DockStyle.Fill, AllowUserToAddRows = false,
        AutoGenerateColumns = false, RowHeadersVisible = false,
    };

    private readonly string _csvPath = Path.Combine(AppContext.BaseDirectory, &quot;data&quot;, &quot;deliveries.csv&quot;);

    public MainForm()
    {
        Text = &quot;약국 반품 보상&quot;;
        Width = 900; Height = 600; StartPosition = FormStartPosition.CenterScreen;
        _lblTotal.Font = new Font(_lblTotal.Font, FontStyle.Bold);

        BuildGrid();

        var top = new FlowLayoutPanel { Dock = DockStyle.Top, Height = 48, Padding = new Padding(8, 6, 8, 6) };
        top.Controls.AddRange(new Control[] { _btnLoad, _btnCalc, _lblStatus });

        var bottom = new Panel { Dock = DockStyle.Bottom, Height = 40, Padding = new Padding(12, 8, 8, 8) };
        _lblTotal.Dock = DockStyle.Left; bottom.Controls.Add(_lblTotal);

        Controls.Add(_dgv);     // 가운데(Fill)
        Controls.Add(top);      // 위
        Controls.Add(bottom);   // 아래

        _btnLoad.Click += OnLoad;
        _btnCalc.Click += OnCalc;
        _dgv.DataError += (_, e) =&amp;gt; e.ThrowException = false; // 콤보 값 오류 무시
    }

    private void BuildGrid()
    {
        void Col(string name, string header, int w, bool ro = true)
            =&amp;gt; _dgv.Columns.Add(new DataGridViewTextBoxColumn { Name = name, HeaderText = header, Width = w, ReadOnly = ro });

        Col(&quot;file&quot;, &quot;파일&quot;, 110); Col(&quot;gtin&quot;, &quot;GTIN&quot;, 130); Col(&quot;lot&quot;, &quot;로트&quot;, 80);
        Col(&quot;expiry&quot;, &quot;유통기한&quot;, 90); Col(&quot;serial&quot;, &quot;일련번호&quot;, 70);
        var reason = new DataGridViewComboBoxColumn { Name = &quot;reason&quot;, HeaderText = &quot;사유&quot;, Width = 64 };
        reason.Items.AddRange(&quot;만기&quot;, &quot;손상&quot;, &quot;기타&quot;);
        _dgv.Columns.Add(reason);
        Col(&quot;reqty&quot;, &quot;요청수량&quot;, 64, ro: false);
        Col(&quot;approved&quot;, &quot;승인&quot;, 52); Col(&quot;credit&quot;, &quot;보상금액&quot;, 90); Col(&quot;status&quot;, &quot;상태&quot;, 220);
    }

    private void OnLoad(object? sender, EventArgs e)
    {
        using var ofd = new OpenFileDialog
        {
            Multiselect = true,                                   // ★ 여러 개 선택
            Filter = &quot;이미지 (*.png;*.jpg;*.jpeg;*.bmp)|*.png;*.jpg;*.jpeg;*.bmp|모든 파일|*.*&quot;,
        };
        if (ofd.ShowDialog(this) != DialogResult.OK) return;

        var repo = DeliveryRepository.LoadCsv(_csvPath);
        _dgv.Rows.Clear();

        foreach (var path in ofd.FileNames)
        {
            var codes = BarcodeServiceCpp.DecodeDetailed(path);   // 2편 디코더
            if (codes.Count == 0)
            {
                _dgv.Rows.Add(Path.GetFileName(path), &quot;&quot;, &quot;&quot;, &quot;&quot;, &quot;&quot;, &quot;만기&quot;, &quot;&quot;, &quot;&quot;, &quot;&quot;, &quot;디코드 실패&quot;);
                continue;
            }
            foreach (var c in codes)
            {
                var f = Gs1Parser.Parse(c.Text);                  // 1편 파서
                int prefill = f.Gtin is null ? 0
                    : repo.FindByGtinLot(f.Gtin, f.Lot).Sum(m =&amp;gt; m.DeliveredQty);
                _dgv.Rows.Add(Path.GetFileName(path), f.Gtin ?? &quot;&quot;, f.Lot ?? &quot;&quot;,
                    f.Expiry?.ToString(&quot;yyyy-MM-dd&quot;) ?? &quot;&quot;, f.Serial ?? &quot;&quot;,
                    &quot;만기&quot;, prefill &amp;gt; 0 ? prefill.ToString() : &quot;&quot;, &quot;&quot;, &quot;&quot;, &quot;불러옴&quot;);
            }
        }
        _lblStatus.Text = $&quot;{_dgv.Rows.Count}개 코드 인식. 사유&amp;middot;요청수량 확인 후 [보상 계산].&quot;;
    }

    private void OnCalc(object? sender, EventArgs e)
    {
        var svc = new CompensationService(DeliveryRepository.LoadCsv(_csvPath));
        decimal total = 0;
        foreach (DataGridViewRow row in _dgv.Rows)
        {
            string gtin = Cell(row, &quot;gtin&quot;);
            if (string.IsNullOrEmpty(gtin)) continue;
            string lot = Cell(row, &quot;lot&quot;);
            DateOnly? exp = DateOnly.TryParse(Cell(row, &quot;expiry&quot;), out var d) ? d : null;
            ReturnReason reason = Cell(row, &quot;reason&quot;) switch { &quot;손상&quot; =&amp;gt; ReturnReason.Damage, &quot;기타&quot; =&amp;gt; ReturnReason.Other, _ =&amp;gt; ReturnReason.Expiry };
            int qty = int.TryParse(Cell(row, &quot;reqty&quot;), out var q) ? q : 0;

            var r = svc.Evaluate(new ReturnRequest(gtin, string.IsNullOrEmpty(lot) ? null : lot, exp, qty, reason));
            total += r.CreditAmount;
            row.Cells[&quot;approved&quot;].Value = r.ApprovedQty.ToString();
            row.Cells[&quot;credit&quot;].Value = r.CreditAmount.ToString(&quot;N0&quot;);
            row.Cells[&quot;status&quot;].Value = $&quot;[{r.Status}] {r.Message}&quot;;
        }
        _lblTotal.Text = $&quot;총 보상 금액: {total:N0} 원&quot;;
    }

    private static string Cell(DataGridViewRow row, string col) =&amp;gt; row.Cells[col].Value?.ToString() ?? &quot;&quot;;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;  핵심:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;레이아웃&lt;/b&gt;: top(Dock=Top), bottom(Dock=Bottom), _dgv(Fill)을 Controls.Add 한다. 추가 &lt;b&gt;순서가 중요&lt;/b&gt;하다 &amp;mdash; Fill을 먼저 넣고 Top/Bottom을 나중에 넣어야 가운데가 위/아래에 안 가린다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;OpenFileDialog { Multiselect = true }&lt;/b&gt;: 파일 여러 개 선택. ofd.FileNames로 경로 배열을 받는다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;그리드&lt;/b&gt;: AutoGenerateColumns=false로 우리가 컬럼을 직접 정의(BuildGrid). &quot;사유&quot;는 콤보박스 컬럼, &quot;요청수량&quot;만 편집 가능.&lt;/li&gt;
&lt;li&gt;흐름: 각 파일 &amp;rarr; DecodeDetailed(2편) &amp;rarr; Gs1Parser.Parse(1편) &amp;rarr; 행 추가. [보상 계산]은 행을 돌며 CompensationService.Evaluate(1편).&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;  &lt;b&gt;deliveries.csv 준비&lt;/b&gt;: 1편의 data/deliveries.csv를 이 프로젝트에도 두고, &quot;출력 디렉터리로 복사 = 새 버전이면 복사&quot;로 설정(또는 위 csproj의 &amp;lt;None Include=&quot;data\**\*&quot; ...&amp;gt;).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;✅ 직접 해보기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;F5로 실행 &amp;rarr; [파일 불러오기]로 바코드 사진(2편에서 만든 test.png나 실제 사진) 선택 &amp;rarr; 표에 GTIN/유통기한/로트가 채워지고 &amp;rarr; [보상 계산] 누르면 승인&amp;middot;보상&amp;middot;총액이 나온다. &lt;b&gt;여기까지가 &quot;쓸 수 있는 앱&quot;의 첫 모습이다.&lt;/b&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Lesson 9 &amp;mdash; 이미지 미리보기 + 파란 박스 오버레이&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  목표&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;왼쪽에 현재 이미지를 보여주고, 판독한 코드 위치를 &lt;b&gt;파란 사각형 + 번호&amp;middot;문자 라벨&lt;/b&gt;로 겹쳐 그린다. 파일 간 [이전]/[다음] 이동도 넣는다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  개념 1: 커스텀 그림판 만들기 (Panel 상속)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이미지와 박스를 그리려면 &lt;b&gt;직접 그리는 컨트롤&lt;/b&gt;이 필요하다. Panel을 상속해 OnPaint(그리기)와 마우스 이벤트를 우리가 처리하는 ImageCanvas를 만든다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;DoubleBuffered = true: 깜빡임 방지(뒤에서 다 그린 뒤 한 번에 표시).&lt;/li&gt;
&lt;li&gt;OnPaint에서 Graphics로 이미지&amp;middot;도형&amp;middot;글자를 그린다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  개념 2: 두 좌표계와 변환 (아주 중요)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;원본 이미지 좌표&lt;/b&gt;: 디코더가 준 꼭짓점(2편). 사진 픽셀 기준.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;화면(컨트롤) 좌표&lt;/b&gt;: 캔버스에 실제로 그려지는 위치. 이미지를 비율 맞춰 줄여 그리므로 다르다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이미지가 그려진 사각형을 _dispRect라 하면, 원본의 점 (ix, iy)는 화면에서:&lt;/p&gt;
&lt;pre class=&quot;sqf&quot;&gt;&lt;code&gt;화면X = _dispRect.Left + ix &amp;times; (_dispRect.Width  / 이미지폭)
화면Y = _dispRect.Top  + iy &amp;times; (_dispRect.Height / 이미지높이)
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반대로 화면&amp;rarr;원본은 나누면 된다(영역 선택에서 쓴다). 이 변환 덕분에 &lt;b&gt;확대/축소해도 박스가 코드에 정확히 붙는다.&lt;/b&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  코드 (9-1) ImageCanvas.cs (완성형)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래는 미리보기&amp;middot;오버레이는 물론 &lt;b&gt;확대/축소&amp;middot;이동&amp;middot;영역 선택까지 포함한 완성본&lt;/b&gt;이다. 이번 Lesson은 &lt;b&gt;그리기&amp;middot;오버레이 부분&lt;/b&gt;(OnPaint, ComputeDispRect)에 집중하고, &lt;b&gt;확대/이동(줌&amp;middot;팬)&amp;middot;영역선택&lt;/b&gt;은 Lesson 10에서 설명한다. (한 파일이라 미리 통째로 둔다.)&lt;/p&gt;
&lt;pre class=&quot;cs&quot;&gt;&lt;code&gt;using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;

namespace PharmaReturn;

/// &amp;lt;summary&amp;gt;
/// 이미지를 비율 유지로 표시하고, 판독 위치를 파란 사각형 + 작은 라벨(번호&amp;middot;판독문자)로 겹쳐 그린다.
/// 확대/축소(줌)와 패닝을 지원하며, 마우스 드래그로 영역을 선택해 원본 픽셀 좌표로 돌려준다.
///  - 마우스 휠: 커서 기준 확대/축소
///  - 좌버튼 드래그: 영역 선택
///  - 가운데버튼 또는 Space+좌드래그: 화면 이동(패닝)
/// &amp;lt;/summary&amp;gt;
public sealed class ImageCanvas : Panel
{
    private Image? _image;
    private List&amp;lt;DecodedCode&amp;gt; _codes = new();

    private float _fitScale = 1f;          // 화면에 맞춘 기본 배율
    private float _zoom = 1f;              // 사용자 추가 배율(1=맞춤)
    private PointF _offset = PointF.Empty; // 패닝 이동
    private RectangleF _dispRect;          // 이미지가 그려진 영역(컨트롤 좌표)

    private bool _selecting;
    private Point _selStart;
    private Rectangle _selControl;

    private bool _panning;
    private Point _panStart;
    private PointF _panOffsetStart;
    private bool _spaceDown;

    public ImageCanvas()
    {
        DoubleBuffered = true;
        BackColor = SystemColors.ControlDark;
        Cursor = Cursors.Cross;
        TabStop = true; // Space 키 입력 받기
    }

    public void SetContent(Image? image, List&amp;lt;DecodedCode&amp;gt; codes)
    {
        _image?.Dispose();
        _image = image;
        _codes = codes ?? new();
        _selControl = Rectangle.Empty;
        ResetView();
    }

    public void SetCodes(List&amp;lt;DecodedCode&amp;gt; codes) { _codes = codes ?? new(); Invalidate(); }
    public bool HasImage =&amp;gt; _image is not null;

    public void ResetView() { _zoom = 1f; _offset = PointF.Empty; Invalidate(); }
    public void ZoomBy(float factor) =&amp;gt; ZoomAt(factor, new Point(ClientSize.Width / 2, ClientSize.Height / 2));

    public void ZoomAt(float factor, Point anchor)
    {
        if (_image is null) return;
        float newZoom = Math.Clamp(_zoom * factor, 1f, 12f);
        if (Math.Abs(newZoom - _zoom) &amp;lt; 0.0001f) return;
        ComputeDispRect();
        float ix = (anchor.X - _dispRect.Left) / _dispRect.Width;
        float iy = (anchor.Y - _dispRect.Top) / _dispRect.Height;
        _zoom = newZoom;
        ComputeDispRect(applyOffset: false);
        float targetLeft = anchor.X - ix * _dispRect.Width;
        float targetTop = anchor.Y - iy * _dispRect.Height;
        _offset = new PointF(targetLeft - _dispRect.Left, targetTop - _dispRect.Top);
        ClampOffset();
        Invalidate();
    }

    /// &amp;lt;summary&amp;gt;선택 영역을 원본 이미지 픽셀 좌표로 반환. 없으면 Empty.&amp;lt;/summary&amp;gt;
    public Rectangle GetSelectionImageRect()
    {
        if (_image is null || _selControl.Width &amp;lt; 3 || _selControl.Height &amp;lt; 3 || _dispRect.Width &amp;lt;= 0)
            return Rectangle.Empty;
        float sx = _image.Width / _dispRect.Width;
        float sy = _image.Height / _dispRect.Height;
        int ix = (int)Math.Round((_selControl.Left - _dispRect.Left) * sx);
        int iy = (int)Math.Round((_selControl.Top - _dispRect.Top) * sy);
        int iw = (int)Math.Round(_selControl.Width * sx);
        int ih = (int)Math.Round(_selControl.Height * sy);
        return new Rectangle(ix, iy, iw, ih);
    }

    // ── 입력(줌/팬/선택) ───────────────────────────────────
    protected override void OnMouseWheel(MouseEventArgs e)
    {
        base.OnMouseWheel(e);
        if (_image is null) return;
        Focus();
        ZoomAt(e.Delta &amp;gt; 0 ? 1.2f : 1f / 1.2f, e.Location);
    }

    protected override void OnMouseDown(MouseEventArgs e)
    {
        base.OnMouseDown(e);
        if (_image is null) return;
        Focus();
        bool pan = e.Button == MouseButtons.Middle || (e.Button == MouseButtons.Left &amp;amp;&amp;amp; _spaceDown);
        if (pan) { _panning = true; _panStart = e.Location; _panOffsetStart = _offset; Cursor = Cursors.SizeAll; }
        else if (e.Button == MouseButtons.Left)
        {
            _selecting = true; _selStart = e.Location;
            _selControl = new Rectangle(e.Location, Size.Empty); Invalidate();
        }
    }

    protected override void OnMouseMove(MouseEventArgs e)
    {
        base.OnMouseMove(e);
        if (_panning)
        {
            _offset = new PointF(_panOffsetStart.X + (e.X - _panStart.X), _panOffsetStart.Y + (e.Y - _panStart.Y));
            ClampOffset(); Invalidate();
        }
        else if (_selecting)
        {
            int x = Math.Min(_selStart.X, e.X), y = Math.Min(_selStart.Y, e.Y);
            _selControl = new Rectangle(x, y, Math.Abs(e.X - _selStart.X), Math.Abs(e.Y - _selStart.Y));
            Invalidate();
        }
    }

    protected override void OnMouseUp(MouseEventArgs e)
    {
        base.OnMouseUp(e);
        _selecting = false; _panning = false;
        Cursor = _spaceDown ? Cursors.SizeAll : Cursors.Cross;
    }

    protected override bool IsInputKey(Keys keyData) =&amp;gt; keyData == Keys.Space || base.IsInputKey(keyData);
    protected override void OnKeyDown(KeyEventArgs e) { base.OnKeyDown(e); if (e.KeyCode == Keys.Space) { _spaceDown = true; Cursor = Cursors.SizeAll; } }
    protected override void OnKeyUp(KeyEventArgs e) { base.OnKeyUp(e); if (e.KeyCode == Keys.Space) { _spaceDown = false; Cursor = Cursors.Cross; } }

    // ── 그리기 ─────────────────────────────────────────────
    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);
        var g = e.Graphics;

        if (_image is null)
        {
            TextRenderer.DrawText(g, &quot;파일을 불러오면 이미지가 여기에 표시됩니다.&quot;,
                Font, ClientRectangle, Color.White,
                TextFormatFlags.HorizontalCenter | TextFormatFlags.VerticalCenter);
            return;
        }

        g.InterpolationMode = InterpolationMode.HighQualityBicubic;
        ComputeDispRect();
        g.DrawImage(_image, _dispRect.X, _dispRect.Y, _dispRect.Width, _dispRect.Height);

        float sx = _dispRect.Width / _image.Width;     // 원본&amp;rarr;화면 배율
        float sy = _dispRect.Height / _image.Height;

        using var pen = new Pen(Color.DodgerBlue, 2f);
        using var labelBg = new SolidBrush(Color.FromArgb(210, 20, 90, 200));
        using var labelFg = new SolidBrush(Color.White);
        using var labelFont = new Font(Font.FontFamily, 8f, FontStyle.Bold);

        for (int i = 0; i &amp;lt; _codes.Count; i++)
        {
            var c = _codes[i];
            if (c.Corners is null || c.Corners.Length &amp;lt; 3) continue;

            var pts = new PointF[c.Corners.Length];
            for (int k = 0; k &amp;lt; pts.Length; k++)        // 원본 꼭짓점 &amp;rarr; 화면 좌표로 변환
                pts[k] = new PointF(_dispRect.Left + c.Corners[k].X * sx, _dispRect.Top + c.Corners[k].Y * sy);
            g.DrawPolygon(pen, pts);                    // 파란 사각형

            string label = $&quot;{i + 1}. {Short(c.Text)}&quot;; // 번호 + 판독문자 앞부분
            SizeF szf = g.MeasureString(label, labelFont);
            float lx = pts[0].X, ly = pts[0].Y - szf.Height - 2;
            if (ly &amp;lt; _dispRect.Top) ly = pts[0].Y + 2;
            g.FillRectangle(labelBg, lx, ly, szf.Width + 6, szf.Height + 2);
            g.DrawString(label, labelFont, labelFg, lx + 3, ly + 1);
        }

        if (_selControl.Width &amp;gt; 0 &amp;amp;&amp;amp; _selControl.Height &amp;gt; 0) // 영역 선택 점선
        {
            using var selPen = new Pen(Color.OrangeRed, 1.5f) { DashStyle = DashStyle.Dash };
            g.DrawRectangle(selPen, _selControl);
        }

        if (_zoom &amp;gt; 1.001f)
            TextRenderer.DrawText(g, $&quot;{_zoom * 100:0}%&quot;, Font, new Point(6, 6), Color.White);
    }

    // ── 보기 계산 ──────────────────────────────────────────
    private void ComputeDispRect(bool applyOffset = true)
    {
        if (_image is null) { _dispRect = RectangleF.Empty; return; }
        _fitScale = Math.Min((float)ClientSize.Width / _image.Width, (float)ClientSize.Height / _image.Height);
        float scale = _fitScale * _zoom;
        float w = _image.Width * scale, h = _image.Height * scale;
        float baseLeft = (ClientSize.Width - w) / 2f, baseTop = (ClientSize.Height - h) / 2f;
        _dispRect = applyOffset
            ? new RectangleF(baseLeft + _offset.X, baseTop + _offset.Y, w, h)
            : new RectangleF(baseLeft, baseTop, w, h);
    }

    private void ClampOffset()
    {
        ComputeDispRect(applyOffset: false);
        float maxX = Math.Max(0, (_dispRect.Width - ClientSize.Width) / 2f);
        float maxY = Math.Max(0, (_dispRect.Height - ClientSize.Height) / 2f);
        _offset = new PointF(Math.Clamp(_offset.X, -maxX, maxX), Math.Clamp(_offset.Y, -maxY, maxY));
    }

    private static string Short(string s) =&amp;gt; s.Length &amp;lt;= 16 ? s : s[..16] + &quot;&amp;hellip;&quot;;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;  이번 Lesson에서 볼 부분:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;OnPaint: 배경에 이미지를 _dispRect만큼 그리고, 각 코드의 &lt;b&gt;원본 꼭짓점 &amp;rarr; 화면 좌표&lt;/b&gt;(sx,sy 곱)로 변환해 DrawPolygon(파란 박스) + 라벨을 그린다.&lt;/li&gt;
&lt;li&gt;ComputeDispRect: 이미지를 화면에 &lt;b&gt;비율 유지로 가운데&lt;/b&gt; 배치하는 사각형 계산(_fitScale). 줌/패닝은 다음 Lesson.&lt;/li&gt;
&lt;li&gt;SetContent: 새 이미지&amp;middot;코드를 넣고 다시 그린다(Invalidate()는 &quot;다시 그려라&quot; 요청).&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  코드 (9-2) MainForm에 미리보기&amp;middot;이동 추가&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Lesson 8 MainForm을 다음과 같이 키운다(달라지는 부분 위주).&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;(a) 파일 1개의 상태를 묶는 작은 클래스 + 목록&lt;/b&gt;: MainForm 안 맨 위에 추가&lt;/p&gt;
&lt;pre class=&quot;cs&quot;&gt;&lt;code&gt;private sealed class LoadedFile
{
    public required string Path { get; init; }
    public List&amp;lt;DecodedCode&amp;gt; Codes { get; init; } = new();
    public bool Failed { get; set; }
}
private readonly List&amp;lt;LoadedFile&amp;gt; _files = new();
private int _current = -1;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;(b) 캔버스&amp;middot;이동 버튼 필드 추가&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;haxe&quot;&gt;&lt;code&gt;private readonly ImageCanvas _canvas = new() { Dock = DockStyle.Fill };
private readonly Button _btnPrev = new() { Text = &quot;◀ 이전&quot;, AutoSize = true, Margin = new Padding(4) };
private readonly Button _btnNext = new() { Text = &quot;다음 ▶&quot;, AutoSize = true, Margin = new Padding(4) };
private readonly Label _lblCounter = new() { AutoSize = true, Margin = new Padding(12, 10, 8, 4), Text = &quot;0 / 0&quot; };
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;(c) 레이아웃을 좌(캔버스)&amp;middot;우(그리드) 분할로&lt;/b&gt;: 생성자의 Controls.Add(_dgv) 부분을 아래로 교체&lt;/p&gt;
&lt;pre class=&quot;haxe&quot;&gt;&lt;code&gt;var navBar = new FlowLayoutPanel { Dock = DockStyle.Bottom, Height = 40, Padding = new Padding(6, 4, 6, 4) };
navBar.Controls.AddRange(new Control[] { _btnPrev, _lblCounter, _btnNext });
var left = new Panel { Dock = DockStyle.Fill };
left.Controls.Add(_canvas);     // 캔버스(Fill)
left.Controls.Add(navBar);      // 그 아래 이동바

var split = new SplitContainer { Dock = DockStyle.Fill, SplitterDistance = 640 };
split.Panel1.Controls.Add(left);   // 왼쪽: 미리보기
split.Panel2.Controls.Add(_dgv);   // 오른쪽: 그리드
Controls.Add(split);               // _dgv 대신 split을 Fill로

_btnPrev.Click += (_, _) =&amp;gt; Move(-1);
_btnNext.Click += (_, _) =&amp;gt; Move(+1);
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;(d) 불러올 때 파일별로 보관하고 현재 이미지 표시&lt;/b&gt;: OnLoad에서 행을 추가하면서 _files에도 담고, 끝에 ShowCurrent() 호출. 그리고 아래 메서드 추가&lt;/p&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;private void Move(int delta)
{
    if (_files.Count == 0) return;
    _current = Math.Clamp(_current + delta, 0, _files.Count - 1);
    ShowCurrent();
}

private void ShowCurrent()
{
    if (_current &amp;lt; 0 || _current &amp;gt;= _files.Count)
    { _canvas.SetContent(null, new List&amp;lt;DecodedCode&amp;gt;()); _lblCounter.Text = &quot;0 / 0&quot;; return; }

    var file = _files[_current];
    Image? img = null;
    try { img = LoadImageUnlocked(file.Path); } catch { }
    _canvas.SetContent(img, file.Codes);            // 이미지 + 그 파일의 코드(박스)
    _lblCounter.Text = $&quot;{_current + 1} / {_files.Count}  &amp;middot;  {Path.GetFileName(file.Path)}&quot;;
}

// 파일을 잠그지 않고 이미지 로드(원본 파일이 잠기면 곤란)
private static Image LoadImageUnlocked(string path)
{
    using var ms = new MemoryStream(File.ReadAllBytes(path));
    using var tmp = Image.FromStream(ms);
    return new Bitmap(tmp);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;  &lt;b&gt;왜 LoadImageUnlocked?&lt;/b&gt; Image.FromFile(path)는 그 파일을 &lt;b&gt;계속 잠근다&lt;/b&gt;(다른 데서 못 건드림). 바이트로 읽어 메모리에서 만들면 잠금이 안 걸린다. 사소하지만 실무에서 자주 무는 함정이다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Lesson 8의 OnLoad는 _files에 담도록 살짝 바꾸고(파일마다 LoadedFile 만들어 Codes에 추가), 디코드 결과 0개면 Failed=true로 표시한다. 완성형 전체 코드는 Lesson 12에 있다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;✅ 직접 해보기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실행 &amp;rarr; 사진 여러 장 불러오기 &amp;rarr; 왼쪽에 첫 이미지가 뜨고 코드 위에 &lt;b&gt;파란 박스 + &quot;1. ...&quot;&lt;/b&gt; 라벨이 보이며, [이전]/[다음]으로 사진을 넘길 수 있으면 성공.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Lesson 10 &amp;mdash; 확대/축소 + 이동(줌&amp;middot;패닝)&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  목표&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;미리보기를 휠/버튼으로 확대&amp;middot;축소하고, 확대 상태에서 화면을 끌어 이동한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  개념: &quot;맞춤 배율 &amp;times; 사용자 배율&quot; + 오프셋&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;_fitScale: 이미지를 창에 꽉 맞추는 기본 배율(Lesson 9).&lt;/li&gt;
&lt;li&gt;_zoom: 사용자가 추가로 거는 배율(1=맞춤, 2=2배&amp;hellip;). 실제 그리는 배율 = _fitScale &amp;times; _zoom.&lt;/li&gt;
&lt;li&gt;_offset: 확대 후 화면을 끌어 옮긴 양(패닝). ClampOffset으로 이미지가 화면 밖으로 너무 빠지지 않게 제한.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;커서 기준 확대&lt;/b&gt;(ZoomAt): 휠을 굴린 &lt;b&gt;커서 위치의 이미지 점이 그대로 있도록&lt;/b&gt; 오프셋을 보정한다 &amp;rarr; &quot;보던 지점이 유지되는&quot; 자연스러운 줌.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 메서드들은 이미 9-1 ImageCanvas.cs에 다 들어 있다(ZoomBy, ZoomAt, ResetView, OnMouseWheel, 패닝용 OnMouseDown/Move/Up, OnKeyDown/Up). 이번엔 &lt;b&gt;버튼만 연결&lt;/b&gt;하면 된다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;  &lt;b&gt;선택과 이동의 충돌 방지&lt;/b&gt;: 좌버튼 드래그는 &quot;영역 선택&quot;으로 이미 쓰고 있다. 그래서 **이동은 Space+좌드래그(또는 가운데 버튼)**로 분리했다(OnMouseDown의 pan 판정). 한 버튼에 두 동작을 욱여넣지 않는 게 사용성에 좋다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  코드: MainForm에 줌 버튼 추가&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;(a) 버튼 필드&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;haxe&quot;&gt;&lt;code&gt;private readonly Button _btnZoomIn  = new() { Text = &quot;＋&quot;,  AutoSize = true, Margin = new Padding(4), Width = 36 };
private readonly Button _btnZoomOut = new() { Text = &quot;－&quot;,  AutoSize = true, Margin = new Padding(4), Width = 36 };
private readonly Button _btnZoomFit = new() { Text = &quot;맞춤&quot;, AutoSize = true, Margin = new Padding(4) };
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;(b) navBar에 끼우기&lt;/b&gt; (Lesson 9의 navBar 줄을 교체)&lt;/p&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;navBar.Controls.AddRange(new Control[] { _btnPrev, _lblCounter, _btnNext, _btnZoomOut, _btnZoomIn, _btnZoomFit });
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;(c) 클릭 연결&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;coffeescript&quot;&gt;&lt;code&gt;_btnZoomIn.Click  += (_, _) =&amp;gt; _canvas.ZoomBy(1.25f);
_btnZoomOut.Click += (_, _) =&amp;gt; _canvas.ZoomBy(0.8f);
_btnZoomFit.Click += (_, _) =&amp;gt; _canvas.ResetView();
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;✅ 직접 해보기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실행 &amp;rarr; 이미지 위에서 &lt;b&gt;휠&lt;/b&gt;을 굴리면 커서 기준으로 확대/축소, &lt;b&gt;＋/－/맞춤&lt;/b&gt; 버튼도 동작, &lt;b&gt;Space+드래그&lt;/b&gt;로 이동되면 성공. 확대해도 파란 박스가 코드에 정확히 붙어 따라온다(좌표 변환 덕분).&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Lesson 11 &amp;mdash; 영역 판독 + 가독문자 OCR(Tesseract)&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  목표&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;① 마우스로 영역을 드래그해 그 부분만 다시 디코드(흐린/작은 코드 회수). ② 바코드가 안 읽히는 박스의 &lt;b&gt;인쇄문자&lt;/b&gt;를 OCR로 읽어 목록에 보완.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  개념 1: 영역 판독&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;캔버스는 드래그한 사각형을 GetSelectionImageRect()로 &lt;b&gt;원본 픽셀 좌표&lt;/b&gt;로 돌려준다(Lesson 9의 화면&amp;rarr;원본 변환). 그 사각형을 2편의 BarcodeServiceCpp.DecodeRegion(path, rect)에 넘기면 그 부분만 잘라 확대 디코드한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  개념 2: OCR(광학 문자 인식)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;바코드 인쇄가 흐려 디코드가 안 돼도, &lt;b&gt;사람이 읽는 글자&lt;/b&gt;(예: (01) ..., (21) ...)는 또렷한 경우가 많다. 그 글자를 &lt;b&gt;Tesseract&lt;/b&gt; 엔진으로 읽어 GTIN&amp;middot;유통기한&amp;middot;로트&amp;middot;일련번호를 뽑는다. 정확도를 위해 영역만 잘라 &lt;b&gt;확대&amp;middot;이진화&lt;/b&gt;한 뒤 인식한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Tesseract는 언어별 학습데이터 파일이 필요하다: &lt;b&gt;tessdata/eng.traineddata&lt;/b&gt;.&lt;/li&gt;
&lt;li&gt;OCR은 사진 품질에 민감해 1~2글자 오인식이 날 수 있다 &amp;rarr; &lt;b&gt;보조/교차검증&lt;/b&gt; 용도, 결과는 사람이 확인.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  코드 (11-1) 패키지&amp;middot;데이터&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;.csproj에 Tesseract 추가 + tessdata 복사:&lt;/p&gt;
&lt;pre class=&quot;armasm&quot;&gt;&lt;code&gt;&amp;lt;ItemGroup&amp;gt;
  &amp;lt;PackageReference Include=&quot;Tesseract&quot; Version=&quot;5.2.0&quot; /&amp;gt;
&amp;lt;/ItemGroup&amp;gt;
&amp;lt;ItemGroup&amp;gt;
  &amp;lt;None Include=&quot;tessdata\**\*&quot; CopyToOutputDirectory=&quot;PreserveNewest&quot; /&amp;gt;
&amp;lt;/ItemGroup&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로젝트에 tessdata 폴더를 만들고 &lt;b&gt;eng.traineddata&lt;/b&gt; 를 넣는다. (구글 &quot;tessdata_fast eng.traineddata&quot; 검색 &amp;rarr; tessdata_fast 저장소의 eng.traineddata 다운로드. 약 4MB.)&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  코드 (11-2) OcrService.cs&lt;/h3&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;using System;
using System.IO;
using System.Text.RegularExpressions;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
using Tesseract;
using DrawRect = System.Drawing.Rectangle;
using SsImage = SixLabors.ImageSharp.Image;

namespace PharmaReturn;

public sealed record OcrFields(string? Sn, string? Gtin, string? Lot, string? Exp, string RawText);

/// &amp;lt;summary&amp;gt;
/// 사람이 읽는 문자를 Tesseract로 읽는다. 두 인쇄 형식 모두 인식.
///  - 괄호형: (01) 08806443096813  (17) 280315  (10) 6248607  (21) 6P0155272
///  - 라벨형: GTIN ...  EXP ...  LOT ...  SN ...
/// 필요: 실행 폴더의 tessdata/eng.traineddata
/// &amp;lt;/summary&amp;gt;
public static class OcrService
{
    private static readonly string TessDataDir = Path.Combine(AppContext.BaseDirectory, &quot;tessdata&quot;);

    private static readonly Regex PGtin = new(@&quot;\(01\)\s*([0-9]{12,14})&quot;);
    private static readonly Regex PExp  = new(@&quot;\(17\)\s*([0-9]{6})&quot;);
    private static readonly Regex PLot  = new(@&quot;\(10\)\s*([0-9A-Za-z]{2,})&quot;);
    private static readonly Regex PSn   = new(@&quot;\(21\)\s*([0-9A-Za-z]{4,})&quot;);
    private static readonly Regex LGtin = new(@&quot;GTIN[\s:]+([A-Z0-9]+)&quot;, RegexOptions.IgnoreCase);
    private static readonly Regex LExp  = new(@&quot;EXP[\s:]+([A-Z0-9 ./-]+)&quot;, RegexOptions.IgnoreCase);
    private static readonly Regex LLot  = new(@&quot;LOT[\s:]+([A-Z0-9]+)&quot;, RegexOptions.IgnoreCase);
    private static readonly Regex LSn   = new(@&quot;SN[\s:]+([A-Z0-9]+)&quot;, RegexOptions.IgnoreCase);

    public static OcrFields ReadFields(string imagePath, DrawRect region = default)
    {
        string text = RunOcr(imagePath, region);
        string? gtin = First(PGtin, text) ?? First(LGtin, text);
        string? lot  = First(PLot, text)  ?? First(LLot, text);
        string? sn   = First(PSn, text)   ?? First(LSn, text);
        string? exp  = FormatExp(First(PExp, text)) ?? First(LExp, text)?.Trim();
        return new OcrFields(sn, gtin, lot, exp, text);
    }

    private static string? First(Regex r, string text)
    { var m = r.Match(text); return m.Success ? m.Groups[1].Value.Trim() : null; }

    private static string? FormatExp(string? yymmdd)
    { var d = Gs1Fields.ParseGs1Date(yymmdd); return d?.ToString(&quot;yyyy-MM-dd&quot;); }

    private static string RunOcr(string imagePath, DrawRect region)
    {
        string tmp = Path.Combine(Path.GetTempPath(), $&quot;ocr_{Guid.NewGuid():N}.png&quot;);
        try
        {
            using (var image = SsImage.Load&amp;lt;Rgb24&amp;gt;(imagePath))
            {
                if (!region.IsEmpty)
                {
                    var r = DrawRect.Intersect(region, new DrawRect(0, 0, image.Width, image.Height));
                    if (r.Width &amp;gt; 1 &amp;amp;&amp;amp; r.Height &amp;gt; 1)
                        image.Mutate(x =&amp;gt; x.Crop(new Rectangle(r.X, r.Y, r.Width, r.Height)));
                }
                int maxSide = Math.Max(image.Width, image.Height);
                int up = Math.Clamp(1200 / Math.Max(1, Math.Min(image.Width, image.Height)), 1, 3);
                if (maxSide * up &amp;gt; 3200) up = Math.Max(1, 3200 / Math.Max(1, maxSide));
                image.Mutate(x =&amp;gt; x.Resize(image.Width * up, image.Height * up).Grayscale().AdaptiveThreshold());
                image.SaveAsPng(tmp);
            }
            using var engine = new TesseractEngine(TessDataDir, &quot;eng&quot;, EngineMode.Default);
            engine.SetVariable(&quot;tessedit_char_whitelist&quot;, &quot;ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789()[] :./-&quot;);
            using var pix = Pix.LoadFromFile(tmp);
            using var page = engine.Process(pix, PageSegMode.SparseText);
            return page.GetText() ?? &quot;&quot;;
        }
        finally { try { if (File.Exists(tmp)) File.Delete(tmp); } catch { } }
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;  핵심:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;정규식 두 벌(P*=괄호형, L*=영문 라벨형)로 어느 인쇄 형식이든 GTIN/유통기한/로트/일련번호를 뽑는다.&lt;/li&gt;
&lt;li&gt;RunOcr: 영역만 잘라 &amp;rarr; 확대 &amp;rarr; 흑백 &amp;rarr; &lt;b&gt;적응형 이진화&lt;/b&gt;(조명 편차 보정) &amp;rarr; 임시 PNG &amp;rarr; Tesseract Process.&lt;/li&gt;
&lt;li&gt;tessedit_char_whitelist: 인식 후보 글자를 제한해 오인식을 줄인다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  코드 (11-3) MainForm에 [영역 판독]&amp;middot;[가독문자 OCR] 버튼&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;(a) 버튼 필드 + navBar 추가 + 클릭 연결&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;haxe&quot;&gt;&lt;code&gt;private readonly Button _btnRegion = new() { Text = &quot;영역 판독&quot;, AutoSize = true, Margin = new Padding(4) };
private readonly Button _btnOcr    = new() { Text = &quot;가독문자 OCR&quot;, AutoSize = true, Margin = new Padding(4) };
// navBar.Controls.AddRange(..., _btnRegion, _btnOcr);
// _btnRegion.Click += OnRegionDecode;
// _btnOcr.Click += OnOcr;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;(b) 핸들러&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;cs&quot;&gt;&lt;code&gt;private void OnRegionDecode(object? sender, EventArgs e)
{
    if (_current &amp;lt; 0) return;
    var file = _files[_current];
    var sel = _canvas.GetSelectionImageRect();
    if (sel.IsEmpty) { MessageBox.Show(this, &quot;이미지에서 영역을 드래그한 뒤 [영역 판독].&quot;); return; }

    var found = BarcodeServiceCpp.DecodeRegion(file.Path, sel);
    var repo = DeliveryRepository.LoadCsv(_csvPath);
    int added = 0;
    foreach (var c in found)
    {
        if (file.Codes.Any(x =&amp;gt; x.Text == c.Text)) continue;   // 중복 제외
        file.Codes.Add(c);
        AddDecodedRow(Path.GetFileName(file.Path), c, repo);
        added++;
    }
    _canvas.SetCodes(file.Codes);
    _lblStatus.Text = added &amp;gt; 0 ? $&quot;영역 판독: {added}개 추가&quot; : &quot;선택 영역에서 코드를 못 찾음&quot;;
}

private void OnOcr(object? sender, EventArgs e)
{
    if (_current &amp;lt; 0) return;
    var file = _files[_current];
    var sel = _canvas.GetSelectionImageRect();   // 비어 있으면 전체

    OcrFields ocr;
    try { ocr = OcrService.ReadFields(file.Path, sel); }
    catch (Exception ex)
    { MessageBox.Show(this, $&quot;OCR 실패: {ex.Message}\n(tessdata/eng.traineddata 확인)&quot;); return; }

    var add = MessageBox.Show(this,
        $&quot;OCR 결과\n GTIN: {ocr.Gtin}\n LOT: {ocr.Lot}\n EXP: {ocr.Exp}\n SN: {ocr.Sn}\n\n목록에 추가할까요?&quot;,
        &quot;가독문자 OCR&quot;, MessageBoxButtons.YesNo);
    if (add == DialogResult.Yes &amp;amp;&amp;amp; !string.IsNullOrEmpty(ocr.Gtin))
    {
        DateOnly? exp = DateOnly.TryParse(ocr.Exp, out var d) ? d : null;
        var repo = DeliveryRepository.LoadCsv(_csvPath);
        int prefill = repo.FindByGtinLot(ocr.Gtin!, string.IsNullOrEmpty(ocr.Lot) ? null : ocr.Lot).Sum(m =&amp;gt; m.DeliveredQty);
        AddRow(Path.GetFileName(file.Path), ocr.Gtin ?? &quot;&quot;, ocr.Lot ?? &quot;&quot;,
            exp?.ToString(&quot;yyyy-MM-dd&quot;) ?? &quot;&quot;, ocr.Sn ?? &quot;&quot;, &quot;만기&quot;,
            prefill &amp;gt; 0 ? prefill.ToString() : &quot;&quot;, &quot;&quot;, &quot;&quot;, &quot;OCR 보완 &amp;mdash; 확인 필요&quot;);
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(여기서 쓰는 AddDecodedRow, AddRow는 Lesson 12 전체 코드에 정의돼 있다.)&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;✅ 직접 해보기&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;작은 코드 위를 드래그 &amp;rarr; [영역 판독] &amp;rarr; 새 박스/행이 생기면 성공.&lt;/li&gt;
&lt;li&gt;바코드가 흐린 박스의 &lt;b&gt;글자 영역&lt;/b&gt;을 드래그 &amp;rarr; [가독문자 OCR] &amp;rarr; GTIN/LOT/EXP가 떠서 &quot;예&quot;로 목록에 추가되면 성공.&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OCR 실패 메시지가 뜨면 tessdata/eng.traineddata가 실행 폴더(bin...\tessdata)에 복사됐는지 확인.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Lesson 12 &amp;mdash; 완성형 MainForm + 보상 계산 + 배포&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  목표&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금까지의 조각을 합친 &lt;b&gt;완성형 MainForm.cs&lt;/b&gt; 로 마무리하고, 남에게 줄 수 있는 &lt;b&gt;설치/실행 파일&lt;/b&gt;로 배포한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  코드: 완성형 MainForm.cs (전체)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래로 통째로 교체하면 된다. (Lesson 8~11에서 배운 것이 모두 들어 있다)&lt;/p&gt;
&lt;pre class=&quot;cs&quot;&gt;&lt;code&gt;using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Windows.Forms;

namespace PharmaReturn;

public sealed class MainForm : Form
{
    private sealed class LoadedFile
    {
        public required string Path { get; init; }
        public List&amp;lt;DecodedCode&amp;gt; Codes { get; init; } = new();
        public bool Failed { get; set; }
    }

    private readonly List&amp;lt;LoadedFile&amp;gt; _files = new();
    private int _current = -1;

    private readonly Button _btnLoad = new() { Text = &quot;파일 불러오기 (여러 개 선택 가능)&quot;, AutoSize = true, Margin = new Padding(4) };
    private readonly Button _btnCalc = new() { Text = &quot;보상 계산&quot;, AutoSize = true, Margin = new Padding(4) };
    private readonly Label _lblStatus = new() { AutoSize = true, Margin = new Padding(12, 10, 4, 4), Text = &quot;이미지를 불러오세요.&quot; };

    private readonly ImageCanvas _canvas = new() { Dock = DockStyle.Fill };
    private readonly Button _btnPrev = new() { Text = &quot;◀ 이전&quot;, AutoSize = true, Margin = new Padding(4) };
    private readonly Button _btnNext = new() { Text = &quot;다음 ▶&quot;, AutoSize = true, Margin = new Padding(4) };
    private readonly Button _btnRegion = new() { Text = &quot;영역 판독&quot;, AutoSize = true, Margin = new Padding(4) };
    private readonly Button _btnOcr = new() { Text = &quot;가독문자 OCR&quot;, AutoSize = true, Margin = new Padding(4) };
    private readonly Button _btnZoomIn = new() { Text = &quot;＋&quot;, AutoSize = true, Margin = new Padding(4), Width = 36 };
    private readonly Button _btnZoomOut = new() { Text = &quot;－&quot;, AutoSize = true, Margin = new Padding(4), Width = 36 };
    private readonly Button _btnZoomFit = new() { Text = &quot;맞춤&quot;, AutoSize = true, Margin = new Padding(4) };
    private readonly Label _lblCounter = new() { AutoSize = true, Margin = new Padding(12, 10, 8, 4), Text = &quot;0 / 0&quot; };
    private readonly Label _lblHint = new() { AutoSize = true, Margin = new Padding(12, 10, 4, 4), ForeColor = SystemColors.GrayText, Text = &quot;휠=확대/축소, Space+드래그=이동, 드래그=영역 선택 후 [영역 판독]/[OCR]&quot; };

    private readonly DataGridView _dgv = new()
    {
        Dock = DockStyle.Fill, AllowUserToAddRows = false,
        AutoGenerateColumns = false, SelectionMode = DataGridViewSelectionMode.FullRowSelect,
        RowHeadersVisible = false,
    };
    private readonly Label _lblTotal = new() { AutoSize = true, Text = &quot;총 보상 금액: 0 원&quot; };

    private readonly string _csvPath = Path.Combine(AppContext.BaseDirectory, &quot;data&quot;, &quot;deliveries.csv&quot;);

    public MainForm()
    {
        Text = &quot;약국 반품 보상 &amp;mdash; 다중 바코드 판독&quot;;
        Width = 1180; Height = 700; StartPosition = FormStartPosition.CenterScreen;
        _lblTotal.Font = new Font(_lblTotal.Font, FontStyle.Bold);

        BuildGrid();

        var top = new FlowLayoutPanel { Dock = DockStyle.Top, Height = 48, Padding = new Padding(8, 6, 8, 6) };
        top.Controls.AddRange(new Control[] { _btnLoad, _btnCalc, _lblStatus });

        var navBar = new FlowLayoutPanel { Dock = DockStyle.Bottom, Height = 40, Padding = new Padding(6, 4, 6, 4) };
        navBar.Controls.AddRange(new Control[] { _btnPrev, _lblCounter, _btnNext, _btnZoomOut, _btnZoomIn, _btnZoomFit, _btnRegion, _btnOcr, _lblHint });
        var left = new Panel { Dock = DockStyle.Fill };
        left.Controls.Add(_canvas);
        left.Controls.Add(navBar);

        var split = new SplitContainer { Dock = DockStyle.Fill, SplitterDistance = 640 };
        split.Panel1.Controls.Add(left);
        split.Panel2.Controls.Add(_dgv);

        var bottom = new Panel { Dock = DockStyle.Bottom, Height = 40, Padding = new Padding(12, 8, 8, 8) };
        _lblTotal.Dock = DockStyle.Left;
        bottom.Controls.Add(_lblTotal);

        Controls.Add(split);
        Controls.Add(top);
        Controls.Add(bottom);

        _btnLoad.Click += OnLoad;
        _btnCalc.Click += OnCalc;
        _btnPrev.Click += (_, _) =&amp;gt; Move(-1);
        _btnNext.Click += (_, _) =&amp;gt; Move(+1);
        _btnRegion.Click += OnRegionDecode;
        _btnOcr.Click += OnOcr;
        _btnZoomIn.Click += (_, _) =&amp;gt; _canvas.ZoomBy(1.25f);
        _btnZoomOut.Click += (_, _) =&amp;gt; _canvas.ZoomBy(0.8f);
        _btnZoomFit.Click += (_, _) =&amp;gt; _canvas.ResetView();
        _dgv.DataError += (_, e) =&amp;gt; e.ThrowException = false;
    }

    private void BuildGrid()
    {
        void Col(string name, string header, int w, bool ro = true)
            =&amp;gt; _dgv.Columns.Add(new DataGridViewTextBoxColumn { Name = name, HeaderText = header, Width = w, ReadOnly = ro });

        Col(&quot;file&quot;, &quot;파일&quot;, 110); Col(&quot;gtin&quot;, &quot;GTIN&quot;, 130); Col(&quot;lot&quot;, &quot;로트&quot;, 80);
        Col(&quot;expiry&quot;, &quot;유통기한&quot;, 90); Col(&quot;serial&quot;, &quot;일련번호&quot;, 70);
        var reason = new DataGridViewComboBoxColumn { Name = &quot;reason&quot;, HeaderText = &quot;사유&quot;, Width = 64 };
        reason.Items.AddRange(&quot;만기&quot;, &quot;손상&quot;, &quot;기타&quot;);
        _dgv.Columns.Add(reason);
        Col(&quot;reqty&quot;, &quot;요청수량&quot;, 64, ro: false);
        Col(&quot;approved&quot;, &quot;승인&quot;, 52); Col(&quot;credit&quot;, &quot;보상금액&quot;, 90); Col(&quot;status&quot;, &quot;상태&quot;, 220);
    }

    private void OnLoad(object? sender, EventArgs e)
    {
        using var ofd = new OpenFileDialog
        {
            Multiselect = true, Title = &quot;바코드 이미지 선택 (여러 개 가능)&quot;,
            Filter = &quot;이미지 파일 (*.png;*.jpg;*.jpeg;*.bmp)|*.png;*.jpg;*.jpeg;*.bmp|모든 파일 (*.*)|*.*&quot;,
        };
        if (ofd.ShowDialog(this) != DialogResult.OK) return;

        var repo = SafeLoadRepo();
        _files.Clear(); _dgv.Rows.Clear();

        foreach (var path in ofd.FileNames)
        {
            var file = new LoadedFile { Path = path };
            try { file.Codes.AddRange(BarcodeServiceCpp.DecodeDetailed(path)); }
            catch (Exception ex)
            {
                file.Failed = true;
                AddRow(Path.GetFileName(path), &quot;&quot;, &quot;&quot;, &quot;&quot;, &quot;&quot;, &quot;만기&quot;, &quot;&quot;, &quot;&quot;, &quot;&quot;, $&quot;오류: {ex.Message}&quot;);
                _files.Add(file); continue;
            }
            if (file.Codes.Count == 0)
            {
                file.Failed = true;
                AddRow(Path.GetFileName(path), &quot;&quot;, &quot;&quot;, &quot;&quot;, &quot;&quot;, &quot;만기&quot;, &quot;&quot;, &quot;&quot;, &quot;&quot;, &quot;디코드 실패 &amp;mdash; 영역 판독 시도 가능&quot;);
            }
            else foreach (var c in file.Codes) AddDecodedRow(Path.GetFileName(path), c, repo);
            _files.Add(file);
        }

        _current = _files.Count &amp;gt; 0 ? 0 : -1;
        ShowCurrent();
        int codes = _files.Sum(f =&amp;gt; f.Codes.Count);
        _lblStatus.Text = $&quot;파일 {_files.Count}개에서 코드 {codes}개 인식. 사유&amp;middot;요청수량 확인 후 [보상 계산].&quot;;
        _lblTotal.Text = &quot;총 보상 금액: 0 원&quot;;
    }

    private void Move(int delta)
    {
        if (_files.Count == 0) return;
        _current = Math.Clamp(_current + delta, 0, _files.Count - 1);
        ShowCurrent();
    }

    private void ShowCurrent()
    {
        if (_current &amp;lt; 0 || _current &amp;gt;= _files.Count)
        { _canvas.SetContent(null, new List&amp;lt;DecodedCode&amp;gt;()); _lblCounter.Text = &quot;0 / 0&quot;; return; }

        var file = _files[_current];
        Image? img = null;
        try { img = LoadImageUnlocked(file.Path); } catch { }
        _canvas.SetContent(img, file.Codes);
        _lblCounter.Text = $&quot;{_current + 1} / {_files.Count}  &amp;middot;  {Path.GetFileName(file.Path)}&quot;
                           + (file.Failed &amp;amp;&amp;amp; file.Codes.Count == 0 ? &quot;  (판독 실패)&quot; : &quot;&quot;);
    }

    private void OnRegionDecode(object? sender, EventArgs e)
    {
        if (_current &amp;lt; 0 || _current &amp;gt;= _files.Count) return;
        var file = _files[_current];
        var sel = _canvas.GetSelectionImageRect();
        if (sel.IsEmpty)
        { MessageBox.Show(this, &quot;이미지 위에서 마우스로 영역을 드래그해 선택한 뒤 [영역 판독]을 누르세요.&quot;, &quot;안내&quot;); return; }

        List&amp;lt;DecodedCode&amp;gt; found;
        try { found = BarcodeServiceCpp.DecodeRegion(file.Path, sel); }
        catch (Exception ex) { MessageBox.Show(this, $&quot;영역 판독 오류:\n{ex.Message}&quot;, &quot;오류&quot;); return; }

        var repo = SafeLoadRepo();
        int added = 0;
        foreach (var c in found)
        {
            if (file.Codes.Any(x =&amp;gt; x.Text == c.Text)) continue;
            file.Codes.Add(c); AddDecodedRow(Path.GetFileName(file.Path), c, repo); added++;
        }
        if (added &amp;gt; 0) file.Failed = false;
        _canvas.SetCodes(file.Codes); ShowCurrent();
        _lblStatus.Text = added &amp;gt; 0 ? $&quot;영역 판독: 새 코드 {added}개 추가됨.&quot; : &quot;선택 영역에서 코드를 찾지 못했습니다.&quot;;
    }

    private void OnOcr(object? sender, EventArgs e)
    {
        if (_current &amp;lt; 0 || _current &amp;gt;= _files.Count) return;
        var file = _files[_current];
        var sel = _canvas.GetSelectionImageRect();
        if (sel.IsEmpty &amp;amp;&amp;amp;
            MessageBox.Show(this, &quot;영역을 선택하지 않았습니다. 이미지 전체를 OCR할까요?\n(라벨 텍스트 영역만 드래그하면 정확도가 훨씬 높습니다.)&quot;,
                &quot;가독문자 OCR&quot;, MessageBoxButtons.OKCancel, MessageBoxIcon.Question) != DialogResult.OK)
            return;

        OcrFields ocr;
        try { ocr = OcrService.ReadFields(file.Path, sel); }
        catch (Exception ex)
        {
            MessageBox.Show(this, $&quot;OCR 실행 실패:\n{ex.Message}\n\ntessdata/eng.traineddata 파일이 실행 폴더에 있는지 확인하세요.&quot;, &quot;오류&quot;);
            return;
        }

        string cross = &quot;(이 파일에 판독된 바코드 없음)&quot;;
        if (file.Codes.Count &amp;gt; 0)
        {
            var g = Gs1Parser.Parse(file.Codes[0].Text);
            cross = $&quot;바코드: GTIN={g.Gtin} LOT={g.Lot} EXP={g.Expiry:yyyy-MM-dd}\n&quot;
                  + $&quot;교차검증: GTIN {(Same(ocr.Gtin, g.Gtin) ? &quot;일치&quot; : &quot;불일치&quot;)}, LOT {(Same(ocr.Lot, g.Lot) ? &quot;일치&quot; : &quot;불일치&quot;)}&quot;;
        }

        var add = MessageBox.Show(this,
            $&quot;OCR 결과\n  SN   : {ocr.Sn}\n  GTIN : {ocr.Gtin}\n  LOT  : {ocr.Lot}\n  EXP  : {ocr.Exp}\n\n{cross}\n\n이 내용을 반품 목록에 추가할까요?&quot;,
            &quot;가독문자 OCR&quot;, MessageBoxButtons.YesNo, MessageBoxIcon.Information);

        if (add == DialogResult.Yes &amp;amp;&amp;amp; !string.IsNullOrEmpty(ocr.Gtin))
        {
            DateOnly? exp = DateOnly.TryParse(ocr.Exp, out var d) ? d : null;
            AddManualRow(Path.GetFileName(file.Path), ocr.Gtin, ocr.Lot, exp, ocr.Sn, &quot;OCR 보완 &amp;mdash; 값 확인 필요&quot;);
            _lblStatus.Text = &quot;OCR 보완 행을 추가했습니다. GTIN&amp;middot;로트&amp;middot;수량을 확인 후 [보상 계산].&quot;;
        }
    }

    private void OnCalc(object? sender, EventArgs e)
    {
        var repo = SafeLoadRepo();
        if (repo is null) return;
        var svc = new CompensationService(repo); // 운영일(DateTime.Today)
        decimal total = 0;

        foreach (DataGridViewRow row in _dgv.Rows)
        {
            string gtin = Cell(row, &quot;gtin&quot;);
            if (string.IsNullOrEmpty(gtin)) continue;
            string lot = Cell(row, &quot;lot&quot;);
            DateOnly? expiry = DateOnly.TryParse(Cell(row, &quot;expiry&quot;), out var d) ? d : null;
            ReturnReason reason = Cell(row, &quot;reason&quot;) switch { &quot;손상&quot; =&amp;gt; ReturnReason.Damage, &quot;기타&quot; =&amp;gt; ReturnReason.Other, _ =&amp;gt; ReturnReason.Expiry };
            int qty = int.TryParse(Cell(row, &quot;reqty&quot;), out var q) ? q : 0;

            var r = svc.Evaluate(new ReturnRequest(gtin, string.IsNullOrEmpty(lot) ? null : lot, expiry, qty, reason));
            total += r.CreditAmount;
            SetResult(row, r.ApprovedQty.ToString(), r.CreditAmount.ToString(&quot;N0&quot;), $&quot;[{r.Status}] {r.Message}&quot;);
        }
        _lblTotal.Text = $&quot;총 보상 금액: {total:N0} 원&quot;;
    }

    // ── 보조 ───────────────────────────────────────────────
    private void AddDecodedRow(string fileName, DecodedCode c, DeliveryRepository? repo)
    {
        var f = Gs1Parser.Parse(c.Text);
        int prefill = PrefillQty(repo, f);
        AddRow(fileName, f.Gtin ?? &quot;&quot;, f.Lot ?? &quot;&quot;, f.Expiry?.ToString(&quot;yyyy-MM-dd&quot;) ?? &quot;&quot;, f.Serial ?? &quot;&quot;,
            &quot;만기&quot;, prefill &amp;gt; 0 ? prefill.ToString() : &quot;&quot;, &quot;&quot;, &quot;&quot;, &quot;불러옴&quot;);
    }

    private void AddManualRow(string fileName, string? gtin, string? lot, DateOnly? exp, string? serial, string status)
    {
        var repo = SafeLoadRepo();
        int prefill = (repo is not null &amp;amp;&amp;amp; !string.IsNullOrEmpty(gtin))
            ? repo.FindByGtinLot(gtin!, string.IsNullOrEmpty(lot) ? null : lot).Sum(m =&amp;gt; m.DeliveredQty) : 0;
        AddRow(fileName, gtin ?? &quot;&quot;, lot ?? &quot;&quot;, exp?.ToString(&quot;yyyy-MM-dd&quot;) ?? &quot;&quot;, serial ?? &quot;&quot;,
            &quot;만기&quot;, prefill &amp;gt; 0 ? prefill.ToString() : &quot;&quot;, &quot;&quot;, &quot;&quot;, status);
    }

    private static int PrefillQty(DeliveryRepository? repo, Gs1Fields f)
    {
        if (repo is null || f.Gtin is null) return 0;
        var matches = repo.FindByGtinLot(f.Gtin, f.Lot).ToList();
        return matches.Count == 0 ? 0 : matches.Sum(m =&amp;gt; m.DeliveredQty);
    }

    private static bool Same(string? a, string? b)
        =&amp;gt; !string.IsNullOrEmpty(a) &amp;amp;&amp;amp; !string.IsNullOrEmpty(b)
           &amp;amp;&amp;amp; string.Equals(a.Replace(&quot; &quot;, &quot;&quot;), b.Replace(&quot; &quot;, &quot;&quot;), StringComparison.OrdinalIgnoreCase);

    private DeliveryRepository? SafeLoadRepo()
    {
        try { return DeliveryRepository.LoadCsv(_csvPath); }
        catch (Exception ex)
        { MessageBox.Show(this, $&quot;납품내역 로드 실패:\n{_csvPath}\n\n{ex.Message}&quot;, &quot;오류&quot;); return null; }
    }

    private static Image LoadImageUnlocked(string path)
    {
        using var ms = new MemoryStream(File.ReadAllBytes(path));
        using var tmp = Image.FromStream(ms);
        return new Bitmap(tmp);
    }

    private void AddRow(params string[] values) =&amp;gt; _dgv.Rows.Add(values);
    private static string Cell(DataGridViewRow row, string col) =&amp;gt; row.Cells[col].Value?.ToString() ?? &quot;&quot;;
    private static void SetResult(DataGridViewRow row, string approved, string credit, string status)
    {
        row.Cells[&quot;approved&quot;].Value = approved;
        row.Cells[&quot;credit&quot;].Value = credit;
        row.Cells[&quot;status&quot;].Value = status;
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;  보상 계산(OnCalc) 한 번 더:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;그리드의 각 행에서 GTIN/로트/유통기한/사유/요청수량을 읽어 ReturnRequest를 만들고 Evaluate(1편). 승인&amp;middot;보상&amp;middot;상태를 그 행에 다시 적고 총액을 누적한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;매번 SafeLoadRepo()로 납품내역을 새로 읽어&lt;/b&gt; 계산하므로(기반품 누적이 초기화됨) 여러 번 눌러도 결과가 누적&amp;middot;왜곡되지 않는다(멱등).&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  배포(다른 PC에서 실행하게 만들기)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발 PC에선 F5면 되지만, 남에게 줄 땐 &quot;실행 파일 묶음&quot;을 만든다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;방법 A &amp;mdash; 자체 포함 게시(권장, .NET 설치 불필요):&lt;/b&gt; 명령줄(프로젝트 폴더)에서&lt;/p&gt;
&lt;pre class=&quot;llvm&quot;&gt;&lt;code&gt;dotnet publish -c Release -r win-x64 --self-contained true -p:PublishSingleFile=true
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;결과: bin\Release\net8.0-windows\win-x64\publish\ 에 PharmaReturn.exe(+ 네이티브 dll, data, tessdata).&lt;/li&gt;
&lt;li&gt;받는 사람은 .NET 설치 없이 .exe 실행. &lt;b&gt;단, data\deliveries.csv와 tessdata\eng.traineddata가 exe 옆에 함께 있어야&lt;/b&gt; 한다(없으면 CSV/OCR 동작 실패).&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;방법 B &amp;mdash; 프레임워크 종속(가벼움):&lt;/b&gt; 받는 PC에 .NET 8 데스크톱 런타임이 있을 때&lt;/p&gt;
&lt;pre class=&quot;ebnf&quot;&gt;&lt;code&gt;dotnet publish -c Release
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;  ZXingCpp&amp;middot;Tesseract의 &lt;b&gt;네이티브 dll은 64비트&lt;/b&gt;라, 게시도 win-x64로. (그래서 csproj에 x64를 고정했다.)   첫 실행 시 SmartScreen 경고가 뜰 수 있다(서명 안 된 exe). 사내 배포면 코드 서명 인증서로 서명하면 깔끔하다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;✅ 최종 점검 체크리스트&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;[ ] 사진 여러 장 불러와 자동 판독 &amp;rarr; 표에 채워진다&lt;/li&gt;
&lt;li&gt;[ ] 미리보기에 파란 박스 + 번호&amp;middot;문자 라벨이 코드에 맞게 보인다&lt;/li&gt;
&lt;li&gt;[ ] 휠/버튼 확대&amp;middot;축소, Space+드래그 이동&lt;/li&gt;
&lt;li&gt;[ ] 작은 코드는 드래그 &amp;rarr; [영역 판독]으로 회수&lt;/li&gt;
&lt;li&gt;[ ] 흐린 코드는 글자 영역 드래그 &amp;rarr; [가독문자 OCR] &amp;rarr; 목록 보완&lt;/li&gt;
&lt;li&gt;[ ] [보상 계산] &amp;rarr; 승인/부분/거부 + 보상금액 + 총액&lt;/li&gt;
&lt;li&gt;[ ] dotnet publish로 만든 exe가 다른 폴더(또는 PC)에서 data&amp;middot;tessdata와 함께 실행된다&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;강의 전체 마무리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;세 편으로 만든 것:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;1편(두뇌)&lt;/b&gt;: 모델 &amp;middot; GS1 파서 &amp;middot; 납품 저장소 &amp;middot; 보상 계산 (콘솔, 무의존)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;2편(눈)&lt;/b&gt;: ZXingCpp + ImageSharp로 디코드 &amp;middot; 위치 &amp;middot; 다중 &amp;middot; 타일 &amp;middot; 영역&lt;/li&gt;
&lt;li&gt;&lt;b&gt;3편(얼굴)&lt;/b&gt;: WinForms &amp;mdash; 불러오기 &amp;middot; 미리보기 &amp;middot; 줌/이동 &amp;middot; 박스 오버레이 &amp;middot; 영역 판독 &amp;middot; OCR 보완 &amp;middot; 보상 &amp;middot; 배포&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;핵심 설계 교훈:&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;로직과 UI를 분리&lt;/b&gt;하면, 두뇌를 콘솔로 먼저 검증하고 UI를 자유롭게 얹을 수 있다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;좌표 변환&lt;/b&gt;(원본 &amp;harr; 화면, 타일 &amp;harr; 원본)을 한 곳에서 일관되게 다루면 줌&amp;middot;박스&amp;middot;영역선택이 모두 들어맞는다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;현실의 한계&lt;/b&gt;(흐린 인쇄)는 코드가 아니라 운영(촬영 개선&amp;middot;OCR 보완&amp;middot;재라벨)으로 보완한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추가 사항&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- DB 연동은&amp;nbsp; 개인&amp;nbsp; 취향에&amp;nbsp; 맞게&amp;nbsp; 교체가&amp;nbsp; 필요&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 결과&amp;nbsp; 저장&amp;nbsp; 기록 이력이 없어&amp;nbsp; 추가개발&amp;nbsp; 필요&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 무료 SDK 인경우 곡선&amp;nbsp; 바코드 보정능력이 떨어짐 (&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;상용&amp;nbsp; SDK 연동필요)&lt;/span&gt;&lt;/p&gt;</description>
      <category>개발(IT)/C#(VisualStudio)</category>
      <category>DataMatrix GS1 스캔</category>
      <category>DataMatrix 다중판독</category>
      <category>GS1 Parser</category>
      <category>GS1 파서</category>
      <category>OCR 판독</category>
      <category>vs2022 c#</category>
      <category>소니스토리</category>
      <author>isony</author>
      <guid isPermaLink="true">https://isony.tistory.com/348</guid>
      <comments>https://isony.tistory.com/entry/%EC%9D%98%EC%95%BD%ED%92%88-%EB%B0%98%ED%92%88-%EB%B3%B4%EC%83%81-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%A8-%EB%A7%8C%EB%93%A4%EA%B8%B0-%E2%80%94-%EB%8B%A8%EA%B3%84%EB%B3%84-%EA%B0%95%EC%9D%98-3%ED%8E%B8-%C2%B7-%EC%99%84%EC%84%B1#entry348comment</comments>
      <pubDate>Wed, 8 Jul 2026 06:33:03 +0900</pubDate>
    </item>
    <item>
      <title>의약품 반품 보상 프로그램 만들기 &amp;mdash; 단계별 강의 (2편)</title>
      <link>https://isony.tistory.com/entry/%EC%9D%98%EC%95%BD%ED%92%88-%EB%B0%98%ED%92%88-%EB%B3%B4%EC%83%81-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%A8-%EB%A7%8C%EB%93%A4%EA%B8%B0-%E2%80%94-%EB%8B%A8%EA%B3%84%EB%B3%84-%EA%B0%95%EC%9D%98-2%ED%8E%B8</link>
      <description>&lt;h1&gt;의약품 반품 보상 프로그램 만들기 &amp;mdash; 단계별 강의 (2편)&lt;/h1&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1편에서 만든 &quot;두뇌&quot;(파서&amp;middot;대조&amp;middot;보상)는 &lt;b&gt;바코드 문자열&lt;/b&gt;을 입력으로 받았다. 그런데 그 문자열은 어디서 오나? &lt;b&gt;이미지(사진) 속 GS1 DataMatrix를 디코드&lt;/b&gt;해서 얻는다. 2편은 바로 그 부분이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2편을 끝내면: 이미지 파일을 넣으면 &amp;rarr; 그 안의 DataMatrix를 (여러 개라도) 읽어 &lt;b&gt;문자열 + 위치 좌표&lt;/b&gt;로 돌려주고, &lt;b&gt;큰 사진 속 작은 코드&lt;/b&gt;나 &lt;b&gt;사용자가 고른 영역&lt;/b&gt;도 처리하는 클래스를 갖게 된다. 여전히 콘솔에서 테스트한다. (화면 UI는 3편)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 편은 요청하신 대로 &lt;b&gt;설명을 더 자세히&lt;/b&gt; 넣었다. 개념이 처음이면  과   박스를 천천히 읽자.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;들어가기 전에 &amp;mdash; 큰 그림&lt;/h2&gt;
&lt;pre class=&quot;isbl&quot;&gt;&lt;code&gt; [사진/이미지 파일]
        │  (2편에서 만드는 부분)
        ▼
 ┌─────────────────────────┐
 │  BarcodeServiceCpp       │   &amp;larr; ZXingCpp(디코드) + ImageSharp(이미지 처리)
 │  &quot;이미지 &amp;rarr; 코드 문자열 + 위치&quot;  │
 └─────────────────────────┘
        │  &quot;(01)08806443096813(17)280315(10)6248607(21)...&quot;
        ▼
 ┌─────────────────────────┐
 │  Gs1Parser (1편)         │   &amp;larr; 문자열 &amp;rarr; GTIN/유통기한/로트
 └─────────────────────────┘
        ▼
 ┌─────────────────────────┐
 │ Repository + Compensation │  &amp;larr; 대조 + 보상 (1편)
 └─────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉 2편의 산출물 BarcodeServiceCpp는 1편의 Gs1Parser &lt;b&gt;앞에&lt;/b&gt; 붙는 &quot;눈&quot; 역할이다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Lesson 5 &amp;mdash; 바코드 디코딩 기초&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  목표&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;NuGet 패키지를 설치하고, 이미지 파일 하나에서 DataMatrix를 읽어 문자열로 출력한다. 테스트용 코드 이미지도 직접 만든다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  개념 1: NuGet 패키지란?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;NuGet&lt;/b&gt;은 .NET의 &quot;라이브러리 앱스토어&quot;다. 남이 만든 기능 묶음(패키지)을 프로젝트에 한 줄로 추가한다. 우리가 쓸 패키지:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;패키지 역할 비고&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;ZXingCpp&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;바코드 &lt;b&gt;디코드&lt;/b&gt;(zxing-cpp의 .NET 래퍼)&lt;/td&gt;
&lt;td&gt;네이티브 라이브러리 포함, 다중 판독이 기본&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;SixLabors.ImageSharp&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;이미지 &lt;b&gt;로드&amp;middot;자르기&amp;middot;확대&amp;middot;흑백&lt;/b&gt; 처리&lt;/td&gt;
&lt;td&gt;2.1.x = 무료(Apache-2.0)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;ZXing.Net&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;바코드 &lt;b&gt;생성&lt;/b&gt;(테스트 이미지 만들기용)&lt;/td&gt;
&lt;td&gt;디코드는 ZXingCpp가 더 강함&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;  &lt;b&gt;왜 디코드는 ZXingCpp, 생성은 ZXing.Net?&lt;/b&gt; 디코드(읽기)는 정확도가 생명이라 더 강한 zxing-cpp(C++ 엔진)를 쓴다. 생성(쓰기)은 테스트 이미지를 만드는 용도라 순수 .NET인 ZXing.Net이면 충분하다. 역할에 맞게 도구를 나눈 것이다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  개념 2: DataMatrix가 뭔가&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DataMatrix는 정사각형 안에 작은 흑백 점(모듈)으로 데이터를 담는 2D 바코드다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;왼쪽&amp;middot;아래 변의 &lt;b&gt;실선 L자&lt;/b&gt;(finder pattern)로 스캐너가 위치&amp;middot;방향을 찾는다.&lt;/li&gt;
&lt;li&gt;위&amp;middot;오른쪽 변의 &lt;b&gt;점선&lt;/b&gt;(timing pattern)으로 가로&amp;middot;세로 칸 수를 센다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;오류정정(Reed-Solomon)&lt;/b&gt; 덕분에 일부(최대 ~30%)가 손상돼도 복원된다. (단, 인쇄가 흐려 데이터 자체가 뭉개지면 한계가 있다 &amp;mdash; 7편쯤 실제로 겪는다.)&lt;/li&gt;
&lt;li&gt;의약품은 보통 &lt;b&gt;GS1 DataMatrix&lt;/b&gt;: 맨 앞에 FNC1 표시가 있고, GTIN&amp;middot;유통기한&amp;middot;로트&amp;middot;일련번호를 AI로 담는다(1편 파서가 처리하는 그것).&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;less&quot;&gt;&lt;code&gt;  DataMatrix 구조(개념도)
   ┌ ─ ─ ─ ─ ┐   &amp;larr; timing(점선): 칸 수
   █ ░ █ ░ █ ░     데이터(흑/백 모듈)
   █ █ ░ █ ░ █
   █ ░ ░ █ █ ░
   █ █ █ █ █ █   &amp;larr; finder(실선 L): 위치/방향
   └ 실 선 변 ┘
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  개념 3: 이미지를 디코더에 넘기는 흐름&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ZXingCpp는 이미지를 &lt;b&gt;ImageView&lt;/b&gt; 라는 형태로 받는다. 이건 &quot;픽셀 바이트 배열 + 가로&amp;middot;세로 크기 + 픽셀 형식(RGB 등)&quot;을 묶은 얇은 포장지다. 그래서 흐름은:&lt;/p&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;이미지 파일 ──(ImageSharp로 로드)──▶ Rgb24 이미지
            ──(픽셀을 byte[]로 복사)──▶ rgb 바이트 배열
            ──(ImageView로 포장)──▶ ZXingCpp에 전달 ──▶ 결과 목록
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;  &lt;b&gt;왜 RGB 바이트 배열이 필요한가?&lt;/b&gt; 디코더는 &quot;픽셀 색이 죽 늘어선 숫자 배열&quot;만 이해한다. JPG/PNG는 압축된 파일이라 그대로는 못 읽는다. 그래서 ImageSharp가 압축을 풀어 Rgb24(픽셀당 R,G,B 3바이트) 이미지로 만들고, 그 픽셀들을 byte[]로 복사해 넘긴다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  코드 (5-1) 패키지 설치 &amp;amp; 프로젝트 설정&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1편의 콘솔 프로젝트에 패키지를 추가한다. VS2022: &lt;b&gt;도구 &amp;rarr; NuGet 패키지 관리자 &amp;rarr; 솔루션용 NuGet 관리&lt;/b&gt; &amp;rarr; 검색해 설치. 또는 .csproj를 직접 편집:&lt;/p&gt;
&lt;pre class=&quot;xml&quot;&gt;&lt;code&gt;&amp;lt;Project Sdk=&quot;Microsoft.NET.Sdk&quot;&amp;gt;
  &amp;lt;PropertyGroup&amp;gt;
    &amp;lt;OutputType&amp;gt;Exe&amp;lt;/OutputType&amp;gt;
    &amp;lt;TargetFramework&amp;gt;net8.0&amp;lt;/TargetFramework&amp;gt;
    &amp;lt;ImplicitUsings&amp;gt;enable&amp;lt;/ImplicitUsings&amp;gt;
    &amp;lt;Nullable&amp;gt;enable&amp;lt;/Nullable&amp;gt;
    &amp;lt;RootNamespace&amp;gt;PharmaReturn&amp;lt;/RootNamespace&amp;gt;
    &amp;lt;!-- ZXingCpp 네이티브 라이브러리는 64비트다. 64비트로 고정. --&amp;gt;
    &amp;lt;Platforms&amp;gt;x64&amp;lt;/Platforms&amp;gt;
    &amp;lt;PlatformTarget&amp;gt;x64&amp;lt;/PlatformTarget&amp;gt;
  &amp;lt;/PropertyGroup&amp;gt;

  &amp;lt;ItemGroup&amp;gt;
    &amp;lt;PackageReference Include=&quot;ZXingCpp&quot; Version=&quot;0.5.1&quot; /&amp;gt;
    &amp;lt;PackageReference Include=&quot;SixLabors.ImageSharp&quot; Version=&quot;2.1.9&quot; /&amp;gt;
    &amp;lt;PackageReference Include=&quot;ZXing.Net&quot; Version=&quot;0.16.10&quot; /&amp;gt;
  &amp;lt;/ItemGroup&amp;gt;

  &amp;lt;ItemGroup&amp;gt;
    &amp;lt;None Include=&quot;data\**\*&quot; CopyToOutputDirectory=&quot;PreserveNewest&quot; /&amp;gt;
  &amp;lt;/ItemGroup&amp;gt;
&amp;lt;/Project&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;  &lt;b&gt;&amp;lt;PlatformTarget&amp;gt;x64&amp;lt;/PlatformTarget&amp;gt; 가 왜 중요?&lt;/b&gt; ZXingCpp는 안에 C++로 만든 네이티브 .dll을 품고 있는데 64비트다. 프로젝트가 32비트(AnyCPU+Prefer32bit)면 그 dll을 못 불러 DllNotFoundException이 난다. 그래서 64비트로 못 박는다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  코드 (5-2) 테스트용 코드 이미지 만들기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;카메라가 없어도 테스트하려면, 우리가 코드 이미지를 만들어 그걸 다시 읽으면 된다(닫힌 루프). TestImageMaker.cs 추가:&lt;/p&gt;
&lt;pre class=&quot;cs&quot;&gt;&lt;code&gt;using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;
using ZXing;
using ZXing.Common;
using ZXing.Datamatrix;

namespace PharmaReturn;

/// &amp;lt;summary&amp;gt;테스트용 GS1 DataMatrix PNG를 만든다(생성=ZXing.Net).&amp;lt;/summary&amp;gt;
public static class TestImageMaker
{
    public static void Generate(string content, string outPath, int codePx = 240)
    {
        var hints = new Dictionary&amp;lt;EncodeHintType, object&amp;gt;
        {
            { EncodeHintType.GS1_FORMAT, true }, // 맨 앞에 FNC1(=GS1 표시) 추가
            { EncodeHintType.MARGIN, 1 },        // 코드 둘레 여백(quiet zone)
        };
        // 1) 내용 &amp;rarr; 흑백 격자(BitMatrix)로 인코딩
        BitMatrix matrix = new DataMatrixWriter()
            .encode(content, BarcodeFormat.DATA_MATRIX, codePx, codePx, hints);

        // 2) 격자를 PNG로 그리기 (true=검정, false=흰색)
        using var img = new Image&amp;lt;L8&amp;gt;(matrix.Width, matrix.Height);
        for (int y = 0; y &amp;lt; matrix.Height; y++)
            for (int x = 0; x &amp;lt; matrix.Width; x++)
                img[x, y] = new L8(matrix[x, y] ? (byte)0 : (byte)255);
        img.Save(outPath);
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;  한 줄씩:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;DataMatrixWriter().encode(...): 내용을 흑백 격자(BitMatrix)로 만든다. GS1_FORMAT=true면 GS1 규칙대로 FNC1을 앞에 붙인다.&lt;/li&gt;
&lt;li&gt;Image&amp;lt;L8&amp;gt;: 8비트 회색(L=Luminance) 이미지. 0=검정, 255=흰색.&lt;/li&gt;
&lt;li&gt;격자의 각 칸을 픽셀로 칠해 PNG로 저장.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  코드 (5-3) 가장 단순한 디코더&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;BarcodeServiceCpp.cs 추가(이번 Lesson 버전 &amp;mdash; 다음 Lesson에서 키운다):&lt;/p&gt;
&lt;pre class=&quot;cs&quot;&gt;&lt;code&gt;using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;
using ZXingCpp;
using SsImage = SixLabors.ImageSharp.Image;   // &amp;larr; 이름 충돌 회피(아래  )

namespace PharmaReturn;

public static class BarcodeServiceCpp
{
    /// &amp;lt;summary&amp;gt;이미지 한 장에서 DataMatrix 문자열을 모두 읽는다.&amp;lt;/summary&amp;gt;
    public static List&amp;lt;string&amp;gt; DecodeAll(string imagePath)
    {
        // 1) 이미지 로드 &amp;rarr; RGB 픽셀 바이트로 복사
        using var image = SsImage.Load&amp;lt;Rgb24&amp;gt;(imagePath);
        var rgb = new byte[image.Width * image.Height * 3];
        image.CopyPixelDataTo(rgb);

        // 2) ZXingCpp가 이해하는 ImageView로 포장
        var view = new ImageView(rgb, image.Width, image.Height, ImageFormat.RGB);

        // 3) 디코더 설정: DataMatrix만, 반전/회전도 시도
        var reader = new BarcodeReader
        {
            Formats = BarcodeFormat.DataMatrix, // 포맷 한정 &amp;rarr; 빠르고 정확
            TryInvert = true,                   // 흰 바탕 검은 코드의 반전도 시도
            TryRotate = true,                   // 돌아간 코드도 시도
        };

        // 4) From()은 찾은 모든 바코드 목록을 돌려준다(다중 판독이 기본)
        var results = new List&amp;lt;string&amp;gt;();
        foreach (var b in reader.From(view))
            if (b.IsValid &amp;amp;&amp;amp; !string.IsNullOrEmpty(b.Text))
                results.Add(b.Text);
        return results;
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;  &lt;b&gt;using SsImage = SixLabors.ImageSharp.Image; 이게 뭐죠?&lt;/b&gt; ZXingCpp에도 Image라는 타입이 있고 SixLabors.ImageSharp에도 Image가 있다. 둘 다 using 하면 컴파일러가 &quot;어느 Image?&quot;라며 &lt;b&gt;모호 참조 오류&lt;/b&gt;를 낸다(실제로 만들다 보면 만나는 흔한 에러다). 그래서 ImageSharp의 Image에 SsImage라는 &lt;b&gt;별명&lt;/b&gt;을 붙여 명확히 가리킨다. Rgb24는 ImageSharp에만, ImageView&amp;middot;BarcodeReader는 ZXingCpp에만 있어 충돌이 없다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;✅ 직접 해보기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Program.cs를 잠깐 이렇게:&lt;/p&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;using PharmaReturn;

string path = Path.Combine(AppContext.BaseDirectory, &quot;test.png&quot;);
// 1) 테스트 코드 만들기 (괄호 없는 원시형으로 생성)
TestImageMaker.Generate(&quot;010880644309681317280315106248607&quot;, path);
// 2) 다시 읽기
foreach (var code in BarcodeServiceCpp.DecodeAll(path))
    Console.WriteLine(&quot;읽음: &quot; + code);
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;읽음: ...08806443096813...280315...6248607... 처럼 나오면 성공. (생성 옵션에 따라 GS 구분자가 보이지 않게 섞일 수 있는데, 1편 파서가 처리하니 걱정 말자.)&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Lesson 6 &amp;mdash; 위치 좌표 + 다중 판독&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  목표&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;바코드의 **문자열뿐 아니라 위치(네 꼭짓점)**도 함께 얻는다. 이건 나중에 화면에서 파란 박스를 그릴 재료다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  개념 1: 왜 위치가 필요한가&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3편 화면에서 &quot;이 박스를 읽었어요&quot;를 사람이 보려면, 코드가 이미지의 &lt;b&gt;어디에&lt;/b&gt; 있는지 알아야 한다. 디코더는 각 코드의 &lt;b&gt;네 꼭짓점 좌표&lt;/b&gt;(좌상&amp;middot;우상&amp;middot;우하&amp;middot;좌하)를 함께 알려준다.&lt;/p&gt;
&lt;pre class=&quot;gcode&quot;&gt;&lt;code&gt;   (TopLeft)───────(TopRight)
       │   DataMatrix   │
   (BottomLeft)────(BottomRight)
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 좌표는 &lt;b&gt;이미지 픽셀 좌표&lt;/b&gt;다. 즉 &quot;원본 이미지에서 왼쪽 위가 (0,0), 오른쪽으로 X, 아래로 Y&quot;인 좌표계. (화면에 그릴 땐 확대/이동을 반영해 변환해야 하는데, 그건 3편에서.)&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  개념 2: 결과를 담을 그릇 DecodedCode&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문자열 + 꼭짓점 4개 + 유효 여부를 한 묶음으로 만든다. 1편에서 배운 record가 딱이다.&lt;/p&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;public sealed record DecodedCode(string Text, System.Drawing.Point[] Corners, bool Valid);
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;  System.Drawing.Point는 &quot;정수 좌표 한 점(X,Y)&quot;을 담는 표준 타입이다. 크로스플랫폼 콘솔(net8.0)에서도 쓸 수 있다(System.Drawing.Primitives에 포함). 매번 길게 쓰기 싫어서 파일 위에서 using DrawPoint = System.Drawing.Point; 별명을 준다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  개념 3: &quot;좌표 변환 함수&quot;를 미리 끼워두는 설계&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 Lesson(타일)에서, 잘라낸 조각 안의 좌표를 &lt;b&gt;원본 이미지 좌표로 되돌려야&lt;/b&gt; 한다. 그래서 디코딩 핵심부를 만들 때, &quot;꼭짓점을 어떻게 변환할지&quot;를 &lt;b&gt;함수로 받아두면&lt;/b&gt; 전체/조각 모두 같은 코드로 처리할 수 있다. 이게 Func&amp;lt;int,int,DrawPoint&amp;gt; transform다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;전체 이미지일 때: (x, y) =&amp;gt; 그대로 (x, y) &amp;mdash; 변환 없음.&lt;/li&gt;
&lt;li&gt;조각(타일)일 때: (x, y) =&amp;gt; (타일위치 + x/확대배율, ...) &amp;mdash; 원본 좌표로 환산.&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;  처음 보면 &quot;함수를 인자로 넘긴다&quot;가 낯설 수 있다. 요리로 비유하면, 디코딩 함수는 &quot;재료를 그릇에 담는 일&quot;만 하고, **담기 직전에 적용할 양념(좌표 변환)**을 호출자가 골라 건네는 것이다. 덕분에 같은 디코딩 함수를 전체/조각에 재사용한다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  코드&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;BarcodeServiceCpp.cs를 아래로 키운다(전체 이미지 다중 판독 + 위치).&lt;/p&gt;
&lt;pre class=&quot;cs&quot;&gt;&lt;code&gt;using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;
using ZXingCpp;
using SsImage = SixLabors.ImageSharp.Image;
using DrawPoint = System.Drawing.Point;

namespace PharmaReturn;

/// &amp;lt;summary&amp;gt;판독 결과 1건: 원문 + 4꼭짓점(원본 이미지 픽셀 좌표).&amp;lt;/summary&amp;gt;
public sealed record DecodedCode(string Text, DrawPoint[] Corners, bool Valid);

public static class BarcodeServiceCpp
{
    /// &amp;lt;summary&amp;gt;전체 이미지에서 다중 판독(위치 포함).&amp;lt;/summary&amp;gt;
    public static List&amp;lt;DecodedCode&amp;gt; DecodeDetailed(string imagePath)
    {
        using var image = SsImage.Load&amp;lt;Rgb24&amp;gt;(imagePath);
        // 전체 이미지: 좌표 변환 없음 &amp;rarr; 그대로
        return DecodeView(image, (x, y) =&amp;gt; new DrawPoint(x, y));
    }

    /// &amp;lt;summary&amp;gt;문자열만 필요할 때(하위 호환).&amp;lt;/summary&amp;gt;
    public static List&amp;lt;string&amp;gt; DecodeAll(string imagePath)
        =&amp;gt; DecodeDetailed(imagePath).Select(c =&amp;gt; c.Text).ToList();

    /// &amp;lt;summary&amp;gt;
    /// 한 장의 (이미 준비된) 이미지를 디코드한다.
    /// transform: 디코더가 준 조각-내부 좌표(cx,cy)를 원본 좌표로 바꾸는 함수.
    /// &amp;lt;/summary&amp;gt;
    private static List&amp;lt;DecodedCode&amp;gt; DecodeView(Image&amp;lt;Rgb24&amp;gt; img, Func&amp;lt;int, int, DrawPoint&amp;gt; transform)
    {
        var rgb = new byte[img.Width * img.Height * 3];
        img.CopyPixelDataTo(rgb);
        var view = new ImageView(rgb, img.Width, img.Height, ImageFormat.RGB);

        var reader = new BarcodeReader
        {
            Formats = BarcodeFormat.DataMatrix,
            TryInvert = true,
            TryRotate = true,
        };

        var list = new List&amp;lt;DecodedCode&amp;gt;();
        foreach (var b in reader.From(view))
        {
            if (!b.IsValid || string.IsNullOrEmpty(b.Text)) continue;

            // Position: 네 꼭짓점(PointI: X, Y).
            // ※ 설치된 ZXingCpp 버전에 따라 멤버명이 다를 수 있다(아래 ⚠️).
            var p = b.Position;
            var corners = new[]
            {
                transform(p.TopLeft.X,     p.TopLeft.Y),
                transform(p.TopRight.X,    p.TopRight.Y),
                transform(p.BottomRight.X, p.BottomRight.Y),
                transform(p.BottomLeft.X,  p.BottomLeft.Y),
            };
            list.Add(new DecodedCode(b.Text, corners, true));
        }
        return list;
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;  핵심:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;DecodeDetailed는 DecodeView에 &quot;변환 안 함&quot; 함수를 넘긴다(전체 이미지니까).&lt;/li&gt;
&lt;li&gt;b.Position에서 네 꼭짓점을 꺼내 transform을 거쳐 Corners에 담는다.&lt;/li&gt;
&lt;li&gt;결과는 DecodedCode 목록.&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;⚠️ &lt;b&gt;버전 주의(중요):&lt;/b&gt; b.Position.TopLeft.X 부분은 ZXingCpp 버전에 따라 멤버 이름이 다를 수 있다(예: Position이 배열/인덱서이거나 TopLeft가 소문자거나). 빌드에서 이 줄에 에러가 나면, 설치된 버전의 Barcode/Position 정의를 보고 그 이름에 맞춰 바꾸면 된다. &lt;b&gt;나머지 구조는 그대로 둔다.&lt;/b&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;✅ 직접 해보기&lt;/h3&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;using PharmaReturn;
string path = Path.Combine(AppContext.BaseDirectory, &quot;test.png&quot;);
TestImageMaker.Generate(&quot;010880644309681317280315106248607&quot;, path);

foreach (var c in BarcodeServiceCpp.DecodeDetailed(path))
{
    Console.WriteLine($&quot;문자열: {c.Text}&quot;);
    Console.WriteLine($&quot;좌상 꼭짓점: ({c.Corners[0].X},{c.Corners[0].Y})&quot;);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문자열과 좌상 꼭짓점 좌표가 같이 나오면 성공. (좌표는 코드가 그려진 위치 픽셀이다.)&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Lesson 7 &amp;mdash; 타일 판독(대량&amp;middot;작은 코드) + 영역 판독&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  목표&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;큰 사진 한 장에 작은 코드가 여러 개여도 최대한 다 읽는다. 또 사용자가 고른 &lt;b&gt;특정 영역만&lt;/b&gt; 다시 읽는다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  개념 1: 왜 전체 디코드로는 부족한가&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스마트폰 사진은 크다(예: 1152&amp;times;2560). 그 안에 코드가 작게 여러 개면, 디코더가 전체에서 &lt;b&gt;한두 개만&lt;/b&gt; 찾고 만다. 코드가 화면 대비 너무 작아 &quot;안 보이는&quot; 셈이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;해결책 = 타일 분할.&lt;/b&gt; 이미지를 작은 사각형(타일)으로 쪼개 각 타일을 디코드하면, 그 타일 안에선 코드가 &lt;b&gt;상대적으로 커져&lt;/b&gt; 잘 읽힌다. 거기에 타일을 &lt;b&gt;확대(upscale)&lt;/b&gt; 까지 하면 더 좋아진다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt; 큰 사진을 격자로 쪼갬(겹치게)        각 타일을 확대해서 디코드
 ┌────┬────┬────┐                  ┌──────────┐
 │ ▥  │  ▥ │ ▥  │   ──▶ 타일1 ──▶  │   ▥▥▥    │ ──▶ 읽힘!
 ├────┼────┼────┤                  └──────────┘
 │  ▥ │ ▥  │  ▥ │
 └────┴────┴────┘
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  개념 2: 겹침(overlap)이 왜 필요한가&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드가 타일 &lt;b&gt;경계에 걸치면&lt;/b&gt; 잘려서 못 읽는다. 그래서 타일을 50% 정도 &lt;b&gt;겹치게&lt;/b&gt; 이동시키면, 경계에 걸린 코드도 옆 타일에선 온전히 들어온다.&lt;/p&gt;
&lt;pre class=&quot;gherkin&quot;&gt;&lt;code&gt; 겹침 없음: 경계의 코드가 반토막 ✗
   |&amp;oline;&amp;oline;&amp;oline;&amp;oline;|&amp;oline;&amp;oline;&amp;oline;&amp;oline;|
   |  ▥▮|▮▥  |     &amp;larr; 코드가 두 타일에 쪼개짐
 겹침 50%: 다음 타일이 절반 겹쳐 온전히 포함 ✓
   |&amp;oline;&amp;oline;&amp;oline;&amp;oline;|
      |&amp;oline;&amp;oline;&amp;oline;&amp;oline;|        &amp;larr; 이 타일 안에 코드 전체가 들어옴
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;step = tile &amp;times; (1 - overlap) 만큼만 이동한다. overlap=0.5면 타일 크기의 절반씩 이동.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  개념 3: 좌표 되돌리기(이게 transform의 진짜 쓸모)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;타일을 잘라 &lt;b&gt;3배 확대&lt;/b&gt;해서 디코드하면, 디코더가 주는 꼭짓점은 &quot;확대된 조각 안&quot; 좌표다. 이걸 &lt;b&gt;원본 좌표&lt;/b&gt;로 되돌려야 화면에 제 위치에 그린다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;조각은 원본의 (ox, oy)에서 잘렸고, up배 확대됐다.&lt;/li&gt;
&lt;li&gt;그러니 조각 내부 좌표 (cx, cy) &amp;rarr; 원본 좌표 = (ox + cx/up, oy + cy/up).&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이게 (cx, cy) =&amp;gt; new DrawPoint(ox + cx / up, oy + cy / up) 한 줄의 의미다. Lesson 6에서 &quot;변환 함수를 받아두는&quot; 설계를 한 이유가 여기서 빛난다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  개념 4: 중복 제거(dedup)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;타일이 겹치니 같은 코드가 여러 타일에서 잡힌다. 그래서 &lt;b&gt;문자열을 키로&lt;/b&gt; 딕셔너리에 담아(TryAdd) 같은 내용은 한 번만 남긴다. (의약품은 일련번호(21)가 낱개마다 달라 문자열이 전부 달라서, 서로 다른 박스가 합쳐질 걱정은 없다.)&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  코드 (최종형)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;BarcodeServiceCpp.cs를 최종 버전으로 키운다. (Lesson 6 버전에 타일/영역/확대 처리를 더한 것)&lt;/p&gt;
&lt;pre class=&quot;cs&quot;&gt;&lt;code&gt;using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;   // Crop, Resize, Grayscale, Contrast
using ZXingCpp;
using SsImage = SixLabors.ImageSharp.Image;
using DrawPoint = System.Drawing.Point;
using DrawRect = System.Drawing.Rectangle;

namespace PharmaReturn;

public sealed record DecodedCode(string Text, DrawPoint[] Corners, bool Valid);

public static class BarcodeServiceCpp
{
    /// &amp;lt;summary&amp;gt;전체 + 타일 다중 패스로 가능한 모든 코드를 위치와 함께 회수.&amp;lt;/summary&amp;gt;
    public static List&amp;lt;DecodedCode&amp;gt; DecodeDetailed(string imagePath)
    {
        using var image = SsImage.Load&amp;lt;Rgb24&amp;gt;(imagePath);
        var byText = new Dictionary&amp;lt;string, DecodedCode&amp;gt;();

        // 1) 전체 이미지 한 번
        foreach (var c in DecodeView(image, (x, y) =&amp;gt; new DrawPoint(x, y)))
            byText.TryAdd(c.Text, c);

        // 2) 타일 패스: (타일 크기, 확대배율) 두 조합으로 작은 코드 회수
        foreach (var (tile, up) in new[] { (512, 2), (320, 3) })
            TilePass(image, tile, overlap: 0.5, upscale: up, byText);

        return byText.Values.ToList();
    }

    /// &amp;lt;summary&amp;gt;지정 영역만 확대해 재판독(꼭짓점은 원본 좌표로 보정).&amp;lt;/summary&amp;gt;
    public static List&amp;lt;DecodedCode&amp;gt; DecodeRegion(string imagePath, DrawRect region)
    {
        using var image = SsImage.Load&amp;lt;Rgb24&amp;gt;(imagePath);
        // 영역이 이미지 밖으로 나가지 않게 교집합으로 자른다
        var r = DrawRect.Intersect(region, new DrawRect(0, 0, image.Width, image.Height));
        if (r.Width &amp;lt;= 1 || r.Height &amp;lt;= 1) return new();

        const int up = 2;
        using var crop = image.Clone(c =&amp;gt; c.Crop(new Rectangle(r.X, r.Y, r.Width, r.Height))
                                           .Resize(r.Width * up, r.Height * up).Grayscale());
        var byText = new Dictionary&amp;lt;string, DecodedCode&amp;gt;();
        foreach (var c in DecodeView(crop, (cx, cy) =&amp;gt; new DrawPoint(r.X + cx / up, r.Y + cy / up)))
            byText.TryAdd(c.Text, c);
        return byText.Values.ToList();
    }

    public static List&amp;lt;string&amp;gt; DecodeAll(string imagePath)
        =&amp;gt; DecodeDetailed(imagePath).Select(c =&amp;gt; c.Text).ToList();

    // ── 내부 ───────────────────────────────────────────────
    private static void TilePass(Image&amp;lt;Rgb24&amp;gt; image, int tile, double overlap, int upscale,
                                 Dictionary&amp;lt;string, DecodedCode&amp;gt; byText)
    {
        int step = Math.Max(1, (int)(tile * (1 - overlap))); // 겹침만큼 덜 이동
        for (int y = 0; y &amp;lt; image.Height; y += step)
            for (int x = 0; x &amp;lt; image.Width; x += step)
            {
                int w = Math.Min(tile, image.Width - x);   // 가장자리에서 잘림 방지
                int h = Math.Min(tile, image.Height - y);
                if (w &amp;lt; 40 || h &amp;lt; 40) continue;             // 너무 작은 조각은 스킵

                int ox = x, oy = y, up = upscale;
                // 조각을 잘라 &amp;rarr; 확대 &amp;rarr; 흑백 &amp;rarr; 대비 강화
                using var crop = image.Clone(c =&amp;gt; c.Crop(new Rectangle(ox, oy, w, h))
                                                   .Resize(w * up, h * up).Grayscale().Contrast(1.2f));
                // 조각 내부 좌표 &amp;rarr; 원본 좌표로 되돌리는 변환을 넘긴다
                foreach (var c in DecodeView(crop, (cx, cy) =&amp;gt; new DrawPoint(ox + cx / up, oy + cy / up)))
                    byText.TryAdd(c.Text, c);  // 중복(같은 문자열)은 자동 무시
            }
    }

    private static List&amp;lt;DecodedCode&amp;gt; DecodeView(Image&amp;lt;Rgb24&amp;gt; img, Func&amp;lt;int, int, DrawPoint&amp;gt; transform)
    {
        var rgb = new byte[img.Width * img.Height * 3];
        img.CopyPixelDataTo(rgb);
        var view = new ImageView(rgb, img.Width, img.Height, ImageFormat.RGB);

        var reader = new BarcodeReader
        {
            Formats = BarcodeFormat.DataMatrix,
            TryInvert = true,
            TryRotate = true,
        };

        var list = new List&amp;lt;DecodedCode&amp;gt;();
        foreach (var b in reader.From(view))
        {
            if (!b.IsValid || string.IsNullOrEmpty(b.Text)) continue;
            var p = b.Position;
            var corners = new[]
            {
                transform(p.TopLeft.X,     p.TopLeft.Y),
                transform(p.TopRight.X,    p.TopRight.Y),
                transform(p.BottomRight.X, p.BottomRight.Y),
                transform(p.BottomLeft.X,  p.BottomLeft.Y),
            };
            list.Add(new DecodedCode(b.Text, corners, true));
        }
        return list;
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;  새로 들어온 것 설명:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;image.Clone(c =&amp;gt; c.Crop(...).Resize(...).Grayscale().Contrast(...))&lt;/b&gt;: ImageSharp의 처리 체인. 원본을 건드리지 않고 복제본에 자르기&amp;rarr;확대&amp;rarr;흑백&amp;rarr;대비 강화를 순서대로 적용한다. (using System.Drawing.Processing; 필요)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;흑백&amp;middot;대비&lt;/b&gt;를 왜? 디코더는 명암으로 모듈을 구분한다. 색 정보를 빼고 대비를 키우면 인쇄가 옅은 코드도 잘 잡힌다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;DecodeRegion&lt;/b&gt;: 사용자가 고른 사각형(region)만 잘라 2배 확대해 디코드. 3편에서 &quot;영역 판독&quot; 버튼에 연결된다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;DrawRect.Intersect&lt;/b&gt;: 사용자가 이미지 경계 밖까지 드래그해도 안전하게 이미지 안으로 잘라준다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  개념 5(중요): 그래도 안 되는 코드가 있다 &amp;mdash; 한계와 운영&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;타일&amp;middot;확대&amp;middot;대비까지 다 해도, &lt;b&gt;인쇄 자체가 흐려 데이터가 손상된 코드&lt;/b&gt;는 못 읽는다(오류정정 한도 밖). 이건 알고리즘이 아니라 물리적 한계다. 운영에서는:&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;더 정면&amp;middot;근접 촬영&lt;/b&gt; 또는 &lt;b&gt;줄(트레이) 단위로 나눠 촬영&lt;/b&gt; &amp;rarr; 정상 인쇄분은 거의 다 잡힘.&lt;/li&gt;
&lt;li&gt;그래도 안 되면 &lt;b&gt;그 박스의 인쇄문자(사람이 읽는 글자)를 OCR로 보완&lt;/b&gt; &amp;rarr; 3편에서 만든다.&lt;/li&gt;
&lt;li&gt;인쇄가 흐린 로트는 &lt;b&gt;입고 검수 단계에서 재라벨/반려&lt;/b&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;✅ 직접 해보기&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;여러 코드를 한 장에 만들어 다중 판독 확인:&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;using PharmaReturn;
string dir = AppContext.BaseDirectory;

// 코드 3장을 각각 만든 뒤, 직접 한 장에 합치긴 번거로우니
// 여기서는 '한 장에 1개' 이미지를 여러 개 만들어 각각 디코드해 본다.
string[] codes =
{
    &quot;010880644309681317280315106248607&quot;,
    &quot;010880644309632517280414106240606&quot;,
    &quot;010880644304152317290420101190605&quot;,
};
for (int i = 0; i &amp;lt; codes.Length; i++)
{
    string p = Path.Combine(dir, $&quot;t{i}.png&quot;);
    TestImageMaker.Generate(codes[i], p);
    var found = BarcodeServiceCpp.DecodeDetailed(p);
    Console.WriteLine($&quot;t{i}.png &amp;rarr; {found.Count}개: {string.Join(&quot; / &quot;, found.Select(c =&amp;gt; c.Text))}&quot;);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 파일에서 1개씩 읽히면 OK.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;(선택) 실제 스마트폰으로 박스 사진을 찍어 프로젝트에 넣고 DecodeDetailed(&quot;내사진.jpg&quot;)로 몇 개 잡히는지 보자. 정면&amp;middot;또렷할수록 많이 잡힌다. 전체 1패스보다 &lt;b&gt;타일 패스 덕분에 더 많이&lt;/b&gt; 잡히는 걸 체감할 수 있다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2편 마무리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금까지:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;TestImageMaker.cs &amp;mdash; 테스트용 코드 이미지 생성(ZXing.Net)&lt;/li&gt;
&lt;li&gt;BarcodeServiceCpp.cs &amp;mdash; 이미지 &amp;rarr; 코드 문자열 &lt;b&gt;+ 위치&lt;/b&gt;, &lt;b&gt;다중&amp;middot;타일&amp;middot;영역&lt;/b&gt; 판독(ZXingCpp + ImageSharp)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 1편 + 2편을 합치면 &quot;&lt;b&gt;이미지 &amp;rarr; 코드 문자열 &amp;rarr; 파싱 &amp;rarr; 대조 &amp;rarr; 보상&lt;/b&gt;&quot;의 끝에서 끝까지가 콘솔에서 돈다. 한번 직접 이어 붙여 실행해 보자:&lt;/p&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;using PharmaReturn;
var repo = DeliveryRepository.LoadCsv(Path.Combine(AppContext.BaseDirectory, &quot;data&quot;, &quot;deliveries.csv&quot;));
var svc = new CompensationService(repo, today: new DateOnly(2026, 6, 16));

foreach (var c in BarcodeServiceCpp.DecodeDetailed(&quot;내사진.jpg&quot;))   // ① 이미지 &amp;rarr; 코드
{
    var f = Gs1Parser.Parse(c.Text);                                // ② 파싱
    var r = svc.Evaluate(new ReturnRequest(f.Gtin!, f.Lot, f.Expiry, 1, ReturnReason.Expiry)); // ③ 보상
    Console.WriteLine($&quot;{f.Gtin} {f.Lot} &amp;rarr; [{r.Status}] {r.Message}&quot;);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;핵심 복습&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;디코더는 &lt;b&gt;이미지 픽셀 배열(ImageView)&lt;/b&gt; 을 먹는다 &amp;rarr; ImageSharp로 변환해 넘긴다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;다중 판독&lt;/b&gt;은 reader.From()이 목록을 주는 것으로 기본 지원.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;타일 분할 + 확대 + 겹침&lt;/b&gt;으로 큰 사진의 작은 코드 회수율을 끌어올린다. 조각 좌표는 transform으로 원본 좌표로 되돌린다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;물리적으로 흐린 코드&lt;/b&gt;는 한계 &amp;rarr; 촬영 개선 또는 OCR 보완(3편).&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>개발(IT)/C#(VisualStudio)</category>
      <category>DataMatrix GS1 스캔</category>
      <category>DataMatrix 구조</category>
      <category>DataMatrix 다중판독</category>
      <category>GS1 DataMatrix 디코드</category>
      <category>GS1 Parser</category>
      <category>OCR ImageSharp 처리</category>
      <category>OCR 바코드판독</category>
      <category>ZXing.Net</category>
      <category>ZXingCpp 생성</category>
      <category>소니스토리</category>
      <author>isony</author>
      <guid isPermaLink="true">https://isony.tistory.com/347</guid>
      <comments>https://isony.tistory.com/entry/%EC%9D%98%EC%95%BD%ED%92%88-%EB%B0%98%ED%92%88-%EB%B3%B4%EC%83%81-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%A8-%EB%A7%8C%EB%93%A4%EA%B8%B0-%E2%80%94-%EB%8B%A8%EA%B3%84%EB%B3%84-%EA%B0%95%EC%9D%98-2%ED%8E%B8#entry347comment</comments>
      <pubDate>Mon, 6 Jul 2026 07:33:10 +0900</pubDate>
    </item>
    <item>
      <title>2026년07월05일 주일예배 (이재훈목사님) - 1부</title>
      <link>https://isony.tistory.com/entry/2026%EB%85%8407%EC%9B%9405%EC%9D%BC-%EC%A3%BC%EC%9D%BC%EC%98%88%EB%B0%B0-%EC%9D%B4%EC%9E%AC%ED%9B%88%EB%AA%A9%EC%82%AC%EB%8B%98-1%EB%B6%80</link>
      <description>&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;2026년07월05일 주일예배 (이재훈목사님) - 1부&lt;/h2&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;주의 말씀 : 나를 따르라&amp;nbsp; (8)&lt;/h2&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;그리스도를 통하여 서로에게&lt;/h2&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;성경 :&amp;nbsp; 요한일서 1:3 ~ 7 말씀 (출처:우리말성경)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&amp;lt; 성경 &amp;gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;1:3 우리가 보고 들은 것을 여러분에게도 전파합니다. 이는 여러분과 우리가 서로 사귐이 있게 하려는 것입니다. 우리의 사귐은 아버지와 그의 아들 예수 그리스도와 함께하는 사귐입니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;1:4 우리가 이 글을 쓰는 것은 우리 서로의 기쁨이 가득 차고 넘치게 하려는 것입니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;1:5 우리가 그리스도에게서 듣고 여러분에게 전하는 소식은 이것입니다. 곧 하나님은 빛이시니 하나님 안에는 어둠이 전혀 없습니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;1:6 만일 우리가 하나님과 사귐이 있다고 하면서 여전히 어둠 가운데 행한다면 우리는 거짓말하는 것이며 진리를 따라 사는 것이 아닙니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;1:7 그러나 하나님께서 빛 가운데 계신 것처럼 우리가 빛 가운데 행하면 우리에게는 서로 사귐이 있고 하나님의 아들 예수의 피가 우리를 모든 죄에서 깨끗하게 해 주십니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&amp;lt; 예배 영상 &amp;gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;a href=&quot;https://youtu.be/T-6F2Nj2fEE&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://youtu.be/T-6F2Nj2fEE&lt;/a&gt;&lt;/b&gt;&lt;/p&gt;
&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignCenter&quot; data-video-host=&quot;youtube&quot; data-video-url=&quot;https://www.youtube.com/watch?v=T-6F2Nj2fEE&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/cXUrtX/dJMb8SpTmn1/yKZssVdLpftqnxvyZPa4D1/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=570_156_702_300,https://scrap.kakaocdn.net/dn/cEfRLB/dJMb8ZvMIQR/2dI63HOrPvjCaMNA1VmcK1/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=570_156_702_300,https://scrap.kakaocdn.net/dn/b6fcMG/dJMb8WMAZwV/MtvuX7mKiXXLPtsVHrQviK/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=570_156_702_300&quot; data-video-width=&quot;860&quot; data-video-height=&quot;484&quot; data-video-origin-width=&quot;860&quot; data-video-origin-height=&quot;484&quot; data-ke-mobilestyle=&quot;widthContent&quot; data-video-title=&quot;주일예배2026 07 05&quot; data-original-url=&quot;&quot;&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/T-6F2Nj2fEE&quot; width=&quot;860&quot; height=&quot;484&quot; frameborder=&quot;&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;figcaption style=&quot;display: none;&quot;&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&amp;lt; 사도신경 &amp;gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;bandicam 2026-07-05 07-42-42-436.jpg&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zfnvq/dJMcabkyVcw/CkeCxRzKEK0goCQ9KEBfCK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zfnvq/dJMcabkyVcw/CkeCxRzKEK0goCQ9KEBfCK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zfnvq/dJMcabkyVcw/CkeCxRzKEK0goCQ9KEBfCK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fzfnvq%2FdJMcabkyVcw%2FCkeCxRzKEK0goCQ9KEBfCK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-filename=&quot;bandicam 2026-07-05 07-42-42-436.jpg&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;bandicam 2026-07-05 07-43-05-059.jpg&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/br8Kgg/dJMcagMWYHy/aX9IKwikSTFPxfNcmeRCTK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/br8Kgg/dJMcagMWYHy/aX9IKwikSTFPxfNcmeRCTK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/br8Kgg/dJMcagMWYHy/aX9IKwikSTFPxfNcmeRCTK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbr8Kgg%2FdJMcagMWYHy%2FaX9IKwikSTFPxfNcmeRCTK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-filename=&quot;bandicam 2026-07-05 07-43-05-059.jpg&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>성경과 QT/주일예배(온누리교회)</category>
      <category>CGNTV</category>
      <category>그리스도를 통하여 서로에게</category>
      <category>나를 따르라</category>
      <category>소니스토리</category>
      <category>온누리교회</category>
      <category>온누리교회 주일예배</category>
      <category>우리말성경</category>
      <category>우리말성경 요한일서</category>
      <category>이재훈목사</category>
      <category>이재훈목사 주일예배</category>
      <author>isony</author>
      <guid isPermaLink="true">https://isony.tistory.com/346</guid>
      <comments>https://isony.tistory.com/entry/2026%EB%85%8407%EC%9B%9405%EC%9D%BC-%EC%A3%BC%EC%9D%BC%EC%98%88%EB%B0%B0-%EC%9D%B4%EC%9E%AC%ED%9B%88%EB%AA%A9%EC%82%AC%EB%8B%98-1%EB%B6%80#entry346comment</comments>
      <pubDate>Sun, 5 Jul 2026 07:54:38 +0900</pubDate>
    </item>
    <item>
      <title>[블로그 운영] 티스토리 애드센스 신청부터 GSC 등록까지 - 2주 완성 가이드 (IT 블로그 기준)</title>
      <link>https://isony.tistory.com/entry/%EB%B8%94%EB%A1%9C%EA%B7%B8-%EC%9A%B4%EC%98%81-%ED%8B%B0%EC%8A%A4%ED%86%A0%EB%A6%AC-%EC%95%A0%EB%93%9C%EC%84%BC%EC%8A%A4-%EC%8B%A0%EC%B2%AD%EB%B6%80%ED%84%B0-GSC-%EB%93%B1%EB%A1%9D%EA%B9%8C%EC%A7%80-2%EC%A3%BC-%EC%99%84%EC%84%B1-%EA%B0%80%EC%9D%B4%EB%93%9C-IT-%EB%B8%94%EB%A1%9C%EA%B7%B8-%EA%B8%B0%EC%A4%80</link>
      <description>&lt;h1&gt;[블로그 운영] 티스토리 애드센스 신청부터 GSC 등록까지 - 2주 완성 가이드 (IT 블로그 기준)&lt;/h1&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;테스트 환경&lt;/b&gt;: 티스토리, Google AdSense, Google Search Console&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;블로그를 몇 달 동안 열심히 운영한 후 가장 궁금해지는 것이 &lt;b&gt;&quot;언제, 어떻게 애드센스를 신청해야 승인률이 높을까?&quot;&lt;/b&gt; 입니다. 검색해보면 정보가 산재해 있고, 서로 다른 조언이 많아서 결정하기 어렵습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저 역시 IT 블로그(Oracle DBA &amp;middot; 서버 관리) 20편을 발행한 시점에 애드센스 신청을 진행했습니다. 이 글에서는 그 과정을 &lt;b&gt;2주 완성 로드맵&lt;/b&gt;으로 정리했습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;신청 전 반드시 준비해야 할 필수 페이지 3종&lt;/li&gt;
&lt;li&gt;Google Search Console 등록과 색인 요청&lt;/li&gt;
&lt;li&gt;Google Analytics 연동&lt;/li&gt;
&lt;li&gt;애드센스 신청 절차&lt;/li&gt;
&lt;li&gt;승인 후 광고 배치 최적화&lt;/li&gt;
&lt;li&gt;반려 시 재신청 전략&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히 &lt;b&gt;IT 전문 블로그는 CPC(광고 클릭 단가)가 높아서 일반 블로그보다 2~3배 유리&lt;/b&gt;합니다. 정확한 절차를 따르면 승인 확률이 매우 높습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;급하신 분은 &lt;b&gt;&lt;u&gt;최종 체크리스트&lt;/u&gt;&lt;/b&gt;부터 보세요.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;신청 전 준비 - 언제 신청해야 하나&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;애드센스 신청 최적 타이밍의 기준입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;항목 최소 기준 권장&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;발행 글 수&lt;/td&gt;
&lt;td&gt;10편&lt;/td&gt;
&lt;td&gt;&lt;b&gt;20편 이상&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;운영 기간&lt;/td&gt;
&lt;td&gt;1개월&lt;/td&gt;
&lt;td&gt;&lt;b&gt;3개월 이상&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;카테고리&lt;/td&gt;
&lt;td&gt;2개&lt;/td&gt;
&lt;td&gt;&lt;b&gt;3~4개&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;일 평균 방문자&lt;/td&gt;
&lt;td&gt;10명&lt;/td&gt;
&lt;td&gt;&lt;b&gt;50명 이상&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;필수 페이지&lt;/td&gt;
&lt;td&gt;없음&lt;/td&gt;
&lt;td&gt;&lt;b&gt;3개 필수&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;IT 블로그의 강점&lt;/b&gt;: CPC가 높아서 일반 블로그보다 트래픽 대비 승인이 빠릅니다. 20편 정도면 충분합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  전체 로드맵 (2주 완성)&lt;/h2&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;Week 1 (신청 준비):
  Day 1-2: 필수 페이지 작성 (Privacy Policy, About, Contact)
  Day 3-4: 티스토리 최적화 + 사이드바 정리
  Day 5-7: GSC + Google Analytics 등록 + 색인 요청

Week 2 (신청 및 승인 대기):
  Day 8: 애드센스 신청
  Day 9-14: 승인 대기 (IT 블로그 평균 3~7일)
  승인 후: 광고 배치 최적화
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Step 1: 필수 페이지 3종 작성 (Day 1-2)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이 3개가 없으면 거의 100% 반려됩니다.&lt;/b&gt; GDPR&amp;middot;CCPA 같은 개인정보 보호법 대응 때문에 필수입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;필수 페이지 1: Privacy Policy (개인정보처리방침)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;애드센스 심사관이 반드시 확인하는 페이지입니다. Google이 사용하는 쿠키에 대한 안내가 반드시 포함되어야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;포함해야 할 필수 내용:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;수집하는 정보의 종류 (접속 로그, 쿠키, 댓글 등)&lt;/li&gt;
&lt;li&gt;정보 수집 목적 (통계 분석, 광고 최적화)&lt;/li&gt;
&lt;li&gt;제3자 서비스 이용 (Google AdSense, Analytics 등)&lt;/li&gt;
&lt;li&gt;쿠키 사용 안내와 브라우저별 설정 방법&lt;/li&gt;
&lt;li&gt;방문자 권리 (열람, 삭제 요청)&lt;/li&gt;
&lt;li&gt;문의처&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;필수 페이지 2: About (블로그 소개)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&quot;이 사람이 정말 이 분야 전문가인가?&quot;&lt;/b&gt; 를 판단하는 페이지입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;포함해야 할 필수 내용:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;블로그가 다루는 주제와 카테고리&lt;/li&gt;
&lt;li&gt;운영자의 배경 (경력, 전문 분야)&lt;/li&gt;
&lt;li&gt;블로그 개설 이유&lt;/li&gt;
&lt;li&gt;글 작성 원칙&lt;/li&gt;
&lt;li&gt;FAQ (자주 묻는 질문)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;팁&lt;/b&gt;: 본인의 실무 경력을 구체적으로 명시하세요. &quot;15년 경력의 DBA&quot; 같은 문구가 신뢰도를 크게 올립니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;필수 페이지 3: Contact (문의처)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이메일 등 실제 연락 가능한 방법이 있어야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;포함해야 할 필수 내용:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이메일 주소 (실제 사용 가능한 것)&lt;/li&gt;
&lt;li&gt;문의 가능한 내용 범위&lt;/li&gt;
&lt;li&gt;응답 시간 안내&lt;/li&gt;
&lt;li&gt;사용하지 않는 문의 (스팸 거절 등)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;티스토리에 3개 페이지 배치하기&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;1. 새 글로 작성 (제목: &quot;개인정보처리방침&quot;, &quot;블로그 소개&quot;, &quot;문의하기&quot;)
2. 카테고리는 &quot;블로그 정보&quot; 같은 별도 카테고리 생성 후 등록
3. 티스토리 관리 &amp;rarr; 메뉴 &amp;rarr; 상단/하단 메뉴에 링크 추가
4. 또는 사이드바 위젯에 링크 추가
5. 실제 클릭해서 페이지가 열리는지 반드시 확인
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;중요&lt;/b&gt;: 사이드바나 하단 메뉴에서 &lt;b&gt;누구나 쉽게 클릭 가능&lt;/b&gt;해야 합니다. 숨겨진 페이지는 감지되지 않아서 반려됩니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Step 2: 블로그 최적화 (Day 3-4)&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;카테고리 구조 정리&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;방문자가 첫 3초에 &quot;이 블로그가 무엇을 다루는지&quot; 파악할 수 있어야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;권장 카테고리 구조 (2단계 이내):&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;  대분류 (3~5개)
   └──   소분류 (2~4개씩)
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;나쁜 예:&lt;/b&gt; 카테고리 없음 / 모든 글이 &quot;기타&quot;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;좋은 예:&lt;/b&gt; 명확한 대분류 + 관련 시리즈끼리 소분류로 묶기&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;시리즈 가이드 페이지 만들기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;블로그 첫 화면에 방문자가 원하는 글을 5초 안에 찾을 수 있게 하는 페이지입니다. &quot;공지&quot;로 설정해서 항상 상단에 노출합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;포함해야 할 내용:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;시리즈별 안내&lt;/li&gt;
&lt;li&gt;직무별 추천 읽기 경로&lt;/li&gt;
&lt;li&gt;검색 방법 안내&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;사이드바 정리&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;권장 구성 순서:&lt;/b&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;검색창 (최상단)&lt;/li&gt;
&lt;li&gt;카테고리 메뉴&lt;/li&gt;
&lt;li&gt;시리즈 가이드 링크&lt;/li&gt;
&lt;li&gt;인기 글 위젯&lt;/li&gt;
&lt;li&gt;최근 글&lt;/li&gt;
&lt;li&gt;Privacy Policy / About / Contact 링크&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;블로그 제목 옆 한 줄 소개&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;좋은 예:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&quot;15년차 전산관리자가 정리한 Oracle DBA 실무 노트&quot;&lt;/li&gt;
&lt;li&gt;&quot;운영 현장의 트러블슈팅과 자동화 가이드&quot;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;나쁜 예:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&quot;IT 블로그입니다&quot;&lt;/li&gt;
&lt;li&gt;&quot;코딩 일상&quot;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한 줄로 정체성을 명확히 하면 심사관과 방문자 모두에게 좋은 인상을 줍니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Step 3: Google Search Console (GSC) 등록 (Day 5-6)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;애드센스 신청과는 별개지만 &lt;b&gt;트래픽 데이터를 얻는 유일한 창구&lt;/b&gt;입니다. 반드시 병행하세요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;GSC 사이트 등록&lt;/h3&gt;
&lt;pre class=&quot;vim&quot;&gt;&lt;code&gt;1. https://search.google.com/search-console 접속
2. Google 계정으로 로그인
3. &quot;속성 추가&quot; 클릭
4. &quot;URL 접두어&quot; 선택 (도메인 방식보다 티스토리에서 쉬움)
5. 본인 블로그 URL 입력 (예: https://본인아이디.tistory.com/)
6. &quot;계속&quot; 클릭
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;소유권 확인 (HTML 태그 방식)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;티스토리에서는 HTML 태그 방식이 가장 쉽습니다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;1. GSC 확인 방법에서 &quot;HTML 태그&quot; 선택
2. 표시되는 &amp;lt;meta&amp;gt; 태그 복사
   예: &amp;lt;meta name=&quot;google-site-verification&quot; content=&quot;ABC123...&quot; /&amp;gt;
   
3. 티스토리 관리 &amp;rarr; 꾸미기 &amp;rarr; 스킨 편집 &amp;rarr; HTML 편집
4. &amp;lt;head&amp;gt; 태그 바로 아래에 붙여넣기
5. 저장
6. GSC로 돌아가서 &quot;확인&quot; 클릭
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;확인 실패 시 체크리스트:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&amp;lt;head&amp;gt; 태그 안에 정확히 들어갔는지&lt;/li&gt;
&lt;li&gt;스킨 저장 후 실제 반영되었는지 (F12로 소스 확인)&lt;/li&gt;
&lt;li&gt;캐시 문제라면 24시간 후 재시도&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;사이트맵 제출 (필수)&lt;/h3&gt;
&lt;pre class=&quot;crmsh&quot;&gt;&lt;code&gt;1. GSC 왼쪽 메뉴 &amp;rarr; &quot;Sitemaps&quot; 클릭
2. &quot;새 사이트맵 추가&quot;에 다음 입력:
   sitemap.xml
3. &quot;제출&quot; 클릭
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;티스토리는 자동으로 sitemap.xml을 생성해줍니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;색인 요청 (모든 글에 대해)&lt;/h3&gt;
&lt;pre class=&quot;lsl&quot;&gt;&lt;code&gt;1. GSC 왼쪽 메뉴 &amp;rarr; &quot;URL 검사&quot;
2. 검사창에 각 글의 URL 입력
3. &quot;색인 생성 요청&quot; 클릭
4. 발행한 모든 글에 대해 반복
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;팁&lt;/b&gt;: 하루에 10~15개씩 나눠서 요청하세요. 한 번에 너무 많이 요청하면 지연될 수 있습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Step 4: Google Analytics 연동 (Day 6, 선택이지만 강추)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;애드센스 필수는 아니지만 &lt;b&gt;트래픽 분석에 필수&lt;/b&gt;입니다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;1. https://analytics.google.com 접속
2. &quot;측정 시작&quot; &amp;rarr; 계정 만들기
3. 속성 만들기 &amp;rarr; 웹 &amp;rarr; 데이터 스트림 생성
4. 표시되는 측정 ID (G-XXXXXXX) 복사

5. 티스토리 관리 &amp;rarr; 꾸미기 &amp;rarr; 스킨 편집 &amp;rarr; HTML 편집
6.  태그 바로 아래에 gtag 코드 삽입
7. 측정 ID를 본인 값으로 교체
8. 저장
9. 24시간 후 애널리틱스에서 데이터 확인
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;애널리틱스가 있으면 &lt;b&gt;어떤 글이 트래픽 많은지, 어디서 유입되는지&lt;/b&gt; 데이터가 쌓입니다. 이 데이터가 광고 최적화의 기반이 됩니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Step 5: 신청 전 최종 체크리스트 (Day 7)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;애드센스 신청 직전에 하나씩 체크하세요.&lt;/p&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;[ ] 글 20편 이상 발행 완료
[ ] Privacy Policy 페이지 발행 및 링크 접근 가능
[ ] About 페이지 발행 및 링크 접근 가능
[ ] Contact 페이지 발행 및 링크 접근 가능
[ ] 3개 페이지 링크를 사이드바 또는 하단(footer)에 배치
[ ] 시리즈 가이드 페이지 발행 및 공지 설정
[ ] GSC 등록 및 사이트맵 제출 완료
[ ] 발행한 글 모두 색인 요청 완료
[ ] 블로그 제목 옆 한 줄 소개 등록
[ ] Google Analytics 연동 (선택)
[ ] Google 검색에서 본인 블로그가 나오는지 확인
    &amp;rarr; 검색어: site:본인블로그.tistory.com
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;모두 체크되면 신청&lt;/b&gt;하세요. 하나라도 빠지면 반려 확률이 급증합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Step 6: 애드센스 신청 (Day 8)&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;신청 절차&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;1. https://www.google.com/adsense/start/ 접속
2. Google 계정 로그인 (블로그와 동일 계정 사용 강권)

3. 사이트 URL 입력
   &amp;rarr; 예: https://sony-story.tistory.com/

4. 국가 선택: 대한민국

5. 결제 정보 입력
   &amp;rarr; 본인 실명, 주소, 전화번호
   &amp;rarr; 이름은 신분증과 100% 일치 (나중에 본인 인증 필요)

6. 광고 코드 받기
   &amp;rarr; HTML 코드 복사

7. 티스토리에 코드 삽입
   &amp;rarr; 관리 &amp;rarr; 꾸미기 &amp;rarr; 스킨 편집 &amp;rarr; HTML 편집
   &amp;rarr;  태그 바로 아래에 붙여넣기
   &amp;rarr; 저장

8. 애드센스로 돌아가 &quot;완료&quot; 클릭

9. 심사 요청 &amp;rarr; 대기
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;심사 기간 안내&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;블로그 유형 평균 승인 기간&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;IT 전문 블로그&lt;/td&gt;
&lt;td&gt;3~7일 (빠른 편)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;일반 정보 블로그&lt;/td&gt;
&lt;td&gt;1~2주&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;라이프 스타일&lt;/td&gt;
&lt;td&gt;2~3주&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;최대 대기&lt;/td&gt;
&lt;td&gt;4주까지 가능&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결과는 등록한 이메일로 통보됩니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;심사 중 절대 하지 말아야 할 것&lt;/h3&gt;
&lt;pre class=&quot;gcode&quot;&gt;&lt;code&gt;❌ 광고 코드를 반복해서 삭제/재설치
❌ 블로그 URL 변경
❌ 콘텐츠 대량 삭제
❌ 애드센스 정책 위반 콘텐츠 게시
❌ 클릭 유도 (본인 클릭, 지인 클릭 요청)
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;심사 중에는 &lt;b&gt;평소처럼 정상 운영&lt;/b&gt;하시면 됩니다. 새 글을 계속 올리는 건 오히려 좋은 신호입니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;승인 후 광고 배치 최적화&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;승인되면 광고를 어디에 어떻게 배치할지가 수익을 결정합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;IT 블로그 최적 광고 배치&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;┌──────────────────────────────┐
│  블로그 헤더                 │
├──────────────────────────────┤
│  글 제목                     │
│                              │
│  도입부 (2~3문단)            │
│                              │
│  [  광고 #1 - 인아티클]     │ &amp;larr; 이탈률 낮은 위치
│                              │
│  본문 (주요 내용)            │
│  ...                         │
│                              │
│  [  광고 #2 - 인아티클]     │ &amp;larr; 중간 광고
│                              │
│  본문 계속                   │
│  마무리                      │
│                              │
│  [  광고 #3 - 하단 배너]    │ &amp;larr; 마지막 배너
│                              │
│  관련 글 / 댓글              │
└──────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;권장 광고 개수와 원칙&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;글 1편당 최대 3개&lt;/b&gt; (더 많으면 이탈률 급증)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;첫 광고는 스크롤 후에&lt;/b&gt; (도입부 다음, 본문 진입 지점)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;모바일 우선 고려&lt;/b&gt; (트래픽 60~70%가 모바일)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;자동 광고 vs 수동 광고&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;방식 장점 단점&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;자동 광고&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;설정 간편, Google 최적화&lt;/td&gt;
&lt;td&gt;위치 통제 어려움&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;수동 광고&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;정밀 위치 통제&lt;/td&gt;
&lt;td&gt;관리 번거로움&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;추천 전략&lt;/b&gt;: 처음 3개월은 &lt;b&gt;자동 광고&lt;/b&gt;로 운영하면서 데이터를 쌓고, 이후 &lt;b&gt;수동 광고&lt;/b&gt;로 전환.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;예상 수익 - IT 블로그 기준&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CPC가 높은 IT 트러블슈팅 블로그의 현실적 수익입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일 방문자 예상 월 수익 (원)&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;100명&lt;/td&gt;
&lt;td&gt;10,000 ~ 30,000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;300명&lt;/td&gt;
&lt;td&gt;30,000 ~ 100,000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1,000명&lt;/td&gt;
&lt;td&gt;100,000 ~ 300,000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3,000명&lt;/td&gt;
&lt;td&gt;300,000 ~ 1,000,000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10,000명&lt;/td&gt;
&lt;td&gt;1,000,000 ~ 3,000,000&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;IT 전문 콘텐츠의 강점&lt;/b&gt;: 클릭 단가가 일반 블로그의 2~3배. 트러블슈팅 콘텐츠는 절박한 사용자가 유입되어 광고 클릭률도 높습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;주의&lt;/b&gt;: 위 수치는 참고용이며 실제 수익은 콘텐츠, 트래픽 소스, 계절, 광고 시장 상황에 따라 크게(많이) 다를 수 있습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;★ 자주 발생하는 반려 사유 5가지&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;반려 사유 1: &quot;가치가 없는 콘텐츠&quot;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;원인&lt;/b&gt;: 글이 너무 짧거나(500자 미만), 다른 사이트 복사, AI 생성 티가 강함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;해결&lt;/b&gt;:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;본인의 실무 경험 한 줄 이상 추가&lt;/li&gt;
&lt;li&gt;스크린샷과 실제 코드 예시 포함&lt;/li&gt;
&lt;li&gt;본인만의 인사이트나 함정 사례 명시&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;반려 사유 2: &quot;탐색이 어려움&quot;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;원인&lt;/b&gt;: 카테고리 구조 없음, 사이드바 정리 안 됨, 시리즈 안내 없음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;해결&lt;/b&gt;:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;카테고리 3개 이상 명확히 구성&lt;/li&gt;
&lt;li&gt;시리즈 가이드 페이지 발행 및 공지 설정&lt;/li&gt;
&lt;li&gt;인기 글 위젯, 검색창 사이드바에 배치&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;반려 사유 3: &quot;필수 페이지 부재&quot;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;원인&lt;/b&gt;: Privacy Policy, About, Contact 중 하나라도 빠짐 또는 접근 불가&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;해결&lt;/b&gt;:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;3개 페이지 모두 발행&lt;/li&gt;
&lt;li&gt;사이드바나 하단 메뉴에서 클릭 가능하게 배치&lt;/li&gt;
&lt;li&gt;실제 클릭 테스트로 접근성 확인&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;반려 사유 4: &quot;정책 위반 콘텐츠&quot;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;원인&lt;/b&gt;: 저작권 위반 이미지, 다른 블로그 복붙, 폭력/성인 콘텐츠&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;해결&lt;/b&gt;:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이미지는 본인 캡처 또는 Unsplash 등 무료 이미지만 사용&lt;/li&gt;
&lt;li&gt;다른 사이트 콘텐츠 인용 시 출처 명시&lt;/li&gt;
&lt;li&gt;문제 되는 콘텐츠 삭제&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;반려 사유 5: &quot;구글 정책 위반&quot;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;원인&lt;/b&gt;: 클릭 유도 문구, 광고 위치 잘못, 자동 클릭 봇&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;해결&lt;/b&gt;:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&quot;광고를 클릭해주세요&quot; 같은 문구 절대 금지&lt;/li&gt;
&lt;li&gt;광고를 콘텐츠와 명확히 구분&lt;/li&gt;
&lt;li&gt;본인이나 지인 클릭 요청 금지&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;반려 시 재신청 전략&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반려되어도 당황하지 마세요. IT 블로그는 재신청 승인률이 매우 높습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;재신청 절차&lt;/h3&gt;
&lt;pre class=&quot;lsl&quot;&gt;&lt;code&gt;1. 반려 이메일에 명시된 사유 정확히 파악
2. 해당 사유 개선 (콘텐츠 보강, 페이지 추가 등)
3. 개선 후 최소 2주 대기 (즉시 재신청 시 자동 반려)
4. 애드센스 관리 &amp;rarr; &quot;재검토 요청&quot; 클릭
5. 개선 사항 상세히 기재 (500자 이상 권장)
6. 재심사 대기
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;재신청 시 개선 기록 작성 팁&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;나쁜 예:&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;1c&quot;&gt;&lt;code&gt;&quot;모든 것을 개선했습니다.&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;좋은 예:&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;1) Privacy Policy 페이지 추가 (사이드바에서 접근 가능)
2) 카테고리 구조를 4개 대분류 + 6개 소분류로 재편
3) 짧은 글 5편 삭제, 대신 심층 분석 글 3편 추가
4) 시리즈 가이드 페이지 신설 및 공지 설정
5) 모든 이미지를 본인 촬영 또는 무료 라이선스로 교체
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구체적이고 측정 가능한 개선 사항 나열이 핵심입니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;승인 후 30일 로드맵&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Week 1: 자동 광고 활성화&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;자동 광고 기능 ON&lt;/li&gt;
&lt;li&gt;광고 개수 3~4개로 제한&lt;/li&gt;
&lt;li&gt;하루 3~5회 트래픽과 수익 확인&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Week 2~3: 데이터 수집&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;어떤 글에 트래픽이 많은지 파악&lt;/li&gt;
&lt;li&gt;어떤 광고 위치의 CTR(클릭률)이 높은지 분석&lt;/li&gt;
&lt;li&gt;이탈률 높은 위치 파악&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Week 4: 최적화&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;자동 광고 &amp;rarr; 수동 광고 전환 검토&lt;/li&gt;
&lt;li&gt;인기 글에 광고 위치 조정&lt;/li&gt;
&lt;li&gt;첫 수익 정산 확인 (100달러 이상 시 지급)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;승인률을 100%로 만드는 5가지 팁&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 3개 필수 페이지가 진짜로 접근 가능한지 확인&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사이드바 링크 클릭 &amp;rarr; 실제로 페이지가 열리는지 반드시 테스트하세요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. 시리즈 가이드가 공지로 첫 화면에 보이는지&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;방문자가 첫 3초에 &quot;전문 블로그&quot; 인상을 받아야 합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. 사이드바가 정리되어 있는지&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;카테고리, 인기 글, 검색창이 명확한 위치에 있어야 합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4. 발행한 글이 검색으로 찾아지는지&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구글에서 site:본인블로그.tistory.com으로 검색해서 결과가 나와야 합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5. 프로필과 소개가 채워져 있는지&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;운영자가 &quot;누구인지&quot; 알 수 있어야 신뢰도가 높아집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 5가지가 완벽하면 &lt;b&gt;IT 전문 블로그는 거의 100% 승인&lt;/b&gt;됩니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;마무리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;애드센스 승인은 블로그 수익화의 시작점이지만, &lt;b&gt;정말 중요한 것은 승인 이후&lt;/b&gt;입니다. 광고 수익은 결국 &lt;b&gt;트래픽 &amp;times; CPC &amp;times; CTR&lt;/b&gt;의 함수입니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;트래픽&lt;/b&gt;: 꾸준한 글 발행과 SEO 최적화&lt;/li&gt;
&lt;li&gt;&lt;b&gt;CPC&lt;/b&gt;: 콘텐츠 분야 (IT 트러블슈팅은 유리)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;CTR&lt;/b&gt;: 광고 위치 최적화&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 세 가지를 6개월~1년 꾸준히 개선하면 부수입 파이프라인이 자연스럽게 만들어집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;승인 자체는 IT 블로그의 경우 상대적으로 쉽습니다. 이 글의 로드맵대로 준비하고 신청하시면 큰 무리 없이 통과하실 수 있을 것입니다. 저 역시 이 절차대로 진행했고 예상보다 빠르게 승인받았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;혹시 신청 과정에서 막히는 부분이 있거나, 반려 사유가 애매하시다면 댓글로 공유해주세요. 함께 해결책을 찾아보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;승인후 가장 많이 하는실수&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;광고수익을 높이겠다고 욕심을 내어 본인(친구)이 잦은 광고 클릭하는 경우가 많습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로그램에 의해 모두 모니터링되어 승인 계정이 잠겨 사용 할 수 없게 됩니다. (기본 1개월 ~ 3개월)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>수익창출/에드센스(AdSense)</category>
      <category>Google AdSense 신청방법</category>
      <category>GSC 등록방법</category>
      <category>블로그 광고배치</category>
      <category>소니스토리</category>
      <category>애드센스 반려 사유</category>
      <category>애드센스 수익계산</category>
      <category>티스토리 개인정보처리방침</category>
      <category>티스토리 수익화</category>
      <category>티스토리 애드센스 신청</category>
      <category>티스토리 에드센스 승인</category>
      <author>isony</author>
      <guid isPermaLink="true">https://isony.tistory.com/345</guid>
      <comments>https://isony.tistory.com/entry/%EB%B8%94%EB%A1%9C%EA%B7%B8-%EC%9A%B4%EC%98%81-%ED%8B%B0%EC%8A%A4%ED%86%A0%EB%A6%AC-%EC%95%A0%EB%93%9C%EC%84%BC%EC%8A%A4-%EC%8B%A0%EC%B2%AD%EB%B6%80%ED%84%B0-GSC-%EB%93%B1%EB%A1%9D%EA%B9%8C%EC%A7%80-2%EC%A3%BC-%EC%99%84%EC%84%B1-%EA%B0%80%EC%9D%B4%EB%93%9C-IT-%EB%B8%94%EB%A1%9C%EA%B7%B8-%EA%B8%B0%EC%A4%80#entry345comment</comments>
      <pubDate>Fri, 3 Jul 2026 07:11:05 +0900</pubDate>
    </item>
    <item>
      <title>[오라클 운영] RMAN 백업과 복구 완벽 가이드 - 운영 환경 표준 패턴부터 5가지 복구 시나리오까지</title>
      <link>https://isony.tistory.com/entry/%EC%98%A4%EB%9D%BC%ED%81%B4-%EC%9A%B4%EC%98%81-RMAN-%EB%B0%B1%EC%97%85%EA%B3%BC-%EB%B3%B5%EA%B5%AC-%EC%99%84%EB%B2%BD-%EA%B0%80%EC%9D%B4%EB%93%9C-%EC%9A%B4%EC%98%81-%ED%99%98%EA%B2%BD-%ED%91%9C%EC%A4%80-%ED%8C%A8%ED%84%B4%EB%B6%80%ED%84%B0-5%EA%B0%80%EC%A7%80-%EB%B3%B5%EA%B5%AC-%EC%8B%9C%EB%82%98%EB%A6%AC%EC%98%A4%EA%B9%8C%EC%A7%80</link>
      <description>&lt;h1&gt;[오라클 운영] RMAN 백업과 복구 완벽 가이드 - 운영 환경 표준 패턴부터 5가지 복구 시나리오까지&lt;/h1&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;테스트 환경&lt;/b&gt;: Oracle 19c / 21c, Oracle Linux 8&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DBA가 가장 두려워하는 순간이 있습니다. &lt;b&gt;&quot;DB가 안 올라옵니다.&quot;&lt;/b&gt; 운영팀에서 새벽 4시에 전화가 옵니다. 데이터 손상, 디스크 장애, 컨트롤 파일 손실. 이때 DBA의 진짜 실력은 평소 백업이 얼마나 잘 되어 있느냐로 결정됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오라클은 RMAN(Recovery Manager)이라는 표준 백업 도구를 제공합니다. 그런데 한국어 자료는 대부분 &lt;b&gt;&quot;RMAN으로 백업하는 법&quot;&lt;/b&gt; 까지만 다루고, &lt;b&gt;&quot;운영 환경에서 어떻게 표준화하고 어떻게 복구하는가&quot;&lt;/b&gt; 는 산발적입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글에서는 다음을 종합 정리했습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;RMAN의 본질과 다른 백업과의 차이&lt;/li&gt;
&lt;li&gt;운영 환경 표준 백업 전략 (Level 0 + Level 1)&lt;/li&gt;
&lt;li&gt;자동화 가능한 실전 스크립트&lt;/li&gt;
&lt;li&gt;&lt;b&gt;★ 5가지 복구 시나리오&lt;/b&gt; (전체, 시점, 테이블스페이스, 컨트롤 파일, PDB)&lt;/li&gt;
&lt;li&gt;자주 발생하는 함정과 트러블슈팅&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;장애 대응 중이라면 &lt;u&gt;긴급 복구 시나리오&lt;/u&gt;부터 보세요. 본 글은 &lt;u&gt;CDB/PDB 운영 가이드&lt;/u&gt;의 보완편 성격도 갖습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;RMAN이란 무엇인가&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;RMAN은 오라클이 제공하는 &lt;b&gt;데이터베이스 전용 백업/복구 도구&lt;/b&gt;입니다. OS 레벨 파일 복사와는 본질적으로 다릅니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;OS 백업 vs RMAN 백업&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;항목 OS 백업 (cp, tar) RMAN 백업&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;백업 방식&lt;/td&gt;
&lt;td&gt;파일 통째 복사&lt;/td&gt;
&lt;td&gt;블록 단위 인식&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;핫 백업&lt;/td&gt;
&lt;td&gt;ALTER TABLESPACE BEGIN BACKUP 필요&lt;/td&gt;
&lt;td&gt;별도 작업 불필요&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;증분 백업&lt;/td&gt;
&lt;td&gt;❌ 불가&lt;/td&gt;
&lt;td&gt;✅ 가능 (변경 블록만)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;손상 감지&lt;/td&gt;
&lt;td&gt;❌ 불가&lt;/td&gt;
&lt;td&gt;✅ 자동 (block checksum)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;압축&lt;/td&gt;
&lt;td&gt;OS 도구 필요&lt;/td&gt;
&lt;td&gt;✅ 내장&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;복구 자동화&lt;/td&gt;
&lt;td&gt;수동&lt;/td&gt;
&lt;td&gt;✅ 자동 (Archive Log 적용)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;운영 표준&lt;/td&gt;
&lt;td&gt;비권장&lt;/td&gt;
&lt;td&gt;&lt;b&gt;권장&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;운영 환경에서는 RMAN이 사실상 유일한 표준&lt;/b&gt;입니다. OS 백업은 RMAN 백업의 보조 수단으로만 사용하세요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;RMAN의 핵심 객체 3가지&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체 역할&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;백업 셋(Backup Set)&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;RMAN 전용 형식의 백업 파일 (압축, 효율적)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;이미지 카피(Image Copy)&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;데이터파일 1:1 복사본 (OS 파일과 동일 형식)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;컨트롤 파일 자동 백업&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;데이터베이스 메타데이터 (필수)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대부분의 운영 환경에서는 백업 셋 + 컨트롤 파일 자동 백업 조합을 표준으로 사용합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;★ 첫 RMAN 설정 - 운영 표준 CONFIGURE&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;RMAN의 강력함은 &lt;b&gt;CONFIGURE 명령으로 영구 설정&lt;/b&gt;할 수 있다는 점입니다. 한 번 설정하면 매번 다시 지정할 필요가 없습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;권장 표준 설정&lt;/h3&gt;
&lt;pre class=&quot;cmake&quot;&gt;&lt;code&gt;# RMAN 접속
rman target /
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;# 1) 컨트롤 파일 자동 백업 ★ 필수
RMAN&amp;gt; CONFIGURE CONTROLFILE AUTOBACKUP ON;

# 2) 보존 정책 - 7일 복구 윈도우
RMAN&amp;gt; CONFIGURE RETENTION POLICY TO RECOVERY WINDOW OF 7 DAYS;

# 3) 백업 셋 자동 압축
RMAN&amp;gt; CONFIGURE COMPRESSION ALGORITHM 'MEDIUM';

# 4) 백업 옵션 - 압축 백업 셋 기본
RMAN&amp;gt; CONFIGURE DEVICE TYPE DISK PARALLELISM 4 BACKUP TYPE TO COMPRESSED BACKUPSET;

# 5) 백업 위치 - FRA 또는 별도 디스크
RMAN&amp;gt; CONFIGURE CHANNEL DEVICE TYPE DISK FORMAT '/backup/rman/%U';

# 6) 손상 블록 처리
RMAN&amp;gt; CONFIGURE MAXSETSIZE TO UNLIMITED;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;현재 설정 확인&lt;/h3&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;RMAN&amp;gt; SHOW ALL;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 표준 설정만 해두면 백업 명령이 단순해집니다.&lt;/p&gt;
&lt;pre class=&quot;abnf&quot;&gt;&lt;code&gt;RMAN&amp;gt; BACKUP DATABASE PLUS ARCHIVELOG;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 한 줄이 압축 + 병렬 + 자동 컨트롤 파일 백업 + 위치 지정까지 모두 포함합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;★ 운영 표준 백업 전략 - Level 0 + Level 1&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;운영 환경에서 가장 검증된 패턴입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;백업 일정 표준&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;일요일 새벽 2시:  Level 0 (전체 백업, 약 1~3시간)
월~토 새벽 2시:   Level 1 (증분 백업, 약 10~30분)
매시간:            ARCHIVELOG 백업
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Level 0 - 일요일 전체 백업 스크립트&lt;/h3&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;#!/bin/bash
# /home/oracle/scripts/rman_level0.sh

export ORACLE_HOME=/u01/app/oracle/product/19c/dbhome_1
export ORACLE_SID=PRODDB
export PATH=$ORACLE_HOME/bin:$PATH

LOG=/var/log/rman/level0_$(date +%Y%m%d).log

rman target / log=$LOG &amp;lt;&amp;lt; EOF
RUN {
    CROSSCHECK BACKUP;
    CROSSCHECK ARCHIVELOG ALL;
    
    BACKUP AS COMPRESSED BACKUPSET 
        INCREMENTAL LEVEL 0 
        DATABASE 
        TAG 'WEEKLY_L0';
    
    BACKUP ARCHIVELOG ALL 
        DELETE INPUT 
        TAG 'WEEKLY_L0_ARC';
    
    DELETE NOPROMPT OBSOLETE;
    DELETE NOPROMPT EXPIRED BACKUP;
}
EXIT;
EOF
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Level 1 - 평일 증분 백업 스크립트&lt;/h3&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;#!/bin/bash
# /home/oracle/scripts/rman_level1.sh

export ORACLE_HOME=/u01/app/oracle/product/19c/dbhome_1
export ORACLE_SID=PRODDB
export PATH=$ORACLE_HOME/bin:$PATH

LOG=/var/log/rman/level1_$(date +%Y%m%d).log

rman target / log=$LOG &amp;lt;&amp;lt; EOF
RUN {
    CROSSCHECK BACKUP;
    
    BACKUP AS COMPRESSED BACKUPSET 
        INCREMENTAL LEVEL 1 
        DATABASE 
        TAG 'DAILY_L1';
    
    BACKUP ARCHIVELOG ALL 
        DELETE INPUT 
        TAG 'DAILY_L1_ARC';
    
    DELETE NOPROMPT OBSOLETE;
}
EXIT;
EOF
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;cron 등록&lt;/h3&gt;
&lt;pre class=&quot;dts&quot;&gt;&lt;code&gt;# crontab -e (oracle 사용자)
0 2 * * 0   /home/oracle/scripts/rman_level0.sh &amp;gt; /var/log/rman/level0.log 2&amp;gt;&amp;amp;1
0 2 * * 1-6 /home/oracle/scripts/rman_level1.sh &amp;gt; /var/log/rman/level1.log 2&amp;gt;&amp;amp;1
0 * * * *   /home/oracle/scripts/rman_arclog.sh &amp;gt; /var/log/rman/arclog.log 2&amp;gt;&amp;amp;1
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Differential vs Cumulative Level 1 - 어떤 걸 쓸까&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Level 1 증분 백업은 두 가지 방식이 있고, 트레이드오프가 명확합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;항목 DIFFERENTIAL (기본) CUMULATIVE&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;대상&lt;/td&gt;
&lt;td&gt;가장 최근 Level 0 또는 Level 1 이후 변경분&lt;/td&gt;
&lt;td&gt;&lt;b&gt;가장 최근 Level 0 이후&lt;/b&gt; 변경분&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;백업 크기&lt;/td&gt;
&lt;td&gt;작음&lt;/td&gt;
&lt;td&gt;점진적 증가&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;복구 시 적용&lt;/td&gt;
&lt;td&gt;모든 Level 1 차례로&lt;/td&gt;
&lt;td&gt;마지막 Level 1 하나만&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;복구 속도&lt;/td&gt;
&lt;td&gt;느림&lt;/td&gt;
&lt;td&gt;빠름&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;운영 권장&lt;/td&gt;
&lt;td&gt;백업 시간 최적화 시&lt;/td&gt;
&lt;td&gt;&lt;b&gt;복구 시간 최적화 시&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;명령어 차이&lt;/h3&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;# Differential (기본값)
BACKUP INCREMENTAL LEVEL 1 DATABASE;

# Cumulative (명시)
BACKUP INCREMENTAL LEVEL 1 CUMULATIVE DATABASE;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;선택 가이드&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;OLTP 운영 (24/7 가용성 중시)&lt;/b&gt; &amp;rarr; CUMULATIVE&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;복구 시간 단축이 가장 중요&lt;/li&gt;
&lt;li&gt;백업 디스크는 충분히 확보&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;대용량 DW (백업 윈도우 짧음)&lt;/b&gt; &amp;rarr; DIFFERENTIAL&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;백업 시간이 더 중요&lt;/li&gt;
&lt;li&gt;복구는 자주 발생하지 않음&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Block Change Tracking 활성화 (필수)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Level 1 백업 속도를 5~10배 향상시키는 옵션입니다. 운영 환경이라면 무조건 켜세요.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;SQL&amp;gt; ALTER DATABASE ENABLE BLOCK CHANGE TRACKING
     USING FILE '/u01/oradata/bct/bct.log' REUSE;

-- 활성화 확인
SELECT * FROM v$block_change_tracking;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;BCT는 변경된 블록을 비트맵으로 추적해서 Level 1 백업 시 전체 데이터파일을 스캔할 필요가 없게 합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Retention Policy - Recovery Window vs Redundancy&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;RMAN은 어떤 백업을 &quot;필요 없는 백업(obsolete)&quot;으로 판단할지 두 가지 방식을 지원합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;방식 의미 시나리오&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;RECOVERY WINDOW&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;시점 기반: &quot;N일 전까지 복구 가능하도록 보존&quot;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;PITR이 중요한 운영 환경 (권장)&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;REDUNDANCY&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;개수 기반: &quot;최근 N개 백업 보존&quot;&lt;/td&gt;
&lt;td&gt;하드웨어 다중성만 중요한 환경&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;설정 예시&lt;/h3&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;# 7일 복구 윈도우 (권장)
RMAN&amp;gt; CONFIGURE RETENTION POLICY TO RECOVERY WINDOW OF 7 DAYS;

# 또는 3개 백업 보존
RMAN&amp;gt; CONFIGURE RETENTION POLICY TO REDUNDANCY 3;

# 또는 정책 비활성 (모든 백업 보존, 권장하지 않음)
RMAN&amp;gt; CONFIGURE RETENTION POLICY TO NONE;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;OBSOLETE vs EXPIRED - 헷갈리지 말 것 ★&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상태 의미 발견 방법&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;OBSOLETE&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;정책상 불필요 (파일은 존재)&lt;/td&gt;
&lt;td&gt;REPORT OBSOLETE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;EXPIRED&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;파일이 실제로 없음 (RMAN 카탈로그에는 등록)&lt;/td&gt;
&lt;td&gt;CROSSCHECK BACKUP 후 발견&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;pre class=&quot;mipsasm&quot;&gt;&lt;code&gt;# 불필요 백업 식별
RMAN&amp;gt; REPORT OBSOLETE;

# 불필요 백업 삭제
RMAN&amp;gt; DELETE NOPROMPT OBSOLETE;

# 카탈로그와 실제 파일 동기화
RMAN&amp;gt; CROSSCHECK BACKUP;

# 카탈로그에 있는데 실제 파일 없는 것 정리
RMAN&amp;gt; DELETE NOPROMPT EXPIRED BACKUP;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;운영 스크립트에는 두 정리 명령을 모두 포함&lt;/b&gt;시키세요.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;19c 환경 주의사항&lt;/b&gt;: Oracle 19c 2023.01 CPU 이후 일부 환경에서 retention policy 동작이 미묘하게 변경되었습니다. 패치 적용 후엔 반드시 REPORT OBSOLETE로 동작을 확인하세요.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;★ 5가지 복구 시나리오&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;장애 발생 시 가장 중요한 부분입니다. 시나리오별 정확한 절차를 정리했습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;시나리오 1: 전체 데이터베이스 복구 (Complete Recovery)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DB 전체가 손상되어 모든 데이터파일 복구가 필요한 경우입니다.&lt;/p&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;# 1) DB를 MOUNT 상태로
sqlplus / as sysdba
SQL&amp;gt; STARTUP MOUNT;

# 2) RMAN 접속해서 복구
rman target /

RMAN&amp;gt; RESTORE DATABASE;
RMAN&amp;gt; RECOVER DATABASE;

# 3) DB OPEN
SQL&amp;gt; ALTER DATABASE OPEN;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3개 명령으로 전체 복구가 완료됩니다. &lt;b&gt;이게 RMAN의 진짜 위력&lt;/b&gt;입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;시나리오 2: 특정 시점 복구 (PITR - Point-In-Time Recovery)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;어제 오후 3시 상태로 되돌려 주세요&quot; 같은 경우입니다. 운영 사고 대응에 필수입니다.&lt;/p&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;sqlplus / as sysdba
SQL&amp;gt; STARTUP MOUNT;
SQL&amp;gt; EXIT;

rman target /

RMAN&amp;gt; RUN {
    SET UNTIL TIME &quot;TO_DATE('2026-05-28 15:00:00', 'YYYY-MM-DD HH24:MI:SS')&quot;;
    RESTORE DATABASE;
    RECOVER DATABASE;
}

# OPEN RESETLOGS (PITR 후 필수)
SQL&amp;gt; ALTER DATABASE OPEN RESETLOGS;
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;중요&lt;/b&gt;: PITR 후엔 반드시 즉시 &lt;b&gt;새 Level 0 백업&lt;/b&gt;을 받으세요. RESETLOGS 이후엔 이전 백업으로 복구할 수 없습니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;시나리오 3: 단일 테이블스페이스 복구&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특정 테이블스페이스만 손상된 경우, 전체 DB를 멈추지 않고 복구 가능합니다.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;# 1) 테이블스페이스 오프라인
sqlplus / as sysdba
SQL&amp;gt; ALTER TABLESPACE users OFFLINE IMMEDIATE;

# 2) RMAN으로 해당 테이블스페이스만 복구
rman target /

RMAN&amp;gt; RESTORE TABLESPACE users;
RMAN&amp;gt; RECOVER TABLESPACE users;

# 3) 다시 온라인
SQL&amp;gt; ALTER TABLESPACE users ONLINE;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;다른 사용자는 정상 서비스를 받으면서&lt;/b&gt; 특정 테이블스페이스만 복구할 수 있다는 게 RMAN의 큰 장점입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;시나리오 4: 컨트롤 파일 손실 복구&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 까다로운 시나리오입니다. 컨트롤 파일 자동 백업 설정이 이때 빛을 발합니다.&lt;/p&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;# 1) DB 중지
sqlplus / as sysdba
SQL&amp;gt; SHUTDOWN ABORT;

# 2) NOMOUNT 상태로 시작
SQL&amp;gt; STARTUP NOMOUNT;

# 3) RMAN으로 컨트롤 파일 복구
rman target /

# 자동 백업에서 가장 최근 컨트롤 파일 복구
RMAN&amp;gt; RESTORE CONTROLFILE FROM AUTOBACKUP;

# 4) MOUNT
SQL&amp;gt; ALTER DATABASE MOUNT;

# 5) 데이터베이스 복구
RMAN&amp;gt; RECOVER DATABASE;

# 6) RESETLOGS로 OPEN
SQL&amp;gt; ALTER DATABASE OPEN RESETLOGS;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CONFIGURE CONTROLFILE AUTOBACKUP ON을 안 해뒀다면 이 시나리오에서 복구가 매우 어려워집니다. &lt;b&gt;반드시 켜두세요.&lt;/b&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;★ 시나리오 5: PDB 단위 복구 (12c+)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;CDB/PDB 운영 가이드&lt;/u&gt;에서 다룬 멀티테넌트 환경의 특수 시나리오입니다.&lt;/p&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;# 1) 특정 PDB만 CLOSE
sqlplus / as sysdba
SQL&amp;gt; ALTER PLUGGABLE DATABASE testpdb CLOSE IMMEDIATE;

# 2) RMAN으로 PDB만 복구
rman target /

RMAN&amp;gt; RESTORE PLUGGABLE DATABASE testpdb;
RMAN&amp;gt; RECOVER PLUGGABLE DATABASE testpdb;

# 3) PDB OPEN
SQL&amp;gt; ALTER PLUGGABLE DATABASE testpdb OPEN;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;다른 PDB는 정상 가동하면서&lt;/b&gt; 한 PDB만 복구합니다. 이게 멀티테넌트 환경의 강력함입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;PDB 단위 백업 (위와 짝)&lt;/h3&gt;
&lt;pre class=&quot;armasm&quot;&gt;&lt;code&gt;RMAN&amp;gt; BACKUP PLUGGABLE DATABASE prodpdb;
RMAN&amp;gt; BACKUP PLUGGABLE DATABASE prodpdb, testpdb;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PDB 단위 백업/복구 정책을 분리해 두면 운영 유연성이 크게 올라갑니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;백업 검증 - 정기 확인 필수 ★&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;백업이 있다&quot;와 &quot;백업이 복구 가능하다&quot;는 다릅니다. &lt;b&gt;백업 검증은 백업만큼 중요&lt;/b&gt;합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;정기 검증 명령&lt;/h3&gt;
&lt;pre class=&quot;shell&quot;&gt;&lt;code&gt;# 백업 파일 존재 여부 확인
RMAN&amp;gt; CROSSCHECK BACKUP;

# 가장 강력한 검증: 가상 복구 시뮬레이션
RMAN&amp;gt; RESTORE DATABASE VALIDATE;

# 특정 백업 검증
RMAN&amp;gt; VALIDATE BACKUPSET 12345;

# 데이터파일 손상 블록 검사
RMAN&amp;gt; VALIDATE DATABASE;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;권장 검증 일정&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;빈도 명령 목적&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;일일&lt;/td&gt;
&lt;td&gt;CROSSCHECK BACKUP&lt;/td&gt;
&lt;td&gt;파일 존재 확인&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;주간&lt;/td&gt;
&lt;td&gt;RESTORE DATABASE VALIDATE&lt;/td&gt;
&lt;td&gt;복구 가능 검증&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;월간&lt;/td&gt;
&lt;td&gt;별도 서버에 &lt;b&gt;실제 복구 테스트&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;진짜 확신&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;월간 실제 복구 테스트&lt;/b&gt;가 운영 환경의 진짜 안전장치입니다. 시뮬레이션과 실제는 다르고, 테스트를 안 하면 정말 필요한 순간에 못 합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;백업 상태 확인 쿼리&lt;/h3&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- 최근 백업 이력
SELECT session_recid, input_type, status,
       TO_CHAR(start_time, 'YYYY-MM-DD HH24:MI') AS start_at,
       elapsed_seconds / 60 AS elapsed_min,
       ROUND(input_bytes/1024/1024/1024, 2) AS input_gb,
       ROUND(output_bytes/1024/1024/1024, 2) AS output_gb
FROM   v$rman_backup_job_details
WHERE  start_time &amp;gt; SYSDATE - 7
ORDER  BY start_time DESC;

-- 마지막 성공 백업 시각
SELECT input_type,
       MAX(end_time) AS last_success
FROM   v$rman_backup_job_details
WHERE  status = 'COMPLETED'
GROUP  BY input_type;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;운영 모니터링 대시보드에 두 쿼리를 자동 표시하면 백업 상태를 한눈에 파악할 수 있습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;자주 발생하는 트러블슈팅 5가지&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;함정 1: ORA-19809 - FRA 공간 부족&lt;/h3&gt;
&lt;pre class=&quot;livecodeserver&quot;&gt;&lt;code&gt;ORA-19809: limit exceeded for recovery files
ORA-19804: cannot reclaim NN bytes disk space from MM limit
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원인: Fast Recovery Area(FRA)에 백업/archive log가 가득 참.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해결:&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;-- 현재 사용량 확인
SELECT * FROM v$recovery_area_usage;

-- FRA 크기 확장
ALTER SYSTEM SET db_recovery_file_dest_size = 100G SCOPE=BOTH;

-- 또는 정리
RMAN&amp;gt; DELETE NOPROMPT OBSOLETE;
RMAN&amp;gt; DELETE NOPROMPT EXPIRED BACKUP;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;함정 2: archive log 디스크 가득참 &amp;rarr; DB 멈춤&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;archive log 백업과 정리가 안 되면 archive 디스크가 가득 차서 모든 트랜잭션이 중단됩니다.&lt;/p&gt;
&lt;pre class=&quot;vala&quot;&gt;&lt;code&gt;# 응급: archive 백업 후 삭제
RMAN&amp;gt; BACKUP ARCHIVELOG ALL DELETE INPUT;

# 절대 금지: rm으로 archive 직접 삭제
# &amp;rarr; RMAN 카탈로그 불일치 발생
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;리눅스 디스크 부족 가이드&lt;/u&gt;에서 다룬 케이스와 직접 연결됩니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;함정 3: 컨트롤 파일 자동 백업 비활성화&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CONFIGURE CONTROLFILE AUTOBACKUP OFF로 되어 있으면 컨트롤 파일 손실 시 복구 매우 어려워집니다. 반드시 ON.&lt;/p&gt;
&lt;pre class=&quot;abnf&quot;&gt;&lt;code&gt;RMAN&amp;gt; CONFIGURE CONTROLFILE AUTOBACKUP ON;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;함정 4: BCT 미설정 &amp;rarr; Level 1 백업 느림&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Block Change Tracking이 꺼져 있으면 Level 1 백업이 전체 데이터파일을 스캔합니다. 백업 시간이 5~10배 더 걸립니다.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;ALTER DATABASE ENABLE BLOCK CHANGE TRACKING
USING FILE '/u01/oradata/bct/bct.log' REUSE;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;함정 5: 백업 검증을 한 번도 안 함&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;진짜 사고는 &quot;백업이 있다고 믿었는데 실제로는 복구 불가&quot;인 경우입니다. &lt;b&gt;월 1회 별도 서버에 실제 복구 테스트&lt;/b&gt;를 표준에 포함시키세요.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;운영 환경 권장 표준&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;최소 표준 체크리스트&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;[ ] CONFIGURE CONTROLFILE AUTOBACKUP ON&lt;/li&gt;
&lt;li&gt;[ ] CONFIGURE RETENTION POLICY TO RECOVERY WINDOW OF 7 DAYS&lt;/li&gt;
&lt;li&gt;[ ] 일요일 Level 0 + 평일 Level 1 + 매시간 archivelog&lt;/li&gt;
&lt;li&gt;[ ] Block Change Tracking 활성화&lt;/li&gt;
&lt;li&gt;[ ] FRA 사용량 모니터링 (80% 임계값)&lt;/li&gt;
&lt;li&gt;[ ] 백업 성공 알림 자동화&lt;/li&gt;
&lt;li&gt;[ ] 주간 RESTORE DATABASE VALIDATE 실행&lt;/li&gt;
&lt;li&gt;[ ] &lt;b&gt;월간 별도 서버에 실제 복구 테스트&lt;/b&gt; ★&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;백업 모니터링 알림 스크립트&lt;/h3&gt;
&lt;pre class=&quot;bash&quot;&gt;&lt;code&gt;#!/bin/bash
# /home/oracle/scripts/backup_monitor.sh
# 24시간 이내에 백업이 없으면 알림

sqlplus -s / as sysdba &amp;lt;&amp;lt; EOF
WHENEVER SQLERROR EXIT 1
SET HEADING OFF FEEDBACK OFF
SELECT CASE 
    WHEN MAX(end_time) &amp;lt; SYSDATE - 1 THEN 'ALERT'
    ELSE 'OK'
END FROM v$rman_backup_job_details WHERE status = 'COMPLETED';
EXIT;
EOF

if [ $? -ne 0 ]; then
    echo &quot;Backup failed in last 24h&quot; | mail -s &quot;DB Backup Alert: $(hostname)&quot; dba@company.com
fi
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;마무리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;RMAN은 강력하지만 &lt;b&gt;표준화되지 않은 RMAN은 사고의 원인&lt;/b&gt;이 됩니다. 핵심을 다시 정리하면:&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;CONFIGURE로 영구 표준 설정&lt;/b&gt; &amp;mdash; 매번 명령 입력 금지&lt;/li&gt;
&lt;li&gt;&lt;b&gt;일요일 Level 0 + 평일 Level 1 + 매시간 archivelog&lt;/b&gt; &amp;mdash; 검증된 표준 패턴&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Block Change Tracking 필수&lt;/b&gt; &amp;mdash; Level 1 백업 5~10배 빠름&lt;/li&gt;
&lt;li&gt;&lt;b&gt;검증은 백업만큼 중요&lt;/b&gt; &amp;mdash; 정기 VALIDATE + 월간 실제 복구 테스트&lt;/li&gt;
&lt;li&gt;&lt;b&gt;PDB 환경은 PDB 단위 백업 분리&lt;/b&gt; &amp;mdash; 유연성 극대화&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;운영 환경에서 RMAN 표준을 정착시키는 가장 좋은 방법은 &lt;b&gt;이번 글의 스크립트와 체크리스트를 그대로 사내 표준으로 채택&lt;/b&gt;하는 것입니다. 본인 환경에 맞춰 일부 경로와 임계값만 조정하면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이로써 본 블로그의 &lt;b&gt;30일 발행 캘린더의 마지막 글이자 오라클 운영 실무 시리즈의 마무리&lt;/b&gt;가 완성되었습니다. 백업과 복구는 DBA가 항상 마지막에 책임지는 영역입니다. 이 글이 본인의 운영 환경 표준화에 도움이 되었으면 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비슷한 RMAN 운영 사례, 더 좋은 패턴, 또는 까다로운 복구 경험이 있다면 댓글로 공유해 주세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>DBA 실무/Oracle(오라클)</category>
      <category>archive log 디스크 가득</category>
      <category>Oracle PITR</category>
      <category>Oracle RMAN 사용법</category>
      <category>PDB 백업복구</category>
      <category>RMAN Level 0 Level 1 차이</category>
      <category>RMAN 백업</category>
      <category>RMAN 복구</category>
      <category>소니스토리</category>
      <category>컨트롤 파일 복구</category>
      <category>테이블스페이스 복구</category>
      <author>isony</author>
      <guid isPermaLink="true">https://isony.tistory.com/344</guid>
      <comments>https://isony.tistory.com/entry/%EC%98%A4%EB%9D%BC%ED%81%B4-%EC%9A%B4%EC%98%81-RMAN-%EB%B0%B1%EC%97%85%EA%B3%BC-%EB%B3%B5%EA%B5%AC-%EC%99%84%EB%B2%BD-%EA%B0%80%EC%9D%B4%EB%93%9C-%EC%9A%B4%EC%98%81-%ED%99%98%EA%B2%BD-%ED%91%9C%EC%A4%80-%ED%8C%A8%ED%84%B4%EB%B6%80%ED%84%B0-5%EA%B0%80%EC%A7%80-%EB%B3%B5%EA%B5%AC-%EC%8B%9C%EB%82%98%EB%A6%AC%EC%98%A4%EA%B9%8C%EC%A7%80#entry344comment</comments>
      <pubDate>Wed, 1 Jul 2026 06:59:06 +0900</pubDate>
    </item>
    <item>
      <title>의약품 반품 보상 프로그램 만들기 &amp;mdash; 단계별 강의 (1편)</title>
      <link>https://isony.tistory.com/entry/%EC%9D%98%EC%95%BD%ED%92%88-%EB%B0%98%ED%92%88-%EB%B3%B4%EC%83%81-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%A8-%EB%A7%8C%EB%93%A4%EA%B8%B0-%E2%80%94-%EB%8B%A8%EA%B3%84%EB%B3%84-%EA%B0%95%EC%9D%98-1%ED%8E%B8</link>
      <description>&lt;h1&gt;의약품 반품 보상 프로그램 만들기 &amp;mdash; 단계별 강의 (1편)&lt;/h1&gt;
&lt;h1&gt;&lt;span style=&quot;color: #333333; font-size: 16px; letter-spacing: 0px;&quot;&gt;목표: 약국에서 만기&amp;middot;손상 의약품을 반품하면, &lt;/span&gt;&lt;b&gt;케이스의 GS1 DataMatrix 바코드를 읽어 &amp;rarr; 납품내역과 대조 &amp;rarr; 보상 수량/금액을 계산&lt;/b&gt;&lt;span style=&quot;color: #333333; font-size: 16px; letter-spacing: 0px;&quot;&gt;해 주는 프로그램을 처음부터 직접 만든다.&lt;/span&gt;&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 1편에서는 &lt;b&gt;외부 라이브러리 없이&lt;/b&gt; 동작하는 &quot;두뇌&quot;(파싱&amp;middot;대조&amp;middot;보상)를 콘솔 프로젝트로 만들고, 실제로 실행해 결과를 확인한다. 바코드 카메라&amp;middot;이미지&amp;middot;화면(UI)은 2~3편에서 붙인다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;0. 이 강의 사용법&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;각 Lesson은 &lt;b&gt;  목표 &amp;rarr;   개념 &amp;rarr;   코드 &amp;rarr;   코드 설명 &amp;rarr; ✅ 직접 해보기&lt;/b&gt; 순서다.&lt;/li&gt;
&lt;li&gt;코드는 그대로 따라 쳐도 되고, 복사해도 된다. 단, &lt;b&gt;한 번은 직접 쳐 보는 것&lt;/b&gt;을 권한다(손이 기억한다).&lt;/li&gt;
&lt;li&gt;막히면 그 Lesson의 &quot;직접 해보기&quot;까지 통과했는지 먼저 확인하자.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;전체 로드맵&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;편 Lesson 내용 프로젝트 형태&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;1편(지금)&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;0~4&lt;/td&gt;
&lt;td&gt;환경 구축, 도메인 모델, GS1 파서, 납품내역 저장소, 보상 계산&lt;/td&gt;
&lt;td&gt;콘솔&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2편&lt;/td&gt;
&lt;td&gt;5~7&lt;/td&gt;
&lt;td&gt;바코드 디코드(ZXingCpp), 이미지 처리(ImageSharp), 다중&amp;middot;타일 판독&lt;/td&gt;
&lt;td&gt;콘솔&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3편&lt;/td&gt;
&lt;td&gt;8~12&lt;/td&gt;
&lt;td&gt;WinForms 전환, 이미지 뷰어+확대/축소, 영역 판독, OCR(Tesseract), 배포&lt;/td&gt;
&lt;td&gt;WinForms&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;핵심 원칙 하나: &lt;b&gt;&quot;두뇌(로직)&quot;와 &quot;얼굴(UI)&quot;을 분리한다.&lt;/b&gt; 그래서 1편의 로직 클래스들은 화면을 전혀 모른다. 덕분에 콘솔로 먼저 검증하고, 나중에 WinForms든 웹이든 그대로 얹을 수 있다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Lesson 0 &amp;mdash; 개발 환경 구축&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  목표&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Visual Studio 2022에서 C# 콘솔 프로젝트를 만들고 실행한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  개념&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;.NET 8 SDK&lt;/b&gt;: C# 코드를 빌드&amp;middot;실행하는 도구. VS2022 설치 시 &quot;.NET 데스크톱 개발&quot; 워크로드를 고르면 함께 깔린다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;콘솔 앱&lt;/b&gt;: 화면(창) 없이 텍스트만 입출력하는 가장 단순한 프로그램. 로직을 배우기에 최적.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  따라 하기&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Visual Studio 2022 설치 시 워크로드 &lt;b&gt;&quot;.NET 데스크톱 개발&quot;&lt;/b&gt; 체크.&lt;/li&gt;
&lt;li&gt;VS2022 실행 &amp;rarr; &lt;b&gt;새 프로젝트 만들기&lt;/b&gt; &amp;rarr; &lt;b&gt;콘솔 앱&lt;/b&gt;(C#) 선택.&lt;/li&gt;
&lt;li&gt;프로젝트 이름: PharmaReturn, 프레임워크: &lt;b&gt;.NET 8.0&lt;/b&gt;.&lt;/li&gt;
&lt;li&gt;만들어진 Program.cs에 이미 Console.WriteLine(&quot;Hello, World!&quot;);가 있다. &lt;b&gt;F5&lt;/b&gt;(디버그 실행) 또는 &lt;b&gt;Ctrl+F5&lt;/b&gt;(그냥 실행).&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;✅ 직접 해보기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;검은 콘솔 창에 Hello, World!가 보이면 성공. 안 보이면 .NET 8 SDK 설치를 다시 확인하자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;명령줄을 선호하면: 폴더에서 dotnet new console -n PharmaReturn &amp;rarr; cd PharmaReturn &amp;rarr; dotnet run.&lt;/span&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Lesson 1 &amp;mdash; 도메인 모델 만들기 (Models.cs)&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  목표&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로그램이 다룰 &quot;데이터의 모양&quot;을 먼저 정의한다. 납품내역, 반품요청, 보상결과 같은 것들.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  개념&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;모델(Model)&lt;/b&gt;: 현실의 개념을 코드로 표현한 데이터 묶음. 예) &quot;납품 한 줄&quot;은 납품번호&amp;middot;약국&amp;middot;GTIN&amp;middot;로트&amp;middot;유통기한&amp;middot;수량&amp;middot;단가를 가진다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;record&lt;/b&gt;: 값을 담는 불변(immutable) 객체를 짧게 정의하는 C# 문법. 한 번 만들면 안 바뀌는 &quot;기록&quot;에 적합.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;enum&lt;/b&gt;: 정해진 몇 가지 값 중 하나(예: 반품 사유 = 만기 / 손상 / 기타).&lt;/li&gt;
&lt;li&gt;&lt;b&gt;DateOnly&lt;/b&gt;: 시각 없이 날짜만 다루는 타입(유통기한&amp;middot;납품일에 적합).&lt;/li&gt;
&lt;li&gt;&lt;b&gt;?(nullable)&lt;/b&gt;: 값이 &quot;없을 수도 있음&quot;을 표시(예: 로트번호를 모를 수도 있다 &amp;rarr; string?).&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;용어 정리(의약품 GS1):&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;GTIN&lt;/b&gt;: 국제거래단품식별코드. 제품 종류를 식별(AI 01).&lt;/li&gt;
&lt;li&gt;&lt;b&gt;로트(LOT)/배치&lt;/b&gt;: 같은 제조 묶음 번호(AI 10).&lt;/li&gt;
&lt;li&gt;&lt;b&gt;유통기한(EXP)&lt;/b&gt;: AI 17, YYMMDD 6자리.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;일련번호(Serial)&lt;/b&gt;: 낱개 식별(AI 21).&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  코드&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로젝트에 &lt;b&gt;새 클래스 파일&lt;/b&gt; Models.cs를 추가하고 아래로 교체한다.&lt;/p&gt;
&lt;pre class=&quot;cs&quot;&gt;&lt;code&gt;using System.Linq;

namespace PharmaReturn;   // &amp;larr; 프로젝트 이름과 맞춘다(콘솔 새 프로젝트라면 PharmaReturn)

/// &amp;lt;summary&amp;gt;
/// GS1 파싱 결과. 모든 AI는 Ai 딕셔너리에 들어가고,
/// 자주 쓰는 항목(GTIN/유통기한/로트/일련번호)은 강타입 프로퍼티로 노출한다.
/// &amp;lt;/summary&amp;gt;
public sealed class Gs1Fields
{
    public Dictionary&amp;lt;string, string&amp;gt; Ai { get; } = new();

    public string? Gtin =&amp;gt; Ai.GetValueOrDefault(&quot;01&quot;);           // (01) GTIN-14
    public string? Lot =&amp;gt; Ai.GetValueOrDefault(&quot;10&quot;);            // (10) 로트/배치번호
    public string? Serial =&amp;gt; Ai.GetValueOrDefault(&quot;21&quot;);         // (21) 일련번호
    public DateOnly? Expiry =&amp;gt; ParseGs1Date(Ai.GetValueOrDefault(&quot;17&quot;));        // (17) 유통기한
    public DateOnly? ProductionDate =&amp;gt; ParseGs1Date(Ai.GetValueOrDefault(&quot;11&quot;)); // (11) 제조일

    /// &amp;lt;summary&amp;gt;GS1 날짜(YYMMDD)를 DateOnly로 변환. DD가 00이면 해당 월 말일로 처리.&amp;lt;/summary&amp;gt;
    public static DateOnly? ParseGs1Date(string? yymmdd)
    {
        if (string.IsNullOrEmpty(yymmdd) || yymmdd.Length != 6) return null;
        if (!int.TryParse(yymmdd[..2], out var yy)) return null;
        if (!int.TryParse(yymmdd.Substring(2, 2), out var mm)) return null;
        if (!int.TryParse(yymmdd.Substring(4, 2), out var dd)) return null;
        if (mm is &amp;lt; 1 or &amp;gt; 12) return null;

        // GS1 규칙(간이): 00~50 -&amp;gt; 20xx, 51~99 -&amp;gt; 19xx
        int year = yy &amp;lt;= 50 ? 2000 + yy : 1900 + yy;
        if (dd == 0) dd = DateTime.DaysInMonth(year, mm);   // 일자 미지정 = 월 말일
        if (dd &amp;lt; 1 || dd &amp;gt; DateTime.DaysInMonth(year, mm)) return null;
        return new DateOnly(year, mm, dd);
    }

    public override string ToString() =&amp;gt;
        Ai.Count == 0 ? &quot;(빈 코드)&quot; : string.Join(&quot;  &quot;, Ai.Select(k =&amp;gt; $&quot;({k.Key}){k.Value}&quot;));
}

/// &amp;lt;summary&amp;gt;납품(출고) 내역 한 줄.&amp;lt;/summary&amp;gt;
public sealed record DeliveryRecord(
    string DeliveryId,
    string PharmacyId,
    DateOnly DeliveryDate,
    string Gtin,
    string ProductName,
    string LotNo,
    DateOnly ExpiryDate,
    int DeliveredQty,
    decimal UnitPrice);

public enum ReturnReason { Expiry, Damage, Other }

/// &amp;lt;summary&amp;gt;약국이 올린 반품 요청 1건.&amp;lt;/summary&amp;gt;
public sealed record ReturnRequest(
    string Gtin,
    string? LotNo,
    DateOnly? ExpiryDate,
    int RequestedQty,
    ReturnReason Reason);

public enum CompensationStatus { Approved, PartiallyApproved, Rejected }

/// &amp;lt;summary&amp;gt;보상 계산 결과.&amp;lt;/summary&amp;gt;
public sealed record CompensationResult(
    ReturnRequest Request,
    CompensationStatus Status,
    int ApprovedQty,
    decimal CreditAmount,
    string Message,
    DeliveryRecord? MatchedDelivery);
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  코드 설명&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Gs1Fields: 바코드에서 읽은 AI들을 Ai[&quot;01&quot;]처럼 딕셔너리에 담고, 자주 쓰는 것만 Gtin, Expiry 등으로 편하게 꺼내쓰게 했다.&lt;/li&gt;
&lt;li&gt;ParseGs1Date: &quot;280315&quot; &amp;rarr; 2028-03-15. &lt;b&gt;방어적으로&lt;/b&gt; 숫자가 아니면 null을 돌려준다(바코드가 깨졌을 수 있으니). DD==00(일자 미지정)은 GS1 규칙대로 &quot;그 달 말일&quot;로 본다.&lt;/li&gt;
&lt;li&gt;DeliveryRecord/ReturnRequest/CompensationResult: 한 줄짜리 record로 데이터 묶음을 정의. MatchedDelivery가 ?인 이유는 매칭이 안 될 수도 있어서.&lt;/li&gt;
&lt;li&gt;decimal UnitPrice: 돈은 double이 아니라 &lt;b&gt;decimal&lt;/b&gt;(반올림 오차 없는 타입)로.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;✅ 직접 해보기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;빌드(Ctrl+Shift+B)가 &lt;b&gt;에러 없이&lt;/b&gt; 통과하면 OK. 아직 실행 결과는 없다(데이터 정의만 했으니).&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Lesson 2 &amp;mdash; GS1 바코드 파서 (Gs1Parser.cs)&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  목표&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;바코드에서 읽은 한 줄 문자열을 GTIN&amp;middot;유통기한&amp;middot;로트로 &lt;b&gt;분해&lt;/b&gt;한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  개념&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;GS1 DataMatrix가 디코드되면 보통 두 형태 중 하나로 나온다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;원시(raw)&lt;/b&gt;: 01 + GTIN(14자리) + 17 + 날짜(6자리) + 10 + 로트(가변) &amp;hellip; 가변 길이 항목 뒤에는 &lt;b&gt;GS(ASCII 29)&lt;/b&gt; 라는 보이지 않는 구분자가 붙는다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;괄호(HRI)&lt;/b&gt;: (01)08800051300003(17)220129(10)VL200101 &amp;mdash; 실제 제품을 zxing-cpp로 읽으면 이렇게 많이 나온다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파서는 &lt;b&gt;둘 다&lt;/b&gt; 처리해야 한다. 핵심 규칙:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;고정 길이 AI&lt;/b&gt;(01=14, 17=6 등)는 정해진 길이만큼 잘라낸다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;가변 길이 AI&lt;/b&gt;(10, 21 등)는 다음 GS(또는 끝)까지 읽는다.&lt;/li&gt;
&lt;li&gt;AI 길이는 2~4자리가 섞여 있어, 4&amp;rarr;3&amp;rarr;2자리 순으로 &quot;아는 AI&quot;인지 맞춰본다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  코드&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Gs1Parser.cs 추가:&lt;/p&gt;
&lt;pre class=&quot;cs&quot;&gt;&lt;code&gt;using System.Text.RegularExpressions;

namespace PharmaReturn;

/// &amp;lt;summary&amp;gt;
/// GS1 Application Identifier(AI) 파서. 두 가지 입력 형식을 모두 처리한다.
///  1) 원시(raw) 형식: 선택적 심볼로지 식별자(]d2) + AI/값 연접, 가변 AI는 GS(ASCII 29)로 구분
///  2) 괄호(HRI) 형식: (01)08800051300003(17)220129(10)VL200101
/// &amp;lt;/summary&amp;gt;
public static class Gs1Parser
{
    /// &amp;lt;summary&amp;gt;그룹 구분자(Group Separator, ASCII 29).&amp;lt;/summary&amp;gt;
    public const char GS = '\u001D';

    private static readonly Dictionary&amp;lt;string, int&amp;gt; FixedValueLen = new()
    {
        [&quot;00&quot;] = 18, [&quot;01&quot;] = 14, [&quot;02&quot;] = 14,
        [&quot;11&quot;] = 6, [&quot;12&quot;] = 6, [&quot;13&quot;] = 6, [&quot;15&quot;] = 6, [&quot;16&quot;] = 6, [&quot;17&quot;] = 6,
        [&quot;20&quot;] = 2,
    };

    private static readonly HashSet&amp;lt;string&amp;gt; KnownVariable = new()
    {
        &quot;10&quot;, &quot;21&quot;, &quot;22&quot;, &quot;30&quot;, &quot;37&quot;,
        &quot;90&quot;, &quot;91&quot;, &quot;92&quot;, &quot;93&quot;, &quot;94&quot;, &quot;95&quot;, &quot;96&quot;, &quot;97&quot;, &quot;98&quot;, &quot;99&quot;,
        &quot;240&quot;, &quot;241&quot;, &quot;242&quot;, &quot;250&quot;, &quot;251&quot;, &quot;253&quot;, &quot;254&quot;, &quot;255&quot;,
    };

    private static readonly HashSet&amp;lt;string&amp;gt; AllKnown =
        FixedValueLen.Keys.Concat(KnownVariable).ToHashSet();

    private static readonly Regex HriAi = new(@&quot;\((\d{2,4})\)([^(]*)&quot;, RegexOptions.Compiled);

    public static Gs1Fields Parse(string? raw)
    {
        var result = new Gs1Fields();
        if (string.IsNullOrEmpty(raw)) return result;

        // 괄호(HRI) 형식이면 그쪽으로 처리
        if (raw.Contains('(') &amp;amp;&amp;amp; HriAi.IsMatch(raw))
            return ParseParenthesized(raw, result);

        return ParseRaw(raw, result);
    }

    // (01)...(17)...(10)... 형태
    private static Gs1Fields ParseParenthesized(string raw, Gs1Fields result)
    {
        foreach (Match m in HriAi.Matches(raw))
        {
            string ai = m.Groups[1].Value;
            string val = m.Groups[2].Value.Trim();
            result.Ai[ai] = val;
        }
        return result;
    }

    // 원시 연접 형식
    private static Gs1Fields ParseRaw(string raw, Gs1Fields result)
    {
        string s = StripSymbologyId(raw);
        int i = 0;
        while (i &amp;lt; s.Length)
        {
            if (s[i] == GS) { i++; continue; }

            string ai = MatchAi(s, i);
            i += ai.Length;
            if (i &amp;gt; s.Length) break;

            if (FixedValueLen.TryGetValue(ai, out int len))
            {
                len = Math.Min(len, s.Length - i);
                result.Ai[ai] = s.Substring(i, len);
                i += len;
            }
            else
            {
                int gs = s.IndexOf(GS, i);
                if (gs &amp;lt; 0) gs = s.Length;
                result.Ai[ai] = s.Substring(i, gs - i);
                i = gs;
            }
        }
        return result;
    }

    private static string StripSymbologyId(string s)
        =&amp;gt; s.Length &amp;gt;= 3 &amp;amp;&amp;amp; s[0] == ']' ? s.Substring(3) : s;

    private static string MatchAi(string s, int pos)
    {
        for (int n = 4; n &amp;gt;= 2; n--)
        {
            if (pos + n &amp;lt;= s.Length &amp;amp;&amp;amp; AllKnown.Contains(s.Substring(pos, n)))
                return s.Substring(pos, n);
        }
        return pos + 2 &amp;lt;= s.Length ? s.Substring(pos, 2) : s.Substring(pos);
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  코드 설명&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Parse가 입력을 보고 &lt;b&gt;괄호형이면&lt;/b&gt; ParseParenthesized, 아니면 ParseRaw로 보낸다.&lt;/li&gt;
&lt;li&gt;ParseParenthesized: 정규식 \((\d{2,4})\)([^(]*) 로 &quot;(AI)값&quot; 짝을 모두 뽑는다. 값은 다음 ( 전까지.&lt;/li&gt;
&lt;li&gt;ParseRaw: 맨 앞 심볼로지 식별자(]d2)를 떼고, AI를 4&amp;rarr;3&amp;rarr;2자리로 맞춰가며, 고정 길이면 길이만큼&amp;middot;가변이면 GS까지 잘라 담는다.&lt;/li&gt;
&lt;li&gt;static class인 이유: 상태(데이터)를 안 갖는 순수 기능 모음이라 인스턴스를 만들 필요가 없다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;✅ 직접 해보기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Program.cs를 잠깐 아래처럼 바꿔 실행해 보자.&lt;/p&gt;
&lt;pre class=&quot;cs&quot;&gt;&lt;code&gt;using PharmaReturn;

var raw = &quot;(01)08800051300003(17)220129(10)VL200101&quot;;
var f = Gs1Parser.Parse(raw);
Console.WriteLine($&quot;GTIN={f.Gtin}&quot;);      // 08800051300003
Console.WriteLine($&quot;유통기한={f.Expiry}&quot;); // 2022-01-29
Console.WriteLine($&quot;로트={f.Lot}&quot;);        // VL200101
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;세 줄이 위 주석값과 같이 나오면 파서 완성! (확인 후 Program.cs는 Lesson 4에서 다시 쓴다.)&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Lesson 3 &amp;mdash; 납품내역 저장소 (DeliveryRepository.cs)&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  목표&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;무엇을 누구에게 얼마나 납품했는가&quot;를 보관하고, GTIN&amp;middot;로트로 찾고, &lt;b&gt;이미 반품된 수량&lt;/b&gt;을 추적한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  개념&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;저장소(Repository)&lt;/b&gt;: 데이터를 담고 꺼내는 창구. 지금은 메모리 + CSV 파일로 간단히. 나중에 DB로 바꿔도 이 창구만 교체하면 된다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;CSV&lt;/b&gt;: 콤마로 구분된 표 데이터. 엑셀로 편집 가능해 테스트에 편하다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;기반품 추적&lt;/b&gt;: 같은 로트를 두 번 반품해 과다 보상받는 걸 막으려고, (GTIN|로트)별 누적 반품수량을 들고 있는다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  코드&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DeliveryRepository.cs 추가:&lt;/p&gt;
&lt;pre class=&quot;cs&quot;&gt;&lt;code&gt;using System.Globalization;

namespace PharmaReturn;

/// &amp;lt;summary&amp;gt;
/// 납품내역 저장소(샘플: 인메모리 + CSV). 실제로는 DB(EF Core/Dapper)로 대체.
/// 이미 반품된 수량을 (GTIN|LOT) 단위로 누적 추적해 과다 보상을 막는다.
/// &amp;lt;/summary&amp;gt;
public sealed class DeliveryRepository
{
    private readonly List&amp;lt;DeliveryRecord&amp;gt; _deliveries = new();
    private readonly Dictionary&amp;lt;string, int&amp;gt; _returnedQty = new();

    public IReadOnlyList&amp;lt;DeliveryRecord&amp;gt; All =&amp;gt; _deliveries;

    public void Add(DeliveryRecord d) =&amp;gt; _deliveries.Add(d);

    public static DeliveryRepository LoadCsv(string path)
    {
        var repo = new DeliveryRepository();
        var inv = CultureInfo.InvariantCulture;

        foreach (var line in File.ReadLines(path).Skip(1)) // 헤더 스킵
        {
            if (string.IsNullOrWhiteSpace(line)) continue;
            var c = line.Split(',');
            repo.Add(new DeliveryRecord(
                DeliveryId:   c[0].Trim(),
                PharmacyId:   c[1].Trim(),
                DeliveryDate: DateOnly.Parse(c[2].Trim(), inv),
                Gtin:         c[3].Trim(),
                ProductName:  c[4].Trim(),
                LotNo:        c[5].Trim(),
                ExpiryDate:   DateOnly.Parse(c[6].Trim(), inv),
                DeliveredQty: int.Parse(c[7].Trim(), inv),
                UnitPrice:    decimal.Parse(c[8].Trim(), inv)));
        }
        return repo;
    }

    /// &amp;lt;summary&amp;gt;GTIN(필수)과 로트(선택)로 납품내역 매칭. 로트가 null이면 GTIN만으로 매칭.&amp;lt;/summary&amp;gt;
    public IEnumerable&amp;lt;DeliveryRecord&amp;gt; FindByGtinLot(string gtin, string? lot)
        =&amp;gt; _deliveries.Where(d =&amp;gt; d.Gtin == gtin &amp;amp;&amp;amp; (lot == null || d.LotNo == lot));

    public int GetReturnedQty(string gtin, string lot)
        =&amp;gt; _returnedQty.GetValueOrDefault(Key(gtin, lot));

    public void AddReturnedQty(string gtin, string lot, int qty)
        =&amp;gt; _returnedQty[Key(gtin, lot)] = GetReturnedQty(gtin, lot) + qty;

    private static string Key(string gtin, string lot) =&amp;gt; $&quot;{gtin}|{lot}&quot;;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 테스트용 데이터 파일을 만든다. 프로젝트에 폴더 data를 만들고 그 안에 &lt;b&gt;deliveries.csv&lt;/b&gt; 를 추가:&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;DeliveryId,PharmacyId,DeliveryDate,Gtin,ProductName,LotNo,ExpiryDate,DeliveredQty,UnitPrice
D2025-001,PH-1001,2025-01-15,08801234567890,타이레놀정500mg,LOT2406A,2026-03-31,100,3200
D2025-002,PH-1001,2025-02-10,08801234567906,아목시실린캡슐250mg,LOT2501B,2027-08-31,60,1500
D2021-005,PH-1003,2021-12-01,08800051300003,테스트제품 VL,VL200101,2022-01-29,50,1200
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 이 파일이 &lt;b&gt;실행 폴더로 복사&lt;/b&gt;되도록, 솔루션 탐색기에서 deliveries.csv 선택 &amp;rarr; 속성 &amp;rarr; &lt;b&gt;출력 디렉터리로 복사 = 새 버전이면 복사&lt;/b&gt;로 설정한다. (또는 .csproj에 아래 추가)&lt;/p&gt;
&lt;pre class=&quot;armasm&quot;&gt;&lt;code&gt;&amp;lt;ItemGroup&amp;gt;
  &amp;lt;None Include=&quot;data\**\*&quot; CopyToOutputDirectory=&quot;PreserveNewest&quot; /&amp;gt;
&amp;lt;/ItemGroup&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  코드 설명&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;LoadCsv: 첫 줄(헤더) 건너뛰고, 콤마로 쪼개 DeliveryRecord로 만든다. CultureInfo.InvariantCulture로 날짜&amp;middot;숫자 파싱을 지역설정에 흔들리지 않게 고정.&lt;/li&gt;
&lt;li&gt;FindByGtinLot: 로트를 주면 GTIN+로트, 안 주면 GTIN만으로 매칭(LINQ Where).&lt;/li&gt;
&lt;li&gt;_returnedQty: &quot;GTIN|로트&quot; &amp;rarr; 누적 반품수량. GetReturnedQty/AddReturnedQty로 읽고 더한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;✅ 직접 해보기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Program.cs에서 임시로:&lt;/p&gt;
&lt;pre class=&quot;cs&quot;&gt;&lt;code&gt;using PharmaReturn;
var repo = DeliveryRepository.LoadCsv(Path.Combine(AppContext.BaseDirectory, &quot;data&quot;, &quot;deliveries.csv&quot;));
Console.WriteLine($&quot;납품 {repo.All.Count}건 로드&quot;);          // 납품 3건 로드
foreach (var d in repo.FindByGtinLot(&quot;08801234567890&quot;, null))
    Console.WriteLine($&quot;{d.ProductName} / {d.LotNo} / {d.DeliveredQty}개&quot;);
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;납품 3건 로드&quot;와 타이레놀 한 줄이 나오면 성공. (파일을 못 찾으면 &quot;출력 디렉터리로 복사&quot; 설정을 확인.)&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Lesson 4 &amp;mdash; 보상 계산 + 전체 통합 (CompensationService.cs)&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  목표&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반품 요청을 납품내역과 대조해 &lt;b&gt;승인/부분승인/거부&lt;/b&gt;와 보상 금액을 정한다. 그리고 Lesson 1~4를 한 흐름으로 묶어 실행한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  개념&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보상 규칙(샘플):&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;GTIN(+로트) 매칭 안 되면 &amp;rarr; &lt;b&gt;거부&lt;/b&gt;(납품내역 없음).&lt;/li&gt;
&lt;li&gt;만기 사유인데 유통기한이 아직 한참 남았으면 &amp;rarr; &lt;b&gt;거부&lt;/b&gt;(이상 없음).&lt;/li&gt;
&lt;li&gt;잔여 반품 가능 수량 = 납품 &amp;minus; 기반품. 0 이하면 &amp;rarr; &lt;b&gt;거부&lt;/b&gt;.&lt;/li&gt;
&lt;li&gt;승인 수량 = min(요청, 잔여). 요청보다 적게 승인되면 &lt;b&gt;부분 승인&lt;/b&gt;. 보상 = 승인수량 &amp;times; 단가.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  코드&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CompensationService.cs 추가:&lt;/p&gt;
&lt;pre class=&quot;cs&quot;&gt;&lt;code&gt;namespace PharmaReturn;

/// &amp;lt;summary&amp;gt;
/// 반품 요청을 납품내역과 대조해 보상(승인) 수량/금액을 계산한다.
/// &amp;lt;/summary&amp;gt;
public sealed class CompensationService
{
    private readonly DeliveryRepository _repo;
    private readonly int _expiryWindowDays;   // 만기 임박 허용일
    private readonly DateOnly _today;

    public CompensationService(DeliveryRepository repo, int expiryWindowDays = 90, DateOnly? today = null)
    {
        _repo = repo;
        _expiryWindowDays = expiryWindowDays;
        _today = today ?? DateOnly.FromDateTime(DateTime.Today);
    }

    public CompensationResult Evaluate(ReturnRequest req)
    {
        var matches = _repo.FindByGtinLot(req.Gtin, req.LotNo).ToList();
        if (matches.Count == 0)
            return Reject(req, &quot;납품내역 없음(GTIN/로트 불일치) &amp;mdash; 보상 불가&quot;);

        var d = matches[0];
        string lot = req.LotNo ?? d.LotNo;

        // 만기 사유 검증
        if (req.Reason == ReturnReason.Expiry)
        {
            DateOnly threshold = _today.AddDays(_expiryWindowDays);
            if (d.ExpiryDate &amp;gt; threshold)
                return Reject(req, $&quot;유통기한 이상 없음({d.ExpiryDate:yyyy-MM-dd}) &amp;mdash; 만기 반품 대상 아님&quot;);
        }

        int delivered = matches.Sum(m =&amp;gt; m.DeliveredQty);
        int alreadyReturned = _repo.GetReturnedQty(req.Gtin, lot);
        int remaining = delivered - alreadyReturned;
        if (remaining &amp;lt;= 0)
            return Reject(req, $&quot;반품 가능 수량 없음(납품 {delivered}, 기반품 {alreadyReturned})&quot;);

        int approved = Math.Min(req.RequestedQty, remaining);
        decimal credit = approved * d.UnitPrice;
        _repo.AddReturnedQty(req.Gtin, lot, approved);

        if (approved == req.RequestedQty)
            return new CompensationResult(req, CompensationStatus.Approved, approved, credit,
                $&quot;승인: {approved}개 보상&quot;, d);

        return new CompensationResult(req, CompensationStatus.PartiallyApproved, approved, credit,
            $&quot;부분 승인: 요청 {req.RequestedQty} 중 {approved}개 보상(잔여 한도 {remaining})&quot;, d);
    }

    private static CompensationResult Reject(ReturnRequest req, string msg)
        =&amp;gt; new(req, CompensationStatus.Rejected, 0, 0m, msg, null);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  코드 설명&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;생성자에서 today를 받게 한 건 &lt;b&gt;테스트를 재현 가능&lt;/b&gt;하게 하려는 것(운영에선 비우면 오늘 날짜 사용).&lt;/li&gt;
&lt;li&gt;규칙을 위에서 아래로 &quot;걸리면 즉시 거부, 다 통과하면 승인&quot; 구조로 짰다. 읽기 쉽고 디버깅 쉽다.&lt;/li&gt;
&lt;li&gt;_repo.AddReturnedQty(...)로 승인분을 바로 누적해, 같은 로트를 또 반품하면 잔여가 줄어든다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  전체 통합 Program.cs&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 1편의 결과물을 한 흐름으로 묶는다. Program.cs를 아래로 교체:&lt;/p&gt;
&lt;pre class=&quot;cs&quot;&gt;&lt;code&gt;using PharmaReturn;

var evalDate = new DateOnly(2026, 6, 16); // 데모 재현용 기준일(운영은 생략 &amp;rarr; 오늘)
var repo = DeliveryRepository.LoadCsv(Path.Combine(AppContext.BaseDirectory, &quot;data&quot;, &quot;deliveries.csv&quot;));
var svc = new CompensationService(repo, expiryWindowDays: 90, today: evalDate);

// 바코드에서 읽었다고 가정한 코드들(괄호형/원시형 섞어서)
var scannedCodes = new[]
{
    &quot;(01)08801234567890(17)260331(10)LOT2406A(21)SN0001&quot;, // 타이레놀, 만기 경과
    &quot;(01)08800051300003(17)220129(10)VL200101&quot;,           // VL, 만기 경과
    &quot;(01)08801234567906(17)270831(10)LOT2501B&quot;,           // 아목시실린, 기한 멀음
};

// 각 코드의 (사유, 요청수량)은 검수 화면 입력값이라고 가정
var input = new (ReturnReason Reason, int Qty)[]
{
    (ReturnReason.Expiry, 30),
    (ReturnReason.Expiry, 10),
    (ReturnReason.Expiry, 5),
};

Console.WriteLine($&quot;{&quot;GTIN&quot;,-16}{&quot;로트&quot;,-10}{&quot;유통기한&quot;,-12}{&quot;요청&quot;,4}{&quot;승인&quot;,5}{&quot;보상금액&quot;,12}  결과&quot;);
Console.WriteLine(new string('-', 80));

decimal total = 0;
for (int i = 0; i &amp;lt; scannedCodes.Length; i++)
{
    var f = Gs1Parser.Parse(scannedCodes[i]);              // ① 파싱
    var req = new ReturnRequest(f.Gtin!, f.Lot, f.Expiry, input[i].Qty, input[i].Reason);
    var r = svc.Evaluate(req);                             // ② 대조 + 보상
    total += r.CreditAmount;
    Console.WriteLine($&quot;{f.Gtin,-16}{f.Lot,-10}{f.Expiry,-12:yyyy-MM-dd}{req.RequestedQty,4}{r.ApprovedQty,5}{r.CreditAmount,12:N0}  [{r.Status}] {r.Message}&quot;);
}
Console.WriteLine(new string('-', 80));
Console.WriteLine($&quot;총 보상 금액: {total:N0} 원&quot;);
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;✅ 직접 해보기 (1편 최종 결과)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실행하면 대략 이런 표가 나온다(기준일 2026-06-16):&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;GTIN            로트       유통기한      요청  승인     보상금액  결과
--------------------------------------------------------------------------------
08801234567890  LOT2406A  2026-03-31     30   30      96,000  [Approved] 승인: 30개 보상
08800051300003  VL200101  2022-01-29     10   10      12,000  [Approved] 승인: 10개 보상
08801234567906  LOT2501B  2027-08-31      5    0           0  [Rejected] 유통기한 이상 없음(2027-08-31) ...
--------------------------------------------------------------------------------
총 보상 금액: 108,000 원
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;1번: 만기 경과 &amp;rarr; 30개 전량 승인(30&amp;times;3,200=96,000).&lt;/li&gt;
&lt;li&gt;2번: 만기 경과 &amp;rarr; 10개 승인(10&amp;times;1,200=12,000).&lt;/li&gt;
&lt;li&gt;3번: 유통기한이 2027년이라 만기 반품 대상 아님 &amp;rarr; 거부.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 표가 나오면 &lt;b&gt;1편 완성&lt;/b&gt;이다. &quot;바코드 한 줄 &amp;rarr; 파싱 &amp;rarr; 납품 대조 &amp;rarr; 보상&quot; 두뇌가 동작하는 것.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;더 해보기: input의 사유를 Damage로 바꾸면(손상) 유통기한 검증을 건너뛴다. 요청 수량을 납품수량보다 크게 주면 &quot;부분 승인&quot;이 나온다. 같은 코드를 두 번 넣으면 두 번째는 잔여 한도가 줄어드는 것도 확인해 보자.&lt;/span&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1편 마무리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금까지 만든 것:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Models.cs &amp;mdash; 데이터의 모양&lt;/li&gt;
&lt;li&gt;Gs1Parser.cs &amp;mdash; 바코드 문자열 &amp;rarr; GTIN/유통기한/로트 (괄호형&amp;middot;원시형 모두)&lt;/li&gt;
&lt;li&gt;DeliveryRepository.cs &amp;mdash; 납품내역 보관&amp;middot;매칭&amp;middot;기반품 추적&lt;/li&gt;
&lt;li&gt;CompensationService.cs &amp;mdash; 보상 판정(승인/부분/거부)&lt;/li&gt;
&lt;li&gt;Program.cs &amp;mdash; 위를 한 흐름으로 묶은 콘솔 데모&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;다음 편 예고&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;2편&lt;/b&gt;: 진짜 바코드 이미지를 읽는다. ZXingCpp(zxing-cpp)로 GS1 DataMatrix를 디코드하고, 위치 좌표를 얻고, &lt;b&gt;한 장에 여러 개&lt;/b&gt;&amp;middot;&lt;b&gt;큰 사진의 작은 코드&lt;/b&gt;(타일 판독)를 처리한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;3편&lt;/b&gt;: 콘솔을 &lt;b&gt;WinForms&lt;/b&gt;로 바꿔, 파일 불러오기&amp;middot;이미지 미리보기&amp;middot;&lt;b&gt;확대/축소&lt;/b&gt;&amp;middot;판독 위치 파란 박스&amp;middot;영역 판독&amp;middot;&lt;b&gt;가독문자 OCR(Tesseract)&lt;/b&gt;&amp;middot;결과 그리드&amp;middot;보상 계산까지 완성하고 배포한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>개발(IT)/C#(VisualStudio)</category>
      <category>DataMatrix Decode</category>
      <category>GS1 DataMatrix</category>
      <category>GS1 Parser</category>
      <category>OCR DataMatrix</category>
      <category>OCR 바코드 판독</category>
      <category>ZXingCpp 바코드 디코드</category>
      <category>가독문자 OCR</category>
      <category>데이타메트릭스 디코드</category>
      <category>소니스토리</category>
      <category>의약품 반품 보상 프로그램</category>
      <author>isony</author>
      <guid isPermaLink="true">https://isony.tistory.com/343</guid>
      <comments>https://isony.tistory.com/entry/%EC%9D%98%EC%95%BD%ED%92%88-%EB%B0%98%ED%92%88-%EB%B3%B4%EC%83%81-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%A8-%EB%A7%8C%EB%93%A4%EA%B8%B0-%E2%80%94-%EB%8B%A8%EA%B3%84%EB%B3%84-%EA%B0%95%EC%9D%98-1%ED%8E%B8#entry343comment</comments>
      <pubDate>Mon, 29 Jun 2026 08:43:25 +0900</pubDate>
    </item>
    <item>
      <title>[리눅스 운영] 디스크 용량 부족 (df 100%) 해결 - 5가지 원인과 체계적 진단법 (DBA 환경 특화)</title>
      <link>https://isony.tistory.com/entry/%EB%A6%AC%EB%88%85%EC%8A%A4-%EC%9A%B4%EC%98%81-%EB%94%94%EC%8A%A4%ED%81%AC-%EC%9A%A9%EB%9F%89-%EB%B6%80%EC%A1%B1-df-100-%ED%95%B4%EA%B2%B0-5%EA%B0%80%EC%A7%80-%EC%9B%90%EC%9D%B8%EA%B3%BC-%EC%B2%B4%EA%B3%84%EC%A0%81-%EC%A7%84%EB%8B%A8%EB%B2%95-DBA-%ED%99%98%EA%B2%BD-%ED%8A%B9%ED%99%94</link>
      <description>&lt;h1&gt;[리눅스 운영] 디스크 용량 부족 (df 100%) 해결 - 5가지 원인과 체계적 진단법 (DBA 환경 특화)&lt;/h1&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;테스트 환경&lt;/b&gt;: Oracle Linux 8 / RHEL 8 / Ubuntu 22.04&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;새벽 3시. &quot;ALERT: /u01 사용량 98%&quot; 모니터링 알람이 옵니다. 1시간 후엔 운영 DB가 멈출 수 있습니다. 어디부터 정리해야 할까요?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리눅스 디스크 용량 부족은 가장 흔하면서도 가장 위험한 운영 장애입니다. &lt;b&gt;무작정 rm을 휘두르면 서비스가 죽고, 가만히 있으면 디스크가 100%가 됩니다.&lt;/b&gt; 더 까다로운 점은 다음 같은 상황이 자주 발생한다는 것입니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;df는 100%인데 du로 보면 공간이 안 차 있음 (어디가 차지하고 있는 건가?)&lt;/li&gt;
&lt;li&gt;큰 파일을 지웠는데 공간이 회수되지 않음&lt;/li&gt;
&lt;li&gt;공간은 있는데 &quot;No space left on device&quot; 발생&lt;/li&gt;
&lt;li&gt;어제 정리했는데 오늘 또 가득 참&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 글은 리눅스 디스크 용량 부족을 &lt;b&gt;체계적으로 진단하는 3단계 명령&lt;/b&gt;부터 시작해서, 5가지 원인별 해결법, 그리고 &lt;b&gt;오라클 운영 환경의 특화 케이스&lt;/b&gt;까지 정리했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;장애 대응 중이라면 &lt;u&gt;긴급 응급 처치&lt;/u&gt;부터 보세요.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;★ 3차원 진단 명령 - 모든 시작점&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대부분의 사람이 df -h만 보고 끝내는데, &lt;b&gt;이것만으로는 진단 못 하는 케이스가 30% 이상&lt;/b&gt;입니다. 반드시 3가지를 함께 확인하세요.&lt;/p&gt;
&lt;pre class=&quot;properties&quot;&gt;&lt;code&gt;# 1) 블록 사용량 - 가장 흔한 진단
df -h

# 2) inode 사용량 - 작은 파일 많을 때 (자주 놓침)
df -i

# 3) 삭제됐는데 프로세스가 잡고 있는 파일 (df와 du가 다를 때)
sudo lsof +L1
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;결과 해석법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;증상 원인&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;df -h 100% + du도 큼&lt;/td&gt;
&lt;td&gt;일반 디스크 부족 (원인 1, 3, 5 참고)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;df -h 100% + du는 작음&lt;/td&gt;
&lt;td&gt;&lt;b&gt;삭제됐는데 잡힌 파일&lt;/b&gt; (원인 2 참고)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;df -h 여유 + 쓰기 실패&lt;/td&gt;
&lt;td&gt;&lt;b&gt;inode 고갈&lt;/b&gt; (원인 4 참고)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;df -i 100%&lt;/td&gt;
&lt;td&gt;inode 고갈 확정&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 표를 책갈피해 두면 진단 시간이 절반으로 줄어듭니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;★ df vs du 차이 - 왜 결과가 다른가&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;운영자가 가장 헷갈리는 부분입니다. 둘은 &lt;b&gt;완전히 다른 방식으로 디스크를 측정&lt;/b&gt;합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;명령 측정 방법 보는 것&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;df&lt;/td&gt;
&lt;td&gt;&lt;b&gt;파일시스템 superblock 카운터&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;할당된 모든 블록 (삭제된 파일 점유 포함)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;du&lt;/td&gt;
&lt;td&gt;&lt;b&gt;디렉토리 트리 순회&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;실제 접근 가능한 파일&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 구조적 차이 때문에 다음 같은 결과 차이가 발생합니다.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;# df는 100% 사용 중이라고 함
$ df -h /
Filesystem      Size  Used Avail Use% Mounted on
/dev/sda1       50G   50G   0     100% /

# du로 합산하면 30GB만 있음
$ sudo du -sh /
30G   /

# 차이 20GB는 어디로? &amp;rarr; 삭제됐는데 프로세스가 잡고 있는 파일!
$ sudo lsof +L1
COMMAND   PID  USER  FD  TYPE  DEVICE  SIZE/OFF  NLINK  NODE  NAME
java      1234 app   77w REG   8,1     21474836  0      ...   /var/log/app.log (deleted)
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;핵심&lt;/b&gt;: df와 du가 다르면 거의 100% &quot;deleted but open&quot; 파일입니다. 이게 ORA-12541(리스너 죽음)의 &lt;u&gt;listener.log 4GB 케이스&lt;/u&gt;와 같은 메커니즘이에요.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;긴급 응급 처치 (5분 안에)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;운영 환경이 멈출 위기라면 즉시 다음을 시도하세요. 안전한 순서대로 정리했습니다.&lt;/p&gt;
&lt;pre class=&quot;jboss-cli&quot;&gt;&lt;code&gt;# 1) 가장 큰 로그/임시 디렉토리 빠르게 확인
sudo du -sh /var/log /tmp /var/tmp /var/cache 2&amp;gt;/dev/null

# 2) journal 로그 7일치만 남기고 정리 (가장 안전)
sudo journalctl --vacuum-time=7d

# 3) 패키지 캐시 정리
sudo dnf clean all          # RHEL/Oracle Linux
sudo apt clean              # Ubuntu/Debian

# 4) 30일 이상 된 압축 로그 정리
sudo find /var/log -name &quot;*.gz&quot; -mtime +30 -delete

# 5) 100MB 이상 파일 식별 (지우기 전 검토 필수)
sudo find / -xdev -type f -size +100M -exec ls -lh {} \; 2&amp;gt;/dev/null | sort -k5 -rh | head -20
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 5단계로 보통 5~20GB는 즉시 회수됩니다. 그 후 원인을 진단해서 재발 방지를 하세요.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;원인 1: 로그 파일 미회전 (가장 흔함)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리눅스 디스크 부족의 50% 이상이 이 케이스입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;진단 방법&lt;/h3&gt;
&lt;pre class=&quot;excel&quot;&gt;&lt;code&gt;# /var/log에서 가장 큰 파일 찾기
sudo du -sh /var/log/*  | sort -rh | head -10

# 1GB 이상 로그 파일 식별
sudo find /var/log -type f -size +1G -exec ls -lh {} \;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;해결 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1) 활성 로그 파일은 안전하게 truncate&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;stata&quot;&gt;&lt;code&gt;# ❌ 위험: 단순 rm은 deleted but open 상태 만듦
rm /var/log/huge.log

# ✅ 안전: truncate (프로세스가 파일을 열어둔 채 유지)
sudo truncate -s 0 /var/log/huge.log

# 또는
sudo : &amp;gt; /var/log/huge.log
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2) logrotate 강제 실행&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;awk&quot;&gt;&lt;code&gt;sudo logrotate -f /etc/logrotate.conf
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3) 오래된 회전 로그 정리&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;# 30일 이상 된 압축 로그 삭제
sudo find /var/log -name &quot;*.gz&quot; -mtime +30 -delete
sudo find /var/log -name &quot;*.log.[0-9]*&quot; -mtime +30 -delete
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;재발 방지 - logrotate 표준 설정&lt;/h3&gt;
&lt;pre class=&quot;dts&quot;&gt;&lt;code&gt;/var/log/app/*.log {
    daily
    rotate 14
    compress
    delaycompress
    missingok
    notifempty
    copytruncate       # &amp;larr; 활성 파일도 안전하게 처리
    size 100M
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;copytruncate 옵션이 핵심입니다. 이게 없으면 회전 후에도 프로세스가 옛 파일을 잡고 있어서 공간이 회수되지 않습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;★ 원인 2: 삭제됐는데 프로세스가 잡고 있는 파일 (deleted but open)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 까다로운 케이스입니다. 단순 rm으로는 해결 안 됩니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;무엇이 문제인가&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리눅스에서 rm은 &lt;b&gt;파일을 디렉토리 트리에서만 제거&lt;/b&gt;합니다. 프로세스가 그 파일을 열고 있으면 inode와 디스크 블록은 그대로 유지됩니다. 프로세스가 닫거나 재시작될 때까지 공간이 회수되지 않습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;진단 방법&lt;/h3&gt;
&lt;pre class=&quot;nginx&quot;&gt;&lt;code&gt;# 삭제된 채 열려 있는 파일 모두 확인
sudo lsof +L1

# 또는 &quot;(deleted)&quot; 키워드로 검색
sudo lsof | grep '(deleted)'

# 가장 큰 deleted 파일 찾기
sudo lsof +L1 | awk '{print $7, $NF}' | sort -rn | head -10
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;출력 예시:&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;COMMAND   PID    USER  FD   TYPE  DEVICE  SIZE/OFF    NLINK  NODE     NAME
java      1234   app   77w  REG   8,1     21474836480 0      1283397  /var/log/app.log (deleted)
oracle    25575  oracle 33   REG   65,65   4294983680  0      31014933 /oradata/file.dbf (deleted)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;해결 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;방법 1: 프로세스 재시작 (가장 안전)&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;# nginx의 경우 - USR1 시그널로 로그 reopen (재시작 없이 처리)
sudo kill -USR1 $(cat /var/run/nginx.pid)

# 일반 systemd 서비스 재시작
sudo systemctl restart &amp;lt;service-name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;방법 2: /proc 파일 디스크립터를 통한 truncate (재시작 불가 시)&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;# lsof 출력에서 PID와 FD 번호 확인 후
# 예: PID 1234, FD 77

sudo truncate -s 0 /proc/1234/fd/77

# 또는
echo &amp;gt; /proc/1234/fd/77
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;위험 경고&lt;/b&gt;: 이 방법은 &lt;b&gt;로그 파일에만 안전&lt;/b&gt;합니다. 데이터베이스 파일이나 진행 중인 작업 파일에 사용하면 &lt;b&gt;데이터 손실 또는 손상&lt;/b&gt;이 발생합니다. 반드시 (deleted) 표시와 파일 종류를 먼저 확인하세요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;자주 발생하는 시나리오&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Java 애플리케이션의 로그 파일&lt;/b&gt;: 무한 append 후 rm&lt;/li&gt;
&lt;li&gt;&lt;b&gt;오라클 listener.log&lt;/b&gt;: 누군가 rm 했지만 리스너 프로세스가 잡고 있음&lt;/li&gt;
&lt;li&gt;&lt;b&gt;nginx access.log&lt;/b&gt;: logrotate 미설정 환경에서 수동 rm&lt;/li&gt;
&lt;li&gt;&lt;b&gt;rsyslog 로그&lt;/b&gt;: 회전 설정 오류&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;운영 환경에서 디스크 공간이 갑자기 회수되지 않는다면 99% 이 케이스입니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;원인 3: 패키지 캐시 / 옛 커널 / Docker 누적&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;운영 시간이 길어질수록 자연 증가하는 영역입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;진단 방법&lt;/h3&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;# 패키지 캐시
sudo du -sh /var/cache/dnf /var/cache/apt 2&amp;gt;/dev/null

# 설치된 커널 목록
rpm -q kernel              # RHEL/Oracle Linux
dpkg --list | grep linux-image    # Ubuntu

# Docker (있다면)
sudo docker system df
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;해결 방법&lt;/h3&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;# 1) 패키지 캐시 정리
sudo dnf clean all           # RHEL/Oracle Linux
sudo apt clean               # Ubuntu/Debian

# 2) 옛 커널 정리 (현재 부팅 커널은 절대 삭제 금지)
uname -r   # 현재 커널 확인 후

# RHEL/Oracle Linux: 최신 2개만 유지
sudo dnf remove --oldinstallonly --setopt installonly_limit=2 kernel-core

# Ubuntu
sudo apt autoremove --purge

# 3) Docker 정리 (있다면)
sudo docker system prune -a --volumes
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;★ 원인 4: inode 고갈 (df는 여유, 쓰기 실패)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 케이스는 한국어 자료에 깊이 다루지 않는 영역입니다. &lt;b&gt;공간은 충분한데 새 파일 생성이 실패&lt;/b&gt;하는 황당한 상황입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;무엇이 문제인가&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리눅스 파일시스템은 파일/디렉토리마다 &lt;b&gt;inode 1개&lt;/b&gt;를 사용합니다. 작은 파일이 수백만 개 있으면 블록은 여유롭지만 inode가 고갈됩니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;진단 방법&lt;/h3&gt;
&lt;pre class=&quot;lsl&quot;&gt;&lt;code&gt;# inode 사용량 확인
df -i

# IUse%가 100% 또는 95% 이상이면 고갈
Filesystem      Inodes  IUsed   IFree  IUse%  Mounted on
/dev/sda1       3276800 3276800 0      100%   /

# 어느 디렉토리에 파일이 많은지 찾기
sudo find / -xdev -type d 2&amp;gt;/dev/null -exec sh -c '
    count=$(ls -A &quot;$1&quot; 2&amp;gt;/dev/null | wc -l)
    echo &quot;$count $1&quot;
' _ {} \; | sort -rn | head -20
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;자주 발생하는 시나리오&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;메일 큐&lt;/b&gt;: /var/spool/postfix/ 또는 /var/spool/mail/&lt;/li&gt;
&lt;li&gt;&lt;b&gt;PHP 세션 파일&lt;/b&gt;: /tmp 또는 /var/lib/php/session&lt;/li&gt;
&lt;li&gt;&lt;b&gt;애플리케이션 캐시&lt;/b&gt;: 사용자별 캐시 파일이 누적&lt;/li&gt;
&lt;li&gt;&lt;b&gt;잘못 구성된 cron&lt;/b&gt;: 매 분마다 작은 파일 생성&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;해결 방법&lt;/h3&gt;
&lt;pre class=&quot;crystal&quot;&gt;&lt;code&gt;# 1) 메일 큐 정리 (postfix)
sudo postsuper -d ALL

# 2) PHP 세션 정리
sudo find /var/lib/php/session -type f -mtime +7 -delete

# 3) 임시 파일 정리
sudo find /tmp -type f -atime +7 -delete

# 4) 특정 디렉토리의 오래된 작은 파일 일괄 삭제
sudo find /path/to/dir -type f -mtime +30 -delete
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;주의&lt;/b&gt;: 파일이 너무 많아 find -delete도 느릴 수 있습니다. rm -rf /path/to/dir/*은 &lt;b&gt;&quot;argument list too long&quot; 에러&lt;/b&gt;가 날 수 있으니 find 사용을 권장합니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;원인 5: 마운트가 가려진 디렉토리 (Hidden Mount)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;드물지만 한 번 발생하면 미궁에 빠지는 케이스입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;무엇이 문제인가&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마운트 포인트로 사용된 디렉토리에 &lt;b&gt;이미 파일이 있던 상태&lt;/b&gt;에서 마운트하면, 원래 파일들이 보이지 않지만 공간은 계속 차지합니다.&lt;/p&gt;
&lt;pre class=&quot;vala&quot;&gt;&lt;code&gt;# 예시: /data 디렉토리에 100GB 파일이 있는 상태에서
# 그 위에 새 디스크를 마운트
sudo mount /dev/sdb1 /data

# 이제 ls /data 하면 새 디스크 내용만 보임
# 하지만 원래 100GB는 여전히 디스크 어딘가에 존재
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;진단 방법&lt;/h3&gt;
&lt;pre class=&quot;haskell&quot;&gt;&lt;code&gt;# 마운트 정보 확인
sudo lsblk
mount | column -t

# 마운트 풀고 원래 내용 확인
sudo umount /data
ls -la /data

# 큰 파일이 보이면 그게 숨겨져 있던 것
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;해결 방법&lt;/h3&gt;
&lt;pre class=&quot;haskell&quot;&gt;&lt;code&gt;# 1) 일시 umount 후 정리
sudo umount /data
sudo rm -rf /data/*    # &amp;larr; 원래 숨겨져 있던 파일들 삭제

# 2) 다시 마운트
sudo mount /dev/sdb1 /data
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 사고를 막으려면 &lt;b&gt;마운트 포인트로 사용할 디렉토리는 빈 폴더로 만들어 두는 것&lt;/b&gt;이 표준입니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;★ 오라클 운영 환경 특화 케이스&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DBA가 운영하는 환경에서 자주 발생하는 디스크 고갈 시나리오입니다. 본 블로그의 다른 글들과 직접 연결되는 영역이에요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1) listener.log가 4GB 초과&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.whodo.net/entry/%EC%98%A4%EB%9D%BC%ED%81%B4-%EC%97%90%EB%9F%AC-ORA-12541-TNS-%EB%A6%AC%EC%8A%A4%EB%84%88%EA%B0%80-%EC%97%86%EC%8A%B5%EB%8B%88%EB%8B%A4-5%EA%B0%80%EC%A7%80-%EC%9B%90%EC%9D%B8%EA%B3%BC-%ED%95%B4%EA%B2%B0%EB%B0%A9%EB%B2%95-%EC%8B%A4%EB%AC%B4-DBA-%EC%A0%95%EB%A6%AC&quot;&gt;ORA-12541 글&lt;/a&gt;에서 다룬 케이스. Windows 32bit 또는 일부 파일시스템 환경에서 listener.log가 4GB를 넘으면 리스너가 죽고 디스크도 차지합니다.&lt;/p&gt;
&lt;pre class=&quot;jboss-cli&quot;&gt;&lt;code&gt;# 위치 확인
lsnrctl status | grep &quot;Listener Log File&quot;

# 안전한 정리 (리스너 중지 후)
lsnrctl stop
mv listener.log listener.log.$(date +%Y%m%d).bak
lsnrctl start

# 영구 해결: ADRCI로 자동 로테이션
adrci
ADRCI&amp;gt; set home diag/tnslsnr/{호스트명}/listener
ADRCI&amp;gt; set control (SHORTP_POLICY = 168, LONGP_POLICY = 720)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2) alert log와 trace 파일 누적&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오라클은 /u01/app/oracle/diag 아래에 진단 파일을 계속 쌓아갑니다.&lt;/p&gt;
&lt;pre class=&quot;shell&quot;&gt;&lt;code&gt;# 진단 디렉토리 사용량 확인
sudo du -sh /u01/app/oracle/diag/*

# ADRCI로 일괄 정리 (가장 안전)
adrci
ADRCI&amp;gt; show homes
ADRCI&amp;gt; set home diag/rdbms/proddb/PRODDB
ADRCI&amp;gt; purge -age 10080 -type trace      # 7일 이상 trace 삭제 (분 단위)
ADRCI&amp;gt; purge -age 43200 -type alert      # 30일 이상 alert 삭제
ADRCI&amp;gt; purge -age 10080 -type incident
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3) archive log 폭증&lt;/h3&gt;
&lt;pre class=&quot;gams&quot;&gt;&lt;code&gt;# 위치 확인
sqlplus / as sysdba
SQL&amp;gt; SHOW PARAMETER log_archive_dest

# 사용량 확인
sudo du -sh /u01/app/oracle/fast_recovery_area/

# RMAN으로 안전하게 정리
rman target /
RMAN&amp;gt; CROSSCHECK ARCHIVELOG ALL;
RMAN&amp;gt; DELETE EXPIRED ARCHIVELOG ALL;
RMAN&amp;gt; DELETE ARCHIVELOG ALL COMPLETED BEFORE 'SYSDATE-7';
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;경고&lt;/b&gt;: archive log를 무작정 rm으로 삭제하면 RMAN 카탈로그와 불일치가 발생합니다. 반드시 RMAN으로 처리하세요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4) datapump dump 파일 누적&lt;/h3&gt;
&lt;pre class=&quot;jboss-cli&quot;&gt;&lt;code&gt;# 보통 위치
sudo ls -lh /backup/dpdump/*.dmp

# 30일 이상된 백업 자동 정리 스크립트
sudo find /backup/dpdump -name &quot;*.dmp&quot; -mtime +30 -delete
sudo find /backup/dpdump -name &quot;*.log&quot; -mtime +30 -delete
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;절대 하지 말아야 할 것 ★&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;장애 대응 중 다급해서 실수하기 쉬운 위험 작업들입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;❌ 1: rm -rf /* 패턴&lt;/h3&gt;
&lt;pre class=&quot;jboss-cli&quot;&gt;&lt;code&gt;# 변수가 비어 있으면 / 전체가 삭제됨
rm -rf $UNDEFINED_VAR/*    # &amp;larr; 절대 금지
rm -rf /tmp /var/tmp /...  # 공백 실수 위험
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;항상 &lt;b&gt;변수에 값이 있는지&lt;/b&gt; 먼저 확인하고, 절대 경로를 사용하세요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;❌ 2: 활성 데이터파일에 truncate&lt;/h3&gt;
&lt;pre class=&quot;awk&quot;&gt;&lt;code&gt;# 절대 금지: 운영 DB 데이터파일
sudo truncate -s 0 /u01/oradata/PRODDB/system01.dbf
# &amp;rarr; DB 손상, 복구 불가
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;truncate -s 0은 &lt;b&gt;로그 파일에만&lt;/b&gt; 사용하세요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;❌ 3: archive log 직접 삭제&lt;/h3&gt;
&lt;pre class=&quot;dts&quot;&gt;&lt;code&gt;# 절대 금지
rm /u01/app/oracle/fast_recovery_area/PRODDB/archivelog/*.arc
# &amp;rarr; RMAN 카탈로그 불일치, 복구 시 실패
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;RMAN으로 처리해야 합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;❌ 4: 현재 부팅 커널 삭제&lt;/h3&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;# 위험
sudo dnf remove kernel-$(uname -r)
# &amp;rarr; 재부팅 시 부팅 실패
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설치 커널 정리 시 반드시 uname -r로 현재 커널을 확인하세요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;❌ 5: /etc, /usr 임의 삭제&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시스템 동작에 필수입니다. 큰 파일이 있어도 절대 건드리지 마세요.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;재발 방지 - 자동 모니터링 + 알림&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;장애를 막는 가장 좋은 방법은 &lt;b&gt;85% 차기 전에 알림&lt;/b&gt;을 받는 것입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;간단한 모니터링 스크립트&lt;/h3&gt;
&lt;pre class=&quot;stata&quot;&gt;&lt;code&gt;#!/bin/bash
# /home/oracle/scripts/disk_monitor.sh

THRESHOLD=85
MAIL_TO=&quot;dba@company.com&quot;

df -h | awk -v threshold=$THRESHOLD '
NR &amp;gt; 1 &amp;amp;&amp;amp; $5 != &quot;&quot; {
    use = int(substr($5, 1, length($5)-1))
    if (use &amp;gt;= threshold) {
        print $6 &quot; is &quot; $5 &quot; used (threshold &quot; threshold &quot;%)&quot;
    }
}' | while read line; do
    echo &quot;$line&quot; | mail -s &quot;DISK ALERT: $(hostname)&quot; $MAIL_TO
done

# inode 점검도 함께
df -i | awk -v threshold=$THRESHOLD '
NR &amp;gt; 1 &amp;amp;&amp;amp; $5 != &quot;&quot; {
    use = int(substr($5, 1, length($5)-1))
    if (use &amp;gt;= threshold) {
        print $6 &quot; inode &quot; $5 &quot; used&quot;
    }
}'
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;crystal&quot;&gt;&lt;code&gt;# cron에 등록 (5분마다)
*/5 * * * * /home/oracle/scripts/disk_monitor.sh
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;자동 정리 cron (안전한 영역만)&lt;/h3&gt;
&lt;pre class=&quot;lsl&quot;&gt;&lt;code&gt;# 매일 새벽 2시 - journal, 패키지 캐시, 30일 로그
0 2 * * * journalctl --vacuum-time=7d
0 2 * * * find /var/log -name &quot;*.gz&quot; -mtime +30 -delete

# 매주 일요일 - ADRCI 오라클 진단 파일 정리
0 3 * * 0 /home/oracle/scripts/adrci_cleanup.sh
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;마무리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리눅스 디스크 용량 부족은 단순한 &quot;쓰레기 정리&quot; 작업이 아니라, &lt;b&gt;체계적 진단이 필요한 운영 사고&lt;/b&gt;입니다. 핵심을 한 번 더 정리하면:&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;3차원 진단 (df -h, df -i, lsof +L1)&lt;/b&gt; &amp;mdash; 한 가지만 보지 말 것&lt;/li&gt;
&lt;li&gt;&lt;b&gt;df와 du가 다르면 deleted-but-open 파일&lt;/b&gt; &amp;mdash; 단순 rm으로 안 풀림&lt;/li&gt;
&lt;li&gt;&lt;b&gt;로그 파일은 truncate -s 0&lt;/b&gt; &amp;mdash; rm보다 안전&lt;/li&gt;
&lt;li&gt;&lt;b&gt;inode 고갈 확인 필수&lt;/b&gt; &amp;mdash; 공간 있어도 쓰기 실패&lt;/li&gt;
&lt;li&gt;&lt;b&gt;오라클 환경은 ADRCI / RMAN으로 정리&lt;/b&gt; &amp;mdash; 직접 rm 금지&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;운영 환경의 디스크 고갈을 근본적으로 막으려면 &lt;b&gt;logrotate 표준화 + ADRCI 자동 정리 + 85% 임계값 모니터링&lt;/b&gt; 세 가지를 갖춰 두세요. 이 셋만 있으면 디스크 관련 새벽 호출의 90%는 사라집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비슷한 케이스를 겪으셨거나, 더 좋은 재발 방지 패턴이 있다면 댓글로 공유해 주세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>DBA 실무/Oracle(오라클)</category>
      <category>archive log 삭제</category>
      <category>df -i 사용량</category>
      <category>df vs du 차이</category>
      <category>inode 부족해결</category>
      <category>linux disk full 해결</category>
      <category>listener.log 4GB</category>
      <category>lsof deleted 파일</category>
      <category>리눅스 디스크 부족 해결</category>
      <category>소니스토리</category>
      <category>운영서버 디스크100%</category>
      <author>isony</author>
      <guid isPermaLink="true">https://isony.tistory.com/342</guid>
      <comments>https://isony.tistory.com/entry/%EB%A6%AC%EB%88%85%EC%8A%A4-%EC%9A%B4%EC%98%81-%EB%94%94%EC%8A%A4%ED%81%AC-%EC%9A%A9%EB%9F%89-%EB%B6%80%EC%A1%B1-df-100-%ED%95%B4%EA%B2%B0-5%EA%B0%80%EC%A7%80-%EC%9B%90%EC%9D%B8%EA%B3%BC-%EC%B2%B4%EA%B3%84%EC%A0%81-%EC%A7%84%EB%8B%A8%EB%B2%95-DBA-%ED%99%98%EA%B2%BD-%ED%8A%B9%ED%99%94#entry342comment</comments>
      <pubDate>Mon, 29 Jun 2026 06:52:50 +0900</pubDate>
    </item>
    <item>
      <title>2026년06월28일 주일예배 (이재훈목사님) - 1부</title>
      <link>https://isony.tistory.com/entry/2026%EB%85%8406%EC%9B%9428%EC%9D%BC-%EC%A3%BC%EC%9D%BC%EC%98%88%EB%B0%B0-%EC%9D%B4%EC%9E%AC%ED%9B%88%EB%AA%A9%EC%82%AC%EB%8B%98-1%EB%B6%80</link>
      <description>&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;2026년06월27일 주일예배 (이재훈목사님) - 1부&lt;/h2&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;주의 말씀 : 나를 따르라&amp;nbsp; (7)&lt;/h2&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;한적한 곳에서 다시 세워지는 삶&lt;/h2&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;성경 :&amp;nbsp; 마가복음(Mark) 1:32 ~ 38 말씀 (출처:우리말성경)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&amp;lt; 성경 &amp;gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;1:32 그날 저녁 해진 후에 사람들이 아픈 사람들과 귀신 들린 사람들을 전부 예수께로 데려왔습니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;1:33 온 동네 사람들이 문 앞에 모여들었습니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;1:34 예수께서는 온갖 병에 걸린 사람들을 많이 고쳐 주셨습니다. 그리고 많은 귀신들도 내쫓아 주셨습니다. 예수께서는 귀신들이 예수가 누구신지 알고 있기 때문에 귀신들이 말하는 것을 허락하지 않으셨습니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;1:35 매우 이른 새벽 아직 어둑어둑할 때 예수께서 일어나 외딴 곳으로 가셔서 기도하셨습니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;1:36 시몬과 그 일행들이 예수를 찾아 나섰습니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;1:37 그들이 마침내 예수를 만나자 소리쳐 말했습니다. &amp;ldquo;모든 사람들이 선생님을 찾고 있습니다.&amp;rdquo;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;1:38 예수께서 대답하셨습니다. &amp;ldquo;가까운 이웃 마을들에 가서도 말씀을 전파하도록 하자. 내가 이 일을 하러 왔다.&amp;rdquo;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&amp;lt; 예배 영상 &amp;gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;a href=&quot;https://youtu.be/PZG7oUOCnas&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://youtu.be/PZG7oUOCnas&lt;/a&gt;&lt;/b&gt;&lt;/p&gt;
&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignCenter&quot; data-video-host=&quot;youtube&quot; data-video-url=&quot;https://www.youtube.com/watch?v=PZG7oUOCnas&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/5oh7V/dJMb9g5llUh/cYk6CjYrwBNvhnilykBns1/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=554_130_714_304,https://scrap.kakaocdn.net/dn/bb0EDs/dJMb9jOxgnK/Jql6L4MxbsyB5ayqrZ44Y1/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=554_130_714_304,https://scrap.kakaocdn.net/dn/17OtQ/dJMb9kmmUe0/sjms4MiRAuESWDLvKY6VZk/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=554_130_714_304&quot; data-video-width=&quot;860&quot; data-video-height=&quot;484&quot; data-video-origin-width=&quot;860&quot; data-video-origin-height=&quot;484&quot; data-ke-mobilestyle=&quot;widthContent&quot; data-video-title=&quot;주일예배2026 06 28&quot; data-original-url=&quot;&quot;&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/PZG7oUOCnas&quot; width=&quot;860&quot; height=&quot;484&quot; frameborder=&quot;&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;figcaption style=&quot;display: none;&quot;&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>성경과 QT/주일예배(온누리교회)</category>
      <category>2026년06월28일 주일예배</category>
      <category>CGNTV</category>
      <category>나를 따르라</category>
      <category>다시 세워지는 삶</category>
      <category>마가복음 한적한 곳</category>
      <category>소니스토리</category>
      <category>우리말성경</category>
      <category>이재훈목사</category>
      <category>주일예배</category>
      <category>한적한 곳</category>
      <author>isony</author>
      <guid isPermaLink="true">https://isony.tistory.com/341</guid>
      <comments>https://isony.tistory.com/entry/2026%EB%85%8406%EC%9B%9428%EC%9D%BC-%EC%A3%BC%EC%9D%BC%EC%98%88%EB%B0%B0-%EC%9D%B4%EC%9E%AC%ED%9B%88%EB%AA%A9%EC%82%AC%EB%8B%98-1%EB%B6%80#entry341comment</comments>
      <pubDate>Sun, 28 Jun 2026 08:09:41 +0900</pubDate>
    </item>
    <item>
      <title>[Claude Code 활용 4편] CLAUDE.md 완벽 작성 가이드 - DBA&amp;middot;운영자용 템플릿 3종</title>
      <link>https://isony.tistory.com/entry/Claude-Code-%ED%99%9C%EC%9A%A9-4%ED%8E%B8-CLAUDEmd-%EC%99%84%EB%B2%BD-%EC%9E%91%EC%84%B1-%EA%B0%80%EC%9D%B4%EB%93%9C-DBA%C2%B7%EC%9A%B4%EC%98%81%EC%9E%90%EC%9A%A9-%ED%85%9C%ED%94%8C%EB%A6%BF-3%EC%A2%85</link>
      <description>&lt;h1&gt;[Claude Code 활용 4편] CLAUDE.md 완벽 작성 가이드 - DBA&amp;middot;운영자용 템플릿 3종&lt;/h1&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;테스트 환경&lt;/b&gt;: Claude Code v2.x, Opus 4.7 / Sonnet 4.6&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.whodo.net/entry/Claude-Code-%ED%99%9C%EC%9A%A9-1%ED%8E%B8-DBA%EC%99%80-%EC%84%9C%EB%B2%84-%EA%B4%80%EB%A6%AC%EC%9E%90%EA%B0%80-Claude-Code%EB%A5%BC-%EC%8D%A8%EC%95%BC-%ED%95%98%EB%8A%94-%EC%9D%B4%EC%9C%A0-%EC%84%A4%EC%B9%98%EB%B6%80%ED%84%B0-%EC%8B%A4%EC%A0%84-5%EA%B0%80%EC%A7%80-%ED%99%9C%EC%9A%A9%EA%B9%8C%EC%A7%80&quot;&gt;1편(입문)&lt;/a&gt;, &lt;a href=&quot;https://www.whodo.net/entry/Claude-Code-%ED%99%9C%EC%9A%A9-2%ED%8E%B8-%EC%85%B8-%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EC%99%80-%EC%9A%B4%EC%98%81-%EC%9E%90%EB%8F%99%ED%99%94%EC%97%90-Claude-Code-%ED%99%9C%EC%9A%A9%ED%95%98%EA%B8%B0-%EC%8B%A4%EC%A0%84-%EC%82%AC%EB%A1%80-5%EA%B0%80%EC%A7%80&quot;&gt;2편(셸 스크립트)&lt;/a&gt;, &lt;a href=&quot;https://www.whodo.net/entry/Claude-Code-%ED%99%9C%EC%9A%A9-3%ED%8E%B8-SQL%EA%B3%BC-Oracle-DBA-%EC%97%85%EB%AC%B4%EC%97%90-Claude-Code-%ED%99%9C%EC%9A%A9%ED%95%98%EA%B8%B0-%ED%8A%9C%EB%8B%9D%EB%B6%80%ED%84%B0-%ED%8A%B8%EB%9F%AC%EB%B8%94%EC%8A%88%ED%8C%85%EA%B9%8C%EC%A7%80&quot;&gt;3편(SQL&amp;middot;DBA)&lt;/a&gt;까지 Claude Code를 운영 업무에 활용하는 방법을 다뤘다면, 이번 4편은 &lt;b&gt;그 모든 활용의 효율을 2~3배로 끌어올리는 도구 &amp;mdash; CLAUDE.md&lt;/b&gt; 에 집중합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CLAUDE.md는 Claude Code의 &lt;b&gt;프로젝트 메모리 파일&lt;/b&gt;입니다. 모든 세션 시작 시 자동으로 로드되어 본인의 환경, 규칙, 표준을 Claude에게 매번 설명할 필요가 없게 해줍니다. 잘 만든 CLAUDE.md 한 장이 있으면:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;매번 환경 설명 불필요&lt;/b&gt; &amp;mdash; &quot;RHEL 8 환경이고 오라클 19c 운영 중인데...&quot;를 매번 안 써도 됨&lt;/li&gt;
&lt;li&gt;&lt;b&gt;표준 준수&lt;/b&gt; &amp;mdash; 본인 회사의 명명 규칙, 코드 스타일을 자동 적용&lt;/li&gt;
&lt;li&gt;&lt;b&gt;위험 작업 차단&lt;/b&gt; &amp;mdash; 운영 DB 직접 수정 같은 위험 행동 사전 차단&lt;/li&gt;
&lt;li&gt;&lt;b&gt;응답 품질 향상&lt;/b&gt; &amp;mdash; Claude가 본인 환경에 맞춘 답변 생성&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 글에서는 CLAUDE.md의 기본 원칙부터, &lt;b&gt;DBA&amp;middot;서버 관리자가 그대로 복사해서 사용할 수 있는 3가지 템플릿&lt;/b&gt;, 그리고 운영 환경에서 자주 발생하는 함정까지 정리했습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;CLAUDE.md란 무엇인가&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CLAUDE.md는 프로젝트 루트에 두는 &lt;b&gt;마크다운 형식의 메모리 파일&lt;/b&gt;입니다. Claude Code는 세션 시작 시 이 파일을 자동으로 읽어 본인의 컨텍스트로 사용합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;동작 방식&lt;/h3&gt;
&lt;pre class=&quot;vala&quot;&gt;&lt;code&gt;cd ~/work/ops-scripts
ls -la
# CLAUDE.md    &amp;larr; 이 파일이 있으면 자동 로드
# backup.sh
# monitor.sh

claude
# Claude가 CLAUDE.md를 읽고 &quot;RHEL 8, 오라클 19c 환경&quot;임을 인지한 상태로 시작
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;CLAUDE.md vs Skill vs Hook&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;세 도구의 역할이 헷갈리기 쉬워서 비교표로 정리합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;도구 로드 시점 준수율 용도&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;CLAUDE.md&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;항상 (매 세션)&lt;/td&gt;
&lt;td&gt;~70%&lt;/td&gt;
&lt;td&gt;환경, 규칙, 표준&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;.claude/rules/*.md&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;경로 패턴 매칭 시&lt;/td&gt;
&lt;td&gt;~70%&lt;/td&gt;
&lt;td&gt;특정 영역 상세 규칙&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;Skill&lt;/b&gt; (.claude/skills/SKILL.md)&lt;/td&gt;
&lt;td&gt;작업 매칭 시&lt;/td&gt;
&lt;td&gt;자동&lt;/td&gt;
&lt;td&gt;도메인 지식 모음&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;Hook&lt;/b&gt; (.claude/hooks/)&lt;/td&gt;
&lt;td&gt;도구 호출 시&lt;/td&gt;
&lt;td&gt;&lt;b&gt;100%&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;절대 금지/강제 사항&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;핵심&lt;/b&gt;: CLAUDE.md는 가이드라인이고, Hook은 강제 규칙입니다. 절대 어겨선 안 되는 규칙(예: rm -rf 금지)은 CLAUDE.md가 아닌 Hook으로 처리해야 합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;첫 CLAUDE.md 만들기 - 3가지 방법&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;방법 1: /init 명령 (가장 빠름)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude Code 안에서:&lt;/p&gt;
&lt;pre class=&quot;markdown&quot;&gt;&lt;code&gt;&amp;gt; /init
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude가 현재 폴더를 분석해서 자동으로 CLAUDE.md 초안을 생성합니다. 빌드 도구, 테스트 프레임워크, 코드 패턴을 인식해서 시작점을 제공합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;방법 2: # 명령으로 점진적 추가&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;작업 중에 메시지를 #로 시작하면 Claude가 그 지시를 자동으로 CLAUDE.md에 추가합니다.&lt;/p&gt;
&lt;pre class=&quot;clean&quot;&gt;&lt;code&gt;&amp;gt; # 모든 셸 스크립트는 #!/bin/bash로 시작하고 set -e 옵션 사용
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude가 이 규칙을 CLAUDE.md에 기록해서 다음 세션에도 적용됩니다. &lt;b&gt;운영 중에 발견한 규칙을 그때그때 누적&lt;/b&gt;하는 방식이라 매우 실용적입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;방법 3: 직접 작성&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본 템플릿(아래 섹션 참고)을 복사해서 시작하는 것이 가장 빠릅니다.&lt;/p&gt;
&lt;pre class=&quot;dos&quot;&gt;&lt;code&gt;cd ~/work/ops-scripts
vi CLAUDE.md
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;★ 좋은 CLAUDE.md의 5가지 원칙&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여러 시행착오를 거쳐 정리된 원칙입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;원칙 1: 짧게, 200줄 이하 ★ 가장 중요&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CLAUDE.md는 &lt;b&gt;매 세션 매 턴마다 컨텍스트 윈도우를 차지&lt;/b&gt;합니다. 길어질수록 Claude의 응답 품질이 측정 가능할 정도로 떨어집니다.&lt;/p&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;✅ 40줄짜리 정밀한 CLAUDE.md
❌ 400줄짜리 모든 것을 담은 CLAUDE.md
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;긴 내용은 .claude/rules/*.md로 분리하고 필요할 때만 로드되게 하세요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;원칙 2: 환경과 규칙 명시&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude가 본인 환경을 모르면 일반론으로 답합니다. 환경 정보가 있으면 환경 특화 답변이 나옵니다.&lt;/p&gt;
&lt;pre class=&quot;markdown&quot;&gt;&lt;code&gt;# 환경
- OS: Oracle Linux 8.8
- DB: Oracle 19c (PRODDB, TESTDB)
- 셸: bash
- 시간대: Asia/Seoul
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;원칙 3: 금지 사항을 명확히&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해야 할 것보다 &lt;b&gt;하면 안 되는 것&lt;/b&gt;을 먼저 적으세요. 운영 환경에서 사고 예방 효과가 큽니다.&lt;/p&gt;
&lt;pre class=&quot;markdown&quot;&gt;&lt;code&gt;# 절대 금지
- 운영 DB(PRODDB)에 직접 DML/DDL 실행
- DROP TABLE, TRUNCATE 자동 실행
- shutdown, reboot 명령
- 비밀번호 평문 파일 저장
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;원칙 4: 점진적 개선&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음부터 완벽한 CLAUDE.md를 만들려고 하지 마세요. 작게 시작해서 운영하면서 개선하는 게 표준입니다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;Day 1: 환경 정보 + 기본 규칙 (20줄)
Week 1: 사고 사례 반영해서 금지 사항 추가 (40줄)
Month 1: 코드 스타일과 워크플로우 정착 (80줄)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;원칙 5: 절대 룰은 Hook으로&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CLAUDE.md는 약 &lt;b&gt;70%만 준수&lt;/b&gt;됩니다. 절대 어겨선 안 되는 규칙은 Hook으로 강제하세요.&lt;/p&gt;
&lt;pre class=&quot;vala&quot;&gt;&lt;code&gt;# .claude/hooks/pre-tool-use.sh 예시
# rm -rf / 같은 위험 명령 즉시 차단
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;★ DBA&amp;middot;운영자용 CLAUDE.md 템플릿 3종 (복붙 가능)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 글의 핵심입니다. 본인 환경에 맞춰 수정해서 바로 사용하세요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;템플릿 1: 셸 스크립트 / 운영 자동화용&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.whodo.net/entry/Claude-Code-%ED%99%9C%EC%9A%A9-2%ED%8E%B8-%EC%85%B8-%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EC%99%80-%EC%9A%B4%EC%98%81-%EC%9E%90%EB%8F%99%ED%99%94%EC%97%90-Claude-Code-%ED%99%9C%EC%9A%A9%ED%95%98%EA%B8%B0-%EC%8B%A4%EC%A0%84-%EC%82%AC%EB%A1%80-5%EA%B0%80%EC%A7%80&quot;&gt;2편(셸 스크립트)&lt;/a&gt;에서 다룬 작업 환경에 최적화된 템플릿입니다.&lt;/p&gt;
&lt;pre class=&quot;markdown&quot;&gt;&lt;code&gt;# 운영 자동화 작업 환경

## 환경 정보
- OS: Oracle Linux 8.8 (RHEL 8 호환)
- 셸: bash 4.4+
- 사용자: oracle, root (sudo)
- 시간대: Asia/Seoul
- 패키지 관리: dnf

## 주요 경로
- 스크립트: /home/oracle/scripts
- 백업: /backup
- 로그: /var/log/ops
- 오라클 진단: /u01/app/oracle/diag

## 셸 스크립트 작성 규칙
- 항상 `#!/bin/bash`로 시작
- `set -euo pipefail` 사용 (에러 시 즉시 종료)
- 변수는 대문자, 함수는 소문자
- 모든 작업은 /var/log/ops.log에 timestamp와 함께 기록
- 날짜 형식: YYYYMMDD_HHMMSS

## cron 등록 규칙
- 새벽 1~5시 사이는 백업/배치, 9~18시는 운영 시간
- 같은 시간대 동시 실행 작업 피할 것
- 모든 cron 출력은 로그 파일로 리다이렉트

## 절대 금지
- `rm -rf` 와일드카드 사용 금지 (구체 경로 지정)
- 운영 데이터 디렉토리(/u01/oradata) 직접 수정 금지
- root 사용자로 오라클 작업 금지
- 비밀번호 스크립트 평문 저장 금지 (Wallet 사용)

## 도구
- 백업: rman, expdp
- 모니터링: lsnrctl, tnsping, ps, top, sar
- 로그 분석: grep, awk, sed
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;템플릿 2: 오라클 SQL/DBA 작업용&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.whodo.net/entry/Claude-Code-%ED%99%9C%EC%9A%A9-3%ED%8E%B8-SQL%EA%B3%BC-Oracle-DBA-%EC%97%85%EB%AC%B4%EC%97%90-Claude-Code-%ED%99%9C%EC%9A%A9%ED%95%98%EA%B8%B0-%ED%8A%9C%EB%8B%9D%EB%B6%80%ED%84%B0-%ED%8A%B8%EB%9F%AC%EB%B8%94%EC%8A%88%ED%8C%85%EA%B9%8C%EC%A7%80&quot;&gt;3편(SQL&amp;middot;DBA)&lt;/a&gt;에서 다룬 작업에 최적화된 템플릿입니다.&lt;/p&gt;
&lt;pre class=&quot;markdown&quot;&gt;&lt;code&gt;# Oracle DBA 작업 환경

## DB 정보
- Oracle 19c (19.21)
- 인스턴스: PRODDB (운영), TESTDB (테스트)
- 캐릭터셋: AL32UTF8
- 멀티테넌트: 사용 (CDB$ROOT + PROD_PDB, TEST_PDB)
- 시간대: Asia/Seoul

## 주요 스키마
- APP_USER: 애플리케이션 메인 (운영)
- BATCH_USER: 배치 작업
- READ_ONLY_USER: 모니터링 전용

## SQL 작성 규칙
- 키워드는 대문자, 객체명은 소문자
- 들여쓰기 4 spaces
- JOIN은 ANSI 표준 (LEFT JOIN, INNER JOIN)
- 변수 바인딩은 :name 형식 (positional 안 됨)
- 주석은 단일 라인 `--`로, 블록 주석 `/* */` 지양

## 권한 / 객체 관리
- 직접 GRANT 우선 (PL/SQL에서 ROLE 권한 무효화)
- 시노님은 PUBLIC보다 PRIVATE + GRANT 조합 권장
- 새 테이블 생성 시 인덱스 + COMMENT 필수

## DBMS_SCHEDULER 작업 표준
- job_type은 PLSQL_BLOCK 기본
- repeat_interval에 BYHOUR/BYMINUTE/BYSECOND 모두 명시
- start_date에 명시적 타임존(Asia/Seoul) 지정
- 작업 등록 후 SAVE STATE 적용 (PDB 환경)

## 절대 금지
- 운영 DB(PRODDB)에 다음 명령 절대 실행 금지:
  - `WHERE` 절 없는 UPDATE / DELETE
  - `DROP TABLE`, `TRUNCATE`
  - `ALTER SYSTEM` (DBA 매니저 사전 승인 필요)
- 비밀번호를 SQL 안에 평문으로 작성 금지
- 운영 DB 변경 작업은 항상 ROLLBACK SQL 함께 제시

## 자주 사용하는 진단 쿼리 위치
- ~/dba-toolkit/monitoring/ : 일상 점검
- ~/dba-toolkit/tuning/ : 성능 분석
- ~/dba-toolkit/troubleshoot/ : 장애 대응
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;템플릿 3: 통합 운영 환경 (가장 흔한 케이스)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 두 가지를 통합한 본격 운영용입니다. 본인 환경에 가장 가까운 템플릿입니다.&lt;/p&gt;
&lt;pre class=&quot;markdown&quot;&gt;&lt;code&gt;# 통합 운영 작업 환경

## 환경
- OS: Oracle Linux 8.8 / Windows Server 2019 (혼합)
- DB: Oracle 19c PRODDB, Oracle 21c TESTDB
- 시간대: Asia/Seoul
- 사용자: oracle (DB), root (시스템)

## 작업 디렉토리 구조
- ~/work/scripts/   : 운영 자동화 스크립트
- ~/work/sql/       : SQL 파일과 점검 쿼리
- ~/work/reports/   : 일일/주간 점검 보고서
- ~/dba-toolkit/    : 자주 쓰는 진단 쿼리 모음

## 운영 표준
- 모든 변경 작업은 개발 &amp;rarr; 테스트 &amp;rarr; 운영 단계 거침
- 운영 변경은 변경 SQL + ROLLBACK SQL 함께 제시
- 백업 확인: RMAN 마지막 백업이 24시간 이내인지
- 작업 시간: 일과 시간 외 (또는 점검 시간 활용)

## 절대 금지 (사고 방지)
- 운영 DB의 DROP, TRUNCATE, 단독 UPDATE/DELETE
- shutdown, reboot, systemctl stop 자동 실행
- 비밀번호 평문 저장 (Wallet, 환경변수 활용)
- 모든 사용자 대상 비밀번호 정책 일괄 변경

## 자주 사용하는 도구
- 셸: bash (Linux), PowerShell (Windows)
- DB 접속: sqlplus, sqlplus64
- 모니터링: lsnrctl, top, vmstat, iostat
- 백업: rman, expdp/impdp

## 응답 스타일
- 명령어는 코드 블록으로
- 위험한 작업은 실행 전 영향 범위 설명 먼저
- 운영 DB 변경 시 항상 &quot;이 작업은 운영 환경에 적용됩니다. 진행하시겠습니까?&quot;로 확인
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;계층 구조 활용 - .claude/rules/ 디렉토리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CLAUDE.md를 200줄 이하로 유지하려면 &lt;b&gt;상세 규칙을 별도 파일로 분리&lt;/b&gt;하세요. .claude/rules/ 폴더에 두면 경로 패턴 매칭으로 lazy 로드됩니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;구조 예시&lt;/h3&gt;
&lt;pre class=&quot;dos&quot;&gt;&lt;code&gt;project/
├── CLAUDE.md                    &amp;larr; 최소한의 환경/규칙 (40~80줄)
├── .claude/
│   └── rules/
│       ├── sql-style.md         &amp;larr; SQL 작성 상세 규칙
│       ├── backup-policy.md     &amp;larr; 백업 정책 상세
│       └── security.md          &amp;larr; 보안 정책 상세
└── scripts/
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;rules 파일 형식&lt;/h3&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;---
paths: [&quot;**/*.sql&quot;, &quot;**/*.pls&quot;]
---

# SQL 작성 상세 규칙

(SQL이나 PL/SQL 파일을 다룰 때만 이 내용이 로드됨)

## 인덱스 명명 규칙
- IDX_{테이블명_약자}_{컬럼명_약자}
- 유니크 인덱스는 UX_

## 트리거 작성 규칙
...
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;paths에 명시한 패턴에 매칭되는 파일을 다룰 때만 로드되어 컨텍스트를 절약합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;CLAUDE.md 점진적 개선 - 운영 사이클&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음 만든 CLAUDE.md를 어떻게 개선할지 단계별로 정리했습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Week 1: 시작&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본 환경 정보 + 절대 금지 규칙 3~5개로 시작 (20~40줄).&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Week 2~4: 사고/실수 반영&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude가 본인 의도와 다르게 동작한 경우, # 명령으로 즉시 CLAUDE.md에 규칙 추가.&lt;/p&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;&amp;gt; # PL/SQL 작성 시 ROLE 통한 권한 의존 금지, 직접 GRANT 확인 후 작성
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Month 1+: 코드 스타일 추가&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자주 사용하는 패턴, 명명 규칙, 표준 절차를 누적.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Month 3+: 분리 시점&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CLAUDE.md가 200줄을 넘으면 .claude/rules/로 영역별 분리 시작.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;자주 발생하는 함정 5가지&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;함정 1: 너무 길게 작성&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;200~300줄 넘어가면 Claude의 응답 품질이 떨어집니다. 짧게 유지.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;함정 2: 추상적 규칙&lt;/h3&gt;
&lt;pre class=&quot;1c&quot;&gt;&lt;code&gt;❌ &quot;코드를 깨끗하게 작성하세요&quot;  &amp;larr; 추상적
✅ &quot;함수는 30줄 이하, 변수명은 snake_case&quot;  &amp;larr; 구체적
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구체적이고 측정 가능한 규칙이어야 Claude가 적용합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;함정 3: CLAUDE.md만 믿기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CLAUDE.md는 70% 준수입니다. 정말 중요한 규칙(보안, 운영 DB 보호)은 Hook으로 강제하세요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;함정 4: 한 번 만들고 방치&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;운영 환경은 계속 변합니다. 분기에 한 번 정도 CLAUDE.md를 리뷰하고 갱신하세요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;함정 5: 개인 사용자 레벨 누락&lt;/h3&gt;
&lt;pre class=&quot;objectivec&quot;&gt;&lt;code&gt;~/.claude/CLAUDE.md         # 모든 프로젝트 공통 규칙
project1/CLAUDE.md          # 프로젝트별 규칙
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자주 사용하는 개인 표준은 ~/.claude/CLAUDE.md에 두면 모든 프로젝트에서 적용됩니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;실전 점검 명령&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;본인의 CLAUDE.md 품질을 Claude에게 검토받을 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;&amp;gt; 현재 CLAUDE.md를 검토하고 다음을 평가해 줘:
  1. 200줄 이하인가? 줄여야 할 영역은?
  2. 추상적 규칙 &amp;rarr; 구체적 규칙으로 바꿔야 할 것
  3. 절대 금지 항목 중 Hook으로 옮겨야 할 것
  4. DBA&amp;middot;운영자 관점에서 빠진 핵심 규칙
  5. 개선 우선순위 TOP 5
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 점검을 분기에 한 번 정도 실행하면 CLAUDE.md가 자연스럽게 진화합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;시리즈 마무리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude Code 시리즈 4편에 걸쳐 &lt;b&gt;DBA&amp;middot;서버 관리자가 Claude Code를 활용하는 방법&lt;/b&gt;을 다뤘습니다. 핵심을 한 번 더 정리하면:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;1편&lt;/b&gt;: Claude Code는 운영자에게도 강력한 도구이며 5가지 핵심 활용이 가능&lt;/li&gt;
&lt;li&gt;&lt;b&gt;2편&lt;/b&gt;: 셸 스크립트와 운영 자동화에서 사이클을 한 곳에서 끝낼 수 있음&lt;/li&gt;
&lt;li&gt;&lt;b&gt;3편&lt;/b&gt;: SQL&amp;middot;DBA 업무에서 매일 1~2시간 절약 가능&lt;/li&gt;
&lt;li&gt;&lt;b&gt;4편 (이 글)&lt;/b&gt;: CLAUDE.md가 모든 활용의 효율을 2~3배로 끌어올리는 핵심&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CLAUDE.md는 단순한 메모리 파일이 아니라 &lt;b&gt;본인의 운영 표준을 코드로 만든 자산&lt;/b&gt;입니다. 잘 만든 CLAUDE.md 하나가 매일의 작업 효율, 사고 예방, 표준 준수를 동시에 해결합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;본인 환경에 맞는 CLAUDE.md를 만들고 점진적으로 개선해 나가세요. 6개월 후 돌아보면 &lt;b&gt;운영 노하우가 그대로 텍스트로 축적된 가장 가치 있는 파일&lt;/b&gt;이 되어 있을 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비슷한 CLAUDE.md 활용 경험이나 더 좋은 템플릿이 있다면 댓글로 공유해 주세요. 다른 운영자들과 노하우를 함께 쌓아가면 좋겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>AI (Claude 활용)/Claude Code 시리즈</category>
      <category>AI 코딩 도구 표준</category>
      <category>Claude Code 메모리</category>
      <category>Claude Code 베스트 프랙티스</category>
      <category>Claude Code 설정</category>
      <category>CLAUDE.md 작성법</category>
      <category>claude/rules 사용법</category>
      <category>DBA CLAUDE.md</category>
      <category>소니스토리</category>
      <category>운영자 CLAUDE.md</category>
      <category>팀 표준 AI</category>
      <author>isony</author>
      <guid isPermaLink="true">https://isony.tistory.com/340</guid>
      <comments>https://isony.tistory.com/entry/Claude-Code-%ED%99%9C%EC%9A%A9-4%ED%8E%B8-CLAUDEmd-%EC%99%84%EB%B2%BD-%EC%9E%91%EC%84%B1-%EA%B0%80%EC%9D%B4%EB%93%9C-DBA%C2%B7%EC%9A%B4%EC%98%81%EC%9E%90%EC%9A%A9-%ED%85%9C%ED%94%8C%EB%A6%BF-3%EC%A2%85#entry340comment</comments>
      <pubDate>Fri, 26 Jun 2026 07:36:14 +0900</pubDate>
    </item>
    <item>
      <title>[오라클 에러] ORA-01555 snapshot too old - 5가지 원인과 해결방법 (UNDO 일관성 읽기 모델 완벽 정리)</title>
      <link>https://isony.tistory.com/entry/%EC%98%A4%EB%9D%BC%ED%81%B4-%EC%97%90%EB%9F%AC-ORA-01555-snapshot-too-old-5%EA%B0%80%EC%A7%80-%EC%9B%90%EC%9D%B8%EA%B3%BC-%ED%95%B4%EA%B2%B0%EB%B0%A9%EB%B2%95-UNDO-%EC%9D%BC%EA%B4%80%EC%84%B1-%EC%9D%BD%EA%B8%B0-%EB%AA%A8%EB%8D%B8-%EC%99%84%EB%B2%BD-%EC%A0%95%EB%A6%AC</link>
      <description>&lt;h1&gt;[오라클 에러] ORA-01555 snapshot too old - 5가지 원인과 해결방법 (UNDO 일관성 읽기 모델 완벽 정리)&lt;/h1&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;테스트 환경&lt;/b&gt;: Oracle 11g / 12c / 19c / 21c&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;월말 결산 시즌, 새벽 4시. 4시간 동안 돌던 결산 리포트가 마지막 단계에서 &lt;b&gt;ORA-01555: snapshot too old&lt;/b&gt; 로 실패합니다. 처음부터 다시 돌리면 또 4시간. 그동안 운영팀과 회계팀에서 전화가 빗발칩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ORA-01555는 DBA가 가장 자주 마주치면서도 가장 자주 오해하는 에러입니다. &lt;b&gt;&quot;UNDO 늘리면 된다&quot;&lt;/b&gt; 는 단순한 답은 절반만 맞습니다. 어떨 때는 UNDO를 10배 늘려도 재발하고, 어떨 때는 SQL 한 줄만 바꿔도 해결됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 글에서는 ORA-01555의 본질인 &lt;b&gt;읽기 일관성(Read Consistency) 모델&lt;/b&gt;부터 시작해서, 5가지 원인을 진단하고 근본 해결하는 방법까지 정리했습니다. 특히 &lt;b&gt;Fetch Across Commit&lt;/b&gt;, &lt;b&gt;LOB 세그먼트 케이스&lt;/b&gt;, &lt;b&gt;expdp FLASHBACK_TIME&lt;/b&gt;같이 한국어 자료에서 잘 다루지 않는 영역까지 포함했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;장애 대응 중이라면 &lt;b&gt;&lt;u&gt;긴급 응급 처치&lt;/u&gt;&lt;/b&gt;부터 보세요.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;에러 메시지 전문&lt;/h2&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;ORA-01555: snapshot too old: rollback segment number XX with name &quot;_SYSSMU...&quot; too small
ORA-01555: 스냅샷이 너무 오래되었습니다: %s 롤백 세그먼트 번호가 너무 작습니다
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;19c 이상에서는 다음과 같이 더 상세한 메시지가 나오기도 합니다.&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;ORA-01555: snapshot too old: rollback segment number XX with name &quot;_SYSSMU...&quot; too small
ORA-22924: snapshot too old (LOB 케이스)
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ORA-22924는 LOB 관련 ORA-01555입니다. 일반 ORA-01555와 원인이 완전히 다르므로 구분해야 합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;★ ORA-01555의 본질 - 읽기 일관성(Read Consistency) 모델&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다른 블로그에서 잘 다루지 않는 부분이지만, 이걸 이해해야 ORA-01555를 진짜로 해결할 수 있습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;일관성 읽기란&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오라클은 &lt;b&gt;트랜잭션이 시작된 시점&lt;/b&gt;의 데이터를 일관되게 보여주는 보장을 제공합니다. 쿼리가 4시간 걸려도 그 4시간 동안 다른 사용자가 데이터를 바꿔도, 쿼리는 &lt;b&gt;시작 시점&lt;/b&gt;의 데이터를 봅니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;어떻게 가능한가&lt;/h3&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;[Time 10:00] 리포트 쿼리 시작
   &amp;darr; &quot;이 시점의 데이터로 끝까지 본다&quot;
   
[Time 10:30] OLTP가 row X를 update &amp;rarr; COMMIT
   &amp;darr; 오라클은 row X의 변경 전 값을 UNDO에 보관
   
[Time 12:00] 리포트 쿼리가 row X에 도달
   &amp;darr; &quot;10:00 시점 값&quot;이 필요함
   &amp;darr; UNDO에서 변경 전 값을 가져옴
   &amp;darr; ✅ 일관된 결과 반환
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;ORA-01555가 발생하는 순간&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;[Time 10:00] 리포트 쿼리 시작
[Time 10:30] OLTP가 row X update &amp;rarr; COMMIT
[Time 11:00] UNDO_RETENTION (15분) 만료 &amp;rarr; UNDO 공간 재사용
[Time 12:00] 리포트가 row X에 도달
   &amp;darr; &quot;10:00 시점 값&quot;이 필요한데
   &amp;darr; UNDO에 그 값이 없음 (덮어쓰여짐)
   &amp;darr; ❌ ORA-01555 발생
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;한 줄 요약&lt;/b&gt;: ORA-01555는 &lt;b&gt;&quot;필요한 과거 데이터의 UNDO가 사라져서 일관성을 보장할 수 없음&quot;&lt;/b&gt; 의 에러입니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;UNDO 세그먼트의 3가지 상태&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;UNDO 영역의 각 블록은 다음 중 하나의 상태를 가집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상태 의미 재사용 가능?&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;ACTIVE&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;현재 진행 중인 트랜잭션이 사용 중&lt;/td&gt;
&lt;td&gt;❌ 절대 불가&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;UNEXPIRED&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;커밋됐지만 일관성 읽기를 위해 보관 (UNDO_RETENTION 기간 내)&lt;/td&gt;
&lt;td&gt;△ 공간 부족 시 재사용&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;EXPIRED&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;UNDO_RETENTION 지남&lt;/td&gt;
&lt;td&gt;✅ 자유롭게 재사용&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;핵심&lt;/b&gt;: ACTIVE는 절대 못 건드리지만, &lt;b&gt;UNEXPIRED는 공간이 부족하면 재사용&lt;/b&gt;될 수 있습니다. 이 경우 ORA-01555가 발생합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;상태 확인 쿼리&lt;/h3&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;SELECT tablespace_name, status, 
       ROUND(SUM(bytes)/1024/1024, 2) AS mb
FROM   dba_undo_extents
GROUP  BY tablespace_name, status
ORDER  BY tablespace_name, status;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;출력 예시:&lt;/p&gt;
&lt;pre class=&quot;lsl&quot;&gt;&lt;code&gt;TABLESPACE_NAME  STATUS      MB
---------------  ---------   --------
UNDOTBS1         ACTIVE      120
UNDOTBS1         UNEXPIRED   3500
UNDOTBS1         EXPIRED     50    &amp;larr; 이게 너무 작으면 위험
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;EXPIRED 공간이 거의 없으면 오라클이 UNEXPIRED를 침범하기 시작합니다. 이게 ORA-01555의 직접적 신호입니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;긴급 응급 처치&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;운영 중에 ORA-01555가 자주 발생하고 있다면 우선 다음을 시도하세요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;즉시 조치 (5분 안에)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1) UNDO_RETENTION 늘리기&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;-- 현재 값 확인
SHOW PARAMETER undo_retention

-- 1시간(3600초)으로 증가
ALTER SYSTEM SET undo_retention = 3600 SCOPE=BOTH;
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;주의&lt;/b&gt;: 이는 &quot;목표값&quot;일 뿐입니다. UNDO 테이블스페이스 공간이 부족하면 오라클은 이 값을 무시합니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2) UNDO 테이블스페이스 확장&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- 자동 확장 활성화
ALTER DATABASE DATAFILE '/u01/oradata/db1/undotbs01.dbf'
    AUTOEXTEND ON NEXT 100M MAXSIZE 32G;

-- 또는 직접 추가
ALTER DATABASE DATAFILE '/u01/oradata/db1/undotbs01.dbf' 
    RESIZE 10G;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3) RETENTION GUARANTEE 활성화 (신중히)&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- UNDO 테이블스페이스 이름 확인
SELECT tablespace_name FROM dba_tablespaces WHERE contents = 'UNDO';

-- 보장 모드 활성화
ALTER TABLESPACE UNDOTBS1 RETENTION GUARANTEE;
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;경고&lt;/b&gt;: RETENTION GUARANTEE는 UNDO 데이터를 절대 덮어쓰지 않도록 보장하지만, &lt;b&gt;공간 부족 시 새 트랜잭션이 ORA-30036으로 실패&lt;/b&gt;할 수 있습니다. 일관성 vs 가용성의 트레이드오프를 이해하고 사용하세요.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이걸로 응급은 처리되지만, 근본 원인은 따로 진단해야 합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;빠른 진단 체크리스트&lt;/h2&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- 1) 최근 ORA-01555 발생 횟수
SELECT SUM(ssolderrcnt) AS ora_1555_count
FROM   v$undostat;

-- 2) 최장 쿼리 시간 (지난 7일)
SELECT MAX(maxquerylen) AS max_query_seconds
FROM   v$undostat;

-- 3) 현재 UNDO 사용 압력
SELECT MAX(unxpstealcnt) AS undo_pressure_indicator
FROM   v$undostat;

-- 4) UNDO 세그먼트별 상태
SELECT status, COUNT(*), ROUND(SUM(bytes)/1024/1024, 2) AS mb
FROM   dba_undo_extents
GROUP  BY status;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;maxquerylen이 현재 undo_retention보다 크면 사고 발생률이 높습니다. unxpstealcnt가 0이 아니면 이미 UNEXPIRED 침범이 시작된 상태입니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;원인 1: UNDO_RETENTION이 최장 쿼리보다 짧음 (가장 흔함)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ORA-01555의 60% 이상이 이 케이스입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;진단&lt;/h3&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- 현재 설정
SHOW PARAMETER undo_retention   -- 예: 900 (15분)

-- 실제 최장 쿼리 시간
SELECT MAX(maxquerylen) FROM v$undostat;   -- 예: 14400 (4시간)
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설정 15분 vs 실제 최장 4시간 &amp;rarr; 사고 100% 발생.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;해결&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;UNDO_RETENTION을 최장 쿼리보다 충분히 길게 설정:&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;-- 4시간(14400초) + 여유 1시간 = 5시간으로 설정
ALTER SYSTEM SET undo_retention = 18000 SCOPE=BOTH;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;실무 권장값:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;OLTP 중심: 3600 ~ 7200초 (1~2시간)&lt;/li&gt;
&lt;li&gt;배치/리포트 환경: 21600초 이상 (6시간)&lt;/li&gt;
&lt;li&gt;DW: 43200초 이상 (12시간)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;TUNED_UNDORETENTION 확인 (★ 11g+)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;11g부터 오라클이 자동으로 UNDO 보존 기간을 조정합니다.&lt;/p&gt;
&lt;pre class=&quot;n1ql&quot;&gt;&lt;code&gt;SELECT MIN(tuned_undoretention) AS effective_min,
       MAX(tuned_undoretention) AS effective_max
FROM   v$undostat;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;tuned_undoretention이 설정한 undo_retention보다 작다면 오라클이 공간 부족 때문에 자동 단축한 것입니다. 이 경우 UNDO 테이블스페이스 자체를 늘려야 합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;원인 2: UNDO 테이블스페이스 자체가 작음&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;UNDO_RETENTION은 충분한데 UNDO 공간이 부족한 케이스입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;진단&lt;/h3&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- UNDO 테이블스페이스 크기와 자동 확장 여부
SELECT tablespace_name, file_name, autoextensible,
       ROUND(bytes/1024/1024, 2) AS size_mb,
       ROUND(maxbytes/1024/1024, 2) AS max_mb
FROM   dba_data_files
WHERE  tablespace_name LIKE 'UNDO%';

-- 사용량
SELECT tablespace_name,
       ROUND(SUM(CASE WHEN status = 'EXPIRED' THEN bytes ELSE 0 END)/1024/1024, 2) AS expired_mb,
       ROUND(SUM(CASE WHEN status = 'UNEXPIRED' THEN bytes ELSE 0 END)/1024/1024, 2) AS unexpired_mb,
       ROUND(SUM(CASE WHEN status = 'ACTIVE' THEN bytes ELSE 0 END)/1024/1024, 2) AS active_mb
FROM   dba_undo_extents
GROUP  BY tablespace_name;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;UNDO 사이즈 산정 공식&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;필요한 UNDO 크기 = 최장 쿼리 시간 &amp;times; 초당 UNDO 생성량 &amp;times; 안전계수(1.5~2)
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- 초당 UNDO 생성량
SELECT MAX(undoblks / ((end_time - begin_time) * 24 * 3600)) AS undo_blocks_per_sec,
       ROUND(MAX(undoblks / ((end_time - begin_time) * 24 * 3600)) * 8192 / 1024 / 1024, 2) AS undo_mb_per_sec
FROM   v$undostat;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예시: 초당 UNDO 1MB &amp;times; 최장 쿼리 4시간(14400초) &amp;times; 1.5 = &lt;b&gt;21.6GB&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이보다 작으면 UNDO 부족이 발생할 수 있습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;해결&lt;/h3&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- 데이터파일 추가
ALTER TABLESPACE UNDOTBS1 ADD DATAFILE 
    '/u01/oradata/db1/undotbs02.dbf' SIZE 10G AUTOEXTEND ON;

-- 또는 기존 파일 자동 확장
ALTER DATABASE DATAFILE '/u01/oradata/db1/undotbs01.dbf'
    AUTOEXTEND ON NEXT 1G MAXSIZE 32G;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;★ 원인 3: Fetch Across Commit (코드 사이드 문제)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 케이스는 한국어 자료에 깊이 다루지 않는 영역인데, &lt;b&gt;개발자 코드의 근본 문제&lt;/b&gt;입니다. UNDO를 아무리 늘려도 이 패턴이 있으면 ORA-01555가 재발합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;문제 패턴&lt;/h3&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- ❌ Fetch Across Commit 안티 패턴
DECLARE
    CURSOR c_data IS SELECT * FROM big_table;
BEGIN
    FOR rec IN c_data LOOP
        UPDATE big_table SET col = new_value WHERE id = rec.id;
        COMMIT;  -- &amp;larr; 같은 테이블의 update를 매 row commit
    END LOOP;
END;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;왜 ORA-01555가 발생하나&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;커서는 처음 OPEN될 때 SCN(System Change Number)을 기록&lt;/li&gt;
&lt;li&gt;같은 테이블에 UPDATE + COMMIT 반복 &amp;rarr; UNDO 폭증&lt;/li&gt;
&lt;li&gt;UNDO_RETENTION 지나면서 UNDO 재사용&lt;/li&gt;
&lt;li&gt;커서가 후반 row에 도달했을 때 처음 SCN 시점의 데이터 재구성 불가 &amp;rarr; ORA-01555&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;해결 - BULK COLLECT 패턴&lt;/h3&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;-- ✅ 권장 패턴
DECLARE
    CURSOR c_data IS SELECT id, col FROM big_table;
    TYPE t_id IS TABLE OF big_table.id%TYPE;
    TYPE t_col IS TABLE OF big_table.col%TYPE;
    l_id t_id;
    l_col t_col;
BEGIN
    OPEN c_data;
    LOOP
        FETCH c_data BULK COLLECT INTO l_id, l_col LIMIT 1000;
        EXIT WHEN l_id.COUNT = 0;
        
        FORALL i IN 1..l_id.COUNT
            UPDATE big_table SET col = new_value WHERE id = l_id(i);
        
        COMMIT;  -- 1000개 단위 commit
    END LOOP;
    CLOSE c_data;
END;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또는 커서를 다시 열어서 처리하는 방식:&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- 청크 단위로 분리 처리
BEGIN
    LOOP
        UPDATE big_table SET col = new_value
        WHERE  rownum &amp;lt;= 1000 AND processed = 'N';
        
        EXIT WHEN SQL%ROWCOUNT = 0;
        COMMIT;
    END LOOP;
END;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;식별 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;운영 중 발생한 ORA-01555의 어떤 SQL이 원인인지 찾기:&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- 장기 실행 SQL 확인
SELECT sql_id, executions, 
       ROUND(elapsed_time/1000000, 2) AS elapsed_sec,
       SUBSTR(sql_text, 1, 100) AS sql_preview
FROM   v$sqlarea
WHERE  elapsed_time/1000000 &amp;gt; 900  -- 15분 이상
ORDER  BY elapsed_time DESC
FETCH  FIRST 10 ROWS ONLY;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;★ 원인 4: LOB 세그먼트의 ORA-01555 (특수 케이스)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LOB(CLOB/BLOB) 컬럼이 있는 테이블에서 발생하는 ORA-01555는 &lt;b&gt;UNDO 테이블스페이스를 사용하지 않습니다&lt;/b&gt;. 일반 UNDO 설정을 아무리 늘려도 해결 안 됩니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;무엇이 다른가&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LOB는 자체적으로 UNDO를 관리합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모드 파라미터 의미&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;PCTVERSION&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;0~100&lt;/td&gt;
&lt;td&gt;LOB 세그먼트의 N%를 undo로 사용 (기본 10%)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;RETENTION&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;(시간)&lt;/td&gt;
&lt;td&gt;UNDO_RETENTION 값을 사용&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;둘 중 하나만&lt;/b&gt; 사용합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;진단&lt;/h3&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;-- LOB 컬럼의 retention 설정 확인
SELECT owner, table_name, column_name, segment_name, 
       pctversion, retention, cache, logging
FROM   dba_lobs
WHERE  owner = '소유자명'
  AND  table_name = '테이블명';
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PCTVERSION이 10이면 LOB 세그먼트의 10%만 undo로 사용 &amp;mdash; DML이 많으면 부족합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;해결&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;PCTVERSION 증가:&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;ALTER TABLE my_table MODIFY LOB(lob_column) (PCTVERSION 30);
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;RETENTION으로 변경:&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;ALTER TABLE my_table MODIFY LOB(lob_column) (RETENTION);
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;RETENTION 모드는 UNDO_RETENTION 파라미터를 그대로 사용해서 일관성을 제공합니다. 대용량 LOB DML 환경에서는 RETENTION 모드를 권장합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;★ 원인 5: expdp의 FLASHBACK_TIME / FLASHBACK_SCN&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터펌프 export 중에 ORA-01555가 발생하는 케이스입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;무엇이 문제인가&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;expdp는 일관된 export를 위해 시작 시점의 SCN을 사용합니다. 큰 테이블을 export하는 동안 다른 트랜잭션이 많이 발생하면 UNDO 부족으로 ORA-01555가 발생합니다.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;# expdp가 자동으로 사용하는 옵션
expdp user/pwd schemas=APP_USER \
      flashback_time=systimestamp \
      directory=DATA_PUMP_DIR \
      dumpfile=app.dmp
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;해결&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;방법 1: 시간 분산 export&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스키마를 나눠서 작은 단위로 export.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;expdp user/pwd tables=APP_USER.big_table_1 \
      flashback_time=systimestamp ...

expdp user/pwd tables=APP_USER.big_table_2 \
      flashback_time=systimestamp ...
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;방법 2: 한가한 시간대로 이동&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DML이 적은 시간(새벽 2~4시)에 실행. UNDO 압력이 적어 ORA-01555 발생 가능성 감소.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;방법 3: UNDO 일시적 증가&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;export 직전 UNDO 늘리고 끝나면 원복.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;-- export 전
ALTER SYSTEM SET undo_retention = 14400 SCOPE=BOTH;

-- export 후
ALTER SYSTEM SET undo_retention = 3600 SCOPE=BOTH;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;운영 환경 권장 표준&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;장기 안정 운영을 위한 권장 설정입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;UNDO 설정 표준&lt;/h3&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;-- 1) 자동 UNDO 관리 활성화 (11g+ 기본)
ALTER SYSTEM SET undo_management = 'AUTO' SCOPE=SPFILE;

-- 2) UNDO_RETENTION을 최장 쿼리보다 충분히 길게
ALTER SYSTEM SET undo_retention = 7200 SCOPE=BOTH;  -- 2시간

-- 3) UNDO 테이블스페이스 자동 확장
ALTER DATABASE DATAFILE '/path/undotbs01.dbf' 
    AUTOEXTEND ON NEXT 1G MAXSIZE 32G;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;모니터링 쿼리 (일일 점검)&lt;/h3&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- 1) ORA-01555 발생 추세 (7일)
SELECT TO_CHAR(begin_time, 'YYYY-MM-DD HH24') AS hour,
       MAX(ssolderrcnt) AS ora_1555_count,
       MAX(maxquerylen) AS max_query_sec
FROM   v$undostat
WHERE  begin_time &amp;gt; SYSDATE - 7
GROUP  BY TO_CHAR(begin_time, 'YYYY-MM-DD HH24')
HAVING MAX(ssolderrcnt) &amp;gt; 0
ORDER  BY hour DESC;

-- 2) UNDO 압력 지표
SELECT TO_CHAR(begin_time, 'YYYY-MM-DD HH24') AS hour,
       unxpstealcnt   AS unexpired_steal,
       expstealcnt    AS expired_steal,
       expblkreucnt   AS expired_reuse
FROM   v$undostat
WHERE  unxpstealcnt &amp;gt; 0
   OR  expstealcnt &amp;gt; 0;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;권장 알림 임계값&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지표 경고 위험&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;ssolderrcnt (시간당 ORA-01555 수)&lt;/td&gt;
&lt;td&gt;&amp;gt;= 1&lt;/td&gt;
&lt;td&gt;&amp;gt;= 5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;UNEXPIRED steal 발생&lt;/td&gt;
&lt;td&gt;알림&lt;/td&gt;
&lt;td&gt;즉시 조치&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;UNDO 사용률&lt;/td&gt;
&lt;td&gt;70%&lt;/td&gt;
&lt;td&gt;90%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TUNED_UNDORETENTION &amp;lt; UNDO_RETENTION&lt;/td&gt;
&lt;td&gt;알림&lt;/td&gt;
&lt;td&gt;RETENTION GUARANTEE 검토&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;그래도 안 풀린다면&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 5가지로도 해결되지 않는 드문 케이스:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Oracle 버그&lt;/b&gt;: 일부 패치 버전에서 ORA-01555 false alarm 발생 (My Oracle Support Doc 269814.1)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;RAC 환경의 GES 락&lt;/b&gt;: 노드 간 동기화 지연으로 발생&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Active Data Guard에서 standby query&lt;/b&gt;: max_data_delay 설정 영향&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Flashback Database 활성화&lt;/b&gt;: Flashback log와 UNDO 상호 작용&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;마무리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ORA-01555는 &quot;UNDO 부족&quot;이라는 표면적 메시지와 달리, &lt;b&gt;실제로는 5가지 다른 원인이 있으며 각각 다르게 해결&lt;/b&gt;해야 합니다. 무작정 UNDO를 늘리기 전에 다음을 점검하세요.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;v$undostat으로 실제 최장 쿼리 시간 측정&lt;/b&gt; &amp;mdash; UNDO_RETENTION이 충분한가&lt;/li&gt;
&lt;li&gt;&lt;b&gt;UNDO 테이블스페이스 사이즈 산정 공식&lt;/b&gt; 적용 &amp;mdash; 단순 추측 금지&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Fetch Across Commit 패턴 코드 리뷰&lt;/b&gt; &amp;mdash; UNDO 늘려도 해결 안 되는 케이스&lt;/li&gt;
&lt;li&gt;&lt;b&gt;LOB 컬럼이 있다면 PCTVERSION/RETENTION 별도 점검&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;expdp 시 UNDO 일시 증가 또는 시간 분산&lt;/b&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 효과적인 예방은 &lt;b&gt;개발 단계에서 BULK COLLECT 패턴을 표준화&lt;/b&gt;하는 것입니다. PL/SQL 코드 리뷰 항목에 &quot;Fetch Across Commit 없는가&quot;를 포함시키면 운영에 들어간 후 발생하는 ORA-01555의 상당 부분을 막을 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비슷한 케이스를 겪으셨거나, 위 방법으로도 해결되지 않은 상황이 있다면 댓글로 공유해 주세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>DBA 실무/Oracle(오라클)</category>
      <category>export ora-01555</category>
      <category>Fetch Across Commit</category>
      <category>LOB PCTVERSION</category>
      <category>ORA-0155 원인</category>
      <category>ORA-01555 해결</category>
      <category>ORA-22924</category>
      <category>TUNED_UNDORETENTION</category>
      <category>UNDO 입력</category>
      <category>V$UNDOSTAT</category>
      <category>소니스토리</category>
      <author>isony</author>
      <guid isPermaLink="true">https://isony.tistory.com/339</guid>
      <comments>https://isony.tistory.com/entry/%EC%98%A4%EB%9D%BC%ED%81%B4-%EC%97%90%EB%9F%AC-ORA-01555-snapshot-too-old-5%EA%B0%80%EC%A7%80-%EC%9B%90%EC%9D%B8%EA%B3%BC-%ED%95%B4%EA%B2%B0%EB%B0%A9%EB%B2%95-UNDO-%EC%9D%BC%EA%B4%80%EC%84%B1-%EC%9D%BD%EA%B8%B0-%EB%AA%A8%EB%8D%B8-%EC%99%84%EB%B2%BD-%EC%A0%95%EB%A6%AC#entry339comment</comments>
      <pubDate>Wed, 24 Jun 2026 07:55:15 +0900</pubDate>
    </item>
    <item>
      <title>[오라클 운영] Oracle 12c 멀티테넌트(CDB/PDB) 운영 가이드 - 상태 관리부터 Unplug/Plug까지</title>
      <link>https://isony.tistory.com/entry/%EC%98%A4%EB%9D%BC%ED%81%B4-%EC%9A%B4%EC%98%81-Oracle-12c-%EB%A9%80%ED%8B%B0%ED%85%8C%EB%84%8C%ED%8A%B8CDBPDB-%EC%9A%B4%EC%98%81-%EA%B0%80%EC%9D%B4%EB%93%9C-%EC%83%81%ED%83%9C-%EA%B4%80%EB%A6%AC%EB%B6%80%ED%84%B0-UnplugPlug%EA%B9%8C%EC%A7%80</link>
      <description>&lt;h1&gt;[오라클 운영] Oracle 12c 멀티테넌트(CDB/PDB) 운영 가이드 - 상태 관리부터 Unplug/Plug까지&lt;/h1&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;테스트 환경&lt;/b&gt;: Oracle 12c / 19c / 21c / 23ai&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;12c부터 도입된 멀티테넌트 아키텍처는 19c에서 사실상 표준이 되었고, 21c부터는 비-CDB(non-CDB) 모드가 desupport되어 &lt;b&gt;CDB가 유일한 옵션&lt;/b&gt;입니다. 이제 오라클을 다룬다면 CDB/PDB 환경을 피할 수 없어요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 한국어 운영 자료의 상당수가 11g 시절 비-CDB 환경 기준이라, 처음 CDB 환경을 마주한 DBA는 다음과 같은 질문에 막힙니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;접속했더니 갑자기 객체가 안 보임 (다른 컨테이너에 있는 줄도 모르고)&lt;/li&gt;
&lt;li&gt;DB 재시작 후 &lt;a href=&quot;https://www.whodo.net/entry/%EC%98%A4%EB%9D%BC%ED%81%B4-%EC%97%90%EB%9F%AC-ORA-12514-TNS%EB%A6%AC%EC%8A%A4%EB%84%88%EA%B0%80-%EC%84%9C%EB%B9%84%EC%8A%A4%EB%A5%BC-%EC%95%8C%EC%A7%80-%EB%AA%BB%ED%95%A8-5%EA%B0%80%EC%A7%80-%EC%9B%90%EC%9D%B8%EA%B3%BC-%ED%95%B4%EA%B2%B0%EB%B0%A9%EB%B2%95-PDB-%ED%99%98%EA%B2%BD-%ED%8F%AC%ED%95%A8&quot;&gt;ORA-12514&lt;/a&gt; 발생 (이전 글에서 다룬 PDB MOUNTED 상태)&lt;/li&gt;
&lt;li&gt;사용자를 만들었더니 ORA-65096: invalid common user... 발생&lt;/li&gt;
&lt;li&gt;PDB를 다른 서버로 옮기고 싶은데 방법 모름&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 글에서는 CDB/PDB의 기본 개념부터 시작해, &lt;b&gt;상태 관리(SAVE STATE)&lt;/b&gt;, &lt;b&gt;PDB 이동(Unplug/Plug)&lt;/b&gt;, 그리고 &lt;b&gt;운영 표준 패턴&lt;/b&gt;까지 정리했습니다. 이 글은 &lt;a href=&quot;https://www.whodo.net/entry/%EC%98%A4%EB%9D%BC%ED%81%B4-%EC%97%90%EB%9F%AC-ORA-12514-TNS%EB%A6%AC%EC%8A%A4%EB%84%88%EA%B0%80-%EC%84%9C%EB%B9%84%EC%8A%A4%EB%A5%BC-%EC%95%8C%EC%A7%80-%EB%AA%BB%ED%95%A8-5%EA%B0%80%EC%A7%80-%EC%9B%90%EC%9D%B8%EA%B3%BC-%ED%95%B4%EA%B2%B0%EB%B0%A9%EB%B2%95-PDB-%ED%99%98%EA%B2%BD-%ED%8F%AC%ED%95%A8&quot;&gt;ORA-12514 글&lt;/a&gt;의 후속 심화편 성격입니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;CDB/PDB 아키텍처 한눈에&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 멀티테넌트 구조를 그림으로 이해해 봅시다.&lt;/p&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;┌──────────────────── CDB (Container Database) ────────────────────┐
│                                                                  │
│  ┌─────────────┐  ┌───────────┐  ┌──────────┐  ┌──────────┐      │
│  │  CDB$ROOT   │  │ PDB$SEED  │  │ PRODPDB  │  │ TESTPDB  │      │
│  │             │  │           │  │          │  │          │      │
│  │ - 시스템     │  │ - 템플릿   │  │ - 운영용  │  │ - 테스트  │       │
│  │ - 메타데이터 │   │ - 읽기전용 │  │   사용자  │  │   사용자  │       │
│  │ - 공통사용자 │   │           │  │   데이터 │  │   데이터  │       │
│  └─────────────┘  └───────────┘  └──────────┘  └──────────┘       │
│                                                                   │
│  ┌─ 공유 ─────────────────────────────────────────────────────┐   │
│  │ 인스턴스(SGA, 백그라운드 프로세스), 컨트롤 파일, REDO, UNDO │   │
│  └────────────────────────────────────────────────────────────┘   │
└───────────────────────────────────────────────────────────────────┘&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;컨테이너별 역할&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컨테이너 역할 평소 상태&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;CDB$ROOT&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;시스템 메타데이터, 공통 사용자, 운영 관리&lt;/td&gt;
&lt;td&gt;READ WRITE (항상)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;PDB$SEED&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;새 PDB 생성을 위한 템플릿&lt;/td&gt;
&lt;td&gt;READ ONLY (자동)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;사용자 PDB&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;실제 비즈니스 데이터&lt;/td&gt;
&lt;td&gt;READ WRITE (목표 상태)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;핵심 사실 4가지&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;모든 PDB는 인스턴스를 공유합니다&lt;/b&gt; &amp;mdash; SGA, 백그라운드 프로세스는 CDB 단 하나&lt;/li&gt;
&lt;li&gt;&lt;b&gt;PDB는 독립적인 데이터베이스처럼 동작합니다&lt;/b&gt; &amp;mdash; 사용자, 객체, 권한이 각각 분리&lt;/li&gt;
&lt;li&gt;&lt;b&gt;하나의 CDB에 수백 개의 PDB를 담을 수 있습니다&lt;/b&gt; &amp;mdash; 19c 기준 최대 252개(라이선스에 따라)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;비-CDB는 21c부터 사라졌습니다&lt;/b&gt; &amp;mdash; 신규 구축 시 CDB는 필수&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;컨테이너 전환과 기본 명령&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CDB/PDB 운영의 출발점은 &lt;b&gt;&quot;내가 지금 어디 있는가&quot;&lt;/b&gt; 를 아는 것입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;현재 컨테이너 확인&lt;/h3&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- 현재 컨테이너 이름
SHOW CON_NAME

-- 현재 컨테이너 ID (1=ROOT, 2=SEED, 3+=PDB)
SHOW CON_ID

-- 모든 컨테이너 목록과 상태
SELECT con_id, name, open_mode FROM v$containers ORDER BY con_id;
SELECT name, open_mode FROM v$pdbs;  -- PDB만
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;컨테이너 전환&lt;/h3&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- CDB$ROOT로 이동
ALTER SESSION SET CONTAINER = CDB$ROOT;

-- 특정 PDB로 이동
ALTER SESSION SET CONTAINER = PRODPDB;

-- 다시 ROOT로
ALTER SESSION SET CONTAINER = CDB$ROOT;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;직접 PDB로 접속&lt;/h3&gt;
&lt;pre class=&quot;nginx&quot;&gt;&lt;code&gt;# Easy Connect로 PDB에 바로 접속
sqlplus scott/tiger@dbserver:1521/prodpdb

# tnsnames.ora에 service_name = prodpdb 별칭이 있으면
sqlplus scott/tiger@PRODPDB
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PDB는 마치 독립 DB처럼 service_name으로 접속합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;일상적으로 가장 많이 쓰는 명령 모음&lt;/h3&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- PDB 상태 확인
SHOW PDBS

-- 출력 예시:
-- CON_ID  CON_NAME    OPEN MODE   RESTRICTED
-- ------  --------    ---------   ----------
--   2     PDB$SEED    READ ONLY   NO
--   3     PRODPDB     READ WRITE  NO
--   4     TESTPDB     MOUNTED     (안 열림)

-- PDB 단순 열기
ALTER PLUGGABLE DATABASE TESTPDB OPEN;

-- 모든 PDB 한꺼번에 열기
ALTER PLUGGABLE DATABASE ALL OPEN;

-- 특정 PDB만 제외
ALTER PLUGGABLE DATABASE ALL EXCEPT TESTPDB OPEN;

-- PDB 닫기
ALTER PLUGGABLE DATABASE TESTPDB CLOSE IMMEDIATE;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;★ PDB 상태 관리 - SAVE STATE (가장 중요)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CDB/PDB 운영에서 가장 자주 발생하는 사고가 &lt;b&gt;DB 재시작 후 PDB가 MOUNTED 상태로 머무름&lt;/b&gt; 입니다. &lt;a href=&quot;https://www.whodo.net/entry/%EC%98%A4%EB%9D%BC%ED%81%B4-%EC%97%90%EB%9F%AC-ORA-12514-TNS%EB%A6%AC%EC%8A%A4%EB%84%88%EA%B0%80-%EC%84%9C%EB%B9%84%EC%8A%A4%EB%A5%BC-%EC%95%8C%EC%A7%80-%EB%AA%BB%ED%95%A8-5%EA%B0%80%EC%A7%80-%EC%9B%90%EC%9D%B8%EA%B3%BC-%ED%95%B4%EA%B2%B0%EB%B0%A9%EB%B2%95-PDB-%ED%99%98%EA%B2%BD-%ED%8F%AC%ED%95%A8&quot;&gt;ORA-12514 글&lt;/a&gt;에서 다룬 그 문제예요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;무엇이 문제인가&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본 동작:&lt;/p&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;DB 재시작 전: PDB1 = READ WRITE, PDB2 = READ WRITE
       &amp;darr; SHUTDOWN IMMEDIATE / STARTUP
DB 재시작 후: PDB1 = MOUNTED,    PDB2 = MOUNTED
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PDB는 CDB가 재기동되면 &lt;b&gt;기본적으로 MOUNTED 상태로 올라옵니다&lt;/b&gt;. 접속하려면 매번 수동으로 OPEN해야 하고, 자동화 스크립트나 모니터링 도구가 ORA-12514로 실패합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;해결: SAVE STATE 명령 (12.1.0.2+)&lt;/h3&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- 1) PDB를 원하는 상태로 만들기
ALTER PLUGGABLE DATABASE prodpdb OPEN;

-- 2) 그 상태를 저장
ALTER PLUGGABLE DATABASE prodpdb SAVE STATE;

-- 3) 또는 모든 PDB의 현재 상태를 한꺼번에 저장
ALTER PLUGGABLE DATABASE ALL SAVE STATE;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 하면 CDB 재시작 후에도 PDB가 자동으로 OPEN 상태로 복원됩니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;저장 상태 확인&lt;/h3&gt;
&lt;pre class=&quot;pf&quot;&gt;&lt;code&gt;SELECT con_name, instance_name, state
FROM   cdb_pdb_saved_states;

-- 또는
SELECT con_id, con_name, state
FROM   dba_pdb_saved_states;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;저장 상태 제거&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특정 PDB를 더 이상 자동 OPEN하지 않으려면:&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;ALTER PLUGGABLE DATABASE testpdb DISCARD STATE;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 DB 재시작 시 그 PDB는 MOUNTED 상태로 유지됩니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;트리거 방식 (12.1.0.1 이하만)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;12.1.0.2 미만 환경에서는 SAVE STATE가 없어서 트리거로 처리해야 합니다.&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;CREATE OR REPLACE TRIGGER open_all_pdbs
AFTER STARTUP ON DATABASE
BEGIN
    EXECUTE IMMEDIATE 'ALTER PLUGGABLE DATABASE ALL OPEN';
END;
/
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;12.1.0.2 이상이라면 트리거 방식은 권장하지 않습니다.&lt;/b&gt; SAVE STATE가 더 안전하고 표준입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;실무 팁&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;신규 PDB를 생성하면 반드시 마지막에 SAVE STATE를 실행하세요. 한 줄 빠뜨려서 야간에 사고가 나는 사례가 많습니다.&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- 신규 PDB 생성 표준 절차
CREATE PLUGGABLE DATABASE newpdb FROM PDB$SEED ...;
ALTER PLUGGABLE DATABASE newpdb OPEN;
ALTER PLUGGABLE DATABASE newpdb SAVE STATE;  -- ★ 잊지 말 것
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;★ 공통 사용자 vs 로컬 사용자&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CDB 환경에서 사용자 관리의 핵심입니다. 잘못하면 ORA-65096 에러가 발생하거나 보안 문제가 생깁니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;두 종류의 사용자&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;항목 공통 사용자 (Common User) 로컬 사용자 (Local User)&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;접두사&lt;/td&gt;
&lt;td&gt;C## 또는 c## 필수&lt;/td&gt;
&lt;td&gt;일반 이름&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;소속&lt;/td&gt;
&lt;td&gt;CDB 전체 (모든 PDB)&lt;/td&gt;
&lt;td&gt;특정 PDB만&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;생성 위치&lt;/td&gt;
&lt;td&gt;CDB$ROOT에서 생성&lt;/td&gt;
&lt;td&gt;특정 PDB에서 생성&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;권한 부여&lt;/td&gt;
&lt;td&gt;CONTAINER=ALL 가능&lt;/td&gt;
&lt;td&gt;해당 PDB만&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;운영 용도&lt;/td&gt;
&lt;td&gt;DBA, 모니터링, 백업&lt;/td&gt;
&lt;td&gt;애플리케이션 사용자&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;공통 사용자 생성&lt;/h3&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- CDB$ROOT에 접속
ALTER SESSION SET CONTAINER = CDB$ROOT;

-- C## 접두사 필수
CREATE USER c##dba_monitor IDENTIFIED BY pwd
    CONTAINER = ALL;
    
GRANT CREATE SESSION TO c##dba_monitor CONTAINER = ALL;
GRANT SELECT_CATALOG_ROLE TO c##dba_monitor CONTAINER = ALL;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 생성한 사용자는 &lt;b&gt;모든 PDB에 같은 이름으로 존재&lt;/b&gt;합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;로컬 사용자 생성 (가장 흔한 경우)&lt;/h3&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;-- 특정 PDB로 이동
ALTER SESSION SET CONTAINER = PRODPDB;

-- 일반 이름 사용
CREATE USER app_user IDENTIFIED BY pwd;
GRANT CONNECT, RESOURCE TO app_user;
GRANT UNLIMITED TABLESPACE TO app_user;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 사용자는 PRODPDB에만 존재하고 다른 PDB에서는 보이지 않습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;자주 발생하는 에러&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;ORA-65096: invalid common user or role name&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;-- ❌ CDB$ROOT에서 일반 이름으로 사용자 생성 시도
ALTER SESSION SET CONTAINER = CDB$ROOT;
CREATE USER scott IDENTIFIED BY tiger;
-- &amp;rarr; ORA-65096
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해결: 컨테이너를 PDB로 옮긴 후 생성하거나, 이름에 C## 접두사를 붙입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;ORA-65049: creation of local user or role is not allowed in CDB$ROOT&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같은 케이스. 로컬 사용자는 PDB에서만 생성 가능합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;사용자 조회&lt;/h3&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- 현재 컨테이너의 사용자만
SELECT username, common, created FROM dba_users;

-- CDB 전체의 사용자 (공통 사용자만 보임)
SELECT username, con_id, common FROM cdb_users;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;PDB 생성과 제거&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;운영 환경에서 새 사업부나 신규 시스템 도입 시 자주 하는 작업입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;PDB$SEED로부터 생성 (기본)&lt;/h3&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- CDB$ROOT에서 실행
CREATE PLUGGABLE DATABASE newpdb
    ADMIN USER pdb_admin IDENTIFIED BY secure_pwd
    FILE_NAME_CONVERT = (
        '/u01/oradata/cdb/pdbseed/',
        '/u01/oradata/cdb/newpdb/'
    );

-- 생성 후 열기 + 상태 저장
ALTER PLUGGABLE DATABASE newpdb OPEN;
ALTER PLUGGABLE DATABASE newpdb SAVE STATE;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ADMIN USER는 해당 PDB의 관리자 계정으로 자동 생성됩니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;기존 PDB 복제 (Clone)&lt;/h3&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- 소스 PDB를 READ ONLY로 변경
ALTER PLUGGABLE DATABASE prodpdb CLOSE;
ALTER PLUGGABLE DATABASE prodpdb OPEN READ ONLY;

-- 복제
CREATE PLUGGABLE DATABASE testpdb FROM prodpdb
    FILE_NAME_CONVERT = (
        '/u01/oradata/cdb/prodpdb/',
        '/u01/oradata/cdb/testpdb/'
    );

-- 소스를 다시 READ WRITE로
ALTER PLUGGABLE DATABASE prodpdb CLOSE;
ALTER PLUGGABLE DATABASE prodpdb OPEN;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;테스트 환경 구축, 마이그레이션 테스트에 자주 사용됩니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;PDB 삭제&lt;/h3&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- 1) 닫기
ALTER PLUGGABLE DATABASE testpdb CLOSE IMMEDIATE;

-- 2) 데이터파일까지 삭제
DROP PLUGGABLE DATABASE testpdb INCLUDING DATAFILES;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;경고&lt;/b&gt;: INCLUDING DATAFILES는 물리 파일까지 영구 삭제합니다. 백업 확인 후 실행하세요.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;★ PDB Unplug / Plug - 다른 CDB로 이동&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CDB/PDB의 가장 강력한 기능 중 하나입니다. &lt;b&gt;PDB를 통째로 다른 서버의 CDB로 옮길 수 있습니다.&lt;/b&gt; 한국어 자료에 깊이 있는 글이 거의 없는 영역이에요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Unplug (꺼내기)&lt;/h3&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- 1) PDB를 닫기 (Unplug는 닫힌 상태에서만 가능)
ALTER PLUGGABLE DATABASE prodpdb CLOSE IMMEDIATE;

-- 2) XML 메타데이터 방식 (전통적)
ALTER PLUGGABLE DATABASE prodpdb UNPLUG INTO '/backup/prodpdb.xml';

-- 또는 PDB 아카이브 방식 (12.2+, 데이터파일까지 압축)
ALTER PLUGGABLE DATABASE prodpdb UNPLUG INTO '/backup/prodpdb.pdb';
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;형식 차이&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;.xml&lt;/td&gt;
&lt;td&gt;메타데이터만. 데이터파일은 별도로 복사 필요&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;.pdb&lt;/td&gt;
&lt;td&gt;메타데이터 + 데이터파일을 하나로 압축. 이동에 편리&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Unplug된 PDB 제거 (원본 CDB에서)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Unplug 후에도 PDB는 원본 CDB에 남아있습니다(MOUNTED 상태). 완전히 제거하려면:&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;DROP PLUGGABLE DATABASE prodpdb KEEP DATAFILES;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;KEEP DATAFILES로 해야 데이터파일은 보존되어 새 CDB에 plug할 수 있습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Plug (꽂기) - 다른 CDB에서&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;새 서버의 CDB로 파일을 옮긴 후:&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- XML 방식
CREATE PLUGGABLE DATABASE prodpdb USING '/backup/prodpdb.xml'
    NOCOPY 
    TEMPFILE REUSE;

-- 또는 .pdb 아카이브 방식
CREATE PLUGGABLE DATABASE prodpdb USING '/backup/prodpdb.pdb';

-- 열기 + 상태 저장
ALTER PLUGGABLE DATABASE prodpdb OPEN;
ALTER PLUGGABLE DATABASE prodpdb SAVE STATE;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;활용 시나리오&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;DB 서버 교체&lt;/b&gt;: PDB를 그대로 새 서버로 이동&lt;/li&gt;
&lt;li&gt;&lt;b&gt;클라우드 이전&lt;/b&gt;: 온프레미스 &amp;rarr; 클라우드 마이그레이션&lt;/li&gt;
&lt;li&gt;&lt;b&gt;테스트 환경 구축&lt;/b&gt;: 운영 PDB를 테스트 CDB로 복제&lt;/li&gt;
&lt;li&gt;&lt;b&gt;버전 업그레이드&lt;/b&gt;: 19c CDB의 PDB를 21c CDB로 plug (compatibility 체크 필요)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;주의사항&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;호환성 검사 필수&lt;/b&gt;: plug 전에 DBMS_PDB.CHECK_PLUG_COMPATIBILITY로 확인&lt;/li&gt;
&lt;li&gt;&lt;b&gt;TDE 사용 중이면&lt;/b&gt;: ENCRYPT USING transport_secret 옵션 필수&lt;/li&gt;
&lt;li&gt;&lt;b&gt;CDB 호환성&lt;/b&gt;: 19c CDB &amp;rarr; 12c CDB로 plug는 불가 (downgrade 안 됨)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;운영 모니터링 - CDB_* 뷰 활용&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CDB 환경에서는 DBA_* 뷰가 &lt;b&gt;현재 컨테이너만&lt;/b&gt; 보여줍니다. &lt;b&gt;CDB_&lt;/b&gt;* 뷰가 전체 CDB를 보여주는 표준입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;자주 쓰는 CDB_* 뷰&lt;/h3&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- 전체 PDB와 상태
SELECT con_id, name, open_mode, restricted, application_root
FROM   cdb_pdbs;

-- 전체 PDB의 데이터파일 사용량
SELECT con_id, tablespace_name, 
       ROUND(SUM(bytes)/1024/1024, 2) AS size_mb
FROM   cdb_data_files
GROUP  BY con_id, tablespace_name
ORDER  BY con_id, tablespace_name;

-- 전체 PDB의 사용자
SELECT con_id, username, common, account_status
FROM   cdb_users
ORDER  BY con_id, username;

-- 전체 PDB의 세션 수
SELECT con_id, COUNT(*) AS session_cnt
FROM   v$session
GROUP  BY con_id
ORDER  BY con_id;

-- 전체 PDB의 백업 이력
SELECT con_id, session_key, input_type, status,
       TO_CHAR(start_time, 'YYYY-MM-DD HH24:MI:SS') AS start_at
FROM   cdb_rman_backup_job_details
ORDER  BY start_time DESC;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;CON_ID로 컨테이너 식별&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CON_ID 컬럼이 각 행이 어느 컨테이너에 속한지 알려줍니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;0: CDB 전체 (공유 정보)&lt;/li&gt;
&lt;li&gt;1: CDB$ROOT&lt;/li&gt;
&lt;li&gt;2: PDB$SEED&lt;/li&gt;
&lt;li&gt;3+: 사용자 PDB&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;운영 환경 권장 패턴 5가지&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. SAVE STATE는 PDB 생성 시 자동화&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PDB 생성 스크립트 마지막에 항상 SAVE STATE를 포함하세요.&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- 표준 PDB 생성 스크립트 (사내 표준으로 보관)
PROMPT === PDB 생성 시작 ===
CREATE PLUGGABLE DATABASE &amp;amp;pdb_name FROM PDB$SEED ...;

PROMPT === PDB 열기 ===
ALTER PLUGGABLE DATABASE &amp;amp;pdb_name OPEN;

PROMPT === 상태 저장 (재시작 시 자동 OPEN) ===
ALTER PLUGGABLE DATABASE &amp;amp;pdb_name SAVE STATE;

PROMPT === 완료 ===
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. 명시적 서비스 사용&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PDB 이름과 동일한 service_name에 의존하지 말고 &lt;b&gt;별도 서비스를 만들어 사용&lt;/b&gt;하세요.&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- PRODPDB에서 실행
BEGIN
    DBMS_SERVICE.CREATE_SERVICE(
        service_name =&amp;gt; 'app_prod_svc',
        network_name =&amp;gt; 'app_prod_svc'
    );
    DBMS_SERVICE.START_SERVICE('app_prod_svc');
END;
/
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 하면 나중에 PDB를 다른 CDB로 옮기거나 이름을 바꿔도 애플리케이션 연결 문자열을 변경할 필요가 없습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. DBA는 공통 사용자, 애플리케이션은 로컬 사용자&lt;/h3&gt;
&lt;pre class=&quot;clean&quot;&gt;&lt;code&gt;공통 사용자 (C##): 모니터링, 백업, 운영자
로컬 사용자: 애플리케이션, 비즈니스 사용자
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 분리를 지키면 보안 사고와 권한 혼란을 크게 줄일 수 있습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4. CDB_* 뷰 사용 표준화&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스크립트 작성 시 DBA_* 대신 CDB_* 뷰를 기본으로 사용하세요. CON_ID로 필터링하면 동일한 결과를 얻으면서도 전체 CDB 진단이 가능합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5. PDB 단위 백업 정책 분리&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;RMAN으로 PDB 단위 백업을 분리해 두면 PDB 하나만 복구 가능합니다.&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- PRODPDB만 백업
BACKUP PLUGGABLE DATABASE PRODPDB;

-- PRODPDB만 복구
RESTORE PLUGGABLE DATABASE PRODPDB;
RECOVER PLUGGABLE DATABASE PRODPDB;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;자주 발생하는 함정 5가지&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;함정 1: 컨테이너 전환 안 한 채 작업&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CDB$ROOT에서 일반 사용자 만들기 시도 &amp;rarr; ORA-65096. 작업 전 항상 SHOW CON_NAME으로 위치 확인.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;함정 2: PDB 재시작 후 자동 OPEN 안 됨&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SAVE STATE 미적용. 위 섹션 참고.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;함정 3: DBA_USERS에 모든 사용자가 안 보임&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DBA_USERS는 현재 컨테이너만 보여줌. 전체를 보려면 CDB_USERS 사용.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;함정 4: PDB 이름 그대로 service_name 사용&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;운영 중 PDB 이름 변경이 어려워짐. 위 권장 패턴 2번 참고.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;함정 5: Unplug 후 원본 CDB에 PDB 남아있음&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DROP PLUGGABLE DATABASE ... KEEP DATAFILES로 정리해야 함.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;23ai에서 새로 추가된 기능 (간단히)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;23ai에서 PDB 운영에 관련된 주요 신기능:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;PDB Snapshot Carousel&lt;/b&gt;: PDB의 시점별 스냅샷을 자동으로 회전 관리. 빠른 복구나 클론에 활용&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Refreshable PDB 개선&lt;/b&gt;: 원격 PDB에서 자동 새로 고침&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Read-Only User on PDB&lt;/b&gt;: 읽기 전용 사용자에게 PDB 단위 권한 부여&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자세한 활용은 별도 글에서 다룰 예정입니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;마무리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CDB/PDB 환경은 처음에는 복잡해 보이지만, &lt;b&gt;컨테이너 개념을 잡고 SAVE STATE를 적극 활용&lt;/b&gt;하면 운영이 오히려 더 편해집니다. 한 인스턴스에 여러 DB를 담을 수 있어서 자원 활용도와 관리 효율이 비-CDB 환경보다 압도적입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;운영 환경에 처음 도입한다면 다음 순서를 추천합니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;테스트 CDB에서 SAVE STATE, 공통/로컬 사용자 충분히 익히기&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;표준 PDB 생성 스크립트 만들기&lt;/b&gt; (SAVE STATE 포함)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;명시적 서비스 사용 정책 수립&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;CDB_ 뷰 기반 모니터링 쿼리 표준화*&lt;/li&gt;
&lt;li&gt;&lt;b&gt;PDB 단위 백업 정책 도입&lt;/b&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히 &lt;a href=&quot;https://www.whodo.net/entry/%EC%98%A4%EB%9D%BC%ED%81%B4-%EC%97%90%EB%9F%AC-ORA-12514-TNS%EB%A6%AC%EC%8A%A4%EB%84%88%EA%B0%80-%EC%84%9C%EB%B9%84%EC%8A%A4%EB%A5%BC-%EC%95%8C%EC%A7%80-%EB%AA%BB%ED%95%A8-5%EA%B0%80%EC%A7%80-%EC%9B%90%EC%9D%B8%EA%B3%BC-%ED%95%B4%EA%B2%B0%EB%B0%A9%EB%B2%95-PDB-%ED%99%98%EA%B2%BD-%ED%8F%AC%ED%95%A8&quot;&gt;ORA-12514&lt;/a&gt;로 인한 야간 사고를 막으려면 SAVE STATE 적용을 운영 표준에 반드시 포함시키세요. 이 한 가지만으로도 운영 사고의 상당 부분이 예방됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비슷한 CDB/PDB 운영 사례나 더 좋은 패턴이 있다면 댓글로 공유해 주세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>DBA 실무/Oracle(오라클)</category>
      <category>ALTER PLUGGABLE DATABASE SAVE STATE</category>
      <category>multitenant</category>
      <category>ora-65096</category>
      <category>PDB Clone</category>
      <category>PDB MOUNT 자동해제</category>
      <category>PDB 복제</category>
      <category>PDB 자동 OPEN</category>
      <category>멀티테넌트</category>
      <category>소니스토리</category>
      <category>오라클 CDB PDB</category>
      <author>isony</author>
      <guid isPermaLink="true">https://isony.tistory.com/338</guid>
      <comments>https://isony.tistory.com/entry/%EC%98%A4%EB%9D%BC%ED%81%B4-%EC%9A%B4%EC%98%81-Oracle-12c-%EB%A9%80%ED%8B%B0%ED%85%8C%EB%84%8C%ED%8A%B8CDBPDB-%EC%9A%B4%EC%98%81-%EA%B0%80%EC%9D%B4%EB%93%9C-%EC%83%81%ED%83%9C-%EA%B4%80%EB%A6%AC%EB%B6%80%ED%84%B0-UnplugPlug%EA%B9%8C%EC%A7%80#entry338comment</comments>
      <pubDate>Mon, 22 Jun 2026 08:15:18 +0900</pubDate>
    </item>
    <item>
      <title>2026년06월21일 주일예배 (이재훈목사님) - 1부</title>
      <link>https://isony.tistory.com/entry/2026%EB%85%8406%EC%9B%9421%EC%9D%BC-%EC%A3%BC%EC%9D%BC%EC%98%88%EB%B0%B0-%EC%9D%B4%EC%9E%AC%ED%9B%88%EB%AA%A9%EC%82%AC%EB%8B%98-1%EB%B6%80</link>
      <description>&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;2026년06월21일 주일예배 (이재훈목사님) - 1부&lt;/h2&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;주의 말씀 : 나를 따르라&amp;nbsp; (6)&lt;/h2&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;너는 내 사랑하는 자녀라&lt;/h2&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;성경 :&amp;nbsp; 마태복음 3:13 ~ 17 말씀 (출처:우리말성경)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&amp;lt; 성경 &amp;gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;3:13 그때 예수께서 요한에게 세례를 받으시려고 갈릴리에서 요단 강으로 오셨습니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;3:14 그러나 요한은 이를 말리면서 예수께 말했습니다. &amp;ldquo;제가 오히려 선생님께 세례를 받아야 합니다. 그런데 제게 오시다니요!&amp;rdquo;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;3:15 예수께서 대답하셨습니다. &amp;ldquo;지금은 그렇게 하도록 하여라. 우리가 이와 같이 해 모든 의를 이루는 것이 옳다.&amp;rdquo; 그러자 요한은 그대로 따랐습니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;3:16 예수께서 세례를 받으시고 물속에서 올라오셨습니다. 그때 예수께서는 하늘이 열리고 하나님의 영이 비둘기처럼 자신에게 내려오는 것을 보셨습니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;3:17 그리고 하늘에서 소리가 들려왔습니다. &amp;ldquo;이는 내가 사랑하는 아들이다. 내가 그를 매우 기뻐한다.&amp;rdquo;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&amp;lt; 예배 영상 &amp;gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;a href=&quot;https://youtu.be/E2w2KS2BvD0&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://youtu.be/E2w2KS2BvD0&lt;/a&gt;&lt;/b&gt;&lt;/p&gt;
&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignCenter&quot; data-video-host=&quot;youtube&quot; data-video-url=&quot;https://www.youtube.com/watch?v=E2w2KS2BvD0&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/dWEqDU/dJMb86Pbe9e/7vtrHIhKT4CaaAynMglFv1/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=550_160_686_308,https://scrap.kakaocdn.net/dn/CaPsh/dJMb88fadkz/hEdZRXzGj1jdwLQyMKdo7K/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=550_160_686_308,https://scrap.kakaocdn.net/dn/bqqGHG/dJMb82eWuVQ/HkGn5fK55lduMHRqNk9KOK/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=550_160_686_308&quot; data-video-width=&quot;860&quot; data-video-height=&quot;484&quot; data-video-origin-width=&quot;860&quot; data-video-origin-height=&quot;484&quot; data-ke-mobilestyle=&quot;widthContent&quot; data-video-title=&quot;주일예배2026 06 21&quot; data-original-url=&quot;&quot;&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/E2w2KS2BvD0&quot; width=&quot;860&quot; height=&quot;484&quot; frameborder=&quot;&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;figcaption style=&quot;display: none;&quot;&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>성경과 QT/주일예배(온누리교회)</category>
      <category>CGNTV</category>
      <category>나를 따르라</category>
      <category>너는 내 사랑하는 자녀라</category>
      <category>마태복음</category>
      <category>마태복음 내 사랑하는 자녀</category>
      <category>소니스토리</category>
      <category>온누리교회</category>
      <category>우리말성경</category>
      <category>이재훈목사</category>
      <category>주일예배</category>
      <author>isony</author>
      <guid isPermaLink="true">https://isony.tistory.com/337</guid>
      <comments>https://isony.tistory.com/entry/2026%EB%85%8406%EC%9B%9421%EC%9D%BC-%EC%A3%BC%EC%9D%BC%EC%98%88%EB%B0%B0-%EC%9D%B4%EC%9E%AC%ED%9B%88%EB%AA%A9%EC%82%AC%EB%8B%98-1%EB%B6%80#entry337comment</comments>
      <pubDate>Sun, 21 Jun 2026 08:07:53 +0900</pubDate>
    </item>
    <item>
      <title>[오라클 에러] ORA-12154 TNS:could not resolve the connect identifier - 5가지 원인과 해결방법 (접속 에러 3종 비교)</title>
      <link>https://isony.tistory.com/entry/%EC%98%A4%EB%9D%BC%ED%81%B4-%EC%97%90%EB%9F%AC-ORA-12154-TNScould-not-resolve-the-connect-identifier-5%EA%B0%80%EC%A7%80-%EC%9B%90%EC%9D%B8%EA%B3%BC-%ED%95%B4%EA%B2%B0%EB%B0%A9%EB%B2%95-%EC%A0%91%EC%86%8D-%EC%97%90%EB%9F%AC-3%EC%A2%85-%EB%B9%84%EA%B5%90</link>
      <description>&lt;h1&gt;[오라클 에러] ORA-12154 TNS:could not resolve the connect identifier - 5가지 원인과 해결방법 (접속 에러 3종 비교)&lt;/h1&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;테스트 환경&lt;/b&gt;: Oracle Client 11g / 12c / 19c / 21c, Oracle Linux 8 / Windows 11&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ORA-12154는 오라클 클라이언트가 가장 먼저 마주칠 수 있는 접속 에러입니다. &lt;a href=&quot;https://www.whodo.net/entry/%EC%98%A4%EB%9D%BC%ED%81%B4-%EC%97%90%EB%9F%AC-ORA-12541-TNS-%EB%A6%AC%EC%8A%A4%EB%84%88%EA%B0%80-%EC%97%86%EC%8A%B5%EB%8B%88%EB%8B%A4-5%EA%B0%80%EC%A7%80-%EC%9B%90%EC%9D%B8%EA%B3%BC-%ED%95%B4%EA%B2%B0%EB%B0%A9%EB%B2%95-%EC%8B%A4%EB%AC%B4-DBA-%EC%A0%95%EB%A6%AC&quot;&gt;ORA-12541(리스너 없음)&lt;/a&gt;이나 &lt;a href=&quot;https://www.whodo.net/entry/%EC%98%A4%EB%9D%BC%ED%81%B4-%EC%97%90%EB%9F%AC-ORA-12514-TNS%EB%A6%AC%EC%8A%A4%EB%84%88%EA%B0%80-%EC%84%9C%EB%B9%84%EC%8A%A4%EB%A5%BC-%EC%95%8C%EC%A7%80-%EB%AA%BB%ED%95%A8-5%EA%B0%80%EC%A7%80-%EC%9B%90%EC%9D%B8%EA%B3%BC-%ED%95%B4%EA%B2%B0%EB%B0%A9%EB%B2%95-PDB-%ED%99%98%EA%B2%BD-%ED%8F%AC%ED%95%A8&quot;&gt;ORA-12514(서비스 모름)&lt;/a&gt;이 &quot;서버에 도달했는데 안 됨&quot;이라면, &lt;b&gt;ORA-12154는 &quot;서버에 도달조차 못함&quot;&lt;/b&gt; 의 의미입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글로 본 블로그의 &lt;b&gt;접속 에러 3종 시리즈가 완성&lt;/b&gt;됩니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;ORA-12154&lt;/b&gt;: 별칭(connect identifier) 자체를 못 풀어서 어디로 가야 할지 모름&lt;/li&gt;
&lt;li&gt;&lt;b&gt;ORA-12541&lt;/b&gt;: 어디로 가야 할지는 알았는데 그 호스트의 리스너가 죽음&lt;/li&gt;
&lt;li&gt;&lt;b&gt;ORA-12514&lt;/b&gt;: 리스너는 살아있는데 요청한 서비스를 모름&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 글에서는 ORA-12154의 5가지 원인을 분류하고, 특히 &lt;b&gt;여러 오라클 클라이언트가 설치된 환경에서 자주 발생하는 환경변수 충돌&lt;/b&gt;까지 정리했습니다. 급하신 분은 &lt;u&gt;빠른 진단 체크리스트&lt;/u&gt;부터 보세요.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;에러 메시지 전문&lt;/h2&gt;
&lt;pre class=&quot;less&quot;&gt;&lt;code&gt;ORA-12154: TNS:could not resolve the connect identifier specified
ORA-12154: TNS: 지정된 접속 식별자를 해석할 수 없습니다.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일부 버전에서는 다음 형태로도 보일 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;ORA-12154: TNS:could not resolve service name
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만 실제 동작은 동일합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;★ 접속 에러 3종 비교 (12154 vs 12541 vs 12514)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;세 에러가 발생하는 단계를 그림으로 표현하면 다음과 같습니다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;클라이언트가 SQL 실행
   │
   ├─ 1단계: 별칭(예: PRODDB)을 풀어서 host:port를 찾기
   │           └─ 실패 시 &amp;rarr; ORA-12154
   │
   ├─ 2단계: host:port의 리스너에 접속
   │           └─ 실패 시 &amp;rarr; ORA-12541
   │
   ├─ 3단계: 리스너에 service_name 요청
   │           └─ 실패 시 &amp;rarr; ORA-12514
   │
   └─ 4단계: DB 인스턴스 접속 &amp;rarr; 인증(ORA-01017 등)
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;항목 ORA-12154 ORA-12541 ORA-12514&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;단계&lt;/td&gt;
&lt;td&gt;1단계 (이름 해석)&lt;/td&gt;
&lt;td&gt;2단계 (리스너 접속)&lt;/td&gt;
&lt;td&gt;3단계 (서비스 매칭)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;의미&lt;/td&gt;
&lt;td&gt;별칭 못 풂&lt;/td&gt;
&lt;td&gt;리스너 응답 없음&lt;/td&gt;
&lt;td&gt;서비스 미등록&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;위치&lt;/td&gt;
&lt;td&gt;&lt;b&gt;클라이언트 측 문제&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;서버 또는 네트워크&lt;/td&gt;
&lt;td&gt;서버 측 문제&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;핵심 점검 파일&lt;/td&gt;
&lt;td&gt;tnsnames.ora, sqlnet.ora&lt;/td&gt;
&lt;td&gt;listener.ora&lt;/td&gt;
&lt;td&gt;service_names&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;클라이언트 환경변수 영향&lt;/td&gt;
&lt;td&gt;⭐⭐⭐⭐⭐&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;가장 중요한 차이&lt;/b&gt;: ORA-12154는 &lt;b&gt;클라이언트 PC의 설정 문제&lt;/b&gt;입니다. 서버는 멀쩡합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;한 줄 진단법&lt;/b&gt;: 같은 별칭을 다른 PC나 다른 서버에서는 잘 쓰는데 내 PC에서만 안 되면 거의 100% ORA-12154 케이스입니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;ORA-12154의 본질 - &quot;별칭 해석&quot;의 의미&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ORA-12154를 이해하려면 &lt;b&gt;클라이언트가 별칭(connect identifier)을 어떻게 해석하는지&lt;/b&gt; 알아야 합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;사용자 입력 &amp;rarr; 실제 접속 정보 변환&lt;/h3&gt;
&lt;pre class=&quot;vala&quot;&gt;&lt;code&gt;# 사용자가 입력한 것
sqlplus scott/tiger@PRODDB

# 클라이언트가 PRODDB라는 별칭을 해석해서 알아내야 하는 것
# 1. 어떤 호스트에 접속? &amp;rarr; 192.168.10.5
# 2. 어떤 포트? &amp;rarr; 1521
# 3. 어떤 서비스? &amp;rarr; orclpdb
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 해석 과정에서 클라이언트가 사용하는 정보 출처(naming method)는 sqlnet.ora의 NAMES.DIRECTORY_PATH 파라미터로 결정됩니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;NAMES.DIRECTORY_PATH 기본값&lt;/h3&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;NAMES.DIRECTORY_PATH = (TNSNAMES, EZCONNECT)
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;값 의미&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;TNSNAMES&lt;/td&gt;
&lt;td&gt;tnsnames.ora 파일 사용 (가장 일반적)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;EZCONNECT&lt;/td&gt;
&lt;td&gt;host:port/service_name 형식 직접 입력&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LDAP&lt;/td&gt;
&lt;td&gt;LDAP 디렉토리 서버 사용&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HOSTNAME&lt;/td&gt;
&lt;td&gt;DNS 호스트명 자동 매칭 (deprecated)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ORA-12154는 이 모든 방법으로도 별칭을 못 풀었다는 의미입니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;빠른 진단 체크리스트&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ORA-12154가 발생했을 때 30초 만에 원인을 좁히는 순서입니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;tnsnames.ora 파일이 어디 있는지 확인&lt;/b&gt; &amp;rarr; 파일 위치 자체가 문제일 수 있음&lt;/li&gt;
&lt;li&gt;&lt;b&gt;파일 안에 해당 별칭이 정확히 있는지 확인&lt;/b&gt; &amp;rarr; 오타 / 누락&lt;/li&gt;
&lt;li&gt;&lt;b&gt;파일 구문 오류 확인&lt;/b&gt; &amp;rarr; 괄호 짝, 들여쓰기&lt;/li&gt;
&lt;li&gt;&lt;b&gt;TNS_ADMIN 환경변수 확인&lt;/b&gt; &amp;rarr; 클라이언트가 어느 파일을 보는지&lt;/li&gt;
&lt;li&gt;&lt;b&gt;여러 ORACLE_HOME 설치 환경인지 확인&lt;/b&gt; &amp;rarr; 어느 것을 쓰는지&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;원인 1: tnsnames.ora 파일에 별칭이 없거나 오타 (가장 흔함)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ORA-12154의 50% 이상이 이 케이스입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;진단 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1단계: tnsnames.ora 위치 찾기&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;php&quot;&gt;&lt;code&gt;# Linux/Unix
find / -name tnsnames.ora 2&amp;gt;/dev/null
echo $ORACLE_HOME
echo $TNS_ADMIN

# 일반적 위치
# $ORACLE_HOME/network/admin/tnsnames.ora
# $TNS_ADMIN/tnsnames.ora
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;taggerscript&quot;&gt;&lt;code&gt;:: Windows
where tnsnames.ora
echo %ORACLE_HOME%
echo %TNS_ADMIN%

:: 일반적 위치
:: %ORACLE_HOME%\network\admin\tnsnames.ora
:: %TNS_ADMIN%\tnsnames.ora
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2단계: 파일 안에 별칭이 있는지 확인&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;perl&quot;&gt;&lt;code&gt;# Linux에서 PRODDB 별칭 찾기
grep -i &quot;^PRODDB&quot; $TNS_ADMIN/tnsnames.ora
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원하는 별칭이 안 나오면 파일에 추가되지 않은 것입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;해결 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;tnsnames.ora 파일에 별칭을 추가합니다.&lt;/p&gt;
&lt;pre class=&quot;lisp&quot;&gt;&lt;code&gt;PRODDB =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.10.5)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = orclpdb)
    )
  )
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;실무 팁&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;운영 환경에서는 tnsnames.ora를 &lt;b&gt;중앙에서 관리&lt;/b&gt;하고 모든 클라이언트에 동일 파일을 배포하는 것이 표준입니다. 사용자별로 다르게 설정하면 ORA-12154 사고가 끊임없이 발생합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;원인 2: tnsnames.ora 구문 오류 (괄호 짝, 오타)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파일이 있고 별칭도 있는데 ORA-12154가 발생한다면 &lt;b&gt;파일 어딘가에 구문 오류&lt;/b&gt;가 있을 가능성이 높습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;흔한 구문 오류&lt;/h3&gt;
&lt;pre class=&quot;nix&quot;&gt;&lt;code&gt;PRODDB =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.10.5)(PORT = 1521))
    (CONNECT_DATA =
      (SERVICE_NAME = orclpdb)
    )
   )
   &amp;larr;── 여기에 짝이 안 맞는 괄호 1개 더

TESTDB =          &amp;larr; 위 문제 때문에 이 별칭부터 모두 인식 안 됨
  (DESCRIPTION = ...
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;중요한 점&lt;/b&gt;: 파일 안 한 곳의 구문 오류가 &lt;b&gt;그 이후의 모든 별칭을 인식 불가&lt;/b&gt;로 만들 수 있습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;진단 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1) tnsping으로 별칭 동작 확인&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;ebnf&quot;&gt;&lt;code&gt;tnsping PRODDB
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;별칭이 정상이면 응답이 옵니다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;OK (10 msec)
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;별칭이 인식 안 되면:&lt;/p&gt;
&lt;pre class=&quot;applescript&quot;&gt;&lt;code&gt;TNS-03505: Failed to resolve name
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2) 별칭별로 차례대로 tnsping&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;properties&quot;&gt;&lt;code&gt;tnsping PRODDB
tnsping TESTDB
tnsping DEVDB
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어느 별칭부터 실패하는지 찾으면, 그 직전 별칭 정의에 구문 오류가 있다는 뜻입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;해결 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자주 발생하는 구문 오류 패턴:&lt;/p&gt;
&lt;pre class=&quot;nix&quot;&gt;&lt;code&gt;❌ 괄호 짝 안 맞음
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.10.5)(PORT = 1521)

❌ 들여쓰기 잘못으로 별칭과 본문 연결 안 됨
PRODDB =
(DESCRIPTION = ...     &amp;larr; 최상위로 가버림

❌ 콤마 사용 (오라클 tnsnames.ora는 콤마 안 씀)
(ADDRESS = (PROTOCOL=TCP), (HOST=192.168.10.5), (PORT=1521))

❌ 따옴표 안 쓰는데 따옴표 들어감
(HOST = &quot;192.168.10.5&quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;수정 후 클라이언트 도구를 &lt;b&gt;재시작&lt;/b&gt;해야 반영됩니다(SQL Developer, Toad 등).&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;★ 원인 3: TNS_ADMIN 환경변수 누락 또는 잘못 설정&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 까다로운 케이스 중 하나입니다. 파일도 있고 내용도 맞는데, &lt;b&gt;클라이언트가 그 파일을 안 보고 있는&lt;/b&gt; 경우입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;진단 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Linux/Unix&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;bash&quot;&gt;&lt;code&gt;# 환경변수 확인
echo $TNS_ADMIN
echo $ORACLE_HOME

# 실제로 어느 파일을 보는지 추적
strace -f -e openat sqlplus scott/tiger@PRODDB 2&amp;gt;&amp;amp;1 | grep -i tnsnames
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Windows&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;dos&quot;&gt;&lt;code&gt;echo %TNS_ADMIN%
echo %ORACLE_HOME%

:: 또는 시스템 환경변수에서 확인
set | findstr ORACLE
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;클라이언트의 tnsnames.ora 탐색 순서&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오라클 클라이언트가 tnsnames.ora를 찾는 순서는 다음과 같습니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;TNS_ADMIN 환경변수&lt;/b&gt;가 가리키는 경로&lt;/li&gt;
&lt;li&gt;&lt;b&gt;$ORACLE_HOME/network/admin/&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;(Windows만) 레지스트리의 TNS_ADMIN 값&lt;/li&gt;
&lt;li&gt;(Linux 옛 환경) /etc/&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;상위 단계에서 찾으면 하위 단계는 안 봅니다.&lt;/b&gt; 그래서 TNS_ADMIN이 잘못된 경로를 가리키면 정상적인 tnsnames.ora가 있어도 무시됩니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;해결 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Linux: 영구 설정&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;# ~/.bashrc 또는 ~/.bash_profile에 추가
export ORACLE_HOME=/u01/app/oracle/product/19c/client_1
export TNS_ADMIN=$ORACLE_HOME/network/admin
export PATH=$ORACLE_HOME/bin:$PATH

source ~/.bashrc
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Windows: 환경변수 GUI 설정&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내 PC 우클릭 &amp;rarr; 속성 &amp;rarr; 고급 시스템 설정 &amp;rarr; 환경 변수&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시스템 변수에 추가:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ORACLE_HOME: C:\app\oracle\product\19.0.0\client_1&lt;/li&gt;
&lt;li&gt;TNS_ADMIN: %ORACLE_HOME%\network\admin&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;실무 팁&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;운영 환경에서는 &lt;b&gt;TNS_ADMIN을 명시적으로 설정&lt;/b&gt;하는 것을 권장합니다. ORACLE_HOME에 의존하지 않으면 클라이언트 업그레이드 시 tnsnames.ora를 재배포할 필요가 없습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;★ 원인 4: 여러 ORACLE_HOME 설치 환경의 충돌 (Windows에서 흔함)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 케이스는 다른 한국어 블로그에서 깊이 다루지 않는 영역입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;무엇이 문제인가&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한 PC에 SQL Developer, Toad, Instant Client, Forms 등 &lt;b&gt;여러 오라클 클라이언트가 설치&lt;/b&gt;되어 있으면 각자 다른 ORACLE_HOME을 가집니다. 사용자는 한 곳의 tnsnames.ora를 수정했는데, 클라이언트는 다른 곳을 보고 있어서 ORA-12154가 발생합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;진단 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Windows에서 설치된 ORACLE_HOME 목록 확인&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;stata&quot;&gt;&lt;code&gt;:: 레지스트리에서 확인
reg query HKLM\SOFTWARE\Oracle /s | findstr ORACLE_HOME
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여러 경로가 나오면 충돌 가능성이 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;현재 클라이언트가 사용하는 ORACLE_HOME 확인&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;elixir&quot;&gt;&lt;code&gt;:: 실제 사용 중인 sqlplus 위치
where sqlplus

:: 그 폴더 상위의 network\admin\tnsnames.ora가 실제 사용 파일
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;해결 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;방법 1: TNS_ADMIN을 강제 지정&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여러 ORACLE_HOME이 있어도 TNS_ADMIN은 우선됩니다.&lt;/p&gt;
&lt;pre class=&quot;elixir&quot;&gt;&lt;code&gt;:: 시스템 환경변수에 TNS_ADMIN 추가
:: &amp;rarr; 모든 클라이언트가 한 곳의 tnsnames.ora 사용
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;방법 2: 각 ORACLE_HOME의 tnsnames.ora를 동일 내용으로 동기화&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;tex&quot;&gt;&lt;code&gt;:: 표준 파일을 복사
xcopy /Y C:\standard\tnsnames.ora C:\app\oracle_home1\network\admin\
xcopy /Y C:\standard\tnsnames.ora C:\app\oracle_home2\network\admin\
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;번거롭지만 가장 확실한 방법입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;실무 팁&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;운영자 PC에서 새 클라이언트를 설치할 때마다 ORA-12154가 빈번히 발생합니다. 표준 tnsnames.ora를 git이나 공유 폴더에 두고, 새 클라이언트 설치 시 그 파일을 강제 복사하는 절차를 만들어 두세요.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;원인 5: sqlnet.ora의 NAMES.DIRECTORY_PATH 설정&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;tnsnames.ora는 멀쩡한데도 클라이언트가 LDAP 같은 다른 방법을 시도해서 실패하는 경우입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;진단 방법&lt;/h3&gt;
&lt;pre class=&quot;nginx&quot;&gt;&lt;code&gt;# sqlnet.ora 확인
cat $TNS_ADMIN/sqlnet.ora
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음과 같이 LDAP만 설정되어 있으면 tnsnames.ora를 보지 않습니다.&lt;/p&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;NAMES.DIRECTORY_PATH = (LDAP)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;해결 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;sqlnet.ora를 수정해서 TNSNAMES를 포함합니다.&lt;/p&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;NAMES.DIRECTORY_PATH = (TNSNAMES, EZCONNECT, LDAP)
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;순서가 중요합니다.&lt;/b&gt; 먼저 나열된 방법이 우선 시도됩니다. 일반 환경에서는 TNSNAMES를 가장 앞에 두는 것을 권장합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;파일이 없는 경우&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;sqlnet.ora 파일 자체가 없어도 됩니다. 이 경우 오라클은 기본값 (TNSNAMES, EZCONNECT)을 사용합니다. &lt;b&gt;이상한 sqlnet.ora가 있어서 문제가 된다면 차라리 그 파일을 백업하고 삭제&lt;/b&gt;하는 것이 빠른 해결책입니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;★ Easy Connect로 우회 (즉시 사용 가능)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ORA-12154의 원인을 분석하는 동안 &lt;b&gt;별칭 없이 직접 접속&lt;/b&gt;할 수 있는 방법이 있습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Easy Connect 구문&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;sqlplus scott/tiger@호스트:포트/서비스명
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예시:&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;sqlplus scott/tiger@192.168.10.5:1521/orclpdb
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 방식은 tnsnames.ora를 사용하지 않기 때문에 ORA-12154가 발생하지 않습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Easy Connect 활용 시나리오&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;tnsnames.ora 설정 문제로 급하게 접속해야 할 때&lt;/li&gt;
&lt;li&gt;새 서버에 임시 접속할 때&lt;/li&gt;
&lt;li&gt;자동화 스크립트에서 별칭 의존성을 없애고 싶을 때&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;제한사항&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Easy Connect는 sqlnet.ora의 NAMES.DIRECTORY_PATH에 EZCONNECT가 포함되어 있어야 동작합니다. 기본값에는 포함되어 있으니 일반 환경에서는 바로 사용 가능합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;빠른 해결 체크리스트 (종합)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5분 안에 원인을 좁히는 종합 체크리스트입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;순서 확인 항목 명령어&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;tnsnames.ora 위치 확인&lt;/td&gt;
&lt;td&gt;find / -name tnsnames.ora 또는 where tnsnames.ora&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;TNS_ADMIN 환경변수&lt;/td&gt;
&lt;td&gt;echo $TNS_ADMIN&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;별칭 존재 여부&lt;/td&gt;
&lt;td&gt;grep -i &quot;^별칭&quot; tnsnames.ora&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;tnsping 동작&lt;/td&gt;
&lt;td&gt;tnsping 별칭&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;임시 우회 시도&lt;/td&gt;
&lt;td&gt;Easy Connect 사용&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;sqlnet.ora 설정&lt;/td&gt;
&lt;td&gt;cat $TNS_ADMIN/sqlnet.ora&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 5단계로 ORA-12154의 95% 이상이 해결됩니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;그래도 안 풀린다면&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 5가지로도 해결되지 않는 드문 케이스:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;파일 권한 문제&lt;/b&gt;: tnsnames.ora 읽기 권한이 없는 경우 (chmod 644)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;파일 인코딩 문제&lt;/b&gt;: BOM이 포함된 UTF-8 파일에서 발생 가능 (UTF-8 without BOM으로 저장)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;줄바꿈 문제&lt;/b&gt;: Windows에서 만든 파일을 Linux에서 사용 시 (dos2unix tnsnames.ora)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;LDAP 디렉토리 서버 응답 없음&lt;/b&gt;: NAMES.DIRECTORY_PATH에 LDAP만 있는 경우&lt;/li&gt;
&lt;li&gt;&lt;b&gt;윈도우 레지스트리 충돌&lt;/b&gt;: 여러 ORACLE_HOME 등록 시&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;마무리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ORA-12154는 메시지가 다소 추상적이지만, &lt;b&gt;본질은 &quot;클라이언트가 별칭을 못 풀었다&quot;&lt;/b&gt; 는 단순한 문제입니다. 거의 모든 케이스가 &lt;b&gt;클라이언트 PC의 설정&lt;/b&gt;에 원인이 있으며, 서버는 멀쩡합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;같은 별칭이 다른 PC에서는 잘 되는지&lt;/b&gt; 확인하면 가장 빠른 분리 진단이 가능합니다. 잘 된다면 본인 PC의 환경변수, tnsnames.ora 파일 위치, sqlnet.ora 설정을 차례로 점검하세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;운영 환경에서 ORA-12154 사고를 근본적으로 줄이려면 &lt;b&gt;TNS_ADMIN 표준화&lt;/b&gt;가 가장 좋습니다. 한 경로를 정해 두고 모든 클라이언트가 그 파일을 보도록 강제하면 클라이언트 업그레이드, 신규 설치, 마이그레이션 시 발생하는 95%의 사고를 막을 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이로써 본 블로그의 &lt;b&gt;접속 에러 3종 시리즈(12154, 12541, 12514)&lt;/b&gt; 가 완성되었습니다. 세 에러를 단계별로 이해하면 어떤 접속 문제가 발생해도 빠르게 원인을 좁힐 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비슷한 케이스를 겪으셨거나, 위 방법으로도 해결되지 않은 상황이 있다면 댓글로 공유해 주세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>DBA 실무/Oracle(오라클)</category>
      <category>Easy Connect 직접접속</category>
      <category>NAMES.DIRECTORY_PATH sqlnet.ora</category>
      <category>ORA-12154 갑자기 발생</category>
      <category>ORA-12154 원인</category>
      <category>ORA-12514 해결</category>
      <category>tnsnames.ora 위치</category>
      <category>TNS_ADMIN 설정</category>
      <category>소니스토리</category>
      <category>여러 ORACLE_HOME 충돌</category>
      <category>클라이언트 재설치후 ORA-12154</category>
      <author>isony</author>
      <guid isPermaLink="true">https://isony.tistory.com/336</guid>
      <comments>https://isony.tistory.com/entry/%EC%98%A4%EB%9D%BC%ED%81%B4-%EC%97%90%EB%9F%AC-ORA-12154-TNScould-not-resolve-the-connect-identifier-5%EA%B0%80%EC%A7%80-%EC%9B%90%EC%9D%B8%EA%B3%BC-%ED%95%B4%EA%B2%B0%EB%B0%A9%EB%B2%95-%EC%A0%91%EC%86%8D-%EC%97%90%EB%9F%AC-3%EC%A2%85-%EB%B9%84%EA%B5%90#entry336comment</comments>
      <pubDate>Fri, 19 Jun 2026 08:24:44 +0900</pubDate>
    </item>
    <item>
      <title>[오라클 운영] ROLE 기반 권한 관리 완벽 가이드 - PL/SQL의 함정과 INVOKER rights까지</title>
      <link>https://isony.tistory.com/entry/%EC%98%A4%EB%9D%BC%ED%81%B4-%EC%9A%B4%EC%98%81-ROLE-%EA%B8%B0%EB%B0%98-%EA%B6%8C%ED%95%9C-%EA%B4%80%EB%A6%AC-%EC%99%84%EB%B2%BD-%EA%B0%80%EC%9D%B4%EB%93%9C-PLSQL%EC%9D%98-%ED%95%A8%EC%A0%95%EA%B3%BC-INVOKER-rights%EA%B9%8C%EC%A7%80</link>
      <description>&lt;h1&gt;[오라클 운영] ROLE 기반 권한 관리 완벽 가이드 - PL/SQL의 함정과 INVOKER rights까지&lt;/h1&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;테스트 환경&lt;/b&gt;: Oracle 11g / 12c / 19c / 21c&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오라클 권한 관리에서 ROLE은 핵심 도구입니다. 사용자가 100명, 객체가 1,000개인 환경에서 직접 GRANT를 일일이 관리하면 운영이 마비됩니다. ROLE을 쓰면 권한을 그룹화해서 사용자 단위가 아닌 &lt;b&gt;역할 단위로 관리&lt;/b&gt;할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 ROLE을 운영하다 보면 다음과 같은 황당한 상황을 만나게 됩니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;분명히 ROLE에 SELECT 권한을 줬는데 프로시저가 ORA-00942&lt;/li&gt;
&lt;li&gt;똑같은 SQL인데 SQL*Plus에서는 되고 PL/SQL에서는 안 됨&lt;/li&gt;
&lt;li&gt;ROLE을 부여했는데 다음 세션에서 권한이 사라짐&lt;/li&gt;
&lt;li&gt;직접 GRANT로 바꾸니 갑자기 해결됨&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 글에서는 ROLE의 기본부터 시작해서, &lt;b&gt;PL/SQL에서 ROLE이 무효화되는 보안 설계 이유&lt;/b&gt;, &lt;b&gt;DEFINER vs INVOKER rights의 트레이드오프&lt;/b&gt;, 그리고 운영 환경에서 ROLE을 안전하게 쓰는 표준 패턴까지 정리했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글은 &lt;a href=&quot;https://www.whodo.net/entry/%EC%98%A4%EB%9D%BC%ED%81%B4-%EC%97%90%EB%9F%AC-ORA-00942-table-or-view-does-not-exist-6%EA%B0%80%EC%A7%80-%EC%9B%90%EC%9D%B8%EA%B3%BC-%ED%95%B4%EA%B2%B0%EB%B0%A9%EB%B2%95-%EA%B6%8C%ED%95%9C%EA%B3%BC-PLSQL-%EC%BC%80%EC%9D%B4%EC%8A%A4%EA%B9%8C%EC%A7%80&quot;&gt;ORA-00942 글&lt;/a&gt;의 &quot;원인 4 - PL/SQL 내부 ROLE 무효화&quot;의 후속 심화편입니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;ROLE이란 무엇인가&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ROLE은 &lt;b&gt;권한들의 묶음(이름 있는 권한 집합)&lt;/b&gt; 입니다. 사용자에게 권한을 직접 부여하는 대신, 권한을 ROLE에 부여하고 ROLE을 사용자에게 부여합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;직접 부여 vs ROLE 비교&lt;/h3&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- ❌ 직접 부여 방식 (사용자 100명 &amp;times; 객체 50개 = 5,000번 GRANT)
GRANT SELECT ON hr.employees TO user1;
GRANT SELECT ON hr.departments TO user1;
GRANT SELECT ON hr.employees TO user2;
GRANT SELECT ON hr.departments TO user2;
-- ... 무한 반복

-- ✅ ROLE 방식 (객체 50번 + 사용자 100번 = 150번)
CREATE ROLE ROLE_HR_READ;
GRANT SELECT ON hr.employees TO ROLE_HR_READ;
GRANT SELECT ON hr.departments TO ROLE_HR_READ;
-- ... 객체별 1회씩

GRANT ROLE_HR_READ TO user1;
GRANT ROLE_HR_READ TO user2;
-- ... 사용자별 1회씩
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;운영 환경에서는 ROLE 사용이 표준이며, 권한 회수/감사도 훨씬 간편해집니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;ROLE 기본 문법&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;생성 / 부여 / 회수 / 삭제&lt;/h3&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- 생성
CREATE ROLE ROLE_HR_READ;

-- 비밀번호 보호 ROLE (활성화 시 비밀번호 필요)
CREATE ROLE ROLE_HR_ADMIN IDENTIFIED BY secret_pwd;

-- 권한 부여
GRANT SELECT ON hr.employees TO ROLE_HR_READ;
GRANT EXECUTE ON hr.pkg_payroll TO ROLE_HR_READ;

-- 시스템 권한도 부여 가능
GRANT CREATE SESSION TO ROLE_HR_READ;

-- 사용자에게 ROLE 부여
GRANT ROLE_HR_READ TO scott;

-- ROLE을 다른 ROLE에 부여 (계층 구조)
GRANT ROLE_HR_READ TO ROLE_HR_MANAGER;

-- 회수
REVOKE ROLE_HR_READ FROM scott;

-- 삭제
DROP ROLE ROLE_HR_READ;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;활성화 / 비활성화&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ROLE은 부여된 후에도 &lt;b&gt;세션 단위로 활성/비활성&lt;/b&gt; 상태를 가집니다.&lt;/p&gt;
&lt;pre class=&quot;crmsh&quot;&gt;&lt;code&gt;-- 현재 활성 ROLE 확인
SELECT * FROM session_roles;

-- 특정 ROLE만 활성화 (나머지는 비활성)
SET ROLE ROLE_HR_READ;

-- 모든 ROLE 활성화
SET ROLE ALL;

-- 비밀번호 보호 ROLE 활성화
SET ROLE ROLE_HR_ADMIN IDENTIFIED BY secret_pwd;

-- ROLE 모두 비활성화
SET ROLE NONE;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;기본 활성화 설정&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자가 접속 시 자동으로 활성화할 ROLE을 설정할 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;-- scott이 접속하면 ROLE_HR_READ만 자동 활성화
ALTER USER scott DEFAULT ROLE ROLE_HR_READ;

-- 모든 ROLE 자동 활성화 (기본값)
ALTER USER scott DEFAULT ROLE ALL;

-- 자동 활성화 없음
ALTER USER scott DEFAULT ROLE NONE;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;★ PL/SQL에서 ROLE이 무효화되는 이유 (가장 중요한 부분)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ROLE 운영의 가장 큰 함정입니다. 다른 한국어 블로그에서 거의 다루지 않는 영역이에요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;증상&lt;/h3&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- 1) ROLE에 SELECT 권한 부여
GRANT SELECT ON hr.employees TO ROLE_HR_READ;
GRANT ROLE_HR_READ TO scott;

-- 2) scott으로 접속해서 직접 SQL 실행 &amp;rarr; ✅ 잘 됨
SELECT COUNT(*) FROM hr.employees;
-- COUNT(*)
-- ------
--    107

-- 3) 같은 SQL을 프로시저로 만들기 &amp;rarr; ❌ 컴파일 시 ORA-00942
CREATE OR REPLACE PROCEDURE proc_count_emp AS
    v_cnt NUMBER;
BEGIN
    SELECT COUNT(*) INTO v_cnt FROM hr.employees;
END;
/
-- 컴파일 에러: PL/SQL: ORA-00942: table or view does not exist
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;권한은 분명히 있는데 PL/SQL 안에서만 안 됩니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;왜 이런 설계인가 - 보안 의도&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오라클의 PL/SQL은 기본적으로 &lt;b&gt;DEFINER rights(정의자 권한)&lt;/b&gt; 으로 동작합니다. 그리고 &lt;b&gt;DEFINER rights PL/SQL이 컴파일될 때 ROLE은 모두 disable되어 평가&lt;/b&gt;됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;왜?&lt;/b&gt; 보안 때문입니다. 시나리오를 생각해 봅시다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;사용자 A가 ROLE_READ를 통해 데이터에 접근 가능&lt;/li&gt;
&lt;li&gt;사용자 A가 ROLE 권한으로 프로시저 생성&lt;/li&gt;
&lt;li&gt;나중에 DBA가 사용자 A에게서 ROLE_READ 회수&lt;/li&gt;
&lt;li&gt;&amp;rarr; 프로시저는 여전히 ROLE 권한으로 동작해버림 (보안 구멍)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 시나리오를 막기 위해 &lt;b&gt;DEFINER rights는 직접 부여된 권한만 인정&lt;/b&gt;합니다. ROLE을 통한 우회를 차단하는 보안 메커니즘이에요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;해결 방법 3가지&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;방법 1: 직접 GRANT (가장 흔한 해결)&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;oxygene&quot;&gt;&lt;code&gt;-- 객체 소유자(HR)에서 실행
GRANT SELECT ON employees TO scott;

-- 이후 프로시저 재컴파일
ALTER PROCEDURE proc_count_emp COMPILE;
-- &amp;rarr; 정상 컴파일됨
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;방법 2: INVOKER rights로 변경&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;CREATE OR REPLACE PROCEDURE proc_count_emp
AUTHID CURRENT_USER  -- &amp;larr; 호출자 권한으로 실행, ROLE 인식
AS
    v_cnt NUMBER;
BEGIN
    SELECT COUNT(*) INTO v_cnt FROM hr.employees;
END;
/
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AUTHID CURRENT_USER를 명시하면 &lt;b&gt;호출자의 권한 + ROLE&lt;/b&gt;이 인식됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;방법 3: Dynamic SQL 사용 (우회 기법, 일반적이지 않음)&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;oxygene&quot;&gt;&lt;code&gt;CREATE OR REPLACE PROCEDURE proc_count_emp AS
    v_cnt NUMBER;
BEGIN
    -- 동적 SQL은 런타임에 권한 체크
    EXECUTE IMMEDIATE 'SELECT COUNT(*) FROM hr.employees' INTO v_cnt;
END;
/
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만 이 방식은 가독성이 떨어지고 SQL 인젝션 위험이 있어 추천하지 않습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;DEFINER rights vs INVOKER rights&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 모델의 핵심 차이를 표로 정리합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;항목 DEFINER (기본) INVOKER (AUTHID CURRENT_USER)&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;실행 권한&lt;/td&gt;
&lt;td&gt;프로시저 &lt;b&gt;소유자&lt;/b&gt; 권한&lt;/td&gt;
&lt;td&gt;프로시저 &lt;b&gt;호출자&lt;/b&gt; 권한&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ROLE 인식&lt;/td&gt;
&lt;td&gt;❌ 무효화&lt;/td&gt;
&lt;td&gt;✅ 인식&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;객체 해석&lt;/td&gt;
&lt;td&gt;소유자 스키마 기준&lt;/td&gt;
&lt;td&gt;호출자 스키마 기준&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;같은 코드, 다른 사용자&lt;/td&gt;
&lt;td&gt;항상 같은 동작&lt;/td&gt;
&lt;td&gt;사용자별 다른 동작 가능&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;보안 책임&lt;/td&gt;
&lt;td&gt;소유자&lt;/td&gt;
&lt;td&gt;호출자&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;일반 운영 권장&lt;/td&gt;
&lt;td&gt;비즈니스 로직&lt;/td&gt;
&lt;td&gt;공통 유틸리티&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;시나리오별 선택 가이드&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;DEFINER rights를 써야 할 때:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;비즈니스 로직 (특정 테이블만 다루는 작업)&lt;/li&gt;
&lt;li&gt;보안 캡슐화 (호출자에게 객체 접근 권한 없이 결과만 제공)&lt;/li&gt;
&lt;li&gt;일관된 동작이 필요한 경우&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;INVOKER rights를 써야 할 때:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;공통 유틸리티 (예: 모든 사용자가 자기 데이터를 다루는 함수)&lt;/li&gt;
&lt;li&gt;DBA용 진단 스크립트&lt;/li&gt;
&lt;li&gt;ROLE 권한이 반드시 필요한 경우&lt;/li&gt;
&lt;li&gt;SQL 없는 순수 PL/SQL 패키지 (DBMS_OUTPUT 등)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;실전 예제&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;DEFINER rights 적합 케이스 (기본값):&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- HR 부서의 직원 통계를 모든 사용자에게 제공
-- 하지만 employees 테이블 자체 접근은 금지
CREATE OR REPLACE PROCEDURE get_emp_count(p_dept_id NUMBER, p_count OUT NUMBER)
-- AUTHID DEFINER (기본값, 생략 가능)
AS
BEGIN
    SELECT COUNT(*) INTO p_count
    FROM employees
    WHERE department_id = p_dept_id;
END;
/

-- 모든 사용자가 EXECUTE 권한만 받으면 됨
GRANT EXECUTE ON get_emp_count TO PUBLIC;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;INVOKER rights 적합 케이스:&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;oxygene&quot;&gt;&lt;code&gt;-- 호출자의 스키마에서 자기 테이블 통계를 보여주는 공통 유틸리티
CREATE OR REPLACE PROCEDURE my_table_stats
AUTHID CURRENT_USER  -- 호출자 권한
AS
BEGIN
    FOR rec IN (SELECT table_name, num_rows FROM user_tables) LOOP
        DBMS_OUTPUT.PUT_LINE(rec.table_name || ': ' || rec.num_rows);
    END LOOP;
END;
/
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 프로시저는 SCOTT이 실행하면 SCOTT의 테이블, HR이 실행하면 HR의 테이블을 보여줍니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;★ INVOKER rights의 보안 함정 - INHERIT PRIVILEGES (12c+)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;12c부터 추가된 보안 메커니즘인데, 한국어 자료에 거의 다뤄지지 않는 부분입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;무엇이 문제인가&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;INVOKER rights 프로시저는 &lt;b&gt;호출자의 권한으로 실행&lt;/b&gt;됩니다. 이게 보안적으로 위험할 수 있어요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;시나리오:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;낮은 권한 사용자 LOW_USER가 INVOKER rights 프로시저 작성&lt;/li&gt;
&lt;li&gt;DBA가 이 프로시저를 호출함 (DBA의 권한으로 실행됨)&lt;/li&gt;
&lt;li&gt;LOW_USER가 이 프로시저 안에 악의적 코드를 심으면 DBA 권한으로 동작&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;해결: INHERIT PRIVILEGES 권한&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;12c부터 INVOKER rights 프로시저를 실행하려면 &lt;b&gt;소유자가 호출자의 권한을 상속받을 수 있어야&lt;/b&gt; 합니다.&lt;/p&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;-- LOW_USER가 SCOTT의 권한을 상속받을 수 있도록 허용
GRANT INHERIT PRIVILEGES ON SCOTT TO LOW_USER;

-- 모든 사용자의 권한 상속 가능 (DBA만 부여)
GRANT INHERIT ANY PRIVILEGES TO LOW_USER;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 권한이 없으면 INVOKER rights 프로시저 실행 시 &lt;b&gt;ORA-06598: insufficient INHERIT PRIVILEGES privilege&lt;/b&gt; 가 발생합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;기본 정책&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;12c 신규 설치 시 기본적으로:&lt;/p&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;GRANT INHERIT PRIVILEGES ON 모든사용자 TO PUBLIC;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 설정이 들어가 있습니다. 그래서 평소엔 문제없이 동작합니다. &lt;b&gt;다만 보안 강화 환경에서 이걸 REVOKE했다면 ORA-06598 사고가 발생할 수 있습니다.&lt;/b&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;실무 권장&lt;/h3&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;-- DBA가 모든 사용자에게서 PUBLIC INHERIT 회수
REVOKE INHERIT PRIVILEGES ON SCOTT FROM PUBLIC;

-- 신뢰할 수 있는 사용자에게만 명시적으로 부여
GRANT INHERIT PRIVILEGES ON SCOTT TO trusted_user;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;운영 환경의 보안 정책에 따라 결정하세요.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;ROLE 표준 운영 패턴&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;권장 ROLE 계층 구조&lt;/h3&gt;
&lt;pre class=&quot;less&quot;&gt;&lt;code&gt;사용자
  &amp;darr; GRANT
ROLE_HR_MANAGER (관리자)
  &amp;darr; 포함
ROLE_HR_WRITE (쓰기)
  &amp;darr; 포함
ROLE_HR_READ (읽기)
  &amp;darr; GRANT
객체 권한 (SELECT, INSERT, ...)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;구현 예제&lt;/h3&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- 1) 기본 읽기 ROLE
CREATE ROLE ROLE_HR_READ;
GRANT SELECT ON hr.employees TO ROLE_HR_READ;
GRANT SELECT ON hr.departments TO ROLE_HR_READ;

-- 2) 쓰기 ROLE (읽기 권한 포함)
CREATE ROLE ROLE_HR_WRITE;
GRANT ROLE_HR_READ TO ROLE_HR_WRITE;  -- 계층 구조
GRANT INSERT, UPDATE, DELETE ON hr.employees TO ROLE_HR_WRITE;

-- 3) 관리자 ROLE (쓰기 권한 포함)
CREATE ROLE ROLE_HR_MANAGER;
GRANT ROLE_HR_WRITE TO ROLE_HR_MANAGER;
GRANT EXECUTE ON hr.pkg_admin TO ROLE_HR_MANAGER;

-- 4) 사용자에게 적절한 레벨 부여
GRANT ROLE_HR_READ TO analyst_user;
GRANT ROLE_HR_WRITE TO operator_user;
GRANT ROLE_HR_MANAGER TO admin_user;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 하면 사용자 역할 변경 시 ROLE 한 줄만 변경하면 됩니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;PL/SQL 호출 사용자를 위한 별도 처리&lt;/h3&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- PL/SQL 안에서 사용할 권한은 직접 GRANT
GRANT SELECT ON hr.employees TO batch_user;
GRANT SELECT ON hr.departments TO batch_user;

-- 일반 조회용은 ROLE로
GRANT ROLE_HR_READ TO batch_user;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;같은 사용자에게 ROLE과 직접 GRANT를 병행하는 것이 운영 환경의 일반적 패턴입니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;자주 발생하는 함정과 진단 쿼리&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;함정 1: 권한이 있는지 헷갈릴 때&lt;/h3&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- 현재 사용자의 직접 부여 권한
SELECT * FROM user_tab_privs;

-- ROLE 통해 받은 권한
SELECT * FROM role_tab_privs
WHERE role IN (SELECT granted_role FROM user_role_privs);

-- 두 가지 합쳐서 보기 (실효 권한)
SELECT 'DIRECT' AS source, table_name, privilege, NULL AS via_role
FROM   user_tab_privs
UNION ALL
SELECT 'ROLE', rtp.table_name, rtp.privilege, urp.granted_role
FROM   role_tab_privs rtp
JOIN   user_role_privs urp ON rtp.role = urp.granted_role;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;함정 2: PL/SQL 컴파일 시 ORA-00942&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원인 90%는 ROLE 권한 의존. 위에서 다룬 3가지 해결 방법 적용.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;함정 3: ROLE이 활성화되지 않음&lt;/h3&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- 부여된 ROLE 확인
SELECT * FROM user_role_privs;

-- 활성 ROLE 확인
SELECT * FROM session_roles;

-- 차이가 있으면 비활성 상태
SET ROLE 부여된_role_명;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;함정 4: 보안 검토 시 ROLE 계층 추적&lt;/h3&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- 특정 ROLE을 받은 모든 사용자/ROLE 추적 (재귀)
SELECT LEVEL, grantee, granted_role
FROM   dba_role_privs
START  WITH granted_role = 'ROLE_HR_READ'
CONNECT BY PRIOR grantee = granted_role;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 쿼리로 ROLE 변경 시 영향받는 사용자를 미리 파악할 수 있습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;마무리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ROLE은 오라클 권한 관리의 표준 도구지만, &lt;b&gt;PL/SQL의 DEFINER rights와 함께 쓸 때 발생하는 함정&lt;/b&gt;을 모르면 운영 사고로 직결됩니다. 핵심을 다시 한 번 정리하면:&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;DEFINER rights PL/SQL에서 ROLE 권한은 무효화됨&lt;/b&gt; &amp;mdash; 보안 설계이며 의도된 동작&lt;/li&gt;
&lt;li&gt;&lt;b&gt;PL/SQL용 권한은 직접 GRANT가 표준&lt;/b&gt; &amp;mdash; ROLE이 아니라 직접 부여&lt;/li&gt;
&lt;li&gt;&lt;b&gt;INVOKER rights (AUTHID CURRENT_USER)&lt;/b&gt; &amp;mdash; ROLE 인식 가능, 단 보안 영향 고려&lt;/li&gt;
&lt;li&gt;&lt;b&gt;12c+ INHERIT PRIVILEGES&lt;/b&gt; &amp;mdash; INVOKER rights 보안 강화 메커니즘 숙지&lt;/li&gt;
&lt;li&gt;&lt;b&gt;계층 구조&lt;/b&gt; &amp;mdash; READ &amp;rarr; WRITE &amp;rarr; ADMIN 같은 단계로 설계&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;운영 환경에서 ROLE을 도입할 때 가장 좋은 방법은 &lt;b&gt;초기 설계 단계에서 PL/SQL 호출 패턴을 미리 식별&lt;/b&gt;하는 것입니다. 어떤 사용자가 PL/SQL을 통해 권한을 사용할지, 어떤 권한이 ROLE로 충분하고 어떤 권한은 직접 부여가 필요한지 미리 정리하면 ORA-00942 사고의 90%는 예방 가능합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비슷한 ROLE 운영 사례나 더 좋은 패턴이 있다면 댓글로 공유해 주세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>DBA 실무/Oracle(오라클)</category>
      <category>CREATE ROLE</category>
      <category>GRANT ROLE</category>
      <category>ORA-06598</category>
      <category>PL/SQL ROLE 무효화</category>
      <category>PL/SQL ROLE 안됨</category>
      <category>ROLE 계층구조</category>
      <category>소니스토리</category>
      <category>오라클 ROLE 사용법</category>
      <category>오라클 권한관리</category>
      <category>프로시져 ORA-00942 ROLE</category>
      <author>isony</author>
      <guid isPermaLink="true">https://isony.tistory.com/335</guid>
      <comments>https://isony.tistory.com/entry/%EC%98%A4%EB%9D%BC%ED%81%B4-%EC%9A%B4%EC%98%81-ROLE-%EA%B8%B0%EB%B0%98-%EA%B6%8C%ED%95%9C-%EA%B4%80%EB%A6%AC-%EC%99%84%EB%B2%BD-%EA%B0%80%EC%9D%B4%EB%93%9C-PLSQL%EC%9D%98-%ED%95%A8%EC%A0%95%EA%B3%BC-INVOKER-rights%EA%B9%8C%EC%A7%80#entry335comment</comments>
      <pubDate>Wed, 17 Jun 2026 08:00:39 +0900</pubDate>
    </item>
    <item>
      <title>[오라클 운영] DBMS_SCHEDULER 캘린더 표현식 완벽 정리 - FREQ, BYHOUR, BYDAY 모든 활용</title>
      <link>https://isony.tistory.com/entry/%EC%98%A4%EB%9D%BC%ED%81%B4-%EC%9A%B4%EC%98%81-DBMSSCHEDULER-%EC%BA%98%EB%A6%B0%EB%8D%94-%ED%91%9C%ED%98%84%EC%8B%9D-%EC%99%84%EB%B2%BD-%EC%A0%95%EB%A6%AC-FREQ-BYHOUR-BYDAY-%EB%AA%A8%EB%93%A0-%ED%99%9C%EC%9A%A9</link>
      <description>&lt;h1&gt;[오라클 운영] DBMS_SCHEDULER 캘린더 표현식 완벽 정리 - FREQ, BYHOUR, BYDAY 모든 활용&lt;/h1&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;테스트 환경&lt;/b&gt;: Oracle 11g / 12c / 19c / 21c&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DBMS_SCHEDULER로 작업을 등록할 때 가장 헷갈리는 부분이 &lt;b&gt;repeat_interval 표현식&lt;/b&gt;입니다. 단순한 &quot;매일 새벽 2시&quot;는 쉽지만, &lt;b&gt;&quot;매월 마지막 평일 18시&quot;&lt;/b&gt;, &lt;b&gt;&quot;매분기 첫 번째 월요일&quot;&lt;/b&gt;, &lt;b&gt;&quot;공휴일 제외 평일 9시&quot;&lt;/b&gt; 같은 요구사항을 받으면 막막해집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글은 &lt;a href=&quot;https://www.whodo.net/entry/%EC%98%A4%EB%9D%BC%ED%81%B4-%EC%8B%A4%EB%AC%B4-DBMSSCHEDULER%EB%A1%9C-%ED%94%84%EB%A1%9C%EC%8B%9C%EC%A0%80%EB%A5%BC-6%EC%8B%9C%EA%B0%84-%EB%8B%A8%EC%9C%84-%EC%8B%A4%ED%96%89%ED%95%98%EA%B8%B0-%EB%8F%99%EC%A0%81-%EC%9D%B8%EC%9E%90-%EC%A0%84%EB%8B%AC-%EC%99%84%EB%B2%BD-%EC%98%88%EC%A0%9C&quot;&gt;이전 글 (DBMS_SCHEDULER 6시간 배치 예제)&lt;/a&gt;의 후속편입니다. 거기서는 한 가지 시나리오만 다뤘다면, 이번 글은 &lt;b&gt;운영 환경에서 자주 만나는 모든 스케줄 표현식을 카탈로그처럼 정리&lt;/b&gt;했습니다. 책갈피해 두고 필요할 때마다 꺼내 쓰는 레퍼런스 글로 활용하세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;급하신 분은 &lt;u&gt;자주 쓰는 표현식 모음&lt;/u&gt;부터 보세요.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;기본 문법 - 한 번에 정리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;캘린더 표현식의 전체 구조입니다.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;repeat_interval = 
    FREQ=빈도
    [; INTERVAL=숫자]
    [; BYMONTH=월목록]
    [; BYWEEKNO=주차]
    [; BYYEARDAY=일자]
    [; BYMONTHDAY=일목록]
    [; BYDAY=요일목록]
    [; BYHOUR=시목록]
    [; BYMINUTE=분목록]
    [; BYSECOND=초목록]
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;규칙&lt;/b&gt;:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;FREQ는 필수, 나머지는 선택&lt;/li&gt;
&lt;li&gt;각 절은 세미콜론(;)으로 구분&lt;/li&gt;
&lt;li&gt;절 안의 여러 값은 콤마(,)로 구분 (예: BYHOUR=4,10,16,22)&lt;/li&gt;
&lt;li&gt;대소문자 구분 없음 (관습적으로 대문자)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;FREQ - 7가지 빈도&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;FREQ 값 의미&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;YEARLY&lt;/td&gt;
&lt;td&gt;매년&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MONTHLY&lt;/td&gt;
&lt;td&gt;매월&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WEEKLY&lt;/td&gt;
&lt;td&gt;매주&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DAILY&lt;/td&gt;
&lt;td&gt;매일&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HOURLY&lt;/td&gt;
&lt;td&gt;매시간&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MINUTELY&lt;/td&gt;
&lt;td&gt;매분&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SECONDLY&lt;/td&gt;
&lt;td&gt;매초&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;BY 절 핵심 9가지&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;절 가능한 값 음수 의미&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;BYMONTH&lt;/td&gt;
&lt;td&gt;1~12 또는 JAN~DEC&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BYMONTHDAY&lt;/td&gt;
&lt;td&gt;1~31, -1~-31&lt;/td&gt;
&lt;td&gt;-1 = 마지막 날&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BYDAY&lt;/td&gt;
&lt;td&gt;MON,TUE,WED,THU,FRI,SAT,SUN&lt;/td&gt;
&lt;td&gt;-1FRI = 마지막 금요일&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BYHOUR&lt;/td&gt;
&lt;td&gt;0~23&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BYMINUTE&lt;/td&gt;
&lt;td&gt;0~59&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BYSECOND&lt;/td&gt;
&lt;td&gt;0~59&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BYYEARDAY&lt;/td&gt;
&lt;td&gt;1~366, -1~-366&lt;/td&gt;
&lt;td&gt;-1 = 연중 마지막 날&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BYWEEKNO&lt;/td&gt;
&lt;td&gt;1~53&lt;/td&gt;
&lt;td&gt;-1 = 마지막 주&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BYSETPOS&lt;/td&gt;
&lt;td&gt;-366~366&lt;/td&gt;
&lt;td&gt;-1 = 매치 중 마지막&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;INTERVAL - 빈도 간격&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;INTERVAL=N은 &quot;FREQ N번마다 한 번&quot;입니다.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;FREQ=DAILY; INTERVAL=10    -- 10일마다
FREQ=HOURLY; INTERVAL=6    -- 6시간마다
FREQ=WEEKLY; INTERVAL=2    -- 격주
FREQ=MONTHLY; INTERVAL=3   -- 분기마다
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;주의&lt;/b&gt;: FREQ=HOURLY; INTERVAL=6은 &quot;6시간 간격&quot;이지 &quot;04, 10, 16, 22시 정각&quot;이 아닙니다. &lt;b&gt;정확한 시각을 원하면 BYHOUR를 쓰세요.&lt;/b&gt; &lt;a href=&quot;https://www.whodo.net/entry/%EC%98%A4%EB%9D%BC%ED%81%B4-%EC%8B%A4%EB%AC%B4-DBMSSCHEDULER%EB%A1%9C-%ED%94%84%EB%A1%9C%EC%8B%9C%EC%A0%80%EB%A5%BC-6%EC%8B%9C%EA%B0%84-%EB%8B%A8%EC%9C%84-%EC%8B%A4%ED%96%89%ED%95%98%EA%B8%B0-%EB%8F%99%EC%A0%81-%EC%9D%B8%EC%9E%90-%EC%A0%84%EB%8B%AC-%EC%99%84%EB%B2%BD-%EC%98%88%EC%A0%9C&quot;&gt;이전 글의 함정&lt;/a&gt; 참고.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;자주 쓰는 표현식 모음 - 케이스별&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;운영 환경에서 가장 많이 만나는 시나리오들입니다. 그대로 복붙해서 활용하세요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  일 단위&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원하는 동작 표현식&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;매일 자정&lt;/td&gt;
&lt;td&gt;FREQ=DAILY;BYHOUR=0;BYMINUTE=0;BYSECOND=0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;매일 새벽 2시 30분&lt;/td&gt;
&lt;td&gt;FREQ=DAILY;BYHOUR=2;BYMINUTE=30;BYSECOND=0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;매일 4번 (04, 10, 16, 22시)&lt;/td&gt;
&lt;td&gt;FREQ=DAILY;BYHOUR=4,10,16,22;BYMINUTE=0;BYSECOND=0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;매일 영업시간만 (9~18시, 매시간 정각)&lt;/td&gt;
&lt;td&gt;FREQ=HOURLY;BYHOUR=9,10,11,12,13,14,15,16,17,18&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10일에 한 번&lt;/td&gt;
&lt;td&gt;FREQ=DAILY;INTERVAL=10&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  주 단위&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원하는 동작 표현식&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;매주 월요일 9시&lt;/td&gt;
&lt;td&gt;FREQ=WEEKLY;BYDAY=MON;BYHOUR=9;BYMINUTE=0;BYSECOND=0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;평일만 (월~금) 9시&lt;/td&gt;
&lt;td&gt;FREQ=DAILY;BYDAY=MON,TUE,WED,THU,FRI;BYHOUR=9&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;주말만 (토~일) 자정&lt;/td&gt;
&lt;td&gt;FREQ=DAILY;BYDAY=SAT,SUN;BYHOUR=0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;격주 금요일 18시&lt;/td&gt;
&lt;td&gt;FREQ=WEEKLY;INTERVAL=2;BYDAY=FRI;BYHOUR=18&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;매주 월수금 새벽 6시&lt;/td&gt;
&lt;td&gt;FREQ=WEEKLY;BYDAY=MON,WED,FRI;BYHOUR=6&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  월 단위&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원하는 동작 표현식&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;매월 1일 자정&lt;/td&gt;
&lt;td&gt;FREQ=MONTHLY;BYMONTHDAY=1;BYHOUR=0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;매월 15일 새벽 3시&lt;/td&gt;
&lt;td&gt;FREQ=MONTHLY;BYMONTHDAY=15;BYHOUR=3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;매월 마지막 날 23시&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;FREQ=MONTHLY;BYMONTHDAY=-1;BYHOUR=23&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;매월 마지막 평일 18시&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;FREQ=MONTHLY;BYDAY=MON,TUE,WED,THU,FRI;BYSETPOS=-1;BYHOUR=18&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;매월 첫째 월요일&lt;/td&gt;
&lt;td&gt;FREQ=MONTHLY;BYDAY=1MON&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;매월 둘째 수요일&lt;/td&gt;
&lt;td&gt;FREQ=MONTHLY;BYDAY=2WED&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;매월 마지막 금요일&lt;/td&gt;
&lt;td&gt;FREQ=MONTHLY;BYDAY=-1FRI&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;분기마다 (1, 4, 7, 10월 1일)&lt;/td&gt;
&lt;td&gt;FREQ=MONTHLY;BYMONTH=1,4,7,10;BYMONTHDAY=1&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  연 단위&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원하는 동작 표현식&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;매년 1월 1일 자정&lt;/td&gt;
&lt;td&gt;FREQ=YEARLY;BYMONTH=1;BYMONTHDAY=1;BYHOUR=0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;매년 12월 31일 23:59&lt;/td&gt;
&lt;td&gt;FREQ=YEARLY;BYMONTH=12;BYMONTHDAY=31;BYHOUR=23;BYMINUTE=59&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;매년 마지막 평일&lt;/td&gt;
&lt;td&gt;FREQ=YEARLY;BYDAY=MON,TUE,WED,THU,FRI;BYSETPOS=-1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;매년 첫째 월요일&lt;/td&gt;
&lt;td&gt;FREQ=YEARLY;BYDAY=1MON&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  시간/분/초 단위&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원하는 동작 표현식&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;매시간 정각&lt;/td&gt;
&lt;td&gt;FREQ=HOURLY;BYMINUTE=0;BYSECOND=0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;매시간 30분&lt;/td&gt;
&lt;td&gt;FREQ=HOURLY;BYMINUTE=30;BYSECOND=0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5분마다&lt;/td&gt;
&lt;td&gt;FREQ=MINUTELY;INTERVAL=5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;15분마다 (정각, 15, 30, 45)&lt;/td&gt;
&lt;td&gt;FREQ=HOURLY;BYMINUTE=0,15,30,45&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;매분 정각&lt;/td&gt;
&lt;td&gt;FREQ=MINUTELY;BYSECOND=0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;30초마다&lt;/td&gt;
&lt;td&gt;FREQ=SECONDLY;INTERVAL=30&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;★ BYDAY 음수 / N번째 표현 - 가장 강력한 기능&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;BYDAY는 단순 요일 외에도 &lt;b&gt;&quot;N번째 요일&quot;&lt;/b&gt; 또는 &lt;b&gt;&quot;마지막 요일&quot;&lt;/b&gt; 을 표현할 수 있습니다. 이걸 알면 복잡한 스케줄도 한 줄로 해결됩니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;표기 규칙&lt;/h3&gt;
&lt;pre class=&quot;cs&quot;&gt;&lt;code&gt;[숫자]요일
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;표현 의미&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;MON&lt;/td&gt;
&lt;td&gt;매주 월요일&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1MON&lt;/td&gt;
&lt;td&gt;첫째 월요일&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2MON&lt;/td&gt;
&lt;td&gt;둘째 월요일&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;-1MON&lt;/td&gt;
&lt;td&gt;마지막 월요일&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;-2MON&lt;/td&gt;
&lt;td&gt;마지막에서 두 번째 월요일&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;실전 예시&lt;/h3&gt;
&lt;pre class=&quot;lsl&quot;&gt;&lt;code&gt;-- 매월 두 번째 월요일 10시 (이사회 같은 정기 일정)
'FREQ=MONTHLY;BYDAY=2MON;BYHOUR=10'

-- 매월 마지막 토요일 자정 (월말 백업)
'FREQ=MONTHLY;BYDAY=-1SAT;BYHOUR=0'

-- 매분기 첫째 수요일 (분기 정산)
'FREQ=MONTHLY;BYMONTH=1,4,7,10;BYDAY=1WED'
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;★ BYSETPOS - 매치 결과 중 N번째 선택&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;BYSETPOS는 다른 BY 절의 결과 집합 중에서 &lt;b&gt;N번째만&lt;/b&gt; 선택합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;가장 유용한 예시: &quot;매월 마지막 평일&quot;&lt;/h3&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;-- BYDAY는 평일 전부를 매치, BYSETPOS=-1로 마지막만
FREQ=MONTHLY; BYDAY=MON,TUE,WED,THU,FRI; BYSETPOS=-1
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 표현식은 매월 마지막 날이 토요일이라도 그 전 금요일을 선택합니다. 즉, &lt;b&gt;달력상 마지막 평일&lt;/b&gt;을 정확히 잡습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;더 활용 예시&lt;/h3&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;-- 매월 첫 번째 평일 9시 (월초 정산 시작)
FREQ=MONTHLY; BYDAY=MON,TUE,WED,THU,FRI; BYSETPOS=1; BYHOUR=9

-- 매월 마지막에서 두 번째 평일
FREQ=MONTHLY; BYDAY=MON,TUE,WED,THU,FRI; BYSETPOS=-2

-- 분기 마지막 평일 18시 (분기 마감)
FREQ=MONTHLY; BYMONTH=3,6,9,12; BYDAY=MON,TUE,WED,THU,FRI; BYSETPOS=-1; BYHOUR=18
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;★ INCLUDE / EXCLUDE - 공휴일 처리 (실무 핵심)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한국어 자료에 거의 없는 강력한 기능입니다. &lt;b&gt;다른 schedule을 참조해서 포함/제외&lt;/b&gt;할 수 있습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;시나리오: 공휴일 제외하고 평일에만 실행&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1단계: 공휴일 schedule 정의&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;1c&quot;&gt;&lt;code&gt;-- 2026년 공휴일 schedule 생성
BEGIN
    DBMS_SCHEDULER.CREATE_SCHEDULE(
        schedule_name =&amp;gt; 'KOREA_HOLIDAYS_2026',
        start_date    =&amp;gt; SYSTIMESTAMP,
        repeat_interval =&amp;gt; 'FREQ=YEARLY;BYDATE=20260101,20260301,20260505,' ||
                           '20260606,20260815,20261003,20261009,20261225'
    );
END;
/
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2단계: 작업 schedule에서 EXCLUDE 사용&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;php&quot;&gt;&lt;code&gt;BEGIN
    DBMS_SCHEDULER.CREATE_JOB(
        job_name        =&amp;gt; 'JOB_WORKDAY_BATCH',
        job_type        =&amp;gt; 'STORED_PROCEDURE',
        job_action      =&amp;gt; 'PKG_BATCH.RUN_DAILY',
        repeat_interval =&amp;gt; 'FREQ=DAILY;BYDAY=MON,TUE,WED,THU,FRI;' ||
                           'EXCLUDE=KOREA_HOLIDAYS_2026;BYHOUR=2',
        enabled         =&amp;gt; TRUE
    );
END;
/
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 하면 평일이라도 공휴일이면 실행되지 않습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;INCLUDE / INTERSECT의 차이&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;키워드 의미&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;INCLUDE&lt;/td&gt;
&lt;td&gt;참조 schedule의 날짜를 &lt;b&gt;추가&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;EXCLUDE&lt;/td&gt;
&lt;td&gt;참조 schedule의 날짜를 &lt;b&gt;제외&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;INTERSECT&lt;/td&gt;
&lt;td&gt;참조 schedule과 &lt;b&gt;공통된&lt;/b&gt; 날짜만&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;pre class=&quot;1c&quot;&gt;&lt;code&gt;-- 평일 + 공휴일에도 실행 (휴일에도 점검)
'FREQ=DAILY;BYDAY=MON,TUE,WED,THU,FRI;INCLUDE=KOREA_HOLIDAYS_2026'

-- 공휴일에만 실행
'FREQ=DAILY;INTERSECT=KOREA_HOLIDAYS_2026'
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;BYDATE - 특정 날짜 직접 지정&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;BYDATE는 MMDD 또는 YYYYMMDD 형식으로 특정 날짜를 직접 지정합니다.&lt;/p&gt;
&lt;pre class=&quot;lsl&quot;&gt;&lt;code&gt;-- 매년 1월 1일과 12월 25일
'FREQ=YEARLY;BYDATE=0101,1225'

-- 특정 연도의 특정 날짜
'FREQ=YEARLY;BYDATE=20260315,20260920'

-- 분기 마지막 날 (3, 6, 9, 12월의 마지막 날)
'FREQ=MONTHLY;BYMONTH=3,6,9,12;BYMONTHDAY=-1'
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공휴일이나 특별 이벤트일을 한꺼번에 처리할 때 유용합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;★ 검증 방법 - EVALUATE_CALENDAR_STRING&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;복잡한 표현식을 만들었다면 &lt;b&gt;실제 등록 전에 다음 N번의 실행 시각을 미리 확인&lt;/b&gt;해야 합니다. 그렇지 않으면 의도와 다른 시각에 실행되는 사고가 납니다.&lt;/p&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;SET SERVEROUTPUT ON

DECLARE
    v_start   TIMESTAMP WITH TIME ZONE := SYSTIMESTAMP;
    v_next    TIMESTAMP WITH TIME ZONE;
BEGIN
    DBMS_OUTPUT.PUT_LINE('검증할 표현식: FREQ=MONTHLY;BYDAY=MON,TUE,WED,THU,FRI;BYSETPOS=-1;BYHOUR=18');
    DBMS_OUTPUT.PUT_LINE('-----------------------------------');
    
    FOR i IN 1..10 LOOP
        DBMS_SCHEDULER.EVALUATE_CALENDAR_STRING(
            calendar_string   =&amp;gt; 'FREQ=MONTHLY;BYDAY=MON,TUE,WED,THU,FRI;BYSETPOS=-1;BYHOUR=18',
            start_date        =&amp;gt; SYSTIMESTAMP,
            return_date_after =&amp;gt; v_start,
            next_run_date     =&amp;gt; v_next
        );
        DBMS_OUTPUT.PUT_LINE(i || '회차: ' || 
            TO_CHAR(v_next, 'YYYY-MM-DD (DY) HH24:MI:SS'));
        v_start := v_next;
    END LOOP;
END;
/
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;출력 예시:&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;1회차: 2026-05-29 (FRI) 18:00:00
2회차: 2026-06-30 (TUE) 18:00:00
3회차: 2026-07-31 (FRI) 18:00:00
4회차: 2026-08-31 (MON) 18:00:00
...
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이 검증 단계를 생략하지 마세요.&lt;/b&gt; 실수의 95%가 여기서 잡힙니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;자주 발생하는 함정 5가지&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;함정 1: BY 절 생략 시 start_date 값이 적용됨&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;-- start_date가 2026-06-01 09:23:17 인데
-- BYHOUR을 생략
'FREQ=DAILY'
-- &amp;rarr; 매일 09:23:17에 실행됨 (09:00 아님!)
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해결: 정확한 시각을 원하면 항상 BYHOUR, BYMINUTE, BYSECOND를 명시.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;함정 2: HOURLY INTERVAL의 시작점&lt;/h3&gt;
&lt;pre class=&quot;lsl&quot;&gt;&lt;code&gt;-- &quot;6시간마다&quot;라고 등록했는데
'FREQ=HOURLY;INTERVAL=6'
-- &amp;rarr; start_date에 따라 09, 15, 21, 03시 식으로 어긋날 수 있음
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해결: 정확한 시각을 원하면 BYHOUR=4,10,16,22 같이 명시.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;함정 3: 31일 없는 달의 처리&lt;/h3&gt;
&lt;pre class=&quot;lsl&quot;&gt;&lt;code&gt;'FREQ=MONTHLY;BYMONTHDAY=31'
-- &amp;rarr; 2월은 매치 없음 &amp;rarr; 실행 안 됨
-- &amp;rarr; 4월, 6월, 9월, 11월도 매치 없음
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해결: &quot;매월 말일&quot;이 목적이면 BYMONTHDAY=-1 사용.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;함정 4: 타임존 불일치&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;19c부터 DBMS_SCHEDULER가 세션 타임존을 사용합니다. UTC 환경 서버에서 한국 시간 9시를 의도했는데 새벽 6시(KST)에 실행되는 사고가 자주 발생합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해결: start_date에 명시적 타임존 지정.&lt;/p&gt;
&lt;pre class=&quot;lisp&quot;&gt;&lt;code&gt;start_date =&amp;gt; TO_TIMESTAMP_TZ('2026-06-01 09:00:00 Asia/Seoul',
                              'YYYY-MM-DD HH24:MI:SS TZR')
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;함정 5: 음수 BYDAY 표기 오류&lt;/h3&gt;
&lt;pre class=&quot;ada&quot;&gt;&lt;code&gt;-- ❌ 잘못된 표기 (공백 들어감)
'FREQ=MONTHLY;BYDAY=-1 FRI'

-- ✅ 올바른 표기 (붙여 씀)
'FREQ=MONTHLY;BYDAY=-1FRI'
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;음수와 요일 사이에 공백을 넣으면 파싱 오류가 발생합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;운영 환경 권장 표준&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;작업 등록 표준 패턴&lt;/h3&gt;
&lt;pre class=&quot;php&quot;&gt;&lt;code&gt;BEGIN
    DBMS_SCHEDULER.CREATE_JOB(
        job_name        =&amp;gt; 'JOB_명칭',
        job_type        =&amp;gt; 'PLSQL_BLOCK',
        job_action      =&amp;gt; '...',
        -- start_date에 명시적 타임존
        start_date      =&amp;gt; TO_TIMESTAMP_TZ(
                              '2026-06-01 02:00:00 Asia/Seoul',
                              'YYYY-MM-DD HH24:MI:SS TZR'),
        -- 정확한 시각 위해 BYHOUR/BYMINUTE/BYSECOND 모두 명시
        repeat_interval =&amp;gt; 'FREQ=DAILY;BYHOUR=2;BYMINUTE=0;BYSECOND=0',
        enabled         =&amp;gt; TRUE,
        comments        =&amp;gt; '명확한 작업 설명'
    );
END;
/
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;체크리스트&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;[ ] BY 절 누락 없는가? (HOUR, MINUTE, SECOND)&lt;/li&gt;
&lt;li&gt;[ ] EVALUATE_CALENDAR_STRING으로 검증했는가?&lt;/li&gt;
&lt;li&gt;[ ] start_date에 타임존을 명시했는가?&lt;/li&gt;
&lt;li&gt;[ ] 공휴일 처리가 필요한가? (EXCLUDE 활용)&lt;/li&gt;
&lt;li&gt;[ ] 31일/말일 처리에 함정이 없는가?&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;마무리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DBMS_SCHEDULER의 캘린더 표현식은 처음엔 복잡해 보이지만, &lt;b&gt;빈도(FREQ) + BY 절 조합&lt;/b&gt; 이라는 단순한 구조입니다. 자주 쓰는 패턴 10여 개만 익혀 두면 운영 환경의 거의 모든 스케줄을 한 줄로 표현할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히 &lt;b&gt;BYSETPOS와 EXCLUDE 같은 고급 기능&lt;/b&gt;은 운영 현장에서 정말 강력합니다. &quot;마지막 평일&quot;이나 &quot;공휴일 제외&quot; 같은 요구사항을 트리거나 별도 스크립트로 우회하지 마세요. 캘린더 표현식 한 줄로 깔끔하게 해결됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 중요한 건 &lt;b&gt;등록 전 EVALUATE_CALENDAR_STRING으로 검증하는 습관&lt;/b&gt;입니다. 운영에 들어간 후 의도와 다르게 동작하는 스케줄을 잡는 것보다 100배 빠릅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비슷한 스케줄링 요구사항이나 더 좋은 패턴이 있다면 댓글로 공유해 주세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>DBA 실무/Oracle(오라클)</category>
      <category>DBMS_SCHEDULER BYHOUR</category>
      <category>DBMS_SCHEDULER 공휴일 제외</category>
      <category>DBMS_SCHEDULER 타임존 어긋남</category>
      <category>DBMS_SCHEDULER 표현식</category>
      <category>repeat_interval 안됨</category>
      <category>매월 마지막 평일 스케줄</category>
      <category>소니스토리</category>
      <category>오라클 스케줄러 매일</category>
      <category>오라클 스케줄러 매주</category>
      <category>오라클 스케줄러 안됨</category>
      <author>isony</author>
      <guid isPermaLink="true">https://isony.tistory.com/334</guid>
      <comments>https://isony.tistory.com/entry/%EC%98%A4%EB%9D%BC%ED%81%B4-%EC%9A%B4%EC%98%81-DBMSSCHEDULER-%EC%BA%98%EB%A6%B0%EB%8D%94-%ED%91%9C%ED%98%84%EC%8B%9D-%EC%99%84%EB%B2%BD-%EC%A0%95%EB%A6%AC-FREQ-BYHOUR-BYDAY-%EB%AA%A8%EB%93%A0-%ED%99%9C%EC%9A%A9#entry334comment</comments>
      <pubDate>Mon, 15 Jun 2026 08:11:27 +0900</pubDate>
    </item>
    <item>
      <title>2026년06월14일 주일예배 (이재훈목사님) - 1부</title>
      <link>https://isony.tistory.com/entry/2026%EB%85%8406%EC%9B%9414%EC%9D%BC-%EC%A3%BC%EC%9D%BC%EC%98%88%EB%B0%B0-%EC%9D%B4%EC%9E%AC%ED%9B%88%EB%AA%A9%EC%82%AC%EB%8B%98-1%EB%B6%80</link>
      <description>&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;2026년06월14일 주일예배 (이재훈목사님) - 1부&lt;/h2&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;주의 말씀 : 나를 따르라&amp;nbsp; (5)&lt;/h2&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;마르지 않는 시냇가에 뿌리를 내리다&lt;/h2&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;성경 :&amp;nbsp; 시편(Psalm) 1:1 ~ 6 말씀 (출처:우리말성경)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&amp;lt; 성경 &amp;gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;1:1 복이 있는 사람은 악한 사람들의 꾀를 따라가지 않고 죄인들의 길에 서지 않으며 남을 업신여기는 사람들과 자리를 함께하지 않고&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;1:2 오직 여호와의 율법을 즐거워하고 그 율법을 밤낮으로 깊이 생각하는 자로다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;1:3 그는 시냇가에 심은 나무가 계절에 따라 열매를 맺고 그 잎이 시들지 않는 것처럼 하는 일마다 모두 잘되리라.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;1:4 악인은 그렇지 않으니 그저 바람에 날려가는 겨와 같도다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;1:5 그러므로 악인들이 심판을 받을 때 죄인들은 의인의 모임에 참석하지 못하리라.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;1:6 의인의 길은 여호와께서 보호하시나 악인의 길은 망하리라.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&amp;lt; 예배 영상 &amp;gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;a href=&quot;https://youtu.be/5IKoRqCooxk&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://youtu.be/5IKoRqCooxk&lt;/a&gt;&lt;/b&gt;&lt;/p&gt;
&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignCenter&quot; data-video-host=&quot;youtube&quot; data-video-url=&quot;https://www.youtube.com/watch?v=5IKoRqCooxk&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/cxDCIs/dJMb8Xkn33K/CC1dIdM3PZrZwkTBsY64r1/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=554_130_714_304,https://scrap.kakaocdn.net/dn/c2LLrV/dJMb85W1Wrn/M3rg7tvW0rzZoEtN14j0kK/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=554_130_714_304,https://scrap.kakaocdn.net/dn/DcL8H/dJMb8T98hk3/xpKoNNeukDAiL46Hka7hWK/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=554_130_714_304&quot; data-video-width=&quot;860&quot; data-video-height=&quot;484&quot; data-video-origin-width=&quot;860&quot; data-video-origin-height=&quot;484&quot; data-ke-mobilestyle=&quot;widthContent&quot; data-video-title=&quot;주일예배2026 06 14&quot; data-original-url=&quot;&quot;&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/5IKoRqCooxk&quot; width=&quot;860&quot; height=&quot;484&quot; frameborder=&quot;&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;figcaption style=&quot;display: none;&quot;&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>성경과 QT/주일예배(온누리교회)</category>
      <category>CGNTV</category>
      <category>나를 따를라</category>
      <category>마르지 않는 시냇가</category>
      <category>소니스토리</category>
      <category>시편</category>
      <category>영상예배</category>
      <category>온누리교회</category>
      <category>우리말성경</category>
      <category>이재훈목사</category>
      <category>주일예배</category>
      <author>isony</author>
      <guid isPermaLink="true">https://isony.tistory.com/333</guid>
      <comments>https://isony.tistory.com/entry/2026%EB%85%8406%EC%9B%9414%EC%9D%BC-%EC%A3%BC%EC%9D%BC%EC%98%88%EB%B0%B0-%EC%9D%B4%EC%9E%AC%ED%9B%88%EB%AA%A9%EC%82%AC%EB%8B%98-1%EB%B6%80#entry333comment</comments>
      <pubDate>Sun, 14 Jun 2026 08:12:29 +0900</pubDate>
    </item>
    <item>
      <title>[오라클 운영] 시노님(SYNONYM) 완전 정리 - PUBLIC vs PRIVATE, 이름 해석 우선순위, 실무 가이드</title>
      <link>https://isony.tistory.com/entry/%EC%98%A4%EB%9D%BC%ED%81%B4-%EC%9A%B4%EC%98%81-%EC%8B%9C%EB%85%B8%EB%8B%98SYNONYM-%EC%99%84%EC%A0%84-%EC%A0%95%EB%A6%AC-PUBLIC-vs-PRIVATE-%EC%9D%B4%EB%A6%84-%ED%95%B4%EC%84%9D-%EC%9A%B0%EC%84%A0%EC%88%9C%EC%9C%84-%EC%8B%A4%EB%AC%B4-%EA%B0%80%EC%9D%B4%EB%93%9C</link>
      <description>&lt;h1&gt;[오라클 운영] 시노님(SYNONYM) 완전 정리 - PUBLIC vs PRIVATE, 이름 해석 우선순위, 실무 가이드&lt;/h1&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;테스트 환경&lt;/b&gt;: Oracle 11g / 12c / 19c / 21c / 23ai&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오라클을 1~2년 다루면 시노님은 누구나 한 번쯤 만듭니다. 그런데 시노님을 단순히 &lt;b&gt;&quot;별칭&quot;&lt;/b&gt; 정도로만 이해하고 있으면 운영 환경에서 다음과 같은 황당한 상황을 만나게 됩니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;분명히 같은 시노님인데 사용자마다 다른 테이블을 가리킴&lt;/li&gt;
&lt;li&gt;PUBLIC 시노님을 만들었는데 어떤 사용자에게는 안 보임&lt;/li&gt;
&lt;li&gt;시노님은 살아있는데 사용하면 &lt;a href=&quot;https://www.whodo.net/entry/%EC%98%A4%EB%9D%BC%ED%81%B4-%EC%97%90%EB%9F%AC-ORA-00942-table-or-view-does-not-exist-6%EA%B0%80%EC%A7%80-%EC%9B%90%EC%9D%B8%EA%B3%BC-%ED%95%B4%EA%B2%B0%EB%B0%A9%EB%B2%95-%EA%B6%8C%ED%95%9C%EA%B3%BC-PLSQL-%EC%BC%80%EC%9D%B4%EC%8A%A4%EA%B9%8C%EC%A7%80&quot;&gt;ORA-00942&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;DROP 후 재생성했는데 권한이 사라짐&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 글에서는 시노님의 &lt;b&gt;PUBLIC vs PRIVATE 핵심 차이&lt;/b&gt;, &lt;b&gt;이름 해석 우선순위&lt;/b&gt;, &lt;b&gt;권한과의 관계&lt;/b&gt;, 그리고 운영 환경에서 자주 발생하는 문제와 해결법까지 정리했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히 &lt;a href=&quot;https://www.whodo.net/entry/%EC%98%A4%EB%9D%BC%ED%81%B4-%EC%97%90%EB%9F%AC-ORA-00942-table-or-view-does-not-exist-6%EA%B0%80%EC%A7%80-%EC%9B%90%EC%9D%B8%EA%B3%BC-%ED%95%B4%EA%B2%B0%EB%B0%A9%EB%B2%95-%EA%B6%8C%ED%95%9C%EA%B3%BC-PLSQL-%EC%BC%80%EC%9D%B4%EC%8A%A4%EA%B9%8C%EC%A7%80&quot;&gt;ORA-00942 글&lt;/a&gt;의 &quot;원인 5 - 시노님 깨짐&quot;의 후속편 성격으로, 시노님을 깊이 이해하면 ORA-00942의 상당 부분이 자연스럽게 해결됩니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;시노님이란 무엇인가&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시노님은 &lt;b&gt;다른 데이터베이스 객체에 대한 별칭(alias)&lt;/b&gt; 입니다. 테이블, 뷰, 시퀀스, 프로시저, 패키지 등 거의 모든 객체에 대해 만들 수 있습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;왜 쓰는가 - 3가지 이유&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1) 스키마 prefix를 숨겨서 간결한 SQL&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- 시노님 없을 때
SELECT * FROM hr_schema.employees;
SELECT * FROM hr_schema.departments;

-- 시노님 있을 때
SELECT * FROM employees;
SELECT * FROM departments;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2) 위치 투명성 (Location Transparency)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체가 다른 스키마나 다른 DB로 이동해도 시노님만 수정하면 애플리케이션 코드는 그대로 둘 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- 처음: 같은 DB의 다른 스키마
CREATE SYNONYM employees FOR hr_schema.employees;

-- 나중: 원격 DB로 이전
CREATE OR REPLACE SYNONYM employees FOR hr_schema.employees@remote_db;
-- 애플리케이션은 그대로 SELECT * FROM employees;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3) 보안 추상화&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제 객체의 소유자와 이름을 숨겨서 보안 정보 노출을 줄입니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;PUBLIC vs PRIVATE - 핵심 비교&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 자주 헷갈리는 두 종류 시노님의 차이입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;항목 PRIVATE PUBLIC&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;소유자&lt;/td&gt;
&lt;td&gt;특정 사용자 (스키마)&lt;/td&gt;
&lt;td&gt;PUBLIC 그룹&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;접근 범위&lt;/td&gt;
&lt;td&gt;소유자만 (또는 명시적 prefix)&lt;/td&gt;
&lt;td&gt;모든 사용자&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;생성 권한&lt;/td&gt;
&lt;td&gt;CREATE SYNONYM&lt;/td&gt;
&lt;td&gt;CREATE PUBLIC SYNONYM&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;이름 충돌&lt;/td&gt;
&lt;td&gt;같은 스키마 내 객체와 충돌 가능&lt;/td&gt;
&lt;td&gt;모든 사용자 객체와 충돌 가능성&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;이름 우선순위&lt;/td&gt;
&lt;td&gt;Local 객체 다음&lt;/td&gt;
&lt;td&gt;Private 시노님 다음 (가장 마지막)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;운영 권장도&lt;/td&gt;
&lt;td&gt;⭐⭐⭐⭐ (권장)&lt;/td&gt;
&lt;td&gt;⭐⭐ (신중히)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;생성 문법 차이&lt;/h3&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- PRIVATE (자기 스키마에)
CREATE SYNONYM employees FOR hr_schema.employees;

-- PRIVATE (다른 스키마에) - CREATE ANY SYNONYM 권한 필요
CREATE SYNONYM batch_user.employees FOR hr_schema.employees;

-- PUBLIC - CREATE PUBLIC SYNONYM 권한 필요
CREATE PUBLIC SYNONYM employees FOR hr_schema.employees;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;★ 이름 해석 우선순위 (가장 중요)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오라클이 SELECT * FROM employees 같은 쿼리를 만났을 때 객체를 찾는 순서입니다. 이걸 모르면 시노님 동작이 예상과 다를 때 미궁에 빠집니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;해석 순서&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;현재 스키마의 객체&lt;/b&gt; (테이블/뷰/시퀀스 등 실제 객체)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;현재 스키마의 PRIVATE 시노님&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;PUBLIC 시노님&lt;/b&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;실전 시나리오로 이해하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 상황을 가정해 봅시다.&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- HR_SCHEMA에 employees 테이블 존재
-- BATCH_USER 스키마에 employees 테이블 또는 시노님 존재 가능

-- 시나리오 A: 공용 시노님만 있는 경우
-- PUBLIC SYNONYM employees &amp;rarr; HR_SCHEMA.employees

SELECT * FROM employees;
-- &amp;rarr; PUBLIC SYNONYM 사용 &amp;rarr; HR_SCHEMA.employees 조회
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- 시나리오 B: BATCH_USER가 같은 이름의 자기 테이블을 만든 경우
CREATE TABLE batch_user.employees (id NUMBER);

SELECT * FROM employees;
-- &amp;rarr; BATCH_USER.employees 조회 (PUBLIC 시노님 무시!)
-- &amp;rarr; 1순위가 Local 객체이기 때문
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- 시나리오 C: PRIVATE 시노님과 PUBLIC 시노님 충돌
CREATE SYNONYM employees FOR app_user.employees;  -- PRIVATE
CREATE PUBLIC SYNONYM employees FOR hr_schema.employees;  -- PUBLIC

SELECT * FROM employees;
-- &amp;rarr; app_user.employees 조회 (PRIVATE이 PUBLIC을 가림)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;실무에서 자주 발생하는 사고&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;운영 중인 PUBLIC 시노님이 어느 날부터 다른 데이터를 보여주는 경우, 십중팔구 &lt;b&gt;누군가 같은 이름의 PRIVATE 시노님 또는 테이블을 만든 것&lt;/b&gt;입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;진단 쿼리&lt;/h3&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;-- 같은 이름이 여러 곳에 있는지 확인
SELECT 'TABLE/VIEW' AS type, owner, object_name
FROM   dba_objects
WHERE  object_name = UPPER('찾는_이름')
UNION ALL
SELECT 'SYNONYM' AS type, owner, synonym_name
FROM   dba_synonyms
WHERE  synonym_name = UPPER('찾는_이름');
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여러 행이 나오면 이름 충돌 상황이고, 우선순위에 따라 어떤 게 실제로 사용되는지 결정됩니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;권한과 시노님 - 가장 큰 오해&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다른 블로그에서 자주 빠뜨리는 핵심입니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;시노님 자체는 보안 단위가 아닙니다. 시노님에 부여한 권한은 실제로 원본 객체에 부여된 것입니다.&lt;/b&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;무슨 뜻인가&lt;/h3&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- HR_SCHEMA로 접속
CREATE TABLE employees (id NUMBER, name VARCHAR2(100));

-- PUBLIC 시노님 생성
CREATE PUBLIC SYNONYM employees FOR hr_schema.employees;

-- BATCH_USER로 접속
SELECT * FROM employees;
-- &amp;rarr; ORA-00942 발생 (왜?)
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;시노님이 PUBLIC이라고 해도 데이터 접근 권한까지 자동으로 주어지지 않습니다.&lt;/b&gt; 실제 테이블에 SELECT 권한이 필요합니다.&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- HR_SCHEMA에서 권한 부여
GRANT SELECT ON employees TO batch_user;
-- 또는 모두에게
GRANT SELECT ON employees TO PUBLIC;

-- 이제 BATCH_USER에서 SELECT 가능
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;권장 패턴&lt;/h3&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- 1) 원본 객체 권한 부여
GRANT SELECT, INSERT, UPDATE, DELETE ON hr_schema.employees TO batch_user;

-- 2) 시노님 생성
CREATE SYNONYM batch_user.employees FOR hr_schema.employees;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;권한과 시노님은 &lt;b&gt;별개로 관리&lt;/b&gt;하세요.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;DROP / ALTER / 재생성 시 주의사항&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;OR REPLACE 활용 (권장)&lt;/h3&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- 안전한 재정의
CREATE OR REPLACE PUBLIC SYNONYM employees FOR hr_schema.employees;

-- 23ai 이상에서는 IF NOT EXISTS도 가능
CREATE PUBLIC SYNONYM IF NOT EXISTS employees FOR hr_schema.employees;
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;23ai 주의&lt;/b&gt;: OR REPLACE와 IF NOT EXISTS를 동시에 쓰면 ORA-11541: REPLACE and IF NOT EXISTS cannot coexist 에러가 발생합니다. 둘 중 하나만 선택하세요.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;DROP 시 권한 영향&lt;/h3&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- 시노님을 DROP해도 원본 테이블의 권한은 영향 없음
DROP PUBLIC SYNONYM employees;

-- 시노님 다시 만들면 원본 권한이 그대로 적용됨
CREATE PUBLIC SYNONYM employees FOR hr_schema.employees;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시노님은 별칭일 뿐이므로 DROP/재생성이 원본의 데이터나 권한에 영향을 주지 않습니다. 다만 시노님을 참조하는 다른 객체(예: 뷰)는 INVALID 상태가 됩니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;INVALID 시노님 일괄 재컴파일&lt;/h3&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- 무효 상태 객체 확인
SELECT owner, object_name, object_type, status
FROM   dba_objects
WHERE  status = 'INVALID'
  AND  object_type IN ('SYNONYM', 'VIEW', 'PROCEDURE', 'PACKAGE');

-- 일괄 재컴파일
EXEC DBMS_UTILITY.COMPILE_SCHEMA('BATCH_USER');
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;시노님 조회 - 데이터 딕셔너리 뷰 3종&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;뷰 보이는 범위 권한&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;USER_SYNONYMS&lt;/td&gt;
&lt;td&gt;자기가 소유한 시노님&lt;/td&gt;
&lt;td&gt;모든 사용자&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ALL_SYNONYMS&lt;/td&gt;
&lt;td&gt;접근 가능한 모든 시노님 (PUBLIC 포함)&lt;/td&gt;
&lt;td&gt;모든 사용자&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DBA_SYNONYMS&lt;/td&gt;
&lt;td&gt;DB의 모든 시노님&lt;/td&gt;
&lt;td&gt;DBA 권한&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;자주 쓰는 쿼리 모음&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1) 자기 스키마의 시노님 모두 보기&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;n1ql&quot;&gt;&lt;code&gt;SELECT synonym_name, table_owner, table_name, db_link
FROM   user_synonyms;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2) PUBLIC 시노님 중 특정 객체를 가리키는 것 찾기&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;SELECT synonym_name, table_owner, table_name
FROM   dba_synonyms
WHERE  owner = 'PUBLIC'
  AND  table_name = UPPER('찾는_객체명');
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3) 시노님이 가리키는 객체가 실제로 존재하는지 확인 (★ 깨진 시노님 진단)&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;SELECT s.owner, s.synonym_name, s.table_owner, s.table_name,
       CASE WHEN o.object_name IS NULL THEN '깨짐 (대상 없음)' 
            ELSE 'OK' 
       END AS status
FROM   dba_synonyms s
LEFT   JOIN dba_objects o
       ON s.table_owner = o.owner
      AND s.table_name = o.object_name
WHERE  s.synonym_name = UPPER('찾는_시노님');
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;깨진 시노님을 발견하면 &lt;a href=&quot;https://www.whodo.net/entry/%EC%98%A4%EB%9D%BC%ED%81%B4-%EC%97%90%EB%9F%AC-ORA-00942-table-or-view-does-not-exist-6%EA%B0%80%EC%A7%80-%EC%9B%90%EC%9D%B8%EA%B3%BC-%ED%95%B4%EA%B2%B0%EB%B0%A9%EB%B2%95-%EA%B6%8C%ED%95%9C%EA%B3%BC-PLSQL-%EC%BC%80%EC%9D%B4%EC%8A%A4%EA%B9%8C%EC%A7%80&quot;&gt;ORA-00942 글&lt;/a&gt;의 &quot;원인 5&quot;를 참고해서 처리하세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;4) 시노님 체인 추적 (시노님이 시노님을 가리키는 경우)&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;WITH syn_chain (level_no, owner, synonym_name, table_owner, table_name) AS (
    SELECT 1, owner, synonym_name, table_owner, table_name
    FROM   dba_synonyms
    WHERE  synonym_name = UPPER('시작_시노님')
    UNION ALL
    SELECT sc.level_no + 1, s.owner, s.synonym_name, s.table_owner, s.table_name
    FROM   dba_synonyms s, syn_chain sc
    WHERE  s.synonym_name = sc.table_name
      AND  s.owner = sc.table_owner
)
SELECT * FROM syn_chain;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시노님이 또 다른 시노님을 가리키는 체인은 디버깅이 어려우므로 가능한 한 피하세요.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;PUBLIC vs PRIVATE 실무 가이드 - 어떤 걸 쓸 것인가&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;운영 환경에서 어떤 시노님을 쓸지 결정할 때의 기준입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;PUBLIC 시노님을 써야 할 때&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;데이터 딕셔너리 뷰&lt;/b&gt; (예: ALL_TABLES, DBA_USERS)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;모든 사용자가 공통으로 접근해야 하는 공유 객체&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;표준 라이브러리 / 공통 함수 패키지&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;PRIVATE 시노님을 써야 할 때 (대부분의 경우)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;특정 애플리케이션 사용자만 접근하는 객체&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;운영 환경의 비즈니스 테이블&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;권한 관리를 사용자별로 다르게 해야 하는 경우&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;PUBLIC 시노님 남용의 위험&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PUBLIC 시노님은 편리해 보이지만 &lt;b&gt;운영 환경에서는 가능한 줄이는 것&lt;/b&gt;이 좋습니다. 이유는:&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;이름 공간 충돌&lt;/b&gt;: 모든 사용자의 객체 이름 공간을 침범&lt;/li&gt;
&lt;li&gt;&lt;b&gt;보안 위험&lt;/b&gt;: 객체 존재가 모든 사용자에게 노출됨&lt;/li&gt;
&lt;li&gt;&lt;b&gt;이관/마이그레이션 어려움&lt;/b&gt;: 다른 환경으로 옮길 때 PUBLIC 시노님 모두를 추적해야 함&lt;/li&gt;
&lt;li&gt;&lt;b&gt;삭제 영향 범위&lt;/b&gt;: DROP 시 모든 사용자에게 영향&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;권장 운영 표준&lt;/h3&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- ❌ PUBLIC 남용 (운영 환경에서 권장하지 않음)
CREATE PUBLIC SYNONYM employees FOR hr_schema.employees;
CREATE PUBLIC SYNONYM departments FOR hr_schema.departments;
CREATE PUBLIC SYNONYM jobs FOR hr_schema.jobs;
-- ... 수십 개

-- ✅ 권한 + PRIVATE 시노님 조합 (권장)
GRANT SELECT ON hr_schema.employees TO batch_user;
GRANT SELECT ON hr_schema.departments TO batch_user;

-- BATCH_USER로 접속해서
CREATE SYNONYM employees FOR hr_schema.employees;
CREATE SYNONYM departments FOR hr_schema.departments;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 하면 사용자별 격리가 명확해지고, 권한 추적이 쉬워집니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;자주 발생하는 문제 5가지&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;문제 1: 시노님은 있는데 ORA-00942&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원본 객체에 대한 SELECT 권한 누락. &lt;a href=&quot;https://www.whodo.net/entry/%EC%98%A4%EB%9D%BC%ED%81%B4-%EC%97%90%EB%9F%AC-ORA-00942-table-or-view-does-not-exist-6%EA%B0%80%EC%A7%80-%EC%9B%90%EC%9D%B8%EA%B3%BC-%ED%95%B4%EA%B2%B0%EB%B0%A9%EB%B2%95-%EA%B6%8C%ED%95%9C%EA%B3%BC-PLSQL-%EC%BC%80%EC%9D%B4%EC%8A%A4%EA%B9%8C%EC%A7%80&quot;&gt;ORA-00942 글&lt;/a&gt; 참고.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;문제 2: 갑자기 다른 데이터가 보임&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;같은 이름의 PRIVATE 시노님이나 Local 객체가 생긴 것. 이름 해석 우선순위 확인.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;문제 3: 편집기에서 보이는 것과 SELECT 결과가 다름&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;편집기(SQL Developer, Toad)는 현재 사용자의 컨텍스트로 객체를 표시합니다. 다른 사용자로 접속하면 시노님이 다른 객체를 가리킬 수 있습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;문제 4: PL/SQL에서만 시노님 인식 안 됨&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.whodo.net/entry/%EC%98%A4%EB%9D%BC%ED%81%B4-%EC%97%90%EB%9F%AC-ORA-00942-table-or-view-does-not-exist-6%EA%B0%80%EC%A7%80-%EC%9B%90%EC%9D%B8%EA%B3%BC-%ED%95%B4%EA%B2%B0%EB%B0%A9%EB%B2%95-%EA%B6%8C%ED%95%9C%EA%B3%BC-PLSQL-%EC%BC%80%EC%9D%B4%EC%8A%A4%EA%B9%8C%EC%A7%80&quot;&gt;ORA-00942 글&lt;/a&gt;의 &quot;원인 4 - DEFINER rights + ROLE 무효화&quot;와 같은 케이스. 시노님 자체가 아니라 권한 문제일 가능성이 높습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;문제 5: DB Link 시노님이 작동 안 함&lt;/h3&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;CREATE SYNONYM remote_emp FOR employees@remote_db;
SELECT * FROM remote_emp;
-- ORA-02019: connection description for remote database not found
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DB Link가 끊어졌거나 사용자에게 해당 DB Link 권한이 없는 경우. user_db_links 확인.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;마무리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시노님은 단순한 별칭이지만, &lt;b&gt;이름 해석 우선순위&lt;/b&gt;와 &lt;b&gt;권한과의 관계&lt;/b&gt;를 정확히 이해하지 못하면 운영 환경에서 미궁에 빠지기 쉽습니다. 핵심을 다시 한 번 요약하면:&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;객체 해석은 &lt;b&gt;Local &amp;rarr; PRIVATE &amp;rarr; PUBLIC&lt;/b&gt; 순서&lt;/li&gt;
&lt;li&gt;&lt;b&gt;시노님은 권한과 별개&lt;/b&gt; &amp;mdash; GRANT는 원본 객체에 부여해야 함&lt;/li&gt;
&lt;li&gt;&lt;b&gt;PUBLIC은 신중히&lt;/b&gt; &amp;mdash; 운영 환경에서는 PRIVATE + GRANT 조합 권장&lt;/li&gt;
&lt;li&gt;&lt;b&gt;시노님 체인은 가능한 피할 것&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;데이터 딕셔너리 뷰&lt;/b&gt;(USER/ALL/DBA_SYNONYMS)로 진단&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;신규 시스템을 설계할 때 시노님 사용 표준을 미리 정해 두면 운영 사고를 크게 줄일 수 있습니다. PUBLIC 시노님을 만들기 전에 한 번 더 생각해 보세요. &quot;정말 모든 사용자가 접근해야 하는가? PRIVATE으로 대체할 수 없는가?&quot;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비슷한 시노님 관련 이슈를 겪으셨거나, 더 좋은 운영 패턴이 있다면 댓글로 공유해 주세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>CREATE SYNONYM 사용법</category>
      <category>GRANT SYNONYM</category>
      <category>Private Synonym</category>
      <category>Public Synonym</category>
      <category>소니스토리</category>
      <category>시노님 ORA-00942</category>
      <category>시노님 우선순위</category>
      <category>오라클 시노님</category>
      <category>오라클 시노님 권한</category>
      <category>오라클 시노님 차이</category>
      <author>isony</author>
      <guid isPermaLink="true">https://isony.tistory.com/332</guid>
      <comments>https://isony.tistory.com/entry/%EC%98%A4%EB%9D%BC%ED%81%B4-%EC%9A%B4%EC%98%81-%EC%8B%9C%EB%85%B8%EB%8B%98SYNONYM-%EC%99%84%EC%A0%84-%EC%A0%95%EB%A6%AC-PUBLIC-vs-PRIVATE-%EC%9D%B4%EB%A6%84-%ED%95%B4%EC%84%9D-%EC%9A%B0%EC%84%A0%EC%88%9C%EC%9C%84-%EC%8B%A4%EB%AC%B4-%EA%B0%80%EC%9D%B4%EB%93%9C#entry332comment</comments>
      <pubDate>Fri, 12 Jun 2026 08:05:22 +0900</pubDate>
    </item>
    <item>
      <title>[오라클 에러] ORA-04031 unable to allocate shared memory - 5가지 원인과 해결방법 (단편화 진단 포함)</title>
      <link>https://isony.tistory.com/entry/%EC%98%A4%EB%9D%BC%ED%81%B4-%EC%97%90%EB%9F%AC-ORA-04031-unable-to-allocate-shared-memory-5%EA%B0%80%EC%A7%80-%EC%9B%90%EC%9D%B8%EA%B3%BC-%ED%95%B4%EA%B2%B0%EB%B0%A9%EB%B2%95-%EB%8B%A8%ED%8E%B8%ED%99%94-%EC%A7%84%EB%8B%A8-%ED%8F%AC%ED%95%A8</link>
      <description>&lt;h1&gt;[오라클 에러] ORA-04031 unable to allocate shared memory - 5가지 원인과 해결방법 (단편화 진단 포함)&lt;/h1&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;테스트 환경&lt;/b&gt;: Oracle 11g / 12c / 19c / 21c&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;새벽 3시. 운영 DB 모니터링 알람이 울립니다. 알람 내용은 &lt;b&gt;&quot;ORA-04031: unable to allocate XXXX bytes of shared memory&quot;&lt;/b&gt;. 애플리케이션이 멈췄고, 신규 접속도 안 됩니다. DB가 사실상 frozen 상태입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ORA-04031은 DBA가 운영 환경에서 가장 두려워하는 에러 중 하나입니다. &lt;b&gt;단순히 &quot;메모리 부족&quot;이라고 생각하면 절대 풀리지 않습니다.&lt;/b&gt; SGA를 64GB로 늘렸는데도 며칠 후 재발하는 경우가 흔합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 글에서는 ORA-04031의 진짜 정체를 짚고, &lt;b&gt;단편화와 단순 부족을 구분&lt;/b&gt;해서 진단하는 방법, &lt;b&gt;임시 처치와 근본 해결&lt;/b&gt;까지 정리했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;급하게 운영 DB를 살려야 한다면 &lt;u&gt;긴급 응급 처치&lt;/u&gt;부터 보세요.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;에러 메시지 전문과 해석&lt;/h2&gt;
&lt;pre class=&quot;mipsasm&quot;&gt;&lt;code&gt;ORA-04031: unable to allocate 4096 bytes of shared memory 
(&quot;shared pool&quot;,&quot;SELECT * FROM orders WHERE...&quot;,&quot;sql area&quot;,&quot;KGL heap&quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 메시지는 진단의 시작점입니다. 4가지 정보가 들어있어요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;항목 위치 의미&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;요청 크기&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;4096 bytes&lt;/td&gt;
&lt;td&gt;오라클이 할당하려던 메모리 크기&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;메모리 풀&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&quot;shared pool&quot;&lt;/td&gt;
&lt;td&gt;어느 메모리 영역에서 실패했는지&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;객체 타입&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&quot;SELECT * FROM...&quot;&lt;/td&gt;
&lt;td&gt;무엇을 위한 할당이었는지 (SQL 텍스트 일부)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;힙 타입&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&quot;sql area&quot;,&quot;KGL heap&quot;&lt;/td&gt;
&lt;td&gt;내부 메모리 구조 (KGL = Kernel Generic Library)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;메모리 풀이 어디인지가 가장 중요합니다.&lt;/b&gt; 풀별로 원인과 해결법이 완전히 다릅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;풀 용도 흔한 발생 시점&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;shared pool&lt;/td&gt;
&lt;td&gt;SQL/PLSQL 파싱, 라이브러리 캐시&lt;/td&gt;
&lt;td&gt;OLTP 운영 중 (가장 흔함)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;large pool&lt;/td&gt;
&lt;td&gt;RMAN 백업, 병렬 쿼리&lt;/td&gt;
&lt;td&gt;백업 작업 중&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;java pool&lt;/td&gt;
&lt;td&gt;Java 저장 프로시저&lt;/td&gt;
&lt;td&gt;Java 기반 작업&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;streams pool&lt;/td&gt;
&lt;td&gt;GoldenGate, Streams 복제&lt;/td&gt;
&lt;td&gt;복제 환경&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;ORA-04031의 진짜 본질 - 단편화 vs 단순 부족 ★&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다른 블로그가 잘 다루지 않는 부분이지만, 이게 ORA-04031 진단의 핵심입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;흔한 오해&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;메모리 부족이니까 SGA를 늘리면 된다&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이건 절반만 맞습니다. &lt;b&gt;실제로는 메모리에 여유 공간이 있는데도 ORA-04031이 발생하는 경우가 매우 많습니다.&lt;/b&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;단편화의 비유&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;shared pool을 책장이라고 생각해 보세요.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;책장에 빈 공간이 총 1GB &lt;b&gt;남아있지만&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;그 1GB가 1MB 단위 1024개로 쪼개져 있고&lt;/li&gt;
&lt;li&gt;새로 들어와야 할 책이 500MB짜리라면?&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;빈 공간 총량은 충분하지만 &lt;b&gt;연속된 큰 공간이 없어서 책을 못 꽂습니다&lt;/b&gt;. 이게 단편화입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ORA-04031의 70% 이상이 이 패턴입니다. SGA를 늘려도 일정 시간 후 다시 단편화가 진행되어 재발합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;단편화의 진짜 원인&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대부분은 &lt;b&gt;하드 파싱(Hard Parse) 폭증&lt;/b&gt;입니다.&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- 리터럴 SQL (매번 새로운 SQL로 인식됨 - 단편화 주범)
SELECT * FROM orders WHERE customer_id = 1001;
SELECT * FROM orders WHERE customer_id = 1002;
SELECT * FROM orders WHERE customer_id = 1003;
-- ... 매 customer_id마다 별도 SQL로 저장됨

-- 바인드 변수 SQL (한 번만 파싱됨 - 단편화 방지)
SELECT * FROM orders WHERE customer_id = :cust_id;
-- 모든 customer_id가 이 한 SQL로 처리됨
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리터럴 SQL이 초당 수백~수천 개씩 발생하면 shared pool에 매번 새로운 chunk가 할당되고, 오래된 것은 제거되면서 메모리 공간이 잘게 쪼개집니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;긴급 응급 처치 (1분 안에)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;운영 DB가 멈춰서 당장 살려야 한다면 다음을 먼저 시도하세요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Step 1: shared pool 플러시 (가장 빠른 임시 해결)&lt;/h3&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;ALTER SYSTEM FLUSH SHARED_POOL;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 명령으로 shared pool의 SQL 캐시가 비워지면서 단편화가 해소됩니다. &lt;b&gt;대부분의 ORA-04031이 즉시 풀립니다.&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;주의&lt;/b&gt;: 이건 응급 처치일 뿐 근본 해결이 아닙니다. 같은 원인이 남아있으면 몇 시간~며칠 안에 재발합니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Step 2: 접속도 안 되면 인스턴스 재기동&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;플러시 명령조차 실행이 안 될 정도로 심한 상태라면 DB 재기동이 필요합니다.&lt;/p&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;# SQL*Plus로 sysdba 접속
sqlplus / as sysdba

SQL&amp;gt; SHUTDOWN IMMEDIATE;
SQL&amp;gt; STARTUP;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;재기동은 마지막 수단입니다. 가능하면 플러시로 해결하세요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Step 3: 근본 원인 진단 시작&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;응급 조치 후 반드시 다음 진단을 진행해야 합니다. 그렇지 않으면 무조건 재발합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;원인 1: 하드 파싱 폭증 (가장 흔함, 60~70%)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리터럴 SQL이 너무 많아서 shared pool이 폭증하는 케이스입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;진단 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1) 라이브러리 캐시 적중률 확인&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;n1ql&quot;&gt;&lt;code&gt;SELECT namespace,
       gethitratio AS hit_ratio,
       pinhitratio AS pin_hit_ratio,
       reloads,
       invalidations
FROM   v$librarycache
WHERE  namespace IN ('SQL AREA', 'TABLE/PROCEDURE');
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;hit_ratio가 0.95(95%) 이하면 하드 파싱이 많은 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2) 하드 파싱 발생 횟수 확인&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;SELECT name, value
FROM   v$sysstat
WHERE  name IN ('parse count (hard)', 'parse count (total)', 'execute count');
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(parse count (hard) / parse count (total)) &amp;times; 100이 5%를 넘으면 하드 파싱 비율이 너무 높습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3) 단편화된 SQL TOP 발견&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;SELECT sql_text, executions, parse_calls,
       sharable_mem, persistent_mem
FROM   v$sqlarea
WHERE  parse_calls &amp;gt; 100
  AND  executions &amp;lt; 10
ORDER  BY sharable_mem DESC
FETCH  FIRST 20 ROWS ONLY;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;executions가 적은데 parse_calls가 많은 SQL은 매번 다른 SQL로 인식되는 것입니다. 단편화의 주범입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;해결 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;방법 1: 바인드 변수 사용 (근본 해결, 권장)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;애플리케이션 코드에서 리터럴을 바인드 변수로 변경합니다.&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;// ❌ 리터럴
String sql = &quot;SELECT * FROM orders WHERE customer_id = &quot; + customerId;

// ✅ 바인드 변수
String sql = &quot;SELECT * FROM orders WHERE customer_id = ?&quot;;
ps.setInt(1, customerId);
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;방법 2: CURSOR_SHARING 파라미터 (임시 해결)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드 수정이 불가능한 경우 오라클이 자동으로 리터럴을 바인드 변수로 변환하도록 설정합니다.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;ALTER SYSTEM SET CURSOR_SHARING = 'FORCE' SCOPE=BOTH;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;값 의미&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;EXACT&lt;/td&gt;
&lt;td&gt;기본값. SQL 텍스트가 완전히 같아야 재사용&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;FORCE&lt;/td&gt;
&lt;td&gt;모든 리터럴을 바인드 변수로 자동 변환&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SIMILAR&lt;/td&gt;
&lt;td&gt;11g 이후 deprecated. 사용 금지&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;주의&lt;/b&gt;: FORCE 설정은 실행 계획에 영향을 줄 수 있습니다. 운영 환경에 적용 전 충분한 테스트 필수입니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;원인 2: SGA 크기 자체가 부족&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터베이스 워크로드 대비 SGA 크기가 실제로 부족한 경우입니다. ORA-04031의 20~30%에 해당합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;진단 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1) 현재 SGA 사용 상황&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;n1ql&quot;&gt;&lt;code&gt;SELECT pool, name, ROUND(bytes/1024/1024, 2) AS mb
FROM   v$sgastat
WHERE  pool IS NOT NULL
ORDER  BY pool, bytes DESC;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2) shared pool 자유 메모리 확인&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;SELECT name, ROUND(bytes/1024/1024, 2) AS free_mb
FROM   v$sgastat
WHERE  name = 'free memory';
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;총 shared pool의 10% 이상 자유 공간이 있어야 안정적입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3) 오라클 자동 조언 활용&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;n1ql&quot;&gt;&lt;code&gt;SELECT shared_pool_size_for_estimate AS pool_mb,
       estd_lc_size AS estd_lib_cache_mb,
       estd_lc_time_saved_factor,
       estd_lc_load_time_factor
FROM   v$shared_pool_advice
ORDER  BY shared_pool_size_for_estimate;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;estd_lc_time_saved_factor가 1에 가까운 첫 크기가 권장값입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;해결 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;ASMM 환경 (자동 메모리 관리)&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;-- sga_target 증가
ALTER SYSTEM SET sga_target = 8G SCOPE=BOTH;

-- 또는 메모리 자동 관리 (11g+)
ALTER SYSTEM SET memory_target = 12G SCOPE=BOTH;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;수동 메모리 관리 환경&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;ALTER SYSTEM SET shared_pool_size = 2G SCOPE=BOTH;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SGA 변경은 SPFILE 사용 시 즉시 반영됩니다. PFILE 사용 시 재기동 필요.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;원인 3: large pool / java pool / streams pool 부족&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;shared pool이 아닌 다른 풀에서 에러가 발생한 경우입니다. 에러 메시지를 다시 확인하세요.&lt;/p&gt;
&lt;pre class=&quot;lasso&quot;&gt;&lt;code&gt;ORA-04031: unable to allocate XX bytes of shared memory (&quot;large pool&quot;,...)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;자주 발생하는 시나리오&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;large pool&lt;/b&gt;: RMAN 백업 중, 병렬 쿼리(PARALLEL 힌트) 사용 중&lt;/li&gt;
&lt;li&gt;&lt;b&gt;java pool&lt;/b&gt;: Java 저장 프로시저 호출 시&lt;/li&gt;
&lt;li&gt;&lt;b&gt;streams pool&lt;/b&gt;: GoldenGate, Oracle Streams 복제 환경&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;진단 방법&lt;/h3&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;-- 풀별 사용량 확인
SELECT pool, ROUND(SUM(bytes)/1024/1024, 2) AS total_mb
FROM   v$sgastat
WHERE  pool IS NOT NULL
GROUP  BY pool;

-- 풀별 자유 메모리
SELECT pool, name, ROUND(bytes/1024/1024, 2) AS mb
FROM   v$sgastat
WHERE  name = 'free memory';
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;해결 방법&lt;/h3&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;-- large pool 증가 (RMAN/병렬 쿼리)
ALTER SYSTEM SET large_pool_size = 512M SCOPE=BOTH;

-- java pool 증가
ALTER SYSTEM SET java_pool_size = 256M SCOPE=BOTH;

-- streams pool 증가 (복제 환경)
ALTER SYSTEM SET streams_pool_size = 512M SCOPE=BOTH;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ASMM 환경(sga_target 설정됨)에서는 오라클이 풀 간 메모리를 자동 조정하지만, &lt;b&gt;명시적 최소값을 지정&lt;/b&gt;하면 보호됩니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;원인 4: 메모리 누수 (오라클 버그 또는 특정 패키지)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;흔하지는 않지만 특정 버전&amp;middot;패치에서 메모리 누수 버그가 알려진 경우가 있습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;증상&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;운영 시작 직후엔 안정적&lt;/li&gt;
&lt;li&gt;시간이 지날수록 free memory가 점진적으로 감소&lt;/li&gt;
&lt;li&gt;특정 작업 또는 패키지 호출 후 메모리 회수 안 됨&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;진단 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1) 시간대별 자유 메모리 추이 모니터링&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- AWR 스냅샷 기반 추이 (Diagnostics Pack 필요)
SELECT snap_id, 
       TO_CHAR(begin_interval_time, 'YYYY-MM-DD HH24:MI') AS snap_time,
       ROUND(bytes/1024/1024, 2) AS free_mb
FROM   dba_hist_sgastat sg, dba_hist_snapshot s
WHERE  sg.snap_id = s.snap_id
  AND  sg.name = 'free memory'
  AND  sg.pool = 'shared pool'
ORDER  BY snap_id DESC
FETCH  FIRST 48 ROWS ONLY;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자유 메모리가 시간에 따라 단조 감소하면 메모리 누수 의심.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2) 특정 객체 메모리 점유 확인&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;SELECT name, type, sharable_mem
FROM   v$db_object_cache
WHERE  sharable_mem &amp;gt; 1048576  -- 1MB 이상
ORDER  BY sharable_mem DESC
FETCH  FIRST 20 ROWS ONLY;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;해결 방법&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;현재 PSU/RU 패치 적용&lt;/b&gt; 상태 확인 (Oracle Support Doc ID 146599.1)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;특정 패키지가 의심된다면 DBMS_SHARED_POOL.KEEP으로 PIN&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;aspectj&quot;&gt;&lt;code&gt;EXEC DBMS_SHARED_POOL.KEEP('SCHEMA.PACKAGE_NAME', 'P');
&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;My Oracle Support의 자동 진단 도구(AHF)&lt;/b&gt; 활용&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;19c 이상에서는 AHF(Autonomous Health Framework)가 ORA-04031 자동 진단을 지원합니다.&lt;/p&gt;
&lt;pre class=&quot;mipsasm&quot;&gt;&lt;code&gt;tfactl diagcollect -ora-04031
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;원인 5: session_cached_cursors 설정 과다 (드물지만 강력함)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 케이스는 다른 한국어 블로그에서 거의 다루지 않는 영역입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;무엇이 문제인가&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;session_cached_cursors가 너무 높게 설정되면, 각 세션이 캐시하는 커서가 누적되어 shared pool 내 KGLH0 영역이 폭증합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본값은 50인데, 일부 환경에서 500~1000으로 설정한 경우 ORA-04031의 원인이 됩니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;진단 방법&lt;/h3&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;SHOW PARAMETER session_cached_cursors

-- KGLH0 영역 사용량 확인
SELECT name, ROUND(bytes/1024/1024, 2) AS mb
FROM   v$sgastat
WHERE  name = 'KGLH0'
  AND  pool = 'shared pool';
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;KGLH0가 SGA stat에서 TOP 5 안에 들어가면 의심하세요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;해결 방법&lt;/h3&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;-- 적정 수준으로 조정 (보통 50~200)
ALTER SYSTEM SET session_cached_cursors = 100 SCOPE=SPFILE;
-- 재기동 필요
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;재발 방지 - 운영 환경 모니터링 (★ 실무 핵심)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ORA-04031은 한 번 발생하면 운영 사고로 직결되므로, &lt;b&gt;사전 모니터링이 필수&lt;/b&gt;입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;일일 점검 쿼리&lt;/h3&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;-- 1. 풀별 자유 메모리 비율
WITH pool_stats AS (
    SELECT pool,
           SUM(CASE WHEN name = 'free memory' THEN bytes ELSE 0 END) AS free_bytes,
           SUM(bytes) AS total_bytes
    FROM   v$sgastat
    WHERE  pool IS NOT NULL
    GROUP  BY pool
)
SELECT pool,
       ROUND(total_bytes/1024/1024, 2) AS total_mb,
       ROUND(free_bytes/1024/1024, 2)  AS free_mb,
       ROUND(free_bytes/total_bytes * 100, 2) AS free_pct
FROM   pool_stats
ORDER  BY pool;

-- 2. 하드 파싱 비율
SELECT ROUND(
         (SELECT value FROM v$sysstat WHERE name = 'parse count (hard)') / 
         (SELECT value FROM v$sysstat WHERE name = 'parse count (total)') * 100,
         2) AS hard_parse_pct
FROM   dual;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자유 메모리 비율이 10% 미만이거나 하드 파싱 비율이 5%를 넘으면 경고 알림을 발송하도록 자동화하세요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;권장 운영 표준&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;항목 권장값 이유&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;shared_pool 자유 메모리&lt;/td&gt;
&lt;td&gt;15% 이상 유지&lt;/td&gt;
&lt;td&gt;단편화 여유&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;하드 파싱 비율&lt;/td&gt;
&lt;td&gt;5% 미만&lt;/td&gt;
&lt;td&gt;단편화 방지&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;cursor_sharing&lt;/td&gt;
&lt;td&gt;EXACT (개발 정상), FORCE (레거시 임시)&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;session_cached_cursors&lt;/td&gt;
&lt;td&gt;50~200&lt;/td&gt;
&lt;td&gt;KGLH0 폭증 방지&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;주기적 shared pool flush&lt;/td&gt;
&lt;td&gt;❌ 권장하지 않음&lt;/td&gt;
&lt;td&gt;근본 해결 우선&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;그래도 안 풀린다면&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 5가지로도 해결되지 않는 드문 케이스:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;HugePages 설정 누락&lt;/b&gt;: Linux 환경에서 SGA가 크면 HugePages 설정이 거의 필수&lt;/li&gt;
&lt;li&gt;&lt;b&gt;NUMA 환경 최적화 미적용&lt;/b&gt;: 멀티 소켓 서버에서 메모리 액세스 비효율 발생&lt;/li&gt;
&lt;li&gt;&lt;b&gt;RAC 환경 특화 이슈&lt;/b&gt;: 노드 간 라이브러리 캐시 동기화 문제 (gc 대기 이벤트)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;AMM/ASMM 충돌&lt;/b&gt;: memory_target과 sga_target 동시 설정 시 예측 불가 동작&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 영역은 Oracle Support와 협업 또는 AHF 자동 진단이 가장 빠른 길입니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;마무리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ORA-04031은 &quot;메모리 부족&quot;이라는 표면적 메시지와 달리, &lt;b&gt;실제로는 단편화 문제인 경우가 70% 이상&lt;/b&gt;입니다. SGA를 늘리는 것은 임시 대응에 불과하고, &lt;b&gt;하드 파싱을 줄이는 것이 진짜 해결&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;운영 환경에서 ORA-04031이 발생했다면 즉시 ALTER SYSTEM FLUSH SHARED_POOL로 시스템을 복구한 후, &lt;b&gt;24시간 안에 반드시 근본 원인을 진단&lt;/b&gt;하세요. 그렇지 않으면 며칠 안에 더 큰 장애로 돌아옵니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 좋은 예방은 &lt;b&gt;개발 단계에서 바인드 변수를 표준화하는 것&lt;/b&gt;입니다. 운영에 들어간 후 리터럴 SQL을 잡는 건 매우 어렵습니다. 신규 시스템 구축 시 코드 리뷰 항목에 반드시 포함시키세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비슷한 케이스를 겪으셨거나, 위 방법으로도 해결되지 않은 상황이 있다면 댓글로 공유해 주세요. 함께 진단해 보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>DBA 실무/Oracle(오라클)</category>
      <category>DBA실무</category>
      <category>ORA-04031 large pool</category>
      <category>ORA-04031 단편화</category>
      <category>ORA-04031 원인</category>
      <category>ORA-04031 해결</category>
      <category>shared pool 단편화</category>
      <category>shared pool 부족</category>
      <category>unable to allocate shared memory</category>
      <category>소니스토리</category>
      <category>오라클 SGA 부족 긴급</category>
      <author>isony</author>
      <guid isPermaLink="true">https://isony.tistory.com/331</guid>
      <comments>https://isony.tistory.com/entry/%EC%98%A4%EB%9D%BC%ED%81%B4-%EC%97%90%EB%9F%AC-ORA-04031-unable-to-allocate-shared-memory-5%EA%B0%80%EC%A7%80-%EC%9B%90%EC%9D%B8%EA%B3%BC-%ED%95%B4%EA%B2%B0%EB%B0%A9%EB%B2%95-%EB%8B%A8%ED%8E%B8%ED%99%94-%EC%A7%84%EB%8B%A8-%ED%8F%AC%ED%95%A8#entry331comment</comments>
      <pubDate>Wed, 10 Jun 2026 09:34:56 +0900</pubDate>
    </item>
    <item>
      <title>[오라클 에러] ORA-00942 table or view does not exist - 6가지 원인과 해결방법 (권한과 PL/SQL 케이스까지)</title>
      <link>https://isony.tistory.com/entry/%EC%98%A4%EB%9D%BC%ED%81%B4-%EC%97%90%EB%9F%AC-ORA-00942-table-or-view-does-not-exist-6%EA%B0%80%EC%A7%80-%EC%9B%90%EC%9D%B8%EA%B3%BC-%ED%95%B4%EA%B2%B0%EB%B0%A9%EB%B2%95-%EA%B6%8C%ED%95%9C%EA%B3%BC-PLSQL-%EC%BC%80%EC%9D%B4%EC%8A%A4%EA%B9%8C%EC%A7%80</link>
      <description>&lt;h1&gt;[오라클 에러] ORA-00942 table or view does not exist - 6가지 원인과 해결방법 (권한과 PL/SQL 케이스까지)&lt;/h1&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;테스트 환경&lt;/b&gt;: Oracle 11g / 12c / 19c / 21c&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ORA-00942는 오라클에서 가장 자주 마주치는 에러 중 하나입니다. 메시지가 단순해서 &quot;그 객체가 없나 보다&quot; 하고 넘기기 쉽지만, &lt;b&gt;실제로는 객체가 존재하는데도 ORA-00942가 나는 케이스가 절반 이상&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히 다음 상황에서 자주 발생합니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;분명히 테이블이 있는데 SELECT가 안 됨&lt;/li&gt;
&lt;li&gt;다른 사용자는 되는데 내 계정만 안 됨&lt;/li&gt;
&lt;li&gt;어제까지 잘 되던 프로시저가 갑자기 ORA-00942&lt;/li&gt;
&lt;li&gt;쿼리는 잘 되는데 PL/SQL 안에서만 ORA-00942&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글에서는 ORA-00942의 6가지 원인을 분류하고, &lt;b&gt;권한 부족인데 왜 ORA-01031이 아니라 ORA-00942가 나는지&lt;/b&gt;, 그리고 &lt;b&gt;PL/SQL 내부에서의 특수한 케이스&lt;/b&gt;까지 정리했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;급하신 분은 &lt;u&gt;빠른 진단 체크리스트&lt;/u&gt;부터 보세요.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;에러 메시지 전문&lt;/h2&gt;
&lt;pre class=&quot;gams&quot;&gt;&lt;code&gt;ORA-00942: table or view does not exist
ORA-00942: 테이블 또는 뷰가 존재하지 않습니다
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SQL*Plus, SQL Developer, JDBC, 애플리케이션 로그 어디에서나 동일하게 발생합니다. 에러 메시지가 어떤 객체인지 알려주지 않는 게 진단을 어렵게 만드는 부분입니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;중요&lt;/b&gt;: 메시지가 &quot;존재하지 않는다&quot;고 말하지만, &lt;b&gt;오라클은 &quot;보이지 않는다&quot;와 &quot;존재하지 않는다&quot;를 같은 에러로 처리&lt;/b&gt;합니다. 이게 ORA-00942의 진짜 정체입니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;ORA-00942의 핵심 개념 - 권한과 가시성&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다른 블로그에서 잘 다루지 않는 부분이지만, 이걸 이해해야 ORA-00942를 진짜로 해결할 수 있습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;왜 권한 부족이 ORA-01031이 아니라 ORA-00942인가&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오라클의 보안 설계는 &lt;b&gt;&quot;권한 없는 사용자에게는 객체의 존재 자체를 알리지 않는다&quot;&lt;/b&gt; 는 원칙을 따릅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 권한 부족 시 ORA-01031(&quot;권한이 불충분합니다&quot;)이 발생한다면, 공격자는 다음을 알 수 있습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ORA-00942 응답 &amp;rarr; 그런 객체 없음&lt;/li&gt;
&lt;li&gt;ORA-01031 응답 &amp;rarr; 객체는 있는데 권한 없음 (= &lt;b&gt;객체가 존재한다는 정보 노출&lt;/b&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이건 데이터베이스 구조 정보를 노출하는 보안 취약점입니다. 그래서 오라클은 &lt;b&gt;권한이 없으면 &quot;존재하지 않음&quot;이라고 응답&lt;/b&gt;합니다. 즉:&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;ORA-00942는 &quot;객체가 없다&quot;가 아니라, &quot;당신에게는 보이지 않는다&quot;는 의미입니다.&lt;/b&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 차이를 알면 진단 방향이 완전히 달라집니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;빠른 진단 체크리스트&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ORA-00942를 30초 만에 원인을 좁히는 순서입니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;DBA 계정으로 객체 존재 여부 확인&lt;/b&gt; &amp;rarr; 정말 없는가, 아니면 보이지 않는가?&lt;/li&gt;
&lt;li&gt;&lt;b&gt;객체의 소유 스키마 확인&lt;/b&gt; &amp;rarr; 다른 스키마인가?&lt;/li&gt;
&lt;li&gt;&lt;b&gt;현재 사용자에게 SELECT 권한이 있는가&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;PL/SQL 안에서 발생했는가&lt;/b&gt; &amp;rarr; ROLE 권한 문제일 가능성&lt;/li&gt;
&lt;li&gt;&lt;b&gt;객체가 INVALID 상태인가&lt;/b&gt; &amp;rarr; 의존성 깨진 뷰/시노님&lt;/li&gt;
&lt;li&gt;&lt;b&gt;객체 이름에 대소문자/특수문자 포함?&lt;/b&gt; &amp;rarr; 따옴표 케이스&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;원인 1: 객체가 실제로 없거나 오타 (가장 흔함)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본적인 케이스지만 가장 많이 발생합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;진단 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;DBA 권한으로 객체가 실제로 존재하는지 확인:&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- 모든 스키마에서 해당 객체 검색
SELECT owner, object_name, object_type, status
FROM   dba_objects
WHERE  UPPER(object_name) = UPPER('찾는_객체명');
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;행이 0건이면 &lt;b&gt;객체가 정말 없는 것&lt;/b&gt;입니다. 행이 있다면 다음 원인으로 넘어가세요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;해결 방법&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;객체명 오타 수정&lt;/li&gt;
&lt;li&gt;객체 생성 (필요한 경우)&lt;/li&gt;
&lt;li&gt;다른 환경(개발/스테이징)에 있는지 확인&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;원인 2: 다른 스키마의 객체에 접근 (스키마 prefix 누락) ★ 가장 자주 헷갈림&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오라클에서 객체는 항상 &lt;b&gt;소유 스키마&lt;/b&gt;에 속합니다. 다른 스키마의 객체에 접근할 때는 스키마명을 명시해야 합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;시나리오&lt;/h3&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- APP_USER 스키마에 EMPLOYEES 테이블이 있고
-- 현재 접속한 사용자는 BATCH_USER일 때

SELECT * FROM employees;          -- ❌ ORA-00942
SELECT * FROM app_user.employees; -- ✅ 가능 (권한이 있다면)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;진단 방법&lt;/h3&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;-- 객체가 어느 스키마에 있는지 확인
SELECT owner, object_name, object_type
FROM   all_objects
WHERE  UPPER(object_name) = UPPER('EMPLOYEES');
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;owner 컬럼이 현재 접속 사용자(USER)와 다르면 prefix가 필요합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;해결 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;방법 1: 스키마 prefix 추가&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;n1ql&quot;&gt;&lt;code&gt;SELECT * FROM app_user.employees;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;방법 2: 시노님(SYNONYM) 생성 (권장)&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;-- PUBLIC 시노님 (모든 사용자가 prefix 없이 접근)
CREATE PUBLIC SYNONYM employees FOR app_user.employees;

-- PRIVATE 시노님 (특정 사용자만)
CREATE SYNONYM employees FOR app_user.employees;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;방법 3: 권한 부여 + 시노님 조합 (실무 표준)&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- APP_USER로 접속해서
GRANT SELECT ON employees TO batch_user;

-- BATCH_USER로 접속해서
CREATE SYNONYM employees FOR app_user.employees;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 하면 BATCH_USER가 SELECT * FROM employees로 접근 가능합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;원인 3: 권한 부족 (객체는 있지만 보이지 않음)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원인 2와 비슷해 보이지만, &lt;b&gt;권한 자체가 없는 경우&lt;/b&gt;입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;진단 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 사용자가 해당 객체에 어떤 권한이 있는지 확인합니다.&lt;/p&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;-- 직접 부여받은 권한
SELECT * FROM user_tab_privs 
WHERE  table_name = 'EMPLOYEES';

-- ROLE을 통해 받은 권한
SELECT role, table_name, privilege
FROM   role_tab_privs
WHERE  role IN (SELECT granted_role FROM user_role_privs)
  AND  table_name = 'EMPLOYEES';
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 쿼리 모두 결과가 없으면 권한이 전혀 없는 것입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;해결 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체 소유자(또는 DBA)가 권한을 부여합니다.&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- 객체 소유자로 접속
GRANT SELECT ON employees TO batch_user;

-- 여러 권한 한 번에
GRANT SELECT, INSERT, UPDATE, DELETE ON employees TO batch_user;

-- 모든 권한
GRANT ALL ON employees TO batch_user;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;권한 부여 후 클라이언트는 &lt;b&gt;재접속&lt;/b&gt;해야 즉시 반영됩니다(세션 캐시 때문).&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;실무 팁&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;운영 환경에서는 &lt;b&gt;개별 사용자에게 직접 권한을 주지 말고 ROLE 기반&lt;/b&gt;으로 관리하세요.&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- ROLE 생성
CREATE ROLE ROLE_BATCH_READ;

-- ROLE에 권한 부여
GRANT SELECT ON app_user.employees TO ROLE_BATCH_READ;
GRANT SELECT ON app_user.departments TO ROLE_BATCH_READ;

-- 사용자에게 ROLE 부여
GRANT ROLE_BATCH_READ TO batch_user;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만 ROLE 기반 권한에는 &lt;b&gt;PL/SQL에서의 함정&lt;/b&gt;이 있습니다(다음 원인 4 참고).&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;원인 4: PL/SQL 내부에서 ORA-00942 (★ 고급, 가장 까다로움)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 케이스는 다른 블로그에서 거의 다루지 않는 영역인데, &lt;b&gt;PL/SQL 개발자가 만나면 가장 헷갈리는 케이스&lt;/b&gt;입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;증상&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;직접 SQL로는 SELECT * FROM employees 가 잘 됨&lt;/li&gt;
&lt;li&gt;똑같은 SQL을 PL/SQL 프로시저 안에 넣으면 ORA-00942&lt;/li&gt;
&lt;li&gt;어제까지 잘 되던 프로시저가 갑자기 컴파일 안 됨&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;원인: DEFINER vs INVOKER 권한 + ROLE 무효화&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오라클 PL/SQL은 기본적으로 &lt;b&gt;DEFINER rights(정의자 권한)&lt;/b&gt; 으로 동작합니다. 즉:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로시저를 &lt;b&gt;만든 사용자(소유자)&lt;/b&gt; 의 권한으로 실행&lt;/li&gt;
&lt;li&gt;호출하는 사용자의 권한이 아님&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 &lt;b&gt;결정적으로, DEFINER rights PL/SQL에서는 ROLE을 통해 받은 권한이 무효화&lt;/b&gt;됩니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;예시 시나리오&lt;/h3&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- 1) APP_USER가 EMPLOYEES 테이블 소유

-- 2) BATCH_USER에게 ROLE 통해 권한 부여
GRANT SELECT ON app_user.employees TO ROLE_BATCH_READ;
GRANT ROLE_BATCH_READ TO batch_user;

-- 3) BATCH_USER로 접속해서 직접 SQL 실행
SELECT * FROM app_user.employees;
-- ✅ 잘 됨 (ROLE 권한 인식)

-- 4) 같은 SQL을 BATCH_USER 소유 프로시저에 넣음
CREATE OR REPLACE PROCEDURE PROC_READ_EMP AS
    CURSOR c1 IS SELECT * FROM app_user.employees;
BEGIN
    NULL;
END;
/
-- ❌ ORA-00942 발생 (ROLE 권한 무효화)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;해결 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;방법 1: 직접 GRANT (가장 흔한 해결)&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- ROLE을 거치지 말고 직접 부여
GRANT SELECT ON app_user.employees TO batch_user;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 프로시저 재컴파일:&lt;/p&gt;
&lt;pre class=&quot;cal&quot;&gt;&lt;code&gt;ALTER PROCEDURE PROC_READ_EMP COMPILE;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;방법 2: INVOKER rights로 변경&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;CREATE OR REPLACE PROCEDURE PROC_READ_EMP
AUTHID CURRENT_USER  -- &amp;larr; INVOKER rights
AS
    CURSOR c1 IS SELECT * FROM app_user.employees;
BEGIN
    NULL;
END;
/
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AUTHID CURRENT_USER를 명시하면 호출한 사용자의 권한으로 실행되어 ROLE 권한도 인식됩니다. 다만 운영 환경에서는 보안 정책에 따라 신중히 결정해야 합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;실무 팁&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;운영 환경에서 갑자기 프로시저가 ORA-00942로 동작 안 한다면 다음을 의심하세요.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;객체 소유자 또는 권한 부여가 변경됨&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;ROLE에서 권한이 회수됨&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;참조하는 객체가 다른 스키마로 이동&lt;/b&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;dba_dependencies 뷰로 프로시저가 어떤 객체를 참조하는지 확인할 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;SELECT referenced_owner, referenced_name, referenced_type
FROM   dba_dependencies
WHERE  owner = 'BATCH_USER'
  AND  name  = 'PROC_READ_EMP';
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;원인 5: 시노님이 깨졌거나 가리키는 객체가 없음&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시노님은 다른 객체를 가리키는 별칭일 뿐, 시노님 자체가 객체를 보장하지 않습니다. &lt;b&gt;원본 객체가 사라지거나 권한이 회수되면 시노님은 살아있지만 사용 시 ORA-00942&lt;/b&gt; 가 발생합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;진단 방법&lt;/h3&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;-- 시노님이 가리키는 대상 확인
SELECT owner, synonym_name, table_owner, table_name
FROM   all_synonyms
WHERE  UPPER(synonym_name) = UPPER('찾는_객체명');
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가리키는 table_owner.table_name이 실제로 존재하는지 별도로 확인:&lt;/p&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;SELECT owner, object_name, object_type, status
FROM   dba_objects
WHERE  owner = '확인된_OWNER'
  AND  object_name = '확인된_NAME';
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원본 객체가 없거나 권한이 없으면 시노님이 깨진 것입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;해결 방법&lt;/h3&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- 깨진 시노님 제거 후 재생성
DROP PUBLIC SYNONYM employees;
CREATE PUBLIC SYNONYM employees FOR app_user.employees;

-- 또는 권한 재부여
GRANT SELECT ON app_user.employees TO PUBLIC;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;원인 6: 대소문자 / 특수문자 문제 (드물지만 강력함)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오라클은 객체명을 &lt;b&gt;자동으로 대문자로 저장&lt;/b&gt;합니다. 그런데 객체 생성 시 따옴표로 감싸면 &lt;b&gt;대소문자가 그대로 저장&lt;/b&gt;되어 case-sensitive해집니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;시나리오&lt;/h3&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- 따옴표로 감싸서 생성 (의도적이든 실수든)
CREATE TABLE &quot;employees&quot; (id NUMBER);   -- 소문자로 저장됨

-- 일반 접근 시
SELECT * FROM employees;                 -- ❌ ORA-00942 (대문자 EMPLOYEES를 찾음)

-- 정확히 접근하려면
SELECT * FROM &quot;employees&quot;;               -- ✅ 가능
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;진단 방법&lt;/h3&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;-- 대소문자 그대로 확인
SELECT owner, object_name, object_type
FROM   dba_objects
WHERE  object_name LIKE '%mployee%';
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;object_name이 EMPLOYEES가 아니라 employees처럼 소문자로 보이면 case-sensitive 객체입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;해결 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가능하면 &lt;b&gt;객체명을 표준화(대문자)&lt;/b&gt; 하세요.&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- 기존 객체 이름 변경
ALTER TABLE &quot;employees&quot; RENAME TO employees;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;운영 중인 환경이라면 시노님으로 우회 가능합니다.&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;CREATE SYNONYM employees_std FOR &quot;employees&quot;;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;빠른 해결 체크리스트 (종합)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5분 안에 원인을 좁히는 종합 체크리스트입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;순서 확인 항목 명령어&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;DBA로 객체 존재 여부&lt;/td&gt;
&lt;td&gt;SELECT owner, object_name FROM dba_objects WHERE object_name = UPPER('객체명');&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;어느 스키마에 있는가&lt;/td&gt;
&lt;td&gt;위 쿼리의 owner 컬럼 확인&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;직접 권한이 있는가&lt;/td&gt;
&lt;td&gt;SELECT * FROM user_tab_privs WHERE table_name = '객체명';&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;ROLE 권한이 있는가&lt;/td&gt;
&lt;td&gt;SELECT * FROM role_tab_privs WHERE role IN (SELECT granted_role FROM user_role_privs);&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;PL/SQL 안에서 발생했는가&lt;/td&gt;
&lt;td&gt;DEFINER vs INVOKER, 직접 GRANT 필요&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;시노님이 깨졌는가&lt;/td&gt;
&lt;td&gt;SELECT * FROM all_synonyms WHERE synonym_name = '객체명';&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;그래도 안 풀린다면&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 6가지로도 해결되지 않는 드문 케이스:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;VPD(Virtual Private Database) / Row-Level Security&lt;/b&gt;: 보안 정책으로 특정 사용자에게 객체가 숨겨져 있는 경우&lt;/li&gt;
&lt;li&gt;&lt;b&gt;컨테이너 컨텍스트 오류 (12c+ 멀티테넌트)&lt;/b&gt;: CDB$ROOT에서 PDB의 객체에 접근하려는 경우. ALTER SESSION SET CONTAINER = PDB명; 필요&lt;/li&gt;
&lt;li&gt;&lt;b&gt;객체가 RECYCLEBIN에 있음&lt;/b&gt;: 누군가 DROP했지만 PURGE는 안 한 상태. SELECT * FROM recyclebin;으로 확인 가능&lt;/li&gt;
&lt;li&gt;&lt;b&gt;DBLINK 끊김&lt;/b&gt;: 원격 객체 접근 시 DBLINK가 끊어진 경우. SELECT * FROM user_db_links; 확인&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;마무리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ORA-00942는 메시지는 단순하지만 원인의 폭이 매우 넓은 에러입니다. &lt;b&gt;&quot;객체가 없다&quot;라기보다 &quot;내게 보이지 않는다&quot;&lt;/b&gt; 로 사고를 전환하면 진단이 훨씬 정확해집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히 &lt;b&gt;PL/SQL 내부에서 발생하는 ORA-00942는 90% 이상이 ROLE을 통한 권한 부여 때문&lt;/b&gt;입니다. 운영 환경에서 프로시저 컴파일이 갑자기 안 되면 가장 먼저 이걸 의심하세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;권한 관리는 처음 설계할 때 ROLE 기반과 직접 GRANT의 트레이드오프를 미리 고려하는 것이 중요합니다. 신규 DB 구축 시 권한 모델을 표준화해 두면 ORA-00942로 인한 운영 사고를 크게 줄일 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비슷한 케이스를 겪으셨거나, 위 방법으로도 해결되지 않은 상황이 있다면 댓글로 공유해 주세요. 함께 진단해 보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>DBA 실무/Oracle(오라클)</category>
      <category>AUTHID CURRENT_USER</category>
      <category>DBA실무</category>
      <category>ora-00942</category>
      <category>ORA-00942 원인</category>
      <category>ORA-00942 해결</category>
      <category>PL/SQL ORA-00942</category>
      <category>ROLE 권한 PL/SQL</category>
      <category>table or view does not exist</category>
      <category>소니스토리</category>
      <category>오라클 시노님 깨짐</category>
      <author>isony</author>
      <guid isPermaLink="true">https://isony.tistory.com/330</guid>
      <comments>https://isony.tistory.com/entry/%EC%98%A4%EB%9D%BC%ED%81%B4-%EC%97%90%EB%9F%AC-ORA-00942-table-or-view-does-not-exist-6%EA%B0%80%EC%A7%80-%EC%9B%90%EC%9D%B8%EA%B3%BC-%ED%95%B4%EA%B2%B0%EB%B0%A9%EB%B2%95-%EA%B6%8C%ED%95%9C%EA%B3%BC-PLSQL-%EC%BC%80%EC%9D%B4%EC%8A%A4%EA%B9%8C%EC%A7%80#entry330comment</comments>
      <pubDate>Mon, 8 Jun 2026 07:43:39 +0900</pubDate>
    </item>
    <item>
      <title>2026년06월07일 주일예배 (이재훈목사님) - 1부</title>
      <link>https://isony.tistory.com/entry/2026%EB%85%8406%EC%9B%9407%EC%9D%BC-%EC%A3%BC%EC%9D%BC%EC%98%88%EB%B0%B0-%EC%9D%B4%EC%9E%AC%ED%9B%88%EB%AA%A9%EC%82%AC%EB%8B%98-1%EB%B6%80</link>
      <description>&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;2026년06월07일&amp;nbsp;주일예배 (이재훈목사님) - 1부&lt;/h2&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;주의 말씀 : 나를 따르라&amp;nbsp; (4)&lt;/h2&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;바위 틈새에서 바라본 영광&lt;/h2&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;성경 :&amp;nbsp; 출이집트기 33:12 ~ 23 말씀 (출처:우리말성경)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&amp;lt; 성경 &amp;gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;33:12 모세가 여호와께 말했습니다. &amp;ldquo;주께서 내게 &amp;lsquo;이 백성들을 이끌라&amp;rsquo;고 줄곧 말씀해 오시지 않으셨습니까? 그러나 나와 함께 누구를 보내실지 알려 주지 않으셨습니다. 주께서 말씀하셨습니다. &amp;lsquo;내가 너를 이름으로 알고 너는 내게 은총을 입었다&amp;rsquo;라고 말입니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;33:13 주께서 나를 기쁘게 여기신다면 제발 주의 길을 내게 가르쳐 주셔서 내가 주를 알게 하시고 계속해서 주께 은총을 입게 해 주십시오. 또 이 민족이 주의 백성들임을 생각해 주십시오.&amp;rdquo;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;33:14 여호와께서 대답하셨습니다. &amp;ldquo;내가 친히 너와 함께 가겠다. 내가 너를 무사하게 할 것이다.&amp;rdquo;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;33:15 그러자 모세는 여호와께 말했습니다. &amp;ldquo;주께서 친히 우리와 함께 가지 않으시면 아예 우리를 여기서 올려 보내지 마십시오.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;33:16 주께서 우리와 함께 가지 않으시면 나와 주의 백성들이 주께 은총을 입었는지 누가 어떻게 알겠습니까? 나와 주의 백성들이 지면의 다른 모든 백성들과 어떻게 구별되겠습니까?&amp;rdquo;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;33:17 그러자 여호와께서 모세에게 &amp;ldquo;네가 말한 그대로 내가 하겠다. 네가 내 은총을 입었고 내가 너를 이름으로 알기 때문이다&amp;rdquo;라고 말씀하셨습니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;33:18 그러자 모세는 &amp;ldquo;그러면 부탁입니다만, 내게 주의 영광을 보여 주십시오&amp;rdquo;라고 말했습니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;33:19 그러자 여호와께서 말씀하셨습니다. &amp;ldquo;내가 내 모든 선함을 네 앞에 지나가게 하겠고 내가 네 앞에 내 이름 여호와를 선포하겠다. 나는 내가 불쌍히 여길 자를 불쌍히 여기고 긍휼히 여길 자를 긍휼히 여길 것이다.&amp;rdquo;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;33:20 그분께서 이어 말씀하셨습니다. &amp;ldquo;그러나 네가 내 얼굴은 보지 못한다. 나를 보고 살아남은 사람이 없다.&amp;rdquo;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;33:21 그러고 나서 여호와께서 또 말씀하셨습니다. &amp;ldquo;자, 내 가까운 곳에 바위가 있으니 그 위에 서 있어라.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;33:22 그러면 내 영광이 지나갈 때 내가 너를 바위 틈새에 두고 내가 다 지나갈 때까지 내 손으로 덮을 것이다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;33:23 그러고 나서 내가 내 손을 뗄 것이니 너는 내 뒷모습만 보고 내 얼굴은 보지 못할 것이다.&amp;rdquo;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&amp;lt; 예배 영상 &amp;gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://youtu.be/xnY5W1JPT18&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://youtu.be/xnY5W1JPT18&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1365&quot; data-origin-height=&quot;768&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/crMXIh/dJMcaar3fxr/UowxwRkN2dIjVFVjHNYuR0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/crMXIh/dJMcaar3fxr/UowxwRkN2dIjVFVjHNYuR0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/crMXIh/dJMcaar3fxr/UowxwRkN2dIjVFVjHNYuR0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcrMXIh%2FdJMcaar3fxr%2FUowxwRkN2dIjVFVjHNYuR0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1365&quot; height=&quot;768&quot; data-origin-width=&quot;1365&quot; data-origin-height=&quot;768&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&amp;lt; 사도신경 &amp;gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;bandicam 2026-06-07 07-58-42-754.jpg&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c548yB/dJMcacDpXd1/tRc10uPeY2qxvaNPis5llK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c548yB/dJMcacDpXd1/tRc10uPeY2qxvaNPis5llK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c548yB/dJMcacDpXd1/tRc10uPeY2qxvaNPis5llK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc548yB%2FdJMcacDpXd1%2FtRc10uPeY2qxvaNPis5llK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-filename=&quot;bandicam 2026-06-07 07-58-42-754.jpg&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;bandicam 2026-06-07 07-59-05-743.jpg&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Fzhc9/dJMcaiQ6KSr/acQxNNnaaQkZgAubuFEw91/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Fzhc9/dJMcaiQ6KSr/acQxNNnaaQkZgAubuFEw91/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Fzhc9/dJMcaiQ6KSr/acQxNNnaaQkZgAubuFEw91/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFzhc9%2FdJMcaiQ6KSr%2FacQxNNnaaQkZgAubuFEw91%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-filename=&quot;bandicam 2026-06-07 07-59-05-743.jpg&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>성경과 QT/주일예배(온누리교회)</category>
      <category>CGNTV</category>
      <category>나를 따르라</category>
      <category>바라본 영광</category>
      <category>소니스토리</category>
      <category>영상예배</category>
      <category>온누리교회</category>
      <category>우리말성경</category>
      <category>이재훈목사</category>
      <category>주일예배</category>
      <category>출이집트</category>
      <author>isony</author>
      <guid isPermaLink="true">https://isony.tistory.com/329</guid>
      <comments>https://isony.tistory.com/entry/2026%EB%85%8406%EC%9B%9407%EC%9D%BC-%EC%A3%BC%EC%9D%BC%EC%98%88%EB%B0%B0-%EC%9D%B4%EC%9E%AC%ED%9B%88%EB%AA%A9%EC%82%AC%EB%8B%98-1%EB%B6%80#entry329comment</comments>
      <pubDate>Sun, 7 Jun 2026 08:16:23 +0900</pubDate>
    </item>
    <item>
      <title>[오라클 에러] ORA-12514 TNS:리스너가 서비스를 알지 못함 - 5가지 원인과 해결방법 (PDB 환경 포함)</title>
      <link>https://isony.tistory.com/entry/%EC%98%A4%EB%9D%BC%ED%81%B4-%EC%97%90%EB%9F%AC-ORA-12514-TNS%EB%A6%AC%EC%8A%A4%EB%84%88%EA%B0%80-%EC%84%9C%EB%B9%84%EC%8A%A4%EB%A5%BC-%EC%95%8C%EC%A7%80-%EB%AA%BB%ED%95%A8-5%EA%B0%80%EC%A7%80-%EC%9B%90%EC%9D%B8%EA%B3%BC-%ED%95%B4%EA%B2%B0%EB%B0%A9%EB%B2%95-PDB-%ED%99%98%EA%B2%BD-%ED%8F%AC%ED%95%A8</link>
      <description>&lt;h1&gt;[오라클 에러] ORA-12514 TNS:리스너가 서비스를 알지 못함 - 5가지 원인과 해결방법 (PDB 환경 포함)&lt;/h1&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;테스트 환경&lt;/b&gt;: Oracle 12c / 19c / 21c / 23ai, Oracle Linux 8, Windows Server 2019&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ORA-12514는 ORA-12541과 함께 오라클 접속 시 가장 자주 마주치는 에러입니다. 두 에러는 메시지가 비슷해서 자주 혼동되는데, &lt;b&gt;원인은 완전히 다릅니다&lt;/b&gt;.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;ORA-12541&lt;/b&gt;: 리스너 자체가 죽었거나 응답 안 함&lt;/li&gt;
&lt;li&gt;&lt;b&gt;ORA-12514&lt;/b&gt;: 리스너는 살아있지만 요청한 &lt;b&gt;서비스를 모름&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히 12c부터 도입된 멀티테넌트(CDB/PDB) 환경에서는 ORA-12514가 폭증했습니다. 19c 이상에서 운영 중인 환경이라면 더더욱 자주 만나는 에러입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 글에서는 ORA-12514의 5가지 원인을 분류하고, &lt;b&gt;PDB 환경 특화 이슈와 도메인(DB_DOMAIN) 미스매치&lt;/b&gt;까지 정리했습니다. 급하신 분은 &lt;u&gt;빠른 진단 체크리스트&lt;/u&gt;부터 보세요.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;에러 메시지 전문&lt;/h2&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;ORA-12514: TNS:listener does not currently know of service requested in connect descriptor
ORA-12514: TNS:리스너가 현재 접속 기술자에 요청된 서비스를 알지 못함
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;19c 이상에서는 더 자세한 정보가 함께 표시되기도 합니다.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;ORA-12514: Cannot connect to database. Service sales_service.example.com is not registered 
with the listener at host 10.9.7.5 port 1522. (CONNECTION_ID=...)
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 형식은 어떤 서비스명이 문제인지 명확히 알려주기 때문에 진단에 큰 도움이 됩니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;ORA-12541 vs ORA-12514 - 한 표로 정리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 에러가 헷갈리는 분들을 위한 핵심 비교표입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;항목 ORA-12541 ORA-12514&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;메시지&lt;/td&gt;
&lt;td&gt;리스너가 없습니다&lt;/td&gt;
&lt;td&gt;리스너가 서비스를 알지 못함&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;리스너 상태&lt;/td&gt;
&lt;td&gt;&lt;b&gt;죽음 / 응답 없음&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;살아있음&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;lsnrctl status&lt;/td&gt;
&lt;td&gt;연결 실패&lt;/td&gt;
&lt;td&gt;정상 출력&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;telnet host 1521&lt;/td&gt;
&lt;td&gt;실패&lt;/td&gt;
&lt;td&gt;성공&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;핵심 원인&lt;/td&gt;
&lt;td&gt;리스너 프로세스 자체 문제&lt;/td&gt;
&lt;td&gt;&lt;b&gt;service_name 미등록 / 오기재&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PDB 환경 영향&lt;/td&gt;
&lt;td&gt;영향 없음&lt;/td&gt;
&lt;td&gt;&lt;b&gt;매우 큼&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;해결 방향&lt;/td&gt;
&lt;td&gt;리스너 시작 / 포트 / 방화벽&lt;/td&gt;
&lt;td&gt;service_name 확인 / PDB 상태&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;한 줄 진단법&lt;/b&gt;: 클라이언트에서 tnsping host:port 가 성공하는데 sqlplus 접속이 안 되면 ORA-12514, tnsping 자체가 실패하면 ORA-12541일 가능성이 큽니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;빠른 진단 체크리스트&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;본격 해결 전에 30초 만에 원인을 좁히는 순서입니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;lsnrctl services 실행&lt;/b&gt; &amp;rarr; 리스너가 알고 있는 서비스 목록 확인&lt;/li&gt;
&lt;li&gt;&lt;b&gt;연결 문자열의 service_name 확인&lt;/b&gt; &amp;rarr; 위 목록에 있는가?&lt;/li&gt;
&lt;li&gt;&lt;b&gt;PDB 환경이면 &amp;rarr; PDB 상태 확인&lt;/b&gt; (select name, open_mode from v$pdbs;)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;DB_DOMAIN 설정 확인&lt;/b&gt; &amp;rarr; 도메인 누락 가능성 (show parameter db_domain)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;리스너 시작 직후 5분 이내라면&lt;/b&gt; &amp;rarr; 등록 대기 중일 수 있음&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;원인 1: service_name 오타 또는 누락 (가장 흔함)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ORA-12514의 70% 이상이 이 케이스입니다. 클라이언트의 tnsnames.ora에 적힌 SERVICE_NAME과 실제 DB의 서비스명이 다르면 발생합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;진단 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;서버에서 리스너가 알고 있는 서비스 목록 확인:&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;ebnf&quot;&gt;&lt;code&gt;lsnrctl services
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;출력 예시:&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;Services Summary...
Service &quot;ORCL&quot; has 1 instance(s).
  Instance &quot;ORCL&quot;, status READY, has 1 handler(s) for this service...
Service &quot;ORCLXDB&quot; has 1 instance(s).
  Instance &quot;ORCL&quot;, status READY, has 1 handler(s) for this service...
Service &quot;pdbprod&quot; has 1 instance(s).
  Instance &quot;ORCL&quot;, status READY, has 1 handler(s) for this service...
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기에 &lt;b&gt;있는&lt;/b&gt; 서비스명만 접속 가능합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;클라이언트의 tnsnames.ora 확인:&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;lisp&quot;&gt;&lt;code&gt;PRODDB =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.10.5)(PORT = 1521))
    (CONNECT_DATA =
      (SERVICE_NAME = pdbprod)   &amp;larr; 이 값이 lsnrctl services 결과에 있어야 함
    )
  )
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;service_name vs SID - 자주 혼동&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;신입 DBA가 가장 헷갈리는 부분입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구분 SID SERVICE_NAME&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;의미&lt;/td&gt;
&lt;td&gt;인스턴스 식별자&lt;/td&gt;
&lt;td&gt;서비스 식별자 (논리적)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;멀티테넌트&lt;/td&gt;
&lt;td&gt;CDB만 가능&lt;/td&gt;
&lt;td&gt;&lt;b&gt;PDB 접속에 필수&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;권장&lt;/td&gt;
&lt;td&gt;레거시 호환용&lt;/td&gt;
&lt;td&gt;&lt;b&gt;신규 코드에서 권장&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;형식 (tnsnames)&lt;/td&gt;
&lt;td&gt;(SID = ORCL)&lt;/td&gt;
&lt;td&gt;(SERVICE_NAME = pdbprod)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;형식 (Easy Connect)&lt;/td&gt;
&lt;td&gt;host:port:SID&lt;/td&gt;
&lt;td&gt;host:port/service_name&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Easy Connect 표기법 차이를 보세요.&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;# SID 방식 (레거시)
sqlplus user/pw@192.168.10.5:1521:ORCL

# SERVICE_NAME 방식 (권장)
sqlplus user/pw@192.168.10.5:1521/pdbprod
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: 와 / 의 차이로 SID인지 SERVICE_NAME인지가 결정됩니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;해결 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;lsnrctl services 결과의 정확한 서비스명을 그대로 사용하세요.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;sqlplus user/pw@192.168.10.5:1521/pdbprod
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;원인 2: PDB가 OPEN 상태가 아님 (12c+ 멀티테넌트 특화) ★&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 케이스는 다른 한국어 블로그에서 거의 다루지 않는 영역입니다. &lt;b&gt;멀티테넌트 환경에서 ORA-12514가 발생하면 가장 먼저 의심해야 할 케이스&lt;/b&gt;입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;무엇이 문제인가&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PDB는 &lt;b&gt;OPEN 상태일 때만&lt;/b&gt; 자신의 서비스가 리스너에 자동 등록됩니다. PDB가 MOUNTED 상태로 머물러 있으면 해당 PDB의 service_name이 리스너에 보이지 않아 ORA-12514가 발생합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DB가 재시작되면 PDB는 &lt;b&gt;기본적으로 MOUNTED 상태&lt;/b&gt;로 올라오기 때문에, &lt;b&gt;DB 재시작 직후 ORA-12514가 발생하는 가장 흔한 이유&lt;/b&gt;가 이 경우입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;진단 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CDB$ROOT에 접속해서 PDB 상태를 확인합니다.&lt;/p&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;sqlplus / as sysdba

SQL&amp;gt; SELECT name, open_mode, restricted FROM v$pdbs;

NAME         OPEN_MODE    RESTRICTED
------------ ------------ ----------
PDB$SEED     READ ONLY    NO
PDBPROD      MOUNTED      &amp;larr; 이게 문제
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PDBPROD가 MOUNTED 상태라면 리스너에서도 안 보입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;해결 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1) PDB를 OPEN 상태로 변경&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;ALTER PLUGGABLE DATABASE PDBPROD OPEN;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2) 다음 재시작 시에도 자동으로 OPEN되도록 영구 설정&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;ALTER PLUGGABLE DATABASE PDBPROD SAVE STATE;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 설정을 하지 않으면 DB 재시작 때마다 PDB를 수동으로 OPEN해야 합니다. 운영 환경에서는 반드시 SAVE STATE를 적용하세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3) 모든 PDB 일괄 OPEN&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;ALTER PLUGGABLE DATABASE ALL OPEN;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;실무 팁&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DB 시작 트리거를 만들어 PDB 자동 OPEN을 보장하는 방법도 있지만, 12.1.0.2 이상에서는 위 SAVE STATE 명령이 표준 방법입니다. 트리거 방식보다 안전하고 권장됩니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;원인 3: DB 인스턴스가 리스너에 등록 안 됨 (동적 등록 실패)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오라클은 DB 인스턴스가 시작될 때 &lt;b&gt;PMON 프로세스가 리스너에 자신을 동적으로 등록&lt;/b&gt;합니다. 이 등록이 실패하면 리스너는 인스턴스의 존재를 모릅니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;자주 발생하는 시나리오&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;리스너 시작 직후 1~2분 이내&lt;/b&gt;: 등록이 아직 완료되지 않은 일시적 상태 (잠시 기다리면 해결)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;리스너 포트가 비표준 (1521이 아님)&lt;/b&gt;: 인스턴스에 LOCAL_LISTENER 파라미터 설정 필요&lt;/li&gt;
&lt;li&gt;&lt;b&gt;리스너와 인스턴스가 다른 호스트&lt;/b&gt;: 동적 등록은 기본적으로 동일 호스트 가정&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;진단 방법&lt;/h3&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;SQL&amp;gt; SHOW PARAMETER local_listener
SQL&amp;gt; SHOW PARAMETER service_names
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PMON에게 강제로 재등록 요청:&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;SQL&amp;gt; ALTER SYSTEM REGISTER;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 명령을 실행한 후 다시 lsnrctl services를 보면 서비스가 등록됩니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;해결 방법: 비표준 포트 환경&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리스너 포트가 1522처럼 1521이 아니라면, 인스턴스에 LOCAL_LISTENER 파라미터를 명시해야 합니다.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;ALTER SYSTEM SET LOCAL_LISTENER = 
  '(ADDRESS=(PROTOCOL=TCP)(HOST=192.168.10.5)(PORT=1522))' 
  SCOPE=BOTH;

ALTER SYSTEM REGISTER;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;원인 4: DB_DOMAIN 미스매치 (19c 이상에서 흔함) ★&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;19c 이상 환경에서 service_name에 도메인이 붙는 경우가 일반적입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;무엇이 문제인가&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DB_DOMAIN 파라미터가 example.com으로 설정되어 있으면, 인스턴스가 리스너에 등록하는 service_name은 자동으로 orcl.example.com처럼 도메인이 붙은 형태가 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클라이언트가 SERVICE_NAME = orcl로만 요청하면 리스너는 &quot;그런 서비스 없음&quot;으로 응답합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;진단 방법&lt;/h3&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;SQL&amp;gt; SHOW PARAMETER db_domain
SQL&amp;gt; SHOW PARAMETER service_names
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;lsnrctl services 결과와 클라이언트의 tnsnames.ora 값을 비교합니다.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;# 서버에서 보이는 실제 서비스명
Service &quot;orcl.example.com&quot;

# 클라이언트가 요청하는 서비스명
SERVICE_NAME = orcl   &amp;larr; 도메인 누락
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;해결 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1) 클라이언트의 tnsnames.ora에 도메인 추가 (권장)&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;SERVICE_NAME = orcl.example.com
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2) 또는 인스턴스의 service_names를 도메인 없이 등록&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;ALTER SYSTEM SET SERVICE_NAMES = 'orcl' SCOPE=BOTH;
ALTER SYSTEM REGISTER;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;후자는 환경 표준에 따라 결정합니다. 운영 정책상 도메인을 유지해야 한다면 1번 방식으로 가세요.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;원인 5: listener.ora 정적 등록 설정 오류&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대부분의 환경에서는 동적 등록을 사용하지만, 정적 등록이 필요한 경우가 있습니다(예: 외부 프로시저 호출, RMAN 백업 카탈로그 접속).&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;정적 등록 vs 동적 등록&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구분 동적 등록 정적 등록&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;누가 등록&lt;/td&gt;
&lt;td&gt;PMON 프로세스 (자동)&lt;/td&gt;
&lt;td&gt;DBA가 listener.ora에 직접 작성&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DB 다운 시&lt;/td&gt;
&lt;td&gt;자동 해제&lt;/td&gt;
&lt;td&gt;등록 유지 (BLOCKED 상태로 보임)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;시작 시점&lt;/td&gt;
&lt;td&gt;DB 인스턴스 시작 시&lt;/td&gt;
&lt;td&gt;리스너 시작 시&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;권장&lt;/td&gt;
&lt;td&gt;일반적 운영 환경&lt;/td&gt;
&lt;td&gt;특수 목적 (RMAN, 외부 프로시저)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;listener.ora 정적 등록 예시&lt;/h3&gt;
&lt;pre class=&quot;lisp&quot;&gt;&lt;code&gt;SID_LIST_LISTENER =
  (SID_LIST =
    (SID_DESC =
      (GLOBAL_DBNAME = orcl)
      (ORACLE_HOME = /u01/app/oracle/product/19c/dbhome_1)
      (SID_NAME = ORCL)
    )
  )

LISTENER =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.10.5)(PORT = 1521))
  )
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;자주 발생하는 실수&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;GLOBAL_DBNAME을 클라이언트의 SERVICE_NAME과 다르게 입력&lt;/li&gt;
&lt;li&gt;SID_NAME을 잘못 입력 (실제 인스턴스명과 불일치)&lt;/li&gt;
&lt;li&gt;정적 등록 후 리스너 미재시작 (lsnrctl reload 필요)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;해결 방법&lt;/h3&gt;
&lt;pre class=&quot;properties&quot;&gt;&lt;code&gt;# 설정 변경 후 반드시 reload
lsnrctl reload

# 또는 재시작
lsnrctl stop
lsnrctl start

# 확인
lsnrctl services
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;빠른 해결 체크리스트&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5분 안에 원인을 좁히는 종합 체크리스트입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;순서 확인 항목 명령어&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;리스너가 알고 있는 서비스 목록&lt;/td&gt;
&lt;td&gt;lsnrctl services&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;클라이언트의 service_name 정확한가&lt;/td&gt;
&lt;td&gt;tnsnames.ora 확인&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;PDB 환경이면 PDB 상태 확인&lt;/td&gt;
&lt;td&gt;SELECT name, open_mode FROM v$pdbs;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;DB_DOMAIN 설정&lt;/td&gt;
&lt;td&gt;SHOW PARAMETER db_domain&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;강제 재등록 시도&lt;/td&gt;
&lt;td&gt;ALTER SYSTEM REGISTER;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 5단계로 ORA-12514의 95% 이상이 해결됩니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;그래도 안 풀린다면&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 5가지로도 해결되지 않는 드문 케이스:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Data Guard 환경에서 Standby에 접속 시도&lt;/b&gt;: Standby의 service_names는 별도 등록이 필요&lt;/li&gt;
&lt;li&gt;&lt;b&gt;RAC 환경의 SCAN 리스너 vs 로컬 리스너 혼동&lt;/b&gt;: SCAN 리스너로 접속해야 하는데 로컬 리스너 호스트로 접속 시도&lt;/li&gt;
&lt;li&gt;&lt;b&gt;리스너 시작 직후 5분 이내&lt;/b&gt;: 동적 등록 완료 전 일시적 ORA-12514. 잠시 후 자동 해결&lt;/li&gt;
&lt;li&gt;&lt;b&gt;방화벽이 1521만 열고 동적 포트 차단&lt;/b&gt;: 일부 환경에서 데이터 통신용 동적 포트가 별도 필요&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;마무리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ORA-12514는 &quot;서비스를 모름&quot;이라는 한 가지 증상이지만, 원인은 service_name 오타부터 PDB 상태, DB_DOMAIN 미스매치까지 다양합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;ORA-12541과 헷갈리지 않는 것&lt;/b&gt;이 진단의 첫 단추입니다. 리스너가 살아있는지 (lsnrctl status) 확인했다면 ORA-12541은 아니고, 그다음으로 어떤 서비스를 알고 있는지 (lsnrctl services) 확인하는 것이 핵심입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히 &lt;b&gt;12c 이상 멀티테넌트 환경에서 DB 재시작 후 발생한 ORA-12514라면 90% 이상이 PDB가 MOUNTED 상태&lt;/b&gt;입니다. ALTER PLUGGABLE DATABASE ... SAVE STATE 한 줄로 재발을 영구 방지할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비슷한 케이스를 겪으셨거나, 위 방법으로도 해결되지 않은 상황이 있다면 댓글로 공유해 주세요. 함께 해결책을 찾아보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>DBA 실무/Oracle(오라클)</category>
      <category>ORA-12514</category>
      <category>ORA-12514 햬껼</category>
      <category>ORAC-12514 원인</category>
      <category>TNS 리쓰너</category>
      <category>소니스토리</category>
      <author>isony</author>
      <guid isPermaLink="true">https://isony.tistory.com/328</guid>
      <comments>https://isony.tistory.com/entry/%EC%98%A4%EB%9D%BC%ED%81%B4-%EC%97%90%EB%9F%AC-ORA-12514-TNS%EB%A6%AC%EC%8A%A4%EB%84%88%EA%B0%80-%EC%84%9C%EB%B9%84%EC%8A%A4%EB%A5%BC-%EC%95%8C%EC%A7%80-%EB%AA%BB%ED%95%A8-5%EA%B0%80%EC%A7%80-%EC%9B%90%EC%9D%B8%EA%B3%BC-%ED%95%B4%EA%B2%B0%EB%B0%A9%EB%B2%95-PDB-%ED%99%98%EA%B2%BD-%ED%8F%AC%ED%95%A8#entry328comment</comments>
      <pubDate>Fri, 5 Jun 2026 12:33:46 +0900</pubDate>
    </item>
    <item>
      <title>[Claude Code 활용 3편] SQL과 Oracle DBA 업무에 Claude Code 활용하기 (튜닝부터 트러블슈팅까지)</title>
      <link>https://isony.tistory.com/entry/Claude-Code-%ED%99%9C%EC%9A%A9-3%ED%8E%B8-SQL%EA%B3%BC-Oracle-DBA-%EC%97%85%EB%AC%B4%EC%97%90-Claude-Code-%ED%99%9C%EC%9A%A9%ED%95%98%EA%B8%B0-%ED%8A%9C%EB%8B%9D%EB%B6%80%ED%84%B0-%ED%8A%B8%EB%9F%AC%EB%B8%94%EC%8A%88%ED%8C%85%EA%B9%8C%EC%A7%80</link>
      <description>&lt;h1&gt;[Claude Code 활용 3편] SQL과 Oracle DBA 업무에 Claude Code 활용하기 (튜닝부터 트러블슈팅까지)&lt;/h1&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;테스트 환경&lt;/b&gt;: Oracle 19c / 21c, Claude Code v2.x&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.whodo.net/entry/Claude-Code-%ED%99%9C%EC%9A%A9-1%ED%8E%B8-DBA%EC%99%80-%EC%84%9C%EB%B2%84-%EA%B4%80%EB%A6%AC%EC%9E%90%EA%B0%80-Claude-Code%EB%A5%BC-%EC%8D%A8%EC%95%BC-%ED%95%98%EB%8A%94-%EC%9D%B4%EC%9C%A0-%EC%84%A4%EC%B9%98%EB%B6%80%ED%84%B0-%EC%8B%A4%EC%A0%84-5%EA%B0%80%EC%A7%80-%ED%99%9C%EC%9A%A9%EA%B9%8C%EC%A7%80&quot;&gt;1편&lt;/a&gt;에서 Claude Code 입문을, &lt;a href=&quot;https://www.whodo.net/entry/Claude-Code-%ED%99%9C%EC%9A%A9-2%ED%8E%B8-%EC%85%B8-%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EC%99%80-%EC%9A%B4%EC%98%81-%EC%9E%90%EB%8F%99%ED%99%94%EC%97%90-Claude-Code-%ED%99%9C%EC%9A%A9%ED%95%98%EA%B8%B0-%EC%8B%A4%EC%A0%84-%EC%82%AC%EB%A1%80-5%EA%B0%80%EC%A7%80&quot;&gt;2편&lt;/a&gt;에서 셸 스크립트 자동화를 다뤘습니다. 이번 3편은 &lt;b&gt;Oracle DBA 업무에 Claude Code를 활용하는 방법&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DBA 업무는 SQL 작성&amp;middot;튜닝, 작업 등록, 트러블슈팅, 모니터링이 핵심입니다. 이 영역에서 Claude Code는 단순한 &quot;쿼리 생성기&quot;를 넘어, &lt;b&gt;본인 환경의 실행 계획&amp;middot;통계 정보&amp;middot;에러 로그를 함께 분석하면서 답을 주는 협업 파트너&lt;/b&gt; 역할을 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 글에서는 다음 5가지 사례를 다룹니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;SQL 작성 (특히 복잡한 분석 쿼리)&lt;/li&gt;
&lt;li&gt;실행 계획 분석과 튜닝 방향 제시&lt;/li&gt;
&lt;li&gt;DBMS_SCHEDULER 작업 자동 생성&lt;/li&gt;
&lt;li&gt;ORA 에러 분석 및 해결 방향 제시&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DBA 일일 점검 보고서 자동 생성&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;시작 전 - DBA용 CLAUDE.md 설정&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DBA 작업에 특화된 컨텍스트를 미리 정의해 두면 매번 환경 설명을 안 해도 됩니다.&lt;/p&gt;
&lt;pre class=&quot;markdown&quot;&gt;&lt;code&gt;# DBA 작업 환경

## DB 정보
- Oracle 19c (19.21.0)
- OS: Oracle Linux 8.8
- 인스턴스: PRODDB
- 캐릭터셋: AL32UTF8
- 타임존: Asia/Seoul

## 주요 스키마
- APP_USER: 애플리케이션 메인 스키마
- BATCH_USER: 배치 작업 스키마
- READ_ONLY_USER: 조회 전용 (모니터링)

## SQL 작성 규칙
- 키워드는 대문자, 객체명은 소문자
- 들여쓰기는 4 spaces
- JOIN은 ANSI 표준 (LEFT JOIN, INNER JOIN)
- WHERE 절이 없는 UPDATE/DELETE는 절대 작성 금지
- 운영 DB의 DDL은 항상 IF EXISTS / IF NOT EXISTS 사용

## 보안 규칙
- 비밀번호를 SQL 안에 평문으로 넣지 말 것
- DROP, TRUNCATE는 영향 범위 사전 확인 후 안내
- 운영 환경 변경 SQL은 항상 ROLLBACK 시나리오 포함
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 컨텍스트가 있으면 &quot;쿼리 짜 줘&quot;라고만 해도 본인 환경 표준에 맞춰 결과가 나옵니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;사례 1: 복잡한 분석 SQL 작성&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단순 SELECT는 직접 작성하는 게 빠릅니다. Claude Code의 진짜 강점은 &lt;b&gt;여러 조건과 비즈니스 로직이 얽힌 분석 쿼리&lt;/b&gt;에서 드러납니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;프롬프트&lt;/h3&gt;
&lt;pre class=&quot;markdown&quot;&gt;&lt;code&gt;&amp;gt; 다음 분석 쿼리를 작성해 줘.
  
  - 대상 테이블: orders, order_items, customers, products
  - 조건:
    1. 최근 30일 주문 데이터
    2. 고객 등급(VIP, GOLD, SILVER)별로 분리
    3. 등급별 매출 합계와 주문 건수
    4. 각 등급에서 가장 많이 팔린 상품 TOP 3
    5. 등급 간 비교를 위한 전체 대비 비율 (%) 포함
  - 결과는 한 쿼리로 (WITH 절 활용)
  - 인덱스 활용을 고려해 작성
  - 가독성을 위해 주석 추가
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude가 만들어 주는 쿼리는 WITH 절로 단계를 나누고, 윈도우 함수(RANK() OVER (...))로 TOP N을 추출하며, RATIO_TO_REPORT()로 비율까지 계산합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;더 효과적인 활용 - 점진적 개선&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음에 받은 쿼리에 대해 이어서 요청하면 더 정교해집니다.&lt;/p&gt;
&lt;pre class=&quot;markdown&quot;&gt;&lt;code&gt;&amp;gt; 이 쿼리를 EXPLAIN PLAN으로 분석해서 인덱스가 잘 활용되는지 확인하고,
  비효율적인 부분이 있다면 힌트(/*+ ... */)를 추가해서 개선해 줘.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude가 실행 계획을 직접 보고 (EXPLAIN PLAN FOR ... + DBMS_XPLAN.DISPLAY) 비효율을 찾아 힌트를 제안합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;사례 2: 실행 계획 분석과 튜닝 방향&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DBA 업무에서 가장 시간이 걸리는 작업 중 하나가 &lt;b&gt;느린 쿼리의 원인 분석&lt;/b&gt;입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;프롬프트&lt;/h3&gt;
&lt;pre class=&quot;markdown&quot;&gt;&lt;code&gt;&amp;gt; 다음 SQL의 실행 계획을 분석해 줘.
  [SQL 본문]
  
  - 현재 실행 시간: 약 45초
  - 데이터 건수: orders 약 5천만 건, order_items 약 2억 건
  - 기존 인덱스: orders(customer_id), order_items(order_id)
  
  실행 계획을 분석하고:
  1. 가장 비용이 큰 단계가 어디인가
  2. 풀 스캔이 발생하는가, 발생한다면 의도된 것인가
  3. 조인 순서와 조인 방식이 적절한가
  4. 추가하면 좋을 인덱스
  5. 쿼리 자체를 재작성하면 더 빠를지
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude는 EXPLAIN PLAN을 실행하고 (또는 사용자가 제공한 실행 계획을 분석하고), 위 5가지 항목을 짚어 줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히 강력한 부분은 &lt;b&gt;&quot;인덱스 추가 시 효과 추정&quot;&lt;/b&gt; 입니다.&lt;/p&gt;
&lt;pre class=&quot;erlang&quot;&gt;&lt;code&gt;&amp;gt; orders(customer_id, order_date) 복합 인덱스를 추가하면 
  이 쿼리의 실행 계획이 어떻게 바뀔지 예측해 줘.
  그리고 다른 SQL에 미칠 영향(인덱스 유지 비용, 다른 쿼리에서의 활용)도 함께.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인덱스 추가는 한 번 결정하면 되돌리기 부담스러운 작업입니다. 사전에 영향도를 검토하는 데 큰 도움이 됩니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;사례 3: DBMS_SCHEDULER 작업 자동 생성&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.whodo.net/entry/Claude-Code-%ED%99%9C%EC%9A%A9-2%ED%8E%B8-%EC%85%B8-%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EC%99%80-%EC%9A%B4%EC%98%81-%EC%9E%90%EB%8F%99%ED%99%94%EC%97%90-Claude-Code-%ED%99%9C%EC%9A%A9%ED%95%98%EA%B8%B0-%EC%8B%A4%EC%A0%84-%EC%82%AC%EB%A1%80-5%EA%B0%80%EC%A7%80&quot;&gt;이전 글&lt;/a&gt;에서 DBMS_SCHEDULER 작업을 수동으로 등록하는 방법을 다뤘는데, Claude Code를 쓰면 더 빠릅니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;프롬프트&lt;/h3&gt;
&lt;pre class=&quot;markdown&quot;&gt;&lt;code&gt;&amp;gt; 다음 사양으로 DBMS_SCHEDULER 작업을 생성해 줘.
  
  - 작업명: JOB_DAILY_STATS_REFRESH
  - 실행할 프로시저: PKG_STATS.REFRESH_DAILY
  - 인자: 어제 날짜 (YYYY-MM-DD 형식)
  - 실행 시각: 매일 새벽 1시 30분
  - 타임존: Asia/Seoul 명시
  - 실패 시 dba@company.com에 메일 알림
  - 평균 실행 시간이 1시간을 넘으면 경고
  - 작업 등록 SQL과 함께 검증 쿼리도 같이
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude가 만들어 주는 결과:&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- 1) 작업 생성
BEGIN
    DBMS_SCHEDULER.CREATE_JOB(
        job_name        =&amp;gt; 'JOB_DAILY_STATS_REFRESH',
        job_type        =&amp;gt; 'PLSQL_BLOCK',
        job_action      =&amp;gt; q'[
            DECLARE
                v_yest VARCHAR2(10) := TO_CHAR(SYSDATE - 1, 'YYYY-MM-DD');
            BEGIN
                PKG_STATS.REFRESH_DAILY(v_yest);
            END;
        ]',
        start_date      =&amp;gt; TO_TIMESTAMP_TZ(
                              TO_CHAR(SYSDATE+1, 'YYYY-MM-DD') || ' 01:30:00 Asia/Seoul',
                              'YYYY-MM-DD HH24:MI:SS TZR'),
        repeat_interval =&amp;gt; 'FREQ=DAILY;BYHOUR=1;BYMINUTE=30;BYSECOND=0',
        enabled         =&amp;gt; TRUE,
        comments        =&amp;gt; '일일 통계 갱신 (어제 날짜 기준)'
    );
END;
/

-- 2) 실패 알림 등록
BEGIN
    DBMS_SCHEDULER.ADD_JOB_EMAIL_NOTIFICATION(
        job_name   =&amp;gt; 'JOB_DAILY_STATS_REFRESH',
        recipients =&amp;gt; 'dba@company.com',
        events     =&amp;gt; 'JOB_FAILED, JOB_BROKEN, JOB_OVER_MAX_DUR'
    );
END;
/

-- 3) 최대 실행 시간 1시간 설정
BEGIN
    DBMS_SCHEDULER.SET_ATTRIBUTE(
        name      =&amp;gt; 'JOB_DAILY_STATS_REFRESH',
        attribute =&amp;gt; 'max_run_duration',
        value     =&amp;gt; INTERVAL '1' HOUR
    );
END;
/

-- 4) 검증 쿼리
SELECT job_name, state, enabled, 
       TO_CHAR(next_run_date, 'YYYY-MM-DD HH24:MI:SS') AS next_run,
       max_run_duration
FROM   user_scheduler_jobs
WHERE  job_name = 'JOB_DAILY_STATS_REFRESH';
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;수동 작성 시간 약 10분 &amp;rarr; Claude 활용 시간 30초.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;사례 4: ORA 에러 분석 및 해결 방향 ★ 가장 강력한 활용&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DBA가 가장 자주 마주치는 게 &lt;b&gt;알 수 없는 ORA-XXXXX 에러&lt;/b&gt;입니다. 평소라면 검색 &amp;rarr; 블로그 5개 &amp;rarr; 본인 환경에 맞춰 변형의 과정을 거치는데, Claude Code는 한 번에 해결합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;프롬프트 (장애 발생 직후)&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;&amp;gt; alert 로그에서 다음 에러가 발생했어.
  
  [에러 메시지 전체 붙여 넣기]
  
  - 발생 시각: 2026-05-30 14:23:17
  - 직전에 실행 중이던 작업: 월말 배치 (PKG_MONTHLY.CLOSE_ACCOUNTS)
  - DB 버전: Oracle 19.21
  - 메모리: SGA 64GB / PGA 32GB
  
  원인을 분석하고:
  1. 어떤 종류의 문제인지 (메모리/락/IO/네트워크 등)
  2. 즉시 확인할 진단 쿼리 (v$ 뷰)
  3. 단기 해결 방안 (장애 대응)
  4. 근본 해결 방안 (재발 방지)
  순서로 정리해 줘.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude가 에러 코드를 분석하고, &lt;b&gt;본인 환경의 v$ 뷰를 직접 조회해서 추가 정보를 수집&lt;/b&gt;한 뒤, 단계별 대응 방안을 제시합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;더 발전된 활용 - alert 로그 자동 감시&lt;/h3&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;&amp;gt; /u01/app/oracle/diag/rdbms/proddb/PRODDB/trace/alert_PRODDB.log 파일을 
  지속적으로 감시하다가 ORA-, TNS-, ORACLE Instance 같은 키워드가 
  새로 발견되면 분석 보고서를 자동 생성하는 스크립트를 만들어 줘.
  
  보고서에는:
  - 발견 시각
  - 에러 메시지 (앞뒤 10줄 컨텍스트 포함)
  - 1차 분석 (Claude의 추정 원인)
  - 권장 대응 절차
  
  보고서는 /var/log/oracle/alerts/ 폴더에 timestamp 파일명으로 저장.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;운영 환경에 한 번 설정해 두면, &lt;b&gt;장애 발생 즉시 1차 분석된 보고서가 자동 생성&lt;/b&gt;됩니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;사례 5: DBA 일일 점검 보고서 자동 생성&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;매일 아침 출근해서 DB 상태를 점검하는 작업은 시간이 오래 걸리지만 빠뜨릴 수 없는 일입니다. 이걸 한 번에 자동화할 수 있습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;프롬프트&lt;/h3&gt;
&lt;pre class=&quot;markdown&quot;&gt;&lt;code&gt;&amp;gt; DBA 일일 점검 보고서를 자동으로 생성하는 SQL 스크립트를 만들어 줘.
  점검 항목:
  
  [1. 인스턴스 상태]
  - DB 가동 시간 (uptime)
  - 인스턴스 상태 (open/mount/started)
  
  [2. 저장 공간]
  - 테이블스페이스별 사용률 (90% 이상은 경고)
  - 데이터파일 자동 확장 한계 도달 여부
  - ASM 디스크 그룹 사용률 (있는 경우)
  
  [3. 백업 상태]
  - 마지막 RMAN 백업 성공 시각
  - 24시간 이내 백업이 없으면 경고
  
  [4. 작업 상태]
  - DBMS_SCHEDULER 작업 중 BROKEN 상태인 것
  - 직전 24시간 내 실패한 작업
  
  [5. 성능 지표]
  - 직전 1시간 평균 대기 이벤트 TOP 5
  - Buffer Cache Hit Ratio
  - 활성 세션 수
  
  [6. 알람]
  - 직전 24시간 내 alert 로그의 ORA- 에러
  
  결과는 마크다운 형식으로 정리하고, 
  /home/oracle/reports/daily_YYYYMMDD.md 파일에 저장.
  매일 아침 8시에 자동 실행되도록 cron 등록까지.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 한 번의 요청으로 완성된 점검 스크립트와 자동화 설정이 나옵니다. 매일 30분 걸리던 작업이 출근하면 메일함에 보고서가 와 있는 상태가 됩니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;DBA 업무 도입 시 추가 팁&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 운영 DB에 직접 접속 금지 패턴&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CLAUDE.md에 다음을 명시하세요.&lt;/p&gt;
&lt;pre class=&quot;markdown&quot;&gt;&lt;code&gt;# 작업 환경 분리
- Claude Code 작업: 개발 DB(devdb)만 직접 접속 허용
- 운영 DB(proddb)의 변경 작업은 다음 절차 필수:
  1. 개발 DB에서 검증
  2. 변경 SQL과 ROLLBACK SQL 함께 작성
  3. DBA 매니저 리뷰
  4. 운영 적용은 사람이 직접
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 하면 Claude가 운영 DB에 직접 변경을 시도하지 않습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. SQL 라이브러리화&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자주 쓰는 점검 쿼리, 트러블슈팅 쿼리를 한 폴더에 모으고 git으로 관리하세요. Claude가 다음에 비슷한 작업을 할 때 이 라이브러리를 참고합니다.&lt;/p&gt;
&lt;pre class=&quot;stylus&quot;&gt;&lt;code&gt;~/dba-toolkit/
├── monitoring/
│   ├── tablespace_check.sql
│   ├── session_wait_top.sql
│   └── lock_check.sql
├── tuning/
│   ├── slow_query_finder.sql
│   └── index_usage_analysis.sql
└── CLAUDE.md  &amp;larr; 폴더의 사용 안내
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. 실행 계획은 항상 확인&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude가 만든 쿼리가 빠르게 동작할 거라는 보장은 없습니다. &lt;b&gt;운영 환경에 배포하기 전 EXPLAIN PLAN 확인은 필수&lt;/b&gt;입니다.&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;EXPLAIN PLAN FOR
[Claude가 만든 쿼리];

SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4. 권한 최소화 원칙&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude Code가 접속하는 DB 계정은 작업에 필요한 최소 권한만 부여하세요. SELECT만 필요한 작업은 SELECT 권한만, 등 분리합니다. 만일의 사고를 줄입니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;시리즈 마무리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3편에 걸쳐 DBA와 서버 관리자 관점에서 Claude Code 활용법을 정리했습니다. 핵심을 요약하면:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;1편&lt;/b&gt;: Claude Code는 운영자에게도 강력한 도구다. 코딩이 아니라 텍스트 기반 업무 전반의 효율을 높인다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;2편&lt;/b&gt;: 셸 스크립트와 운영 자동화에서 Claude Code는 검색-분석-스크립트 작성-문서화 사이클을 한 곳에서 끝낸다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;3편 (이 글)&lt;/b&gt;: DBA 업무에서는 SQL 작성, 튜닝, 트러블슈팅, 점검 자동화에 활용해 매일 1~2시간을 절약할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;도입할 때 가장 중요한 건 &lt;b&gt;점진적으로&lt;/b&gt;, &lt;b&gt;읽기 작업부터&lt;/b&gt;, &lt;b&gt;운영 환경은 신중하게&lt;/b&gt; 입니다. Claude Code는 강력하지만 도구일 뿐이고, 최종 책임은 운영자에게 있습니다. 검토 없이 그대로 실행하는 일은 절대 피하세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 시리즈를 보고 도입을 시도하셨거나, 더 좋은 활용 패턴을 발견하셨다면 댓글로 공유해 주세요. 여러 운영자의 경험이 모이면 더 풍부한 활용 가이드가 됩니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;시리즈 안내&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://www.whodo.net/entry/Claude-Code-%ED%99%9C%EC%9A%A9-1%ED%8E%B8-DBA%EC%99%80-%EC%84%9C%EB%B2%84-%EA%B4%80%EB%A6%AC%EC%9E%90%EA%B0%80-Claude-Code%EB%A5%BC-%EC%8D%A8%EC%95%BC-%ED%95%98%EB%8A%94-%EC%9D%B4%EC%9C%A0-%EC%84%A4%EC%B9%98%EB%B6%80%ED%84%B0-%EC%8B%A4%EC%A0%84-5%EA%B0%80%EC%A7%80-%ED%99%9C%EC%9A%A9%EA%B9%8C%EC%A7%80&quot;&gt;1편: DBA와 서버 관리자가 Claude Code를 써야 하는 이유 - 설치부터 실전 5가지 활용까지&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.whodo.net/entry/Claude-Code-%ED%99%9C%EC%9A%A9-2%ED%8E%B8-%EC%85%B8-%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EC%99%80-%EC%9A%B4%EC%98%81-%EC%9E%90%EB%8F%99%ED%99%94%EC%97%90-Claude-Code-%ED%99%9C%EC%9A%A9%ED%95%98%EA%B8%B0-%EC%8B%A4%EC%A0%84-%EC%82%AC%EB%A1%80-5%EA%B0%80%EC%A7%80&quot;&gt;2편: 셸 스크립트와 운영 자동화에 Claude Code 활용하기&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;3편 (이 글)&lt;/b&gt;: SQL과 Oracle DBA 업무에 Claude Code 활용하기&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>AI (Claude 활용)/Claude Code 시리즈</category>
      <category>AI 운영 자동화</category>
      <category>Claude Code DBMS_SCHEDULER</category>
      <category>Claude Code ORA 에러</category>
      <category>Claude Code SQL</category>
      <category>Claude Code 실행계획</category>
      <category>Claude Code 오라클</category>
      <category>Claude Code 활용</category>
      <category>DBA AI 도구</category>
      <category>DBA실무</category>
      <category>소니스토리</category>
      <author>isony</author>
      <guid isPermaLink="true">https://isony.tistory.com/327</guid>
      <comments>https://isony.tistory.com/entry/Claude-Code-%ED%99%9C%EC%9A%A9-3%ED%8E%B8-SQL%EA%B3%BC-Oracle-DBA-%EC%97%85%EB%AC%B4%EC%97%90-Claude-Code-%ED%99%9C%EC%9A%A9%ED%95%98%EA%B8%B0-%ED%8A%9C%EB%8B%9D%EB%B6%80%ED%84%B0-%ED%8A%B8%EB%9F%AC%EB%B8%94%EC%8A%88%ED%8C%85%EA%B9%8C%EC%A7%80#entry327comment</comments>
      <pubDate>Thu, 4 Jun 2026 08:11:13 +0900</pubDate>
    </item>
    <item>
      <title>[Claude Code 활용 2편] 셸 스크립트와 운영 자동화에 Claude Code 활용하기 (실전 사례 5가지)</title>
      <link>https://isony.tistory.com/entry/Claude-Code-%ED%99%9C%EC%9A%A9-2%ED%8E%B8-%EC%85%B8-%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EC%99%80-%EC%9A%B4%EC%98%81-%EC%9E%90%EB%8F%99%ED%99%94%EC%97%90-Claude-Code-%ED%99%9C%EC%9A%A9%ED%95%98%EA%B8%B0-%EC%8B%A4%EC%A0%84-%EC%82%AC%EB%A1%80-5%EA%B0%80%EC%A7%80</link>
      <description>&lt;h1&gt;[Claude Code 활용 2편] 셸 스크립트와 운영 자동화에 Claude Code 활용하기 (실전 사례 5가지)&lt;/h1&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;테스트 환경&lt;/b&gt;: Oracle Linux 8 / RHEL 8 / Ubuntu 22.04, Claude Code v2.x&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.whodo.net/entry/Claude-Code-%ED%99%9C%EC%9A%A9-1%ED%8E%B8-DBA%EC%99%80-%EC%84%9C%EB%B2%84-%EA%B4%80%EB%A6%AC%EC%9E%90%EA%B0%80-Claude-Code%EB%A5%BC-%EC%8D%A8%EC%95%BC-%ED%95%98%EB%8A%94-%EC%9D%B4%EC%9C%A0-%EC%84%A4%EC%B9%98%EB%B6%80%ED%84%B0-%EC%8B%A4%EC%A0%84-5%EA%B0%80%EC%A7%80-%ED%99%9C%EC%9A%A9%EA%B9%8C%EC%A7%80&quot;&gt;이전 1편&lt;/a&gt;에서 Claude Code 설치와 기본 활용을 다뤘다면, 이번 2편은 &lt;b&gt;서버 관리자가 매일 마주치는 작업을 Claude Code로 자동화하는 실전 사례&lt;/b&gt;를 정리했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;운영 환경에서 가장 시간을 많이 잡아먹는 일이 셸 스크립트 작성, 로그 분석, 장애 진단입니다. 이 작업들이 Claude Code의 가장 큰 강점이 발휘되는 영역입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 글에서는 다음 5가지 사례를 다룹니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;정기 백업 스크립트 자동 생성&lt;/li&gt;
&lt;li&gt;디스크 용량 모니터링 + 알림 스크립트&lt;/li&gt;
&lt;li&gt;로그 파일 분석과 패턴 추출&lt;/li&gt;
&lt;li&gt;cron 작업 일괄 점검&lt;/li&gt;
&lt;li&gt;장애 진단 스크립트 (서버가 느려졌을 때)&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모든 예제는 &lt;b&gt;그대로 복사해서 활용 가능한 프롬프트&lt;/b&gt;로 제공합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;시작 전 - CLAUDE.md 만들기 (★ 효율 2배)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;본격 활용 전에 한 가지 세팅을 하면 작업 효율이 크게 올라갑니다. &lt;b&gt;CLAUDE.md&lt;/b&gt; 파일을 프로젝트 폴더에 두면 Claude가 자동으로 읽어서 매번 환경 설명을 안 해도 됩니다.&lt;/p&gt;
&lt;pre class=&quot;dos&quot;&gt;&lt;code&gt;cd ~/work/ops
vi CLAUDE.md
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음과 같이 작성합니다.&lt;/p&gt;
&lt;pre class=&quot;markdown&quot;&gt;&lt;code&gt;# 환경 정보
- OS: Oracle Linux 8.8
- 셸: bash
- DB: Oracle 19c
- 백업 위치: /backup
- 로그 위치: /var/log, /u01/app/oracle/diag

# 작업 규칙
- 모든 스크립트는 #!/bin/bash로 시작
- 변수는 대문자, 함수는 소문자
- 실패 시 exit 1
- 모든 작업은 /var/log/ops.log에 timestamp와 함께 기록
- 백업 파일명은 yyyymmdd_HHMMSS 형식

# 보안
- 비밀번호는 파일에 직접 쓰지 말고 Oracle Wallet 사용
- 운영 DB(prod_db1)에는 직접 접속 금지, 점프 서버 경유
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 파일이 있으면 &quot;스크립트 짜 줘&quot;라고만 해도 위 규칙에 맞춰 결과가 나옵니다. 운영 표준화에도 큰 도움이 됩니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;사례 1: 정기 백업 스크립트 자동 생성&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 일상적인 작업입니다. 백업 스크립트는 매번 비슷한 구조인데도 매번 새로 짜기는 귀찮습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;프롬프트&lt;/h3&gt;
&lt;pre class=&quot;markdown&quot;&gt;&lt;code&gt;&amp;gt; 오라클 DB의 datapump 백업 스크립트를 만들어 줘.
  - 매일 새벽 2시 실행
  - 백업 대상: PROD_DB 스키마
  - 저장 경로: /backup/dpdump
  - 파일명: prod_db_YYYYMMDD_HHMMSS.dmp
  - 7일 이전 파일은 자동 삭제
  - 압축 옵션 사용
  - 실행 로그는 /var/log/dpbackup.log에 기록
  - 실패 시 exit code와 함께 종료
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Claude가 만들어 주는 결과 (예시)&lt;/h3&gt;
&lt;pre class=&quot;bash&quot;&gt;&lt;code&gt;#!/bin/bash
#
# datapump 백업 스크립트
# 대상: PROD_DB 스키마 / 보관 7일
#

# 환경 변수
export ORACLE_HOME=/u01/app/oracle/product/19c/dbhome_1
export ORACLE_SID=PRODDB
export PATH=$ORACLE_HOME/bin:$PATH

# 백업 설정
BACKUP_DIR=&quot;/backup/dpdump&quot;
LOG_FILE=&quot;/var/log/dpbackup.log&quot;
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
DUMP_FILE=&quot;prod_db_${TIMESTAMP}.dmp&quot;
SCHEMA=&quot;PROD_DB&quot;

log() {
    echo &quot;[$(date '+%Y-%m-%d %H:%M:%S')] $1&quot; &amp;gt;&amp;gt; &quot;$LOG_FILE&quot;
}

log &quot;백업 시작: ${DUMP_FILE}&quot;

# datapump 실행
expdp \&quot;/ as sysdba\&quot; \
    schemas=${SCHEMA} \
    directory=DATA_PUMP_DIR \
    dumpfile=${DUMP_FILE} \
    logfile=expdp_${TIMESTAMP}.log \
    compression=ALL &amp;gt;&amp;gt; &quot;$LOG_FILE&quot; 2&amp;gt;&amp;amp;1

if [ $? -ne 0 ]; then
    log &quot;백업 실패 - exit code 1&quot;
    exit 1
fi

# 7일 이전 파일 정리
find &quot;$BACKUP_DIR&quot; -name &quot;prod_db_*.dmp&quot; -type f -mtime +7 -delete

log &quot;백업 완료: ${DUMP_FILE}&quot;
exit 0
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기에 &quot;cron에 등록까지 해 줘&quot;를 이어서 요청하면 crontab -e 라인까지 만들어 줍니다.&lt;/p&gt;
&lt;pre class=&quot;basic&quot;&gt;&lt;code&gt;0 2 * * * /home/oracle/scripts/dpbackup.sh &amp;gt;/dev/null 2&amp;gt;&amp;amp;1
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;효과&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존: 30분~1시간 (검색 + 변형 + 테스트) &amp;rarr; Claude 활용: 5분.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;사례 2: 디스크 용량 모니터링 + 알림&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;운영 환경에서 가장 자주 발생하는 장애 중 하나가 디스크 풀입니다. 미리 막는 스크립트가 있으면 좋은데, 처음부터 짜기는 귀찮습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;프롬프트&lt;/h3&gt;
&lt;pre class=&quot;markdown&quot;&gt;&lt;code&gt;&amp;gt; 다음 조건으로 디스크 모니터링 셸 스크립트를 작성해 줘.
  - df로 모든 마운트 포인트 사용률 확인
  - 80% 이상이면 경고, 90% 이상이면 위험으로 분류
  - 위험 등급 발생 시 sendmail로 alert@company.com에 메일 발송
  - 메일 본문에 어떤 마운트가 몇 % 차 있는지, 큰 폴더 TOP 5도 포함
  - 5분마다 실행 가능한 구조로 (cron 등록 가정)
  - 직전 알림 후 1시간 내에는 같은 마운트에 대한 중복 알림 방지
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;핵심은 마지막 줄, &lt;b&gt;&quot;중복 알림 방지&quot;&lt;/b&gt; 입니다. 단순 모니터링 스크립트는 디스크가 풀이면 5분마다 메일이 와서 운영자가 더 짜증이 납니다. 이런 디테일을 한 번에 요구할 수 있는 게 Claude Code의 강점입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude가 만들어 주는 스크립트에는 &lt;b&gt;상태 파일(/var/run/disk_monitor.state)&lt;/b&gt; 을 활용해서 마지막 알림 시각을 저장하고 비교하는 로직까지 들어갑니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;추가 활용&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 스크립트를 만들고 나서 다음 명령을 이어서 줘 보세요.&lt;/p&gt;
&lt;pre class=&quot;erlang&quot;&gt;&lt;code&gt;&amp;gt; 이 스크립트를 운영팀에 인수인계할 수 있도록 README.md를 만들어 줘.
  설치, 실행, 알림 메일 예시, 트러블슈팅 항목까지 포함해서.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문서화까지 한 번에 끝납니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;사례 3: 로그 파일 분석과 패턴 추출&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;운영 중에 가장 답답한 순간이 &lt;b&gt;&quot;수백 MB짜리 로그에서 특정 패턴 찾기&quot;&lt;/b&gt; 입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;프롬프트 (장애 직후)&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;&amp;gt; /var/log/messages 최근 24시간 분량에서 다음을 분석해 줘.
  1. OOM Killer 발생 여부와 발생 시각 / 죽은 프로세스
  2. systemd 서비스 실패 (Failed to start) 목록
  3. 디스크 I/O 에러 (sd*, error 패턴)
  4. 시간대별 에러 발생 빈도 그래프 (텍스트로)
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude가 직접 로그 파일을 읽고 grep / awk / 정렬을 조합해서 결과를 보여줍니다. 평소라면 30분 걸리는 분석이 1분 안에 끝납니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;더 강력한 활용 - 알 수 없는 에러 분석&lt;/h3&gt;
&lt;pre class=&quot;crystal&quot;&gt;&lt;code&gt;&amp;gt; /u01/app/oracle/diag/rdbms/proddb/PRODDB/trace/alert_PRODDB.log 
  파일 마지막 100줄을 보고, 이상 징후가 있는지 분석해 줘.
  ORA- 에러가 있다면 각각의 원인과 해결 방향을 정리해 줘.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오라클 alert 로그에서 ORA-XXXXX 에러를 찾아 각각의 의미와 대응 방안까지 요약해 줍니다. 트러블슈팅 시간이 크게 줄어듭니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;사례 4: cron 작업 일괄 점검&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서버를 인수인계 받았거나 오래된 서버를 점검할 때 가장 먼저 해야 할 일 중 하나입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;프롬프트&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;&amp;gt; 이 서버의 모든 사용자의 crontab을 수집해서 다음을 분석해 줘.
  1. 어떤 스크립트들이 등록되어 있는가
  2. 실행 주기 (매시간/매일/매주)
  3. 스크립트 파일이 실제로 존재하는가
  4. 최근 7일 내에 정상 실행되었는가 (로그 기준)
  5. 중복되거나 충돌 가능성이 있는 작업이 있는가
  결과를 마크다운 표로 정리해 줘.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude가 for user in $(cut -d: -f1 /etc/passwd); do crontab -u $user -l; done 같은 명령을 제안하고 실행한 뒤, 결과를 분석해서 표로 정리해 줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;운영 환경 인수인계, 서버 정리, 컴플라이언스 점검 등 다양한 상황에서 활용 가능합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;사례 5: 장애 진단 스크립트 (서버가 느려졌을 때) ★ 가장 강력한 활용&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;장애 대응 중에 가장 중요한 건 속도입니다. &quot;서버 느려요&quot;라는 연락을 받았을 때, 일반적인 점검 순서를 모두 도는 데 10분 이상 걸립니다. 이걸 한 번에 자동화할 수 있습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;프롬프트&lt;/h3&gt;
&lt;pre class=&quot;haml&quot;&gt;&lt;code&gt;&amp;gt; 서버가 느려졌을 때 5분 안에 원인을 찾기 위한 진단 스크립트를 만들어 줘.
  다음 항목을 자동으로 수집해서 보고서 형태로 출력:
  
  [시스템]
  - load average (uptime)
  - CPU 사용률 (top 1회 / mpstat)
  - 메모리 사용률, swap 사용량
  - 디스크 IO 부하 (iostat 1회 5초 평균)
  - 네트워크 연결 상태 (ss -s)
  
  [프로세스]
  - CPU 점유 TOP 10
  - 메모리 점유 TOP 10
  - 좀비 프로세스 존재 여부
  
  [DB (Oracle)]
  - 활성 세션 수 (v$session 카운트, sysdba 권한 필요)
  - 대기 이벤트 TOP 5 (v$session_wait)
  - 락 발생 여부
  
  [로그]
  - /var/log/messages 마지막 50줄에서 에러 패턴
  - alert 로그 최근 5분 이내 ORA- 발생 여부
  
  결과는 /tmp/diag_YYYYMMDD_HHMMSS.txt에 저장하고
  요약은 화면에 출력.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 한 번의 프롬프트로 평소 10분 걸리던 1차 진단을 30초로 단축할 수 있는 진단 스크립트가 만들어집니다. 한 번 만들어 두고 운영 표준 도구로 등록해 두면 매번 활용 가능합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;운영 환경 도입 시 추가 팁&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 위험한 명령 자동 차단&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CLAUDE.md에 다음 규칙을 명시하면 안전성이 더 올라갑니다.&lt;/p&gt;
&lt;pre class=&quot;markdown&quot;&gt;&lt;code&gt;# 절대 금지 명령
- rm -rf /*
- DROP TABLE / DROP USER (단순 SQL 안내는 가능)
- shutdown / reboot
- 운영 DB의 ALTER SYSTEM
- iptables -F (방화벽 전체 삭제)

이 패턴을 포함한 명령은 절대 실행 제안하지 말 것.
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. 실행 권한 분리&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude Code를 실행하는 OS 계정과 운영 작업을 실행하는 계정을 분리하세요. Claude Code는 일반 사용자 계정으로 띄우고, 실제 운영 작업은 sudo를 통해 명시적으로 승인하는 패턴을 권장합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. 결과물은 git으로 관리&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude가 만들어 준 스크립트를 그냥 쓰지 말고 git 저장소에 commit하세요. 운영 표준화에도 도움이 되고, 나중에 같은 패턴을 다시 활용할 때도 편리합니다.&lt;/p&gt;
&lt;pre class=&quot;dockerfile&quot;&gt;&lt;code&gt;git init
git add scripts/
git commit -m &quot;백업 스크립트 v1 - Claude Code 작성&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4. 점진적 자동화&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음부터 모든 작업을 자동화하지 마세요. 다음 순서를 권장합니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;검색&amp;middot;문서화 작업부터&lt;/b&gt; (가장 안전, 가장 큰 효과)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;개발/테스트 환경 스크립트 작성&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;운영 환경의 읽기 전용 모니터링 스크립트&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;운영 환경의 백업/정리 작업&lt;/b&gt; (단방향 작업)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;운영 환경의 변경 작업&lt;/b&gt; (마지막 단계, 반드시 리뷰)&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;마무리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude Code는 단순히 &quot;코드를 빠르게 짜주는 도구&quot;가 아니라 &lt;b&gt;운영자의 인지 부하를 크게 낮춰주는 도구&lt;/b&gt;입니다. 검색-분석-스크립트 작성-문서화의 사이클이 한 곳에서 끝나면서 실제 업무에 들이는 시간이 1/3 이하로 줄어듭니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 3편에서는 &lt;b&gt;SQL 작성&amp;middot;튜닝과 오라클 DBA 업무에 Claude Code를 활용하는 방법&lt;/b&gt;을 다룹니다. DBMS_SCHEDULER 작업 등록, SQL 튜닝, ORA 에러 분석 등 DBA 업무에 특화된 사례를 정리할 예정입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;본인이 자동화한 운영 작업이나 더 좋은 패턴이 있다면 댓글로 공유해 주세요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;시리즈 안내&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://www.whodo.net/entry/Claude-Code-%ED%99%9C%EC%9A%A9-1%ED%8E%B8-DBA%EC%99%80-%EC%84%9C%EB%B2%84-%EA%B4%80%EB%A6%AC%EC%9E%90%EA%B0%80-Claude-Code%EB%A5%BC-%EC%8D%A8%EC%95%BC-%ED%95%98%EB%8A%94-%EC%9D%B4%EC%9C%A0-%EC%84%A4%EC%B9%98%EB%B6%80%ED%84%B0-%EC%8B%A4%EC%A0%84-5%EA%B0%80%EC%A7%80-%ED%99%9C%EC%9A%A9%EA%B9%8C%EC%A7%80&quot;&gt;1편: DBA와 서버 관리자가 Claude Code를 써야 하는 이유 - 설치부터 실전 5가지 활용까지&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;2편 (이 글)&lt;/b&gt;: 셸 스크립트와 운영 자동화에 Claude Code 활용하기&lt;/li&gt;
&lt;li&gt;&lt;b&gt;3편&lt;/b&gt;: SQL과 DBA 업무에 Claude Code 활용하기 (작성 예정)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>AI (Claude 활용)/Claude Code 시리즈</category>
      <category>AI 운영 자동화</category>
      <category>claude code</category>
      <category>Claude Code 리눅스</category>
      <category>Claude Code 쉘 스크립트</category>
      <category>Claude Code 운영</category>
      <category>Claude Code 자동화</category>
      <category>DBA 실무</category>
      <category>소니스토리</category>
      <category>오라클</category>
      <author>isony</author>
      <guid isPermaLink="true">https://isony.tistory.com/326</guid>
      <comments>https://isony.tistory.com/entry/Claude-Code-%ED%99%9C%EC%9A%A9-2%ED%8E%B8-%EC%85%B8-%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EC%99%80-%EC%9A%B4%EC%98%81-%EC%9E%90%EB%8F%99%ED%99%94%EC%97%90-Claude-Code-%ED%99%9C%EC%9A%A9%ED%95%98%EA%B8%B0-%EC%8B%A4%EC%A0%84-%EC%82%AC%EB%A1%80-5%EA%B0%80%EC%A7%80#entry326comment</comments>
      <pubDate>Wed, 3 Jun 2026 07:12:35 +0900</pubDate>
    </item>
    <item>
      <title>[Claude Code 활용 1편] DBA와 서버 관리자가 Claude Code를 써야 하는 이유 - 설치부터 실전 5가지 활용까지</title>
      <link>https://isony.tistory.com/entry/Claude-Code-%ED%99%9C%EC%9A%A9-1%ED%8E%B8-DBA%EC%99%80-%EC%84%9C%EB%B2%84-%EA%B4%80%EB%A6%AC%EC%9E%90%EA%B0%80-Claude-Code%EB%A5%BC-%EC%8D%A8%EC%95%BC-%ED%95%98%EB%8A%94-%EC%9D%B4%EC%9C%A0-%EC%84%A4%EC%B9%98%EB%B6%80%ED%84%B0-%EC%8B%A4%EC%A0%84-5%EA%B0%80%EC%A7%80-%ED%99%9C%EC%9A%A9%EA%B9%8C%EC%A7%80</link>
      <description>&lt;h1&gt;[Claude Code 활용 1편] DBA와 서버 관리자가 Claude Code를 써야 하는 이유 - 설치부터 실전 5가지 활용까지&lt;/h1&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;테스트 환경&lt;/b&gt;: macOS / Ubuntu 22.04 / Windows 11(WSL2), Node.js 20, Claude Code v2.x&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발자 사이에서 Claude Code 이야기가 많이 들립니다. 그런데 &lt;b&gt;&quot;나는 코드 짜는 사람도 아닌데 이게 나에게 도움이 될까?&quot;&lt;/b&gt; 하는 분들도 계실 겁니다. 결론부터 말씀드리면, 운영 환경을 관리하는 DBA나 서버 관리자에게 Claude Code는 &lt;b&gt;셸 스크립트, SQL 쿼리, 설정 파일, 로그 분석 도구가 일상인 업무에서 즉시 효과를 보는 도구&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 시리즈는 총 3편으로 구성됩니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;1편 (이 글)&lt;/b&gt;: Claude Code가 무엇이고, 어떻게 설치하며, 운영자 관점에서 어떤 활용이 가능한지&lt;/li&gt;
&lt;li&gt;&lt;b&gt;2편&lt;/b&gt;: 셸 스크립트와 운영 자동화에 활용하기&lt;/li&gt;
&lt;li&gt;&lt;b&gt;3편&lt;/b&gt;: SQL과 DBA 업무에 활용하기&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 1편은 입문 가이드입니다. &lt;b&gt;개발 경험이 적어도 따라할 수 있도록&lt;/b&gt; 구성했고, &quot;이런 작업에 쓸 수 있구나&quot; 감을 잡는 데 초점을 맞췄습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Claude Code란 무엇인가&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude Code는 &lt;b&gt;Anthropic이 만든 터미널 기반 AI 코딩 어시스턴트&lt;/b&gt;입니다. ChatGPT처럼 웹브라우저에서 쓰는 게 아니라, &lt;b&gt;본인 컴퓨터의 터미널(명령 프롬프트)에서 자연어로 대화하면서 작업&lt;/b&gt;합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존 AI 도구와 가장 다른 점은 세 가지입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;항목 일반 AI 챗봇 Claude Code&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;작업 환경&lt;/td&gt;
&lt;td&gt;웹 브라우저 (복붙 필수)&lt;/td&gt;
&lt;td&gt;터미널 (파일에 직접 작업)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;파일 접근&lt;/td&gt;
&lt;td&gt;❌ 불가&lt;/td&gt;
&lt;td&gt;✅ 직접 읽고 쓰기&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;명령 실행&lt;/td&gt;
&lt;td&gt;❌ 불가&lt;/td&gt;
&lt;td&gt;✅ 셸 명령 실행 가능&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;컨텍스트&lt;/td&gt;
&lt;td&gt;대화 한 번으로 끝&lt;/td&gt;
&lt;td&gt;프로젝트 폴더 전체 인식&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;운영자 입장에서 가장 큰 차이는 &lt;b&gt;&quot;파일을 직접 읽고 쓸 수 있다&quot;&lt;/b&gt; 입니다. 셸 스크립트, SQL 파일, 로그 파일을 일일이 복사해서 챗봇에 붙여 넣을 필요 없이, &quot;이 파일 분석해 줘&quot; 한 마디면 됩니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;설치 (Linux / macOS / Windows WSL2)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설치는 약 5분이면 끝납니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1단계: Node.js 설치 확인&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude Code는 Node.js 18 이상이 필요합니다.&lt;/p&gt;
&lt;pre class=&quot;crmsh&quot;&gt;&lt;code&gt;node --version
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;v18.x.x 이상이 나오면 OK. 없거나 낮은 버전이라면:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Ubuntu/CentOS&lt;/b&gt;: sudo apt install nodejs npm 또는 &lt;a href=&quot;https://github.com/nodesource/distributions&quot;&gt;NodeSource 저장소&lt;/a&gt; 활용&lt;/li&gt;
&lt;li&gt;&lt;b&gt;macOS&lt;/b&gt;: brew install node&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Windows&lt;/b&gt;: WSL2 환경에 Ubuntu를 설치하고 위 명령 실행 권장&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2단계: Claude Code 설치&lt;/h3&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;npm install -g @anthropic-ai/claude-code
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전역 설치(-g)라 어디서든 claude 명령으로 호출됩니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3단계: 첫 실행 및 로그인&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;작업할 폴더로 이동한 뒤 명령어를 실행합니다.&lt;/p&gt;
&lt;pre class=&quot;gradle&quot;&gt;&lt;code&gt;cd ~/work/myproject
claude
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫 실행 시 인증 절차가 진행됩니다. 브라우저가 열리거나 코드를 입력하라는 안내가 나오는데, 가이드대로 따라가면 됩니다. &lt;b&gt;Claude.ai 유료 플랜(Pro/Max) 계정으로 로그인하거나 API 키를 입력&lt;/b&gt;하면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요금제별로 사용량 제한이 다르므로 본인의 상황에 맞게 선택하세요. 자세한 내용은 &lt;a href=&quot;https://docs.claude.com/en/docs/claude-code/overview&quot;&gt;Anthropic 공식 문서&lt;/a&gt;에서 확인 가능합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4단계: 첫 명령&lt;/h3&gt;
&lt;pre class=&quot;markdown&quot;&gt;&lt;code&gt;&amp;gt; 이 폴더에 있는 파일들을 보고 어떤 프로젝트인지 설명해 줘
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자연어로 입력하면 Claude가 폴더를 분석하고 응답합니다. 영어로 쓸 필요 없고, &lt;b&gt;한국어 그대로 입력해도 정상 동작&lt;/b&gt;합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;운영자 관점에서 Claude Code의 진짜 장점&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다른 블로그들은 대부분 &quot;코드 작성&quot;에 초점을 맞춥니다. 하지만 DBA나 서버 관리자 관점에서는 다른 강점들이 더 큽니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;장점 1: 검색-요약-적용 사이클이 한 곳에서 끝남&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;장애가 터졌을 때 평소 워크플로우:&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;에러 메시지 구글 검색&lt;/li&gt;
&lt;li&gt;스택오버플로우 / 한국어 블로그 5~10개 클릭&lt;/li&gt;
&lt;li&gt;정보 취합&lt;/li&gt;
&lt;li&gt;본인 환경에 맞게 변형&lt;/li&gt;
&lt;li&gt;적용&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude Code 워크플로우:&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;claude 실행 후 &quot;이 에러 원인이 뭐고 어떻게 해결해?&quot; 입력&lt;/li&gt;
&lt;li&gt;분석 결과 + 본인 환경에 맞춘 명령어를 바로 제시&lt;/li&gt;
&lt;li&gt;승인하면 즉시 적용&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히 &lt;b&gt;본인 서버의 설정 파일, 로그, 환경 정보를 직접 보고 답을 주기 때문에&lt;/b&gt; 검색 결과를 본인 환경에 끼워 맞추는 수고가 없어집니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;장점 2: 셸 명령 실행 권한 (수동 승인 방식)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;디스크 용량 확인하고 가장 큰 폴더 찾아 줘&quot;라고 하면 Claude가 df -h, du -sh /* 같은 명령을 제안하고 &lt;b&gt;사용자가 승인하면 실행&lt;/b&gt;합니다. 명령 실행 전에 항상 확인을 받는 구조라 운영 환경에서도 안전합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;장점 3: 한 번의 컨텍스트로 여러 파일 다루기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;크론탭, 셸 스크립트, 로그 파일을 한꺼번에 보면서 &quot;이 크론에서 호출하는 스크립트가 왜 매일 새벽 3시에 에러가 나는지 진단해 줘&quot;가 가능합니다. 웹 챗봇에 일일이 붙여 넣는 것과 차원이 다릅니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;장점 4: 반복 작업의 자동화&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;매주 반복하는 점검 작업, 매일 돌리는 통계 스크립트 등을 한 번 만들어 두면 다음부터는 &quot;지난번 그 스크립트 좀 수정해 줘&quot; 한 마디면 됩니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;DBA&amp;middot;서버 관리자가 첫 주에 시도해볼 만한 5가지 활용&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설치 직후 바로 효과를 체감할 수 있는 케이스 5개입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;활용 1: 셸 스크립트 빠르게 만들기&lt;/h3&gt;
&lt;pre class=&quot;crystal&quot;&gt;&lt;code&gt;&amp;gt; /home/oracle/backup 디렉토리에서 7일 이상 된 .dmp 파일을 찾아 
  /backup/archive로 이동시키는 셸 스크립트를 작성해 줘.
  실행 결과는 /var/log/cleanup.log에 기록하고.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;응답으로 완성된 스크립트를 받고, &quot;이거 cron에 매일 새벽 3시 실행되도록 등록해 줘&quot;까지 이어갈 수 있습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;활용 2: 로그 파일 분석&lt;/h3&gt;
&lt;pre class=&quot;excel&quot;&gt;&lt;code&gt;&amp;gt; /var/log/messages 최근 1000줄에서 OOM Killer 발생 여부 확인하고, 
  발생했다면 어떤 프로세스가 죽었는지 정리해 줘.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;수백 MB짜리 로그를 grep으로 헤매는 대신, Claude가 패턴을 찾아주고 요약까지 합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;활용 3: 설정 파일 검토&lt;/h3&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;&amp;gt; 이 listener.ora 파일을 보고 설정상 문제가 있는지, 
  보안 관점에서 개선할 점이 있는지 알려 줘.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오라클 listener.ora, sqlnet.ora, init.ora 같은 설정 파일을 던져 주면 분석해 줍니다. 검토 기준을 알려주면 더 구체적인 피드백이 옵니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;활용 4: 명령어 / 문법 즉시 확인&lt;/h3&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;&amp;gt; RHEL 8에서 firewalld로 1521 포트만 특정 IP 대역(192.168.10.0/24)에 
  허용하는 명령어 알려 줘.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;검색 &amp;rarr; 블로그 5개 비교 &amp;rarr; 본인 환경 맞춤 변형의 과정이 한 번에 끝납니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;활용 5: 문서화 자동 생성&lt;/h3&gt;
&lt;pre class=&quot;armasm&quot;&gt;&lt;code&gt;&amp;gt; 이 backup.sh 스크립트의 동작을 운영팀에 인수인계할 수 있도록 
  마크다운 문서로 정리해 줘. 사전 조건, 실행 방법, 
  실패 시 대응까지 포함해서.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;운영 인수인계 문서는 만들기 귀찮은 작업 중 하나입니다. 스크립트를 보여주면 자동으로 정리된 문서를 만들어 줍니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;실무 도입 시 주의사항 4가지&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;운영 환경에 적용하기 전에 알아둬야 할 것들입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 운영 DB에 직접 명령 실행은 금물&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude Code가 똑똑하긴 하지만, &lt;b&gt;운영 환경의 실행 권한은 별도 계정 / 별도 터미널로 분리&lt;/b&gt;하세요. 개발 / 테스트 환경에서 충분히 검증한 후 운영에 적용하는 워크플로를 유지해야 합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. 민감 정보 노출 주의&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비밀번호, API 키, 개인정보가 들어 있는 파일을 통째로 분석시키면 외부 API로 전송됩니다. 작업 전에 마스킹하거나, 회사 보안 정책상 외부 AI 도구 사용이 제한된다면 사전에 확인하세요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. 권한 승인 패턴 익히기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude Code는 파일 변경이나 명령 실행 전에 항상 사용자 확인을 받습니다. &lt;b&gt;&quot;yes&quot;를 습관처럼 누르지 말고&lt;/b&gt;, 어떤 명령을 실행하려는지 한 번씩 확인하는 습관이 필요합니다. 특히 rm, chmod, truncate 같은 명령은 더 그렇습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4. 모델 선택 (비용 vs 성능)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;복잡한 작업은 상위 모델(Opus 계열), 간단한 작업은 하위 모델(Haiku, Sonnet)을 쓰면 비용을 절약할 수 있습니다. /model 명령으로 변경 가능합니다. 사용 가능한 모델은 시기별로 달라지니 공식 문서를 참고하세요.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;첫 주 학습 계획 - 운영자용&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설치 후 첫 일주일은 다음 순서로 익히는 것을 권장합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일차 학습 내용&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1일차&lt;/td&gt;
&lt;td&gt;설치 + 자연어 대화 익히기 (claude 명령으로 일상 질문)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2일차&lt;/td&gt;
&lt;td&gt;셸 스크립트 작성 시키기 (위 활용 1번)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3일차&lt;/td&gt;
&lt;td&gt;로그 파일 분석 (위 활용 2번)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4일차&lt;/td&gt;
&lt;td&gt;설정 파일 검토 (위 활용 3번)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5일차&lt;/td&gt;
&lt;td&gt;CLAUDE.md 파일 만들기 (프로젝트별 컨텍스트 설정)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6~7일차&lt;/td&gt;
&lt;td&gt;본인 실제 업무에 한 가지 적용해 보기&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;CLAUDE.md&lt;/b&gt; 는 프로젝트 폴더에 두면 Claude가 자동으로 읽는 메모입니다. &quot;이 폴더는 오라클 DB 운영 스크립트가 모여 있고, RHEL 8 환경입니다&quot; 같은 컨텍스트를 적어두면 매번 설명할 필요가 없어집니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;마무리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude Code는 코딩에 관심 없는 운영자에게도 강력한 도구입니다. &lt;b&gt;&quot;코드를 작성하는 도구&quot;가 아니라 &quot;텍스트 기반 업무를 자동화하는 도구&quot;&lt;/b&gt; 로 접근하면 활용 범위가 훨씬 넓어집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 2편에서는 본격적으로 &lt;b&gt;셸 스크립트 작성과 운영 자동화&lt;/b&gt; 사례를 다룹니다. 실제 운영 환경에서 자주 만나는 작업을 예제로 풀어 가겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;질문이나 본인 환경에서 시도해 본 경험이 있다면 댓글로 공유해 주세요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;시리즈 안내&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;1편 (이 글)&lt;/b&gt;: DBA와 서버 관리자가 Claude Code를 써야 하는 이유 - 설치부터 실전 5가지 활용까지&lt;/li&gt;
&lt;li&gt;&lt;b&gt;2편&lt;/b&gt;: 셸 스크립트와 운영 자동화에 Claude Code 활용하기 (작성 예정)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;3편&lt;/b&gt;: SQL과 DBA 업무에 Claude Code 활용하기 (작성 예정)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>AI (Claude 활용)/Claude Code 시리즈</category>
      <category>AI 코딩 도구</category>
      <category>ai 코딩 도구 비교</category>
      <category>Anthropic Claude</category>
      <category>Claude Code 사용법</category>
      <category>Claude Code 설치</category>
      <category>Claude Code 한국어</category>
      <category>DBA실무</category>
      <category>소니스토리</category>
      <category>오라클</category>
      <author>isony</author>
      <guid isPermaLink="true">https://isony.tistory.com/325</guid>
      <comments>https://isony.tistory.com/entry/Claude-Code-%ED%99%9C%EC%9A%A9-1%ED%8E%B8-DBA%EC%99%80-%EC%84%9C%EB%B2%84-%EA%B4%80%EB%A6%AC%EC%9E%90%EA%B0%80-Claude-Code%EB%A5%BC-%EC%8D%A8%EC%95%BC-%ED%95%98%EB%8A%94-%EC%9D%B4%EC%9C%A0-%EC%84%A4%EC%B9%98%EB%B6%80%ED%84%B0-%EC%8B%A4%EC%A0%84-5%EA%B0%80%EC%A7%80-%ED%99%9C%EC%9A%A9%EA%B9%8C%EC%A7%80#entry325comment</comments>
      <pubDate>Tue, 2 Jun 2026 13:03:46 +0900</pubDate>
    </item>
    <item>
      <title>[오라클 실무] DBMS_SCHEDULER로 프로시저를 6시간 단위 실행하기 - 동적 인자 전달 완벽 예제</title>
      <link>https://isony.tistory.com/entry/%EC%98%A4%EB%9D%BC%ED%81%B4-%EC%8B%A4%EB%AC%B4-DBMSSCHEDULER%EB%A1%9C-%ED%94%84%EB%A1%9C%EC%8B%9C%EC%A0%80%EB%A5%BC-6%EC%8B%9C%EA%B0%84-%EB%8B%A8%EC%9C%84-%EC%8B%A4%ED%96%89%ED%95%98%EA%B8%B0-%EB%8F%99%EC%A0%81-%EC%9D%B8%EC%9E%90-%EC%A0%84%EB%8B%AC-%EC%99%84%EB%B2%BD-%EC%98%88%EC%A0%9C</link>
      <description>&lt;h1&gt;[오라클 실무] DBMS_SCHEDULER로 프로시저를 6시간 단위 실행하기 - 동적 인자 전달 완벽 예제&lt;/h1&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;테스트 환경&lt;/b&gt;: Oracle 12c / 19c / 21c&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DBMS_SCHEDULER로 배치 작업을 등록할 때 가장 자주 막히는 부분이 &lt;b&gt;&quot;실행할 때마다 바뀌는 인자(예: 어제/오늘 날짜)를 어떻게 동적으로 전달하느냐&quot;&lt;/b&gt; 입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SET_JOB_ARGUMENT_VALUE로 인자를 박으면 정적 값이 고정되어 매일 같은 값으로 실행되고, 그렇다고 매번 작업을 다시 만들 수도 없습니다. 정답은 &lt;b&gt;PLSQL_BLOCK 타입으로 호출하면서 인자 평가를 작업 액션 안으로 넣는 것&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 글에서는 실제 운영 환경에서 자주 나오는 케이스 &amp;mdash; &lt;b&gt;&quot;PROC_TAX_PURCHASE_A10(어제, 오늘)을 매일 04시, 10시, 16시, 22시에 실행&quot;&lt;/b&gt; &amp;mdash; 를 예제로, 등록부터 검증, 운영까지 한 번에 정리했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;급하신 분은 &lt;u&gt;전체 코드 한 번에 보기&lt;/u&gt; 섹션부터 보세요.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;요구사항 정리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 만들 작업의 사양을 정리해 봅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;항목 내용&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;실행할 프로시저&lt;/td&gt;
&lt;td&gt;PROC_TAX_PURCHASE_A10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;인자 1&lt;/td&gt;
&lt;td&gt;어제 날짜 (YYYYMMDD 8자리 문자열)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;인자 2&lt;/td&gt;
&lt;td&gt;오늘 날짜 (YYYYMMDD 8자리 문자열)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;실행 주기&lt;/td&gt;
&lt;td&gt;매일 04시, 10시, 16시, 22시 (6시간 간격)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;인자 평가 시점&lt;/td&gt;
&lt;td&gt;&lt;b&gt;매 실행 시점&lt;/b&gt; (등록 시점 아님)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;핵심은 마지막 줄입니다. 작업을 한 번 등록하지만, 실행될 때마다 그 시점의 SYSDATE로 인자가 다시 계산되어야 합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;전체 코드 한 번에 보기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;복붙해서 바로 사용하실 수 있는 완성 코드입니다.&lt;/p&gt;
&lt;pre class=&quot;php&quot;&gt;&lt;code&gt;BEGIN
    DBMS_SCHEDULER.CREATE_JOB(
        job_name        =&amp;gt; 'JOB_TAX_PURCHASE_A10',
        job_type        =&amp;gt; 'PLSQL_BLOCK',
        job_action      =&amp;gt; q'[
            DECLARE
                v_yest  VARCHAR2(8) := TO_CHAR(SYSDATE - 1, 'YYYYMMDD');
                v_today VARCHAR2(8) := TO_CHAR(SYSDATE,     'YYYYMMDD');
            BEGIN
                PROC_TAX_PURCHASE_A10(v_yest, v_today);
            END;
        ]',
        start_date      =&amp;gt; SYSTIMESTAMP,
        repeat_interval =&amp;gt; 'FREQ=DAILY;BYHOUR=4,10,16,22;BYMINUTE=0;BYSECOND=0',
        enabled         =&amp;gt; TRUE,
        comments        =&amp;gt; '세금/구매 데이터 처리 - 매일 04, 10, 16, 22시 실행'
    );
END;
/
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드 하나만 실행하면 작업 등록이 끝납니다. 이제 각 부분을 자세히 보겠습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;코드 한 줄씩 해부하기&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1) job_name - 작업 이름&lt;/h3&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;job_name =&amp;gt; 'JOB_TAX_PURCHASE_A10'
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;작업 이름은 스키마 내에서 유일해야 합니다. 접두사 JOB_을 일관되게 붙이면 dba_scheduler_jobs 조회 시 한 번에 모아 볼 수 있어 운영에 유리합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2) job_type - 작업 유형&lt;/h3&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;job_type =&amp;gt; 'PLSQL_BLOCK'
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;STORED_PROCEDURE를 쓰면 SET_JOB_ARGUMENT_VALUE로 인자를 박아야 해서 &lt;b&gt;동적 인자 전달이 사실상 불가능&lt;/b&gt;합니다. 인자가 매번 달라져야 하는 경우 PLSQL_BLOCK이 답입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;유형 동적 인자 사용 시점&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;PLSQL_BLOCK&lt;/td&gt;
&lt;td&gt;✅ 가능&lt;/td&gt;
&lt;td&gt;인자가 매 실행마다 달라질 때 (이 경우)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;STORED_PROCEDURE&lt;/td&gt;
&lt;td&gt;❌ 정적만&lt;/td&gt;
&lt;td&gt;인자가 고정될 때&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;EXECUTABLE&lt;/td&gt;
&lt;td&gt;✅ 가능&lt;/td&gt;
&lt;td&gt;OS 셸 스크립트 실행&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3) job_action - 핵심 ★&lt;/h3&gt;
&lt;pre class=&quot;vbnet&quot;&gt;&lt;code&gt;job_action =&amp;gt; q'[
    DECLARE
        v_yest  VARCHAR2(8) := TO_CHAR(SYSDATE - 1, 'YYYYMMDD');
        v_today VARCHAR2(8) := TO_CHAR(SYSDATE,     'YYYYMMDD');
    BEGIN
        PROC_TAX_PURCHASE_A10(v_yest, v_today);
    END;
]'
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글에서 가장 중요한 부분입니다. 두 가지 디테일이 들어있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;디테일 1: q'[ ]' 인용 표기법 사용&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;job_action은 VARCHAR2 문자열입니다. 안에 작은따옴표가 들어가면 보통 두 번 써야 하는데(''YYYYMMDD''), 코드가 지저분해집니다. Oracle 10g부터 지원하는 &lt;b&gt;q-quoting&lt;/b&gt; 문법을 쓰면 작은따옴표를 그대로 쓸 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;ada&quot;&gt;&lt;code&gt;-- ❌ 일반 방식 (작은따옴표 두 번 - 가독성 떨어짐)
job_action =&amp;gt; 'BEGIN PROC_TAX_PURCHASE_A10(TO_CHAR(SYSDATE-1,''YYYYMMDD''), TO_CHAR(SYSDATE,''YYYYMMDD'')); END;'

-- ✅ q-quoting (작은따옴표 그대로 - 깔끔)
job_action =&amp;gt; q'[BEGIN PROC_TAX_PURCHASE_A10(TO_CHAR(SYSDATE-1,'YYYYMMDD'), TO_CHAR(SYSDATE,'YYYYMMDD')); END;]'
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;긴 PL/SQL 블록일수록 차이가 큽니다. 운영 코드에서는 q-quoting 사용을 강력히 권장합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;디테일 2: 인자를 변수에 먼저 담는 패턴&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;직접 호출도 가능합니다.&lt;/p&gt;
&lt;pre class=&quot;lisp&quot;&gt;&lt;code&gt;BEGIN
    PROC_TAX_PURCHASE_A10(
        TO_CHAR(SYSDATE-1, 'YYYYMMDD'),
        TO_CHAR(SYSDATE,   'YYYYMMDD')
    );
END;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 변수에 먼저 받아두는 패턴이 &lt;b&gt;두 가지 이유로 더 안전&lt;/b&gt;합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫째, &lt;b&gt;자정 경계 문제 방지&lt;/b&gt;. 두 SYSDATE 호출 사이에 자정이 지나면 어제와 오늘 값이 어긋날 수 있습니다. 새벽 04시 실행에서는 거의 발생하지 않지만, 변수에 한 번에 담아두면 인자 일관성이 보장됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;둘째, &lt;b&gt;로그 남기기 쉬움&lt;/b&gt;. 디버깅이 필요할 때 변수 값을 DBMS_OUTPUT.PUT_LINE이나 로그 테이블에 기록하기 편합니다.&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- 디버깅 가능한 확장 패턴
DECLARE
    v_yest  VARCHAR2(8) := TO_CHAR(SYSDATE - 1, 'YYYYMMDD');
    v_today VARCHAR2(8) := TO_CHAR(SYSDATE,     'YYYYMMDD');
BEGIN
    INSERT INTO batch_log VALUES (SYSDATE, 'A10 시작', v_yest, v_today);
    PROC_TAX_PURCHASE_A10(v_yest, v_today);
    INSERT INTO batch_log VALUES (SYSDATE, 'A10 종료', v_yest, v_today);
    COMMIT;
END;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4) repeat_interval - 6시간 간격 표현&lt;/h3&gt;
&lt;pre class=&quot;lsl&quot;&gt;&lt;code&gt;repeat_interval =&amp;gt; 'FREQ=DAILY;BYHOUR=4,10,16,22;BYMINUTE=0;BYSECOND=0'
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 표현식이 &quot;매일 04:00, 10:00, 16:00, 22:00 실행&quot;을 의미합니다. 각 절을 분해하면:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;절 의미&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;FREQ=DAILY&lt;/td&gt;
&lt;td&gt;일 단위 반복&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BYHOUR=4,10,16,22&lt;/td&gt;
&lt;td&gt;04시, 10시, 16시, 22시&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BYMINUTE=0&lt;/td&gt;
&lt;td&gt;0분 (정각)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BYSECOND=0&lt;/td&gt;
&lt;td&gt;0초&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;왜 FREQ=HOURLY;INTERVAL=6을 안 쓰는가?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;FREQ=HOURLY;INTERVAL=6도 6시간마다 실행되긴 하지만, 시작 시각이 start_date에 따라 결정되어 &quot;정확히 04/10/16/22시&quot;가 보장되지 않습니다. 예를 들어 11시에 등록하면 11시, 17시, 23시, 05시로 실행될 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;시각을 명시적으로 지정해야 한다면 반드시 BYHOUR를 쓰세요.&lt;/b&gt; 이게 운영자가 가장 자주 실수하는 부분입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;BYMINUTE=0;BYSECOND=0을 꼭 넣어야 하는 이유&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;생략하면 작업 등록 시각의 분/초가 매 실행에도 적용됩니다. 11:23:45에 등록했다면 04:23:45, 10:23:45 식으로 실행됩니다. 정각 실행이 필요하면 반드시 명시하세요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5) start_date - 시작 시각&lt;/h3&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;start_date =&amp;gt; SYSTIMESTAMP
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SYSTIMESTAMP로 지정하면 &quot;지금부터 활성&quot;이라는 뜻입니다. 다음 실행은 다음 BYHOUR 시각에 자동으로 잡힙니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;타임존 주의 (★ 19c 이상)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;19c부터 DBMS_SCHEDULER가 세션 타임존을 사용하면서 업그레이드 후 실행 시각이 어긋나는 사례가 있습니다. 운영 환경이라면 &lt;b&gt;명시적 타임존 지정이 안전&lt;/b&gt;합니다.&lt;/p&gt;
&lt;pre class=&quot;lisp&quot;&gt;&lt;code&gt;start_date =&amp;gt; TO_TIMESTAMP_TZ('2026-06-02 04:00:00 Asia/Seoul',
                              'YYYY-MM-DD HH24:MI:SS TZR')
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;6) enabled - 활성화 여부&lt;/h3&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;enabled =&amp;gt; TRUE
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DBMS_SCHEDULER의 기본값은 &lt;b&gt;FALSE(비활성)&lt;/b&gt; 입니다. 명시적으로 TRUE를 주지 않으면 작업은 등록되지만 &lt;b&gt;절대 실행되지 않습니다&lt;/b&gt;. 가장 흔한 함정 중 하나입니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;등록 직후 검증 - 3단계&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;운영 환경에 작업을 등록했다면 다음 3가지를 반드시 확인하세요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;단계 1: 작업이 정상 등록되었나&lt;/h3&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;SELECT job_name, state, enabled, 
       TO_CHAR(next_run_date, 'YYYY-MM-DD HH24:MI:SS') AS next_run,
       repeat_interval
FROM   user_scheduler_jobs
WHERE  job_name = 'JOB_TAX_PURCHASE_A10';
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;확인 포인트:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;state = SCHEDULED (정상)&lt;/li&gt;
&lt;li&gt;enabled = TRUE&lt;/li&gt;
&lt;li&gt;next_run = 가장 가까운 04/10/16/22시 중 하나&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;단계 2: 다음 10번의 실행 시각 미리보기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스케줄이 의도대로 잡혔는지 등록 전에 검증하는 가장 좋은 방법입니다.&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;DECLARE
    v_start   TIMESTAMP WITH TIME ZONE := SYSTIMESTAMP;
    v_next    TIMESTAMP WITH TIME ZONE;
BEGIN
    FOR i IN 1..10 LOOP
        DBMS_SCHEDULER.EVALUATE_CALENDAR_STRING(
            calendar_string   =&amp;gt; 'FREQ=DAILY;BYHOUR=4,10,16,22;BYMINUTE=0;BYSECOND=0',
            start_date        =&amp;gt; SYSTIMESTAMP,
            return_date_after =&amp;gt; v_start,
            next_run_date     =&amp;gt; v_next
        );
        DBMS_OUTPUT.PUT_LINE(i || '회차: ' || TO_CHAR(v_next, 'YYYY-MM-DD HH24:MI:SS TZR'));
        v_start := v_next;
    END LOOP;
END;
/
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;출력 예시:&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;1회차: 2026-06-01 22:00:00 ASIA/SEOUL
2회차: 2026-06-02 04:00:00 ASIA/SEOUL
3회차: 2026-06-02 10:00:00 ASIA/SEOUL
4회차: 2026-06-02 16:00:00 ASIA/SEOUL
...
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;이 검증을 본 등록 전에 미리 실행하면 사고를 95% 막을 수 있습니다.&lt;/b&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;단계 3: 수동으로 한 번 실행 테스트&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스케줄에 따른 첫 실행을 기다리지 말고, 즉시 한 번 돌려서 프로시저 자체에 문제가 없는지 확인합니다.&lt;/p&gt;
&lt;pre class=&quot;php&quot;&gt;&lt;code&gt;EXEC DBMS_SCHEDULER.RUN_JOB('JOB_TAX_PURCHASE_A10', use_current_session =&amp;gt; FALSE);
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;use_current_session =&amp;gt; FALSE로 주면 실제 스케줄러 워커가 실행하는 환경과 동일하게 동작합니다. 권한, 세션 설정 등 문제를 미리 잡을 수 있습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;실행 이력 모니터링&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;작업 등록만큼 중요한 게 사후 모니터링입니다. &lt;b&gt;SCHEDULED 상태인데도 실제로는 안 돌고 있는 경우&lt;/b&gt;가 운영 환경에서 자주 발생합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;일별 실행 결과 확인&lt;/h3&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;SELECT TO_CHAR(actual_start_date, 'YYYY-MM-DD HH24:MI:SS') AS start_time,
       status,
       run_duration,
       error#,
       SUBSTR(errors, 1, 200) AS error_message
FROM   user_scheduler_job_run_details
WHERE  job_name = 'JOB_TAX_PURCHASE_A10'
ORDER  BY actual_start_date DESC
FETCH  FIRST 20 ROWS ONLY;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;status 가능 값:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;SUCCEEDED: 정상 완료&lt;/li&gt;
&lt;li&gt;FAILED: 실패 (error#, errors에서 사유 확인)&lt;/li&gt;
&lt;li&gt;STOPPED: 외부에서 중단됨&lt;/li&gt;
&lt;li&gt;BROKEN: 연속 실패로 자동 비활성화됨&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;실패 알림 자동화 (★ 실무 핵심)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;운영 환경에서는 &lt;b&gt;작업이 실패했을 때 즉시 알림&lt;/b&gt;이 필요합니다. DBMS_SCHEDULER는 이메일 알림을 기본 지원합니다.&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- 1) 메일 서버 설정 (한 번만)
BEGIN
    DBMS_SCHEDULER.SET_SCHEDULER_ATTRIBUTE('email_server', 'smtp.company.com:25');
    DBMS_SCHEDULER.SET_SCHEDULER_ATTRIBUTE('email_sender', 'dba@company.com');
END;
/

-- 2) 실패 시 알림 등록
BEGIN
    DBMS_SCHEDULER.ADD_JOB_EMAIL_NOTIFICATION(
        job_name   =&amp;gt; 'JOB_TAX_PURCHASE_A10',
        recipients =&amp;gt; 'dba-team@company.com',
        events     =&amp;gt; 'JOB_FAILED, JOB_BROKEN, JOB_SCH_LIM_REACHED'
    );
END;
/
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 해두면 작업이 실패한 순간 담당자에게 메일이 발송됩니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;운영 관리 명령어 모음&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자주 쓰는 명령어를 모았습니다. 운영 매뉴얼에 그대로 활용 가능합니다.&lt;/p&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;-- 즉시 실행 (수동)
EXEC DBMS_SCHEDULER.RUN_JOB('JOB_TAX_PURCHASE_A10');

-- 임시 비활성화 (점검 시)
EXEC DBMS_SCHEDULER.DISABLE('JOB_TAX_PURCHASE_A10');

-- 다시 활성화
EXEC DBMS_SCHEDULER.ENABLE('JOB_TAX_PURCHASE_A10');

-- 실행 시각 변경 (예: 매일 03, 09, 15, 21시로)
BEGIN
    DBMS_SCHEDULER.SET_ATTRIBUTE(
        name      =&amp;gt; 'JOB_TAX_PURCHASE_A10',
        attribute =&amp;gt; 'repeat_interval',
        value     =&amp;gt; 'FREQ=DAILY;BYHOUR=3,9,15,21;BYMINUTE=0;BYSECOND=0'
    );
END;
/

-- 현재 실행 중인 인스턴스 강제 중지
EXEC DBMS_SCHEDULER.STOP_JOB('JOB_TAX_PURCHASE_A10', force =&amp;gt; TRUE);

-- 작업 완전 삭제
EXEC DBMS_SCHEDULER.DROP_JOB('JOB_TAX_PURCHASE_A10');
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;운영 환경 주의사항 5가지&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 이전 실행이 안 끝났는데 다음 시각이 오면?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DBMS_SCHEDULER는 기본적으로 &lt;b&gt;이전 실행이 완료될 때까지 다음 실행을 대기&lt;/b&gt;시킵니다. 06시간 간격이라 6시간 안에 끝나야 다음 사이클이 정상 동작합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 작업이 길어질 수 있다면 작업 분할 또는 병렬 처리를 검토하세요. &lt;b&gt;실행 시간 모니터링은 필수&lt;/b&gt;입니다.&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- 평균 / 최대 실행 시간 확인
SELECT AVG(EXTRACT(SECOND FROM run_duration) +
           EXTRACT(MINUTE FROM run_duration) * 60) AS avg_seconds,
       MAX(EXTRACT(SECOND FROM run_duration) +
           EXTRACT(MINUTE FROM run_duration) * 60) AS max_seconds
FROM   user_scheduler_job_run_details
WHERE  job_name = 'JOB_TAX_PURCHASE_A10'
  AND  status = 'SUCCEEDED'
  AND  actual_start_date &amp;gt; SYSDATE - 30;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. JOB_QUEUE_PROCESSES 파라미터 확인&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 값이 0이면 모든 스케줄러 작업이 중지됩니다.&lt;/p&gt;
&lt;pre class=&quot;mipsasm&quot;&gt;&lt;code&gt;SHOW PARAMETER job_queue_processes
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본값은 보통 1000입니다. 너무 낮게 설정되어 있으면 동시 실행 작업이 많을 때 대기가 발생합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. 권한 확인&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PROC_TAX_PURCHASE_A10이 다른 스키마에 있다면 EXECUTE 권한이 필요하고, 작업을 만들 사용자는 CREATE JOB 시스템 권한이 있어야 합니다.&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- 권한 확인
SELECT * FROM user_sys_privs WHERE privilege LIKE '%JOB%';
SELECT * FROM user_tab_privs WHERE table_name = 'PROC_TAX_PURCHASE_A10';
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4. RAC 환경에서 특정 노드 지정&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특정 인스턴스에서만 실행하고 싶다면:&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;BEGIN
    DBMS_SCHEDULER.SET_ATTRIBUTE(
        name      =&amp;gt; 'JOB_TAX_PURCHASE_A10',
        attribute =&amp;gt; 'INSTANCE_ID',
        value     =&amp;gt; 1
    );
END;
/
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5. 작업 실행 중 DB 재시작 시 동작&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;작업이 실행 중인데 DB가 셧다운되면 해당 실행은 중단되고, 다음 스케줄 시각부터 정상 동작합니다. 중단된 실행은 자동 재시작되지 &lt;b&gt;않습니다&lt;/b&gt;. 누락된 데이터가 있다면 수동 실행이 필요합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;마무리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DBMS_SCHEDULER로 동적 인자가 필요한 배치 작업을 등록할 때 핵심은 세 가지입니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;PLSQL_BLOCK 타입 + job_action 안에 인자 평가&lt;/b&gt; &amp;mdash; 매 실행 시점에 SYSDATE가 새로 계산됩니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;repeat_interval에 BYHOUR/BYMINUTE/BYSECOND 명시&lt;/b&gt; &amp;mdash; 정확한 시각에 실행하려면 모두 지정해야 합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;등록 후 EVALUATE_CALENDAR_STRING으로 검증&lt;/b&gt; &amp;mdash; 예상과 다른 시각에 잡히는 사고를 미리 막습니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글의 예제는 매일 4회 실행되는 세금/구매 데이터 처리지만, 같은 패턴으로 &lt;b&gt;매시간 통계 갱신&lt;/b&gt;, &lt;b&gt;매주 마감 작업&lt;/b&gt;, &lt;b&gt;매월 1일 정산 배치&lt;/b&gt; 등 어떤 주기 작업이라도 응용 가능합니다. 본인 환경의 실행 시각과 프로시저 이름만 바꾸면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비슷한 배치 작업을 운영하면서 만난 이슈나, 더 좋은 패턴이 있다면 댓글로 공유해 주세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>DBA 실무/Oracle(오라클)</category>
      <category>BYHOUR</category>
      <category>DBA</category>
      <category>DBMS_SCHEDULER</category>
      <category>EVALUATE_CALENDER_STRING</category>
      <category>q-quoting</category>
      <category>repeat_interval</category>
      <category>오라클</category>
      <category>오라클배치</category>
      <category>오라클스케줄러</category>
      <category>프로시저자동실행</category>
      <author>isony</author>
      <guid isPermaLink="true">https://isony.tistory.com/324</guid>
      <comments>https://isony.tistory.com/entry/%EC%98%A4%EB%9D%BC%ED%81%B4-%EC%8B%A4%EB%AC%B4-DBMSSCHEDULER%EB%A1%9C-%ED%94%84%EB%A1%9C%EC%8B%9C%EC%A0%80%EB%A5%BC-6%EC%8B%9C%EA%B0%84-%EB%8B%A8%EC%9C%84-%EC%8B%A4%ED%96%89%ED%95%98%EA%B8%B0-%EB%8F%99%EC%A0%81-%EC%9D%B8%EC%9E%90-%EC%A0%84%EB%8B%AC-%EC%99%84%EB%B2%BD-%EC%98%88%EC%A0%9C#entry324comment</comments>
      <pubDate>Mon, 1 Jun 2026 16:38:00 +0900</pubDate>
    </item>
    <item>
      <title>[오라클] DBMS_JOB과 DBMS_SCHEDULER 차이점 - 언제 뭘 써야 할까? (19c 변환 동작까지)</title>
      <link>https://isony.tistory.com/entry/%EC%98%A4%EB%9D%BC%ED%81%B4-DBMSJOB%EA%B3%BC-DBMSSCHEDULER-%EC%B0%A8%EC%9D%B4%EC%A0%90-%EC%96%B8%EC%A0%9C-%EB%AD%98-%EC%8D%A8%EC%95%BC-%ED%95%A0%EA%B9%8C-19c-%EB%B3%80%ED%99%98-%EB%8F%99%EC%9E%91%EA%B9%8C%EC%A7%80</link>
      <description>&lt;h1&gt;오라클 DBMS_JOB과 DBMS_SCHEDULER 차이점 - 언제 뭘 써야 할까? (19c 변환 동작까지)&lt;/h1&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;테스트 환경&lt;/b&gt;: Oracle 11g / 12c / 19c / 21c&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오라클에서 작업을 자동화할 때 가장 많이 검색되는 질문 중 하나가 &lt;b&gt;&quot;DBMS_JOB과 DBMS_SCHEDULER, 둘 다 있는데 뭐가 다른가?&quot;&lt;/b&gt; 입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결론부터 말씀드리면, &lt;b&gt;2026년 현재 시점에서 새로 만드는 작업은 100% DBMS_SCHEDULER를 써야 합니다&lt;/b&gt;. DBMS_JOB은 12cR2부터 deprecated되었고, 19c부터는 사용해도 내부적으로 DBMS_SCHEDULER로 변환되어 동작합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇다면 왜 아직도 운영 환경에 DBMS_JOB이 살아있고, 두 개의 차이를 알아둬야 하는 걸까요? 이번 글에서 둘의 핵심 차이, 19c부터 달라진 동작, 그리고 기존 DBMS_JOB을 DBMS_SCHEDULER로 옮기는 실무 방법까지 정리했습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;한 줄 요약&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구분 DBMS_JOB DBMS_SCHEDULER&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;등장 시점&lt;/td&gt;
&lt;td&gt;Oracle 7 이전부터&lt;/td&gt;
&lt;td&gt;Oracle 10g부터&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;현재 상태&lt;/td&gt;
&lt;td&gt;&lt;b&gt;12cR2부터 deprecated&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;권장 표준&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;19c 이상 동작&lt;/td&gt;
&lt;td&gt;내부적으로 DBMS_SCHEDULER로 변환&lt;/td&gt;
&lt;td&gt;그대로 사용&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;새 개발 권장 여부&lt;/td&gt;
&lt;td&gt;❌ 사용 금지&lt;/td&gt;
&lt;td&gt;✅ 권장&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;새 코드는 무조건 DBMS_SCHEDULER. 이게 끝입니다. 다만 운영 중인 DBMS_JOB을 이해하고 마이그레이션하려면 두 패키지의 차이를 알아야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;핵심 차이점 비교&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;항목 DBMS_JOB DBMS_SCHEDULER&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;작업 종류&lt;/td&gt;
&lt;td&gt;PL/SQL 블록만&lt;/td&gt;
&lt;td&gt;PL/SQL, 저장 프로시저, OS 실행파일, 외부 스크립트, 체인(Chain)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;외부 OS 명령 실행&lt;/td&gt;
&lt;td&gt;❌ 불가&lt;/td&gt;
&lt;td&gt;✅ 가능 (EXECUTABLE 타입)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;트랜잭션 동작&lt;/td&gt;
&lt;td&gt;&lt;b&gt;트랜잭션의 일부&lt;/b&gt; (COMMIT 해야 등록됨)&lt;/td&gt;
&lt;td&gt;&lt;b&gt;별도 트랜잭션&lt;/b&gt; (즉시 커밋)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;스케줄 표현&lt;/td&gt;
&lt;td&gt;DATE 산술식 (SYSDATE+1)&lt;/td&gt;
&lt;td&gt;캘린더 표현식 (FREQ=DAILY;BYHOUR=2)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;의존성/체인&lt;/td&gt;
&lt;td&gt;❌ 없음&lt;/td&gt;
&lt;td&gt;✅ 작업 간 의존 관계 정의 가능&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;리소스 관리&lt;/td&gt;
&lt;td&gt;❌ 없음&lt;/td&gt;
&lt;td&gt;✅ Resource Manager 연동&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;작업 클래스&lt;/td&gt;
&lt;td&gt;❌ 없음&lt;/td&gt;
&lt;td&gt;✅ Job Class로 그룹 관리&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;모니터링 뷰&lt;/td&gt;
&lt;td&gt;DBA_JOBS, DBA_JOBS_RUNNING&lt;/td&gt;
&lt;td&gt;DBA_SCHEDULER_JOBS, DBA_SCHEDULER_JOB_RUN_DETAILS 등 풍부&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;오류 처리&lt;/td&gt;
&lt;td&gt;빈약&lt;/td&gt;
&lt;td&gt;상세한 실행 이력 및 실패 사유 기록&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 표만 봐도 &lt;b&gt;DBMS_SCHEDULER가 모든 면에서 우위&lt;/b&gt;라는 게 명확합니다. 단 한 가지, &lt;b&gt;트랜잭션 동작&lt;/b&gt;은 상황에 따라 DBMS_JOB이 유리한 경우가 있는데, 이건 뒤에서 다룹니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;DBMS_JOB - 옛날 방식&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;기본 사용법&lt;/h3&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;DECLARE
    v_job NUMBER;
BEGIN
    DBMS_JOB.SUBMIT(
        job       =&amp;gt; v_job,
        what      =&amp;gt; 'BEGIN my_procedure; END;',
        next_date =&amp;gt; SYSDATE,
        interval  =&amp;gt; 'SYSDATE + 1/24'   -- 1시간마다
    );
    COMMIT;   -- ★ 이게 없으면 등록 안 됨
END;
/
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;DBMS_JOB의 결정적 단점&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;외부 OS 명령 실행 불가&lt;/b&gt; &amp;mdash; PL/SQL 블록만 돌릴 수 있어서 백업 스크립트, 외부 파일 처리 등은 불가능&lt;/li&gt;
&lt;li&gt;&lt;b&gt;INTERVAL이 모호하고 가독성 떨어짐&lt;/b&gt; &amp;mdash; 'SYSDATE + 1/24'가 매시간이라는 걸 한눈에 알기 어려움&lt;/li&gt;
&lt;li&gt;&lt;b&gt;실행 이력 추적 어려움&lt;/b&gt; &amp;mdash; 실패 사유, 실행 시간 같은 정보가 빈약&lt;/li&gt;
&lt;li&gt;&lt;b&gt;작업 간 의존성 표현 불가&lt;/b&gt; &amp;mdash; &quot;A 끝나면 B 실행&quot; 같은 체인 구성 안 됨&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;그래도 살아남는 이유: 트랜잭션 일부 동작 ★&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DBMS_JOB은 &lt;b&gt;트랜잭션의 일부&lt;/b&gt;로 작업을 등록합니다. 즉, COMMIT을 해야만 작업이 실제로 큐에 들어갑니다. 이게 의외로 유용한 케이스가 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;시나리오&lt;/b&gt;: 트리거에서 이메일 발송 작업을 등록하는데, 트리거를 발동시킨 트랜잭션이 롤백되면 이메일도 발송되면 안 되는 경우.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DBMS_JOB을 쓰면 트랜잭션이 롤백될 때 등록된 작업도 같이 사라집니다. 반면 DBMS_SCHEDULER는 등록 즉시 커밋되어 별도 트랜잭션이 되므로, 트리거 안에서 호출하면 본 트랜잭션이 롤백되어도 이메일은 발송됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;19c부터 DBMS_SCHEDULER도 CREATE_JOBS(복수형) 프로시저에 commit_semantics =&amp;gt; 'TRANSACTIONAL' 옵션이 추가되어 이 동작을 구현할 수 있지만, 단일 작업 등록에는 적용되지 않아 여전히 일부 시나리오에서는 DBMS_JOB의 호환성이 필요한 상황이 남아 있습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;조회&lt;/h3&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;SELECT job, what, last_date, next_date, interval, broken
FROM dba_jobs;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;DBMS_SCHEDULER - 표준 방식&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;기본 사용법&lt;/h3&gt;
&lt;pre class=&quot;php&quot;&gt;&lt;code&gt;BEGIN
    DBMS_SCHEDULER.CREATE_JOB(
        job_name        =&amp;gt; 'MY_DAILY_JOB',
        job_type        =&amp;gt; 'PLSQL_BLOCK',
        job_action      =&amp;gt; 'BEGIN my_procedure; END;',
        start_date      =&amp;gt; SYSTIMESTAMP,
        repeat_interval =&amp;gt; 'FREQ=DAILY;BYHOUR=2;BYMINUTE=30',  -- 매일 02:30
        enabled         =&amp;gt; TRUE,
        comments        =&amp;gt; '일일 통계 갱신 작업'
    );
END;
/
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;COMMIT이 필요 없습니다.&lt;/b&gt; CREATE_JOB 자체가 즉시 커밋됩니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;repeat_interval 표현식 - 캘린더 구문&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이게 DBMS_SCHEDULER의 강점입니다. 자연어에 가까운 표현이 가능합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원하는 동작 repeat_interval 표현&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;매일 02:30&lt;/td&gt;
&lt;td&gt;FREQ=DAILY;BYHOUR=2;BYMINUTE=30&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;매주 월~금 09:00&lt;/td&gt;
&lt;td&gt;FREQ=WEEKLY;BYDAY=MON,TUE,WED,THU,FRI;BYHOUR=9&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;매월 1일 00:00&lt;/td&gt;
&lt;td&gt;FREQ=MONTHLY;BYMONTHDAY=1;BYHOUR=0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;매월 마지막 평일&lt;/td&gt;
&lt;td&gt;FREQ=MONTHLY;BYDAY=-1MON,-1TUE,-1WED,-1THU,-1FRI&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5분마다&lt;/td&gt;
&lt;td&gt;FREQ=MINUTELY;INTERVAL=5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;매년 1월 1일&lt;/td&gt;
&lt;td&gt;FREQ=YEARLY;BYMONTH=1;BYMONTHDAY=1&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DBMS_JOB의 'TRUNC(SYSDATE+1)+2.5/24' 보다 압도적으로 가독성이 좋습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;다양한 작업 유형&lt;/h3&gt;
&lt;pre class=&quot;dart&quot;&gt;&lt;code&gt;-- 1) PL/SQL 블록
job_type =&amp;gt; 'PLSQL_BLOCK'

-- 2) 저장 프로시저
job_type =&amp;gt; 'STORED_PROCEDURE'
job_action =&amp;gt; 'SCHEMA.PACKAGE.PROCEDURE'

-- 3) OS 실행 파일 (★ DBMS_JOB은 불가능했던 영역)
job_type =&amp;gt; 'EXECUTABLE'
job_action =&amp;gt; '/u01/app/scripts/backup.sh'

-- 4) 외부 작업 (원격 서버)
job_type =&amp;gt; 'EXTERNAL_SCRIPT'
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OS 스크립트 실행은 운영 자동화의 핵심입니다. 백업, 로그 정리, 외부 시스템 연동 등이 가능해집니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;조회&lt;/h3&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- 작업 목록
SELECT job_name, job_type, repeat_interval, state, enabled
FROM dba_scheduler_jobs
WHERE owner = 'SCOTT';

-- 실행 이력 (실패 사유 포함)
SELECT job_name, status, run_duration, error#, errors,
       actual_start_date
FROM dba_scheduler_job_run_details
WHERE owner = 'SCOTT'
ORDER BY actual_start_date DESC;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실패 시 error#(에러 코드)과 errors(상세 메시지)까지 자동으로 기록됩니다. DBMS_JOB과는 비교할 수 없는 운영 편의성입니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;★ 19c부터 달라진 동작 (이걸 모르면 헷갈립니다)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대부분의 한국어 블로그가 이 부분을 놓치고 있는데, &lt;b&gt;운영 DB를 19c로 업그레이드했다면 반드시 알아야 합니다&lt;/b&gt;.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;무엇이 변했나&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;19c부터 &lt;b&gt;DBMS_JOB.SUBMIT을 호출해도 내부적으로 DBMS_SCHEDULER 작업으로 생성&lt;/b&gt;됩니다. 백워드 호환성을 위해 인터페이스는 살려두되, 실제 실행 엔진은 통합한 것입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;확인 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;19c 환경에서 DBMS_JOB으로 작업을 만들어 보면 양쪽 뷰에 다 보입니다.&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- 1) DBMS_JOB으로 작업 생성
DECLARE v_job NUMBER;
BEGIN
    DBMS_JOB.SUBMIT(v_job, 'BEGIN NULL; END;', SYSDATE, 'SYSDATE+1');
    COMMIT;
END;
/

-- 2) 두 뷰 모두에서 조회됨
SELECT job, what FROM user_jobs;
SELECT job_name, job_action FROM user_scheduler_jobs;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;user_scheduler_jobs에서 보면 작업 이름이 DBMS_JOB$_숫자 형태로 자동 생성됩니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;실무에서 주의할 점&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;JOB_QUEUE_PROCESSES 파라미터는 둘이 공유&lt;/b&gt;합니다. DBMS_JOB과 DBMS_SCHEDULER 작업의 동시 실행 수 합계가 이 값을 넘을 수 없습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;DBMS_JOB의 트랜잭션 동작은 유지&lt;/b&gt;됩니다. 19c에서도 COMMIT을 안 하면 등록되지 않습니다 (이 부분만큼은 호환성이 살아있음).&lt;/li&gt;
&lt;li&gt;&lt;b&gt;업그레이드 시 기존 DBMS_JOB이 자동 변환&lt;/b&gt;됩니다. 변환 불가능한 작업이 있으면 JOB_TABLE_INTEGRITY 경고가 뜨므로 업그레이드 전 점검이 필요합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;21c 이후는?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;21c에서도 DBMS_JOB은 여전히 사용 가능하지만, &lt;b&gt;언젠가는 완전히 제거(desupport)될 예정&lt;/b&gt;입니다. 신규 개발은 무조건 DBMS_SCHEDULER로 가야 하는 이유입니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;어떤 걸 써야 할까? 실무 가이드&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상황별 결정 트리입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;신규 작업 개발&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;무조건 DBMS_SCHEDULER.&lt;/b&gt; 예외 없음. 단순한 PL/SQL 호출이라도 DBMS_SCHEDULER로 시작하세요. 나중에 외부 스크립트 호출이 추가되거나 복잡한 스케줄이 필요해질 때 돌아오는 비용이 큽니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;기존 DBMS_JOB이 운영 중&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;점진적 마이그레이션 권장.&lt;/b&gt; 19c에서 자동 변환되어 동작은 하지만, 다음 시점에 옮기는 게 좋습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;해당 작업의 로직을 수정할 일이 생겼을 때&lt;/li&gt;
&lt;li&gt;DB 업그레이드 작업과 함께&lt;/li&gt;
&lt;li&gt;작업 실패 추적이 필요해질 때&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;트리거 안에서 비동기 작업 등록&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;여전히 DBMS_JOB이 유리한 거의 유일한 경우.&lt;/b&gt; 트랜잭션과 함께 롤백되어야 하는 작업이면 DBMS_JOB을 유지하거나, DBMS_SCHEDULER의 트랜잭셔널 옵션을 활용하세요.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;DBMS_JOB &amp;rarr; DBMS_SCHEDULER 마이그레이션 예시&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존 DBMS_JOB 작업이 다음과 같다면:&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- 기존 (DBMS_JOB) - 매일 새벽 2시 30분 실행
DECLARE v_job NUMBER;
BEGIN
    DBMS_JOB.SUBMIT(
        job       =&amp;gt; v_job,
        what      =&amp;gt; 'BEGIN stats_proc; END;',
        next_date =&amp;gt; TRUNC(SYSDATE+1) + 2.5/24,
        interval  =&amp;gt; 'TRUNC(SYSDATE+1) + 2.5/24'
    );
    COMMIT;
END;
/
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DBMS_SCHEDULER로 옮기면:&lt;/p&gt;
&lt;pre class=&quot;php&quot;&gt;&lt;code&gt;-- 새 방식 (DBMS_SCHEDULER)
BEGIN
    DBMS_SCHEDULER.CREATE_JOB(
        job_name        =&amp;gt; 'STATS_DAILY_JOB',
        job_type        =&amp;gt; 'PLSQL_BLOCK',
        job_action      =&amp;gt; 'BEGIN stats_proc; END;',
        start_date      =&amp;gt; SYSTIMESTAMP,
        repeat_interval =&amp;gt; 'FREQ=DAILY;BYHOUR=2;BYMINUTE=30',
        enabled         =&amp;gt; TRUE,
        comments        =&amp;gt; '일일 통계 작업 (DBMS_JOB에서 마이그레이션)'
    );
END;
/
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;마이그레이션 시 체크리스트&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;기존 작업의 정확한 실행 시각 확인&lt;/b&gt; &amp;mdash; dba_jobs.next_date, interval 분석&lt;/li&gt;
&lt;li&gt;&lt;b&gt;변환된 repeat_interval 검증&lt;/b&gt; &amp;mdash; dbms_scheduler.evaluate_calendar_string으로 다음 실행 시각 미리 확인&lt;/li&gt;
&lt;li&gt;&lt;b&gt;테스트 환경에서 먼저 실행&lt;/b&gt; &amp;mdash; 운영 환경 직접 변경은 금물&lt;/li&gt;
&lt;li&gt;&lt;b&gt;모니터링 추가&lt;/b&gt; &amp;mdash; 마이그레이션 후 첫 1주일은 dba_scheduler_job_run_details 매일 확인&lt;/li&gt;
&lt;li&gt;&lt;b&gt;기존 DBMS_JOB 제거&lt;/b&gt; &amp;mdash; 새 작업이 정상 동작 확인 후 DBMS_JOB.REMOVE(job_id)&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;자주 발생하는 트러블슈팅&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;작업이 등록은 됐는데 실행이 안 됨&lt;/h3&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- 1) JOB_QUEUE_PROCESSES 확인
SHOW PARAMETER job_queue_processes;
-- 0이면 모든 작업이 중지됨. 권장값: 1000 또는 기본값
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;작업이 disabled 상태로 등록됨&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DBMS_SCHEDULER는 기본값이 enabled =&amp;gt; FALSE입니다. 명시적으로 TRUE를 주거나, 생성 후 ENABLE하세요.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;DBMS_SCHEDULER.ENABLE('MY_JOB');
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;RAC 환경에서 특정 인스턴스에서만 실행하고 싶을 때&lt;/h3&gt;
&lt;pre class=&quot;typescript&quot;&gt;&lt;code&gt;DBMS_SCHEDULER.SET_ATTRIBUTE(
    name      =&amp;gt; 'MY_JOB',
    attribute =&amp;gt; 'INSTANCE_ID',
    value     =&amp;gt; 1
);
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;실행 시각이 예상과 다를 때&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;타임존 문제일 가능성이 높습니다. 19c부터 DBMS_SCHEDULER가 세션 타임존을 사용하는 동작 차이로 인해 업그레이드 후 실행 시각이 변경되는 사례가 보고되었습니다. start_date에 명시적 타임존을 지정하세요.&lt;/p&gt;
&lt;pre class=&quot;lisp&quot;&gt;&lt;code&gt;start_date =&amp;gt; TO_TIMESTAMP_TZ('2026-01-01 02:30:00 Asia/Seoul',
                              'YYYY-MM-DD HH24:MI:SS TZR')
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;마무리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DBMS_JOB과 DBMS_SCHEDULER는 같은 기능을 하는 두 가지 패키지가 아니라, &lt;b&gt;세대가 다른 도구&lt;/b&gt;입니다. 2026년 현재 시점에서 새 작업은 무조건 DBMS_SCHEDULER이며, DBMS_JOB은 호환성을 위한 레거시 인터페이스로만 봐야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히 &lt;b&gt;19c부터 DBMS_JOB이 내부적으로 DBMS_SCHEDULER로 변환되어 동작&lt;/b&gt;한다는 사실은 운영 DB 업그레이드 시 반드시 알아야 할 내용입니다. 두 시스템이 자원을 공유하기 때문에 트러블슈팅 시 양쪽 뷰를 모두 확인하는 습관을 들이세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존 DBMS_JOB이 많은 운영 환경이라면 한 번에 옮기지 말고, 작업 단위로 점진적으로 마이그레이션하는 것이 안전합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;질문이나 비슷한 마이그레이션 경험이 있다면 댓글로 공유해 주세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>DBA 실무/Oracle(오라클)</category>
      <category>DBA</category>
      <category>DBA실무</category>
      <category>dbms_job</category>
      <category>DBMS_SCHEDULER</category>
      <category>repeat_interval</category>
      <category>오라클</category>
      <category>오라클19C</category>
      <category>오라클스케줄러</category>
      <category>오라클자동화</category>
      <category>오라클작업</category>
      <author>isony</author>
      <guid isPermaLink="true">https://isony.tistory.com/323</guid>
      <comments>https://isony.tistory.com/entry/%EC%98%A4%EB%9D%BC%ED%81%B4-DBMSJOB%EA%B3%BC-DBMSSCHEDULER-%EC%B0%A8%EC%9D%B4%EC%A0%90-%EC%96%B8%EC%A0%9C-%EB%AD%98-%EC%8D%A8%EC%95%BC-%ED%95%A0%EA%B9%8C-19c-%EB%B3%80%ED%99%98-%EB%8F%99%EC%9E%91%EA%B9%8C%EC%A7%80#entry323comment</comments>
      <pubDate>Mon, 1 Jun 2026 16:29:17 +0900</pubDate>
    </item>
    <item>
      <title>2026년05월31일 주일예배 (이재훈목사님) - 1부</title>
      <link>https://isony.tistory.com/entry/2026%EB%85%8405%EC%9B%9431%EC%9D%BC-%EC%A3%BC%EC%9D%BC%EC%98%88%EB%B0%B0-%EC%9D%B4%EC%9E%AC%ED%9B%88%EB%AA%A9%EC%82%AC%EB%8B%98-1%EB%B6%80</link>
      <description>&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;2026년05월31일 주일예배 (이재훈목사님) - 1부&lt;/h2&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;주의 말씀 : 나를 따르라&amp;nbsp; (3)&lt;/h2&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;사슴이 알려준 제자도의 비밀&lt;/h2&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;성경 :&amp;nbsp; 시편(Psalm) 42:1 ~ 11 말씀 (출처:우리말성경)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&amp;lt; 성경 &amp;gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;42:1 오 하나님이여, 사슴이 목이 말라 헐떡거리며 시냇물을 찾듯이 내 영혼이 목이 말라 주를 찾습니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;42:2 내 영혼이 하나님을, 살아 계신 하나님을 목말라합니다. 내가 언제 나아가서 하나님을 뵐 수 있겠습니까?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;42:3 사람들이 밤낮으로 내게 &amp;ldquo;네 하나님이 어디 있느냐?&amp;rdquo; 하니 내 눈물이 밤낮으로 내 음식이 됐습니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;42:4 지난날들을 생각해 보면 내 영혼을 토해 내지 않을 수 없습니다. 내가 많은 사람들과 함께 그 행렬을 이끌고 하나님의 집으로 가며 명절을 지키러 가는 사람들 사이에서 기뻐 외치며 찬양했습니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;42:5 오 내 영혼아, 왜 그렇게 풀이 죽어 있느냐? 왜 이렇게 내 속에서 불안해하느냐? 너는 하나님을 바라라. 그 도와주시는 얼굴을 보아라. 내가 오히려 그분을 찬양하리라.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;42:6 오 내 하나님이여, 내 영혼이 내 속에서 풀 죽어 있으니 요단 땅 헤르몬 산, 곧 미살 산을 바라보며 내가 주를 기억할 것입니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;42:7 주의 폭포 소리에 깊은 바다가 깊은 바다를 부르고 주의 파도와 주의 물결이 나를 덮칩니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;42:8 그러나 낮에는 여호와께서 그 신실함을 보여 주시고 밤에는 주의 노래가 내게 있으니 내 기도가 내 생명 되신 하나님께 닿을 것입니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;42:9 내 반석이신 하나님께 내가 말할 것입니다. &amp;ldquo;왜 나를 잊으셨습니까? 내가 왜 적들에게 억눌린 채 슬퍼하며 돌아다녀야 합니까?&amp;rdquo;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;42:10 내 원수들이 나를 조롱하며 날마다 &amp;ldquo;네 하나님이 어디 있느냐?&amp;rdquo; 하는 말이 마치 칼이 내 뼈마디를 쑤시는 것 같습니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;42:11 오 내 영혼아, 왜 이렇게 풀이 죽어 있느냐? 왜 이렇게 내 속에서 불안해하느냐? 너는 하나님을 바라라. 내가 오히려 그분을 찬양하리라. 그분은 내 얼굴을 도와주시는 분이며 내 하나님이십니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&amp;lt; 예배 영상 &amp;gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;a href=&quot;https://youtu.be/T2nehx2yVOk&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://youtu.be/T2nehx2yVOk&lt;/a&gt;&lt;/b&gt;&lt;/p&gt;
&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignCenter&quot; data-video-host=&quot;youtube&quot; data-video-url=&quot;https://www.youtube.com/watch?v=T2nehx2yVOk&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/tLnpj/dJMb83SpUzz/lkXgqXmHtmfZgNMYBKjPMK/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=554_152_694_304,https://scrap.kakaocdn.net/dn/bzdmUy/dJMb84X5GtK/STPk57Zij5Km3VptThO550/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=554_152_694_304,https://scrap.kakaocdn.net/dn/IMbez/dJMb85W0iwR/ksakb06H70uctHJ3ucE6Fk/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=554_152_694_304&quot; data-video-width=&quot;860&quot; data-video-height=&quot;484&quot; data-video-origin-width=&quot;860&quot; data-video-origin-height=&quot;484&quot; data-ke-mobilestyle=&quot;widthContent&quot; data-video-title=&quot;주일예배2026 05 31&quot; data-original-url=&quot;&quot;&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/T2nehx2yVOk&quot; width=&quot;860&quot; height=&quot;484&quot; frameborder=&quot;&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;figcaption style=&quot;display: none;&quot;&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>성경과 QT/주일예배(온누리교회)</category>
      <category>CGNTV</category>
      <category>나를따르라</category>
      <category>소니스토리</category>
      <category>시편</category>
      <category>영상예배</category>
      <category>온누리교회</category>
      <category>우리말성경</category>
      <category>이재훈목사</category>
      <category>제자도의비밀</category>
      <category>주일예배</category>
      <author>isony</author>
      <guid isPermaLink="true">https://isony.tistory.com/322</guid>
      <comments>https://isony.tistory.com/entry/2026%EB%85%8405%EC%9B%9431%EC%9D%BC-%EC%A3%BC%EC%9D%BC%EC%98%88%EB%B0%B0-%EC%9D%B4%EC%9E%AC%ED%9B%88%EB%AA%A9%EC%82%AC%EB%8B%98-1%EB%B6%80#entry322comment</comments>
      <pubDate>Sun, 31 May 2026 08:10:55 +0900</pubDate>
    </item>
    <item>
      <title>[오라클 에러] ORA-28000 계정이 잠겼습니다 - 잠금 해제부터 재발 방지까지 (실무 DBA 정리)</title>
      <link>https://isony.tistory.com/entry/%EC%98%A4%EB%9D%BC%ED%81%B4-%EC%97%90%EB%9F%AC-ORA-28000-%EA%B3%84%EC%A0%95%EC%9D%B4-%EC%9E%A0%EA%B2%BC%EC%8A%B5%EB%8B%88%EB%8B%A4-%EC%9E%A0%EA%B8%88-%ED%95%B4%EC%A0%9C%EB%B6%80%ED%84%B0-%EC%9E%AC%EB%B0%9C-%EB%B0%A9%EC%A7%80%EA%B9%8C%EC%A7%80-%EC%8B%A4%EB%AC%B4-DBA-%EC%A0%95%EB%A6%AC</link>
      <description>&lt;h1&gt;[오라클 에러] ORA-28000 계정이 잠겼습니다 - 잠금 해제부터 재발 방지까지 (실무 DBA 정리)&lt;/h1&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;테스트 환경&lt;/b&gt;: Oracle 11g / 12c / 19c / 21c&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ORA-28000은 운영 DB에서 가장 자주 발생하는 계정 관련 에러입니다. &quot;그냥 풀어주면 끝&quot;이라고 생각하기 쉽지만, &lt;b&gt;풀어줘도 1분 만에 다시 잠기는 케이스&lt;/b&gt;가 운영 환경에선 매우 흔합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 글에서는 ORA-28000의 4가지 원인을 분류하고, &lt;b&gt;잠금 해제뿐 아니라 &quot;왜 잠겼는지&quot; 추적하는 방법&lt;/b&gt;, 그리고 &lt;b&gt;재발 방지를 위한 실무 가이드&lt;/b&gt;까지 정리했습니다. 특히 자동화 스크립트나 애플리케이션이 잘못된 비밀번호로 계속 시도해서 계정이 매일 잠기는 상황에 대한 진단법은 다른 글에서 잘 다루지 않는 부분입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;급하신 분은 &lt;u&gt;빠른 잠금 해제&lt;/u&gt; 섹션부터 보세요.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;u&gt;에러 메시지 전문&lt;/u&gt;&lt;/h2&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;ORA-28000: the account is locked
ORA-28000: 계정이 잠겼습니다.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SQL*Plus, SQL Developer, JDBC, 애플리케이션 로그 어디에서나 동일하게 발생합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ORA-01017(비밀번호 무효)과 자주 혼동되는데, 둘은 명확히 다릅니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;ORA-01017&lt;/b&gt;: 비밀번호가 틀렸다 (로그인 자체는 시도 가능)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;ORA-28000&lt;/b&gt;: 계정이 잠겨서 시도조차 안 받는다&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비밀번호를 맞게 입력해도 ORA-28000은 발생합니다. 보안상의 이유로 잠긴 상태이기 때문입니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;u&gt;빠른 잠금 해제 &lt;/u&gt;(1분 안에)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;급하면 이 두 줄만 실행하면 됩니다.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;-- DBA 권한 계정으로 접속해서
ALTER USER scott ACCOUNT UNLOCK;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비밀번호도 만료된 상태라면:&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;ALTER USER scott IDENTIFIED BY NewPassword2026 ACCOUNT UNLOCK;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;하지만 이게 끝이 아닙니다.&lt;/b&gt; 실무에서는 &quot;잠긴 원인&quot;을 찾지 않으면 풀어도 또 잠깁니다. 아래 진단 과정을 반드시 거치세요.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;ORA-28000 진단 - 왜 잠겼는지부터 확인&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;잠금 해제 전에 &lt;b&gt;계정 상태와 잠금 시각&lt;/b&gt;부터 확인합니다.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;SELECT username, account_status, lock_date, expiry_date, profile
FROM dba_users
WHERE UPPER(username) = UPPER('scott');
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;account_status 컬럼이 알려주는 정보:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상태 의미 원인&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;LOCKED&lt;/td&gt;
&lt;td&gt;DBA가 수동으로 잠금&lt;/td&gt;
&lt;td&gt;관리자 잠금 (원인 2)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LOCKED(TIMED)&lt;/td&gt;
&lt;td&gt;로그인 실패 횟수 초과로 자동 잠김&lt;/td&gt;
&lt;td&gt;원인 1 (가장 흔함)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;EXPIRED &amp;amp; LOCKED&lt;/td&gt;
&lt;td&gt;만료 + 잠금 동시&lt;/td&gt;
&lt;td&gt;원인 3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;EXPIRED(GRACE) &amp;amp; LOCKED&lt;/td&gt;
&lt;td&gt;만료 임박 + 잠금&lt;/td&gt;
&lt;td&gt;정책 + 시도 실패&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;lock_date는 &lt;b&gt;언제 잠겼는지&lt;/b&gt; 알려주는 핵심 정보입니다. 이 시각을 기준으로 로그를 추적하면 누가/무엇이 잘못된 비밀번호로 시도했는지 알 수 있습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;lt; 원인 1&amp;gt; 로그인 실패 횟수 초과 (FAILED_LOGIN_ATTEMPTS)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 흔한 원인입니다. 기본 설정은 보안 정책에 따라 3~10회 범위로 다양합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;정책 확인&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 사용자가 어떤 프로파일에 속해 있는지, 그리고 그 프로파일의 잠금 정책이 어떻게 되어 있는지 확인합니다.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;-- 1) 사용자가 속한 프로파일 확인
SELECT username, profile
FROM dba_users
WHERE UPPER(username) = UPPER('scott');

-- 2) 프로파일의 잠금 관련 정책 확인
SELECT resource_name, limit
FROM dba_profiles
WHERE profile = 'DEFAULT'
  AND resource_name IN ('FAILED_LOGIN_ATTEMPTS', 'PASSWORD_LOCK_TIME');
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결과 예시:&lt;/p&gt;
&lt;pre class=&quot;properties&quot;&gt;&lt;code&gt;RESOURCE_NAME            LIMIT
------------------------ --------
FAILED_LOGIN_ATTEMPTS    10
PASSWORD_LOCK_TIME       1
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 의미는 &lt;b&gt;&quot;10번 연속 비밀번호 틀리면, 1일 동안 자동 잠금&quot;&lt;/b&gt; 입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;PASSWORD_LOCK_TIME에 따른 동작 차이 (★ 실무 함정)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 두 가지 동작이 미묘하게 다르고, 모르면 진단을 헷갈리게 만듭니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;PASSWORD_LOCK_TIME = 숫자(예: 1)&lt;/b&gt;: 시간 경과 후 자동 해제. account_status는 LOCKED(TIMED)로 표시.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;PASSWORD_LOCK_TIME = UNLIMITED&lt;/b&gt;: DBA가 수동으로 풀 때까지 해제 안 됨. account_status는 LOCKED로 표시.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;해결 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;즉시 해제:&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;ALTER USER scott ACCOUNT UNLOCK;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;해제 후 반드시 해야 할 것: 실패한 IP/호스트 추적&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해제만 하면 어디선가 잘못된 비밀번호로 계속 시도하는 주체가 똑같이 또 잠급니다. 누가 시도했는지 먼저 찾으세요.&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;SELECT username, userhost, terminal, os_username,
       timestamp, returncode
FROM dba_audit_trail
WHERE username = UPPER('scott')
  AND returncode = 1017  -- 로그인 실패 코드
  AND timestamp &amp;gt; SYSDATE - 1
ORDER BY timestamp DESC;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;returncode = 1017은 비밀번호 틀림으로 인한 실패를 의미합니다. userhost와 terminal로 어느 서버에서 시도했는지 확인하면, 거기 있는 잘못된 비밀번호의 자동화 스크립트나 애플리케이션을 찾을 수 있습니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;참고&lt;/b&gt;: 12c 이상에서 통합 감사(Unified Auditing)를 쓴다면 unified_audit_trail 뷰를 조회하세요. 컬럼은 약간 다르지만 개념은 동일합니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;lt; 원인 2&amp;gt; DBA가 수동으로 잠금&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;명시적 잠금은 다음 명령으로 발생합니다.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;ALTER USER scott ACCOUNT LOCK;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;어떨 때 발생하나&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;퇴사자 계정 비활성화&lt;/li&gt;
&lt;li&gt;보안 사고 대응 (의심 계정 차단)&lt;/li&gt;
&lt;li&gt;임시 점검 (애플리케이션 점검 중 계정 차단)&lt;/li&gt;
&lt;li&gt;신규 DB 설치 시 기본 잠금 상태 (HR, SCOTT, OUTLN, DBSNMP 등)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;진단 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;dba_users.account_status가 LOCKED이고, lock_date가 NULL이 아니면 누군가 수동으로 잠근 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;신규 DB의 기본 잠금 계정을 확인하려면:&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;SELECT username, account_status
FROM dba_users
WHERE account_status LIKE 'LOCKED%'
ORDER BY username;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;해결 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해제 자체는 동일합니다.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;ALTER USER scott ACCOUNT UNLOCK;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만 &lt;b&gt;수동 잠금은 보통 이유가 있어서 잠근 것&lt;/b&gt;이므로, 무작정 풀기 전에 잠근 이유를 확인하세요. 보안 사고 대응 중인 계정을 풀면 큰 문제가 될 수 있습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;lt; 원인 3&amp;gt; 비밀번호 만료 후 grace period 종료&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비밀번호 정책에 따라 일정 기간(PASSWORD_LIFE_TIME)이 지나면 비밀번호가 만료되고, 유예 기간(PASSWORD_GRACE_TIME) 안에 변경하지 않으면 계정이 잠깁니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;진단 방법&lt;/h3&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;SELECT username, account_status, expiry_date
FROM dba_users
WHERE UPPER(username) = UPPER('scott');

-- 정책 확인
SELECT resource_name, limit
FROM dba_profiles
WHERE profile = 'DEFAULT'
  AND resource_name IN ('PASSWORD_LIFE_TIME', 'PASSWORD_GRACE_TIME');
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;account_status가 EXPIRED &amp;amp; LOCKED이면 이 케이스입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;해결 방법&lt;/h3&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;-- 새 비밀번호 부여 + 잠금 해제
ALTER USER scott IDENTIFIED BY NewPassword2026 ACCOUNT UNLOCK;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만료된 계정은 비밀번호를 재설정해야 잠금이 풀립니다. 그냥 UNLOCK만 하면 다음 로그인 시 즉시 만료 상태로 돌아갑니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;lt; 원인 4&amp;gt; Data Guard Standby 환경의 &quot;보이지 않는 잠금&quot; (★ 고급)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이건 일반 블로그에서 거의 다루지 않는 케이스인데, &lt;b&gt;Active Data Guard 환경에서 운영 중인 분들에게는 필수 지식&lt;/b&gt;입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;증상&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Primary와 Standby 양쪽 모두 dba_users.account_status = 'OPEN'&lt;/li&gt;
&lt;li&gt;그런데 Standby에 접속하면 ORA-28000 발생&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;dba_users만 보면 잠긴 흔적이 없어서 한참 헤매는 케이스입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;원인&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Active Data Guard는 read-only이기 때문에 표준 DDL로 계정 잠금을 변경할 수 없습니다. 대신 Standby용 메모리 구조에 별도로 잠금 정보가 저장됩니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;진단 방법 (Standby에서)&lt;/h3&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;SELECT rua.con_id,
       du.username,
       rua.passw_locked,
       rua.passw_lock_unlim,
       TO_CHAR(rua.passw_lock_time, 'YYYY-MM-DD HH24:MI:SS') AS locked_date
FROM v$ro_user_account rua, dba_users du
WHERE rua.userid = du.user_id
  AND (rua.passw_locked = 1 OR rua.passw_lock_unlim = 1);
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 결과에 행이 나오면 Standby에서 별도로 잠긴 것입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;해결 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;12.1.0.2 이상에서는 Active Data Guard 환경에서도 Standby 직접 잠금 해제가 가능합니다. 자세한 구문은 Oracle MOS(My Oracle Support)에서 환경별로 확인하세요. 단순 환경이라면 Primary에서 잠금 해제 후 Redo Apply를 기다리는 방법이 가장 안전합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;u&gt;재발 방지 - 자동화 스크립트가 매일 계정을 잠그는 케이스 (★ 실무 핵심)&lt;/u&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;운영 환경에서 가장 골치 아픈 시나리오입니다. &lt;b&gt;DBA가 풀어주면 1분 만에 다시 잠기는 상황.&lt;/b&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;증상&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;매일 아침 출근하면 특정 계정이 잠겨 있고, HR 시스템이 안 돌아간다는 연락을 받습니다. 풀어주면 잠시 정상이지만, 어느 순간 또 잠깁니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;원인&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;어딘가의 자동화 스크립트, 배치 작업, 또는 애플리케이션 설정에 옛날 비밀번호가 남아있어서, 일정 주기로 잘못된 비밀번호로 접속을 시도&lt;/b&gt;하고 있는 것입니다. 흔한 시나리오:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;비밀번호 변경 후 일부 서버의 설정 파일만 업데이트되고 다른 서버는 빠짐&lt;/li&gt;
&lt;li&gt;옛 백업 서버의 cron job이 살아있음&lt;/li&gt;
&lt;li&gt;개발자 PC에 저장된 SQL Developer 연결이 옛 비밀번호로 자동 시도&lt;/li&gt;
&lt;li&gt;모니터링 도구가 옛 비밀번호 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;추적 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;dba_audit_trail에서 최근 24시간 동안 실패한 로그인의 IP/호스트를 모두 추출합니다.&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;SELECT userhost, terminal, os_username,
       COUNT(*) AS fail_count,
       MIN(timestamp) AS first_attempt,
       MAX(timestamp) AS last_attempt
FROM dba_audit_trail
WHERE username = UPPER('scott')
  AND returncode = 1017
  AND timestamp &amp;gt; SYSDATE - 1
GROUP BY userhost, terminal, os_username
ORDER BY fail_count DESC;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결과의 userhost(시도한 서버)와 os_username(시도한 OS 계정)을 들고 인프라 팀과 협의해서 그 서버의 설정 파일을 잡아내야 합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;임시 우회 (긴급할 때만)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서비스 장애가 너무 심해서 시간을 벌어야 한다면, 해당 사용자만 별도 프로파일에 묶어서 잠금 정책을 풀어둘 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;-- 임시 프로파일 생성
CREATE PROFILE TEMP_NO_LOCK LIMIT
    FAILED_LOGIN_ATTEMPTS UNLIMITED
    PASSWORD_LIFE_TIME UNLIMITED;

-- 해당 사용자에게 임시 적용
ALTER USER scott PROFILE TEMP_NO_LOCK;
ALTER USER scott ACCOUNT UNLOCK;
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;경고&lt;/b&gt;: 이건 어디까지나 &lt;b&gt;임시 조치&lt;/b&gt;입니다. FAILED_LOGIN_ATTEMPTS = UNLIMITED는 &lt;b&gt;무차별 대입 공격을 무방비로 받게 되는 설정&lt;/b&gt;이므로, 원인을 찾자마자 원복해야 합니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;-- 원인 해결 후 원복
ALTER USER scott PROFILE DEFAULT;
DROP PROFILE TEMP_NO_LOCK;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;u&gt;절대 하지 말아야 할 것&lt;/u&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;블로그를 검색하면 FAILED_LOGIN_ATTEMPTS를 영구적으로 UNLIMITED로 풀어버리는 가이드가 종종 보이는데, &lt;b&gt;운영 환경에서는 절대 하지 마세요&lt;/b&gt;.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;-- ★ 운영 환경에서 절대 사용 금지
ALTER PROFILE DEFAULT LIMIT FAILED_LOGIN_ATTEMPTS UNLIMITED;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 설정은 모든 사용자에게 적용되며, 무차별 대입 공격(brute-force)을 막는 마지노선을 없애는 것입니다. 보안 감사에서도 즉시 지적되는 항목입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;권장 정책 (실무 기준)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;FAILED_LOGIN_ATTEMPTS: 5 ~ 10 사이가 일반적&lt;/li&gt;
&lt;li&gt;PASSWORD_LOCK_TIME: 1 (1일) &amp;mdash; 너무 짧으면 공격에 취약, 너무 길면 운영 부담&lt;/li&gt;
&lt;li&gt;자동화 계정은 별도 프로파일로 분리하고, 모니터링 강화&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;마무리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ORA-28000은 단순 잠금 해제로 끝나는 에러가 아니라, &lt;b&gt;&quot;왜 잠겼는가&quot;&lt;/b&gt; 를 추적해야 진짜 해결되는 에러입니다. 풀어도 계속 잠기는 환경이라면 99%는 어딘가의 자동화 스크립트나 옛 설정이 원인이며, dba_audit_trail 추적이 그 답을 알려줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;운영 환경에서는 &lt;b&gt;계정 잠금 이벤트를 모니터링하는 알림 체계&lt;/b&gt;를 갖추는 것이 가장 좋은 재발 방지입니다. 잠긴 직후에 알림이 오면 원인 추적이 훨씬 쉬워지기 때문입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비슷한 케이스를 겪으셨거나, Standby 환경에서 까다로운 잠금 이슈가 있다면 댓글로 공유해 주세요. 함께 진단해 보겠습니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;관련 글&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://www.whodo.net/entry/%EC%98%A4%EB%9D%BC%ED%81%B4-%EC%97%90%EB%9F%AC-ORA-12541-TNS-%EB%A6%AC%EC%8A%A4%EB%84%88%EA%B0%80-%EC%97%86%EC%8A%B5%EB%8B%88%EB%8B%A4-5%EA%B0%80%EC%A7%80-%EC%9B%90%EC%9D%B8%EA%B3%BC-%ED%95%B4%EA%B2%B0%EB%B0%A9%EB%B2%95-%EC%8B%A4%EB%AC%B4-DBA-%EC%A0%95%EB%A6%AC&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;ORA-12541: TNS 리스너가 없습니다 - 5가지 원인과 해결방법&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.whodo.net/entry/오라클-에러-ORA-01017-사용자명비밀번호-무효-6가지-원인과-해결방법-12c-19c-21c-차이까지&quot;&gt;ORA-01017: invalid username/password - 6가지 원인과 해결법&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>DBA 실무/Oracle(오라클)</category>
      <category>Data Guard</category>
      <category>DBA</category>
      <category>DBA실무</category>
      <category>FAILED_LOGIN_ATTEMPTS</category>
      <category>ora-28000</category>
      <category>PASSWORD_LOCK_TIME</category>
      <category>계정잠김</category>
      <category>소니스토리</category>
      <category>오라클에러</category>
      <category>오라클프로파일</category>
      <author>isony</author>
      <guid isPermaLink="true">https://isony.tistory.com/321</guid>
      <comments>https://isony.tistory.com/entry/%EC%98%A4%EB%9D%BC%ED%81%B4-%EC%97%90%EB%9F%AC-ORA-28000-%EA%B3%84%EC%A0%95%EC%9D%B4-%EC%9E%A0%EA%B2%BC%EC%8A%B5%EB%8B%88%EB%8B%A4-%EC%9E%A0%EA%B8%88-%ED%95%B4%EC%A0%9C%EB%B6%80%ED%84%B0-%EC%9E%AC%EB%B0%9C-%EB%B0%A9%EC%A7%80%EA%B9%8C%EC%A7%80-%EC%8B%A4%EB%AC%B4-DBA-%EC%A0%95%EB%A6%AC#entry321comment</comments>
      <pubDate>Sat, 30 May 2026 04:04:41 +0900</pubDate>
    </item>
    <item>
      <title>[오라클 에러] ORA-01017 사용자명/비밀번호 무효 - 6가지 원인과 해결방법 (12c, 19c, 21c 차이까지)</title>
      <link>https://isony.tistory.com/entry/%EC%98%A4%EB%9D%BC%ED%81%B4-%EC%97%90%EB%9F%AC-ORA-01017-%EC%82%AC%EC%9A%A9%EC%9E%90%EB%AA%85%EB%B9%84%EB%B0%80%EB%B2%88%ED%98%B8-%EB%AC%B4%ED%9A%A8-6%EA%B0%80%EC%A7%80-%EC%9B%90%EC%9D%B8%EA%B3%BC-%ED%95%B4%EA%B2%B0%EB%B0%A9%EB%B2%95-12c-19c-21c-%EC%B0%A8%EC%9D%B4%EA%B9%8C%EC%A7%80</link>
      <description>&lt;h1&gt;[오라클 에러] ORA-01017 사용자명/비밀번호 무효 - 6가지 원인과 해결방법 (12c, 19c, 21c 차이까지)&lt;/h1&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;테스트 환경&lt;/b&gt;: Oracle 11g / 12c / 19c / 21c&amp;nbsp;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DBA 업무 중 가장 자주 받는 문의가 &lt;b&gt;&quot;비밀번호 분명히 맞는데 ORA-01017이 떠요&quot;&lt;/b&gt; 입니다. 단순 오타라면 한 번에 풀리겠지만, 오라클 버전별 인증 방식이 다르고 특수문자 처리 문제까지 겹치면서 의외로 시간을 잡아먹는 에러입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히 &lt;b&gt;12c 이상에서 비밀번호 대소문자 구분이 강제&lt;/b&gt;되고, &lt;b&gt;21c부터는 케이스 무시 옵션 자체가 제거&lt;/b&gt;되면서 예전 매뉴얼대로 처리하다 막히는 경우가 늘었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 글에서는 ORA-01017의 6가지 원인을 분류하고, 버전별 차이점까지 정리했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;u&gt;에러 메시지 전문&lt;/u&gt;&lt;/h2&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;ORA-01017: invalid username/password; logon denied
ORA-01017: 사용자명/비밀번호가 부적합. 로그온할 수 없습니다.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SQL*Plus, JDBC, ODBC, 애플리케이션 로그 어디에서나 동일하게 발생합니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;참고&lt;/b&gt;: 이 에러는 &lt;b&gt;&quot;로그인 실패&quot;&lt;/b&gt; 만 알려줄 뿐, &lt;b&gt;&quot;왜 실패했는지&quot;&lt;/b&gt; 는 알려주지 않습니다. 보안상 의도된 동작이며, 진짜 원인은 직접 진단해야 합니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;u&gt;ORA-01017 빠른 진단 체크리스트&lt;/u&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;본격적인 해결법 전에, 30초 만에 원인을 좁히는 순서입니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;사용자명 대소문자, 비밀번호 대소문자 정확히 입력?&lt;/b&gt; &amp;rarr; 원인 1&lt;/li&gt;
&lt;li&gt;&lt;b&gt;dba_users에서 계정 존재하나?&lt;/b&gt; &amp;rarr; 원인 2&lt;/li&gt;
&lt;li&gt;&lt;b&gt;계정 상태가 OPEN인가?&lt;/b&gt; (LOCKED는 ORA-28000, EXPIRED는 ORA-28001) &amp;rarr; 원인 3&lt;/li&gt;
&lt;li&gt;&lt;b&gt;비밀번호에 특수문자(@, $, !, # 등) 포함?&lt;/b&gt; &amp;rarr; 원인 4&lt;/li&gt;
&lt;li&gt;&lt;b&gt;SYS 계정 접속인데 as sysdba 빠뜨림?&lt;/b&gt; &amp;rarr; 원인 5&lt;/li&gt;
&lt;li&gt;&lt;b&gt;최근 DB 업그레이드(11g &amp;rarr; 12c+) 했나?&lt;/b&gt; &amp;rarr; 원인 6 (가장 까다로움)&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하나씩 보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;lt; 원인 1&amp;gt; 단순 오타 + 비밀번호 대소문자&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 흔한 원인이고, 동시에 가장 간과되는 원인입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Oracle 11g부터 비밀번호는 기본적으로 대소문자를 구분합니다.&lt;/b&gt; 11g 이전 환경에 익숙한 분들이 자주 놓치는 부분입니다.&lt;/p&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;-- 둘은 서로 다른 비밀번호로 취급됨
SQL&amp;gt; conn scott/Tiger
SQL&amp;gt; conn scott/tiger
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;진단 방법&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;사용자명을 다른 곳에 그대로 타이핑해서 오타 확인&lt;/li&gt;
&lt;li&gt;비밀번호를 메모장에 한 번 쳐서 시각적으로 확인 (특히 l(엘) &amp;harr; 1(일), O &amp;harr; 0 혼동)&lt;/li&gt;
&lt;li&gt;키보드 한/영 키 상태 확인&lt;/li&gt;
&lt;li&gt;CapsLock 상태 확인&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;해결 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비밀번호를 모른다면 DBA 권한으로 재설정합니다.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;ALTER USER scott IDENTIFIED BY NewPassword2026;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비밀번호에 영문 대소문자, 숫자, 특수문자를 섞었다면 &lt;b&gt;반드시 입력 시에도 정확히 동일하게&lt;/b&gt; 입력해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;lt; 원인 2&amp;gt; 계정 자체가 없음&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;생각보다 흔한 케이스입니다. 신규 환경 구축, 스키마 이름 오기재, 또는 사용자가 다른 DB 사용자명과 혼동했을 때 발생합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;진단 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DBA 권한 계정으로 접속해서 확인합니다.&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;SELECT username, account_status, created
FROM dba_users
WHERE UPPER(username) = UPPER('찾는_사용자명');
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;행이 0건이면 &lt;b&gt;계정 자체가 없는 것&lt;/b&gt;입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;해결 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;계정이 없다면 생성합니다.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;CREATE USER scott IDENTIFIED BY Tiger2026;
GRANT CONNECT, RESOURCE TO scott;
GRANT UNLIMITED TABLESPACE TO scott;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;실무 팁&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;운영 환경에서 &quot;있어야 할 계정이 사라진 경우&quot;라면 누군가 DROP USER를 실행했을 가능성이 있습니다. dba_audit_session 또는 통합 감사(unified_audit_trail) 로그를 확인하세요. 작업 이력 추적은 사후 대응에 매우 중요합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;lt; 원인 3&amp;gt; 계정이 잠겼거나 만료됨 (다른 에러와 혼동)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;엄밀히 말하면 다음 두 케이스는 &lt;b&gt;별도의 에러 코드&lt;/b&gt;가 뜨지만, 일부 클라이언트나 애플리케이션 로그에서 ORA-01017으로 묶여서 표시되는 경우가 있어 같이 다룹니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;ORA-28000&lt;/b&gt;: 계정이 잠겨 있음 (LOCKED)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;ORA-28001&lt;/b&gt;: 비밀번호 만료 (EXPIRED)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;진단 방법&lt;/h3&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;SELECT username, account_status, lock_date, expiry_date
FROM dba_users
WHERE UPPER(username) = UPPER('사용자명');
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;account_status 컬럼이 가능한 값:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상태 의미&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;OPEN&lt;/td&gt;
&lt;td&gt;정상&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LOCKED&lt;/td&gt;
&lt;td&gt;수동 잠금&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LOCKED(TIMED)&lt;/td&gt;
&lt;td&gt;로그인 실패 횟수 초과로 잠김&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;EXPIRED&lt;/td&gt;
&lt;td&gt;비밀번호 만료&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;EXPIRED(GRACE)&lt;/td&gt;
&lt;td&gt;만료 임박 (유예기간)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;EXPIRED &amp;amp; LOCKED&lt;/td&gt;
&lt;td&gt;둘 다&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;해결 방법&lt;/h3&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;-- 잠금 해제
ALTER USER scott ACCOUNT UNLOCK;

-- 비밀번호 재설정 + 만료 해제
ALTER USER scott IDENTIFIED BY NewPassword2026;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상세한 잠금/만료 처리는 다음 글에서 따로 다룹니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;lt; 원인 4&amp;gt; 비밀번호에 특수문자 포함 (쉘 escape 문제)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비밀번호에 @, $, !, #, &amp;amp; 같은 특수문자가 포함되어 있으면, &lt;b&gt;OS 쉘이 해당 문자를 먼저 해석&lt;/b&gt;해버려서 오라클에 잘못된 값이 전달됩니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;가장 악명 높은 @ 문자&lt;/h3&gt;
&lt;pre class=&quot;autoit&quot;&gt;&lt;code&gt;# 비밀번호가 'Tiger@123' 인 경우
sqlplus scott/Tiger@123@ORCL
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이건 오라클이 사용자명=scott, 비밀번호=Tiger, DB=123@ORCL로 해석합니다. 당연히 ORA-01017 발생.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;해결 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1) 큰따옴표로 비밀번호 묶기&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;autoit&quot;&gt;&lt;code&gt;sqlplus scott/\&quot;Tiger@123\&quot;@ORCL
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Linux/Mac에서는 백슬래시 escape도 같이 써야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2) 비밀번호를 분리해서 프롬프트로 입력&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;nginx&quot;&gt;&lt;code&gt;sqlplus scott@ORCL
# Enter password: 프롬프트에서 입력
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 방법이 가장 안전합니다. 비밀번호가 셸 히스토리에도 안 남고, 특수문자 escape도 신경 쓸 필요 없습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3) Windows cmd에서는 따옴표 사용&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;perl&quot;&gt;&lt;code&gt;sqlplus scott/&quot;Tiger@123&quot;@ORCL
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;실무 팁&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쉘 스크립트에서 sqlplus를 호출할 때 비밀번호가 특수문자를 포함하면 매번 사고가 납니다. &lt;b&gt;운영 자동화 스크립트는 비밀번호를 평문 대신 wallet(시큐어 외부 비밀번호 저장소)에 저장&lt;/b&gt;하는 것을 강력히 권장합니다. 보안과 안정성을 동시에 잡습니다.&lt;/p&gt;
&lt;pre class=&quot;nginx&quot;&gt;&lt;code&gt;# wallet 사용 시
sqlplus /@ORCL_ALIAS
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;lt; 원인 5&amp;gt; SYS 계정 접속 시 as sysdba 누락&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SYS 계정은 일반 접속 방식으로는 들어갈 수 없습니다. &lt;b&gt;반드시 as sysdba 또는 as sysoper&lt;/b&gt; 를 명시해야 합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;잘못된 접속 (ORA-01017 발생)&lt;/h3&gt;
&lt;pre class=&quot;nginx&quot;&gt;&lt;code&gt;sqlplus sys/manager@ORCL
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;올바른 접속&lt;/h3&gt;
&lt;pre class=&quot;nginx&quot;&gt;&lt;code&gt;sqlplus &quot;sys/manager@ORCL as sysdba&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또는&lt;/p&gt;
&lt;pre class=&quot;actionscript&quot;&gt;&lt;code&gt;sqlplus / as sysdba
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;/만 쓰면 OS 인증(운영체제 계정으로 인증)으로 접속합니다. 서버에 직접 oracle 계정으로 들어와 있다면 비밀번호 없이도 SYS로 접속 가능합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;실무 팁&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SYSTEM 계정도 가끔 ORA-01017이 나는데, 이건 단순히 비밀번호 문제일 가능성이 높습니다. SYS는 인증 방식 차이, SYSTEM은 일반 계정과 동일하게 다루면 됩니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;lt; 원인 6&amp;gt; DB 업그레이드 후 발생 (12c+ 인증 모드 변경) ★ 핵심&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 케이스가 ORA-01017 트러블슈팅에서 가장 까다롭습니다. &lt;b&gt;다른 블로그에서 가장 자주 빠뜨리는 부분&lt;/b&gt;이기도 합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;무엇이 변했나&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Oracle 12c Release 2 (12.2)부터 인증 프로토콜이 &quot;Exclusive Mode&quot;로 기본 설정&lt;/b&gt;되었습니다. 이 모드에서는 10G 패스워드 버전(케이스 무시)을 사용할 수 없습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Oracle 21c부터는 SEC_CASE_SENSITIVE_LOGON 파라미터 자체가 제거(desupported)&lt;/b&gt; 되었습니다. 즉, 21c에서는 케이스 구분을 끄는 옵션이 아예 없습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;어떤 상황에서 문제 되나&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;11g 또는 그 이전 버전에서 운영하던 DB를 12.2+로 업그레이드한 경우, 다음 조건의 계정은 &lt;b&gt;업그레이드 직후 로그인이 안 됩니다&lt;/b&gt;.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;비밀번호를 11g 이전부터 한 번도 변경하지 않은 계정&lt;/li&gt;
&lt;li&gt;&amp;rarr; password_versions 컬럼이 10G만 가지고 있는 상태&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;진단 방법&lt;/h3&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;SELECT username, password_versions
FROM dba_users
WHERE UPPER(username) = UPPER('사용자명');
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결과 해석:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;password_versions 의미&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;10G&lt;/td&gt;
&lt;td&gt;케이스 무시 (12.2+에서 로그인 불가)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10G 11G&lt;/td&gt;
&lt;td&gt;11g 이상 호환 가능&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10G 11G 12C&lt;/td&gt;
&lt;td&gt;최신 (가장 안전)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;11G 12C&lt;/td&gt;
&lt;td&gt;12c 이후 생성/변경된 계정&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;10G만 있는 계정이 12.2+ 환경에서 ORA-01017이 뜨는 정확한 원인입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;해결 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1) 비밀번호 재설정 (권장)&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;ALTER USER scott IDENTIFIED BY NewPassword2026;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비밀번호를 변경하면 현재 인증 모드에 맞는 password version이 자동 생성됩니다. 이게 가장 깔끔합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2) 임시 우회 (12c~19c에서만 가능, 21c 불가)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;sqlnet.ora 파일에 다음 설정 추가:&lt;/p&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;SQLNET.ALLOWED_LOGON_VERSION_SERVER = 11
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리스너 또는 DB 재시작 후 적용됩니다. 단, &lt;b&gt;이건 임시 조치이며 보안 수준을 낮추는 것&lt;/b&gt;입니다. 운영 환경에서는 가능한 빨리 비밀번호 재설정 방식으로 전환하세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3) 일괄 점검 쿼리 (★ 운영자 필수)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;업그레이드 전에 영향받을 계정을 미리 식별합니다.&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- 10G 버전만 가진 계정 식별
SELECT username, password_versions
FROM dba_users
WHERE password_versions = '10G';
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 결과에 있는 모든 계정은 업그레이드 전에 비밀번호를 한 번씩 변경해 두면 사고를 막을 수 있습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;실무 팁&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;운영 DB 업그레이드 직후 갑자기 여러 애플리케이션에서 ORA-01017이 동시 다발로 발생한다면 &lt;b&gt;99% 이 케이스&lt;/b&gt;입니다. 당황하지 말고 위 쿼리부터 돌려보세요.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;u&gt;그래도 안 풀린다면&lt;/u&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 6가지로도 해결되지 않는 드문 케이스:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;클라이언트 charset과 서버 charset 불일치로 한글 비밀번호 깨짐&lt;/b&gt;: 비밀번호에 한글이 들어있다면 가능한 영문/숫자/특수문자로만 재설정 권장&lt;/li&gt;
&lt;li&gt;&lt;b&gt;failed_login_attempts 정책으로 추가 잠금&lt;/b&gt;: 비밀번호 틀린 직후 LOCKED로 전환되어 ORA-01017이 잠시 후 ORA-28000으로 바뀜&lt;/li&gt;
&lt;li&gt;&lt;b&gt;외부 인증 (OS, LDAP, Kerberos) 환경&lt;/b&gt;: dba_users의 authentication_type 컬럼 확인 필요&lt;/li&gt;
&lt;li&gt;&lt;b&gt;PDB 접속 시 service_name 누락&lt;/b&gt;: 12c+ 멀티테넌트 환경에서 sqlplus user/pw@host:port/PDB명 형식 필요&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;마무리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ORA-01017은 단순 오타부터 업그레이드 후 인증 모드 변경까지 원인의 폭이 매우 넓은 에러입니다. 한 번에 해결되지 않는다면 위 6가지 원인을 순서대로 짚어보세요. 특히 &lt;b&gt;운영 DB에서 갑자기 발생했다면 최근 변경 이력(업그레이드, 패치, 보안 정책 변경)을 먼저 확인&lt;/b&gt;하는 것이 가장 빠른 길입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비밀번호 정책과 password_versions 관리는 평소에 신경 쓰지 않다가 업그레이드 시점에 한꺼번에 터지는 경우가 많습니다. 분기에 한 번씩 dba_users 점검하는 루틴을 권장합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비슷한 케이스를 겪으셨거나, 위 방법으로 해결되지 않은 상황이 있다면 댓글로 공유해 주세요. 함께 진단해 보겠습니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;관련 글&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://www.whodo.net/entry/%EC%98%A4%EB%9D%BC%ED%81%B4-%EC%97%90%EB%9F%AC-ORA-12541-TNS-%EB%A6%AC%EC%8A%A4%EB%84%88%EA%B0%80-%EC%97%86%EC%8A%B5%EB%8B%88%EB%8B%A4-5%EA%B0%80%EC%A7%80-%EC%9B%90%EC%9D%B8%EA%B3%BC-%ED%95%B4%EA%B2%B0%EB%B0%A9%EB%B2%95-%EC%8B%A4%EB%AC%B4-DBA-%EC%A0%95%EB%A6%AC&quot;&gt;ORA-12541: TNS 리스너가 없습니다 - 5가지 원인과 해결방법&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.whodo.net/entry/오라클-에러-ORA-28000-계정이-잠겼습니다-잠금-해제부터-재발-방지까지-실무-DBA-정리&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;ORA-28000: 계정이 잠겼습니다 - 잠금 해제와 재발 방지&lt;/a&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;(작성 예정)&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>DBA 실무/Oracle(오라클)</category>
      <category>DBA</category>
      <category>DBA실무</category>
      <category>Exclusive Mode</category>
      <category>ora-01017</category>
      <category>password_version</category>
      <category>소니스토리</category>
      <category>오라클로그인</category>
      <category>오라클비밀번호</category>
      <category>오라클업그레이드</category>
      <category>오라클에러</category>
      <author>isony</author>
      <guid isPermaLink="true">https://isony.tistory.com/320</guid>
      <comments>https://isony.tistory.com/entry/%EC%98%A4%EB%9D%BC%ED%81%B4-%EC%97%90%EB%9F%AC-ORA-01017-%EC%82%AC%EC%9A%A9%EC%9E%90%EB%AA%85%EB%B9%84%EB%B0%80%EB%B2%88%ED%98%B8-%EB%AC%B4%ED%9A%A8-6%EA%B0%80%EC%A7%80-%EC%9B%90%EC%9D%B8%EA%B3%BC-%ED%95%B4%EA%B2%B0%EB%B0%A9%EB%B2%95-12c-19c-21c-%EC%B0%A8%EC%9D%B4%EA%B9%8C%EC%A7%80#entry320comment</comments>
      <pubDate>Fri, 29 May 2026 04:04:40 +0900</pubDate>
    </item>
    <item>
      <title>[오라클 에러] ORA-12541 TNS 리스너가 없습니다 - 5가지 원인과 해결방법 (실무 DBA 정리)</title>
      <link>https://isony.tistory.com/entry/%EC%98%A4%EB%9D%BC%ED%81%B4-%EC%97%90%EB%9F%AC-ORA-12541-TNS-%EB%A6%AC%EC%8A%A4%EB%84%88%EA%B0%80-%EC%97%86%EC%8A%B5%EB%8B%88%EB%8B%A4-5%EA%B0%80%EC%A7%80-%EC%9B%90%EC%9D%B8%EA%B3%BC-%ED%95%B4%EA%B2%B0%EB%B0%A9%EB%B2%95-%EC%8B%A4%EB%AC%B4-DBA-%EC%A0%95%EB%A6%AC</link>
      <description>&lt;h1&gt;[오라클 에러] ORA-12541 TNS 리스너가 없습니다 - 5가지 원인과 해결방법 (실무 DBA 정리)&lt;/h1&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;테스트 환경&lt;/b&gt;: Oracle 19c / Windows Server 2019 / Oracle Linux 8&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오라클 접속 시 가장 자주 마주치는 에러 중 하나가 바로 &lt;b&gt;ORA-12541&lt;/b&gt;입니다. 어제까지 멀쩡히 접속되던 DB에 갑자기 연결이 안 되거나, 신규 클라이언트에서 접속이 안 될 때 이 에러가 뜹니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실무에서 운영 DB를 관리하면서 이 에러를 수십 번 마주쳤는데, 원인이 의외로 다양합니다. 단순히 &quot;리스너 재시작&quot;만으로 해결되지 않는 경우도 많아서, 이번 글에서는 &lt;b&gt;5가지 원인을 분류하고 각각의 해결 방법&lt;/b&gt;까지 정리했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;급하신 분은 아래 &lt;u&gt;빠른 해결 순서&lt;/u&gt;부터 보세요.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;u&gt;에러 메시지 전문&lt;/u&gt;&lt;/h2&gt;
&lt;pre class=&quot;less&quot;&gt;&lt;code&gt;ORA-12541: TNS:리스너가 없습니다
ORA-12541: TNS:no listener
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SQL*Plus, SQL Developer, Toad, 그리고 애플리케이션 로그 등 어디에서나 이 메시지가 동일하게 나타납니다. 한글 환경에서는 한글로, 영문 환경에서는 영문으로 표시됩니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;ORA-12541은 왜 발생할까?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한 줄로 정리하면 &lt;b&gt;&quot;클라이언트가 리스너에 접속을 시도했지만, 해당 위치에 리스너가 응답하지 않는 상태&quot;&lt;/b&gt; 입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오라클은 클라이언트와 DB 인스턴스 사이에 &lt;b&gt;리스너(Listener)&lt;/b&gt; 라는 중간 프로세스가 통신을 중개합니다. 이 리스너가 죽었거나, 클라이언트가 잘못된 곳을 두드리고 있으면 ORA-12541이 발생합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원인은 크게 5가지로 나눌 수 있습니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;리스너 서비스 자체가 죽음&lt;/li&gt;
&lt;li&gt;listener.log 파일이 4GB를 초과 (Windows 환경에서 자주 발생)&lt;/li&gt;
&lt;li&gt;방화벽이 1521 포트를 차단&lt;/li&gt;
&lt;li&gt;tnsnames.ora의 HOST 값이 잘못됨&lt;/li&gt;
&lt;li&gt;다른 프로세스가 1521 포트를 점유&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하나씩 해결 방법을 보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;lt; 원인 1&amp;gt; 리스너 서비스 자체가 죽음 (가장 흔함)&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;진단 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서버에 접속해서 리스너 상태를 확인합니다.&lt;/p&gt;
&lt;pre class=&quot;ebnf&quot;&gt;&lt;code&gt;lsnrctl status
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리스너가 정상이면 다음과 같이 STATUS of the LISTENER와 함께 등록된 서비스 목록이 출력됩니다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;STATUS of the LISTENER
------------------------
Alias                     LISTENER
Version                   TNSLSNR for Linux: Version 19.0.0.0.0
Start Date                28-MAY-2026 09:15:23
Uptime                    0 days 5 hr. 12 min. 8 sec
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 리스너가 죽었다면 아래와 같은 메시지가 나옵니다.&lt;/p&gt;
&lt;pre class=&quot;less&quot;&gt;&lt;code&gt;TNS-12541: TNS:리스너가 없습니다
TNS-12560: TNS:프로토콜 어댑터 오류
TNS-00511: 리스너가 없습니다
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;해결 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Linux/Unix 환경&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;crmsh&quot;&gt;&lt;code&gt;# oracle 계정으로 실행
lsnrctl start
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Windows 환경&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Win + R &amp;rarr; services.msc 입력 &amp;rarr; OracleOraDB19Home1TNSListener 같은 이름의 서비스를 찾아 &lt;b&gt;시작&lt;/b&gt;을 누릅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또는 관리자 권한 cmd에서:&lt;/p&gt;
&lt;pre class=&quot;dos&quot;&gt;&lt;code&gt;net start OracleOraDB19Home1TNSListener
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서비스 이름은 오라클 버전과 설치 옵션에 따라 다릅니다. Oracle...TNSListener로 시작하는 이름을 찾으세요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;실무 팁&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;운영 환경에서 리스너가 갑자기 죽었다면 &lt;b&gt;단순히 재시작만 하지 말고 죽은 원인부터 확인&lt;/b&gt;하세요. 그냥 살려두면 며칠 뒤 똑같이 죽습니다. 다음 항목인 listener.log 확인이 첫 번째 해야 할 일입니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;lt; 원인 2&amp;gt; listener.log 파일이 4GB 초과 (간과하기 쉬운 케이스)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이건 &lt;b&gt;Windows 32bit 환경 또는 일부 파일시스템 제약이 있는 환경&lt;/b&gt;에서 발생합니다. listener.log 파일이 4GB를 넘으면 리스너가 로그를 더 쓸 수 없어서 &lt;b&gt;자체적으로 죽거나, 죽은 것처럼 응답하지 않는 상태&lt;/b&gt;가 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;운영한 지 오래된 DB 서버에서 &quot;어느 날 갑자기&quot; ORA-12541이 발생한다면 이걸 가장 먼저 의심하세요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;진단 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;listener.log 위치는 lsnrctl status의 출력에서 확인할 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;gradle&quot;&gt;&lt;code&gt;Listener Log File         /app/oracle/diag/tnslsnr/서버명/listener/alert/log.xml
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또는 기본 경로:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Linux&lt;/b&gt;: $ORACLE_BASE/diag/tnslsnr/{호스트명}/listener/trace/listener.log&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Windows&lt;/b&gt;: %ORACLE_BASE%\diag\tnslsnr\{호스트명}\listener\trace\listener.log&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 파일 크기를 확인해서 4GB에 가깝거나 초과했다면 원인이 맞습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;해결 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1) 리스너 중지&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;lsnrctl stop
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2) listener.log 백업 후 삭제 (또는 이름 변경)&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;# Linux
mv listener.log listener.log.20260528.bak

# Windows
ren listener.log listener.log.20260528.bak
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3) 리스너 재시작&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;crmsh&quot;&gt;&lt;code&gt;lsnrctl start
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;재발 방지 (★ 실무 핵심)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이게 한 번 발생했다면 다음에 또 발생합니다. 영구 해결을 위해 &lt;b&gt;로그 로테이션을 자동화&lt;/b&gt;해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 간단한 방법은 ADRCI(Automatic Diagnostic Repository Command Interpreter)로 보관 정책을 설정하는 것입니다.&lt;/p&gt;
&lt;pre class=&quot;jboss-cli&quot;&gt;&lt;code&gt;adrci
ADRCI&amp;gt; show homes
ADRCI&amp;gt; set home diag/tnslsnr/{호스트명}/listener
ADRCI&amp;gt; set control (SHORTP_POLICY = 168, LONGP_POLICY = 720)
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SHORTP_POLICY는 시간 단위(기본 720시간=30일), LONGP_POLICY는 일 단위(기본 8760시간=365일)입니다. 위 예시는 trace를 7일, alert를 30일만 보관합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또는 더 간단하게, listener.ora에 로깅 비활성화 옵션을 줘서 트래픽 로그를 최소화할 수도 있습니다(단, 보안 감사가 필요한 환경에서는 비추천).&lt;/p&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;LOGGING_LISTENER = OFF
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;lt; 원인 3&amp;gt; 방화벽이 1521 포트를 차단&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;신규로 구축한 서버, 또는 보안 정책 변경 직후에 자주 발생합니다. 리스너는 살아있는데 클라이언트의 패킷이 서버까지 도달하지 못하는 상황입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;진단 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;클라이언트에서 telnet으로 포트 도달 여부 확인&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;x86asm&quot;&gt;&lt;code&gt;telnet {DB서버 IP} 1521
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;연결이 즉시 끊기거나 &quot;연결할 수 없습니다&quot;가 나오면 방화벽 문제일 가능성이 큽니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;서버에서 포트 LISTEN 상태 확인&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;1c&quot;&gt;&lt;code&gt;# Linux
netstat -tlnp | grep 1521
ss -tlnp | grep 1521

# Windows
netstat -ano | findstr 1521
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;0.0.0.0:1521 또는 *:1521로 LISTEN 상태가 보이면 서버는 정상이고, 방화벽이 막은 겁니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;해결 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Linux (firewalld)&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;dockerfile&quot;&gt;&lt;code&gt;sudo firewall-cmd --permanent --add-port=1521/tcp
sudo firewall-cmd --reload
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Linux (iptables)&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;sudo iptables -A INPUT -p tcp --dport 1521 -j ACCEPT
sudo service iptables save
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Windows&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Windows Defender 방화벽 &amp;rarr; 고급 설정 &amp;rarr; 인바운드 규칙 &amp;rarr; 새 규칙 &amp;rarr; 포트 &amp;rarr; TCP / 1521&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;회사 네트워크 방화벽이 막는 경우라면 인프라 팀에 1521 포트 오픈 요청을 해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;lt; 원인 4&amp;gt; tnsnames.ora의 HOST 값이 잘못됨&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클라이언트의 tnsnames.ora 파일에 적힌 HOST가 잘못되어 있으면, 엉뚱한 곳을 두드리니 당연히 ORA-12541이 납니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히 다음 케이스에서 자주 발생합니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;서버 IP가 변경되었는데 tnsnames.ora를 안 고침&lt;/li&gt;
&lt;li&gt;localhost로 설정했지만 다른 PC에서 접속 시도&lt;/li&gt;
&lt;li&gt;DNS 환경이라 호스트명이 변경됨&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;진단 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클라이언트 tnsnames.ora 위치:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Windows&lt;/b&gt;: %ORACLE_HOME%\network\admin\tnsnames.ora&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Linux&lt;/b&gt;: $ORACLE_HOME/network/admin/tnsnames.ora&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파일을 열어서 접속하려는 TNS 별칭의 HOST 값을 확인합니다.&lt;/p&gt;
&lt;pre class=&quot;lisp&quot;&gt;&lt;code&gt;ORCL =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.10.5)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = ORCL)
    )
  )
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;해결 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1) tnsping으로 별칭 동작 확인&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;ebnf&quot;&gt;&lt;code&gt;tnsping ORCL
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;확인(10밀리초) 같은 응답이 나오면 정상. 안 나오면 HOST/PORT를 의심합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2) HOST를 실제 IP로 수정&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;localhost로 되어 있다면 실제 서버 IP나 호스트명으로 변경합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3) ping으로 IP 도달 여부 추가 확인&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;ping 192.168.10.5
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;실무 팁&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서버 마이그레이션 직후 클라이언트마다 tnsnames.ora를 일일이 고치는 게 번거롭다면, &lt;b&gt;DNS에 별칭을 만들어 두는 방식&lt;/b&gt;을 권장합니다. 이렇게 하면 IP가 바뀌어도 DNS만 갱신하면 끝입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;lt; 원인 5&amp;gt; 다른 프로세스가 1521 포트를 점유&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;흔하지는 않지만, 1521 포트를 다른 프로세스가 먼저 점유한 경우 리스너가 시작 자체를 못 합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;진단 방법&lt;/h3&gt;
&lt;pre class=&quot;properties&quot;&gt;&lt;code&gt;# Linux
sudo lsof -i :1521
sudo netstat -tlnp | grep 1521

# Windows
netstat -ano | findstr 1521
tasklist | findstr {PID}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;tnslsnr 또는 TNSLSNR.exe 외의 다른 프로세스가 1521을 잡고 있다면 그게 원인입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;해결 방법&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 흔한 시나리오는 &lt;b&gt;이전에 종료된 리스너의 좀비 프로세스가 남아있는 경우&lt;/b&gt;입니다. 해당 PID를 강제 종료합니다.&lt;/p&gt;
&lt;pre class=&quot;jboss-cli&quot;&gt;&lt;code&gt;# Linux
sudo kill -9 {PID}

# Windows (관리자 권한)
taskkill /F /PID {PID}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 다른 정상 서비스가 1521을 쓰고 있다면, 오라클 리스너의 포트를 변경하는 것이 안전합니다. listener.ora에서 포트를 1522 등으로 변경하고, 클라이언트의 tnsnames.ora도 같이 변경합니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;u&gt;빠른 해결 체크리스트&lt;/u&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5분 안에 원인을 좁히는 순서입니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;서버에서 lsnrctl status 실행&lt;/b&gt; &amp;rarr; 리스너 살아있나?
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;죽었으면 &amp;rarr; 원인 1 또는 2&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;클라이언트에서 telnet {IP} 1521&lt;/b&gt; &amp;rarr; 포트 도달하나?
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;안 되면 &amp;rarr; 원인 3&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;tnsping {별칭} 실행&lt;/b&gt; &amp;rarr; 별칭 해석되나?
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;실패면 &amp;rarr; 원인 4&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;listener.log 파일 크기&lt;/b&gt; &amp;rarr; 4GB 근처인가?
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;그렇다면 &amp;rarr; 원인 2 (이 케이스는 한 번 터지면 또 터집니다)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;netstat으로 1521 점유 프로세스 확인&lt;/b&gt; &amp;rarr; tnslsnr 맞나?
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;다른 프로세스면 &amp;rarr; 원인 5&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;u&gt;그래도 안 풀린다면&lt;/u&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 5가지로도 해결되지 않는 드문 케이스:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Windows 사용자명에 한글/공백 포함&lt;/b&gt;: 오라클이 환경변수 해석을 못 하는 경우가 있습니다. 사용자명 변경 또는 별도 계정 생성으로 해결됩니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;ORACLE_HOME 환경변수가 잘못 설정됨&lt;/b&gt;: 여러 오라클 버전을 설치한 환경에서 발생. echo $ORACLE_HOME(Linux) 또는 echo %ORACLE_HOME%(Windows)으로 확인.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;호스트명이 IP로 풀리지 않음&lt;/b&gt;: /etc/hosts 또는 Windows hosts 파일에 호스트명-IP 매핑 추가.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;마무리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ORA-12541은 결국 &lt;b&gt;&quot;리스너에 접속이 안 됨&quot;&lt;/b&gt; 이라는 한 가지 증상이지만, 원인은 서버, 네트워크, 클라이언트 설정 어디서나 발생할 수 있습니다. 무작정 리스너 재시작부터 하기보다는, 위 체크리스트 순서대로 진단하시면 5분 안에 원인을 찾을 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히 &lt;b&gt;운영 환경에서 갑자기 발생한 경우 원인 2(listener.log 4GB)&lt;/b&gt; 를 가장 먼저 확인하세요. 재발률이 가장 높은 케이스입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비슷한 케이스를 겪으셨거나, 위 방법으로도 해결이 안 되는 상황이 있다면 댓글로 공유해 주세요. 함께 해결책을 찾아보겠습니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;관련 글&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://www.whodo.net/entry/오라클-에러-ORA-01017-사용자명비밀번호-무효-6가지-원인과-해결방법-12c-19c-21c-차이까지&quot;&gt;ORA-01017: invalid username/password - 6가지 원인과 해결법&lt;/a&gt; (작성 예정)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.whodo.net/entry/오라클-에러-ORA-28000-계정이-잠겼습니다-잠금-해제부터-재발-방지까지-실무-DBA-정리&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;ORA-28000: 계정이 잠겼습니다 - 잠금 해제와 재발 방지&lt;/a&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;(작성 예정)&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>DBA 실무/Oracle(오라클)</category>
      <category>DBA</category>
      <category>DBA실무</category>
      <category>lsnrctl</category>
      <category>ORA-12541</category>
      <category>TNS리스너</category>
      <category>소니스토리</category>
      <category>오라클</category>
      <category>오라클에러</category>
      <category>오라클트러블슈팅</category>
      <author>isony</author>
      <guid isPermaLink="true">https://isony.tistory.com/319</guid>
      <comments>https://isony.tistory.com/entry/%EC%98%A4%EB%9D%BC%ED%81%B4-%EC%97%90%EB%9F%AC-ORA-12541-TNS-%EB%A6%AC%EC%8A%A4%EB%84%88%EA%B0%80-%EC%97%86%EC%8A%B5%EB%8B%88%EB%8B%A4-5%EA%B0%80%EC%A7%80-%EC%9B%90%EC%9D%B8%EA%B3%BC-%ED%95%B4%EA%B2%B0%EB%B0%A9%EB%B2%95-%EC%8B%A4%EB%AC%B4-DBA-%EC%A0%95%EB%A6%AC#entry319comment</comments>
      <pubDate>Thu, 28 May 2026 08:17:34 +0900</pubDate>
    </item>
    <item>
      <title>2026년05월24일 주일예배 (이재훈목사님) - 1부</title>
      <link>https://isony.tistory.com/entry/2026%EB%85%8405%EC%9B%9424%EC%9D%BC-%EC%A3%BC%EC%9D%BC%EC%98%88%EB%B0%B0-%EC%9D%B4%EC%9E%AC%ED%9B%88%EB%AA%A9%EC%82%AC%EB%8B%98-1%EB%B6%80</link>
      <description>&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;2026년05월24일 주일예배 (이재훈목사님) - 1부&lt;/h2&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;주의 말씀 : 나를 따르라&amp;nbsp; (2)&lt;/h2&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;붙어있음, 그것이 곧 열매이다.&lt;/h2&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;성경 :&amp;nbsp; 요한복음 15:1 ~ 8 말씀 (출처:우리말성경)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&amp;lt; 성경 &amp;gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;15:1 &amp;ldquo;나는 참 포도나무요 내 아버지는 농부시다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;15:2 내게 붙어 있으면서도 열매를 맺지 못하는 가지는 아버지께서 다 자르실 것이요, 열매를 맺는 가지는 더 많은 열매를 맺도록 깨끗하게 손질하신다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;15:3 너희는 내가 너희에게 말한 그 말로 인해 이미 깨끗해졌다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;15:4 내 안에 머물러 있으라. 그러면 나도 너희 안에 머물러 있을 것이다. 가지가 포도나무에 붙어 있지 않으면 스스로 열매를 맺지 못하는 것처럼 너희도 내 안에 있지 않으면 열매를 맺을 수 없다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;15:5 나는 포도나무요 너희는 가지다. 그가 내 안에 있고 내가 그 안에 있으면 그 사람은 많은 열매를 맺는다. 나를 떠나서는 너희가 아무것도 할 수 없다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;15:6 누구든지 내 안에 있지 않으면 그 사람은 쓸모없는 가지처럼 버려져 말라 버린다. 사람들이 그런 가지들은 모아다가 불 속에 던져 태워 버린다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;15:7 만일 너희가 내 안에 있고 내 말이 너희 안에 있으면 너희가 원하는 것이 무엇이든지 구하라. 그러면 그대로 이루어질 것이다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;15:8 너희가 열매를 많이 맺으면 내 제자가 되고 이것으로 아버지께서 영광을 받으실 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&amp;lt; 예배 영상 &amp;gt;&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=8d-XKf90bos&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.youtube.com/watch?v=8d-XKf90bos&lt;/a&gt;&lt;/b&gt;&lt;/p&gt;
&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignCenter&quot; data-video-host=&quot;youtube&quot; data-video-url=&quot;https://www.youtube.com/watch?v=8d-XKf90bos&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/cXxWkI/dJMb9c9DWEw/d6DWsKaI2hcfSK6KnNrKHk/img.jpg?width=480&amp;amp;height=360&amp;amp;face=222_98_271_151,https://scrap.kakaocdn.net/dn/JVTND/dJMb9hC7iDz/KFKSV3qgGs6OLQZxkikTOK/img.jpg?width=480&amp;amp;height=360&amp;amp;face=225_97_271_147,https://scrap.kakaocdn.net/dn/ixu6c/dJMb9efj4Hd/2uiUmYr1AiVRUkXUYTgUi1/img.jpg?width=480&amp;amp;height=360&amp;amp;face=222_98_271_151&quot; data-video-width=&quot;480&quot; data-video-height=&quot;360&quot; data-video-origin-width=&quot;480&quot; data-video-origin-height=&quot;360&quot; data-ke-mobilestyle=&quot;widthContent&quot; data-video-title=&quot;주일예배2026 05 24&quot; data-original-url=&quot;&quot;&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/8d-XKf90bos&quot; width=&quot;480&quot; height=&quot;360&quot; frameborder=&quot;&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;figcaption style=&quot;display: none;&quot;&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>성경과 QT/주일예배(온누리교회)</category>
      <category>CGNTV</category>
      <category>나를따르라</category>
      <category>소니스토리</category>
      <category>예배영상</category>
      <category>온누리교회</category>
      <category>요한복음</category>
      <category>우리말성경</category>
      <category>이재훈목사</category>
      <category>주일예배</category>
      <author>isony</author>
      <guid isPermaLink="true">https://isony.tistory.com/318</guid>
      <comments>https://isony.tistory.com/entry/2026%EB%85%8405%EC%9B%9424%EC%9D%BC-%EC%A3%BC%EC%9D%BC%EC%98%88%EB%B0%B0-%EC%9D%B4%EC%9E%AC%ED%9B%88%EB%AA%A9%EC%82%AC%EB%8B%98-1%EB%B6%80#entry318comment</comments>
      <pubDate>Sun, 24 May 2026 08:07:44 +0900</pubDate>
    </item>
    <item>
      <title>2026년05월17일 주일예배 (이재훈목사님) - 1부</title>
      <link>https://isony.tistory.com/entry/2026%EB%85%8405%EC%9B%9417%EC%9D%BC-%EC%A3%BC%EC%9D%BC%EC%98%88%EB%B0%B0-%EC%9D%B4%EC%9E%AC%ED%9B%88%EB%AA%A9%EC%82%AC%EB%8B%98-1%EB%B6%80</link>
      <description>&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;2026년05월17일 주일예배 (이재훈목사님) - 1부&lt;/h2&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;주의 말씀 : 나를 따르라&amp;nbsp; (1) 그리스도를 따를 수 있는 단 하의 근거&lt;/h2&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;성경 :&amp;nbsp; 로마서 6:1 ~ 11 말씀 (출처:우리말성경)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&amp;lt; 성경 &amp;gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;6:1 그러면 우리가 무슨 말을 해야 하겠습니까? 은혜를 더하게 하려고 죄 가운데 머물러 있어야 하겠습니까?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;6:2 결코 그럴 수 없습니다. 죄에 대해 죽은 우리가 어떻게 죄 가운데 그대로 살겠습니까?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;6:3 그리스도와 연합해 세례를 받은 우리는 모두 그리스도의 죽으심과 연합해 세례를 받은 줄을 알지 못합니까?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;6:4 그러므로 우리는 그리스도의 죽으심과 연합해 세례를 받음으로써 그분과 함께 묻혔습니다. 이는 그리스도께서 아버지의 영광으로 인해 죽은 자들 가운데서 살리심을 받은 것처럼 우리도 또한 새 생명 가운데서 살게 하려는 것입니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;6:5 우리가 그리스도의 죽으심과 같은 죽음으로 그분과 연합한 사람이 됐다면 분명히 우리는 그리스도의 부활하심과 같은 부활로도 그분과 연합한 사람이 될 것입니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;6:6 우리의 옛 사람이 십자가에 못 박힌 것은 죄의 몸이 멸해져 우리가 더 이상 죄의 종이 되지 않게 하려는 것임을 압니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;6:7 이는 죽은 사람은 이미 죄에서 벗어났기 때문입니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;6:8 우리가 그리스도와 함께 죽었다면 또한 그분과 함께 살 것을 믿습니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;6:9 우리가 알기로 죽은 사람 가운데서 살리심을 받은 그리스도께서는 다시 죽지 않으시고 죽음이 더 이상 그분을 지배하지 못합니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;6:10 그리스도께서 죽으신 것은 죄에 대해 단번에 죽으신 것이요, 그분이 사시는 것은 하나님께 대해 사시는 것입니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;u&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;6:11 이와 같이 여러분도 자신을 죄에 대해서는 죽은 자요, 하나님께 대해서는 그리스도 예수 안에서 산 자로 여기십시오.&lt;/span&gt; &lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&amp;lt; 예배 영상 &amp;gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=McEmBJavR-4&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.youtube.com/watch?v=McEmBJavR-4&lt;/a&gt;&lt;/p&gt;
&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignCenter&quot; data-video-host=&quot;youtube&quot; data-video-url=&quot;https://www.youtube.com/watch?v=McEmBJavR-4&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/dAoGyh/dJMb86O61oJ/qtOYWIE5AEkjukxNaMvmIK/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=584_128_760_320,https://scrap.kakaocdn.net/dn/O5rSs/dJMb9aKKkd2/k4OBXMb0CkrYjeM6PkAfwk/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=584_128_760_320,https://scrap.kakaocdn.net/dn/bJrLQL/dJMb86O61oK/aJDfDkdzMWL9KfkJKrScJ1/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=584_128_760_320&quot; data-video-width=&quot;860&quot; data-video-height=&quot;484&quot; data-video-origin-width=&quot;860&quot; data-video-origin-height=&quot;484&quot; data-ke-mobilestyle=&quot;widthContent&quot; data-video-title=&quot;주일예배2026 05 17&quot; data-original-url=&quot;&quot;&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/McEmBJavR-4&quot; width=&quot;860&quot; height=&quot;484&quot; frameborder=&quot;&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;figcaption style=&quot;display: none;&quot;&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://youtu.be/McEmBJavR-4&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://youtu.be/McEmBJavR-4&lt;/a&gt;&lt;/p&gt;
&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignCenter&quot; data-video-host=&quot;youtube&quot; data-video-url=&quot;https://www.youtube.com/watch?v=McEmBJavR-4&quot; data-video-width=&quot;0&quot; data-video-height=&quot;0&quot; data-video-origin-width=&quot;0&quot; data-video-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot; data-video-title=&quot;주일예배2026 05 17&quot; data-video-thumbnail=&quot;&quot; data-original-url=&quot;&quot;&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/McEmBJavR-4&quot; width=&quot;0&quot; height=&quot;0&quot; frameborder=&quot;&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;figcaption style=&quot;display: none;&quot;&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>성경과 QT/주일예배(온누리교회)</category>
      <category>CGNTV</category>
      <category>나를따르라</category>
      <category>로마서</category>
      <category>소니스토리</category>
      <category>예배영상</category>
      <category>온누리교회</category>
      <category>우리말성경</category>
      <category>이재훈목사</category>
      <category>주일예배</category>
      <author>isony</author>
      <guid isPermaLink="true">https://isony.tistory.com/317</guid>
      <comments>https://isony.tistory.com/entry/2026%EB%85%8405%EC%9B%9417%EC%9D%BC-%EC%A3%BC%EC%9D%BC%EC%98%88%EB%B0%B0-%EC%9D%B4%EC%9E%AC%ED%9B%88%EB%AA%A9%EC%82%AC%EB%8B%98-1%EB%B6%80#entry317comment</comments>
      <pubDate>Sun, 17 May 2026 08:12:25 +0900</pubDate>
    </item>
    <item>
      <title>2026년05월10일 주일예배 (이재훈목사님) - 1부</title>
      <link>https://isony.tistory.com/entry/2026%EB%85%8405%EC%9B%9410%EC%9D%BC-%EC%A3%BC%EC%9D%BC%EC%98%88%EB%B0%B0-%EC%9D%B4%EC%9E%AC%ED%9B%88%EB%AA%A9%EC%82%AC%EB%8B%98-1%EB%B6%80</link>
      <description>&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;2026년05월10일 주일예배 (이재훈목사님) - 1부&lt;/h2&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;주의 말씀 : 상한 갈대 위에 드리운 날개&lt;/h2&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;성경 :&amp;nbsp; 롯기 2:1 ~ 13 말씀 (출처:우리말성경)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&amp;lt; 성경 &amp;gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;2:1 나오미에게는 남편 쪽 친척으로 엘리멜렉 가문 가운데 큰 부자가 하나 있었는데 그 이름은 보아스였습니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;2:2 모압 여자 룻이 나오미에게 말했습니다. &amp;ldquo;밭에 갔다 오겠습니다. 누군가 제게 잘 대해 주는 사람을 만나면 그 사람을 따라가 이삭을 주워 오겠습니다.&amp;rdquo; 그러자 나오미가 그녀에게 말했습니다. &amp;ldquo;내 딸아, 잘 갔다 오너라.&amp;rdquo;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;2:3 그러자 그녀는 밖으로 나가 추수하는 사람들을 따라 밭에서 이삭을 줍기 시작했습니다. 그런데 우연히도 그녀가 일하고 있던 곳은 엘리멜렉의 친척인 보아스의 밭이었습니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;2:4 바로 그때 보아스가 베들레헴에서 도착해 추수하는 사람들에게 말했습니다. &amp;ldquo;여호와께서 너희와 함께하시기를 원한다!&amp;rdquo; 그들이 대답했습니다. &amp;ldquo;여호와께서 주인어른께 복 주시기를 빕니다.&amp;rdquo;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;2:5 보아스가 추수하는 사람들의 감독에게 물었습니다. &amp;ldquo;저 젊은 여자는 누구요?&amp;rdquo;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;2:6 추수하는 사람들의 감독이 대답했습니다. &amp;ldquo;나오미와 함께 모압에서 나온 그 모압 여자입니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;2:7 그녀가 추수하는 사람들을 따라가며 이삭을 줍게 해 달라고 말했습니다. 그러더니 밭에 나가 아까 잠깐 집에서 쉰 것 외에는 아침부터 지금까지 저렇게 계속 열심히 일하고 있습니다.&amp;rdquo;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;2:8 그러자 보아스가 룻에게 말했습니다. &amp;ldquo;내 딸이여, 내 말을 들어 보시오. 다른 밭에 가서 이삭을 줍지 말고 여기서 멀리 가지도 말고 여기 내 여종들과 함께 일하시오.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;2:9 사람들이 추수하는 이 밭을 잘 살피며 따라 다니시오. 내가 사람들에게도 당신을 건드리지 말라고 말해 두었소. 그리고 목이 마르면 가서 젊은이들이 채워 놓은 물병에서 물을 따라 마셔도 되오.&amp;rdquo;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;2:10 이 말에 룻은 얼굴을 땅에 대고 엎드려 말했습니다. &amp;ldquo;내가 이방 사람인데도 어째서 친절을 베풀어 주시고 돌봐 주십니까?&amp;rdquo;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;2:11 보아스가 대답했습니다. &amp;ldquo;남편이 죽은 후 당신이 시어머니에게 한 일에 대해 모두 들었소. 당신의 부모와 고향을 떠나 알지도 못하는 민족과 함께 살려고 온 것 말이오.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;2:12 여호와께서 당신의 행실에 대해 갚아 주실 것이오. 당신이 이스라엘의 하나님 여호와의 날개 아래로 보호받으러 왔으니 그분께서 당신에게 넉넉히 갚아 주실 것이오.&amp;rdquo;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;2:13 룻이 말했습니다. &amp;ldquo;내 주여, 내가 당신 앞에서 은총을 얻기 원합니다. 내가 당신의 여종들만도 못한데 나를 위로해 주시고 이 여종에게 다정하게 말씀해 주셨습니다.&amp;rdquo;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&amp;lt; 예배 영상 &amp;gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;a href=&quot;https://youtu.be/6bNickgzuQ0&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://youtu.be/6bNickgzuQ0&lt;/a&gt;&lt;/b&gt;&lt;/p&gt;
&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignCenter&quot; data-video-host=&quot;youtube&quot; data-video-url=&quot;https://www.youtube.com/watch?v=6bNickgzuQ0&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/oLkQU/dJMb8SpMmmW/l0rxlH9K24T3r7aNspJDJ1/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=576_144_720_300,https://scrap.kakaocdn.net/dn/bdpg3x/dJMb9c9Cgq2/ivJ92RA91CltdGz474LtS0/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=576_144_720_300,https://scrap.kakaocdn.net/dn/bPU1di/dJMb9iILmxi/EYl1wNizFehCBXDzqQwdMk/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=576_144_720_300&quot; data-video-width=&quot;860&quot; data-video-height=&quot;484&quot; data-video-origin-width=&quot;860&quot; data-video-origin-height=&quot;484&quot; data-ke-mobilestyle=&quot;widthContent&quot; data-video-title=&quot;주일예배2026 05 10&quot; data-original-url=&quot;&quot;&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/6bNickgzuQ0&quot; width=&quot;860&quot; height=&quot;484&quot; frameborder=&quot;&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;figcaption style=&quot;display: none;&quot;&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&amp;lt; 말씀요약 &amp;gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;하나님은 가정 안에서 때로 불행해 보이는 과정을 통해 아름다운 결말로 섭리하신다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. 하나님은 우리가 절망할때 이미 먼저 움직이시고 계신다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. 하나님은 절망한 가정에 기대 이상의 넘치는 은혜를 보내신다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. 믿음의 눈이 열릴때 하나님의 예비하심이 보인다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>성경과 QT/주일예배(온누리교회)</category>
      <category>CGNTV</category>
      <category>롯기</category>
      <category>상항갈대</category>
      <category>소니스토리</category>
      <category>예배영상</category>
      <category>온누리교회</category>
      <category>우리말성경</category>
      <category>이재훈목사</category>
      <category>주일예배</category>
      <category>하나님날개</category>
      <author>isony</author>
      <guid isPermaLink="true">https://isony.tistory.com/316</guid>
      <comments>https://isony.tistory.com/entry/2026%EB%85%8405%EC%9B%9410%EC%9D%BC-%EC%A3%BC%EC%9D%BC%EC%98%88%EB%B0%B0-%EC%9D%B4%EC%9E%AC%ED%9B%88%EB%AA%A9%EC%82%AC%EB%8B%98-1%EB%B6%80#entry316comment</comments>
      <pubDate>Sun, 10 May 2026 08:07:02 +0900</pubDate>
    </item>
    <item>
      <title>2026년05월03일 주일예배 (이재훈목사님) - 1부</title>
      <link>https://isony.tistory.com/entry/2026%EB%85%8405%EC%9B%9403%EC%9D%BC-%EC%A3%BC%EC%9D%BC%EC%98%88%EB%B0%B0-%EC%9D%B4%EC%9E%AC%ED%9B%88%EB%AA%A9%EC%82%AC%EB%8B%98-1%EB%B6%80</link>
      <description>&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;2026년05월03일 주일예배 (이재훈목사님) - 1부&lt;/h2&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;주의 말씀 : 하나님의 뜻을 행하는 가족&lt;/h2&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;성경 :&amp;nbsp; 마가복음(Mark) 3:31 - 35 말씀 (출처:우리말성경)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&amp;lt; 성경 &amp;gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;3:31 그때 예수의 어머니와 형제들이 찾아왔습니다. 그들은 밖에 서서 사람을 시켜 예수를 불렀습니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;3:32 많은 사람들이 예수 곁에 둘러앉아 있었는데 그들이 예수께 말했습니다. &amp;ldquo;보십시오. 선생님의 어머니와 형제들이 밖에서 선생님을 찾고 계십니다.&amp;rdquo;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;3:33 예수께서 그들에게 물으셨습니다. &amp;ldquo;누가 내 어머니고 내 형제들이냐?&amp;rdquo;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;3:34 그러고는 곁에 둘러앉은 그들을 보며 말씀하셨습니다. &amp;ldquo;보라. 내 어머니와 내 형제들이다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;3:35 누구든지 하나님의 뜻을 행하는 사람이 바로 내 형제요, 자매요, 어머니다.&amp;rdquo;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&amp;lt; 예배 영상 &amp;gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;a href=&quot;https://youtu.be/RFRxYGv9Zmw&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://youtu.be/RFRxYGv9Zmw&lt;/a&gt;&lt;/b&gt;&lt;/p&gt;
&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignCenter&quot; data-video-host=&quot;youtube&quot; data-video-url=&quot;https://www.youtube.com/watch?v=RFRxYGv9Zmw&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/c6Ozoo/dJMb86O5mo8/Ycdshg9IPtjtafG1cb1IJ0/img.jpg?width=480&amp;amp;height=360&amp;amp;face=220_91_287_164,https://scrap.kakaocdn.net/dn/cmSALj/dJMb9fZyU7p/YyhFkmXMqpznDizbvxg0AK/img.jpg?width=480&amp;amp;height=360&amp;amp;face=220_91_287_164,https://scrap.kakaocdn.net/dn/dgHudp/dJMb9kmgjxb/GDljYVwpmWz7Yds5EB5bwk/img.jpg?width=480&amp;amp;height=360&amp;amp;face=220_91_287_164&quot; data-video-width=&quot;480&quot; data-video-height=&quot;360&quot; data-video-origin-width=&quot;480&quot; data-video-origin-height=&quot;360&quot; data-ke-mobilestyle=&quot;widthContent&quot; data-video-title=&quot;Sony&quot; data-original-url=&quot;&quot;&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/RFRxYGv9Zmw&quot; width=&quot;480&quot; height=&quot;360&quot; frameborder=&quot;&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;figcaption style=&quot;display: none;&quot;&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>성경과 QT/주일예배(온누리교회)</category>
      <category>CGNTV</category>
      <category>가족</category>
      <category>마가복음</category>
      <category>소니스토리</category>
      <category>영상예배</category>
      <category>온누리교회</category>
      <category>우리말성경</category>
      <category>이재훈목사</category>
      <category>주일예배</category>
      <category>하나님의뜻</category>
      <author>isony</author>
      <guid isPermaLink="true">https://isony.tistory.com/315</guid>
      <comments>https://isony.tistory.com/entry/2026%EB%85%8405%EC%9B%9403%EC%9D%BC-%EC%A3%BC%EC%9D%BC%EC%98%88%EB%B0%B0-%EC%9D%B4%EC%9E%AC%ED%9B%88%EB%AA%A9%EC%82%AC%EB%8B%98-1%EB%B6%80#entry315comment</comments>
      <pubDate>Sun, 3 May 2026 15:39:44 +0900</pubDate>
    </item>
    <item>
      <title>2026년04월26일 주일예배 (이재훈목사님) - 1부</title>
      <link>https://isony.tistory.com/entry/2026%EB%85%8404%EC%9B%9426%EC%9D%BC-%EC%A3%BC%EC%9D%BC%EC%98%88%EB%B0%B0-%EC%9D%B4%EC%9E%AC%ED%9B%88%EB%AA%A9%EC%82%AC%EB%8B%98-1%EB%B6%80</link>
      <description>&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;2026년04월26일 주일예배 (이재훈목사님) - 1부&lt;/h2&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;주의 말씀 : 버릴것이 없는 인생&lt;/h2&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;성경 :&amp;nbsp; 요한복음(John) 6:11 - 13 말씀 (출처:우리말성경)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&amp;lt; 성경 &amp;gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;6:11 예수께서는 빵을 들고 감사기도를 드리신 후 앉아 있는 사람들에게 원하는 만큼씩 나눠 주셨습니다. 물고기를 가지고도 똑같이 하셨습니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;6:12 그들이 모두 배불리 먹은 뒤에 예수께서 제자들에게 말씀하셨습니다. &amp;ldquo;남은 것은 하나도 버리지 말고 모아 두라.&amp;rdquo;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;6:13 그리하여 그들이 남은 것을 모아 보니 보리빵 다섯 개로 먹고 남은 것이 12바구니에 가득 찼습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&amp;lt; 말씀요약 &amp;gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&quot;버리지말라&quot; - &quot;하나도 잃어버려지지 않도록 하라&quot;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. 하나님은 작은 것도 버리지 않으시는 분이시다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. 배부름으로 영적 긴장감이 버려지지 않도록 해야 한다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. 하나님께 드려지는 인생만이 버릴 것이 없는 인생이다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&amp;lt; 예배 영상 &amp;gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;a href=&quot;https://youtu.be/eiRdfzEPDpk&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://youtu.be/eiRdfzEPDpk&lt;/a&gt;&lt;/b&gt;&lt;/p&gt;
&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignCenter&quot; data-video-host=&quot;youtube&quot; data-video-url=&quot;https://www.youtube.com/watch?v=eiRdfzEPDpk&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/c6TEg2/dJMb9aKHPF8/pH26GwZ3OGKNXd0JBtPhsK/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=600_132_732_276,https://scrap.kakaocdn.net/dn/8g7PQ/dJMb887byqR/WMkxVnzqMpU6GcHByNcpq0/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=600_132_732_276,https://scrap.kakaocdn.net/dn/bs5v28/dJMb82MFPLV/yK6otrtb0OoFoAT5roDBvk/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=600_132_732_276&quot; data-video-width=&quot;860&quot; data-video-height=&quot;484&quot; data-video-origin-width=&quot;860&quot; data-video-origin-height=&quot;484&quot; data-ke-mobilestyle=&quot;widthContent&quot; data-video-title=&quot;Sony&quot; data-original-url=&quot;&quot;&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/eiRdfzEPDpk&quot; width=&quot;860&quot; height=&quot;484&quot; frameborder=&quot;&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;figcaption style=&quot;display: none;&quot;&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>성경과 QT/주일예배(온누리교회)</category>
      <category>CGNTV</category>
      <category>버리지말라</category>
      <category>소니스토리</category>
      <category>영상예배</category>
      <category>온누리교회</category>
      <category>요한복음</category>
      <category>우리말성경</category>
      <category>이재훈목사</category>
      <category>주일예배</category>
      <author>isony</author>
      <guid isPermaLink="true">https://isony.tistory.com/314</guid>
      <comments>https://isony.tistory.com/entry/2026%EB%85%8404%EC%9B%9426%EC%9D%BC-%EC%A3%BC%EC%9D%BC%EC%98%88%EB%B0%B0-%EC%9D%B4%EC%9E%AC%ED%9B%88%EB%AA%A9%EC%82%AC%EB%8B%98-1%EB%B6%80#entry314comment</comments>
      <pubDate>Sun, 26 Apr 2026 08:03:48 +0900</pubDate>
    </item>
    <item>
      <title>2026년04월19일 주일예배 (이기원목사님) - 1부</title>
      <link>https://isony.tistory.com/entry/2026%EB%85%8404%EC%9B%9419%EC%9D%BC-%EC%A3%BC%EC%9D%BC%EC%98%88%EB%B0%B0-%EC%9D%B4%EA%B8%B0%EC%9B%90%EB%AA%A9%EC%82%AC%EB%8B%98-1%EB%B6%80</link>
      <description>&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;2026년04월19일 주일예배 (이기원목사님) - 1부&lt;/h2&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;주의 말씀 : 영적 성숙의 길&lt;/h2&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;성경 :&amp;nbsp; 요한일서(1 John) 2:12 - 17 말씀 (출처:우리말성경)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&amp;lt; 성경 &amp;gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;2:12 자녀들이여, 내가 여러분에게 쓰는 것은 여러분의 죄가 그리스도의 이름으로 용서됐기 때문입니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;2:13 아버지들이여, 내가 여러분에게 쓰는 것은 여러분이 태초부터 계시는 분을 알기 때문입니다. 청년들이여, 내가 여러분에게 쓰는 것은 여러분이 악한 자를 이겼기 때문입니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;2:14 자녀들이여, 내가 여러분에게 쓰는 것은 여러분이 아버지를 알았기 때문입니다. 아버지들이여, 내가 여러분에게 쓰는 것은 여러분이 태초부터 계시는 분을 알았기 때문입니다. 청년들이여, 내가 여러분에게 쓴 것은 여러분이 강하고 하나님의 말씀이 여러분 안에 거하시며 여러분이 그 악한 자를 이겼기 때문입니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;2:15 여러분은 이 세상이나 세상에 있는 것들을 사랑하지 마십시오. 누구든지 세상을 사랑하면 아버지의 사랑이 그 사람 안에 있지 않습니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;2:16 이는 세상에 있는 모든 것들, 곧 육신의 탐욕과 안목의 정욕과 세상살이의 자랑은 아버지에게서 온 것이 아니라 세상으로부터 온 것이기 때문입니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;2:17 세상도 사라지고 세상의 정욕도 사라지지만 하나님의 뜻을 행하는 사람은 영원히 살 것입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&amp;lt; 예배 영상 &amp;gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;a href=&quot;https://youtu.be/JkZx6_RCTd0&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://youtu.be/JkZx6_RCTd0&lt;/a&gt;&lt;/b&gt;&lt;/p&gt;
&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignCenter&quot; data-video-host=&quot;youtube&quot; data-video-url=&quot;https://www.youtube.com/watch?v=JkZx6_RCTd0&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/tusqk/dJMb9jOoN0q/EhOJa93TCBjzXkCgFTEesk/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=526_160_686_334,https://scrap.kakaocdn.net/dn/gr40u/dJMb8RRTJNN/UsWXuatLSKbAQkNipg2AIK/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=526_160_686_334,https://scrap.kakaocdn.net/dn/kIXFA/dJMb81GZavG/HE2Qi3frjkJcZmFqwgkuSK/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=526_160_686_334&quot; data-video-width=&quot;860&quot; data-video-height=&quot;484&quot; data-video-origin-width=&quot;860&quot; data-video-origin-height=&quot;484&quot; data-ke-mobilestyle=&quot;widthContent&quot; data-video-title=&quot;Sony&quot; data-original-url=&quot;&quot;&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/JkZx6_RCTd0&quot; width=&quot;860&quot; height=&quot;484&quot; frameborder=&quot;&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;figcaption style=&quot;display: none;&quot;&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>성경과 QT/주일예배(온누리교회)</category>
      <category>CGNTV</category>
      <category>소니스토리</category>
      <category>영상예배</category>
      <category>예배영상</category>
      <category>온누리교회</category>
      <category>요한일서</category>
      <category>우리말성경</category>
      <category>이기원목사</category>
      <category>주일예배</category>
      <author>isony</author>
      <guid isPermaLink="true">https://isony.tistory.com/313</guid>
      <comments>https://isony.tistory.com/entry/2026%EB%85%8404%EC%9B%9419%EC%9D%BC-%EC%A3%BC%EC%9D%BC%EC%98%88%EB%B0%B0-%EC%9D%B4%EA%B8%B0%EC%9B%90%EB%AA%A9%EC%82%AC%EB%8B%98-1%EB%B6%80#entry313comment</comments>
      <pubDate>Sun, 19 Apr 2026 08:09:07 +0900</pubDate>
    </item>
    <item>
      <title>2026년04월12일 주일예배 (박종길목사님) - 1부</title>
      <link>https://isony.tistory.com/entry/2026%EB%85%8404%EC%9B%9412%EC%9D%BC-%EC%A3%BC%EC%9D%BC%EC%98%88%EB%B0%B0-%EB%B0%95%EC%A2%85%EA%B8%B8%EB%AA%A9%EC%82%AC%EB%8B%98-1%EB%B6%80</link>
      <description>&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;2026년04월12일 주일예배 (박종길목사님) - 1부&lt;/h2&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;주의 말씀 : 브니엘&lt;/h2&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;성경 :&amp;nbsp; 창세기(Genesis) 32 : 27 - 31 말씀 (출처:우리말성경)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&amp;lt; 성경 &amp;gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;32:27 그 사람이 물었습니다. &amp;ldquo;네 이름이 무엇이냐?&amp;rdquo; 그가 대답했습니다. &amp;ldquo;야곱입니다.&amp;rdquo;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;32:28 그 사람이 말했습니다. &amp;ldquo;이제 네 이름은 더 이상 야곱이 아니라 이스라엘이다. 네가 하나님과 겨루고 사람들과 겨루어 이겼기 때문이다.&amp;rdquo;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;32:29 야곱이 말했습니다. &amp;ldquo;주의 이름을 말씀해 주십시오.&amp;rdquo; 그가 대답했습니다. &amp;ldquo;어찌 내 이름을 묻느냐?&amp;rdquo; 그가 거기에서 야곱을 축복했습니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;32:30 야곱이 그곳을 브니엘이라 부르고는 말했습니다. &amp;ldquo;내가 하나님을 대면해서 보았는데도 내 생명이 보존됐구나.&amp;rdquo;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;32:31 야곱이 브니엘을 떠날 때 해가 떴습니다. 그는 엉덩이뼈가 어긋나서 절뚝거렸습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1. 홀로 있게 하신다.&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2. 이름을 물으신다.&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3. 브니엘의 소망을 주신다.&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&amp;lt; 예배 영상 &amp;gt;&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;a href=&quot;https://youtu.be/zaZDG6Dh-cQ&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://youtu.be/zaZDG6Dh-cQ&lt;/a&gt;&lt;/b&gt;&lt;/p&gt;
&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignCenter&quot; data-video-host=&quot;youtube&quot; data-video-url=&quot;https://www.youtube.com/watch?v=zaZDG6Dh-cQ&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/brRtYC/dJMb85vP95T/02u5V1GnLy0oo4ZOwhiHJ0/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=504_180_668_360,https://scrap.kakaocdn.net/dn/ccB3n1/dJMb9aKGgxx/kNVKTGcIbNWs2ULYtGGJL0/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=504_180_668_360,https://scrap.kakaocdn.net/dn/cPMq15/dJMb84XZTIz/0SAE1GK196jIjUjp3ilCFk/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=504_180_668_360&quot; data-video-width=&quot;860&quot; data-video-height=&quot;484&quot; data-video-origin-width=&quot;860&quot; data-video-origin-height=&quot;484&quot; data-ke-mobilestyle=&quot;widthContent&quot; data-video-title=&quot;주일예배2026 04 12&quot; data-original-url=&quot;&quot;&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/zaZDG6Dh-cQ&quot; width=&quot;860&quot; height=&quot;484&quot; frameborder=&quot;&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;figcaption style=&quot;display: none;&quot;&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>성경과 QT/주일예배(온누리교회)</category>
      <category>CGNTV</category>
      <category>박종길목사</category>
      <category>브니엘</category>
      <category>소니스토리</category>
      <category>영상예배</category>
      <category>예배영상</category>
      <category>우리말성경</category>
      <category>이스라엘</category>
      <category>주일예배</category>
      <category>창세기</category>
      <author>isony</author>
      <guid isPermaLink="true">https://isony.tistory.com/312</guid>
      <comments>https://isony.tistory.com/entry/2026%EB%85%8404%EC%9B%9412%EC%9D%BC-%EC%A3%BC%EC%9D%BC%EC%98%88%EB%B0%B0-%EB%B0%95%EC%A2%85%EA%B8%B8%EB%AA%A9%EC%82%AC%EB%8B%98-1%EB%B6%80#entry312comment</comments>
      <pubDate>Sun, 12 Apr 2026 08:09:11 +0900</pubDate>
    </item>
    <item>
      <title>2026년04월05일 주일예배 (이재훈목사님) - 1부</title>
      <link>https://isony.tistory.com/entry/2026%EB%85%8404%EC%9B%9405%EC%9D%BC-%EC%A3%BC%EC%9D%BC%EC%98%88%EB%B0%B0-%EC%9D%B4%EC%9E%AC%ED%9B%88%EB%AA%A9%EC%82%AC%EB%8B%98-1%EB%B6%80</link>
      <description>&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;2026년04월05일 주일예배 (이재훈목사님) - 1부&lt;/h2&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;주의 말씀 : 잠긴 문 너머 오신 부활의 주님&lt;/h2&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;성경 :&amp;nbsp; 요한복음(John) 20:19 - 21 말씀 (출처:우리말성경)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&amp;lt; 성경 &amp;gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;20:19 그날, 곧 그 주간의 첫날 저녁에 제자들은 유대 사람들을 두려워해 문들을 걸어 잠그고 모여 있었습니다. 그때 예수께서 오셔서 그들 가운데 서서 말씀하셨습니다. &amp;ldquo;너희에게 평강이 있을지어다!&amp;rdquo;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;20:20 이렇게 말씀하신 뒤 예수께서는 제자들에게 자신의 손과 옆구리를 보여 주셨습니다. 그러자 제자들은 주를 보고 기뻐했습니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;20:21 예수께서 제자들에게 다시 말씀하셨습니다. &amp;ldquo;너희에게 평강이 있을지어다! 아버지께서 나를 보내신 것처럼 나도 너희를 보낸다.&amp;rdquo;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&amp;lt; 부활절 칸타타 영상 &amp;gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://youtu.be/q9gLuG5Zs48&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://youtu.be/q9gLuG5Zs48&lt;/a&gt;&lt;/p&gt;
&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignCenter&quot; data-video-host=&quot;youtube&quot; data-video-url=&quot;https://www.youtube.com/watch?v=q9gLuG5Zs48&quot; data-video-width=&quot;0&quot; data-video-height=&quot;0&quot; data-video-origin-width=&quot;0&quot; data-video-origin-height=&quot;0&quot; data-ke-mobilestyle=&quot;widthContent&quot; data-video-title=&quot;부활절 칸타타 (2026.04.05) - 온누리예배 1부&quot; data-video-thumbnail=&quot;&quot; data-original-url=&quot;&quot;&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/q9gLuG5Zs48&quot; width=&quot;0&quot; height=&quot;0&quot; frameborder=&quot;&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;figcaption style=&quot;display: none;&quot;&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&amp;lt; 예배 영상 &amp;gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;a href=&quot;https://youtu.be/ehEeItHmpKw&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://youtu.be/ehEeItHmpKw&lt;/a&gt;&lt;/b&gt;&lt;/p&gt;
&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignCenter&quot; data-video-host=&quot;youtube&quot; data-video-url=&quot;https://www.youtube.com/watch?v=ehEeItHmpKw&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/4zwVQ/dJMb8WeAbgo/VGpIKNunWtlAAuAdd5MSDK/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=578_140_706_280,https://scrap.kakaocdn.net/dn/g8Z7j/dJMb8Z3rP1T/f76qLdmmlCfnPyGktsGnq0/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=578_140_706_280,https://scrap.kakaocdn.net/dn/bFcuK5/dJMb9jgxNPY/fafxcvOIE9YhbCES8iGIl1/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=578_140_706_280&quot; data-video-width=&quot;860&quot; data-video-height=&quot;484&quot; data-video-origin-width=&quot;860&quot; data-video-origin-height=&quot;484&quot; data-ke-mobilestyle=&quot;widthContent&quot; data-video-title=&quot;주일예배2026 04 05&quot; data-original-url=&quot;&quot;&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/ehEeItHmpKw&quot; width=&quot;860&quot; height=&quot;484&quot; frameborder=&quot;&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;figcaption style=&quot;display: none;&quot;&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&amp;lt; 사도신경 &amp;gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;bandicam 2026-04-05 08-02-09-184.jpg&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bQK1BR/dJMcafF8OII/yvqdnAjsdOdp9pCzgZf910/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bQK1BR/dJMcafF8OII/yvqdnAjsdOdp9pCzgZf910/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bQK1BR/dJMcafF8OII/yvqdnAjsdOdp9pCzgZf910/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbQK1BR%2FdJMcafF8OII%2FyvqdnAjsdOdp9pCzgZf910%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-filename=&quot;bandicam 2026-04-05 08-02-09-184.jpg&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;bandicam 2026-04-05 08-02-32-908.jpg&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cApNnb/dJMcajaEH9T/7LsYshKoTrFRTeNskd6HsK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cApNnb/dJMcajaEH9T/7LsYshKoTrFRTeNskd6HsK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cApNnb/dJMcajaEH9T/7LsYshKoTrFRTeNskd6HsK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcApNnb%2FdJMcajaEH9T%2F7LsYshKoTrFRTeNskd6HsK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1920&quot; height=&quot;1080&quot; data-filename=&quot;bandicam 2026-04-05 08-02-32-908.jpg&quot; data-origin-width=&quot;1920&quot; data-origin-height=&quot;1080&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>성경과 QT/주일예배(온누리교회)</category>
      <category>CGNTV</category>
      <category>부활절</category>
      <category>소니스토리</category>
      <category>예배영상</category>
      <category>온누리교회</category>
      <category>요한복음</category>
      <category>우리말성경</category>
      <category>이재훈목사</category>
      <category>주일예배</category>
      <category>칸타타</category>
      <author>isony</author>
      <guid isPermaLink="true">https://isony.tistory.com/311</guid>
      <comments>https://isony.tistory.com/entry/2026%EB%85%8404%EC%9B%9405%EC%9D%BC-%EC%A3%BC%EC%9D%BC%EC%98%88%EB%B0%B0-%EC%9D%B4%EC%9E%AC%ED%9B%88%EB%AA%A9%EC%82%AC%EB%8B%98-1%EB%B6%80#entry311comment</comments>
      <pubDate>Sun, 5 Apr 2026 08:30:14 +0900</pubDate>
    </item>
  </channel>
</rss>