[Flutter] Camera 플러그인을 사용하여 사진 촬영하는 방법

[Flutter] Camera 플러그인을 사용하여 사진 촬영하는 방법

2023-07-15 hit count image

Flutter에서 사진 촬영 등 카메라 기능을 사용하기 위해 Camera 플러그인을 사용하는 방법에 대해서 알아보도록 하겠습니다.

개요

Flutter에서 사진 촬영등 카메라 기능을 사용하기 위해서는 Flutter에서 제공하는 Camera 플러그인을 사용할 필요가 있습니다.

이번 블로그 포스트에서는 Camera 플러그인을 사용하여 사진 촬영하는 방법에 대해서 알아보도록 하겠습니다. 여기서 소개하는 소스코드는 GitHub에서 확인하실 수 있습니다.

프로젝트 생성

Camera 플러그인을 통해 Flutter에서 사진 촬영하는 방법을 알아보기 위해, 다음 명령어를 사용하여 새로운 Flutter 프로젝트를 생성합니다.

flutter create camera_example

Camera 플러그인 설치

새로운 Flutter 프로젝트가 생성되었다면, 다음 명령어를 실행하여 Camera 플러그인을 설치합니다.

flutter pub add camera

iOS 설정

iOS에서 Camera 플러그인을 사용하기 위해서는 권한 설정을 해야 합니다. ios/Runner/Info.plist 파일을 열고 다음과 같이 권한을 추가합니다.

  ...
	<key>NSCameraUsageDescription</key>
	<string>Camera permission is required.</string>
	<key>NSMicrophoneUsageDescription</key>
	<string>Microphone permission is required.</string>
</dict>
</plist>

안드로이드 설정

Camera 플러그인은 안드로이드 SDK 21 이상만을 지원합니다. 따라서 android/app/build.gradle 파일을 열고 다음과 같이 minSdkVersion을 수정해야 합니다.

  ...
  defaultConfig {
    ...
    minSdkVersion 21
    ...
  }
  ...

사진 촬영 기능 구현

이번 블로그 포스트에서는 Camera 플로그인을 사용하여 사진을 촬영하는 화면과 촬영한 사진을 보여주는 화면을 구현하는 방법에 대해서 소개하겠습니다.

사진 촬영

Camera 플러그인을 사용하여 사진 촬영하는 화면을 구현하기 위해, lib/camera_screen.dart 파일을 생성하고 다음과 같이 수정합니다.

import 'package:camera/camera.dart';
import 'package:camera_example/photo_preview.dart';
import 'package:flutter/material.dart';

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

  @override
  State<CameraScreen> createState() => _CameraScreenState();
}

class _CameraScreenState extends State<CameraScreen> {
  CameraController? _cameraController;
  bool _isCameraReady = false;

  @override
  void initState() {
    super.initState();

    availableCameras().then((cameras) {
      if (cameras.isNotEmpty && _cameraController == null) {
        _cameraController = CameraController(
          cameras.first,
          ResolutionPreset.medium,
        );

        _cameraController!.initialize().then((_) {
          setState(() {
            _isCameraReady = true;
          });
        });
      }
    });
  }

  void _onTakePicture(BuildContext context) {
    _cameraController!.takePicture().then((image) {
      Navigator.of(context).push(
        MaterialPageRoute(
          builder: (context) => PhotoPreview(
            imagePath: image.path,
          ),
        ),
      );
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Take a photo')),
      body: SafeArea(
        child: Column(
          children: [
            Expanded(
              flex: 1,
              child: _cameraController != null && _isCameraReady
                  ? CameraPreview(_cameraController!)
                  : Container(
                      color: Colors.grey,
                    ),
            ),
            Padding(
              padding: const EdgeInsets.all(16),
              child: ElevatedButton(
                onPressed: _cameraController != null
                    ? () => _onTakePicture(context)
                    : null,
                child: const Text('Take a photo'),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

Camera 플러그인을 사용하는 코드를 좀 더 자세히 살펴보겠습니다.

...
@override
void initState() {
  super.initState();

  availableCameras().then((cameras) {
    if (cameras.isNotEmpty && _cameraController == null) {
      _cameraController = CameraController(
        cameras.first,
        ResolutionPreset.medium,
      );

      _cameraController!.initialize().then((_) {
        setState(() {
          _isCameraReady = true;
        });
      });
    }
  });
}
...

Camera 플러그인의 availableCameras 함수를 사용하여 카메라가 사용 가능한지 확인합니다. 카메라가 사용 가능하면 CameraController를 초기화합니다.

...
Expanded(
  flex: 1,
  child: _cameraController != null && _isCameraReady
      ? CameraPreview(_cameraController!)
      : Container(
          color: Colors.grey,
        ),
),
...

이렇게 초기화한 CameraControllerCamera 플러그인이 제공하는 CameraPreview 위젯을 사용하여 카메라 촬영 화면을 구성합니다.

...
void _onTakePicture(BuildContext context) {
  _cameraController!.takePicture().then((image) {
    Navigator.of(context).push(
      MaterialPageRoute(
        builder: (context) => PhotoPreview(
          imagePath: image.path,
        ),
      ),
    );
  });
}
...

마지막으로 CameraControllertakePicture 함수를 사용하여 사진 촬영 기능을 구현합니다. 사진 촬영된 결과물은 XFile로 반환되며, 이렇게 반환된 사진 이미지의 경로를 사진 촬영 결과물을 표시하기 위한 화면으로 전달합니다.

사진 촬영 결과 표시

Camera 플러그인을 사용하여 촬영한 사진을 화면에 표시하기 위해, lib/photo_preview.dart 파일을 생성하고 다음과 같이 수정합니다.

import 'dart:io';

import 'package:flutter/material.dart';

class PhotoPreview extends StatelessWidget {
  final String imagePath;

  const PhotoPreview({required this.imagePath, super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Preview')),
      body: Container(
        color: Colors.grey,
        child: Center(
          child: Image.file(
            File(imagePath),
          ),
        ),
      ),
    );
  }
}

Camera 플러그인으로 촬영한 사진의 경로를 전달받으므로, 전달받은 사진의 경로를 Image.file을 사용하여 표시합니다.

...
child: Image.file(
  File(imagePath),
),
...

main.dart

이렇게 만든 화면을 사용하기 위해 lib/main.dart 파일을 다음과 같이 수정합니다.

import 'package:camera_example/camera_screen.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Camera Example',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const CameraScreen(),
    );
  }
}

확인

Flutter에서 Camera 플러그인을 사용하여 사진 촬영 기능을 구현해보았습니다. 이제 앱을 실행하여 사진 촬영 기능이 정상적으로 동작하는지 확인해보겠습니다.

카메라 기능은 시뮬레이터(에뮬레이터)에서는 사용할 수 없으므로, 실제 단말기를 사용하여 앱을 실행해야 합니다. 앱을 실행하면 다음과 같이 카메라의 권한을 물어보는 화면이 표시됩니다.

Flutter Camera plugin - camera permission on iOS

OK를 눌러 권한을 설정하면, 다음과 같이 마이크에 대한 권한을 물어보는 화면이 표시됩니다.

Flutter Camera plugin - microphone permission on iOS

모든 권한을 설정하면 다음과 같이 카메라 촬영 화면이 표시되는 것을 확인할 수 있습니다.

Flutter Camera plugin - take a photo view on iOS

마지막으로, Take a photo 버튼을 눌러 사진을 촬영하면 다음과 같이 촬영된 사진이 화면에 표시되는 것을 확인할 수 있습니다.

Flutter Camera plugin - image preview on iOS

테스트 코드

Camera 플러그인을 사용하여 구현한 사진 촬영 기능에 대한 테스트 코드는 다음 블로그를 참고해 주시기 바랍니다.

완료

이것으로 Camera 플러그인을 사용하여 Flutter에서 사진 촬영 기능을 구현하는 방법에 대해서 알아보았습니다. 공식 문서에서도 Camera 플러그인을 사용하여 사진 촬영 기능을 구현하는 방법에 대해서 소개하고 있으니, 참고하시면 좋을 것 같습니다.

제 블로그가 도움이 되셨나요? 하단의 댓글을 달아주시면 저에게 큰 힘이 됩니다!

앱 홍보

책 홍보

스무디 한 잔 마시며 끝내는 React Native 책을 출판한지 벌써 2년이 다되었네요.
이번에도 좋은 기회가 있어서 스무디 한 잔 마시며 끝내는 리액트 + TDD 책을 출판하게 되었습니다.

아래 링크를 통해 제가 쓴 책을 구매하실 수 있습니다.
많은 분들에게 도움이 되면 좋겠네요.

스무디 한 잔 마시며 끝내는 React Native, 비제이퍼블릭
스무디 한 잔 마시며 끝내는 리액트 + TDD, 비제이퍼블릭
[심통]현장에서 바로 써먹는 리액트 with 타입스크립트 : 리액트와 스토리북으로 배우는 컴포넌트 주도 개발, 심통
Posts