どちらを選んだかは、先に言わない。どう選んだかを、判断が動いた順番のまま書く。題材は、ワンタップで送った1行のメモが、最終的にどこへ着地するか、だ。ObsidianのMarkdownファイルに1行足すのか、NotionのデータベースにAPIで書き込むのか。画面を何で描くかをUIKitとSwiftUIで選んだ前回の続きで、今回は道具そのものではなく、書いたものの行き先を選ぶ。
「メモアプリ Obsidian Notion どっち」で検索すると、たいていは編集体験や見た目の比較が出てくる。だが自分がここで選ぶのは編集の場所ではない。ワンタップで送った思いつきが、最初に着地する場所の設計だ。そこは編集画面より前の、もっと乾いたレイヤの話になる。
何を選ぶ問題なのか、をまず狭める
キャプチャ専用のメモアプリにとって、「行き先」は2つの意味に分かれる。1つは、ユーザーが最終的に読み返す場所。もう1つは、送信ボタンを押した直後にデータが物理的に書き込まれる場所。この2つは同じとは限らない。
今回決めるのは後者だ。前者、つまり「どこで整理して読むか」は、正直ユーザーの好みでいい。ObsidianでもNotionでも、Apple純正メモでも、本人が心地よい場所ならそれが正解になる。問題は、その手前の「送った瞬間、どこに、どうやって、確実に1行を刻むか」の部分で、ここだけはアプリの設計者が引き受けないといけない。
だから比較の土俵を、機能の多さやUIの好みから、いったん引きはがす。比べるのは2つの書き込みパラダイムだ。片方はローカルのMarkdownファイルに追記する方式。もう片方は、ネットワーク越しにホスト型データベースのAPIを叩く方式。Obsidianは前者の代表で、Notionは後者の代表になる。この2つは、思想がかなり違う。
候補を並べる
行き先の候補は、実際には4つあった。
- Obsidianの保管庫(vault)に、ローカルのMarkdownファイルとして追記する
- NotionのAPIを呼び、指定データベースのページやブロックとして追記する
- メールだけで完結させ、外部ツール連携は持たない
- 1と2を両方やる(二重書き込み)
3のメール単独は、このアプリがもともと採っている土台だ。送信は自分宛メールとして届く。この時点で「消えない」は担保できている。だが受信箱は、PKMのように構造化して育てる場所ではない。セカンドブレインやZettelkastenの入口として使うなら、メールの外にもう1つ、積み上がる置き場が要る。だから連携先を1つ足す判断になった。
4の二重書き込みは魅力的に見えて、最初に落ちた。書き込み先が2つあると、片方が成功して片方が失敗したときに、どちらを正とするかが決まらない。「メールには届いたがNotionには入っていない」という半端な状態を検知して、片側だけ再送する仕組みを、キャプチャの速さを守りながら作るのは割に合わない。真実が2つある設計は、どちらかが遅れた瞬間に、ユーザーへ「入ったのか、入っていないのか」を答えられなくなる。連携先は1つに絞る、と早い段階で決めた。
残ったのは1と2、Obsidianファイル追記か、NotionのAPI追記か、という一騎打ちになった。
比べる軸を、キャプチャの都合で立てる
軸は7本立てた。ここで大事なのは、軸に重みをつける前に、この道具が「キャプチャ専用」だという前提を思い出すことだ。Day8で書いたInbox一本の設計や、Day3で書いた送信の到達契約と同じで、評価軸は用途から逆算しないと意味を持たない。
| 軸 | Obsidian(ローカルMarkdown追記) | Notion(ホストDBへAPI追記) |
|---|---|---|
| 書き込み遅延 | ローカルファイルI/O、ほぼ即時 | ネット往復あり、数百ms〜秒 |
| オフライン | 圏外でもその場で書ける | ネット必須、圏外は不可 |
| データ所有 | 手元の.md、ロックインなし |
Notionサーバ上、エクスポート前提 |
| 設定の手間 | フォルダを一度選ぶだけ | 連携トークン発行+DB選択+項目対応 |
| 失敗モード | iCloud同期の遅延、ファイル競合 | 429レート制限、トークン失効、API変更 |
| 構造・検索 | 平文の時刻付き行、構造は弱い | プロパティ・リレーションで強い |
| 長期の寿命 | アプリが消えてもファイルは残る | アカウントとAPIに依存 |
この表を眺めると、NotionはNotionで明確に強い列を持っている。構造・検索の行だ。プロパティを持ったデータベースに入れられれば、タグやステータスや締切で後から絞り込める。これはMarkdownの平文追記には出せない強さだ。
だが、キャプチャの瞬間に効く軸はそこではない。効くのは上の3行——遅延、オフライン、所有——になる。ここが今回の判断の中心だった。
iPhoneのクイックキャプチャ先は、ObsidianとNotionのどちらが向くのか
この問いに一般解はない。ただ「キャプチャ専用の入口」という条件を付けると、答えは片方に寄る。理由は、キャプチャという行為の仕事が「思いついたことを、信頼できる場所に、考えを止めずに置く」で終わっているからだ。整理はそのあとの、別フェーズの仕事になる。
キャプチャと整理の分業、という言い方をしている。外に出ているときはiPhoneで捕まえるだけ捕まえて、机に戻ってからObsidianなりNotionなりでじっくり畳む。この分け方を採ると、入口に求める性質がくっきりする。速いこと。圏外でも死なないこと。書いたものが自分の手元に残ること。この3つだ。
Notionのデータベースは、整理フェーズでは頼れる。しかしキャプチャの入口に置くと、3つとも引っかかる。APIはネットワークを要求するから、電車のトンネルや山では書けない。1本の往復に数百ミリ秒かかることもあり、送ってすぐ次を書きたいテンポに割り込む。そしてデータはNotionのサーバ側にある。どれもNotionの欠陥ではなく、ホスト型DBという構造から来る、当然の帰結だ。
一方、Obsidianの保管庫は、ただのフォルダに置かれた.mdファイルの集まりでしかない。Obsidianはアカウントを要求せず、既定ではネットワークにも出ない。だから追記は、iCloud Drive上のローカルファイルに1行を足すだけの、ネット不要の操作になる。キャプチャの入口が欲しがる性質と、ローカルMarkdownの性質が、ちょうど噛み合っていた。
Obsidian側は、ファイルに1行足すだけになる
言葉で書くと単純だが、実装はいくつか気をつける点がある。追記先は、その日のyyyy-MM-dd.mdか、固定のInboxノートのどちらか。形式は- HH:mm メモのタイムスタンプ付きリスト行。既存の中身は壊さず、末尾に1行だけ増やす。
フォルダへのアクセスは、ユーザーが一度選んだvaultのsecurity-scoped bookmarkで持っておく。書き込みは、他プロセス(Obsidian本体やiCloud同期)と競合しないようNSFileCoordinatorで調停する。
func appendLine(_ line: String, to noteURL: URL) throws {
var coordError: NSError?
let coordinator = NSFileCoordinator()
coordinator.coordinate(writingItemAt: noteURL,
options: .forMerging,
error: &coordError) { url in
let existing = (try? String(contentsOf: url, encoding: .utf8)) ?? ""
// 末尾に改行がなければ足してから1行追記する
let joined = existing.isEmpty || existing.hasSuffix("\n")
? existing + line + "\n"
: existing + "\n" + line + "\n"
try? joined.data(using: .utf8)?.write(to: url, options: .atomic)
}
if let coordError { throw coordError }
}
タイムスタンプ行の組み立ては、ロケール非依存で固定する。ユーザーの端末設定に引っ張られてHHが12時間表記になると、あとで並べたとき崩れるからだ。
private let stamp: DateFormatter = {
let f = DateFormatter()
f.locale = Locale(identifier: "en_US_POSIX") // 端末設定に依存させない
f.dateFormat = "HH:mm"
return f
}()
func formattedLine(for memo: String, at date: Date) -> String {
"- \(stamp.string(from: date)) \(memo)"
}
この経路には、意図的にネットワーク呼び出しを1つも置いていない。キャプチャのホットパスは、ローカルファイルI/Oだけで閉じる。ここが今回の設計でいちばん守りたかった線だ。保管庫がObsidian Sync専用でiCloud Driveに出てこない場合だけ、例外としてobsidian:// URLスキームで一瞬開いて追記するフォールバックに切り替える。詳しい分解はDay9で書いた。
Notionに自動でメモを追記するのと、Obsidianに追記するのは何が違うのか
同じ「自動追記」でも、Notion側は絵がまるで変わる。2021年に公開されたNotionのAPIは、REST型のよくできたAPIだ。だが叩くには、連携トークンによる認証と、生きたネットワークが要る。書き込みは、ローカルI/Oではなく、こういうHTTPリクエストになる。
func appendToNotion(_ memo: String, databaseId: String,
token: String) async throws {
var req = URLRequest(url: URL(string: "https://api.notion.com/v1/pages")!)
req.httpMethod = "POST"
req.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
req.setValue("2022-06-28", forHTTPHeaderField: "Notion-Version")
req.setValue("application/json", forHTTPHeaderField: "Content-Type")
req.httpBody = try JSONSerialization.data(withJSONObject: [
"parent": ["database_id": databaseId],
"properties": ["Name": ["title": [["text": ["content": memo]]]]]
])
let (_, resp) = try await URLSession.shared.data(for: req)
// 429 が返るので、Retry-After を尊重してキューし直す必要がある
guard (resp as? HTTPURLResponse)?.statusCode == 200 else {
throw CaptureError.notionRejected
}
}
コードの行数はさほど変わらない。だが背後に抱えるものが違う。まず、書き込みにかかる時間の内訳がまるで別物だ。ローカルのファイル追記は、フォルダを開いて調停し、既存の内容に1行足して原子的に書き戻すだけで、実測では数ミリ秒の世界に収まる。対してNotion経路は、名前解決とTLSの確立、リクエストの往復、JSONの直列化と応答の解釈がぶら下がり、電波が良くても合計で数百ミリ秒、悪ければ1秒を超える。10回連続で送るテンポの入力では、この差は誤差ではなく体感になる。
抱えるものの違いは、遅延だけではない。Notionのレート制限は、1つの連携あたり平均で毎秒3リクエスト、15分あたり2,700回が目安とされる。個人が数分に1回メモを送るぶんには当たらない。しかし「当たらないから無視していい」ではなく、当たったときに429とRetry-Afterを見て、送信済みキューを崩さずに待って再送する経路を、キャプチャの速さと両立させて実装する義務が生まれる。トークンが失効すれば書けなくなるし、Notion-Versionが上がればペイロードの追従も要る。オフラインなら、そもそも1バイトも書けない。加えて、使い始めるまでの段取りも重い。Notion側で連携(インテグレーション)を作ってトークンを発行し、書き込みたいデータベースにその連携を共有し、どのプロパティにメモ本文を入れるかを対応づける。ここまでやって、ようやく最初の1行が入る。Obsidian側は、iCloud Drive上の保管庫フォルダを一度選ぶだけで終わる。
つまりNotion追記は、送信の裏にもう1つ、小さな配送システムを建てるのに近い。Day3やDay11で、メール配送の到達契約と後処理の分離に苦労した話を書いたが、Notion経路を採ると、あの苦労がもう一式増える。Obsidianのファイル追記には、その配送システムがまるごと要らない。差の本質は、機能ではなく、抱える運用の重さの側にあった。
選び、そして何を捨てたか
選んだのは、Obsidianのローカルファイル追記だ。キャプチャの入口としては、遅延・オフライン・所有の3軸が支配的で、ローカルMarkdownがその3つを素で満たしていた。ネットワーク越しのAPIを、いちばん速くありたいホットパスに置く理由が、この用途では見つからなかった。
だが、捨てたものは正直に数える。Notionを選ばなかったことで、構造化された取り込みを最初から諦めている。送った瞬間にステータスを「未整理」にし、プロジェクトのリレーションを張り、締切プロパティを埋める——そういう「入口で構造を持たせる」運用は、平文の- HH:mm追記では出せない。もしあなたの母艦がNotionで、ワークフローの全部がそのデータベースの上で回っているなら、キャプチャもNotionのInbox用DBへ直接入れるほうが、後の手数は確実に減る。そこはNotionが正しく勝つ場所だ。
もう1つ正直に書くと、ローカルファイル追記にも弱点はある。iCloud同期はときどき数秒遅れるし、複数端末が同じ.mdを同時に触れば競合の目もある。構造がない平文なので、増えすぎたInboxノートは、結局あとで人間が仕分ける前提になる。この「あとで仕分ける」問題は、Day12で思考実験として掘った通り、消えたわけではなく、整理フェーズへ先送りしただけだ。
それでも釣り合っていると判断した。キャプチャ専用という形にとっては、入口の軽さと手元に残る安心のほうが、入口での構造化より重い。この重みづけは、Day16でUIKitを選んだときと同じ筋で出している。良し悪しは道具単体では決まらず、いつも「何のための入口か」とセットで決まる。用途がNotion中心に変われば、この答えも当然ひっくり返る。
3ヶ月後に、この判断を見直すとしたらどこか
決めたことより、決めた前提が崩れる場所を書いておくほうが、あとで役に立つ。次にこの選択を疑うなら、たぶん次の3点のどれかが引き金になる。
1つ目、Notionのようなホスト型ツールが、オフラインの書き込みキューをAPI側で正式に持ったとき。いま「ネット必須」を弱点に数えた根拠が消えるので、重みづけをやり直す必要が出る。2つ目、ユーザーの保管庫がObsidian Sync専用で、iCloud Driveに出てこないケースが想定より多かったとき。その場合は主役がファイル追記ではなくobsidian://フォールバックになり、設計の重心がずれる。3つ目、キャプチャ時のファイルI/Oが、保管庫の肥大で目に見えて遅くなったとき。ローカルが速いという前提そのものが揺らぐ。
この3つのどれかが起きたら、たぶん自分はまたこの表を引っぱり出して、軸の重みを引き直す。そのときのために、判断の中身ではなく、判断の手順を残しておく——というのが、この記事の本当の目的だった。
最後に、答えを持っていない問いを1つ置く。あなたがiPhoneで思いつきを捕まえるとき、その最初の1行は、手元のファイルに落ちてほしいだろうか、それともクラウドのデータベースに構造ごと入ってほしいだろうか。そしてその選択を決めるのは、「圏外でも書けること」だろうか、それとも「入れた瞬間から検索で引けること」だろうか。自分はキャプチャの入口では前者を取ったが、整理の母艦では後者が正しい日も多い。あなたの入口では、どちらが重いか、コメントで一言もらえると次の見直しのいい目印になる。
参考にした仕様とドキュメント
- Obsidian Help(公式)— 保管庫が平文Markdownのローカルファイルであることの仕様: https://obsidian.md/help/data-storage
- Obsidian URI(公式)— フォールバックで使う
obsidian://スキームの仕様: https://help.obsidian.md/Extending+Obsidian/Obsidian+URI - Notion API — Request limits(公式)— 毎秒3リクエスト・429の挙動: https://developers.notion.com/reference/request-limits
- Obsidian連携シンプルメモ Obsidian連携の挙動仕様 —
yyyy-MM-dd.md追記とフォールバックの判断基準: https://simplememofast.com/obsidian/
Obsidian連携シンプルメモ
捕まえるのはiPhone、寝かせて整理するのはObsidian。ワンタップで送った1行が、iCloud Drive上の保管庫のノートへローカル追記で積み上がる、起動0.3秒のキャプチャ専用メモアプリ(プラグイン不要)。
App Store:https://apps.apple.com/jp/app/captio%E5%BC%8F%E3%82%B7%E3%83%B3%E3%83%97%E3%83%AB%E3%83%A1%E3%83%A2/id6749649498