1. 프로그래밍의 과정
- 추상화(Abstraction): 복잡한 문제의 핵심 요소만을 추출하여 단순화한 모델로 표현하는 과정
- 알고리즘(Algorithm): 특정 문제 해결을 위해 명확하고 구체적인 단계로 구성된 절차
- 효율성(Efficiency): 알고리즘이 실행될 때 소모되는 시간과 메모리 등 소요되는 자원을 최소화하는 능력
- 휴리스틱(Heuristic): 최적의 해답을 찾기 어려울 때 실용적이고 빠른 해결책을 제시하는 접근 방법
- 근사(Approximation): 정확한 값 대신 문제 해결에 적절한 근접한 값을 사용하는 방식
프로그래밍은 주로 풀고자 하는 문제를 추상화하고, 이를 위한 알고리즘을 작성하며, 효율성을 높이기 위해 최적화를 하는 과정으로 구성된다.
⇒ 이쪽으로 나아가면 평생 죽을 때까지 반복하게 될 일
2. 컴퓨터의 기본 구조
- 반도체(Semiconductor): 전기적 신호를 처리하는 컴퓨터의 핵심 부품
- 이진 표현(Binary Representation): 컴퓨터가 인식할 수 있도록 데이터를 0과 1로 표현하는 방법
- 하드웨어(Hardware, HW): 컴퓨터의 물리적인 구성 요소로 프로세서, 메모리, 저장장치 등을 포함
- 소프트웨어(Software, SW): 컴퓨터의 가상의 구성 요소로 커널, 운영체제 등을 포함
- 커널(Kernel): HW-SW 사이의 상호작용을 담당하는 소프트웨어
- 운영체제(Operating System, OS): HW-SW-사용자 간의 상호작용을 담당하는 소프트웨어

운영체제 또한 하나의 소프트웨어! 컴퓨터가 실행될 때 가장 먼저 실행되는 소프트웨어가 운영체제이다.
3. 프로그래밍 언어
프로그래밍 언어는 크게 저수준 언어와 고수준 언어로 나뉜다.
| 구분 | 저수준 언어(Low-level Language) | 고수준 언어(High-level Language) |
|---|---|---|
| 개념 | 기계가 이해할 수 있어 하드웨어와 밀접한 언어 | 사람이 이해하고 작성하기 쉬운 언어 |
| 예시 | 바이너리(이진표현), 어셈블리어 | C, C++, Python 등 대부분의 프로그래밍 언어 |
| 특징 | 이식성이 매우 낮음 (실력만 있다면) 매우 높은 효율성을 보임 | 이식성이 매우 높음 대부분의 경우에 자동으로 최적의 효율을 보여줌 |
4. 컴파일과 컴파일러
그런데 위의 표를 보면… 고수준 언어는 기계가 이해할 수 없다?
⇒ 맞다! 우리가 주로 다루는 고수준 언어는 결국 기계가 이해할 수 있는 코드로 변환되어야만 한다! 이 과정을 **컴파일(Compile)**이라 하며, 이를 수행하는 프로그램을 **컴파일러(Compiler)**라 한다.
컴파일러 속에서 일어나는 컴파일 과정은 대략적으로 다음과 같다.

음… 그만 알아보자.
4.1. 여담
??: "어! 그러면 소프트웨어를 만드려면 컴파일 과정을 거쳐야 하는데, 컴파일을 하는 컴파일러도 하나의 프로그램이잖아요. 그럼 그 프로그램은 어떻게 컴파일한건데요?"
당연+충격적이게도, 극초기의 프로그램은 사람이 직접 이진표현된 기계어를 작성했다. 이를 쉽게 만들기 위해 그나마 사람이 읽을 수는 있는 어셈블리어를 만들게 되었고, 어셈블리어를 기계어로 바꾸는 어셈블러(Assembler)는 사람이 직접 기계어로 작성했다.이것조차 불편하니 더 편한 고수준 언어인 C를 만들었고 이를 컴파일하는 컴파일러는 어셈블리어로 작성되었다. 이것도 불편하다고 문법을 비약적으로 축약하니 Python이 만들어졌다더라…
선대 프로그래머의 수많은 노력(노가다) 끝에 현재 편하게 파이썬과 같은 고수준 언어를 쓸 수 있는 것이다.
참고: 두 수를 더하는 Python 코드와 C언어에서 컴파일된 기계어 코드(축약)의 비교
[Python]
a, b = 3, 4
print(a + b)[기계어(축약됨)]
11001111 00000000 00000010 00000000 10000101 00000000 01001000
01010000 01010010 00000000 00000000 10001000 01010100 00000001
00000000 00000000 00000000 00000100 00000000 01111000 01011111
00000000 00000000 01100100 00000000 00000010 00000000 00000000
01110011 00000000 01011000 10011000 00000000 00000000 00000000
00000000 00000000 01011111 01101001 00000000 01010100 00000000
00000001 10100100 00000000 00000000 01110111 01101110 01011111
00000000 00000000 01011000 00000000 00000010 00000000 00000000
01011111 01011111 00000000 00000000 00000000 00000000 00000000
00000011 00000000 00010000 01100111 00000000 01010100 01010011
00000000 00000000 00000000 00000000 00000000 00000001 00011001
00000000 01001110 00000000 00000000 00000000 10011000 00000000
00000001 00110100 00000000 01101000 00000000 01101000 00000000
00011000 00000000 11011000 00000000 01010000 00000000 00000000
00000001 00000000 00000000 00000000 00000000 00001100 01110011
00101111 00011011 00000000 10010000 10010101 00110010 00000000
00000000 00001111 00000011 01011011 00010000 00101000 00000000
00001100 00000000 00000010 01000111 00101111 01101001 01010011
00101110 01101001 00000000 00010000 00000000 00101001 00000000
00000000 00000000 00000000 00000000 00000001 11111101 10000000
10111111 00011111 01101000 00011110 11101000 01011110 00001010
00000000 00101000 00000000 00000101 01000000 11111111 01011111
00010000 00011111 00000001 00011100 00000000 00000010 00000000
01000000 01000000 00000000 00000000 00010000 00000000 00000000
00100000 00000000 00000001 00000000 00000000 00000000 00000000
00000000 00000001 00000000 01110100 00000000 01011111 00000000
00000000 01011111 01100101 01101000 00000000 00000000 00000010
00010000 00000001 00000000 00110100 00000000 00000001 00000010
00000000 01101101 01100011 01100101 01011111 01011111 01100110
11111010 00000001 00000000 00000000 00000100 00000000 00000000
00000000 10000001 00000000 00000000 01100001 11101001 01110110
01000010 01000100 00011111 01010111 01011000 00000100 01001111
01111100 01001000 10101100 01100110 01101011 01111100 10111101
10000011 11111111 01110001 11100000 01100101 10000010 11110001
00000110 11110001 10100011 10010010 10101100 01100110 01101011
01111100 10111101 10101101 11000110 11010001 00000101 10000101
00101100 01011000 00000100 01001111 01111100 01001000 10100101
00001011 01000110 10100101 01000000 5. 인터프리터
하지만 우리가 지금 다루는 Python은 인터프리터 언어이다.
인터프리터는 내부적으로 가상머신을 구축하고 실시간으로 코드를 한 줄씩 읽어 바이트코드라는 중간 산물을 거쳐 실행한다. 즉, 코드가 줄 단위로 컴파일되어 즉시 실행된다.
| 컴파일 언어 | 인터프리터 언어 |
|---|---|
| 코드 ⇒ 프로그램 때 한번만 컴파일 된다 | 프로그램을 실행시킬 때마다 컴파일 된다 |
| 모든 코드를 한번에 컴파일한다 | 한 줄씩 컴파일한다 |
| 실행속도가 빠르다 | 실행속도가 (매우) 느리다 |
| 대화형 프로그래밍이 불가능하다 | 실시간 대화형으로 프로그래밍 가능하다 |
참고로 다들 Python으로 AI 짠다는 소리 들어봤을 것이다. 실행속도가 (매우) 느린 인터프리터 언어인 파이썬으로 어떻게 AI를 짜느냐 하면, 핵심 연산 부분은 전부 C + 어셈블리어로 짜놓고 이걸 파이썬 명령어로 실행시키는 구조이다. 편의성과 속도 두 마리 토끼를 모두 잡은 셈.
6. 오류와 디버깅
프로그래밍 과정에서는 수없이 많은 에러를 맞닥뜨리고 이를 해결하기 위한 디버깅 과정을 거치게 된다.
- 오류(Error): 프로그램 실행 중 기대한 것과 다르게 작동하는 현상
- 디버깅(Debugging): 발생한 오류를 찾고 수정하는 과정
이러한 에러에는 다음의 두 가지 종류가 있다.
| Syntax Error (구문 오류) | Semantic Error (의미 오류) |
|---|---|
| 문법적으로 잘못된 코드 | 문법상으로는 맞지만, 의도한 의미와 다른 코드 |
| ex) python: a + b 4 | ex) 숫자 0으로 나누기, 더해야하는데 빼버리기 |
하지만, 보통 다음의 두 분류를 더 많이 사용하게 될 것이다. (사심 조금 있음)
| Compile Error (컴파일 에러) | Runtime Error (런타임 에러) |
|---|---|
| 컴파일 시점에 발생하는 오류 | 프로그램 실행 중에 발생하는 오류 |
파이썬은 대화형으로 각 줄마다 컴파일되기에 코드를 수백줄을 짜도 실행시키기 전까진 오류 여부를 알 수 없다. 따라서 대부분 런타임 에러로 취급된다.
참고로 컴파일 에러보다 런타임 에러가, 구문 오류보다 의미 오류가 훨씬 위험한 에러이다 (실행시키고 나서도 오류가 나는 특정 상황이 발생할 때까지 틀렸는지도 모르는 시한폭탄)
6.1. Ariane 5 로켓 폭발 사고
1996년 6월 4일, Ariane 5 Flight 501은 유럽우주국(ESA)이 개발한 로켓의 첫 비행에서 발사 37초 후 자세제어에 실패하여 급격한 궤도 이탈 후 안전을 위해 발사 59초 후 지상 관제소에서 자폭 시스템 가동.
직접적인 인명 피해는 없었지만, 5억 달러의 위성과 장비가 파괴됨 기존 Ariane 4의 소프트웨어를 그대로 Ariane 5에 재사용하던 과정에서 수직 속도 데이터를 64비트 부동소수점(float) → 16비트 정수(integer)로 “런타임”에 변환(casting)하며 정수 오버플로우가 발생, 이로 인해 로켓 자세 제어 시스템이 고장남
가끔 코드를 작성할 때 구문 오류를 알려주는 에디터의 기능을 보게 되는데, 이는 컴파일러/인터프리터가 계산하는 것이 아니라 Language Server Protocol (LSP)를 이용하여 실시간 문법 검사 및 다양한 부가기능을 제시해주는 Code Intellisense 서비스이다
7. 에디터와 IDE
코드 에디터와 IDE를 상당히 혼동하는 경우가 있는데, 다음과 같은 차이가 있음을 꼭 알아두자 (모르면 이상한거 설치한다)
| 소스코드 편집기 (Code Editor) | 통합 개발 환경 (Integrated Development Environment, IDE) | |
|---|---|---|
| 차이 | ✅ 소스코드 작성과 기본적인 편의기능만 제공 ✅ 지원하는 프로그램의 경우 확장 플러그인으로 다양한 부가기능 설치 가능 ✅ 간단하고 비교적 가벼움 (리소스 적게 먹음) ✅ 커스텀하기 좋음 | ✅ 전체 개발 과정에 대한 통합 서비스 제공 ✅ 코드 작성 + 컴파일 + 실행 + 디버깅 + 배포 + 패키지 관리 등 많은 편의 기능을 이미 탑재 ✅ 복잡하고 비교적 무거움 (리소스 많이 먹음) ✅ 커스텀하기 비교적 안좋음 |
| 예시 | 메모장(??), Visual Studio Code, Atom, Vim 등 | Pycharm, Visual Studio, IntelliJ 등 |
8. CLI, GUI, 쉘과 환경변수, 파이썬 코드의 실행 방법
파이썬을 실행시킬 때 Pycharm을 쓴다면 대부분 F5나 실행버튼 한번에 딸깍 하고 프로그램이 실행된다. 하지만 적어도 프로그래밍을 한다고 말하려면 내 코드가 어떻게 실행되는지는 알아야 하지 않을까?
많이 어려울 수 있지만, 이해만 한다면 프로그래밍에서의 애로사항이 많이 줄어들 것이라 확신한다.
8.1. GUI (Graphical User Interface)
우리는 현재 사용자의 편의성을 위해 시각적으로 쉽게 다룰 수 있는 운영체제를 주로 접하고 쓴다. (Windows, MacOS 등) 이렇듯 마우스를 움직이거나 손으로 터치하여 컴퓨터의 기능을 조작하는 방식의 인터페이스를 GUI라 부른다.
Pycharm에서 실행 버튼을 누르는 것도, GUI의 일환이다.
8.2. CLI (Command-Line Interface)
우리가 GUI를 이용해 컴퓨터와 상호작용할 때, 실제로는 내부적으로 일련의 코드를 실행시킴으로써 컴퓨터에게 직접적인 명령을 내린다. 이처럼 우리는 GUI 뿐 아니라 기본적인 명령어들을 CLI를 이용하여 텍스트로 입력할 수 있다.
Windows 운영체제를 이용한다면 바탕화면에 있는 자신이 원하는 프로그램의 “바로가기”를 우클릭해서 속성 창을 열어보자. 그렇다면 아래와 같이 어떠한 코드가 적혀있는 것이 보일 것이다.

이것을 복사해놓고, 윈도우 검색 창에서 cmd를 입력해 가장 처음에 뜨는 프로그램(명령 프롬프트)을 실행하자. 해당 프로그램의 창에 복사해 놓은 코드를 복사해서 Enter를 누르면 당신은 CLI를 이용하여 프로그램을 실행시킨 것이다.
우리가 방금 사용한 CMD 프로그램(Mac에서는 Zsh)와 같이 기본적으로 모든 운영체제에는 GUI는 없을 지언정, CLI는 탑재되어있다. 이 CLI마저 없다면 우리는 컴퓨터와 상호작용 할 수 있는 방법이 사라진다.
8.3. 쉘
CMD, Zsh와 같이 사용자가 명령어를 입력하면 이를 해석해 커널에 전달하고, 실행 결과를 다시 사용자에게 보여주는 CLI의 일종이다. 즉, 쉘은 사용자의 명령을 받아 실행하는 “껍데기(shell)” 역할의 프로그램이다.
8.4. 환경 변수 (Environment variable)
환경 변수란 운영체제와 쉘에서 프로그램이 동작하는 환경 정보를 담고 있다. 말이 정말 어려운데, 이 중 우리가 많이 접할 PATH 라는 환경 변수에 대해서만 대표적으로 짚고 가보자.
(Windows에서) 우리가 방금 실행한 CMD 창을 켜서 notepad라고 입력하면 메모장이 뜨고 explorer라고 치면 파일 탐색기가 뜬다. 하지만 chrome을 입력해보면 에러가 뜨게 되는데, 이는 chrome이 PATH 라는 환경 변수에 등록되어있지 않기 때문에 발생한다.
원래 CLI는 자신이 있는 디렉토리(Directory, 소위 폴더라고 부르는 것)에 있는 프로그램만 실행시킬 수 있으나 이 환경 변수PATH 에 프로그램을 등록하면 어떤 디렉토리에서 CLI를 이용하여도 해당 프로그램을 즉시 실행시킬 수 있게 된다. 만약 CMD에 python을 입력하여서 바로 파이썬 대화형 창이 활성화된다면 파이썬이 환경변수PATH 에 등록되어 있는 것이고, 아니라면 환경변수PATH 에 등록되어 있지 않은 것이다. (이는 필수가 아니다)
8.5. Python코드 (.py)가 어떻게 실행되는가
Pycharm에서 코드를 실행하면 쉘은 정확히는 파이썬 인터프리터 프로그램(python.exe)을 실행시키게 된다.
이렇게 쉘에서 프로그램을 실행시킬 때에는 **인자(Arguments)**라는 것을 입력할 수 있는데, 이 인자에 우리가 작성한 파이썬 파일을 넣어주면 우리가 짠 코드를 실행시키게 된다.
즉, Pycharm에서 내부적으로 실행하는 코드는 다음과 같다.
{Python 인터프리터의 경로} {내가 작성한 코드 파일의 경로}
ex)
C:\\Users\\user\\AppData\\Local\\Python312\\python.exe C:\\Users\\user\\Desktop\\lab_p1.py9. 기본적인 단축키
이거 모르면 진짜 심각한거니 하루빨리 외워야 한다.
- Ctrl(Command) + C : 복사
- Ctrl(Command) + V: 붙여넣기
- Ctrl + X / Command + alt + V: 오려내기
- Ctrl(Command) + Z: 되돌리기
- Ctrl(Command) + Shift + Z: 앞으로 감기
10. 비트(bit, b)와 바이트(byte, B)
1비트는 이진 표현에서 한 자릿수를 의미한다. 즉 1비트는 0 또는 1만이 가능하다. 1바이트는 8개의 비트가 모인 것으로 8자리 이진수를 표현할 수 있으며 총 256개의 가짓수를 표현할 수 있다.
기호로써 표현할 때 비트는 소문자 b 를 사용하고 바이트는 대문자 B 를 사용한다.
23Kb = 23,000b = 2,875B = 2.875KB
3MB = 3,000,000B = 24,000,000b = 24Mb11. 고정 소수점과 부동 소수점
컴퓨터는 이진 표현을 사용하기에 10진수로 표현되어있는 소수 중 일부를 정확히 표현하는데 한계가 있다.
이러한 정밀도 오류를 표준화시키는 근사 방법으로 정한 규약이 고정 소수점과 부동 소수점이다.
| 구분 | 고정 소수점 | 부동 소수점 |
|---|---|---|
| 소수점 위치 | 고정됨 | 자유롭게 이동 |
| 표현 범위 | 제한적 | 훨씬 넓음 |
| 정밀도 | 선형 | 비선형 |
| 연산 속도 | 빠름 (하드웨어 단순) | 느릴 수 있음 (정밀도 보정 필요) |
| 사용 예 | 임베디드, DSP | 대부분의 현대 언어 및 계산기 |
컴퓨터의 소수 표현은 고정 소수점과 부동 소수점 표현 방식 모두 오차를 지니지만, 여러 편의성에 의해 대부분의 컴퓨터에서 부동 소수점을 주로 사용한다.
가장 간단한 예시는 다음으로, 이는 파이썬 뿐 아니라 모든 언어에서 동일하게 일어나는 현상이다.
a = 0.1 + 0.2
print(a) # 출력: 0.30000000000000004
print(a == 0.3) # 출력: False12. PEP8 (Python Enhance Proposal 8)
파이썬 뿐 아니라 다양한 프로그래밍 언어는 각자 언어의 지향점과 스타일에 맞게 코드를 작성하는 스타일을 통일하는 것을 권장한다. 아래에 나온 스타일 가이드는 대부분의 언어에서 통용되며, 가장 기본적으로 지켜야 되는 필수 스타일 가이드이기에 꼭 습관화 하는 것이 중요하다.
- 연산자 주변에는 한 칸의 공백을 넣는다.
a = 1 + 2 / (3 + 5) ✅a=1 + 2 / (3 + 5) ❌a = 1+2 /(3 + 5) ❌
- 콤마(
,)와 콜론(,) 뒤에 한 칸의 공백을 넣는다.a = [1, 2, 3] ✅a = [1,2,3] ❌
- 변수, 함수의 이름은 소문자와 밑줄을 이용해 구분하는
snake_case를 사용한다. 상수의 경우 대문자를 사용한다.this_is_variable ✅THIS_IS_CONSTANT ✅this_is_function ✅
위의 스타일 가이드에도 몇몇 널리 퍼진 예외는 있다. 또한 자신만의 코딩 스타일도 중요하기에 결국 프로그래밍을 해 나가는 과정 동안 조금씩 변하게 될 것이다. 하지만 적어도 자신만의 예외를 만들 것이라면 일관되게 작성할 수 있도록 신경을 써야 나중에 고치기 쉽다.
13. 변수와 상수, 데이터, 타입, 표현식
- 변수(Variable): 변할 수 있는 값으로, 데이터를 잠시 담아두는 용도로 사용한다.
- 상수(Constant): 고정된 값으로, 보통 프로그램 내에서 고정된 값을 담는 용도로 사용한다.
- 연산자(Operator): 값을 처리하여 결과를 반환하는 기호로, 산술, 논리, 비교 연산자 등이 있다.
- 표현식(Expression): 연산자와 값을 결합하여 하나의 값으로 평가할 수 있는 코드 조합
- 리터럴(Literal): 변수, 또는 상수의 값을 표현식으로 계산하지 않고 직접 숫자로 입력하는 방식
파이썬에서는 변수와 상수가 내부적으로는 구분되지 않고, 소문자와 대문자를 이용해 가시적으로만 구분한다.
파이썬의 가장 기본 데이터 타입은 int , float , bool , str 이 있으며, 특징으로는 다음이 있다.
- 파이썬의
float은 64비트 부동소수점 형식을 사용한다. - 파이썬의
int는 **오버플로우(Overflow)**가 일어나지 않는다. - 동적 타이핑(Dynamic Typing): 변수에 할당되는 데이터의 타입이 런타임에 결정되고 변수의 타입이 고정되어있지 않다.
- 강한 타이핑(Strong Typing): 서로 호환되지 않는 데이터 타입 간 묵시적 형 변환이 불가능하다.
[참고]
int = Integer (정수형)
float = floating point (소수형)
bool = boolean (참/거짓)
str = string (문자열)이 포스팅에는, 이해의 편의성을 위해 정확하지 않은 표현이 있을 수 있습니다