메뉴 닫기

파이썬 ast.literal_eval 안전한 문자열 파싱과 예외 처리 완벽 가이드

파이썬 ast.literal_eval 안전한 문자열 파싱과 예외 처리 완벽 가이드

🚀 파이썬 문자열을 안전하게 다루는 법부터 예외 처리까지 한 번에 정리했습니다

파이썬을 배우다 보면 문자열을 코드처럼 실행하거나 변환해야 하는 경우가 자주 생깁니다.
그중 많은 초보자들이 eval() 함수를 무심코 사용하다가 보안 문제에 노출되곤 하는데요.
실제로 eval은 외부 입력을 그대로 실행해버리기 때문에 해킹이나 시스템 손상 위험까지 발생할 수 있습니다.
이런 문제를 예방하기 위해 파이썬에서는 안전하게 리터럴을 평가할 수 있는 ast.literal_eval()이라는 함수를 제공합니다.
개발 실무에서 JSON, 딕셔너리, 리스트 등의 문자열 데이터를 안전하게 변환할 때 반드시 알아두어야 하는 핵심 도구입니다.

이 글에서는 ast.literal_eval이 무엇인지, 왜 안전한지, 어떤 데이터에서 활용할 수 있는지, 그리고 발생할 수 있는 예외와 올바른 처리 방법까지 단계별로 살펴보겠습니다.
특히 문자열 파싱 과정에서 마주칠 수 있는 대표적인 에러 상황과 대처법도 함께 정리했으니, 중급 수준의 파이썬 개발자라면 실무에 바로 적용할 수 있을 것입니다.



🔎 ast.literal_eval이란 무엇인가?

파이썬에서 ast.literal_eval() 함수는 문자열로 표현된 파이썬 리터럴을 안전하게 파싱하여 실제 객체로 변환하는 기능을 제공합니다.
여기서 리터럴이란 숫자, 문자열, 리스트, 딕셔너리, 튜플, 불리언 값 등 코드 실행과 관계없는 순수 데이터 구조를 의미합니다.
즉, 코드 실행을 하지 않고 데이터만 해석하기 때문에 보안상 안전합니다.

예를 들어, JSON 문자열과 유사한 데이터를 받아서 리스트나 딕셔너리로 변환해야 하는 상황에서 자주 쓰입니다.
단순히 eval()을 사용할 경우 코드 실행까지 일어나 보안에 치명적이지만, literal_eval은 오직 리터럴 데이터만 허용하기 때문에 안전한 데이터 처리가 가능합니다.

CODE BLOCK
import ast

data_str = "{'name': 'Alice', 'age': 25, 'hobbies': ['coding', 'music']}"
result = ast.literal_eval(data_str)

print(result)
print(type(result))

위 코드에서 문자열 형태의 딕셔너리를 literal_eval에 전달하면, 실제 파이썬 딕셔너리 객체로 안전하게 변환됩니다.
실행 결과는 {‘name’: ‘Alice’, ‘age’: 25, ‘hobbies’: [‘coding’, ‘music’]} 와 같은 딕셔너리로 반환되며, 타입은 dict입니다.

💡 TIP: JSON 데이터를 처리할 때는 json.loads()가 더 적합하지만, 파이썬 고유의 리터럴 문자열을 다룰 때는 ast.literal_eval()이 강력한 도구가 됩니다.

🛡️ eval과 literal_eval의 차이와 보안성

파이썬의 eval() 함수는 문자열을 받아 파이썬 코드로 실행하는 기능을 제공합니다.
즉, 단순한 데이터뿐 아니라 함수 호출, 변수 참조, 심지어 시스템 명령 실행까지 가능하다는 뜻입니다.
이 때문에 eval을 그대로 사용하는 것은 보안상 매우 위험하며, 특히 외부 입력을 처리할 때는 치명적인 보안 취약점으로 이어질 수 있습니다.

반면 ast.literal_eval()은 이름 그대로 ‘리터럴’만 허용합니다.
즉, 숫자, 문자열, 리스트, 튜플, 딕셔너리, 불리언, None 과 같은 기본 데이터만 변환할 수 있고, 함수나 클래스 실행 같은 동적 코드 실행은 전혀 허용되지 않습니다.
이 차이 덕분에 literal_eval은 안전한 데이터 파싱에 특화되어 있습니다.

CODE BLOCK
import ast

# eval 사용 (위험)
user_input = "__import__('os').system('rm -rf /')"  
# 절대 실행하면 안 되는 위험한 코드

# literal_eval 사용 (안전)
safe_input = "{'id': 1, 'role': 'admin'}"
print(ast.literal_eval(safe_input))

⚠️ 주의: eval은 악의적인 문자열이 들어올 경우 시스템 명령 실행으로 이어질 수 있습니다. 따라서 사용자 입력을 처리할 때는 반드시 eval 대신 ast.literal_eval을 사용하는 것이 안전합니다.

정리하자면, eval은 유연하지만 보안 위험이 크고, literal_eval은 기능이 제한적이지만 안전합니다.
실무에서는 보안이 최우선이므로 eval은 가능한 한 피하고 literal_eval을 습관적으로 사용하는 것이 올바른 접근입니다.



⚙️ 활용 가능한 데이터 타입과 예제

ast.literal_eval은 파이썬에서 안전하게 사용할 수 있는 특정 리터럴 타입만 허용합니다.
이는 문자열을 그대로 코드 실행하는 것이 아니라, 단순히 데이터 구조로 변환하는 방식이기 때문입니다.
다음은 literal_eval이 처리할 수 있는 대표적인 타입들입니다.

  • 🔢숫자 (int, float, complex)
  • 📝문자열
  • 📦리스트튜플
  • 📑딕셔너리 (key-value 구조)
  • 불리언 (True/False)None

아래 예제를 보면 문자열 데이터가 어떻게 실제 파이썬 객체로 변환되는지 이해할 수 있습니다.

CODE BLOCK
import ast

print(ast.literal_eval("[1, 2, 3]"))         # 리스트 → [1, 2, 3]
print(ast.literal_eval("('a', 'b')"))        # 튜플 → ('a', 'b')
print(ast.literal_eval("{'x': 10, 'y': 20}")) # 딕셔너리 → {'x': 10, 'y': 20}
print(ast.literal_eval("None"))              # None → None
print(ast.literal_eval("3.14"))              # 실수 → 3.14

위 예제는 각각의 문자열이 실제 파이썬 객체로 안전하게 변환되는 모습을 보여줍니다.
만약 지원하지 않는 타입을 변환하려 한다면 예외가 발생하므로, 어떤 타입이 허용되는지 미리 이해하는 것이 중요합니다.

💎 핵심 포인트:
ast.literal_eval은 파이썬의 리터럴 데이터만 안전하게 변환할 수 있습니다. 따라서 코드 실행 가능성이 있는 객체는 절대 허용되지 않습니다.

🚨 발생할 수 있는 예외와 원인

ast.literal_eval은 안전하게 데이터를 처리할 수 있지만, 모든 입력을 무조건 변환할 수 있는 것은 아닙니다.
지원하지 않는 타입이나 잘못된 구문이 들어오면 예외가 발생합니다.
이러한 예외는 올바른 코드 작성과 예외 처리의 필요성을 보여줍니다.

❌ ValueError

잘못된 데이터 형식이 들어올 경우 발생합니다.
예를 들어, 문자열이 파이썬 리터럴 구조와 전혀 맞지 않을 때 ValueError가 발생합니다.

CODE BLOCK
import ast
ast.literal_eval("Hello World")  # ValueError 발생

⚠️ SyntaxError

구문이 올바르지 않거나 닫히지 않은 따옴표, 잘못된 리스트나 딕셔너리 표기법이 들어왔을 때 SyntaxError가 발생합니다.

CODE BLOCK
import ast
ast.literal_eval("{'a':1, 'b':2")  # SyntaxError 발생 (닫는 중괄호 없음)

🚫 TypeError

지원하지 않는 타입이나 실행 가능한 객체를 포함할 때 발생합니다.
예를 들어, 함수 호출이 들어 있는 문자열을 평가하려 하면 TypeError가 발생합니다.

CODE BLOCK
import ast
ast.literal_eval("open('test.txt')")  # TypeError 발생

⚠️ 주의: literal_eval은 안전성을 보장하기 위해 허용되지 않는 입력에는 반드시 예외를 발생시킵니다. 따라서 try-except 구문을 활용해 적절히 처리하는 습관이 필요합니다.



💡 안전한 예외 처리 방법과 베스트 프랙티스

ast.literal_eval을 사용할 때는 입력이 항상 올바른 리터럴이라고 가정하면 안 됩니다.
실무에서는 외부에서 들어오는 데이터가 오류를 포함하거나 공격 의도를 가질 수 있기 때문에 예외 처리가 필수적입니다.
특히 ValueError, SyntaxError, TypeError와 같은 예외를 대비해야 합니다.

✅ try-except 활용

가장 기본적인 방법은 try-except 블록을 활용해 안전하게 처리하는 것입니다.
예외가 발생하면 로그를 남기거나 기본값을 반환하는 식으로 안정성을 확보할 수 있습니다.

CODE BLOCK
import ast

def safe_eval(data_str, default=None):
    try:
        return ast.literal_eval(data_str)
    except (ValueError, SyntaxError, TypeError):
        return default

print(safe_eval("{'id': 1, 'name': 'Alice'}"))  # 정상 변환
print(safe_eval("open('file.txt')", default={})) # 예외 발생 → 기본값 반환

🛠️ 입력 검증과 병행

try-except만으로는 부족할 수 있습니다.
사전에 정규 표현식이나 JSON 스키마 검증 같은 방식을 사용해 입력이 올바른 형식인지 체크한 뒤 literal_eval을 적용하는 것이 더 안전합니다.

💡 TIP: 데이터가 JSON 포맷에 가깝다면 json.loads()를 우선 고려하고, 파이썬 리터럴이 필요한 경우에만 literal_eval을 사용하는 것이 가장 안전한 접근입니다.

정리하자면, ast.literal_eval은 강력하면서도 안전한 도구이지만, 언제나 예외 처리와 입력 검증을 병행해야 합니다.
이 습관을 들여야 예기치 못한 오류를 막고 시스템을 더욱 안정적으로 운영할 수 있습니다.

자주 묻는 질문 (FAQ)

ast.literal_eval은 eval과 완전히 동일한 기능을 제공하나요?
아니요. eval은 코드 실행까지 가능하지만 literal_eval은 안전하게 리터럴 데이터만 파싱할 수 있습니다. 따라서 보안상 literal_eval이 훨씬 안전합니다.
literal_eval로 JSON 데이터를 처리해도 되나요?
가능은 하지만 권장되지 않습니다. JSON 데이터는 json.loads()를 사용하는 것이 더 안전하고 표준적인 방법입니다.
literal_eval이 지원하지 않는 타입은 무엇이 있나요?
함수 호출, 클래스 인스턴스, 모듈, 시스템 명령 실행 같은 동적 객체는 허용되지 않습니다. 기본적인 리터럴 데이터만 처리할 수 있습니다.
SyntaxError와 ValueError의 차이는 무엇인가요?
SyntaxError는 문법적으로 잘못된 문자열에서 발생하고, ValueError는 문법은 맞지만 유효하지 않은 값일 때 발생합니다.
literal_eval이 TypeError를 발생시키는 경우는 언제인가요?
함수 호출이나 지원되지 않는 타입이 문자열에 포함되었을 때 TypeError가 발생합니다. 이는 보안상의 안전장치입니다.
외부 입력 데이터를 literal_eval로 바로 변환해도 괜찮을까요?
바로 변환하는 것보다 try-except를 활용한 예외 처리와 입력 검증 과정을 반드시 거쳐야 안전합니다.
literal_eval은 파이썬 내장 함수인가요?
literal_eval은 파이썬 표준 라이브러리인 ast 모듈에 포함된 함수입니다. 별도의 설치 없이 사용할 수 있습니다.
literal_eval과 안전성이 비슷한 다른 대안이 있나요?
JSON 데이터를 다룰 때는 json.loads()가 가장 좋은 대안입니다. 그 외에는 직접 파서를 구현하거나 정규식 검증을 추가로 사용하는 방법이 있습니다.

📝 파이썬 ast.literal_eval로 안전한 문자열 처리 정리

파이썬에서 문자열을 안전하게 처리하려면 ast.literal_eval()을 적극적으로 활용하는 것이 좋습니다.
eval과 달리 코드 실행을 허용하지 않고, 숫자·문자열·리스트·딕셔너리 같은 리터럴 데이터만 변환할 수 있기 때문에 보안상 안전합니다.
특히 외부 입력을 다뤄야 하는 환경에서는 필수적으로 고려해야 할 도구입니다.

다만 literal_eval도 완벽하지는 않습니다.
잘못된 구문이나 허용되지 않는 타입이 들어올 경우 ValueError, SyntaxError, TypeError와 같은 예외가 발생할 수 있습니다.
따라서 항상 try-except 블록을 사용하고, 필요하다면 입력 검증을 병행하는 것이 안전한 베스트 프랙티스입니다.
JSON 데이터를 다루는 경우에는 json.loads()와 함께 적절히 구분해서 사용하는 습관을 들이는 것이 좋습니다.

결론적으로, ast.literal_eval은 문자열 파싱 과정에서 발생할 수 있는 보안 문제를 예방하는 강력한 도구입니다.
안전한 데이터 처리와 예외 처리를 병행한다면, 실무 환경에서도 안심하고 활용할 수 있습니다.


🏷️ 관련 태그 : 파이썬문자열, 파이썬보안, ast모듈, literal_eval, 파이썬예외처리, 파이썬중급, 데이터파싱, 안전한코딩, eval보안위험, 파이썬가이드