당신의 LLM들은 실제 OOP를 수행하지 않으며, 구조적입니다.

발행: (2026년 2월 18일 오후 07:35 GMT+9)
8 분 소요
원문: Dev.to

Source: Dev.to

생성형 AI는 매일 코드를 작성합니다

클래스, 서비스, 모델, 컨트롤러. 겉보기에는 모든 것이 올바른 것처럼 보입니다. 컴파일도 되고, 테스트도 통과하고, “작업을 수행합니다.”

그럼에도 반복되는 문제가 있습니다:

LLM이 생성한 코드는 종종 캡슐화가 부실합니다.
“조금”이 아니라.
구조적으로 캡슐화가 부실합니다.

게터와 세터로 가득 찬 클래스, 거의 행동이 없고, 비즈니스 로직이 여기저기 흩어져 있습니다. 요컨대: 객체‑지향이 아니라 데이터‑지향 코드입니다.

왜 그럴까요?
그리고 더 중요한 질문: AI를 사용할 때 어떻게 하면 더 나은 코드를 만들 수 있을까요?

OOP가 원래 의미했던 것 (그리고 우리가 잊은 것)

  • 클래스
  • private 속성
  • getter / setter
  • 인터페이스

하지만 이것은 원래의 비전이 아니다.

Alan Kay(OOP의 아버지 중 한 사람)에게 핵심 아이디어는 클래스가 아니라 메시지였다.

“OOP는 나에게 메시징, 로컬 보존 및 보호와 상태‑프로세스 숨기기, 그리고 모든 것의 극단적인 늦은 바인딩만을 의미한다.”

다시 말해:

  • 객체는 소통한다
  • 객체는 자신의 상태를 스스로 보관한다
  • 객체는 내부 로직을 숨긴다
  • 객체는 느슨하게 결합된다

그가 사용한 비유는 생물학적이었다: 내부 장기를 드러내지 않고 상호작용하는 자율 세포와 같다.

LLM이 대신 생성하는 것

Typical example generated by an AI:

public class User {
    private String email;

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }
}

깨끗하고 많은 튜토리얼에서 “베스트 프랙티스”라고 소개됩니다. 하지만 이는 캡슐화아닙니다.

왜일까요?

  • 내부 상태가 외부에 노출됨
  • 내부 타입이 고정됨
  • 검증 로직이 없음
  • 비즈니스 로직이 외부로 밀려남

결과: 행동 로직이 서비스, 컨트롤러 등에 흩어지거나, 더 나빠서는 어디에든 중복되어 나타납니다. 우리는 이를 빈약한 클래스(anemic class) 라고 부릅니다. 즉, 접근자만 가진 단순한 데이터 주머니에 불과합니다.

게터/세터의 잘못된 보안감

게터와 세터는 캡슐화를 제공하는 듯 보이지만 실제로는:

  • 내부 구조를 노출한다
  • 강한 결합을 만든다
  • 구현 결정을 고정시킨다

필드, 그 타입 또는 로직을 변경하면 곧 광범위한 파손이 발생한다. 객체지향 프로그래밍에서 상태를 노출하는 것은 거의 항상 추상화 누수이다.

객체에 물어볼 더 나은 질문

대신에 이렇게 물어보세요:

if (user.getEmail() == null) {
    // logic here
}

다음과 같이 물어보세요:

if (user.canBeContacted()) {
    // logic here
}

이미 진전이 있습니다:

  • 행동이 지역화되었습니다
  • 비즈니스 규칙이 객체 안에 있습니다
  • 구현이 진화할 수 있습니다

하지만 우리는 더 나아갈 수 있습니다.

메시지와 이벤트 접근 방식

Alan Kay의 비전에서 객체는 자신이 무엇인지 말하지 않고, 요청받은 것에 응답합니다.

상태를 읽는 대신:

  • 의도를 보낸다
  • 객체가 결정한다
  • 상태는 내부에 남는다

이벤트‑드리븐 또는 메시지‑지향 모델은 바로 이것을 가능하게 합니다:

  • 내부 상태 전이
  • 강력한 디커플링
  • 로직이 한 곳에 집중

이것은 “더 복잡한” 것이 아니라 더 명시적입니다.

Why LLMs struggle so much with real encapsulation

It’s not because AIs are “bad.” It’s structural.

  • They learn from existing code – GitHub is filled with CRUDs, DTOs, anemic classes.
  • Getters / setters are statistically dominant, so they’re “probable” and therefore generated.
  • Business behavior is contextual; LLMs excel at the local, less at global consistency.
  • Message‑oriented code is less verbose but more conceptual, making it harder to infer without explicit intention.

The AI doesn’t understand your domain. It extrapolates patterns.

AI를 활용해 OOP 코드를 더 잘 작성하는 방법

해결책은 AI 사용을 중단하는 것이 아니라, AI를 더 잘 안내하는 것입니다.

클래스를 생성할 때, 스스로에게 (그리고 모델에게) 다음 질문을 해 보세요:

  • 이 클래스가 무언가를 수행하나요, 아니면 단순히 데이터를 전달하나요?
  • 객체에 질문을 하나요, 아니면 상태를 읽나요?
  • 동작이 지역화되어 있나요, 아니면 흩어져 있나요?
  • 호출자를 깨뜨리지 않고 구현을 변경할 수 있나요?

답이 “아니오”라면, 이는 아마도 진정한 OOP가 아닐 것입니다.

실제 문제는 AI가 아니다

  • 우리는 빈약한 OOP를 정상화했습니다
  • 우리는 캡슐화를 가시성과 혼동했습니다
  • 우리는 행동을 데이터 구조로 대체했습니다

LLM은 단지 우리가 수년간 만들어온 것을 재현할 뿐입니다.

결론

캡슐화는 다음이 아니다:

  • 프라이빗 필드
  • 퍼블릭 getter
  • 수동적인 모델

캡슐화는 다음과 같다:

  • 자신의 상태를 책임지는 객체
  • 지역화된 비즈니스 규칙
  • 직접 접근보다 메시지
  • 최소한의 결합도

AI가 도움이 될 수는 있지만, 좋은 모델링을 절대 대체할 수는 없습니다.

추가 읽기

“Loopy Loops”를 Dave의 블로그에서 읽기

0 조회
Back to Blog

관련 글

더 보기 »

OpenClaw는 설계상 안전하지 않다

OpenClaw는 설계상 안전하지 않다. Cline 공급망 공격, 2월 17일. 인기 있는 VS Code 확장 프로그램인 Cline이 침해되었다. 공격 체인은 여러 AI‑...