From 0ea288cf8f31efa37a999019616100c568f2d019 Mon Sep 17 00:00:00 2001 From: KimGiHyeon Date: Tue, 17 Mar 2026 16:19:03 +0900 Subject: [PATCH 01/24] =?UTF-8?q?docs:=20README=EC=97=90=20=EB=B0=B1?= =?UTF-8?q?=EC=97=94=EB=93=9C=20=EC=95=84=ED=82=A4=ED=85=8D=EC=B2=98=20?= =?UTF-8?q?=EA=B7=B8=EB=A6=BC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index a2e8471..4e7cc43 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,10 @@ ![React](https://go-skill-icons.vercel.app/api/icons?i=ts,nextjs,zustand,reactquery,tailwind,storybook,pnpm,turborepo,googleanalytics,sentry&perline=5) +### ๐Ÿฅถ Back-end Architecture +knu-matzip excalidraw + + ### ๐Ÿ“ฑ ์ฃผ์š” ๊ธฐ๋Šฅ #### 1. ๋ง›์ง‘ ํƒ์ƒ‰ From 5388090bdfdd93934537189b0f1a124ebd31bc34 Mon Sep 17 00:00:00 2001 From: KimGiHyeon Date: Tue, 17 Mar 2026 18:22:45 +0900 Subject: [PATCH 02/24] docs: Replace back-end architecture image Updated back-end architecture image in README. --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 4e7cc43..822427c 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,8 @@ ### ๐Ÿฅถ Back-end Architecture -knu-matzip excalidraw +knu-matzip excalidraw + ### ๐Ÿ“ฑ ์ฃผ์š” ๊ธฐ๋Šฅ From 73191ed70bb996c5a2b2a7e4141040144c15a218 Mon Sep 17 00:00:00 2001 From: KimGiHyeon Date: Tue, 17 Mar 2026 18:38:08 +0900 Subject: [PATCH 03/24] Update back-end architecture image in README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 822427c..56f6b74 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ ### ๐Ÿฅถ Back-end Architecture -knu-matzip excalidraw +knu-matzip excalidraw From 113438c5dad47e2f29f3d4c2d3457bd2b3adadf2 Mon Sep 17 00:00:00 2001 From: gihhyeon Date: Mon, 23 Mar 2026 20:10:19 +0900 Subject: [PATCH 04/24] =?UTF-8?q?chore:=20=EB=A7=9B=EC=A7=91=20=EC=83=81?= =?UTF-8?q?=EC=84=B8=20=EC=A1=B0=ED=9A=8C=20k6=20=EA=B8=B0=EB=B0=98=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=84=B8=ED=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .dockerignore | 5 + Dockerfile | 12 ++ Dockerfile.loadtest | 14 ++ src/main/resources/application-loadtest.yml | 42 +++++ .../sql/place-detail-loadtest-1000.sql | 106 +++++++++++ ...lace-detail-loadtest-before-async-1000.sql | 171 ++++++++++++++++++ 6 files changed, 350 insertions(+) create mode 100644 .dockerignore create mode 100644 Dockerfile create mode 100644 Dockerfile.loadtest create mode 100644 src/main/resources/application-loadtest.yml create mode 100644 src/test/resources/sql/place-detail-loadtest-1000.sql create mode 100644 src/test/resources/sql/place-detail-loadtest-before-async-1000.sql diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..1d7de19 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,5 @@ +.git +build/ +out/ +.gradle/ +Dockerfile \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..e54dbd9 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,12 @@ +# 1. ๋ฒ ์ด์Šค ์ด๋ฏธ์ง€ ์„ค์ • (JDK ํ™˜๊ฒฝ) +FROM openjdk:17-jdk-slim + +# 2. ์ž‘์—… ๋””๋ ‰ํ† ๋ฆฌ ์„ค์ • +WORKDIR /app + +# 3. ๋นŒ๋“œ๋œ jar ํŒŒ์ผ์„ ์ปจํ…Œ์ด๋„ˆ๋กœ ๋ณต์‚ฌ +# (build/libs/ ์•ˆ์— ์žˆ๋Š” .jar ํŒŒ์ผ์„ app.jar๋กœ ๋ณต์‚ฌ) +COPY build/libs/*.jar app.jar + +# 4. ์•ฑ ์‹คํ–‰ +ENTRYPOINT ["java", "-jar", "app.jar"] \ No newline at end of file diff --git a/Dockerfile.loadtest b/Dockerfile.loadtest new file mode 100644 index 0000000..1b1c621 --- /dev/null +++ b/Dockerfile.loadtest @@ -0,0 +1,14 @@ +FROM gradle:8.10.2-jdk17 AS builder + +WORKDIR /workspace +COPY . . +RUN gradle bootJar --no-daemon + +FROM eclipse-temurin:17-jre-jammy + +WORKDIR /app +COPY --from=builder /workspace/build/libs/*.jar /app/app.jar + +EXPOSE 8080 + +ENTRYPOINT ["java", "-jar", "/app/app.jar"] diff --git a/src/main/resources/application-loadtest.yml b/src/main/resources/application-loadtest.yml new file mode 100644 index 0000000..c540521 --- /dev/null +++ b/src/main/resources/application-loadtest.yml @@ -0,0 +1,42 @@ +spring: + datasource: + url: ${DB_URL:jdbc:mysql://mysql:3306/knu_matzip?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Seoul} + username: ${DB_USERNAME:matzip} + password: ${DB_PASSWORD:dummy-password} + jpa: + hibernate: + ddl-auto: create + properties: + hibernate: + format_sql: false + jdbc.time_zone: Asia/Seoul + +jwt: + secret-key: ${JWT_SECRET_KEY:dummy-jwt-secret} + expiration-time: 3600000 + refresh-expiration-time: 1209600000 + +oauth2: + kakao: + client-id: ${KAKAO_CLIENT_ID:dummy-client-id} + redirect-uri: ${KAKAO_REDIRECT_URI:http://localhost:8080/api/v1/auth/callback} + +app: + auth: + allowed-origins: + - http://localhost:3000 + - http://localhost:8080 + success-path: ${AUTH_SUCCESS_PATH:/login/success} + failure-path: ${AUTH_FAILURE_PATH:/login/failure} + state-secret: ${STATE_SECRET_KEY:dummy-state-secret} + cookie-secure: false + cookie-same-site: Lax + +image: + base-url: ${IMAGE_BASE_URL:http://localhost:8080} + +logging: + level: + root: INFO + org.hibernate.SQL: WARN + org.hibernate.orm.jdbc.bind: WARN diff --git a/src/test/resources/sql/place-detail-loadtest-1000.sql b/src/test/resources/sql/place-detail-loadtest-1000.sql new file mode 100644 index 0000000..a005d6f --- /dev/null +++ b/src/test/resources/sql/place-detail-loadtest-1000.sql @@ -0,0 +1,106 @@ +SET FOREIGN_KEY_CHECKS = 0; + +DELETE FROM daily_view_count; +DELETE FROM photo; +DELETE FROM menu; +DELETE FROM place_category; +DELETE FROM place_tag; +DELETE FROM place; +DELETE FROM category; +DELETE FROM tag; + +SET FOREIGN_KEY_CHECKS = 1; + +select * from place; + + +INSERT INTO category (id, category_name, icon_key, created_at, updated_at) +VALUES + (1, 'ํ•œ์‹', 'korean', NOW(), NOW()), + (2, '์ค‘์‹', 'chinese', NOW(), NOW()), + (3, '์ผ์‹', 'japanese', NOW(), NOW()); + +INSERT INTO tag (id, tag_name, icon_key, created_at, updated_at) +VALUES + (1, '๊ฐ€์„ฑ๋น„', 'value', NOW(), NOW()), + (2, 'ํ˜ผ๋ฐฅ', 'solo', NOW(), NOW()), + (3, '์›จ์ดํŒ…', 'waiting', NOW(), NOW()); + +-- 3. ๋ง›์ง‘ ๋ฐ์ดํ„ฐ 1,000๊ฐœ ์ƒ์„ฑ +INSERT INTO place ( + id, campus, kakao_place_id, place_name, address, + latitude, longitude, description, like_count, + view_count, registered_by, status, created_at, updated_at +) +WITH RECURSIVE seq AS ( + SELECT 1 AS n + UNION ALL + SELECT n + 1 FROM seq WHERE n < 1000 +) +SELECT + n, 'CHEONAN', CONCAT('loadtest-kakao-', LPAD(n, 4, '0')), + CONCAT('๋ถ€ํ•˜ํ…Œ์ŠคํŠธ ๋ง›์ง‘ ', n), CONCAT('์ถฉ๋‚จ ์ฒœ์•ˆ์‹œ ํ…Œ์ŠคํŠธ๋กœ ', n), + 36.800000 + (n * 0.0001), 127.100000 + (n * 0.0001), + CONCAT('k6 ์ƒ์„ธ ์กฐํšŒ ์‘๋‹ต ์†๋„ ์ธก์ •์„ ์œ„ํ•œ ํ…Œ์ŠคํŠธ ๋ฐ์ดํ„ฐ #', n), + MOD(n, 200), MOD(n, 500), NULL, 'APPROVED', NOW(), NOW() +FROM seq; + +-- 4. ๋ง›์ง‘-์นดํ…Œ๊ณ ๋ฆฌ ๋งคํ•‘ (1๊ณณ๋‹น 2๊ฐœ์”ฉ) +INSERT INTO place_category (place_id, category_id, display_order) +WITH RECURSIVE seq AS ( + SELECT 1 AS n + UNION ALL + SELECT n + 1 FROM seq WHERE n < 1000 +) +SELECT * FROM ( + SELECT n AS place_id, 1 + MOD(n - 1, 3) AS category_id, 0 AS display_order FROM seq + UNION ALL + SELECT n AS place_id, 1 + MOD(n, 3) AS category_id, 1 AS display_order FROM seq + ) AS t; + +-- 5. ๋ง›์ง‘-ํƒœ๊ทธ ๋งคํ•‘ (1๊ณณ๋‹น 2๊ฐœ์”ฉ) +INSERT INTO place_tag (place_id, tag_id) +WITH RECURSIVE seq AS ( + SELECT 1 AS n + UNION ALL + SELECT n + 1 FROM seq WHERE n < 1000 +) +SELECT * FROM ( + SELECT n AS place_id, 1 + MOD(n - 1, 3) AS tag_id FROM seq + UNION ALL + SELECT n AS place_id, 1 + MOD(n, 3) AS tag_id FROM seq + ) AS t; + +INSERT INTO photo (place_id, photo_url, display_order, fetched_at, created_at, updated_at) +WITH RECURSIVE seq AS ( + SELECT 1 AS n + UNION ALL + SELECT n + 1 FROM seq WHERE n < 1000 +) +SELECT * FROM ( + SELECT n, CONCAT('https://cdn.example.com/place/', n, '/photo-1.jpg') AS url, 1 AS ord, + NOW() AS f_at, NOW() AS c_at, NOW() AS u_at FROM seq + UNION ALL + SELECT n, CONCAT('https://cdn.example.com/place/', n, '/photo-2.jpg'), 2, NOW(), NOW(), NOW() FROM seq + ) AS t; + +-- 7. ๋ฉ”๋‰ด ๋ฐ์ดํ„ฐ ์ƒ์„ฑ (NOW() ๋ณ„์นญ ์ถ”๊ฐ€๋กœ ์—๋Ÿฌ ํ•ด๊ฒฐ) +INSERT INTO menu (place_id, name, price, is_recommended, created_at, updated_at) +WITH RECURSIVE seq AS ( + SELECT 1 AS n + UNION ALL + SELECT n + 1 FROM seq WHERE n < 1000 +) +SELECT * FROM ( + SELECT n, CONCAT('๋Œ€ํ‘œ๋ฉ”๋‰ด-', n, '-1') AS m_name, 8000 + MOD(n, 5) * 500 AS p, TRUE AS rec, + NOW() AS c_at, NOW() AS u_at FROM seq + UNION ALL + SELECT n, CONCAT('๋Œ€ํ‘œ๋ฉ”๋‰ด-', n, '-2'), 9000 + MOD(n, 7) * 400, FALSE, NOW(), NOW() FROM seq + UNION ALL + SELECT n, CONCAT('๋Œ€ํ‘œ๋ฉ”๋‰ด-', n, '-3'), 10000 + MOD(n, 9) * 300, FALSE, NOW(), NOW() FROM seq + ) AS t; + +-- 8. AUTO_INCREMENT ๊ฐ’ ์กฐ์ • +ALTER TABLE category AUTO_INCREMENT = 4; +ALTER TABLE tag AUTO_INCREMENT = 4; +ALTER TABLE place AUTO_INCREMENT = 1001; diff --git a/src/test/resources/sql/place-detail-loadtest-before-async-1000.sql b/src/test/resources/sql/place-detail-loadtest-before-async-1000.sql new file mode 100644 index 0000000..8718b9f --- /dev/null +++ b/src/test/resources/sql/place-detail-loadtest-before-async-1000.sql @@ -0,0 +1,171 @@ +SET SESSION cte_max_recursion_depth = 2000; +SET FOREIGN_KEY_CHECKS = 0; + +DELETE FROM daily_view_count; +DELETE FROM photo; +DELETE FROM menu; +DELETE FROM place_category; +DELETE FROM place_tag; +DELETE FROM place; +DELETE FROM category; +DELETE FROM tag; + +SET FOREIGN_KEY_CHECKS = 1; + +INSERT INTO category (category_id, category_name, icon_key) +VALUES + (1, 'ํ•œ์‹', 'korean'), + (2, '์ค‘์‹', 'chinese'), + (3, '์ผ์‹', 'japanese'); + +INSERT INTO tag (tag_id, tag_name, icon_key) +VALUES + (1, '๊ฐ€์„ฑ๋น„', 'value'), + (2, 'ํ˜ผ๋ฐฅ', 'solo'), + (3, '์›จ์ดํŒ…', 'waiting'); + +INSERT INTO place ( + place_id, + campus, + kakao_place_id, + place_name, + address, + latitude, + longitude, + description, + like_count, + view_count, + registered_by, + status, + created_at, + updated_at +) +WITH RECURSIVE seq AS ( + SELECT 1 AS n + UNION ALL + SELECT n + 1 FROM seq WHERE n < 1000 +) +SELECT + n, + 'CHEONAN', + CONCAT('before-async-kakao-', LPAD(n, 4, '0')), + CONCAT('๋น„๋™๊ธฐ ๋ถ„๋ฆฌ ์ „ ๋ง›์ง‘ ', n), + CONCAT('์ถฉ๋‚จ ์ฒœ์•ˆ์‹œ ํšŒ๊ท€ํ…Œ์ŠคํŠธ๋กœ ', n), + 36.800000 + (n * 0.0001), + 127.100000 + (n * 0.0001), + CONCAT('๋™๊ธฐ ์กฐํšŒ์ˆ˜ ๊ฐฑ์‹  ๋น„๊ต์šฉ ํ…Œ์ŠคํŠธ ๋ฐ์ดํ„ฐ #', n), + MOD(n, 200), + 100 + MOD(n, 500), + NULL, + 'APPROVED', + NOW(), + NOW() +FROM seq; + +INSERT INTO daily_view_count ( + id, + place_id, + view_date, + count, + created_at, + updated_at +) +WITH RECURSIVE seq AS ( + SELECT 1 AS n + UNION ALL + SELECT n + 1 FROM seq WHERE n < 1000 +) +SELECT + n, + n, + CURRENT_DATE(), + 10 + MOD(n, 300), + NOW(), + NOW() +FROM seq; + +INSERT INTO place_category (place_id, category_id) +WITH RECURSIVE seq AS ( + SELECT 1 AS n + UNION ALL + SELECT n + 1 FROM seq WHERE n < 1000 +) +SELECT n, 1 + MOD(n - 1, 3) FROM seq +UNION ALL +SELECT n, 1 + MOD(n, 3) FROM seq; + +INSERT INTO place_tag (place_id, tag_id) +WITH RECURSIVE seq AS ( + SELECT 1 AS n + UNION ALL + SELECT n + 1 FROM seq WHERE n < 1000 +) +SELECT n, 1 + MOD(n - 1, 3) FROM seq +UNION ALL +SELECT n, 1 + MOD(n, 3) FROM seq; + +INSERT INTO photo ( + place_id, + photo_url, + display_order, + created_at, + fetched_at +) +WITH RECURSIVE seq AS ( + SELECT 1 AS n + UNION ALL + SELECT n + 1 FROM seq WHERE n < 1000 +) +SELECT + n, + CONCAT('https://cdn.example.com/before-async/place/', n, '/photo-1.jpg'), + 1, + NOW(), + NOW() +FROM seq +UNION ALL +SELECT + n, + CONCAT('https://cdn.example.com/before-async/place/', n, '/photo-2.jpg'), + 2, + NOW(), + NOW() +FROM seq; + +INSERT INTO menu ( + place_id, + name, + price, + is_recommended +) +WITH RECURSIVE seq AS ( + SELECT 1 AS n + UNION ALL + SELECT n + 1 FROM seq WHERE n < 1000 +) +SELECT + n, + CONCAT('๋™๊ธฐ๋ฉ”๋‰ด-', n, '-1'), + 8000 + MOD(n, 5) * 500, + TRUE +FROM seq +UNION ALL +SELECT + n, + CONCAT('๋™๊ธฐ๋ฉ”๋‰ด-', n, '-2'), + 9000 + MOD(n, 7) * 400, + FALSE +FROM seq +UNION ALL +SELECT + n, + CONCAT('๋™๊ธฐ๋ฉ”๋‰ด-', n, '-3'), + 10000 + MOD(n, 9) * 300, + FALSE +FROM seq; + +ALTER TABLE category AUTO_INCREMENT = 4; +ALTER TABLE tag AUTO_INCREMENT = 4; +ALTER TABLE place AUTO_INCREMENT = 1001; +ALTER TABLE daily_view_count AUTO_INCREMENT = 1001; + From 572e2d290c9b27e3380a4951262f744934ebbe6e Mon Sep 17 00:00:00 2001 From: KimGiHyeon Date: Fri, 27 Mar 2026 15:02:15 +0900 Subject: [PATCH 05/24] Update project duration to current operation --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 56f6b74..37e5e12 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ ### ๐Ÿ—“๏ธ ๊ธฐ๊ฐ„ -2025.09 ~ 2025.11 +2025.09 ~ ํ˜„์žฌ [์šด์˜ ์ค‘] ### โš™๏ธ ๊ธฐ์ˆ  ์Šคํƒ From e768c5b09d8e7258291576701f6de57b98d202e7 Mon Sep 17 00:00:00 2001 From: gihhyeon Date: Sun, 23 Aug 2026 21:03:33 +0900 Subject: [PATCH 06/24] =?UTF-8?q?refactor:=20DTO=20=EB=84=A4=EC=9D=B4?= =?UTF-8?q?=EB=B0=8D=20=ED=86=B5=EC=9D=BC=20=EB=B0=8F=20=EC=99=80=EC=9D=BC?= =?UTF-8?q?=EB=93=9C=EC=B9=B4=EB=93=9C=20import=20=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/controller/AdminController.java | 20 ++++++------- .../PlaceRegisterRequestReviewRequest.java | 6 ---- .../PlaceRegisterRequestReviewRequestDto.java | 6 ++++ ...laceRegisterRequestDetailResponseDto.java} | 6 ++-- ... => PlaceRegisterRequestsResponseDto.java} | 6 ++-- .../com/matzip/auth/api/AuthController.java | 20 ++++++------- .../com/matzip/auth/api/AuthControllerV2.java | 6 ++-- ...Request.java => KakaoLoginRequestDto.java} | 2 +- ...ginResponse.java => LoginResponseDto.java} | 2 +- ...quest.java => TokenReissueRequestDto.java} | 2 +- ...kenResponse.java => TokenResponseDto.java} | 2 +- .../matzip/auth/application/AuthService.java | 20 ++++++------- .../auth/infra/kakao/KakaoLoginApiClient.java | 12 ++++---- ...sponse.java => KakaoTokenResponseDto.java} | 2 +- ...esponse.java => KakaoUserResponseDto.java} | 2 +- .../controller/LotteryEventController.java | 22 +++++++------- ...Request.java => ApplyEventRequestDto.java} | 2 +- ...sponse.java => ApplyEventResponseDto.java} | 6 ++-- ....java => EventEntryResultResponseDto.java} | 10 +++---- ... => LotteryEventAnonymousResponseDto.java} | 12 ++++---- ...onse.java => LotteryEventResponseDto.java} | 10 +++---- .../controller/response/LotteryEventView.java | 2 +- ...java => ParticipatedEventResponseDto.java} | 10 +++---- .../lottery/service/LotteryEventService.java | 28 ++++++++--------- .../controller/PlaceRequestController.java | 2 +- .../api/response/PlaceDetailResponseDto.java | 6 +++- .../application/service/PlaceLikeService.java | 7 ++++- .../application/service/PlaceReadService.java | 30 ++++++++++++++++--- .../application/service/PlaceService.java | 18 +++++++++-- ...LotteryEventServiceGetEntryResultTest.java | 6 ++-- .../application/PlaceServiceCachingTest.java | 8 ++++- .../place/application/PlaceServiceTest.java | 8 ++++- 32 files changed, 178 insertions(+), 123 deletions(-) delete mode 100644 src/main/java/com/matzip/admin/controller/request/PlaceRegisterRequestReviewRequest.java create mode 100644 src/main/java/com/matzip/admin/controller/request/PlaceRegisterRequestReviewRequestDto.java rename src/main/java/com/matzip/admin/controller/response/{PlaceRegisterRequestDetailResponse.java => PlaceRegisterRequestDetailResponseDto.java} (87%) rename src/main/java/com/matzip/admin/controller/response/{PlaceRegisterRequestsResponse.java => PlaceRegisterRequestsResponseDto.java} (79%) rename src/main/java/com/matzip/auth/api/dto/{KakaoLoginRequest.java => KakaoLoginRequestDto.java} (93%) rename src/main/java/com/matzip/auth/api/dto/{LoginResponse.java => LoginResponseDto.java} (96%) rename src/main/java/com/matzip/auth/api/dto/{TokenReissueRequest.java => TokenReissueRequestDto.java} (91%) rename src/main/java/com/matzip/auth/api/dto/{TokenResponse.java => TokenResponseDto.java} (90%) rename src/main/java/com/matzip/auth/infra/kakao/dto/{KakaoTokenResponse.java => KakaoTokenResponseDto.java} (95%) rename src/main/java/com/matzip/auth/infra/kakao/dto/{KakaoUserResponse.java => KakaoUserResponseDto.java} (87%) rename src/main/java/com/matzip/lottery/controller/request/{ApplyEventRequest.java => ApplyEventRequestDto.java} (95%) rename src/main/java/com/matzip/lottery/controller/response/{ApplyEventResponse.java => ApplyEventResponseDto.java} (75%) rename src/main/java/com/matzip/lottery/controller/response/{EventEntryResultResponse.java => EventEntryResultResponseDto.java} (70%) rename src/main/java/com/matzip/lottery/controller/response/{LotteryEventAnonymousResponse.java => LotteryEventAnonymousResponseDto.java} (56%) rename src/main/java/com/matzip/lottery/controller/response/{LotteryEventResponse.java => LotteryEventResponseDto.java} (73%) rename src/main/java/com/matzip/lottery/controller/response/{ParticipatedEventResponse.java => ParticipatedEventResponseDto.java} (61%) diff --git a/src/main/java/com/matzip/admin/controller/AdminController.java b/src/main/java/com/matzip/admin/controller/AdminController.java index 0f13c23..a93718b 100644 --- a/src/main/java/com/matzip/admin/controller/AdminController.java +++ b/src/main/java/com/matzip/admin/controller/AdminController.java @@ -1,8 +1,8 @@ package com.matzip.admin.controller; -import com.matzip.admin.controller.request.PlaceRegisterRequestReviewRequest; -import com.matzip.admin.controller.response.PlaceRegisterRequestDetailResponse; -import com.matzip.admin.controller.response.PlaceRegisterRequestsResponse; +import com.matzip.admin.controller.request.PlaceRegisterRequestReviewRequestDto; +import com.matzip.admin.controller.response.PlaceRegisterRequestDetailResponseDto; +import com.matzip.admin.controller.response.PlaceRegisterRequestsResponseDto; import com.matzip.admin.service.AdminPlaceRegisterRequestService; import com.matzip.common.exception.BusinessException; import com.matzip.common.exception.code.ErrorCode; @@ -32,21 +32,21 @@ public AdminController(PlaceRepository placeRepository, AdminPlaceRegisterReques } @GetMapping("/requests/places") - public ApiResponse> findPlaceRegisterRequests() { - List data = placeRepository.findPendingPlaces() + public ApiResponse> findPlaceRegisterRequests() { + List data = placeRepository.findPendingPlaces() .stream() - .map(PlaceRegisterRequestsResponse::from) + .map(PlaceRegisterRequestsResponseDto::from) .toList(); return ApiResponse.success(data); } @GetMapping("/requests/places/{placeId}") - public ApiResponse findPlaceRegisterRequestDetail( + public ApiResponse findPlaceRegisterRequestDetail( @PathVariable("placeId") Long placeId ) { - PlaceRegisterRequestDetailResponse data = placeRepository.findByIdWithCategoriesAndTags(placeId) - .map(PlaceRegisterRequestDetailResponse::from) + PlaceRegisterRequestDetailResponseDto data = placeRepository.findByIdWithCategoriesAndTags(placeId) + .map(PlaceRegisterRequestDetailResponseDto::from) .orElseThrow(() -> new BusinessException(ErrorCode.PLACE_NOT_FOUND)); return ApiResponse.success(data); @@ -55,7 +55,7 @@ public ApiResponse findPlaceRegisterRequestD @PostMapping("/requests/places/{placeId}/review") public ApiResponse reviewPlaceRegisterRequest( @PathVariable("placeId") Long placeId, - @RequestBody PlaceRegisterRequestReviewRequest request + @RequestBody PlaceRegisterRequestReviewRequestDto request // , @AuthenticationPrincipal UserPrincipal admin ) { adminPlaceRegisterRequestService.review( diff --git a/src/main/java/com/matzip/admin/controller/request/PlaceRegisterRequestReviewRequest.java b/src/main/java/com/matzip/admin/controller/request/PlaceRegisterRequestReviewRequest.java deleted file mode 100644 index e51c4db..0000000 --- a/src/main/java/com/matzip/admin/controller/request/PlaceRegisterRequestReviewRequest.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.matzip.admin.controller.request; - -import com.matzip.admin.domain.RequestReviewStatus; - -public record PlaceRegisterRequestReviewRequest(RequestReviewStatus status, String rejectedReason) { -} diff --git a/src/main/java/com/matzip/admin/controller/request/PlaceRegisterRequestReviewRequestDto.java b/src/main/java/com/matzip/admin/controller/request/PlaceRegisterRequestReviewRequestDto.java new file mode 100644 index 0000000..4a86bc7 --- /dev/null +++ b/src/main/java/com/matzip/admin/controller/request/PlaceRegisterRequestReviewRequestDto.java @@ -0,0 +1,6 @@ +package com.matzip.admin.controller.request; + +import com.matzip.admin.domain.RequestReviewStatus; + +public record PlaceRegisterRequestReviewRequestDto(RequestReviewStatus status, String rejectedReason) { +} diff --git a/src/main/java/com/matzip/admin/controller/response/PlaceRegisterRequestDetailResponse.java b/src/main/java/com/matzip/admin/controller/response/PlaceRegisterRequestDetailResponseDto.java similarity index 87% rename from src/main/java/com/matzip/admin/controller/response/PlaceRegisterRequestDetailResponse.java rename to src/main/java/com/matzip/admin/controller/response/PlaceRegisterRequestDetailResponseDto.java index 3125958..b3ac07f 100644 --- a/src/main/java/com/matzip/admin/controller/response/PlaceRegisterRequestDetailResponse.java +++ b/src/main/java/com/matzip/admin/controller/response/PlaceRegisterRequestDetailResponseDto.java @@ -12,7 +12,7 @@ import java.util.List; @Builder -public record PlaceRegisterRequestDetailResponse(Long placeId, String placeName, LocalDate requestDate, List photos, +public record PlaceRegisterRequestDetailResponseDto(Long placeId, String placeName, LocalDate requestDate, List photos, String address, LocationDto location, String description, List menus, List categories, List tags) { @@ -31,8 +31,8 @@ public static MenusResponse from(Menu menu) { } } - public static PlaceRegisterRequestDetailResponse from(Place place) { - return PlaceRegisterRequestDetailResponse.builder() + public static PlaceRegisterRequestDetailResponseDto from(Place place) { + return PlaceRegisterRequestDetailResponseDto.builder() .placeId(place.getId()) .placeName(place.getName()) .requestDate(place.getCreatedAt().toLocalDate()) diff --git a/src/main/java/com/matzip/admin/controller/response/PlaceRegisterRequestsResponse.java b/src/main/java/com/matzip/admin/controller/response/PlaceRegisterRequestsResponseDto.java similarity index 79% rename from src/main/java/com/matzip/admin/controller/response/PlaceRegisterRequestsResponse.java rename to src/main/java/com/matzip/admin/controller/response/PlaceRegisterRequestsResponseDto.java index 30bfa99..e347e84 100644 --- a/src/main/java/com/matzip/admin/controller/response/PlaceRegisterRequestsResponse.java +++ b/src/main/java/com/matzip/admin/controller/response/PlaceRegisterRequestsResponseDto.java @@ -10,11 +10,11 @@ import java.util.List; @Builder -public record PlaceRegisterRequestsResponse(Long placeId, String placeName, LocalDate requestDate, Campus campus, +public record PlaceRegisterRequestsResponseDto(Long placeId, String placeName, LocalDate requestDate, Campus campus, List categories, List tags) { - public static PlaceRegisterRequestsResponse from(Place place) { - return PlaceRegisterRequestsResponse.builder() + public static PlaceRegisterRequestsResponseDto from(Place place) { + return PlaceRegisterRequestsResponseDto.builder() .placeId(place.getId()) .placeName(place.getName()) .requestDate(place.getCreatedAt().toLocalDate()) diff --git a/src/main/java/com/matzip/auth/api/AuthController.java b/src/main/java/com/matzip/auth/api/AuthController.java index 3628867..ac1d75f 100644 --- a/src/main/java/com/matzip/auth/api/AuthController.java +++ b/src/main/java/com/matzip/auth/api/AuthController.java @@ -1,9 +1,9 @@ package com.matzip.auth.api; -import com.matzip.auth.api.dto.KakaoLoginRequest; -import com.matzip.auth.api.dto.LoginResponse; -import com.matzip.auth.api.dto.TokenReissueRequest; -import com.matzip.auth.api.dto.TokenResponse; +import com.matzip.auth.api.dto.KakaoLoginRequestDto; +import com.matzip.auth.api.dto.LoginResponseDto; +import com.matzip.auth.api.dto.TokenReissueRequestDto; +import com.matzip.auth.api.dto.TokenResponseDto; import com.matzip.auth.application.AuthService; import com.matzip.auth.application.util.KakaoAuthorizeUrlBuilder; import com.matzip.auth.application.dto.ReissueResult; @@ -67,9 +67,9 @@ public ResponseEntity authorize(@RequestParam("clientOrigin") String clien * @return */ @PostMapping("/token") - public ResponseEntity> reissue( + public ResponseEntity> reissue( @CookieValue(value = RT_COOKIE_NAME, required = false) String rtCookie, - @RequestBody(required = false) TokenReissueRequest body + @RequestBody(required = false) TokenReissueRequestDto body ) { String incomingRt = (body != null && StringUtils.hasText(body.getRefreshToken())) ? body.getRefreshToken() @@ -79,13 +79,13 @@ public ResponseEntity> reissue( throw new BusinessException(ErrorCode.UNAUTHORIZED, "๋ฆฌํ”„๋ ˆ์‹œ ํ† ํฐ์ด ์—†์Šต๋‹ˆ๋‹ค."); } - ReissueResult result = authService.reissue(new TokenReissueRequest(incomingRt)); + ReissueResult result = authService.reissue(new TokenReissueRequestDto(incomingRt)); // ํšŒ์ „๋œ ์ƒˆ Refresh Token์„ ์ฟ ํ‚ค๋กœ ์„ค์ • ResponseCookie rtCookieNew = buildRtCookie(result.refreshToken(), result.refreshTokenExpiresInMs()); // ๋ฐ”๋””๋Š” Access Token๋งŒ - TokenResponse bodyDto = TokenResponse.builder() + TokenResponseDto bodyDto = TokenResponseDto.builder() .tokenType("Bearer") .accessToken(result.accessToken()) .accessTokenExpiresIn(result.accessTokenExpiresInMs()) @@ -129,8 +129,8 @@ public ResponseEntity kakaoCallback( } try { - // KakaoLoginRequest์˜ redirectUri๋Š” ์ธ๊ฐ€์ฝ”๋“œ ๋ฐ›์„ ๋•Œ ์‚ฌ์šฉ๋œ redirectUri - LoginResponse res = authService.login(new KakaoLoginRequest(code, "http://localhost:3000/login/loading/success")); + // KakaoLoginRequestDto์˜ redirectUri๋Š” ์ธ๊ฐ€์ฝ”๋“œ ๋ฐ›์„ ๋•Œ ์‚ฌ์šฉ๋œ redirectUri + LoginResponseDto res = authService.login(new KakaoLoginRequestDto(code, "http://localhost:3000/login/loading/success")); // ๋กœ๊ทธ์ธ ์„ฑ๊ณต ResponseCookie rtCookie = buildRtCookie(res.getRefreshToken(), res.getRefreshTokenExpiresIn()); diff --git a/src/main/java/com/matzip/auth/api/AuthControllerV2.java b/src/main/java/com/matzip/auth/api/AuthControllerV2.java index 96ef386..6b2a00b 100644 --- a/src/main/java/com/matzip/auth/api/AuthControllerV2.java +++ b/src/main/java/com/matzip/auth/api/AuthControllerV2.java @@ -1,7 +1,7 @@ package com.matzip.auth.api; -import com.matzip.auth.api.dto.KakaoLoginRequest; -import com.matzip.auth.api.dto.LoginResponse; +import com.matzip.auth.api.dto.KakaoLoginRequestDto; +import com.matzip.auth.api.dto.LoginResponseDto; import com.matzip.auth.application.AuthService; import com.matzip.common.response.ApiResponse; import org.springframework.http.HttpHeaders; @@ -27,7 +27,7 @@ public AuthControllerV2(AuthService authService) { @GetMapping("/oauth2") public ResponseEntity> kakaoLogin(@RequestParam("code") String code, @RequestParam("redirectUri") String redirectUri) { - LoginResponse loginResponse = authService.login(new KakaoLoginRequest(code, redirectUri)); + LoginResponseDto loginResponse = authService.login(new KakaoLoginRequestDto(code, redirectUri)); // ResponseCookie accessTokenCookie = // generateCookie("accessToken", loginResponse.getAccessToken(), Duration.ofHours(1)); diff --git a/src/main/java/com/matzip/auth/api/dto/KakaoLoginRequest.java b/src/main/java/com/matzip/auth/api/dto/KakaoLoginRequestDto.java similarity index 93% rename from src/main/java/com/matzip/auth/api/dto/KakaoLoginRequest.java rename to src/main/java/com/matzip/auth/api/dto/KakaoLoginRequestDto.java index a15c269..696b259 100644 --- a/src/main/java/com/matzip/auth/api/dto/KakaoLoginRequest.java +++ b/src/main/java/com/matzip/auth/api/dto/KakaoLoginRequestDto.java @@ -12,7 +12,7 @@ @NoArgsConstructor(access = AccessLevel.PROTECTED) @AllArgsConstructor @Builder -public class KakaoLoginRequest { +public class KakaoLoginRequestDto { @NotBlank(message = "์ธ๊ฐ€ ์ฝ”๋“œ๋Š” ํ•„์ˆ˜์ž…๋‹ˆ๋‹ค.") private String code; diff --git a/src/main/java/com/matzip/auth/api/dto/LoginResponse.java b/src/main/java/com/matzip/auth/api/dto/LoginResponseDto.java similarity index 96% rename from src/main/java/com/matzip/auth/api/dto/LoginResponse.java rename to src/main/java/com/matzip/auth/api/dto/LoginResponseDto.java index 926a4ac..18a64e8 100644 --- a/src/main/java/com/matzip/auth/api/dto/LoginResponse.java +++ b/src/main/java/com/matzip/auth/api/dto/LoginResponseDto.java @@ -9,7 +9,7 @@ @NoArgsConstructor(access = AccessLevel.PROTECTED) @AllArgsConstructor @Builder -public class LoginResponse { +public class LoginResponseDto { // ํ† ํฐ ์„น์…˜ private String tokenType; // "Bearer" ๊ณ ์ • ์‚ฌ์šฉ? diff --git a/src/main/java/com/matzip/auth/api/dto/TokenReissueRequest.java b/src/main/java/com/matzip/auth/api/dto/TokenReissueRequestDto.java similarity index 91% rename from src/main/java/com/matzip/auth/api/dto/TokenReissueRequest.java rename to src/main/java/com/matzip/auth/api/dto/TokenReissueRequestDto.java index 960701e..0c64180 100644 --- a/src/main/java/com/matzip/auth/api/dto/TokenReissueRequest.java +++ b/src/main/java/com/matzip/auth/api/dto/TokenReissueRequestDto.java @@ -11,7 +11,7 @@ @NoArgsConstructor(access = AccessLevel.PROTECTED) @AllArgsConstructor @Builder -public class TokenReissueRequest { +public class TokenReissueRequestDto { @NotBlank(message = "๋ฆฌํ”„๋ ˆ์‹œ ํ† ํฐ์€ ํ•„์ˆ˜์ž…๋‹ˆ๋‹ค.") private String refreshToken; diff --git a/src/main/java/com/matzip/auth/api/dto/TokenResponse.java b/src/main/java/com/matzip/auth/api/dto/TokenResponseDto.java similarity index 90% rename from src/main/java/com/matzip/auth/api/dto/TokenResponse.java rename to src/main/java/com/matzip/auth/api/dto/TokenResponseDto.java index 122a97a..787305b 100644 --- a/src/main/java/com/matzip/auth/api/dto/TokenResponse.java +++ b/src/main/java/com/matzip/auth/api/dto/TokenResponseDto.java @@ -9,7 +9,7 @@ @NoArgsConstructor(access = AccessLevel.PROTECTED) @AllArgsConstructor @Builder -public class TokenResponse { +public class TokenResponseDto { private String tokenType; private String accessToken; diff --git a/src/main/java/com/matzip/auth/application/AuthService.java b/src/main/java/com/matzip/auth/application/AuthService.java index e34a056..7747567 100644 --- a/src/main/java/com/matzip/auth/application/AuthService.java +++ b/src/main/java/com/matzip/auth/application/AuthService.java @@ -1,13 +1,13 @@ package com.matzip.auth.application; -import com.matzip.auth.api.dto.KakaoLoginRequest; -import com.matzip.auth.api.dto.LoginResponse; -import com.matzip.auth.api.dto.TokenReissueRequest; +import com.matzip.auth.api.dto.KakaoLoginRequestDto; +import com.matzip.auth.api.dto.LoginResponseDto; +import com.matzip.auth.api.dto.TokenReissueRequestDto; import com.matzip.auth.application.dto.ReissueResult; import com.matzip.auth.domain.RefreshToken; import com.matzip.auth.infra.kakao.KakaoLoginApiClient; -import com.matzip.auth.infra.kakao.dto.KakaoTokenResponse; -import com.matzip.auth.infra.kakao.dto.KakaoUserResponse; +import com.matzip.auth.infra.kakao.dto.KakaoTokenResponseDto; +import com.matzip.auth.infra.kakao.dto.KakaoUserResponseDto; import com.matzip.common.config.ImageProperties; import com.matzip.common.config.JwtProperties; import com.matzip.common.exception.BusinessException; @@ -45,15 +45,15 @@ private long refreshTokenTtlMs() { } @Transactional - public LoginResponse login(KakaoLoginRequest loginRequest) { + public LoginResponseDto login(KakaoLoginRequestDto loginRequest) { // 1) ์ธ๊ฐ€ ์ฝ”๋“œ -> ์นด์นด์˜ค ์•ก์„ธ์Šค ํ† ํฐ ๊ตํ™˜ - KakaoTokenResponse kakaoToken = kakaoLoginApiClient.exchangeToken(loginRequest.getCode(), loginRequest.getRedirectUri()); + KakaoTokenResponseDto kakaoToken = kakaoLoginApiClient.exchangeToken(loginRequest.getCode(), loginRequest.getRedirectUri()); if (kakaoToken == null || kakaoToken.getAccessToken() == null) { throw new BusinessException(ErrorCode.KAKAO_LOGIN_FAILED, "์นด์นด์˜ค ํ† ํฐ ์‘๋‹ต์ด ๋น„์–ด ์žˆ์Šต๋‹ˆ๋‹ค."); } // 2) ์นด์นด์˜ค ์‚ฌ์šฉ์ž ์ •๋ณด ์กฐํšŒ - KakaoUserResponse kakaoUser = kakaoLoginApiClient.getUser(kakaoToken.getAccessToken()); + KakaoUserResponseDto kakaoUser = kakaoLoginApiClient.getUser(kakaoToken.getAccessToken()); if (kakaoUser == null || kakaoUser.getId() == null) { throw new BusinessException(ErrorCode.KAKAO_LOGIN_FAILED, "์นด์นด์˜ค ์‚ฌ์šฉ์ž ์ •๋ณด ์กฐํšŒ ์‹คํŒจ"); } @@ -94,7 +94,7 @@ public LoginResponse login(KakaoLoginRequest loginRequest) { saved.updateToken(refreshToken); // ๋ณ€๊ฒฝ ๊ฐ์ง€์— ์˜ํ•ด ์—…๋ฐ์ดํŠธ } - return LoginResponse.builder() + return LoginResponseDto.builder() .tokenType("Bearer") .accessToken(accessToken) .accessTokenExpiresIn(accessTokenTtlMs()) @@ -109,7 +109,7 @@ public LoginResponse login(KakaoLoginRequest loginRequest) { } @Transactional - public ReissueResult reissue(TokenReissueRequest request) { + public ReissueResult reissue(TokenReissueRequestDto request) { final String requestRt = request.getRefreshToken(); if (requestRt == null || requestRt.isBlank()) { throw new BusinessException(ErrorCode.INVALID_INPUT_VALUE, "๋ฆฌํ”„๋ ˆ์‹œ ํ† ํฐ์€ ํ•„์ˆ˜์ž…๋‹ˆ๋‹ค."); diff --git a/src/main/java/com/matzip/auth/infra/kakao/KakaoLoginApiClient.java b/src/main/java/com/matzip/auth/infra/kakao/KakaoLoginApiClient.java index 0c1c351..e4da03e 100644 --- a/src/main/java/com/matzip/auth/infra/kakao/KakaoLoginApiClient.java +++ b/src/main/java/com/matzip/auth/infra/kakao/KakaoLoginApiClient.java @@ -1,7 +1,7 @@ package com.matzip.auth.infra.kakao; -import com.matzip.auth.infra.kakao.dto.KakaoTokenResponse; -import com.matzip.auth.infra.kakao.dto.KakaoUserResponse; +import com.matzip.auth.infra.kakao.dto.KakaoTokenResponseDto; +import com.matzip.auth.infra.kakao.dto.KakaoUserResponseDto; import com.matzip.common.config.KakaoProperties; import com.matzip.common.exception.BusinessException; import com.matzip.common.exception.code.ErrorCode; @@ -29,7 +29,7 @@ public class KakaoLoginApiClient { /** * ์ธ๊ฐ€์ฝ”๋“œ - ์นด์นด์˜ค ์•ก์„ธ์Šค ํ† ํฐ ๊ตํ™˜ */ - public KakaoTokenResponse exchangeToken(String authorizationCode, String redirectUri) { + public KakaoTokenResponseDto exchangeToken(String authorizationCode, String redirectUri) { MultiValueMap form = new LinkedMultiValueMap<>(); form.add("grant_type", "authorization_code"); form.add("client_id", kakaoProperties.getClientId()); @@ -56,7 +56,7 @@ public KakaoTokenResponse exchangeToken(String authorizationCode, String redirec ErrorCode.KAKAO_LOGIN_FAILED, "์นด์นด์˜ค ํ† ํฐ ๊ตํ™˜ ์‹คํŒจ: " + body))) ) - .bodyToMono(KakaoTokenResponse.class) + .bodyToMono(KakaoTokenResponseDto.class) .block(); } catch (BusinessException be) { throw be; @@ -70,7 +70,7 @@ public KakaoTokenResponse exchangeToken(String authorizationCode, String redirec * ์นด์นด์˜ค ์‚ฌ์šฉ์ž ์ •๋ณด ์กฐํšŒ * Authorization ํ—ค๋”: Bearer {accessToken} */ - public KakaoUserResponse getUser(String accessToken) { + public KakaoUserResponseDto getUser(String accessToken) { try { return webClientBuilder .baseUrl(API_HOST) @@ -88,7 +88,7 @@ public KakaoUserResponse getUser(String accessToken) { ErrorCode.KAKAO_LOGIN_FAILED, "์นด์นด์˜ค ์‚ฌ์šฉ์ž ์กฐํšŒ ์‹คํŒจ: " + body))) ) - .bodyToMono(KakaoUserResponse.class) + .bodyToMono(KakaoUserResponseDto.class) .block(); } catch (BusinessException be) { throw be; diff --git a/src/main/java/com/matzip/auth/infra/kakao/dto/KakaoTokenResponse.java b/src/main/java/com/matzip/auth/infra/kakao/dto/KakaoTokenResponseDto.java similarity index 95% rename from src/main/java/com/matzip/auth/infra/kakao/dto/KakaoTokenResponse.java rename to src/main/java/com/matzip/auth/infra/kakao/dto/KakaoTokenResponseDto.java index b2c88a2..a525a7f 100644 --- a/src/main/java/com/matzip/auth/infra/kakao/dto/KakaoTokenResponse.java +++ b/src/main/java/com/matzip/auth/infra/kakao/dto/KakaoTokenResponseDto.java @@ -10,7 +10,7 @@ */ @Getter @NoArgsConstructor -public class KakaoTokenResponse { +public class KakaoTokenResponseDto { // ํ† ํฐ ํƒ€์ž…, bearer๋กœ ๊ณ ์ • @JsonProperty("token_type") diff --git a/src/main/java/com/matzip/auth/infra/kakao/dto/KakaoUserResponse.java b/src/main/java/com/matzip/auth/infra/kakao/dto/KakaoUserResponseDto.java similarity index 87% rename from src/main/java/com/matzip/auth/infra/kakao/dto/KakaoUserResponse.java rename to src/main/java/com/matzip/auth/infra/kakao/dto/KakaoUserResponseDto.java index 2fea195..78ae7ef 100644 --- a/src/main/java/com/matzip/auth/infra/kakao/dto/KakaoUserResponse.java +++ b/src/main/java/com/matzip/auth/infra/kakao/dto/KakaoUserResponseDto.java @@ -9,7 +9,7 @@ */ @Getter @NoArgsConstructor -public class KakaoUserResponse { +public class KakaoUserResponseDto { // ์นด์นด์˜ค ๊ณ ์œ  ์‚ฌ์šฉ์ž ID (Long) private Long id; diff --git a/src/main/java/com/matzip/lottery/controller/LotteryEventController.java b/src/main/java/com/matzip/lottery/controller/LotteryEventController.java index 135e4d9..06e540e 100644 --- a/src/main/java/com/matzip/lottery/controller/LotteryEventController.java +++ b/src/main/java/com/matzip/lottery/controller/LotteryEventController.java @@ -2,11 +2,11 @@ import com.matzip.common.response.ApiResponse; import com.matzip.common.security.UserPrincipal; -import com.matzip.lottery.controller.request.ApplyEventRequest; -import com.matzip.lottery.controller.response.ApplyEventResponse; -import com.matzip.lottery.controller.response.EventEntryResultResponse; +import com.matzip.lottery.controller.request.ApplyEventRequestDto; +import com.matzip.lottery.controller.response.ApplyEventResponseDto; +import com.matzip.lottery.controller.response.EventEntryResultResponseDto; import com.matzip.lottery.controller.response.LotteryEventView; -import com.matzip.lottery.controller.response.ParticipatedEventResponse; +import com.matzip.lottery.controller.response.ParticipatedEventResponseDto; import com.matzip.lottery.service.LotteryEventService; import java.util.List; @@ -37,23 +37,23 @@ public ApiResponse findEvent(@AuthenticationPrincipal UserPrin } @GetMapping("/entries") - public ApiResponse> getParticipatedEvents(@AuthenticationPrincipal UserPrincipal user) { - List data = lotteryEventService.getParticipatedEvents(user.getUserId()); + public ApiResponse> getParticipatedEvents(@AuthenticationPrincipal UserPrincipal user) { + List data = lotteryEventService.getParticipatedEvents(user.getUserId()); return ApiResponse.success(data); } @GetMapping("/{eventId}/entries") - public ApiResponse getEntryResult(@PathVariable Long eventId, + public ApiResponse getEntryResult(@PathVariable Long eventId, @AuthenticationPrincipal UserPrincipal user) { - EventEntryResultResponse data = lotteryEventService.getEntryResult(eventId, user.getUserId()); + EventEntryResultResponseDto data = lotteryEventService.getEntryResult(eventId, user.getUserId()); return ApiResponse.success(data); } @PostMapping("/{eventId}/apply") - public ApiResponse applyForPrize(@PathVariable Long eventId, - @Validated @RequestBody ApplyEventRequest request, + public ApiResponse applyForPrize(@PathVariable Long eventId, + @Validated @RequestBody ApplyEventRequestDto request, @AuthenticationPrincipal UserPrincipal user) { - ApplyEventResponse data = lotteryEventService.applyForPrize(eventId, user.getUserId(), request); + ApplyEventResponseDto data = lotteryEventService.applyForPrize(eventId, user.getUserId(), request); return ApiResponse.success(data); } } diff --git a/src/main/java/com/matzip/lottery/controller/request/ApplyEventRequest.java b/src/main/java/com/matzip/lottery/controller/request/ApplyEventRequestDto.java similarity index 95% rename from src/main/java/com/matzip/lottery/controller/request/ApplyEventRequest.java rename to src/main/java/com/matzip/lottery/controller/request/ApplyEventRequestDto.java index 2682e1b..b4676cc 100644 --- a/src/main/java/com/matzip/lottery/controller/request/ApplyEventRequest.java +++ b/src/main/java/com/matzip/lottery/controller/request/ApplyEventRequestDto.java @@ -6,7 +6,7 @@ import jakarta.validation.constraints.Pattern; -public record ApplyEventRequest( +public record ApplyEventRequestDto( @NotBlank(message = "ํ•ธ๋“œํฐ ๋ฒˆํ˜ธ๋ฅผ ์ž…๋ ฅํ•ด ์ฃผ์„ธ์š”.") @Pattern(regexp = "^010-\\d{3,4}-\\d{4}$", message = "์˜ฌ๋ฐ”๋ฅธ ํ•ธ๋“œํฐ ๋ฒˆํ˜ธ ํ˜•์‹์ด ์•„๋‹™๋‹ˆ๋‹ค. (์˜ˆ: 010-1234-5678)") String phoneNumber, diff --git a/src/main/java/com/matzip/lottery/controller/response/ApplyEventResponse.java b/src/main/java/com/matzip/lottery/controller/response/ApplyEventResponseDto.java similarity index 75% rename from src/main/java/com/matzip/lottery/controller/response/ApplyEventResponse.java rename to src/main/java/com/matzip/lottery/controller/response/ApplyEventResponseDto.java index 0ab8b15..ba43838 100644 --- a/src/main/java/com/matzip/lottery/controller/response/ApplyEventResponse.java +++ b/src/main/java/com/matzip/lottery/controller/response/ApplyEventResponseDto.java @@ -5,7 +5,7 @@ @Builder -public record ApplyEventResponse( +public record ApplyEventResponseDto( String phoneNumber, AgreementsResponse agreements ) { @@ -13,8 +13,8 @@ public record ApplyEventResponse( public record AgreementsResponse(boolean termsAgreed, boolean privacyAgreed) { } - public static ApplyEventResponse from(WinnerContact contact) { - return ApplyEventResponse.builder() + public static ApplyEventResponseDto from(WinnerContact contact) { + return ApplyEventResponseDto.builder() .phoneNumber(contact.getPhoneNumber()) .agreements(new AgreementsResponse(contact.isTermsAgreed(), contact.isPrivacyAgreed())) .build(); diff --git a/src/main/java/com/matzip/lottery/controller/response/EventEntryResultResponse.java b/src/main/java/com/matzip/lottery/controller/response/EventEntryResultResponseDto.java similarity index 70% rename from src/main/java/com/matzip/lottery/controller/response/EventEntryResultResponse.java rename to src/main/java/com/matzip/lottery/controller/response/EventEntryResultResponseDto.java index 7715a2f..d202b2c 100644 --- a/src/main/java/com/matzip/lottery/controller/response/EventEntryResultResponse.java +++ b/src/main/java/com/matzip/lottery/controller/response/EventEntryResultResponseDto.java @@ -6,9 +6,9 @@ import java.time.LocalDateTime; @Builder -public record EventEntryResultResponse( +public record EventEntryResultResponseDto( Long eventId, - LotteryEventResponse.PrizeResponse prize, + LotteryEventResponseDto.PrizeResponse prize, int totalWinnersCount, int participantsCount, int usedTicketsCount, @@ -17,11 +17,11 @@ public record EventEntryResultResponse( boolean isPhoneSubmitted ) { - public static EventEntryResultResponse of(LotteryEvent event, int participantsCount, int usedTicketsCount, + public static EventEntryResultResponseDto of(LotteryEvent event, int participantsCount, int usedTicketsCount, boolean isWinner, boolean isPhoneSubmitted) { - return EventEntryResultResponse.builder() + return EventEntryResultResponseDto.builder() .eventId(event.getId()) - .prize(LotteryEventResponse.PrizeResponse.from(event.getPrize())) + .prize(LotteryEventResponseDto.PrizeResponse.from(event.getPrize())) .totalWinnersCount(event.getWinnersCount()) .participantsCount(participantsCount) .usedTicketsCount(usedTicketsCount) diff --git a/src/main/java/com/matzip/lottery/controller/response/LotteryEventAnonymousResponse.java b/src/main/java/com/matzip/lottery/controller/response/LotteryEventAnonymousResponseDto.java similarity index 56% rename from src/main/java/com/matzip/lottery/controller/response/LotteryEventAnonymousResponse.java rename to src/main/java/com/matzip/lottery/controller/response/LotteryEventAnonymousResponseDto.java index d9d54df..8a673ba 100644 --- a/src/main/java/com/matzip/lottery/controller/response/LotteryEventAnonymousResponse.java +++ b/src/main/java/com/matzip/lottery/controller/response/LotteryEventAnonymousResponseDto.java @@ -6,19 +6,19 @@ import java.time.LocalDateTime; @Builder -public record LotteryEventAnonymousResponse(Long eventId, LotteryEventResponse.PrizeResponse prize, +public record LotteryEventAnonymousResponseDto(Long eventId, LotteryEventResponseDto.PrizeResponse prize, int totalWinnersCount, int participantsCount, LocalDateTime eventEndDate) implements LotteryEventView { - public static LotteryEventAnonymousResponse empty() { - return LotteryEventAnonymousResponse.builder() + public static LotteryEventAnonymousResponseDto empty() { + return LotteryEventAnonymousResponseDto.builder() .build(); } - public static LotteryEventAnonymousResponse of(LotteryEvent lotteryEvent, int participantsCount) { - return LotteryEventAnonymousResponse.builder() + public static LotteryEventAnonymousResponseDto of(LotteryEvent lotteryEvent, int participantsCount) { + return LotteryEventAnonymousResponseDto.builder() .eventId(lotteryEvent.getId()) - .prize(LotteryEventResponse.PrizeResponse.from(lotteryEvent.getPrize())) + .prize(LotteryEventResponseDto.PrizeResponse.from(lotteryEvent.getPrize())) .totalWinnersCount(lotteryEvent.getWinnersCount()) .participantsCount(participantsCount) .eventEndDate(lotteryEvent.getEndDateTime()) diff --git a/src/main/java/com/matzip/lottery/controller/response/LotteryEventResponse.java b/src/main/java/com/matzip/lottery/controller/response/LotteryEventResponseDto.java similarity index 73% rename from src/main/java/com/matzip/lottery/controller/response/LotteryEventResponse.java rename to src/main/java/com/matzip/lottery/controller/response/LotteryEventResponseDto.java index 70d95e8..ed8d85e 100644 --- a/src/main/java/com/matzip/lottery/controller/response/LotteryEventResponse.java +++ b/src/main/java/com/matzip/lottery/controller/response/LotteryEventResponseDto.java @@ -7,17 +7,17 @@ import java.time.LocalDateTime; @Builder -public record LotteryEventResponse(Long eventId, PrizeResponse prize, int totalWinnersCount, int participantsCount, +public record LotteryEventResponseDto(Long eventId, PrizeResponse prize, int totalWinnersCount, int participantsCount, int usedTicketsCount, LocalDateTime eventEndDate) implements LotteryEventView { - public static LotteryEventResponse empty() { - return LotteryEventResponse.builder() + public static LotteryEventResponseDto empty() { + return LotteryEventResponseDto.builder() .build(); } - public static LotteryEventResponse of(LotteryEvent lotteryEvent, int participantsCount, int usedTicketsCount) { - return LotteryEventResponse.builder() + public static LotteryEventResponseDto of(LotteryEvent lotteryEvent, int participantsCount, int usedTicketsCount) { + return LotteryEventResponseDto.builder() .eventId(lotteryEvent.getId()) .prize(PrizeResponse.from(lotteryEvent.getPrize())) .totalWinnersCount(lotteryEvent.getWinnersCount()) diff --git a/src/main/java/com/matzip/lottery/controller/response/LotteryEventView.java b/src/main/java/com/matzip/lottery/controller/response/LotteryEventView.java index ef58943..6fb9594 100644 --- a/src/main/java/com/matzip/lottery/controller/response/LotteryEventView.java +++ b/src/main/java/com/matzip/lottery/controller/response/LotteryEventView.java @@ -1,5 +1,5 @@ package com.matzip.lottery.controller.response; -public sealed interface LotteryEventView permits LotteryEventResponse, LotteryEventAnonymousResponse { +public sealed interface LotteryEventView permits LotteryEventResponseDto, LotteryEventAnonymousResponseDto { } diff --git a/src/main/java/com/matzip/lottery/controller/response/ParticipatedEventResponse.java b/src/main/java/com/matzip/lottery/controller/response/ParticipatedEventResponseDto.java similarity index 61% rename from src/main/java/com/matzip/lottery/controller/response/ParticipatedEventResponse.java rename to src/main/java/com/matzip/lottery/controller/response/ParticipatedEventResponseDto.java index 99158c8..6ef6134 100644 --- a/src/main/java/com/matzip/lottery/controller/response/ParticipatedEventResponse.java +++ b/src/main/java/com/matzip/lottery/controller/response/ParticipatedEventResponseDto.java @@ -6,18 +6,18 @@ import java.time.LocalDateTime; @Builder -public record ParticipatedEventResponse( +public record ParticipatedEventResponseDto( Long eventId, - LotteryEventResponse.PrizeResponse prize, + LotteryEventResponseDto.PrizeResponse prize, int totalWinnersCount, int participantsCount, LocalDateTime eventEndDate ) { - public static ParticipatedEventResponse of(LotteryEvent event, int participantsCount) { - return ParticipatedEventResponse.builder() + public static ParticipatedEventResponseDto of(LotteryEvent event, int participantsCount) { + return ParticipatedEventResponseDto.builder() .eventId(event.getId()) - .prize(LotteryEventResponse.PrizeResponse.from(event.getPrize())) + .prize(LotteryEventResponseDto.PrizeResponse.from(event.getPrize())) .totalWinnersCount(event.getWinnersCount()) .participantsCount(participantsCount) .eventEndDate(event.getEndDateTime()) diff --git a/src/main/java/com/matzip/lottery/service/LotteryEventService.java b/src/main/java/com/matzip/lottery/service/LotteryEventService.java index 7dec2b2..fa1ecc5 100644 --- a/src/main/java/com/matzip/lottery/service/LotteryEventService.java +++ b/src/main/java/com/matzip/lottery/service/LotteryEventService.java @@ -2,13 +2,13 @@ import com.matzip.common.exception.BusinessException; import com.matzip.common.exception.code.ErrorCode; -import com.matzip.lottery.controller.request.ApplyEventRequest; -import com.matzip.lottery.controller.response.ApplyEventResponse; -import com.matzip.lottery.controller.response.EventEntryResultResponse; -import com.matzip.lottery.controller.response.LotteryEventAnonymousResponse; -import com.matzip.lottery.controller.response.LotteryEventResponse; +import com.matzip.lottery.controller.request.ApplyEventRequestDto; +import com.matzip.lottery.controller.response.ApplyEventResponseDto; +import com.matzip.lottery.controller.response.EventEntryResultResponseDto; +import com.matzip.lottery.controller.response.LotteryEventAnonymousResponseDto; +import com.matzip.lottery.controller.response.LotteryEventResponseDto; import com.matzip.lottery.controller.response.LotteryEventView; -import com.matzip.lottery.controller.response.ParticipatedEventResponse; +import com.matzip.lottery.controller.response.ParticipatedEventResponseDto; import com.matzip.lottery.domain.LotteryEntries; import com.matzip.lottery.domain.LotteryEntry; import com.matzip.lottery.domain.LotteryEvent; @@ -56,30 +56,30 @@ public LotteryEventView getCurrentEvent(Long userId) { int participantsCount = lotteryEntries.getParticipantsCount(); if (userId == null) { - return LotteryEventAnonymousResponse.of(currentEvent, participantsCount); + return LotteryEventAnonymousResponseDto.of(currentEvent, participantsCount); } int usedTicketsCount = lotteryEntries.countEntriesByUser(userId); - return LotteryEventResponse.of(currentEvent, participantsCount, usedTicketsCount); + return LotteryEventResponseDto.of(currentEvent, participantsCount, usedTicketsCount); }) .orElse(null); } @Transactional(readOnly = true) - public List getParticipatedEvents(Long userId) { + public List getParticipatedEvents(Long userId) { List events = lotteryEntryRepository.findDistinctEndedLotteryEventsByUserId(userId, LocalDateTime.now()); return events.stream() .map(event -> { int participantsCount = lotteryEntryRepository.countParticipantsByLotteryEvent(event); - return ParticipatedEventResponse.of(event, participantsCount); + return ParticipatedEventResponseDto.of(event, participantsCount); }) .toList(); } @Transactional(readOnly = true) - public EventEntryResultResponse getEntryResult(Long eventId, Long userId) { + public EventEntryResultResponseDto getEntryResult(Long eventId, Long userId) { LotteryEvent event = lotteryEventRepository.findById(eventId) .orElseThrow(() -> new BusinessException(ErrorCode.INVALID_INPUT_VALUE, "์ด๋ฒคํŠธ๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. eventId: " + eventId)); @@ -97,11 +97,11 @@ public EventEntryResultResponse getEntryResult(Long eventId, Long userId) { boolean isWinner = winnerRepository.findByUserIdAndEventId(userId, eventId).isPresent(); boolean isPhoneSubmitted = winnerContactRepository.findByUserIdAndEventId(userId, eventId).isPresent(); - return EventEntryResultResponse.of(event, participantsCount, usedTicketsCount, isWinner, isPhoneSubmitted); + return EventEntryResultResponseDto.of(event, participantsCount, usedTicketsCount, isWinner, isPhoneSubmitted); } @Transactional - public ApplyEventResponse applyForPrize(Long eventId, Long userId, ApplyEventRequest request) { + public ApplyEventResponseDto applyForPrize(Long eventId, Long userId, ApplyEventRequestDto request) { LotteryEvent event = lotteryEventRepository.findById(eventId) .orElseThrow(() -> new BusinessException(ErrorCode.INVALID_INPUT_VALUE, "์ด๋ฒคํŠธ๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. eventId: " + eventId)); @@ -132,7 +132,7 @@ public ApplyEventResponse applyForPrize(Long eventId, Long userId, ApplyEventReq discordWinnerNotificationService.notifyWinnerContactSubmitted(event, userId, request.phoneNumber()); - return ApplyEventResponse.from(contact); + return ApplyEventResponseDto.from(contact); } @Transactional diff --git a/src/main/java/com/matzip/place/api/controller/PlaceRequestController.java b/src/main/java/com/matzip/place/api/controller/PlaceRequestController.java index 0688b56..22dad71 100644 --- a/src/main/java/com/matzip/place/api/controller/PlaceRequestController.java +++ b/src/main/java/com/matzip/place/api/controller/PlaceRequestController.java @@ -1,6 +1,6 @@ package com.matzip.place.api.controller; -import com.matzip.admin.controller.response.PlaceRegisterRequestDetailResponse; +import com.matzip.admin.controller.response.PlaceRegisterRequestDetailResponseDto; import com.matzip.common.exception.BusinessException; import com.matzip.common.exception.code.ErrorCode; import com.matzip.common.response.ApiResponse; diff --git a/src/main/java/com/matzip/place/api/response/PlaceDetailResponseDto.java b/src/main/java/com/matzip/place/api/response/PlaceDetailResponseDto.java index d43922e..95f6412 100644 --- a/src/main/java/com/matzip/place/api/response/PlaceDetailResponseDto.java +++ b/src/main/java/com/matzip/place/api/response/PlaceDetailResponseDto.java @@ -1,7 +1,11 @@ package com.matzip.place.api.response; import com.fasterxml.jackson.annotation.JsonProperty; -import com.matzip.place.domain.entity.*; +import com.matzip.place.domain.entity.Category; +import com.matzip.place.domain.entity.Menu; +import com.matzip.place.domain.entity.Photo; +import com.matzip.place.domain.entity.Place; +import com.matzip.place.domain.entity.Tag; import com.matzip.place.dto.CategoryDto; import com.matzip.place.dto.LocationDto; import com.matzip.place.dto.PhotoDto; diff --git a/src/main/java/com/matzip/place/application/service/PlaceLikeService.java b/src/main/java/com/matzip/place/application/service/PlaceLikeService.java index 4ef86d8..b4afdcb 100644 --- a/src/main/java/com/matzip/place/application/service/PlaceLikeService.java +++ b/src/main/java/com/matzip/place/application/service/PlaceLikeService.java @@ -4,7 +4,12 @@ import com.matzip.common.exception.code.ErrorCode; import com.matzip.place.api.response.PlaceLikeResponseDto; import com.matzip.place.api.response.PlaceCommonResponseDto; -import com.matzip.place.domain.entity.*; +import com.matzip.place.domain.entity.Category; +import com.matzip.place.domain.entity.Place; +import com.matzip.place.domain.entity.PlaceCategory; +import com.matzip.place.domain.entity.PlaceLike; +import com.matzip.place.domain.entity.PlaceTag; +import com.matzip.place.domain.entity.Tag; import com.matzip.place.infra.repository.PlaceCategoryRepository; import com.matzip.place.infra.repository.PlaceLikeRepository; import com.matzip.place.infra.repository.PlaceRepository; diff --git a/src/main/java/com/matzip/place/application/service/PlaceReadService.java b/src/main/java/com/matzip/place/application/service/PlaceReadService.java index 3e45412..013728f 100644 --- a/src/main/java/com/matzip/place/application/service/PlaceReadService.java +++ b/src/main/java/com/matzip/place/application/service/PlaceReadService.java @@ -6,12 +6,34 @@ import com.matzip.common.exception.BusinessException; import com.matzip.common.exception.code.ErrorCode; import com.matzip.place.api.request.MapSearchRequestDto; -import com.matzip.place.api.response.*; -import com.matzip.place.domain.*; -import com.matzip.place.domain.entity.*; +import com.matzip.place.api.response.MapSearchResponseDto; +import com.matzip.place.api.response.PlaceCommonResponseDto; +import com.matzip.place.api.response.PlaceDetailResponseDto; +import com.matzip.place.api.response.PlaceMenuSearchResponseDto; +import com.matzip.place.api.response.PlaceRegisterStatusDetailResponseDto; +import com.matzip.place.api.response.PlaceRegisterStatusResponseDto; +import com.matzip.place.api.response.PlaceSearchResponseDto; +import com.matzip.place.domain.Campus; +import com.matzip.place.domain.DailyViewCount; +import com.matzip.place.domain.PlaceStatus; +import com.matzip.place.domain.SortType; +import com.matzip.place.domain.entity.Category; +import com.matzip.place.domain.entity.Menu; +import com.matzip.place.domain.entity.Photo; +import com.matzip.place.domain.entity.Place; +import com.matzip.place.domain.entity.PlaceCategory; +import com.matzip.place.domain.entity.PlaceTag; +import com.matzip.place.domain.entity.Tag; import com.matzip.place.dto.CategoryDto; import com.matzip.place.dto.TagDto; -import com.matzip.place.infra.repository.*; +import com.matzip.place.infra.repository.CategoryRepository; +import com.matzip.place.infra.repository.DailyViewCountRepository; +import com.matzip.place.infra.repository.MenuRepository; +import com.matzip.place.infra.repository.PhotoRepository; +import com.matzip.place.infra.repository.PlaceCategoryRepository; +import com.matzip.place.infra.repository.PlaceLikeRepository; +import com.matzip.place.infra.repository.PlaceRepository; +import com.matzip.place.infra.repository.PlaceTagRepository; import com.matzip.user.domain.User; import com.matzip.user.infra.UserRepository; import lombok.RequiredArgsConstructor; diff --git a/src/main/java/com/matzip/place/application/service/PlaceService.java b/src/main/java/com/matzip/place/application/service/PlaceService.java index 25d8771..1c1ec91 100644 --- a/src/main/java/com/matzip/place/application/service/PlaceService.java +++ b/src/main/java/com/matzip/place/application/service/PlaceService.java @@ -3,16 +3,28 @@ import com.matzip.place.dto.LocationDto; import com.matzip.place.dto.MenuDto; import com.matzip.place.dto.PhotoDto; -import com.matzip.place.domain.entity.*; +import com.matzip.place.domain.entity.Category; +import com.matzip.place.domain.entity.Menu; +import com.matzip.place.domain.entity.Photo; +import com.matzip.place.domain.entity.Place; +import com.matzip.place.domain.entity.PlaceCategory; +import com.matzip.place.domain.entity.PlaceTag; +import com.matzip.place.domain.entity.Tag; import com.matzip.place.infra.kakao.KakaoApiClient; import com.matzip.place.api.request.PlaceCheckRequestDto; import com.matzip.place.api.request.PlaceRequestDto; import com.matzip.place.api.response.PlaceCheckResponseDto; import com.matzip.place.api.response.PlaceRegisterResponseDto; import com.matzip.place.application.port.PlaceTempStore.PlaceSnapshot; -import com.matzip.place.domain.*; +import com.matzip.place.domain.PlaceStatus; import com.matzip.place.application.port.PlaceTempStore; -import com.matzip.place.infra.repository.*; +import com.matzip.place.infra.repository.CategoryRepository; +import com.matzip.place.infra.repository.MenuRepository; +import com.matzip.place.infra.repository.PhotoRepository; +import com.matzip.place.infra.repository.PlaceCategoryRepository; +import com.matzip.place.infra.repository.PlaceRepository; +import com.matzip.place.infra.repository.PlaceTagRepository; +import com.matzip.place.infra.repository.TagRepository; import com.matzip.user.domain.User; import com.matzip.user.infra.UserRepository; import com.matzip.common.infra.discord.DiscordWebhookSender; diff --git a/src/test/java/com/matzip/lottery/service/LotteryEventServiceGetEntryResultTest.java b/src/test/java/com/matzip/lottery/service/LotteryEventServiceGetEntryResultTest.java index 6830dbd..68304bd 100644 --- a/src/test/java/com/matzip/lottery/service/LotteryEventServiceGetEntryResultTest.java +++ b/src/test/java/com/matzip/lottery/service/LotteryEventServiceGetEntryResultTest.java @@ -2,7 +2,7 @@ import com.matzip.common.exception.BusinessException; import com.matzip.common.exception.code.ErrorCode; -import com.matzip.lottery.controller.response.EventEntryResultResponse; +import com.matzip.lottery.controller.response.EventEntryResultResponseDto; import com.matzip.lottery.domain.LotteryEvent; import com.matzip.lottery.domain.Prize; import com.matzip.lottery.domain.Winner; @@ -78,7 +78,7 @@ class GetEntryResultSuccess { BDDMockito.given(winnerContactRepository.findByUserIdAndEventId(anyLong(), anyLong())).willReturn(Optional.empty()); // when - EventEntryResultResponse result = lotteryEventService.getEntryResult(EVENT_ID, USER_ID); + EventEntryResultResponseDto result = lotteryEventService.getEntryResult(EVENT_ID, USER_ID); // then assertThat(result.eventId()).isEqualTo(EVENT_ID); @@ -103,7 +103,7 @@ class GetEntryResultSuccess { BDDMockito.given(winnerContactRepository.findByUserIdAndEventId(anyLong(), anyLong())).willReturn(Optional.empty()); // when - EventEntryResultResponse result = lotteryEventService.getEntryResult(EVENT_ID, USER_ID); + EventEntryResultResponseDto result = lotteryEventService.getEntryResult(EVENT_ID, USER_ID); // then assertThat(result.eventId()).isEqualTo(EVENT_ID); diff --git a/src/test/java/com/matzip/place/application/PlaceServiceCachingTest.java b/src/test/java/com/matzip/place/application/PlaceServiceCachingTest.java index 998aefd..b094a2e 100644 --- a/src/test/java/com/matzip/place/application/PlaceServiceCachingTest.java +++ b/src/test/java/com/matzip/place/application/PlaceServiceCachingTest.java @@ -12,7 +12,13 @@ import com.matzip.place.domain.entity.Category; import com.matzip.place.domain.Campus; import com.matzip.place.domain.PlaceStatus; -import com.matzip.place.infra.repository.*; +import com.matzip.place.infra.repository.CategoryRepository; +import com.matzip.place.infra.repository.MenuRepository; +import com.matzip.place.infra.repository.PhotoRepository; +import com.matzip.place.infra.repository.PlaceCategoryRepository; +import com.matzip.place.infra.repository.PlaceRepository; +import com.matzip.place.infra.repository.PlaceTagRepository; +import com.matzip.place.infra.repository.TagRepository; import com.matzip.user.infra.UserRepository; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; diff --git a/src/test/java/com/matzip/place/application/PlaceServiceTest.java b/src/test/java/com/matzip/place/application/PlaceServiceTest.java index 7ce711d..73612dd 100644 --- a/src/test/java/com/matzip/place/application/PlaceServiceTest.java +++ b/src/test/java/com/matzip/place/application/PlaceServiceTest.java @@ -9,7 +9,13 @@ import com.matzip.place.domain.entity.Category; import com.matzip.place.domain.entity.PlaceCategory; import com.matzip.place.infra.kakao.KakaoApiClient; -import com.matzip.place.infra.repository.*; +import com.matzip.place.infra.repository.CategoryRepository; +import com.matzip.place.infra.repository.MenuRepository; +import com.matzip.place.infra.repository.PhotoRepository; +import com.matzip.place.infra.repository.PlaceCategoryRepository; +import com.matzip.place.infra.repository.PlaceRepository; +import com.matzip.place.infra.repository.PlaceTagRepository; +import com.matzip.place.infra.repository.TagRepository; import com.matzip.user.infra.UserRepository; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; From e0796c4033e511abafe2018bc25859d2121f7a03 Mon Sep 17 00:00:00 2001 From: gihhyeon Date: Tue, 25 Aug 2026 21:08:16 +0900 Subject: [PATCH 07/24] =?UTF-8?q?refactor:=20place=20DTO=EB=A5=BC=20?= =?UTF-8?q?=EC=97=AD=ED=95=A0=EB=B3=84=20=EC=9C=84=EC=B9=98=EB=A1=9C=20?= =?UTF-8?q?=EC=9E=AC=EB=B0=B0=EC=B9=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../matzip/place/application/service/PlaceService.java | 8 ++++---- .../java/com/matzip/place/infra/kakao/KakaoApiClient.java | 6 +++--- .../java/com/matzip/place/infra/kakao/KakaoApiParser.java | 8 ++++---- .../MenuDto.java => infra/kakao/dto/KakaoMenuDto.java} | 4 ++-- .../matzip/place/application/PlaceServiceCachingTest.java | 4 ++-- 5 files changed, 15 insertions(+), 15 deletions(-) rename src/main/java/com/matzip/place/{dto/MenuDto.java => infra/kakao/dto/KakaoMenuDto.java} (66%) diff --git a/src/main/java/com/matzip/place/application/service/PlaceService.java b/src/main/java/com/matzip/place/application/service/PlaceService.java index 1c1ec91..b5646f8 100644 --- a/src/main/java/com/matzip/place/application/service/PlaceService.java +++ b/src/main/java/com/matzip/place/application/service/PlaceService.java @@ -1,7 +1,7 @@ package com.matzip.place.application.service; import com.matzip.place.dto.LocationDto; -import com.matzip.place.dto.MenuDto; +import com.matzip.place.infra.kakao.dto.KakaoMenuDto; import com.matzip.place.dto.PhotoDto; import com.matzip.place.domain.entity.Category; import com.matzip.place.domain.entity.Menu; @@ -89,9 +89,9 @@ public PlaceCheckResponseDto preview(PlaceCheckRequestDto req) { placeTempStore.put(cachedSnapshot); List menuItems = new ArrayList<>(); - List srcMenus = snap.menus(); + List srcMenus = snap.menus(); if (srcMenus != null) { - for (MenuDto m : srcMenus) { + for (KakaoMenuDto m : srcMenus) { MenuItem item = MenuItem.builder() .menuId(m.getMenuId()) .name(m.getName()) @@ -265,7 +265,7 @@ private void notifyPlaceRegistrationRequest(Place place) { private PlaceSnapshot createPlaceSnapshot(PanelSnapshot snap) { List sMenus = new ArrayList<>(); if (snap.menus() != null) { - for (MenuDto md : snap.menus()) { + for (KakaoMenuDto md : snap.menus()) { sMenus.add(new SMenu(md.getMenuId(), md.getName(), md.getPrice())); } } diff --git a/src/main/java/com/matzip/place/infra/kakao/KakaoApiClient.java b/src/main/java/com/matzip/place/infra/kakao/KakaoApiClient.java index c873aa6..c89cbe1 100644 --- a/src/main/java/com/matzip/place/infra/kakao/KakaoApiClient.java +++ b/src/main/java/com/matzip/place/infra/kakao/KakaoApiClient.java @@ -1,7 +1,7 @@ package com.matzip.place.infra.kakao; import com.fasterxml.jackson.databind.JsonNode; -import com.matzip.place.dto.MenuDto; +import com.matzip.place.infra.kakao.dto.KakaoMenuDto; import com.matzip.place.dto.PhotoDto; import com.matzip.common.exception.KakaoApiException; import com.matzip.common.exception.code.ErrorCode; @@ -77,7 +77,7 @@ public PanelSnapshot getPanelSnapshot(String kakaoPlaceId) { double longitude = KakaoApiParser.requireNumber(panel.at("/summary/point/lon"), "summary.point.lon"); // 2) ๋ฉ”๋‰ด/์‚ฌ์ง„ ์ถ”์ถœ - List menus = KakaoApiParser.extractMenus(panel); + List menus = KakaoApiParser.extractMenus(panel); List photos = KakaoApiParser.extractPhotos(panel); return new PanelSnapshot(confirmId, placeName, finalAddress, latitude, longitude, menus, photos); @@ -98,7 +98,7 @@ public record PanelSnapshot( String address, double latitude, double longitude, - List menus, + List menus, List photos ) {} diff --git a/src/main/java/com/matzip/place/infra/kakao/KakaoApiParser.java b/src/main/java/com/matzip/place/infra/kakao/KakaoApiParser.java index 8a49f8d..cd0b268 100644 --- a/src/main/java/com/matzip/place/infra/kakao/KakaoApiParser.java +++ b/src/main/java/com/matzip/place/infra/kakao/KakaoApiParser.java @@ -1,7 +1,7 @@ package com.matzip.place.infra.kakao; import com.fasterxml.jackson.databind.JsonNode; -import com.matzip.place.dto.MenuDto; +import com.matzip.place.infra.kakao.dto.KakaoMenuDto; import com.matzip.place.dto.PhotoDto; import com.matzip.common.exception.KakaoApiException; import com.matzip.common.exception.code.ErrorCode; @@ -17,8 +17,8 @@ public class KakaoApiParser { * panel3 ์‘๋‹ต์—์„œ ๋ฉ”๋‰ด ์ •๋ณด๋ฅผ ์ถ”์ถœ * /menu/menus/items ๊ฒฝ๋กœ์—์„œ ๋ฉ”๋‰ด ๋ฐ์ดํ„ฐ๋ฅผ ํŒŒ์‹ฑ */ - public static List extractMenus(JsonNode root) { - List list = new ArrayList<>(); + public static List extractMenus(JsonNode root) { + List list = new ArrayList<>(); JsonNode items = root.at("/menu/menus/items"); if (items != null && items.isArray()) { @@ -48,7 +48,7 @@ public static List extractMenus(JsonNode root) { price = parsePrice(priceText); } - list.add(MenuDto.builder() + list.add(KakaoMenuDto.builder() .menuId(productId) .name(name) .price(price) diff --git a/src/main/java/com/matzip/place/dto/MenuDto.java b/src/main/java/com/matzip/place/infra/kakao/dto/KakaoMenuDto.java similarity index 66% rename from src/main/java/com/matzip/place/dto/MenuDto.java rename to src/main/java/com/matzip/place/infra/kakao/dto/KakaoMenuDto.java index 0faad8f..4702a43 100644 --- a/src/main/java/com/matzip/place/dto/MenuDto.java +++ b/src/main/java/com/matzip/place/infra/kakao/dto/KakaoMenuDto.java @@ -1,11 +1,11 @@ -package com.matzip.place.dto; +package com.matzip.place.infra.kakao.dto; import lombok.Builder; import lombok.Getter; @Getter @Builder -public class MenuDto { +public class KakaoMenuDto { private Long menuId; private String name; private int price; diff --git a/src/test/java/com/matzip/place/application/PlaceServiceCachingTest.java b/src/test/java/com/matzip/place/application/PlaceServiceCachingTest.java index b094a2e..f80f091 100644 --- a/src/test/java/com/matzip/place/application/PlaceServiceCachingTest.java +++ b/src/test/java/com/matzip/place/application/PlaceServiceCachingTest.java @@ -1,7 +1,7 @@ package com.matzip.place.application; import com.matzip.common.infra.discord.DiscordWebhookSender; -import com.matzip.place.dto.MenuDto; +import com.matzip.place.infra.kakao.dto.KakaoMenuDto; import com.matzip.place.dto.PhotoDto; import com.matzip.place.application.service.PlaceService; import com.matzip.place.infra.kakao.KakaoApiClient; @@ -130,7 +130,7 @@ private KakaoApiClient.PanelSnapshot createMockPanelSnapshot() { "์ถฉ๋‚จ ์ฒœ์•ˆ์‹œ ์„œ๋ถ๊ตฌ ๋ถ€์„ฑ14๊ธธ 46 ์ง€๊ด‘๋นŒ๋”ฉ 1์ธต", 37.123456, 127.123456, - List.of(MenuDto.builder().menuId(1L).name("ํ…Œ์ŠคํŠธ ๋ฉ”๋‰ด").price(10000).build()), + List.of(KakaoMenuDto.builder().menuId(1L).name("ํ…Œ์ŠคํŠธ ๋ฉ”๋‰ด").price(10000).build()), List.of(PhotoDto.builder().photoId(1L).photoUrl("http://test.com/photo.jpg").displayOrder(1).build()) ); } From 7f17deea1812b58c4d67ff07d3dc147063ab7e2d Mon Sep 17 00:00:00 2001 From: gihhyeon Date: Thu, 27 Aug 2026 19:15:51 +0900 Subject: [PATCH 08/24] =?UTF-8?q?chore:=20PR=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= =?UTF-8?q?=20=EA=B2=80=EC=A6=9D=EC=9D=84=20=EC=9C=84=ED=95=9C=20CI=20?= =?UTF-8?q?=EC=9B=8C=ED=81=AC=ED=94=8C=EB=A1=9C=EC=9A=B0=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/ci.yml | 47 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..27f2a42 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,47 @@ +name: CI + +on: + pull_request: + branches: + - develop + - main + push: + branches: + - develop + +concurrency: + group: ci-${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + test: + runs-on: ubuntu-latest + + permissions: + contents: read + checks: write + pull-requests: write + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up JDK 17 + uses: actions/setup-java@v4 + with: + java-version: '17' + distribution: 'temurin' + cache: 'gradle' + + - name: Grant execute permission for gradlew + run: chmod +x ./gradlew + + - name: Run tests + run: ./gradlew test + + - name: Publish test report + uses: mikepenz/action-junit-report@v5 + if: always() + with: + report_paths: 'build/test-results/test/TEST-*.xml' + check_name: 'Test Report' From 2723b13ac78301339ecfd031a5570ed8181f0151 Mon Sep 17 00:00:00 2001 From: gihhyeon Date: Wed, 2 Sep 2026 19:56:51 +0900 Subject: [PATCH 09/24] =?UTF-8?q?refactor:=20place=20=EB=8F=84=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=EC=9D=84=20=EB=A0=88=EC=9D=B4=EC=96=B4=EB=93=9C=20?= =?UTF-8?q?=ED=91=9C=EC=A4=80=20=ED=8C=A8=ED=82=A4=EC=A7=80=EB=A1=9C=20?= =?UTF-8?q?=ED=86=B5=EC=9D=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/controller/AdminController.java | 2 +- .../event/RequestReviewEventListener.java | 2 +- .../AdminPlaceRegisterRequestService.java | 2 +- .../application/port/PlaceTempStore.java | 115 ------------------ .../matzip/place/client/PlaceSnapshot.java | 106 ++++++++++++++++ .../PlaceTempStoreMemory.java | 8 +- .../kakao/KakaoApiClient.java | 4 +- .../kakao/KakaoApiParser.java | 4 +- .../kakao/dto/KakaoMenuDto.java | 2 +- .../controller/CategoryController.java | 8 +- .../{api => }/controller/PlaceController.java | 18 +-- .../controller/PlaceLikeController.java | 8 +- .../controller/PlaceReadController.java | 12 +- .../controller/PlaceRequestController.java | 8 +- .../request/MapSearchRequestDto.java | 2 +- .../request/PlaceCheckRequestDto.java | 2 +- .../{api => dto}/request/PlaceRequestDto.java | 2 +- .../response/MapSearchResponseDto.java | 2 +- .../response/MenuResponseDto.java | 2 +- .../response/PlaceCheckResponseDto.java | 2 +- .../response/PlaceCommonResponseDto.java | 2 +- .../response/PlaceDetailResponseDto.java | 2 +- .../response/PlaceLikeResponseDto.java | 2 +- .../response/PlaceMenuSearchResponseDto.java | 2 +- .../response/PlaceRegisterResponseDto.java | 2 +- .../PlaceRegisterStatusDetailResponseDto.java | 2 +- .../PlaceRegisterStatusResponseDto.java | 2 +- .../response/PlaceSearchResponseDto.java | 2 +- .../repository/CategoryRepository.java | 2 +- .../repository/DailyViewCountRepository.java | 2 +- .../repository/MenuRepository.java | 2 +- .../repository/PhotoRepository.java | 2 +- .../repository/PlaceCategoryRepository.java | 2 +- .../repository/PlaceLikeRepository.java | 2 +- .../repository/PlaceRepository.java | 2 +- .../repository/PlaceTagRepository.java | 2 +- .../{infra => }/repository/TagRepository.java | 2 +- .../service/CategoryService.java | 4 +- .../service/PlaceLikeService.java | 14 +-- .../service/PlaceReadService.java | 34 +++--- .../service/PlaceService.java | 42 +++---- .../service/ViewCountService.java | 6 +- .../matzip/AbstractMatzipApplicationTest.java | 2 +- .../application/PlaceReadServiceTest.java | 6 +- .../application/PlaceServiceCachingTest.java | 41 ++++--- .../place/application/PlaceServiceTest.java | 33 ++--- 46 files changed, 258 insertions(+), 269 deletions(-) delete mode 100644 src/main/java/com/matzip/place/application/port/PlaceTempStore.java create mode 100644 src/main/java/com/matzip/place/client/PlaceSnapshot.java rename src/main/java/com/matzip/place/{infra/cache => client}/PlaceTempStoreMemory.java (91%) rename src/main/java/com/matzip/place/{infra => client}/kakao/KakaoApiClient.java (97%) rename src/main/java/com/matzip/place/{infra => client}/kakao/KakaoApiParser.java (98%) rename src/main/java/com/matzip/place/{infra => client}/kakao/dto/KakaoMenuDto.java (79%) rename src/main/java/com/matzip/place/{api => }/controller/CategoryController.java (84%) rename src/main/java/com/matzip/place/{api => }/controller/PlaceController.java (79%) rename src/main/java/com/matzip/place/{api => }/controller/PlaceLikeController.java (87%) rename src/main/java/com/matzip/place/{api => }/controller/PlaceReadController.java (82%) rename src/main/java/com/matzip/place/{api => }/controller/PlaceRequestController.java (89%) rename src/main/java/com/matzip/place/{api => dto}/request/MapSearchRequestDto.java (93%) rename src/main/java/com/matzip/place/{api => dto}/request/PlaceCheckRequestDto.java (87%) rename src/main/java/com/matzip/place/{api => dto}/request/PlaceRequestDto.java (97%) rename src/main/java/com/matzip/place/{api => dto}/response/MapSearchResponseDto.java (97%) rename src/main/java/com/matzip/place/{api => dto}/response/MenuResponseDto.java (94%) rename src/main/java/com/matzip/place/{api => dto}/response/PlaceCheckResponseDto.java (95%) rename src/main/java/com/matzip/place/{api => dto}/response/PlaceCommonResponseDto.java (97%) rename src/main/java/com/matzip/place/{api => dto}/response/PlaceDetailResponseDto.java (98%) rename src/main/java/com/matzip/place/{api => dto}/response/PlaceLikeResponseDto.java (94%) rename src/main/java/com/matzip/place/{api => dto}/response/PlaceMenuSearchResponseDto.java (93%) rename src/main/java/com/matzip/place/{api => dto}/response/PlaceRegisterResponseDto.java (96%) rename src/main/java/com/matzip/place/{api => dto}/response/PlaceRegisterStatusDetailResponseDto.java (98%) rename src/main/java/com/matzip/place/{api => dto}/response/PlaceRegisterStatusResponseDto.java (96%) rename src/main/java/com/matzip/place/{api => dto}/response/PlaceSearchResponseDto.java (92%) rename src/main/java/com/matzip/place/{infra => }/repository/CategoryRepository.java (81%) rename src/main/java/com/matzip/place/{infra => }/repository/DailyViewCountRepository.java (96%) rename src/main/java/com/matzip/place/{infra => }/repository/MenuRepository.java (94%) rename src/main/java/com/matzip/place/{infra => }/repository/PhotoRepository.java (93%) rename src/main/java/com/matzip/place/{infra => }/repository/PlaceCategoryRepository.java (95%) rename src/main/java/com/matzip/place/{infra => }/repository/PlaceLikeRepository.java (95%) rename src/main/java/com/matzip/place/{infra => }/repository/PlaceRepository.java (98%) rename src/main/java/com/matzip/place/{infra => }/repository/PlaceTagRepository.java (94%) rename src/main/java/com/matzip/place/{infra => }/repository/TagRepository.java (80%) rename src/main/java/com/matzip/place/{application => }/service/CategoryService.java (84%) rename src/main/java/com/matzip/place/{application => }/service/PlaceLikeService.java (90%) rename src/main/java/com/matzip/place/{application => }/service/PlaceReadService.java (92%) rename src/main/java/com/matzip/place/{application => }/service/PlaceService.java (90%) rename src/main/java/com/matzip/place/{application => }/service/ViewCountService.java (87%) diff --git a/src/main/java/com/matzip/admin/controller/AdminController.java b/src/main/java/com/matzip/admin/controller/AdminController.java index a93718b..ba7162b 100644 --- a/src/main/java/com/matzip/admin/controller/AdminController.java +++ b/src/main/java/com/matzip/admin/controller/AdminController.java @@ -8,7 +8,7 @@ import com.matzip.common.exception.code.ErrorCode; import com.matzip.common.response.ApiResponse; // import com.matzip.common.security.UserPrincipal; -import com.matzip.place.infra.repository.PlaceRepository; +import com.matzip.place.repository.PlaceRepository; // import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; diff --git a/src/main/java/com/matzip/admin/event/RequestReviewEventListener.java b/src/main/java/com/matzip/admin/event/RequestReviewEventListener.java index 21b8cc8..d464a68 100644 --- a/src/main/java/com/matzip/admin/event/RequestReviewEventListener.java +++ b/src/main/java/com/matzip/admin/event/RequestReviewEventListener.java @@ -4,7 +4,7 @@ import com.matzip.common.exception.code.ErrorCode; import com.matzip.lottery.service.LotteryEventService; import com.matzip.place.domain.entity.Place; -import com.matzip.place.infra.repository.PlaceRepository; +import com.matzip.place.repository.PlaceRepository; import com.matzip.user.domain.User; import lombok.extern.slf4j.Slf4j; import org.springframework.scheduling.annotation.Async; diff --git a/src/main/java/com/matzip/admin/service/AdminPlaceRegisterRequestService.java b/src/main/java/com/matzip/admin/service/AdminPlaceRegisterRequestService.java index 21f932f..e32c24a 100644 --- a/src/main/java/com/matzip/admin/service/AdminPlaceRegisterRequestService.java +++ b/src/main/java/com/matzip/admin/service/AdminPlaceRegisterRequestService.java @@ -8,7 +8,7 @@ import com.matzip.common.exception.code.ErrorCode; import com.matzip.place.domain.PlaceStatus; import com.matzip.place.domain.entity.Place; -import com.matzip.place.infra.repository.PlaceRepository; +import com.matzip.place.repository.PlaceRepository; import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; diff --git a/src/main/java/com/matzip/place/application/port/PlaceTempStore.java b/src/main/java/com/matzip/place/application/port/PlaceTempStore.java deleted file mode 100644 index a7a5eac..0000000 --- a/src/main/java/com/matzip/place/application/port/PlaceTempStore.java +++ /dev/null @@ -1,115 +0,0 @@ -package com.matzip.place.application.port; - -import java.util.List; - -/** - * ์ž„์‹œ ์Šค๋ƒ…์ƒท ์ €์žฅ์†Œ Port - */ -public interface PlaceTempStore { - - void put(PlaceSnapshot snapshot); - - PlaceSnapshot findById(String kakaoPlaceId); - - void remove(String kakaoPlaceId); - - final class PlaceSnapshot { - - private final String kakaoPlaceId; - private final String placeName; - private final String address; - private final double latitude; - private final double longitude; - - private final List menus; // ํ”„๋ฆฌ๋ทฐ ๋‹น์‹œ ๋ฉ”๋‰ด ์Šค๋ƒ…์ƒท - private final List photos; // ํ”„๋ฆฌ๋ทฐ ๋‹น์‹œ ์‚ฌ์ง„ ์Šค๋ƒ…์ƒท - - public PlaceSnapshot( - String kakaoPlaceId, - String placeName, - String address, - double latitude, - double longitude, - List menus, - List photos - ) { - // ํ•„์ˆ˜ ๊ฐ’ ๊ฒ€์ฆ. ์ƒ์„ธ ๊ฒ€์ฆ์€ ์ƒ์œ„ ์„œ๋น„์Šค์—์„œ ์ˆ˜ํ–‰ - if (kakaoPlaceId == null || kakaoPlaceId.isBlank()) { - throw new IllegalArgumentException("kakaoPlaceId๋Š” ๋น„์–ด ์žˆ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค."); - } - if (placeName == null || placeName.isBlank()) { - throw new IllegalArgumentException("placeName์€ ๋น„์–ด ์žˆ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค."); - } - if (address == null || address.isBlank()) { - throw new IllegalArgumentException("address๋Š” ๋น„์–ด ์žˆ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค."); - } - this.kakaoPlaceId = kakaoPlaceId; - this.placeName = placeName; - this.address = address; - this.latitude = latitude; - this.longitude = longitude; - // NPE ๋ฐฉ์ง€: ๋ถˆ๋ณ€ ๋ฆฌ์ŠคํŠธ ๋ณด์žฅ(์—ฌ๊ธฐ์„œ๋Š” null์ด๋ฉด ๋นˆ ๋ฆฌ์ŠคํŠธ๋กœ ๋Œ€์ฒด) - this.menus = (menus == null) ? List.of() : menus; - this.photos = (photos == null) ? List.of() : photos; - } - - public String getKakaoPlaceId() { return kakaoPlaceId; } - public String getPlaceName() { return placeName; } - public String getAddress() { return address; } - public double getLatitude() { return latitude; } - public double getLongitude() { return longitude; } - public List getMenus() { return menus; } - public List getPhotos() { return photos; } - - - public static final class SMenu { - private final Long menuId; - private final String name; - private final int price; - - public SMenu(Long menuId, String name, int price) { - if (name == null || name.isBlank()) { - throw new IllegalArgumentException("๋ฉ”๋‰ด ์ด๋ฆ„์€ ๋น„์–ด ์žˆ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค."); - } - if (price < 0) { - throw new IllegalArgumentException("๋ฉ”๋‰ด ๊ฐ€๊ฒฉ์€ ์Œ์ˆ˜์ผ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค."); - } - this.menuId = menuId; - this.name = name; - this.price = price; - } - - public Long getMenuId() { - return menuId; - } - - public String getName() { - return name; - } - - public int getPrice() { - return price; - } - } - - - public static final class SPhoto { - private final Long photoId; // ์™ธ๋ถ€์—์„œ ์‹๋ณ„์šฉ์œผ๋กœ ์ œ๊ณต๋˜๋ฉด ์‚ฌ์šฉ(์—†์œผ๋ฉด null) - private final String photoUrl; // ํ•„์ˆ˜ - private final int displayOrder; - - public SPhoto(Long photoId, String photoUrl, int displayOrder) { - if (photoUrl == null || photoUrl.isBlank()) { - throw new IllegalArgumentException("photoUrl์€ ๋น„์–ด ์žˆ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค."); - } - this.photoId = photoId; - this.photoUrl = photoUrl; - this.displayOrder = displayOrder; - } - - public Long getPhotoId() { return photoId; } - public String getPhotoUrl() { return photoUrl; } - public int getDisplayOrder() { return displayOrder; } - } - } -} diff --git a/src/main/java/com/matzip/place/client/PlaceSnapshot.java b/src/main/java/com/matzip/place/client/PlaceSnapshot.java new file mode 100644 index 0000000..c9d7456 --- /dev/null +++ b/src/main/java/com/matzip/place/client/PlaceSnapshot.java @@ -0,0 +1,106 @@ +package com.matzip.place.client; + +import java.util.List; + +/** + * ์ž„์‹œ ์Šค๋ƒ…์ƒท ๋ฐ์ดํ„ฐ. ํ”„๋ฆฌ๋ทฐ ์‹œ์ ์˜ ๋ง›์ง‘ ์ •๋ณด๋ฅผ ์ž„์‹œ ์ €์žฅ์†Œ์— ๋‹ด์„ ๋•Œ ์‚ฌ์šฉ. + */ +public final class PlaceSnapshot { + + private final String kakaoPlaceId; + private final String placeName; + private final String address; + private final double latitude; + private final double longitude; + + private final List menus; // ํ”„๋ฆฌ๋ทฐ ๋‹น์‹œ ๋ฉ”๋‰ด ์Šค๋ƒ…์ƒท + private final List photos; // ํ”„๋ฆฌ๋ทฐ ๋‹น์‹œ ์‚ฌ์ง„ ์Šค๋ƒ…์ƒท + + public PlaceSnapshot( + String kakaoPlaceId, + String placeName, + String address, + double latitude, + double longitude, + List menus, + List photos + ) { + // ํ•„์ˆ˜ ๊ฐ’ ๊ฒ€์ฆ. ์ƒ์„ธ ๊ฒ€์ฆ์€ ์ƒ์œ„ ์„œ๋น„์Šค์—์„œ ์ˆ˜ํ–‰ + if (kakaoPlaceId == null || kakaoPlaceId.isBlank()) { + throw new IllegalArgumentException("kakaoPlaceId๋Š” ๋น„์–ด ์žˆ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค."); + } + if (placeName == null || placeName.isBlank()) { + throw new IllegalArgumentException("placeName์€ ๋น„์–ด ์žˆ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค."); + } + if (address == null || address.isBlank()) { + throw new IllegalArgumentException("address๋Š” ๋น„์–ด ์žˆ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค."); + } + this.kakaoPlaceId = kakaoPlaceId; + this.placeName = placeName; + this.address = address; + this.latitude = latitude; + this.longitude = longitude; + // NPE ๋ฐฉ์ง€: ๋ถˆ๋ณ€ ๋ฆฌ์ŠคํŠธ ๋ณด์žฅ(์—ฌ๊ธฐ์„œ๋Š” null์ด๋ฉด ๋นˆ ๋ฆฌ์ŠคํŠธ๋กœ ๋Œ€์ฒด) + this.menus = (menus == null) ? List.of() : menus; + this.photos = (photos == null) ? List.of() : photos; + } + + public String getKakaoPlaceId() { return kakaoPlaceId; } + public String getPlaceName() { return placeName; } + public String getAddress() { return address; } + public double getLatitude() { return latitude; } + public double getLongitude() { return longitude; } + public List getMenus() { return menus; } + public List getPhotos() { return photos; } + + + public static final class SMenu { + private final Long menuId; + private final String name; + private final int price; + + public SMenu(Long menuId, String name, int price) { + if (name == null || name.isBlank()) { + throw new IllegalArgumentException("๋ฉ”๋‰ด ์ด๋ฆ„์€ ๋น„์–ด ์žˆ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค."); + } + if (price < 0) { + throw new IllegalArgumentException("๋ฉ”๋‰ด ๊ฐ€๊ฒฉ์€ ์Œ์ˆ˜์ผ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค."); + } + this.menuId = menuId; + this.name = name; + this.price = price; + } + + public Long getMenuId() { + return menuId; + } + + public String getName() { + return name; + } + + public int getPrice() { + return price; + } + } + + + public static final class SPhoto { + private final Long photoId; // ์™ธ๋ถ€์—์„œ ์‹๋ณ„์šฉ์œผ๋กœ ์ œ๊ณต๋˜๋ฉด ์‚ฌ์šฉ(์—†์œผ๋ฉด null) + private final String photoUrl; // ํ•„์ˆ˜ + private final int displayOrder; + + public SPhoto(Long photoId, String photoUrl, int displayOrder) { + if (photoUrl == null || photoUrl.isBlank()) { + throw new IllegalArgumentException("photoUrl์€ ๋น„์–ด ์žˆ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค."); + } + this.photoId = photoId; + this.photoUrl = photoUrl; + this.displayOrder = displayOrder; + } + + public Long getPhotoId() { return photoId; } + public String getPhotoUrl() { return photoUrl; } + public int getDisplayOrder() { return displayOrder; } + } +} diff --git a/src/main/java/com/matzip/place/infra/cache/PlaceTempStoreMemory.java b/src/main/java/com/matzip/place/client/PlaceTempStoreMemory.java similarity index 91% rename from src/main/java/com/matzip/place/infra/cache/PlaceTempStoreMemory.java rename to src/main/java/com/matzip/place/client/PlaceTempStoreMemory.java index 1fb6583..1ddf555 100644 --- a/src/main/java/com/matzip/place/infra/cache/PlaceTempStoreMemory.java +++ b/src/main/java/com/matzip/place/client/PlaceTempStoreMemory.java @@ -1,6 +1,5 @@ -package com.matzip.place.infra.cache; +package com.matzip.place.client; -import com.matzip.place.application.port.PlaceTempStore; import org.springframework.stereotype.Component; import java.time.Duration; @@ -14,14 +13,13 @@ * Todo ์šด์˜ ํ™˜๊ฒฝ์—์„  Redis?? */ @Component -public class PlaceTempStoreMemory implements PlaceTempStore { +public class PlaceTempStoreMemory { private static final Duration TTL = Duration.ofMinutes(10); // key: kakaoPlaceId private final Map store = new ConcurrentHashMap<>(); - @Override public void put(PlaceSnapshot snapshot) { if (snapshot == null || snapshot.getKakaoPlaceId() == null || snapshot.getKakaoPlaceId().isBlank()) { throw new IllegalArgumentException("snapshot ๋˜๋Š” kakaoPlaceId๊ฐ€ ์œ ํšจํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค."); @@ -31,7 +29,6 @@ public void put(PlaceSnapshot snapshot) { store.put(snapshot.getKakaoPlaceId(), new Entry(snapshot, expireAt)); } - @Override public PlaceSnapshot findById(String kakaoPlaceId) { if (kakaoPlaceId == null || kakaoPlaceId.isBlank()) { return null; @@ -48,7 +45,6 @@ public PlaceSnapshot findById(String kakaoPlaceId) { return e.snapshot; } - @Override public void remove(String kakaoPlaceId) { if (kakaoPlaceId != null) { store.remove(kakaoPlaceId); diff --git a/src/main/java/com/matzip/place/infra/kakao/KakaoApiClient.java b/src/main/java/com/matzip/place/client/kakao/KakaoApiClient.java similarity index 97% rename from src/main/java/com/matzip/place/infra/kakao/KakaoApiClient.java rename to src/main/java/com/matzip/place/client/kakao/KakaoApiClient.java index c89cbe1..a695a3b 100644 --- a/src/main/java/com/matzip/place/infra/kakao/KakaoApiClient.java +++ b/src/main/java/com/matzip/place/client/kakao/KakaoApiClient.java @@ -1,7 +1,7 @@ -package com.matzip.place.infra.kakao; +package com.matzip.place.client.kakao; import com.fasterxml.jackson.databind.JsonNode; -import com.matzip.place.infra.kakao.dto.KakaoMenuDto; +import com.matzip.place.client.kakao.dto.KakaoMenuDto; import com.matzip.place.dto.PhotoDto; import com.matzip.common.exception.KakaoApiException; import com.matzip.common.exception.code.ErrorCode; diff --git a/src/main/java/com/matzip/place/infra/kakao/KakaoApiParser.java b/src/main/java/com/matzip/place/client/kakao/KakaoApiParser.java similarity index 98% rename from src/main/java/com/matzip/place/infra/kakao/KakaoApiParser.java rename to src/main/java/com/matzip/place/client/kakao/KakaoApiParser.java index cd0b268..b1e9d4b 100644 --- a/src/main/java/com/matzip/place/infra/kakao/KakaoApiParser.java +++ b/src/main/java/com/matzip/place/client/kakao/KakaoApiParser.java @@ -1,7 +1,7 @@ -package com.matzip.place.infra.kakao; +package com.matzip.place.client.kakao; import com.fasterxml.jackson.databind.JsonNode; -import com.matzip.place.infra.kakao.dto.KakaoMenuDto; +import com.matzip.place.client.kakao.dto.KakaoMenuDto; import com.matzip.place.dto.PhotoDto; import com.matzip.common.exception.KakaoApiException; import com.matzip.common.exception.code.ErrorCode; diff --git a/src/main/java/com/matzip/place/infra/kakao/dto/KakaoMenuDto.java b/src/main/java/com/matzip/place/client/kakao/dto/KakaoMenuDto.java similarity index 79% rename from src/main/java/com/matzip/place/infra/kakao/dto/KakaoMenuDto.java rename to src/main/java/com/matzip/place/client/kakao/dto/KakaoMenuDto.java index 4702a43..eacdeb0 100644 --- a/src/main/java/com/matzip/place/infra/kakao/dto/KakaoMenuDto.java +++ b/src/main/java/com/matzip/place/client/kakao/dto/KakaoMenuDto.java @@ -1,4 +1,4 @@ -package com.matzip.place.infra.kakao.dto; +package com.matzip.place.client.kakao.dto; import lombok.Builder; import lombok.Getter; diff --git a/src/main/java/com/matzip/place/api/controller/CategoryController.java b/src/main/java/com/matzip/place/controller/CategoryController.java similarity index 84% rename from src/main/java/com/matzip/place/api/controller/CategoryController.java rename to src/main/java/com/matzip/place/controller/CategoryController.java index fcf4670..36bfdb7 100644 --- a/src/main/java/com/matzip/place/api/controller/CategoryController.java +++ b/src/main/java/com/matzip/place/controller/CategoryController.java @@ -1,12 +1,12 @@ -package com.matzip.place.api.controller; +package com.matzip.place.controller; import com.matzip.common.response.ApiResponse; -import com.matzip.place.api.response.PlaceCommonResponseDto; -import com.matzip.place.application.service.PlaceReadService; +import com.matzip.place.dto.response.PlaceCommonResponseDto; +import com.matzip.place.service.PlaceReadService; import com.matzip.place.domain.Campus; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; -import com.matzip.place.application.service.CategoryService; +import com.matzip.place.service.CategoryService; import com.matzip.place.dto.CategoryDto; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; diff --git a/src/main/java/com/matzip/place/api/controller/PlaceController.java b/src/main/java/com/matzip/place/controller/PlaceController.java similarity index 79% rename from src/main/java/com/matzip/place/api/controller/PlaceController.java rename to src/main/java/com/matzip/place/controller/PlaceController.java index 51b7a7b..2d7188d 100644 --- a/src/main/java/com/matzip/place/api/controller/PlaceController.java +++ b/src/main/java/com/matzip/place/controller/PlaceController.java @@ -1,15 +1,15 @@ -package com.matzip.place.api.controller; +package com.matzip.place.controller; import com.matzip.common.response.ApiResponse; import com.matzip.common.security.UserPrincipal; -import com.matzip.place.api.request.PlaceCheckRequestDto; -import com.matzip.place.api.request.PlaceRequestDto; -import com.matzip.place.api.response.PlaceCheckResponseDto; -import com.matzip.place.api.response.PlaceRegisterResponseDto; -import com.matzip.place.api.response.PlaceMenuSearchResponseDto; -import com.matzip.place.api.response.PlaceSearchResponseDto; -import com.matzip.place.application.service.PlaceReadService; -import com.matzip.place.application.service.PlaceService; +import com.matzip.place.dto.request.PlaceCheckRequestDto; +import com.matzip.place.dto.request.PlaceRequestDto; +import com.matzip.place.dto.response.PlaceCheckResponseDto; +import com.matzip.place.dto.response.PlaceRegisterResponseDto; +import com.matzip.place.dto.response.PlaceMenuSearchResponseDto; +import com.matzip.place.dto.response.PlaceSearchResponseDto; +import com.matzip.place.service.PlaceReadService; +import com.matzip.place.service.PlaceService; import com.matzip.place.domain.Campus; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; diff --git a/src/main/java/com/matzip/place/api/controller/PlaceLikeController.java b/src/main/java/com/matzip/place/controller/PlaceLikeController.java similarity index 87% rename from src/main/java/com/matzip/place/api/controller/PlaceLikeController.java rename to src/main/java/com/matzip/place/controller/PlaceLikeController.java index d43b2d5..9043057 100644 --- a/src/main/java/com/matzip/place/api/controller/PlaceLikeController.java +++ b/src/main/java/com/matzip/place/controller/PlaceLikeController.java @@ -1,10 +1,10 @@ -package com.matzip.place.api.controller; +package com.matzip.place.controller; import com.matzip.common.response.ApiResponse; import com.matzip.common.security.UserPrincipal; -import com.matzip.place.api.response.PlaceLikeResponseDto; -import com.matzip.place.api.response.PlaceCommonResponseDto; -import com.matzip.place.application.service.PlaceLikeService; +import com.matzip.place.dto.response.PlaceLikeResponseDto; +import com.matzip.place.dto.response.PlaceCommonResponseDto; +import com.matzip.place.service.PlaceLikeService; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.RestController; import org.springframework.security.core.annotation.AuthenticationPrincipal; diff --git a/src/main/java/com/matzip/place/api/controller/PlaceReadController.java b/src/main/java/com/matzip/place/controller/PlaceReadController.java similarity index 82% rename from src/main/java/com/matzip/place/api/controller/PlaceReadController.java rename to src/main/java/com/matzip/place/controller/PlaceReadController.java index 6339af9..281a451 100644 --- a/src/main/java/com/matzip/place/api/controller/PlaceReadController.java +++ b/src/main/java/com/matzip/place/controller/PlaceReadController.java @@ -1,13 +1,13 @@ -package com.matzip.place.api.controller; +package com.matzip.place.controller; import com.matzip.common.response.ApiResponse; import com.matzip.common.security.UserPrincipal; -import com.matzip.place.api.request.MapSearchRequestDto; -import com.matzip.place.api.response.PlaceCommonResponseDto; +import com.matzip.place.dto.request.MapSearchRequestDto; +import com.matzip.place.dto.response.PlaceCommonResponseDto; import jakarta.validation.Valid; -import com.matzip.place.api.response.MapSearchResponseDto; -import com.matzip.place.api.response.PlaceDetailResponseDto; -import com.matzip.place.application.service.PlaceReadService; +import com.matzip.place.dto.response.MapSearchResponseDto; +import com.matzip.place.dto.response.PlaceDetailResponseDto; +import com.matzip.place.service.PlaceReadService; import com.matzip.place.domain.Campus; import com.matzip.place.domain.SortType; import lombok.RequiredArgsConstructor; diff --git a/src/main/java/com/matzip/place/api/controller/PlaceRequestController.java b/src/main/java/com/matzip/place/controller/PlaceRequestController.java similarity index 89% rename from src/main/java/com/matzip/place/api/controller/PlaceRequestController.java rename to src/main/java/com/matzip/place/controller/PlaceRequestController.java index 22dad71..3821c37 100644 --- a/src/main/java/com/matzip/place/api/controller/PlaceRequestController.java +++ b/src/main/java/com/matzip/place/controller/PlaceRequestController.java @@ -1,13 +1,13 @@ -package com.matzip.place.api.controller; +package com.matzip.place.controller; import com.matzip.admin.controller.response.PlaceRegisterRequestDetailResponseDto; import com.matzip.common.exception.BusinessException; import com.matzip.common.exception.code.ErrorCode; import com.matzip.common.response.ApiResponse; import com.matzip.common.security.UserPrincipal; -import com.matzip.place.api.response.PlaceRegisterStatusDetailResponseDto; -import com.matzip.place.api.response.PlaceRegisterStatusResponseDto; -import com.matzip.place.application.service.PlaceReadService; +import com.matzip.place.dto.response.PlaceRegisterStatusDetailResponseDto; +import com.matzip.place.dto.response.PlaceRegisterStatusResponseDto; +import com.matzip.place.service.PlaceReadService; import lombok.RequiredArgsConstructor; import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.web.bind.annotation.GetMapping; diff --git a/src/main/java/com/matzip/place/api/request/MapSearchRequestDto.java b/src/main/java/com/matzip/place/dto/request/MapSearchRequestDto.java similarity index 93% rename from src/main/java/com/matzip/place/api/request/MapSearchRequestDto.java rename to src/main/java/com/matzip/place/dto/request/MapSearchRequestDto.java index b3c18cd..9d57208 100644 --- a/src/main/java/com/matzip/place/api/request/MapSearchRequestDto.java +++ b/src/main/java/com/matzip/place/dto/request/MapSearchRequestDto.java @@ -1,4 +1,4 @@ -package com.matzip.place.api.request; +package com.matzip.place.dto.request; import jakarta.validation.constraints.NotNull; import lombok.Getter; diff --git a/src/main/java/com/matzip/place/api/request/PlaceCheckRequestDto.java b/src/main/java/com/matzip/place/dto/request/PlaceCheckRequestDto.java similarity index 87% rename from src/main/java/com/matzip/place/api/request/PlaceCheckRequestDto.java rename to src/main/java/com/matzip/place/dto/request/PlaceCheckRequestDto.java index 74d03a7..277fa19 100644 --- a/src/main/java/com/matzip/place/api/request/PlaceCheckRequestDto.java +++ b/src/main/java/com/matzip/place/dto/request/PlaceCheckRequestDto.java @@ -1,4 +1,4 @@ -package com.matzip.place.api.request; +package com.matzip.place.dto.request; import jakarta.validation.constraints.NotNull; import lombok.Getter; diff --git a/src/main/java/com/matzip/place/api/request/PlaceRequestDto.java b/src/main/java/com/matzip/place/dto/request/PlaceRequestDto.java similarity index 97% rename from src/main/java/com/matzip/place/api/request/PlaceRequestDto.java rename to src/main/java/com/matzip/place/dto/request/PlaceRequestDto.java index d7bed6d..aa8c4d3 100644 --- a/src/main/java/com/matzip/place/api/request/PlaceRequestDto.java +++ b/src/main/java/com/matzip/place/dto/request/PlaceRequestDto.java @@ -1,4 +1,4 @@ -package com.matzip.place.api.request; +package com.matzip.place.dto.request; import com.matzip.place.domain.Campus; import jakarta.validation.constraints.*; diff --git a/src/main/java/com/matzip/place/api/response/MapSearchResponseDto.java b/src/main/java/com/matzip/place/dto/response/MapSearchResponseDto.java similarity index 97% rename from src/main/java/com/matzip/place/api/response/MapSearchResponseDto.java rename to src/main/java/com/matzip/place/dto/response/MapSearchResponseDto.java index 9e57104..12b640c 100644 --- a/src/main/java/com/matzip/place/api/response/MapSearchResponseDto.java +++ b/src/main/java/com/matzip/place/dto/response/MapSearchResponseDto.java @@ -1,4 +1,4 @@ -package com.matzip.place.api.response; +package com.matzip.place.dto.response; import com.matzip.place.dto.CategoryDto; import com.matzip.place.dto.LocationDto; diff --git a/src/main/java/com/matzip/place/api/response/MenuResponseDto.java b/src/main/java/com/matzip/place/dto/response/MenuResponseDto.java similarity index 94% rename from src/main/java/com/matzip/place/api/response/MenuResponseDto.java rename to src/main/java/com/matzip/place/dto/response/MenuResponseDto.java index 6d65fe8..c5d99cc 100644 --- a/src/main/java/com/matzip/place/api/response/MenuResponseDto.java +++ b/src/main/java/com/matzip/place/dto/response/MenuResponseDto.java @@ -1,4 +1,4 @@ -package com.matzip.place.api.response; +package com.matzip.place.dto.response; import com.fasterxml.jackson.annotation.JsonProperty; import com.matzip.place.domain.entity.Menu; diff --git a/src/main/java/com/matzip/place/api/response/PlaceCheckResponseDto.java b/src/main/java/com/matzip/place/dto/response/PlaceCheckResponseDto.java similarity index 95% rename from src/main/java/com/matzip/place/api/response/PlaceCheckResponseDto.java rename to src/main/java/com/matzip/place/dto/response/PlaceCheckResponseDto.java index cb00793..35461fb 100644 --- a/src/main/java/com/matzip/place/api/response/PlaceCheckResponseDto.java +++ b/src/main/java/com/matzip/place/dto/response/PlaceCheckResponseDto.java @@ -1,4 +1,4 @@ -package com.matzip.place.api.response; +package com.matzip.place.dto.response; import com.fasterxml.jackson.annotation.JsonProperty; import com.matzip.place.dto.LocationDto; diff --git a/src/main/java/com/matzip/place/api/response/PlaceCommonResponseDto.java b/src/main/java/com/matzip/place/dto/response/PlaceCommonResponseDto.java similarity index 97% rename from src/main/java/com/matzip/place/api/response/PlaceCommonResponseDto.java rename to src/main/java/com/matzip/place/dto/response/PlaceCommonResponseDto.java index b421304..ba462bd 100644 --- a/src/main/java/com/matzip/place/api/response/PlaceCommonResponseDto.java +++ b/src/main/java/com/matzip/place/dto/response/PlaceCommonResponseDto.java @@ -1,4 +1,4 @@ -package com.matzip.place.api.response; +package com.matzip.place.dto.response; import com.matzip.place.dto.CategoryDto; import com.matzip.place.dto.TagDto; diff --git a/src/main/java/com/matzip/place/api/response/PlaceDetailResponseDto.java b/src/main/java/com/matzip/place/dto/response/PlaceDetailResponseDto.java similarity index 98% rename from src/main/java/com/matzip/place/api/response/PlaceDetailResponseDto.java rename to src/main/java/com/matzip/place/dto/response/PlaceDetailResponseDto.java index 95f6412..17f0235 100644 --- a/src/main/java/com/matzip/place/api/response/PlaceDetailResponseDto.java +++ b/src/main/java/com/matzip/place/dto/response/PlaceDetailResponseDto.java @@ -1,4 +1,4 @@ -package com.matzip.place.api.response; +package com.matzip.place.dto.response; import com.fasterxml.jackson.annotation.JsonProperty; import com.matzip.place.domain.entity.Category; diff --git a/src/main/java/com/matzip/place/api/response/PlaceLikeResponseDto.java b/src/main/java/com/matzip/place/dto/response/PlaceLikeResponseDto.java similarity index 94% rename from src/main/java/com/matzip/place/api/response/PlaceLikeResponseDto.java rename to src/main/java/com/matzip/place/dto/response/PlaceLikeResponseDto.java index 61c8dc5..8219c9d 100644 --- a/src/main/java/com/matzip/place/api/response/PlaceLikeResponseDto.java +++ b/src/main/java/com/matzip/place/dto/response/PlaceLikeResponseDto.java @@ -1,4 +1,4 @@ -package com.matzip.place.api.response; +package com.matzip.place.dto.response; import lombok.Builder; import lombok.Getter; diff --git a/src/main/java/com/matzip/place/api/response/PlaceMenuSearchResponseDto.java b/src/main/java/com/matzip/place/dto/response/PlaceMenuSearchResponseDto.java similarity index 93% rename from src/main/java/com/matzip/place/api/response/PlaceMenuSearchResponseDto.java rename to src/main/java/com/matzip/place/dto/response/PlaceMenuSearchResponseDto.java index b98e5d6..108577b 100644 --- a/src/main/java/com/matzip/place/api/response/PlaceMenuSearchResponseDto.java +++ b/src/main/java/com/matzip/place/dto/response/PlaceMenuSearchResponseDto.java @@ -1,4 +1,4 @@ -package com.matzip.place.api.response; +package com.matzip.place.dto.response; import com.matzip.place.domain.entity.Menu; import lombok.Builder; diff --git a/src/main/java/com/matzip/place/api/response/PlaceRegisterResponseDto.java b/src/main/java/com/matzip/place/dto/response/PlaceRegisterResponseDto.java similarity index 96% rename from src/main/java/com/matzip/place/api/response/PlaceRegisterResponseDto.java rename to src/main/java/com/matzip/place/dto/response/PlaceRegisterResponseDto.java index 7d4ba63..c21afe3 100644 --- a/src/main/java/com/matzip/place/api/response/PlaceRegisterResponseDto.java +++ b/src/main/java/com/matzip/place/dto/response/PlaceRegisterResponseDto.java @@ -1,4 +1,4 @@ -package com.matzip.place.api.response; +package com.matzip.place.dto.response; import com.matzip.place.dto.CategoryDto; import com.matzip.place.dto.TagDto; diff --git a/src/main/java/com/matzip/place/api/response/PlaceRegisterStatusDetailResponseDto.java b/src/main/java/com/matzip/place/dto/response/PlaceRegisterStatusDetailResponseDto.java similarity index 98% rename from src/main/java/com/matzip/place/api/response/PlaceRegisterStatusDetailResponseDto.java rename to src/main/java/com/matzip/place/dto/response/PlaceRegisterStatusDetailResponseDto.java index e328bf4..1bf2782 100644 --- a/src/main/java/com/matzip/place/api/response/PlaceRegisterStatusDetailResponseDto.java +++ b/src/main/java/com/matzip/place/dto/response/PlaceRegisterStatusDetailResponseDto.java @@ -1,4 +1,4 @@ -package com.matzip.place.api.response; +package com.matzip.place.dto.response; import com.matzip.place.domain.entity.Category; import com.matzip.place.domain.entity.Menu; diff --git a/src/main/java/com/matzip/place/api/response/PlaceRegisterStatusResponseDto.java b/src/main/java/com/matzip/place/dto/response/PlaceRegisterStatusResponseDto.java similarity index 96% rename from src/main/java/com/matzip/place/api/response/PlaceRegisterStatusResponseDto.java rename to src/main/java/com/matzip/place/dto/response/PlaceRegisterStatusResponseDto.java index 6031c6d..64e8036 100644 --- a/src/main/java/com/matzip/place/api/response/PlaceRegisterStatusResponseDto.java +++ b/src/main/java/com/matzip/place/dto/response/PlaceRegisterStatusResponseDto.java @@ -1,4 +1,4 @@ -package com.matzip.place.api.response; +package com.matzip.place.dto.response; import com.matzip.place.domain.entity.Place; import com.matzip.place.dto.CategoryDto; diff --git a/src/main/java/com/matzip/place/api/response/PlaceSearchResponseDto.java b/src/main/java/com/matzip/place/dto/response/PlaceSearchResponseDto.java similarity index 92% rename from src/main/java/com/matzip/place/api/response/PlaceSearchResponseDto.java rename to src/main/java/com/matzip/place/dto/response/PlaceSearchResponseDto.java index d8116cb..c14e374 100644 --- a/src/main/java/com/matzip/place/api/response/PlaceSearchResponseDto.java +++ b/src/main/java/com/matzip/place/dto/response/PlaceSearchResponseDto.java @@ -1,4 +1,4 @@ -package com.matzip.place.api.response; +package com.matzip.place.dto.response; import com.matzip.place.domain.entity.Place; import lombok.Builder; diff --git a/src/main/java/com/matzip/place/infra/repository/CategoryRepository.java b/src/main/java/com/matzip/place/repository/CategoryRepository.java similarity index 81% rename from src/main/java/com/matzip/place/infra/repository/CategoryRepository.java rename to src/main/java/com/matzip/place/repository/CategoryRepository.java index 596dd0b..2beef2f 100644 --- a/src/main/java/com/matzip/place/infra/repository/CategoryRepository.java +++ b/src/main/java/com/matzip/place/repository/CategoryRepository.java @@ -1,4 +1,4 @@ -package com.matzip.place.infra.repository; +package com.matzip.place.repository; import com.matzip.place.domain.entity.Category; import org.springframework.data.jpa.repository.JpaRepository; diff --git a/src/main/java/com/matzip/place/infra/repository/DailyViewCountRepository.java b/src/main/java/com/matzip/place/repository/DailyViewCountRepository.java similarity index 96% rename from src/main/java/com/matzip/place/infra/repository/DailyViewCountRepository.java rename to src/main/java/com/matzip/place/repository/DailyViewCountRepository.java index 9ceca84..5fee129 100644 --- a/src/main/java/com/matzip/place/infra/repository/DailyViewCountRepository.java +++ b/src/main/java/com/matzip/place/repository/DailyViewCountRepository.java @@ -1,4 +1,4 @@ -package com.matzip.place.infra.repository; +package com.matzip.place.repository; import com.matzip.place.domain.Campus; import com.matzip.place.domain.DailyViewCount; diff --git a/src/main/java/com/matzip/place/infra/repository/MenuRepository.java b/src/main/java/com/matzip/place/repository/MenuRepository.java similarity index 94% rename from src/main/java/com/matzip/place/infra/repository/MenuRepository.java rename to src/main/java/com/matzip/place/repository/MenuRepository.java index 94a720e..e13d0f8 100644 --- a/src/main/java/com/matzip/place/infra/repository/MenuRepository.java +++ b/src/main/java/com/matzip/place/repository/MenuRepository.java @@ -1,4 +1,4 @@ -package com.matzip.place.infra.repository; +package com.matzip.place.repository; import com.matzip.place.domain.Campus; import com.matzip.place.domain.entity.Menu; diff --git a/src/main/java/com/matzip/place/infra/repository/PhotoRepository.java b/src/main/java/com/matzip/place/repository/PhotoRepository.java similarity index 93% rename from src/main/java/com/matzip/place/infra/repository/PhotoRepository.java rename to src/main/java/com/matzip/place/repository/PhotoRepository.java index 0bbfcd9..d119974 100644 --- a/src/main/java/com/matzip/place/infra/repository/PhotoRepository.java +++ b/src/main/java/com/matzip/place/repository/PhotoRepository.java @@ -1,4 +1,4 @@ -package com.matzip.place.infra.repository; +package com.matzip.place.repository; import com.matzip.place.domain.entity.Photo; import com.matzip.place.domain.entity.Place; diff --git a/src/main/java/com/matzip/place/infra/repository/PlaceCategoryRepository.java b/src/main/java/com/matzip/place/repository/PlaceCategoryRepository.java similarity index 95% rename from src/main/java/com/matzip/place/infra/repository/PlaceCategoryRepository.java rename to src/main/java/com/matzip/place/repository/PlaceCategoryRepository.java index 8b1618d..9ceb403 100644 --- a/src/main/java/com/matzip/place/infra/repository/PlaceCategoryRepository.java +++ b/src/main/java/com/matzip/place/repository/PlaceCategoryRepository.java @@ -1,4 +1,4 @@ -package com.matzip.place.infra.repository; +package com.matzip.place.repository; import com.matzip.place.domain.entity.Place; import com.matzip.place.domain.entity.PlaceCategory; diff --git a/src/main/java/com/matzip/place/infra/repository/PlaceLikeRepository.java b/src/main/java/com/matzip/place/repository/PlaceLikeRepository.java similarity index 95% rename from src/main/java/com/matzip/place/infra/repository/PlaceLikeRepository.java rename to src/main/java/com/matzip/place/repository/PlaceLikeRepository.java index e448ab1..2d8b738 100644 --- a/src/main/java/com/matzip/place/infra/repository/PlaceLikeRepository.java +++ b/src/main/java/com/matzip/place/repository/PlaceLikeRepository.java @@ -1,4 +1,4 @@ -package com.matzip.place.infra.repository; +package com.matzip.place.repository; import com.matzip.place.domain.entity.Place; import com.matzip.place.domain.entity.PlaceLike; diff --git a/src/main/java/com/matzip/place/infra/repository/PlaceRepository.java b/src/main/java/com/matzip/place/repository/PlaceRepository.java similarity index 98% rename from src/main/java/com/matzip/place/infra/repository/PlaceRepository.java rename to src/main/java/com/matzip/place/repository/PlaceRepository.java index 032f2f1..d6c5998 100644 --- a/src/main/java/com/matzip/place/infra/repository/PlaceRepository.java +++ b/src/main/java/com/matzip/place/repository/PlaceRepository.java @@ -1,4 +1,4 @@ -package com.matzip.place.infra.repository; +package com.matzip.place.repository; import com.matzip.place.domain.Campus; import com.matzip.place.domain.PlaceStatus; diff --git a/src/main/java/com/matzip/place/infra/repository/PlaceTagRepository.java b/src/main/java/com/matzip/place/repository/PlaceTagRepository.java similarity index 94% rename from src/main/java/com/matzip/place/infra/repository/PlaceTagRepository.java rename to src/main/java/com/matzip/place/repository/PlaceTagRepository.java index 2529313..8e28065 100644 --- a/src/main/java/com/matzip/place/infra/repository/PlaceTagRepository.java +++ b/src/main/java/com/matzip/place/repository/PlaceTagRepository.java @@ -1,4 +1,4 @@ -package com.matzip.place.infra.repository; +package com.matzip.place.repository; import com.matzip.place.domain.entity.Place; import com.matzip.place.domain.entity.PlaceTag; diff --git a/src/main/java/com/matzip/place/infra/repository/TagRepository.java b/src/main/java/com/matzip/place/repository/TagRepository.java similarity index 80% rename from src/main/java/com/matzip/place/infra/repository/TagRepository.java rename to src/main/java/com/matzip/place/repository/TagRepository.java index ba0de29..7fdeb09 100644 --- a/src/main/java/com/matzip/place/infra/repository/TagRepository.java +++ b/src/main/java/com/matzip/place/repository/TagRepository.java @@ -1,4 +1,4 @@ -package com.matzip.place.infra.repository; +package com.matzip.place.repository; import com.matzip.place.domain.entity.Tag; import org.springframework.data.jpa.repository.JpaRepository; diff --git a/src/main/java/com/matzip/place/application/service/CategoryService.java b/src/main/java/com/matzip/place/service/CategoryService.java similarity index 84% rename from src/main/java/com/matzip/place/application/service/CategoryService.java rename to src/main/java/com/matzip/place/service/CategoryService.java index 3a0e878..5178290 100644 --- a/src/main/java/com/matzip/place/application/service/CategoryService.java +++ b/src/main/java/com/matzip/place/service/CategoryService.java @@ -1,7 +1,7 @@ -package com.matzip.place.application.service; +package com.matzip.place.service; import com.matzip.place.dto.CategoryDto; -import com.matzip.place.infra.repository.CategoryRepository; +import com.matzip.place.repository.CategoryRepository; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; diff --git a/src/main/java/com/matzip/place/application/service/PlaceLikeService.java b/src/main/java/com/matzip/place/service/PlaceLikeService.java similarity index 90% rename from src/main/java/com/matzip/place/application/service/PlaceLikeService.java rename to src/main/java/com/matzip/place/service/PlaceLikeService.java index b4afdcb..7fb96ac 100644 --- a/src/main/java/com/matzip/place/application/service/PlaceLikeService.java +++ b/src/main/java/com/matzip/place/service/PlaceLikeService.java @@ -1,19 +1,19 @@ -package com.matzip.place.application.service; +package com.matzip.place.service; import com.matzip.common.exception.BusinessException; import com.matzip.common.exception.code.ErrorCode; -import com.matzip.place.api.response.PlaceLikeResponseDto; -import com.matzip.place.api.response.PlaceCommonResponseDto; +import com.matzip.place.dto.response.PlaceLikeResponseDto; +import com.matzip.place.dto.response.PlaceCommonResponseDto; import com.matzip.place.domain.entity.Category; import com.matzip.place.domain.entity.Place; import com.matzip.place.domain.entity.PlaceCategory; import com.matzip.place.domain.entity.PlaceLike; import com.matzip.place.domain.entity.PlaceTag; import com.matzip.place.domain.entity.Tag; -import com.matzip.place.infra.repository.PlaceCategoryRepository; -import com.matzip.place.infra.repository.PlaceLikeRepository; -import com.matzip.place.infra.repository.PlaceRepository; -import com.matzip.place.infra.repository.PlaceTagRepository; +import com.matzip.place.repository.PlaceCategoryRepository; +import com.matzip.place.repository.PlaceLikeRepository; +import com.matzip.place.repository.PlaceRepository; +import com.matzip.place.repository.PlaceTagRepository; import com.matzip.user.domain.User; import com.matzip.user.infra.UserRepository; import lombok.RequiredArgsConstructor; diff --git a/src/main/java/com/matzip/place/application/service/PlaceReadService.java b/src/main/java/com/matzip/place/service/PlaceReadService.java similarity index 92% rename from src/main/java/com/matzip/place/application/service/PlaceReadService.java rename to src/main/java/com/matzip/place/service/PlaceReadService.java index 013728f..ef35deb 100644 --- a/src/main/java/com/matzip/place/application/service/PlaceReadService.java +++ b/src/main/java/com/matzip/place/service/PlaceReadService.java @@ -1,18 +1,18 @@ -package com.matzip.place.application.service; +package com.matzip.place.service; import com.matzip.admin.domain.RequestReview; import com.matzip.admin.domain.RequestReviewStatus; import com.matzip.admin.repository.RequestReviewRepository; import com.matzip.common.exception.BusinessException; import com.matzip.common.exception.code.ErrorCode; -import com.matzip.place.api.request.MapSearchRequestDto; -import com.matzip.place.api.response.MapSearchResponseDto; -import com.matzip.place.api.response.PlaceCommonResponseDto; -import com.matzip.place.api.response.PlaceDetailResponseDto; -import com.matzip.place.api.response.PlaceMenuSearchResponseDto; -import com.matzip.place.api.response.PlaceRegisterStatusDetailResponseDto; -import com.matzip.place.api.response.PlaceRegisterStatusResponseDto; -import com.matzip.place.api.response.PlaceSearchResponseDto; +import com.matzip.place.dto.request.MapSearchRequestDto; +import com.matzip.place.dto.response.MapSearchResponseDto; +import com.matzip.place.dto.response.PlaceCommonResponseDto; +import com.matzip.place.dto.response.PlaceDetailResponseDto; +import com.matzip.place.dto.response.PlaceMenuSearchResponseDto; +import com.matzip.place.dto.response.PlaceRegisterStatusDetailResponseDto; +import com.matzip.place.dto.response.PlaceRegisterStatusResponseDto; +import com.matzip.place.dto.response.PlaceSearchResponseDto; import com.matzip.place.domain.Campus; import com.matzip.place.domain.DailyViewCount; import com.matzip.place.domain.PlaceStatus; @@ -26,14 +26,14 @@ import com.matzip.place.domain.entity.Tag; import com.matzip.place.dto.CategoryDto; import com.matzip.place.dto.TagDto; -import com.matzip.place.infra.repository.CategoryRepository; -import com.matzip.place.infra.repository.DailyViewCountRepository; -import com.matzip.place.infra.repository.MenuRepository; -import com.matzip.place.infra.repository.PhotoRepository; -import com.matzip.place.infra.repository.PlaceCategoryRepository; -import com.matzip.place.infra.repository.PlaceLikeRepository; -import com.matzip.place.infra.repository.PlaceRepository; -import com.matzip.place.infra.repository.PlaceTagRepository; +import com.matzip.place.repository.CategoryRepository; +import com.matzip.place.repository.DailyViewCountRepository; +import com.matzip.place.repository.MenuRepository; +import com.matzip.place.repository.PhotoRepository; +import com.matzip.place.repository.PlaceCategoryRepository; +import com.matzip.place.repository.PlaceLikeRepository; +import com.matzip.place.repository.PlaceRepository; +import com.matzip.place.repository.PlaceTagRepository; import com.matzip.user.domain.User; import com.matzip.user.infra.UserRepository; import lombok.RequiredArgsConstructor; diff --git a/src/main/java/com/matzip/place/application/service/PlaceService.java b/src/main/java/com/matzip/place/service/PlaceService.java similarity index 90% rename from src/main/java/com/matzip/place/application/service/PlaceService.java rename to src/main/java/com/matzip/place/service/PlaceService.java index b5646f8..efea0c5 100644 --- a/src/main/java/com/matzip/place/application/service/PlaceService.java +++ b/src/main/java/com/matzip/place/service/PlaceService.java @@ -1,7 +1,7 @@ -package com.matzip.place.application.service; +package com.matzip.place.service; import com.matzip.place.dto.LocationDto; -import com.matzip.place.infra.kakao.dto.KakaoMenuDto; +import com.matzip.place.client.kakao.dto.KakaoMenuDto; import com.matzip.place.dto.PhotoDto; import com.matzip.place.domain.entity.Category; import com.matzip.place.domain.entity.Menu; @@ -10,21 +10,21 @@ import com.matzip.place.domain.entity.PlaceCategory; import com.matzip.place.domain.entity.PlaceTag; import com.matzip.place.domain.entity.Tag; -import com.matzip.place.infra.kakao.KakaoApiClient; -import com.matzip.place.api.request.PlaceCheckRequestDto; -import com.matzip.place.api.request.PlaceRequestDto; -import com.matzip.place.api.response.PlaceCheckResponseDto; -import com.matzip.place.api.response.PlaceRegisterResponseDto; -import com.matzip.place.application.port.PlaceTempStore.PlaceSnapshot; +import com.matzip.place.client.kakao.KakaoApiClient; +import com.matzip.place.dto.request.PlaceCheckRequestDto; +import com.matzip.place.dto.request.PlaceRequestDto; +import com.matzip.place.dto.response.PlaceCheckResponseDto; +import com.matzip.place.dto.response.PlaceRegisterResponseDto; +import com.matzip.place.client.PlaceSnapshot; import com.matzip.place.domain.PlaceStatus; -import com.matzip.place.application.port.PlaceTempStore; -import com.matzip.place.infra.repository.CategoryRepository; -import com.matzip.place.infra.repository.MenuRepository; -import com.matzip.place.infra.repository.PhotoRepository; -import com.matzip.place.infra.repository.PlaceCategoryRepository; -import com.matzip.place.infra.repository.PlaceRepository; -import com.matzip.place.infra.repository.PlaceTagRepository; -import com.matzip.place.infra.repository.TagRepository; +import com.matzip.place.client.PlaceTempStoreMemory; +import com.matzip.place.repository.CategoryRepository; +import com.matzip.place.repository.MenuRepository; +import com.matzip.place.repository.PhotoRepository; +import com.matzip.place.repository.PlaceCategoryRepository; +import com.matzip.place.repository.PlaceRepository; +import com.matzip.place.repository.PlaceTagRepository; +import com.matzip.place.repository.TagRepository; import com.matzip.user.domain.User; import com.matzip.user.infra.UserRepository; import com.matzip.common.infra.discord.DiscordWebhookSender; @@ -36,10 +36,10 @@ import java.util.*; import java.util.stream.Collectors; -import static com.matzip.place.infra.kakao.KakaoApiClient.*; -import static com.matzip.place.api.request.PlaceRequestDto.*; -import static com.matzip.place.api.response.PlaceCheckResponseDto.*; -import static com.matzip.place.application.port.PlaceTempStore.PlaceSnapshot.*; +import static com.matzip.place.client.kakao.KakaoApiClient.*; +import static com.matzip.place.dto.request.PlaceRequestDto.*; +import static com.matzip.place.dto.response.PlaceCheckResponseDto.*; +import static com.matzip.place.client.PlaceSnapshot.*; @Service @RequiredArgsConstructor @@ -56,7 +56,7 @@ public class PlaceService { private final PlaceCategoryRepository placeCategoryRepository; private final PlaceTagRepository placeTagRepository; private final UserRepository userRepository; - private final PlaceTempStore placeTempStore; + private final PlaceTempStoreMemory placeTempStore; private final DiscordWebhookSender discordWebhookSender; public PlaceCheckResponseDto preview(PlaceCheckRequestDto req) { diff --git a/src/main/java/com/matzip/place/application/service/ViewCountService.java b/src/main/java/com/matzip/place/service/ViewCountService.java similarity index 87% rename from src/main/java/com/matzip/place/application/service/ViewCountService.java rename to src/main/java/com/matzip/place/service/ViewCountService.java index fc69e2e..295d963 100644 --- a/src/main/java/com/matzip/place/application/service/ViewCountService.java +++ b/src/main/java/com/matzip/place/service/ViewCountService.java @@ -1,8 +1,8 @@ -package com.matzip.place.application.service; +package com.matzip.place.service; import com.matzip.place.domain.DailyViewCount; -import com.matzip.place.infra.repository.DailyViewCountRepository; -import com.matzip.place.infra.repository.PlaceRepository; +import com.matzip.place.repository.DailyViewCountRepository; +import com.matzip.place.repository.PlaceRepository; import lombok.RequiredArgsConstructor; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; diff --git a/src/test/java/com/matzip/AbstractMatzipApplicationTest.java b/src/test/java/com/matzip/AbstractMatzipApplicationTest.java index 268ec1b..859f602 100644 --- a/src/test/java/com/matzip/AbstractMatzipApplicationTest.java +++ b/src/test/java/com/matzip/AbstractMatzipApplicationTest.java @@ -3,7 +3,7 @@ import com.matzip.fixture.PlaceFixtures; import com.matzip.fixture.UserFixtures; import com.matzip.place.domain.entity.Place; -import com.matzip.place.infra.repository.PlaceRepository; +import com.matzip.place.repository.PlaceRepository; import com.matzip.user.domain.User; import com.matzip.user.infra.UserRepository; import org.junit.jupiter.api.BeforeEach; diff --git a/src/test/java/com/matzip/place/application/PlaceReadServiceTest.java b/src/test/java/com/matzip/place/application/PlaceReadServiceTest.java index 3e967b2..82b9a54 100644 --- a/src/test/java/com/matzip/place/application/PlaceReadServiceTest.java +++ b/src/test/java/com/matzip/place/application/PlaceReadServiceTest.java @@ -1,11 +1,11 @@ package com.matzip.place.application; -import com.matzip.place.application.service.PlaceReadService; +import com.matzip.place.service.PlaceReadService; import com.matzip.place.domain.Campus; import com.matzip.place.domain.PlaceStatus; import com.matzip.place.domain.entity.Place; -import com.matzip.place.infra.repository.DailyViewCountRepository; -import com.matzip.place.infra.repository.PlaceRepository; +import com.matzip.place.repository.DailyViewCountRepository; +import com.matzip.place.repository.PlaceRepository; import com.matzip.user.domain.User; import com.matzip.user.infra.UserRepository; import lombok.extern.slf4j.Slf4j; diff --git a/src/test/java/com/matzip/place/application/PlaceServiceCachingTest.java b/src/test/java/com/matzip/place/application/PlaceServiceCachingTest.java index f80f091..a6ffdaf 100644 --- a/src/test/java/com/matzip/place/application/PlaceServiceCachingTest.java +++ b/src/test/java/com/matzip/place/application/PlaceServiceCachingTest.java @@ -1,24 +1,25 @@ package com.matzip.place.application; import com.matzip.common.infra.discord.DiscordWebhookSender; -import com.matzip.place.infra.kakao.dto.KakaoMenuDto; +import com.matzip.place.client.kakao.dto.KakaoMenuDto; import com.matzip.place.dto.PhotoDto; -import com.matzip.place.application.service.PlaceService; -import com.matzip.place.infra.kakao.KakaoApiClient; -import com.matzip.place.api.request.PlaceCheckRequestDto; -import com.matzip.place.api.request.PlaceRequestDto; -import com.matzip.place.api.response.PlaceCheckResponseDto; -import com.matzip.place.application.port.PlaceTempStore; +import com.matzip.place.service.PlaceService; +import com.matzip.place.client.kakao.KakaoApiClient; +import com.matzip.place.dto.request.PlaceCheckRequestDto; +import com.matzip.place.dto.request.PlaceRequestDto; +import com.matzip.place.dto.response.PlaceCheckResponseDto; +import com.matzip.place.client.PlaceTempStoreMemory; +import com.matzip.place.client.PlaceSnapshot; import com.matzip.place.domain.entity.Category; import com.matzip.place.domain.Campus; import com.matzip.place.domain.PlaceStatus; -import com.matzip.place.infra.repository.CategoryRepository; -import com.matzip.place.infra.repository.MenuRepository; -import com.matzip.place.infra.repository.PhotoRepository; -import com.matzip.place.infra.repository.PlaceCategoryRepository; -import com.matzip.place.infra.repository.PlaceRepository; -import com.matzip.place.infra.repository.PlaceTagRepository; -import com.matzip.place.infra.repository.TagRepository; +import com.matzip.place.repository.CategoryRepository; +import com.matzip.place.repository.MenuRepository; +import com.matzip.place.repository.PhotoRepository; +import com.matzip.place.repository.PlaceCategoryRepository; +import com.matzip.place.repository.PlaceRepository; +import com.matzip.place.repository.PlaceTagRepository; +import com.matzip.place.repository.TagRepository; import com.matzip.user.infra.UserRepository; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -31,7 +32,7 @@ import java.util.List; import java.util.Optional; -import static com.matzip.place.application.port.PlaceTempStore.PlaceSnapshot.*; +import static com.matzip.place.client.PlaceSnapshot.*; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; @@ -45,7 +46,7 @@ class PlaceServiceCachingTest { private PlaceService placeService; @Mock private KakaoApiClient kakaoApiClient; - @Mock private PlaceTempStore placeTempStore; + @Mock private PlaceTempStoreMemory placeTempStore; @Mock private PlaceRepository placeRepository; @Mock private CategoryRepository categoryRepository; @Mock private TagRepository tagRepository; @@ -78,7 +79,7 @@ void preview_ShouldSaveSnapshotToCache() { assertThat(result.getAddress()).isEqualTo("์ถฉ๋‚จ ์ฒœ์•ˆ์‹œ ์„œ๋ถ๊ตฌ ๋ถ€์„ฑ14๊ธธ 46 ์ง€๊ด‘๋นŒ๋”ฉ 1์ธต"); // ์บ์‹œ์— ์Šค๋ƒ…์ƒท์ด ์ €์žฅ๋˜์—ˆ๋Š”์ง€ ํ™•์ธ - verify(placeTempStore, times(1)).put(any(PlaceTempStore.PlaceSnapshot.class)); + verify(placeTempStore, times(1)).put(any(PlaceSnapshot.class)); } @Test @@ -86,7 +87,7 @@ void preview_ShouldSaveSnapshotToCache() { void register_ShouldUseCacheAndReduceKakaoApiCalls() { // given PlaceRequestDto request = createPlaceRequest(); - PlaceTempStore.PlaceSnapshot cachedSnapshot = createMockPlaceSnapshot(); + PlaceSnapshot cachedSnapshot = createMockPlaceSnapshot(); Category category = createMockCategory(1L); when(placeRepository.findByKakaoPlaceIdAndStatus(eq(TEST_KAKAO_PLACE_ID), eq(PlaceStatus.APPROVED))) @@ -135,8 +136,8 @@ private KakaoApiClient.PanelSnapshot createMockPanelSnapshot() { ); } - private PlaceTempStore.PlaceSnapshot createMockPlaceSnapshot() { - return new PlaceTempStore.PlaceSnapshot( + private PlaceSnapshot createMockPlaceSnapshot() { + return new PlaceSnapshot( TEST_KAKAO_PLACE_ID, "์นดํŽ˜์นดํ‚ค", "์ถฉ๋‚จ ์ฒœ์•ˆ์‹œ ์„œ๋ถ๊ตฌ ๋ถ€์„ฑ14๊ธธ 46 ์ง€๊ด‘๋นŒ๋”ฉ 1์ธต", diff --git a/src/test/java/com/matzip/place/application/PlaceServiceTest.java b/src/test/java/com/matzip/place/application/PlaceServiceTest.java index 73612dd..b6e0b95 100644 --- a/src/test/java/com/matzip/place/application/PlaceServiceTest.java +++ b/src/test/java/com/matzip/place/application/PlaceServiceTest.java @@ -1,21 +1,22 @@ package com.matzip.place.application; import com.matzip.common.infra.discord.DiscordWebhookSender; -import com.matzip.place.api.request.PlaceRequestDto; -import com.matzip.place.application.port.PlaceTempStore; -import com.matzip.place.application.service.PlaceService; +import com.matzip.place.dto.request.PlaceRequestDto; +import com.matzip.place.client.PlaceTempStoreMemory; +import com.matzip.place.client.PlaceSnapshot; +import com.matzip.place.service.PlaceService; import com.matzip.place.domain.Campus; import com.matzip.place.domain.PlaceStatus; import com.matzip.place.domain.entity.Category; import com.matzip.place.domain.entity.PlaceCategory; -import com.matzip.place.infra.kakao.KakaoApiClient; -import com.matzip.place.infra.repository.CategoryRepository; -import com.matzip.place.infra.repository.MenuRepository; -import com.matzip.place.infra.repository.PhotoRepository; -import com.matzip.place.infra.repository.PlaceCategoryRepository; -import com.matzip.place.infra.repository.PlaceRepository; -import com.matzip.place.infra.repository.PlaceTagRepository; -import com.matzip.place.infra.repository.TagRepository; +import com.matzip.place.client.kakao.KakaoApiClient; +import com.matzip.place.repository.CategoryRepository; +import com.matzip.place.repository.MenuRepository; +import com.matzip.place.repository.PhotoRepository; +import com.matzip.place.repository.PlaceCategoryRepository; +import com.matzip.place.repository.PlaceRepository; +import com.matzip.place.repository.PlaceTagRepository; +import com.matzip.place.repository.TagRepository; import com.matzip.user.infra.UserRepository; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -29,8 +30,8 @@ import java.util.List; import java.util.Optional; -import static com.matzip.place.application.port.PlaceTempStore.PlaceSnapshot.SMenu; -import static com.matzip.place.application.port.PlaceTempStore.PlaceSnapshot.SPhoto; +import static com.matzip.place.client.PlaceSnapshot.SMenu; +import static com.matzip.place.client.PlaceSnapshot.SPhoto; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.*; @@ -44,7 +45,7 @@ class PlaceServiceTest { private PlaceService placeService; @Mock private KakaoApiClient kakaoApiClient; - @Mock private PlaceTempStore placeTempStore; + @Mock private PlaceTempStoreMemory placeTempStore; @Mock private PlaceRepository placeRepository; @Mock private CategoryRepository categoryRepository; @Mock private TagRepository tagRepository; @@ -93,8 +94,8 @@ private PlaceRequestDto createPlaceRequest() { return request; } - private PlaceTempStore.PlaceSnapshot createMockPlaceSnapshot() { - return new PlaceTempStore.PlaceSnapshot( + private PlaceSnapshot createMockPlaceSnapshot() { + return new PlaceSnapshot( TEST_KAKAO_PLACE_ID, "์นดํŽ˜์นดํ‚ค", "์ถฉ๋‚จ ์ฒœ์•ˆ์‹œ ์„œ๋ถ๊ตฌ ๋ถ€์„ฑ14๊ธธ 46 ์ง€๊ด‘๋นŒ๋”ฉ 1์ธต", From 809cf2807eb8662a08b6efb5c704e7984abd2400 Mon Sep 17 00:00:00 2001 From: gihhyeon Date: Wed, 2 Sep 2026 20:05:33 +0900 Subject: [PATCH 10/24] =?UTF-8?q?refactor:=20auth=20=EB=8F=84=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=EC=9D=84=20=EB=A0=88=EC=9D=B4=EC=96=B4=EB=93=9C=20?= =?UTF-8?q?=ED=91=9C=EC=A4=80=20=ED=8C=A8=ED=82=A4=EC=A7=80=EB=A1=9C=20?= =?UTF-8?q?=ED=86=B5=EC=9D=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kakao/KakaoLoginApiClient.java | 6 +++--- .../kakao/dto/KakaoTokenResponseDto.java | 2 +- .../kakao/dto/KakaoUserResponseDto.java | 2 +- .../{api => controller}/AuthController.java | 20 +++++++++---------- .../{api => controller}/AuthControllerV2.java | 8 ++++---- .../{application => }/dto/ReissueResult.java | 2 +- .../request}/KakaoLoginRequestDto.java | 2 +- .../request}/TokenReissueRequestDto.java | 2 +- .../response}/LoginResponseDto.java | 2 +- .../response}/TokenResponseDto.java | 2 +- .../{application => service}/AuthService.java | 16 +++++++-------- .../NickNameGenerator.java | 2 +- .../ProfileAssignment.java | 2 +- .../util/KakaoAuthorizeUrlBuilder.java | 2 +- .../util/StatelessStateSigner.java | 2 +- .../ProfileAssignmentTest.java | 2 +- .../util/StatelessStateSignerTest.java | 2 +- 17 files changed, 38 insertions(+), 38 deletions(-) rename src/main/java/com/matzip/auth/{infra => client}/kakao/KakaoLoginApiClient.java (96%) rename src/main/java/com/matzip/auth/{infra => client}/kakao/dto/KakaoTokenResponseDto.java (95%) rename src/main/java/com/matzip/auth/{infra => client}/kakao/dto/KakaoUserResponseDto.java (85%) rename src/main/java/com/matzip/auth/{api => controller}/AuthController.java (92%) rename src/main/java/com/matzip/auth/{api => controller}/AuthControllerV2.java (90%) rename src/main/java/com/matzip/auth/{application => }/dto/ReissueResult.java (85%) rename src/main/java/com/matzip/auth/{api/dto => dto/request}/KakaoLoginRequestDto.java (93%) rename src/main/java/com/matzip/auth/{api/dto => dto/request}/TokenReissueRequestDto.java (91%) rename src/main/java/com/matzip/auth/{api/dto => dto/response}/LoginResponseDto.java (95%) rename src/main/java/com/matzip/auth/{api/dto => dto/response}/TokenResponseDto.java (88%) rename src/main/java/com/matzip/auth/{application => service}/AuthService.java (93%) rename src/main/java/com/matzip/auth/{application => service}/NickNameGenerator.java (97%) rename src/main/java/com/matzip/auth/{application => service}/ProfileAssignment.java (94%) rename src/main/java/com/matzip/auth/{application => service}/util/KakaoAuthorizeUrlBuilder.java (94%) rename src/main/java/com/matzip/auth/{application => service}/util/StatelessStateSigner.java (98%) rename src/test/java/com/matzip/auth/{application => service}/ProfileAssignmentTest.java (98%) rename src/test/java/com/matzip/auth/{application => service}/util/StatelessStateSignerTest.java (96%) diff --git a/src/main/java/com/matzip/auth/infra/kakao/KakaoLoginApiClient.java b/src/main/java/com/matzip/auth/client/kakao/KakaoLoginApiClient.java similarity index 96% rename from src/main/java/com/matzip/auth/infra/kakao/KakaoLoginApiClient.java rename to src/main/java/com/matzip/auth/client/kakao/KakaoLoginApiClient.java index e4da03e..ca71c69 100644 --- a/src/main/java/com/matzip/auth/infra/kakao/KakaoLoginApiClient.java +++ b/src/main/java/com/matzip/auth/client/kakao/KakaoLoginApiClient.java @@ -1,7 +1,7 @@ -package com.matzip.auth.infra.kakao; +package com.matzip.auth.client.kakao; -import com.matzip.auth.infra.kakao.dto.KakaoTokenResponseDto; -import com.matzip.auth.infra.kakao.dto.KakaoUserResponseDto; +import com.matzip.auth.client.kakao.dto.KakaoTokenResponseDto; +import com.matzip.auth.client.kakao.dto.KakaoUserResponseDto; import com.matzip.common.config.KakaoProperties; import com.matzip.common.exception.BusinessException; import com.matzip.common.exception.code.ErrorCode; diff --git a/src/main/java/com/matzip/auth/infra/kakao/dto/KakaoTokenResponseDto.java b/src/main/java/com/matzip/auth/client/kakao/dto/KakaoTokenResponseDto.java similarity index 95% rename from src/main/java/com/matzip/auth/infra/kakao/dto/KakaoTokenResponseDto.java rename to src/main/java/com/matzip/auth/client/kakao/dto/KakaoTokenResponseDto.java index a525a7f..53d91d3 100644 --- a/src/main/java/com/matzip/auth/infra/kakao/dto/KakaoTokenResponseDto.java +++ b/src/main/java/com/matzip/auth/client/kakao/dto/KakaoTokenResponseDto.java @@ -1,4 +1,4 @@ -package com.matzip.auth.infra.kakao.dto; +package com.matzip.auth.client.kakao.dto; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Getter; diff --git a/src/main/java/com/matzip/auth/infra/kakao/dto/KakaoUserResponseDto.java b/src/main/java/com/matzip/auth/client/kakao/dto/KakaoUserResponseDto.java similarity index 85% rename from src/main/java/com/matzip/auth/infra/kakao/dto/KakaoUserResponseDto.java rename to src/main/java/com/matzip/auth/client/kakao/dto/KakaoUserResponseDto.java index 78ae7ef..16d2f25 100644 --- a/src/main/java/com/matzip/auth/infra/kakao/dto/KakaoUserResponseDto.java +++ b/src/main/java/com/matzip/auth/client/kakao/dto/KakaoUserResponseDto.java @@ -1,4 +1,4 @@ -package com.matzip.auth.infra.kakao.dto; +package com.matzip.auth.client.kakao.dto; import lombok.Getter; diff --git a/src/main/java/com/matzip/auth/api/AuthController.java b/src/main/java/com/matzip/auth/controller/AuthController.java similarity index 92% rename from src/main/java/com/matzip/auth/api/AuthController.java rename to src/main/java/com/matzip/auth/controller/AuthController.java index ac1d75f..d745fa8 100644 --- a/src/main/java/com/matzip/auth/api/AuthController.java +++ b/src/main/java/com/matzip/auth/controller/AuthController.java @@ -1,13 +1,13 @@ -package com.matzip.auth.api; - -import com.matzip.auth.api.dto.KakaoLoginRequestDto; -import com.matzip.auth.api.dto.LoginResponseDto; -import com.matzip.auth.api.dto.TokenReissueRequestDto; -import com.matzip.auth.api.dto.TokenResponseDto; -import com.matzip.auth.application.AuthService; -import com.matzip.auth.application.util.KakaoAuthorizeUrlBuilder; -import com.matzip.auth.application.dto.ReissueResult; -import com.matzip.auth.application.util.StatelessStateSigner; +package com.matzip.auth.controller; + +import com.matzip.auth.dto.request.KakaoLoginRequestDto; +import com.matzip.auth.dto.response.LoginResponseDto; +import com.matzip.auth.dto.request.TokenReissueRequestDto; +import com.matzip.auth.dto.response.TokenResponseDto; +import com.matzip.auth.service.AuthService; +import com.matzip.auth.service.util.KakaoAuthorizeUrlBuilder; +import com.matzip.auth.dto.ReissueResult; +import com.matzip.auth.service.util.StatelessStateSigner; import com.matzip.common.config.AuthRedirectProperties; import com.matzip.common.config.KakaoProperties; import com.matzip.common.exception.BusinessException; diff --git a/src/main/java/com/matzip/auth/api/AuthControllerV2.java b/src/main/java/com/matzip/auth/controller/AuthControllerV2.java similarity index 90% rename from src/main/java/com/matzip/auth/api/AuthControllerV2.java rename to src/main/java/com/matzip/auth/controller/AuthControllerV2.java index 6b2a00b..4b6d641 100644 --- a/src/main/java/com/matzip/auth/api/AuthControllerV2.java +++ b/src/main/java/com/matzip/auth/controller/AuthControllerV2.java @@ -1,8 +1,8 @@ -package com.matzip.auth.api; +package com.matzip.auth.controller; -import com.matzip.auth.api.dto.KakaoLoginRequestDto; -import com.matzip.auth.api.dto.LoginResponseDto; -import com.matzip.auth.application.AuthService; +import com.matzip.auth.dto.request.KakaoLoginRequestDto; +import com.matzip.auth.dto.response.LoginResponseDto; +import com.matzip.auth.service.AuthService; import com.matzip.common.response.ApiResponse; import org.springframework.http.HttpHeaders; import org.springframework.http.ResponseCookie; diff --git a/src/main/java/com/matzip/auth/application/dto/ReissueResult.java b/src/main/java/com/matzip/auth/dto/ReissueResult.java similarity index 85% rename from src/main/java/com/matzip/auth/application/dto/ReissueResult.java rename to src/main/java/com/matzip/auth/dto/ReissueResult.java index 29dc772..816e588 100644 --- a/src/main/java/com/matzip/auth/application/dto/ReissueResult.java +++ b/src/main/java/com/matzip/auth/dto/ReissueResult.java @@ -1,4 +1,4 @@ -package com.matzip.auth.application.dto; +package com.matzip.auth.dto; public record ReissueResult( String accessToken, diff --git a/src/main/java/com/matzip/auth/api/dto/KakaoLoginRequestDto.java b/src/main/java/com/matzip/auth/dto/request/KakaoLoginRequestDto.java similarity index 93% rename from src/main/java/com/matzip/auth/api/dto/KakaoLoginRequestDto.java rename to src/main/java/com/matzip/auth/dto/request/KakaoLoginRequestDto.java index 696b259..d35ae12 100644 --- a/src/main/java/com/matzip/auth/api/dto/KakaoLoginRequestDto.java +++ b/src/main/java/com/matzip/auth/dto/request/KakaoLoginRequestDto.java @@ -1,4 +1,4 @@ -package com.matzip.auth.api.dto; +package com.matzip.auth.dto.request; import jakarta.validation.constraints.NotBlank; import lombok.*; diff --git a/src/main/java/com/matzip/auth/api/dto/TokenReissueRequestDto.java b/src/main/java/com/matzip/auth/dto/request/TokenReissueRequestDto.java similarity index 91% rename from src/main/java/com/matzip/auth/api/dto/TokenReissueRequestDto.java rename to src/main/java/com/matzip/auth/dto/request/TokenReissueRequestDto.java index 0c64180..2c8c276 100644 --- a/src/main/java/com/matzip/auth/api/dto/TokenReissueRequestDto.java +++ b/src/main/java/com/matzip/auth/dto/request/TokenReissueRequestDto.java @@ -1,4 +1,4 @@ -package com.matzip.auth.api.dto; +package com.matzip.auth.dto.request; import jakarta.validation.constraints.NotBlank; import lombok.*; diff --git a/src/main/java/com/matzip/auth/api/dto/LoginResponseDto.java b/src/main/java/com/matzip/auth/dto/response/LoginResponseDto.java similarity index 95% rename from src/main/java/com/matzip/auth/api/dto/LoginResponseDto.java rename to src/main/java/com/matzip/auth/dto/response/LoginResponseDto.java index 18a64e8..2ce963e 100644 --- a/src/main/java/com/matzip/auth/api/dto/LoginResponseDto.java +++ b/src/main/java/com/matzip/auth/dto/response/LoginResponseDto.java @@ -1,4 +1,4 @@ -package com.matzip.auth.api.dto; +package com.matzip.auth.dto.response; import lombok.*; diff --git a/src/main/java/com/matzip/auth/api/dto/TokenResponseDto.java b/src/main/java/com/matzip/auth/dto/response/TokenResponseDto.java similarity index 88% rename from src/main/java/com/matzip/auth/api/dto/TokenResponseDto.java rename to src/main/java/com/matzip/auth/dto/response/TokenResponseDto.java index 787305b..be3a38a 100644 --- a/src/main/java/com/matzip/auth/api/dto/TokenResponseDto.java +++ b/src/main/java/com/matzip/auth/dto/response/TokenResponseDto.java @@ -1,4 +1,4 @@ -package com.matzip.auth.api.dto; +package com.matzip.auth.dto.response; import lombok.*; diff --git a/src/main/java/com/matzip/auth/application/AuthService.java b/src/main/java/com/matzip/auth/service/AuthService.java similarity index 93% rename from src/main/java/com/matzip/auth/application/AuthService.java rename to src/main/java/com/matzip/auth/service/AuthService.java index 7747567..8c5854a 100644 --- a/src/main/java/com/matzip/auth/application/AuthService.java +++ b/src/main/java/com/matzip/auth/service/AuthService.java @@ -1,13 +1,13 @@ -package com.matzip.auth.application; +package com.matzip.auth.service; -import com.matzip.auth.api.dto.KakaoLoginRequestDto; -import com.matzip.auth.api.dto.LoginResponseDto; -import com.matzip.auth.api.dto.TokenReissueRequestDto; -import com.matzip.auth.application.dto.ReissueResult; +import com.matzip.auth.dto.request.KakaoLoginRequestDto; +import com.matzip.auth.dto.response.LoginResponseDto; +import com.matzip.auth.dto.request.TokenReissueRequestDto; +import com.matzip.auth.dto.ReissueResult; import com.matzip.auth.domain.RefreshToken; -import com.matzip.auth.infra.kakao.KakaoLoginApiClient; -import com.matzip.auth.infra.kakao.dto.KakaoTokenResponseDto; -import com.matzip.auth.infra.kakao.dto.KakaoUserResponseDto; +import com.matzip.auth.client.kakao.KakaoLoginApiClient; +import com.matzip.auth.client.kakao.dto.KakaoTokenResponseDto; +import com.matzip.auth.client.kakao.dto.KakaoUserResponseDto; import com.matzip.common.config.ImageProperties; import com.matzip.common.config.JwtProperties; import com.matzip.common.exception.BusinessException; diff --git a/src/main/java/com/matzip/auth/application/NickNameGenerator.java b/src/main/java/com/matzip/auth/service/NickNameGenerator.java similarity index 97% rename from src/main/java/com/matzip/auth/application/NickNameGenerator.java rename to src/main/java/com/matzip/auth/service/NickNameGenerator.java index 8f4387c..5bc44d3 100644 --- a/src/main/java/com/matzip/auth/application/NickNameGenerator.java +++ b/src/main/java/com/matzip/auth/service/NickNameGenerator.java @@ -1,4 +1,4 @@ -package com.matzip.auth.application; +package com.matzip.auth.service; import org.springframework.stereotype.Component; diff --git a/src/main/java/com/matzip/auth/application/ProfileAssignment.java b/src/main/java/com/matzip/auth/service/ProfileAssignment.java similarity index 94% rename from src/main/java/com/matzip/auth/application/ProfileAssignment.java rename to src/main/java/com/matzip/auth/service/ProfileAssignment.java index 2b62523..67400c6 100644 --- a/src/main/java/com/matzip/auth/application/ProfileAssignment.java +++ b/src/main/java/com/matzip/auth/service/ProfileAssignment.java @@ -1,4 +1,4 @@ -package com.matzip.auth.application; +package com.matzip.auth.service; import com.matzip.user.domain.ProfileBackground; import com.matzip.user.domain.ProfileImage; diff --git a/src/main/java/com/matzip/auth/application/util/KakaoAuthorizeUrlBuilder.java b/src/main/java/com/matzip/auth/service/util/KakaoAuthorizeUrlBuilder.java similarity index 94% rename from src/main/java/com/matzip/auth/application/util/KakaoAuthorizeUrlBuilder.java rename to src/main/java/com/matzip/auth/service/util/KakaoAuthorizeUrlBuilder.java index a33ace9..de14a1e 100644 --- a/src/main/java/com/matzip/auth/application/util/KakaoAuthorizeUrlBuilder.java +++ b/src/main/java/com/matzip/auth/service/util/KakaoAuthorizeUrlBuilder.java @@ -1,4 +1,4 @@ -package com.matzip.auth.application.util; +package com.matzip.auth.service.util; import com.matzip.common.config.KakaoProperties; import lombok.RequiredArgsConstructor; diff --git a/src/main/java/com/matzip/auth/application/util/StatelessStateSigner.java b/src/main/java/com/matzip/auth/service/util/StatelessStateSigner.java similarity index 98% rename from src/main/java/com/matzip/auth/application/util/StatelessStateSigner.java rename to src/main/java/com/matzip/auth/service/util/StatelessStateSigner.java index 6dc4587..95018f3 100644 --- a/src/main/java/com/matzip/auth/application/util/StatelessStateSigner.java +++ b/src/main/java/com/matzip/auth/service/util/StatelessStateSigner.java @@ -1,4 +1,4 @@ -package com.matzip.auth.application.util; +package com.matzip.auth.service.util; import com.matzip.common.config.AuthRedirectProperties; import com.matzip.common.exception.BusinessException; diff --git a/src/test/java/com/matzip/auth/application/ProfileAssignmentTest.java b/src/test/java/com/matzip/auth/service/ProfileAssignmentTest.java similarity index 98% rename from src/test/java/com/matzip/auth/application/ProfileAssignmentTest.java rename to src/test/java/com/matzip/auth/service/ProfileAssignmentTest.java index 911f5f3..203974f 100644 --- a/src/test/java/com/matzip/auth/application/ProfileAssignmentTest.java +++ b/src/test/java/com/matzip/auth/service/ProfileAssignmentTest.java @@ -1,4 +1,4 @@ -package com.matzip.auth.application; +package com.matzip.auth.service; import com.matzip.user.domain.ProfileBackground; import com.matzip.user.domain.ProfileImage; diff --git a/src/test/java/com/matzip/auth/application/util/StatelessStateSignerTest.java b/src/test/java/com/matzip/auth/service/util/StatelessStateSignerTest.java similarity index 96% rename from src/test/java/com/matzip/auth/application/util/StatelessStateSignerTest.java rename to src/test/java/com/matzip/auth/service/util/StatelessStateSignerTest.java index 5cc8746..6f1ee11 100644 --- a/src/test/java/com/matzip/auth/application/util/StatelessStateSignerTest.java +++ b/src/test/java/com/matzip/auth/service/util/StatelessStateSignerTest.java @@ -1,4 +1,4 @@ -package com.matzip.auth.application.util; +package com.matzip.auth.service.util; import com.matzip.common.config.AuthRedirectProperties; import org.junit.jupiter.api.BeforeEach; From 7c873e9fbd0d404b087d70a5e856c0d1fec9ff62 Mon Sep 17 00:00:00 2001 From: gihhyeon Date: Wed, 2 Sep 2026 20:16:33 +0900 Subject: [PATCH 11/24] =?UTF-8?q?refactor:=20user=20=EB=8F=84=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=EC=9D=84=20=EB=A0=88=EC=9D=B4=EC=96=B4=EB=93=9C=20?= =?UTF-8?q?=ED=91=9C=EC=A4=80=20=ED=8C=A8=ED=82=A4=EC=A7=80=EB=A1=9C=20?= =?UTF-8?q?=ED=86=B5=EC=9D=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/matzip/auth/service/AuthService.java | 2 +- .../java/com/matzip/place/service/PlaceLikeService.java | 2 +- .../java/com/matzip/place/service/PlaceReadService.java | 2 +- src/main/java/com/matzip/place/service/PlaceService.java | 2 +- .../matzip/user/{api => }/controller/UserController.java | 6 +++--- .../user/{api => dto}/response/UserProfileResponseDto.java | 2 +- .../matzip/user/{infra => repository}/UserRepository.java | 2 +- .../matzip/user/{application => service}/UserService.java | 6 +++--- src/test/java/com/matzip/AbstractMatzipApplicationTest.java | 2 +- .../com/matzip/place/application/PlaceReadServiceTest.java | 2 +- .../matzip/place/application/PlaceServiceCachingTest.java | 2 +- .../java/com/matzip/place/application/PlaceServiceTest.java | 2 +- 12 files changed, 16 insertions(+), 16 deletions(-) rename src/main/java/com/matzip/user/{api => }/controller/UserController.java (85%) rename src/main/java/com/matzip/user/{api => dto}/response/UserProfileResponseDto.java (94%) rename src/main/java/com/matzip/user/{infra => repository}/UserRepository.java (88%) rename src/main/java/com/matzip/user/{application => service}/UserService.java (85%) diff --git a/src/main/java/com/matzip/auth/service/AuthService.java b/src/main/java/com/matzip/auth/service/AuthService.java index 8c5854a..16f40ab 100644 --- a/src/main/java/com/matzip/auth/service/AuthService.java +++ b/src/main/java/com/matzip/auth/service/AuthService.java @@ -17,7 +17,7 @@ import com.matzip.user.domain.ProfileBackground; import com.matzip.user.domain.ProfileImage; import com.matzip.user.domain.User; -import com.matzip.user.infra.UserRepository; +import com.matzip.user.repository.UserRepository; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; diff --git a/src/main/java/com/matzip/place/service/PlaceLikeService.java b/src/main/java/com/matzip/place/service/PlaceLikeService.java index 7fb96ac..aa6dd60 100644 --- a/src/main/java/com/matzip/place/service/PlaceLikeService.java +++ b/src/main/java/com/matzip/place/service/PlaceLikeService.java @@ -15,7 +15,7 @@ import com.matzip.place.repository.PlaceRepository; import com.matzip.place.repository.PlaceTagRepository; import com.matzip.user.domain.User; -import com.matzip.user.infra.UserRepository; +import com.matzip.user.repository.UserRepository; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; diff --git a/src/main/java/com/matzip/place/service/PlaceReadService.java b/src/main/java/com/matzip/place/service/PlaceReadService.java index ef35deb..a545c7e 100644 --- a/src/main/java/com/matzip/place/service/PlaceReadService.java +++ b/src/main/java/com/matzip/place/service/PlaceReadService.java @@ -35,7 +35,7 @@ import com.matzip.place.repository.PlaceRepository; import com.matzip.place.repository.PlaceTagRepository; import com.matzip.user.domain.User; -import com.matzip.user.infra.UserRepository; +import com.matzip.user.repository.UserRepository; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; diff --git a/src/main/java/com/matzip/place/service/PlaceService.java b/src/main/java/com/matzip/place/service/PlaceService.java index efea0c5..2e58186 100644 --- a/src/main/java/com/matzip/place/service/PlaceService.java +++ b/src/main/java/com/matzip/place/service/PlaceService.java @@ -26,7 +26,7 @@ import com.matzip.place.repository.PlaceTagRepository; import com.matzip.place.repository.TagRepository; import com.matzip.user.domain.User; -import com.matzip.user.infra.UserRepository; +import com.matzip.user.repository.UserRepository; import com.matzip.common.infra.discord.DiscordWebhookSender; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; diff --git a/src/main/java/com/matzip/user/api/controller/UserController.java b/src/main/java/com/matzip/user/controller/UserController.java similarity index 85% rename from src/main/java/com/matzip/user/api/controller/UserController.java rename to src/main/java/com/matzip/user/controller/UserController.java index 132c401..87744cf 100644 --- a/src/main/java/com/matzip/user/api/controller/UserController.java +++ b/src/main/java/com/matzip/user/controller/UserController.java @@ -1,9 +1,9 @@ -package com.matzip.user.api.controller; +package com.matzip.user.controller; import com.matzip.common.response.ApiResponse; import com.matzip.common.security.UserPrincipal; -import com.matzip.user.api.response.UserProfileResponseDto; -import com.matzip.user.application.UserService; +import com.matzip.user.dto.response.UserProfileResponseDto; +import com.matzip.user.service.UserService; import lombok.RequiredArgsConstructor; import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.web.bind.annotation.GetMapping; diff --git a/src/main/java/com/matzip/user/api/response/UserProfileResponseDto.java b/src/main/java/com/matzip/user/dto/response/UserProfileResponseDto.java similarity index 94% rename from src/main/java/com/matzip/user/api/response/UserProfileResponseDto.java rename to src/main/java/com/matzip/user/dto/response/UserProfileResponseDto.java index cdda4d7..2723886 100644 --- a/src/main/java/com/matzip/user/api/response/UserProfileResponseDto.java +++ b/src/main/java/com/matzip/user/dto/response/UserProfileResponseDto.java @@ -1,4 +1,4 @@ -package com.matzip.user.api.response; +package com.matzip.user.dto.response; import com.matzip.user.domain.User; import lombok.Builder; diff --git a/src/main/java/com/matzip/user/infra/UserRepository.java b/src/main/java/com/matzip/user/repository/UserRepository.java similarity index 88% rename from src/main/java/com/matzip/user/infra/UserRepository.java rename to src/main/java/com/matzip/user/repository/UserRepository.java index 0f6b967..548d402 100644 --- a/src/main/java/com/matzip/user/infra/UserRepository.java +++ b/src/main/java/com/matzip/user/repository/UserRepository.java @@ -1,4 +1,4 @@ -package com.matzip.user.infra; +package com.matzip.user.repository; import com.matzip.user.domain.User; import org.springframework.data.jpa.repository.JpaRepository; diff --git a/src/main/java/com/matzip/user/application/UserService.java b/src/main/java/com/matzip/user/service/UserService.java similarity index 85% rename from src/main/java/com/matzip/user/application/UserService.java rename to src/main/java/com/matzip/user/service/UserService.java index 53e5e51..bdc6615 100644 --- a/src/main/java/com/matzip/user/application/UserService.java +++ b/src/main/java/com/matzip/user/service/UserService.java @@ -1,11 +1,11 @@ -package com.matzip.user.application; +package com.matzip.user.service; import com.matzip.common.config.ImageProperties; import com.matzip.common.exception.BusinessException; import com.matzip.common.exception.code.ErrorCode; -import com.matzip.user.api.response.UserProfileResponseDto; +import com.matzip.user.dto.response.UserProfileResponseDto; import com.matzip.user.domain.User; -import com.matzip.user.infra.UserRepository; +import com.matzip.user.repository.UserRepository; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; diff --git a/src/test/java/com/matzip/AbstractMatzipApplicationTest.java b/src/test/java/com/matzip/AbstractMatzipApplicationTest.java index 859f602..d1d9d3f 100644 --- a/src/test/java/com/matzip/AbstractMatzipApplicationTest.java +++ b/src/test/java/com/matzip/AbstractMatzipApplicationTest.java @@ -5,7 +5,7 @@ import com.matzip.place.domain.entity.Place; import com.matzip.place.repository.PlaceRepository; import com.matzip.user.domain.User; -import com.matzip.user.infra.UserRepository; +import com.matzip.user.repository.UserRepository; import org.junit.jupiter.api.BeforeEach; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/src/test/java/com/matzip/place/application/PlaceReadServiceTest.java b/src/test/java/com/matzip/place/application/PlaceReadServiceTest.java index 82b9a54..099eb06 100644 --- a/src/test/java/com/matzip/place/application/PlaceReadServiceTest.java +++ b/src/test/java/com/matzip/place/application/PlaceReadServiceTest.java @@ -7,7 +7,7 @@ import com.matzip.place.repository.DailyViewCountRepository; import com.matzip.place.repository.PlaceRepository; import com.matzip.user.domain.User; -import com.matzip.user.infra.UserRepository; +import com.matzip.user.repository.UserRepository; import lombok.extern.slf4j.Slf4j; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; diff --git a/src/test/java/com/matzip/place/application/PlaceServiceCachingTest.java b/src/test/java/com/matzip/place/application/PlaceServiceCachingTest.java index a6ffdaf..042dc9b 100644 --- a/src/test/java/com/matzip/place/application/PlaceServiceCachingTest.java +++ b/src/test/java/com/matzip/place/application/PlaceServiceCachingTest.java @@ -20,7 +20,7 @@ import com.matzip.place.repository.PlaceRepository; import com.matzip.place.repository.PlaceTagRepository; import com.matzip.place.repository.TagRepository; -import com.matzip.user.infra.UserRepository; +import com.matzip.user.repository.UserRepository; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; diff --git a/src/test/java/com/matzip/place/application/PlaceServiceTest.java b/src/test/java/com/matzip/place/application/PlaceServiceTest.java index b6e0b95..ad956cd 100644 --- a/src/test/java/com/matzip/place/application/PlaceServiceTest.java +++ b/src/test/java/com/matzip/place/application/PlaceServiceTest.java @@ -17,7 +17,7 @@ import com.matzip.place.repository.PlaceRepository; import com.matzip.place.repository.PlaceTagRepository; import com.matzip.place.repository.TagRepository; -import com.matzip.user.infra.UserRepository; +import com.matzip.user.repository.UserRepository; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; From 7cb25ecf439d8d6854445583d999ac5c497c3f47 Mon Sep 17 00:00:00 2001 From: gihhyeon Date: Wed, 2 Sep 2026 20:35:32 +0900 Subject: [PATCH 12/24] =?UTF-8?q?refactor:=20lottery=20=EB=8F=84=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20dto=C2=B7client=20=EC=9C=84=EC=B9=98=EB=A5=BC=20?= =?UTF-8?q?=EB=A0=88=EC=9D=B4=EC=96=B4=EB=93=9C=20=ED=91=9C=EC=A4=80?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DiscordWinnerNotificationService.java | 2 +- .../controller/LotteryEventController.java | 10 +++++----- .../request/ApplyEventRequestDto.java | 2 +- .../response/ApplyEventResponseDto.java | 2 +- .../response/EventEntryResultResponseDto.java | 2 +- .../LotteryEventAnonymousResponseDto.java | 2 +- .../response/LotteryEventResponseDto.java | 2 +- .../response/LotteryEventView.java | 2 +- .../response/ParticipatedEventResponseDto.java | 2 +- .../lottery/service/LotteryEventService.java | 16 ++++++++-------- .../LotteryEventServiceAutoEntryTest.java | 2 +- .../LotteryEventServiceGetEntryResultTest.java | 2 +- 12 files changed, 23 insertions(+), 23 deletions(-) rename src/main/java/com/matzip/lottery/{infra => client}/discord/DiscordWinnerNotificationService.java (96%) rename src/main/java/com/matzip/lottery/{controller => dto}/request/ApplyEventRequestDto.java (94%) rename src/main/java/com/matzip/lottery/{controller => dto}/response/ApplyEventResponseDto.java (92%) rename src/main/java/com/matzip/lottery/{controller => dto}/response/EventEntryResultResponseDto.java (95%) rename src/main/java/com/matzip/lottery/{controller => dto}/response/LotteryEventAnonymousResponseDto.java (95%) rename src/main/java/com/matzip/lottery/{controller => dto}/response/LotteryEventResponseDto.java (96%) rename src/main/java/com/matzip/lottery/{controller => dto}/response/LotteryEventView.java (70%) rename src/main/java/com/matzip/lottery/{controller => dto}/response/ParticipatedEventResponseDto.java (94%) diff --git a/src/main/java/com/matzip/lottery/infra/discord/DiscordWinnerNotificationService.java b/src/main/java/com/matzip/lottery/client/discord/DiscordWinnerNotificationService.java similarity index 96% rename from src/main/java/com/matzip/lottery/infra/discord/DiscordWinnerNotificationService.java rename to src/main/java/com/matzip/lottery/client/discord/DiscordWinnerNotificationService.java index 3fa2ea9..3b7b42e 100644 --- a/src/main/java/com/matzip/lottery/infra/discord/DiscordWinnerNotificationService.java +++ b/src/main/java/com/matzip/lottery/client/discord/DiscordWinnerNotificationService.java @@ -1,4 +1,4 @@ -package com.matzip.lottery.infra.discord; +package com.matzip.lottery.client.discord; import com.matzip.common.infra.discord.DiscordWebhookSender; import com.matzip.lottery.domain.LotteryEvent; diff --git a/src/main/java/com/matzip/lottery/controller/LotteryEventController.java b/src/main/java/com/matzip/lottery/controller/LotteryEventController.java index 06e540e..3e137ab 100644 --- a/src/main/java/com/matzip/lottery/controller/LotteryEventController.java +++ b/src/main/java/com/matzip/lottery/controller/LotteryEventController.java @@ -2,11 +2,11 @@ import com.matzip.common.response.ApiResponse; import com.matzip.common.security.UserPrincipal; -import com.matzip.lottery.controller.request.ApplyEventRequestDto; -import com.matzip.lottery.controller.response.ApplyEventResponseDto; -import com.matzip.lottery.controller.response.EventEntryResultResponseDto; -import com.matzip.lottery.controller.response.LotteryEventView; -import com.matzip.lottery.controller.response.ParticipatedEventResponseDto; +import com.matzip.lottery.dto.request.ApplyEventRequestDto; +import com.matzip.lottery.dto.response.ApplyEventResponseDto; +import com.matzip.lottery.dto.response.EventEntryResultResponseDto; +import com.matzip.lottery.dto.response.LotteryEventView; +import com.matzip.lottery.dto.response.ParticipatedEventResponseDto; import com.matzip.lottery.service.LotteryEventService; import java.util.List; diff --git a/src/main/java/com/matzip/lottery/controller/request/ApplyEventRequestDto.java b/src/main/java/com/matzip/lottery/dto/request/ApplyEventRequestDto.java similarity index 94% rename from src/main/java/com/matzip/lottery/controller/request/ApplyEventRequestDto.java rename to src/main/java/com/matzip/lottery/dto/request/ApplyEventRequestDto.java index b4676cc..32b4497 100644 --- a/src/main/java/com/matzip/lottery/controller/request/ApplyEventRequestDto.java +++ b/src/main/java/com/matzip/lottery/dto/request/ApplyEventRequestDto.java @@ -1,4 +1,4 @@ -package com.matzip.lottery.controller.request; +package com.matzip.lottery.dto.request; import jakarta.validation.Valid; import jakarta.validation.constraints.NotBlank; diff --git a/src/main/java/com/matzip/lottery/controller/response/ApplyEventResponseDto.java b/src/main/java/com/matzip/lottery/dto/response/ApplyEventResponseDto.java similarity index 92% rename from src/main/java/com/matzip/lottery/controller/response/ApplyEventResponseDto.java rename to src/main/java/com/matzip/lottery/dto/response/ApplyEventResponseDto.java index ba43838..4896d63 100644 --- a/src/main/java/com/matzip/lottery/controller/response/ApplyEventResponseDto.java +++ b/src/main/java/com/matzip/lottery/dto/response/ApplyEventResponseDto.java @@ -1,4 +1,4 @@ -package com.matzip.lottery.controller.response; +package com.matzip.lottery.dto.response; import com.matzip.lottery.domain.WinnerContact; import lombok.Builder; diff --git a/src/main/java/com/matzip/lottery/controller/response/EventEntryResultResponseDto.java b/src/main/java/com/matzip/lottery/dto/response/EventEntryResultResponseDto.java similarity index 95% rename from src/main/java/com/matzip/lottery/controller/response/EventEntryResultResponseDto.java rename to src/main/java/com/matzip/lottery/dto/response/EventEntryResultResponseDto.java index d202b2c..9b100fc 100644 --- a/src/main/java/com/matzip/lottery/controller/response/EventEntryResultResponseDto.java +++ b/src/main/java/com/matzip/lottery/dto/response/EventEntryResultResponseDto.java @@ -1,4 +1,4 @@ -package com.matzip.lottery.controller.response; +package com.matzip.lottery.dto.response; import com.matzip.lottery.domain.LotteryEvent; import lombok.Builder; diff --git a/src/main/java/com/matzip/lottery/controller/response/LotteryEventAnonymousResponseDto.java b/src/main/java/com/matzip/lottery/dto/response/LotteryEventAnonymousResponseDto.java similarity index 95% rename from src/main/java/com/matzip/lottery/controller/response/LotteryEventAnonymousResponseDto.java rename to src/main/java/com/matzip/lottery/dto/response/LotteryEventAnonymousResponseDto.java index 8a673ba..7548704 100644 --- a/src/main/java/com/matzip/lottery/controller/response/LotteryEventAnonymousResponseDto.java +++ b/src/main/java/com/matzip/lottery/dto/response/LotteryEventAnonymousResponseDto.java @@ -1,4 +1,4 @@ -package com.matzip.lottery.controller.response; +package com.matzip.lottery.dto.response; import com.matzip.lottery.domain.LotteryEvent; import lombok.Builder; diff --git a/src/main/java/com/matzip/lottery/controller/response/LotteryEventResponseDto.java b/src/main/java/com/matzip/lottery/dto/response/LotteryEventResponseDto.java similarity index 96% rename from src/main/java/com/matzip/lottery/controller/response/LotteryEventResponseDto.java rename to src/main/java/com/matzip/lottery/dto/response/LotteryEventResponseDto.java index ed8d85e..d365cc2 100644 --- a/src/main/java/com/matzip/lottery/controller/response/LotteryEventResponseDto.java +++ b/src/main/java/com/matzip/lottery/dto/response/LotteryEventResponseDto.java @@ -1,4 +1,4 @@ -package com.matzip.lottery.controller.response; +package com.matzip.lottery.dto.response; import com.matzip.lottery.domain.LotteryEvent; import com.matzip.lottery.domain.Prize; diff --git a/src/main/java/com/matzip/lottery/controller/response/LotteryEventView.java b/src/main/java/com/matzip/lottery/dto/response/LotteryEventView.java similarity index 70% rename from src/main/java/com/matzip/lottery/controller/response/LotteryEventView.java rename to src/main/java/com/matzip/lottery/dto/response/LotteryEventView.java index 6fb9594..0037965 100644 --- a/src/main/java/com/matzip/lottery/controller/response/LotteryEventView.java +++ b/src/main/java/com/matzip/lottery/dto/response/LotteryEventView.java @@ -1,4 +1,4 @@ -package com.matzip.lottery.controller.response; +package com.matzip.lottery.dto.response; public sealed interface LotteryEventView permits LotteryEventResponseDto, LotteryEventAnonymousResponseDto { } diff --git a/src/main/java/com/matzip/lottery/controller/response/ParticipatedEventResponseDto.java b/src/main/java/com/matzip/lottery/dto/response/ParticipatedEventResponseDto.java similarity index 94% rename from src/main/java/com/matzip/lottery/controller/response/ParticipatedEventResponseDto.java rename to src/main/java/com/matzip/lottery/dto/response/ParticipatedEventResponseDto.java index 6ef6134..5b6ba93 100644 --- a/src/main/java/com/matzip/lottery/controller/response/ParticipatedEventResponseDto.java +++ b/src/main/java/com/matzip/lottery/dto/response/ParticipatedEventResponseDto.java @@ -1,4 +1,4 @@ -package com.matzip.lottery.controller.response; +package com.matzip.lottery.dto.response; import com.matzip.lottery.domain.LotteryEvent; import lombok.Builder; diff --git a/src/main/java/com/matzip/lottery/service/LotteryEventService.java b/src/main/java/com/matzip/lottery/service/LotteryEventService.java index fa1ecc5..b91b38a 100644 --- a/src/main/java/com/matzip/lottery/service/LotteryEventService.java +++ b/src/main/java/com/matzip/lottery/service/LotteryEventService.java @@ -2,18 +2,18 @@ import com.matzip.common.exception.BusinessException; import com.matzip.common.exception.code.ErrorCode; -import com.matzip.lottery.controller.request.ApplyEventRequestDto; -import com.matzip.lottery.controller.response.ApplyEventResponseDto; -import com.matzip.lottery.controller.response.EventEntryResultResponseDto; -import com.matzip.lottery.controller.response.LotteryEventAnonymousResponseDto; -import com.matzip.lottery.controller.response.LotteryEventResponseDto; -import com.matzip.lottery.controller.response.LotteryEventView; -import com.matzip.lottery.controller.response.ParticipatedEventResponseDto; +import com.matzip.lottery.dto.request.ApplyEventRequestDto; +import com.matzip.lottery.dto.response.ApplyEventResponseDto; +import com.matzip.lottery.dto.response.EventEntryResultResponseDto; +import com.matzip.lottery.dto.response.LotteryEventAnonymousResponseDto; +import com.matzip.lottery.dto.response.LotteryEventResponseDto; +import com.matzip.lottery.dto.response.LotteryEventView; +import com.matzip.lottery.dto.response.ParticipatedEventResponseDto; import com.matzip.lottery.domain.LotteryEntries; import com.matzip.lottery.domain.LotteryEntry; import com.matzip.lottery.domain.LotteryEvent; import com.matzip.lottery.domain.WinnerContact; -import com.matzip.lottery.infra.discord.DiscordWinnerNotificationService; +import com.matzip.lottery.client.discord.DiscordWinnerNotificationService; import com.matzip.lottery.repository.LotteryEntryRepository; import com.matzip.lottery.repository.LotteryEventRepository; import com.matzip.lottery.repository.WinnerContactRepository; diff --git a/src/test/java/com/matzip/lottery/service/LotteryEventServiceAutoEntryTest.java b/src/test/java/com/matzip/lottery/service/LotteryEventServiceAutoEntryTest.java index 0e19bf4..c003751 100644 --- a/src/test/java/com/matzip/lottery/service/LotteryEventServiceAutoEntryTest.java +++ b/src/test/java/com/matzip/lottery/service/LotteryEventServiceAutoEntryTest.java @@ -6,7 +6,7 @@ import com.matzip.lottery.repository.LotteryEventRepository; import com.matzip.lottery.repository.WinnerContactRepository; import com.matzip.lottery.repository.WinnerRepository; -import com.matzip.lottery.infra.discord.DiscordWinnerNotificationService; +import com.matzip.lottery.client.discord.DiscordWinnerNotificationService; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; diff --git a/src/test/java/com/matzip/lottery/service/LotteryEventServiceGetEntryResultTest.java b/src/test/java/com/matzip/lottery/service/LotteryEventServiceGetEntryResultTest.java index 68304bd..cf9282a 100644 --- a/src/test/java/com/matzip/lottery/service/LotteryEventServiceGetEntryResultTest.java +++ b/src/test/java/com/matzip/lottery/service/LotteryEventServiceGetEntryResultTest.java @@ -2,7 +2,7 @@ import com.matzip.common.exception.BusinessException; import com.matzip.common.exception.code.ErrorCode; -import com.matzip.lottery.controller.response.EventEntryResultResponseDto; +import com.matzip.lottery.dto.response.EventEntryResultResponseDto; import com.matzip.lottery.domain.LotteryEvent; import com.matzip.lottery.domain.Prize; import com.matzip.lottery.domain.Winner; From ef4114a0675686a5063be12fc066a141018cf0c0 Mon Sep 17 00:00:00 2001 From: gihhyeon Date: Wed, 2 Sep 2026 20:41:54 +0900 Subject: [PATCH 13/24] =?UTF-8?q?refactor:=20admin=20=EB=8F=84=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20dto=20=EC=9C=84=EC=B9=98=EB=A5=BC=20=EB=A0=88?= =?UTF-8?q?=EC=9D=B4=EC=96=B4=EB=93=9C=20=ED=91=9C=EC=A4=80=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/matzip/admin/controller/AdminController.java | 6 +++--- .../request/PlaceRegisterRequestReviewRequestDto.java | 2 +- .../response/PlaceRegisterRequestDetailResponseDto.java | 2 +- .../response/PlaceRegisterRequestsResponseDto.java | 2 +- .../com/matzip/place/controller/PlaceRequestController.java | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) rename src/main/java/com/matzip/admin/{controller => dto}/request/PlaceRegisterRequestReviewRequestDto.java (78%) rename src/main/java/com/matzip/admin/{controller => dto}/response/PlaceRegisterRequestDetailResponseDto.java (97%) rename src/main/java/com/matzip/admin/{controller => dto}/response/PlaceRegisterRequestsResponseDto.java (96%) diff --git a/src/main/java/com/matzip/admin/controller/AdminController.java b/src/main/java/com/matzip/admin/controller/AdminController.java index ba7162b..234c751 100644 --- a/src/main/java/com/matzip/admin/controller/AdminController.java +++ b/src/main/java/com/matzip/admin/controller/AdminController.java @@ -1,8 +1,8 @@ package com.matzip.admin.controller; -import com.matzip.admin.controller.request.PlaceRegisterRequestReviewRequestDto; -import com.matzip.admin.controller.response.PlaceRegisterRequestDetailResponseDto; -import com.matzip.admin.controller.response.PlaceRegisterRequestsResponseDto; +import com.matzip.admin.dto.request.PlaceRegisterRequestReviewRequestDto; +import com.matzip.admin.dto.response.PlaceRegisterRequestDetailResponseDto; +import com.matzip.admin.dto.response.PlaceRegisterRequestsResponseDto; import com.matzip.admin.service.AdminPlaceRegisterRequestService; import com.matzip.common.exception.BusinessException; import com.matzip.common.exception.code.ErrorCode; diff --git a/src/main/java/com/matzip/admin/controller/request/PlaceRegisterRequestReviewRequestDto.java b/src/main/java/com/matzip/admin/dto/request/PlaceRegisterRequestReviewRequestDto.java similarity index 78% rename from src/main/java/com/matzip/admin/controller/request/PlaceRegisterRequestReviewRequestDto.java rename to src/main/java/com/matzip/admin/dto/request/PlaceRegisterRequestReviewRequestDto.java index 4a86bc7..4e24eeb 100644 --- a/src/main/java/com/matzip/admin/controller/request/PlaceRegisterRequestReviewRequestDto.java +++ b/src/main/java/com/matzip/admin/dto/request/PlaceRegisterRequestReviewRequestDto.java @@ -1,4 +1,4 @@ -package com.matzip.admin.controller.request; +package com.matzip.admin.dto.request; import com.matzip.admin.domain.RequestReviewStatus; diff --git a/src/main/java/com/matzip/admin/controller/response/PlaceRegisterRequestDetailResponseDto.java b/src/main/java/com/matzip/admin/dto/response/PlaceRegisterRequestDetailResponseDto.java similarity index 97% rename from src/main/java/com/matzip/admin/controller/response/PlaceRegisterRequestDetailResponseDto.java rename to src/main/java/com/matzip/admin/dto/response/PlaceRegisterRequestDetailResponseDto.java index b3ac07f..d6ff6fa 100644 --- a/src/main/java/com/matzip/admin/controller/response/PlaceRegisterRequestDetailResponseDto.java +++ b/src/main/java/com/matzip/admin/dto/response/PlaceRegisterRequestDetailResponseDto.java @@ -1,4 +1,4 @@ -package com.matzip.admin.controller.response; +package com.matzip.admin.dto.response; import com.matzip.place.domain.entity.Menu; import com.matzip.place.domain.entity.Place; diff --git a/src/main/java/com/matzip/admin/controller/response/PlaceRegisterRequestsResponseDto.java b/src/main/java/com/matzip/admin/dto/response/PlaceRegisterRequestsResponseDto.java similarity index 96% rename from src/main/java/com/matzip/admin/controller/response/PlaceRegisterRequestsResponseDto.java rename to src/main/java/com/matzip/admin/dto/response/PlaceRegisterRequestsResponseDto.java index e347e84..69b6c97 100644 --- a/src/main/java/com/matzip/admin/controller/response/PlaceRegisterRequestsResponseDto.java +++ b/src/main/java/com/matzip/admin/dto/response/PlaceRegisterRequestsResponseDto.java @@ -1,4 +1,4 @@ -package com.matzip.admin.controller.response; +package com.matzip.admin.dto.response; import com.matzip.place.domain.Campus; import com.matzip.place.domain.entity.Place; diff --git a/src/main/java/com/matzip/place/controller/PlaceRequestController.java b/src/main/java/com/matzip/place/controller/PlaceRequestController.java index 3821c37..92a0cd8 100644 --- a/src/main/java/com/matzip/place/controller/PlaceRequestController.java +++ b/src/main/java/com/matzip/place/controller/PlaceRequestController.java @@ -1,6 +1,6 @@ package com.matzip.place.controller; -import com.matzip.admin.controller.response.PlaceRegisterRequestDetailResponseDto; +import com.matzip.admin.dto.response.PlaceRegisterRequestDetailResponseDto; import com.matzip.common.exception.BusinessException; import com.matzip.common.exception.code.ErrorCode; import com.matzip.common.response.ApiResponse; From 65424bffc5fa0d0157cc4ec41c590f1a2f42669c Mon Sep 17 00:00:00 2001 From: gihhyeon Date: Wed, 2 Sep 2026 23:00:27 +0900 Subject: [PATCH 14/24] =?UTF-8?q?docs:=20CLAUDE.md=EC=97=90=20=EC=95=84?= =?UTF-8?q?=ED=82=A4=ED=85=8D=EC=B2=98=20=ED=91=9C=EC=A4=80=EA=B3=BC=20?= =?UTF-8?q?=EC=9E=91=EC=97=85=20=EA=B7=9C=EC=B9=99=20=EB=AC=B8=EC=84=9C?= =?UTF-8?q?=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CLAUDE.md | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..dbe611c --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,96 @@ +# KNU-Matzip Server + +์ด ์ €์žฅ์†Œ์—์„œ ์ž‘์—…ํ•  ๋•Œ ์ง€ํ‚ค๋Š” ๊ทœ์น™์„ ์ •๋ฆฌํ•œ๋‹ค. ์‚ฌ์šฉ์ž์˜ ๋ช…์‹œ์  ์ง€์‹œ๊ฐ€ ์žˆ์œผ๋ฉด ๊ทธ๊ฒƒ์„ ์šฐ์„ ํ•œ๋‹ค. + +KNU-Matzip ๋ฐฑ์—”๋“œ. Spring Boot 3.4 (Java 17) + JPA + MySQL. + +## ๊ตฌ์กฐ + +๋‹จ์ผ Gradle ๋ชจ๋“ˆ์ด๋ฉฐ `com.matzip` ์•„๋ž˜๋ฅผ **๋„๋ฉ”์ธ๋ณ„๋กœ ๋‚˜๋ˆˆ(package-by-domain)** ๊ตฌ์กฐ๋‹ค. +๋„๋ฉ”์ธ ํŒจํ‚ค์ง€ ๋‚ด๋ถ€๋Š” **๊ณ ์ „ 3๊ณ„์ธต ๋ ˆ์ด์–ด๋“œ ์•„ํ‚คํ…์ฒ˜**๋กœ ํ†ต์ผํ•œ๋‹ค. ์˜์กด์€ ์œ„์—์„œ ์•„๋ž˜๋กœ ๋‹จ๋ฐฉํ–ฅ, ์ง์ ‘ ํ˜ธ์ถœํ•œ๋‹ค. + +```text +controller -> service -> repository -> DB + (client: DB๊ฐ€ ์•„๋‹Œ ์™ธ๋ถ€ ์—ฐ๋™ ์–ด๋Œ‘ํ„ฐ โ€” service๊ฐ€ ์ง์ ‘ ํ˜ธ์ถœ) +``` + +- ๋„๋ฉ”์ธ ํŒจํ‚ค์ง€: `auth`(์นด์นด์˜ค ๋กœ๊ทธ์ธ/JWT ๋ฐœ๊ธ‰), `user`(ํ”„๋กœํ•„), `place`(๋ง›์ง‘ ๋“ฑ๋กยท์กฐํšŒยท์ฐœยท๊ฒ€์ƒ‰), `lottery`(์‘๋ชจ ์ด๋ฒคํŠธ), `admin`(๋ง›์ง‘ ์Šน์ธ/๊ฑฐ์ ˆ), `common`(๊ณตํ†ต). +- **ํ•˜์œ„ ๊ณ„์ธต์ด ์ƒ์œ„ ๊ณ„์ธต์— ์ •์˜๋œ ์ธํ„ฐํŽ˜์ด์Šค(port)๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ์˜์กด์„ฑ ์—ญ์ „ ๊ตฌ์กฐ๋ฅผ ์“ฐ์ง€ ์•Š๋Š”๋‹ค** (ํ—ฅ์‚ฌ๊ณ ๋‚  ์•„๋‹˜). ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ํ•„์š”ํ•˜๋ฉด ๊ทธ ์ธํ„ฐํŽ˜์ด์Šค๋Š” ์ž์‹ ์ด ์†ํ•œ ๊ณ„์ธต์— ๋‘”๋‹ค. +- ๋„๋ฉ”์ธ ํŒจํ‚ค์ง€ ๋‚ด๋ถ€ ํ‘œ์ค€: + - `controller/` โ€” Presentation. `@RestController`. ์š”์ฒญ/์‘๋‹ต ๋ฐ”๋””๋Š” `dto/`์˜ DTO ์‚ฌ์šฉ. + - `service/` โ€” Business. `@Service` ๊ตฌํ˜„์ฒด. **์ธํ„ฐํŽ˜์ด์Šค ์—†์ด ๊ตฌํ˜„์ฒด๋งŒ ๋‘”๋‹ค** (์‹ค์ œ ๊ต์ฒด๊ฐ€ ํ•„์š”ํ•œ ์˜ˆ์™ธ์—๋งŒ ์ธํ„ฐํŽ˜์ด์Šค ์ถ”๊ฐ€, ๊ทธ ์ธํ„ฐํŽ˜์ด์Šค๋„ ์ด ๊ณ„์ธต ์†Œ์œ ). + - `repository/` โ€” Data Access. Spring Data JPA ๋ฆฌํฌ์ง€ํ† ๋ฆฌ(์ธํ„ฐํŽ˜์ด์Šค = DAO, ๊ตฌํ˜„์€ ํ”„๋ ˆ์ž„์›Œํฌ ์ƒ์„ฑ). DB์™€ ์ง์ ‘ ํ†ต์‹ . + - `domain/` โ€” ๋„๋ฉ”์ธ ๋ชจ๋ธ. JPA ์—”ํ‹ฐํ‹ฐ(`domain/entity/`)์™€ enum/๊ฐ’ ํƒ€์ž…. ์—ฌ๋Ÿฌ ๊ณ„์ธต์—์„œ ๊ณต์œ . + - `dto/` โ€” ์ „์†ก ๊ฐ์ฒด. `dto/request/`, `dto/response/`๋กœ ๋‚˜๋ˆˆ๋‹ค. ์š”์ฒญ/์‘๋‹ต ์–‘์ชฝ์ด ๊ณต์œ ํ•˜๋Š” ์กฐ๊ฐ์€ `dto/` ๋ฃจํŠธ์— ๋‘”๋‹ค. + - `client/` (ํ•„์š”ํ•  ๋•Œ๋งŒ) โ€” DB๊ฐ€ ์•„๋‹Œ ์™ธ๋ถ€ ์—ฐ๋™ ์–ด๋Œ‘ํ„ฐ(์™ธ๋ถ€ API ํด๋ผ์ด์–ธํŠธยท์บ์‹œ ๋“ฑ). ์™ธ๋ถ€ ์‘๋‹ต ํŒŒ์‹ฑ DTO๋Š” `client/.../dto`. + - `event/` (ํ•„์š”ํ•  ๋•Œ๋งŒ) โ€” ์Šคํ”„๋ง ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ด๋ฒคํŠธ/๋ฆฌ์Šค๋„ˆ. ํŠน์ • ๊ณ„์ธต์— ์†ํ•˜์ง€ ์•Š๋Š” ๊ต์ฐจ ๊ด€์‹ฌ์‚ฌ๋ผ ์ „์šฉ ํŒจํ‚ค์ง€๋กœ ๋‘”๋‹ค. + +## ๊ตฌํ˜„ ๊ทœ์น™ + +### ์ปจํŠธ๋กค๋Ÿฌ์™€ ์‘๋‹ต + +- ๋ชจ๋“  ์ปจํŠธ๋กค๋Ÿฌ ์‘๋‹ต์€ `common/response/ApiResponse`๋กœ ๊ฐ์‹ผ๋‹ค. ํŒฉํ† ๋ฆฌ: `ApiResponse.success(data)`, `successWithoutData()`(DELETE/PATCH ๋“ฑ), `successWithEmptyList()`. ์‘๋‹ต ํ˜•ํƒœ๋Š” `{ status, timestamp, data, error }`. +- ๋น„์ฆˆ๋‹ˆ์Šค ์˜ˆ์™ธ๋Š” `BusinessException`(+ `ErrorCode` enum)์„ ๋˜์ง€๊ณ , `GlobalExceptionHandler`๊ฐ€ ์ค‘์•™์—์„œ `ApiResponse` ์—๋Ÿฌ ํ˜•ํƒœ๋กœ ๋ณ€ํ™˜ํ•œ๋‹ค. **์ปจํŠธ๋กค๋Ÿฌ์—์„œ try/catch ํ•˜์ง€ ์•Š๋Š”๋‹ค.** + +### ์ธ์ฆ + +- Stateless JWT. `JwtAuthenticationFilter`๊ฐ€ ํ† ํฐ์„ ๊ฒ€์ฆํ•ด `UserPrincipal`์„ ์„ธํŒ…ํ•œ๋‹ค(์„ธ์…˜ ์—†์Œ, CSRF off). +- `SecurityConfig`์ƒ ๋Œ€๋ถ€๋ถ„ ์—”๋“œํฌ์ธํŠธ๋Š” `permitAll`, ์ผ๋ถ€ ์ด๋ฒคํŠธ ์‘๋ชจ ๊ฒฝ๋กœ๋งŒ ์ธ์ฆ ํ•„์š”. +- ์ธ์ฆ ์—ฌ๋ถ€๋Š” ์ปจํŠธ๋กค๋Ÿฌ/์„œ๋น„์Šค๋‹จ์—์„œ `UserPrincipal` ์œ ๋ฌด๋กœ ๋ถ„๊ธฐํ•œ๋‹ค. + +### ์„œ๋น„์Šค + +- `service/`์—๋Š” `@Service` ๊ตฌํ˜„์ฒด๋งŒ ๋‘”๋‹ค. ์ƒ์œ„(controller)๊ฐ€ ํ•˜์œ„(service, repository)๋ฅผ ์ง์ ‘ ํ˜ธ์ถœํ•œ๋‹ค. +- ์™ธ๋ถ€ providerยท์บ์‹œ ๋“ฑ DB๊ฐ€ ์•„๋‹Œ ์—ฐ๋™์€ `client/`์˜ ์–ด๋Œ‘ํ„ฐ๋ฅผ service๊ฐ€ ์ง์ ‘ ์‚ฌ์šฉํ•œ๋‹ค. + +### ์˜์†์„ฑ + +- JPA ์—”ํ‹ฐํ‹ฐ๋Š” `domain/entity/`์— ๋‘”๋‹ค. +- ๋ชจ๋“  ์—”ํ‹ฐํ‹ฐ๋Š” `common/entity/BaseEntity`๋ฅผ ์ƒ์†ํ•ด `createdAt`/`updatedAt` ๊ฐ์‚ฌ(auditing)๋ฅผ ์ผ๊ด€๋˜๊ฒŒ ์ ์šฉํ•œ๋‹ค(`@MappedSuperclass` + `AuditingEntityListener`, PK๋Š” `IDENTITY`). +- ์Šคํ‚ค๋งˆ ๋ฐ˜์˜์€ ํ”„๋กœํŒŒ์ผ์„ ๋”ฐ๋ฅธ๋‹ค: `local`์€ `ddl-auto: update`, `prod`๋Š” `validate`. + +### DTO + +- ๋ชจ๋“  DTO๋Š” `Dto` ์ ‘๋ฏธ์‚ฌ๋ฅผ ๋ถ™์ธ๋‹ค. ์œ ์ผํ•œ ์˜ˆ์™ธ๋Š” ์‘๋‹ต ๋ž˜ํผ `ApiResponse`. +- HTTP ์š”์ฒญ/์‘๋‹ต DTO๋Š” `dto/request`ยท`dto/response`. ์š”์ฒญ/์‘๋‹ต์ด ๊ณต์œ ํ•˜๋Š” ์กฐ๊ฐ์€ `dto/` ๋ฃจํŠธ. ์™ธ๋ถ€ API ์‘๋‹ต ํŒŒ์‹ฑ DTO๋Š” ํ•ด๋‹น `client/.../dto`. +- ํ”„๋ ˆ์ž„์›Œํฌยท์—”ํ‹ฐํ‹ฐ ํƒ€์ž…์„ ์‘๋‹ต DTO ๋Œ€์‹  ๊ทธ๋Œ€๋กœ ๋…ธ์ถœํ•˜์ง€ ์•Š๋Š”๋‹ค. + +### ์„ค์ •๊ณผ ์•Œ๋ฆผ + +- ํ”„๋กœํผํ‹ฐ๋Š” `@ConfigurationProperties` ํด๋ž˜์Šค(`common/config/`์˜ `JwtProperties`, `KakaoProperties`, `ImageProperties`, `DiscordWebhookProperties` ๋“ฑ)๋กœ ๋ฐ”์ธ๋”ฉํ•œ๋‹ค. +- ๋ง›์ง‘ ๋“ฑ๋ก/๋‹น์ฒจ ์•Œ๋ฆผ์€ `common/infra/discord/DiscordWebhookSender`. ๋น„๋™๊ธฐ๋Š” `AsyncConfiguration`, ์Šค์ผ€์ค„๋Ÿฌ๋Š” `SchedulerConfiguration`. + +## ์ž‘์—… ๋ฐฉ์‹ + +1. ์ž‘์—… ์ „์— ๊ด€๋ จ ์ฝ”๋“œ, ํ…Œ์ŠคํŠธ, ์„ค์ •์„ ์ฝ๊ณ  ํ˜„์žฌ ๋™์ž‘์„ ๊ทผ๊ฑฐ๋กœ ์‚ผ๋Š”๋‹ค. +2. ์ƒˆ ์ž‘์—… ์ด์Šˆ๋Š” GitHub Issues์— ์ƒ์„ฑํ•˜๊ณ , ์ด์Šˆ ๋ฒˆํ˜ธ๋ฅผ ๋ธŒ๋žœ์น˜/PR ๋งฅ๋ฝ์— ์‚ฌ์šฉํ•œ๋‹ค(์˜ˆ: `refactor/142-place-layered`). +3. ๊ตฌํ˜„ ์ „์— ์‚ฌ์šฉ์ž์—๊ฒŒ ์ž‘์—… ๊ณ„ํš์„ ๋จผ์ € ๊ณต์œ ํ•˜๊ณ  ํ™•์ธ์„ ๋ฐ›๋Š”๋‹ค. +4. PR์„ ์˜ฌ๋ฆฌ๊ธฐ ์ „์— ๋ณ€๊ฒฝ ๋‚ด์šฉ๊ณผ ๊ฒ€์ฆ ๊ฒฐ๊ณผ๋ฅผ ์‚ฌ์šฉ์ž์—๊ฒŒ ๋จผ์ € ๋ฆฌ๋ทฐ๋ฐ›๋Š”๋‹ค. +5. ์š”๊ตฌ์‚ฌํ•ญ์„ ์ถ”์ธกํ•ด ๋ฉ”์šฐ์ง€ ์•Š๋Š”๋‹ค. ๋ชจํ˜ธํ•จ์ด ๊ฒฐ๊ณผ๋‚˜ ๊ณต๊ฐœ ๊ณ„์•ฝ(์—”๋“œํฌ์ธํŠธยท์‘๋‹ต ํ˜•ํƒœ)์„ ๋ฐ”๊พธ๋ฉด ์„ ํƒ์ง€์™€ ์˜ํ–ฅ์„ ๋ช…์‹œํ•˜๊ณ  ํ™•์ธํ•œ๋‹ค. +6. ์š”๊ตฌ ๋ฒ”์œ„๋ฅผ ์ถฉ์กฑํ•˜๋Š” ์ตœ์†Œ ๋ณ€๊ฒฝ๋งŒ ํ•œ๋‹ค. +7. ๋ณ€๊ฒฝ ์œ„ํ—˜์— ๋งž๋Š” ํ…Œ์ŠคํŠธ๋ฅผ ์ถ”๊ฐ€/์ˆ˜์ •ํ•˜๊ณ  ๊ฒ€์ฆํ•œ๋‹ค. ๊ฒ€์ฆํ•˜์ง€ ๋ชปํ•œ ํ•ญ๋ชฉ์„ ์™„๋ฃŒ๋กœ ํ‘œํ˜„ํ•˜์ง€ ์•Š๋Š”๋‹ค. + +## ์‹คํ–‰ + +- ๋กœ์ปฌ ์‹คํ–‰: `SPRING_PROFILES_ACTIVE=local ./gradlew bootRun` +- ๋กœ์ปฌ MySQL(`localhost:3306/knu_matzip`)๊ณผ env var๊ฐ€ ํ•„์š”ํ•˜๋‹ค: `DB_USER`, `DB_PASS`, `JWT_SECRET_KEY`, `KAKAO_CLIENT_ID`, `STATE_SECRET_KEY`. + +## ๊ฒ€์ฆ + +- ๋นŒ๋“œ(ํ…Œ์ŠคํŠธ ํฌํ•จ): `./gradlew build` +- ์ „์ฒด ํ…Œ์ŠคํŠธ: `./gradlew test` +- ๋‹จ์ผ ํ…Œ์ŠคํŠธ: `./gradlew test --tests "com.matzip.place.service.PlaceReadServiceTest"` (๋ฉ”์„œ๋“œ๊นŒ์ง€: `...PlaceServiceTest.๋ฉ”์„œ๋“œ๋ช…`) +- ํ…Œ์ŠคํŠธ๋Š” `src/test/resources/application.yml`์˜ H2 ์ธ๋ฉ”๋ชจ๋ฆฌ + ๋”๋ฏธ ์‹œํฌ๋ฆฟ์œผ๋กœ ์™„๊ฒฐ์ ์ด๋ผ ์™ธ๋ถ€ DBยท์‹œํฌ๋ฆฟ ์—†์ด ๋ˆ๋‹ค. + +## ์ปค๋ฐ‹ + +- ์ปค๋ฐ‹ ๋ฉ”์‹œ์ง€๋Š” `type: ์ œ๋ชฉ` ํ˜•์‹์œผ๋กœ ์“ด๋‹ค. ์˜ˆ: `refactor: place ๋„๋ฉ”์ธ์„ ๋ ˆ์ด์–ด๋“œ ํ‘œ์ค€ ํŒจํ‚ค์ง€๋กœ ํ†ต์ผ` +- `type`: `feat`, `fix`, `refactor`, `chore`, `docs` +- ์ œ๋ชฉ์€ ํ•œ๊ตญ์–ด๋กœ ๊ฐ„๊ฒฐํ•˜๊ฒŒ ์“ฐ๊ณ  ๋์— ๋งˆ์นจํ‘œ๋ฅผ ๋ถ™์ด์ง€ ์•Š๋Š”๋‹ค. +- ํ•˜๋‚˜์˜ ์ปค๋ฐ‹์€ ํ•˜๋‚˜์˜ ๋…ผ๋ฆฌ์  ๋ณ€๊ฒฝ๋งŒ ๋‹ด๋Š”๋‹ค. + +## Pull Request + +- PR base branch๋Š” ํ•ญ์ƒ `develop`์œผ๋กœ ์žก๋Š”๋‹ค. `main` push๊ฐ€ ์šด์˜ ๋ฐฐํฌ(EC2) ํŠธ๋ฆฌ๊ฑฐ๋‹ค. +- PR ์ œ๋ชฉ์€ ์ด์Šˆ ์œ ํ˜• ์ ‘๋‘์‚ฌ๋ฅผ ๋ถ™์ธ๋‹ค(์˜ˆ: `[refactor] ...`, `[feature] ...`). +- PR ๋ณธ๋ฌธ์€ `.github/pull_request_template.md` ํ˜•์‹(์ž‘์—… ๋‚ด์šฉ, ์ฒดํฌ๋ฆฌ์ŠคํŠธ, ๊ด€๋ จ ์ด์Šˆ)์„ ๋”ฐ๋ฅด๊ณ  `close #์ด์Šˆ๋ฒˆํ˜ธ`๋กœ ์—ฐ๊ฒฐํ•œ๋‹ค. \ No newline at end of file From 99190a9802efed629d2ce30a023996999458b115 Mon Sep 17 00:00:00 2001 From: gihhyeon Date: Wed, 2 Sep 2026 23:06:03 +0900 Subject: [PATCH 15/24] =?UTF-8?q?chore:=20PR=20=ED=85=9C=ED=94=8C=EB=A6=BF?= =?UTF-8?q?=EC=9D=84=20What/Why/How=20=EA=B5=AC=EC=A1=B0=EB=A1=9C=20?= =?UTF-8?q?=EA=B0=9C=ED=8E=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/pull_request_template.md | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 947c929..5bddbb2 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,20 +1,23 @@ -## ๐Ÿ“Œ PR ์ œ๋ชฉ -๊ฐ„๊ฒฐํ•˜๊ณ  ๋ช…ํ™•ํ•˜๊ฒŒ ์š”์•ฝ +## ์š”์•ฝ + -## โœ… ์ž‘์—… ๋‚ด์šฉ +## What โ€” ๋ฌด์—‡์„ ๋ฐ”๊ฟจ๋‚˜ + +- -- [ ] ์ž‘์—… 1: ์–ด๋–ค ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ–ˆ๋Š”์ง€ -- [ ] ์ž‘์—… 2: ์–ด๋–ค ๋ฒ„๊ทธ๋ฅผ ์ˆ˜์ •ํ–ˆ๋Š”์ง€ +## Why โ€” ์™œ ํ•„์š”ํ•œ๊ฐ€ + -## ๐Ÿ” ์ฒดํฌ๋ฆฌ์ŠคํŠธ +## How โ€” ์–ด๋–ป๊ฒŒ ๊ตฌํ˜„ํ–ˆ๋‚˜ + -- [ ] ์ฝ”๋“œ์— ๋ถˆํ•„์š”ํ•œ ์ฃผ์„/์ฝ”๋“œ ์ œ๊ฑฐ -- [ ] ๋ฆฌ๋ทฐ์–ด๊ฐ€ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋„๋ก ์„ค๋ช… ์ถ”๊ฐ€ +## ์ฒดํฌ๋ฆฌ์ŠคํŠธ +- [ ] ๋ถˆํ•„์š”ํ•œ ์ฃผ์„/์ฝ”๋“œ ์ œ๊ฑฐ +- [ ] ํ…Œ์ŠคํŠธ ์ถ”๊ฐ€/๊ฐฑ์‹  ๋ฐ ํ†ต๊ณผ (`./gradlew test`) +- [ ] ๊ณต๊ฐœ ๊ณ„์•ฝ ์˜ํ–ฅ ํ™•์ธ (์—”๋“œํฌ์ธํŠธยท์‘๋‹ต ํ˜•ํƒœ ๋ณ€๊ฒฝ ์‹œ ๋ฒ”์œ„ ๋ช…์‹œ) -## ๐ŸŽฏ ๊ด€๋ จ ์ด์Šˆ +## ๊ด€๋ จ ์ด์Šˆ +- close # -- close #์ด์Šˆ๋ฒˆํ˜ธ - -## ๐Ÿ’ฌ ๊ธฐํƒ€ ๊ณต์œ ํ•˜๊ณ  ์‹ถ์€ ๋‚ด์šฉ - -๊ธฐํƒ€ ๊ณต์œ ํ•  ๋งŒํ•œ ์ด์Šˆ, ๊ณ ๋ฏผ ๋“ฑ ์ž์œ ๋กญ๊ฒŒ ์ž‘์„ฑํ•ด์ฃผ์„ธ์š”. +## ๊ธฐํƒ€ / ๋ฆฌ๋ทฐ ํฌ์ธํŠธ + From 95c6b40e24e923e19cc595ba5166ac81c71f5838 Mon Sep 17 00:00:00 2001 From: gihhyeon Date: Thu, 3 Sep 2026 22:44:10 +0900 Subject: [PATCH 16/24] =?UTF-8?q?refactor:=20=EC=98=88=EC=99=B8=20?= =?UTF-8?q?=EC=B2=98=EB=A6=AC=20=EC=A0=95=EB=A6=AC=20=EB=B0=8F=20GlobalExc?= =?UTF-8?q?eptionHandler=20=ED=91=9C=EC=A4=80=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - ๋ฏธ์‚ฌ์šฉ ์˜ˆ์™ธ ํด๋ž˜์Šค 4๊ฐœ ์‚ญ์ œ (PlaceAlreadyExistsException, PlaceRegistrationException, ValidationException, ExceptionUtils) - GlobalExceptionHandler ๋กœ๊ทธ ๋ ˆ๋ฒจ์„ ์ƒํƒœ์ฝ”๋“œ๋กœ ๋ถ„๊ธฐ (5xx๋Š” error+์ŠคํƒํŠธ๋ ˆ์ด์Šค, 4xx๋Š” warn์œผ๋กœ ๋‚ฎ์ถฐ ๋กœ๊ทธ ์˜ค์—ผ ๋ฐฉ์ง€) - ์—๋Ÿฌ ์‘๋‹ต์— machine-readable code ํ•„๋“œ ์ถ”๊ฐ€ (ErrorInfo = {code, message}) - ๋ฏธ์‚ฌ์šฉ error(String, String) ์˜ค๋ฒ„๋กœ๋“œ ์ œ๊ฑฐ, error(ErrorCode) โ†’ error(ErrorCode, message) ์œ„์ž„์œผ๋กœ ์ค‘๋ณต ์ œ๊ฑฐ --- .../common/exception/ExceptionUtils.java | 93 ------------------- .../exception/GlobalExceptionHandler.java | 25 +++-- .../PlaceAlreadyExistsException.java | 13 --- .../exception/PlaceRegistrationException.java | 22 ----- .../common/exception/ValidationException.java | 22 ----- .../matzip/common/response/ApiResponse.java | 27 +----- 6 files changed, 21 insertions(+), 181 deletions(-) delete mode 100644 src/main/java/com/matzip/common/exception/ExceptionUtils.java delete mode 100644 src/main/java/com/matzip/common/exception/PlaceAlreadyExistsException.java delete mode 100644 src/main/java/com/matzip/common/exception/PlaceRegistrationException.java delete mode 100644 src/main/java/com/matzip/common/exception/ValidationException.java diff --git a/src/main/java/com/matzip/common/exception/ExceptionUtils.java b/src/main/java/com/matzip/common/exception/ExceptionUtils.java deleted file mode 100644 index 362c3b9..0000000 --- a/src/main/java/com/matzip/common/exception/ExceptionUtils.java +++ /dev/null @@ -1,93 +0,0 @@ -package com.matzip.common.exception; - -import com.matzip.common.exception.code.ErrorCode; - -public class ExceptionUtils { - - private ExceptionUtils() { - // ์œ ํ‹ธ๋ฆฌํ‹ฐ ํด๋ž˜์Šค์ด๋ฏ€๋กœ ์ธ์Šคํ„ด์Šค ์ƒ์„ฑ ๋ฐฉ์ง€ - } - - /** - * ์กฐ๊ฑด์ด ์ฐธ์ด๋ฉด BusinessException์„ ๋ฐœ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค. - */ - public static void throwIf(boolean condition, ErrorCode errorCode) { - if (condition) { - throw new BusinessException(errorCode); - } - } - - /** - * ์กฐ๊ฑด์ด ์ฐธ์ด๋ฉด BusinessException์„ ๋ฐœ์ƒ (์ปค์Šคํ…€ ๋ฉ”์‹œ์ง€ ํฌํ•จ) - */ - public static void throwIf(boolean condition, ErrorCode errorCode, String message) { - if (condition) { - throw new BusinessException(errorCode, message); - } - } - - /** - * ์กฐ๊ฑด์ด ๊ฑฐ์ง“์ด๋ฉด BusinessException์„ ๋ฐœ์ƒ - */ - public static void throwIfNot(boolean condition, ErrorCode errorCode) { - if (!condition) { - throw new BusinessException(errorCode); - } - } - - /** - * ์กฐ๊ฑด์ด ๊ฑฐ์ง“์ด๋ฉด BusinessException์„ ๋ฐœ์ƒ (์ปค์Šคํ…€ ๋ฉ”์‹œ์ง€ ํฌํ•จ) - */ - public static void throwIfNot(boolean condition, ErrorCode errorCode, String message) { - if (!condition) { - throw new BusinessException(errorCode, message); - } - } - - /** - * ๊ฐ์ฒด๊ฐ€ null์ด๋ฉด BusinessException์„ ๋ฐœ์ƒ - */ - public static void throwIfNull(Object object, ErrorCode errorCode) { - if (object == null) { - throw new BusinessException(errorCode); - } - } - - /** - * ๊ฐ์ฒด๊ฐ€ null์ด๋ฉด BusinessException์„ ๋ฐœ์ƒ (์ปค์Šคํ…€ ๋ฉ”์‹œ์ง€ ํฌํ•จ) - */ - public static void throwIfNull(Object object, ErrorCode errorCode, String message) { - if (object == null) { - throw new BusinessException(errorCode, message); - } - } - - /** - * ๋ฌธ์ž์—ด์ด ๋น„์–ด์žˆ์œผ๋ฉด BusinessException์„ ๋ฐœ์ƒ - */ - public static void throwIfEmpty(String string, ErrorCode errorCode) { - if (string == null || string.trim().isEmpty()) { - throw new BusinessException(errorCode); - } - } - - /** - * ๋ฌธ์ž์—ด์ด ๋น„์–ด์žˆ์œผ๋ฉด BusinessException์„ ๋ฐœ์ƒ (์ปค์Šคํ…€ ๋ฉ”์‹œ์ง€ ํฌํ•จ) - */ - public static void throwIfEmpty(String string, ErrorCode errorCode, String message) { - if (string == null || string.trim().isEmpty()) { - throw new BusinessException(errorCode, message); - } - } - - /** - * ์นดํ…Œ๊ณ ๋ฆฌ, ์ถ”์ฒœ ๋ฉ”๋‰ด, ํƒœ๊ทธ ๋“ฑ ๊ฐœ์ˆ˜ ์ œํ•œ - */ - public static void throwIfExceeds(int currentCount, int limit, ErrorCode errorCode) { - if (currentCount > limit) { - throw new BusinessException(errorCode); - } - } - - -} diff --git a/src/main/java/com/matzip/common/exception/GlobalExceptionHandler.java b/src/main/java/com/matzip/common/exception/GlobalExceptionHandler.java index b490a09..1493077 100644 --- a/src/main/java/com/matzip/common/exception/GlobalExceptionHandler.java +++ b/src/main/java/com/matzip/common/exception/GlobalExceptionHandler.java @@ -3,6 +3,7 @@ import com.matzip.common.exception.code.ErrorCode; import com.matzip.common.response.ApiResponse; import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.http.converter.HttpMessageNotReadableException; import org.springframework.validation.BindException; @@ -25,9 +26,15 @@ public class GlobalExceptionHandler { */ @ExceptionHandler(BaseException.class) protected ResponseEntity> handleBaseException(BaseException e) { - log.error("{}: {}", e.getClass().getSimpleName(), e.getMessage()); + HttpStatus status = e.getErrorCode().getStatus(); + // 5xx(์„œ๋ฒ„/์™ธ๋ถ€์—ฐ๋™ ์žฅ์• )๋งŒ ์ŠคํƒํŠธ๋ ˆ์ด์Šค์™€ ํ•จ๊ป˜ error, 4xx(์˜ˆ์ƒ๋œ ๊ทœ์น™ ์œ„๋ฐ˜)๋Š” warn + if (status.is5xxServerError()) { + log.error("{}: {}", e.getClass().getSimpleName(), e.getMessage(), e); + } else { + log.warn("{}: {}", e.getClass().getSimpleName(), e.getMessage()); + } return ResponseEntity - .status(e.getErrorCode().getStatus()) + .status(status) .body(ApiResponse.error(e.getErrorCode(), e.getMessage())); } @@ -36,7 +43,7 @@ protected ResponseEntity> handleBaseException(BaseException e) */ @ExceptionHandler(MethodArgumentNotValidException.class) protected ResponseEntity> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) { - log.error("MethodArgumentNotValidException: {}", e.getMessage()); + log.warn("MethodArgumentNotValidException: {}", e.getMessage()); String detail = e.getBindingResult().getFieldErrors().get(0).getDefaultMessage(); return ResponseEntity .status(ErrorCode.VALIDATION_ERROR.getStatus()) @@ -48,7 +55,7 @@ protected ResponseEntity> handleMethodArgumentNotValidExceptio */ @ExceptionHandler(BindException.class) protected ResponseEntity> handleBindException(BindException e) { - log.error("BindException: {}", e.getMessage()); + log.warn("BindException: {}", e.getMessage()); String detail = e.getBindingResult().getFieldErrors().get(0).getDefaultMessage(); return ResponseEntity .status(ErrorCode.VALIDATION_ERROR.getStatus()) @@ -60,7 +67,7 @@ protected ResponseEntity> handleBindException(BindException e) */ @ExceptionHandler(HttpRequestMethodNotSupportedException.class) protected ResponseEntity> handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e) { - log.error("HttpRequestMethodNotSupportedException: {}", e.getMessage()); + log.warn("HttpRequestMethodNotSupportedException: {}", e.getMessage()); return ResponseEntity .status(ErrorCode.METHOD_NOT_ALLOWED.getStatus()) .body(ApiResponse.error(ErrorCode.METHOD_NOT_ALLOWED)); @@ -71,7 +78,7 @@ protected ResponseEntity> handleHttpRequestMethodNotSupportedE */ @ExceptionHandler(MissingServletRequestParameterException.class) protected ResponseEntity> handleMissingServletRequestParameterException(MissingServletRequestParameterException e) { - log.error("MissingServletRequestParameterException: {}", e.getMessage()); + log.warn("MissingServletRequestParameterException: {}", e.getMessage()); String message = getMissingParameterMessage(e.getParameterName()); return ResponseEntity .status(ErrorCode.INVALID_INPUT_VALUE.getStatus()) @@ -93,7 +100,7 @@ private String getMissingParameterMessage(String parameterName) { */ @ExceptionHandler(HttpMessageNotReadableException.class) protected ResponseEntity> handleHttpMessageNotReadableException(HttpMessageNotReadableException e) { - log.error("HttpMessageNotReadableException: {}", e.getMessage()); + log.warn("HttpMessageNotReadableException: {}", e.getMessage()); return ResponseEntity .status(ErrorCode.INVALID_INPUT_VALUE.getStatus()) .body(ApiResponse.error(ErrorCode.INVALID_INPUT_VALUE, "์ž˜๋ชป๋œ ์š”์ฒญ ๋ณธ๋ฌธ์ž…๋‹ˆ๋‹ค.")); @@ -104,7 +111,7 @@ protected ResponseEntity> handleHttpMessageNotReadableExceptio */ @ExceptionHandler(MethodArgumentTypeMismatchException.class) protected ResponseEntity> handleMethodArgumentTypeMismatchException(MethodArgumentTypeMismatchException e) { - log.error("MethodArgumentTypeMismatchException: {}", e.getMessage()); + log.warn("MethodArgumentTypeMismatchException: {}", e.getMessage()); return ResponseEntity .status(ErrorCode.INVALID_TYPE_VALUE.getStatus()) .body(ApiResponse.error(ErrorCode.INVALID_TYPE_VALUE, e.getMessage())); @@ -126,7 +133,7 @@ protected ResponseEntity> handleNoResourceFound(NoResourceFoun */ @ExceptionHandler(NoHandlerFoundException.class) protected ResponseEntity> handleNoHandlerFoundException(NoHandlerFoundException e) { - log.error("NoHandlerFoundException: {}", e.getMessage()); + log.warn("NoHandlerFoundException: {}", e.getMessage()); return ResponseEntity .status(ErrorCode.INVALID_INPUT_VALUE.getStatus()) .body(ApiResponse.error(ErrorCode.INVALID_INPUT_VALUE, "์š”์ฒญํ•œ ๋ฆฌ์†Œ์Šค๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.")); diff --git a/src/main/java/com/matzip/common/exception/PlaceAlreadyExistsException.java b/src/main/java/com/matzip/common/exception/PlaceAlreadyExistsException.java deleted file mode 100644 index ba4ffeb..0000000 --- a/src/main/java/com/matzip/common/exception/PlaceAlreadyExistsException.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.matzip.common.exception; - -import com.matzip.common.exception.code.ErrorCode; - -public class PlaceAlreadyExistsException extends BusinessException { - public PlaceAlreadyExistsException() { - super(ErrorCode.PLACE_ALREADY_EXISTS); - } - - public PlaceAlreadyExistsException(String message) { - super(ErrorCode.PLACE_ALREADY_EXISTS, message); - } -} diff --git a/src/main/java/com/matzip/common/exception/PlaceRegistrationException.java b/src/main/java/com/matzip/common/exception/PlaceRegistrationException.java deleted file mode 100644 index a68743d..0000000 --- a/src/main/java/com/matzip/common/exception/PlaceRegistrationException.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.matzip.common.exception; - -import com.matzip.common.exception.code.ErrorCode; - -public class PlaceRegistrationException extends BaseException { - - public PlaceRegistrationException(ErrorCode errorCode) { - super(errorCode); - } - - public PlaceRegistrationException(ErrorCode errorCode, String message) { - super(errorCode, message); - } - - public PlaceRegistrationException(ErrorCode errorCode, Throwable cause) { - super(errorCode, cause); - } - - public PlaceRegistrationException(ErrorCode errorCode, String message, Throwable cause) { - super(errorCode, message, cause); - } -} diff --git a/src/main/java/com/matzip/common/exception/ValidationException.java b/src/main/java/com/matzip/common/exception/ValidationException.java deleted file mode 100644 index 98b97f1..0000000 --- a/src/main/java/com/matzip/common/exception/ValidationException.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.matzip.common.exception; - -import com.matzip.common.exception.code.ErrorCode; - -public class ValidationException extends BaseException { - - public ValidationException(ErrorCode errorCode) { - super(errorCode); - } - - public ValidationException(ErrorCode errorCode, String message) { - super(errorCode, message); - } - - public ValidationException(ErrorCode errorCode, Throwable cause) { - super(errorCode, cause); - } - - public ValidationException(ErrorCode errorCode, String message, Throwable cause) { - super(errorCode, message, cause); - } -} diff --git a/src/main/java/com/matzip/common/response/ApiResponse.java b/src/main/java/com/matzip/common/response/ApiResponse.java index a3193f7..23551d5 100644 --- a/src/main/java/com/matzip/common/response/ApiResponse.java +++ b/src/main/java/com/matzip/common/response/ApiResponse.java @@ -60,32 +60,13 @@ public static ApiResponse successWithEmptyList() { .build(); } - /** - * ์‹คํŒจ ์‘๋‹ต ์ƒ์„ฑ - */ - public static ApiResponse error(String code, String message) { - return ApiResponse.builder() - .status("ERROR") - .timestamp(LocalDateTime.now()) - .error(ErrorInfo.builder() - .message(message) - .build()) - .build(); - } - /** * ์‹คํŒจ ์‘๋‹ต ์ƒ์„ฑ (ErrorCode ์‚ฌ์šฉ) */ public static ApiResponse error(ErrorCode errorCode) { - return ApiResponse.builder() - .status("ERROR") - .timestamp(LocalDateTime.now()) - .error(ErrorInfo.builder() - .message(errorCode.getMessage()) - .build()) - .build(); + return error(errorCode, errorCode.getMessage()); } - + /** * ์‹คํŒจ ์‘๋‹ต ์ƒ์„ฑ (ErrorCode + ์ƒ์„ธ ๋ฉ”์‹œ์ง€) */ @@ -94,14 +75,16 @@ public static ApiResponse error(ErrorCode errorCode, String detailMessage .status("ERROR") .timestamp(LocalDateTime.now()) .error(ErrorInfo.builder() + .code(errorCode.name()) .message(detailMessage) .build()) .build(); } - + @Getter @Builder public static class ErrorInfo { + private final String code; private final String message; } } From 578f32cd56445a448e3224f6ed4dc6bf2103e567 Mon Sep 17 00:00:00 2001 From: gihhyeon Date: Fri, 4 Sep 2026 18:20:53 +0900 Subject: [PATCH 17/24] =?UTF-8?q?refactor:=20=EC=99=B8=EB=B6=80=20API=20?= =?UTF-8?q?=ED=98=B8=EC=B6=9C=EC=97=90=20=EA=B3=B5=ED=86=B5=20=ED=83=80?= =?UTF-8?q?=EC=9E=84=EC=95=84=EC=9B=83=20=EC=84=A4=EC=A0=95=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - HttpClientConfig ์‹ ๊ทœ: RestClientCustomizer/WebClientCustomizer๋กœ connect 2s / read 5s ํƒ€์ž„์•„์›ƒ์„ ์ž๋™ ๊ตฌ์„ฑ ๋นŒ๋”์— ์ค‘์•™ ์ ์šฉ - KakaoApiClient๋ฅผ RestClient.Builder ์ฃผ์ž… ๋ฐฉ์‹์œผ๋กœ ๋ณ€๊ฒฝํ•ด ์ปค์Šคํ„ฐ๋งˆ์ด์ € ํƒ€์ž„์•„์›ƒ์ด ์ ์šฉ๋˜๋„๋ก ํ•จ (no-arg ์ž์ฒด๋นŒ๋“œ ์ƒ์„ฑ์ž ์ œ๊ฑฐ) - Discord/KakaoLogin WebClient๋Š” ์ฃผ์ž…๋œ ๋นŒ๋”๋กœ ํƒ€์ž„์•„์›ƒ ์ž๋™ ์ƒ์† --- .../common/config/HttpClientConfig.java | 38 +++++++++++++++++++ .../place/client/kakao/KakaoApiClient.java | 10 ++--- 2 files changed, 41 insertions(+), 7 deletions(-) create mode 100644 src/main/java/com/matzip/common/config/HttpClientConfig.java diff --git a/src/main/java/com/matzip/common/config/HttpClientConfig.java b/src/main/java/com/matzip/common/config/HttpClientConfig.java new file mode 100644 index 0000000..d2ba788 --- /dev/null +++ b/src/main/java/com/matzip/common/config/HttpClientConfig.java @@ -0,0 +1,38 @@ +package com.matzip.common.config; + +import io.netty.channel.ChannelOption; +import java.time.Duration; +import org.springframework.boot.http.client.ClientHttpRequestFactoryBuilder; +import org.springframework.boot.http.client.ClientHttpRequestFactorySettings; +import org.springframework.boot.web.client.RestClientCustomizer; +import org.springframework.boot.web.reactive.function.client.WebClientCustomizer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.client.reactive.ReactorClientHttpConnector; +import reactor.netty.http.client.HttpClient; + + +@Configuration +public class HttpClientConfig { + + private static final Duration CONNECT_TIMEOUT = Duration.ofSeconds(2); + private static final Duration READ_TIMEOUT = Duration.ofSeconds(5); + + @Bean + RestClientCustomizer restClientTimeoutCustomizer() { + ClientHttpRequestFactorySettings settings = ClientHttpRequestFactorySettings.defaults() + .withConnectTimeout(CONNECT_TIMEOUT) + .withReadTimeout(READ_TIMEOUT); + return builder -> builder.requestFactory( + ClientHttpRequestFactoryBuilder.detect().build(settings)); + } + + + @Bean + WebClientCustomizer webClientTimeoutCustomizer() { + HttpClient httpClient = HttpClient.create() + .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, (int) CONNECT_TIMEOUT.toMillis()) + .responseTimeout(READ_TIMEOUT); + return builder -> builder.clientConnector(new ReactorClientHttpConnector(httpClient)); + } +} diff --git a/src/main/java/com/matzip/place/client/kakao/KakaoApiClient.java b/src/main/java/com/matzip/place/client/kakao/KakaoApiClient.java index a695a3b..c41a0a1 100644 --- a/src/main/java/com/matzip/place/client/kakao/KakaoApiClient.java +++ b/src/main/java/com/matzip/place/client/kakao/KakaoApiClient.java @@ -22,17 +22,13 @@ public class KakaoApiClient { private final RestClient restClient; - public KakaoApiClient() { - this(RestClient.builder() + public KakaoApiClient(RestClient.Builder restClientBuilder) { + this.restClient = restClientBuilder .baseUrl(BASE_URL) .defaultHeader("Pf", "web") .defaultHeader(HttpHeaders.REFERER, REFERER) .defaultHeader(HttpHeaders.USER_AGENT, USER_AGENT) - .build()); - } - - public KakaoApiClient(RestClient restClient) { - this.restClient = restClient; + .build(); } /** From 0361401a03695e78ce2a4b2e31377185c5402644 Mon Sep 17 00:00:00 2001 From: gihhyeon Date: Fri, 4 Sep 2026 19:02:51 +0900 Subject: [PATCH 18/24] =?UTF-8?q?refactor:=20=EC=A2=8B=EC=95=84=EC=9A=94?= =?UTF-8?q?=20=EC=88=98=20=EC=A6=9D=EA=B0=90=EC=9D=84=20=EC=9B=90=EC=9E=90?= =?UTF-8?q?=EC=A0=81=20UPDATE=EB=A1=9C=20=EB=B3=80=EA=B2=BD=ED=95=B4=20los?= =?UTF-8?q?t-update=20=EB=B0=A9=EC=A7=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - PlaceRepository์— incrementLikeCount/decrementLikeCount @Modifying ์ฟผ๋ฆฌ ์ถ”๊ฐ€ (๊ธฐ์กด incrementViewCount์™€ ๋™์ผ ํŒจํ„ด, decrement๋Š” likeCount > 0 ์กฐ๊ฑด์œผ๋กœ 0 ๋ฏธ๋งŒ ๋ฐฉ์ง€) - PlaceLikeService์˜ addLike/removeLike๊ฐ€ ์—”ํ‹ฐํ‹ฐ in-memory ์ฆ๊ฐ ๋Œ€์‹  ์›์ž์  ์ฟผ๋ฆฌ ์‚ฌ์šฉ - ์„œ๋กœ ๋‹ค๋ฅธ ์‚ฌ์šฉ์ž๊ฐ€ ๋™์‹œ์— ๊ฐ™์€ ๋ง›์ง‘์„ ์ข‹์•„์š”ํ•  ๋•Œ ์ฆ๊ฐ€๋ถ„์ด ์œ ์‹ค๋˜๋˜ ๋ฌธ์ œ ํ•ด๊ฒฐ - ์ด์ œ ์‚ฌ์šฉ๋˜์ง€ ์•Š๋Š” Place.incrementLikeCount/decrementLikeCount ์ œ๊ฑฐ - ๋™์‹œ์„ฑ ํšŒ๊ท€ ๋ฐฉ์ง€ ํ…Œ์ŠคํŠธ(PlaceLikeServiceConcurrencyTest) ์ถ”๊ฐ€ --- .../com/matzip/place/domain/entity/Place.java | 9 --- .../place/repository/PlaceRepository.java | 8 +++ .../place/service/PlaceLikeService.java | 6 +- .../PlaceLikeServiceConcurrencyTest.java | 67 +++++++++++++++++++ 4 files changed, 78 insertions(+), 12 deletions(-) create mode 100644 src/test/java/com/matzip/place/service/PlaceLikeServiceConcurrencyTest.java diff --git a/src/main/java/com/matzip/place/domain/entity/Place.java b/src/main/java/com/matzip/place/domain/entity/Place.java index c493f3c..5fb6005 100644 --- a/src/main/java/com/matzip/place/domain/entity/Place.java +++ b/src/main/java/com/matzip/place/domain/entity/Place.java @@ -120,13 +120,4 @@ public List getTags() { .toList(); } - public void incrementLikeCount() { - this.likeCount++; - } - - public void decrementLikeCount() { - if (this.likeCount > 0) { - this.likeCount--; - } - } } diff --git a/src/main/java/com/matzip/place/repository/PlaceRepository.java b/src/main/java/com/matzip/place/repository/PlaceRepository.java index d6c5998..e80345a 100644 --- a/src/main/java/com/matzip/place/repository/PlaceRepository.java +++ b/src/main/java/com/matzip/place/repository/PlaceRepository.java @@ -52,6 +52,14 @@ List findWithinBoundsAndSortByDistance( @Query("UPDATE Place p SET p.viewCount = p.viewCount + 1 WHERE p.id = :placeId") void incrementViewCount(@Param("placeId") Long placeId); + @Modifying + @Query("UPDATE Place p SET p.likeCount = p.likeCount + 1 WHERE p.id = :placeId") + void incrementLikeCount(@Param("placeId") Long placeId); + + @Modifying + @Query("UPDATE Place p SET p.likeCount = p.likeCount - 1 WHERE p.id = :placeId AND p.likeCount > 0") + void decrementLikeCount(@Param("placeId") Long placeId); + @EntityGraph(attributePaths = {"placeCategories.category", "placeTags.tag"}) @Query("SELECT DISTINCT p FROM Place p " + "JOIN p.placeCategories pc " + diff --git a/src/main/java/com/matzip/place/service/PlaceLikeService.java b/src/main/java/com/matzip/place/service/PlaceLikeService.java index aa6dd60..3f8ba38 100644 --- a/src/main/java/com/matzip/place/service/PlaceLikeService.java +++ b/src/main/java/com/matzip/place/service/PlaceLikeService.java @@ -45,8 +45,8 @@ public PlaceLikeResponseDto addLike(Long userId, Long placeId) { } placeLikeRepository.save(PlaceLike.of(user, place)); - place.incrementLikeCount(); - + placeRepository.incrementLikeCount(placeId); + return PlaceLikeResponseDto.addLike(placeId); } @@ -57,7 +57,7 @@ public PlaceLikeResponseDto removeLike(Long userId, Long placeId) { placeLikeRepository.findByUserAndPlace(user, place).ifPresent(placeLike -> { placeLikeRepository.delete(placeLike); - place.decrementLikeCount(); + placeRepository.decrementLikeCount(placeId); }); return PlaceLikeResponseDto.removeLike(placeId); diff --git a/src/test/java/com/matzip/place/service/PlaceLikeServiceConcurrencyTest.java b/src/test/java/com/matzip/place/service/PlaceLikeServiceConcurrencyTest.java new file mode 100644 index 0000000..3f2202f --- /dev/null +++ b/src/test/java/com/matzip/place/service/PlaceLikeServiceConcurrencyTest.java @@ -0,0 +1,67 @@ +package com.matzip.place.service; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.matzip.AbstractMatzipApplicationTest; +import com.matzip.fixture.UserFixtures; +import com.matzip.place.domain.entity.Place; +import com.matzip.place.repository.PlaceRepository; +import com.matzip.user.domain.User; +import com.matzip.user.repository.UserRepository; +import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.stream.IntStream; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +class PlaceLikeServiceConcurrencyTest extends AbstractMatzipApplicationTest { + + private final ExecutorService executorService = Executors.newFixedThreadPool(16); + + @Autowired + private PlaceLikeService placeLikeService; + @Autowired + private UserRepository userRepository; + @Autowired + private PlaceRepository placeRepository; + + @AfterEach + void tearDown() { + executorService.shutdown(); + } + + @Test + void ์„œ๋กœ_๋‹ค๋ฅธ_์‚ฌ์šฉ์ž๊ฐ€_๋™์‹œ์—_์ข‹์•„์š”๋ฅผ_๋ˆŒ๋Ÿฌ๋„_์ข‹์•„์š”_์ˆ˜๊ฐ€_์œ ์‹ค๋˜์ง€_์•Š๋Š”๋‹ค() throws InterruptedException { + // given: ๋™์ผ place์— ์ข‹์•„์š”๋ฅผ ๋ˆ„๋ฅผ ์„œ๋กœ ๋‹ค๋ฅธ ์‚ฌ์šฉ์ž N๋ช… + int userCount = 20; + Long placeId = testPlaces.get(0).getId(); + List likers = IntStream.range(0, userCount) + .mapToObj(i -> userRepository.save(UserFixtures.createUserWith("liker" + i))) + .toList(); + + // when: ๋ชจ๋“  ์‚ฌ์šฉ์ž๊ฐ€ ๋™์‹œ์— addLike ํ˜ธ์ถœ + CountDownLatch startLatch = new CountDownLatch(1); + CountDownLatch doneLatch = new CountDownLatch(userCount); + for (User liker : likers) { + executorService.submit(() -> { + try { + startLatch.await(); + placeLikeService.addLike(liker.getId(), placeId); + } catch (Exception e) { + log.error(e.getMessage(), e); + } finally { + doneLatch.countDown(); + } + }); + } + startLatch.countDown(); + doneLatch.await(); + + // then: ์›์ž์  UPDATE๋ผ๋ฉด ์ฆ๊ฐ€๋ถ„ ์œ ์‹ค ์—†์ด ์ •ํ™•ํžˆ N + Place place = placeRepository.findById(placeId).orElseThrow(); + assertThat(place.getLikeCount()).isEqualTo(userCount); + } +} From 4ae986fcf9714cab4a15116662d1addad3738090 Mon Sep 17 00:00:00 2001 From: gihhyeon Date: Mon, 7 Sep 2026 20:18:09 +0900 Subject: [PATCH 19/24] =?UTF-8?q?test:=20=EC=A2=8B=EC=95=84=EC=9A=94=20?= =?UTF-8?q?=EB=8F=99=EC=8B=9C=EC=84=B1=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EA=B2=AC=EA=B3=A0=EC=84=B1=20=EA=B0=9C=EC=84=A0=20(PR=20#158?= =?UTF-8?q?=20=EB=A6=AC=EB=B7=B0=20=EB=B0=98=EC=98=81)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - ์Šค๋ ˆ๋“œํ’€ ํฌ๊ธฐ๋ฅผ ์‚ฌ์šฉ์ž ์ˆ˜(20)๋กœ ๋งž์ถฐ ์‹ค์ œ 20-way ๋™์‹œ์„ฑ ๋ณด์žฅ (๊ธฐ์กด 16์œผ๋กœ๋Š” ์ตœ๋Œ€ 16-way) - doneLatch.await์— ํƒ€์ž„์•„์›ƒ(10s) + ์™„๋ฃŒ ์—ฌ๋ถ€ ๊ฒ€์ฆ์œผ๋กœ CI ๋ฌดํ•œ ๋Œ€๊ธฐ ๋ฐฉ์ง€ - ์›Œ์ปค ์Šค๋ ˆ๋“œ ์˜ˆ์™ธ๋ฅผ ์ˆ˜์ง‘ํ•ด ๊ฒ€์ฆํ•˜์—ฌ ์˜ˆ์™ธ๊ฐ€ ํ…Œ์ŠคํŠธ ์‹คํŒจ๋กœ ์ด์–ด์ง€๋„๋ก ๊ฐœ์„  (log.error๋กœ ์ŠคํƒํŠธ๋ ˆ์ด์Šค ๋‚จ๊ธฐ๊ณ  failures ํ๋กœ ํŒ์ •) --- .../PlaceLikeServiceConcurrencyTest.java | 28 ++++++++++++------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/src/test/java/com/matzip/place/service/PlaceLikeServiceConcurrencyTest.java b/src/test/java/com/matzip/place/service/PlaceLikeServiceConcurrencyTest.java index 3f2202f..d5f0525 100644 --- a/src/test/java/com/matzip/place/service/PlaceLikeServiceConcurrencyTest.java +++ b/src/test/java/com/matzip/place/service/PlaceLikeServiceConcurrencyTest.java @@ -9,9 +9,11 @@ import com.matzip.user.domain.User; import com.matzip.user.repository.UserRepository; import java.util.List; +import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; import java.util.stream.IntStream; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; @@ -19,7 +21,10 @@ class PlaceLikeServiceConcurrencyTest extends AbstractMatzipApplicationTest { - private final ExecutorService executorService = Executors.newFixedThreadPool(16); + private static final int USER_COUNT = 20; + + // ํ’€ ํฌ๊ธฐ๋ฅผ ์‚ฌ์šฉ์ž ์ˆ˜ ์ด์ƒ์œผ๋กœ ๋‘์–ด ์‹ค์ œ USER_COUNT-way ๋™์‹œ์„ฑ์„ ๋ณด์žฅํ•œ๋‹ค. + private final ExecutorService executorService = Executors.newFixedThreadPool(USER_COUNT); @Autowired private PlaceLikeService placeLikeService; @@ -30,38 +35,41 @@ class PlaceLikeServiceConcurrencyTest extends AbstractMatzipApplicationTest { @AfterEach void tearDown() { - executorService.shutdown(); + executorService.shutdownNow(); } @Test void ์„œ๋กœ_๋‹ค๋ฅธ_์‚ฌ์šฉ์ž๊ฐ€_๋™์‹œ์—_์ข‹์•„์š”๋ฅผ_๋ˆŒ๋Ÿฌ๋„_์ข‹์•„์š”_์ˆ˜๊ฐ€_์œ ์‹ค๋˜์ง€_์•Š๋Š”๋‹ค() throws InterruptedException { // given: ๋™์ผ place์— ์ข‹์•„์š”๋ฅผ ๋ˆ„๋ฅผ ์„œ๋กœ ๋‹ค๋ฅธ ์‚ฌ์šฉ์ž N๋ช… - int userCount = 20; Long placeId = testPlaces.get(0).getId(); - List likers = IntStream.range(0, userCount) + List likers = IntStream.range(0, USER_COUNT) .mapToObj(i -> userRepository.save(UserFixtures.createUserWith("liker" + i))) .toList(); - // when: ๋ชจ๋“  ์‚ฌ์šฉ์ž๊ฐ€ ๋™์‹œ์— addLike ํ˜ธ์ถœ + // when: ๋ชจ๋“  ์‚ฌ์šฉ์ž๊ฐ€ ๋™์‹œ์— addLike ํ˜ธ์ถœ (startLatch๋กœ ๋™์‹œ์„ฑ ๊ทน๋Œ€ํ™”) CountDownLatch startLatch = new CountDownLatch(1); - CountDownLatch doneLatch = new CountDownLatch(userCount); + CountDownLatch doneLatch = new CountDownLatch(USER_COUNT); + ConcurrentLinkedQueue failures = new ConcurrentLinkedQueue<>(); for (User liker : likers) { executorService.submit(() -> { try { startLatch.await(); placeLikeService.addLike(liker.getId(), placeId); } catch (Exception e) { - log.error(e.getMessage(), e); + log.error(e.getMessage(), e); // ์ŠคํƒํŠธ๋ ˆ์ด์Šค (์ง„๋‹จ์šฉ) + failures.add(e); // ํ…Œ์ŠคํŠธ ์‹คํŒจ ์กฐ๊ฑด (ํŒ์ •์šฉ) } finally { doneLatch.countDown(); } }); } startLatch.countDown(); - doneLatch.await(); + boolean completed = doneLatch.await(10, TimeUnit.SECONDS); - // then: ์›์ž์  UPDATE๋ผ๋ฉด ์ฆ๊ฐ€๋ถ„ ์œ ์‹ค ์—†์ด ์ •ํ™•ํžˆ N + // then: ๋ชจ๋“  ์ž‘์—…์ด ์‹œ๊ฐ„ ๋‚ด ์™„๋ฃŒ๋˜๊ณ , ์˜ˆ์™ธ ์—†์ด, ์ฆ๊ฐ€๋ถ„ ์œ ์‹ค ์—†์ด ์ •ํ™•ํžˆ N + assertThat(completed).isTrue(); + assertThat(failures).isEmpty(); Place place = placeRepository.findById(placeId).orElseThrow(); - assertThat(place.getLikeCount()).isEqualTo(userCount); + assertThat(place.getLikeCount()).isEqualTo(USER_COUNT); } } From 4f551f1660b0e5e8c733c54508b8e6555dc90c00 Mon Sep 17 00:00:00 2001 From: gihhyeon Date: Mon, 7 Sep 2026 23:36:49 +0900 Subject: [PATCH 20/24] =?UTF-8?q?fix:=20=EC=98=A4=EB=8A=98=EC=9D=98=20?= =?UTF-8?q?=EB=A7=9B=EC=A7=91=20=EC=A1=B0=ED=9A=8C=EC=88=98=20=EB=9E=AD?= =?UTF-8?q?=ED=82=B9=EC=9D=B4=20=EB=B9=88=20=EA=B0=92=EC=9D=84=20=EB=B0=98?= =?UTF-8?q?=ED=99=98=ED=95=98=EB=8A=94=20=EB=AC=B8=EC=A0=9C=20=ED=8F=B4?= =?UTF-8?q?=EB=B0=B1=EC=9C=BC=EB=A1=9C=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - ์˜ค๋Š˜ ์กฐํšŒ ๋ฐ์ดํ„ฐ๊ฐ€ ๋ถ€์กฑํ•œ ์ƒˆ๋ฒฝ/์ €ํŠธ๋ž˜ํ”ฝ ๊ตฌ๊ฐ„์— ๋นˆ ๋žญํ‚น์ด ๋‚˜์˜ค๋˜ ๋ฌธ์ œ ์ˆ˜์ • - getDailyRankingByViews๋ฅผ ํด๋ฐฑ ์ฒด์ธ์œผ๋กœ ๋ณ€๊ฒฝ (์˜ค๋Š˜ 3๊ณณ ์ด์ƒ โ†’ ์–ด์ œ 3๊ณณ ์ด์ƒ โ†’ ์ „์ฒด ๋ˆ„์  ์กฐํšŒ์ˆ˜) - ๋ˆ„์  ์กฐํšŒ์ˆ˜ ๋žญํ‚น ์ฟผ๋ฆฌ findTopByCampusOrderByViewCount ์ถ”๊ฐ€ - ๋žญํ‚น ๋ฉ”์„œ๋“œ ๊ณตํ†ต ๋กœ์ง์„ buildRankingResponse ํ—ฌํผ๋กœ ์ถ”์ถœ - ์˜ค๋Š˜์˜ ๋ง›์ง‘ ํด๋ฐฑ ์‹œ๋‚˜๋ฆฌ์˜ค ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ ์ถ”๊ฐ€ --- .../place/repository/PlaceRepository.java | 3 + .../place/service/PlaceReadService.java | 50 +++++----- .../application/PlaceReadServiceTest.java | 99 +++++++++++++++++++ 3 files changed, 128 insertions(+), 24 deletions(-) diff --git a/src/main/java/com/matzip/place/repository/PlaceRepository.java b/src/main/java/com/matzip/place/repository/PlaceRepository.java index e80345a..49e882e 100644 --- a/src/main/java/com/matzip/place/repository/PlaceRepository.java +++ b/src/main/java/com/matzip/place/repository/PlaceRepository.java @@ -72,6 +72,9 @@ List findWithinBoundsAndSortByDistance( @Query("SELECT p FROM Place p WHERE p.campus = :campus AND p.status = 'APPROVED' ORDER BY p.likeCount DESC") List findTopByCampusOrderByLikeCount(@Param("campus") Campus campus, Pageable pageable); + @Query("SELECT p FROM Place p WHERE p.campus = :campus AND p.status = 'APPROVED' ORDER BY p.viewCount DESC") + List findTopByCampusOrderByViewCount(@Param("campus") Campus campus, Pageable pageable); + @Query("SELECT p FROM Place p WHERE p.campus = :campus AND p.status = 'APPROVED' ORDER BY p.createdAt DESC") List findTopByCampusOrderByCreatedAtDesc(@Param("campus") Campus campus, Pageable pageable); diff --git a/src/main/java/com/matzip/place/service/PlaceReadService.java b/src/main/java/com/matzip/place/service/PlaceReadService.java index a545c7e..78dd7cb 100644 --- a/src/main/java/com/matzip/place/service/PlaceReadService.java +++ b/src/main/java/com/matzip/place/service/PlaceReadService.java @@ -130,46 +130,48 @@ public List getRanking(Campus campus, SortType sortType) return getRankingByLikes(campus); } + /** + * ์˜ค๋Š˜์˜ ๋ง›์ง‘(์กฐํšŒ์ˆ˜ ๋žญํ‚น). ์˜ค๋Š˜ ์กฐํšŒ ๋ฐ์ดํ„ฐ๊ฐ€ ๋ถ€์กฑํ•œ ์ƒˆ๋ฒฝ/์ €ํŠธ๋ž˜ํ”ฝ ๊ตฌ๊ฐ„์— ๋นˆ ๊ฐ’์ด ๋ฐ˜ํ™˜๋˜์ง€ ์•Š๋„๋ก + * ์˜ค๋Š˜(3๊ณณ ์ด์ƒ) โ†’ ์–ด์ œ(3๊ณณ ์ด์ƒ) โ†’ ์ „์ฒด ๋ˆ„์  ์กฐํšŒ์ˆ˜ ์ˆœ์œผ๋กœ ํด๋ฐฑํ•œ๋‹ค. + */ private List getDailyRankingByViews(Campus campus) { - LocalDate today = LocalDate.now(); Pageable topN = PageRequest.of(0, RANKING_SIZE); + LocalDate today = LocalDate.now(); - List dailyRankings = dailyViewCountRepository.findDailyRankingByCampus(campus, today, topN); - List places = dailyRankings.stream() - .map(DailyViewCount::getPlace) - .collect(Collectors.toList()); + List todayRanking = findDailyRankingPlaces(campus, today, topN); + if (todayRanking.size() >= RANKING_SIZE) { + return buildRankingResponse(todayRanking); + } - Map relatedDataMap = getPlaceRelatedDataInBatch(places); + List yesterdayRanking = findDailyRankingPlaces(campus, today.minusDays(1), topN); + if (yesterdayRanking.size() >= RANKING_SIZE) { + return buildRankingResponse(yesterdayRanking); + } - return dailyRankings.stream() - .map(dailyViewCount -> { - Place place = dailyViewCount.getPlace(); + List viewCountRanking = placeRepository.findTopByCampusOrderByViewCount(campus, topN); + return buildRankingResponse(viewCountRanking); + } - PlaceRelatedData relatedData = relatedDataMap.get(place.getId()); - return PlaceCommonResponseDto.from(place, relatedData.categories(), relatedData.tags()); - }) + private List findDailyRankingPlaces(Campus campus, LocalDate date, Pageable pageable) { + return dailyViewCountRepository.findDailyRankingByCampus(campus, date, pageable).stream() + .map(DailyViewCount::getPlace) .collect(Collectors.toList()); } private List getRankingByLikes(Campus campus) { Pageable topN = PageRequest.of(0, RANKING_SIZE); - - List places = placeRepository.findTopByCampusOrderByLikeCount(campus, topN); - - Map relatedDataMap = getPlaceRelatedDataInBatch(places); - - return places.stream() - .map(place -> { - PlaceRelatedData relatedData = relatedDataMap.get(place.getId()); - return PlaceCommonResponseDto.from(place, relatedData.categories(), relatedData.tags()); - }) - .collect(Collectors.toList()); + return buildRankingResponse(placeRepository.findTopByCampusOrderByLikeCount(campus, topN)); } private List getRankingByLatest(Campus campus) { Pageable topN = PageRequest.of(0, LATEST_PLACES_SIZE); - List places = placeRepository.findTopByCampusOrderByCreatedAtDesc(campus, topN); + return buildRankingResponse(placeRepository.findTopByCampusOrderByCreatedAtDesc(campus, topN)); + } + /** + * Place ๋ชฉ๋ก์„ ์—ฐ๊ด€ ๋ฐ์ดํ„ฐ(์นดํ…Œ๊ณ ๋ฆฌ/ํƒœ๊ทธ)์™€ ํ•จ๊ป˜ ์‘๋‹ต DTO๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๊ณตํ†ต ๋กœ์ง. + */ + private List buildRankingResponse(List places) { Map relatedDataMap = getPlaceRelatedDataInBatch(places); return places.stream() diff --git a/src/test/java/com/matzip/place/application/PlaceReadServiceTest.java b/src/test/java/com/matzip/place/application/PlaceReadServiceTest.java index 099eb06..424abd3 100644 --- a/src/test/java/com/matzip/place/application/PlaceReadServiceTest.java +++ b/src/test/java/com/matzip/place/application/PlaceReadServiceTest.java @@ -2,12 +2,21 @@ import com.matzip.place.service.PlaceReadService; import com.matzip.place.domain.Campus; +import com.matzip.place.domain.DailyViewCount; import com.matzip.place.domain.PlaceStatus; +import com.matzip.place.domain.SortType; import com.matzip.place.domain.entity.Place; +import com.matzip.place.dto.response.PlaceCommonResponseDto; import com.matzip.place.repository.DailyViewCountRepository; import com.matzip.place.repository.PlaceRepository; import com.matzip.user.domain.User; import com.matzip.user.repository.UserRepository; + +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.support.TransactionTemplate; + +import java.time.LocalDate; +import java.util.List; import lombok.extern.slf4j.Slf4j; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; @@ -39,6 +48,9 @@ public class PlaceReadServiceTest { @Autowired private DailyViewCountRepository dailyViewCountRepository; + @Autowired + private PlatformTransactionManager transactionManager; + private Place testPlace; private User testUser; @@ -114,4 +126,91 @@ void getPlaceDetail_concurrentAccess() throws InterruptedException { assertThat(finalPlace.getViewCount()).isEqualTo(numberOfThreads); }); } + + @Test + @DisplayName("์˜ค๋Š˜์˜ ๋ง›์ง‘: ์˜ค๋Š˜ ์กฐํšŒ์ˆ˜ ๋žญํ‚น์ด 3๊ณณ ์ด์ƒ์ด๋ฉด ์˜ค๋Š˜ ๋žญํ‚น์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค") + void dailyRanking_returnsToday_whenTodayHasEnough() { + // given + LocalDate today = LocalDate.now(); + Place p1 = createApprovedPlace("t1"); + Place p2 = createApprovedPlace("t2"); + Place p3 = createApprovedPlace("t3"); + saveDailyCount(p1, today, 10); + saveDailyCount(p2, today, 30); + saveDailyCount(p3, today, 20); + + // when + List result = placeReadService.getRanking(Campus.CHEONAN, SortType.VIEWS); + + // then: ์˜ค๋Š˜ count DESC ์ˆœ + assertThat(result).extracting(PlaceCommonResponseDto::getPlaceId) + .containsExactly(p2.getId(), p3.getId(), p1.getId()); + } + + @Test + @DisplayName("์˜ค๋Š˜์˜ ๋ง›์ง‘: ์˜ค๋Š˜์ด 3๊ณณ ๋ฏธ๋งŒ์ด๋ฉด ์–ด์ œ ๋žญํ‚น(3๊ณณ ์ด์ƒ)์œผ๋กœ ํด๋ฐฑํ•œ๋‹ค") + void dailyRanking_fallsBackToYesterday_whenTodayInsufficient() { + // given + LocalDate today = LocalDate.now(); + LocalDate yesterday = today.minusDays(1); + Place p1 = createApprovedPlace("y1"); + Place p2 = createApprovedPlace("y2"); + Place p3 = createApprovedPlace("y3"); + saveDailyCount(p1, today, 5); // ์˜ค๋Š˜์€ 1๊ณณ๋ฟ (3 ๋ฏธ๋งŒ) + saveDailyCount(p1, yesterday, 10); + saveDailyCount(p2, yesterday, 30); + saveDailyCount(p3, yesterday, 20); + + // when + List result = placeReadService.getRanking(Campus.CHEONAN, SortType.VIEWS); + + // then: ๋นˆ ๊ฐ’์ด ์•„๋‹ˆ๋ผ ์–ด์ œ ๋žญํ‚น์œผ๋กœ ํด๋ฐฑ + assertThat(result).extracting(PlaceCommonResponseDto::getPlaceId) + .containsExactly(p2.getId(), p3.getId(), p1.getId()); + } + + @Test + @DisplayName("์˜ค๋Š˜์˜ ๋ง›์ง‘: ์˜ค๋Š˜ยท์–ด์ œ ๋ชจ๋‘ 3๊ณณ ๋ฏธ๋งŒ์ด๋ฉด ์ „์ฒด ๋ˆ„์  ์กฐํšŒ์ˆ˜๋กœ ํด๋ฐฑํ•œ๋‹ค") + void dailyRanking_fallsBackToTotalViewCount_whenNoRecentData() { + // given: ์˜ค๋Š˜/์–ด์ œ daily ๋ฐ์ดํ„ฐ ์—†์Œ, ๋ˆ„์  ์กฐํšŒ์ˆ˜๋งŒ ์กด์žฌ + Place p1 = createApprovedPlace("v1"); + Place p2 = createApprovedPlace("v2"); + Place p3 = createApprovedPlace("v3"); + bumpViewCount(p1, 10); + bumpViewCount(p2, 30); + bumpViewCount(p3, 20); + + // when + List result = placeReadService.getRanking(Campus.CHEONAN, SortType.VIEWS); + + // then: ๋นˆ ๊ฐ’์ด ์•„๋‹ˆ๋ผ ๋ˆ„์  ์กฐํšŒ์ˆ˜ DESC๋กœ ํด๋ฐฑ + assertThat(result).isNotEmpty(); + assertThat(result).extracting(PlaceCommonResponseDto::getPlaceId) + .containsExactly(p2.getId(), p3.getId(), p1.getId()); + } + + private Place createApprovedPlace(String suffix) { + return placeRepository.save(Place.builder() + .name("๋ง›์ง‘_" + suffix) + .address("์ฃผ์†Œ_" + suffix) + .kakaoPlaceId("kakao_" + suffix) + .campus(Campus.CHEONAN) + .latitude(36.1) + .longitude(127.1) + .status(PlaceStatus.APPROVED) + .build()); + } + + private void saveDailyCount(Place place, LocalDate date, int count) { + dailyViewCountRepository.save(new DailyViewCount(place, date, count)); + } + + private void bumpViewCount(Place place, int times) { + // incrementViewCount๋Š” @Modifying์ด๋ผ ํŠธ๋žœ์žญ์…˜์ด ํ•„์š”ํ•˜๋‹ค (์šด์˜์—์„  ์„œ๋น„์Šค @Transactional ์•ˆ์—์„œ ํ˜ธ์ถœ๋จ) + new TransactionTemplate(transactionManager).executeWithoutResult(status -> { + for (int i = 0; i < times; i++) { + placeRepository.incrementViewCount(place.getId()); + } + }); + } } From eedcb795a79ceb73a8feea6ea7b7311bf597874f Mon Sep 17 00:00:00 2001 From: gihhyeon Date: Tue, 8 Sep 2026 23:25:12 +0900 Subject: [PATCH 21/24] =?UTF-8?q?feat:=20=EB=B9=84=EC=A6=88=EB=8B=88?= =?UTF-8?q?=EC=8A=A4=20=EC=9D=B4=EB=B2=A4=ED=8A=B8=20=EB=A1=9C=EA=B9=85=20?= =?UTF-8?q?=EC=9D=B8=ED=94=84=EB=9D=BC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - common/analytics: EventType/TargetType, EventLog(BaseEntity), AnalyticsEvent(record), AnalyticsRecorder(๋ฐœํ–‰ ํ—ฌํผ), AnalyticsEventListener(๋น„๋™๊ธฐ AFTER_COMMIT ์ ์žฌ), EventLogRepository, properties JSON ์ปจ๋ฒ„ํ„ฐ - ๊ธฐ์กด ApplicationEvent + @Async @TransactionalEventListener ํŒจํ„ด ์žฌ์‚ฌ์šฉ - fire-and-forget: ์ ์žฌ ์‹คํŒจ๊ฐ€ ๋น„์ฆˆ๋‹ˆ์Šค ํŠธ๋žœ์žญ์…˜์— ์˜ํ–ฅ ์—†์Œ --- .../common/analytics/AnalyticsEvent.java | 30 +++++++ .../analytics/AnalyticsEventListener.java | 37 +++++++++ .../common/analytics/AnalyticsRecorder.java | 32 ++++++++ .../common/analytics/JsonMapConverter.java | 44 ++++++++++ .../common/analytics/domain/EventType.java | 14 ++++ .../common/analytics/domain/TargetType.java | 9 +++ .../analytics/domain/entity/EventLog.java | 80 +++++++++++++++++++ .../repository/EventLogRepository.java | 7 ++ 8 files changed, 253 insertions(+) create mode 100644 src/main/java/com/matzip/common/analytics/AnalyticsEvent.java create mode 100644 src/main/java/com/matzip/common/analytics/AnalyticsEventListener.java create mode 100644 src/main/java/com/matzip/common/analytics/AnalyticsRecorder.java create mode 100644 src/main/java/com/matzip/common/analytics/JsonMapConverter.java create mode 100644 src/main/java/com/matzip/common/analytics/domain/EventType.java create mode 100644 src/main/java/com/matzip/common/analytics/domain/TargetType.java create mode 100644 src/main/java/com/matzip/common/analytics/domain/entity/EventLog.java create mode 100644 src/main/java/com/matzip/common/analytics/repository/EventLogRepository.java diff --git a/src/main/java/com/matzip/common/analytics/AnalyticsEvent.java b/src/main/java/com/matzip/common/analytics/AnalyticsEvent.java new file mode 100644 index 0000000..a4ab922 --- /dev/null +++ b/src/main/java/com/matzip/common/analytics/AnalyticsEvent.java @@ -0,0 +1,30 @@ +package com.matzip.common.analytics; + +import com.matzip.common.analytics.domain.EventType; +import com.matzip.common.analytics.domain.TargetType; + +import java.time.LocalDateTime; +import java.util.Map; + +/** + * ๋„๋ฉ”์ธ ์„œ๋น„์Šค๊ฐ€ ๋ฐœํ–‰ํ•˜๋Š” ๋ถ„์„ ์ด๋ฒคํŠธ ํŽ˜์ด๋กœ๋“œ + * ๋„๋ฉ”์ธ์€ ์ด record๋งŒ ๋ฐœํ–‰ํ•˜๊ณ , ์ ์žฌ ์ฑ…์ž„์€ AnalyticsEventListener๊ฐ€ ์ง„๋‹ค + */ +public record AnalyticsEvent( + EventType eventType, + Long userId, + String anonymousId, + TargetType targetType, + Long targetId, + Map properties, + LocalDateTime occurredAt +) { + + public static AnalyticsEvent of(EventType eventType, Long userId) { + return new AnalyticsEvent(eventType, userId, null, null, null, null, LocalDateTime.now()); + } + + public static AnalyticsEvent of(EventType eventType, Long userId, TargetType targetType, Long targetId) { + return new AnalyticsEvent(eventType, userId, null, targetType, targetId, null, LocalDateTime.now()); + } +} diff --git a/src/main/java/com/matzip/common/analytics/AnalyticsEventListener.java b/src/main/java/com/matzip/common/analytics/AnalyticsEventListener.java new file mode 100644 index 0000000..c5c3664 --- /dev/null +++ b/src/main/java/com/matzip/common/analytics/AnalyticsEventListener.java @@ -0,0 +1,37 @@ +package com.matzip.common.analytics; + +import com.matzip.common.analytics.domain.entity.EventLog; +import com.matzip.common.analytics.repository.EventLogRepository; +import lombok.extern.slf4j.Slf4j; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Component; +import org.springframework.transaction.event.TransactionPhase; +import org.springframework.transaction.event.TransactionalEventListener; + +/** + * ๋ถ„์„ ์ด๋ฒคํŠธ๋ฅผ event_log์— ์ ์žฌํ•œ๋‹ค. + * - AFTER_COMMIT: ์ปค๋ฐ‹๋œ ์•ก์…˜๋งŒ ๊ธฐ๋ก(๋กค๋ฐฑ๋˜๋ฉด ๋‚จ๊ธฐ์ง€ ์•Š์Œ) + * - fallbackExecution: ํŠธ๋žœ์žญ์…˜ ๋ฐ–์—์„œ ๋ฐœํ–‰๋œ ์ด๋ฒคํŠธ(์˜ˆ: ์ž๋™ ์‘๋ชจ ํ›„)๋„ ๋†“์น˜์ง€ ์•Š์Œ + * - @Async + try-catch: ์ ์žฌ ์‹คํŒจยท์ง€์—ฐ์ด ๋น„์ฆˆ๋‹ˆ์Šค ํ๋ฆ„์— ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š๋„๋ก ๊ฒฉ๋ฆฌ(fire-and-forget) + */ +@Slf4j +@Component +public class AnalyticsEventListener { + + private final EventLogRepository eventLogRepository; + + public AnalyticsEventListener(EventLogRepository eventLogRepository) { + this.eventLogRepository = eventLogRepository; + } + + @Async + @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT, fallbackExecution = true) + public void on(AnalyticsEvent event) { + try { + eventLogRepository.save(EventLog.from(event)); + } catch (Exception e) { + log.warn("[๋ถ„์„ ์ด๋ฒคํŠธ ์ ์žฌ ์‹คํŒจ] type={}, userId={}, targetId={}", + event.eventType(), event.userId(), event.targetId(), e); + } + } +} diff --git a/src/main/java/com/matzip/common/analytics/AnalyticsRecorder.java b/src/main/java/com/matzip/common/analytics/AnalyticsRecorder.java new file mode 100644 index 0000000..e6f5ee5 --- /dev/null +++ b/src/main/java/com/matzip/common/analytics/AnalyticsRecorder.java @@ -0,0 +1,32 @@ +package com.matzip.common.analytics; + +import com.matzip.common.analytics.domain.EventType; +import com.matzip.common.analytics.domain.TargetType; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.stereotype.Component; + +/** + * ๋„๋ฉ”์ธ ์„œ๋น„์Šค๊ฐ€ ํ•œ ์ค„๋กœ ๋ถ„์„ ์ด๋ฒคํŠธ๋ฅผ ๋ฐœํ–‰ํ•˜๋„๋ก ๋•๋Š” ์–‡์€ ํ—ฌํผ + * ์‹ค์ œ ์ ์žฌ๋Š” AnalyticsEventListener๊ฐ€ ์ปค๋ฐ‹ ์ดํ›„ ๋น„๋™๊ธฐ๋กœ ์ˆ˜ํ–‰ํ•œ๋‹ค. + */ +@Component +public class AnalyticsRecorder { + + private final ApplicationEventPublisher applicationEventPublisher; + + public AnalyticsRecorder(ApplicationEventPublisher applicationEventPublisher) { + this.applicationEventPublisher = applicationEventPublisher; + } + + public void record(AnalyticsEvent event) { + applicationEventPublisher.publishEvent(event); + } + + public void record(EventType eventType, Long userId) { + record(AnalyticsEvent.of(eventType, userId)); + } + + public void record(EventType eventType, Long userId, TargetType targetType, Long targetId) { + record(AnalyticsEvent.of(eventType, userId, targetType, targetId)); + } +} diff --git a/src/main/java/com/matzip/common/analytics/JsonMapConverter.java b/src/main/java/com/matzip/common/analytics/JsonMapConverter.java new file mode 100644 index 0000000..ac2954c --- /dev/null +++ b/src/main/java/com/matzip/common/analytics/JsonMapConverter.java @@ -0,0 +1,44 @@ +package com.matzip.common.analytics; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.persistence.AttributeConverter; +import jakarta.persistence.Converter; + +import java.util.Map; + +/** + * event_log.properties(๋ถ€๊ฐ€ ์†์„ฑ)๋ฅผ Map โ†” JSON ๋ฌธ์ž์—ด๋กœ ์ž๋™ ๋ณ€ํ™˜ํ•œ๋‹ค. + * ๊ฐ’์ด ์—†์œผ๋ฉด null๋กœ ์ €์žฅํ•ด ์ปฌ๋Ÿผ์„ ๋น„์›Œ๋‘”๋‹ค(MVP ๋‹จ๊ณ„์—์„  ๋Œ€๋ถ€๋ถ„ ๋น„์–ด ์žˆ์Œ) + */ +@Converter +public class JsonMapConverter implements AttributeConverter, String> { + + private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); + private static final TypeReference> MAP_TYPE = new TypeReference<>() { + }; + + @Override + public String convertToDatabaseColumn(Map attribute) { + if (attribute == null || attribute.isEmpty()) { + return null; + } + try { + return OBJECT_MAPPER.writeValueAsString(attribute); + } catch (Exception e) { + throw new IllegalArgumentException("์ด๋ฒคํŠธ properties ์ง๋ ฌํ™” ์‹คํŒจ", e); + } + } + + @Override + public Map convertToEntityAttribute(String dbData) { + if (dbData == null || dbData.isBlank()) { + return null; + } + try { + return OBJECT_MAPPER.readValue(dbData, MAP_TYPE); + } catch (Exception e) { + throw new IllegalArgumentException("์ด๋ฒคํŠธ properties ์—ญ์ง๋ ฌํ™” ์‹คํŒจ", e); + } + } +} diff --git a/src/main/java/com/matzip/common/analytics/domain/EventType.java b/src/main/java/com/matzip/common/analytics/domain/EventType.java new file mode 100644 index 0000000..a32c253 --- /dev/null +++ b/src/main/java/com/matzip/common/analytics/domain/EventType.java @@ -0,0 +1,14 @@ +package com.matzip.common.analytics.domain; + +/** + * ์„œ๋ฒ„์‚ฌ์ด๋“œ์—์„œ ์ ์žฌํ•˜๋Š” ๋น„์ฆˆ๋‹ˆ์Šค ์ด๋ฒคํŠธ ์ข…๋ฅ˜ + * GA4๊ฐ€ ๋ณด์ง€ ๋ชปํ•˜๊ฑฐ๋‚˜ DB ์กฐ์ธ์ด ํ•„์š”ํ•œ ์ด๋ฒคํŠธ๋งŒ ๋‚จ๊ธด๋‹ค. + */ +public enum EventType { + SIGNUP, + LOGIN, + PLACE_REGISTER_REQUESTED, + PLACE_APPROVED, + PLACE_REJECTED, + EVENT_ENTERED +} diff --git a/src/main/java/com/matzip/common/analytics/domain/TargetType.java b/src/main/java/com/matzip/common/analytics/domain/TargetType.java new file mode 100644 index 0000000..cb418f4 --- /dev/null +++ b/src/main/java/com/matzip/common/analytics/domain/TargetType.java @@ -0,0 +1,9 @@ +package com.matzip.common.analytics.domain; + +/** + * ์ด๋ฒคํŠธ๊ฐ€ ๊ฐ€๋ฆฌํ‚ค๋Š” ๋Œ€์ƒ ์ข…๋ฅ˜. target_id์™€ ํ•จ๊ป˜ ์ €์žฅํ•ด ๋น„์ฆˆ๋‹ˆ์Šค ํ…Œ์ด๋ธ”๊ณผ ์กฐ์ธํ•  ๋•Œ ์“ด๋‹ค. + */ +public enum TargetType { + PLACE, + LOTTERY_EVENT +} diff --git a/src/main/java/com/matzip/common/analytics/domain/entity/EventLog.java b/src/main/java/com/matzip/common/analytics/domain/entity/EventLog.java new file mode 100644 index 0000000..d9b05ad --- /dev/null +++ b/src/main/java/com/matzip/common/analytics/domain/entity/EventLog.java @@ -0,0 +1,80 @@ +package com.matzip.common.analytics.domain.entity; + +import com.matzip.common.analytics.AnalyticsEvent; +import com.matzip.common.analytics.JsonMapConverter; +import com.matzip.common.analytics.domain.EventType; +import com.matzip.common.entity.BaseEntity; +import jakarta.persistence.Column; +import jakarta.persistence.Convert; +import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.Index; +import jakarta.persistence.Table; +import lombok.Builder; +import lombok.Getter; + +import java.time.LocalDateTime; +import java.util.Map; + +@Getter +@Entity +@Table( + name = "event_log", + indexes = { + @Index(name = "idx_event_log_type_occurred", columnList = "event_type, occurred_at"), + @Index(name = "idx_event_log_user_occurred", columnList = "user_id, occurred_at") + } +) +public class EventLog extends BaseEntity { + + @Enumerated(EnumType.STRING) + @Column(name = "event_type", nullable = false, length = 50) + private EventType eventType; + + @Column(name = "user_id") + private Long userId; + + @Column(name = "anonymous_id", length = 100) + private String anonymousId; + + @Column(name = "target_type", length = 50) + private String targetType; + + @Column(name = "target_id") + private Long targetId; + + @Convert(converter = JsonMapConverter.class) + @Column(name = "properties", length = 4000) + private Map properties; + + @Column(name = "occurred_at", nullable = false) + private LocalDateTime occurredAt; + + protected EventLog() { + } + + @Builder + private EventLog(EventType eventType, Long userId, String anonymousId, String targetType, + Long targetId, Map properties, LocalDateTime occurredAt) { + this.eventType = eventType; + this.userId = userId; + this.anonymousId = anonymousId; + this.targetType = targetType; + this.targetId = targetId; + this.properties = properties; + this.occurredAt = occurredAt; + } + + public static EventLog from(AnalyticsEvent event) { + return EventLog.builder() + .eventType(event.eventType()) + .userId(event.userId()) + .anonymousId(event.anonymousId()) + .targetType(event.targetType() == null ? null : event.targetType().name()) + .targetId(event.targetId()) + .properties(event.properties()) + .occurredAt(event.occurredAt() == null ? LocalDateTime.now() : event.occurredAt()) + .build(); + } +} diff --git a/src/main/java/com/matzip/common/analytics/repository/EventLogRepository.java b/src/main/java/com/matzip/common/analytics/repository/EventLogRepository.java new file mode 100644 index 0000000..da90b21 --- /dev/null +++ b/src/main/java/com/matzip/common/analytics/repository/EventLogRepository.java @@ -0,0 +1,7 @@ +package com.matzip.common.analytics.repository; + +import com.matzip.common.analytics.domain.entity.EventLog; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface EventLogRepository extends JpaRepository { +} From cfad1f1da0404b567bbaf28ff186a5f81d85ed47 Mon Sep 17 00:00:00 2001 From: gihhyeon Date: Tue, 8 Sep 2026 23:25:20 +0900 Subject: [PATCH 22/24] =?UTF-8?q?feat:=20=EB=B9=84=EC=A6=88=EB=8B=88?= =?UTF-8?q?=EC=8A=A4=20=EC=9D=B4=EB=B2=A4=ED=8A=B8=20=EA=B3=84=EC=B8=A1=20?= =?UTF-8?q?=EC=A7=80=EC=A0=90=20=EC=97=B0=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/event/RequestReviewEventListener.java | 8 +++++++- .../service/AdminPlaceRegisterRequestService.java | 12 +++++++++++- .../java/com/matzip/auth/service/AuthService.java | 9 +++++++++ .../java/com/matzip/place/service/PlaceService.java | 10 ++++++++++ .../place/application/PlaceServiceCachingTest.java | 2 ++ .../matzip/place/application/PlaceServiceTest.java | 2 ++ 6 files changed, 41 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/matzip/admin/event/RequestReviewEventListener.java b/src/main/java/com/matzip/admin/event/RequestReviewEventListener.java index d464a68..e93d9fe 100644 --- a/src/main/java/com/matzip/admin/event/RequestReviewEventListener.java +++ b/src/main/java/com/matzip/admin/event/RequestReviewEventListener.java @@ -1,5 +1,8 @@ package com.matzip.admin.event; +import com.matzip.common.analytics.AnalyticsRecorder; +import com.matzip.common.analytics.domain.EventType; +import com.matzip.common.analytics.domain.TargetType; import com.matzip.common.exception.BusinessException; import com.matzip.common.exception.code.ErrorCode; import com.matzip.lottery.service.LotteryEventService; @@ -17,10 +20,12 @@ public class RequestReviewEventListener { private final LotteryEventService lotteryEventService; private final PlaceRepository placeRepository; + private final AnalyticsRecorder analyticsRecorder; - public RequestReviewEventListener(LotteryEventService lotteryEventService, PlaceRepository placeRepository) { + public RequestReviewEventListener(LotteryEventService lotteryEventService, PlaceRepository placeRepository, AnalyticsRecorder analyticsRecorder) { this.lotteryEventService = lotteryEventService; this.placeRepository = placeRepository; + this.analyticsRecorder = analyticsRecorder; } @Async @@ -36,6 +41,7 @@ public void enterCurrentEventOnApproval(RequestReviewEvent event) { boolean entered = lotteryEventService.enterCurrentEventOnPlaceApproval(registrant.getId(), place.getId()); if (entered) { log.info("[์ž๋™ ์‘๋ชจ ์™„๋ฃŒ] userId: {}, placeId: {}", registrant.getId(), place.getId()); + analyticsRecorder.record(EventType.EVENT_ENTERED, registrant.getId(), TargetType.PLACE, place.getId()); return; } log.info("[์ž๋™ ์‘๋ชจ ์Šคํ‚ต] ์ง„ํ–‰ ์ค‘ ์ด๋ฒคํŠธ ์—†์Œ ๋˜๋Š” ์ด๋ฏธ ์‘๋ชจ๋จ. userId: {}, placeId: {}", registrant.getId(), place.getId()); diff --git a/src/main/java/com/matzip/admin/service/AdminPlaceRegisterRequestService.java b/src/main/java/com/matzip/admin/service/AdminPlaceRegisterRequestService.java index e32c24a..a141246 100644 --- a/src/main/java/com/matzip/admin/service/AdminPlaceRegisterRequestService.java +++ b/src/main/java/com/matzip/admin/service/AdminPlaceRegisterRequestService.java @@ -4,6 +4,9 @@ import com.matzip.admin.domain.RequestReviewStatus; import com.matzip.admin.event.RequestReviewEvent; import com.matzip.admin.repository.RequestReviewRepository; +import com.matzip.common.analytics.AnalyticsRecorder; +import com.matzip.common.analytics.domain.EventType; +import com.matzip.common.analytics.domain.TargetType; import com.matzip.common.exception.BusinessException; import com.matzip.common.exception.code.ErrorCode; import com.matzip.place.domain.PlaceStatus; @@ -23,11 +26,13 @@ public class AdminPlaceRegisterRequestService { private final PlaceRepository placeRepository; private final RequestReviewRepository requestReviewRepository; private final ApplicationEventPublisher applicationEventPublisher; + private final AnalyticsRecorder analyticsRecorder; - public AdminPlaceRegisterRequestService(PlaceRepository placeRepository, RequestReviewRepository requestReviewRepository, ApplicationEventPublisher applicationEventPublisher) { + public AdminPlaceRegisterRequestService(PlaceRepository placeRepository, RequestReviewRepository requestReviewRepository, ApplicationEventPublisher applicationEventPublisher, AnalyticsRecorder analyticsRecorder) { this.placeRepository = placeRepository; this.requestReviewRepository = requestReviewRepository; this.applicationEventPublisher = applicationEventPublisher; + this.analyticsRecorder = analyticsRecorder; } @Transactional @@ -44,6 +49,11 @@ public void review(Long placeId, RequestReviewStatus status, String rejectedReas } applicationEventPublisher.publishEvent(new RequestReviewEvent(placeId, status)); + + EventType eventType = status == RequestReviewStatus.APPROVED + ? EventType.PLACE_APPROVED + : EventType.PLACE_REJECTED; + analyticsRecorder.record(eventType, null, TargetType.PLACE, placeId); } private void approve(Place place/*, Long adminId*/) { diff --git a/src/main/java/com/matzip/auth/service/AuthService.java b/src/main/java/com/matzip/auth/service/AuthService.java index 16f40ab..fb63c39 100644 --- a/src/main/java/com/matzip/auth/service/AuthService.java +++ b/src/main/java/com/matzip/auth/service/AuthService.java @@ -8,6 +8,8 @@ import com.matzip.auth.client.kakao.KakaoLoginApiClient; import com.matzip.auth.client.kakao.dto.KakaoTokenResponseDto; import com.matzip.auth.client.kakao.dto.KakaoUserResponseDto; +import com.matzip.common.analytics.AnalyticsRecorder; +import com.matzip.common.analytics.domain.EventType; import com.matzip.common.config.ImageProperties; import com.matzip.common.config.JwtProperties; import com.matzip.common.exception.BusinessException; @@ -36,6 +38,7 @@ public class AuthService { private final NickNameGenerator nickNameGenerator; private final ProfileAssignment profileAssignment; + private final AnalyticsRecorder analyticsRecorder; private long accessTokenTtlMs() { return jwtProps.getExpirationTime(); @@ -94,6 +97,12 @@ public LoginResponseDto login(KakaoLoginRequestDto loginRequest) { saved.updateToken(refreshToken); // ๋ณ€๊ฒฝ ๊ฐ์ง€์— ์˜ํ•ด ์—…๋ฐ์ดํŠธ } + // 5) ๋ถ„์„ ์ด๋ฒคํŠธ ๊ธฐ๋ก (GA๊ฐ€ ๋ชป ๋ณด๋Š” ํšŒ์› ๊ฐ€์ž…/๋กœ๊ทธ์ธ ์‹ ํ˜ธ) + if (firstLogin) { + analyticsRecorder.record(EventType.SIGNUP, user.getId()); + } + analyticsRecorder.record(EventType.LOGIN, user.getId()); + return LoginResponseDto.builder() .tokenType("Bearer") .accessToken(accessToken) diff --git a/src/main/java/com/matzip/place/service/PlaceService.java b/src/main/java/com/matzip/place/service/PlaceService.java index 2e58186..81d1299 100644 --- a/src/main/java/com/matzip/place/service/PlaceService.java +++ b/src/main/java/com/matzip/place/service/PlaceService.java @@ -28,6 +28,9 @@ import com.matzip.user.domain.User; import com.matzip.user.repository.UserRepository; import com.matzip.common.infra.discord.DiscordWebhookSender; +import com.matzip.common.analytics.AnalyticsRecorder; +import com.matzip.common.analytics.domain.EventType; +import com.matzip.common.analytics.domain.TargetType; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -58,6 +61,7 @@ public class PlaceService { private final UserRepository userRepository; private final PlaceTempStoreMemory placeTempStore; private final DiscordWebhookSender discordWebhookSender; + private final AnalyticsRecorder analyticsRecorder; public PlaceCheckResponseDto preview(PlaceCheckRequestDto req) { final String kakaoPlaceId = req.getKakaoPlaceId(); @@ -150,6 +154,12 @@ public PlaceRegisterResponseDto register(PlaceRequestDto req) { .build(); placeRepository.save(place); + analyticsRecorder.record( + EventType.PLACE_REGISTER_REQUESTED, + registeredBy == null ? null : registeredBy.getId(), + TargetType.PLACE, + place.getId()); + List categoryIds = req.getCategoryIds(); if (categoryIds.size() != new LinkedHashSet<>(categoryIds).size()) { throw new IllegalArgumentException("categoryId๋Š” ์ค‘๋ณต๋  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค."); diff --git a/src/test/java/com/matzip/place/application/PlaceServiceCachingTest.java b/src/test/java/com/matzip/place/application/PlaceServiceCachingTest.java index 042dc9b..8a4c617 100644 --- a/src/test/java/com/matzip/place/application/PlaceServiceCachingTest.java +++ b/src/test/java/com/matzip/place/application/PlaceServiceCachingTest.java @@ -1,5 +1,6 @@ package com.matzip.place.application; +import com.matzip.common.analytics.AnalyticsRecorder; import com.matzip.common.infra.discord.DiscordWebhookSender; import com.matzip.place.client.kakao.dto.KakaoMenuDto; import com.matzip.place.dto.PhotoDto; @@ -56,6 +57,7 @@ class PlaceServiceCachingTest { @Mock private PlaceCategoryRepository placeCategoryRepository; @Mock private PlaceTagRepository placeTagRepository; @Mock private DiscordWebhookSender discordWebhookSender; + @Mock private AnalyticsRecorder analyticsRecorder; private static final String TEST_KAKAO_PLACE_ID = "1852074823"; diff --git a/src/test/java/com/matzip/place/application/PlaceServiceTest.java b/src/test/java/com/matzip/place/application/PlaceServiceTest.java index ad956cd..4f9ac10 100644 --- a/src/test/java/com/matzip/place/application/PlaceServiceTest.java +++ b/src/test/java/com/matzip/place/application/PlaceServiceTest.java @@ -1,5 +1,6 @@ package com.matzip.place.application; +import com.matzip.common.analytics.AnalyticsRecorder; import com.matzip.common.infra.discord.DiscordWebhookSender; import com.matzip.place.dto.request.PlaceRequestDto; import com.matzip.place.client.PlaceTempStoreMemory; @@ -55,6 +56,7 @@ class PlaceServiceTest { @Mock private PlaceCategoryRepository placeCategoryRepository; @Mock private PlaceTagRepository placeTagRepository; @Mock private DiscordWebhookSender discordWebhookSender; + @Mock private AnalyticsRecorder analyticsRecorder; @Test @DisplayName("์นดํ…Œ๊ณ ๋ฆฌ๋Š” ์š”์ฒญ categoryIds ์ˆœ์„œ๋Œ€๋กœ ์ €์žฅ๋œ๋‹ค") From 55739906d6dd93ec7e84be6f05102fe70b1886d0 Mon Sep 17 00:00:00 2001 From: gihhyeon Date: Tue, 8 Sep 2026 23:33:29 +0900 Subject: [PATCH 23/24] =?UTF-8?q?test:=20=EC=9D=B4=EB=B2=A4=ED=8A=B8=20?= =?UTF-8?q?=EB=A1=9C=EA=B9=85=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - JSON ์ปจ๋ฒ„ํ„ฐ ์ง๋ ฌํ™”/์—ญ์ง๋ ฌํ™” - ๋ฆฌ์Šค๋„ˆ ์ ์žฌยทํ•„๋“œ ๋งคํ•‘ยทproperties ์™•๋ณต - ์ปค๋ฐ‹ ์‹œ ์ ์žฌ / ๋กค๋ฐฑ ์‹œ ๋ฏธ์ ์žฌ(AFTER_COMMIT) ํ†ตํ•ฉ ๊ฒ€์ฆ --- .../analytics/AnalyticsEventListenerTest.java | 60 ++++++++++++ .../AnalyticsEventLoggingIntegrationTest.java | 94 +++++++++++++++++++ .../analytics/JsonMapConverterTest.java | 36 +++++++ 3 files changed, 190 insertions(+) create mode 100644 src/test/java/com/matzip/common/analytics/AnalyticsEventListenerTest.java create mode 100644 src/test/java/com/matzip/common/analytics/AnalyticsEventLoggingIntegrationTest.java create mode 100644 src/test/java/com/matzip/common/analytics/JsonMapConverterTest.java diff --git a/src/test/java/com/matzip/common/analytics/AnalyticsEventListenerTest.java b/src/test/java/com/matzip/common/analytics/AnalyticsEventListenerTest.java new file mode 100644 index 0000000..2bdb852 --- /dev/null +++ b/src/test/java/com/matzip/common/analytics/AnalyticsEventListenerTest.java @@ -0,0 +1,60 @@ +package com.matzip.common.analytics; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.matzip.AbstractMatzipApplicationTest; +import com.matzip.common.analytics.domain.EventType; +import com.matzip.common.analytics.domain.TargetType; +import com.matzip.common.analytics.domain.entity.EventLog; +import com.matzip.common.analytics.repository.EventLogRepository; +import java.time.LocalDateTime; +import java.util.List; +import java.util.Map; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +class AnalyticsEventListenerTest extends AbstractMatzipApplicationTest { + + @Autowired + private EventLogRepository eventLogRepository; + + // @Async ํ”„๋ก์‹œ๋ฅผ ์šฐํšŒํ•ด ๋งคํ•‘ยท์ ์žฌ ๋กœ์ง์„ ๋™๊ธฐ์ ์œผ๋กœ ๊ฒ€์ฆํ•˜๊ธฐ ์œ„ํ•ด ์ง์ ‘ ์ƒ์„ฑํ•œ๋‹ค. + private AnalyticsEventListener analyticsEventListener; + + @BeforeEach + void clearEventLog() { + eventLogRepository.deleteAll(); + analyticsEventListener = new AnalyticsEventListener(eventLogRepository); + } + + @Test + void ์ด๋ฒคํŠธ๋ฅผ_event_log์—_ํ•„๋“œ๊นŒ์ง€_๊ทธ๋Œ€๋กœ_์ ์žฌํ•œ๋‹ค() { + AnalyticsEvent event = AnalyticsEvent.of(EventType.PLACE_REGISTER_REQUESTED, 42L, TargetType.PLACE, 7L); + + analyticsEventListener.on(event); + + List logs = eventLogRepository.findAll(); + assertThat(logs).hasSize(1); + EventLog saved = logs.get(0); + assertThat(saved.getEventType()).isEqualTo(EventType.PLACE_REGISTER_REQUESTED); + assertThat(saved.getUserId()).isEqualTo(42L); + assertThat(saved.getTargetType()).isEqualTo("PLACE"); + assertThat(saved.getTargetId()).isEqualTo(7L); + assertThat(saved.getOccurredAt()).isNotNull(); + assertThat(saved.getCreatedAt()).isNotNull(); + } + + @Test + void properties๊ฐ€_JSON์œผ๋กœ_์™•๋ณต๋œ๋‹ค() { + AnalyticsEvent event = new AnalyticsEvent( + EventType.PLACE_REJECTED, null, null, TargetType.PLACE, 3L, + Map.of("reason", "์ค‘๋ณต ๋“ฑ๋ก"), LocalDateTime.now()); + + analyticsEventListener.on(event); + + EventLog saved = eventLogRepository.findAll().get(0); + assertThat(saved.getUserId()).isNull(); + assertThat(saved.getProperties()).containsEntry("reason", "์ค‘๋ณต ๋“ฑ๋ก"); + } +} diff --git a/src/test/java/com/matzip/common/analytics/AnalyticsEventLoggingIntegrationTest.java b/src/test/java/com/matzip/common/analytics/AnalyticsEventLoggingIntegrationTest.java new file mode 100644 index 0000000..7f7fccc --- /dev/null +++ b/src/test/java/com/matzip/common/analytics/AnalyticsEventLoggingIntegrationTest.java @@ -0,0 +1,94 @@ +package com.matzip.common.analytics; + +import static org.assertj.core.api.Assertions.assertThat; + +import com.matzip.AbstractMatzipApplicationTest; +import com.matzip.common.analytics.domain.EventType; +import com.matzip.common.analytics.repository.EventLogRepository; +import java.util.concurrent.TimeUnit; +import java.util.function.BooleanSupplier; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.support.TransactionTemplate; + +/** + * ๋ฐœํ–‰(AnalyticsRecorder) โ†’ ํŠธ๋žœ์žญ์…˜ ์ปค๋ฐ‹ โ†’ ๋น„๋™๊ธฐ ๋ฆฌ์Šค๋„ˆ ์ ์žฌ๊นŒ์ง€์˜ ํ†ตํ•ฉ ๋™์ž‘ ๊ฒ€์ฆ. + * AFTER_COMMIT ์˜๋ฏธ์ƒ, ์ปค๋ฐ‹๋œ ํŠธ๋žœ์žญ์…˜์˜ ์ด๋ฒคํŠธ๋งŒ ์ ์žฌ๋˜๊ณ  ๋กค๋ฐฑ๋˜๋ฉด ๋‚จ์ง€ ์•Š์•„์•ผ ํ•œ๋‹ค. + */ +class AnalyticsEventLoggingIntegrationTest extends AbstractMatzipApplicationTest { + + @Autowired + private AnalyticsRecorder analyticsRecorder; + @Autowired + private EventLogRepository eventLogRepository; + @Autowired + private PlatformTransactionManager transactionManager; + + private TransactionTemplate transactionTemplate; + + @BeforeEach + void setUpTransactionTemplate() { + transactionTemplate = new TransactionTemplate(transactionManager); + eventLogRepository.deleteAll(); + } + + @Test + void ์ปค๋ฐ‹๋œ_ํŠธ๋žœ์žญ์…˜์—์„œ_๋ฐœํ–‰ํ•œ_์ด๋ฒคํŠธ๋Š”_๋น„๋™๊ธฐ๋กœ_์ ์žฌ๋œ๋‹ค() { + transactionTemplate.executeWithoutResult(status -> + analyticsRecorder.record(EventType.LOGIN, 100L)); + + // ๋น„๋™๊ธฐ AFTER_COMMIT ๋ฆฌ์Šค๋„ˆ๊ฐ€ ์ ์žฌํ•  ๋•Œ๊นŒ์ง€ ๋Œ€๊ธฐ + boolean saved = waitUntil(() -> eventLogRepository.count() == 1, 2000); + + assertThat(saved).isTrue(); + assertThat(eventLogRepository.findAll().get(0).getEventType()).isEqualTo(EventType.LOGIN); + } + + @Test + void ๋กค๋ฐฑ๋œ_ํŠธ๋žœ์žญ์…˜์—์„œ_๋ฐœํ–‰ํ•œ_์ด๋ฒคํŠธ๋Š”_์ ์žฌ๋˜์ง€_์•Š๋Š”๋‹ค() { + try { + transactionTemplate.executeWithoutResult(status -> { + analyticsRecorder.record(EventType.LOGIN, 200L); + throw new RuntimeException("์˜๋„์  ๋กค๋ฐฑ"); + }); + } catch (RuntimeException ignored) { + // ๋กค๋ฐฑ ์œ ๋„์šฉ ์˜ˆ์™ธ + } + + // AFTER_COMMIT์€ ๋กค๋ฐฑ ์‹œ ์‹คํ–‰๋˜์ง€ ์•Š์œผ๋ฏ€๋กœ, ์ž ์‹œ ๋Œ€๊ธฐํ•ด๋„ ์ ์žฌ๋˜์ง€ ์•Š์•„์•ผ ํ•œ๋‹ค + boolean neverSaved = stayFalse(() -> eventLogRepository.count() > 0, 500); + assertThat(neverSaved).isTrue(); + } + + private boolean waitUntil(BooleanSupplier condition, long timeoutMs) { + long deadline = System.currentTimeMillis() + timeoutMs; + while (System.currentTimeMillis() < deadline) { + if (condition.getAsBoolean()) { + return true; + } + sleep(); + } + return condition.getAsBoolean(); + } + + private boolean stayFalse(BooleanSupplier condition, long durationMs) { + long deadline = System.currentTimeMillis() + durationMs; + while (System.currentTimeMillis() < deadline) { + if (condition.getAsBoolean()) { + return false; + } + sleep(); + } + return !condition.getAsBoolean(); + } + + private void sleep() { + try { + TimeUnit.MILLISECONDS.sleep(50); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } +} diff --git a/src/test/java/com/matzip/common/analytics/JsonMapConverterTest.java b/src/test/java/com/matzip/common/analytics/JsonMapConverterTest.java new file mode 100644 index 0000000..1cf2048 --- /dev/null +++ b/src/test/java/com/matzip/common/analytics/JsonMapConverterTest.java @@ -0,0 +1,36 @@ +package com.matzip.common.analytics; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.Map; +import org.junit.jupiter.api.Test; + +class JsonMapConverterTest { + + private final JsonMapConverter converter = new JsonMapConverter(); + + @Test + void Map๋ฅผ_JSON_๋ฌธ์ž์—ด๋กœ_์ง๋ ฌํ™”ํ•˜๊ณ _๋‹ค์‹œ_Map์œผ๋กœ_์—ญ์ง๋ ฌํ™”ํ•œ๋‹ค() { + Map properties = Map.of("query", "๋ˆ๊นŒ์Šค", "resultCount", 12); + + String json = converter.convertToDatabaseColumn(properties); + Map restored = converter.convertToEntityAttribute(json); + + assertThat(json).contains("๋ˆ๊นŒ์Šค"); + assertThat(restored).containsEntry("query", "๋ˆ๊นŒ์Šค"); + assertThat(restored).containsEntry("resultCount", 12); + } + + @Test + void null์ด๋‚˜_๋นˆ_Map์€_null๋กœ_์ €์žฅํ•œ๋‹ค() { + assertThat(converter.convertToDatabaseColumn(null)).isNull(); + assertThat(converter.convertToDatabaseColumn(Map.of())).isNull(); + } + + @Test + void null์ด๋‚˜_๋นˆ_๋ฌธ์ž์—ด์€_null๋กœ_๋ณต์›ํ•œ๋‹ค() { + assertThat(converter.convertToEntityAttribute(null)).isNull(); + assertThat(converter.convertToEntityAttribute("")).isNull(); + assertThat(converter.convertToEntityAttribute(" ")).isNull(); + } +} From 394691ff6d3b6c94081cca41289f8c247bea3dbb Mon Sep 17 00:00:00 2001 From: gihhyeon Date: Wed, 9 Sep 2026 00:05:41 +0900 Subject: [PATCH 24/24] =?UTF-8?q?chore:=20event=5Flog=20prod=20DDL=20?= =?UTF-8?q?=EB=B0=8F=20=EA=B2=80=EC=A6=9D=20=EC=BF=BC=EB=A6=AC=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - prod(validate) ๋ฐฐํฌ ์ „ ์ˆ˜๋™ ์ƒ์„ฑ์šฉ CREATE TABLE - DAU/์‹ ๊ทœ๊ฐ€์ž…/์ฝ”ํ˜ธํŠธ ๋ฆฌํ…์…˜/๋“ฑ๋กโ†’์Šน์ธโ†’์‘๋ชจ ํผ๋„ ์ง‘๊ณ„ ์ฟผ๋ฆฌ --- src/main/resources/sql/event_log.sql | 75 ++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 src/main/resources/sql/event_log.sql diff --git a/src/main/resources/sql/event_log.sql b/src/main/resources/sql/event_log.sql new file mode 100644 index 0000000..950df51 --- /dev/null +++ b/src/main/resources/sql/event_log.sql @@ -0,0 +1,75 @@ +-- ๋น„์ฆˆ๋‹ˆ์Šค ์ด๋ฒคํŠธ ๋กœ๊น…(event_log) ์ฐธ๊ณ  ์Šคํฌ๋ฆฝํŠธ +-- GA4(ํด๋ผ์ด์–ธํŠธ ์ž๋™์ˆ˜์ง‘)๊ฐ€ ๋ชป ๋ณด๊ฑฐ๋‚˜ DB ์กฐ์ธ์ด ํ•„์š”ํ•œ ๋น„์ฆˆ๋‹ˆ์Šค ์ด๋ฒคํŠธ๋ฅผ ์„œ๋ฒ„์—์„œ ์ ์žฌํ•œ๋‹ค. +-- ์ ์žฌ ๊ฒฝ๋กœ: common/analytics ์˜ AnalyticsRecorder(๋ฐœํ–‰) -> AnalyticsEventListener(๋น„๋™๊ธฐ AFTER_COMMIT ์ ์žฌ) + +-- ===================================================================== +-- [ํ•„์ˆ˜] prod ๋ฐฐํฌ ์ „ ์ˆ˜๋™ DDL +-- prod ๋Š” ddl-auto: validate ์ด๋ฏ€๋กœ ์ด ํ…Œ์ด๋ธ”์„ ๋จผ์ € ์ƒ์„ฑํ•˜์ง€ ์•Š์œผ๋ฉด ๊ธฐ๋™์— ์‹คํŒจํ•œ๋‹ค. +-- (local/test ๋Š” ์ž๋™ ์ƒ์„ฑ) ์ปฌ๋Ÿผ ์ •์˜๋Š” ์—”ํ‹ฐํ‹ฐ ๋งคํ•‘๊ณผ ์ผ์น˜์‹œ์ผœ validate ๋ฅผ ํ†ต๊ณผ์‹œํ‚จ๋‹ค. +-- ๋ฐฐํฌ ํ›„ ๊ธฐ๋™ ๋กœ๊ทธ์— ์Šคํ‚ค๋งˆ validate ์—๋Ÿฌ๊ฐ€ ์—†๋Š”์ง€ ํ™•์ธํ•  ๊ฒƒ. +-- ===================================================================== +CREATE TABLE event_log ( + id BIGINT NOT NULL AUTO_INCREMENT, + event_type VARCHAR(50) NOT NULL, + user_id BIGINT NULL, + anonymous_id VARCHAR(100) NULL, + target_type VARCHAR(50) NULL, + target_id BIGINT NULL, + properties VARCHAR(4000) NULL, + occurred_at DATETIME(6) NOT NULL, + created_at DATETIME(6) NULL, + updated_at DATETIME(6) NULL, + PRIMARY KEY (id), + KEY idx_event_log_type_occurred (event_type, occurred_at), + KEY idx_event_log_user_occurred (user_id, occurred_at) +) ENGINE = InnoDB + DEFAULT CHARSET = utf8mb4; + +-- ์ ์žฌ ์ด๋ฒคํŠธ(MVP): SIGNUP, LOGIN, PLACE_REGISTER_REQUESTED, +-- PLACE_APPROVED, PLACE_REJECTED, EVENT_ENTERED + +-- ===================================================================== +-- ๊ฒ€์ฆ์šฉ ์ง‘๊ณ„ ์ฟผ๋ฆฌ +-- ===================================================================== + +-- 1) ์ผ๋ณ„ ์‹ ๊ทœ ๊ฐ€์ž… ์ถ”์ด (ํš๋“) +SELECT DATE(occurred_at) AS d, COUNT(*) AS signups +FROM event_log +WHERE event_type = 'SIGNUP' +GROUP BY DATE(occurred_at) +ORDER BY d; + +-- 2) ์ผ๋ณ„ DAU (๋กœ๊ทธ์ธ ๊ธฐ์ค€, ํšŒ์› ๋ฆฌํ…์…˜์˜ ๊ธฐ๋ฐ˜) +SELECT DATE(occurred_at) AS d, COUNT(DISTINCT user_id) AS dau +FROM event_log +WHERE event_type = 'LOGIN' +GROUP BY DATE(occurred_at) +ORDER BY d; + +-- 3) ๊ฐ€์ž… ์ฃผ์ฐจ ๋Œ€๋น„ 7์ผ ์ดํ›„ ์žฌ๋กœ๊ทธ์ธ (์ฃผ๊ฐ„ ์ฝ”ํ˜ธํŠธ ๋ฆฌํ…์…˜ ๊ฐ„์ด ๋ฒ„์ „) +WITH signup AS ( + SELECT user_id, MIN(occurred_at) AS signup_at + FROM event_log WHERE event_type = 'SIGNUP' GROUP BY user_id +) +SELECT + YEARWEEK(s.signup_at, 3) AS signup_week, + COUNT(DISTINCT s.user_id) AS signups, + COUNT(DISTINCT CASE WHEN l.occurred_at >= s.signup_at + INTERVAL 7 DAY + THEN l.user_id END) AS relogin_after_7d +FROM signup s +LEFT JOIN event_log l ON l.user_id = s.user_id AND l.event_type = 'LOGIN' +GROUP BY YEARWEEK(s.signup_at, 3) +ORDER BY signup_week; + +-- 4) ๋“ฑ๋ก -> ์Šน์ธ/๋ฐ˜๋ ค -> ์‘๋ชจ ํผ๋„ +SELECT event_type, COUNT(*) AS cnt +FROM event_log +WHERE event_type IN ('PLACE_REGISTER_REQUESTED', 'PLACE_APPROVED', 'PLACE_REJECTED', 'EVENT_ENTERED') +GROUP BY event_type; + +-- 5) ์ด๋ฒคํŠธ ์‘๋ชจ๋ฅผ ์บ ํผ์Šค๋ณ„๋กœ (GA ๊ฐ€ ๋ชป ํ•˜๋Š” ๋น„์ฆˆ๋‹ˆ์Šค ์กฐ์ธ ์˜ˆ์‹œ) +SELECT p.campus, COUNT(*) AS entries +FROM event_log e +JOIN place p ON e.target_type = 'PLACE' AND e.target_id = p.id +WHERE e.event_type = 'EVENT_ENTERED' +GROUP BY p.campus;