FlutterDart앱스토어브랜딩i18n

마작 조이에서 마작한판으로 — 앱 이름을 바꾼 이유와 그 과정

2026년 7월 14일5 분 읽기

마작 조이에서 마작한판으로

만들고 있는 마작 게임 이름이 "마작 조이"였다. 스토어에 등록하기 전에 마지막으로 한 번 더 검토해보자 싶어서 스토어에서 "마작"을 검색해봤는데, 좋지 않은 걸 발견했다. 검색 결과 대부분이 짝맞추기 솔리테어 게임이었다. 같은 그림 두 개를 찾아서 없애는, 흔히 말하는 "마작 게임" 장르 말이다.

문제는 내가 만든 게임은 그런 게 아니라는 거다. 패를 뽑고 버리고, 몸통(스트레이트/트리플) 4개와 머리 1개를 맞춰서 완성하는 진짜 4인 마작이다. 규칙 자체는 전통 마작 그대로고, 다만 역·판수·부수 같은 복잡한 점수 계산만 걷어내고 "기본 100점 + 보너스"로 단순화했을 뿐이다. 그런데 "마작 조이"라는 이름은 딱 저 짝맞추기 게임들과 같은 계열로 보였다. 검색 결과에 묻히는 정도가 아니라, 어렵게 찾아낸 사용자조차 "짝맞추기겠거니" 하고 지나칠 수 있는 이름이었다.

이름을 다시 짓기로 했다.

방향을 좁혀가는 과정

처음엔 그냥 "정통 마작"처럼 대놓고 직설적인 이름을 생각했다. 진짜마작, 정통마작 같은 것들. 그런데 이런 이름은 너무 딱딱하고, 정작 이 게임의 장점(아이도 이해할 수 있게 룰을 단순화했다는 것)과는 안 어울렸다.

다음으로 게임의 특징인 "점수 영수증" 연출을 브랜드로 살려보려 했다. 마작영수증 같은 이름. 재미있긴 한데, 검색 키워드로서는 약했다.

마지막으로 정착한 게 가족/캐주얼 초대형이었다. "한판 하자"는 표현이 힌트였다. 한국에서 고스톱이나 화투, 장기처럼 진짜 승부가 있는 전통 테이블 게임을 부를 때 자연스럽게 쓰는 말이다. 이 표현 자체가 "쌍 맞추기 퍼즐이 아니라 실제로 겨루는 게임"이라는 걸 은근히 신호해준다. 그렇게 마작한판으로 정했다.

다국어 표기는 번역하는 쪽으로 갔다. 이 게임은 한국어/영어/중국어 3개 언어를 지원하는데, 브랜드 이름이라고 무조건 로마자 표기(Mahjong Hanpan)를 고집하기보다는, 각 언어권에서 자연스럽게 읽히는 이름을 쓰는 게 낫다고 판단했다.

언어이름
한국어마작한판
영어Mahjong Round
중국어一局麻将 (yījú májiàng)

중국어 쪽은 특히 잘 맞아떨어졌다. "一局"이 딱 "한 판"에 대응하는 표현이라, 억지로 의역하지 않아도 자연스럽게 같은 뉘앙스가 나왔다.

스토어 문구를 쓰다가 발견한 실수

이름을 정하고 나서, 앱스토어 등록 문구(제목/짧은 설명/상세 설명)를 새로 쓰기 시작했다. 처음엔 이렇게 썼다.

마작한판 - 짝맞추기 아닌 진짜 마작

"짝맞추기가 아니다"라고 부정문으로 확실히 못박으면, 오해를 미리 차단할 수 있을 거라 생각했다. 그런데 실제로 flutter run -d chrome으로 앱을 켜서 화면에 뜬 문구를 눈으로 보다가 뭔가 이상하다는 걸 깨달았다. 제목 바로 아래, 화면에 큼지막하게 "짝맞추기"라는 글자가 그대로 박혀 있었다.

부정어("아닌")는 사람이 훑어 읽을 때도, 검색 엔진이 텍스트를 인덱싱할 때도 쉽게 무시된다. 결국 남는 인상은 정확히 피하고 싶었던 단어 — "짝맞추기" — 그 자체였다. 애써 이름을 바꿔놓고, 정작 눈에 잘 띄는 자리에 그 단어를 다시 심어놓은 셈이었다.

그래서 원칙을 하나 세웠다. 브랜드 문구(제목/태그라인/설명 첫 문장)에서는 그 단어를 부정형으로도 아예 언급하지 않는다. 대신 처음부터 긍정형으로만 말한다.

- 마작한판 - 짝맞추기 아닌 진짜 마작
+ 마작한판 - 진짜로 겨루는 4인 마작
- 一局麻将 - 不是配对游戏
+ 一局麻将 - 真正的4人麻将对局

이 원칙을 title.txt, 앱 안의 태그라인, 상세 설명 첫 문장까지 한/영/중 3개 언어 전부에 다시 적용했다. 특정 단어를 피하고 싶을 땐 "그 단어를 부정하는 문장"이 아니라 "그 단어가 아예 등장할 필요가 없는 문장"을 써야 한다는 걸, 직접 화면에 띄워보고 나서야 체감했다.

코드에 실제로 반영하기

이름만 바꾸고 끝나는 게 아니었다. 앱 안팎에 흩어져 있던 옛 이름을 하나씩 찾아서 정리해야 했다.

다국어 앱 이름을 위한 필드 추가

이 프로젝트는 lib/i18n/strings.dart에 언어별 Strings 객체(_ko, _en, _zh)를 두고 화면 문구를 관리한다. 그런데 정작 홈 화면의 앱 이름 텍스트는 언어와 무관하게 'Mahjong Joy'로 하드코딩되어 있었다. 이 기회에 appTitle 필드를 새로 추가해서 언어별로 다르게 뜨도록 고쳤다.

class Strings {
  final String appTitle;   // 신규 추가
  final String tagline;
  // ...

  const Strings({
    required this.appTitle,
    required this.tagline,
    // ...
  });
}

const _ko = Strings(appTitle: '마작한판', tagline: '마작한판 — 진짜로 겨루는 4인 마작', /* ... */);
const _en = Strings(appTitle: 'Mahjong Round', tagline: 'Mahjong Round — real 4-player mahjong, simple scoring', /* ... */);
const _zh = Strings(appTitle: '一局麻将', tagline: '一局麻将 — 真正的4人麻将对局', /* ... */);

main.dartMaterialApp(title: ...)과 홈 화면 스플래시의 Text('Mahjong Joy')를 전부 settings.strings.appTitle로 바꿨다. settings는 이미 MahjongJoyApp 위젯의 생성자 인자로 들어와 있어서, context.watch 없이도 바로 접근할 수 있었다.

런처 표시 이름

안드로이드와 iOS는 각각 별도로 "런처에 보이는 이름"을 갖고 있다. 둘 다 단순 문자열 교체였다.

<!-- android/app/src/main/AndroidManifest.xml -->
android:label="마작한판"
<!-- ios/Runner/Info.plist -->
<key>CFBundleDisplayName</key>
<string>마작한판</string>

패키지 ID까지 다시 바꾸기

여기서 조금 더 큰 결정을 했다. 안드로이드 패키지 ID(applicationId)에 남아있던 mahjongjoy라는 이름도 mahjonghanpan으로 바꾸기로 한 것이다. 패키지 ID는 사용자 눈에는 안 보이지만, 스토어에 한 번 배포하고 나면 사실상 바꿀 수 없는 값이라 미리 정리하는 게 나았다.

// android/app/build.gradle.kts
namespace = "com.backdev.mahjonghanpan"
applicationId = "com.backdev.mahjonghanpan"

패키지 ID를 바꾸면 코틀린 소스 폴더 경로(com/backdev/mahjongjoy/)도 그 이름을 따라가야 한다. 안드로이드는 패키지 경로와 폴더 구조가 1:1로 묶여 있어서, 폴더를 새로 만들고 MainActivity.kt를 옮긴 뒤 옛 폴더를 지웠다.

mkdir -p android/app/src/main/kotlin/com/backdev/mahjonghanpan
# MainActivity.kt의 package 선언도 com.backdev.mahjonghanpan으로 수정
rm -rf android/app/src/main/kotlin/com/backdev/mahjongjoy

iOS 쪽(ios/Runner.xcodeproj/project.pbxproj)의 PRODUCT_BUNDLE_IDENTIFIER도 같은 값으로 맞췄다. 아직 Xcode가 없어서 iOS 빌드는 못 해보지만, 나중에 빌드할 때 어긋나지 않도록 미리 통일해뒀다.

스토어 등록 문구 9개 파일

이 프로젝트는 store/{ko,en,zh}/ 폴더에 title.txt, short_description.txt, full_description.txt를 따로 관리하고 있어서, 실제 Play Console에 붙여넣을 때는 복사만 하면 되게 해뒀다. 이번에 이 9개 파일 전부를 새 이름과 새 포지셔닝("짝맞추기가 아니라 진짜로 겨루는 4인 마작")으로 다시 썼다.

버전을 리셋하고 다시 빌드

패키지 ID가 바뀌면 스토어 입장에서는 완전히 새로운 앱이 된다. 마침 이전에 테스트용으로 1.0.0, 1.0.1, 1.0.2 버전을 미리 만들어뒀었는데(테스트 기간에 순서대로 올리면서 "개발 중"인 느낌을 내려는 목적이었다), 새 패키지에서도 같은 흐름을 그대로 반복하기로 하고 버전을 리셋했다.

# pubspec.yaml
version: 1.0.0+1   # 1.0.2+3 이었던 것을 되돌림
flutter build appbundle --release

빌드가 끝난 뒤 옛 패키지(com.backdev.mahjongjoy)로 이미 설치되어 있던 앱은 테스트 폰에서 지우고, 새 패키지(com.backdev.mahjonghanpan)로 새로 설치했다. 패키지 ID가 다르면 안드로이드는 두 앱을 완전히 별개로 취급하기 때문에, 그냥 새로 설치만 하면 옛 버전은 아이콘만 남고 자동으로 덮어써지지 않는다. adb uninstall로 직접 정리해야 했다.

정리

이번 작업의 흐름을 요약하면 이렇다.

  1. 문제 발견: 스토어에서 "마작"을 검색해보니 짝맞추기 솔리테어 게임이 대부분이었고, "마작 조이"라는 이름이 그 부류로 오인될 위험이 컸다.
  2. 이름 방향 탐색: 직설적인 "정통/진짜" 강조형 → 특징(영수증) 강조형 → **가족/캐주얼 초대형("한판 하자")**으로 좁혀서 "마작한판"을 확정했다.
  3. 다국어 표기: 로마자 표기를 고집하지 않고 언어별로 자연스럽게 번역했다 (마작한판 / Mahjong Round / 一局麻将).
  4. 카피 실수 발견: "짝맞추기 아닌"처럼 부정형으로 피하고 싶은 단어를 다시 언급하면 오히려 역효과라는 걸, 실제 화면을 띄워보고 나서 깨달았다. 이후 브랜드 문구에선 그 단어를 아예 쓰지 않는 원칙으로 통일했다.
  5. 코드 반영: strings.dart에 다국어 appTitle 필드를 추가하고, AndroidManifest/Info.plist의 런처 이름, 패키지 ID(및 코틀린 소스 경로), 스토어 등록 문구 9개 파일까지 전부 정리했다.
  6. 버전 리셋 후 재배포: 패키지 ID가 바뀌면 스토어 입장에선 새 앱이라는 점을 감안해, 테스트 버전 번호를 1.0.0으로 되돌리고 새로 빌드해 테스트 폰에 설치했다.

브랜드 이름 하나 바꾸는 게 단순히 텍스트 파일 몇 개 고치는 일일 줄 알았는데, 실제로는 앱 코드·플랫폼 설정·스토어 문구·패키지 ID까지 전부 사슬처럼 엮여 있었다. 그리고 무엇보다, 좋은 이름인지 아닌지는 문서로 검토할 때보다 실제 화면에 띄워놓고 눈으로 봤을 때 훨씬 잘 보인다는 것도 다시 확인했다.

PM

backtodev

40대 PM, 다시 개발자로 돌아갑니다. 실패하고 배우며 성장하는 기록.