[하나디지털파워온] 개발

JUJU·2024년 6월 15일
0

프로젝트

목록 보기
15/26

1. 사용자가 보낸 사진 저장

이미지 저장 방식

  1. 이미지 자체를 DB에 저장하는 방식
    -> DB 병목등의 문제

  2. 경로 저장 방식
    -> 다른 저장소에 따로 저장 하고, 해당 주소를 DB에 저장하는 방식

2번 방식을 사용해서 이미지 저장을 구현하기로 결정


Photo 클래스

@Entity
@Getter
@Table(name = "photo")
public class Photo {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "photo_id", nullable = false)
    private Long photoId;

    @ManyToOne
    @JoinColumn(name = "user_id", nullable = false)
    private User user;

    @Column(name = "file_path", nullable = false)
    private String filePath;

    @Column(name = "upload_time", nullable = false)
    private LocalDateTime uploadTime;

    @Column(name = "latitude", nullable = false)
    private double latitude;

    @Column(name = "longitude", nullable = false)
    private double longitude;

    @Column(name = "status", nullable = false)
    private String status;

    @Builder
    public Photo(Long photoId, User user, String filePath, LocalDateTime uploadTime, double latitude, double longitude, String status) {
        this.photoId = photoId;
        this.user = user;
        this.filePath = filePath;
        this.uploadTime = uploadTime;
        this.latitude = latitude;
        this.longitude = longitude;
        this.status = status;
    }


    public Photo() {

    }

PhotoController 클래스

@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public ResponseEntity<String> uploadPhoto(@RequestPart("file") MultipartFile file, @ModelAttribute PhotoRequest request) {
        try {
            UUID id = UUID.fromString(request.getId());
            Double latitude = Double.valueOf(request.getLatitude());
            Double longitude = Double.valueOf(request.getLongitude());

            Long userId = userService.findUserIdById(id);
            PhotoDTO photoDTO = photoService.storePhoto(file, userId, latitude, longitude);

            return ResponseEntity.ok("File uploaded successfully: " + photoDTO.getFilePath());
        } catch (Exception e) {
            return ResponseEntity.badRequest().body("Failed to upload file: " + e.getMessage());
        }
    }

프론트에서 Request Body로 전달해야 할 내용

  1. file (이미지 파일)
  2. id (사용자 id)
  3. latitude (사진찍은 위치의 위도)
  4. longitude (사진찍은 위치의 경도)
    ...

    더 추가될 가능성 있음!

Swagger에서는 사용 불가. Postman으로 실행해봐야 함




2. 사진에서 텍스트 추출

gcloud vision api 사용

설정 & 사용법

  1. glcoud CLI 설치
  2. gcloud init
  3. gcloud 명령어 환경변수에 넣기
  4. 결제 활성화
  5. 자바 코드 실행


텍스트 추출 결과

Text: 닌텐도
40만원
→30만원


텍스트 추출 결과

Text: 인기반찬 BEST10
1000
삼계탕
오늘의행사
진미채
10,000원
->5,000원
1-
234567
8.
9 10 11 12 13 14 15
A
16 17 18 19 20 21 22
23 24 25 26 27 28 29

생각보다 성능이 너무 좋아서, 필요 없는 문자들까지 인식되어버리는 문제가 발생했다.

굳이 텍스트 추출을 해야하나?
이미지 자체를 AI에 넘기면 될 것 같은데

Vertex AI를 사용해보자.
AI로 할인 정보 판단 (쓸데없는 텍스트가 존재할 수 있으므로)

일단은 패스
구현 됐다고 생각하자.




3. DB에 할인 정보 저장

  1. 할인 이미지와 사용자 데이터, 위치 정보를 같이 보내는 경우
  2. 할인 이미지 없이, 사용자 데이터와 위치 정보만 보내는 경우
  • 사용자의 데이터 저장(중요 - 하나은행 이득 포인트)

4. 프론트에서 특정 위치 주변의 할인 정보 요청


위도: 37.5844, 경도: 127.0587 근처 10KM 내에 존재하는 모든 할인 정보를 JSON 형식으로 응답한다.




오류

@PostMapping
    public ResponseEntity<String> uploadPhoto(@RequestPart("file") MultipartFile file, @RequestBody PhotoRequest request) {
        try {
            UUID id = UUID.fromString(request.getId());
            Double latitude = Double.valueOf(request.getLatitude());
            Double longitude = Double.valueOf(request.getLongitude());

            Long userId = userService.findUserIdById(id);
            PhotoDTO photoDTO = photoService.storePhoto(file, userId, latitude, longitude);
            return ResponseEntity.ok("File uploaded successfully: " + photoDTO.getFilePath());
        } catch (Exception e) {
            return ResponseEntity.badRequest().body("Failed to upload file: " + e.getMessage());
        }
    }

위의 uploadPhoto 메소드를 실행했더니 다음과 같은 오류가 발생했다.

Resolved [org.springframework.web.HttpMediaTypeNotSupportedException:
Content-Type 'multipart/form-data;boundary=--------------------------440780948424522369548408;
charset=UTF-8' is not supported]

위의 오류에 대해서 구글링을 해봤는데, StackOverflow에서 다음과 같은 문구를 발견했다.
In case of MultipartFile you can't use JSON data so you can't use @RequestBody


First Try (실패)

file을 PhotoRequest의 새로운 필드로 넣으면 되지 않을까?

@RequestBody 는 데이터를 JSON 형태로 전달받는다.
단순히 내부에 MultipartFile 형태의 필드를 추가했다고해서 해당 값을 @RequestBody 로 바인딩 할 수는 없다.

Second Try (성공)

@RequestBody@ModelAttribute로 변경

➜ @ModelAttribute는 multipart/form-data를 포함하여 모든 폼 데이터를 객체에 바인딩할 수 있는 메커니즘을 제공한다.


profile
개발자 지망생

0개의 댓글

관련 채용 정보