Skip to content

refactor: 네트워크 레이어 리팩터링#60

Merged
clxxrlove merged 4 commits into
developfrom
BOOK-107-refactor/#57
Jul 8, 2025
Merged

refactor: 네트워크 레이어 리팩터링#60
clxxrlove merged 4 commits into
developfrom
BOOK-107-refactor/#57

Conversation

@clxxrlove
Copy link
Copy Markdown
Member

@clxxrlove clxxrlove commented Jul 8, 2025

🔗 관련 이슈

📘 작업 유형

  • ✨ Feature (기능 추가)
  • 🐞 Bugfix (버그 수정)
  • 🔧 Refactor (코드 리팩토링)
  • ⚙️ Chore (환경 설정)
  • 📝 Docs (문서 작성 및 수정)
  • ✅ Test (기능 테스트)
  • 🎨 style (코드 스타일 수정)

📙 작업 내역

  • NetworkError가 상위 모듈이 아닌 Network Layer에 잘못 위치하던 부분 수정
  • 일부 throwable한 메소드를 AnyPublisher로 변경
  • @Autowired의 가이드 수정

🧪 테스트 내역

  • 브라우저/기기에서 동작 확인
  • 엣지 케이스 테스트 완료
  • 기존 기능 영향 없음

💬 추가 설명 or 리뷰 포인트 (선택)

  • @Autowired는 사실 생각한게 있어서 그 부분 수정하려고 했는데 이미 잘 되어있었어서... 문서만 수정했습니다.
  • throwable한 메소드들을 과연 AnyPublisher로 전부 묶는게 맞는 건지 잘 모르겠습니다.
    • 일단 바꿀만한 것들만 조금 바꿨고 애매한 것들은 냅뒀는데요. 처음부터 Combine 설계를 했으면 모를까 어렵네요.
    • 나중에 각잡고 리팩터링 하겠습니다...

Summary by CodeRabbit

  • 문서화

    • @Autowired 프로퍼티 래퍼 사용 예시와 가이드가 개선되었습니다.
  • 신규 기능

    • 네트워크 오류 타입에 retryTriggerunknown 케이스가 추가되었습니다.
  • 버그 수정

    • 네트워크 요청 및 URL 생성 관련 오류 처리가 더욱 구체적인 NetworkError 타입으로 통일되었습니다.
    • 네트워크 요청 흐름이 비동기 스트림 기반으로 개선되어 오류 발생 시 일관된 처리가 가능합니다.
  • 리팩터

    • 네트워크 요청, URL 생성, 오류 처리 로직이 Combine 기반의 비동기 스트림으로 전환되었습니다.
    • 불필요한 사용자 정의 오류 타입(RetryTrigger)이 제거되었습니다.
    • 네트워크 요청 재시도 로직이 NetworkError.retryTrigger 조건에 맞게 개선되었습니다.
  • 기타

    • 일부 파일에 모듈 임포트가 추가되어 의존성이 명확해졌습니다.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jul 8, 2025

## Walkthrough

이 변경사항은 네트워크 및 DI 관련 모듈에서 기존의 do-catch 기반 동기 에러 처리 방식을 Combine의 AnyPublisher 기반 비동기 스트림으로 리팩토링하고, Autowired의 사용 시점에 대한 가이드 및 예시를 문서화하는 작업을 포함합니다. 일부 불필요한 에러 타입이 제거되고, 네트워크 에러 타입이 통일되었습니다.

## Changes

| 파일/그룹 | 변경 요약 |
|---|---|
| BKCore/Sources/DiContainer/Autowired.swift | Autowired 사용 예시 및 가이드 문서화 변경(구현/인터페이스 변경 없음) |
| BKData/Sources/Error/NetworkError.swift | NetworkError enum에 retryTrigger, unknown 케이스 추가 |
| BKData/Sources/Interface/Network/NetworkProvider.swift<br>BKNetwork/Sources/Provider/DefaultNetworkProvider.swift<br>BKNetwork/Sources/Provider/OAuthNetworkProvider.swift | request 메서드 반환 타입을 AnyPublisher<T, Error> → AnyPublisher<T, NetworkError>로 변경 및 에러 처리 방식 통일 |
| BKData/Sources/Interface/Network/URLBuilding.swift<br>BKNetwork/Sources/Helper/URLBuilder.swift | makeURL 메서드를 동기/throwing → AnyPublisher<URL, NetworkError>로 변경 |
| BKNetwork/Sources/Extension/RequestTarget+.swift | makeURLRequest 메서드를 동기/throwing → AnyPublisher<URLRequest, NetworkError>로 변경, accessToken 파라미터 제거 |
| BKNetwork/Sources/Helper/AuthInterceptor.swift | RetryTrigger 에러 사용 → NetworkError.retryTrigger 사용으로 변경 |
| BKNetwork/Sources/Error/RetryTrigger.swift | RetryTrigger 에러 타입 파일 삭제 |
| BKNetwork/Sources/Extension/Publisher+.swift | Publisher extension이 Failure == NetworkError일 때만 동작하도록 제약 추가 |
| BKNetwork/Sources/Extension/HTTPURLResponse+.swift<br>BKNetwork/Sources/Extension/URLRequest+.swift | BKData 모듈 import 추가(기능 변화 없음) |

## Sequence Diagram(s)

```mermaid
sequenceDiagram
    participant ViewModel
    participant NetworkProvider
    participant RequestTarget
    participant URLBuilder
    participant Network
    participant Decoder

    ViewModel->>NetworkProvider: request(target, type)
    NetworkProvider->>RequestTarget: makeURLRequest()
    RequestTarget->>URLBuilder: makeURL(target)
    URLBuilder-->>RequestTarget: AnyPublisher<URL, NetworkError>
    RequestTarget-->>NetworkProvider: AnyPublisher<URLRequest, NetworkError>
    NetworkProvider->>Network: URLSession.dataTaskPublisher
    Network-->>NetworkProvider: Data, Response
    NetworkProvider->>Decoder: decode(Data)
    Decoder-->>NetworkProvider: Decoded Object / Error
    NetworkProvider-->>ViewModel: AnyPublisher<T, NetworkError>

Assessment against linked issues

Objective Addressed Explanation
do ~ catch 제거 및 AnyPublisher 기반 비동기 처리로 리팩토링 (#57)
Publisher의 debugger 추가 등 간단한 디버깅 지원 (#57)
Autowired 타이밍(사용 시점) 조정 및 문서화 (#57)

Poem

/(⁎˃ᆺ˂)/
네트워크 흐름이 Publisher로 변신했네,
do-catch는 안녕, 스트림이 반겨주네!
Autowired도 깔끔하게 가이드 추가,
에러 타입 통일로 마음이 후련하다.
오늘도 깔끔한 코드밭에서
토끼는 신나게 뛰논다! 🥕✨


<!-- walkthrough_end -->


---

<details>
<summary>📜 Recent review details</summary>

**Configuration used: .coderabbit.yaml**
**Review profile: CHILL**
**Plan: Pro**


<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between ae895e58db16c01c963370764e48ba195b5a5f4e and a35d1f61901e65f40226b127ae1ff67a08c16613.

</details>

<details>
<summary>📒 Files selected for processing (1)</summary>

* `src/Projects/BKNetwork/Sources/Provider/OAuthNetworkProvider.swift` (2 hunks)

</details>

<details>
<summary>🚧 Files skipped from review as they are similar to previous changes (1)</summary>

* src/Projects/BKNetwork/Sources/Provider/OAuthNetworkProvider.swift

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)</summary>

* GitHub Check: build

</details>

</details>
<!-- internal state start -->


<!-- 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 -->

<!-- internal state end -->
<!-- finishing_touch_checkbox_start -->

<details open="true">
<summary>✨ Finishing Touches</summary>

- [ ] <!-- {"checkboxId": "7962f53c-55bc-4827-bfbf-6a18da830691"} --> 📝 Generate Docstrings
<details open="true">
<summary>🧪 Generate unit tests</summary>

- [ ] <!-- {"checkboxId": "f47ac10b-58cc-4372-a567-0e02b2c3d479", "radioGroupId": "utg-output-choice-group-unknown_comment_id"} -->   Create PR with unit tests
- [ ] <!-- {"checkboxId": "07f1e7d6-8a8e-4e23-9900-8731c2c87f58", "radioGroupId": "utg-output-choice-group-unknown_comment_id"} -->   Post copyable unit tests in a comment
- [ ] <!-- {"checkboxId": "6ba7b810-9dad-11d1-80b4-00c04fd430c8", "radioGroupId": "utg-output-choice-group-unknown_comment_id"} -->   Commit unit tests in branch `BOOK-107-refactor/#57`

</details>

</details>

<!-- finishing_touch_checkbox_end -->
<!-- tips_start -->

---

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.

<details>
<summary>❤️ Share</summary>

- [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai)
- [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai)
- [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai)
- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code)

</details>

<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=YAPP-Github/Reed-iOS&utm_content=60):

- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
  - `I pushed a fix in commit <commit_id>, please review it.`
  - `Explain this complex logic.`
  - `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 explain this code block.`
  -	`@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 explain its main purpose.`
  - `@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.`

### Support

Need help? Create a ticket on our [support page](https://www.coderabbit.ai/contact-us/support) for assistance with any issues or questions.

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](https://docs.coderabbit.ai/finishing-touches/docstrings) for this PR.
- `@coderabbitai generate sequence diagram` to generate a sequence diagram of the changes in this PR.
- `@coderabbitai auto-generate unit tests` to generate unit tests for this PR.
- `@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` or `@coderabbitai 요약` 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.

### Documentation and Community

- Visit our [Documentation](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->

Copy link
Copy Markdown

@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 (3)
src/Projects/BKNetwork/Sources/Extension/RequestTarget+.swift (1)

12-25: 인증 로직이 인터셉터로 이동한 것을 확인했습니다.

accessToken 파라미터와 addAuthorization 호출이 제거되었지만, OAuthNetworkProvider에서 AuthInterceptor.adapt()를 통해 처리되는 것을 확인했습니다. 이는 관심사의 분리 측면에서 더 나은 설계입니다.

다만, 구현을 더 간단하게 개선할 수 있습니다:

-        Just(())
-            .setFailureType(to: NetworkError.self)
-            .tryMap { _ in
+        Deferred {
+            Future<URLRequest, NetworkError> { promise in
+                do {
                 var request = try URLRequest(baseURL + path, query: query)
                 request.makeURLHeaders(headers)
                 request.httpMethod = method.rawValue
                 request.cachePolicy = .reloadIgnoringLocalCacheData
                 if let body { request.setBody(body) }
-                return request
+                    promise(.success(request))
+                } catch {
+                    promise(.failure(error as? NetworkError ?? NetworkError.invalidURL))
+                }
             }
-            .mapError { error in error as? NetworkError ?? NetworkError.invalidURL }
+        }
             .eraseToAnyPublisher()
src/Projects/BKNetwork/Sources/Provider/DefaultNetworkProvider.swift (2)

30-30: 프로덕션 환경에서 debugError 사용 시 주의가 필요합니다.

debugError는 개발 중에는 유용하지만, 프로덕션에서는 민감한 정보가 로그에 노출될 수 있습니다. 조건부 컴파일을 사용하여 디버그 빌드에서만 활성화하는 것을 고려해보세요.

-                    .debugError("Decoding Failed", logger: AppLogger.network)
+                    #if DEBUG
+                    .debugError("Decoding Failed", logger: AppLogger.network)
+                    #endif

31-31: 에러 매핑 시 더 구체적인 에러 타입을 고려해보세요.

현재 모든 비-NetworkError를 .invalidResponse로 매핑하고 있는데, 이로 인해 디코딩 에러나 다른 유용한 에러 정보가 손실될 수 있습니다.

-                    .mapError { $0 as? NetworkError ?? .invalidResponse }
+                    .mapError { error in
+                        if let networkError = error as? NetworkError {
+                            return networkError
+                        } else if error is DecodingError {
+                            return NetworkError.decodingFailed
+                        } else {
+                            return NetworkError.unknown
+                        }
+                    }

참고: NetworkErrordecodingFailed 케이스가 없다면 추가를 고려해보세요.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b0c41cd and ae895e5.

📒 Files selected for processing (13)
  • src/Projects/BKCore/Sources/DiContainer/Autowired.swift (1 hunks)
  • src/Projects/BKData/Sources/Error/NetworkError.swift (1 hunks)
  • src/Projects/BKData/Sources/Interface/Network/NetworkProvider.swift (1 hunks)
  • src/Projects/BKData/Sources/Interface/Network/URLBuilding.swift (1 hunks)
  • src/Projects/BKNetwork/Sources/Error/RetryTrigger.swift (0 hunks)
  • src/Projects/BKNetwork/Sources/Extension/HTTPURLResponse+.swift (1 hunks)
  • src/Projects/BKNetwork/Sources/Extension/Publisher+.swift (1 hunks)
  • src/Projects/BKNetwork/Sources/Extension/RequestTarget+.swift (1 hunks)
  • src/Projects/BKNetwork/Sources/Extension/URLRequest+.swift (1 hunks)
  • src/Projects/BKNetwork/Sources/Helper/AuthInterceptor.swift (1 hunks)
  • src/Projects/BKNetwork/Sources/Helper/URLBuilder.swift (1 hunks)
  • src/Projects/BKNetwork/Sources/Provider/DefaultNetworkProvider.swift (1 hunks)
  • src/Projects/BKNetwork/Sources/Provider/OAuthNetworkProvider.swift (2 hunks)
💤 Files with no reviewable changes (1)
  • src/Projects/BKNetwork/Sources/Error/RetryTrigger.swift
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: clxxrlove
PR: YAPP-Github/Reed-iOS#56
File: src/Projects/BKPresentation/Sources/Constant/PresentationKeys.swift:3-5
Timestamp: 2025-07-07T13:53:13.006Z
Learning: clxxrlove prefers using enum over struct for constants namespace due to better runtime performance, memory layout, and compiler optimizations. Enum prevents instantiation at compile time without needing private init().
🧬 Code Graph Analysis (1)
src/Projects/BKNetwork/Sources/Provider/OAuthNetworkProvider.swift (7)
src/Projects/BKNetwork/Sources/Extension/RequestTarget+.swift (1)
  • makeURLRequest (12-25)
src/Projects/BKNetwork/Sources/Provider/DefaultNetworkProvider.swift (1)
  • request (16-34)
src/Projects/BKNetwork/Sources/Helper/AuthInterceptor.swift (2)
  • adapt (13-19)
  • retryIfNeeded (21-31)
src/Projects/BKNetwork/Sources/Extension/Optional+.swift (1)
  • orThrow (6-11)
src/Projects/BKNetwork/Sources/Extension/HTTPURLResponse+.swift (1)
  • validate (9-27)
src/Projects/BKNetwork/Sources/Extension/Data+.swift (1)
  • decode (6-10)
src/Projects/BKNetwork/Sources/Extension/Publisher+.swift (1)
  • retryIf (7-20)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build
🔇 Additional comments (13)
src/Projects/BKCore/Sources/DiContainer/Autowired.swift (2)

10-14: 예시 확장 추가 👍
ViewModel에서 네임드 의존성을 주입하는 구체적인 예시가 추가되어 @Autowired 사용법이 한층 명확해졌습니다. 실제 코드에서도 동일한 패턴을 유지하면 신규 합류자에게 큰 도움이 될 것 같습니다.


16-20: 가이드 문구의 논리적 모순 수정 제안
17 ~ 19행에서 “ViewModel을 제외한 모든 계층에서는 @Autowired”, 이어서 “Data, Domain 계층은 생성자 주입을 사용”이라고 안내하고 있어 혼동을 줄 수 있습니다. ViewModel 사용 여부가 앞뒤에서 상반되므로 표현을 하나로 통일해 주세요.
[ suggest_nitpick ]

가능한 수정 예시:

-/// ViewModel을 제외한 모든 계층에서는 `Assembly`에서 `@Autowired`로 주입합니다.
-/// Data, Domain 등의 계층에서는 테스트가 필수불가결적이므로 생성자 주입을 통한 DI를 활용해주세요.
-/// 단, ViewModel의 경우에는 편리하게 `@Autowired` 주입을 추천드립니다.
+/// • Data, Domain 등 테스트 중심 계층: **생성자 주입** 권장  
+/// • ViewModel 및 Presentation 계층: 불필요한 보일러플레이트를 줄이기 위해 **`@Autowired` 사용** 권장  
+/// • 기타 계층: 상황에 따라 `@Autowired` 또는 생성자 주입 선택
src/Projects/BKNetwork/Sources/Extension/URLRequest+.swift (1)

3-3: 모듈 구조 개선을 위한 적절한 import 추가

NetworkErrorBKData 모듈로 이동함에 따라 필요한 import를 추가한 것이 적절합니다.

src/Projects/BKNetwork/Sources/Extension/HTTPURLResponse+.swift (1)

4-4: 네트워크 에러 통합을 위한 일관된 import 추가

NetworkError 타입 사용을 위해 BKData 모듈 import를 추가한 것이 리팩터링 목표와 일치합니다.

src/Projects/BKData/Sources/Error/NetworkError.swift (1)

9-10: 네트워크 에러 처리 통합을 위한 새로운 케이스 추가

retryTriggerunknown 케이스를 추가하여 에러 처리를 통합한 것이 좋습니다. 특히 retryTrigger는 기존 RetryTrigger 구조체를 대체하여 에러 타입을 단일화했습니다.

src/Projects/BKNetwork/Sources/Helper/AuthInterceptor.swift (1)

29-29: 에러 타입 통합을 위한 적절한 변경

RetryTrigger 구조체 대신 NetworkError.retryTrigger를 사용하여 에러 타입을 통일한 것이 리팩터링 목표와 일치합니다.

src/Projects/BKNetwork/Sources/Extension/Publisher+.swift (2)

3-3: NetworkError 타입 사용을 위한 필수 import

NetworkError 타입을 사용하기 위해 BKData 모듈을 import한 것이 적절합니다.


6-6: 타입 안전성 향상을 위한 제네릭 제약 추가

Publisher 확장을 Failure == NetworkError로 제한하여 네트워크 에러 처리의 타입 안전성을 높인 것이 좋습니다. 네트워크 레이어의 에러 처리가 더욱 명확해졌습니다.

src/Projects/BKData/Sources/Interface/Network/NetworkProvider.swift (1)

7-10: 에러 타입을 구체화한 좋은 변경입니다!

Error에서 NetworkError로 타입을 좁힌 것은 타입 안전성을 높이고 에러 처리를 더 명확하게 만듭니다.

src/Projects/BKData/Sources/Interface/Network/URLBuilding.swift (1)

3-8: Combine 기반 비동기 처리로의 일관된 전환입니다.

동기식 throwing 함수에서 AnyPublisher를 반환하는 비동기 함수로 변경한 것은 네트워크 레이어 전체의 리팩토링 방향과 일치합니다.

src/Projects/BKNetwork/Sources/Helper/URLBuilder.swift (1)

8-19: Publisher 체인을 활용한 깔끔한 구현입니다.

makeURLRequest()의 결과에서 URL을 추출하고, 적절한 에러 처리를 수행하는 구현이 잘 되어 있습니다.

src/Projects/BKNetwork/Sources/Provider/OAuthNetworkProvider.swift (1)

3-3: BKCore 임포트가 추가되었습니다.

BKCore 모듈이 필요한 이유를 확인해주세요. 사용되지 않는다면 제거하는 것이 좋습니다.

src/Projects/BKNetwork/Sources/Provider/DefaultNetworkProvider.swift (1)

17-34: Combine 기반 비동기 처리로의 리팩토링이 잘 구현되었습니다!

반환 타입을 NetworkError로 구체화하여 타입 안전성을 향상시키고, reactive chain을 통해 비동기 처리를 깔끔하게 구현한 점이 좋습니다.

Comment thread src/Projects/BKNetwork/Sources/Provider/OAuthNetworkProvider.swift
Copy link
Copy Markdown
Member

@doyeonk429 doyeonk429 left a comment

Choose a reason for hiding this comment

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

👍👍

@clxxrlove clxxrlove merged commit 17fca87 into develop Jul 8, 2025
3 checks passed
@clxxrlove clxxrlove deleted the BOOK-107-refactor/#57 branch July 8, 2025 10:18
@coderabbitai coderabbitai Bot mentioned this pull request Jul 21, 2025
10 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BOOK-107/refactor] 일부 모듈 리팩토링

2 participants