간단한 앱에서 OperationQueue를 활용하여 특정 작업을 Main Thread 가 아닌 Sub Thread 에서 실행시키는 방법을 보자.
위 앱은 Download 버튼을 누르면 용량이 상당히 큰 이미지를 다운 받아 상단의 Image View 에 띄우는 아주 간단한 앱이다.
사진을 다운 받는 url 주소는 imageURL 상수에 넣어두고, 이를 imageData 에 넣은 후 최종적으로 image 라는 상수에 이미지 형태로 넣는 코드다.
이미지를 정상적으로 다운 받고, 마지막으로 UIImage 인스턴스를 만들었으면 이제 Storyboard 에 있는 Image View 에 이미지를 삽입하기만 하면 된다.
그러나 이 상태로 실행을 하면 문제가 발생한다. 바로 Download 버튼을 누르면 화면 전체가 멈춰버린다. 이미지가 로딩이 되면 그제서야 버튼이 다시 정상 동작하기 시작한다.
왜 그런걸까?
이유는 위의 코드가 동기 메서드 ( async method ) 이기 때문이다.
밑줄 쳐놓은 Data.init(contentsOf: imageURL) 이 코드에서 이미지가 다운이 되는데, 몇 메가바이트가 족히 넘어가는 이미지를 다운받으려면 몇 초는 걸린다 (인터넷 환경이 느리면 더 걸림).
즉, 이미지가 다 다운로드가 되기 전까지는 그 다음 코드로 넘어가지를 않는다. 그래서 화면의 일시 정지 (freeze) 현상을 보게 된 것이다.
바로 이때 OperationQueue 를 활용할 수 있다.
OperationQueue 클래스의 addOperation 메서드를 이용하여 우리의 코드를 실행시켜보자.
이렇게 작성하면 이미지를 다운 받는 작업을 Main Thread 가 아닌 다른 Thread 에서 처리하게 되어, 버튼의 freezing 현상을 방지할 수 있다.
근데 문제가 있다. self.imageView.image = image 이 부분에서 보라색 에러가 뜬다. 에러 내용을 보자하니 이 줄의 코드는 Main Thread 에서만 실행이 가능하다는 내용이다.
이렇게 에러가 뜨는 이유는, UI와 관련된 부분 을 세팅하거나 수정할 때는 오직 Main Thread 를 이용해야 하기 때문이다.
아래와 같이 수정해주자.
밑 줄 해놓은 코드를 보면 대강 알겠지만, imageView의 이미지를 업데이트 하는 작업은 Main Thread 에서 이루어질 수 있도록 코드를 수정하였다.
이제 다운로드 버튼을 눌러도 버튼이 Freezing 되는 현상을 볼 수 없다.
이미지를 다운 받는 작업은 Main Thread 가 아닌 다른 별도의 Thread 에서 이루어지고 있고, 다운을 다 받은 후에는 해당 이미지를 ImageView에 세팅하는 작업은 Main Thread 에서 이루어지고 있다.