[Java] 절차적/구조적 프로그래밍과 객체지향 프로그래밍

공부하는 감자·2024년 1월 7일
0

Java

목록 보기
1/5

들어가는 말

객체 지향 프로그래밍은 절차적/구조적 프로그램의 어깨를 딛고 있다.

객체 지향 언어를 이해하기 위해 절차적/구조적 프로그래밍을 아는 것이 큰 도움이 된다.

따라서, 보통 객체지향 프로그래밍을 설명할 때 언급하는 프로그래밍들을 간략하게 설명한다.

순차적 프로그래밍

영어로는 Sequential Programming이며, 비구조적 프로그래밍이라고도 한다.

  • 명령어가 순서대로 실행되며 한 번에 하나의 작업만 처리한다.
  • 시작점부터 끝까지 일련의 단계를 따라가며 실행한다.

이는 코드로 따지자면, 함수 하나에 모든 기능을 구현한 것으로 보인다. 구조가 없이, 위에서 아래로 흘러가는 것이다.

예시

이를 테면, 사용자로부터 2개의 숫자를 입력 받아 더하는 프로그램을 만든다고 하자.

그러면 순차적 프로그래밍에서는 아래와 같이 코드를 짤 수 있다. 코드는 ChatGPT의 도움을 받았다.

#include <stdio.h>

int main() {
    // 프로그램 시작
    printf("두 숫자를 입력하세요.\n");

    // 1. 사용자로부터 첫 번째 숫자 입력 받기
    double num1;
    printf("첫 번째 숫자: ");
    scanf("%lf", &num1);

    // 2. 사용자로부터 두 번째 숫자 입력 받기
    double num2;
    printf("두 번째 숫자: ");
    scanf("%lf", &num2);

    // 3. 입력값에 대한 처리: 두 숫자 더하기
    double result = num1 + num2;

    // 4. 처리된 결과 출력
    printf("두 숫자의 합: %.2lf\n", result);

    // 5. 프로그램 종료
    printf("프로그램을 종료합니다.\n");

    return 0;
}

goto문

goto 문은 프로그램에서 특정 위치로 이동하는 명령문으로, 실행 흐름을 명시적으로 변경할 수 있다.

순차적 프로그래밍에서는 위에서 아래로 코드를 실행 시키는데, 예를 들어 어떤 조건에서는 특정 위치로 건너 뛰어서 실행시키고 싶을 때 사용한다.

아래 코드는 사용자로부터 정수를 입력 받았을 때

  • 입력 값이 음의 정수라면 오류 메시지를 출력하고
  • 입력 값이 0이나 양의 정수라면 화면에 결과를 출력한다.
#include <stdio.h>

int main() {
    int userInput;

    // 사용자로부터 정수 입력 받기
    printf("정수를 입력하세요: ");
    scanf("%d", &userInput);

    // 입력값이 0보다 작으면 error 레이블로 이동
    if (userInput < 0) {
        goto error;
    }

    // 입력값이 0보다 크거나 같으면 정상적인 결과 출력
    printf("입력한 수: %d\n", userInput);
    return 0;

// 오류 메시지 출력을 위한 레이블
error:
    printf("오류: 입력값이 0보다 작습니다.\n");
    return 1;
}

goto의 폐혜

goto를 사용하면 프로그램의 실행 순서를 이리저리 이동할 수 있게 된다. 그러나 이동이 잦아지면 코드를 이해하기에 복잡해질 가능성이 있다.

게다가 goto를 이용한 이동은 프로그램을 논리적으로 잘 구성하면 모두 피할 수 있는 것들이기 때문에, 자바에서는 원천적으로 사용을 금지하고 있다.

따라서 위 예제 코드들도 C언어를 사용했다.

자바에서의 goto

goto의 폐해로 자바는 아예 goto를 예약어로 선점해 사용하지 못하게 막아두었다.

자바 공식 문서에서 goto는 not used(사용 안함)임을 확인할 수 있다.

절차적 프로그래밍

goto를 사용하지 말자!

영어로는 procedural programming라고 한다.

순차적 프로그래밍에서는 중복되는 코드가 발생할 수밖에 없다.

이때, 중복되는 기능이나 관련 없는 기능들을 따로 분리함으로써 구조를 만든 프로그래밍 패러다임이 바로 절차적 프로그래밍이다.

이렇게 분리해낸 단위를 프로시저라고 하며, 보통 함수를 말한다.

  • 프로그램을 일련의 프로시저(절차 또는 함수)로 나누었다.
  • 각 프로시저는 특정 작업을 수행하며, 이러한 프로시저들이 순서대로 호출되어 전체 프로그램이 수행된다.
  • 호출을 통해 추상화와 재사용성을 얻어내는 것이 본질이다.
  • C, Pascal, Fortran 등의 언어가 절차적 프로그래밍 언어이다.

프로시저의 종류

  • 루틴: main 문
  • 서브루틴: main문 밖에서 정의한, 반환 값이 없는 코드 블럭
  • 함수: main문 밖에서 정의한, 반환 값이 있는 코드 블럭

예제

순차적 프로그래밍의 예제를 절차적 프로그래밍으로 변경한 결과이다.

#include <stdio.h>

// 함수 선언
void printWelcomeMessage();
double getUserInput(char message[]);
double addNumbers(double num1, double num2);
void printResult(double result);
void printProgramExitMessage();

int main() {
    // 프로그램 시작
    printWelcomeMessage();

    // 1. 사용자로부터 첫 번째 숫자 입력 받기
    double num1 = getUserInput("첫 번째 숫자: ");

    // 2. 사용자로부터 두 번째 숫자 입력 받기
    double num2 = getUserInput("두 번째 숫자: ");

    // 3. 입력값에 대한 처리: 두 숫자 더하기
    double result = addNumbers(num1, num2);

    // 4. 처리된 결과 출력
    printResult(result);

    // 5. 프로그램 종료
    printProgramExitMessage();

    return 0;
}

// 환영 메시지 출력 함수
void printWelcomeMessage() {
    printf("두 숫자를 입력하세요.\n");
}

// 사용자 입력 받기 함수
double getUserInput(char message[]) {
    double input;
    printf("%s", message);
    scanf("%lf", &input);
    return input;
}

// 두 숫자 더하기 함수
double addNumbers(double num1, double num2) {
    return num1 + num2;
}

// 결과 출력 함수
void printResult(double result) {
    printf("두 숫자의 합: %.2lf\n", result);
}

// 프로그램 종료 메시지 출력 함수
void printProgramExitMessage() {
    printf("프로그램을 종료합니다.\n");
}

구조적 프로그래밍

함수를 쓰자!

구조적 프로그래밍(structured programming)은 절차적 프로그래밍의 하위 개념으로 볼 수 있다.

구조적 프로그래밍은 함수를 쓰라는 것이다. 이렇게 함수를 사용하면 다음과 같은 이점이 있다.

  • 중복 코드를 한 곳에 모아 관리할 수 있다.
  • 논리를 함수 단위로 분리해서 이해하기 쉬운 코드를 작성할 수 있다.

구조적 프로그래밍의 지침 중에는 공유 사용 시 문제가 발생하기 쉬운 전역 변수보다는 지역 변수를 쓰라는 것도 있다.

순차적 프로그래밍 vs 절차적/구조적 프로그래밍

그림으로 보자면 아래와 같을 것이다.

객체지향 프로그래밍

인간은 이미 객체지향 방식으로 생각하고 있다.

절차적/구조적 프로그래밍까지의 과정은 인간이 기계를 이해하려는 노력에서 크게 벗어나지 못했다. 특히 포인터의 개념은 기계 수준으로 눈높이를 낮추지 않으면 이해하기 매우 힘든 부분이다.

이러한 기계 종속적인 개발에서 벗어나, 현실 세계처럼 프로그래밍할 수 없을까라는 고민 속에서 객체 지향의 개념이 탄생했다.

객체지향은 현실 세계를 반영한다.

우리가 주변에서 사물을 인지하는 방식대로 프로그래밍할 수 있지 않겠는가?

객체지향이 현실 세계를 반영한다는 증거는 바로 객체다.

  • 세상에 존재하는 모든 것은 사물, 즉 객체(Object)이다.
  • 각각의 사물은 고유하다.
  • 사물은 속성을 갖는다.
  • 사물은 행위를 한다.

객체

사물을 하나하나 이해하기보다는 사물을 분류(class)해서 이해하는 것이 인간의 인지법이다.

이를 테면, 우리는 다음과 같이 분류한다.

  • 직립보행을 하며 말을 하는 존재를 사람이라고 분류한다.
  • 연미복, 짧은 다리, 날지 못하는 새를 펭귄이라고 분류한다.
  • 밤하늘에 반짝이는 사물들을 별이라고 분류한다.

여기서 사람이라는 분류 안의 객체(Object)들은 나이, 몸무게, 키 등의 속성(property)과 먹다, 자다, 울다 등의 행위(method)를 가지고 있다.

객체 지향은 직관적이다

다시 정리하자면, 객체 지향은 실제 사물을 인지 및 사고하는 방식대로 객체 단위의 프로그래밍이 가능하다.

즉, 인간의 인지 및 사고 방식까지 프로그래밍에 접목하는 인간(개발자) 지향을 실천하고 있는 것이다. 그래서 객체 지향은 직관적이라고 할 수 있다.

자바 언어의 절자적/구조적 프로그래밍의 유산

절차적/구조적 프로그래밍에서 나온 개념들과 자바 언어는 다음과 같이 연결 시킬 수 있다.

  • goto문: 제어 흐름을 이리저리 이동시키는 용도 → 자바의 순서도와 제어문
  • 함수: 중복 코드 제거와 논리를 분할하기 위한 용도 → 자바의 메서드

결론적으로, 객체 지향 언어에서 절차적/구조적 프로그래밍의 유산은 메서드 안에서 확인할 수 있다.

객체 지향 프로그래밍에서 제어문이 존재할 수 있는 유일한 공간은 바로 메서드 내부이기 때문이다.

함수(Function) vs 메서드(Method)

둘은 다르지 않다.

절차적/구조적 프로그래밍에서는 함수라고 불렀는데, 객체 지향에서는 조금 다르게 불러야 할 것 같아서 메서드라고 이름 붙였다고 한다.

그래도 굳이 차이점을 찾는다면 함수는 클래스나 객체와 아무 관계가 없지만, 메서드는 반드시 클래스 정의 안에 존재해야 한다는 것이다.

💡 객체 지향 언어에서 클래스 외부에 존재할 수 있는 것은 없다.
import 문은 편의 기능이며, 타이핑을 적게 하기 위한 편의 기능일 뿐이다.

오해: 절차지향 vs 객체지향

절차지향?

인터넷에서 객체지향 프로그래밍을 검색하다 보면, 자주 ‘절차지향 프로그래밍’이라는 문장을 볼 수 있을 것이다.

그리고 이런 경우, 절차지향과 객체지향을 반대되는 개념으로 설명할 때가 많다.

그러나 절차지향이라는 단어부터가 틀린 것이다. 정확히 말하자면 ‘절차적’이 옳은 표현이다.

객체지향과 절차

프로그래밍의 기본 틀은 절차를 기반으로 두고 있다. 객체지향도 절차적 프로그래밍을 기반으로 객체라는 것을 도입한 것이다.

즉, 두 개념은 상반되는 개념이 아니다.

절차적 프로그래밍 언어와 객체지향 프로그래밍 언어

절차적 프로그래밍은 ‘데이터를 중심으로 함수’를 만들어 쓰는 편이고, 객체지향은 ‘데이터와 기능(함수)들을 묶어 하나의 객체’로 만들어 쓴다.

보통, 아래의 기준에 따라 절차적 언어와 객체지향 언어가 나뉜다.

  1. 캡슐화, 다형성, 클래스 상속을 지원하는가?
  2. 데이터 접근 제한을 걸 수 있는가?

보통은 위 기준을 만족하면 객체지향, 만족하지 않으면 절차적 성격이 강해진다.

정리

  • 객체 지향 프로그래밍은 연산자, 제어문, 메모리 관리 체계 등등 많은 부분을 절차적/구조적 프로그래밍에서 차용하고 있다.
  • C++도 C 언어를 부정한 것이 아니라 계승한 것이다.
  • 절차적/구조적 프로그래밍 기법도 잘 알고 있어야 한다.

Reference

참고 서적

📔 스프링 입문을 위한 자바 객체 지향의 원리와 이해

참고 사이트

구조적 프로그래밍

비구조적 프로그래밍과 구조적 프로그래밍

절차적/구조적 프로그래밍 - procedural/structed programming

[IT지식] 프로시저(PROCEDURE)란?

절차 지향

객체지향(OOP)과 절차적 프로그래밍(PP)

절차지향 VS 객체지향

[CS/Basic] 절차적 프로그래밍은 '절차지향'이 아니다!

객체지향, 왜 중요한지 모르겠지만 개념을 최대한 정리해봤다!

profile
책을 읽거나 강의를 들으며 공부한 내용을 정리합니다. 가끔 개발하는데 있었던 이슈도 올립니다.

0개의 댓글