Develop/Design Pattern

Design Pattern : VO ( Value Object ) μ™œ μ‚¬μš©ν• κΉŒ ?

proggg 2024. 10. 31. 22:10
728x90

μ½”λ“œλ“€μ„ μ‚΄νŽ΄λ³΄λ‹€κ°€ VO κ°€ λ°œκ²¬λλ‹€. 이것이 무엇인고.. ν•˜λ‹ˆ value object λž€λ‹€. μ•Œκ³  μžˆμ–΄μ•Ό ν•  것 κ°™λ‹€. DAO DTO VO impl ... μ•„μ£Ό λͺ¨λ₯΄κ² λŠ”것듀 νˆ¬μ„±μ΄μ΄λ‹€. λ””μžμΈνŒ¨ν„΄μ„ 곡뢀해야겠닀고 λ§ˆμŒλ¨Ήμ€ μˆœκ°„μ΄μ—ˆλ‹€. 자격증 μ‹œν—˜ λ³Ό λ•Œ μžˆμ—ˆλ˜ μ—„μ²­ λ§Žμ€ λ””μžμΈνŒ¨ν„΄λ“€μ΄ μžˆλ‹€λŠ” 사싀을 μ•Œμ§€λ§Œ 일단 λ‚΄ μ—…λ¬΄μ˜ λ””μžμΈνŒ¨ν„΄μ€ μ•Œμ•„μ•Όκ² λ‹€. μ–΄μ°¨ν”Ό κ°λ™μ—†λŠ” 배움은 금방 μžŠν˜€μ§€κΈ° λ•Œλ¬Έ..

1. VO( Value Obejct ) λŠ” λ¬΄μ—‡μΌκΉŒ

VO 의 κ·Έ 사전적인 μ˜λ―ΈλŠ” μ•„λž˜μ™€ κ°™λ‹€. 

VO(Value Object)λŠ”  κ°μ²΄μ§€ν–₯ ν”„λ‘œκ·Έλž˜λ°μ—μ„œ λ°μ΄ν„°μ˜ 일관성과 μ½”λ“œμ˜ 가독성을 높이기 μœ„ν•΄ μ‚¬μš©λ˜λŠ” μ€‘μš”ν•œ κ°œλ…μž…λ‹ˆλ‹€. VOλŠ” κ°œλ³„μ μœΌλ‘œ 식별될 ν•„μš” 없이, κ·Έ λ‚΄λΆ€ κ°’λ§ŒμœΌλ‘œ μ •μ˜ λ˜λŠ” κ°μ²΄μž…λ‹ˆλ‹€. 즉, 두 VO 객체가 같은 값을 가지면 λ™μΌν•œ κ²ƒμœΌλ‘œ μ·¨κΈ‰λ©λ‹ˆλ‹€. μ΄λŸ¬ν•œ νŠΉμ„± 덕뢄에 VOλŠ” 도메인 λͺ¨λΈλ§μ΄λ‚˜ 데이터 전달 객체둜 널리 μ‚¬μš©λ©λ‹ˆλ‹€.

 

도메인λͺ¨λΈλ§μ€ 뭐고 데이터 전달 κ°μ²΄λŠ” 뭘까. 이건 λ‹€μŒμ— μ•Œμ•„λ³΄λ„λ‘ ν•˜κ³ , μ•Œμ•„μ•Ό ν•  것은 

 

1. VOκ°€ λ°μ΄ν„°μ˜ 일관성과 μ½”λ“œμ˜ 가독성을 높인닀.

2. VOλŠ” κ°œλ³„μ μœΌλ‘œ 식별 될 ν•„μš” 없이, κ·Έ λ‚΄λΆ€ κ°’λ§ŒμœΌλ‘œ μ •μ˜ λ˜λŠ” 객체이닀.

 

이 λ‘κ°œ 인것 κ°™λ‹€. κ°œλ³„μ μœΌλ‘œ 식별 될 ν•„μš” 없이 같은 값을 가지면 λ™μΌν•œ κ²ƒμœΌλ‘œ μ·¨κΈ‰λ˜λŠ”λ° 이것이 μ–΄λ–»κ²Œ (1) μ½”λ“œμ˜ 가독성을 λ†’μ΄λŠ”μ§€λŠ” 사싀 잘 와닿지 μ•ŠλŠ”λ‹€. 

 

(2) 의 μ •μ˜κ°€ λ‚΄λΆ€ 값이 κ°™λ‹€κ³  같은 κ²ƒμœΌλ‘œ μ·¨κΈ‰λœλ‹€. λΌλŠ” μ„€λͺ…μ—μ„œ λ§ˆμΉ˜μ§€λ§Œ, 사싀 μ—¬κΈ°μ—λŠ” κ°œλ³„μ μœΌλ‘œ 식별 될 ν•„μš” μ—†λ‹€. κ°€ 더 μ€‘μš”ν•˜λ‹€. 예λ₯Όλ“€μ–΄ 직윑면체λ₯Ό 그리기 μœ„ν•΄

int sidelength_1

int sidelength_2

int sidelength_3

int sidelength_4

int sidelength_5

int sidelength_6 

 

처럼 primitive type 으둜 ν•˜λ‚˜μ”© μ„ μ–Έν•˜λŠ” 것이 μ•„λ‹ˆλΌ. 그것을 μœ„ν•œ 객체λ₯Ό λ§Œλ“€κ³  κ·Έ 객체의 값이 κ°™λ‹€λ©΄ λ™μΌν•œ κ²ƒμœΌλ‘œ μ—¬κΈ°κ² λ‹€λŠ” μ˜λ―Έμ΄λ‹€. 값을 μœ„ν•œ 객체인 것이닀. 


2. VO( Value Obejct ) μ™œ μ“°λŠ”κ±ΈκΉŒ ?

VO κ°€ μ‚¬μš©λ˜λŠ” μ΄μœ λŠ” primitive type 이 μ–΄λ–€ λ„λ©”μΈμ˜ 객체λ₯Ό μ„€λͺ…ν•˜κΈ° λΆ€μ‘±ν•˜κΈ° λ•Œλ¬Έμ΄λ‹€.

즉, primitive type 으둜 λ‹€κ°ν˜•μ„ λ§Œλ“€κΈ° μœ„ν•΄μ„œλŠ” μ§μ‚¬κ°ν˜•μ„ μœ„ν•œ primitive type 의 속성이 ν•„μš”ν•˜κ³ , μ •μ˜€κ°ν˜•μ˜ primitive type 속성이 ν•„μš”ν•˜κ²Œ 될 것 이닀. λ‹€κ°ν˜•μ„ λ§Œλ“€κΈ° μœ„ν•΄μ„œ 맀번 λ³€μˆ˜λ₯Ό λ§Œλ“€μ–΄ 쀄 것인가 ? μš°λ¦¬λŠ” 객체λ₯Ό μ•Œκ³  있기 λ•Œλ¬Έμ— κ·ΈλŸ΄ν•„μš”κ°€ μ—†λ‹€.

 

이런 κ°„λ‹¨ν•œ μ‚¬λ‘€μ²˜λŸΌ VO κ°€ primitive type 보닀 잘 μ“°μΈλ‹€λŠ” 즉 ν•„μš”ν•˜λ‹€λŠ” 것을 μ‚΄νŽ΄λ³΄μž.

 

2.1 ) primitive type 을 객체가 μ œλŒ€λ‘œ ν™œμš©ν•˜μ§€ μ•ŠλŠ”λ‹€. 

public class Ladder {

    private final int width;
    private final int height;

    public void Ladder(int width, int height) {
        this.width = width;
        this.height = height;
    }
}

 

μ΄λ•Œ Ladder μƒμ„±μž μΈμˆ˜λŠ” int λ₯Ό μ‚¬μš©ν•˜μ§€λ§Œ, μ§„μ§œ Ladder 객체가 width 와 heigth λ₯Ό 잘 μ‚¬μš©ν–ˆμ„κΉŒ ? 

 

μ•„λ‹ˆλ‹€. κ·Έ μ΄μœ λŠ” μžλ£Œν˜•μ˜ 속성을 μ œλŒ€λ‘œ κ³ λ €ν•˜μ§€ μ•Šμ€κ²ƒμ΄κΈ° λ•Œλ¬Έμ΄λ‹€. λ‹¨μ μœΌλ‘œ

1. μ‚¬λ‹€λ¦¬μ˜ 높이가 λ”ν•΄μ§€λŠ” κΈ°λŠ₯이 ν•„μš”ν•œκ°€ ?
2. μ‚¬λ‹€λ¦¬μ˜ 높이λ₯Ό κ³±ν•˜κ±°λ‚˜ λ‚˜λˆ„λŠ” 것이 κ°€λŠ₯ν•œκ°€?
3. μ‚¬λ‹€λ¦¬μ˜ 높이가 μŒμˆ˜κ°€ λ˜λŠ”κ²ƒμ΄ κ°€λŠ₯ν•œκ°€?

의 μ§ˆλ¬Έμ—μ„œ "예"λŠ” μ—†λ‹€. integer λŠ” μœ„μ˜ 연산이 κ°€λŠ₯ν•œ μžλ£Œν˜•μΈλ° μ™œ integer λ₯Ό ν™œμš©ν•΄μ•Ό ν• κΉŒ ? 이 점이 객체가 primitive λ₯Ό μ œλŒ€λ‘œ ν™œμš©ν•˜μ§€ μ•ŠλŠ”λ‹€λŠ” 것이닀. 

 

μ΄λ ‡κ²Œ 별 생각없이 λ„λ©”μΈμ˜ 속성을 λ‚˜νƒ€λ‚΄κΈ° μœ„ν•΄μ„œ primitive type 을 μ“°λŠ” κ΄€μŠ΅μ„ primitive obsession이라고 ν•œλ‹€. 

 

[μ°Έμ‘°] https://ksh-coding.tistory.com/83

 

VO(Value Object)λŠ” λ¬΄μ—‡μΌκΉŒ? μ™œ μ‚¬μš©ν• κΉŒ?

1. VO(Value Object)λž€? VO의 의미λ₯Ό 보면 λ‹€μŒκ³Ό κ°™λ‹€. * VOλž€ λ„λ©”μΈμ—μ„œ ν•œ 개 λ˜λŠ” κ·Έ μ΄μƒμ˜ 속성듀을 λ¬Άμ–΄μ„œ νŠΉμ • 값을 λ‚˜νƒ€λ‚΄λŠ” 객체λ₯Ό μ˜λ―Έν•œλ‹€. * ν•΄λ‹Ή 속성듀을 primitive νƒ€μž…μ΄λ‹€! (int, boolean, ...

ksh-coding.tistory.com

 

2.2 ) ν•œ 곳이 μ•„λ‹ˆλΌ μ—¬λŸ¬κ³³μ—μ„œ μ‚¬μš©λ  λ•Œ 쀑볡 μ½”λ“œκ°€ λ°œμƒν•œλ‹€. 

 

λ„ˆλΉ„μ™€ 높이λ₯Ό κ°€μ§€λŠ” 것이 사닀리 뿐 μ•„λ‹ˆλΌ μ§μ‚¬κ°ν˜• λ„ν˜•λ„ κ°€μ§ˆ 수 μžˆλ‹€. μ΄λ•Œ 사닀리와 μ§μ‚¬κ°ν˜•μ€ λ„ˆλΉ„μ™€ 높이에 λŒ€ν•œ μœ νš¨μ„±μ„ κ²€μ‚¬ν•œ 후에 μƒμ„±λ˜μ–΄μ•Ό ν•œλ‹€. κ·Έλ ‡κΈ° λ•Œλ¬Έμ— μ§μ‚¬κ°ν˜•κ³Ό 사닀리 처럼 넓이와 λ†’μ΄μ˜ 속성을 κ°€μ§€λŠ” λͺ¨λ“  객체에 μ€‘λ³΅λ˜λŠ” μ½”λ“œκ°€ λ°œμƒ ν•  것이닀. 

κ·Έλž˜μ„œ 높이와 λ„ˆλΉ„κ°€ μ œλŒ€λ‘œ μ‚¬μš©λ˜μ–΄ 헀메지 μ•Šλ„λ‘  섀계λ₯Ό ν•΄μ•Ό ν•  것이닀. 

 

 

2.3 )  ν•œ 곳이 μ•„λ‹ˆλΌ μ—¬λŸ¬ κ³³μ—μ„œ μ‚¬μš©λ  λ•Œ λΆˆλ³€μ„ ν•œ λ²ˆμ— 보μž₯ν•  수 μ—†λ‹€. 

2-2 와 λ§ˆμ°¬κ°€μ§€λ‘œ λ„ˆλΉ„μ™€ 높이λ₯Ό κ°€μ§€λŠ” 것이 사닀리 뿐 μ•„λ‹ˆλΌ λ‹€λ₯Έ λ„ν˜•μ˜ 객체도 κ°€μ§ˆ 수 μžˆλŠ”λ°, 이 λ•Œλ¬Έμ— λ‚΄κ°€ λ§ˆμ§€λ§‰μœΌλ‘œ μ ‘κ·Όν–ˆλ˜ 객체의 λ„ˆλΉ„κ°€ μ§μ‚¬κ°ν˜•μΈμ§€ 사닀리꼴인지 보증할 수 μžˆλ‚˜? μ—†λ‹€. 이것을 μœ„ν•΄μ„œλŠ” 각 객체 μ„ μ–Έ λ‹¨κ³„μ—μ„œ final 이 λΆ™μ—ˆλŠ”μ§€ ν™•μΈν•΄μ•Όν•œλ‹€ κ·Έλ§ˆμ €λ„ μ—†μœΌλ©΄ λ‚΄κ°€ μ–΄λ–€ λ„ˆλΉ„μ— μ ‘κ·Όν–ˆλŠ”μ§€ μ•Œ 수 μ—†κ²Œ λœλ‹€.  λ”°λΌμ„œ VO λ₯Ό 톡해 이 λ¬Έμ œμ λ“€μ„ μ μ ˆν•œ μ„€κ³„λ‘œ ν•΄κ²°ν•˜λ €λŠ” 것이닀. 

 

 

βœ… VO κ°€ μ§„μ§œλ‘œ μ‚¬μš©λ˜λŠ” 이유 

1. primitive νƒ€μž…μ˜ κΈ°λŠ₯듀을 'κ°’'이 λ‹€ μ‚¬μš©ν•˜μ§€ μ•ŠλŠ”λ‹€.
2. 'κ°’'이 μ—¬λŸ¬ κ³³μ—μ„œ μ‚¬μš©λ˜λ©΄ 정보가 λͺ¨λ‘ μ—¬λŸ¬ 곳에 퍼져 있기 λ•Œλ¬Έμ—, μœ νš¨μ„± κ²€μ‚¬λ‚˜ λΆˆλ³€ 체크 등을 ν•΄λ‹Ή 'κ°’'이 μžˆλŠ” λͺ¨λ“  κ°μ²΄μ—μ„œ μ§„ν–‰ν•΄μ•Όν•œλ‹€.

 

 

3.  VO( Value Obejct ) 생성 μ œμ•½μ‘°κ±΄/νŠΉμ§•

1. λΆˆλ³€μ„± (Immutability)

VOλŠ” 일반적으둜 λΆˆλ³€μ„±μ„ 가지며, ν•œ 번 μƒμ„±λœ ν›„ κ·Έ 값이 λ³€κ²½λ˜μ§€ μ•ŠλŠ”λ‹€. λΆˆλ³€μ„±μ„ 톡해 λ°μ΄ν„°μ˜ 일관성을 보μž₯ν•˜κ³ , 데이터가 예기치 μ•Šκ²Œ λ³€κ²½λ˜λŠ” 문제λ₯Ό 방지할 수 μžˆλ‹€.예λ₯Ό λ“€μ–΄, MoneyλΌλŠ” VO 객체가 μžˆμ„ λ•Œ, amount와 currencyλΌλŠ” 값이 μ΄ˆκΈ°ν™”λœ μ΄ν›„μ—λŠ” λ³€κ²½λ˜μ§€ μ•ŠλŠ”κ²ƒμ΄γ…γ„·.

2. 동등성_κ°’μœΌλ‘œλΉ„κ΅λœ (Equality by Value)

VOλŠ” λ™μΌν•œ 값을 κ°€μ§€λŠ” 경우 λ™μΌν•œ 객체둜 κ°„μ£Όλ©λ‹ˆλ‹€. 이둜 인해 VOλŠ” λ©”λͺ¨λ¦¬ μ£Όμ†Œκ°€ μ•„λ‹ˆλΌ 객체가 가진 값에 따라 동일성을 νŒλ‹¨ν•˜κ²Œ λ©λ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄, 두 Address 객체가 street, city, state, postalCodeκ°€ λͺ¨λ‘ κ°™λ‹€λ©΄ λ™μΌν•œ 객체둜 μΈμ‹λ©λ‹ˆλ‹€.

3. μžκ°€ μœ νš¨μ„± 검사 (Self -Validation)

primitive type 을 μ‚¬μš© ν–ˆμ„ λ•Œ μ‚¬μš© ν•  λͺ¨λ“  κ³³μ—μ„œ μœ νš¨μ„± 검사λ₯Ό ν•΄μ•Όν•œλ‹€λŠ” 문제점이 μžˆμ—ˆλ‹€. VO λ₯Ό μ‚¬μš©ν•œλ‹€λ©΄ 격리된 객체 μ•ˆμ—μ„œ μœ νš¨μ„±μ„ κ²€μ‚¬ν•˜μ—¬ μ‚¬μš© ν•  수 μžˆλ‹€. 

 

4.  VO( Value Obejct ) μ‚¬μš© μ˜ˆμ‹œ

μ•žμ„œ λ„ˆλΉ„μ™€ λ†’μ΄μ˜ μ‚¬λ‹€λ¦¬λ‘œ VO λ₯Ό μ„€λͺ…ν–ˆλŠ”λ°, primitive type 이 μ•„λ‹Œ VO νŠΉμ„±μ„ μ§€μΌœμ„œ λ§Œλ“€μ–΄λ³΄λ©΄ μ•„λž˜μ™€ κ°™λ‹€. 

public class ShapeProperty {
		
    // λΆˆλ³€μ„± (Immutable)
    private final int width;
    private final int height;

    public Shape(final int width, final int height) {
        // μžκ°€ μœ νš¨μ„± 검사 (Self-Validation)
        validateWidth(width);
        validateHeight(height);
        
        this.width = width;
        this.height = height;
    }

    // 동등성 (Equality)
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        ShapeProperty that = (ShapeProperty) o;
        return width == that.width && height == that.height;
    }

    @Override
    public int hashCode() {
        return Objects.hash(width, height);
    }
}

 

VO λ₯Ό ν†΅ν•΄μ„œ width 와 height λ₯Ό μ‚¬μš© ν•  μˆ˜λ„ μžˆλŠ” κ°μ²΄μ—λŠ” ShapeProperty 객체λ₯Ό μ‚¬μš©ν•΄ κ·Έ 값을 보μž₯ν•˜λŠ” 것이닀. μ•„λž˜λŠ” VO λ₯Ό ν™œμš©ν•΄ 사닀리λ₯Ό μ„ μ–Έν•œ 것이닀. 

// μ›μ‹œ νƒ€μž… μ‚¬μš©
public class Ladder {
		
    private final int width;
    private final int height;

    public void Ladder(int width, int height) {
    	validateWidth(width);
        validateHeight(height);
        
        this.width = width;
        this.height = height;
    }
}

// VO둜 λ³€κ²½
public class Ladder {
		
    private final ShapeProperty shapeProperty;

    public void Ladder(final ShapeProperty shapeProperty) {
        this.shapeProperty = shapeProperty;
    }
}

 

끝. 

728x90