본문 바로가기
IT

[Unity/Zepeto] Multiplay 서버에서 HTTP Get 통신 / 제페토 HTTP 통신

by 배애앰이 좋아 2024. 1. 17.
반응형

 

 

1. 아래 링크를 참고해서 기본적인 환경 설정을 해줍니다

 

제페토 공식 가이드 사이트 : https://docs.zepeto.me/studio/lang-ko/reference/httpservice

node.js 설치와 VScode 설치 : https://sinsucoding.tistory.com/2

추가 참고 : https://als2019.tistory.com/130

설치 이후 추가 서버 환경 설정 : https://plan2018.tistory.com/892

 


 

2. 위를 통해 웹과의 간단한 서버 통신 테스트가 끝났다면 제페토와 연결 테스트해보기

 

관련된 구조를 이해하기 위해서는 기존 예제를 가지고 따라하며 분석하면서 이해하기

제페토 예제에 쓰인 링크 : https://restcountries.com/v3.1/name/japan?fields=capital

 

 

위처럼 구조가 나오는 것을 확인할 수 있습니다. 제페토가 읽어 들이는 타입은 공식 가이드에 보듯이 5가지( ApplicationJson/ApplicationXml/ApplicationUrlEncoded/TextPlain/TextXml )를 읽어 들일 수 있는데 먼저 예제에서 주어진 json 타입으로 테스트를 하였습니다.

 

아래는 node.js 작성한 Sever Code :

 

const http = require("http");
var url = require('url');

const sever = http.createServer((req, res)=>{
    var reqUrl = req.url;   // 클라이언트로부터 요청이 온 urlStr
    var parsedUrl = url.parse(reqUrl, true);  // 요청받은 urlStr -> urlObj로 변환
    var pathname = parsedUrl.pathname; // 주소 이름
// 주소 이름 호출 : "http://localhost:3065/itemsCoin" 일 경우, pathname = /itemsCoin

    console.log(pathname);
    console.log(req.url, req.method);

    const result = [{
        "capital" : ["tokyo"]
    }];

    res.writeHead(200, {'Content-Type':'application/json'}); // 보내는 데이터 헤더 설정
    res.end(JSON.stringify(result)); // 실제 보내지는 데이터 내용 - body - 본론
});

sever.listen(3065, ()=>{
    console.log("서버 실행 중");
});

 

위의 원하는 값이 제대로 나오는지 웹페이지에서 확인해주면 좋습니다. 참고로 위 코드에서 주의 있게 봐야 하는 부분은 res.writeHead(200, {'Content-Type':'application/json'});JSON으로 보내준다는 것을 명시해줘야 합니다.

 

테스트 주소 : http://localhost:3065/

 

 

위처럼 나온다면 먼저 제페토 예제에서 제공한 웹사이트처럼 동일한 데이터를 보내는 것을 확인할 수 있습니다.

 

아래는 제페토 index.ts Code :

 

private findCapitalCity() {
        console.log('get findCapitalCity 1'); 
        HttpService.getAsync( // GET 타입이라는 것을 표기
            "http://localhost:3065/", // 보내는 서버 주소
            { 'Accept': HttpContentType.ApplicationJson }) // 타입
            // Handler for the HTTP Response   
            .then((httpResponse) => { // 데이터를 받았을 때
                console.log('get findCapitalCity 2');
                if (httpResponse.statusCode != 200) {
                    // If it was not 200(OK), do not proceed and raise a custom error
                    throw (`API Error: ${httpResponse.statusCode} ${httpResponse.statusText}`);
                }
                let countries = JSON.parse(httpResponse.response); // 받은 데이터 분해
                console.log("The capital city of Japan is:");
                console.log(`${countries[0].capital}`); // 데이터 일부 출력
            });
}

 

참고로 위 코드에서 주의 있게 봐야 하는 부분은 { 'Accept': HttpContentType.ApplicationJson }) 으로 위의 res.writeHead(200, {'Content-Type':'application/json'}); 와 동일한 타입이 되어야 오류가 나지 않는다.

 

테스트 했을 때 아래처럼 나오면 성공적이다.

 

 


 

위의 간단한 예제를 해봤으니 좀 더 복잡한 구조를 테스트 해볼 수 있습니다.

서버 주소의 이름을 다르게 해서 다른 값들을 들고 오는 것을 테스트 해보겠습니다.

 

// node.js code

const http = require("http");
var url = require('url');

const sever = http.createServer((req, res)=>{
    var reqUrl = req.url;   // 클라이언트로부터 요청이 온 urlStr
    var parsedUrl = url.parse(reqUrl, true);  // 요청받은 urlStr -> urlObj로 변환
    var pathname = parsedUrl.pathname;

    console.log(pathname);
    console.log(req.url, req.method);

    const itemsCoin = [{ // 여러 데이터 배열
        "band1" : ["10"],
        "band2" : ["5"]
    }];

    const monstersAttackPower = [{
        "BigTitan" : ["10"],
        "SmallTitan" : ["5"]
    }];

    if(pathname == '/itemsCoin') { // 받은 주소를 판별해서 데이터 보내기
        res.writeHead(200, {'Content-Type':'application/json'});
        res.end(JSON.stringify(itemsCoin));
    }else if(pathname == '/monstersAttackPower') {
        res.writeHead(200, {'Content-Type':'application/json'});
        res.end(JSON.stringify(monstersAttackPower));
    }else{
        // res.writeHead(404, {'Content-Type' : 'text/html'});
        // res.end('404 : NOT FOUND');
    }
    
});

sever.listen(3065, ()=>{
    console.log("서버 실행 중");
});

 

위 코드에서 주의 깊게 봐야 하는 점은 일단 배열을 여러 개 설정해서 보낸 점과 if(pathname == '/itemsCoin') 처럼 주소에 따라 보내는 값이 다르게 설정했다는 점입니다.

 

위 경우에 기존 http://localhost:3065/ 로 테스트를 하면 보내는 데이터가 없기 때문에 무한 로딩 또는 오류가 뜹니다.

 

위 코드에서 데이터를 얻기 위해서는 http://localhost:3065/monstersAttackPower 또는 http://localhost:3065/itemsCoin 처럼 pathname 으로 설정한 주소로 들어가야 합니다.

 

 

위처럼 나오면 성공적입니다.

 

// zepeto index.ts code

private findCapitalCity() {
				// 주소를 다르게 해서 받는 데이터를 다르게 테스트
        HttpService.getAsync(
            "http://localhost:3065/itemsCoin",
            { 'Accept': HttpContentType.ApplicationJson })
            .then((httpResponse) => {
                if (httpResponse.statusCode != 200) {
                    throw (`API Error: ${httpResponse.statusCode} ${httpResponse.statusText}`);
                }
                let itemsCoin = JSON.parse(httpResponse.response);
                console.log("The band1 of itemsCoin is:");
                console.log(`${itemsCoin[0].band1}`);
                console.log("The band2 of itemsCoin is:");
                console.log(`${itemsCoin[0].band2}`);
            }
        );

        HttpService.getAsync(
            "http://localhost:3065/monstersAttackPower",
            { 'Accept': HttpContentType.ApplicationJson })
            .then((httpResponse) => {
                if (httpResponse.statusCode != 200) {
                    throw (`API Error: ${httpResponse.statusCode} ${httpResponse.statusText}`);
                }
                let monstersAttackPower = JSON.parse(httpResponse.response);
                console.log("The SmallTitan of monstersAttackPower is:");
                console.log(`${monstersAttackPower[0].SmallTitan}`);
                console.log("The BigTitan of monstersAttackPower is:");
                console.log(`${monstersAttackPower[0].BigTitan}`);
            }
        );

    }

 

마찬가지로 그럼 index.ts 에서도 코드 변화가 필요합니다. 불려올 때 "http://localhost:3065/itemsCoin" 같은 주소가 바꿔야 하며 여러 배열을 보내기 때문에 console 에 찍은 것처럼 여러 값들을 조회할 수 있습니다.

 

 

위처럼 나오면 성공적입니다.

 

마지막으로 제페토 가이드를 보면 어디서 오류가 날지도 모르니 방어적으로 코드를 작성하라고 적혀 있습니다. 이 부분은 매우 중요합니다. 제페토 게임을 돌리다 보면 예민하고 사소한 부분에서 오류나 전체가 안 돌아가는 경우가 있기 때문입니다. 고로 위 코드 일부를 방어적 코드로 바꿔보면,

 

// zepeto index.ts code

HttpService.getAsync(
            "http://localhost:3065/itemsCoin",
            { 'Accept': HttpContentType.ApplicationJson })
            .then((httpResponse) => {
                if (httpResponse.statusCode != 200) {
                    throw (`API Error: ${httpResponse.statusCode} ${httpResponse.statusText}`);
                }
                return httpResponse.response;
            }).then((response) => {
                let itemsCoin = JSON.parse(response);
                if (!Array.isArray(itemsCoin) || !itemsCoin.length) {
                    // If it is not an array, or is empty
                    // do not proceed and raise a custom error
                    throw (`API Error: Response data is not valid`);
                }
                let item = itemsCoin[0];
                if (!item.band1 || !item.band2) {
                    throw (`API Error: 'capital' field not valid`);
                }
                console.log("The band1 of itemsCoin is:");
                console.log(`${itemsCoin[0].band1}`);
                console.log("The band2 of itemsCoin is:");
                console.log(`${itemsCoin[0].band2}`);
            }).catch((reason) => {
                console.log("API Request error");
                console.log(reason);
        });

 

위처럼 바꿀 수 있습니다.

 


 

위 테스트 하면서 주의할 점 :

 

http://localhost:3065/itemsCoinhttp://localhost:3065/itemsCoin/ 는 다릅니다. /를 붙임으로써 제대로 결과가 안 나올 수 있으니 꼭 주의하면서 테스트해야 합니다.

 

 

반응형

댓글