현재 맵(Map) 자료형으로 구현된 DB를 이후의 강의에서 MySQL로 변경할 예정이다. 아직 코드가 많지 않으므로 이대로 바꾸는 게 어렵지 않을 것이다. 하지만 이번 기회에 마이그레이션에 대비하여 구조를 개선해 보는 것도 좋은 경험이 될 거라 생각했다. 구체적으로는 DB 관련 로직을 한 곳으로 모으고 싶었다. 라우터와 강하게 결합되어 있는 DB 코드를 분리한다고 볼 수 있다.
현재 회원 DB를 사용하는 로직이 라우터 여기저기에 흩어져 있다.
이 회원 DB 관련 로직들을 한 곳으로 모아야 이후의 DB 마이그레이션이 쉬워질 것이다.
한 곳으로 모으는 김에 필요한 로직도 정리하면 더 좋을 것이다. 사용되는 로직을 보고 필요한 기능을 정리해보니 다음과 같다.
개별 회원 CRUD: 현재 U가 존재하지는 않지만, 필요해질 가능성이 높다.
전체 회원 조회: 리팩터링 중에 디버그용으로 있으면 좋겠다고 생각했다.
로그인
존재하는 아이디인지 확인
위 정보를 바탕으로 클래스로 구현한 회원 DB는 다음과 같다.
만들고 보니 이 클래스의 역할이 MVC 패턴에서의 모델에 가깝다는 것을 깨달았다. 이전에 Java 국비학원에서 생각 없이 찍어 내던 그 구조였다!
이제 DB 마이그레이션을 진행할 때는 이 클래스의 내부 코드만 수정하면 될 것이다. 또는 이 클래스와 같은 구조의 클래스를 만들고, 라우터에서 사용하는 클래스만 바꾸면 될 것이다.
클래스를 사용하는 라우터의 코드는 다음과 같이 바뀌었다.
로그인 로직도 바뀌었는데, 아이디와 비밀번호를 확인하는 로직과 회원 정보를 가져오는 로직을 분리했다. DB 상으로는 한 번 더 쿼리를 하므로 성능 하락이지만, 지금으로서는 이 편이 좋다고 판단했다.
개인적으로 생각한 이 리팩터링의 장점은 다음과 같다.
원래 목적대로 DB 마이그레이션이 쉬워진다.
나중에 SQL문 같은 DB 로직이 라우터에 흘러 들어올 가능성을 차단한다.
메서드 이름을 회원 엔티티(entity) 관점에서 만들 수 있다. (users.set → users.createUser)
장기적으로 비즈니스 로직을 분리하기 쉬워진다. (흔히 말하는 서비스 계층 분리)
사실 TypeScript의 인터페이스를 사용하면 더 좋을 것이다. 인터페이스에서 메서드의 형태만 정의하고 구현은 클래스에 위임할 수 있다. 라우터에서도 인터페이스에만 의존하면, DB 마이그레이션이 쉬워진다.
처음에 고안했던 방식이기도 하다. 하지만 강의에서 아직 TypeScript를 다루지 않기도 했고, 순수 JavaScript로 도전해 보는 것도 의미가 있었다고 생각한다.
현재 라우터가 채널과 회원, 두 가지가 있으며 이 리팩터링은 회원에 대해서만 적용되었다. 이후의 강의에서 실제로 DB 교체가 진행될 것이다. 마이그레이션을 진행하며, 이렇게 대비를 한 회원이 대비를 안 한 채널과 비교해서 정말 좋은지도 작성해 보겠다.