From 470384d29d7abf6602df175f1f828ff11013db7a Mon Sep 17 00:00:00 2001 From: jihyun Date: Mon, 4 Aug 2025 02:31:54 +0900 Subject: [PATCH 1/2] =?UTF-8?q?=20[=20feat=20]=205=20:=20k6=20=EB=B6=80?= =?UTF-8?q?=ED=95=98=20=ED=85=8C=EC=8A=A4=ED=8A=B8=EB=A5=BC=20=EC=9C=84?= =?UTF-8?q?=ED=95=9C=20=EB=8F=84=EC=BB=A4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/docker-compose.yml | 8 ++++++ backend/k6/Dockerfile | 8 ++++++ backend/k6/script.js | 12 +++++++++ .../booktree/global/config/RedisConfig.java | 26 +++++++++---------- 4 files changed, 41 insertions(+), 13 deletions(-) create mode 100644 backend/docker-compose.yml create mode 100644 backend/k6/Dockerfile create mode 100644 backend/k6/script.js diff --git a/backend/docker-compose.yml b/backend/docker-compose.yml new file mode 100644 index 0000000..7be53d7 --- /dev/null +++ b/backend/docker-compose.yml @@ -0,0 +1,8 @@ +#version: "3.8" + +services: + k6: + build: + context: ./k6 + dockerfile: Dockerfile + container_name: k6-test 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..4837422 --- /dev/null +++ b/backend/k6/script.js @@ -0,0 +1,12 @@ +import http from 'k6/http'; +import { sleep } from 'k6'; + +export let options = { + vus: 10, // virtual users + duration: '30s', +}; + +export default function () { + http.get('http://host.docker.internal:8080/api/test'); + 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); From 10767425426945590396e4d2c4f2f1390c2c6321 Mon Sep 17 00:00:00 2001 From: jihyun Date: Mon, 4 Aug 2025 03:03:43 +0900 Subject: [PATCH 2/2] =?UTF-8?q?[=20feat=20]=205:=20=EB=B6=80=ED=95=98=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=EB=A5=BC=20=EC=9C=84=ED=95=9C=20k6?= =?UTF-8?q?=20=EC=84=A4=EC=A0=95=20=EC=B6=94=EA=B0=80=20=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/docker-compose.yml | 2 + backend/k6/script.js | 39 +++++++++++++++++-- .../global/config/SecurityConfigBookTree.java | 3 +- .../global/image/service/ImageService.java | 3 ++ .../booktree/global/utils/S3Uploader.java | 2 +- 5 files changed, 43 insertions(+), 6 deletions(-) diff --git a/backend/docker-compose.yml b/backend/docker-compose.yml index 7be53d7..40e2d51 100644 --- a/backend/docker-compose.yml +++ b/backend/docker-compose.yml @@ -6,3 +6,5 @@ services: context: ./k6 dockerfile: Dockerfile container_name: k6-test + volumes: + - ./k6:/app diff --git a/backend/k6/script.js b/backend/k6/script.js index 4837422..8acd9fa 100644 --- a/backend/k6/script.js +++ b/backend/k6/script.js @@ -1,12 +1,43 @@ import http from 'k6/http'; -import { sleep } from 'k6'; +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: 10, // virtual users - duration: '30s', + vus: 100, + duration: '10s', }; export default function () { - http.get('http://host.docker.internal:8080/api/test'); + // 랜덤 이미지 선택 + 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/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) {