앱에 QR 스캔 기능을 붙여야 했다. 예전 프로젝트에서는 expo-barcode-scanner를 그냥 갖다 썼는데, 이번에 다시 보니 deprecated 상태였다. Expo 공식 문서도 이제 expo-camera의 CameraView나 react-native-vision-camera를 쓰라고 안내한다.
expo-camera로도 되긴 하는데, 스캔 성능이나 프레임 처리 세밀함을 생각하면 VisionCamera 쪽이 확실히 낫다. 예전엔 VisionCamera로 바코드를 읽으려면 프레임 프로세서 + MLKit 플러그인을 직접 붙여야 해서 세팅이 꽤 번거로웠는데, v3부터 codeScanner가 내장돼서 훨씬 간단해졌다.
설치
npx expo install react-native-vision-camera
Expo 프로젝트라면 config plugin으로 카메라 권한 문구를 넣어준다. app.json에 이렇게.
{
"plugins": [
[
"react-native-vision-camera",
{ "cameraPermissionText": "QR 스캔을 위해 카메라 접근이 필요합니다." }
]
]
}
네이티브 모듈이라 Expo Go에서는 안 돌아간다. npx expo run:ios 같은 dev client 빌드가 필요하다. 이거 모르고 Expo Go에서 계속 크래시나서 한참 헤맸다.
권한 요청
카메라를 켜기 전에 권한부터 받아야 한다. VisionCamera는 훅으로 이걸 깔끔하게 처리해준다.
import { useCameraPermission, useCameraDevice } from 'react-native-vision-camera';
const { hasPermission, requestPermission } = useCameraPermission();
useEffect(() => {
if (!hasPermission) requestPermission();
}, [hasPermission]);
스캐너 붙이기
핵심은 useCodeScanner 훅이다. 읽을 코드 타입을 배열로 지정하고, 인식됐을 때 콜백만 넘기면 끝이다.
import { Camera, useCodeScanner } from 'react-native-vision-camera';
function Scanner() {
const device = useCameraDevice('back');
const codeScanner = useCodeScanner({
codeTypes: ['qr', 'ean-13', 'code-128'],
onCodeScanned: (codes) => {
const value = codes[0]?.value;
if (value) console.log('스캔됨:', value);
},
});
if (!device) return null;
return (
<Camera
style={StyleSheet.absoluteFill}
device={device}
isActive={true}
codeScanner={codeScanner}
/>
);
}
codeTypes에 'qr'만 넣으면 QR 전용, EAN·Code128을 같이 넣으면 상품 바코드까지 읽는다.
중복 스캔을 막아야 한다
여기서 실전 팁 하나. onCodeScanned은 카메라가 코드를 잡고 있는 동안 계속, 초당 수십 번씩 불린다. 스캔 한 번에 화면을 넘기려 하면 콜백이 폭주해서 네비게이션이 여러 번 쌓인다.
ref 플래그로 한 번만 처리하도록 잠가주는 게 편하다.
const locked = useRef(false);
onCodeScanned: (codes) => {
if (locked.current) return;
locked.current = true;
const value = codes[0]?.value;
router.push({ pathname: '/result', params: { value } });
},
isActive={false}로 카메라를 잠깐 꺼주는 방법도 있는데, 다시 스캔 화면으로 돌아올 때 플래그만 풀어주면 되니까 나는 위 방식이 더 깔끔했다.
정리하면 VisionCamera v3의 codeScanner는 별도 플러그인 없이 QR·바코드를 다 처리한다. 주의할 점은 Expo Go가 아니라 dev client로 돌려야 한다는 것, 그리고 콜백 폭주를 막을 잠금 처리 정도다. 세팅만 넘기면 실제 스캔 코드는 20줄이 안 된다.