관리 메뉴

밤 늦게까지 여는 카페

[Python] json 데이터에 한글이 포함되어 있을 때 dumps 호출하면 깨지는 현상 본문

For Fun/잡학 지식

[Python] json 데이터에 한글이 포함되어 있을 때 dumps 호출하면 깨지는 현상

Jㅐ둥이 2024. 4. 19. 22:08

안녕하세요. 오늘은 Python을 이용해서 로그를 저장하다가 발견한 한글 깨짐 이슈를 기록해보려고 합니다.

 

정말 간단한 이슈였는데 힘들게 찾아서 참 씁쓸했습니다... ㅋㅋㅋ

TL-DR

  • json 데이터에 한글이 포함되어 있는 상태에서 dump 해야 한다면 ensure_ascii=False 인자를 추가하자!
  • 예시) json.dumps(data, ensure_ascii=False)

1. 로그 저장 과정

로그가 저장되는 과정을 간단하게 설명하면 아래 그림과 같습니다.

로그 저장 과정

 

IoT Core로 들어온 데이터가 Kinesis Data Firehose를 통해서 Amazon Lambda로 전달됩니다.

Lambda로 전달된 데이터는 약간의 가공을 거친 뒤 S3에 저장됩니다.

  • 뒤에 Glue, Athena도 있지만 크게 중요하지 않아서 제외했습니다.

2. Lambda의 역할

AWS IoT Core에 전달되는 데이터는 아래와 같은 형태입니다.

{
  "level": "info",
  "msg": "succeed to send message.",
  "timestamp": "2024-04-18 22:00:10.903228"
}

 

 

그런데 Kinesis에서 데이터가 합쳐져서 Lambda로 전달될 때 데이터가 1줄로 취급된다는 문제가 있습니다.

[
    {
      "level": "info",
      "msg": "succeed to send message.",
      "timestamp": "2024-04-18 22:00:10.903228"
    },
    {
      "level": "info",
      "msg": "failed to send message.",
      "timestamp": "2024-04-18 22:00:10.903228"
    }
]
=>
{"level":"info","msg":"succeed to send message.","timestamp":"2024-04-18 22:00:10.903228"},{"level":"info","msg":"failed to send message.","timestamp":"2024-04-18 22:00:10.903228"}

 

 

이를 해결하기 위해서 중간에 Lambda를 붙인 것이었습니다.

Lambda를 붙이면 각 데이터 사이에 "\n"을 추가해서 서로 다른 데이터로 인식할 수 있는 것이죠.

 

3. 한글 로그가 깨지는 문제 발생

이제 편하게 로그를 볼 수 있어서 정말 좋았는데 정말 이상하게도 데이터에 한글이 포함되어 있으면 로그가 깨지는 문제가 발생합니다.

 

분명히 AWS IoT Core로 전달할 때는 아래와 같이 한글 인코딩이 문제 없었는데

{
  "level": "info",
  "msg": "네트워크 통신에 실패했습니다.",
  "timestamp": "2024-04-18 22:00:10.903228"
}

 

Athena를 통해서 로그를 조회하면 다음과 같이 한글이 깨지는 것입니다 ㅜㅠ

{
  "level": "info",
  "msg": "\\ub124\\ud2b8\\uc6cc\\ud06c \\ud1b5\\uc2e0\\uc5d0 \\uc2e4\\ud328\\ud588\\uc2b5\\ub2c8\\ub2e4.",
  "timestamp": "2024-04-18 22:00:10.903228"
}

 

4. 원인 파악

처음에는 인코딩 문제인가 싶었는데 찾다 찾다보니 Python json 라이브러리의 문제라는 것을 알 수 있었습니다ㅜㅠ

 

Lambda는 다음과 비슷하게 코드가 작성되어 있는데 바로 json.dumps 함수가 문제였습니다.

def lambda_handler(event, context):
    output_records = []
    
    for record in event["records"]:
        output_records.append(json.dumps(record)+"\n")
        
    return {"records": output_records}

 

dumps 함수는 기본적으로 json 데이터를 아스키 코드로 저장하는데

 

한글처럼 아스키 코드가 없는 문자의 경우 유니코드로 변환되는 것이었습니다.

예시

 

5. 해결!

해결 방법은 정말 간단하게도 json.dumps 함수를 호출할 때 ensure_ascii=False 인자를 추가해주는 것입니다.

https://github.com/python/cpython/blob/3.12/Lib/json/__init__.py

반응형