
생성 수정
IBM * 레드햇 AX 과정 · 20강
시맨틱 웹과 pgvector — 의미를 저장하는 데이터베이스
2026년 6월 29일(월) ~ 7월 3일(금)
9. 시맨틱 웹 — 웹에 뜻을 얹기
9.1 텍스트의 나열에서 의미의 구조로
시맨틱 웹(Semantic Web) — [웹 설계 방식]인데, [컴퓨터가 스스로 정보의 뜻을 이해하도록 의미 구조를 부여한다]는 점에서 기존 웹과 구별됩니다.
텍스트의 단순 나열이었던 기존 웹에 의미론적 구조를 부여하려는 시도입니다.
9.2 <div style> 과 <h1> — 같은 화면, 다른 뜻
<!-- 구문론적 웹 -->
<div style="font-size:32px; font-weight:bold;">식품위생법 개정안</div>
<!-- 의미론적 웹 -->
<h1>식품위생법 개정안</h1>
브라우저 화면에서는 둘 다 큰 굵은 글씨로 똑같이 보입니다. 그런데 완전히 다릅니다.
<div style="..."> | <h1> | |
|---|---|---|
| 지정하는 것 | 시각적 형식 규칙만 | 문서에서의 역할(제목) |
| 컴퓨터가 아는 것 | "큰 글씨다" | "이것은 이 문서의 최상위 제목이다" |
| 검색엔진 | 본문과 구별 못 함 | 문서 주제로 인식 |
| 스크린리더 | 그냥 텍스트 | 제목으로 읽고 건너뛰기 제공 |
⭐ 구문론적 웹: 컴퓨터는 이 데이터의 본질적 중요도나 맥락을 알지 못한 채 단순히 '큰 글씨'로만 인지합니다. ⭐ 의미론적 웹: 컴퓨터가 이 토큰을 단순한 문자열이 아닌 '중요한 제목이자 고유한 데이터 자원' 으로 스스로 인식하게 만듭니다.
3주차에서 배운 마크업(Markup) = 기계를 위한 이름표라는 정의가 여기서 완성됩니다. <h1> 은 사람에게 큰 글씨를 보여주려는 태그가 아니라 기계에게 "이건 제목"이라고 알려주는 이름표입니다.
9.3 시맨틱 웹의 세 가지 도구
| 도구 | 무엇인가 | 하는 일 |
|---|---|---|
| 시맨틱 태그 | <h1>, <article>, <nav>, <time> … | 각 조각의 역할을 표시 |
| RDF (Resource Description Framework) | 주어-서술어-목적어의 트리플 | 데이터끼리 관계를 연결 |
| 온톨로지 (Ontology) | 도메인 지식 사전 | 어떤 클래스와 관계가 존재하는지 정의 |
RDF — 문장을 세 조각으로
주어(Subject) 서술어(Predicate) 목적어(Object)
───────────── ───────────────── ──────────────
식품위생법 개정안 → 발효일이 → 2026-07-01
식품위생법 개정안 → 관련규정이 → HACCP 의무화 규정
HACCP 의무화 규정 → 적용대상이 → 식품제조업체
이 트리플들을 이으면 그대로 그래프가 됩니다. 노드가 주어·목적어, 엣지가 서술어입니다. 그래서 RDF와 그래프 DB는 같은 모양입니다(5.3절). 축 4의 오른쪽이 웹에서 나타난 이름이 RDF입니다.
9.4 세 층으로 정리
[온톨로지] ← 어떤 개념과 관계가 존재하는가 (사전)
▲
[RDF] ← 실제 데이터끼리 어떻게 이어지는가 (문장)
▲
[시맨틱 태그] ← 이 조각이 무슨 역할인가 (이름표)
아래에서 위로 갈수록 뜻이 진해집니다. 축 1의 오른쪽으로 이동하는 계단입니다.
10. pgvector — 의미론이 데이터베이스로 내려앉는 자리
10.1 웹의 시맨틱 개념을 DB로 옮기면
웹 영역의 시맨틱 개념을 데이터베이스 저장·검색 체계로 고도화해 구현한 형태가 바로 임베딩과 pgvector 의 결합입니다.
[일반 데이터: 구문론적 형태]
│ (임베딩 모델 / 어텐션 통과)
▼
[고차원 벡터: 의미론적 좌표 압축]
│
▼
[pgvector 에 저장 및 제어]
10.2 구문론적 키워드 검색의 한계
기존 RDB는 "식품위생법" 이라는 텍스트 토큰이 정확히 일치하는지 문법적으로만 비교했습니다.
SELECT * FROM documents WHERE title LIKE '%식품위생법%';
| 검색어 | 찾히는가 | 왜 |
|---|---|---|
식품위생법 | ✅ | 글자가 같음 |
식품 위생법 | ❌ | 띄어쓰기 하나 |
식품위생 관련 법령 | ❌ | 글자가 다름 |
HACCP 의무화 규정 | ❌ | 뜻은 매우 가깝지만 글자가 전혀 다름 |
⭐ 띄어쓰기나 단어가 조금만 달라도 검색하지 못하는 것 — 이것이 명확한 구문론적 한계입니다.
10.3 의미론적 벡터 검색
- 임베딩: 텍스트나 데이터(구문론적 형태)를 어텐션 블록 등이 포함된 AI 임베딩 모델에 통과시켜, 맥락과 뜻이 담긴 수백~수천 개의 숫자인 고차원 벡터(의미론적 좌표) 로 변환합니다.
- pgvector: PostgreSQL 내부에서 이 벡터값을 저장(
vector타입) 하고 고차원 공간의 거리를 계산(코사인 유사도 등) 하여 검색할 수 있게 합니다.
-- 1) 확장 설치
CREATE EXTENSION IF NOT EXISTS vector;
-- 2) 벡터 컬럼을 가진 테이블
CREATE TABLE mail_documents (
id BIGSERIAL PRIMARY KEY,
subject TEXT NOT NULL,
body TEXT NOT NULL,
embedding vector(768), -- ⭐ 임베딩 컬럼
created_at TIMESTAMPTZ DEFAULT now()
);
-- 3) 유사도 인덱스 (없으면 전수 검색이 된다)
CREATE INDEX ON mail_documents
USING hnsw (embedding vector_cosine_ops);
-- 4) 의미로 검색하기 — <=> 는 코사인 거리 연산자
SELECT id, subject
FROM mail_documents
ORDER BY embedding <=> :query_embedding
LIMIT 5;
거리 연산자 세 가지
| 연산자 | 거리 종류 | 언제 |
|---|---|---|
<=> | 코사인 거리 | 텍스트 임베딩의 기본값. 벡터의 방향만 본다 |
<-> | 유클리드(L2) 거리 | 크기까지 의미가 있을 때 |
<#> | 음의 내적 | 정규화된 벡터에서 빠른 계산 |
⚠️ 인덱스를 만들 때 쓴 거리 연산자와 검색할 때 쓰는 연산자가 같아야 합니다.
vector_cosine_ops로 인덱스를 만들고<->로 검색하면 인덱스를 타지 않고 전수 검색이 됩니다. 느려진 이유를 못 찾는 흔한 함정입니다.
10.4 왜 굳이 PostgreSQL 안에서 하는가
전용 벡터 DB(Qdrant, Chroma 등)가 있는데도 pgvector를 쓰는 이유가 있습니다.
| pgvector | 전용 벡터 DB | |
|---|---|---|
| 위치·운영 | 이미 쓰는 PostgreSQL 안. 백업·권한이 기존 정책에 통합 | 별도 서버·컨테이너. 관리 대상이 하나 늘어남 |
| 트랜잭션·조인 | 기존 테이블과 한 트랜잭션, 일반 컬럼과 같이 필터링 가능 | 별도 정합성 관리, 메타데이터 필터에 제약 |
| 초대규모 | 수억 벡터에서는 불리 | 대규모에 최적화 |
💡 시작은 pgvector, 규모가 커지면 전용 벡터 DB 검토. "DB를 하나 더 늘리는 것"은 3주차에서 배운 폴리글랏 퍼시스턴스의 이득과 운영 비용을 저울질하는 결정입니다.
11. AWS 3대 서비스 — 어디까지 내가 관리하는가
11.1 이 절의 축
AWS 서비스는 수백 개지만 웹 서비스를 세우는 데 필요한 기본은 셋이고, 이 셋은 하나의 축 위에 순서대로 놓입니다.
내가 다 관리 AWS 가 다 관리
◀──────────────────────────────────────────────────────────────▶
EC2 RDS S3
(컴퓨팅) (데이터베이스) (스토리지)
OS·런타임 직접 플랫폼 관리 자동화 인프라·용량 자동
이것이 이 장의 축 5입니다. 오른쪽으로 갈수록 편해지지만 자유도가 줄어듭니다. 전형적인 트레이드오프입니다.
11.2 Amazon EC2 (Elastic Compute Cloud)
- 개념: 클라우드에서 제공하는 가상 서버(Virtual Server) — 역할: 애플리케이션 실행, 연산 처리 등 인프라의 '두뇌'
| 특징 | 내용 |
|---|---|
| 자유도 | OS(Linux, Windows 등) 선택부터 소프트웨어 설치, 방화벽 설정까지 서버 제어 권한(Root)을 완벽히 가짐 |
| 유연한 확장성 | 트래픽 증가 시 인스턴스 사양을 높이거나(Scale-up), 서버 대수를 늘리는(Scale-out / Auto Scaling) 작업이 용이 |
| 다양한 인스턴스 타입 | 용도에 맞춰 CPU·메모리·GPU·스토리지 성능이 최적화된 모델 선택 가능 |
Scale-up과 Scale-out — 같은 "확장"이 아니다
| Scale-up (수직 확장) | Scale-out (수평 확장) | |
|---|---|---|
| 무엇을 | 한 대를 더 좋게 | 여러 대로 더 많이 |
| 한계 | 물리적 상한이 있음 | 이론적으로 계속 늘릴 수 있음 |
| 전제 | 없음 | 애플리케이션이 무상태(Stateless) 여야 함 |
⭐ 축 3이 여기서 회수됩니다. 서버가 상태를 들고 있으면(세션을 메모리에 보관하면) 서버 대수를 늘리는 순간 어느 서버에 붙느냐에 따라 결과가 달라집니다. 그래서 확장 가능한 백엔드는 무상태로 설계하고, 상태는 DB나 Redis 같은 바깥의 필드에 둡니다. 4주차에서 "백엔드에서 CSV를 제거해 무상태를 유지"했던 이유가 정확히 이것입니다.
11.3 Amazon RDS (Relational Database Service)
- 개념: 클라우드 기반의 관계형 데이터베이스 관리형 서비스(Managed RDBMS) — 역할: 회원 정보, 결제 데이터 등 구조화된(정형) 데이터의 안전한 저장 및 관리
| 특징 | 내용 |
|---|---|
| 운영 자동화 | 데이터베이스 설치, 패치, 백업, 복구 등 복잡한 인프라 관리를 AWS가 대행 |
| 고가용성 | 다중 가용 영역(Multi-AZ) 동기화로 기본 DB 장애 시 예비 DB로 자동 전환(Failover) 되어 서비스 중단 방지 |
| 지원 엔진 | MySQL, PostgreSQL, MariaDB, Oracle, Microsoft SQL Server, 그리고 AWS 최적화 엔진 Amazon Aurora |
가용 영역(AZ, Availability Zone) 은 같은 지역(Region) 안의 물리적으로 분리된 데이터센터입니다. Multi-AZ는 "한 건물이 정전돼도 다른 건물의 복제본이 즉시 이어받는다"는 뜻이며, 백업(과거로 되돌리기)과는 다른 개념입니다. Failover는 지금 이 순간의 연속성입니다.
⚠️ EC2에 직접 PostgreSQL을 설치하는 것과 RDS를 쓰는 것의 차이는 기능이 아니라 책임입니다. 같은 PostgreSQL이지만 패치·백업·장애 전환을 누가 하느냐가 다릅니다.
11.4 Amazon S3 (Simple Storage Service)
- 개념: 무제한 용량의 객체 스토리지 서비스(Object Storage) — 역할: 이미지, 동영상, 로그 파일, 백업본 등 비구조화된(비정형) 파일 저장
| 특징 | 내용 |
|---|---|
| 무제한 저장 공간 | 개별 객체(파일)는 최대 5TB까지 업로드 가능. 전체 저장 용량에는 제한 없음 |
| 높은 내구성 | 99.999999999% (11개의 9) 내구성으로 설계. 여러 데이터센터에 복제본을 분산 저장 |
| 웹 접근성 | 각 파일마다 고유한 URL 주소가 부여되어 웹에서 직접 접근하거나 정적 웹사이트 호스팅에 활용 가능 |
객체 스토리지는 파일 시스템이 아니다
파일 시스템은 폴더 트리 구조에 경로로 접근하고 파일 일부만 수정할 수 있지만, 객체 스토리지는 평평한 버킷 + 키(key) 구조에 HTTP URL로 접근하며 수정은 객체 전체 교체입니다.
⚠️
s3://bucket/images/2026/07/a.png에서images/2026/07/은 폴더가 아니라 키 이름의 일부입니다. 그래서 "폴더 이름 바꾸기"가 실제로는 모든 객체를 새 키로 복사하고 지우는 일이 됩니다.
11.5 서비스 요약 및 비교
| 서비스 | 분류 | 핵심 용도 | 관리 주체 | 데이터 형태 |
|---|---|---|---|---|
| EC2 | 컴퓨팅 | 웹 서버, WAS, 배치 프로그램 실행 | 사용자 (OS 및 런타임 직접 관리) | — |
| RDS | 데이터베이스 | 회원·상품·주문 등 정형 데이터 관리 | AWS + 사용자 (플랫폼 관리 자동화) | 행/열 구조 (SQL) |
| S3 | 스토리지 | 미디어 파일, 로그, 빌드 아티팩트 저장 | AWS (인프라 및 용량 자동 관리) | 객체 (파일 단위) |
11.6 전형적인 웹 서비스 아키텍처 (3-Tier 협업 구조)
[브라우저]
│ ① HTTPS 요청
▼
┌───────────┐
│ EC2 │ 웹 서버 / WAS (Nginx, Node.js, FastAPI …)
└───────────┘
│ │
② SQL │ │ (③ 이미지는 EC2를 거치지 않는다)
▼ │
┌────────┐ │
│ RDS │ │
└────────┘ │
▼
┌──────────┐ ③ 브라우저가 S3 URL 로 직접 다운로드
│ S3 │ ◀───────────────────────────────────────
└──────────┘
- 사용자 요청 처리 (EC2): 사용자가 웹사이트에 접속하면 EC2에 배포된 웹 서버(Nginx, Node.js, Spring Boot 등)가 비즈니스 로직을 처리합니다.
- 구조화 데이터 조회 (RDS): 로그인이나 주문처럼 관계형 데이터가 필요하면 EC2는 RDS에 쿼리를 보내 데이터를 쓰고 읽습니다.
- 정적 자원 서빙 (S3): 상품 이미지나 첨부 파일 같은 대용량 미디어는 EC2 내부가 아닌 S3에 보관하며, 클라이언트가 S3 URL로 직접 다운로드받아 EC2의 네트워크 부하를 줄입니다.
⭐ 3번이 핵심 설계 판단입니다. "파일을 서버에 저장하면 안 되나?" — 됩니다. 하지만 그 순간 서버가 상태를 갖게 됩니다. 서버를 한 대 더 늘리면 그 파일은 새 서버에 없어서 Scale-out이 막힙니다. 그래서 파일은 밖으로 빼서 S3에 둡니다. 다시 축 3입니다.
11.7 비용은 기능이 아니라 설계다
⚠️ 이번 주 읽을거리 중 하나가 AWS 요금 1,755만 원 폭탄 사례입니다. (13.4절)
클라우드 비용 사고는 대부분 "비싼 서비스를 골라서"가 아니라 "안 쓰는 것이 계속 켜져 있어서" 또는 "바깥으로 나가는 트래픽이 많아서" 생깁니다.
| 새는 곳 | 왜 | 대응 |
|---|---|---|
| 실험용 인스턴스를 안 끔 | 시간당 과금 | 예산 알림(Budget Alert) 설정 |
| GPU 인스턴스 방치 | 단가가 매우 높음 | 사용 후 즉시 중지·종료 |
| 아웃바운드 트래픽 | 밖으로 나가는 데이터에 과금 | CDN 캐싱, 이미지 최적화 |
| 키 유출 | 남이 내 계정으로 자원 생성 | 키를 코드에 하드코딩하지 않기 |
⭐ 3주차에서 배운 API 키는
.env로 라는 원칙이 여기서 금액으로 되돌아옵니다. 클라우드에서 키 유출 = 무제한 결제 권한 유출입니다.
12. 실습 — 이번 주에 손으로 한 것
12.1 Ollama로 EXAONE 받기
로컬 SLM의 시작입니다. 명령 두 줄입니다.
# 모델 내려받기
ollama pull exaone3.5:2.4b
# 대화형으로 실행해 보기
ollama run exaone3.5:2.4b
exaone3.5:2.4b의2.4b는 파라미터 24억 개를 뜻합니다. 7B보다 작아 가벼운 장비에서도 돌아갑니다.- EXAONE은 한국어에 특화된 오픈웨이트 모델로, 1.6절의 ① 파운데이션 모델 자리에 들어갑니다.
- 내려받은 모델은 디스크에 저장되고
run하는 순간 VRAM으로 로드됩니다. 3주차의 LOAD(역직렬화)와 같은 방향입니다. - 이후 이 모델을 core의 오케스트레이터로 등록합니다.
12.2 온프레미스 멀티 에이전트 온톨로지 허브 구조
9주차의 스타 토폴로지에 역할을 배정합니다.
| 이름 | 역할 | 설명 |
|---|---|---|
star_craft | 허브(Hub) | 스타 토폴로지의 중심. 전역 온톨로지 인덱스·라우팅 |
lol | core | 순수 인프라 레이어 (DB 엔진·외부 클라이언트) |
faker | 오케스트레이터(Orchestrator) | 어느 에이전트에게 일을 넘길지 결정 |
그리고 apps/star_craft/_docs/star-craft-pipeline.md 에 허브가 도커의 graph db·vector db에 접속하는 파이프라인 전략을 기술합니다.
💡 문서를
_docs아래에 두는 것은 9주차의 문서 배치 프랙탈 규칙을 따른 것입니다. 공통 문서는 루트_docs, 각 앱의 문서는 그 앱 아래_docs.
12.3 LangChain → LangSmith → LangGraph 순차 추가
fastapi/requirements.txt 에 파이썬·토치 버전을 먼저 확인한 뒤 아래 순서로 하나씩 추가합니다.
langchain
langsmith
langgraph
⚠️ 한 번에 셋을 넣지 말고 순차적으로 추가합니다. 의존성 충돌이 났을 때 어느 패키지가 원인인지 즉시 알 수 있기 때문입니다.
| 패키지 | 무엇인가 |
|---|---|
| LangChain | LLM 호출·프롬프트·도구·메모리를 체인으로 엮는 프레임워크 |
| LangSmith | 그 체인의 실행을 추적·평가하는 관측 도구 |
| LangGraph | 체인을 그래프(노드-엣지) 로 표현해 분기·루프·상태를 다루는 확장 |
⭐ 랭그래프와 그래프 DB는 상호 필수 조건입니다. LangGraph는 에이전트의 실행 흐름을 그래프로 표현하고, 그래프 DB는 지식을 그래프로 저장합니다. 둘 다 "노드와 엣지"라는 같은 구조를 쓰기 때문에 흐름과 지식을 같은 언어로 다룰 수 있게 됩니다.
12.4 도커에 그래프 DB와 벡터 DB 올리기
docker-compose.yaml 에 neo4j 와 qdrant 를 추가합니다.
# 두 컨테이너만 백그라운드로 기동
docker-compose up neo4j qdrant -d
비밀번호가 필요하므로 .env 에 값을 추가한 뒤 다시 실행합니다.
# .env
NEO4J_PASSWORD=<강한-비밀번호>
docker-compose up neo4j qdrant -d
⚠️ 환경변수를 고쳤으면 컨테이너를 다시 띄워야 반영됩니다. 3주차에서 배운 "환경변수 고쳤는데 안 바뀜 → 서버를 재시작해야 함"이 컨테이너에도 그대로 적용됩니다.
12.5 DB 세 개를 각각 독립 컨테이너로
.env 의 기존 설정은 그대로 둡니다.
DATABASE_URL=postgresql+psycopg://<user>:<password>@<host>:5432/<db>
그 위에 도커 컨테이너로 세 개의 DB를 각각 독립 컨테이너로 구동합니다.
| 컨테이너 | 종류 | 이 프로젝트에서의 역할 |
|---|---|---|
redis | 키-값 저장소 | 캐시·세션·큐 |
pgvector | PostgreSQL + 벡터 확장 | 의미론적 검색 (축 4 왼쪽) |
neo4j | 그래프 DB | 관계 탐색 (축 4 오른쪽) |
⭐ 이것이 3주차에서 배운 폴리글랏 퍼시스턴스(Polyglot Persistence) 의 실제 모습입니다. "DB 하나로 다 하기"가 아니라 질문의 종류마다 맞는 저장소를 쓰는 것입니다. 각각을 독립 컨테이너로 두면 하나가 죽어도 나머지가 살아 있습니다 — 장애 격리입니다.
12.6 도커 안의 DB 확인하기
컨테이너 안에서 실제로 데이터가 들어갔는지 확인하는 절차입니다. 이 명령들은 외워둘 가치가 있습니다.
# 1) 돌아가는 컨테이너 목록 확인
docker ps
# 2) db 컨테이너 안의 psql 로 접속
docker exec -it db psql -U user -d tailor
접속한 psql 프롬프트 안에서 쓰는 명령입니다.
| 명령 | 하는 일 |
|---|---|
\l | 데이터베이스 목록 |
\dt | 테이블 목록 |
\d contacts | contacts 테이블의 구조 |
\dx | 설치된 확장(extension) 확인 — vector 가 있는지 여기서 봅니다 |
\q | 종료 |
컨테이너에 들어가지 않고 밖에서 한 줄로 실행할 수도 있습니다.
docker exec -it db psql -U user -d tailor -c "SELECT count(*) FROM contacts;"
-it= 인터랙티브 + 터미널 할당(대화형으로 붙을 때 필요). /-c "..."= 명령 하나만 실행하고 빠져나옴(스크립트에 넣기 좋은 형태).
💡
\dx가 특히 중요합니다. pgvector를 쓰려면CREATE EXTENSION vector;가 실행되어 있어야 하는데, "코드는 맞는데type "vector" does not exist에러가 난다"의 원인이 대부분 여기입니다.
12.7 온톨로지 폴더 만들기
5.6절의 설계를 실제 폴더로 옮깁니다.
apps/star_craft/domain/ontology/
원칙 세 가지를 다시 확인합니다.
core/에는 도메인 지식을 넣지 않습니다. 순수 인프라만.- 개별 유스케이스(예: 스팸 분류)는 스포크에 남기고, 허브의 온톨로지를 참조합니다.
- 의존성은
spoke → hub만 허용합니다.
12.8 구글 주소록 연동과 로컬 저장 (소버린 AI)
메일 발송 화면에서 닉네임을 한 글자 칠 때마다 검색해 이메일을 자동 입력하는 기능입니다.
절차:
- 구글 주소록에서 export로 연락처 파일을 내려받습니다.
- 파일을 파싱해 로컬 DB(
contacts테이블)에 적재한 뒤, 프론트에서 한 글자마다 검색 요청 → 후보 목록 → 선택 시 이메일 자동 입력.
⭐ 소버린 AI 관점에서 개인 주소록은 민감정보로 보고 로컬에만 저장합니다. 그래서 이 데이터는 외부 클라우드 DB가 아니라 도커 안의
pgvector와 graph db에 들어갑니다. 1.3절의 "이유 1: 철저한 데이터 보안"이 코드 한 줄이 아니라 저장 위치의 결정으로 나타난 사례입니다.
⚠️ 한 글자마다 요청을 보내면 서버가 금방 몸살이 납니다. 입력이 멈춘 뒤 일정 시간 뒤에 보내는 디바운스(debounce) 를 반드시 넣으세요.
12.9 텔레그램 업무보고 봇
작업 결과를 자동으로 보고받는 통로를 만듭니다.
① 봇 만들기
- 텔레그램에서
@BotFather를 찾아/newbot을 입력합니다. - 봇 이름을 입력합니다.
- 유저네임을 입력합니다. ⚠️ 반드시
_bot또는Bot으로 끝나야 합니다. - 발급된 HTTP API 토큰을 저장합니다.
② Chat ID 확보
⚠️ 봇 대화방에서 반드시
[시작]또는/start를 눌러야 메시지를 받을 수 있습니다. 텔레그램은 사용자가 먼저 말을 걸지 않은 상대에게 봇이 메시지를 보내는 것을 막습니다. "코드는 맞는데 메시지가 안 온다"의 1순위 원인이 이것입니다.
/start 이후 Chat ID를 확인합니다.
③ 코드에 붙이기
# .env
TELEGRAM_TOKEN=<봇토큰>
TELEGRAM_CHAT_ID=<채팅ID>
import os
import httpx
from dotenv import load_dotenv
load_dotenv()
TELEGRAM_TOKEN = os.environ["TELEGRAM_TOKEN"]
TELEGRAM_CHAT_ID = os.environ["TELEGRAM_CHAT_ID"]
async def send_telegram_message(text: str) -> bool:
url = f"https://api.telegram.org/bot{TELEGRAM_TOKEN}/sendMessage"
payload = {"chat_id": TELEGRAM_CHAT_ID, "text": text}
async with httpx.AsyncClient() as client:
response = await client.post(url, json=payload)
return response.status_code == 200
그리고 메일 발송 엔드포인트에서 발송 후 보고를 보냅니다.
@app.post("/api/send-email")
async def send_email(payload: dict):
result = await mail_service.send(payload)
await send_telegram_message(f"메일 발송 완료: {payload['to']}")
return result
💡 이 구조는 6주차에서 배운 아웃바운드 어댑터입니다. 도메인 로직은 "보고한다"만 알고 텔레그램이라는 구체적 수단은 어댑터가 압니다. 나중에 슬랙으로 바꾸더라도 도메인은 손대지 않습니다. (DIP)
12.10 Cloudflare에 도메인 연결하기
DNS 레코드 2건
Cloudflare에서 Add a domain 을 한 뒤, 레코드 두 개를 등록합니다.
| # | Type | Name | 값 | Proxy status |
|---|---|---|---|---|
| ① | A | @ | IPv4 76.76.21.21 | DNS only (회색 구름) |
| ② | CNAME | www | (동일 대상) | DNS only (회색 구름) |
⚠️⚠️ "전 레코드가 회색 구름"이라는 경고 팝업이 뜨면
I'll do this later로 넘어가세요. 주황색 구름(프록시)을 먼저 켜면 Vercel의 도메인 소유권 인증과 SSL 발급에서 에러가 납니다. 순서는 회색으로 연결 완료 → 인증·SSL 정상 → 그 다음에 프록시 검토입니다.
네임서버 이전
- 도메인 등록기관(예: 가비아)에 로그인해 설정 → 네임서버를 Cloudflare가 알려준 값으로 변경합니다. 계정마다 값이 다릅니다. 예:
aaron.ns.cloudflare.com,ines.ns.cloudflare.com - Cloudflare로 돌아와 네임서버 검사를 실행합니다.
- 활성화까지 5~30분. 완료되면 "Great news! Cloudflare is now protecting your site" 메시지가 뜹니다.
💡 네임서버 변경은 "이 도메인의 주소록을 누가 관리할 것인가"를 바꾸는 일이라 전파에 시간이 걸립니다. 기다림도 절차의 일부입니다.
12.11 Cloudflare Zero Trust 터널로 로컬 서버 열기
내 컴퓨터에서 돌아가는 서버를 공인 IP 없이 인터넷에 노출하는 방법입니다.
⭐ Cloudflare Zero Trust > Tunnels 는 카드 등록 없이 사용 가능합니다.
절차:
- 터널 이름을 지정하고, 커넥터로 Docker를 선택합니다.
- 화면에 제공된 명령을 복사합니다.
- VSCode 터미널에 붙여넣고 엔터를 칩니다.
- 녹색 표시가 뜨면
Continue.
이어서 Routes를 설정합니다. 점 세 개 → Edit route 에서 Service URL 에 다음을 입력합니다.
http://host.docker.internal:8000
그리고 브라우저에서 http://api.example.cloud 로 접속했을 때 Swagger 문서가 나오면 성공입니다.
⚠️
host.docker.internal이 핵심입니다. 터널 커넥터는 도커 컨테이너 안에서 돌아가므로, 컨테이너 입장에서localhost는 자기 자신이지 내 PC가 아닙니다.host.docker.internal은 컨테이너에서 호스트 머신을 가리키는 특별한 이름입니다. "터널은 녹색인데 502가 뜬다"의 대부분이 이 주소를localhost로 적어서 생깁니다.
퀵터널 — 더 빠른 방법
n8n을 localhost:5678 로 띄운 뒤 Cloudflare 퀵터널로 즉시 배포할 수도 있습니다. 도메인 설정 없이 임시 주소를 받아 외부에서 접근하는 방식으로 시연·테스트에 적합합니다.
12.12 n8n 라우터로 들어온 메일을 pgvector에 저장
이번 주 파이프라인의 종착점입니다.
detective_mary_mail_router.py 를 작성하되, 기존의 crew_smith_captain_router.py 파이프라인을 참조합니다.
⭐ 반드시 임베딩 컬럼을 생성해서 insert 합니다. 본문 텍스트만 넣으면 그건 그냥 RDB입니다. 임베딩 컬럼이 있어야 의미론적 검색이 가능해집니다. (10.3절)
# 개념 흐름 — 라우터에서 pgvector 까지
async def handle_incoming_mail(mail: MailDTO) -> None:
# 1) 본문을 임베딩 벡터로
vector = await embedder.encode(mail.body) # 예: 768차원
# 2) 원문 + 벡터를 함께 저장
await repository.insert(
subject=mail.subject,
body=mail.body,
embedding=vector, # ⭐ 이 컬럼이 빠지면 의미 검색이 불가능하다
)
임베딩 모델 고르기
pgvector 저장 단계에서 쓸 임베딩 모델은 2026년 한국 현장 기준으로 후보를 추리고 트레이드오프를 비교해 정합니다. 볼 것은 셋입니다.
| 기준 | 확인할 점 |
|---|---|
| 한국어 성능 | 한국어를 제대로 학습했는가. 다국어 모델이면 한국어 비중은? |
| 차원 수 | 클수록 표현력↑ 저장·검색 비용↑. vector(768) vs vector(1536) |
| 실행 위치 | 로컬에서 돌릴 수 있는가(소버린) vs API 호출인가(비용·유출) |
⚠️ 한 번 정하면 바꾸기 어렵습니다. 모델을 바꾸면 저장된 벡터를 전부 다시 만들어야 하고(재임베딩), 차원 수가 다르면 컬럼 정의부터 바뀝니다. 그래서 이 결정은 초반에 신중히 합니다.
12.13 KcELECTRA-base로 메일 먼저 거르기
모든 메일을 다 저장할 필요는 없습니다. 스팸·이상 메일은 파이프라인에 들어오기 전에 걸러냅니다.
KcELECTRA-base 를 detective_watson_watcher_interactor.py 에 import해 메일을 필터링하고, 정상 메일만 기존 파이프라인으로 넘겨 pgvector에 전달합니다.
[n8n 라우터] ──▶ [watcher: KcELECTRA-base 필터] ──┬─▶ 정상 ─▶ [임베딩] ─▶ [pgvector]
└─▶ 스팸 ─▶ 폐기 / 격리
| 왜 작은 모델을 앞에 두는가 | |
|---|---|
| 비용 | 스팸까지 임베딩하면 그만큼 연산과 저장 공간이 낭비됩니다 |
| 품질 | 스팸 벡터가 섞이면 유사도 검색 결과가 오염됩니다 |
| 속도 | 분류 전용 소형 모델은 생성 모델보다 훨씬 빠릅니다 |
⭐ 1.7절에서 말한 하이브리드 전략의 실제 모습입니다 — 분류·전처리는 작은 로컬 모델, 무거운 작업은 그 뒤에.
KcELECTRA는 한국어 구어체(댓글 등)로 학습된 모델이라 실제 메일 텍스트에 잘 맞습니다.
12.14 구현 검증 프롬프트 — 코드 수정은 금지
정책 문서와 실제 구현이 일치하는지 확인하는 프롬프트입니다.
detective-mary-mail-policy.md 여기에 적힌 정책대로 구현된 것인지 체크해줘. (코드 수정은 금지)
⭐
(코드 수정은 금지)가 이 프롬프트의 핵심입니다. 이 괄호가 없으면 AI는 발견한 불일치를 즉시 고치기 시작하고, 그러면 "무엇이 안 되어 있었는지"를 사람이 볼 기회가 사라집니다. 점검과 수정은 분리된 두 작업입니다. 먼저 목록을 받고, 무엇을 고칠지는 사람이 정합니다.
그리고 이 점검에서 나온 미구현 항목들은 곧 앞으로 학습할 내용의 목록이기도 합니다.
6주차에서 배운 하네스(Harness) 관점입니다. AI에게 일을 시키는 것이 아니라 AI가 벗어나지 못할 울타리와 점검 장치를 먼저 만드는 것입니다. 정책 문서(
*-policy.md)가 울타리이고, 이 검증 프롬프트가 센서입니다.
12.15 파일 업로드를 S3로 보내기
프론트에서 업로드한 파일이 백엔드 라우터에 도착하면, AWS S3 버킷으로 전송합니다.
[브라우저: 파일 선택]
│ multipart/form-data
▼
[FastAPI 라우터] ← 여기서 검증 (확장자·크기·MIME)
│
▼
[S3 버킷] ← 저장. 응답으로 객체 URL
│
▼
[DB] ← 파일 자체가 아니라 URL(또는 키)만 저장
핵심 원칙 세 가지입니다.
- 파일 본체는 DB에 넣지 않습니다. DB에는 S3 키 또는 URL만 저장합니다.
- EC2 로컬 디스크에 저장하지 않습니다. 그러면 서버가 상태를 갖게 되어 Scale-out이 막힙니다. (11.6절)
- 라우터에서 검증합니다. 확장자·용량·MIME 타입을 통과한 것만 올립니다. 버킷을 통째로 공개(public)로 열지 마세요.
12.16 OpenCV 맛보기
컴퓨터 비전의 입구를 열어두는 샘플입니다.
import cv2
# 이미지 읽기
img = cv2.imread("sample.jpg")
# 크기와 채널 확인 — (높이, 너비, 채널)
print(img.shape)
# 흑백 변환
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 크기 조정
resized = cv2.resize(gray, (320, 240))
# 저장
cv2.imwrite("output.jpg", resized)
⚠️ OpenCV는 색상 순서가 RGB가 아니라 BGR 입니다. 그래서 상수 이름도
COLOR_BGR2GRAY입니다. 다른 라이브러리와 섞어 쓸 때 색이 이상하게 나오면 이 순서를 먼저 의심하세요.
💡 이미지는 결국 숫자 배열입니다.
img.shape이(480, 640, 3)이면 3차원 배열, 즉 3주차에서 배운 텐서(Tensor) 입니다. 임베딩에서 텍스트가 벡터가 되었듯 이미지는 처음부터 숫자이며, 그래서 이미지 임베딩도 같은 방식으로 성립합니다.
13. 이 주의 읽을거리와 그 맥락
13.1 랭체인(LangChain)이란
🔗 https://www.samsungsds.com/kr/insights/what-is-langchain.html
이게 왜 이 주의 자료인가: 같은 날 requirements.txt 에 langchain → langsmith → langgraph 를 순차 추가했습니다(12.3절). 설치하기 전에 이 도구가 무엇을 해결하려고 만들어졌는지를 알아야 합니다. LangChain의 존재 이유는 "LLM 호출을 편하게"가 아니라 모델·프롬프트·도구·메모리·저장소를 갈아끼울 수 있는 부품으로 만드는 것이며, 3주차에서 배운 전략 패턴과 포트&어댑터가 라이브러리 형태로 구현된 것이라고 보면 정확합니다.
13.2 어텐션 개념 정리 영상 (DL6)
🔗 https://youtu.be/_Z3rXeJahMs
이게 왜 이 주의 자료인가: 8장 전체의 시각 자료입니다. Q·K·V의 내적과 소프트맥스가 행렬 위에서 실제로 어떻게 계산되는지를 애니메이션으로 보면, "어텐션 맵"이라는 말이 추상적인 비유가 아니라 실제 숫자 표라는 사실이 분명해집니다. 이 주에 pgvector에 넣은 벡터가 어디서 나온 것인지를 끝까지 따라가 보는 영상입니다.
13.3 후킹(Hook)은 '이벤트 알림' 역할
🔗 https://youtu.be/0Kx_8n2qI1o
이게 왜 이 주의 자료인가: 이번 주 파이프라인의 출발점이 n8n 웹훅(Webhook) 입니다. "후킹은 이벤트 알림"이라는 한 줄이 웹훅·리액트 Hooks·Git Hook을 한꺼번에 정리해 줍니다.
| 이름 | 무엇에 걸어두는가 | 언제 불리는가 |
|---|---|---|
| Webhook | HTTP 엔드포인트 | 외부 시스템에 사건이 생겼을 때 |
| React Hooks | 컴포넌트 생명주기 | 렌더·마운트·값 변경 시점 |
| Git Hook (pre-commit) | 커밋·푸시 시점 | 그 동작이 일어나기 직전 |
셋 다 "내가 부르는 게 아니라 불려지는 것" 입니다. 3주차에서 배운 IoC(제어의 역전) 와 같은 구조입니다.
13.4 AWS 1,755만 원 요금 폭탄 사례
🔗 https://velog.io/@ysung327/AWS-1700만원-요금폭탄-맞았다
이게 왜 이 주의 자료인가: 같은 주에 S3에 파일을 올리기 시작했고(12.15절), EC2·RDS·S3를 배웠습니다(11장). 클라우드는 켜는 것은 쉽고 끄는 것은 잊기 쉽습니다. 이 글은 "무엇을 쓸 것인가"만큼 "얼마가 나올 것인가"를 설계 단계에서 계산해야 한다는 사실을 금액으로 보여줍니다. 계정을 만들자마자 할 일은 예산 알림(Budget Alert) 설정입니다. (11.7절)
13.5 Resend — 메일 전송 API
이게 왜 이 주의 자료인가: 이번 주 파이프라인의 마지막 조각이 메일 발송입니다. n8n의 Gmail 노드로도 보낼 수 있지만, 백엔드에서 직접 보내야 하는 경우(트랜잭션 메일, 알림)에는 전용 API가 필요합니다. n8n(자동화 도구)과 Resend(전송 API)는 경쟁 관계가 아니라 층위가 다릅니다. n8n은 "언제 어떤 순서로", Resend는 "실제 전달" — 이 장의 축으로 보면 n8n이 정책, Resend가 실행입니다.
13.6 n8n을 쓰는 이유
🔗 https://youtube.com/shorts/WqOe_bqgKtA
이게 왜 이 주의 자료인가: 이번 주 내내 n8n이 파이프라인의 입구 역할을 했습니다. 직접 코드를 짜면 되는데 왜 도구를 끼우는가에 대한 답입니다. n8n의 자리는 6주차에서 배운 아웃바운드 어댑터이자 바뀔 가능성이 높은 바깥쪽입니다. 자주 바뀌는 것을 코드 밖으로 빼두면 연동처가 바뀌어도 도메인 로직은 그대로입니다.
부록 A. 용어 사전
| 용어 | 영문 | 상위 범주 | 정의 |
|---|---|---|---|
| 구문론 | Syntax | 해석 관점 | 형식과 구조적 규칙이 맞는가를 보는 관점 |
| 의미론 | Semantics | 해석 관점 | 본질적인 뜻과 맥락이 맞는가를 보는 관점 |
| SLM | Small Language Model | 언어 모델 | 파라미터가 작아 단일 서버·GPU에서 구동 가능한 모델 |
| LLM | Large Language Model | 언어 모델 | 파라미터가 매우 큰 대규모 언어 모델 |
| 온프레미스 | On-Premise | 실행 위치 | 자사 건물·인프라 안에서 직접 구동하는 방식 |
| 소버린 AI | Sovereign AI | 관점 | 데이터 주권을 자체 보유하는 AI 운영 관점 |
| VRAM | Video RAM | 하드웨어 | GPU 메모리. 로컬 모델 크기의 상한을 정함 |
| 양자화 | Quantization | 모델 압축 | 가중치 정밀도를 낮춰 메모리를 줄이는 기법 |
| 파운데이션 모델 | Foundation Model | 모델 유형 | 미세조정의 기반이 되는 사전학습 모델 |
| 미세조정 | Fine-Tuning | 학습 방법 | 사전학습 모델을 특정 도메인 데이터로 추가 학습 |
| 서빙 프레임워크 | Serving Framework | 인프라 | 모델 실행을 최적화하고 API로 노출하는 층 |
| vLLM | — | 서빙 프레임워크 | 고성능·고처리량 서빙에 특화 |
| Ollama | — | 서빙 프레임워크 | 로컬에서 명령 한 줄로 모델을 받고 실행 |
| EXAONE | — | 파운데이션 모델 | 한국어 특화 오픈웨이트 언어 모델 |
| KcELECTRA | — | 분류 모델 | 한국어 구어체 학습 기반의 경량 분류 모델 |
| 딥러닝 | Deep Learning | 방법론 | 데이터를 학습하는 인공신경망 방법론 |
| AI 에이전트 | AI Agent | 시스템 | 목표 달성을 위해 스스로 판단·행동하는 자율 시스템 |
| 자기 성찰 | Self-Reflection | 에이전트 동작 | 결과를 확인해 스스로 경로를 수정하는 루프 |
| 무상태 | Stateless | 상태 성질 | 내부에 상태를 보관하지 않는 성질 |
| 상태 유지 | Stateful | 상태 성질 | 내부에 상태를 보관하는 성질 |
| 화살표 함수 | Arrow Function | JS 문법 | this 를 선언 위치 기준으로 고정하는 함수 |
| 렉시컬 디스 | Lexical This | JS 개념 | 호출이 아니라 선언 위치로 this 가 정해지는 성질 |
| 클로저 | Closure | JS 개념 | 외부 함수 종료 후에도 그 스코프 변수를 기억하는 함수 |
| 렉시컬 환경 | Lexical Environment | JS 내부 구조 | 선언 시점의 스코프 정보를 담은 구조 |
| 데이터 은닉 | Private Variable | 설계 기법 | 외부에서 직접 접근하지 못하게 상태를 감춤 |
| Context | — | React 기능 | 하위 컴포넌트가 공유하는 전역 상태 통로 |
| 임베딩 | Embedding | 데이터 변환 | 비정형 데이터를 의미가 보존된 고차원 수치 벡터로 변환 |
| 인코딩 | Encoding | 데이터 변환 | 식별을 위해 값에 번호를 붙이는 것 (거리에 의미 없음) |
| 밀집 벡터 | Dense Vector | 데이터 형태 | 대부분의 값이 0이 아닌 벡터 |
| 코사인 유사도 | Cosine Similarity | 거리 척도 | 두 벡터의 방향 일치도로 유사도를 재는 방법 |
| 청킹 | Chunking | RAG 절차 | 문서를 임베딩 단위로 쪼개는 것 |
| 벡터 DB | Vector Database | 저장소 | 고차원 벡터의 유사도 검색에 특화된 저장소 |
| ANN | Approximate Nearest Neighbor | 알고리즘 | 근사적으로 가장 가까운 이웃을 빠르게 찾는 방식 |
| HNSW | Hierarchical Navigable Small World | ANN 알고리즘 | 계층형 그래프를 타고 이웃을 좁혀가는 방식 |
| IVF | Inverted File Index | ANN 알고리즘 | 공간을 구역으로 나눠 가까운 구역만 탐색 |
| 그래프 DB | Graph Database | 저장소 | 관계를 일급 객체로 다루는 노드-엣지 저장소 |
| 노드 | Node / Vertice | 그래프 요소 | 그래프의 점. 엔티티 |
| 엣지 | Edge / Link | 그래프 요소 | 그래프의 선. 관계 |
| 일급 객체 | First-class Citizen | 개념 | 값처럼 저장·전달·질의할 수 있는 대상 |
| 그래프 탐색 | Graph Traversal | 연산 | 포인터를 따라 네트워크를 종단하는 연산 |
| Neo4j | — | 그래프 DB | 대표적인 그래프 데이터베이스 제품 |
| Qdrant | — | 벡터 DB | 대표적인 전용 벡터 데이터베이스 제품 |
| pgvector | — | PostgreSQL 확장 | PostgreSQL에 vector 타입과 유사도 검색을 추가 |
| RAG | Retrieval-Augmented Generation | 기법 | 검색 결과를 프롬프트에 포함해 생성하는 방식 |
| Vector RAG | — | RAG 유형 | 질문을 임베딩해 벡터 DB에서 유사 검색 |
| Graph RAG | — | RAG 유형 | 그래프 DB에서 관계성 데이터를 추출 |
| GraphRAG | — | 아키텍처 | 벡터 검색과 그래프 구조를 결합한 RAG |
| 환각 | Hallucination | 현상 | 모델이 그럴듯한 거짓을 만들어내는 현상 |
| 온톨로지 | Ontology | 지식 구조 | 개념·속성·관계를 정형화한 지식 지도 |
| is-a | — | 온톨로지 관계 | "~는 ~의 한 종류다" (상속) |
| part-of | — | 온톨로지 관계 | "~는 ~에 속한다" (부분-전체) |
| 규칙 기반 | Rule-based | 의사결정 방식 | 명시적 If-Then으로 통제하는 방식 |
| 정책 기반 | Policy-based | 의사결정 방식 | 목적함수·제약·보상을 정의하는 방식 |
| 규칙 폭발 | Rule Explosion | 실패 양상 | 예외가 늘며 규칙 수가 기하급수적으로 증가 |
| 목적함수 | Objective Function | 최적화 요소 | 무엇을 최대·최소화할지 정의한 수식 |
| 가드레일 | Guardrail | 통제 장치 | 절대 넘으면 안 되는 경계를 강제하는 검증 |
| 디지털 트윈 | Digital Twin | 시뮬레이션 | 현실 대상을 가상 공간에 복제한 모델 |
| 토큰 | Token | 데이터 단위 | 규칙에 따라 쪼갠 최소 분절 단위 |
| 어텐션 | Attention | 신경망 기법 | 토큰끼리 주목도를 계산해 문맥을 반영하는 메커니즘 |
| Query | Q | 어텐션 요소 | "나를 설명해 주는 게 주변에 있는가"를 묻는 벡터 |
| Key | K | 어텐션 요소 | "내가 그 단서다"라고 답하는 벡터 |
| Value | V | 어텐션 요소 | 실제로 더해질 의미론적 변화량 벡터 |
| 내적 | Dot Product | 연산 | 두 벡터의 방향 일치도를 한 숫자로 만드는 연산 |
| 소프트맥스 | Softmax | 연산 | 값들을 양수로 만들고 합이 1이 되게 정규화 |
| 어텐션 맵 | Attention Map | 산출물 | 어떤 토큰이 어디에 얼마나 주목하는지의 분포 |
| 멀티헤드 어텐션 | Multi-Head Attention | 구조 | 여러 어텐션을 병렬로 돌려 다각도 관계를 포착 |
| 트랜스포머 | Transformer | 아키텍처 | 어텐션을 핵심으로 하는 신경망 구조 |
| 시맨틱 웹 | Semantic Web | 웹 설계 | 기계가 뜻을 이해하도록 구조를 부여한 웹 |
| 시맨틱 태그 | Semantic Tag | HTML | 역할을 나타내는 태그 (<h1>, <article> 등) |
| RDF | Resource Description Framework | 데이터 모델 | 주어-서술어-목적어 트리플로 관계를 표현 |
| EC2 | Elastic Compute Cloud | AWS 컴퓨팅 | 자유도 높은 클라우드 가상 서버 |
| RDS | Relational Database Service | AWS DB | 운영이 자동화된 관리형 관계형 DB |
| S3 | Simple Storage Service | AWS 스토리지 | 무제한 용량의 객체 스토리지 |
| Scale-up | 수직 확장 | 확장 전략 | 한 대의 사양을 높이는 것 |
| Scale-out | 수평 확장 | 확장 전략 | 서버 대수를 늘리는 것 |
| Multi-AZ | Multi Availability Zone | 고가용성 | 물리적으로 분리된 데이터센터에 동기 복제 |
| Failover | — | 고가용성 | 장애 시 예비 자원으로 자동 전환 |
| 객체 스토리지 | Object Storage | 저장 방식 | 폴더 트리가 아닌 버킷+키 구조의 저장소 |
| LangChain | — | 프레임워크 | LLM·프롬프트·도구를 체인으로 엮는 도구 |
| LangSmith | — | 관측 도구 | 체인 실행을 추적·평가 |
| LangGraph | — | 프레임워크 확장 | 실행 흐름을 그래프로 표현해 분기·루프·상태 처리 |
| n8n | — | 자동화 도구 | 노드 기반 워크플로우 자동화 |
| 웹훅 | Webhook | 연동 방식 | 사건 발생 시 지정 URL로 알림을 보내는 방식 |
| 퀵터널 | Quick Tunnel | Cloudflare 기능 | 도메인 설정 없이 임시 주소로 로컬을 노출 |
| Zero Trust Tunnel | — | Cloudflare 기능 | 공인 IP 없이 로컬 서비스를 안전하게 노출 |
host.docker.internal | — | 도커 호스트명 | 컨테이너에서 호스트 머신을 가리키는 이름 |
| 디바운스 | Debounce | 프론트 기법 | 입력이 멈춘 뒤에 한 번만 요청을 보내는 처리 |
| OpenCV | — | 라이브러리 | 이미지·영상 처리를 위한 컴퓨터 비전 라이브러리 |
부록 B. 스스로 확인하기
먼저 답해보고, 막히면 옆의 절을 펼치세요.
| # | 질문 | 답이 있는 곳 |
|---|---|---|
| 1 | SLM을 온프레미스에 세우는 네 가지 이유는? | 1.3 |
| 2 | 7B 모델에 왜 VRAM 16GB가 필요한가? 계산식으로 | 1.4 |
| 3 | 양자화는 무엇을 얻고 무엇을 잃는가? | 1.5 |
| 4 | 온프레미스 SLM 아키텍처 3요소와, 각각이 담당하는 실패 유형은? | 1.6 |
| 5 | 딥러닝과 에이전트를 나누는 두 축은? | 2.3 |
| 6 | 화살표 함수와 클로저는 축구장의 어디에 각각 놓이는가? | 3.2, 3.3 |
| 7 | 인코딩과 임베딩의 결정적 차이는? | 4.2 |
| 8 | King − Man + Woman ≈ Queen 이 성립하는 이유는? | 4.3 |
| 9 | HNSW와 IVF는 각각 무엇을 희생해서 무엇을 얻는가? | 5.2 |
| 10 | 그래프 DB에서 "관계가 일급 객체"라는 말의 뜻은? | 5.3 |
| 11 | GraphRAG는 왜 벡터 DB만으로 부족한 질문을 푸는가? | 5.5 |
| 12 | 온톨로지 폴더를 core/ 에 두면 안 되는 이유는? | 5.6 |
| 13 | 규칙 기반의 대표 실패 양상 이름은? | 6.1 |
| 14 | 통합 워크플로우에서 정책이 앞이고 규칙이 뒤인 이유는? | 6.5 |
| 15 | "구문론 검사를 통과했다"는 말의 정확한 뜻은? | 7.2 |
| 16 | Q·K·V를 각각 한 문장으로 말하면? | 8.3 |
| 17 | 어텐션이 결과를 "교체"가 아니라 "덧셈"으로 하는 이유는? | 8.3 |
| 18 | <div style> 과 <h1> 은 화면이 같은데 무엇이 다른가? | 9.2 |
| 19 | 키워드 검색이 "HACCP 의무화 규정"을 못 찾는 이유는? | 10.2 |
| 20 | pgvector 인덱스를 만들었는데도 느린 흔한 원인은? | 10.3 |
| 21 | Scale-out에 왜 무상태가 전제되는가? | 11.2 |
| 22 | 파일을 EC2 디스크가 아니라 S3에 두는 이유는? | 11.6, 12.15 |
| 23 | 터널이 녹색인데 502가 뜨는 대표 원인은? | 12.11 |
| 24 | \dx 를 언제 쓰는가? | 12.6 |
| 25 | 텔레그램 봇이 메시지를 못 보내는 1순위 원인은? | 12.9 |
| 26 | Cloudflare 주황색 구름을 먼저 켜면 안 되는 이유는? | 12.10 |
| 27 | 검증 프롬프트에 (코드 수정은 금지) 를 붙이는 이유는? | 12.14 |
부록 C. 자주 하는 실수
| 실수 | 바로잡기 |
|---|---|
| "SLM = 성능이 낮은 모델" | ❌ 크기 축과 성능 축은 다릅니다. 도메인 특화 시 충분한 정확도 |
| "온프레미스의 premise = 전제" | ❌ 건물·구내입니다. "우리 건물 안에서" |
| "GPU만 좋으면 큰 모델이 돌아간다" | ⚠️ 상한을 정하는 것은 VRAM 용량입니다 |
| "양자화하면 공짜로 가벼워진다" | ⚠️ 정밀도를 잃습니다. 트레이드오프 |
| "RAG는 모델을 똑똑하게 만드는 것" | ❌ RAG의 목적은 환각 방지와 최신성입니다 |
| "에이전트는 딥러닝보다 발전한 기술" | ❌ 층위가 다릅니다. 에이전트 안에 딥러닝이 있습니다 |
| "프롬프트를 잘 쓰면 그게 에이전트" | ⚠️ 도구 사용 + 피드백 루프가 없으면 한 번의 추론입니다 |
| "에이전트가 목표까지 스스로 정한다" | ❌ 목표·권한은 사람이 줍니다. 정하는 것은 경로입니다 |
| "화살표 함수는 그냥 짧게 쓰는 문법" | ❌ this 의 결정 방식이 다릅니다 (Lexical This) |
| "무상태가 항상 옳다" | ⚠️ 기억할 것은 어딘가에 있어야 합니다. 좁은 자리에 몰아두는 것이 목표 |
| "임베딩 = 텍스트를 숫자로 바꾸는 것" | ⚠️ 그건 인코딩입니다. 임베딩은 거리에 뜻이 있습니다 |
| "적재와 질의에 다른 임베딩 모델을 써도 된다" | ❌ 같은 모델이어야 합니다. 다르면 거리 계산이 무의미 |
| "벡터 DB가 그래프 DB의 상위 호환" | ❌ 축이 다릅니다. 유사도 ↔ 관계 |
| "인덱스는 나중에 만들면 된다" | ⚠️ 없으면 전수 검색이 됩니다 |
| "인덱스를 만들었는데 느리다" | ⚠️ 인덱스의 거리 연산자와 쿼리 연산자가 다른지 확인 |
| "RAG = 벡터 DB" | ❌ RAG는 검색 결과를 프롬프트에 넣는 것. 저장소는 선택지 |
| "규칙 기반은 구식" | ❌ 법·안전 검증은 규칙이어야 합니다. 자리가 다를 뿐 |
| "가드레일을 파이프라인 중간에 둔다" | ⚠️ 마지막에 둬야 최종 출력의 검증을 보장합니다 |
| "문법 검사를 통과했으니 맞다" | ❌ 형식만 맞습니다. 뜻은 별개입니다 |
| "토큰 = 단어" | ⚠️ 규칙에 따른 분절 단위. 단어보다 작을 수도 큽니다 |
| "어텐션은 중요한 것만 남긴다" | ❌ 버리지 않고 가중치를 다르게 줘서 더합니다 |
| "임베딩 값은 고정이다" | ⚠️ 초기 임베딩만 고정. 어텐션을 지나며 이동합니다 |
"<div> 에 스타일 주면 제목이 된다" | ❌ 사람에게만 제목입니다. 기계는 모릅니다 |
"S3의 images/ 는 폴더다" | ❌ 키 이름의 일부입니다. 이름 변경 = 전체 복사 |
| "RDS는 EC2에 DB 깐 것보다 기능이 많다" | ⚠️ 같은 엔진입니다. 다른 건 책임의 소재 |
| "파일은 서버에 저장하면 편하다" | ⚠️ 서버가 상태를 갖게 되어 Scale-out이 막힙니다 |
| "터널이 녹색이니 설정은 끝" | ⚠️ Service URL이 localhost 면 502. host.docker.internal |
| "Cloudflare 프록시를 먼저 켜자" | ❌ SSL·소유권 인증이 깨집니다. 회색 구름 먼저 |
| "봇 토큰만 있으면 메시지가 간다" | ❌ 사용자가 먼저 /start 를 눌러야 합니다 |
"type vector does not exist 는 코드 문제" | ⚠️ \dx 로 확장 설치 여부부터 확인하세요 |
| "AI에게 점검시키면서 고치라고 같이 말한다" | ⚠️ 점검과 수정은 분리하세요. (코드 수정은 금지) |
| "클라우드 요금은 다 쓰고 나서 보면 된다" | ❌ 예산 알림을 먼저 겁니다 |
부록 D. 날짜별 색인
이 장의 내용이 실제 수업에서 어느 날 다뤄졌는지입니다.
| 날짜 | 다룬 내용 | 이 장의 절 |
|---|---|---|
| 6/29 (월) | LLM 대비 SLM의 장점과 한계, 온프레미스 SLM 도입 배경·하드웨어·양자화·아키텍처 3요소, 딥러닝 vs AI 에이전트, 온프레미스 멀티 에이전트 온톨로지 허브 구조(star_craft=허브 / lol=core / faker=오케스트레이터), 올라마로 EXAONE 받기, 허브 파이프라인 문서, 랭체인·랭스미스·랭그래프 순차 추가, docker-compose에 neo4j·qdrant 추가, redis·pgvector·neo4j 독립 컨테이너 구동 | 1, 2, 5.6, 12.1~12.5, 13.1 |
| 6/30 (화) | 에이전틱 AI 시대의 온톨로지 — 검색을 넘어 실행으로, 온톨로지 설계 4단계(객체 탐색 → 클래스 정의 → 속성 부여 → is-a·part-of 관계 연결), 온톨로지 폴더 위치와 spoke → hub 의존성 규칙, 구글 주소록 API 연동, 소버린 AI 관점의 로컬 저장, 도커 내부 DB 확인 명령어, 텔레그램 업무보고 봇 3단계 | 1.3, 5.6, 12.6~12.9 |
| 7/1 (수) | 축구장 비유(페널티 에어리어 ↔ 넓은 필드), 화살표 함수·클로저·React·파이썬 매핑, Vector RAG vs Graph RAG, 후킹은 이벤트 알림, 구현 검증 프롬프트, n8n 퀵터널 배포, Cloudflare 도메인 연결·DNS 레코드 2건·회색 구름 원칙, 네임서버 이전, Zero Trust 터널과 host.docker.internal | 3, 5.5, 12.10~12.11, 12.14, 13.3 |
| 7/2 (목) | 임베딩, 벡터 DB(ANN·HNSW·IVF), 그래프 DB(노드-엣지·그래프 탐색), GraphRAG, 규칙 기반 vs 정책 기반, 통합 지능형 아키텍처 매트릭스와 워크플로우, n8n 라우터 → pgvector 저장(임베딩 컬럼 필수), 한국 현장 기준 임베딩 모델 선정, KcELECTRA-base 메일 필터 | 4, 5, 6, 12.12~12.13 |
| 7/3 (금) | 구문론 vs 의미론, 토큰과 어텐션(Q·K·V, 내적·소프트맥스·어텐션 맵, 멀티헤드), 시맨틱 웹(시맨틱 태그·RDF·온톨로지), pgvector와 의미론적 검색, AWS EC2·RDS·S3와 3-Tier 구조, AWS 요금 폭탄 사례, S3 파일 업로드, OpenCV 샘플, Resend | 7, 8, 9, 10, 11, 12.15~12.16, 13.2, 13.4, 13.5 |
부록 E. Gemini / NotebookLM 프롬프트
복습 문제 받기
이 10주차 교재만 근거로 8문제를 내줘. 비전공자 기준으로.
"구문론 vs 의미론", "규칙 기반 vs 정책 기반", "어텐션의 Q·K·V"는 반드시 포함해줘.
답은 바로 주지 말고, 내가 답한 다음에 채점하고
틀린 이유를 교재의 어느 절을 근거로 설명해줘. 교재에 없는 내용은 꺼내지 마.
인포그래픽 ① — 이 장의 중심 축
「7. 구문론과 의미론」의 7.3 표를 인포그래픽 1장으로 만들어줘.
- 가운데 세로줄을 기준으로 왼쪽은 구문론(Rule-based), 오른쪽은 의미론(Policy-based)
- 위에서 아래로 네 층: 데이터 단위 / 웹 / 데이터베이스 / 의사결정
- 각 층마다 왼쪽·오른쪽에 해당 기술 이름을 적고, 왼쪽에서 오른쪽으로 가는 화살표에
"무엇이 더해졌는가"를 한 단어로 표시 (예: 문맥, 관계, 좌표)
- 전문용어는 한글(영문) 병기
인포그래픽 ② — 축구장
「3. 축구장 — 페널티 에어리어와 넓은 필드」를 인포그래픽 1장으로 만들어줘.
- 축구장 그림 위에 좌우 페널티 에어리어와 가운데 넓은 필드를 배치
- 에어리어 안: 화살표 함수 / React 함수형 컴포넌트+Hooks / 파이썬 인스턴스 메서드
- 필드 위: 클로저 / React 클래스형·Context / 파이썬 클래스
- 아래쪽에 3.4의 비교표를 그대로 넣고, "무상태 ↔ 상태 유지" 축을 크게
인포그래픽 ③ — 통합 워크플로우
「6.5 통합 워크플로우」를 세로 흐름도 인포그래픽으로 만들어줘.
- 원천정보 → 임베딩 → (벡터DB / 그래프DB 두 갈래) → 정책 기반 엔진 → 규칙 기반 가드레일 → 최종안
- 두 DB 갈래는 색을 다르게 하고, 각각 "유사도" / "관계"라고 라벨
- 정책 엔진은 둥근 모양, 규칙 가드레일은 각진 모양으로 대비
- 오른쪽 여백에 "왜 정책이 먼저이고 규칙이 나중인가"를 두 줄로
인포그래픽 ④ — 어텐션
「8. 토큰과 어텐션 메커니즘」을 인포그래픽 1장으로 만들어줘.
- 위: "The fluffy blue creature" 를 토큰으로 쪼갠 줄
- 가운데: creature 의 Q 가 fluffy·blue 의 K 와 연결되는 화살표, 굵기로 어텐션 가중치 표현
- 아래: E_old + ΔE = E_new 를 수식과 함께, "그냥 생명체 → 복슬복슬하고 파란 생명체"
- 오른쪽 아래에 "멀티헤드 = 이 그림을 96장 겹친 것" 이라고 작게
막힐 때
10주차에서 "___" 가 이해가 안 돼.
이 교재의 판별 축 5개(구문론/의미론, 규칙/정책, 무상태/상태, 유사도/관계, 내가 관리/AWS 관리)만
써서 다시 설명해줘. 교재에 없는 새 비유는 만들지 마.
미국식 분류로 다시 정리하기
이 교재에 나온 비유(축구장, 뇌와 몸, 통합 번역기, 장기 기억 장치, 연상 지도)를 전부 걷어내고,
"이것은 무엇의 한 종류인가 / 형제 개념과 무엇으로 갈리는가" 형식으로만
임베딩·벡터DB·그래프DB·규칙 기반·정책 기반·토큰·어텐션을 다시 정의해줘.
앞뒤 장 연결 확인
이 교재에서 "앞에서 배운" 또는 "앞 장에서 이어집니다"라고 표시된 부분을 모두 찾아서,
3·4·6·9주차의 어떤 개념이 이번 장에서 어떤 이름으로 다시 나오는지 표로 정리해줘.
컬럼: 원래 장 / 원래 이름 / 이번 장의 절 / 이번 장에서의 이름 / 무엇이 달라졌는가
LangTailor