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 등의 도구를 익히도록 해야겠다.
'Android' 카테고리의 다른 글
[안드로이드] Play Store 심사 탈락 사례 모음 & 대응 방법 (1) | 2025.05.06 |
---|---|
[안드로이드] 앱 성능 최적화 : 렌더링 성능 (1) | 2025.04.27 |
[안드로이드] 앱 성능 최적화 : 네트워크 최적화 (0) | 2025.04.27 |
[안드로이드] 앱 성능 최적화 : 메모리 최적화 (1) | 2025.04.26 |
[안드로이드]커스텀 EditText 만들기 (1) | 2025.04.22 |