Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
ee2e363
fix(pick): PickService 버전 인터페이스 분리
yu-so-young2 Oct 19, 2025
d883524
test: PickServiceStrategyTest 작성
yu-so-young2 Oct 19, 2025
31c7547
Merge pull request #192 from dreamyPatisiel/DP-563
ssosee Oct 19, 2025
f82613c
fix: 일주일 이내 데이터 검사 util 함수 추가
yu-so-young2 Oct 22, 2025
f0cf808
fix: 픽픽픽 메인 API, 나고픽 API V2
yu-so-young2 Oct 26, 2025
6094a53
test: 픽픽픽 메인 API, 나고픽 API 테스트코드
yu-so-young2 Oct 26, 2025
479d15e
fix: 픽픽픽 메인 조회시 내용 마크다운 문법 제거
yu-so-young2 Oct 26, 2025
e3009b2
docs: 픽픽픽 메인, 나고픽 V2 문서
yu-so-young2 Oct 26, 2025
b4079c3
fix: 코드리뷰 반영
yu-so-young2 Oct 26, 2025
850c311
fix: 일주일 이내 기준 시간 외부에서 주입하도록 수정
yu-so-young2 Oct 26, 2025
9fb3ff5
Merge pull request #193 from dreamyPatisiel/DP-561
ssosee Oct 29, 2025
17de395
feat(MemberPickServiceV2): 픽픽픽 검색 기능 추가 및 테스트 코드 구현
ssosee Oct 29, 2025
a036cf1
feat(MemberPickServiceV2): 픽픽픽 검색 기능 추가 및 테스트 코드 구현
ssosee Nov 1, 2025
e50023d
feat(MemberPickServiceV2): 픽픽픽 검색 기능 추가 및 테스트 코드 구현
ssosee Nov 1, 2025
6fd9a10
feat(PickControllerV2): 픽픽픽 검색 기능 추가 및 테스트 코드 구현
ssosee Nov 2, 2025
8ec439e
feat(GuestPickServiceV2): findPickMainSearch() @Transactional 누락 추가
ssosee Nov 2, 2025
0fec0fc
feat(SecurityConstant): pick v2 endpoint whitelist url 추가
ssosee Nov 2, 2025
f124d2d
fix(리뷰 반영)
ssosee Nov 5, 2025
11210ee
Merge pull request #194 from dreamyPatisiel/DP-560
yu-so-young2 Nov 5, 2025
817185e
feat(pick): 픽픽픽 상세 조회 V2
yu-so-young2 Nov 5, 2025
051de8a
feat(pick): 픽픽픽 상세 조회 V2 API 구현
yu-so-young2 Nov 5, 2025
d1c497e
fix(dockerfile): 이미지 교체
yu-so-young2 Nov 5, 2025
58d41c3
test(pick): 픽픽픽 상세 조회 V2 테스트코드 수정
yu-so-young2 Nov 5, 2025
568d192
fix(pick): 상세조회 V2 문서 위치 변경
daisy-gbike Nov 5, 2025
b5fe7a2
Merge pull request #195 from dreamyPatisiel/DP-566
ssosee Nov 7, 2025
9b273e0
fix(): 픽픽픽 검색 중복 데이터 발생 이슈
ssosee Nov 16, 2025
5bd542e
Merge pull request #197 from dreamyPatisiel/DP-569
yu-so-young2 Nov 16, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Dockerfile-dev
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
FROM openjdk:21-jdk
FROM eclipse-temurin:21-jdk
# JAR 파일 메인 디렉토리에 복사
COPY build/libs/*.jar app.jar

# 타임존 설정
ENV TZ Asia/Seoul

# 시스템 진입점 정의
CMD java -jar -Dspring.profiles.active=dev /app.jar
CMD java -jar -Dspring.profiles.active=dev /app.jar
3 changes: 3 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,9 @@ dependencies {
// mybatis
implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:3.0.4'

// markdown parser
implementation 'org.commonmark:commonmark:0.21.0'

compileOnly 'org.projectlombok:lombok'
runtimeOnly 'com.h2database:h2'
runtimeOnly 'org.mariadb.jdbc:mariadb-java-client'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
= 픽픽픽
= 픽픽픽 V1

include::pick-main.adoc[]
include::pick-detail.adoc[]
Expand Down
34 changes: 34 additions & 0 deletions src/docs/asciidoc/api/pick/v2/pick-detail-v2.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
[[Pick-Detail-V2]]
== 픽픽픽 상세 API V2(GET: /devdevdev/api/v2/picks/{pickId})

* 픽픽픽 아이디로 상세 화면을 조회할 수 있다.
* 픽픽픽 게시글의 상태가 승인 상태(`APPROVAL`)가 아니면 조회할 수 없다.
* V1과 비교하여 응답에 **투표수(voteTotalCount)**와 **댓글수(commentTotalCount)** 필드가 추가되었다.

=== 정상 요청/응답

==== HTTP Request

include::{snippets}/pick-detail-v2/http-request.adoc[]

==== HTTP Request Header Fields

include::{snippets}/pick-detail-v2/request-headers.adoc[]

==== HTTP Request Path Parameters Fields

include::{snippets}/pick-detail-v2/path-parameters.adoc[]

==== HTTP Response

include::{snippets}/pick-detail-v2/http-response.adoc[]

==== HTTP Response Fields

include::{snippets}/pick-detail-v2/response-fields.adoc[]

=== V1과의 차이점

* `data.voteTotalCount`: 픽픽픽 전체 투표 수 (NEW)
* `data.commentTotalCount`: 픽픽픽 전체 댓글 수 (NEW)

17 changes: 17 additions & 0 deletions src/docs/asciidoc/api/pick/v2/pick-main-v2.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[[Pick-Main-V2]]
== 픽픽픽 메인 API(GET: /devdevdev/api/v2/picks)
* 픽픽픽 메인 화면을 조회할 수 있다.
* 회원/익명 사용자에 따라 API 응답값이 상이하다.

=== 정상 요청/응답
==== HTTP Request
include::{snippets}/pick-main-v2/http-request.adoc[]
==== HTTP Request Header Fields
include::{snippets}/pick-main-v2/request-headers.adoc[]
==== HTTP Request Query Parameters Fields
include::{snippets}/pick-main-v2/query-parameters.adoc[]

==== HTTP Response
include::{snippets}/pick-main-v2/http-response.adoc[]
==== HTTP Response Fields
include::{snippets}/pick-main-v2/response-fields.adoc[]
17 changes: 17 additions & 0 deletions src/docs/asciidoc/api/pick/v2/pick-search-v2.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[[pick-search-v2]]
== 픽픽픽 메인 검색 API(GET: /devdevdev/api/v2/picks/search)
* 픽픽픽 메인에서 검색 결과를 반환한다.
* 정확도순 정렬만 가능하다.

=== 정상 요청/응답
==== HTTP Request
include::{snippets}/pick-search-v2/http-request.adoc[]
==== HTTP Request Header Fields
include::{snippets}/pick-search-v2/request-headers.adoc[]
==== HTTP Request Query Parameters Fields
include::{snippets}/pick-search-v2/query-parameters.adoc[]

==== HTTP Response
include::{snippets}/pick-search-v2/http-response.adoc[]
==== HTTP Response Fields
include::{snippets}/pick-search-v2/response-fields.adoc[]
38 changes: 38 additions & 0 deletions src/docs/asciidoc/api/pick/v2/pick-similarity-v2.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
[[Pick-Similarties-V2]]
== 나도 고민 했는데 픽픽픽 API(GET: /devdevdev/api/v2/picks/{pickId}/similarties)

* 픽픽픽 상세와 유사도가 가장 높은 픽픽픽 3개를 조회한다.
* 유사도가 가장 높은 픽픽픽이 존재하지 않으면 빈 배열로 응답된다.
* 유사도 계산에 사용되는 embeddings 값이 없을 경우 503 예외를 발생한다.
** 외부 API(Open AI API) 를 사용하기 때문에 embeddings 값을 저장하지 못할 수 있다.
* 회원/익명 사용자 모두 조회할 수 있다.

=== 정상 요청/응답

==== HTTP Request

include::{snippets}/pick-similarity-v2/http-request.adoc[]

==== HTTP Request Header Fields

include::{snippets}/pick-similarity-v2/request-headers.adoc[]

==== HTTP Request Path Parameters Fields

include::{snippets}/pick-similarity-v2/path-parameters.adoc[]

==== HTTP Response

include::{snippets}/pick-similarity-v2/http-response.adoc[]

==== HTTP Response Fields

include::{snippets}/pick-similarity-v2/response-fields.adoc[]

=== 예외

==== HTTP Response

include::{snippets}/pick-similarity-not-found/response-body.adoc[]
include::{snippets}/pick-similarity-bad-request/response-body.adoc[]
include::{snippets}/pick-similarity-internal-server-exception/response-body.adoc[]
6 changes: 6 additions & 0 deletions src/docs/asciidoc/api/pick/v2/pick.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
= 픽픽픽 V2

include::pick-main-v2.adoc[]
include::pick-detail-v2.adoc[]
include::pick-search-v2.adoc[]
include::pick-similarity-v2.adoc[]
3 changes: 2 additions & 1 deletion src/docs/asciidoc/index.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ include::api/token/token.adoc[]
include::api/member/member.adoc[]
include::api/mypage/mypage.adoc[]
include::api/common/common.adoc[]
include::api/pick/pick.adoc[]
include::api/pick/v1/pick.adoc[]
include::api/pick/v2/pick.adoc[]
include::api/pick-commnet/pick-comment.adoc[]
include::api/tech-article/tech-article.adoc[]
include::api/tech-article-comment/tech-article-comment.adoc[]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Table(indexes = {
@Index(name = "idx__content_status", columnList = "contentStatus"),
@Index(name = "idx__member", columnList = "member_id")
@Index(name = "idx__member", columnList = "member_id"),
@Index(name = "idx_pick_01", columnList = "title")
})
public class Pick extends BasicTime {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,6 @@ public interface PickRepository extends JpaRepository<Pick, Long>, PickRepositor
List<Pick> findTop1000ByContentStatusAndEmbeddingsIsNotNullOrderByCreatedAtDesc(ContentStatus contentStatus);

Long countByMember(Member member);

Long countByContentStatus(ContentStatus contentStatus);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.dreamypatisiel.devdevdev.domain.repository.pick;

import lombok.Getter;

@Getter
public class PickSearchDto {
private final Long pickId;
private final Double maxTotalScore;

public PickSearchDto(Long pickId, Double maxTotalScore) {
this.pickId = pickId;
this.maxTotalScore = maxTotalScore;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
import com.dreamypatisiel.devdevdev.domain.entity.Member;
import com.dreamypatisiel.devdevdev.domain.entity.Pick;
import com.dreamypatisiel.devdevdev.domain.repository.pick.PickSort;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;

Expand All @@ -15,4 +17,6 @@ public interface PickRepositoryCustom {
Optional<Pick> findPickWithPickOptionByPickId(Long pickId);

Slice<Pick> findPicksByMemberAndCursor(Pageable pageable, Member member, Long pickId);

List<Pick> findPicksWithPickOptionWithMemberByIdIn(Set<Long> ids);
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
Expand Down Expand Up @@ -66,6 +67,16 @@ public Slice<Pick> findPicksByMemberAndCursor(Pageable pageable, Member member,
return new SliceImpl<>(contents, pageable, hasNextPage(contents, pageable.getPageSize()));
}

@Override
public List<Pick> findPicksWithPickOptionWithMemberByIdIn(Set<Long> ids) {
return query.selectFrom(pick)
.leftJoin(pick.pickOptions, pickOption)
.leftJoin(pick.member, member).fetchJoin()
.where(pick.id.in(ids)
.and(pick.contentStatus.eq(ContentStatus.APPROVAL)))
.fetch();
}

@Override
public Optional<Pick> findPickWithPickOptionWithPickVoteWithMemberByPickId(Long pickId) {
Pick findPick = query.selectFrom(pick)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.dreamypatisiel.devdevdev.domain.repository.pick.mybatis;

import com.dreamypatisiel.devdevdev.domain.repository.pick.PickSearchDto;
import java.util.List;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

@Mapper
public interface PickMapper {
List<PickSearchDto> findPickSearchDtoByKeywordAndCursor(@Param("cursorId") Long pickId,
@Param("keyword") String keyword,
@Param("cursorSearchScore") Double searchScore,
@Param("limit") int limit);
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@

@Service
@Transactional(readOnly = true)
public class GuestPickService extends PickCommonService implements PickService {
public class GuestPickService extends PickCommonService implements PickServiceV1 {

public static final String INVALID_ANONYMOUS_CAN_NOT_USE_THIS_FUNCTION_MESSAGE = "비회원은 현재 해당 기능을 이용할 수 없습니다.";

Expand Down
Loading
Loading