핑계라면 핑계겠지만,
개발 일정에 쫓겨가며 부랴부랴 개발을 하고 있던 시절이 있었다.
최대한 노력하며 보기 좋고 깔끔한 코드를 짜고자 했지만, 일이 터지고 말았다.
로컬에서 개발과 테스트를 마친 후, 개발서버에 배포를 했는데 프론트앤드 개발자분에게 바로 메신저가 왔다.
'API 응답이 안오는데요? 제품 로그인이 안되네요.'
나는 로그인쪽을 수정하지 않았기에 내가 원인이 아닐 거라는 생각만 가지고 원인 파악을 들어갔다.
(대체 누구야 라는 건방진 생각도 했다지)
로그를 까고 보니 서버는 기동조차 하지 못하고 기동중에 죽어버렸던 것이다.
마지막 서버 로그를 확인해보니
StackOverFlowError 무한참조... 어쩌고... 로그를 내면서 내가 구성한 서비스들끼리에 순환 참조 관계를
그림으로 나타내주었는데,
순환 참조가 뱅글뱅글 돌면서 양방향 의존을 하고 있었다.
(캡처 이미지가 없는 게 아쉽네)
양방향 의존 관계가 왜 나쁜데?
양방향 의존관계는 그 단어에서도 유추가 가능하듯 양쪽이 서로를 의존하고 있다는 것이다.
그 말은 즉 한쪽이 변경되면 다른 쪽도 변경되어야 하고,
그 다른 쪽이 변경되면 이 한쪽도 영향을 받게 되는 것이다.
양방향 의존성은 성능 이슈를 만들고, 양쪽 객체의 싱크를 맞추기 위한 노력이 필요하게 되고
메서드 순환 호출을 야기할 수 있는 안 좋은 구조이다.
그렇다면 어떻게 수정해야 할까
방법은 크게 두 가지가 있다.
1. 애초에 잘못된 구조니 구조부터 다시 짜자
나는 이 방식을 택했다.
서비스별 구성과 기능 분리를 잘했더라면 양방향 의존을 할 일이 있었을까?
내가 발생시켰던 양방향 참조 관계는
사용자 계정을 관리하는 '사용자 서비스'에서
해당 사용자가 계약을 맺은 계약 정보를 얻어오기 위해 '계약 서비스'와 의존을 맺었고,
'계약 서비스'에서는 해당 계약 정보에 속해있는 주 계정과 부 계정을 얻어오기 위해
계약 그룹과 계약그룹 내 사용자별로 '사용자 서비스'에 의존을 맺었다.
이 말은 동일한 기능을 기준점에 따라서 양쪽 클래스에 모두 구현을 하여 사용하게 되었던 것이다.
결국 나는 이 부분의 테이블 스키마부터 다시 구성하고
양방향 참조 관계를 맺지 않게 패키지와 서비스 구성을 다시 하여 양방향 참조 관계를 없앴다.
2. 어쩔 수 없다. 양방향 주입을 인정하자
나는 이 부분에 개발이 많이 진행되지 않아서 다시 처음부터 구성하였지만,
개발이 너무 많이 진행됐거나 일정이 부족하여 임시로라도 해결을 해줘야 할 땐
양방향 참조를 허용? 하는 방식으로 변경해야 할 것이다.
의존성을 주입하는 방법은 3가지가 있다.
- 생성자 주입 (Constructor Injection)
- 필드 주입 (Field Injection)
- 수정자 주입 (Setter Injection)
이중에 Spring에서 사용을 권장하는 방식은 1번의 방식인데,
그 이유는
순환 참조를 방지할 수 있기 때문이다.
이 내용이 오늘 포스팅의 주된 원인이 아닐까 싶다.
개발을 하다 보면 어쩔 수 없이 의존성이 생기면서 양방향으로 의존을 하게 되는 경우가 생길 수 있다.
생성자 주입을 사용하면 컴파일 시점에서 양방향 의존관계를 파악할 수 있기 때문에
순환 참조를 방지할 수 있게 되는 것이다.
실수는 한 번으로 족하다.
하지만 내 블로그 내용처럼
실수했어도, 틀렸어도, 실패했어도 그 과정에서 배운다면 된 거다!
이번 일도 실수를 한번 했기 때문에 배우고 다시 동일한 실수를 저지르지 않기 위한 경험이었다고 생각한다.
하지만 똑같은 실수를 공부하지 않고 넘어가서 또 저지르게 된다면
그건 정말 개발자로서 성장이 정체되었다고 생각한다.

오늘의 실수도 열심히 공부하고 똑같은 실수를 반복하지 말자!
'Programing > Spring' 카테고리의 다른 글
WAS (Spring Boot) - DB 성능 개선과 최적화 (4) - RedisTemplate (0) | 2022.06.02 |
---|---|
WAS (Spring Boot) - DB 성능 개선과 최적화 (3) - RestClient (0) | 2022.06.02 |
Rest 통신 기반의 CRUD Transaction 처리 해보기 (AOP, Generic) (3) | 2022.05.23 |
WAS (Spring Boot) - DB 성능 개선과 최적화 (2) - RestTemplate (0) | 2022.05.14 |
WAS (Spring Boot) - DB 성능 개선과 최적화 (1) - JDBC (0) | 2022.05.14 |