유니티 데이터베이스 연동 (Unity Database connection)

2020. 2. 5. 10:05기술/네트워크

반응형

데이터베이스를 사용하는 이유는 정보를 안전하게(보안) 저장하기 위함입니다.

PC나 스마트 기기에 정보 저장 시 손실 될 우려가 있고 해킹에 취약합니다.

진행 키워드를 알려드리고 이것은 전체적으로 훑어보는 방식으로 공부하는 것이며 지식의 뼈대입니다.

1. 웹호스팅

 - 웹호스팅이 무엇인지 익힙니다.

 - 생활코딩에서 필요 시 다른 지식도 공부합니다. 범위가 있으므로 필요한 정보만 보는 것이 중요합니다. 이해하기 쉽게 설명을 잘해주십니다.

 - 저는 닷홈으로 사용하며 공부용도이므로 무료로 사용합니다. 아마존(AWS)은 결제정보를 입력해야 해서 번거롭습니다.

 - 추후 다른 웹호스팅을 이용해도 되고 아마존을 이용해도 되는데 일단 어딘가에 파일을 올리고 php가 동작하게끔 해주는 것이 중요합니다.

 - 마이닷홈에서 웹서버/FTP 정보, DB 정보 등을 알 수 있습니다.

 - 웹서버 아이피(IP)를 잘 알아두는 게 중요합니다.

2. 파일질라

 - 파일질라 프로그램을 설치합니다.

 - 웹서버에 폴더 만들기 파일 업로드 등을 편리하게 해주는 프로그램입니다.

 - (참고) 유니티 에셋번들 파일을 올리고 다운로드하는 테스트도 할 수 있습니다.

3. phpMyAdmin

 - 마이닷홈 > 제공 내역 > MySQL관리에서 phpMyAdmin에 접속할 수 있습니다.

 - 접속 시 아이디 비밀번호를 잘 알아두세요.

 - user 테이블을 만듭니다. 열(id, name)

 - 정보를 넣습니다. (SQL문 INSERT)

4. Bitnami

 - Bitnami를 설치합니다. APMSetup인지 Bitnami인지 중요하지 않고 APM(Apache, PHP, MySql) 실행환경을 만드는 것이 중요합니다. (방법) 

 - 내 컴퓨터(클라이언트 측)에서 php와 데이터베이스를 사용할 수 있게 합니다. 웹호스팅을 이용할 경우 웹서버에도 설치되어 있겠습니다. php 파일 작성 후 잘 동작하는지 내컴퓨터에서 확인합니다. 미설치시 테스트하려면 웹서버에 항상 업로드해야 하기 때문에 번거롭습니다.

 - 콘솔창으로 mysql에 접속해도 되지만 phpMyAdmin을 이용해서 데이터베이스를 확인해봅니다.

Bitnami 설치 폴더에 있는 manager-windows.exe 실행 시

 - phpMyAdmin 로그인 시 사용자명은 root이고 암호는 Bitnami 설치 시 입력한 암호입니다.

 - 3번에서 진행 했었던 데이터베이스와 테이블을 클라이언트 측에서 만들 수 있습니다.

 - 간단한 php 파일을 작성하여 실행해봅니다.

C:\Bitnami\wampstack-7.3.13-0\apache2\htdocs\firstapp\helloworld.php가 있다면 크롬과 같은 웹프로그램에서 http://localhost/firstapp/helloworld.php을 입력하면 php 파일을 실행할 수 있습니다.

 - C언어의 printf()라고 할 수 있는 php의 ehco 명령어로 웹페이지에 Hello world를 출력해봅니다.

 - 저는 php 에디터로 Visual Studio Code 프로그램을 사용합니다.

 - 웹서버에서 말고 내컴퓨터에서 테스트해보기 위해 3번과 동일하게 클라이언트 측의 데이터베이스 세팅을 하고 SQL INSERT를 사용하여 정보를 넣습니다. 즉, 정보는 내컴퓨터(클라이언트측)과 닷홈(웹서버)에 2가지로 동일한 정보가 존재하게 됩니다.

5. PHP

 - 위에서 만든 id, name 정보를 웹프로그램에 출력해봅니다.

 - php 기초 함수를 익혀야합니다.

 - php만 사용하려면 HTML 관련 문법은 필요하지 않습니다.

 - helloworld.php 파일을 클라이언트측 (http://localhost/firstapp/helloworld2.php)에서 실행하면 내컴퓨터 데이터베이스에 저장된 정보를 보여줍니다.

 - 파일질라를 사용하여 닷홈에 업로드하고 id, pw를 정확하게 입력한 후 닷홈url을 통해 php를 실행하면 (http://(your_account).dothome.co.kr/firstapp/helloworld.php) 데이터베이스에 입력한 정보를 가지고 올 수 있습니다.

 - 주요함수 mysqli_fetch_assoc

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
<?php
 
// 문자열 출력 \n<br>은 개행
echo "Hello World\n<br>";
 
// 외부로 부터 변수값 얻어오기
$param1 = $_POST['param1'];
$param2 = $_POST['param2'];
 
// 주석처리 하는 방법
//$conn = mysqli_connect("localhost", "webserver_id", "webserver_pw");
$conn = mysqli_connect("localhost""local_id""local_pw");
mysqli_query($conn'SET NAMES utf8');
 
if (!mysqli_select_db($conn"database_name"))
{
    echo "Unable to select mydbname: " .mysql_error();
    exit;
}
 
$sql = "SELECT * FROM user(table_name) LIMIT 10";
 
$result = mysqli_query($conn$sql);
 
if (!$result)
{
    echo "Could not successfully run query ($sql) from DB: " . mysql_error();
    exit;
}
 
if (mysqli_num_rows($result== 0)
{
    echo "No rows found, nothing to print so am exiting";
    exit;
}
 
while ($row = mysqli_fetch_assoc($result))
{
    // 테이블에 만들어 놓은 id행과 name행의 정보
    echo "{$row['id']} {$row['name']}\n<br>";
}
?>
cs

 - 보통 데이터는 byte[]나 json을 이용하는데 json을 이용해 보겠습니다. php에서 json 문자열을 만드는 로직을 작성합니다. (json_encode 사용)

 6. 유니티

 - 유니티에서 데이터베이스의 정보를 가져옵니다.

 - 유니티 JsonUtility는 Dictionary 같은 자료구조는 변환이 안 되는 기본적인 기능만 제공하니 JsonFX를 사용합니다.

 - json 문자열을 class로 변환해 주는 사이트 http://json2csharp.com/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
using System.Collections;
using System.Collections.Generic;
using UnityEngine.Networking;
using UnityEngine;
using UnityEngine.UI;
 
public class TestPhp : MonoBehaviour
{
    [SerializeField]
    Text message = null;
 
    [SerializeField]
    Text m_UserData = null;
 
    public class ResUserData
    {
        // 배열이 아니고 꼭 리스트로 해야합니다.
        public List<UserData> UserData;
    }
 
    public class UserData
    {
        public string id;
        public string name;
    }
 
    void Start()
    {
        StartCoroutine(GetUserData());
    }
 
    IEnumerator GetUserData()
    {
        // php로 값 전달하기
        WWWForm form = new WWWForm();
        form.AddField("param1""2");
        form.AddField("param1""유저이름2");
 
        // Webserver
        //using (UnityWebRequest www = UnityWebRequest.Post("http://your_account.dothome.co.kr/firstapp/helloworld.php", form))
        
        // Local
        using (UnityWebRequest www = UnityWebRequest.Post("http://localhost/firstapp/helloworld.php", form))
        {
            yield return www.SendWebRequest();
 
            if (www.isNetworkError || www.isHttpError)
            {
                Debug.Log(www.error);
            }
            else
            {
                string data = www.downloadHandler.text;
                Debug.Log(data);
                message.text = data;
                ResUserData res = JsonFx.Json.JsonReader.Deserialize<ResUserData>(data);
 
                string szUser = "";
                foreach (UserData userData in res.UserData)
                {
                    szUser += userData.id + " ";
                    szUser += userData.name + "\r\n";
                }
 
                m_UserData.text = szUser;
            }
        }
    }
}
cs

 7. 보안과 데이터 최적화

 - 마지막으로 데이터 전송/수신 시 json 문자열을 암호화/복호화해 주어야 합니다. (예:AES_256 암호화)

 - 데이터 최적화 : 전송/수신 시 데이터를 최적화 하려면 byte 배열이 더 좋아보입니다. json vs byte array 구글 검색을 하면 장단점에 대해 알 수 있습니다. json은 개발자 가독성이 좋으며 byte array는 데이터가 작습니다. byte에 bit 연산으로 데이터스트림을 더 작게 만들 수도 있습니다.

 - byte 배열로 데이터를 저장/읽기 할 경우 클래스에 변수가 추가 된다거나 했을 때 코드 관리하기가 조금 어려워질 수 있습니다. byte 배열 스트림에 맞춰야 하기 때문입니다. (해결방법은 try catch로 바이트 읽기) json이 코드 관리면에서는 편리합니다.

 - 저는 byte 배열 + 데이터를 보고 수정할 수 있는 툴이 있는게 좋다고 생각합니다.

 

 다음 테스트 코드를 실행 했을 때 캐릭터 데이터의 byte Level을 전송하기 위해서 json은 11bytes가 필요합니다. 보통 json 문자열에 한글이 포함되어 있는 경우가 있어서 UTF8로 변환하기 때문에 "Level" 문자열에서 하나의 문자 표현에 2byte를 사용합니다.

 

 반면 byte 스트림을 이용하면 1byte면 충분합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
    public class CharacterData
    {
        public byte Level;
    }
 
    public void TestClassToJson()
    {
        CharacterData chrData = new CharacterData();
        chrData.Level = 4;
 
        string json = JsonWriter.Serialize(chrData);
 
        byte[] jsonByte = Encoding.UTF8.GetBytes(json);
 
        Debug.LogFormat("json is {0}, jsonByte length is {1}", json, jsonByte.Length);
    }
 
    public void TestDataStream()
    {
        DataStream dataStream = new DataStream();
        CharacterData chrData = new CharacterData();
        chrData.Level = 4;
 
        dataStream.Write(chrData.Level);
 
        Debug.LogFormat("DataStream length is {0}", dataStream.Size);
    }
cs

 

 - Bit로 표현할 수 있는 데이터

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
    public enum ePeopleBit
    {
        // Bit Flag 예)
        NONE        = 0,
        MALE        = (1 << 0),
        NPC         = (1 << 1),
        KOREAN      = (1 << 2),
        SOMEBIT_A   = (1 << 3),
        SOMEBIT_B   = (1 << 4),
        SOMEBIT_C   = (1 << 5),
        SOMEBIT_D   = (1 << 6),
        FINAL       = (1 << 7),
        // 1 << 8 은 256이므로 byte max 255를 초과하므로 사용불가
    }
 
    public class People
    {
        byte PeopleInfo = 0;
 
        public ePeopleBit Info { get { return (ePeopleBit)PeopleInfo; } }
 
        public void SetPeople(ePeopleBit people)
        {
            PeopleInfo |= (byte)people;
        }
 
        public bool GetPeopleInfo(ePeopleBit people)
        {
            return ((ePeopleBit)(PeopleInfo & (byte)people) == people);
        }
    }
 
    public void TestBit()
    {
        People people = new People();
        people.SetPeople(ePeopleBit.MALE | ePeopleBit.KOREAN | ePeopleBit.FINAL);
        bool IsMALE = people.GetPeopleInfo(ePeopleBit.MALE);
        bool IsFinalBit = people.GetPeopleInfo(ePeopleBit.FINAL);
        Debug.LogFormat("PeopleInfo {0}, IsMale {1}, IsFinal {2}", people.Info, IsMALE, IsFinalBit);
 
        // 예)
        // int is 4byte (32bit)
        // 0000 0000 0000 0000 0000 0000 0000 0000
        //int MapClear1   = 0x0100;   // 0001 0000 0000
        //int MapClear2   = 0x0200;   // 0010 0000 0000
 
        //// ushort is 2byte (16bit)
        //// 0000 0000 0000 1111
        //ushort EquipInfo = 0;
        //ushort Helmet = 1;          // 1
        //ushort Armor = (1 << 1);    // 2
        //ushort Boots = (2 << 1);    // 4
        //ushort Glove = (4 << 1);    // 8
        //EquipInfo = (ushort)(Helmet | Armor | Boots | Glove);
    }
cs

 


반응형

'기술 > 네트워크' 카테고리의 다른 글

푸시 알림 유니티 (Notification Unity)  (0) 2021.12.24
파이어베이스 (Firebase)  (0) 2021.06.02
프라우드넷 스터디 2  (0) 2017.10.25
N vs N 네트워크 게임  (0) 2017.10.18
프라우드넷 스터디 1  (0) 2017.08.01