비주얼 타이머를 개발해서 2019년 6월에 출시했고 1년여 시간이 지나 1만 건 다운로드를 넘겼다. 현재는 목표로 했던 기능은 대부분 구현했고 성능 문제 개선, 사용자 피드백 적용을 고민하고 있다. 개발을 시작하면서 어렴풋이 정한 마일스톤인데 달성해서 기분 좋다.
비주얼 타이머는 남은 시간을 직관적으로 확인할 수 있도록 진행 상황을 표시해주는 시각화 타이머로, 소리, 색상, 문구 등 다양한 개인화 기능을 제공한다. 앱은 React native를 사용했고 공지 등 서버 자원은 Azure Function App, 이슈와 리퍼지터리는 Github에서 관리했다.
개발 동기
생산성 도구를 만들어보고 싶다
프로젝트로 실무 감각을 유지하고 싶다
사이드 프로젝트로 작은 앱은 만들어 봤으니 조금 큰 앱을 만들고 싶다
애플 개발자 등록 비용이라도 벌고 싶다
개발 전
이전부터 생산성 도구에 관심이 많아 만들어보고 싶었다. 타이머는 나도 자주 사용하는 앱 중 하나였고 앱스토어에서 새로운 앱은 없나 종종 검색하기도 했었다. 생산성 앱을 만들겠다는 결정을 하고 나서 다음 과정을 거쳤다.
이전에 시험 삼아 만들어본 팁 계산기 앱에서 얻은 경험을 바탕으로 무슨 앱을 만들지 결정했다.
앱 이름에서 제공하는 기능을 명확하게 알 수 있도록: 별도로 마케팅할 가능성이 작으니까 나는 앱스토어 검색에 최적화하는 쪽으로 기울었다. 앱스토어에서 다양한 키워드로 검색해보니 검색 키워드가 앱 이름이면 유명한 앱보다 먼저 검색 결과에 노출되는 경우가 많았다.
앱스토어에서 검색했을 때 경쟁 앱이 적당히 있어야: 큰 카테고리에서는 검색 순위에 밀릴 수 있어도 조금이라도 카테고리가 좁아지면 상위 순위에 나와야 한다. 검색했을 때 경쟁 앱이 전혀 없다면 사람들이 검색하지 않는 키워드일 가능성도 크다.
기존 앱에서 개선할 만한 부분 확인하기: 다른 앱도 사용해보고 그 앱 리뷰도 보고 업데이트 로그를 보니 이런 앱을 만들며 겪을 피드백과 개선 과정을 이해하는 데 도움이 되었다. (물론 로그를 대충 적는 앱, 이해하기 힘든 리뷰도 많지만)
타이머 자체 기능도 당연히 중요하지만 사소한 개인화 기능을 요청하는 리뷰가 많았다. 그래서 다양한 설정을 할 수 있는 타이머를 만들어보기로 했고 가능한 한 대부분의 설정을 변경할 수 있도록 계획했다. 그 중에도 아동을 대상으로 한 개인화 기능은 유료로 제공해서 수익을 만들기로 했다.
개발 과정
프로젝트는 React native를 사용하기로 했다. 웹앱은 생각보다 느린 반응이 눈에 보여서 Flutter와 RN 사이에서 고민했는데 지금은 많이 개선되었지만 당시에 Flutter로 만들었다는 앱을 써보니 웹앱보다는 빠르지만 약간 느린 인상을 받아서 RN으로 결정하게 되었다.
Expo도 편의 라이브러리가 많아서 좋지만, 결정 당시에는 한국어 입력 문제가 있어서 바로 react native를 사용하기로 했다.
처음에는 공통으로 사용하는 컴포넌트를 만들어서 다른 프로젝트를 하게 되더라도 활용할 수 있도록 계획을 세웠다. 설정 저장/불러오기나 국제화 지원과 같이 전역에서 사용되는 라이브러리는 큰 문제 없이 계획한 방식대로 만들 수 있었다. 다만 생각처럼 되지 않은 부분은 표현 컴포넌트였다. RN에서 기본적인 컴포넌트를 많이 지원하긴 하지만 iOS 스타일의 크고 작은 표현 컴포넌트는 다른 라이브러리를 사용하거나 직접 만들어야 했다. 공개된 라이브러리가 많이 있지만 필요한 기능은 극히 일부인 데다 스타일 일관성을 맞추는 노력이 생각보다 많이 필요로 해서 직접 만들게 되었다. 이렇게 부분적으로 기능하는 컴포넌트는 당장에는 잘 동작하지만, 특정 상황만 고려해서 만든 탓에 다른 프로젝트에서 쓰기엔 조금 부족했다.
디자인은 iOS 기본 컴포넌트를 거의 따라가서 큰 막힘은 없었다. 아직도 약간씩 어색한 부분이 있지만 대부분 컴포넌트가 나름 비슷하게 동작한다. 그 외는... 좀 대충 만든 부분도 있지만 그래도 동작은 하니까 일단 뒀다. (타이머 순서 바꾸는 부분이라든지 매우 안 이쁘다.)
기능 중 완료 이미지 모음 리소스를 만드는 데 가장 많은 시간이 걸렸다. 완료 이미지 모음은 동물 등 이미지와 함께 이미지에 맞는 효과음이 타이머 완료 시에 표시되는 기능이다. 적합한 저작권을 가진 리소스를 찾고 정리해서 넣는 과정에 많은 시간을 썼다. 직접 일러스트라든지 그릴 수 있었다면 시간을 좀 더 줄일 수 있었을까.
서버는 Azure Function App을 사용하고 있는데 공지를 그냥 JSON 형식으로 내려주는 수준이라 별도의 데이터베이스 없이 작성했다. 그런 덕분에 응답도 빠르고 비용도 안 들어서 지금까지 그대로 유지되고 있다.
개발은 출시까지 4개월 정도 걸렸는데 개발은 1달 반에서 2달 정도 걸렸고 나머지는 앱 리소스(소리 효과, 이미지)와 앱스토어 메타 정보(앱 소개, 정책 등)을 준비하는 데 시간을 썼다.
개발이 완료된 후에는 이상한모임 분들에게 테스트를 부탁해서 진행했다. 이 과정에서 앱이 어떤 맥락과 흐름에서 동작해야 하는지 피드백을 많이 주셔서 큰 도움이 되었다.
마케팅
홍보는 페이스북 그룹, 이상한모임 채널, 클리앙, 내 소셜 계정에서 진행했다. 소개 글과 함께 프로모션 코드도 나눴다. 다운로드 수는 확실히 이런 홍보를 할 때마다 오르긴 했지만 액티브 유저 수 추세는 큰 변동이 없이 항상 일정하게 증가했다. 돈을 쓰지 않아서 그랬을까, 프로모션 코드도 돈이라고 생각한다면 업데이트마다 꽤 지출했다고 볼 수 있겠다.
페이스북 타깃 광고는 제공하는 도구로 확인해보니 적어도 광고 본 사람 중 30% 이상은 받고 결제해야 손익 분기인 비용이라 집행하지 않았다...
그래도 적은 수지만 앱스토어에서 검색해 받는 사람도 꾸준히 있다. 메타 정보를 작성하는 일도 생각보다 쉽지 않았다. 업데이트마다 조금씩 변경하고 있지만, 검색 지표가 명확하게 공개돼 있지 않아서 솔직히 잘 모르겠다. (어떤 키워드로 검색했는지 등)
개선과 피드백
앱 출시 이후 성능 문제를 계속 개선하고 있고 사용자 피드백도 그 과정에서 반영하고 있다. 초기에는 불안정하게 동작하는 부분이 있어서 못쓰겠다는 리뷰 받고 참담했는데 부지런히 안정화했다. 이 과정에서 Xcode의 프로파일링 도구가 큰 도움이 되었다.
피드백은 앱 내 이메일 보내기로도 오지만 대부분은 앱스토어 리뷰로 남긴다. 만족도를 물어보고 이메일로 보낼지 앱스토어 리뷰로 보낼지 구분하겠다고 백로그에 적어두고는 그동안 잊고 지냈... 그동안 작은 피드백도 많이 받았는데 이미 개인화에 중점을 두고 만든 덕분에 대부분 피드백은 간단하게 추가할 수 있었다.
다만 구조적인 변화가 필요한 피드백은 백로그로 쌓고 있다. 가령 여러 타이머를 동시에 사용하거나 순서대로 동작하도록 하는 방식은 현재 구조에서는 처음에 염두에 두지 않았던 부분이라 구현이 어렵다. 좀 더 정리해서 차기 버전에서는 구현할 수 있는 구조로 가고 싶다.
아쉬운 점
사용자 추적
앱스토어커넥트에서 제공하는 분석 도구는 피상적인 수준이라 실제 데이터를 볼 수 없다는 점이 늘 불편하다. 실제 사용은 앱을 실행했을 때 버전 확인과 공지 데이터를 받기 때문에 애저 펑션앱 사용량으로 확인할 수 있지만, 여전히 부족하다. GA 등 추적 도구를 사용해서 어떤 기능을 주로 사용하는지 등 데이터를 모으면 개발 방향을 잡는 데 더 도움이 될 텐데 그러지 않았다. 처음부터 이 부분이 중요하다는 이야기를 들었는데도 지금까지 적용하지 않은 것은 정말 반성해야 한다.
약한 수익 모델
현재는 인앱 결제로 수익이 발생하고 있다.
완료 시 나오는 이미지 모음
개발 지원하기
처음 앱을 기획할 때는 아동용 타이머로 방향을 잡고 있어서 완료 이미지 모음을 인앱으로 제공했다. 앱을 공개한 이후에는 아동용 타이머 외에 일반 용도로 많이 사용하길래 커피 지원하기 같은 개발 지원 항목을 추가했다. 한국에서는 개발 지원이, 미국 스토어에서는 이미지 모음 결제가 많다. 내가 쓰는 시간을 생각하면 아직도 많이 부족하지만 그래도 앱개발자 등록 비용은 해결할 수 있게 되었다.
다음 버전에서는 인앱을 정리하고 유료로 전환하는 것을 고민하고 있는데 이런 결정은 어떻게 해야 하는 걸까, 사용자에게 무슨 가치를 주고 있는지, 그 비용은 어떻게 결정해야 할지 배우고 싶다.
안드로이드 지원
처음에는 RN이면 안드로이드 지원은 저절로 되겠지 생각했는데 실제로 돌려본 결과는 처참했다. iOS는 그래도 작게나마 해본 경험이 있어서 트러블슈팅도 큰 문제가 없었는데 안드로이드는 구동 자체도 쉽지 않았다. 차기 버전에서는 안드로이드도 같이 지원하고 싶다.
자동화와 테스트 부족
지금 앱은 일부 로직에 유닛테스트가 있지만, 아직 많이 부족하고 자동화도 없다. 앞으로 개선해야 하는 부분이다.
잘한 점
React Native
React로 많은 프로젝트를 해보지 않았는데 이 앱을 만들고 관리하면서 많이 배웠다. 정말 매달 새로운 기능과 라이브러리에 눈과 머리가 바쁘다. 출시 이후에도 react에 hook도 들어오고 많은 새 기능이 들어오고 있는데 업데이트 과정에서 조금씩 적용하고 개선하며 많이 배우고 있다.
확실히 js나 react에 경험이 있다면 큰 문제 없이 RN 프로젝트도 꾸릴 수 있다. 물론 타깃 플랫폼도 잘 알면 더 편하다. 특히 기능이나 용어는 각 타깃 플랫폼에서 제공하는 용어로 많이 설명되고 있어서 안드로이드와 iOS의 용어 차이를 알아두는 것도 도움이 됐다.
다국어 지원
처음부터 고려하지 않았다면 꽤 번거로운 작업이 되었을 텐데 지금 와서는 잘 한 결정 중 하나다. 현재 영어랑 한국어만 지원하지만 지금까지 지역 통계를 보면 확실히 도움이 되었다. 마케팅도, 프로모션도 대부분 한국에 했는데 다운로드 비율이나 수익 비중은 미국이 더 크다.
우선순위와 시간 관리
혼자 하는 프로젝트는 내 마음대로 할 수 있다는 장점이 있지만, 한편으로는 정말로 제한적인 시간 자원을 어떻게 관리하는가 하는 점이 정말 큰 어려움이었다. 특히 내가 안 하면 아무것도 진행이 되지 않는다는 점이 당연하지만 피곤했다.
다행히 처음에 계획한 최소 기능은 대부분 만들어냈고 학업 하면서도 크고 작은 개선 작업을 진행했다. 출시 이후에는 적은 분량이라도 한 달에 한 번은 업데이트 할 수 있도록 노력했다. 지금까지 받은 피드백 중 적용된 것은 일부지만 개선 과정에서 좋은 리뷰도 많이 받을 수 있었다.
이 이전에도 앱을 만들어본 경험은 있지만, 하루 정도면 만들었던 수준의 앱과는 경험의 깊이가 달랐다. 특히 앱은 웹과는 확실히 다른 맥락과 인터페이스를 갖고 있었다. 앱을 출시하는 경험은 평소라면 별 생각 없이 쓰던 수많은 앱을 교과서처럼 보이게 했다. 아름답고 멋지고 편리한 기능을 모두 앱에 적용하고 싶었지만 작아도 정교한 기능은 보는 것과 다르게 훨씬 많은 시간을 필요로 했다. 쉽진 않겠지만 다음엔 그런 부분도 꼼꼼하게 구현해보고픈 욕심도 생겼다.
지금 이렇게 되돌아보면 잘한 점보다 부족한 점도 많고 배워야 할 부분도 산더미다. 그래도 부족한 부분이 많지만 유용하게 사용하고 있다는 리뷰 하나하나가 큰 힘이 됐다. 앞으로 개선될 타이머와 만들어갈 많은 프로젝트에서도 이런 경험이 거름이 되었으면 좋겠다.
const theme = localStorage.getItem('theme');
if (theme) {
document.documentElement.setAttribute('data-theme', theme);
}
시스템 설정을 확인하기 위해서 window.matchMedia() 함수를 사용할 수 있다. CSS의 미디어 쿼리가 현재 페이지에 해당하는지 확인하는 기능을 제공한다.
function toggleTheme() {
// 저장된 값이 없다면 시스템 설정을 기준으로 함
const currentTheme = localStorage.getItem('theme')
|| (
window.matchMedia("(prefers-color-scheme: dark)").matches
? 'dark'
: 'light'
);
const newTheme = currentTheme === 'dark' ? 'light' : 'dark';
// 최상위 엘리먼트에 설정, 로컬 스토리지에 설정을 저장
document.documentElement.setAttribute('data-theme', newTheme);
localStorage.setItem('theme', newTheme);
}
만약 미디어 쿼리의 결과를 동적으로 반영해야 하는 경우에는 window.matchMedia()의 반환값인 MediaQueryList에 이벤트 리스너를 추가할 수 있다.
const mql = window.matchMedia("(prefers-color-scheme: dark)");
mql.addEventListener((e) => {
if (e.matches) {
// 해당 미디어 쿼리가 참인 경우
} else {
// 해당 미디어 쿼리가 거짓인 경우
}
});
동네가 그렇게 치안이 나쁜 것은 아니지만 가끔 동네 페이스북 그룹이나 넥스트도어 같은 곳에서 접하게 되는 크고 작은 사건 탓에 집을 비울 때 조금 걱정이 있었다. 그나마 보안 카메라를 설치하고 나서는 불안감은 줄어들긴 했지만 누가 봐도 집에 있는지 없는지 밖에서 판단할 수 없었으면 싶었다. 이전에 코스트코에서 구입한 WeMo 플러그로 조명을 켜고 끌 수 있었지만 아무래도 연결하는 조명이 스탠드 정도라서 만족스럽지 않았다. 그래서 기존 벽 스위치를 교체하는 방법을 알아보다가 wifi 스위치를 구입해서 설치하게 되었다.
물론 고민하고 찾아볼 필요 없이 기술자를 부르면 금방 끝날 일이다! 전기 공사는 정말 위험할 수 있는 일이기 때문에 무슨 작업이 어떻게 필요한지 정확히 모른다면 전문가를 찾는 것이 맞습니다.
자격과 규정 확인하기
캘리포니아도 전기 공사를 하려면 자격이 필요하다. 다만 프로젝트의 크기가 자재와 인건비 포함 $500 미만인 경우에는 CA B&P Section 7048 (Small Operations)에 따라서 자격 없이도 가능하다. 스위치 4개 교체하는 수준이고 유튜브 영상 보고 크게 시간 걸리는 작업도 아닌 것 같아서 직접 해야겠다고 판단했다.
미국은 National Electrical Code(NEC)를 주기적으로 발행하고 그 NEC를 기준으로 각 주마다 전기 공사 규정(electrical code)이 존재한다. 각 주, 지역마다 적용되는 전기 공사 규정이 다르고 규모에 따라 허가(permit)가 필요한 경우도 있다. 전기 기술자를 통해 설치한다면 이 부분도 확인해달라고 하면 된다. 나는 내가 설치하려고 했기 때문에 시청에 문의했고 단순 스위치 교환에는 별도의 허가 없이 가능하다는 답변을 받았다.
중성선 확인하기
한국과 미국은 전력 공급 방식이 다르다. 한국은 주로 단상 2선식으로 220V만 공급되는 것에 비해 미국은 단상 3선식으로 110V와 240V가 공급된다. 일반적으로 벽 플러그는 110V만 쓸 수 있지만 전기 오븐과 같이 전력을 많이 쓰는 가전은 240V로 연결되어 있다.
스위치도 어떤 스위치냐에 따라 조금씩 다르지만 Wifi 단일 스위치라면 일반적으로 다음 4개의 선을 연결해야 한다.
Line/Hot wire (주로 빨강 또는 검정): 전력 공급 선
Load wire (주로 검정): 설치된 기기(전등)에 연결된 선
Ground wire (주로 노출된 구리선 또는 녹색): 접지선
Neutral wire (주로 흰색): 중성선, 회로를 완료할 수 있도록 배전반에 연결된 선
스위치의 역할은 공급되는 전력을 전등에 연결하거나 차단하는 역할을 한다. 스위치가 전기를 연결하게 되면 전기가 전등을 거쳐 다시 전력이 공급되는 곳으로 돌아간다. 회로가 연결되는 것으로 전력은 공급되고 전등은 불이 켜진다.
기계식 스위치는 끄면 물리적으로 전등에 전달되는 전기를 끊게 된다. Wifi 스위치는 끈 상태에서도 전력이 계속 있어야 하기 때문에 스위치를 켜지 않은 상태에서도 회로가 연결되어 있어야 한다. 그 회로를 완료하는 역할을 중성선이 수행하게 된다. 그래서 중성선 여부가 중요하다.
중성선은 2009년 NEC 이후에 필수가 되었기 때문에 최근에 지어진 건물이라면 중성선이 존재할 가능성이 높다. 만약 중성선이 없다면 중성선을 설치해야 하는데 이 경우는 기술자가 필요하고 이런 추가 작업은 대부분 허가가 요구된다. 대안이라면 중성선을 필요로 하지 않는 wifi 스위치를 찾아야 하는데 그런 제품은 자체 베터리를 사용하며 UL 인증 제품이 아닐 수 있으니 유의해야 한다.
스위치 결정하기
시중에 나와있는 스위치가 상당히 많고 리뷰도 다양하다. 저렴한 제품도 많지만 대부분 저렴한 이유가 있다. UL 인증을 받은 제품인지 확인하는 것이 가장 중요하다. 이 인증이 없다면 집 보험에 문제가 생길 수 있다. UL listed인지 구입 전에 꼼꼼하게 확인해야 한다. 저렴한 제품 중에는 UL listed라면서 실제로는 그렇지 않은 경우도 있다고 하니 주의해야 한다.
어떤 네트워크를 사용하는지도 염두해야 한다. Wifi 외에도 Z-Wave, Zigbee 등 다양한 규격이 존재한다. 만약 Ring 등 보안 시스템이 있고 거기에 연결해서 쓴다면 호환 여부도 확인해봐야 한다. 스위치 설치할 곳의 wifi 신호도 염두해야 한다. 신호가 약하면 당연히 잘 동작하지 않는다.
구글 홈이나 아마존 에코 연동 여부도 확인해야 한다. 사용하는 제품이 있다면 연동을 지원하는지 확인한다.
어떤 스위치를 교체할지도 미리 고민해야 한다. 스위치 종류는 단일 스위치, 여러 위치에서 끄고 켤 수 있는 3 way 혹은 4 way 스위치, 밝기를 조절할 수 있는 디머 스위치(dimmer) 정도로 구분된다.
Lutron, GE, TP-Link를 후보로 두고 리뷰를 보다가 TP-Link를 골랐다. Lutron도 유명하다는데 처음 들어봤고 GE 제품은 Z-wave에 더 중점을 두고 있었다. TP-Link는 wifi 기반이고 리뷰도 크게 나쁘지 않은 데다 앱도 괜찮았다. tplink-smarthome-api 같은 라이브러리도 있어서 나중에 필요에 따라 제어하는데 더 편리할 것으로 보고 결정했다.
필요에 맞게 TP-Link Kasa HS200, HS220 v2 제품을 구입했다.
설치하기
설치에는 다음 도구가 필요했다.
스크류 드라이버
와이어 넛 (wire nuts): 결선에 필요한데 TP-Link 제품에 포함되어 있었음
전기 테스터(electrical tester): 비접촉식 제품이나 멀티미터를 사용
다용도 칼: 스위치 패널과 페인트가 붙어 페인트가 흉하게 뜯어질 수 있어서 분리 전에 패널과 벽 사이를 칼로 그어준다.
스위치
먼저 전력 차단기를 내려야 한다. 차단기에 어느 구역 차단기인지 표시가 되어 있다면 확인하고 내린다. 없다면 전등 스위치를 켜놓고 차단기를 내려 전등이 꺼지는지 확인한다.
드라이버로 나사를 풀고 스위치 패널을 연다. 전기 테스터로 아직도 전력이 흐르는지 확인한다. 스위치를 분리하고 wifi 스위치를 연결한다.
선은 끝을 맞춰 나란히 잡고 와이어 넛을 끼워 돌린다. line/load은 구분 없이 꽂으면 된다. 와이어 넛이 더이상 돌아가지 않을 때까지 돌리면 된다. 연결한 후에 선의 노출 부분이 밖에서 보이지 않아야 한다.
선을 잘 정리해서 스위치를 제자리에 부착한다. 선이 접히지는 않았는지, 닿으면 안되는 선에 닿지는 않았는지 확인하고 잘 넣는다. 차단기를 올리고 제대로 동작하는지 확인한다.
디머 스위치는 line/load 구분이 필요하다. 기존 연결된 스위치를 참고하면 도움이 된다. 일반 스위치와 동일하게 차단기를 내리고 테스터로 확인하고 작업을 시작한다.
TP Link 앱을 설치하고 wifi에 등록하면 끝난다.
활용
TP Link 앱도 생각보다 깔끔하고 큰 문제 없이 잘 동작했다. 기존 사용하던 WeMo는 앱이 정말 불안정하고 wifi가 오락가락할 때가 자주 있었는데 TP Link는 훨씬 깔끔하고 잘 동작한다. 게다가 집에서 구글 홈을 사용하고 있고 WeMo를 가끔 못찾을 때가 있어서 답답했는데 스위치는 잘 동작해서 좋다.
집에 연결된 모든 장비는 slack에도 hubot으로 제어할 수 있는데 새 스위치도 쉽게 연결할 수 있었다.
자는 시간을 제외하고는 대부분의 시간을 크고 작은 화면을 본다. 특별한 내용이 없더라도 화면을 스크롤 하는 일이 일상이다. 누군가와 함께 앉아 있더라도 잠시나마 서로 화면을 보느라 조용해지는 시간도 종종 있다. 그렇게 많은 시간을 쓰고 있다는 것을 나도 잘 알지만, 장점이 있다고만 생각해왔었다. 새로운 정보를 빠르게 습득할 수 있다든지, 잠깐 물 뜨러 가면서도 비는 시간 없이 무언가를 볼 수 있다는 점에 내가 자투리 시간을 잘 활용하고 있다는 기분도 들었다.
그래서 디지털 미니멀리즘이라는 제목만 보고도 대충 덮어놓고 지냈던 내 습관을 마주해야 했다. 가끔 스마트폰을 너무 많이 들여다보면 며칠 쉬어보기도 했지만, 순간뿐이었다. 스크린 타임을 설정하고도 15분 제한 무시를 수시로 누르다가 결국은 기능을 꺼버린다. 나는 어째서 절제하지 못하는가, 그런 죄책감을 느끼면서도 또다시 수시로 화면을 봤다.
디지털 미니멀리즘에서는 이런 중독에 가까운 증상이 주의력을 기반으로 움직이는 기업을 문제로 삼았다. 프로덕트나 서비스에 오래 체류할수록 수익이 느는 기업은 어떤 방식을 사용해서든 그 시간을 늘리려고 한다. 마치 슬롯머신을 돌리는 것처럼 스크롤을 돌리면 새로 고침과 함께 내가 원하는 정보가 튀어나올 것처럼 디자인했다는 것이다. 단순히 비약이라고 하기에는 내 행동을 돌아봤을 때 그렇게 사실이 아니라고 단정적으로 말하긴 어려웠다. 나도 아침부터 저녁까지 스크롤을 손으로 당겼으니까. 당길 때마다 달라지는 타임라인과 뉴스피드를 보기 바빴으니까. 내 주의력을 내어주고 쓸 만큼 나에게 도움이 되는가 생각해보면 솔직히 부끄러운 마음만 든다.
책에서는 철저하게 멀어진 후에 다시 각 도구와 서비스의 가치를 세심히 평가하고 삶에 도입하는 방식을 이야기한다. 예를 들면 트위터는 일주일 또는 하루 중 정해진 시간만 확인한다. 그리고 정말로 필요한 정보만 볼 수 있도록 세세한 필터를 지정한다. 이런 방식은 이렇게 해야 한다고 정해진 것이 아니라 정말 자신에게 필요한 것인가를 심사숙고하는 과정에서 결정되어야 한다고 이야기한다. 책에서도 다양한 사람들의 다양한 접근 방식을 설명하고 있고 자신에게 맞는 방법을 고를 수 있도록 돕는다.
물론 이런 책 한 권 보고 짠! 하고 바뀌진 않았다. 나도 책에서 제안하듯 단호하게 끊지 못했다. 책을 덮고 나서도 여러 차례 시도했는데 잠깐의 틈이라도 생기면 화면을 보는 내 모습에 좀 더 심각성을 느꼈다. 내 산만함을 정돈할 좋은 기회가 되었으면 좋겠다.
사용자 인터페이스(User Interface, UI) 디자인은 사용자가 할 작업을 예측해서 인터페이스의 엘리먼트에 쉽게 접근하고 이해할 수 있는가, 그리고 손쉽게 사용할 수 있는가에 중점을 둡니다. UI는 상호작용 디자인, 시각 디자인, 정보 아키텍처의 개념을 통합하고 있습니다.
인터페이스 엘리먼트 선택
사용자는 이미 특정 방식으로 동작하는 인터페이스 엘리먼트에 익숙합니다. 그러므로 그 사용자 경험에 일관성이 있어 사용자가 예측할 수 있는 엘리먼트와 레이아웃을 선택하도록 합니다. 그런 선택은 사용자가 업무를 능률적이고 만족스럽게 완료할 수 있는데 도움 됩니다.
인터페이스 엘리먼트는 다음과 같지만, 이 목록이 전부는 아닙니다.
입력 컨트롤: 버튼, 텍스트 필드, 체크박스, 라디오 버튼, 드롭다운 메뉴, 목록 박스, 토글, 날짜 필드
탐색 컴포넌트: 브레드크럼, 슬라이더, 검색 필드, 페이지네이션, 태그, 아이콘
정보성 컴포넌트: 툴팁, 아이콘, 프로그레스 바, 알림, 메시지 박스, 모달 윈도우
컨테이너: 아코디언
내용을 표시할 때 여러 엘리먼트를 사용해야 적절한 예도 있습니다. 그런 상황에서는 균형을 찾는 것이 중요합니다. 예를 들어서 엘리먼트를 사용했을 때 공간을 절약할 수 있는 예도 있지만, 사용자에게 드랍박스 메뉴 또는 해당 엘리먼트에 무엇이 있는지 추측하도록 강제하기 때문에 정신적인 부담감을 줄 수도 있습니다.
인터페이스 디자인의 모범 사례
모든 디자인은 사용자를 아는 것에 근간을 둡니다. 그 이해는 사용자의 목표, 기술 수준, 선호도와 경향도 포함합니다. 사용자를 이해한 다음에는 인터페이스를 디자인할 때 다음 항목을 염두에 둬야 합니다.
인터페이스를 단순하게 유지합니다. 모범적인 인터페이스는 사용자에게 거의 보이지 않습니다. 불필요한 엘리먼트는 피하고 명확한 언어로 레이블이나 안내를 넣어줍니다.
일관성을 유지하고 일반 UI 엘리먼트를 사용합니다. 일반 엘리먼트를 UI에서 사용하면 사용자는 더 편하게 느끼고 더 빨리 적응할 수 있습니다. 언어, 레이아웃, 디자인을 아우르는 일정한 패턴을 만드는 일도 중요합니다. 이런 패턴은 사용자가 더 효율적으로 도구를 사용하는 데 도움이 됩니다. 사용자가 한번 사용법을 습득하면 같은 프로덕트의 다른 부분에서도 그 사용법을 동일한 방식으로 쓸 수 있어야 합니다.
레이아웃의 목적이 명확해야 합니다. 항목과 페이지의 공간적 관계를 고려합니다. 그리고 중요도를 기준으로 페이지의 구조를 잡아야 합니다. 주의 깊게 배치된 항목은 사용자가 가장 중요한 정보 조각에 집중하는 데 도움이 됩니다. 또한 빠르게 살펴보는 일도 쉬워지고 가독성도 개선됩니다.
전략적으로 색상과 텍스처를 선택합니다. 사용자가 각 항목에 집중하거나 집중하지 않도록 색, 빛, 대조나 텍스처를 활용할 수 있습니다.
타이포그래피로 계층 구조를 만들고 명료성을 높입니다. 어떤 서체를 사용할지 유의합니다. 다양한 크기와 서체, 정렬 방식은 사용자가 쉽게 훑어보게 만들며 시인성과 가독성을 높일 수 있습니다.
시스템이 지금 일어나는 일을 파악할 수 있게 합니다. 항상 사용자에게 위치, 동작, 상태의 변화나 오류를 알려줍니다. 다양한 UI 엘리먼트를 사용하며 다양한 상태와 상호작용하게 되는데 사용자가 현재 상황을 쉽게 파악할 수 있게 되면 진행 과정에서 사용자가 겪는 불편함을 완화하는 데 도움 됩니다.
기본 설정에 대해 고려합니다. 사람들이 어떤 목표와 기대를 갖고 이 프로덕트를 사용하는지 주의깊게 생각하고 예측합니다. 이 과정에서 사용자의 수고를 덜어줄 수 있는 기본 설정을 만들 수 있습니다. 이 과정은 특히 폼 디자인에서 중요한데 일부 필드를 미리 선택된 항목으로 할지 아니면 직접 일일이 입력하도록 할지 등 사용자의 사용성을 고려해볼 수 있습니다.
참고 문헌
Jesse James Garrett’s The Elements of User Experience: User-Centered Design for the Web and Beyond (2nd Edition).
Peter Morville and Louis Rosenfeld’s Information Architecture for the World Wide Web: Designing Large-Scale Web Sites.
suckless의 st 터미널을 사용하고 있는데 간혹 한글 입력에서 띄어쓰기 순서가 뒤죽박죽되는 문제가 있었다. 가령 "맑은 물"을 입력하면 "맑 은물"로 입력되는 식이다.
입력하는 속도에 상관없이 이 증상이 가끔 나타나서 불편했었다. 다른 터미널에서는 별 문제 없이 동작하는 점에서 볼 때 st의 문제라고 생각했었는데 urxvt 코드랑 비교해봐도 크게 차이나는 부분은 없었다. 그래서 im 떄문인가 싶어서 fcitx 대신 ibus랑 scim도 설치해서 확인해봤는데 문제가 더 두드러지게 나타났다.
st의 run 함수에서 실제로 전달받는 XEvent를 확인해보면 실제로 띄어쓰기가 가끔 먼저 전달되는 경우를 확인할 수 있었다. XEvent 자체가 비동기라서 순서가 반대로 온다면 fcitx의 문제이거나 컴퓨터 성능탓에 처리 지연이 있다거나 다른 터미널에 비해 가벼워서 사이클 속도가 훨씬 빨라 지연이 눈에 띄게 보인다거나... 그런 가정만 늘어갔다. 10번 입력하면 한 두 번 발생하기 때문에 무엇이 문제인지 판단하기도 어려웠다.
그래서 st 코드를 하나씩 살펴보며 변경할 수 있는 구조는 다 변경해봤다. 그러던 중에 XCreateIC 호출 부분을 수정했는데 일단 순서가 뒤바뀌는 문제는 고쳐졌다! XIMPreeditNothing에서 XIMPreeditNone으로 변경했다. 커서 위치에 표시되는 입력창이 화면 좌측 하단에 고정되어 표시된다.
얼마 전 구입한 크롬북에 무엇을 어떻게 설치해서 써야 낮은 사양에서도 편하게 쓸 수 있나 둘러보다가 suckless에서 만든 dwm에 대해 알게 되었다. 레딧에서 자주 보였던 윈도우 관리자라서 이름 정도는 알고 있었지만 그렇게까지 미니멀한게 필요하지 않다는 생각에 찾아보지도 않았었다. 조그마한 메모리 사용까지도 영향을 받는 기기를 쓰다보니 무거운 데스크탑 환경을 벗어나야만 했다.
Our project focuses on advanced and experienced computer users. ("Philosophy")
코드 품질에 대한 이야기도 흥미롭다. 직관적으로 문제를 해결하는 코드가 코드 복잡도를 낮춘다는 이야기도 재미있다. 모든 내용이 유익하다고는 할 수 없고 공감이 안되는 부분도 있긴 하지만 소프트웨어가 어떤 맥락에서 만들어졌는지 이해하는데는 큰 도움이 된다.
As the number of lines of code in your software shrinks, the more skilled you have become and the less your software sucks. ("Philosophy")
처음엔 왜 이런 기능도 없어보이는 도구가 필요한가 의아했는데 설치하고 한동안 사용해보니 그 매력에 완전 빠졌다. dwm을 사용하면 tmux의 확장판인 기분이 든다. 프로그램의 모든 창을 타일로 관리할 수 있기 때문이다. tmux는 터미널만 정렬하고 쓸 수 있지만 dwm은 실행할 수 있는 모든 것을 타일로 관리할 수 있다. 물론 타일 외에도 다른 레이아웃도 사용할 수 있고 태그라는 기능으로 다중 윈도우처럼 사용하는 것도 가능하다. 게다가 매우 가벼워서 존재하지 않는 것처럼 느껴질 정도다.
특별히 독특하다고 느낀 부분은 코드 패치인데 프로그램이 모든 기능을 지원하고 설정을 제공하는 것이 아니라는 점이다. 필요한 기능은 별도의 diff 파일로 제공하고 있어서 기능이 필요하지 않으면 아예 바이너리에도 포함되지 않는다. 이런 실용주의적 접근이 아마 도구 자체가 가벼운 이유인 듯 하다. 익숙하지 않다면 분명 복잡한 과정이겠지만.
설치
설치는 직접 받아서 빌드해야 한다. 설정을 위한 파일이 따로 존재하지 않고 config.h에 정의해서 빌드해야 하기 때문이다. c로 작성된 소프트웨어라 컴파일러가 없다면 설치해야 한다.
dwm을 효과적으로 사용하려면 동적 메뉴인 dmenu도 설치해야 한다. dwm처럼 suckless의 dmenu 페이지에서 받거나 git 리포지터리를 이용한다.
$ git clone https://git.suckless.org/dmenu/ && cd dmenu
$ make config.h
$ make && make install
이제 로그아웃해서 dwm 세션을 선택해 로그인하면 된다.
단축키
dwm을 시작해보면 아무 것도 없는 휑한 화면만 나온다. 대부분의 기능은 단축키로 사용할 수 있다. 기본 단축키를 기준으로 설명하지만 이 단축키는 모두 config.h에서 추가/수정/삭제가 가능하다.
Shift + Alt + Q dwm 종료하기
Shift + Alt + Enter 터미널 실행하기
Alt + P dmenu 열기
Shift + Alt + C 현재 창 닫기
Alt + j, k 창 커서 이동하기
Alt + h, l 마스터 창 크기 조절하기
Alt + d, i 창 마스터/스택으로 이동하기
Alt + Enter 마스터 창과 스택 바꾸기
Alt + 1...9 해당 숫자 태그로 이동하기
Shift + Alt + 1...9 현재 창 해당 태그로 보내기
# 레이아웃
Alt + t 타일 모드
Alt + f 플로팅 모드
Alt + m 모노클 모드
## 플로팅 모드
Alt + 우클릭 창 크기 조절하기
Alt + 좌클릭 창 위치 이동하기
Shift + Alt + Space 플로팅 전환하기
타일로도 충분히 편리하게 사용하고 있어서 플로팅은 거의 사용하지 않고 있다.
우측 상단에 dwm-{버전} 표시는 status라고 하는 영역인데 이 영역 문자열은 다음 명령어로 변경할 수 있다.
$ xsetroot -name "Hello World"
이 상태 영역을 주기적으로 업데이트하는 별도의 도구를 설치하면 편리하다. dwmstatus 페이지에서 상태 모니터 도구를 찾을 수 있다. 나도 하나 간단하게 작성했는데 dwm-simple-status에서 확인할 수 있다.
suckless에서 개발한 다양한 도구를 보고 있으면 나도 이런 가벼운 도구를 만들고싶다는 생각이 자연스레 따라온다. 많은 dwm 포크와 클론을 보면 비슷한 생각을 하는 사람이 많나보다. dwm, dmenu, surf, st 모두 웹사이트에 게시한 철학을 잘 따라서 만들어진 도구라 더 매력적으로 느껴지는 것 같다.
그동안 AT&T의 DirectTV를 인터넷과 함께 번들로 사용하고 있었다. 한국 채널도 나오고 집에서도 한국 방송을 꽤 보고 있기 때문에 이 케이블 TV를 계속 유지했었는데 번들 할인도 끝나더니 최근에 기본 요금도 올랐다. 작년에 크롬캐스트를 사용하면서 대부분 방송은 온디맨드코리아(사랑해요)랑 넷플릭스, 유튜브로 보고 있고 케이블 TV는 정말 가끔 야구나 보는 정도였다.
남 캘리포니아 지역에는 한국 방송을 송출하는 공중파 방송국도 있고 공중파는 처음에 설치하는 장비 값만 들면 계속 무료로 시청할 수 있어서 DirectTV를 해지하고 공중파(OTA; Over-the-air)로 전환하기로 했다.
수신 가능 채널 확인
먼저 집에서 DTV 신호를 받을 수 있는지 확인해야 한다. 아래 웹사이트에서 채널을 얼마나 수신할 수 있는지 확인할 수 있다.
이 지도에서 몇 마일이나 떨어진 거리인가 확인하는 것이 가장 중요하다. 거리가 멀수록 좋은 안테나가 필요하고 가격도 올라간다. 내 경우는 35마일에서 40마일 내외에 모든 채널이 있었다.
안테나 선택
안테나는 수신 거리와 송출 방향에 따라 어떤 종류를 사야하는지 달라진다.
안테나는 크게 설치 위치에 따라 실내용과 실외용으로 나뉜다. 실외는 수신이 잘 되긴 하지만 전문 장비가 없으면 설치하기가 어렵고 새가 집을 만든다거나 날씨의 영향을 받는다거나 여러 문제가 생길 가능성이 있다. 실내는 그런 문제가 덜한 대신 수신은 잘 안될 가능성도 있다는데 신호가 약할 만큼 먼 거리가 아니라서 실내로 설치하기로 했다.
그리고 안테나는 수신 방향에 따라 지향성과 무지향성으로 구분된다. 지향성은 특정 각도에만 수신이 가능한 대신 약한 신호도 더 잘 잡고, 무지향성은 넓은 각도에서 수신할 수 있는 대신 신호가 약하면 잘 수신하지 못한다고 한다. 우리집은 위 지도에서 봤을 때 거의 대부분 송출국이 몰려 있어서 지향성 안테나로 골랐다.
만약 모든 송출국과 거리가 멀고 신호가 약하다면 지향성 안테나를 여러 방향으로 설치해서 신호를 합치는 방법도 있다. 이럴 때는 여러 안테나와 함께 컴바이너(Combiner)를 구입하면 된다. 이 장비는 분배기(Divider)랑 똑같이 생겼고 통합, 분배 둘 다 역할을 할 수 있는 경우도 있다.
구입 장비
집에는 이미 케이블 TV가 설치되어 있었고 이 케이블 TV의 셋톱박스도 안테나 케이블(Coaxial cable)이고 모든 선이 단자함에 연결되어 있었다. 총 3개 방에 연결되어 있었는데 손님 방에도 케이블 연결을 추가하기로 해서 안테나 선을 방 4개로 분배해야 했다. 손님 방 케이블은 아예 케이블 끝에 연결부도 작업되어 있지 않았다.
전에 IP 카메라를 설치하면서 다락에서 단자함으로 내린 Cat5e 케이블이 있었다. 그래서 안테나를 다락 내에 설치한 후에 안테나 케이블을 Cat5e 케이블을 따라서 단자함으로 끌어오기로 했다.
기존에 연결되어 있지 않았던 단자함 내 안테나 케이블에서 손님 방과 연결된 선을 찾아 컨넥터를 부착했다.
안테나는 미리 조립해 다락에 올려 설치했다.
안테나 케이블을 연결한 후에 단자함으로 내렸고 새로 구입한 분배기에 연결했다.
케이블TV 분배기에 연결되어 있던 케이블을 모두 빼서 새 분배기에 연결했다.
새로 만든 손님방 케이블도 분배기에 연결했다.
각 티비에 연결된 DirectTV 중계기에서 안테나 케이블을 빼서 티비에 직접 연결했다.
각 티비마다 안테나 신호를 사용하도록 채널 검색을 수행했다.
티비에서 가장 자주 보는 채널과 가장 안나오는 채널을 틀어놓고 안테나의 방향을 조금씩 조절해서 가장 잘 나오는 방향으로 맞췄다.
문제 해결
단자함 내에 연결되지 않은 안테나 케이블이 많았다. 어느 케이블이 손님 방과 연결되어 있는지 확인해야 했었는데 별 장비도 없고 그래서 일단 손님 방에 티비를 벽에 있는 케이블 단자와 연결했다. 안테나도 미리 조립했기 때문에 안테나에 케이블을 연결한 후, 케이블 끝을 단자함에 있는 모든 케이블에 하나씩 가져다 대보고 티비 화면에 간섭이 나타나는지 확인했다. 티비는 신호를 잡지 못하고 있기 때문에 지직거리는 화면이 출력되고 있었다. 다행히 10개 케이블 중 하나에서 깜빡이는 간섭을 확인할 수 있었다. 최종적으로 연결해서 확인해보니 손님 방에 연결된 케이블이 맞았다.
이전에 IP 카메라를 설치하면서 익숙해졌던 것도 있어서 그런지 생각보다 손쉽게 설치할 수 있었다. 지출이 줄어든 만큼 다른 구독 서비스도 덜한 죄책감으로 사용할 수 있을 것 같다.
Windows에 Hyper-V로 Ubuntu를 설치한 후에 제공하는 도구로 접속해보면 마우스도 느리게 움직이고 키보드 입력도 답답하다.
이 문제를 해소하기 위해 고급 세션 모드(enhanced session mode)가 추가되었다. 내부적으로 RDP를 이용해서 해당 가상 컴퓨터(VM)에 접속하는 방식이다. Windows 10 버전 1709 이후로 제공되는 Hyper-V 빨리 만들기 (Quick Create) 프로그램에서는 이 고급 세션 모드를 기본적으로 사용할 수 있도록 설정된 Ubuntu VM을 제공하고 있다.
하지만 직접 리눅스 이미지를 사용해서 VM을 생성했다면 별도의 설정이 필요하다. 해당 설정을 위한 스크립트는 microsoft/linux-vm-tools에서 제공하고 있다. 해당 스크립트에는 linux-virtual 관련 툴 설치, xrdp 설치 및 설정이 포함되어 있고 각 항목마다 주석으로 설명이 있어서 어떤 도구가 설치되는지 궁금하다면 확인해보자.
설치한 Ubuntu는 19.10이며 위 스크립트는 18.04인데 설치에 큰 차이가 없었다. 16대 버전은 다른 설치파일이 존재하므로 위 링크를 참조해야 한다.