BackEnd/Spring

[ Spring Boot ] Google Zxing - QR 코드 생성

Yume Dev 2024. 12. 11. 23:33
반응형

Google의 오픈 소스인 바코드 생성 로직을 활용

 

gitHub에서 zxing기능에 추가적인 설명이 있으며, QR코드 말고도 다른 바코드를 생성할 수 있는 것 같다

 

https://github.com/zxing/zxing

 

GitHub - zxing/zxing: ZXing ("Zebra Crossing") barcode scanning library for Java, Android

ZXing ("Zebra Crossing") barcode scanning library for Java, Android - zxing/zxing

github.com

 


Implement

zxing을 사용하기 위해 build.gradle에 의존성을 추가

    implementation group: 'com.google.zxing', name: 'javase', version: '3.5.0'
    implementation group: 'com.google.zxing', name: 'core', version: '3.5.0'

React Front

특정 버튼을 눌러 QR 코드를 생성하기 위해 프론트에서 버튼을 누르면 백을 호출해서 QR이미지를 가져오도록 구현

 

로그인 버튼을 만들어 로그인 버튼을 누르면 QR코드 생성 로직을 호출하여 QR코드 이미지를 가져와 화면에 뿌려주도록 처리

axios 호출로 백을 호출한 후

 

이미지 파일 가져오기 위해 responseType: blob으로 처리 

async function handleLoginAPIReauest() {
        const response = await axios.post('http://localhost:8080/login/qr', {
            responseType: 'blob',
        })
        const url = URL.createObjectURL(response.data)

        setQrImage(url)
    }
    return (
      <>
          {qrImage ? <img src={qrImage} alt="qrcode"/> : <></>}
          <p><button style={style} onClick={handleLoginAPIReauest}>로그인</button></p>
      </>
    )

Java BackEnd

QR코드를 모바일로 찍으면 백으로도 해당 url을 호출하도록 해야하므로

QR코드를 찍었을때 호출한 url과 같이 보낼 데이터를 임시로 세팅

핸드폰으로 QR코드를 할 경우 localhost:8080방식으로 백 호출이 안되어서 자신의 pc ip를 이용하여 같은 네트워크로 연결하여 테스트를 진행

 

QR코드를 만들때 데이터를 보내야할때는 String타입만 보낼 수 있어서

url과 데이터를 map형태로 만들고 JSON으로 변경시켜준다.

            // QR 코드 생성 정보
            int width = 200;
            int height = 200;

            // 사용자 데이터 (테스트)
            String url = "http://ip주소:8080/login/qr-check";
            String userId = "test";
            String password = "1234";

            // 데이터 세팅
            JSONObject data = new JSONObject();
            data.put("userId", userId);
            data.put("password", password);

            // 최종 결과 JSON 객체 생성
            JSONObject qrData = new JSONObject();
            qrData.put("url", url);
            qrData.put("data", data);

 

BitMatrix를 사용하여 바코드를 생성할 수 있으며

첫번째 파라미터는 해당 바코드에 담길 데이터를 보낸다.

JSON으로 변형하여 프론트롤 보내면 \n 처럼 특수문자도 포함되어서 보내주게 되어 .toString(4)를 활용하여 \n같은 특수 문자는 안보내지도록 처리

 

두번째 파라미터는 바코드 형태이며 , QR코드를 생성할 것이기에 QR로 설정

이후는 바코드의 크기 파라미터이다.

 

이후 생성된 BitMatrix를 png이미지로 변환후 해당 이미지를 프론트로 전달

            // QR 코드 생성
            BitMatrix encode = new MultiFormatWriter().encode(
                    qrData.toString(4),
                    BarcodeFormat.QR_CODE,
                    width,
                    height
            );

            // QR 코드 이미지 출력 스트림
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            MatrixToImageWriter.writeToStream(encode, "PNG", out);

            // HTTP 응답 반환
            return ResponseEntity
                    .ok()
                    .contentType(MediaType.IMAGE_PNG)
                    .body(out.toByteArray());

 

[ 전체 코드 ]

    @PostMapping("/qr")
    public ResponseEntity<byte[]> QrLogin() {
        try {
            // QR 코드 생성 정보
            int width = 200;
            int height = 200;

            // 사용자 데이터 (테스트)
            String url = "http://ip주소:8080/login/qr-check";
            String userId = "test";
            String password = "1234";

            // 데이터 세팅
            JSONObject data = new JSONObject();
            data.put("userId", userId);
            data.put("password", password);

            // 최종 결과 JSON 객체 생성
            JSONObject qrData = new JSONObject();
            qrData.put("url", url);
            qrData.put("data", data);

            // QR 코드 생성
            BitMatrix encode = new MultiFormatWriter().encode(
                    qrData.toString(4),
                    BarcodeFormat.QR_CODE,
                    width,
                    height
            );

            // QR 코드 이미지 출력 스트림
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            MatrixToImageWriter.writeToStream(encode, "PNG", out);

            // HTTP 응답 반환
            return ResponseEntity
                    .ok()
                    .contentType(MediaType.IMAGE_PNG)
                    .body(out.toByteArray());

        } catch (Exception e) {
            // 예외 처리 및 로깅
            System.err.println("Error while generating QR code: " + e.getMessage());
            e.printStackTrace();

            // 에러 응답 반환
            return ResponseEntity
                    .status(500)
                    .body(null);
        }
    }

Result

그럼 로그인 버튼을 누르면 백에서 QR코드 이미지를 불러와지고 이를 img 태그의 src에 넣으면 QR 이미지가 화면에 노출된다.

 

핸드폰으로 해당 QR을 찍으면 QR코드를 만들때 추가한 데이터가 나온다


Features

한글데이터를 보내고 싶어서 테스트를 해보았는데 카메라로 찍어서 데이터를 확인해 보니 ???? 로 보이는 것을 확인

 

만약 데이터를 전송할때 한글 데이터를 전송하고 싶은 경우에는 인코딩 작업을 해주어야한다.

 

이런식으로 EncodeHintType을 주어서 UTF-8로 인코딩을 해준후

BitMatrix에 hints를 파라미터로 넘겨주면 한글 데이터를 카메라로 찍어도 ????로 나오지 않고 정상적으로 한글을 보여준다.

        String qrData = "한글한글"
        Map<EncodeHintType, Object> hints = new HashMap<>();
        hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");

        BitMatrix bitMatrix = new MultiFormatWriter().encode(
                qrData, 
                BarcodeFormat.QR_CODE, 
                width, 
                height, 
                hints
        );
728x90
반응형