본문 바로가기
spring & boot/Spring & Spring Boot

[SpringBoot] QR코드 생성 & Test(링크이동) - zxing

by lucas_owner 2023. 3. 24.

1. 서론

몇년전 시작된 COVID19의 여파로 비대면, 비접촉 관련된 시스템들이 많이 생겨났다. (QR인증, QR결제 ...)

심지어 QR코드는 2000년 6월에 표준이 되었을 정도로, 오래된 기술이지만, COVID19 로 인해 사용범위, 활용성이 높아진것 같다.

 

더불어 옥외광고, 모바일 앱, 웹사이트 내부링크 등등 활용되는곳도 점점 많아지고, 생활에 점점더 밀접해지고 있다.

 

 

1-1. 바코드 vs QR 코드?

사실 일반인의 입장에서 보면, "바코드와 QR코드가 다른점이 뭐야? 둘다 똑같은거 아니야?" 라는 말을 하게된다.

왜 일상에서는 QR 코드를 더 많이 사용할까? 

  • 바코드 
    • 레이저(스캔물체)를 수평방향으로 인식해야 한다.
    • 최대 20자의 정보 저장 가능.
    • 바코드의 "I" 높이 중 일부분이 훼손되어도 인식 가능
    • 단점: 정보저장량, 인식률 
  • QR 코드
    • 어떤 방향으로 스캔해도 인식 가능.(대각선, 정방향, 역방향 등등)
    • 최대 숫자 7089자, 문자 4296자에 해당하는 정보 저장 가능.
    • 인식률, 속도 높음.
    • 암호화, 위변조 방지 등 보안 기능 존재.
    • 단점: QR 코드의 수정,삭제 불가능.

- 우리가 일상생활에서 활용하기에는, 많은 정보를 저장할수 있고, 인식률이 빠른(빨리빨리의 민족) 장점들이 있기에,

많이 활용되는 방법인것 같다고 생각한다.

 

 

1-2. QR 코드 생성 방법

- 현재 QR 코드의 생성 방법은 예전에 비해 많아졌다, 그중 개발에 활용할 수 있는 일부만 보겠다.

 

  1. Google QR Codes API 에 요청 하는 방법
  2. Open Source를 통한 Local에서 생성.
  3. QR Code 생성을 제공하는 기타 사이트(네이버, 어도비 등등)

- 1번에 해당하는 Open API를 사용하기에는, 여러가지 절차, 통신, 인증,인가, API Spec 등 고려해야 할 부분이 많다. 

하지만 2번 솔루션을 활용한다면, 그 모든것들을 직접 제어 할 수있고 편리하다. (또한 구글 API 가 언제 지원종료될지 아무도 모른다.)

 

해당 포스팅에서는 2번 솔루션을 사용해 Spring boot 에서 간단하게 QR코드를 생성, 제공할것이다. 

 

 

2. ZXING - Google Open Source

- 사용하게될 오픈 소스인 'zxing'는 구글에서 제공하는 오픈 소스이다. 

모바일, 웹 같은곳에서 활용 할 수 있다.

 

- GItHub: zxing 오픈소스 공식 - for Java

* https://github.com/zxing/zxing

 

해당 공식 문서에 들어가면 더욱 자세한 스펙 및 정보를 확인 할 수 있다.

 

 

 

3. QR 코드 생성 및 제공 Test 

 

3-1. 라이브러리 추가. - Gradle

// QR Code - zxing
	implementation group: 'com.google.zxing', name: 'javase', version: '3.5.0'
	implementation group: 'com.google.zxing', name: 'core', version: '3.5.0'

 

3-2. 요청 페이지

- 간단하게 요청 링크(사이트)를 구성하자. 

* 필자는 index.html 내부에 구성.

<div>
    <h3>내 티스토리 블로그 QR Code!</h3>
    <a href="/qr/tistory">QR to Tistory!!</a>
</div>

 

3-3. Controller - QR 생성, 제공

package boot.bootprac.qr.controller;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.ByteArrayOutputStream;
import java.io.IOException;

/************
 * @info : QR Code 생성 및 제공 Controller
 * @name : QrController
 * @date : 2023/03/24 5:32 PM
 * @version : 1.0.0
 * @Description :
 ************/
@RestController
@RequiredArgsConstructor
@Slf4j
public class QrController {


    @GetMapping("/qr/tistory")
    public ResponseEntity<byte[]> qrToTistory() throws WriterException, IOException {
    	// QR 정보
        int width = 200;
        int height = 200;
        String url = "https://lucas-owner.tistory.com/";

        // QR Code - BitMatrix: qr code 정보 생성
        BitMatrix encode = new MultiFormatWriter()
        			.encode(url, BarcodeFormat.QR_CODE, width, height);

        // QR Code - Image 생성. : 1회성으로 생성해야 하기 때문에
        // stream으로 Generate(1회성이 아니면 File로 작성 가능.)
        try {
	        //output Stream
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            
            //Bitmatrix, file.format, outputStream
            MatrixToImageWriter.writeToStream(encode, "PNG", out);
            
            return ResponseEntity.ok()
                    .contentType(MediaType.IMAGE_PNG)
                    .body(out.toByteArray());

        }catch (Exception e){log.warn("QR Code OutputStream 도중 Excpetion 발생, {}", e.getMessage());}

        return null;
    }
}

- html 에서 form 태그를 활용, 이동하고자 하는 페이지의 주소를 파라미터로 받아와도 된다.

* 여기서는 해당 블로그의 주소를 QR 코드로 생성하고자, 고정 주소를 사용.

 

- QR 코드 이미지의 사이즈나, 색상 등등 변경 할 수 있다.(Custom)

MatrixToImageConfig custom = new MatrixToImageConfig(MatrixToImageConfig.BLACK, -1);

 

 

 

4. Test 

4-1. html로 작성했던 링크로 Request 를 전송하자.

HTML <a> 태그

 

 

 

4-2. Rest Controller에서 생성한 QR코드를 이미지 형태로 확인 할 수 있다.

 

4-3. 핸드폰의 카메라로 QR 인식 또한 확인되고, 해당 링크로 이동하는것도 확인되었다.

핸드폰 QR 스캔

 

 

추가 - Image 전송(Link)

- Spring Boot 내부의 resources/image 폴더안에 있는 이미지를 보여주고 싶었다. 

QR Code 스캔 -> 서버 내부 이미지 전송(출력)

 

*(2023.03.25) 전통적인 방법대로 링크를 거는 방법을 제외하고, QR Code 내부에 이미지를 첨부 하고 싶었지만, 이미지 파일의 용량 떄문에 제한 된다는점 때문에 아직 해결 하지 못했다 (QR Code의 정보량을 늘리면 되지만, 생각처럼 되질 않았다.)

 

Code 

	// Generate QR Code
	@GetMapping("/qr/image")
    public ResponseEntity<byte[]> qrToImage() throws WriterException, IOException{
        String text = "http://localhost:8080/qr/get/image";

        // QR
        int width = 200;
        int height = 200;

        BitMatrix encode = new MultiFormatWriter().encode(text, BarcodeFormat.QR_CODE, width, height);

        try {
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

            MatrixToImageWriter.writeToStream(encode, "PNG", outputStream);

            return
                ResponseEntity.ok()
                        .contentType(MediaType.IMAGE_PNG)
                        .body(outputStream.toByteArray());
        }catch (Exception e){
            log.warn("QR Code Exceptions {}", e.getMessage());
        }
        return null;
    }

    // Image File Response
    @GetMapping("/qr/get/image")
    public ResponseEntity<byte[]> name() throws IOException {
        // Image name - ImageFile to Byte[]
        String imageName = "java_logo_icon.png";
        byte[] byteFile = getImageBye(imageName);

        // Header
        HttpHeaders headers = new HttpHeaders();
        headers.add("Content-Type", "image/png");
        headers.add("Content-Length", String.valueOf(byteFile.length));

        // Return
        return new ResponseEntity<byte[]>(byteFile, headers, HttpStatus.OK);
    }

        // Image to Byte[]
        private byte[] getImageBye(String imageName) throws IOException{
            // image 경로 및 File
            ClassPathResource classPathResource = new ClassPathResource("static/images/"+ imageName);
            File file = classPathResource.getFile();

            byte[] byteImage = null;

            BufferedImage originalImage = null;
            ByteArrayOutputStream out = new ByteArrayOutputStream();

            originalImage = ImageIO.read(file);
            ImageIO.write(originalImage, "png", out);
            out.flush();

            byteImage = out.toByteArray();
            return byteImage;
        }

- 현재 솔루션은 QR Code 내부에 Image를 리턴하는 url을 적재 하고, 스캔하면 해당 url 을 통해 이미지를 보는 방식이다..

 

- Scan Test는 -> url 주소를 ip주소:8080/~ 이러한 방식으로 하면 핸드폰으로도 localhost 에 접속할 수 있다.

 


- QR 코드 생성 기능을 이용하면, 활용할 수 있는 기능들을 더 테스트 해보고 싶어졌다. 대부분은 이미 시중에 나와있다.

(로그인, 결제, 기타 등록 등등,,,)

 

- 간단하게 웹페이지, 이미지, 정보 같은것들을 요청 하고 사용할때는, QR 코드 기술을 활용해 보면 좋을것 같다. 

 

반응형

댓글