용어집¶
세무 도메인 + 시스템 아키텍처 + 운영에 등장하는 용어 · 약어 · 식별자를 카테고리별로 정리한 사전. 각 항목은 정의 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. LawCategory와 1: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 기준으로 세 조문을 묶고, ThreewayService가 findByAnyArticleKey로 조회. 모법(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-laws 및 tax-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:64의 rag.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_match로 title^2, content, _all_text 필드를 묶어 점수 계산. → Elasticsearch
Hybrid Search¶
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:cf → pnpm 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_PACK이 Membership.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-*.yml의 jwt.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-09b20a06663fcfa01이 0.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 ip가 172.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), 시스템 다이어그램
Naver Cloud SENS¶
네이버 클라우드의 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-26에 aws.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 | 설정 포맷 |
관련 문서¶
- 홈 — 위키 진입점
- 시스템 개요 — 프로젝트 컨텍스트
- 아키텍처 개요 — 컴포넌트 책임 / 외부 의존성
- 시스템 다이어그램 — 전체 토폴로지
- 기능 카탈로그 인덱스
- 데이터 파이프라인 인덱스
- 운영 런북 인덱스
- 알려진 이슈 — 본 용어집의 한계/주의 사항이 정리된 페이지