본문 바로가기

개발 공부

객체지향 프로그래밍(OOP)

객체지향 프로그래밍(OOP)

객체지향 프로그래밍(Object-Oriented Programming, 이하 OOP)은 현실 세계를 프로그래밍에 그대로 옮겨놓은 것처럼 객체 단위로 코드를 구성하는 프로그래밍 패러다임입니다.

OOP에서는 데이터와 그 데이터를 다루는 함수를 하나의 단위로 묶어서 객체(Object) 라고 부릅니다.

이 객체들 간의 상호작용을 통해 프로그램이 동작하게 됩니다.

 

객체지향의 4대 특성

1. 캡슐화(Encapsulation)

  • 객체 내부의 상태(data)를 외부에서 직접 접근하지 못하도록 감추고, 메서드를 통해서만 접근하게 하는 원칙입니다.
  • 예: private 프로퍼티, public getter/setter
class User {
  private password: string;

  constructor(password: string) {
    this.password = password;
  }

  checkPassword(input: string): boolean {
    return this.password === input;
  }
}

 

 

2. 상속(Inheritance)

  • 부모 클래스의 속성과 메서드를 자식 클래스가 물려받을 수 있게 합니다.
  • 코드 재사용성과 확장성에 큰 장점이 있음
class Animal {
  move() {
    console.log("움직이는 중");
  }
}

class Dog extends Animal {
  bark() {
    console.log("멍멍!");
  }
}

 

 

3. 다형성(Polymorphism)

  • 같은 메서드 이름이라도 상황에 따라 다른 동작을 하도록 만드는 것입니다.
  • 오버라이딩, 오버로딩이 이에 해당
class Animal {
  speak() {
    console.log("소리를 낸다");
  }
}

class Cat extends Animal {
  speak() {
    console.log("야옹");
  }
}

 

4. 추상화(Abstraction)

  • 불필요한 내부 구현은 숨기고, 꼭 필요한 기능만 외부에 노출
  • 인터페이스나 추상 클래스로 구현
abstract class Shape {
  abstract getArea(): number;
}

class Rectangle extends Shape {
  constructor(private width: number, private height: number) {
    super();
  }

  getArea(): number {
    return this.width * this.height;
  }
}

 


 

예시: 게시글 필터링 기능

어떤 게시판 페이지에서 아래와 같은 기능이 있다고 가정해봅시다.

  • 게시글 리스트를 날짜, 조회수, 좋아요 순 등으로 정렬할 수 있음
  • 필터 타입은 점점 늘어날 수 있음
  • 확장성 있는 방식으로 필터 로직을 구성하고 싶음

나쁜 예시: if문 덕지덕지

function sortPosts(posts: Post[], sortType: string): Post[] {
  if (sortType === "latest") {
    return [...posts].sort((a, b) => b.createdAt - a.createdAt);
  }
  if (sortType === "views") {
    return [...posts].sort((a, b) => b.viewCount - a.viewCount);
  }
  if (sortType === "likes") {
    return [...posts].sort((a, b) => b.likeCount - a.likeCount);
  }
  return posts;
}
  • 처음에는 간단해 보여도 필터 종류가 늘어날수록 조건문이 꼬리를 물고 늘어지고, 테스트도 어려워집니다.

좋은 예시: 전략 패턴 + 객체지향

// 1. 필터 전략을 추상화 (추상 클래스 or 인터페이스)
interface PostSortStrategy {
  sort(posts: Post[]): Post[];
}

// 2. 각각의 전략 구현
class LatestSort implements PostSortStrategy {
  sort(posts: Post[]): Post[] {
    return [...posts].sort((a, b) => b.createdAt - a.createdAt);
  }
}

class ViewSort implements PostSortStrategy {
  sort(posts: Post[]): Post[] {
    return [...posts].sort((a, b) => b.viewCount - a.viewCount);
  }
}

class LikeSort implements PostSortStrategy {
  sort(posts: Post[]): Post[] {
    return [...posts].sort((a, b) => b.likeCount - a.likeCount);
  }
}

// 3. 컨텍스트 클래스
class PostSorter {
  constructor(private strategy: PostSortStrategy) {}

  setStrategy(strategy: PostSortStrategy) {
    this.strategy = strategy;
  }

  sort(posts: Post[]): Post[] {
    return this.strategy.sort(posts);
  }
}

 

실제 사용 예시 (React 컴포넌트)

const sortMap = {
  latest: new LatestSort(),
  views: new ViewSort(),
  likes: new LikeSort(),
};

function PostList({ posts }: { posts: Post[] }) {
  const [sortType, setSortType] = useState<keyof typeof sortMap>("latest");

  const sorter = new PostSorter(sortMap[sortType]);
  const sortedPosts = sorter.sort(posts);

  return (
    <div>
      <select onChange={(e) => setSortType(e.target.value as keyof typeof sortMap)}>
        <option value="latest">최신순</option>
        <option value="views">조회수순</option>
        <option value="likes">좋아요순</option>
      </select>

      {sortedPosts.map((post) => (
        <PostCard key={post.id} post={post} />
      ))}
    </div>
  );
}

 

객체지향 개념 정리

개념 예시
캡슐화 sort 메서드 내부 구현은 외부에서 몰라도 됨
추상화 PostSortStrategy 인터페이스로 전략들의 공통 구조 정의
다형성 LatestSort, ViewSort, LikeSort 모두 sort()를 다르게 구현
유지보수성 필터 전략 추가 시 if 조건문 없이 클래스 하나만 추가하면 끝