[뒤끝팁] 뒤끝으로 ‘출석 체크’ 기능 만들기 가이드


안녕하세요! 뒤끝입니다?

오늘은 개발자님들이 뒤끝을 200% 완벽하게 이용하실 수 있도록, 뒤끝을 활용하여 ‘출석체크 기능 만들기’ 가이드를 준비했습니다.

사실 뒤끝은 현재 직접적으로는 출석체크 기능을 제공하고 있지 않아요. 그렇지만 뒤끝베이스①게임 정보관리 기능②차트 관리 기능을 활용하면, 개발자님이 원하는 ‘출석체크’ 기능을 만들어 운용할 수 있습니다.

지금부터 따라오기만 하면 이해할 수 있는 출석체크 기능, 함께 만들러 가 보실까요? ?



1. 출석체크 보상 기획 및 차트 생성하기

먼저 유저에게 날짜별로 어떤 출석 보상을 줄 것인지, 개발자님의 게임에 맞도록 기획하는 작업이 필요합니다. 그리고 기획한 내용을 바탕으로 차트를 생성하세요.

이때 해당 차트에는 출석 보상으로 지급할 아이템의 모든 정보를 입력할 필요 없이, 아이템의 ID 값만 추가하면 충분합니다.

출석 보상 차트

dayitemldnum
1item_potion_010
2item_jual_0100


아이템 ID 값을 이용하여 게임 내부의 아이콘 이미지를 조회하고, 아이템 차트에서 아이템 ID를 이용하여 정보를 조회할 수 있어요. 그러므로 위 예시처럼 최소한의 정보만 입력하여 차트를 제작해 줍니다.

이렇게 생성한 차트를 뒤끝 콘솔의 [뒤끝 차트]에 업로드하면, 1단계 완료!?

뒤끝베이스 [차트 관리] 기능> 개발문서 보기



2. 출석체크 확인 데이터 생성하기

출석체크 보상을 설정했다면, 그다음으로는 유저의 출석 여부를 확인할 수 있는 시스템을 설계해야겠지요.

유저가 출석체크를 했는지 확인하기 위해서 기 운용중인 유저정보 테이블에 출석체크 확인용 컬럼을 1개 추가하는 작업이 필요합니다.


[가정]

먼저 이번 달에 얼마나 출석을 했는지 확인하기 위해, 해당 컬럼에 bool 배열 형태의 데이터를 저장한다.
(해당 일에 출석을 한 경우 true, 하지 않은 경우 false)

① user_info 테이블에 attendanceChek 컬럼이 존재하고 여기에는 bool 배열이 저장되어 있다.
② user_info 테이블에 lastLogin 컬럼이 존재하고 여기에는 유저의 마지막 로그인 일자가 저장되어있다.
③ 유저가 로그인을 한 경우 서버로부터 user_info 테이블을 조회하고,
attendanceCheck 컬럼과 lastLogin 컬럼은 항상 함께 갱신된다.



a. 마지막으로 로그인 한 날짜와 오늘 날짜의 ‘month’가 다른 경우

해당 월에 처음으로 로그인한 경우입니다.
출석 정보를 초기화하고 오늘 날짜에 출석 처리를 해 줍니다.

b. 마지막으로 로그인 한 날짜와 오늘 날짜의 ‘month’가 같고, ‘day’도 같은 경우

이미 당일에 출석 처리가 된 상태입니다.

c. 마지막으로 로그인 한 날짜와 오늘 날짜의 ‘month’가 같고, ‘day’는 다른 경우

해당 일에 출석을 하지않은 경우입니다.
오늘 날짜에 출석 처리를 해 줍니다.



이와같이 경우의 수를 세 가지로 나누어 로직을 설계하면, 2단계도 완료!?

뒤끝베이스 [게임 정보관리] 기능> 개발문서 보기



부록) 출석체크 클라이언트 로직

개발자님들을 위해 뒤끝이 준비한 부록입니다. 2단계 a, b, c 로직 작성 시 아래를 참고해 주세요!

✔아래 로직은 스키마 미정의 테이블을 사용하였습니다.
✔단순 참고용 수도 코드로 차트 조회 등은 빠져 있으며, 해당 코드를 그대로 복사 및 붙여넣기 하더라도 동작을 하지 않습니다.

다음을 참고하여, 개발자님의 게임에 맞는 로직을 작성해 보세요?

// 서버시간을 조회하여 현재 출석을 할 수 있는 경우로 가정하겠습니다.
// user_info 라는 테이블을 get한 결과로 리턴된 BackendReturnObject를 인자값으로 넘겨줍니다.
// 오늘의 일자를 인자값으로 넘겨줍니다. (서버시간을 DateTime으로 변환하여 넘겨줍니다.)
void AttendanceCheck(BackendReturnObject bro, DateTime nowDay)
{
	if(bro.IsSuccess() == false)
	{
		// 서버에 요청을 실패한 경우 바로 리턴합니다.
    // 서버와 통신 실패 UI를 띄웁니다.
		return;
	}

	// user_info 를 메모리 상에 저장합니다.
	// Flatten 함수를 이용하여 datatype 인덱스를 제거합니다.
	var userInfo = BackendReturnObject.Flatten(bro.Rows())[0];

	// 출석 정보를 조회
  var attendanceCheck = userInfo["attendanceCheck"];
	var lastLogin = userInfo["lastLogin"].ToString();
	var lastLoginDate = DateTime.Parse(lastLogin);

	// 이번달이 일수가 총 몇일인지 계산
	var monthLength = DateTime.DaysInMonth(nowDay.Year, nowDay.Month);

	// 서버에 저장할 출석 정보를 미리 선언
	Param check = new Param();

	// 오늘 날짜의 'Month'와 마지막 로그인 날짜의 'Month'가 다르면
	// 출석정보를 초기화 해야됨
	if(nowDay.Month != lastLoginDate.Month)
	{
		// 빈 출석 정보 생성
		bool[] checkDate = new bool[monthLength];
		// 배열 내 모든 데이터를 false로 초기화
		checkDate.Initialize();
		// 오늘 출석 정보 생성
		checkDate[nowDay.Day - 1] = true;
		// 출석 정보를 갱신
		check.Add("attendanceCheck", checkDate);
	}
	// 오늘 날짜의 'Month'가 같고
	// 오늘 날짜의 'Day'와 마지막 로그인 날짜의 Day'가 같으면
	// 출석을 이미 했음
	else if(nowDay.Day == lastLoginDate.Day)
	{
		// 이미 출석했으니 그대로 리턴
		return;
	}
	// 오늘 날짜의 'Month'가 같고, 오늘 날짜와 'Day'가 다르면
	// 출석 해야됨 
	else
	{
		// 마지막 로그인 일자와 출석 정보는 항상 함께 업데이트 된다고 가정하기 때문에
		// attendanceCheck의 길이와 monthLength 는 동일합니다.
		attendanceCheck[nowDay.Day - 1] = true;
		
		// 출석 정보에 갱신할 데이터 추가
		check.Add("attendanceCheck", attendanceCheck);
	}

	// 마지막 로그인 일자를 오늘로 갱신
	check.Add("lastLogin", nowDay.ToString("yyyy-MM-ddTHH:mm:ss.FFFZ");

	// 출석체크 보상 차트에서 보상으로 지급되어야 할 아이템 ID를 확인합니다.
  var attendanceCheckItemId = attendanceChart[nowDay.Day - 1]["itemId"];
	// 아이템 ID를 기반으로 아이템 정보를 확인합니다.
	var attendanceCheckItem = itemChart[attendanceCheckItemId];

	// attendanceCheckItem을 기반으로 서버에 업데이트 할 Param값을 생성합니다.
	Param itemData = new Param()
	// .. 아이템 데이터 Add

	TransactionParam transaction = new TransactionParam();
	transaction.AddUpdate("user_info", "user_info inDate", check);
	transaction.AddInsert("inventory", "inventory inDate", itemData);
	
	// 트랜잭션으로 user_info update와 inventory insert 요청 보내기
	var result = Backend.GameInfo.TransactionWrite(transaction);

	if(result.IsSuccess() == false)
	{
		// 요청 실패 처리
		return;
	}

	// 요청 성공 처리
	return;
}


여기까지 뒤끝 개발팀이 전하는 ‘뒤끝으로 출석체크 만들기’ 가이드였습니다. 모두들 잘 따라오셨나요?

많은 게임들이 초반 리텐션을 높이고, 고객 충성도를 유지하기 위해 ‘출석체크’ 보상 이벤트를 진행합니다. 일반적으로 연속 접속을 할수록 보상이 커지도록 하여, 유저로 하여금 지속적으로 게임에 접속하도록 유도하는 역할을 하는데요.

오늘 소개 드린 뒤끝의 기능을 활용하여, 개발자님의 게임에도 ‘출석체크’ 기능을 구현하실 수 있습니다.


뒤끝으로 출석체크 만들기 CLEAR!?
개발자님의 게임, 뒤끝과 함께 만들어가요.

3

2 Comments

  1. 위 a,b 조건 즉

    a. 유저 접속 시, 해당 일자에 아직 ‘로그인’처리가 되어있지 않은 경우
    이 경우 유저가 attendanceCheck 컬럼의 bool 배열에서 특정 일자에 해당하는 배열 인덱스의 값을 true로 갱신하고, 해당 일자에 배정된 아이템을 지급합니다.

    b. 유저 접속 시, 이미 해당 일자에 ‘로그인’ 처리가 되어있는 경우
    이 경우에는 우선 7월과 8월을 제외하고는 ‘붙어있는 달끼리, 한 달의 전체 일 수가 서로 다르다’는 점을 유의해야 합니다.

    b-1. 서버에 저장된 출석 일수의 길이와, 이번 달의 전체 일 수의 길이가 다르다면?
    : 출석 정보를 초기화한 후, 위 ‘a’ 로직을 수행해야 합니다.

    b-2. 서버에 저장된 출석 일수와, 이번 달의 전체 일 수의 길이가 같다면? (7,8월 달인 경우 or 지난달에 한 번 도 출석을 하지 않은 경우가 해당돼요)
    : 우선, 서버에 저장된 출석 데이터에서 오늘 일자이후에 true인 데이터가 존재하는지 확인해야 합니다.

    true인 데이터가 존재하면 출석 정보를 초기화하고 ‘a’ 로직을 수행합니다. 만약 true인 데이터가 존재하지 않는다면, 유저가 해당 월 / 해당 일자에 이미 로그인을 한 것이기 때문에 아무런 작업을 하지 않고 리턴합니다.

    에서 오류가 날만 한 부분에 대하여 궁금증이 생겨 답글 남겨 봅니다.

    b-2의 조건에서 궁금증이 생깁니다.

    7 -> 8월을 기준으로 상황을 만들어보면 유저가 7월 1일부터 7월 10일까지 접속 후 7월 11일부터 7월 31일까지 미접속을 유지한 후 8월로 넘어가 8월 1일부터 8월 10일까지 미접속을 유지한 후 8월 11일부터 8월 31일까지 접속을 진행한다고 가정할 때 b-2의 조건에는 걸리지 않고 11일 접속보상부터 이어서 진행할 수 있을 수 있다고 보입니다.

    초심자가 보고 진행할 수 있도록 만든 블로그 글이므로 더더욱 이런 버그에 대해서는 없게 만드는 것이 블로그에 좋은 기능으로 보입니다. 이 부분 확인 후 블로그 수정 부탁드립니다.

    • 안녕하세요, 개발자님?
      도움이 되는 의견 남겨주심에 감사하다는 말씀 먼저 전합니다.

      이야기해 주신 부분 검토하였고 수정 진행하였습니다.
      보다 접근하기 쉬운 방법으로 도움이 되고자, 전반적으로 로직을 재구성하는 작업을 거쳤으니 이 점 양해 부탁드립니다.

      더욱 노력하며 함께 성장하는 뒤끝이 되겠습니다.
      감사합니다. ?

댓글