매일 업데이트
2023-08-20 23:45 12 min

[Fixed] Java에서 "기호를 찾을 수 없음" 오류를 해결하는 방법

자바는 웹, 모바일, 그리고 엔터프라이즈 어플리케이션 개발에 널리 쓰이는, 객체 지향적이고 강력한 타입의 프로그래밍 언어입니다. 썬 마이크로시스템즈에서 개발되었으며 현재는 오라클 코퍼레이션에서 소유하고 있는 자바는 뛰어난 이식성, 확장성, 신뢰성, 그리고 안정성으로 인해 많은 개발자들에게 사랑받는 언어가 되었습니다.

자바 프로그램을 만들 때, 자바 프로그래밍 언어는 먼저 자바 소스 코드를 바이트 코드로 변환합니다. 그다음 이 바이트 코드는 자바 가상 머신(JVM)에 의해 기계어로 해석되어 자바 프로그램이 실행됩니다. 이러한 과정을 거치므로 자바는 컴파일 언어이자 동시에 해석 언어라고 할 수 있습니다.

컴파일 과정은 전체 소스 코드를 한 번에 스캔하여 기계 코드로 번역하는 것을 의미합니다. 반면, 인터프리터는 소스 코드를 한 줄씩 읽어 기계 코드로 변환합니다.

컴파일 시, 컴파일러는 프로그램 내에서 사용되는 모든 식별자 목록을 만듭니다. 자바에서 식별자는 변수, 클래스, 메소드, 패키지, 그리고 인터페이스 등 프로그램의 여러 요소에 할당된 이름입니다.

자바 프로그램을 컴파일하는 과정에서 오류가 발생할 수 있는데, 이를 컴파일 오류 또는 컴파일 시간 오류라고 합니다. 컴파일 오류는 자바 컴파일러가 프로그램의 바이트 코드를 성공적으로 생성하지 못하게 만듭니다.

컴파일 오류가 발생하면 프로그램은 컴파일되지 않습니다. 이러한 오류는 소스 코드의 구문, 의미, 또는 구조적 문제로 인해 발생할 수 있습니다. 컴파일 오류의 대표적인 예시 중 하나가 '기호를 찾을 수 없음' 오류입니다.

오류: 기호를 찾을 수 없음

앞서 언급했듯이, 컴파일 과정에서 자바 컴파일러는 프로그램에서 사용되는 모든 식별자 목록을 만들고 각 식별자의 의미를 파악합니다. 만약 컴파일러가 인식하지 못하는 식별자를 발견하거나, 식별자가 무엇을 참조하는지 알 수 없는 경우 '기호를 찾을 수 없음' 오류가 발생합니다.

'기호를 찾을 수 없음' 오류는 컴파일러가 이해할 수 없는 식별자를 사용하고 있기 때문에, 해당 식별자가 무슨 역할을 해야 하는지 알 수 없다는 것을 나타내는 오류입니다.

이 오류는 사용하려는 식별자가 선언되지 않았거나, 현재 사용 중인 범위 내에서 접근할 수 없거나, 필요한 import 문이 빠져있는 경우에 발생할 수 있습니다. '기호를 찾을 수 없음' 오류가 발생하면 컴파일이 실패하게 됩니다.

오류 원인: 기호를 찾을 수 없음

'기호를 찾을 수 없음' 오류의 주요 원인은 다음과 같습니다:

  • 변수, 메소드, 클래스, 또는 패키지 이름의 철자가 잘못되었거나, 오타가 있는 경우. 자바는 대소문자를 구분하기 때문에 대소문자 오류도 이 문제를 일으킬 수 있습니다.
  • 변수, 메소드, 또는 클래스를 선언하지 않고 사용하거나, 선언하기 전에 사용한 경우.
  • 변수, 메소드, 또는 클래스가 선언된 범위 밖에서 사용된 경우.
  • new 키워드를 사용하지 않고 클래스의 인스턴스를 생성하려고 한 경우.
  • 다른 패키지에 속한 클래스를 사용하려고 할 때 import 문을 누락한 경우. 다른 패키지의 클래스를 사용하기 전에 반드시 import 해야 합니다.
  • 잘못된 패키지를 import 한 경우.

컴파일러가 코드에서 위의 오류들을 감지하면 컴파일을 중지하고 '기호를 찾을 수 없음' 오류를 발생시킵니다.

오류의 예시: 기호를 찾을 수 없음

'기호를 찾을 수 없음' 오류가 발생하는 다양한 원인과 해결 방법을 자세히 알아보기 위해 몇 가지 코드 예시를 살펴보겠습니다.

#1. 오타

변수, 메소드, 클래스, 또는 패키지 이름의 철자가 틀렸거나 잘못된 대소문자를 사용하면 '기호를 찾을 수 없음' 오류가 발생합니다. 아래 코드를 확인해 보세요.

class Test {
  public static void main(String[] args) {
    int even_number = 4;
    System.out.println(even_numbe); // 변수 이름 오타
    System.out.println(Even_number);// 대소문자 오류
    int sum = addnumber(5, 20); // 메소드 이름 오타 및 대소문자 오류
    System.out.println(sum);
  }
  
  public static int addNumbers(int a, int b) {
    int result = a + b;
    return result;
  }
}

위 코드를 컴파일하면 다음과 같은 결과가 나타납니다.

오류를 수정하려면 변수와 메소드 이름을 정확하게 사용해야 합니다. 예시 코드에서는 변수 `even_number`와 메소드 이름 `addNumbers`에 오타가 있거나 대소문자를 잘못 사용했습니다. 이 오류를 수정하려면 아래와 같이 변수와 메소드 이름을 올바르게 사용해야 합니다.

class Test {
  public static void main(String[] args) {
    int even_number = 4;
    System.out.println(even_number); // 올바른 변수 이름과 대소문자 사용
    System.out.println(even_number); // 올바른 변수 이름과 대소문자 사용
    int sum = addNumbers(5, 20); // 올바른 메소드 이름 사용
    System.out.println(sum);
  }

  public static int addNumbers(int a, int b) {
    int result = a + b;
    return result;
  }
}

결과:

4
4
25

#2. 선언되지 않은 변수

변수를 선언하기 전에 사용하거나, 해당 범위 밖에서 변수, 메소드, 그리고 클래스를 사용하면 '기호를 찾을 수 없음' 오류가 발생합니다. 다음 코드를 살펴보세요.

class Test {
  public static void main(String[] args) {
    System.out.println(y); // y는 선언되지 않음
    System.out.println(num); // num은 선언 전에 사용됨
    int num = 4; // num의 선언 및 초기화
    if (num > 3) {
      int x = 2;
    };
    System.out.println(x); // x는 범위 밖에서 사용됨
  }
}

이 코드를 컴파일한 결과는 다음과 같습니다.

이 오류를 해결하려면 프로그램에서 사용되는 모든 변수를 먼저 선언하고, 선언한 후에 사용해야 합니다. 예시에서는 변수 `y`와 `num`이 선언되기 전에 사용되었습니다. 이 오류를 수정하려면 변수를 선언한 후에 사용해야 합니다.

변수 `x`는 선언된 범위 밖에서 사용되었습니다. 이 문제를 수정하려면 아래와 같이 변수를 선언된 `if` 블록 내에서 사용해야 합니다.

class Test {
  public static void main(String[] args) {
    String y = "Hello World";
    System.out.println(y); // y는 선언 후에 사용됨
    int num = 4; 
    System.out.println(num); // num은 선언 후에 사용됨
    
    if (num > 3) {
      int x = 2;
      System.out.println(x); // x는 if문 범위 내에서 사용됨
    };
  }
}

결과:

Hello World
4
2

#3. 범위를 벗어난 변수, 메소드 및 클래스

선언된 범위 밖에서 변수, 메소드, 그리고 클래스를 사용하면, 아래 코드처럼 '기호를 찾을 수 없음' 오류가 나타납니다.

class Test {
  public static void main(String[] args) {
    if (true) {
      int number = 10;
    }
    System.out.println(number); // 'number'는 범위 밖에서 사용됨
  }
}

이 코드를 컴파일하면 다음 오류가 발생합니다.

오류를 수정하려면 변수 `number`를 선언된 범위 내에서 사용해야 합니다. 즉, 아래와 같이 `if` 블록 범위 내에서 사용해야 합니다.

class Test {
  public static void main(String[] args) {
    if (true) {
      int number = 10;
      System.out.println(number); // number는 if 블록 범위 내에서 사용됨
    }
  }
}

결과:

10

#4. new 키워드를 사용하지 않고 클래스의 인스턴스 만들기

자바는 객체 지향 언어이므로 자바 프로그램에서 클래스의 인스턴스, 즉 객체를 생성할 수 있습니다. 하지만 `new` 키워드를 사용하지 않고 객체를 만들려고 하면 '기호를 찾을 수 없음' 오류가 나타납니다.

public class Car {
  private String make;
  private String model;

  public Car(String make, String model) {
    this.make = make;
    this.model = model;
  }

  public String getMake() {
    return make;
  }

  public String getModel() {
    return model;
  }

  public static void main(String[] args) {
    // new를 사용하지 않고 Car 클래스 인스턴스 생성 시도
    Car myCar = Car("Ford", "Fiesta");

    System.out.println("제조사: " + myCar.getMake());
    System.out.println("모델: " + myCar.getModel());
  }
}

이 코드를 컴파일하면 다음과 같은 오류가 발생합니다.

오류를 수정하려면 객체를 생성할 때마다 `new` 키워드를 사용해야 합니다. 자바에서 클래스의 인스턴스를 생성하려면 `new` 키워드가 필수입니다. `Car` 클래스의 인스턴스를 생성하려면 아래와 같이 `new Car()`를 사용해야 합니다.

public class Car {
  private String make;
  private String model;

  public Car(String make, String model) {
    this.make = make;
    this.model = model;
  }

  public String getMake() {
    return make;
  }

  public String getModel() {
    return model;
  }

  public static void main(String[] args) {
    // new 키워드를 사용하여 Car 인스턴스를 올바르게 생성
    Car myCar = new Car("Ford", "Fiesta");

    System.out.println("제조사: " + myCar.getMake());
    System.out.println("모델: " + myCar.getModel());
  }
}

결과:

제조사: Ford
모델: Fiesta

#5. 누락된 import 문

다른 패키지에 있는 클래스를 import 하지 않고 사용하려고 하면 '기호를 찾을 수 없음' 오류가 발생합니다. 아래 코드를 참조해 주세요.

class Test {
  public static void main(String[] args) {
    System.out.println("숫자를 입력하세요:");
    // Scanner 클래스 import 누락
    Scanner scanner = new Scanner(System.in);
    int number = scanner.nextInt();
    System.out.println("입력한 숫자는: " + number);
    scanner.close();
  }
}

위 코드를 컴파일한 결과는 다음과 같습니다.

Scanner 클래스는 자바 프로그램에서 키보드로부터 사용자 입력을 받는 데 사용됩니다. 이 클래스를 사용하려면 먼저 해당 클래스가 정의된 패키지를 import 해야 합니다. Scanner 클래스를 import 하면 아래와 같이 사용할 수 있습니다. import 문은 아래 코드의 첫 번째 줄에 있습니다.

import java.util.Scanner;
class Test {
  public static void main(String[] args) {
    System.out.println("숫자를 입력하세요:");
    // Scanner 클래스 import
    Scanner scanner = new Scanner(System.in);
    int number = scanner.nextInt();
    System.out.println("입력한 숫자는: " + number);
    scanner.close();
  }
}

결과:

숫자를 입력하세요:
45
입력한 숫자는: 45

#6. 잘못된 import 문

사용하려는 패키지를 import 하지 않는 것 외에도 잘못된 패키지를 import 하면 '기호를 찾을 수 없음' 오류가 발생할 수 있습니다. 다음 코드를 살펴보세요.

import java.util.Dates; // 잘못된 패키지 import - 올바른 패키지는 Date
class Test {
  public static void main(String[] args) {
    Dates now = new Dates();
        System.out.println(now);
  }
}

이 코드를 컴파일하면 다음과 같은 오류가 발생합니다.

발생한 '기호를 찾을 수 없음' 오류를 수정하려면 올바른 패키지를 import 해야 합니다. 오류를 발생시킨 코드에서는 `Dates` 클래스를 import 했습니다. 하지만 자바에는 `Dates`라는 내장 클래스가 없습니다. 올바른 클래스 이름은 `Date`입니다. 따라서 오류를 제거하려면 아래와 같이 `Dates`가 아닌 `Date`를 import 해야 합니다.

import java.util.Date; // 올바른 패키지 import - Dates가 아닌 Date
class Test {
  public static void main(String[] args) {
    Date now = new Date();
        System.out.println(now);
  }
}

결과:

Thu Aug 17 12:02:12 EAT 2023

오류의 영향: 컴파일 중 '기호를 찾을 수 없음' 오류

컴파일 오류이므로 '기호를 찾을 수 없음' 오류의 가장 직접적인 영향은 컴파일 프로세스의 실패입니다. 자바가 바이트 코드로 컴파일될 때 소스 코드에서 오류가 발견되면 컴파일 과정은 중단됩니다. 따라서 프로그램 실행에 사용할 수 있는 바이트 코드는 생성되지 않습니다.

이러한 오류가 발생하면 가장 먼저 해야 할 일은 소스 코드 디버깅을 시작하여 오류 원인을 찾고 수정하는 것입니다. 디버깅은 언어에 익숙해지도록 돕는 장점도 있지만, 개발 시간을 지연시킬 수 있습니다. 또한 소스 코드에 오류가 있으면 전체적인 코드 품질에 악영향을 줄 수 있습니다.

결론

'기호를 찾을 수 없음' 오류는 흔하게 발생하는 오류이며, 자바 코드를 작성하면서 마주칠 수밖에 없습니다. 다행히도 이 오류는 비교적 쉽게 피할 수 있습니다. '기호를 찾을 수 없음' 오류는 잘못된 식별자 사용에서 비롯되는 경우가 많습니다. 따라서 오류를 예방하려면 모든 변수, 메소드, 그리고 클래스를 사용하기 전에 반드시 선언했는지 확인해야 합니다.

또한 프로그램에서 사용 중인 식별자를 참조할 때 오타가 없는지 확인하고, 식별자를 선언한 범위 내에서 모든 식별자를 사용해야 합니다. 마지막으로, 프로그램에서 외부 패키지나 클래스를 사용하는 경우 사용하기 전에 올바른 패키지를 프로그램으로 import 해야 합니다.

비즈니스에 적합한 최적의 자바 모니터링 소프트웨어를 찾아보는 것도 도움이 될 수 있습니다.

저자
Korea

기술 트렌드와 실용적인 팁을 전하는 लेखक입니다.