본문 바로가기

Android/기타

[Android] 멀티스레드에 대한 개인적인 생각

반응형

Java를 공부하다보면 Thread라는 녀석을 볼 수 있다. 공부할 당시에는 '이게 왜 필요하지?'라는 생각이 처음에 들었었고 또 이걸 실제로 적용을 어떻게 시키는지에 대해서도 이해가 잘 안 되었던 것 같다. 그래서 첫 회사에서 멀티스레드로 구현을 하면서 많은 이슈(에러 및 버그)를 겪었었고 그 과정에서 정리할 수 있었던 포인트에 대해 정리해보려고 한다. 아마 신입들한테 도움이 되지 않을까 싶다.(스레드 고수들은 굳이 안 읽어도 됩니다...)

 

1. 멀티스레드는 왠만하면 피해라.

이제 막 신입 아니면 스레드에 익숙치 않은 개발자라면 특히 해당된다. 멀티스레드로 에러가 발생한다면 사수 없이 찾기란 거의 불가능에 가깝다고 생각한다. 경험이 좀 쌓이고 나서 해도 늦지 않다......

 

2. 라이브러리를 잘 활용하자.

파일 입출력 혹은 네트워크 통신 등은 스레드가 필수다. 하지만 저것을 위해 직접 구현을 해야할까? API 통신을 할 때는 Retrofit2, 이미지 로딩은 Glide 등 대표적으로 쓰이는 검증된 오픈 소스 라이브러리들이 있다. 뭔가 직접 구현하는 것을 더 좋아하는 개발자들도 있겠지만 실무에서는 굳이 안전한 길을 놔두고 돌아갈 필요는 없다.

 

3. 스레드끼리 공유하는 객체에 대한 사용을 주의하자.

여기까지 왔다면 어쩔 수 없이 멀티스레드를 쓰는 경우일 것이다. 그렇다면 아래와 같은 상황들로 간단히 정리할 수 있을 것 같다.(스레드 A, B 기준) 안드로이드 기준으로 생각해본다면 UI(메인) 스레드와 다른 스레드(네트워크 통신, 파일 입출력 등)

  • A 스레드에서 접근하고 B 스레드에서 접근
    • 안전
  • A 스레드에서 접근하고 B 스레드에서 수정
    • B 스레드에서 수정하는 부분에 락 필요함
  • A 스레드에서 수정하고 B 스레드에서 수정
    • A, B 각각 스레드에서 수정하는 부분에 락 필요함
  • A, B 공유하는 객체 혹은 변수가 없음
    • 안전

 

첫 회사 실수 경험인데 예시로 적합할 것 같아 추가로 적어본다. 그 때 구현했던 것이 채팅 메시지를 채팅방 화면(UI)에 뿌리는 것이었다. 근데 채팅 메시지 리스트에 메시지를 추가하고 삭제하는 부분을 따로 작업 스레드로 빼서 구현했었고 해당 리스트 그대로 Adapter에 넘겨주었었다. 그 결과 메시지를 추가할 때 간헐적으로 List에서는 해당 Position이 있는데 RecyclerView에서는 없어서 죽는 문제가 발생하였다. 이 문제 역시 2번째 경우에 해당한다. 이런 경우 버그를 재현하는 것도 쉽지 않기 때문에 스레드를 사용할 시 이 항목에 대해서 검토를 해야한다.

 

4. 락은 필요할 때만 걸자.

위의 첫 회사 실수 경험 때 조치로 전체에 락을 걸었었다. 나중에 코드리뷰할 때 탈탈 털렸지만...^^;;

락을 간단히 설명하자면 A, B라는 두 공간(스레드)를 연결하는 통로가 있는데 이 통로에 필요할 때 잠그거나 여는 것이라고 생각하면 쉽다.

그러면 이 락을 막 써도 될까? 그 부분은 다음을 통해서 설명할 수 있다.

 

예시로 다음과 같은 상황이 주어졌다고 해보자

  • A, B라는 공간이 존재
  • B에서는 a, b, c라는 작업이 있음
  • A, B에서 공유하는 부분은 a 작업임

자 이 상황에서 다음 경우에 대해 생각해보자

  • B 전체에 락을 거는 경우(class에 synchronized 붙이는 것)
    • 이 경우에는 a, b, c라는 작업을 할 때마다 락을 걸고 푸는 과정이 있는 것과 마찬가지로 생각하면 됨
    • b, c는 A와 관련이 없어서 굳이 락이 필요 없음
    • 자바에서 보면 클래스 전체에 거는 것이기 때문에 멤버 변수, 메소드 전체에 락을 걸고 푸는 과정이 있다고 생각하면 됨
  • a, b, c에 락을 거는 경우(필요한 영역을 포함하는 메소드 전체에 synchronized 붙이는 것)
    • B 전체에 락을 거는 것보단 낫지만 b, c를 수행할 때도 락이 있기 때문에 속도 저하가 생김
  • a 부분에만 락을 거는 경우(class에서 필요한 영역에만 synchronized 붙이는 것)
    • 이 부분이 제일 깔끔(필요한 경우에만 락을 씀)

 

정리하자면 사수가 없는 신입 혹은 주니어 개발자들이 실무에서 멀티스레드를 쓰는 것은 왠만하면 지양하고 어쩔 수 없는 경우 3, 4번 같은 포인트만 생각해서 구현을 하는 것이 좋을 것 같다. 끝

반응형