24.11.07 TIL Generic

신성훈·2024년 11월 7일

TIL

목록 보기
73/162

제네릭(Generic)이란?

제네릭은 특정 타입에 의존하지 않고 다양한 타입을 처리할 수 있는 기능입니다. 컴파일 단계에서 타입 안정성을 확보할 수 있어, 런타임 오류를 줄이는 데 도움을 줍니다.

1. 제네릭의 장점

  1. 코드 재사용성 증가
    다양한 데이터 타입을 하나의 코드로 처리 가능

  2. 타입 안정성 유지
    컴파일 시점에서 타입 검사로 오류 방지

  3. 가독성 향상
    타입이 명확하게 정의되어 코드 이해도 증가

2. 제네릭 타입 매개변수 관례

T - Type (일반적인 타입)
E - Element (요소)
K - Key (키)
V - Value (값)
N - Number (숫자)

3. 기본 사용 예시

// 제네릭 클래스
public class Box<T> {
    private T value;
    
    public void setValue(T value) {
        this.value = value;
    }
    
    public T getValue() {
        return value;
    }
}

// 사용 예시
Box<Integer> intBox = new Box<>();
intBox.setValue(123);
System.out.println(intBox.getValue());  // 123

Box<String> strBox = new Box<>();
strBox.setValue("Hello");
System.out.println(strBox.getValue());  // Hello

4. 와일드카드 사용

// 상한 제한 와일드카드
public void processNumbers(List<? extends Number> numbers) {
    // Number의 하위 타입만 허용
}

// 하한 제한 와일드카드
public void addNumbers(List<? super Integer> numbers) {
    // Integer의 상위 타입만 허용
}

// 비한정적 와일드카드
public void printList(List<?> list) {
    // 모든 타입 허용
}

5. 제네릭 메소드

public class Util {
    public static <T> void swap(T[] array, int i, int j) {
        T temp = array[i];
        array[i] = array[j];
        array[j] = temp;
    }
}

6. Spring에서의 활용

// Repository 계층
public interface GenericRepository<T, ID> extends JpaRepository<T, ID> {
    // 공통된 메서드 정의
}

// Service 계층
public class UserService<T> {
    private final GenericRepository<T, Long> repository;
    
    public UserService(GenericRepository<T, Long> repository) {
        this.repository = repository;
    }
    
    public T findById(Long id) {
        return repository.findById(id).orElse(null);
    }
}

// ResponseEntity 사용
public ResponseEntity<List<UserDto>> getUsers() {
    List<UserDto> users = userService.findAll();
    return ResponseEntity.ok(users);
}

// Optional 사용
public Optional<User> findById(Long id) {
    return userRepository.findById(id);
}

// Stream API 활용
public List<UserDto> getUserDtos(List<User> users) {
    return users.stream()
               .map(UserDto::from)
               .collect(Collectors.toList());
}

7. 주의사항

// 제네릭 배열 생성 불가
T[] array = new T[10];  // 컴파일 에러

// 올바른 방법
T[] array = (T[]) new Object[10];

// 제네릭 타입 소거
// 컴파일 후에는 제네릭 타입 정보가 사라지고 Object로 변환됨

정리

제네릭은 Java와 Spring에서 타입 안정성과 코드 재사용성을 높이는 핵심 기능입니다. 특히 Spring의 Repository나 Service 계층에서 다양한 엔티티를 처리할 때 유용하게 활용됩니다. 다만, 제네릭 타입 소거나 배열 생성 제한 같은 특징들을 잘 이해하고 사용해야 합니다.
이러한 제네릭의 이해와 활용은 견고하고 유지보수가 쉬운 코드를 작성하는 데 큰 도움이 됩니다.

profile
조급해하지 말고, 흐름을 만들고, 기록하면서 쌓아가자.

0개의 댓글