# Awesome Life - Full Contents for AI Ingestion > This document contains the full text of the 15 most recent articles from Awesome Life for efficient ingestion by AI search engines and agents. --- ## [나디르 위성영상 캡셔닝을 위한 오픈웨이트 멀티모달 모델 비교](https://butteryoon.github.io/dev/2026/07/17/nadir_captioning_models.html) - **Published Date**: 2026-07-17 - **Author**: James Yoon - **Tags**: llm, multimodal, VLM, remote sensing, captioning, open weight - **Description**: 수직(나디르) 시점 위성영상 캡셔닝에 쓸 수 있는 오픈웨이트 VLM들 — 범용 모델과 원격탐사 특화 모델 비교 ### Content:

나디르(nadir, 수직 하방) 시점 위성영상에 텍스트 캡션을 자동으로 붙이는 작업에 어떤 오픈웨이트 멀티모달 모델을 쓸 수 있는지 조사한 내용을 정리한다. 지난 글에서 MLLM과 임베딩 모델의 역할 차이를 다뤘다면, 이번에는 캡셔닝(MLLM 쪽)에 초점을 맞춘다.

TL;DR: 범용 오픈웨이트 VLM(Qwen3-VL, InternVL3, Gemma 3 등)은 그대로 쓰면 위성영상 도메인 갭 때문에 캡션 품질이 떨어진다. 소규모로 시작한다면 원격탐사 특화 모델(RS-LLaVA, GeoChat, SkyEyeGPT)을 먼저 평가하고, 자체 데이터가 있다면 범용 최신 모델에 LoRA 파인튜닝하는 것이 현재 가장 실용적인 선택이다.

나디르 위성영상 캡셔닝은 무엇이 어려운가?

일반 사진과 달리 나디르 시점 영상에는 범용 VLM이 학습한 데이터와의 도메인 갭이 존재한다.

어떤 오픈웨이트 모델을 쓸 수 있나?

범용 오픈웨이트 VLM (2026년 기준)

모델 규모 라이선스 특징
Qwen3-VL 다양한 크기 Apache 2.0 Qwen 시리즈 최신, 멀티모달 추론·긴 컨텍스트 강화
Qwen2.5-VL-72B 72B Qwen MMMU ~70%, OCR 강점, 오픈웨이트 최상위권
InternVL3-78B 78B MIT MIT 라이선스 중 최강급 (MMMU ~72%)
Gemma 3 4B~27B Gemma 128K 컨텍스트, 가벼운 배포
Pixtral 12B 12B Apache 2.0 12B급에서 강력
Phi-4-Multimodal ~5B MIT 소형 클래스 최강, 엣지 배포 후보

벤치마크(MMMU, OCRBench 등) 기준으로는 상용 모델과 경쟁하는 수준이지만, 이 점수는 일반 도메인 기준이라 위성영상에 그대로 이어지지 않는다는 점을 유의해야 한다.

원격탐사 특화 모델

모델 베이스 특징
RS-LLaVA LLaVA + LoRA RS-instructions 데이터셋으로 캡셔닝·VQA 공동 학습
GeoChat LLaVA-1.5 + LoRA 영역 지정 질의와 공간 좌표 그라운딩 지원
SkyEyeGPT 자체 구조 8개 RS 데이터셋에서 이미지/영역 캡셔닝 검증, RS 비디오 캡셔닝 지원

셋 다 LLaVA 계열의 검증된 레시피(시각 인코더 + 어댑터 + LLM, LoRA 파인튜닝)를 원격탐사 데이터(RSICD 등)에 적용한 것이라, 나디르 영상 캡션의 도메인 어휘(토지 피복, 시설물 유형)를 범용 모델보다 잘 구사한다. 단점은 베이스 LLM이 최신 모델 대비 한 세대 뒤라는 점이다.

어떻게 선택해야 하나?

  1. 빠른 검증이 목표 → RS-LLaVA/GeoChat을 그대로 돌려 자체 영상에서 캡션 품질을 먼저 확인한다. 특화 모델이 기대에 못 미치면 그 격차가 파인튜닝 필요성의 근거가 된다.
  2. 자체 캡션 데이터가 있다 → 최신 범용 모델(Qwen3-VL, InternVL3 등)에 LoRA 파인튜닝하는 편이 특화 모델의 구식 베이스를 쓰는 것보다 상한선이 높다. GeoChat·RS-LLaVA가 이미 같은 방식(LoRA)으로 효과를 입증했다.
  3. 라이선스 제약이 있다 → 상용 활용이라면 MIT(InternVL3, Phi-4)나 Apache 2.0(Qwen3-VL, Pixtral) 라이선스를 우선 검토한다.
  4. 대량 처리 파이프라인 → 캡셔닝 전에 임베딩 모델로 필터링해서 MLLM 호출량을 줄이는 하이브리드 구성을 권장한다.

평가는 어떻게 하나?

원격탐사 캡셔닝의 표준 벤치마크로 RSICD, UCM-Captions, Sydney-Captions 등이 쓰이고, 지표는 BLEU/METEOR/CIDEr가 일반적이다. 다만 자동 지표는 도메인 어휘의 정확성(시설물 오인식 등)을 잘 잡지 못하므로, 실제 도입 시에는 자체 영상 표본에 대한 전문가 검수를 병행하는 것이 안전하다.

참고

--- ## [블로그를 AI 검색 시대에 맞게 손보기](https://butteryoon.github.io/tools/2026/07/16/blog_seo_llm.html) - **Published Date**: 2026-07-16 - **Author**: James Yoon - **Tags**: jekyll, seo, llms.txt, json-ld, mermaid, claude code - **Description**: mermaid 렌더링, 썸네일 정비, llms.txt와 JSON-LD 적용까지 — 블로그 개선 작업 기록 ### Content:

지난 이틀간의 대청소(블로그 정리)에 이어, 오늘은 블로그를 Google과 AI 검색 엔진이 잘 읽어갈 수 있는 구조로 손봤다. 작업은 Claude Code와 Gemini 에이전트를 함께 활용했다.

TL;DR: mermaid 다이어그램 렌더러를 테마에 추가하고, 발행 글 19건의 썸네일을 주제에 맞는 이미지로 교체했으며, llms.txt·JSON-LD 구조화 데이터·robots.txt AI 크롤러 허용까지 적용해 LLM 검색 친화적인 블로그로 만들었다.

mermaid 다이어그램 렌더링 지원

멀티 에이전트 구조를 다룬 Caller/Executor 패턴 글을 쓰면서 mermaid 플로우차트를 넣었는데, 이 테마에는 mermaid 렌더러가 없어 코드 블록으로만 표시됐다.

확인해보니 테마의 _includes/javascripts.html이 어느 레이아웃에도 include되어 있지 않았고, 참조하던 assets/js/main.js도 존재하지 않는 테마 잔재였다. 이 파일을 mermaid 로더로 교체하고 default 레이아웃에 include했다. mermaid 블록이 있는 페이지에서만 CDN에서 라이브러리를 로드하므로 다른 페이지에는 부담이 없다.

<script type="module">
  const blocks = document.querySelectorAll('pre code.language-mermaid, code.language-mermaid');
  if (blocks.length > 0) {
    const mermaid = (await import('https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs')).default;
    blocks.forEach(code => {
      const pre = code.closest('pre') || code;
      const div = document.createElement('div');
      div.className = 'mermaid';
      div.textContent = code.textContent;
      pre.replaceWith(div);
    });
    mermaid.initialize({ startOnLoad: false, theme: 'default' });
    await mermaid.run();
  }
</script>

썸네일 정비

발행 글 전체의 썸네일을 인벤토리해보니 범용 플레이스홀더(image-title.jpg)를 쓰거나 아예 이미지가 없는 글이 19건이었다. 3건은 기존 주제별 이미지를 재사용하고, 나머지는 Unsplash에서 주제에 맞는 무료 이미지(키보드, 분석 대시보드, 암호화폐, 서버랙 등) 12종을 받아 교체했다. Unsplash 라이선스는 출처 표기 없이 상업적 사용이 가능하다.

llms.txt와 JSON-LD — AI 검색 최적화

AI 검색 엔진(ChatGPT Search, Perplexity, Gemini 등)이 사이트를 잘 인용하도록 세 가지를 적용했다.

llms.txt / llms-full.txt

llms.txt는 LLM이 HTML을 긁지 않고도 사이트 구조를 파악할 수 있게 도메인 루트에 두는 커뮤니티 표준 파일이다. Jekyll Liquid 템플릿으로 만들어 빌드할 때마다 자동 갱신되게 했다.

---
layout: null
permalink: /llms.txt
---
# {{ site.title }}
## Recent Articles
{% for post in site.posts limit:40 %}
- [{{ post.title }}]({{ site.url }}{{ post.url }}): {{ post.description }}
{% endfor %}

JSON-LD 구조화 데이터

head.html에 글 페이지는 BlogPosting, 그 외는 WebSite 스키마의 JSON-LD를 주입했다. dateModified가 front matter의 last_modified_at과 연동되므로, 글을 수정하고 이 값을 갱신하면 검색엔진에 “살아있는 콘텐츠”라는 신호를 준다.

robots.txt에 AI 크롤러 명시 허용

GPTBot, ChatGPT-User, ClaudeBot, Claude-Web, Google-Extended, PerplexityBot을 명시적으로 허용했다.

검증

배포 후 실제 서빙 상태를 확인했다.

❯ curl -s -o /dev/null -w "%{http_code}" https://butteryoon.github.io/llms.txt
200

앞으로의 글쓰기 가이드

AI 검색에 인용되기 좋은 글을 위한 권장사항도 정리해뒀다. 이 글부터 적용해본다.

  1. Answer-First: 글 시작에 TL;DR 블록으로 핵심 답을 먼저 제시
  2. 질문형 헤더: “SCP 전송 명령” 대신 “SCP로 파일을 어떻게 전송하나요?”처럼 사용자가 물어볼 법한 형태로
  3. 정보 밀도 유지: 실제 명령어, 설정 파일, 에러 출력 같은 구체적 데이터가 LLM 인용에 유리
  4. last_modified_at 갱신: 글을 수정할 때마다 반드시 갱신

참고

--- ## [위성 영상 처리: 멀티모달 LLM vs 이미지 임베딩 모델](https://butteryoon.github.io/dev/2026/07/16/satellite_mllm_vs_embedding.html) - **Published Date**: 2026-07-16 - **Author**: James Yoon - **Tags**: llm, multimodal, embedding, CLIP, remote sensing, satellite - **Description**: 위성 영상 도메인에서 멀티모달 LLM과 CLIP 계열 임베딩 모델의 차이와 하이브리드 활용법 ### Content:

위성 영상(Remote Sensing) 도메인에서 텍스트 디스크립션을 만들고 특징을 추출하는 방법을 조사하면서, 멀티모달 LLM이미지 임베딩 모델(RemoteCLIP, GeoRSCLIP 등)의 차이를 정리해봤다. 두 접근은 목적과 작동 방식, 성능 특성이 뚜렷하게 다르다.

두 접근의 정의

멀티모달 LLM (MLLM)

이미지(위성 영상)와 텍스트 입력을 결합해 시각적 추론을 수행하고, 최종적으로 자연어 문장을 생성하는 거대 모델이다.

이미지 임베딩 모델 (CLIP 계열)

대조 학습(Contrastive Learning)으로 위성 영상과 텍스트를 같은 벡터 공간에 매핑해 특징을 추출하는 모델이다.

핵심 차이점

비교 항목 멀티모달 LLM 임베딩 모델 (RemoteCLIP 등)
출력 형태 자연어 텍스트 고정 차원 벡터 (512, 768차원 등)
자연어 생성 가능 (맥락 해석 후 새 문장 생성) 불가능 (텍스트 후보와 유사도 비교만)
주요 태스크 VQA, 종합 분석·요약 제로샷 분류, 유사 이미지 검색
연산량 수십억~수백억 파라미터, 무거움 수억 개 이하, 추론 속도 빠름
데이터 활용 고수준 맥락 추론·묘사 대규모 DB 인덱싱·고속 검색

작동 원리

MLLM은 시각 인코더로 영상의 시각 토큰을 뽑고, 어댑터(Projection Layer)를 거쳐 LLM의 텍스트 임베딩 공간으로 투영한 뒤, 프롬프트와 함께 자기회귀(Autoregressive) 방식으로 한 토큰씩 문장을 생성한다.

결과물 예시: “해당 위성 이미지는 전형적인 도심 주거 지역으로, 적색 지붕의 단독 주택들이 격자형 도로망을 따라 조밀하게 밀집해 있습니다.”

CLIP 계열은 이미지 인코더와 텍스트 인코더의 투 타워(Two-tower) 구조다. 영상과 텍스트를 각각 벡터로 바꾸고, 학습 시 두 벡터의 코사인 유사도를 극대화하도록 정렬한다.

결과물 예시: 영상 입력 시 [0.12, -0.45, 0.89, ...] 같은 벡터를 반환하고, 이 벡터는 “항구 시설”이라는 텍스트 벡터와 가장 가까운 거리에 놓인다.

장단점

멀티모달 LLM

이미지 임베딩 모델

결론: 하이브리드로 쓰자

두 모델은 상호 배타적이지 않고, 실제 시스템에서는 보완적으로 조합하는 것이 이상적이다.

  1. 대규모 필터링 단계 (임베딩 모델): RemoteCLIP/GeoRSCLIP으로 수천 장의 위성 이미지에서 관심 영역(활주로, 항만, 주거 구역 등)을 제로샷 분류·검색으로 고속 필터링
  2. 세부 보고서 생성 단계 (MLLM): 필터링된 타깃 이미지만 MLLM에 전달해 미세 변화 감지와 종합 분석 디스크립션을 자동 작성

임베딩 모델이 넓게 거르고 MLLM이 깊게 읽는 구조라, 비용과 속도, 품질의 균형을 맞출 수 있다.

참고

--- ## [Caller/Executor 패턴으로 멀티 에이전트 구성하기](https://butteryoon.github.io/dev/2026/07/16/caller_executor_agent.html) - **Published Date**: 2026-07-16 - **Author**: James Yoon - **Tags**: llm, ai agent, mcp, foundry, langgraph, multi-agent - **Description**: Foundry Toolbox와 MCP를 이용한 Caller-Executor 멀티 에이전트 구조 정리 ### Content:

멀티 에이전트 시스템을 만들면서 정리한 Caller/Executor 패턴 구조를 기록해둔다. 사용자 요청을 받는 에이전트(Caller)와 실제 작업을 수행하는 전문 에이전트(Executor)를 분리하고, 둘 사이를 MCP(Model Context Protocol)로 연결하는 구성이다.

구조 개요

역할은 둘로 나뉜다.

핵심은 Caller가 Executor를 직접 HTTP로 호출하지 않는다는 점이다. Executor는 Foundry Toolbox를 통해 하나의 tool로 노출되고, Caller의 LLM이 질문을 보고 그 tool을 쓸지 말지 판단한다.

Caller 초기화 흐름

Caller 진입점(main())에서 하는 일은 크게 세 가지다: tool 로드 → 에이전트 생성 → 서버 실행.

순서 함수/객체 역할
1 main() 진입점
2 _load_toolbox_tools() Toolbox에서 tool 로드
3 DefaultAzureCredential() Azure 인증 객체 생성
4 get_bearer_token_provider() 토큰 공급자 생성
5 _ToolboxAuth 매 요청마다 최신 Bearer 토큰 주입
6 MultiServerMCPClient(...) Toolbox MCP 연결
7 client.get_tools() tool 목록 가져오기
8 _build_chat_model() Azure AI Foundry LLM 모델 객체 생성
9 create_agent(...) LangGraph 에이전트 생성
10 ResponsesHostServer(graph).run(...) 서버 실행

인증 처리가 눈여겨볼 부분인데, 토큰이 만료될 수 있으므로 고정 토큰을 쓰지 않고 _ToolboxAuth 같은 인증 객체가 매 요청마다 최신 Bearer 토큰을 받아 주입하는 구조로 만든다.

런타임 요청 처리 흐름

사용자가 질문을 보내면 다음 순서로 동작한다.

  1. 요청이 서버(ResponsesHostServer)에 들어옴
  2. 에이전트(graph)가 요청을 처리
  3. LLM이 질문을 보고 tool 사용 여부를 판단
  4. 필요하면 전문 에이전트 tool(예: math_expert)을 선택
  5. tool 호출이 Toolbox/MCP 경로를 통해 Executor로 전달
  6. Executor가 답변을 생성해 반환
  7. Caller가 결과를 정리해 최종 답변을 사용자에게 반환
flowchart TD
    A[사용자 요청] --> B[ResponsesHostServer]
    B --> C[LangGraph Agent]
    C --> D[LLM 모델]
    C --> E[Tool 목록]
    E --> F[math_expert tool]
    F --> G[Toolbox MCP Endpoint]
    G --> H[Executor Agent]
    H --> I[전문 답변 결과]
    I --> F
    F --> C
    C --> J[최종 응답]
    J --> K[사용자에게 반환]

이 구조의 장점

핵심 정리

참고

--- ## [OpenRouter 무료 모델을 API로 사용하기](https://butteryoon.github.io/tools/2026/07/15/openrouter_free.html) - **Published Date**: 2026-07-15 - **Author**: James Yoon - **Tags**: llm, openrouter, api, free - **Description**: OpenRouter의 프리(:free) 모델을 API로 호출하는 방법과 사용 가능한 모델 목록 ### Content:

온프레미스 서비스로 오픈웨이트 모델을 사용하려 할 때 GPU 인프라가 충분하지 않으면 여러가지 모델을 하기 어렵다. 이렇게 LLM 모델별 API로 테스트해보고 싶은데 비용이 부담될 때 OpenRouter의 무료 모델을 쓸 수 있다. 여러 프로바이더의 모델을 하나의 OpenAI 호환 API로 호출할 수 있고, 모델 ID에 :free가 붙은 모델은 과금 없이 사용할 수 있다.

OpenRouter란

OpenRouter는 OpenAI, Anthropic, Google, Meta 등 여러 프로바이더의 모델을 하나의 API 엔드포인트로 중계해주는 서비스다. OpenAI SDK와 호환되기 때문에 base URL과 API 키만 바꾸면 기존 코드를 그대로 쓸 수 있다.

API 키 발급

  1. openrouter.ai 가입
  2. 우측 상단 프로필 > Keys 메뉴에서 Create Key
  3. 발급된 sk-or-v1-... 키를 환경변수로 저장
# PowerShell
[System.Environment]::SetEnvironmentVariable("OPENROUTER_API_KEY", "<발급받은 키>", "User")
# bash
export OPENROUTER_API_KEY="<발급받은 키>"

무료 모델 찾기

모델 목록 페이지에서 가격 필터를 FREE로 설정하면 무료 모델만 볼 수 있다. 아래처럼 API로도 확인할 수 있는데, 모델 ID가 :free로 끝나는 것들이다.

curl -s https://openrouter.ai/api/v1/models | \
  jq -r '.data[].id | select(endswith(":free"))'

이 글을 쓰는 시점(2026-07-15) 기준으로 사용할 수 있는 무료 모델은 20개다. Llama 3.3 70B, Qwen3 Coder 480B, NVIDIA Nemotron 3 Ultra 550B 같은 대형 모델도 무료로 테스트할 수 있다.

OpenRouter Free Models

API 호출

API의 모델명에 “openrouter/free”로 적으면 프리 모델중에 인풋에 알맞는 모델을 선택해서 응답을 해준다. ( 어떤 모델이 선택됐는지 알 수는 없다 )

curl

curl https://openrouter.ai/api/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $OPENROUTER_API_KEY" \
  -d '{
    "model": "meta-llama/llama-3.3-70b-instruct:free",
    "messages": [
      {"role": "user", "content": "안녕하세요. 자기소개 해주세요."}
    ]
  }'

Python (OpenAI SDK)

from openai import OpenAI

client = OpenAI(
    base_url="https://openrouter.ai/api/v1",
    api_key=os.environ["OPENROUTER_API_KEY"],
)

resp = client.chat.completions.create(
    model="qwen/qwen3-coder:free",
    messages=[{"role": "user", "content": "파이썬으로 퀵정렬 구현해줘"}],
)
print(resp.choices[0].message.content)

무료 모델 사용 한도

무료 모델에는 요청 횟수 제한이 있다 (2026년 7월 기준).

구분 분당 요청 일일 요청
기본 20회 50회
크레딧 $10 이상 구매 이력 20회 1,000회

$10만 한 번 충전해두면 하루 1,000회까지 늘어나므로, 본격적으로 테스트할 계획이라면 최소 크레딧을 넣어두는 것이 편하다. 무료 모델은 프로바이더 사정에 따라 목록이 자주 바뀌고, 입력한 데이터가 학습에 사용될 수 있다는 점도 유의해야 한다.

마무리

VSCode AI TOOLS 플러그인에 커스텀 모델로 오픈라우터 프리모델을 등록하고 플레이그라운에서 여러모델을 비교하며 가장 적합한 모델을 찾을 수 있다.

참고

--- ## [PowerShell 프로파일 기본 설정](https://butteryoon.github.io/tools/2026/07/15/powershell_profile.html) - **Published Date**: 2026-07-15 - **Author**: James Yoon - **Tags**: PowerShell, profile, oh-my-posh, alias, Windows Terminal - **Description**: 내가 쓰는 PowerShell 프로파일 기준으로 정리한 기본 설정 방법 ### Content:

새 PC를 세팅할 때마다 PowerShell 프로파일을 다시 만들게 되는데, 지금 쓰고 있는 프로파일을 기준으로 기본 설정 방법을 정리해둔다.

프로파일 파일 위치

PowerShell 7(pwsh) 기준으로 프로파일 경로는 $PROFILE 변수로 확인할 수 있다.

 $PROFILE
C:\Users\<사용자>\Documents\PowerShell\Microsoft.PowerShell_profile.ps1

파일이 없으면 만들어주고, 편집기로 연다.

if (-not (Test-Path $PROFILE)) { New-Item -ItemType File -Path $PROFILE -Force }
nvim $PROFILE   # 또는 notepad $PROFILE

프로파일은 PowerShell이 시작될 때마다 실행되는 스크립트라서, 여기에 프롬프트 테마·별칭·함수를 넣어두면 매 세션에서 바로 쓸 수 있다.

프롬프트 테마: oh-my-posh

oh-my-posh로 프롬프트를 꾸민다. winget으로 설치하고 프로파일에 초기화 한 줄만 넣으면 된다.

winget install JanDeDobbeleer.OhMyPosh
# $PROFILE
oh-my-posh init pwsh | Invoke-Expression

테마를 지정하고 싶으면 --config에 테마 파일을 넘긴다. 아이콘이 깨지면 Nerd Font를 설치하고 터미널 글꼴로 지정해야 한다.

oh-my-posh init pwsh --config "$env:POSH_THEMES_PATH\atomic.omp.json" | Invoke-Expression

명령어 추천: PowerToys Command Not Found

PowerToys의 Command Not Found 기능을 켜면, 없는 명령어를 입력했을 때 winget으로 설치할 수 있는 패키지를 추천해준다. PowerToys 설정에서 활성화하면 프로파일에 아래 블록이 자동으로 추가된다.

Import-Module -Name Microsoft.WinGet.CommandNotFound

기본 별칭 정리

PowerShell은 curl, cat 같은 유닉스 명령어를 자체 cmdlet의 별칭으로 잡아놔서, 진짜 curl이나 bat 같은 도구를 쓰려면 기본 별칭을 먼저 지워야 한다.

# 기본 별칭 제거
if ( Test-Path Alias:curl ) { Remove-Item Alias:curl }
if ( Test-Path Alias:cat )  { Remove-Item Alias:cat }

# 새 별칭
Set-Alias vi nvim
Set-Alias cat bat
Set-Alias magick -Value "C:\Program Files\ImageMagick-7.1.1-Q16-HDRI\magick.exe"

디렉토리 이동 함수

자주 가는 디렉토리는 함수로 만들어두면 편하다.

Function cwork { Set-Location "C:\work\workspace\" }
Function cdesk { Set-Location "$env:USERPROFILE\Desktop" }
Function cdocs { Set-Location "$env:USERPROFILE\Documents" }

환경변수 등록

API 키 같은 환경변수도 프로파일에서 등록할 수 있다. "User" 스코프로 지정하면 사용자 환경변수로 저장된다.

[System.Environment]::SetEnvironmentVariable("MY_API_KEY", "<발급받은 키>", "User")

프로파일을 dotfiles 저장소 등에 공개할 계획이 있다면 키 값을 프로파일에 직접 적지 말고 별도 파일로 분리하는 것이 안전하다.

유틸리티 함수

리눅스 습관대로 쓰거나 자주 확인하는 정보는 함수로 정리해뒀다.

Function ver { Write-Output $PSVersionTable }                  # 버전 확인
Function export { Get-ChildItem -Path Env:\ }                  # 환경변수 목록
Function Get-IPinfo { ipconfig | Select-String IPv4 }          # 내부 IP
Function Get-MyIPinfo { curl "http://api.ipify.org?format=json" }  # 공인 IP
Function uptime { Get-WmiObject -Class Win32_OperatingSystem |
  Select-Object @{n='LastBoot';e={$_.ConvertToDateTime($_.LastBootUpTime)}} }
Function Get-Title { Get-Process | Where-Object {$_.mainWindowTitle} |
  Format-Table Id, Name, mainWindowTitle -AutoSize }           # 창 있는 프로세스
Function Get-WiFi-Profile { netsh wlan show profile }          # 저장된 Wi-Fi 목록

SSH 역터널을 함수로 만들어두면 원격 접속 준비도 한 단어로 끝난다.

Function oc01 { ssh -R 53022:localhost:22 oc01 }

적용

프로파일을 수정한 뒤에는 새 세션을 열거나 다시 로드한다.

. $PROFILE

참고

--- ## [방화벽 뒤 PC 접속을 위한 터널링 도구들](https://butteryoon.github.io/tools/2026/07/15/tunneling_tools.html) - **Published Date**: 2026-07-15 - **Author**: James Yoon - **Tags**: ngrok, tailscale, CloudFlare, tunnel, remote desktop - **Description**: ngrok, Cloudflare Tunnel, Tailscale 등 방화벽 뒤의 PC나 로컬 서비스를 외부에서 접속할 수 있게 해주는 터널링 도구들을 비교해본다. ### Content:

2023년에 작성해두었던 초안을 보완해서 발행한다. 방화벽으로 접속이 제한된 네트워크 안의 PC나 로컬에서 개발 중인 서비스를 외부에서 접속해야 할 때 사용할 수 있는 터널링 도구들을 정리해본다.

터널링 도구가 필요한 경우

회사나 집의 PC는 대부분 공유기나 방화벽 뒤에 있어서 외부에서 직접 접속할 수 없다. 포트포워딩이나 VPN을 구성하면 되지만 네트워크 관리 권한이 없거나 설정이 번거로운 경우가 많다. 이럴 때 터널링 도구를 쓰면 내부에서 외부의 중계 서버로 아웃바운드 연결을 만들어두고, 그 연결을 통해 거꾸로 내부 서비스에 접속할 수 있다.

ngrok

ngrok은 이 분야에서 가장 유명한 도구다. 로컬에서 ngrok http 8080 한 줄이면 https://xxxx.ngrok-free.app 같은 공개 URL이 만들어져서 웹훅 테스트나 데모 공유에 특히 편하다.

Cloudflare Tunnel (cloudflared)

Cloudflare Tunnelcloudflared 데몬을 내부 PC에 설치해서 Cloudflare 네트워크로 아웃바운드 터널을 만드는 방식이다.

Tailscale

Tailscale은 위 두 가지와 성격이 조금 다르다. 특정 포트를 공개 URL로 노출하는 게 아니라, 내 디바이스들끼리 WireGuard 기반의 프라이빗 네트워크(메시 VPN)를 만들어준다. 각 디바이스에 100.x.x.x 대역의 IP가 할당되고, 어디에 있든 서로 직접 접속할 수 있다.

외부의 불특정 다수에게 서비스를 보여주는 용도보다는 “내 PC들끼리 어디서나 SSH/RDP로 붙는” 용도에 가장 잘 맞는다. 자세한 사용법은 예전에 정리한 TailScale을 이용한 개인 네트워크 구성하기 글을 참고한다.

tunnelto.dev는?

초안을 쓸 당시 관심을 가졌던 tunnelto.dev는 Rust로 만들어진 오픈소스 터널링 도구인데, 2026년 현재도 서비스는 살아있다. 무료 플랜이 있고 고정 서브도메인은 월 $4부터다. 다만 ngrok이나 Cloudflare Tunnel에 비해 커뮤니티나 기능 발전이 활발한 편은 아니라서, 지금 새로 시작한다면 아래 세 가지 중에서 고르는 것을 추천한다.

비교 정리

도구 무료 여부 방식 주 용도
ngrok 무료(랜덤 도메인, 제한 있음) 공개 URL 터널 웹훅 테스트, 임시 데모
Cloudflare Tunnel 무료(자기 도메인 필요, Quick Tunnel은 도메인 불필요) 공개 URL 터널 개인 서비스 상시 노출
Tailscale 무료(3 사용자 / 100 디바이스) 메시 VPN 내 디바이스 간 SSH/RDP 원격 접속

정리하면, 잠깐 보여줄 거면 ngrok, 도메인 걸고 계속 운영할 거면 Cloudflare Tunnel, 내 장비들 원격 접속용이면 Tailscale이다.

참고

--- ## [오픈소스 VOIP 구성요소 정리](https://butteryoon.github.io/dev/2026/07/15/survey_voip.html) - **Published Date**: 2026-07-15 - **Author**: James Yoon - **Tags**: voip, sip, opensips, rtpengine, kamailio - **Description**: 오픈소스로 VOIP 시스템을 구성할 때 쓰는 시그널링/미디어 엔진들을 정리해본다. ### Content:

2021년에 OpenSIPS 2.4와 RTPEngine mr7.4 조합을 메모해둔 초안을 보완해서 발행한다. 오픈소스로 VOIP 시스템을 만들 때 쓰이는 주요 구성요소를 현재(2026년) 기준으로 정리해본다.

VOIP 시스템은 크게 두 축으로 나뉜다. 호 설정/해제를 담당하는 시그널링(SIP) 과, 실제 음성 패킷을 나르는 미디어(RTP) 다. 오픈소스 세계에서는 이 둘을 별도 컴포넌트로 분리해 조합하는 구성이 일반적이다.

시그널링 엔진: OpenSIPS

미디어 엔진: RTPEngine

그 외 눈여겨볼 프로젝트

정리하면, 대량 호 라우팅은 OpenSIPS 또는 Kamailio + RTPEngine 조합, 통화 기능(IVR/PBX)이 중심이면 FreeSWITCH나 Asterisk를 조합하는 것이 일반적인 오픈소스 VOIP 스택이다.

참고

--- ## [Slack 메시지 curl로 보내기](https://butteryoon.github.io/tools/2026/07/15/slack_webhook.html) - **Published Date**: 2026-07-15 - **Author**: James Yoon - **Tags**: slack, webhook, curl - **Description**: Slack Incoming Webhook을 만들고 curl 한 줄로 채널에 메시지를 보내는 방법 정리 ### Content:

2020년에 gist만 올려두고 묵혀둔 초안을 보완해서 발행한다. 스크립트나 배치 작업이 끝났을 때 Slack 채널로 알림을 받고 싶다면 Incoming Webhook + curl 조합이 가장 간단하다.

Incoming Webhook 만들기

  1. https://api.slack.com/apps에서 Create New App → From scratch로 앱을 만든다. (앱 이름, 워크스페이스 선택)
  2. 앱 설정 화면에서 Incoming Webhooks 메뉴로 들어가 Activate Incoming Webhooks를 On으로 켠다.
  3. 하단의 Add New Webhook to Workspace를 누르고 메시지를 보낼 채널을 선택한 뒤 Allow(허용) 한다.
  4. https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXX 형태의 Webhook URL이 생성된다.

이 URL은 사실상 비밀 토큰이다. URL만 알면 누구나 채널에 글을 쓸 수 있으니 공개 저장소에 커밋하지 말고 환경변수 등으로 관리한다. 유출됐다면 앱 대시보드에서 revoke 하고 새로 발급받으면 된다.

curl로 메시지 보내기

curl -X POST -H 'Content-type: application/json' \
  --data '{"text":"빌드 완료! :tada:"}' \
  https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXX

성공하면 응답으로 ok가 온다. 줄바꿈은 \n, 이모지는 :tada: 같은 코드로 넣을 수 있고, 더 예쁘게 꾸미고 싶으면 blocks 페이로드(Block Kit)를 쓰면 된다.

쉘 스크립트에서 쓸 때는 이렇게 함수로 만들어두면 편하다.

SLACK_WEBHOOK_URL="https://hooks.slack.com/services/..."
notify() {
  curl -s -X POST -H 'Content-type: application/json' \
    --data "{\"text\":\"$1\"}" "$SLACK_WEBHOOK_URL"
}
notify "백업 작업 완료: $(date '+%F %T')"

gist 코드

예전에 만들어둔 PowerShell/curl 예제 gist.

참고

--- ## [WSL 리눅스에서 메일 보내기](https://butteryoon.github.io/tools/2026/07/15/sendmail_on_wsl.html) - **Published Date**: 2026-07-15 - **Author**: James Yoon - **Tags**: wsl, mail, msmtp, mutt - **Description**: WSL Ubuntu 터미널에서 msmtp + mutt로 Gmail SMTP를 통해 메일을 보내는 방법 ### Content:

2020년에 mutt 설치 로그만 붙여놓고 방치했던 초안을 보완해서 발행한다. WSL Ubuntu 터미널에서 스크립트 결과를 메일로 받고 싶을 때, 로컬에 postfix 같은 MTA를 세팅하는 것보다 msmtp로 Gmail SMTP에 릴레이하는 쪽이 훨씬 간단하고 요즘 방식이다.

왜 msmtp인가

예전 초안에서는 mutt를 설치하다가 딸려오는 postfix까지 세팅했는데, WSL에서 postfix를 직접 굴리면 가정용 IP라 대부분 스팸 처리되고 관리도 번거롭다. msmtp는 가벼운 SMTP 클라이언트라 설정 파일 하나로 Gmail 계정을 통해 메일을 보낼 수 있다.

설치

$ sudo apt update
$ sudo apt install msmtp msmtp-mta mutt
...
The following NEW packages will be installed:
  msmtp msmtp-mta mutt libtokyocabinet9
Do you want to continue? [Y/n] Y

msmtp-mta를 같이 설치하면 sendmail 명령이 msmtp로 연결되어 mutt나 cron이 그대로 쓸 수 있다.

Gmail 앱 비밀번호 발급

Gmail은 일반 비밀번호로는 SMTP 로그인이 안 된다. 구글 계정에 2단계 인증을 켠 뒤 앱 비밀번호 페이지에서 16자리 앱 비밀번호를 만들어 쓴다.

msmtp 설정

~/.msmtprc 파일을 만든다.

defaults
auth           on
tls            on
tls_starttls   on
tls_trust_file /etc/ssl/certs/ca-certificates.crt
logfile        ~/.msmtp.log

account        gmail
host           smtp.gmail.com
port           587
from           myid@gmail.com
user           myid@gmail.com
password       발급받은앱비밀번호16자리

account default : gmail

비밀번호가 들어 있으니 권한을 꼭 조인다.

$ chmod 600 ~/.msmtprc

메일 보내기

msmtp 단독으로도 보낼 수 있고,

$ echo -e "Subject: WSL test mail\n\n백업 스크립트 완료" | msmtp jsyoon@example.com

첨부파일이 필요하면 mutt를 쓴다. ~/.muttrc에 한 줄만 추가하면 mutt가 msmtp로 발송한다.

set sendmail = "/usr/bin/msmtp"
set use_from = yes
set realname = "ButterYoon"
set from = "myid@gmail.com"

한 줄 발송 예제.

$ echo "본문 내용" | mutt -s "제목" -a result.log -- jsyoon@example.com

cron 작업 끝에 붙여두면 WSL에서도 작업 결과를 메일로 받아볼 수 있다.

참고

--- ## [사이드프로젝트용 무료 OPEN API 목록 정리](https://butteryoon.github.io/tools/2026/07/15/openapi_list.html) - **Published Date**: 2026-07-15 - **Author**: James Yoon - **Tags**: openapi, api - **Description**: 사이드프로젝트에 바로 쓸 수 있는 무료 OPEN API들을 무료 한도와 함께 정리 ### Content:

2021년에 링크만 모아두고 방치했던 초안을 보완해서 발행한다. 사이드프로젝트를 시작할 때 데이터 소스로 바로 쓸 수 있는 무료 OPEN API들을 무료 한도와 함께 정리했다.

목록

API 한줄 설명 무료 한도
OpenWeather 현재 날씨, 예보, 대기오염 등 날씨 데이터 API 60 calls/min, 월 100만 콜 수준. 이메일만으로 API 키 발급
geo.ipify (IP Geolocation) IP 주소로 국가/도시/좌표/ISP를 조회하는 API 월 1,000회 무료 lookup
Unsplash API 고해상도 무료 사진 검색/랜덤 이미지 API 데모 모드 시간당 50회, 프로덕션 승인 시 시간당 5,000회
Open-Meteo API 키 없이 바로 쓰는 오픈소스 날씨 API 비상업적 용도 무료, 키 발급조차 필요 없음
TMDB 영화/TV 프로그램 메타데이터, 포스터 이미지 API 비상업적 용도 무료 (API 키 발급)
ExchangeRate-API 환율 데이터 API Open access는 키 없이, 무료 플랜 월 1,500회

간단히 특징을 보면,

참고

--- ## [네이버 서치어드바이저에 사이트 등록하기](https://butteryoon.github.io/tools/2026/07/15/naver_search_advisor.html) - **Published Date**: 2026-07-15 - **Author**: James Yoon - **Tags**: naver, search advisor, seo - **Description**: 네이버 서치어드바이저에 사이트를 등록하고 소유확인, 사이트맵 제출까지 진행하는 방법 ### Content:

2020년에 초안으로 남겨두었던 글을 보완해서 발행한다. 네이버 검색에 블로그가 노출되도록 네이버 서치어드바이저에 사이트를 등록하고, 소유확인과 사이트맵 제출까지 진행하는 과정을 정리한다.

서치어드바이저 접속과 사이트 등록

https://searchadvisor.naver.com에 접속해서 네이버 계정으로 로그인한 뒤, 상단의 웹마스터 도구로 들어간다. 사이트 URL 입력란에 https://를 포함한 전체 주소를 입력하고 등록한다.

사이트 소유확인

등록 직후 소유확인 단계가 진행된다. 두 가지 방법 중 하나를 선택하면 된다.

  1. HTML 파일 업로드: 제공되는 확인용 HTML 파일(naver로 시작하는 파일명)을 내려받아 사이트 루트 경로에 업로드한다. Jekyll 블로그라면 저장소 루트에 파일을 넣어두면 된다.
  2. HTML 메타태그: <meta name="naver-site-verification" content="..."> 형태의 태그를 사이트 <head> 영역에 추가한다. 파일 업로드가 번거로운 환경이라면 이 방법이 간편하다.

적용 후 소유확인 버튼을 누르면 검증이 완료된다.

사이트맵 제출

소유확인이 끝나면 왼쪽 메뉴의 요청 > 사이트맵 제출로 이동해서 sitemap.xml 경로를 입력하고 확인을 누른다. Jekyll 블로그는 jekyll-sitemap 플러그인을 쓰면 사이트맵이 자동 생성된다. RSS를 쓴다면 요청 > RSS 제출에서 feed.xml도 함께 제출해 두면 좋다. 제출 후 실제 검색 노출까지는 며칠에서 2주 정도 걸릴 수 있다.

사이트 간단 체크 도구

서치어드바이저에는 사이트의 검색 최적화 상태를 빠르게 점검해주는 사이트 간단 체크 도구가 있다. URL을 입력하면 robots.txt, 사이트 제목/설명, OpenGraph 태그 등의 상태를 확인해준다.

사이트 간단 체크 결과

체크 결과에서 사이트 제목·설명이나 OpenGraph 항목이 비어 있다면 <head>에 title, description 메타태그와 og:title, og:description 태그를 채워주자. Jekyll이라면 jekyll-seo-tag 플러그인으로 한 번에 해결할 수 있다.

참고

--- ## [MetaMask에 Polygon 네트워크 추가하기](https://butteryoon.github.io/tools/2026/07/15/metamask_polygon.html) - **Published Date**: 2026-07-15 - **Author**: James Yoon - **Tags**: MetaMask, Polygon, blockchain, wallet - **Description**: MetaMask 지갑에 Polygon PoS 네트워크를 수동으로 추가하는 방법을 정리한다. ### Content:

2022년에 작성해두었던 초안을 보완해서 발행한다. MetaMask 지갑에 Polygon PoS 네트워크를 수동으로 추가하는 방법을 정리해본다.

MetaMask 설치

MetaMask는 가장 널리 쓰이는 이더리움 계열 지갑이다. 공식 다운로드 페이지에서 브라우저 확장(Chrome, Firefox, Edge 등)이나 모바일 앱을 설치하고 지갑을 생성한다. 시드 문구(Secret Recovery Phrase)는 절대 온라인에 저장하지 말고 안전한 곳에 보관한다.

MetaMask는 기본적으로 이더리움 메인넷만 설정되어 있어서 Polygon 같은 다른 네트워크는 직접 추가해야 한다. 최근 버전에서는 네트워크 선택 목록에 Polygon이 기본 제공 목록으로 떠서 클릭 한 번으로 추가되는 경우도 있지만, 없다면 아래처럼 수동으로 추가한다.

Polygon PoS 네트워크 수동 추가

MetaMask에서 좌측 상단의 네트워크 선택 드롭다운을 열고 Add networkAdd a network manually를 선택한 뒤 아래 값을 입력한다.

항목
Network name Polygon PoS
New RPC URL https://polygon-rpc.com
Chain ID 137
Currency symbol POL
Block explorer URL https://polygonscan.com

저장하면 네트워크 목록에 Polygon이 추가되고, 선택하면 바로 전환된다.

참고로 Polygon의 네이티브 토큰은 원래 MATIC이었는데 2024년에 POL로 리브랜딩되었다. 예전 가이드에는 통화 기호가 MATIC으로 나와 있지만 현재는 POL을 사용한다.

초안에 적어두었던 예전 문서 링크는 현재 docs.polygon.technology의 MetaMask 가이드로 옮겨졌으니 최신 값은 공식 문서를 확인하는 것이 좋다.

참고

--- ## [ffmpeg로 SRT 스트리밍 해보기 (listener / caller 모드)](https://butteryoon.github.io/dev/2026/07/15/ffmpeg_srt_mode.html) - **Published Date**: 2026-07-15 - **Author**: James Yoon - **Tags**: ffmpeg, ffplay, srt, mpegts, streaming - **Description**: ffmpeg로 mp4 파일을 SRT 프로토콜로 실시간 전송하고 ffplay로 재생해본다. ### Content:

2020년에 ffmpeg로 SRT 스트리밍을 테스트하면서 적어둔 초안을 보완해서 발행한다. mp4 파일을 ffmpeg로 읽어 SRT 프로토콜로 전송하고, ffplay로 받아서 재생하는 가장 단순한 구성을 정리한다.

SRT 프로토콜이란

SRT(Secure Reliable Transport)는 Haivision이 공개한 오픈소스 저지연 스트리밍 프로토콜이다. UDP 기반이지만 패킷 재전송(ARQ)과 타임스탬프 기반 전송으로 불안정한 공용 인터넷 구간에서도 안정적인 전송이 가능하고, AES 암호화도 지원한다. RTMP를 대체하는 기여(contribution)용 프로토콜로 방송 업계에서 많이 쓰이고 있으며, OBS Studio도 SRT 송출/수신(ingest)을 지원한다.

SRT 연결에는 세 가지 모드가 있다.

ffmpeg의 SRT URL 형식은 srt://hostname:port?option1=value1&option2=value2 이고, mode 외에도 latency(재전송 버퍼 지연), streamid, pkt_size, passphrase(암호화) 같은 옵션을 쿼리스트링으로 지정할 수 있다.

SRT Server(listener) Mode

mp4 파일을 실시간 속도(-re)로 읽어서 재인코딩 없이(-c copy) MPEG-TS 컨테이너로 감싸 SRT listener로 대기시킨다.

❯ ffmpeg -re -i .\BigBuckBunny.mp4 -c copy -f mpegts "srt://:8888?mode=listener"

SRT Client(caller) Mode

다른 터미널에서 ffplay로 접속해서 재생한다. mode를 생략하면 기본값이 caller라서 그냥 주소만 주면 된다.

❯ ffplay srt://localhost:8888

반대로 ffmpeg 쪽을 caller로, 수신 쪽(ffplay 또는 OBS의 Media Source)을 listener로 구성할 수도 있다. 예를 들어 OBS에서 srt://0.0.0.0:8888?mode=listener로 입력 소스를 만들어 두고, ffmpeg가 srt://obs호스트:8888 로 밀어 넣는 식이다.

참고

--- ## [Bing 웹마스터 도구에 사이트 등록하기](https://butteryoon.github.io/tools/2026/07/15/bing_webmaster_tool.html) - **Published Date**: 2026-07-15 - **Author**: James Yoon - **Tags**: bing, webmaster, seo - **Description**: Bing Webmaster Tools에 블로그를 등록하고 사이트맵을 제출하는 방법 ### Content:

2020년에 초안으로 남겨두었던 글을 보완해서 발행한다. Microsoft Bing 검색에 블로그가 노출되도록 Bing 웹마스터 도구(Bing Webmaster Tools)에 사이트를 등록하고 사이트맵을 제출하는 과정을 정리한다.

Bing 웹마스터 도구 접속

https://www.bing.com/webmasters에 접속해서 로그인한다. Microsoft 계정 외에 Google, Facebook 계정으로도 로그인할 수 있다.

사이트 등록

사이트를 추가하는 방법은 두 가지다.

Bing 사이트 추가

1. Google Search Console에서 가져오기 (추천)

이미 구글 서치 콘솔에 사이트를 등록해 두었다면 이 방법이 가장 간단하다. 가져오기(Import) 버튼을 누르고 Google 계정으로 로그인해 권한을 허용하면, 서치 콘솔에 등록된 사이트 목록이 나온다. 가져올 사이트를 선택하면 별도의 소유 확인 절차 없이 등록이 끝난다. 서치 콘솔에 제출해 둔 사이트맵도 함께 가져온다.

2. 수동으로 추가하기

수동 등록을 선택하면 사이트 URL을 입력한 뒤 소유 확인을 진행해야 한다. XML 파일(BingSiteAuth.xml) 업로드, HTML 메타태그 삽입, DNS CNAME 레코드 추가 중 하나를 선택할 수 있다. GitHub Pages 블로그라면 메타태그를 <head>에 추가하는 방법이 편하다.

Bing 사이트 추가 완료

사이트맵 제출

등록이 끝나면 대시보드 왼쪽 메뉴의 사이트맵(Sitemaps) 에서 https://내도메인/sitemap.xml 주소를 제출한다. Google Search Console에서 가져오기로 등록했다면 사이트맵이 이미 들어와 있을 수 있으니 목록만 확인하면 된다. 제출 후 수집까지는 보통 몇 시간에서 며칠 정도 걸린다.

마무리

URL 검사 도구로 개별 페이지의 색인 상태를 확인할 수 있고, 검색 성능 리포트에서 노출/클릭 통계도 볼 수 있다. 구글 서치 콘솔에 등록해 둔 사이트라면 가져오기 기능 덕분에 몇 분이면 끝나니 함께 등록해 두자.

참고