JAVA/Effective Java

[아이템 62] 다른 타입이 적절하다면 문자열 사용을 피하라

꾸준함. 2024. 3. 17. 16:01

문자열은 널리 사용되며 자바에서 잘 지원되기 때문에, 일반적으로 텍스트 표현 이외의 다른 용도로도 자주 사용됩니다.

이번 아이템에서는 문자열을 쓰지 않아야 할 사례를 다루겠습니다.

  • 문자열은 다른 값 타입을 대신하기에 적합하지 않음
  • 문자열은 열거 타입을 대신하기에 적합하지 않음
  • 문자열은 혼합 타입을 대신하기에 적합하지 않음
  • 문자열은 권한을 표현하기에 적합하지 않음

 

1. 문자열은 다른 값 타입을 대신하기에 적합하지 않음

  • 많은 개발자들이 파일, 네트워크, 키보드 입력으로부터 데이터를 받을 때 주로 문자열을 이용
  • 하지만 입력받을 데이터가 진짜 문자열인 경우 즉, 텍스트일 때만 문자열을 사용하는 것을 권장
    • 데이터가 수치형이면 int, long, double 등 수치에 적합한 타입을 사용
    • `Yes/No`와 같은 질문의 답이라면 적절한 enum 타입 혹은 boolean을 사용

 

  • 정리하자면 문자열은 텍스트 데이터를 다룰 때에만 사용하고, 다른 종류의 데이터는 적절한 값 타입을 사용하여 처리하는 것이 권장

 

2. 문자열은 열거 타입을 대신하기에 적합하지 않음

  • 아이템 34에서 다루었다시피 상수를 열거할 경우에는 문자열 열거 패턴 클래스보다 enum 타입이 훨씬 나음

 

2.1 문자열 열거 패턴 클래스


 

2.2 열거 타입


 

3. 문자열은 혼합 타입을 대신하기에 적합하지 않음

  • 여러 요소가 혼합된 데이터를 하나의 문자열로 표현하는 것은 대체로 좋지 않음


 

코드 부연 설명

  • i.next()에 구분자로 사용한 '#' 문자가 있는 경우 혼란스러운 결과가 발생
  • 각 요소를 개별적으로 접근하기 위해서 특정 기준을 통해 문자열을 파싱해야 해서 느리고, 귀찮고, 오류 가능성도 큼
  • 차라리 전용 클래스를 새로 만들어서 각 데이터 별로 멤버 변수를 취하는 것을 권장

 

4. 문자열은 권한을 표현하기에 적합하지 않음

  • 다음과 같이 권한(capacity)를 문자열로 표현하는 경우가 종종 있음

 

4.1 문자열을 사용하여 권한을 구분한 잘 못된 예


 

잘 못된 이유

  • 쓰레드 구분용 문자열 키가 전역 변수에 공유됨
    • 위 방식이 의도대로 동작하기 위해서는 각 클라이언트가 고유한 키를 제공해야 함
    • 만약 ThreadLocal을 사용하는 클라이언트들끼리 합의가 되지 않은 상태로 동일한 키를 사용한다면 의도치 않게 같은 변수를 공유하게 되어 제대로 작동도 안 할뿐더러 보안에도 취약

 

4.2 별도의 타입으로 권한을 구분하여 해결한 예

 

 

개선 포인트

  • 앞서의 문자열 기반 API의 문제점을 해결해주지만 개선 포인트 존재
    • set/get 메서드는 더 이상 정적 메서드일 필요가 없기 때문에 Key의 인스턴스 메서드로 변경하는 것을 권장
    • 위와 같이 처리시 Key는 더 이상 쓰레드 지역변수를 구분하기 위한 Key가 아니라 그 자체가 쓰레드 지역 변수가 됨

 

4.3 개선된 예

 

결과적으로 지금의 top level 클래스인 ThreadLocal은 별달리 하는 일이 없어지므로 치워버리고, 중첩 클래스 Key 클래스명을 ThreadLocal로 변경했습니다.


 

개선 포인트

  • 위 API는 get으로 얻은 Object를 실제 타입으로 타입 캐스팅 해야하기 때문에 type-safe 하지 않음

 

4.4 최종 버전

 

제네릭을 사용하면 type-safe하게 처리 가능합니다.


 

정리

  • 더 적합한 데이터 타입이 있거나 새로 작성할 수 있는 경우 문자열을 사용하지 말자
    • 문자열을 잘 못 사용할 경우 번거롭고, 유연하지 않으며, 느리고 오류 발생 가능성이 크기 때문

 

참고

이펙티브 자바

반응형