탭이 안 되는 링크 — 텔레그램에서 옵시디언 노트 열기

작성자

카테고리:

탭이 안 되는 링크 — 텔레그램에서 옵시디언 노트 열기

셀프호스팅 구축기 15편. 구축기를 마쳤어도 막상 쓰다 보면 후속 문제가 나온다 — 13편에서 동기화한 노트, 그 링크가 폰에서 탭이 안 됐다.

← 이전 편: 13편 — 내 노트는 내 서버에 (Obsidian LiveSync)

요약

  • 옵시디언 노트는 obsidian://open?vault=...&file=... 형태의 고유 링크를 가진다
  • 이 링크를 텔레그램으로 보내면 파란 링크가 아니라 회색 죽은 글씨 — 탭이 안 된다
  • 원인: 채팅앱은 http/https만 자동으로 링크화한다. obsidian:// 같은 커스텀 스킴은 무시
  • 해결: https 주소 한 단을 끼운다 — https로 받아서 브라우저가 obsidian://로 튕기는 “셔틀” 페이지
  • 그 셔틀을 집 서버 대신 Cloudflare Worker(서버리스)에 올렸다 — 집 컴퓨터가 꺼져도 동작, 비용 0원

1. 증상 — 회색으로 죽은 링크

옵시디언은 노트마다 고유 링크를 준다. 노트를 우클릭해 “obsidian URL 복사”를 누르면 obsidian://open?vault=내볼트&file=폴더/노트 같은 주소가 잡힌다. 이걸 텔레그램으로 보내면 파란 글씨가 될 줄 알았는데, 회색 평문으로 떴다. 눌러도 아무 일도 안 일어난다. 링크가 아니라 그냥 글자였던 것이다.

2. 원인 — 채팅앱은 http/https만 링크로 만든다

채팅앱은 메시지 글자를 훑어 URL을 찾으면 자동으로 탭 가능한 링크로 바꾼다. 단 이 자동 변환은 http://·https://(그리고 텔레그램 자체의 tg://)에만 적용된다. obsidian://·notion://·slack:// 같은 앱 전용 커스텀 스킴은 변환 대상이 아니라 평문으로 남는다. 텔레그램 iOS 저장소에도 “커스텀 URI 스킴 링크는 클릭이 안 된다”는 같은 이슈가 올라와 있다.

버튼이나 마크다운 링크로 우회하면 되지 않냐 — 그것도 안 된다. 봇이 메시지에 붙이는 인라인 버튼·링크 역시 http/https/tg만 허용한다. 커스텀 스킴은 거부된다.

3. 정석 패턴 — https “셔틀” 한 단 끼우기

커스텀 스킴이 직접 못 가니, 중간에 https를 한 번 거치게 한다.

  1. 텔레그램에는 https 링크를 보낸다 → 파란 링크가 된다
  2. 탭하면 브라우저가 그 https 페이지를 연다
  3. 그 페이지의 자바스크립트가 obsidian://로 튕긴다 → 옵시디언이 열린다

이 패턴은 새로운 게 아니다. obsid.net이라는 공개 무료 서비스가 정확히 이 일만 한다 — vaultfile을 받아 브라우저에서 obsidian://로 넘겨주는 정적 페이지다. 그대로 써도 된다.

4. 그런데 왜 직접 만들었나

obsid.net이 있는데 굳이 직접 만든 이유는 이 시리즈의 일관된 이유와 같다.

  • 제3자를 안 거친다 — 내 볼트 이름과 노트 경로가 남의 서버(로깅을 안 한다 해도)를 지나가지 않는다
  • 내 도메인o.내도메인 한 줄, 링크가 내 것
  • 내가 페이지를 통제 — 자동 이동이 막힐 때 누를 버튼, 어떤 노트인지 보여주는 파일명을 직접 넣을 수 있다 (7절 함정 때문에 중요하다)

처음엔 이미 띄워 둔 다른 앱의 정적 폴더에 페이지를 하나 얹었다. 작동은 했지만, 알림용 리다이렉트를 상관없는 앱 안에 끼워 넣은 꼴이라 경계가 더러워졌다. 리다이렉트는 어느 앱에도 속하지 않는 범용 유틸이다. 그래서 떼어내 독립시켰다.

5. 어디에 둘까 — 집 서버 vs 엣지

독립시킨다면 둘 중 하나다.

집 서버에 작은 웹서버 Cloudflare Worker(엣지)
동작 조건 집 컴퓨터가 켜져 있어야 집 컴퓨터 꺼져도 동작
인증서 직접 발급·갱신 자동
비용 전기 무료(하루 10만 요청)
종속 없음 Cloudflare

리다이렉트는 1초짜리 정적 응답이라 집 서버를 굳이 깨워 둘 이유가 없다. Cloudflare Worker를 골랐다 — 코드 한 조각을 클라우드 엣지에 올리면 서버를 직접 굴리지 않고도 응답한다(이걸 서버리스라 한다). 6편에서 산 도메인이 이미 Cloudflare에 있으니 서브도메인 하나 붙이면 끝이다.

6. 작동 — https가 받아서 obsidian://로 튕긴다

Worker가 하는 일은 짧다. ?f=노트경로를 받아, 그걸 obsidian:// 링크로 바꾼 HTML 한 장을 돌려준다.

export default {
  async fetch(request) {
    const url = new URL(request.url);
    const file = url.searchParams.get('f') || '';
    const vault = url.searchParams.get('v') || 'MyVault';
    const uri = 'obsidian://open?vault=' +
      encodeURIComponent(vault) + '&file=' + encodeURIComponent(file);
    const html = '<!doctype html><meta charset=utf-8>'
      + '<p>' + file + '</p>'
      + '<a href="' + uri + '">노트 열기</a>'
      + '<script>setTimeout(function(){location.href=' + JSON.stringify(uri) + '},350)</' + 'script>';
    return new Response(html, {
      headers: { 'content-type': 'text/html; charset=utf-8' }
    });
  }
}

텔레그램에는 https://o.내도메인/?f=노트경로만 보낸다. 이건 https라 파란 링크가 되고, 탭하면 위 페이지가 떠서 옵시디언으로 넘긴다.

7. 함정 셋

① 자동 이동이 막힌다. location.href = obsidian://...로 자동 전환을 걸어도, 모바일 브라우저(특히 안드로이드 크롬·채팅앱 내장 브라우저)는 사용자가 직접 누르지 않은 커스텀 스킴 이동을 보안상 막는 경우가 있다(“Navigation is blocked”). 그래서 자동 이동에만 기대면 안 되고, 사용자가 탭할 “노트 열기” 버튼을 반드시 같이 둔다. 자동 전용 페이지가 가끔 안 먹는 이유가 이거다.

② 볼트 이름이 기기마다 다르다. obsidian://open?vault=X의 X는 그 기기에 등록된 볼트 표시 이름과 정확히 같아야 한다. PC에선 열리는데 폰에선 “노트 없음”이 뜨면 십중팔구 볼트 이름이 다른 것이다. 옵시디언 포럼에도 “안드로이드에서 앱은 열리는데 노트는 안 열린다”는 같은 사례가 있다. 링크에 &v=폰볼트이름을 맞춰 주면 된다.

③ 동기화가 먼저다. 링크는 노트를 여는 거지 만들어 주는 게 아니다. 그 노트가 폰에 동기화돼 있어야(13편 LiveSync) 열린다.

8. 비용

  • Cloudflare Worker: 0원 (무료 플랜 하루 10만 요청)
  • 도메인: 이미 보유(6편), 서브도메인 추가비 없음
  • 집 서버 부담: 없음(엣지가 응답)

한 줄 정리

채팅앱은 http/https만 링크로 만든다. obsidian:// 같은 앱 링크는 https 셔틀 한 단을 끼워야 탭이 된다. 그 셔틀을 Cloudflare Worker에 올리면 집 서버와 무관하게 공짜로 돈다. 단 자동 이동은 막힐 수 있으니 버튼을 같이 두고, 볼트 이름을 기기에 맞춰라.

코멘트

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다