본문 바로가기
language/java

var 키워드

by 죄니안죄니 2026. 6. 17.
반응형

이제부터는 최신 Java 문법(Java 17+) 시리즈를 시작한다.

첫 번째는 var 키워드이다.

이 글은 단순히 "타입을 생략하는 문법"이 아니라 Java가 왜 var를 도입했고, 언제 사용해야 하는지를 실무 관점에서 설명한다.


var 키워드

var는 새로운 타입이 아니라 컴파일러가 지역 변수(Local Variable)의 타입을 자동으로 추론(Type Inference)하는 문법이다.

(Java 10부터 지원)


Java는 왜 var를 추가했을까?

Java는 오랫동안 이런 코드를 사용했다.

 
Map<String, List<User>> userMap =
        new HashMap<String, List<User>>();
 

변수 이름보다 타입이 더 길다.


Stream를 사용하면 더 심해진다.

 
Map<String, Long> result =
        users.stream()
             .collect(
                 Collectors.groupingBy(
                     User::getDepartment,
                     Collectors.counting()
                 )
             );
 

실제로 개발자는

변수 이름보다 Generic 타입을 읽는 시간이 더 길어졌다.
 

그래서 Java는

컴파일러가 타입을 알 수 있다면 대신 써주자.

라는 개념으로 var를 도입했다.


첫 번째 오해

많은 사람들이

 
var name = "Kim";
 

을 보고

Java도 JavaScript처럼 동적 타입 언어가 된 건가?

라고 생각한다.

절대 아니다.


Java는 여전히 정적 타입 언어이다.

 
var name = "Kim";
 

컴파일러는 내부적으로

 
String name = "Kim";
 

으로 변환한다.


즉,

작성

var name = "Kim";

↓

컴파일

String name = "Kim";

↓

실행
 

이다.


타입은 절대로 변하지 않는다.

 
var name = "Kim";

name = "Lee";
 

가능하다.


하지만

 
var name = "Kim";

name = 100;
 

컴파일 오류이다.

이미

 
String name = "Kim";
 

으로 결정되었기 때문이다.


var는 Object도 아니다.

다음 코드를 보자.

 
var list = List.of("A", "B");
 

많은 사람들이

 
Object list = List.of("A", "B");
 

라고 생각한다.


실제로는

 
List<String> list = List.of("A", "B");
 

이다.


그래서

 
list.add(100);
 

컴파일 단계에서 바로 오류가 발생한다.


var는 어디에서 사용할 수 있을까?

1. 지역 변수

 
public void save() {

    var name = "Kim";

}
 

가능하다.


2. for문

 
for (var i = 0; i < 10; i++) {

}
 

가능하다.


3. 향상된 for문

 
for (var user : users) {

}
 

가능하다.


사용할 수 없는 곳

필드

 
class User {

    var name = "Kim";

}
 

컴파일 오류


메서드 파라미터

 
public void save(var name) {

}
 

컴파일 오류


반환 타입

 
public var findUser() {

}
 

컴파일 오류


null

 
var value = null;
 

컴파일 오류


왜냐하면

null

↓

타입 정보 없음

↓

컴파일러가 추론 불가능
 

이기 때문이다.


Generic과 함께 사용할 때 가장 빛난다.

기존

 
HashMap<String, List<User>> userMap =
        new HashMap<>();
 

var 사용

 
var userMap =
        new HashMap<String, List<User>>();
 

읽기가 훨씬 편하다.


Stream에서도 많이 사용한다.

기존

 
List<User> activeUsers =
        users.stream()
             .filter(User::isActive)
             .toList();
 

var

 
var activeUsers =
        users.stream()
             .filter(User::isActive)
             .toList();
 

코드가 훨씬 간결해진다.


Builder Pattern과도 잘 어울린다.

기존

 
User user =
        User.builder()
            .name("Kim")
            .age(30)
            .build();
 

var

 
var user =
        User.builder()
            .name("Kim")
            .age(30)
            .build();
 

Builder의 반환 타입이 변경되어도 선언부를 수정할 필요가 없다.


하지만 남용하면 안 된다.

다음 코드를 보자.

 
var result = service.execute();
 

여기서

result

↓

User?

Order?

String?

Map?

List?
 

전혀 알 수 없다.


반대로

 
var userMap =
        new HashMap<Long, User>();
 

변수명

+

초기값
 

만 봐도 타입이 명확하다.


Oracle이 권장하는 사용법

Oracle도 var 사용 시

좋은 변수명과 함께 사용할 것

을 권장한다.


좋은 예

 
var activeUsers =
        userRepository.findAll();
 

좋지 않은 예

 
var data =
        service.execute();
 

또는

 
var x = ...
var y = ...
var z = ...
 

실무에서 가장 많이 사용하는 패턴

Collection 생성

 
var userMap =
        new HashMap<Long, User>();
 

Stream 결과

 
var result =
        users.stream()
             .collect(Collectors.toList());
 

Optional

 
var optionalUser =
        repository.findById(id);
 

Builder

 
var order =
        Order.builder()
             .id(1L)
             .build();
 

var를 사용할지 말지 판단하는 기준

좋은 경우

 
var users =
        userRepository.findAll();
 
  • 타입이 명확하다.
  • 코드가 짧아진다.
  • 가독성이 좋아진다.

좋지 않은 경우

 
var value =
        service.execute();
 
  • 타입이 보이지 않는다.
  • IDE 없이는 이해하기 어렵다.
  • 코드 리뷰가 어려워진다.

실무 스타일

대부분의 실무 프로젝트에서는 다음 원칙을 많이 사용한다.

적극적으로 사용

 
var userMap = new HashMap<String, User>();

var users = userRepository.findAll();

var order = Order.builder().build();
 

명시적으로 타입 작성

 
User user = service.findUser();

OrderResponse response = service.save();

List<Product> products = repository.findAll();
 

반환 타입이 비즈니스 의미를 가지는 경우에는 명시적으로 적는 경우가 많다.


면접 포인트

var란?

새로운 타입이 아니라 컴파일러가 지역 변수의 타입을 자동으로 추론하는 문법이다.


var는 동적 타입인가?

아니다.

 
var name = "Kim";
 

은 컴파일 시

 
String name = "Kim";
 

으로 결정되며 이후 타입은 변경되지 않는다.


var의 장점

  • 코드 간결
  • Generic 중복 제거
  • Builder, Stream과 높은 궁합
  • 리팩토링에 유리

var의 단점

  • 타입이 숨겨질 수 있다.
  • 의미 없는 변수명과 함께 사용하면 가독성이 떨어진다.
  • 필드, 파라미터, 반환 타입에는 사용할 수 없다.

다음 글

다음 글은 Text Block(Java 15) 이다.

  • """ 문법이 등장한 이유
  • SQL, JSON, HTML 문자열을 왜 더 읽기 쉽게 만들었는지
  • 들여쓰기(stripIndent) 규칙
  • 실무에서 MyBatis, JPA Native Query, JSON 작성 시 어떻게 활용하는지

를 실무 예제와 함께 자세히 설명하겠다.

반응형

'language > java' 카테고리의 다른 글

Switch Expression(Java 14)  (0) 2026.06.17
Text Block(Java 15)  (0) 2026.06.17
Reflection + Annotation + Proxy + ThreadLocal  (0) 2026.06.16
ThreadLocal Memory Leak  (0) 2026.06.16
ThreadLocal 원리  (0) 2026.06.16

댓글