1. 소개: Java에서 문자열 검색이 중요한 이유
문자열 조작은 Java 프로그래밍 시 가장 자주 사용되는 작업 중 하나입니다.
사용자 입력을 검사하거나 파일 내용을 파싱하거나 특정 키워드를 검색할 때, 주어진 문자열에 특정 단어가 포함되어 있는지를 판단해야 할 경우가 많습니다.
이러한 요구를 충족시키기 위해 Java는 contains() 라는 편리한 메서드를 제공합니다.
이 메서드를 사용하면 한 문자열이 다른 문자열을 부분적으로 포함하고 있는지를 쉽게 판단할 수 있습니다.
예를 들어, 오류 메시지에 특정 키워드가 포함되어 있는지 확인하고 싶을 때 contains() 를 한 줄의 코드로 구현할 수 있습니다.
특히 웹 애플리케이션, API 처리, 로그 분석 등 대량의 텍스트를 다루는 상황에서는 contains() 메서드가 코드 가독성과 유지보수성을 크게 향상시킵니다.
하지만 대소문자 구분이나 null 가능성 등 중요한 고려사항도 존재합니다.
이 글에서는 Java의 contains() 메서드를 자세히 살펴봅니다—기본 사용법과 흔히 저지르는 실수, 다른 메서드와의 차이점, 실무 적용 사례 등을 다룹니다.
초보자뿐만 아니라 실제 프로젝트에서 Java를 활발히 사용하는 개발자에게도 유용한 정보를 제공하는 것이 목표입니다.
2. contains() 메서드의 기본 문법 및 특성
Java의 contains() 메서드는 문자열이 부분적으로 다른 문자열을 포함하고 있는지를 판단합니다.
문법은 매우 간단하지만 일상적인 프로그래밍 작업에서 매우 실용적이고 자주 사용됩니다.
기본 문법
boolean result = targetString.contains(searchString);
이 메서드는 String 클래스에 속하며, CharSequence(보통 String)를 인자로 받습니다.
반환값은 boolean이며, 대상 문자열이 주어진 부분 문자열을 포함하면 true, 그렇지 않으면 false를 반환합니다.
샘플 코드
String message = "Java programming is fun!";
boolean hasKeyword = message.contains("programming");
System.out.println(hasKeyword); // Output: true
위 예제에서 부분 문자열 "programming"이 대상 문자열에 존재하므로 contains() 가 true를 반환합니다.
메서드의 특성
- 부분 일치만 검사: 정확히 일치하는지를 확인하려면
equals()를 사용하세요. - 대소문자 구분: 예를 들어
"Java"와"java"는 서로 다른 문자열로 취급됩니다(자세한 내용은 아래에서 설명). - 정규식 미지원: 단순히 문자열 존재 여부만 확인하므로 패턴 매칭이 필요할 경우
matches()나Pattern클래스를 사용해야 합니다.
null이 전달될 때의 동작
contains() 에 null을 전달하면 NullPointerException이 발생합니다.
예를 들어, 다음 코드는 예외를 발생시킵니다:
String text = null;
System.out.println(text.contains("test")); // Exception occurs
마찬가지로 대상 문자열 자체가 null인 경우에도 동일한 예외가 발생합니다.
따라서 contains() 를 호출하기 전에 null 체크를 수행하는 것이 강력히 권장됩니다.
3. 실용적인 사용 예시와 중요한 고려사항
Java의 contains() 메서드는 직관적이고 편리하지만, 잘못 사용하면 예상치 못한 버그나 비효율적인 코드가 생길 수 있습니다.
이 섹션에서는 contains() 의 기본 사용법과 함께 반드시 유념해야 할 핵심 포인트를 설명합니다.
3-1. 기본 사용 예시
다음 코드는 대상 문자열에 특정 키워드가 포함되어 있는지를 확인하는 간단한 예시를 보여줍니다:
String sentence = "今日はJavaの勉強をしています。";
if (sentence.contains("Java")) {
System.out.println("Javaが含まれています。");
} else {
System.out.println("Javaは含まれていません。");
}
보시다시피 contains() 는 if 문과 함께 사용되어 조건 분기를 수행하는 경우가 많습니다.
3-2. 대소문자 구분
contains() 메서드는 대소문자를 구분합니다.
예를 들어, 다음 코드는 false를 반환합니다:
String text = "Welcome to Java";
System.out.println(text.contains("java")); // false
이러한 경우, 비교 전에 문자열을 소문자(또는 대문자)로 변환하는 것이 일반적입니다:
String text = "Welcome to Java";
System.out.println(text.toLowerCase().contains("java")); // true
이 접근 방식은 입력 케이스의 차이를 제거하는 데 도움이 됩니다 (예: 사용자 입력).
3-3. null 및 빈 문자열 처리
contains()를 사용할 때 가장 중요한 고려 사항 중 하나는 null 처리입니다.
대상 문자열이나 인수가 null인 경우 NullPointerException이 발생합니다.
String text = null;
System.out.println(text.contains("test")); // Runtime error
이 문제를 피하기 위해 항상 null 검사를 추가하세요:
if (text != null && text.contains("test")) {
// Safe to process
}
또한 주의:
빈 문자열 ("")을 전달하면 항상 true를 반환합니다.
String sample = "test";
System.out.println(sample.contains("")); // true
그러나 이 동작은 실제로 거의 유용하지 않으며, 빈 문자열이 의도치 않게 전달되면 버그를 초래할 수 있습니다.
3-4. 여러 키워드 검색 미지원
contains()는 한 번에 하나의 키워드만 확인할 수 있습니다.
여러 키워드를 확인하려면 contains()를 여러 번 호출하거나 Stream API를 사용해야 합니다.
String target = "エラーコード123:アクセス拒否";
if (target.contains("エラー") || target.contains("拒否")) {
System.out.println("問題のあるメッセージです。");
}
또는 동적 키워드 세트의 경우:
List<String> keywords = Arrays.asList("エラー", "障害", "失敗");
boolean found = keywords.stream().anyMatch(target::contains);
4. contains()와 자주 비교되는 메서드
Java는 문자열을 비교하거나 특정 부분 문자열이 존재하는지 확인하는 여러 메서드를 제공합니다.
그중 contains()는 “부분 일치”에 사용되지만, 다른 메서드들도 유사한 목적으로 사용됩니다.
이 섹션에서는 이러한 메서드들의 특성과 차이점을 설명하여 적절히 사용하도록 돕습니다.
4-1. equals()와의 차이: 정확 일치 vs. 부분 일치
equals()는 두 문자열이 정확히 동일한지 결정합니다.
반대로, contains()는 부분 일치를 확인합니다.
String a = "Java";
String b = "Java";
System.out.println(a.equals(b)); // true: Exact match
System.out.println(a.contains("av")); // true: Partial match
주요 차이점:
| Comparison | equals() | contains() |
|---|---|---|
| Match Type | Exact match | Partial match |
| Case Sensitivity | Sensitive | Sensitive |
| Argument Type | Object | CharSequence |
사용 지침:
값이 정확히 일치해야 할 때 (예: ID 확인) equals()를 사용하세요.
부분 일치가 허용될 때 (예: 키워드 검색) contains()를 사용하세요.
4-2. indexOf()와의 차이: 위치가 필요한지 여부
indexOf() 메서드는 문자열 내에 부분 문자열이 존재하는지 확인하는 데도 사용할 수 있습니다.
차이점은 indexOf()가 발견된 경우 부분 문자열의 시작 인덱스를 반환한다는 것입니다.
부분 문자열을 찾지 못하면 -1을 반환합니다.
String text = "Hello, Java World!";
System.out.println(text.indexOf("Java")); // 7
System.out.println(text.indexOf("Python")); // -1
indexOf()를 사용하여 contains()의 동작을 재현할 수도 있습니다:
if (text.indexOf("Java") >= 0) {
System.out.println("It is contained.");
}
사용 지침:
인덱스가 필요하지 않다면 contains()가 더 읽기 쉽고 선호됩니다.
4-3. matches()와의 차이: 정규 표현식 지원
matches() 메서드는 문자열이 주어진 정규 표현식과 완전히 일치하는지 확인합니다.
반대로, contains()는 리터럴 부분 문자열 일치만 확인하며 regex를 지원하지 않습니다.
String text = "abc123";
System.out.println(text.matches(".*123")); // true
System.out.println(text.contains(".*123")); // false (not regex)
정규 표현식 기반 부분 일치를 원한다면 Pattern 클래스를 사용하세요:
4-4. 기능 비교 요약
| Method | Purpose | Return Type | Regex Support | Use Case |
|---|---|---|---|---|
contains() | Partial match | boolean | No | Keyword search |
equals() | Exact match | boolean | No | ID/password checks |
indexOf() | Get match position | int | No | Index-based processing |
matches() | Regex match | boolean | Yes | Find pattern-based strings |
5. 일반적인 사용 사례 및 샘플 코드
Java의 contains() 메서드는 간단하지만 실제 개발 시나리오에서 널리 사용됩니다.
일반적인 사용 사례로는 사용자 입력 검증, 로그 분석, 필터링 작업 등이 있습니다.
이 섹션에서는 해당 코드와 함께 실용적인 예제를 다룹니다.
5-1. 사용자 입력 검증 (금지 단어 감지)
폼이나 채팅 애플리케이션에서 특정 금지 단어가 포함되어 있는지 감지해야 할 수 있습니다.
String input = "このアプリは最悪だ";
String banned = "最悪";
if (input.contains(banned)) {
System.out.println("不適切な言葉が含まれています。");
}
여러 개의 NG 단어 처리:
List<String> bannedWords = Arrays.asList("最悪", "バカ", "死ね");
for (String word : bannedWords) {
if (input.contains(word)) {
System.out.println("不適切な言葉が含まれています: " + word);
break;
}
}
5-2. 로그 파일 분석 (특정 메시지 감지)
시스템 또는 애플리케이션 로그를 분석할 때, ERROR나 WARN과 같은 특정 키워드가 포함된 라인만 추출하고 싶을 수 있습니다.
List<String> logs = Arrays.asList(
"[INFO] サーバーが起動しました",
"[ERROR] データベース接続失敗",
"[WARN] メモリ使用率が高い"
);
for (String log : logs) {
if (log.contains("ERROR")) {
System.out.println("エラー発生ログ: " + log);
}
}

5-3. 리스트에서 문자열 필터링 (Stream API 사용)
대용량 데이터셋을 다룰 때, Stream API를 사용하여 특정 부분 문자열을 포함하는 요소만 추출합니다:
List<String> users = Arrays.asList("tanaka@example.com", "sato@gmail.com", "yamada@yahoo.co.jp");
List<String> gmailUsers = users.stream()
.filter(email -> email.contains("@gmail.com"))
.collect(Collectors.toList());
System.out.println(gmailUsers); // [sato@gmail.com]
5-4. HTTP 요청 헤더 또는 URL 파싱
웹 개발에서 라우팅이나 디바이스별 처리를 위해 User-Agent나 URL에 포함된 부분 문자열을 확인해야 할 수 있습니다.
String userAgent = "Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X)";
if (userAgent.contains("iPhone")) {
System.out.println("スマートフォンからのアクセスです。");
}
5-5. 파일 경로 또는 확장자 확인
파일 경로를 사용해 파일 유형을 판단하려면:
String filePath = "/usr/local/data/sample.csv";
if (filePath.contains(".csv")) {
System.out.println("CSVファイルです。");
}
Note:
파일 확장자를 확인할 때는 endsWith(".csv")가 더 정확한 경우가 많습니다.
실용적인 고려 사항
- 정확성이 필요할 때는 정규화(예:
toLowerCase(),trim())를 적용하세요. - 대규모 데이터의 경우 Stream API나 정규식을 고려하세요.
contains()는 부분 일치이므로, 보다 안전한 로직을 위해 다른 조건과 결합하세요.
6. 성능 고려 사항
contains() 메서드는 가독성과 단순성이 뛰어나지만, 대규모 데이터셋을 다루거나 반복 작업을 수행할 때 성능 영향을 고려해야 합니다.
이 섹션에서는 contains()의 처리 비용과 효율성을 높이기 위한 대안 접근법을 설명합니다.
6-1. contains()의 내부 동작 및 시간 복잡도
contains() 메서드는 대상 문자열을 시작부터 순차적으로 검색하여 부분 문자열을 찾습니다.
내부적으로는 indexOf() 메서드에 의존하며, 최악의 경우 시간 복잡도는 다음과 같습니다:
O(n * m)
– n = 대상 문자열의 길이
– m = 검색 문자열의 길이
무거운 처리를 하는 예시:
for (String line : hugeTextList) {
if (line.contains("error")) {
// processing
}
}
대규모 루프 내에서 반복될 경우 성능에 크게 영향을 미칠 수 있습니다.
6-2. 빈번한 검색 시 성능 향상 기법
대규모 데이터셋에서 contains()를 반복적으로 사용할 때, 다음 기법들이 처리 속도를 향상시킬 수 있습니다:
• 모든 문자열을 미리 소문자로 변환하기
각 비교마다 toLowerCase()를 호출하는 대신, 사전에 문자열을 정규화하세요:
List<String> normalizedList = originalList.stream()
.map(String::toLowerCase)
.collect(Collectors.toList());
• parallel()을 사용한 Stream API로 병렬 처리
CPU 코어를 활용해 검색 속도를 높이세요:
List<String> result = hugeTextList.parallelStream()
.filter(line -> line.contains("keyword"))
.collect(Collectors.toList());
• 복잡한 검색 패턴을 위한 정규식 사용
조건이 복잡하고 하나의 정규식으로 표현될 수 있다면 Pattern이 더 나은 성능을 보일 수 있습니다:
Pattern pattern = Pattern.compile("error|fail|fatal");
for (String log : logs) {
if (pattern.matcher(log).find()) {
// matched
}
}
6-3. 메모리 효율성 및 재사용성 고려 사항
toLowerCase()나 substring()과 같이 문자열을 자주 변환하는 작업은 불필요한 문자열 객체를 많이 생성하여 메모리 사용량에 영향을 줄 수 있습니다.
이는 장시간 실행되는 애플리케이션이나 서버 측 처리에서 특히 중요합니다.
핵심 포인트:
- 불필요한 문자열 인스턴스 생성을 피합니다.
- 대용량 데이터셋의 경우 버퍼링이나 청크 처리를 고려합니다.
- 반복적인
contains()결과를 캐시하면 특정 상황에서 성능이 향상될 수 있습니다.
7. 다른 프로그래밍 언어와의 비교
Java의 contains() 메서드는 간단하고 신뢰할 수 있는 부분 문자열 매칭을 제공하지만, 다른 언어들도 각자의 특성을 가진 유사한 기능을 제공합니다.
이 섹션에서는 Python, JavaScript, C#에서의 부분 문자열 확인을 비교하여 차이점과 유사점을 강조합니다.
7-1. Python: in 연산자를 이용한 간단한 부분 매치
Python에서는 in 연산자를 사용해 부분 문자열 포함 여부를 확인할 수 있습니다:
text = "Hello, Python!"
if "Python" in text:
print("含まれています")
이 문법은 매우 가독성이 높으며—마치 자연어처럼—학습 부담이 거의 없습니다.
차이점 및 참고 사항:
in은 메서드가 아니라 언어 연산자입니다.- Python도 문자열 비교 시 대소문자를 구분합니다.
None은 예외를 발생시키므로 null 체크가 필요합니다.
7-2. JavaScript: includes()를 이용한 부분 매치
JavaScript(ES6+)에서는 includes() 메서드를 사용할 수 있습니다:
const text = "JavaScript is fun";
console.log(text.includes("fun")); // true
이 메서드는 Java의 contains()와 매우 유사하여 사고 전환이 쉽습니다.
차이점 및 참고 사항:
undefined를 전달해도 예외가 발생하지 않고 단순히false를 반환합니다.includes()는 배열에도 적용 가능해 활용도가 높습니다.
7-3. C#: Java와 유사한 Contains()
C# 역시 Java와 비슷한 동작을 하는 Contains() 메서드를 제공합니다:
string text = "Welcome to C#";
bool result = text.Contains("C#");
차이점 및 참고 사항:
- C#의
Contains()는 기본적으로 대소문자를 구분하지만,StringComparison.OrdinalIgnoreCase를 사용하면 대소문자를 무시할 수 있습니다. - null을 전달하면
ArgumentNullException이 발생합니다.
7-4. 언어별 비교 표
| Language | Example Syntax | Case Sensitivity | Notes |
|---|---|---|---|
| Java | "abc".contains("a") | Sensitive | Throws exception on null |
| Python | "a" in "abc" | Sensitive | Most intuitive syntax |
| JavaScript | "abc".includes("a") | Sensitive | Also works for arrays |
| C# | "abc".Contains("a") | Sensitive (configurable) | Comparison mode can be chosen |
요약: 사용 사례에 맞는 문법 선택
부분 문자열 확인은 모든 언어에서 공통적인 요구사항이지만, 각 언어는 자체적인 메서드나 문법을 제공합니다.
Java의 contains()는 안정성과 명확성을 제공해 엔터프라이즈 시스템 및 유지보수성이 중요한 애플리케이션에 적합합니다.
Python과 JavaScript는 더 간결하고 직관적인 문법을 제공해 가벼운 스크립트나 빠른 프로토타이핑에 이상적입니다.
공통 개념과 각 언어의 특성을 이해하면 다양한 언어에서 보다 안전하고 효율적인 코드를 작성할 수 있습니다.
8. 자주 묻는 질문 (FAQ)
아래는 Java의 contains() 메서드와 관련된 흔히 묻는 질문들로, 까다로운 포인트를 이해하고 일반적인 실수를 피하는 데 도움이 됩니다.
Q1. contains()는 대소문자를 구분하나요?
예, 대소문자를 구분합니다.
예를 들어, "Java".contains("java")는 false를 반환합니다.
해결 방법:
String input = "Welcome to Java";
boolean result = input.toLowerCase().contains("java");
Q2. 정규식을 사용해 부분 매치를 확인하려면 어떻게 해야 하나요?
contains() 정규 표현식을 지원하지 않습니다.
대신 matches() 또는 Pattern 클래스를 사용하세요.
예시 (숫자 패턴 확인):
import java.util.regex.Pattern;
import java.util.regex.Matcher;
String text = "注文番号: A123456";
Pattern pattern = Pattern.compile("A\\d+");
Matcher matcher = pattern.matcher(text);
if (matcher.find()) {
System.out.println("パターンに一致しました。");
}
Q3. contains()를 null에 호출하면 어떻게 되나요?
NullPointerException이 발생합니다.
String target = null;
System.out.println(target.contains("test")); // Error
해결책:
if (target != null && target.contains("test")) {
System.out.println("含まれています。");
}
Q4. 빈 문자열 (“”)을 contains()에 전달하면 어떻게 되나요?
항상 true를 반환합니다.
String text = "Java";
System.out.println(text.contains("")); // true
공식 사양의 일부이지만, 이 동작은 거의 유용하지 않으며 빈 문자열이 의도되지 않은 경우 예상치 못한 버그를 일으킬 수 있습니다.
Q5. contains()가 한 번에 여러 키워드를 검색할 수 있나요?
아니요. 각 호출은 하나의 키워드만 확인합니다.
String text = "本日はシステムエラーが発生しました";
if (text.contains("エラー") || text.contains("障害") || text.contains("失敗")) {
System.out.println("問題が検出されました。");
}
동적 접근 방식:
List<String> keywords = Arrays.asList("エラー", "障害", "失敗");
boolean found = keywords.stream().anyMatch(text::contains);
Q6. contains()와 indexOf()는 언제 사용해야 하나요?
contains()는 boolean을 반환하고, indexOf()는 숫자 인덱스를 반환합니다.
- 단순히 부분 문자열이 존재하는지 확인하고 싶을 때
contains()를 사용합니다. - 위치도 필요할 때는
indexOf()를 사용합니다.String text = "Error: Disk full"; if (text.contains("Error")) { int pos = text.indexOf("Error"); System.out.println("Position: " + pos); }
9. 결론
Java의 contains() 메서드는 특정 부분 문자열이 문자열에 포함되어 있는지 판단하는 강력하고 편리한 도구입니다.
사용자 입력 검증, 로그 분석, 데이터 필터링 등 다양한 상황에서 널리 사용됩니다.
이 글에서는 다음을 다루었습니다:
- 기본 구문 및 반환값
- 대소문자 구분 및 처리 방법
- null 및 빈 문자열 처리
- 다른 문자열 비교 메서드와의 차이점
- 실용적인 사용 사례: 검증, 로그 검색, 스트림 처리
- 성능 고려 사항 및 최적화 기법
- Python, JavaScript, C#와의 비교
- 자주 묻는 질문 및 문제 해결 팁
contains()는 직관적이고 다재다능하지만, 대용량 데이터셋, 빈번한 호출, 복잡한 검색 조건과 같은 경우에는 사용을 신중히 평가해야 합니다.
정규화, 병렬 처리, 정규식, 캐싱 전략을 결합하면 성능과 가독성을 모두 유지할 수 있습니다.
contains()는 Java에서 문자열을 다루는 기본적인 메서드이므로, 이 글이 여러분이 개발 프로젝트에서 보다 안전하고 효율적으로 사용할 수 있게 도움이 되길 바랍니다.

