논문이나 교과서에서 보는, 테두리로 둘러싸이고 “Algorithm 1”처럼 번호가 붙은 의사코드는 LaTeX의 기본 기능이 아니라 패키지로 만듭니다. 처음 헷갈리는 지점은 비슷한 이름의 패키지가 여러 개 있다는 점입니다. 핵심은 입구(플로트하는 번호 상자)와 내용(의사코드 자체)을 서로 다른 패키지가 맡는 분업입니다. 이 페이지에서는 그 지형을 정리하고, algorithm 플로트 안에 algpseudocode 본문을 넣는 표준 조합과, 모든 것을 하나로 처리하는 경쟁자인 algorithm2e를 실제로 컴파일할 수 있는 코드와 함께 살펴봅니다. 여기에는 실시간 렌더러가 없으므로, 각 예제가 무엇을 만들어 내는지 본문에서 설명합니다.
입구와 내용: 두 층 구조
의사코드 조판은 역할이 다른 두 층으로 나뉩니다. 첫 번째 층은 입구입니다. figure나 table처럼 페이지 위에서 떠다니며 “Algorithm 1” 캡션과 일련 번호, 상호 참조, 필요하다면 알고리즘 목록까지 제공하는 상자입니다. 이를 제공하는 것이 algorithm 패키지(\usepackage{algorithm})이고, \begin{algorithm} … \end{algorithm} 환경을 하나 추가합니다.
두 번째 층은 내용입니다. \State(한 문장), \While(반복), \If(조건 분기) 같은 명령으로 들여쓰기와 행 번호를 갖춘 의사코드 자체를 조판하는 부분입니다. 여기서 선택지가 갈립니다. 오래된 algorithmic 패키지, 그 후계로 더 자유롭게 고칠 수 있는 algorithmicx(실제로는 그 위의 algpseudocode 레이아웃을 사용), 그리고 독립된 별도 계열 algorithm2e입니다.
핵심은 본문 패키지는 원칙적으로 하나만 고르는 것입니다. algpseudocode와 algorithm2e는 문법과 철학이 완전히 달라 섞으면 충돌합니다. 반면 입구인 algorithm은 algpseudocode와 짝으로 쓰도록 되어 있습니다. algorithm2e는 입구와 내용을 모두 자체적으로 갖고 있으므로 algorithm이 필요 없고, 함께 쓰는 것은 권장되지 않습니다. 아래 표가 전체 그림을 보여 줍니다.
| 패키지 | 층 | 역할 |
|---|---|---|
algorithm | 입구 | 플로트 상자 + “Algorithm N” 캡션/번호. 본문 패키지와 함께 사용 |
algorithmic | 내용(구식) | 원조 의사코드 환경. 대문자 명령(\STATE 등). 거의 수정 불가 |
algpseudocode | 내용(현대) | algorithmicx의 표준 레이아웃. 모양은 algorithmic과 같지만 훨씬 유연함 |
algorithm2e | 입구+내용 | 독립적 자체 완결형. 독자 문법(\KwIn, \eIf, 행 끝 \\;). 단독 사용 |
algorithm은 algorithms bundle에 들어 있으며, 같은 번들에 algorithmic도 포함되어 있습니다. algorithmicx는 별도 배포이지만, algpseudocode를 읽으면 내부에서 자동으로 불러오기 때문에 사용자가 algorithmicx를 직접 \usepackage할 필요는 없습니다.
algpseudocode 명령
algpseudocode 의사코드는 \begin{algorithmic} … \end{algorithmic} 환경 안에 씁니다. 환경 이름이 본문 패키지 이름(algpseudocode)과 다르다는 점에 주의하세요. 환경은 어디까지나 algorithmic입니다. 시작 시의 선택 인수 [1]은 행 번호를 제어하며, 0은 번호 없음, 1은 모든 행 번호, n은 n행마다 번호를 붙입니다. 명령 이름은 모두 첫 글자만 대문자(\State, \While 등)라서, 모두 대문자인 옛 algorithmic(\STATE, \WHILE)과 가장 쉽게 구별됩니다.
기본은 \State로, 의사코드의 각 행 시작을 나타냅니다. 대입이나 절차 호출 등 하나의 문장마다 \State를 둡니다. 반면 \While이나 \If처럼 블록을 여는 명령 앞에는 \State가 필요 없습니다(블록 명령 자체가 새 행을 시작합니다). 블록 내용은 자동으로 들여쓰기되며, 소스 쪽 들여쓰기는 출력에 영향을 주지 않습니다. 주요 명령은 다음과 같습니다.
\State— 하나의 문장(행)의 시작.\State $x \\gets 1$처럼 사용합니다.\For{cond}…\EndFor— for 반복. 출력은 “for … do”로 시작해 “end for”로 닫힙니다.\ForAll{cond}도 있습니다.\While{cond}…\EndWhile— while 반복. “while … do” / “end while”.\If{cond}…\ElsIf{cond}…\Else…\EndIf— 조건 분기. “if … then”, “else if … then”, “else”, “end if”.\ElsIf와\Else는 생략할 수 있습니다.\Function{name}{args}…\EndFunction— 함수. “function name(args)” / “end function”. 절차형\Procedure{name}{args}…\EndProcedure도 같은 모양입니다.\Return— 반환값. 곧은 굵은 키워드 “return …”으로 조판됩니다.\Comment{...}— 행 끝 주석. 오른쪽 삼각형 ▷ 뒤에 주석이 놓입니다.\Require/\Ensure— 전제 조건과 사후 조건. 각각 굵은 “Require:” / “Ensure:” 라벨이 앞에 붙습니다.
이 키워드들은 바꿀 수 있습니다. 예를 들어 영어 “Require:”, “Ensure:” 대신 입력/출력 의미로 “Input:”, “Output:”을 쓰고 싶다면 프리앰블에서 \renewcommand{\algorithmicrequire}{\textbf{Input:}}, \renewcommand{\algorithmicensure}{\textbf{Output:}}로 재정의합니다. 마찬가지로 \algorithmicwhile, \algorithmicdo 등을 바꾸면 반복과 분기의 단어도 자유롭게 바꿀 수 있습니다.
완성 예: algorithm + algpseudocode
두 층을 조합하면 이렇게 됩니다. 바깥은 algorithm 플로트로 감싸고, \caption{…}으로 캡션을, \label{…}로 참조 라벨을 붙이며, 안쪽의 algorithmic 환경에 의사코드를 씁니다. 다음은 거듭제곱 y = xⁿ을 계산하는 고전적인 알고리즘입니다.
\documentclass{article}
\usepackage{algorithm}
\usepackage{algpseudocode}
\begin{document}
\begin{algorithm}
\caption{Calculate $y = x^n$}\label{alg:power}
\begin{algorithmic}[1]
\Require $n \geq 0$
\Ensure $y = x^n$
\State $y \gets 1$
\State $X \gets x$
\State $N \gets n$
\While{$N \neq 0$}
\If{$N$ is even}
\State $X \gets X \times X$
\State $N \gets N / 2$ \Comment{even case}
\Else
\State $y \gets y \times X$
\State $N \gets N - 1$
\EndIf
\EndWhile
\State \Return $y$
\end{algorithmic}
\end{algorithm}
アルゴリズム~\ref{alg:power} は累乗を計算する。
\end{document}컴파일하면 위아래에 가로줄이 있는 상자가 페이지에 플로트로 배치되고, 위쪽에 “Algorithm 1 Calculate y = xⁿ”라는 제목이 붙습니다(번호는 자동). 상자 안에서는 각 행 왼쪽에 1, 2, 3 … 행 번호가 붙고, 처음 두 행은 굵은 “Require:”, “Ensure:” 뒤에 전제 조건과 결과를 보입니다. \While 행은 굵은 while과 끝의 do로 조판되고, 그 내용은 한 단계 들여쓰기됩니다. \Comment 주석은 오른쪽 삼각형 뒤에 행 끝에 놓이며, 마지막 행은 return 뒤에 y가 이어집니다. 본문의 \ref{alg:power}는 상자 번호(여기서는 1)로 바뀌어 “Algorithm 1 is…”처럼 표시됩니다.
의사코드 안의 수식($N \\neq 0$, $y \\gets 1$)은 일반 수식 모드와 마찬가지로 $…$로 감쌉니다. \gets는 왼쪽 화살표(←)로, 대입을 나타내는 관용 표기입니다. 번호와 상호 참조를 확정하려면 algorithm을 쓰는 문서는 평소처럼 두 번 컴파일합니다.
경쟁자: algorithm2e
또 하나의 주요 선택지는 algorithm2e입니다. 이는 입구와 내용을 하나의 패키지 안에서 자체 완결시키는 별도 계열로, \begin{document} 전에 \usepackage[...]{algorithm2e}로 읽습니다. algorithm 환경 자체가 플로트이므로 안쪽에 다른 본문 환경을 넣을 필요가 없습니다. 문법도 algpseudocode와 크게 다릅니다.
가장 큰 차이는 두 가지입니다. 첫째, 입력과 출력은 전용 명령 \KwIn{…}, \KwOut{…}(또는 \KwData{…}, \KwResult{…})으로 쓰며, 각각 굵은 “Input:”, “Output:”, “Data:”, “Result:”로 조판됩니다. 둘째, 조건 분기와 반복은 본문을 인수로 넘기는 중괄호 형식입니다. 예를 들어 if–then–else는 \eIf{cond}{then part}{else part}처럼 블록 내용을 { }로 넘깁니다(e는 else가 있음을 뜻합니다). \For{cond}{body}, \While{cond}{body}도 마찬가지입니다.
또 하나 주의할 규칙은 모든 문장의 끝을 \\;(백슬래시+세미콜론)로 닫아야 한다는 것입니다. 이를 잊으면 다음 문장이 같은 행에 이어집니다. 다음은 짧은 예입니다.
\documentclass{article}
\usepackage[ruled,linesnumbered]{algorithm2e}
\begin{document}
\begin{algorithm}[H]
\caption{Sum of positive entries}
\KwIn{an array $a[1..n]$}
\KwOut{the sum $s$ of its positive entries}
$s \gets 0$\;
\For{$i \gets 1$ \KwTo $n$}{
\eIf{$a[i] > 0$}{
$s \gets s + a[i]$\;
}{
skip\;
}
}
\Return $s$\;
\end{algorithm}
\end{document}이 예에서는 ruled 옵션으로 위아래에 가로줄이 그어지고 위쪽에 캡션 행이 붙은 상자가 만들어지며, linesnumbered로 각 행에 번호가 붙습니다. [H]는 그림표에서의 배치 지정과 같아서, 플로트시키지 않고 그 자리에 고정합니다(h, t, b, p도 사용할 수 있습니다). algorithm2e는 내부에서 [H]를 자체 구현하므로 float 패키지를 따로 읽을 필요가 없습니다(옛 algorithm 패키지에서 [H]를 쓸 때 \usepackage{float}가 필요한 것과 다릅니다). 상자 처음에는 굵은 “Input:”, “Output:”가 놓이고, \For 행은 for i ← 1 to n do로 조판되며 본문은 들여쓰기됩니다. \eIf는 if … then의 참 블록과 else의 거짓 블록을 위아래로 놓습니다. 각 \; 위치에서 줄바꿈이 일어나고 마지막 행에 return s가 출력됩니다.
모양을 다듬는 명령도 몇 가지 있습니다. \SetAlgoLined(옛 이름 \SetLine)는 블록 경계에 세로줄을 그려 구조를 보이고, \DontPrintSemicolon은 문장 끝의 \\;가 출력에 표시되지 않게 합니다. \KwTo는 “to”, \Return은 “return”으로 조판되는 내장 키워드이며, 이것들도 재정의해서 일본어 등으로 바꿀 수 있습니다. 주석은 \tcc{…}(/* … */ 형식)나 \tcp{…}(// 형식)로 넣습니다.
어느 쪽을 쓸까
둘 다 널리 쓰이며, 우열이라기보다 관습의 차이입니다. algorithm + algpseudocode는 \State를 바탕으로 한 단순한 명령 체계이며, 행 머리에 키워드가 오고 do, then, end …로 감싸는 전통적 의사코드 모양을 좋아하거나 학회 템플릿이 이를 전제로 할 때 적합합니다. algorithm2e는 입력/출력 선언이 명시적이고, 블록을 중괄호로 넘기는 방식과 세로줄이 있는 모양을 좋아하는 사람, 다국어 키워드와 세밀한 사용자 정의를 많이 쓰는 사람에게 인기가 있습니다.
반복하지만, 본문 패키지는 하나로 좁히는 것이 원칙입니다. algpseudocode와 algorithm2e를 모두 읽으면 \For, \If 같은 같은 이름의 명령이 충돌해 오류가 납니다. 문서 전체에서 어느 한쪽으로 통일하세요. algorithm2e를 쓰는 경우 입구인 algorithm은 필요하지 않습니다. algorithm2e 자체가 algorithm 환경을 정의하므로 둘을 모두 읽으면 환경 이름이 충돌합니다.