Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@


## 📹 시연 영상

https://youtu.be/fRpYXArJiNk

## 💻 개발 환경
- 개발 언어: JavaScript, Java, SQL, JSON
Expand Down
51 changes: 0 additions & 51 deletions emotion-server/app.py

This file was deleted.

33,314 changes: 0 additions & 33,314 deletions emotion-server/haarcascade/haarcascade_frontalface_default.xml

This file was deleted.

32 changes: 0 additions & 32 deletions emotion-server/model.py

This file was deleted.

6 changes: 0 additions & 6 deletions emotion-server/requirements.txt

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti
)
.authorizeHttpRequests(
(requests) -> requests
.requestMatchers("/users/check-email").permitAll()
.requestMatchers("/users/check-nickname").permitAll()
.requestMatchers("/", "/users/join", "/users/login", "/swagger-ui/**", "/v3/api-docs/**", "/api/personas", "/api/emotion").permitAll()
.requestMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

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

@RestController
@RequestMapping("/users")
public class UserRestController {
Expand Down Expand Up @@ -58,4 +61,22 @@ public ApiResponse<UserResponseDTO.UserInfoDTO> updateCurrentUserInfo(@RequestBo
UserResponseDTO.UserInfoDTO updatedUserInfo = userService.updateUserInfo(currentUserId, request);
return ApiResponse.onSuccess(updatedUserInfo);
}

@GetMapping("/check-email")
@Operation(summary = "이메일 중복 체크 API", description = "회원가입 시 이메일 중복 여부를 확인하는 API입니다.")
public ApiResponse<Map<String, Boolean>> checkEmailDuplicate(@RequestParam String email) {
boolean isAvailable = userService.isEmailAvailable(email);
Map<String, Boolean> result = new HashMap<>();
result.put("available", isAvailable);
return ApiResponse.onSuccess(result);
}

@GetMapping("/check-nickname")
@Operation(summary = "닉네임 중복 체크 API", description = "회원가입 시 닉네임 중복 여부를 확인하는 API입니다.")
public ApiResponse<Map<String, Boolean>> checkNicknameDuplicate(@RequestParam String nickname) {
boolean isAvailable = userService.isNicknameAvailable(nickname);
Map<String, Boolean> result = new HashMap<>();
result.put("available", isAvailable);
return ApiResponse.onSuccess(result);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,20 @@
@Repository
public interface UserRepository extends JpaRepository<Users, Long> {
Optional<Users> findByEmail(String email);

/**
* 이메일 존재 여부 확인
*
* @param email 확인할 이메일
* @return 이메일이 존재하면 true, 없으면 false
*/
boolean existsByEmail(String email);

/**
* 닉네임 존재 여부 확인
*
* @param name 확인할 닉네임
* @return 닉네임이 존재하면 true, 없으면 false
*/
boolean existsByName(String name);
}
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,8 @@ public ChatMessageDto.Response generateChatResponse(Persona persona, List<ChatMe
ChatCompletionRequest completionRequest = ChatCompletionRequest.builder()
.model(CHAT_MODEL)
.messages(messages)
.maxTokens(300) // 최대 토큰 수 제한
.temperature(0.7) // 응답 다양성 조절
.maxTokens(100) // 최대 토큰 수 제한
.temperature(0.9) // 응답 다양성 조절
.n(1) // 생성할 응답 수
.build();

Expand Down Expand Up @@ -628,7 +628,7 @@ private String buildPromptFromJson(JsonNode personaJson, Persona persona) {
prompt.append(" 이 태그는 응답의 마지막에 위치해야 하며, 태그 없이 응답을 종료하지 마세요.");

// 감정 선택지 결정 (한글로 변경)
String emotionChoices = "차분, 인내, 지지, 친근, 안심, 사려깊음, 중립";
String emotionChoices = "기쁨,행복,즐거움,친근,슬픔,우울,실망,화남,분노,짜증,놀람,당황,걱정,불안,공포,중립,평온,차분";
if (personaJson.has("available_emotions") && personaJson.get("available_emotions").isArray()) {
StringBuilder emotions = new StringBuilder();
JsonNode availableEmotions = personaJson.get("available_emotions");
Expand Down Expand Up @@ -732,8 +732,7 @@ private String extractEmotion(String response, Persona persona) {

// 4. 응답 내용에서 감정 단어 검색
// 감정 단어 목록
String[] Emotions = {"행복", "슬픔", "화남", "신남", "차분", "중립", "친근", "지지",
"자신감", "열정", "낙관", "인내", "안심", "사려깊음"};
String[] Emotions = {"기쁨","행복","즐거움","친근","슬픔","우울","실망","화남","분노","짜증","놀람","당황","걱정","불안","공포","중립","평온","차분"};

// 마지막 문장에서만 감정 단어 검색
int lastSentenceStart = Math.max(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,72 +39,23 @@ public String getPersonaProfileImageUrl(DiscType discType, Gender gender, Intege
log.warn("DISC 유형 또는 성별이 null입니다. 기본 이미지를 사용합니다.");
return s3Service.getProfileImageUrl(DEFAULT_IMAGE_PATH);
}

// 연령대 결정
String ageGroup = getAgeGroup(age);

// 성별 문자열 (None인 경우 Male로 처리)
String genderStr = (gender == Gender.None) ? "Male" : gender.name();

// 기본 이미지 경로 생성
String discTypeStr = discType.name();
String imagePath = String.format("%s/%s/%s/%s_%s_%s.png",
PROFILE_BASE_PATH, discTypeStr, genderStr, discTypeStr, genderStr, ageGroup);
String imagePath = String.format("%s/%s/%s/%s_%s.png",
PROFILE_BASE_PATH, discTypeStr, genderStr, discTypeStr, genderStr);

// 이미지 존재 여부 확인
if (amazonS3.doesObjectExist(bucketName, imagePath)) {
log.info("페르소나 프로필 이미지를 찾았습니다: {}", imagePath);
return s3Service.getProfileImageUrl(imagePath);
}

// 대체 이미지 시도 (같은 DISC 유형, 같은 성별, 다른 연령대)
String[] alternativeAgeGroups = {"20", "30", "40", "10"};
for (String altAgeGroup : alternativeAgeGroups) {
if (!altAgeGroup.equals(ageGroup)) {
String altImagePath = String.format("%s/%s/%s/%s_%s_%s.png",
PROFILE_BASE_PATH, discTypeStr, genderStr, discTypeStr, genderStr, altAgeGroup);

if (amazonS3.doesObjectExist(bucketName, altImagePath)) {
log.info("대체 연령대 프로필 이미지를 찾았습니다: {}", altImagePath);
return s3Service.getProfileImageUrl(altImagePath);
}
}
}

// 대체 이미지 시도 (같은 DISC 유형, 다른 성별)
String alternativeGender = genderStr.equals("Male") ? "Female" : "Male";
String altGenderImagePath = String.format("%s/%s/%s/%s_%s_%s.png",
PROFILE_BASE_PATH, discTypeStr, alternativeGender, discTypeStr, alternativeGender, ageGroup);

if (amazonS3.doesObjectExist(bucketName, altGenderImagePath)) {
log.info("대체 성별 프로필 이미지를 찾았습니다: {}", altGenderImagePath);
return s3Service.getProfileImageUrl(altGenderImagePath);
}

// 기본 이미지 반환
log.warn("적합한 프로필 이미지를 찾을 수 없습니다. 기본 이미지를 사용합니다.");
return s3Service.getProfileImageUrl(DEFAULT_IMAGE_PATH);
}

/**
* 나이를 연령대 그룹으로 변환합니다.
*
* @param age 나이
* @return 연령대 그룹 (10, 20, 30, 40)
*/
private String getAgeGroup(Integer age) {
if (age == null) {
return "20"; // 기본값
}

if (age < 20) {
return "10";
} else if (age < 30) {
return "20";
} else if (age < 40) {
return "30";
} else {
return "40";
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,20 @@ public interface UserService {
* @return 수정된 사용자 정보 DTO
*/
UserResponseDTO.UserInfoDTO updateUserInfo(Long userId, UserRequestDTO.UpdateUserDto request);

/**
* 이메일 중복 체크
*
* @param email 중복 체크할 이메일
* @return 사용 가능한 이메일이면 true, 이미 사용 중이면 false
*/
boolean isEmailAvailable(String email);

/**
* 닉네임 중복 체크
*
* @param nickname 중복 체크할 닉네임
* @return 사용 가능한 닉네임이면 true, 이미 사용 중이면 false
*/
boolean isNicknameAvailable(String nickname);
}
Original file line number Diff line number Diff line change
Expand Up @@ -114,29 +114,42 @@ public UserResponseDTO.UserInfoDTO updateUserInfo(Long userId, UserRequestDTO.Up
}
}

// 새 Users 객체 생성 및 저장
Users updatedUser = Users.builder()
.id(user.getId())
.name(newName)
.email(user.getEmail())
.password(newPassword)
.gender(newGender)
.role(user.getRole())
.socialType(user.getSocialType())
.build();

updatedUser = userRepository.save(updatedUser);

// DTO로 변환하여 반환
return UserResponseDTO.UserInfoDTO.builder()
.id(updatedUser.getId())
.name(updatedUser.getName())
.email(updatedUser.getEmail())
.gender(updatedUser.getGender())
.role(updatedUser.getRole())
.socialType(updatedUser.getSocialType())
.createdAt(updatedUser.getCreatedAt())
.build();
}
// 새 Users 객체 생성 및 저장
Users updatedUser = Users.builder()
.id(user.getId())
.name(newName)
.email(user.getEmail())
.password(newPassword)
.gender(newGender)
.role(user.getRole())
.socialType(user.getSocialType())
.build();
updatedUser = userRepository.save(updatedUser);
// DTO로 변환하여 반환
return UserResponseDTO.UserInfoDTO.builder()
.id(updatedUser.getId())
.name(updatedUser.getName())
.email(updatedUser.getEmail())
.gender(updatedUser.getGender())
.role(updatedUser.getRole())
.socialType(updatedUser.getSocialType())
.createdAt(updatedUser.getCreatedAt())
.build();
}

@Override
@Transactional(readOnly = true)
public boolean isEmailAvailable(String email) {
// 이메일이 존재하지 않으면 true(사용 가능), 존재하면 false(사용 불가) 반환
return !userRepository.existsByEmail(email);
}

@Override
@Transactional(readOnly = true)
public boolean isNicknameAvailable(String nickname) {
// 닉네임이 존재하지 않으면 true(사용 가능), 존재하면 false(사용 불가) 반환
return !userRepository.existsByName(nickname);
}
}