지금까지 우리는 변수에 데이터를 저장하고, 연산자로 이 데이터들을 계산하고 비교하는 방법을 배웠습니다. 하지만 프로그램이 단순히 위에서 아래로 순서대로만 실행된다면, 매우 단순한 작업밖에 할 수 없을 것입니다. 실제 프로그램은 상황에 따라 다른 동작을 하거나, 특정 작업을 여러 번 반복해야 합니다.
이처럼 프로그램의 실행 흐름을 지휘하는 것을 제어 구조(Control Structures) 또는 흐름 제어문이라고 합니다. 제어 구조를 사용하면 코드에 지능을 부여하여, 조건에 따라 분기하거나 특정 코드 블록을 반복 실행하도록 만들 수 있습니다.
이 글에서는 Lua의 핵심 제어 구조인 조건문(if)과 반복문(while, repeat, for)의 사용법을 자세히 알아보고, 프로그램의 흐름을 더욱 유연하게 만드는 방법을 익혀보겠습니다.
상황에 따른 판단: 조건문 if
if
문은 가장 기본적인 제어 구조로, 주어진 조건이 참인지 거짓인지에 따라 다른 코드를 실행하도록 만듭니다. 마치 “만약 비가 오면, 우산을 챙겨라”와 같은 논리적 판단을 코드에 구현하는 것입니다.
Lua의 진실 혹은 거짓: Lua에서는
false
와nil
두 가지 값만이 ‘거짓’으로 간주됩니다. 그 외의 모든 값(숫자0
, 빈 문자열""
포함)은 ‘참’으로 취급됩니다.
기본 if
문
가장 간단한 형태는 if ... then ... end
구조입니다. 조건이 참일 경우에만 then
과 end
사이의 코드가 실행됩니다.
local temperature = 25
if temperature > 20 then -- 조건: 온도가 20보다 큰가? (참)
print("날씨가 따뜻합니다.") -- 조건이 참이므로 실행됨
end
if ... else
문 (그렇지 않다면)
조건이 참일 때와 거짓일 때 각각 다른 코드를 실행하고 싶다면 else
를 사용합니다.
local age = 15
if age >= 19 then -- 조건: 나이가 19 이상인가? (거짓)
print("성인입니다.") -- 실행되지 않음
else -- 조건이 거짓일 경우 실행됨
print("미성년자입니다.")
end
if ... elseif ... else
문 (다양한 조건 검사)
여러 조건을 순서대로 검사하고 싶을 때는 elseif
를 사용합니다. if
또는 elseif
조건 중 하나라도 참이 되면 해당 블록의 코드를 실행하고, 나머지 조건은 검사하지 않은 채 if
문 전체를 빠져나옵니다.
local grade = "B"
if grade == "A" then
print("우수합니다!")
elseif grade == "B" then -- 첫 번째 조건은 거짓, 이 조건은 참
print("좋습니다!") -- 이 코드가 실행되고 if문 종료
elseif grade == "C" then
print("보통입니다.")
else
print("노력이 필요합니다.")
end
지루한 작업의 자동화: 반복문 (Loops)
반복문은 특정 조건이 만족되는 동안 또는 지정된 횟수만큼 코드 블록을 자동으로 반복 실행합니다. Lua는 while
, repeat
, for
세 가지 종류의 반복문을 제공합니다.
while
루프: 조건이 참인 동안 반복
while
루프는 주어진 조건이 참인 동안 do
와 end
사이의 코드를 계속해서 반복합니다. 루프에 진입하기 전에 조건을 먼저 검사하므로, 처음부터 조건이 거짓이면 코드는 한 번도 실행되지 않을 수 있습니다.
local count = 1
while count <= 5 do -- 조건: count가 5보다 작거나 같은 동안
print("현재 카운트: " .. count)
count = count + 1 -- count 값을 1 증가시켜야 루프가 언젠가 끝납니다.
end
print("while 루프 종료.")
-- 출력: 현재 카운트: 1, 2, 3, 4, 5
경고:
while
루프 안에서 조건을 변경하는 코드가 없다면, 조건이 영원히 참으로 유지되어 프로그램이 멈추는 무한 루프에 빠질 수 있습니다. 항상 루프가 종료될 수 있는 조건을 만들어야 합니다.
repeat ... until
루프: 조건이 참이 될 때까지 반복
repeat
루프는 while
과 비슷하지만 두 가지 중요한 차이가 있습니다.
- 코드를 먼저 실행하고 루프 끝에서 조건을 검사합니다. 따라서 코드는 최소 한 번은 반드시 실행됩니다.
until
뒤의 조건이 참(true)이 되면 루프를 종료합니다. (while
은 조건이 거짓이 되면 종료)
local attempts = 0
local password_correct
repeat
attempts = attempts + 1
print("시도 " .. attempts .. ": 비밀번호를 확인합니다...")
-- 3번째 시도에서 성공했다고 가정
if attempts == 3 then
password_correct = true
end
until password_correct == true -- 조건: password_correct가 true가 되면 종료
print("로그인 성공!")
-- 출력: 시도 1, 시도 2, 시도 3을 거친 후 로그인 성공!
for
루프: 가장 구조적인 반복
for
루프는 정해진 횟수만큼 반복하거나, 테이블 같은 데이터 모음의 모든 항목을 순회하는 데 가장 널리 사용되는 반복문입니다. Lua에는 두 가지 형태의 for
루프가 있습니다.
1. 숫자 for
루프
시작값부터 끝값까지 특정 단계(step)만큼 변수 값을 변경하며 반복합니다.
for 변수 = 시작값, 끝값, [단계값] do ... end
단계값
을 생략하면 기본값은1
입니다. 음수일 수도 있습니다.
-- 1부터 5까지 1씩 증가
for i = 1, 5 do
print("i = " .. i)
end
-- 10부터 0까지 2씩 감소
for j = 10, 0, -2 do
print("j = " .. j)
end
2. 제네릭 for
루프 (테이블 순회)
이터레이터(iterator) 함수를 사용하여 테이블과 같은 컬렉션의 모든 요소를 순회합니다. Lua는 테이블 순회를 위한 유용한 이터레이터 pairs
와 ipairs
를 기본으로 제공합니다.
pairs(테이블)
: 테이블의 모든 키-값 쌍을 순회합니다. (순서는 보장되지 않음)
local person = { name = "Alice", age = 30, city = "Seoul" }
for key, value in pairs(person) do
print(key .. ": " .. tostring(value))
end
-- 출력 예시 (순서는 바뀔 수 있음):
-- name: Alice
-- city: Seoul
-- age: 30
ipairs(테이블)
: 테이블의 배열 부분(정수 인덱스 1, 2, 3…)을 순서대로 순회합니다.
local colors = { "red", "green", "blue" }
for index, color in ipairs(colors) do
print("Index " .. index .. ": " .. color)
end
-- 출력:
-- Index 1: red
-- Index 2: green
-- Index 3: blue
흐름을 끊는 기술: break
때로는 루프가 끝나기 전에 특정 조건이 만족되면 즉시 반복을 중단해야 할 때가 있습니다. 이때 break
키워드를 사용하면 자신을 감싸고 있는 가장 안쪽의 루프 하나를 즉시 빠져나갈 수 있습니다.
local numbers = { 1, 5, 12, 8, 25, 3 }
local target = 8
for index, num in ipairs(numbers) do
print("확인 중: " .. num)
if num == target then
print("목표(" .. target .. ")를 인덱스 " .. index .. "에서 찾았습니다!")
break -- 목표를 찾았으므로 더 이상 반복할 필요 없음
end
end
참고: goto
문에 대하여
Lua에는 goto
문도 존재하지만, 코드의 흐름을 예측하기 어렵게 만들고 유지보수를 힘들게 하는 원인이 될 수 있으므로 사용을 극도로 자제하는 것이 좋습니다. 대부분의 경우 if
, 루프, break
, 함수를 사용해 더 명확하고 구조적인 코드를 작성할 수 있습니다.
이번 글에서는 프로그램의 실행 흐름을 제어하는 핵심적인 방법들을 배웠습니다.
if
,elseif
,else
: 조건에 따라 다른 코드를 실행하여 프로그램이 지능적으로 판단하게 합니다.while
,repeat
,for
: 반복적인 작업을 자동화하여 효율성을 높입니다.break
: 필요할 때 루프를 탈출하여 흐름을 유연하게 제어합니다.
이러한 제어 구조를 자유자재로 활용하면, 단순히 순서대로만 실행되는 코드를 넘어 다양한 상황에 동적으로 반응하는 강력한 프로그램을 만들 수 있습니다.