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