Skip to content

[Feat] 네트워킹 로깅 플러그인 구현#34

Merged
taipaise merged 2 commits into
developfrom
feat/network-logging
Aug 4, 2025
Merged

[Feat] 네트워킹 로깅 플러그인 구현#34
taipaise merged 2 commits into
developfrom
feat/network-logging

Conversation

@taipaise
Copy link
Copy Markdown
Collaborator

@taipaise taipaise commented Aug 3, 2025

🌁 Background

  • 이전 [Feat] NetworkService 플러그인 구현 #30 에서 로깅 로직을 꼬아버린 바람에 네트워크 요청/응답을 확인하는데 어려움이 있었습니다.
  • 때문에 플러그인을 통해 요청/응답 값을 확인해볼 수 있도록 구현했습니다.
  • 다만 response body의 경우, 값이 너무 길어지는 경우가 있었습니다. 오히려 가독성이 떨어진다고 느껴져서 server에서 보내는 code와 message 값만 콘솔에 찍도록 구현했습니다

📱 Screenshot

image - request는 헤더를 찍기 때문에 토큰 값이 포함되어 있어 사진 첨부하지 않았습니다. (어차피 만료된 토큰이지만 그래도 올리지 않기로 함~!)

👩‍💻 Contents

  • 네트워크 로깅 플러그인 구현

Summary by CodeRabbit

  • 신규 기능

    • 네트워크 요청 및 응답에 대한 상세 로그를 제공하는 BitnagilLoggingPlugin이 추가되었습니다.
  • 리팩터링

    • 기존 네트워크 서비스의 수동 로그 코드가 제거되고, 로그 처리가 플러그인으로 위임되었습니다.

@taipaise taipaise requested a review from choijungp August 3, 2025 14:13
@taipaise taipaise self-assigned this Aug 3, 2025
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Aug 3, 2025

Walkthrough

NetworkService에 새로운 플러그인 BitnagilLoggingPlugin이 추가되었습니다. 기존에 performRequest 메서드 내에서 수동으로 처리하던 네트워크 요청 및 응답에 대한 로깅 코드가 삭제되고, 그 역할이 새 플러그인으로 위임되었습니다. BitnagilLoggingPlugin은 네트워크 요청과 응답의 주요 정보를 구조적으로 로깅합니다.

Changes

Cohort / File(s) Change Summary
NetworkService 플러그인 및 로깅 구조 변경
Projects/DataSource/Sources/NetworkService/NetworkService.swift
BitnagilLoggingPlugin을 플러그인 배열에 추가. 기존 네트워크 요청/응답 관련 수동 로깅 코드 삭제 및 guard문 포맷 개선.
BitnagilLoggingPlugin 신설
Projects/DataSource/Sources/NetworkService/Plugin/BitnagilLoggingPlugin.swift
NetworkPlugin 프로토콜을 준수하는 새 플러그인 BitnagilLoggingPlugin 추가. 요청/응답의 상세 정보를 구조적으로 로깅.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant NetworkService
    participant BitnagilLoggingPlugin
    participant Server

    Client->>NetworkService: performRequest(endpoint)
    NetworkService->>BitnagilLoggingPlugin: willSend(request, endpoint)
    BitnagilLoggingPlugin-->>NetworkService: (로깅 후) request 반환
    NetworkService->>Server: HTTP 요청 전송
    Server-->>NetworkService: HTTP 응답 수신
    NetworkService->>BitnagilLoggingPlugin: didReceive(response, data, endpoint)
    BitnagilLoggingPlugin-->>NetworkService: (로깅 후) 제어 반환
    NetworkService-->>Client: 결과 반환
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Possibly related PRs

  • [Feat] NetworkService 플러그인 구현 #30: 기존 플러그인 기반 네트워크 구조에 새로운 로깅 플러그인을 추가하며, 동일한 NetworkService 클래스와 플러그인 시스템을 직접 확장하므로 코드 레벨에서 밀접하게 관련됨.

Poem

🐇
로그는 이제 플러그인에 맡기고
네트워크 흐름은 한결 깔끔해졌네!
요청과 응답, 꼼꼼히 기록하며
Bitnagil의 귀가 더 밝아졌지.
토끼는 오늘도 로그를 모으며
코드 숲을 뛰어다닌다—깡총!

Note

⚡️ Unit Test Generation is now available in beta!

Learn more here, or try it out under "Finishing Touches" below.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/network-logging

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
🪧 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.
    • 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 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 for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai 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 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.

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 (7)
Projects/DataSource/Sources/NetworkService/Plugin/BitnagilLoggingPlugin.swift (7)

49-55: JSON 파싱 오류 처리 개선을 고려해보세요.

현재 JSON 파싱 실패 시 빈 문자열로 처리하고 있는데, 파싱 실패 이유를 로깅하면 디버깅에 도움이 될 수 있습니다.

-        if
-            let data = data,
-            let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any]
-        {
-            code = json["code"] as? String ?? ""
-            message = json["message"] as? String ?? ""
-        }
+        if let data = data {
+            do {
+                if let json = try JSONSerialization.jsonObject(with: data) as? [String: Any] {
+                    code = json["code"] as? String ?? ""
+                    message = json["message"] as? String ?? ""
+                }
+            } catch {
+                BitnagilLogger.log(logType: .debug, message: "JSON 파싱 실패: \(error.localizedDescription)")
+            }
+        }

11-11: 접근 제어자 추가를 고려해보세요.

구조체가 NetworkService 내부에서만 사용된다면 internal 또는 private 접근 제어자를 명시하여 모듈 경계를 명확히 하는 것을 고려해보세요.


17-21: HTTP 바디 처리 로직 개선

현재 구현은 적절하지만 몇 가지 개선점이 있습니다:

  1. 대용량 바디 데이터에 대한 처리가 없습니다
  2. 한국어 메시지 사용이 일관적이지 않습니다

다음과 같이 개선할 수 있습니다:

        let body: String
        if let bodyData = request.httpBody {
-            body = String(data: bodyData, encoding: .utf8) ?? "디코딩 실패"
+            if bodyData.count > 1024 {
+                body = "용량이 큰 데이터 (\(bodyData.count) bytes)"
+            } else {
+                body = String(data: bodyData, encoding: .utf8) ?? "디코딩 실패"
+            }
        } else {
            body = "내용 없음"
        }

39-42: HTTPURLResponse 타입캐스팅 실패 처리

타입캐스팅 실패에 대한 에러 로깅이 적절합니다. 다만 실제 response 타입 정보를 포함하면 디버깅에 더 도움이 될 것 같습니다.

-            BitnagilLogger.log(logType: .error, message: "🚨\(urlString)에 대한 response는 HTTPResponse가 아닙니다.🚨")
+            BitnagilLogger.log(logType: .error, message: "🚨\(urlString)에 대한 response는 HTTPResponse가 아닙니다. 실제 타입: \(type(of: response))🚨")

46-55: JSON 파싱 에러 처리 개선

현재 try?를 사용하여 JSON 파싱 실패를 조용히 무시하고 있습니다. 파싱 실패 시에도 로그에 이를 명시하면 디버깅에 도움이 될 것입니다.

        // code/message 추출
        var code: String = ""
        var message: String = ""
        if let data = data {
-            if let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any] {
-                code = json["code"] as? String ?? ""
-                message = json["message"] as? String ?? ""
+            do {
+                if let json = try JSONSerialization.jsonObject(with: data) as? [String: Any] {
+                    code = json["code"] as? String ?? ""
+                    message = json["message"] as? String ?? ""
+                }
+            } catch {
+                BitnagilLogger.log(logType: .debug, message: "JSON 파싱 실패: \(error.localizedDescription)")
            }
        }

11-11: 구조체 접근 제어자 고려사항

현재 BitnagilLoggingPlugininternal 접근 수준으로 선언되어 있습니다. 다른 모듈에서 이 플러그인을 사용할 가능성이 있다면 public 선언을 고려해보세요.


49-55: JSON 파싱 로직 개선 제안

현재 JSON 파싱이 실패하면 빈 문자열로 처리되는데, 디버깅 목적을 고려하면 파싱 실패 이유를 로그에 남기는 것이 더 유용할 수 있습니다.

다음과 같이 개선할 수 있습니다:

-        if
-            let data = data,
-            let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any]
-        {
-            code = json["code"] as? String ?? ""
-            message = json["message"] as? String ?? ""
-        }
+        if let data = data {
+            do {
+                let json = try JSONSerialization.jsonObject(with: data) as? [String: Any]
+                code = json?["code"] as? String ?? ""
+                message = json?["message"] as? String ?? ""
+            } catch {
+                code = "JSON 파싱 실패"
+                message = error.localizedDescription
+            }
+        }
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between a5eff16 and a68a8b0.

📒 Files selected for processing (2)
  • Projects/DataSource/Sources/NetworkService/NetworkService.swift (2 hunks)
  • Projects/DataSource/Sources/NetworkService/Plugin/BitnagilLoggingPlugin.swift (1 hunks)
👮 Files not reviewed due to content moderation or server errors (2)
  • Projects/DataSource/Sources/NetworkService/Plugin/BitnagilLoggingPlugin.swift
  • Projects/DataSource/Sources/NetworkService/NetworkService.swift
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: choijungp
PR: YAPP-Github/Bitnagil-iOS#30
File: Projects/DataSource/Sources/NetworkService/Plugin/RefreshTokenPlugin.swift:42-43
Timestamp: 2025-07-30T03:56:18.617Z
Learning: choijungp는 현재 테스트 단계에서 RefreshTokenPlugin의 토큰 갱신 로직 디버깅을 위해 액세스 토큰과 리프레시 토큰의 실제 값을 로그에 기록하는 것을 선호함.
🔇 Additional comments (17)
Projects/DataSource/Sources/NetworkService/Plugin/BitnagilLoggingPlugin.swift (8)

11-11: 구조체 선언이 적절합니다.

NetworkPlugin 프로토콜을 올바르게 구현하고 있습니다.


17-21: 바디 데이터 처리 로직이 적절합니다.

nil 체크와 UTF-8 디코딩 실패에 대한 처리가 잘 되어 있습니다.


36-67: 응답 로깅 구현이 효율적입니다.

HTTPURLResponse 타입 체크와 JSON 파싱을 통한 구조적 로깅이 잘 구현되어 있습니다. 전체 응답 바디 대신 필요한 필드만 추출하여 로그 가독성을 높인 점이 좋습니다.


15-15: 헤더 로깅 시 보안 고려사항

헤더에는 토큰 정보가 포함되어 있어 민감한 정보가 로그에 노출될 수 있습니다. 검색된 학습 내용에 따르면 현재 테스트 단계에서는 토큰 값 로깅을 선호하지만, 프로덕션 환경에서는 보안 위험이 있을 수 있습니다.

프로덕션 배포 전에 민감한 헤더 값(Authorization, X-API-Key 등)을 마스킹하는 로직 추가를 고려해보세요:

-        let headers = request.allHTTPHeaderFields ?? [:]
+        let headers = sanitizeHeaders(request.allHTTPHeaderFields ?? [:])

그리고 헤더 새니타이제이션 함수를 추가:

private func sanitizeHeaders(_ headers: [String: String]) -> [String: String] {
    let sensitiveKeys = ["Authorization", "X-API-Key", "Cookie"]
    return headers.mapValues { key, value in
        sensitiveKeys.contains(key) ? "***" : value
    }
}

57-66: 응답 로깅 구조가 잘 설계되었습니다.

요청 URL, 상태 코드, 그리고 서버의 code/message만 로깅하여 가독성을 유지하면서도 필요한 정보를 제공하는 균형 잡힌 접근 방식입니다. PR 목표에 부합합니다.


12-34: 요청 로깅 구현이 잘 되어 있습니다

URLRequest의 주요 정보들(URL, HTTP 메서드, 헤더, 바디)을 모두 포함하여 디버깅에 유용한 로그를 제공하고 있습니다. 바디 디코딩 실패 시 적절한 대체 메시지도 제공합니다.


17-21: 토큰 정보 로깅에 대한 보안 고려사항

헤더에 포함된 토큰 정보가 로그에 기록됩니다. 이전 학습 내용에 따르면 현재 테스트 단계에서는 디버깅을 위해 실제 토큰 값 로깅을 선호하지만, 프로덕션 환경에서는 보안상 토큰 정보를 마스킹하는 것을 고려해야 합니다.

프로덕션 배포 전에 민감한 정보 로깅에 대한 정책을 확인하고, 필요시 토큰 마스킹 기능 추가를 검토해보세요.


36-67: 응답 로깅 구현이 적절합니다

HTTPURLResponse 타입 체크, 상태 코드 추출, JSON에서 code/message 필드 파싱이 안전하게 구현되어 있습니다. JSON 파싱 실패 시에도 빈 문자열로 처리하여 로그가 중단되지 않도록 했습니다.

Projects/DataSource/Sources/NetworkService/NetworkService.swift (9)

21-22: 플러그인 통합이 올바르게 구현되었습니다.

BitnagilLoggingPlugin이 적절한 순서로 plugins 배열에 추가되었습니다. 로깅은 일반적으로 다른 플러그인들의 작업 완료 후에 수행되는 것이 좋으므로 배열의 마지막에 위치시킨 것이 적절합니다.


81-81: 코드 포맷팅 개선이 좋습니다.

guard 문을 한 줄로 정리하여 가독성이 향상되었습니다.


86-86: 일관된 코드 스타일이 적용되었습니다.

다른 guard 문과 동일한 스타일로 통일되어 코드 일관성이 향상되었습니다.


21-22: 로깅 플러그인 통합이 올바르게 구현되었습니다.

BitnagilLoggingPlugin이 적절한 위치에 추가되어 다른 플러그인들과 함께 작동할 수 있도록 구성되었습니다. 플러그인 순서도 논리적으로 배치되어 있습니다 (토큰 주입 → 토큰 갱신 → 재시도 → 로깅).


81-81: Guard문 포맷팅 개선

한 줄로 정리된 guard문이 더 간결하고 읽기 쉽습니다.


86-86: 일관된 포맷팅 스타일

다른 guard문과 일관된 스타일로 정리되어 코드 가독성이 향상되었습니다.


21-22: 로깅 플러그인 통합이 적절합니다

BitnagilLoggingPlugin이 플러그인 배열에 올바르게 추가되어 네트워크 요청/응답 로깅을 담당하게 되었습니다. 플러그인 패턴을 통해 관심사가 잘 분리되었습니다.


81-81: Guard 문 포맷팅 개선

Guard 문이 더 간결하게 포맷팅되어 가독성이 향상되었습니다.

Also applies to: 86-86


21-22: 수동 로깅 코드 완전 제거 확인

  • Projects/DataSource/Sources/NetworkService/NetworkService.swift에서 BitnagilLogger 호출이 없습니다.
  • 상태 코드 관련 수동 로깅(status code 로그)도 모두 제거되었습니다.

모든 네트워크 로깅이 BitnagilLoggingPlugin으로 일원화되어 중복이 해소되었으므로, 해당 리팩토링은 적절하게 적용되었습니다.

Comment on lines +12 to +34
func willSend(request: URLRequest, endpoint: Endpoint) async throws -> URLRequest {
let urlString = request.url?.absoluteString ?? ""
let method = request.httpMethod ?? ""
let headers = request.allHTTPHeaderFields ?? [:]
let body: String
if let bodyData = request.httpBody {
body = String(data: bodyData, encoding: .utf8) ?? "디코딩 실패"
} else {
body = "내용 없음"
}

BitnagilLogger.log(
logType: .debug,
message: """
REQUEST➡️
- URL: \(urlString)
- Method: \(method)
- Headers: \(headers)
- Body: \(body)
"""
)
return request
}
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot Aug 3, 2025

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

보안 민감 정보 로깅에 대한 주의가 필요합니다.

현재 코드는 모든 헤더 정보를 로깅하고 있어 토큰과 같은 민감한 정보가 노출될 수 있습니다. 검색된 학습 내용에 따르면 choijungp님이 디버깅 목적으로 토큰 값 로깅을 선호하신다고 하지만, 프로덕션 환경에서는 보안상 위험할 수 있습니다.

다음과 같이 민감한 헤더를 마스킹하는 방식을 고려해보세요:

-        let headers = request.allHTTPHeaderFields ?? [:]
+        let sensitiveHeaders = ["Authorization", "X-Access-Token", "X-Refresh-Token"]
+        var headers = request.allHTTPHeaderFields ?? [:]
+        for key in sensitiveHeaders {
+            if headers[key] != nil {
+                headers[key] = "***MASKED***"
+            }
+        }

또는 디버그 빌드에서만 전체 헤더를 로깅하도록 할 수 있습니다:

+        #if DEBUG
         let headers = request.allHTTPHeaderFields ?? [:]
+        #else
+        var headers = request.allHTTPHeaderFields ?? [:]
+        let sensitiveHeaders = ["Authorization", "X-Access-Token", "X-Refresh-Token"]
+        for key in sensitiveHeaders {
+            if headers[key] != nil {
+                headers[key] = "***MASKED***"
+            }
+        }
+        #endif
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
func willSend(request: URLRequest, endpoint: Endpoint) async throws -> URLRequest {
let urlString = request.url?.absoluteString ?? ""
let method = request.httpMethod ?? ""
let headers = request.allHTTPHeaderFields ?? [:]
let body: String
if let bodyData = request.httpBody {
body = String(data: bodyData, encoding: .utf8) ?? "디코딩 실패"
} else {
body = "내용 없음"
}
BitnagilLogger.log(
logType: .debug,
message: """
REQUEST➡️
- URL: \(urlString)
- Method: \(method)
- Headers: \(headers)
- Body: \(body)
"""
)
return request
}
func willSend(request: URLRequest, endpoint: Endpoint) async throws -> URLRequest {
let urlString = request.url?.absoluteString ?? ""
let method = request.httpMethod ?? ""
#if DEBUG
// In debug builds, log headers unmasked for easier debugging
let headers = request.allHTTPHeaderFields ?? [:]
#else
// In non-debug builds, mask sensitive header values
var headers = request.allHTTPHeaderFields ?? [:]
let sensitiveHeaders = ["Authorization", "X-Access-Token", "X-Refresh-Token"]
for key in sensitiveHeaders {
if headers[key] != nil {
headers[key] = "***MASKED***"
}
}
#endif
let body: String
if let bodyData = request.httpBody {
body = String(data: bodyData, encoding: .utf8) ?? "디코딩 실패"
} else {
body = "내용 없음"
}
BitnagilLogger.log(
logType: .debug,
message: """
REQUEST➡️
- URL: \(urlString)
- Method: \(method)
- Headers: \(headers)
- Body: \(body)
"""
)
return request
}
🤖 Prompt for AI Agents
In Projects/DataSource/Sources/NetworkService/Plugin/BitnagilLoggingPlugin.swift
around lines 12 to 34, the current logging of all HTTP headers may expose
sensitive information like tokens. To fix this, modify the logging logic to mask
sensitive headers such as Authorization by replacing their values with a
placeholder before logging. Alternatively, restrict full header logging to debug
builds only by using conditional compilation flags, ensuring sensitive data is
not logged in production environments.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

OSLogger의 log level이 debug라 release 환경에서는 로그가 찍히지 않는다 생각했습니다. 추후 확인해보고 잘못된 지식이었다면 조치하도록 하겠습니다.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧩 Analysis chain

🌐 Web query:

OSLogger debug level logs in iOS release builds vs debug builds behavior

💡 Result:

In iOS, OSLogger (using the OSLog framework) supports multiple log levels, including debug, info, and error. The key behavior difference is that debug-level logs generated by OSLogger are visible in Debug builds but are suppressed in Release builds by default. This design helps prevent leaking sensitive or verbose debug information in production and reduces performance and storage overhead[1][3][7].

Supporting Details:

  • Debug Logs in Debug Builds:
    Debug logs (e.g., Logger().debug("Debug log")) are fully visible when running Debug builds, such as in the Xcode debugger or Console app, provided filtering options for log levels are enabled[1][7]. This is intended for development and troubleshooting during active coding.

  • Debug Logs in Release Builds:
    In Release builds (used for App Store distribution and TestFlight), debug-level logs are not emitted or are filtered out by the unified logging system. This means you generally cannot see debug-level output from OSLogger in production builds, even if you search directly for them in the Console on a device[1][3][7].

    • Apple’s official logging system intentionally suppresses both debug and trace messages from release builds to avoid unnecessary performance impact, storage use, and potential privacy issues[1][3].
    • Other log levels (e.g., error, fault) do remain visible in Release builds, as these are intended for significant events and errors that should be monitored in production[1][7].
  • Best Practices and Rationale:

    • Custom logging wrappers sometimes use preprocessor flags (like #if DEBUG) to allow more verbose logging in development and automatically silence or reduce log output in production[3][4].
    • Comprehensive logging at debug level in production isn't supported or recommended, both for privacy and efficiency reasons[1][3].
    • If you need to capture additional logs in production, you must log at the info, error, or higher levels, depending on severity. Alternatively, you may create a custom build configuration, but this is typically discouraged unless necessary for debugging specific production issues[2][4].

Summary Table:

Log Level Debug Build Release Build
debug/trace Visible Not visible
info Visible Visible
error/fault Visible Visible

References:

If you require debug-level log information in production for troubleshooting, consider elevating affected log statements to the info or error level (temporarily), or, as a last resort, implement a custom logging mechanism with explicit configuration to ensure it does not violate user privacy or App Store requirements[2][3][4].

Citations:


@taipaise 맞습니다! 웹 검색 결과 확인해보니 당신의 이해가 정확합니다.

OSLogger의 debug 레벨 로그는 실제로 Release 빌드에서 자동으로 억제됩니다:

  • Debug 빌드: debug 레벨 로그가 표시됨
  • Release 빌드: debug 레벨 로그가 자동으로 필터링되어 표시되지 않음
  • 다른 레벨들 (info, error, fault): Release 빌드에서도 계속 표시됨

이는 Apple이 의도적으로 설계한 보안 및 성능 최적화 기능입니다. 따라서 현재 구현이 보안상 안전하다고 볼 수 있습니다.

다만 코드의 명확성을 위해 이런 동작에 대한 주석을 추가하는 것을 고려해볼 수 있습니다:

// Debug 레벨 로그는 Release 빌드에서 자동으로 억제되어 민감한 정보가 프로덕션에 노출되지 않음
BitnagilLogger.log(
    logType: .debug,
    message: """
            REQUEST➡️
            - URL: \(urlString)
            - Method: \(method)
            - Headers: \(headers)  // Release 빌드에서는 로깅되지 않음
            - Body: \(body)
            """
)

정확한 지식을 가지고 계셨고, 확인해보겠다는 열린 자세도 훌륭합니다! 🐰

  (\   /)
 ( ._. )
o_(")(")  // 배워가는 토끼

🧠 Learnings used
Learnt from: choijungp
PR: YAPP-Github/Bitnagil-iOS#30
File: Projects/DataSource/Sources/NetworkService/Plugin/RefreshTokenPlugin.swift:42-43
Timestamp: 2025-07-30T03:56:18.617Z
Learning: choijungp는 현재 테스트 단계에서 RefreshTokenPlugin의 토큰 갱신 로직 디버깅을 위해 액세스 토큰과 리프레시 토큰의 실제 값을 로그에 기록하는 것을 선호함.

Learnt from: choijungp
PR: YAPP-Github/Bitnagil-iOS#19
File: Projects/Domain/Sources/UseCase/Onboarding/OnboardingUseCase.swift:0-0
Timestamp: 2025-07-16T10:58:30.858Z
Learning: choijungp는 OnboardingUseCase의 convertToDictionary 함수에서 에러 처리 개선을 추후 고민하고 반영할 계획을 가지고 있음.

Copy link
Copy Markdown
Contributor

@choijungp choijungp left a comment

Choose a reason for hiding this comment

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

헐 ...... 완전 띵 덕분에 로그 확인이 훨씬 더 수월할 것 같아요 ... ....
미루기만 했던 일을 띵은 바로 해내시다니 !!!!!!

짱푸루부 !!!!!!!!!!!!!! 👍🏻

@taipaise taipaise merged commit d99a002 into develop Aug 4, 2025
2 checks passed
@taipaise taipaise deleted the feat/network-logging branch August 5, 2025 13:12
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.

2 participants