다시 유선으로

라즈베리 파이를 이용한 타임 캡슐을 한동안 돌렸으나, 여러 문제점이 있었다.

우선, 너무나 느리다. 라즈베리 파이에 랜선으로 연결해도 최대 초당 8메가바이트 정도의 몹시 느긋한 백업 속도를 보여준다. 그런데 아무것도 안 하고 있는 맥을 한 시간 마다 백업할 때도 타임머신은 100-200메가바이트 정도를 디스크에 쓴다. (무엇을 쓰는 지는 짐작이 가지 않는다.) 여기에 굼벵이 속도가 결합하면 맥이 돌아가는 거의 모든 시간 동안 타임 머신 백업이 진행중이라는 어쩐지 마음이 편치 않은 일이 벌어진다.

게다가 라즈베리 파이가 열심히 디스크를 쓰는 동안 만약 네트워크 연결이 불안정해지면 곧바로 백업 데이타에 오염이 생길 수 있다. 실제로 몇 번인가 백업에 사용되는 Sparse bundle이 맛이 가서 전체 백업을 처음부터 다시 시작해보니 이 장치가 미워지기 시작했다.

결국 긴 케이블을 하나 구입하여 타임머신 하드디스크를 멀리 두는 방법으로 돌아왔다. 재미는 없지만 빠르고 조용하다.


Hammerspoon으로 삽질하기

iOSDevWeekly를 통해서 Hammerspoon이라는 오픈소스 앱을 알게 되었습니다. 이름이 재미난 이 앱은 맥에서 항상 돌아가면서 여러 이벤트나 키보드 단축키에 반응하여 Lua 코드로 작성된 기능들을 실행합니다. 설치하면 멋진 아이콘과 함께 맥 자동화의 방대한 가능성이 열리고 너무나 할 수 있는 것이 많아서 어디서부터 시작해야 하나 막막해집니다. 그 때 생각난 것이

AirPods. iOS와는 잘 붙고 잘 떨어지는데 어째서인지 맥과의 연결이 매끄럽지 못합니다. Toothfairy라는 앱을 써보았지만 별로 도움이 되지 않습니다. 가장 신뢰성 있게 맥과 에어팓을 연결하는 방법은 메뉴바 > 블루투스 아이콘 > AirPods > connect인데, 이거 차라리 유선 이어폰을 꼽고 말지, 라는 생각이 들어서 괴로워집니다. 블루투스는 사람들에게 고통을 주기 위해서 악마가 만들어낸 표준이 아닐까요?

Hammerspoon과 BluetoothConnector로 괴로움을 조금 줄일 수 있습니다. 단축키 하나에 hs.execute()로 BluetoothConnector가 동작하도록 지정해 두는 것이죠.

casc = {"cmd", "alt", "shift", "ctrl"}
hs.hotkey.bind(casc, "A", function()
	hs.execute("swift <path to BluetoothConnector.swift> <AirPods Address>")
end)

casc라는 괴상한 키조합은 Ergodox키보드의 Hyper키를 이용합니다. 이 정도 시점에서 Keyboard Maestro 같은 것을 이용해서 클릭과 메뉴선택을 자동화하면 되는거 아냐? 라는 생각이 슬며시 들지만, 스위프트 스크립트를 돌리는 쪽이 어쩐지 멋지지요.


라즈베리 파이로 타임 캡슐

나의 백업 설정

최후의 방어선 온라인 백업은 Backblaze입니다. 만약 집에 불이 나거나 역대급 천재지변으로 많은 것이 사라져도 작업을 부활시킬 수 있다고 생각하면 1년에 50달러는 아깝지 않습니다. 주로 쓰는 맥은 생각날 때마다 사나흘에 한 번, Super Duper!로 클론을 만들어 둡니다.

디스크 클론이나 온라인 백업은 사실 마음의 평화를 위하는 측면이 더 크고, 실제로 가장 꺼내쓰기 좋은 백업 방식은 역시 Time Machine입니다. 한 시간 단위의 자동 백업 덕분에 절망의 구렁텅이에서 건져 올려진 경험이 다들 한 번 쯤 있을 것입니다.

하지만 무선 주변장치의 시대에 USB 하드디스크를 직접 연결해야 하는 Time Machine은 우아하지 못합니다. 무선으로 우아한 Time Capsule은 출시가 너무나 오래 전이라서 붙어있는 공유기의 성능이 의심스러운 가운데, 급기야 단종되었습니다 (잠시 묵념). 와이파이에 연결된 하드디스크를 하나 만들어서 타임 캡슐 대용으로 써먹을 수 있지 않을까, 연구를 좀 해보았습니다.

Pime Capsule

연구 결과는 라즈베리 파이에 3TB 하드디스크를 연결하여 타임 캡슐로 쓰는 것입니다. 불현듯 Pime Capsule이라는 이름이 떠올라서 흡족했는데 검색을 해보니 역시 누군가가 먼저 생각해낸 이름입니다. 그러니 이 이름은 쓰지 않습니다.

이런, 저런, 고대의 기록들을 보면서 진행하다보니 어마어마한 시행착오가 있었습니다. 가장 친절하고 최신인 포스팅은 How-To Geek의 Justin Pot이 썼습니다.

나의 재료

하나만 빼고 How-To Geek에서 시키는 대로 하면 됩니다. netatalk 디펜던시 설치 부분에서 libmysqlclient-dev는 찾을 수 없다고 나오니 이것만 슬쩍 빼고

sudo aptitude install build-essential libevent-dev libssl-dev libgcrypt11-dev libkrb5-dev libpam0g-dev libwrap0-dev libdb-dev libtdb-dev avahi-daemon libavahi-client-dev libacl1-dev libldap2-dev libcrack2-dev systemtap-sdt-dev libdbus-1-dev libdbus-glib-1-dev libglib2.0-dev libio-socket-inet6-perl tracker libtracker-sparql-1.0-dev libtracker-miner-1.0-dev

이렇게 설치하면 놀랍게도 별 문제 없이 진행됩니다. 뭔가 수상한 것이 가득 섞인 3대째 내려오는 육수 같은 느낌이 들지만 netatalk 설치에 대해서 공부하고 싶진 않으니 그냥 넘어갑니다.

라즈베리 파이가 재부팅 된 경우 간혹 외장하드가 읽기전용(ro)으로 마운트 되어 타임머신 백업이 작동하지 않는 경우가 있는데 이럴 때는

fsck.hfsplus -f /dev/sda2

검사를 한 번 해주고 umount 하고, 다시 마운트 해주면 읽기쓰기(rw)로 제대로 마운트됩니다. (jaysonlorenzen.wordpress.com)

백업 속도

DIY 타임 캡슐 만들기는 라즈베리 파이 3B 모델로 먼저 시작했습니다. 그러나 2.4GHz 와이파이로는 백업 속도가 너무 느려서 맥이 거의 항상 백업 중인 상태가 됩니다. 3B+에 랜선을 꽂아서 쓰면 2-3배 속도 향상이 있습니다. 만, 어라? 무선이 아니네? 음…

외장하드 불면증 해소

용건이 끝나면 바로 잠드는 맥에 직접 연결된 외장하드와 달리, 라즈베리 파이에 연결된 외장하드는 24시간 돌아갑니다. Caleb Wood가 제안한 hdparm은 도시바 하드에서 어쩐지 동작하지 않습니다. hd-idle이라는 프로그램도 시도해보았으나 소용 없습니다. 어지간히 잠자기 싫어하는 도시바 하드를 재우기 위해서 결국 스크립트를 하나 만듭니다.

sudo apt install hdparm sysstat python3

이것을 설치하면 iostat으로 외장하드의 읽기/쓰기 상태를 확인할 수 있습니다. 60초 주기로 iostat을 돌리고 읽기/쓰기 활동이 없으면 외장하드에 잠자기를 먹이는 파이썬 스크립트입니다.

import subprocess

def issue_standby():
    subprocess.call("sudo hdparm -y /dev/sda", shell=True)

process = subprocess.Popen("iostat -y 60 sda", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
while process.poll() is None:
    outstring = process.stdout.readline()
    if "sda" in str(outstring):
        components = outstring.decode("utf-8").split()
        byteread = int(components[4])
        bytewritten = int(components[5])
        if byteread + bytewritten == 0:
            issue_standby()

/home/pi/hdsleep/hdsleep.py에 담고, crontab -e로 crontab에 아래 라인을 추가하여, 부팅하면 위 스크립트가 돌도록 해줍니다.

@reboot python3 /home/pi/hdsleep/hdsleep.py > /dev/null

교훈

장대한 삽질을 거치면서 어째서 똑똑한 사람들은 간편한 문제 해결을 위해서 돈을 아끼지 않는지, 혹은 애플은 어째서 타임 캡슐을 접었는지에 대하여 희미한 힌트를 얻을 수 있었습니다.



수정

2018-06-14 netatalk 버전:
힘들게 직접 컴파일해서 최신 버전의 netatalk를 돌리니 알 수 없는 이유로 몇 번의 백업 이후에 자꾸만 파일 시스템 오류가 나면서 Disk Utility 조차 디스크를 포기해 버립니다. apt install netatalk로 설치하는 오래된 버전을 사용하니 오히려 문제가 안 발생하는데 운 때문인지는 잘 모르겠습니다.


MoonBurst 업데이트

Vapor 2를 이용하는 MoonBurst를 만든 것이 얼마 안 된 것 같은데 Vapor 3.0이 릴리즈 되었습니다. 근본적으로 많이 바뀌어서 Controller를 완전히 새로 작성해야 했습니다. 최근에 나온 멋진 것을 쓰려면 어느정도의 양계질은 피할 수 없나봅니다.

Vapor 3에는 SwiftNIO? Future? 생소한 것들이 많이 도입되어 단순한 블로그 엔진을 업데이트하는 데에도 상당히 애를 먹었습니다. 굉장히 강력한 기능을 가진 다목적 웹 후레임웤을 그저 라우팅하고 HTTPResponse 만들어 돌려주는 데에 쓰고 있자니 핵폭탄으로 파리를 잡는 기분이 들고 뭐 나쁘지 않습니다.



WebtoonCutter 업데이트

macOS에서 긴 웹툰 JPEG 파일을 짧게 잘라서 나눠주는, 웹툰 편집자의 필수 앱! … WebtoonCutter가 0.3으로 업데이트 되었습니다.

3월에 공개한 WebtoonCutter 0.2가 어째서 웹툰 세계에서 돌풍을 일으키지 못하였나? 라는 고민을 하다가, 그래 앱 아이콘이 없어서 그럴거야! 라는 (아마도 잘못된) 결론을 얻었습니다.

iOS 앱 아이콘은 Sketch로 만듭니다만, macOS 아이콘은 어떻게 만들면 좋을까요. Bjango 존잘님의 포스트를 보니 아이콘을 만들 때 3D 렌더링을 하기도 하는군요. 전에 구체적인 목표 없이 Blender를 배우다가 포기한 생각이 나서 이번에는 확고한 목적을 가지고 다시 배워보았습니다.

Blender는 참으로 맥스럽지 않은 UI를 갖고 있어서 아주 기초적인 사용법에 익숙해지는 데도 상당히 오래 걸립니다. 운좋게도, 맨땅에 Blender Tutorial로 검색하여 Blender Guru라는 훌륭한 튜토리얼을 발견하였습니다. 우선, 그가 손쉽게 도너츠나 모루를 만드는 것을 침을 흘리면서 구경했습니다. 그다음, 내가 만들면 왜 어딘가 이상할까 약간의 좌절을 거치면서 튜토리얼을 따라해 봅니다. 무수한 양계질 끝에 구상했던 작두 모양 아이콘을 만들었습니다. 좀 더 잘 만들고 싶지만 이미 비이성적으로 많은 시간을 아이콘 제작에 써버렸습니다. 모자란 아이콘이라도 없는 것보다는 낫겠지요.

WebtoonCutter 다운로드


JSON Feed 발행 시작

피드를 발행하는 웹사이트가 좋다. 특히 비정기적으로 새로운 글이 올라오는 개인 블로그의 경우에는 피드를 구독하여 챙겨보는 것이 생각날 때마다 (보통 생각보다 자주…) 방문하는 것보다 편리하다. 이곳을 돌리는 블로그 엔진 MoonBurst에도 피드 발행 기능을 넣었다.

블로그 포스트들을 JSON Feed로 만드는 것은 Swift 4 부터 가능해진 Encodable 프로토콜을 이용하여 아름답게 해결 할 수 있었다. 이전에 진인웍스 블로그Atom 피드를 만들 때는 XML 템플릿에 문자 바꾸기 방식으로 했는데, 그때보다는 발전한 것 같아서 기분이 좋다.

Conditional GET을 어떻게 지원할까 잠시 고민하다가 발행할 때마다 feed.json을 파일로 만들어두면 골치아픈 부분은 Nginx가 알아서 한다는 상식적인 해결책이 떠올랐다.

그러니 각자 선호하는 피드 리더에 https://joyh.me/feed.json를 추가하면 되겠다. 나는 FeedWrangler를 쓴다.


macOS용 웹툰 이미지 자르기 앱 WebtoonCutter

WebtoonCutter Screenshot 웹툰은 위아래 스크롤에 어울리게 제작되기 때문에 전체 이미지의 높이가 몇 만 픽셀에 달할 정도로 길쭉한 모양을 갖습니다. 이런 이미지를 통으로 보내면 작은 모바일 브라우저들은 힘들어하기 때문에 보통 웹툰 사이트들은 이미지를 수평 방향으로 잘게 잘라서 보내줍니다.

경제만화계의 큰 별 조립식님께서 저스툰에 행동경제학과 관련된 만화를 연재하고 있습니다. 연재 준비가 막바지일 때 저는 놀라운 사실을 하나 알게 되었습니다. 위에서 언급한 잘라진 이미지들을 작가가 편집부에 제공해야 한다는 것입니다. 당연히 서버에서 알아서 자르거나 최소한 편집부에서 뭔가 도구를 이용해서 잘라서 올릴 것이라고 생각했는데 예상보다 원시적인 상황이었습니다.

다행히 호랑 작가님이 배포하는 윈도우용 프로그램이 있다는 것을 전해 들었습니다만, 안타깝게도 조립식 작가님 집에는 윈도우 컴퓨터가 없습니다.

제가 가진 게임용 PC에 프로그램 좀 설치해 달라는 부탁을 받자마자 연재 끝날 때까지 주기적으로 귀찮아 질 것 같은 강한 예감이 찾아왔습니다. 한 번 크게 귀찮고 말 요량으로 도구를 제작하기로 마음먹었습니다. 처음엔 Workflow로 해결 가능한 간단한 작업이라고 생각했으나 커다란 이미지들을 모아서 자르려니 if else 구조가 너무 복잡해져서 그냥 앱을 하나 만드는 쪽으로 방향을 바꾸었습니다.

본격 맥 앱 제작은 처음이라 튜토리얼을 주섬주섬 보면서 WebtoonCutter를 만들었습니다. 단순하고 무지하게 이미지들을 전부 램에 때려 넣고 메인스레드에서만 잘라도 그럭저럭 쓸만하게 돌아갑니다. 요즘 컴퓨터는 참 좋군요. 이미지 자르는 부분보다 맥 앱 샌드박스를 적용하고 코드사인을 하는 데에 더 많은 삽질이 있었습니다. 아직은 앱 아이콘도 없고 허술하지만 소스를 Github에 올렸으니 필요하면 자유롭게 가져다 쓰시면 좋겠습니다.

WebtoonCutter 다운로드


MoonBurst

블로그를 만들었으면 어떻게 돌아가는지 먼저 포스팅 하는 것이 인지상정. MoonBurst는 Swift로 만들어진 블로그엔진입니다. HTTP 관련 복잡한 일은 Vapor에게 맡기고 MoonBurst가 하는 일은 간단합니다.

작성일로 정렬된 글들의 markdown파일을 갖고, 요청된 페이지가 메모리 캐시에 없으면 Cmark를 이용하여 html로 바꾼 다음 헤더와 푸터를 붙여서 캐시합니다. 포스트 초안은 Drafts 폴더에 저장 되었다가 모종의 방법으로 발행이 되면 Posts 폴더로 옮겨집니다. 한 포스트라도 발행하면 모든 캐시가 날아갑니다. Brent Simmons의 Imagining a Node Blogging System for Geeks 에서 많은 힌트를 얻었습니다.

Linode에서 가장 저렴한 ($5/月) VPS에 Ubuntu, Nginx, Vapor, Cmark 만 준비되면 돌릴 수 있으니 제법 포터블하다고… 하기엔 Vapor의 덩치가 좀 크군요.

Swift Package Manager로 Xcode 프로젝트를 만들면 Xcode로 돌리고 디버깅도 가능합니다. 블로그 엔진을 Xcode에서 ⌘ + R로 실행한다니 재미있지요.

이론적으로 막대한 트래픽을 견딜 수 있습니다, 만, 한국말로 쓰여진 텍스트 중심의 블로그가 터무니없는 트래픽을 받을 일은 좀처럼 없겠지요.

YAGNI 정신에 입각하여 200줄 정도의 엉성한 코드로 만들어져서 지금은 기능이 많이 부족합니다. RSS, 페이지 나누기, 각주, 코드 스타일링 등등. 천천히 만들어서 나중에는 오픈소스까지 하고 싶습니다.


블로그 다시 시작

2013년 어느날 문득 이제는 이메일 주소가 전화번호보다 신분 증명과 연락에 더 중요하겠다는 생각이 들었다. 그렇다면 이렇게 중차대한 것을 그저 공짜라고 지메일에 전부 맡길 수는 없다, 곧바로 joyh.me 도메인을 구입하였다. 자 그럼 이제 도메인도 준비 되었겠다, 조만간 내가 존경하는 프로그래머들 처럼 스스로 블로그 엔진을 만들어서 돌려야지. (빨리 감기 5년) …… 이메일 주소만 쓰다가 5년이 훌쩍 지나갔다.

내가 해온 다른 많은 일들과 같이, 마침내 더는 두고 볼 수 없어서 블로그 엔진을 만들었다. 이제 여기에 뭔가를 쓰기 시작하려는데, 특정한 주제가 있으면 좋을 것 같다. 하지만 블로그 시작에 몇 년 걸렸던 내가 Weekly Blog for X 스타일을 쓰기에는 무리겠고, 마침 5년 전쯤부터 가동이 중단된 Joyh의 고품격음악블로그의 정신을 이어받아, 뚜렷한 목적 없이 비정기적인 글들을 쓰고 싶다.




모든 글 보기