Skip to content

[Chore] v2 네트워크 공통 기반 구성 - #83

Merged
MinHeokChoi merged 2 commits into
mainfrom
chore/#81-v2-network-foundation
Jul 28, 2026
Merged

[Chore] v2 네트워크 공통 기반 구성#83
MinHeokChoi merged 2 commits into
mainfrom
chore/#81-v2-network-foundation

Conversation

@MinHeokChoi

@MinHeokChoi MinHeokChoi commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

✨ PR 유형

어떤 변경 사항이 있나요??

  • 새로운 기능 추가
  • 버그 수정
  • 사용자 UI 디자인 변경 및 추가
  • 코드에 영향을 주지 않는 변경사항(오타 수정, 탭 사이즈 변경, 변수명 변경)
  • 코드 리팩토링
  • 주석 추가 및 수정
  • 문서 수정
  • 테스트 추가, 테스트 리팩토링
  • 빌드 부분 혹은 패키지 매니저 수정
  • 파일 혹은 폴더명 수정
  • 파일 혹은 폴더 삭제

🛠️ 작업내용

  • 운영/커스텀 Base URL과 request/resource timeout을 관리하는
    NetworkConfiguration을 추가했습니다.
  • MoruTargetType, public/bearer 인증 경계, Moya provider 조립과
    DefaultAPIClient actor를 추가했습니다.
  • 공통 응답과 HTTP/논리/전송/디코딩/인증/취소 오류 계약을 추가했습니다.
  • Target이 직접 선언한 Authorization 헤더를 제거하고 필수 AccessTokenPlugin만
    bearer token을 주입하도록 고정했습니다.
  • Swift Task cancellation을 Alamofire request cancellation으로 전달합니다.
  • 토큰, 헤더, 요청 본문을 기록하지 않는 DEBUG OSLog를 추가했습니다.
  • /health Target, deterministic Moya stub 테스트와 v2 확장 문서를 추가했습니다.
  • App/DependencyContainer 런타임 주입과 앱 시작 네트워크 호출은 추가하지 않았습니다.
  • SwiftData, Domain, 기존 Local Repository 계약은 변경하지 않았습니다.

검증

  • Network Foundation XCTest: 22 passed, 0 failed/skipped
  • 전체 XCTest 직렬 재검증(iPhone 16 Simulator, iOS 26.5):
    294 passed, 0 failed/skipped
  • iPhone 16 Simulator Debug build: passed
  • generic iPhone Debug/Release build: passed
  • bash Scripts/check-iphone-functional-gate.sh: passed
  • bash Scripts/check-swiftdata-boundary.sh: passed
  • plutil -lint Moru/Info.plist: passed
  • git diff --check: passed
  • 운영 /health: HTTP 200 / OK
  • 실제 iPhone: 미검증

📋 추후 진행 상황

  • 후속 P1에서 인증 Target/DTO와 RemoteDataSource를 추가합니다.
  • Keychain, 토큰 재발급, 런타임 계정 세션 주입은 각각 후속 PR에서 구현합니다.

📌 리뷰 포인트

  • public 요청에 Authorization 헤더가 남지 않고 bearer 요청만 token snapshot을
    한 번 읽는지 확인해 주세요.
  • 2xx 논리 오류, HTTP 오류, void/raw 응답, cancellation 매핑이 공통 계약과
    맞는지 확인해 주세요.
  • 기존 v1 오프라인 부팅 경로에 런타임 변화가 없는지 확인해 주세요.

✅ Checklist

PR이 다음 요구 사항을 충족하는지 확인해주세요!!!

Closes #81

Summary by CodeRabbit

  • New Features
    • Introduced a shared networking foundation with typed API responses, raw data retrieval, void request support, and a health-check endpoint.
    • Added bearer-token authorization plumbing and target-to-network request adaptation.
  • Bug Fixes
    • Standardized API error reporting, including logical failures in successful HTTP responses, decoding/envelope validation, and cancellation mapping.
    • Improved retry classification for temporary transport/server failures.
  • Documentation
    • Documented v2 networking conventions, authentication boundaries, response handling rules, and integration workflow.
  • Tests
    • Added comprehensive networking coverage for timeouts, headers, response/error mapping, cancellation, and logging safety.

@coderabbitai

coderabbitai Bot commented Jul 25, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 3ca6de84-18da-4ae6-b286-fc4a7ebe7ff9

📥 Commits

Reviewing files that changed from the base of the PR and between 0bbec7e and 778e825.

📒 Files selected for processing (1)
  • Moru/Moru/Network/Core/APIClient.swift
🚧 Files skipped from review as they are similar to previous changes (1)
  • Moru/Moru/Network/Core/APIClient.swift

📝 Walkthrough

Walkthrough

Adds a v2 networking foundation using Moya and Alamofire, including shared request contracts, typed response handling, bearer authentication, timeout configuration, error and cancellation mapping, health-check support, comprehensive tests, and architecture documentation.

Changes

Network Foundation

Layer / File(s) Summary
Network contracts and configuration
Moru/Moru/Network/Core/APIResponse.swift, Moru/Moru/Network/Core/APIError.swift, Moru/Moru/Network/Core/AuthenticationRequirement.swift, Moru/Moru/Network/Core/MoruTargetType.swift, Moru/Moru/Network/Core/NetworkConfiguration.swift, Moru/Moru/Network/Targets/HealthTarget.swift
Defines response envelopes, API errors and retryability, authentication requirements, target contracts, validated network settings, and the /health target.
Provider composition and request adaptation
Moru/Moru/Network/Core/MoyaTargetAdapter.swift, Moru/Moru/Network/Core/MoyaProviderFactory.swift, Moru/Moru/Network/Core/NetworkLogPlugin.swift
Adapts targets for Moya, snapshots bearer tokens, applies timeouts and plugins, and logs request metadata without headers or bodies.
API execution and error handling
Moru/Moru/Network/Core/APIClient.swift
Implements typed, void, and raw-data requests with status validation, envelope decoding, authentication gating, transport error mapping, and cancellation coordination.
Behavior validation and integration guidance
Moru/MoruTests/NetworkFoundationTests.swift, Moru/docs/V2NetworkFoundation.md, README.md
Tests response handling, authentication, cancellation, timeouts, token snapshots, retryability, and log redaction; documents v2 network boundaries and usage conventions.

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

Sequence Diagram(s)

sequenceDiagram
  participant Caller
  participant DefaultAPIClient
  participant MoyaProviderFactory
  participant MoyaProvider
  participant Server
  Caller->>DefaultAPIClient: request target
  DefaultAPIClient->>MoyaProviderFactory: adapt target and configure provider
  DefaultAPIClient->>MoyaProvider: perform request
  MoyaProvider->>Server: send HTTP request
  Server-->>MoyaProvider: return response
  MoyaProvider-->>DefaultAPIClient: return data or error
  DefaultAPIClient-->>Caller: decode result or throw APIError
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed 제목이 v2 네트워크 공통 기반 추가라는 핵심 변경을 짧고 명확하게 요약합니다.
Description check ✅ Passed 필수 섹션을 모두 채웠고 작업내용, 후속 작업, 리뷰 포인트, 체크리스트가 충분히 정리돼 있습니다.
Linked Issues check ✅ Passed 공통 API Client, Base URL, 응답/오류 매핑, bearer 주입, /health 테스트, 문서화 등 #81 요구사항을 충족합니다.
Out of Scope Changes check ✅ Passed v1 로컬 경로와 제외 범위를 유지하며 변경은 네트워크 기반, 테스트, 문서에 국한됩니다.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/#81-v2-network-foundation

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

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
Moru/Moru/Network/Core/APIClient.swift (1)

42-102: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicate envelope decode + isSuccess handling between request and requestVoid.

Both methods repeat the same decode-and-map-to-APIError logic (Lines 51-63 vs 86-101). Extracting a shared helper would keep the envelope contract in one place and reduce future drift risk.

♻️ Proposed refactor
+  private func decodeEnvelope<Payload: Decodable & Sendable>(
+    _ type: Payload.Type,
+    from response: HTTPResponseSnapshot
+  ) throws -> APIResponse<Payload> {
+    do {
+      return try decoder.decode(APIResponse<Payload>.self, from: response.data)
+    } catch {
+      throw APIError.decoding(error.localizedDescription)
+    }
+  }
+
   func request<Target: MoruTargetType, Payload: Decodable & Sendable>(
     _ target: Target,
     as payloadType: Payload.Type
   ) async throws -> Payload {
     let response = try await perform(target)
     try validateStatus(response)

-    let envelope: APIResponse<Payload>
-
-    do {
-      envelope = try decoder.decode(APIResponse<Payload>.self, from: response.data)
-    } catch {
-      throw APIError.decoding(error.localizedDescription)
-    }
+    let envelope = try decodeEnvelope(Payload.self, from: response)

     guard envelope.isSuccess else {
       throw APIError.server(
         statusCode: response.statusCode,
         code: envelope.code,
         message: envelope.message
       )
     }
     ...
   }

   func requestVoid<Target: MoruTargetType>(_ target: Target) async throws {
     let response = try await perform(target)
     try validateStatus(response)

     guard response.statusCode != 204,
           response.statusCode != 205 else {
       return
     }

-    let envelope: APIResponse<EmptyAPIResult>
-
-    do {
-      envelope = try decoder.decode(
-        APIResponse<EmptyAPIResult>.self,
-        from: response.data
-      )
-    } catch {
-      throw APIError.decoding(error.localizedDescription)
-    }
+    let envelope = try decodeEnvelope(EmptyAPIResult.self, from: response)

     guard envelope.isSuccess else {
       throw APIError.server(
         statusCode: response.statusCode,
         code: envelope.code,
         message: envelope.message
       )
     }
   }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Moru/Moru/Network/Core/APIClient.swift` around lines 42 - 102, Extract the
duplicated envelope decoding and success validation from request and requestVoid
into a shared helper on APIClient, parameterized for the requested Decodable
payload type and response data/status code. Have both methods reuse that helper
while preserving their existing result-unwrapping behavior in request and
void-response handling for 204/205 in requestVoid.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@Moru/Moru/Network/Core/APIClient.swift`:
- Around line 42-102: Extract the duplicated envelope decoding and success
validation from request and requestVoid into a shared helper on APIClient,
parameterized for the requested Decodable payload type and response data/status
code. Have both methods reuse that helper while preserving their existing
result-unwrapping behavior in request and void-response handling for 204/205 in
requestVoid.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: e4ee65bf-b92f-45e5-b64e-e8309565fa87

📥 Commits

Reviewing files that changed from the base of the PR and between a9e88b5 and 0bbec7e.

📒 Files selected for processing (13)
  • Moru/Moru/Network/Core/APIClient.swift
  • Moru/Moru/Network/Core/APIError.swift
  • Moru/Moru/Network/Core/APIResponse.swift
  • Moru/Moru/Network/Core/AuthenticationRequirement.swift
  • Moru/Moru/Network/Core/MoruTargetType.swift
  • Moru/Moru/Network/Core/MoyaProviderFactory.swift
  • Moru/Moru/Network/Core/MoyaTargetAdapter.swift
  • Moru/Moru/Network/Core/NetworkConfiguration.swift
  • Moru/Moru/Network/Core/NetworkLogPlugin.swift
  • Moru/Moru/Network/Targets/HealthTarget.swift
  • Moru/MoruTests/NetworkFoundationTests.swift
  • Moru/docs/V2NetworkFoundation.md
  • README.md

@MinHeokChoi
MinHeokChoi merged commit c44afae into main Jul 28, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Chore] v2 공통 서버 통신 기반 구축

1 participant