---
title: Kotlin API 레퍼런스
description: OpenTester Android SDK 0.1.0의 설정, 함수, 데이터 모델과 오류 타입입니다.
---

# Kotlin API 레퍼런스

패키지는 `dev.opentester.sdk`이며 현재 문서는 SDK `0.1.0`을 기준으로 합니다.

## OpenTesterConfig

```kotlin
data class OpenTesterConfig(
    val appId: String,
    val apiBaseUrl: String,
    val webBaseUrl: String,
    val redirectUri: String,
    val allowInsecureLocalhost: Boolean = false,
    val languageTag: String = "en",
)
```

| 필드                     | 설명                                                                        |
| ------------------------ | --------------------------------------------------------------------------- |
| `appId`                  | 개발자 콘솔에서 생성한 앱 ID. 서버에는 유효한 UUID가 필요합니다.            |
| `apiBaseUrl`             | API 서버 origin. 예: `https://api.example.com`. `/api/v1`은 SDK가 붙입니다. |
| `webBaseUrl`             | OpenTester 웹 origin. 로그인 경로 `/sdk/authorize`는 SDK가 붙입니다.        |
| `redirectUri`            | 등록한 HTTPS App Link. query·fragment·사용자 정보를 넣을 수 없습니다.       |
| `allowInsecureLocalhost` | 개발용 로컬 HTTP와 샘플 callback 허용. 기본 `false`.                        |
| `languageTag`            | SDK 메시지, API `Accept-Language`, 브라우저 인증 화면의 언어. 기본 `en`.    |

서버 origin에는 경로, 사용자 정보, query, fragment를 넣지 않습니다. 기본적으로 HTTPS만 허용합니다. `allowInsecureLocalhost = true`일 때 HTTP는 `localhost`, `127.0.0.1`, `10.0.2.2`, `[::1]`에서만 허용하며 Android의 cleartext 정책은 별도 설정해야 합니다.

개발용 custom scheme은 `opentester-sample`만 허용합니다. 배포 설정은 검증된 HTTPS App Links를 사용합니다. 잘못된 설정은 생성 시 예외를 던집니다.

지원 언어는 영어, 한국어, 일본어, 독일어, 프랑스어, 힌디어, 브라질 포르투갈어, 튀르키예어, 인도네시아어입니다. 예: `ko-KR`, `ja-JP`, `pt-BR`. 미지원 언어는 영어로 대체하며 사용자 작성 보고서는 번역하지 않습니다.

## OpenTester

```kotlin
class OpenTester(val config: OpenTesterConfig)
```

앱에 하나의 인스턴스를 만들고 Activity 재생성 중에도 유지합니다. 모든 네트워크 함수는 내부에서 `Dispatchers.IO`를 사용합니다. 연결 timeout은 10초, 읽기 timeout은 15초이며 HTTP redirect를 따라가지 않습니다.

| 함수                                             | 반환값           | 동작                                                                                     |
| ------------------------------------------------ | ---------------- | ---------------------------------------------------------------------------------------- |
| `authenticate(activity: Activity)`               | `Unit`           | 새 로그인 상태를 만들고 시스템 브라우저 Custom Tab을 엽니다. 메인 스레드에서 호출합니다. |
| `createAuthenticationUri()`                      | `Uri`            | 새 로그인 URI를 생성합니다. 자체 시스템 브라우저 런처에 전달할 때 사용합니다.            |
| `suspend handleCallback(callback: Uri)`          | `AccessGrant`    | callback 검증과 일회용 코드 교환 후 SDK 세션을 저장합니다.                               |
| `suspend checkAccess()`                          | `AccessGrant`    | 서버에서 현재 앱 참여 권한을 확인합니다.                                                 |
| `suspend submitBug(report: BugReport)`           | `SubmittedIssue` | 버그를 제출합니다.                                                                       |
| `suspend submitFeedback(report: FeedbackReport)` | `SubmittedIssue` | 개선 의견을 제출합니다.                                                                  |
| `logout()`                                       | `Unit`           | 메모리의 토큰과 진행 중 인증을 지웁니다.                                                 |

`authenticate()`와 `createAuthenticationUri()`는 호출할 때 기존 SDK 세션을 초기화합니다. `logout()`은 브라우저 세션을 종료하지 않습니다. 자세한 흐름은 [인증 가이드](/sdk/authentication)를 참고하세요.

## AccessGrant와 Tester

```kotlin
data class Tester(
    val id: String,
    val name: String,
    val email: String,
)

data class AccessGrant(
    val appId: String,
    val campaignId: String,
    val user: Tester,
)
```

`AccessGrant`는 인증 또는 권한 확인 시점의 승인 결과입니다. `campaignId`는 앱에 연결된 테스트 캠페인 ID입니다. 토큰 문자열은 공개 반환 모델에 포함되지 않으며 SDK 내부 메모리에 보관됩니다. 이메일 등 테스터 정보를 불필요하게 로그에 남기지 마세요.

## BugReport

```kotlin
data class BugReport(
    val title: String,
    val description: String,
    val steps: String = "",
    val expected: String = "",
    val actual: String = "",
    val appVersion: String,
    val deviceInfo: String,
    val clientRequestId: String = UUID.randomUUID().toString(),
)
```

`appVersion`과 `deviceInfo`는 기본값이 없는 생성자 인자입니다. `deviceInfo`에 보낼 정보가 없다면 `""`를 지정합니다. `clientRequestId`는 `java.util.UUID`로 자동 생성됩니다. 재시도에는 같은 값을 사용합니다.

## FeedbackReport

```kotlin
data class FeedbackReport(
    val title: String,
    val description: String,
    val appVersion: String,
    val deviceInfo: String = "",
    val clientRequestId: String = UUID.randomUUID().toString(),
)
```

개선 의견에는 버그 전용 `steps`, `expected`, `actual` 인자가 없습니다. 두 보고서 모델의 길이 제한과 중복 처리 규칙은 [보고서 제출 가이드](/sdk/feedback#input-limits)에 설명되어 있습니다.

## SubmittedIssue

```kotlin
data class SubmittedIssue(
    val id: String,
    val title: String,
    val status: String,
)
```

새 제출의 `status`는 `open`입니다. 중복 요청에는 기존 보고서의 현재 상태를 반환할 수 있습니다. 상태는 `open`, `confirmed`, `fixed`, `closed`이며 SDK 모델에서는 문자열로 제공됩니다.

## OpenTesterException

모든 하위 타입은 `OpenTesterException`을 상속합니다.

| 타입               | 추가 필드         | 의미와 처리                                                           |
| ------------------ | ----------------- | --------------------------------------------------------------------- |
| `NotAuthenticated` | 없음              | SDK 세션이 없거나 만료됨. 로그인 시작                                 |
| `InvalidCallback`  | 없음              | 진행 중 로그인 없음, 만료, callback 또는 state 불일치. 새 로그인 시작 |
| `Api`              | `statusCode: Int` | HTTP 실패. `400` 입력 확인, `401` 재로그인, `403` 참여 권한 확인      |
| `Network`          | 원인 예외         | 연결 실패·timeout. 보고서는 같은 UUID로 재시도                        |
| `InvalidResponse`  | 원인 예외         | JSON 또는 응답 모델 해석 실패. 서버 주소와 버전 확인                  |

잘못된 설정과 빈 제목·설명은 `OpenTesterException`이 아닌 입력 검증 예외를 발생시킬 수 있습니다. SDK 함수 밖의 호스트 오류와 coroutine 취소도 별도로 처리합니다.
