[Java] Scanner / next() 와 nextLine() 차이를 알아보자.

2021-02-12


Scanner 에는 String을 입력받는 메서드 next()와 nextLine() 이 있는데, 오늘은 이 둘의 차이를 알아보도록 하자.


 - Scanner.next()

package nextLineVsNext;

import java.util.Scanner;

public class Main {

	public static void main(String[] args) {
		
		Scanner scan = new Scanner(System.in);

		String str1 = scan.next();
		// 우선 next의 경우 공백문자를 받아들일 수가 없다.
		// 위와 같이 입력 "a a"와 같은 결과를 주었다고 보자.
		System.out.println("str1 -> " + str1);
	}
}        

 

출력결과를 확인해보면  " a"에서의 '공백'과  'a'는 없고, 처음에 a만 저장되어 출력되는 것을 확인할 수 있다. 여기서 확인 가능한 Scanner의 next는 토큰의 개념으로 문자열을 입력받는데, 해당 토큰에서 공백 문자는 구분자로 인식해 앞에있는 'a'만 저장되는 것이다. 즉 쉽게 말하면 Enter 키는 물론 Space 키도 구분자로 인식하여 저장되지 않는다.


 - Scanner.nextLine()

package nextLineVsNext;

import java.util.Scanner;

public class Main {

	public static void main(String[] args) {
		
		Scanner scan = new Scanner(System.in);
		
        	String str2 = scan.nextLine();
		System.out.println("str2 -> " + str2);
		// 출력결과 공백문자가 포함된 문자열을 입력값으로 
		// 주었음에도 불구하고 모두 저장하여 출력되는 것을 확인할 수 있다.

	}
}

 

그래서 바로 nextLine 메소드가 필요해진다. 메서드 이름에서도 느껴지듯이 공백 문자와 상관없이 콘솔 창 한 줄(Line)에 있으면 모두 문자열로 인식해 String 변수로 리턴한다. 기존에 next()와 마찬가지로 "a a"를 입력값으로 넣어주어 보겠다. 결과를 확인해보면 공백 문자와 상관없이 모두 저장된 것을 확인할 수 있다.



그러면 여기서 궁금증이 생길 수가 있다. 그러면next 말고 nextLine 안 쓰면 되는 거 아니야? 라고 말이다. 메서드가 두 개면 그에 따른 이유가 있다. 아래 예제를 보자. 이번에는 연속해서 next와 nextLine 메서드를 사용해보자 매개변수는 마찬가지로 "a a"를 줄 것이다.

package nextLineVsNext;

import java.util.Scanner;

public class Main {

	public static void main(String[] args) {
		
		Scanner scan = new Scanner(System.in);
		String str1 = scan.next();
		System.out.println("str1 -> " + str1);
		String str2 = scan.nextLine();
		System.out.println("str2 -> " + str2);
		
		// 출력결과
		//a a
		//a
		// a

그럼 위와 같은 요상한 결과가 나오게 된다. 이는 next()로 받고 남은 " a"가 scan.nextLine으로 넘어가기 때문이다. 쉽게 말하면 " a" 라는 버려진 문자열은 지금 버퍼에 남겨져 있는 상태인데, 이와 같은 버퍼를 처리하지 않고 다시 입력을 받을려고 하니, 버퍼측에서는 이미 저장되어 있는 기존에 문자열을 입력도 받기전에 던져버리는 것이다. 때문에 nextLine() 전에 nextXXX와 같은 메서드를 사용했다면 반드시 버퍼를 비워주어야 한다.


 - 버퍼 처리방법

package nextLineVsNext;

import java.util.Scanner;

public class Main {

	public static void main(String[] args) {
		
		Scanner scan = new Scanner(System.in);	
		String str1 = scan.next();
		System.out.println("str1 -> " + str1);
		scan.nextLine();
		String str2 = scan.nextLine();
		System.out.println("str2 -> " + str2);
	
	}
}        

위와 같이 nextLine으로 변수에 담기 전에 nextLine 메서드만 호출해 버퍼를 비워주면 문제없이 다음 입력을 받을 수 있다.


물론 애초부터 String 타입 nextLine으로 받은 뒤 각 변수형에 맞게 Wrapper클래스에 담아 다시 원하는 형태로
형 변환을 해주면 이와 같은 버퍼 문제는 생각하지 않아도 된다. 아래는 그 예이다.

package nextLineVsNext;

import java.util.Scanner;

public class Main {

	public static void main(String[] args) {
		
		Scanner scan = new Scanner(System.in);
		String temp = scan.nextLine();
		int num1 = Integer.parseInt(temp);
		System.out.println("num1 -> " + num1);
		String str2 = scan.nextLine();
		System.out.println("str2 -> " + str2);		
	}
}