Skip to content

feat, refactor: addChild 방식 드롭다운 구현 - #647

Merged
hgjwilly merged 12 commits into
developfrom
refactor/koindropdown-addchild
Nov 2, 2026
Merged

hgjwilly merged 12 commits into
developfrom
refactor/koindropdown-addchild

Conversation

@hgjwilly

@hgjwilly hgjwilly commented Nov 2, 2026 •

Copy link
Copy Markdown
Contributor

#️⃣연관된 이슈

📝작업 내용

기존 드롭다운(KoinDropdown + KoinDropdownHost)의 scrollView 안에 overlay와 드롭다운 View를 추가하는 방식은 다음과 같은 문제를 갖습니다.

  • scrollView 밖(하단 버튼 등)의 터치를 막지 못하므로, 화면마다 isPresenting 가드가 필요했음
  • 화면마다 KoinDropdownHost를 프로퍼티로 들고 셀·서브뷰까지 전달해야 했음(prepareDropdown(host:))
  • scrollView가 없는 화면에서는 쓸 수 없었음
  • 화면 크기가 바뀌어도 드롭다운 위치·너비가 갱신되지 않았음

addChild 방식 드롭다운으로 리팩토링하며 이를 개선합니다.

구조

  • KoinDropdownViewController: 부모 VC의 view 전체를 덮는 child VC
    • 드롭다운 표시 중에는 바깥 영역(부모 화면)의 터치가 막힌다. 바깥 영역을 탭하면 드롭다운을 닫는다.
    • +Present(표시·해제), +Scroll(스크롤·inset 조정), +Layout(배치·그림자)으로 파일 분리
  • UIViewController+Dropdown
    • presentDropdown(anchor:content:configuration:), isPresentingDropdown
    • UIView.presentDropdown(...): responder chain으로 가장 가까운 VC를 찾아 띄움(셀·서브뷰에서 바로 호출 가능)
  • KoinDropdownContentView: 콘텐츠 프로토콜(별도 파일로 분리)
  • KoinDropdownConfiguration: direction, shadow
    • 기존 topPadding은 direction의 연관값 spacing(anchor와 드롭다운 사이 간격)으로 대체

동작

  • 아래 공간이 부족하면 하단 inset을 추가하고스크롤합니다. 닫으면 원복합니다.
  • 스크롤 이동과 드롭다 블록에서 바꿔,trigger와 드롭다운이 함께 움직입니다.
  • 회전·창 크기 변경(iP 지 않고 anchor기준으로 다시 배치합니다.
  • direction 옵션
    • .down(spacing:): 항상 아래로 열림(기존 동작)
    • `.auto(downSpacing→ 더 넓은 쪽 순으로자동 선택. 방향별로 간격을 따로 지정
    • .auto는 시간표 롭다운용입니다. 현재사용하는 화면은 없습니다.

스크린샷 (선택)

💬리뷰 요구사항(선택)

바텀시트 안에서 쓸 때, 시트 콘텐츠에서 UIView.presentDropdowclipsToBounds)에 갇혀잘립니다. 콘텐츠는 이벤트만 방출하고, 시트를 띄운 VC가 presentDropdown`을 호출해야합니다.

Summary by CodeRabbit

  • New Features
    • Dropdowns are now presented directly from date, time, and selection controls across posting and application flows.
    • Dropdowns can adjust their placement to available space and keep their content accessible when space is limited.
    • Tapping outside a dropdown or choosing its dismiss action closes it.
  • Improvements
    • Form actions can proceed while a dropdown is open, and dropdowns are handled more smoothly during navigation and keyboard changes.

@hgjwilly hgjwilly self-assigned this Nov 2, 2026
@hgjwilly hgjwilly added REFACTOR 리팩토링 FEAT 기능 개발 및 api 연동 labels Nov 2, 2026
@coderabbitai

coderabbitai Bot commented Nov 2, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 50 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Learn how review limits work.

Review configuration:

Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 675e7fe7-1f56-4caf-a568-f14273098355
Commits

Reviewing files that changed from the base of the PR and between fc22767 and 6bf8a36.

Files selected for processing: 24
  • Koin/Core/Extensions/UIKit/UIViewController+Dropdown.swift
  • Koin/Core/View/UIKit/KoinDropdown/KoinDropdown.swift
  • Koin/Core/View/UIKit/KoinDropdown/KoinDropdownAnimator.swift
  • Koin/Core/View/UIKit/KoinDropdown/KoinDropdownConfiguration.swift
  • Koin/Core/View/UIKit/KoinDropdown/KoinDropdownContentView.swift
  • Koin/Core/View/UIKit/KoinDropdown/KoinDropdownHost.swift
  • Koin/Core/View/UIKit/KoinDropdown/KoinDropdownViewController+Layout.swift
  • Koin/Core/View/UIKit/KoinDropdown/KoinDropdownViewController+Present.swift
  • Koin/Core/View/UIKit/KoinDropdown/KoinDropdownViewController+Scroll.swift
  • Koin/Core/View/UIKit/KoinDropdown/KoinDropdownViewController.swift
  • Koin/Presentation/CallVan/CallVanPost/CallVanPostViewController.swift
  • Koin/Presentation/LostItem/EditLostItem/EditLostItemViewController.swift
  • Koin/Presentation/LostItem/EditLostItem/SubViews/EditLostItemFoundDateView.swift
  • Koin/Presentation/LostItem/PostLostItem/PostLostItemViewController.swift
  • Koin/Presentation/LostItem/PostLostItem/SubViews/AddLostItemCollectionView/AddLostItemCollectionView.swift
  • Koin/Presentation/LostItem/PostLostItem/SubViews/AddLostItemCollectionView/AddLostItemCollectionViewCell.swift
  • Koin/Presentation/Recruit/RecruitApply/RecruitApplyViewController.swift
  • Koin/Presentation/Recruit/RecruitApply/Subviews/RecruitApplyFirstStepView.swift
  • Koin/Presentation/Recruit/RecruitPost/RecruitPostViewController.swift
  • Koin/Presentation/Recruit/RecruitProfilePost/RecruitProfilePostViewController.swift
  • Koin/Presentation/Recruit/RecruitProfilePost/SecondStepView/RecruitProfilePostSecondStepView.swift
  • Koin/Presentation/Recruit/RecruitProfilePost/SecondStepView/Subviews/RecruitProfilePostActivityEditTableViewCell.swift
  • Koin/Presentation/Recruit/RecruitProfilePost/SecondStepView/Subviews/RecruitProfilePostActivityTableView.swift
  • koin.xcodeproj/project.pbxproj

No actionable comments were generated in the recent review.

Recent review info
Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 4591f465-58d4-4c41-a57c-5f22ee0aad29
Commits

Reviewing files that changed from the base of the PR and between 4900f45 and fc22767.

Files selected for processing: 24
  • Koin/Core/Extensions/UIKit/UIViewController+Dropdown.swift
  • Koin/Core/View/UIKit/KoinDropdown/KoinDropdown.swift
  • Koin/Core/View/UIKit/KoinDropdown/KoinDropdownAnimator.swift
  • Koin/Core/View/UIKit/KoinDropdown/KoinDropdownConfiguration.swift
  • Koin/Core/View/UIKit/KoinDropdown/KoinDropdownContentView.swift
  • Koin/Core/View/UIKit/KoinDropdown/KoinDropdownHost.swift
  • Koin/Core/View/UIKit/KoinDropdown/KoinDropdownViewController+Layout.swift
  • Koin/Core/View/UIKit/KoinDropdown/KoinDropdownViewController+Present.swift
  • Koin/Core/View/UIKit/KoinDropdown/KoinDropdownViewController+Scroll.swift
  • Koin/Core/View/UIKit/KoinDropdown/KoinDropdownViewController.swift
  • Koin/Presentation/CallVan/CallVanPost/CallVanPostViewController.swift
  • Koin/Presentation/LostItem/EditLostItem/EditLostItemViewController.swift
  • Koin/Presentation/LostItem/EditLostItem/SubViews/EditLostItemFoundDateView.swift
  • Koin/Presentation/LostItem/PostLostItem/PostLostItemViewController.swift
  • Koin/Presentation/LostItem/PostLostItem/SubViews/AddLostItemCollectionView/AddLostItemCollectionView.swift
  • Koin/Presentation/LostItem/PostLostItem/SubViews/AddLostItemCollectionView/AddLostItemCollectionViewCell.swift
  • Koin/Presentation/Recruit/RecruitApply/RecruitApplyViewController.swift
  • Koin/Presentation/Recruit/RecruitApply/Subviews/RecruitApplyFirstStepView.swift
  • Koin/Presentation/Recruit/RecruitPost/RecruitPostViewController.swift
  • Koin/Presentation/Recruit/RecruitProfilePost/RecruitProfilePostViewController.swift
  • Koin/Presentation/Recruit/RecruitProfilePost/SecondStepView/RecruitProfilePostSecondStepView.swift
  • Koin/Presentation/Recruit/RecruitProfilePost/SecondStepView/Subviews/RecruitProfilePostActivityEditTableViewCell.swift
  • Koin/Presentation/Recruit/RecruitProfilePost/SecondStepView/Subviews/RecruitProfilePostActivityTableView.swift
  • koin.xcodeproj/project.pbxproj
Files with no reviewable changes: 6
  • Koin/Core/View/UIKit/KoinDropdown/KoinDropdownHost.swift
  • Koin/Presentation/Recruit/RecruitApply/Subviews/RecruitApplyFirstStepView.swift
  • Koin/Presentation/Recruit/RecruitProfilePost/SecondStepView/RecruitProfilePostSecondStepView.swift
  • Koin/Core/View/UIKit/KoinDropdown/KoinDropdown.swift
  • Koin/Presentation/LostItem/PostLostItem/SubViews/AddLostItemCollectionView/AddLostItemCollectionView.swift
  • Koin/Presentation/Recruit/RecruitProfilePost/SecondStepView/Subviews/RecruitProfilePostActivityTableView.swift

Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.

Walkthrough

The dropdown implementation now uses a view controller with directional placement, layout, and scroll handling. UIKit helpers provide presentation from views and view controllers. Call-van, lost-item, and recruitment screens now use the new presentation API instead of KoinDropdownHost.

Changes: Dropdown presentation

Layer / File(s) Summary
Configuration and content contract
Koin/Core/View/UIKit/KoinDropdown/KoinDropdownConfiguration.swift, KoinDropdownContentView.swift, KoinDropdownAnimator.swift
Configuration supports downward or automatic placement with direction-specific spacing and shadow padding. The content protocol exposes a dismiss publisher and height. The animator uses a hidden offset for presentation and dismissal.
Controller lifecycle and layout
Koin/Core/View/UIKit/KoinDropdown/KoinDropdownViewController*, KoinDropdownViewController+*, KoinDropdown.swift, KoinDropdownHost.swift
The new controller manages presentation, dismissal, directional layout, and scroll preparation and restoration. The former dropdown view and host are removed.
Presentation API and project wiring
Koin/Core/Extensions/UIKit/UIViewController+Dropdown.swift, koin.xcodeproj/project.pbxproj
UIKit helpers present a dropdown from a view controller or find a controller through a view’s responder chain. The project registers the new dropdown implementation files.
Application call-site migration
Koin/Presentation/CallVan/CallVanPost/CallVanPostViewController.swift, Koin/Presentation/LostItem/*, Koin/Presentation/Recruit/*
Call-van, lost-item, and recruitment screens use direct dropdown presentation. Host setup and presentation checks are removed or replaced with controller state checks.

Estimated code review effort: 4 (Complex) | ~45 minutes

Change: Feature

Sequence Diagram(s)

sequenceDiagram
  participant DateButton
  participant UIView
  participant UIViewController
  participant KoinDropdownViewController
  participant KoinDropdownContentView
  DateButton->>UIView: call presentDropdown with anchor and content
  UIView->>UIViewController: find controller through responder chain
  UIViewController->>KoinDropdownViewController: attach child and present
  KoinDropdownViewController->>KoinDropdownContentView: add content and subscribe to dismiss publisher
Loading

Possibly related issues

  • Issue 646: The PR replaces host-managed dropdown presentation with a controller-based implementation and adds directional layout and scroll handling described in the issue.
  • Issue 644: The PR delegates view-based presentation to a view controller, but the supplied summaries do not show a bottom-sheet-specific integration change.
Merge Risk: Minimal · previous review fc227

No actionable issue was established that should block merging after normal checks.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 24.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documenta… Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly identifies the main change: replacing the existing dropdown approach with an addChild-based implementation.
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

Docstring coverage is 24.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 25 functions across 17 files. (1 skipped: 1 unsupported.)

Resolution

Write docstrings for the functions missing them to satisfy the coverage threshold.

Finishing Touches
Generate docstrings
  • Commit to this branch
  • Create a new PR
Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

@hgjwilly
hgjwilly force-pushed the refactor/koindropdown-addchild branch from fc22767 to 6bf8a36 Compare November 2, 2026 10:40
@hgjwilly
hgjwilly merged commit aa4fac7 into develop Nov 2, 2026
2 checks passed
@hgjwilly
hgjwilly deleted the refactor/koindropdown-addchild branch November 2, 2026 15:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

FEAT 기능 개발 및 api 연동 REFACTOR 리팩토링

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant