메모상자를 대화 상대로 진화시키기
독서는 작가의 말을 듣는 것이다. 만약, 나에게 울림이 있었던 내용을 한 번에 보여주는 무언가가 있다면 얼마나 좋을까? 내가 '결혼'이라는 주제로 대화를 해야 할 때, 내가 말 할 수 있는 참신한 토픽를 알려주는 무언가가 있다면 얼마나 좋을까? 12월 31일에 올해의 나는 무엇을 하며 살아왔는지 한 번에 보여주는 무언가가 있다면 얼마나 좋을까?
주어진 일과 오늘 하루만 충실하게 살면서, 그간 나의 역사를 한번에 보여주는 도구가 있으면 얼마나 좋을까? 이 포스팅은 바로 이 도구에 관한 이야기이다. 나만을 위한 자동화된 시스템이야기다. 일상속에서 나와 공명을 일으키는 사건을 모아서 알려주고, 내 생각의 지향성이 어디를 향하는지 보여주는 환경를 만드는 방법이다.
우연한 발견(세렌디피티)을 필연적 발견으로 만드는 방법
Obsidian특정 구역에 CSS를 적용하는 방법
Obsidian으로 유지 보수 가능한 작업 구조에 대한 팁
Obsidiand에서 DataviewJS 활용 방법과 팁
Obsidian에서 나만의 Javascript 함수로 자동화 하는 방법
기타 등등..
- 제텔카스텐에 대해 들어본 사람
- 제텔카스텐을 시도해본 사람
- Obsidian을 이미 사용하고 활용할 수 있는 사람
니콜라스 루만은 그의 에세이 Communication with SlipBoxes 에서 자신의 제텔카스텐을 소통의 파트너라고 표현했다. 루만이 말하는 '대화'의 필수 조건은 서로 놀랄 만한 요소가 있어야 한다.
1년 내내 똑같은 말만하고, 뻔한 이야기만 하는 사람과 단둘이 저녁식사를 해야 하거나 커피숍을 가야한다면 얼마나 고통스럽겠는가. 상상도 하기도 싫다. '대화'라고 말 할 수 있으려면 새롭고 흥미로운 내용이 있어야 한다.
2024년 신년 프로젝트 기획 회의에서 새로운 아이디어가 꼭 처음보는 아이디어일 필요는 없다. 과거에 중요하게 생각했지만 놓쳤던 아이디어가 될 수 있다. 이미 알고 있는 것도 새로운 관점과 새로운 방법을 더하면 새로운 아이디어가 된다.
루만의 메모상자가 파트너로 진화한 이유 중 하나는 메모 상자를 열어 볼 때 마다, 현재 시점의 내가 잊고 있었던 아이디어를 발견하게 되기 때문이다. 루만의 뇌는 과거와 달라진 새로운 관점으로 과거 아이디어를 재해석한다. 이 과정에서 지금 상황에 맞는 새로운 생각을 불러들였을 것이다. 즉, 메모 상자를 열어 볼 때마다 새로운 것을 발견하고, 새로운 생각을 떠오릴 수 밖에 없었을 것이다.
루만은, 제텔카스텐이 소통의 상대가 되기 위해서, 최소한 몇 년이 지나야 한다고 했다. 루만은 하루에 6장의 메모를 남겼다. 메모상자가 소통의 상대로 진화하는 최소 기간을 3년으로 잡으면 대략 5,000장이 넘어야 한다. 하지만, 내 생각은 이거다. 21c를 살아가는 인간이 어떠한 기능를 넣으면 메모상자가 대화상대로 진화하는 기간을 빠르게 앞당길 수 있지 않을까? 그래서 워드클라우드를 사용하기로 했다.엄밀하게 말하면 키워드 클라우드다.
나는 아래 종류의 파일에 키워드 클라우드를 만들어서 템플릿화 했다.
Inbox : 책, 유튜브, PDF, 웹페이지의 핵심 내용을 정리한 파일
Keyword : 내가 관심있어 하는 키워드(a.k.a 해쉬태그) 파일
Project : 내가 진행중인 프로젝트
(Home)Second Brain 페이지 : 최근 14일 키워드 순위
책을 읽으면 요약이 기록된 파일을 만든다. 요약된 내용중에서 유용하다고 생각하는 내용은 각각의 원자 메모로 만든다. 책이 요약된 파일과 각각의 메모는 의미 키워드를 링크로 입력한다.
책 파일의 키워드 클라우드는 요약된 내용이 기록된 Inbox의 파일과 각각의 Cards에 입력된 키워드를 모아서 보여준다. 중복된 숫자가 많을 수록 큰 글자로 보여준다.
키워드 노트는 자신의 백링크들에 입력되어있는 키워드들을 보여준다. 마찬가지로 중복된 숫자가 많은 키워드는 크게 표시한다.
나는 메모만 하면된다. 이 메모에 어떤 키워드를 넣을지만 고민하면 된다. 옵시디언은 내가 등록한 키워드를 바탕으로 적절한 곳에 관련된 메타포(Metaphor)와 메토니미(Metonymy)를 자동으로 큐레이션 한다. 우리에게 필요한 것은 '어떤 키워드를 넣을 것인가'에 대한 규칙을 정하면 된다.
아래에 있는 코드를 사용한다고 Work Cloud가 만들어 지지 않는다. Obsidian 유저마다 폴더, 링크, 태그, 파일명 등을 사용하는 방식이 다르기 때문이다. 자신의 작업구조에 맞게 수정 하는데 도움이 될 수 있는 뼈대 포인트 위주로 글을 구성했다.
이 글에서 작성한 코드는 배포를 위한 코드가 아니라 개인 목적으로 사용하는 코드라 깔끔하지 않다. 사실 깔끔하게 만들지도 모른다. 나는 개발자가 아니니까.
Obsidian을 어느 정도 능숙하게 사용하는 사람을 위한 글이기 때문에 디테일한 설명은 하지 않는다. 사실, 자세히 다루면 문서의 내용이 너무 길어져서 자세한 내용은 생략했다.
궁금한 사항이 있으시면 편하게 질문을 남겨주세요.
태그 클라우드를 만들기 위해 Dataview를 설치해야 한다.
Dataview 플러그인 설치 -> Dataview 설정에서 Enable JavaScript Queries를 활성화 한다
참고로, 내가 사용하는 태그 클라우드는 여기의 코드를 바탕으로 수정했다. 우리가 할 일은 이 코드를 Obsidian에서 나의 목적에 맞게 적용하는 것이다.
Dataview를 설치하고 Javascript Queries 를 설정했으면 옵시디언 노트에 아래와 같이 dataviewjs 코드를 입력한다.
5-16행 : table는 2차원 배열로 링크와 값이 들어있다.
-> 링크를 쓰는 이유는 워드 클라우드에 보여지는 단어를 링크로 동작하게 하기 위함이다.
-> 값은 링크에 대한 가중치다. 내가 사용하는 용도로 말하자면, 'A'라는 책으로 만들어진 메모들에 붙혀진 해쉬태그의 수를 말한다.
31행 : valueToLevel 함수는 table에 있는 키워드의 값을 1~7범위 레벨로 변경시킨다. 즉, 워드 클라우드의 글자 크기는 총 7개다.
위 Step1.js 코드를 입력하고 미리보기를 보면 아래 그림과 같이 table에 있는 키워드의 링크가 나열된다. 나열된 링크들을 워드 클라우드 형태로 변경시키기만 하면 된다.
DataviewJS의 Table에 입력한 딸기는 80으로 가장커서 cloud7 레벨, 자두는 5로 가장 작아서 cloud1 로 지정되었다. 각각의 링크는 값의 크기에 따라 cloud1 ~ cloud7 라는 속성 값을 가진다. 이를 활용해서 스타일을 지정할 수 있다.
Go, Next Step!
옵시디언은 CSS를 이용해서 개인화된 스타일을 지정 할 수 있다. 파일의 종류마다 각각 다른 스타일을 지정하기 위해 Properties에 cssClasses를 사용 할 수 있다.
CSS Snippet 설정 -> 여기를 참조
cssClass 사용 방법이 잘 나와 있는 문서는 찾지 못했다. �
옵시디언은 cssClasses를 지원해서 파일마다 다른 CSS를 적용할 수 있지만, 문서 내 특정 구역에 CSS를 적용하는 공식적인 방법은 없다. 내가 찾은 편법은 Callout을 이용하는 것이다. Callout의 이름으로 내가 원하는 구역에 커스텀 CSS를 적용할 수 있다.
바로가보자, 아래의 코드를 CSS Snippet에 적용한다.
코드를 모두 설명할 수 없지만,
30~36행 : Cloud1 ~ 7 마다 클자 크기 비율을 조정하고 싶으면 수정한다.
63~69행 : 자신만의 색을 지정하고 싶으면 수정한다.
위 코드로 CSS 파일을 만들고, Obsidian CSS 스니펫을 적용한다. 옵시디언 노트에 아래와 같이 WordCloud 라는 이름의 Callout안에 이전 Step1.js 코드를 넣는다. 아래, step3.txt를 바로 활용해도 좋다.
위 내용을 옵시디언 노트에 입력하고 보기모드를 실행하면 아래와 같이 CSS가 적용되어 링크가 워드클라우드 형태로 보여진다.
자신의 테마에 따라 키워드 클라우드 가로폭이 100%로 꽉 채워지지 않고, 여백이 있을 수 있다. 자신이 사용하는 테마와 콜아웃설정에 따라 CSS를 조정해야 한다. 참고로, 새로운 Vault에서 기본 테마에서 적용한 결과 약간의 여백이 있었다.
참고로 나는 AnuPpucin 테마를 사용하고 Vanilla Normal 스타일 Callout를 사용한다. 이 설정을 추천하는 것이 아니고 참고용이다.
이제 다음으로 할 일은 어떻게 나의 Obsidian 에서 table형태로 가져올지에 대해 고민해야 한다.
이 글을 보고 바로 워드 클라우드를 적용할 수 없는 이유는, 사람마다 Obsidian Vault를 운영하는 방법이 다르기 때문이다. 위의 step3의 DataviewJS 코드에서 5번 행 table 을 만드는 법이 필요하다.
Obsidian 사용자마다 운영하는 방식이 다 다르기 때문에, 간단한 사례만 언급했다.
자료, 정보, 생각, 아이디어들을 담을 수 있는 가장 좋은 그릇은 키워드라고 생각한다. 니콜라스 루만의 제텔카스텐에서 키워드는 그의 색인 방법 중 핵심이었다. 나 또한 키워드가 지식 네트워크에서 허브로 동작하는 강력한 도구라고 생각한다.
하나의 메모에는 다양한 유형의 링크가 존재한다. 이전 메모, 다음 메모, 출처, 외부링크, 관련된 메모, 내용을 보충하는 메모 그리고 키워드가 있다. 일반적으로 키워드는 태그를 사용하지만 나는 링크를 사용한다. 아래 그림은 내가 사용하는 Obsidian Vault의 최상위 폴더다. 키워드는 괄호 닫힘 기호 ) 를 사용한다. 예를 들어서 '제텔카스텐'이란 키워드를 넣고 싶으면 [[) 제텔카스텐]]과 같이 입력한다. 즉, Obsidian 노트의 아웃링크(OutLinks)들 중에서 ')'로 시작하는 링크는 모두 키워드란 의미이다.
※ 당연히, 이렇게 할 필요가 없다. 나는 나의 방식에 맞게 활용법을 고안한 것이다. 자신에게 맞는 방법을 찾으려면, 이미 운영하는 방식의 한계를 인식하고 활용하는 방법을 생각해야 한다. 옵시디언과 같은 무한한 가능성을 가진 프로그램은 한계를 인식하는 것이 중요하다. 기능 추가를 위해 작업 방식을 추가하고 변경하는 습관은 디지털 도구를 활용한 지식관리를 지속하기 힘들게 할 것이다. 뼈대 위에 살을 붙혀야지, 뼈대를 계속 바꾸면 그 시스템은 무너져버릴 것이다. 이것은 개인적인 생각이지만, 평생 자신의 작업 구조를 만들고자 하는 사람들에게 생각해 볼 문제라 남겨보았다.
심플한 형태로 아래와 같이 하나의 마크다운 문서에 수박7개, 멜론6개, 사과5개, 배4개, 감자3개, 고구마2개, 포도1개 링크가 있다고 가정해보자. 아래와 같은 DataviewJS코드를 사용하면 키워드 링크와 수로 만들어진 테이블을 얻을 수 있다.
11번 행의 coutDuplicates는 1차원 배열에서 중복되는 요소의 개수를 세고, [요소, 중복 횟수]형태의 2차원 배열을 반환하는 함수다. step4.js를 실행하면 위 그림처럼 링크 중복 수를 이용한 2차원 배열을 얻을 수 있다. 이제 앞서 만든 코드와 합치면 된다.
지금까지 사용한 코드를 조합해서 아래의 dataviewjs 코드를 사용하면 현재 파일의 아웃링크중에서 ) 로 시작하는 링크로 워드 클라우드를 만들 수 있다.
위 코드에서 27번 라인에서 링크의 aliases를 사용하는 방식으로 코드를 수정하면 워드 클라우드에 보여줄 텍스트를 가공할 수 있다.
오른쪽 그림은 27번 라인의 코드를 result.push(["[[" + key + "|#" + key.slice(2,) + "]]", counts[key]]) 로 수정한 결과다.
이 코드는 하나의 파일의 아웃링크로 워드 클라우드를 만든다. 자신만의 워드 클라우드를 적용하고자 한다면, 어떤 데이터로 테이블을 만들지 결정하고 코드를 작성해야 한다. 백링크의 키워드이든, 특정 태그와 관련된 메모들의 아웃링크 키워드이든, 개인의 목적에 맞게 변경되어야 한다.
하지만, 이렇게 긴 코드를 작성하면 몇 가지 문제가 있다. 첫째는, 긴 코드를 보고 싶지 않다는 것. 두번째는,이미 적용된 노트는 수동으로 수정해야하는 문제점이 있다. 이 문제들를 해결하기 위해 CustomJS를 사용할 수 있다.
나는 다양한 큐레이션을 위해 DataviewJS를 많이 사용한다. DataviewJS로 도배된 유형의 파일도 많다. 하지만 3가지 주요한 문제가 있다. 1-2 항목만 먼저 다루고, 마지막 항목은 따로 다룬다.
보고 싶지 않은 긴 코드
기존 노트에 업데이트 사항을 반영하지 못함
Refresh로 인한 사용자 경험 저하
Obsidian은 DataviewJS, Templater와 같은 플러그인으로 Javascript를 사용해 자신만의 작업구조를 구축할 수 있다. Dataview와 Templater는 각각 개인화된 함수나 데이터셋을 만들고 적용할 수 있다. 공용으로 사용하고 싶은 나만의 라이브러리를 만들고 싶으면 CustomJS 플러그인을 사용할 수 있다.
일반적으로 Templater를 사용해서 옵시디언 파일의 템플릿을 적용한다. 이 경우 템플릿이 적용되어도 이미 템플릿이 적용된 파일들은 업데이트 되지 않는다. CustomJS를 사용하면 이미 템플릿이 적용된 파일도 최신 업데이트를 반영시킬 수 있다. 물론, Javascript를 이용한 무언가여야만 한다.
또 하나의 장점은 더이상 긴 Javascript 코드를 보지 않아도 된다. step5과 같은 긴 코드를 아래 step6.txt처럼 하나의 함수 하나로 해결 할 수 있다.
CustomJS 플러그인을 설치하고, 설정에서 나만의 Javascript 파일 또는 폴더를 지정할 수 있다.
CustomJS 폴더에 LucyKeywordCloud.js 파일을 만들고 아래와 같이 코드를 입력했다.
step6.txt을 Obsidian 문서에 입력하고, step7.js를 CustomJS 에 등록된 파일에 입력하면 step5를 실행한 결과와 동일하게 볼 수 있다.
이제 Obsidian Template 또는 Template이 적용된 문서를 직접 수정하지 않고, LucyKeywordCloud.js 에서 내가 원하는 옵션을 추가하거나, 기능을 추가할 수 있다.
Dataview를 사용했을 때 언급한 3가지 문제 중 2가지는 CustomJS로 해결이 되었다. 마지막 하나가 남았다.
보고 싶지 않은 긴 코드 -> CustomJS로 해결
Clear : 기존 노트에 업데이트 사항을 반영하지 못함 -> CustomJS로 해결
Dataview Refresh로 인한 사용자 경험 저하
Obsidian을 사용하는 가장 큰 이유는 쾌적함이다. 거슬리거나, 방해받는 느낌이 들면 생각을 기록으로 남기는 본연의 일에 집중할 수 없다. 디지털 제텔카스텐을 구성할 때 가장 주안점을 두는 것은 병목 현상을 제거하는 것이다. 크든 작든 어떤 이유로든 방해요소가 없어야 한다.
Dataview, DataviewJS 코드는 주기적으로 Refresh 되면서 최신 데이터를 반영한다. 나는 이 Refresh 되는 시간을 늘리고, Refresh는 수동으로 하도록 설정했다. 아래 그림과 같이 Refresh Interval을 600,000로 수정했다. ms 단위이니 10분에 한 번씩 Refresh되도록 설정했다. (기본 설정 2.5초다.) 10분에 한 번이면 집중에 크게 방해되지 않는다고 생각했다.
수동으로 Refresh 하는 방법은 명령어 팔레트에서 Dataview: Force Refresh All Views and Blocks 를 실행하거나, 해당 명령어를 단축키로 만들어서 사용할 수 있다.
나는 Buttons 플러그인을 다양하게 활용하고 있는데, Buttons 플러그인을 이용하면 커멘트 팔레트에 있는 명령어를 실행시키는 버튼을 만들 수 있다.
Refresh가 필요한 Dataview 또는 DataviewJS 코드를 사용할 경우 위의 버튼을 세트로 사용하면 쾌적한 환경을 구성 할 수 있다.
Obsidian을 사용할 수 있고, chatGPT를 사용할 수 있게 된 시대에 살아가는 것을 행운이라고 느낀다. 이 두가지가 없었다면 생각만 하는 것을 실제로 만들지 못했을 것이다.
이 글을 쓰면서 다양한 유즈케이스를 두고 몇 가지 솔루션을 제안하고 싶었으나, 너무 방대해져서 중심이 되는 포인트만 설명했다. 작업구조를 고려하지 않고 나의 코드를 그대로 보여주는 것은 도움이 되지 않을것이라 생각했다. 다음에는 실제 나의 코드를 설명하거나, 이 글 각각의 단락들에 대한 상세한 활용법에 대해 적어볼까 한다.
꼭 워드클라우드를 만들지 않더라도, 세컨드브레인을 구축하거나, 옵시디언을 유용하게 활용하는 팁등을 뷔페처럼 담았으니 입맛에 맛는 반찬이 있었기를 바랍니다.
혹시, 드시고 싶은 다른 반찬이 있나요? ㅎ