프로그래머스/Spring Boot

[Spring Boot] Generic

annovation 2025. 3. 10. 08:51

Generic

  • 제네릭(Generic)은 클래스나 메서드에서 사용할 데이터 타입을 컴파일 타임에 미리 지정하지 않고, 필요할 때 지정할 수 있도록 해주는 기능입니다. 즉, 다양한 타입의 데이터를 처리할 수 있도록 유연성을 제공하는 기능입니다.
  • 제네릭 <T> 타입 파라미터로, 다양한 타입의 데이터를 담을 수 있게 해줍니다.

Generic<T>

@JsonInclude(JsonInclude.Include.NON_NULL)
@AllArgsConstructor
@Getter
public class RsData<T> { // 제네릭 타입 T 선언
    private String resultCode;
    private String msg;
    private T data; // 제네릭 타입을 가진 변수

    public RsData(String resultCode, String msg) {
        this(resultCode, msg, null); // data가 null일 수도 있음
    }
}
  • <T>“어떤 타입이 올지 미리 정해지지 않은 타입” 을 의미합니다.
  • RsData 클래스가 사용될 때 실제 타입을 결정 하게 됩니다.
  • data 필드는 어떤 타입이든 받을 수 있는 변수가 됩니다.

Generic<T> 사용 예시

1. Generic<T> 활용한 RsData 클래스 구조 예시

public class RsData<T> {
    private String resultCode;  // 결과 코드
    private String msg;         // 메시지
    private T data;            // 제네릭 타입의 데이터

    // T 타입의 데이터를 포함한 생성자
    public RsData(String resultCode, String msg, T data) {
        this.resultCode = resultCode;
        this.msg = msg;
        this.data = data;
    }

    // 데이터 없는 버전의 생성자
    public RsData(String resultCode, String msg) {
        this(resultCode, msg, null);
    }
}

 

2. RsData<T> 사용 예시

// Post 타입으로 사용
RsData<Post> postRs = new RsData<>("200", "성공", new Post());

// List<Post> 타입으로 사용
RsData<List<Post>> postsRs = new RsData<>("200", "성공", postList);

// String 타입으로 사용
RsData<String> messageRs = new RsData<>("200", "성공", "안녕하세요");

// Void 타입으로 사용 (ex. DELETE 메서드의 경우 data가 null이어야 하므로)
RsData<Void> deleteitem = new RsData<>("200", "성공");
  • Void 타입 사용시, 지정된 제너릭 타입의 데이터 변수에 null이 아닐 경우 오류 발생

3. Controller에서 사용 예시

@PostMapping("/posts")
public RsData<PostDto> createPost(@RequestBody PostRequest request) {
    Post post = postService.create(request);
    return new RsData<>(
        "200",
        "게시글이 생성되었습니다.",
        new PostDto(post)
    );
}
  • return 타입을 정의된 PostDto 타입이 아닌 다른 타입(ex. String, int 등)이 return되면 바로 오류를 발견할 수 있다.
  • return 타입으로 RsData<PostDto>처럼 제너릭을 정의해주면, return new RsData<>처럼 return에서는 제너릭 타입을 생략가능하다.

Generic을 사용하는 이유

1. 타입 안정성

// 컴파일 시점에 타입 체크
RsData<Post> postRs = new RsData<>("200", "성공", new Post());
Post post = postRs.getData();  // 형변환 필요 없음

// 잘못된 타입 사용 시 컴파일 에러
String str = postRs.getData();  // 컴파일 에러!

 

2. 코드 재사용

// 다양한 타입에 대해 같은 응답 구조 사용
public RsData<Post> createPost() { ... }
public RsData<Comment> createComment() { ... }
public RsData<User> createUser() { ... }

출처

OpenAI ChatGPT (https://openai.com)