Readable Code - dnwls16071/Backend_Summary GitHub Wiki

๐Ÿ“š ์ถ”์ƒ(ๆŠฝ่ฑก)

  • ๊ฐ€๋…์„ฑ(Readability) = ๊ธ€์ด ์ž˜ ์ฝํžŒ๋‹ค = ์ดํ•ด๊ฐ€ ์ž˜ ๋œ๋‹ค = ์œ ์ง€๋ณด์ˆ˜ ํ•˜๊ธฐ ์ˆ˜์›”ํ•˜๋‹ค = ์‹œ๊ฐ„๊ณผ ์ž์›์ด ์ ˆ์•ฝ๋œ๋‹ค.

์ถ”์ƒ(abstract) vs ๊ตฌ์ฒด(concrete)

  • ์ถ”์ƒ = ํŠน์ • ์ธก๋ฉด์„ ๊ฐ€๋ ค๋‚ด๊ณ  ๋ถˆํ•„์š”ํ•œ ๋ถ€๋ถ„์„ ๋ฒ„๋ฆฐ๋‹ค.

๋„ค์ด๋ฐ(naming)๐Ÿค”

  • โœ…๏ธ์ด๋ฆ„์„ ์ง“๋Š”๋‹ค๋Š” ํ–‰์œ„๋Š” ์ถ”์ƒ์  ์‚ฌ๊ณ ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•œ๋‹ค.
    • ํ‘œํ˜„ํ•˜๊ณ ์ž ํ•˜๋Š” ๊ตฌ์ฒด์—์„œ ์ •๋ง ์ค‘์š”ํ•œ ํ•ต์‹ฌ ๊ฐœ๋…๋งŒ์„ ์ถ”์ถœํ•ด ์ž˜ ๋“œ๋Ÿฌ๋‚ด๋Š” ํ‘œํ˜„
    • ์šฐ๋ฆฌ ๋„๋ฉ”์ธ์˜ ๋ฌธ๋งฅ ์•ˆ์—์„œ ์ดํ•ด๋˜๋Š” ์šฉ์–ด
  • โœ…๏ธ๋‹จ์ˆ˜์™€ ๋ณต์ˆ˜๋ฅผ ๊ตฌ๋ถ„ํ•˜์ž.
    • ๋์— -(e)s๋ฅผ ๋ถ™์—ฌ ์–ด๋–ค ๋ฐ์ดํ„ฐ๊ฐ€ ๋‹จ์ˆ˜์ธ์ง€ ๋ณต์ˆ˜์ธ์ง€๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ๊ฒƒ๋งŒ์œผ๋กœ๋„ ์ฝ๋Š” ์ด์—๊ฒŒ ์ค‘์š”ํ•œ ์ •๋ณด๋ฅผ ๊ฐ™์ด ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋‹ค.
  • โœ…๏ธ์ด๋ฆ„์„ ์ค„์ด์ง€ ์•Š๋Š”๋‹ค.
    • ๊ฐ€๋…์„ฑ์„ ํฌ์ƒํ•ด ์–ป๋Š” ๋ถ€๋ถ„์œผ๋กœ ์žƒ๋Š” ๊ฒƒ์— ๋น„ํ•ด ์–ป๋Š” ๊ฒƒ์ด ์ ๋‹ค.
  • โœ…๏ธ์€์–ด/๋ฐฉ์–ธ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค.
    • ๋„๋ฉ”์ธ ์šฉ์–ด๋ฅผ ๋จผ์ € ์ •์˜ํ•˜๋Š” ๊ณผ์ •์ด ๋จผ์ € ํ•„์š”ํ•  ์ˆ˜๋„ ์žˆ๋‹ค. ๋ชจ๋‘๊ฐ€ ์•„๋Š” ๊ฒƒ์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.

๋ฉ”์„œ๋“œ ์ถ”์ƒํ™”(method abstraction)๐Ÿค”

  • โœ…๏ธํ•œ ๋ฉ”์„œ๋“œ์˜ ์ฃผ์ œ๋Š” ๋ฐ˜๋“œ์‹œ ํ•˜๋‚˜๋‹ค.
    • ๋ฉ”์„œ๋“œ์˜ ์ด๋ฆ„์œผ๋กœ ๊ตฌ์ฒด์ ์ธ ๋‚ด์šฉ์„ ์ถ”์ƒํ™”ํ•œ๋‹ค.
  • โœ…๏ธ์ƒ๋žตํ•  ์ •๋ณด์™€ ์˜๋ฏธ๋ฅผ ๋ถ€์—ฌํ•˜๊ณ  ๋“œ๋Ÿฌ๋‚ผ ์ •๋ณด๋ฅผ ๊ตฌ๋ถ„ํ•œ๋‹ค.

๋ฉ”์„œ๋“œ ์„ ์–ธ๋ถ€๐Ÿค”

  • โœ…๏ธvoid ๋Œ€์‹  ๋ฐ˜ํ™˜ํ•  ๋งŒํ•œ ๊ฐ’์ด ์žˆ๋Š”์ง€ ๊ณ ๋ฏผํ•ด๋ณธ๋‹ค. -> ๋ฐ˜ํ™˜๊ฐ’์ด ์žˆ๋‹ค๋ฉด ํ…Œ์ŠคํŠธ๊ฐ€ ์šฉ์ดํ•˜๊ธฐ ๋•Œ๋ฌธ์—

๋งค์ง ๋„˜๋ฒ„, ๋งค์ง ์ŠคํŠธ๋ง๐Ÿค”

  • โœ…๏ธ๋งค์ง ๋„˜๋ฒ„/๋งค์ง ์ŠคํŠธ๋ง : ์˜๋ฏธ๋ฅผ ๊ฐ–๊ณ  ์žˆ์œผ๋‚˜ ์ƒ์ˆ˜๋กœ ์ถ”์ถœ๋˜์ง€ ์•Š์€ ์ˆซ์ž, ๋ฌธ์ž์—ด ๋“ฑ
    • ์ด๋Ÿฐ ์ƒ์ˆ˜ ์ถ”์ถœ์„ ํ†ตํ•ด ์ด๋ฆ„์„ ์ง“๊ณ  ์˜๋ฏธ๋ฅผ ๋ถ€์—ฌํ•จ์œผ๋กœ์จ ๊ธฐ๋…์„ฑ๊ณผ ์œ ์ง€๋ณด์ˆ˜์„ฑ์„ ๋†’์ธ๋‹ค.
แ„‰แ…ณแ„แ…ณแ„…แ…ตแ†ซแ„‰แ…ฃแ†บ 2025-09-10 11 01 07

๐Ÿ“š ๋…ผ๋ฆฌ/์‚ฌ๊ณ ์˜ ํ๋ฆ„

Early Return

  • Early Return์œผ๋กœ else์˜ ์‚ฌ์šฉ์„ ์ง€์–‘ํ•˜์ž.
// badโŒ
int get_string_type(char* string) {
    int ret = 0;
    if (is_rule_1(string)) {
        ret = 1;
    } else {
        if (is_rule_2(string)) {
            ret = 2;
        } else {
            ret = 0;
        }
    }

    return ret;
}

// goodโญ•
int is_valid(char* string) {
    if (is_rule_1(string))
        return 1;
    if (is_rule_2(string))
        return 2;

    return 0;
}

๊ณต๋ฐฑ ๋ผ์ธ์˜ ์˜๋ฏธ

  • ๋ณต์žกํ•œ ๋กœ์ง์˜ ๋Š์–ด ์ฝ๊ธฐ๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ

๋ถ€์ •์–ด๋ฅผ ๋Œ€ํ•˜๋Š” ์ž์„ธ

// badโŒ -> 2๋ฒˆ์˜ ์‚ฌ๊ณ ๋ฅผ ํ•„์š”๋กœ ํ•œ๋‹ค.
if (!isLeftDirection()) {
   doSomething();
}

// goodโญ• -> 1๋ฒˆ์ด๋ฉด ๋
if (isNotLeftDirection()) {
  doSomething();
}
  • ๋ถ€์ •์–ด๊ตฌ๋ฅผ ์“ฐ์ง€ ์•Š์•„๋„ ๋˜๋Š” ์ƒํ™ฉ์ธ๊ฐ€๋ฅผ ์ฒดํฌํ•œ๋‹ค.
  • ๋ถ€์ •์–ด ์˜๋ฏธ๋ฅผ ๋‹ด๊ณ  ์žˆ๋Š” ๋‹ค๋ฅธ ๋‹จ์–ด๊ฐ€ ์กด์žฌํ•˜๋Š”์ง€ ๊ณ ๋ฏผํ•˜๊ณ  ์ง์ ‘ ๋ถ€์ •์–ด๊ตฌ๋กœ ๋ฉ”์„œ๋“œ๋ช…์„ ๊ตฌ์„ฑํ•œ๋‹ค.
    • ๋ถ€์ • ์—ฐ์‚ฐ์ž(!)์˜ ๊ฐ€๋…์„ฑ ์ €ํ•ด

ํ•ดํ”ผ ์ผ€์ด์Šค์™€ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ

  • ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•  ๊ฐ€๋Šฅ์„ฑ์„ ๋‚ฎ์ถ”๋Š” ๊ฒƒ์— ์ดˆ์ ์„ ๋งž์ถฐ์•ผ ํ•œ๋‹ค.
  • ์˜๋„ํ•œ ์˜ˆ์™ธ์™€ ์˜๋„์น˜์•Š์€ ์˜ˆ์™ธ๋ฅผ ๊ตฌ๋ถ„ํ•œ๋‹ค.
    • ์‚ฌ์šฉ์ž์—๊ฒŒ ๋ณด์—ฌ์ค„ ์˜ˆ์™ธ์™€ ๊ฐœ๋ฐœ์ž๊ฐ€ ๋ณด๊ณ  ์ฒ˜๋ฆฌํ•ด์•ผ ํ•  ์˜ˆ์™ธ๋ฅผ ๊ตฌ๋ถ„ํ•œ๋‹ค.

Null

  • NPE๋ฅผ ๋ฐฉ์ง€ํ•˜๋Š” ๋ฐฉํ–ฅ์œผ๋กœ ๊ฒฝ๊ฐ์‹ฌ์„ ๊ฐ€์ ธ์•ผ ํ•œ๋‹ค.
  • ๋ฉ”์„œ๋“œ ์„ค๊ณ„ ์‹œ return null์„ ์ž์ œํ•œ๋‹ค. ๋งŒ์•ฝ ์–ด๋ ต๋‹ค๋ฉด Optional ์‚ฌ์šฉ์„ ๊ณ ๋ คํ•ด๋ณธ๋‹ค.
  • Optional
    • Optional์€ ๋น„์‹ผ ๊ฐ์ฒด์ด๋‹ค. ๊ผญ ํ•„์š”ํ•œ ์ƒํ™ฉ์—์„œ ๋ฐ˜ํ™˜ ํƒ€์ž…์— ์‚ฌ์šฉํ•œ๋‹ค.
    • Optional์€ ์ ˆ๋Œ€๋กœ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋ฐ›์ง€ ์•Š๋„๋ก ํ•œ๋‹ค. ๋ถ„๊ธฐ ์ผ€์ด์Šค๋ฅผ ๋”ฐ์ ธ์•ผํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.
    • Optional์„ ๋ฐ˜ํ™˜๋ฐ›์•˜๋‹ค๋ฉด ๋น ๋ฅด๊ฒŒ ํ•ด์†Œํ•œ๋‹ค.
    • orElse(), orElseGet(), orElseThrow() ์ฐจ์ด๋ฅผ ์ˆ™์ง€ํ•˜๊ณ  ์‚ฌ์šฉํ•˜๋„๋ก ํ•œ๋‹ค.

1. orElseThrow() : ๊ฐ’์ด ์—†๋Š” ๊ฒƒ์„ '์˜ˆ์™ธ'๋กœ ์ฒ˜๋ฆฌํ•  ๋•Œ

  • Optional์ด ๋น„์–ด์žˆ์„ ๊ฒฝ์šฐ, ์ง€์ •๋œ ์˜ˆ์™ธ(Exception)๋ฅผ ๋ฐœ์ƒ์‹œํ‚จ๋‹ค.

2. orElseGet() : ๊ฐ’์ด ์—†์„ ๋•Œ '๋Œ€์ฒด ๊ฐ’์„ ๋™์ ์œผ๋กœ ์ƒ์„ฑ'ํ•ด์•ผ ํ•  ๋•Œ

  • Optional์ด ๋น„์–ด์žˆ์„ ๊ฒฝ์šฐ์—๋งŒ, ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋ฐ›์€ Supplier (๋žŒ๋‹ค์‹ ๋˜๋Š” ๋ฉ”์„œ๋“œ ๋ ˆํผ๋Ÿฐ์Šค)๋ฅผ ์‹คํ–‰ํ•˜์—ฌ ๊ทธ ๊ฒฐ๊ณผ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
    • ๋Œ€์ฒดํ•  ๊ธฐ๋ณธ๊ฐ’์ด ์ƒˆ๋กœ์šด ๊ฐ์ฒด ์ƒ์„ฑ์„ ํ•„์š”๋กœ ํ•  ๋•Œ
    • ๋Œ€์ฒดํ•  ๊ฐ’์„ ๊ฐ€์ ธ์˜ค๊ธฐ ์œ„ํ•ด ๋‹ค๋ฅธ ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๊ฑฐ๋‚˜ ๋ณต์žกํ•œ ์—ฐ์‚ฐ์ด ํ•„์š”ํ•  ๋•Œ

3. orElse() : ๊ฐ’์ด ์—†์„ ๋•Œ '์ด๋ฏธ ๋งŒ๋“ค์–ด์ง„ ์ƒ์ˆ˜ ๊ฐ’'์„ ์‚ฌ์šฉํ•  ๋•Œ

  • Optional์ด ๋น„์–ด์žˆ์„ ๊ฒฝ์šฐ, ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋ฐ›์€ ๊ฐ’์„ ๊ทธ๋Œ€๋กœ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
  • ๋ถˆํ•„์š”ํ•œ ์—ฐ์‚ฐ : orElse() ์•ˆ์— ๊ฐ์ฒด ์ƒ์„ฑ์ด๋‚˜ ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ ์ฝ”๋“œ๋ฅผ ๋„ฃ์œผ๋ฉด, Optional์— ๊ฐ’์ด ์กด์žฌํ•ด์„œ ๊ทธ ๊ฒฐ๊ณผ๊ฐ€ ํ•„์š” ์—†์Œ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ  ๋ฌด์กฐ๊ฑด ์‹คํ–‰๋˜์–ด ์„ฑ๋Šฅ ์ €ํ•˜์˜ ์›์ธ์ด ๋  ์ˆ˜ ์žˆ๋‹ค.

๐Ÿ“š ๊ฐ์ฒด ์ง€ํ–ฅ ํŒจ๋Ÿฌ๋‹ค์ž„

  • ๊ฐ์ฒด(Object) = ๋ฐ์ดํ„ฐ + ์ฝ”๋“œ
  • ๊ฐ์ฒด ์ถ”์ƒํ™” ํ•„์š” ๋‹จ๊ณ„
    • ๋น„๊ณต๊ฐœ ํ•„๋“œ(๋ฐ์ดํ„ฐ) + ๋น„๊ณต๊ฐœ ๋กœ์ง(์ฝ”๋“œ)
    • ๊ณต๊ฐœ ๋ฉ”์„œ๋“œ ์„ ์–ธ๋ถ€๋ฅผ ํ†ตํ•ด ์™ธ๋ถ€ ์„ธ๊ณ„์™€ ์†Œํ†ต
    • ๊ฐ์ฒด ์ฑ…์ž„์ด ๋‚˜๋‰จ์— ๋”ฐ๋ผ ๊ฐ์ฒด ๊ฐ„ ํ˜‘๋ ฅ์ด ๋ฐœ์ƒ

๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค ๋•Œ ์ฃผ์˜ํ•  ์ 

  • โœ…๏ธ1๊ฐœ์˜ ๊ด€์‹ฌ์‚ฌ๋กœ ๋ช…ํ™•ํ•˜๊ฒŒ ์ฑ…์ž„์ด ์ •์˜๋˜์—ˆ๋Š”๊ฐ€?
  • โœ…๏ธ์ƒ์„ฑ์ž ํ˜น์€ ์ •์  ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ์—์„œ ์œ ํšจ์„ฑ ๊ฒ€์ฆ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.
    • ๋„๋ฉ”์ธ์— ํŠนํ™”๋œ ๊ฒ€์ฆ ๋กœ์ง์ด ๋“ค์–ด๊ฐˆ ์ˆ˜ ์žˆ๋‹ค.
class Money {
    private long value;

    public Money(long value) {
        if (value < 0) {
            throw new IllegalArgumentException("๋ˆ์€ 0์› ์ด์ƒ์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.");
        }
        this.value = value;
    }
}
  • โœ…๏ธsetter ์‚ฌ์šฉ์€ ์ž์ œํ•œ๋‹ค.
    • ๋ฐ์ดํ„ฐ๋Š” ๋ถˆ๋ณ€์ด ์ตœ๊ณ ๋‹ค. ๋ณ€ํ•˜๋Š” ๋ฐ์ดํ„ฐ๋ผ๋„ ๊ฐ์ฒด๊ฐ€ ํ•ธ๋“ค๋งํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•œ๋‹ค.
    • ๊ฐ์ฒด ๋‚ด๋ถ€์—์„œ ์™ธ๋ถ€ ์„ธ๊ณ„์˜ ๊ฐœ์ž… ์—†์ด ์ž์ฒด์ ์ธ ๋ณ€๊ฒฝ/๊ฐ€๊ณต์œผ๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š”๊ฐ€๋ฅผ ํ™•์ธํ•œ๋‹ค.
    • ๋งŒ์•ฝ ์™ธ๋ถ€์—์„œ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๋ฐ์ดํ„ฐ๋กœ ๋ฐ์ดํ„ฐ ๋ณ€๊ฒฝ ์š”์ฒญ์„ ํ•˜๋Š” ๊ฒฝ์šฐ set~๋ณด๋‹ค๋Š” update~์™€ ๊ฐ™์ด ์˜๋„๋ฅผ ๋“œ๋Ÿฌ๋‚ด๋Š” ๋„ค์ด๋ฐ์„ ๊ณ ๋ คํ•œ๋‹ค.
  • โœ…๏ธgetter๋„ ์ฒ˜์Œ์—” ์‚ฌ์šฉ์„ ์ž์ œํ•œ๋‹ค. ํ•„์š”ํ•œ ๊ฒฝ์šฐ์—๋งŒ ์ถ”๊ฐ€ํ•˜๋„๋ก ํ•œ๋‹ค.
    • ์™ธ๋ถ€์—์„œ ๊ฐ์ฒด ๋‚ด์˜ ๋ฐ์ดํ„ฐ๊ฐ€ ํ•„์š”ํ•˜๋‹ค๊ณ  getter๋ฅผ ๋‚จ๋ฐœํ•˜๋Š” ๊ฒƒ์€ ๋ฌด๋ก€ํ•œ ํ–‰๋™์ด๋‹ค. ๊ฐ์ฒด์— ๋ฉ”์‹œ์ง€๋ฅผ ์š”์ฒญํ•œ๋‹ค.
Person person = new Person();

// badโŒ
if (person.getWallet().getID().findAge() >= 19) {
  pass();
}

// goodโญ•
if (person.isAgeGraterThanOrEqualTo(19) {
  pass();
}
  • โœ…๏ธ๊ฐ์ฒด์˜ ํ•„๋“œ ์ˆ˜๋ฅผ ์ค„์—ฌ๋ผ.
    • ๋ถˆํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๊ฐ€ ๋งŽ์„์ˆ˜๋ก ๋ณต์žก๋„๊ฐ€ ๋†’์•„์ง€๊ณ  ๋Œ€์‘ํ•  ๋ณ€ํ™”๊ฐ€ ๋งŽ์•„์ง„๋‹ค.
    • ๋ฉ”์„œ๋“œ ๊ธฐ๋Šฅ์œผ๋กœ๋„ ์ œ๊ณต์ด ๊ฐ€๋Šฅํ•˜๋ฉด OK, ๋‹จ ๋ฏธ๋ฆฌ ๊ฐ€๊ณตํ•˜๋Š” ๊ฒƒ์ด ์„ฑ๋Šฅ ์ƒ์˜ ์ด์ ์ด ์žˆ๋‹ค๋ฉด ํ•„๋“œ๋กœ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๊ฒƒ๋„ ์ข‹์„ ์ˆœ ์žˆ๋‹ค.
class Bill {
    private final List<Menu> menus;
    private final long totalPrice;  // ๋ฏธ๋ฆฌ ๊ฐ€์ง€๊ณ  ์žˆ์„์ˆ˜๋„ ์žˆ๋Š” ๊ฐ’

    // ๋ฉ”์„œ๋“œ ๊ธฐ๋Šฅ์œผ๋กœ ์ถฉ๋ถ„ํžˆ ๊ณ„์‚ฐํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ’
    public long calculateTotalPrice() {
        return this.menus.stream()
                   .mapToLong(Menu::getPrice)
                   .sum();
    }
}

SOLID - SRP(๋‹จ์ผ ์ฑ…์ž„ ์›์น™)

  • โœ…๏ธํ•˜๋‚˜์˜ ํด๋ž˜์Šค๋Š” ๋‹จ ํ•œ ๊ฐ€์ง€ ๋ณ€๊ฒฝ ์ด์œ ๋งŒ์„ ๊ฐ€์ ธ์•ผ ํ•œ๋‹ค.
    • ๊ฐ์ฒด๊ฐ€ ๊ฐ€์ง„ ๊ณต๊ฐœ ๋ฉ”์„œ๋“œ, ํ•„๋“œ, ์ƒ์ˆ˜ ๋“ฑ์€ ํ•ด๋‹น ๊ฐ์ฒด์˜ ๋‹จ์ผ ์ฑ…์ž„์— ์˜ํ•ด์„œ๋งŒ ๋ณ€๊ฒฝ์ด ๋˜์–ด์•ผ ํ•œ๋‹ค.

SOLID - OCP(๊ฐœ๋ฐฉ ํ์‡„ ์›์น™)

  • โœ…๏ธํ™•์žฅ์—๋Š” ์—ด๋ ค ์žˆ๊ณ , ์ˆ˜์ •์—๋Š” ๋‹ซํ˜€ ์žˆ์–ด์•ผ ํ•œ๋‹ค.
    • ๊ธฐ์กด ์ฝ”๋“œ ๋ณ€๊ฒฝ์—†์ด, ์‹œ์Šคํ…œ ๊ธฐ๋Šฅ์„ ํ™•์žฅํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•œ๋‹ค.
    • ์ถ”์ƒํ™”์™€ ๋‹คํ˜•์„ฑ์„ ํ™œ์šฉํ•ด OCP๋ฅผ ์ง€ํ‚ฌ ์ˆ˜ ์žˆ๋‹ค. ๊ตฌ์ฒด์— ์˜์กดํ•˜๊ธฐ๋ณด๋‹ค ์ธํ„ฐํŽ˜์ด์Šค๋กœ ๋ถ„๋ฆฌํ•ด์•ผ ํ•œ๋‹ค.
  • ๋ฌด์—‡์ด, ์™œ ๋ณ€ํ•  ๊ฒƒ์ธ๊ฐ€?
  • ๋ณ€ํ•˜๋Š” ๊ฒƒ์„ '์•ฝ์†(์ธํ„ฐํŽ˜์ด์Šค)'์œผ๋กœ ๋งŒ๋“ค์—ˆ๋Š”๊ฐ€?
  • '์—ญํ• '๊ณผ '์ฑ…์ž„'์„ ๋ช…ํ™•ํžˆ ๋ถ„๋ฆฌํ–ˆ๋Š”๊ฐ€?
  • '์ƒ์†' ๋Œ€์‹  '๊ตฌ์„ฑ'์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋Š”๊ฐ€?

SOLID - LSP(๋ฆฌ์Šค์ฝ”ํ”„ ์น˜ํ™˜ ์›์น™)

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

SOLID - ISP(์ธํ„ฐํŽ˜์ด์Šค ๋ถ„๋ฆฌ ์›์น™)

  • โœ…๏ธํด๋ผ์ด์–ธํŠธ๋Š” ์ž์‹ ์ด ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ์ธํ„ฐํŽ˜์ด์Šค์— ์˜์กดํ•˜๋ฉด ์•ˆ๋œ๋‹ค. ๊ทธ๋Ÿฌ๋‹ˆ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ž˜๊ฒŒ ์ชผ๊ฐœ๋ผ.
    • ISP๋ฅผ ์œ„๋ฐ˜ํ•˜๋ฉด ๋ถˆํ•„์š”ํ•œ ์˜์กด์„ฑ์œผ๋กœ ์ธํ•ด ๊ฒฐํ•ฉ๋„๊ฐ€ ๋†’์•„์ง€๊ณ  ํŠน์ • ๊ธฐ๋Šฅ ๋ณ€๊ฒฝ์ด ์—ฌ๋Ÿฌ ํด๋ž˜์Šค์— ์˜ํ–ฅ์„ ๋ฏธ์น  ์ˆ˜ ์žˆ๋‹ค.

SOLID - DIP(์˜์กด ๊ด€๊ณ„ ์ฃผ์ž… ์›์น™)

  • โœ…๏ธ์ƒ์œ„ ์ˆ˜์ค€ ๋ชจ๋“ˆ์€ ํ•˜์œ„ ์ˆ˜์ค€ ๋ชจ๋“ˆ์— ์˜์กดํ•ด์„œ๋Š” ์•ˆ ๋œ๋‹ค. ๋‘˜ ๋ชจ๋‘ ์ถ”์ƒํ™”์— ์˜์กดํ•ด์•ผ ํ•œ๋‹ค.

๐Ÿ“š ๊ฐ์ฒด ์ง€ํ–ฅ ์ ์šฉํ•˜๊ธฐ

แ„‰แ…ณแ„แ…ณแ„…แ…ตแ†ซแ„‰แ…ฃแ†บ 2025-09-07 แ„‹แ…ฉแ„’แ…ฎ 2 11 47 แ„‰แ…ณแ„แ…ณแ„…แ…ตแ†ซแ„‰แ…ฃแ†บ 2025-09-07 แ„‹แ…ฉแ„’แ…ฎ 2 12 11
  • ์ƒ์†๋ณด๋‹ค๋Š” ์กฐํ•ฉ์„ ์‚ฌ์šฉํ•˜์ž.
  • ์ƒ์†์€ ์‹œ๋ฉ˜ํŠธ์ฒ˜๋Ÿผ ๊ตณ์–ด์ง€๋Š” ๊ตฌ์กฐ๋‹ค. ์ˆ˜์ •์ด ์–ด๋ ต๋‹ค.
  • ์กฐํ•ฉ๊ณผ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ™œ์šฉํ•˜๋Š” ๊ฒƒ์ด ์œ ์—ฐํ•œ ๊ตฌ์กฐ๋ฅผ ๋งŒ๋“ ๋‹ค.

Value Object(VO)

  • ๊ธฐ๋ณธ ํƒ€์ž…์„ ๊ฐ์ฒด๋กœ ๊ฐ์‹ธ๊ณ  ์˜๋ฏธ๋ฅผ ๋ถ€์—ฌํ•ด ์ถ”์ƒํ™”
  • ๋„๋ฉ”์ธ์˜ ์–ด๋–ค ๊ฐœ๋…์„ ์ถ”์ƒํ™”ํ•˜์—ฌ ํ‘œํ˜„ํ•œ ๊ฐ’ ๊ฐ์ฒด
  • ๊ฐ’์œผ๋กœ ์ทจ๊ธ‰ํ•˜๊ธฐ ์œ„ํ•ด์„œ ๋ถˆ๋ณ€์„ฑ, ๋™๋“ฑ์„ฑ, ์œ ํšจ์„ฑ ๊ฒ€์ฆ ๋“ฑ์„ ๋ณด์žฅํ•ด์•ผ ํ•œ๋‹ค.
    • ๋ถˆ๋ณ€์„ฑ : final ํ•„๋“œ, setter ๊ธˆ์ง€
    • ๋™๋“ฑ์„ฑ : ์„œ๋กœ ๋‹ค๋ฅธ ์ธ์Šคํ„ด์Šค์—ฌ๋„ ๋‚ด๋ถ€ ๊ฐ’์ด ๊ฐ™์œผ๋ฉด ๊ฐ™์€ ๊ฐ’ ๊ฐ์ฒด๋กœ ์ทจ๊ธ‰ํ•œ๋‹ค. ์ด ๋•Œ, equals()์™€ hashCode() ์žฌ์ •์˜๊ฐ€ ํ•„์š”ํ•˜๋‹ค.
    • ์œ ํšจ์„ฑ ๊ฒ€์ฆ : ๊ฐ์ฒด๊ฐ€ ์ƒ์„ฑ๋˜๋Š” ์‹œ์ ์— ๋Œ€ํ•ด ์œ ํšจ์„ฑ์„ ๊ฒ€์ฆ
public class Money {
    
    private final long value;

    public Money(long value) {
        if (value < 0) {
            throw new IllegalArgumentException("๋ˆ์€ 0์› ์ด์ƒ์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.");
        }
        this.value = value;
    }

    // equals() & hashCode() ์žฌ์ •์˜
}

Money money1 = new Money(10000);
Money money2 = new Money(10000); // ๊ฐ™์€ 10000์›์ด๋ผ๋Š” ํ‘œ๋ฉด์  ๊ฐ€์น˜๋ฅผ ์ง€๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ™์€ ๋ˆ์ด๋‹ค.
  • Entity๋Š” ์‹๋ณ„์ž๊ฐ€ ์กด์žฌํ•œ๋‹ค. ์‹๋ณ„์ž๊ฐ€ ์•„๋‹Œ ํ•„๋“œ์˜ ๊ฐ’์ด ๋‹ฌ๋ผ๋„ ์‹๋ณ„์ž๊ฐ€ ๊ฐ™์œผ๋ฉด ๋™๋“ฑํ•œ ๊ฐ์ฒด๋กœ ์ทจ๊ธ‰ํ•œ๋‹ค.
    • equals() & hashCode()๋„ ์‹๋ณ„์ž ํ•„๋“œ๋งŒ ๊ฐ€์ง€๊ณ  ์žฌ์ •์˜ํ•  ์ˆ˜ ์žˆ๋‹ค.
    • ์‹๋ณ„์ž๊ฐ€ ๊ฐ™์€๋ฐ ์‹๋ณ„์ž๊ฐ€ ์•„๋‹Œ ํ•„๋“œ ๊ฐ’์ด ์„œ๋กœ ๋‹ค๋ฅธ ๋‘ ์ธ์Šคํ„ด์Šค๊ฐ€ ์žˆ๋‹ค๋ฉด ์‹œ๊ฐ„์ด ์ง€๋‚จ์— ๋”ฐ๋ผ ๋ณ€ํ™”ํ•œ ๊ฒƒ์œผ๋กœ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.
  • VO๋Š” ์‹๋ณ„์ž ์—†์ด ๋‚ด๋ถ€ ๋ชจ๋“  ๊ฐ’์ด ๋‹ค ๊ฐ™์•„์•ผ ๋™๋“ฑํ•œ ๊ฐ์ฒด๋กœ ์ทจ๊ธ‰ํ•œ๋‹ค.

์ฐธ๊ณ  - VO vs Entity

// badโŒ
public class Lotto {
    private final List<Integer> numbers; // ๋กœ๋˜ ๋ฒˆํ˜ธ๋ฅผ List๋กœ ์ง์ ‘ ๊ด€๋ฆฌ

    public Lotto(List<Integer> numbers) {
        // ์œ ํšจ์„ฑ ๊ฒ€์ฆ ๋กœ์ง์ด ์™ธ๋ถ€์— ๋…ธ์ถœ๋˜๊ฑฐ๋‚˜ ์ค‘๋ณต๋  ๊ฐ€๋Šฅ์„ฑ์ด ๋†’์Œ
        if (numbers.size() != 6) {
            throw new IllegalArgumentException("๋กœ๋˜ ๋ฒˆํ˜ธ๋Š” 6๊ฐœ์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.");
        }
        this.numbers = numbers;
    }

    // numbers๋ฅผ ์ง์ ‘ ๋ฐ˜ํ™˜ํ•˜์—ฌ ์™ธ๋ถ€์—์„œ ์ˆ˜์ •๋  ์œ„ํ—˜์ด ์žˆ์Œ (getNumbers().add(7))
    public List<Integer> getNumbers() {
        return numbers;
    }

    public boolean contains(int number) {
        // ์ปฌ๋ ‰์…˜์— ๋Œ€ํ•œ ๋‹จ์ˆœ ์œ„์ž„ ๋ฉ”์„œ๋“œ
        return numbers.contains(number);
    }
}

// goodโญ•
public class LottoNumbers {
    private static final int LOTTO_NUMBER_SIZE = 6;

    private final List<Integer> numbers;

    public LottoNumbers(List<Integer> numbers) {
        validateSize(numbers); // ์ƒ์„ฑ ์‹œ์ ์— ์œ ํšจ์„ฑ ๊ฒ€์ฆ
        validateDuplicate(numbers); // ์ค‘๋ณต ๊ฒ€์ฆ
        this.numbers = numbers;
    }

    // ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ๋‚ด๋ถ€์— ํฌํ•จ (์˜ˆ: ํŠน์ • ์ˆซ์ž๋ฅผ ํฌํ•จํ•˜๋Š”์ง€)
    public boolean contains(int number) {
        return this.numbers.contains(number);
    }

    // ๋‹น์ฒจ ๋ฒˆํ˜ธ์™€ ๋ช‡ ๊ฐœ๊ฐ€ ์ผ์น˜ํ•˜๋Š”์ง€ ๊ณ„์‚ฐํ•˜๋Š” ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง
    public int countMatch(LottoNumbers winningNumbers) {
        return (int) this.numbers.stream()
                .filter(winningNumbers::contains)
                .count();
    }
    
    // ์™ธ๋ถ€์—์„œ ์ปฌ๋ ‰์…˜์„ ์ง์ ‘ ์ˆ˜์ •ํ•˜์ง€ ๋ชปํ•˜๋„๋ก ๋ฐฉ์–ด์  ๋ณต์‚ฌ ๋˜๋Š” unmodifiableList ๋ฐ˜ํ™˜
    public List<Integer> getNumbers() {
        return Collections.unmodifiableList(numbers);
    }

    private void validateSize(List<Integer> numbers) {
        if (numbers.size() != LOTTO_NUMBER_SIZE) {
            throw new IllegalArgumentException("๋กœ๋˜ ๋ฒˆํ˜ธ๋Š” " + LOTTO_NUMBER_SIZE + "๊ฐœ์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.");
        }
    }

    private void validateDuplicate(List<Integer> numbers) {
        if (numbers.stream().distinct().count() != numbers.size()) {
            throw new IllegalArgumentException("๋กœ๋˜ ๋ฒˆํ˜ธ๋Š” ์ค‘๋ณต๋  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.");
        }
    }
}

// Lotto ํด๋ž˜์Šค๋Š” ์ด์ œ LottoNumbers ์ผ๊ธ‰ ์ปฌ๋ ‰์…˜์„ ์‚ฌ์šฉ
public class Lotto {
    private final LottoNumbers lottoNumbers;
    private final int bonusNumber;

    public Lotto(LottoNumbers lottoNumbers, int bonusNumber) {
        this.lottoNumbers = lottoNumbers;
        this.bonusNumber = bonusNumber;
    }
    
    // ... ๋‹น์ฒจ ์—ฌ๋ถ€ ํ™•์ธ ๋“ฑ Lotto์™€ ๊ด€๋ จ๋œ ๋‹ค๋ฅธ ๋กœ์ง ...
}

Enum

  • Enum์€ ์ƒ์ˆ˜์˜ ์ง‘ํ•ฉ์ด๋ฉฐ ์ƒ์ˆ˜์™€ ๊ด€๋ จ๋œ ๋กœ์ง์„ ๋‹ด์„ ์ˆ˜ ์žˆ๋Š” ๊ณต๊ฐ„์ด๋‹ค.
  • ํŠน์ • ๋„๋ฉ”์ธ ๊ฐœ๋…์— ๋Œ€ํ•ด ๊ทธ ์ข…๋ฅ˜์™€ ๊ธฐ๋Šฅ์„ ๋ช…์‹œ์ ์œผ๋กœ ํ‘œํ˜„ํ•ด์ค„ ์ˆ˜ ์žˆ๋‹ค.
  • ๋ณ€๊ฒฝ์ด ์ •๋ง ์žฆ์€ ๊ฐœ๋…์€ Enum๋ณด๋‹ค DB๋กœ ๊ด€๋ฆฌํ•˜๋Š” ๊ฒƒ์ด ๋‚˜์„ ์ˆ˜ ์žˆ๋‹ค.

๐Ÿ“š ์ฝ”๋“œ

์ฃผ์„(comment)

์‚ฌ์‹ค ์ฃผ์„์— ๋Œ€ํ•œ ๋ถ€๋ถ„์€ ์—ฌํƒœ๊นŒ์ง€ ๊ฐœ๋ฐœ์„ ํ•˜๋ฉด์„œ ํฌ๊ฒŒ ์‹ ๊ฒฝ์„ ์“ฐ์ง€ ์•Š์•˜๋‹ค. ์˜คํžˆ๋ ค ๋‚˜๋Š” ์ฃผ์„์ด๋ผ๋Š” ๊ฒƒ์ด ์ด๋Ÿฌ์ด๋Ÿฌํ•œ ๊ฒƒ์ž„์„ ์„ค๋ช…ํ•˜๊ธฐ์— ์ข‹๋‹ค๊ณ  ์ƒ๊ฐํ–ˆ์—ˆ๋‹ค.

  • ์ฃผ์„์„ ์ž‘์„ฑํ•  ๋•Œ ์ž์ฃผ ๋ณ€ํ•˜๋Š” ์ •๋ณด๋Š” ์ตœ๋Œ€ํ•œ ์ง€์–‘ํ•ด์„œ ์ž‘์„ฑํ•œ๋‹ค.
  • ๋งŒ์•ฝ ๊ด€๋ จ ์ •์ฑ…์ด ๋ณ€ํ•˜๊ฑฐ๋‚˜ ์ฝ”๋“œ๊ฐ€ ๋ณ€๊ฒฝ๋˜์—ˆ๋‹ค๋ฉด ์ฃผ์„๋„ ์žŠ์ง€ ์•Š๊ณ  ํ•จ๊ป˜ ์—…๋ฐ์ดํŠธํ•œ๋‹ค.
  • ์ข‹์€ ์ฃผ์„์ด๋ž€, ๋ชจ๋“  ํ‘œํ˜„ ๋ฐฉ๋ฒ•์„ ์ด๋™์›ํ•ด ์ฝ”๋“œ์— ์˜๋„๋ฅผ ๋…น์—ฌ๋‚ด๊ณ  ๊ทธ๋Ÿผ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ  ์ „๋‹ฌํ•ด์•ผ ํ•  ์ •๋ณด๊ฐ€ ๋‚จ์•˜์„ ๋•Œ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹์€ ์ฃผ์„์ด ๋œ๋‹ค.

๋ณ€์ˆ˜์™€ ๋ฉ”์„œ๋“œ์˜ ๋‚˜์—ด ์ˆœ์„œ

๊ฐœ๋ฐœํ•˜๋ฉด์„œ ํŒŒ๋ผ๋ฏธํ„ฐ์˜ ์ˆœ์„œ๋‚˜ ๋ณ€์ˆ˜, ๋ฉ”์„œ๋“œ ๋“ฑ์˜ ์ˆœ์„œ๋„ ํฌ๊ฒŒ ์‹ ๊ฒฝ์“ฐ์ง€ ์•Š์•˜๋˜ ๊ฒƒ ๊ฐ™๋‹ค.

  • ๋ณ€์ˆ˜๋Š” ์‚ฌ์šฉํ•˜๋Š” ์ˆœ์„œ๋Œ€๋กœ ๋‚˜์—ดํ•œ๋‹ค.
  • ๋ฉ”์„œ๋“œ์˜ ์ˆœ์„œ๋„ ๊ณ ๋ คํ•ด๋ณด์•„์•ผ ํ•˜๋Š”๋ฐ, ๊ฐ์ฒด ์ž…์žฅ์—์„œ ์ƒ๊ฐํ•ด๋ณธ๋‹ค.

์˜ค๋ฒ„ ์—”์ง€๋‹ˆ์–ด๋ง

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

์€ํƒ„ํ™˜์€ ์—†๋‹ค

  • ์ง€์† ๊ฐ€๋Šฅํ•œ ์†Œํ”„ํŠธ์›จ์–ด์˜ ํ’ˆ์งˆ์ด๋ƒ ๊ธฐ์ˆ  ๋ถ€์ฑ„๋ฅผ ์•ˆ๊ณ  ๊ฐ€๋Š” ๋น ๋ฅธ ๊ฒฐ๊ณผ๋ฌผ์ด๋ƒ
  • ํด๋ฆฐ ์ฝ”๋“œ๋ฅผ ์ถ”๊ตฌํ•˜์ง€ ๋ง๋ผ๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ๋ฏธ๋ž˜ ์‹œ์ ์—์„œ๋„ ์ž˜ ๊ณ ์น  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋Š” ์ฝ”๋“œ ์„ผ์Šค๊ฐ€ ํ•„์š”
โš ๏ธ **GitHub.com Fallback** โš ๏ธ