본문 바로가기
프로젝트/자리 있어요?

[Refactoring] 22.08.15. 매장 정보 관리 페이지 (이어서)

by 규글 2022. 8. 15.

매장 정보 관리 페이지

 이전 매장 정보 관리 페이지[각주:1] 에서 이어서 작업하려고 한다. 살펴보고 싶은 내용은 매장에 대한 tag 관련 logic과 매장 정보를 삭제하는 logic에 대한 것이다.

 

 

코드 뜯어보기

StoreController.java

Tag Logic

  • myStore

 지난 게시글에서 Http 의존성을 제거해준 controller의 myStore method는 매장 관리 페이지로 넘어가는 요청에 대한 처리를 해준다. 해당 과정에서는 tag를 화면에 출력하기 위한 logic이 있는데 이에 대해 살펴보고자 한다.

 Tag 정보를 저장할 때, List 그대로를 DB에 저장할 수 없었다. 그래서 tag 관련 List를 string 으로 바꿔서 DB에 저장하는 방식을 채택했었다. DB로부터 data를 받아올 때는 DB의 String을 String array로 받아 그것을 다시 List 객체로 바꾸는 logic을 사용했다.

 첫 번째 생각은 추가하는 logic에서 굳이 String array를 List로 바꿔주어야 하는가, 두 번째 생각은 당시 tag 정보에 아무 내용이 없어 발생하는 오류를 피하기 위해 dummy data를 insert 해주고 초항이 아닌 두 번째 항부터 출력하도록 한 부분에서 dummy data를 없앨 수 있는가의 여부이다.

 

 우선 굳이 List로 변환하지 않고 단순히 String array를 전달해도 정상적으로 front에서 tag 정보를 출력하는 것을 확인할 수 있었다. 즉, List로 변환하는 logic은 불필요한 logic이라고 할 수 있으므로 지워주었다. 하지만 tag 정보에 아무것도 전달되지 않는다면 오류가 발생하기때문에 DB에서 받아온 Dto에 아무런 내용이 없을 때 null 이 아닌 빈 String array를 전달할 수 있도록 해주었다.

 

  • addTag / deleteTag

 myStore의 logic을 저렇게 바꿔주고 나면 service의 add tag logic에서 문제가 발생한다. 문제는 tag에 아무런 정보가 없을 때 발생한다. DB에서 아무런 정보를 받아오지 못하면, null 값에 method를 사용하는 것이 되어버리기때문에 NullPointerException이 발생하는 것이다. 이 null 로 인한 문제를 해결해주면서 List로 바꾸지 않을 수 있는 방법이 있을까?

 사실 List를 쓴 이유는 String array는 그 크기가 만들 때 고정되기 때문이다. 하지만 지금 돌이켜보면 생각이 짧았던 것 같다. String array가 선언시에 크기가 고정되는 것이라면 너무 형태 그대로에 집착하지 않고, 약간의 편법을 통하면 for문을 사용하지 않고 List를 사용하지 않아도 되었을 것이다.

 우선 DB에서 받을 내용을 null 이 아닌 아무것도 없는 상태로 초기화했다. 만약 DB에서 받아온 tag 정보가 null이 아니면 해당 data에 ",empty" 를 붙여서 String array로 바꿀 때 눈속임을 할 수 있도록 한다. 그 눈속임을 한 자리에 해당하는 index에 새로운 tag data를 넣어서 다시금 String으로 전환한 후에 DB에 data를 update 하는 방식으로 바꾸었다.

 

 갑자기 생각나서 StringBuilder 라는 친구를 사용해보았다. 하지만 뭔가 String 에서의 이득이라는 생각이 들지는 않는다. 만들어지는 String 객체의 수가 같다고 생각한다. 처음 StringBuilder에서 1개의 개수를 줄였으나 StringBuilder를 다시 String으로 만드는데에 1개가 늘어서 결국 같은 것이 아닐까? 이에 대해서 자세하게 알지는 못한다.

 

 사실 그렇게 사용하면 안되지만, 태그를 중복되게 입력할 수도 있다. 그럴 경우 중복된 내용을 하나 지우려고 하는데, 원하는 위치에 있는 tag가 지워지는 것이 아닐 수도 있긴 하다. List를 쓰지않고 String array만을 사용하는 logic은 현 상태보다 더 복잡해지는 것 같아서 이것은 그냥 두기로 했다.

 

 

 

 

 

 

 

 

 

 

 

 

매장 정보 삭제 Logic

 다시 매장 정보 삭제하는 method로 돌아왔다. 지금은 넘겨받은 StoreDto 객체에 number data가 있으면 그 번호에 해당하는 매장 관련 data를 지우는 것이고, 없으면 해당 계정이 관리하고 있는 모든 매장 data를 지우는 logic이다.

 

 Refatoring을 시작하기 전에는 회원 탈퇴 시, 해당 계정이 관리하는 모든 매장의 data를 service가 아닌 controller 단에서 매장 번호들에 대해 각각 service method를 호출하여 삭제했었다. 하지만 이 과정을 service 단으로 들여오면서 계정이 관리하는 매장 전체의 data를 List로 받아 for 문을 수행하는지가 다르고, 안쪽의 logic은 동일하다. 과연 이것이 최선일까에 대해 고민해보려고 한다.

 

그럼 하나의 service logic으로 만들어야 할까? 
또한 한 쪽 Service에서 다른 Service 객체를 주입받아서 사용해도 될까? 
첫 번째 질문에 대한 내용은 이후 Transaction(트랜잭션) 처리를 위해서도 하나로 합쳐주는 것이 좋다고 생각한다. 
두 번째 질문에 대한 내용은 서로 다른 Service 객체 사이에 의존성이 존재해도 되는가에 대한 여부를 고려해야할 것 같다.

 당시 고민했던 내용이다. 현재 UsersController의 delete method 에는 두 service logic이 있다. 과연 이 logic들을 하나로 만들어야 할까? 역시 transaction 이 하나의 service logic을 기준으로 동작하는 것이므로, service logic을 여러 개 호출하는 방식이면 마지막 logic에서 문제가 발생했어도 이전 Dao method는 정상적으로 수행된 것이므로 옳게 된 동작이 아니게 된 것이다. 따라서 하나로 합쳐주는 것이 좋을 것 같다. 그리고 service에서 다른 service에 의존성을 갖게하는 것은 역시 좋지 않은 방향성인 것 같다.

 다시 이전 내용들을 확인해보면 UsersController에서는 이 회원 정보를 삭제하는 delete method 이외에도 마이 페이지로 이동하는 info method에서, StoreController에서는 검색 메인 페이지로 이동하는 main method와 매장 상세 정보 페이지로 이동하는 goStoreDetail method에서 여러 개의 service logic을 사용하고 있다. 이번 게시글에서는 매장을 삭제하는 logic만 수정하고 나머지 내용들을 다음 게시글에서 수정해야겠다.

 

 우선 매장을 삭제하는 logic으로 돌아오면 결국 하나의 service logic으로 통일해야한다는 것이다. 그래서 StoreService의 delete method에 분기해놓은 내용을 UsersSerivice의 deleteUser method로 옮기고, UsersController에서는 StoreService의 deleteStore method를 호출하지 않도록 수정했다. 

 

 처음에는 하나의 method로 만들어서 비슷한 logic을 반복하지 않기 위해 코딩한 방식이었는데, refactoring을 하면서 그 방식이 좋지 않았음을 깨닫고 있다. 하지만 기존에 회원 정보를 삭제하는 dao method를 수행하면서, 수행 여부에 따라 결과를 분기한 부분에서 문제가 발생할 수 있을 것 같다. 예를 들어 회원이 관리하는 모든 매장 정보들을 삭제하였으나 회원의 정보를 삭제하는 과정이 수행되었으나 제대로 지워지지 않을 경우(그럴 경우는 사실 없을 것 같지만), 매장 정보는 지워지고 회원 정보는 지워지지 않을 수도 있지 않을까?

 

 다음 게시물은 UsersController와 StoreController에서 여러 service logic을 사용하는 나머지 부분에 대해 수정해보려고 한다.

댓글