2025-08-27-TIL
Today I Learned
오늘은 멘토링이 있는 날이다. 이전 시간에 ACID에 대해서 깊이있는 이야기를 했는데, 관련 내용이 ‘데이터 중심 애플리케이션’의 07장 트랜잭션에 나와있다. 이 책에서 말하는 설명을 잘 읽어보면 ACID 속성의 하나하나가 더 와닿는다. 이 네 가지 속성에 대해서는 다시 한 번 정리해봐야겠다. 그리고 MongoDB 등 NoSQL에서도 지원하는데, 어떻게 지원 가능한지 구현기술을 학습해보려고 한다.
2025-08-27-Mentoring
팩토리란?
“팩토리(Factory)”라는 말은 단순히 “객체를 만들어주는 곳”이라는 뜻이다. 즉, 프로그래밍에서 new를 직접 쓰지 않고, 객체 생성을 전담하는 클래스나 메서드를 가리킨다.
현실의 공장(factory)처럼 → 재료를 넣으면 완제품이 나오는 구조이다. 개발에서 factory는 → 파라미터(조건)를 넘기면 → 적절한 객체(인스턴스)를 생성해 반환한다.
팩토리의 종류는 세 가지가 있다.
단순 팩토리(Simple Factory)
- 정적 메서드 등을 이용해 조건에 맞는 객체를 생성한다.
- 디자인 패턴 책(GOF)에는 포함되지 않지만, 실무에서 자주 쓰인다.
1
2
3
4
5
6
7
8
9
class ShapeFactory {
public static Shape getShape(String type) {
switch (type) {
case "circle": return new Circle();
case "square": return new Square();
default: throw new IllegalArgumentException("Unknown type");
}
}
}
팩토리 메서드 패턴(Factory Method Pattern)
- 객체 생성을 서브클래스에게 위임하는 구조.
createSomething()
같은 메서드를 추상화하고, 서브클래스가 실제 객체를 리턴.
추상 팩토리 패턴(Abstract Factory Pattern)
- 관련된 객체들의 “제품군”을 생성하는 인터페이스를 제공.
- 예:
GUIFactory
→createButton()
,createCheckbox()
등.
팩토리는 객체 생성 로직이 복잡하거나, 자주 변경될 가능성이 있을 때 유용하다. 클라이언트 코드가 구체 클래스(new
)에 의존하지 않게 만들고 싶을 때에도 적용이 가능하다. 이는 SOLID 원칙 중에서 “확장에는 열려 있고, 수정에는 닫혀 있어야 한다”(OCP 원칙)를 지킬 때 사용된다.
팩토리(Factory)는 객체 생성을 대신해주는 “공장 역할”을 하는 클래스나 메서드이다. 결국 new
를 직접 쓰는 대신, 객체 생성 책임을 한곳에 모아두는 것이다.
IoC란?
스프링에서 IoC(Inversion of Control, 제어의 역전)란 객체의 생성과 의존성 관리를 개발자가 직접 하는 대신, 스프링 컨테이너(프레임워크)가 대신 관리해주는 개념을 말한다.
IoC를 잘 구현한 곳은?
IoC를 잘 구현한다는 의미는 무엇일까?
- 인터페이스에 의존하고, 구현 선택은 구성으로 분리한다.
- 생성자 주입을 기본으로(필드 주입은 피함).
- 인프라/환경 의존(데이터소스, 메시징, 캐시 등)은 컨테이너가 관리하고 필요하면 @Qualifier / @Primary로 선택.
- 클라이언트 코드(비즈니스 로직)는 주요 책임에 집중하고, 생성/선택 책임은 외부(IoC 컨테이너)에 위임.
- 이 구조 덕분에 확장 용이(OCP), 재사용/테스트 용이, 관심사 분리가 자연스럽게 달성됨.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@Component
@RequiredArgsConstructor
public class PopularCountingInterceptor implements HandlerInterceptor {
private final PopularCounterPort counter;
@Override
public void afterCompletion(@NotNull HttpServletRequest req, @NotNull HttpServletResponse res, @NotNull Object handler, Exception ex) {
if (!(handler instanceof HandlerMethod)) return;
if (res.getStatus() < 200 || res.getStatus() >= 300) return;
String uri = req.getRequestURI();
String ticker = extractTickerFromUri(uri);
if (ticker == null) return;
Instant now = Instant.now();
counter.increment(ticker, PopularWindow.M15, now);
counter.increment(ticker, PopularWindow.H1, now);
counter.increment(ticker, PopularWindow.D1, now);
counter.increment(ticker, PopularWindow.D7, now);
}
}
멘토님은 프로젝트에서 PopularCountingInterceptor를 활용한 부분이 IoC를 잘 활용한 예시라고 설명해주셨다. 이 인터셉터는 시세 및 차트 조회 API의 데이터를 카운팅하도록 스프링 프레임워크에 위임한다.
스프링 컨테이너가 관리하는 @Component
빈이고, @RequiredArgsConstructor
로 생성자 주입(불변성 보장) + 포트 인터페이스(PopularCounterPort
)에 의존 → 구체 구현과 분리된 느슨한 결합(OCP 실천)이다.