diff --git a/subprojects/api/src/main/java/com/poemfoot/api/controller/CardController.java b/subprojects/api/src/main/java/com/poemfoot/api/controller/CardController.java index afbe4c9..3f6e5bf 100644 --- a/subprojects/api/src/main/java/com/poemfoot/api/controller/CardController.java +++ b/subprojects/api/src/main/java/com/poemfoot/api/controller/CardController.java @@ -9,6 +9,7 @@ import com.poemfoot.api.dto.response.card.CardResponse; import com.poemfoot.api.service.CardService; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; @@ -32,6 +33,7 @@ public class CardController { @GetMapping @Operation(summary = "특정 요청자의 카드 목록 조회") public ResponseEntity findCards( + @Parameter(description = "테스트 유저", example = "test") @RequestHeader(DEVICE_ID) String deviceId ) { return ResponseEntity.ok(cardService.findCards(deviceId)); @@ -40,6 +42,7 @@ public ResponseEntity findCards( @PostMapping @Operation(summary = "카드 생성 (생성 전, 시 생성 필요함)") public ResponseEntity saveCard( + @Parameter(description = "테스트 유저", example = "test") @RequestHeader(DEVICE_ID) String deviceId, @RequestBody CardRequest cardRequest ) { diff --git a/subprojects/api/src/main/java/com/poemfoot/api/controller/MemberController.java b/subprojects/api/src/main/java/com/poemfoot/api/controller/MemberController.java index be5c8ca..e3b6bff 100644 --- a/subprojects/api/src/main/java/com/poemfoot/api/controller/MemberController.java +++ b/subprojects/api/src/main/java/com/poemfoot/api/controller/MemberController.java @@ -7,6 +7,7 @@ import com.poemfoot.api.dto.response.member.MemberResponse; import com.poemfoot.api.service.MemberService; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; @@ -28,6 +29,7 @@ public class MemberController { @Operation(summary = "신규 사용자 저장 요청") @PostMapping public ResponseEntity saveMember( + @Parameter(description = "테스트 유저", example = "test") @RequestHeader(DEVICE_ID) String deviceId, @RequestBody MemberRequest memberRequest ) { @@ -37,6 +39,7 @@ public ResponseEntity saveMember( @Operation(summary = "등록된 사용자인지 확인 요청") @GetMapping("/check") public ResponseEntity findSavedMember( + @Parameter(description = "테스트 유저", example = "test") @RequestHeader(DEVICE_ID) String deviceId ) { return ResponseEntity.ok(memberService.findSavedMember(deviceId)); diff --git a/subprojects/api/src/main/java/com/poemfoot/api/service/CardService.java b/subprojects/api/src/main/java/com/poemfoot/api/service/CardService.java index 7da34e3..73a5295 100644 --- a/subprojects/api/src/main/java/com/poemfoot/api/service/CardService.java +++ b/subprojects/api/src/main/java/com/poemfoot/api/service/CardService.java @@ -13,8 +13,8 @@ import com.poemfoot.api.exception.notfound.member.NotFoundMemberException; import com.poemfoot.api.repository.CardRepository; import com.poemfoot.api.repository.MemberRepository; +import com.poemfoot.gpt.GptProvider; import com.poemfoot.gpt.dto.response.chat.GptChatPoemResponse; -import com.poemfoot.gpt.service.GptPoemProvider; import com.poemfoot.w3w.W3wProvider; import java.util.List; import lombok.RequiredArgsConstructor; @@ -31,7 +31,7 @@ public class CardService { private final CardRepository cardRepository; private final MemberRepository memberRepository; private final W3wProvider w3wProvider; - private final GptPoemProvider gptPoemProvider; + private final GptProvider gptProvider; private final PoemService poemService; private final W3wService w3wService; @@ -64,7 +64,7 @@ public CardResponse saveCard(String deviceId, CardRequest request) { public CardReadyResponse checkReadiness() { boolean isReadiness = - gptPoemProvider.validateGptRequest() && w3wProvider.validateW3WRequest(); + gptProvider.validateGptRequest() && w3wProvider.validateW3WRequest(); return CardReadyResponse.from(isReadiness); } diff --git a/subprojects/api/src/main/java/com/poemfoot/api/service/PoemService.java b/subprojects/api/src/main/java/com/poemfoot/api/service/PoemService.java index 0f8aed1..291fc55 100644 --- a/subprojects/api/src/main/java/com/poemfoot/api/service/PoemService.java +++ b/subprojects/api/src/main/java/com/poemfoot/api/service/PoemService.java @@ -7,10 +7,10 @@ import com.poemfoot.api.domain.poem.PoemAnswer; import com.poemfoot.api.exception.notfound.poem.NotFoundPoemException; import com.poemfoot.api.repository.PoemRepository; +import com.poemfoot.gpt.GptProvider; import com.poemfoot.gpt.dto.request.GptChatPoemRequest; import com.poemfoot.gpt.dto.response.chat.GptChatPoemResponse; import com.poemfoot.gpt.exception.toomanyrequest.GptTooManyRequestException; -import com.poemfoot.gpt.service.GptPoemProvider; import java.util.List; import java.util.Objects; import java.util.Optional; @@ -27,7 +27,7 @@ public class PoemService { private static final String TITLE_KEY = "제목"; private static final String CONTENT_KEY = "내용"; - private final GptPoemProvider gptPoemProvider; + private final GptProvider gptProvider; private final PoemRepository poemRepository; @Transactional @@ -40,7 +40,7 @@ public GptChatPoemResponse requestPoem(List words, String location) { return new GptChatPoemResponse(answer.getContent()); } - return gptPoemProvider.completionChat(request) + return gptProvider.completionChat(request) .orElseThrow(GptTooManyRequestException::new); } diff --git a/subprojects/gpt/src/main/java/com/poemfoot/gpt/GptProvider.java b/subprojects/gpt/src/main/java/com/poemfoot/gpt/GptProvider.java new file mode 100644 index 0000000..4962ec1 --- /dev/null +++ b/subprojects/gpt/src/main/java/com/poemfoot/gpt/GptProvider.java @@ -0,0 +1,11 @@ +package com.poemfoot.gpt; + +import com.poemfoot.gpt.dto.request.GptChatPoemRequest; +import com.poemfoot.gpt.dto.response.chat.GptChatPoemResponse; +import java.util.Optional; + +public interface GptProvider { + Optional completionChat(GptChatPoemRequest request); + boolean validateGptRequest(); + +} diff --git a/subprojects/gpt/src/main/java/com/poemfoot/gpt/config/GptConfig.java b/subprojects/gpt/src/main/java/com/poemfoot/gpt/config/GptConfig.java index e8b5836..28c6c12 100644 --- a/subprojects/gpt/src/main/java/com/poemfoot/gpt/config/GptConfig.java +++ b/subprojects/gpt/src/main/java/com/poemfoot/gpt/config/GptConfig.java @@ -1,6 +1,7 @@ package com.poemfoot.gpt.config; -import com.poemfoot.gpt.service.GptPoemProvider; +import com.poemfoot.gpt.GptProvider; +import com.poemfoot.gpt.service.MockGptProviderImpl; import com.theokanning.openai.service.OpenAiService; import java.time.Duration; import java.util.concurrent.atomic.AtomicInteger; @@ -37,8 +38,8 @@ public OpenAiService openAiService() { } @Bean - public GptPoemProvider gptPoemProvider(OpenAiService openAiService) { - return new GptPoemProvider(openAiService); + public GptProvider gptPoemProvider(OpenAiService openAiService) { + return new MockGptProviderImpl(openAiService); } @Scheduled(cron = "0 0 0 * * *") // 매일 자정에 실행 diff --git a/subprojects/gpt/src/main/java/com/poemfoot/gpt/dto/response/chat/GptChatPoemResponse.java b/subprojects/gpt/src/main/java/com/poemfoot/gpt/dto/response/chat/GptChatPoemResponse.java index fdcedd0..d0d3d6f 100644 --- a/subprojects/gpt/src/main/java/com/poemfoot/gpt/dto/response/chat/GptChatPoemResponse.java +++ b/subprojects/gpt/src/main/java/com/poemfoot/gpt/dto/response/chat/GptChatPoemResponse.java @@ -50,4 +50,9 @@ public GptChatPoemResponse(String message) { this.messages = List.of(message); this.reuse = true; } + + public GptChatPoemResponse(String message, boolean reuse) { + this.messages = List.of(message); + this.reuse = reuse; + } } diff --git a/subprojects/gpt/src/main/java/com/poemfoot/gpt/service/GptPoemProvider.java b/subprojects/gpt/src/main/java/com/poemfoot/gpt/service/GptProviderImpl.java similarity index 92% rename from subprojects/gpt/src/main/java/com/poemfoot/gpt/service/GptPoemProvider.java rename to subprojects/gpt/src/main/java/com/poemfoot/gpt/service/GptProviderImpl.java index ee8b196..5cf81cc 100644 --- a/subprojects/gpt/src/main/java/com/poemfoot/gpt/service/GptPoemProvider.java +++ b/subprojects/gpt/src/main/java/com/poemfoot/gpt/service/GptProviderImpl.java @@ -3,6 +3,7 @@ import static com.poemfoot.gpt.config.GptConfig.MAX_TOTAL_REQUEST_COUNT; import static com.poemfoot.gpt.config.GptConfig.totalRequestCount; +import com.poemfoot.gpt.GptProvider; import com.poemfoot.gpt.dto.request.GptChatPoemRequest; import com.poemfoot.gpt.dto.response.chat.GptChatPoemResponse; import com.poemfoot.gpt.exception.server.GptOverRequestException; @@ -12,17 +13,16 @@ import java.util.Optional; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -@Service @Slf4j @RequiredArgsConstructor @Transactional(readOnly = true) -public class GptPoemProvider { +public class GptProviderImpl implements GptProvider { private final OpenAiService openAiService; + @Override @Transactional public Optional completionChat(GptChatPoemRequest request) { validateGptRequest(); @@ -35,6 +35,7 @@ public Optional completionChat(GptChatPoemRequest request) return Optional.empty(); } + @Override public boolean validateGptRequest() { if (totalRequestCount.get() >= MAX_TOTAL_REQUEST_COUNT) { throw new GptOverRequestException(); diff --git a/subprojects/gpt/src/main/java/com/poemfoot/gpt/service/MockGptProviderImpl.java b/subprojects/gpt/src/main/java/com/poemfoot/gpt/service/MockGptProviderImpl.java new file mode 100644 index 0000000..f379b0c --- /dev/null +++ b/subprojects/gpt/src/main/java/com/poemfoot/gpt/service/MockGptProviderImpl.java @@ -0,0 +1,38 @@ +package com.poemfoot.gpt.service; + +import static com.poemfoot.gpt.config.GptConfig.MAX_TOTAL_REQUEST_COUNT; +import static com.poemfoot.gpt.config.GptConfig.totalRequestCount; + +import com.poemfoot.gpt.GptProvider; +import com.poemfoot.gpt.dto.request.GptChatPoemRequest; +import com.poemfoot.gpt.dto.response.chat.GptChatPoemResponse; +import com.poemfoot.gpt.exception.server.GptOverRequestException; +import com.theokanning.openai.service.OpenAiService; +import java.util.Optional; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +public class MockGptProviderImpl implements GptProvider { + + private final OpenAiService openAiService; + + @Override + public Optional completionChat(GptChatPoemRequest request) { + return Optional.of(new GptChatPoemResponse( + """ + { + "제목": "test", + "내용": "test test test test" + } + """, + false)); + } + + @Override + public boolean validateGptRequest() { + if (totalRequestCount.get() >= MAX_TOTAL_REQUEST_COUNT) { + throw new GptOverRequestException(); + } + return true; + } +} diff --git a/subprojects/w3w/src/main/java/com/poemfoot/w3w/config/W3wConfig.java b/subprojects/w3w/src/main/java/com/poemfoot/w3w/config/W3wConfig.java index cc57293..9537eac 100644 --- a/subprojects/w3w/src/main/java/com/poemfoot/w3w/config/W3wConfig.java +++ b/subprojects/w3w/src/main/java/com/poemfoot/w3w/config/W3wConfig.java @@ -1,5 +1,7 @@ package com.poemfoot.w3w.config; +import com.poemfoot.w3w.W3wProvider; +import com.poemfoot.w3w.impl.MockW3wProviderImpl; import com.what3words.javawrapper.What3WordsV3; import java.util.concurrent.atomic.AtomicInteger; import org.springframework.beans.factory.annotation.Value; @@ -21,6 +23,11 @@ public What3WordsV3 what3WordsV3() { return new What3WordsV3(apiKey); } + @Bean + public W3wProvider w3wProvider(What3WordsV3 what3WordsV3) { + return new MockW3wProviderImpl(what3WordsV3); + } + @Scheduled(cron = "0 0 0 * * *") // 매일 자정에 실행 public void resetCounter() { totalRequestCount.set(0); diff --git a/subprojects/w3w/src/main/java/com/poemfoot/w3w/impl/MockW3wProviderImpl.java b/subprojects/w3w/src/main/java/com/poemfoot/w3w/impl/MockW3wProviderImpl.java new file mode 100644 index 0000000..960a021 --- /dev/null +++ b/subprojects/w3w/src/main/java/com/poemfoot/w3w/impl/MockW3wProviderImpl.java @@ -0,0 +1,56 @@ +package com.poemfoot.w3w.impl; + +import static com.poemfoot.w3w.config.W3wConfig.MAX_TOTAL_REQUEST_COUNT; +import static com.poemfoot.w3w.config.W3wConfig.totalRequestCount; + +import com.poemfoot.w3w.W3wProvider; +import com.poemfoot.w3w.dto.W3wCoordinatesResponse; +import com.poemfoot.w3w.dto.W3wWordsResponse; +import com.poemfoot.w3w.exception.server.W3wOverRequestException; +import com.what3words.javawrapper.What3WordsV3; +import com.what3words.javawrapper.response.ConvertTo3WA; +import com.what3words.javawrapper.response.ConvertToCoordinates; +import com.what3words.javawrapper.response.Coordinates; +import com.what3words.javawrapper.response.Square; +import java.util.Locale; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +public class MockW3wProviderImpl implements W3wProvider { + + private final What3WordsV3 w3wApi; + + @Override + public W3wWordsResponse getWords(double latitude, double longitude, Locale locale) { + ConvertTo3WA convertTo3WA = new ConvertTo3WA("KR", + new Square(37.543149,127.081497,37.543122,127.081463), + "서울특별시", + new Coordinates(37.543136,127.08148), + "보일러.소녀.국물", + "ko", + "https://w3w.co/%EB%B3%B4%EC%9D%BC%EB%9F%AC.%EC%86%8C%EB%85%80.%EA%B5%AD%EB%AC%BC"); + + return W3wWordsResponse.of(convertTo3WA); + } + + @Override + public W3wCoordinatesResponse getCoordinates(String word1, String word2, String word3) { + ConvertToCoordinates convertToCoordinates = new ConvertToCoordinates("KR", + new Square(37.543149,127.081497,37.543122,127.081463), + "서울특별시", + new Coordinates(37.543136,127.08148), + "보일러.소녀.국물", + "ko", + "https://w3w.co/%EB%B3%B4%EC%9D%BC%EB%9F%AC.%EC%86%8C%EB%85%80.%EA%B5%AD%EB%AC%BC"); + + return W3wCoordinatesResponse.of(convertToCoordinates); + } + + @Override + public boolean validateW3WRequest() { + if (totalRequestCount.get() >= MAX_TOTAL_REQUEST_COUNT) { + throw new W3wOverRequestException(); + } + return true; + } +} diff --git a/subprojects/w3w/src/main/java/com/poemfoot/w3w/impl/W3wProviderImpl.java b/subprojects/w3w/src/main/java/com/poemfoot/w3w/impl/W3wProviderImpl.java index a7cb7b6..b8af515 100644 --- a/subprojects/w3w/src/main/java/com/poemfoot/w3w/impl/W3wProviderImpl.java +++ b/subprojects/w3w/src/main/java/com/poemfoot/w3w/impl/W3wProviderImpl.java @@ -13,9 +13,7 @@ import com.what3words.javawrapper.response.ConvertToCoordinates; import java.util.Locale; import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Component; -@Component @RequiredArgsConstructor public class W3wProviderImpl implements W3wProvider {