2025년 9월 28일 일요일

TIL: GraphRAG

애초에 연관계가 있는 데이터는 graph 정보까지 같이 저장해서 RAG에 쓰나봄. 그동안은 주로 영상 쪽으로만 봤더니 이런 게 필요하다는 상황 자체를 인지 못했음.


"지금까지 Vector RAG를 살펴보았다면, 이제 또 다른 RAG, Graph RAG에 대해 알아보고자 합니다. 단순히 '의미가 비슷한' 정보를 찾는 것을 넘어, 정보들 사이의 '명시적인 관계'와 '구조적인 맥락'을 활용하여 LLM의 답변 능력을 한 단계 끌어올리는 접근 방식입니다." https://mz-moonzoo.tistory.com/94


개인 위키를 다시 만들 궁리를 하면서 방대하고 다양한 주제로 파편화된 문서들 속에서 관령문서라는 정보를 어떻게 잘 뽑아내야 하는지 아리송했는데 아마 이게 들어맞지 않을까 싶음.

 

https://hub.docker.com/r/apache/age (왜 설명에 이미지가 깨졌는지 모르겠지만 어쨌든 최근까지 업데이트가 있어서 프로젝트는 살아있는 걸로 판단)

저장 쪽을 찾아봤는데 pg_vector와는 또 별개로 구현체가 있음.

https://bitnine.tistory.com/542 보면 둘 다 쓰는 것도 되긴 하나본데 둘 다 설정된 docker 이미지는 아직 못 찾음. https://github.com/apache/age/issues/1121 같이 수요는 있음.

2025년 9월 19일 금요일

쉘 스크립트에서 xargs를 썼다가 파일명에 공백 하나가 아니라 공백 두 개가 있을 때를 완전히 놓친 이야기

xargs를 자주 쓰는 편인데 한동안 잘 썼던 스크립트를 어쩌다 검산할 일이 생겼다.

정제해서 뽑아뒀던 파일 목록이 실제로 잘 있는지 [ -e "$FN" ]으로 검사해봤는데 분명 눈으로는 있는 파일이 스크립트에는 없다고 잡힌다.

맥과 리눅스 환경 차이 때문에 생기는 인코딩 문제일까 해서 convmv도 돌려봤지만 이상 없고.

 

그래서 직접 탭 눌러가며 파일 경로를 자동완성 해보니 그제야 문제가 보였다. 스페이스가 두 개 들어간 파일명이었다.

정제 단계에서 xargs를 거치는 부분이 있는데 이게 공백 여럿을 공백 하나로 바꿔버린 거였다. xargs에 -0 옵션을 주라거나 find 자체에서부터 -print0 옵션을 쓰라거나 하는 얘기들이 있는데 이건 좀 번거로워 보였다.

xargs echo xyz 처럼 STDIN을 xargs 통해서 뭉치던 걸 xargs echo -n | cat - <(echo " xyz")
 처럼 뭉치는 걸로 바꿨더니 증상이 해결되었다. echo 자체가 STDIN을 받아주면 좋을 텐데 그런 건 없는 모양.

2025년 9월 18일 목요일

명세만 작성하면 코드가 뚝딱?

깃허브에서 Spec Kit을 발표했다. 예전에는 Copilot Workspace라고 해서 웹페이지에서 요구사항을 입력하고 실행계획을 짜고 코드를 적당히 만들어서 PR로 제출해주는 기능이 맛보기로 잠깐 나왔다 종료됐는데, 이번엔 그 기조를 유지하면서 '봇에게 일정한 동작 규칙을 파일로 부여하는 게 좋다'거나 '큰 요구사항 하나를 주기보다는 작은 단위로 쪼개서 주라'거나, '봇에게 매번 채팅으로 입력하는 것보다는 작업 지시서를 주고 그걸 따라 진행하게 만드는 게 좋다'는 그간의 활용법을 일정한 틀로 뽑아냈다.

 

Copilot Workspace 당시에 잘 썼던 기억이 있어서 Spec Kit도 좋은 이미지고, vscode에서 개인 프로젝트의 명세만 작성해보았다. LLM의 context 제한에 맞춰 작업 범위를 줄이면 좋고 따라서 에이전트도 역할별로 나누라거나 작업대상 파일을 나누라거나 하는 얘기를 볼 때면 이론적으로 그렇구나 하고 넘어갔었는데 vscode에서 /specify 명령을 여러 번 입력하면서 명세의 틀이 잡혀가는 걸 보니 그게 이런 얘기였구나 싶다.

AI 활용법 경험담 중에 '깃허브 이슈에 할일을 쭉 적어두고 여러 AI CLI의 무료분을 활용해서 자동적으로 처리하게 만든다'는 얘기가 꽤 솔깃했는데 Spec Kit도 비슷하게 '명세만 잘 작성해두고 시작!이라고 외치면 이런저런 AI의 무료분을 활용해서 매일 조금씩 개발'하는 방식으로 쓰일 수 있을까 해서 기대가 된다. (어떤 의미론 '선언적 프로그래밍'이라고 해야 할까?)

 

vscode의 github copilot 창에서 써봤다.

1. 파일 바꾼 걸 매번 승인하라고 뜨는데 채팅 안에서의 자동 동작은 파일이 이미 승인되었다고 전제하고 수행되어서 '이상하네 파일이 없어요'하고 멈추는 경우가 종종 생겼음. 찾아보니  chat.editing.autoAcceptDelay 설정이 0으로 되어서 비활성화였고 1로 바꾸니까 생성 직후에 바로 승인되어서 이어지는 명령들이 부드럽게 진행됨.

2. 작업을 하다 보면 쉘로 npm, npx, git 같은 명령을 수행하게 되는데 이것도 자꾸 승인하라고 떠서 결국 chat.tools.terminal.autoApprove에서 rm 같은 몇 가지만 제외하고 /.*/로 전체 허용하고 말았다. git add && git commit 같이 두 명령을 붙여서 실행하는 경우에 vscode 설정의 설명으로는 git add와 git commit이 허용되어 있으면 당연히 쌍으로 붙은 것도 허용될 것 같았는데 실제로는 매번 물어왔다. 이건 전체허용 뒤에도 여전히 물어서 뭐가 문제인지 오리무중.

3. 자동 생성된 텍스트가 vscode에서 자동으로 formatter 처리되어서 약간씩 문법만 달라지는 경우가 생기는데 이건 설정은 못 봤고(FIXME), 채팅에 '생성한 파일은 lint도 자동으로 한 다음에 커밋'하라고 지시하니가 그렇겠다고 하고 실제로도 그렇게 동작했음 (next.js 초기화 과정에서 선택한 biome를 매번 파일마다 실행하는 방식)

4. @/xyz/AnyFile 같은 경로를 인식하지 못해서 일단 수동으로 상대경로로 다 바꿔줬는데 이건 나중에 일괄로 바꾸면 되니까. 자동 생성 때 뭐가 문제였는지도 나중에. 

 

쭉 진행해보니 자잘한 빨간줄들은 대충 해결하면서 tasks.md의 끝까지 진행했다고 나온다. 막상 하고 보니 UI 쪽은 아예 최초 명세에서부터 빠져 있어서 E2E 테스트와 함께 덧붙여가야 하는데, 이 과정이 모호하게 느껴진다. 아마 채팅창에 직접 이것저것 넣는 부분을 /specify와 /plan으로 녹여내서 명세서를 보완해야 할 것 같긴 한데. 그냥은 반영 안 하고 꼭 spec.md 파일을 직접 열어둔 상태에서 /specify 문구를 넣어야 반영하는 식인가?

 

자동 변경이 아니거나 하다가 잘 안 된 찌꺼기들은 자동 커밋이 안 되고 남는 것 같은데 이게 좀 번거롭다. 커밋하라고 명령하면 커밋 메시지까지 자동으로 만들어서 넣으니까 별 문제는 아니지만.

 

근데 깃허브 코파일럿이 이렇게 쿼터를 많이 주나? 엄청 많이 쓴 건 아닌 것 같지만 그래도 중간에 코파일럿 무료 허용량 다 썼다고 멈출 줄 알았는데, 3시간 좀 넘게 이것저것 해서 next.js로 URL 2개 접속되는 거 볼 때까지 중단없이 잘 진행이 된다.

https://github.com/keizie/wiki-engine

리눅스에서 스팀, 에픽 게임이 된다고?

Fedora Asahi Remix를 통해 M1에 리눅스를 깔아서 쓰면서, Asahi Linux 팀의 소식을 접할 때 '그래픽 드라이버가 많이 발전해서 이제 게임 성능이 아주 좋아졌어요!' 같은 내용을 비교적 자주 보았다.

물론 스팀OS 같이 비-윈도우 환경에서 게임 기동이 된다는 건 당연히 알고 있었지만 Wine이니 CrossOver니 하는 예전의 경험들 때문에 그 과정을 직접 하는 건 아주 번거로울 거라고 생각해 시도도 안 했고 게임이라는 건 응당 윈도우로 부팅해서 한다고만 생각했었다.

하지만 재부팅을 한 번 할 때마다 시간도 걸리고 번거로운 점들이 있어서, 기왕에 아사히 소식을 통해 '스팀을 깔면 된다'더라 하는 얘기들도 있어서 시도를 해봤다. 그리고 마침내 나도 재부팅 안 하고 어지간한 게임을 할 수 있다는 걸 깨달았다.

 

스팀은 애초에 우분투에는 정식으로 APT 저장소가 있고, RPM 쪽도 저장소가 있는 것 같은데 아사히에는 아사히 팀이 직접 관리하는 저장소가 딸려온다. 에픽은 https://github.com/Heroic-Games-Launcher/HeroicGamesLauncher 라고 이름이 살짝 다른 구현체가 존재한다. (GUI는 heroic, CLI는 legendary라는 이름인 게 매력 포인트)

M1의 aarch64 아키텍처는 스팀이 지원하고 에픽은 amd64만 된다. 스팀에서 기나긴 다운로드 시간을 감수하고 몇 가지를 깔아봤지만 규모가 크다 싶은 게임은 그래픽 문제보다는 메모리 문제로 뜨다가 갑자기 끝나버린다. 스팀 OOM이 명시적으로 뜨는 경우도 있고 아닐 때도 있고. 아사히 블로그 글에도 보면 에뮬레이션 비용이 더 들다보니 16기가 램이 필요하다고 되어 있다. 나의 작은 M1은 기본형 8기가 램.

 

그래서 나는 서버로 쓰던 amd64에 스팀과 히로익을 모두 깔아보았다. 램도 그래픽 자원도 풍부하다. 서버 프로세스가 바쁠 때 영향을 받아서 좀 밀린다는 것과 게임용-윈도우가 SSD인 것에 비해 디스크 읽기가 현격히 느려서 로딩이 하세월이라는 것 정도가 아쉽다. 예전 어딘가에서 전설처럼 들은 '서버실 성능 좋은 머신에 가상머신으로 스타 여러 개 깔아서 하고 있더라'는 일화가 생각난다.

또 나는 게임에 트레이너 도움을 받는 걸 즐기는데 https://github.com/DeckCheatz/wemod-launcher 라고 아예 스팀 아래에 트레이너를 끼워넣어서 같이 띄워주는 구현체도 있길래 이 역시 적용했다.

여기까지 프로젝트를 끌고 온 사람들 모두 대단하다. 복어회를 먹기까지 끝없는 시행착오를 반복했을 그 끈기가 여기에도 적용되었을 것이다. 

2025년 9월 10일 수요일

코드가 법이다, 그 후

"옥주현, 수년간 소속사 불법 운영···형사처벌 대상"이라는 제목의 기사를 접했다. "대중문화예술산업발전법상 법인과 1인 초과 개인사업자로 활동하고 있는 연예인은 대중문화예술기획업으로 등록해 활동해야 한다. 이는 필수적 법적 요건으로 위반할 시 형사 처벌을 포함한 법적 제재를 받는다."고 하여, 법령상 특정 업종으로 등록해야 하는데 누락했으니 '불법 운영'이라는 내용이었다. 기사에는 실수로 누락했다는 해명이 있었다. 나는 이 해명이 맞고 기사가 악의적으로 나왔다고 짐작한다. (+ 그 며칠 뒤엔 성시경도 같은 이유로 기사가 났다. 아마 누군가 날 잡아서 이름 있는 연예인들 소속사마다 법인의 업종을 다 추려본 모양)

 

대한민국 법령 체계가 어떤 국가적 개념들이 모인 단일한 뿌리에서 자라나는 게 아니라 실무 주체인 주무기관이 있고 그 주무기관 산하에 소관법령이라는 형태로 나열된다는 걸 깨닫고 놀랐었다. (예: 산림청 소관법령) 그리고 각 주무기관은 자기 사업을 각자 영위하고 거기에 필요한 법률을 각자 정부입법으로 만들어낸다. (중간과정 매우 생략 주의) 이 과정에서 개념적으로는 인접한데 소관이 갈리는 경우가 생기면서 일반인이 보기엔 이상한 경우도 생긴다. (예: 화재는 소방청 소관이지만 산불은 산림청 주관이고 소방청은 협조)

 

이 때문에 일반 시민들은 시시 때때로 바뀌는 법령을 잘 따라가지 못하고 때로는 '담당 공무원이 나보다 몰라서 관련 규정을 차근차근 알려줘야 했다' (예: 캐스퍼 전기차는 경차 아니고 소형차여서 취득세 부과) 류의 경험담이 종종 보인다. 일상생활에 밀접한 세법, 건축법, 소방법 같은 건 각 분야 전문가가 업무적인 고도의 전문성과 함께 법령을 꾸준히 따라가는  전문성도 구비해야 한다.

이 상황에서 공무원을 욕하고 다그친다고 상황이 나아질 것 같지도 않다. 이미 일선 공무원은 주먹구구식으로 업무를 분장하고 혹은 그마저도 잘 지켜지지 않고 한쪽으로 쏠려서 부담을 느껴 면직하거나 목숨을 끊거나 하고, 순환 보직으로 계속 바뀌는 와중에 인수인계라는 게 존재하지 않아서 계속 새 사람이 전혀 모르는 일을 떠맡는다고 한다.

 

나는 옥주현의 소속사도 행정 절차 중 하나를 누락했을 뿐이고 억울한 입장이라고 이해했으므로, 이렇게 억울한 상황이 어떻게 생겼는지 그리고 어떻게 하면 앞으로는 생기지 않을지 궁금했다. 그래서 ChatGPT를 열어서 물어보았다. 다음은 내가 입력한 질의들이고 수정이나 재시도는 없이 한 번에 쭉 진행되었다.

  1.  https://m.entertain.naver.com/home/article/144/0001066309 이 기사를 읽을 수 있나?
  2.  좋아. 나는 실수로 누락했다는 주장이 그럴듯하다고 생각해. 그래서 https://law.go.kr 에서 정보를 찾아봤지. 아래 URL은 검색 결과 페이지야. https://law.go.kr/lsBylSc.do?menuId=9&subMenuId=55&tabMenuId=261&query=%EB%8C%80%EC%A4%91%EB%AC%B8%ED%99%94%EC%98%88%EC%88%A0%EA%B8%B0%ED%9A%8D%EC%97%85#liBgcolor2 https://law.go.kr/LSW/aai/searchList.do?query=%EB%8C%80%EC%A4%91%EB%AC%B8%ED%99%94%EC%98%88%EC%88%A0%EA%B8%B0%ED%9A%8D%EC%97%85&pageNum=1&pagePer=10&searchType=1&modelYn=N&indexNames=&version=&ignoreWord=&keywordSearchYn=N&searchResultLsKndCd=0&firstSearchKeyword=&preSearchKeyword=&searchKndCd=0&mainType=main&detailSearchYn=N&lsChapCd=&lsKndCd=&upCptOfiCd=&cptOfiCd=&startAncYd=&endAncYd=&startEfYd=&endEfYd=&startPrmlYd=&endPrmlYd=&startAdmRulEfYd=&endAdmRulEfYd=&sortCode=0&bylClsCd=&chk= 검색 결과를 보면 일단 법률 수준에서 바로 대중문화예술기획업이라는 키워드가 나오지는 않는 것 같아. 법률 하위의 시행령이나 규칙 같은 걸로 내려가야 실질적인 용어로 검색이 되고. 여기서 내가 너한테 요청하고 싶은 건, 대중문화예술기획업 같은 업종을 등록하는 행정절차가 필요하다는 걸 당사자 시민이 알려면 어떤 문서들을 어떻게 파악해야 하는 건지 니가 심층적으로 검토해줬으면 해.
  3.  너는 애초에 저런 법이 있고, 저런 업종에 대한 등록 의무가 있으리란 걸 인지한 사람을 전제로 하고 그 이후의 실무 절차를 설명하고 있다고 이해했어. 내가 궁금한 건 애초에 저런 법이 있어서 따라야 한다는 사실 자체를 시민 당사자가 어떻게 예상할 수 있냐는 거야. 바꿔 말하면 내가 하고자 하는 행위가 행정적으로 그리고 법적으로 어떤 의미가 있고 어떤 법률에 영향을 받는지 어떻게 알 수 있지?
  4.  좋아. 내가 질문한 방향에 맞게 답이 된 것 같아. 하지만 결국 1) 일반인은 알기 어려운 게 사실이고 2) 정부에서 잘 알려줘야 하고 3) 누락은 여전히 생길 수 밖에 없다 ...라는 거잖아? 니가 정리는 잘 했지만 결국 실상은 매우 실망스럽네. 그럼 가급적 최신 연구나 세계 각국의 실험적 행정을 검색해서 이 점을 개선하려는 시도가 있었는지 봐줄 수 있나?
  5.  다음 단계로 제시된 3가지 중에서 2와 3을 볼 수 있으면 좋겠네.
  6. B를 해줘. A는 B가 끝난 다음에 진행할지 판단할 테니까 다시 물어봐줘.
  7.  B의 결과는 기대보다 미흡하네. A를 보여줘.
  8.  1,2 모두 지금 관심사는 아니야. 오히려 궁금한 건, 위의 yaml을 원래의 법령에서 추출할 때 각 조항을 어떤 문법에 따라 분석하고 yaml로 추출할 조항과 무시할 조항을 선택했는지야.
  9. 좋아. 실제 원문에서 추출한 yaml을 보여줘. 
  10. 명확한 패턴이 있는 조문에서 if-then-else를 뽑아냈다는 건 이해했고 결과도 좋아 보여. 그럼 반대로 원문에는 있지만 yaml 추출에 사용되지 않은 조항이 유의미한 정보를 담고 있는지 경우를 파악할 수 있을까? 그러니까 다시 말하면 yaml에 충분한 규정이 담기지 못하는 경우를 막을 수 있을까? 
  11. 좋아. yaml에 없는 보조 정보가 어떻게 정리되는지 예시를 보여줘.
  12. (이 뒤에 변환 코드까지 달라고 해봤지만 매우 단순한 문자열 감지뿐이어서 참고는 되지 않음) 

 

ChatGPT에 적힌 내용을 모두 신뢰하는 건 아니고 큰 틀에서 어떤 키워드가 있는지만 본다면 Rule as Code (RaC)가 가장 그럴듯하다. 이걸로 검색을 해보면 OECD 문서가 나오기도 해서 아무말이나 지어낸 게 아니라 시중에 진짜로 쓰이는 용어인 것 같다.

개념 자체는 이미 알고 있다. 2006년 출판, 2009년 한국에 번역된 로렌스 레식의 코드 2.0을 당시에 읽었고 그 전에 나왔던 저작들도 접했었다. 또한 오픈소스 동네에서 지내며 실생활에 프로그램이 어떤 영향을 끼치는지도 체감했기 때문에 매일매일 변동증감하는 코드가 그 자체로 곧 규정으로 기능한다는 개념도 쉽게 수용했다. 아마 영어권 화자라면 code라는 말 자체를 프로그램과 규정으로 구분해서 받아들일 필요 없이 그냥 중의적인 표현으로 보았겠지.

ChatGPT와의 대화가 끝으로 가면서는 실제 법률을 어떻게 코드화는지 사례를 보여주기에, 개별 사례보다는 코드화 그 자체의 원리나 패턴을 물었고, 실제 문언에서 if-then-else를 어떻게 뽑아내었는지 설명이 제시되었다. 애초에 법령 자체가 코드라면 이런 변환 과정 자체가 없어도 되고 문맥에 따라 해석이 달라질 수 있는 경우도 더 적을 것이다.

 

코드가 법이란 건 알고 있다. 다음은 법률이 코드여야 한다의 순서인가? 

리눅스에서 지문 인증이 된다고?

예전처럼 리눅스 커널 메일링리스트를 받아보는 건 아니지만 M1에 아사히 리눅스를 깔아서 쓰고 있기도 하고 2025년 여름 즈음으로 어쩐지 커널 버전업이 활발하기도 해서 종종 이런저런 채널로 커널 소식을 접할 때가 있고 마침 유튜브에 이번 주의 그런 영상이 떠서 보았다.

 

https://github.com/xapp-project/fingwit

민트 리눅스라는 배포판에서 위 프로젝트를 기본 내장해서 지문 인식을 도입한다는 모양이다. 민트를 쓰지는 않다보니 바로 확인해볼 수는 없겠다.

기왕 M1에 리눅스를 깔아서 쓰고 있기도 하고 이미 터치ID 딸린 애플 키보드를 하나 가지고 있기도 해서 (맥미니도 그렇고, 맥북도 조개 모양으로 닫아놓고 쓸 때는 외장 키보드에 지문 인식이 붙은 게 좋긴 좋다), 당연히 저 프로젝트 주변으로 터치ID 키워드가 존재할 거라고 생각했다.

 

linux "fprintd" apple touch id -site:apple.com

하지만 놀랍게도 fingwit으로는 전혀 나오는 게 없고, 더 하위의 fprintd로 찾아보니 좀 나오는 게 있다.

https://www.reddit.com/r/archlinux/comments/1mc7wup/touch_id_with_hyprland/?tl=ko

https://itsfoss.com/fingerprint-login-ubuntu/

아마 fingwit 말고도 이미 기존 구현체들이 있어서 우분투 그놈에서는 바로 설정 가능한 모양이다. 적어도 스크린샷으로 보이는 건 그렇다. 민트는 개중 새롭고 가볍고 뭐 그런 구현체를 채택한 거겠지.

 

이렇게 되면 아사히 리눅스 동네에서 fprintd 어쩌구 하는 얘기가 많지 않은 게 오히려 이상하게 느껴진다. 리눅스를 쓰는 집단들 중에 지문 인식기 달린 장치를 보유했을 가능성이 가장 높을 것 같은데. 

2025년 9월 1일 월요일

큰 화면으로 전자책을 보기 위한 모험

주로 전자책에서 TTS를 켜서 귀로 듣는 편이다. 종이책을 직접 다 보기엔 눈도 피곤하고 금방 집중력도 떨어지곤 해서다. 전에는 교보문고 전자도서관 등에서 자치단체 공공도서관을 통해 읽곤 했는데 얼마 전에 밀리의 서재에서 AI TTS라는 게 나와서 목소리 품질이 꽤 좋아져 만족스럽다.

그렇다고 아예 화면을 안 볼 수도 없는 게, TTS가 읽어준 게 억양과 발음이 모호해서 무슨 말인지 직접 봐야 한다거나 앞에서 무슨 말을 했길래 이 대목이 이렇게 된 건지 다시 봐야 한다거나 가끔은 정말 눈으로 직접 보고 싶은 인상적인 대목도 있거나 등등 여러 경우가 있다. 거대한 확대경이 붙은 자동 발화 독서대 같은 거랄까.

 

하지만 전자책 시장의 DRM 정책은 이 과정을 거의 불가능하게 만든다. 안드로이드 기기에서 크롬캐스트를 통해 화면을 공유하면 전자책은 그냥 검게만 나온다. 전자책 화면은 DRM 기술로 제한되어서 다른 기기로 전송할 수 없다는 게 그 이유다.

그래서 방법을 찾다가 결국 안드로이드 기기 자체가 DP Alt로 외부 모니터 출력을 지원하기도 한다는 걸 알았다. 이 기능이 들어가면 기기 가격이 꽤 비싸져서 결국 2025년 하반기인 현재에 2023년 출시 기기를 중고로 사야했다. Y700 2세대.

 

드디어 큰 화면으로 볼 수 있게 되었다. 하지만 노트북에 외장 모니터를 연결하는 거랑은 차원이 달랐다. 안드로이드 기기에 USB-C 케이블로 모니터를 연결하면 그 전의 해상도 설정은 사라지고 무조건 그 모니터가 지원하는 최대 해상도로 설정되었다. 4K 모니터이기 때문에 FHD로 다시 바꿔야 글자를 눈으로 따라읽을 수 있는 정도가 된다. 모니터를 뺐다가 다시 꽂을 때도 그리고 해상도를 바꿀 때도 아마 이 기기는 디스플레이 공간을 완전히 새로 구성하는 것인지 거기에 떠 있는 앱은 몽땅 초기 상태로 되돌아간다. 손이 많이 간다. 2023년 구세대 기기라 그런 건가 하는 생각도 들긴 하는데 OS가 나름 최신이니 그런 문제는 아니겠지.

USB-C로 연결한 뒤에 오디오 출력도 약간 곤란한 문제가 있었다. 기본적으로는 안드로이드 기기 자체 스피커로 소리를 내거나 연결된 모니터 스피커로 소리 내는 선택지가 있는데 나는 이미 그 모니터는 크롬캐스트 기기에 연결하면서 저품질 내장 스피커는 음소거로 바꾼 상태라 모니터로는 소리가 나지 않는다. 얼마 전 가구 배치를 새로 정리하면서 스피커에 입력 포트를 다 써버려서 더 뭘 어떻게 하기도 어렵다. 결국 이미 스피커에 물린 리눅스 장치에서 블루투스 오디오 프로파일을 활성화해서 안드로이드가 블루투스로 소리를 보내면 블루투스 신호를 받은 리눅스가 거기 물린 스피커선으로 소리를 다시 보내는 식으로 일단 정리를 했다.


여기까지만 해도 이미 꽤 번거로운데 밀리의 서재 앱이 한결 더 상황을 곤란하게 만든다. 교보문서 전자도서관 앱이나 교보문서 e북 앱은 안 그런데, 밀리의 서재는 외부 모니터로 띄워두고 TTS를 재생한 상태에서 블루투스로 연결했던 마우스를 연결 해제하면 TTS 재생이 멈춘다. (외부 모니터 없을 때는 멈추지도 않는다) 모니터를 연결하고 나면 기기 본 화면을 터치패드 모드로 바꾸는 기능이 있긴 하지만 마우스랑은 편리함이 완전 다르기 때문에 가급적 마우스를 쓰고 싶었을 뿐인데. (로지텍 마우스라서 연결된 3가지 기기 중에서 잠깐 바꾸면 되는 수준이다) (+ 리모콘 크기의 터치패드 달린 키보드를 찾아봤지만 가격이 싼만큼 품질도 안 좋다고 함)

그래서 이걸 밀리의 서재에 1:1 문의로 넣었더니 '블루투스 기기에 대한 최적화가 진행되지 않았다'고 질문 내용에 대해서는 한 문장으로 답변을 마치고 그 뒤에 이어지는 문장들은 '외부 화면은 차단하고 있는데 왜 그게 된다는지 모르겠고 아마 그 자체가 에러' 운운으로 길게 이어진다. '너 혹시 나의 소중한 DRM을 깨뿌순 거니??' 하는 붉고 굵은 글자가 눈에 보이는 것만 같았다. 어쩌면 다음 밀리앱 업데이트에는 아예 DP Alt 안에서도 못 쓰게 되는 건가 괜히 무서울 따름이다.

'큰 화면으로 보려는 수요가 있다는 걸 무시하지 말아달라'고 다시 답을 달았다. 당신의 눈이 언제까지나 작은 화면의 작은 글씨를 감당해낼 수 있을 거라 장담하지 말라.