안녕하세요, 뒤끝 Backend.GameData.Get 관련하여 동작 방식 문의드립니다.
현재 게임 내에서 친구 추천 기능을 구현하면서 다음과 같이 유저 메타 테이블에서
레벨 구간으로 필터링한 뒤, 최대 100명의 유저를 조회하고 있습니다.
public void SuggestedFriend(Action done)
{
if (suggesetObjects.Count > 0)
return;
finalSuggeset.Clear();
Where where = new Where();
int myTheme = GetTheme(GameController.Instance.UserInfo.UserLevelTotal);
int startLevel = ThemeStart(myTheme - seatchRange);
int endLevel = ThemeEnd(myTheme + seatchRange);
where.Greater("player_level", startLevel);
where.Less("player_level", endLevel); // 이부분은 이렇게 사용하면 안되는건 인지 하고 수정하였습니다
int maxtheme = JsonDataHandler.Instance.GetThemeMaxNum(GameController.Instance.UserInfo.UserSeason);
var bro = Backend.GameData.Get(MetaTable, where, 100); // 최대 100명 조회
if (!bro.IsSuccess())
{
Debug.Log(bro);
return;
}
if (bro.GetReturnValuetoJSON()["rows"].Count <= 0)
{
Debug.Log(bro);
return;
}
Dictionary<string, string> list = new Dictionary<string, string>();
for (int i = 0; i < bro.Rows().Count; ++i)
{
var inDate = bro.Rows()[i]["owner_inDate"]["S"].ToString();
var nickname = bro.Rows()[i]["nickname"]["S"].ToString();
var friendCode = bro.Rows()[i]["friend_code"]["S"].ToString();
// 과거에는 여기에서 Add를 사용했습니다.
// list.Add(inDate, nickname);
list.TryAdd(inDate, nickname);
}
list = ShuffleDictionary(list);
...
}
발생했던 문제
위 코드에서 처음에는 TryAdd가 아니라 Dictionary.Add 를 사용하고 있었고,
실서비스 로그에서 다음과 같은 형태의 예외가 발생했습니다.
System.ArgumentException: An item with the same key has already been added. Key: owner_inDate
즉, 동일한 owner_inDate 값을 가진 row가 두 번 이상 반환되어 Dictionary.Add 에서 중복 key 예외가 발생했습니다.
코드 상으로는 owner_inDate 를 “유저 1명당 1개 row” 라는 전제로 사용하고 있었기 때문에,
Backend.GameData.Get(MetaTable, where, 100) 결과에 동일 owner_inDate 가 여러 개 포함될 수 있다고는 예상하지 못했습니다.
현재는 TryAdd 로 수정하여 예외는 더 이상 발생하지 않지만,
문제를 분석하는 과정에서 한 가지 특이한 점이 있어 확인을 부탁드리고자 합니다.
기종별 발생 빈도 편차
위 예외가 발생한 유저들을 집계해 보았을 때,
전체 유저 중 Galaxy A15 / A16 계열 기종에서 해당 예외 발생 비율이 유난히 높게 나타났습니다.
- 무작위 200명 정도를 샘플링했을 때
→ 특정 기종(A15, A16)의 비중이 비정상적으로 높게 나타남 - 코드 상으로는 단순히
GameData.Get(MetaTable, where, 100)후Rows()를 순회하는 구조이고,
기종별로 분기하거나 다른 조건을 쓰는 코드는 없습니다.
에러 자체는 저희가 Add 를 사용한 쪽의 문제라는 것은 인지하고 있으나,
“왜 특정 기종에서만 유달리 중복 key(동일 owner_inDate)가 많이 나오는가?”
라는 부분이 궁금해서 아래 내용을 확인 요청드립니다.
확인 요청 드리고 싶은 사항
-
Backend.GameData.Get으로 조회할 때
동일 테이블 / 동일 where 조건 / 동일 limit(예: 100)으로 호출하더라도,
2.여러 row에 동일한owner_inDate값이 포함되어 반환될 수 있는지*
(예: 한 유저가 같은 테이블에 여러 row를 갖는 구조라면 가능할 것 같은데,
MetaTable 성격 상 “유저당 1 row” 라는 전제에서 설계되어 있어서요.) -
Backend.GameData.Get결과가
요청을 보낸 단말 환경(휴대폰 기종, OS, 네트워크 환경 등)에 따라
반환되는 row의 우선순위나 구성에 차이가 날 수 있는지
- 예: 특정 샤딩/캐싱 정책이나 내부 정렬 방식으로 인해
동일 조건에서 일부 유저군이 더 자주 선택될 가능성이 있는지 - 동일 where 조건/limit으로 여러 번 호출 시,
어떤 기준으로 row가 선택/정렬되는지(예: createdAt 오름차순, 내림차순, 랜덤 등)
- 혹시
GameData.Get이 내부적으로
요청 단말의 어떤 값(예: gamer_id, owner_inDate 등)에 따라
조회 범위 혹은 우선순위가 달라질 수 있는 로직이 있는지 여부
정리하면,
저희 코드에서 Add 사용으로 인한 예외는 수정하였으나,
특정 기종에서 동일 owner_inDate 중복이 유독 많이 관측되는 현상이 단순 우연인지,
혹은 Backend.GameData.Get 의 내부 동작(정렬/샘플링/캐시 등)과 관련이 있을 수 있는지
확인 받고 싶습니다.
확인 부탁드립니다.
감사합니다.