๊ด€๋ฆฌ ๋ฉ”๋‰ด

deVlog

[๋””์ž์ธ ํŒจํ„ด] ์ƒ์„ฑ ํŒจํ„ด - Prototype Pattern (ํ”„๋กœํ† ํƒ€์ž… ํŒจํ„ด) ๋ณธ๋ฌธ

๐Ÿ› ๏ธ Software Architecture/Design Pattern

[๋””์ž์ธ ํŒจํ„ด] ์ƒ์„ฑ ํŒจํ„ด - Prototype Pattern (ํ”„๋กœํ† ํƒ€์ž… ํŒจํ„ด)

์€๋ฃจ๋ฐ 2025. 4. 3. 23:54

 

๋ชฉ์ฐจ

     

     

    ๐Ÿ“‡ ๊ฐœ์š”

    ํ”„๋กœํ† ํƒ€์ž… ํŒจํ„ด(Prototype Pattern)์€ ๊ธฐ์กด ๊ฐ์ฒด๋ฅผ ๋ณต์ œํ•˜์—ฌ ์ƒˆ๋กœ์šด ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๋Š” ์ƒ์„ฑ ๋””์ž์ธ ํŒจํ„ด์ด๋‹ค. ์ฆ‰, ์›ํ˜•์ด ๋˜๋Š” ์ธ์Šคํ„ด์Šค๋ฅผ ์‚ฌ์šฉํ•ด ์ƒˆ๋กœ์šด ์ธ์Šคํ„ด์Šค๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐฉ์‹์œผ๋กœ, ๊ฐ์ฒด ์ƒ์„ฑ ๋น„์šฉ์ด ํฐ ๊ฒฝ์šฐ์— ํšจ์œจ์ ์ด๋‹ค.

    โญ๏ธ ํŠน์ง•

    • ๊ธฐ์กด ๊ฐ์ฒด์˜ ์ƒํƒœ๋ฅผ ๊ทธ๋Œ€๋กœ ๋ณต์‚ฌํ•˜์—ฌ ์ƒˆ๋กœ์šด ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.
    • ๊ฐ์ฒด ์ƒ์„ฑ ๊ณผ์ •์˜ ๋ณต์žก์„ฑ์„ ๊ฐ์ถ˜๋‹ค.
    • ๊ฐ์ฒด ์ƒ์„ฑ ๋น„์šฉ์ด ํฐ ๊ฒฝ์šฐ์— ์„ฑ๋Šฅ์„ ํ–ฅ์ƒ์‹œํ‚จ๋‹ค.
    • ํ”„๋ ˆ์ž„์›Œํฌ ํ™•์žฅ ์‹œ ๊ตฌ์ฒด์ ์ธ ํด๋ž˜์Šค ์ •๋ณด ์—†์ด๋„ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.

     

    ๐Ÿ‘ฉ๐Ÿป‍๐Ÿ’ป ์ฝ”๋“œ๋กœ ์•Œ์•„๋ณด์ž

    ํ”„๋กœํ† ํƒ€์ž… ํŒจํ„ด์„ ๊ตฌํ˜„ํ•˜๋Š” ์—ฌ๋Ÿฌ ๋ฐฉ๋ฒ•์„ ์‚ดํŽด๋ณด์ž.

    1. Cloneable ์ธํ„ฐํŽ˜์ด์Šค ๊ตฌํ˜„

    // 1. Cloneable ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•œ ํ”„๋กœํ† ํƒ€์ž… ํด๋ž˜์Šค
    public class Shape implements Cloneable {
        private String type;
        private String color;
        
        public Shape() {
            // ๊ธฐ๋ณธ ์ƒ์„ฑ์ž
        }
        
        public Shape(String type, String color) {
            this.type = type;
            this.color = color;
        }
        
        // Java์—์„œ ์ œ๊ณตํ•˜๋Š” clone() ๋ฉ”์„œ๋“œ ์˜ค๋ฒ„๋ผ์ด๋“œ
        @Override
        public Shape clone() {
            try {
                // Object.clone()์€ ์–•์€ ๋ณต์‚ฌ(shallow copy)๋ฅผ ์ˆ˜ํ–‰
                return (Shape) super.clone();
            } catch (CloneNotSupportedException e) {
                e.printStackTrace();
                return null;
            }
        }
        
        // getters and setters
        public String getType() {
            return type;
        }
        
        public void setType(String type) {
            this.type = type;
        }
        
        public String getColor() {
            return color;
        }
        
        public void setColor(String color) {
            this.color = color;
        }
        
        @Override
        public String toString() {
            return "Shape [type=" + type + ", color=" + color + "]";
        }
    }
    
    // ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ
    public class PrototypeExample {
        public static void main(String[] args) {
            // ์›๋ณธ ๊ฐ์ฒด ์ƒ์„ฑ
            Shape originalShape = new Shape("Circle", "Red");
            System.out.println("Original: " + originalShape);
            
            // ํ”„๋กœํ† ํƒ€์ž…์„ ์ด์šฉํ•œ ๋ณต์ œ
            Shape clonedShape = originalShape.clone();
            System.out.println("Cloned: " + clonedShape);
            
            // ๋ณต์ œ๋œ ๊ฐ์ฒด ์ˆ˜์ •
            clonedShape.setColor("Blue");
            System.out.println("Modified Clone: " + clonedShape);
            System.out.println("Original After Clone Modification: " + originalShape);
        }
    }
    

    2. ๊นŠ์€ ๋ณต์‚ฌ(Deep Copy) ๊ตฌํ˜„

    // ๋ณต์žกํ•œ ๋‚ด๋ถ€ ๊ฐ์ฒด๋ฅผ ๊ฐ€์ง„ ํ”„๋กœํ† ํƒ€์ž… ํด๋ž˜์Šค
    public class ComplexShape implements Cloneable {
        private String name;
        private List<Point> points; // ๋‚ด๋ถ€ ๊ฐ์ฒด ์ฐธ์กฐ
        
        public ComplexShape(String name) {
            this.name = name;
            this.points = new ArrayList<>();
        }
        
        public void addPoint(Point point) {
            points.add(point);
        }
        
        // ๊นŠ์€ ๋ณต์‚ฌ ๊ตฌํ˜„
        @Override
        public ComplexShape clone() {
            try {
                ComplexShape cloned = (ComplexShape) super.clone();
                // ๋‚ด๋ถ€ List ๊ฐ์ฒด๋„ ๋ณต์ œ
                cloned.points = new ArrayList<>();
                
                // ๊ฐ Point ๊ฐ์ฒด๋„ ๋ณต์ œ
                for (Point point : this.points) {
                    cloned.points.add(point.clone());
                }
                
                return cloned;
            } catch (CloneNotSupportedException e) {
                e.printStackTrace();
                return null;
            }
        }
        
        // getters and setters
        
        @Override
        public String toString() {
            return "ComplexShape [name=" + name + ", points=" + points + "]";
        }
    }
    
    // ๋‚ด๋ถ€ ๊ฐ์ฒด ํด๋ž˜์Šค
    public class Point implements Cloneable {
        private int x;
        private int y;
        
        public Point(int x, int y) {
            this.x = x;
            this.y = y;
        }
        
        @Override
        public Point clone() {
            try {
                return (Point) super.clone();
            } catch (CloneNotSupportedException e) {
                return new Point(this.x, this.y);
            }
        }
        
        // getters and setters
        
        @Override
        public String toString() {
            return "(" + x + "," + y + ")";
        }
    }
    

    3. ์ง๋ ฌํ™”๋ฅผ ์ด์šฉํ•œ ๋ณต์ œ

    import java.io.*;
    
    public class SerializableShape implements Serializable {
        private static final long serialVersionUID = 1L;
        
        private String type;
        private String color;
        
        public SerializableShape(String type, String color) {
            this.type = type;
            this.color = color;
        }
        
        // ์ง๋ ฌํ™”๋ฅผ ํ†ตํ•œ ๊นŠ์€ ๋ณต์‚ฌ
        public SerializableShape deepCopy() {
            try {
                // ๊ฐ์ฒด๋ฅผ ๋ฐ”์ดํŠธ ์ŠคํŠธ๋ฆผ์œผ๋กœ ์ง๋ ฌํ™”
                ByteArrayOutputStream bos = new ByteArrayOutputStream();
                ObjectOutputStream oos = new ObjectOutputStream(bos);
                oos.writeObject(this);
                
                // ๋ฐ”์ดํŠธ ์ŠคํŠธ๋ฆผ์—์„œ ๊ฐ์ฒด๋กœ ์—ญ์ง๋ ฌํ™”
                ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
                ObjectInputStream ois = new ObjectInputStream(bis);
                return (SerializableShape) ois.readObject();
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }
        
        // getters and setters
        
        @Override
        public String toString() {
            return "SerializableShape [type=" + type + ", color=" + color + "]";
        }
    }
    

    4. ๋ณต์ œ ์ƒ์„ฑ์ž/ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ ์‚ฌ์šฉ

    public class Product {
        private String name;
        private double price;
        private List<String> features;
        
        // ๊ธฐ๋ณธ ์ƒ์„ฑ์ž
        public Product(String name, double price) {
            this.name = name;
            this.price = price;
            this.features = new ArrayList<>();
        }
        
        // ๋ณต์ œ ์ƒ์„ฑ์ž
        public Product(Product source) {
            this.name = source.name;
            this.price = source.price;
            // ๊นŠ์€ ๋ณต์‚ฌ
            this.features = new ArrayList<>(source.features);
        }
        
        // ์ •์  ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ
        public static Product copyOf(Product source) {
            return new Product(source);
        }
        
        public void addFeature(String feature) {
            features.add(feature);
        }
        
        // getters and setters
        
        @Override
        public String toString() {
            return "Product [name=" + name + ", price=" + price + ", features=" + features + "]";
        }
    }
    
    // ์‚ฌ์šฉ ์˜ˆ
    Product original = new Product("Smartphone", 999.99);
    original.addFeature("5G");
    original.addFeature("OLED Display");
    
    // ๋ณต์ œ ์ƒ์„ฑ์ž ์‚ฌ์šฉ
    Product clone1 = new Product(original);
    
    // ์ •์  ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ ์‚ฌ์šฉ
    Product clone2 = Product.copyOf(original);
    

    5. ์Šคํ”„๋ง ํ”„๋ ˆ์ž„์›Œํฌ์˜ ํ”„๋กœํ† ํƒ€์ž… ๋นˆ ์Šค์ฝ”ํ”„

    import org.springframework.context.annotation.Scope;
    import org.springframework.stereotype.Component;
    
    @Component
    @Scope("prototype")
    public class PrototypeBean {
        private String property;
        
        public PrototypeBean() {
            // ์ดˆ๊ธฐํ™” ์ž‘์—… (๋น„์šฉ์ด ํฐ ์ž‘์—… ๊ฐ€์ •)
            System.out.println("PrototypeBean instance created");
        }
        
        // getters and setters
    }
    
    // ์‚ฌ์šฉ ์˜ˆ (์Šคํ”„๋ง ์ปจํ…์ŠคํŠธ์—์„œ)
    @Autowired
    private ApplicationContext context;
    
    public void usePrototypes() {
        // ๋งค๋ฒˆ ์ƒˆ๋กœ์šด ์ธ์Šคํ„ด์Šค ์ƒ์„ฑ
        PrototypeBean bean1 = context.getBean(PrototypeBean.class);
        PrototypeBean bean2 = context.getBean(PrototypeBean.class);
        
        // bean1๊ณผ bean2๋Š” ์„œ๋กœ ๋‹ค๋ฅธ ์ธ์Šคํ„ด์Šค
        System.out.println(bean1 == bean2); // false
    }
    

     

     

    โ˜˜๏ธ ์žฅ/๋‹จ์ 

    โœ… ์žฅ์ 

    1. ๋ณต์žกํ•œ ๊ฐ์ฒด ์ƒ์„ฑ ๋น„์šฉ ์ ˆ๊ฐ
      • ๊ฐ์ฒด ์ƒ์„ฑ ๋น„์šฉ์ด ํฐ ๊ฒฝ์šฐ ์ด๋ฏธ ์ƒ์„ฑ๋œ ๊ฐ์ฒด๋ฅผ ๋ณต์ œํ•˜๋Š” ๊ฒƒ์ด ํšจ์œจ์ ์ด๋‹ค.
      • ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์กฐํšŒ, ๋„คํŠธ์›Œํฌ ์š”์ฒญ, ๋ณต์žกํ•œ ๊ณ„์‚ฐ ๋“ฑ์„ ํ”ผํ•  ์ˆ˜ ์žˆ๋‹ค.
    2. ๊ตฌ์ฒด์ ์ธ ํด๋ž˜์Šค์— ์˜์กดํ•˜์ง€ ์•Š๋Š” ๊ฐ์ฒด ์ƒ์„ฑ
      • ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๊ฐ์ฒด์˜ ๊ตฌ์ฒด์ ์ธ ํด๋ž˜์Šค๋ฅผ ๋ชฐ๋ผ๋„ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.
      • ๋‹คํ˜•์„ฑ์„ ํ™œ์šฉํ•œ ์œ ์—ฐํ•œ ์„ค๊ณ„๊ฐ€ ๊ฐ€๋Šฅํ•˜๋‹ค.
    3. ๋ณต์žกํ•œ ์ดˆ๊ธฐํ™” ์ฝ”๋“œ ์ œ๊ฑฐ
      • ๊ฐ์ฒด๋ฅผ ์ฒ˜์Œ๋ถ€ํ„ฐ ์ƒ์„ฑํ•˜๋Š” ๋Œ€์‹  ์ด๋ฏธ ์ดˆ๊ธฐํ™”๋œ ์ƒํƒœ๋ฅผ ๋ณต์‚ฌํ•˜์—ฌ ์‚ฌ์šฉํ•œ๋‹ค.
      • ์ดˆ๊ธฐํ™” ๋กœ์ง์„ ์ค‘๋ณตํ•ด์„œ ์ž‘์„ฑํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค.
    4. ์„ค์ •์ด๋‚˜ ์ƒํƒœ๊ฐ€ ๋น„์Šทํ•œ ๊ฐ์ฒด ์ƒ์„ฑ
      • ๊ธฐ์กด ๊ฐ์ฒด๋ฅผ ์•ฝ๊ฐ„๋งŒ ์ˆ˜์ •ํ•˜์—ฌ ์œ ์‚ฌํ•œ ์—ฌ๋Ÿฌ ๊ฐ์ฒด๋ฅผ ํšจ์œจ์ ์œผ๋กœ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.
      • ๋ฐ˜๋ณต์ ์ธ ๊ฐ์ฒด ์ƒ์„ฑ ์ฝ”๋“œ๋ฅผ ์ค„์ผ ์ˆ˜ ์žˆ๋‹ค.

    โŒ ๋‹จ์ 

    1. ๊นŠ์€ ๋ณต์‚ฌ์˜ ๊ตฌํ˜„ ๋ณต์žก์„ฑ
      • ๊ฐ์ฒด๊ฐ€ ์ˆœํ™˜ ์ฐธ์กฐ๋‚˜ ๋ณต์žกํ•œ ์ฐธ์กฐ ๊ด€๊ณ„๋ฅผ ๊ฐ€์งˆ ๊ฒฝ์šฐ ๊นŠ์€ ๋ณต์‚ฌ ๊ตฌํ˜„์ด ์–ด๋ ต๋‹ค.
      • ํŠนํžˆ ๋ณต์žกํ•œ ๊ฐ์ฒด ๊ทธ๋ž˜ํ”„์—์„œ ๋ชจ๋“  ๊ฐ์ฒด๋ฅผ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ๋ณต์ œํ•˜๊ธฐ ์–ด๋ ต๋‹ค.
    2. ์ƒ์„ฑ์ž ํ˜ธ์ถœ ํšŒํ”ผ
      • ๋ณต์ œ ๊ณผ์ •์—์„œ ๊ฐ์ฒด์˜ ์ƒ์„ฑ์ž๊ฐ€ ํ˜ธ์ถœ๋˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ๋‹ค.
      • ์ด๋กœ ์ธํ•ด ๊ฐ์ฒด ์ƒ์„ฑ ๊ณผ์ •์„ ์ถ”์ ํ•˜๊ฑฐ๋‚˜ ๋””๋ฒ„๊น…ํ•˜๊ธฐ ์–ด๋ ค์šธ ์ˆ˜ ์žˆ๋‹ค.
    3. ๊นŠ์€ ๋ณต์‚ฌ์™€ ์–•์€ ๋ณต์‚ฌ์˜ ์„ ํƒ
      • ์ƒํ™ฉ์— ๋”ฐ๋ผ ๊นŠ์€ ๋ณต์‚ฌ๊ฐ€ ํ•„์š”ํ• ์ง€ ์–•์€ ๋ณต์‚ฌ๊ฐ€ ์ ์ ˆํ• ์ง€ ๊ฒฐ์ •ํ•ด์•ผ ํ•œ๋‹ค.
      • ์ž˜๋ชป๋œ ์„ ํƒ์€ ์˜ˆ์ƒ์น˜ ๋ชปํ•œ ๋ฒ„๊ทธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ฌ ์ˆ˜ ์žˆ๋‹ค.
    4. ๋ณต์ œ ๋™์ž‘ ์ •์˜์˜ ์–ด๋ ค์›€
      • ์ผ๋ถ€ ๊ฐ์ฒด์˜ ๊ฒฝ์šฐ ์–ด๋–ค ์ƒํƒœ๋ฅผ ๋ณต์ œํ•ด์•ผ ํ•˜๊ณ  ์–ด๋–ค ์ƒํƒœ๋Š” ์œ ์ง€ํ•ด์•ผ ํ•˜๋Š”์ง€ ์ •์˜ํ•˜๊ธฐ ์–ด๋ ต๋‹ค.
      • ์˜ˆ๋ฅผ ๋“ค์–ด ID๋‚˜ ํƒ€์ž„์Šคํƒฌํ”„ ๊ฐ™์€ ๊ฐ’์€ ๋ณต์ œ๋˜์ง€ ์•Š์•„์•ผ ํ•  ์ˆ˜ ์žˆ๋‹ค.

     

    ๐Ÿ’ก ์ž๋ฐ”/์Šคํ”„๋ง ํ”„๋ ˆ์ž„์›Œํฌ์—์„œ์˜ ํ”„๋กœํ† ํƒ€์ž…

    1. ์ž๋ฐ”์˜ Cloneable ์ธํ„ฐํŽ˜์ด์Šค

    Java API์—์„œ๋Š” Cloneable ์ธํ„ฐํŽ˜์ด์Šค์™€ Object.clone() ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ํ”„๋กœํ† ํƒ€์ž… ํŒจํ„ด์„ ์ง€์›ํ•œ๋‹ค.

    public class CloneableExample implements Cloneable {
        private int id;
        private String name;
        
        // ์–•์€ ๋ณต์‚ฌ ๊ตฌํ˜„
        @Override
        public CloneableExample clone() throws CloneNotSupportedException {
            return (CloneableExample) super.clone();
        }
    }
    

    2. ์Šคํ”„๋ง์˜ ํ”„๋กœํ† ํƒ€์ž… ๋นˆ ์Šค์ฝ”ํ”„

    ์Šคํ”„๋ง ํ”„๋ ˆ์ž„์›Œํฌ์—์„œ๋Š” ๋นˆ ์Šค์ฝ”ํ”„๋ฅผ ํ†ตํ•ด ํ”„๋กœํ† ํƒ€์ž… ํŒจํ„ด์„ ์ง€์›ํ•œ๋‹ค.

    import org.springframework.context.annotation.Scope;
    import org.springframework.context.annotation.ScopedProxyMode;
    import org.springframework.stereotype.Component;
    
    // 1. ์• ๋…ธํ…Œ์ด์…˜์œผ๋กœ ํ”„๋กœํ† ํƒ€์ž… ์Šค์ฝ”ํ”„ ์ง€์ •
    @Component
    @Scope("prototype")
    public class PrototypeComponent {
        // ๋งค๋ฒˆ ์ƒˆ ์ธ์Šคํ„ด์Šค ์ƒ์„ฑ
    }
    
    // 2. ๋ฉ”์„œ๋“œ ๋ ˆ๋ฒจ์—์„œ ํ”„๋กœํ† ํƒ€์ž… ๋นˆ ์ •์˜
    @Configuration
    public class AppConfig {
        @Bean
        @Scope("prototype")
        public PrototypeBean prototypeBean() {
            return new PrototypeBean();
        }
    }
    
    // 3. XML ๊ตฌ์„ฑ์œผ๋กœ ํ”„๋กœํ† ํƒ€์ž… ๋นˆ ์ •์˜
    <!-- applicationContext.xml -->
    <bean id="prototypeBean" class="com.example.PrototypeBean" scope="prototype"/>
    

    3. ์Šคํ”„๋ง์˜ ApplicationContext์™€ ํ”„๋กœํ† ํƒ€์ž… ๋นˆ

    @Service
    public class SomeService {
        private final ApplicationContext context;
        
        @Autowired
        public SomeService(ApplicationContext context) {
            this.context = context;
        }
        
        public void doSomething() {
            // ํ•„์š”ํ•  ๋•Œ๋งˆ๋‹ค ์ƒˆ ์ธ์Šคํ„ด์Šค ํš๋“
            PrototypeBean bean = context.getBean(PrototypeBean.class);
            bean.process();
        }
    }
    

    4. ํ”„๋กœํ† ํƒ€์ž… ๋นˆ์„ ์‹ฑ๊ธ€ํ†ค ๋นˆ์— ์ฃผ์ž…ํ•˜๋Š” ๋ฌธ์ œ

    @Service // ๊ธฐ๋ณธ์ ์œผ๋กœ ์‹ฑ๊ธ€ํ†ค ์Šค์ฝ”ํ”„
    public class SingletonService {
        // ์ฃผ์˜: ์ด๋ ‡๊ฒŒ ์ฃผ์ž…ํ•˜๋ฉด ํ•ญ์ƒ ๊ฐ™์€ ํ”„๋กœํ† ํƒ€์ž… ์ธ์Šคํ„ด์Šค ์‚ฌ์šฉ
        @Autowired
        private PrototypeBean prototypeBean; // ํ•œ ๋ฒˆ๋งŒ ์ฃผ์ž…๋จ
        
        // ํ•ด๊ฒฐ์ฑ…: ObjectFactory ์‚ฌ์šฉ
        @Autowired
        private ObjectFactory<PrototypeBean> prototypeBeanFactory;
        
        public void correctWay() {
            // ๋งค๋ฒˆ ์ƒˆ ์ธ์Šคํ„ด์Šค ํš๋“
            PrototypeBean bean = prototypeBeanFactory.getObject();
            bean.process();
        }
    }
    

     

    ๐Ÿ“š ์‹ค์ œ ์‚ฌ์šฉ ์‚ฌ๋ก€

    1. ์ž๋ฐ”์˜ Object.clone()
      • Java ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ ์ œ๊ณตํ•˜๋Š” ๊ธฐ๋ณธ์ ์ธ ํ”„๋กœํ† ํƒ€์ž… ๋ฉ”์ปค๋‹ˆ์ฆ˜
      • ์˜ˆ: ArrayList, HashMap ๋“ฑ ์ปฌ๋ ‰์…˜ ๋ณต์ œ
    2. ์Šคํ”„๋ง ํ”„๋ ˆ์ž„์›Œํฌ์˜ ํ”„๋กœํ† ํƒ€์ž… ๋นˆ
      • ์Šคํ”„๋ง์—์„œ ๋นˆ์„ ํ”„๋กœํ† ํƒ€์ž… ์Šค์ฝ”ํ”„๋กœ ์ •์˜
      • ์˜ˆ: ์‚ฌ์šฉ์ž๋ณ„ ์„ค์ •, ์š”์ฒญ๋ณ„ ๊ฐ์ฒด ์ƒ์„ฑ
    3. ๋””์ž์ธ ์‹œ์Šคํ…œ์˜ UI ์ปดํฌ๋„ŒํŠธ
      • ๊ธฐ๋ณธ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ณต์ œํ•˜์—ฌ ๋‹ค์–‘ํ•œ ์Šคํƒ€์ผ์˜ ์ปดํฌ๋„ŒํŠธ ์ƒ์„ฑ
      • ์˜ˆ: ๋ฒ„ํŠผ, ์นด๋“œ, ํผ ์š”์†Œ ๋“ฑ์˜ ํ…œํ”Œ๋ฆฟ
    4. ๊ฒŒ์ž„ ๊ฐœ๋ฐœ์˜ ๊ฐ์ฒด ์ƒ์„ฑ
      • ๊ธฐ๋ณธ ๊ฒŒ์ž„ ๊ฐ์ฒด๋ฅผ ๋ณต์ œํ•˜์—ฌ ๋‹ค์–‘ํ•œ ์ธ์Šคํ„ด์Šค ์ƒ์„ฑ
      • ์˜ˆ: ์  ์บ๋ฆญํ„ฐ, ์•„์ดํ…œ, ์žฅ์• ๋ฌผ ๋“ฑ
    5. ๋ฌธ์„œ ํ…œํ”Œ๋ฆฟ ์‹œ์Šคํ…œ
      • ๊ธฐ๋ณธ ๋ฌธ์„œ๋ฅผ ๋ณต์ œํ•˜์—ฌ ์ƒˆ๋กœ์šด ๋ฌธ์„œ ์ƒ์„ฑ
      • ์˜ˆ: ์›Œ๋“œ ํ”„๋กœ์„ธ์„œ์˜ ํ…œํ”Œ๋ฆฟ, ๋ณด๊ณ ์„œ ์–‘์‹
    6. ์บ์‹ฑ ์‹œ์Šคํ…œ
      • ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ๊ฐ€์ ธ์˜จ ๊ฐ์ฒด๋ฅผ ์บ์‹œํ•˜๊ณ  ๋ณต์ œํ•˜์—ฌ ์‚ฌ์šฉ
      • ์˜ˆ: ์ฝ๊ธฐ ์ „์šฉ ๋ฐ์ดํ„ฐ ๋ณต์ œ
    7. ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ ํ™˜๊ฒฝ์˜ ์•ˆ์ „ํ•œ ๊ฐ์ฒด ๋ณต์ œ
      • ๊ณต์œ  ๊ฐ์ฒด์˜ ์Šค๋ƒ…์ƒท์„ ๋งŒ๋“ค์–ด ๊ฐ ์Šค๋ ˆ๋“œ์—์„œ ์•ˆ์ „ํ•˜๊ฒŒ ์‚ฌ์šฉ
      • ์˜ˆ: ๋ถˆ๋ณ€ ๊ฐ์ฒด์˜ ๋ณต์ œ๋ณธ ์ƒ์„ฑ
    8. ํ…Œ์ŠคํŠธ ํ”ฝ์Šค์ฒ˜ ์ƒ์„ฑ
      • ํ…Œ์ŠคํŠธ์— ํ•„์š”ํ•œ ๊ฐ์ฒด ์ƒํƒœ๋ฅผ ๋ฏธ๋ฆฌ ์„ค์ •ํ•˜๊ณ  ๋ณต์ œํ•ด์„œ ์‚ฌ์šฉ
      • ์˜ˆ: JUnit ํ…Œ์ŠคํŠธ์˜ ๊ธฐ๋ณธ ๋ฐ์ดํ„ฐ ์„ค์ •
    9. ๋„๋ฉ”์ธ ๊ฐ์ฒด ์ƒ์„ฑ
      • ๊ธฐ๋ณธ ๋„๋ฉ”์ธ ๊ฐ์ฒด๋ฅผ ํ…œํ”Œ๋ฆฟ์œผ๋กœ ์‚ฌ์šฉํ•˜์—ฌ ์œ ์‚ฌํ•œ ๊ฐ์ฒด ์ƒ์„ฑ
      • ์˜ˆ: ์ฃผ๋ฌธ, ๊ณ ๊ฐ, ์ œํ’ˆ ๋“ฑ์˜ ๊ธฐ๋ณธ ํ…œํ”Œ๋ฆฟ
    10. ์„ค์ • ๊ฐ์ฒด ๋ณต์ œ
      • ๊ธฐ๋ณธ ์„ค์ •์„ ๋ณต์ œํ•˜์—ฌ ์•ฝ๊ฐ„์˜ ์ˆ˜์ •๋งŒ์œผ๋กœ ์ƒˆ๋กœ์šด ์„ค์ • ์ƒ์„ฑ
      • ์˜ˆ: ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์„ค์ •, ์‚ฌ์šฉ์ž ํ”„๋กœํ•„

     

    ๐Ÿ“Œ ์ •๋ฆฌ

    ํ”„๋กœํ† ํƒ€์ž… ํŒจํ„ด์€ ๊ธฐ์กด ๊ฐ์ฒด๋ฅผ ๋ณต์ œํ•˜์—ฌ ์ƒˆ๋กœ์šด ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋””์ž์ธ ํŒจํ„ด์ด๋‹ค.

    ์ด ํŒจํ„ด์€ ๊ฐ์ฒด ์ƒ์„ฑ ๋น„์šฉ์ด ํฐ ๊ฒฝ์šฐ ์„ฑ๋Šฅ์„ ํ–ฅ์ƒ์‹œํ‚ค๊ณ , A ๊ตฌ์ฒด์ ์ธ ํด๋ž˜์Šค ์ •๋ณด ์—†์ด๋„ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค€๋‹ค. ํ•˜์ง€๋งŒ ๊นŠ์€ ๋ณต์‚ฌ ๊ตฌํ˜„์˜ ๋ณต์žก์„ฑ, ์ƒ์„ฑ์ž ํ˜ธ์ถœ ํšŒํ”ผ, ๋ณต์ œ ๋™์ž‘ ์ •์˜์˜ ์–ด๋ ค์›€ ๋“ฑ์˜ ๋‹จ์ ์ด ์žˆ๋‹ค.

    โœ… ์–ธ์ œ ์‚ฌ์šฉํ•˜๋ฉด ์ข‹์„๊นŒ?

    • ๊ฐ์ฒด ์ƒ์„ฑ ๋น„์šฉ์ด ํด ๋•Œ (DB ์กฐํšŒ, ๋„คํŠธ์›Œํฌ ์š”์ฒญ, ๋ณต์žกํ•œ ๊ณ„์‚ฐ ๋“ฑ)
    • ๋น„์Šทํ•œ ๊ฐ์ฒด๋ฅผ ๋‹ค์–‘ํ•œ ์ƒํƒœ๋กœ ์ƒ์„ฑํ•ด์•ผ ํ•  ๋•Œ
    • ๋Ÿฐํƒ€์ž„์— ํด๋ž˜์Šค๋ฅผ ๋™์ ์œผ๋กœ ์ถ”๊ฐ€ํ•˜๊ฑฐ๋‚˜ ์ œ๊ฑฐํ•ด์•ผ ํ•  ๋•Œ
    • ๊ฐ์ฒด์˜ ๊ตฌ์ฒด์ ์ธ ํƒ€์ž…์„ ์•Œ์ง€ ๋ชปํ•˜๊ฑฐ๋‚˜ ์˜์กดํ•˜๊ณ  ์‹ถ์ง€ ์•Š์„ ๋•Œ
    • ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ ํŒจํ„ด์œผ๋กœ๋Š” ๋„ˆ๋ฌด ๋งŽ์€ ์„œ๋ธŒํด๋ž˜์Šค๊ฐ€ ํ•„์š”ํ•  ๋•Œ

    โŒ ์–ธ์ œ ํ”ผํ•ด์•ผ ํ• ๊นŒ?

    • ๊ฐ์ฒด์˜ ๋‚ด๋ถ€ ์ƒํƒœ๊ฐ€ ๋งค์šฐ ๋ณต์žกํ•˜๊ฑฐ๋‚˜ ์ˆœํ™˜ ์ฐธ์กฐ๊ฐ€ ์žˆ์„ ๋•Œ
    • ๊ฐ์ฒด์˜ ์ƒ์„ฑ ๋น„์šฉ์ด ๋‚ฎ๊ณ  ๊ฐ„๋‹จํ•  ๋•Œ
    • ๊ฐ์ฒด๊ฐ€ ๊ณต์œ  ์ž์›์ด๋‚˜ ์™ธ๋ถ€ ๋ฆฌ์†Œ์Šค์— ์˜์กดํ•  ๋•Œ
    • ๊ฐ์ฒด์˜ ๋…๋ฆฝ์„ฑ์ด ์ค‘์š”ํ•œ ๊ฒฝ์šฐ