diff --git a/backend/docker-compose.yml b/backend/docker-compose.yml new file mode 100644 index 0000000..40e2d51 --- /dev/null +++ b/backend/docker-compose.yml @@ -0,0 +1,10 @@ +#version: "3.8" + +services: + k6: + build: + context: ./k6 + dockerfile: Dockerfile + container_name: k6-test + volumes: + - ./k6:/app diff --git a/backend/k6/Dockerfile b/backend/k6/Dockerfile new file mode 100644 index 0000000..2ab263c --- /dev/null +++ b/backend/k6/Dockerfile @@ -0,0 +1,8 @@ +# ./k6/Dockerfile +FROM grafana/k6:latest + +WORKDIR /app + +COPY ./script.js . + +ENTRYPOINT ["k6", "run", "script.js"] diff --git a/backend/k6/script.js b/backend/k6/script.js new file mode 100644 index 0000000..8acd9fa --- /dev/null +++ b/backend/k6/script.js @@ -0,0 +1,43 @@ +import http from 'k6/http'; +import { sleep, check } from 'k6'; + +// ✅ init 단계에서 미리 파일 열기 (전역 스코프) +const file1 = open('/app/test1.png', 'b'); +const file2 = open('/app/test2.png', 'b'); +const file3 = open('/app/test3.png', 'b'); + +// 파일 배열 +const imageFiles = [ + { name: 'test1.png', content: file1 }, + { name: 'test2.png', content: file2 }, + { name: 'test3.png', content: file3 }, +]; + +// 테스트 옵션 +export let options = { + vus: 100, + duration: '10s', +}; + +export default function () { + // 랜덤 이미지 선택 + const randomIndex = Math.floor(Math.random() * imageFiles.length); + const image = imageFiles[randomIndex]; + + const data = { + postId: '5', + 'images[0]': http.file(file1, 'test1.png'), + 'images[1]': http.file(file2, 'test2.png'), + 'images[2]': http.file(file3, 'test3.png'), + }; + + + + const res = http.patch('http://host.docker.internal:8080/api/images/post/update', data); + + check(res, { + '✅ 상태 코드 200': (r) => r.status === 200, + }); + + sleep(1); +} diff --git a/backend/src/main/java/com/example/booktree/global/config/RedisConfig.java b/backend/src/main/java/com/example/booktree/global/config/RedisConfig.java index 97f9e40..fd7ecc1 100644 --- a/backend/src/main/java/com/example/booktree/global/config/RedisConfig.java +++ b/backend/src/main/java/com/example/booktree/global/config/RedisConfig.java @@ -20,23 +20,23 @@ public class RedisConfig { @Value("${spring.data.redis.password:}") // password가 비어있을 수도 있으니까 기본값은 빈 문자열로 private String redisPassword; - @Bean - public RedisConnectionFactory redisConnectionFactory() { - LettuceConnectionFactory factory = new LettuceConnectionFactory(redisHost, redisPort); - if (!redisPassword.isBlank()) { - factory.setPassword(redisPassword); - } - return factory; - } - // @Bean // public RedisConnectionFactory redisConnectionFactory() { -// return new LettuceConnectionFactory(); // localhost:6379 기본 설정 -// -// // return new LettuceConnectionFactory("127.0.0.1", 6379); -> 커스터마이징 -// +// LettuceConnectionFactory factory = new LettuceConnectionFactory(redisHost, redisPort); +// if (!redisPassword.isBlank()) { +// factory.setPassword(redisPassword); +// } +// return factory; // } + @Bean + public RedisConnectionFactory redisConnectionFactory() { + return new LettuceConnectionFactory(); // localhost:6379 기본 설정 + + // return new LettuceConnectionFactory("127.0.0.1", 6379); -> 커스터마이징 + + } + @Bean public StringRedisTemplate redisTemplate(RedisConnectionFactory connectionFactory) { return new StringRedisTemplate(connectionFactory); diff --git a/backend/src/main/java/com/example/booktree/global/config/SecurityConfigBookTree.java b/backend/src/main/java/com/example/booktree/global/config/SecurityConfigBookTree.java index 6777bdc..5b9f299 100644 --- a/backend/src/main/java/com/example/booktree/global/config/SecurityConfigBookTree.java +++ b/backend/src/main/java/com/example/booktree/global/config/SecurityConfigBookTree.java @@ -44,7 +44,8 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti "/h2-console/**", "/api/users", "/api/v1/users/find/**", - "/api/v1/users/get/profile/**" + "/api/v1/users/get/profile/**", + "/api/images/**" ).permitAll() //무중단 배포 추가, 이메일 추가 diff --git a/backend/src/main/java/com/example/booktree/global/image/service/ImageService.java b/backend/src/main/java/com/example/booktree/global/image/service/ImageService.java index 07ad614..17b30a6 100644 --- a/backend/src/main/java/com/example/booktree/global/image/service/ImageService.java +++ b/backend/src/main/java/com/example/booktree/global/image/service/ImageService.java @@ -15,11 +15,13 @@ import java.util.List; import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; @Service @RequiredArgsConstructor +@Slf4j public class ImageService { private final ImageRepository imageRepository; @@ -87,6 +89,7 @@ public List uploadPostImage(Long postId, List multipartFil List postImageList = post.getImageList(); + //이미지 객체에서 Url만 추출 List imageUrlList = new ArrayList<>(); for (Image image : postImageList) { diff --git a/backend/src/main/java/com/example/booktree/global/utils/S3Uploader.java b/backend/src/main/java/com/example/booktree/global/utils/S3Uploader.java index d3a1905..2a1eb08 100644 --- a/backend/src/main/java/com/example/booktree/global/utils/S3Uploader.java +++ b/backend/src/main/java/com/example/booktree/global/utils/S3Uploader.java @@ -119,7 +119,7 @@ public List autoImagesUploadAndDelete(List beforePostImages, Lis .map(MultipartFile.class::cast) .findFirst() .orElse(null); - //System.out.println("!! name : " + upload.getOriginalFilename()); + System.out.println("!! name : " + upload.getOriginalFilename()); try { uploadFile(upload); } catch (IOException e) {