interface 란? spring interface injection - interface의 구현체 주입

동기

인터페이스(interface)는 자바 프로그래밍 언어에서 클래스들이 구현해야 하는 동작을 지정하는데 사용되는 추상형이다.

위키백과

데이터를 가지고오는 repository가 있다고 가정해보자. 이 repository의 기능을 호출하여 원하는 데이터를 가지오고, 원하는 기능을 구현 할 수 있다.

그리고 실제로 데이터를 가지고 오는 방법에는 여러가지가 있다. mybatis, hibernate 처럼 방법이 다를수도있고 mydql, oricale, mongodb 처럼 저장소가 다를 수 있다.

하지만 이를 사용하는 caller입장에서는 원래 목적대로 데이터만 가지고 올 수 있으면 된다. 동일하게 여러가지 방법과 저장소를 repository라는 이름으로 부르고 그 역할을 데이터를 가지고 오도록 한다. 그리고 이를 호출하는 caller는 repository가 내부적으로 어떻게 동작하는지 구현체에 정보는 알 필요가 없다

이처럼 공통적인 기능을 interface로 정의하여 사용하는 입장에서는 동일하게.
그리고 세부적인 내용과 다른점은 구현체마다 각자 구현을 책임을지고 이를통해 결합도도 낮추고 확장성을 높일수 있다.

그리고 인터페이스의 스팩에 맞게 여러 구현체를 만들어 두었을때, 사용하는 caller 입장에서는 적절한 인터페이스를 골라서 사용할 필요가 있다. 본문에서는 인터페이스를 선택하는 방법에 관하여 다룬다.

인터페이스의 사용

같은 기능을 하는 여러개 구현체를 만들어놓고, 필요에따라서 구현체를 바꿔끼워가며 사용한다.
사용하는 입장에서는 내부 구현을 알 필요는 없고 상황에 맞게 구현체를 선택 하여 사용 할 수 있다.
그리고 실제 수행해야하는 동작들은 구현체가 책임을 가진다.

그렇다면 실제 로직에서 구현체를 선택하는 방법은 무엇이 있을까?

spirng이 아닌 순수 java에서

제일 많이 사용하는 예는 collection이 있다.

1
List<String> names = new ArrayList<>();

우리는 namesArrayList로 되어있는지 LinkedList로 되어있는지 알 필요없이 List로서 정의된 인터페이스를 사용하고, 실제 동작 로직은 구현체가 책임진다.

spring - interface 주입받기

어떠한 데이터를 가지고오는 방법으로 여러 종류의 datasource를 사용한다고 가정해보자.
데이터를 가지고온다는 행위를 repository의 기능으로 하고 인터페이스를만든다
그리고 이 방법에 대해서 구현체로 구현한다.

interface 구현

아래는 판매자 정보에 대한 인터페이스 예제이다

1
2
3
interface ShopRepository {
...
}

그리고 각각 jdbc / hibernate 2개종류의 구현체가 있다

1
2
3
4
@Repository
public class jdbcShopRepository implements ShopRepository {
...
}
1
2
3
4
@Repository
public class HibernateShopRepository implements ShopRepository {
...
}

사용

이름으로 구분

사용하는곳에서 이름으로 구분하는 방법이 있다. spring 에서는 인터페이스의 구현체가 여러개인경우 이름에 해당하는 의존성이 있다면 주입해준다

1
2
3
4
5
@Autowired
private ShopRepository jdbcShopRepository;

@Autowired
private ShopRepository HibernateShopRepository;

동일한이름이라면 @Primary

1
2
@Autowired
private ShopRepository shopRepository;

구현체를 구현할때 우선순위를 정해 줄 수 있다

1
2
3
4
5
@Primary
@Repository
public class jdbcShopRepository implements ShopRepository {
...
}
1
2
3
4
@Repository
public class HibernateShopRepository implements ShopRepository {
...
}

@Qualifier

변수명을통해 구현체의 이름으로 주입하기 싫다면 @Qualifier를 사용할수도 있다

1
2
3
4
5
6
7
@Autowired
@Qualifier("JdbcShopRepository")
private ShopRepository shopRepository1;

@Autowired
@Qualifier("HibernateShopRepository")
private ShopRepository shopRepository2;

next

api를 호출하는 파라메터에따라서, 특정시기에따라서 등 여러가지이유로 동적으로 구현체를 선택해야 하는 경우가 있다.
다음 포스팅에서는 동적으로 구현체를 선택하는 방법을 알아본다.

https://hyeonguj.github.io/2020/02/07/spring-interface-choice-implements-dynamically/

Comments