프로젝트를 진행하면서 백엔드 서버에서 프론트 측으로 이미지 정보를 전송해줘야 하는 경우가 많이 발생하였다.
보통은 이미지 서버를 별도로 운영하여 원본의 데이터를 제공하지 않고 이미지 서버(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';
functionExample() {
// like 는 사용 변수, setLike 는 State 변경 함수let [like, setLike] = useState(0);
return (
<div><ponClick = { () => {
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 표현식을 사용하였다
resframework 의 Response 와 api_view 를 import 하여 각각 get, post, put, delete 요청을 모두 result 함수로 처리하게 하고 요청 방식에 따라 로직을 구분하여 나눈다
코드 정삭적으로 실행되는 것 확인
경로 추가
test2 경로로 접속 시 실행될 함수 선언
spring 에서 jsp 파일에 코드를 작성
접속하면 에러가 뜨는데 이유는 서로 다른 서버에 데이터를 요청하게되면 에러가 발생함...!!!
이 에러를 해결해주기 위해선 라이브러리 설치가 필요하다
서로 다른 서버끼리 데이터 교환을 허용해주는 라이브러리인 django-cors-headers 설치
settings.py 에 접속하여 설치한 crosheaders 라이브러리를 설정해준다 >> 정상적으로 데이터가 전송된다
CORS(Cross-Origin Resource Sharing) : 서로 다른 서버들 끼리 데이터를 주고 받으려 할때 발생하는 오류
이제부터 데이터를 요청하고 응답하면 된다
대출이 가능한지 가능하지 않은지 확인하는 부분을 구현해볼 것임
pandas 설치
sklearn 설치 ( 사이킷런 )
bank 경로 추가
머신 코드 작성
test1 프로젝트 안에 있는 bank_analysis.py 파일을 import 하여 init() 으로 초기화하여 객체에 저장장
django 서버 재실행
이제 스프링 코드 작성
경로 작성
bank_form.jsp 작성 ( 코드 아래 참고 )
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html><html><head><metacharset="UTF-8"><title>Insert title here</title><scriptsrc="https://code.jquery.com/jquery-3.2.1.min.js"></script><scripttype="text/javascript">functiontest(){
let form = {}
//배열 형태로 만들어 준다[{name:day,value:값},{name:weather,value:값}...]let arr = $("#frm").serializeArray()
for(i=0;i<arr.length;i++){
form[arr[i].name]=arr[i].value
}
$.ajax({
url : "http://localhost:8000/bank/", type:"GET",
data: form ,
contentType:"application/json;charset=utf-8",
dataType:"json",
success: function(data){
console.log("전송 성공 : ", data);
if( data.key == 0 )
msg ="가입 가능성 있음"else
msg ="가입 안합니다!!!!!"
$("#result").html( msg )
},error:function(){
alert("문제 발생")
}
})
}
</script></head><body><h1>정기예금 가입 여부</h1><bid="result">결과를 보여줍니다</b><hr><formid="frm"><inputtype="text"name="age"placeholder="사용자 나이 입력"><br><inputtype="text"name="duration"placeholder="마지막 접촉 지속 시간(초)"><br><inputtype="text"name="campaign"placeholder="마케팅 전화를 받은 수(몇번 통화 됐는지)"><br><!-- 10일전 마지막 통화인지 20일전 마지막 통화인지를 수로 입력 --><inputtype="text"name="pdays"placeholder="마지막으로 통화한 일 수"><br><inputtype="text"name="previous"placeholder="가입 제의를 한 횟수"><br><inputtype="button"onclick="test()"value="click"></form></body></html>
spring 서버 실행 후 경로 접속
접속 성공
spring 서버에서 데이터를 django 서버로 전송하여 데이터 처리 후 다시 spring 서버로 받아서 메세지 처리....