뒤끝펑션 트랜잭션 중, bad,signature,,잘못된,signature,입니다.

고객님의 문의에 답변하는 직원은 고객 여러분의 가족 중 한 사람일 수 있습니다.
고객의 언어폭력(비하, 조롱, 욕설, 협박, 성희롱 등)으로부터 직원을 보호하기 위해
관련 법에 따라 수사기관에 필요한 조치를 요구할 수 있으며, 형법에 의해 처벌 대상이 될 수 있습니다.

커뮤니티 이용 정책에 위배되는 게시물을 작성할 경우, 별도 안내 없이 게시물 삭제 또는 커뮤니티 이용이 제한될 수 있습니다.

문의 응대 : 평일 오전 10시 ~ 오후 6시
문의를 남기실 경우 다음 항목을 작성해 주세요.
정보가 부족하거나 응대시간 외 문의하는 경우 확인 및 답변이 지연될 수 있습니다.

  • 뒤끝 SDK 버전 : 5.9.4
  • 프로젝트명 : Critadel Rush
  • 스테이터스 코드 :
  • 에러 코드 :
  • 에러 메시지 : bad,signature,잘못된,signature,입니다, 잘못된 bad,signature,잘못된,signature,입니다 입니다

뒤끝펑션 상에서 트랜잭션 쓰기를 통해 게임정보 Update를 하려고 합니다.
Backend.GameData.TransactionWriteV2(transactionList);
이때 transactionList에 넣는 param_RewardBank.Add(RESERVEDREWARDS, tempDic);의
tempDic이 Dictionary<int, string>입니다.

트랜잭션 쓰기를 시도하면 bad signature 오류가 나올때도 있고 안 나올 때도 있어서 확인해 보았는데요. transactionList에 넣는 Dictionary 내용에 따라 그런 것 같습니다.

Dictionary<int, string> tempDic = new Dictionary<int, string>();
tempDic.Add(103, “500”);
tempDic.Add(101, “5”);
//오류 발생함

tempDic.Add(101, “5”);
tempDic.Add(103, “500”);
//정상

tempDic.Add(101, “500”);
tempDic.Add(103, “5”);
//정상

tempDic.Add(103, “123”);
tempDic.Add(101, “55”);
//오류 발생함

tempDic.Add(101, “55”);
tempDic.Add(103, “123”);
//정상

tempDic.Add(201, “5”);
tempDic.Add(103, “500”);
//오류 발생함

return Backend.StringToStream(JsonMapper.ToJson(transactionList));
로 transactionList를 확인해 보면

{“result”:"[{“action”:1,“table”:“RewardBank”,“inDate”:null,“where”:{},“param”:{“ReservedRewards”:{“103”:“500”,“101”:“5”}},“ownerInDate”:null}]"}
이와 같은 메세지가 왔습니다…

int 키 순서가 오름차순이 아니면 오류가 나는 느낌인데
정렬부터하고 넣어줘야 하는 건가요?
아니면 SortedDictionary를 써야할까요?

안녕하세요, 개발자님.
관련 내용 확인하여 안내드릴 수 있도록 하겠습니다.
안내까지 다소 시간이 소요될 수 있는 점 양해 부탁드립니다.

확인이 지연되어 죄송합니다.
남겨주신 정보상으로는 정확한 확인에 어려움이 있는 상황입니다.
보다 정확한 확인을 위해 사용하고 계신 코드 정보를 공유하여 주시면 확인하여 안내드릴 수 있도록 하겠습니다.

using Amazon.Lambda.Core;
using BackEnd;
using BackEnd.Game;
using LitJson;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Numerics;
using System.Text;

[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.Json.JsonSerializer))]

namespace BackendFunction {
    public class BFunc {

        public class MissionData {
            public int KEY; //미션 index
            public int MI; //미션 종류
            public BigInteger GV; //미션 목표값
            public bool WR; //보상 수령 여부
        }

        public class MissionRewardGetAns {
            public GetRewardResult state;
            public List<string> rewards = new List<string>();
            public string message;
        }

        public class ServerInventoryData {
            public int Key;
            public int Count;
            public int CurrentStar;
        }

        public enum GetRewardResult {
            Error = -1,
            Nothing = 0,
            RewardGet = 1,
        }

        public enum MissionType {
            None = 0,
            Daily = 1,
            Weekly = 2,
            Achievement = 3,
            DailyPoint = 4,
            WeeklyPoint = 5,
            NewUser7Days = 6,
            StageWaveCompetition = 7,
            HeroGrowth = 8,
        }

        private const string MISSIONDATA = "MissionData";
        private const string MISSION_DAY = "Mission_Day";
        private const string MISSION_WEEK = "Mission_Week";
        private const string MISSIONTYPE = "MissionType";
        private const string MISSIONKEY = "MissionKey";
        private const string MISSIONPROGRESS = "MissionProgress";
        private const string POINTREWARDINDEX = "PointRewardIndex";
        private const string REWARDBANK = "RewardBank";
        private const string RESERVEDREWARDS = "ReservedRewards";
        //private const string REWARDDIA = "RewardDia";
        private const string ITEMKEY = "itemKey";
        private const string ITEMAMOUNT = "itemAmount";
        private const string KEY = "Key";
        private const string ACHIEVEMENT_STACK = "Achievement_Stack";
        private const string MISSIONPOINTREWARDDAILY = "MissionPointReward_Daily";
        private const string MISSIONPOINTREWARDWEEKLY = "MissionPointReward_Weekly";
        private const string CLEARMISSIONNUMBER = "ClearMissionNumber";
        private const string MISSIONOBJECTIVE = "MissionObjective";
        private const string GOALVALUE = "GoalValue";

        private const string MISSION_EVENT_NEWUSER7DAYS = "Mission_Event_NewUser7Days";
        private const string MISSION_EVENT_STAGEWAVECOMPETITION = "Mission_Event_StageWaveCompetetion";
        private const string MISSION_EVENT_HEROGROWTH = "Mission_Event_HeroGrowth";

        private StringBuilder _sb = new StringBuilder();

        public Stream Function(Stream stream, ILambdaContext context) {
            try {
                // Initialize BackendFunction API
                Backend.Initialize(ref stream);
            } catch (Exception e) {
                //Return the reason if Initializing BackendFunction API was failed
                return ReturnErrorObject("initialize " + e.ToString());
            }

            // TODO
            if (Backend.HasKey(MISSIONTYPE) == false) return ReturnErrorObject("MissionType parameter required");

            MissionType missonType = MissionType.None;
            int[] missionKey = new int[0];
            int[] pointRewardIndexs = new int[0];
            string[] missionKey_String = new string[0];
            BigInteger[] missionProgress = new BigInteger[0];
            try {
                missonType = (MissionType)int.Parse(Backend.Content[MISSIONTYPE].ToString());

                bool isPointType = false;
                switch (missonType) {
                    case MissionType.Daily: break;
                    case MissionType.Weekly: break;
                    case MissionType.Achievement: break;
                    case MissionType.DailyPoint: isPointType = true; break;
                    case MissionType.WeeklyPoint: isPointType = true; break;
                    case MissionType.NewUser7Days: break;
                    case MissionType.StageWaveCompetition: break;
                    case MissionType.HeroGrowth: break;
                    default: return ReturnErrorObject("MissionType parse result not valid " + missonType);
                }

                if (isPointType) {
                    //일일미션, 주간미션 포인트 모아서 추가 보상 버전
                    if (Backend.HasKey(POINTREWARDINDEX) == false) return ReturnErrorObject("PointRewardIndex parameter required");
                    JsonData priJson = Backend.Content[POINTREWARDINDEX];
                    pointRewardIndexs = new int[priJson.Count];
                    for (int i = 0; i < priJson.Count; i++) {
                        pointRewardIndexs[i] = int.Parse(priJson[i].ToString());
                    }
                    
                } else {
                    //일일미션,주간미션,업적 슬롯 보상 버전
                    if (Backend.HasKey(MISSIONKEY) == false) return ReturnErrorObject("MissionKey parameter required");
                    if (Backend.HasKey(MISSIONPROGRESS) == false) return ReturnErrorObject("MissionProgress parameter required");
                    JsonData keyJson = Backend.Content[MISSIONKEY];
                    missionKey_String = new string[keyJson.Count];
                    missionKey = new int[keyJson.Count];
                    for (int i = 0; i < keyJson.Count; i++) {
                        missionKey_String[i] = keyJson[i].ToString();
                        missionKey[i] = int.Parse(missionKey_String[i]);
                    }

                    JsonData progJson = Backend.Content[MISSIONPROGRESS];
                    missionProgress = new BigInteger[progJson.Count];
                    for (int i = 0; i < progJson.Count; i++) {
                        missionProgress[i] = BigInteger.Parse(progJson[i].ToString());
                    }
                }

            } catch (Exception e){
                return ReturnErrorObject($"Mission Parameter parsing fail: {Backend.Content[MISSIONTYPE]}\n" + e.Message);
            }
            if (missonType == MissionType.None) return ReturnErrorObject("MissionType None is not valid ");

            //RewardBank 테이블
            BackendReturnObject rewardBankBro = Backend.GameData.GetMyData(REWARDBANK, new Where());
            if (rewardBankBro.IsSuccess() == false) return Backend.StringToStream(JsonMapper.ToJson(MakeResponseError("RewardBank get failed")));
            JsonData rewardBankJson = rewardBankBro.FlattenRows();
            if (rewardBankJson.Count <= 0) {
                Param newParam = new Param();
                newParam.Add(RESERVEDREWARDS, new Dictionary<int, string>());
                BackendReturnObject insertBro = Backend.GameData.Insert(REWARDBANK, newParam);
                if (insertBro.IsSuccess()) {
                    rewardBankBro = Backend.GameData.GetMyData(REWARDBANK, new Where());
                    if (rewardBankBro.IsSuccess() == false) return Backend.StringToStream(JsonMapper.ToJson(MakeResponseError("RewardBank DB row not created")));
                    rewardBankJson = rewardBankBro.FlattenRows();
                } else {
                    return Backend.StringToStream(JsonMapper.ToJson(MakeResponseError("RewardBank DB row insert failed: " + insertBro.GetMessage())));
                }
            }
            JsonData rewardBankRow = rewardBankJson[0];
            SortedDictionary<int, string> rewardStringDic;
            Dictionary<int, BigInteger> rewardSumDic = new Dictionary<int, BigInteger>();
            if (rewardBankRow[RESERVEDREWARDS].Count > 0) {
                rewardStringDic = JsonConvert.DeserializeObject<SortedDictionary<int, string>>(rewardBankRow[RESERVEDREWARDS].ToJson());
                foreach (var item in rewardStringDic) {
                    rewardSumDic.Add(item.Key, BigInteger.Parse(item.Value));
                }
            } else {
                rewardStringDic = new SortedDictionary<int, string>();
            }

            //미션과 업적 정보 차트
            BackendReturnObject chartBro = Backend.Chart.GetChartListV2();
            if (chartBro.IsSuccess() == false) return Backend.StringToStream(JsonMapper.ToJson(MakeResponseError("Error during chart parsing (0)")));
            JsonData chartFlatRows = chartBro.FlattenRows();
            Dictionary<string, string> chartDic = new Dictionary<string, string>();
            for (int i = 0; i < chartFlatRows.Count; i++) {
                chartDic[chartFlatRows[i]["chartName"].ToString()] = chartFlatRows[i]["selectedChartFileId"].ToString();
            }

            //본격적으로 보상 수령 처리 시작
            BackendReturnObject tableBro = Backend.GameData.GetMyData(MISSIONDATA, new Where());
            JsonData tableFlatRows = tableBro.FlattenRows();
            if (tableFlatRows.Count <= 0) return Backend.StringToStream(JsonMapper.ToJson(MakeResponseError("No mission DB row found (A)")));
            JsonData tableRow = tableFlatRows[0];
            

            MissionRewardGetAns newResponse = new MissionRewardGetAns();
            newResponse.state = GetRewardResult.RewardGet;

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

            Param param_RewardBank = new Param();
            transactionList.Add(TransactionValue.SetUpdate(REWARDBANK, new Where(), param_RewardBank));

            if ((missonType == MissionType.Daily) || (missonType == MissionType.Weekly) || (missonType == MissionType.NewUser7Days) || (missonType == MissionType.StageWaveCompetition) || (missonType == MissionType.HeroGrowth)) {
                string columnString = null;
                if (missonType == MissionType.Daily) columnString = MISSION_DAY;
                else if (missonType == MissionType.Weekly) columnString = MISSION_WEEK;
                else if (missonType == MissionType.NewUser7Days) columnString = MISSION_EVENT_NEWUSER7DAYS;
                else if (missonType == MissionType.StageWaveCompetition) columnString = MISSION_EVENT_STAGEWAVECOMPETITION;
                else if (missonType == MissionType.HeroGrowth) columnString = MISSION_EVENT_HEROGROWTH;

                if (columnString == null) return Backend.StringToStream(JsonMapper.ToJson(MakeResponseError("Wrong mission column: " + missonType)));

                //차트 뒤져서 보상값 얼마인지 확인해야됨
                BackendReturnObject missionChart = null;
                if (missonType == MissionType.Daily) missionChart = Backend.Chart.GetChartContents(chartDic["DailyMission"]);
                else if (missonType == MissionType.Weekly) missionChart = Backend.Chart.GetChartContents(chartDic["WeeklyMission"]);
                else if (missonType == MissionType.NewUser7Days) missionChart = Backend.Chart.GetChartContents(chartDic["Event_NewUser7DaysMission"]);
                else if (missonType == MissionType.StageWaveCompetition) missionChart = Backend.Chart.GetChartContents(chartDic["Event_StageClearCompetition"]);
                else if (missonType == MissionType.HeroGrowth) missionChart = Backend.Chart.GetChartContents(chartDic["Event_HeroGrowth"]);
                if (missionChart == null) return Backend.StringToStream(JsonMapper.ToJson(MakeResponseError("Reward chart is null for " + missonType)));
                JsonData missionChartJson = missionChart.FlattenRows();

                List<MissionData> missionsOnDb = null;
                if (tableRow.ContainsKey(columnString) == false) {
                    if ((missonType == MissionType.NewUser7Days) || (missonType == MissionType.StageWaveCompetition) || (missonType == MissionType.HeroGrowth)) {
                        //이 미션들은 MissionDateCheck에서 컬럼을 만들어 주지 않음.
                        missionsOnDb = new List<MissionData>();
                        for (int i = 0; i < missionChartJson.Count; i++) {
                            JsonData data = missionChartJson[i];
                            MissionData newMission = new MissionData();
                            newMission.KEY = int.Parse(data[KEY].ToString());
                            newMission.MI = int.Parse(data[MISSIONOBJECTIVE].ToString());
                            newMission.GV = BigInteger.Parse(data[GOALVALUE].ToString());
                            newMission.WR = false;
                            missionsOnDb.Add(newMission);
                        }
                    } else {
                        return Backend.StringToStream(JsonMapper.ToJson(MakeResponseError("No mission data found (B)")));
                    }   
                }
                if (missionsOnDb == null) missionsOnDb = JsonConvert.DeserializeObject<List<MissionData>>(tableRow[columnString].ToJson());
                List<MissionData> foundMission = new List<MissionData>();
                for (int j = 0; j < missionKey.Length; j++) {
                    for (int i = 0; i < missionsOnDb.Count; i++) {
                        if (missionsOnDb[i].KEY == missionKey[j]) {
                            foundMission.Add(missionsOnDb[i]);
                            break;
                        }
                    }
                }

                if (foundMission.Count != missionKey.Length) return Backend.StringToStream(JsonMapper.ToJson(MakeResponseError($"Found mission count and Requested mission number doesn't match {foundMission.Count} / {missionKey.Length}")));
                for (int i = 0; i < foundMission.Count; i++) {
                    if (foundMission[i] == null) return Backend.StringToStream(JsonMapper.ToJson(MakeResponseError("MissionId not found from DB: " + missionKey[i])));
                    if (foundMission[i].WR) return Backend.StringToStream(JsonMapper.ToJson(MakeResponseError("Already rewarded mission: " + missionKey[i])));
                    if (foundMission[i].GV > missionProgress[i]) return Backend.StringToStream(JsonMapper.ToJson(MakeResponseError($"Mission{missionKey[i]} goal not fuifilled: ({missionProgress[i]} / {foundMission[i].GV})")));
                    foundMission[i].WR = true; //어차피 class라서 ref이므로 여기다 수정해도 됨.
                }



                for (int j = 0; j < foundMission.Count; j++) {
                    JsonData missionRow = null;
                    for (int i = 0; i < missionChartJson.Count; i++) {
                        if (missionChartJson[i][KEY].ToString() == missionKey_String[j]) {
                            missionRow = missionChartJson[i];
                            break;
                        }
                    }
                    if (missionRow == null) return Backend.StringToStream(JsonMapper.ToJson(MakeResponseError("MissionKey not found from Chart" + missionKey_String[j])));
                    //if (int.TryParse(missionRow[REWARDDIA].ToString(), out int reward)) {
                    //    rewardDia += reward;
                    //} else {
                    //    return Backend.StringToStream(JsonMapper.ToJson(MakeResponseError("Error during chart parsing (B)")));
                    //}

                    int itemKey;
                    if (int.TryParse(missionRow[ITEMKEY].ToString(), out itemKey) == false) return Backend.StringToStream(JsonMapper.ToJson(MakeResponseError("itemKey invalid")));
                    if (itemKey == 0) return Backend.StringToStream(JsonMapper.ToJson(MakeResponseError("itemKey is 0")));
                    BigInteger itemAmount = BigInteger.Parse(missionRow[ITEMAMOUNT].ToString());

                    _sb.Clear();
                    _sb.Append(itemKey);
                    _sb.Append('/');
                    _sb.Append(itemAmount.ToString());
                    newResponse.rewards.Add(_sb.ToString());
                    if (rewardSumDic.TryAdd(itemKey, itemAmount)) {
                        rewardStringDic.Add(itemKey, itemAmount.ToString());
                    } else {
                        rewardSumDic[itemKey] += itemAmount;
                        rewardStringDic[itemKey] = rewardSumDic[itemKey].ToString();
                    }
                }


                //트랜잭션으로 미션 보상 수령 + 보상 실제 지급
                Param param_Mission = new Param {
                    { columnString, missionsOnDb }
                };
                transactionList.Add(TransactionValue.SetUpdate(MISSIONDATA, new Where(), param_Mission));

            } else if (missonType == MissionType.Achievement) {
                BackendReturnObject achChart = Backend.Chart.GetChartContents(chartDic["AchievementMission"]);
                JsonData achChartJson = achChart.FlattenRows();
                Dictionary<int, int> achStackDic = new Dictionary<int, int>();
                if (tableRow.ContainsKey(ACHIEVEMENT_STACK)) {
                    try {
                        achStackDic = JsonConvert.DeserializeObject<Dictionary<int, int>>(tableRow[ACHIEVEMENT_STACK].ToJson());
                    } catch (Exception e) {
                        return Backend.StringToStream(JsonMapper.ToJson(MakeResponseError("Achievement_Stack Json read failed: " + e.Message)));
                    }
                } else achStackDic = new Dictionary<int, int>();

                for (int i = 0; i < missionKey.Length; i++) {
                    JsonData achRow = null;
                    for (int j = 0; j < achChartJson.Count; j++) {
                        if (int.Parse(achChartJson[j][KEY].ToString()) == missionKey[i]) {
                            achRow = achChartJson[j];
                            break;
                        }
                    }
                    if (achRow == null) return Backend.StringToStream(JsonMapper.ToJson(MakeResponseError("achievement key invalid: " + missionKey[i])));

                    BigInteger goalValue_Min = BigInteger.Parse(achRow["GoalValue_Min"].ToString());
                    BigInteger goalValue_Max = BigInteger.Parse(achRow["GoalValue_Max"].ToString());
                    BigInteger goalValue_Incre = BigInteger.Parse(achRow["ValueIncrease"].ToString());
                    //rewardDia += int.Parse(achRow[REWARDDIA].ToString());

                    int itemKey;
                    if (int.TryParse(achRow[ITEMKEY].ToString(), out itemKey) == false) return Backend.StringToStream(JsonMapper.ToJson(MakeResponseError("itemKey invalid")));
                    if (itemKey == 0) return Backend.StringToStream(JsonMapper.ToJson(MakeResponseError("itemKey is 0")));
                    BigInteger itemAmount = BigInteger.Parse(achRow[ITEMAMOUNT].ToString());

                    _sb.Clear();
                    _sb.Append(itemKey);
                    _sb.Append('/');
                    _sb.Append(itemAmount.ToString());
                    newResponse.rewards.Add(_sb.ToString());
                    if (rewardSumDic.TryAdd(itemKey, itemAmount)) {
                        rewardStringDic.Add(itemKey, itemAmount.ToString());
                    } else {
                        rewardSumDic[itemKey] += itemAmount;
                        rewardStringDic[itemKey] = rewardSumDic[itemKey].ToString();
                    }

                    int currentAchStack = 0;
                    if (achStackDic.ContainsKey(missionKey[i])) currentAchStack = achStackDic[missionKey[i]];
                    else achStackDic.Add(missionKey[i], 0);

                    BigInteger goalValue_Calc = goalValue_Min + goalValue_Incre * currentAchStack;
                    if (goalValue_Calc > goalValue_Max) return Backend.StringToStream(JsonMapper.ToJson(MakeResponseError($"Achievement{missionKey[i]} goal overflow: ({goalValue_Calc} / {goalValue_Max})")));
                    if (goalValue_Calc > missionProgress[i]) return Backend.StringToStream(JsonMapper.ToJson(MakeResponseError($"Achievement{missionKey[i]} goal not fuifilled: ({missionProgress[i]} / {goalValue_Calc})")));

                    achStackDic[missionKey[i]] = (currentAchStack + 1);
                }

                //트랜잭션으로 업적 보상 수령 + 보상 실제 지급
                Param param_Mission = new Param {
                    { ACHIEVEMENT_STACK, achStackDic },
                };
                transactionList.Add(TransactionValue.SetUpdate(MISSIONDATA, new Where(), param_Mission));


            } else if ((missonType == MissionType.DailyPoint) || (missonType == MissionType.WeeklyPoint)) {
                string columnString;
                if (missonType == MissionType.DailyPoint) {
                    columnString = MISSIONPOINTREWARDDAILY;
                } else {
                    columnString = MISSIONPOINTREWARDWEEKLY;
                }

                int maxLength = 0;
                for (int i = 0; i < pointRewardIndexs.Length; i++) {
                    if (maxLength <= pointRewardIndexs[i]) maxLength = pointRewardIndexs[i] + 1;
                }
                int[] pointRewardArray; //해당 보상 이미 받았는지 체크
                if (tableRow.ContainsKey(columnString)) {
                    try {
                        pointRewardArray = JsonConvert.DeserializeObject<int[]>(tableRow[columnString].ToJson());
                        if (pointRewardArray.Length < maxLength) {
                            int[] backup = new int[pointRewardArray.Length];
                            for (int i = 0; i < pointRewardArray.Length; i++) backup[i] = pointRewardArray[i];
                            pointRewardArray = new int[maxLength];
                            for (int i = 0; i < backup.Length; i++) pointRewardArray[i] = backup[i];
                        }

                    } catch {
                        pointRewardArray = new int[maxLength];
                    }
                } else {
                    //db 없으면 새로 만들고 (미션 1개 깨고 해금되는 보상이면 index 값이 1임)
                    pointRewardArray = new int[maxLength];
                }

                for (int i = 0; i < pointRewardIndexs.Length; i++) {
                    int rewardIndex = pointRewardIndexs[i];
                    if (pointRewardArray[rewardIndex] != 0) return Backend.StringToStream(JsonMapper.ToJson(MakeResponseError("Already rewarded MissionPointReward exist: " + rewardIndex)));
                    pointRewardArray[rewardIndex] = 1;
                } //하나라도 이미 보상을 수령했으면 오류 처리

                //차트 뒤져서 보상값 얼마인지 확인해야됨
                BackendReturnObject missionChart = Backend.Chart.GetChartContents(chartDic["MissionPointReward"]);
                JsonData missionChartJson = missionChart.GetFlattenJSON()["rows"];

                //int rewardDia = -1;
                for (int pri = 0; pri < pointRewardIndexs.Length; pri++) {
                    for (int i = 0; i < missionChartJson.Count; i++) {
                        if (int.Parse(missionChartJson[i][CLEARMISSIONNUMBER].ToString()) == pointRewardIndexs[pri]) {
                            if (((missonType == MissionType.DailyPoint) && (missionChartJson[i][MISSIONTYPE].ToString()[0] == 'D'))
                                || ((missonType == MissionType.WeeklyPoint) && ((missionChartJson[i][MISSIONTYPE].ToString()[0] == 'W')))) {
                                if (missionChartJson[i][MISSIONTYPE].ToString()[0] == 'D') { //기획에서 이 차트 구성을 요구함
                                    //rewardDia += int.Parse(missionChartJson[i][REWARDDIA].ToString());
                                    int itemKey;
                                    if (int.TryParse(missionChartJson[i][ITEMKEY].ToString(), out itemKey) == false) return Backend.StringToStream(JsonMapper.ToJson(MakeResponseError("itemKey invalid")));
                                    if (itemKey == 0) return Backend.StringToStream(JsonMapper.ToJson(MakeResponseError("itemKey is 0")));
                                    BigInteger itemAmount = BigInteger.Parse(missionChartJson[i][ITEMAMOUNT].ToString());

                                    _sb.Clear();
                                    _sb.Append(itemKey);
                                    _sb.Append('/');
                                    _sb.Append(itemAmount.ToString());
                                    newResponse.rewards.Add(_sb.ToString());
                                    if (rewardSumDic.TryAdd(itemKey, itemAmount)) {
                                        rewardStringDic.Add(itemKey, itemAmount.ToString());
                                    } else {
                                        rewardSumDic[itemKey] += itemAmount;
                                        rewardStringDic[itemKey] = rewardSumDic[itemKey].ToString();
                                    }
                                }
                            }
                        }
                    }
                }


                //트랜잭션으로 미션 보상 수령 + 보상 실제 지급
                Param param_MissionPointReward = new Param {
                    { columnString, pointRewardArray }
                };
                transactionList.Add(TransactionValue.SetUpdate(MISSIONDATA, new Where(), param_MissionPointReward));

            } else {
                return Backend.StringToStream(JsonMapper.ToJson(MakeResponseError("Not implemented mission type " + missonType)));
            }

            //_sb.Clear();
            //foreach (var item in rewardStringDic) {
            //    _sb.Append($"[{item.Key}: {item.Value}]\n");
            //}
            //return Backend.StringToStream(_sb.ToString());
            Dictionary<int, string> tempDic = new Dictionary<int, string>();
            tempDic.Add(201, "5");
            tempDic.Add(103, "500");

            param_RewardBank.Add(RESERVEDREWARDS, tempDic);

            BackendReturnObject transactionBro = Backend.GameData.TransactionWriteV2(transactionList);
            if (transactionBro.IsSuccess() == false) return Backend.StringToStream(JsonMapper.ToJson(MakeResponseError("Error during update user DB\n" + transactionBro.GetMessage())));

            return Backend.StringToStream(JsonMapper.ToJson(newResponse));

        }

        private int KeySort((int, string) x, (int,string) y) {
            if (x.Item1 > y.Item1) return 1;
            else if (x.Item1 < y.Item1) return -1;
            return 0;
        }

        static Stream ReturnErrorObject(string err) {
            JObject error = new JObject();
            error.Add("error", err);

            return Backend.JsonToStream(error.ToString());
        }



        public MissionRewardGetAns MakeResponseError(string _message) {
            MissionRewardGetAns newResponse = new MissionRewardGetAns();
            newResponse.state = GetRewardResult.Error;
            newResponse.message = _message;

            return newResponse;
        }
    }
}


코드 전체 공유드립니다.
지금은 SortedDictionary를 써서 문제는 안 겪는 중입니다.
오류가 나도록 마지막 부분에 tempDic 부분을 넣어두었습니다.

좋아요 1

배드 시그니쳐 에러는 뒤끝펑션에 한해서 순서에 따른 이슈가 있는 것으로 확인됩니다.
알파벳으로 시작하는 문자열을 key 값으로 사용하거나,
Dictionary 키값 소팅해서 사용해 주시면 감사하겠습니다.

추후 뒤끝펑션 픽스가 이루어지는 경우 추가 답변으로 안내드릴 수 있도록 하겠습니다.