Tcl
"오늘의AI위키"의 AI를 통해 더욱 풍부하고 폭넓은 지식 경험을 누리세요.
1. 개요
Tcl(Tool Command Language)은 1988년 존 오스터하우트가 개발한 프로그래밍 언어이다. 원래는 전자 설계 자동화 소프트웨어 확장을 위해 만들어졌지만, 독립적인 언어로 발전하여 1997년 ACM 소프트웨어 시스템 상을 수상했다. Tcl은 명령어 기반 언어로, 모든 것이 명령어이며 전위 표기법을 사용한다. Tcl은 1990년대 초 Tk 툴킷과 결합하여 GUI 스크립팅 환경인 Tcl/Tk로 인기를 얻었으며, 현재는 오픈 소스로 개발되고 있다. Tcl은 다양한 운영체제에서 사용 가능하며, C, C++, Java 등 다른 언어와의 인터페이스를 지원한다. 확장 패키지를 통해 GUI, 자동화, 데이터베이스 접근 등 다양한 기능을 제공하며, 객체 지향 프로그래밍을 위한 TclOO를 지원한다.
더 읽어볼만한 페이지
- 1988년 개발된 프로그래밍 언어 - 울프럼 언어
울프럼 언어는 울프럼 리서치에서 개발한 기호 계산 프로그래밍 언어로서, 매스매티카에 처음 소개된 후 3차원 모델링, 데이터 분석, 이미지 처리 등의 기능이 추가되어 과학, 공학, 금융, 데이터 과학 등 다양한 분야에서 활용되고 있으며, 특히 라즈베리 파이 버전 무료 제공으로 대중적으로 알려졌다. - 1988년 개발된 프로그래밍 언어 - 모듈라-3
모듈라-3는 1986년 개발된 프로그래밍 언어로, 모듈, 인터페이스, 제네릭, 가비지 컬렉션 등의 특징을 가지며, 자바, 파이썬 등 여러 언어에 영향을 미쳤다. - 텍스트 지향 프로그래밍 언어 - PHP
PHP는 라스무스 러도프가 개발한 범용 스크립팅 언어로, 웹 개발에 널리 사용되며 LAMP 아키텍처의 핵심 요소이다. - 텍스트 지향 프로그래밍 언어 - 펄
펄은 래리 월이 개발한 텍스트 조작에 강점을 가진 다목적 프로그래밍 언어이며, 1987년 펄 1.0이 처음 공개된 이후 여러 버전 업데이트를 거쳐 객체 지향 프로그래밍과 유니코드 지원 기능을 추가했고, 현재 펄 5가 널리 사용되며 CPAN을 통해 방대한 모듈 생태계를 제공한다. - 다중 패러다임 프로그래밍 언어 - 펄
펄은 래리 월이 개발한 텍스트 조작에 강점을 가진 다목적 프로그래밍 언어이며, 1987년 펄 1.0이 처음 공개된 이후 여러 버전 업데이트를 거쳐 객체 지향 프로그래밍과 유니코드 지원 기능을 추가했고, 현재 펄 5가 널리 사용되며 CPAN을 통해 방대한 모듈 생태계를 제공한다. - 다중 패러다임 프로그래밍 언어 - 모조 (프로그래밍 언어)
모조는 모듈러사에서 개발한 파이썬과 유사한 구문의 고성능 프로그래밍 언어로, AI 애플리케이션 개발에 초점을 맞추고 러스트의 영향을 받은 메모리 안전성을 제공하며 향후 오픈 소스로 전환될 예정이다.
| Tcl - [IT 관련 정보]에 관한 문서 | |
|---|---|
| 지도 정보 | |
| 기본 정보 | |
| 이름 | Tcl |
![]() | |
| 패러다임 | 다중 패러다임: 이벤트 기반, 함수형, 명령형, 객체 지향 |
| 출시일 | 1988년 |
| 설계자 | 존 오스터하우트 |
| 개발자 | Tcl 코어 팀 |
| 최신 릴리스 버전 | 9.0 |
| 최신 릴리스 날짜 | 2024년 9월 26일 |
| 최신 미리보기 버전 | 9.0b3 |
| 최신 미리보기 날짜 | 2024년 7월 31일 |
| 타이핑 | 동적 타이핑, 모든 것이 문자열 |
| 구현체 | ActiveTcl Androwish |
| 방언 | Jim Eagle |
| 영향을 받은 언어 | AWK Lisp |
| 영향을 준 언어 | PHP PowerShell Tea TH1 |
| 라이선스 | BSD 스타일 |
| 웹사이트 | Tcl 공식 웹사이트 Tcl/Tk 공식 웹사이트 |
| 파일 확장자 | .tcl .tbc |
| 프로그래밍 언어 분류 | |
| 분류 | 객체 지향 언어 명령형 언어 함수형 언어 스크립트 언어 |
| 소프트웨어 정보 | |
| 명칭 | Tcl |
![]() | |
| 최신 버전 | 9.0.0 |
| 최신 버전 발표일 | 2024년 9월 26일 |
| 최신 평가판 | 9.0b3 |
| 최신 평가판 발표일 | 2024년 7월 31일 |
| 대응 운영체제 | 크로스 플랫폼 |
| 대응 플랫폼 | 크로스 플랫폼 |
| 라이선스 | 오픈 소스 |
| 공식 웹사이트 | https://www.tcl.tk/ |
| 추가 정보 | |
| 읽는 법 | 티클 |
| Tcl/Tk 읽는 법 | 티클・티케이 |
| Tclet 읽는 법 | 티클렛 |
2. 역사
Tcl은 1988년 캘리포니아대학교 버클리캠퍼스의 존 오스터하우트 박사에 의해 처음 개발되었다.[48] 당시 애플리케이션 프로그램에 내장되는 확장용 스크립트 언어는 표준이 없었고, 애플리케이션마다 독자적인 언어가 구현되어 있었다. 애플리케이션 사용자는 도구마다 다른 스크립트 언어를 익혀야 했기 때문에, 오스터하우트는 UNIX 애플리케이션에서 표준이 되는 확장 스크립트 언어를 디자인하려고 했다.
Tcl은 애플리케이션에 쉽게 통합될 수 있도록 라이브러리로 제공되며, C 언어로 작성된 애플리케이션에 쉽게 통합할 수 있다. 언어 구조가 간소하며 높은 확장성을 가지고 있고, 인터프리터 언어라는 특징이 있다.
Tk는 Tcl을 위해 개발된 GUI 툴킷으로, 간단한 코드로 GUI를 만들 수 있다. 1990년대 초 Tcl에 번들 형태로 공개되었으며, 애플(Apple)의 하이퍼카드(HyperCard)에 영감을 받아 개발되었다. 초기에는 Tcl의 활용 사례 중 하나로 소개되었지만, 사용 편의성으로 인해 Tcl과 함께 "Tcl/Tk" 형태의 GUI 스크립팅 환경으로 인기를 얻었다. Tk는 Perl(Perl/Tk), Python(Tkinter), 루비(Ruby)(Ruby/Tk) 등 다른 언어에서도 표준 GUI 키트로 사용되었다.
1994년부터 1998년까지 썬 마이크로시스템즈(Sun Microsystems)에서 Tcl/Tk 개발이 진행되었다. 썬은 WWW 클라이언트 환경 정복을 목표로 하였고, Tcl/Tk도 웹 브라우저 상에서 Tk GUI를 작동시키는 플러그인, 브라우저 스크립트 언어로서의 Tcl 통합, 국제화 대응(내부 처리 유니코드화), 인터프리터에서 바이트 컴파일러로 변경 등의 기능적 발전을 이루었다. 그러나 다른 기술과의 경쟁, 브라우저 지원 부족 등으로 WWW에서 큰 인기를 얻는 데는 실패했다.
2000년부터 Tcl/Tk 개발은 오픈소스로 이전되어 활발하게 진행되고 있다. 2005년 현재 Tcl은 Perl, Python, Ruby에 비해 사용자 수가 적지만, EDA 도구에서는 표준 스크립트 언어로 널리 사용되고 있으며, 한국전자지도 웹시스템에서도 일부 사용된다. Tk는 GTK+, Qt와 함께 경량 프로그래밍 언어의 사실상 표준 GUI 툴킷 중 하나로 널리 사용되고 있다.
FlightAware[29]를 포함한 여러 기업에서 제품의 일부로 Tcl을 사용한다.
2. 1. 주요 연혁
Tcl 프로그래밍 언어는 1988년 봄, 존 오스터하우트가 캘리포니아대학교 버클리캠퍼스에서 근무하던 중에 만들어졌다.[11][12] 처음에는 프로그래머들이 전자 설계 자동화(EDA) 소프트웨어, 특히 당시 존 오스터하우트의 전문 분야였던 VLSI 설계 도구 매직을 확장하기 위한 자신만의 언어를 고안하면서 생겨난 "좌절감의 산물"이었다.[13][14] 이후 Tcl은 독자적으로 인정받게 되었고, 오스터하우트는 Tcl/Tk로 1997년 ACM 소프트웨어 시스템상을 수상했다.[15]Tcl의 이름은 원래 '''T'''ool '''C'''ommand '''L'''anguage에서 유래되었지만, 일반적으로 ''TCL''이 아닌 ''Tcl''로 표기한다.[16]
| 날짜 | 이벤트 |
|---|---|
| 1990년 1월 | 버클리 이외 지역에 Tcl 발표 (겨울 USENIX). |
| 1990년 6월 | Expect 발표 (여름 USENIX). |
| 1991년 1월 | Tk 최초 발표 (겨울 USENIX). |
| 1993년 6월 | 첫 번째 Tcl/Tk 컨퍼런스 (버클리). incr Tcl 발표. |
| 1997년 8월 | Tcl 8.0에서 바이트코드 컴파일러 도입.[17] |
| 1999년 4월 | Tcl 8.1에서 완전한 유니코드 지원[18] 및 고급 정규 표현식 도입.[19] |
| 1999년 8월 | Tcl 8.2에서 Tcl 확장 아키텍처(TEA) 도입.[20] |
| 2000년 8월 | Tcl 핵심 팀 구성, Tcl을 보다 커뮤니티 중심의 개발 모델로 전환.[21] |
| 2002년 9월 | 아홉 번째 Tcl/Tk 컨퍼런스 (밴쿠버). starkit 패키징 시스템 발표. Tcl 8.4.0 출시.[22] |
| 2007년 12월 | Tcl 8.5에서 새로운 데이터 형식, 새로운 확장 저장소, bignums,[23] 람다 추가.[24][25] |
| 2012년 12월 | Tcl 8.6에서 내장 동적 객체 시스템인 TclOO 및 스택리스 평가 추가.[26] |
| 2024년 9월 | Tcl 9.0에서 64비트 기능, 전체 유니코드 코드 포인트 범위 지원, epoll 및 kqueue 사용[27] |
Tcl은 다음과 같은 특징을 가지고 있다:
Tcl 컨퍼런스 및 워크숍은 미국과 유럽에서 모두 개최된다.[28]
3. 특징
Tcl 언어의 특징을 한마디로 표현하면 "모든 것이 문자열"이다. Tcl은 명령어 행의 순차 실행만으로 이루어지는 간단한 문법과 일관된 리스트 구조를 결합하여 매우 간단한 규칙으로 광범위한 영역을 다룬다. 명령어 행은 하나의 리스트이며, 첫 번째 요소가 명령어이고, 그 이후의 요소가 명령어에 대한 인수로 처리된다. 리스프 언어와 유사한 일관성을 가지고 있지만, 리스트 요소의 구분 기호가 공백이나 탭이기 때문에, 이러한 문자가 무시되는 일반적인 프로그래밍 언어에 익숙한 사람들에게는 혼란을 줄 수도 있다.
3. 1. 문법 및 기본 의미론
Tcl 스크립트는 명령어 호출의 연속으로 구성된다. 명령어 호출은 공백으로 구분되고 줄 바꿈이나 세미콜론으로 끝나는 단어들의 목록이다. 첫 번째 단어는 명령어의 이름이고, 뒤따르는 단어들은 인수로 처리된다.
```tcl
commandName argument1 argument2 ... argumentN
```
예를 들어, `puts` 명령어는 콘솔에 문자열을 출력한다.
puts "Hello, World!"
이 명령어는 "Hello, World!" 문자열을 표준 출력으로 보낸다.
변수나 다른 명령어의 결과는 문자열에 대입될 수 있다. 다음은 `set`과 `expr` 명령어를 사용하여 계산 결과를 변수에 저장하고, `puts`로 출력하는 예제이다.
# expr은 텍스트 문자열을 표현식으로 평가합니다.
set sum [expr 1+2+3+4+5]
puts "The sum of the numbers 1..5 is $sum."
`#` 문자는 주석을 나타낸다.
# 중괄호를 사용하면 변수 치환은 expr에 의해 수행됩니다.
set x 1
set sum [expr {$x + 2 + 3 + 4 + 5}]; # $x는 expr에 매개변수를 전달하기 전에 치환되지 않습니다;
# expr은 표현식을 평가하는 동안 $x를 1로 치환합니다.
puts "The sum of the numbers 1..5 is $sum."; # sum은 15입니다.
# 중괄호를 사용하지 않으면 변수 치환은 정의 위치(어휘적 범위)에서 발생합니다.
set x 2
set op *
set y 3
set res [expr $x$op$y]; # $x, $op, $y가 치환되고 표현식은 6으로 평가됩니다.
puts "$x $op $y is $res."; # $x, $op, $y, $res가 문자열로 치환되고 평가됩니다.
위 예제처럼 Tcl에는 명령어라는 하나의 기본 요소가 있다. 따옴표와 치환 규칙은 각 명령어의 인수가 어떻게 처리되는지 결정한다.
인수 처리 전에, 줄의 마지막 문자(줄 바꿈 바로 앞)가 백슬래시(\\)면, 백슬래시-줄 바꿈 조합은 공백으로 바뀐다. 이것은 줄 연결을 제공한다.
일반적인 인수 처리는 다음과 같다.
베어 단어와 큰따옴표로 묶인 단어에서는 세 가지 치환이 발생한다.
치환은 왼쪽에서 오른쪽으로 한 번만 수행된다. 치환된 텍스트는 다시 스캔되지 않는다. 단일 단어에 여러 번의 치환이 나타날 수 있다.
Tcl 8.5부터는 `{*}`를 단어 앞에 붙여 단어를 하위 단어로 분할할 수 있다.
Unix 명령 쉘과 달리 Tcl은 명시적으로 지시하지 않으면 문자열을 다시 구문 분석하지 않는다.
대부분의 Tcl 명령어는 가변 인수 함수이며, `proc`(스크립트 명령어 프로시저 생성자)을 사용하면 기본값과 임의 개수의 인수를 처리할 수 있다.
Tcl은 정적으로 형식이 지정되지 않는다. 변수는 정수, 부동 소수점, 문자열, 목록 등 어떤 값이든 가질 수 있으며, 필요에 따라 다른 유형으로 해석된다. 값은 불변이며, 값을 변경하는 연산은 새 값을 반환한다.
Tcl 언어의 특징은 "모든 것이 문자열"이라는 점이다. Tcl은 명령어 행의 순차 실행만으로 이루어지는 간단한 문법과 일관된 리스트 구조를 결합하여 매우 간단한 규칙으로 광범위한 영역을 다룬다. 명령어 행은 하나의 리스트이며, 첫 번째 요소가 명령어이고, 그 이후의 요소가 명령어에 대한 인수로 처리된다. 리스프 언어와 유사한 일관성을 가지고 있지만, 리스트 요소의 구분 기호가 공백이나 탭이기 때문에, 이러한 문자가 무시되는 일반적인 프로그래밍 언어에 익숙한 사람들에게는 혼란을 줄 수도 있다.
리스트는 문자열이다. 리스트를 구성하는 요소는 공백이나 탭으로 구분된다. 공백이나 탭을 요소에 포함하고 싶다면, 그 요소를 중괄호(`{`, `}`)로 감싸면 된다. 다음 문자열은 세 개의 요소로 구성된 리스트이다.
This is {a pen}
Tcl 파서가 소스 코드에서 명령어 행으로 리스트를 추출할 때, 하나의 리스트의 끝은 개행 코드 또는 세미콜론(`;`)으로 판단한다. 하지만 개행 코드나 세미콜론이 중괄호 안에 있으면, 그것을 리스트의 끝 기호로는 간주하지 않는다. 따라서, 다음 3행의 문자열은 3개의 요소로 구성된 하나의 리스트이다. 개행 코드는 3개 있지만, 마지막 개행 코드만이 리스트의 끝 기호 역할을 한다.
```tcl
if {$a<0} {
set a 0
}
```
위 리스트는 Tcl의 `if` 명령어이며 C 언어의 `if` 문과 비슷하다. 하지만 중괄호가 리스트 기술 기호로 채택되었으므로 비슷할 뿐이다. 위의 `if` 명령어를 다음과 같이 개행 위치를 바꾸면, `if` 명령어의 인수 오류가 발생한다.
```tcl
if {$a<0}
{
set a 0
}
```
Tcl 파서는 위 4행의 문자열을 두 개의 리스트로 인식한다. 따라서 첫 번째 행의 `if` 명령어 행은 인수가 하나만 주어진 것이 되어, 인수 오류가 발생한다.
여기서 중요한 것은, 오류를 반환한 것은 `if` 명령어이며, Tcl 파서가 검출한 "구문 오류"가 아니라는 점이다. Tcl에는 제어문과 같은 "문"이 없다. 분기나 반복과 같은 실행 제어도 단순히 명령어로 구현될 뿐이다. Tcl에는 리스트 구조와 아래에 설명하는 "특수 기호"만 있을 뿐, 세세한 규칙은 없다.
Tcl 구문 분석기는 리스트의 첫 번째 요소를 항상 명령어 이름으로 인식한다. 다른 요소들은 명령어에 전달할 인수로 인식한다. 그러나 인수 요소가 대괄호(`[`, `]`)로 묶여 있으면, 그 안의 내용을 명령어 행으로 인식하여 실행한 후 원래의 인수 값을 구한다. 이것이 “명령어 치환”이다.
set a [expr 100*2]
Tcl 파서는 변수 기능을 제공하여 명령어 간 데이터 전달을 처리한다. 변수는 `set` 명령어로 생성된다. 그리고, `$` 기호가 앞에 붙은 요소를 변수 이름으로 간주하고, 그 값으로 요소 전체를 치환한다. 이것이 "변수 치환"이다.
set a {This is a pen.}
puts $a
변수 치환은 명령어 행의 첫 번째 요소에도 적용된다. 즉, 명령어 이름을 변수로 지정할 수도 있다.
변수 치환은 한 번만 실행된다. 변수 치환 결과에 문자 "$"가 포함되어 있어도 재치환이 시도되지 않는다.
또한, 변수 치환으로 얻어진 문자열에 공백이 포함되어 있어도, 두 개의 인수로가 아니라, 공백이 포함된 하나의 인수로 전달된다. 인수 분리(리스트 인식)는 변수 치환 전에 이루어지기 때문이다. 만약 치환 결과에서 다시 인수 분리를 수행하고 싶다면 `eval` 명령어를 사용한다.
리스트 구조에서 설명했듯이, 중괄호(`{`, `}`)는 개행 코드와 같은 특수 문자의 기능을 무효화한다. 이 규칙은 명령어 치환자(bracket)와 변수 치환자($ 기호)에도 적용된다. 따라서 아래 코드에서는 명령어 치환과 변수 치환이 모두 수행되지 않는다.
puts {[expr 100*$num] 円}
따라서 실행 결과로 출력되는 문자열은 다음과 같다.
\[expr 100*$num] 円
명령어 치환과 변수 치환을 수행하고, 공백을 포함하는 문자열을 하나의 인수로 `puts` 명령어에 전달하려면, 중괄호 대신 큰따옴표(`"`)로 감싸면 된다.
puts "[expr 100*$num] 円"
`num` 변수에 3이 설정되어 있다면 명령어 실행 결과로 300 円이 출력된다.
이처럼 큰따옴표의 기능은 중괄호 기능과 거의 동일하지만, Tcl 파서에 명령어 치환과 변수 치환을 허용하는 점이 다르다. 큰따옴표 안에서의 명령어 치환, 변수 치환은 Tcl의 특징적인 기능이다. 큰따옴표와 중괄호의 기능은 리스트 요소의 처음과 끝에 작성된 경우에만 유효하다. 아래 예에서는 `" "`는 문자로 취급된다.
set text 石を投げたら"ゴツン"と音がした
여러 명령어를 한 줄에 작성하려면 명령어 줄을 세미콜론(`;`)으로 구분하면 된다.
set a 100 ; set b 200; puts [expr $a * $b]
하나의 명령어를 여러 줄로 작성하려면 줄 끝에 백슬래시를 추가한다.
command $arg1 $arg2 \
$arg3 $arg4
`$` 문자 앞에 `\`를 붙이면 `$` 치환자 기능을 억제하고 단순한 문자로 취급할 수 있다.
puts "금액=\$100"
명령어 치환자(`[`, `]`), 중괄호(`{`, `}`) 앞에 붙인 경우에도 마찬가지이다.
기본적으로 백슬래시는 C 언어와 거의 같은 기능을 가지고 있다. 예를 들어 개행 코드는 "`\n`"으로 쓸 수 있다.
Tcl 파서(구문 분석기)가 전달한 인자가 명령어 내부에서 평가되는지 여부는 중요하다. 여기서 평가란 명령어 치환이나 변수 치환을 의미한다. 예를 들어 산술 연산을 수행하는 `expr` 명령어는 인자를 내부적으로 평가한다. 따라서 다음 두 명령어는 같은 결과를 반환한다.
```tcl
expr $a*$b
expr {$a*$b}
```
Tcl 파서가 하지 않더라도 `expr` 명령어가 내부적으로 변수 치환을 하므로 같은 결과를 얻을 수 있다. `if` 명령어나 `while` 명령어는 첫 번째 인자로 주어진 문자열을 명령어 내부에서 `expr`을 사용하여 평가하고 그 결과를 사용한다.
```tcl
set val true
if $val {~처리~}
while $val {~처리~}
```
Tcl 파서는 첫 번째 인자 "`$val`"을 평가하여 "`true`"(문자열)로 바꾼다. 마찬가지로 두 번째 인자 "`{~처리~}`"를 평가하여 문자열 리터럴이므로 같은 값 "`{~처리~}`"으로 바꾸고 다음과 같이 한다.
```tcl
if true {~처리~}
while true {~처리~}
```
Tcl 파서는 그 후 `true`와 `{~처리~}`를 `if`, `while` 명령어에 전달하고, `if`, `while` 명령어는 받은 문자열을 `expr` 명령어에 "`[expr true]`"로 전달하고, 그 결과를 가지고 처리를 계속한다. 주의해야 할 것은 `while` 명령어는 `{~처리~}`를 모두 평가한 후 다시 첫 번째 인자를 `expr`로 평가하지만, 위 코드에서는 주어진 값이 `true`이므로 `{~처리~}` 안에 "`set val false`"와 같은 문장이 있더라도, 첫 번째 인자로 주어진 값 자체는 변하지 않으므로 무한 루프를 반복하게 된다(`{~처리~}` 안에 `break` 명령어가 포함되어 있지 않은 경우).
```tcl
set val true
if {$val} {~처리~}
while {$val} {~처리~}
```
이 경우 Tcl 파서는 인자를 순서대로 평가하고, 첫 번째 인자로 "`{$val}`"이라는 4글자 문자열 리터럴을, 두 번째 인자로 "`{~처리~}`"를 `if`, `while` 명령어에 전달한다. `if`, `while` 명령어는 받은 문자열을 `expr` 명령어에 "`[expr {$val}]`"로 전달하고, 그 결과를 가지고 처리를 계속한다. `while` 명령어는 `{~처리~}`를 모두 평가한 후 다시 첫 번째 인자를 `expr`로 평가하지만, 위 코드에서는 주어진 값이 `{$val}`이므로 `{~처리~}` 안에 "`set val false`"와 같은 문장이 있으면, 그 평가값도 `false`가 되어 그 시점에서 반복 처리를 종료한다.
반면, `switch` 명령어의 첫 번째 인자는 내부적으로 평가되지 않는다. 따라서 아래 두 번째 기술은 기대하는 결과를 얻을 수 없다.
```tcl
switch $val {...}
switch {$val} {...}
```
만약 인자를 명령어 내부에서 평가해 준다면, 그 인자를 중괄호({})로 묶어 전달하는 것이 효율적이다. Tcl 파서와 명령어 양쪽에 의한 다중 평가 처리를 피할 수 있기 때문이다. 이러한 이유로 `if` 명령어나 `while` 명령어나 `for` 명령어의 인자는 항상 중괄호로 묶어야 한다. 특히 루프 조건식은 반드시 중괄호로 묶어야 한다. 중괄호로 묶지 않으면 변수 치환이 된 후 루프 명령어에 전달되므로, 상수를 나열한 조건식이 되어 무한 루프를 초래한다.
4. 예제
아래는 Tcl 셸에 붙여넣어 실행 가능한 간단한 코드 예제이다.
리스트 구조에서 설명했듯이, 중괄호({, })는 개행 코드와 같은 특수 문자의 기능을 무효화한다. 이 규칙은 명령어 치환자(bracket)와 변수 치환자($ 기호)에도 적용된다. 따라서 아래 코드에서는 명령어 치환과 변수 치환이 모두 수행되지 않는다.
puts {[expr 100*$num] 円}
위 코드를 실행하면 다음과 같은 문자열이 출력된다.
[expr 100*$num] 円
명령어 치환과 변수 치환을 수행하고, 공백을 포함하는 문자열을 하나의 인수로 `puts` 명령어에 전달하려면, 중괄호 대신 큰따옴표(")를 사용한다.
puts "[expr 100*$num] 円"
`num` 변수에 3이 설정되어 있다면 위 코드는 300円|엔일본어을 출력한다.
이처럼 큰따옴표는 중괄호와 거의 동일한 기능을 하지만, Tcl 파서가 명령어 치환과 변수 치환을 허용한다는 점이 다르다. 큰따옴표 안에서의 명령어 치환과 변수 치환은 Tcl의 특징적인 기능이다. 큰따옴표와 중괄호는 리스트 요소의 처음과 끝에 작성된 경우에만 유효하다. 아래 예제에서는 " "가 문자로 취급된다.
set text 石を投げたら"ゴツン"と音がした
'수 더하기', '메아리 서버', '전자 시계' 예제는 하위 섹션에서 자세히 설명한다.
4. 1. 수 더하기
방법 (ㄱ) - 'foreach' 반복문을 이용하여 덧셈```tcl
set numbers {1 2 3 4 5 6 7 8 9 10}
set result 0
foreach number $numbers {
set result [expr {$result + $number}]
}
puts $result
```
방법 (ㄴ) - 'join' 명령을 이용하여 훨씬 더 우아한 방법으로 덧셈
```tcl
set numbers {1 2 3 4 5 6 7 8 9 10}
puts [expr [join $numbers +]]
```
방법 (ㄷ) - 더하기 명령을 리스트 펼치기 문법과 함께 사용
```tcl
namespace import tcl::mathop::+
set numbers {1 2 3 4 5 6 7 8 9 10}
puts [+ {*}$numbers]
4. 2. 메아리 서버
tcl#!/usr/bin/env tclsh
# 여러 동시 연결을 처리할 수 있는 에코 서버 예제입니다.
proc newConnection { sock addr port } {
# 클라이언트 연결은 라인 버퍼링, 넌블로킹 모드로 처리됩니다.
fconfigure $sock -blocking no -buffering line
# 소켓을 읽을 수 있을 때 handleData 프로시저를 호출합니다.
fileevent $sock readable [ list handleData $sock ]
}
proc handleData { sock } {
puts -nonewline $sock [ gets $sock ]
if { [ eof $sock ] } {
close $sock
}
}
# 서버가 호출될 때 인수로 주어진 포트에 대한 모든 연결을 처리합니다. (newConnection 프로시저 호출)
set port [ lindex $argv 0 ]
socket -server newConnection $port
# 더미 변수(forever)를 기다려 이벤트 루프에 진입합니다.
vwait forever
4. 3. 전자 시계
Tk와 timer 이벤트를 이용하는 또 다른 예제(https://web.archive.org/web/20080906222256/http://wiki.tcl.tk/2563 A simple A/D clock)는 네 줄의 코드로 전자 시계를 만든다.```tcl
package require Tk
proc every {ms body} {
eval $body
after $ms [list every $ms $body]
}
pack [label .clock -textvar time]
every 1000 {set ::time [clock format [clock seconds] -format %H:%M:%S]} ;# RS
```
설명: 첫 번째 줄은 Tk 패키지를 불러들인다. 두 번째 줄(실제로는 4줄에 걸쳐있는)은 액션('body')을 매 'ms' 밀리초마다 반복해서 실행하는 명령어 "every"를 정의하고, 세 번째 줄은 변수 'time'에 연동되는 라벨을 만들고 스크린에 출력되도록 한다. 네 번째 줄은 매 초마다 변수 'time'이 형식이 갖춰진 지역 시간으로 갱신되도록 한다.
변경 사항:
- `
` 태그를 ` ` 태그로 변경했습니다. ``는 허용되지 않는 문법입니다. - 코드 블록 가독성을 높이기 위해 `
` 태그를 사용하여 코드블럭을 감싸서 출력하도록 변경하였습니다. - 코드 내 들여쓰기를 추가하여 가독성을 높였습니다.
5. Safe-Tcl
Safe-Tcl은 Tcl의 하위 집합으로, Tcl 스크립트가 호스트 시스템이나 애플리케이션에 피해를 줄 수 없도록 기능을 제한한다.[32] 파일 시스템 접근이 제한되고 임의의 시스템 명령어 실행이 차단된다. 신뢰할 수 없는 인터프리터가 신뢰할 수 없는 스크립트의 코드를 실행하는 이중 인터프리터 모델을 사용한다. 나털리얼 보렌스타인과 마셜 로즈가 이메일에서 활성 메시지를 포함하기 위해 설계했다. ''application/safe-tcl''과 ''multipart/enabled-mail''이 지원되는 경우 Safe-Tcl을 이메일에 포함할 수 있다. Safe-Tcl의 기능은 그 이후 표준 Tcl/Tk 릴리스의 일부로 통합되었다.[33][34]
6. 주요 명령어
- `set`: 변수에 새로운 값을 쓰거나(변수가 없으면 생성), 인수가 하나만 주어지면 해당 변수의 값을 반환한다.
- `proc`: 새로운 명령어를 정의한다. 이 명령어는 지정된 Tcl 스크립트를 실행하며, `return`을 사용하여 호출자에게 즉시 제어를 반환할 수 있다.
- `if`: 조건(첫 번째 인수)이 참이면 지정된 스크립트 본문(두 번째 인수)을 실행한다. `elseif`나 `else`를 사용하여 추가 조건을 지정할 수 있다.
- `while`: 조건(첫 번째 인수)이 참인 동안 지정된 스크립트 본문을 반복 실행한다.
- `foreach`: 목록의 각 요소를 제어 변수에 할당하면서 지정된 본문을 실행한다.
- `for`: 제어 변수 초기화, 조건, "다음 반복" 문(본문 실행 후 실행)을 지정하여 반복 실행을 간편하게 처리한다.
- `break`: 반복문의 본문 실행을 중단하고 반복문에서 반환한다.
- `continue`: 본문 실행을 중단하지만, 제어는 반복문으로 돌아간다. (`while`은 다시 루프 실행, `for`와 `foreach`는 다음 반복).
- `return`: 프로시저 내부 깊이에 관계없이 현재 본문 실행을 중단하고, 지정된 값을 호출자에게 반환한다.
- `expr`: 인자를 별도의 수식 해석기에 전달하고, 평가된 값을 반환한다. (`if` 및 반복문의 조건에도 사용).
- `list`: 모든 인자로 구성된 리스트를 생성하거나, 인자가 없으면 빈 문자열을 생성한다. `lindex` 명령어로 원래 인자를 추출할 수 있다.
- `array`: 배열 변수를 조작한다.
- `dict`: (8.5 버전부터) 딕셔너리를 조작한다. 딕셔너리는 짝수 개의 요소로 구성된 리스트이며, 두 요소마다 키/값 쌍으로 해석된다.
- `regexp`: 문자열에 대한 정규 표현식을 일치시킨다.
- `regsub`: 정규 표현식 패턴 일치를 기반으로 치환을 수행한다.
- uplevel: 명령 스크립트가 현재 범위가 아닌 다른 범위에서 실행될 수 있도록 한다.
- upvar: 다른 스택 프레임의 변수에 대한 링크를 만든다.
- `namespace`: 명령어와 변수에 대한 별도의 컨텍스트를 만들고, 액세스하고, 삭제할 수 있다.
- `apply`: (8.5 버전부터) 익명 함수를 적용한다.
- `coroutine`, `yield`, `yieldto`: (8.6 버전부터) 코루틴으로부터 값을 생성하고 생성한다.
- `try`: 오류와 예외를 가로채고 처리할 수 있다.
- `catch`: 예외적인 반환 값을 가로챌 수 있다.
- `zlib`: (8.6 버전부터) Zlib 라이브러리의 압축 및 체크섬 기능에 대한 액세스를 제공한다.
`uplevel` 명령어는 명령 스크립트를 스택에서 현재 가장 안쪽의 범위가 아닌 다른 범위에서 실행할 수 있도록 한다. 이는 호출 스택을 호출 트리로 변환하는 효과를 낸다.[37]
`upvar` 명령어는 현재 프로시저의 하나 이상의 지역 변수가 상위 프로시저 호출의 변수 또는 전역 변수를 참조하도록 한다. 이는 이름으로 호출하는 프로시저 호출의 구현을 단순화하고, Tcl 프로시저로 새로운 제어 구조를 구축하는 것을 더 쉽게 만든다.[38]
7. 객체 지향 프로그래밍
Tcl 8.6은 2012년에 내장 동적 객체 시스템인 TclOO를 추가했다.[30] 여기에는 다음과 같은 기능이 포함된다.
- 클래스 기반 객체 시스템. 이것은 대부분의 프로그래머가 객체 지향 프로그래밍(OO)에서 기대하는 것이다.
- 객체별 사용자 정의 및 클래스의 동적 재정의 허용
- 메타클래스
- 필터
- 믹스인
- 사용자 정의 방식으로 메서드를 구현하기 위한 시스템. 따라서 패키지 작성자가 메서드 구현을 수행하는 매우 다른 방식을 원하는 경우 상당히 간단하게 수행할 수 있다.
Tcl은 2012년까지 객체 지향 구문을 지원하지 않았으므로,[30] 객체 지향 프로그래밍을 가능하게 하는 다양한 확장 패키지가 등장했다. 이러한 패키지는 기존 Tcl 소스 코드에 널리 사용된다. 인기 있는 확장 패키지로는 다음이 있다.
- 인크리먼트 Tcl(incr Tcl)
- XOTcl
- Itk
- Snit
- http://jfontain.free.fr/stooop.html STOOOP
TclOO는 강력한 객체 지향 시스템을 구축하기 위해 추가된 것뿐만 아니라, 확장 패키지가 이를 기반으로 객체 지향 추상화를 구축할 수 있도록 하기 위해서도 추가되었다. TclOO가 출시된 후 인크리먼트 Tcl(incr Tcl)은 TclOO를 기반으로 사용하도록 업데이트되었다.[26]
8. 웹 애플리케이션 개발
http://www.tcl.tk/software/tclhttpd/ Tcl 웹 서버는 순수 Tcl로 구현된 HTTP 프로토콜 서버이며, 일반 Tcl 인터프리터 위에서 스크립트로 실행된다.
https://tcl.apache.org/rivet/ Apache Rivet은 개발자가 Tcl을 스크립팅 언어로 사용하여 동적인 웹 애플리케이션을 생성할 수 있도록 하는 아파치 HTTP 서버용 오픈 소스 프로그래밍 시스템이다. Rivet은 PHP, ASP, JSP와 유사하며, 주로 Damon Courtney, David Welton, Massimo Manghi, Harald Oehlmann, 그리고 Karl Lehenbauer에 의해 개발되었다. Rivet은 데이터베이스 상호 작용(Oracle, PostgreSQL, MySQL, SQLite 등)이나 GD Graphics Library와 같은 인기 애플리케이션과의 인터페이스 등 수많은 기능을 제공하는 수천 개의 공개적으로 사용 가능한 Tcl 패키지를 사용할 수 있다.
9. 다른 언어와의 인터페이스
Tcl은 기본적으로 C 언어와 인터페이스된다.[39] 이는 원래 C로 작성된 명령어에 대한 구문적 프런트엔드를 제공하기 위한 프레임워크로 작성되었기 때문이며, 언어의 모든 명령어(if나 while과 같이 그렇지 않으면 키워드가 될 수 있는 것들 포함)는 이러한 방식으로 구현된다. 각 명령어 구현 함수에는 명령어의 (이미 치환된) 인수를 설명하는 값의 배열이 전달되며, 해당 값을 자유롭게 해석할 수 있다.
디지털 논리 시뮬레이터에는 종종 Verilog, VHDL, SystemVerilog 하드웨어 언어를 시뮬레이션하기 위한 Tcl 스크립팅 인터페이스가 포함되어 있다.
임의의 C 함수와 Tcl 런타임을 연결하는 데 필요한 코드를 자동으로 생성하는 도구(예: SWIG, [http://elf.org/ffidl Ffidl])가 있으며, [http://equi4.com/starkit/critcl.html Critcl]은 그 반대로 Tcl 스크립트 내에 임의의 C 코드를 포함하고 런타임에 DLL로 컴파일할 수 있도록 한다.
Tcl 명령어에는 Tcl 파서에 미리 구현된 내장 명령어와 사용자가 생성한 확장 명령어가 있다. 확장 명령어 구현은 다음과 같다.
1. C언어 등으로 "명령어 본체 함수"와 "등록용 함수"를 작성하여 동적 링크 라이브러리 파일에 저장한다.
2. 내장 명령어인 `load`를 사용하여 확장 명령어를 등록한다.
load hello.dll hello
`load` 명령어의 인수에는 "라이브러리 파일명"과 "등록용 명령어명"을 준다. `load` 명령어는 등록용 명령어명에서 "등록용 함수"명을 찾아 이를 실행한다. 예를 들어 `hello` 명령어라면 `Hello_Init`을 실행한다. 이 "등록용 함수" 안에 실제 등록 처리를 작성해 둔다. 따라서, `load` 명령어에 전달한 명령어명에 라이브러리명의 의미를 부여하고, "등록용 함수" 안에서 여러 개의 명령어를 등록하는 것도 가능하다.
"실제" 명령어 등록은 C언어 인터페이스용 함수인 `Tcl_CreateCommand`나 `Tcl_CreateObjCommand`를 사용하여 수행한다. 확장 명령어의 실체가 되는 "명령어 본체 함수"를 정해진 형식과 인수에 따라 미리 정의해 두고, 그 명령어 함수 주소와 공개 명령어명을 인수로 주어 실행하면 등록된다.
명령어 등록 함수 예시는 다음과 같다.
int Hello_Init (Tcl_Interp *interp)
{
Tcl_CreateObjCommand (interp, "hello", Tcl_HelloCmd, NULL, NULL) ;
return TCL_OK ;
}
명령어 본체 함수 예시는 다음과 같다.
int Tcl_HelloCmd (ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv [])
{
...
return TCL_OK ;
}
명령어 본체 함수는 Tcl 파서로부터 인수를 인수 개수(argc)와 인수 문자열 배열(argv)로 받는다. 단, 인수를 문자열로 받는 방식은 `Tcl_CreateCommand` 함수로 등록하는 경우이며, 인수를 Tcl 객체로 받고 싶은 경우에는 위 예와 같이 `Tcl_CreateObjCommand` 함수로 등록한다.
10. 확장 패키지
Tcl 언어는 GUI, 터미널 기반 애플리케이션 자동화, 데이터베이스 접근 등 추가 기능을 제공하는 확장 패키지를 항상 지원해 왔다. 일반적으로 사용되는 확장 기능은 다음과 같다.
- '''Tk''': 가장 인기 있는 Tcl 확장 기능은 다양한 운영 체제에 대한 그래픽 사용자 인터페이스 라이브러리를 제공하는 Tk 툴킷이다. 각 GUI는 하나 이상의 ''프레임''으로 구성되며, 각 프레임에는 레이아웃 관리자가 있다.
- '''Expect''': 또 다른 매우 인기 있는 Tcl 확장 기능 중 하나는 Expect 확장 기능이다. Expect와 Tcl의 초기 밀접한 관계는 Unix 테스트와 같이 Expect가 (오늘날에도 여전히) telnet, ssh 및 직렬 세션을 자동화하여 많은 반복적인 작업(즉, 이전에는 대화형으로만 가능했던 애플리케이션의 스크립팅)을 수행하는 데 매우 성공적으로 사용된 분야에서 Tcl의 인기에 크게 기여했다. Tcl은 Expect를 실행하는 유일한 방법이었으므로 Tcl은 이러한 산업 분야에서 매우 인기를 얻었다.
- '''Tile/Ttk''': Tile/Ttk[40]는 운영 체제의 API를 호출하여 실제로 플랫폼에 기본적인 변형으로 Tk의 대부분 위젯을 대체할 수 있는 스타일 및 테마 위젯 컬렉션이다. 이러한 방식으로 다루는 테마는 Windows XP, Windows Classic, Qt(X11 KDE 환경 라이브러리에 연결됨), Aqua(Mac OS X)이다. 이미지 픽스맵으로 보완된 위젯 정의를 사용하여 테마를 이러한 호출 없이 구성할 수도 있다. 이러한 방식으로 생성된 테마에는 Classic Tk, Step, Alt/Revitalized, Plastik 및 Keramik이 포함된다. Tcl 8.4에서는 이 패키지를 Tile이라고 하지만, Tcl 8.5에서는 Tk의 핵심 배포판(Ttk로)에 통합되었다.
- '''Tix''': Tix(Tk Interface eXtension)는 Tcl/Tk 및 Python 애플리케이션의 기능을 확장하는 일련의 사용자 인터페이스 구성 요소이다. Tix 프로젝트 그룹의 자원봉사자들이 유지 관리하고 BSD 스타일 라이선스에 따라 배포되는 오픈 소스 소프트웨어 패키지이다.[41]
- '''Itcl/IncrTcl''': Itcl은 Tcl의 객체 시스템이며 일반적으로 [incr Tcl](Tcl에서 증가시키는 방법, C++ 이름과 유사)이라고 한다.
- '''Tcllib''': Tcllib는 컴파일 단계 없이 사용할 수 있는 Tcl용 스크립트 패키지 세트이다.
- '''Tklib''': Tklib는 Tk용 유틸리티 모듈 컬렉션이며 Tcllib의 동반자이다.
- '''tDOM''': tDOM은 Expat 파서를 기반으로 XML을 구문 분석하기 위한 Tcl 확장 기능이다.
- '''TclTLS''': TclTLS는 Tcl에 대한 OpenSSL 확장 기능이다.
- '''TclUDP''': TclUDP[42] 확장 기능은 Tcl에서 사용자 데이터그램 프로토콜(UDP) 소켓을 지원하는 간단한 라이브러리를 제공한다.
- '''TWAPI''': TWAPI(Tcl Windows API)는 Windows API에 대한 바인딩을 제공하는 Tcl에 대한 확장 기능이다.
- '''데이터베이스''': Tcl 8.6의 일부인 Tcl Database Connectivity(TDBC)는 Tcl 스크립트를 위한 일반적인 데이터베이스 액세스 인터페이스이다. 현재 MySQL, ODBC, PostgreSQL 및 SQLite 데이터베이스에 액세스하기 위한 드라이버를 지원한다. 향후 더 많은 드라이버가 계획되어 있다. 데이터베이스에 대한 액세스는 다양한 데이터베이스별 확장 기능을 통해서도 지원된다.[43]
참조
[1]
웹사이트
PHP on Hormones – history of PHP presentation by Rasmus Lerdorf given at the MySQL Conference in Santa Clara, California
http://itc.conversat[...]
The Conversations Network
2007-04-26
[2]
웹사이트
PowerShell and WPF: WTF
http://blogs.msdn.co[...]
Microsoft
[3]
웹사이트
TH1 Scripts
https://fossil-scm.o[...]
Fossil
[4]
웹사이트
Tcl/Tk License Terms
http://www.tcl-lang.[...]
[5]
웹사이트
Tcl Dev Kit – Compiler
http://docs.activest[...]
[6]
뉴스그룹
Re: TCL certification
https://groups.googl[...]
2005-07-04
[7]
웹사이트
Language
http://www.tcl-lang.[...]
[8]
서적
Tcl Fundamentals
[9]
웹사이트
Uses for Tcl/Tk
http://www.tcl-lang.[...]
[10]
웹사이트
Cisco IOS Scripting with TCL Configuration Guide
http://www.cisco.com[...]
[11]
웹사이트
History of Tcl
http://www.stanford.[...]
Stanford University
[12]
웹사이트
History of Tcl
http://www.tcl-lang.[...]
[13]
서적
Tcl and the Tk Toolkit
[14]
웹사이트
EDA
https://wiki.tcl-lan[...]
[15]
웹사이트
John K Ousterhout – Award Winner
http://awards.acm.or[...]
[16]
웹사이트
Tcl vs. TCL
http://wiki.tcl.tk/1[...]
[17]
웹사이트
Tcl/Tk 8.0 Release Announcement
http://www.tcl.tk/so[...]
[18]
웹사이트
Tcl/Tk 8.1 Release Announcement
http://www.tcl.tk/so[...]
[19]
웹사이트
New Regular Expression Features in Tcl 8.1
http://www.tcl.tk/do[...]
[20]
웹사이트
Tcl/Tk 8.2 Release Announcement
http://www.tcl.tk/so[...]
1999-08-18
[21]
웹사이트
Tcl/Tk Core Development
http://www.tcl.tk/co[...]
[22]
웹사이트
Tcl/Tk 8.4 Release Announcement
http://www.tcl.tk/so[...]
2013-06-01
[23]
웹사이트
TIP #237: Arbitrary-Precision Integers for Tcl
http://www.tcl.tk/cg[...]
[24]
웹사이트
TIP #194: TIP #194: Procedures as Values via apply
http://www.tcl.tk/cg[...]
[25]
웹사이트
Tcl/Tk 8.5 Release Announcement
http://www.tcl.tk/so[...]
2013-09-18
[26]
웹사이트
Tcl/Tk 8.6 Release Announcement
http://www.tcl.tk/so[...]
2013-09-20
[27]
웹사이트
Tcl/Tk 9.0 Release Announcement
https://www.tcl-lang[...]
2024-09-26
[28]
웹사이트
Tcl/Tk Conferences
https://www.tcl.tk/c[...]
[29]
웹사이트
FlightAware
https://github.com/f[...]
[30]
웹사이트
TIP #257: Object Orientation for Tcl
http://www.tcl.tk/cg[...]
[31]
웹사이트
Download Tcl/Tk Sources
http://www.tcl.tk/so[...]
[32]
웹사이트
Safe Tcl
http://www.tcl.tk/so[...]
[33]
학회발표
Mobile Code Security
https://books.google[...]
1996-09-18
[34]
서적
Practical programming in Tcl and Tk
Prentice Hall PTR
[35]
웹사이트
Tcl manual page – Tcl Built-In Commands
http://www.tcl.tk/ma[...]
[36]
웹사이트
Dodekalogue
http://wiki.tcl.tk/1[...]
Tcler's Wiki
2014-06-14
[37]
웹사이트
uplevel manual page – Built-In Commands
http://www.tcl.tk/ma[...]
2016-06-14
[38]
웹사이트
upvar manual page – Built-In Commands
http://www.tcl.tk/ma[...]
2016-06-14
[39]
웹사이트
Tcl C API
https://www.tcl.tk/m[...]
2016-11-02
[40]
웹사이트
Tile: an improved themeing engine for Tk
http://tktable.sourc[...]
2016-08-07
[41]
웹사이트
Tix License
http://tix.sourcefor[...]
SourceForge
2012-08-07
[42]
웹사이트
TclUDP
http://wiki.tcl.tk/8[...]
Tcl'ers Wiki
2012-08-07
[43]
웹사이트
TDBC
http://wiki.tcl.tk/2[...]
Tcl'ers Wiki
2012-08-07
[44]
웹사이트
Tcl/Tk 9.0
https://www.tcl.tk/s[...]
2024-11-08
[45]
웹사이트
Tcl/Tk 9.0
https://www.tcl.tk/s[...]
2024-09-19
[46]
웹사이트
Latest Release: Tcl/Tk 9.0.0 (Sep 26, 2024)
http://www.tcl.tk/so[...]
2024-09-26
[47]
웹사이트
Windows PowerShell : PowerShell and WPF: WTF
https://devblogs.mic[...]
[48]
일반
Dr. John Kenneth Ousterhout
[49]
웹사이트
Tcl vs. TCL
http://wiki.tcl.tk/1[...]
Tcler's Wiki
2008-07-19
본 사이트는 AI가 위키백과와 뉴스 기사,정부 간행물,학술 논문등을 바탕으로 정보를 가공하여 제공하는 백과사전형 서비스입니다.
모든 문서는 AI에 의해 자동 생성되며, CC BY-SA 4.0 라이선스에 따라 이용할 수 있습니다.
하지만, 위키백과나 뉴스 기사 자체에 오류, 부정확한 정보, 또는 가짜 뉴스가 포함될 수 있으며, AI는 이러한 내용을 완벽하게 걸러내지 못할 수 있습니다.
따라서 제공되는 정보에 일부 오류나 편향이 있을 수 있으므로, 중요한 정보는 반드시 다른 출처를 통해 교차 검증하시기 바랍니다.
문의하기 : help@durumis.com
