CREATE YOUR WORLD
멀티플레이
Multiplay 서버에서 HTTP 요청하기
15분
zepeto 월드 멀티플레이 서버에서 zepeto multiplay httpservice 모듈을 사용하여 http 요청을 할 수 있습니다 비즈니스 로직 작업, 데이터 저장, 통계 분석, 오류 추적 등을 위해 외부 웹 서비스를 통합하세요 https 프로토콜만 사용되도록 하세요 http는 개발 환경에서만 지원됩니다 요청은 포트 80과 443에서만 허용됩니다 요청 및 응답 본문의 최대 크기는 16kb로 제한됩니다 과도한 요청이 발생할 경우 월드 서비스에 대한 잠재적 제한을 피하기 위해 분당 요청 수를 500 이하로 유지하세요 외부 웹 서비스가 5초 이내에 응답하지 않으면 요청이 실패합니다 응답 헤더의 content type이 httpcontenttype 열거형에 정의된 값과 일치하는지 확인하세요 그렇지 않으면 요청이 실패합니다 다양한 이유로 웹 요청이 실패할 가능성이 있으므로 방어적으로 코딩하는 것이 좋습니다 zepeto multiplay httpservice 📘 다음 가이드를 참조하세요 \[ zepeto multiplay httpservice api https //developer zepeto me/docs/multiplay server/interfaces/zepeto multiplay httpservice httpservice ] 메서드 방법 설명 httpservice getasync(url string, headers? httpheader) promise 비동기적으로 http get 요청을 수행합니다 \[매개변수] \ url 요청을 보낼 웹 주소입니다 \ headers http 요청 헤더입니다 (선택 사항) \[반환 값] \ promise\<httpresponse> 응답에 대한 정보를 포함하는 httpresponse 객체를 promise로 반환합니다 httpservice postasync(url string, body httpbodytype, headers? httpheader) promise 비동기적으로 http post 요청을 수행합니다 \[매개변수] \ url 요청을 보낼 웹 주소입니다 \ body 요청 본문 내용입니다 \ headers http 요청 헤더입니다 (선택 사항) \[반환 값] \ promise\<httpresponse> 응답에 대한 정보를 포함하는 httpresponse 객체를 promise로 반환합니다 httpservice postasync(url string, body httpbodytype, httpcontenttype httpcontenttype, headers? httpheader) promise 비동기적으로 http post 요청을 수행합니다 \[매개변수] \ url 요청을 보낼 웹 주소입니다 \ body 요청 본문 내용입니다 \ httpcontenttype 요청 content type 헤더를 지정합니다 \ headers http 요청 헤더입니다 (선택 사항) \[반환 값] \ promise\<httpresponse> 응답에 대한 정보를 포함하는 httpresponse 객체를 promise로 반환합니다 이 서명을 사용할 때, headers에 'content type'을 추가하면 httpcontenttype에 지정된 내용으로 덮어씌워집니다 기타 선언 선언 설명 httpcontenttype http 헤더의 content type을 지정하는 상수의 열거형입니다 \ applicationjson 'application/json' \ applicationxml 'application/xml' \ applicationurlencoded 'application/x www form urlencoded' \ textplain 'text/plain' \ textxml 'text/xml' httpbodytype http 요청 본문 콘텐츠의 유형으로, 문자열 또는 문자열 키와 임의의 값을 가진 객체일 수 있습니다 httpheader http 요청 헤더를 정의하는 유형으로, 속성 값은 객체 내에서 문자열 또는 숫자일 수 있습니다 httpresponse http 요청 결과 및 응답 데이터에 대한 정보를 포함하는 인터페이스입니다 \ statuscodehttp 응답의 상태 코드를 나타내는 숫자입니다 일반적으로 200은 성공적인 요청을 나타냅니다 \ statustexthttp 응답의 상태 메시지를 나타내는 문자열입니다 일반적으로 "ok"는 성공적인 요청을 나타냅니다 \ response http 응답 본문 데이터가 포함된 문자열입니다 📘 http 상태 https //developer mozilla org/en us/docs/web/http/status https //developer mozilla org/en us/docs/web/http/status 코드 샘플 기본 get 요청 간단한 get 요청 예제를 만들어 보겠습니다 httpservice getasync 새로운 클라이언트가 멀티플레이 룸에 연결되면, 외부 웹 서비스에 http 요청을 보내고 결과를 기록합니다 restcountries com https //restcountries com/ 는 다양한 국가에 대한 정보를 제공하는 오픈 api입니다 우리는 이 서비스를 사용하여 일본의 수도를 알아낼 것입니다 multiplay를 설정한 후, world multiplay/index ts를 열고 서버 스크립트를 다음과 같이 작성하세요 📘 다음 가이드를 참조하세요 \[ 멀티플레이 docid\ lqdlv5a9ek5hwd16tv0y ] import { sandbox, sandboxoptions, sandboxplayer } from "zepeto multiplay"; import { httpservice } from "zepeto multiplay httpservice"; export default class extends sandbox { oncreate(options sandboxoptions) { } onjoin(client sandboxplayer) { this findcapitalcity() } onleave(client sandboxplayer, consented? boolean) { } findcapitalcity() { // make the request to the restcountries api httpservice getasync("https //restcountries com/v3 1/name/japan?fields=capital") // handler for the http response then((httpresponse) => { // parse the json response data from the api (which is nested in http response) let countries = json parse(httpresponse response); console log("the capital city of japan is "); console log(`${countries\[0] capital}`); }); } } 코드 설명 클라이언트가 멀티플레이 룸에 연결되면, onjoin 함수가 트리거되고, findcapitalcity 만약 getasync 호출이 restcountries api에 성공하면, httpresponse 객체에 접근할 수 있습니다 then 콜백에서 api 응답을 json 형식에서 객체로 변환하기 위해 httpresponse response 를 파싱합니다 api 응답의 구조를 참조하여 원하는 속성에 접근하고 그 값을 출력합니다 unity editor에서 멀티플레이 서버를 실행하고 장면을 재생하면, 콘솔에 다음과 같은 내용이 표시됩니다 일본의 수도는 도쿄 방어적 코딩 관행 한편, 서론의 주의 사항에서 언급했듯이, 웹 요청은 웹 주소나 api 응답 형식의 변경 등 다양한 이유로 실패할 수 있습니다 이러한 요청을 적절히 처리하지 않으면 월드 플레이에 다양한 부정적인 영향을 미칠 수 있으므로, 특히 http 요청을 처리할 때 방어적으로 코딩하는 것이 권장됩니다 다음은 위의 코드에 여러 방어적 코딩 기법을 적용한 예입니다 findcapitalcity() { // restcountries api에 요청을 보냅니다 httpservice getasync( "https //restcountries com/v3 1/name/japan?fields=capital", { 'accept' httpcontenttype applicationjson }) // http 응답 핸들러 then((httpresponse) => { // api 호출이 200(ok)을 반환했는지 확인합니다 if (httpresponse statuscode != 200) { // 200(ok)이 아니면 진행하지 않고 사용자 정의 오류를 발생시킵니다 throw (`api 오류 ${httpresponse statuscode} ${httpresponse statustext}`); } // api로부터 json 응답 데이터를 반환합니다 return httpresponse response; }) // api로부터 json 응답 데이터 핸들러 then((response) => { // json 응답 데이터를 파싱합니다 let countries = json parse(response); // api 응답 데이터가 유효한지 확인합니다 if (!array isarray(countries) || !countries length) { // 배열이 아니거나 비어있으면 // 진행하지 않고 사용자 정의 오류를 발생시킵니다 throw (`api 오류 응답 데이터가 유효하지 않습니다 `); } let country = countries\[0]; // 'capital' 필드가 유효한지 확인합니다 if (!country capital) { // 'capital' 필드가 존재하지 않거나 비어있으면 // 진행하지 않고 사용자 정의 오류를 발생시킵니다 throw (`api 오류 'capital' 필드가 유효하지 않습니다 `); } console log("일본의 수도는 ") console log(`${country capital}`); }) // getasync 호출 및 'then' 절에서 발생하는 오류 핸들러 catch((reason) => { console log("api 요청 오류"); console log(reason); }); } 여기 적용된 방어적 코딩 기술은 다음과 같습니다 다음 사용 accept 헤더 accept 헤더는 응답 본문의 예상 content type을 지정하는 데 사용됩니다 서버에 따라 응답 content type은 accept 헤더에 따라 조정될 수 있습니다 확인 httpresponse statuscode httpresponse statuscode 속성은 요청의 성공 여부를 확인하는 데 사용됩니다 json 데이터 구조 검증 json parse 로 구문 분석된 객체의 데이터 구조가 예상 구조와 일치하는지 확인합니다 속성 존재 확인 사용하려는 속성이 실제로 객체에 존재하는지 확인합니다 promise의 사용 catch 메서드 promise의 catch 메서드는 api 요청 및 응답 처리 중 발생할 수 있는 오류를 처리하는 데 사용됩니다 이 기술들은 예기치 않은 오류에 직면했을 때 코드가 신뢰성 있게 작동하도록 보호하여 강력함을 향상시킵니다 클라이언트와의 통합을 위한 룸 메시지 http 요청은 멀티플레이 서버에서만 가능합니다 그러나 멀티플레이 룸 메시지를 사용하면 클라이언트에서 서버를 트리거하여 외부 웹 서비스에 http 요청을 보내고 클라이언트 내에서 응답을 활용할 수 있습니다 다음 예제는 클라이언트 서버 통합을 보여줍니다 이 시연에서는 클라이언트의 ui에서 버튼을 누르면 버튼에 해당하는 국가의 수도가 표시됩니다 📘 다음 가이드를 참조하십시오 \[ multiplay room message docid\ yt8t8xpljhscnor5y4r7n ] 클라이언트 코드 import { zepetoscriptbehaviour } from 'zepeto script' import { room } from 'zepeto multiplay' import { zepetoworldmultiplay } from 'zepeto world'; import { button, text } from 'unityengine ui' export default class samplescript extends zepetoscriptbehaviour { public multiplay zepetoworldmultiplay; public room room; public countrybuttons button\[]; public capitaltext text; start() { interface response { capitals string\[] } for (const countrybutton of this countrybuttons) { countrybutton onclick addlistener(() => { if (this room !== null) { // send the country name as a 'client to server' type message to the server this room send("client to server", countrybutton getcomponentinchildren\<text>() text); } }); }; this multiplay roomcreated += (room room) => { this room = room; // handle messages received with a 'server to client' type this room addmessagehandler("server to client", (message response) => { // for countries with multiple capital cities, // join the string elements with ', ' and display on the scene this capitaltext text = message capitals join(", "); }); }; } } 코드 설명 우리는 국가 이름을 표시하는 버튼을 반복하는 리스너를 정의합니다 클릭하면 이 리스너는 멀티플레이 서버에 방 메시지를 보냅니다 이 리스너는 버튼에 표시된 국가 이름을 '클라이언트 서버' 유형 메시지로 보냅니다 응답을 처리하기 위해, 우리는 '서버 클라이언트' 유형으로 수신된 방 메시지를 처리하는 리스너도 정의합니다 이 리스너는 서버에서 수신한 수도 이름을 화면에 표시합니다 여러 수도가 있는 경우, 화면에 쉼표로 구분하여 표시됩니다 서버 코드 import { sandbox, sandboxoptions, sandboxplayer } from "zepeto multiplay"; import { httpservice } from "zepeto multiplay httpservice"; export default class extends sandbox { oncreate(options sandboxoptions) { // 'client to server' 유형의 메시지를 처리합니다 this onmessage("client to server", (client, message) => { console log(`클라이언트 ${client userid}가 요청을 보냈습니다 메시지 ${message}`); this findcapitalcity(message, client); }); } onjoin(client sandboxplayer) { } onleave(client sandboxplayer, consented? boolean) { } findcapitalcity(countryname string, client sandboxplayer) { // countryname을 경로 매개변수로 사용하여 api 요청 // countryname은 클라이언트가 방 메시지로 보냅니다 httpservice getasync(`https //restcountries com/v3 1/name/${countryname}?fields=capital`) then((httpresponse) => { if (httpresponse statuscode != 200) { throw (`api 오류 ${httpresponse statuscode} ${httpresponse statustext}`); } return httpresponse response; }) then((response) => { let countries = json parse(response); if (!array isarray(countries) || !countries length) { throw (`api 오류 응답 데이터가 유효하지 않습니다 `); } let country = countries\[0]; if (!country capital) { throw (`api 오류 'capital' 필드가 유효하지 않습니다 `); } // 클라이언트에게 'server to client' 유형의 메시지를 보냅니다 // 메시지는 수도 이름을 포함하는 객체입니다 client send("server to client", { "capitals" country capital }); }) catch((reason) => { console log("api 요청 오류"); console log(reason); }); } } 코드 설명 우리는 '클라이언트 서버' 유형의 멀티플레이 룸 메시지를 수신하면 호출하는 리스너를 정의합니다 findcapitalcity 우리는 국가 이름을 사용하여 멀티플레이 룸 메시지의 주소를 구성하고 getasync 호출을 합니다 만약 getasync 호출이 성공하면, 응답은 이전 예제와 같이 처리됩니다 restcountries api의 응답에서 얻은 수도 이름은 '서버 클라이언트' 유형의 룸 메시지로 클라이언트에 전송됩니다 post 요청 마지막으로, httpservice postasync 를 사용하여 post 요청 예제를 만들어 보겠습니다 postman echo https //postman echo com/ 는 웹 요청에서 수신된 내용을 보여주는 구조화된 응답을 제공하는 서비스로, 클라이언트가 요청을 올바르게 구성했는지 확인하는 데 효과적입니다 이 예제를 통해 쿼리 매개변수, 요청 본문 및 헤더가 포함된 post 요청을 설정하고 요청이 올바르게 구성되었는지 확인할 것입니다 multiplay를 설정한 다음, world multiplay/index ts를 열고 서버 스크립트를 다음과 같이 작성하세요 import { sandbox, sandboxoptions, sandboxplayer } from "zepeto multiplay"; import { httpcontenttype, httpservice } from "zepeto multiplay httpservice"; export default class extends sandbox { oncreate(options sandboxoptions) { } onjoin(client sandboxplayer) { this echopost() } onleave(client sandboxplayer, consented? boolean) { } echopost() { httpservice postasync( // api 엔드포인트와 쿼리 매개변수 "https //postman echo com/post?argkey=argvalue", // json 요청 본문 { "datakey" "datavalue" }, // 요청 콘텐츠 유형 httpcontenttype applicationjson, // http 헤더 { "header key" "header value" }) then((httpresponse) => { if (httpresponse statuscode != 200) { throw (`api 오류 ${httpresponse statuscode} ${httpresponse statustext}`); } return httpresponse response; }) then((response) => { let parsed = json parse(response); console log(`쿼리 매개변수 argkey ${parsed args argkey}`); console log(`요청 본문 datakey ${parsed data datakey}`); console log(`요청 헤더 header key ${parsed headers\["header key"]}`) }) catch((reason) => { console log("api 요청 오류"); console log(reason); }); } } 코드 설명 클라이언트가 멀티플레이 룸에 연결될 때, echopost 함수가 onjoin 트리거에서 호출됩니다 postasync 요청을 만들 때 첫 번째 매개변수에서 쿼리 매개변수를 포함한 url 문자열을 구성합니다 두 번째 매개변수에서 요청 본문 내용을 설정합니다 네 번째 매개변수에서 요청 헤더를 구성합니다 요청 본문이 json 형식임을 지정하기 위해 세 번째 매개변수에 'application/json' content type을 설정합니다 만약 postasync 호출이 성공하면, 우리는 httpresponse 객체에 접근할 수 있습니다 그 후 콜백에서 우리는 httpresponse response 를 파싱하여 api 응답을 json 형식에서 객체로 변환합니다 api 응답의 구조를 참조하여, 우리는 콘솔 출력을 사용하여 http 요청의 쿼리 매개변수, 요청 본문 및 요청 헤더가 올바르게 구성되었는지 확인합니다 unity 에디터에서 멀티플레이 서버를 실행하고 장면을 재생하면 콘솔에 다음과 같은 내용이 표시됩니다 쿼리 매개변수 argkey\ argvalue 요청 본문 datakey\ datavalue 요청 헤더 header key\ header value