Overview

요즘 어떤 장소를 방문하려면 QR코드 인증은 필수라고 할 수 있습니다. 어디에나 QR 인증을 위한 핸드폰 / 태블릿 pc 가 설치되어 있는 것을 볼 수 있는데요. 모바일 앱에서 QR 코드를 읽기 위한 QR 스캐너를 vue 프로젝트로 구현한 과정을 소개해보겠습니다.

Contents

  1. QR 코드 vs. 바코드
  2. Vue.js 웹앱 프로젝트에 QR 코드 스캔 기능 도입하기
  3. 마무리

QR 코드 (Quick Response code) vs. 바코드 (Barcode)


본격적으로 QR코드 스캐너를 구현하기 전에 바코드와 QR코드의 차이점을 알아보겠습니다. 일상 생활에서는 바코드와 QR 코드를 사용하면서 차이점을 체감하지 못했는데 스캐너 기능을 구현하려고 하니 이 둘의 차이점이 문득 궁금해졌습니다.

먼저 주변 도처에서 볼 수 있는 바코드는 바 형태로 이루어진 1차원 바코드(1D barcode)로 제한된 정보를 가로로만 저장할 수 있는 특성을 가지고 있습니다. 즉, 정보를 가로 방향으로만 인코딩할 수 있으며 스캔 역시 가로 방향으로만 가능하다는 뜻입니다. 바코드를 구성하는 많은 “바” 들은 수직적으로는 아무런 정보를 담고 있지 않습니다.

athena

바코드의 제한점을 보완해서 나온 것이 QR 코드인데, QR 코드는 2차원 바코드(2D barcode)로 가로, 세로로 정보를 저장할 수 있습니다. 또 바코드보다 더 많은 용량, 다양한 형태의 데이터를 저장할 수 있다는 장점을 가지고 있습니다. 바코드 타입에 따른 데이터 용량은 여기에서 확인하실 수 있습니다. 무엇보다 QR 코드는 360도 어느 방향에서도 인식할 수 있다는 장점이 있으며 이름과 같이 빠른 인식 속도를 가지고 있습니다.

QR코드도 다양한 유형이 있지만 기본형을 기준으로 구성을 조금 더 자세히 알아보겠습니다.

  • Data Module: QR 코드를 구성하는 영역으로 데이터를 담고 있는 부분입니다.
  • Position Marker: 모든 QR 코드에는 3개의 포지션 마커가 있습니다. Inner eye와 Outer eye 로 구성되어 있으며 QR 코드의 위치와 방향을 식별하여 스캐너/카메라가 데이터 모듈을 빠르게 스캔할 수 있도록 도와주는 역할을 합니다.
  • Quiet Zone: QR 코드를 둘러싸고 있는 하얀색 마진을 의미합니다. 스캐너가 QR 코드를 빠르고 정확하게 식별할 수 있는데 중요한 역할을 담당합니다.
athena

이렇게 바코드와 QR 코드는 서로 다른 특성을 가지고 있는데 처음부터 QR 코드의 장점을 잘 알고 있었다면 개발을 시작하기 전 특성에 맞는 기능 구현을 계획할 수 있을 것입니다. 기능적인 구현에 앞서 기술적 특성이나 배경에 대한 리서치를 좀 더 구체적으로 해야겠다는 다짐을 하는 계기가 되었습니다.

Vue.js 웹앱 프로젝트에 QR 코드 스캔 기능 도입하기


사실 최초에는 QR 코드 스캐너가 아닌 바코드 스캐너 구현을 기획했었지만 기능상의 이슈로 QR 코드 스캐너 구현으로 기획을 변경하게 되었습니다. 기존 기획대로 바코드 스캐너를 구현해놓고 보니 모바일 카메라로는 바코드 인식이 거의 안 되는 이슈를 발견했기 때문입니다. 처음에는 패키지 인스톨이나 관련 설정을 잘못한 줄 알고 코드를 뒤적여봤지만 100번 시도하면 1번 정도 인식이 되긴 했습니다. 잘 구현된 라이브러리들이 많으니 어렵지 않을 거라는 예상과 달리 바코드 스캐너는 실효성 부족으로 인한 명확한 한계를 가지고 있었습니다.

QR 코드 스캐너 구현

별도의 어플리케이션 없이도 핸드폰에 내장된 카메라에서 손쉽게 QR 코드 스캔을 할 수 있을 정도로 모바일 카메라를 이용한 QR 코드 인식이 용이하다는 점을 깨닫고 바코드 스캔이 아닌 QR 코드 스캔 기능을 구현하는 것으로 기획 방향을 수정했습니다.

앞서 언급했듯이 QR 코드는 인식률이 매우 높기도 하고 360도 어느 각도에서든 인식이 가능하다는 장점이 있습니다. 기존에 구현해놓은 바코드 스캐너 라이브러리에서 QR 스캔 기능도 제공했기 때문에 라이브러리 변경 없이 진행하려고 했지만, 유지와 보수 및 기능의 안정성 측면에서 더 상위 랭크의 라이브러리를 사용하는 것이 좋겠다는 조언을 받아 vue-qrcode-reader로 변경하여 기능을 구현했습니다.

카메라 권한 추가

기획 내용 중에는 QR 코드 스캐너 뿐만 아니라 카메라를 사용하여 직접 사진을 찍어 업로드하고 사진 앨범에서 사진을 가져오는 등의 추가 기능도 구현이 필요했기 때문에 카메라 사용에 대한 권한을 먼저 추가해주었습니다.

athena

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="kr.co.brandi.tms">
   ...

    <!-- 카메라 -->
    <uses-permission android:name="android.permission.CAMERA"/>
    <uses-feature android:name="android.hardware.camera"/>
    <uses-feature android:name="android.hardware.camera.autofocus"/>

    ...
</manifest>

브라우저 지원 & HTTPS 통신

본격적으로 QR 코드 스캐너를 구현하기에 앞서 먼저 알아두어야 할 점이 있습니다. vue-qrcode-reader 라이브러리는 익스플로러를 지원하지 않습니다. 크롬의 경우에도 https 혹은 로컬호스트 위에서만 카메라에 접근할 수 있기 때문에 웹 프로토콜은 https 를 사용하는 것으로 설정해야 합니다. 처음 사용했던 바코드 스캔 라이브러리의 경우 아래와 같이 친절한 에러 메시지를 띄워주지 않고 카메라가 떠야 할 화면이 그냥 빈 화면으로 표출되어 버려서 당황했던 기억이 있는데 https 로 변경 후 정상적으로 작동하는 기능을 확인할 수 있었습니다.

athena

QR 스캔 컴포넌트 선언

이제 vue.js 프로젝트에 QR코드 스캐너 기능을 구현할 차례입니다. 라이브러리를 사용하기로 했기 때문에 QR 코드를 인식하는데 필요한 모든 구성을 패키지 설치만으로 손쉽게 구현해볼 수 있습니다. 먼저 패키지를 설치해줍니다.

npm install vue-qrcode-reader

패키지를 설치한 후 아래 코드 블럭과 같이 <template> 블럭 안에 QrcodeStream 컴포넌트를 선언해주기만 하면 QR 코드를 인식할 수 있는 스캐너 기능을 바로 사용할 수 있습니다.

카메라가 로드되면 QR코드 데이터 스캔이 가능하고 decode 이벤트를 통해 스캔한 데이터를 읽어낼 수 있습니다. 한 가지 알아둘 점은 같은 QR 코드를 한 번에 여러 번 읽을 수 없다는 점입니다. 카메라가 QR 코드 데이터를 decode 하는 속도가 매우 빠르기 때문에 같은 데이터를 연속적으로 스캔하는 액션을 허용할 경우 이벤트가 과도하게 발생하여 사용성에 불편함을 초래합니다.

실제로 처음 사용했던 바코드 리더 라이브러리의 경우 같은 데이터를 연속적으로 스캔하는 액션에 제한을 두지 않았기 때문에 카메라가 로드되는 동안 QR 코드 데이터가 계속 스캔되었습니다. 만약 QR코드를 스캔해서 API 통신을 목적으로 기능이 구현되어야 한다면, 이 케이스는 스캔이 될 때마다 API 를 호출하여 불필요한 통신이 계속되는 등 리소스 낭비 및 상태 변경에 불안정성을 갖게 됩니다. 따라서 vue 의 watch 속성을 적용해 스캔한 QR 코드 데이터가 변경될 때만 API 통신하는 함수를 동작시킨다는 조건이 필요합니다.

하지만 vue-qrcode-reader 에서는 자체적으로 같은 데이터를 스캔할 경우 마지막으로 decode 된 데이터만 캐시한 후 데이터의 변경이 있을 때만 이벤트를 emit 하여 효율적인 방식으로 스캔 기능을 제공합니다.

<template>
  <qrcode-stream @decode="onDecode"/>
</template>

<script>
import { QrcodeStream } from 'vue-qrcode-reader'

export default {
  name: 'DeliveryStartScan',
	
  ...
  
  methods: {
    onDecode (result) {
      this.qrCodeData = result
    }
  },
  ...
  components : {
    QrcodeStream,
  }
}
</script>

지금까지 웹 프로토콜을 https 로 설정하고 QR 스트림 컴포넌트까지 선언하여 웹앱 내에서 QR 코드를 스캔할 수 있는 카메라 컴포넌트를 간단히 로드해보았습니다.

Conclusion

vue.js 와 vue-qrcode-reader 라이브러리 덕분에 모바일 네이티브 언어에 능숙하지 않아도 웹앱을 통한 QR 코드 스캐너를 간단히 구현할 수 있었습니다. 라이브러리를 사용하면 개발의 효율성이 높아지겠지만 구현하려는 기능의 기술적 문맥과 라이브러리의 동작 원리를 파악하고 사용하는 것과 단순히 패키지만 인스톨하여 구현한 기능은 큰 차이가 있을 것이라고 생각합니다. 효율성을 챙기되 본인이 구현한 기능에 대해 정확히 아는 것도 중요하다는 것을 다시 한 번 되새기며 글을 마치겠습니다. 감사합니다!

참고

https://www.premierelectronics.com/blog/barcode-types-identificaton-understanding

https://www.qrcode-tiger.com/qr-code-data-size

https://www.geeksforgeeks.org/difference-between-barcode-and-qr-code/

https://developer.android.com/guide/topics/permissions/overview?hl=ko

https://gruhn.github.io/vue-qrcode-reader/api/QrcodeStream.html#events


최지선 | 풀필먼트개발실 풀필먼트개발팀
브랜디, 오직 예쁜 옷만