프로토타입 기반 언어란 무엇인가요?

김상욱·2024년 11월 15일

프로토타입 기반 언어란 무엇인가요?

프로토타입 기반 언어는 클래스의 개념 없이 객체를 중심으로 동작하는 객체 지향 프로그래밍 언어를 의미. 객체 생성과 상속의 개념이 클래스가 아닌 프로토타입을 기반으로 이루어짐.

  1. 클래스가 없음 : 클래스 기반 언어는 객체 생성 시 클래스를 미리 정의해야 하지만 프로토타입 기반 언어는 기존 객체를 복사하여 새로운 객체를 생성
  2. 프로토타입 상속 : 객체는 다른 객체를 상속받아 동작을 확장하거나 수정할 수 있음. 이를 프로토타입 체인이라고 함. 상속을 구현하기 위해 [[Prototype]] 또는 __proto__와 같은 내부 프로퍼티를 활용합니다.
  3. 동적 속성 추가 : 객체에 속성을 동적으로 추가하거나 제거할 수 있다. 런타임 시 객체의 구조를 변경할 수 있어 유연한 설계가 가능
  4. 새로운 객체는 기존 객체를 복제하여 생성. 이를 원형 객체(prototype object)라고 부릅니다.

객체를 동적으로 수정하고 확장 가능하며, 클래스 정의가 필요 없기에 코드가 간단하다. 또한 기존 객체를 복사하여 새로운 객체를 쉽게 생성이 가능하다.

하지만, 프로토타입 체인이 깊어질 수록 디버깅이나 유지보수가 어려워질 수 있으며 클래스 기반이 아니기에 구조적 규칙이 약해 코드의 일관성이 떨어질 수 있다. 또한 런타임 시 동적인 속성 추가나 상속이 이루어지기 때문에 성능에 문제가 될 수 있다.

ex) JavaScript : 가장 대표적인 프로토타입 기반 언어

// 프로토타입 객체 생성
const animal = {
    sound: function() {
        console.log(this.noise);
    }
};

// animal을 프로토타입으로 하는 객체 생성
const dog = Object.create(animal);
dog.noise = "Bark!";
dog.sound(); // 출력: "Bark!"

// animal을 프로토타입으로 하는 또 다른 객체 생성
const cat = Object.create(animal);
cat.noise = "Meow!";
cat.sound(); // 출력: "Meow!"

Java Spring/Spring Boot와 관련하여 프로토타입 기반 언어의 개념을 이해하거나 응용할 실습은 직접적인 연관이 적지만, 이 개념을 활용하여 Java에서 객체 지향의 동작 방식과 비교하거나 유연한 객체 생성 및 처리를 연습하는 데 도움이 될 수 있습니다. 특히 백엔드 개발자로서 객체 생성 및 의존성 주입을 이해하는 데 응용할 수 있습니다.

다음은 신입 백엔드 개발자로서 실습 가능한 방향과 아이디어입니다.


1. Java에서 프로토타입 패턴을 활용한 객체 생성

Spring은 객체 생성을 관리하는 빈 스코프(Bean Scope)로 프로토타입(prototype) 스코프를 제공합니다. 이를 활용해 객체의 유연한 생성과 관리를 실습할 수 있습니다.

실습 아이디어

  • 싱글톤 vs 프로토타입 스코프 비교 실습
    Spring Boot에서 @Scope("prototype")과 @Scope("singleton")을 설정하고, 빈의 생성 및 사용 방식을 비교합니다.
@Component
@Scope("prototype")
public class PrototypeBean {
    public PrototypeBean() {
        System.out.println("Prototype Bean 생성");
    }
}

@Component
@Scope("singleton")
public class SingletonBean {
    public SingletonBean() {
        System.out.println("Singleton Bean 생성");
    }
}

@RestController
public class ScopeController {
    private final PrototypeBean prototypeBean;
    private final SingletonBean singletonBean;

    public ScopeController(PrototypeBean prototypeBean, SingletonBean singletonBean) {
        this.prototypeBean = prototypeBean;
        this.singletonBean = singletonBean;
    }

    @GetMapping("/scope")
    public String testScope() {
        System.out.println("Prototype Bean: " + prototypeBean);
        System.out.println("Singleton Bean: " + singletonBean);
        return "Check console for results!";
    }
}
  • 결과 확인
    • Prototype Bean은 매 요청마다 새로 생성되고, Singleton Bean은 애플리케이션 전체에서 하나만 생성됩니다.

2. Java에서 프로토타입 패턴 구현

Java에서는 프로토타입 기반 객체 생성을 구현하기 위해 Prototype Design Pattern을 사용할 수 있습니다. 이를 통해 객체를 동적으로 복제(clone)하는 방법을 익히고 Spring의 프로토타입 스코프와 비교할 수 있습니다.

실습 아이디어

  • Java에서 Cloneable 인터페이스를 사용해 객체 복제 연습
class Animal implements Cloneable {
    String name;

    public Animal(String name) {
        this.name = name;
    }

    @Override
    public Animal clone() throws CloneNotSupportedException {
        return (Animal) super.clone();
    }
}

public class PrototypeExample {
    public static void main(String[] args) throws CloneNotSupportedException {
        Animal dog = new Animal("Dog");
        Animal clonedDog = dog.clone();

        System.out.println("Original: " + dog.name);
        System.out.println("Cloned: " + clonedDog.name);
    }
}
  • Spring Bean Prototype과 비교
    위 코드를 Spring의 @Scope("prototype")과 결합해 비교하면, 직접적으로 객체를 복제하는 방식과 Spring Container가 관리하는 객체 생성 방식의 차이를 이해할 수 있습니다.

3. 의존성 주입(DI)에서 동적 객체 생성

Spring에서는 동적으로 필요한 객체를 생성하거나 프로토타입 스코프의 객체를 주입하기 위해 ObjectProvider를 사용합니다. 이를 실습해보면 객체 생성을 유연하게 처리하는 방법을 익힐 수 있습니다.

실습 아이디어

  • ObjectProvider를 사용해 프로토타입 객체 동적 생성
@Component
@Scope("prototype")
public class DynamicBean {
    public DynamicBean() {
        System.out.println("Dynamic Bean 생성");
    }
}

@RestController
public class DynamicController {
    private final ObjectProvider<DynamicBean> dynamicBeanProvider;

    public DynamicController(ObjectProvider<DynamicBean> dynamicBeanProvider) {
        this.dynamicBeanProvider = dynamicBeanProvider;
    }

    @GetMapping("/dynamic")
    public String createDynamicBean() {
        DynamicBean bean = dynamicBeanProvider.getObject();
        System.out.println("사용 중인 Bean: " + bean);
        return "Dynamic Bean 생성 완료!";
    }
}
  • 결과 확인
    /dynamic 엔드포인트를 호출할 때마다 새로운 객체가 생성됨을 확인할 수 있습니다.

4. Rest API를 활용한 객체 관리와 생성

백엔드 개발자로서 객체 관리 및 생성을 API로 설계해보는 것도 실습이 될 수 있습니다.

실습 아이디어

  • 사용자 정의 객체 생성 API 구현
    • POST 요청으로 JSON 데이터를 받아 동적으로 객체를 생성하고 관리
    • 객체의 속성을 동적으로 수정하거나 확장 가능하도록 설계
@RestController
@RequestMapping("/api/objects")
public class ObjectController {
    private final List<Map<String, Object>> objects = new ArrayList<>();

    @PostMapping
    public Map<String, Object> createObject(@RequestBody Map<String, Object> data) {
        objects.add(data);
        return data;
    }

    @GetMapping
    public List<Map<String, Object>> getObjects() {
        return objects;
    }
}
  • 결과 확인
    • POST /api/objects로 JSON 데이터를 보내 객체 생성
    • GET /api/objects로 현재 저장된 객체 리스트 확인

5. 실제 프로젝트 응용: 플러그인 시스템

프로토타입 기반 객체 생성은 플러그인 시스템 설계에 적합합니다. 동적으로 새로운 기능을 추가하거나 변경할 수 있는 구조를 만들어보세요.

실습 예제

  • 플러그인 관리 시스템
    • 플러그인 인터페이스를 설계
    • 플러그인 등록/삭제 API 구현
    • 동적으로 플러그인 기능 실행

실습을 통해 배울 수 있는 점

  • 객체 지향 설계의 유연성과 한계
  • Spring에서의 스코프와 객체 관리
  • 동적 객체 생성 및 의존성 주입
  • Rest API 설계와 객체 처리

이와 같은 실습을 통해 Spring/Spring Boot의 실제 동작 원리와 객체 관리를 이해하고, 유연한 설계 방식을 학습할 수 있습니다.

0개의 댓글