
게임 개발 중, 특정 국가의 유저에게서 `게임이 튕긴다`, `버그 때문에 앱이 종료된다`는 보고를 받았다면 가장 당황스러울 것이다. 특히 이 문제가 터키, 러시아 등 일부 지역에서만 문자열 파싱 과정 중에 발생한다면, 디버깅은 미궁에 빠지기 쉽다.
대부분의 경우, 이 현상은 문화권마다 다른 소수점 구분 기호(Decimal Separator) 때문에 발생한다. 유니티(Unity)에서 문자열을 숫자로 변환할 때, 시스템의 지역 설정에 따라 `콤마(,)`와 `마침표(.)` 중 어떤 것을 소수점으로 인식할지가 달라지기 때문이다. 이 글에서는 이 미스터리한 버그의 원인을 파헤치고, 모든 문화권에서 안전하게 문자열을 파싱하는 `CultureInfo.InvariantCulture` 사용법을 알아본다.
문화권별 소수점 구분 기호의 함정
우리가 흔히 사용하는 숫자 포맷은 전 세계적으로 동일하지 않다. 특히 소수점과 천 단위 구분 기호에서 차이를 보인다. 이 차이를 이해하지 못하면 지역 설정에 따른 파싱 오류가 발생하기 쉽다.
주요 문화권별 숫자 형식
| 형식 그룹 | 소수점 구분 기호 | 천 단위 구분 기호 | 예시 국가 | 예시 (1234.56) |
| 영미권 (A 그룹) | 마침표 (.) | 콤마 (,) | 미국, 영국, 캐나다, 호주, 인도, 한국, 일본 | 1,234.56 |
| 유럽/라틴권 (B 그룹) | 콤마 (,) | 마침표 (.) | 터키, 러시아, 독일, 프랑스, 스페인, 브라질, 이탈리아 | 1.234,56 |
- 영미권 (A 그룹): 소수점은 `마침표(.)`를 사용하고, 천 단위 구분 기호는 `콤마(,)`를 사용한다. (예: 1,234.56)
- 유럽 대륙 및 일부 국가 (B 그룹): 소수점은 `콤마(,)`를 사용하고, 천 단위 구분 기호는 `마침표(.)` 또는 `공백`을 사용한다. (예: 1 234,56 또는 1.234,56)
Unity/C#의 기본 동작
C#에서 float.Parse()나 Convert.ToSingle()와 같은 메서드를 사용하여 문자열을 숫자로 변환할 때, 기본적으로 현재 실행 중인 디바이스/운영체제의 문화권 설정(Current Culture)을 따른다.
만약 소수점 구분 기호로 `콤마(,)`를 사용하는 터키 디바이스에서, 코드에 하드코딩된 `마침표(.)` 기반의 숫자 문자열("1.5")을 파싱하려고 하면 어떤 일이 발생할까?
터키 문화권의 파서는 "1.5"를 다음과 같이 인식할 수 있다.
- 소수점은 `콤마(,)`여야 하는데, `마침표(.)`가 있으므로 유효한 숫자가 아닐 가능성이 높다.
- 파싱 메서드는 이를 잘못된 형식으로 간주하고 `FormatException`을 발생시킨다.
이 예외(Exception)를 개발자가 적절히 처리하지 않았다면, 게임은 멈추거나 크래시(Crash)로 이어져 유저에게 "앱이 종료되는" 경험을 선사하게 되는 것이다.
만국 공통의 안전 장치: CultureInfo.InvariantCulture
이러한 지역 설정 의존적인 문자열 파싱 문제를 해결하기 위한 표준 해법이 바로 `CultureInfo.InvariantCulture`이다.
InvariantCulture란?
InvariantCulture는 문화권 중립적인(Culture-Agnostic) 설정을 제공하는 CultureInfo 객체이다. 이는 특정 국가나 언어에 얽매이지 않고, 표준화된 방식으로 데이터 형식을 처리하도록 정의되어 있다.
특히 숫자 파싱에 있어서 InvariantCulture는 다음과 같은 규칙을 따르도록 강제한다.
- 소수점 구분 기호: `마침표(.)`로 고정한다.
- 천 단위 구분 기호: `콤마(,)`로 고정한다.
이는 영미권의 표준 형식과 일치하며, 대부분의 데이터 파일이나 개발 환경에서 하드코딩된 숫자 문자열 형식으로 사용되는 방식이다.
InvariantCulture를 사용한 안전한 파싱
float.Parse() 또는 Convert.ToSingle() 메서드를 사용할 때, 두 번째 인수로 CultureInfo.InvariantCulture를 명시적으로 전달하면 어떤 디바이스 환경에서도 항상 마침표(.)를 소수점으로 사용하여 파싱을 시도하게 된다.
안전하지 않은 코드 (잠재적 오류 발생):
// 터키/러시아 디바이스에서는 'FormatException' 발생 가능
string strValue = "123.45";
float unsafeValue = float.Parse(strValue);
안전한 코드
using System.Globalization;
// ...
// 어떤 디바이스에서도 '.'를 소수점으로 인식하도록 강제
string strValue = "123.45";
float safeValue = float.Parse(strValue, CultureInfo.InvariantCulture);
// Convert 클래스를 사용할 때도 동일하게 적용
float convertedValue = Convert.ToSingle(strValue, CultureInfo.InvariantCulture);
Tip: 만약 파싱에 실패했을 때 크래시를 방지하고 기본값 처리를 원한다면, float.TryParse() 메서드에 CultureInfo.InvariantCulture를 사용하는 것이 훨씬 안전하다.
using System.Globalization;
// ...
string strValue = "123.45";
if (float.TryParse(strValue, NumberStyles.Float, CultureInfo.InvariantCulture, out float result))
{
// 파싱 성공, result 사용
Debug.Log($"파싱 성공: {result}");
}
else
{
// 파싱 실패, 오류 처리 또는 기본값 사용
Debug.LogError("문자열 파싱에 실패했습니다.");
}
개발 환경을 넘어 데이터 관리까지
CultureInfo.InvariantCulture의 중요성은 단순히 문자열을 파싱할 때뿐만 아니라, 데이터를 파일(예: CSV, JSON)로 저장하거나 로그를 기록할 때에도 마찬가지로 중요하다.
- 데이터 저장 :fa-solid fa-database: : 만약 터키 디바이스에서 ToString()으로 숫자를 문자열로 변환하여 파일에 저장하면, 123,45 형태로 저장될 수 있다. 이 파일을 다른 지역의 개발자나 서버가 다시 읽어 들일 때, 소수점/콤마 문제로 인해 파싱 오류가 발생할 수 있다. 데이터를 저장할 때도 ToString(CultureInfo.InvariantCulture)를 사용하여 표준 형식으로 통일해야 한다.
- 로그 기록 :fa-solid fa-square-terminal: : 로그 파일에 숫자 값을 기록할 때도 InvariantCulture를 사용해야 나중에 로그를 분석하는 툴이나 스크립트가 전 세계 모든 로그 파일에서 일관된 포맷을 기대할 수 있다.
CultureInfo.InvariantCulture는 전역적으로 일관된 데이터 처리를 보장하는 소프트웨어의 '국제 표준 규격'을 적용하는 것과 같다. 이 작은 습관 하나가 전 세계 유저를 포용하는 글로벌 게임의 안정성을 크게 좌우하게 된다.
마무리
유니티 개발에서 문자열 파싱은 사소하게 여겨지기 쉽지만, 문화권별 차이를 고려하지 않으면 예기치 않은 곳에서 심각한 버그를 유발할 수 있다. 특히 터키나 러시아와 같이 소수점 구분 기호로 콤마(,)를 사용하는 지역에서 발생했던 앱 종료 문제는 `CultureInfo.InvariantCulture`를 사용함으로써 완벽하게 해결할 수 있다. 이 표준화된 방식을 프로젝트 전반에 적용하여, 모든 유저에게 안정적이고 쾌적한 게임 경험을 제공할 수 있도록 코드를 작성하는 것이 중요하다.
'Unity' 카테고리의 다른 글
| [Tip] Unity 버텍스 스냅핑(Vertex Snapping)을 활용한 오브젝트 정렬 (1) | 2026.01.07 |
|---|---|
| [Tip] Unity 인스펙터에서 표현식으로 오브젝트를 간편하게 정렬하는 방법 (0) | 2025.10.26 |
| [Tip] 유니티(Unity) 개발 속도 획기적으로 줄이는 방법 : Enter Play Mode (0) | 2025.08.28 |
| Unity C# 스크립트에서 summary 주석 활용하여 코드 가독성 높이는 방법 (0) | 2025.08.25 |
| [Tip] Unity 에서 Scene View 카메라를 Game View에 적용시키는 방법 (2) | 2025.07.24 |