Skip to content

Latest commit

ย 

History

History
512 lines (363 loc) ยท 24 KB

File metadata and controls

512 lines (363 loc) ยท 24 KB

item 30 : ์ด์™•์ด๋ฉด ์ œ๋„ค๋ฆญ ๋ฉ”์„œ๋“œ๋กœ ๋งŒ๋“ค๋ผ

ํด๋ž˜์Šค์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ, ๋ฉ”์„œ๋“œ๋„ ์ œ๋„ค๋ฆญ์œผ๋กœ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.

๋งค๊ฐœ๋ณ€์ˆ˜ํ™” ํƒ€์ž…์„ ๋ฐ›๋Š” ์ •์  ์œ ํ‹ธ๋ฆฌํ‹ฐ ๋ฉ”์„œ๋“œ๋Š” ๋ณดํ†ต ์ œ๋„ค๋ฆญ์ด๋‹ค. ์˜ˆ์ปจ๋Œ€ Collections์˜ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ๋ฉ”์„œ๋“œ(binarysearch, sort ๋“ฑ)๋Š” ๋ชจ๋‘ ์ œ๋„ค๋ฆญ์ด๋‹ค.

1. ์ œ๋„ค๋ฆญ ๋ฉ”์„œ๋“œ ์ž‘์„ฑ๋ฒ•

1) ๋กœ ํƒ€์ž…์„ ์‚ฌ์šฉํ•˜๋Š” ๋ฌธ์ œ์ 

๋จผ์ €, ๋กœ ํƒ€์ž…(raw type)์„ ์‚ฌ์šฉํ•œ union ๋ฉ”์„œ๋“œ๋Š” ์ปดํŒŒ์ผ ๊ฒฝ๊ณ ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค:

public static Set union(Set s1, Set s2) {
    Set result = new HashSet(s1);
    result.addAll(s2);
    return result;
}

์ด ๋ฉ”์„œ๋“œ๋Š” ๊ฒฝ๊ณ  ์—†์ด ์ปดํŒŒ์ผ๋˜์ง€๋งŒ, ํƒ€์ž… ์•ˆ์ „์„ฑ์„ ๋ณด์žฅํ•˜์ง€ ์•Š๋Š”๋‹ค. Set ํƒ€์ž…์˜ ์›์†Œ๊ฐ€ ์–ด๋–ค ํƒ€์ž…์ธ์ง€ ์•Œ ์ˆ˜ ์—†์–ด, ClassCastException์ด ๋ฐœ์ƒํ•  ๊ฐ€๋Šฅ์„ฑ์ด ๋†’๋‹ค.

2) ์ œ๋„ค๋ฆญ ํƒ€์ž…์œผ๋กœ ์•ˆ์ „์„ฑ ํ™•๋ณด

๋กœ ํƒ€์ž… ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋ ค๋ฉด ๋ฉ”์„œ๋“œ๋ฅผ ์ œ๋„ค๋ฆญ ๋ฉ”์„œ๋“œ๋กœ ์ž‘์„ฑํ•ด์•ผ ํ•œ๋‹ค.

public static <E> Set<E> union(Set<E> s1, Set<E> s2) {
    Set<E> result = new HashSet<>(s1);
    result.addAll(s2);
    return result;
}
  • <E>: ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์„ ์–ธ
  • Set<E>: ๋ฉ”์„œ๋“œ์˜ ๋ฐ˜ํ™˜ ํƒ€์ž…๊ณผ ๋งค๊ฐœ๋ณ€์ˆ˜ ํƒ€์ž…์— ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํƒ€์ž… ์•ˆ์ „์„ฑ์„ ๋ณด์žฅํ•œ๋‹ค.

์ด ๋ฉ”์„œ๋“œ๋Š” ์ž…๋ ฅ ์ง‘ํ•ฉ๊ณผ ๋ฐ˜ํ™˜ ์ง‘ํ•ฉ์˜ ํƒ€์ž…์ด ์ผ์น˜ํ•ด์•ผ ํ•˜๋ฉฐ, ํƒ€์ž… ์•ˆ์ „ํ•œ ์ฝ”๋“œ๋กœ ์ปดํŒŒ์ผํ•  ์ˆ˜ ์žˆ๋‹ค.

3) ์ œ๋„ค๋ฆญ ์‚ฌ์šฉ ํ‹€

public static <E/*ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜ ๋ชฉ๋ก*/> Set<E/*๋ฐ˜ํ™˜ ํƒ€์ž…*/> union(Set<E/*ํŒŒ๋ผ๋ฏธํ„ฐ ํƒ€์ž…*/> s1, Set<E> s2) {
    Set<E> result = new HashSet<>(s1);
    result.addAll(s2);
    return result;
}
  • ์ˆœ์„œ๋Œ€๋กœ ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜ ๋ชฉ๋ก, ๋ฐ˜ํ™˜ ํƒ€์ž…, ํŒŒ๋ผ๋ฏธํ„ฐ ํƒ€์ž… 3๊ฐ€์ง€๋ฅผ ๋ฉ”์„œ๋“œ ์‹œ๊ทธ๋‹ˆ์ฒ˜์— ์ž…๋ ฅํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ์ด ๋ฉ”์„œ๋“œ๋Š” ๊ฒฝ๊ณ  ์—†์ด ์ปดํŒŒ์ผ ๋˜๋ฉฐ, ํƒ€์ž… ์•ˆ์ „ํ•˜๊ณ , ์“ฐ๊ธฐ๋„ ์‰ฝ๋‹ค.
  • union ๋ฉ”์„œ๋“œ๋Š” ์ง‘ํ•ฉ 3๊ฐœ๏ผˆ์ž…๋ ฅ 2๊ฐœ, ๋ฐ˜ํ™˜ 1๊ฐœ๏ผ‰์˜ ํƒ€์ž…์ด ๋ชจ๋‘ ๊ฐ™์•„์•ผ ํ•œ๋‹ค.

4) ํ™œ์šฉ ์˜ˆ์ œ

public static void main๏ผˆString[] args๏ผ‰ {
    Set<String> guys = Set.of("ํ†ฐ", "๋”•", "ํ—ค๋ฆฌ");
    Set<String> stooges = Set.of("๋ž˜๋ฆฌ", "๋ชจ์—", "์ปฌ๋ฆฌ");
    Set<String> aflCio = union(guys, stooges);
    System.out.println("aflCio = " + aflCio);
}

๋ชจ์—, ํ†ฐ, ํ•ด๋ฆฌ, ๋ž˜๋ฆฌ, ์ปฌ๋ฆฌ, ๋”• ์ถœ๋ ฅ๋จ

  • ์œ„ ์˜ˆ์ œ์—์„œ๋Š” ๋‘ ๊ฐœ์˜ Set<String>์„ ํ•ฉ์ณ ์ƒˆ๋กœ์šด ์ง‘ํ•ฉ์„ ์ƒ์„ฑํ•œ๋‹ค.
  • ์ด ๋ฉ”์„œ๋“œ๋Š” ์ œ๋„ค๋ฆญ ๋ฉ”์„œ๋“œ์ด๊ธฐ ๋•Œ๋ฌธ์—, ์ปดํŒŒ์ผ ์‹œ ํƒ€์ž… ๊ฒ€์‚ฌ๋ฅผ ํ†ตํ•ด ์•ˆ์ „ํ•œ ์ฝ”๋“œ์ž„์„ ๋ณด์žฅํ•œ๋‹ค.

5) ํ•œ์ •์  ์™€์ผ๋“œ ์นด๋“œ๋ฅผ ์ด์šฉํ•œ union ๋ฉ”์„œ๋“œ

ํ•œ์ •์  ์™€์ผ๋“œ์นด๋“œ ํƒ€์ž…์„ ์‚ฌ์šฉํ•˜์—ฌ union ๋ฉ”์„œ๋“œ๋ฅผ ๋” ์œ ์—ฐํ•˜๊ฒŒ ๊ฐœ์„ ํ•  ์ˆ˜ ์žˆ๋‹ค.

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

import java.util.HashSet;
import java.util.Set;

public class UnionExample {

    // ํ•œ์ •์  ์™€์ผ๋“œ์นด๋“œ ํƒ€์ž…์„ ์‚ฌ์šฉํ•œ union ๋ฉ”์„œ๋“œ
    public static <E> Set<E> union(Set<? extends E> s1, Set<? extends E> s2) {
        Set<E> result = new HashSet<>(s1);
        result.addAll(s2);
        return result;
    }

    public static void main(String[] args) {
        Set<String> guys = Set.of("ํ†ฐ", "๋”•", "ํ—ค๋ฆฌ");
        Set<String> stooges = Set.of("๋ž˜๋ฆฌ", "๋ชจ์—", "์ปฌ๋ฆฌ");
        
        // ํ•œ์ •์  ์™€์ผ๋“œ์นด๋“œ ํƒ€์ž…์„ ์‚ฌ์šฉํ•œ union ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœ
        Set<String> aflCio = union(guys, stooges);
        
        // ๊ฒฐ๊ณผ ์ถœ๋ ฅ
        System.out.println("aflCio = " + aflCio);
    }
}
    Set<E> result = new HashSet<>(s1);
    result.addAll(s2);
    return result;
}

Set<? extends E>๋Š” E์˜ ํ•˜์œ„ ํƒ€์ž…์„ ํ—ˆ์šฉํ•˜์—ฌ ๋‹ค์–‘ํ•œ ํƒ€์ž…์˜ ์ง‘ํ•ฉ์„ ํ•ฉ์น  ์ˆ˜ ์žˆ๋‹ค.

  • ๋ฉ”์„œ๋“œ ์‹œ๊ทธ๋‹ˆ์ฒ˜:
    • public static <E> Set<E> union(Set<? extends E> s1, Set<? extends E> s2):
      • <E>๋Š” ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์ •์˜ํ•œ๋‹ค.
      • Set<? extends E>๋Š” E์˜ ํ•˜์œ„ ํƒ€์ž…์„ ๋‚˜ํƒ€๋‚ด๋Š” ํ•œ์ •์  ์™€์ผ๋“œ์นด๋“œ ํƒ€์ž…์ด๋‹ค. ์ฆ‰, s1๊ณผ s2๋Š” E์˜ ํ•˜์œ„ ํƒ€์ž…์ธ ์ง‘ํ•ฉ์„ ๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค.
      • ๋ฐ˜ํ™˜ ํƒ€์ž…์€ Set<E>๋กœ, ๋‘ ์ง‘ํ•ฉ์˜ ํ•ฉ์ง‘ํ•ฉ์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
  • ์œ ์—ฐํ•œ ํƒ€์ž… ์ฒ˜๋ฆฌ:
    • Set<? extends E>๋ฅผ ์‚ฌ์šฉํ•จ์œผ๋กœ์จ, ์ž…๋ ฅ ์ง‘ํ•ฉ์˜ ํƒ€์ž…์ด E์˜ ํ•˜์œ„ ํƒ€์ž…์ผ ๋•Œ์—๋„ ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ์ถœ๋ ฅ ๊ฒฐ๊ณผ:
    • guys์™€ stooges ๋‘ ์ง‘ํ•ฉ์˜ ํ•ฉ์ง‘ํ•ฉ์„ ๊ตฌํ•œ ๊ฒฐ๊ณผ๊ฐ€ ์ถœ๋ ฅ๋œ๋‹ค.

2. ์ œ๋„ค๋ฆญ ์‹ฑ๊ธ€ํ„ด ํŒฉํ„ฐ๋ฆฌ

๋•Œ๋กœ๋Š” ๋ถˆ๋ณ€ ๊ฐ์ฒด๋ฅผ ์—ฌ๋Ÿฌ ํƒ€์ž…์œผ๋กœ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋งŒ๋“ค์–ด์•ผ ํ•  ๋•Œ๊ฐ€ ์žˆ๋‹ค.

์ œ๋„ค๋ฆญ ์‹ฑ๊ธ€ํ„ด ํŒฉํ„ฐ๋ฆฌ ํŒจํ„ด์„ ์‚ฌ์šฉํ•˜๋ฉด, ๋Ÿฐํƒ€์ž„์— ํ•˜๋‚˜์˜ ๊ฐ์ฒด๋ฅผ ์–ด๋–ค ํƒ€์ž…์œผ๋กœ๋“  ๋งค๊ฐœ๋ณ€์ˆ˜ํ™”ํ•  ์ˆ˜ ์žˆ๋‹ค.

๋‹ค์Œ์€ ์ œ๋„ค๋ฆญ ์‹ฑ๊ธ€ํ„ด ํŒจํ„ด์„ ์‚ฌ์šฉํ•˜์—ฌ ํ•ญ๋“ฑ ํ•จ์ˆ˜(identity function)๋ฅผ ๊ตฌํ˜„ํ•œ ์˜ˆ์ œ๋กœ, ์ด ํŒจํ„ด์„ ํ†ตํ•ด ํ•˜๋‚˜์˜ ๊ฐ์ฒด๋ฅผ ์–ด๋–ค ํƒ€์ž…์œผ๋กœ๋“  ๋งค๊ฐœ๋ณ€์ˆ˜ํ™”ํ•  ์ˆ˜ ์žˆ๋‹ค.

1) ์—ฌ๊ธฐ์„œ ์ž ๊น ๋Ÿฐํƒ€์ž„์— ํ•˜๋‚˜์˜ ๊ฐ์ฒด๋ฅผ ์–ด๋–ค ํƒ€์ž…์œผ๋กœ๋“  ๋งค๊ฐœ๋ณ€์ˆ˜ํ™”ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๋ฌด์Šจ๋œป์ผ๊นŒ?

๋งค๊ฐœ๋ณ€์ˆ˜ํ™”(Parameterized)๋ž€ ์–ด๋–ค ์š”์†Œ๋ฅผ ํŠน์ • ๊ฐ’์ด๋‚˜ ํƒ€์ž…์— ๋งž๊ฒŒ ์ผ๋ฐ˜ํ™”ํ•˜์—ฌ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•œ๋‹ค.

๋Ÿฐํƒ€์ž„์— ํ•˜๋‚˜์˜ ๊ฐ์ฒด๋ฅผ ์–ด๋–ค ํƒ€์ž…์œผ๋กœ๋“  ๋งค๊ฐœ๋ณ€์ˆ˜ํ™”ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์€ ์ œ๋„ค๋ฆญ ํƒ€์ž…์˜ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•  ๋•Œ ์‚ฌ์šฉํ•˜๋Š” ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ๋Ÿฐํƒ€์ž„์— ๊ฒฐ์ •๋  ์ˆ˜ ์žˆ๋‹ค๋Š” ์˜๋ฏธ์ด๋‹ค.

์ฆ‰, ์ปดํŒŒ์ผ ์‹œ์ ์—๋Š” ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ์†Œ๊ฑฐ๋˜์ง€๋งŒ, ๋Ÿฐํƒ€์ž„์— ์ œ๋„ค๋ฆญ ๊ฐ์ฒด๋ฅผ ํŠน์ • ํƒ€์ž…์œผ๋กœ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์„ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๋œป์ด๋‹ค.

์ž๋ฐ”์—์„œ ์ œ๋„ค๋ฆญ์€ ์ปดํŒŒ์ผ ์‹œ์ ์— ํƒ€์ž… ๊ฒ€์‚ฌ๋ฅผ ์ˆ˜ํ–‰ํ•˜๊ณ , ๋Ÿฐํƒ€์ž„์—๋Š” ํƒ€์ž… ์ •๋ณด๋ฅผ ์ œ๊ฑฐํ•˜๋Š” "ํƒ€์ž… ์†Œ๊ฑฐ(type erasure)" ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•œ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜, ์ œ๋„ค๋ฆญ ์‹ฑ๊ธ€ํ„ด ํŒจํ„ด์„ ํ†ตํ•ด ๋Ÿฐํƒ€์ž„์— ํƒ€์ž…์„ ๋ณ€๊ฒฝํ•˜์—ฌ ์—ฌ๋Ÿฌ ํƒ€์ž…์— ๋Œ€ํ•ด ๋™์ผํ•œ ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

2) ์ œ๋„ค๋ฆญ ์‹ฑ๊ธ€ํ„ด ํŒฉํ† ๋ฆฌ ํŒจํ„ด ์˜ˆ์ œ

// ํ•ญ๋“ฑ ํ•จ์ˆ˜(identity function)๋ฅผ ๊ตฌํ˜„ํ•œ ์ œ๋„ค๋ฆญ ์‹ฑ๊ธ€ํ„ด ๊ฐ์ฒด
// ์ž…๋ ฅ ๊ฐ’์„ ๊ทธ๋Œ€๋กœ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜ ๊ฐ์ฒด๋กœ, ์ƒํƒœ๊ฐ€ ์—†๊ธฐ ๋•Œ๋ฌธ์— ์—ฌ๋Ÿฌ ํƒ€์ž…์— ๋Œ€ํ•ด ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅ
private static final UnaryOperator<Object> IDENTITY_FN = t -> t;

@SuppressWarnings("unchecked")
public static <T> UnaryOperator<T> identityFunction() {
    // ์ œ๋„ค๋ฆญ ํƒ€์ž… T๋กœ ํ˜•๋ณ€ํ™˜ํ•˜์—ฌ ๋ฐ˜ํ™˜ (ํƒ€์ž… ์•ˆ์ „์„ฑ์ด ๋ณด์žฅ๋˜๋ฏ€๋กœ ๋น„๊ฒ€์‚ฌ ๊ฒฝ๊ณ ๋ฅผ ์–ต์ œ)
    return (UnaryOperator<T>) IDENTITY_FN;
}
  • IDENTITY_FN์€ ์ž…๋ ฅ๊ฐ’์„ ์ˆ˜์ • ์—†์ด ๊ทธ๋Œ€๋กœ ๋ฐ˜ํ™˜ํ•˜๋Š” UnaryOperator<Object> ํƒ€์ž…์˜ ํ•จ์ˆ˜ ๊ฐ์ฒด์ด๋‹ค.
  • identityFunction() ๋ฉ”์„œ๋“œ๋Š” ์ œ๋„ค๋ฆญ ๋ฉ”์„œ๋“œ๋กœ, ํ˜ธ์ถœ ์‹œ ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜ T์— ๋งž๊ฒŒ ํ•ญ๋“ฑ ํ•จ์ˆ˜ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
  • @SuppressWarnings("unchecked") ์• ๋„ˆํ…Œ์ด์…˜์€ ์ปดํŒŒ์ผ๋Ÿฌ์˜ ๋น„๊ฒ€์‚ฌ ํ˜•๋ณ€ํ™˜ ๊ฒฝ๊ณ ๋ฅผ ์–ต์ œํ•œ๋‹ค. ์—ฌ๊ธฐ์„œ๋Š” ํƒ€์ž… ์•ˆ์ „์„ฑ์ด ๋ณด์žฅ๋˜๊ธฐ ๋•Œ๋ฌธ์— ์‚ฌ์šฉํ•ด๋„ ๋ฌธ์ œ๊ฐ€ ์—†๋‹ค.

3) ์ œ๋„ค๋ฆญ ์‹ฑ๊ธ€ํ„ด ์‚ฌ์šฉ ์˜ˆ์ œ

UnaryOperator๋ฅผ ์–ด๋–ค ํƒ€์ž…์ด๋“  ๊ณ„์†ํ•ด์„œ ์ด์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

public static void main(String[] args) {
    // ๋ฌธ์ž์—ด ๋ฐฐ์—ด
    String[] strings = { "์‚ผ๋ฒ ", "๋Œ€๋งˆ", "๋‚˜์ผ๋ก " };
    // ์ œ๋„ค๋ฆญ ์‹ฑ๊ธ€ํ„ด์„ ์‚ฌ์šฉํ•˜์—ฌ UnaryOperator<String> ํƒ€์ž…์˜ ํ•ญ๋“ฑ ํ•จ์ˆ˜ ์ƒ์„ฑ
    UnaryOperator<String> sameString = identityFunction();
    // ๋ฐฐ์—ด์˜ ๊ฐ ์›์†Œ์— ๋Œ€ํ•ด ํ•ญ๋“ฑ ํ•จ์ˆ˜๋ฅผ ์ ์šฉ (๊ฐ’์ด ๊ทธ๋Œ€๋กœ ์ถœ๋ ฅ๋จ)
    for (String s : strings) {
        System.out.println(sameString.apply(s));
    }

    // ์ˆซ์ž ๋ฐฐ์—ด
    Number[] numbers = { 1, 2.0, 3L };
    // ์ œ๋„ค๋ฆญ ์‹ฑ๊ธ€ํ„ด์„ ์‚ฌ์šฉํ•˜์—ฌ UnaryOperator<Number> ํƒ€์ž…์˜ ํ•ญ๋“ฑ ํ•จ์ˆ˜ ์ƒ์„ฑ
    UnaryOperator<Number> sameNumber = identityFunction();
    // ๋ฐฐ์—ด์˜ ๊ฐ ์›์†Œ์— ๋Œ€ํ•ด ํ•ญ๋“ฑ ํ•จ์ˆ˜๋ฅผ ์ ์šฉ (๊ฐ’์ด ๊ทธ๋Œ€๋กœ ์ถœ๋ ฅ๋จ)
    for (Number n : numbers) {
        System.out.println(sameNumber.apply(n));
    }
}
  • identityFunction() ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด UnaryOperator<String>๊ณผ UnaryOperator<Number>๋กœ ๊ฐ๊ฐ์˜ ํƒ€์ž…์— ๋Œ€ํ•ด ํ•ญ๋“ฑ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.
  • ๋ฌธ์ž์—ด ๋ฐฐ์—ด๊ณผ ์ˆซ์ž ๋ฐฐ์—ด์˜ ๊ฐ ์š”์†Œ์— ๋Œ€ํ•ด ํ•ญ๋“ฑ ํ•จ์ˆ˜๋ฅผ ์ ์šฉํ•˜์—ฌ ๊ฐ’์„ ๊ทธ๋Œ€๋กœ ์ถœ๋ ฅํ•œ๋‹ค. ์ปดํŒŒ์ผ ๊ฒฝ๊ณ ๋‚˜ ์˜ค๋ฅ˜ ์—†์ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

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

3. ์žฌ๊ท€์  ํƒ€์ž… ํ•œ์ •

์žฌ๊ท€์  ํƒ€์ž… ํ•œ์ •์€ ์ œ๋„ค๋ฆญ ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ์ž๊ธฐ ์ž์‹ ์„ ์‚ฌ์šฉํ•˜์—ฌ ํƒ€์ž…์˜ ํ—ˆ์šฉ ๋ฒ”์œ„๋ฅผ ํ•œ์ •ํ•˜๋Š” ๊ฒƒ์„ ๋งํ•œ๋‹ค. ์ฃผ๋กœ Comparable ์ธํ„ฐํŽ˜์ด์Šค์™€ ํ•จ๊ป˜ ์‚ฌ์šฉ๋˜์–ด, ํŠน์ • ํƒ€์ž…์ด ์ž๊ธฐ ์ž์‹ ๊ณผ ๋น„๊ตํ•  ์ˆ˜ ์žˆ๋„๋ก ์ œํ•œํ•œ๋‹ค.

์žฌ๊ท€์  ํƒ€์ž… ํ•œ์ •์€ ์ •๋ ฌ, ๊ฒ€์ƒ‰, ์ตœ๋Œ“๊ฐ’ ๋˜๋Š” ์ตœ์†Ÿ๊ฐ’ ๊ณ„์‚ฐ๊ณผ ๊ฐ™์€ ๋น„๊ต ์—ฐ์‚ฐ์ด ํ•„์š”ํ•œ ๋ฉ”์„œ๋“œ์—์„œ ์ž์ฃผ ์‚ฌ์šฉ๋œ๋‹ค.

// ์ปฌ๋ ‰์…˜ ๋‚ด์˜ ์›์†Œ ์ค‘์—์„œ ๊ฐ€์žฅ ํฐ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฉ”์„œ๋“œ
// <E extends Comparable<E>>๋Š” E ํƒ€์ž…์ด ์ž๊ธฐ ์ž์‹ ๊ณผ ๋น„๊ต ๊ฐ€๋Šฅํ•˜๋‹ค๋Š” ์˜๋ฏธ
public static <E extends Comparable<E>> E max(Collection<E> c) {
    // ์ปฌ๋ ‰์…˜์ด ๋น„์–ด ์žˆ๋Š” ๊ฒฝ์šฐ ์˜ˆ์™ธ ๋ฐœ์ƒ
    if (c.isEmpty()) {
        throw new IllegalArgumentException("์ปฌ๋ ‰์…˜์ด ๋น„์–ด ์žˆ์Šต๋‹ˆ๋‹ค.");
    }

    E result = null;
    // ์ปฌ๋ ‰์…˜์˜ ๊ฐ ์›์†Œ๋ฅผ ์ˆœํšŒํ•˜๋ฉฐ ์ตœ๋Œ“๊ฐ’ ์ฐพ๊ธฐ
    for (E e : c) {
        // ์ฒ˜์Œ ์›์†Œ์ด๊ฑฐ๋‚˜ ํ˜„์žฌ ์ตœ๋Œ“๊ฐ’๋ณด๋‹ค ํฐ ๊ฒฝ์šฐ ์ตœ๋Œ“๊ฐ’ ๊ฐฑ์‹ 
        if (result == null || e.compareTo(result) > 0) {
            result = e;
        }
    }
    // ์ตœ๋Œ“๊ฐ’ ๋ฐ˜ํ™˜
    return result;
}

์œ„ ๋ฉ”์„œ๋“œ๋Š” ์ปฌ๋ ‰์…˜์˜ ์ตœ๋Œ“๊ฐ’์„ ๊ตฌํ•˜๋ฉฐ, Comparable<E>๋ฅผ ๊ตฌํ˜„ํ•œ ํƒ€์ž…์ด์–ด์•ผ๋งŒ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๋‹ค.

  • <E extends Comparable<E>> : ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜ E๋Š” Comparable<E>๋ฅผ ๊ตฌํ˜„ํ•ด์•ผ ํ•œ๋‹ค๋Š” ๋œป์ž…๋‹ˆ๋‹ค. ์ฆ‰, E ํƒ€์ž…์˜ ๊ฐ์ฒด๋ผ๋ฆฌ ๋น„๊ตํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•œ๋‹ค.
  • ์ด ๋ฉ”์„œ๋“œ๋Š” ์ปฌ๋ ‰์…˜์— ์žˆ๋Š” ์›์†Œ์˜ ์ž์—ฐ์  ์ˆœ์„œ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์ตœ๋Œ“๊ฐ’์„ ์ฐพ๋Š”๋‹ค.
  • ์ปฌ๋ ‰์…˜์ด ๋น„์–ด ์žˆ์„ ๊ฒฝ์šฐ IllegalArgumentException์„ ์ฐพ๋Š”๋‹ค.
  • ์žฌ๊ท€์  ํƒ€์ž… ํ•œ์ •์„ ํ†ตํ•ด E ํƒ€์ž…์˜ ๊ฐ์ฒด๊ฐ€ ์„œ๋กœ ๋น„๊ต ๊ฐ€๋Šฅํ•จ์„ ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ๋ณด์žฅํ•ด์ค€๋‹ค.

JPA EnumConverter ์˜ˆ์‹œ

public interface CodeValue {
	String getCode();
	String getValue();
}

public class EnumConverter<E extends Enum<E> & CodeValue> implements AttributeConverter<E, String> {

	private Class<E> clz;

	protected EnumConverter(Class<E> enumClass) {
		this.clz = enumClass;
	}

	@Override
	public String convertToDatabaseColumn(E attribute) {
		return attribute != null ? attribute.getCode() : null;
	}

	@Override
	public E convertToEntityAttribute(String dbData) {
		if (dbData == null)
			return null;
		return EnumSet.allOf(clz).stream()
			.filter(e -> e.getCode().equals(dbData))
			.findAny()
			.orElseThrow(() -> new BusinessException(ErrorCode.ENUM_NOT_FOUND));
	}
}

@Converter(autoApply = true)
public class ChargerTypeConverter extends EnumConverter<ChargerType> {
	public ChargerTypeConverter() {
		super(ChargerType.class);
	}
}

@Convert(converter = ChargerTypeConverter.class)
@Column(name = "charger_type", nullable = false)
private ChargerType chargerType;

public enum ChargerType implements CodeValue {
	SLOW("SLOW", "์™„์†"),
	AC3("AC3", "AC3์ƒ"),
	DESTINATION("DESTINATION", "๊ธ‰์†"),
	ETC("ETC", "๊ธฐํƒ€"),
	;

	private final String code;
	private final String value;

	ChargerType(String code, String value) {
		this.code = code;
		this.value = value;
	}

	@Override
	public String getCode() {
		return code;
	}

	@Override
	public String getValue() {
		return value;
	}
}

์ด ์ฝ”๋“œ๋Š” JPA(Java Persistence API)์—์„œ ์‚ฌ์šฉ๋˜๋Š” ์ปค์Šคํ…€ AttributeConverter๋ฅผ ํ†ตํ•ด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์™€ ์—”ํ‹ฐํ‹ฐ ๊ฐ„์˜ ๋ณ€ํ™˜์„ ์ฒ˜๋ฆฌํ•˜๋Š” ์˜ˆ์ œ์ž…๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ๋Š” Enum ํƒ€์ž…์ธ ChargerType์„ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ปฌ๋Ÿผ์— ์ €์žฅํ•˜๊ณ , ๋‹ค์‹œ ์—”ํ‹ฐํ‹ฐ ์†์„ฑ์œผ๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๊ณผ์ •์„ ๋‹ค๋ฃน๋‹ˆ๋‹ค.

์ฃผ์š” ๊ตฌ์„ฑ ์š”์†Œ ์„ค๋ช…

  1. CodeValue ์ธํ„ฐํŽ˜์ด์Šค

    • ์ด ์ธํ„ฐํŽ˜์ด์Šค๋Š” ๊ฐ ์—ด๊ฑฐํ˜•(Enum)์ด getCode()์™€ getValue() ๋ฉ”์„œ๋“œ๋ฅผ ๊ตฌํ˜„ํ•ด์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ๋ณด์žฅํ•ฉ๋‹ˆ๋‹ค.
    • ์ด ์ฝ”๋“œ์—์„œ๋Š” getCode()๊ฐ€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ €์žฅํ•  ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๊ณ , getValue()๊ฐ€ ํ‘œํ˜„ํ•  ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
    public interface CodeValue {
        String getCode();
        String getValue();
    }
  2. EnumConverter ํด๋ž˜์Šค

    • ์ด ํด๋ž˜์Šค๋Š” AttributeConverter<E, String>์„ ๊ตฌํ˜„ํ•˜์—ฌ ์ œ๋„ค๋ฆญ ํƒ€์ž…์˜ ์—ด๊ฑฐํ˜•(E extends Enum<E> & CodeValue)์„ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ String ํƒ€์ž…์œผ๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.
    • E๋Š” Enum ํƒ€์ž…์ด๋ฉด์„œ CodeValue ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•œ ์—ด๊ฑฐํ˜•์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.
    • AttributeConverter<E, String>: E ํƒ€์ž…์˜ ์†์„ฑ์„ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ String ํƒ€์ž…์œผ๋กœ ๋ณ€ํ™˜ํ•˜๊ณ , ๋ฐ˜๋Œ€๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.
    public class EnumConverter<E extends Enum<E> & CodeValue> implements AttributeConverter<E, String> {
        private Class<E> clz;
    
        protected EnumConverter(Class<E> enumClass) {
            this.clz = enumClass;
        }
    
        @Override
        public String convertToDatabaseColumn(E attribute) {
            // ์—”ํ‹ฐํ‹ฐ ์†์„ฑ(E)์„ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ปฌ๋Ÿผ(String)์œผ๋กœ ๋ณ€ํ™˜
            return attribute != null ? attribute.getCode() : null;
        }
    
        @Override
        public E convertToEntityAttribute(String dbData) {
            // ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ String์„ ์—”ํ‹ฐํ‹ฐ ์†์„ฑ์œผ๋กœ ๋ณ€ํ™˜
            if (dbData == null)
                return null;
            return EnumSet.allOf(clz).stream()
                .filter(e -> e.getCode().equals(dbData)) // Enum์˜ ์ฝ”๋“œ์™€ ์ผ์น˜ํ•˜๋Š” ํ•ญ๋ชฉ์„ ์ฐพ์Œ
                .findAny()
                .orElseThrow(() -> new BusinessException(ErrorCode.ENUM_NOT_FOUND)); // ์ฐพ์ง€ ๋ชปํ•˜๋ฉด ์˜ˆ์™ธ ๋ฐœ์ƒ
        }
    }
    • convertToDatabaseColumn ๋ฉ”์„œ๋“œ:
      • ์—”ํ‹ฐํ‹ฐ์˜ ์—ด๊ฑฐํ˜• ์†์„ฑ์„ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ €์žฅํ•  String ํƒ€์ž…์˜ ๊ฐ’์œผ๋กœ ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
      • ์—ด๊ฑฐํ˜• ๊ฐ’์ด null์ธ ๊ฒฝ์šฐ null์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด getCode() ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ๋ณ€ํ™˜๋œ ์ฝ”๋“œ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
    • convertToEntityAttribute ๋ฉ”์„œ๋“œ:
      • ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ๊ฐ€์ ธ์˜จ String ๊ฐ’์„ ์—”ํ‹ฐํ‹ฐ์˜ ์—ด๊ฑฐํ˜• ํƒ€์ž…์œผ๋กœ ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
      • EnumSet.allOf(clz)๋ฅผ ํ†ตํ•ด ํ•ด๋‹น ์—ด๊ฑฐํ˜• ํด๋ž˜์Šค์˜ ๋ชจ๋“  ๊ฐ’์„ ์ˆœํšŒํ•˜๋ฉฐ, getCode() ๋ฉ”์„œ๋“œ๋กœ ํ•„ํ„ฐ๋งํ•˜์—ฌ ๋งค์นญ๋˜๋Š” ์—ด๊ฑฐํ˜• ๊ฐ’์„ ์ฐพ์Šต๋‹ˆ๋‹ค.
      • ๋งค์นญ๋˜๋Š” ๊ฐ’์ด ์—†์œผ๋ฉด BusinessException์„ ๋ฐœ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค(ENUM_NOT_FOUND).
  3. ChargerTypeConverter ํด๋ž˜์Šค

    • EnumConverter์˜ ๊ตฌ์ฒด์ ์ธ ๊ตฌํ˜„์ฒด๋กœ, ChargerType ์—ด๊ฑฐํ˜• ํƒ€์ž…์— ๋Œ€ํ•œ ๋ณ€ํ™˜๊ธฐ๋ฅผ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.
    • @Converter(autoApply = true) ์–ด๋…ธํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•˜์—ฌ JPA๊ฐ€ ์ž๋™์œผ๋กœ ์ด ๋ณ€ํ™˜๊ธฐ๋ฅผ ์ ์šฉํ•˜๋„๋ก ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
    @Converter(autoApply = true)
    public class ChargerTypeConverter extends EnumConverter<ChargerType> {
        public ChargerTypeConverter() {
            super(ChargerType.class);
        }
    }
  4. ChargerType ์—ด๊ฑฐํ˜•

    • ChargerType์€ CodeValue ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•œ ์—ด๊ฑฐํ˜•์ž…๋‹ˆ๋‹ค.
    • ๊ฐ ์ƒ์ˆ˜์—๋Š” code์™€ value๋ผ๋Š” ๋‘ ๊ฐœ์˜ ํ•„๋“œ๋ฅผ ๊ฐ€์ง€๋ฉฐ, ์ด๋Š” ์ƒ์„ฑ์ž์—์„œ ์„ค์ •๋ฉ๋‹ˆ๋‹ค.
    • ์˜ˆ๋ฅผ ๋“ค์–ด, SLOW("SLOW", "์™„์†")๋Š” code๊ฐ€ "SLOW"์ด๊ณ , value๊ฐ€ "์™„์†"์ธ ์—ด๊ฑฐํ˜• ์ƒ์ˆ˜๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

    ์˜ค์ง jpa๋งŒ ์žˆ๋Š” ์ปจํ„ฐ๋ฒ„ ๊ธฐ๋Šฅ์œผ๋กœ SLOW => ์™„์†์œผ๋กœ DB์— ๋“ค์–ด๊ฐ€๊ณ  ๋˜ ์ž๋ฐ”๋กœ ๋‚˜์˜ฌ๋•Œ SLOW๋กœ ๋‚˜์˜ค๋Š” ๊ทธ๋Ÿฐ ๋Š๋‚Œ?

    public enum ChargerType implements CodeValue {
        SLOW("SLOW", "์™„์†"),
        AC3("AC3", "AC3์ƒ"),
        DESTINATION("DESTINATION", "๊ธ‰์†"),
        ETC("ETC", "๊ธฐํƒ€");
    
        private final String code;
        private final String value;
    
        ChargerType(String code, String value) {
            this.code = code;
            this.value = value;
        }
    
        @Override
        public String getCode() {
            return code;
        }
    
        @Override
        public String getValue() {
            return value;
        }
    }
  5. ์—”ํ‹ฐํ‹ฐ์—์„œ์˜ ์‚ฌ์šฉ ์˜ˆ์‹œ

    @Convert(converter = ChargerTypeConverter.class)
    @Column(name = "charger_type", nullable = false)
    private ChargerType chargerType;
    • ์ด ์ฝ”๋“œ์—์„œ๋Š” chargerType ํ•„๋“œ๊ฐ€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ charger_type ์ปฌ๋Ÿผ๊ณผ ๋งคํ•‘๋ฉ๋‹ˆ๋‹ค.
    • @Convert ์–ด๋…ธํ…Œ์ด์…˜์„ ํ†ตํ•ด ChargerTypeConverter๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ChargerType ๊ฐ’์„ ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

๋™์ž‘ ํ๋ฆ„

  1. ์—”ํ‹ฐํ‹ฐ -> ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค:
    • ChargerType ์—ด๊ฑฐํ˜• ๊ฐ’์ด convertToDatabaseColumn ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด String ๊ฐ’์œผ๋กœ ๋ณ€ํ™˜๋˜์–ด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ €์žฅ๋ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ChargerType.SLOW์˜ ๊ฒฝ์šฐ "SLOW"๋กœ ์ €์žฅ๋ฉ๋‹ˆ๋‹ค.
  2. ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค -> ์—”ํ‹ฐํ‹ฐ:
    • ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ๊ฐ€์ ธ์˜จ String ๊ฐ’์ด convertToEntityAttribute ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ChargerType ์—ด๊ฑฐํ˜• ๊ฐ’์œผ๋กœ ๋ณ€ํ™˜๋ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, "SLOW"๊ฐ€ ChargerType.SLOW๋กœ ๋ณ€ํ™˜๋ฉ๋‹ˆ๋‹ค.
  3. ์˜ˆ์™ธ ์ฒ˜๋ฆฌ:
    • ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ๊ฐ’์ด ๋งค์นญ๋˜๋Š” ChargerType ์ƒ์ˆ˜๋ฅผ ์ฐพ์ง€ ๋ชปํ•˜๋ฉด BusinessException์ด ๋ฐœ์ƒํ•˜์—ฌ ์ฒ˜๋ฆฌ๋ฉ๋‹ˆ๋‹ค.

์ฝ”๋“œ์˜ ์žฅ์ 

  • ์ผ๊ด€์„ฑ ์œ ์ง€: ์—ด๊ฑฐํ˜• ๊ฐ’์„ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ฝ”๋“œ๋กœ ์ €์žฅํ•˜๊ณ , ์ฝ”๋“œ ๊ฐ’์œผ๋กœ๋ถ€ํ„ฐ ์—ด๊ฑฐํ˜• ๊ฐ’์„ ๋งคํ•‘ํ•  ์ˆ˜ ์žˆ๋Š” ์ผ๊ด€๋œ ๋ฐฉ์‹์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
  • ์žฌ์‚ฌ์šฉ์„ฑ: EnumConverter๋Š” ๋ชจ๋“  CodeValue ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ์—ด๊ฑฐํ˜•์— ๋Œ€ํ•ด ๋ฒ”์šฉ์ ์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋ณ€ํ™˜๊ธฐ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
  • ์œ ์—ฐํ•œ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ: ๋ณ€ํ™˜ ์‹คํŒจ ์‹œ ์˜ˆ์™ธ๋ฅผ ๋ช…ํ™•ํ•˜๊ฒŒ ์ •์˜ํ•˜์—ฌ ์˜ค๋ฅ˜ ์ƒํ™ฉ์„ ์‰ฝ๊ฒŒ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด ์ฝ”๋“œ๋Š” JPA์—์„œ ์—ด๊ฑฐํ˜• ํƒ€์ž…์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐ ์œ ์šฉํ•˜๋ฉฐ, ์ปค์Šคํ…€ ๋ณ€ํ™˜๊ธฐ๋ฅผ ํ†ตํ•ด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์™€ ์—”ํ‹ฐํ‹ฐ ๊ฐ„์˜ ๋ณ€ํ™˜์„ ํšจ๊ณผ์ ์œผ๋กœ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

์žฅ์ ์€?

์ด ์ฝ”๋“œ๋Š” JPA์—์„œ ์—ด๊ฑฐํ˜•(Enum) ํƒ€์ž…์„ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์™€ ์—ฐ๋™ํ•  ๋•Œ ๋ช‡ ๊ฐ€์ง€ ์ค‘์š”ํ•œ ์ด์ ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค:

1. ์ฝ”๋“œ์™€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๊ฐ„์˜ ๋งคํ•‘์„ ์ผ๊ด€๋˜๊ฒŒ ์œ ์ง€

  • EnumConverter๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์—ด๊ฑฐํ˜• ๊ฐ’(์˜ˆ: ChargerType.SLOW)์„ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ €์žฅํ•  ๋•Œ ๋ฌธ์ž์—ด(SLOW)๋กœ ๋ณ€ํ™˜ํ•˜๊ณ , ๋‹ค์‹œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ์—ด๊ฑฐํ˜• ํƒ€์ž…์œผ๋กœ ๋ณ€ํ™˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์ด๋ฅผ ํ†ตํ•ด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์™€ ์ฝ”๋“œ ๊ฐ„์˜ ๋ฐ์ดํ„ฐ ์ผ๊ด€์„ฑ์„ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์—ด๊ฑฐํ˜• ๊ฐ’์ด ๋ณ€๊ฒฝ๋˜๋”๋ผ๋„ ์ฝ”๋“œ์˜ ๋ณ€๊ฒฝ๋งŒ์œผ๋กœ ์‰ฝ๊ฒŒ ๋ฐ˜์˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

2. ์ปค์Šคํ…€ ๋ณ€ํ™˜ ๋กœ์ง ๊ตฌํ˜„์˜ ์œ ์—ฐ์„ฑ

  • EnumConverter๋ฅผ ํ†ตํ•ด ๋ณ€ํ™˜ ๋กœ์ง์„ ์ปค์Šคํ„ฐ๋งˆ์ด์ฆˆํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ €์žฅํ•˜๋Š” ๊ฐ’์˜ ํ˜•์‹์ด๋‚˜ ํŠน์ • ์กฐ๊ฑด์— ๋”ฐ๋ฅธ ๋ณ€ํ™˜ ๋ฐฉ์‹์„ ์‰ฝ๊ฒŒ ์กฐ์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • JPA์˜ ๊ธฐ๋ณธ ๋ณ€ํ™˜๊ธฐ ๋Œ€์‹  ์ปค์Šคํ…€ ๋ณ€ํ™˜๊ธฐ๋ฅผ ์‚ฌ์šฉํ•จ์œผ๋กœ์จ, ์—”ํ‹ฐํ‹ฐ ํ•„๋“œ์— ๋Œ€ํ•œ ์„ธ๋ถ€์ ์ธ ๋ณ€ํ™˜ ๋กœ์ง์„ ์ ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

3. ์ฝ”๋“œ์˜ ์žฌ์‚ฌ์šฉ์„ฑ๊ณผ ์œ ์ง€๋ณด์ˆ˜์„ฑ ํ–ฅ์ƒ

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

4. ์•ˆ์ „ํ•œ ํƒ€์ž… ๋ณ€ํ™˜๊ณผ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ

  • ๋ณ€ํ™˜ ์‹œ ๋งค์นญ๋˜๋Š” ์—ด๊ฑฐํ˜•์ด ์—†์œผ๋ฉด BusinessException์„ ํ†ตํ•ด ์˜ˆ์™ธ๋ฅผ ๋ช…ํ™•ํ•˜๊ฒŒ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ์ž˜๋ชป๋œ ๋ฐ์ดํ„ฐ๋‚˜ ์˜ˆ์ƒ์น˜ ๋ชปํ•œ ๊ฐ’์ด ๋“ค์–ด์˜ค๋Š” ์ƒํ™ฉ์— ๋Œ€๋น„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • CodeValue ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ†ตํ•ด ๊ฐ ์—ด๊ฑฐํ˜•์ด getCode()์™€ getValue()๋ฅผ ๋ฐ˜๋“œ์‹œ ๊ตฌํ˜„ํ•˜๋„๋ก ๊ฐ•์ œํ•จ์œผ๋กœ์จ, ํƒ€์ž… ์•ˆ์ •์„ฑ์„ ๋ณด์žฅํ•ฉ๋‹ˆ๋‹ค.

5. ์ž๋™ ๋งคํ•‘ ๊ธฐ๋Šฅ ์ง€์›

  • @Converter(autoApply = true)๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ํ•ด๋‹น ๋ณ€ํ™˜๊ธฐ๋ฅผ ์ž๋™์œผ๋กœ ์ ์šฉํ•˜์—ฌ, ์—”ํ‹ฐํ‹ฐ์—์„œ ๋งค๋ฒˆ @Convert๋ฅผ ๋ช…์‹œํ•˜์ง€ ์•Š์•„๋„ ๋ฉ๋‹ˆ๋‹ค. ์ด๋Š” ์ฝ”๋“œ์˜ ๊ฐ„๊ฒฐํ•จ๊ณผ ๊ฐ€๋…์„ฑ์„ ๋†’์—ฌ์ค๋‹ˆ๋‹ค.

6. ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์Šคํ‚ค๋งˆ ๋ณ€๊ฒฝ ์‹œ ์œ ์—ฐ์„ฑ ์ œ๊ณต

  • ์˜ˆ๋ฅผ ๋“ค์–ด, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ €์žฅ๋˜๋Š” ๋ฌธ์ž์—ด ๊ฐ’์ด "SLOW"์—์„œ "S"๋กœ ๋ณ€๊ฒฝ๋˜๋Š” ์ƒํ™ฉ์ด ๋ฐœ์ƒํ•  ๋•Œ, EnumConverter์˜ ๋ณ€ํ™˜ ๋กœ์ง๋งŒ ์ˆ˜์ •ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์Šคํ‚ค๋งˆ ๋ณ€๊ฒฝ์— ์œ ์—ฐํ•˜๊ฒŒ ๋Œ€์ฒ˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ •๋ฆฌ

์ด ์ฝ”๋“œ์˜ ์ฃผ์š” ์žฅ์ ์€ ์ผ๊ด€๋œ ๋ณ€ํ™˜ ๋กœ์ง๊ณผ ์žฌ์‚ฌ์šฉ์„ฑ, ์œ ์—ฐํ•œ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ๋ฅผ ํ†ตํ•ด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์™€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ฐ„์˜ ๋งคํ•‘์„ ์•ˆ์ „ํ•˜๊ณ  ํšจ์œจ์ ์œผ๋กœ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์ž…๋‹ˆ๋‹ค. EnumConverter๋ฅผ ํ†ตํ•ด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ๊ฐ’๊ณผ ์ฝ”๋“œ์˜ ์—ด๊ฑฐํ˜• ๊ฐ„์˜ ๋งคํ•‘์„ ๋ช…ํ™•ํžˆ ์ •์˜ํ•จ์œผ๋กœ์จ, ์œ ์ง€๋ณด์ˆ˜์„ฑ์ด ๋†’๊ณ  ์˜ค๋ฅ˜ ๋ฐœ์ƒ ๊ฐ€๋Šฅ์„ฑ์ด ๋‚ฎ์•„์ง‘๋‹ˆ๋‹ค.

MYBATIS

ํƒ€์ž… ํ•ธ๋“ค๋Ÿฌ๋ผ๋Š” ํด๋ž˜์Šค ์ •์˜, XML์— ๋„ฃ์–ด๋‘๋ฉด ์—ด๊ฑฐํ˜• ๋ณ€ํ™˜ํ•ด์ค€๋‹ค๋Š” ๊ฒƒ

์ถœ์ฒ˜ : https://velog.io/@ghk4889/mybatis%EC%9D%98-custom-typehandler-%EB%A7%8C%EB%93%A4%EA%B8%B0JAVA-Enum-%ED%83%80%EC%9E%85

์žฌ๊ท€์  ํƒ€์ž… ํ•œ์ •์˜ ์˜๋ฏธ

<E extends Comparable<E>>๋Š” "E ํƒ€์ž…์˜ ๊ฐ์ฒด๊ฐ€ ์ž๊ธฐ ์ž์‹ (E)๊ณผ ๋น„๊ต ๊ฐ€๋Šฅํ•˜๋‹ค"๋Š” ์˜๋ฏธ์ด๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, String์€ Comparable<String>์„ ๊ตฌํ˜„ํ•˜๊ณ , Integer๋Š” Comparable<Integer>๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ์‹์ด๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ์ปฌ๋ ‰์…˜ ๋‚ด์˜ ์›์†Œ๊ฐ€ ์„œ๋กœ ๋น„๊ต ๊ฐ€๋Šฅํ•จ์„ ๋ณด์žฅํ•  ์ˆ˜ ์žˆ๋‹ค.

โœจ ์ตœ์ข… ์ •๋ฆฌ : ์ œ๋„ค๋ฆญ ๋ฉ”์„œ๋“œ์˜ ์žฅ์ ๊ณผ ํ™œ์šฉ

  1. ์•ˆ์ „์„ฑ๊ณผ ํŽธ๋ฆฌ์„ฑ:
  • ์ œ๋„ค๋ฆญ ๋ฉ”์„œ๋“œ๋Š” ํƒ€์ž… ์•ˆ์ „์„ฑ์„ ์ œ๊ณตํ•˜์—ฌ, ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ ์‹œ ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ํƒ€์ž… ๊ฒ€์‚ฌ๋ฅผ ํ•ด์ค€๋‹ค.
  • ํ˜•๋ณ€ํ™˜์„ ๋ช…์‹œ์ ์œผ๋กœ ํ•  ํ•„์š”๊ฐ€ ์—†์–ด์„œ ์‚ฌ์šฉํ•˜๊ธฐ ์‰ฝ๊ณ , ์ฝ”๋“œ์˜ ๊ฐ€๋…์„ฑ๋„ ํ–ฅ์ƒ๋œ๋‹ค.
  1. ํ˜•๋ณ€ํ™˜ ์—†๋Š” ์‚ฌ์šฉ:
  • ์ œ๋„ค๋ฆญ ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด, ์ž…๋ ฅ ๋งค๊ฐœ๋ณ€์ˆ˜์™€ ๋ฐ˜ํ™˜๊ฐ’์˜ ํƒ€์ž…์„ ๋ช…์‹œ์ ์œผ๋กœ ํ˜•๋ณ€ํ™˜ํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค.
  • ๋ฉ”์„œ๋“œ์˜ ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ํƒ€์ž…์„ ๊ฒฐ์ •ํ•˜๋ฏ€๋กœ, ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๋ถˆํ•„์š”ํ•œ ํ˜•๋ณ€ํ™˜ ์—†์ด ์•ˆ์ „ํ•˜๊ฒŒ ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
  1. ๊ธฐ์กด ๋ฉ”์„œ๋“œ์˜ ๊ฐœ์„ :
  • ๊ธฐ์กด์˜ ํ˜•๋ณ€ํ™˜์„ ํ•„์š”๋กœ ํ•˜๋Š” ๋ฉ”์„œ๋“œ๋Š” ์ œ๋„ค๋ฆญ ๋ฉ”์„œ๋“œ๋กœ ๋ณ€๊ฒฝํ•˜์—ฌ ๋” ์•ˆ์ „ํ•˜๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.
  • ๊ธฐ์กด ํด๋ผ์ด์–ธํŠธ ์ฝ”๋“œ์— ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š์œผ๋ฉด์„œ๋„, ์ƒˆ๋กœ์šด ์‚ฌ์šฉ์ž์—๊ฒŒ๋Š” ๋” ํŽธ๋ฆฌํ•œ ๋ฉ”์„œ๋“œ๋ฅผ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ๋‹ค.
  1. ์ฝ”๋“œ ์žฌ์‚ฌ์šฉ์„ฑ:
  • ์ œ๋„ค๋ฆญ ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋‹ค์–‘ํ•œ ํƒ€์ž…์— ๋Œ€ํ•ด ํ•˜๋‚˜์˜ ๋ฉ”์„œ๋“œ๋ฅผ ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด ์ฝ”๋“œ ์ค‘๋ณต์ด ์ค„์–ด๋“ ๋‹ค.
  • ์ œ๋„ค๋ฆญ ๋ฉ”์„œ๋“œ๋Š” ํƒ€์ž… ์•ˆ์ „์„ฑ๊ณผ ์ฝ”๋“œ ์žฌ์‚ฌ์šฉ์„ฑ์„ ๋†’์ธ๋‹ค.

์ œ๋„ค๋ฆญ์„ ์‚ฌ์šฉํ•˜๋ฉด ์ปดํŒŒ์ผ ์‹œ์ ์— ํƒ€์ž… ์•ˆ์ „์„ฑ์„ ๋ณด์žฅ๋ฐ›์„ ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๊ธฐ์กด ์ฝ”๋“œ์™€์˜ ํ˜ธํ™˜์„ฑ์„ ์œ ์ง€ํ•˜๋ฉด์„œ ๋” ์œ ์—ฐํ•˜๊ณ  ์•ˆ์ „ํ•œ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.

์ถœ์ฒ˜