Skip to content

WIR (Week In Review) 26년 7월 3주차 ​


다중화 LB 환경에서 인증서 누락된 LB 찾아내는 기법 ​

OS 전체 DNS 설정을 건드리지 않고 Terminal에서 특정 IP로 콕 집어서 요청을 보내는 방법이 있습니다. 가장 깔끔하고 추천하는 방법은 curl 명령어의 --resolve 옵션을 사용하는 것입니다.

방법 1. curl --resolve (가장 추천) ​

도메인 주소를 입력하지만, DNS를 거치지 않고 지정한 IP로 강제 매핑하여 요청을 보냅니다. SSL/TLS 증명서 검증(SNI)과 HTTP Host 헤더까지 모두 정석대로 동작합니다.

# 아래명령어일때
nslookup hello.world.io

10.184.23.222 IP로 HTTPS(443) 테스트 ​

curl -v https://hello.world.io --resolve hello.world.io:443:10.0.1.1

10.184.23.180 IP로 HTTP(80) 테스트 ​

curl -v http://hello.world.io--resolve hello.world.io:80:10.0.1.2

• -v 옵션을 붙여두면 아래처럼 커넥션 성공 여부와 어떤 IP로 접속했는지 디버깅 정보가 다 보입니다.

  • Added hello.world.io:443:10.x.x.x to DNS cache

인터뷰 및 도서 발췌 미국에 보내는 러브레터 컨텐츠 감상 ​

토마스 슈만 이라는 작가가 쓴 Love Letter to America (미국에 보내는 러브레터) 컨텐츠를 읽어봤다. 이 책을 보면 "The Four Stages of Subversion(전복의 4단계)"라는 도표와 함께 기술된 내용이 있는데 아래 4단계에 걸쳐 작가가 주장하는 내용, 즉 서방 세계를 향해 경고했던 '이념 전복(Ideological Subversion)' 전략의 핵심 4단계를 간단히 소개하면

Demoralization : 15~20년 소요 ​

  • "It takes from 15 to 20 years to demoralize a nation. Why that many years? Because this is the minimum number of years required to educate one generation of students in the country of your enemy exposed to the ideology of the enemy."

  • "Exposure to true information does not matter anymore. A person who was demoralized is unable to assess true information. The facts tell nothing to him."

Destabilization : 2~5년 소요 ​

  • "It takes 2 to 5 years to destabilize a nation. What matters is essentials: economy, foreign relations, defense systems."

Crisis : 최대 6주 ​

  • "It may take only up to 6 weeks to bring a country to the verge of crisis. You can see it in Central America now."

Normalization : 무기한 ​

  • "And after crisis, with a violent change of power, structure, and economy, you have so-called the period of normalization. It may last indefinitely."
  • "Normalization is a cynical expression borrowed from Soviet propaganda. When the Soviet tanks moved into Czechoslovakia in 1968, Comrade Brezhnev said, 'Now the situation in brotherly Czechoslovakia is normalized.'"

AI 하이브리드 검색시스템 구축 계획/구상 ​

WebSocket 통신은 Network 탭에 안 보인다 ​

키워드: WebSocket, NiceGUI, socket.io 간단설명: 검색해도 통신이 없어 보였던 건 데이터가 안 오간 게 아니라, 처음 맺어둔 하나의 WebSocket 연결 안에서 메시지로만 오가기 때문. 일반 XHR/Fetch 요청이 새로 안 생겨서 안 보였을 뿐, 실제론 서버가 다 처리 중이었음.

벡터화 ⊃ 임베딩 (포함 관계) ​

키워드: 벡터화, 임베딩, 의미 좌표 간단설명: 벡터화는 "글자를 숫자 배열로" 바꾸는 넓은 개념. 임베딩은 그중 의미까지 좌표에 담는 똑똑한 벡터화. 뜻이 비슷하면 좌표도 가깝게 놓임. one-hot 같은 단순 벡터화는 의미 관계를 못 담음.

pgvector는 임베딩을 하지 않는다 ​

키워드: pgvector, 벡터 저장·검색, 텍스트→벡터 분리 간단설명: PostgreSQL(pgvector)은 "이미 만들어진 벡터"의 거리 계산만 함. 텍스트를 벡터로 바꾸는 임베딩은 밖(Spring Boot 등)에서 하고 결과 벡터만 넘겨야 함. 그래서 임베딩 모델 없이는 넣을 벡터도, 텍스트 검색도 불가능.

임베딩 모델은 따로 확보해야 한다 (2가지 방식) ​

키워드: 임베딩 모델, API vs 로컬, 차원 일치 간단설명: (A) API(VoyageAI·OpenAI)로 빌려 쓰기 — 키만 필요, 모델은 상대 서버에 있음. (B) HuggingFace 모델 다운받아 로컬 실행 — Java는 DJL/ONNX 필요. 색인 모델 = 검색 모델이어야 하고, 모델의 차원(예 1024)이 pgvector 컬럼 차원과 정확히 일치해야 함.

임베딩은 CPU에서도 된다 (GPU는 속도 문제) ​

키워드: 행렬 곱, CPU vs GPU, 규모 간단설명: 임베딩은 대량의 행렬 곱셈이라 병렬에 강한 GPU가 수십~수백 배 빠를 뿐, CPU에서도 가능. 소량·작은 모델은 CPU로 충분. 대량 색인·고트래픽·큰 모델일 때 GPU(또는 API)가 필요.

Chroma는 임베딩 모델을 자동으로 숨겨줬던 것 ​

키워드: ChromaDB, all-MiniLM-L6-v2, 자동 임베딩 간단설명: 예전에 "DB만으로 유사도 검색"됐던 건 Chroma가 기본 임베딩 모델(MiniLM)을 자동 다운로드해 CPU에서 돌려줬기 때문. 임베딩은 항상 있었고 Chroma가 감춰준 것뿐. pgvector는 이 편의 기능이 없어 직접 임베딩해야 함.

키워드 검색은 임베딩보다 FTS + 하이브리드가 더 중요할듯 ​

키워드: 키워드 추출, FTS(GIN), 하이브리드 검색 간단설명: 키워드만 낱개로 임베딩하면 문맥이 사라져 품질 저하. 정확한 키워드 매칭은 FTS(전문검색)가 적합. 실무에선 FTS(키워드) + 벡터(의미)를 합친 하이브리드 검색을 씀.

임베딩 모델 “성능”의 의미 ​

키워드: MTEB, 다운스트림 태스크, 상대적 지표 • “성능 좋다”는 절대적 개념이 아니라 검색/분류/클러스터링 등 특정 태스크 기준 평가 • MTEB(Massive Text Embedding Benchmark)가 업계 표준 리더보드 • 도메인·언어에 따라 순위가 뒤집힐 수 있어 범용 1위 ≠ 내 용도 최적

1024차원으로 자연어/키워드 임베딩벡터 변환 방법 ​

키워드: sentence-transformers, bge-large, dimensions 파라미터 • OpenAI API는 dimensions 파라미터로 차원 축소 가능 • bge-large, bge-m3(다국어) 등은 기본값이 1024차원이라 별도 축소 불필요 • 억지로 차원 맞추려 PCA/랜덤 프로젝션 하기보다 애초에 맞는 모델 선택이 낫다

(임베딩모델) sentence-transformers의 VM 서빙 한계 ​

키워드: CPU 서빙, GIL, TEI • CPU만으로도 동작하지만 처리량은 낮고 Python GIL 때문에 진짜 병렬처리 불가 • 모델이 프로세스당 1~2GB 상주, gunicorn 멀티워커 시 메모리 배수로 증가 • 고트래픽이면 Hugging Face의 Rust 기반 서버 TEI(Text Embeddings Inference)가 대안

배치 큐잉으로 처리량 최적화 ​

키워드: 배칭, asyncio.Queue, 레이턴시-처리량 트레이드오프 • 요청을 즉시 처리 안 하고 짧은 시간(MAX_WAIT_MS) 모아 한 번에 encode하면 처리량 급증 • 레이턴시 예산(예: 300ms) 중 일부만 대기시간으로 쓰고 나머지는 실제 encode에 배분 • 동기 함수인 model.encode()는 run_in_executor로 스레드풀에 위임해야 이벤트 루프 안 막힘

3계층 아키텍처 분리 ​

키워드: Controller-Service-Engine, 관심사 분리 • Controller는 HTTP만, Service는 호출 순서(오케스트레이션)만, Engine은 실제 모델 실행만 담당 • Engine 내부도 EmbeddingEngine(모델 실행)과 BatchScheduler(배칭 전략)로 세분화 가능 • 이렇게 나누면 모델 교체/배칭 전략 변경/캐싱 추가가 서로 침범하지 않음

하이브리드 검색시스템 구축방안 ​

1단계: 하이브리드 검색 (backend, Postgres)
- 전체 DB에서 정답이 될 가능성이 있는 후보군 선발 : 검색키워드 입력받아 > FTS,pgvector 각 100개 언더로 뽑기 (총200개)
  - 키워드 검색 (FTS): 고유명사, 품번, 정확한 단어 매칭 (tsvector 인덱스 활용 상위 100개)
  - 의미 검색 (pgvector): 동의어, 문맥, 사용자 의도 매칭 (HNSW 인덱스 활용 상위 100개)

2단계: RRF 순위 합산(backend 연산), 총 50개
- 키워드 50개 + 의미 50개 중복 제거 및 등수 기반 RRF 점수 계산하여 상위 50개 후보추출

3단계: VoyageAI Rerank API 정렬 
- 50개 후보 텍스트를 VoyageAI Rerank API로 전송 (Cross-Encoder)해서 거르기
- 최종 상위 20개 품질 순 정렬 후 응답

피드백시스템
- search_log : 검색 버튼을 누르고 결과가 반환될 때 적재, 검색 트렌드 분석, 결과가 0건인 검색어(Zero Result Query) 발굴, 향후 클릭률(CTR) 계산의 기준 분모
- click_log : 사용자가 검색 결과 카드나 항목을 클릭하는 순간 저장, GA4 적용되어있는데 필요성은 고민

4단계: 비즈니스 스코어링
- 단순 관련성을 넘어 서비스 유용성을 반영한 최종 노출 순위 결정
- 점수 보정: 최종 점수 = (Reranker 점수) × (최신성 가중치) × (인기/클릭 수 가중치)
- 결과 반환: 최종 상위 5~10개 결과를 클라이언트에 응답

영어공부 (Writing) ​

# 전화영어 튜터 프롬프트

아래 전체를 복사해서 새 대화 첫 메시지로 붙여넣으면 됩니다.

---

You are my English phone-call tutor. We will have a casual spoken-style conversation, like a phone English lesson.

## Rules during the conversation

- Start by suggesting ONE random conversation topic (different every session — daily life, work, travel, news, hypotheticals, etc.) and ask me an opening question.
- Talk like a real phone call: short, natural, spoken English. 1–3 sentences per turn, then ask a follow-up question to keep me talking.
- Do NOT correct my English during the conversation. No grammar notes, no rephrasing, no teaching. Just respond naturally, even if I make mistakes.
- Silently keep track of my mistakes and awkward expressions for the final feedback.
- Match your difficulty slightly above my level so I learn naturally.

## Ending the conversation

When I say "끝" or "wrap up", stop the conversation and give me feedback **in Korean** in this exact format:

### 📞 오늘의 대화 피드백

**1. 교정 (Corrections)**
내가 틀리게 말한 문장들. 각 항목:
- ❌ 내가 한 말 → ⭕ 자연스러운 표현 (왜 어색한지 한 줄 설명)

**2. 어휘 업그레이드 (Word Upgrades)**
내가 쓴 단어 중 어색하거나 더 좋은 단어가 있는 경우:
- 내가 쓴 단어 → 추천 단어/표현 (뉘앙스 차이 설명 + 예문 1개)

**3. 오늘의 키워드 (New Vocabulary)**
오늘 주제에서 내가 몰랐을 법한, 알면 좋은 단어·표현 5개:
- 단어/표현 — 뜻, 예문 1개

**4. 총평**
잘한 점 1~2개 + 다음에 집중할 것 1개 (2~3문장, 격려 위주)

If I made very few mistakes, say so honestly — don't invent errors. Now start by greeting me and suggesting today's topic.