1. 개요
소프트웨어를 개발할 때 문자열의 명명 형식(String Naming Type)을 변환해야 할 경우가 왕왕 있었는데, 이에 따라 자유자재로 변환이 가능한 Utilty 기능의 필요성을 느껴 개발하였고 이 포스팅에서 소개하고자 한다.
1.1. 명명 형식 종류
| 명명 형식 | 예시 | 
|---|---|
| Lower Snake Case | hello_world | 
| Upper Snake Case | HELLO_WORLD | 
| Lower Skewer Case | hello-world | 
| Upper Skewer Case | HELLO-WORLD | 
| Pascal Case | HelloWorld | 
| Camel Case | helloWorld | 
| Title Case | Hello World | 
| Lower Case | hello world | 
| Upper Case | HELLO WORLD | 
2. 활용 문법
2.1. extension
2.2. get
3. 구현
3.1. 열거형 (Enum)
명명 형식의 종류를 나타내는 열거형 StringCaseType 이다.
enum StringCaseType {
  lowerSnakeCase, upperSnakeCase,
  lowerSkewerCase, upperSkewerCase,
  pascalCase, camelCase,
  titleCase, lowerCase, upperCase;
}3.2. 클래스 (Class)
3.2.1. 생성자 (Constructor)
전달받은 value 매개변수가 어떤 종류인지 파악하여 해당 종류에 대한 Setter 를 사용해 _value 값을 최신화한다.
StringCaseConverter(String value) {
  var type = getCaseType(value);
  switch (type) {
    case StringCaseType.lowerSnakeCase: lowerSnakeCase = value; break;
    case StringCaseType.upperSnakeCase: upperSnakeCase = value; break;
    case StringCaseType.lowerSkewerCase: lowerSkewerCase = value; break;
    case StringCaseType.upperSkewerCase: upperSkewerCase = value; break;
    case StringCaseType.pascalCase: pascalCase = value; break;
    case StringCaseType.camelCase: camelCase = value; break;
    case StringCaseType.titleCase: titleCase = value; break;
    case StringCaseType.lowerCase: lowerCase = value; break;
    case StringCaseType.upperCase: upperCase = value; break;
    default: throw ArgumentError('Unknown case type for: $value');
  }
}3.2.2. _value 속성
StringCaseConverter 클래스가 가지는 유일한 속성으로 Lower Snake Case 형식으로 저장된다.
late String _value;3.2.3. 접근자 (Accessor), 설정자 (Mutator)
/// lower_snake_case
String get lowerSnakeCase => _value;
set lowerSnakeCase(String s) => _value = s;
/// UPPER_SNAKE_CASE
String get upperSnakeCase => _value.toUpperCase();
set upperSnakeCase(String s) => _value = s.toLowerCase();
/// lower_skewer_case
String get lowerSkewerCase => _value.replaceAll('_', '-');
set lowerSkewerCase(String s) => _value = s.replaceAll('-', '_');
/// UPPER_SKEWER_CASE
String get upperSkewerCase => lowerSkewerCase.toUpperCase();
set upperSkewerCase(String s) => lowerSkewerCase = s.toLowerCase();
/// PascalCase
String get pascalCase {
  final words = _splitToWords(_value);
  return words.map(_capitalizeFirstLetter).join();
}
set pascalCase(String s) {
  final words = _splitToWords(s);
  _value = words.map((word) => word.toLowerCase()).join('_');
}
/// camelCase
String get camelCase {
  final words = _splitToWords(_value);
  return [words.first.toLowerCase(), ...words.skip(1).map(_capitalizeFirstLetter)].join();
}
set camelCase(String s) {
  final words = _splitToWords(s);
  _value = words.map((word) => word.toLowerCase()).join('_');
}
/// Title Case
String get titleCase {
  final words = _splitToWords(_value.replaceAll('_', ' ').replaceAll('-', ' '));
  return words.map(_capitalizeFirstLetter).join(' ');
}
set titleCase(String s) {
  final words = s.split(RegExp(r'\s+'));
  _value = words.map((word) => word.toLowerCase()).join('_');
}
/// lower case
String get lowerCase => titleCase.toLowerCase();
set lowerCase(String s) => titleCase = s.toLowerCase();
/// UPPER CASE
String get upperCase => titleCase.toUpperCase();
set upperCase(String s) => titleCase = s.toUpperCase();3.2.4. 정적 메소드 (Static Method)
3.2.4.1. getCaseType()
문자열 str 의 명명 형식을 반환한다.
- 매개변수
| 자료형 | 변수명 | 설명 | 
|---|---|---|
| String | str | 명명 형식을 조사할 문자열 | 
- 반환값
| 자료형 | 설명 | 
|---|---|
| StringCaseType | str 의 명명 형식 | 
static StringCaseType getCaseType(String str) {
  var isLower = str == str.toLowerCase();
  var isUpper = str == str.toUpperCase();
  var hasUnderscore = str.contains('_');
  var hasHyphen = str.contains('-');
  var hasSpace = str.contains(' ');
  /// 모든 문자가 소문자인 경우
  if (isLower) {
    if (hasUnderscore) return StringCaseType.lowerSnakeCase;
    if (hasHyphen) return StringCaseType.lowerSkewerCase;
    return StringCaseType.lowerCase;
  }
  /// 모든 문자가 대문자인 경우
  else if (isUpper) {
    if (hasUnderscore) return StringCaseType.upperSnakeCase;
    if (hasHyphen) return StringCaseType.upperSkewerCase;
    return StringCaseType.upperCase;
  }
  /// 소문자와 대문자가 섞인 경우
  else {
    var firstChar = str[0];
    var isFirstCharUpper = firstChar.toUpperCase() == firstChar;
    var isFirstCharLower = firstChar.toLowerCase() == firstChar;
    if (hasSpace) return StringCaseType.titleCase;
    if (isFirstCharUpper && !hasUnderscore && !hasHyphen) return StringCaseType.pascalCase;
    if (isFirstCharLower && !hasUnderscore && !hasHyphen) return StringCaseType.camelCase;
  }
  throw ArgumentError('Unknown case type for: $str');
}3.2.4.2. _splitToWords()
문자열 str 을 - 또는 _ 를 구분자로 하여 단어별로 구분한 배열을 반환한다.
- 매개변수
| 자료형 | 변수명 | 설명 | 
|---|---|---|
| String | str | 단어별로 구분할 문자열 | 
- 반환값
| 자료형 | 설명 | 
|---|---|
| List<String> | str 를 단어별로 구분한 배열 | 
static List<String> _splitToWords(String str) {
  final pattern = RegExp(r'[A-Z]?[a-z]+|[A-Z]+(?=[A-Z][a-z]|$)|\d+');
  final matches = pattern.allMatches(str.replaceAll(RegExp(r'[-_]'), ' '));
  return matches.map((m) => m.group(0) ?? '').toList();
}3.2.4.3. _capitalizeFirstLetter()
문자열 str 의 첮 문자를 대문자로 바꾼다.
- 매개변수
| 자료형 | 변수명 | 설명 | 
|---|---|---|
| String | str | 첫 문자를 대문자로 바꿀 문자열 | 
- 반환값
| 자료형 | 설명 | 
|---|---|
| String | str 의 첫 문자를 대문자로 바꾼 문자열 | 
static String _capitalizeFirstLetter(String str) {
  if (str.isEmpty) return str;
  return str[0].toUpperCase() + str.substring(1).toLowerCase();
}4. 전체 코드
enum StringCaseType {
  lowerSnakeCase, upperSnakeCase,
  lowerSkewerCase, upperSkewerCase,
  pascalCase, camelCase,
  titleCase, lowerCase, upperCase;
}
class StringCaseConverter {
  StringCaseConverter(String value) {
    var type = getCaseType(value);
    switch (type) {
      case StringCaseType.lowerSnakeCase: lowerSnakeCase = value; break;
      case StringCaseType.upperSnakeCase: upperSnakeCase = value; break;
      case StringCaseType.lowerSkewerCase: lowerSkewerCase = value; break;
      case StringCaseType.upperSkewerCase: upperSkewerCase = value; break;
      case StringCaseType.pascalCase: pascalCase = value; break;
      case StringCaseType.camelCase: camelCase = value; break;
      case StringCaseType.titleCase: titleCase = value; break;
      case StringCaseType.lowerCase: lowerCase = value; break;
      case StringCaseType.upperCase: upperCase = value; break;
      default: throw ArgumentError('Unknown case type for: $value');
    }
  }
  /// default: lower_snake_case
  late String _value;
  /// lower_snake_case
  String get lowerSnakeCase => _value;
  set lowerSnakeCase(String s) => _value = s;
  /// UPPER_SNAKE_CASE
  String get upperSnakeCase => _value.toUpperCase();
  set upperSnakeCase(String s) => _value = s.toLowerCase();
  /// lower_skewer_case
  String get lowerSkewerCase => _value.replaceAll('_', '-');
  set lowerSkewerCase(String s) => _value = s.replaceAll('-', '_');
  /// UPPER_SKEWER_CASE
  String get upperSkewerCase => lowerSkewerCase.toUpperCase();
  set upperSkewerCase(String s) => lowerSkewerCase = s.toLowerCase();
  /// PascalCase
  String get pascalCase {
    final words = _splitToWords(_value);
    return words.map(_capitalizeFirstLetter).join();
  }
  set pascalCase(String s) {
    final words = _splitToWords(s);
    _value = words.map((word) => word.toLowerCase()).join('_');
  }
  /// camelCase
  String get camelCase {
    final words = _splitToWords(_value);
    return [words.first.toLowerCase(), ...words.skip(1).map(_capitalizeFirstLetter)].join();
  }
  set camelCase(String s) {
    final words = _splitToWords(s);
    _value = words.map((word) => word.toLowerCase()).join('_');
  }
  /// Title Case
  String get titleCase {
    final words = _splitToWords(_value.replaceAll('_', ' ').replaceAll('-', ' '));
    return words.map(_capitalizeFirstLetter).join(' ');
  }
  set titleCase(String s) {
    final words = s.split(RegExp(r'\s+'));
    _value = words.map((word) => word.toLowerCase()).join('_');
  }
  /// lower case
  String get lowerCase => titleCase.toLowerCase();
  set lowerCase(String s) => titleCase = s.toLowerCase();
  /// UPPER CASE
  String get upperCase => titleCase.toUpperCase();
  set upperCase(String s) => titleCase = s.toUpperCase();
  static StringCaseType getCaseType(String str) {
    var isLower = str == str.toLowerCase();
    var isUpper = str == str.toUpperCase();
    var hasUnderscore = str.contains('_');
    var hasHyphen = str.contains('-');
    var hasSpace = str.contains(' ');
    /// 모든 문자가 소문자인 경우
    if (isLower) {
      if (hasUnderscore) return StringCaseType.lowerSnakeCase;
      if (hasHyphen) return StringCaseType.lowerSkewerCase;
      return StringCaseType.lowerCase;
    }
    /// 모든 문자가 대문자인 경우
    else if (isUpper) {
      if (hasUnderscore) return StringCaseType.upperSnakeCase;
      if (hasHyphen) return StringCaseType.upperSkewerCase;
      return StringCaseType.upperCase;
    }
    /// 소문자와 대문자가 섞인 경우
    else {
      var firstChar = str[0];
      var isFirstCharUpper = firstChar.toUpperCase() == firstChar;
      var isFirstCharLower = firstChar.toLowerCase() == firstChar;
      if (hasSpace) return StringCaseType.titleCase;
      if (isFirstCharUpper && !hasUnderscore && !hasHyphen) return StringCaseType.pascalCase;
      if (isFirstCharLower && !hasUnderscore && !hasHyphen) return StringCaseType.camelCase;
    }
    throw ArgumentError('Unknown case type for: $str');
  }
  static List<String> _splitToWords(String str) {
    final pattern = RegExp(r'[A-Z]?[a-z]+|[A-Z]+(?=[A-Z][a-z]|$)|\d+');
    final matches = pattern.allMatches(str.replaceAll(RegExp(r'[-_]'), ' '));
    return matches.map((m) => m.group(0) ?? '').toList();
  }
  static String _capitalizeFirstLetter(String str) {
    if (str.isEmpty) return str;
    return str[0].toUpperCase() + str.substring(1).toLowerCase();
  }
}5. 사용법
void main() {
  print(StringCaseConverter('hello_world').pascalCase);      // HelloWorld
  print(StringCaseConverter('HELLO_WORLD').pascalCase);      // HelloWorld
  print(StringCaseConverter('hello-world').pascalCase);      // HelloWorld
  print(StringCaseConverter('HELLO-WORLD').pascalCase);      // HelloWorld
  print(StringCaseConverter('HelloWorld').pascalCase);       // HelloWorld
  print(StringCaseConverter('helloWorld').pascalCase);       // HelloWorld
  print(StringCaseConverter('Hello World').pascalCase);      // HelloWorld
  print(StringCaseConverter('hello world').pascalCase);      // HelloWorld
  print(StringCaseConverter('HELLO WORLD').pascalCase);      // HelloWorld
  print(StringCaseConverter('hello_world').lowerSnakeCase);  // hello_world
  print(StringCaseConverter('hello_world').upperSnakeCase);  // HELLO_WORLD
  print(StringCaseConverter('hello_world').lowerSkewerCase); // hello-world
  print(StringCaseConverter('hello_world').upperSkewerCase); // HELLO-WORLD
  print(StringCaseConverter('hello_world').pascalCase);      // HelloWorld
  print(StringCaseConverter('hello_world').camelCase);       // helloWorld
  print(StringCaseConverter('hello_world').titleCase);       // Hello World
  print(StringCaseConverter('hello_world').lowerCase);       // hello world
  print(StringCaseConverter('hello_world').upperCase);       // HELLO WORLD
}관련 링크
728x90
    
    
  'Develop > Flutter' 카테고리의 다른 글
| [Flutter] 한글 Utility 기능 (0) | 2025.01.28 | 
|---|---|
| [Flutter] Duration 값 간결히 나타내기 (0) | 2023.11.01 | 
| [Flutter] 순환 캐러셀 (Circular Carousel) 위젯 만들기 (0) | 2023.10.16 | 
| [Flutter] 토스 스타일의 Pressable 커스텀 위젯 만들기 (0) | 2023.09.23 | 
 
									
								 
									
								 
									
								