Solving Circular Dependencies: @Lazy Is Just a Workaround
Problem
While building the Gift API at Kakao Tech Campus, I ran into a circular dependency.
1
2
ProductService → OptionService
OptionService → ProductService
When creating an option, I needed to check if the product exists—so OptionService referenced ProductService. But ProductService also referenced OptionService for option-related logic.
When I started the app, a circular reference error popped up.
Temporary Fix: @Lazy
I slapped on the @Lazy annotation to get it working.
1
2
3
4
public OptionService(OptionRepository optionRepository, @Lazy ProductService productService) {
this.optionRepository = optionRepository;
this.productService = productService;
}
@Lazy delays bean creation until it’s actually used, dodging the circular reference error.
Mentor Feedback
But then my mentor gave me this:
“A circular reference is a sign that two classes are too tightly coupled. @Lazy can hide the error temporarily, but you should fix the design.”
Fundamental Solution
Methods my mentor suggested:
1. Check if they really need to depend on each other
- Looking at the logic again, some of it didn’t need to go through a service
- Some parts could be resolved by injecting the Repository directly
2. Make it unidirectional
- See if bidirectional dependency can become unidirectional
- Rearrange logic so one service doesn’t need the other
3. Introduce a Facade service
- Create a higher-level service that coordinates both
- Something like
ProductOptionFacadethat combines the two
Lessons Learned
@Lazyhides the problem—it doesn’t solve it- Circular dependencies are a design smell
- Direction of dependencies matters a lot in OOP
- Fixing structure now saves headaches later
From Kakao Tech Campus 3rd cohort Gift API clone coding, summarizing mentor feedback.
