[TIL] 코딩테스트에서 Scanner 대신 BufferedReader를 써야 하는 이유

2025. 9. 6. 16:09·알고리즘

 

 

알고리즘 문제를 풀다 보면 Scanner를 사용하다가 시간 초과를 겪는 경우가 있습니다.

 

테스트케이스에서는 통과했는데 제출하니 시간 초과 ??? 

 

좌측(Scanner 방식), 우측(BufferedReader 방식)

이처럼 입력부만 Scanner -> BufferedReader로 바꾸니 바로 통과되는 경우가 많았는데요 !

 

Scanner는 배우기 쉽고 편하지만, 이처럼 시간초과라는 문제를 초래하기도 합니다.

 

그렇다면, 왜 Scanner 대신 BufferedReader를 사용해야 하고, 

어떻게 사용하는지에 대해 한번 알아보도록 하겠습니다.


1. Scanner vs BufferedReader 비교

구분 Scanner BufferedReader
속도 상대적으로 느림 (정규식 기반 파싱) 빠름 (버퍼 단위 입력)
입력 단위 공백(next()) / 줄(nextLine()) 줄 단위(readLine())
파싱 자동 변환 지원 (정수, 실수 등) 문자열만 반환 → 직접 파싱 필요
코드 난이도 간단 조금 복잡
적합한 경우 소규모 입력, 간단 실습 대규모 입력, 코딩테스트, 파일 입출력

 

쉬운 예시를 통해 살펴보겠습니다.

https://www.acmicpc.net/problem/10818

 

 

Scanner 동작 방식

1. 첫 줄 5 읽기 : nextInt() 호출

- 내부에서 정규식 검사(정수인지) -> 정수 변환

2. 두 번째 줄 "20 10 35 30 7" 읽기 : nextInt() 5번 호출

- 호출할 때마다 정규식 검사 -> 정수 변환

즉, 숫자 하나 읽을 때마다 정규식을 돌려서 시간과 메모리 낭비가 발생합니다.

 

BufferedReader 동작 방식

1. 첫 줄 5 읽기 : Integer.parseInt("5")

2. 두 번째 줄 "20 10 35 30 7" 통째로 읽기

3. StringTokenizer로 20, 10, 35, 30, 7 분리

4. 정수로 변환 후 배열 저장

즉, 한 줄을 통째로 읽어 처리하므로 시간과 메모리 낭비를 줄일 수 있습니다.

 

2. BufferedReader 원리

- 데이터를 8KB(8192 byte) 버퍼에 먼저 모아둡니다.

- 프로그램에서 readLinke()을 호출하면, 이미 버퍼에 쌓여있는 데이터를 줄 단위로 꺼냅니다. (정규식 검사 XX)

- 정규식 검사가 없고, 문자열만 반환하기 때문에 원하는 타입으로 변환은 직접 수행해야 합니다. (Integer.parseInt 등)

- 대신, 대용량 입력일수록 훨씬 빠르게 처리할 수 있습니다.

 

버퍼(Buffer)의 개념

버퍼는 데이터를 임시로 저장하는 중간 창고입니다.
입출력 장치는 CPU보다 느리기 때문에, 버퍼에 데이터를 모았다가 한꺼번에 전달하면 호출 횟수가 줄어들어 속도가 빨라집니다.

 

3. BufferedReader 기본 사용법

import java.io.*;
import java.util.*;

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        // 한 줄 입력
        String line = br.readLine();
        System.out.println(line);

        // 공백 단위 입력
        StringTokenizer st = new StringTokenizer(br.readLine());
        int a = Integer.parseInt(st.nextToken());
        int b = Integer.parseInt(st.nextToken());
        System.out.println(a + b);

        br.close();
    }
}

- readLine() : 한 줄 통째로 문자열 반환

- StringTokenizer : 문자열 공백 단위 분리

- Integer.parseInt() : 정수 변환

Tip. 입력이 여러 줄에 걸쳐 들어오는 경우
while (!st.hasMoreTokens()) st = new StringTokenizer(br.readLine());​
이러한 패턴으로 토큰 고갈 대비를 해주면 안전합니다.

 

4. 출력 최적화: BufferedWriter

입력이 많을 때뿐 아니라 출력도 많다면 System.out.println 대신 BufferedWriter를 씁니다.

BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
for (int i = 1; i <= 10; i++) {
    bw.write(i + "\n");
}
bw.flush();
bw.close();

 

출력 내용을 버퍼에 모았다가 flush()로 한 번에 내보내기 때문에 대량 출력 시 효율적입니다.

 

5. 알고리즘에서 자주 쓰는 패턴

간단한 문제들을 통해 자주 쓰는 패턴에 대해 살펴보겠습니다 !

 

정수 1개 입력 https://www.acmicpc.net/problem/10818

int n = Integer.parseInt(br.readLine());

 

정수 여러 개 입력 https://www.acmicpc.net/problem/10871

StringTokenizer st = new StringTokenizer(br.readLine());
int a = Integer.parseInt(st.nextToken());
int b = Integer.parseInt(st.nextToken());

 

정수 배열 입력 https://www.acmicpc.net/problem/10807

int n = Integer.parseInt(br.readLine());
int[] arr = new int[n];
StringTokenizer st = new StringTokenizer(br.readLine());
for (int i = 0; i < n; i++) arr[i] = Integer.parseInt(st.nextToken());

 

 

2차원 배열 입력 https://www.acmicpc.net/problem/10810

StringTokenizer st = new StringTokenizer(br.readLine());
int n = Integer.parseInt(st.nextToken());
int m = Integer.parseInt(st.nextToken());
int[][] arr = new int[n][m];
for (int i = 0; i < n; i++) {
    st = new StringTokenizer(br.readLine());
    for (int j = 0; j < m; j++) {
        arr[i][j] = Integer.parseInt(st.nextToken());
    }
}

 

대량 출력 https://www.acmicpc.net/problem/15552

BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
for (int i = 1; i <= 100; i++) bw.write(i + "\n");
bw.flush();
bw.close();

 

6. Scanner → BufferedReader 변환 예시

 

마무리

- Scanner : 쉽고 간편하지만 대량 입력에서는 정규식 비용으로 느려짐
- BufferedReader: 직접 파싱이 필요하지만 훨씬 빠르며 코테 표준
- BufferedWriter: 출력이 많을수록 효과가 큼

 

따라서 알고리즘 문제에서는 BufferedReader + StringTokenizer + BufferedWriter 조합을 기본 템플릿으로 삼는 것이 가장 효율적입니다.

 

이제는 BufferedReader를 습관화해 시간 초과 걱정 없이 더 빠르게 문제를 풀어보세요 !

 

'알고리즘' 카테고리의 다른 글

알고리즘을 공부하면서 깨달은 점.zip  (1) 2025.11.24
[TIL] 알고리즘 BFS & DFS 정리  (0) 2025.09.23
알고리즘 공부 정리  (3) 2025.08.29
조합과 순열 : 개념부터 구현 방식까지 정리  (0) 2025.05.05
자바 문자열 핵심 정리  (0) 2025.03.22
'알고리즘' 카테고리의 다른 글
  • 알고리즘을 공부하면서 깨달은 점.zip
  • [TIL] 알고리즘 BFS & DFS 정리
  • 알고리즘 공부 정리
  • 조합과 순열 : 개념부터 구현 방식까지 정리
uoaheu
uoaheu
uoaheu 님의 블로그 입니다.
  • uoaheu
    uoaheu 님의 블로그
    uoaheu
  • 전체
    오늘
    어제
    • 분류 전체보기 (50)
      • 알고리즘 (7)
      • CS (9)
      • FRONTEND (9)
        • React (12)
        • Kotlin (1)
        • JS (5)
        • HTML (2)
      • SQL (2)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    멀티캠퍼스it부트캠프
    유레카3기
    토스 uiux
    엘지유플러스유레카프론트엔드
    토스분석
    토스 앱 분석
    mysql 피벗테이블
    부트캠프후기
    혼자서 공부하는 네트워크
    알고리즘
    mysql
    useactionstate
    toss 분석
    BFS
    boj25418
    mysql로 피벗테이블만들기
    이더넷프레임
    toss uiux
    리액트usestate
    백준1926번
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
uoaheu
[TIL] 코딩테스트에서 Scanner 대신 BufferedReader를 써야 하는 이유
상단으로

티스토리툴바