본문 바로가기
유니티

HTTP 통신

by SUGI_ 2023. 8. 24.

실시간 통신 (Socket) - 포톤

클라이언트 - 서버 실시간으로 연결

한번 연결하면 계속 연결해놓은 상태로 유지 

계속 왔다갔다 주기적으로 체크

양방향 통신

 

서버 개발자가 어떤걸 선택하는냐에 따라 다름

TCP - 데이터를 주고 받을 때 전달하는 신뢰 (유실되지 않겠끔) (더 느리지만 정확)

UDP - 전달하는 데이터가 유실 (속도가 더 빠름)

 

Http 통신 (웹통신)

클라이언트 -----> 서버 요청 / 응답

서버가 먼저 클라이언트한테 줄 수 없음

단방향 통신

ex ) 주소 치면 서버한테 요청 / 응답받을 수 있음

REST API (주소 ex www.naver.com/login)

주소값을 통해서 통신을 하겠다

 

POST : 서버한테 데이터를 생성 (ex 유저정보 저장)

PUT : 서버한테 데이터를 업데이트 / 기존의 데이터를 수정

GET : 서버한테 데이터 요청 (ex 유저정보 주세요)
DELETE : 서버한테 데이터 삭제

 

서버들이 제작해놓은 url 을 주고 우리는 그 url을 사용하면 된다.

실무에서는 거의 POST GET만 사용 (서버에서 생성 수정을 해주는 식)

 

GET 실무.

 

 

테스트 가능한 사이

 

JSONPlaceholder - Free Fake REST API

{JSON} Placeholder Free fake API for testing and prototyping. Powered by JSON Server + LowDB. Tested with XV. Serving ~2 billion requests each month.

jsonplaceholder.typicode.com

using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using UnityEngine;
using UnityEngine.Networking;

//주소값
//https://jsonplaceholder.typicode.com
//예시
/*"postId": 1,
    "id": 1,
    "name": "id labore ex et quam laborum",
    "email": "Eliseo@gardner.biz",
    "body": "laudantium enim quasi est s\ntempiciendis et nam sapiente accusantium"*/


//통신관련 정보들은 한쪽에서 받기
[Serializable]
public class JsonList<T>
{
    public List<T> data;
}

#region 테스트용
[Serializable]

public struct CommentInfo
{
    public int postId;
    public int id;
    public string name;
    public string email;
    public string body;
}

//POST를 위한 임시값
[Serializable]
public struct SignUpInfo
{
    public string userName;
    public string brithDay;
    public int age;
}
#endregion

public enum RequestType
{
    GET,
    POST,
    PUT,
    DELETE,
    //이미지 다운로드
    TEXTURE
}

//웹 통신하기 위한 정보를 가지고 있는 클래스
public class HttpInfo
{
    public RequestType requestType;
    public string url = "";
    public string body; //json 형태로
    //using System; 필요 딜리게이트 함수를 담을 수 있는 있는 변수
    //어떤함수를 담을 것이지 
    public Action<DownloadHandler> onReceive;

    //useDefaultUrl = 디폴트 true
    public void Set(RequestType type, string u, 
        Action<DownloadHandler> callback, bool useDefaultUrl = true)
    {
        requestType = type;
        //조건을 걸어준다.
        if(useDefaultUrl) url = "https://jsonplaceholder.typicode.com";
        url += u;
        
        onReceive = callback;
    }
}

//받아서 요청
public class HttpManager : MonoBehaviour
{
    //public 삭제
    static HttpManager instance;

    //HttpManager return 하는 함수
    //1.
    public static HttpManager Get()
    {
        if(instance == null)
        {
            //게임오브젝트 생성 new
            GameObject go = new GameObject("HttpStudy");
            //만들어진 게임오브젝트에 HttpManager 컴포넌트 붙이자
            go.AddComponent<HttpManager>();
        }

        return instance;
    }

    //2.
    private void Awake()
    {
        if(instance == null)
        {
            instance = this;
            //없으면 붙겠끔 하는 코드도 넣어주기
            DontDestroyOnLoad(gameObject);
        }

        else
        {
            Destroy(gameObject);
        }
    }

    //서버에게 REST API 요청 (GET, POST, PUT, DELETE)
    public void SendRequest(HttpInfo httpInfo)
    {
        StartCoroutine(CoSendRequest(httpInfo));
    }

    //코루틴으로 보내야됨.
    //매개변수로 받아서 할 것임.
    IEnumerator CoSendRequest(HttpInfo httpInfo)
    {
        //※로딩바 돌게
        print("로딩바 도는 중");

        //웹 통신을 위한 using UnityEngine.Networking; 필요
        UnityWebRequest req = null;

        switch(httpInfo.requestType)
        {
            case RequestType.GET:
                //Get방식으로 req에 정보 셋팅 
                //req = UnityWebRequest.Get(주소값)
                req = UnityWebRequest.Get(httpInfo.url);
                break;
            case RequestType.POST: //body, 헤더 필요
                req = UnityWebRequest.PostWwwForm(httpInfo.url, httpInfo.body);
                //byte [] 배열로 만들어야 한다 (using System.Text; 필요)
                byte[] byteBody = Encoding.UTF8.GetBytes(httpInfo.body);
                req.uploadHandler = new UploadHandlerRaw(byteBody);

                //post는 헤더 추가해야함 (키 벨류) 여러개 등록할 수 있음 ++
                req.SetRequestHeader("Content-Type","application/json");

                break;
            case RequestType.PUT:
                req = UnityWebRequest.Put(httpInfo.url, "");
                break;
            case RequestType.DELETE:
                req = UnityWebRequest.Delete(httpInfo.url);
                break;
            case RequestType.TEXTURE: //이미지다운로드
                req = UnityWebRequestTexture.GetTexture(httpInfo.url);
                break;
        }

        //서버에 요청을 보내고 응답이 올때까지 양보한다.
        yield return req.SendWebRequest();

        //응답도 Action을 통해서 할 것임.
        //성공 or 실패
        //만약에 응답이 성공했다면
        if(req.result == UnityWebRequest.Result.Success)
        {
            //응답에 성공했을 때 req.downloandHandler.text 응답 받은 내용이 담겨져 있음
            //print("네트워크 응답 : " + req.downloadHandler.text);

            if(httpInfo.onReceive != null)
            {
                httpInfo.onReceive(req.downloadHandler);
            }
        }

        //통신 실패
        else
        {
            print("네트워크 에러 : " + req.error);
        }

        //※로딩바 끝나게
        print("로딩바 끝남");
    }
}
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;

public class UIManager : MonoBehaviour
{
    public Image downloadImage;

    public void OnClickGet()
    {
        //todos
        HttpInfo info = new HttpInfo();

        info.Set(RequestType.GET, "/todos", OnReceiveGet);

        //OnReceiveGet -> 람다식으로 무명함수 넣을 수 있음
        /*info.Set(RequestType.GET, "/todos", (DownloadHandler downloadHandler) =>
        {
            print("OnReceiveGet" + downloadHandler.text);
        });*/

        //info의 정보를 요청을 보내자
        HttpManager.Get().SendRequest(info);
    }

    //using UnityEngine.Networking; 필요
    void OnReceiveGet(DownloadHandler downloadHandler)
    {
        print("OnReceiveGet" + downloadHandler.text);
    }

    public List<CommentInfo> comments;

    public void OnClickComment()
    {
        //todos
        HttpInfo info = new HttpInfo();

        //info.Set(RequestType.GET, "/todos", OnReceiveGet);

        //OnReceiveGet -> 람다식으로 무명함수 넣을 수 있음
        info.Set(RequestType.GET, "/comments", (DownloadHandler downloadHandler) =>
        {
            print("코멘트 리스트" + downloadHandler.text);

            //Json 데이터로 가공
            //"{\ 문자열안에 스트링으로 인식함
            string jsonData = "{\"data\" : " + downloadHandler.text + "}";

            JsonList<CommentInfo> commentList =  JsonUtility.FromJson<JsonList<CommentInfo>>(jsonData);

            comments = commentList.data;
        });

        //info의 정보를 요청을 보내자
        HttpManager.Get().SendRequest(info);
    }

    public void PostTest()
    {
        HttpInfo info = new HttpInfo();
        info.Set(RequestType.POST, "/sign_up", (DownloadHandler downloadHandeler) => { 
            //Post 데이터 전송했을 때 서버로부터 응답 옵니다.
        });

        SignUpInfo signUpInfo = new SignUpInfo();
        signUpInfo.userName = "김현진";
        signUpInfo.age = 25;
        signUpInfo.brithDay = "830410";

        //Json 데이터를 넣겠다.
        info.body = JsonUtility.ToJson(signUpInfo);

        HttpManager.Get().SendRequest(info);
    }

    public void OnClickDownloadImage()
    {
        //https://via.placeholder.com/150/92c952

        HttpInfo info = new HttpInfo();

        //기본 URL을 쓸 필요가 없다.
        info.Set(
            RequestType.TEXTURE,
            "https://item.kakaocdn.net/do/c838c164801d148d4fe09b83adada4c88f324a0b9c48f77dbce3a43bd11ce785",
            OnCompleteDownloadTexture, false);

        //info의 정보를 요청을 보내자
        HttpManager.Get().SendRequest(info);
    }

    //다운로드 된 이미지
    //텍스처는 Json 형태가 아님 색상정보
    void OnCompleteDownloadTexture(DownloadHandler downloadHandler)
    {
        //다운로드된 Image 데이터를 Sprite 로 만든다. //형변환
        //Texture2D -> Sprite
        Texture2D texture = ((DownloadHandlerTexture)downloadHandler).texture;
        //새로운 사각형
        downloadImage.sprite = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), Vector2.zero);
    }
}
728x90

'유니티' 카테고리의 다른 글

Firebase  (1) 2023.08.29
[유니티] 싱글톤만들기  (0) 2023.08.26
JSON (JavaScript Object Notation)  (1) 2023.08.23
[유니티] 파일저장  (0) 2023.08.23
[유니티] Joints  (0) 2023.08.17