본문 바로가기

Android

[안드로이드] NetworkOnMainThreadException 발생 원인과 해결 방법

반응형
android.os.NetworkOnMainThreadException

안드로이드 개발 중 아래와 같은 익숙한 에러 메시지를 종종 본적이 있을 것이다.

안드로이드에 익숙한 개발자이더라도 볼수 있는 에러고, 이 예외가 왜 발생하는지, 그리고 어떻게 해결하는지를 구체적으로 정리하도록 하겠다.

1. NetworkOnMainThreadException은 언제 발생할까?

NetworkOnMainThreadException은 네트워크 작업을 메인(UI) 스레드에서 실행할 때 발생한다.
예를 들어 아래와 같이 HttpURLConnection을 onCreate() 안에서 직접 호출하면 바로 이 예외발생한다.

URL url = new URL("https://example.com");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
InputStream in = conn.getInputStream(); // ❌ 예외 발생​

안드로이드 3.0 (Honeycomb, API 11)부터는 메인 스레드에서 네트워크 요청을 엄격하게 금지하고 있기 때문이다.


2. 메인 스레드에서는 왜 네트워크 작업이 금지될까?

메인 스레드는 UI를 처리하는 핵심 스레드이다. 이곳에서 네트워크처럼 시간이 오래 걸릴 수 있는 작업을 하면 화면이 멈추거나 ANR(Application Not Responding) 에러로 이어질 수 있다.

안드로이드는 이런 UI 멈춤 현상을 방지하기 위해, 네트워크 작업이 메인 스레드에서 실행되면 NetworkOnMainThreadException가 발생한다.

3. NetworkOnMainThreadException 해결 방법 3가지

1) Thread 또는 Executor 사용

new Thread(() -> {
    try {
        URL url = new URL("https://example.com");
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        InputStream in = conn.getInputStream();
        // 데이터 처리...
    } catch (Exception e) {
        e.printStackTrace();
    }
}).start();

 

2)  AsyncTask (단, 구버전에서만)

최근에는 Deprecated 됐기 때문에 신규 프로젝트에는 비추천

 

3) Coroutine 또는 ViewModelScope (Kotlin + Jetpack 환경)

viewModelScope.launch(Dispatchers.IO) {
    val result = URL("https://example.com").readText()
    withContext(Dispatchers.Main) {
        // UI 업데이트
    }
}

 

4. 실무에서는 이렇게 사용

실제 앱에서는 Retrofit + Coroutine + ViewModel 조합이 거의 표준이다.
직접 HttpURLConnection을 쓰는 경우는 거의 없으며, 그럴 경우에도 반드시 Dispatchers.IO나 별도 Thread로 분리해서 실행해야 한다.

 

5. 요약

항목 설명
원인 메인 스레드에서 네트워크 작업을 시도
시점 API 11 이상 (Android 3.0+)부터 예외 발생
해결 백그라운드 스레드에서 실행 (Thread, Coroutine, Retrofit 등 사용)

 

6. 개발 팁

  • 테스트 중 일시적으로 예외를 피하고 싶다면 StrictMode를 완화할 수도 있지만, 절대 실제 서비스에 사용하면 안 된다.
  • StrictMode.ThreadPolicy 설정을 변경해서 강제로 허용할 수는 있으나, 이는 일시적인 디버깅 용도로만 사용해야한다.
if (Build.VERSION.SDK_INT > 9) {
    StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
    StrictMode.setThreadPolicy(policy);
}

 

7. 마무리 정리

NetworkOnMainThreadException은 초보자를 위한 트랩이자, 성능을 위한 보호장치이다. 이 에러는 앱 구조에서 비동기 처리가 필요한 시점이라는 신호이다. 코루틴, RxJava, Retrofit 등의 도구를 익히도록 해야겠다.

반응형