Files

3.1 KiB

interface 생성 예시

좋은 예시 1: application output port

public interface UserReader {
    Optional<User> findByEmail(UserEmail email);
    Optional<User> findById(UserId userId);
}

@Repository
public class JpaUserReader implements UserReader {
    ...
}

왜 좋은가:

  • application이 persistence 구현을 모른다
  • 바깥 구현 교체와 테스트 대역 주입이 쉽다
  • 레이어 경계가 분명하다

좋은 예시 2: 외부 시스템 client contract

public interface VaultTransitClient {
    String sign(String keyName, byte[] input);
    PublicKey readPublicKey(String keyName);
}

왜 좋은가:

  • 외부 연동 경계가 분명하다
  • HttpClient/WebClient/Jackson 세부가 계약에 새지 않는다
  • fake/stub 구현으로 테스트하기 쉽다

좋은 예시 3: 교체 가능한 정책 객체

public interface PasswordHasher {
    String hash(String rawPassword);
    boolean matches(String rawPassword, String encodedPassword);
}

왜 좋은가:

  • 알고리즘 교체 가능성이 실제로 있다
  • application/domain이 구체 해시 구현을 모른다

좋은 예시 4: 인터페이스 없이 concrete class 유지

@Component
public class LoginResponseAssembler {
    public LoginResponse toResponse(User user, TokenPair tokenPair) {
        ...
    }
}

왜 좋은가:

  • 내부 presentation helper일 뿐 계약 경계가 아니다
  • 구현체 1개, 교체 가치 낮음, 인터페이스 이득 작음
  • 불필요한 LoginResponseAssemblerImpl을 만들지 않는다

나쁜 예시 1: 의미 없는 Service/Impl 쌍

public interface UserService {
    User create(CreateUserCommand command);
}

@Service
public class UserServiceImpl implements UserService {
    ...
}

문제:

  • 실제 경계/교체/테스트 seam 의미가 약하다
  • 타입만 늘고 추상화 이득이 거의 없다
  • “관성적인 인터페이스”에 가깝다

나쁜 예시 2: 기술 세부를 계약에 노출

public interface UserClient {
    ResponseEntity<String> getUser(String id);
}

문제:

  • Spring Web 타입이 계약에 박힌다
  • 호출자가 구현 기술에 묶인다

개선:

  • 도메인/애플리케이션에 더 맞는 결과 타입으로 계약 정의

나쁜 예시 3: 여러 책임을 한 인터페이스에 몰아넣기

public interface UserManager {
    User findUser(...);
    User saveUser(...);
    void sendEmail(...);
    String issueToken(...);
}

문제:

  • 하나의 역할이 아니다
  • 호출자마다 일부만 필요할 가능성이 높다
  • 응집도가 낮다

나쁜 예시 4: 조기 추상화

public interface DeadlineService {
    void setDeadline(...);
}

public class TaskDeadlineService implements DeadlineService { ... }

public class PaymentDeadlineService implements DeadlineService { ... }

문제:

  • 지금은 비슷해 보여도 미래에 다르게 진화할 수 있다
  • 아직 공통 계약이 자연스러운지 검증되지 않았다

개선 방향:

  • 충분한 공통성/경계 필요가 생길 때까지 분리된 concrete class 유지