테마
버그와 개선 의견 제출
로그인과 앱 참여 승인이 완료되면 submitBug() 또는 submitFeedback()을 호출합니다. 두 함수 모두 coroutine에서 실행하는 suspend 함수이며 결과로 SubmittedIssue를 반환합니다.
SDK는 호스트가 전달한 텍스트만 전송합니다. 화면, 로그, 입력값, 기기 정보, 충돌 정보를 자동으로 수집하지 않습니다. 전송 전에 보고서 내용과 포함할 기기 정보를 사용자에게 보여주세요.
버그 제출
kotlin
import dev.opentester.sdk.BugReport
val report = BugReport(
title = "저장 버튼이 동작하지 않아요",
description = "새 프로젝트에서 제목을 입력한 뒤 저장을 눌렀습니다.",
steps = "1. 새 프로젝트 열기\n2. 제목 입력\n3. 저장 누르기",
expected = "프로젝트가 저장되고 목록으로 이동",
actual = "화면 변화 없이 입력한 내용이 남음",
appVersion = "1.0.0-test",
deviceInfo = "Pixel; Android 16",
)
// 인증된 tester를 coroutine에서 호출합니다.
val submitted = tester.submitBug(report)개선 의견 제출
kotlin
import dev.opentester.sdk.FeedbackReport
val report = FeedbackReport(
title = "검색창 옆에 필터를 배치해 주세요",
description = "현재는 목록 끝까지 내려가야 필터를 찾을 수 있습니다.",
appVersion = "1.0.0-test",
)
val submitted = tester.submitFeedback(report)개선 의견은 kind: "feedback"으로 저장됩니다. FeedbackReport.deviceInfo는 생략할 수 있습니다. BugReport.deviceInfo는 생성자 인자이지만 수집할 정보가 없다면 빈 문자열을 지정할 수 있습니다.
입력 제한
서버는 문자열의 앞뒤 공백을 제거한 뒤 다음 제한을 검사합니다. 호스트 폼에도 같은 제한을 적용하면 제출 실패를 줄일 수 있습니다.
| 필드 | 필수 여부 | 제한 |
|---|---|---|
title | 필수 | 1–160자 |
description | 필수 | 1–10,000자 |
steps | 버그에서 선택 | 최대 10,000자 |
expected | 버그에서 선택 | 최대 5,000자 |
actual | 버그에서 선택 | 최대 5,000자 |
appVersion | 필수 | 1–100자 |
deviceInfo | 값은 선택 | 최대 500자 |
clientRequestId | 필수, 기본 자동 생성 | UUID |
submitBug()와 submitFeedback()은 제목·설명이 비어 있으면 네트워크 요청 전에 IllegalArgumentException을 던집니다. 다른 입력 제한은 서버가 검사하며 위반 시 OpenTesterException.Api의 상태 코드가 400입니다.
중복 제출과 재시도
보고서 객체는 생성될 때 clientRequestId를 만듭니다. 네트워크가 끊겨 결과를 받지 못했다면 같은 보고서 객체 또는 같은 UUID로 재시도합니다. 서버는 같은 앱·테스터·clientRequestId의 요청에 기존 보고서를 반환합니다.
kotlin
// 폼을 확정할 때 한 번 생성해 ViewModel 등 유지되는 객체에 보관합니다.
val pending = BugReport(
title = "목록이 새로 고쳐지지 않음",
description = "새 항목을 추가했지만 목록에 나타나지 않습니다.",
appVersion = "1.0.0-test",
deviceInfo = "",
)
// 첫 시도와 재시도 모두 pending을 전달합니다.
val result = tester.submitBug(pending)같은 UUID에 다른 내용을 보내도 기존 보고서가 반환되며 내용이 수정되지 않습니다. 사용자가 내용을 바꾸어 새 보고서를 제출한다면 새 UUID를 사용하세요. SDK가 자동으로 재시도하거나 오프라인에서 요청을 저장하지는 않습니다.
오류 처리
다음은 인증된 tester와 report를 coroutine에서 사용하는 처리 예입니다. statusText를 앱의 상태 UI에 연결합니다.
kotlin
import dev.opentester.sdk.OpenTesterException
import kotlinx.coroutines.CancellationException
val statusText = try {
val issue = tester.submitBug(report)
"제출 완료: ${issue.id}"
} catch (e: CancellationException) {
throw e
} catch (e: OpenTesterException.NotAuthenticated) {
"테스터 로그인이 필요합니다."
} catch (e: OpenTesterException.Network) {
"연결을 확인한 뒤 같은 보고서로 다시 시도해 주세요."
} catch (e: OpenTesterException.Api) {
when (e.statusCode) {
400 -> "보고서의 필수 항목과 길이를 확인해 주세요."
401 -> "세션이 만료되었습니다. 다시 로그인해 주세요."
403 -> "이 앱의 참여 승인 상태를 확인해 주세요."
429 -> "요청이 많습니다. 잠시 후 다시 시도해 주세요."
else -> e.message ?: "요청을 처리하지 못했습니다."
}
} catch (e: OpenTesterException) {
e.message ?: "응답을 처리하지 못했습니다."
} catch (e: IllegalArgumentException) {
"제목과 설명을 입력해 주세요."
}서버가 401 또는 403을 반환하면 SDK는 메모리의 인증 세션을 제거합니다. 참여 상태를 확인하고 다시 로그인한 뒤 제출하세요. coroutine 취소를 일반 오류로 삼키지 않도록 CancellationException은 다시 던집니다.
제출 후 흐름
새 보고서의 상태는 open입니다. 개발자는 콘솔에서 내용을 확인하고 confirmed, fixed, closed 등으로 상태를 변경할 수 있습니다. 제출 성공만으로 XP나 보상이 지급되지는 않으며 기여 심사가 별도로 진행됩니다.
SDK는 제출 결과의 id, title, status를 반환합니다. 테스터의 기여·보상 내역은 웹 로그인 후 확인하며, SDK 토큰으로 개발자용 API나 보상함에 접근할 수 없습니다.