무색
기술블로그
에세이
연구
프로덕트
소개

무색

소프트웨어로 비즈니스의 가능성을 만듭니다. 웹·앱 개발, 음성 AI, 자동화 콘텐츠 제작까지 — 기술이 필요한 곳에 무색이 있습니다.

연락처

[email protected]

사업자 정보

상호: 무색

대표: 배성재

사업자등록번호: 577-58-00836

인천광역시 연수구 인천타워대로 323, 에이동 8층 801-802호 AB-132 (송도동, 송도 센트로드)

© 2026 무색. All rights reserved.
개인정보처리방침·이용약관
INCHEON, KR
Obsidian NFS 지식 관리 키 비주얼
크로스커팅
2026. 1. 24.

Obsidian + NFS: 번역 논문과 노트를 한곳에서 관리하기

NFSObsidianknowledge-managementhomelabglossary

논문을 번역하다 보면 결과물이 여기저기 흩어진다. GPU 서버에 번역된 PDF가 쌓이고, 노트북에선 Obsidian으로 메모를 적고, 용어 사전은 또 다른 디렉토리에 있고. 어느 순간 "아까 번역한 그 논문 어디 뒀지?" 하면서 터미널을 뒤지는 자신을 발견했다.

해결책은 의외로 단순했다. 모든 걸 NFS 공유 스토리지 한 곳에 모으면 된다.

SSD 한 장으로 시작하는 공유 스토리지

홈랩 구성은 좀 복잡하다. Samsung 990 PRO 2TB SSD를 Hyper-V에서 Proxmox로 패스스루하고, 다시 worker1 VM의 /mnt/ssd에 마운트한다. 3단계 패스스루인 셈이다. 이 SSD 위에 K8s NFS Server Pod을 띄우면 클러스터 안팎에서 같은 파일 시스템을 쓸 수 있다.

핵심 트릭은 모든 PV의 NFS 경로를 루트(/)로 통일한 것이다. 처음에는 서비스마다 하위 경로를 나눴는데 서비스 간 파일 공유가 필요해지면서 전부 루트로 바꿨다. 덕분에 Syncthing, n8n, WSL 모두 같은 디렉토리 트리를 본다.

# NFS PV - 모든 소비자가 같은 루트를 공유
apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfs-syncthing
spec:
  nfs:
    server: 192.168.31.35  # MetalLB IP
    path: /                 # 루트 통일!
  mountOptions:
    - nfsvers=4
  claimRef:               # 바인딩 고정
    namespace: syncthing
    name: shared-nfs

번역 파이프라인이 NFS에 쓰고, Obsidian이 읽는다

n8n 번역 워크플로는 PDF를 받으면 두 가지 일을 동시에 한다. 원본 PDF를 NFS의 /shared/obsidian-vault/ 경로에 즉시 저장하고, TranslateGemma에 번역을 요청한다. 번역이 끝나면 결과 PDF도 같은 경로에 떨어진다.

Obsidian은 Syncthing을 통해 이 NFS 볼륨과 동기화된다. 그래서 번역 워크플로가 PDF를 저장하는 순간 Obsidian 볼트에도 자동으로 나타난다. WSL에서 직접 NFS를 마운트해서 파일을 편집할 수도 있다. 별도 복사나 동기화 스크립트 없이 "한 곳에 쓰면 어디서든 읽힌다"는 구조다.

glossary.json으로 번역 품질 누적하기

논문 번역에서 가장 짜증나는 건 용어 불일치다. 같은 논문 안에서 "attention mechanism"이 "주의 메커니즘"으로도, "어텐션 메카니즘"으로도 번역되면 읽기가 힘들다. 여러 논문을 번역할수록 문제는 더 커진다.

이걸 해결하려고 마스터 용어 사전(glossary.json)을 만들었다. 모든 논문의 용어가 하나의 JSON 파일에 누적된다. 새 논문을 번역할 때 기존 용어는 마스터 사전의 번역을 그대로 쓰고, 신규 용어만 추가한다. TranslateGemma가 번역할 때 이 사전을 프롬프트에 주입해서 일관된 번역을 보장한다.

# 마스터 사전에서 기존 용어 재사용, 신규만 추가
for src, tgt in new_terms.items():
    if src in master:
        existing[src] = master[src]  # 마스터 번역 유지
    else:
        master[src] = tgt
        added[src] = tgt

용어가 너무 많으면 컨텍스트 윈도우를 잡아먹어 번역 품질이 떨어지기도 한다. 그래서 논문별 CSV를 마스터의 부분집합으로 뽑아 해당 논문에 등장하는 용어만 주입하는 게 중요했다.

디렉토리 구조

결과적으로 NFS 공유 볼륨의 구조는 이렇게 생겼다.

/shared/
  obsidian-vault/
    zotero-zotmoov/
      public/           # 번역 원본+결과 PDF
    notes/              # Obsidian 노트
  paper-translate/
    glossary.json       # 마스터 용어 사전
    papers/
      paper-name.csv    # 논문별 용어 CSV

n8n이 obsidian-vault/에 PDF를 저장하면 Syncthing이 Obsidian으로 동기화한다. glossary.json은 번역할 때마다 갱신되고, 논문별 CSV는 그 부분집합으로 자동 생성된다.

삽질 기록

NFS 셋업에서 가장 많이 헤맨 건 두 가지다.

첫째, kubelet이 호스트 레벨에서 NFS를 마운트하기 때문에 K8s 내부 DNS(nfs-server.shared-storage.svc)를 PV에 쓸 수 없다. MetalLB가 할당한 고정 IP를 써야 한다. 이걸 몰라서 한참 삽질했다.

둘째, NFSv4 전용 서버인데 PV에 mountOptions: [nfsvers=4]를 빼먹으면 NFSv3으로 폴백해서 마운트가 실패한다. 에러 메시지가 명확하지 않아서 원인 찾기가 어려웠다.

glossary 쪽에서는 용어를 통째로 주입했다가 컨텍스트 윈도우 문제를 겪었다. 마스터 사전에 용어가 300개 넘어가니까 본문 번역 품질이 눈에 띄게 떨어졌다. 논문별 CSV로 필요한 용어만 골라 넣는 방식으로 바꾸고 나서야 해결됐다.

NFS라는 오래된 답

돌이켜보면 이 구조의 핵심은 별거 없다. NFS로 파일 시스템을 공유하고 각 서비스가 자기 역할에 맞게 읽고 쓰는 것뿐이다. n8n은 PDF를 저장하고, TranslateGemma는 glossary를 읽고, Obsidian은 결과를 보여준다. 데이터가 이동하는 게 아니라 한 곳에 머물면서 여러 서비스가 접근하는 패턴이다.

NFS는 1984년에 나온 프로토콜이다. 40년이 넘었는데 여전히 이런 문제를 풀기에 가장 실용적인 도구라는 게 재밌다. 화려한 오브젝트 스토리지나 분산 파일시스템 대신 NFS 하나로 충분했다.

자주 묻는 질문

NFS PersistentVolume에서 K8s 내부 DNS를 쓸 수 없는 이유는?
kubelet이 호스트 레벨에서 NFS를 마운트하기 때문에 K8s 내부 DNS(svc.cluster.local)를 해석할 수 없습니다. MetalLB가 할당한 고정 IP를 PV의 nfs.server에 지정해야 합니다.
논문 번역 시 마스터 용어 사전을 통째로 주입하면 안 되나요?
용어가 300개 이상이면 컨텍스트 윈도우를 과도하게 차지해 번역 품질이 떨어집니다. 논문별 CSV로 해당 논문에 등장하는 용어만 골라 부분집합으로 주입하는 것이 효과적입니다.
Obsidian과 NFS를 연결하는 방법은?
K8s에서 Syncthing Pod이 NFS 볼륨을 마운트하고, 로컬 Obsidian 볼트와 Syncthing으로 동기화합니다. 번역 파이프라인이 NFS에 PDF를 저장하면 자동으로 Obsidian에 나타납니다.
크로스커팅(7/18)
Prev

Claude Code 헤드리스 모드: 서브프로세스로 AI 삽입하기

Next

서버 진행상황을 클라이언트에서 보는 세 가지 패턴