웹과 프론트엔드의 절대 강자 자바스크립트(JavaScript)와, 게임 엔진 및 임베디드 스크립트의 감초 루아(Lua)는 닮은 듯하면서도 완전히 다른 매력을 가진 멀티 패러다임 언어입니다.
두 언어의 철학, 문법, 데이터 구조, 비동기 메커니즘까지 벨로그 독자분들을 위해 모든 차이점을 세부적인 코드 예시와 함께 파헤쳐 봅니다.
| 비교 항목 | 자바스크립트 (JavaScript) | 루아 (Lua) |
|---|---|---|
| 탄생 목적 | 웹 브라우저 내 동적 제어 및 상호작용 | C/C++ 프로그램에 쉽게 내장(Embedded)할 수 있는 가벼운 스크립트 엔진 |
| 주요 사용처 | 웹 프론트엔드/백엔드(Node.js), 앱 개발(RN) | 게임 개발(로블록스, 월드오브워크래프트), 임베디드, IoT |
| 엔진 크기 | V8 엔진 기준 수십 MB 이상 (무겁고 복잡함) | 순수 C 언어로 작성되어 수백 KB 수준 (극도로 가볍고 빠름) |
두 언어는 코드 표기법(Syntax) 스타일에서 확연한 차이를 보입니다. 자바스크립트는 C-Style(중괄호)을, 루아는 Ada/Pascal-Style(텍스트 키워드)을 따릅니다.
{}로 블록을 구분하며, 주석은 // 또는 /* */를 사용합니다. 문장 끝에 세미콜론 ;을 붙이는 것이 관례입니다.then, do로 블록을 시작하고 end로 블록을 닫습니다. 주석은 -- 또는 --[[ --]]를 사용합니다. 세미콜론 ;은 완전히 선택 사항이며 거의 쓰지 않습니다.// [JavaScript] 조건문 예시
if (score >= 90) {
console.log("A 학점");
} else {
console.log("B 학점");
}
-- [Lua] 조건문 예시
if score >= 90 then
print("A 학점")
else
print("B 학점")
end
let, const를 사용해 깔끔한 블록 스코프를 만듭니다.local 키워드를 반드시 명시해야 합니다.// [JavaScript] 변수 스코프
function test() {
let localVar = "이것은 지역 변수";
const constantVar = "이것은 상수";
}
-- [Lua] 변수 스코프
function test()
local localVar = "이것은 지역 변수"
globalVar = "키워드가 없으므로 전역 변수가 됨 (주의!)"
end
개발자들 사이에서 가장 유명한 차이점입니다.
0부터 시작합니다.1부터 시작합니다.// [JavaScript] 인덱싱
const arr = ["사과", "바나나"];
console.log(arr[0]); // 출력: 사과
-- [Lua] 인덱싱
local arr = {"사과", "바나나"}
print(arr[1]) -- 출력: 사과 (1부터 시작!)
[]과 객체 {}를 명확히 구분합니다.{}이라는 단 하나의 데이터 구조만 존재합니다. 테이블을 순서대로 쓰면 배열이 되고, 키-값 쌍으로 쓰면 딕셔너리/객체가 됩니다.// [JavaScript] 배열과 객체 분리
let userArray = ["Minjo", 25];
let userObject = { name: "Minjo", age: 25 };
-- [Lua] 모든 것은 테이블로 해결
local userArray = {"Minjo", 25} -- 리스트 스타일 테이블
local userObject = { name = "Minjo", age = 25 } -- 딕셔너리 스타일 테이블
null과 정의되지 않음을 뜻하는 undefined가 분리되어 있습니다.nil 하나만 존재합니다. 테이블에서 특정 키에 nil을 대입하면 해당 데이터가 완전히 삭제되는 독특한 특성이 있습니다.// [JavaScript] 데이터 빈 값 처리
let data = null;
let profile = { name: "Minjo" };
profile.name = null; // 값은 여전히 key로 남아있음
-- [Lua] nil 대입을 통한 요소 삭제
local profile = { name = "Minjo", age = 25 }
profile.age = nil -- age 키 자체가 테이블에서 완전히 삭제됨
두 언어 모두 클래스 기반 언어(Java, C++ 등)가 아니며, 프로토타입과 메타 구조를 활용해 OOP를 흉내 냅니다.
class, constructor, extends 키워드를 도입하여 직관적인 클래스 상속 문법을 제공합니다.__index 메타메소드를 활용해 개발자가 직접 상속 구조를 바닥부터 구현해야 합니다.// [JavaScript] 현대적인 클래스 상속
class Animal {
constructor(name) { this.name = name; }
speak() { console.log(this.name + "가 소리를 냅니다."); }
}
class Dog extends Animal {}
-- [Lua] 메타테이블을 활용한 프로토타입 상속 직접 구현
Animal = {}
function Animal:new(name)
local obj = { name = name }
setmetatable(obj, { __index = self }) -- 상속 구조 연결
return obj
end
function Animal:speak() print(self.name .. "가 소리를 냅니다.") end
Dog = Animal:new() -- 상속 효과
Promise, async/await를 통해 비동기 Non-blocking I/O 처리가 핵심 강점입니다.coroutine.yield)시키고, 필요할 때 다시 재개(coroutine.resume)하는 방식으로 스레드 제어권을 개발자가 동기적으로 직접 주고받습니다.// [JavaScript] Promise 기반 비동기 처리
async function fetchData() {
let response = await fetch('https://api.example.com');
let data = await response.json();
console.log(data);
}
-- [Lua] 코루틴을 이용한 상태 일시 정지 및 재개
local co = coroutine.create(function()
print("코루틴 시작")
coroutine.yield() -- 중간에 제어권 반납하고 멈춤
print("코루틴 재개됨")
end)
coroutine.resume(co) -- "코루틴 시작" 출력 후 대기
coroutine.resume(co) -- "코루틴 재개됨" 출력
| 특징 | 자바스크립트 (JavaScript) | 루아 (Lua) |
|---|---|---|
| 문법 스타일 | C 스타일 ({}, //, ;) | Ada/Pascal 스타일 (end, --) |
| 배열 인덱스 | 0번부터 시작 | 1번부터 시작 |
| 기본 변수 스코프 | let, const (블록 스코프 선언 필요) | 키워드 없으면 전역(Global), local 선언 필수 |
| 대표 데이터 구조 | Array [], Object {} 분리 | 오직 Table {}로 통합 관리 |
| 비어있는 값 | null 및 undefined | nil |
| 동시성 처리 | 이벤트 루프, Promise, async/await | 코루틴 (Coroutine) 체계 |
| 클래스 상속 | class, extends 문법 내장 | 메타테이블(metatable)로 직접 구현 |
자바스크립트는 거대한 웹 생태계와 강력한 비동기 처리를 위해 엔진 자체가 거대해지고 고도화된 언어라면, 루아는 메인 프로그램(C/C++)을 보조하기 위해 불필요한 기능을 전부 덜어내고 극도의 가벼움과 커스텀 가능성을 추구한 언어입니다.
자바스크립트에 익숙한 프론트엔드 개발자가 루아(예: 로블록스 개발 등)를 접할 때는 1번 인덱스 시작과 local 키워드 생략 시 전역 변수가 되는 점만 주의하면 빠르게 적응하실 수 있습니다!