프로젝트를 진행하면서 백엔드 서버에서 프론트 측으로 이미지 정보를 전송해줘야 하는 경우가 많이 발생하였다.
보통은 이미지 서버를 별도로 운영하여 원본의 데이터를 제공하지 않고 이미지 서버(Storage)에 저장된 이미지의 url 을 제공하여 이미지를 제공하지만 제한된 프로젝트 기한 내에 이미지 서버까지 구축하는 데는 시간적으로 촉박할거 같아 백엔드 서버에서 원본 데이터를 프론트로 전송해주기로 했다.
처음엔 프론트에서 이미지나 파일을 multipart/form-data 로 백엔드 서버로 전송하여 처리했기 때문에 동일하게 백엔드 서버도 multipart/form-data 를 사용하여 이미지를 프론트로 전송하면 된다고 생각했다.
그러나 multipart/form-data 로 이미지를 전송된 이미지를 프론트에서 처리할 수 있는 방법이 존재하는지 몰랐고, 여러가지 방법을 찾던 와중 Base64 형태로 이미지를 백엔드 측에서 인코딩하여 문자열로 프론트로 보내주게 되면 프론트에서는 문자열로 인코딩된 이미지 정보를 <img src="data:image/<이미지확장자>;base64,<data코드>"> 다음과 같은 형태로 인코딩된 이미지를 바로 출력할 수 있다는걸 알게 되었다.
결국, 서버에서 이미지를 전송할때 Base64 로 이미지를 인코딩하여 인코딩된 문자열을 전송해주기로 하였다.
DTO 의 이미지 파일 이름을 기준으로 파일을 불러와 인코딩하여 다시 DTO 에 저장 후 RestController 를 통해 응답
위와 같이 Base64 로 인코딩된 이미지를 바로 보낼 때 장점과 단점
- 장점 -
1. 서버에서 이미지를 저장할 때 이미지의 원본을 저장할 필요 없이 인코딩된 문자열을 저장하여 바로 문자열을 불러 응답해줄 수 있다
2. 렌더링될 때 HTML dom 을 통해 렌더링되기 때문에 이미지가 끊기지 않고 출력된다
- 단점 -
1. 프론트 코드의 길이가 매우 길어지므로 코드의 가독성이 떨어진다
2. 용량이 증가한다
( 256가지를 표현할 수 있는 바이트를 printable한 64가지를 사용해서 표현하니 당연하다 다시 말해, 8비트를 6비트로 표현하는 것이다 3개의 8비트는 4개의 6비트로 표현할 수 있다 따라서 Base64 인코딩을 사용하면 원본보다 33%의 크기 증가가 발생한다 )
( 현재는 이미지 원본을 보내서 useState 에 데이터 키 값을 통해 받은 이미지 값을 return 하는 함수를 생성하고 해당 State 를 이미지 src 부분에 사용하면 이미지가 출력되는 것을 알게되었으므로 추후에 서버측과 클라이언트 측의 이미지 처리 방식 코드의 변경이 필요하다 )
import { useState } from 'react';
// useState 를 사용하기 위해선 react 에서 제공하는 useState 를 import!!
2. State 변수를 선언 및 사용
import { useState } from 'react';
function Example() {
// like 는 사용 변수, setLike 는 State 변경 함수
let [like, setLike] = useState(0);
return (
<div>
<p onClick = { () => {
setLike(like + 1); // useState 변경 함수 사용하여 값을 변경
}}>좋아요👍🏻 {like}</p> // useState 변수 사용
</div>
);
}
useState 변수를 사용해 저장된 State 값을 꺼내서 사용하고, 변경 함수를 사용하여 State 에 저장된 값을 변경한다.
useState 는 component 를 띄우거나 띄우지 않거나 등 상태를 변경하는데 사용된다.
프로젝트를 진행하면서 매 주 혹은 매 일마다 유저 테이블의 특정 컬럼 값의 데이터를 초기화 시켜야하는 문제가 발생했다.
위 문제를 스케쥴러를 사용하여 처리하고자 하였는데 검색해보니 사용하려하는 MySQL 자체에서 제공하는 스케쥴러와 Java 에서 제공하는 스케쥴러 두 가지 방식이 존재하는 것을 알았다.
나는 위 두가지 방법 중 Java 에서 제공하는 스케쥴러 기능을 사용하기로 했는데 그 이유는 DB 에 스케쥴러를 적용할 경우 현재 개발 과정에서는 H2 데이터베이스를 사용하기 때문에 배포 이후 실제 사용하는 MySQL 데이터베이스에 스케쥴러를 설정하여 테스트를 진행해야 하는데 Java 에서 제공하는 스케쥴러를 사용하면 DB 가 변경되어도 메소드에서 호출하는 JPA 쿼리가 자동으로 변경된 데이터베이스로 쿼리를 변경하여 처리하기 때문이다.
1. @Scheduled 어노테이션을 사용하기 위해 메인 어플리케이션에 @EnableScheduling 설정
메인 어플리케이션에 @EnableScheduling 어노테이션을 적용해줘야 메소드에 사용하는 @Schedule 어노테이션이 정상적으로 작동한다
2. 반복적으로 실행하고자 하는 메소드에 @Scheduled 어노테이션 사용
사용하고자 하는 메소드에 @Scheduled 어노테이션을 사용하여 일정 시간 혹은 일정 간격마다 메소드를 반복 실행시킨다.
3. 메소드 반복 실행 주기를 설정 및 기준 시간 설정
반복 주기 설정 및 기준 시간 설정 ( 현재는 @Scheduled 속성 중 cron 표현식을 사용하였으며 매 월 1일 자정마다 메소드가 반복 실행되게끔 설정 )
반복 주기 표현은 @Scheduled 어노테이션의 속성 값 마다 표현 방법이 다르며 나는 cron 표현식을 사용하였다