메이플스토리 월드 루아 기초

# 학습 과정 소개

메이플스토리 월드에서는 루아라는 언어를 사용하여 스크립트를 작성합니다. 이번 시간에는 루아의 기본 사용법과 메이플스토리 월드에서 사용하는 예제를 함께 살펴보겠습니다.

# 변수

변수란 데이터를 저장하는 메모리 공간, 값을 담아두는 그릇입니다.

## 변수의 범위

루아에서 사용하는 변수는 아래의 두 가지로 나뉩니다.

[{"변수":"전역(global) 변수","설명":"어느 곳이든 접근 가능한 변수로 아무 선언 없이 사용하면 전역 변수입니다. 단, 메이플스토리 월드에서는 전역 변수 사용을 권장하지 않습니다. 전역 변수처럼 사용하고 싶은 값이 있다면 스크립트에서 [프로퍼티](\/docs\/?postId=205)를 사용해 봅시다."},{"변수":"지역(local) 변수","설명":"같은 함수 또는 같은 구문 내에서만 접근 가능한 변수입니다.그 변수가 정의된 범위(scope)에서만 유효하며, 해당 범위의 실행이 끝나면 파괴됩니다."}]

  
[png](1671159060417acd3c899fc994089b6179d65757f711a) 위의 그림에 나와있듯이, **Property a**는 스크립트 전체에서 참조할 수 있습니다. **지역 변수 b**는 **B 영역**에서 유효하며, **지역 변수 c**는 **C 영역**에서만 유효하고, 해당 범위의 실행이 끝나면 파괴됩니다.   
예제를 통해 변수의 범위를 이해해 봅시다.   
1\. 먼저 메이커에서 **LuaTest**라는 새 스크립트 컴포넌트를 생성하고 **Hierarchy - common**에 **LuaTest** 컴포넌트를 추가합니다.   
2\. 아래와 같이 프로퍼티를 추가합니다. ```lua @Component script TestPropertySynchronizer extends Component @Sync property integer testP = 0 end ```   
3\. `OnBeginPlay()`, `testFunction()` 함수를 추가한 뒤 아래와 같이 입력해 봅시다. 원래 루아 문법에서는 출력할 때 **print**라는 명령을 사용하지만 메이플스토리 월드에서는 이것을 가공한 `log()` 함수를 사용하므로 앞으로의 예제에서도 `log()` 함수를 활용하겠습니다.   
아래와 같이 입력하고  **[시작]** 버튼을 눌러 콘솔 창에 **log**를 출력해 봅시다. 주석의 값이 각각 출력되는 것을 확인할 수 있습니다. ```lua @Component script BasicFeatureDemo extends Component @Sync property integer testP = 0 
    
    
    @ExecSpace("ServerOnly")
    method void OnBeginPlay()
    log(self.testP) -- 0
    self.testP = self.testP + 100
    log(self.testP) -- 100
    
    -- OnBeginPlay() 함수 내에서 유효한 지역 변수 a를 정의합니다.
    local a = "A"
    log(a) -- A
    
    if true then
    	-- 지역 변수 a의 값을 변경합니다.
    	a = 1
    
    	-- 조건문 내에서만 유효한 지역 변수 b를 정의합니다.
    	local b = "B"
    	log(b) -- B
    end
    
    log(a) -- 1
    
    --[[조건문 범위에서만 유효했던 지역 변수 b는 파괴되었으므로
    함수 범위에서 b 값은 nil입니다.]]
    log(b) -- nil
    
    -- testFunction()을 호출합니다.
    self:testFunction()
    end
    
    method void testFunction()
    -- Property에서 정의한 testP는 스크립트 전체에서 접근할 수 있습니다.
    log(self.testP) -- 100
    
    --[[OnBeginPlay()에서 유효했던 지역 변수 a는 파괴되었으므로
    여기에서 a 값은 nil입니다.]]
    log(a) -- nil
    end
    

end
    
    
    ## 변수 유형
    루아의 변수는 내부적으로 유형이 존재하기는 하지만 변수를 생성할 때 그 유형을 명시하지는 않습니다. 변수에 들어가는 값에 따라 그 유형이 정해집니다.
    
    | 변수 유형 | 설명 |
    | --- | --- |
    | nil | 값이 없음을 뜻합니다.   
    논리 연산에서 nil은 거짓(false)이고 전역 변수 및 테이블 키에서의 nil은 버려집니다. |
    | boolean | true와 false 값만 갖습니다.   
    0, 1의 수치로 변환되지 않습니다. |
    | number | 64비트 실수입니다. |
    | integer | 64비트 정수입니다. |
    | string | 문자열입니다.   
     큰따옴표(") 또는 작은따옴표(')로 감싸서 사용합니다. |
    | table | 복합 자료형입니다.   
    배열(Array) 형태와 사전(Dictionary) 형태로 모두 사용할 수 있습니다. |
    
    type() 함수로 변수의 유형을 확인할 수 있습니다.
    예를 들어 아래와 같이 입력하고 **log**를 출력하면 주석의 값이 각각 출력됩니다.
    
    

@Component script TypeDemonstrator extends Component @ExecSpace("ServerOnly") method void OnBeginPlay() local a = 1 log(type(a)) -- number
    
    
        
        a = 1234.5678
        log(type(a)) -- number
        
        a = "hello"
        log(type(a)) -- string
        
        a = (0 > 10)
        log(type(a)) -- boolean
        
        a= nil
        log(type(a)) -- nil
        
        a = {}
        log(type(a)) -- table
        
        a = {"Lua", "Test"}
        log(type(a)) -- table
    end
    

end
    
    
    메이플스토리 월드에서는 위의 유형 외에도 별도의 데이터 타입을 제공합니다. [프로퍼티](/docs/?postId=205) 가이드의 **프로퍼티 타입** 항목에서 자세한 내용을 확인할 수 있습니다.
    
    # 테이블
    
    루아에서는 배열(Array)과 사전(Dictionary) 형태 모두 테이블입니다.
    여러 개의 데이터를 다룰 때 보통 테이블을 활용하며 **{ }** 형태로 선언합니다. 
    

@Component script ServerInitializer extends Component @ExecSpace("ServerOnly") method void OnBeginPlay() local table = {} end end
    
    
    ## 배열(Array)
    배열은 루아에서 상당히 많이 활용되며, 데이터를 모아서 저장하는데 유용합니다.
    
    ### 배열 만들기
    예를 들어 아래의 형태로 만듭니다.
    

@Component script TestDataInitializer extends Component @ExecSpace("ServerOnly") method void OnBeginPlay() local testArray = {"A string", 1.234, self.Enable} end end
    
    
    ### 값 읽기
    배열은 인덱스[no]로 접근할 수 있습니다.
    대부분의 프로그래밍 언어에서는 첫 번째 인덱스로 **0**을 사용하는데 루아에서는 **1**을 사용합니다.
    

@Component script ArrayExample extends Component @ExecSpace("ServerOnly") method void OnBeginPlay() local testArray = {"A string", 1.234, self.Enable} log(testArray[1]) -- A string log(testArray[2]) -- 1.234 log(testArray[3]) -- true end end
    
    
    ### 값 작성하기
    배열에 값을 작성하거나 변경하려면 인덱스[no]로 접근하여 값을 입력합니다.
    

@Component script ArrayManipulation extends Component @ExecSpace("ServerOnly") method void OnBeginPlay() local testArray = {11, 22, 33}
    
    
        
        testArray[2] = "bb"
        testArray[4] = "44"
        
        log(testArray[2]) -- bb
        log(testArray[3]) -- 33
        log(testArray[4]) -- 44
    end
    

end
    
    
    ### 값 추가하기
    배열에 값을 추가하는 두 가지 방법을 소개합니다.
    * `table.insert()` 함수를 활용합니다.
    * `array[#array+1]` 문법을 활용합니다.
    
    

@Component script ArrayManipulationDemo extends Component @ExecSpace("ServerOnly") method void OnBeginPlay() local testArray = {"A", 1.234}
    
    
        
        table.insert(testArray, "C")
        testArray[#testArray+1] = "D"
        
        log(testArray[3]) -- C
        log(testArray[4]) -- D
    end
    

end
    
    
      
    
    배열의 중간에 값을 추가하려면 `table.insert()` 함수의 두 번째 인수에 추가하려는 인덱스 값을 적습니다.
    

@Component script TableInsertDemo extends Component @ExecSpace("ServerOnly") method void OnBeginPlay() local testArray = {"A", "B"}
    
    
        
        -- 2번 인덱스에 "and"를 추가
        table.insert(testArray, 2, "and")
        
        log(testArray[1]) -- A
        log(testArray[2]) -- and
        log(testArray[3]) -- B
    end
    

end
    
    
    ### 값 제거하기
    배열에서 값을 제거할 때는 `table.remove()` 함수를 사용합니다.
    

@Component script FirstElementRemover extends Component @ExecSpace("ServerOnly") method void OnBeginPlay() local array = {11, 22, 33, 44, 55}
    
    
        
        -- 1번 인덱스를 제거
        table.remove(array, 1)
        log(array[1]) -- 22
    end
    

end
    
    
      
    
    > **더 알아보기**
    > 스크립트 에디터에서 테이블에서 활용할 수 있는 다양한 함수들을 확인할 수 있습니다.
    > [png](16703984668191d7f941283f84d42b1b97146d6773bce)
    
    ## 사전(Dictionary)
    사전은 **key - value** 형태의 테이블입니다. 자료 구조에서 데이터를 빠르게 검색하기 위해 주로 사용합니다.
    
    ### 사전 만들기
    사전을 만들 때는 `key = value` 형태로 정의하고 콤마(,)로 구분합니다.
    

@Component script InitialDataSetup extends Component @ExecSpace("ServerOnly") method void OnBeginPlay() local myDictionary = {a = "myNumber", myNumber = 5, myString = "TTT", myBoolean = true} end end
    
    
    ### 값 읽기
    사전은 아래와 같은 형태로 읽습니다.
    

@Component script DictionaryDataDemo extends Component @ExecSpace("ServerOnly") method void OnBeginPlay() local myDictionary = {a = "myNumber", myNumber = 5, myString = "TTT", myBoolean = true}
    
    
        
        log(myDictionary.myNumber) -- 5
        log(myDictionary.myString) -- TTT
        log(myDictionary["myBoolean"]) -- true
    end
    

end
    
    
    ### 값 작성하기
    사전에 값을 정의하거나 다시 쓸 때도 **Key**를 활용합니다.
    

@Component script DictionaryUpdater extends Component @ExecSpace("ServerOnly") method void OnBeginPlay() local myDictionary = {name = "Tom", age = 20}
    
    
        
        -- 값 변경
        myDictionary.name = "Katy"
        myDictionary.age = 25
        
        -- Key - Value 추가
        myDictionary.favoriteGame = "MapleStory Worlds"
        
        log(myDictionary.name) -- Katy
        log(myDictionary.age) -- 25
        log(myDictionary.favoriteGame) -- MapleStory Worlds
    end
    

end
    
    
    ### Key - Value 삭제하기
    **Key - Value**를 삭제하려면 **Key**의 값을 **nil**로 설정합니다.
    

@Component script DictionaryOperations extends Component @ExecSpace("ServerOnly") method void OnBeginPlay() local myDictionary = {name = "Tom", age = 30, favoriteGame = "MapleStory Worlds", job = "Programmer"}
    
    
        
        -- Key - Value 삭제
        myDictionary.job = nil
        
        -- myDictionary 전체를 순회하며 key, value를 출력
        for key, value in pairs(myDictionary) do
            log(key, value)
        end
        
        --[[결과 :
        age 30
        name Tom
        favoriteGame MapleStory Worlds
        ]]
    end
    

end
    
    
    > **더 알아보기**
    > 위의 예제에서 활용한 for 문에 대해서는 [메이플스토리 월드 루아 구문](/docs?postId=944) 가이드의 **for 문** 부분을 참고합시다.
    
    ## 테이블 참조
    테이블을 새 변수에 저장하면 루아에서는 해당 테이블의 복사본을 만들지 않습니다. 대신 변수는 원본 테이블을 참조합니다.
    

@Component script ReferenceDemo extends Component @ExecSpace("ServerOnly") method void OnBeginPlay() local original = {10, 100, 1000} local reference = original
    
    
        
        log(reference[1], reference[2], reference[3]) -- 10, 100, 1000
        
        -- 원본 값 수정
        original[1] = "A"
        original[2] = "B"
        
        log(reference[1], reference[2], reference[3]) -- A, B, 1000
    end
    

end
    
    
    # 연산자
    
    루아에서 사용할 수 있는 연산자입니다.
    
    ## 산술 연산자
    산술 연산을 할 때 사용하는 연산자입니다.
    
    | 연산자 | 설명 |
    | --- | --- |
    | `+` | 더하기 |
    | `-` | 빼기 |
    | `*` | 곱하기 |
    | `/` | 나누기 |
    | `//` | 나눈 후 몫만 취함 |
    | `%` | 나눈 후 나머지만 취함 |
    | `^` | 지수 |
    
    예를 들어 아래와 같이 입력하고 **log**를 출력하면 주석의 값이 출력됩니다.
    

@Component script ArithmeticDemo extends Component @ExecSpace("ServerOnly") method void OnBeginPlay() log(1 + 1) -- 2 log(1 - 1) -- 0 log(5 * 5) -- 25 log(13 / 5) -- 2.6 log(13 // 5) -- 2 log(13 % 5) -- 3 log(2 ^ 4) -- 16.0 end end
    
    
    ## 관계 연산자
    관계를 판단할 때 사용하는 연산자입니다. 결과는 boolean입니다.
    
    | 연산자 | 설명 |
    | --- | --- |
    | `=` | 선언 |
    | `==` | 같다 |
    | `~=` | 다르다 |
    | `>` | 크다 |
    | `<` | 작다 |
    | `>=` | 크거나 같다 |
    | `<=` | 작거나 같다 |
    
    예를 들어 아래와 같이 입력하고 **log**를 출력하면 주석의 값이 출력됩니다.
    

@Component script RelationalOperatorDemo extends Component @ExecSpace("ServerOnly") method void OnBeginPlay() local a = 1 local b = 2 log(a == b) -- false log(a ~= b) -- true log(a > b) -- false log(a < b) -- true log(a >= b) -- false log(a <= b) -- true end end
    
    
    ## 논리 연산자
    논리 연산자는 참 또는 거짓을 반환합니다. 인수가 거짓이 아니면, 그리고 0이 아니면 참으로 반환합니다.
    
    | 연산자 | 설명 |
    | --- | --- |
    | `and` | A and B. A와 B가 모두 true이어야 true. |
    | `or` | A or B. A 또는 B가 true이어야 true |
    | `not` | true 면 false, false 면 true |
    
    ## 기타 연산자
    그밖에 유용하게 사용할 수 있는 연산자입니다.
    
    | 연산자 | 설명 |
    | --- | --- |
    | `#` | 배열의 길이 |
    | `..` | 문자열 합치기|
    
    예를 들어 아래와 같이 입력하고 **log**를 출력하면 주석의 값이 출력됩니다.
    

@Component script GreetingMessageLogger extends Component @ExecSpace("ServerOnly") method void OnBeginPlay() local a = {"HELLO", "MapleStory Worlds"}
    
    
        
        log(#a) -- 2
        log(a[1].."! "..a[2]) -- HELLO! MapleStory Worlds
    end
    

end
    
    
    # 함수
    
    함수는 명령으로 여러 번 실행할 수 있는 코드 블록입니다. 이벤트에 연결하거나 콜백으로 할당할 수 있습니다. 더 자세한 내용은 [함수](/docs/?postId=172) 가이드를 참고합니다.
    
    # 주석과 Annotation
    
    주석은 아래와 같이 표시합니다.
    
    | 주석 | 설명 |
    | --- | --- |
    | `--` | 한 줄 주석 |
    | `--[[]]` | 다중 라인 주석 |
    | `---@` | Annotation은 코드에 추가하여 사용하는 일종의 메타데이터입니다.   
    더 자세한 내용은 [Annotation](/docs/?postId=824) 가이드를 참고합니다. |
    
    # 마무리
    
    루아의 기본 사용법과 예제를 살펴보았습니다. 이어서 루아로 스크립트를 작성할 때 자주 사용하는 구문의 사용법을 익혀봅시다. [메이플스토리 월드 루아 구문](/docs?postId=944)에서 관련 내용을 확인할 수 있습니다.