콘솔에 테이블을 덤프하는 방법?


109

중첩 된 테이블 (n-deep)이 포함 된 테이블의 내용을 표시하는 데 문제가 있습니다. print성명이나 빠르고 더러운 것을 통해 std 또는 콘솔에 덤프하고 싶지만 방법을 알 수 없습니다. NSDictionarygdb를 사용하여 인쇄 할 때 얻을 수있는 대략적인 것을 찾고 있습니다.

답변:


56

테이블 직렬화에 대한 Lua Wiki를 자유롭게 찾아보십시오 . 콘솔에 테이블을 덤프하는 방법에 대한 여러 가지 방법을 나열합니다.

자신에게 가장 적합한 것을 선택하기 만하면됩니다. 이를 수행하는 방법에는 여러 가지가 있지만 일반적으로 Penlight의 방법을 사용합니다 .

> t = { a = { b = { c = "Hello world!", 1 }, 2, d = { 3 } } }
> require 'pl.pretty'.dump(t)
{
  a = {
    d = {
      3
    },
    b = {
      c = "Hello world!",
      1
    },
    2
  }
}

6
멍청하고 더 많은 초보자 질문 : pl.pretty와 같은 확장 프로그램을 설치하려면 어떻게해야합니까? 타르 볼을 풀고 HD에서 사물을 배치하기위한 이상적인 지점을 찾지 않고 보석 설치와 같은 작업을 수행 할 수 있다면 좋을 것입니다. 빠르고 고통없는 "이 방법"이 있습니까?
Cliff

1
Dah, 마지막 댓글을 게시하기 전에 홈페이지를 봤어야 했어요! 설치가 내가 원하는만큼 빠르거나 고통 스럽지는 않지만 나쁘지는 않습니다.
Cliff

penlight는 내가 찾고 있던 것에 빛을 비 춥니 다!
Cliff

7
@Cliff luarocks는 펜 라이트 설치하려면
방랑

101

이 질문이 이미 답변 된 것으로 표시된 것을 알고 있지만 여기에 내 라이브러리를 연결하겠습니다. inspect.lua라고하며 여기에서 찾을 수 있습니다.

https://github.com/kikito/inspect.lua

다른 파일에서 요구할 수있는 단일 파일입니다. Lua 값을 사람이 읽을 수있는 문자열로 변환하는 함수를 반환합니다.

local inspect = require('inspect')

print(inspect({1,2,3})) -- {1, 2, 3}
print(inspect({a=1,b=2})
-- {
--   a = 1
--   b = 2
-- }

하위 테이블을 적절하게 들여 쓰기하고 "재귀 테이블"(자신에 대한 참조를 포함하는 테이블)을 올바르게 처리하므로 무한 루프에 들어 가지 않습니다. 합리적인 방식으로 값을 정렬합니다. 또한 메타 테이블 정보를 인쇄합니다.

문안 인사!


Lua Wiki에 라이브러리를 추가해야 할 수도 있습니다 . 귀하의 라이브러리는 다른 라이브러리에서는 인쇄하지 않는 메타 테이블도 인쇄합니다.
Michal Kottman 2012

문제는 inspect.lua가 실제로 "직렬화"범주에 맞지 않는다는 것입니다. 반환하는 텍스트는 유효한 Lua 코드가 아닙니다. 디버깅 / 인간 읽기에 사용되어야합니다. 끝에 작은 링크를 추가 할 수 있다고 생각합니다.
kikito

1
위키에 inspect.lua를 추가했습니다.
kikito 2012

luarocks에 넣어주세요
해킹-R

3
@ Hack-R 그것은 luarocks에 있습니다 :luarocks install inspect
kikito

86

나는 이것이 유용하다는 것을 알았다. 재귀라면 중첩 된 테이블도 인쇄 할 수 있기 때문입니다. 출력에서 가장 예쁜 형식을 제공하지는 않지만 이러한 간단한 기능의 경우 디버깅을 이기기가 어렵습니다.

function dump(o)
   if type(o) == 'table' then
      local s = '{ '
      for k,v in pairs(o) do
         if type(k) ~= 'number' then k = '"'..k..'"' end
         s = s .. '['..k..'] = ' .. dump(v) .. ','
      end
      return s .. '} '
   else
      return tostring(o)
   end
end

예 :

local people = {
   {
      name = "Fred",
      address = "16 Long Street",
      phone = "123456"
   },

   {
      name = "Wilma",
      address = "16 Long Street",
      phone = "123456"
   },

   {
      name = "Barney",
      address = "17 Long Street",
      phone = "123457"
   }

}

print("People:", dump(people))

다음 출력을 생성합니다.

사람 : {[1] = {[ "address"] = 16 Long Street, [ "phone"] = 123456, [ "name"] = Fred,}, [2] = {[ "address"] = 16 Long Street , [ "phone"] = 123456, [ "name"] = Wilma,}, [3] = {[ "address"] = 17 Long Street, [ "phone"] = 123457, [ "name"] = Barney, },}


1
외부 라이브러리가 필요하지 않은 것을 공유하기에 좋습니다.
Julian Knight

정말 큰 테이블에서 함수가 stackoverflow 오류를 발생시킵니다
Herrgott

20

이것을 찾았습니다 :

-- Print contents of `tbl`, with indentation.
-- `indent` sets the initial level of indentation.
function tprint (tbl, indent)
  if not indent then indent = 0 end
  for k, v in pairs(tbl) do
    formatting = string.rep("  ", indent) .. k .. ": "
    if type(v) == "table" then
      print(formatting)
      tprint(v, indent+1)
    elseif type(v) == 'boolean' then
      print(formatting .. tostring(v))      
    else
      print(formatting .. v)
    end
  end
end

여기에서 https://gist.github.com/ripter/4270799

나에게 꽤 잘 작동합니다 ...


19

내가 본 대부분의 순수한 lua 인쇄 테이블 함수는 깊은 재귀에 문제가 있으며 너무 깊어지면 스택 오버플로를 일으키는 경향이 있습니다. 내가 작성한이 인쇄 테이블 함수에는이 문제가 없습니다. 또한 연결을 처리하는 방식으로 인해 정말 큰 테이블을 처리 할 수 ​​있어야합니다. 이 기능을 개인적으로 사용했을 때 약 1 초 만에 63k 줄을 출력했습니다.

출력은 또한 lua 구문을 유지하며 숫자, 부울, 문자열 및 테이블 데이터 유형 만 형식화 할 수 있도록 수정 된 경우 출력을 파일에 기록하여 스크립트를 쉽게 수정하여 간단한 영구 저장을 수행 할 수 있습니다.

function print_table(node)
    local cache, stack, output = {},{},{}
    local depth = 1
    local output_str = "{\n"

    while true do
        local size = 0
        for k,v in pairs(node) do
            size = size + 1
        end

        local cur_index = 1
        for k,v in pairs(node) do
            if (cache[node] == nil) or (cur_index >= cache[node]) then

                if (string.find(output_str,"}",output_str:len())) then
                    output_str = output_str .. ",\n"
                elseif not (string.find(output_str,"\n",output_str:len())) then
                    output_str = output_str .. "\n"
                end

                -- This is necessary for working with HUGE tables otherwise we run out of memory using concat on huge strings
                table.insert(output,output_str)
                output_str = ""

                local key
                if (type(k) == "number" or type(k) == "boolean") then
                    key = "["..tostring(k).."]"
                else
                    key = "['"..tostring(k).."']"
                end

                if (type(v) == "number" or type(v) == "boolean") then
                    output_str = output_str .. string.rep('\t',depth) .. key .. " = "..tostring(v)
                elseif (type(v) == "table") then
                    output_str = output_str .. string.rep('\t',depth) .. key .. " = {\n"
                    table.insert(stack,node)
                    table.insert(stack,v)
                    cache[node] = cur_index+1
                    break
                else
                    output_str = output_str .. string.rep('\t',depth) .. key .. " = '"..tostring(v).."'"
                end

                if (cur_index == size) then
                    output_str = output_str .. "\n" .. string.rep('\t',depth-1) .. "}"
                else
                    output_str = output_str .. ","
                end
            else
                -- close the table
                if (cur_index == size) then
                    output_str = output_str .. "\n" .. string.rep('\t',depth-1) .. "}"
                end
            end

            cur_index = cur_index + 1
        end

        if (size == 0) then
            output_str = output_str .. "\n" .. string.rep('\t',depth-1) .. "}"
        end

        if (#stack > 0) then
            node = stack[#stack]
            stack[#stack] = nil
            depth = cache[node] == nil and depth + 1 or depth - 1
        else
            break
        end
    end

    -- This is necessary for working with HUGE tables otherwise we run out of memory using concat on huge strings
    table.insert(output,output_str)
    output_str = table.concat(output)

    print(output_str)
end

다음은 예입니다.

local t = {
    ["abe"] = {1,2,3,4,5},
    "string1",
    50,
    ["depth1"] = { ["depth2"] = { ["depth3"] = { ["depth4"] = { ["depth5"] = { ["depth6"] = { ["depth7"]= { ["depth8"] = { ["depth9"] = { ["depth10"] = {1000}, 900}, 800},700},600},500}, 400 }, 300}, 200}, 100},
    ["ted"] = {true,false,"some text"},
    "string2",
    [function() return end] = function() return end,
    75
}

print_table(t)

산출:

{
    [1] = 'string1',
    [2] = 50,
    [3] = 'string2',
    [4] = 75,
    ['abe'] = {
        [1] = 1,
        [2] = 2,
        [3] = 3,
        [4] = 4,
        [5] = 5
    },
    ['function: 06472B70'] = 'function: 06472A98',
    ['depth1'] = {
        [1] = 100,
        ['depth2'] = {
            [1] = 200,
            ['depth3'] = {
                [1] = 300,
                ['depth4'] = {
                    [1] = 400,
                    ['depth5'] = {
                        [1] = 500,
                        ['depth6'] = {
                            [1] = 600,
                            ['depth7'] = {
                                [1] = 700,
                                ['depth8'] = {
                                    [1] = 800,
                                    ['depth9'] = {
                                        [1] = 900,
                                        ['depth10'] = {
                                            [1] = 1000
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    },
    ['ted'] = {
        [1] = true,
        [2] = false,
        [3] = 'some text'
    }
}

tab기능이 너무 복잡합니다. 기본적으로는 string.repeat('\t', amt)성능이 훨씬 떨어집니다.
발은 모니카 복원

6

앞에서 언급했듯이 작성해야합니다. 내 겸손한 버전은 다음과 같습니다. (슈퍼 기본 버전)

function tprint (t, s)
    for k, v in pairs(t) do
        local kfmt = '["' .. tostring(k) ..'"]'
        if type(k) ~= 'string' then
            kfmt = '[' .. k .. ']'
        end
        local vfmt = '"'.. tostring(v) ..'"'
        if type(v) == 'table' then
            tprint(v, (s or '')..kfmt)
        else
            if type(v) ~= 'string' then
                vfmt = tostring(v)
            end
            print(type(t)..(s or '')..kfmt..' = '..vfmt)
        end
    end
end

예:

local mytbl = { ['1']="a", 2, 3, b="c", t={d=1} }
tprint(mytbl)

출력 (Lua 5.0) :

table[1] = 2
table[2] = 3
table["1"] = "a"
table["t"]["d"] = 1
table["b"] = "c"

1
아주 독창적입니다! 나는 그것을 좋아한다.
Jack Giffin


2

이것은 테이블 및 사용자 데이터 제외를 지원하는 내 버전입니다.

-- Lua Table View by Elertan
table.print = function(t, exclusions)
    local nests = 0
    if not exclusions then exclusions = {} end
    local recurse = function(t, recurse, exclusions)
        indent = function()
            for i = 1, nests do
                io.write("    ")
            end
        end
        local excluded = function(key)
            for k,v in pairs(exclusions) do
                if v == key then
                    return true
                end
            end
            return false
        end
        local isFirst = true
        for k,v in pairs(t) do
            if isFirst then
                indent()
                print("|")
                isFirst = false
            end
            if type(v) == "table" and not excluded(k) then
                indent()
                print("|-> "..k..": "..type(v))
                nests = nests + 1
                recurse(v, recurse, exclusions)
            elseif excluded(k) then
                indent()
                print("|-> "..k..": "..type(v))
            elseif type(v) == "userdata" or type(v) == "function" then
                indent()
                print("|-> "..k..": "..type(v))
            elseif type(v) == "string" then
                indent()
                print("|-> "..k..": ".."\""..v.."\"")
            else
                indent()
                print("|-> "..k..": "..v)
            end
        end
        nests = nests - 1
    end

    nests = 0
    print("### START TABLE ###")
    for k,v in pairs(t) do
        print("root")
        if type(v) == "table" then
            print("|-> "..k..": "..type(v))
            nests = nests + 1
            recurse(v, recurse, exclusions)
        elseif type(v) == "userdata" or type(v) == "function" then
            print("|-> "..k..": "..type(v))
        elseif type(v) == "string" then
            print("|-> "..k..": ".."\""..v.."\"")
        else
            print("|-> "..k..": "..v)
        end
    end
    print("### END TABLE ###")
end

이것은 예입니다

t = {
    location = {
       x = 10,
       y = 20
    },
    size = {
      width = 100000000,
      height = 1000,
    },
    name = "Sidney",
    test = {
        hi = "lol",
    },
    anotherone = {
        1, 
        2, 
        3
    }
}

table.print(t, { "test" })

인쇄물:

   ### START TABLE ###
root
|-> size: table
    |
    |-> height: 1000
    |-> width: 100000000
root
|-> location: table
    |
    |-> y: 20
    |-> x: 10
root
|-> anotherone: table
    |
    |-> 1: 1
    |-> 2: 2
    |-> 3: 3
root
|-> test: table
    |
    |-> hi: "lol"
root
|-> name: "Sidney"
### END TABLE ###

루트는 제외를 제거하지 않습니다.


2

JSON 형식 (나중에 IDE에서 "미화"할 수 있음) :

local function format_any_value(obj, buffer)
    local _type = type(obj)
    if _type == "table" then
        buffer[#buffer + 1] = '{"'
        for key, value in next, obj, nil do
            buffer[#buffer + 1] = tostring(key) .. '":'
            format_any_value(value, buffer)
            buffer[#buffer + 1] = ',"'
        end
        buffer[#buffer] = '}' -- note the overwrite
    elseif _type == "string" then
        buffer[#buffer + 1] = '"' .. obj .. '"'
    elseif _type == "boolean" or _type == "number" then
        buffer[#buffer + 1] = tostring(obj)
    else
        buffer[#buffer + 1] = '"???' .. _type .. '???"'
    end
end

용법:

local function format_as_json(obj)
    if obj == nil then return "null" else
        local buffer = {}
        format_any_value(obj, buffer)
        return table.concat(buffer)
    end
end

local function print_as_json(obj)
    print(_format_as_json(obj))
end

print_as_json {1, 2, 3}
print_as_json(nil)
print_as_json("string")
print_as_json {[1] = 1, [2] = 2, three = { { true } }, four = "four"}

BTW, 나는 또한 몇 가지 다른 솔루션을 작성했습니다. 매우 빠른 솔루션 과 특수 문자 이스케이프가 있는 솔루션 : https://github.com/vn971/fast_json_encode


이것은 작전에서 구체적으로 요청한 것이 아니지만 실제로 내가 찾고 있던 것입니다. 간단한 해결책과 같은 감사합니다. NodeMCU와 같이 공간이 제한된 Lua 환경에서 더 쉽게 사용할 수 있습니다.
Sawtaytoes

1

당신은 그것을 스스로 코딩해야합니다. 나는 이것을 썼고 그것은 당신에게 유용 할 수 있습니다

function printtable(table, indent)

  indent = indent or 0;

  local keys = {};

  for k in pairs(table) do
    keys[#keys+1] = k;
    table.sort(keys, function(a, b)
      local ta, tb = type(a), type(b);
      if (ta ~= tb) then
        return ta < tb;
      else
        return a < b;
      end
    end);
  end

  print(string.rep('  ', indent)..'{');
  indent = indent + 1;
  for k, v in pairs(table) do

    local key = k;
    if (type(key) == 'string') then
      if not (string.match(key, '^[A-Za-z_][0-9A-Za-z_]*$')) then
        key = "['"..key.."']";
      end
    elseif (type(key) == 'number') then
      key = "["..key.."]";
    end

    if (type(v) == 'table') then
      if (next(v)) then
        printf("%s%s =", string.rep('  ', indent), tostring(key));
        printtable(v, indent);
      else
        printf("%s%s = {},", string.rep('  ', indent), tostring(key));
      end 
    elseif (type(v) == 'string') then
      printf("%s%s = %s,", string.rep('  ', indent), tostring(key), "'"..v.."'");
    else
      printf("%s%s = %s,", string.rep('  ', indent), tostring(key), tostring(v));
    end
  end
  indent = indent - 1;
  print(string.rep('  ', indent)..'}');
end

1
답장 해 주셔서 감사합니다. 나는 이것을 시도하고 얻는다 : 전역 '정렬'(무값)을 호출하려고 시도
Cliff

변경 sorttable.sort...이 틀림 local sort = table.sort이가에서 찍은 코드 어딘가에.
Michal Kottman 2012

당신은 약간의 상상력이 있어야합니다! 편의를 위해 라이브러리 테이블 스페이스에서 _G로 복사 된 여러 기호가 있습니다. sort이 (가) table.sort, strrepis string.rep, strmatchis string.match등 의 복사본입니다 . 더 이상 있으면 알려 주시면 내 대답을 변경하겠습니다.
Borodin 2012

죄송합니다. 구조를 되풀이하려는 내 자신의 시도가 스택 오버플로를 만났기 때문에 테이블의 그물이 매우 깊습니다. (말장난이 아닙니다!) 재귀를 풀고 적절한 테일 콜을 사용하려고 머리를 두드리는 중이었지만 여기에 게시 한 지점에서 좌절했습니다.
Cliff

일반적으로 이러한 함수에서 재귀를 제거 할 수는 없습니다. 최종 재귀가 아니기 때문입니다. 더 큰 스택으로 빌드 된 Lua를 사용하거나 Lua 테이블을 사용하여 동일한 알고리즘을 구현하여 재귀 스택을 저장하십시오.
Borodin 2012

1
--~ print a table
function printTable(list, i)

    local listString = ''
--~ begin of the list so write the {
    if not i then
        listString = listString .. '{'
    end

    i = i or 1
    local element = list[i]

--~ it may be the end of the list
    if not element then
        return listString .. '}'
    end
--~ if the element is a list too call it recursively
    if(type(element) == 'table') then
        listString = listString .. printTable(element)
    else
        listString = listString .. element
    end

    return listString .. ', ' .. printTable(list, i + 1)

end


local table = {1, 2, 3, 4, 5, {'a', 'b'}, {'G', 'F'}}
print(printTable(table))

안녕하세요, 저는 순수 Lua에서이 작업을 수행하는 siple 코드를 작성했습니다. 버그가 있습니다 (목록의 마지막 요소 뒤에 혼수 상태를 작성).하지만 프로토 타입으로 빠르게 작성하는 방법은 필요합니다.


1

다른 버전 추가. 이것은 또한 사용자 데이터를 반복 하려고 시도 합니다.

function inspect(o,indent)
    if indent == nil then indent = 0 end
    local indent_str = string.rep("    ", indent)
    local output_it = function(str)
        print(indent_str..str)
    end

    local length = 0

    local fu = function(k, v)
        length = length + 1
        if type(v) == "userdata" or type(v) == 'table' then
            output_it(indent_str.."["..k.."]")
            inspect(v, indent+1)
        else
            output_it(indent_str.."["..k.."] "..tostring(v))
        end
    end

    local loop_pairs = function()
        for k,v in pairs(o) do fu(k,v) end
    end

    local loop_metatable_pairs = function()
        for k,v in pairs(getmetatable(o)) do fu(k,v) end
    end

    if not pcall(loop_pairs) and not pcall(loop_metatable_pairs) then
        output_it(indent_str.."[[??]]")
    else
        if length == 0 then
            output_it(indent_str.."{}")
        end
    end
end

1

나는 내 자신의 함수를 사용하여 테이블의 내용을 인쇄하지만 그것이 귀하의 환경에 얼마나 잘 변환되는지 확신하지 못합니다.

---A helper function to print a table's contents.
---@param tbl table @The table to print.
---@param depth number @The depth of sub-tables to traverse through and print.
---@param n number @Do NOT manually set this. This controls formatting through recursion.
function PrintTable(tbl, depth, n)
  n = n or 0;
  depth = depth or 5;

  if (depth == 0) then
      print(string.rep(' ', n).."...");
      return;
  end

  if (n == 0) then
      print(" ");
  end

  for key, value in pairs(tbl) do
      if (key and type(key) == "number" or type(key) == "string") then
          key = string.format("[\"%s\"]", key);

          if (type(value) == "table") then
              if (next(value)) then
                  print(string.rep(' ', n)..key.." = {");
                  PrintTable(value, depth - 1, n + 4);
                  print(string.rep(' ', n).."},");
              else
                  print(string.rep(' ', n)..key.." = {},");
              end
          else
              if (type(value) == "string") then
                  value = string.format("\"%s\"", value);
              else
                  value = tostring(value);
              end

              print(string.rep(' ', n)..key.." = "..value..",");
          end
      end
  end

  if (n == 0) then
      print(" ");
  end
end

-1

약간의 Alundaio 코드를 겸손하게 수정했습니다.

-- by Alundaio
-- KK modified 11/28/2019

function dump_table_to_string(node, tree, indentation)
    local cache, stack, output = {},{},{}
    local depth = 1


    if type(node) ~= "table" then
        return "only table type is supported, got " .. type(node)
    end

    if nil == indentation then indentation = 1 end

    local NEW_LINE = "\n"
    local TAB_CHAR = " "

    if nil == tree then
        NEW_LINE = "\n"
    elseif not tree then
        NEW_LINE = ""
        TAB_CHAR = ""
    end

    local output_str = "{" .. NEW_LINE

    while true do
        local size = 0
        for k,v in pairs(node) do
            size = size + 1
        end

        local cur_index = 1
        for k,v in pairs(node) do
            if (cache[node] == nil) or (cur_index >= cache[node]) then

                if (string.find(output_str,"}",output_str:len())) then
                    output_str = output_str .. "," .. NEW_LINE
                elseif not (string.find(output_str,NEW_LINE,output_str:len())) then
                    output_str = output_str .. NEW_LINE
                end

                -- This is necessary for working with HUGE tables otherwise we run out of memory using concat on huge strings
                table.insert(output,output_str)
                output_str = ""

                local key
                if (type(k) == "number" or type(k) == "boolean") then
                    key = "["..tostring(k).."]"
                else
                    key = "['"..tostring(k).."']"
                end

                if (type(v) == "number" or type(v) == "boolean") then
                    output_str = output_str .. string.rep(TAB_CHAR,depth*indentation) .. key .. " = "..tostring(v)
                elseif (type(v) == "table") then
                    output_str = output_str .. string.rep(TAB_CHAR,depth*indentation) .. key .. " = {" .. NEW_LINE
                    table.insert(stack,node)
                    table.insert(stack,v)
                    cache[node] = cur_index+1
                    break
                else
                    output_str = output_str .. string.rep(TAB_CHAR,depth*indentation) .. key .. " = '"..tostring(v).."'"
                end

                if (cur_index == size) then
                    output_str = output_str .. NEW_LINE .. string.rep(TAB_CHAR,(depth-1)*indentation) .. "}"
                else
                    output_str = output_str .. ","
                end
            else
                -- close the table
                if (cur_index == size) then
                    output_str = output_str .. NEW_LINE .. string.rep(TAB_CHAR,(depth-1)*indentation) .. "}"
                end
            end

            cur_index = cur_index + 1
        end

        if (size == 0) then
            output_str = output_str .. NEW_LINE .. string.rep(TAB_CHAR,(depth-1)*indentation) .. "}"
        end

        if (#stack > 0) then
            node = stack[#stack]
            stack[#stack] = nil
            depth = cache[node] == nil and depth + 1 or depth - 1
        else
            break
        end
    end

    -- This is necessary for working with HUGE tables otherwise we run out of memory using concat on huge strings
    table.insert(output,output_str)
    output_str = table.concat(output)

    return output_str

end

그때:

print(dump_table_to_string("AA", true,3))

print(dump_table_to_string({"AA","BB"}, true,3))

print(dump_table_to_string({"AA","BB"}))

print(dump_table_to_string({"AA","BB"},false))

print(dump_table_to_string({"AA","BB",{22,33}},true,2))

제공합니다 :

only table type is supported, got string

{
   [1] = 'AA',
   [2] = 'BB'
}

{
 [1] = 'AA',
 [2] = 'BB'
}

{[1] = 'AA',[2] = 'BB'}

{
  [1] = 'AA',
  [2] = 'BB',
  [3] = {
    [1] = 22,
    [2] = 33
  }
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.