프론트엔드/JavaScript

객체 지향 프로그래밍

Ryuzy 2025. 4. 13. 19:23
728x90
반응형

1. 프로그램 패러다임

프로그래밍을 바라보는 방식 또는 문제를 해결하기 위한 사고 방식입니다. 즉, "어떻게 프로그램을 구성하고 동작하게 할 것인가"에 대한 철학 또는 스타일입니다.

 

1. 절차 지향 프로그래밍

절차지향 프로그래밍은 코드를 순서대로 실행되는 일련의 절차(또는 단계)로 구성하는 방식입니다.
데이터와 기능을 분리하고, 함수를 사용하여 문제를 단계적으로 해결해 나가며,
흐름 중심으로 설계되기 때문에 프로그램이 위에서 아래로 흐르는 형태를 가집니다.
대표적인 절차지향 언어로는 C언어가 있으며, 작은 프로그램이나 계산 중심의 작업에 적합합니다.

const names = ["김사과", "반하나", "오렌지", "이메론"];

for (let i = 0; i < names.length; i++) {
  if (names[i].startsWith("김")) {
    console.log("안녕하세요, " + names[i] + "님!");
  }
}

 

2. 객체 지향 프로그래밍

객체지향 프로그래밍(Object-Oriented Programming, OOP)은 프로그램을 구성할 때 현실 세계의 사물들을 객체로 모델링하여, 객체 간의 상호작용을 통해 문제를 해결하는 방식입니다. 각 객체는 속성(데이터)과 행동(메서드)을 가지며, 객체들을 재사용하고 확장하며 협력하게 함으로써 코드의 재사용성, 유지보수성, 확장성을 높입니다. 자바스크립트에서는 객체 리터럴, 생성자 함수, 클래스(class)를 통해 객체를 만들 수 있으며, 주요 특징으로는 캡슐화, 상속, 추상화, 다형성이 있습니다.

const greeter = {
  names: ["김사과", "반하나", "오렌지", "이메론"],
  greetKim: function () {
    for (let name of this.names) {
      if (name.startsWith("김")) {
        console.log("안녕하세요, " + name + "님!");
      }
    }
  }
};

greeter.greetKim();

 

3. 함수형 프로그래밍

함수형 프로그래밍은 함수 자체를 중심에 두는 프로그래밍 패러다임으로, 데이터를 변경하지 않고(불변성), 순수 함수를 조합하여 문제를 해결합니다. 사이드 이펙트(부작용)를 최소화하고, 함수를 값처럼 전달하거나 반환할 수 있어 코드가 예측 가능하고 테스트하기 쉬운 장점이 있습니다. 자바스크립트에서는 map, filter, reduce 같은 메서드들이 함수형 프로그래밍을 지원합니다.

const names = ["김사과", "반하나", "오렌지", "이메론"];

names
  .filter(name => name.startsWith("김"))
  .forEach(name => console.log("안녕하세요, " + name + "님!"));

 

 

2. 객체 지향 프로그래밍이 중요한 이유

1. 복잡한 프로그램을 더 쉽게 구성할 수 있습니다.

현실처럼 "사람", "차", "학생" 같은 객체를 만들고, 그 객체가 스스로 행동하도록 구성하니 사고방식이 자연스럽고 직관적입니다.

 

2. 코드를 재사용하기 쉽습니다. (재사용성)

객체는 틀(클래스)로 만들고, 필요한 만큼 복사해서 사용할 수 있어요. 같은 구조의 객체를 쉽게 여러 개 만들 수 있고, 중복 코드 없이 효율적으로 개발할 수 있습니다.

 

3. 프로그램을 유지보수하고 수정하기가 쉽습니다. (확장성, 유지보수성)

객체는 역할별로 코드가 나뉘어져 있어서, 수정할 때 다른 부분에 영향을 덜 줍니다.

 

4. 현실 세계와 비슷해서 협업과 이해가 쉽습니다.

객체지향은 현실을 닮은 구조이기 때문에, 여러 사람이 함께 작업할 때도 누가 어떤 객체를 맡는지 명확하게 나눌 수 있고, 읽기도 이해하기도 쉬워집니다.

 

 

3. 객체

자바스크립트에서 객체(Object)는 하나의 값에 여러 데이터를 담을 수 있는 자료형으로, 속성(프로퍼티)과 동작(메서드)을 함께 표현할 수 있는 구조입니다. 객체는 현실 세계의 사물을 코드로 표현할 때 유용하며, 키-값 쌍(key-value pair)의 형태로 데이터를 저장합니다. 예를 들어 사람을 객체로 표현하면 name, age 같은 속성이 있고, sayHello() 같은 메서드를 가질 수 있습니다. 객체는 {} 중괄호로 감싸서 만들며, 자바스크립트에서 매우 중요한 자료형으로, 배열, 함수, 클래스도 결국은 객체 기반으로 동작합니다.

 

1. 객체 리터럴(Object Literal)

  • 중괄호 {} 안에 직접 속성과 메서드를 정의
  • 가장 흔하게 쓰이는 방식
const person = {
  name: "김사과",
  age: 20,
  greet: function() {
    console.log("안녕하세요, 저는 " + this.name + "입니다.");
  }
};

person.greet();

 

2. new Object() 생성자 사용

  • 객체를 빈 상태로 만들고, 나중에 속성 추가
  • 많이 쓰이진 않지만 원리적으로 알아두면 좋습니다.
const person = new Object();
person.name = "반하나";
person.age = 25;
person.greet = function() {
  console.log("안녕하세요, 저는 " + this.name + "입니다.");
};

person.greet();

 

3. 생성자 함수(Constructor Function)

  • new 키워드와 함께 사용
  • 객체를 여러 개 찍어낼 수 있는 템플릿(틀) 역할
function Person(name, age) {
  this.name = name;
  this.age = age;
  this.greet = function() {
    console.log("안녕하세요, 저는 " + this.name + "입니다.");
  };
}

const p1 = new Person("이메론", 30);
p1.greet();

 

4. 클래스(Class, ES6)

  • 구조가 명확하고 객체지향 언어와 유사
  • 생성자 함수보다 더 깔끔하고 요즘 많이 사용
class Person {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }

  greet() {
    console.log(`안녕하세요, 저는 ${this.name}입니다.`);
  }
}

const p2 = new Person("배애리", 27);
p2.greet();

 

5. Object.create() 사용

  • 기존 객체(proto)를 프로토타입으로 삼는 새 객체 생성
  • 상속을 구현할 때 유용
const proto = {
  greet: function() {
    console.log(`안녕하세요, 저는 ${this.name}입니다.`);
  }
};

const person = Object.create(proto);
person.name = "안가도";
person.age = 32;

person.greet();

 

 

4. 객체 복사

자바스크립트에서 객체는 참조값(주소)를 저장합니다. 그래서 객체를 복사한다고 해도, 단순히 같은 객체를 함께 가리키게 될 수 있습니다.

const obj1 = { name: "김사과" };
const obj2 = obj1;

obj2.name = "오렌지";

console.log(obj1.name);

 

1. 얕은 복사(Shallow Copy)

얕은 복사는 객체의 1단계 속성만 복사하고, 속성 값이 또 다른 객체나 배열이면 참조만 복사합니다.

const obj1 = { name: "김사과", age: 20 };
const obj2 = Object.assign({}, obj1);

obj2.name = "오렌지";
console.log(obj1.name);

 

const obj1 = { name: "김사과", age: 20 };
const obj2 = { ...obj1 };

obj2.age = 25;
console.log(obj1.age);

 

const obj1 = {
  name: "김사과",
  address: { city: "서울" }
};

const obj2 = { ...obj1 };
obj2.address.city = "부산";

// address는 객체이기 때문에, obj1과 obj2가 같은 주소를 공유합니다.
console.log(obj1.address.city); // "부산" 😨

 

2. 깊은 복사(Deep Copy)

객체 내부의 모든 중첩된 값들까지 복사하는 방법입니다. 즉, 완전히 새로운 객체를 만드는 것입니다.

function deepCopy(value) {
  // 원시값은 그대로 반환
  if (typeof value !== "object" || value === null) {
    return value;
  }

  // 배열일 경우
  if (Array.isArray(value)) {
    const result = [];
    for (let i = 0; i < value.length; i++) {
      result[i] = deepCopy(value[i]);
    }
    return result;
  }

  // 객체일 경우
  const result = {};
  for (let key in value) {
    result[key] = deepCopy(value[key]);
  }
  return result;
}

const original = {
  name: "오렌지",
  scores: [90, 80, 100],
  address: {
    city: "서울",
    zip: "12345"
  }
};

const copy = deepCopy(original);
copy.name = "김사과";
copy.scores[0] = 70;
copy.address.city = "부산";

console.log(original.name);
console.log(original.scores[0]);
console.log(original.address.city);

 

 

5. 스프레드 문법

스프레드 문법은 ... (점 3개)를 사용해서 배열이나 객체의 값을 펼쳐서(전개해서) 복사하거나 전달할 수 있는 문법입니다. 즉, 배열이나 객체 안의 요소들을 하나하나 꺼내서 다른 배열, 객체, 함수 등으로 옮겨줄 수 있습니다.

const fruits = ["사과", "바나나"];
const newFruits = [...fruits, "포도"];
console.log(newFruits);

 

// arr2는 arr1의 복사본 (같은 값이지만 서로 다른 배열)
const arr1 = [1, 2, 3];
const arr2 = [...arr1]; // 새 배열 생성

 

const a = [1, 2];
const b = [3, 4];
const result = [...a, ...b];

 

function add(x, y, z) {
  return x + y + z;
}

const nums = [1, 2, 3];
console.log(add(...nums)); // 6

 

const person = { name: "김사과", age: 20 };
const copy = { ...person };

 

const a = { name: "김사과" };
const b = { age: 20 };
const merged = { ...a, ...b };

 

 

6. rest 문법

rest 문법은 ...을 사용해서 여러 개의 값을 "하나로 묶는" 문법이에요. 남는 값들을 전부 모아서 하나의 변수에 담아주는 역할을 합니다.

const numbers = [1, 2, 3, 4, 5];

const [first, second, ...rest] = numbers;

console.log(first);
console.log(second);
console.log(rest);

 

function sum(...nums) {
  let total = 0;
  for (let n of nums) {
    total += n;
  }
  return total;
}

console.log(sum(1, 2, 3));
console.log(sum(10, 20, 30, 40));

 

const user = {
  name: "김사과",
  age: 20,
  city: "서울"
};

const { name, ...rest } = user;

console.log(name);
console.log(rest);

 

 

7. 객체 구조 분해 할당

구조 분해 할당(Destructuring Assignment)은 배열이나 객체에서 원하는 값을 꺼내어 변수에 간단하게 할당할 수 있게 해주는 문법입니다. 배열에서는 순서대로, 객체에서는 속성 이름을 기준으로 값을 꺼낼 수 있어 가독성이 좋고 코드가 간결해집니다.

const obj = { name: "김사과", age: 20 };
const { name, age } = obj;

console.log(name);
console.log(age);

 

function display({name, age, address, job}) {
  console.log(name, age, address, job);
}

const apple = {name:'김사과', age:20, address: {si:'서울시', gu:'서초구', dong:'양재동'}};
console.log(apple);
const new_apple = { ...apple, job: '프로그래머'};
display(new_apple);

 

// new_apple에 pet 속성이 없으면 → "루시"를 기본값으로 사용합니다.
const { pet = "루시" } = new_apple;

 

// new_apple.job 속성 값을 변수 hobby에 저장합니다.
// 원래 이름은 job, 내가 쓰고 싶은 이름은 hobby!
const { job: hobby } = new_apple;

 

// styles라는 속성 안에 있는 color를 꺼냅니다.
const component = {
  name: 'Button',
  styles: {
    size: 20,
    color: 'black'
  }
};

function changeColor({ styles: { color } }) {
  console.log(color); // "black"
}
728x90
반응형