Generic이란
Generic을 이용하면 비슷한 기능을 하는 여러 함수/클래스들을 하나로 묶을 수 있기때문에 코드의 재사용성이 높아진다 제네릭 타입 사용법은 여러 자료들이 많기때문에 실제로 어떻게 사용될 수 있는지 예제를 만들어보았다

요구사항

  • 사용자가 사진데이터와 Todo데이터를 요구한다
  • 사진데이터와 Todo데이터를 특정서버로 HTTP 요청하는데 이 때 특정서버는 jsonplaceholder를 이용한다.
    • jsonholder의 Response는 다음과 같다 image image
    • WebClient를 이용하여 Http통신을 한다
1
2
3
4
5
6
      private WebClient getWebClient() {
              return WebClient.builder()
                      .baseUrl("https://jsonplaceholder.typicode.com")
                      .build();
          }
      

제네릭 타입 사용 전

1. Request Class 생성

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
abstract static private class Response{

}

@Data
@NoArgsConstructor
private static class Photo extends Response{
    Integer albumId;
    Integer id;
    String title;
    String url;
    String thumbnailUrl;
    String hi;
}

@Data
@NoArgsConstructor
private static class Todo extends Response{
    Integer userId;
    Integer id;
    String title;
    String completed;
}

2. 요청하는 함수

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public Photo requestPhoto() {
    Photo result = getWebClient().get()
            .uri("/photos/1")
            .retrieve()
            .bodyToMono(Photo.class)
            .block();

    return result;
}

public Todo requestTodo() {
    Todo result = getWebClient().get()
            .uri("/todos/1")
            .retrieve()
            .bodyToMono(Todo.class)
            .block();

    return result;
}

3. 실제클라이언트코드 겸 테스트코드

1
2
3
4
5
6
7
@Test
public void test(){
    Photo photo = requestPhoto();
    assertNull(requestPhoto().getHi());
    assertEquals(requestPhoto().getTitle(),"accusamus beatae ad facilis cum similique qui sunt");
    assertEquals(requestTodo().getTitle(),"delectus aut autem");
}

이처럼 클라이언트는 requestPhoto(), requestTodo() 이런식으로 요청별로 여러가지의 함수를 만들어야한다
하지만 제네릭 타입을 이용하면 하나의 함수로 통일시킬수있다

제네릭타입 사용 후

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public <T extends Response> T requestApi(String url, Class<T> classType) {
    T result = (T) getWebClient().get()
            .uri("/{url}/1",url)
            .retrieve()
            .bodyToMono(classType)
            .block();

    return (T)result;
}

@Test
public void test2(){
    assertEquals(requestApi("photos", Photo.class).getTitle(),"accusamus beatae ad facilis cum similique qui sunt");
    assertEquals(requestApi("todos", Todo.class).getTitle(),"delectus aut autem");
}
  • 자, 이제 여러가지 함수를 만들 필요 없이 requestApi() 함수 하나로 통일 시킬수있게 되었다
  • 다형성을 이용해야하기때문에 꼭 Request Class는 공통적으로 부모클래스를 상속받아야한다

댓글 쓰기