안녕하세요. 마수리입니다.
오늘은 StringBuidler
에 대해서 알아볼까 합니다.
이 주제를 선택한 이유는 2가지가 있는데요
오늘의 글에선 StringBuilder
에 대해 간단한 개요를 이야기 해볼까 합니다.
여러분도 기본적으로 다들 알고 계신 것은 C#이나 JAVA의 string
객체는 불변타입이라 +
연산 등으로 string
을 이어 붙인다면 계속해서 새로운 string
객체가 생성되어 메모리 낭비와 GC의 부담을 준다는 것입니다. 이런 것을 해결하기 위해 등장한 것이 바로! 오늘의 주인공! Stringbuilder
입니다!
StringBuilder
는 Append()
, AppendLine()
등의 함수를 이용해서 추가적인 메모리 할당 없이(?) String
객체를 조작할 수 있다고 알려져 있는데요. StringBuilder
는 과연 어떻게 이루어져 있을까요?
한번 진지하게 고민해보시면 좋을 것 같습니다. 왜냐구요? 누군가 면접에서 물어보거든요 😂
다행히 저는 그때 당시 내가 StringBuilder
의 개발을 맡았다면 이렇게 했을 것이다 라고 잘 추측해서 이야길 했고 대부분 실제 코드도 그러 하였습니다. 여러분도 지금 이 글을 더 읽기 전에 한번 쯤 고민해 보셨으면 합니다
과연
StringBudiler
는 어떻게 문제를 해결했을까?
우선 가장 먼저 떠올리셔야 하는 아이디어는 버퍼입니다.
StringBuilder
는 지속적인 메모리 할당을 피하기 위해 자체 버퍼를 가지고 있습니다. 계속적인 string
객체의 메모리 할당을 피하기 위해선 자체 버퍼를 가지고 있어 한번만 크게 메모리를 할당하고 그 할당된 공간에 문자열을 추가하는 방식으로 구현되어 있을 것입니다.
그럼 다음 고민이 버퍼의 크기를 어떻게 결정하냐는 것이다.
버퍼의 크기는 기본 생성자를 호출했을 때 16개의 문자를 받을 수 있게 설정 되어있습니다. 그럼 StringBuilder
는 16개의 문자만 받을 수 있는건가? 그렇지 않습니다. 만약 16개 이상의 문자를 Append()
한다면 기존 버퍼들(최종적으로 버퍼는 여러개가 될 수 있습니다)의 크기에 비례해 새로운 버퍼를 만들고 문자열을 계속 이어서 버퍼에 써 내려갑니다.
어려분이 Append()
혹은 AppendLine()
을 사용해서 문자열을 이어나간 이유는 최종적으로 ToString()
을 사용해서 string
객체를 얻기 위함이였을 것입니다. 그럼 ToString()
을 했을 땐 어떻게 최종적으로 string
객체를 만들어 줄까요?
string
객체를 기존에 가지고 있던 모든 버퍼의 크기를 합한 것만큼 한번에 할당하고 기존에 있던 모든 버퍼를 돌면서 복사를 진행합니다. 이렇게 되면 적어도 +
연산을 이용해서 계속해서 메모리를 할당하는 것에 비해선 확실히 메모리 할당과 GC의 부담을 줄여줄 것 같습니다.
우리가 사용하던 StringBuilder
는 이러한 과정을 통해서 작업이 이루어집니다.
그럼
StringBuilder
를 어떻게 사용해야 좋을까요? 내부 구현은 어떻게 되어있을까요?
그 이야기에 대해선 다음 글에서 이야기 해보도록 하겠습니다.
감사합니다.