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

[Refactoring] 22.08.10. 매장 정보 관리 페이지 (미완)

by 규글 2022. 8. 10.

매장 정보 관리 페이지

구성

1. 매장 정보 관리

  • 매장의 기본 정보뿐만 아니라 메뉴, 리뷰, 주문, 자리에 대한 정보까지 관리할 수 있다.

2. 대표 이미지 변경

  • 매장을 대표할 수 있는 이미지를 변경할 수 있다. 클릭하면 이미지를 선택하고, 업로드할 수 있도록 만들어두었다. 해당 이미지는 매장 검색 시, 썸네일로 보이게 되며, 매장의 상세 정보를 확인할 때, 상호명 왼쪽에 작은 이미지로 보이게 된다.

3. 부가 이미지 변경

  • 매장에 대해 조금 더 보일 수 있도록 4개의 이미지를 설정할 수 있도록 했다. 이미지들은 매장의 상세 정보를 확인할 때 확인할 수 있다.

4. 매장 정보 변경

  • 매장에 대한 정보를 변경할 수 있다.
  • 테스트 중에 특수문자를 사용해봤는데, 해당 내용에 대해서는 오류를 내고 있었다. 이에 대한 수정도 이루어져야 할 것 같다.

5. 태그 정보

  • 검색 노출에 도움을 줄 수 있는 태그 정보를 입력하고 수정할 수 있다.

6. 매장 열기 / 닫기

  • 관리하고 있는 매장이 검색에 노출될 수 있도록 열고 닫을 수 있는 기능을 넣었다.

7. 매장 정보 삭제

  • 매장 정보를 삭제할 수 있다.

 

코드 뜯어보기

StoreController.java

  • myStore

 매장 정보 관리 페이지 요청에 대한 controller의 method이다. 별 문제 없어보이지만 문제가 있다. Service logic으로 들어가보면 Request parameter를 받았음에도 사용하지 않고 있는데, 애초에 request scope에서 가져올 수 있는 내용이기때문에 중복되므로 지워주었다.

 

 Dto 객체를 이용할 것이었다면 애초부터 number에 대한 값을 Dto 객체로 받았어도 좋았을 것 같다. Dto로 data를 받게 되면 따로 Dto 객체를 생성해서 'num' data를 넣어주지 않고 단순히 email 정보만 넣어서 DB를 조회할 수 있게 되고, 따로 request scope로 받은 num data를 조회하지 않아도 된다. 그리고 단순히 list라고 적힌 parameter를 tagList 라는 이름으로 바꾸어주었으며, 마지막에 굳이 넘겨주지 않아도 되었을 'num' 라인을 지워주었다.

 

  • addTag / deleteTag

 매장에 대한 tag 추가 요청에 대한 controller의 method이다. 역시나 Map 객체를 만들고 값을 put 하는 과정을 service 단으로 넘기고 싶다.

 

 사실 'easter egg' 라는 친구는 null pointer exception 때문에 project 기간 당시에 넣었던 기억이 난다. 여러 단계를 거치던 중, 처음 DB에 매장 정보가 생성될 때, front 단에 등장하지 않는 tag 정보를 하나 넣어주는 것으로 오류를 잡으려는 것으로 마무리했던 것 같다. 그래서 tag 관련 if문을 지워주었다.

 개발때부터 계속 걸리던 부분 중에 하나가 service의 getMyStore_num method 이다. Email과 번호로 DB의 매장 정보를 불러오는 method와, email이 없이 번호만을 이용해서 DB의 매장 정보를 불러오는 method로 나눈 것이다. 여기에서는 구조 상 email 정보를 필요로 하는 method가 되는 것이 맞다고 생각해서 Request 객체를 추가로 전달해서 email 정보를 받은 후, 다른 Dao method를 사용하는 것으로 바꿔주었다. 그리고 DB query 문 성공 여부에 따라 response를 달리할 수 있도록 Map 객체를 controller에서 service로 들여오면서 바꿔주었다.

 deleteTag method 도 동일하게 바꿔주었다.

 

  • storeUpdate

 매장에 대한 tag를 삭제하는 controller의 method 이다. 마찬가지로 Map 객체를 service 단에서 다루고 싶다.

 

 Map 을 service 단에서 처리하는 것은 어려운 일이 아니지만, 의외로 메뉴에 대한 내용을 update 하는 dao method가 있어서 당황했다. 이또한 DB 설계에서의 문제였다. DB의 메뉴 table을 확인해보면 매장의 이름에 대한 column이 존재한다. 당시 필자가 SQL문을 잘 작성하지 못해서 대안으로 DB을 변경하면서까지 오류 없는 기능 수행에만 집중했었는데, 이런 중복은 피하는 것이 좋을 것 같다. 필자가 잘못한 것이다. 일단 query 문으로 인한 update 문이 수행되었는지의 여부에 따라 다른 response를 위해 Map 객체를 service 단으로 가져와서 분기했다.

 

  • uploadImage

 매장에 대해 간단히 보일 수 있는 로고 및 기타 이미지를 올릴 수 있는 controller의 method 이다. 여기에서 또한 Map 객체를 service 단에서 다루고 싶다.

 

 이미지를 upload 하는 logic은 마이 페이지에서 프로필 이미지를 업로드하는 것과 동일하다. 오히려 여기에서 눈길을 끄는 것은 if 문으로 어떤 이미지에 해당하는 것인지 분기해놓은 부분이다. 보면 모두 동일하게 check라는 값을 전달받아 경우의 수를 나눴는데, front 단에서는 해당 name으로 된 값을 check 로 전달하고 있었다. 그리고 해당 내용을 DB의 query 문에서도 경우의 수를 분리해두었다. Logic 자체를 그냥 둔다고 해도 DB에는 imageCheck 라는 column은 사실 필요가 없고, 해당 column에 data를 넣는 과정도 필요가 없다. 그래서 해당 dao method 자체를 지워버렸다. 저런 식으로 분기를 하지 않고 바로 알아서 찾아서 upload 하는 방식은 없을까 하고 고민했는데, 알아서 method를 골라갈 수는 없을 것 같다.

 

 이 과정에서 test 중에 썸네일 이미지가 정상적으로 보이지 않는 모습을 확인했다. 이는 해당 element에 들어갈 이미지의 정보가 존재하지 않을 때, 기본 이미지를 출력하도록 경우의 수를 나누면서 id 정보를 입력해주지 않았기 때문이다. 기본 이미지가 들어가도록 하는 것은 필자가 아닌 팀원이 작성한 부분인데, 필자가 조금만 더 신경썼다면 누락되지 않았텐데 아쉬운 부분이다. id를 부여해주어서 이미지가 정상적으로 보이는 것을 확인했다.

 

 마이페이지에서 프로필 이미지를 upload 하는 것과는 다른 logic이다. 필자는 이미지를 보이게 하는 것과 동시에 upload가 수행되는 것이 마음에 들지 않았다. 그래서 따로 썸네일을 바로 보이게 할 수 있는 logic을 검색해서 찾아 적용했다. 이미지를 선택해서 해당 element에 change가 발생하면 이미지를 읽어올 수 있도록 한 것이다. Change가 발생한, 즉 event가 발생한 target에 files 에는 해당 file에 대한 정보가 담겨있다. 그래서 file을 FileReader 객체로 읽어서 이미지가 load 되었을 때, 이미지를 보일 element의 src에 이미지의 정보가 담긴 target의 result 정보를 넣어준 것이다.

 

  • storeOnOff

 검색 시 매장 정보가 노출될 수 있게 해주는 controller의 method이다. 역시 Map 객체를 service 단에서 다루도록 변경할 것이다.

 특별한 logic은 없고 그저 dao method 만이 전부이다. 해당 dao method가 정상적으로 수행되었는지에 대한 여부에 따라 Map 객체에 다르게 return 해서 front 단에서 서로 다른 response를 보일 수 있도록 했다.

 

  • deleteStore

 매장 정보를 삭제하는 controller 의 method이다. 역시 Map 객체를 service 단에서 다루고 싶다.

 

 사실 이 부분은 마이 페이지에서 회원 탈퇴하는 UsersController의 method를 확인할 때 다루었다. 하지만 이후에 test를 거치는 과정에서 매장 삭제 과정에서 오류가 발생했다. 오류란, 매장과 관련된 data는 정상적으로 삭제되었지만, 매장 자체의 data는 삭제되지 않는다는 점이었다. 게다가 하나의 매장 정보만 지우고 싶었는데, 모든 매장에 대한 정보를 지우고 있었다. deleteStore 를 요청했을 때 해당 email 로 된 모든 매장 정보를 불러와서 지우기 때문인데, UsersController 단에서의 반복문 logic을 service 안쪽으로 들여오면서 문제가 발생한 것이다. 때문에 하나의 정보만을 지우고 싶을 때를 함께 고려해서 logic을 수정해야 한다.

 deleteStore service logic을 요청하는 곳은 두 군데이다. 마이 페이지에서 회원 탈퇴 요청을 할 때, 그리고 매장 관리 페이지에서 매장 삭제를 할 때이다. 두 요청의 차이는 마이 페이지에서의 요청에는 매장 number data 가 존재하지 않는다는 점이다. 요청에 number data가 없으면 0으로 받게 되는데, 이를 이용해서 if문으로 분기할 수 있을 것이다.

 

 우선 이전 마이 페이지에서 회원 탈퇴를 하는 controller의 logic에서 StoreDto를 받는 이유가 삭제할 매장의 number data를 Dto 객체를 통해 받기 위해서였다. 여기까지 확인하지 못하고 지웠던 내용이 이곳[각주:1] 에 적혀있다. 다시 StoreDto 객체를 전달받도록 고쳐주었다.

 

 이를 이용해서 if 문으로 경우의 수를 나누고 생각해보니, 회원 정보를 삭제하는 service logic은 UserService, StoreService의 두 service logic을 순차로 수행하는 것이 아니라 하나의 logic으로 합쳐야 한다는 생각이 들었다. 서로가 독립된 logic이 아니라 하나의 흐름이 되어야 한다는 것이다.

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

 

 일단 이에 대한 문제를 해결하기에 앞서 검색 중 큰 문제를 발견했기에, 일단은 number data에 대한 존재 여부로 if문을 통해 분기하는 것으로 잠시 마무리했다.

 

 

  • Test 과정에서 로그인 문제

 

댓글