절차지향 프로그래밍이란?
절차지향 프로그래밍은 프로그램을 절차(순차)적으로 구성하는 방법입니다. 이 방식은 코드를 순차적으로 실행하는 것에 중점을 두고 있으며, 프로그램의 흐름을 제어하는 함수들로 나누어 작업을 처리합니다.
- 절차지향의 주요 특징
- 순차적 처리 : 프로그램이 위에서 아래로 순서대로 실행됩니다.
- 함수 중심 : 코드의 기능을 수행하는 독립적인 함수로 구성되어 있습니다.
- 데이터와 함수의 분리 : 함수와 데이터가 서로 분리된 형태로 존재합니다.
절차지향 방식의 예시
int add(int a, int b) {
return a + b;
}
int main() {
int result = add(5, 10);
printf("Result: %d\n", result);
return 0;
}
위 코드에서 add() 함수가 두 숫자를 더하는 역할을 하며, main() 함수에서 이를 호출해 결과를 출력하는 구조입니다. 절차지향 방식은 간단한 문제를 해결하는 데 적합하지만, 프로그램이 커지고 복잡해질수록 유지보수 및 확장성에 한계가 생길 수 있습니다.
객체지향 프로그래밍이란?
객체지향 프로그래밍(Object-Oriented Programming, OOP)은 프로그램을 단순한 명령어의 집합이 아닌, 객체라는 독립적인 단위로 나누어 설계하는 방식입니다. 이 객체들은 속성(데이터)과 메서드(기능)를 가지고 있으며, 서로 상호작용하면서 프로그램이 동작하게 됩니다. 객체지향 프로그래밍의 주요 목표는 현실 세계의 개념을 프로그래밍에 반영하여 코드의 재사용성, 확장성, 유지보수성을 높이는 것입니다.
- 객체지향의 주요 개념
- 캡슐화 : 데이터와 관련 기능을 하나의 객체로 묶어 관리합니다.
- 상속: 기존 클래스의 속성과 기능을 새로운 클래스가 물려받을 수 있습니다.
- 추상화: 같은 이름의 메서드가 상황에 따라 다르게 동작할 수 있습니다.
- 다형성: 복잡한 시스템을 단순화해서 필요한 정보만을 외부에 제공하고, 불필요한 세부 사항은 숨깁니다.
객체지향 프로그래밍의 역사
객체지향 프로그래밍의 개념은 1960년대에 시뮬라(Simula)라는 프로그래밍 언어에서 시작되었습니다. 시뮬라는 최초로 클래스를 도입해 객체 기반의 프로그래밍을 가능하게 했습니다. 이후 1980년대에 등장한 C++은 C언어의 효율성과 객체지향의 장점을 결합해 프로그래밍 언어의 패러다임을 확장했습니다. 1990년대에 자바(Java)가 등장하면서 OOP를 더 널리 확산시켰습니다. 자바는 플랫폼 독립성이라는 장점을 내세우며 OOP의 개념을 더욱 발전시켰습니다. 자바는 "한 번 작성하면 어디서든 실행할 수 있다"라는 슬로건으로 객체지향의 확산을 주도했으며, 가비지 컬렉션을 통해 메모리 관리를 자동화해서 개발자의 부담을 줄였습니다.
객체지향 프로그래밍의 핵심 개념
클래스와 객체
클래스(Class)는 객체를 정의하는 청사진(템플릿)입니다. 클래스는 속성(데이터)과 메서드(함수)로 구성되며, 실제 동작을 수행하는 인스턴스는 객체(Object)라고 부릅니다. 아래 코드에서 Car 클래스는 자동차의 속성과 동작을 정의하는 설계도이며, car 객체는 그 클래스를 기반으로 만들어진 인스턴스입니다.
class Car {
// 속성 (필드)
String model;
int year;
// 생성자
Car(String model, int year) {
this.model = model;
this.year = year;
}
// 메서드
void drive() {
System.out.println(model + " is driving.");
}
}
public class Main {
public static void main(String[] args) {
Car car = new Car("Toyota", 2022); // 객체 생성
car.drive(); // 메서드 호출
}
}
캡슐화
캡슐화는 객체의 데이터를 외부에서 직접 접근하지 못하게 하고, 데이터를 보호하는 개념입니다. 보통 클래스 내의 필드는 private로 선언해 외부에서 접근하지 못하게 하고, 대신 메서드를 통해 데이터를 읽거나 수정할 수 있습니다. 이를 통해 데이터의 무결성을 보호하고, 객체 내부의 구현을 외부에 노출하지 않음으로써 유지보수가 쉬워집니다.
public class Person {
private String name; // private로 속성 감추기(외부에서 접근 불가)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
상속
상속은 기존 클래스의 특정을 물려받아 새로운 클래스를 정의하는 방식입니다. 상속을 통해 중복된 코드를 줄이고, 새로운 클래스에서 기존 기능을 확장하거나 수정할 수 있습니다. 아래 코드에서 Dog 클래스는 Animal 클래스를 상속받았으며, sound() 메서드를 재정의해서 개의 소리를 출력합니다.
public class Animal {
public void sound() {
System.out.println("동물이 소리를 냅니다.");
}
}
public class Dog extends Animal {
@Override
public void sound() {
System.out.println("개가 멍멍 짖습니다.");
}
}
public class Main {
public static void main(String[] args) {
Animal dog = new Dog();
dog.sound(); // 상속받은 메서드 실행
}
}
추상화
추상화는 객체의 복잡한 내부 구현을 감추고, 필요한 정보만 외부에 제공해서 복잡성을 줄이는 개념입니다. 추상화 덕분에 사용자는 객체의 구체적인 동작 방식에 대해 알 필요 없이 인터페이스 또는 추상 클래스를 통해 객체를 사용할 수 있습니다. 이를 통해 프로그램의 복잡성을 줄이고, 설계를 더 명확하게 할 수 있습니다
- 인터페이스 : 객체의 동작 규격을 정의하는 역할을 하며, 객체가 따라야 할 계약을 의미합니다.
- 추상 클래스 : 객체의 공통된 속성과 메서드를 정의하는 클래스이지만, 구체적인 구현은 하지 않고, 자식 클래스에서 구체적인 동작을 구현해야 합니다.
아래 코드에서 Animal 클래스는 추상 클래스로, 구체적인 sound() 메서드는 구현하지 않았지만, 자식 클래스인 Dog에서 구체적으로 구현했습니다. 추상화는 중요한 부분만 노출하고, 복잡한 세부 사항은 감추는 역할을 합니다.
abstract class Animal {
abstract void sound(); // 추상 메서드 (구현 X)
void sleep() {
System.out.println("잠을 잡니다."); // 일반 메서드 (구현 O)
}
}
class Dog extends Animal {
@Override
void sound() {
System.out.println("개가 멍멍 짖습니다."); // 구체적인 구현
}
}
public class Main {
public static void main(String[] args) {
Animal dog = new Dog();
dog.sound(); // "개가 멍멍 짖습니다."
dog.sleep(); // "잠을 잡니다."
}
}
다형성
다형성은 하나의 참조 변수가 여러 타입의 객체를 가리킬 수 있는 성질을 말합니다. 이를 통해 프로그램의 유연성과 확장성을 높일 수 있으며, 동일한 코드로 다양한 객체를 처리할 수 있게 해줍니다.
class Animal {
public void sound() {
System.out.println("동물이 소리를 냅니다.");
}
}
class Cat extends Animal {
@Override
public void sound() {
System.out.println("고양이가 야옹합니다.");
}
}
class Dog extends Animal {
@Override
public void sound() {
System.out.println("개가 멍멍합니다.");
}
}
// 다형성 예시
public class Main {
public static void main(String[] args) {
Animal dog = new Dog();
dog.sound(); // "개가 멍멍합니다."
}
}
절차지향 VS 객체지향
구분 | 절차지향 프로그래밍 | 객체지향 프로그래밍 |
중심 개념 | 함수와 절차 중심 | 객체와 클래스 중심 |
데이터 관리 | 데이터와 함수가 분리됨 | 데이터와 메서드가 객체 내에서 캡슐화됨 |
코드 재사용 | 함수 재사용에 의존 | 상속, 다형성을 통해 코드 재사용 가능 |
유지보수성 | 코드가 복집해질수록 유지보수가 어려움 | 모듈화된 코드로 유지보수가 용이함 |
예시 | C, JavaScript | Java, C++, Python |
객체지향 프로그래밍의 장점
- 코드 재사용성 : 상속과 다형성을 통해 기존 코드를 쉽게 재사용할 수 있습니다.
- 유지보수성 : 캡슐화와 모듈화 된 구조로 인해 코드 수정이 용이합니다.
- 유연성 : 객체 간의 관계를 통해 확장성과 유연성을 극대화할 수 있습니다.
- 현실 세계 모델링 : 실제 사물을 객체로 표현함으로써 직관적으로 시스템을 설계할 수 있습니다.
결론
절차지향에서 객체지향으로 넘어가는 것은 단순히 코드 작성 스타일의 변화가 아닌, 사고방식의 전환을 의미합니다. 객체지향 프로그래밍(OOP)은 소프트웨어 개발의 필수적인 패러다임으로 자리 잡고 있으며, 현실 세계의 문제를 컴퓨터 프로그래밍으로 해결하는 강력한 도구입니다. 객체지향의 기본 개념을 이해하고 활용함으로써 더 효율적이고 유지보수 가능한 코드를 작성할 수 있습니다.
'☕️Java[자바] > OOP[객체지향프로그래밍]' 카테고리의 다른 글
[객체지향 프로그래밍] 생성자와 객체 초기화 : 효울적인 객체 생성 방법 (0) | 2024.09.22 |
---|---|
[객체지향 프로그래밍] 캡슐화 - 데이터 보호와 정보 은닉의 핵심 원리 (0) | 2024.09.20 |
[객체지향 프로그래밍] 다형성 - 다양한 형태의 객체를 다루는 방법 (0) | 2024.09.18 |
[객체지향 프로그래밍] 추상화 - 복잡성을 줄이는 설계의 핵심 (1) | 2024.09.17 |
[객체지향 프로그래밍] 상속 - 코드의 재사용 (0) | 2024.09.17 |