[뒤끝팁] 랜덤 조회 활용 백서, 친구/길드 추천 만들기

안녕하세요 개발자 여러분!🙋‍♀️
개발이 필요 없는 게임 서버, 뒤끝입니다.

오늘은 뒤끝 랜덤 조회 기능으로 ‘친구/길드 추천 기능’ 구현하는 법을 한 번에 소개 드릴게요😊

목차

1. 친구 추천 만들기 👧🏻👦🏻

사전 준비 안내

친구 추천 만들기 예제에서는 아래 두 가지 기능을 활용합니다.

① 게임 정보 기능
② 랜덤 조회 기능

우선 본격적으로 게임 로직을 구현하기 전에, 초기에 세팅해야 할 몇 가지를 짚어보겠습니다.

1. 프로필을 등록할 게임 정보 테이블 생성
게임 정보 테이블 생성 화면

[게임 정보 관리] 메뉴에서 프로필을 보여줄 Public 테이블을 생성합니다.
프로필은 게임 내에서 타인에게 노출되는 부분이므로, Private가 아닌 Public으로 설정합니다.

2. 친구 추천용 랜덤 테이블 생성

아래 메뉴를 통해, ‘랜덤 조회 생성’ 버튼을 눌러 랜덤 조회를 생성합니다.
💡 [뒤끝 콘솔] > [뒤끝베이스] > [랜덤 조회]

랜덤 조회 생성 팝업
생성된 UUID

여기서 생성된 UUID는 이후에 데이터를 등록하거나 불러올 때 사용됩니다.

게임 로직

모두 준비가 되셨다면, 이제 유니티에서 다음과 같이 리스트 형태로 친구가 추천되도록
구현해 보겠습니다.

유니티 친구 리스트 구현 예시
1. 프로필에 등록할 게임 정보 데이터 생성
유니티 친구 추천 오브젝트

위 이미지는 유니티에서 친구 추천 창에 띄워 줄 오브젝트입니다.
이 프로필에는 다음 정보들을 보여주려고 합니다.

  • 프로필 사진
  • 유저 레벨
  • 닉네임
  • 자기소개 글

그리고 이 데이터를 PROFILE 테이블에 저장하도록 하겠습니다. 추가로 데이터 등록이 완료되었으면 level의 값을 랜덤 테이블에도 저장합니다.

아래 로직으로 회원 가입 시 해당 데이터가 등록되도록 한다면, 모든 유저가 추가되겠죠?

				
					int level = 1;

// 프로필 아이디는 로컬에 저장된 프로필 이미지 도감의 번호에 맞게 이미지를 가져오는 값입니다.
// 해당 예제에서는 이미지가 부족하여 숫자에 맞게 프로필 이미지의 색이 변하는 로직으로 대체했습니다.
int profile_id = rand.Next(0, 3);

Param param = new Param();
param.Add("profile_id", profile_id);
param.Add("level", level);
param.Add("content", $"안녕하세요. {Backend.UserNickName}입니다. 잘부탁드립니다.");
param.Add("nickName", Backend.UserNickName);

var bro = Backend.GameData.Insert("PROFILE", param);

if (bro.IsSuccess() == false) {
	Debug.LogError("데이터 등록 중 에러가 발생했습니다. " + bro);
	return;
}

// 랜덤 데이터 등록
bro = Backend.RandomInfo.SetRandomData(RandomType.User, "b24d7f40-7437-11ed-8567-b5ba2f1d82d9", level);

if (bro.IsSuccess() == false) {
	Debug.LogError("랜덤 데이터 등록 중 에러가 발생했습니다. : " + bro);
}
				
			
2. 추천 친구 리스트 불러오기

이제 처음에 등록했던 두 데이터를 이용해서, 추천 친구 리스트 UI를 만들어 보겠습니다.
로직은 다음과 같습니다.

  1. 랜덤 테이블 조회를 통해 랜덤 유저 inDate 가져오기
  2. 트랜잭션 리스트에 where.Equal(”owner_inDate”, 유저 inDate)를 가진 Get 트랜잭션 추가
  3. 트랜잭션 읽기 실행
  4. 트랜잭션의 리턴 값으로 나온 데이터들 친구 추천 오브젝트에 적용
				
					int myLevel = 1; // 내 레벨

// 1. 랜덤 테이블 조회를 통해 랜덤 유저 inDate 가져오기
var bro = Backend.RandomInfo.GetRandomData(RandomType.User, "b24d7f40-7437-11ed-8567-b5ba2f1d82d9" , myLevel, 5, 10);

if (bro.IsSuccess() == false) {
    Debug.LogError("랜덤 조회중 에러가 발생했습니다. : " + bro);
}

List<TransactionValue> transactionValues = new List<TransactionValue>();

for (int i = 0; i < bro.Rows().Count; i++) {
    Where where = new Where();
    
//2. 트랜잭션 리스트에 where.Equal(”owner_inDate”, 유저 inDate)를 가진 Get 트랜잭션 추가
where.Equal("owner_inDate", bro.Rows()[i]["gamerInDate"].ToString());

    transactionValues.Add(TransactionValue.SetGet("PROFILE", where));

    if (transactionValues.Count > 10) {
        break;
    }
}

// 3. 트랜잭션 읽기 실행
bro = Backend.GameData.TransactionReadV2(transactionValues);

if (bro.IsSuccess()) {
    //트랜잭션의 리턴값으로 나온 데이터들 친구 추천 오브젝트에 적용
    foreach (JsonData gameDataJson in bro.GetFlattenJSON()["Responses"]) {
        var friendObject = Instantiate(_friendItemObject, _userListGameObject.transform, true);
        if (friendObject.GetComponent<ItemObject>().Initialize(gameDataJson) == false) {
            Destroy(friendObject);
        }
    }
}
else {
    Debug.LogError("트랜잭션 읽어오기 도중 에러가 발생했습니다." + bro);
}


Debug.Log("랜덤 유저 불러오기가 완료되었습니다.");
				
			

그리고 프로필을 나타내는 오브젝트의 스크립트는 다음과 같습니다.

				
					public class ItemObject : MonoBehaviour {

    [SerializeField] private Image _userProfile;
    [SerializeField] private Text _userName;
    [SerializeField] private Text _userContent;
    [SerializeField] private Text _userLevel;
    [SerializeField] private Button _requestFriendButton;
    
    
    string _userInDate = String.Empty;

    public bool Initialize(JsonData userDataJson) {
        try {
            
            int profileId = int.Parse(userDataJson["profile_id"].ToString());
            _userLevel.text = userDataJson["level"].ToString();
            _userContent.text = userDataJson["content"].ToString();

            _userName.text = userDataJson["nickName"].ToString();
            _userInDate = userDataJson["owner_inDate"].ToString();

            switch (profileId) {
                case 0:
                    _userProfile.color = Color.blue;
                    break;
                case 1:
                    _userProfile.color = Color.yellow;
                    break;
                case 2:
                    _userProfile.color = Color.green;
                    break;
                
            }
            
            
            _requestFriendButton.onClick.AddListener( () => {
                var bro = Backend.Friend. RequestFriend(_userInDate);
                if (bro.IsSuccess()) {
                    Debug.Log("친구 요청을 보냈습니다");
                }
                else {
                    Debug.LogError("친구 요청을 보내지 못했습니다.");
                }

                _requestFriendButton.enabled = true;
                _requestFriendButton.name = "요청됨";
            });
            
            return true;
        }
        catch (Exception e) {
            Debug.LogError("데이터 파싱중 에러가 발생하였습니다. : " + e);
            return false;
        }
    }
}
				
			
3. 결과

오늘 안내드린 순서로 작업을 해 보시면, 아래와 같은 결과 화면을 확인하실 수 있습니다.

친구추천 인게임 UI

랜덤 테이블에서 검색된 유저 수만큼 트랜잭션을 불러오고, 그 데이터를 친구 추천 오브젝트에 적용시켜 보여주게 되는 것입니다.😊

2. 길드 추천 만들기 🛡️🏹

참고사항🚨

'길드 추천 만들기'는 1번의 친구 추천 만들기와 비슷한 구조로 진행이 될 텐데요. 
'길드 추천'은 친구 추천과 다르게 
트랜잭션 기능을 제공하지 않고 있습니다. 

그렇기 때문에 지나친 함수 호출에 주의해 주셔야 하는데요. 유저의 새로고침 등으로 인한 연속적인 랜덤 조회 시도는 요금 과다 청구 및 
403 Forbidden 에러를 발생 시킬 수 있으므로, 호출 수에 제한을 걸어두시는 것을 추천 드립니다.

사전 준비 안내

역시나 이번 예제에서도  랜덤 조회 기능을 활용합니다.

본격적으로 길드를 랜덤으로 추천하는 게임 로직을 구현하기에 앞서, 먼저 추천할 길드의 랜덤 리스트가 준비되어 있어야 하겠죠?

1. 길드 랜덤 테이블 생성

아래 메뉴를 통해, ‘랜덤 조회 생성’ 버튼을 눌러 랜덤 조회를 생성합니다.
💡 [뒤끝 콘솔] > [뒤끝베이스] > [랜덤 조회]

뒤끝 콘솔 길드 랜덤 테이블 생성
생성된 UUID

여기서 생성된 UUID는 길드의 레벨 데이터 변경 시 등록, 또는 길드를 랜덤으로 호출할 때 사용됩니다.

게임 로직

모두 준비가 되셨다면, 이제 유니티에서 다음과 같이 리스트 형태로 추천되는 길드를 나열해 볼 겁니다.

길드 추천 예시 화면
1. 추천 오브젝트에 보여줄 메타 정보를 가진 길드 생성
추천할 길드 정보

위 이미지는 유니티에서 길드 추천 창에 띄워 줄 오브젝트입니다.
이 프로필에는 다음 정보들을 보여주려고 합니다. (길드 생성 시, 일반적으로 필요한 기본 정보입니다)

  • 프로필 사진
  • 길드의 레벨 (메타정보)
  • 길드 이름 (인원/최대 인원)
  • 길드 소개 글

그리고 위 정보들을 보여주기 위한 데이터를 넣어줍니다.

				
					int level = 1;

// 프로필 아이디는 로컬에 저장된 프로필 이미지 도감의 번호에 맞게 이미지를 가져오는 값입니다.
// 해당 예제에서는 이미지가 부족하여 숫자에 맞게 프로필 이미지의 색이 변하는 로직으로 대체했습니다.
int profile_id = Random.Range(0, 3);

// 이후 UI 오브젝트로 보여줄 데이터들입니다.
Param param = new Param();
param.Add("profile_id", profile_id);
param.Add("level", level);
param.Add("content", $"{name} 길드입니다. 잘부탁드립니다.");

var bro = Backend.Guild.CreateGuildV3("원하는 길드 이름", 10, param);

if (bro.IsSuccess() == false) {
	Debug.LogError("길드 생성 중 에러가 발생했습니다. " + bro);
	return;
}

bro = Backend.RandomInfo.SetRandomData(RandomType.Guild, "246af8f0-7505-11ed-a50e-5beec811ecdf", level);
if (bro.IsSuccess() == false) {
	Debug.LogError("랜덤 데이터 등록 중 에러가 발생했습니다. : " + bro);
}
				
			

위 로직대로라면 길드를 생성할 때 profile_id, level, content가 같이 생성되겠지요? 😃
그리고 마지막에는 랜덤 삽입 함수를 이용하여 위에서 만든 길드 랜덤 테이블에 데이터를 넣어줍니다.

2. 랜덤 길드 불러오기

위 로직이 잘 적용되었다면, 길드를 생성할 때마다 랜덤 테이블에 길드 데이터가 차곡차곡 쌓이게 됩니다. 충분한 데이터가 쌓였다면, 이제는 렌덤 테이블에서 길드들을 불러올 차례인데요!

 불러오는 로직은 다음과 같습니다.

  1. 길드 랜덤 조회를 통해, 랜덤 길드 inDate 가져오기
  2. GetGuildInfoV3()를 통해 랜덤 조회에서 불러온 길드 검색
  3. 검색된 데이터들을 길드 추천 오브젝트에 적용
				
					int recommandLevel = 1;

// 길드 랜덤 조회(보여주는 길드는 3개이지만 여분으로 5개까지 호출하였습니다.)
bro = Backend.RandomInfo.GetRandomData(RandomType.Guild, "246af8f0-7505-11ed-a50e-5beec811ecdf" , recommandLevel, 5, 5);

if (bro.IsSuccess() == false) {
    Debug.LogError("랜덤 조회중 에러가 발생했습니다. : " + bro);
}

Debug.Log("랜덤 조회에 성공했습니다. : " + bro);

// 보여줄 길드는 3개지만 파싱 중 에러가 발생하는 길드가 있을 수 있으므로 5개까지 불러왔습니다.
// 해당 값을 통해 3개까지 체크 후, 길드 파싱을 종료합니다.
int maxGuildListCount = 0;

foreach (JsonData guildDataJson in bro.Rows()) {
    if (maxGuildListCount >= 3) {
        break;
    }
    // 1. 랜덤 테이블 조회를 통해 길드 inDate가져오기
    string guildInDate = guildDataJson["guildInDate"].ToString();
    
    // 2. GetGuildInfoV3()를 통해 랜덤 조회에서 불러온 길드 검색
    var bro2 = Backend.Guild.GetGuildInfoV3(guildInDate);
    
    if (bro2.IsSuccess()) {
        Debug.Log("길드 상세 정보 조회에 성공했습니다.\n" + bro2);
        var guildObject = Instantiate(_guildItemObject, _guildListGameObject.transform, true);
        // 3. 검색된 데이터들 길드 추천 오브젝트에 적용
        if (guildObject.GetComponent<ItemObject>().Initialize(bro2.GetFlattenJSON()["guild"]) == false) {
           //파싱에 실패했다면 해당 길드는 파기합니다. 
           Destroy(guildObject);
        }
        else {
            // 파싱에 성공했다면 limit을 증가시킵니다.(3개 이상이면 종료)
            maxGuildListCount++;
        }                
    }
}

Debug.Log("랜덤 길드 불러오기가 완료되었습니다.");
				
			

그리고 길드 프로필을 나타내는 오브젝트의 스크립트는 다음과 같습니다.

				
					using System;
using UnityEngine;
using UnityEngine.UI;

using BackEnd;
using LitJson;

public class ItemObject : MonoBehaviour {

    [SerializeField] private Image _guildProfile; // 길드 프로필 사진
    [SerializeField] private Text _guildName; // 길드 이름
    [SerializeField] private Text _guildContent; // 길드 자기소개글
    [SerializeField] private Text _guildLevel; // 길드 레벨(메타정보)
    [SerializeField] private Button _requestGuildJoinButton; // 클릭 시, 가입요청하는 버튼
    
    // 아이템별로 가르키는 길드의 inDate
    string _guildInDate = String.Empty;

    // GetGuildInfoV3()를 통해 리턴받은 Json 데이터를 이용합니다.
    public bool Initialize(JsonData guildDataJson) {
        try {
            
            int profileId = int.Parse(guildDataJson["profile_id"].ToString());
            _guildLevel.text = guildDataJson["level"].ToString();
            _guildContent.text = guildDataJson["content"].ToString();

            _guildName.text = guildDataJson["guildName"].ToString();
            _guildName.text += $"({guildDataJson["memberCount"]}/20)";
            _guildInDate = guildDataJson["inDate"].ToString();

            // 원래라면 아이디에 따른 로컬에 저장된 길드의 엠블럼등을 보여줘야하지만
            // 해당 예제에서는 색의 변경으로 대체했습니다.
            switch (profileId) {
                case 0:
                    _guildProfile.color = Color.blue;
                    break;
                case 1:
                    _guildProfile.color = Color.yellow;
                    break;
                case 2:
                    _guildProfile.color = Color.green;
                    break;
                
            }

             // 버튼 클릭시 길드 가입 요청
            _requestGuildJoinButton.onClick.AddListener( () => { 
                var bro = Backend.Guild.ApplyGuildV3(_guildInDate);
                if (bro.IsSuccess()) {
                    Debug.Log("길드 가입 요청을 보냈습니다");
                }
                else {
                    Debug.LogError("길드 가입 요청을 보내지 못했습니다.");
                }

                _requestGuildJoinButton.enabled = true;
                _requestGuildJoinButton.name = "요청됨";
            });
            
            return true;
        }
        catch (Exception e) {
            Debug.LogError("데이터 파싱중 에러가 발생하였습니다. : " + e);
            return false;
        }
    }
}
				
			
3. 결과

오늘 안내드린 순서대로 작업을 하고 게임을 실행시키면? 아래와 같은 화면을 확인하실 수 있습니다.

길드 추천 UI 구현 화면

랜덤 테이블에서 검색된 길드의 수 만큼 정보를 불러와, 그 데이터를 오브젝트에 적용시켜 보여주게 되는 것입니다.😊

뒤끝으로 ‘친구 추천’ 및 ‘길드 추천’ 기능을 구현하실 예정이라면,
오늘 안내드린 로직을 참고해 보세요!

더 수월하고 더 가벼운 기능 구현이 가능하실 거예요.

관련하여 궁금한 부분이 있으시다면 언제든 댓글 남겨주시기 바랍니다.
감사합니다! 😊

0

댓글