자바를 배우다 보면 변수를 만들었는데 사용할 수 없거나, 숫자를 계산했는데 예상과 다른 결과가 나올 때가 있습니다. 이때 자주 만나는 개념이 스코프형변환입니다.

스코프는 변수를 사용할 수 있는 범위입니다. 형변환은 값을 다른 타입으로 바꾸는 과정입니다.

앞에서 변수와 연산자가 아직 헷갈린다면 자바 변수 완전 정리 — 이름표 붙은 보관함으로 이해하기, 자바 연산자 한 번에 정리 — 산술부터 대입까지를 먼저 보고 오는 편이 좋습니다.


1. 스코프란?

스코프는 변수를 사용할 수 있는 범위입니다. 쉽게 말하면 변수가 살아 있는 구역입니다.

자바에서는 중괄호 {}가 스코프를 나누는 중요한 기준이 됩니다.

public class ScopeExample {
    public static void main(String[] args) {
        int outside = 10;

        if (outside > 0) {
            int inside = 20;
            System.out.println(outside);
            System.out.println(inside);
        }

        System.out.println(outside);
    }
}

outsidemain 메서드 안에서 만들어졌기 때문에 main 안에서 사용할 수 있습니다. insideif 블록 안에서 만들어졌기 때문에 if 블록 안에서만 사용할 수 있습니다.


2. 블록 안에서 만든 변수는 밖에서 사용할 수 없습니다

아래 코드는 오류가 납니다.

public class ScopeErrorExample {
    public static void main(String[] args) {
        if (true) {
            int count = 3;
        }

        System.out.println(count); // 오류
    }
}

countif 블록 안에서 만들어졌습니다. 그래서 if 블록이 끝난 뒤에는 사용할 수 없습니다.

이런 구조를 그림으로 보면 다음과 같습니다.

main 블록
├─ if 블록
│  └─ count 사용 가능
└─ if 블록 밖
   └─ count 사용 불가

변수는 자신이 선언된 중괄호 안에서만 살아 있습니다. 중괄호를 벗어나면 그 변수는 더 이상 사용할 수 없습니다.


3. 변수를 필요한 범위에 선언하기

변수는 너무 넓은 범위에 만들기보다, 필요한 곳에 가깝게 선언하는 편이 좋습니다.

public class ScopeGoodExample {
    public static void main(String[] args) {
        int score = 85;

        if (score >= 80) {
            String message = "합격입니다.";
            System.out.println(message);
        }
    }
}

message는 합격일 때만 필요합니다. 그래서 if 블록 안에 선언해도 충분합니다.

반대로 여러 블록에서 함께 써야 하는 값이라면 바깥에 선언해야 합니다.

public class ScopeSharedExample {
    public static void main(String[] args) {
        int score = 85;
        String result;

        if (score >= 80) {
            result = "합격";
        } else {
            result = "불합격";
        }

        System.out.println(result);
    }
}

resultif, else가 끝난 뒤에도 출력해야 합니다. 그래서 if 바깥에 먼저 선언했습니다.


4. 같은 이름의 변수를 다시 만들 수 있을까?

같은 스코프 안에서는 같은 이름의 변수를 다시 선언할 수 없습니다.

int age = 20;
int age = 30; // 오류

이미 age라는 변수가 같은 범위에 있기 때문입니다.

값을 바꾸고 싶다면 다시 선언하는 것이 아니라 대입해야 합니다.

int age = 20;
age = 30;

처음 줄은 변수를 만드는 선언입니다. 두 번째 줄은 이미 있는 변수에 새 값을 넣는 대입입니다.


5. 형변환이란?

형변환은 값을 다른 타입으로 바꾸는 것입니다. 자바에서는 타입이 맞지 않으면 값을 바로 넣을 수 없는 경우가 있습니다.

int count = 10;
double countDouble = count;

위 코드는 가능합니다. int 값인 10double 변수에 넣으면 10.0처럼 더 넓은 타입으로 바뀝니다.

형변환은 크게 두 가지로 볼 수 있습니다.

구분의미예시
자동 형변환자바가 자동으로 타입을 바꿈int에서 double
명시적 형변환개발자가 직접 타입 변환을 지시double에서 int

6. 자동 형변환

자동 형변환은 작은 범위의 타입을 큰 범위의 타입에 넣을 때 일어납니다. 값이 손실될 가능성이 낮기 때문에 자바가 자동으로 처리합니다.

int intValue = 10;
long longValue = intValue;
double doubleValue = intValue;

System.out.println(longValue);   // 10
System.out.println(doubleValue); // 10.0

int보다 long이 더 큰 정수 범위를 가집니다. double은 소수까지 표현할 수 있습니다.

그래서 int 값을 long이나 double에 넣는 것은 자연스럽게 허용됩니다.

int → long → double

이 방향은 더 넓은 그릇으로 옮기는 느낌입니다. 작은 컵의 물을 큰 컵에 옮기는 것과 비슷합니다.


7. 명시적 형변환

반대로 큰 범위의 타입을 작은 범위의 타입에 넣을 때는 자바가 자동으로 처리하지 않습니다. 값이 잘릴 수 있기 때문입니다.

double temperature = 32.8;
int roundedDown = temperature; // 오류

double에는 소수점이 있습니다. 하지만 int는 정수만 저장할 수 있습니다.

이때는 개발자가 직접 형변환을 지시해야 합니다.

double temperature = 32.8;
int roundedDown = (int) temperature;

System.out.println(roundedDown); // 32

(int)는 이 값을 int로 바꾸겠다는 뜻입니다. 다만 소수점 아래 값은 반올림되지 않고 버려집니다.

double value = 9.99;
int result = (int) value;

System.out.println(result); // 9

명시적 형변환은 가능하지만, 값이 손실될 수 있다는 점을 항상 생각해야 합니다.


8. 계산 중 타입은 어떻게 바뀔까

서로 다른 타입끼리 계산하면 더 넓은 타입으로 맞춰지는 경우가 많습니다.

int count = 3;
double price = 2.5;

double total = count * price;
System.out.println(total); // 7.5

countint이고 pricedouble입니다. 계산할 때 int 값이 double 쪽으로 맞춰져서 결과도 double이 됩니다.

정수끼리 계산하면 결과도 정수입니다.

int total = 5;
int people = 2;

System.out.println(total / people); // 2

소수점까지 보고 싶다면 둘 중 하나를 double로 바꿔야 합니다.

int total = 5;
int people = 2;

System.out.println((double) total / people); // 2.5

(double) total로 먼저 바꿨기 때문에 전체 계산 결과도 double이 됩니다.


9. 형변환에서 실수하기 쉬운 부분

형변환은 편리하지만, 값을 잃을 수 있습니다. 특히 아래 상황을 조심해야 합니다.

소수점이 사라지는 경우

double weight = 1.8;
int intWeight = (int) weight;

System.out.println(intWeight); // 1

1.81이 됩니다. 반올림이 아니라 소수점 아래를 버린다는 점이 중요합니다.

너무 큰 값을 작은 타입에 넣는 경우

int big = 1000;
byte small = (byte) big;

System.out.println(small);

byte는 담을 수 있는 범위가 작습니다. 범위를 넘어서는 값을 억지로 넣으면 예상하기 어려운 결과가 나올 수 있습니다.

입문 단계에서는 이런 변환을 일부러 많이 쓸 일은 적습니다. 하지만 작은 타입으로 강제 변환할 때는 값의 범위를 꼭 확인해야 합니다.


10. 직접 풀어볼 예시

스코프와 형변환은 직접 오류를 만나보면 더 빨리 이해됩니다. 아래 예시를 실행하거나 값을 바꿔보면서 확인해보면 좋습니다.

평균을 소수점까지 구하기

public class AverageCastingExample {
    public static void main(String[] args) {
        int korean = 80;
        int english = 75;
        int math = 90;

        int sum = korean + english + math;
        double average = (double) sum / 3;

        System.out.println(sum);     // 245
        System.out.println(average); // 81.66666666666667
    }
}

sum / 3만 쓰면 정수 나눗셈이 됩니다. 그래서 (double) sum으로 먼저 바꾼 뒤 나눴습니다.

블록 안 변수 확인하기

public class ScopePractice {
    public static void main(String[] args) {
        int level = 5;

        if (level >= 5) {
            String title = "초보 탈출";
            System.out.println(title);
        }

        System.out.println(level);
    }
}

levelmain 블록 안에서 사용할 수 있습니다. titleif 블록 안에서만 사용할 수 있습니다.


정리

스코프와 형변환은 자바 코드가 예상대로 동작하게 만드는 기본 개념입니다.

  • 스코프는 변수를 사용할 수 있는 범위입니다.
  • 중괄호 {}는 변수의 사용 범위를 나누는 기준이 됩니다.
  • 블록 안에서 만든 변수는 블록 밖에서 사용할 수 없습니다.
  • 자동 형변환은 작은 타입에서 큰 타입으로 갈 때 주로 일어납니다.
  • 명시적 형변환은 개발자가 직접 (타입)을 적어 변환하는 방식입니다.
  • doubleint로 바꾸면 소수점 아래가 버려집니다.
  • 정수끼리 나누면 결과도 정수입니다.

스코프를 이해하면 변수를 어디에 선언해야 하는지 판단하기 쉬워집니다. 형변환을 이해하면 숫자 계산 결과가 왜 예상과 달라지는지 더 빨리 찾을 수 있습니다.