최근 수정 시각 : 2024-11-14 18:19:55

절차적 프로그래밍


[[컴퓨터공학|컴퓨터 과학 & 공학
Computer Science & Engineering
]]
[ 펼치기 · 접기 ]
||<tablebgcolor=#fff,#1c1d1f><tablecolor=#373a3c,#ddd><colbgcolor=#0066DC><colcolor=white> 기반 학문 ||수학(해석학 · 이산수학 · 수리논리학 · 선형대수학 · 미적분학 · 미분방정식 · 대수학(환론 · 범주론) · 정수론) · 이론 컴퓨터 과학 · 암호학 · 전자공학 · 언어학(형태론 · 통사론 · 의미론 · 화용론 · 음운론) · 인지과학 ||
하드웨어 구성 SoC · CPU · GPU(그래픽 카드 · GPGPU) · ROM · RAM · SSD · HDD · 참조: 틀:컴퓨터 부품
기술 기계어 · 어셈블리어 · C/C++ · C# · Java · Python · BIOS · 절차적 프로그래밍 · 객체 지향 프로그래밍 · 해킹 · ROT13 · 일회용 비밀번호 · 사물인터넷 · 와이파이 · GPS · 임베디드 · 인공신경망 · OpenGL · EXIF · 마이크로아키텍처 · ACPI · UEFI · NERF · gRPC · 리버스 엔지니어링 · HCI · UI · UX · 대역폭 · DBMS · NoSQL · 해시(SHA · 브루트 포스 · 레인보우 테이블 · salt · 암호화폐) · RSA 암호화 · 하드웨어 가속
연구

기타
논리 회로(보수기 · 가산기 · 논리 연산 · 불 대수 · 플립플롭) · 정보이론 · 임베디드 시스템 · 운영 체제 · 데이터베이스 · 프로그래밍 언어{컴파일러(어셈블러 · JIT) · 인터프리터 · 유형 이론 · 파싱 · 링커 · 난해한 프로그래밍 언어} · 메타데이터 · 기계학습 · 빅데이터 · 폰노이만 구조 · 양자컴퓨터 · 행위자 모델 · 인코딩(유니코드 · MBCS) · 네트워크 · 컴퓨터 보안 · OCR · 슈퍼컴퓨터 · 튜링 머신 · FPGA · 딥러닝 · 컴퓨터 구조론 · 컴퓨터 비전 · 컴퓨터 그래픽스 · 인공지능 · 시간 복잡도(최적화) · 소프트웨어 개발 방법론 · 디자인 패턴 · 정보처리이론 · 재귀 이론 · 자연어 처리(기계 번역 · 음성인식) · 버전 (버전 관리 시스템 · Git · GitHub)

1. 소개2. 장점3. 단점

1. 소개

Procedural Programming

절차적 프로그래밍이란 단순히 순차적인 명령 수행이 아니라 함수, 메소드, 루틴, 서브루틴 등(이를 통틀어 '프로시저'라고 한다.)을 이용한 프로그래밍 패러다임을 뜻한다. 명령형 프로그래밍의 일종이다.

'절차적 프로그래밍'이라는 한국어 번역은 오해의 여지가 크다. Procedural Programming에서 Procedural를 '절차적'으로 번역해버려서 마치 절차적으로 실행하는 것이 중점이 되는 것처럼 보이기 때문이다.[1] 그런데 절차적이지 않은 프로그래밍이란 건 애초에 존재하지 않는다. Procedural의 Procedure는 '절차'라는 의미가 아니라 위에도 언급되었듯 '프로시저'의 의미이다. 이 패러다임에서는 프로시저 콜, 즉 함수 호출을 통해서 추상화와 재사용성을 얻어내는 것이 본질이기 때문이다. 그러나 이미 교과서에 절차적 프로그래밍이라고 줄기차게 쓰여져 있어서 굳어져버렸기 때문에 어쩔 수 없이 이 번역명이 사용되고 있다.

절차적 프로그래밍이라는 이해하기 힘든 이상한 번역이 현재 가장 오래 사용되고 있는 표현인 만큼, 순차적 프로그래밍, 객체 지향 프로그래밍, 함수형 프로그래밍과의 관계를 오해하기 쉽다. 가령 순차적 프로그래밍과의 비교에서 순차적 프로그래밍은 순차를 중시하고 절차적 프로그래밍은 절차를 중시한다는 이상한 논리를 가져다 대는 경우가 있다. 이는 번역의 문제로 위의 문단을 읽었으면 코드를 단순히 실행 순서의 관점으로만 보는 순차적 프로그래밍과 프로시저 단위로 보는 절차적 프로그래밍과의 차이를 알 수 있다.

다른 문제로는 객체 지향 프로그래밍과 비교해서 마치 절차적 프로그래밍이 객체 지향의 반대이며 심지어 '절차 지향'으로 알고 있는 사람들도 있다. 절차 지향이라는 용어는 잘못된 표현이며 절차적 프로그래밍이 맞다. 절차 지향으로 부르는 사람이 없는 것은 아니지만 대부분은 절차적 프로그래밍이라는 용어를 사용한다. 또한 객체 지향이 절차적 프로그래밍의 반대 의미처럼 사용되는 것에 대해서, 객체 지향의 반대 개념은 절차적 프로그래밍이 아니다. 절차적 프로그래밍의 관점이 프로시저에서 객체로 확장된 것에 가깝기에 일치한다고 볼 수는 없어도 서로 공유하는 부분이 차이보다 더 많다. 애당초 둘다 명령형 프로그래밍의 하위 개념이다. 그래서 보통 제대로 된 서적에서 객체 지향과 비교할 때는 "객체 지향과 일반적인 절차적 프로그래밍(쉽게말해서 객체를 사용하지 않는)"이라는 단서를 붙힌다.

현대 프로그래밍 언어에서의 프로시저와 함수의 구분은 없어진 것이나 다름없기에 함수형 프로그래밍과 절차적 프로그래밍이 동등한 것이냐는 이야기가 있다. 그러나 함수형 프로그래밍의 관점은 순수함수와 일등객체인 함수에 관심이 있는 것이고 절차적 프로그래밍은 함수(그리고 이를 관리하는 모듈)에 의한 재사용성에 초점을 둔 것이기에 두 개념은 차이가 있다.

2. 장점

프로시저를 이용하여 프로그래밍을 하게 되면 기본적으로 함수를 통해 코드의 재활용성이 높아지게 된다. 또한 메인 프로시저뿐만 아니라 함수의 호출을 통해 여러 부분을 생략하여 프로그램 흐름을 쉽게 볼 수 있으므로 코드의 가독성이 높아진다. 또한 모듈화와 구조화가 더 용이해지므로 대규모 프로젝트에 많은 프로그래머들이 투입된 경우 자신이 맡은 부분만 프로그래밍하여 조립하는 것도 가능하다.

3. 단점

당연히 단점 또한 존재한다. 기본적으로 프로시저를 호출하는 것은 그냥 코드를 쓰는 것보다 시간이 매우 많이 소모된다.

32비트 Windows 환경의 프로시저 호출에 관여하는 레지스터는 4개로 볼 수 있다. 스택 바닥의 주소를 가지고 있는 EBP, 현재 스택의 주소를 가지고 있는 ESP, 다음 명령어의 주소를 가지고 있는 EIP, 코드 세그먼트 CS인데, CS에 영향을 주지 않는 근거리 함수 호출 및 반환의 경우 다음 과정을 거친다.
  1. 스택에 인자를 넣는다. (메모리 접근)
  2. 스택에 EIP를 넣는다. (현재 명령어 주소 저장. 메모리 접근)
  3. EIP에 함수의 주소를 넣는다. (함수의 주소로 이동)
  4. 스택에 EBP를 넣는다. (스택 바닥 주소 저장. 메모리 접근)
  5. EBP에 ESP를 넣는다. (현재 스택의 주소를 새로운 스택 바닥 주소로 함)
  6. 함수 실행 (이 과정에서 ESP를 적절히 빼서 지역 변수를 할당할 수 있으며, EBP의 값은 바꾸지 않는다)
  7. ESP에 EBP를 넣는다. (함수 호출 전의 스택 주소 복원)
  8. 스택을 뽑아 EBP에 넣는다. (함수 호출 전의 스택 바닥 주소 복원. 메모리 접근)
  9. 스택을 뽑아 EIP에 넣는다. (함수 호출 전의 명령어 주소 복원 후 그 주소로 이동. 메모리 접근)
이 중 2~3의 과정은 CALL 명령어에 포함되어 있고, 9의 과정은 RET 명령어의 기능이며, 4~8의 과정은 호출되는 함수 측에서 코딩을 해 줘야 한다.

꽤 복잡한 과정을 거치며, 코드를 그냥 쓰는 것(인라인)보다 적어도 네 번의 메모리 접근을 더 요구하고, 인자를 전달하는 경우 적어도 인자의 개수만큼의 메모리 접근을 추가적으로 필요로 하는 등 매우매우매우 많은 시간과 자원을 잡아먹는다. 그러므로 함수를 사용할 때 원칙적으로는 이것이 꼭 필요한지 생각해 보는 것이 좋다.

다만 프로시저를 프로시저가 아닌 것처럼 사용하는 방법이 있다. 그것은 바로 C++ 등에서 지원하는 인라인 함수이다. 인라인 함수를 사용하게 되면 컴파일러가 함수를 호출하는 것이 아니라(스택 프레임 등을 확보하고 프레임 포인터들을 바꾸는 것이 아니라), 인라인 함수 내의 내용으로 코드를 바꾸어 버린다. 따라서 코드를 그냥 쓰는 것과 다름없이 사용가능하다.

다만 위의 내용은 다소 낡은 내용인데, 현재는 대부분의 컴파일러 성능이 좋아진 터라 최적화 옵션을 주면 inline 지시자 없이도 자동으로 인라이닝을 해주기 때문이다. 또 하드웨어의 성능도 향상되어 현재 단순 프로시저 콜 오버헤드를 걱정해야 하는 시기는 이미 지났다고 볼 수 있다. 이제는 커널 튜닝/해킹을 하지 않는 이상 함수 콜 오버헤드를 걱정할 필요는 없다! 따지고 보면 객체 지향 프로그래밍은 vtable 참조 때문에 프로시저 지향 프로그래밍보다 함수 콜이 느린데도 잘만 쓴다. 예전 컴퓨터 기준으로 작성된 프로그래밍 기법 중에서 자주 찾아볼 수 있는 현상. 최근 프로그래밍은 성능도 성능이지만 편의성, 호환성, 생산성을 예전보다 중시하는 추세이다.


[1] 'Procedure'의 한글 뜻에 '절차' 뿐 만이 아닌 '방법'이라는 의미도 있기에 '절차'를 순서에 중점을 두고 해석을 하는 것이 아닌, '일을 처리하는 방법 그 자체'로 해석해야 한다. 즉, '방법'이라는 덩어리 하나 하나에 중점을 둬야 한다.