From e324ecd62098845c8b92e3ed1e985af5aaef1f19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EC=A7=80?= Date: Wed, 16 Apr 2025 18:04:22 +0900 Subject: [PATCH 1/9] =?UTF-8?q?[feat]=20#22=20-=20swagger=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 --- build.gradle | 1 + .../Minjin/TagCafe/config/SwaggerConfig.java | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+) create mode 100644 src/main/java/com/Minjin/TagCafe/config/SwaggerConfig.java diff --git a/build.gradle b/build.gradle index 4439bec..06fedd9 100644 --- a/build.gradle +++ b/build.gradle @@ -40,6 +40,7 @@ dependencies { testImplementation 'org.springframework.boot:spring-boot-starter-test' testRuntimeOnly 'org.junit.platform:junit-platform-launcher' implementation 'org.springframework.boot:spring-boot-starter-data-jpa' + implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.2.0' } tasks.named('test') { diff --git a/src/main/java/com/Minjin/TagCafe/config/SwaggerConfig.java b/src/main/java/com/Minjin/TagCafe/config/SwaggerConfig.java new file mode 100644 index 0000000..29c39ac --- /dev/null +++ b/src/main/java/com/Minjin/TagCafe/config/SwaggerConfig.java @@ -0,0 +1,18 @@ +package com.Minjin.TagCafe.config; + +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.info.Info; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class SwaggerConfig { + @Bean + public OpenAPI openAPI() { + return new OpenAPI() + .info(new Info() + .title("TagCafe API") + .description("카공러 맞춤형 카페 정보 플랫폼 TagCafe의 API 명세서입니다.") + .version("v1.0.0")); + } +} From 9e743401f50c03aa194e02c05a1df3fc1d55a753 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EC=A7=80?= Date: Wed, 16 Apr 2025 18:18:46 +0900 Subject: [PATCH 2/9] =?UTF-8?q?[feat]=20#22=20-=20CafeController=EC=97=90?= =?UTF-8?q?=20Swagger=20=EC=96=B4=EB=85=B8=ED=85=8C=EC=9D=B4=EC=85=98=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/Minjin/TagCafe/controller/CafeController.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/main/java/com/Minjin/TagCafe/controller/CafeController.java b/src/main/java/com/Minjin/TagCafe/controller/CafeController.java index 92b8054..eed64b4 100644 --- a/src/main/java/com/Minjin/TagCafe/controller/CafeController.java +++ b/src/main/java/com/Minjin/TagCafe/controller/CafeController.java @@ -6,6 +6,8 @@ import com.Minjin.TagCafe.entity.Cafe; import com.Minjin.TagCafe.repository.CafeRepository; import com.Minjin.TagCafe.service.CafeService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -15,6 +17,7 @@ import java.util.*; import java.util.stream.Collectors; +@Tag(name = "Cafe", description = "카페 정보 조회 및 필터 검색 API") @RestController @RequestMapping("/cafes") @RequiredArgsConstructor @@ -24,6 +27,7 @@ public class CafeController { private final CafeRepository cafeRepository; // id로 카페 조회 + @Operation(summary = "ID로 카페 조회", description = "카페 ID를 기반으로 카페 상세 정보를 조회합니다.") @GetMapping("/{cafeId}") public ResponseEntity getCafeById(@PathVariable("cafeId") Long cafeId) { Cafe cafe = cafeService.getCafeById(cafeId); @@ -54,6 +58,7 @@ public ResponseEntity getCafeById(@PathVariable("cafeId") Long cafeId) } // 검색 + @Operation(summary = "카페 검색", description = "키워드로 카페를 검색합니다.") @GetMapping("/search") public ResponseEntity> searchCafe(@RequestParam(name = "query") String query) { List cafes = cafeService.searchCafeByKeyword(query); @@ -72,6 +77,7 @@ public ResponseEntity> searchCafe(@RequestParam(name = "quer } // 지도 영역 내 카페 조회 (위경도 범위 내 검색) + @Operation(summary = "지도의 특정 영역 내 카페 조회", description = "지도 상에서 특정 위경도 범위에 있는 카페 목록을 반환합니다.") @GetMapping("/area") public ResponseEntity> getCafesInArea(@RequestParam(name = "minLat") double minLat, @RequestParam(name = "maxLat") double maxLat, @@ -105,6 +111,7 @@ public ResponseEntity> getCafesInArea(@RequestParam(name = "mi } // 특정 태그와 특정 값을 가진 카페 조회 + @Operation(summary = "여러 태그 조건으로 카페 필터링", description = "태그 이름과 값들을 기준으로 카페를 필터링하여 조회합니다.") @GetMapping("/filter") public ResponseEntity> getCafesByMultipleTags(@RequestParam(name = "tagNames") List tagNames, @RequestParam(name = "values") List values) { @@ -152,6 +159,7 @@ public ResponseEntity> getCafesByMultipleTags(@RequestParam(na // admin - 카페 검색 후 db 저장 + @Operation(summary = "admin - 카페 저장", description = "관리자가 카페 정보를 저장합니다.") @PostMapping public ResponseEntity addCafe(@RequestBody CafeDto cafeDto) { Cafe savedCafe = cafeService.addCafe(cafeDto); @@ -159,6 +167,7 @@ public ResponseEntity addCafe(@RequestBody CafeDto cafeDto) { } // admin - 태그 값 업데이트 + @Operation(summary = "admin - 카페 태그 수정", description = "특정 카페의 태그 정보(wifi, 책상 등)를 수정합니다.") @PutMapping("/{cafeId}/tags") public ResponseEntity updateCafeTags(@PathVariable("cafeId") Long cafeId, @RequestBody CafeDto cafeDto) { @@ -176,12 +185,14 @@ public ResponseEntity updateCafeTags(@PathVariable("cafeId") Long cafeId, } // 모든 카페 조회 API 추가 + @Operation(summary = "모든 카페 조회", description = "전체 카페 목록을 조회합니다.") @GetMapping public ResponseEntity> getAllCafes() { List cafes = cafeService.getAllCafes(); return ResponseEntity.ok(cafes); } + @Operation(summary = "카페 태그 조회", description = "카페 ID를 기준으로 태그(wifi, 콘센트 등) 정보를 조회합니다.") @GetMapping("/{cafeId}/tags") public ResponseEntity> getCafeTags(@PathVariable("cafeId") Long cafeId) { Cafe cafe = cafeRepository.findById(cafeId) From d8821387251993ecfc1cecaecf813576aa23258e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EC=A7=80?= Date: Wed, 16 Apr 2025 18:24:58 +0900 Subject: [PATCH 3/9] =?UTF-8?q?[feat]=20#22=20-=20faq,=20review=EC=97=90?= =?UTF-8?q?=20=EC=96=B4=EB=85=B8=ED=85=8C=EC=9D=B4=EC=85=98=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 --- .../java/com/Minjin/TagCafe/controller/FAQController.java | 6 ++++++ .../com/Minjin/TagCafe/controller/ReviewController.java | 5 +++++ 2 files changed, 11 insertions(+) diff --git a/src/main/java/com/Minjin/TagCafe/controller/FAQController.java b/src/main/java/com/Minjin/TagCafe/controller/FAQController.java index 0a89fe0..751f8de 100644 --- a/src/main/java/com/Minjin/TagCafe/controller/FAQController.java +++ b/src/main/java/com/Minjin/TagCafe/controller/FAQController.java @@ -7,6 +7,8 @@ import com.Minjin.TagCafe.entity.QA; import com.Minjin.TagCafe.repository.FeedbackRepository; import com.Minjin.TagCafe.repository.QARepository; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; @@ -16,6 +18,7 @@ import java.util.Map; import java.util.stream.Collectors; +@Tag(name = "FAQ", description = "자주 묻는 질문 및 사용자 피드백 관련 API") @RestController @RequestMapping("/faq") @CrossOrigin(origins = "http://tagcafe.site") @@ -30,6 +33,7 @@ public FAQController(FeedbackRepository feedbackRepository, QARepository qaRepos //자주 묻는 질문 조회 + @Operation(summary = "자주 묻는 질문 조회", description = "모든 QA 데이터를 조회합니다.") @GetMapping("/qa") public ResponseEntity> getQAs() { List qaList = qaRepository.findAll(); @@ -37,6 +41,7 @@ public ResponseEntity> getQAs() { } //사용자 의견 및 오류 제보 제출 + @Operation(summary = "사용자 피드백 제출", description = "사용자의 의견이나 오류 제보를 저장합니다.") @PostMapping("/feedback") public ResponseEntity> submitFeedback(@RequestBody FeedbackRequest request) { Feedback feedback = new Feedback(); @@ -51,6 +56,7 @@ public ResponseEntity> submitFeedback(@RequestBody FeedbackR } // ✅ 관리자용 - 사용자 의견 및 오류 목록 조회 API + @Operation(summary = "admin - 사용자 피드백 전체 조회", description = "관리자가 보는 사용자 피드백 목록입니다.") @GetMapping("/feedback") public ResponseEntity> getFeedbackList() { List feedbacks = feedbackRepository.findAll() diff --git a/src/main/java/com/Minjin/TagCafe/controller/ReviewController.java b/src/main/java/com/Minjin/TagCafe/controller/ReviewController.java index 35a0b3a..19c9022 100644 --- a/src/main/java/com/Minjin/TagCafe/controller/ReviewController.java +++ b/src/main/java/com/Minjin/TagCafe/controller/ReviewController.java @@ -3,11 +3,14 @@ import com.Minjin.TagCafe.dto.ReviewDTO; import com.Minjin.TagCafe.entity.Review; import com.Minjin.TagCafe.service.ReviewService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import java.util.List; +@Tag(name = "Review", description = "카페 리뷰 작성, 조회, 수정, 삭제 관련 API") @RestController @RequestMapping("/reviews") public class ReviewController { @@ -17,6 +20,7 @@ public ReviewController(ReviewService reviewService) { this.reviewService = reviewService; } + @Operation(summary = "리뷰 작성", description = "카페에 대한 새로운 리뷰를 작성합니다.") @PostMapping("/create") public ResponseEntity createReview(@RequestBody ReviewDTO reviewDTO) { System.out.println("Received DTO:"+ reviewDTO); @@ -28,6 +32,7 @@ public ResponseEntity createReview(@RequestBody ReviewDTO reviewDTO) { return ResponseEntity.ok("리뷰가 저장되었습니다."); } + @Operation(summary = "카페별 리뷰 조회", description = "특정 카페에 작성된 모든 리뷰를 조회합니다.") @GetMapping("/{cafeId}") public ResponseEntity> getReviewsByCafe(@PathVariable("cafeId") Long cafeId) { return ResponseEntity.ok(reviewService.getReviewsByCafeId(cafeId)); From 4fff021201206ef1270054da51960964f7ba66fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EC=A7=80?= Date: Wed, 16 Apr 2025 18:32:26 +0900 Subject: [PATCH 4/9] =?UTF-8?q?[feat]=20#22=20-=20my,=20reportedCafe,=20sa?= =?UTF-8?q?vedCafe,=20user=20=EC=96=B4=EB=85=B8=ED=85=8C=EC=9D=B4=EC=85=98?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Minjin/TagCafe/controller/MyController.java | 9 +++++++++ .../controller/ReportedCafeController.java | 15 +++++++++++++++ .../TagCafe/controller/SavedCafeController.java | 7 +++++++ .../Minjin/TagCafe/controller/UserController.java | 7 +++++++ 4 files changed, 38 insertions(+) diff --git a/src/main/java/com/Minjin/TagCafe/controller/MyController.java b/src/main/java/com/Minjin/TagCafe/controller/MyController.java index a59cadc..177cddf 100644 --- a/src/main/java/com/Minjin/TagCafe/controller/MyController.java +++ b/src/main/java/com/Minjin/TagCafe/controller/MyController.java @@ -4,6 +4,8 @@ import com.Minjin.TagCafe.entity.Cafe; import com.Minjin.TagCafe.repository.CafeRepository; import com.Minjin.TagCafe.service.ReviewService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.servlet.http.HttpSession; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; @@ -14,6 +16,7 @@ import java.util.List; import java.util.Map; +@Tag(name = "My", description = "마이페이지 - 내가 작성한 리뷰 조회 및 관리 API") @RestController @RequestMapping("/my") public class MyController { @@ -23,6 +26,7 @@ public class MyController { @Autowired private CafeRepository cafeRepository; + @Operation(summary = "내가 작성한 리뷰 목록 조회", description = "userEmail을 기반으로 사용자가 작성한 리뷰 목록을 조회합니다.") @GetMapping("/reviews") public ResponseEntity> getUserReviews( @RequestHeader("Authorization") String authorizationHeader, @@ -40,6 +44,7 @@ public ResponseEntity> getUserReviews( return ResponseEntity.ok(reviews); } + @Operation(summary = "리뷰 상세 조회", description = "리뷰 ID를 기반으로 해당 리뷰의 상세 정보와 카페 정보를 조회합니다.") @GetMapping("/reviews/{reviewId}") public ResponseEntity> getReviewById(@PathVariable("reviewId") Long reviewId) { if (reviewId == null) { @@ -65,12 +70,14 @@ public ResponseEntity> getReviewById(@PathVariable("reviewId } } + @Operation(summary = "리뷰 수정", description = "리뷰 ID를 기반으로 내용을 수정합니다.") @PutMapping("/reviews/{reviewId}") public ResponseEntity updateReview(@PathVariable("reviewId") Long reviewId, @RequestBody ReviewDTO dto) { reviewService.updateReview(reviewId, dto); return ResponseEntity.ok("리뷰가 성공적으로 수정되었습니다."); } + @Operation(summary = "리뷰 삭제", description = "리뷰 ID를 기반으로 리뷰를 삭제합니다.") @DeleteMapping("/reviews/{reviewId}") public ResponseEntity deleteReview(@PathVariable("reviewId") Long reviewId) { try { @@ -80,6 +87,8 @@ public ResponseEntity deleteReview(@PathVariable("reviewId") Long review return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("리뷰 삭제 실패"); } } + + @Operation(summary = "태그 기반 리뷰 필터 조회", description = "userEmail과 선택한 태그 조건을 바탕으로 리뷰를 필터링하여 조회합니다.") @GetMapping("/reviews/filter") public ResponseEntity> getReviewsByCafeWithFilter( @RequestParam("userEmail") String userEmail, diff --git a/src/main/java/com/Minjin/TagCafe/controller/ReportedCafeController.java b/src/main/java/com/Minjin/TagCafe/controller/ReportedCafeController.java index acb328f..b32306c 100644 --- a/src/main/java/com/Minjin/TagCafe/controller/ReportedCafeController.java +++ b/src/main/java/com/Minjin/TagCafe/controller/ReportedCafeController.java @@ -9,6 +9,8 @@ import com.Minjin.TagCafe.service.CafeService; import com.Minjin.TagCafe.service.ReportedCafeService; import com.Minjin.TagCafe.repository.CafeRepository; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.security.core.userdetails.UsernameNotFoundException; @@ -19,6 +21,7 @@ import java.util.Map; import java.util.stream.Collectors; +@Tag(name = "Report", description = "카페 제보 등록 및 관리자 승인/관리 API") @RestController @RequiredArgsConstructor @RequestMapping("/report") @@ -31,12 +34,14 @@ public class ReportedCafeController { private final ReviewRepository reviewRepository; private final CafeService cafeService; + @Operation(summary = "카페 제보 등록", description = "사용자가 새로운 카페를 제보합니다.") @PostMapping public ResponseEntity reportCafe(@RequestBody ReportedCafe reportedCafe) { reportedCafeService.reportCafe(reportedCafe); return ResponseEntity.ok("제보 완료"); } + @Operation(summary = "내 제보 목록 조회", description = "사용자의 이메일을 기준으로 등록한 제보들을 조회합니다.") @GetMapping("/user/{userEmail}") public ResponseEntity> getReportsByUser(@PathVariable("userEmail") String userEmail) { List reports = reportedCafeService.getReportsByUser(userEmail); @@ -45,6 +50,8 @@ public ResponseEntity> getReportsByUser(@PathVariable("use .toList(); return ResponseEntity.ok(dtos); } + + @Operation(summary = "제보 상세 조회", description = "제보 ID를 기준으로 해당 제보 내용을 조회합니다.") @GetMapping("/{id}") public ResponseEntity getReportedCafe(@PathVariable("id") Long id) { ReportedCafe report = reportedCafeRepository.findById(id) @@ -52,6 +59,7 @@ public ResponseEntity getReportedCafe(@PathVariable("id") Long id) return ResponseEntity.ok(report); } + @Operation(summary = "제보 수정", description = "등록된 제보의 내용을 수정합니다.") @PutMapping("/{id}") public ResponseEntity updateReportedCafe(@PathVariable("id") Long id, @RequestBody ReportedCafe updated) { ReportedCafe report = reportedCafeRepository.findById(id) @@ -71,6 +79,7 @@ public ResponseEntity updateReportedCafe(@PathVariable("id") Long id, @R } //이미있는 카페인지 확인 + @Operation(summary = "카카오 ID로 기존 카페 조회", description = "중복 등록 방지를 위해 kakaoPlaceId로 등록된 카페가 있는지 확인합니다.") @GetMapping("/cafes/kakao/{kakaoPlaceId}") public ResponseEntity getCafeByKakaoPlaceId(@PathVariable("kakaoPlaceId") Long kakaoPlaceId) { return cafeRepository.findByKakaoPlaceId(kakaoPlaceId) @@ -82,6 +91,7 @@ public ResponseEntity getCafeByKakaoPlaceId(@PathVariable("kakaoPlaceId") Lon //관리자기능 //미승인 제보목록조회 + @Operation(summary = "admin - 미승인 제보 목록 조회", description = "승인되지 않은 제보 목록을 조회합니다.") @GetMapping("/admin/pending") public ResponseEntity> getPendingReports() { List pending = reportedCafeRepository.findByStatus(ReportedCafe.ReportStatus.PENDING); @@ -89,6 +99,7 @@ public ResponseEntity> getPendingReports() { } // 모든 제보 목록 조회 + @Operation(summary = "admin - 모든 제보 목록 조회", description = "관리자가 보는 전체 제보 목록입니다.") @GetMapping("/admin/all") public ResponseEntity> getAllReports() { List reports = reportedCafeRepository.findAll(); @@ -98,7 +109,9 @@ public ResponseEntity> getAllReports() { return ResponseEntity.ok(dtos); } + //제보 승인 + @Operation(summary = "admin - 제보 승인 및 카페 등록", description = "제보를 승인하여 실제 카페 정보로 저장하고, 자동으로 리뷰를 생성합니다.") @PostMapping("/admin/approve/{id}") public ResponseEntity approveReport(@PathVariable("id") Long id, @RequestBody(required = false) PhotoUrlsRequest photoUrlsRequest) { @@ -166,6 +179,7 @@ public ResponseEntity approveReport(@PathVariable("id") Long id, } // 제보 상세 조회 + @Operation(summary = "admin - 미승인 제보 상세 조회", description = "관리자가 미승인 제보 하나의 상세 정보를 조회합니다.") @GetMapping("/admin/pending/{id}") public ResponseEntity getPendingReportDetail(@PathVariable("id") Long id) { ReportedCafe report = reportedCafeRepository.findById(id) @@ -174,6 +188,7 @@ public ResponseEntity getPendingReportDetail(@PathVariable("id") L } // 제보 삭제 + @Operation(summary = "admin - 제보 반려 처리", description = "제보 상태를 REJECTED로 변경합니다.") @DeleteMapping("/admin/delete/{id}") public ResponseEntity deleteReport(@PathVariable("id") Long id) { ReportedCafe report = reportedCafeRepository.findById(id) diff --git a/src/main/java/com/Minjin/TagCafe/controller/SavedCafeController.java b/src/main/java/com/Minjin/TagCafe/controller/SavedCafeController.java index 65c003e..5c3a153 100644 --- a/src/main/java/com/Minjin/TagCafe/controller/SavedCafeController.java +++ b/src/main/java/com/Minjin/TagCafe/controller/SavedCafeController.java @@ -4,12 +4,15 @@ import com.Minjin.TagCafe.entity.Cafe; import com.Minjin.TagCafe.entity.SavedCafe; import com.Minjin.TagCafe.service.SavedCafeService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import java.util.List; +@Tag(name = "SavedCafe", description = "사용자 저장한 카페 및 방문여부 관리 API") @RestController @RequestMapping("/saved-cafes") @RequiredArgsConstructor @@ -17,12 +20,14 @@ public class SavedCafeController { private final SavedCafeService savedCafeService; // 저장한 카페 목록 조회 + @Operation(summary = "저장한 카페 목록 조회", description = "사용자의 userId를 기준으로 저장한 카페 목록을 조회합니다.") @GetMapping public ResponseEntity> getSavedCafes(@RequestParam("userId") Long userId) { return ResponseEntity.ok(savedCafeService.getSavedCafes(userId)); } // 카페 저장 여부 토글 (저장 or 삭제) + @Operation(summary = "카페 저장 토글", description = "카페를 저장하거나 삭제(찜 해제)합니다. 이미 저장되어 있으면 삭제됩니다.") @PatchMapping("/{cafeId}") public ResponseEntity toggleSavedStatus( @RequestParam("userId") Long userId, @@ -33,6 +38,7 @@ public ResponseEntity toggleSavedStatus( } // 방문여부 업데이트 + @Operation(summary = "카페 방문여부 토글", description = "카페의 방문 여부(방문함/안함)를 변경합니다.") @PatchMapping("/{cafeId}/visited") public ResponseEntity toggleVisited( @RequestParam("userId") Long userId, @@ -46,6 +52,7 @@ public ResponseEntity toggleVisited( } // 저장한 카페 목록 + 필터링 적용 + @Operation(summary = "저장한 카페 필터링 조회", description = "저장한 카페 목록을 태그 조건에 따라 필터링해서 조회합니다.") @GetMapping("/filter") public ResponseEntity> getSavedCafesWithFilter( @RequestParam("userId") Long userId, diff --git a/src/main/java/com/Minjin/TagCafe/controller/UserController.java b/src/main/java/com/Minjin/TagCafe/controller/UserController.java index 11c069c..18acde9 100644 --- a/src/main/java/com/Minjin/TagCafe/controller/UserController.java +++ b/src/main/java/com/Minjin/TagCafe/controller/UserController.java @@ -3,6 +3,8 @@ import com.Minjin.TagCafe.dto.NicknameRequest; import com.Minjin.TagCafe.entity.User; import com.Minjin.TagCafe.repository.UserRepository; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.servlet.http.Cookie; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; @@ -17,6 +19,7 @@ import java.util.Map; import java.util.Optional; +@Tag(name = "User", description = "사용자 정보 관리 및 탈퇴 API") @RestController @RequestMapping("/users") @RequiredArgsConstructor @@ -26,6 +29,8 @@ public class UserController { @Value("${kakao.client.id}") private String kakaoClientId; + + @Operation(summary = "닉네임 변경", description = "사용자의 이메일을 기반으로 닉네임을 변경합니다.") @PutMapping("/nickname") public ResponseEntity updateNickname(@RequestBody NicknameRequest request) { String email = request.getEmail(); @@ -42,6 +47,7 @@ public ResponseEntity updateNickname(@RequestBody NicknameRequest reques return ResponseEntity.status(HttpStatus.NOT_FOUND).body("사용자를 찾을 수 없습니다"); } + @Operation(summary = "회원 탈퇴", description = "이메일로 사용자를 삭제하고 세션 및 쿠키를 정리합니다.") @DeleteMapping("/delete") public ResponseEntity> deleteUser(@RequestParam("email") String email, HttpServletRequest req, HttpServletResponse res) { Optional userOptional = userRepository.findByEmail(email); @@ -77,6 +83,7 @@ public ResponseEntity> deleteUser(@RequestParam("email") Str } } + @Operation(summary = "유저 ID 조회", description = "이메일을 기반으로 유저 ID를 조회합니다.") @GetMapping("/id") public ResponseEntity getUserId(@RequestParam("email") String email) { Optional user = userRepository.findByEmail(email); From 0207c954dc7fc33231f7424c18caa8fb5b49466b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EC=A7=80?= Date: Wed, 16 Apr 2025 18:33:18 +0900 Subject: [PATCH 5/9] =?UTF-8?q?[feat]=20#22=20-=20home=EC=9D=80=20swagger?= =?UTF-8?q?=20=EB=AA=A9=EB=A1=9D=EC=97=90=EC=84=9C=20=EC=A0=9C=EC=99=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/Minjin/TagCafe/controller/HomeController.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/com/Minjin/TagCafe/controller/HomeController.java b/src/main/java/com/Minjin/TagCafe/controller/HomeController.java index 45678db..7f9cfaa 100644 --- a/src/main/java/com/Minjin/TagCafe/controller/HomeController.java +++ b/src/main/java/com/Minjin/TagCafe/controller/HomeController.java @@ -1,9 +1,11 @@ package com.Minjin.TagCafe.controller; +import io.swagger.v3.oas.annotations.Hidden; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.servlet.view.RedirectView; +@Hidden @RestController public class HomeController { @GetMapping("/") From abe50858c5182107d6a4326d401daab45b9c46e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EC=A7=80?= Date: Wed, 16 Apr 2025 18:34:11 +0900 Subject: [PATCH 6/9] =?UTF-8?q?[feat]=20#22=20-=20KakaoAuthController=20?= =?UTF-8?q?=EC=96=B4=EB=85=B8=ED=85=8C=EC=9D=B4=EC=85=98=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 --- .../java/com/Minjin/TagCafe/config/KakaoAuthController.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/com/Minjin/TagCafe/config/KakaoAuthController.java b/src/main/java/com/Minjin/TagCafe/config/KakaoAuthController.java index e4fca10..bbf1daa 100644 --- a/src/main/java/com/Minjin/TagCafe/config/KakaoAuthController.java +++ b/src/main/java/com/Minjin/TagCafe/config/KakaoAuthController.java @@ -3,6 +3,8 @@ import com.Minjin.TagCafe.entity.User; import com.Minjin.TagCafe.repository.UserRepository; import com.Minjin.TagCafe.util.JwtUtil; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -21,6 +23,7 @@ import java.util.Map; import java.util.Optional; +@Tag(name = "Auth", description = "카카오 로그인 및 사용자 인증 관련 API") @RestController @RequestMapping("/oauth/kakao") @RequiredArgsConstructor @@ -33,6 +36,7 @@ public class KakaoAuthController { private final UserRepository userRepository; private final JwtUtil jwtUtil; + @Operation(summary = "카카오 로그인 시작", description = "카카오 로그인 인증 페이지로 리디렉션합니다.") @GetMapping("/login") public RedirectView kakaoLogin() { String kakaoAuthUrl = "https://kauth.kakao.com/oauth/authorize" @@ -44,6 +48,7 @@ public RedirectView kakaoLogin() { return new RedirectView(kakaoAuthUrl); } + @Operation(summary = "카카오 로그인 콜백", description = "카카오 인증 후 사용자 정보를 받아옵니다.") @GetMapping("/callback") public RedirectView kakaoCallback(@RequestParam(name="code") String code) { @@ -119,6 +124,7 @@ public RedirectView kakaoCallback(@RequestParam(name="code") String code) { + "&token=" + jwtToken); } + @Operation(summary = "로그인한 사용자 정보 조회", description = "현재 로그인한 사용자의 정보를 반환합니다.") @GetMapping("/userinfo") public ResponseEntity getUserInfo(@RequestParam("access_token") String accessToken) { String userInfoUrl = "https://kapi.kakao.com/v2/user/me"; From 8b6752d11f6a5e2e8460f35a25be325f0a9b4e3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EC=A7=80?= Date: Wed, 16 Apr 2025 19:03:36 +0900 Subject: [PATCH 7/9] =?UTF-8?q?[docs]=20#22=20-=20README=20=EC=97=85?= =?UTF-8?q?=EB=8D=B0=EC=9D=B4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 54 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index a3cad8d..55efffd 100644 --- a/README.md +++ b/README.md @@ -1 +1,54 @@ -# TagCafe-BE \ No newline at end of file +# TagCafe Backend + +**카공에 진심인 당신을 위한 카페 플랫폼, TagCafe** + +와이파이, 책상 크기, 콘센트 등 카공에 중요한 요소들을 태그 기반으로 필터링하고, +리뷰와 제보를 통해 사용자에게 딱 맞는 카페를 찾아주는 서비스입니다. + +--- + +## 🌐 배포 주소 + +- 웹 서비스: [https://tagcafe.site](https://tagcafe.site) +- Swagger API 문서: [https://tagcafe.site/swagger-ui/index.html](https://tagcafe.site/swagger-ui/index.html) + +--- + +## 🧑‍💻 역할 + +| 이름 | 역할 | +|:----:|----------------------------------------------------------------| +| | 카페 검색 및 조회, 태그 필터링, 카페 저장 기능 개발
Swagger를 활용한 전체 API 문서화 | +| | 회원 관리, 마이페이지(리뷰/제보) 기능 구현
카카오 로그인 연동
CI/CD 설정 및 배포 자동화 | + +--- + +## 🛠 기술 스택 + +| 항목 | 내용 | +|------|------| +| 언어 | Java 17 | +| 프레임워크 | Spring Boot 3.4.2 | +| ORM | Spring Data JPA | +| 빌드 도구 | Gradle | +| DB | MySQL 8.0 (AWS RDS) | +| 인증 | Spring Security + Kakao OAuth + JWT | +| 배포 | Docker | +| API 문서화 | Swagger (springdoc-openapi) | +| 환경 변수 | dotenv-java (.env) | + +--- + +## 📁 프로젝트 구조 + +```bash +📦 TagCafe +┣ 📂 config # 전역 설정 (보안, Swagger, 카카오 OAuth 등) +┣ 📂 controller # API 컨트롤러 +┣ 📂 dto # 요청/응답 DTO +┣ 📂 entity # JPA 엔티티 +┣ 📂 repository # DB 접근 (JPA 레포지토리) +┣ 📂 service # 비즈니스 로직 처리 +┣ 📂 util # 공통 유틸 기능 (JWT) +┗ TagCafeApplication.java # 메인 클래스 +``` From e00c7e14fe80a3393c2dfb3044facd218d0c6f20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EC=A7=80?= Date: Wed, 16 Apr 2025 20:03:53 +0900 Subject: [PATCH 8/9] =?UTF-8?q?[docs]=20#22=20-=20=EB=A6=AC=EB=93=9C?= =?UTF-8?q?=EB=AF=B8=20=EA=B8=B0=EC=88=A0=20=EC=8A=A4=ED=83=9D=20=EC=97=85?= =?UTF-8?q?=EB=8D=B0=EC=9D=B4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 55efffd..5bd0bac 100644 --- a/README.md +++ b/README.md @@ -25,17 +25,20 @@ ## 🛠 기술 스택 -| 항목 | 내용 | -|------|------| -| 언어 | Java 17 | -| 프레임워크 | Spring Boot 3.4.2 | -| ORM | Spring Data JPA | -| 빌드 도구 | Gradle | -| DB | MySQL 8.0 (AWS RDS) | -| 인증 | Spring Security + Kakao OAuth + JWT | -| 배포 | Docker | -| API 문서화 | Swagger (springdoc-openapi) | -| 환경 변수 | dotenv-java (.env) | +| 항목 | 내용 | +|-------------|------------------------------------------------------------------| +| 언어 | Java 17 | +| 프레임워크 | Spring Boot 3.4.2 | +| ORM | Spring Data JPA | +| 빌드 도구 | Gradle | +| DB | MySQL 8.0 (AWS RDS) | +| 인증 | Spring Security + Kakao OAuth 2.0 + JWT | +| 배포 | Docker + Docker Compose + NGINX | +| CI/CD | GitHub Actions → EC2 자동 배포 | +| 웹서버 | NGINX (React + API 리버스 프록시) | +| 인증서 | Let’s Encrypt (HTTPS 인증서 적용) | +| 환경 변수 | dotenv-java 기반 `.env`, `application.yml` 에서 외부 주입 | +| API 문서화 | Swagger (springdoc-openapi) | --- From cdf7a9f746a6002461142a49584c567d3e7358a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=AF=BC=EC=A7=80?= Date: Wed, 16 Apr 2025 21:52:35 +0900 Subject: [PATCH 9/9] Update README.md --- README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 5bd0bac..b73a1f4 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ - 웹 서비스: [https://tagcafe.site](https://tagcafe.site) - Swagger API 문서: [https://tagcafe.site/swagger-ui/index.html](https://tagcafe.site/swagger-ui/index.html) ---- +
## 🧑‍💻 역할 @@ -21,7 +21,7 @@ | | 카페 검색 및 조회, 태그 필터링, 카페 저장 기능 개발
Swagger를 활용한 전체 API 문서화 | | | 회원 관리, 마이페이지(리뷰/제보) 기능 구현
카카오 로그인 연동
CI/CD 설정 및 배포 자동화 | ---- +
## 🛠 기술 스택 @@ -40,7 +40,7 @@ | 환경 변수 | dotenv-java 기반 `.env`, `application.yml` 에서 외부 주입 | | API 문서화 | Swagger (springdoc-openapi) | ---- +
## 📁 프로젝트 구조 @@ -55,3 +55,5 @@ ┣ 📂 util # 공통 유틸 기능 (JWT) ┗ TagCafeApplication.java # 메인 클래스 ``` + +