[Unity]로드된 리소스의 메모리 누수

2022. 4. 13. 00:02Tech/Unity

    목차

이 글은 이전에 운영하던 깃 블로그에서 옮겨온 글입니다.

 

서론

 메모리 누수는 프로그램이 메모리 부족으로 인해 갑자기 종료되게 하는 주된 원인 중 하나입니다. 허용된 메모리 이상을 사용할 경우 시스템단에서 강제로 종료시켜 버리기 때문이죠. 누수라는 것은 불필요한 메모리가 할당된 뒤 적절하게 해제되지 못하고 떠돌기 때문에 발생합니다. Unity개발을 하면서도 메모리 누수를 보곤 합니다. 아니 분명 가비지 컬렉터 때문에 메모리 해제는 관리가 되고 있는 것 아닌가?라는 생각을 할 수 있지만, 아닙니다. 이번 글에서는 Unity의 메모리 누수, 특히 로드된 리소스로 인해 발생하는 누수에 관하여 다뤄 보려 합니다.


Unity의 메모리 관리방식

 이전에 가비지컬렉터(Unity, C#) 관련 글에서 Unity(C#, Monobehaivor)는 참조 카운팅 방식으로 메모리를 관리한다고 한 적이 있습니다. 정리하자면 할당된 메모리를 참조하고 있는 수가 0이 되면 사용하지 않는 메모리(가비지)로 판단하여 GC가 자동으로 회수합니다.

 

Unity를 시작한지 얼마 안 되었을 때였습니다. 사용이 끝난 오브젝트들을 Destory() 함수로 파괴해주고, 참조하고 있던 캐시를 null로 바꿔주어서 참조 카운트를 0으로 바꿔주는 식으로 사용한 적이 있습니다. 아마 정석인 방법일 것입니다. Hierarchy상에서도 게임씬상에서도 사라진 상황이고, 프로파일러 상에서도 참조 카운트는 0이었습니다. 그런데도 웬걸, 메모리가 계속해서 증가하는 게 아닌가요? 메모리 누수였습니다.


로드된 리소스의 메모리 누수

 분명 Hierarchy상에서도 없고, 씬에서도 없고, 참조개수도 0인데… 가비지인데... GC가 회수를 안 해간 것일까요? GC가 고장 난 것인가? 무슨 상황이지? 하고 당황했던 기억이 있습니다.

 

 이유는 오브젝트가 '로드된 리소스' 였다는 것이었습니다. Instantiate() 함수로 인스턴스화한인스턴스 화한 오브젝트는 일반적으로 Destory()를 통해서 가비지 수집 대상이 됩니다. 하지만 인스턴스 화한 재료가(원본, original) public 변수로 참조된 오브젝트(프리 팹 등)이거나 Resource.Load()로 로드된 리소스(텍스쳐, 프리 팹 등)라면? 씬상에 없어도, 참조 카운트가 0이어도 Mono의 GC는 해당 메모리를 회수하지 않습니다. 이는 관리하는 영역이 다르기 때문입니다.


해결방법은?

 이경우 Resources.UnloadUnusedAssets() 함수를 호출하면 됩니다. Unity 문서에는 이 함수에 대해 다음과 같이 설명하고 있습니다. "씬에서 사용되지 않고있는 에셋에 할당된 메모리를 해제합니다." 즉, 씬상에서 존재하지 않는다면, 위에서 설명한 대로 Hierarchy상에 없고 참조카운트가 0이라면 해제를 해준다는 뜻입니다. 수동으로 관리하는 리소스들에 관해서는 메모리 누수에 조금 더 신경 쓸 필요가 있는 거 같습니다.


마무리

 인생… 이것도 모르고 삽질했던 학생 시절이 떠오르네요. 그래도 이 삽질 덕분에 실제 업무에서는 도움이 되었으니 나쁘지 않은 경험이었습니다.

반응형
LIST

'Tech > Unity' 카테고리의 다른 글

[Unity]UIWebView Deprecated 이슈 해결 법  (0) 2022.04.13
[Unity]직렬화(Serialization)  (0) 2022.04.13
[Unity]Unity mobile native plugin  (0) 2022.04.12
[Unity]Scene 사이의 전환  (0) 2022.04.12
[Unity]코루틴(Coroutine)  (0) 2022.04.12