Typst로 문서를 만들어 보자!


지금까지는 문서를 만들 일이 있을 때 PPT나 Word를 사용했었는데, 최근에 Typst를 알게 돼서 이를 기반으로 동아리 모의대회 해설을 만들어 보았다. 문법을 익히기도 쉬웠고, 바로바로 변동사항이 미리보기에 반영돼서 매력적이었다.

Typst로 작성한 에디토리얼

 아직 사용해보지 않았지만, 동시에 여러 명이 문서를 편집할 수 있다는 점도 굉장히 편리한 기능 중 하나. 연말에 진행할 교내 대회 해설도 Typst를 사용해서 만들어볼만 할 것 같다. 레퍼런스에 문법과 관련된 사항이 자세하게 설명돼 있다.

익힌 것들을 기록해두고자 글을 씁니다. 다소 글이 복잡하더라도 양해 바랍니다 🙌🏻


최초에 파일을 만들면, 워드를 처음 만들었을 때와 같이 빈 문서가 눈에 들어온다.

왼쪽이 문서를 작성하는 곳이고, 오른쪽이 왼쪽의 코드를 컴파일한 결과가 미리보기로 나타나지는 공간이다. 왼쪽에서 코드를 수정할 때마다, 컴파일 상에 에러가 발생하지 않으면 그때그때 새로고침돼 오른쪽 미리보기에 반영된다.

Typst는 LaTeX와 같이 문서를 작성하기 위해 만들어졌으므로, 논문이나 발표 자료 등 많은 곳에 사용할 수 있다만, 잠깐 배운 몇가지 기능을 소개하기 위해서 간단한 사용법만 소개한다. 더 깊은 내용에 관해서는 레퍼런스를 참고하기 바란다!

#set 을 통해서 해당 문서에서 사용되는 함수 내 인자를 미리 전역적으로 설정할 수 있다. 함수(function)은 타입 중 하나인데, 페이지의 속성을 설정하는 page, 텍스트의 속성을 설정하는 text, 리스트를 나타내는 list 등이 있다.

설정하는 방법은 #set 함수(속성: 값, …) 이다. 만약 내가 이 문서에서 특정 글꼴을 사용하고 싶다면 아래 그림과 같이 작성하면 된다. set으로 설정된 속성들은 따로 다시 설정하지 않는 한 유지된다.

워드로 말하자면 용지 방향 (가로, 세로)를 의미하는 page의 flipped 속성도 있다. #set page(flipped: true) 로 설정해 주면 가로로 긴 페이지에서 작업할 수 있다.

문서를 작업하는 것이라서 메모장 정도 아니야? 라고 생각할 수 있지만, Typst는 오히려 프로그래밍 언어에 가깝다.

배열도 있고, 원소 하나하나에 대해서 함수를 먹이는 map도 있고, if/elsefor loop 과 같은 많은 것들을 지원한다.

몇 가지 함수나 사용 방법을 다뤄보기 위해 표를 만들어 보자. (문제 번호, 문제 이름, 난이도)를 적어 둘 표이다. 미리 완성된 표는 아래와 같다.

표를 작성할 때에는 #grid 를 사용한다. 해당 함수 안에 들어가는 속성 중 유용한 것으로는 columns(몇 개의 열이 들어가는지), gutter(행/열 간 간격)이 있다.

위와 같이 작성하면 된다. 표 안에 들어가는 content(Typst의 타입이다) 들은 한 행을 기준으로 채워나가기 때문에, 이렇게 작성할 수 있다.

그런데 이렇게 작성하다 보면 굉장히 불편하다…(불편해야 한다)

하나하나 작성하는 것은 둘째치고, 각각의 텍스트가 어디에 위치하는지 코드를 보고 한 눈에 알 수 없기 때문이다. 이 때 반복문을 사용하면 편리하게 작성할 수 있다.

코드가 조금 어려워졌지만, 훨씬 깔끔하고 가독성있게 작성할 수 있다. row_content 라는 새로운 함수를 만들었다. 해당 함수는 한 줄에 해당하는 grid를 만들어준다. 한 줄에 해당하는 grid를 매번 만들어서 삽입하면 되고, 그것도 반복문을 통해서 간략하게 진행한다.

이렇게 하면 problem이 많아지더라도 위에서 선언한 problems 만을 수정하면 된다.

이제 각 칸에 색을 입혀 보자!

#set text(font: "Pretendard", weight: "medium")
 
#let header = ("번호", "제목", "난이도")
#let problems = (
  ("3A", "Pen Pineapple Apple Pen", "Easy"),
  ("3B", "증가 배열 만들기", "Easy"),
  ("3C", "카우버거", "Medium")
)
 
#let cell = rect.with(
  fill: rgb("f0f0f0"),
  width: 100%
)
#let black_cell = cell.with(fill: black)
 
#let header_content(p1, p2, p3) = {
    grid(
    columns: (10%, 30%, 15%),
    column-gutter: 1pt,
    black_cell[#text(fill: white)[#p1]],
    black_cell[#text(fill: white)[#p2]],
    black_cell[#text(fill: white)[#p3]]
  )
}
 
#let row_content(p1, p2, p3) = {
  grid(
    columns: (10%, 30%, 15%),
    column-gutter: 1pt,
    cell[#p1],
    cell[#p2], 
    cell[#p3]
  )
}
 
#grid(
  columns: (100%),
  row-gutter: 1pt,
  header_content(..header),
  ..problems.map(problem => {
    row_content(..problem)    
  })
)

각 함수 (cell, text)에 잇따르는 대괄호는 content를 의미하며, 안에 content가 해당 함수에 의해 감싸져서 나온다. 예를 들어, 중간에 #text(fill: white)[#p1] 은 text함수를 적용할 내용이 p1이라는 의미이다. content 내부는 텍스트 취급하므로, 파라미터 값이나 함수를 사용하고 싶다면 앞에 #를 붙여줘야 한다.

이외에도 alignimagelist와 같이 많은 함수를 사용해서 문서를 풍성하게 만들 수 있다.

직접 만든 문서는 아래 링크에서 확인할 수 있고, 해당 문서를 만들면서 적용한 여러 문법들이 도움되길 바란다! Typst에서는 특히나 PDF 미리보기 구역에서 원하는 항목을 클릭할 경우, 해당 항목이 렌더링된 코드를 찾아가주기도 하니 여러 기능을 유용하게 잘 사용했으면 좋겠다.

https://github.com/donghoony/typst_editorial

Categories