자바에서 인터페이스(Interface)는 메서드의 집합을 정의하는 데 사용되는 추상 타입이다. 인터페이스는 클래스가 구현해야 하는 메서드의 서명을 지정하지만, 실제 구현은 제공하지 않는다. 이를 통해 특정 기능을 클래스가 구현하도록 강제할 수 있다.
자바 인터페이스의 주요 특징
- 추상 메서드(abstract methods)
- 인터페이스 내의 모든 메서드는 기본적으로 abstract이며, 메서드 본문이 없다.
- 자바 8부터는 default 메서드와 static 메서드를 사용할 수 있어 메서드 본문을 가질 수 있다.
- 상수(constants)
- 인터페이스 내에 정의된 변수는 'public static final'로 자동으로 지정되며, 상수로 취급된다.
- 다중 상속
- 클래스는 하나의 부모 클래스만 상속할 수 있지만, 여러 개의 인터페이스를 구현할 수는 있다. 이를 통해 다중 상속의 문제를 해결할 수 있다.
- 구현(implements)
- 인터페이스를 구현하는 클래스는 implements 키워드를 사용하며, 인터페이스에 정의된 모든 메서드를 구현해야 한다.
인터페이스의 사용 목적
- 표준화
- 인터페이스는 클래스가 특정 메서드를 구현하도록 강제하여 일관성을 유지할 수 있다. 예를 들어, 여러 클래스가 동일한 메서드를 가지도록 하여 사용자가 해당 메서드를 일관되게 사용할 수 있다.
- 유연한 설계
- 인터페이스를 사용하면 클래스의 구체적인 구현에 의존하지 않고, 상호작용을 정의할 수 있다. 이는 시스템이 확장 가능하고 유지보수하기 쉽게 만든다.
- 다형성(polymorphism)
- 인터페이스를 통해 다형성을 구현할 수 있다. 인터페이스 타입의 변수는 해당 인터페이스를 구현한 어떤 클래스의 인스턴스도 참조할 수 있다. 이를 통해 코드의 유연성과 재사용성을 높일 수 있다.
// 인터페이스 정의
public interface Animal {
void makeSound(); // 추상 메서드
}
// 인터페이스를 구현하는 클래스
public class Dog implements Animal {
@Override
public void makeSound() {
System.out.println("Woof");
}
}
public class Cat implements Animal {
@Override
public void makeSound() {
System.out.println("Meow");
}
}
public class Main {
public static void main(String[] args) {
Animal dog = new Dog();
Animal cat = new Cat();
dog.makeSound(); // 출력: Woof
cat.makeSound(); // 출력: Meow
}
}
이 예제에서 Animal 인터페이스는 makeSound 메서드를 정의한다. Dog와 Cat 클래스는 각각 Animal 인터페이스를 구현하고 makeSound 메서드를 구체적으로 정의한다. 이로써 Main 클래스에서 Animal 타입의 변수로 Dog와 Cat 객체를 생성하고, 각각의 makeSound 메서드를 호출할 수 있다.
인터페이스를 사용하면, 코드의 결합도를 낮추고, 모듈성을 높이며, 유지보수와 확장을 용이하게 할 수 있다.
Java Spring 프레임워크에서도 Inteface를 사용하는 것은 여러 가지 이점을 준다.
의존성 주입(Dependency Injection)
Spring에서는 의존성 주입을 통해 객체 간의 결합도를 낮추고, 객체의 생성과 관리를 Spring 컨테이너가 담당하게 한다. 인터페이스를 사용하면 구현체 간의 의존성을 줄여 코드의 유연성을 높일 수 있다.
public interface UserService {
void createUser(String name);
}
@Service
public class UserServiceImpl implements UserService {
@Override
public void createUser(String name) {
// 사용자 생성 로직
}
}
@Controller
public class UserController {
private final UserService userService;
@Autowired
public UserController(UserService userService) {
this.userService = userService;
}
// 요청 핸들러 메서드
}
이 예제에서 UserController는 UserService 인터페이스에 의존하고 있다. Spring의 의존성 주입을 통해 UserServiceImpl 구현체가 주입된다. 이를 통해 UserController는 UserServiceImpl 구현체의 변경에 영향을 받지 않고, 인터페이스를 통해 서비스 메서드를 호출할 수 있다.
테스트 용이성
인터페이스를 사용하면 테스트 시 Mock 객체나 스텁을 쉽게 주입할 수 있다. 이는 단위 테스트 작성과 테스트 자동화에 매우 유리하다.
@RunWith(SpringRunner.class)
@WebMvcTest(UserController.class)
public class UserControllerTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private UserService userService;
@Test
public void testCreateUser() throws Exception {
// given
String userName = "John Doe";
doNothing().when(userService).createUser(userName);
// when & then
mockMvc.perform(post("/users")
.param("name", userName))
.andExpect(status().isOk());
verify(userService, times(1)).createUser(userName);
}
}
이 테스트에서 UserService는 @MockBean을 사용해 Mock 객체로 주입되었다. 이를 통해 실제 구현체 없이도 UserController의 기능을 테스트할 수 있다.
유연한 아키텍처와 유지보수성
인터페이스를 사용하면 구현체의 변경이 용이해진다. 예를 들어, 새로운 기능을 추가하거나 기존 기능을 변경할 때 인터페이스를 구현하는 새로운 클래스를 작성해 기존 코드를 수정하지 않고도 시스템을 확장할 수 있다.
public interface PaymentService {
void processPayment();
}
@Service
public class CreditCardPaymentService implements PaymentService {
@Override
public void processPayment() {
// 신용카드 결제 처리 로직
}
}
@Service
public class PayPalPaymentService implements PaymentService {
@Override
public void processPayment() {
// PayPal 결제 처리 로직
}
}
@Configuration
public class PaymentConfig {
@Bean
public PaymentService paymentService() {
// 조건에 따라 다른 구현체를 반환
return new CreditCardPaymentService();
}
}
이 예제에서는 PaymentService 인터페이스를 구현하는 여러 구현체가 있다. 설정 클래스에서 조건에 따라 다른 구현체를 반환하도록 하여, 시스템의 요구사항에 맞게 쉽게 구현체를 변경할 수 있다.
결론
Java Spring에서 인터페이스를 사용하면 의존성 주입, 테스트 용이성, 유연한 아키텍처, 다형성 등의 이점을 얻을 수 있다. 이는 코드의 결합도를 낮추고 유지보수성을 높여, 더 견고하고 확장 가능한 애플리케이션을 개발할 수 있게 한다.
'프로그래밍 언어 > JAVA' 카테고리의 다른 글
예외 처리 (0) | 2024.02.05 |
---|---|
Static / Non-Static method (0) | 2024.01.29 |
Enum - 1 (feat. final) (0) | 2023.11.08 |
Stream (0) | 2023.11.04 |
Optional (0) | 2023.08.23 |