diff --git a/smarketing-ai/deployment/Jenkinsfile b/smarketing-ai/deployment/Jenkinsfile index e55f855..912d946 100644 --- a/smarketing-ai/deployment/Jenkinsfile +++ b/smarketing-ai/deployment/Jenkinsfile @@ -35,24 +35,24 @@ podTemplate( echo "Team ID: ${props.teamid}" } - stage("Check Changes") { - script { - def changes = sh( - script: "git diff --name-only HEAD~1 HEAD", - returnStdout: true - ).trim() - - echo "Changed files: ${changes}" - - if (!changes.contains("smarketing-ai/")) { - echo "No changes in smarketing-ai, skipping build" - currentBuild.result = 'SUCCESS' - error("Stopping pipeline - no changes detected") - } - - echo "Changes detected in smarketing-ai, proceeding with build" - } - } +// stage("Check Changes") { +// script { +// def changes = sh( +// script: "git diff --name-only HEAD~1 HEAD", +// returnStdout: true +// ).trim() +// +// echo "Changed files: ${changes}" +// +// if (!changes.contains("smarketing-ai/")) { +// echo "No changes in smarketing-ai, skipping build" +// currentBuild.result = 'SUCCESS' +// error("Stopping pipeline - no changes detected") +// } +// +// echo "Changes detected in smarketing-ai, proceeding with build" +// } +// } stage("Setup AKS") { container('azure-cli') { diff --git a/smarketing-ai/services/sns_content_service.py b/smarketing-ai/services/sns_content_service.py index 16fd8ba..ac8bc77 100644 --- a/smarketing-ai/services/sns_content_service.py +++ b/smarketing-ai/services/sns_content_service.py @@ -1380,7 +1380,7 @@ class SnsContentService: 'call_to_action': ['방문', '예약', '문의', '공감', '이웃추가'], 'image_placement_strategy': [ '매장 외관 → 인테리어 → 메뉴판 → 음식 → 분위기', - '텍스트 2-3문장마다 이미지 배치', + ##'텍스트 2-3문장마다 이미지 배치', '이미지 설명은 간결하고 매력적으로', '마지막에 대표 이미지로 마무리' ] @@ -1713,6 +1713,11 @@ class SnsContentService: 5. 줄바꿈을 활용하여 가독성 향상 6. 해시태그는 본문과 자연스럽게 연결되도록 배치 +**이미지 태그 사용법:** +- [IMAGE_1]: 첫 번째 이미지 배치 위치 +- [IMAGE_2]: 두 번째 이미지 배치 위치 +- 각 이미지 태그 다음 줄에 이미지 설명 문구 작성 + **필수 요구사항:** {request.requirement} or '고객의 관심을 끌고 방문을 유도하는 매력적인 게시물' @@ -1777,21 +1782,14 @@ class SnsContentService: 1. 검색자의 궁금증을 해결하는 정보 중심 작성 2. 구체적인 가격, 위치, 운영시간 등 실용 정보 포함 3. 개인적인 경험과 솔직한 후기 작성 -4. 각 섹션마다 적절한 위치에 [IMAGE_X] 태그로 이미지 배치 위치 표시 -5. 이미지마다 간단한 설명 문구 추가 -6. 지역 정보와 접근성 정보 포함 - -**이미지 태그 사용법:** -- [IMAGE_1]: 첫 번째 이미지 배치 위치 -- [IMAGE_2]: 두 번째 이미지 배치 위치 -- 각 이미지 태그 다음 줄에 이미지 설명 문구 작성 +4. 이미지마다 간단한 설명 문구 추가 +5. 지역 정보와 접근성 정보 포함 **필수 요구사항:** {request.requirement} or '유용한 정보를 제공하여 방문을 유도하는 신뢰성 있는 후기' 네이버 검색에서 상위 노출되고, 실제로 도움이 되는 정보를 제공하는 블로그 포스트를 작성해주세요. 필수 요구사항을 반드시 참고하여 작성해주세요. -이미지 배치 위치를 [IMAGE_X] 태그로 명확히 표시해주세요. """ return prompt diff --git a/smarketing-java/common/src/main/java/com/won/smarketing/common/config/SecurityConfig.java b/smarketing-java/common/src/main/java/com/won/smarketing/common/config/SecurityConfig.java index 89f1436..dcc1f20 100644 --- a/smarketing-java/common/src/main/java/com/won/smarketing/common/config/SecurityConfig.java +++ b/smarketing-java/common/src/main/java/com/won/smarketing/common/config/SecurityConfig.java @@ -43,7 +43,11 @@ public class SecurityConfig { .cors(cors -> cors.configurationSource(corsConfigurationSource())) .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) .authorizeHttpRequests(auth -> auth - .anyRequest().permitAll() + .requestMatchers("/api/auth/**", "/api/member/register", "/api/member/check-duplicate/**", + "/api/member/validate-password", "/swagger-ui/**", "/v3/api-docs/**", + "/swagger-resources/**", "/webjars/**", "/actuator/**", "/health/**", "/error" + ).permitAll() + .anyRequest().authenticated() ) .addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class); diff --git a/smarketing-java/deployment/Jenkinsfile b/smarketing-java/deployment/Jenkinsfile index a84cf56..26ced99 100644 --- a/smarketing-java/deployment/Jenkinsfile +++ b/smarketing-java/deployment/Jenkinsfile @@ -43,22 +43,22 @@ podTemplate( echo "Image Org: ${props.image_org}" } - stage("Check Changes") { - script { - def changes = sh( - script: "git diff --name-only HEAD~1 HEAD", - returnStdout: true - ).trim() - - if (!changes.contains("smarketing-java/")) { - echo "No changes in smarketing-java, skipping build" - currentBuild.result = 'SUCCESS' - error("Stopping pipeline - no changes detected") - } - - echo "Changes detected in smarketing-java, proceeding with build" - } - } +// stage("Check Changes") { +// script { +// def changes = sh( +// script: "git diff --name-only HEAD~1 HEAD", +// returnStdout: true +// ).trim() +// +// if (!changes.contains("smarketing-java/")) { +// echo "No changes in smarketing-java, skipping build" +// currentBuild.result = 'SUCCESS' +// error("Stopping pipeline - no changes detected") +// } +// +// echo "Changes detected in smarketing-java, proceeding with build" +// } +// } stage("Setup AKS") { container('azure-cli') { diff --git a/smarketing-java/deployment/deploy.yaml.template b/smarketing-java/deployment/deploy.yaml.template index 2a2defd..04836c2 100644 --- a/smarketing-java/deployment/deploy.yaml.template +++ b/smarketing-java/deployment/deploy.yaml.template @@ -182,29 +182,6 @@ spec: name: common-secret - secretRef: name: member-secret - startupProbe: - tcpSocket: - port: 8081 - initialDelaySeconds: 30 - periodSeconds: 10 - timeoutSeconds: 5 - failureThreshold: 10 - livenessProbe: - httpGet: - path: /actuator/health - port: 8081 - initialDelaySeconds: 120 - periodSeconds: 30 - timeoutSeconds: 10 - failureThreshold: 3 - readinessProbe: - httpGet: - path: /actuator/health - port: 8081 - initialDelaySeconds: 60 - periodSeconds: 10 - timeoutSeconds: 5 - failureThreshold: 3 --- apiVersion: apps/v1 @@ -248,29 +225,7 @@ spec: name: common-secret - secretRef: name: store-secret - startupProbe: - tcpSocket: - port: 8082 - initialDelaySeconds: 30 - periodSeconds: 10 - timeoutSeconds: 5 - failureThreshold: 10 - livenessProbe: - httpGet: - path: /actuator/health - port: 8082 - initialDelaySeconds: 120 - periodSeconds: 30 - timeoutSeconds: 10 - failureThreshold: 3 - readinessProbe: - httpGet: - path: /actuator/health - port: 8082 - initialDelaySeconds: 60 - periodSeconds: 10 - timeoutSeconds: 5 - failureThreshold: 3 + --- apiVersion: apps/v1 @@ -314,29 +269,7 @@ spec: name: common-secret - secretRef: name: marketing-content-secret - startupProbe: - tcpSocket: - port: 8083 - initialDelaySeconds: 30 - periodSeconds: 10 - timeoutSeconds: 5 - failureThreshold: 10 - livenessProbe: - httpGet: - path: /actuator/health - port: 8083 - initialDelaySeconds: 120 - periodSeconds: 30 - timeoutSeconds: 10 - failureThreshold: 3 - readinessProbe: - httpGet: - path: /actuator/health - port: 8083 - initialDelaySeconds: 60 - periodSeconds: 10 - timeoutSeconds: 5 - failureThreshold: 3 + --- apiVersion: apps/v1 @@ -380,29 +313,7 @@ spec: name: common-secret - secretRef: name: ai-recommend-secret - startupProbe: - tcpSocket: - port: 8084 - initialDelaySeconds: 30 - periodSeconds: 10 - timeoutSeconds: 5 - failureThreshold: 10 - livenessProbe: - httpGet: - path: /actuator/health - port: 8084 - initialDelaySeconds: 120 - periodSeconds: 30 - timeoutSeconds: 10 - failureThreshold: 3 - readinessProbe: - httpGet: - path: /actuator/health - port: 8084 - initialDelaySeconds: 60 - periodSeconds: 10 - timeoutSeconds: 5 - failureThreshold: 3 + --- # Services @@ -462,84 +373,44 @@ spec: type: ClusterIP --- -# deploy.yaml.template의 Ingress 부분 - 완전한 설정 apiVersion: networking.k8s.io/v1 kind: Ingress metadata: - name: smarketing-backend - namespace: ${namespace} + name: smarketing-ingress annotations: kubernetes.io/ingress.class: nginx - nginx.ingress.kubernetes.io/rewrite-target: /$2 - nginx.ingress.kubernetes.io/ssl-redirect: "false" - nginx.ingress.kubernetes.io/use-regex: "true" + # nginx.ingress.kubernetes.io/rewrite-target: /$2 # 이 줄 제거 + # nginx.ingress.kubernetes.io/use-regex: "true" # 이 줄 제거 spec: - ingressClassName: nginx rules: - host: smarketing.20.249.184.228.nip.io http: paths: - # Member 서비스 - 인증 관련 - - path: /api/auth(/|$)(.*) - pathType: ImplementationSpecific + - path: /api/auth + pathType: Prefix backend: service: - name: member + name: auth-service port: number: 80 - # Member 서비스 - 회원 관리 (누락된 경로!) - - path: /api/member(/|$)(.*) - pathType: ImplementationSpecific + - path: /api/store + pathType: Prefix backend: service: - name: member + name: store-service port: number: 80 - # Store 서비스 - - path: /api/store(/|$)(.*) - pathType: ImplementationSpecific + - path: /api/content + pathType: Prefix backend: service: - name: store + name: content-service port: number: 80 - # Store 서비스 - 매출 관련 - - path: /api/sales(/|$)(.*) - pathType: ImplementationSpecific + - path: /api/recommend + pathType: Prefix backend: service: - name: store + name: recommend-service port: - number: 80 - # Store 서비스 - 메뉴 관련 - - path: /api/menu(/|$)(.*) - pathType: ImplementationSpecific - backend: - service: - name: store - port: - number: 80 - # Store 서비스 - 이미지 업로드 - - path: /api/images(/|$)(.*) - pathType: ImplementationSpecific - backend: - service: - name: store - port: - number: 80 - # Marketing Content 서비스 - - path: /api/content(/|$)(.*) - pathType: ImplementationSpecific - backend: - service: - name: marketing-content - port: - number: 80 - # AI Recommend 서비스 - - path: /api/recommend(/|$)(.*) - pathType: ImplementationSpecific - backend: - service: - name: ai-recommend - port: - number: 80 + number: 80 \ No newline at end of file diff --git a/smarketing-java/deployment/deploy_env_vars b/smarketing-java/deployment/deploy_env_vars index 7a5d327..6cfb19e 100644 --- a/smarketing-java/deployment/deploy_env_vars +++ b/smarketing-java/deployment/deploy_env_vars @@ -9,7 +9,7 @@ image_org=smarketing # Application Settings replicas=1 -allowed_origins=http://20.249.171.38 +allowed_origins=http://20.249.154.194 # Security Settings jwt_secret_key=8O2HQ13etL2BWZvYOiWsJ5uWFoLi6NBUG8divYVoCgtHVvlk3dqRksMl16toztDUeBTSIuOOPvHIrYq11G2BwQ diff --git a/smarketing-java/marketing-content/src/main/java/com/won/smarketing/content/application/service/PosterContentService.java b/smarketing-java/marketing-content/src/main/java/com/won/smarketing/content/application/service/PosterContentService.java index 944f98a..043a8b2 100644 --- a/smarketing-java/marketing-content/src/main/java/com/won/smarketing/content/application/service/PosterContentService.java +++ b/smarketing-java/marketing-content/src/main/java/com/won/smarketing/content/application/service/PosterContentService.java @@ -84,7 +84,7 @@ public class PosterContentService implements PosterContentUseCase { // 콘텐츠 엔티티 생성 Content content = Content.builder() .contentType(ContentType.POSTER) - .platform(Platform.GENERAL) + .platform(Platform.POSTER) .title(request.getTitle()) .content(request.getContent()) .images(request.getImages()) diff --git a/smarketing-java/marketing-content/src/main/java/com/won/smarketing/content/application/service/SnsContentService.java b/smarketing-java/marketing-content/src/main/java/com/won/smarketing/content/application/service/SnsContentService.java index 233bd5d..2aa51d0 100644 --- a/smarketing-java/marketing-content/src/main/java/com/won/smarketing/content/application/service/SnsContentService.java +++ b/smarketing-java/marketing-content/src/main/java/com/won/smarketing/content/application/service/SnsContentService.java @@ -14,6 +14,7 @@ import com.won.smarketing.content.presentation.dto.SnsContentCreateRequest; import com.won.smarketing.content.presentation.dto.SnsContentCreateResponse; import com.won.smarketing.content.presentation.dto.SnsContentSaveRequest; import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; @@ -34,6 +35,9 @@ public class SnsContentService implements SnsContentUseCase { private final AiContentGenerator aiContentGenerator; private final BlobStorageService blobStorageService; + @Value("${azure.storage.container.poster-images:content-images}") + private String contentImageContainer; + /** * SNS 콘텐츠 생성 * @@ -44,8 +48,10 @@ public class SnsContentService implements SnsContentUseCase { @Transactional public SnsContentCreateResponse generateSnsContent(SnsContentCreateRequest request, List files) { //파일들 주소 가져옴 - List urls = blobStorageService.uploadImage(files, "containerName"); - request.setImages(urls); + if(files != null) { + List urls = blobStorageService.uploadImage(files, contentImageContainer); + request.setImages(urls); + } // AI를 사용하여 SNS 콘텐츠 생성 String content = aiContentGenerator.generateSnsContent(request); @@ -67,8 +73,6 @@ public class SnsContentService implements SnsContentUseCase { CreationConditions conditions = CreationConditions.builder() .category(request.getCategory()) .requirement(request.getRequirement()) - //.toneAndManner(request.getToneAndManner()) - //.emotionIntensity(request.getEmotionIntensity()) .eventName(request.getEventName()) .startDate(request.getStartDate()) .endDate(request.getEndDate()) @@ -76,7 +80,6 @@ public class SnsContentService implements SnsContentUseCase { // 콘텐츠 엔티티 생성 및 저장 Content content = Content.builder() -// .contentType(ContentType.SNS_POST) .platform(Platform.fromString(request.getPlatform())) .title(request.getTitle()) .content(request.getContent()) diff --git a/smarketing-java/marketing-content/src/main/java/com/won/smarketing/content/domain/model/Platform.java b/smarketing-java/marketing-content/src/main/java/com/won/smarketing/content/domain/model/Platform.java index 66e266c..aea9446 100644 --- a/smarketing-java/marketing-content/src/main/java/com/won/smarketing/content/domain/model/Platform.java +++ b/smarketing-java/marketing-content/src/main/java/com/won/smarketing/content/domain/model/Platform.java @@ -17,7 +17,7 @@ public enum Platform { FACEBOOK("페이스북"), KAKAO_STORY("카카오스토리"), YOUTUBE("유튜브"), - GENERAL("일반"); + POSTER("포스터"); private final String displayName; diff --git a/smarketing-java/marketing-content/src/main/java/com/won/smarketing/content/presentation/controller/ContentController.java b/smarketing-java/marketing-content/src/main/java/com/won/smarketing/content/presentation/controller/ContentController.java index ab7afa1..bb4bfc6 100644 --- a/smarketing-java/marketing-content/src/main/java/com/won/smarketing/content/presentation/controller/ContentController.java +++ b/smarketing-java/marketing-content/src/main/java/com/won/smarketing/content/presentation/controller/ContentController.java @@ -46,7 +46,7 @@ public class ContentController { @Operation(summary = "SNS 게시물 생성", description = "AI를 활용하여 SNS 게시물을 생성합니다.") @PostMapping(path = "/sns/generate", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) public ResponseEntity> generateSnsContent(@Valid @RequestPart("request") String requestJson, - @Valid @RequestPart("files") List images) throws JsonProcessingException { + @Valid @RequestPart(name = "files", required = false) List images) throws JsonProcessingException { SnsContentCreateRequest request = objectMapper.readValue(requestJson, SnsContentCreateRequest.class); SnsContentCreateResponse response = snsContentUseCase.generateSnsContent(request, images); return ResponseEntity.ok(ApiResponse.success(response, "SNS 콘텐츠가 성공적으로 생성되었습니다."));