파이썬 데이터 직렬화 표준 가이드, UTF-8부터 스키마 버전 관리까지 안전한 저장 형식 설계 방법
🧩 데이터 형식을 아무렇게나 저장하면 반드시 문제 생깁니다 파이썬 직렬화 포맷에 적용해야 할 공통 정책 6가지를 정리했습니다
데이터를 파일이나 API 응답으로 내보내다 보면 처음에는 잘 돌아가는 것처럼 보여도, 팀이 커지거나 버전이 쌓일수록 예측하지 못한 문제가 하나둘씩 드러납니다.
문자 인코딩이 달라서 한글이 깨진다든지, 줄바꿈 규칙이 엉켜서 git diff가 폭발한다든지, 서버는 UTC로 저장했는데 화면에서는 현지 시간인 척 보여주다 숫자 계산이 틀어진다든지, 금액을 float으로 처리했다가 소수점 오차가 쌓인다든지 하는 식이죠.
이건 결국 “데이터 직렬화 규칙을 초기에 얼마나 명확하게 박아두었는가”의 문제에 가깝습니다.
개별 개발자 취향이나 그때그때의 편의로 맡겨두면 나중에 바꾸기 정말 힘듭니다.
그래서 파이썬에서 JSON, YAML, CSV, Avro 등 어떤 포맷을 쓰든 공통으로 지켜야 하는 기본 원칙을 조직 차원에서 문서화해두는 게 중요합니다.
이번 글에서는 파이썬에서 사용하는 모든 데이터 직렬화 포맷에 공통으로 적용해야 할 핵심 정책을 정리합니다.
핵심은 다음과 같습니다.
첫째, 인코딩은 UTF-8로 고정합니다.
둘째, 개행은 \n으로 통일합니다.
셋째, 타임존은 UTC로 저장하고 사용자에게는 별도로 표시합니다.
넷째, 금액처럼 정밀한 수치는 Decimal로 관리합니다.
다섯째, 스키마 버전을 version이나 $schema 필드로 명시합니다.
여섯째, 호환성과 마이그레이션 계획을 미리 세워서 과거 데이터를 깨뜨리지 않도록 합니다.
이 내용은 단순한 베스트 프랙티스가 아니라, 장기적으로 유지 가능한 데이터 계약(data contract)을 만드는 최소 조건에 가깝습니다.
팀 내 규칙 문서나 사내 공용 라이브러리의 기본 정책으로 삼기에도 적합합니다.
📋 목차
📌 UTF-8 고정과 개행 \n 통일은 왜 필수인가
파이썬으로 JSON, CSV, YAML 등 어떤 직렬화 포맷을 만들든 가장 먼저 정해야 하는 건 문자 인코딩과 줄바꿈 규칙입니다.
인코딩은 반드시 UTF-8로 고정하고, 줄바꿈은 \n(Newline, LF)로 통일한다는 원칙이 필요합니다.
이 두 가지는 겉으로 보기엔 사소해 보이지만, 나중에 협업과 배포 환경이 다양해질수록 품질과 유지보수 비용을 좌우하게 됩니다.
먼저 UTF-8 고정부터 이야기해볼 만합니다.
만약 어떤 파일은 UTF-8, 어떤 파일은 CP949나 EUC-KR처럼 다른 인코딩으로 저장된다면 운영 환경이 달라질 때마다 깨질 가능성이 생깁니다.
로컬 윈도우 환경에서는 정상처럼 보이던 한글이, 리눅스 컨테이너나 클라우드 배치 작업 로그에서는 “ìë” 식으로 깨지는 익숙한 문제들이 여기서 나옵니다.
API나 데이터 파이프라인은 결국 여러 언어, 여러 OS, 여러 데이터 처리 도구에 걸쳐서 소비되기 때문에, UTF-8로 통일해두면 어느 쪽에서도 추가 변환 없이 안전하게 읽고 쓸 수 있습니다.
결국 UTF-8은 협업의 기본 언어라고 보면 됩니다.
실무에서는 이걸 그냥 구두로만 정하면 안 되고, 실제 코드 레벨에서 강제해 두는 게 좋습니다.
예를 들어 파이썬에서 파일을 쓸 때는 다음처럼 encoding=”utf-8″을 명시해주는 식입니다.
이렇게 해두면 개발자별 OS나 IDE 기본 설정이 달라도 결과물은 항상 동일해집니다.
import json
data = {
"name": "테스트",
"status": "ok"
}
# UTF-8 인코딩 고정
with open("result.json", "w", encoding="utf-8", newline="\n") as f:
json.dump(data, f, ensure_ascii=False)
f.write("\n") # 마지막 개행 규칙까지 명시적으로 관리
여기서 눈여겨볼 부분이 하나 더 있습니다.
바로 newline=”\n”입니다.
줄바꿈 문자는 생각보다 민감합니다.
운영체제마다 기본 줄바꿈 문자가 다르기 때문입니다.
리눅스와 macOS는 LF(\n), 윈도우는 CRLF(\r\n)를 기본으로 사용합니다.
같은 내용의 JSON이라도 한쪽은 \n, 다른 쪽은 \r\n으로 저장되면 git diff가 온통 개행 차이로 물들어 버리고 실제 변경 내역을 리뷰하기 힘들어집니다.
CI에서 체크섬(hash) 비교할 때도 “내용은 같은데 줄바꿈만 달라서” 다른 파일로 취급되어 버리고요.
그래서 조직 차원에서 “모든 직렬화 파일은 \n(LF)만 허용한다”라고 못을 박아두는 게 좋습니다.
이건 단순한 취향 통일이 아니라, 재현 가능한 결과물(reproducible output)을 만드는 핵심입니다.
데이터 덤프를 만들어 아티팩트로 보관하거나 히스토리컬 데이터 세트를 장기간 축적할 때, 줄바꿈이 표준화돼 있으면 훨씬 안정적으로 비교, 검증, 감사(audit)가 가능합니다.
💡 TIP: 깃 훅(pre-commit)이나 CI에서 UTF-8 여부와 LF 여부를 자동으로 검사해두면 “사람이 실수로 규칙을 어기는 상황”을 초반에 차단할 수 있습니다.
사후 정리보다 사전 차단이 훨씬 저렴합니다.
⚠️ 주의: 어떤 팀은 “우리는 윈도우에서만 돌리니까 CRLF로 가자”라고 합의해버리기도 합니다.
겉으로는 편해 보이지만, 나중에 컨테이너 기반 배치 잡, 리눅스 기반 서버리스 함수, 클라우드 데이터 파이프라인으로 확장될 때 호환성이 크게 떨어질 수 있습니다.
장기적으로 보면 LF(\n) 단일화가 더 안전합니다.
| 정책 항목 | 왜 필요한가 |
|---|---|
| 모든 직렬화 파일은 UTF-8로 인코딩 | 한글/이모지 등 멀티바이트 문자 손상 방지, 다양한 플랫폼 간 일관성 확보 |
| 모든 줄바꿈은 \n(LF)만 허용 | git diff 안정화, 체크섬 일관성 확보, 재현 가능한 빌드/아카이빙 가능 |
정리하자면, “UTF-8 인코딩 고정”과 “개행은 \n으로 통일”은 사소한 코드 스타일 문제가 아니라, 데이터의 진실성을 보존하고 팀의 시간과 스트레스를 아끼는 최소한의 방어막입니다.
파이썬 프로젝트라면 파일 저장 함수, 로깅 유틸, 데이터 익스포트 유틸에 이 두 가지를 공통 기본값으로 심어두는 방식을 추천합니다.
🌍 타임존은 UTC로 저장하고 표시는 분리한다
데이터 직렬화에서 시간(Time) 처리는 늘 복병입니다.
시각 데이터를 잘못 저장하거나 표시하면, 실제로는 같은 시각인데 지역별로 달라 보이거나, 서버와 사용자 화면 간 시간이 엇갈려 혼란을 일으키곤 합니다.
이런 문제는 대부분 “저장 시 타임존이 섞여버린 경우”에서 시작됩니다.
그래서 시간은 UTC로 저장하고, 표시할 때만 지역 시간으로 변환하는 원칙이 절대적으로 중요합니다.
UTC(협정 세계시)는 전 세계에서 공통으로 사용하는 기준 시각입니다.
서울은 UTC+9, 런던은 UTC+0, 뉴욕은 UTC-5 식으로 각 지역이 UTC를 기준으로 오프셋을 갖습니다.
데이터를 UTC로 저장하면, 어느 나라에서 API를 호출하든 “시간대 변환”을 단 한 번의 계산으로 해결할 수 있습니다.
반대로 “저장 자체를 지역 시각으로 해버리면” 국가별, 서버별 환경마다 결과가 달라져 버립니다.
로그, 이벤트 타임스탬프, 예약 스케줄 같은 데이터가 일관성을 잃게 됩니다.
파이썬에서는 datetime 객체를 항상 timezone-aware 상태로 유지하는 것이 중요합니다.
즉, naive datetime(타임존 정보 없는 객체)을 피하고 tzinfo가 명시된 형태로 다뤄야 합니다.
예를 들어 아래 코드는 UTC 기반으로 현재 시각을 얻어 직렬화할 때 올바른 형태입니다.
from datetime import datetime, timezone
import json
data = {
"event": "user_signup",
"created_at": datetime.now(timezone.utc).isoformat()
}
print(json.dumps(data, indent=2))
출력 결과는 다음과 같습니다.
{
"event": "user_signup",
"created_at": "2025-10-28T09:43:00.512Z"
}
여기서 끝의 “Z”는 UTC 시각임을 의미합니다.
이 형태는 ISO 8601 표준 형식이므로, 어떤 언어나 환경에서도 타임존 정보를 잃지 않습니다.
즉, 저장 단계에서부터 UTC로 통일하면 서버, DB, 클라이언트 간 시간 불일치 문제를 원천 차단할 수 있습니다.
표시 단계에서는 사용자의 로컬 타임존을 반영해 변환하면 됩니다.
예를 들어 한국 사용자는 UTC 시각에 +9시간을 더한 값으로 보여주면 되고, 브라우저의 Intl API나 moment.js, day.js 같은 라이브러리를 활용하면 간단하게 처리할 수 있습니다.
💡 TIP: 서버-클라이언트 구조에서는 서버는 UTC 기준으로 저장, 프런트엔드는 현지 시간으로 표시라는 역할 분리를 명확히 하는 게 핵심입니다.
양쪽이 중간 어딘가에서 애매하게 변환하면 결국 두 번 변환되거나 아예 변환되지 않는 일이 생깁니다.
또한 DB나 로그 시스템에서도 UTC 통일은 필수입니다.
특히 AWS, GCP, Azure와 같은 클라우드 환경에서는 서버 인스턴스의 기본 시간대가 UTC이기 때문에, 이를 그대로 유지해야 모든 시스템 로그의 시각이 일관성을 가집니다.
만약 DB는 UTC, 애플리케이션은 KST로 설정되어 있다면, 동일한 이벤트가 서로 다른 시점으로 기록되어 추적이 불가능해질 수 있습니다.
| 단계 | 원칙 |
|---|---|
| 데이터 저장 | UTC 기준으로 저장 (ISO 8601 형식, Z 표시 포함) |
| 데이터 표시 | 사용자 로컬 타임존 기준으로 변환 후 노출 |
결국 UTC 저장 원칙은 데이터 일관성을 위한 ‘시간의 기준점’을 세우는 일입니다.
시스템이 여러 국가로 확장될수록, 또 로그나 분석 데이터를 장기적으로 보관할수록 UTC 통일의 가치가 더 커집니다.
💸 정밀 수치는 float이 아니라 Decimal로 관리한다
데이터 직렬화 과정에서 종종 간과되지만, 실제로 가장 많은 장애를 일으키는 부분 중 하나가 바로 수치 정밀도(precision) 문제입니다.
특히 금액, 환율, 측정값처럼 소수점 이하 단위가 중요한 데이터를 float 타입으로 저장했다가, 나중에 “0.1 + 0.2 = 0.30000000000000004” 같은 결과가 나오는 경험을 한 분도 많을 겁니다.
이는 컴퓨터 내부의 부동소수점 연산 특성 때문으로, 직렬화 단계에서부터 float을 그대로 사용하면 데이터의 신뢰도가 무너질 수 있습니다.
그래서 파이썬의 Decimal 클래스를 사용하는 것이 표준적인 해결책입니다.
Decimal은 금융, 회계, 통계 처리 등에서 오차 없이 정확한 계산을 보장합니다.
또한 JSON 직렬화 시에도 문자열로 변환해 저장하면 다른 언어나 시스템과의 호환성을 쉽게 확보할 수 있습니다.
from decimal import Decimal
import json
data = {
"price": str(Decimal("19.99")),
"tax": str(Decimal("1.50"))
}
print(json.dumps(data, indent=2))
이렇게 저장하면 출력 결과는 다음과 같습니다.
{
"price": "19.99",
"tax": "1.50"
}
즉, Decimal을 문자열 형태로 직렬화하면 데이터 손실 없이 안전하게 교환할 수 있습니다.
다른 언어(Java, Go, JavaScript 등)에서도 이 문자열을 Decimal 타입으로 다시 파싱하여 동일한 정밀도로 계산할 수 있기 때문입니다.
💎 핵심 포인트:
직렬화 시 float을 절대 그대로 쓰지 말고 Decimal을 문자열로 변환해야 합니다.
이렇게 해야 정밀도를 잃지 않고, 데이터 분석이나 재계산 과정에서도 오류가 누적되지 않습니다.
또한 Decimal을 사용할 때는 context precision을 명시적으로 설정해 두면 좋습니다.
예를 들어 소수점 이하 6자리까지만 계산하도록 전역 설정을 고정할 수 있습니다.
from decimal import Decimal, getcontext
getcontext().prec = 6 # 소수점 6자리 정밀도 유지
a = Decimal("10.1234567")
b = Decimal("0.0000012")
print(a + b) # 10.1235
이처럼 명시적인 정밀도 관리가 가능하다는 점에서 Decimal은 단순한 데이터 타입이 아니라 데이터 무결성을 지키는 도구로 이해하는 게 맞습니다.
특히 금액, 단가, 세율, 환율 등 “소수점 단위가 의미 있는 수치”를 다루는 모든 직렬화 정책에서 필수로 포함되어야 합니다.
| 항목 | 권장 방식 |
|---|---|
| 가격, 세율, 통화 데이터 | Decimal로 계산하고 문자열로 직렬화 |
| 측정값, 좌표, 물리 단위 | 정밀도 요구 시 Decimal 사용, 그렇지 않으면 float 가능 |
⚠️ 주의: 일부 JSON 라이브러리는 Decimal을 직접 직렬화할 수 없습니다.
이 경우 반드시 문자열로 변환하거나 custom encoder를 정의해야 합니다.
그렇지 않으면 TypeError가 발생합니다.
요약하면, 정밀 수치는 Decimal로 관리하고, float은 임시 계산에만 사용하는 것이 파이썬 데이터 직렬화의 기본 원칙입니다.
이것만 지켜도 수치 오차로 인한 회계 오류나 데이터 불일치 문제를 대부분 예방할 수 있습니다.
📂 스키마 버전은 version 또는 $schema 필드로 명시한다
데이터 직렬화 포맷에서 종종 빠지는 항목이 바로 스키마 버전 관리입니다.
처음에는 “필드 몇 개만 직렬화하면 되니까 간단하지” 싶지만, 시간이 지나며 구조가 바뀌거나 새 필드가 추가되면 이전 데이터와 충돌하기 시작합니다.
이 문제를 근본적으로 막는 가장 확실한 방법이 바로 version 또는 $schema 필드를 명시적으로 포함하는 것입니다.
스키마 버전은 말 그대로 “이 데이터가 어떤 구조로 만들어졌는가”를 알려주는 정보입니다.
예를 들어 JSON, YAML, Avro 등 어떤 형식을 쓰더라도, 다음처럼 버전 필드를 항상 포함하면 이후 유지보수와 마이그레이션이 훨씬 수월해집니다.
{
"$schema": "https://example.com/schema/user-profile-v2.json",
"version": 2,
"name": "홍길동",
"email": "hong@example.com"
}
이렇게 해두면, 나중에 v3에서 구조가 달라져도 기존 데이터를 안전하게 해석할 수 있습니다.
데이터를 읽는 쪽에서는 version 필드를 보고 “v2 구조로 처리해야겠다”라고 판단할 수 있기 때문이죠.
결국 이건 단순히 숫자를 하나 추가하는 게 아니라 데이터 계약(data contract)을 명문화하는 행위에 가깝습니다.
파이썬에서는 dataclass나 pydantic 모델을 사용할 때, 스키마 버전을 상수로 포함시키는 방식이 좋습니다.
예를 들어 다음처럼 데이터 모델 안에 버전을 명시적으로 포함해두면, 모든 직렬화 결과물에서 일관성 있게 유지됩니다.
from pydantic import BaseModel
class UserProfile(BaseModel):
version: int = 2
name: str
email: str
또한 JSON Schema를 병행하면 자동 검증이 가능해집니다.
“$schema” 필드로 스키마 정의 URL을 명시하고, 외부 검증 도구(jsonschema, ajv 등)로 유효성을 체크하면 “스키마가 바뀌었을 때 어느 데이터가 영향을 받는가”를 빠르게 파악할 수 있습니다.
💡 TIP: 스키마 버전은 “데이터 구조의 약속”을 나타냅니다.
개발자 간, 서비스 간, 그리고 과거 데이터와 미래 데이터 간의 호환성을 유지하려면 반드시 포함해야 합니다.
실무에서는 버전 필드만으로는 부족할 수 있습니다.
그래서 보통 다음과 같은 정책을 함께 둡니다.
- 📘모든 직렬화 파일은 최소 1개 이상의 version 또는 $schema 필드 포함
- 📗변경 시 마이그레이션 매뉴얼에 버전 간 차이 기록
- 📙스키마 검증 자동화 (CI 단계에서 jsonschema validate 실행)
이 정책이 제대로 자리 잡으면 “필드가 빠졌다”, “형식이 달라졌다” 같은 혼란을 초반에 방지할 수 있습니다.
또한, 데이터 API나 외부 파트너와의 연동 시에도 명시된 버전 정보를 통해 명확하게 대응할 수 있습니다.
⚠️ 주의: “우리는 내부용이라 버전 필요 없다”는 생각은 위험합니다.
한 번이라도 구조가 바뀌면 과거 백업, 로그, 캐시 데이터가 전부 무용지물이 될 수 있습니다.
항상 버전 필드를 포함하세요.
정리하자면, 스키마 버전 명시는 단순한 문서화가 아니라, 데이터 시스템의 진화 과정을 안전하게 이어주는 설계 기반입니다.
모든 직렬화 포맷에서 “version” 또는 “$schema”를 필수 필드로 두는 것, 이것이 장기 유지 가능한 데이터 구조의 첫걸음입니다.
🛠️ 호환성과 마이그레이션 계획을 미리 설계한다
데이터 직렬화 포맷을 설계할 때 가장 어려운 부분이 바로 “시간이 지나도 깨지지 않게 유지하는 것”입니다.
즉, 지금의 코드가 1년 뒤에도, 버전이 바뀐 다음에도 여전히 기존 데이터를 읽고 처리할 수 있어야 합니다.
이걸 가능하게 만드는 핵심 개념이 바로 호환성(compatibility)과 마이그레이션(migration) 설계입니다.
일반적으로 데이터 구조가 바뀌면 세 가지 형태의 호환성 문제가 생깁니다.
- 🔄Backward compatibility — 새로운 코드가 이전 버전의 데이터를 여전히 읽을 수 있는가?
- ⬆️Forward compatibility — 이전 코드가 새 버전의 데이터를 최소한 무시하지 않고 읽을 수 있는가?
- ⚖️Full compatibility — 양쪽이 서로 다른 버전의 데이터를 완전히 이해하고 처리할 수 있는가?
이 중 최소한 Backward compatibility는 반드시 지켜야 합니다.
새 버전이 배포되더라도 기존의 JSON, CSV, YAML 데이터를 읽을 수 있어야 “데이터 손실 없이 진화”가 가능하기 때문입니다.
이를 위해서는 다음과 같은 전략이 필요합니다.
- 📌기존 필드는 삭제하지 말고, deprecated 표시를 추가한 뒤 일정 기간 유지
- 📌새 필드 추가 시 기본값을 설정해 null 에러를 방지
- 📌파서(parser)는 예기치 못한 필드가 있어도 무시하도록 설계
- 📌데이터 버전별 마이그레이션 스크립트를 관리 (예: v1 → v2 변환기)
파이썬에서는 이런 변환 로직을 별도의 migrations 모듈로 분리해두면 좋습니다.
아래는 버전별 변환 예시입니다.
def migrate_v1_to_v2(data: dict) -> dict:
"""사용자 데이터 구조를 v1에서 v2로 변환"""
if "username" in data and "name" not in data:
data["name"] = data["username"]
del data["username"]
data["version"] = 2
return data
이런 마이그레이션 스크립트를 준비해두면, 새로운 버전이 추가될 때마다 기존 데이터를 안전하게 변환할 수 있습니다.
API나 배치 작업에서도 이 함수를 공용으로 호출하면, 어디서든 자동으로 버전 업그레이드가 일어납니다.
💎 핵심 포인트:
데이터 형식을 바꾸는 것은 코드보다 훨씬 비쌉니다.
그래서 “한 번 배포된 데이터는 절대 깨지지 않는다”는 원칙 아래에서 호환성을 유지해야 합니다.
그게 바로 데이터 엔지니어링의 신뢰도를 결정짓는 요소입니다.
호환성 정책은 단순한 기술적 설정이 아니라, 팀 문화의 일환입니다.
“필드 이름을 함부로 바꾸지 않는다”, “모든 데이터에는 버전을 포함한다”, “새 필드는 backward-safe하게 추가한다” 같은 원칙이 문서화돼야 합니다.
이렇게 하면 새로운 개발자가 합류하거나 시스템이 확장돼도, 데이터 파이프라인 전체가 안정적으로 유지됩니다.
| 항목 | 권장 정책 |
|---|---|
| 기존 필드 변경 | 삭제 금지, deprecated 주석 추가 |
| 새 필드 추가 | 기본값 포함, backward compatible 보장 |
| 버전 업그레이드 | 마이그레이션 스크립트 작성 및 자동 테스트 추가 |
요약하자면, 직렬화 포맷을 설계할 때 가장 중요한 건 “앞으로도 안전하게 진화할 수 있는 구조”를 만드는 일입니다.
즉, 지금의 편의보다 내일의 안정성을 우선해야 한다는 뜻입니다.
이 원칙을 팀의 공통 정책으로 삼으면, 데이터 변경이 두렵지 않은 시스템을 만들 수 있습니다.
❓ 자주 묻는 질문 (FAQ)
UTF-8 대신 다른 인코딩을 써도 되나요?
\n 대신 \r\n을 써도 문제는 없나요?
UTC 저장이 꼭 필요한 이유가 뭔가요?
Decimal을 꼭 문자열로 직렬화해야 하나요?
스키마 버전 필드가 없으면 어떤 문제가 생기나요?
직렬화 포맷마다 정책이 달라도 되나요?
기존 데이터를 새 포맷으로 바꾸려면 어떻게 하나요?
호환성을 테스트하는 좋은 방법이 있을까요?
🧾 데이터를 오래 버틸 수 있게 만드는 직렬화의 기본 원칙
데이터 직렬화는 단순히 ‘파일로 저장하는 행위’가 아닙니다.
시간이 지나도 변하지 않는 데이터 계약을 정의하는 일입니다.
이번 글에서 다룬 여섯 가지 원칙은, 파이썬뿐 아니라 어떤 언어와 환경에서도 통하는 데이터 지속성의 최소 기준입니다.
정리하자면 다음과 같습니다.
- ✅UTF-8 고정으로 문자 깨짐 방지
- ✅\n 통일로 OS 간 차이 제거
- ✅UTC 저장, 지역 표시 분리로 시각 일관성 확보
- ✅Decimal 사용으로 정밀도 유지
- ✅version 또는 $schema 명시로 구조 진화 관리
- ✅호환성/마이그레이션 계획으로 장기 안정성 확보
이 여섯 가지 규칙을 팀의 코드 컨벤션과 저장 정책에 포함시키면, 데이터 손상, 파싱 오류, 버전 충돌 같은 문제의 대부분을 예방할 수 있습니다.
직렬화 정책은 한 번 정하면 오래갑니다.
따라서 지금의 설계가 나중의 비용을 좌우합니다.
조금 번거롭더라도 지금 확실히 정해두는 게 최선의 선택입니다.
결국 “데이터는 한 번 저장되면 끝이 아니라, 시간이 지나도 계속 읽히고 해석돼야 한다”는 관점이 중요합니다.
그 기준을 잡아주는 게 바로 오늘 이야기한 파이썬 데이터 직렬화 공통 정책입니다.
🏷️ 관련 태그 : 파이썬직렬화, 데이터표준화, UTF8인코딩, 타임존UTC, Decimal정밀도, JSON스키마, 데이터호환성, 마이그레이션전략, 백엔드가이드, 데이터엔지니어링