포스트

[Java] 스트림 인덱스 출력과 객체지향적 책임 분리 (DI & SRP)

[Java] 스트림 인덱스 출력과 객체지향적 책임 분리 (DI & SRP)

“한 줄 요약: 스트림을 통한 선언적 출력 개선과 객체의 생성 및 관리 책임을 분리하여 응집도 높은 설계 구현”

1. 🔍 문제 분석 (Problem Understanding)

  • 상황: 상품 리스트 출력 시 for문과 인덱스(i)를 사용함.
  • 문제점: 문자열 더하기(+)의 반복으로 가독성이 낮고, 출력 형식이 로직에 강하게 결합되어 수정이 번거로움.
  • 핵심 질문: “어떻게 하면 출력을 깔끔하게 하고, 각 객체가 자신의 역할에만 집중하게 만들 수 있을까?”

2. 💡 해결 전략 (Approach)

  • 기술적 개선: IntStream.range()String.format()을 조합하여 인덱스 기반 출력을 선언적으로 교체.
  • 설계적 개선:
    • 외부 의존성(Scanner): 상위 계층(main)에서 생성하여 주입.
    • 내부 책임(Formatter): 해당 기능을 사용하는 클래스(CommerceSystem)가 소유.

3. 🚧 설계 고민: “이 객체를 생성할 책임은 누구에게 있는가?”

과제를 확장하며 CommerceSystem으로 로직을 옮길 때, 객체 생성 위치에 대한 중요한 설계적 선택을 내렸다.

3-1. Scanner는 왜 main에서 생성해야 하는가? (의존성 주입)

  • 이유: Scanner(System.in)는 시스템 외부(키보드)와의 연결 통로다.
  • 결론: 시스템의 진입점인 main이 입력 도구를 결정하고 CommerceSystem에 전달(DI)해야 한다. 이렇게 하면 나중에 입력 소스가 ‘파일’이나 ‘네트워크’로 바뀌어도 CommerceSystem의 코드는 수정할 필요가 없어진다.

3-2. 출력 유틸리티는 왜 CommerceSystem 내부에 두는가? (응집도)

  • 이유: 상품 정보를 어떤 포맷으로 보여줄지는 시스템의 ‘구현 상세’다.
  • 결론: 출력을 담당하는 책임은 CommerceSystem에 있으므로, 관련 유틸리티 객체도 내부에 선언하여 응집도를 높이는 것이 객체지향적 캡슐화에 부합한다.

4. ✅ 최종 코드 (Final Code)

[개선된 스트림 출력 로직]

1
2
3
4
5
6
7
8
// IntStream을 활용해 인덱스(i)와 상품 객체를 매핑하여 출력
IntStream.range(0, products.size())
    .mapToObj(i -> String.format("%d. %s | %d원 | %s", 
                i + 1, 
                products.get(i).getName(), 
                products.get(i).getPrice(), 
                products.get(i).getDescription()))
    .forEach(System.out::println);

[방법 2] AtomicInteger 활용 (필터링이 필요할 때 유용)

1
2
3
4
AtomicInteger index = new AtomicInteger(1);
products.stream()
    .map(p -> index.getAndIncrement() + ". " + p.name + " | " + p.price + "원")
    .forEach(System.out::println);

5. 📝 배운 점 (Key Takeaways)

  • 기술적 수확: IntStream.range()를 활용하면 인덱스가 필요한 반복 작업도 스트림의 이점(가독성, 유지보수성)을 누리며 처리할 수 있다.

  • 객체지향의 본질: new()를 쓰기 전에 “이 객체가 정말 이 클래스의 책임인가?” 를 고민하게 되었다.
    • 외부 의존성은 주입(Injection) 받고, 내부 상세 책임은 캡슐화(Encapsulation) 하는 것이 유연한 설계를 만드는 핵심임을 깨달았다.
  • 다짐: 앞으로 아무 생각 없이 코드를 작성하기보다, 각 클래스의 역할(Role)과 책임(Responsibility)을 먼저 정의하는 습관을 지녀야겠다.
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.