Node.js 빌드 로그 JSONB 파싱 오류 및 asyncpg 타입 불일치 문제
Node.js 빌드 로그 파싱 오류 및 asyncpg 타입 불일치 문제 해결 경험 공유. 데이터 타입 변환 및 로직 오류 수정 과정.
Node.js 빌드 로그 JSONB 파싱 오류 및 asyncpg 타입 불일치 문제
빌드 로그 데이터를 처리하다가 JSONB 필드 파싱 오류와 비동기 PostgreSQL 라이브러리(asyncpg)에서 발생하는 데이터 타입 불일치 문제로 꽤나 고생했습니다. 이 글은 비슷한 증상으로 어려움을 겪는 분들께 도움이 되고자 작성했습니다.
시도와 함정
처음에는 JSONB 데이터의 summary 필드가 예상치 못한 문자열 형태로 들어오는 경우를 대비해 파싱 로직에 방어 코드를 추가했습니다. 하지만 문제는 여기서 끝나지 않았죠. asyncpg 라이브러리가 date 객체를 직접 전달받지 못하고 문자열만 받는다는 것을 알게 되었습니다.
# 예시: 초기 파싱 시도 (문자열 반환 케이스 방어) try: summary_data = json.loads(row.summary) except json.JSONDecodeError: summary_data = {} # 혹은 기본값 처리예시: asyncpg 타입 불일치 발생 지점 추측
row.date는 datetime 객체였지만, asyncpg는 문자열을 기대하는 듯 보였다.
await db.execute("INSERT INTO build_logs (date, summary) VALUES ($1, $2)", row.date, row.summary)
asyncpg가 date 객체를 문자열로 변환하지 못해 오류가 발생하는 것을 확인하고, build_log 테이블의 date 컬럼에 date 객체를 직접 전달하도록 코드를 수정했습니다.
# asyncpg 타입 불일치 해결 시도
# row.date는 datetime 객체
await db.execute("INSERT INTO build_logs (date, summary) VALUES ($1, $2)", row.date.isoformat(), row.summary)
이 과정에서 get_model_for_tier 함수에서 'lite' 티어에 대한 task 이름을 잘못 참조하는 KeyError도 발견했습니다.
원인
주요 원인은 두 가지였습니다. 첫째, asyncpg 라이브러리가 데이터베이스에 date 객체를 직접 전달받을 때 예상치 못한 타입 변환 오류를 발생시켰습니다. 둘째, 특정 로직에서 'lite' 티어에 대한 task 이름을 잘못 참조하는 KeyError가 있었습니다.
해결
JSONB 파싱 관련 오류는 json.loads를 사용해 명시적으로 파싱하도록 처리했습니다. asyncpg의 타입 불일치 문제는 date 객체를 .isoformat()을 사용하여 문자열로 변환한 후 전달함으로써 해결했습니다. 또한, get_model_for_tier 함수 내 'lite' 티어의 잘못된 task 참조를 수정했습니다.
# 최종 해결 코드 (간략화) import json from datetime import datetime... (db 연결 및 기타 설정)
async def process_build_log(row): # JSONB 파싱 오류 처리 try: summary_data = json.loads(row.summary) except json.JSONDecodeError: summary_data = {"error": "Invalid JSON"} # 혹은 다른 기본값
# asyncpg 타입 불일치 해결 (date 객체를 isoformat 문자열로 변환) date_str = row.date.isoformat() if isinstance(row.date, datetime) else str(row.date) await db.execute( "INSERT INTO build_logs (date, summary) VALUES ($1, $2)", date_str, json.dumps(summary_data) # 다시 JSON 문자열로 저장 )def get_model_for_tier(tier): task_map = { 'standard': 'standard_task', 'lite': 'lite_task', # 올바른 task 이름으로 수정 'premium': 'premium_task', } return task_map.get(tier)
... (이후 로직)
결과
- 빌드 로그 데이터의 JSONB 파싱 및 저장 과정이 안정화되었습니다.
asyncpg라이브러리를 통한 데이터베이스 쓰기 작업에서 타입 불일치 오류가 사라졌습니다.- 'lite' 티어 조회 시 발생하던
KeyError가 해결되어 해당 기능이 정상 작동합니다.
정리 — 같은 함정 안 빠지려면
- [ ] 데이터베이스 라이브러리 사용 시, 예상치 못한 타입 변환 오류가 발생할 수 있음을 인지합니다.
- [ ]
date,datetime객체 등은 데이터베이스 라이브러리가 요구하는 형식(주로 문자열)으로 명시적으로 변환하여 전달합니다..isoformat()이 유용합니다. - [ ] JSON 데이터를 다룰 때는 항상
json.JSONDecodeError와 같은 예외 처리를 잊지 않습니다. - [ ] 복잡한 로직에서는 딕셔너리 키 참조 시
KeyError발생 가능성을 염두에 두고.get()메서드나try-except블록을 활용합니다.
태그