diff --git a/build.gradle b/build.gradle index 32922ead..5ba01d2f 100644 --- a/build.gradle +++ b/build.gradle @@ -22,12 +22,18 @@ configurations { repositories { mavenCentral() maven { url 'https://jitpack.io' } + maven { url 'https://repo.spring.io/milestone' } +} + +ext { + set('springAiVersion', "1.0.0-M1") } dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-validation' implementation 'org.springframework.boot:spring-boot-starter-web' + developmentOnly 'org.springframework.boot:spring-boot-devtools' // security implementation 'io.jsonwebtoken:jjwt-api:0.12.5' @@ -37,6 +43,10 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-security' implementation 'org.springframework.boot:spring-boot-starter-oauth2-client' + // GPT 프롬프트 + implementation 'org.springframework.ai:spring-ai-openai-spring-boot-starter' + // implementation 'io.github.flashvayne:chatgpt-spring-boot-starter:1.0.4' + // redis implementation 'org.springframework.boot:spring-boot-starter-data-redis' @@ -66,6 +76,12 @@ dependencies { implementation 'org.springframework.data:spring-data-elasticsearch:' } +dependencyManagement { + imports { + mavenBom "org.springframework.ai:spring-ai-bom:${springAiVersion}" + } +} + tasks.named('test') { useJUnitPlatform() -} +} \ No newline at end of file diff --git a/src/main/java/com/umc/naoman/domain/shareGroup/controller/ShareGroupController.java b/src/main/java/com/umc/naoman/domain/shareGroup/controller/ShareGroupController.java index f285fd5d..d38379f8 100644 --- a/src/main/java/com/umc/naoman/domain/shareGroup/controller/ShareGroupController.java +++ b/src/main/java/com/umc/naoman/domain/shareGroup/controller/ShareGroupController.java @@ -56,7 +56,7 @@ public class ShareGroupController { }) public ResultResponse getShareGroupDetailInfo(@PathVariable(name = "shareGroupId") Long shareGroupId) { ShareGroup shareGroup = shareGroupService.findShareGroup(shareGroupId); - List profileList = shareGroupService.findProfileList(shareGroupId); + List profileList = shareGroupService.findProfileListByShareGroupId(shareGroupId); return ResultResponse.of(ShareGroupResultCode.SHARE_GROUP_INFO, shareGroupConverter.toShareGroupDetailInfo(shareGroup, profileList)); @@ -69,7 +69,7 @@ public ResultResponse getShareGroupDeta }) public ResultResponse getShareGroupByInviteCode(@RequestParam String inviteCode) { ShareGroup shareGroup = shareGroupService.findShareGroup(inviteCode); - List profileList = shareGroupService.findProfileList(shareGroup.getId()); + List profileList = shareGroupService.findProfileListByShareGroupId(shareGroup.getId()); return ResultResponse.of(ShareGroupResultCode.SHARE_GROUP_INFO, shareGroupConverter.toShareGroupDetailInfo(shareGroup, profileList)); diff --git a/src/main/java/com/umc/naoman/domain/shareGroup/converter/ShareGroupConverter.java b/src/main/java/com/umc/naoman/domain/shareGroup/converter/ShareGroupConverter.java index a91fd3d1..dfe95289 100644 --- a/src/main/java/com/umc/naoman/domain/shareGroup/converter/ShareGroupConverter.java +++ b/src/main/java/com/umc/naoman/domain/shareGroup/converter/ShareGroupConverter.java @@ -16,10 +16,11 @@ public class ShareGroupConverter { private static final String BASE_URL = "https://naoman/invite/"; //baseUrl 상수 - public ShareGroup toEntity(ShareGroupRequest.createShareGroupRequest request) { + public ShareGroup toEntity(ShareGroupRequest.createShareGroupRequest request, String inviteCode, String groupName) { return ShareGroup.builder() - .memberCount(request.getMemberNameList().size()) // 변경 가능성 있음. memberCount 대신 nameList의 size 사용 - .name("임시 공유 그룹 이름") //임시 공유 그룹 이름 + .memberCount(request.getMemberNameList().size()) //nameList의 size 사용 + .inviteCode(inviteCode) // 생성된 초대 코드 + .name(groupName) // gpt로 만들어진 공유 그룹 이름 .build(); } diff --git a/src/main/java/com/umc/naoman/domain/shareGroup/entity/Profile.java b/src/main/java/com/umc/naoman/domain/shareGroup/entity/Profile.java index 47a5ff36..9053b458 100644 --- a/src/main/java/com/umc/naoman/domain/shareGroup/entity/Profile.java +++ b/src/main/java/com/umc/naoman/domain/shareGroup/entity/Profile.java @@ -1,7 +1,17 @@ package com.umc.naoman.domain.shareGroup.entity; import com.umc.naoman.domain.member.entity.Member; -import jakarta.persistence.*; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.Builder; diff --git a/src/main/java/com/umc/naoman/domain/shareGroup/entity/ShareGroup.java b/src/main/java/com/umc/naoman/domain/shareGroup/entity/ShareGroup.java index 6e9464e0..6070729d 100644 --- a/src/main/java/com/umc/naoman/domain/shareGroup/entity/ShareGroup.java +++ b/src/main/java/com/umc/naoman/domain/shareGroup/entity/ShareGroup.java @@ -1,11 +1,20 @@ package com.umc.naoman.domain.shareGroup.entity; import com.umc.naoman.global.entity.BaseTimeEntity; -import jakarta.persistence.*; -import lombok.*; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.OneToMany; +import jakarta.persistence.Table; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; import org.hibernate.annotations.SQLRestriction; -import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; @@ -13,7 +22,6 @@ @Table(name = "share_groups") @SQLRestriction("deleted_at is NULL") @Getter -@Setter @Builder @NoArgsConstructor(access = AccessLevel.PROTECTED) @AllArgsConstructor diff --git a/src/main/java/com/umc/naoman/domain/shareGroup/service/OpenAiService.java b/src/main/java/com/umc/naoman/domain/shareGroup/service/OpenAiService.java new file mode 100644 index 00000000..b38700e3 --- /dev/null +++ b/src/main/java/com/umc/naoman/domain/shareGroup/service/OpenAiService.java @@ -0,0 +1,7 @@ +package com.umc.naoman.domain.shareGroup.service; + +import java.util.List; + +public interface OpenAiService { + String generateGroupName(String place, List meetingTypeList); +} diff --git a/src/main/java/com/umc/naoman/domain/shareGroup/service/OpenAiServiceImpl.java b/src/main/java/com/umc/naoman/domain/shareGroup/service/OpenAiServiceImpl.java new file mode 100644 index 00000000..a0b90aa6 --- /dev/null +++ b/src/main/java/com/umc/naoman/domain/shareGroup/service/OpenAiServiceImpl.java @@ -0,0 +1,27 @@ +package com.umc.naoman.domain.shareGroup.service; + +import lombok.RequiredArgsConstructor; +import org.springframework.ai.openai.OpenAiChatModel; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +@Service +@Transactional(readOnly = true) +@RequiredArgsConstructor +public class OpenAiServiceImpl implements OpenAiService { + + private final OpenAiChatModel chatModel; + + public String generateGroupName(String place, List meetingTypeList) { + String prompt = String.format("장소: %s, 모임 종류: %s \n위 키워드를 참고해 재미있는 그룹 이름을 공백 포함 10자~20자 사이로 하나만 지어줘. 큰따옴표는 제외하고 보여줘.", + place, String.join(", ", meetingTypeList)); + String response = chatModel.call(prompt); + return removeQuotes(response); + } + + private String removeQuotes(String response) { + return response.replace("\"", ""); // 모든 큰따옴표 제거 + } +} \ No newline at end of file diff --git a/src/main/java/com/umc/naoman/domain/shareGroup/service/ShareGroupService.java b/src/main/java/com/umc/naoman/domain/shareGroup/service/ShareGroupService.java index f05fc26d..6c968beb 100644 --- a/src/main/java/com/umc/naoman/domain/shareGroup/service/ShareGroupService.java +++ b/src/main/java/com/umc/naoman/domain/shareGroup/service/ShareGroupService.java @@ -11,14 +11,15 @@ public interface ShareGroupService { ShareGroup createShareGroup(ShareGroupRequest.createShareGroupRequest request, Member member); + ShareGroup joinShareGroup(Long shareGroupId, Long profileId, Member member); + ShareGroup getInviteInfo(Long shareGroupId, Member member); + ShareGroup deleteShareGroup(Long shareGroupId, Member member); + Page getMyShareGroupList(Member member, Pageable pageable); ShareGroup findShareGroup(Long shareGroupId); ShareGroup findShareGroup(String inviteCode); - List findProfileList(Long shareGroupId); - ShareGroup joinShareGroup(Long shareGroupId, Long profileId, Member member); + List findProfileListByShareGroupId(Long shareGroupId); + List findProfileListByMemberId(Long memberId); Profile findProfile(Long profileId); Profile findProfile(Long shareGroupId, Long memberID); - Page getMyShareGroupList(Member member, Pageable pageable); - ShareGroup deleteShareGroup(Long shareGroupId, Member member); - ShareGroup getInviteInfo(Long shareGroupId, Member member); boolean doesProfileExist(Long shareGroupId, Long memberId); } diff --git a/src/main/java/com/umc/naoman/domain/shareGroup/service/ShareGroupServiceImpl.java b/src/main/java/com/umc/naoman/domain/shareGroup/service/ShareGroupServiceImpl.java index 693c6549..281ddf28 100644 --- a/src/main/java/com/umc/naoman/domain/shareGroup/service/ShareGroupServiceImpl.java +++ b/src/main/java/com/umc/naoman/domain/shareGroup/service/ShareGroupServiceImpl.java @@ -9,7 +9,6 @@ import com.umc.naoman.domain.shareGroup.repository.ProfileRepository; import com.umc.naoman.domain.shareGroup.repository.ShareGroupRepository; import com.umc.naoman.global.error.BusinessException; -import com.umc.naoman.global.error.code.MemberErrorCode; import com.umc.naoman.global.error.code.ShareGroupErrorCode; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; @@ -30,17 +29,20 @@ public class ShareGroupServiceImpl implements ShareGroupService { private final ShareGroupRepository shareGroupRepository; private final ProfileRepository profileRepository; private final ShareGroupConverter shareGroupConverter; + private final OpenAiService openAiService; @Transactional @Override public ShareGroup createShareGroup(ShareGroupRequest.createShareGroupRequest request, Member member) { + // GPT 프롬프트로 groupName 생성 + String groupName = openAiService.generateGroupName(request.getPlace(), request.getMeetingTypeList()); + // 초대링크를 위한 고유번호 생성 (UUID) String inviteCode = UUID.randomUUID().toString().replace("-", "").toUpperCase(); // 변환 로직 - ShareGroup newShareGroup = shareGroupConverter.toEntity(request); - newShareGroup.setInviteCode(inviteCode); + ShareGroup newShareGroup = shareGroupConverter.toEntity(request, inviteCode, groupName); // 생성된 공유 그룹 저장 ShareGroup savedShareGroup = shareGroupRepository.save(newShareGroup); @@ -139,11 +141,6 @@ public ShareGroup findShareGroup(String inviteCode) { .orElseThrow(() -> new BusinessException(ShareGroupErrorCode.SHARE_GROUP_NOT_FOUND)); } - @Override - public List findProfileList(Long shareGroupId) { - return profileRepository.findByShareGroupId(shareGroupId); - } - @Override public Profile findProfile(Long profileId) { return profileRepository.findById(profileId) @@ -161,4 +158,13 @@ public boolean doesProfileExist(Long shareGroupId, Long memberId) { return profileRepository.existsByShareGroupIdAndMemberId(shareGroupId, memberId); } + @Override + public List findProfileListByShareGroupId(Long shareGroupId) { + return profileRepository.findByShareGroupId(shareGroupId); + } + + @Override + public List findProfileListByMemberId(Long memberId) { + return profileRepository.findByMemberId(memberId); + } } \ No newline at end of file