gimmickbutreal
[Springboot/Java] QR 코드 생성/저장/출력 본문
Java, Oracle, Spring boot 환경에서 백엔드로 구축
1. Mapper 설계
1
2
3
4
5
6
7
8
9
|
@Mapper
public interface QrCodeMapper {
/**
* 아래의 매개변수를 DB에 QR코드 정보로 삽입하는 역할
* @param link
* @param qrCode
*/
void insertQrCode(@Param("link") String link, @Param("qrCode") byte[] qrCode);
}
|
cs |
- 위 코드는 Mybatis에서 사용하는 Mapper 인터페이스
- @Mapper : 해당 애너테이션은 MyBatis가 인터페이스를 Mapper로 인식하도록 함
- @Param : 해당 애너테이션은 메서드 배개변수 이름과 SQL 매개변수 이름을 매핑시켜줌. 이를 사용해 insertQrCode 메서드에서 매개변수로 받은 link와 qrCode를 Oracle에서 사용할 수 있음
2. Service 설계
1
2
3
4
|
public interface QrCodeService {
public byte[] generateQrCode(String link) throws IOException, WriterException;
}
|
cs |
- link 매개변수를 받아 생성된 QR 코드를 byte 배열로 반환
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
@Service
@RequiredArgsConstructor
public class QrCodeServiceImpl implements QrCodeService {
private final QrCodeMapper qrCodeMapper; // QrCodeMapper 빈 객체 주입을 위한 final 필드
// 매개변수로 받은 문자열 링크를 이용해 QR 코드를 생성하고 DB에 삽입한 후, 생성된 QR 코드 바이트 배열을 반환하는 메서드
public byte[] generateQrCode(String link) throws IOException, WriterException {
// QR 코드 생성
byte[] qrCodeBytes = QRCodeGenerator.generateQRCodeImage(link);
// DB에 QR 코드 삽입
qrCodeMapper.insertQrCode(link, qrCodeBytes);
return qrCodeBytes; // 생성된 QR 코드 바이트 배열을 반환
}
}
|
cs |
- @Service : 해당 애너테이션은 해당 클래스를 스프링의 Bean으로 등록함. Component Scan 기능을 이용해 스프링 컨테이너가 자동으로 생성
- @RequiredArgsConstructor : 해당 애너테이션은 생성자 주입을 위한 Lombok 애너테이션으로, 필드 주입 대신 생성자를 이용해 의존성 주입을 할 수 있음
- 생성자를 통해 의존성을 주입하는 방식을 사용하면, 코드의 결합도가 낮아져 유지보수가 용이해지며, 객체 생성 시점에 모든 의존성이 주입되어 NullPointerException 등의 오류를 방지할 수 있음
- Impl 클래스를 따로 만드는 이유
1. 인터페이스와 구현체를 분리함으로써 유연성을 높이기 위함
- 인터페이스는 메서드의 명세만을 정의하고, 구현체에서는 이를 구체적으로 구현하게 됨. 이를 통해, 다양한 구현체를 만들 수 있으며, 런타임에 구현체를 동적으로 변경할 수 있음
2. 코드의 일관성과 가독성 향상
- 인터페이스에 정의된 메서드의 이름과 매개변수, 반환값 등을 따르기 때문
3. Repository 설계
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
@Repository
public class QrCodeRepository {
private final QrCodeMapper qrCodeMapper; // 데이터베이스와 상호작용을 위해 생성자에서 해당 객체를 받아와 필드에 할당함
public QrCodeRepository(QrCodeMapper qrCodeMapper) {
this.qrCodeMapper = qrCodeMapper;
}
public void saveQrCode(String link, Long id) throws IOException, WriterException {
link = "https://www.naver.com";
id = 12L;
// QR 코드 생성
byte[] qrCodeBytes = QRCodeGenerator.generateQRCodeImage(link);
// 데이터베이스에 QR 코드 삽입
qrCodeMapper.insertQrCode(link, qrCodeBytes);
}
}
|
cs |
- link와 id 값은 임의로 지정한 것이며, 메서드 파라미터로 전달 받아서 사용하려면 임의로 설정한 두 값을 지우고 insertQrCoded 메서드에 id 값을 추가로 전달받도록 해야함. QrCodeMapper에도 Long id 변수를 추가.
4. Generator 설계
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
public class QRCodeGenerator {
/**
* 주어진 링크를 인코딩하여 QR 코드 이미지를 생성하고,
* 그 이미지를 byte 배열 형태로 반환하는 메서드
* @param link
* @return QR 코드 이미지를 바이트 배열 형태로 변환
* @throws WriterException
* @throws IOException
*/
public static byte[] generateQRCodeImage(String link) throws WriterException, IOException {
// QR코드 생성 옵션 설정
Map<EncodeHintType, Object> hintMap = new HashMap<>();
hintMap.put(EncodeHintType.MARGIN, 0);
hintMap.put(EncodeHintType.CHARACTER_SET,"UTF-8");
// QR 코드 생성
QRCodeWriter qrCodeWriter = new QRCodeWriter();
BitMatrix bitMatrix = qrCodeWriter.encode(link, BarcodeFormat.QR_CODE, 200, 200, hintMap);
// QR 코드 이미지 생성
BufferedImage qrCodeImage = MatrixToImageWriter.toBufferedImage(bitMatrix);
// QR 코드 이미지를 바이트 배열로 변환, byteArrayOutputStream에 저장
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ImageIO.write(qrCodeImage,"png", byteArrayOutputStream);
byteArrayOutputStream.flush();
byte[] qrCodeBytes = byteArrayOutputStream.toByteArray();
byteArrayOutputStream.close();
return qrCodeBytes;
}
}
|
cs |
5. Controller 설계
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
@Controller
// 해당 클래스의 생성자를 자동으로 생성
// QrCodeController 생성자는 QrCodeService 타입의 매개변수를 받으며, @Autowired 어노테이션을 사용하지 않아도 자동으로 의존성 주입이 가능
@RequiredArgsConstructor
public class QrCodeController {
// QrCodeService 클래스에 대한 객체 생성
private final QrCodeService qrCodeService;
/** HTTP GET 요청이 /qr 경로로 들어왔을 때 showQrCode 메서드 실행
*
* @param model
* @return qr/qrcode view
* @throws IOException
* @throws WriterException
*/
@GetMapping("/qr")
public String showQrCode(Model model) throws IOException, WriterException {
// QR 코드 생성 및 모델에 추가
String link = "https://www.naver.com";
// 변수에 생성된 QR 코드 이미지 데이터가 저장
byte[] qrCodeBytes = qrCodeService.generateQrCode(link);
// byte 배열 형태로 저장된 QR 코드 이미지 데이터를 Base64 인코딩하여 문자열 형태로 변환
String qrCode = Base64.getEncoder().encodeToString(qrCodeBytes);
// qrCode 변숫값을 qrCode라는 이름으로 Model 객체에 추가. Model 객체에 데이터를 추가하면 Spring MVC는 해당 데이터를 View로 전달하여 화면에 렌더링
model.addAttribute("qrCode", qrCode);
return "qr/qrcode";
}
}
|
cs |
6. View 설계
1
2
3
4
5
6
7
8
9
10
11
12
|
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>QR Code</title>
</head>
<body>
<h1>QR Code</h1>
<img th:src="'data:image/png;base64,'+${qrCode}" alt="QR Code">
</body>
</html>
|
cs |
7. 출력 화면
직접 개발한 코드며 리팩토링을 진행할 예정.
백엔드가 아닌 클라이언트 상에서 개발하는 방법도 매우 좋은 선택
'Programming > Spring Boot' 카테고리의 다른 글
토스페이먼츠 API Hook 연동 (0) | 2023.03.11 |
---|---|
[Spring Boot] 영속성 컨텍스트 (Persistence Context) (0) | 2022.09.06 |
[Spring Boot] 타임리프(Thymeleaf) URL (0) | 2022.09.01 |
[Spring Boot] 서비스(Service)가 필요한 이유 (0) | 2022.09.01 |
[Spring Boot] GetMapping 애노테이션 (0) | 2022.08.13 |