<?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>Tue, 18 Aug 2026 05:38:49 +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>[PostgreSQL 시리즈 3편] DML과 트랜잭션 - Oracle UNDO vs PostgreSQL MVCC (시리즈 핵심)</title>
      <link>https://isony.tistory.com/entry/PostgreSQL-%EC%8B%9C%EB%A6%AC%EC%A6%88-3%ED%8E%B8-DML%EA%B3%BC-%ED%8A%B8%EB%9E%9C%EC%9E%AD%EC%85%98-Oracle-UNDO-vs-PostgreSQL-MVCC-%EC%8B%9C%EB%A6%AC%EC%A6%88-%ED%95%B5%EC%8B%AC</link>
      <description>&lt;h1&gt;[PostgreSQL 시리즈 3편] DML과 트랜잭션 - Oracle UNDO vs PostgreSQL MVCC (시리즈 핵심)&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;: PostgreSQL 17, Rocky Linux 9 / Oracle 19c&amp;nbsp;&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;p data-ke-size=&quot;size16&quot;&gt;Oracle DBA가 PostgreSQL을 다룰 때 SQL 문법은 금방 익숙해집니다. 하지만 &lt;b&gt;트랜잭션이 내부에서 어떻게 동작하는지&lt;/b&gt;는 근본적으로 다릅니다. 이 차이를 모르면 &quot;왜 테이블이 안 줄어들지?&quot;, &quot;왜 디스크가 계속 늘지?&quot; 같은 문제에서 헤맵니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;핵심은 하나입니다. &lt;b&gt;Oracle은 UNDO, PostgreSQL은 MVCC.&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;DML 문법 비교 (INSERT/UPDATE/DELETE)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;★ Oracle UNDO vs PostgreSQL MVCC&lt;/b&gt; (이 시리즈의 심장)&lt;/li&gt;
&lt;li&gt;왜 PostgreSQL엔 ORA-01555가 없는가&lt;/li&gt;
&lt;li&gt;대신 등장하는 &lt;b&gt;dead tuple&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;/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;DML 문법 비교 (빠르게)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 기본 DML은 대부분 동일합니다. 차이나는 부분만 짚습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;INSERT&lt;/h3&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- 단일 행 (동일)
INSERT INTO employees (emp_name) VALUES ('홍길동');

-- 다중 행 (PostgreSQL이 더 깔끔)
INSERT INTO employees (emp_name) VALUES 
    ('홍길동'), ('김철수'), ('이영희');

-- Oracle의 INSERT ALL 대신 위 방식 사용
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;UPDATE / DELETE&lt;/h3&gt;
&lt;pre class=&quot;n1ql&quot;&gt;&lt;code&gt;-- UPDATE (동일)
UPDATE employees SET salary = salary * 1.1 WHERE dept_id = 10;

-- DELETE (동일)
DELETE FROM employees WHERE emp_id = 5;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;RETURNING - PostgreSQL의 편리 기능&lt;/h3&gt;
&lt;pre class=&quot;n1ql&quot;&gt;&lt;code&gt;-- INSERT/UPDATE/DELETE 결과를 바로 반환!
INSERT INTO employees (emp_name) VALUES ('박신입') 
RETURNING emp_id, emp_name;

UPDATE employees SET salary = 5000 WHERE emp_id = 1 
RETURNING emp_id, salary;

DELETE FROM employees WHERE emp_id = 10 
RETURNING *;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;RETURNING은 Oracle의 RETURNING INTO와 유사하지만 더 간편합니다. 방금 생성된 ID를 바로 받을 때 특히 유용합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;UPSERT - MERGE의 대안&lt;/h3&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;-- PostgreSQL의 ON CONFLICT (Oracle MERGE 대응)
INSERT INTO employees (emp_id, emp_name) 
VALUES (1, '홍길동')
ON CONFLICT (emp_id) 
DO UPDATE SET emp_name = EXCLUDED.emp_name;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Oracle의 MERGE보다 간결합니다. PostgreSQL 15부터는 MERGE 문도 지원하지만, 간단한 경우 ON CONFLICT가 더 편합니다.&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;★ 핵심: Oracle UNDO vs PostgreSQL MVCC&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 이 글의 심장입니다. 두 DB가 &lt;b&gt;동시성 제어&lt;/b&gt;를 어떻게 다르게 처리하는지 이해하면, PostgreSQL 운영의 절반을 이해한 것입니다.&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;1c&quot;&gt;&lt;code&gt;&quot;A가 데이터를 수정 중일 때, 
 B는 수정 전 데이터를 일관되게 읽어야 한다&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;Oracle의 방법: UNDO&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;1. UPDATE 실행
2. 변경 전 데이터를 UNDO 세그먼트에 저장
3. 실제 데이터 블록을 새 값으로 덮어씀
4. 다른 세션이 옛 값을 읽으려 하면?
   &amp;rarr; UNDO에서 옛 값을 재구성해서 보여줌
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;데이터 블록: [새 값] &amp;larr; 제자리에서 덮어씀
UNDO:       [옛 값] &amp;larr; 별도 저장, 읽기 일관성용
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;특징&lt;/b&gt;: 데이터는 제자리에서 갱신되고, 옛 값은 UNDO에 따로 보관됩니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;PostgreSQL의 방법: MVCC&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;1. UPDATE 실행
2. 기존 행은 그대로 두고 (dead 표시만)
3. 새 값으로 완전히 새로운 행 버전을 생성
4. 다른 세션이 옛 값을 읽으려 하면?
   &amp;rarr; 옛 행 버전이 아직 그 자리에 있음, 그대로 읽음
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;UPDATE 전:
[행 v1: 홍길동, 급여 3000] &amp;larr; 유효

UPDATE 후 (급여 3500으로):
[행 v1: 홍길동, 급여 3000] &amp;larr; dead tuple (옛 트랜잭션용)
[행 v2: 홍길동, 급여 3500] &amp;larr; 유효 (새 트랜잭션용)
&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;합니다. 옛 버전은 그 자리에 남습니다(dead tuple).&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;핵심 차이 정리&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;항목 Oracle (UNDO) PostgreSQL (MVCC)&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;UNDO 세그먼트&lt;/td&gt;
&lt;td&gt;테이블 내 dead tuple&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;읽기 일관성&lt;/td&gt;
&lt;td&gt;UNDO에서 재구성&lt;/td&gt;
&lt;td&gt;옛 버전 직접 읽기&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;옛 값 정리&lt;/td&gt;
&lt;td&gt;UNDO 자동 관리&lt;/td&gt;
&lt;td&gt;&lt;b&gt;VACUUM 필요&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;대표 문제&lt;/td&gt;
&lt;td&gt;ORA-01555&lt;/td&gt;
&lt;td&gt;테이블 bloat&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;왜 PostgreSQL엔 ORA-01555가 없는가&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Oracle DBA라면 ORA-01555: snapshot too old에 시달린 기억이 있을 것입니다.&lt;/p&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;1. 긴 조회 쿼리가 실행 중
2. 그 사이 다른 세션들이 활발히 UPDATE
3. UNDO 세그먼트가 재사용되어 옛 값이 사라짐
4. 긴 쿼리가 옛 값을 읽으려는데 UNDO에 없음!
5. &amp;rarr; ORA-01555 발생
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;UNDO 공간이 한정되어 있어서 재사용되면서 생기는 문제입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;PostgreSQL엔 왜 없나&lt;/h3&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;PostgreSQL은 옛 행 버전이 테이블 안에 그대로 남아있음
&amp;rarr; 긴 쿼리가 필요로 하는 한 그 버전은 삭제 안 됨
&amp;rarr; 읽을 값이 사라질 일이 없음
&amp;rarr; ORA-01555 같은 에러 없음!
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&quot;긴 쿼리에 유리하다&quot;&lt;/b&gt; 는 것이 MVCC의 장점입니다. 대용량 배치나 리포팅 쿼리가 많은 환경에서 이 차이는 큽니다.&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;★ 대신 등장하는 문제: dead tuple과 bloat&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공짜 점심은 없습니다. MVCC는 ORA-01555를 없앤 대신 새로운 관리 포인트를 만듭니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;dead tuple이 쌓인다&lt;/h3&gt;
&lt;pre class=&quot;gcode&quot;&gt;&lt;code&gt;UPDATE/DELETE가 많으면:
&amp;rarr; dead tuple(죽은 행 버전)이 계속 쌓임
&amp;rarr; 테이블이 실제 데이터보다 훨씬 커짐 (bloat)
&amp;rarr; 조회 성능 저하 (죽은 행도 스캔)
&amp;rarr; 디스크 낭비
&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;-- 테스트 테이블
CREATE TABLE test_bloat (id INTEGER, val TEXT);
INSERT INTO test_bloat SELECT g, 'data' FROM generate_series(1, 100000) g;

-- 대량 UPDATE 반복 (dead tuple 생성)
UPDATE test_bloat SET val = 'updated';
UPDATE test_bloat SET val = 'updated2';
UPDATE test_bloat SET val = 'updated3';

-- dead tuple 확인
SELECT relname, n_live_tup, n_dead_tup 
FROM pg_stat_user_tables 
WHERE relname = 'test_bloat';
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;n_dead_tup(죽은 튜플 수)이 쌓인 것을 볼 수 있습니다. 10만 건 테이블을 3번 UPDATE하면 dead tuple이 30만 개까지 생길 수 있습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;해결: VACUUM&lt;/h3&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;-- 수동 VACUUM (dead tuple 공간 회수)
VACUUM test_bloat;

-- 통계까지 갱신
VACUUM ANALYZE test_bloat;

-- 완전 회수 (테이블 잠금, 주의!)
VACUUM FULL test_bloat;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;중요&lt;/b&gt;: 평소에는 &lt;b&gt;autovacuum&lt;/b&gt;이 자동으로 이 일을 합니다. 하지만 autovacuum 설정이 부적절하면 dead tuple이 쌓여 문제가 됩니다. 이건 PostgreSQL 운영의 핵심이라 &lt;b&gt;11편에서 통째로&lt;/b&gt; 다룹니다.&lt;/p&gt;
&lt;pre class=&quot;mipsasm&quot;&gt;&lt;code&gt;Oracle DBA의 사고 전환:
&quot;UNDO 관리&quot; &amp;rarr; &quot;VACUUM 관리&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;트랜잭션 격리 수준도 차이가 있습니다.&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;Oracle 기본:     READ COMMITTED
PostgreSQL 기본: READ COMMITTED
&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;격리 수준 Oracle PostgreSQL&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;READ UNCOMMITTED&lt;/td&gt;
&lt;td&gt;(READ COMMITTED로 처리)&lt;/td&gt;
&lt;td&gt;(READ COMMITTED로 처리)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;READ COMMITTED&lt;/td&gt;
&lt;td&gt;✅ 기본&lt;/td&gt;
&lt;td&gt;✅ 기본&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;REPEATABLE READ&lt;/td&gt;
&lt;td&gt;(SERIALIZABLE로)&lt;/td&gt;
&lt;td&gt;✅ 진짜 지원&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SERIALIZABLE&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅ (SSI 방식)&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;Oracle은 REPEATABLE READ를 명시적으로 지원하지 않고 SERIALIZABLE로 처리합니다.&lt;/li&gt;
&lt;li&gt;PostgreSQL은 REPEATABLE READ를 진짜로 지원하며, SERIALIZABLE은 SSI(Serializable Snapshot Isolation)라는 정교한 방식을 씁니다.&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;-- Oracle: 자동으로 트랜잭션 시작, COMMIT 필요
-- PostgreSQL: 동일하게 COMMIT/ROLLBACK

-- 명시적 트랜잭션
BEGIN;                              -- 트랜잭션 시작
UPDATE employees SET salary = 5000 WHERE emp_id = 1;
-- 문제 없으면
COMMIT;
-- 문제 있으면
-- ROLLBACK;

-- 격리 수준 지정
BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ;
-- ...
COMMIT;
&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;avrasm&quot;&gt;&lt;code&gt;Oracle: DDL은 자동 커밋 (암묵적)
PostgreSQL: DDL도 트랜잭션 안에서 롤백 가능! (강점)
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PostgreSQL은 CREATE TABLE, ALTER TABLE 같은 DDL도 트랜잭션 안에서 롤백할 수 있습니다. Oracle DBA에게는 놀라운 부분이며, 마이그레이션 스크립트를 안전하게 실행할 수 있는 장점입니다.&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;BEGIN;
CREATE TABLE test_ddl (id INT);
ALTER TABLE test_ddl ADD COLUMN name TEXT;
-- 문제 발견!
ROLLBACK;   -- 테이블 생성이 통째로 취소됨 (Oracle은 불가)
&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;★ AI 활용 - 동시성 문제 분석&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MVCC 관련 문제를 만났을 때 Claude를 활용하는 법입니다.&lt;/p&gt;
&lt;pre class=&quot;markdown&quot;&gt;&lt;code&gt;프롬프트 예시:
&quot;PostgreSQL에서 이 테이블의 dead tuple이 계속 쌓입니다.
pg_stat_user_tables 결과는 다음과 같습니다:
[결과 붙여넣기]

1. 현재 상태 진단
2. autovacuum이 제대로 동작하는지 확인 방법
3. 개선 방안
을 Oracle DBA가 이해하기 쉽게 설명해줘&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MVCC는 개념이 복잡해서 AI에게 &quot;Oracle에 비유해서 설명해줘&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;[PostgreSQL 시리즈 4편] psql 완벽 활용 + AI로 학습 가속&lt;/b&gt; 입니다. Phase 1(입문)의 마지막으로, psql의 강력한 메타 명령어들과 Claude를 활용한 Oracle&amp;rarr;PostgreSQL 학습법을 다룹니다.&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;이 시리즈의 핵심인 MVCC를 정리하면:&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;Oracle은 UNDO, PostgreSQL은 MVCC&lt;/b&gt; &amp;mdash; 근본적 차이&lt;/li&gt;
&lt;li&gt;&lt;b&gt;MVCC는 새 버전 추가&lt;/b&gt; &amp;mdash; 덮어쓰지 않음&lt;/li&gt;
&lt;li&gt;&lt;b&gt;ORA-01555가 없다&lt;/b&gt; &amp;mdash; 긴 쿼리에 유리&lt;/li&gt;
&lt;li&gt;&lt;b&gt;대신 dead tuple/bloat&lt;/b&gt; &amp;mdash; VACUUM 관리 필요&lt;/li&gt;
&lt;li&gt;&lt;b&gt;DDL도 롤백 가능&lt;/b&gt; &amp;mdash; 마이그레이션에 안전&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 개념을 이해하셨다면 PostgreSQL 운영의 가장 큰 산을 넘으신 것입니다. &quot;UNDO 관리에서 VACUUM 관리로&quot; 사고를 전환하는 것이 Oracle DBA의 핵심 과제입니다. 이 dead tuple 관리는 나중에 11편(VACUUM)과 12편(운영 문제)에서 다시 깊게 다룹니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MVCC를 이해하며 &quot;아하&quot; 했던 순간이나 궁금한 점이 있다면 댓글로 공유해주세요. 같은 전환을 겪는 Oracle DBA들에게 큰 도움이 됩니다.&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 실무/PostgreSQL</category>
      <category>dead tuple bloat</category>
      <category>Oracle UNDO MVCC 차이</category>
      <category>PostgreSQL AI 활용</category>
      <category>PostgreSQL DDL 롤백</category>
      <category>PostgreSQL MVCC</category>
      <category>PostgreSQL ORA-01555</category>
      <category>PostgreSQL vs Oracle 동시성</category>
      <category>PostgreSQL 트랜젝션 격리</category>
      <category>RETURNING ON CONFLICT</category>
      <category>소니스토리</category>
      <author>isony</author>
      <guid isPermaLink="true">https://isony.tistory.com/374</guid>
      <comments>https://isony.tistory.com/entry/PostgreSQL-%EC%8B%9C%EB%A6%AC%EC%A6%88-3%ED%8E%B8-DML%EA%B3%BC-%ED%8A%B8%EB%9E%9C%EC%9E%AD%EC%85%98-Oracle-UNDO-vs-PostgreSQL-MVCC-%EC%8B%9C%EB%A6%AC%EC%A6%88-%ED%95%B5%EC%8B%AC#entry374comment</comments>
      <pubDate>Mon, 17 Aug 2026 07:42:36 +0900</pubDate>
    </item>
    <item>
      <title>2026년08월16일 주일예배 (이재훈목사님) - 1부</title>
      <link>https://isony.tistory.com/entry/2026%EB%85%8408%EC%9B%9416%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년08월16일 주일예배 (이재훈목사님) - 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; 누가복음(Luke) 4:16 ~ 30 말씀 (출처:우리말성경)&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;4:16 예수께서 자신이 자라나신 나사렛에 오셨습니다. 안식일이 되자 예수께서 늘 하시던 대로 회당에 가셔서 성경을 읽으려고 일어나셨습니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;4:17 예언자 이사야의 두루마리를 건네받으시고 두루마리를 펼쳐 이렇게 기록된 곳을 찾아 읽으셨습니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;4:18 &amp;ldquo;주의 영이 내게 내리셨다. 이는 하나님께서 내게 기름을 부으셔서 가난한 사람들에게 복음을 전파하도록 하기 위해서다. 하나님께서는 포로 된 사람들에게 자유를, 못 보는 사람들에게 다시 볼 수 있음을, 억눌린 사람들에게 해방을 선포하기 위해 나를 보내셨다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;4:19 주의 은혜의 해를 선포하도록 하기 위함이다.&amp;rdquo;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;4:20 예수께서는 두루마리를 말아서 시중들던 자에게 돌려주시고 자리에 앉으셨습니다. 회당 안에 있던 모든 사람의 눈이 일제히 예수를 주시했습니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;4:21 그러자 예수께서 그들에게 말씀을 시작하셨습니다. &amp;ldquo;오늘 이 말씀이 너희가 듣는 자리에서 이루어졌다!&amp;rdquo;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;4:22 그러자 모든 사람이 감탄하고 그분의 입에서 나오는 은혜로운 말씀에 놀라며 &amp;ldquo;저 사람은 요셉의 아들이 아닌가?&amp;rdquo;라고 물었습니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;4:23 예수께서 그들에게 말씀하셨습니다. &amp;ldquo;틀림없이 너희는 &amp;lsquo;의사야, 네 병이나 고쳐라!&amp;rsquo; 하는 속담을 들이대며 &amp;lsquo;우리가 소문에 들은 대로 당신이 가버나움에서 했다는 모든 일을 여기 당신의 고향에서도 해 보시오&amp;rsquo;라고 할 것이다.&amp;rdquo;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;4:24 예수께서 이어 말씀하셨습니다. &amp;ldquo;내가 진실로 너희에게 말한다. 어떤 예언자도 자기 고향에서는 인정받지 못하는 법이다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;4:25 그러나 내가 진실로 너희에게 말한다. 많은 과부들이 엘리야 시대에 이스라엘에 있었다. 그때 3년 반 동안 하늘 문이 닫혀 온 땅에 극심한 기근이 들었다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;4:26 그런데 하나님께서는 그 과부들 중 어느 누구에게도 엘리야를 보내지 않으시고 오직 시돈에 있는 사렙다 마을의 한 과부에게 보내셨다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;4:27 또 많은 나병 환자들이 엘리사 예언자 시대에 이스라엘에 있었다. 그러나 그들 중 어느 누구도 시리아 사람 나아만 외에는 깨끗함을 받지 못했다.&amp;rdquo;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;4:28 회당 안에 있던 사람들은 모두 이 말씀을 듣고 화가 잔뜩 났습니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;4:29 그들은 일어나서 예수를 마을 밖으로 쫓아냈습니다. 그리고 마을이 세워진 산 벼랑으로 끌고 가서 그 아래로 밀쳐 떨어뜨리려고 했습니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;4:30 그러나 예수께서는 사람들의 한가운데를 지나 떠나가셨습니다.&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/YUFk9qGqOFo&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://youtu.be/YUFk9qGqOFo&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=YUFk9qGqOFo&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/bqLuZZ/dJMb8PGMJEk/hW3oAL4cKftM4Zjg7pQVtk/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=210_220_430_460,https://scrap.kakaocdn.net/dn/bEM9xD/dJMb8VNMo67/dXAkLiL1JC1TsTmTkmSl2K/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=210_220_430_460,https://scrap.kakaocdn.net/dn/CqyNF/dJMb8Uago0B/vLNyuLhkBlufUhimi9VTmK/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=210_220_430_460&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 08 16&quot; data-original-url=&quot;&quot;&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/YUFk9qGqOFo&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>누가복음 4장</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/373</guid>
      <comments>https://isony.tistory.com/entry/2026%EB%85%8408%EC%9B%9416%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#entry373comment</comments>
      <pubDate>Sun, 16 Aug 2026 08:34:36 +0900</pubDate>
    </item>
    <item>
      <title>ORA-00600 [3005]로 DB가 안 열릴 때 &amp;mdash; 컨트롤파일 재생성 복구 기록</title>
      <link>https://isony.tistory.com/entry/ORA-00600-3005%EB%A1%9C-DB%EA%B0%80-%EC%95%88-%EC%97%B4%EB%A6%B4-%EB%95%8C-%E2%80%94-%EC%BB%A8%ED%8A%B8%EB%A1%A4%ED%8C%8C%EC%9D%BC-%EC%9E%AC%EC%83%9D%EC%84%B1-%EB%B3%B5%EA%B5%AC-%EA%B8%B0%EB%A1%9D</link>
      <description>&lt;h1&gt;ORA-00600 [3005]로 DB가 안 열릴 때 &amp;mdash; 컨트롤파일 재생성 복구 기록&lt;/h1&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Oracle 10.2.0.3 (32-bit Windows) / NOARCHIVELOG 환경에서 ALTER DATABASE OPEN이 ORA-00600: internal error code, arguments: [3005], [1], [345], [3], [0], [0], [], [] 로 실패하던 DB를 컨트롤파일 재생성으로 살린 기록입니다. 중간에 판단을 한 번 잘못했고, 그 부분도 그대로 남겼습니다.&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;1. 상황&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Oracle Database 10g Enterprise Edition &lt;b&gt;10.2.0.3.0 &amp;mdash; 32-bit Windows&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;NOARCHIVELOG&lt;/b&gt; 모드&lt;/li&gt;
&lt;li&gt;데이터파일 21개, 온라인 redo 3그룹(각 500MB)&lt;/li&gt;
&lt;li&gt;마지막 백업 없음&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;STARTUP 하면 MOUNT까지는 올라가는데 OPEN에서 죽습니다.&lt;/p&gt;
&lt;pre class=&quot;prolog&quot;&gt;&lt;code&gt;데이터베이스가 마운트되었습니다.
ORA-00600: 내부 오류 코드, 인수 : [3005], [1], [345], [3], [0], [0], [], []
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. ORA-00600은 인자가 전부다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ORA-00600은 &quot;커널 내부에서 뭔가 잘못됐다&quot;는 것 외에 아무 의미가 없습니다. &lt;b&gt;첫 번째 인자&lt;/b&gt;가 사실상 진짜 에러 코드이고, 나머지는 컨텍스트입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;alert log 위치:&lt;/p&gt;
&lt;pre class=&quot;mipsasm&quot;&gt;&lt;code&gt;SHOW PARAMETER background_dump_dest;   -- 또는 diagnostic_dest
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$ORACLE_BASE/admin/&amp;lt;SID&amp;gt;/bdump/alert_&amp;lt;SID&amp;gt;.log&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;1번&lt;/td&gt;
&lt;td&gt;3005&lt;/td&gt;
&lt;td&gt;오류 식별자 (redo 계열)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2번&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;thread 1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3번&lt;/td&gt;
&lt;td&gt;345&lt;/td&gt;
&lt;td&gt;&lt;b&gt;시퀀스 345&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4번&lt;/td&gt;
&lt;td&gt;3&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;당시 v$log는 이랬습니다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;GROUP#  SEQUENCE#  BYTES       STATUS     FIRST_TIME
     1        343  524288000   INACTIVE   26/07/25
     3        342  524288000   INACTIVE   26/07/16
     2        344  524288000   CURRENT    26/08/03
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CURRENT가 344, 라운드로빈상 다음 차례는 그룹 3(342를 담고 있던 가장 오래된 그룹) &amp;rarr; &lt;b&gt;시퀀스 345&lt;/b&gt;. 인자 [345], [3]과 정확히 일치합니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;즉, OPEN 과정에서 redo thread를 열며 그룹 3에 시퀀스 345를 할당하는 순간 실패하고 있었습니다.&lt;/b&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. 먼저 복구가 필요한 상태인지 확인&lt;/h2&gt;
&lt;pre class=&quot;n1ql&quot;&gt;&lt;code&gt;SELECT log_mode, open_mode, checkpoint_change# FROM v$database;
SELECT * FROM v$recover_file;
SELECT status, COUNT(*), MIN(checkpoint_change#), MAX(checkpoint_change#)
  FROM v$datafile_header GROUP BY status;
SELECT MIN(checkpoint_change#), MAX(checkpoint_change#) FROM v$datafile;
&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;LOG_MODE      OPEN_MODE   CHECKPOINT_CHANGE#
NOARCHIVELOG  MOUNTED     3.4146E10

v$recover_file &amp;rarr; 선택된 레코드가 없습니다.

STATUS   COUNT(*)  MIN(CKPT)   MAX(CKPT)
ONLINE         21  3.4146E10   3.4146E10
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;v$recover_file이 비어 있고 21개 파일의 checkpoint SCN이 전부 같습니다. &lt;b&gt;여기서 &quot;일관 상태니 복구 불필요&quot;라고 판단했는데, 이게 나중에 틀린 것으로 드러납니다.&lt;/b&gt; (&amp;rarr; 6절)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한 가지 팁: 3.4146E10 같은 지수 표기는 수십만 단위 차이를 가려버립니다.&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;SET NUMWIDTH 20
SELECT MIN(checkpoint_change#), MAX(checkpoint_change#),
       COUNT(DISTINCT checkpoint_change#)
  FROM v$datafile_header;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4. 1차 시도 &amp;mdash; 로그 클리어 (실패)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그룹 3의 물리 파일 문제일 수 있으니 비워봅니다.&lt;/p&gt;
&lt;pre class=&quot;n1ql&quot;&gt;&lt;code&gt;SELECT group#, status, type, member FROM v$logfile ORDER BY group#;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;세 그룹 모두 STATUS 공백(정상), 경로는 C:\ORACLE10G\ORADATA\REDO0[1-3].LOG.&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;ALTER DATABASE CLEAR LOGFILE GROUP 3;
-- 데이타베이스가 변경되었습니다.

ALTER DATABASE OPEN;
-- ORA-00600: ... [3005], [1], [345], [3], [0], [0], [], []
&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;rarr; 물리 redo 파일이 아니라 &lt;b&gt;컨트롤파일 안의 redo thread 레코드&lt;/b&gt;가 깨진 것. 그룹 3의 내용을 지워도 컨트롤파일이 여전히 &quot;345를 그룹 3에&quot;라는 잘못된 상태를 고집하고 있습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;5. 2차 시도 &amp;mdash; 컨트롤파일 재생성&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5-1. 정보 확보 (MOUNT 상태에서)&lt;/h3&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;SET LINESIZE 200 PAGESIZE 500
SELECT file#, name FROM v$datafile ORDER BY file#;
SELECT name FROM v$tempfile;     -- ★ 반드시 기록
SELECT name FROM v$controlfile;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;v$tempfile은 꼭 적어두세요.&lt;/b&gt; 컨트롤파일을 재생성하면 tempfile 정보가 사라져서 나중에 수동으로 다시 추가해야 합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5-2. trace 스크립트 뽑기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;udump 폴더를 뒤질 필요 없이 경로를 직접 지정할 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;ALTER DATABASE BACKUP CONTROLFILE TO TRACE AS 'C:\oracle10g\cf_raw.sql';
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5-3. 콜드 백업&lt;/h3&gt;
&lt;pre class=&quot;autoit&quot;&gt;&lt;code&gt;SHUTDOWN IMMEDIATE
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터파일이 여러 드라이브에 흩어져 있으면 &lt;b&gt;전부&lt;/b&gt; 복사해야 합니다. 이 사례는 C:\ORACLE10G\ORADATA\에 3개, D:\ORADATA\에 18개였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기까지가 되돌릴 수 있는 마지막 지점입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5-4. 스크립트 편집&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;cf_raw.sql 안에는 두 벌이 들어 있습니다.&lt;/p&gt;
&lt;pre class=&quot;delphi&quot;&gt;&lt;code&gt;-- Set #1. NORESETLOGS case     &amp;larr; 온라인 로그가 살아있을 때
-- Set #2. RESETLOGS case       &amp;larr; 온라인 로그가 손상됐을 때
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번엔 Set #2를 썼습니다. 그리고 &lt;b&gt;CREATE CONTROLFILE ~ ; 한 덩어리만&lt;/b&gt; 남기고 STARTUP NOMOUNT, RECOVER DATABASE, ALTER DATABASE OPEN RESETLOGS, ALTER TABLESPACE TEMP ADD TEMPFILE 줄은 전부 제거합니다. 이 명령들은 결과를 보면서 직접 칠 겁니다.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;CREATE CONTROLFILE REUSE DATABASE &quot;ORCL&quot; RESETLOGS  NOARCHIVELOG
    MAXLOGFILES 16
    MAXLOGMEMBERS 3
    MAXDATAFILES 100
    MAXINSTANCES 8
    MAXLOGHISTORY 292
LOGFILE
  GROUP 1 'C:\ORACLE10G\ORADATA\REDO01.LOG'  SIZE 500M,
  GROUP 2 'C:\ORACLE10G\ORADATA\REDO02.LOG'  SIZE 500M,
  GROUP 3 'C:\ORACLE10G\ORADATA\REDO03.LOG'  SIZE 500M
DATAFILE
  'C:\ORACLE10G\ORADATA\SYSTEM01.DBF',
  'C:\ORACLE10G\ORADATA\UNDOTBS01.DBF',
  'C:\ORACLE10G\ORADATA\SYSAUX01.DBF',
  'D:\ORADATA\APP_DAT1.DBF',
  ...
CHARACTER SET KO16KSC5601
;
&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;DATAFILE 개수가 실제와 일치하는지 세어볼 것.&lt;/b&gt; 빠진 파일은 그대로 유실됩니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;CHARACTER SET은 절대 임의로 바꾸지 말 것.&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메모장으로 저장할 땐 파일 형식을 &quot;모든 파일&quot;로 바꾸세요. 안 그러면 cf.sql.txt가 됩니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5-5. 실행&lt;/h3&gt;
&lt;pre class=&quot;moonscript&quot;&gt;&lt;code&gt;STARTUP NOMOUNT
@C:\oracle10g\cf.sql
-- 제어 파일이 생성되었습니다.  &amp;rarr; 자동으로 MOUNT 상태
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;6. 여기서 판단 착오 &amp;mdash; FUZZY를 안 봤다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3절에서 &quot;SCN이 전부 같으니 복구 불필요&quot;라고 봤기 때문에, 복구 프롬프트에서 그냥 CANCEL을 쳤습니다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;RECOVER DATABASE USING BACKUP CONTROLFILE UNTIL CANCEL;
ORA-00279: change 34145857632 (08/03/2026 22:00:04) needed for thread 1
ORA-00289: 제안 : C:\ORACLE10G\RDBMS\ARC00344_1024935211.001
ORA-00280: change 34145857632 for thread 1 is in sequence #344

로그 지정: cancel

ORA-01547: 경고: RECOVER 성공했지만 OPEN RESETLOGS 시 아래 오류 발생
ORA-01194: 파일 1은 더 많은 복구가 필요합니다
ORA-01110: 데이터 파일 1: 'C:\ORACLE10G\ORADATA\SYSTEM01.DBF'
ORA-01112: 미디어 복구가 시작되지 않았습니다
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;v$datafile_header의 checkpoint SCN이 전부 같다고 해서 일관 상태인 게 아닙니다.&lt;/b&gt; FUZZY 플래그가 YES면 redo 적용이 더 필요합니다. 이걸 확인했어야 했습니다.&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;SELECT DISTINCT fuzzy, status FROM v$datafile_header;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;v$recover_file이 비어 있던 것도, 원래 컨트롤파일 기준으로는 &quot;미디어 복구 대상 파일이 없다&quot;는 뜻이지 &quot;redo 적용이 끝났다&quot;는 뜻이 아닙니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;7. 해결 &amp;mdash; 온라인 redo 로그를 직접 지정&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ORA-00280을 다시 읽어보면 답이 있습니다.&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;change 34145857632 for thread 1 is in sequence #344
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필요한 redo가 &lt;b&gt;시퀀스 344&lt;/b&gt;, 즉 CURRENT였던 REDO02.LOG 안에 그대로 있습니다. NOARCHIVELOG라 아카이브 파일(ARC00344_...)은 존재하지 않지만, &lt;b&gt;온라인 로그 파일 경로를 직접 입력하면 됩니다.&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;RECOVER DATABASE USING BACKUP CONTROLFILE UNTIL CANCEL;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프롬프트에서 CANCEL 대신:&lt;/p&gt;
&lt;pre class=&quot;taggerscript&quot;&gt;&lt;code&gt;로그 지정: C:\ORACLE10G\ORADATA\REDO02.LOG
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;erlang&quot;&gt;&lt;code&gt;Log applied.
Media recovery complete.
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;ALTER DATABASE OPEN RESETLOGS;
-- 데이타베이스가 변경되었습니다.

ALTER TABLESPACE TEMP ADD TEMPFILE 'C:\ORACLE10G\ORADATA\TEMP01.DBF' SIZE 500M REUSE;
&lt;/code&gt;&lt;/pre&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;온라인 redo 로그 파일이 살아있어야&lt;/b&gt; 성립합니다. &quot;redo 파일을 .old로 옮겨두라&quot;는 조언을 그대로 따랐다가 이 단계에서 막힐 뻔했습니다. RESETLOGS 절차에서 온라인 로그를 치우기 전에, 그 안의 redo가 필요한지 먼저 확인하세요.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;8. 오픈 후 정리&lt;/h2&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;-- 즉시 콜드 백업 (RESETLOGS 이전 백업은 더 이상 쓸 수 없음)
SHUTDOWN IMMEDIATE
-- &amp;rarr; ORADATA 전체 복사

-- 무결성 확인
SELECT owner, object_type, COUNT(*) FROM dba_objects
 WHERE status='INVALID' GROUP BY owner, object_type;
SELECT tablespace_name, status FROM dba_tablespaces;

-- INVALID 객체 재컴파일
@?/rdbms/admin/utlrp.sql
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;alert log에 ORA-600이 재발하지 않는지 며칠 지켜보는 것도 필요합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;9. 정리하며&lt;/h2&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;ORA-00600은 &lt;b&gt;인자를 읽는 것&lt;/b&gt;에서 시작. [3005], [1], [345], [3]은 &quot;thread 1, 그룹 3, 시퀀스 345&quot;로 곧장 해석됨&lt;/li&gt;
&lt;li&gt;v$log와 대조해 인자가 가리키는 지점을 특정&lt;/li&gt;
&lt;li&gt;CLEAR LOGFILE로 물리 파일 요인을 배제 &amp;rarr; 컨트롤파일 문제로 좁혀짐&lt;/li&gt;
&lt;li&gt;컨트롤파일 재생성&lt;/li&gt;
&lt;li&gt;필요한 redo는 온라인 로그에서 직접 공급&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;checkpoint_change#가 같다 &amp;ne; 일관 상태. &lt;b&gt;FUZZY를 같이 봐야 한다&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;ORA-00280의 &quot;is in sequence #N&quot;은 버리는 정보가 아니라 &lt;b&gt;해결의 실마리&lt;/b&gt;다&lt;/li&gt;
&lt;li&gt;복구 절차에서 파일을 치우기 전에, 그 파일이 필요한지부터 확인한다&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;&lt;b&gt;근본 문제는 따로 있었다&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번에 정말 위험했던 건 ORA-600 자체가 아니라 &lt;b&gt;NOARCHIVELOG + 백업 부재&lt;/b&gt;였습니다. 온라인 로그에 시퀀스 344가 남아 있었던 건 상당 부분 운이었습니다. 로그 스위치 간격이 7/16 &amp;rarr; 7/25 &amp;rarr; 8/3로 길었던 덕에 필요한 redo가 덮어쓰이지 않았을 뿐, 트랜잭션이 조금만 많았다면 344는 이미 순환되어 사라졌을 겁니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ARCHIVELOG 모드 전환&lt;/li&gt;
&lt;li&gt;RMAN 정기 백업 구성&lt;/li&gt;
&lt;li&gt;10.2.0.3 / 32-bit Windows는 지원 종료 &amp;mdash; 패치 경로가 없으므로 마이그레이션 계획 수립&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;참고&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ORA-00600의 정확한 인자 의미는 My Oracle Support의 &lt;b&gt;ORA-600/ORA-7445 Lookup Tool&lt;/b&gt;에서 조회할 수 있습니다. 이 글의 [3005] 해석은 인자 패턴과 v$log 대조로 역산한 것입니다.&lt;/li&gt;
&lt;li&gt;운영 DB라면 어떤 조치든 &lt;b&gt;콜드 백업 확보 후&lt;/b&gt; 진행하세요. 특히 NOARCHIVELOG 환경에서 RESETLOGS는 되돌릴 수 없습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>DBA 실무/Oracle(오라클)</category>
      <category>ora-00600</category>
      <category>ORA-3005</category>
      <category>ORA-600</category>
      <category>Oracle 10g</category>
      <category>Oracle NOARCHIVELOG 모드</category>
      <category>Oracle OPEN 복구</category>
      <category>Oracle OPEN 오류</category>
      <category>Oracle REDO</category>
      <category>소니스토리</category>
      <author>isony</author>
      <guid isPermaLink="true">https://isony.tistory.com/372</guid>
      <comments>https://isony.tistory.com/entry/ORA-00600-3005%EB%A1%9C-DB%EA%B0%80-%EC%95%88-%EC%97%B4%EB%A6%B4-%EB%95%8C-%E2%80%94-%EC%BB%A8%ED%8A%B8%EB%A1%A4%ED%8C%8C%EC%9D%BC-%EC%9E%AC%EC%83%9D%EC%84%B1-%EB%B3%B5%EA%B5%AC-%EA%B8%B0%EB%A1%9D#entry372comment</comments>
      <pubDate>Fri, 14 Aug 2026 08:32:13 +0900</pubDate>
    </item>
    <item>
      <title>[PostgreSQL 시리즈 2편] 자료형과 DDL 완벽 비교 - Oracle 타입을 PostgreSQL로 옮기기</title>
      <link>https://isony.tistory.com/entry/PostgreSQL-%EC%8B%9C%EB%A6%AC%EC%A6%88-2%ED%8E%B8-%EC%9E%90%EB%A3%8C%ED%98%95%EA%B3%BC-DDL-%EC%99%84%EB%B2%BD-%EB%B9%84%EA%B5%90-Oracle-%ED%83%80%EC%9E%85%EC%9D%84-PostgreSQL%EB%A1%9C-%EC%98%AE%EA%B8%B0%EA%B8%B0</link>
      <description>&lt;h1&gt;[PostgreSQL 시리즈 2편] 자료형과 DDL 완벽 비교 - Oracle 타입을 PostgreSQL로 옮기기&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;: PostgreSQL 17, Rocky Linux 9 / Oracle 19c&lt;/span&gt;&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PostgreSQL로 넘어온 Oracle DBA가 실무에서 가장 먼저 부딪히는 것이 &lt;b&gt;자료형&lt;/b&gt;입니다. NUMBER, VARCHAR2, DATE... 익숙한 타입들이 PostgreSQL에선 다른 이름이거나, 아예 개념이 다릅니다. 여기서 잘못 매핑하면 데이터 정합성 문제나 성능 저하로 이어집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 편에서는 &lt;a href=&quot;https://www.whodo.net/entry/PostgreSQL-%EC%8B%9C%EB%A6%AC%EC%A6%88-1%ED%8E%B8-Oracle-DBA%EB%A5%BC-%EC%9C%84%ED%95%9C-PostgreSQL-%EC%B2%AB%EA%B1%B8%EC%9D%8C-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98%EB%B6%80%ED%84%B0-%EC%B2%AB-%EC%A0%91%EC%86%8D%EA%B9%8C%EC%A7%80&quot;&gt;1편(첫걸음)&lt;/a&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;Oracle vs PostgreSQL 자료형 완벽 매핑표&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;숫자&amp;middot;문자&amp;middot;날짜 타입의 핵심 차이&lt;/li&gt;
&lt;li&gt;&lt;b&gt;★ SERIAL vs IDENTITY vs 시퀀스&lt;/b&gt; (자동 증가 컬럼)&lt;/li&gt;
&lt;li&gt;CREATE TABLE과 제약조건 문법 비교&lt;/li&gt;
&lt;li&gt;PostgreSQL 고유 타입 맛보기&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모든 예제는 직접 실행 가능하니, psql을 열고 따라 해보세요.&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;Oracle 타입을 PostgreSQL로 옮길 때 참조하는 표입니다. 실무에서 가장 자주 쓰는 것 위주로 정리했습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;숫자 타입&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Oracle PostgreSQL 비고&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;NUMBER(p,s)&lt;/td&gt;
&lt;td&gt;NUMERIC(p,s)&lt;/td&gt;
&lt;td&gt;정확한 소수&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NUMBER (정수)&lt;/td&gt;
&lt;td&gt;INTEGER, BIGINT&lt;/td&gt;
&lt;td&gt;크기에 맞게 선택&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NUMBER(10)&lt;/td&gt;
&lt;td&gt;INTEGER 또는 BIGINT&lt;/td&gt;
&lt;td&gt;자릿수 고려&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BINARY_FLOAT&lt;/td&gt;
&lt;td&gt;REAL&lt;/td&gt;
&lt;td&gt;4바이트 부동소수&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BINARY_DOUBLE&lt;/td&gt;
&lt;td&gt;DOUBLE PRECISION&lt;/td&gt;
&lt;td&gt;8바이트 부동소수&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;: Oracle은 NUMBER 하나로 대부분 처리하지만, PostgreSQL은 &lt;b&gt;용도에 맞는 정수 타입&lt;/b&gt;을 선택하는 게 성능에 좋습니다.&lt;/p&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;-- Oracle 스타일 (모두 NUMBER)
-- emp_id NUMBER, salary NUMBER(10,2)

-- PostgreSQL 권장 (용도별)
emp_id   INTEGER,        -- 또는 BIGINT
salary   NUMERIC(10,2)   -- 정확한 금액
&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;angelscript&quot;&gt;&lt;code&gt;SMALLINT: -32,768 ~ 32,767 (2바이트)
INTEGER:  약 -21억 ~ 21억 (4바이트) &amp;larr; 대부분 이걸로
BIGINT:   매우 큰 수 (8바이트)
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;NUMERIC은 정확하지만 느립니다. 금액처럼 정확성이 중요할 때만 쓰고, 일반 정수는 INTEGER를 쓰세요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;문자 타입&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Oracle PostgreSQL 비고&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;VARCHAR2(n)&lt;/td&gt;
&lt;td&gt;VARCHAR(n)&lt;/td&gt;
&lt;td&gt;가변 길이&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CHAR(n)&lt;/td&gt;
&lt;td&gt;CHAR(n)&lt;/td&gt;
&lt;td&gt;고정 길이&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CLOB&lt;/td&gt;
&lt;td&gt;TEXT&lt;/td&gt;
&lt;td&gt;대용량 텍스트&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NVARCHAR2&lt;/td&gt;
&lt;td&gt;VARCHAR&lt;/td&gt;
&lt;td&gt;PostgreSQL은 기본 유니코드&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;PostgreSQL의 TEXT는 &lt;b&gt;길이 제한이 없고 성능도 좋습니다&lt;/b&gt;. Oracle의 CLOB처럼 특별 취급하지 않습니다.&lt;/li&gt;
&lt;li&gt;사실 PostgreSQL에서는 VARCHAR(n)과 TEXT의 성능 차이가 거의 없습니다. 길이 제한이 꼭 필요한 게 아니면 TEXT를 써도 됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;-- Oracle
-- memo CLOB, name VARCHAR2(100)

-- PostgreSQL
memo  TEXT,          -- 길이 제한 없음, 성능 좋음
name  VARCHAR(100)   -- 제한 필요 시
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;날짜&amp;middot;시간 타입&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Oracle PostgreSQL 비고&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;DATE&lt;/td&gt;
&lt;td&gt;TIMESTAMP&lt;/td&gt;
&lt;td&gt;Oracle DATE는 시분초 포함&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DATE (날짜만)&lt;/td&gt;
&lt;td&gt;DATE&lt;/td&gt;
&lt;td&gt;PostgreSQL DATE는 날짜만&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TIMESTAMP&lt;/td&gt;
&lt;td&gt;TIMESTAMP&lt;/td&gt;
&lt;td&gt;유사&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TIMESTAMP WITH TIME ZONE&lt;/td&gt;
&lt;td&gt;TIMESTAMPTZ&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;: Oracle의 DATE는 &lt;b&gt;시분초를 포함&lt;/b&gt;하지만, PostgreSQL의 DATE는 &lt;b&gt;날짜만&lt;/b&gt; 담습니다.&lt;/p&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;-- Oracle DATE = 날짜 + 시분초
-- &amp;rarr; PostgreSQL에서는 TIMESTAMP로 매핑해야 함!

-- 잘못된 매핑 (시분초 사라짐)
hire_date DATE          -- PostgreSQL: 날짜만!

-- 올바른 매핑
hire_date TIMESTAMP     -- Oracle DATE의 시분초까지 보존
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이걸 놓치면 마이그레이션 시 &lt;b&gt;시간 정보가 통째로 사라집니다.&lt;/b&gt; Oracle DBA가 가장 많이 하는 실수 중 하나입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;기타 타입&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Oracle PostgreSQL 비고&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;BLOB&lt;/td&gt;
&lt;td&gt;BYTEA&lt;/td&gt;
&lt;td&gt;바이너리&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RAW&lt;/td&gt;
&lt;td&gt;BYTEA&lt;/td&gt;
&lt;td&gt;바이너리&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ROWID&lt;/td&gt;
&lt;td&gt;ctid&lt;/td&gt;
&lt;td&gt;물리 위치 (개념 다름)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;XMLTYPE&lt;/td&gt;
&lt;td&gt;XML&lt;/td&gt;
&lt;td&gt;XML&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;(없음)&lt;/td&gt;
&lt;td&gt;JSONB&lt;/td&gt;
&lt;td&gt;PostgreSQL 강점!&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;(없음)&lt;/td&gt;
&lt;td&gt;배열 타입&lt;/td&gt;
&lt;td&gt;PostgreSQL 강점!&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;(없음)&lt;/td&gt;
&lt;td&gt;UUID&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;마지막 3개(JSONB, 배열, UUID)는 Oracle에 없거나 약한 PostgreSQL의 강점입니다. 8편에서 집중 조명합니다.&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;★ 자동 증가 컬럼 - SERIAL vs IDENTITY vs 시퀀스&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Oracle DBA가 가장 반가워하는 부분입니다. Oracle에서 자동 증가 컬럼을 만들려면 &lt;b&gt;시퀀스 + 트리거&lt;/b&gt;를 따로 만들어야 했지만, PostgreSQL은 훨씬 간단합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;방법 1: SERIAL (가장 간단)&lt;/h3&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;CREATE TABLE employees (
    emp_id SERIAL PRIMARY KEY,   -- 자동 증가!
    emp_name VARCHAR(100)
);

-- INSERT 시 emp_id 자동 생성
INSERT INTO employees (emp_name) VALUES ('홍길동');
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SERIAL은 내부적으로 시퀀스를 자동 생성하고 연결합니다. Oracle의 시퀀스+트리거를 한 줄로 대체합니다.&lt;/p&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;SERIAL 종류:
SMALLSERIAL: 2바이트
SERIAL:      4바이트 (INTEGER)
BIGSERIAL:   8바이트 (BIGINT) &amp;larr; 대용량 테이블 권장
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;방법 2: IDENTITY (SQL 표준, 권장)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PostgreSQL 10부터 SQL 표준인 IDENTITY를 지원합니다. Oracle 12c의 IDENTITY와 동일한 문법입니다.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;CREATE TABLE employees (
    emp_id INTEGER GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
    emp_name VARCHAR(100)
);
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;SERIAL vs IDENTITY 선택&lt;/b&gt;:&lt;/p&gt;
&lt;pre class=&quot;http&quot;&gt;&lt;code&gt;SERIAL:   전통적, 간단, 널리 쓰임
IDENTITY: SQL 표준, 더 엄격한 제어 (권장)

GENERATED ALWAYS: 사용자가 값 직접 입력 불가 (안전)
GENERATED BY DEFAULT: 직접 입력도 허용 (유연)
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최신 프로젝트에서는 &lt;b&gt;IDENTITY&lt;/b&gt;를 권장합니다. Oracle 12c 이상을 써온 분이라면 익숙한 문법일 것입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;방법 3: 시퀀스 직접 사용 (Oracle 스타일)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Oracle처럼 시퀀스를 직접 만들 수도 있습니다.&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- 시퀀스 생성 (Oracle과 유사)
CREATE SEQUENCE emp_seq START 1 INCREMENT 1;

-- 사용 (Oracle: emp_seq.NEXTVAL)
SELECT nextval('emp_seq');   -- 다음 값
SELECT currval('emp_seq');   -- 현재 값

-- 테이블에서 사용
CREATE TABLE employees (
    emp_id INTEGER DEFAULT nextval('emp_seq') PRIMARY KEY,
    emp_name VARCHAR(100)
);
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Oracle과 문법 차이&lt;/b&gt;:&lt;/p&gt;
&lt;pre class=&quot;groovy&quot;&gt;&lt;code&gt;Oracle:     emp_seq.NEXTVAL, emp_seq.CURRVAL
PostgreSQL: nextval('emp_seq'), currval('emp_seq')
&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;CREATE TABLE 완벽 비교 (실습)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 실제 테이블을 만들며 제약조건까지 비교합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Oracle 스타일 테이블&lt;/h3&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;-- Oracle
CREATE TABLE departments (
    dept_id    NUMBER(10)    PRIMARY KEY,
    dept_name  VARCHAR2(100) NOT NULL,
    location   VARCHAR2(50)  DEFAULT 'Seoul',
    created_at DATE          DEFAULT SYSDATE
);
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;PostgreSQL로 변환&lt;/h3&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;-- PostgreSQL
CREATE TABLE departments (
    dept_id    INTEGER GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
    dept_name  VARCHAR(100) NOT NULL,
    location   VARCHAR(50)  DEFAULT 'Seoul',
    created_at TIMESTAMP    DEFAULT CURRENT_TIMESTAMP
);
&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;pgsql&quot;&gt;&lt;code&gt;NUMBER(10)  &amp;rarr; INTEGER (+ IDENTITY로 자동증가)
VARCHAR2    &amp;rarr; VARCHAR
DATE        &amp;rarr; TIMESTAMP (시분초 보존)
SYSDATE     &amp;rarr; CURRENT_TIMESTAMP
&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;sql&quot;&gt;&lt;code&gt;CREATE TABLE employees (
    emp_id     INTEGER GENERATED ALWAYS AS IDENTITY,
    emp_name   VARCHAR(100) NOT NULL,
    email      VARCHAR(100) UNIQUE,
    dept_id    INTEGER,
    salary     NUMERIC(10,2) CHECK (salary &amp;gt; 0),
    hire_date  TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    
    -- 기본키
    CONSTRAINT pk_emp PRIMARY KEY (emp_id),
    -- 외래키
    CONSTRAINT fk_dept FOREIGN KEY (dept_id) 
        REFERENCES departments(dept_id)
);
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Oracle과 거의 동일&lt;/b&gt;합니다. PRIMARY KEY, FOREIGN KEY, UNIQUE, CHECK, NOT NULL 모두 같은 문법입니다. 이 부분은 Oracle DBA에게 부담이 없습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;함정: 외래키 인덱스&lt;/h3&gt;
&lt;pre class=&quot;http&quot;&gt;&lt;code&gt;Oracle: 외래키 컬럼에 인덱스 자동 생성 안 됨 (수동 필요)
PostgreSQL: 마찬가지로 자동 생성 안 됨

&amp;rarr; 양쪽 모두 외래키 컬럼에 인덱스를 수동으로 만들어야
  성능 문제(락 등)를 피할 수 있음
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- 외래키 컬럼에 인덱스 (권장)
CREATE INDEX idx_emp_dept ON employees(dept_id);
&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;테이블 수정 (ALTER TABLE)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컬럼 추가&amp;middot;수정도 비교해봅니다.&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- 컬럼 추가 (거의 동일)
ALTER TABLE employees ADD COLUMN phone VARCHAR(20);

-- 컬럼 타입 변경 (문법 차이)
-- Oracle: ALTER TABLE emp MODIFY (phone VARCHAR2(30));
-- PostgreSQL:
ALTER TABLE employees ALTER COLUMN phone TYPE VARCHAR(30);

-- 컬럼 삭제 (동일)
ALTER TABLE employees DROP COLUMN phone;

-- 컬럼명 변경 (동일)
ALTER TABLE employees RENAME COLUMN phone TO mobile;

-- 기본값 설정 (문법 차이)
-- Oracle: ALTER TABLE emp MODIFY (location DEFAULT 'Busan');
-- PostgreSQL:
ALTER TABLE employees ALTER COLUMN location SET DEFAULT 'Busan';
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;핵심 차이&lt;/b&gt;: Oracle의 MODIFY가 PostgreSQL에서는 ALTER COLUMN ... TYPE, SET DEFAULT 등으로 세분화됩니다.&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;PostgreSQL 고유 타입 맛보기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Oracle에 없는 PostgreSQL만의 타입을 미리 살짝 보겠습니다. (자세한 건 8편에서)&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 products (
    product_id INTEGER GENERATED ALWAYS AS IDENTITY,
    name       VARCHAR(100),
    tags       TEXT[]        -- 문자열 배열
);

INSERT INTO products (name, tags) 
VALUES ('노트북', ARRAY['전자', '컴퓨터', '휴대용']);

-- 배열 검색
SELECT * FROM products WHERE '전자' = ANY(tags);
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Oracle이라면 별도 테이블로 정규화해야 할 것을 배열로 간단히 처리합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;JSONB 타입&lt;/h3&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- JSON을 네이티브로 저장하고 인덱싱까지!
CREATE TABLE events (
    event_id INTEGER GENERATED ALWAYS AS IDENTITY,
    data     JSONB
);

INSERT INTO events (data) 
VALUES ('{&quot;user&quot;: &quot;kim&quot;, &quot;action&quot;: &quot;login&quot;, &quot;ip&quot;: &quot;1.2.3.4&quot;}');

-- JSON 필드 조회
SELECT data-&amp;gt;&amp;gt;'user' AS username FROM events;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JSONB는 PostgreSQL의 킬러 기능 중 하나입니다. Oracle도 JSON을 지원하지만 PostgreSQL의 JSONB가 더 강력하고 널리 쓰입니다.&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;p data-ke-size=&quot;size16&quot;&gt;Oracle DDL을 PostgreSQL로 변환할 때 Claude를 활용하면 빠릅니다.&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;프롬프트 예시:
&quot;다음 Oracle CREATE TABLE 문을 PostgreSQL 17로 
변환해줘. 다음을 지켜서:
- DATE는 시분초 필요 여부를 물어보고 매핑
- NUMBER는 용도에 맞는 정수/NUMERIC로
- 시퀀스+트리거는 IDENTITY로
- 바뀐 부분마다 이유 주석

[Oracle DDL 붙여넣기]&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;주의&lt;/b&gt;: AI 변환 결과는 반드시 검증하세요. 특히 DATE &amp;rarr; TIMESTAMP 매핑은 데이터 손실과 직결되므로 꼭 확인해야 합니다.&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;[PostgreSQL 시리즈 3편] DML과 트랜잭션 - MVCC의 차이&lt;/b&gt; 입니다. INSERT/UPDATE/DELETE 문법 비교와 함께, Oracle의 UNDO와 PostgreSQL의 MVCC가 어떻게 다른지 &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;마무리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Oracle 자료형을 PostgreSQL로 옮길 때 핵심입니다.&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;NUMBER는 용도별로&lt;/b&gt; &amp;mdash; INTEGER/BIGINT/NUMERIC 구분&lt;/li&gt;
&lt;li&gt;&lt;b&gt;DATE 함정 주의&lt;/b&gt; &amp;mdash; Oracle DATE &amp;rarr; PostgreSQL TIMESTAMP (시분초!)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;자동 증가는 IDENTITY 권장&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;JSONB&amp;middot;배열&lt;/b&gt; &amp;mdash; Oracle에 없는 강점 (8편에서)&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자료형 매핑은 마이그레이션의 첫 관문입니다. 특히 DATE 함정과 NUMBER 선택만 정확히 해도 많은 문제를 예방할 수 있습니다. 다음 편에서는 이 시리즈의 하이라이트인 MVCC를 다룹니다. Oracle DBA에게 가장 낯선, 그러나 가장 중요한 개념입니다.&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 실무/PostgreSQL</category>
      <category>NUMBER NUMERIC 변환</category>
      <category>Oracle DATE TIMESTAMP</category>
      <category>Oracle PostgreSQL 데이터 타입</category>
      <category>Oracle 마이그레이션 타입</category>
      <category>PostgreSQL Serial Identity</category>
      <category>PostgreSQL Table</category>
      <category>PostgreSQL 자동증가</category>
      <category>VARCHAR2 VARCHAR</category>
      <category>소니스토리</category>
      <category>시퀀스 nextval</category>
      <author>isony</author>
      <guid isPermaLink="true">https://isony.tistory.com/371</guid>
      <comments>https://isony.tistory.com/entry/PostgreSQL-%EC%8B%9C%EB%A6%AC%EC%A6%88-2%ED%8E%B8-%EC%9E%90%EB%A3%8C%ED%98%95%EA%B3%BC-DDL-%EC%99%84%EB%B2%BD-%EB%B9%84%EA%B5%90-Oracle-%ED%83%80%EC%9E%85%EC%9D%84-PostgreSQL%EB%A1%9C-%EC%98%AE%EA%B8%B0%EA%B8%B0#entry371comment</comments>
      <pubDate>Fri, 14 Aug 2026 08:25:48 +0900</pubDate>
    </item>
    <item>
      <title>PostgreSQL 시리즈 1편] Oracle DBA를 위한 PostgreSQL 첫걸음 - 아키텍처부터 첫 접속까지</title>
      <link>https://isony.tistory.com/entry/PostgreSQL-%EC%8B%9C%EB%A6%AC%EC%A6%88-1%ED%8E%B8-Oracle-DBA%EB%A5%BC-%EC%9C%84%ED%95%9C-PostgreSQL-%EC%B2%AB%EA%B1%B8%EC%9D%8C-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98%EB%B6%80%ED%84%B0-%EC%B2%AB-%EC%A0%91%EC%86%8D%EA%B9%8C%EC%A7%80</link>
      <description>&lt;h1&gt;[PostgreSQL 시리즈 1편] Oracle DBA를 위한 PostgreSQL 첫걸음 - 아키텍처부터 첫 접속까지&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;: PostgreSQL 17, Rocky Linux 9 / Oracle 19c&lt;/span&gt;&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Oracle을 오래 다뤄온 DBA에게 PostgreSQL은 &lt;b&gt;낯설면서도 익숙한&lt;/b&gt; 데이터베이스입니다. SQL은 대부분 통하는데, 아키텍처와 운영 방식은 꽤 다릅니다. 이 차이를 모르고 Oracle 습관대로 접근하면 곳곳에서 헤맵니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 시리즈는 &lt;b&gt;15년차 Oracle DBA가 PostgreSQL로 넘어가며 정리한 실전 노트&lt;/b&gt;입니다. 모든 개념을 Oracle과 비교하되, PostgreSQL 중심으로 설명합니다. Oracle을 아는 분이라면 훨씬 빠르게 습득하실 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 1편에서 다룰 내용입니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;왜 지금 PostgreSQL인가&lt;/li&gt;
&lt;li&gt;&lt;b&gt;아키텍처 비교&lt;/b&gt; (프로세스&amp;middot;메모리 구조)&lt;/li&gt;
&lt;li&gt;설치와 첫 접속 (sqlplus vs psql)&lt;/li&gt;
&lt;li&gt;Oracle DBA가 가장 먼저 헷갈리는 것들&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실습 위주로 진행하니, PostgreSQL을 설치할 환경(로컬 VM이나 클라우드)을 준비하시면 좋습니다.&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;왜 지금 PostgreSQL인가&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Oracle DBA가 PostgreSQL을 배워야 하는 이유는 명확합니다.&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;라이선스 비용&lt;/b&gt;: Oracle의 높은 라이선스 부담으로 많은 기업이 PostgreSQL로 전환 중&lt;/li&gt;
&lt;li&gt;&lt;b&gt;인기도&lt;/b&gt;: Stack Overflow 개발자 설문에서 2023년 이후 가장 인기 있는 DB&lt;/li&gt;
&lt;li&gt;&lt;b&gt;클라우드&lt;/b&gt;: AWS RDS, Azure, GCP 모두 PostgreSQL을 핵심으로 지원&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Oracle 호환성&lt;/b&gt;: 최근 Oracle도 PostgreSQL 호환성을 강화할 만큼 무시할 수 없는 존재&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Oracle DBA의 강점&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Oracle을 아는 것은 PostgreSQL 학습에 &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;★ 아키텍처 비교 - 가장 중요한 첫 단추&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Oracle DBA가 PostgreSQL에서 가장 먼저 이해해야 할 것이 아키텍처 차이입니다. 여기서 많은 개념이 갈립니다.&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;b&gt;Oracle&lt;/b&gt;: 인스턴스 = SGA + 백그라운드 프로세스 집합&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;Oracle 인스턴스
├── SGA (공유 메모리)
│   ├── Shared Pool
│   ├── Buffer Cache
│   └── Redo Log Buffer
├── PGA (프로세스별 메모리)
└── 백그라운드 프로세스
    ├── DBWn (DB Writer)
    ├── LGWR (Log Writer)
    ├── CKPT (Checkpoint)
    ├── SMON (System Monitor)
    ├── PMON (Process Monitor)
    └── ARCn (Archiver)
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;PostgreSQL&lt;/b&gt;: postmaster + 연결별 백엔드 프로세스&lt;/p&gt;
&lt;pre class=&quot;less&quot;&gt;&lt;code&gt;PostgreSQL 인스턴스 (클러스터)
├── Shared Buffers (공유 메모리)
├── WAL Buffers
├── postmaster (메인 프로세스)
├── 연결별 backend 프로세스 (연결 1개 = 프로세스 1개)
└── 백그라운드 프로세스
    ├── Background Writer
    ├── Checkpointer
    ├── WAL Writer
    ├── Autovacuum (PostgreSQL 고유!)
    └── Archiver
&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;1. 연결 = 프로세스&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;http&quot;&gt;&lt;code&gt;Oracle: 공유 서버 or 전용 서버 (프로세스 관리 정교)
PostgreSQL: 연결 1개당 backend 프로세스 1개

&amp;rarr; PostgreSQL은 연결이 많으면 프로세스가 많아짐
&amp;rarr; 그래서 연결 풀러(PgBouncer)가 거의 필수
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이건 나중에 &quot;연결 부족&quot; 문제로 이어지는 중요한 차이입니다 (12편에서 상세히).&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. SMON/PMON이 없음&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;avrasm&quot;&gt;&lt;code&gt;Oracle: SMON(인스턴스 복구), PMON(프로세스 정리) 등 복잡한 백그라운드
PostgreSQL: 더 단순한 백그라운드 구조
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. Autovacuum이라는 고유 존재&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;isbl&quot;&gt;&lt;code&gt;Oracle에는 없는 개념
PostgreSQL의 MVCC 특성상 반드시 필요
&amp;rarr; dead tuple(죽은 행) 정리
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Autovacuum은 PostgreSQL 운영의 핵심이라 11편에서 통째로 다룹니다. 지금은 &quot;Oracle에 없는 중요한 것이 있다&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;개념 Oracle PostgreSQL&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;Database (CDB/PDB)&lt;/td&gt;
&lt;td&gt;Cluster&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;논리 그룹&lt;/td&gt;
&lt;td&gt;Tablespace&lt;/td&gt;
&lt;td&gt;Tablespace (유사)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;스키마&lt;/td&gt;
&lt;td&gt;User = Schema&lt;/td&gt;
&lt;td&gt;Database &amp;gt; Schema&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;트랜잭션 로그&lt;/td&gt;
&lt;td&gt;Redo Log&lt;/td&gt;
&lt;td&gt;WAL (Write-Ahead Log)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;복구&lt;/td&gt;
&lt;td&gt;Redo + UNDO&lt;/td&gt;
&lt;td&gt;WAL + MVCC&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;Oracle은 &quot;User = Schema&quot;지만, PostgreSQL은 &lt;b&gt;Database 안에 여러 Schema&lt;/b&gt;가 있고 그 안에 객체가 있습니다.&lt;/li&gt;
&lt;li&gt;Oracle의 UNDO에 해당하는 별도 구조가 PostgreSQL엔 없습니다. 대신 &lt;b&gt;MVCC&lt;/b&gt;로 처리합니다 (3편에서 상세히).&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;이제 직접 해봅시다. Rocky Linux 9 기준입니다.&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;# PostgreSQL 공식 repo 추가
sudo dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-9-x86_64/pgdg-redhat-repo-latest.noarch.rpm

# 기본 모듈 비활성화
sudo dnf -qy module disable postgresql

# PostgreSQL 17 설치
sudo dnf install -y postgresql17-server postgresql17

# 초기화 (Oracle의 DBCA에 해당)
sudo /usr/pgsql-17/bin/postgresql-17-setup initdb

# 서비스 시작
sudo systemctl enable --now postgresql-17
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Oracle과 비교&lt;/b&gt;: Oracle의 dbca로 DB를 만드는 것처럼, PostgreSQL은 initdb로 클러스터를 초기화합니다. 다만 훨씬 가볍고 빠릅니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;첫 접속 - sqlplus vs psql&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Oracle의 sqlplus에 해당하는 것이 psql입니다.&lt;/p&gt;
&lt;pre class=&quot;vala&quot;&gt;&lt;code&gt;# postgres 유저로 전환 (기본 관리자)
sudo -i -u postgres

# psql 접속 (sqlplus / as sysdba 느낌)
psql
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;접속하면 프롬프트가 나타납니다.&lt;/p&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;postgres=#
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;=#는 슈퍼유저, =&amp;gt;는 일반 유저를 의미합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;sqlplus vs psql 명령어 비교&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;작업 Oracle (sqlplus) PostgreSQL (psql)&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;sqlplus user/pass&lt;/td&gt;
&lt;td&gt;psql -U user -d db&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DB 목록&lt;/td&gt;
&lt;td&gt;SELECT name FROM v$database;&lt;/td&gt;
&lt;td&gt;\l&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;테이블 목록&lt;/td&gt;
&lt;td&gt;SELECT * FROM tab;&lt;/td&gt;
&lt;td&gt;\dt&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;테이블 구조&lt;/td&gt;
&lt;td&gt;DESC 테이블&lt;/td&gt;
&lt;td&gt;\d 테이블&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;유저 목록&lt;/td&gt;
&lt;td&gt;SELECT * FROM dba_users;&lt;/td&gt;
&lt;td&gt;\du&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;현재 유저&lt;/td&gt;
&lt;td&gt;SHOW USER&lt;/td&gt;
&lt;td&gt;SELECT current_user;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SQL 파일 실행&lt;/td&gt;
&lt;td&gt;@script.sql&lt;/td&gt;
&lt;td&gt;\i script.sql&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;나가기&lt;/td&gt;
&lt;td&gt;EXIT&lt;/td&gt;
&lt;td&gt;\q&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;: PostgreSQL의 &lt;b&gt;역슬래시 명령어(\)&lt;/b&gt; 가 psql의 강력한 기능입니다. Oracle의 DESC보다 훨씬 다양합니다. 이건 4편에서 깊게 다룹니다.&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;-- 데이터베이스 생성 (Oracle의 PDB 생성 느낌)
CREATE DATABASE testdb;

-- 접속 전환 (sqlplus의 connect)
\c testdb

-- 테이블 생성
CREATE TABLE employees (
    emp_id SERIAL PRIMARY KEY,
    emp_name VARCHAR(100),
    hire_date DATE DEFAULT CURRENT_DATE
);

-- 데이터 입력
INSERT INTO employees (emp_name) VALUES ('홍길동'), ('김철수');

-- 조회
SELECT * FROM employees;

-- 테이블 구조 확인 (DESC 대신)
\d 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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;SERIAL: Oracle의 시퀀스+트리거를 한 방에 (2편에서 상세히)&lt;/li&gt;
&lt;li&gt;CURRENT_DATE: Oracle의 SYSDATE에 해당&lt;/li&gt;
&lt;li&gt;\d: DESC 대신&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;Oracle DBA가 가장 먼저 헷갈리는 것 5가지&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;경험상 Oracle DBA가 PostgreSQL 초반에 가장 많이 헷갈리는 부분입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. Database vs Schema 구조&lt;/h3&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;Oracle: 하나의 DB, User=Schema
PostgreSQL: 여러 Database, 각 Database 안에 여러 Schema

&amp;rarr; PostgreSQL에서 다른 database의 테이블은 
  기본적으로 직접 조인 안 됨 (Oracle과 큰 차이)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. 세미콜론 필수&lt;/h3&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- Oracle: sqlplus에서 SELECT는 세미콜론
-- PostgreSQL: psql에서 모든 문장에 세미콜론 필수
SELECT 1;  -- 세미콜론 없으면 실행 안 됨
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. 대소문자 처리&lt;/h3&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- PostgreSQL은 따옴표 없는 식별자를 소문자로 변환
CREATE TABLE Test (...);   -- 실제로는 test로 생성됨
SELECT * FROM &quot;Test&quot;;      -- 대문자 쓰려면 큰따옴표 (권장 안 함)

-- Oracle은 대문자로 변환 &amp;rarr; 정반대!
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이건 Oracle DBA가 정말 자주 실수하는 부분입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4. UNDO가 없음&lt;/h3&gt;
&lt;pre class=&quot;http&quot;&gt;&lt;code&gt;Oracle: UNDO 테이블스페이스로 읽기 일관성
PostgreSQL: MVCC로 각 행의 여러 버전 유지

&amp;rarr; ORA-01555 같은 에러가 없는 대신
  VACUUM이라는 새로운 관리 포인트 등장
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5. 접속 설정 파일&lt;/h3&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;Oracle: tnsnames.ora, listener.ora
PostgreSQL: postgresql.conf(설정), pg_hba.conf(접속 권한)

&amp;rarr; pg_hba.conf를 모르면 원격 접속이 안 됨
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;pg_hba.conf는 초보자가 원격 접속에서 막히는 대표 원인입니다. 접속 방식(trust, md5, scram-sha-256 등)을 정의합니다.&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로 PostgreSQL 학습 가속하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Oracle DBA가 PostgreSQL을 배울 때 Claude 같은 AI를 활용하면 학습 속도가 크게 빨라집니다. 간단한 활용법을 소개합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Oracle &amp;rarr; PostgreSQL 변환 학습&lt;/h3&gt;
&lt;pre class=&quot;1c&quot;&gt;&lt;code&gt;프롬프트 예시:
&quot;다음 Oracle SQL을 PostgreSQL로 변환하고, 
바뀐 부분과 그 이유를 설명해줘.

[Oracle SQL 붙여넣기]&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;pre class=&quot;1c&quot;&gt;&lt;code&gt;&quot;Oracle의 [개념]은 PostgreSQL에서 
무엇에 해당하고, 어떻게 다른지 설명해줘&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 시리즈도 이런 방식으로 학습하면서 정리한 노트입니다. AI 활용법은 4편에서 본격적으로 다룹니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;주의&lt;/b&gt;: 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;[PostgreSQL 시리즈 2편] 자료형과 DDL 완벽 비교&lt;/b&gt; 입니다. Oracle과 PostgreSQL의 데이터 타입 매핑, SERIAL/IDENTITY, CREATE TABLE 문법 차이를 실습으로 다룹니다.&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;Oracle DBA의 PostgreSQL 첫걸음에서 기억할 핵심입니다.&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; 연결=프로세스, Autovacuum 존재&lt;/li&gt;
&lt;li&gt;&lt;b&gt;UNDO 대신 MVCC&lt;/b&gt; &amp;mdash; VACUUM이라는 새 관리 포인트&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Database &amp;gt; Schema 구조&lt;/b&gt; &amp;mdash; Oracle의 User=Schema와 다름&lt;/li&gt;
&lt;li&gt;&lt;b&gt;대소문자는 소문자 변환&lt;/b&gt; &amp;mdash; Oracle과 정반대&lt;/li&gt;
&lt;li&gt;&lt;b&gt;psql의 역슬래시 명령어&lt;/b&gt; &amp;mdash; DESC보다 강력&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Oracle 경험은 PostgreSQL 학습에 큰 자산입니다. 핵심 개념은 이미 아시니, &lt;b&gt;차이나는 부분만&lt;/b&gt; 집중하면 빠르게 익힐 수 있습니다. 이번 편에서 아키텍처의 큰 그림을 잡으셨다면, 다음 편부터는 실제 문법으로 들어가 보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PostgreSQL로 전환하며 겪은 경험이나 궁금한 점이 있다면 댓글로 공유해주세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;같은 길을 걷는 Oracle DBA들에게 큰 도움이 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>DBA 실무/PostgreSQL</category>
      <category>Oracle DBA PostgreSQL 전환</category>
      <category>Oracle PostgreSQL 차이</category>
      <category>Oracle UNDO PostgreSQL MVCC</category>
      <category>pg_hba.conf</category>
      <category>PostgreSQL 17 설치</category>
      <category>PostgreSQL 대소문자</category>
      <category>PostgreSQL 아키텍처</category>
      <category>PostgreSQL 첫접속</category>
      <category>sqlplus psql 비교</category>
      <category>소니스토리</category>
      <author>isony</author>
      <guid isPermaLink="true">https://isony.tistory.com/370</guid>
      <comments>https://isony.tistory.com/entry/PostgreSQL-%EC%8B%9C%EB%A6%AC%EC%A6%88-1%ED%8E%B8-Oracle-DBA%EB%A5%BC-%EC%9C%84%ED%95%9C-PostgreSQL-%EC%B2%AB%EA%B1%B8%EC%9D%8C-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98%EB%B6%80%ED%84%B0-%EC%B2%AB-%EC%A0%91%EC%86%8D%EA%B9%8C%EC%A7%80#entry370comment</comments>
      <pubDate>Wed, 12 Aug 2026 06:55:11 +0900</pubDate>
    </item>
    <item>
      <title>PostgreSQL, 설치할 때 정한 걸로 3년을 삽니다 &amp;mdash; 설치부터 초기 설정까지</title>
      <link>https://isony.tistory.com/entry/PostgreSQL-%EC%84%A4%EC%B9%98%ED%95%A0-%EB%95%8C-%EC%A0%95%ED%95%9C-%EA%B1%B8%EB%A1%9C-3%EB%85%84%EC%9D%84-%EC%82%BD%EB%8B%88%EB%8B%A4-%E2%80%94-%EC%84%A4%EC%B9%98%EB%B6%80%ED%84%B0-%EC%B4%88%EA%B8%B0-%EC%84%A4%EC%A0%95%EA%B9%8C%EC%A7%80</link>
      <description>&lt;h1&gt;PostgreSQL, 설치할 때 정한 걸로 3년을 삽니다 &amp;mdash; 설치부터 초기 설정까지&lt;/h1&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;PostgreSQL 실무 시리즈 ①&lt;/b&gt; 이 글의 모든 명령어와 출력은 실제로 실행한 결과입니다.&lt;br /&gt;검증 환경: PostgreSQL 16.2 / Ubuntu 22.04 / UTF8&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PostgreSQL 설치는 쉽습니다. apt install postgresql 한 줄이면 끝나니까요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제는 그 다음입니다. &lt;b&gt;설치 시점에 정하고 나면 두 번 다시 못 바꾸는 옵션이 몇 개 있는데, 하필 그게 기본값으로 두면 안 되는 것들입니다.&lt;/b&gt; 그리고 그 대가는 보통 2~3년 뒤, 데이터가 수백 GB로 불어난 다음에 청구됩니다.&lt;/p&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;1. 배포판 기본 패키지를 쓰지 마세요&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Ubuntu 22.04에서 기본 저장소를 확인해 보면 이렇습니다.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;$ apt-cache policy postgresql
postgresql:
  Installed: (none)
  Candidate: 14+238
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;14입니다.&lt;/b&gt; PostgreSQL 14는 2026년 11월에 지원이 끝납니다. 지금 새로 구축하면서 이걸 깔면, 서비스를 오픈하기도 전에 EOL 카운트다운이 시작됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메이저 버전은 릴리스 후 &lt;b&gt;5년간&lt;/b&gt; 지원됩니다. 그래서 신규 구축이면 최소한 16 이상, 가급적 17을 쓰는 게 맞습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Ubuntu / Debian &amp;mdash; PGDG 공식 저장소&lt;/h3&gt;
&lt;pre class=&quot;awk&quot;&gt;&lt;code&gt;sudo apt install -y curl ca-certificates
sudo install -d /usr/share/postgresql-common/pgdg
sudo curl -o /usr/share/postgresql-common/pgdg/apt.postgresql.org.asc \
     --fail https://www.postgresql.org/media/keys/ACCC4CF8.asc

. /etc/os-release
echo &quot;deb [signed-by=/usr/share/postgresql-common/pgdg/apt.postgresql.org.asc] \
https://apt.postgresql.org/pub/repos/apt $VERSION_CODENAME-pgdg main&quot; \
  | sudo tee /etc/apt/sources.list.d/pgdg.list

sudo apt update
sudo apt install -y postgresql-17 postgresql-contrib-17
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;RHEL / Rocky / Alma 9&lt;/h3&gt;
&lt;pre class=&quot;crystal&quot;&gt;&lt;code&gt;sudo dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-9-x86_64/pgdg-redhat-repo-latest.noarch.rpm
sudo dnf -qy module disable postgresql          # &amp;larr; 이거 빼면 충돌합니다
sudo dnf install -y postgresql17-server postgresql17-contrib
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;RHEL 계열에서 dnf module disable postgresql을 빠뜨리면 OS 기본 모듈과 충돌해서 설치가 꼬입니다. 검색하면 나오는 설치 가이드 중에 이 줄이 빠진 게 꽤 많습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;contrib를 반드시 같이 설치하세요&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;postgresql-contrib에는 이런 게 들어 있습니다.&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;pg_stat_statements&lt;/td&gt;
&lt;td&gt;&lt;b&gt;쿼리별 누적 실행시간 통계.&lt;/b&gt; 슬로우 쿼리를 찾는 유일한 제대로 된 수단&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;pgstattuple&lt;/td&gt;
&lt;td&gt;테이블 팽창 정밀 측정&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;pg_buffercache&lt;/td&gt;
&lt;td&gt;버퍼 캐시 내용 조회&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;pg_trgm&lt;/td&gt;
&lt;td&gt;LIKE '%검색어%' 인덱싱&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;pgcrypto&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; 나중에 넣으려면 shared_preload_libraries 변경 &amp;rarr; 재기동이 필요해서, 결국 장애 상황에서 서비스를 한 번 더 내려야 합니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고로 이 시리즈를 쓰면서 쓴 검증 환경에는 contrib가 없었습니다(샌드박스 제약). 덕분에 pg_stat_statements 없이 슬로우 쿼리를 추적하는 게 얼마나 답답한지 몸으로 겪었습니다. 로그를 뒤지는 것 말고는 방법이 없습니다.&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;2. initdb &amp;mdash; 여기서 정하면 되돌릴 수 없습니다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PostgreSQL에서 &lt;b&gt;클러스터&lt;/b&gt;는 하나의 데이터 디렉터리(PGDATA)와 그 안의 여러 데이터베이스를 뜻합니다. initdb는 이 클러스터를 만드는 명령입니다.&lt;/p&gt;
&lt;pre class=&quot;crystal&quot;&gt;&lt;code&gt;initdb -D /var/lib/pgsql/17/data \
       -U postgres \
       --encoding=UTF8 \
       --locale=C \
       --data-checksums
&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;Data page checksums are enabled.
creating subdirectories ... ok
selecting dynamic shared memory implementation ... posix
selecting default max_connections ... 100
selecting default shared_buffers ... 128MB
selecting default time zone ... Asia/Seoul
creating configuration files ... ok
running bootstrap script ... ok
performing post-bootstrap initialization ... ok
syncing data to disk ... ok

initdb: warning: enabling &quot;trust&quot; authentication for local connections
initdb: hint: You can change this by editing pg_hba.conf or using the option -A, ...

Success. You can now start the database server using:
    pg_ctl -D /var/lib/pgsql/17/data -l logfile start
&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;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;① --data-checksums &amp;mdash; 무조건 켜세요&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;디스크에서 비트가 조용히 뒤집히는 일(silent corruption)은 생각보다 자주 일어납니다. 체크섬이 없으면 &lt;b&gt;데이터가 깨져도 아무도 모릅니다.&lt;/b&gt; 깨진 값이 그대로 조회되고, 그대로 백업되고, 그대로 복제됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;체크섬을 켜면 손상된 페이지를 읽을 때 에러를 냅니다. 문제를 &quot;지금&quot; 알게 되는 거죠.&lt;/p&gt;
&lt;pre class=&quot;applescript&quot;&gt;&lt;code&gt;$ psql -c &quot;SHOW data_checksums;&quot;
 data_checksums
----------------
 on
&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;PostgreSQL 18부터는 기본값이 on입니다.&lt;/b&gt; 17 이하라면 직접 지정해야 합니다. 이미 만든 클러스터에 나중에 켜려면 pg_checksums 명령으로 가능하지만, &lt;b&gt;DB를 정지시킨 상태에서 전체 페이지를 다시 써야 합니다.&lt;/b&gt; 100GB면 서비스 중단 시간이 꽤 깁니다. 처음에 켜세요.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;② --locale=C &amp;mdash; 한국어 서비스에서도 이게 맞습니다&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기가 제일 오해가 많은 지점입니다. &quot;한국어 데이터니까 ko_KR.UTF-8을 써야 하는 거 아닌가?&quot; 싶으실 텐데요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;실제로 C 로케일에서 한글이 어떻게 정렬되는지 보시죠.&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;SELECT unnest(ARRAY['하늘','가방','나무','다리','마을']) AS w ORDER BY 1;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;asciidoc&quot;&gt;&lt;code&gt;  w
------
 가방
 나무
 다리
 마을
 하늘
&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;우연이 아닙니다. 유니코드의 한글 음절 블록(U+AC00~U+D7A3)이 &lt;b&gt;초성-중성-종성 순서로 배열&lt;/b&gt;되어 있어서, 코드포인트 순서가 곧 한글 사전순입니다. C 로케일은 바이트 순서로 정렬하는데, UTF-8은 코드포인트 순서를 보존하므로 결과가 같아집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 C 로케일에서 뭐가 다르냐면, &lt;b&gt;영문 대소문자&lt;/b&gt;입니다.&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- C 로케일 (기본)
SELECT w FROM unnest(ARRAY['apple','Banana','apricot','Avocado','cherry']) AS t(w) ORDER BY w;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;armasm&quot;&gt;&lt;code&gt; Avocado
 Banana
 apple
 apricot
 cherry
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대문자가 전부 앞으로 나옵니다. 사람이 기대하는 순서는 아니죠. 이건 컬럼 단위로 COLLATE를 지정하면 해결됩니다.&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;SELECT w FROM unnest(ARRAY['apple','Banana','apricot','Avocado','cherry']) AS t(w)
ORDER BY w COLLATE &quot;en_US.utf8&quot;;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;armasm&quot;&gt;&lt;code&gt; apple
 apricot
 Avocado
 Banana
 cherry
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;C 로케일을 쓰면 얻는 것&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;첫째, LIKE '접두어%' 가 인덱스를 그냥 탑니다.&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;EXPLAIN (COSTS OFF) SELECT * FROM customers WHERE email LIKE 'user100%';
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt; Bitmap Heap Scan on customers
   Filter: (email ~~ 'user100%'::text)
   -&amp;gt;  Bitmap Index Scan on customers_email_key
         Index Cond: ((email &amp;gt;= 'user100'::text) AND (email &amp;lt; 'user101'::text))
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반 인덱스가 접두어 검색 범위로 변환됐습니다. &lt;b&gt;C 이외의 로케일에서는 이게 안 됩니다.&lt;/b&gt; text_pattern_ops 연산자 클래스를 지정한 별도 인덱스를 하나 더 만들어야 합니다.&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- C 로케일이 아니라면 이런 인덱스가 추가로 필요합니다
CREATE INDEX idx_customers_email_pattern ON customers(email text_pattern_ops);
&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;셋째, 이게 제일 중요한데 &amp;mdash; glibc 업그레이드 사고를 원천 차단합니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OS를 업그레이드하면 glibc의 정렬 규칙이 바뀝니다. 그러면 기존에 만들어 둔 문자열 인덱스는 &lt;b&gt;논리적으로 깨진 상태&lt;/b&gt;가 됩니다. 인덱스는 옛 규칙으로 정렬돼 있는데 검색은 새 규칙으로 하니까, &lt;b&gt;분명히 있는 데이터가 조회되지 않습니다.&lt;/b&gt; UNIQUE 제약이 뚫려서 중복이 들어가기도 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;에러도 안 납니다. 그냥 조용히 틀린 답을 줍니다. 겪어본 사람들이 하나같이 치를 떠는 이유입니다.&lt;/p&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;-- 지금 클러스터의 로케일 확인
SELECT datname, datcollate, datctype, pg_encoding_to_char(encoding) AS encoding
FROM pg_database WHERE datname = 'shop';
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;asciidoc&quot;&gt;&lt;code&gt; datname | datcollate | datctype | encoding
---------+------------+----------+----------
 shop    | C          | C        | UTF8
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;C 로케일은 정렬 규칙이 &quot;바이트 순서&quot;로 고정이라 OS가 바뀌어도 변하지 않습니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;PostgreSQL 15 이상이면 ICU 콜레이션이라는 더 나은 선택지가 있습니다.&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;initdb --locale-provider=icu --icu-locale=ko-KR --encoding=UTF8 ...
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ICU는 정렬 규칙 버전이 DB에 기록되어서, 규칙이 바뀌면 PostgreSQL이 &lt;b&gt;경고를 띄웁니다.&lt;/b&gt; glibc처럼 조용히 깨지지 않습니다. 다만 ICU 라이브러리를 포함해 빌드된 패키지여야 합니다. 확인은 이렇게:&lt;/p&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;SELECT collname FROM pg_collation WHERE collprovider = 'i' LIMIT 5;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(ICU 미지원 빌드에서는 CREATE COLLATION ... provider = icu 시 ERROR: ICU is not supported in this build가 납니다.)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;정리하면 &amp;mdash; 클러스터는 C 또는 ICU로 만들고, 로케일별 정렬이 필요한 곳에만 COLLATE를 붙이세요.&lt;/b&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;③ 마지막 경고 줄을 읽으세요&lt;/h3&gt;
&lt;pre class=&quot;groovy&quot;&gt;&lt;code&gt;initdb: warning: enabling &quot;trust&quot; authentication for local connections
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;trust는 &quot;비밀번호 없이 아무나 들어와도 된다&quot;는 뜻입니다.&lt;/b&gt; 로컬 접속 한정이지만, 서버에 셸을 딸 수 있는 사람은 누구나 슈퍼유저로 DB에 들어옵니다. 애플리케이션 계정 하나만 뚫려도 끝입니다.&lt;/p&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;3. postgresql.conf &amp;mdash; 처음 손댈 것만&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;먼저, 파일 위치는 SQL로 확인하세요&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;SHOW config_file;
SHOW hba_file;
SHOW data_directory;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;asciidoc&quot;&gt;&lt;code&gt;                    config_file
----------------------------------------------------
 /var/lib/pgsql/17/data/postgresql.conf

                    hba_file
------------------------------------------------
 /var/lib/pgsql/17/data/pg_hba.conf
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Debian/Ubuntu 계열은 설정이 /etc/postgresql/17/main/에, 데이터가 /var/lib/postgresql/17/main/에 따로 있습니다. RHEL 계열은 둘 다 PGDATA 안에 있습니다. 그래서 더더욱 SQL로 확인하는 게 확실합니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;설정을 바꾸는 3가지 방법&lt;/h3&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;-- 1) 파일 직접 편집 (전통적)
-- 2) ALTER SYSTEM (postgresql.auto.conf에 기록, 파일보다 우선)
ALTER SYSTEM SET log_min_duration_statement = '200ms';
SELECT pg_reload_conf();

-- 3) 세션/롤 단위
SET work_mem = '256MB';                          -- 현재 세션만
ALTER ROLE reporter SET statement_timeout = '10min';   -- 해당 롤 접속 시마다
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ALTER SYSTEM은 편하지만 &lt;b&gt;파일에 뭐가 적혀 있는지와 실제 동작이 달라질 수 있어서&lt;/b&gt; 헷갈립니다. 현재 값은 항상 pg_settings로 확인하세요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;재기동이 필요한지 아닌지 &amp;mdash; context 컬럼&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 name, setting, context FROM pg_settings
WHERE name IN ('shared_buffers','work_mem','max_connections','random_page_cost',
               'log_min_duration_statement','wal_level','archive_command',
               'effective_cache_size','autovacuum_naptime','listen_addresses')
ORDER BY context, name;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;            name            |  setting  |  context
----------------------------+-----------+------------
 listen_addresses           | localhost | postmaster    &amp;larr; 재기동 필요
 max_connections            | 100       | postmaster    &amp;larr; 재기동 필요
 shared_buffers             | 16384     | postmaster    &amp;larr; 재기동 필요
 wal_level                  | replica   | postmaster    &amp;larr; 재기동 필요
 archive_command            | test ! ...| sighup        &amp;larr; reload로 충분
 autovacuum_naptime         | 60        | sighup        &amp;larr; reload로 충분
 log_min_duration_statement | 200       | superuser     &amp;larr; 세션에서도 변경 가능
 effective_cache_size       | 524288    | user          &amp;larr; 아무나 세션에서 변경 가능
 random_page_cost           | 4         | user
 work_mem                   | 4096      | user
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;context 의미 개수&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&lt;/td&gt;
&lt;td&gt;세션에서 SET으로 즉시 변경&lt;/td&gt;
&lt;td&gt;141&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;sighup&lt;/td&gt;
&lt;td&gt;pg_reload_conf() 로 반영&lt;/td&gt;
&lt;td&gt;94&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;postmaster&lt;/td&gt;
&lt;td&gt;&lt;b&gt;재기동 필요&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;57&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;superuser&lt;/td&gt;
&lt;td&gt;슈퍼유저만 세션 변경 가능&lt;/td&gt;
&lt;td&gt;44&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;internal&lt;/td&gt;
&lt;td&gt;컴파일 시 결정, 변경 불가&lt;/td&gt;
&lt;td&gt;18&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;sighup 파라미터는 무중단으로 바뀝니다.&lt;/b&gt; 실제로 해보면:&lt;/p&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;SHOW autovacuum_naptime;        -- 1min
ALTER SYSTEM SET autovacuum_naptime = '30s';
SELECT pg_reload_conf();
SHOW autovacuum_naptime;        -- 30s
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;postmaster 파라미터는 reload해도 안 먹습니다.&lt;/b&gt; 대신 PostgreSQL이 &quot;재기동 대기 중&quot;이라고 알려줍니다.&lt;/p&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;ALTER SYSTEM SET shared_buffers = '256MB';
SELECT pg_reload_conf();

SELECT name, setting, unit, pending_restart FROM pg_settings WHERE pending_restart;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;asciidoc&quot;&gt;&lt;code&gt;      name      | setting | unit | pending_restart
----------------+---------+------+-----------------
 shared_buffers | 16384   | 8kB  | t
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;pending_restart가 t인 항목이 있는지 배포 후 확인하는 습관을 들이세요.&lt;/b&gt; &quot;설정을 바꿨는데 왜 안 먹지?&quot;의 대부분이 이겁니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;초기 설정 &amp;mdash; 메모리 16GB 서버 기준&lt;/h3&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;# --- 접속 ---
listen_addresses = 'localhost'     # 앱 서버가 따로면 해당 대역만
port = 5432
max_connections = 100              # 무작정 늘리지 마세요

# --- 메모리 ---
shared_buffers = 4GB               # 물리 메모리의 25%
effective_cache_size = 12GB        # 75%. 실제 할당이 아니라 옵티마이저 힌트
work_mem = 16MB                    # 세션&amp;times;정렬연산 단위로 잡힙니다
maintenance_work_mem = 1GB         # VACUUM / CREATE INDEX 속도에 직결

# --- 디스크 ---
random_page_cost = 1.1             # SSD면 반드시 낮추세요 (기본 4.0은 HDD 가정)
effective_io_concurrency = 200

# --- WAL ---
wal_level = replica
max_wal_size = 4GB
checkpoint_timeout = 15min
checkpoint_completion_target = 0.9

# --- 로깅 (운영 필수) ---
logging_collector = on
log_directory = 'log'
log_min_duration_statement = 200   # 200ms 넘는 쿼리 전부 기록
log_line_prefix = '%m [%p] %u@%d %a %h '
log_checkpoints = on
log_lock_waits = on
log_temp_files = 0
log_autovacuum_min_duration = 0

# --- 타임아웃 (사고 예방) ---
lock_timeout = 5s
idle_in_transaction_session_timeout = 5min
&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;random_page_cost = 1.1&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본값 4.0은 회전 디스크를 가정한 값입니다. SSD 서버에서 이걸 그대로 두면 옵티마이저가 인덱스 스캔을 부당하게 싫어하고 순차 스캔을 고릅니다. &lt;b&gt;인덱스를 만들었는데 안 타는 이유 중 상당수가 이겁니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;log_min_duration_statement = 200&lt;/b&gt;&lt;/p&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;work_mem은 함정이 있습니다.&lt;/b&gt; &quot;커넥션당&quot;이 아니라 &lt;b&gt;&quot;쿼리 안의 정렬/해시 연산 하나당&quot;&lt;/b&gt; 입니다. 복잡한 쿼리 하나가 정렬 3개 + 해시 2개를 쓰면 work_mem &amp;times; 5를 잡습니다. 여기에 동시 접속 100개를 곱하면 서버가 OOM으로 죽습니다. &lt;b&gt;전역은 보수적으로(8~32MB) 두고, 무거운 배치에서만 SET LOCAL work_mem = '512MB'로 올리세요.&lt;/b&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;OS 레벨에서 하나만 &amp;mdash; THP 끄기&lt;/h3&gt;
&lt;pre class=&quot;crystal&quot;&gt;&lt;code&gt;echo never &amp;gt; /sys/kernel/mm/transparent_hugepage/enabled
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Transparent Huge Pages가 켜져 있으면 예측 불가능한 지연 스파이크가 생깁니다. PostgreSQL뿐 아니라 거의 모든 DB의 공통 권고사항입니다. 부팅 시 적용되도록 systemd 유닛이나 GRUB 파라미터로 고정하세요.&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. pg_hba.conf &amp;mdash; 여기서 사고가 납니다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;initdb가 만들어 준 기본 파일입니다.&lt;/p&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;# TYPE  DATABASE        USER            ADDRESS                 METHOD
local   all             all                                     trust
host    all             all             127.0.0.1/32            trust
host    all             all             ::1/128                 trust
local   replication     all                                     trust
host    replication     all             127.0.0.1/32            trust
host    replication     all             ::1/128                 trust
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;전부 trust입니다.&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;# TYPE  DATABASE  USER      ADDRESS         METHOD
local   all       postgres                  peer
host    shop      app_rw    10.0.1.0/24     scram-sha-256
host    shop      reporter  10.0.2.15/32    scram-sha-256
host    all       all       0.0.0.0/0       reject
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;pg_hba.conf는 &lt;b&gt;위에서부터 순서대로 평가하고, 처음 매칭된 줄로 확정&lt;/b&gt;합니다. 아래에 더 엄격한 규칙이 있어도 소용없습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 맨 위에 trust 줄이 하나 남아 있으면 &lt;b&gt;그 아래 모든 규칙이 무의미해집니다.&lt;/b&gt; 흔한 사고 패턴이 이렇습니다: 보안 설정을 열심히 추가했는데, 기본 trust 줄을 지우는 걸 잊는 것.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;마지막에 reject 줄을 두는 걸 습관화하세요.&lt;/b&gt; 의도하지 않은 접속을 명시적으로 막습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;규칙 ②: md5 말고 scram-sha-256&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;md5는 레거시입니다. PostgreSQL 10부터 scram-sha-256이 들어왔고, 14부터는 기본값입니다.&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;SHOW password_encryption;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt; scram-sha-256
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제로 어떻게 저장되는지 확인할 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;SELECT rolname, left(rolpassword, 14) AS stored_as
FROM pg_authid WHERE rolpassword IS NOT NULL;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;asciidoc&quot;&gt;&lt;code&gt; rolname  |   stored_as
----------+----------------
 repl     | SCRAM-SHA-256$
 reporter | SCRAM-SHA-256$
&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;password_encryption을 바꿔도 기존 비밀번호는 그대로입니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실험해 봤습니다. md5로 계정을 하나 만들고:&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;SET password_encryption = 'md5';
CREATE ROLE legacy_user LOGIN PASSWORD 'secret123';
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;asciidoc&quot;&gt;&lt;code&gt;   rolname   | stored_as
-------------+------------
 legacy_user | md57e8388b     &amp;larr; md5 해시
 reporter    | SCRAM-SHA-
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 password_encryption을 scram-sha-256으로 되돌리고 다시 확인하면:&lt;/p&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;SHOW password_encryption;          -- scram-sha-256
SELECT rolname, left(rolpassword,10) FROM pg_authid WHERE rolname='legacy_user';
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;asciidoc&quot;&gt;&lt;code&gt;   rolname   | stored_as
-------------+------------
 legacy_user | md57e8388b     &amp;larr; 여전히 md5
&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;sql&quot;&gt;&lt;code&gt;ALTER ROLE legacy_user PASSWORD 'secret123';   -- 같은 비밀번호라도 다시 설정
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;asciidoc&quot;&gt;&lt;code&gt;   rolname   |   stored_as
-------------+----------------
 legacy_user | SCRAM-SHA-256$
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구버전에서 업그레이드해 온 클러스터라면 &lt;b&gt;반드시 확인하세요.&lt;/b&gt; pg_hba.conf를 scram-sha-256으로 바꿨는데 md5 해시만 있는 계정은 아예 로그인이 안 됩니다. 배포 직후 장애로 이어집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전수 점검 쿼리:&lt;/p&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;SELECT rolname,
       CASE WHEN rolpassword LIKE 'SCRAM-SHA-256$%' THEN 'scram'
            WHEN rolpassword LIKE 'md5%'           THEN 'md5 (전환 필요)'
            ELSE '없음/기타' END AS pw_type
FROM pg_authid WHERE rolcanlogin ORDER BY 2, 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;METHOD 언제&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;scram-sha-256&lt;/td&gt;
&lt;td&gt;&lt;b&gt;기본 선택.&lt;/b&gt; 앱/사용자 계정&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;peer&lt;/td&gt;
&lt;td&gt;로컬 유닉스 소켓. OS 계정명 = DB 롤명일 때. postgres 유지보수 접속에 편리&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;cert&lt;/td&gt;
&lt;td&gt;클라이언트 인증서. 보안 요구가 높을 때&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;trust&lt;/td&gt;
&lt;td&gt;&lt;b&gt;운영 금지&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;md5&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;llvm&quot;&gt;&lt;code&gt;psql -c &quot;SELECT pg_reload_conf();&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;p data-ke-size=&quot;size16&quot;&gt;적용 결과는 이 뷰로 확인할 수 있습니다 (PostgreSQL 10+).&lt;/p&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;SELECT line_number, type, database, user_name, address, auth_method, error
FROM pg_hba_file_rules;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;gherkin&quot;&gt;&lt;code&gt; line_number | type  |   database    | user_name |  address  | auth_method | error
-------------+-------+---------------+-----------+-----------+-------------+-------
         117 | local | {all}         | {all}     |           | trust       |
         119 | host  | {all}         | {all}     | 127.0.0.1 | trust       |
         121 | host  | {all}         | {all}     | ::1       | trust       |
         124 | local | {replication} | {all}     |           | trust       |
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;error 컬럼이 비어 있지 않으면 문법 오류입니다. &lt;b&gt;reload 전에 이걸로 검증하는 습관을 들이면 &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;5. 기동하고 확인하기&lt;/h2&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;sudo systemctl enable --now postgresql-17
sudo systemctl status postgresql-17

# 또는 pg_ctl 직접
pg_ctl -D $PGDATA -l $PGDATA/startup.log start
&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;SELECT version();
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt; PostgreSQL 16.2 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 10.2.1, 64-bit
&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;슈퍼유저로 애플리케이션을 붙이지 마세요. SQL 인젝션 하나로 COPY ... FROM PROGRAM을 통해 서버 셸이 열립니다.&lt;/p&gt;
&lt;pre class=&quot;sql&quot;&gt;&lt;code&gt;-- 1) 권한 묶음 롤 (로그인 불가)
CREATE ROLE app_rw NOLOGIN;
CREATE ROLE app_ro NOLOGIN;

GRANT CONNECT ON DATABASE shop TO app_rw, app_ro;
GRANT USAGE ON SCHEMA public TO app_rw, app_ro;
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO app_rw;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO app_ro;

-- 2) 앞으로 만들 테이블에도 자동 적용 &amp;larr; 이거 빼먹으면 매번 GRANT 해야 합니다
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO app_ro;
ALTER DEFAULT PRIVILEGES IN SCHEMA public
  GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO app_rw;

-- 3) 실제 접속 계정
CREATE ROLE api LOGIN PASSWORD '...';
GRANT app_rw TO api;

-- 4) 폭주 방지
ALTER ROLE api SET statement_timeout = '30s';
ALTER ROLE api SET idle_in_transaction_session_timeout = '60s';
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;ALTER DEFAULT PRIVILEGES는 꼭 넣으세요.&lt;/b&gt; 이게 없으면 새 테이블을 만들 때마다 조회 계정에 GRANT를 다시 해야 합니다. &quot;리포팅 계정이 새로 만든 테이블만 못 봐요&quot; 문의의 대부분이 이것 때문입니다.&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;6. 배포 전 체크리스트&lt;/h2&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;□ PGDG 저장소로 최신 지원 버전을 설치했는가 (배포판 기본 X)
□ postgresql-contrib 를 함께 설치했는가
□ initdb 에 --data-checksums 를 줬는가        &amp;rarr; SHOW data_checksums
□ 로케일이 C 또는 ICU 인가                     &amp;rarr; SELECT datcollate FROM pg_database
□ 인코딩이 UTF8 인가
□ pg_hba.conf 에 trust 가 남아 있지 않은가
□ 인증이 scram-sha-256 인가
□ 기존 계정이 전부 SCRAM 해시로 저장돼 있는가  &amp;rarr; pg_authid 조회
□ pg_hba_file_rules 에 error 가 없는가
□ log_min_duration_statement / log_checkpoints / log_lock_waits 를 켰는가
□ random_page_cost 를 SSD 에 맞게 낮췄는가
□ pending_restart 가 비어 있는가
□ 앱 계정이 슈퍼유저가 아니고, ALTER DEFAULT PRIVILEGES 를 걸었는가
□ THP 를 껐는가
□ statement_timeout / idle_in_transaction_session_timeout 을 설정했는가
&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;되돌릴 수 없는 결정은 세 개&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; &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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 글에서는 &lt;b&gt;자료형과 제약조건&lt;/b&gt;을 다룹니다. numeric과 float의 차이 때문에 정산이 1원씩 틀어지는 이유, timestamp와 timestamptz를 잘못 고르면 글로벌 서비스에서 무슨 일이 생기는지, 그리고 NOT IN에 NULL이 하나 섞였을 때 쿼리 결과가 통째로 사라지는 현상을 실제 출력으로 보여드리겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>DBA 실무/PostgreSQL</category>
      <category>PostgreSQL 데이터 체크섬</category>
      <category>PostgreSQL 로케일</category>
      <category>PostgreSQL 배포</category>
      <category>PostgreSQL 설정</category>
      <category>postgresql 설치</category>
      <category>PostgreSQL 인증</category>
      <category>PostgreSQL 인코딩</category>
      <category>소니스토리</category>
      <author>isony</author>
      <guid isPermaLink="true">https://isony.tistory.com/369</guid>
      <comments>https://isony.tistory.com/entry/PostgreSQL-%EC%84%A4%EC%B9%98%ED%95%A0-%EB%95%8C-%EC%A0%95%ED%95%9C-%EA%B1%B8%EB%A1%9C-3%EB%85%84%EC%9D%84-%EC%82%BD%EB%8B%88%EB%8B%A4-%E2%80%94-%EC%84%A4%EC%B9%98%EB%B6%80%ED%84%B0-%EC%B4%88%EA%B8%B0-%EC%84%A4%EC%A0%95%EA%B9%8C%EC%A7%80#entry369comment</comments>
      <pubDate>Mon, 10 Aug 2026 21:28:23 +0900</pubDate>
    </item>
    <item>
      <title>2026년08월09일 주일예배 - 1부/2부</title>
      <link>https://isony.tistory.com/entry/2026%EB%85%8408%EC%9B%9409%EC%9D%BC-%EC%A3%BC%EC%9D%BC%EC%98%88%EB%B0%B0-%EC%A0%95%ED%9A%8C%EC%84%B1%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년08월09일 주일예배 (정회성목사님) - 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; 누가복음 7:36 ~ 50 말씀 (출처:개역개정)&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;7:36 한 바리새인이 예수께 자기와 함께 잡수시기를 청하니 이에 바리새인의 집에 들어가 앉으셨을 때에&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;7:37 그 동네에 죄를 지은 한 여자가 있어 예수께서 바리새인의 집에 앉아 계심을 알고 향유 담은 옥합을 가지고 와서&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;7:38 예수의 뒤로 그 발 곁에 서서 울며 눈물로 그 발을 적시고 자기 머리털로 닦고 그 발에 입맞추고 향유를 부으니&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;7:39 예수를 청한 바리새인이 이것을 보고 마음에 이르되 이 사람이 만일 선지자더면 자기를 만지는 이 여자가 누구며 어떠한 자 곧 죄인인 줄을 알았으리라 하거늘&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;7:40 예수께서 대답하여 이르시되 시몬아 내가 네게 이를 말이 있다 하시니 그가 이르되 선생님 말씀하소서&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;7:41 이르시되 빚 주는 사람에게 빚진 자가 둘이 있어 하나는 오백 데나리온을 졌고 하나는 오십 데나리온을 졌는데&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;7:42 갚을 것이 없으므로 둘 다 탕감하여 주었으니 둘 중에 누가 그를 더 사랑하겠느냐&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;7:43 시몬이 대답하여 이르되 내 생각에는 많이 탕감함을 받은 자니이다 이르시되 네 판단이 옳다 하시고&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;7:44 그 여자를 돌아보시며 시몬에게 이르시되 이 여자를 보느냐 내가 네 집에 들어올 때 너는 내게 발 씻을 물도 주지 아니하였으되 이 여자는 눈물로 내 발을 적시고 그 머리털로 닦았으며&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;7:45 너는 내게 입맞추지 아니하였으되 그는 내가 들어올 때로부터 내 발에 입맞추기를 그치지 아니하였으며&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;7:46 너는 내 머리에 감람유도 붓지 아니하였으되 그는 향유를 내 발에 부었느니라&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;7:47 이러므로 내가 네게 말하노니 그의 많은 죄가 사하여졌도다 이는 그의 사랑함이 많음이라 사함을 받은 일이 적은 자는 적게 사랑하느니라&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;7:48 이에 여자에게 이르시되 네 죄사함을 받았느니라 하시니&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;7:49 함께 앉아 있는 자들이 속으로 말하되 이가 누구이기에 죄도 사하는가 하더라&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;7:50 예수께서 여자에게 이르시되 네 믿음이 너를 구원하였으니 평안히 가라 하시니라&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/1jGsQU5mB9Q&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://youtu.be/1jGsQU5mB9Q&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=1jGsQU5mB9Q&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/uhX5U/dJMb85W8VDU/fMNY85zrrViLeCbGJygLCK/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=0_0_1280_720,https://scrap.kakaocdn.net/dn/srXcc/dJMb89yteLw/iA59mpk92caV9JZX8O1L41/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=0_0_1280_720&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 08 09&quot; data-original-url=&quot;&quot;&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/1jGsQU5mB9Q&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;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;2026년08월09일 주일예배 (오민목사님) - 2부&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:1 ~ 17 말씀 (출처:우리말성경)&lt;/h2&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; 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 &amp;ldquo;일어나 저 큰 성읍 니느웨로 가서 그 도시에 선포하여라. 이는 그 도시의 죄악이 내 앞에까지 이르렀기 때문이다.&amp;rdquo;&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 선장이 그에게 다가와서 말했습니다. &amp;ldquo;네가 어떻게 잠을 잘 수 있느냐? 일어나 네 하나님께 소리쳐 부르짖어라! 혹시 하나님께서 우리를 생각해서 우리가 죽지 않게 될지도 모른다.&amp;rdquo;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;1:7 선원들이 서로 말했습니다. &amp;ldquo;이리 와서 제비를 뽑아 이 재난이 누구 탓인지 알아내자.&amp;rdquo; 그들이 제비를 뽑았더니 제비가 요나에게 뽑혔습니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;1:8 그러자 그들이 그에게 물었습니다. &amp;ldquo;우리에게 닥친 이 재난이 누구 때문인지 말해 보아라. 네 직업은 무엇이냐? 어디에서 오느냐? 어느 나라 사람이냐? 네가 어느 민족이냐?&amp;rdquo;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;1:9 요나가 대답했습니다. &amp;ldquo;나는 히브리 사람입니다. 바다와 땅을 만드신 하늘의 하나님 여호와를 섬기고 있습니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;1: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;1:11 바다에 폭풍이 점점 더 거세졌습니다. 그들이 그에게 말했습니다. &amp;ldquo;바다를 진정시키려면 대체 우리가 네게 어떻게 해야 하느냐?&amp;rdquo;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;1: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;1:13 그러나 그들은 육지로 돌아가려고 힘껏 노를 저었습니다. 그럴지라도 소용이 없었습니다. 바다에 폭풍이 더 거세졌습니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;1: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;1:15 그리고 그들은 요나를 들어서 바다 속으로 던졌습니다. 그러자 사나운 바다가 잠잠해졌습니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;1:16 그들이 여호와를 크게 두려워해 그들은 여호와께 희생제물을 드리고 서원했습니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;1:17 그러나 여호와께서는 큰 물고기를 준비하셔서 요나를 삼키게 하셨습니다. 요나는 그 물고기 뱃속에서 3일 밤낮을 보냈습니다.&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/v9hWfoj8sx8&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://youtu.be/v9hWfoj8sx8&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=v9hWfoj8sx8&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/b2U5rG/dJMb9cBXllq/cTf0jrkxSL233jmeb2IVt1/img.jpg?width=480&amp;amp;height=360&amp;amp;face=196_101_261_172,https://scrap.kakaocdn.net/dn/DjfZi/dJMb83SyEXe/RzY45iPogxzALbn9x19dl0/img.jpg?width=480&amp;amp;height=360&amp;amp;face=196_101_261_172,https://scrap.kakaocdn.net/dn/fyblb/dJMb81Hc6LR/SuRwkpnTYi83IFi26BsmI1/img.jpg?width=480&amp;amp;height=360&amp;amp;face=196_101_261_172&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 08 092&quot; data-original-url=&quot;&quot;&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/v9hWfoj8sx8&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;
&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>누가복음 7장</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/368</guid>
      <comments>https://isony.tistory.com/entry/2026%EB%85%8408%EC%9B%9409%EC%9D%BC-%EC%A3%BC%EC%9D%BC%EC%98%88%EB%B0%B0-%EC%A0%95%ED%9A%8C%EC%84%B1%EB%AA%A9%EC%82%AC%EB%8B%98-1%EB%B6%80#entry368comment</comments>
      <pubDate>Sun, 9 Aug 2026 08:06:29 +0900</pubDate>
    </item>
    <item>
      <title>[Claude 시리즈 13편] Claude Code로 개인 자산 만들기 - 쓸수록 쌓이는 자동화 시스템 (Phase 3 완결)</title>
      <link>https://isony.tistory.com/entry/Claude-%EC%8B%9C%EB%A6%AC%EC%A6%88-13%ED%8E%B8-Claude-Code%EB%A1%9C-%EA%B0%9C%EC%9D%B8-%EC%9E%90%EC%82%B0-%EB%A7%8C%EB%93%A4%EA%B8%B0-%EC%93%B8%EC%88%98%EB%A1%9D-%EC%8C%93%EC%9D%B4%EB%8A%94-%EC%9E%90%EB%8F%99%ED%99%94-%EC%8B%9C%EC%8A%A4%ED%85%9C-Phase-3-%EC%99%84%EA%B2%B0</link>
      <description>&lt;h1&gt;[Claude 시리즈 13편] Claude Code로 개인 자산 만들기 - 쓸수록 쌓이는 자동화 시스템 (Phase 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, MCP, Skills, CLAUDE.md (2026년 7월 기준)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대부분의 사람은 AI를 &lt;b&gt;일회용&lt;/b&gt;으로 씁니다. 질문하고, 답 받고, 끝. 다음에 또 처음부터.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 진짜 고수는 다르게 씁니다. AI를 쓸 때마다 &lt;b&gt;뭔가가 쌓입니다.&lt;/b&gt; 프롬프트가 템플릿이 되고, 반복 작업이 Skill이 되고, 환경이 CLAUDE.md에 정리됩니다. 6개월 후 돌아보면, &lt;b&gt;본인만의 자동화 시스템&lt;/b&gt;이 만들어져 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이걸 저는 &lt;b&gt;&quot;개인 자산(personal asset)&quot;&lt;/b&gt; 이라고 부릅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글은 지금까지 배운 모든 것 &amp;mdash; &lt;a href=&quot;https://www.whodo.net/entry/Claude-%EC%8B%9C%EB%A6%AC%EC%A6%88-10%ED%8E%B8-Claude-API-%EC%82%AC%EC%9A%A9%EB%B2%95-%EA%B0%9C%EB%B0%9C%EC%9E%90%EB%A5%BC-%EC%9C%84%ED%95%9C-%EC%8B%A4%EC%A0%84-%EC%9E%85%EB%AC%B8-2026%EB%85%84-%EC%B5%9C%EC%8B%A0&quot;&gt;API&lt;/a&gt;, &lt;a href=&quot;https://www.whodo.net/entry/Claude-%EC%8B%9C%EB%A6%AC%EC%A6%88-11%ED%8E%B8-Claude-MCP-%EC%99%84%EB%B2%BD-%EC%A0%95%EB%A6%AC-AI%EB%A5%BC-%EC%99%B8%EB%B6%80-%EB%8F%84%EA%B5%AC%EC%99%80-%EC%97%B0%EA%B2%B0%ED%95%98%EB%8A%94-%ED%91%9C%EC%A4%80-2026-%EC%B5%9C%EC%8B%A0&quot;&gt;MCP&lt;/a&gt;, &lt;a href=&quot;https://www.whodo.net/entry/Claude-%EC%8B%9C%EB%A6%AC%EC%A6%88-12%ED%8E%B8-Claude-Skills-%EB%A7%8C%EB%93%A4%EA%B8%B0-%EB%B0%98%EB%B3%B5-%EC%9E%91%EC%97%85%EC%9D%84-Claude%EC%97%90%EA%B2%8C-%EA%B0%80%EB%A5%B4%EC%B9%98%EA%B8%B0-SKILLmd-%EC%99%84%EB%B2%BD-%EA%B0%80%EC%9D%B4%EB%93%9C&quot;&gt;Skills&lt;/a&gt;, &lt;a href=&quot;https://www.whodo.net/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&quot;&gt;CLAUDE.md&lt;/a&gt; &amp;mdash; 를 종합해서 나만의 자산을 구축하는 방법입니다.&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;4가지 building block 조합하기&lt;/li&gt;
&lt;li&gt;실전 구축 로드맵 (단계별)&lt;/li&gt;
&lt;li&gt;직무별 자산 구축 예시&lt;/li&gt;
&lt;li&gt;복리 효과 &amp;mdash; 왜 쌓아야 하는가&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글은 &lt;b&gt;Phase 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;&quot;개인 자산&quot;이란 무엇인가&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개인 자산은 &lt;b&gt;본인의 업무 지식과 반복 작업이 코드&amp;middot;설정&amp;middot;문서로 축적된 시스템&lt;/b&gt;입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;일회용 사용 vs 자산 축적&lt;/h3&gt;
&lt;pre class=&quot;gcode&quot;&gt;&lt;code&gt;일회용 사용:
매번 환경 설명 &amp;rarr; 매번 절차 설명 &amp;rarr; 답 받고 끝
&amp;rarr; 다음에 또 처음부터

자산 축적:
CLAUDE.md에 환경 기록 (한 번)
Skill에 절차 저장 (한 번)
MCP로 도구 연결 (한 번)
&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;&lt;b&gt;CLAUDE.md&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;환경&amp;middot;규칙&lt;/td&gt;
&lt;td&gt;&quot;이 프로젝트는 Oracle 19c&quot;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;Skills&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;반복 절차&lt;/td&gt;
&lt;td&gt;&quot;장애 진단 절차&quot;, &quot;보고서 형식&quot;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;MCP 연결&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;도구 접근&lt;/td&gt;
&lt;td&gt;DB, GitHub, 모니터링&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;프롬프트 라이브러리&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;검증된 요청&lt;/td&gt;
&lt;td&gt;자주 쓰는 프롬프트 모음&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;스크립트 모음&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;자동화 코드&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가 본인의 업무 방식을 아는 상태&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가지 Building Block 조합하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금까지 배운 4가지를 어떻게 조합하는지가 핵심입니다.&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;CLAUDE.md &amp;rarr; &quot;이 환경은 이렇다&quot; (항상 적용)
Skills    &amp;rarr; &quot;이 작업은 이렇게 한다&quot; (필요시)
MCP       &amp;rarr; &quot;이 도구에 접근한다&quot; (외부 연결)
API       &amp;rarr; &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;하나씩 쓸 때보다 함께 쓸 때 강력합니다.&lt;/p&gt;
&lt;pre class=&quot;excel&quot;&gt;&lt;code&gt;예: DBA 운영 자산

CLAUDE.md: Oracle 19c 환경, 명명 규칙, 금지 사항
    +
Skills: &quot;장애 진단 절차&quot;, &quot;AWR 분석법&quot;, &quot;백업 점검&quot;
    +
MCP: 운영 DB 조회, 모니터링 시스템 연결
    +
스크립트: 자주 쓰는 진단 SQL, 점검 스크립트

= Claude가 본인 환경을 완전히 이해하고
  실제 도구에 접근하며 표준 절차로 일하는 시스템
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 상태가 되면 &quot;ORA-01555 발생, 원인 분석해줘&quot; 한 마디에 Claude가 본인 DB를 실제 조회하고, 표준 진단 절차를 따라, 본인 환경 규칙에 맞게 답합니다.&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;less&quot;&gt;&lt;code&gt;[ ] 작업 폴더 생성 (예: ~/work)
[ ] CLAUDE.md 작성 (환경, 규칙, 금지사항)
[ ] Claude Code 설치 및 연결 확인
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CLAUDE.md는 &lt;a href=&quot;https://www.whodo.net/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&quot;&gt;Claude Code 4편&lt;/a&gt;의 템플릿을 활용하세요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2단계: 반복 작업 Skill화 (2~4주)&lt;/h3&gt;
&lt;pre class=&quot;cs&quot;&gt;&lt;code&gt;[ ] 매주 하는 작업 3개 식별
[ ] 각각을 Skill로 만들기
[ ] 실제로 쓰면서 description 다듬기
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;매번 같은 설명을 반복한다&quot; 싶으면 그게 Skill 후보입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3단계: 도구 연결 (1~2개월)&lt;/h3&gt;
&lt;pre class=&quot;less&quot;&gt;&lt;code&gt;[ ] 자주 접근하는 시스템 파악 (DB, GitHub 등)
[ ] MCP 서버 연결 (3~5개만)
[ ] 보안 점검 (권한 최소화)
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MCP는 &lt;a href=&quot;https://www.whodo.net/entry/Claude-%EC%8B%9C%EB%A6%AC%EC%A6%88-11%ED%8E%B8-Claude-MCP-%EC%99%84%EB%B2%BD-%EC%A0%95%EB%A6%AC-AI%EB%A5%BC-%EC%99%B8%EB%B6%80-%EB%8F%84%EA%B5%AC%EC%99%80-%EC%97%B0%EA%B2%B0%ED%95%98%EB%8A%94-%ED%91%9C%EC%A4%80-2026-%EC%B5%9C%EC%8B%A0&quot;&gt;11편&lt;/a&gt;을 참고하되, 너무 많이 연결하지 마세요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4단계: 프롬프트 라이브러리 (지속)&lt;/h3&gt;
&lt;pre class=&quot;cs&quot;&gt;&lt;code&gt;[ ] 효과 좋았던 프롬프트 저장
[ ] 카테고리별 정리
[ ] Projects나 Skill로 체계화
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5단계: 자동화 확장 (3개월+)&lt;/h3&gt;
&lt;pre class=&quot;cs&quot;&gt;&lt;code&gt;[ ] 반복 스크립트를 Claude Code로 관리
[ ] 필요시 API로 완전 자동화
[ ] 정기 작업 스케줄링
&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; 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;★ 직무별 자산 구축 예시&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;DBA&amp;middot;서버 관리자&lt;/h3&gt;
&lt;pre class=&quot;asciidoc&quot;&gt;&lt;code&gt;CLAUDE.md:
- Oracle 19c, Oracle Linux 8 환경
- 운영/테스트 DB 구분
- 위험 명령 금지 규칙

Skills:
- 장애 진단 절차 (에러코드별)
- AWR/성능 분석법
- 백업 점검 체크리스트
- 정기 점검 리포트 작성

MCP:
- 운영 DB 조회 (읽기 전용)
- 모니터링 시스템

스크립트:
- 일일 점검 SQL 모음
- 로그 분석 도구
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 블로그의 &lt;a href=&quot;https://www.whodo.net/category/DBA%20%EC%8B%A4%EB%AC%B4/Oracle%28%EC%98%A4%EB%9D%BC%ED%81%B4%29&quot;&gt;Oracle 시리즈&lt;/a&gt;와 &lt;a href=&quot;https://www.whodo.net/category/AI%20%28Claude%20%ED%99%9C%EC%9A%A9%29/Claude%20Code%20%EC%8B%9C%EB%A6%AC%EC%A6%88&quot;&gt;Claude Code 시리즈&lt;/a&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;CLAUDE.md:
- 기술 스택, 코드 컨벤션
- 아키텍처 개요

Skills:
- 커밋 메시지 규칙
- 코드 리뷰 체크리스트
- 릴리스 절차
- 테스트 작성 표준

MCP:
- GitHub (이슈/PR)
- 데이터베이스
- CI/CD 시스템

스크립트:
- 프로젝트 셋업 자동화
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;블로거&amp;middot;콘텐츠 제작자&lt;/h3&gt;
&lt;pre class=&quot;asciidoc&quot;&gt;&lt;code&gt;CLAUDE.md:
- 블로그 정체성, 타겟 독자
- 글쓰기 톤

Skills:
- 글 작성 절차 (구조, SEO)
- 제목 생성 규칙
- 이미지 캡션 작성

MCP:
- 파일시스템 (초안 관리)

프롬프트 라이브러리:
- 기획, 초안, 편집, SEO 프롬프트
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 블로그의 &lt;u&gt;Claude Code로 블로그 글 초안 만들기&lt;/u&gt;가 이 자산의 실제 사례입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;기획자&amp;middot;관리자&lt;/h3&gt;
&lt;pre class=&quot;asciidoc&quot;&gt;&lt;code&gt;CLAUDE.md:
- 조직 컨텍스트, 보고 체계

Skills:
- 주간/월간 보고서 형식
- 회의록 정리 절차
- 기획서 템플릿

MCP:
- 캘린더, 문서 시스템

프롬프트 라이브러리:
- 이메일, 보고, 기획 프롬프트
&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;시간이 지날수록 커진다&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;1개월차:
- CLAUDE.md + Skill 2~3개
- 약간의 시간 절약

3개월차:
- Skill 10개 + MCP 연결
- 반복 작업 대부분 자동화
- 하루 1~2시간 절약

6개월차:
- 정교한 시스템
- Claude가 본인 업무를 깊이 이해
- 하루 2~3시간 절약, 품질도 향상

1년차:
- 본인만의 업무 OS
- 신입에게 물려줄 수 있는 자산
- 이직/독립 시에도 가져가는 경쟁력
&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. Skill끼리 조합되어 더 큰 작업 처리
3. 축적된 노하우가 품질을 높임
4. 관리 비용은 늘지 않는데 효용은 증가
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;단리(매번 처음)가 아니라 복리(쌓임)&lt;/b&gt; 로 일하는 것 &amp;mdash; 이게 AI 시대 생산성의 핵심입니다.&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;입니다. CLAUDE.md, Skills, 프롬프트 라이브러리는 회사 기밀만 빼면 본인이 가져갑니다. 어디를 가도 &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;1. 버전 관리&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CLAUDE.md, Skills를 git으로 관리하면 변경 이력이 남고 백업이 됩니다.&lt;/p&gt;
&lt;pre class=&quot;jboss-cli&quot;&gt;&lt;code&gt;cd ~/work
git init
# CLAUDE.md, .claude/skills/ 등 관리
# 단, 비밀 정보는 .gitignore
&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;분기에 한 번, 안 쓰는 Skill&amp;middot;MCP를 정리하세요. 쌓이기만 하면 오히려 방해됩니다.&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;각 Skill이 뭘 하는지 간단히 기록. 6개월 후의 본인이 이해할 수 있게.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4. 보안 우선&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;MCP 권한 최소화&lt;/li&gt;
&lt;li&gt;회사 기밀과 개인 자산 분리&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5. 공유 가능한 것은 공유&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;팀에 유용한 Skill은 공유하세요. 팀 전체의 생산성이 올라갑니다.&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 3 마무리 - 심화 여정 정리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글로 &lt;b&gt;Phase 3(심화&amp;middot;전문)이 완결&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;10편&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;API &amp;mdash; Claude를 코드에 통합&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;11편&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;MCP &amp;mdash; 외부 도구 연결&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;12편&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;Skills &amp;mdash; 절차를 가르치기&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;13편&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;자산 &amp;mdash; 모든 걸 종합&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Phase 1이 &quot;Claude를 아는 것&quot;, Phase 2가 &quot;Claude로 일하는 것&quot;, Phase 3가 &lt;b&gt;&quot;Claude를 나만의 시스템으로 만드는 것&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;마무리&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;4가지 조합&lt;/b&gt; &amp;mdash; CLAUDE.md + Skills + MCP + 스크립트&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;AI를 일회용으로 쓰는 사람과 자산으로 쌓는 사람의 격차는 시간이 갈수록 벌어집니다. 오늘 CLAUDE.md 한 줄, Skill 하나부터 시작하세요. 6개월 후 본인만의 업무 시스템을 갖게 될 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금까지 Claude 시리즈 본편(오프닝~13편)을 함께해 주셔서 감사합니다. 이 시리즈 자체가 제가 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>AI 업무시스템</category>
      <category>AI 자산화</category>
      <category>Claude Code 활용</category>
      <category>Claude Skills MCP 조합</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/366</guid>
      <comments>https://isony.tistory.com/entry/Claude-%EC%8B%9C%EB%A6%AC%EC%A6%88-13%ED%8E%B8-Claude-Code%EB%A1%9C-%EA%B0%9C%EC%9D%B8-%EC%9E%90%EC%82%B0-%EB%A7%8C%EB%93%A4%EA%B8%B0-%EC%93%B8%EC%88%98%EB%A1%9D-%EC%8C%93%EC%9D%B4%EB%8A%94-%EC%9E%90%EB%8F%99%ED%99%94-%EC%8B%9C%EC%8A%A4%ED%85%9C-Phase-3-%EC%99%84%EA%B2%B0#entry366comment</comments>
      <pubDate>Fri, 7 Aug 2026 13:00:20 +0900</pubDate>
    </item>
    <item>
      <title>[Claude 시리즈 12편] Claude Skills 만들기 - 반복 작업을 Claude에게 가르치기 (SKILL.md 완벽 가이드)</title>
      <link>https://isony.tistory.com/entry/Claude-%EC%8B%9C%EB%A6%AC%EC%A6%88-12%ED%8E%B8-Claude-Skills-%EB%A7%8C%EB%93%A4%EA%B8%B0-%EB%B0%98%EB%B3%B5-%EC%9E%91%EC%97%85%EC%9D%84-Claude%EC%97%90%EA%B2%8C-%EA%B0%80%EB%A5%B4%EC%B9%98%EA%B8%B0-SKILLmd-%EC%99%84%EB%B2%BD-%EA%B0%80%EC%9D%B4%EB%93%9C</link>
      <description>&lt;h1&gt;[Claude 시리즈 12편] Claude Skills 만들기 - 반복 작업을 Claude에게 가르치기 (SKILL.md 완벽 가이드)&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, Claude.ai, Agent Skills (2026년 7월 기준)&lt;/p&gt;
&lt;/blockquote&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;&quot;보고서 만들 땐 이 형식으로, 이 순서로, 이 규칙을 지켜서...&quot; 를 매번 반복하는 대신, &lt;b&gt;한 번만 가르치고 계속 재사용&lt;/b&gt;할 수 있다면 어떨까요? 그게 &lt;b&gt;Skills(Agent Skills)&lt;/b&gt; 입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Skills는 절차&amp;middot;규칙&amp;middot;전문 지식을 &lt;b&gt;폴더 하나에 담아&lt;/b&gt; Claude에게 주는 기능입니다. Claude는 필요할 때만 자동으로 그 Skill을 불러 쓰고, 안 쓸 때는 무시합니다. 2025년 12월 오픈 표준이 되면서 Claude뿐 아니라 여러 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;Skills가 무엇이고 왜 필요한가&lt;/li&gt;
&lt;li&gt;&lt;b&gt;★ MCP vs Skills vs CLAUDE.md vs Projects&lt;/b&gt; &amp;mdash; 언제 뭘 쓸까&lt;/li&gt;
&lt;li&gt;SKILL.md 구조 완벽 해부&lt;/li&gt;
&lt;li&gt;나만의 Skill 만들기 (3가지 방법)&lt;/li&gt;
&lt;li&gt;실전 Skill 예시&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%AC%ED%99%94%28%EC%A0%84%EB%AC%B8%29&quot;&gt;Phase 3&lt;/a&gt;의 세 번째 글로, &lt;a href=&quot;https://www.whodo.net/entry/Claude-%EC%8B%9C%EB%A6%AC%EC%A6%88-11%ED%8E%B8-Claude-MCP-%EC%99%84%EB%B2%BD-%EC%A0%95%EB%A6%AC-AI%EB%A5%BC-%EC%99%B8%EB%B6%80-%EB%8F%84%EA%B5%AC%EC%99%80-%EC%97%B0%EA%B2%B0%ED%95%98%EB%8A%94-%ED%91%9C%EC%A4%80-2026-%EC%B5%9C%EC%8B%A0&quot;&gt;MCP 편&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;Skills란 무엇인가 - &quot;온디맨드 전문성&quot;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Skills를 한마디로 표현하면 &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;haml&quot;&gt;&lt;code&gt;매번 반복하는 것들:
- &quot;릴리스할 땐 테스트 &amp;rarr; 버전업 &amp;rarr; 태그 &amp;rarr; 푸시 순서로&quot;
- &quot;보고서는 이 템플릿, 이 톤, 이 구조로&quot;
- &quot;PDF 만들 땐 이 규칙 지켜서&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;Skills의 해결&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;절차를 &lt;b&gt;SKILL.md 파일&lt;/b&gt;에 한 번 적어두면:&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;1. Claude가 시작 시 Skill의 이름&amp;middot;설명만 스캔 (가벼움)
2. 관련 작업이 오면 그 Skill의 전체 내용을 로드
3. 그 절차대로 작업 수행
4. 안 쓸 때는 무시 (토큰 거의 안 씀)
&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; 판단해서 필요할 때만 씁니다. 이걸 model-invoked라고 합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2026년 현재 위상&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;2025년 12월 18일&lt;/b&gt; Agent Skills 오픈 표준 발표&lt;/li&gt;
&lt;li&gt;&lt;b&gt;26개 이상 플랫폼&lt;/b&gt; 채택 (Claude, OpenAI Codex, Gemini CLI, Cursor, VS Code 등)&lt;/li&gt;
&lt;li&gt;Anthropic이 &lt;b&gt;사전 제작 Skills&lt;/b&gt; 제공 (PowerPoint, Excel, Word, PDF)&lt;/li&gt;
&lt;li&gt;오픈소스 Skill 저장소 공개 (github.com/anthropics/skills)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MCP처럼 Skills도 특정 회사 것이 아닌 &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;★ MCP vs Skills vs CLAUDE.md vs Projects&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;CLAUDE.md&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;프로젝트 환경&amp;middot;규칙 (항상 로드)&lt;/td&gt;
&lt;td&gt;회사 취업 규칙&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;Skills&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;특정 절차&amp;middot;전문성 (필요시 로드)&lt;/td&gt;
&lt;td&gt;업무 매뉴얼&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;MCP&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;외부 도구&amp;middot;데이터 연결&lt;/td&gt;
&lt;td&gt;도구함&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;Projects&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;h3 data-ke-size=&quot;size23&quot;&gt;언제 무엇을 쓰나&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;CLAUDE.md&lt;/b&gt; &amp;mdash; &quot;이 프로젝트는 이런 환경이다&quot;&lt;/p&gt;
&lt;pre class=&quot;haml&quot;&gt;&lt;code&gt;- 항상 적용되는 규칙
- 예: &quot;이 프로젝트는 pnpm 사용, TypeScript, 이 코드 스타일&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Skills&lt;/b&gt; &amp;mdash; &quot;이 작업은 이렇게 하는 것이다&quot;&lt;/p&gt;
&lt;pre class=&quot;haml&quot;&gt;&lt;code&gt;- 특정 작업의 절차
- 예: &quot;릴리스 절차&quot;, &quot;PDF 생성 규칙&quot;, &quot;보고서 작성법&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;MCP&lt;/b&gt; &amp;mdash; &quot;이 외부 시스템에 접근한다&quot;&lt;/p&gt;
&lt;pre class=&quot;asciidoc&quot;&gt;&lt;code&gt;- 도구/데이터 연결
- 예: GitHub 조회, DB 쿼리, 파일 접근
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Projects&lt;/b&gt; &amp;mdash; &quot;이 작업 공간에서 일한다&quot;&lt;/p&gt;
&lt;pre class=&quot;haml&quot;&gt;&lt;code&gt;- claude.ai의 대화 묶음 + 파일
- 예: &quot;A사 운영 프로젝트&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;결정적 차이: CLAUDE.md vs Skills&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 둘이 가장 헷갈립니다.&lt;/p&gt;
&lt;pre class=&quot;1c&quot;&gt;&lt;code&gt;CLAUDE.md에 이런 게 자라나고 있다면:
&quot;릴리스하려면 테스트 돌리고, 버전 올리고, 
 태그 달고, 이 순서로 푸시하고...&quot;
&amp;rarr; 이건 &quot;사실&quot;이 아니라 &quot;절차&quot;입니다
&amp;rarr; Skill로 빼내야 합니다
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;규칙(fact)은 CLAUDE.md, 절차(procedure)는 Skill.&lt;/b&gt; CLAUDE.md가 절차로 비대해지면 Skill로 분리하세요.&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;★ SKILL.md 구조 완벽 해부&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Skill의 핵심은 SKILL.md 파일 하나입니다. 구조를 뜯어봅니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;최소 구조&lt;/h3&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;---
name: pdf-generator
description: PDF 문서를 생성할 때 사용. 표지, 목차, 
             페이지 번호가 필요한 공식 문서에 적합.
---

# PDF 생성 절차

1. 먼저 문서 구조를 확인합니다
2. 표지를 생성합니다
3. ...
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;필수 항목은 딱 2개&lt;/b&gt;: name과 description. 나머지는 모두 선택입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;frontmatter 해부&lt;/h3&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;---
name: skill-이름              # 필수: 소문자, 하이픈
description: 무엇을, 언제      # 필수: 트리거 조건 명확히
---
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;description이 가장 중요합니다.&lt;/b&gt; Claude는 이 설명을 보고 &quot;이 작업에 이 Skill을 쓸까&quot; 판단합니다.&lt;/p&gt;
&lt;pre class=&quot;1c&quot;&gt;&lt;code&gt;❌ description: &quot;PDF 관련 스킬&quot;  (모호)
✅ description: &quot;PDF 문서를 생성하거나 편집할 때 사용. 
   표지, 목차, 페이지 번호, 워터마크가 필요한 
   공식 문서 작업에 적합.&quot;  (구체적)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3계층 Progressive Disclosure&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Skills의 영리한 설계입니다. 토큰을 아끼기 위해 3단계로 로드됩니다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;1계층: name + description (~100 토큰)
        &amp;rarr; 시작 시 모든 Skill의 이걸 스캔

2계층: SKILL.md 본문 (~5,000 토큰 권장)
        &amp;rarr; 해당 Skill이 선택되면 로드

3계층: 참조 파일 (필요할 때만)
        &amp;rarr; 본문에서 가리키는 추가 파일
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 구조 덕분에 Skill이 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;Skill은 파일 하나가 아니라 &lt;b&gt;폴더&lt;/b&gt;입니다.&lt;/p&gt;
&lt;pre class=&quot;applescript&quot;&gt;&lt;code&gt;my-skill/
├── SKILL.md           # 필수: 메인 지침
├── scripts/           # 선택: 실행 스크립트
│   └── generate.py
├── references/        # 선택: 참조 문서
│   └── template.md
└── assets/            # 선택: 리소스
    └── logo.png
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;간단한 Skill은 SKILL.md 하나로 충분하고, 복잡하면 스크립트&amp;middot;템플릿을 추가합니다.&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;★ 나만의 Skill 만들기 - 3가지 방법&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.ai나 Cowork에서 &lt;b&gt;skill-creator&lt;/b&gt;를 쓰면 대화만으로 Skill을 만들 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;prolog&quot;&gt;&lt;code&gt;&amp;gt; skill-creator를 써서 스킬을 만들어줘.
  
  내가 자주 하는 작업: 주간 업무 보고서 작성
  형식: [설명]
  규칙: [설명]
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude가 몇 가지 질문을 하고 SKILL.md를 작성해서 바로 쓸 수 있는 Skill로 패키징해줍니다. 비개발자에게 가장 좋은 방법입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;방법 2: 직접 작성 (Claude Code)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude Code에서 파일로 직접 만듭니다.&lt;/p&gt;
&lt;pre class=&quot;elm&quot;&gt;&lt;code&gt;# 개인 스킬 위치
mkdir -p ~/.claude/skills/weekly-report
vi ~/.claude/skills/weekly-report/SKILL.md
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;---
name: weekly-report
description: 주간 업무 보고서를 작성할 때 사용. 
             완료/진행중/이슈로 분류하고 상급자가 
             5초 안에 파악 가능한 형식으로 정리.
---

# 주간 업무 보고서 작성

## 형식
1. 이번 주 완료 (불릿, 각 1줄)
2. 진행 중 (진행률 %)
3. 이슈/블로커 (심각도 표시)
4. 다음 주 계획

## 규칙
- 상급자 관점에서 핵심만
- 전문 용어는 괄호로 설명
- 각 항목 2줄 이내
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저장하면 Claude가 자동으로 발견하고, 주간 보고 요청 시 이 Skill을 씁니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;방법 3: 기존 Skill 가져오기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Anthropic 공식 저장소나 커뮤니티 Skill을 활용합니다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;github.com/anthropics/skills
&amp;rarr; 예술, 음악, 디자인, 테스트, MCP 생성 등 다양
&amp;rarr; 대부분 오픈소스 (Apache 2.0)
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존 Skill을 참고해서 본인 것으로 수정하는 게 빠릅니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Skill 위치 (Claude Code)&lt;/h3&gt;
&lt;pre class=&quot;jboss-cli&quot;&gt;&lt;code&gt;개인 스킬: ~/.claude/skills/&amp;lt;name&amp;gt;/SKILL.md
프로젝트 스킬: .claude/skills/&amp;lt;name&amp;gt;/SKILL.md

확인:
ls ~/.claude/skills/*/SKILL.md    # 개인
ls .claude/skills/*/SKILL.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;실전 Skill 예시&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;예시 1: 커밋 메시지 규칙 (개발자)&lt;/h3&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;---
name: commit-message
description: git 커밋 메시지를 작성할 때 사용. 
             conventional commits 형식과 팀 규칙 적용.
---

# 커밋 메시지 작성 규칙

## 형식
&amp;lt;type&amp;gt;(&amp;lt;scope&amp;gt;): &amp;lt;제목&amp;gt;

&amp;lt;본문&amp;gt;

## type
- feat: 새 기능
- fix: 버그 수정
- refactor: 리팩터링
- docs: 문서
- test: 테스트

## 규칙
- 제목은 50자 이내, 명령형
- 본문은 &quot;무엇을, 왜&quot; (어떻게는 코드가 설명)
- 이슈 번호 있으면 하단에 참조
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;예시 2: SQL 리뷰 (DBA)&lt;/h3&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;---
name: sql-review
description: SQL 쿼리를 리뷰할 때 사용. Oracle 환경 기준 
             성능, 보안, 가독성을 점검하고 개선안 제시.
---

# SQL 리뷰 절차

## 점검 항목
1. 성능: 인덱스 활용, 풀스캔 여부, 조인 순서
2. 보안: SQL 인젝션 위험, 권한 과다
3. 가독성: 명명 규칙, 들여쓰기, 주석
4. Oracle 특화: 힌트 적절성, 바인드 변수 사용

## 출력 형식
- 심각도별(높음/중간/낮음) 분류
- 각 지적에 개선 SQL 포함
- 운영 적용 시 주의사항
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;예시 3: 블로그 글 작성 (블로거)&lt;/h3&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;---
name: blog-post
description: 기술 블로그 글을 작성할 때 사용. 
             트러블슈팅 형식과 SEO 규칙 적용.
---

# 블로그 글 작성 절차

## 구조
1. 도입부 (실제 장애 시나리오, 150자)
2. 빠른 진단 체크리스트
3. 원인별 해결 (3~5개)
4. 재발 방지
5. 관련 글 링크

## 규칙
- 존댓말, &quot;여러분&quot; 지양
- 코드 블록 언어 명시
- 상단에 테스트 환경 표기
- SEO: 제목 40~60자, 핵심 키워드 포함
&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;Skill 잘 만드는 팁&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. description에 집중&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude가 Skill을 쓸지 말지는 description으로 결정됩니다. &lt;b&gt;무엇을, 언제&lt;/b&gt; 쓰는지 구체적으로.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. 본문은 5,000 토큰 이내&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. 하나의 Skill = 하나의 목적&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여러 작업을 한 Skill에 담지 마세요. 목적별로 분리해야 정확히 트리거됩니다.&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;Skill은 &quot;절차&quot;를 담는 곳입니다. 단순 사실은 CLAUDE.md로.&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가 제대로 트리거하는지 확인하며 description을 다듬으세요.&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: description이 모호함&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: CLAUDE.md와 혼동&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;환경 규칙을 Skill로, 절차를 CLAUDE.md로 넣는 반대 실수. 절차=Skill, 사실=CLAUDE.md.&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;여러 목적을 한 Skill에. 목적별 분리하세요.&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;본문이 수만 토큰이면 비효율. 5,000 토큰 이내 + 참조 파일 활용.&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;트리거 안 되는 Skill은 무용지물. 실제로 써보고 확인.&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 시리즈 13편] Claude Code로 개인 자산 만들기&lt;/b&gt; 입니다. Phase 3의 마지막 글로, 지금까지 배운 것들(API, MCP, Skills, 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 Skills의 핵심을 다시 정리하면:&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;Skills = 온디맨드 전문성&lt;/b&gt; &amp;mdash; 필요할 때만 로드되는 절차&lt;/li&gt;
&lt;li&gt;&lt;b&gt;절차는 Skill, 사실은 CLAUDE.md&lt;/b&gt; &amp;mdash; 역할 구분&lt;/li&gt;
&lt;li&gt;&lt;b&gt;SKILL.md의 핵심은 description&lt;/b&gt; &amp;mdash; 트리거를 좌우&lt;/li&gt;
&lt;li&gt;&lt;b&gt;3계층 로드로 토큰 절약&lt;/b&gt; &amp;mdash; 많아도 가벼움&lt;/li&gt;
&lt;li&gt;&lt;b&gt;하나의 Skill = 하나의 목적&lt;/b&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;매번 같은 설명을 반복하고 있다면, 그게 바로 Skill로 만들 신호입니다. 대화로 만드는 skill-creator부터 시작해서, 점점 본인만의 Skill 라이브러리를 쌓아가시길 권합니다. 한 번 가르치면 계속 재사용하는 것 &amp;mdash; 이게 Skills의 본질입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;본인이 만든 유용한 Skill이나 활용 사례가 있다면 댓글로 공유해주세요.&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>AI (Claude 활용)/Claude 심화(전문)</category>
      <category>Claude Skills</category>
      <category>Claude 스킬 만들기</category>
      <category>Claude 스킬 예시</category>
      <category>Claude 스킬 작성법</category>
      <category>Claude.md vs Skills</category>
      <category>MCP vs Skills</category>
      <category>skill-creator</category>
      <category>SKILL.md 작성법</category>
      <category>Skills 차이</category>
      <category>소니스토리</category>
      <author>isony</author>
      <guid isPermaLink="true">https://isony.tistory.com/365</guid>
      <comments>https://isony.tistory.com/entry/Claude-%EC%8B%9C%EB%A6%AC%EC%A6%88-12%ED%8E%B8-Claude-Skills-%EB%A7%8C%EB%93%A4%EA%B8%B0-%EB%B0%98%EB%B3%B5-%EC%9E%91%EC%97%85%EC%9D%84-Claude%EC%97%90%EA%B2%8C-%EA%B0%80%EB%A5%B4%EC%B9%98%EA%B8%B0-SKILLmd-%EC%99%84%EB%B2%BD-%EA%B0%80%EC%9D%B4%EB%93%9C#entry365comment</comments>
      <pubDate>Wed, 5 Aug 2026 07:36:00 +0900</pubDate>
    </item>
    <item>
      <title>[Claude 시리즈 11편] Claude MCP 완벽 정리 - AI를 외부 도구와 연결하는 표준 (2026 최신)</title>
      <link>https://isony.tistory.com/entry/Claude-%EC%8B%9C%EB%A6%AC%EC%A6%88-11%ED%8E%B8-Claude-MCP-%EC%99%84%EB%B2%BD-%EC%A0%95%EB%A6%AC-AI%EB%A5%BC-%EC%99%B8%EB%B6%80-%EB%8F%84%EA%B5%AC%EC%99%80-%EC%97%B0%EA%B2%B0%ED%95%98%EB%8A%94-%ED%91%9C%EC%A4%80-2026-%EC%B5%9C%EC%8B%A0</link>
      <description>&lt;h1&gt;[Claude 시리즈 11편] Claude MCP 완벽 정리 - AI를 외부 도구와 연결하는 표준 (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;: Claude Desktop, Claude Code, MCP 2.x (2026년 7월 기준)&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;내 GitHub 이슈 확인해서 우선순위 정리해줘.&quot;&lt;/b&gt; &lt;b&gt;&quot;우리 데이터베이스에서 지난달 매출 뽑아줘.&quot;&lt;/b&gt; &lt;b&gt;&quot;이 문서를 내 드라이브에 저장해줘.&quot;&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;MCP(Model Context Protocol)&lt;/b&gt; 입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MCP는 2024년 11월 Anthropic이 발표한 오픈 표준으로, 2026년 현재 &lt;b&gt;AI 업계 전체의 표준&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;MCP가 정확히 무엇인가 (비유로 이해)&lt;/li&gt;
&lt;li&gt;핵심 구조 (Client, Server, Transport)&lt;/li&gt;
&lt;li&gt;기본 MCP 서버 연결하기 (실전)&lt;/li&gt;
&lt;li&gt;어떤 서버를 먼저 써야 하나&lt;/li&gt;
&lt;li&gt;커스텀 MCP 서버 개념&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://isony.tistory.com/category/AI%20%28Claude%20%ED%99%9C%EC%9A%A9%29/Claude%20%EC%8B%AC%ED%99%94%28%EC%A0%84%EB%AC%B8%29&quot;&gt;Phase 3&lt;/a&gt;의 두 번째 글입니다. &lt;a href=&quot;https://isony.tistory.com/entry/Claude-%EC%8B%9C%EB%A6%AC%EC%A6%88-10%ED%8E%B8-Claude-API-%EC%82%AC%EC%9A%A9%EB%B2%95-%EA%B0%9C%EB%B0%9C%EC%9E%90%EB%A5%BC-%EC%9C%84%ED%95%9C-%EC%8B%A4%EC%A0%84-%EC%9E%85%EB%AC%B8-2026%EB%85%84-%EC%B5%9C%EC%8B%A0&quot;&gt;API 편&lt;/a&gt;에 이어 개발자&amp;middot;파워유저를 위한 심화 내용입니다.&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;MCP란 무엇인가 - &quot;AI를 위한 USB&quot;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 좋은 비유는 &lt;b&gt;USB&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;USB가 나오기 전에는 프린터, 마우스, 키보드마다 다른 포트와 케이블이 필요했습니다. USB는 &lt;b&gt;하나의 표준 규격&lt;/b&gt;으로 이 모든 것을 연결했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MCP도 마찬가지입니다.&lt;/p&gt;
&lt;pre class=&quot;properties&quot;&gt;&lt;code&gt;MCP 이전:
Claude ─(각각 다른 방식)&amp;rarr; GitHub
Claude ─(각각 다른 방식)&amp;rarr; 데이터베이스
Claude ─(각각 다른 방식)&amp;rarr; Slack
&amp;rarr; 도구마다 별도 통합 개발 필요

MCP 이후:
Claude ─(MCP 표준)&amp;rarr; [GitHub / DB / Slack / ...]
&amp;rarr; 하나의 프로토콜로 모든 도구 연결
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;한 줄 정의&lt;/b&gt;: MCP는 &lt;b&gt;AI가 외부 도구&amp;middot;데이터에 접근하는 표준 방식&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;2023~2024년에는 Claude에 정보를 주려면 &lt;b&gt;복사-붙여넣기&lt;/b&gt;를 해야 했습니다. CSV를 내보내고, 문서를 열어서 긁어오고. MCP는 이 마찰을 없앱니다. Claude가 &lt;b&gt;직접&lt;/b&gt; 파일을 읽고, DB를 조회하고, API를 호출합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2026년 현재 위상&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;9,400개 이상&lt;/b&gt;의 MCP 서버가 공식 레지스트리에 등록&lt;/li&gt;
&lt;li&gt;&lt;b&gt;2025년 12월 Linux Foundation&lt;/b&gt;으로 이관 &amp;rarr; Anthropic만의 것이 아닌 진정한 오픈 표준&lt;/li&gt;
&lt;li&gt;&lt;b&gt;model-agnostic&lt;/b&gt;: Claude뿐 아니라 GPT, Gemini도 MCP 지원&lt;/li&gt;
&lt;li&gt;월 &lt;b&gt;9,700만 다운로드&lt;/b&gt; (16개월 만에 4,750% 성장)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, MCP를 배우는 것은 특정 회사 기술이 아니라 &lt;b&gt;AI 시대의 범용 인프라&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;★ MCP 핵심 구조 3가지&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MCP를 이해하려면 세 가지 구성 요소를 알면 됩니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. MCP Client (클라이언트)&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;예시:
- Claude Desktop (데스크톱 앱)
- Claude Code (터미널)
- Claude.ai (웹, Pro 이상)
- Cursor, 기타 AI 에디터
&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. MCP Server (서버)&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;haml&quot;&gt;&lt;code&gt;예시:
- GitHub 서버: &quot;이슈 생성&quot;, &quot;PR 검토&quot;, &quot;코드 검색&quot;
- PostgreSQL 서버: &quot;쿼리 실행&quot;, &quot;테이블 조회&quot;
- Filesystem 서버: &quot;파일 읽기&quot;, &quot;파일 쓰기&quot;
- Slack 서버: &quot;메시지 전송&quot;, &quot;채널 조회&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서버는 &lt;b&gt;model-agnostic&lt;/b&gt;입니다. GitHub 서버 하나를 만들면 Claude, GPT, Gemini 어디서든 쓸 수 있습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. Transport (전송 방식)&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;stdio&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;로컬 프로세스로 실행&lt;/td&gt;
&lt;td&gt;개인 PC (가장 흔함)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;HTTP/SSE&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;WebSocket&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;stdio&lt;/b&gt;입니다. 본인 컴퓨터에서 서버가 프로세스로 실행됩니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;전체 흐름&lt;/h3&gt;
&lt;pre class=&quot;less&quot;&gt;&lt;code&gt;[나] &amp;rarr; [Claude Desktop = Client]
              &amp;darr; (stdio/HTTP)
       [GitHub MCP Server]
              &amp;darr;
       [실제 GitHub API]
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude가 GitHub 서버에게 &quot;이슈 목록 줘&quot;라고 요청하면, 서버가 실제 GitHub에서 데이터를 가져와 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;MCP의 세 가지 제공물&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MCP 서버는 세 종류를 제공합니다. 구분하면 이해가 쉽습니다.&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;Tools (도구)&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;Claude가 호출하는 함수 (행동)&lt;/td&gt;
&lt;td&gt;&quot;쿼리 실행&quot;, &quot;파일 쓰기&quot;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;Resources (리소스)&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;미리 붙는 컨텍스트 (읽기)&lt;/td&gt;
&lt;td&gt;파일 내용, DB 행&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;Prompts (프롬프트)&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;재사용 프롬프트 템플릿&lt;/td&gt;
&lt;td&gt;&quot;코드 리뷰 표준 절차&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;Tool과 Resource의 차이&lt;/b&gt;: Tool은 &quot;요청해서 실행&quot;(마우스 클릭 같은), Resource는 &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;★ 기본 MCP 서버 연결하기 (실전)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이론은 충분합니다. 실제로 연결해봅시다. Claude Desktop 기준입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Anthropic 공식 레퍼런스 서버 6개&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Anthropic이 직접 제공하는 검증된 서버입니다. 여기서 시작하세요.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;1. filesystem   - 로컬 파일 읽기/쓰기
2. PostgreSQL   - DB 조회
3. Brave Search - 웹 검색
4. GitHub       - 저장소 관리
5. Puppeteer    - 브라우저 제어
6. Google Maps  - 지도/위치
&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 Desktop은 설정 파일을 읽어서 MCP 서버를 로드합니다.&lt;/p&gt;
&lt;pre class=&quot;groovy&quot;&gt;&lt;code&gt;macOS:
~/Library/Application Support/Claude/claude_desktop_config.json

Windows:
%APPDATA%\Claude\claude_desktop_config.json
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Filesystem 서버 연결 예시&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 기본이 되는 파일시스템 서버를 연결해봅시다.&lt;/p&gt;
&lt;pre class=&quot;json&quot;&gt;&lt;code&gt;{
  &quot;mcpServers&quot;: {
    &quot;filesystem&quot;: {
      &quot;command&quot;: &quot;npx&quot;,
      &quot;args&quot;: [
        &quot;-y&quot;,
        &quot;@modelcontextprotocol/server-filesystem&quot;,
        &quot;/Users/사용자명/Documents&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;GitHub 서버 연결 예시&lt;/h3&gt;
&lt;pre class=&quot;json&quot;&gt;&lt;code&gt;{
  &quot;mcpServers&quot;: {
    &quot;github&quot;: {
      &quot;command&quot;: &quot;npx&quot;,
      &quot;args&quot;: [&quot;-y&quot;, &quot;@modelcontextprotocol/server-github&quot;],
      &quot;env&quot;: {
        &quot;GITHUB_TOKEN&quot;: &quot;your-github-token&quot;
      }
    }
  }
}
&lt;/code&gt;&lt;/pre&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. Claude Desktop 완전 종료 후 재시작
3. 대화창에서 도구 아이콘 확인
4. &quot;내 Documents 폴더의 파일 목록 보여줘&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;Claude Code에서 연결&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude Code는 CLI로 더 간단합니다.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;# 서버 추가
claude mcp add github npx @modelcontextprotocol/server-github

# 목록 확인
claude mcp list

# 특정 서버 정보
claude mcp get github
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설정은 ~/.claude/settings.json(사용자) 또는 프로젝트의 .claude/settings.json에 저장됩니다.&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;필수 5개&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;filesystem&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;GitHub&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;이슈/PR/코드&lt;/td&gt;
&lt;td&gt;개발자&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;PostgreSQL/Supabase&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;DB 조회&lt;/td&gt;
&lt;td&gt;개발자/DBA&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;Playwright/Puppeteer&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;Brave Search&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;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;1c&quot;&gt;&lt;code&gt;한 개발자의 측정:
&quot;컨텍스트 윈도우의 30~40%가 한 번도 안 쓴 
도구 스키마로 채워지고 있었다.&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;서버 하나하나가 도구 정의로 컨텍스트를 차지&lt;/b&gt;합니다. 3~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;주 1회만 쓰는 서버 &amp;rarr; 설치하지 말고 CLI 도구로 대체
매일 쓰는 서버 &amp;rarr; MCP로 상시 연결
&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;커스텀 MCP 서버 만들기 (개념)&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;사내 전용 시스템 연결 (자체 API, 내부 DB)&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;기본 구조 (Python 예시)&lt;/h3&gt;
&lt;pre class=&quot;python&quot;&gt;&lt;code&gt;from mcp.server.fastmcp import FastMCP

mcp = FastMCP(&quot;my-server&quot;)

@mcp.tool()
def get_ticket(ticket_id: str) -&amp;gt; str:
    &quot;&quot;&quot;티켓 정보를 조회합니다.&quot;&quot;&quot;
    # 실제 로직 (DB 조회 등)
    return f&quot;티켓 {ticket_id}의 정보...&quot;

@mcp.tool()
def search_notes(keyword: str) -&amp;gt; str:
    &quot;&quot;&quot;프로젝트 노트를 검색합니다.&quot;&quot;&quot;
    # 실제 로직
    return f&quot;'{keyword}' 검색 결과...&quot;

if __name__ == &quot;__main__&quot;:
    mcp.run()
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 만든 서버를 설정 파일에 등록하면 Claude가 get_ticket, search_notes 도구를 쓸 수 있습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;FastMCP 프레임워크&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;FastMCP는 MCP 서버를 쉽게 만드는 프레임워크입니다. 함수에 @mcp.tool() 데코레이터만 붙이면 도구가 됩니다. Docker로 배포하면 팀 전체가 공유할 수도 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;DBA&amp;middot;운영자 활용 아이디어&lt;/b&gt;: 사내 모니터링 시스템, 운영 DB 조회, 로그 검색을 MCP 서버로 만들면 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;MCP는 강력한 만큼 위험도 있습니다. 반드시 이해하세요.&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;stdio 서버는 본인 권한으로 실행됩니다.
&amp;rarr; 그 프로세스가 읽을 수 있는 모든 것을 Claude가 읽을 수 있습니다.
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;filesystem 서버에 홈 디렉토리 전체를 열어주면, Claude가 그 안의 모든 파일에 접근 가능합니다. &lt;b&gt;필요한 폴더만&lt;/b&gt; 열어주세요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. 신뢰할 수 있는 서버만&lt;/h3&gt;
&lt;pre class=&quot;&quot;&gt;&lt;code&gt;❌ 출처 불명의 MCP 서버 설치 금지
✅ 공식 레지스트리, 검증된 커뮤니티 서버만
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MCP 서버는 코드를 실행합니다. 악의적 서버는 위험합니다. 공식 또는 널리 검증된 것만 쓰세요.&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;GitHub 토큰, DB 비밀번호 등을 설정 파일에 넣을 때:
- 최소 권한 토큰 사용
- 설정 파일을 git에 올리지 않기
- 정기적으로 토큰 교체
&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가 MCP 도구로 데이터를 받으면(예: 파일 내용), 그 데이터는 Claude의 컨텍스트로 들어갑니다. 즉 Anthropic 서버로 전송됩니다. &lt;b&gt;민감 데이터&lt;/b&gt;를 다루는 MCP는 신중하게.&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 Code 등에서 팀의 .mcp.json을 가져오면 승인 프롬프트가 뜹니다. &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;개발자&lt;/h3&gt;
&lt;pre class=&quot;1c&quot;&gt;&lt;code&gt;&quot;GitHub에서 이번 스프린트 이슈 가져와서 
우선순위별로 정리하고, 각 이슈에 예상 공수 추정해줘&quot;
&amp;rarr; GitHub MCP로 실제 이슈 조회 + 분석
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;DBA&amp;middot;운영자&lt;/h3&gt;
&lt;pre class=&quot;1c&quot;&gt;&lt;code&gt;&quot;운영 DB에서 최근 24시간 느린 쿼리 TOP 10 뽑아서 
원인 분석해줘&quot;
&amp;rarr; PostgreSQL MCP로 실제 조회 + 진단
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;일반 실무자&lt;/h3&gt;
&lt;pre class=&quot;1c&quot;&gt;&lt;code&gt;&quot;내 Documents 폴더에서 지난달 보고서들 찾아서 
공통 이슈를 요약해줘&quot;
&amp;rarr; filesystem MCP로 파일 접근 + 요약
&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 시리즈 12편] Claude Skills 만들기&lt;/b&gt; 입니다. MCP가 &quot;외부 도구 연결&quot;이라면, Skills는 &quot;반복 작업을 Claude에게 가르치는&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;MCP의 핵심을 다시 정리하면:&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;MCP는 AI를 위한 USB&lt;/b&gt; &amp;mdash; 하나의 표준으로 모든 도구 연결&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Client(Claude) + Server(도구) + Transport(통신)&lt;/b&gt; 3요소&lt;/li&gt;
&lt;li&gt;&lt;b&gt;공식 레퍼런스 6개&lt;/b&gt;부터 시작 (filesystem, GitHub 등)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;3~5개만 설치&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;MCP는 2026년 AI 활용의 핵심 인프라입니다. 복사-붙여넣기 시대를 끝내고 Claude가 본인의 실제 도구와 직접 일하게 만듭니다. 다만 강력한 만큼 보안에 신중해야 합니다. filesystem 서버 하나부터 연결해보며 감을 잡으시길 권합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MCP를 활용한 사례나 유용한 서버 추천이 있다면 댓글로 공유해주세요. 한국어 MCP 정보가 부족한 만큼, 함께 노하우를 모으면 좋겠습니다.&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 mcp</category>
      <category>Claude MCP 서버</category>
      <category>fastmcp</category>
      <category>MCP transport</category>
      <category>MCP 뜻</category>
      <category>MCP 란</category>
      <category>mcp 사용법</category>
      <category>MCP 서버만들기</category>
      <category>MCP 설정</category>
      <category>소니스토리</category>
      <author>isony</author>
      <guid isPermaLink="true">https://isony.tistory.com/364</guid>
      <comments>https://isony.tistory.com/entry/Claude-%EC%8B%9C%EB%A6%AC%EC%A6%88-11%ED%8E%B8-Claude-MCP-%EC%99%84%EB%B2%BD-%EC%A0%95%EB%A6%AC-AI%EB%A5%BC-%EC%99%B8%EB%B6%80-%EB%8F%84%EA%B5%AC%EC%99%80-%EC%97%B0%EA%B2%B0%ED%95%98%EB%8A%94-%ED%91%9C%EC%A4%80-2026-%EC%B5%9C%EC%8B%A0#entry364comment</comments>
      <pubDate>Mon, 3 Aug 2026 07:35:16 +0900</pubDate>
    </item>
    <item>
      <title>2026년08월02일 주일예배 (이재훈목사님) - 1부</title>
      <link>https://isony.tistory.com/entry/2026%EB%85%8408%EC%9B%9402%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년08월02일 주일예배 (이재훈목사님) - 1부&lt;/h2&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;주의 말씀 : 나를 따르라&amp;nbsp; (12)&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; 로마서 12:1 ~ 2 말씀 (출처:우리말성경)&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;12:1 그러므로 형제들이여, 내가 하나님의 자비하심으로 여러분에게 권합니다. 여러분의 몸을 하나님께서 기뻐하시는 거룩한 산 제물로 드리십시오. 이것이 여러분이 드릴 영적 예배입니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #444444; text-align: start;&quot;&gt;12:2 여러분은 이 세대를 본받지 말고 오직 마음을 새롭게 함으로 변화를 받아 하나님의 선하시고 기뻐하시고 온전하신 뜻이 무엇인지 분별하도록 하십시오.&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/eAYiRMmlPnE&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://youtu.be/eAYiRMmlPnE&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=eAYiRMmlPnE&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/bdvaAN/dJMb8QeAQx4/ko0LasC910PckpWOzMGUR0/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=554_152_694_304,https://scrap.kakaocdn.net/dn/eBOPc/dJMb8SpWJce/sTrFTnuysP1PI9AUxK3Jrk/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=554_152_694_304,https://scrap.kakaocdn.net/dn/tscx8/dJMb8VNKuhB/gNT00hkhkEPoPKBqQJ86aK/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 08 02&quot; data-original-url=&quot;&quot;&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/eAYiRMmlPnE&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-08-02 07-49-45-965.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/cabXoK/dJMcagsToow/iuH7OxN6cvMPuEXyyoP91K/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cabXoK/dJMcagsToow/iuH7OxN6cvMPuEXyyoP91K/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cabXoK/dJMcagsToow/iuH7OxN6cvMPuEXyyoP91K/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcabXoK%2FdJMcagsToow%2FiuH7OxN6cvMPuEXyyoP91K%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-08-02 07-49-45-965.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/lNryk/dJMcaafbQdu/bPmC5Vklj6cRhLwKLoKNWK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lNryk/dJMcaafbQdu/bPmC5Vklj6cRhLwKLoKNWK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lNryk/dJMcaafbQdu/bPmC5Vklj6cRhLwKLoKNWK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlNryk%2FdJMcaafbQdu%2FbPmC5Vklj6cRhLwKLoKNWK%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>로마서 12장</category>
      <category>살아 있는 제물</category>
      <category>소니스토리</category>
      <category>우리말성경</category>
      <category>이재훈목사</category>
      <category>주일예배</category>
      <author>isony</author>
      <guid isPermaLink="true">https://isony.tistory.com/363</guid>
      <comments>https://isony.tistory.com/entry/2026%EB%85%8408%EC%9B%9402%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#entry363comment</comments>
      <pubDate>Sun, 2 Aug 2026 08:02:30 +0900</pubDate>
    </item>
    <item>
      <title>[Claude 시리즈 10편] Claude API 사용법 - 개발자를 위한 실전 입문 (2026년 최신)</title>
      <link>https://isony.tistory.com/entry/Claude-%EC%8B%9C%EB%A6%AC%EC%A6%88-10%ED%8E%B8-Claude-API-%EC%82%AC%EC%9A%A9%EB%B2%95-%EA%B0%9C%EB%B0%9C%EC%9E%90%EB%A5%BC-%EC%9C%84%ED%95%9C-%EC%8B%A4%EC%A0%84-%EC%9E%85%EB%AC%B8-2026%EB%85%84-%EC%B5%9C%EC%8B%A0</link>
      <description>&lt;h1&gt;[Claude 시리즈 10편] Claude API 사용법 - 개발자를 위한 실전 입문 (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;: Claude API, Python/Node.js SDK (2026년 7월 기준)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금까지의 시리즈가 &lt;b&gt;Claude.ai 웹/앱&lt;/b&gt;을 다뤘다면, 이번 편부터 시작되는 Phase 3는 &lt;b&gt;개발자를 위한 심화 영역&lt;/b&gt;입니다. 그 첫 번째가 &lt;b&gt;Claude API&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;API를 쓰면 Claude를 본인의 애플리케이션&amp;middot;서비스&amp;middot;자동화에 직접 통합할 수 있습니다. 챗봇, 문서 처리 파이프라인, 데이터 분석 도구 등 무엇이든 Claude의 지능을 넣을 수 있습니다.&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 API vs 구독(Pro/Max)의 차이&lt;/li&gt;
&lt;li&gt;API 키 발급과 첫 요청 (5분)&lt;/li&gt;
&lt;li&gt;2026년 최신 모델과 가격&lt;/li&gt;
&lt;li&gt;핵심 개념 (Messages, 토큰, 컨텍스트)&lt;/li&gt;
&lt;li&gt;비용 절감 3가지 방법 (캐싱, 배치, 모델 선택)&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; 대상입니다. 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;API vs 구독 - 무엇이 다른가&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 먼저 헷갈리는 부분입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;항목 구독 (Pro/Max) API&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;claude.ai 웹/앱&lt;/td&gt;
&lt;td&gt;본인 코드/서비스&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;과금&lt;/td&gt;
&lt;td&gt;월 정액 ($20~200)&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;: 구독은 &quot;내가 직접 쓰는 것&quot;, API는 &quot;내 프로그램이 쓰는 것&quot;입니다. 둘은 &lt;b&gt;별도 결제&lt;/b&gt;입니다. Pro 구독이 있어도 API는 따로 크레딧을 충전해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;언제 API가 필요한가:&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;대량 문서 자동 처리&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;API 키 발급과 첫 요청 (5분)&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://console.anthropic.com 접속
2. 계정 생성 (claude.ai 계정과 별개일 수 있음)
3. 결제 정보 등록 + 크레딧 충전 (최소 $5)
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;참고&lt;/b&gt;: 프로덕션용 영구 무료 tier는 없습니다. 소액 충전 후 시작합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Step 2: API 키 생성&lt;/h3&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;1. Console &amp;rarr; API Keys
2. Create Key
3. 키 이름 입력, 생성
4. 키 복사 (다시 볼 수 없으니 안전하게 보관)
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;보안 경고&lt;/b&gt;: API 키는 비밀번호입니다. 코드에 하드코딩하거나 GitHub에 올리지 마세요. 환경 변수로 관리하세요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Step 3: SDK 설치&lt;/h3&gt;
&lt;pre class=&quot;cmake&quot;&gt;&lt;code&gt;# Python
pip install anthropic

# Node.js
npm install @anthropic-ai/sdk
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Step 4: 첫 요청 (Python)&lt;/h3&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;import anthropic

client = anthropic.Anthropic(
    api_key=&quot;your-api-key&quot;  # 환경 변수 권장
)

message = client.messages.create(
    model=&quot;claude-sonnet-5&quot;,
    max_tokens=1024,
    messages=[
        {&quot;role&quot;: &quot;user&quot;, &quot;content&quot;: &quot;안녕하세요, 자기소개 해주세요.&quot;}
    ]
)

print(message.content[0].text)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;첫 요청 (Node.js)&lt;/h3&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;import Anthropic from '@anthropic-ai/sdk';

const client = new Anthropic({
    apiKey: process.env.ANTHROPIC_API_KEY,
});

const message = await client.messages.create({
    model: 'claude-sonnet-5',
    max_tokens: 1024,
    messages: [
        { role: 'user', content: '안녕하세요, 자기소개 해주세요.' }
    ],
});

console.log(message.content[0].text);
&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;★ 2026년 최신 모델과 가격&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정확한 모델 선택이 비용과 성능을 좌우합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;현재 사용 가능한 모델 (2026년 7월)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모델 ID 특징 입력/출력 (per MTok)&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-haiku-4-5-20251001&lt;/td&gt;
&lt;td&gt;가장 빠르고 저렴&lt;/td&gt;
&lt;td&gt;$1 / $5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;claude-sonnet-5&lt;/td&gt;
&lt;td&gt;가성비 최적 (기본 추천)&lt;/td&gt;
&lt;td&gt;$2 / $10*&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;claude-opus-5&lt;/td&gt;
&lt;td&gt;최고 성능&lt;/td&gt;
&lt;td&gt;$5 / $25&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;claude-fable-5&lt;/td&gt;
&lt;td&gt;프론티어 (최고 난이도)&lt;/td&gt;
&lt;td&gt;$10 / $50&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;*Sonnet 5는 2026년 8월 31일까지 도입가 $2/$10, 이후 $3/$15로 조정 예정.&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;middot;단순 작업 (분류, 추출)  &amp;rarr; Haiku 4.5
일반 작업 (챗봇, RAG, 요약)   &amp;rarr; Sonnet 5 (기본 추천)
복잡한 추론&amp;middot;코딩             &amp;rarr; Opus 5
최고 난이도                  &amp;rarr; Fable 5
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;중요&lt;/b&gt;: 모델 ID는 정확히 입력해야 합니다. 특히 Haiku는 날짜 접미사까지 필요합니다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;✅ claude-haiku-4-5-20251001
❌ claude-haiku-4-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;가격은 &lt;b&gt;토큰&lt;/b&gt; 단위입니다. 대략 &lt;b&gt;한글 1자 &amp;asymp; 1.5~2 토큰, 영어 1단어 &amp;asymp; 1.3 토큰&lt;/b&gt; 수준입니다.&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;예: Sonnet 5로 챗봇 응답 1건
- 입력 1,200 토큰 (시스템 + 대화) &amp;times; $2/MTok = $0.0024
- 출력 250 토큰 &amp;times; $10/MTok = $0.0025
- 합계 약 $0.005 (약 7원)
&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;Messages API 구조&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude API의 핵심은 &lt;b&gt;Messages&lt;/b&gt; 엔드포인트입니다.&lt;/p&gt;
&lt;pre class=&quot;makefile&quot;&gt;&lt;code&gt;message = client.messages.create(
    model=&quot;claude-sonnet-5&quot;,     # 모델 선택
    max_tokens=1024,             # 최대 출력 길이
    system=&quot;당신은 친절한 도우미입니다.&quot;,  # 시스템 프롬프트 (선택)
    messages=[                   # 대화 내역
        {&quot;role&quot;: &quot;user&quot;, &quot;content&quot;: &quot;질문 1&quot;},
        {&quot;role&quot;: &quot;assistant&quot;, &quot;content&quot;: &quot;답변 1&quot;},
        {&quot;role&quot;: &quot;user&quot;, &quot;content&quot;: &quot;질문 2&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;API는 &lt;b&gt;상태를 저장하지 않습니다&lt;/b&gt;. 대화를 이어가려면 &lt;b&gt;전체 히스토리를 매번 보내야&lt;/b&gt; 합니다.&lt;/p&gt;
&lt;pre class=&quot;makefile&quot;&gt;&lt;code&gt;conversation = [
    {&quot;role&quot;: &quot;user&quot;, &quot;content&quot;: &quot;내 이름은 홍길동이야&quot;},
    {&quot;role&quot;: &quot;assistant&quot;, &quot;content&quot;: &quot;안녕하세요 홍길동님!&quot;},
    {&quot;role&quot;: &quot;user&quot;, &quot;content&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;긴 응답을 실시간으로 받으려면 스트리밍을 씁니다.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;with client.messages.stream(
    model=&quot;claude-sonnet-5&quot;,
    max_tokens=1024,
    messages=[{&quot;role&quot;: &quot;user&quot;, &quot;content&quot;: &quot;긴 글 써줘&quot;}]
) as stream:
    for text in stream.text_stream:
        print(text, end=&quot;&quot;, flush=True)
&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;pre class=&quot;ini&quot;&gt;&lt;code&gt;system=&quot;&quot;&quot;당신은 Oracle DBA 전문가입니다.
- SQL은 대문자 키워드로 작성
- 위험한 명령은 경고와 함께 제시
- 한국어로 답변&quot;&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;★ 비용 절감 3가지 방법&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;API 비용을 크게 줄이는 실전 기법입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 프롬프트 캐싱 (최대 90% 절감)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;같은 내용(시스템 프롬프트, 문서)을 반복해서 보낼 때, 캐싱하면 &lt;b&gt;캐시 히트는 입력 가격의 10%&lt;/b&gt; 만 냅니다.&lt;/p&gt;
&lt;pre class=&quot;nix&quot;&gt;&lt;code&gt;message = client.messages.create(
    model=&quot;claude-sonnet-5&quot;,
    max_tokens=1024,
    system=[
        {
            &quot;type&quot;: &quot;text&quot;,
            &quot;text&quot;: &quot;긴 시스템 프롬프트 또는 문서...&quot;,
            &quot;cache_control&quot;: {&quot;type&quot;: &quot;ephemeral&quot;}  # 캐싱
        }
    ],
    messages=[{&quot;role&quot;: &quot;user&quot;, &quot;content&quot;: &quot;질문&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;2. 배치 처리 (50% 할인)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;급하지 않은 대량 작업은 &lt;b&gt;Message Batches API&lt;/b&gt;로 처리하면 50% 저렴합니다.&lt;/p&gt;
&lt;pre class=&quot;nimrod&quot;&gt;&lt;code&gt;# 배치는 최대 24시간 내 처리, 대신 반값
batch = client.messages.batches.create(
    requests=[
        {&quot;custom_id&quot;: &quot;req-1&quot;, &quot;params&quot;: {...}},
        {&quot;custom_id&quot;: &quot;req-2&quot;, &quot;params&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;3. 모델 라우팅&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;작업 난이도에 맞는 모델을 쓰세요.&lt;/p&gt;
&lt;pre class=&quot;python&quot;&gt;&lt;code&gt;def choose_model(task_complexity):
    if task_complexity == &quot;simple&quot;:    # 분류, 추출
        return &quot;claude-haiku-4-5-20251001&quot;  # $1/$5
    elif task_complexity == &quot;medium&quot;:  # 일반
        return &quot;claude-sonnet-5&quot;            # $2/$10
    else:                              # 복잡한 추론
        return &quot;claude-opus-5&quot;             # $5/$25
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단순 작업에 Opus를 쓰는 건 낭비입니다. 대부분은 Sonnet 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;실전 예제&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;예제 1: 문서 요약 함수&lt;/h3&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;import anthropic

client = anthropic.Anthropic()

def summarize(text):
    message = client.messages.create(
        model=&quot;claude-sonnet-5&quot;,
        max_tokens=500,
        messages=[{
            &quot;role&quot;: &quot;user&quot;,
            &quot;content&quot;: f&quot;다음을 3줄로 요약해줘:\n\n{text}&quot;
        }]
    )
    return message.content[0].text

# 사용
summary = summarize(&quot;긴 문서 내용...&quot;)
print(summary)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;예제 2: 구조화된 출력 (JSON)&lt;/h3&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;def extract_info(text):
    message = client.messages.create(
        model=&quot;claude-sonnet-5&quot;,
        max_tokens=500,
        messages=[{
            &quot;role&quot;: &quot;user&quot;,
            &quot;content&quot;: f&quot;&quot;&quot;다음에서 정보를 추출해 JSON으로만 답해줘.
형식: {{&quot;name&quot;: &quot;&quot;, &quot;email&quot;: &quot;&quot;, &quot;phone&quot;: &quot;&quot;}}

텍스트: {text}&quot;&quot;&quot;
        }]
    )
    import json
    return json.loads(message.content[0].text)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;예제 3: 이미지 분석&lt;/h3&gt;
&lt;pre class=&quot;python&quot;&gt;&lt;code&gt;import base64

def analyze_image(image_path):
    with open(image_path, &quot;rb&quot;) as f:
        image_data = base64.b64encode(f.read()).decode()
    
    message = client.messages.create(
        model=&quot;claude-sonnet-5&quot;,
        max_tokens=1024,
        messages=[{
            &quot;role&quot;: &quot;user&quot;,
            &quot;content&quot;: [
                {
                    &quot;type&quot;: &quot;image&quot;,
                    &quot;source&quot;: {
                        &quot;type&quot;: &quot;base64&quot;,
                        &quot;media_type&quot;: &quot;image/jpeg&quot;,
                        &quot;data&quot;: image_data
                    }
                },
                {&quot;type&quot;: &quot;text&quot;, &quot;text&quot;: &quot;이 이미지를 설명해줘&quot;}
            ]
        }]
    )
    return message.content[0].text
&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. API 키 보안&lt;/h3&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;# ❌ 절대 금지
client = anthropic.Anthropic(api_key=&quot;sk-ant-xxxxx&quot;)

# ✅ 환경 변수 사용
import os
client = anthropic.Anthropic(api_key=os.environ[&quot;ANTHROPIC_API_KEY&quot;])
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;.env 파일을 쓰고 .gitignore에 추가하세요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. 에러 처리&lt;/h3&gt;
&lt;pre class=&quot;python&quot;&gt;&lt;code&gt;import anthropic

try:
    message = client.messages.create(...)
except anthropic.RateLimitError:
    # 요청 한도 초과 &amp;rarr; 재시도
    pass
except anthropic.APIError as e:
    # 기타 API 오류
    print(f&quot;API 오류: {e}&quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. 비용 모니터링&lt;/h3&gt;
&lt;pre class=&quot;arcade&quot;&gt;&lt;code&gt;Console &amp;rarr; Usage에서 실시간 사용량 확인
알림(Alert) 설정으로 예산 초과 방지
&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. max_tokens 관리&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;max_tokens는 출력 상한입니다. 너무 크게 잡으면 비용이 늘 수 있으니 필요한 만큼만.&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;네트워크 오류나 일시적 한도 초과에 대비해 지수 백오프 재시도를 구현하세요. SDK가 기본 재시도를 제공하지만, 프로덕션에서는 추가 처리가 필요합니다.&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 시리즈 11편] Claude MCP 완벽 정리&lt;/b&gt; 입니다. Claude를 외부 도구&amp;middot;데이터와 연결하는 MCP(Model Context Protocol)를 다룹니다. 한국어 자료가 거의 없는 영역이라 특히 유용할 것입니다.&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 API 활용의 핵심은:&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;API는 구독과 별개&lt;/b&gt; &amp;mdash; 코드에서 쓰는 용도, 토큰당 과금&lt;/li&gt;
&lt;li&gt;&lt;b&gt;모델 선택이 비용을 좌우&lt;/b&gt; &amp;mdash; 대부분 Sonnet 5로 충분&lt;/li&gt;
&lt;li&gt;&lt;b&gt;캐싱&amp;middot;배치로 최대 90%&amp;middot;50% 절감&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;API 키 보안 필수&lt;/b&gt; &amp;mdash; 환경 변수, .gitignore&lt;/li&gt;
&lt;li&gt;&lt;b&gt;비용 모니터링&amp;middot;한도 설정&lt;/b&gt; &amp;mdash; 프로덕션 전 필수&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;API를 쓰면 Claude의 지능을 본인의 서비스에 무한히 확장할 수 있습니다. 처음에는 $5 충전으로 위 예제들을 실행해보며 감을 잡으시길 권합니다. 실제 프로덕션 배포 전에는 반드시 비용 한도와 에러 처리를 갖추세요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;API로 만든 재미있는 프로젝트나 유용한 활용 사례가 있다면 댓글로 공유해 부탁드려요.&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 API</category>
      <category>Claude API JSON</category>
      <category>Claude API 비용절감</category>
      <category>Claude API 사용법</category>
      <category>Claude API 예제</category>
      <category>Claude API 파이썬</category>
      <category>Claude 배치 API</category>
      <category>Claude 프롬프트 캐싱</category>
      <category>claude-sonnet-5 사용법</category>
      <category>소니스토리</category>
      <author>isony</author>
      <guid isPermaLink="true">https://isony.tistory.com/362</guid>
      <comments>https://isony.tistory.com/entry/Claude-%EC%8B%9C%EB%A6%AC%EC%A6%88-10%ED%8E%B8-Claude-API-%EC%82%AC%EC%9A%A9%EB%B2%95-%EA%B0%9C%EB%B0%9C%EC%9E%90%EB%A5%BC-%EC%9C%84%ED%95%9C-%EC%8B%A4%EC%A0%84-%EC%9E%85%EB%AC%B8-2026%EB%85%84-%EC%B5%9C%EC%8B%A0#entry362comment</comments>
      <pubDate>Fri, 31 Jul 2026 08:39:59 +0900</pubDate>
    </item>
    <item>
      <title>[Claude 시리즈 9편] Claude Projects 활용 완벽 가이드 - 매번 설명하는 시간을 없애기</title>
      <link>https://isony.tistory.com/entry/Claude-%EC%8B%9C%EB%A6%AC%EC%A6%88-9%ED%8E%B8-Claude-Projects-%ED%99%9C%EC%9A%A9-%EC%99%84%EB%B2%BD-%EA%B0%80%EC%9D%B4%EB%93%9C-%EB%A7%A4%EB%B2%88-%EC%84%A4%EB%AA%85%ED%95%98%EB%8A%94-%EC%8B%9C%EA%B0%84%EC%9D%84-%EC%97%86%EC%95%A0%EA%B8%B0</link>
      <description>&lt;h1&gt;[Claude 시리즈 9편] Claude Projects 활용 완벽 가이드 - 매번 설명하는 시간을 없애기&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;매번 &quot;저는 Oracle DBA인데요&quot;, &quot;우리 회사 스타일은 이렇고요&quot;를 반복합니다. 이 반복을 완전히 없애주는 기능이 &lt;b&gt;Projects&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Projects는 관련 대화를 하나의 작업 공간으로 묶고, &lt;b&gt;공유 파일과 지침을 한 번만 설정&lt;/b&gt;해두는 기능입니다. 잘 활용하면 Claude가 본인의 맥락을 항상 아는 상태에서 대화가 시작됩니다.&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;Projects의 개념과 Memory와의 차이&lt;/li&gt;
&lt;li&gt;Project 만들기 실전&lt;/li&gt;
&lt;li&gt;강력한 Custom Instructions 작성법&lt;/li&gt;
&lt;li&gt;직무별 Project 구성 예시 5가지&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;Phase 2(실무 활용)의 마지막 글&lt;/b&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;Projects란 무엇인가&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Projects&lt;/b&gt;는 Claude.ai의 작업 공간 기능입니다. 각 프로젝트는 다음을 가집니다.&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;공유 지식(Project knowledge)&lt;/b&gt;: 업로드한 파일들 (모든 대화가 참조)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;커스텀 지침(Custom instructions)&lt;/b&gt;: 이 프로젝트의 규칙&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;프로젝트 안에서 대화를 시작하면 &lt;b&gt;업로드한 파일과 지침이 자동으로 적용&lt;/b&gt;됩니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Memory와 Projects의 차이&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;항목 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;/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;&quot;이 사람은 DBA&quot;&lt;/td&gt;
&lt;td&gt;&quot;이 프로젝트는 A사 운영 문서&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;: Memory가 &quot;나는 누구인가&quot;를 담당하고, Projects가 &quot;이 일은 무엇인가&quot;를 담당합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;참고&lt;/b&gt;: Projects는 무료 tier에서도 사용 가능합니다.&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;Project 만들기 실전&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. Claude.ai 좌측 사이드바 &amp;rarr; Projects
2. Create project 클릭
3. 프로젝트 이름 입력
   (구체적으로: &quot;A사 Oracle 운영&quot; &amp;gt; &quot;일&quot;)
4. 설명 입력 (선택)
&lt;/code&gt;&lt;/pre&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;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;: 자주 바뀌는 파일은 오히려 혼란을 줄 수 있으니, 안정적인 참조 자료 위주로.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Step 3: Custom Instructions 작성&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이게 가장 중요합니다. 다음 섹션에서 자세히 다룹니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Step 4: 검증&lt;/h3&gt;
&lt;pre class=&quot;1c&quot;&gt;&lt;code&gt;프로젝트 안에서 새 대화를 시작하고:
&quot;내가 업로드한 파일 중 [특정 내용]을 참조해서 
답해줘&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;★ 강력한 Custom Instructions 작성법&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Custom Instructions는 이 프로젝트의 모든 대화에 적용되는 규칙입니다. 잘 쓰면 결과가 확 달라집니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;좋은 Custom Instructions의 구조&lt;/h3&gt;
&lt;pre class=&quot;clean&quot;&gt;&lt;code&gt;## 나에 대해
[직무, 경력, 전문 분야]

## 이 프로젝트에 대해
[무슨 작업, 목적, 배경]

## 응답 방식
[톤, 형식, 길이 선호]

## 규칙
[반드시 지킬 것, 하지 말 것]

## 참고
[자주 쓰는 용어, 약어, 맥락]
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;예시: DBA 운영 프로젝트&lt;/h3&gt;
&lt;pre class=&quot;markdown&quot;&gt;&lt;code&gt;## 나에 대해
15년차 Oracle DBA입니다.

## 이 프로젝트에 대해
A사 Oracle 19c 운영 환경 관리 작업입니다.
- OS: Oracle Linux 8
- DB: PRODDB(운영), TESTDB(테스트)
- 멀티테넌트(CDB/PDB) 구성

## 응답 방식
- SQL은 대문자 키워드, 소문자 객체명
- 위험한 명령은 실행 전 영향 범위 먼저 설명
- 코드에는 주석 포함

## 규칙
- 운영 DB 변경 시 반드시 롤백 SQL도 제시
- DROP, TRUNCATE는 재확인 요청
- 추측하지 말고 불확실하면 명시

## 참고
- &quot;결산 배치&quot; = 매월 말 실행되는 PROC_MONTHLY
- &quot;야간 작업&quot; = 오전 1~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;★ 직무별 Project 구성 예시 5가지&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 개발자&amp;middot;DBA 프로젝트&lt;/h3&gt;
&lt;pre class=&quot;asciidoc&quot;&gt;&lt;code&gt;프로젝트명: &quot;[시스템명] 개발/운영&quot;

지식 파일:
- 아키텍처 문서
- API 명세
- 코딩 컨벤션
- 주요 스키마/테이블 정의

Custom Instructions:
- 기술 스택 명시
- 코드 스타일 규칙
- 보안/성능 요구사항
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. 콘텐츠&amp;middot;마케팅 프로젝트&lt;/h3&gt;
&lt;pre class=&quot;asciidoc&quot;&gt;&lt;code&gt;프로젝트명: &quot;블로그 콘텐츠&quot;

지식 파일:
- 브랜드 가이드
- 과거 잘된 글 3~5개 (스타일 학습용)
- 타겟 독자 정의
- 키워드 목록

Custom Instructions:
- 글쓰기 톤 (예: 친근한 전문가)
- 글 구조 표준
- 피해야 할 표현
&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;asciidoc&quot;&gt;&lt;code&gt;프로젝트명: &quot;[프로젝트명] 기획&quot;

지식 파일:
- 프로젝트 배경 문서
- 시장 조사 자료
- 경쟁사 분석
- 목표 지표

Custom Instructions:
- 의사결정 관점 (비용/효과 중심 등)
- 보고 대상 (경영진 등)
- 산출물 형식
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4. 고객 응대 프로젝트&lt;/h3&gt;
&lt;pre class=&quot;asciidoc&quot;&gt;&lt;code&gt;프로젝트명: &quot;고객 응대&quot;

지식 파일:
- 제품/서비스 FAQ
- 응대 톤 가이드
- 자주 묻는 질문과 표준 답변
- 에스컬레이션 기준

Custom Instructions:
- 응대 톤 (정중, 공감)
- 답변 길이
- 하면 안 되는 약속
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5. 학습&amp;middot;연구 프로젝트&lt;/h3&gt;
&lt;pre class=&quot;asciidoc&quot;&gt;&lt;code&gt;프로젝트명: &quot;[주제] 학습&quot;

지식 파일:
- 교재/논문
- 이전 학습 노트
- 용어 정리

Custom Instructions:
- 내 현재 수준
- 설명 방식 (예시 중심 등)
- 확인 질문 요청
&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;Projects 활용 고급 팁&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;pre class=&quot;gcode&quot;&gt;&lt;code&gt;❌ &quot;회사 일&quot; (모든 게 뒤섞임)
✅ &quot;A시스템 운영&quot; / &quot;월간 보고서&quot; / &quot;신규 기획&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;팁 2: Custom Instructions는 점진적 개선&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가 그 스타일을 학습합니다. 블로거&amp;middot;작가에게 특히 유용합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;팁 4: 팀 공유 (Team 플랜)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Team 플랜에서는 프로젝트를 팀원과 공유할 수 있습니다. 팀 표준을 프로젝트에 담아두면 모두가 일관된 결과를 얻습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;팁 5: Claude Code와 역할 분담&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Claude Code를 쓴다면, Projects와 CLAUDE.md는 별개입니다.&lt;/p&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;Projects (claude.ai): 문서, 기획, 분석 작업
CLAUDE.md (Claude Code): 코드 편집 규칙
&lt;/code&gt;&lt;/pre&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%20Code%20%EC%8B%9C%EB%A6%AC%EC%A6%88&quot;&gt;Claude Code 4편&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: Projects를 안 씀&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 흔한 실수입니다. 매번 맥락을 설명하면서도 Projects를 안 만드는 경우. 반복 작업이 있다면 지금 만드세요.&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: Custom Instructions가 너무 추상적&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;/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;/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 2 마무리 - 실무 활용 정리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글로 &lt;b&gt;Phase 2(실무 활용)가 완결&lt;/b&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;&lt;b&gt;5편&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;이메일&amp;middot;보고서 프롬프트 20개&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;6편&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;데이터 분석 (Excel&amp;middot;CSV, 차트)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;7편&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;회의록 요약과 액션 아이템&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;8편&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;비개발자 코딩 (Artifact, 자동화)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;9편&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;Projects로 체계화&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Phase 1이 &quot;Claude를 아는 것&quot;, Phase 2가 &quot;Claude로 일하는 것&quot;이었습니다. 이제 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;다음 Phase 예고&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 글부터는 &lt;b&gt;Phase 3: 심화&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;&lt;b&gt;10편&lt;/b&gt;: Claude API 사용법&lt;/li&gt;
&lt;li&gt;&lt;b&gt;11편&lt;/b&gt;: Claude MCP 완벽 정리&lt;/li&gt;
&lt;li&gt;&lt;b&gt;12편&lt;/b&gt;: Claude Skills 만들기&lt;/li&gt;
&lt;li&gt;&lt;b&gt;13편&lt;/b&gt;: Claude Code로 개인 자산 만들기&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Phase 3는 개발자&amp;middot;전문가를 위한 심화 내용입니다. 비개발자는 필요한 부분만 골라 보셔도 좋을것 같습니다.&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;Projects 활용의 핵심은:&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;Memory는 &quot;나&quot;, Projects는 &quot;이 일&quot;&lt;/b&gt; &amp;mdash; 함께 쓰기&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Custom Instructions가 핵심&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;매번 설명하는 시간이 아깝다면, 오늘 프로젝트 하나만 만들어보세요. 30분 투자로 이후 수십 시간을 아낄 수 있습니다. 그 효과는 쓸수록 쌓입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;본인의 Projects 활용 사례나 유용한 Custom Instructions가 있다면 댓글로 공유해주세요. 다른 분들에게 큰 도움이 됩니다.&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 projects</category>
      <category>Claude 가이드</category>
      <category>Claude 실무</category>
      <category>Claude 예시</category>
      <category>Claude 프로젝트 구성</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/361</guid>
      <comments>https://isony.tistory.com/entry/Claude-%EC%8B%9C%EB%A6%AC%EC%A6%88-9%ED%8E%B8-Claude-Projects-%ED%99%9C%EC%9A%A9-%EC%99%84%EB%B2%BD-%EA%B0%80%EC%9D%B4%EB%93%9C-%EB%A7%A4%EB%B2%88-%EC%84%A4%EB%AA%85%ED%95%98%EB%8A%94-%EC%8B%9C%EA%B0%84%EC%9D%84-%EC%97%86%EC%95%A0%EA%B8%B0#entry361comment</comments>
      <pubDate>Wed, 29 Jul 2026 08:05:38 +0900</pubDate>
    </item>
    <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>
  </channel>
</rss>