앱 개발 과정 중에 "토큰화"한다는 의미가 무엇인지 알고 싶어서 AI에게 질문을 하고 답변을 얻었습니다.
비전공자인 제 입장에서는 이해하기 쉬운 내용이었고, 두고두고 잊어버리지 않기 위해서 기록하고 공유합니다.
##토큰화(tokenization)란
숫자/색상 값을 코드에 직접 적지 않고, 의미가 담긴 이름(상수)에 묶어 그 이름을 참조하는 것.
// 토큰화 X (raw)
SizedBox(height: 16)
Color(0xFF8B6FB8)
EdgeInsets.all(24)
// 토큰화 O
SizedBox(height: AppTheme.cardGap)
AppTheme.yearlyAccent
EdgeInsets.all(AppTheme.contentHorizontalPadding)
핵심: 값(16)이 무엇인지가 아니라, 그 값이 "어떤 의미로" 쓰이는지를 코드가 드러냅니다.
##왜 토큰화가 필요한가 (구체 예시)
1. 일관성 — 모든 카드 사이가 같은 간격
앱에 카드 사이 간격이 100군데 있다고 가정. 모두가 SizedBox(height: 16)이라면, 디자이너가 "카드 사이 간격을 18px로 넓히자" 하면 100군데 일일이 찾아 16→18로 바꿔야 함. 그런데 AppTheme.cardGap = 16이라는 토큰을 쓰면 한 곳만 바꾸면 100곳이 자동으로 따라 옵니다.
2. 의미 명확성 — 이름이 의도를 알려줌
SizedBox(height: 16)
// 16이 뭘 의미하는지 모름. 우연한 값?
SizedBox(height: AppTheme.cardGap)
// "아, 카드 사이 간격이구나"
다른 개발자가 코드를 볼 때 의도가 즉시 보입니다.
3. 잘못된 재사용 방지 — 우리 #6에서 실제 발견된 사례
// 변경 전
(위험 SizedBox(height: AppTheme.contentHorizontalPadding)
//이름이 "수평 padding"인데 세로(height)에 씀
//값(24)이 우연히 같아서 동작은 했지만,
//디자이너가 가로 padding을
//엉뚱하게 세로 간격까지 26으로 변함
토큰의 이름이 의미와 일치해야 미래 변경에서 사고가 나지 않습니다.
4. 디자이너 ↔ 개발자 공유 어휘
디자이너가 "카드 사이 간격(cardGap)을 좁혀줘"라고 말하면, 개발자가 정확히 어디를 손댈지 즉시 압니다.
즉 같은 단어를 써서, 의사소통 손실이 없습니다.
##토큰화하지 않아야 하는 경우
모든 숫자를 토큰화하면 오히려 코드가 복잡해집니다.
가이드라인:
| 상황 | 토큰화? |
| 화면 레이아웃 (페이지 padding, 카드 간격, 섹션 사이) | ✅ 필수 |
| 카드 내부 미세 조정 (8/12/14 같은 작은 값) | ❌ 보통 그대로 |
| 한 위젯 안에서만 쓰이는 1회성 padding | ❌ 그대로 |
| Row/Column에서 두 항목 사이 작은 6/10/12 | ❌ 그대로 |
기준: 여러 화면에서 반복되는 패턴인가? 그렇다면 토큰화. 이 위젯에서만 쓰는 미세 조정인가? 그렇다면 그대로.
##색상 토큰도 같은 원리
// X
Color(0xFF8B6FB8) // 이게 무슨 보라?
// O
AppTheme.MenuAccent // " 메뉴 액센트 보라"
두 파일에 같은 보라(#8B6FB8)가 따로 정의돼 있는데, 한쪽만 바꾸면 silent하게 일치성이 깨짐. 토큰 한 곳에 정의하면 양쪽 자동 동기화.
저는 위 개념을 듣고 조금 이상한 생각이 들었습니다.
값을 명확하게 정의하면 모두 자동적으로 맞춰지는 것 아닌가 하는 의문이 들었기 때문입니다.
AI는 이것에 다음과 같이 답변해 주었습니다.
"직관적으로는 그렇게 생각할 수 있는데, 실제 컴파일러는 "이 16과 저 16이 같은 의미"라는 걸 알 방법이 없습니다."
##컴파일러 입장: 숫자는 그냥 숫자
// 파일 A
SizedBox(height: 16) // ← 이 16은
SizedBox(height: 16) // ← 이 16과
SizedBox(height: 16) // ← 이 16이
// 파일 B
SizedBox(height: 16) // ← 이 16과
EdgeInsets.all(16) // ← 이 16과
컴파일러에게는 모두 별개의 독립 숫자입니다. "다 같은 16이네 → 한꺼번에 16으로 유지해야지"라고 자동 인식하지 않아요.
// 디자이너: "카드 사이 간격을 18로 넓혀줘"
// 개발자: 6개 16 중 어느 게 카드 사이 간격이지?
// 다 똑같이 보이는데...
의도가 코드에 안 적혀 있어서, 사람이 직접 grep으로 찾고 일일이 판단해야 함. 그러다 한두 개 빠뜨리면 16/18이 섞여서 시각이 무너집니다. -> 토큰을 쓰면 이 문제가 해결됩니다!
// AppTheme.dart (한 곳)
static const double cardGap = 16;
static const double sectionBottom = 16;
// 화면 1
SizedBox(height: AppTheme.cardGap) // 컴파일러: cardGap을 참조 중
SizedBox(height: AppTheme.cardGap) // 컴파일러: cardGap을 참조 중
// 화면 2
SizedBox(height: AppTheme.sectionBottom) // 컴파일러: sectionBottom을 참조 중
이제 컴파일러는 "이건 모두 cardGap이라는 같은 변수를 가리킨다"는 걸 명확히 압니다.
디자이너가 cardGap을 18로 바꾸면
→ AppTheme.dart 한 줄만 수정 → 모든 사용처가 자동 18.
값이 같은 16이어도 cardGap과 sectionBottom을 분리해두면, 미래에 "카드만 좁히고 섹션은 그대로"가 가능해집니다.
이름이 의도를 보존하기 때문이에요.
비유하자면 다음과 같습니다.
- 숫자 직접 쓰기 = 종이에 "16"을 100군데 따로 쓰는 것. "다 같이 18로 바꿔" 하려면 100번 지우개질
- 토큰 쓰기 = "오늘의 라벨"이라는 라벨 통에 16을 한 번 넣음. 100군데에는 "오늘의 라벨"만 가리킴. 통 안의 16을 18로 바꾸면 100군데 자동 18
'앱 개발 이야기' 카테고리의 다른 글
| Futureseed ver 1.1.0 업데이트 소식 (0) | 2026.05.05 |
|---|---|
| 한심했던 나를 걷게 만든 힘, 그리고 부모님을 위해 만든 세상에서 가장 쉬운 걷기 앱 - Walk Habit 안드로이드 버전 출시 (0) | 2026.04.24 |
| 구글 플레이 비공개 테스트 단계 성공! (0) | 2026.04.16 |
| 두번째 앱 출시, Futureseed (0) | 2026.04.09 |
| 구글 플레이 비공개 테스트 거절(리젝) 사유 (12명 테스터 조건) (0) | 2026.03.29 |