• ABOUT
  • POSTS
  • GUESTBOOK

ยฉ 2025 BlueCool12 All rights reserved.

2025.09.08Java

๐Ÿ“‹ ์ž๋ฐ”๋กœ ์ดํ•ดํ•˜๋Š” ์–•์€ ๋ณต์‚ฌ & ๊นŠ์€ ๋ณต์‚ฌ

[๊ธฐ๋ณธ ๊ฐœ๋…]

์–•์€ ๋ณต์‚ฌ(Shallow Copy): ๊ฐ์ฒด์˜ 1์ฐจ ๋ ˆ๋ฒจ ํ•„๋“œ ๊ฐ’๋งŒ ์ƒˆ๋กœ ๋‹ด๋Š”๋‹ค. ์ฐธ์กฐ ํƒ€์ž… ํ•„๋“œ๋Š” ์ฃผ์†Œ(์ฐธ์กฐ)๋งŒ ๋ณต์‚ฌํ•œ๋‹ค. 
๊นŠ์€ ๋ณต์‚ฌ(Deep Copy): ์ค‘์ฒฉ ๊ฐ์ฒด๊นŒ์ง€ ์ƒˆ ์ธ์Šคํ„ด์Šค๋ฅผ ๋งŒ๋“ค์–ด ์ „์ฒด ๊ทธ๋ž˜ํ”„๋ฅผ ๋ณต์ œํ•œ๋‹ค. 

๊ฒฐ๊ณผ์ ์œผ๋กœ ์–•์€ ๋ณต์‚ฌ๋Š” ๋‚ด๋ถ€ ์ฐธ์กฐ๊ฐ€ ๊ณต์œ ๋˜๊ณ  ๊นŠ์€ ๋ณต์‚ฌ๋Š” ๊ณต์œ ๋˜์ง€ ์•Š๋Š”๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ์•„๋ž˜์™€ ๊ฐ™์€ ๋„๋ฉ”์ธ์ด ์žˆ์„ ๋•Œ
 

java
class Address {
  private String city;
  public Address(String city) { this.city = city; }
  public String getCity() { return city; }
  public void setCity(String city) { this.city = city; }
}

class Person {
  private String name;     // ๋ถˆ๋ณ€(๋ฌธ์ž์—ด ์ž์ฒด๋Š” ๋ถˆ๋ณ€)
  private Address address; // ๊ฐ€๋ณ€ ์ฐธ์กฐ ํ•„๋“œ
  
  public Person(String name, Address address) {
    this.name = name;
    this.address = address;
  }
  
  public String getName() { return name; }
  public Address getAddress() { return address; }
}


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

java
Person p1 = new Person("Min", new Address("Seoul"));

// ์ƒˆ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜์˜€์ง€๋งŒ ๋‚ด๋ถ€ ์ฐธ์กฐ ๊ณต์œ 
Person p2 = new Person(p1.getName(), p1.getAddress());

p1.getAddress().setCity("Busan");
System.out.println(p2.getAddress().getCity()); // Busan (๊ฐ™์ด ๋ฐ”๋€œ)


๋ฐ˜๋ฉด ๊นŠ์€ ๋ณต์‚ฌ๋Š” ์ค‘์ฒฉ ๊ฐ์ฒด๊นŒ์ง€ ์ƒˆ๋กœ ๋งŒ๋“œ๋Š” ๊ฒฝ์šฐ์ด๋‹ค. 
 

java
Person p1 = new Person("Min", new Address("Seoul"));

// ๊นŠ์€ ๋ณต์‚ฌ
Person p4 = new Person(
  p1.getName(),
  new Address(p1.getAddress().getCity())
);

p1.getAddress().setCity("Busan");
System.out.println(p4.getAddress().getCity()); // Seoul (์˜ํ–ฅ ์—†์Œ)

 


์ž๋ฐ”์˜ clone() 

์ž๋ฐ”์˜ Cloneable / Object#clone()์€ ์—ญ์‚ฌ์ ์œผ๋กœ ์„ค๊ณ„๊ฐ€ ๋‚œํ•ดํ•˜๋‹ค. 

1. ์–•์€ ๋ณต์‚ฌ๊ฐ€ ๊ธฐ๋ณธ: super.clone()์€ ํ•„๋“œ ๋‹จ์œ„ ๊ฐ’ ๋ณต์‚ฌ๋ฅผ ์ˆ˜ํ–‰ํ•œ๋‹ค. ์›์‹œ ํƒ€์ž…์€ ๊ฐ’์ด ๋ณต์‚ฌ๋˜๊ณ  ์ฐธ์กฐ ํƒ€์ž…์€ ์ฐธ์กฐ๋งŒ ๋ณต์‚ฌ๋˜๋ฏ€๋กœ ์–•์€ ๋ณต์‚ฌ๊ฐ€ ๋œ๋‹ค. ๊ฒŒ๋‹ค๊ฐ€ ์ƒ์„ฑ์ž๋ฅผ ๊ฑฐ์น˜์ง€ ์•Š์•„ ๋ถˆ๋ณ€์‹์ด ๊นจ์งˆ ์œ„ํ—˜์ด ์žˆ๋‹ค. 

2. ์˜ˆ์™ธ/๊ฐ€์‹œ์„ฑ ์ด์Šˆ: ๋‹จ์ˆœ ๋งˆ์ปค ์ธํ„ฐํŽ˜์ด์Šค์ธ Cloneable์„ ๊ตฌํ˜„ํ•˜์ง€ ์•Š์œผ๋ฉด CloneNotSupportedException์„ ๋˜์ง€๋ฉฐ ๊ธฐ๋ณธ์ ์œผ๋กœ protected๋ผ์„œ public์œผ๋กœ ์˜ค๋ฒ„๋ผ์ด๋“œ ํ•˜์ง€ ์•Š์œผ๋ฉด ์™ธ๋ถ€ ์ฝ”๋“œ์—์„œ ํ˜ธ์ถœํ•  ์ˆ˜ ์—†๋‹ค. ๋˜ํ•œ ํ˜ธ์ถœํ•˜๋Š” ์ธก์—์„œ๋„ ๋ถˆํ•„์š”ํ•˜๊ฒŒ ์ฒดํฌ ์˜ˆ์™ธ๋ฅผ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•œ๋‹ค. 

3. ์ƒ์† ํŠธ๋ฆฌ ๋ชจํ˜ธ์„ฑ: ์–ด๋А ๋ ˆ๋ฒจ์—์„œ ๊นŠ๊ฒŒ/์–•๊ฒŒ ๋ณต์‚ฌํ• ์ง€๋ฅผ ๊ฐ•์ œํ•˜์ง€ ์•Š์•„ ํ˜‘์—…/ํ™•์žฅ ๊ณผ์ •์—์„œ ์ผ๊ด€์„ฑ์ด ์‰ฝ๊ฒŒ ๊นจ์ง„๋‹ค. 

๋”ฐ๋ผ์„œ clone()์„ ์‚ฌ์šฉํ•  ๋•Œ๋Š” ๋ชจ๋“  ๊ฐ€๋ณ€ ์ฐธ์กฐ ํ•„๋“œ๋ฅผ ์ง์ ‘ ๋ณต์ œํ•ด์•ผ ๊นŠ์€ ๋ณต์‚ฌ๊ฐ€ ๋œ๋‹ค. 
 

java
// Cloneable ์ƒ์†
class Address implements Cloneable {
  private String city;
  public Address(String city) { this.city = city; }
  public String getCity() { return city; }
  public void setCity(String city) { this.city = city; }
  
  // public์œผ๋กœ ์˜ค๋ฒ„๋ผ์ด๋“œ
  @Override
  public Address clone() {
    // ์˜ˆ์™ธ ์ฒ˜๋ฆฌ
    try {
      return (Address) super.clone(); // ๋ถˆ๋ณ€/๋ฌธ์ž์—ด ํ•„๋“œ๋งŒ ์žˆ์œผ๋ฉด ์•ˆ์ „
    } catch (CloneNotSupportedException e) {
      throw new AssertionError(e);
    }
  }
}

class Person implements Cloneable {
  private String name;
  private Address address; // ๊ฐ€๋ณ€ ์ฐธ์กฐ
  
  public Person(String name, Address address) {
    this.name = name;
    this.address = address;
  }
  
  @Override
  public Person clone() {
    try {
      Person copy = (Person) super.clone(); // ํ•„๋“œ ๋‹จ์œ„ ๋ณต์‚ฌ
      copy.address = address == null ? null : address.clone(); // ๊นŠ์€ ๋ณต์‚ฌ
      return copy;
    } catch (CloneNotSupportedException e) {
      throw new AssertionError(e);
    }
  }
}


์œ„์™€ ๊ฐ™์€ ์ด์œ ๋กœ ์ž๋ฐ”์—์„œ๋Š” ๊ฐ์ฒด ๋ณต์‚ฌ ์‹œ ๋” ๊ถŒ์žฅ๋˜๋Š” ๋ฐฉ๋ฒ•๋“ค์ด ์กด์žฌํ•œ๋‹ค. ์ฒซ ๋ฒˆ์งธ๋กœ๋Š” ๋ณต์‚ฌ ์ƒ์„ฑ์ž/์ •์  ํŒฉํ† ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ์‹์ด๋‹ค. 
 

java
class Person {
  private final String name;
  private final Address address;
  
  public Person(String name, Address address) {
    this.name = name;
    this.address = address; // ์ฃผ์˜: ๊ทธ๋Œ€๋กœ ๋Œ€์ž…ํ•˜๋ฉด ์–•์€ ๋ณต์‚ฌ
  }
  
  // ๋ณต์‚ฌ ์ƒ์„ฑ์ž (๊นŠ์€ ๋ณต์‚ฌ)
  public Person(Person other) {
    this.name = other.name; // String์€ ๋ถˆ๋ณ€
    this.address = other.address == null ? null : new Address(other.address.getCity());
  }
  
  public static Person copyOf(Person other) {
    return new Person(other);
  }
}

*๊ฐ€์žฅ ๋ช…์‹œ์ ์ด๊ณ  ์•ˆ์ „ํ•œ ๋ฐฉ์‹์ด๋‹ค. 

๋‘ ๋ฒˆ์งธ๋Š” ์ง๋ ฌํ™” ๊ธฐ๋ฐ˜์˜ ๊นŠ์€ ๋ณต์‚ฌ์ด๋‹ค. Jackson, Gson, Java ์ง๋ ฌํ™” ๋“ฑ์œผ๋กœ ๊ฐ์ฒด๋ฅผ ๋ฐ”์ดํŠธ/ํŠธ๋ฆฌ๋กœ ๋ฐ”๊ฟจ๋‹ค๊ฐ€ ๋‹ค์‹œ ์ฝ์œผ๋ฉด ๊นŠ์€ ๋ณต์‚ฌ๊ฐ€ ๋œ๋‹ค. 
 

java
ObjectMapper om = new ObjectMapper();

// original ๊ฐ์ฒด๋ฅผ JSON ๋ฐ”์ดํŠธ๋กœ ์ง๋ ฌํ™” 
byte[] bytes = om.writeValueAsBytes(original);

// JSON ๋ฐ”์ดํŠธ๋ฅผ ๋‹ค์‹œ Person.class๋กœ ์—ญ์ง๋ ฌํ™” -> ์ƒˆ๋กœ์šด ๊ฐ์ฒด ์ƒ์„ฑ
Person copy = om.readValue(bytes, Person.class);


๋น ๋ฅด๊ฒŒ ๊ตฌํ˜„์ด ๊ฐ€๋Šฅํ•˜๋‹ค๋Š” ์ ์€ ์žฅ์ ์ด์ง€๋งŒ ์„ฑ๋Šฅ ๋น„์šฉ์ด ํฌ๋‹ค๋Š” ๋‹จ์ ๊ณผ ์ˆœํ™˜ ์ฐธ์กฐ ๊ตฌ์กฐ์˜ ๊ฒฝ์šฐ JSON ์ง๋ ฌํ™” ์‹œ StackOverflow๋‚˜ ๋ฌดํ•œ ๋ฃจํ”„๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค. 

๋˜ํ•œ ํ•„๋“œ๊ฐ€ transient, @JsonIgnore ๋“ฑ์œผ๋กœ ์ง๋ ฌํ™” ๋Œ€์ƒ์—์„œ ์ œ์™ธ๋˜๋Š” ๊ฒฝ์šฐ ๋ณต์‚ฌ ๊ฒฐ๊ณผ๊ฐ€ ๋‹ฌ๋ผ์งˆ ์ˆ˜ ์žˆ์–ด ์ฃผ์˜ํ•ด์„œ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค. 

์„ธ ๋ฒˆ์งธ๋กœ๋Š” ๋งคํ•‘ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด๋‹ค. MapStruct, ModelMapper ๋“ฑ์œผ๋กœ DTO์™€ ๋„๋ฉ”์ธ ๊ฐ„์˜ ๋ณต์‚ฌ ๊ทœ์น™์„ ์ปดํŒŒ์ผ/๋Ÿฐํƒ€์ž„์— ์ƒ์„ฑํ•œ๋‹ค. 
 

java
@Mapper
public interface PersonMapper {
  PersonMapper INSTANCE = Mappers.getMapper(PersonMapper.class);
  
  PersonDto toDto(Person entity);
  Person toEntity(PersonDto dto);
}

// ์‚ฌ์šฉ ์‹œ
Person p1 = new Person("Min", new Address("Seoul"));
PersonDto dto = PersonMapper.INSTANCE.toDto(p1);
// dto ์•ˆ์˜ Address๋„ ์ƒˆ ์ธ์Šคํ„ด์Šค๋กœ ๋งคํ•‘๋˜์–ด ๊นŠ์€ ๋ณต์‚ฌ


๋ฐ˜๋ณต๋˜๋Š” ๋งคํ•‘ ์ฝ”๋“œ๋ฅผ ์ค„์—ฌ ์ƒ์‚ฐ์„ฑ๊ณผ ์œ ์ง€ ๋ณด์ˆ˜์„ฑ์„ ๋†’์ผ ์ˆ˜ ์žˆ๊ณ  ๊นŠ์€ ๋ณต์‚ฌ ๊ทœ์น™์„ ์ค‘์•™์—์„œ ๊ด€๋ฆฌ๊ฐ€ ๊ฐ€๋Šฅํ•˜๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋‹จ์ˆœ ๋ณต์‚ฌ๋งŒ ํ•„์š”ํ•œ ๊ฒฝ์šฐ์—๋Š” ์˜ค๋ฒ„ ์—”์ง€๋‹ˆ์–ด๋ง์ด ๋  ์ˆ˜ ์žˆ๋‹ค. 

 


์ปฌ๋ ‰์…˜๊ณผ ๋ฐฐ์—ด

new ArrayList<>(original)๋Š” ์–•์€ ๋ณต์‚ฌ(์š”์†Œ ์ฐธ์กฐ๋งŒ ๋ณต์‚ฌ)์ด๋‹ค. ๊นŠ์€ ๋ณต์‚ฌ๋ฅผ ์œ„ํ•ด์„œ๋Š” ์š”์†Œ ์ž์ฒด๋ฅผ ๋ณต์‚ฌํ•ด์•ผ ํ•œ๋‹ค. 
 

java
List<Person> src = ...; // ์›๋ณธ ๋ฆฌ์ŠคํŠธ
List<Person> deep = src.stream()
  .map(Person::new)     // Person ๋ณต์‚ฌ ์ƒ์„ฑ์ž๋ฅผ ์ด์šฉํ•ด ์ƒˆ ๊ฐ์ฒด ์ƒ์„ฑ
  .toList();            // ์ƒˆ ๋ฆฌ์ŠคํŠธ๋กœ ์ˆ˜์ง‘


List.copyOf(โ€ฆ)/Set.copyOf(โ€ฆ)๋Š” ๋ถˆ๋ณ€ ๋ฆฌ์ŠคํŠธ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค. ๋ฆฌ์ŠคํŠธ ์ž์ฒด๋Š” ์ƒˆ๋กœ ๋งŒ๋“ค์–ด์ง€์ง€๋งŒ ๋‚ด๋ถ€ ์š”์†Œ๋Š” ๊ทธ๋Œ€๋กœ ์ฐธ์กฐ๋งŒ ๋ณต์‚ฌ๋œ๋‹ค. (์–•์€ ๋ณต์‚ฌ)
 

java
List<String> list = new ArrayList<>();
list.add("Blue");
list.add("Cool");

List<String> copy = List.copyOf(list); // ๋ถˆ๋ณ€ ๋ฆฌ์ŠคํŠธ + ์–•์€ ๋ณต์‚ฌ
copy.add("c"); // UnsupportedOperationException ๋ฐœ์ƒ


๋ฐฐ์—ด์˜ arr.clone()์€ ์ƒˆ ๋ฐฐ์—ด์„ ๋งŒ๋“ค์ง€๋งŒ ์š”์†Œ๊ฐ€ ์ฐธ์กฐ ํƒ€์ž…์ด๋ผ๋ฉด ์–•์€ ๋ณต์‚ฌ์ด๋‹ค. ํ•˜์ง€๋งŒ ์›์‹œ(primitive) ํƒ€์ž… ๋ฐฐ์—ด์€ ๊ฐ’ ๋ณต์‚ฌ์ด๋ฏ€๋กœ ๊ฒฐ๊ณผ์ ์œผ๋กœ ๊นŠ์€ ๋ณต์‚ฌ์ฒ˜๋Ÿผ ๋™์ž‘ํ•œ๋‹ค. 
 

java
Address[] a1 = { new Address("Seoul") };
Address[] a2 = a1.clone(); // ๋ฐฐ์—ด ๊ฐ์ฒด๋Š” ์ƒˆ๋กœ ์ƒ์„ฑ, ์š”์†Œ๋Š” ๊ฐ™์€ ์ฐธ์กฐ

 


๋ฐฉ์–ด์  ๋ณต์‚ฌ(Defensive Copy)

์™ธ๋ถ€์— ๊ฐ€๋ณ€ ๊ฐ์ฒด๋ฅผ ๋…ธ์ถœํ•  ๋•Œ๋Š” ๋ฐ˜๋“œ์‹œ ๋ฐฉ์–ด์  ๋ณต์‚ฌ๋ฅผ ๊ณ ๋ คํ•ด์•ผ ํ•œ๋‹ค.
 

java
class Order {
  private final Date createdAt; // Date๋Š” ๊ฐ€๋ณ€ ํด๋ž˜์Šค
  
  public Order(Date createdAt) {
    this.createdAt = new Date(createdAt.getTime()); // ์ž…๋ ฅ ๋ฐฉ์–ด ๋ณต์‚ฌ
  }
  
  public Date getCreatedAt() {
    return new Date(createdAt.getTime()); // ๋ฐ˜ํ™˜ ๋ฐฉ์–ด ๋ณต์‚ฌ
  }
}

*Instant, LocalDateTime ๊ฐ™์€ java.time ๊ณ„์—ด์€ ๋ถˆ๋ณ€์ด๊ธฐ ๋•Œ๋ฌธ์— ๋ฐฉ์–ด ๋ณต์‚ฌ๊ฐ€ ๋ถˆํ•„์š”ํ•˜๋‹ค. 
 


๋ถˆ๋ณ€(Immutable)

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

์ž๋ฐ”์˜ record๋Š” JDK 16๋ถ€ํ„ฐ ์ •์‹ ๋„์ž…๋œ ๋ฐ์ดํ„ฐ ์ „์šฉ ํด๋ž˜์Šค์ด๋‹ค. ๋ชจ๋“  ํ•„๋“œ๊ฐ€ ์ž๋™์œผ๋กœ final์ด ๋˜๋ฉฐ ์ƒ์„ฑ์ž๋กœ๋งŒ ๊ฐ’์ด ์„ค์ •๋œ๋‹ค. ๋”ฐ๋ผ์„œ record ์ž์ฒด๊ฐ€ ๋ถˆ๋ณ€์ ์ด๋‹ค. 
 

java
public record PersonR(String name, AddressR address) {}
public record AddressR(String city) {}

// ์‚ฌ์šฉ ์‹œ
PersonR p1 = new PersonR("Min", new AddressR("Seoul"));
PersonR p2 = p1; // ๊ฐ™์€ ์ฐธ์กฐ๋ฅผ ์จ๋„ ์•ˆ์ „ํ•˜๋‹ค. (๋ถˆ๋ณ€)


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


equals/hashCode

๋‘ ๊ฐ์ฒด๊ฐ€ ๊ฐ™์€ ์ค‘์ฒฉ ์ฐธ์กฐ๋ฅผ ๊ณต์œ ํ•˜๋ฉด ๊ทธ ๋‚ด๋ถ€ ์ƒํƒœ๊ฐ€ ๋ณ€ํ•  ๋•Œ equals()๋‚˜ hashCode()์˜ ๊ฒฐ๊ณผ๊ฐ€ ๋ฐ”๋€” ์ˆ˜ ์žˆ๋‹ค. 
 

java
class Address {
  String city;
  Address(String city) { this.city = city; }
  // equals/hashCode city ๊ธฐ์ค€์œผ๋กœ ๊ตฌํ˜„ํ–ˆ๋‹ค๊ณ  ๊ฐ€์ •
  @Override
  public boolean equals(Object o) { ... }
  @Override
  public int hashCode() { ... }
}

class Person {
  String name;
  Address address;
  // equals/hashCode: name + address ๊ธฐ์ค€์œผ๋กœ ๊ตฌํ˜„ํ–ˆ๋‹ค๊ณ  ๊ฐ€์ •
  ...
}

Person p1 = new Person("Min", new Address("Seoul"));
Person p2 = new Person(p1.name, p1.address); // ์–•์€ ๋ณต์‚ฌ

Set<Person> set = new HashSet<>();
set.add(p1);

// ์ค‘์ฒฉ ๊ฐ์ฒด(Address) ๋ณ€๊ฒฝ
p1.address.city = "Busan";

// p2.equals(p1)๋Š” ์—ฌ์ „ํžˆ true (๊ฐ™์€ ์ฐธ์กฐ ๊ณต์œ )
// set.contains(p1) -> false (hashCode๊ฐ€ ๋‹ฌ๋ผ์ง)


ํŠนํžˆ HashSet, HashMap ๊ฐ™์€ ํ•ด์‹œ ๊ธฐ๋ฐ˜ ์ปฌ๋ ‰์…˜์—์„œ ์น˜๋ช…์ ์ธ ๋ฒ„๊ทธ๋กœ ์ด์–ด์งˆ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๊นŠ์€ ๋ณต์‚ฌ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค. 

์ด์ „ ๊ธ€
๐Ÿงฉ Spring Bean ๋“ฑ๋ก ์–ด๋…ธํ…Œ์ด์…˜ ์ •๋ฆฌ: @Component๋ถ€ํ„ฐ @Mapper๊นŒ์ง€
๋‹ค์Œ ๊ธ€
๐Ÿ“˜ Ubuntu ์„œ๋ฒ„ ์šด์˜์— ๊ผญ ํ•„์š”ํ•œ ๋ฆฌ๋ˆ…์Šค ๊ธฐ๋ณธ ๋ช…๋ น์–ด
์žฅ์‹์šฉ ๋กœ๊ณ