네트워크 문제 해결

앱에서 생성된 네트워크 트래픽은 기기의 배터리 수명에 상당한 영향을 미칠 수 있습니다. 트래픽을 최적화하려면 트래픽을 측정하고 소스를 식별해야 합니다 네트워크 요청은 사용자 작업, 자체 앱 코드 또는 앱과 통신하는 서버에서 직접 발생할 수 있습니다.

이 주제에서는 네트워크 트래픽을 모니터링하고 분류하는 방법을 설명하고 문제를 식별하고 해결하는 방법을 안내합니다.

네트워크 프로파일러를 사용하여 요청 모니터링

네트워크 프로파일러를 사용하여 애플리케이션의 네트워크 요청을 추적할 수 있습니다. 앱에서 데이터를 전송하는 방법과 시기를 모니터링하고 기본 코드를 적절하게 최적화할 수 있습니다.



그림 1. 네트워크 트래픽 추적 네트워크 트래픽 패턴에 따르면 요청을 미리 가져오거나 업로드를 번들로 묶으면 효율성이 크게 향상될 수 있습니다.

데이터 전송 빈도와 각 연결 중에 전송되는 데이터의 양을 모니터링하여 배터리 효율을 높일 수 있는 애플리케이션 영역을 파악할 수 있습니다. 일반적으로 지연 가능한 짧은 급증을 찾습니다.

전송 급증 원인을 더 잘 식별할 수 있도록 Traffic Stats API를 사용하면 특정 스레드 내의 소켓에서 발생하는 데이터 전송에 TrafficStats.setThreadStatsTag()를 사용하여 태그를 지정할 수 있습니다. 이 함수를 호출해도 특정 스레드의 모든 트래픽에 자동으로 태그를 지정하지는 않습니다. 태그를 소켓에 적용해야 합니다.

스레드 태그가 설정되면 TrafficStats.tagSocket()TrafficStats.untagSocket()를 사용하여 개별 소켓에 수동으로 태그를 지정하고 태그를 해제할 수 있습니다. 소켓이 스레드에서 열려 있거나 서버 소켓이 연결을 수락하는 경우에도 태그가 적용됩니다.

여러 스레드가 동일한 소켓에 동시에 액세스할 때는 네트워크 패킷이 전송되거나 수신되었을 때 소켓에 있던 태그를 사용합니다. 이는 버퍼링 및 재전송으로 인해 사용자가 데이터를 쓰거나 읽을 때와 다를 수 있습니다.

예를 들어 다음 코드 샘플과 같이 여러 유형의 네트워크 트래픽을 나타내는 상수를 정의할 수 있습니다.

Kotlin

const val USER_INITIATED = 0x1000
const val APP_INITIATED = 0x2000
const val SERVER_INITIATED = 0x3000

Java

public static final int USER_INITIATED = 0x1000;
public static final int APP_INITIATED = 0x2000;
public static final int SERVER_INITIATED = 0x3000;

그런 다음 이에 따라 네트워크 요청에 태그를 지정할 수 있습니다.

Kotlin

TrafficStats.setThreadStatsTag(USER_INITIATED)
TrafficStats.tagSocket(outputSocket)
// Transfer data using socket
TrafficStats.untagSocket(outputSocket)

Java

TrafficStats.setThreadStatsTag(USER_INITIATED);
TrafficStats.tagSocket(outputSocket);
// Transfer data using socket
TrafficStats.untagSocket(outputSocket);

HttpURLConnection 라이브러리는 현재 TrafficStats.getThreadStatsTag() 값에 따라 소켓에 자동으로 태그를 지정합니다. 또한 라이브러리는 다음 코드 샘플과 같이 연결 유지 풀을 통해 재활용될 때 소켓에 태그를 지정하고 태그를 해제합니다.

Kotlin

class IdentifyTransferSpikeTask {
    @WorkerThread
    fun request(url: String) {
        TrafficStats.setThreadStatsTag(APP_INITIATED)
        // Make network request using HttpURLConnection.connect()
        ...
        TrafficStats.clearThreadStatsTag()
    }
}

Java

public class IdentifyTransferSpikeTask {
    @WorkerThread
    public void request(String url) {
        TrafficStats.setThreadStatsTag(APP_INITIATED);
        // Make network request using HttpURLConnection.connect()
        ...
        TrafficStats.clearThreadStatsTag();
    }
}

네트워크 트래픽 유형 분석

앱에서 생성된 네트워크 트래픽을 살펴볼 때는 트래픽의 소스를 파악하여 적절하게 최적화할 수 있어야 합니다. 앱이 사용자 작업에 응답하는 경우에는 앱에서 생성하는 빈번한 네트워크 활동이 매우 적절할 수 있지만, 앱이 포그라운드에 있지 않거나 기기가 주머니나 지갑에 있다면 전혀 적절하지 않습니다.

사용자가 시작한 트래픽 분석

사용자가 시작한 네트워크 트래픽은 사용자가 앱 내에서 특정 작업을 실행하는 동안 효율적으로 그룹화되거나, 사용자가 앱에 필요한 추가 정보를 요청할 때 고르지 않게 분산될 수 있습니다. 사용자가 시작한 네트워크 트래픽을 분석하는 목적은 시간 경과에 따라 네트워크를 자주 사용하는 패턴을 찾고 요청을 그룹화하여 빈도를 낮추는 것입니다.

사용자 요청은 예측이 불가능하기 때문에 앱에서 이러한 유형의 네트워크 사용을 최적화하기 어렵습니다. 또한 사용자는 앱을 활발히 사용할 때 빠른 응답을 기대하므로 효율성을 높이기 위해 요청을 지연하면 사용자 경험이 저하될 수 있습니다. 일반적으로 사용자가 앱과 직접 상호작용하는 동안에는 효율적인 네트워크 사용보다 사용자에게 빠른 응답을 우선시해야 합니다.

사용자가 시작한 트래픽을 최적화하기 위한 권장사항은 사용자가 시작한 요청 최적화를 참조하세요.

앱에서 시작한 트래픽 분석

앱에서 시작한 네트워크 트래픽은 일반적으로 네트워크 대역폭의 효율적인 사용에 큰 영향을 미칠 수 있는 영역입니다. 앱의 네트워크 활동을 분석할 때 활동이 없는 기간을 찾고 이러한 기간을 늘릴 수 있는지 여부를 판단하세요. 앱에서 일관된 네트워크 액세스 패턴이 보인다면 이 트래픽을 일괄 처리하여 활동 기간 사이에 기기 무선이 저전력 모드로 다시 전환되도록 하세요.

앱에서 시작한 트래픽을 최적화하기 위한 권장사항은 앱에서 시작한 요청 최적화를 참고하세요.

서버에서 시작한 트래픽 분석

또한 앱과 통신하는 서버에서 시작한 네트워크 활동은 일반적으로 네트워크 대역폭의 효율적인 사용에 큰 영향을 미칠 수 있는 영역입니다. Firebase 클라우드 메시징(FCM)은 서버에서 특정 앱 인스턴스로 데이터를 전송하는 데 사용되는 간단한 메커니즘입니다. FCM을 사용하면 서버는 특정 기기에서 실행 중인 앱에 사용 가능한 새 데이터가 있음을 알릴 수 있습니다.

서버에서 시작한 트래픽을 최적화하기 위한 권장사항은 서버에서 시작한 요청 최적화를 참고하세요.

Battery Historian을 사용하여 네트워크 트래픽 효과 시각화

Battery Historian은 일정 기간 동안의 기기 배터리 소모를 시각화하는 도구입니다. 이 도구를 사용하여 네트워크 활동이 배터리 소비에 미치는 영향을 분석할 수 있습니다. 예를 들어 Battery Historian은 앱에서 무선 라디오를 예상보다 더 자주 사용하는지 표시할 수 있습니다. Battery Historian 사용에 관한 자세한 내용은 Batterystats 및 Battery Historian으로 배터리 사용량 프로파일링을 참고하세요.