Python의 새로운 `t-strings`
(davepeck.org)- 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><script>alert('bad')</script></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에서 이 글이 트렌드가 된 것을 보고 약간 놀랐지만, 질문에 기꺼이 답변할 것임. 하루 종일 틈틈이 참여하려고 노력할 것임