13P by GN⁺ 3일전 | ★ favorite | 댓글 2개
  • t-문자열(t-strings) 은 Python 3.14에서 새롭게 도입될 안전하고 유연한 문자열 처리 기능
  • 기존 f-string과 달리, t-string은 문자열이 아닌 Template 객체로 반환되어 자동 출력 없이 안전한 처리 가능
  • t-string은 HTML, SQL 등 동적 입력을 안전하게 이스케이프할 수 있는 구조를 갖고 있음
  • JavaScript의 **태그 템플릿(tagged templates)**과 유사한 개념으로, 다양한 변환 및 처리 확장이 가능함
  • Python 개발 도구 생태계가 이 기능을 잘 지원한다면, 웹/보안 중심의 문자열 처리 방식에 큰 변화를 줄 수 있음

Python의 새 기능: t-문자열(Template Strings)

  • Python 3.14부터 t"..." 문법으로 사용하는 Template 문자열(t-strings) 이 공식 기능으로 도입됨
  • 기존 f-string과 달리, t-string은 즉시 문자열이 아닌 string.templatelib.Template 객체로 평가됨
  • 이 객체는 출력 전 별도의 가공 과정이 필요하며, 이 과정을 통해 동적 값의 안전한 처리 및 변환 가능

왜 f-string이 위험할 수 있는가?

  • f-string은 즉시 문자열로 평가되기 때문에, 사용자 입력을 포함한 코드에서 SQL Injection이나 XSS 발생 가능
    • 예: f"<div>{user_input}</div>" → 공격 코드가 직접 삽입될 수 있음
  • t-string은 이러한 평가를 지연시켜 명시적으로 가공해야만 사용 가능하게 함

t-string의 예시 사용

  • HTML 이스케이프 처리 예시:

    evil = "<script>alert('bad')</script>"  
    template = t"<p>{evil}</p>"  
    safe = html(template)  
    # safe는 "<p>&lt;script&gt;alert('bad')&lt;/script&gt;</p>"  
    
  • 속성 자동 삽입 등 더 복잡한 처리도 가능:

    attributes = {"src": "roquefort.jpg", "alt": "Yum"}  
    template = t"<img {attributes} />"  
    element = html(template)  
    # 결과: "<img src='roquefort.jpg' alt='Yum' />"  
    

구조와 API

  • Template 객체는 .strings, .values 속성을 통해 원본 텍스트와 대입값을 분리해 제공

  • interpolations 속성을 통해 !s, :>8 등 포맷 세부 정보까지 접근 가능

  • 순회(iteration)를 통해 텍스트와 값이 섞인 상태도 직접 가공 가능

  • 수동 생성도 가능:

    from string.templatelib import Template, Interpolation  
    template = Template(  
      "Hello ",  
      Interpolation(value="World", expression="name"),  
      "!"  
    )  
    

재미있는 예시: 돼지 라틴어 변환기

  • Template 객체의 내용을 순회하며 단어를 Pig Latin으로 변환하는 예제:

    def pig_latin(template: Template) -> str:  
        ...  
    name = "world"  
    template = t"Hello {name}!"  
    assert pig_latin(template) == "Hello orldway!"  
    

향후 발전 방향

  • t-strings는 웹/보안 중심의 문자열 처리 방식에 안전성과 확장성을 가져올 수 있음
  • black, ruff, VS Code 등 개발 도구가 t-string 포맷/하이라이팅을 지원하길 기대
  • JavaScript 개발자가 익숙한 tagged template 방식과 유사해, 여러 프레임워크에서도 활용 가능성 높음

개발자 커뮤니티와의 협업

  • 본 기능은 다양한 Python 커뮤니티 멤버들의 참여와 협업을 통해 완성됨
  • 특히 Jim, Paul, Koudai, Lysandros, 그리고 Guido 등 핵심 인물들과의 교류가 언급됨
  • PEP 750과 그 예제 저장소는 GitHub에서 확인 가능

Python 3.14의 t-문자열 기능은 문자열의 안전성과 확장성을 동시에 확보하며, 기존 f-string의 한계를 넘는 중요한 도약임

Hacker News 의견
  • 전반적으로, 이 기능은 꽤 멋짐. 기본적으로 다음과 같은 코드를

    db.execute("QUERY WHERE name = ?", (name,))
    

    다음과 같이 바꿈

    db.execute(t"QUERY WHERE name = {name}")
    

    새로운 언어 기능의 복잡성을 감수할 만큼 이 문법적 설탕이 이점이 있는지에 대한 질문이 있음. 두 가지 이유로 이 경우에는 그렇다고 생각함

    • 라이브러리 개발자가 {} 확장을 통해 원하는 것을 할 수 있게 하는 것은 좋은 일이며, 좋은 사용 사례를 만들어낼 가능성이 있음
    • 언어 전반에 걸쳐 템플릿 문법을 일반화하여 모든 라이브러리가 같은 방식으로 문제를 해결하도록 하는 것은 아마도 좋은 일임
  • 또한, 도구 생태계가 t-strings를 지원하도록 적응하기를 바람. 예를 들어, black과 ruff가 t-string 내용을 포맷하고, vscode가 HTML이나 SQL 같은 일반적인 유형의 내용을 색상으로 표시하면 좋겠음

    • t-strings에 대한 이 견해는 매우 이상함. 템플릿 문자열이 유효한 HTML이나 SQL로 변환되어야 한다는 것을 추론할 수 있는 유일한 방법은 문자열의 명백한 문법을 기반으로 하는 것인데, 이는 임시방편으로만 가능하며 템플릿 문자열 기능과는 관련이 없음
    • 기능이 설계된 방식에서는 문자열 자체에 어떤 유형의 콘텐츠인지 또는 최종적으로 무엇으로 변환될지에 대한 표시가 없음. 모든 것은 변환 함수에 의해 처리됨
    • 다른 사람들이 추가한 것처럼, sql”select * from {table}” 같은 것이 이를 수행할 수 있었겠지만, 템플릿에 있는 것이 변환 함수에 의해 유효한 sql로 변환될 것이라는 보장이 없음. t“give me {table} but only {columns}”가 템플릿이 처리된 후 유효한 sql로 변환될 수 있음
  • 다음과 같은 깔끔한 SQL 문법을 사용할 수 있을까?

    city = 'London'
    min_age = 21
    # Find all users in London who are 21 or older:
    users = db.get(t'
      SELECT * FROM users
      WHERE city={city} AND age>{min_age}
    ')
    

    db.get() 함수가 템플릿을 수용한다면, 가능할 것임. 지금까지 본 SQL 사용 방법 중 가장 깔끔한 방법일 것임

  • 개인적으로, 이 기능은 일반적인 기능이 되기에는 너무 특정 문제에 집중된 것 같음. Python은 점점 커지고 있음. 사람들이 Python이 배우기 쉽고 간단한지 물어보면 "기본은 그렇지만, 전체 언어를 배우는 것은 그렇지 않음"이라고 말해야 함

    • 이런 점에서 Go는 거의 모든 기능을 거부함으로써 흥미로움. 솔직히 제네릭이 많은 복잡성을 추가하기 때문에 가치가 있는지 확신할 수 없음. 언어를 원래의 초점에 맞추는 일반적인 아이디어가 옳다고 생각함. C++는 언어 자체가 시작했을 때와 거의 닮지 않은 극단적인 경우일 것임
  • 큰 토론 (414 포인트, 10일 전, 324개의 댓글) 링크

  • 꽤 멋짐. JS 기능을 포팅한다면 다음에는 딕셔너리 언패킹/디스트럭처링을 얻을 수 있을까?

    • 이 기능을 너무나도 원함. JS로 돌아가는 주된 이유임
    >>> {a, b=45, c=None, **d} = {'a': 234, xzy: 32456}
    >>> print(a, b, c, d)
    234 45 None {'xyz': 32456}
    
  • 새로운 x-string 기능이 내장된 것만으로 "속임수"처럼 느껴짐. 다음과 같은 것을 할 수 있다면 멋질 것임

    from foo import bar
    bar"zoop"
    
  • 2025년의 Zen of Python:

    There should be one-- and preferably only one --obvious way to do it.
    

    2025년의 Python 문자열 포맷팅:

    • t-strings
    • f-strings
    • %-operator
    • +-operator
    • str.format()
  • 템플릿에 적용할 함수를 f-string 변수에 적용하는 것과 어떻게 다른지 이해가 안됨. 그래서 다음과 같은 대신에:

    evil = "<script>alert('bad')</script>"
    template = t"{evil}"
    safe = html(template)
    

    왜 그냥 이렇게 하지 않는지:

    evil = "<script>alert('bad')</script>"
    safe = f"{html(evil)}"
    

    아니면 f-string을 만들기 전에. 단순히 정화/문자열 조작 부분을 잊지 않게 하고 강제로 거치게 하는 것인지?

  • 안녕하세요! 제가 이 글을 작성했음 :-)

    • 대화에 조금 늦었고 HN에서 이 글이 트렌드가 된 것을 보고 약간 놀랐지만, 질문에 기꺼이 답변할 것임. 하루 종일 틈틈이 참여하려고 노력할 것임