Ionic 4 입문 첫 앱 만들기 튜토리얼(2)

원상연·2020년 11월 22일
0

2019년에 블로그에 적었던 글을 옮겨 왔습니다. 지금은 ionic5 버전이지만 튜토리얼 내용을 옮긴글인 만큼 현재 공식문서도 기본 내용은 크게 바뀌지 않은 상태입니다.


안드로이드, IOS 기기에서 카메라 이용하기

다음으로 IOS 와 Android 기기에서 네이티브 조작을 위해서 플러그인을 추가해 주겠습니다.
저 같은 경우 비주얼 스튜디오를 쓸 때 상단 목록의 터미널탭에서 New Terminal 을 이용하여 편하게 쓰고 있습니다.
이번에는 안드로이드 플랫폼만 추가해보겠습니다.

ionic cordova platform add android

해당 명령을 통해 config.xml 파일을 생성하게 됩니다. 여기서 IOS 와 Android 설정을 할 수 있습니다.

다음으로 DevApp를 설명하고 있는데
개인적으로 직접 기기에 구동시키는 것이 디버깅하기도 수훨하다고 생각하여
일부로 자르고 넘어가도록 하겠습니다.

이용하실 분들은 글에 적힌대로 아이오닉 계정과 DevApp 어플을 받으시면 무선으로 폰에서 직접 구동시킬 수 있습니다.

저는 기기에서 구동시키기 위해 먼저 현재 연결된 기기를 먼저 확인하겠습니다.

ionic cordova run android --list

현재 연결되어있는 기기가 있을 경우 위처럼 연결된 기기에 조회가 되고
없을 경우 아래의 구동 가능한 가상 기기들이 뜨게 됩니다.

혹시 현재 가상기기가 없는 경우에는 따로 설치해 주시거나 직접 기기를 연결해서 진행해 주세요.
저는 스샷 편의상 가상기기로 진행하겠습니다.

ionic cordova run android -l

위와 같이 런해주시고 뒤에 옵션에 맞게 붙여서 실행할 수 있습니다.
아래와 같이 기기에서 실시간으로 구동되게 됩니다.
진행하기 전에 디버깅하는 법을 먼저 짚고 가겠습니다.

브라우저를 이용한 디버깅

기기 디버깅도 보통 웹 js 디버깅하듯이 브라우저에서 할 수 있습니다.
먼저 아무 페이지의 F12 개발자모드로 들어가시면 아래 콘솔 옆에 Remote devices 를 볼 수 있습니다.
해당 기기를 누르면 다음과 같이 구동중인 앱을 볼 수 있고, 옆에 Inspect를 눌러서 Debug 콘솔을 확인할 수 있습니다.
다시 돌아와서 카메라 Dependencies를 추가해 주겠습니다.

카메라 기능 추가하기

그전에 tap2.page.html 에 사진촬영 아이콘을 추가해 봅시다.
< ion-content > 태그에 아래와 같이 추가해주세요

<ion-content>
<img>

<ion-fab vertical="bottom" horizontal="center" slot="fixed">
    <ion-fab-button>
      <ion-icon name="camera"></ion-icon>
    </ion-fab-button>
</ion-fab>
</ion-content>

저장하시면 바로 구동중인 앱에도 버튼이 추가되는 모습 보실 수 있습니다.
다음으로 기기의 사진 기능을 이용하기 위해 dependencies 와 plugin 을 추가해 주겠습니다.

npm install @ionic-native/camera

위를 실행하면 package.json 에 자바스크립트 dependency 가 아래와 유사하게 추가 된 것을 확인할 수 있습니다.

@ionic-native/camera": "^5.13.0"

이어서 아래도 실행해 주세요.

ionic cordova plugin add cordova-plugin-camera

추가로 IOS의 경우 10 버전부터 아래와 같이 config.xml에 접근 사유를 적어줘야 한다고 합니다.

<!-- Required for iOS 10: Camera permission prompt -->
<edit-config file="*-Info.plist" mode="merge" target="NSCameraUsageDescription">
    <string>Used to take pictures</string>
</edit-config>

카메라 플러그인 앵귤러 앱 모듈에 추가

다음으로 src/app/app.module.ts 에서 카메라 모듈을 임포트 하겠습니다.

import { Camera } from '@ionic-native/camera/ngx';

그리고 Provider 에도 Camera 를 아래 형식처럼 추가해 주세요.

providers: [
    StatusBar,
    SplashScreen,
    Camera,
    {provide: ErrorHandler, useClass: IonicErrorHandler}
  ],

아래 처럼 추가했습니다.

갤러리 페이지에 사진 추가하기

지금 버튼은 아무 기능도 없으므로 tab2.page.html 에 click handler 를 추가해줍니다.

<ion-fab vertical="bottom" horizontal="center" slot="fixed">
  <ion-fab-button (click)="takePicture()">
    <ion-icon name="camera"></ion-icon>
  </ion-fab-button>
</ion-fab>

다음으로 image placeholder도 바꿔주어 추후 현재 이미지가 뜰 수 있게 해줍니다.

<img [src]="currentImage" *ngIf="currentImage">

tap2.page.ts 를 열어서 카메라 라이브러리를 임포트 해줍니다.

import { Camera, CameraOptions } from '@ionic-native/camera/ngx';

currentImage 변수를 선언해주고 Camera 를 현재 class constructor 에 주입해줍니다.

export class Tab2Page {
  currentImage: any;

  constructor(private camera: Camera) { }
}

이제 tab2.page.ts 에 takePicture 매서드를 추가해 줍시다.

export class Tab2Page {
  currentImage: any;

  constructor(private camera: Camera) { }

  takePicture() {
    const options: CameraOptions = {
      quality: 100,
      destinationType: this.camera.DestinationType.DATA_URL,
      encodingType: this.camera.EncodingType.JPEG,
      mediaType: this.camera.MediaType.PICTURE
    };

    this.camera.getPicture(options).then((imageData) => {
      this.currentImage = 'data:image/jpeg;base64,' + imageData;
    }, (err) => {
      // Handle error
      console.log("Camera issue:" + err);
    });
  }
}

이렇게만 해주면 IOS 와 Android 에서 동시에 잘 작동하게 됩니다.
가상 기기에서는 카메라 촬영을 켜볼 수 없지만,
연결된 기기에서 버튼을 클릭하면 사진촬영이 뜨게됩니다.
다음으로 해당 앱을 실제 사진 갤러리로 만들고, 사진을 저장하게끔 추가해주겠습니다.

기기에 저장되는 포토 갤러리 만들기

https://ionicframework.com/docs/developer-resources/guides/first-app-v4/creating-photo-gallery-device-storage

서비스를 이용한 카메라 기능 추가하기

프로젝트 위치 터미널에서 아래를 실행시킵니다.

ionic g service services/Photo

services 폴더 아래 PhotoService 가 아래와 같이 추가 됩니다.

import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class PhotoService {
  constructor() { }
}

Photo 클래스를 추가합니다. data 속성은 base64 이미지 입니다.

class Photo {
  data: any;
}

다음으로 사진 갤러리의 Photos 배열을 만들어줍니다.

export class PhotoService {

  public photos: Photo[] = [];

  constructor() { }
}

tab2.page.ts 로 돌아와서 PhotoService 를 임포트하고, Constuctor 에도 아래와 같이 추가해줍니다.

import { PhotoService } from '../services/photo.service';
constructor(private camera: Camera, public photoService: PhotoService) {  }

이제, 기존 카메라 플러그인 코드를 PhotoService 로 모두 옮기겠습니다.
따로 서비스에 옮겨 놓고 임포트해서 사용합니다.
takePicture 매서드와 Camera, CameraOptions 임포트 그리고 Tab2Page의 constructor 옮기면 됩니다.
옮긴 후 기존 이미지 말고 photos 배열로 바꿔줘야 합니다.

this.camera.getPicture(options).then((imageData) => {
    // Add new photo to gallery
    this.photos.unshift({
        data: 'data:image/jpeg;base64,' + imageData
    }); }, (err) => {
    // Handle error
    console.log("Camera issue: " + err);
});

tab2.pages.ts 에는 currentImage 변수와 constructor 의 Camera 를 모두 지우고 PhotoService 만 남겨놉니다.

export class Tab2Page {
  constructor(public photoService: PhotoService) {  }
}

다음으로 tab2.page.html 에서 기존 이미지 태크를 지우고 ion-grid 컴포턴트를 이용하여 정렬합니다.
한 줄에 사진 2장씩 들어가게 루프를 돌려서 칼럼을 추가해 줍니다.
ion-row에 12개의 블럭으로 공간이 되어있으므로, col 사이즈를 6으로 주고 한 줄에 2장씩 들어가게 합니다.

<ion-grid>
  <ion-row>
    <ion-col size="6" *ngFor="let photo of photoService.photos">
      <img [src]="photo.data" />
    </ion-col>
  </ion-row>
</ion-grid>

아까 버튼에서 불러오던 takePicture 매서드 앞에 photoService 를 붙여서 불러오도록 합니다.

<ion-fab-button (click)="photoService.takePicture()">
  <ion-icon name="camera"></ion-icon>
</ion-fab-button>

기기에 사진 저장하기

마지막으로 앱이 꺼져도 사진이 기기에 저장되도록 해줘야 합니다.
먼저 네이티브에 SQLite 플러그인을 추가해줍니다.

ionic cordova plugin add cordova-sqlite-storage

다음으로 웹에서 사용할 자바스크립트 라이브러리를 추가합니다.

npm install --save @ionic/storage

app.module.ts 에 스토리지 모듈을 임포트 해줍니다.

import { IonicStorageModule } from '@ionic/storage';

@NgModule({
  declarations: [AppComponent],
  entryComponents: [],
  imports: [BrowserModule, IonicModule.forRoot(), AppRoutingModule,
    IonicStorageModule.forRoot()
  ],
  providers: [
    StatusBar,
    SplashScreen,
    Camera,
    { provide: RouteReuseStrategy, useClass: IonicRouteStrategy }
  ],
  bootstrap: [AppComponent]
})
export class AppModule {}

PhotoService 클래스에서도 쓸 수 있게 임포트 photo.service.ts 에 임포트 해줍니다.

import { Storage } from '@ionic/storage';

해당 constructor 에도 주입시켜 줍니다.

constructor(private camera: Camera, private storage: Storage) { }

takePicture() 매서드가 촬영 이후 사진을 저장할 수 있도록 해줍니다.

this.camera.getPicture(options).then((imageData) => {
  // Add new photo to gallery
  this.photos.unshift({
    data: 'data:image/jpeg;base64,' + imageData
  });

  // Save all photos for later viewing
  this.storage.set('photos', this.photos);
}, (err) => {
  // Handle error
  console.log("Camera issue: " + err);
});

저장을 했다면 앱이 처음 켜질때 불러오기도 필요합니다. loadSaved() 메서드를 추가해 줍니다.

loadSaved() {
  this.storage.get('photos').then((photos) => {
    this.photos = photos || [];
  });
}

tab2.page.ts 에는 처음 시작할때 loadSaved 메서드가 한 번 실행될 수 있게 추가해 줍니다.

ngOnInit() {
 this.photoService.loadSaved();
}

튜토리얼 완료

여기까지 하시면 튜토리얼에 있는 부분 성공적으로 끝났습니다.
이후 문서에는 테마 적용하는 부분 Ionic Theming 과 페이지 라이프 사이클 Ionic Page Life Cycle 그리고 네비게이션 Angular Navigation 관련 해서 라우트를 비롯한 좋은 내용들이 잘 이어서 설명되어 있습니다.

저는 처음에 위의 과정을 따라하면서 도대체 왜 페이지에 사진 기능을 기껏 넣어 놓고,
갑자기 서비스로 옮기라고해서 사람을 헷갈리게 하나 싶었는데
이후에 기능들을 넣어보니 그렇게 바닥부터 설명해준 덕에 좀 더 수훨하게 이해했던 것 같습니다.

원래 해당 튜토리얼 외에 지도나 위치조회, HTTP 전송 부분도 같이 하려고 했었는데
분량 조절에 실패하여 자잘한 내용이 중복적으로 들어가게 된 것 같습니다.
다음에 이어서 다른 기능들 넣어 보도록하겠습니다.
감사합니다.

0개의 댓글