๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
Programming Language ๐Ÿ’ป/Java โ˜•

[Java] ๊ฐ์ฒด์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋ž˜๋ฐ(OOP) - 1. ๊ฐœ์š”

by lxvxxu 2025. 10. 18.


1) ๊ณ ๊ธ‰ ๊ฐ์ฒด ์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋ž˜๋ฐ(OOP)๋ž€? ๐Ÿงฑ

  • ๊ฐ์ฒด(Object): ๋ฐ์ดํ„ฐ(ํ•„๋“œ) + ํ–‰๋™(๋ฉ”์„œ๋“œ)์„ ๋ฌถ์€ ๋‹จ์œ„
  • ์บก์Аํ™”, ์ƒ์†, ๋‹คํ˜•์„ฑ, ์ถ”์ƒํ™”๊ฐ€ ๊ธฐ๋ณธ 4์š”์†Œ
  • “๊ณ ๊ธ‰” OOP๋Š” ๋‹ค์Œ์„ ๋” ์‹ ๊ฒฝ ์”๋‹ˆ๋‹ค :

 โ‘  ์ธํ„ฐํŽ˜์ด์Šค(Interface)/์ถ”์ƒํด๋ž˜์Šค(Abstract Class) ์ค‘์‹ฌ ์„ค๊ณ„

→ ๊ตฌํ˜„(Concrete)์„ ๊ฐˆ์•„๋ผ์šฐ๊ธฐ ์‰ฝ๊ฒŒ 

์ธํ„ฐํŽ˜์ด์Šค (Interface) ์ถ”์ƒ ํด๋ž˜์Šค (Abstract Class)
  • “๋ฌด์—‡์„ ํ•  ์ˆ˜ ์žˆ๋Š”์ง€”๋งŒ ์•ฝ์†ํ•˜๋Š” ๊ณ„์•ฝ. ๊ตฌํ˜„ํ•  ํด๋ž˜์Šค์˜ ํ•จ์ˆ˜ ์‹œ๊ทธ๋‹ˆ์ณ(method signature)๋งŒ ์ •ํ•ด ๋†“์Œ. (method signature ์ค‘์‹ฌ)
  • ์ผ๋ฐ˜์ ์œผ๋กœ ์ƒํƒœ (์ธ์Šคํ„ด์Šค ํ•„๋“œ) ์—†์Œ
    Java ์ธํ„ฐํŽ˜์ด์Šค ์•ˆ์˜ ํ•„๋“œ๋Š” ๋ชจ๋‘ public static final(์ƒ์ˆ˜)๋กœ ์ทจ๊ธ‰๋˜๋ฉฐ ์ธ์Šคํ„ด์Šค๋ณ„ ๊ฐ’์ด ๋  ์ˆ˜ ์—†๋‹ค.
    - ํ•œ ํด๋ž˜์Šค๊ฐ€ ์—ฌ๋Ÿฌ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋™์‹œ์— ๊ตฌํ˜„ ๊ฐ€๋Šฅ.
  • ์ตœ์‹  ์–ธ์–ด(Java 8+, C# ๋“ฑ)๋Š” default/static ๋ฉ”์„œ๋“œ๋กœ “์„ ํƒ์  ๊ธฐ๋ณธ ๊ตฌํ˜„”์„ ํ—ˆ์šฉ.
  • ๊ณตํ†ต ์ƒํƒœ(ํ•„๋“œ)์™€ ์ผ๋ถ€ ๊ตฌํ˜„์„ ์ œ๊ณตํ•˜๋Š” “๋ผˆ๋Œ€ ํด๋ž˜์Šค”.
  • ์ถ”์ƒ ๋ฉ”์„œ๋“œ(ํ•˜์œ„๊ฐ€ ๋ฐ˜๋“œ์‹œ ๊ตฌํ˜„)์™€ ๊ตฌ์ƒ ๋ฉ”์„œ๋“œ(์ด๋ฏธ ๊ตฌํ˜„)๋ฅผ ํ˜ผํ•ฉ ๊ฐ€๋Šฅ.
  • ๋ณดํ†ต ๋‹จ์ผ ์ƒ์†๋งŒ ํ—ˆ์šฉ(ํ•œ ํด๋ž˜์Šค๊ฐ€ ์ถ”์ƒ ํด๋ž˜์Šค๋ฅผ ํ•˜๋‚˜๋งŒ ์ƒ์†).

โ€ป ํ•จ์ˆ˜ ์‹œ๊ทธ๋‹ˆ์ฒ˜ (method signature)

- ๋ฉ”์„œ๋“œ๋ฅผ ์‹๋ณ„ํ•˜๋Š” “์ด๋ฆ„ + ๋งค๊ฐœ๋ณ€์ˆ˜(parameter, ํƒ€์ž…๊ณผ ์ˆœ์„œ)”์˜ ์กฐํ•ฉ. 

- return type๊ณผ throws ์ ˆ์€ ์ œ์™ธ

“throws ์ ˆ(throws clause)”
 = ๋ฉ”์„œ๋“œ ์„ ์–ธ์—์„œ “์ด ๋ฉ”์„œ๋“œ๊ฐ€ ๋˜์งˆ ์ˆ˜ ์žˆ๋Š” ‘์ฒดํฌ ์˜ˆ์™ธ’ ๋ชฉ๋ก”์„ ์„ ์–ธํ•˜๋Š” ๋ถ€๋ถ„.
๊ตฌํ˜„/์˜ค๋ฒ„๋ผ์ด๋“œ ์‹œ ๋” ๋„“์€(์ƒ์œ„) ์ฒดํฌ ์˜ˆ์™ธ๋กœ ํ™•๋Œ€ํ•˜๋ฉด ์•ˆ ๋˜๊ณ , ๊ฐ™๊ฑฐ๋‚˜ ๋” ์ขํ˜€์•ผ ํ•œ๋‹ค.
// ์‹œ๊ทธ๋‹ˆ์ฒ˜: pay(int)
// ์•„๋ž˜ ๋‘ ๋ฉ”์„œ๋“œ๋Š” ์ด๋ฆ„๊ณผ ํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ€ ๊ฐ™์•„์„œ ใ€Ž ๊ฐ™์€ ์‹œ๊ทธ๋‹ˆ์ฒ˜ ใ€
void pay(int amount);
int  pay(int amount); // ์ปดํŒŒ์ผ ๋ถˆ๊ฐ€(๋ฐ˜ํ™˜ํƒ€์ž…๋งŒ ๋‹ค๋ฅด๋ฉด ์˜ค๋ฒ„๋กœ๋”ฉ ์•„๋‹˜)


// ์˜ค๋ฒ„๋กœ๋”ฉ์€ ํŒŒ๋ผ๋ฏธํ„ฐ ๋ชฉ๋ก์ด ๋‹ฌ๋ผ์•ผ ํ•จ
void pay(long amount);     // pay(long) → ๋‹ค๋ฅธ ์‹œ๊ทธ๋‹ˆ์ฒ˜
void pay(int amount, int tax); // pay(int,int) → ๋‹ค๋ฅธ ์‹œ๊ทธ๋‹ˆ์ฒ˜

 

 

โš ๏ธ ์ธํ„ฐํŽ˜์ด์Šค ๊ตฌํ˜„ ์‹œ์—๋Š” ๋ฐ˜ํ™˜ ํƒ€์ž…์ด ํ˜ธํ™˜๋˜์–ด์•ผ ํ•œ๋‹ค (๋™์ผ ํ˜น์€ ๊ณต๋ณ€ ๋ฐ˜ํ™˜ ํƒ€์ž…)

     = ์ธํ„ฐํŽ˜์ด์Šค ๋ฉ”์„œ๋“œ๋ฅผ ๊ตฌํ˜„(override)ํ•  ๋•Œ ๋ฐ˜ํ™˜ ํƒ€์ž…์„ ๊ฐ™๊ฒŒ ํ•˜๊ฑฐ๋‚˜ “๋” ๊ตฌ์ฒด์ ์ธ(subtype)/ํ•˜์œ„ ํƒ€์ž…”์œผ๋กœ ๋ฐ”๊ฟ”๋„ ๋œ๋‹ค.

interface Repo {
    Number findId();   // ๊ณ„์•ฝ: Number๋ฅผ ๋ฐ˜ํ™˜
}

class IntRepo implements Repo {
    @Override
    public Integer findId() { // OK: Integer๋Š” Number์˜ ํ•˜์œ„ ํƒ€์ž… → ๊ณต๋ณ€ ๋ฐ˜ํ™˜
        return 42;
    }
}

class BadRepo implements Repo {
    @Override
    public Object findId() {  // ์ปดํŒŒ์ผ ์—๋Ÿฌ: Object๋Š” Number์˜ ์ƒ์œ„ ํƒ€์ž…(๋”

 


โ€ป ์ƒํƒœ (์ธ์Šคํ„ด์Šค ํ•„๋“œ)

- ๊ฐ์ฒด(instance, ํด๋ž˜์Šค=๊ฐ์ฒด์˜ ์†์„ฑ์„ ์ •์˜, ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•ด๋†“์€ ์ฝ”๋“œ ์ƒํƒœ)๊ฐ€ ๊ฐœ๋ณ„์ ์œผ๋กœ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๋ฐ์ดํ„ฐ(ํ•„๋“œ, field).

- ์ธ์Šคํ„ด์Šค๋งˆ๋‹ค ๊ฐ’์ด ๋‹ค๋ฅผ ์ˆ˜ ์žˆ์Œ.

  • ์˜ˆ: ์€ํ–‰ ๊ณ„์ขŒ ๊ฐ์ฒด๋งˆ๋‹ค balance๊ฐ€ ๋‹ค๋ฆ„ → balance๊ฐ€ “์ธ์Šคํ„ด์Šค ํ•„๋“œ(์ƒํƒœ)”.
class BankAccount {
    private int balance; // ์ธ์Šคํ„ด์Šค ํ•„๋“œ(์ƒํƒœ)
    public void deposit(int amount) { balance += amount; }
}

 

https://lala9663.tistory.com/31

 

[์ž๋ฐ”] ์ธ์Šคํ„ด์Šค(Instance)๋ž€?

์ธ์Šคํ„ด์Šค(instance) ํด๋ž˜์Šค๋Š” ๊ฐ์ฒด์˜ ์†์„ฑ์„ ์ •์˜ํ•˜๊ณ , ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜์—ฌ ๋งŒ๋“ค์–ด ๋†“์€ ์ฝ”๋“œ ์ƒํƒœ ์‹ค์ œ ํด๋ž˜์Šค๊ธฐ๋ฐ˜์œผ๋กœ ์ƒ์„ฑ๋œ ๊ฐ์ฒด(์ธ์Šคํ„ด์Šค)๋Š” ๊ฐ๊ฐ ๋‹ค๋ฅธ ๋ฉค๋ฒ„ ๋ณ€์ˆ˜ ๊ฐ’์„ ๊ฐ€์ง€๊ฒŒ ๋จ ๊ฐ€๋ น, ํ•™์ƒ์˜

lala9663.tistory.com

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

 


โ€ป  default/static(์ •์ ) ๋ฉ”์†Œ๋“œ

Java 8+์—์„œ ์ธํ„ฐํŽ˜์ด์Šค๋„ ๋ฉ”์„œ๋“œ์˜ “๊ธฐ๋ณธ ๊ตฌํ˜„”์„ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • default ๋ฉ”์„œ๋“œ
    • ์ธํ„ฐํŽ˜์ด์Šค์— ๊ตฌํ˜„ ์ฝ”๋“œ๋ฅผ ๋‘˜ ์ˆ˜ ์žˆ๊ฒŒ ํ•ด ์ฃผ๋Š” ํ‚ค์›Œ๋“œ.
    • ๊ตฌํ˜„ ํด๋ž˜์Šค๋Š”
      • ๊ทธ๋Œ€๋กœ “์ƒ์†ํ•ด ์‚ฌ์šฉ”ํ•˜๊ฑฐ๋‚˜,
      • ํ•„์š”ํ•˜๋ฉด “override(์žฌ์ •์˜)”ํ•  ์ˆ˜ ์žˆ์Œ.
    • ํšจ๊ณผ: ๊ธฐ์กด ์ธํ„ฐํŽ˜์ด์Šค์— ์ƒˆ ๋ฉ”์„œ๋“œ๋ฅผ ์ถ”๊ฐ€ํ•ด๋„, ๊ธฐ๋ณธ ๊ตฌํ˜„์ด ์žˆ์œผ๋‹ˆ ์˜› ๊ตฌํ˜„์ฒด๋“ค์ด ์ฆ‰์‹œ ๊นจ์ง€์ง€ ์•Š์Œ(ํ˜ธํ™˜์„ฑ ์œ ์ง€).
  • static ๋ฉ”์„œ๋“œ
    • ์ธํ„ฐํŽ˜์ด์Šค ์ด๋ฆ„์œผ๋กœ ํ˜ธ์ถœํ•˜๋Š” “์œ ํ‹ธ๋ฆฌํ‹ฐ ๋ฉ”์„œ๋“œ”.
    • ์ธ์Šคํ„ด์Šค(๊ตฌํ˜„ ํด๋ž˜์Šค์˜ ๊ฐ์ฒด)๊ฐ€ ์•„๋‹ˆ๋ผ “์ธํ„ฐํŽ˜์ด์Šค ์ž์ฒด”์— ์†ํ•˜๋ฉฐ, ๊ตฌํ˜„ ํด๋ž˜์Šค์— ์ƒ์†๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

 

๋‹ค์ค‘ ์ƒ์† (Multiple Inheritance)

- ํ•œ Class๊ฐ€ ์—ฌ๋Ÿฌ ๋ถ€๋ชจ Class๋ฅผ ๋™์‹œ์— ์ƒ์†ํ•˜๋Š” ๊ฒƒ

- ๋‹ค์ด์•„๋ชฌ๋“œ ๋ฌธ์ œ ๋ฐœ์ƒ ๊ฐ€๋Šฅ

   (๋‹ค์ค‘ ์ƒ์† ์‹œ ์ƒ์œ„ ๊ณตํ†ต ์กฐ์ƒ์ด ์ค‘๋ณต/๋ชจํ˜ธํ•˜๊ฒŒ ์ƒ์†๋˜์–ด ์–ด๋А ๊ฒฝ๋กœ์˜ ๋ฉค๋ฒ„๋ฅผ ์จ์•ผ ํ•˜๋Š”์ง€ ์• ๋งคํ•ด์ง€๋Š” ๋ฌธ์ œ)

์˜ˆ์‹œ : 

๋‹ค์ด์•„๋ชฌ๋“œ ๋ฌธ์ œ ๋ฐœ์ƒ

struct A { void hello(); };
struct B : A {};
struct C : A {};
struct D : B, C {};

int main() {
    D d;
    // d.hello();  // ๋ชจํ˜ธ์„ฑ ์˜ค๋ฅ˜: 'A::hello'๊ฐ€ ๋‘ ๊ฒฝ๋กœ๋กœ ์กด์žฌ
}

 

๋‹ค์ด์•„๋ชฌ๋“œ ๋ฌธ์ œ ํ•ด๊ฒฐ (๊ฐ€์ƒ ์ƒ์† Virtual Inheritance๋กœ A๋ฅผ ๋‹จ 1๋ฒˆ๋งŒ ๊ณต์œ )

struct A { void hello(); };
struct B : virtual A {};
struct C : virtual A {};
struct D : B, C {};
int main(){ D d; d.hello(); } // OK, A๊ฐ€ ํ•˜๋‚˜๋กœ ๊ณต์œ ๋จ

 

- JAVA๋Š” ๋‹ค์ค‘ ์ƒ์† ์ง€์› ์•ˆ ํ•จ. ๋Œ€์‹  ๋‹ค์ค‘ ์ƒ์† ํšจ๊ณผ๋ฅผ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ด์šฉํ•ด์„œ ๊ตฌํ˜„ ๊ฐ€๋Šฅ!!

   ๐Ÿ‘‰ Type์€ ๋‹ค์ค‘(์—ฌ๋Ÿฌ Interface)์œผ๋กœ ๋ฐ›๊ณ , ๊ตฌํ˜„์€ ํ•ฉ์„ฑ/์œ„์ž„ + ํ•„์š” ์‹œ default ๋ฉ”์„œ๋“œ ๋ณด์กฐํ•˜๋Š” ๋ฐฉ์‹ 

 

 

 

์˜ˆ์‹œ : 

1. ์—ฌ๋Ÿฌ Interface๋ฅผ ํ•œ Class๊ฐ€ ๋™์‹œ์— ๊ตฌํ˜„

interface Cacheable { void put(String k, String v); String get(String k); }
interface Retriable { void withRetry(Runnable r); }

class Service implements Cacheable, Retriable {
    // ๊ตฌํ˜„์€ 'ํ•ฉ์„ฑ'์œผ๋กœ ๋นผ์„œ ์žฌ์‚ฌ์šฉ
    private final Cache cache = new Cache();        // ๋ณ„๋„ ๊ตฌํ˜„์ฒด
    private final RetryPolicy retry = new RetryPolicy();

    @Override public void put(String k, String v){ cache.put(k,v); }
    @Override public String get(String k){ return cache.get(k); }
    @Override public void withRetry(Runnable r){ retry.runWithRetry(r); }
}

 

2. Interface default method๋กœ ๊ฐ€๋ฒผ์šด ๊ตฌํ˜„ ์„ž๊ธฐ (Java 8+)

interface Logger {
    default void log(String m){ System.out.println("[L] " + m); }
}
interface Auditor {
    default void log(String m){ System.out.println("[A] " + m); }
}
class Service implements Logger, Auditor {
    // ์ถฉ๋Œ ์‹œ ๋ฐ˜๋“œ์‹œ ๋ช…์‹œ์ ์œผ๋กœ ํ•ด๊ฒฐ
    @Override public void log(String m){ Logger.super.log(m); }
}

 โ‘ก ํ•ฉ์„ฑ(Composition) ์šฐ์„  → “is-a” ์ƒ์†๋ณด๋‹ค “has-a” ์กฐ๋ฆฝ์„ ์„ ํ˜ธ 

"is-a" ์ƒ์†(inheritance) : A๋Š” B์˜ ํ•œ ์ข…๋ฅ˜์ด๋‹ค.

- ์ƒ์œ„์˜ field, method๋ฅผ ๋ฌผ๋ ค๋ฐ›๋Š”๋‹ค(์žฌ์‚ฌ์šฉ) + overiding์œผ๋กœ ํŠนํ™”

- type ๊ณ„์ธต์œผ๋กœ ๋‹คํ˜•์„ฑ(polymorphism) ํ™œ์šฉ

- ๊ฐ•ํ•œ ๊ฒฐํ•ฉ, ๋‚ฎ์€ ์œ ์—ฐ์„ฑ

- ์ทจ์†Œ ๊ฐ€๋Šฅํ•œ(์• ๋งคํ•œ) ๊ด€๊ณ„์— ์“ฐ์ด๋ฉด LSP ์œ„๋ฒˆ, bug ์œ ๋ฐœ

 

์˜ˆ์‹œ :

class Animal { void move() {} }
class Dog extends Animal { @Override void move() { /* ๊ฑท๊ธฐ */ } }

 

"has-a" ์กฐ๋ฆฝ(composition) : A๋Š” B๋ฅผ ๊ฐ€์ง„๋‹ค. A๋Š” B๋ฅผ ์‚ฌ์šฉํ•ด ์›€์ง์ธ๋‹ค.

- ๊ฐ์ฒด๊ฐ€ ๋‹ค๋ฅธ ๊ฐ์ฒด๋ฅผ ์†์„ฑ์œผ๋กœ ๊ฐ€์ง€๊ณ , ๊ทธ ๊ฐ์ฒด์—๊ฒŒ ์ผ์„ ์œ„์ž„(delegate)ํ•ด ๊ธฐ๋Šฅ์„ ์ด๋ฃฌ๋‹ค.

- ๋‚ด๋ถ€์— ๋‹ค๋ฅธ ๊ฐ์ฒด๋ฅผ field๋กœ ๋‘”๋‹ค.

- ๋А์Šจํ•œ ๊ฒฐํ•ฉ

 

์˜ˆ์‹œ :

interface Payment { void pay(int amount); }
class Card implements Payment { public void pay(int a){ /*...*/ } }
class Kakao implements Payment { public void pay(int a){ /*...*/ } }

class Checkout {                 // has-a Payment
  private Payment payment;
  Checkout(Payment p){ this.payment = p; }
  void setPayment(Payment p){ this.payment = p; } // ๋Ÿฐํƒ€์ž„ ๊ต์ฒด
  void process(int amount){ payment.pay(amount); } // ์œ„์ž„
}

 

์ผ๋ฐ˜ํ™”๋Š” ์ƒ์†ํ™”?

์ผ๋ฐ˜ํ™”๋Š” "is a kind of" ๊ด€๊ณ„์ด๋‹ค.

 

 


 โ‘ข ๋А์Šจํ•œ ๊ฒฐํ•ฉ(Loosely Coupled)๊ณผ ์˜์กด์„ฑ ์ฃผ์ž…(DI) → ํ…Œ์ŠคํŠธ/๊ต์ฒด ์šฉ์ด 

 

 


 โ‘ฃ SOLID ์›์น™ ์ค€์ˆ˜ → ํ™•์žฅ์—” ์—ด๋ ค ์žˆ๊ณ  ๋ณ€๊ฒฝ์—” ๋‹ซํ˜€ ์žˆ๊ฒŒ(Open-Closed) 

https://lxvxxu.tistory.com/1336

 

[Java] ๊ฐ์ฒด์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋ž˜๋ฐ(OOP) - 4. SOLID๋ž€?

 

lxvxxu.tistory.com

 


 

 

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