🔥 부분문자열
Swift에서 문자열(String)의 일부분을 가져오는 경우, 예를 들어 서브스크립트나 prefix(_:)
같은 메서드를 사용할 때, 그 결과는 또 다른 문자열이 아닌 Substring
의 인스턴스라는 점을 알아두시면 좋겠어요. Substring은 String과 대부분의 메서드를 공유하기 때문에, 문자열을 다루는 것과 동일한 방식으로 substring을 다룰 수 있답니다. 그러나 문자열과는 달리, substring은 문자열에 대한 작업을 수행하는 동안 짧은 시간 동안만 사용된다는 것을 기억해 주세요. 결과를 더 오랫동안 저장하려면 substring을 String
의 인스턴스로 변환해야 합니다. 아래 예시를 살펴볼까요?
let greeting = "Hello, world!" let index = greeting.firstIndex(of: ",") ?? greeting.endIndex let beginning = greeting[..<index] // beginning은 "Hello"입니다. // 장기 저장을 위해 결과를 String으로 변환합니다. let newString = String(beginning)
swift
위 코드에서는 다음과 같은 일이 일어나요:
greeting
이라는 문자열을 정의합니다. 내용은 "Hello, world!"이에요.index
라는 상수에greeting
문자열에서 ","의 인덱스를 찾아 저장합니다. 만약 ","를 찾지 못하면greeting
의 끝 인덱스를 사용하도록??
연산자로 지정했어요.beginning
이라는 상수에greeting
의 처음부터index
까지의 substring을 저장합니다. 이때 substring은 "Hello"가 됩니다.- 마지막으로
beginning
substring을String
으로 변환하여newString
이라는 새로운 문자열 상수에 저장합니다. 이제newString
은 substring과는 별개의 문자열이 되었어요.
문자열과 마찬가지로 각 substring에는 substring을 구성하는 문자가 저장되는 메모리 영역이 있어요. 문자열과 substring의 차이점은 성능 최적화를 위해 substring이 원래 문자열의 메모리 일부 또는 다른 substring의 메모리 일부를 재사용할 수 있다는 점이에요. (문자열도 비슷한 최적화가 있지만, 두 문자열이 메모리를 공유하는 경우 두 문자열은 동일합니다.) 이러한 성능 최적화는 문자열이나 substring을 수정할 때까지 메모리 복사에 드는 성능 비용을 치르지 않아도 된다는 것을 의미해요. 앞서 언급했듯이 substring은 장기 저장에 적합하지 않습니다. 원래 문자열의 저장소를 재사용하기 때문에 substring이 사용되는 한 전체 원래 문자열을 메모리에 보관해야 하기 때문이죠.
위 예제에서 greeting
은 문자열이므로 문자열을 구성하는 문자가 저장되는 메모리 영역을 가지고 있어요. beginning
은 greeting
의 substring이기 때문에 greeting
이 사용하는 메모리를 재사용합니다. 반대로 newString
은 문자열이에요. substring에서 생성될 때 자체 저장소를 가집니다. 아래 그림은 이러한 관계를 보여줍니다:
위 그림에서 보듯이, beginning
은 greeting
과 메모리를 공유하고 있어요. 반면 newString
은 새로운 메모리 공간을 가지고 있죠. 따라서 substring을 오래 사용해야 한다면 반드시 새로운 문자열로 변환해주는 게 좋답니다. 그래야 원본 문자열의 메모리를 해제할 수 있으니까요!
이렇게 substring은 원본 문자열의 일부를 효율적으로 가져올 수 있게 해주는 강력한 기능이에요. 하지만 메모리 관리에 주의해야 한다는 점, 잊지 마세요!