소리꽃 KeyBloom TIL 23
첫 출시를 배선하며, 그리고 낸 뒤 터진 것들을 고치며 나온 것들.
오프라인에서 완전할 것
설치해서 쓰는 앱은 인터넷 없이도 그대로여야 한다
웹폰트를 외부 CDN(파일을 여러 지역에 나눠 두고 가까운 곳에서 내려주는 서버망)에서 받아 오게 하면 편하다. 웹에서는 흔한 방식이다. 그런데 설치해서 쓰는 앱이 그러면, 인터넷이 없는 자리에서 글자 모양이 달라지거나 화면이 늦게 뜬다. 공연장에서 쓰는 앱이라 그 자리가 하필 제일 중요한 순간이다.
그래서 폰트 파일을 앱 안에 같이 번들했다(자체 호스팅). 용량이 조금 늘지만 밖에 아무것도 안 물어본다.
설치형 앱을 만들 때는 “인터넷이 끊긴 상태에서 이게 되나”를 기능마다 한 번씩 물어야 한다. 웹에서 옮겨 온 습관 중에 밖을 부르는 게 생각보다 많이 섞여 있다.
곁가지로 알게 된 것 — 영문과 한글에 서로 다른 글꼴을 쓰려고 언어를 판별할 필요는 없다. font-family에 글꼴을 순서대로 적어 두면(폰트 스택) 브라우저가 글자마다 앞에서부터 찾고, 없으면 다음으로 넘어간다. 영문 글꼴에 한글이 없으니 자동으로 갈린다.
돈을 받은 뒤
결제 직후 화면은 전부 다시 그려야 한다
유료를 활성화했더니 워터마크는 바로 사라졌는데, 내보내기 쪽 유료 옵션은 잠긴 채로 남았다. 화면에는 계속 자물쇠가 붙어 있었다.
이유는 화면마다 상태를 보는 시점이 달라서였다. 어떤 것은 매 순간 다시 확인하고, 어떤 것은 앱을 켤 때 한 번 정해 놓고 안 바꾼다. 후자는 결제가 끝나도 스스로 안 바뀐다.
여기서 무서운 건 버그 자체가 아니라 사용자에게 보이는 그림이다. 방금 돈을 냈는데 절반만 풀리면, 사용자는 “결제가 잘못됐나” 아니면 “속았나”를 의심한다. 다른 버그는 불편이지만 이건 신뢰 문제다.
그래서 결제·해제처럼 권한이 바뀌는 순간에는 관련 화면을 하나하나 되짚지 말고 통째로 다시 그리는 쪽이 안전하다. 성능을 아낄 자리가 아니다.
유료 경계는 기술이 이미 그어 준 선에 맞춘다
유료 기능을 어디까지 열지 정하다가, 유료를 앱 버전 전용으로 두기로 했다. 처음엔 웹에서도 일부 유료를 풀 생각이었는데 정리하면서 바꿨다.
근거는 이렇다. 유료의 핵심인 투명 배경 추출과 저지연 라이브 연주는 웹 기술로는 원래 안 된다. 돈 내는 사람은 그 기능 때문에 어차피 앱을 쓴다. 그러면 경계를 “앱이냐 웹이냐”에 맞추는 게 설명하기도 쉽고 예외도 안 생긴다.
유료 경계를 그을 때 임의로 선을 긋는 것보다, 기술이 이미 갈라 놓은 곳에 선을 맞추면 사용자에게 설명할 말이 저절로 생긴다. “앱에서만 되는 기능”은 납득되지만 “웹에서는 일부러 막아 둔 기능”은 반발을 산다.
함께 알아 둔 것 — 라이선스 하나로 몇 대까지 쓸 수 있는지는 앱 코드가 아니라 결제사(Creem) 상품 설정의 활성화 한도에 있다. 한도를 바꾸는 데 앱을 다시 내보낼 필요가 없다. 정책 숫자가 코드 밖에 있으면 이런 자유가 생긴다.
출시하고 나서 안 것
서명했다고 설치 경고가 사라지지 않는다
자동 업데이트를 위해 서명 키를 만들고 서명해서 배포했다. 그런데도 설치할 때 윈도우가 “알 수 없는 게시자”라고 경고했다.
서명이 두 종류인 걸 그때 알았다. 하나는 업데이트 파일이 중간에 바뀌지 않았는지 우리 앱이 검증하는 minisign 서명이고, 다른 하나는 운영체제가 “이 프로그램을 믿을지” 판단하는 코드 서명(Authenticode)이다. 설치할 때 경고를 띄우는 윈도우 기능(SmartScreen)이 보는 건 뒤엣것이다. 앞쪽은 무료로 만들 수 있고 뒤쪽은 인증서를 사야 한다.
경고를 없애려면 돈이 든다. 초기에는 안내 문구로 넘기고, 매출이 붙으면 인증서를 사는 순서로 정했다. 여기서 배운 건 출시 준비를 할 때 “무료로 되는 것”과 “돈을 내야 되는 것”을 미리 갈라 두는 것이다. 둘을 뭉뚱그리면 다 해 놨는데 마지막에 막힌다.
업데이트 경로의 버그는 스스로 못 고친다
릴리스를 냈는데 기존 사용자에게 업데이트 안내창이 안 떴다. 업데이트를 찾긴 찾았는데 “지금 설치할까요”를 묻는 창이 앱 환경에서 안 뜨고 바로 취소로 처리돼서, 업데이트가 조용히 넘어가고 있었다. 앞선 TIL 22의 확인창이 앱에서 안 뜨던 것과 같은 문제였다.
문제는 이 버그가 이미 사용자 컴퓨터에 깔린 옛 버전 안에 박혀 있다는 것이다. 고친 코드는 새 버전에 있는데, 새 버전을 받으려면 옛 버전의 업데이트 기능이 동작해야 한다. 그 사용자는 한 번은 손으로 설치해야 한다.
업데이트·설치·결제처럼 “자기 자신을 갱신하는 통로”에 있는 버그는 다른 버그와 급이 다르다. 원격으로 고칠 수 없고 사용자에게 수동 조치를 부탁해야 한다. 그래서 이 통로는 출시 전에 제일 많이 밟아 봐야 하고, 여기서만큼은 화려한 방식보다 확실히 동작하는 방식을 고르는 게 맞다.
바깥에 내보내는 주소는 안 변하는 이름으로 만든다
판매 페이지의 다운로드 버튼이 설치 파일을 바로 받게 걸어 뒀는데, 파일 이름에 버전 번호가 들어 있었다. 다음 버전을 내면 그 링크가 깨진다.
그래서 설치 파일을 버전 없는 고정된 이름으로도 함께 올리고, 링크는 늘 그 이름을 가리키게 했다. 바깥에 나간 주소는 우리가 회수할 수 없으니, 안 변하는 것으로 만들어 놓고 그 뒤에서 내용을 바꾸는 게 원칙이다.
같은 원칙이 파일 이름뿐 아니라 글 주소·공유 링크에도 그대로 적용된다. 밖으로 나가는 이름에 버전이나 날짜나 순번을 넣는 순간, 나중에 정리할 자유를 잃는다.
요약
- 설치형 앱은 인터넷이 끊겨도 그대로여야 한다 — 밖을 부르는 습관이 웹에서 따라온다
- 권한이 바뀌는 순간에는 화면을 통째로 다시 그린다. 절반만 풀리면 사용자는 결제를 의심한다
- 유료 경계는 기술이 이미 갈라 놓은 곳에 맞춘다 — 설명할 말이 저절로 생긴다
- 서명에도 종류가 있다. 출시 전에 무료로 되는 것과 돈 내야 되는 것을 갈라 둔다
- 자기 자신을 갱신하는 통로의 버그는 원격으로 못 고친다 — 여기만큼은 확실한 방식으로
- 바깥에 나간 주소는 회수할 수 없다. 안 변하는 이름을 먼저 만든다