나무모에 미러 (일반/밝은 화면)
최근 수정 시각 : 2024-04-14 00:48:53

Lua


프로그래밍 사이트 선정 프로그래밍 언어 순위 목록
{{{#!wiki style="margin: 0 -10px -5px; word-break: keep-all"
{{{#!wiki style="display: inline-block; margin: 0 0 -5px; min-width: 25%"
{{{#!folding ⠀[ IEEE Spectrum 2023 ]⠀
{{{#!wiki style="margin:-6px -1px -10px"
<rowcolor=#fff> 스펙트럼 부문 상위 10개 프로그래밍 언어 직업 부문 상위 10개 프로그래밍 언어
1 Python 1 SQL
2 Java 2 Python
3 C++ 3 Java
4 C 4 JavaScript
5 JavaScript 5 C++
6 C# 6 C#
7 SQL 7 C
8 Go 8 HTML
9 TypeScript 9 Shell
10 HTML 10 SAS
}}}}}}}}}
⠀[ Stack Overflow 2023 ]⠀
||<tablewidth=100%><width=2000><-4><bgcolor=#FFA500><tablebgcolor=#fff,#222> 2023년 Stackoverflow 설문조사 기준 인기 상위 25개 프로그래밍 언어 ||
1 JavaScript 14 Rust
2 HTML, CSS 15 Kotlin
3 Python 16 Ruby
4 SQL 17 Lua
5 TypeScript 18 Dart
6 Bash 19 어셈블리어
7 Java 20 Swift
8 C# 21 R
9 C++ 22 Visual Basic
10 C 23 MATLAB
11 PHP 24 VBA
12 PowerShell 25 Groovy
13 Go
⠀[ TIOBE 2024 ]⠀
||<tablewidth=100%><width=2000><-4><bgcolor=deepskyblue><tablebgcolor=#fff,#222> 2024년 2월 기준 검색어 점유율 상위 20개 프로그래밍 언어 ||
1 Python 11 Fortran
2 C 12 Delphi / Object Pascal
3 C++ 13 MATLAB
4 Java 14 Assembly language
5 C# 15 Scratch
6 JavaScript 16 Swift
7 SQL 17 Kotlin
8 Go 18 Rust
9 Visual Basic 19 COBOL
10 PHP 20 Ruby
{{{#!wiki style="margin:0 -10px -5px; min-height: 26px"
{{{#!folding [ 21위 ~ 50위 펼치기 · 접기 ]
{{{#!wiki style="margin: -6px -1px -10px"
21 R 36 Transact-SQL
22 SAS 37 VBScript
23 Classic Visual Basic 38 Haskell
24 Prolog 39 TypeScript
25 Ada 40 Logo
26 Perl 41 Bash
27 (Visual) FoxPro 42 Scheme
28 Dart 43 Solidity
29 D 44 ABAP
30 F# 45 ML
31 Scala 46 X++
32 Objective-C 47 PL/SQL
33 Lua 48 GAMS
34 Julia 49 PowerShell
35 LISP 50 RPG
}}}}}}}}} ||
⠀[ PYPL 2024 ]⠀
||<tablewidth=100%><width=2000><-4><bgcolor=green><tablebgcolor=#fff,#222> 2024년 2월 기준 검색어 점유율 상위 20개 프로그래밍 언어 ||
1 Python 11 Rust
2 Java 12 Go
3 JavaScript 13 Kotlin
4 C/C++ 14 MATLAB
5 C# 15 Ada
6 R 16 Dart
7 PHP 17 Ruby
8 TypeScript 18 PowerShell
9 Swift 19 VBA
10 Objective-C 20 Lua
}}} ||
프로그래밍 언어 목록 · 분류 · 문법

루아
Lua
파일:Lua 로고.svg
<colbgcolor=#fff,#1f2023><colcolor=#000080> 최초 공개 1993년
개발 호베르투 예루잘링스키 외 2명
안정화 최신 버전 5.4.6 - 2024년 3월 2일
파일:홈페이지 아이콘.svg

1. 개요2. 언어적 특징
2.1. 가벼움2.2. 문법적 특징2.3. 테이블2.4. 함수형 프로그래밍
3. 문법
3.1. 변수3.2. 테이블
4. 파편화5. 파생 언어6. 다른 언어들과 비교
6.1. Python과의 비교6.2. JavaScript와의 비교
7. 용도
7.1. 실제 사용 예
7.1.1. 게임7.1.2. 일반 응용 소프트웨어7.1.3. 기타

[clearfix]

1. 개요

#!syntax lua
print("Hello, world!")

또는
#!syntax lua
io.write("Hello, world!")


홈페이지

1993년에 개발된 프로그래밍 언어. 브라질 리우데자네이루의 교황청대학교에서 호베르투 예루잘링스키[1] 및 2명이 공동제작했으며 이름도 을 의미하는 포르투갈어 단어에서 따왔다. 스크립트 언어를 하나의 목적으로 가지고 있기 때문에 굉장히 작고 가벼운 인터프리터형 언어이다. 현재 안정버전은 5.4이다.

태생 자체가 C/C++ 프로그램 내부에 포함(embed)시키기 매우 쉬운 깔끔한 문법의 가벼운 스크립트 언어를 목표로 개발되었다. 교황청대학교 컴퓨터 그래픽 기술 연구소(Tecgraf)에서 내부적으로 개발해서 사용하던 기존의 데이터 처리용 스크립팅 언어 SOL과 DEL의 한계를 극복할 더 강력한 언어가 요구되었다고 한다.[2]

2. 언어적 특징

2.1. 가벼움

인터프리터(또는 후술한 JIT 컴파일러)의 용량이 일백 수십KB[3] 정도로 작고 굉장히 빠르다. 그 흔한 정수도 없을 정도로[4] 굉장히 적은 수의 데이터형만을 지원하긴 하지만 그만큼 가볍다. 다양한 프로그램에 쉽게 붙일 수 있는 이유도 용량과 속도의 부담이 적기 때문. 그러면서도 다양한 패러다임을 가지고 있는데, 절차적으로도, 객체지향적으로도, 함수형으로도 이용할 수 있다.

2.2. 문법적 특징

언어의 문법이 굉장히 단순한 편이다. 다만, C언어 스타일의 언어들과 비교했을 때 다른 점이 많다는 것이 특징이다.

2.3. 테이블

Lua에서는 테이블은 우리가 흔히 아는 테이블과는 달리 배열과 딕셔너리 기능을 기본적으로 모두 할 수 있다.
#!syntax lua
local Table = {2, 5, "s", true, false, a = 2, {2,4,f = 2}, "g"}

위와 같이 다른 언어의 배열과는 다르게 다양한 자료형을 키로 사용가능한데, 이것을 가지고 단순한 구조체, 배열 뿐만 아니라 객체, 클래스, 인터페이스 등을 구현해낼 수 있다. 사실 Lua의 테이블은 단순히 저장하는 것이 아니라 메타 테이블과 같이 써서 테이블에 기능을 붙일 수 있기 때문이다. 그래서 Lua를 잘 다루려면 테이블과 메타 테이블을 잘 다룰 수 있어야 한다.

2.4. 함수형 프로그래밍

Lua도 일단은 함수형 프로그래밍이 어느 정도 된다. 함수를 익명함수로 생성할 수도 있고 전달할 수도 있다(JavaScript에서 지원하는 정도와 비슷하다). 그리고 사실 파일로 저장해서 불러오는 스크립트 자체가 함수다. 대신 성능을 위해서 스택의 크기가 고정되어 있기 때문에 어떤 함수든지 지역 변수를 255개 이상 만들 수가 없다. 대신 전역 범위에 저장하는 _G라는 테이블이 존재한다.

클로저와 익명함수를 지원한다.[7]

다만 함수형 프로그래밍에서 흔히 쓰이는 map, filter, reduce 등의 함수가 기본적으로 제공되지는 않는다.

3. 문법

3.1. 변수

전역 변수를 만들 때는 다른 프로그래밍 언어들과 비슷하게 아래와 같이 만든다.
#!syntax lua a = 2
하지만 지역 변수는 아래와 같이 앞에 local을 붙여 만든다.
#!syntax lua local a = 2
대부분의 Lua를 하는 사람들은 변수 생성 시 local을 붙이고, local을 붙이는 것이 문화 같은 느낌이다.

3.2. 테이블

Lua에서의 테이블은 배열 혹은 딕셔너리와 비슷하다고 생각하면 되는데, 아래와 같이 테이블을 선언할 수 있다.
#!syntax lua local t = {2, "a", true, a = 2, b = {2,5}}
위의 테이블에서 키(key)가 정해진 원소들은 t["a"]t.a와 같이 사용할 수 있다. 그 외에 키가 배정되지 않은 원소들은 1부터 차례대로 인덱스가 매겨져서, t[1]=2, t[2]="a", t[3]=true가 된다.
테이블의 길이를 구할 때는 테이블 변수 앞에 연산자 #을 붙인다.
아래를 실행하면 테이블 t의 길이 3이 출력될 것이다.
#!syntax lua
local t = {2,3,4}
print(#t) -- #t = t의 길이

참고로 Lua에서 그냥 테이블을 print(t)와 같이 출력하면 테이블의 주소값이 나온다.

Lua의 for-loop은 아래 예제와 같이 사용한다.
#!syntax lua
local t = {1,2,4,5}
for i=1, #t do
    print(t[i])
end

변수 i가 1부터 #t까지 증가하며 테이블 t의 원소들을 인덱스 순서대로 출력한다.
아래 예제는 pairs() 함수를 이용한 Lua의 for...in 반복문이다.
#!syntax lua
local t = {10,20,40,50}
for i, v in pairs(t) do
    print("t[" .. i .. "]=" .. v) -- 문자열 합치기 연산자 '..'
end

위 코드를 실행하면 t[1]=10, t[2]=20, t[3]=40, t[4]=50가 순서대로 출력될 것이다. for...in 문에서 i는 인덱스, v는 현재 값을 의미한다.

Lua에는 메타 테이블(Metatable)이라는 것이 존재한다. 먼저 메타 메서드(Metamethod)라는 것을 알아야 하는데, 메타 메서드는 테이블에 어떤 행동이 있었을 때 발생되는 이벤트이다.

메타 테이블은 아래와 같이 설정할 수 있다.
#!syntax lua
local t = {}
local mt = {}
setmetatable(t, mt)

setmetatable()의 1번째 인자에 일반적으로 사용할 테이블을 넣고 2번째 인자에 우리가 메타 테이블로 설정할 테이블로 넣으면 된다.
메타 메서드에는 여러 가지가 존재하는데, 테이블끼리의 사칙연산, 테이블의 여러 함수를 사용, 테이블 강화, 테이블 상수화, 가비지 컬렉터, 테이블에 값이 없을 때 메타 테이블에서 가져오는 등 테이블의 기능 확장을 용이하게 한다. 이러한 메타 메서드는 아예 식별자로 등록되어있고, C++에서의 사용자 operator 정의와 비슷한 느낌이라고 볼 수 있다.
메타 메서드 중 두 가지만 소개하자면,
첫 번째로 __index는 테이블의 키에 해당하는 값이 없을 때[8] 실행된다. 아래는 __index에 대한 예제 코드이다.
#!syntax lua
local t = setmetatable({}, {
    __index = function(self)
        return "없네요"
    end
})
print(t.aff)

위 코드는 사용자가 메타 테이블 t에서 없는 키 aff에 접근했을 때 메타 메서드 __index"없네요"를 반환하는 코드이다.
그래서 없는 키에 접근했을 때 원래는 nil을 반환해야 하는 것이 디폴트이지만, 현재 코드에서는 "없네요"가 반환값으로 정의되어 있으므로 t.aff에 접근하면 값이 "없네요"가 된다.

두 번째로 __add는 두 테이블이 더해졌을 때 실행된다. 아래는 __add에 대한 예제코드이다.
#!syntax lua
local t1 = setmetatable({v = 5}, {
    __add = function(a,b)
        return a.v + b.v
    end
})
local t2 = {v = 1}
print(t1+t2)

위 코드에서 메타 메서드 _addt1 테이블과 또 다른 테이블이 + 연산자로 연결될 때 각 테이블의 v값을 더해 반환하는 메서드로 정의되어있다.
이렇게 메타 테이블로 수많은 것들을 만들 수 있는데 좀 더 활용하거나 다른 메서드를 쓰면 더 짧고 더 좋은 코드를 짤 수 있다.

4. 파편화

중요한 Lua 커뮤니티 파편화가 시작되었다. Lua 5.3버전이 64비트 부동소수점 타입[9]을 명확히 지원하기 위해서 정수형 타입을 도입한 것이 기존의 Lua코드와 호환성 문제를 일으키게 된 것이다.[10] 게다가 LuaJIT을 개발하고 사실상 혼자 유지보수하던 Mike Pall이 앞의 정수형 문제와 기타 몇 가지 이유를 더 들어 5.3 버전을 공개적으로 크게 비판하고 LuaJIT은 Lua 5.1까지만 지원하고 자신은 더이상 개발에 관여하지 않겠다고 선언해서 문제가 매우 복잡해졌다.[11]

때문에 LuaJIT에 의존해 성능 향상을 꾀하던 대다수의 Lua 라이브러리가 Lua 5.1까지만 지원하고 후속 개발이 진행되지 않는 사태에 이르렀다. 현재 Lua 커뮤니티는 순정 인터프리터로도 충분한 상황의 개발자와, LuaJIT과 기타 라이브러리가 꼭 필요한 개발자들로 양분되어버렸다. 파이썬이 파이썬2와 파이썬3로 나뉘어 파편화가 진행되었던 것과 비견된다.[12] Lua가 임베딩용 언어라는 특징과 맞물려 (파이썬의 경우보다도) 파편화가 더 고착화될 가능성도 있는데, 어차피 임베딩이 주 목적인 언어이므로 JIT가 지원되는 5.1만으로도 충분하다는 입장도 있다. 어차피 임베딩 환경에 의존하는 상황에서는 필요한 기능이 환경 자체에서 주어지므로 Lua 수준의 기능 추가는 불필요하며, 오히려 문법이 고정되어 버리는 편이 하위호환성에 더 낫다는 이유.#

4.1. LuaJIT

Lua의 JIT 컴파일러며, 여타 프로그래밍 언어의 JIT보다 더 우수한 성능을 보여준다. 주로 V8와 비교되는데, 자료구조 성능을 제외하면 전반적으로 Lua 쪽이 성능이 더 좋다. Python, Ruby와 비교해도 수십배 정도가 더 빠르다.

JavaScript와 Lua는 문법과 패러다임이 90% 이상 비슷한 사촌언어격이지만 JIT 성능의 구현 측면에 있어서는 JavaScript가 가진 문법 일부가 성능 향상에 약점으로 작용한다고 한다. 참조 또한 메모리 사용량에 있어서 LuaJIT이 더 나은 최적화를 보여주고 있다. 따라서 Node.js를 LuaJIT 기반으로 다시 작성한 Luvit이라는 프로젝트가 활성화되었다.

홈페이지에 따르면 인터프리터를 손수 어셈블리어로 작성했으며, 이미 상당한 수준의 최적화가 되어있다고 한다. Python의 JIT 컴파일러인 PyPy가 자기 자신으로 JIT을 구현하는 것과 대조되는 부분. Lua가 그나마 단순한 언어라 이런 일이 되는 듯하다.

또한, 안 그래도 손쉬운 C언어와의 인터페이스 작업은 LuaJIT의 FFI(Foreign Function Interface)를 이용하면 Low-Level C언어 함수들을 별다른 작업 없이 직접적으로 사용할 수 있다. 이 FFI 방식으로 인해 스크립트 - 네이티브 코드 간 호출규약을 맞추기 위한 별도의 작업이 사실상 필요가 없어지고, C 자료형을 직접 사용할 수 있게 되며 호출 성능은 네이티브에 견줄만큼 빨라지기 때문에, 일단 JIT을 사용하게 되면 기존 Lua 바인딩 코드를 사용할 일이 극히 적어진다. 이 FFI 방식은 이후 Python의 CFFI 라이브러리에 많은 영감을 주었다(Node.js의 node-ffi도 상당한 영향을 받은 것으로 추정된다).

네이티브에 견줄만큼 속도가 빠르고, 메모리 사용량이 매우 적기 때문에 최근 NGINX에 LuaJIT을 포함시켜서 커스터마이징을 한 OpenResty 웹 서버가 인기를 끌고 있다. CDN 서비스로 유명한 Cloudflare와 알렉사 Top 13 규모의 세계에서 가장 큰 C2C 상거래 서비스(지마켓/옥션을 생각하면 된다)인 타오바오에서 주-웹서버로 사용하고 있으며 두 회사의 개발자들이 OpenResty 개발을 주도하고 있다(단 Cloudflare의 CDN 서비스는 사실 NGINX에 LuaJIT으로 코드를 올려 커스터마이징한 서비스들이다. 그래서 타사와 달리 진정한 CDN 서비스가 아니라는 비평도 있다).

알파고로 유명한 구글 딥마인드가 알파고의 기반인 Q-Learning을 구현할 때 사용된 Torch 머신러닝 미들웨어도 LuaJIT으로 작성되어 있다(딥마인드 사의 구인공고는 그래서 C/C++와 Lua 스크립트가 필수역량으로 적혀있다).

5. 파생 언어

C/C++ 언어와 함께 사용하기 편하다는 확실한 장점으로 인해 여러 가지 파생 언어가 나와 있다.

이 외에도 다른 언어에서 Lua로 트랜스파일되는 언어/도구들도 존재한다.

6. 다른 언어들과 비교

6.1. Python과의 비교

파이썬과 자주 비교가 되는데, 두 언어의 초기 개발 목표의 차이가 현재의 두 언어가 갖는 거의 모든 차이의 원인이라고 볼 수 있다. 파이썬은 깨끗한 문법의 고급(high-level) 범용(general) 프로그래밍언어가 개발 목표였고 부수적으로 다른 언어와의 쉬운 접착(glue) 기능이 제공되는 반면에, Lua는 C/C++ 프로그램에 내포(embed)되는 것을 기본 사용례로 가정하고 개발되었고 부수적으로 고급(high-level) 범용(general) 프로그래밍 언어로도 사용할 수 있는 것이다. 즉, 인터프리트형 스크립트 언어라는 공통점을 제외하면 강조하고 있는 점이 거의 정반대이다. 그리고 파이썬이 접착(gluing)이 쉬운 언어이지 내포(embedding)가 쉬운 언어는 아니라는 점도 주목할 만하다.

따라서 파이썬 커뮤니티에서 잘 쓰이는 표현대로 '배터리가 포함된'[13] 파이썬은 어느정도 단독으로 프로그램을 만들 수 있는 환경인 반면, Lua는 기본중의 기본 기능만을 포함하고 있어 단독으로 응용프로그램을 만들려면 손에 꼽히는 외부 라이브러리[14]를 포함하고도 이것저것 직접 구현해야 하는 어려움이 있다. 너무 없어 불편하니 배터리가 포함된 LuaDist나 Lua for Windows같은 프로젝트도 있다.

물론 관점을 바꾸어서 C/C++ 프로그램에 내포할 때를 가정하면, 파이썬은 기본으로 import되는 라이브러리[15]가 많아 메모리 사용량이 큰데 비해 사실상 아무것도 없어 극도로 가볍고 빠른 것이 Lua의 장점이라고 하겠다.[16]

그리고 파이썬 커뮤니티에서도 Lua와 비교해서 embedding 기능쪽으로 부족함을 인지하고, 최근 영역 확장을 시도하고 있다. 파이썬이 스크립트용으로 내포된 유명한 프로그램으로는 3dx Max, Blender가 있다. 둘 다 그 자체로 덩치 큰 프로그램[17]

6.2. JavaScript와의 비교

자주 비교되는 파이썬보다는 오히려 JavaScript가 프로그램 언어 차원에서 Lua와 굉장히 유사한 면이 많다.[18] 그래서 JavaScript에 있는 것을 Lua로 옮기는 경우도 있는데 예로 Node.js를 Lua로 옮긴 Luvit등이 있다.

하지만 JavaScript가 웹 인터페이스 개발의 필수요소가 된 이후에 구글등의 대기업들이 큰 돈과 인력을 동원해서 JIT 컴파일러 개발 및 기타 라이브러리 개발에 힘을 쏟아부었기 때문에, 언어 자체의 유사성이 큰 것과는 별개로 두 언어의 인기도나 개발자 수등에서 이제 비교할 수 없을 정도로 큰 격차가 생긴 것도 사실이다.

유사한 두 언어가 웹 인터페이스에는 JavaScript, 게임에는 Lua라는 식으로 각자의 영역을 하나씩 차지하고 있는 셈인데, 2020년을 전후해서 JavaScript를 Lua처럼 게임용 스크립트 언어로 사용하려는 몇몇 시도들도 존재한다.영역 침범

7. 용도

7.1. 실제 사용 예

7.1.1. 게임

Lua가 쓰인 게임 목록

7.1.2. 일반 응용 소프트웨어

7.1.3. 기타


[1] Roberto Ierusalimschy. 1960년생으로 컴퓨터과학자이며 상단의 리우 교황청 대학과 스탠퍼드 대학교에서 부교수로 역임한 적이 있다. 위키백과에선 성씨를 이에루잘림스시(...)라고 표기하고 있다[2] 출처: The evolution of Lua[3] 상대적으로 덩치가 큰 LuaJIT조차 300KB 정도 된다.[4] 5.3버전에 정수가 추가되었다. 이때문에 Lua 커뮤니티 파편화가 진행중이다. 아래 참고.[5] Roblox Studio의 luau와 같이 복합 대입 연산자를 지원하는 경우에는 A += 1처럼 쓸 수 있다.[6] Roblox Studio에서는 continue가 존재한다.[7] 엄밀히 말하면 Lua에는 클로저만 존재하고, 나머지는 syntactic sugar.[8] 정확히는 Lua는 찾는 값이 없을 때 nil을 반환하기 때문에 'nil일 때'이다.[9] 요즘 C/C++의 double은 대개 IEEE754표준 64비트 부동소수점 타입.[10] 기본 숫자 타입은 여전히 number 뿐이다. math.type()을 통해서 서브 타입을 확인해야만 64비트 부동소수점 타입인 경우에는 double이라고 할 것이지 헷갈리게 float, 정수형인 경우에는 integer라고 구분되어 표시된다.[11] 이후에 사람들이 대체 maintainer를 공개모집했으나 적당한 사람을 찾는데 실패했다.[12] 2008년 파이썬3가 발표된 이후에, 파이썬 커뮤니티의 파편화가 성공적으로 봉합되기까지 10년 남짓한 긴 시간이 소요되었다.[13] 기본으로 포함된 라이브러리가 기능이 풍부해 다른 외부 모듈이 필요없다는 뜻.[14] 주로 LuaRocks에서 구할 수 있다.[15] embedding 상황에서는 잘 쓰이지 않는 것들도 기본 라이브러리에 많이 들어있다.[16] 파이썬 개발자가 작성한 다음의 논의를 참고. embedding이라는 분야만 한정했을 때 Lua가 더 직관적임을 설명하고 embedding 목적으로 파이썬을 꼭 써야 한다면 생각해볼 수 있는 대안을 제안하고 있다.[17] Lua를 직접 언급하며 파이썬도 이쪽으로 좀 더 잘 할 수 있지 않을까 논의하는 영상: The Future of Python[18] Lua는 깔끔한 문법의 JavaScript라는 댓글이 레딧 등 인터넷 게시판에 가끔 보일 정도.[19] 참고로 Roblox는 Lua 5.1 기반으로 만든 Luau를 사용 중이다.