Marketplace
๊ฐ์
ํฌ๋ฆฌ์์ดํฐ๋ Marketplace ๊ธฐ๋ฅ์ ํ์ฉํ์ฌ ๊ณจ๋, ํฌ๋ฆฌ์คํ๊ณผ ๊ฐ์ ๊ฒ์ ๋ด ์ฌํ๋ ์ด, ํ์ฝ, ํ๋ณต ๋ฌผ์ฝ ๋ฑ์ ์์ดํ ์ ์๋ ์ํ์ผ๋ก ๊ตฌ์ฑํ์ฌ ์ฌ์ฉ์์๊ฒ ํ๋งคํ ์ ์์ต๋๋ค.
ํ๋งค์์ ์๋ฌด
ํฌ๋ฆฌ์์ดํฐ๋ ํ๋งคํ ์ํ์ด ๊ตฌ๋งค์์๊ฒ ์ ์์ ์ผ๋ก ์ง๊ธ๋๋๋ก ์ฒ๋ฆฌํ ์๋ฌด๊ฐ ์์ต๋๋ค. ์ง๊ธ ๋๋ฝ์ด๋ ์ค๋ช ๊ณผ ๋ค๋ฅธ ์ํ ๊ตฌ์ฑ, ๊ตฌ๋งคํ ์ํ์ ๊ฐ์น ํผ์ ๋ฑ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ๊ฒฝ์ฐ, ๋ฐ๋์ ์ด์ ๋ํ ์ ์ ํ ํด๊ฒฐ ์กฐ์น๋ฅผ ์ฑ์คํ ์ดํํด์ผ ํฉ๋๋ค. ์ง๊ธ ์๋ฌด๋ฅผ ๋ถ์ฑ์คํ๊ฒ ์ดํํ๊ฑฐ๋ ๊ด๋ จ ์ ๊ณ ๊ฐ ๋ฐ๋ณต์ ์ผ๋ก ์ ์๋ ๊ฒฝ์ฐ, ์ ์ฐ ๋ณด๋ฅ, ์๋ ์ ์ฌ, ๋์๊ฐ ๊ณ์ ๋นํ์ฑํ ๋ฑ์ ๋ถ์ด์ต์ด ๋ฐ์ํ ์ ์์ต๋๋ค.
์์ธํ ์์๋ณด๊ธฐ
์๋ ์ํ ๊ฐ์ด๋๋ผ์ธ์ํ ์ข
๋ฅ
World Product
1ํ์ฑ์ผ๋ก ์ง๊ธ๋๋ ์ฌํ, ์์ดํ ๋ฑ์ ์ํ
์ฌํ ์ง๊ธ(๊ณจ๋, ํฌ๋ฆฌ์คํ ๋ฑ)
์์ดํ ์ง๊ธ(๊ฒ, ๋๋ผ, ํ๋ณต ํฌ์ ๋ฑ)
์๋ชจ์ฑ ์์ดํ (๋ถํ, ๊ฑด๋ฌผ ์ฆ์ ์ค์น๊ถ ๋ฑ)
์ํ ๊ด๋ฆฌ
์ํ์ ์๋๋ณ๋ก ๊ตฌ์ฑ๋๋ฉฐ, ๊ฐ๊ฐ ๊ฐ๋ณ์ ์ผ๋ก ์ค์ ํ ์ ์์ต๋๋ค.
์ํ์ ๋ฑ๋กํ๊ณ ๊ด๋ฆฌํ๋ ค๋ฉด ์๋๋ฅผ ๋จผ์ Publishํด์ผ ํฉ๋๋ค. ์๋๋ฅผ Publish ํ ๋ Owner group์ ๊ทธ๋ฃน์ผ๋ก ์ค์ ํ๋ฉด ๊ทธ๋ฃน์๊ณผ ํจ๊ป ์ํ์ ๊ด๋ฆฌํ๊ณ ์์ต์ ๋ถ๋ฐฐํ ์ ์์ต๋๋ค.
๊ถํ๋ณ ๊ธฐ๋ฅ
์๋์ ์์(๊ฐ์ธ ์๋)
O
O
O
Group Owner(๊ทธ๋ฃน ์๋)
O
O
O
Group Member(๊ทธ๋ฃน ์๋)
O
X
X
์ํ ๋ชฉ๋ก ํ์ธ
Dashboard์ World ํญ์์ ์๋๋ฅผ ํด๋ฆญํ์ฌ ์๋ ํ์ด์ง์ ์ง์ ํ ๋ค์, World Product ํญ์ ํด๋ฆญํ๋ฉด ๋ฑ๋กํ ์ํ์ ํ์ธํ ์ ์์ต๋๋ค.

์ํ ๋ฑ๋ก
+ Create World Product ๋ฒํผ์ ๋๋ฌ ์๋ก์ด ์ํ์ ๋ฑ๋กํ ์ ์์ต๋๋ค.


์ํ ID ๋ณต์ฌํ๊ธฐ
๊ฐ ์ํ ์ด๋ฆ ์์ ํ์๋๋ ... ๋ฒํผ์ ๋๋ฅธ ๋ค์, Copy Product Id๋ฅผ ํด๋ฆญํด์ ์ํ ID๋ฅผ ๋ณต์ฌํ ์ ์์ต๋๋ค.

์ํ ์์
์ํ ์ด๋ฏธ์ง๋ ์ด๋ฆ ์์ญ์ ํด๋ฆญํ์ฌ ์ํ์ ์ด๋ฏธ์ง, ์ด๋ฆ, ๊ฐ๊ฒฉ ๋ฑ์ ์์ ํ ์ ์์ต๋๋ค.

์ ์ ์๊ฒ ์ด๋ฏธ ๊ตฌ๋งค์ฐฝ์ด ์ถ๋ ฅ๋ ์ํ์์ ์ํ ์์ ์ด ๋ฐ์ํ๋ฉด, ๊ฒฐ์ ์์ ์ด์ ์ ๋ณด(๊ฐ๊ฒฉ)์ผ๋ก ์ฒ๋ฆฌ๋ฉ๋๋ค.
์ํ ํ๋งค๋ฅผ ์ํ ์คํฌ๋ฆฝํธ ์ฒ๋ฆฌ
Marketplace๋ฅผ ํตํ ์ํ ๊ตฌ๋งค ๊ธฐ๋ฅ์ ์ ์ ์ ์ฌํ๋ฅผ ์๋ชจํ๋ ์ค์ ๊ธฐ๋ฅ์ด๋ฏ๋ก, pcall ๋ฑ์ ํ์ฉํ ์๊ฒฉํ ์์ธ ์ฒ๋ฆฌ์ ๋๋ฒ๊น ์ด ํ์์ ์ ๋๋ค. ์ด๋ฅผ ํตํด ๋ฐํ์ ์ค๋ฅ๋ ๋คํธ์ํฌ ์ง์ฐ ๋ฑ์ ์ํฉ์์๋ ์์คํ ์ ์์ ์ฑ์ ์ ์งํ ์ ์์ผ๋ฉฐ, ์์ดํ ๋ฏธ์ง๊ธ๊ณผ ๊ฐ์ ์น๋ช ์ ์ธ ๋ฌธ์ ๋ฅผ ์ฌ์ ์ ๋ฐฉ์งํ ์ ์์ต๋๋ค.
๊ธฐ๋ฅ ๋ชฉ๋ก
GetProductInfo(productId, productType)
ํน์ ์ํ ์ ๋ณด ์์ฒญ
GetWorldProductsAsync()
๋ชจ๋ ์๋ ์ํ ์ ๋ณด ์์ฒญ
PromptProductPurchase(player, productId)
๊ตฌ๋งค ์์ฒญ
PromptProductPurchaseFinished
๊ตฌ๋งค์ฐฝ์ด ๊บผ์ง ๋ ํ์ํ ์ด๋ฒคํธ ์ฒ๋ฆฌ
ProcessReceipt
๊ตฌ๋งค ์ฑ๊ณต์ ์ํ ์ง๊ธ ์ฒ๋ฆฌ ํ, ์ ์ ์ง๊ธ๊ฑด์ ์์์ฆ ์ํ๋ฅผ ์๋ฃ๋ก ๋ณ๊ฒฝํ๊ธฐ ์ํ ์ด๋ฒคํธ
ํน์ ์ํ ์ ๋ณด ์์ฒญ(GetProductInfo)
์ํ ID(productId)์ ์ํ ํ์ (Enum.InfoType)์ ํด๋นํ๋ ์ํ ์ ๋ณด๋ฅผ ๋ฐํํฉ๋๋ค.
local MarketplaceService = game:GetService("MarketplaceService")
local function Request_GetProductInfo(productId)
local success, errorOrProductInfo = pcall(function()
return MarketplaceService:GetProductInfo(productId, Enum.InfoType.Product)
end)
if not success then
print("Error: " .. errorOrProductInfo .. " / ProductId : " .. productId)
else
local productInfo = errorOrProductInfo
print("World Product Name: " .. tostring(productInfo.Name))
print("ProductId: " .. tostring(productInfo.ProductId))
print("ProductType: " .. tostring(productInfo.ProductType))
print("PriceInBLUC: " .. tostring(productInfo.PriceInBLUC))
print("Description: " .. tostring(productInfo.Description))
print("Created: " .. productInfo.Created)
print("Updated: " .. productInfo.Updated)
-- UI์ ์ถ๋ ฅ
end
end
๋ชจ๋ ์๋ ์ํ ์ ๋ณด ์์ฒญ(GetWorldProductsAsync)
๋ชจ๋ ์๋ ์ํ์ ๋ํ ์ ๋ณด๋ฅผ ํฌํจํ๋ Pages ๊ฐ์ฒด๋ฅผ ๋ฐํํฉ๋๋ค.
local MarketplaceService = game:GetService("MarketplaceService")
local function Request_GetWorldProductsAsync()
local success, errorOrWorldProducts = pcall(function()
return MarketplaceService:GetWorldProductsAsync()
end)
if not success then
print("Error: " .. errorOrWorldProducts)
else
local worldProducts = errorOrWorldProducts
local pageCount = 1
local dataList = {}
while true do
local currentPage = worldProducts:GetCurrentPage()
-- ๋ง์ง๋ง ํ์ด์ง์ด๋ฉด ๋ฃจํ ํ์ถ
if worldProducts.IsFinished or currentPage == nil then
print(pageCount .. " page IsFinished : " .. tostring(worldProducts.IsFinished))
break
else
worldProducts:AdvanceToNextPageAsync()
pageCount = pageCount + 1
end
-- ํ ํ์ด์ง์ ์ต๋ 100๊ฐ์ ์ํ ์ ๋ณด ๊ตฌ์ฑ
for _, productInfo in pairs(currentPage) do
local i = #dataList + 1
print("------ " .. i .. " ------")
print("World Product Name: " .. tostring(productInfo.Name))
print("ProductId: " .. tostring(productInfo.ProductId))
print("ProductType: " .. tostring(productInfo.ProductType))
print("PriceInBLUC: " .. tostring(productInfo.PriceInBLUC))
print("Description: " .. tostring(productInfo.Description))
print("Created: " .. productInfo.Created)
print("Updated: " .. productInfo.Updated)
table.insert(dataList, productInfo)
-- UI์ ์ถ๋ ฅ
end
end
end
end
๊ตฌ๋งค ์์ฒญ(PromptProductPurchase)
์๋ ์ํ ID(productId)์ ํด๋นํ๋ ์ํ์ ๊ตฌ๋งค๋ฅผ ์์ฒญํฉ๋๋ค. (์์คํ UI๋ก ๊ตฌ๋งค์ฐฝ์ด ์ถ๋ ฅ๋ฉ๋๋ค.)
local MarketplaceService = game:GetService("MarketplaceService")
local function Request_PromptProductPurchase(player, productId)
local success, error = pcall(function()
MarketplaceService:PromptProductPurchase(player, productId)
end)
if not success then
print("Error: " .. error .. " / ProductId : " .. productId)
end
end
๊ตฌ๋งค์ฐฝ ๊บผ์ง ๋(PromptProductPurchaseFinished)
๊ตฌ๋งค ์์ฒญ(PromptProductPurchase)์ ํตํด ์ถ๋ ฅ๋ ๊ตฌ๋งค์ฐฝ์ด ๊บผ์ง ๋ ์ด๋ฒคํธ๊ฐ ํธ์ถ๋๋ฉฐ, ๊ตฌ๋งค๋ฅผ ์ฑ๊ณตํ๋ฉด isPurchased์ true๊ฐ ์ ๋ฌ๋๊ณ , ๊ตฌ๋งค๋ฅผ ์ทจ์ํ๊ฑฐ๋ ์คํจํ๋ฉด false๊ฐ ์ ๋ฌ๋ฉ๋๋ค.
์ด ์ด๋ฒคํธ๋ ๊ตฌ๋งค ์ฐฝ์ ๋ซ์๋์ง ๊ฐ์งํ๊ธฐ ์ํ ์ฉ๋๋ก๋ง ์ฌ์ฉํด์ผ ํ๋ฉฐ, ๊ตฌ๋งคํ ์ํ์ ๋ํ ์ง๊ธ ์ฒ๋ฆฌ ์ฉ๋๋ก๋ ์ ๋ ์ฌ์ฉํ์ง ์์์ผ ํฉ๋๋ค.
local Players = game:GetService("Players")
local MarketplaceService = game:GetService("MarketplaceService")
local function OnPromptPurchaseFinished(userId, productId, isPurchased)
local player = Players:GetPlayerByUserId(userId)
print(player.Name .. " / ProductID : " .. productId .. " / isPurchased : " .. tostring(isPurchased))
end
MarketplaceService.PromptProductPurchaseFinished:Connect(OnPromptPurchaseFinished)
๊ตฌ๋งค ์ฑ๊ณต์ ์ง๊ธ ์ฒ๋ฆฌ(ProcessReceipt)
๊ตฌ๋งค ์ฑ๊ณตํ ์ํ ์ค์์ ์์ง ์ง๊ธ ์ฒ๋ฆฌ๊ฐ ๋์ง ์์ ์์์ฆ ์ ๋ณด๋ฅผ ๋ฐํํ๋ ์ด๋ฒคํธ๊ฐ ํธ์ถ๋ฉ๋๋ค.
์์์ฆ ์ํ
NotProcessedYet
์ํ ๋ฏธ์ง๊ธ ์ํ
ํธ์ถ ์กฐ๊ฑด์ ๋ฐ๋ผ ๋ค์ ํธ์ถ๋ ์ ์์
PurchaseGranted
์ํ ์ง๊ธ ์๋ฃ ์ํ
๋ค์ ํธ์ถ๋์ง ์์
ํธ์ถ ์กฐ๊ฑด
์๋ ์ํ์ ์ฑ๊ณต์ ์ผ๋ก ๊ตฌ๋งคํ์ ๋(๊ตฌ๋งค ์ฑ๊ณต ํ์ ์ด ์ฌ์ฉ์์๊ฒ ํ์๋์์ ๋)
๋ฏธ์ฒ๋ฆฌ ์ํ์ด ์๋ ์ํ์์ ์๋ก์ด ์ํ ๊ตฌ๋งค์, ์ด์ ๋ฏธ์ฒ๋ฆฌ๊ฑด๋ ํจ๊ป ํธ์ถ๋ฉ๋๋ค.
์ฌ์ฉ์๊ฐ ์๋ฒ์ ์ ์(์ฌ์ ์)ํ์ ๋
์ง๊ธ ์ํ ๋ณ๊ฒฝ ๋ฐฉ๋ฒ
์ํ ์ง๊ธ ์ฒ๋ฆฌ ํ์, Enum.ProductPurchaseDecision.PurchaseGranted๋ฅผ ๋ฐํํฉ๋๋ค.
์ฃผ์์ฌํญ
ProcessReceipt ์ด๋ฒคํธ ์ฐ๊ฒฐ์ ์๋ฒ์ธก Script์์ ํ ๋ฒ๋ง ์ค์ ํด์ผ ํฉ๋๋ค.
์ด ์ฝ๋ฐฑ์ ์๊ฐ ์ ํ ์์ด yield ๊ฐ๋ฅํ๋ฉฐ, ์๋ฒ๊ฐ ์คํ ์ค์ธ ํ ์๋ต์ด ๋์์ฌ ๋๊น์ง ์ ํจํฉ๋๋ค.
๋ฏธ์ง๊ธ๋ ์์์ฆ์ด ์ฌ๋ฌ๊ฐ์ธ ๊ฒฝ์ฐ ๊ฐ๊ฐ ํธ์ถ๋๋ฉฐ, ์ฝ๋ฐฑ ํธ์ถ ์์๋ ๋น๊ฒฐ์ ์ (non-deterministic)์ ๋๋ค.
์ฌ์ฉ์๊ฐ ์๋ฒ์ ์์ด์ผ ์ฝ๋ฐฑ์ด ํธ์ถ๋ฉ๋๋ค.
๋จ, ์ฝ๋ฐฑ์ ๊ฒฐ๊ณผ๋ ์ฌ์ฉ์๊ฐ ์๋ฒ์ ์์ด๋ ๋ฐฑ์๋์ ๊ธฐ๋ก๋ ์ ์์ต๋๋ค.
์ฝ๋ฐฑ์์ PurchaseGranted๋ฅผ ๋ฐํํด๋ ๋ฐฑ์๋ ๊ธฐ๋ก์ด ์คํจํ ์ ์์ผ๋ฉฐ, ์ด๋ฐ ๊ฒฝ์ฐ ์์์ฆ์ ์ํ๋ ๋ณ๊ฒฝ๋์ง ์์ต๋๋ค. (๋ฏธ์ง๊ธ ์ํ ์ ์ง)
๋ฏธ์ง๊ธ ์ํ์ ์ํ์ ์๊ธ์ด ์ง๊ธ ๋ณด๋ฅ ์ํ(Escrow)๋ก ๋ณด๊ด๋ฉ๋๋ค.
local Players = game:GetService("Players")
local MarketplaceService = game:GetService("MarketplaceService")
local ProductDeliverer = {}
-----------------------------------------------------------------------------
-- ์๋์ ๊ฐ์ด ํ
์ด๋ธ์ ์ํ ๋ฒํธ ๋ณ๋ก ํจ์๋ฅผ ๊ตฌ์ฑํ์ฌ ์ํ๋ง๋ค ์ง๊ธ ๋ก์ง์ ๊ตฌํํ ์ ์์ต๋๋ค.
ProductDeliverer[์ฌ๊ธฐ์ ์ํ ๋ฒํธ๋ฅผ ๋ฃ์ผ์ธ์.] = function(player)
local success, resultOrError = pcall(function()
-- player์๊ฒ ์ํ ์ง๊ธ ๋ฐ DataStore๋ฅผ ์ด์ฉํ ์ ์ฅ ์ฒ๋ฆฌ
-- Tip.
-- DataStore๋ก ์ํ ์ ๋ณด๋ฅผ ์ ์ฅํ ๋๋
-- ๋คํธ์ํฌ ์ถฉ๋์ด๋ ๊ฒฝ์ ์ํ(race condition)๋ฅผ ๋ฐฉ์งํ๊ธฐ ์ํด
-- IncrementAsync ๋๋ UpdateAsync๋ก ์ฒ๋ฆฌํ๋ ๊ฒ์ ๊ถ์ฅํฉ๋๋ค.
-- ์ง๊ธ ๋ฐ ์ ์ฅ ์ฒ๋ฆฌ๊ฐ ์ฑ๊ณต์ ์ผ๋ก ์๋ฃ๋ ๊ฒฝ์ฐ true ๋ฐํ
return true
end)
if success and resultOrError then
return true
else
return false, resultOrError
end
end
-----------------------------------------------------------------------------
-- ์ํ ๊ตฌ๋งค ์ฑ๊ณต์ ํธ์ถ๋๋ ์์์ฆ ์ฒ๋ฆฌ์ฉ ์ฝ๋ฐฑ
local function OnProcessReceipt(receiptInfo)
-- ์์์ฆ ์ ๋ณด
local success, error = pcall(function()
print("PurchaseId: " .. receiptInfo.PurchaseId)
print("UserId: " .. receiptInfo.PlayerId)
print("ProductId: " .. receiptInfo.ProductId)
print("CurrencySpent: " .. receiptInfo.CurrencySpent)
print("PurchaseDateTime: " .. receiptInfo.PurchaseDateTime)
end)
if not success then
print("Error: " .. tostring(error))
return Enum.ProductPurchaseDecision.NotProcessedYet
end
-- ํ๋ ์ด์ด๊ฐ ์ ํจํ๋ฉด
local productId = receiptInfo.ProductId
local userId = receiptInfo.PlayerId
local player = Players:GetPlayerByUserId(userId)
if player == nil then
print("Error: player is nil")
return Enum.ProductPurchaseDecision.NotProcessedYet
end
-- ์ํ ์ง๊ธ ํจ์ ํธ์ถ
local delivererFunc = ProductDeliverer[productId]
local success, error = delivererFunc(player)
-- ์ํ ์ง๊ธ ์ฑ๊ณต์
if success then
-- ์ง๊ธ ์๋ฃ ์ํ ๋ฐํ
print("Item delivery successful / ProductId : " .. productId)
return Enum.ProductPurchaseDecision.PurchaseGranted
-- ์ํ ์ง๊ธ ์คํจ์
else
print("Error: " .. tostring(error))
return Enum.ProductPurchaseDecision.NotProcessedYet
end
end
MarketplaceService.ProcessReceipt = OnProcessReceipt
ํ
์คํธ ๊ตฌ๋งค
์คํ๋์ค์ ํ ์คํธ ํ๋ ์ด ํ๊ฒฝ์์๋ ์ํ ๊ตฌ๋งค ๋ฐ ์ง๊ธ ์ฒ๋ฆฌ๋ฅผ ํ์ธํ ์ ์์ต๋๋ค. (์ฌํ๊ฐ ์ฐจ๊ฐ๋์ง ์์ต๋๋ค.)
ํ๋งค ํต๊ณ
๊ณง ์ง์๋ ์์ ์ ๋๋ค.
์์ต
์์ต ๋ถ๋ฐฐ
๊ณง ์ง์๋ ์์ ์ ๋๋ค.
์์ต ์ ์ฐ
๊ณง ์ง์๋ ์์ ์ ๋๋ค.
ํ์ฉ ์์
์ธ๊ฒ์ ์ฌํ๋ฅผ ๋ฌด๋ฃ/์ ๋ฃ๋ก ๊ตฌ๋ถํ ๋ค, ์ ๋ฃ ์ฌํ์ ๊ฐ์น๋ฅผ ๋์ด๊ณ ์๋ ์ํ์ผ๋ก ํ๋งคํ์ฌ ์ฌ์ฉ์ ๊ตฌ๋งค๋ฅผ ์ ๋ํ๊ณ ์์ต์ ์ด์งํ ์ ์์ต๋๋ค.
์ผ๋ฐ ์คํจ๋ณด๋ค ๋ ๋์ ํ๋ฆฌํฐ์ ์คํจ์ ์๋ ์ํ์ผ๋ก ๊ตฌ์ฑํ๋ฉด, ํ๋ ์ด์ด์ ๊ฐ์ฑ๊ณผ ๊พธ๋ฏธ๊ธฐ ์๊ตฌ๋ฅผ ์๊ทนํ์ฌ ๊ตฌ๋งค๋ก ์ด์ด์ง ์ ์์ต๋๋ค.
๋ฌด๊ธฐ, ํฌ์ , ์ฌํ ๋ฑ์ ๋ฌถ์ ํจํค์ง ์ํ์ ๊ตฌ์ฑํ๋ฉด, ๊ฐ๋ณ ์์ดํ ๋๋น ๋์ ๊ฐ์ฑ๋น๋ฅผ ํตํด ๊ตฌ๋งค ์ ํ์จ์ ๋์ผ ์ ์์ต๋๋ค.
์ ํฌ ์ค ์ฌ๋งํ์ ๋ ์ฆ์ ๋ถํํ ์ ์๋ ์๋ชจ์ฑ ์์ดํ ์ ์๋ ์ํ์ผ๋ก ๊ตฌ์ฑํ๋ฉด, ๊ฒ์ ํ๋ฆ์ ์ ์งํ๋ฉด์ ์์ฐ์ค๋ฌ์ด ๊ตฌ๋งค๋ฅผ ์ ๋ํ ์ ์์ต๋๋ค.
์์ฆ ํจ์ค์ ๊ฐ์ ์ง์ํ ์ํ์ ํตํด ์ฅ๊ธฐ์ ์ธ ์ฌ์ฉ์ ๋ฆฌํ ์ ๊ณผ ์์ต์ ๋์์ ํ๋ณดํ ์ ์์ต๋๋ค.
์ ๋ฃ ์ํ ์์ฃผ์ ๊ณผ๋ํ ๊ตฌ์ฑ๋ณด๋ค๋, ์ผ์ ์์ค์ ๋ฌด๋ฃ ์ํ์ ์ ์ ํ ์ ๊ณตํ์ฌ ์ฌ์ฉ์ ๋ง์กฑ๋๋ฅผ ๋์ด๊ณ , ์ ๋ขฐ๋ฅผ ๋ฐํ์ผ๋ก ํ ์๋ฐ์ ์ธ ๊ตฌ๋งค๋ฅผ ์ ๋ํ๋ ๊ฒ์ด ๋์ฑ ํจ๊ณผ์ ์ ๋๋ค.
Last updated