Skip to content
2 changes: 2 additions & 0 deletions HalfFifty_BE/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ dependencies {
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.security:spring-security-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
implementation 'software.amazon.awssdk:lambda:2.20.26' // AWS Lambda SDK

}

tasks.named('test') {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package HalfFifty.HalfFifty_BE.translation.bean;

import HalfFifty.HalfFifty_BE.translation.domain.DTO.RequestSignLanguageDTO;
import org.springframework.http.*;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import java.util.HashMap;
import java.util.Map;

@Component
public class FlaskSignLanguageBean {
private final RestTemplate restTemplate;
private final String aiServerUrl = "http://3.39.24.155/predict"; // Flask 서버 URL

public FlaskSignLanguageBean() {
this.restTemplate = new RestTemplate();
}

// Flask AI 서버로 요청 보내기
public Map<String, Object> exec(RequestSignLanguageDTO requestSignLanguageDTO) {
Map<String, Object> requestBody = new HashMap<>();
requestBody.put("keypoints", requestSignLanguageDTO.getKeypoints());

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);

HttpEntity<Map<String, Object>> request = new HttpEntity<>(requestBody, headers);

try {
ResponseEntity<Map> response = restTemplate.postForEntity(aiServerUrl, request, Map.class);

if (response.getStatusCode() == HttpStatus.OK) {
return response.getBody();
} else {
Map<String, Object> errorResponse = new HashMap<>();
errorResponse.put("success", false);
errorResponse.put("error", "AI 서버에서 오류 응답 발생");
return errorResponse;
}
} catch (Exception e) {
e.printStackTrace();
Map<String, Object> errorResponse = new HashMap<>();
errorResponse.put("success", false);
errorResponse.put("error", e.getMessage());
return errorResponse;
}
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package HalfFifty.HalfFifty_BE.translation.bean;

import HalfFifty.HalfFifty_BE.translation.bean.small.CreateTranslationDAOBean;
import HalfFifty.HalfFifty_BE.translation.bean.small.CreateTranslationDTOBean;
import HalfFifty.HalfFifty_BE.translation.bean.small.SaveTranslationDAOBean;
import HalfFifty.HalfFifty_BE.translation.domain.DTO.ResponseTranslationGetDTO;
import HalfFifty.HalfFifty_BE.translation.domain.TranslationDAO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.UUID;

@Component
public class SaveTranslationBean {
CreateTranslationDAOBean createTranslationDAOBean;
CreateTranslationDTOBean createTranslationDTOBean;
SaveTranslationDAOBean saveTranslationDAOBean;

@Autowired
public SaveTranslationBean(CreateTranslationDAOBean createTranslationDAOBean, CreateTranslationDTOBean createTranslationDTOBean, SaveTranslationDAOBean saveTranslationDAOBean) {
this.createTranslationDAOBean = createTranslationDAOBean;
this.createTranslationDTOBean = createTranslationDTOBean;
this.saveTranslationDAOBean = saveTranslationDAOBean;
}

// 번역 기록 저장
public ResponseTranslationGetDTO exec(UUID userId, String translationWord, Double probability) {
// 번역 객체 생성
TranslationDAO translationDAO = createTranslationDAOBean.exec(userId, translationWord);
if(translationDAO == null) return null;

// 번역 저장
saveTranslationDAOBean.exec(translationDAO);

// 수화 번역 객체를 DTO로 변환해서 반환
return createTranslationDTOBean.exec(translationDAO, probability);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package HalfFifty.HalfFifty_BE.translation.bean.small;

import HalfFifty.HalfFifty_BE.translation.domain.TranslationDAO;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.UUID;

@Component
public class CreateTranslationDAOBean {

// 번역 기록 객체 생성
public TranslationDAO exec(UUID userId, String translationWord) {
return TranslationDAO.builder()
.userId(userId)
.translationWord(translationWord)
.createdAt(LocalDateTime.now())
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package HalfFifty.HalfFifty_BE.translation.bean.small;

import HalfFifty.HalfFifty_BE.translation.domain.DTO.ResponseTranslationGetDTO;
import HalfFifty.HalfFifty_BE.translation.domain.TranslationDAO;
import org.springframework.stereotype.Component;

@Component
public class CreateTranslationDTOBean {

// 수화 번역 객체를 DTO로 변환해서 반환
public ResponseTranslationGetDTO exec(TranslationDAO translationDAO, Double probability) {
return ResponseTranslationGetDTO.builder()
.translationId(translationDAO.getTranslationId())
.userId(translationDAO.getUserId())
.translationWord(translationDAO.getTranslationWord())
.createdAt(translationDAO.getCreatedAt())
.probability(probability)
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package HalfFifty.HalfFifty_BE.translation.bean.small;

import HalfFifty.HalfFifty_BE.translation.domain.TranslationDAO;
import HalfFifty.HalfFifty_BE.translation.repository.TranslationRepositoryJPA;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class SaveTranslationDAOBean {
TranslationRepositoryJPA translationRepositoryJPA;

@Autowired
public SaveTranslationDAOBean(TranslationRepositoryJPA translationRepositoryJPA) {
this.translationRepositoryJPA = translationRepositoryJPA;
}

// 번역 기록 저장
public void exec(TranslationDAO translationDAO) {
translationRepositoryJPA.save(translationDAO);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package HalfFifty.HalfFifty_BE.translation.controller;

import HalfFifty.HalfFifty_BE.translation.domain.DTO.RequestSignLanguageDTO;
import HalfFifty.HalfFifty_BE.translation.domain.DTO.ResponseTranslationGetDTO;
import HalfFifty.HalfFifty_BE.translation.service.TranslationService;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping("/translation")
@CrossOrigin("*")
public class TranslationController {
TranslationService translationService;

public TranslationController(TranslationService translationService) {
this.translationService = translationService;
}

// 수화 번역 API
@PostMapping
public ResponseEntity<Map<String, Object>> translateSignLanguage(@RequestBody RequestSignLanguageDTO requestSignLanguageDTO) {
// 번역된 데이터 가져오기
ResponseTranslationGetDTO responseTranslationGetDTO = translationService.signLanguageTranslation(requestSignLanguageDTO);

// 번역 성공 여부 확인
boolean success = responseTranslationGetDTO != null;

// 응답 데이터 구성
Map<String, Object> responseMap = new HashMap<>();
responseMap.put("success", success);
responseMap.put("message", success ? "수화 번역 성공" : "수화 번역 실패");
responseMap.put("translationId", success ? responseTranslationGetDTO.getTranslationId() : null);
responseMap.put("translatedWord", success ? responseTranslationGetDTO.getTranslationWord() : null);
responseMap.put("probability", success ? responseTranslationGetDTO.getProbability() : null);

return ResponseEntity.status(HttpStatus.OK).body(responseMap);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package HalfFifty.HalfFifty_BE.translation.domain.DTO;

import lombok.Data;

import java.util.List;
import java.util.UUID;

@Data
public class RequestSignLanguageDTO {
private List<List<Double>> keypoints; // 10 x 55 형태의 키포인트 데이터
private UUID userId; // 사용자 식별 ID
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package HalfFifty.HalfFifty_BE.translation.domain.DTO;

import lombok.Builder;
import lombok.Data;

import java.time.LocalDateTime;
import java.util.UUID;

@Data
@Builder
public class ResponseTranslationGetDTO {
UUID translationId;
UUID userId;
String translationWord;
Double probability;
LocalDateTime createdAt;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package HalfFifty.HalfFifty_BE.translation.domain;

import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import lombok.*;

import java.time.LocalDateTime;
import java.util.UUID;

@Entity
@NoArgsConstructor
@AllArgsConstructor
@Getter
@Setter
@Builder
public class TranslationDAO {
@Id @GeneratedValue(strategy = GenerationType.AUTO)
UUID translationId;
UUID userId;
String translationWord;
LocalDateTime createdAt;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package HalfFifty.HalfFifty_BE.translation.repository;

import HalfFifty.HalfFifty_BE.translation.domain.TranslationDAO;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import java.util.UUID;

@Repository
public interface TranslationRepositoryJPA extends JpaRepository<TranslationDAO, UUID> {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package HalfFifty.HalfFifty_BE.translation.service;

import HalfFifty.HalfFifty_BE.translation.bean.FlaskSignLanguageBean;
import HalfFifty.HalfFifty_BE.translation.bean.SaveTranslationBean;
import HalfFifty.HalfFifty_BE.translation.domain.DTO.RequestSignLanguageDTO;
import HalfFifty.HalfFifty_BE.translation.domain.DTO.ResponseTranslationGetDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Map;


@Service
public class TranslationService {
SaveTranslationBean saveTranslationBean;
FlaskSignLanguageBean flaskSignLanguageBean;

@Autowired
public TranslationService(SaveTranslationBean saveTranslationBean, FlaskSignLanguageBean flaskSignLanguageBean) {
this.saveTranslationBean = saveTranslationBean;
this.flaskSignLanguageBean = flaskSignLanguageBean;
}

public ResponseTranslationGetDTO signLanguageTranslation(RequestSignLanguageDTO requestSignLanguageDTO) {
Map<String, Object> aiResponse = flaskSignLanguageBean.exec(requestSignLanguageDTO);

if (aiResponse != null && Boolean.TRUE.equals(aiResponse.get("success"))) {
String translatedWord = (String) aiResponse.get("predicted_label");
Double probability = (Double) aiResponse.get("confidence");
return saveTranslationBean.exec(requestSignLanguageDTO.getUserId(), translatedWord, probability);
} else {
return null;
}
}

}
5 changes: 4 additions & 1 deletion HalfFifty_BE/src/main/resources/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,7 @@ spring.jpa.properties.hibernate.format_sql=true
spring.datasource.driver-class-name=${DB_DRIVER_CLASS_NAME}
spring.datasource.url=${DB_URL}
spring.datasource.username=${DB_USERNAME}
spring.datasource.password=${DB_PASSWORD}
spring.datasource.password=${DB_PASSWORD}

# lambda
aws.lambda.functionName = myLambda
Loading