본문 바로가기
잡(job)기술

Appwrite Android Quick Start 정리

by 무니이구나 2025. 5. 15.

Android 프로젝트를 Appwrite와 연동하기 위해 진행한 Quick Start 작업을 진행했지만 시행착오들을 겪었다. 첫 시도라 중간중간 기억해둬야 하겠다 싶은 개념이나 작업들이 있어, 이를 기록해두기 위해서 이 글을 작성한다.

1. Android 프로젝트 생성

  1. Android Studio에서 New Project 클릭
  2. Empty Activity 템플릿 선택 후 Next
  3. 앱 이름(App name)과 패키지 이름(Package name) 입력. 패키지 이름이 Appwrite 프로젝트의 Android 플랫폼과 연동이 되기 때문에 중요하다.
  4. 예: com.example.myapp
  5. Finish 클릭하여 프로젝트 생성

2. Appwrite 프로젝트 및 Android 플랫폼 등록

  1. 브라우저에서 Appwrite Console([https://cloud.appwrite.io](https://cloud.appwrite.io)) 접속 후 로그인
  2. Create Project 또는 기존 프로젝트 선택
  3. 프로젝트 대시보드에서 Settings > Platforms 이동
  4. Add Platform → Android 클릭
  5. App 이름과 패키지 이름 입력
  6. 패키지 이름은 Android Studio에서 설정한 com.example.myapp과 동일하게 입력
  7. Save 클릭

3. Appwrite SDK 추가

  1. app/build.gradle.kts (또는 app/build.gradle) 파일 열기

  2. dependencies 블록에 다음 한 줄 추가:

implementation("io.appwrite:sdk-for-android:7.0.1")

  3. Sync Now 클릭하여 Gradle Sync 실행

4. Appwrite 클라이언트 싱글톤 구현 및 구성 요소 설명

이 단계에서는 Appwrite SDK를 앱 전역에서 편리하게 사용하기 위해 싱글톤 패턴을 적용한다. Appwrite.kt 객체 하나에 주요 구성 요소를 모아 두어, 어디서든 `Appwrite.init(context)` 한 번으로 초기화 후 바로 호출할 수 있다.

Appwrite SDK 주요 구성 요소

  • Client: Appwrite 서버와 통신하는 HTTP 클라이언트이다.
  • setEndpoint(), setProject() 메서드를 이용해 요청할 기본 URL과 프로젝트 ID를 설정한다.
    • ID: 고유 식별자(ID)를 생성하는 유틸리티 클래스이다.
  • ID.unique() 등을 통해 사용자(User), 문서(Document) 등 리소스에 사용할 ID를 자동 생성한다.
    • Account: 사용자 인증 및 세션 관리를 담당하는 서비스 클래스이다.
  • 회원가입, 로그인, 로그아웃, 사용자 정보 조회 등의 메서드를 제공한다.

Region 및 Project ID 확인 방법

  • Region: Appwrite 인스턴스가 호스팅된 위치를 의미한다. 프로젝트를 생성할 때 선택할 수 있도록 메뉴가 나타나는데, 아직은 선택권이 없는 것 같다. Frankfurt만 사용할 수 있었다.
  • Appwrite 콘솔에 로그인 후, 프로젝트 대시보드로 진입하면 프로젝트 이름의 우측 편에 Frankfurt 라는 Region을 확인할 수 있고, 클립보드에 복사도 가능하도록 되어 있다.
  • Project ID: Appwrite 콘솔에서 프로젝트를 식별하는 고유 ID이다.
    • Region을 확인할 때와 마찬가지로 대시 보드에서 프로젝트 이름의 우측에 16진수 형태의 수로 이뤄진 값이 보인다. Region과 마찬가지로 클립보드에 복사도 가능하다.

싱글톤 구현 및 주요 메서드

  1. 파일 생성: `Appwrite.kt`를 프로젝트 루트 패키지(예: `com.example.myapp`)에 추가. 공식 문서의 quick start 예제에 간단한 설명을 추가해뒀다.

  2. 코드 예시:

package com.example.myapp

import android.content.Context
import io.appwrite.Client
import io.appwrite.ID
import io.appwrite.services.Account

object Appwrite {
    // Appwrite 서버와 통신할 클라이언트 객체
    lateinit var client: Client
    // 인증, 세션 관리 등을 처리하는 Account 서비스 객체
    lateinit var account: Account

    /**
     * 앱 시작 시 호출하여 Client와 Account를 초기화한다.
     * - context: 애플리케이션 Context
     * - setEndpoint: Appwrite 엔드포인트 URL (지역 및 버전 포함)
     * - setProject: 프로젝트 ID 설정
     */
    fun init(context: Context) {
        client = Client(context)
            .setEndpoint("https://<REGION>.cloud.appwrite.io/v1Claire
            .setProject("[PROJECT_ID]")
        account = Account(client)
    }

    /**
     * 이메일/비밀번호로 사용자 회원가입을 수행한다.
     * - userId: 고유 ID 생성 (ID 유틸 사용)
     * - email: 사용자 이메일
     * - password: 사용자 패스워드
     * 반환: 생성된 User 객체
     */
    suspend fun onRegister(email: String, password: String) = account.create(
        userId = ID.unique(),
        email = email,
        password = password
    )

    /**
     * 이메일/비밀번호로 로그인 시 세션을 생성한다.
     * - email: 사용자 이메일
     * - password: 사용자 패스워드
     * 반환: 생성된 Session 객체
     */
    suspend fun onLogin(email: String, password: String) = account.createEmailPasswordSession(email, password)

    /**
     * 현재 활성화된 세션을 삭제하여 로그아웃 처리한다.
     */
    suspend fun onLogout() {
        account.deleteSession("current")
    }
}

 

 

3. 용도 요약:

  • init: 앱 시작 시 Appwrite 서버와의 연결을 설정
  • onRegister: 신규 사용자 등록 (회원가입)
  • onLogin: 기존 사용자 로그인 및 세션 생성
  • onLogout: 로그인 세션 종료 및 로그아웃 처리

이제 이 싱글톤 객체를 통해 어느 액티비티나 컴포넌트에서든 손쉽게 Appwrite 기능을 호출할 수 있다.

5. 간단한 로그인/회원가입 화면 구현

  1. MainActivity.kt에 Compose UI 추가
  2. 아래 예제에서 package 선언은 각자가 만든 것으로 변경
package com.example.myapp

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.input.PasswordVisualTransformation
import androidx.compose.ui.unit.dp
import kotlinx.coroutines.launch

class MainActivity : ComponentActivity() {
    @OptIn(ExperimentalMaterial3Api::class)
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        Appwrite.init(applicationContext)

        setContent {
            var email by remember { mutableStateOf("") }
            var password by remember { mutableStateOf("") }
            var user by remember { mutableStateOf<String?>(null) }
            val scope = rememberCoroutineScope()

            Surface(
                modifier = Modifier.fillMaxSize(),
                color = MaterialTheme.colorScheme.background
            ) {
                Column(
                    modifier = Modifier
                        .fillMaxSize()
                        .padding(16.dp),
                    verticalArrangement = Arrangement.Center
                ) {
                    if (user != null) {
                        Text(text = "Logged in as $user")
                        Button(
                            onClick = {
                                scope.launch {
                                    try {
                                        Appwrite.onLogout()
                                        user = null
                                    } catch (e: Exception) {
                                        // 예외 처리 (예: Toast 메시지로 사용자에게 알림)
                                    }
                                }
                            },
                            modifier = Modifier.padding(top = 16.dp)
                        ) {
                            Text("Logout")
                        }
                    } else {
                        TextField(
                            value = email,
                            onValueChange = { email = it },
                            label = { Text("Email") },
                            keyboardOptions = KeyboardOptions(
                                keyboardType = KeyboardType.Email
                            ),
                            modifier = Modifier.fillMaxWidth()
                        )
                        TextField(
                            value = password,
                            onValueChange = { password = it },
                            label = { Text("Password") },
                            visualTransformation = PasswordVisualTransformation(),
                            modifier = Modifier
                                .fillMaxWidth()
                                .padding(top = 8.dp)
                        )
                        Row(
                            modifier = Modifier
                                .fillMaxWidth()
                                .padding(top = 16.dp),
                            horizontalArrangement = Arrangement.SpaceEvenly
                        ) {
                            Button(onClick = {
                                scope.launch {
                                    try {
                                        Appwrite.onLogin(email, password)
                                        user = email
                                    } catch (e: Exception) {
                                        // 예외 처리 (예: Toast 메시지로 사용자에게 알림)
                                    }
                                }
                            }) {
                                Text("Login")
                            }
                            Button(onClick = {
                                scope.launch {
                                    try {
                                        Appwrite.onRegister(email, password)
                                        // 회원가입 후 자동 로그인 처리 (선택 사항)
                                        user = email
                                    } catch (e: Exception) {
                                        // 예외 처리 (예: Toast 메시지로 사용자에게 알림)
                                    }
                                }
                            }) {
                                Text("Register")
                            }
                        }
                    }
                }
            }
        }
    }
}

 

6. 실행 및 확인

  1. 에뮬레이터 또는 실제 기기에서 앱 실행
  2. RegisterLoginLogout 순으로 기능 동작 확인