๐Ÿ”ฐFlutter์™€ ZEGOCLOUD ZIMKit์„ ์‚ฌ์šฉํ•ด ์‹ค์‹œ๊ฐ„ ์ฑ„ํŒ… ์•ฑ ๋งŒ๋“ค๊ธฐ (๋ฐฑ์—”๋“œ ์—†์ด)

๋ฐœํ–‰: (2025๋…„ 12์›” 10์ผ ์˜คํ›„ 07:54 GMT+9)
5 min read
์›๋ฌธ: Dev.to

Source: Dev.to

์†Œ๊ฐœ

์‹ค์‹œ๊ฐ„ ์ฑ„ํŒ… ๊ธฐ๋Šฅ์€ ์ด์ œ ํ˜„๋Œ€ ์•ฑ์˜ ํ•ต์‹ฌ ๊ธฐ๋Šฅ์ž…๋‹ˆ๋‹คโ€”WhatsApp ๊ฐ™์€ ๋ฉ”์‹ ์ € ํ”Œ๋žซํผ์ด๋“ , ๊ณ ๊ฐ ์ง€์› ์ฑ„ํŒ…์ด๋“ , ์ปค๋ฎค๋‹ˆํ‹ฐ ๊ทธ๋ฃน ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด๋“  ๋ง์ด์ฃ . ์„œ๋ฒ„๋ฅผ ์ง์ ‘ ๊ตฌ์ถ•ํ•˜๊ณ , WebSocket์„ ๊ด€๋ฆฌํ•˜๋ฉฐ, ๋ฉ”์‹œ์ง€๋ฅผ ์ˆ˜๋™์œผ๋กœ ๋™๊ธฐํ™”ํ•˜๋Š” ๋Œ€์‹  ZEGOCLOUD๋Š” Flutter ๊ฐœ๋ฐœ์ž๋ฅผ ์œ„ํ•œ ์ฆ‰์‹œ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ API์™€ UI ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ZIMKit์„ ์‚ฌ์šฉํ•˜๋ฉด ๋ฐฑ์—”๋“œ ์ธํ”„๋ผ๋ฅผ ๊ด€๋ฆฌํ•˜์ง€ ์•Š๊ณ ๋„ ๋ช‡ ๋ถ„ ์•ˆ์— ์‹ค์‹œ๊ฐ„ ์ฑ„ํŒ… ์•ฑ์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋ฒˆ ํŠœํ† ๋ฆฌ์–ผ์—์„œ๋Š” ๋‹ค์Œ์„ ํฌํ•จํ•œ ์‹ค์‹œ๊ฐ„ ์ฑ„ํŒ… ์•ฑ์„ ๋งŒ๋“ค๊ฒ ์Šต๋‹ˆ๋‹ค:

  • ๋กœ๊ทธ์ธ
  • 1:1 ์ฑ„ํŒ…
  • ๊ทธ๋ฃน ์ฑ„ํŒ…
  • ์‹ค์‹œ๊ฐ„ ๋ฉ”์‹œ์ง€ ์ „์†ก
  • ๋ฐฑ์—”๋“œ ๋ถˆํ•„์š”

๋งŒ๋“ค๊ฒŒ ๋  ๊ฒƒ

์ด ๊ธ€์„ ๋๊นŒ์ง€ ์ฝ์œผ๋ฉด ๋‹ค์Œ์„ ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค:

  • Flutter์— ZEGOCLOUD ZIMKit ํ†ตํ•ฉํ•˜๊ธฐ
  • ์ฑ„ํŒ… SDK ์ดˆ๊ธฐํ™”ํ•˜๊ธฐ
  • ๋กœ์ปฌ์—์„œ ์‚ฌ์šฉ์ž ๋“ฑ๋กํ•˜๊ธฐ
  • 1:1 ์ฑ„ํŒ… ๋งŒ๋“ค๊ธฐ
  • ๊ทธ๋ฃน ์ฑ„ํŒ… ์ƒ์„ฑ ๋ฐ ์ฐธ์—ฌํ•˜๊ธฐ
  • ์‹ค์‹œ๊ฐ„์œผ๋กœ ๋Œ€ํ™” ๋ชฉ๋ก ํ‘œ์‹œํ•˜๊ธฐ

ZEGOCLOUD๋ž€?

ZEGOCLOUD๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ SDK๋ฅผ ์ œ๊ณตํ•˜๋Š” ํ†ต์‹  ํ”Œ๋žซํผ์ž…๋‹ˆ๋‹ค:

  • ์ธ์•ฑ ์ฑ„ํŒ…
  • ์Œ์„ฑ ๋ฐ ์˜์ƒ ํ†ตํ™”
  • ๋ผ์ด๋ธŒ ์ŠคํŠธ๋ฆฌ๋ฐ
  • ์ธํ„ฐ๋ž™ํ‹ฐ๋ธŒ ๋ฃธ

์›น์‚ฌ์ดํŠธ:
์ธ์•ฑ ์ฑ„ํŒ… ์ œํ’ˆ:
Flutter ๋ฌธ์„œ:

1๋‹จ๊ณ„ โ€” Zego ZIMKit ์„ค์น˜

pubspec.yaml ํŒŒ์ผ์„ ์—ด๊ณ  ZIMKit ์˜์กด์„ฑ์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค:

ZIMKit ์˜์กด์„ฑ

๊ทธ๋Ÿฐ ๋‹ค์Œ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค:

flutter pub get

2๋‹จ๊ณ„ โ€” ์ฑ„ํŒ… SDK ์ดˆ๊ธฐํ™”

์ž๊ฒฉ ์ฆ๋ช…์„ ์œ„ํ•œ ํŒŒ์ผ์„ ๋งŒ๋“ค๊ณ , ์˜ˆ๋ฅผ ๋“ค์–ด utils/app_string.dart ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

โš ๏ธ AppSign์„ ๊ณต๊ฐœ ์ €์žฅ์†Œ์— ์ ˆ๋Œ€ ๋…ธ์ถœํ•˜์ง€ ๋งˆ์„ธ์š”.

ํ•„์ˆ˜ Android ์„ค์ •

๊ถŒํ•œ

android/app/src/main/AndroidManifest.xml ์— ํ•„์š”ํ•œ ๊ถŒํ•œ์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค:

Android ๊ถŒํ•œ

Proguard ๊ทœ์น™ (๋ฆด๋ฆฌ์Šค ๋ชจ๋“œ)

android/app/proguard-rules.pro ํŒŒ์ผ์„ ๋งŒ๋“ค๊ฑฐ๋‚˜ ํŽธ์ง‘ํ•ฉ๋‹ˆ๋‹ค:

Proguard ๊ทœ์น™

Build Gradle ์„ค์ •

android/app/build.gradle ๋ฅผ ํŽธ์ง‘ํ•˜๊ณ  minify์™€ proguard๋ฅผ ํ™œ์„ฑํ™”ํ•ฉ๋‹ˆ๋‹ค:

Gradle ์„ค์ •

Gradle ์Šค๋‹ˆํŽซ

3๋‹จ๊ณ„ โ€” main.dart ์—์„œ ZIMKit ์ดˆ๊ธฐํ™”

import 'package:chat_app_zegogloud/screens/login.dart';
import 'package:chat_app_zegogloud/utils/app_string.dart';
import 'package:flutter/material.dart';
import 'package:zego_zimkit/zego_zimkit.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  ZIMKit().init(appID: AppString.appID, appSign: AppString.appSign);
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Zego Chat',
      theme: ThemeData(primarySwatch: Colors.blue),
      debugShowCheckedModeBanner: false,
      home: const LoginPage(),
    );
  }
}

4๋‹จ๊ณ„ โ€” ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€ ๋งŒ๋“ค๊ธฐ

๋ฐฑ์—”๋“œ ์—†์ด userID์™€ username์„ ์‚ฌ์šฉํ•ด ๋กœ์ปฌ์—์„œ ์‚ฌ์šฉ์ž๋ฅผ ์ธ์ฆํ•ฉ๋‹ˆ๋‹ค.

screens/login.dart

import 'package:chat_app_zegogloud/screens/home.dart';
import 'package:flutter/material.dart';
import 'package:zego_zimkit/zego_zimkit.dart';

class LoginPage extends StatefulWidget {
  const LoginPage({super.key});

  @override
  State create() => _LoginPageState();
}

class _LoginPageState extends State {
  final userId = TextEditingController();
  final userName = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Login to Chat')),
      body: SingleChildScrollView(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          children: [
            TextField(
              controller: userId,
              decoration: const InputDecoration(labelText: 'User ID'),
            ),
            TextField(
              controller: userName,
              decoration: const InputDecoration(labelText: 'User Name'),
            ),
            const SizedBox(height: 20),
            ElevatedButton(
              onPressed: () {
                ZIMKit().connectUser(id: userId.text, name: userName.text);
                Navigator.of(context).push(
                  MaterialPageRoute(builder: (_) => const HomePage()),
                );
              },
              child: const Text('Login'),
            ),
          ],
        ),
      ),
    );
  }
}

5๋‹จ๊ณ„ โ€” ๋Œ€ํ™” ๋ชฉ๋ก์ด ์žˆ๋Š” ํ™ˆ ํŽ˜์ด์ง€

์ด ํŽ˜์ด์ง€์—์„œ๋Š” ๋ชจ๋“  1:1 ์ฑ„ํŒ…๊ณผ ๊ทธ๋ฃน ์ฑ„ํŒ…์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.

screens/home.dart

import 'package:chat_app_zegogloud/screens/login.dart';
import 'package:chat_app_zegogloud/screens/home_page_popUp.dart';
import 'package:flutter/material.dart';
import 'package:zego_zimkit/zego_zimkit.dart';

class HomePage extends StatefulWidget {
  const HomePage({super.key});

  @override
  State create() => _HomePageState();
}

class _HomePageState extends State {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Home Page'),
        actions: [
          IconButton(icon: const Icon(Icons.logout), onPressed: _handleLogout),
          const HomePagePopup(),
        ],
      ),
      body: ZIMKitConversationListView(
        onPressed: (context, conversation) {
          // Navigate to chat screen (implementation omitted for brevity)
        },
      ),
    );
  }

  void _handleLogout() {
    ZIMKit().logout();
    Navigator.of(context).pushReplacement(
      MaterialPageRoute(builder: (_) => const LoginPage()),
    );
  }
}

๋‚˜๋จธ์ง€ UI(์ฑ„ํŒ… ํ™”๋ฉด, ๊ทธ๋ฃน ์ƒ์„ฑ ๋“ฑ)๋Š” ZIMKitMessageListView, ZIMKitMessageInput ๊ฐ™์€ ZIMKit ์œ„์ ฏ์„ ์‚ฌ์šฉํ•˜์—ฌ ๋™์ผํ•œ ํŒจํ„ด์œผ๋กœ ๊ตฌํ˜„๋ฉ๋‹ˆ๋‹ค. ์•ฑ ๋””์ž์ธ์— ๋งž๊ฒŒ ํ•„์š”์— ๋”ฐ๋ผ ์กฐ์ •ํ•˜์„ธ์š”.

Back to Blog

๊ด€๋ จ ๊ธ€

๋” ๋ณด๊ธฐ ยป

Dart ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด ๋ฐฐ์šฐ๊ธฐ: ์ดˆ๋ณด์ž ๊ฐ€์ด๋“œ

Dart๋Š” ํฌ๋กœ์Šคโ€‘ํ”Œ๋žซํผ ๋ชจ๋ฐ”์ผ ์•ฑ์—์„œ ์ธ๊ธฐ๊ฐ€ ๊ธ‰์ฆํ•˜๊ณ  ์žˆ์œผ๋ฉฐ, ํŠนํžˆ Flutter์˜ ์ƒํƒœ๊ณ„๊ฐ€ ์ˆ˜๋…„๊ฐ„ ํญ๋ฐœ์ ์œผ๋กœ ์„ฑ์žฅํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๊ธฐ์‚ฌ์—์„œ๋Š” Dart์˜ ๋ณธ์งˆ์„ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค.

React, Tailwind ๋ฐ Zegocloud๋ฅผ ์‚ฌ์šฉํ•ด ๋น„๋””์˜ค ํ†ตํ™” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋งŒ๋“ค๊ธฐ

์†Œ๊ฐœ ์•ˆ๋…•ํ•˜์„ธ์š” ์—ฌ๋Ÿฌ๋ถ„, ์ตœ๊ทผ์— ์ €๋Š” ์ „์ฒด videoโ€‘calling ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ตฌ์ถ•ํ–ˆ์œผ๋ฉฐ ZEGOCLOUD ์„œ๋น„์Šค๋ฅผ ์‚ฌ์šฉํ•ด ๋ช‡ ๋ถ„ ๋งŒ์— ๋งŒ๋“ค ์ˆ˜ ์žˆ๋Š” ์†๋„์— ๊นœ์ง ๋†€๋ž์Šต๋‹ˆ๋‹ค.

Workflow DevKit ๋‚ด๋ถ€: ํ”„๋ ˆ์ž„์›Œํฌ ํ†ตํ•ฉ์ด ์ž‘๋™ํ•˜๋Š” ๋ฐฉ์‹

ํ•œ ๋‹ฌ ์กฐ๊ธˆ ๋„˜๊ฒŒ ์ „์— Ship AI๋ฅผ ๋ฐœํ‘œํ–ˆ์„ ๋•Œ, ์šฐ๋ฆฌ๋Š” ๊ฐœ๋ฐœ์ž๋“ค์ด ์–ด๋–ค framework๋“  ์‚ฌ์šฉํ•˜๊ณ  ์–ด๋–ค platform์ด๋“  ๋ฐฐํฌํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๊ณ  ์‹ถ์—ˆ์Šต๋‹ˆ๋‹ค.

ํ”„๋กœํ•„

ํ˜„์žฌ ์ƒํƒœ ๐ŸŸข ์ธํ„ด์‹ญ ๋ฐ ์ดˆ๊ธ‰ ๊ธฐํšŒ์— ์—ด๋ ค ์žˆ์Œ Mission: 52์ฃผ ์•ˆ์— 30๊ฐœ์˜ ์•ฑ์„ ๋งŒ๋“ค์–ด ์„ธ๊ณ„ ์ˆ˜์ค€์˜ Android ์—”์ง€๋‹ˆ์–ด๊ฐ€ ๋˜๊ธฐ. ์ €๋Š” ์—ด์ •์ž…๋‹ˆ๋‹ค...