diff --git a/.gradle/8.4/checksums/checksums.lock b/.gradle/8.4/checksums/checksums.lock index 74cdcb2..4aaf664 100644 Binary files a/.gradle/8.4/checksums/checksums.lock and b/.gradle/8.4/checksums/checksums.lock differ diff --git a/.gradle/8.4/dependencies-accessors/dependencies-accessors.lock b/.gradle/8.4/dependencies-accessors/dependencies-accessors.lock index 02115a0..53f1883 100644 Binary files a/.gradle/8.4/dependencies-accessors/dependencies-accessors.lock and b/.gradle/8.4/dependencies-accessors/dependencies-accessors.lock differ diff --git a/.gradle/8.4/executionHistory/executionHistory.bin b/.gradle/8.4/executionHistory/executionHistory.bin index f3a17f4..ef25cfa 100644 Binary files a/.gradle/8.4/executionHistory/executionHistory.bin and b/.gradle/8.4/executionHistory/executionHistory.bin differ diff --git a/.gradle/8.4/executionHistory/executionHistory.lock b/.gradle/8.4/executionHistory/executionHistory.lock index 51ac47b..f0bed89 100644 Binary files a/.gradle/8.4/executionHistory/executionHistory.lock and b/.gradle/8.4/executionHistory/executionHistory.lock differ diff --git a/.gradle/8.4/fileHashes/fileHashes.bin b/.gradle/8.4/fileHashes/fileHashes.bin index e753038..f23353c 100644 Binary files a/.gradle/8.4/fileHashes/fileHashes.bin and b/.gradle/8.4/fileHashes/fileHashes.bin differ diff --git a/.gradle/8.4/fileHashes/fileHashes.lock b/.gradle/8.4/fileHashes/fileHashes.lock index df11c93..e6ad2d4 100644 Binary files a/.gradle/8.4/fileHashes/fileHashes.lock and b/.gradle/8.4/fileHashes/fileHashes.lock differ diff --git a/.gradle/8.4/fileHashes/resourceHashesCache.bin b/.gradle/8.4/fileHashes/resourceHashesCache.bin index 07b1379..21c1601 100644 Binary files a/.gradle/8.4/fileHashes/resourceHashesCache.bin and b/.gradle/8.4/fileHashes/resourceHashesCache.bin differ diff --git a/.gradle/buildOutputCleanup/buildOutputCleanup.lock b/.gradle/buildOutputCleanup/buildOutputCleanup.lock index 57f942d..7ef4ede 100644 Binary files a/.gradle/buildOutputCleanup/buildOutputCleanup.lock and b/.gradle/buildOutputCleanup/buildOutputCleanup.lock differ diff --git a/.gradle/buildOutputCleanup/outputFiles.bin b/.gradle/buildOutputCleanup/outputFiles.bin index bd4c6f2..c3a1415 100644 Binary files a/.gradle/buildOutputCleanup/outputFiles.bin and b/.gradle/buildOutputCleanup/outputFiles.bin differ diff --git a/.gradle/file-system.probe b/.gradle/file-system.probe index 54b8891..8966ed7 100644 Binary files a/.gradle/file-system.probe and b/.gradle/file-system.probe differ diff --git a/build.gradle b/build.gradle index d112b81..696ab65 100644 --- a/build.gradle +++ b/build.gradle @@ -51,7 +51,7 @@ configure(subprojects.findAll { !it.name.endsWith('-biz') && it.name != 'common' runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.11.5' runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.11.5' // Swagger - implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.3.0' + implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.7.0' } } diff --git a/common/build/classes/java/main/com/unicorn/lifesub/common/aop/LoggingAspect.class b/common/build/classes/java/main/com/unicorn/lifesub/common/aop/LoggingAspect.class index fdcf1bc..b5dc8e8 100644 Binary files a/common/build/classes/java/main/com/unicorn/lifesub/common/aop/LoggingAspect.class and b/common/build/classes/java/main/com/unicorn/lifesub/common/aop/LoggingAspect.class differ diff --git a/common/build/classes/java/main/com/unicorn/lifesub/common/config/JpaConfig.class b/common/build/classes/java/main/com/unicorn/lifesub/common/config/JpaConfig.class new file mode 100644 index 0000000..3e4a525 Binary files /dev/null and b/common/build/classes/java/main/com/unicorn/lifesub/common/config/JpaConfig.class differ diff --git a/common/build/classes/java/main/com/unicorn/lifesub/common/exception/ErrorCode.class b/common/build/classes/java/main/com/unicorn/lifesub/common/exception/ErrorCode.class index e9c4184..9602700 100644 Binary files a/common/build/classes/java/main/com/unicorn/lifesub/common/exception/ErrorCode.class and b/common/build/classes/java/main/com/unicorn/lifesub/common/exception/ErrorCode.class differ diff --git a/common/build/libs/common-1.0.0-plain.jar b/common/build/libs/common-1.0.0-plain.jar index 4e1fb1f..1b5f1f2 100644 Binary files a/common/build/libs/common-1.0.0-plain.jar and b/common/build/libs/common-1.0.0-plain.jar differ diff --git a/common/build/tmp/compileJava/previous-compilation-data.bin b/common/build/tmp/compileJava/previous-compilation-data.bin index e17ebe0..e7f40be 100644 Binary files a/common/build/tmp/compileJava/previous-compilation-data.bin and b/common/build/tmp/compileJava/previous-compilation-data.bin differ diff --git a/common/src/main/java/com/unicorn/lifesub/common/aop/LoggingAspect.java b/common/src/main/java/com/unicorn/lifesub/common/aop/LoggingAspect.java index 77098fa..dcdf28e 100644 --- a/common/src/main/java/com/unicorn/lifesub/common/aop/LoggingAspect.java +++ b/common/src/main/java/com/unicorn/lifesub/common/aop/LoggingAspect.java @@ -16,7 +16,9 @@ import java.util.Map; public class LoggingAspect { private final Gson gson = new Gson(); - @Pointcut("execution(* com.unicorn..*.*(..))") + //로깅 대상 패키지 지정. swagger관련 패키지는 제외함 + @Pointcut("execution(* com.unicorn..*.*(..)) && " + + "!execution(* org.springdoc..*.*(..))") private void loggingPointcut() {} @Before("loggingPointcut()") diff --git a/common/src/main/java/com/unicorn/lifesub/common/config/JpaConfig.java b/common/src/main/java/com/unicorn/lifesub/common/config/JpaConfig.java new file mode 100644 index 0000000..efbf7a8 --- /dev/null +++ b/common/src/main/java/com/unicorn/lifesub/common/config/JpaConfig.java @@ -0,0 +1,9 @@ +package com.unicorn.lifesub.common.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.data.jpa.repository.config.EnableJpaAuditing; + +@Configuration +@EnableJpaAuditing +public class JpaConfig { +} \ No newline at end of file diff --git a/common/src/main/java/com/unicorn/lifesub/common/exception/ErrorCode.java b/common/src/main/java/com/unicorn/lifesub/common/exception/ErrorCode.java index 2893107..48068a2 100644 --- a/common/src/main/java/com/unicorn/lifesub/common/exception/ErrorCode.java +++ b/common/src/main/java/com/unicorn/lifesub/common/exception/ErrorCode.java @@ -7,23 +7,24 @@ import lombok.RequiredArgsConstructor; @RequiredArgsConstructor public enum ErrorCode { // Common - INVALID_INPUT_VALUE(400, "Invalid input value"), - INTERNAL_SERVER_ERROR(500, "Internal server error"), + INVALID_INPUT_VALUE(100, "Invalid input value"), + INTERNAL_SERVER_ERROR(110, "Internal server error"), // Member - MEMBER_NOT_FOUND(404, "Member not found"), - INVALID_CREDENTIALS(401, "Invalid credentials"), - TOKEN_EXPIRED(401, "Token expired"), - SIGNATURE_VERIFICATION_EXCEPTION(20, "서명 검증 실패"), - ALGORITHM_MISMATCH_EXCEPTION(30, "알고리즘 불일치"), - INVALID_CLAIM_EXCEPTION(40, "유효하지 않은 클레임"), + MEMBER_NOT_FOUND(200, "Member not found"), + INVALID_CREDENTIALS(210, "Invalid credentials"), + TOKEN_EXPIRED(220, "Token expired"), + SIGNATURE_VERIFICATION_EXCEPTION(230, "서명 검증 실패"), + ALGORITHM_MISMATCH_EXCEPTION(240, "알고리즘 불일치"), + INVALID_CLAIM_EXCEPTION(250, "유효하지 않은 클레임"), // Subscription - SUBSCRIPTION_NOT_FOUND(404, "Subscription not found"), - ALREADY_SUBSCRIBED(400, "Already subscribed to this service"), + SUBSCRIPTION_NOT_FOUND(300, "Subscription not found"), + ALREADY_SUBSCRIBED(310, "Already subscribed to this service"), // Recommend - NO_SPENDING_DATA(404, "No spending data found"), + NO_SPENDING_DATA(400, "No spending data found"), + NO_RECOMMENDATION_DATA(410, "추천 구독 카테고리 없음"), // UnDefined UNDIFINED_ERROR(0, "정의되지 않은 에러"); diff --git a/member/build/classes/java/main/com/unicorn/lifesub/member/MemberApplication.class b/member/build/classes/java/main/com/unicorn/lifesub/member/MemberApplication.class index 075032a..379483c 100644 Binary files a/member/build/classes/java/main/com/unicorn/lifesub/member/MemberApplication.class and b/member/build/classes/java/main/com/unicorn/lifesub/member/MemberApplication.class differ diff --git a/member/build/classes/java/main/com/unicorn/lifesub/member/config/InitialDataLoader.class b/member/build/classes/java/main/com/unicorn/lifesub/member/config/InitialDataLoader.class index fe9d619..231b63a 100644 Binary files a/member/build/classes/java/main/com/unicorn/lifesub/member/config/InitialDataLoader.class and b/member/build/classes/java/main/com/unicorn/lifesub/member/config/InitialDataLoader.class differ diff --git a/member/build/classes/java/main/com/unicorn/lifesub/member/config/SecurityConfig.class b/member/build/classes/java/main/com/unicorn/lifesub/member/config/SecurityConfig.class index a77f430..8e7e97b 100644 Binary files a/member/build/classes/java/main/com/unicorn/lifesub/member/config/SecurityConfig.class and b/member/build/classes/java/main/com/unicorn/lifesub/member/config/SecurityConfig.class differ diff --git a/member/build/classes/java/main/com/unicorn/lifesub/member/config/SwaggerConfig.class b/member/build/classes/java/main/com/unicorn/lifesub/member/config/SwaggerConfig.class index 7360ce7..baa5b20 100644 Binary files a/member/build/classes/java/main/com/unicorn/lifesub/member/config/SwaggerConfig.class and b/member/build/classes/java/main/com/unicorn/lifesub/member/config/SwaggerConfig.class differ diff --git a/member/build/resources/main/application.yml b/member/build/resources/main/application.yml index e4d13de..ac97018 100644 --- a/member/build/resources/main/application.yml +++ b/member/build/resources/main/application.yml @@ -25,13 +25,11 @@ jwt: access-token-validity: ${JWT_ACCESS_TOKEN_VALIDITY:3600000} refresh-token-validity: ${JWT_REFRESH_TOKEN_VALIDITY:86400000} -allowedorigins: ${ALLOWED_ORIGINS:*} +allowed-origins: ${ALLOWED_ORIGINS:*} springdoc: swagger-ui: path: /swagger-ui.html - api-docs: - path: /api-docs logging: level: diff --git a/member/build/tmp/compileJava/previous-compilation-data.bin b/member/build/tmp/compileJava/previous-compilation-data.bin index 197d9fa..780e0a6 100644 Binary files a/member/build/tmp/compileJava/previous-compilation-data.bin and b/member/build/tmp/compileJava/previous-compilation-data.bin differ diff --git a/member/src/main/java/com/unicorn/lifesub/member/MemberApplication.java b/member/src/main/java/com/unicorn/lifesub/member/MemberApplication.java index 636f06b..f0904df 100644 --- a/member/src/main/java/com/unicorn/lifesub/member/MemberApplication.java +++ b/member/src/main/java/com/unicorn/lifesub/member/MemberApplication.java @@ -2,10 +2,16 @@ package com.unicorn.lifesub.member; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.data.jpa.repository.config.EnableJpaAuditing; -@SpringBootApplication +@SpringBootApplication( + scanBasePackages = { + "com.unicorn.lifesub.member", + "com.unicorn.lifesub.common" + } +) public class MemberApplication { public static void main(String[] args) { SpringApplication.run(MemberApplication.class, args); } -} +} \ No newline at end of file diff --git a/member/src/main/java/com/unicorn/lifesub/member/config/InitialDataLoader.java b/member/src/main/java/com/unicorn/lifesub/member/config/DataLoader.java similarity index 90% rename from member/src/main/java/com/unicorn/lifesub/member/config/InitialDataLoader.java rename to member/src/main/java/com/unicorn/lifesub/member/config/DataLoader.java index 70319a0..e439d61 100644 --- a/member/src/main/java/com/unicorn/lifesub/member/config/InitialDataLoader.java +++ b/member/src/main/java/com/unicorn/lifesub/member/config/DataLoader.java @@ -1,4 +1,4 @@ -// File: lifesub/member/src/main/java/com/unicorn/lifesub/member/config/InitialDataLoader.java +// File: lifesub/member/src/main/java/com/unicorn/lifesub/member/config/DataLoader.java package com.unicorn.lifesub.member.config; import com.unicorn.lifesub.member.repository.entity.MemberEntity; @@ -15,7 +15,7 @@ import java.util.stream.IntStream; @Component @RequiredArgsConstructor -public class InitialDataLoader implements CommandLineRunner { +public class DataLoader implements CommandLineRunner { private final MemberRepository memberRepository; private final PasswordEncoder passwordEncoder; @@ -26,7 +26,7 @@ public class InitialDataLoader implements CommandLineRunner { if (memberRepository.count() == 0) { Set userRoles = new HashSet<>(); userRoles.add("USER"); - String encodedPassword = passwordEncoder.encode("P@ssw0rd$"); + String encodedPassword = passwordEncoder.encode("Passw0rd"); IntStream.rangeClosed(1, 10).forEach(i -> { String userId = String.format("user%02d", i); diff --git a/member/src/main/java/com/unicorn/lifesub/member/config/SecurityConfig.java b/member/src/main/java/com/unicorn/lifesub/member/config/SecurityConfig.java index 849673c..ce6da0d 100644 --- a/member/src/main/java/com/unicorn/lifesub/member/config/SecurityConfig.java +++ b/member/src/main/java/com/unicorn/lifesub/member/config/SecurityConfig.java @@ -31,7 +31,7 @@ public class SecurityConfig { private final JwtTokenProvider jwtTokenProvider; private final CustomUserDetailsService customUserDetailsService; - @Value("${allowedorigins}") + @Value("${allowed-origins}") private String allowedOrigins; public SecurityConfig(JwtTokenProvider jwtTokenProvider, CustomUserDetailsService customUserDetailsService) { diff --git a/member/src/main/java/com/unicorn/lifesub/member/config/SwaggerConfig.java b/member/src/main/java/com/unicorn/lifesub/member/config/SwaggerConfig.java index 87b7b8a..23689f4 100644 --- a/member/src/main/java/com/unicorn/lifesub/member/config/SwaggerConfig.java +++ b/member/src/main/java/com/unicorn/lifesub/member/config/SwaggerConfig.java @@ -1,6 +1,7 @@ package com.unicorn.lifesub.member.config; import io.swagger.v3.oas.annotations.enums.SecuritySchemeType; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; import io.swagger.v3.oas.annotations.security.SecurityScheme; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.info.Info; diff --git a/member/src/main/resources/application.yml b/member/src/main/resources/application.yml index e4d13de..ac97018 100644 --- a/member/src/main/resources/application.yml +++ b/member/src/main/resources/application.yml @@ -25,13 +25,11 @@ jwt: access-token-validity: ${JWT_ACCESS_TOKEN_VALIDITY:3600000} refresh-token-validity: ${JWT_REFRESH_TOKEN_VALIDITY:86400000} -allowedorigins: ${ALLOWED_ORIGINS:*} +allowed-origins: ${ALLOWED_ORIGINS:*} springdoc: swagger-ui: path: /swagger-ui.html - api-docs: - path: /api-docs logging: level: diff --git a/mysub-biz/build/classes/java/main/com/unicorn/lifesub/mysub/biz/service/FeeLevel.class b/mysub-biz/build/classes/java/main/com/unicorn/lifesub/mysub/biz/service/FeeLevel.class new file mode 100644 index 0000000..13a6664 Binary files /dev/null and b/mysub-biz/build/classes/java/main/com/unicorn/lifesub/mysub/biz/service/FeeLevel.class differ diff --git a/mysub-biz/build/classes/java/main/com/unicorn/lifesub/mysub/biz/service/MySubscriptionService.class b/mysub-biz/build/classes/java/main/com/unicorn/lifesub/mysub/biz/service/MySubscriptionService.class index a6e7e19..6123599 100644 Binary files a/mysub-biz/build/classes/java/main/com/unicorn/lifesub/mysub/biz/service/MySubscriptionService.class and b/mysub-biz/build/classes/java/main/com/unicorn/lifesub/mysub/biz/service/MySubscriptionService.class differ diff --git a/mysub-biz/build/libs/mysub-biz-1.0.0-plain.jar b/mysub-biz/build/libs/mysub-biz-1.0.0-plain.jar index 50f38fd..ed646de 100644 Binary files a/mysub-biz/build/libs/mysub-biz-1.0.0-plain.jar and b/mysub-biz/build/libs/mysub-biz-1.0.0-plain.jar differ diff --git a/mysub-biz/build/tmp/compileJava/compileTransaction/stash-dir/MySubscriptionService.class.uniqueId0 b/mysub-biz/build/tmp/compileJava/compileTransaction/stash-dir/MySubscriptionService.class.uniqueId0 new file mode 100644 index 0000000..399fd64 Binary files /dev/null and b/mysub-biz/build/tmp/compileJava/compileTransaction/stash-dir/MySubscriptionService.class.uniqueId0 differ diff --git a/mysub-biz/build/tmp/compileJava/previous-compilation-data.bin b/mysub-biz/build/tmp/compileJava/previous-compilation-data.bin index d6768e3..2de2a91 100644 Binary files a/mysub-biz/build/tmp/compileJava/previous-compilation-data.bin and b/mysub-biz/build/tmp/compileJava/previous-compilation-data.bin differ diff --git a/mysub-biz/src/main/java/com/unicorn/lifesub/mysub/biz/service/FeeLevel.java b/mysub-biz/src/main/java/com/unicorn/lifesub/mysub/biz/service/FeeLevel.java new file mode 100644 index 0000000..39520ee --- /dev/null +++ b/mysub-biz/src/main/java/com/unicorn/lifesub/mysub/biz/service/FeeLevel.java @@ -0,0 +1,15 @@ +package com.unicorn.lifesub.mysub.biz.service; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public enum FeeLevel { + + LIKFER("liker"), + COLLECTOR("collector"), + ADDICT("addict"); + + private final String feeLevel; +} diff --git a/mysub-biz/src/main/java/com/unicorn/lifesub/mysub/biz/service/MySubscriptionService.java b/mysub-biz/src/main/java/com/unicorn/lifesub/mysub/biz/service/MySubscriptionService.java index 329a384..4b5ef2e 100644 --- a/mysub-biz/src/main/java/com/unicorn/lifesub/mysub/biz/service/MySubscriptionService.java +++ b/mysub-biz/src/main/java/com/unicorn/lifesub/mysub/biz/service/MySubscriptionService.java @@ -1,11 +1,13 @@ package com.unicorn.lifesub.mysub.biz.service; +import com.unicorn.lifesub.mysub.biz.domain.Category; import com.unicorn.lifesub.mysub.biz.domain.MySubscription; -import com.unicorn.lifesub.mysub.biz.dto.MySubResponse; -import com.unicorn.lifesub.mysub.biz.dto.TotalFeeResponse; -import com.unicorn.lifesub.mysub.biz.usecase.in.MySubscriptionsUseCase; -import com.unicorn.lifesub.mysub.biz.usecase.in.TotalFeeUseCase; -import com.unicorn.lifesub.mysub.biz.usecase.out.MySubscriptionReader; +import com.unicorn.lifesub.mysub.biz.domain.Subscription; +import com.unicorn.lifesub.mysub.biz.dto.*; +import com.unicorn.lifesub.mysub.biz.usecase.in.*; +import com.unicorn.lifesub.mysub.biz.usecase.out.*; +import com.unicorn.lifesub.common.exception.BusinessException; +import com.unicorn.lifesub.common.exception.ErrorCode; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -15,8 +17,17 @@ import java.util.stream.Collectors; @Service @RequiredArgsConstructor -public class MySubscriptionService implements TotalFeeUseCase, MySubscriptionsUseCase { +public class MySubscriptionService implements + TotalFeeUseCase, + MySubscriptionsUseCase, + SubscriptionDetailUseCase, + SubscribeUseCase, + CancelSubscriptionUseCase, + CategoryUseCase { + private final MySubscriptionReader mySubscriptionReader; + private final MySubscriptionWriter mySubscriptionWriter; + private final SubscriptionReader subscriptionReader; @Override @Transactional(readOnly = true) @@ -43,9 +54,66 @@ public class MySubscriptionService implements TotalFeeUseCase, MySubscriptionsUs .collect(Collectors.toList()); } - private String calculateFeeLevel(long totalFee) { - if (totalFee < 100000) return "구독을 좋아하는 사람"; - if (totalFee < 200000) return "구독 수집자"; - return "구독 사치왕"; + @Override + @Transactional(readOnly = true) + public SubDetailResponse getSubscriptionDetail(Long subscriptionId) { + Subscription subscription = subscriptionReader.findById(subscriptionId) + .orElseThrow(() -> new BusinessException(ErrorCode.SUBSCRIPTION_NOT_FOUND)); + + return SubDetailResponse.builder() + .serviceName(subscription.getName()) + .logoUrl(subscription.getLogoUrl()) + .category(subscription.getCategory()) + .description(subscription.getDescription()) + .price(subscription.getPrice()) + .maxSharedUsers(subscription.getMaxSharedUsers()) + .build(); } -} + + @Override + @Transactional + public void subscribe(Long subscriptionId, String userId) { + // 구독 서비스 존재 확인 + subscriptionReader.findById(subscriptionId) + .orElseThrow(() -> new BusinessException(ErrorCode.SUBSCRIPTION_NOT_FOUND)); + + mySubscriptionWriter.save(userId, subscriptionId); + } + + @Override + @Transactional + public void cancel(Long subscriptionId) { + mySubscriptionWriter.delete(subscriptionId); + } + + @Override + @Transactional(readOnly = true) + public List getAllCategories() { + return subscriptionReader.findAllCategories().stream() + .map(category -> CategoryResponse.builder() + .categoryId(category.getCategoryId()) + .categoryName(category.getName()) + .build()) + .collect(Collectors.toList()); + } + + @Override + @Transactional(readOnly = true) + public List getServicesByCategory(String categoryId) { + return subscriptionReader.findByCategory(categoryId).stream() + .map(subscription -> ServiceListResponse.builder() + .serviceId(subscription.getId().toString()) + .serviceName(subscription.getName()) + .description(subscription.getDescription()) + .price(subscription.getPrice()) + .logoUrl(subscription.getLogoUrl()) + .build()) + .collect(Collectors.toList()); + } + + private String calculateFeeLevel(long totalFee) { + if (totalFee < 100000) return FeeLevel.LIKFER.getFeeLevel(); + if (totalFee < 200000) return FeeLevel.COLLECTOR.getFeeLevel(); + return FeeLevel.ADDICT.getFeeLevel(); + } +} \ No newline at end of file diff --git a/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/MySubApplication.class b/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/MySubApplication.class index 81e01ee..b804a93 100644 Binary files a/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/MySubApplication.class and b/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/MySubApplication.class differ diff --git a/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/adapter/SubscriptionAdapter.class b/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/adapter/SubscriptionAdapter.class deleted file mode 100644 index 8bbff21..0000000 Binary files a/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/adapter/SubscriptionAdapter.class and /dev/null differ diff --git a/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/config/DataLoader.class b/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/config/DataLoader.class new file mode 100644 index 0000000..49359e5 Binary files /dev/null and b/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/config/DataLoader.class differ diff --git a/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/config/SecurityConfig.class b/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/config/SecurityConfig.class index c0f2dc5..4333dc5 100644 Binary files a/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/config/SecurityConfig.class and b/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/config/SecurityConfig.class differ diff --git a/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/config/jwt/JwtTokenProvider.class b/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/config/jwt/JwtTokenProvider.class index 4870a8e..f6970e3 100644 Binary files a/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/config/jwt/JwtTokenProvider.class and b/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/config/jwt/JwtTokenProvider.class differ diff --git a/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/controller/CategoryController.class b/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/controller/CategoryController.class index d8e4cad..67dcabb 100644 Binary files a/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/controller/CategoryController.class and b/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/controller/CategoryController.class differ diff --git a/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/controller/MySubController.class b/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/controller/MySubController.class index 65787b1..6f6c125 100644 Binary files a/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/controller/MySubController.class and b/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/controller/MySubController.class differ diff --git a/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/controller/ServiceController.class b/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/controller/ServiceController.class index a4beaeb..27ffbdb 100644 Binary files a/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/controller/ServiceController.class and b/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/controller/ServiceController.class differ diff --git a/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/adapter/MySubscriptionAdapter.class b/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/gateway/MySubscriptionGateway.class similarity index 51% rename from mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/adapter/MySubscriptionAdapter.class rename to mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/gateway/MySubscriptionGateway.class index 11327b0..be8c4c6 100644 Binary files a/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/adapter/MySubscriptionAdapter.class and b/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/gateway/MySubscriptionGateway.class differ diff --git a/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/gateway/SubscriptionGateway.class b/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/gateway/SubscriptionGateway.class new file mode 100644 index 0000000..d7adff7 Binary files /dev/null and b/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/gateway/SubscriptionGateway.class differ diff --git a/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/entity/CategoryEntity$CategoryEntityBuilder.class b/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/gateway/entity/CategoryEntity$CategoryEntityBuilder.class similarity index 68% rename from mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/entity/CategoryEntity$CategoryEntityBuilder.class rename to mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/gateway/entity/CategoryEntity$CategoryEntityBuilder.class index 1edfad0..f40ba9c 100644 Binary files a/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/entity/CategoryEntity$CategoryEntityBuilder.class and b/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/gateway/entity/CategoryEntity$CategoryEntityBuilder.class differ diff --git a/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/entity/CategoryEntity.class b/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/gateway/entity/CategoryEntity.class similarity index 74% rename from mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/entity/CategoryEntity.class rename to mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/gateway/entity/CategoryEntity.class index eff0e93..1e84918 100644 Binary files a/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/entity/CategoryEntity.class and b/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/gateway/entity/CategoryEntity.class differ diff --git a/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/entity/MySubscriptionEntity$MySubscriptionEntityBuilder.class b/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/gateway/entity/MySubscriptionEntity$MySubscriptionEntityBuilder.class similarity index 50% rename from mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/entity/MySubscriptionEntity$MySubscriptionEntityBuilder.class rename to mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/gateway/entity/MySubscriptionEntity$MySubscriptionEntityBuilder.class index 5ba180d..c6aad21 100644 Binary files a/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/entity/MySubscriptionEntity$MySubscriptionEntityBuilder.class and b/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/gateway/entity/MySubscriptionEntity$MySubscriptionEntityBuilder.class differ diff --git a/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/entity/MySubscriptionEntity.class b/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/gateway/entity/MySubscriptionEntity.class similarity index 63% rename from mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/entity/MySubscriptionEntity.class rename to mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/gateway/entity/MySubscriptionEntity.class index f0b20d7..f516792 100644 Binary files a/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/entity/MySubscriptionEntity.class and b/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/gateway/entity/MySubscriptionEntity.class differ diff --git a/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/entity/SubscriptionEntity$SubscriptionEntityBuilder.class b/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/gateway/entity/SubscriptionEntity$SubscriptionEntityBuilder.class similarity index 68% rename from mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/entity/SubscriptionEntity$SubscriptionEntityBuilder.class rename to mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/gateway/entity/SubscriptionEntity$SubscriptionEntityBuilder.class index 9ef9bdd..676874a 100644 Binary files a/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/entity/SubscriptionEntity$SubscriptionEntityBuilder.class and b/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/gateway/entity/SubscriptionEntity$SubscriptionEntityBuilder.class differ diff --git a/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/entity/SubscriptionEntity.class b/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/gateway/entity/SubscriptionEntity.class similarity index 74% rename from mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/entity/SubscriptionEntity.class rename to mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/gateway/entity/SubscriptionEntity.class index daa7aae..4b098fa 100644 Binary files a/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/entity/SubscriptionEntity.class and b/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/gateway/entity/SubscriptionEntity.class differ diff --git a/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/gateway/repository/CategoryJpaRepository.class b/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/gateway/repository/CategoryJpaRepository.class new file mode 100644 index 0000000..4d85a7e Binary files /dev/null and b/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/gateway/repository/CategoryJpaRepository.class differ diff --git a/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/gateway/repository/MySubscriptionJpaRepository.class b/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/gateway/repository/MySubscriptionJpaRepository.class new file mode 100644 index 0000000..3b8713d Binary files /dev/null and b/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/gateway/repository/MySubscriptionJpaRepository.class differ diff --git a/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/gateway/repository/SubscriptionJpaRepository.class b/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/gateway/repository/SubscriptionJpaRepository.class new file mode 100644 index 0000000..15f3e4e Binary files /dev/null and b/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/gateway/repository/SubscriptionJpaRepository.class differ diff --git a/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/repository/CategoryJpaRepository.class b/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/repository/CategoryJpaRepository.class deleted file mode 100644 index 6861a66..0000000 Binary files a/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/repository/CategoryJpaRepository.class and /dev/null differ diff --git a/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/repository/MySubscriptionJpaRepository.class b/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/repository/MySubscriptionJpaRepository.class deleted file mode 100644 index 23fb3fc..0000000 Binary files a/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/repository/MySubscriptionJpaRepository.class and /dev/null differ diff --git a/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/repository/SubscriptionJpaRepository.class b/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/repository/SubscriptionJpaRepository.class deleted file mode 100644 index 7df8b15..0000000 Binary files a/mysub-infra/build/classes/java/main/com/unicorn/lifesub/mysub/infra/repository/SubscriptionJpaRepository.class and /dev/null differ diff --git a/mysub-infra/build/resolvedMainClassName b/mysub-infra/build/resolvedMainClassName new file mode 100644 index 0000000..f6f9e03 --- /dev/null +++ b/mysub-infra/build/resolvedMainClassName @@ -0,0 +1 @@ +com.unicorn.lifesub.mysub.infra.MySubApplication \ No newline at end of file diff --git a/mysub-infra/build/resources/main/application.yml b/mysub-infra/build/resources/main/application.yml index 53222c8..7f58364 100644 --- a/mysub-infra/build/resources/main/application.yml +++ b/mysub-infra/build/resources/main/application.yml @@ -5,22 +5,30 @@ spring: application: name: mysub-service datasource: - url: ${POSTGRES_URL} - username: ${POSTGRES_USER} - password: ${POSTGRES_PASSWORD} + url: jdbc:postgresql://${POSTGRES_HOST:localhost}:${POSTGRES_PORT:5432}/${POSTGRES_DB:mysub} + username: ${POSTGRES_USER:admin} + password: ${POSTGRES_PASSWORD:Passw0rd} driver-class-name: org.postgresql.Driver + # JPA 설정 jpa: hibernate: - ddl-auto: ${JPA_DDL_AUTO:validate} - show-sql: ${JPA_SHOW_SQL:false} + ddl-auto: ${JPA_DDL_AUTO:update} + show-sql: ${JPA_SHOW_SQL:true} properties: hibernate: format_sql: true + dialect: org.hibernate.dialect.PostgreSQLDialect -allowedorigins: ${ALLOWED_ORIGINS:*} +jwt: + secret-key: ${JWT_SECRET_KEY:8O2HQ13etL2BWZvYOiWsJ5uWFoLi6NBUG8divYVoCgtHVvlk3dqRksMl16toztDUeBTSIuOOPvHIrYq11G2BwQ} + +allowed-origins: ${ALLOWED_ORIGINS:*} springdoc: swagger-ui: path: /swagger-ui.html - api-docs: - path: /api-docs \ No newline at end of file + +logging: + level: + com.unicorn: DEBUG + org.hibernate.SQL: TRACE diff --git a/mysub-infra/build/tmp/compileJava/previous-compilation-data.bin b/mysub-infra/build/tmp/compileJava/previous-compilation-data.bin index fba669d..248e39d 100644 Binary files a/mysub-infra/build/tmp/compileJava/previous-compilation-data.bin and b/mysub-infra/build/tmp/compileJava/previous-compilation-data.bin differ diff --git a/mysub-infra/src/main/java/com/unicorn/lifesub/mysub/infra/MySubApplication.java b/mysub-infra/src/main/java/com/unicorn/lifesub/mysub/infra/MySubApplication.java index f2e6486..a665222 100644 --- a/mysub-infra/src/main/java/com/unicorn/lifesub/mysub/infra/MySubApplication.java +++ b/mysub-infra/src/main/java/com/unicorn/lifesub/mysub/infra/MySubApplication.java @@ -2,8 +2,14 @@ package com.unicorn.lifesub.mysub.infra; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.data.jpa.repository.config.EnableJpaAuditing; -@SpringBootApplication +@SpringBootApplication( + scanBasePackages = { + "com.unicorn.lifesub.mysub", + "com.unicorn.lifesub.common" + } +) public class MySubApplication { public static void main(String[] args) { SpringApplication.run(MySubApplication.class, args); diff --git a/mysub-infra/src/main/java/com/unicorn/lifesub/mysub/infra/config/DataLoader.java b/mysub-infra/src/main/java/com/unicorn/lifesub/mysub/infra/config/DataLoader.java new file mode 100644 index 0000000..e91e8e7 --- /dev/null +++ b/mysub-infra/src/main/java/com/unicorn/lifesub/mysub/infra/config/DataLoader.java @@ -0,0 +1,128 @@ +// File: lifesub/mysub-infra/src/main/java/com/unicorn/lifesub/mysub/infra/config/DataLoader.java +package com.unicorn.lifesub.mysub.infra.config; + +import com.unicorn.lifesub.mysub.infra.gateway.entity.CategoryEntity; +import com.unicorn.lifesub.mysub.infra.gateway.entity.SubscriptionEntity; +import com.unicorn.lifesub.mysub.infra.gateway.repository.CategoryJpaRepository; +import com.unicorn.lifesub.mysub.infra.gateway.repository.SubscriptionJpaRepository; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.CommandLineRunner; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +@Slf4j +@Component +@RequiredArgsConstructor +public class DataLoader implements CommandLineRunner { + + private final CategoryJpaRepository categoryRepository; + private final SubscriptionJpaRepository subscriptionRepository; + + @Override + @Transactional + public void run(String... args) { + if (categoryRepository.count() == 0) { + loadCategories(); + } + + if (subscriptionRepository.count() == 0) { + loadSubscriptions(); + } + } + + private void loadCategories() { + log.info("Loading sample categories..."); + + List categories = Arrays.asList( + CategoryEntity.builder() + .categoryId("OTT") + .name("OTT/동영상") + .build(), + CategoryEntity.builder() + .categoryId("MUSIC") + .name("음악") + .build(), + CategoryEntity.builder() + .categoryId("FOOD") + .name("식품") + .build(), + CategoryEntity.builder() + .categoryId("LIFE") + .name("생활") + .build(), + CategoryEntity.builder() + .categoryId("BEAUTY") + .name("뷰티") + .build(), + CategoryEntity.builder() + .categoryId("EDU") + .name("교육") + .build() + ); + + categoryRepository.saveAll(categories); + log.info("Sample categories loaded"); + } + + private void loadSubscriptions() { + log.info("Loading sample subscriptions..."); + + // 카테고리별 서비스 매핑 + Map> subscriptionsByCategory = Map.of( + "OTT", Arrays.asList( + createSubscription("넷플릭스", "전세계 최대 OTT 서비스", "OTT", 17000, 4, "/images/netflix.png"), + createSubscription("티빙", "국내 실시간 방송과 예능/드라마 VOD", "OTT", 13900, 4, "/images/tving.png"), + createSubscription("디즈니플러스", "디즈니, 픽사, 마블, 스타워즈 콘텐츠", "OTT", 9900, 4, "/images/disney.png") + ), + "MUSIC", Arrays.asList( + createSubscription("멜론", "국내 최대 음원 스트리밍", "MUSIC", 10900, 1, "/images/melon.png"), + createSubscription("스포티파이", "전세계 음악 스트리밍", "MUSIC", 10900, 6, "/images/spotify.png"), + createSubscription("유튜브 뮤직", "유튜브 음원 스트리밍", "MUSIC", 8900, 5, "/images/youtube-music.png") + ), + "FOOD", Arrays.asList( + createSubscription("쿠팡이츠", "식품 정기배송", "FOOD", 4900, 1, "/images/coupang-eats.png"), + createSubscription("마켓컬리", "신선식품 새벽배송", "FOOD", 4900, 1, "/images/kurly.png"), + createSubscription("배민", "배달음식 구독", "FOOD", 5900, 1, "/images/baemin.png") + ), + "LIFE", Arrays.asList( + createSubscription("당근", "중고거래 프리미엄", "LIFE", 3900, 1, "/images/karrot.png"), + createSubscription("쿠팡 로켓와우", "무료배송 구독", "LIFE", 4900, 4, "/images/coupang.png"), + createSubscription("밀리의 서재", "전자책 구독", "LIFE", 9900, 1, "/images/millie.png") + ), + "BEAUTY", Arrays.asList( + createSubscription("올리브영", "뷰티 정기구독", "BEAUTY", 15900, 1, "/images/oliveyoung.png"), + createSubscription("시코르", "화장품 구독박스", "BEAUTY", 29900, 1, "/images/chicor.png"), + createSubscription("롭스", "뷰티 멤버십", "BEAUTY", 19900, 1, "/images/lohbs.png") + ), + "EDU", Arrays.asList( + createSubscription("클래스101", "취미/교양 클래스", "EDU", 19900, 1, "/images/class101.png"), + createSubscription("탈잉", "원데이 클래스", "EDU", 29900, 1, "/images/taling.png"), + createSubscription("캐치", "IT 실무 교육", "EDU", 99000, 1, "/images/catch.png") + ) + ); + + // 모든 서비스 저장 + subscriptionsByCategory.values().stream() + .flatMap(List::stream) + .forEach(subscriptionRepository::save); + + log.info("Sample subscriptions loaded"); + } + + private SubscriptionEntity createSubscription(String name, String description, String category, + int price, int maxSharedUsers, String logoUrl) { + return SubscriptionEntity.builder() + .name(name) + .description(description) + .category(category) + .price(price) + .maxSharedUsers(maxSharedUsers) + .logoUrl(logoUrl) + .build(); + } +} diff --git a/mysub-infra/src/main/java/com/unicorn/lifesub/mysub/infra/config/SecurityConfig.java b/mysub-infra/src/main/java/com/unicorn/lifesub/mysub/infra/config/SecurityConfig.java index 13e3286..1c3bd0e 100644 --- a/mysub-infra/src/main/java/com/unicorn/lifesub/mysub/infra/config/SecurityConfig.java +++ b/mysub-infra/src/main/java/com/unicorn/lifesub/mysub/infra/config/SecurityConfig.java @@ -24,7 +24,7 @@ import java.util.List; public class SecurityConfig { protected final JwtTokenProvider jwtTokenProvider; - @Value("${allowedorigins}") + @Value("${allowed-origins}") private String allowedOrigins; public SecurityConfig(JwtTokenProvider jwtTokenProvider) { diff --git a/mysub-infra/src/main/java/com/unicorn/lifesub/mysub/infra/config/jwt/JwtTokenProvider.java b/mysub-infra/src/main/java/com/unicorn/lifesub/mysub/infra/config/jwt/JwtTokenProvider.java index b9b917f..d5468a1 100644 --- a/mysub-infra/src/main/java/com/unicorn/lifesub/mysub/infra/config/jwt/JwtTokenProvider.java +++ b/mysub-infra/src/main/java/com/unicorn/lifesub/mysub/infra/config/jwt/JwtTokenProvider.java @@ -25,7 +25,7 @@ import java.util.stream.Collectors; public class JwtTokenProvider { private final Algorithm algorithm; - public JwtTokenProvider(@Value("${jwt.secret}") String secretKey) { + public JwtTokenProvider(@Value("${jwt.secret-key}") String secretKey) { this.algorithm = Algorithm.HMAC512(secretKey); } diff --git a/mysub-infra/src/main/java/com/unicorn/lifesub/mysub/infra/controller/CategoryController.java b/mysub-infra/src/main/java/com/unicorn/lifesub/mysub/infra/controller/CategoryController.java index e035701..1c72598 100644 --- a/mysub-infra/src/main/java/com/unicorn/lifesub/mysub/infra/controller/CategoryController.java +++ b/mysub-infra/src/main/java/com/unicorn/lifesub/mysub/infra/controller/CategoryController.java @@ -5,6 +5,7 @@ import com.unicorn.lifesub.mysub.biz.dto.CategoryResponse; import com.unicorn.lifesub.mysub.biz.dto.ServiceListResponse; import com.unicorn.lifesub.mysub.biz.usecase.in.CategoryUseCase; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; @@ -17,6 +18,7 @@ import java.util.List; @Tag(name = "구독 카테고리 API", description = "구독 카테고리 관련 API") @RestController +@SecurityRequirement(name = "bearerAuth") //이 어노테이션이 없으면 요청 헤더에 Authorization헤더가 안 생김 @RequestMapping("/api/mysub") @RequiredArgsConstructor public class CategoryController { diff --git a/mysub-infra/src/main/java/com/unicorn/lifesub/mysub/infra/controller/MySubController.java b/mysub-infra/src/main/java/com/unicorn/lifesub/mysub/infra/controller/MySubController.java index e626925..53ac2d2 100644 --- a/mysub-infra/src/main/java/com/unicorn/lifesub/mysub/infra/controller/MySubController.java +++ b/mysub-infra/src/main/java/com/unicorn/lifesub/mysub/infra/controller/MySubController.java @@ -6,6 +6,7 @@ import com.unicorn.lifesub.mysub.biz.dto.TotalFeeResponse; import com.unicorn.lifesub.mysub.biz.usecase.in.MySubscriptionsUseCase; import com.unicorn.lifesub.mysub.biz.usecase.in.TotalFeeUseCase; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; @@ -15,6 +16,7 @@ import java.util.List; @Tag(name = "마이구독 API", description = "마이구독 관련 API") @RestController +@SecurityRequirement(name = "bearerAuth") //이 어노테이션이 없으면 요청 헤더에 Authorization헤더가 안 생김 @RequestMapping("/api/mysub") @RequiredArgsConstructor public class MySubController { diff --git a/mysub-infra/src/main/java/com/unicorn/lifesub/mysub/infra/controller/ServiceController.java b/mysub-infra/src/main/java/com/unicorn/lifesub/mysub/infra/controller/ServiceController.java index 61108f7..859df73 100644 --- a/mysub-infra/src/main/java/com/unicorn/lifesub/mysub/infra/controller/ServiceController.java +++ b/mysub-infra/src/main/java/com/unicorn/lifesub/mysub/infra/controller/ServiceController.java @@ -6,6 +6,7 @@ import com.unicorn.lifesub.mysub.biz.usecase.in.CancelSubscriptionUseCase; import com.unicorn.lifesub.mysub.biz.usecase.in.SubscribeUseCase; import com.unicorn.lifesub.mysub.biz.usecase.in.SubscriptionDetailUseCase; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; @@ -13,6 +14,7 @@ import org.springframework.web.bind.annotation.*; @Tag(name = "구독 서비스 API", description = "구독 서비스 관련 API") @RestController +@SecurityRequirement(name = "bearerAuth") //이 어노테이션이 없으면 요청 헤더에 Authorization헤더가 안 생김 @RequestMapping("/api/mysub/services") @RequiredArgsConstructor public class ServiceController { diff --git a/mysub-infra/src/main/java/com/unicorn/lifesub/mysub/infra/adapter/MySubscriptionAdapter.java b/mysub-infra/src/main/java/com/unicorn/lifesub/mysub/infra/gateway/MySubscriptionGateway.java similarity index 80% rename from mysub-infra/src/main/java/com/unicorn/lifesub/mysub/infra/adapter/MySubscriptionAdapter.java rename to mysub-infra/src/main/java/com/unicorn/lifesub/mysub/infra/gateway/MySubscriptionGateway.java index 9e010e3..76db980 100644 --- a/mysub-infra/src/main/java/com/unicorn/lifesub/mysub/infra/adapter/MySubscriptionAdapter.java +++ b/mysub-infra/src/main/java/com/unicorn/lifesub/mysub/infra/gateway/MySubscriptionGateway.java @@ -1,14 +1,14 @@ -package com.unicorn.lifesub.mysub.infra.adapter; +package com.unicorn.lifesub.mysub.infra.gateway; import com.unicorn.lifesub.common.exception.BusinessException; import com.unicorn.lifesub.common.exception.ErrorCode; import com.unicorn.lifesub.mysub.biz.domain.MySubscription; import com.unicorn.lifesub.mysub.biz.usecase.out.MySubscriptionReader; import com.unicorn.lifesub.mysub.biz.usecase.out.MySubscriptionWriter; -import com.unicorn.lifesub.mysub.infra.entity.MySubscriptionEntity; -import com.unicorn.lifesub.mysub.infra.entity.SubscriptionEntity; -import com.unicorn.lifesub.mysub.infra.repository.MySubscriptionJpaRepository; -import com.unicorn.lifesub.mysub.infra.repository.SubscriptionJpaRepository; +import com.unicorn.lifesub.mysub.infra.gateway.entity.MySubscriptionEntity; +import com.unicorn.lifesub.mysub.infra.gateway.entity.SubscriptionEntity; +import com.unicorn.lifesub.mysub.infra.gateway.repository.MySubscriptionJpaRepository; +import com.unicorn.lifesub.mysub.infra.gateway.repository.SubscriptionJpaRepository; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; @@ -18,7 +18,7 @@ import java.util.stream.Collectors; @Component @RequiredArgsConstructor -public class MySubscriptionAdapter implements MySubscriptionReader, MySubscriptionWriter { +public class MySubscriptionGateway implements MySubscriptionReader, MySubscriptionWriter { private final MySubscriptionJpaRepository mySubscriptionRepository; private final SubscriptionJpaRepository subscriptionRepository; diff --git a/mysub-infra/src/main/java/com/unicorn/lifesub/mysub/infra/adapter/SubscriptionAdapter.java b/mysub-infra/src/main/java/com/unicorn/lifesub/mysub/infra/gateway/SubscriptionGateway.java similarity index 69% rename from mysub-infra/src/main/java/com/unicorn/lifesub/mysub/infra/adapter/SubscriptionAdapter.java rename to mysub-infra/src/main/java/com/unicorn/lifesub/mysub/infra/gateway/SubscriptionGateway.java index e2b2f3e..9266a34 100644 --- a/mysub-infra/src/main/java/com/unicorn/lifesub/mysub/infra/adapter/SubscriptionAdapter.java +++ b/mysub-infra/src/main/java/com/unicorn/lifesub/mysub/infra/gateway/SubscriptionGateway.java @@ -1,14 +1,12 @@ -package com.unicorn.lifesub.mysub.infra.adapter; +package com.unicorn.lifesub.mysub.infra.gateway; -import com.unicorn.lifesub.common.exception.BusinessException; -import com.unicorn.lifesub.common.exception.ErrorCode; import com.unicorn.lifesub.mysub.biz.domain.Subscription; import com.unicorn.lifesub.mysub.biz.domain.Category; import com.unicorn.lifesub.mysub.biz.usecase.out.SubscriptionReader; -import com.unicorn.lifesub.mysub.infra.entity.SubscriptionEntity; -import com.unicorn.lifesub.mysub.infra.entity.CategoryEntity; -import com.unicorn.lifesub.mysub.infra.repository.SubscriptionJpaRepository; -import com.unicorn.lifesub.mysub.infra.repository.CategoryJpaRepository; +import com.unicorn.lifesub.mysub.infra.gateway.entity.SubscriptionEntity; +import com.unicorn.lifesub.mysub.infra.gateway.entity.CategoryEntity; +import com.unicorn.lifesub.mysub.infra.gateway.repository.SubscriptionJpaRepository; +import com.unicorn.lifesub.mysub.infra.gateway.repository.CategoryJpaRepository; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; @@ -18,7 +16,7 @@ import java.util.stream.Collectors; @Component @RequiredArgsConstructor -public class SubscriptionAdapter implements SubscriptionReader { +public class SubscriptionGateway implements SubscriptionReader { private final SubscriptionJpaRepository subscriptionRepository; private final CategoryJpaRepository categoryRepository; diff --git a/mysub-infra/src/main/java/com/unicorn/lifesub/mysub/infra/entity/CategoryEntity.java b/mysub-infra/src/main/java/com/unicorn/lifesub/mysub/infra/gateway/entity/CategoryEntity.java similarity index 88% rename from mysub-infra/src/main/java/com/unicorn/lifesub/mysub/infra/entity/CategoryEntity.java rename to mysub-infra/src/main/java/com/unicorn/lifesub/mysub/infra/gateway/entity/CategoryEntity.java index 59de44e..a7ca116 100644 --- a/mysub-infra/src/main/java/com/unicorn/lifesub/mysub/infra/entity/CategoryEntity.java +++ b/mysub-infra/src/main/java/com/unicorn/lifesub/mysub/infra/gateway/entity/CategoryEntity.java @@ -1,13 +1,13 @@ -package com.unicorn.lifesub.mysub.infra.entity; +package com.unicorn.lifesub.mysub.infra.gateway.entity; import com.unicorn.lifesub.common.entity.BaseTimeEntity; import com.unicorn.lifesub.mysub.biz.domain.Category; import jakarta.persistence.Entity; import jakarta.persistence.Table; +import jakarta.persistence.Id; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; -import org.springframework.data.annotation.Id; @Entity @Table(name = "categories") diff --git a/mysub-infra/src/main/java/com/unicorn/lifesub/mysub/infra/entity/MySubscriptionEntity.java b/mysub-infra/src/main/java/com/unicorn/lifesub/mysub/infra/gateway/entity/MySubscriptionEntity.java similarity index 94% rename from mysub-infra/src/main/java/com/unicorn/lifesub/mysub/infra/entity/MySubscriptionEntity.java rename to mysub-infra/src/main/java/com/unicorn/lifesub/mysub/infra/gateway/entity/MySubscriptionEntity.java index a5b227b..00e0317 100644 --- a/mysub-infra/src/main/java/com/unicorn/lifesub/mysub/infra/entity/MySubscriptionEntity.java +++ b/mysub-infra/src/main/java/com/unicorn/lifesub/mysub/infra/gateway/entity/MySubscriptionEntity.java @@ -1,4 +1,4 @@ -package com.unicorn.lifesub.mysub.infra.entity; +package com.unicorn.lifesub.mysub.infra.gateway.entity; import com.unicorn.lifesub.mysub.biz.domain.MySubscription; import jakarta.persistence.*; diff --git a/mysub-infra/src/main/java/com/unicorn/lifesub/mysub/infra/entity/SubscriptionEntity.java b/mysub-infra/src/main/java/com/unicorn/lifesub/mysub/infra/gateway/entity/SubscriptionEntity.java similarity index 96% rename from mysub-infra/src/main/java/com/unicorn/lifesub/mysub/infra/entity/SubscriptionEntity.java rename to mysub-infra/src/main/java/com/unicorn/lifesub/mysub/infra/gateway/entity/SubscriptionEntity.java index dd21b3a..113a1ae 100644 --- a/mysub-infra/src/main/java/com/unicorn/lifesub/mysub/infra/entity/SubscriptionEntity.java +++ b/mysub-infra/src/main/java/com/unicorn/lifesub/mysub/infra/gateway/entity/SubscriptionEntity.java @@ -1,4 +1,4 @@ -package com.unicorn.lifesub.mysub.infra.entity; +package com.unicorn.lifesub.mysub.infra.gateway.entity; import com.unicorn.lifesub.common.entity.BaseTimeEntity; import com.unicorn.lifesub.mysub.biz.domain.Subscription; diff --git a/mysub-infra/src/main/java/com/unicorn/lifesub/mysub/infra/repository/CategoryJpaRepository.java b/mysub-infra/src/main/java/com/unicorn/lifesub/mysub/infra/gateway/repository/CategoryJpaRepository.java similarity index 54% rename from mysub-infra/src/main/java/com/unicorn/lifesub/mysub/infra/repository/CategoryJpaRepository.java rename to mysub-infra/src/main/java/com/unicorn/lifesub/mysub/infra/gateway/repository/CategoryJpaRepository.java index 655570f..a209e67 100644 --- a/mysub-infra/src/main/java/com/unicorn/lifesub/mysub/infra/repository/CategoryJpaRepository.java +++ b/mysub-infra/src/main/java/com/unicorn/lifesub/mysub/infra/gateway/repository/CategoryJpaRepository.java @@ -1,6 +1,6 @@ -package com.unicorn.lifesub.mysub.infra.repository; +package com.unicorn.lifesub.mysub.infra.gateway.repository; -import com.unicorn.lifesub.mysub.infra.entity.CategoryEntity; +import com.unicorn.lifesub.mysub.infra.gateway.entity.CategoryEntity; import org.springframework.data.jpa.repository.JpaRepository; public interface CategoryJpaRepository extends JpaRepository { diff --git a/mysub-infra/src/main/java/com/unicorn/lifesub/mysub/infra/repository/MySubscriptionJpaRepository.java b/mysub-infra/src/main/java/com/unicorn/lifesub/mysub/infra/gateway/repository/MySubscriptionJpaRepository.java similarity index 64% rename from mysub-infra/src/main/java/com/unicorn/lifesub/mysub/infra/repository/MySubscriptionJpaRepository.java rename to mysub-infra/src/main/java/com/unicorn/lifesub/mysub/infra/gateway/repository/MySubscriptionJpaRepository.java index bb8c9d8..2df4c65 100644 --- a/mysub-infra/src/main/java/com/unicorn/lifesub/mysub/infra/repository/MySubscriptionJpaRepository.java +++ b/mysub-infra/src/main/java/com/unicorn/lifesub/mysub/infra/gateway/repository/MySubscriptionJpaRepository.java @@ -1,6 +1,6 @@ -package com.unicorn.lifesub.mysub.infra.repository; +package com.unicorn.lifesub.mysub.infra.gateway.repository; -import com.unicorn.lifesub.mysub.infra.entity.MySubscriptionEntity; +import com.unicorn.lifesub.mysub.infra.gateway.entity.MySubscriptionEntity; import org.springframework.data.jpa.repository.JpaRepository; import java.util.List; diff --git a/mysub-infra/src/main/java/com/unicorn/lifesub/mysub/infra/repository/SubscriptionJpaRepository.java b/mysub-infra/src/main/java/com/unicorn/lifesub/mysub/infra/gateway/repository/SubscriptionJpaRepository.java similarity index 68% rename from mysub-infra/src/main/java/com/unicorn/lifesub/mysub/infra/repository/SubscriptionJpaRepository.java rename to mysub-infra/src/main/java/com/unicorn/lifesub/mysub/infra/gateway/repository/SubscriptionJpaRepository.java index fd0de3c..45666b5 100644 --- a/mysub-infra/src/main/java/com/unicorn/lifesub/mysub/infra/repository/SubscriptionJpaRepository.java +++ b/mysub-infra/src/main/java/com/unicorn/lifesub/mysub/infra/gateway/repository/SubscriptionJpaRepository.java @@ -1,6 +1,6 @@ -package com.unicorn.lifesub.mysub.infra.repository; +package com.unicorn.lifesub.mysub.infra.gateway.repository; -import com.unicorn.lifesub.mysub.infra.entity.SubscriptionEntity; +import com.unicorn.lifesub.mysub.infra.gateway.entity.SubscriptionEntity; import org.springframework.data.jpa.repository.JpaRepository; import java.util.List; diff --git a/mysub-infra/src/main/resources/application.yml b/mysub-infra/src/main/resources/application.yml index 22a1cb9..7f58364 100644 --- a/mysub-infra/src/main/resources/application.yml +++ b/mysub-infra/src/main/resources/application.yml @@ -9,21 +9,26 @@ spring: username: ${POSTGRES_USER:admin} password: ${POSTGRES_PASSWORD:Passw0rd} driver-class-name: org.postgresql.Driver + # JPA 설정 jpa: hibernate: ddl-auto: ${JPA_DDL_AUTO:update} - show-sql: ${JPA_SHOW_SQL:false} + show-sql: ${JPA_SHOW_SQL:true} properties: hibernate: format_sql: true - -allowedorigins: ${ALLOWED_ORIGINS:*} + dialect: org.hibernate.dialect.PostgreSQLDialect jwt: - secret: ${JWT_SECRET:8O2HQ13etL2BWZvYOiWsJ5uWFoLi6NBUG8divYVoCgtHVvlk3dqRksMl16toztDUeBTSIuOOPvHIrYq11G2BwQ==} + secret-key: ${JWT_SECRET_KEY:8O2HQ13etL2BWZvYOiWsJ5uWFoLi6NBUG8divYVoCgtHVvlk3dqRksMl16toztDUeBTSIuOOPvHIrYq11G2BwQ} + +allowed-origins: ${ALLOWED_ORIGINS:*} springdoc: swagger-ui: path: /swagger-ui.html - api-docs: - path: /api-docs \ No newline at end of file + +logging: + level: + com.unicorn: DEBUG + org.hibernate.SQL: TRACE diff --git a/recommend/build/classes/java/main/com/unicorn/lifesub/recommend/RecommendApplication.class b/recommend/build/classes/java/main/com/unicorn/lifesub/recommend/RecommendApplication.class index 9e6f07c..ed7e555 100644 Binary files a/recommend/build/classes/java/main/com/unicorn/lifesub/recommend/RecommendApplication.class and b/recommend/build/classes/java/main/com/unicorn/lifesub/recommend/RecommendApplication.class differ diff --git a/recommend/build/classes/java/main/com/unicorn/lifesub/recommend/config/DataLoader.class b/recommend/build/classes/java/main/com/unicorn/lifesub/recommend/config/DataLoader.class new file mode 100644 index 0000000..721de6a Binary files /dev/null and b/recommend/build/classes/java/main/com/unicorn/lifesub/recommend/config/DataLoader.class differ diff --git a/recommend/build/classes/java/main/com/unicorn/lifesub/recommend/config/SecurityConfig.class b/recommend/build/classes/java/main/com/unicorn/lifesub/recommend/config/SecurityConfig.class index 1f07e16..a54732a 100644 Binary files a/recommend/build/classes/java/main/com/unicorn/lifesub/recommend/config/SecurityConfig.class and b/recommend/build/classes/java/main/com/unicorn/lifesub/recommend/config/SecurityConfig.class differ diff --git a/recommend/build/classes/java/main/com/unicorn/lifesub/recommend/config/jwt/JwtTokenProvider.class b/recommend/build/classes/java/main/com/unicorn/lifesub/recommend/config/jwt/JwtTokenProvider.class index a47c085..7d9c7ec 100644 Binary files a/recommend/build/classes/java/main/com/unicorn/lifesub/recommend/config/jwt/JwtTokenProvider.class and b/recommend/build/classes/java/main/com/unicorn/lifesub/recommend/config/jwt/JwtTokenProvider.class differ diff --git a/recommend/build/classes/java/main/com/unicorn/lifesub/recommend/controller/RecommendController.class b/recommend/build/classes/java/main/com/unicorn/lifesub/recommend/controller/RecommendController.class index cd9c225..591d5a0 100644 Binary files a/recommend/build/classes/java/main/com/unicorn/lifesub/recommend/controller/RecommendController.class and b/recommend/build/classes/java/main/com/unicorn/lifesub/recommend/controller/RecommendController.class differ diff --git a/recommend/build/classes/java/main/com/unicorn/lifesub/recommend/dto/RecommendCategoryDTO$RecommendCategoryDTOBuilder.class b/recommend/build/classes/java/main/com/unicorn/lifesub/recommend/dto/RecommendCategoryDTO$RecommendCategoryDTOBuilder.class index 83d75f1..8d2d2a4 100644 Binary files a/recommend/build/classes/java/main/com/unicorn/lifesub/recommend/dto/RecommendCategoryDTO$RecommendCategoryDTOBuilder.class and b/recommend/build/classes/java/main/com/unicorn/lifesub/recommend/dto/RecommendCategoryDTO$RecommendCategoryDTOBuilder.class differ diff --git a/recommend/build/classes/java/main/com/unicorn/lifesub/recommend/dto/RecommendCategoryDTO.class b/recommend/build/classes/java/main/com/unicorn/lifesub/recommend/dto/RecommendCategoryDTO.class index 7e6fbc1..53a1b17 100644 Binary files a/recommend/build/classes/java/main/com/unicorn/lifesub/recommend/dto/RecommendCategoryDTO.class and b/recommend/build/classes/java/main/com/unicorn/lifesub/recommend/dto/RecommendCategoryDTO.class differ diff --git a/recommend/build/classes/java/main/com/unicorn/lifesub/recommend/repository/jpa/RecommendRepository.class b/recommend/build/classes/java/main/com/unicorn/lifesub/recommend/repository/jpa/RecommendRepository.class index 2c7316a..252595e 100644 Binary files a/recommend/build/classes/java/main/com/unicorn/lifesub/recommend/repository/jpa/RecommendRepository.class and b/recommend/build/classes/java/main/com/unicorn/lifesub/recommend/repository/jpa/RecommendRepository.class differ diff --git a/recommend/build/classes/java/main/com/unicorn/lifesub/recommend/repository/jpa/SpendingRepository.class b/recommend/build/classes/java/main/com/unicorn/lifesub/recommend/repository/jpa/SpendingRepository.class new file mode 100644 index 0000000..934757e Binary files /dev/null and b/recommend/build/classes/java/main/com/unicorn/lifesub/recommend/repository/jpa/SpendingRepository.class differ diff --git a/recommend/build/classes/java/main/com/unicorn/lifesub/recommend/service/RecommendServiceImpl.class b/recommend/build/classes/java/main/com/unicorn/lifesub/recommend/service/RecommendServiceImpl.class index b97e9ed..8703464 100644 Binary files a/recommend/build/classes/java/main/com/unicorn/lifesub/recommend/service/RecommendServiceImpl.class and b/recommend/build/classes/java/main/com/unicorn/lifesub/recommend/service/RecommendServiceImpl.class differ diff --git a/recommend/build/resolvedMainClassName b/recommend/build/resolvedMainClassName new file mode 100644 index 0000000..5c86a2b --- /dev/null +++ b/recommend/build/resolvedMainClassName @@ -0,0 +1 @@ +com.unicorn.lifesub.recommend.RecommendApplication \ No newline at end of file diff --git a/recommend/build/resources/main/application.yml b/recommend/build/resources/main/application.yml index 9083f84..c93371f 100644 --- a/recommend/build/resources/main/application.yml +++ b/recommend/build/resources/main/application.yml @@ -5,22 +5,31 @@ spring: application: name: recommend-service datasource: - url: ${POSTGRES_URL} - username: ${POSTGRES_USER} - password: ${POSTGRES_PASSWORD} + url: jdbc:postgresql://${POSTGRES_HOST:localhost}:${POSTGRES_PORT:5432}/${POSTGRES_DB:recommend} + username: ${POSTGRES_USER:admin} + password: ${POSTGRES_PASSWORD:Passw0rd} driver-class-name: org.postgresql.Driver + # JPA 설정 jpa: hibernate: - ddl-auto: ${JPA_DDL_AUTO:validate} - show-sql: ${JPA_SHOW_SQL:false} + ddl-auto: ${JPA_DDL_AUTO:update} + show-sql: ${JPA_SHOW_SQL:true} properties: hibernate: format_sql: true + dialect: org.hibernate.dialect.PostgreSQLDialect -allowedorigins: ${ALLOWED_ORIGINS:*} +jwt: + secret-key: ${JWT_SECRET_KEY:8O2HQ13etL2BWZvYOiWsJ5uWFoLi6NBUG8divYVoCgtHVvlk3dqRksMl16toztDUeBTSIuOOPvHIrYq11G2BwQ} + +allowed-origins: ${ALLOWED_ORIGINS:*} springdoc: swagger-ui: path: /swagger-ui.html - api-docs: - path: /api-docs + +logging: + level: + com.unicorn: DEBUG + org.hibernate.SQL: TRACE + diff --git a/recommend/build/tmp/compileJava/previous-compilation-data.bin b/recommend/build/tmp/compileJava/previous-compilation-data.bin index b601dee..f717661 100644 Binary files a/recommend/build/tmp/compileJava/previous-compilation-data.bin and b/recommend/build/tmp/compileJava/previous-compilation-data.bin differ diff --git a/recommend/src/main/java/com/unicorn/lifesub/recommend/RecommendApplication.java b/recommend/src/main/java/com/unicorn/lifesub/recommend/RecommendApplication.java index 58aec01..ed2b38e 100644 --- a/recommend/src/main/java/com/unicorn/lifesub/recommend/RecommendApplication.java +++ b/recommend/src/main/java/com/unicorn/lifesub/recommend/RecommendApplication.java @@ -3,8 +3,12 @@ package com.unicorn.lifesub.recommend; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -@SpringBootApplication - +@SpringBootApplication( + scanBasePackages = { + "com.unicorn.lifesub.recommend", + "com.unicorn.lifesub.common" + } +) public class RecommendApplication { public static void main(String[] args) { SpringApplication.run(RecommendApplication.class, args); diff --git a/recommend/src/main/java/com/unicorn/lifesub/recommend/config/DataLoader.java b/recommend/src/main/java/com/unicorn/lifesub/recommend/config/DataLoader.java new file mode 100644 index 0000000..1ca17e8 --- /dev/null +++ b/recommend/src/main/java/com/unicorn/lifesub/recommend/config/DataLoader.java @@ -0,0 +1,113 @@ +// File: lifesub/recommend/src/main/java/com/unicorn/lifesub/recommend/config/DataLoader.java +package com.unicorn.lifesub.recommend.config; + +import com.unicorn.lifesub.recommend.repository.entity.RecommendedCategoryEntity; +import com.unicorn.lifesub.recommend.repository.entity.SpendingEntity; +import com.unicorn.lifesub.recommend.repository.jpa.RecommendRepository; +import com.unicorn.lifesub.recommend.repository.jpa.SpendingRepository; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.CommandLineRunner; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDate; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Random; + +@Slf4j +@Component +@RequiredArgsConstructor +public class DataLoader implements CommandLineRunner { + + private final RecommendRepository recommendRepository; + private final SpendingRepository spendingRepository; + private final Random random = new Random(); + + private static final List SPENDING_CATEGORIES = Arrays.asList( + "COSMETICS", "ENTERTAINMENT", "EDUCATION", "RESTAURANT", "MUSIC", "DAILY" + ); + + private static final List SUBSCRIPTION_CATEGORIES = Arrays.asList( + "BEAUTY", "OTT", "EDU", "FOOD", "MUSIC", "LIFE" + ); + + @Override // CommandLineRunner의 run 메소드 구현 + @Transactional + public void run(String... args) throws Exception { + log.info("Initializing sample data..."); + initSpendingHistory(); + initRecommendedCategories(); + log.info("Sample data initialization completed."); + } + + private void initSpendingHistory() { + // 기존 데이터 삭제 + spendingRepository.deleteAll(); + + List spendings = new ArrayList<>(); + LocalDate now = LocalDate.now(); + + // user01 ~ user10까지의 지출 데이터 생성 + for (int i = 1; i <= 10; i++) { + String userId = String.format("user%02d", i); + + // 각 사용자별로 지난 한달간 5~10건의 지출 데이터 생성 + int numTransactions = 5 + random.nextInt(6); + + for (int j = 0; j < numTransactions; j++) { + String category = SPENDING_CATEGORIES.get(random.nextInt(SPENDING_CATEGORIES.size())); + long amount = (50 + random.nextInt(451)) * 1000L; // 5만원 ~ 50만원 사이 + int daysAgo = random.nextInt(30); // 최근 30일 이내 + + spendings.add(SpendingEntity.builder() + .userId(userId) + .category(category) + .amount(amount) + .spendingDate(now.minusDays(daysAgo)) + .build()); + } + } + + spendingRepository.saveAll(spendings); + log.info("Spending history data initialized with {} records", spendings.size()); + } + + private void initRecommendedCategories() { + // 기존 데이터 삭제 + recommendRepository.deleteAll(); + + // 지출 카테고리와 추천 구독 카테고리 매핑 데이터 생성 + List categories = Arrays.asList( + RecommendedCategoryEntity.builder() + .spendingCategory("COSMETICS") + .recommendCategory("BEAUTY") + .build(), + RecommendedCategoryEntity.builder() + .spendingCategory("ENTERTAINMENT") + .recommendCategory("OTT") + .build(), + RecommendedCategoryEntity.builder() + .spendingCategory("EDUCATION") + .recommendCategory("EDU") + .build(), + RecommendedCategoryEntity.builder() + .spendingCategory("RESTAURANT") + .recommendCategory("FOOD") + .build(), + RecommendedCategoryEntity.builder() + .spendingCategory("MUSIC") + .recommendCategory("MUSIC") + .build(), + RecommendedCategoryEntity.builder() + .spendingCategory("DAILY") + .recommendCategory("LIFE") + .build() + ); + + recommendRepository.saveAll(categories); + log.info("Recommended categories data initialized with {} records", categories.size()); + } +} \ No newline at end of file diff --git a/recommend/src/main/java/com/unicorn/lifesub/recommend/config/SecurityConfig.java b/recommend/src/main/java/com/unicorn/lifesub/recommend/config/SecurityConfig.java index 4e6975c..bbb87a1 100644 --- a/recommend/src/main/java/com/unicorn/lifesub/recommend/config/SecurityConfig.java +++ b/recommend/src/main/java/com/unicorn/lifesub/recommend/config/SecurityConfig.java @@ -24,7 +24,7 @@ import java.util.List; public class SecurityConfig { protected final JwtTokenProvider jwtTokenProvider; - @Value("${allowedorigins}") + @Value("${allowed-origins}") private String allowedOrigins; public SecurityConfig(JwtTokenProvider jwtTokenProvider) { diff --git a/recommend/src/main/java/com/unicorn/lifesub/recommend/config/jwt/JwtTokenProvider.java b/recommend/src/main/java/com/unicorn/lifesub/recommend/config/jwt/JwtTokenProvider.java index 36ba8f8..011721a 100644 --- a/recommend/src/main/java/com/unicorn/lifesub/recommend/config/jwt/JwtTokenProvider.java +++ b/recommend/src/main/java/com/unicorn/lifesub/recommend/config/jwt/JwtTokenProvider.java @@ -25,7 +25,7 @@ import java.util.stream.Collectors; public class JwtTokenProvider { private final Algorithm algorithm; - public JwtTokenProvider(@Value("${jwt.secret}") String secretKey) { + public JwtTokenProvider(@Value("${jwt.secret-key}") String secretKey) { this.algorithm = Algorithm.HMAC512(secretKey); } diff --git a/recommend/src/main/java/com/unicorn/lifesub/recommend/controller/RecommendController.java b/recommend/src/main/java/com/unicorn/lifesub/recommend/controller/RecommendController.java index 4a1e39d..2fcbf61 100644 --- a/recommend/src/main/java/com/unicorn/lifesub/recommend/controller/RecommendController.java +++ b/recommend/src/main/java/com/unicorn/lifesub/recommend/controller/RecommendController.java @@ -4,6 +4,7 @@ import com.unicorn.lifesub.common.dto.ApiResponse; import com.unicorn.lifesub.recommend.dto.RecommendCategoryDTO; import com.unicorn.lifesub.recommend.service.RecommendService; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; @@ -14,6 +15,7 @@ import org.springframework.web.bind.annotation.RestController; @Tag(name = "구독추천 API", description = "구독추천 관련 API") @RestController +@SecurityRequirement(name = "bearerAuth") //이 어노테이션이 없으면 요청 헤더에 Authorization헤더가 안 생김 @RequestMapping("/api/recommend") @RequiredArgsConstructor public class RecommendController { diff --git a/recommend/src/main/java/com/unicorn/lifesub/recommend/dto/RecommendCategoryDTO.java b/recommend/src/main/java/com/unicorn/lifesub/recommend/dto/RecommendCategoryDTO.java index 820afdf..b4d75ab 100644 --- a/recommend/src/main/java/com/unicorn/lifesub/recommend/dto/RecommendCategoryDTO.java +++ b/recommend/src/main/java/com/unicorn/lifesub/recommend/dto/RecommendCategoryDTO.java @@ -8,6 +8,7 @@ import java.time.LocalDate; @Builder public class RecommendCategoryDTO { private String categoryName; - private String imagePath; private LocalDate baseDate; + private String spendingCategory; + private Long totalSpending; } diff --git a/recommend/src/main/java/com/unicorn/lifesub/recommend/repository/jpa/RecommendRepository.java b/recommend/src/main/java/com/unicorn/lifesub/recommend/repository/jpa/RecommendRepository.java index cc6f31a..ea9a2a8 100644 --- a/recommend/src/main/java/com/unicorn/lifesub/recommend/repository/jpa/RecommendRepository.java +++ b/recommend/src/main/java/com/unicorn/lifesub/recommend/repository/jpa/RecommendRepository.java @@ -1,19 +1,10 @@ package com.unicorn.lifesub.recommend.repository.jpa; import com.unicorn.lifesub.recommend.repository.entity.RecommendedCategoryEntity; -import com.unicorn.lifesub.recommend.repository.entity.SpendingEntity; import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.query.Param; -import java.time.LocalDate; -import java.util.List; import java.util.Optional; public interface RecommendRepository extends JpaRepository { Optional findBySpendingCategory(String category); - - @Query("SELECT s FROM SpendingEntity s WHERE s.userId = :userId AND s.spendingDate >= :startDate") - List findSpendingsByUserIdAndDateAfter(@Param("userId") String userId, - @Param("startDate") LocalDate startDate); -} +} \ No newline at end of file diff --git a/recommend/src/main/java/com/unicorn/lifesub/recommend/repository/jpa/SpendingRepository.java b/recommend/src/main/java/com/unicorn/lifesub/recommend/repository/jpa/SpendingRepository.java new file mode 100644 index 0000000..8d3baa9 --- /dev/null +++ b/recommend/src/main/java/com/unicorn/lifesub/recommend/repository/jpa/SpendingRepository.java @@ -0,0 +1,16 @@ +// File: lifesub/recommend/src/main/java/com/unicorn/lifesub/recommend/repository/jpa/SpendingRepository.java +package com.unicorn.lifesub.recommend.repository.jpa; + +import com.unicorn.lifesub.recommend.repository.entity.SpendingEntity; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +import java.time.LocalDate; +import java.util.List; + +public interface SpendingRepository extends JpaRepository { + @Query("SELECT s FROM SpendingEntity s WHERE s.userId = :userId AND s.spendingDate >= :startDate") + List findSpendingsByUserIdAndDateAfter(@Param("userId") String userId, + @Param("startDate") LocalDate startDate); +} \ No newline at end of file diff --git a/recommend/src/main/java/com/unicorn/lifesub/recommend/service/RecommendServiceImpl.java b/recommend/src/main/java/com/unicorn/lifesub/recommend/service/RecommendServiceImpl.java index 656eb9c..e756118 100644 --- a/recommend/src/main/java/com/unicorn/lifesub/recommend/service/RecommendServiceImpl.java +++ b/recommend/src/main/java/com/unicorn/lifesub/recommend/service/RecommendServiceImpl.java @@ -1,3 +1,4 @@ +// File: lifesub/recommend/src/main/java/com/unicorn/lifesub/recommend/service/RecommendServiceImpl.java package com.unicorn.lifesub.recommend.service; import com.unicorn.lifesub.common.exception.BusinessException; @@ -6,44 +7,50 @@ import com.unicorn.lifesub.recommend.domain.RecommendedCategory; import com.unicorn.lifesub.recommend.domain.SpendingCategory; import com.unicorn.lifesub.recommend.dto.RecommendCategoryDTO; import com.unicorn.lifesub.recommend.repository.jpa.RecommendRepository; +import com.unicorn.lifesub.recommend.repository.jpa.SpendingRepository; +import com.unicorn.lifesub.recommend.repository.entity.SpendingEntity; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.time.LocalDate; +import java.util.List; @Service @RequiredArgsConstructor public class RecommendServiceImpl implements RecommendService { private final RecommendRepository recommendRepository; + private final SpendingRepository spendingRepository; private final SpendingAnalyzer spendingAnalyzer; @Override @Transactional(readOnly = true) public RecommendCategoryDTO getRecommendedCategory(String userId) { LocalDate startDate = LocalDate.now().minusMonths(1); - - SpendingCategory topSpending = spendingAnalyzer.analyzeSpending( - recommendRepository.findSpendingsByUserIdAndDateAfter(userId, startDate) - ); + + List spendings = spendingRepository.findSpendingsByUserIdAndDateAfter(userId, startDate); + + if (spendings.isEmpty()) { + throw new BusinessException(ErrorCode.NO_SPENDING_DATA); + } + + SpendingCategory topSpending = spendingAnalyzer.analyzeSpending(spendings); if (topSpending == null) { throw new BusinessException(ErrorCode.NO_SPENDING_DATA); } RecommendedCategory recommendedCategory = recommendRepository - .findBySpendingCategory(topSpending.getCategory()) - .orElseThrow(() -> new BusinessException(ErrorCode.NO_SPENDING_DATA)) - .toDomain(); + .findBySpendingCategory(topSpending.getCategory()) + .orElseThrow(() -> new BusinessException(ErrorCode.NO_RECOMMENDATION_DATA)) + .toDomain(); return RecommendCategoryDTO.builder() .categoryName(recommendedCategory.getRecommendCategory()) - .imagePath(getCategoryImagePath(recommendedCategory.getRecommendCategory())) .baseDate(recommendedCategory.getBaseDate()) + .spendingCategory(topSpending.getCategory()) + .totalSpending(topSpending.getTotalAmount()) .build(); } - private String getCategoryImagePath(String category) { - return "/images/categories/" + category.toLowerCase() + ".png"; - } -} +} \ No newline at end of file diff --git a/recommend/src/main/resources/application.yml b/recommend/src/main/resources/application.yml index 0590cbf..c93371f 100644 --- a/recommend/src/main/resources/application.yml +++ b/recommend/src/main/resources/application.yml @@ -9,21 +9,27 @@ spring: username: ${POSTGRES_USER:admin} password: ${POSTGRES_PASSWORD:Passw0rd} driver-class-name: org.postgresql.Driver + # JPA 설정 jpa: hibernate: ddl-auto: ${JPA_DDL_AUTO:update} - show-sql: ${JPA_SHOW_SQL:false} + show-sql: ${JPA_SHOW_SQL:true} properties: hibernate: format_sql: true - -allowedorigins: ${ALLOWED_ORIGINS:*} + dialect: org.hibernate.dialect.PostgreSQLDialect jwt: - secret: ${JWT_SECRET:8O2HQ13etL2BWZvYOiWsJ5uWFoLi6NBUG8divYVoCgtHVvlk3dqRksMl16toztDUeBTSIuOOPvHIrYq11G2BwQ==} + secret-key: ${JWT_SECRET_KEY:8O2HQ13etL2BWZvYOiWsJ5uWFoLi6NBUG8divYVoCgtHVvlk3dqRksMl16toztDUeBTSIuOOPvHIrYq11G2BwQ} + +allowed-origins: ${ALLOWED_ORIGINS:*} springdoc: swagger-ui: path: /swagger-ui.html - api-docs: - path: /api-docs + +logging: + level: + com.unicorn: DEBUG + org.hibernate.SQL: TRACE +