Skip to content

Conversation

@Ji-soo708
Copy link
Member

@Ji-soo708 Ji-soo708 commented Feb 13, 2025

💡 작업 내용

  • 실험 공고 수정 시, 입력 자동완성 지원을 위한 조회 API 구현
  • 관련 테스트 코드 추가

✅ 셀프 체크리스트

  • PR 제목을 형식에 맞게 작성했나요?
  • 브랜치 전략에 맞는 브랜치에 PR을 올리고 있나요?
  • 테스트는 잘 통과했나요?
  • 빌드에 성공했나요?
  • 본인을 assign 해주세요.
  • 해당 PR에 맞는 label을 붙여주세요.

🙋🏻‍ 확인해주세요

  • discord 백엔드 채널에서 논의된 사항입니다!

🔗 Jira 티켓


https://yappsocks.atlassian.net/browse/YS-310

Summary by CodeRabbit

  • 새로운 기능

    • 연구자 역할을 가진 사용자는 이제 포스트 편집 전 상세 정보를 미리 조회할 수 있습니다.
    • 포스트 업데이트를 위한 전용 엔드포인트가 추가되어, 기존 데이터를 보다 효율적으로 불러올 수 있습니다.
  • 테스트

    • 정상 호출, 권한 오류, 잘못된 식별자 등 다양한 시나리오를 검증하여 기능의 안정성이 강화되었습니다.

@Ji-soo708 Ji-soo708 added ✅ TEST 테스트 코드 추가 ✨ FEATURE 기능 추가 labels Feb 13, 2025
@Ji-soo708 Ji-soo708 self-assigned this Feb 13, 2025
@Ji-soo708 Ji-soo708 requested a review from chock-cho February 13, 2025 01:15
@coderabbitai
Copy link

coderabbitai bot commented Feb 13, 2025

"""

Walkthrough

이번 변경사항은 실험글 수정 시 필요한 상세 정보를 조회하는 기능을 추가합니다.
ExperimentPostService에 새로운 의존성 및 메소드가 추가되어, 업데이트용 실험글 상세 정보를 제공하며, 관련 UseCase와 매핑 로직이 구현됩니다.
또한, 연구자 전용 엔드포인트를 통해 해당 정보를 조회할 수 있도록 Controller와 Mapper가 수정되고, 이에 대한 테스트 케이스도 추가되었습니다.

Changes

파일 변경 요약
src/.../ExperimentPostService.kt 새로운 private 프로퍼티와 getExperimentPostDetailForUpdate 메소드 추가
src/.../GetExperimentPostDetailForUpdateUseCase.kt UseCase 인터페이스 구현, Input/Output 및 데이터 클래스, 확장 함수 추가로 업데이트용 상세 조회 로직 구현
src/.../ExperimentPostController.kt 연구자 전용 엔드포인트(/{postId}/edit) 및 관련 메소드 추가
src/.../ExperimentPostMapper.kt 업데이트용 조회를 위한 Input 생성 및 Output 변환 매핑 함수 추가
src/.../GetExperimentPostDetailForUpdateUseCaseTest.kt 새로운 UseCase에 대한 정상 및 예외 처리 시나리오 테스트 케이스 추가

Sequence Diagram(s)

sequenceDiagram
  participant C as Client
  participant Con as ExperimentPostController
  participant Map as ExperimentPostMapper
  participant Ser as ExperimentPostService
  participant UC as GetExperimentPostDetailForUpdateUseCase
  participant GW as ExperimentPostGateway

  C->>Con: GET /{postId}/edit 요청
  Con->>Map: toGetExperimentPostDetailForUpdateUseCaseInput(postId)
  Map-->>Con: UseCaseInput 생성
  Con->>Ser: getExperimentPostDetailForUpdate(input)
  Ser->>UC: execute(input) 호출
  UC->>GW: 실험글 조회 요청 (memberId, experimentPostId)
  GW-->>UC: 실험글 정보 반환
  UC-->>Ser: 상세 정보 Output 반환
  Ser-->>Con: Output 반환
  Con->>Map: toGetExperimentPostDetailForUpdateResponse(Output)
  Map-->>Con: ExperimentPostDetailResponse 생성
  Con-->>C: 응답 반환
Loading

Possibly related PRs

Poem

나는 코드를 뛰노는 귀여운 토끼,
실험글의 비밀을 담은 새로운 길을 찾아,
깡충깡충 뛰며 업데이트의 향연을 즐기네,
작은 함수와 클래스가 조화를 이루며
우리의 정원에 코드의 봄을 불러오네!
🐰✨
"""


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@github-actions github-actions bot changed the title feat: 실험 공고 수정 시, 입력 자동완성 지원을 위한 조회 API 구현 [YS-310] feat: 실험 공고 수정 시, 입력 자동완성 지원을 위한 조회 API 구현 Feb 13, 2025
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
src/main/kotlin/com/dobby/backend/application/usecase/experiment/GetExperimentPostDetailForUpdateUseCase.kt (1)

81-98: Extension 함수들이 책임을 잘 분할하여 매핑을 수행하고 있습니다.

  • toExperimentPostDetailForUpdate, toSummaryForUpdate, toTargetGroupForUpdate, toAddressForUpdate 등으로 변환 로직이 명확히 구분되어 있어, 코드 가독성과 유지보수성이 뛰어납니다.
  • ExperimentPost, TargetGroup 등 도메인 객체에서 사용자 정의 DTO로 변환 시, 필수/옵셔널 데이터를 명확히 구분해두면 추가 개발시 혼동을 줄일 수 있습니다.

만약 항목이 많아지는 경우, 변환 로직을 별도 매퍼(Mapping) 객체로 분리하는 것도 고려해 볼 수 있습니다.

Also applies to: 100-110, 112-119, 121-128

src/main/kotlin/com/dobby/backend/presentation/api/mapper/ExperimentPostMapper.kt (1)

157-211: 코드 중복 제거를 위한 리팩토링 제안

toGetExperimentPostDetailForUpdateUseCasetoGetExperimentPostDetailResponse 메소드 간에 중복된 매핑 로직이 존재합니다. 공통 매핑 로직을 추출하여 재사용성을 높이는 것이 좋겠습니다.

다음과 같은 리팩토링을 제안합니다:

private fun mapToExperimentPostDetailResponse(
    experimentPostId: String,
    title: String,
    uploadDate: LocalDateTime,
    uploaderName: String,
    views: Int,
    recruitStatus: RecruitStatus,
    summary: Any,
    targetGroup: Any,
    address: Any,
    content: String,
    imageList: List<String>,
    isAuthor: Boolean,
    isUploaderActive: Boolean,
    alarmAgree: Boolean
): ExperimentPostDetailResponse {
    return ExperimentPostDetailResponse(
        experimentPostId = experimentPostId,
        title = title,
        uploadDate = uploadDate,
        uploaderName = uploaderName,
        views = views,
        recruitStatus = recruitStatus,
        summary = when(summary) {
            is GetExperimentPostDetailForUpdateUseCase.ExperimentPostDetailForUpdate.Summary -> summary.toResponse()
            is GetExperimentPostDetailUseCase.ExperimentPostDetail.Summary -> summary.toResponse()
            else -> throw IllegalArgumentException("Unsupported summary type")
        },
        targetGroup = when(targetGroup) {
            is GetExperimentPostDetailForUpdateUseCase.ExperimentPostDetailForUpdate.TargetGroup -> targetGroup.toResponse()
            is GetExperimentPostDetailUseCase.ExperimentPostDetail.TargetGroup -> targetGroup.toResponse()
            else -> throw IllegalArgumentException("Unsupported target group type")
        },
        address = when(address) {
            is GetExperimentPostDetailForUpdateUseCase.ExperimentPostDetailForUpdate.Address -> address.toResponse()
            is GetExperimentPostDetailUseCase.ExperimentPostDetail.Address -> address.toResponse()
            else -> throw IllegalArgumentException("Unsupported address type")
        },
        content = content,
        imageList = imageList,
        isAuthor = isAuthor,
        isUploaderActive = isUploaderActive,
        alarmAgree = alarmAgree
    )
}

이 공통 메소드를 사용하여 기존 메소드들을 다음과 같이 수정할 수 있습니다:

fun toGetExperimentPostDetailForUpdateUseCase(response: GetExperimentPostDetailForUpdateUseCase.Output): ExperimentPostDetailResponse {
    return mapToExperimentPostDetailResponse(
        experimentPostId = response.experimentPostDetail.experimentPostId,
        title = response.experimentPostDetail.title,
        uploadDate = response.experimentPostDetail.uploadDate,
        uploaderName = response.experimentPostDetail.uploaderName,
        views = response.experimentPostDetail.views,
        recruitStatus = response.experimentPostDetail.recruitStatus,
        summary = response.experimentPostDetail.summary,
        targetGroup = response.experimentPostDetail.targetGroup,
        address = response.experimentPostDetail.address,
        content = response.experimentPostDetail.content,
        imageList = response.experimentPostDetail.imageList,
        isAuthor = response.experimentPostDetail.isAuthor,
        isUploaderActive = response.experimentPostDetail.isUploaderActive,
        alarmAgree = response.experimentPostDetail.alarmAgree
    )
}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 67f4e51 and dd279dc.

📒 Files selected for processing (5)
  • src/main/kotlin/com/dobby/backend/application/service/ExperimentPostService.kt (2 hunks)
  • src/main/kotlin/com/dobby/backend/application/usecase/experiment/GetExperimentPostDetailForUpdateUseCase.kt (1 hunks)
  • src/main/kotlin/com/dobby/backend/presentation/api/controller/ExperimentPostController.kt (1 hunks)
  • src/main/kotlin/com/dobby/backend/presentation/api/mapper/ExperimentPostMapper.kt (1 hunks)
  • src/test/kotlin/com/dobby/backend/application/usecase/experiment/GetExperimentPostDetailForUpdateUseCaseTest.kt (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: build
🔇 Additional comments (9)
src/main/kotlin/com/dobby/backend/application/usecase/experiment/GetExperimentPostDetailForUpdateUseCase.kt (3)

15-23: 클래스 선언과 Input 데이터 클래스 구조가 적절해 보입니다.
클래스와 Input 데이터 클래스가 각각의 책임을 명확히 분리하여 유스케이스를 호출할 때 필요한 파라미터를 깔끔하게 전달하고 있습니다. 대체로 좋은 구조로 보이며 추가적인 파라미터가 필요할 때도 변경 범위가 명확해져 유지보수에 유리합니다.


24-27: Output 데이터 클래스와 execute 메서드의 예외 처리 흐름이 적절합니다.

  • Output 데이터 클래스를 통해 반환 데이터의 구조를 명확히 정의한 점이 가독성과 유지보수성에 좋습니다.
  • execute 메서드 호출 시, Gateway의 findExperimentPostByMemberIdAndPostId(...)null인 경우 예외(ExperimentPostNotFoundException)를 던지는 것은 비정상 상황 처리를 명확히 해줍니다.
  • 필요하다면 예외 케이스에 대한 구체적인 로깅도 고려하실 수 있습니다.

Also applies to: 69-78


28-67: 중첩된 데이터 클래스들의 역할 분리와 구조가 명확합니다.

  • ExperimentPostDetailForUpdate 내의 Summary, TargetGroup, Address 등 세부 정보를 별도의 데이터 클래스로 분리하여 가독성이 좋습니다.
  • 필요한 정보가 체계적으로 배열되어 있어서, 후속 기능 확장(예: 다른 필드 추가)에도 유연하게 대응할 수 있을 것으로 보입니다.
src/test/kotlin/com/dobby/backend/application/usecase/experiment/GetExperimentPostDetailForUpdateUseCaseTest.kt (3)

21-29: mockk 라이브러리를 이용한 멤버 객체(Mock) 설정이 적절합니다.

  • member 객체의 id, name, deletedAt 등을 명확히 정의하여 테스트 환경을 잘 구성했습니다.
  • 이후 다른 테스트 케이스에도 재사용 가능하므로, 불필요한 중복 mock 생성을 줄이는 면에서도 유리합니다.

70-85: 작성자 본인에게 정상적으로 데이터를 반환하는 시나리오 테스트가 명확합니다.

  • given-when-then 구조로 흐름이 분리되어 있어 가독성이 좋습니다.
  • isAuthor 필드가 true로 반환되는지 확인하는 부분이 핵심 로직 검증에 포함되어 잘 처리되었습니다.

87-118: 실패 케이스(작성자가 아니거나 잘못된 ID) 테스트가 체계적으로 분리되어 있습니다.

  • 작성자가 아닌 경우와 존재하지 않는 게시글 ID를 각각 ExperimentPostNotFoundException이 발생하는지 확인하는 로직이 분명합니다.
  • 이 부분은 예외 처리가 의도한 대로 동작하는지 검증하는 핵심 코드로 보이며, 유지보수 시에도 쉽게 참조 가능합니다.
src/main/kotlin/com/dobby/backend/application/service/ExperimentPostService.kt (2)

31-31: 신규 UseCase 주입 방식이 분리되어 있어 의존성 구조가 명확합니다.

  • private val getExperimentPostForUpdateUseCase를 주입받아 변경에 쉽게 대응할 수 있습니다.
  • 새로운 유스케이스가 추가되더라도 차후 확장 용이성이 높아 보입니다.

51-54: getExperimentPostDetailForUpdate 메서드의 역할이 분명합니다.

  • 트랜잭션 범주 내에서 단순히 UseCase의 execute를 호출만 담당하므로, 서비스 레이어 역할을 명확히 구분한 점이 우수합니다.
  • 필요하다면 향후 로깅, 권한 체크 등 부가 로직을 추가하기도 용이합니다.
src/main/kotlin/com/dobby/backend/presentation/api/mapper/ExperimentPostMapper.kt (1)

183-211: 구현이 깔끔하고 잘 되어있습니다!

각 확장 함수가 명확한 책임을 가지고 있으며, 코드가 잘 구조화되어 있습니다.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
src/main/kotlin/com/dobby/backend/presentation/api/mapper/ExperimentPostMapper.kt (2)

164-181: 코드 중복을 제거하여 유지보수성을 향상시킬 수 있습니다.

toGetExperimentPostDetailForUpdateResponsetoGetExperimentPostDetailResponse 함수가 매우 유사한 로직을 가지고 있습니다. 공통 로직을 추출하여 재사용 가능한 private 함수로 만드는 것을 고려해보세요.

예시:

+    private fun toExperimentPostDetailResponse(
+        experimentPostId: String,
+        title: String,
+        uploadDate: LocalDateTime,
+        uploaderName: String,
+        views: Int,
+        recruitStatus: RecruitStatus,
+        summary: ExperimentPostDetailResponse.SummaryResponse,
+        targetGroup: ExperimentPostDetailResponse.TargetGroupResponse,
+        address: ExperimentPostDetailResponse.AddressResponse,
+        content: String,
+        imageList: List<String>,
+        isAuthor: Boolean,
+        isUploaderActive: Boolean,
+        alarmAgree: Boolean
+    ): ExperimentPostDetailResponse {
+        return ExperimentPostDetailResponse(
+            experimentPostId = experimentPostId,
+            title = title,
+            uploadDate = uploadDate,
+            uploaderName = uploaderName,
+            views = views,
+            recruitStatus = recruitStatus,
+            summary = summary,
+            targetGroup = targetGroup,
+            address = address,
+            content = content,
+            imageList = imageList,
+            isAuthor = isAuthor,
+            isUploaderActive = isUploaderActive,
+            alarmAgree = alarmAgree
+        )
+    }

183-211: 확장 함수의 활용이 좋습니다!

Summary, TargetGroup, Address에 대한 확장 함수를 사용하여 코드의 가독성을 높였습니다. 다만, 이 확장 함수들도 기존 코드와 중복되어 있으므로, 공통 인터페이스를 도입하여 코드 중복을 제거하는 것을 고려해보세요.

예시:

interface ExperimentPostDetail {
    interface Summary {
        val startDate: LocalDateTime
        val endDate: LocalDateTime
        val leadResearcher: String
        val matchType: MatchType
        val reward: Int
        val count: Int
        val timeRequired: Int
    }
    // TargetGroup, Address 인터페이스도 유사하게 정의
}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between dd279dc and 878e92a.

📒 Files selected for processing (2)
  • src/main/kotlin/com/dobby/backend/presentation/api/controller/ExperimentPostController.kt (1 hunks)
  • src/main/kotlin/com/dobby/backend/presentation/api/mapper/ExperimentPostMapper.kt (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/main/kotlin/com/dobby/backend/presentation/api/controller/ExperimentPostController.kt
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: build
🔇 Additional comments (1)
src/main/kotlin/com/dobby/backend/presentation/api/mapper/ExperimentPostMapper.kt (1)

157-162: 함수 구현이 깔끔합니다!

현재 멤버 ID와 실험 게시물 ID를 사용하여 UseCase 입력을 생성하는 로직이 명확하게 구현되어 있습니다.

Copy link
Member

@chock-cho chock-cho left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM👍👍 수고하셨어요!

@Ji-soo708 Ji-soo708 merged commit a1c0c54 into dev Feb 13, 2025
3 checks passed
@Ji-soo708 Ji-soo708 deleted the feat/YS-310 branch February 13, 2025 03:19
chock-cho pushed a commit that referenced this pull request Feb 16, 2025
* feat: add GetExperimentPostDetailForUpdateUseCase logic

* test: add GetExperimentPostDetailForUpdateUseCase test code

* refactor: rename mapper class for consistency
chock-cho pushed a commit that referenced this pull request Feb 16, 2025
* feat: add GetExperimentPostDetailForUpdateUseCase logic

* test: add GetExperimentPostDetailForUpdateUseCase test code

* refactor: rename mapper class for consistency
chock-cho pushed a commit that referenced this pull request Feb 16, 2025
* feat: add GetExperimentPostDetailForUpdateUseCase logic

* test: add GetExperimentPostDetailForUpdateUseCase test code

* refactor: rename mapper class for consistency
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

✨ FEATURE 기능 추가 ✅ TEST 테스트 코드 추가

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants