- 마지막 업데이트
게임 해지
이해하기
게임 해지(이용해지)는 이용자가 특정 게임의 인게임 데이터를 삭제하는 기능이에요.
스토브 플랫폼 통합 계정은 유지되며, 해당 게임과 연결된 캐릭터, 재화, 월드 내 모든 정보만 삭제돼요.
| 항목 | 내용 |
|---|---|
| 삭제 범위 | 해당 게임의 캐릭터, 재화, 월드 내 모든 정보 |
| 스토브 계정 | 유지됨 (다른 게임 이용 가능) |
| 진입 경로 | 인게임 설정 화면 |
| 유예기간 | 게임별 0~30일 설정 (0일이면 즉시 해지) |
스토브 계정 유지
게임 해지는 해당 게임과 연결된 스토브 계정(게스트, 정회원)의 인게임 정보만 삭제해요.
스토브 플랫폼 통합 계정은 유지되며, 다른 게임 이용에는 영향이 없어요.
처리 방식
게임 해지는 이용자의 실수를 방지하기 위해 경고 안내와 컨펌 확인 기능을 반드시 제공해야 해요.
해지 처리 흐름은 유예기간 설정 여부에 따라 달라져요.

| 처리 방식 | 설명 | 특이사항 |
|---|---|---|
| 해지 신청 (즉시 해지) | 이용자가 해지 신청 시, 스토브 게임 해지 신청 API 호출 | 해지 완료 시 복구 불가 |
| 해지 신청 (유예기간 존재) | 이용자가 해지 신청 시, 스토브 게임 해지 신청 API 호출 (API 파라미터로 유예기간 제어) | 유예기간 중 취소 가능. 완료 콜백 수신 후 데이터 삭제 |
유예기간 해지 처리 방식
① 유예기간이 지나면 스토브가 자동으로 해지를 완료 처리해요.
② 해지가 완료되면 스토브에서 해지 관련 이벤트를 전달해요.
해지 상태 알림
스토브 플랫폼은 게임 해지 상태가 변경될 때 CP사(개발사) 서버로 실시간 이벤트를 전달해요.
CP사는 Callback API를 구현하여 이벤트를 수신하고, 운영 정책에 맞게 처리해야 해요.
| 이벤트 정보 | 이벤트 발생 상황 | CP사 측 대응 가이드 |
|---|---|---|
게임 해지GAME_WITHDRAW |
이용자가 게임 해지를 신청한 경우 | 이용자 로그아웃 처리 필요 |
게임 해지 신청 취소GAME_WITHDRAW_CANCEL |
이용자가 게임 해지 신청을 취소한 경우 | 동기화 목적의 이벤트. 정책에 따라 처리 |
게임 해지 완료GAME_WITHDRAW_COMPLETE |
이용자가 게임 해지를 완료한 경우 | 동기화 목적의 이벤트. 정책에 따라 처리 |
적용 대상 및 제한 사항
본 스토브 이벤트 기능은 GUID 기반 서비스 게임만 지원해요.
Member_no 기반 게임은 기술 담당자를 통해 사전에 확인이 필요해요.
연동 가이드
사전 준비
| 항목 | 내용 |
|---|---|
| User Access Token 확인 | 게임 해지 요청 API에 이용자의 User Access Token 전달 ㆍ로그인 후 SDK로 획득, 캐싱 없이 실시간 조회 |
| 이용자 식별 방식 | ㆍGUID 기반: Member_no 필드에 GUID 데이터 사용 ㆍMember_no 기반: Member_no 필드에 Member_no 데이터 사용 ㆍ퍼블리싱 기술 담당자 확인 |
| 유예기간 정책 결정 | 즉시 해지 또는 유예기간 해지 방식을 게임별로 선택 |
기본 연동 구조
- 클라이언트: 해지 UI 및 경고 안내 제공
- 인게임 설정 화면에 해지 버튼을 배치해요.

- 인게임 설정 화면에 해지 버튼을 배치해요.
- 해지 요청 전 경고 안내 및 컨펌 확인 팝업을 반드시 제공해야 해요.


- 해지 처리 완료 시 자동으로 로그아웃되므로, 이후 동선(예: 게임 종료 또는 초기 화면 이동)을 처리해야 해요.
| UI 유형 | 설명 |
|---|---|
| 경고 안내 팝업 | "해지하면 모든 정보가 삭제되며, 복구할 수 없습니다." 등 해지 결과를 명확히 안내 |
| 컨펌 확인 팝업 | 게임사가 직접 구현하며, 캐릭터명 입력 등 의도적 행동을 유도해 실수 해지를 방지 |
| 유예기간 안내 팝업 (선택) | 유예기간 적용 시 "해지 후 N일 이내에 해지를 취소할 수 있습니다." 등을 안내 |
- 서버: 게임 해지 처리
- 게임 해지 완료 API를 호출하면 스토브 플랫폼 계정은 유지돼요.
- 요청 시 전달한 서버 인증 토큰과 게임 아이디로 식별된 이용자의 스토브 캐릭터 정보가 전체 월드에 걸쳐 모두 삭제돼요.
- 게임 DB에 기록된 게임 내 정보는 게임에서 직접 유지·삭제해야 해요.
- 스토브 재화(cash) 시스템을 사용하는 경우, 캐릭터가 보유한 재화(cash)도 함께 삭제되니 주의가 필요해요.
GUID 기반 게임 해지 구현 시 주의
이후 이용자가 동일 기기에서 재가입할 경우 신규로 GUID가 발급되어 동일 이용자로 구분이 어려워요.
만약 상기 이슈로 사업적으로 지표 왜곡을 방지하고자 한다면, 스토브 정보사(게임일람) API를 사용하지 않고
스토브 캐릭터 삭제 API를 사용하여 게임 해지 기능을 구현해 주세요.
- 유예기간 설정 및 데이터 삭제 방법
- 게임 해지 유예기간은 각 게임별 자체 정책으로 관리해요.
- 해지 처리 기간 내 게임 진입 시 (PC 예시)

- 해지 처리 기간 내 게임 진입 시 (PC 예시)
- 게임 해지 유예기간은 각 게임별 자체 정책으로 관리해요.
- 해지 처리 기간 내 게임 진입 시 (Mobile 예시)

인게임 데이터 삭제 권장 방식
인게임 DB에 flag를 먼저 변경한 뒤, 점검 시 데이터를 백업하고 삭제하는 방식을 권장해요.
개발하기
모바일 SDK 연동
MobileSDK는 인증 동선에서 해지 취소 기능을 챙기고 있어요
- 게임 해지 신청/완료는 게임 서버 ↔ STOVE 서버 간 REST API/이벤트로 처리되며, MobileSDK는 관여하지 않아요. 자세한 내용은 서버 연동 가이드를 참고해 주세요.
- 해지 취소만 MobileSDK가 담당해요. 유예기간 중 이용자가 게임을 다시 켜고 SDK 로그인을 진행하면, 취소 UI가 자동으로 노출돼요.
- 게임 클라이언트는 별도 SDK 함수 호출 없이 평소처럼
AuthUI.Login만 호출하면 돼요.
동작 흐름
유예기간 중 이용자가 다시 게임을 켜고 로그인하면, SDK가 STOVE에서 해지 신청 상태를 자동 조회해 취소 UI를 띄워요. 이용자가 취소를 선택하면 STOVE에서 신청 상태가 해제되고, 게임 서버는 GAME_WITHDRAW_CANCEL 이벤트로 동기화 처리만 하면 돼요.
게임 측 구현 사항
| 영역 | 해야 할 일 |
|---|---|
| 게임 클라이언트 |
평소처럼 AuthUI.Login만 호출하면 돼요. 취소 UI 노출/처리/이후 로그인 흐름은 SDK가 자동으로 담당해요.
|
| 게임 서버 |
GAME_WITHDRAW_CANCEL 이벤트 수신부 구현 후, 수신 시점에 해지 신청 상태 해제
|
개별 월드 운영 시 서버 간 동기화에 유의해요
공통 서버를 통한 동기화 형태가 아닌, 개별 월드를 통해 운영하는 경우에는 GAME_WITHDRAW_CANCEL 이벤트 수신 시 서버 간 동기화 처리를 반드시 구현해야 해요.
참고
AuthUI.Login의 전체 호출 흐름은 로그인 가이드를 참고해 주세요.- 게임 해지 신청 API(REST), 해지 완료 처리(STOVE 자동),
GAME_WITHDRAW*이벤트 명세는 서버 연동 가이드를 참고해 주세요.
PC SDK 연동
PCSDK IAPSDK가 제공하는 게임 해지 API(IAP_WithdrawGame)를 사용하면 게임 클라이언트에서 STOVE 게임 해지(약관철회) 팝업을 띄울 수 있어요. 이용자가 팝업에서 약관 철회에 동의하면 STOVE가 게임 해지를 처리해요.
스팀런처로 실행한 경우에는 동작하지 않아요. 그러므로 스팀런처를 통해 실행중이라면 호출하지 않아야해요.
현재 로스트아크M 한정으로 제공되는 기능이에요.
2025년 11월 12일 기준, 게임 해지 API는 로스트아크M 한정으로 기능이 제공되는 상태예요. 다른 게임에서 호출하면 정상 동작하지 않을 수 있어요. 향후 전체 게임에 사용 가능하도록 개선 중이며, 전체 사용 가능해지면 본 안내는 제거될 예정이에요.
게임 해지 ≠ STOVE 회원 탈퇴
본 API는 게임 단위 해지(약관 철회)만 처리해요. STOVE 통합 회원 탈퇴는 STOVE 웹 페이지에서 별도로 진행돼요.
사전 준비
Base_RestartAppIfNecessaryAsync콜백의restartAppIfNecessary == false분기에서Base_InitializeEx를 호출해 Base 초기화를 완료해요. 이어서IAP_Initialize(shopKey)(부모 창 지정이 필요하면IAP_InitializeWithWndInfo(shopKey, mainWndHandle))로 IAP 모듈을 초기화해요. 초기화가 완료된 뒤에 게임 해지 API를 호출해야 해요.- 게임 루프에서 콜백 실행 함수(
Base_RunCallback())가 주기적으로 호출돼야 비동기 콜백(해지 결과 콜백, 팝업 종료 콜백)이 동작해요. - 약관 철회가 성공하면 SDK 내부 이용자 토큰이 만료돼요. 이후 흐름을 SDK 호출 없이 게임 종료 안내 → 프로세스 종료까지 처리하도록 미리 설계해야 해요.
개발 흐름
- 옵션 구성: 해지 흐름 파라미터(
StovePCWithdrawGameOption)에 WebView 모드(Internal/External)와 위치·크기를 설정해요. 위치를 정중앙으로 두고 싶으면 PosX/PosY를-1로 지정해요. - API 호출: 게임 해지 API(
IAP_WithdrawGame)로 약관 철회 팝업을 띄워요. - 결과 콜백 처리: 해지 결과 콜백으로
gameWithdrawal == true면 해지가 진행된 것으로 처리해요. - 팝업 종료 콜백 처리: 팝업 종료 콜백으로 이용자가 팝업을 닫은 시점을 받아 게임 종료 안내 UI를 노출해요.
- 게임 종료 처리: 약관 철회가 완료되면 SDK 토큰이 만료되므로 추가 SDK 호출 없이 이용자에게 결과만 안내한 뒤 게임 프로세스를 종료해요.
트러블슈팅
| 상황 | 원인 | 해결 방법 |
|---|---|---|
| 게임 해지 API를 호출했는데 팝업이 뜨지 않거나 정상 동작하지 않아요 | 본 API는 현재 로스트아크M 한정으로 기능이 제공돼요. 다른 게임에서 호출하면 STOVE 백엔드에서 처리되지 않아요. | 본 게임이 기능 적용 대상인지 퍼블리싱 기술 담당자에게 확인하고, 비대상 게임이면 호출 흐름을 비활성화해야 해요. 향후 전체 게임 지원 시점에 다시 활성화하면 문제없어요. |
| 초기화 직후 호출했더니 실패해요 | Base_RestartAppIfNecessaryAsync는 비동기이며 콜백은 Base_RunCallback 호출 시 디스패치돼요. 콜백의 restartAppIfNecessary == false 분기에서 Base_InitializeEx를 호출해야 초기화가 완료돼요. 이 순서가 완료되기 전에 게임 해지 API를 호출하면 실패해요. | Base_RestartAppIfNecessaryAsync 콜백 → Base_InitializeEx → IAP_Initialize 성공 이후에 게임 해지 API를 호출해야 해요. 부팅 시퀀스에서 초기화 완료 여부를 플래그로 확인하면 문제없어요. |
| 약관 철회 후 게임을 계속 진행하니 SDK API가 인증 오류를 반환해요 | 게임 해지 API 성공 시 SDK 내부 이용자 토큰이 만료돼요. 이후 SDK API 호출은 보장되지 않아요. | 결과 콜백에서 gameWithdrawal == true이면 추가 SDK 호출을 하지 말고, 팝업 종료 콜백까지 받은 뒤 이용자 안내 → 게임 종료로 흐름을 마무리해야 해요. |
| 결과 콜백 또는 팝업 종료 콜백이 호출되지 않아요 | 게임 메인 루프에서 콜백 실행 함수(Base_RunCallback())가 호출되지 않으면 SDK가 결과를 게임에 전달할 수 없어요. | 메인 루프에서 매 프레임 또는 일정 주기로 콜백 실행 함수를 호출해야 해요. |
시퀀스 다이어그램
샘플 코드
#include "IAPSDK.h"
using namespace Stove::PCSDK;
using namespace Stove::PCSDK::Base;
using namespace Stove::PCSDK::IAP;
void IAP_WithdrawGame_Example()
{
StovePCWithdrawGameOption Option;
Option.SetWebviewMode(WebViewMode::INTERNAL);
// 정중앙 배치를 원할 경우 PosX/PosY를 -1로 지정
Option.SetWebviewRect(0, 0, 800, 600);
IAP_WithdrawGame(&Option,
[](CallbackResult CallbackResult, bool GameWithdrawal)
{
if (CallbackResult.GetResult().IsSuccessful() && GameWithdrawal)
{
// 게임 해지 성공 처리
}
},
[](CallbackResult CallbackResult)
{
// 팝업 종료 후 결과 안내 + 게임 종료
}
);
}
서버 연동
개발 흐름 - 즉시 탈퇴 처리
- 유저가 게임 내에서 탈퇴 신청을 해요.
- 클라이언트가 게임 서버에 요청을 Game User Access Token을 같이 전달해요.
- 게임 서버 내, 유저 정보를 삭제해요.(트랜잭션으로 제어 합니다)
DELETE /stove-terms/v3.0/agree?service_id={게임id}를 호출해 탈퇴 요청을 보냅니다.
이때 Game User Access Token을 같이 보내주세요.- STOVE에서 탈퇴 완료 및 데이터를 삭제시킵니다.
- game server 측으로 성공 응답을 줍니다.
- 유저가 탈퇴완료 되었고, 게임에서 접속 종료시킵니다.
- 유예기간 없이 즉시 탈퇴 처리

개발 흐름 - 유예기간의 탈퇴 처리
- 유저가 게임 내에서 탈퇴 신청을 해요.
- 클라이언트가 게임 서버에 요청을 Game User Access Token을 같이 전달해요.
- 게임 서버 내, 유저 정보를 탈퇴 신청 상태로 변경합니다.(트랜잭션으로 제어 합니다)
DELETE /stove-terms/agree?service_id={게임id}&delete_yn=N를 호출해 탈퇴 요청을 보냅니다.
이때 Game User Access Token을 같이 보내주세요.- STOVE에서 탈퇴 신청을 진행합니다.
- game server 측으로 탈퇴 예정일자와 성공 응답을 줍니다.
- 유저가 탈퇴가 신청 되었고, 게임에서 접속 종료시킵니다.
- 유예기간를 두고 유저 탈퇴 처리

트러블슈팅
응답 code 별 처리 방안이에요. 상세 응답 코드·메시지 스펙은 API & SDK 레퍼런스 메뉴를 참고하세요.
| 응답 code | 상황 | 처리 방안 |
|---|---|---|
| 70800 | 파라미터의 service_id 값을 잘못 입력한 경우 | 자신의 게임에 맞는 값을 입력해주세요. |
| 70806 | parameter의 service_id 값을 잘못 입력한 경우 | 자신의 게임에 맞는 값을 입력해주세요. |
| 70816 | STOVE 서버 내부의 오류 | 일시적 오류일 수 있으니 재시도 후, 지속되면 기술 담당자를 통해서 문의주세요. |
| 70820 | 이미 탈퇴 신청 중인 유저인 경우 | 중복 탈퇴 신청할 수 없습니다. |
| 70825 | 게임 가입(이용 동의)이 되지 않은 유저인 경우 | 게임 가입이 되지 않았기 때문에 탈퇴 신청을 할 수 없습니다. |
| 70853 | STOVE 서버 내부의 오류 | 일시적 오류일 수 있으니 재시도 후, 지속되면 기술 담당자를 통해서 문의주세요. |
| 70854 | STOVE 서버 내부의 오류 | 일시적 오류일 수 있으니 재시도 후, 지속되면 기술 담당자를 통해서 문의주세요. |
| 70870 | request header에 caller-id를 누락한 경우 | request header에 caller-id key 값을 넣어주세요. |
| 70899 | 파라미터 값이 유효하지 않을 경우 | 올바른 파라미터 값을 입력해주세요. |
샘플 코드
게임 탈퇴 신청 API (DELETE /stove-terms/v3.0/agree?service_id={게임id}) 호출 예제예요.
Base URL은 환경(Live/Sandbox)에 맞춰 교체해 주세요
운영 환경에서는 하드코딩 대신 환경 변수(예: STOVE_API_BASE_URL)나 프레임워크 설정 파일로 분리해 환경별로 주입하는 것을 권장해요.
Game User Access Token 은 매 요청마다 발급된 토큰을 사용하세요
토큰을 로그/저장소에 남기지 마시고, 즉시 폐기되는 변수로만 다뤄주세요. 즉시 철회(delete_yn=Y, 기본값)와 유예 상태(delete_yn=N)는 같은 호출의 쿼리 파라미터로만 달라져요.
// Java 25 LTS — java.net.http.HttpClient + Jackson(ObjectMapper)
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
import java.util.UUID;
ObjectMapper mapper = new ObjectMapper();
String baseUrl = "https://api.onstove.com";
String serviceId = "STOVE_EPIC7";
String callerId = serviceId + "_SERVER";
String callerDetail = UUID.randomUUID().toString();
try (HttpClient client = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(5))
.build()) {
// 유예 처리(철회 예정 상태)는 URL 끝에 &delete_yn=N 추가
URI uri = URI.create(baseUrl + "/stove-terms/v3.0/agree?service_id=" + serviceId);
HttpRequest req = HttpRequest.newBuilder(uri)
.header("Content-Type", "application/json")
.header("Authorization", "Bearer " + gameUserAccessToken)
.header("caller-id", callerId)
.header("caller-detail", callerDetail)
.DELETE()
.build();
HttpResponse<String> res = client.send(req, HttpResponse.BodyHandlers.ofString());
JsonNode data = mapper.readTree(res.body());
if (data.path("code").asInt() != 0) {
// 트러블슈팅 표 참고 (70800 / 70816 / 70820 / 70825 / 70899 등)
throw new IllegalStateException("withdraw failed: " + data.path("code"));
}
long withdrawDt = data.path("value").path("withdraw_dt").asLong(0L);
if (withdrawDt > 0) {
// 유예기간 모드 — withdrawDt 는 unix-ms 탈퇴 예정 일자. 안내 후 게임 세션 종료
} else {
// 즉시 철회 완료 — 게임 세션 종료
}
}