콘텐츠로 이동

용어집

세무 도메인 + 시스템 아키텍처 + 운영에 등장하는 용어 · 약어 · 식별자를 카테고리별로 정리한 사전. 각 항목은 정의 1-3 문장 + 등장하는 위키 페이지 링크로 구성된다. 정의는 각 페이지 본문에서 발췌한 것으로, 추측이 아니라 코드/설정 기반 사실에 한정한다.

카테고리별 빠른 색인


세무 도메인

LawCategory

법령 카테고리 enum. 13개 값(TRANSFER_INCOME, INHERITANCE, STOCK, COMPREHENSIVE_REAL_ESTATE, LOCAL, INCOME, CORPORATE, VALUE_ADDED, SALARY_INSURANCE, ADJUSTMENT_INTERNATIONAL, TAX_NORMAL, ACCOUNTING, COMMERCIAL_LAW)을 가지며, 사용자가 채팅 시작 시 명시 선택하거나 LLM이 추론한다. category 컬럼은 LawCategory.name()을 STRING으로 저장. → 카테고리 / 게시판, 리포트 생성

TaxCategory

LLM 추론 전용 카테고리 enum. LawCategory1:1 매핑이 아니다 — 예: INHERITANCE / GIFT(TaxCategory)가 LawCategory.INHERITANCE 하나로 합쳐진다. TaxCategoryMapping.toLawCategory()에서 변환. → 카테고리 / 게시판

TaxCategoryMapping

카테고리별 키워드 · baseLaws · relatedLaws · taxTypes의 정적 매핑(Issue #88 "주변법"). RAG 검색 시 카테고리 → 베이스법 + 주변법 + 시행령/시행규칙으로 자동 확장하는 allLaws/inferAndExpand 로직의 기반. → 카테고리 / 게시판

주변법

세법 카테고리 대표법 외에 RAG 검색 결과에 끼어 들어오는 상법·민법 등 비세법. isCoreTaxLaw(lawName, primaryLawName)로 필터링하여 초기 참고자료에서 제거하고, 답변 본문에서 명시 언급될 때만 보충 단계에서 재추가한다. → 리포트 생성

3단비교 (Threeway)

법-시행령-시행규칙 세 단계를 묶어 보여주는 비교. tax-threeway ES 인덱스가 article_key 기준으로 세 조문을 묶고, ThreewayServicefindByAnyArticleKey로 조회. 모법(A-prefix) · 시행령(B-prefix) · 시행규칙(C-prefix). → Elasticsearch, 리포트 생성

ReferenceType

참고자료 종류를 분류하는 enum (검색·라우팅 용). LAW / PRECEDENT(판례) / COUNSEL(상담) / GLOSSARY(용어) / WRITTEN_INQUIRY / ENFORCEMENT / ACCOUNTING 등. IntentRouter.MANDATORY_INDICES에 포함되는 항목 결정. → 리포트 생성

DataType

TurnReferenceData.dataType 컬럼에 저장되는 enum (영속화 용). LAW / EXAM(예규) / COUNSEL / WORD(용어) 등 — ReferenceType과 동일하지 않고 1:1도 아님. 프론트엔드 그룹 표시에 사용. → 리포트 생성, 관리자 콘솔

article_key

법령 조문을 식별하는 7자 정규화 키. A/B/C prefix로 법/시행령/시행규칙을 구분. tax-lawstax-threeway 인덱스의 핵심 필드이며 threeway 보충(supplementThreewayReferences)의 join key. → Elasticsearch, 리포트 생성

TaxCategoryAnalysis

TaxCategoryInferenceService.analyzeQuestionWithLlm() 또는 키워드 매칭(analyzeQuestion)의 결과 객체. categoryScores 필드에 카테고리별 점수가 담기며, 점수 ≥ MIN_SCORE_THRESHOLD(2) 카테고리 + 1위의 SECONDARY_SCORE_RATIO(70%) 이상인 보조 카테고리가 후보로 노출된다. → 카테고리 / 게시판


RAG · LLM

RAG (Retrieval-Augmented Generation)

외부 자료를 검색해 LLM 프롬프트 context에 주입한 뒤 답변을 생성하는 패턴. SeMu-GPT 2026의 핵심 — 14개 ES 인덱스에서 hybrid 검색 → 필터/정렬 → LLM이 인용 근거를 포함해 SSE 스트리밍. → 아키텍처 개요, 리포트 생성

HyDE (Hypothetical Document Embeddings)

질문을 직접 임베딩하지 않고 LLM으로 "가상 답변"을 먼저 생성한 뒤 그 가상 답변을 임베딩하여 검색하는 기법. application.yml:64rag.hyde.enabled로 토글 (HydeService). Langfuse 프롬프트 hyde-generator 사용. → 리포트 생성, 임베딩

RRF (Reciprocal Rank Fusion)

BM25 텍스트 검색 결과와 kNN 벡터 검색 결과를 융합하는 ES 8.x retriever.rrf API. rank_constant, window_size로 융합 방식 제어. Law 인덱스에는 SemugptLawElasticRepository.findSimilarLawListWithRRF()로 구현되어 있고 타 인덱스는 application layer에서 결과를 합친다. → Elasticsearch

kNN

벡터 공간에서 k개의 최근접 이웃을 찾는 검색. content_vector (3072 dims, cosine) 필드에 적용. num_candidates=k*2가 통상 파라미터. → Elasticsearch, 임베딩

BM25

ES 기본 텍스트 랭킹 알고리즘. SeMu-GPT는 보통 multi_matchtitle^2, content, _all_text 필드를 묶어 점수 계산. → Elasticsearch

BM25 + kNN을 함께 수행하고 RRF 또는 application-side fusion으로 합치는 패턴. StreamingRagProcessor가 14개 인덱스에 대해 수행한다. → Elasticsearch, 리포트 생성

IntentRouter

사용자 질문의 intent(TAX_QUESTION / REFERENCE_SWITCH / DEPTH_CONTROL / GREETING / OFF_TOPIC)를 분류하고 검색 인덱스 라우팅 + 질문 재작성 + 카테고리 추론을 처리. intent-router.unified.enabled=true면 단일 LLM 호출, 실패 시 Phase 0(3회 분리) fallback. → 리포트 생성

MANDATORY_INDICES

IntentRouter 라우팅 결과에 LLM이 무엇을 선택했든 항상 추가되는 핵심 인덱스 4개 (LAW, PRECEDENT, COUNSEL, GLOSSARY). → 리포트 생성

Query Rewrite

멀티턴 후속 질문을 self-contained 질문으로 재작성하는 단계 (예: "그거 예외는?" → "양도소득세 비과세 예외는?"). Langfuse 프롬프트 query-rewrite 또는 unified IntentRouter가 처리. ConversationTurn.rewrittenQuestion에 저장. → 리포트 생성

Citation Tag

LLM 답변 끝에 부착되는 <citations>id1,id2,...</citations> 태그. 실제 인용 문서 ID 목록을 담으며 parseCitedIds + stripCitationTag 단계에서 추출·제거된다. 누락 시 필터링이 비활성화되어 회귀 위험. → 리포트 생성

Reorder by Citations

LLM이 인용한 문서를 답변 언급 순서로 최상위에 재배치하고, 미인용 문서는 기존 RRF 순서를 유지하는 reorderByCitations() 함수. → 리포트 생성, 시스템 다이어그램

Threeway 보충

검색된 법 조문의 article_key로 tax-threeway 인덱스를 조회해 법-시행령-시행규칙 세트를 자동 보충하는 단계 (supplementThreewayReferences). findBatchById로 1회 ES 호출. → 리포트 생성

답변 기반 보충

답변 텍스트에서 extractLawReferences() regex로 "법인세법 제40조", "같은 법 시행령 제71조" 등을 추출해 누락 조문을 ES에서 가져오는 단계 (supplementReferences, 최대 3건). → 리포트 생성

4-tier 정렬

법령을 [세법 → 카테고리 대표법 → 주변법] + [법 → 시행령 → 시행규칙] + 조문번호 4단계 키로 정렬하는 알고리즘. LawClassificationConfig.getLawSortTier(). → 리포트 생성

MAX_TOTAL_LAWS

4-tier 정렬 후 유지되는 법령 최대 개수. StreamingConversationService.MAX_TOTAL_LAWS = 8 (Issue #129). → 리포트 생성

SSE_TIMEOUT

스트리밍 응답의 emitter 타임아웃. StreamingConversationController.SSE_TIMEOUT = 180_000L (3분, hardcoded). ALB idle_timeout 300s보다 짧아 backend가 먼저 close. → 리포트 생성

Archive Eligibility

대화 세션이 공개 게시판("AI 지식게시판")에 노출될 자격이 있는지 나타내는 boolean 플래그(ConversationSession.isArchiveEligible, nullable). recomputeArchiveEligibleWith(turn) 호출 시 newTurnValid && (기존 turns 모두 valid) 식으로 계산되며, 한 턴이라도 invalid면 false (Issue #148 Option A). → 카테고리 / 게시판

isValidForArchive

턴 단위 적격 판정 메서드. (1) refs 비어있음 (2) 답변이 검색된 참고 자료 / 죄송로 시작 (3) 세무와 관련된 포함 — 하나라도 해당하면 invalid. → 카테고리 / 게시판

Keyword Extraction

적격 세션의 valid 턴들로부터 LLM이 핵심 키워드 5개를 추출해 ConversationSession.keywords(comma-separated)에 저장하는 작업. KeywordExtractionEvent@TransactionalEventListener(AFTER_COMMIT) @Async로 응답 latency 영향 없이 처리. Langfuse 프롬프트 keyword-extraction (Issue #148). → 카테고리 / 게시판, 리포트 생성

Token Quota

사용자가 멤버십 기간 동안 소비할 수 있는 LLM 토큰 한도. tokenUsageService.validateTokenQuota(accountId)가 사전 검증하고 초과 시 TokenQuotaExceededException을 SSE error로 전달 후 emitter close. ADMIN role은 검증 우회. → 리포트 생성, 멤버십 · 구독

Token Pack

사용자가 추가로 구매하는 단발성 토큰 패키지(ProductType.TOKEN_PACK). TokenPack.ofPayment(payment)로 발급되며 expiresAt = purchasedAt + 90일. → 결제 (Toss V2)

TokenUsageLog

계정별 토큰 사용량을 주기 단위로 집계하는 테이블. Membership.currentCycleStart() 기점으로 >= 경계 SUM. → 멤버십 · 구독


데이터 파이프라인

BaseCollector

모든 수집기의 추상 기반 클래스(packages/data-pipeline/.../collectors/base.py). requests.Session 초기화(브라우저 UA, 쿠키 수집, SSL 우회), 점진 백오프 재시도(max_retries=3), save_json/save_csv/save_ndjson 유틸을 제공. → 수집기 (Collectors)

Collector

외부 사이트(법제처 / 국세상담센터 / 조세심판원 등) 14곳을 크롤링하여 JSONL/JSON으로 저장하는 Python 모듈. 정적 HTML은 requests, JavaScript 렌더링은 Selenium(webdriver-manager). → 수집기 (Collectors)

Indexer

수집된 JSONL/JSON을 읽어 ES 인덱스에 bulk 적재하는 Python 모듈. 각 인덱서는 INDEX_NAME 상수 + parse_*_file() 제너레이터 + create_index() 매핑 + bulk_index() 4-stage 구조. → 인덱서 (Indexers)

create_es_client

모든 인덱서가 사용해야 하는 공통 ES 클라이언트 팩토리(utils/elasticsearch.py). 우선순위: URL 임베드된 credential → explicit args → ES_USERNAME/ES_PASSWORD(또는 SEMUGPT_ES_USERNAME/SEMUGPT_ES_PASSWORD) env var. Elasticsearch(es_url) 직접 사용 금지. → 인덱서 (Indexers), CLI 레퍼런스

JSONL

JSON Lines 포맷 (라인당 하나의 JSON 객체). Collector의 증분 저장 단위 — save_every=50 같은 간격으로 fsync. 중단 후 재개 가능하게 만드는 핵심 포맷. → 수집기 (Collectors)

Progress 파일

.progress_{source}.json. items_collected, current_page, last_saved_at을 담아 재실행 시 이어쓰기 가능하게 만드는 collector 상태 파일. → 수집기 (Collectors)

OpenAIEmbedder

Python 측 임베딩 생성 클래스(embeddings/openai_embedder.py). SHA256(text.strip()) 키로 SQLite 캐시 hit 확인 → miss만 OpenAI 호출 → put_many로 캐시 저장. text-embedding-3-large, 3072 dims. → 임베딩, 인덱서 (Indexers)

EmbeddingCache

SQLite WAL 모드 기반 임베딩 캐시(embeddings/cache.py). 바이너리 BLOB 저장. 이전 JSON 캐시(9.2 GB 폭증, 손상 문제)를 대체. 기본 경로 data/embedding_cache.db. → 임베딩

EmbeddingUtil

Backend Kotlin 측 임베딩 헬퍼(apps/backend/.../application/service/EmbeddingUtil.kt). ModelId("text-embedding-3-large")로 query 임베딩 생성. config 외부화 안 된 채 코드 hardcode. → 임베딩, 아키텍처 개요

text-embedding-3-large

OpenAI 임베딩 모델. 3072 dims. 인덱서(Python)와 백엔드(EmbeddingUtil) 양쪽이 동일 모델을 써야 cosine 유사도가 의미를 갖는다. 모델 변경 시 ES 매핑의 dims도 함께 수정 필요. → 임베딩

MAX_TOKENS (Embedding)

임베딩 입력 토큰 한도. MAX_TOKENS = 8000 (openai_embedder.py:18). 모델 한도 8191에서 마진을 둔 값. 초과 시 tiktoken으로 자동 절단 + warning 로그. → 임베딩

_all_text

다수의 텍스트 필드를 copy_to: "_all_text"로 복사해 통합 검색용 단일 필드로 만드는 ES 매핑 컨벤션. 모든 인덱스 공통. → Elasticsearch, 인덱서 (Indexers)

content_vector

각 ES 문서의 임베딩 벡터를 저장하는 dense_vector 필드 (3072 dims, cosine). kNN 검색의 대상. --embed 미지정 시 null이 저장되어 kNN 작동 불가. → Elasticsearch, 인덱서 (Indexers)

Nori

ES analysis-nori 플러그인의 한국어 형태소 분석기. nori_tokenizer (decompound_mode: "mixed") + lowercase + nori_readingform 필터를 묶어 korean_text 분석기로 사용. 모든 인덱스 공통. → Elasticsearch

nori_readingform

한자를 한글로 변환하는 nori 필터. 빠지면 한자 검색이 깨진다 — 운영 중 교체 시 다운타임 위험. → Elasticsearch

semugpt-collect / semugpt-index / semugpt-process

packages/data-pipeline이 제공하는 3개의 typer CLI entry point. uv run 또는 패키지 설치 후 직접 실행. semugpt-upload는 stub(cli/upload.py 미존재). → CLI 레퍼런스

--embed

semugpt-index bulk의 옵션. OpenAI 임베딩 생성 포함(비용 발생). 끄면 content_vector가 null로 저장되어 kNN 검색 미작동. → CLI 레퍼런스

--convert

Collector의 옵션 — JSONL을 인덱서 호환 JSON({collected_at, count, items[]})으로 변환. → 수집기 (Collectors)

oc (law.go.kr)

법제처 공동활용 API의 인증 식별자. Settings.law_api_oc 기본값 "onbiztax". 공동활용 신청 키라 보안 영향은 작지만 env var 우선 권장. → 수집기 (Collectors)

RelationIndexer

tax-relations 인덱스에 ID 매핑만 적재하는 인덱서. content/임베딩 없음. 백엔드 미사용 — 3단 비교는 tax-threeway로 대체됨. → 인덱서 (Indexers)

Backfill Vectors

기존 ES 문서에 누락된 content_vector를 채우는 스크립트 packages/data-pipeline/scripts/backfill_vectors.py. → 임베딩


백엔드 아키텍처

Controller / Service / Domain / Outbound

백엔드의 4-layer 명명 컨벤션. Controller가 HTTP endpoint, Service가 비즈니스 로직, Domain(Entity)이 상태 + 규칙 메서드, Outbound가 외부 시스템 호출(SMS/PG/...). → 회원 / 인증 등 모든 feature 페이지

StreamingConversationController / StreamingConversationService

대화 SSE 엔드포인트와 그 오케스트레이션 서비스. /conversations/**. 쿼터 사전 검증, SseEmitter 라이프사이클, citation 재정렬, threeway/answer 기반 보충을 담당. → 리포트 생성

StreamingRagProcessor

인덱스 라우팅 + ES hybrid search + 필터링/정렬 + LLM 스트리밍 호출을 묶는 RAG 코어. → 리포트 생성, Elasticsearch

ConversationSession / ConversationTurn

신규 채팅 도메인의 두 엔티티. 세션은 카테고리 · title · isActive(soft delete) · isArchiveEligible · keywords를 보유하고, 턴은 세션 안에서 순번(turn_number)으로 누적되는 Q&A 한 쌍 + refs. → 리포트 생성, 카테고리 / 게시판

TurnReferenceData

턴별 RAG 참고자료 매핑 (conversation_turn_reference_data 테이블, dataId + DataType). 답변 본문에 인용된 문서들이 cascade ALL로 함께 persist. → 리포트 생성

Report (legacy)

구버전 리포트 엔티티 (apps/backend/.../application/domain/gpt/Report.kt). 신규 흐름은 ConversationSession/ConversationTurn으로 대체됨 — admin /admin/reports/list 조회와 ReportCleaner cron 외에는 신규 코드 작성 안 함. schema cleanup 후보. → 리포트 생성, 관리자 콘솔

ReportProcess

legacy Report.currentProcess enum. REQUESTED / REFER_LAW / REFER_EXAM / REFER_COUNSEL / COMPLETE / VALIDATION_FAIL. → 관리자 콘솔

Account

사용자 계정 도메인. phone, name, role(GUEST/USER/ADMIN), account_status(ACTIVATED/DEACTIVATED/WITHDRAWAL)를 보유. 멤버십 시작/종료 결정 로직 (findCurrentMembership, addMembership, initMembershipBy***)을 담는다. → 회원 / 인증, 멤버십 · 구독

AccountRole / AccountStatus

계정 권한 / 상태 enum. Role = GUEST / USER / ADMIN. Status = ACTIVATED / DEACTIVATED / WITHDRAWAL. Admin이 /admin/accounts/{id}/role · /admin/accounts/{id}/status로 변경. → 관리자 콘솔, 회원 / 인증

PhoneAuthentication

폰 번호 인증 세션 엔티티. 6자리 코드, 만료 305초, 일별 발급 횟수(issueCount), verify() / issue() / verifyAndCreateAccount() / verifyAndChangeAccount() 메서드. → 회원 / 인증

RefreshTokenBlacklist

사용된 refresh token을 차단하는 테이블. AuthService.reissueToken()이 RT 사용 시 등록 → 재사용 시 AlreadyUsedRefreshTokenException. → 회원 / 인증

MembershipPlanProperties

YML(membership.plans.*)에서 플랜별 가격 · 월 토큰 한도 · 기간을 로드하는 ConfigurationProperties 클래스. getMonthlyTokenLimit()이 null이면 무제한. → 멤버십 · 구독, 쿠폰

SubscriptionRenewalScheduler

매일 09:00 KST(@Scheduled(cron = "0 0 9 * * ?")) 만료 멤버십을 자동 갱신하는 스케줄러. 결제 실패 시 isSubscriptionPaused=true + PaymentMethod.deactivate(). → 멤버십 · 구독

BillingService

정기결제 charge 서비스. 빌링키로 Toss /v1/billing/{billingKey} 호출 → 새 Membership 발급. applyBillingAuthorization() · cancelSubscription() · chargeBillingInternal(). → 결제 (Toss V2), 멤버십 · 구독

ReportCleaner

매일 01:00 cron(@Scheduled(cron = "0 0 1 * * ?"))으로 isClientCanceled=true인 legacy Report를 일괄 삭제하는 클리너. → 리포트 생성

ElasticsearchAuditLog

어드민이 ES 문서를 CRUD할 때 남기는 감사 로그 엔티티. before_data / after_data JSON(≤ 64KB, vector 제외), actionType (CREATE/UPDATE/DELETE), truncated 플래그. → 관리자 콘솔

AuditActionType

ES 감사 로그의 작업 종류 enum. CREATE / UPDATE / DELETE. → 관리자 콘솔

TurnFeedback

사용자 피드백 도메인. rating 1-5, reason nullable. 어드민 화면(/admin/feedbacks)에서 통계 조회. → 관리자 콘솔

LangfusePromptService

Langfuse 프롬프트를 5분 TTL로 캐시하여 getPromptWithConfig()(text, model, temperature, maxTokens)를 반환하는 서비스. 캐시 TTL은 langfuse.prompt.cache-ttl-seconds로 조정. → 모니터링

AsyncConfig

@Async 메서드용 ThreadPoolTaskExecutor 설정 클래스. KeywordExtractionListener · ConversationMemoryIndexingService가 사용. 과거 SimpleAsyncTaskExecutor로 burst 위험이 있었으나 bounded 풀로 교체됨. → 리포트 생성, 카테고리 / 게시판

Spring @Value Binding (relaxed binding)

yml의 hardcoded 값을 동명의 환경변수로 override할 수 있게 해주는 Spring 기능. application-prod.yml의 평문 값도 SPRING_DATASOURCE_PASSWORD 등 env var로 override 가능. → 시크릿 관리


프론트엔드 · 채팅

Next.js 16 App Router

프론트엔드의 라우팅/렌더링 베이스. React 19.2, Tailwind 3.4, Zustand 5. 빌드 모드는 webpack(pnpm build, next.config.js가 CommonJS이므로). → 아키텍처 개요

@opennextjs/cloudflare

Next.js 빌드를 Cloudflare Workers + KV로 변환하는 어댑터. pnpm build:cfpnpm deploy:cf로 dev frontend 배포. → 개발 환경

SSE (Server-Sent Events)

RAG 응답을 점진적으로 토큰 단위로 스트리밍하는 HTTP 방식. SeMu-GPT의 /conversations/stream/conversations/{id}/turns/stream이 사용. 이벤트 종류: metadata / chunk / category_selection / citation_update / complete / error. → 리포트 생성, 시스템 다이어그램

chunk 인코딩

SSE 청크 전송 시 공백을 %20으로 치환하여 trim 방지 → 프론트가 디코드. StreamingConversationController.sendEvent(). → 리포트 생성

category_selection 이벤트

사용자가 카테고리 미선택 + LLM 추론 점수 충분 시 발행되는 SSE 이벤트. 세션 미생성 상태로 후보(top 3 + "해당 없음")를 보내고 사용자 재선택 대기. → 카테고리 / 게시판

citation_update 이벤트

답변 본문이 끝난 뒤 threeway + 답변 기반 보충 + reorder 결과를 프론트에 전달하는 SSE 이벤트. referenceIds + referenceDetails + lowRelevanceTypes. → 리포트 생성

Dev 자동 로그인

NODE_ENV=development일 때 userContext.tsx의 하드코딩된 JWT로 자동 로그인하는 dev tooling. 테스트 계정 display name은 "테스트관리자" (LoginModal.tsx:238), accountId 04aff73d-3eac-41f5-862c-9aa0fd12acc4, ADMIN 권한. → 개발 환경

AI 지식게시판

적격(isArchiveEligible=true) 세션을 비로그인 사용자에게 노출하는 공개 게시판. GET /conversations/public, GET /conversations/public/{sessionId}. editable=false로 표시. → 카테고리 / 게시판


결제 · 멤버십 · 쿠폰

MembershipType

멤버십 티어 enum. FREE / STANDARD / PREMIUM. 모든 티어 appliedDays=30. (참고: TOKEN_PACK은 enum에 없음 — 쿠폰의 productType=TOKEN_PACKMembership.byCoupon을 거치면 런타임 깨짐). → 멤버십 · 구독, 쿠폰

ProductType

결제·쿠폰에서 사용하는 상품 분류. STANDARD / PREMIUM / TOKEN_PACK. → 결제 (Toss V2), 쿠폰

PaymentStatus

결제 상태 enum. 신규: PENDING / DONE / WAITING_DEPOSIT / FAILED. legacy(PortOne 시절, 10개): PRE_VERIFICATION / POST_VERIFICATION / ADDITIONAL_VERIFICATION / ADDITIONAL_VERIFICATION_FAIL / REGISTERED / SCHEDULED / CONFIRMED / VERIFICATION_FAIL / WITHDRAWAL / PAYMENT_FAIL. → 결제 (Toss V2), 관리자 콘솔

PaymentType

결제 수단 분류 enum. CARD / BANK / VIRTUAL_ACCOUNT / TRANSFER / EASY_PAY. → 결제 (Toss V2)

PaymentMethod

사용자의 결제수단 엔티티. billingKey + customerKey + card_name(한글) + card_number(마스킹) + status (ON_STANDBY / ACTIVATED / DEACTIVATED / DELETED). → 결제 (Toss V2)

billingKey / customerKey

Toss 정기결제 식별자 쌍. billingKey는 Toss가 발급하고 customerKey는 클라이언트가 생성. 정기 charge 시 POST /v1/billing/{billingKey}로 호출. → 결제 (Toss V2)

tossOrderId

Toss orderId로 보낼 SeMu-GPT 측 식별자. 1회성은 ORDER_${paymentId}, 정기는 BILLING_${UUID}. → 결제 (Toss V2)

Webhook 멱등

Toss V2가 webhook signature를 제공하지 않으므로, 페이로드의 paymentKey로 Toss API를 재조회(GET /v1/payments/{paymentKey})하여 authoritative source로 검증하는 패턴. 이미 DONE이면 skip. → 결제 (Toss V2)

Coupon

결제 없이 멤버십을 발급하는 단일 사용 토큰. PK = UUID.replace("-","").substring(0,5).uppercase() 5자리. UNUSED / USED 상태. 영구 유효(만료일 없음). → 쿠폰

CouponStatus

쿠폰 상태 enum. UNUSED / USED. → 쿠폰

CouponUseResponse

사용자 쿠폰 등록 결과 enum. OK / USED / INVALID — HTTP status는 모두 200, 클라이언트가 body 파싱해 분기. → 쿠폰

initFreeMembership

신규 가입 시 호출되어 FREE 멤버십을 자동 부여하는 Account 메서드. 계정엔 항상 최소 1개의 membership 레코드가 있어야 한다는 invariant 유지. → 멤버십 · 구독

Subscription Pause

자동 갱신 실패 시 Membership.isSubscriptionPaused = true로 일시정지하는 상태. PaymentMethod도 함께 deactivate. grace period 없음. → 멤버십 · 구독

Subscription Withdrawal

사용자가 구독을 취소하는 행위. Membership.withdrawal() 호출 시 isSubscriptionWithdrawal=true — 현재 주기는 endDate까지 유지, 자동 갱신 대상에서 제외. 회원탈퇴(Account.withdrawal())는 현재 멤버십이 FREE일 때만 허용. → 멤버십 · 구독

currentCycleStart

멤버십 토큰 사용 주기의 시작 시점을 반환하는 Membership.currentCycleStart(). startDate 기점 30일 반복. TokenUsageLog 집계 시 >= 경계. → 멤버십 · 구독

카드사 심사 백도어

폰번호 01099999999 입력 시 코드를 항상 999999로 반환하고 SMS 미발송하는 백도어 (AuthService.issuePhoneAuthentication()). PG사 심사용 — TODO 주석으로 표시되어 심사 통과 후 제거 예정. → 회원 / 인증, 알려진 이슈


인증 · 보안

JWT (JSON Web Token)

인증 토큰 형식. SeMu-GPT는 access token(TokenType.ACCESS = 30분) + refresh token(TokenType.REFRESH = 7일) 쌍을 사용. 서명 키는 application-*.ymljwt.secret (환경변수 JWT_SECRET로 override). → 회원 / 인증, 시크릿 관리

TokenProvider / TokenParser

JWT 발급(TokenProvider) / 파싱(TokenParser) Spring Security 컴포넌트. → 회원 / 인증, 시스템 다이어그램

CORS allowed origins

백엔드가 허용하는 출처 목록. SecurityConfig.kt:200-207에서 정의 — localhost:* 와일드카드 + *.bootalk.co.kr 와일드카드 + semugpt.co.kr, www.semugpt.co.kr, new.semugpt.co.kr (#151 4.5f). 환경변수 CORS_ALLOWED_ORIGINS로 override 가능. → 회원 / 인증, 시크릿 관리

SecurityConfig

Spring Security 설정. /admin/**hasAuthority("ADMIN")으로 게이트(:113), CORS allowed origins, 인증 필터 체인 정의. → 관리자 콘솔, 회원 / 인증

@Identifier accountId

컨트롤러 메서드 파라미터에서 인증된 사용자 ID를 자동 추출하는 커스텀 annotation. JWT access token에서 파싱된 accountId가 주입된다. → 리포트 생성

OAuth2 (미사용)

OAuth2Account, OAuth2Provider 등 도메인 코드는 존재하지만 활성 라우트가 없는 상태. application-oauth.yml에 Naver / Kakao / Google client secret이 평문 커밋되어 있다(미사용이라 즉시 위험 낮음). → 회원 / 인증, 시크릿 관리


인프라 · 운영

Lightsail

AWS의 simple cloud VM 서비스. SeMu-GPT 2026의 dev backend(semugpt-backend, medium_3_0 4GB)와 prod backend(semugpt-prod, large_3_0 8GB, 진행 중)가 사용. → 개발 환경, 운영 배포

ALB (Application Load Balancer)

AWS L7 로드밸런서. Prod의 semu-gpt-alb가 HTTPS:443에서 host header rule로 legacy(api/pro)와 신규(api-new/new)를 분기. idle_timeout=300s. → 운영 배포

Target Group (TG)

ALB가 트래픽을 보낼 인스턴스 묶음. legacy semu-gpt-instance(HTTP:80, EC2), 신규 TG-backend-2026(:8080, priority 100), TG-frontend-2026(:3000, priority 110). → 운영 배포, 시스템 다이어그램

Route 53

AWS 관리형 DNS. hosted zone semugpt.co.kr. (zone ID Z0917222THSORQW5ECCW). Cloudflare가 아님 — 이 때문에 Cloudflare Workers Custom Domain과 Cloudflare Tunnel을 prod 도메인에 적용 불가. → 운영 배포, 아키텍처 개요

RDS (Relational Database Service)

AWS 관리형 MySQL. SeMu-GPT prod = tax-gpt (MySQL 8.0.44, db.t3.micro, 20 GB allocated → autoscale 1000 GB). 엔드포인트 tax-gpt.cl2zydns6yrm.ap-northeast-2.rds.amazonaws.com. ⚠️ PubliclyAccessible=true, SG sg-09b20a06663fcfa010.0.0.0/0:3306 인터넷 노출 (보안 우려). → 운영 배포, 시크릿 관리

RDS Database

한 RDS instance 안의 논리적 DB. SeMu-GPT의 tax-gpt instance엔 4개 DB가 존재 — tax_gpt(legacy live), tax_gpt_v2 / tax-gpt-v3(미사용), semugpt_2026(신규, 부분 migration 완료). → 운영 배포

ACM (AWS Certificate Manager)

AWS TLS 인증서. SeMu-GPT는 두 개 보유 — ap-northeast-2의 *.semugpt.co.kr(wildcard only, apex 미포함, 만료 2026-08-13, ALB용)과 us-east-1의 semugpt.co.kr + *.semugpt.co.kr(만료 2026-08-07, CloudFront용). → 운영 배포

ARN (Amazon Resource Name)

AWS 리소스 고유 식별자. 예: arn:aws:elasticloadbalancing:ap-northeast-2:023888247019:targetgroup/semu-gpt-instance/c290ed2d2bcca56a. → 운영 배포

CloudFront

AWS CDN. legacy frontend가 사용 — apex용 EQH9FKLG1LISZ → S3 semugpt.co.kr, www용 EMX0TAZMBZFP1 → S3 semugpt-hosting. Hard cutover 후 disable 예정 (무기한 연기). → 운영 배포

ECR (Elastic Container Registry)

AWS 컨테이너 이미지 레지스트리. 023888247019.dkr.ecr.ap-northeast-2.amazonaws.com/semugpt-backend — 2026-04-22 생성됐으나 신규 plan에서 미사용 (Docker image push 없이 systemd로 직접 운영). → 운영 배포

VPC Peering

서로 다른 VPC(SeMu-GPT의 Lightsail VPC 172.26.0.0/16 ↔ default VPC 172.31.0.0/16)를 private IP로 연결하는 AWS 기능. pcx-0449043e7e8170851 active. ALB target type ip172.16.0.0/12 CIDR을 peering 경유로 지원. → 운영 배포

Cloudflare Workers

서버리스 엣지 컴퓨팅 플랫폼. SeMu-GPT dev frontend(semugpt-frontend-dev)가 호스팅되는 곳. @opennextjs/cloudflare로 빌드 → wrangler deploy. URL: semu-chat-dev.bootalk.co.kr. → 개발 환경

Cloudflare Tunnel

공개 도메인을 사설 호스트(Lightsail)에 안전하게 라우팅하는 Cloudflare 기능. Tunnel ID 078d8083-eba8-4df2-8026-ebafcb53666b (semugpt-backend)가 semu-gpt-dev.bootalk.co.kr을 Lightsail localhost:8080에 연결. Prod는 사용 불가 (Route 53 유지 결정). → 개발 환경, 시크릿 관리

cloudflared

Cloudflare Tunnel의 호스트 측 데몬. Lightsail에 systemd 서비스로 설치(/etc/cloudflared/config.yml, cert /etc/cloudflared/cert.pem). → 개발 환경

KV (Cloudflare)

Cloudflare Workers의 key-value 스토어. Next.js 정적 자산 보관용. → 시스템 다이어그램

ob 프로파일

SeMu-GPT 인프라 작업에 사용하는 AWS CLI SSO 프로파일. account 023888247019 (alias "onbiztax"). 토큰 만료 1-12시간 → aws sso login --profile ob로 갱신. → 시크릿 관리, 개발 환경

ssh semugpt-aws / ssh semugpt-prod

Lightsail box 접속용 SSH alias. dev = semugpt-aws (key ~/.ssh/aws-semugpt, 허용 IP 49.175.194.2/32 사무실만). prod = semugpt-prod (예정, 같은 키 재사용). → 개발 환경

systemd (semugpt-backend / semugpt-frontend / cloudflared)

Lightsail box의 서비스 매니저. semugpt-backend(Restart=on-failure, RestartSec=30s) / semugpt-frontend(prod 예정) / cloudflared가 등록되어 있고 부팅 시 자동 시작. → 개발 환경, 복구 절차

quiet-logs.conf (systemd drop-in)

/etc/systemd/system/semugpt-backend.service.d/quiet-logs.conf. p6spy SQL 로그 spam을 영구 fix하기 위한 환경변수 override (LOGGING_LEVEL_P6SPY=WARN, LOGGING_LEVEL_ORG_HIBERNATE_SQL=WARN). Lightsail에만 적용 — 로컬 Mac은 SQL DEBUG 그대로. → 개발 환경

disk-alarm / health-monitor

Lightsail에 설치된 2개의 cron 알림 스크립트. /usr/local/bin/disk-alarm.sh(매시, root fs ≥ 80% 감지) + /usr/local/bin/health-monitor.sh(5분마다 actuator/health UP↔DOWN 전환 감지). 상태 전환 시에만 Slack에 webhook 전송. → 모니터링

Flyway (미사용)

DB 스키마 마이그레이션 도구. SeMu-GPT는 사용하지 않음infra/sql/*.sql 파일을 운영자가 수동 적용. ddl-auto: none (prod). → 운영 배포, 알려진 이슈

Hikari Pool

Spring Boot의 JDBC connection pool. application-prod.yml에서 maximum-pool-size: 10으로 설정(RDS max_connections=60 대비 보수적). → 운영 배포

actuator/health

Spring Boot의 헬스 체크 엔드포인트. UP/DOWN 상태 + Hikari/ES/Redis 등 sub-status 반환. health-monitor cron이 5분마다 호출. → 복구 절차, 모니터링

Soft Launch

레거시 인프라(semugpt.co.kr apex/www/api/pro)를 그대로 두고 신규 스택을 서브도메인(new.semugpt.co.kr + api-new.semugpt.co.kr)에 병행 운영하며 사용자가 nav 버튼으로 opt-in 시험하는 방식. Hard cutover는 무기한 연기. → 운영 배포

Hard Cutover

레거시 인프라를 신규 스택으로 완전 전환 + legacy decommission하는 작업. Issue #151의 Phase 12이며 무기한 연기. 시점에 사용자 데이터 추가 migration, 시크릿 회전, RDS SG 잠금 등이 일괄 진행될 예정. → 운영 배포

dev-local.sh

./scripts/dev-local.sh — 백엔드(8080) + 프론트엔드(3010)를 동시에 띄우는 로컬 dev 스크립트. docker-compose.dev.yml의 MySQL / ES / Redis가 떠 있는 것을 전제. → 개발 환경

docker-compose.dev.yml

dev 인프라 컨테이너 정의 — MySQL 8 / Elasticsearch 8.17 + analysis-nori / Redis 7. Lightsail에는 ES_JAVA_OPTS=-Xms1g -Xmx1g 등 git에 커밋 안 된 로컬 수정이 있음(4 GB 박스 적응). → 개발 환경

medium_3_0 / large_3_0

Lightsail bundle 코드. dev backend는 medium_3_0 (4 GB / 2 vCPU / 80 GB SSD, $24/mo), prod backend 예정은 large_3_0 (8 GB / 2 vCPU / 160 GB SSD / 5 TB BW, $44/mo). → 개발 환경, 운영 배포

Static IP (Lightsail)

Lightsail 인스턴스에 부여하는 고정 공인 IP. dev backend는 3.39.17.132, legacy EC2는 3.39.210.101. attach 중에는 무료. → 개발 환경, 운영 배포


외부 서비스

OpenAI

LLM 호출 + 임베딩 생성 외부 서비스. SeMu-GPT는 gpt-5.4 / gpt-5.2 / gpt-5.4-nano(Langfuse config 기반) + text-embedding-3-large를 사용. 백엔드 키는 yml openai.token (env override OPENAI_TOKEN). → 아키텍처 개요, 시크릿 관리

Langfuse

LLM 프롬프트 버저닝 + config(model/temperature/maxTokens) 관리 외부 SaaS. SeMu-GPT의 7개 LLM 호출(rag-final-answer, rag-final-answer-multiturn, rag-document-filter, hyde-generator, intent-router, query-rewrite, tax-category-inference, keyword-extraction)이 모두 trace + config fetch로 의존. → 아키텍처 개요, 모니터링

Toss Payments

결제 PG. SeMu-GPT는 V2 API (https://api.tosspayments.com) 사용 (PortOne V1 → Toss V2 마이그레이션, Issue #109). 1회성 결제 confirm + 정기결제(billingKey 기반) + 가상계좌 webhook 처리. → 결제 (Toss V2)

Toss Widget

브라우저 측 결제 SDK. tossPayments.requestPayment()로 결제창 띄움 → success redirect 후 백엔드 /accounts/payments/confirm 호출 패턴. → 결제 (Toss V2), 시스템 다이어그램

네이버 클라우드의 SMS 발송 SaaS. 휴대폰 인증 코드 발송에 사용. 실 구현체는 SensMessageSender (@Component 활성). Service ID ncp:sms:kr:315481964654:semu-gpt, calling number 028302220. → 회원 / 인증, 시크릿 관리

SnsMessageSender (비활성)

apps/backend/.../application/service/message/의 SMS 구현체 클래스. //@Component 주석으로 비활성 — 실제 사용은 SensMessageSender. ⚠️ AWS SNS와 혼동 주의 (이름은 비슷하지만 다른 시스템). → 회원 / 인증, 알려진 이슈

AWS SNS (Simple Notification Service)

AWS의 pub/sub 알림 서비스. application-prod.yml:26-28 + application-local.yml:24-26aws.sns.enabled=true 설정이 있으나 Naver SENS와는 별개의 시스템. 과거 위키에서 SMS 구현체를 AWS SNS로 잘못 인용한 사례가 있어 주의. → 시크릿 관리, 알려진 이슈

Sentry

프론트엔드 런타임 에러 모니터링 SaaS. @sentry/nextjs v10, org bootalk, project semugpt. withSentryConfig(nextConfig, ...)로 wrap. 백엔드 Sentry는 미설치 (모니터링 갭). → 모니터링

NCP (Naver Cloud Platform)

네이버 클라우드의 줄임말. SENS 등이 여기에 속함. IAM access key / secret key는 ncp.access-key / ncp.secret-key yml 키에 들어감. → 시크릿 관리

Slack incoming webhook

Slack 채널에 메시지를 보내는 일방향 URL. Lightsail box /etc/semugpt/slack-webhook.url (mode 0600, git 미커밋). disk-alarm / health-monitor cron이 사용. → 모니터링, 시크릿 관리

GitHub Actions (deploy-frontend-dev.yml)

dev frontend 자동 배포 워크플로. develop 브랜치 push + apps/frontend/** paths 변경 시 pnpm build:cf → Cloudflare Workers deploy. → 개발 환경, 시스템 다이어그램

uitiorg/semugpt-2026

SeMu-GPT 2026의 GitHub 리포지토리. Issue/PR 트래킹에 사용 (#151 cutover, #148 keyword extraction, #109 Toss V2 등). → 운영 배포


약어 표

알파벳순으로 정렬. 도메인 약어는 본 페이지 위쪽 카테고리에 상세 정의.

약어 풀이 비고
ACM AWS Certificate Manager TLS 인증서
ALB Application Load Balancer AWS L7 LB
API Application Programming Interface
App Router Next.js App Router Next.js 13+ 라우팅 모델
ARN Amazon Resource Name AWS 리소스 식별자
BM25 Best Match 25 텍스트 랭킹 알고리즘
CDN Content Delivery Network
CIDR Classless Inter-Domain Routing IP 주소 블록 표기
CLI Command Line Interface
CORS Cross-Origin Resource Sharing
CRUD Create / Read / Update / Delete
DNS Domain Name System
DSL Domain-Specific Language ES query DSL
EC2 Elastic Compute Cloud AWS VM
ECR Elastic Container Registry AWS 컨테이너 레지스트리
ES Elasticsearch
FE / BE Frontend / Backend
HA High Availability
HTTP / HTTPS Hypertext Transfer Protocol (Secure)
HyDE Hypothetical Document Embeddings RAG 기법
IA Information Architecture 위키 페이지 구성
IAM Identity and Access Management AWS 권한
JPA Java Persistence API Spring 데이터 액세스
JSON JavaScript Object Notation
JSONL JSON Lines 라인당 1 JSON 객체
JVM Java Virtual Machine
JWT JSON Web Token
kNN k-Nearest Neighbors 벡터 검색
KST Korea Standard Time UTC+9
KV Key-Value Cloudflare Workers 스토어
LB Load Balancer
LLM Large Language Model
MCP Model Context Protocol Anthropic의 도구/리소스 통신 표준
NCP Naver Cloud Platform
OAD OpenAPI Documentation neoteroi.mkdocsoad 임베드
OAuth Open Authorization 위임 인증
OG Open Graph SEO 메타 태그
OLTP Online Transaction Processing MySQL 용도
OOM Out Of Memory
PG Payment Gateway Toss 등
PITR Point-In-Time Recovery RDS 백업
PK / FK Primary Key / Foreign Key RDB
PR Pull Request
PROD Production 운영 환경
QPS Queries Per Second
RAG Retrieval-Augmented Generation
RDB Relational Database
RDS Relational Database Service AWS 관리형 DB
REST Representational State Transfer API 패턴
RRF Reciprocal Rank Fusion hybrid 검색 융합
RT Refresh Token
S3 Simple Storage Service AWS 객체 스토리지
SaaS Software as a Service
SDK Software Development Kit
SENS Simple & Easy Notification Service Naver Cloud SMS — ⚠️ AWS SNS와 다름
SEO Search Engine Optimization
SG Security Group AWS 방화벽
SNS Simple Notification Service AWS의 pub/sub — ⚠️ Naver SENS와 별개
SOP Standard Operating Procedure
SPA Single-Page Application
SPOF Single Point Of Failure
SQL Structured Query Language
SSE Server-Sent Events 스트리밍
SSH Secure Shell
SSL / TLS Secure Sockets Layer / Transport Layer Security
SSO Single Sign-On AWS SSO 로그인
TG Target Group ALB 백엔드 그룹
TLS Transport Layer Security
TTL Time To Live 캐시 만료 시간
UA User Agent HTTP 헤더
UI User Interface
URL Uniform Resource Locator
UUID Universally Unique Identifier
VPC Virtual Private Cloud AWS 네트워크 격리
WAL Write-Ahead Logging SQLite 모드
YAML / YML YAML Ain't Markup Language 설정 포맷

관련 문서