Backend
home
📘

[개념 정리] OCP-개방 폐쇄 원칙

생성 일시
2025/02/27 07:54
태그
Java
게시일
2025/02/28
최종 편집 일시
2025/03/01 14:34

1. 개방 폐쇄 원칙이란

소프트웨어 컴포넌트는 확장에 열려 있어야 하고 수정에 관해서는 닫혀 있어야 한다는 의미를 말한다.
다른 개발자가 작업을 수행하기 위해서는 반드시 수정해야 하는 제약 사항을 클래스에 포함해서는 안 된다는 사실을 의미한다.
다양하고 직관적이며 유해하지 않은 방식으로 소프트웨어 확장성을 유지하는 원칙이다.

2. 예시

개방-폐쇄 원칙을 따르지 않는 경우

Shape
package challenge.bad; public interface Shape {}
Java
복사
Rectangle
package challenge.bad; public class Rectangle implements Shape { private final int width; private final int weight; public Rectangle(int width, int weight) { this.width = width; this.weight = weight; } public int getWidth() { return width; } public int getWeight() { return weight; } }
Java
복사
Circle
package challenge.bad; public class Circle implements Shape { private final int radius; public Circle(int radius) { this.radius = radius; } public int getRadius() { return radius; } }
Java
복사
이 코드에서 클래스의 생성자를 활용하여 서로 다른 크기의 직사각형과 원을 쉽게 만들 수 있다. 여러 가지 도형을 만들었다면 모든 면적을 합할 차례이다. 면적의 합을 구하기 위해 AreaCalculator 클래스를 다음과 같이 정의한다.
AreaCalculator
package challenge.bad; import java.util.List; public class AreaCalculator { private final List<Shape> shapes; public AreaCalculator(List<Shape> shapes) { this.shapes = shapes; } /** * 도형을 추가하려면 이 클래스를 수정해야 한다. * 이 코드는 개방-폐쇄 원칙에 맞지 않는다. */ public double sum() { int sum = 0; for (Shape shape : shapes) { if (shape.getClass().equals(Circle.class)) { sum += (int) (Math.PI * Math.pow(((Circle) shape).getRadius(), 2)); } else if (shape.getClass().equals(Rectangle.class)) { sum += ((Rectangle) shape).getHeight() * ((Rectangle) shape).getWidth(); } } return sum; } }
Java
복사
각 도형은 면적을 구하기 위한 고유의 공식이 있으므로 도형의 유형을 구분하려면 if-else 또는 switch 구조가 필요하다. 또한 삼각형과 같은 새로운 도형을 추가하고 싶다면 새로운 if문을 추가하기 위해 AreaCalculator 클래스를 수정해야 한다. 이것은 이 코드가 개방-폐쇄 원칙을 위반한다는 것을 의미한다. 개방-폐쇄 원칙을 준수하도록 코드를 수정하려면 모든 클래스에서 몇 가지를 수정해야 한다.

개방-폐쇄 원칙을 따르는 경우

AreaCalculator에서 도형의 면적 계산 공식을 빼서 공식이 필요한 각 Shape 클래스로 옮기는 것이다. 즉 직사각형, 원 등의 각 도형에 해당하는 클래스에서 자신의 면적을 계산하도록 하는 것이다. 각 도형 클래스에서 면적을 계산하도록 Shape 인터페이스 정의에 area 메서드를 추가한다.
Shape
package challenge.good; public interface Shape { public double area(); }
Java
복사
Circle
package challenge.good; public class Circle implements Shape { private final int radius; public Circle(int radius) { this.radius = radius; } @Override public double area() { return Math.PI * Math.pow(radius, 2); } }
Java
복사
Rectangle
package challenge.good; public class Rectangle implements Shape { private final int width; private final int height; public Rectangle(int width, int height) { this.width = width; this.height = height; } @Override public double area() { return width * height; } }
Java
복사
AreaCalculator
package challenge.good; import java.util.List; public class AreaCalculator { private final List<Shape> shapes; public AreaCalculator(List<Shape> shapes) { this.shapes = shapes; } public double sum() { int sum = 0; for (Shape shape : shapes) { sum += (int) shape.area(); } return sum; } }
Java
복사
이 코드는 개방-폐쇄 원칙을 따른다. AreaCalculator 클래스를 수정하지 않고도 새로운 도형을 추가할 수 있기에 수정에 관해 닫혀 있으면서 확장에 관해서는 열려 있다.