컴퓨터 프로그래밍을 스스로 하게 되면 컴퓨터를 단순히 사용하는 것을 넘어 제어하는 방법을 배우게 된다. 또한 프로그래밍을 할 수록 더 창의적이 되며, 더 정확하게 생각하게 되고, 문제를 논리적으로 분석하고 해결하는 능력도 배양하게 된다.
그런데 프로그래밍을 하려면 어떻게 해야 하는가? 카카오톡, 트위터, 페이스북과 같은 소프트웨어를 구현하려면 무엇을 어떻게 배워야 하는가? 물론 처음부터 언급된 위대한 앱들을 프로그래밍할 수는 없다. 하지만 그러한 앱들을 구현하기 위해서는 프로그래밍을 제대로 할 수 있어야 한다. 결국, 프로그래밍을 먼저 배워야 한다. 쉽고 간단한 것부터 시작해보자.
파이썬은 고수준(high-level) 프로그래밍 언어이다. 즉, 프로그램 코드 작성에 사용되는 언어가 일반 언어와 상당히 유사하며, 따라서 기본 규칙만 이해하면 작성된 프로그램 코드의 의미를 어렵지 않게 이해할 수 있다.
아래 파이썬 코드의 의미를 알아보자. 찬찬히 읽으면 파이썬 언어를 전혀 모른다 해도 의미를 어느정도 이해할 수 있다.
print("숫자맞히기 게임에 환영합니다.")
secret = 9
guess = int(input("0부터 20 사이의 숫자 하나를 입력하세요: "))
if guess == secret:
print("맞았습니다!")
else:
print("틀렸습니다!")
print("게임 종료!")
위 코드를 설명하면 다음과 같다.
if
, else
secret
, guess
int
, input
, print
int
의 의미만 불확실할 것이며 다른 것들은 의미가 명확하다.앞서 살펴본 예제 코드와 같은 것을 소스코드(source code)라 부른다. 즉, 소스코드는 특정 프로그래밍 언어가 제공하는 명령문들을 조합한 결과물이다.
명령문은 소스코드의 구성요소들이다. 소스코드 자체 또한 하나의 명령문이다. 명령문은 보다 작은 크기의 다른 명령문으로 구성되며, 프로그래밍 언어의 기본은 명령문 작성법이다. 한국어, 영어 등 일반 언어의 문장을 작성할 때 지켜야 하는 문법과 동일한 기능을 수행한다.
코드는 소스코드 아니면 소스코드의 일부분, 즉, 특정 명령문을 가리키는 의미로 사용된다.
반면에 프로그램(program)은 사용자가 용도에 따라 바로 실행할 수 있도록 구현된 소스코드를 이용하여 만든 일종의 상품이다. 하지만 프로그램과 소스코드를 특별히 구분하지 않고 사용하기도 한다.
카카오톡, 페이스북, 트위터 등이 모두 특정 기능을 수행하는 프로그램이다. 이런 프로그램을 통틀어 소프트웨어(software)라고 부른다. 특정 프로그램의 소스코드는 개발자 또는 개발회사의 정책에 따라 비공개되기도 한다. 반면에 오픈소스는 프로그램의 소스코드가 공개되어 특정 조건에 따라 누구나 활용할 수 있도록 공개된 소스코드를 의미한다. 관련된 이야기는 오픈소스 시작하기를 참고할 수 있다.
주의: 반면에 하드웨어(hardware)는 컴퓨터, 제어장치 등 소프트웨어를 실행하는 기계를 의미한다.
하지만 소스코드는 실행되기 전까지는 아무런 일도 하지 않는다. 그리고 작성된 소스코드가 의도한 대로 작동하는지를 확인하려면 실행해 보아야 한다. 따라서 어떻게 소스코드를 실행하는지 알아야 한다.
소스코드와 프로그램의 실행은 여러 요소에 의존한다.
파이썬은 소스코드를 바로 실행시킬 수 있다. 물론 파이썬 언어를 컴퓨터 CPU가 바로 이해하지는 못한다. 따라서 파이썬 소스코드를 컴퓨터가 이해할 수 있는 언어로 해석을 해주어야 하는 데, 이 기능을 수행하는 것을 해석기(인터프리터)라고 한다. 즉, 파이썬 언어는 해석기를 이용하여 소스코드의 의미를 CPU에 전달하며, CPU는 전달된 내용을 바로 실행한다.
이와같이 작동하는 프로그래밍 언어를 스크립트 언어라고 부른다. 파이썬과 같은 스크립트 언어로 작성된 소스코드는 한줄한줄 실행할 수 있다. 예를 들어 위 코드의 처음 몇 줄을 따로따로 실행하면 다음과 같다.
print("숫자맞히기 게임에 환영합니다.")
print
함수: 지정된 문장을 화면에 출력한다.guess = int(input("0부터 20 사이의 숫자 하나를 입력하세요: "))
input
함수: 키보드를 이용하여 입력받은 문장을 전달한다.
키보드에서 예를 들어, 숫자 1과 7에 해당하는 키을 누르면
input
함수는 숫자기호 1과 8로 이루어진 문장인 '18'
을 int
함수의 인자로 전달한다.
이렇게 기호들로 이루어진 이루어진 문장을 문자열이라 부른다.int
함수: 숫자기호로만 이루어진 문장을 진짜 숫자로 변환한다.
즉, input
이 넘겨준 문자열을 진자 숫자로 변환한다.
하지만 숫자가 아닌 다른 기호가 포함되어 있으면 오류(error)가 발생한다.int(input())
: int
함수와 input
함수의 합성이다.
즉, input
함수가 변환한 값을 int
함수가 받아 처리한다. guess
변수: int
함수가 변환한 값을 가리킨다.숫자기호 1과 7로 이루어진 문자열 '17'
은 정수가 아니다.
예를 들어 연산이 작동하지 않는다.
'17' + 3
숫자맞히기 게임 소스코드에 사용된 요소들 중에
secret
와 guess
는 변수이다.
변수(variable)은 특정 값을 가리키는 이름이다. 파이썬 지정자(keyword)를 사용하면 안된다거나, 숫자로 시작하면 안된다 는 등의 몇 가지 제한규칙이 있지만 변수 이름은 임의로 지을 수 있다.
변수를 사용하고자 할 때는 먼저 변수가 가리키는 값을 지정해야 한다. 이렇게 변수가 가리키는 값을 지정하는 과정을 변수 할당이라 하며, 변수 할당을 통해 변수 선언이 이루어진다.
예를 들어, secret
변수의 선언은 아래 방식으로 이루어졌다.
secret = 9
주의: 변수가 가리키는 값은 프로그램 실행과정에서 달라질 수 있다. (아래 "프로그램 업그레이드 3" 부분 참조할 것.)
파이썬에서 다루는 대상은 모두 특정 자료형(datatype)을 갖는다.
예를 들어 숫자기호 1과 7로 이루어진 '17'
은 문자열 자료형이다.
문자열 자료형은 작은 인용부호 '
또는 큰 인용부호 "
감싸인다.
주의: 작은 인용부호로만 감싸거나 큰 인용부호로만 문자열을 감싸야 한다.
반면에 숫자 17은 정수형 자료형이다. 파이썬에서 제공하는 기본 자료형은 다음과 같다.
str
: 문자와 문자열int
: 정수float
: 부동소수점(실수)bool
: 진리값(부울)list
: 리스트tuple
: 튜플dict
: 사전자료형을 확인하려면 type
함수를 이용한다.
type('17')
type(17)
주의: int
는 함수일 수도 있고 정수들의 자료형을 가리킬 수도 있다.
하지만 코드에 포함되면 무조건 함수로 이해해야 한다.
type(3.14)
함수 역시 사용되는 인자들의 자료형에 민감하다.
예를 들어, int
함수는 정수로 변환될 수 있는 문자열만 처리할 수 있다.
입력값이 실수 모양의 문자열이거나 다른 종류의 문자열이면 오류가 발생한다.
int("113")
int("11.3")
int("abc")
주어진 두 값이 동일한 값을 나타내는지 여부를 판단하는 것을 동치비교라 한다.
파이썬은 동치비교를 위해 ==
로 표기된느 동치비교 연산자를 제공한다.
예를 들어, 숫자 17과 문자열 15+2는 서로 다른 값이며, 따라서 동치비료를 하면 참(True
)으로 판명한다.
17 == 15 + 2
동치비교는 동일한 자료형을 갖는 값에 대해서만 작동한다.
예를 들어, 숫자 17과 문자열 "17"
은 서로 다른 자료형이기에 동치비교를 하면 거짓(False
)으로 판명한다.
17 == "17"
True
와 False
는 각각 참과 거짓을 나타내는 값이다.
True
와 False
두 개의 값으로만 구성된 자료형을 부울(bool
) 자료형이라 부른다.
type(True)
type(False)
17 == 15 + 2
는 따라서 True
와 동일한 값을 나타낸다.
(17 == 15 + 2) == True
반면에 17 == "17"
은 False
와 동일한 값을 나타낸다.
(17 == "17") == False
특정 조건의 성립여부에 따라 다른 일을 실행하게 만드는 명령문을 조건 제어문이라 부른다. 숫자 맞추기 게임에서 사용된 조건 제어문은 아래와 같다.
if guess == secret:
print("맞았습니다!")
else:
print("틀렸습니다!")
즉, guess
변수가 가리키는 사용자 입력값과 secret
변수가 가리키는 맞춰야 하는 값의
동일여부에 따라 다른 일을 실행한다.
조건 제어문의 일반적인 형식은 다음과 같다.
if 조건식:
명령문1
else:
명령문2
명령문1
과 명령문2
는 각각 if
와 else
의 본체(body)라 부른다.else
명령문은 생략 가능.앞서 설명한 것과 같이 소스코드를 한줄한줄 실행할 수 있는 언어를 해석기 사용 언어 또는 스크립트 언어라고 부르며, 파이썬 소스코드를 해석하여 바로 실행되게 하는 것을 해석기(인터프리터)라고 한다. 해석기가 작동하는 방식은 아래 그림과 같다.
숫자 맞추기 게임의 소스코드를 바로 실행할 수 있다. 실행할 때 숫자를 하나 입력해야 하는데, 예를 들어, 13을 입력해보자.
print("숫자맞히기 게임에 환영합니다.")
secret = 9
guess = int(input("0부터 20 사이의 숫자 하나를 입력하세요: "))
if guess == secret:
print("맞았습니다!")
else:
print("틀렸습니다!")
print("게임 종료!")
반면에 C, 자바 언어의 경우는 컴파일러 사용 언어라 불린다. 컴파일러(compiler)는 소스코드 전체를 한꺼번에 대상코드(object code)로 변환시킨다.
변환 과정에서 소스코드 전체를 컴퓨터가 이해할 수 있는 저수준(low-level) 언어로 번역하면서 링크(link) 등 기타 다른 일들을 수행한다. 컴퓨터는 소스코드가 아닌 대상코드를 실행한다.
컴파일 과정은 그림으로 나타내면 아래와 같다.
특정 기능을 갖는 프로그램의 구현하려면 어떻게 구현할지 구상하는 과정을 먼저 수행해야 한다. 예를 들어, 숫자맞히기 게임을 개발에 필요한 프로그래밍 요소들을 확인하고, 어떻게 배치할 것인가에 대한 구상을 아래와 같이 할 수 있다.
input
함수==
)if
조건 제어문print
함수"숫자맞히기 게임"의 소스코드를 앞서 설명한 구상과정을 생각하면서 다시 한 번 살펴보면 아래와 같다.
아래 코드는 앞서 실행한 코드와 동일하다. 다만 각각의 명령문이 왜 그곳에 위치하였는가를 설명한 주석이 포함되어 있다.
주의: 주석은 소스코드의 구성요소를 설명하는 일반 언어로 작성된 문장이며,
프로그램을 실행에 아무런 영향을 주지 않는다. 즉, 프로그램 실행과정에서 무시된다.
한 줄짜기 주석은 샵(#
)기호로 시작한다.
# 환영인사 출력
print("숫자맞히기 게임에 환영합니다.")
# 맞혀야 하는 숫자 지정
secret = 9
# 사용자로부터 숫자 입력받기
# 입력할 숫자의 범위를 함께 지정함.
guess = int(input("0부터 20 사이의 숫자 하나를 입력하세요: "))
# 두 숫자를 비교하여 결과에 따라 다른 명령문 실행하기
if guess == secret:
print("맞았습니다!")
else:
print("틀렸습니다!")
# 종료 확인 출력
print("게임 종료!")
앞서 설명한 숫자맞히기 게임의 소스코드는 사용자에게 불공평한 게임을 제공한다. 맞춰야 하는 숫자에 대한 아무런 정보를 주지 않기 때문이다.
형평성을 높이기 위해 사용자가 입력한 값이 맞추어야 하는 숫자와 비교해서 큰지, 작은지, 같은지 여부를 알려줄 수 있도록 프로그램을 작성해야 한다.
크기 비교 연산자 <
, >
, <=
, >=
는
각각 작다, 크다, 작거나 같다, 크거나 같다를 판단한다.
0 < 1
1 >= 3
크기 비교 연산자를 활용하여 숫자맞히기 게임을 구현하면 다음과 같다. 예를 들어, 13을 입력하면 "너무 커요!"를, 7을 입력하면 "너무 작아요!"를 출력한다.
print("숫자맞히기 게임에 환영합니다.")
secret = 9
guess = int(input("0부터 20 사이의 숫자 하나를 입력하세요: "))
if guess == secret:
print("맞았습니다!")
else:
if guess > secret:
print("너무 커요!")
else:
print("너무 작아요!")
print("게임 종료!")
print("숫자맞히기 게임에 환영합니다.")
secret = 9
guess = int(input("0부터 20 사이의 숫자 하나를 입력하세요: "))
if guess == secret:
print("맞았습니다!")
else:
if guess > secret:
print("너무 커요!")
else:
print("너무 작아요!")
print("게임 종료!")
if
와 else
의 본체에는 임의의 파이썬 명령문이 사용될 수 있다.
따라서 또다른 조건 제어문이 사용될 수 있다.
이와 같은 조건문을 중첩 조건 제어문이라 부른다.
예를 들어, 위 코드에서 사용된 중첩 조건 제어문은 아래와 같다.
if guess == secret:
print("맞았습니다!")
else:
if guess > secret:
print("너무 커요!")
else:
print("너무 작아요!")
파이썬 소스코드를 작성할 때 경우에 따라 들여쓰기를 반드시 사용해야 한다. 위 숫자맞히기 게임의 소스코드에서 들여쓰기가 반드시 사용되는 곳은 아래와 같다.
if
문의 본체else
문의 본체조건 제어문 이외에 나중에 설명할 while
과 for
반복문의 본체에도 들여쓰기가 적용되어야 한다.
이와같이 조건 제어문, 반복문 등을 한 번 사용할 때마다
들여쓰기 횟수, 즉 들여쓰기 수준이 1씩 증가한다.
들여쓰기의 정도는 사용자가 정한다. 보통 탭(tab) 키를 사용하거나, 스페이스 키를 두 번 또는 네 번 사용한다. 단, 동일한 수준의 들여쓰기가 적용받는 명령문은 동일한 정도로 들여써져야 한다.
예를 들어 아래와 같이 작성하면 오류가 발생한다.
if guess == secret:
print("맞았습니다!")
else:
if guess > secret:
print("너무 커요!")
else:
print("너무 작아요!")
앞서 사용한 중첩 조건 제어문은 사실 필요하지 않다.
바로 위 코드를 보면 guess
와 secret
가 가리키는 두 값이 같거나, 크거나, 그렇지 않을 때 등
세 가지 경우를 다룬다.
이런 경우 굳이 중첩 조건 제어문을 사용하는 대신에 아래와 같이 일반화된 조건 제어문을 사용하는 것이 좋다. 이유는 아무래도 중첩 조건 제어문은 코드를 이해하는 데에 좀 더 복잡할 수 있기 때문이다.
if guess == secret:
print("맞았습니다!")
elif guess > secret:
print("너무 커요!")
else:
print("너무 작아요!")
일반화된 조건 제어문의 형식은 다음과 같다.
if 조건식_1:
명령문_1
elif 조건식_2:
명령문_2
...
elif 조건식_n:
명령문_n
else:
명령문
단, else
부분은 생략 가능.
일반화된 조건 제어문을 활용하여 숫자맞히기 게임을 구현하면 다음과 같으며, 앞서 중첩 조건 제어문을 사용한 코드와 동일하게 작동함을 확인할 수 있다.
print("숫자맞히기 게임에 환영합니다.")
secret = 9
guess = int(input("0부터 20 사이의 숫자 하나를 입력하세요: "))
if guess == secret:
print("맞았습니다!")
elif guess > secret:
print("너무 커요!")
else:
print("너무 작아요!")
print("게임 종료!")
print("숫자맞히기 게임에 환영합니다.")
secret = 9
guess = int(input("0부터 20 사이의 숫자 하나를 입력하세요: "))
if guess == secret:
print("맞았습니다!")
elif guess > secret:
print("너무 커요!")
else:
print("너무 작아요!")
print("게임 종료!")
프로그램 업그레이드 1 수정한 코드는 원래 코드보다 게임의 형평성을 좀 더 보장한다. 그런데 문제가 여전히 남아 있다. 바로 추측한 값이 틀려도 게임이 바로 멈춘다는 점이다. 즉, 새로운 추측을 하려면 게임을 다시 실행해야만 한다.
답을 맞출 때까지 게임이 반복되도록 코드를 수정해보자.
while
반복문¶while
반복문은 특정 조건이 성립하는 동안 특정 코드(반복문의 본체)를 반복해서 실행한다.
while
반복문의 형식은 아래와 같다.
while 조건식:
명령문
조건식
: 조건 제어문에 사용되는 조건식과 동일하다.명령문
: while
반복문의 본체라 부름. 조건식
이 참(True
)인 동안 반복적으로 실행된다.정답을 맞힐 때까지 사용자로부터 계속해서 입력을 받을 수 있어야 한다.
이를 위해 while
반복문을 사용하려면,
조건식과 본체에 사용될 명령문을 지정해야 한다.
비동치비교 연산자 !=
는 동치비교 연산자 ==
와 정반대의 값을 계산한다.
즉, 비교되는 두 값이 다르면 True
, 같으면 False
를 계산한다.
0 != 1
1 != 1
이제 앞서 구상한 내용을 토대로 하여 아래와 같이 while
반복문을 활용할 수 있다.
예를 들어, 7, 13, 9를 차례대로 입력하면 "너무 커요!", ""너무 커요!", "맞았습니다"를 연속으로 출력한다.
print("숫자맞히기 게임에 환영합니다.")
secret = 9
guess = -1
while guess != secret:
guess = int(input("0부터 20 사이의 숫자 하나를 입력하세요: "))
if guess == secret:
print("맞았습니다!")
elif guess > secret:
print("너무 커요!")
else:
print("너무 작아요!")
print("게임 종료!")
위 코드 4번 줄에서 guess
변수를 0에서 20사이의 값 이외의 숫자로 초기화한다.
이유는 두 가지이다.
while
반복문의 조건식에서 guess
변수가 가리키는 값을 확인하려면 guess
변수가 이미 선언되어 있어야 한다.while
반복문의 본체가 한 번 이상 실행되려면 조건식이 처음에 거짓과 동일한 값이어야 한다.
그런데 사용자가 0에서 20 사이의 값을 입력할 것이기에 그 이외의 수인 -1을 사용하였다.
물론, -2, 30 등 다른 수가 사용될 수도 있다. 앞서 프로그램 업그레이드 2에서 개선한 코드는 상당히 훌륭하다. 사용자가 숨은 값을 맞출 수 있도록 유도하며, 숫자 9를 맞혀야만 종료된다.
그런데 위 게임은 한 번 하면 더 이상 사용하지 않는다. 맞혀야 하는 숫자가 항상 9이기 때문이다. 따라서 위 게임을 좀 더 흥미롭게 만들기 위해서 맞혀야 하는 숫자를 게임이 실행될 때마다 임의로 변하도록 바꿀 필요가 있다.
random
모듈¶임의의 정수를 생성하기 위해 randint
함수를 이용하는 방법이 있다.
randint
함수는 두 개의 정수 인자를 받으면 두 정수를 양끝으로 갖는 구간에서 임의의 값을 정하여 리턴한다.
예를 들어, 0부터 20사이의 정수 중에서 임의의 값을 선택하려면 randint(0, 20)
이라 작성하면 된다.
그런데 randint
함수는 덧셈, 뺄셈 등 사칙연산과는 달리,
먼저 random
이라는 모듈을 불러와야(import) 사용할 수 있다.
모듈(module)은 파이썬 소스코드를 담은 파일이며, 확장자로 py를 사용한다. 모듈은 서로 연관이 있는 다양한 함수들을 하나의 파일로 묶어 놓을 때 유용하게 사용한다.
예를 들어, random
모듈, 즉, random.py
파일 안에는 무작위수 생성과 관련된
다양한 함수들이 포함되어 있으며,
지정된 구간 사이에서 임의의 정수를 생성하는 randint
함수가 그중에 하나이다.
특정 모듈을 불러오는 여러 방식이 있다.
여기서는 특정 모듈에 포함된 특정 함수만을 불러오는 방식만 소개한다.
예를 들어, random
모델에 포함된 randint
함수를 사용하려면
아래와 같이 불러와야 한다.
from random import randint
randint
함수가 어떻게 작동하는지를 확인하기 위해 아래 명령을 반복해서 실행해 보는 게 좋다.
randint(0, 20)
randint(0, 20)
randint(0, 20)
randint
함수 활용 방법 구상하기¶숫자맞히기 게임에 무작위수 생성 기능을 추가하고자 하려면,
secret
변수가 가리키는 숫자를 고정된 숫자 9가 아니라
아래와 같이 randint
함수가 0과 20 사이에서 임의로 생성하는 값으로 지정해야 한다.
secret = randint(0, 20)
앞서 구상한 내용을 토대로 하여 아래와 같이 randint
함수를 활용하면,
소스코드 개발자 또한 맞혀야 하는 숫자를 알 수 없게 된다.
아래 게임을 여러 번 실행하면서 게임의 성능을 확인해보자.
from random import randint
print("숫자맞히기 게임에 환영합니다.")
secret = randint(0,20)
guess = -1
while guess != secret:
guess = int(input("0부터 20 사이의 숫자 하나를 입력하세요: "))
if guess == secret:
print("맞았습니다!")
elif guess > secret:
print("너무 커요!")
else:
print("너무 작아요!")
print("게임 종료!")
from random import randint
print("숫자맞추기 게임에 환영합니다.")
secret = randint(0,20)
guess = -1
while guess != secret:
guess = int(input("0부터 20 사이의 숫자 하나를 입력하세요: "))
if guess == secret:
print("맞았습니다!")
elif guess > secret:
print("너무 커요!")
else:
print("너무 작아요!")
print("게임 종료!")
앞서 배운 내용에서 사용된 파이썬 프로그래밍 언어의 요소들에 대한 보다 자세한 설명은 프로그래밍 기본 요소: 변수, 표현식, 명령문에서 확인할 수 있다.
and
)과 논리합(or
)을 활용할 수 있으며,
논리식과 논리연산자에 대한 설명은
씽크 파이썬: 조건문과 재귀를
참고한다.)