UserService가 UserRepository의 구체적인 구현체(JdbcUserRepository)를 직접 생성 UserService 내부 코드를 직접 수정해야 함 @Service
public class UserService {
private final UserRepository userRepository = new JdbcUserRepository(); // 직접 객체 생성
public User getUser(Long id) {
return userRepository.findUserById(id);
}
}
유지보수성 저하
UserRepository의 다른 구현체(MongoUserRepository)를 사용하려면 직접 수정해야 함 private final UserRepository userRepository = new MongoUserRepository(); // 직접 변경 필요
확장성 저하
UserService는 UserRepository 인터페이스만 알고 있으며, 구체적인 구현체는 외부에서 주입 public interface UserRepository {
User findUserById(Long id);
}
@Repository
public class JdbcUserRepository implements UserRepository {
@Override
public User findUserById(Long id) {
// JDBC를 사용한 데이터 조회 로직
return new User(id, "JDBC_User");
}
}
@Repository
public class MongoUserRepository implements UserRepository {
@Override
public User findUserById(Long id) {
// MongoDB를 사용한 데이터 조회 로직
return new User(id, "Mongo_User");
}
}
UserService 구현@Service
public class UserService {
private final UserRepository userRepository;
@Autowired // 생성자 주입
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
public User getUser(Long id) {
return userRepository.findUserById(id);
}
}
UserService 내부 코드를 변경할 필요 없이 외부에서 원하는 구현체를 주입 가능 UserRepository의 변경이 필요해도 UserService 수정 없이 변경 가능 // JdbcUserRepository 주입
UserRepository userRepository = new JdbcUserRepository();
UserService userService = new UserService(userRepository);
MongoUserRepository, JdbcUserRepository 같은 새로운 구현체가 추가되더라도 기존 코드 수정 없이 사용 가능 // MongoUserRepository 주입
UserRepository userRepository = new MongoUserRepository();
UserService userService = new UserService(userRepository);
@Service, @Repository와 함께 사용하면 자동으로 구현체가 주입됨 @Configuration
public class AppConfig {
@Bean
public UserRepository userRepository() {
return new JdbcUserRepository(); // 원하는 구현체로 변경 가능
}
}
Spring에서는 @Autowired를 사용하면 자동으로 적절한 구현체가 주입됨
@Service
public class UserService {
private final UserRepository userRepository;
@Autowired
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
}
@ComponentScan에 의해 @Repository가 자동 등록됨 @Autowired가 있는 생성자를 보고 Spring이 적절한 구현체를 자동으로 주입 | DI 미적용 (직접 생성) | DI 적용 (의존성 주입) | |
|---|---|---|
| 유지보수성 | 구현체 변경 시 UserService 코드 수정 필요 | 구현체 변경 시 UserService 수정 불필요 |
| 확장성 | 새로운 구현체 추가 시 기존 코드 수정 필요 | 새로운 구현체 추가해도 기존 코드 유지 |
| 결합도 | 강한 결합 (High Coupling) | 느슨한 결합 (Low Coupling) |
| OCP (개방-폐쇄 원칙) | 기능 확장 시 기존 코드 수정 필요 | 기존 코드 수정 없이 확장 가능 |
| 테스트 용이성 | 실제 구현체를 사용해야 함 (Mocking 어려움) | Mock 객체를 주입하여 테스트 가능 |
💡 즉, DI를 사용하면 변경에 유연하고 확장성이 뛰어난 코드가 만들어짐! 🚀