[관계형 DB] 플레이어 정보를 저장하는 방법: (1) JSON, XML을 하나의 필드에 저장, (2) 여러 테이블로 나누기

Jin Hur·2022년 7월 17일
0

Server Programming

목록 보기
11/14

트리 형태(구조체와 목록의 집합)의 플레이어 데이터

플레이어 데이터는 다양한 형태의 데이터 구조로 되어있다.
최상위에는 ID, 암호화된 비밀번호, 실제 이름 같은 플레이어 자신의 정보가 있다.
그 밑에는 플레이어가 가진 플레이어 캐릭터가 하나 이상이 있다. 캐릭터의 이름과 플레이어 종족, 레벨, 기타 능력치 등이 있다.
그리고 다시 그 밑에는 캐릭터가 소지한 아이템이 있고, 아이템의 종류, 개수, 여러 가지 속성 등이 있을 것이다.
즉, 플레이어 데이터는 "구조체와 목록의 집합"이라고 할 수 있다.

구조체와 목록의 집합 형태로 되어 있는 데이터 덩어리는 트리 형태로 표현할 수 있다.
이 트리 형태의 데이터를 DB에 저장하는 방법은 크게 두 가지가 있다.

  • 1. 플레이어 데이터 전체를 문서 형태로 만들어서 테이블에 넣는다.
  • 2. 플레이어 데이터를 구성하는 트리 노드 각각을 테이블에 넣는다.

1. JSON 문서 형태로 DB에 저장

플레이어 데이터를 문서 형태로 만들면 JSON 문서 형태로 나온다. JSON 문서는 트리 구조의 데이터를 "문자열" 형태로 표현하며, 트리의 각 노드는 속성을 여러 개 저장할 수 있다.

{
    "id": "Hong Gil Dong",
    "email": "gildong@foofoomail.com",
    "password": "xxiuasdofija",
    "Characters": [
        {
          	// 캐릭터 1
            "name": "Littel_Elf",
            "gender": "Female",
            "level": 35,
            "Items": [ 
                {
                    "type": 123,
                    "amount": 1
                }
            ]
        },
        {
          	// 캐릭터 2
            "name": "Big_Orc",
            "gender": "Male",
            "level": 23,
            "Items": []
        }
    ]
}

플레이어 정보를 위와 같은 JSON 형태 하나로 만든 후 테이블에 저장한다. 플레이어 ID(key)와 플레이어의 JSON 텍스트를 담을 필드 형태이다.

참고로 JSON 텍스트를 담을 필드 타입은 varchar보다는 text 타입이 적합하다. JSON 문자열의 길이가 얼마나 길어질지 장담할 수 없기 때문이다.
JSON이나 XML 중 어느 것도 지원하지 않는 데이터베이스를 사용하고 있을 때는 글자 수 제한이 없는 text 필드 타입을 사용한다.

JSON 대신 XML 형식을 사용해도 된다. XML도 JSON과 마찬가지로 트리 노드와 각 노드의 속성을 저장하는 것이 가능하기 때문이다. 앞서 예로 들었던 JSON 문서를 XML로 변환하면 다음과 같다.

<?xml version="1.0" encoding="UTF-8"?>
    <id>Hong Gil Dong</id>
    <email>"gildong@foofoomail.com"</email>
    <password>"xxiuasdofija"</password>
    <Characters>
        <name>"Littel_Elf"</name>
        <gender>"Female"</gender>
        <level>35</level>
        <Items>
            <type>123</type>
            <amount>1</amount
        </Items>
    </Characters>
    <Characters>
        <name>"Big_Orc"</name>
        <gender>"Male"</gender>
        <level>23</level>
    </Characters>

2. 플레이어 데이터 정보를 여러 테이블로 나누어 저장

JSON이나 XML로 플레이어 정보를 저장하는 방식은 이해하기 쉽다는 장점이 있지만, 플레이어 정보 중에서 원하는 조건 값을 자주 찾아야 할 때는 한계가 있을 수 있다. 이러한 경우 플레이어의 데이터 정보를 여러 테이블에 나누어 저장하면 효과적일 수 있다.

트리의 각 노드(플레이어 노드, 캐릭터 노드)는 속성을 여러 개 가지고 있다. 따라서 각 노드는 데이터베이스의 레코드로 저장한다.

(1) 플레이어 정보 저장 테이블: UserAccount

IDPasswordEtc
Hong Gil Dongxxx...
Hur Jinxxx...

이때 플레이어 ID는 서로 중복되지 않아야 한다. ID 필드에 프라이머리 키를 설정하거나, 유니크 속성이 들어 있는 인덱스를 추가해준다.

(2) 캐릭터 정보 저장 테이블: Character

NameOwnerUserAccountIDgenderlevelEtc
Littel_ElfHong Gil DongFemale35...
Big_OrcHong Gil DongMale23...

데이터베이스의 어떤 테이블을 넣어야 할지 계획을 잡을 때 자주 사용하는 방식은 외래 키를 사용하는 것이다.

플레이어는 플레이어 캐릭터를 여러 개 가지고 있다. 플레이어 캐릭터를 테이블에 저장할 때 플레이어 캐릭터의 고유 이름으로 Name 뿐 아니라 플레이어 ID도 저장하여 "Hong Gil Dong은 캐릭터 Little_Elf아 Big_Orc를 가진다"라고 표현할 수 있다.

OwnerUserAccountID라는 필드는 플레이어 정보를 담은 UserAccout 테이블의 레코드를 가리켜야 한다. 플레이어 테이블 중 고윳값이 보장되는 것은 현재 프라이머리 키로 설정해 놓은 'ID'이다. 따라서 OwnerUserAccountID 필드는 UserAccount의 ID 필드를 가리켜야 한다. 이를 정리해서 말하자면, OwnerUserAccoutID는 UserAccout의 ID 필드를 가리키는 외래 키이다.

마찬가리로 아이템 테이블은 캐릭터 테이블의 캐릭터 레코드를 가리키는 OwnerCharacterID와 같은 외래 키 필드가 있을 것이다.

TypeAmountOwnerCharacterNameEtc
1231Little_Elf...

각 노드의 소유자, 즉 부모 노드는 외래 키가 된다.

외래 키 사용

외래 키를 갖고 특정 레코드를 찾는 시도를 많이 한다. 따라서 외래 키에 대해서 "인덱스"를 설정하는 것이 좋다. 다만 여기서 외래 키는 중복을 허락해야 하므로 논-유니크 인덱스(nonunique index)로 설정해야 한다.

0개의 댓글