String.Chars — 구조체를 문자열로 바꾸는 프로토콜

String.Chars — 구조체를 문자열로 바꾸는 프로토콜

값을 문자열로 표현하고 싶을 때 Elixir가 어떤 규칙으로 바꿔줄지 정의해 두는 것이 String.Chars 프로토콜이에요. "이 타입을 텍스트로 어떻게 보여줄지"를 약속으로 만들어 둔 셈이죠.

출처: String.Chars — The String.Chars protocol

본문

String.Chars 프로토콜은 구조체(structure)를 바이너리(문자열)로 변환하는 일을 담당해요. 다만 그 변환이 "가능할 때만(only if applicable)" 적용된다는 점을 기억해야 해요. 예를 들어 아톰(atom), 정수, 문자열 같은 내장 타입은 물론이고, 사용자가 직접 만든 구조체도 이 프로토콜을 구현하면 to_string/1로 깔끔하게 표현할 수 있게 되죠.

구현해야 하는 함수는 하나뿐이에요. 바로 변환을 실제로 수행하는 to_string/1이에요. defimpl로 프로토콜을 구현하면 되는데, 이때 타입명은 구현하려는 구조체의 이름이 돼요.

defimpl String.Chars do
  def to_string(value) do
    # 문자열로 변환하는 로직
  end
end

재미있는 점은, Kernel이 자동으로 import 하는 to_string/1 함수가 바로 이 프로토콜을 호출한다는 거예요. 즉 어디서 to_string(value)를 호출하든 내부적으로는 String.Chars 프로토콜의 to_string/1 구현이 실행돼요.

또한 문자열 보간(interpolation) 도 인자들에 대해 to_string/1을 호출해요. 예를 들어 "foo#{bar}""foo" <> to_string(bar)와 같은 뜻이에요. 그래서 어떤 값이든 #{} 안에 넣으면 그 값이 자기 타입의 String.Chars 구현에 따라 문자열로 바뀌어 들어가는 거죠. 사용자 정의 구조체를 문자열로 예쁘게 표현하고 싶다면, 그 구조체에 String.Chars 프로토콜을 구현해 두면 되고, to_string/1과 보간 양쪽에서 자동으로 적용돼요.

더 알아보기

  • 관련 프로토콜: String 모듈, to_string/1 (Kernel)
  • 문자열 보간: String 모듈의 Interpolation 섹션
  • 변환 방식: String.Chars와 비슷하게 자신의 타입을 값으로 변환하는 List.Chars, Inspect 프로토콜