이 글은 아래 글을 읽으면서 나름 밑줄 친 내용을 적어둔다..

원문: https://rithm.app/8-lessons-from-a-failed-version-1/

 

Building for 2 years, $194 in revenue, 100% churn, 8 priceless lessons. - Habit & Goal Tracking App: Rithm

Making Software, the hardest way to make an easy living. TL:DR – check out Rithm: Habit tracking machine v2 in apple app store today Hey Kyle here, maker of Rithm. So early 2020, I launched Rithm, an app that helps...

rithm.app

 

 

Rithm이라는 목표관리, 습관 만들기 앱을 1년 반 동안 만들어 론칭. 수익은 194달러. 왜 실패했는가에 대한 복기의 기록.

 

 

교훈 1: 오긍정(False Positive)

개발자가 잘못 생각한 긍정적 시그널 3가지: 돈을 내는 고객. 경쟁력 있는 앱 공간, 니치 마켓에서 판매하는 다른 제품.

한 고객에게 처음 1달러를 쓰게 하는 건 쉬운데, 그다음 1달러 쓰게 하는 건 어렵다.

구독모델.... 고객이 돈 내는 게 문제가 아니라 꾸준히 돈 내게 하는 것(retention)이 매우 중요. 그렇지 않으면 비즈니스 모델을 가질 수 없다. 

유사제품이 많다고 해서 시장이 있다는 것을 의미하는 것은 아니다. revenue-generating business가 중요! 때로는 어떤 개발 스튜디오는 사이드 프로젝트 또는 포트폴리오 때문에 유사 제품을 만들기도 한다.

유사 책이 흥행중이라고 해서(어떤 토픽이 트렌드의 핵심이라고 해서)  실제 앱을 설치해서 행동을 취하는 사람은 많지 않다

추천 책: Why Startups Fail by Tom Eisenmann,

 

 

교훈 2: 비타민(있으면 좋은 것) 대 진통제(꼭 있어야 하는 것)

대부분의 사람들이 힘든 부분을 해소해 주지 않는 앱은 비즈니스적으로 좋은 앱이 아니다.  사람의 필요(need)와 통점(pain point)에 밀접하게 관련 있는 앱이 필요한 앱. 고통스럽고 자주 발생하는 문제를 해결해야 한다.

 

 

교훈 3:사용자의 행동 변화를 이끌어내는 것은 힘들다.

매슬로우 욕망계층에서 상위로 올라갈수록 니즈는 덜하다. 인스타는 우버 잇츠로 저녁 시켜 먹은 다음에나 사용하는 앱.

 

 

교훈 4: 분산

앱 스토어는 사용자들이 믿고 제품을 구매하는 단일창구이지만, 전시 매대가 지극히 제한적. 따라서 앱스토어를 넘어서는 사용자 인터랙션 채널을 확보해야 한다.

 

 

교훈 5: UI/UX측면의 챗봇

챗봇으로 상담하는 것은 생각보다 오래 걸리고, 구시대적인 방법. 차라리 UI를 제공해 주는 것이 떠 빠르다. 특히 습관 앱의 경우 상담사와 이야기하는 경우는 한 달에 한두 번하는 것이고 나머지는 수행하는 데 집중하므로 봇은 UI가 좋지 않더라.  UI 쇄신만으로는 충분하지 않다. 두번 생각하자... 사용자 인터페이스 계층에서 쇄신하는 것인가? 아니면 제품 차별화를 위해 좀 더 심도 깊은 작업을 하는 것인가 고민하자. 

 

교훈 6. 다른 사람도 같은 가려운 곳인가?

자기 가려운 곳을 긁어줘야 하지만.. 그렇다고 남들도 가려울 것이라 전제하고 제품을 만들어서는 안 된다.

 

 

교훈 7. 모든 비즈니스는 제품이 있지만, 모든 제품이 비즈니스는 아니다. 

 

 

교훈 8. 개인에게 팔 것인가 팀에게 팔 것인가.

멀티플레이어 앱이 단일 플레이어 앱보다 훨씬 인기가 좋다(more engaged)

 

 

 

---

원문에 churn이라는 단어가 소개되었는데, 동사로 "마구 휘젓다"라는 뜻이 있지만 "서비스 제공자를 바꾸는 고객"이라는 뜻이고.. churn rate은 고객의 이탈률, 근로자의 이직률을 의미한다고 한다. (네이버 사전 링크)

자세한 설명은 만화로: https://www.figma.com/proto/xkKAXR1Nf6maiLvA55yyCH/AJVC?node-id=47385%3A16&scaling=min-zoom 

 

Figma

Created with Figma

www.figma.com

 

배틀넷 런처.. 새로운 UI로 바뀌었네요.

오랜만에 업데이트했는데, 초기화면에서 바로 L10N 이슈를 찾았습니다.

 

# 맥락없이 번역했을 때 발생할 수 있는 일들

메인화면에서 게임을 즐겨찾기하거나 즐겨찾기에서 게임을 뺄 수 있는데요.

아래 두 화면에서 툴팁을 보시면 바로 L10N(Localization)중 번역 문자열 이슈가 보입니다.

 

 

정황상 소셜 패널에 영문으로 "Add To Favorites"라는 문자열이 두군데 모두 사용되었고, 번역대상 문자열을 뽑다가 어떤 맥락에서 사용된 것인지 모르는 채로 번역팀에 "Add To Favorites"가 전달되어 두 곳 모두  "친한 친구에 추가"로 모두 처리한 것이 아닌가 싶습니다.

이 문제가 번역 과정만의 문제인가? 사실 그렇지는 않습니다.

번역팀(혹은 외부 전문 업체)에서는 소스코드에 접근하는 것이 아니므로 어떤 맥락(상황)에서 해당 문장이 사용되었는지의 정보가 함께 있을 때 정확한 번역이 이루어질 수 있습니다. 

 

예를 들어 크로스 플랫폼 UI를 제공하는 Qt Framework에서 L10N을 지원하기 위해 코드에서는 tr함수를 이용합니다.

QPushButton hello(QPushButton::tr("Hello world!"));

lupdate명령을 통해 소스에서 tr로 된 문자열을 뽑아내죠. 이 과정은 C계열 오픈소스 프로젝트에서 사용하는  po에서도 비슷합니다.

 

보통은 위와 같이 코드에서 다국어 지원을 표시하는데, 번역대상인 문장만으로는 오해의 가능성이 존재합니다.

 

송수신자의 이름을 입력받는 대화창을 생각해 봅시다.

Qt를 이용한다면 다음과 같은 코드가 작성되겠죠.

    QLabel *senderLabel = new QLabel(tr("Name:"));
    QLabel *recipientLabel = new QLabel(tr("Name:"));

lupdate를 하면 dialog.cpp에서 사용되는 L10N대상 문자열은 "Name:"이 추출될 것입니다. 번역팀은 이 정보만 있으니 "이름:"으로 번역해서 업데이트가 되겠죠. 이 번역파일이 적용되면 송수신자 대화상자에 "이름:"이라고만 표시되는 레이블이 2개가 있을 겁니다.

 

이러한 모호성을 없애기 위하여 두번째 인자로 맥락 정보를 제공해 주는 것이 좋습니다.

    QLabel *senderLabel = new QLabel(tr("Name:", "sender"));
    QLabel *recipientLabel = new QLabel(tr("Name:", "recipient"));

즉, "Name:" 이라고 사용되었지만 recipient라는 맥락이 있으니 '이름:'이라는 일반적인 번역 대신 첫번째는 '발송인', 두번째는 '수취인'으로 번역될 수 있겠죠. 정보는 더 많아지지만, 코드는 조금  지저분한 느낌이 드는 것은 사실입니다.

 

비슷한 사례로 인쇄 옵션이 생각나네요. 영어로 가로 출력과 세로 출력이 'Landscape'와 'Portrait'인데, 단어 자체의 뜻은 각각 '조경'과 '초상화'라는 뜻이죠. 그래서 단어만 보고 번역되었을 경우 인쇄 옵션에 생뚱맞게 조경과 초상화가 등장하기도 합니다.

 

개발자분들에게 팁을 드리자면 L10N처리는 문장 단위가 되어야 합니다.

제가 배틀넷 런처 개발당시 겪었던 일을 대략적으로만 소개하겠습니다.(시간은 좀 지났으나..그래도 자세하게 했던 일을 공유하는 것을 피하는것이 제 원칙이라..)

사용자에게 어떤 메시지를 날짜/시간 정보와 함께 표시해야 하는 기능이었는데, 전 포맷팅 문자열을 국가별로 다른 부분만 tr처리를 해서 문장의 일부 부분을 바꾸었습니다. 그랬더니 보스가 절 부르더니 (예가 정확히 기억나지 않는데..) 국가별로 문장 방식이 다를 수 있으니 바뀔 수 있는 부분 말고 문장 단위로 바꾸게끔 것을 가이드하더군요. 그때부터 L10N은 문장 단위로 끊어서 코드에 작성했습니다.

 

 

#L10N, 문장 번역을 넘어서

L10N은 단순히 번역 문제만 말하는 것은 아니고 복잡한 주제들이 있습니다. 대표적으로 표시 형식과 특정 언어만 가지는 문제들이 있죠.

우리가 다루는 데이터에는 날짜, 시간, 숫자(특히 화폐..) 등이 있죠. 날짜만 봐도 2021/03/06, 03/06/2021, 06/03/2021, Mar/06/2021, 2021-03-06 등등 많은 표시형식들이 각 나라별로 있습니다. 화폐단위만 봐도 달러는 센트단위가 있어서 123.45 달러라 표시하면 123달러 45센트가 됩니다만, 원화에서는 소숫점 아래 자리가 없죠. (전이라는 단위가 있긴 합니다만 사용하지 않습니다.)

 

수치표현도 복잡해 집니다. 우리나라를 비롯한 아시아권에서는 주로 만단위의 숫자를 표시하지만 영미권은 천단위로 숫자를 읽습니다. '123,456'의 의미는 뭘까요? 대부분 우리나라사람들은 '12만 3천4백5십6'으로 읽을 겁니다. 하지만 프랑스에서는 '1백2십3 쩜 사오육(소숫점)'으로 이해됩니다. 와우~. 궁금하신분은 Decimal Separator를 읽어보세요. 

 

복수형표시문제, 단어의 성별...

표시형식 문제에 복수형도 복잡하죠.  Qt 문서사이트에 소개된 예를 들어봅시다.

우리나라만 대상으로 하는 소프트웨어를 개발한다고 하면 다음과 같이 코드를 작성하겠죠.

  QString *receivedMessageNotificationFormatter = tr("%d개의 메시지가 도착하였습니다.");

우리나라에서는 몇개의 메시지가 도착하든 상관없이 저 문장 하나로 처리됩니다.

그런데 다음 표를 보세요.

 

프랑스에서는 0개 또는 1개일때는 s가 붙지 않고, 2개 이상에는 s가 붙습니다. (메시지에도 s가 붙고 저장되었다는 동사에도 s가 붙습니다.)

영어에서는 0개또는 2개 이상일 때 s가 붙습니다.(메시지에만 s가 붙고, 동사에는 s가 붙지 않습니다.) 1개일 경우 s가 붙지 않습니다. 

즉, 복수형의 기준 잣대가 언어별로 다르다는 이야기입니다. 특정 국가에서는 단어의 성별에 따라 이어지는 단어의 형태가 바뀌어야 하는 경우도 있습니다.

 

라틴어계열만 그런 것은 아닙니다. 우리말에도 '은는이가'가 있죠.

'닭은 동물이다'와 '고양이는 동물이다'라는 문장이 있죠. '%s은(는) 동물이다'로 표현하는데, 좀 더 매끄러운 문장을 만들려면 %s에 해당하는 단어의 끝 받침에 따라서 '은' 또는 '는'이 선택되어야 하죠.

 

코드에서 L10N을 고려하기 시작하면 챙겨야 할 것들이 많이 있습니다. 하지만 너무 걱정하지 않으셔도 됩니다. 많이 사용되는 L10N 이슈들은 대부분 프레임워크나 운영체제 레벨에서 제공하는 API 또는 정보를 활용하면 됩니다.

 

 

배틀넷 번역때문에 L10N을 문자열 중심으로만 소개했는데, 이미지도 L10N 대상입니다.

우리가 흔히 접하는 이미지(기호)가 국가에 따라 다른 의미를 가질 수도 있기 때문입니다. 널리 알려진 예가 미키마우스 손가락 갯수입니다. 자세히 보신 분들이 있으실 것 같은데 미키마우스는 손가락이 4개입니다. 미키마우스가 일본에서 처음 방영되었을 때 일본 시청자들은 심리적으로 이상한 감정을 느꼈다고 합니다. 지금도 그런지 확인해봐야 합니다만,  일본에서 4손가락은 야쿠자(조폭)이미지를 떠올린다고 합니다. 일본 영화에 가끔 단지 장면이 나오잖아요. "귀여운 미키가 야쿠자라니"라는 무의식이 동작했었다고 하네요. 그래서 L10N에는 번역만 있는 것이 아니라 특정 국가에서 다른 의미나 뉘앙스를 가지는 기호체계를 현지화하는 것이 포함됩니다.

개발에서는 이 문제를 쉽게 resource overriding으로 해결할 수 있습니다.

예를 들어 symbol1.png 이미지가 특정 국가에서는 다르게 바뀌어야 한다면 리소스를 처리하는 부분에서 다음과 같은 방식으로 변경하면 되겠죠? 코드를 아래와 같이 사용하려면 소프트웨어 리소스의 위치 구조도 처음부터 잘 고려해야 합니다.

if (file_exist("{current_locale}/symbol1.png")) {
 return {current_locale}/symbol1.png;
} else {
  return general/symbol1.png;
}

 

배틀넷 런처에서 찾은 번역 오류 이야기하다가 코드 이야기로 빠져서 L10N까지 슬쩍 이야기해보았습니다.

글로벌용 소프트웨어/서비스를 만드는데 작은 도움이 되길 바랍니다.

 

사족

설치/업데이트가 끝나면 "완료하는 중"으로 표시되는데, "마무리 중"이 더 우리글 스럽지 않나 생각되네요.

 

+ Recent posts