본문 바로가기
  • 구름빵의 개발 블로그
Front-End/JavaScript,TypeScript

[JavaScript] String 내장 객체의 비슷한 기능의 함수 비교

by 은빛구름빵 2025. 9. 5.

개요

JavaScript의 Built-In 객체에 보면 String이 있는데, 이 안에 다양한 메서드들이 존재한다.

근데 가만 보면 비슷한 기능을 하는 메서드가 있는 경우가 있다.

굳이 왜 비슷한 기능을 하는 메서드를 만들어 두었을까... 싶어서 이런 함수들을 찾아보고 비교해보려 한다.

 

1. slice() vs. substring()

제일 먼저 slice() 메서드와 substring() 메서드이다. 둘 다 문자열의 특정 구간을 가져오기 위한 함수이다.

둘 다 파라미터로 시작점, 끝점을 보내는데 무슨 차이가 있어서 이렇게 구분을 해놓았나 가장 궁금했던 함수이다.

let line = "JavaScript";
line.slice( 2, 5 );        // "vas"
line.substring( 2, 5 );    // "vas"

사용 예제와 결과만 보아도 거의 동일한 결과가 나온다.

일반적으로 사용 방법에는 차이가 전혀 없다. 그럼 어떤 차이가 있는가?

 

A) 파라미터로 음수를 제공했을 때 처리가 달라진다.

slice()의 경우 파라미터로 음수를 제공 받으면 음수 위치 계산 방법을 통해 위치를 계산해서 결과를 반환한다.

반면 substring()의 경우 파라미터로 음수를 제공 받으면 0으로 취급해서 계산한다.

line.slice( -4, -1 );        // "rip"
line.substring( -4, -1 );    // ""    --> 실제 연산은 line.substring( 0, 0 );

이처럼 음수를 받았을 때 후속 처리가 다르다는 특징이 있다.

문자열의 특정 부분을 가져올 때 맨 앞과 맨 뒤와 같이 앞뒤로 몰린 구간을 지정할 때는 slice()를 유용하게 사용할 수 있을 것 같다.

 

B) 끝지점을 나타내는 값이 시작지점을 나타내는 값보다 작은 경우( 이전인 경우 ) 처리가 달라진다.

slice( a, b )의 경우, a > b라면 빈 문자열을 반환한다. 논리적으로 맞지 않으므로 연산이 이루어지지 않는다.

하지만 substring( a, b )의 경우, a > b라면 substring( b, a )로 바꿔서 연산을 진행한다. 즉, 자기가 알아서 작은 값부터 큰 값까지의 구간을 가져온다는 의미이다.

line.slice( 5, 1 );        // ""
line.substring( 5, 1 );    // "avaS"  --> 실제 연산은 line.substring( 1, 5 );

이처럼 끝지점과 시작 지점의 대소관계가 올바르지 않아도 substring()은 연산을 정상적으로 수행하는 반면 slice()는 그러지 못한다.

 

2. indexOf() vs. search()

두 함수 모두 문자열 내에서 특정 값이 있는지 찾을 때 사용하는 함수이다.

심지어 둘 다 위치를 반환해준다는 점에서 거의 동일한 기능을 수행한다.

하지만 생각보다 두 함수는 큰 차이를 가지고 있다.

const line = "JavaScript";

line.indexOf( "S" );     // 4
line.search( "S" );      // 4

둘 다 단일 파라미터로 찾고자 하는 값을 전달하면 위치를 정확하게 찾아온다.

위 예제에서는 S라는 글자 하나만 사용했지만 문자열을 사용해도 둘 다 모두 정상적으로 작동한다.

그럼 이제 두 함수가 어떤 차이가 있는지 알아보자.

 

A) 찾기 위한 값을 주는 파라미터를 인식하는 방법이 다르다.

indexOf()는 파라미터로 주는 값을 '문자열'로 인식하는 반면 search()는 파라미터로 주는 값을 '정규식'으로 이해한다.

즉, indexOf( "S" ) 는 S라는 값을 문자열로 던져준 것이지만 search( "S" ) 는 S라는 값을 정규식으로 준 것이다.

그렇기 때문에 파라미터로 정규식을 주면 인식하는 방법 또한 다르다

line.indexOf( '/\d+/' );    // /\d+/라는 문자열로 찾음
line.search( '/\d+/' );     // 문자열 내에 있는 정수를 찾음

이렇게 파라미터로 정규식을 주면 수행하는 방식이 완전히 다르다. 

일반적으로 단순한 문자열을 찾을 때는 indexOf()가 더 쉽고 간단하지만 복잡한 조건의 검색을 진행할 때는 search()를 사용하는 것이 좋다.

 

B) 검색 시작 지점 가능 여부가 다르다.

기본적으로 단일 파라미터로 사용할 경우 모두 0번째 인덱스 글자부터 탐색을 진행하지만 indexOf()의 경우 탐색을 시작할 지점을 개발자가 임의로 지정할 수 있다.

line.indexOf( "S", 6 );      // -1
line.search( "S" );          // 4

search()는 반드시 0번 인덱스부터 탐색을 시작하지만 indexOf()는 두 번째 파라미터로 전달한 인덱스부터 탐색을 시작한다.

line이 "JavaScript"라는 문자열이었는데 6번 인덱스면 c부터 이므로 S는 범위에 들어가지 않아 찾을 수 없다는 -1이 반환된다.

 

C) 대소문자를 구분하기 위한 방법이 다르다.

기본적으로 두 함수 모두 대소문자를 구분한다. 즉, J와 j는 다른 글자로 인식한다는 의미이다.

하지만 상황에 따라 대소문자를 구분하지 않고 검색을 진행해야 하는 경우가 있다.

이런 경우에 이 문제를 해결하는 방법이 좀 다르다.

line.indexOf( "j" );       // -1
line.search( "j" );        // -1

// indexOf()의 대소문자 구분 해제 방법
line.toLowerCase();
line.indexOf( "j" );

// search()의 대소문자 구분 해제 방법
line.search( "/j/i" );

indexOf()를 사용하려면 원본 문자열의 대문자를 모두 소문자로 바꿔주는 toLowerCase() 함수를 사용해야 한다.

이 경우, 원본 문자열을 훼손하기 때문에 훼손하지 않기 위해선 임의의 변수를 만들고 그 변수에 문자열을 대입해서 바꿔주어야 한다. 상당히 번거로운 과정을 거쳐야 한다는 단점이 있다.

하지만 search()의 경우 정규식을 허용하기 때문에 정규 표현식 플래그를 통해 대소문자 구분을 해제할 수 있다.

정규식을 인식한다는 점이 가장 큰 특징이라고 볼 수 있다.

 

결론

이 외에도 비슷한 기능을 하는 많은 함수들이 있겠지만 짧은 서칭 시간과 알고 있던 함수 내에서 찾은 것은 이 부분이었다. 특히 substring()과 slice()는 코딩할 때 꽤 사용하는 부분이었는데 Claude 같은 경우도 어떤 때는 substring()을 추천하고 어떤 때는 slice()를 추천하기도 했다. 그 당시 사용할 때 "전엔 substring() 이었는데 왜 이번엔 slice()지?" 라고 의문점을 갖고 추후 알아봐야겠다 생각하고 있었고, 알아보니 이런 차이가 있다는 것을 알 수 있었다.

목표만 동일하다면 어떤 것을 사용해도 차이가 없지만 예외의 상황과 부가적인 기능을 생각하며 둘 중 어떤 함수를 쓸지 생각해봐야 하는 것 같다.