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번 같은 포인트만 생각해서 구현을 하는 것이 좋을 것 같다. 끝
'Android > 기타' 카테고리의 다른 글
[Android] 백그라운드에서 클립보드 이용 시 주의사항 (0) | 2021.10.21 |
---|---|
[Android] 카카오 SDK 설치 안 되는 이슈(Fox 버전 이후) (0) | 2021.09.15 |
[Android] 로그에 대한 개인적인 생각 (0) | 2021.06.23 |
[Android] Android Geocoder maxResults 값에 대해서 (0) | 2020.12.24 |
[Android] Retrofit2 응답 대응 처리 (0) | 2020.12.21 |