[Java] 깊은 복사와 얕은 복사

·2025년 4월 3일

JAVA

목록 보기
16/16
post-thumbnail

velog 에서 홍보를 보고 매일메일이라는 뉴스레터를 구독하게 되었다.

이 뉴스레터는 매일 개발 면접 질문을 보내 주는데, 백엔드와 프론트엔드로 나누어 매일 보내 준다.

풀스택을 지향하고 있는 나는 둘 다 구독하지만, 역시 조금이라도 더 알고 있는 백엔드의 CS 에 조금 더 관심이 가더라.

꼭 면접 때문이 아니더라도 (현재 현업 중) 면접 질문은 CS 에 대한 갈망을 조금이나마 풀어주는 것 같다. 그리고 이건! 취업 전 들여다보던 얕은 복사와 깊은 복사를 간단히 정리해 보는 포스팅이다. 오랜만에 보는 CS가 재미있기 때문에....

먼저 코드를 보자.

깊은 복사와 얕은 복사란?

class Book {

    private String name; // 책 이름
    private Author author; // 저자

    public Book(String name, Author author) {
        this.name = name;
        this.author = author;
    }

    public Book shallowCopy() { // 얕은 복사
        return new Book(this.name, this.author);
    }

    public Book deepCopy() { // 깊은 복사
        Author copiedAuthor = new Author(this.author.getName());
        return new Book(this.name, copiedAuthor);
    }

    public void changeAuthor(String name) { // 저자 이름 변경
        author.setName(name);
    }

    @Override
    public String toString() {
        return "Book name : " + name + ", " + author;
    }

    static class Author {

        private String name; // 저자 이름

        public Author(String name) {
            this.name = name;
        }

        public String getName() { // 저자 이름 반환
            return name;
        }

        public void setName(String name) { // 저자 이름 변경
            this.name = name;
        }

        @Override
        public String toString() {
            return "Author : " + name;
        }
    }

    public static void main(String[] args) {
        Author author1 = new Author("조슈아 블로크");
        Book book1 = new Book("이펙티브 자바", author1);

        // 얕은 복사 후 변경
        Book shallowCopyBook = book1.shallowCopy();
        shallowCopyBook.changeAuthor("Joshua Bloch");

        // 얕은 복사 결과 출력
        System.out.println("After shallow copy and change:");
        System.out.println("Original book1: " + book1);
        System.out.println("Shallow copied book: " + shallowCopyBook);

        Author author2 = new Author("마틴 파울러");
        Book book2 = new Book("리팩터링", author2);

        // 깊은 복사 후 변경
        Book deepCopyBook = book2.deepCopy();
        deepCopyBook.changeAuthor("Martin Fowler");

        // 깊은 복사 결과 출력
        System.out.println("
After deep copy and change:");
        System.out.println("Original book2: " + book2);
        System.out.println("Deep copied book: " + deepCopyBook);
    }
}

1. 얕은 복사란?

코드를 보면, this 를 통해 shallow 얕은 복사는 그 객체 자신을 "참조" 한다.

즉, 복사하여 새로운 것을 만들어 내는 것이 아니라 원본을 가진 값을 만들어내는 것이다.

그러므로 만약 얕은 복사를 한 객체 참조 값이 변경된다? -> 실제 값도 변경이라는 결과

겉보기에는 복사된 것 같지만 실제로는 같은 객체를 공유하는 것이기 때문이다.

Book shallow = original.shallowCopy();
shallow.changeAuthor("바뀐 이름");  // → original 도 같이 바뀜

2. 깊은 복사란?

반면 깊은 복사는 getBook 메서드를 통해, 해당 값을 복사하여 완전히 새로운 객체를 탄생시킨다.

완전히 별개의 객체로 존재하기 때문에, 복사본에서 값을 변경해도 원본에는 영향이 없다.

Book deep = original.deepCopy();
deep.changeAuthor("바뀐 이름");  // → original 은 그대로

3. 그런데 말이죠...

이렇게 설명만 하면 알아듣는다. 그런데 이건 귀납적인 설명이고, 내가 항상 헷갈리고야 말았던 부분은, 아래와 같다.

왜 생성자 new 를 쓰는데도 새 객체가 아니라 본 객체를 참조하는 복사본인 거지?

⭐ new 를 썼는데도 얕은 복사가 되는 이유

public Book shallowCopy() {
    return new Book(this.name, this.author);
}

여기서 new Book(...) 은 Book 객체를 새로 만들고 있다. 즉, Book 객체 자체는 새로운 인스턴스가 맞다.

그러나 이 안에 들어가는 Author 는, this.author = 즉, 기존 걸 그대로 재사용 하는 Author 인 것이다.

그래서 shallowCopy 를 할 경우 Author 값은 영향을 받는다.

여기서 또 짚고 넘어갈 점은, 같은 원리로 Book 객체의 name 을 변경하는 건 깊은 복사이기 때문에 name 을 새로 하는 건 원본에 영향을 안 끼친다.

이상이다.

profile
자바 백엔드 개발자 개인 위키

0개의 댓글