๐Ÿ›ก๏ธ Java ๋ฐฉ์–ด์  ๋ณต์‚ฌ(Defensive Copy)

์„ํ˜„ยท2025๋…„ 2์›” 2์ผ
0

Insight

๋ชฉ๋ก ๋ณด๊ธฐ
5/43

์˜ค๋Š˜์˜ ์ด์•ผ๊ธฐ

๊ฐ์ฒด์˜ ๋ถˆ๋ณ€์„ฑ(immutability)์„ ์œ ์ง€ํ•˜๋ฉด์„œ ์•ˆ์ „ํ•˜๊ฒŒ ๋ฐ์ดํ„ฐ๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ๋‹ค์‹œ ํ•œ๋ฒˆ ์ƒ๊ธฐ์‹œํ‚ค๋Š” ๋งˆ์Œ์œผ๋กœ, ๋ฐฉ์–ด์  ๋ณต์‚ฌ(Defensive Copy)๋ผ๋Š” ๊ฐœ๋…์„ ๋‹ค์‹œ๊ธˆ ์ •๋ฆฌํ•ด๋ณผ ํ•„์š”์„ฑ์„ ๋А๊ผˆ์Šต๋‹ˆ๋‹ค. ์›๋ณธ ๊ฐ์ฒด์˜ ๋ถˆํ•„์š”ํ•œ ๋ณ€๊ฒฝ์„ ๋ฐฉ์ง€ํ•˜๊ณ , ์˜ˆ๊ธฐ์น˜ ์•Š์€ ์‚ฌ์ด๋“œ ์ดํŽ™ํŠธ(Side Effect)๋ฅผ ์ค„์ด๊ธฐ ์œ„ํ•ด ๋ฐฉ์–ด์  ๋ณต์‚ฌ๋ฅผ ์–ด๋–ป๊ฒŒ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.


๋ฐฉ์–ด์  ๋ณต์‚ฌ๋ž€? ๐Ÿค”

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

๋ฐฉ์–ด์  ๋ณต์‚ฌ๊ฐ€ ํ•„์š”ํ•œ ์‹œ์ 

  1. ์ƒ์„ฑ์ž(Constructor)์—์„œ ์™ธ๋ถ€ ๊ฐ์ฒด๋ฅผ ๋‚ด๋ถ€ ํ•„๋“œ์— ์ €์žฅํ•  ๋•Œ
    • ์™ธ๋ถ€์—์„œ ์ „๋‹ฌ๋œ ๊ฐ์ฒด๋ฅผ ์ง์ ‘ ์ €์žฅํ•˜๋ฉด, ์›๋ณธ ๊ฐ์ฒด๊ฐ€ ๋ณ€๊ฒฝ๋  ๊ฒฝ์šฐ ๋‚ด๋ถ€ ๋ฐ์ดํ„ฐ๋„ ๋ณ€๊ฒฝ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  2. Getter ๋ฉ”์„œ๋“œ์—์„œ ๋‚ด๋ถ€ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•  ๋•Œ
    • ๋‚ด๋ถ€ ํ•„๋“œ์˜ ๊ฐ€๋ณ€ ๊ฐ์ฒด๋ฅผ ๊ทธ๋Œ€๋กœ ๋ฐ˜ํ™˜ํ•˜๋ฉด, ์™ธ๋ถ€์—์„œ ํ•ด๋‹น ๊ฐ์ฒด๋ฅผ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฐฉ์–ด์  ๋ณต์‚ฌ ์ ์šฉ ๋ฐฉ๋ฒ• ๐Ÿ› ๏ธ

1๏ธโƒฃ ์ƒ์„ฑ์ž์—์„œ์˜ ๋ฐฉ์–ด์  ๋ณต์‚ฌ

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

โœ… ์ž˜๋ชป๋œ ์˜ˆ์ œ (์›๋ณธ ๊ฐ์ฒด๊ฐ€ ๋ณ€๊ฒฝ๋  ์œ„ํ—˜์ด ์žˆ์Œ)

import java.util.List;

public class Lotto {
    private final List<Integer> numbers;

    public Lotto(List<Integer> numbers) {
        this.numbers = numbers; // ์œ„ํ—˜: ์›๋ณธ ๋ฆฌ์ŠคํŠธ๋ฅผ ๊ทธ๋Œ€๋กœ ์ฐธ์กฐํ•จ
    }
}

numbers ๋ฆฌ์ŠคํŠธ๊ฐ€ ์™ธ๋ถ€์—์„œ ๋ณ€๊ฒฝ๋˜๋ฉด, Lotto ๊ฐ์ฒด์˜ ๋‚ด๋ถ€ ๋ฐ์ดํ„ฐ๋„ ๋ณ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

โœ… ์˜ฌ๋ฐ”๋ฅธ ์˜ˆ์ œ (๋ฐฉ์–ด์  ๋ณต์‚ฌ ์ ์šฉ)

import java.util.List;
import java.util.ArrayList;

public class Lotto {
    private final List<Integer> numbers;

    public Lotto(List<Integer> numbers) {
        this.numbers = new ArrayList<>(numbers); // ๋ฐฉ์–ด์  ๋ณต์‚ฌ ์ ์šฉ
    }
}

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


2๏ธโƒฃ Getter ๋ฉ”์„œ๋“œ์—์„œ์˜ ๋ฐฉ์–ด์  ๋ณต์‚ฌ

๋‚ด๋ถ€ ๋ฐ์ดํ„ฐ๋ฅผ ๊ทธ๋Œ€๋กœ ๋ฐ˜ํ™˜ํ•˜๋ฉด ์™ธ๋ถ€์—์„œ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, ๋ณต์‚ฌ๋ณธ์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒƒ์ด ์•ˆ์ „ํ•ฉ๋‹ˆ๋‹ค.

โœ… ์ž˜๋ชป๋œ ์˜ˆ์ œ (๋‚ด๋ถ€ ๋ฐ์ดํ„ฐ๋ฅผ ์ง์ ‘ ๋…ธ์ถœ)

public List<Integer> getNumbers() {
    return numbers; // ์œ„ํ—˜: ์™ธ๋ถ€์—์„œ numbers ๋ฆฌ์ŠคํŠธ๋ฅผ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ์Œ
}

โœ… ์˜ฌ๋ฐ”๋ฅธ ์˜ˆ์ œ (๋ฐฉ์–ด์  ๋ณต์‚ฌ ์ ์šฉ)

import java.util.Collections;

public List<Integer> getNumbers() {
    return Collections.unmodifiableList(numbers); // ๋ถˆ๋ณ€ ๋ฆฌ์ŠคํŠธ ๋ฐ˜ํ™˜
}

Collections.unmodifiableList()๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ฝ๊ธฐ ์ „์šฉ ๋ฆฌ์ŠคํŠธ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋ฉด, ์™ธ๋ถ€์—์„œ ๋ฆฌ์ŠคํŠธ๋ฅผ ์ˆ˜์ •ํ•˜๋ ค๊ณ  ํ•˜๋ฉด UnsupportedOperationException์ด ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.


3๏ธโƒฃ ๊นŠ์€ ๋ณต์‚ฌ(Deep Copy) ์ ์šฉ ๐Ÿ”„

๊ธฐ๋ณธ์ ์ธ ๋ฐฉ์–ด์  ๋ณต์‚ฌ๋Š” ์–•์€ ๋ณต์‚ฌ(Shallow Copy)๋กœ ์ˆ˜ํ–‰๋˜๋ฏ€๋กœ, ๋ฆฌ์ŠคํŠธ ๋‚ด๋ถ€์˜ ์š”์†Œ๊ฐ€ ๊ฐ€๋ณ€ ๊ฐ์ฒด์ผ ๊ฒฝ์šฐ ์š”์†Œ ์ž์ฒด๋Š” ๋ณต์‚ฌ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ ๊นŠ์€ ๋ณต์‚ฌ(Deep Copy)๋ฅผ ์ ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

โœ… ์˜ˆ์ œ: ๊นŠ์€ ๋ณต์‚ฌ ์ ์šฉ

import java.util.ArrayList;
import java.util.List;

public class Lotto {
    private final List<LottoNumber> numbers;

    public Lotto(List<LottoNumber> numbers) {
        this.numbers = new ArrayList<>();
        for (LottoNumber number : numbers) {
            this.numbers.add(new LottoNumber(number)); // ๊นŠ์€ ๋ณต์‚ฌ ์ ์šฉ
        }
    }

    public List<LottoNumber> getNumbers() {
        List<LottoNumber> copy = new ArrayList<>();
        for (LottoNumber number : numbers) {
            copy.add(new LottoNumber(number));
        }
        return Collections.unmodifiableList(copy);
    }
}

๋ฆฌ์ŠคํŠธ์˜ ์š”์†Œ๊ฐ€ ๊ฐ€๋ณ€ ๊ฐ์ฒด๋ผ๋ฉด, ๊ฐœ๋ณ„ ์š”์†Œ๋„ ๋ณต์‚ฌํ•˜์—ฌ ์ƒˆ๋กœ์šด ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.


โœ… ๋ฐฉ์–ด์  ๋ณต์‚ฌ์˜ ์žฅ์ 

โœ”๏ธ ๋ถˆ๋ณ€์„ฑ(Immutable) ๋ณด์žฅ: ์›๋ณธ ๊ฐ์ฒด๊ฐ€ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š๋„๋ก ๋ณดํ˜ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
โœ”๏ธ ์‚ฌ์ด๋“œ ์ดํŽ™ํŠธ(Side Effect) ๋ฐฉ์ง€: ์™ธ๋ถ€์—์„œ ๋‚ด๋ถ€ ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†์œผ๋ฏ€๋กœ, ์˜ˆ๊ธฐ์น˜ ์•Š์€ ๋ฒ„๊ทธ๋ฅผ ์ค„์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
โœ”๏ธ ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ ํ™˜๊ฒฝ์—์„œ ์•ˆ์ „: ๊ฐ์ฒด๊ฐ€ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š์œผ๋ฏ€๋กœ, ๋™๊ธฐํ™” ๋ฌธ์ œ๋ฅผ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


โš ๏ธ ๋ฐฉ์–ด์  ๋ณต์‚ฌ์˜ ์ฃผ์˜์ 

  1. ์„ฑ๋Šฅ ์˜ค๋ฒ„ํ—ค๋“œ

    • ๊ฐ์ฒด๋ฅผ ๋ณต์‚ฌํ•˜๋Š” ์—ฐ์‚ฐ์ด ์ถ”๊ฐ€๋˜๋ฏ€๋กœ, ๋Œ€๋Ÿ‰์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ค๋ฃฐ ๊ฒฝ์šฐ ์„ฑ๋Šฅ ์ €ํ•˜๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    • ํŠนํžˆ, ๊นŠ์€ ๋ณต์‚ฌ๋Š” ์ฒ˜๋ฆฌ ๋น„์šฉ์ด ๋” ํด ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ์ƒํ™ฉ์— ๋งž๊ฒŒ ์ ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  2. ๊ฐ€๋…์„ฑ ๊ณ ๋ ค

    • ๋ถˆํ•„์š”ํ•œ ๋ฐฉ์–ด์  ๋ณต์‚ฌ๋Š” ์ฝ”๋“œ ๋ณต์žก๋„๋ฅผ ๋†’์ผ ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ, ๋ฐ˜๋“œ์‹œ ํ•„์š”ํ•œ ๊ฒฝ์šฐ์—๋งŒ ์ ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

๐Ÿš€ ๋งˆ์น˜๋ฉฐ

๋ฐฉ์–ด์  ๋ณต์‚ฌ๋Š” ๋ถˆ๋ณ€์„ฑ(immutability)์„ ์œ ์ง€ํ•˜๊ณ , ๊ฐ์ฒด์˜ ๋ฌด๊ฒฐ์„ฑ์„ ๋ณด์žฅํ•˜๋Š” ์ค‘์š”ํ•œ ๊ธฐ๋ฒ•์ž…๋‹ˆ๋‹ค. ํŠนํžˆ, ๊ฐ€๋ณ€ ๊ฐ์ฒด๋ฅผ ๋‹ค๋ฃฐ ๋•Œ ๋ฐฉ์–ด์  ๋ณต์‚ฌ๋ฅผ ์ ์ ˆํžˆ ํ™œ์šฉํ•˜๋ฉด ์˜ˆ๊ธฐ์น˜ ์•Š์€ ๋ฒ„๊ทธ๋ฅผ ๋ฐฉ์ง€ํ•˜๊ณ , ์•ˆ์ •์ ์ธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์—ฌ๋Ÿฌ๋ถ„์˜ ์ฝ”๋“œ์—์„œ๋„ ๋ฐฉ์–ด์  ๋ณต์‚ฌ๋ฅผ ์ ์šฉํ•ด ๋ณด์„ธ์š”! ๐Ÿ†

---

0๊ฐœ์˜ ๋Œ“๊ธ€