JavaScript / 문자열 indexOf()와 lastIndexOf()로 위치 찾기
indexOf()는 문자열에서 찾을 부분 문자열이 처음 나타나는 위치를, lastIndexOf()는 마지막으로 나타나는 위치를 반환합니다. 위치는 0부터 시작하며 찾지 못하면 둘 다 -1을 반환합니다. 두 번째 인수로 검색을 시작할 위치를 지정하면 탐색 방향에 따라 결과가 달라집니다.
첫 위치와 마지막 위치 찾기
indexOf(searchString)는 앞에서부터, lastIndexOf(searchString)는 뒤에서부터 일치하는 부분 문자열의 시작 인덱스를 찾습니다. 문자열은 대소문자를 구분하며, 결과가 0일 수도 있으므로 “찾았다”를 판정할 때는 -1과 비교하세요.
const text = 'banana';
console.log(text.indexOf('ana')); // 1
console.log(text.lastIndexOf('ana')); // 3
console.log(text.indexOf('ANA')); // -1
console.log(text.indexOf('b')); // 0
예를 들어 if (text.indexOf("b"))는 결과 0을 거짓으로 취급해 잘못 판단합니다. text.indexOf("b") !== -1처럼 비교하세요. 위치가 필요 없이 포함 여부만 알면 includes()도 선택할 수 있습니다. 정확한 반환 규칙은 MDN의 indexOf() 문서와 MDN의 lastIndexOf() 문서에서 확인할 수 있습니다.
두 번째 인수의 방향 이해하기
indexOf(query, position)는 지정한 위치부터 오른쪽으로 찾습니다. lastIndexOf(query, position)는 시작 인덱스가 지정한 위치 이하인 일치를 오른쪽부터 거꾸로 찾습니다. 지정 위치의 문자도 검색에 포함됩니다. 두 함수의 두 번째 인수를 같은 숫자로 주어도 의미가 같지 않습니다.
| 표현식 | 결과 | 이유 |
|---|---|---|
"banana".indexOf("ana", 2) |
3 |
2 이후에 시작하는 다음 일치 |
"banana".lastIndexOf("ana", 2) |
1 |
2 이하에서 시작하는 마지막 일치 |
"banana".indexOf("z") |
-1 |
일치 없음 |
처음 검색 결과 다음에서 두 번째 일치를 찾으려면 first + 1을 시작 위치로 주면 됩니다. 겹치는 일치도 찾아야 한다면 이 방식이 유용합니다. 겹치지 않는 일치만 찾으려면 first + query.length부터 검색합니다.
const first = 'banana'.indexOf('ana'); // 1
const overlapping = 'banana'.indexOf('ana', first + 1); // 3
const nonOverlapping = 'banana'.indexOf('ana', first + 'ana'.length); // -1
전체 예제로 직접 위치 바꿔 보기
다음 코드를 UTF-8의 search-example.html로 저장해 브라우저에서 엽니다. 원본 문자열, 찾을 문자열, 선택적인 시작 위치를 입력하고 ‘찾기’를 누릅니다. 위치를 비워 두면 두 메서드의 기본 동작을 비교합니다.
<!doctype html>
<html lang="ko">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>문자열 위치 검색 비교</title>
</head>
<body>
<label for="text">원본 문자열</label>
<input id="text" type="text" value="banana">
<label for="query">찾을 문자열</label>
<input id="query" type="text" value="ana">
<label for="position">시작 위치(비워 두면 전체 검색)</label>
<input id="position" type="text" inputmode="numeric">
<button id="search" type="button">찾기</button>
<button id="reset" type="button">처음으로</button>
<pre id="output" aria-live="polite"></pre>
<script>
const textInput = document.querySelector('#text');
const queryInput = document.querySelector('#query');
const positionInput = document.querySelector('#position');
const output = document.querySelector('#output');
function search() {
const text = textInput.value;
const query = queryInput.value;
const rawPosition = positionInput.value.trim();
if (query === '') {
output.textContent = '찾을 문자열을 입력하세요.';
return;
}
if (rawPosition !== '' && !/^(0|[1-9]\d*)$/.test(rawPosition)) {
output.textContent = '시작 위치는 0 이상의 정수로 입력하세요.';
return;
}
const position = rawPosition === '' ? null : Number(rawPosition);
if (position !== null && !Number.isSafeInteger(position)) {
output.textContent = '안전한 정수 범위 안의 위치를 입력하세요.';
return;
}
const first = position === null
? text.indexOf(query)
: text.indexOf(query, position);
const last = position === null
? text.lastIndexOf(query)
: text.lastIndexOf(query, position);
output.textContent = `indexOf: ${first}\nlastIndexOf: ${last}`;
}
document.querySelector('#search').addEventListener('click', search);
document.querySelector('#reset').addEventListener('click', () => {
textInput.value = 'banana';
queryInput.value = 'ana';
positionInput.value = '';
search();
});
search();
</script>
</body>
</html>
처음에는 indexOf: 1, lastIndexOf: 3이 표시됩니다. 시작 위치에 2를 입력하면 각각 3과 1이 됩니다. ANA를 찾으면 둘 다 -1입니다. 찾을 문자열을 비우거나 음수·소수 위치를 넣으면 입력 안내가 나옵니다. ‘처음으로’를 누르면 banana, ana, 빈 위치로 복원됩니다.
빈 문자열과 문자 인덱스의 주의점
두 메서드 자체는 빈 문자열 검색에도 숫자를 반환합니다. 예제에서는 그 결과가 학습자에게 혼동을 줄 수 있어 빈 검색어를 먼저 거릅니다. 인덱스는 JavaScript 문자열의 UTF-16 코드 단위를 기준으로 하므로, 일부 이모지처럼 코드 단위 두 개를 쓰는 문자가 앞에 있으면 화면의 글자 순서와 숫자가 다를 수 있습니다. 사용자에게 글자 위치를 보여 줄 때 이 차이를 확인하세요.




