문제 분류 수업 진도 대회 채점현황 순위 질문게시판
게임
스도쿠 타이핑 리듬 타자게임 타이핑 테트리스 타이핑 인베이더 타이핑 지뢰찾기 8192 공룡게임 타이핑 플래피버드 랭킹
로그인
← 수업 목록
▶ 슬라이드 시작

출력과 입력

수업 목표

  • 컴퓨터가 화면에 정보를 보여주는 원리(출력)를 이해하고 자유롭게 제어할 수 있다.
  • 사용자가 입력한 정보를 변수에 담아 프로그램에서 활용하는 방법(입력)을 설명할 수 있다.
  • 한 줄에 뭉쳐서 들어오는 데이터를 쪼개고 원하는 형태로 한 번에 변환할 수 있다.

왜 배워야 할까요?

컴퓨터가 아무리 뛰어난 인공지능이고 슈퍼컴퓨터라 하더라도, 우리가 원하는 것을 말해주지 못하고(입력) 컴퓨터의 대답을 듣지 못한다면(출력) 아무 일도 할 수 없습니다. 이 수업을 통해 컴퓨터에게 명령을 내리고 결과를 돌려받는 진짜 프로그래밍의 첫 대화 창구를 열게 됩니다.


생각해보기: 자판기와의 대화

우리가 일상에서 마주치는 자판기를 떠올려 봅시다. 자판기는 평소 화면에 "음료를 선택하세요"라는 메시지를 띄우며 우리에게 말을 건넵니다. 우리는 동전을 넣고 원하는 음료 버튼을 누릅니다. 자판기는 우리가 입력한 정보(금액과 선택한 음료)를 읽어 들여 계산한 뒤, 맛있는 음료수를 아래로 떨어뜨려 줍니다.

스마트폰 앱, 게임, 웹사이트 등 세상의 모든 프로그램은 결국 이 자판기와 같습니다. 컴퓨터가 사람에게 화면으로 정보를 보여주는 행위를 출력(Output)이라 하고, 사람이 컴퓨터에게 키보드나 마우스로 정보를 전달하는 행위를 입력(Input)이라고 합니다. 파이썬을 활용해 컴퓨터와 주고받는 첫 대화의 규칙을 알아봅시다.


1. print() — 컴퓨터가 화면에 말하는 방법

컴퓨터가 들고 있는 데이터나 계산 결과를 모니터 화면에 시각적으로 나타낼 때는 print() 함수를 사용합니다. 괄호 안에 출력하고 싶은 값을 적어주면 됩니다.

print("Hello, World!")    # 글자(문자열) 출력: 반드시 따옴표로 감싸기
print(100)                 # 숫자(정수) 출력
print(3.14)                # 실수 출력

여러 개의 값을 한꺼번에 출력하고 싶을 때는 쉼표(,)로 연결하여 나열합니다. 쉼표로 연결된 값들 사이에는 컴퓨터가 알아서 빈칸을 한 칸씩 띄워 줍니다.

print("이름:", "홍길동")   # 출력결과: 이름: 홍길동
print("점수:", 100, "점")  # 출력결과: 점수: 100 점

출력 형식을 세밀하게 조절하기 (sep와 end)

출력되는 모양을 우리가 원하는 대로 다듬기 위해 print() 안에 추가 옵션을 지정할 수 있습니다. 초심자들이 가장 헷갈려하는 두 옵션의 핵심 차이는 다음과 같습니다.

  • sep (구분자): 값과 값 사이의 연결 고리입니다. 쉼표로 구분된 여러 개의 값을 출력할 때, 값들 사이사이에 끼워 넣을 문자를 지정합니다. (기본값은 빈칸 한 칸 " "입니다.)
  • end (끝 문자): 자동 엔터(줄바꿈) 대신 붙일 마지막 문자입니다. 파이썬의 print()는 값을 화면에 띄운 후 항상 자동으로 줄을 바꿉니다(엔터를 칩니다). 하지만 end 옵션을 쓰면 자동 엔터를 취소하고, 줄바꿈 대신 우리가 지정한 다른 문자(예: 공백이나 단어 등)를 끝에 붙인 뒤 다음 출력 내용이 그 자리에 바로 이어서 출력되도록 합니다.

한눈에 비교하는 작동 원리

동일한 값을 사용했을 때 두 옵션이 적용되는 위치의 차이를 확인해 봅시다.

# 1. sep는 값들 '사이'에만 들어갑니다. (끝에는 들어가지 않음)
print("사과", "배", "감", sep=" 와 ")
# 출력결과: 사과 와 배 와 감

# 2. end는 출력이 끝난 지점에 자동 엔터(줄바꿈) 대신 들어갑니다.
print("사과", "배", "감", end=" 와 ")
print("귤")
# 출력결과: 사과 배 감 와 귤 (줄바꿈 없이 바로 뒤에 '귤'이 이어져서 출력됨)

f-string: 문장 사이에 변수 부드럽게 끼워넣기

글자와 변수를 복잡하게 쉼표로 이어 붙이는 대신, 하나의 문장 안에 자연스럽게 변수 값을 채워 넣는 기법입니다. 문자열 따옴표 바로 앞에 f를 쓰고, 변수가 들어갈 자리를 중괄호 { }로 감싸 줍니다.

name = "홍길동"
score = 98

print(f"안녕하세요, {name}님. 이번 성적은 {score}점입니다.")
# 출력결과: 안녕하세요, 홍길동님. 이번 성적은 98점입니다.

f-string을 사용하는 이유와 장점

  • 높은 코드 가독성: 쉼표(,)나 더하기(+) 연산자로 여러 글자와 변수를 번잡하게 이어 붙이지 않고, 완성될 최종 문장의 형태를 그대로 유지하면서 작성할 수 있어 코드가 한눈에 들어옵니다.
  • 편리한 자동 변환: 숫자를 결합할 때 str(score)처럼 매번 문자로 바꾸는 번거로운 형변환 과정을 거칠 필요가 없이, 중괄호 내부에 변수만 넣으면 파이썬이 알아서 문자 형태로 바꾸어 자연스럽게 결합해 줍니다.
  • 간편한 실시간 연산: 중괄호 { } 안쪽에서 간단한 계산식(예: {score + 5})을 즉석에서 처리하여 바로 출력에 반영할 수 있습니다.

2. input() — 컴퓨터가 사람의 말을 듣는 방법

대화를 하려면 듣는 과정도 필요합니다. input() 함수는 쌩쌩 실행되던 프로그램을 일시 정지시키고 사용자가 키보드로 무언가를 타이핑한 뒤 엔터(Enter) 키를 누를 때까지 기다리게 만듭니다.

user_input = input("이름을 입력하세요: ")
print(f"안녕하세요, {user_input}님!")

괄호 안에 적은 문자열은 사용자가 값을 입력하기 전에 띄워 주는 안내 창 역할을 합니다. 단, 온라인 저지(OJ) 환경에서는 출력 형식을 엄격하게 대조하므로 이 안내 문구가 출력에 섞이면 오답 처리가 됩니다. 따라서 온라인 저지 문제를 풀 때는 안내 문구 없이 input()만 작성하여 입력을 받습니다.

컴퓨터의 안전 규칙: 모든 입력은 일단 문자열(str)

사용자가 키보드로 숫자 5를 입력하더라도, 컴퓨터는 이를 수학 계산을 할 수 없는 문자열인 "5"로 인식합니다. 사용자가 입력할 데이터가 숫자인지, 주소인지, 영문 이름인지 미리 알 수 없기 때문에 가장 안전한 글자 형태로 통일하여 받는 것입니다.
따라서 이 데이터를 진짜 숫자로 다루어 덧셈이나 곱셈을 하려면, 문자열을 정수(int)나 실수(float)로 바꾸어 주는 형변환 작업이 꼭 필요합니다.

참고: 다른 언어와 파이썬의 타입 명시 차이
C, C++, Java와 같은 정적 타입 언어에서는 변수를 만들 때 int age = 20;처럼 타입을 컴퓨터에게 명확하게 먼저 가르쳐주어야 합니다. 만약 정수형 변수에 문자열을 넣으려고 하면 컴파일 과정에서 오류가 발생합니다.
반면 파이썬은 변수의 타입을 미리 지정하지 않고 대입하는 값에 맞춰 실행 중에 결정(동적 타입)하지만, 파이썬 역시 코드의 가독성을 높이고 실수를 방지하기 위해 명시적으로 타입을 적어두는 타입 힌팅(Type Hinting)을 지원합니다.

# 파이썬에서 변수 타입을 명시(타입 힌팅)하는 방법
age: int = 20
name: str = "홍길동"

# 함수의 매개변수와 반환값의 타입을 명시할 수 있습니다.
def add(a: int, b: int) -> int:
    return a + b
# 글자 형태로 들어온 입력을 int()로 감싸 진짜 정수로 바꿉니다.
n = int(input())
print(f"입력한 수의 3배는 {n * 3}입니다.")

3. 한 줄로 뭉쳐서 유입되는 데이터 처리하기

대부분의 알고리즘 문제에서는 10 20처럼 여러 개의 데이터가 한 줄에 공백(스페이스바)을 사이에 두고 한꺼번에 주어집니다. 이 데이터를 각각 쪼개서 원하는 데이터 타입으로 한 번에 변환하여 변수에 담을 때 split()과 map() 함수를 함께 사용합니다.

split() — 공백을 기준으로 문자열 쪼개기

split() 함수는 문자열을 특정 기준(기본값은 공백, 탭, 줄바꿈 등)에 따라 조각조각 잘라내어 리스트 형태로 만들어 줍니다. 사용자가 한 줄에 여러 값을 띄어쓰기로 입력했을 때 이를 나누는 첫 단계입니다.

# "홍길동 95"를 입력받아 공백을 기준으로 자릅니다.
name, score = input().split()
# name 에는 "홍길동"이, score 에는 "95"가 각각 문자열 형태로 대입됩니다.

map() — 여러 데이터에 한꺼번에 형변환 함수 적용하기

split()으로 쪼개서 얻은 조각들은 컴퓨터 입장에서 여전히 글자(문자열) 상태입니다. 이 조각들로 사칙연산을 하려면 하나하나 int()나 float()를 적용해 주어야 하는데, 데이터가 많아질수록 코드가 매우 길어지고 복잡해집니다.
이때 map() 함수를 사용하면 쪼개진 값들에 지정한 함수를 일괄 적용하여 한 번에 원하는 형태의 변수로 변환할 수 있습니다.

map() 함수의 기본 구조:

map(적용할_함수, 대상_데이터)

첫 번째 매개변수에는 적용하고자 하는 변환 기능(예: int, float 등)을 적고, 두 번째 매개변수에는 쪼개진 데이터(예: input().split())를 제공합니다. 이 때 적용할 함수 뒤에 괄호 ()를 붙이지 않고 이름만 적어야 합니다.

가장 헷갈리는 부분: 왜 int()가 아니라 int로 적어야 할까요?

파이썬에서 함수 이름 뒤에 괄호 ()를 붙이는 것은 "지금 즉시 이 함수를 실행하라"는 명령입니다. 만약 map(int(), ...)과 같이 괄호를 붙여서 작성하면, 파이썬은 map이 작동하기도 전에 int()를 먼저 실행해 버립니다. 괄호 안에 아무것도 없는 int()는 실행 결과로 숫자 0을 반환하므로, 결국 map(0, ...)과 같이 실행되어 에러가 발생하게 됩니다.

반면, 괄호 없이 int라고만 이름만 적어주면, 함수를 당장 실행하는 것이 아니라 "정수로 바꾸는 공식(함수 자체)"을 map에게 통째로 넘겨주는 것이 됩니다. 마치 일꾼에게 완성된 주스가 아니라 "주스를 만드는 레시피"를 건네주는 것과 같습니다. 레시피를 받은 map 함수는 나중에 들어오는 데이터를 만날 때마다 이 레시피를 꺼내서 정수로 바꾸어 줍니다.

작동 흐름 예시:

# 사용자가 "3 5"를 입력했다고 가정합니다.
a, b = map(int, input().split())

# 내부적인 작동 순서:
# 1. input()이 "3 5"를 문자열로 가져옵니다.
# 2. split()이 공백을 기준으로 ["3", "5"] 문자열 리스트로 쪼갭니다.
# 3. map이 각 조각에 int 함수(레시피)를 일괄 적용하여 숫자 3과 5로 만듭니다.
# 4. 등호(=)를 통해 변수 a에는 정수 3이, b에는 정수 5가 각각 분배 대입됩니다.

print(a + b)  # 출력결과: 8 (정상적인 정수 덧셈 연산 완료)

4. 자주 하는 입출력 실수와 예방

문자열 덧셈과 숫자 덧셈의 혼동
파이썬에서 문자끼리 더하면 풀처럼 이어 붙여지고, 숫자끼리 더해야 덧셈이 됩니다. 형변환의 시점을 놓치지 마세요.

a = "3"
b = "5"
print(a + b)           # 출력결과: 35 (문자 연결)
print(int(a) + int(b)) # 출력결과: 8  (정수 덧셈)

한 줄 입력을 여러 줄로 나누어 받기
데이터가 한 줄에 10 20 형태로 공백을 두고 동시에 제공되는데, input()을 줄별로 두 번 사용하면 프로그램이 대기 상태에 머무르며 다음 입력을 무한정 기다리게 되어 런타임 에러나 시간 초과가 발생합니다.

# 잘못된 예 (두 줄의 입력을 기다리는 구조)
a = input()
b = input()

# 올바른 예 (한 줄을 받아서 공백으로 분할)
a, b = input().split()

map() 객체를 그대로 출력할 때의 오류
map() 함수의 반환값은 우리가 바로 열어볼 수 있는 리스트가 아니라, 내부적으로 값을 보관하고 있는 특수한 map 객체입니다. 따라서 이를 그대로 print()로 출력하면 원하는 값 목록 대신 이상한 메모리 주소가 출력됩니다.

# 잘못된 예: 변수 하나에 그대로 담아 출력할 때
numbers = map(int, input().split())
print(numbers)
# 출력결과 예시: <map object at 0x7f88bc110> (메모리 주소 출력)

# 올바른 예: list() 함수를 씌워 실제 리스트로 변환한 후 출력해야 합니다
numbers = list(map(int, input().split()))
print(numbers)
# 출력결과: [10, 20, 30] (실제 리스트 값들 출력)

그렇다면 a, b = map(int, input().split())은 왜 list() 없이도 잘 작동할까요?
이것은 파이썬의 다중 대입(언패킹, Unpacking)이라는 특별한 기능 덕분입니다.
좌변에 a, b처럼 여러 개의 변수를 나열하면, 파이썬은 우변의 map 객체 안에서 값을 순서대로 하나씩 꺼내서 a와 b에 자동으로 나누어 담아줍니다. 따라서 이 경우에는 굳이 list()로 감싸지 않아도 에러 없이 각 변수에 정수 값이 쏙쏙 들어갑니다.
요약하자면, 여러 변수에 나누어 담을 때는 list()가 필요 없고, 하나의 변수에 전체 목록을 통째로 담고 싶을 때만 list()를 사용하면 됩니다.


5. 온라인 저지(OJ) 실전 입력 공식

출제되는 문제의 입력 형태를 보고 그대로 적용할 수 있는 기본 코드 조합들입니다.

# 1. 하나의 정수만 입력받을 때
n = int(input())

# 2. 한 줄에 나열된 두 개의 정수를 각각 나누어 받을 때
a, b = map(int, input().split())

# 3. 한 줄에 나열된 여러 개의 정수를 하나의 리스트에 모아 담을 때
numbers = list(map(int, input().split()))

# 4. 첫 줄에 N(데이터 개수)이 주어지고, 그 다음 N줄 동안 값을 한 줄씩 입력받을 때
n = int(input())
for _ in range(n):
    data = int(input())

핵심 요약

도구 역할 기억할 약속
print() 데이터를 화면에 시각적으로 출력합니다. 글자는 따옴표 필수, sep/end 옵션으로 변경 가능.
input() 키보드 입력을 받아옵니다. 받아온 값은 무조건 문자열(str) 상태로 취급됨.
int() / float() 데이터의 타입을 숫자(정수/실수)로 바꿉니다. 사칙연산을 진행하기 전 필수 관문.
split() 긴 문자열을 공백 단위로 쪼갭니다. 나누어진 값들은 여전히 문자열 상태임.
map() 나누어진 값들에 일괄적으로 연산을 적용합니다. map(int, input().split()) 형태로 결합하여 사용.

이번 주 대회 바로가기

1반  |  2반  |  3반  |  4반  |  5반  |  6반  |  7반  |  8반  |  9반

※ 대회 링크는 선생님이 별도 공지합니다.

NOTICE  —  BFStudy OJ 정보샘
애들아, 문제 많이 풀고 게임 잠깐 하는거지?
— 정보샘