Folder 구조에 대한 생각 변화

CURE·2023년 8월 28일

개발

목록 보기
1/13
post-thumbnail

[ 기존 상황 ]

기존 회사 코드의 폴더 구조는 Table별로 이루어져 있으며
Layer 층으로 이루어져 있는데

user
ㄴ userService
ㄴ userRouter
ㄴ userRepository
ㄴ userEntity

다음과 같았다

우선
userRouter - URL 을 담당
userEntity - Table 정의
userRepository - Table 연결
userService - service 로직

호출 순서는

userRouter 
	-> userService ( service logic )
    	-> userRepository ( exports )
    		-> userEntity ( Table 정의 )

하지만 해당 부분에서의 불편함은 매우 존재했다

  • 코드의 재사용이 되질 않는 다는 점
  • requsest, response를 컨트롤 하는 부분이 없다
  • 도메인 로직과 서비스 로직의 혼용으로 유지 보수가 힘들다는 점

따라서 Controller 를 추가함으로써 이를 해결하려 하였다

user
ㄴ userRouter.js
ㄴ userController.js
ㄴ userService.js
ㄴ userRepository.js
ㄴ userEntity.js
userRouter 
	-> userContorller ( req. res. next 처리 )
		-> userService ( service logic )
    		-> userRepository ( exports )
    			-> userEntity ( Table 정의 )

해당 구조의 장점으로는

  • request, response 를 따로 분리함으로써 service 마다 테스트 코드를 작성할 수 있다

  • serivce 함수를 다른 controller 에서 호출할 수 있으므로 코드 재사용성이 올라간다

떠라서 한동안 매우 기분 좋은 하루를 보냈지만 끝내 다른 단점들이 올라오기 시작한다

[단점]

  • service 로직이 점점 커질 경우 재사용이 안되고 하나의 거대한 로직이 되므로 분리한 의미가 없어진다
  • table 하나만 건드는 로직과 여러 table 을 동시에 건드는 함수인 경우 어느 폴더에 있어야 하는지 매우 애매하다는 점

처음엔 그저 folder 구조자체가 큰 폴더로 묶이는 경우 있었기 때문에

user 
ㄴ user
	ㄴ userRouter.js
    ㄴ userController.js
    ㄴ userService.js -> 큰 로직은 해당 파일 에서 처리
    ㄴ userRepository.js
    ㄴ userEntity.js
ㄴ userAccount
	ㄴ userAccountRouter.js
    ㄴ userAccountController.js
    ㄴ userAccountService.js
    ㄴ userAccountRepository.js
    ㄴ userAccountEntity.js

다음과 같은 형태로 진행이 됬지만 서비스 요구사항과 관련된 테이블수가 늘어나면 늘어날 수록 이는 당연히 임시 방편에 그친다는 것을 알게 되었으며

table 마다 조작하는 service 와 다른 table을 동시에 작업하는 service 가 필요하다는 걸 느꼈다

하지만 더 이상의 분류는 할 수가 없어 난감해 하던 찰나

repository.js 라는 부분이 아무 것도 하지 않는 코드임을 깨닫기까지 오랜 시간이 걸리지 않았다

회사에 있었던 코드 상으로는 각 Entity.jsrepository.js 의 관계는 대략 이러했다

// userEntity.js

const Sequelize = require('sequelize')

module.exports = class UserEntity extends Sequelize.Model {
 	static init(sequelize){
     	return super.init({
        	column: {
            	type: Sequelize.INTEGER,
              	allowNull: false
            },
          	...
        }, {
        	sequelize,
          	timestamp: true,
          	...
        })
    }
}
// userReposiotry.js

const baseDB = require('baseRepository')
const userEntity = require('userEntity')

baseDB.UserEntity = userEntity
userEntity.init(baseDB.sequelize)

module.exports = baseDB.UserEntity

즉 Reposiotry 라는 파일은 단순히 위에서도 말했지만
단순히 exports를 통해 연결만 해주는 파일이다

그럼 여기를 더 세분화 하면 될 것같다는 생각이 들었다

따라서 Model 이라는 파일을 하나 더 만들어서

지금의 Entity -> Model
현재의 Repsitory -> Entity 로 옮기고
단일 Table 마다의 service 함수는 Repository
여러 Table 마다의 service 함수는 Service 로 옮기게 된다면
여러 Table 을 오가는 Service 또한 재사용성이 많아 질 것이다

예를 들면 회원 가입로직 이라던지, 회원 탈퇴 로직 등등이 말이다.

결과적으로 현재는 이런 상황까지 오게 되었다

user 
ㄴ user
	ㄴ userRouter.js
    ㄴ userController.js
    ㄴ userService.js
    ㄴ userRepository.js
    ㄴ userEntity.js
	ㄴ userModel.js
  
ㄴ userAccount
	ㄴ userAccountRouter.js
    ㄴ userAccountController.js
    ㄴ userAccountService.js
    ㄴ userAccountRepository.js
    ㄴ userAccountEntity.js
    ㄴ userAccountModel.js
    

막상 적용해보니 각 폴더의 형식이 같아 Default Folder 까지 지정할 수 있어서 매우 편했고 확장성이나 새로운 추가 개발을 할 때도 편안했다 하지만.. 근본적인 문제는 아직까지 남아있었다

  • 새로운 기능이 들어갈 때마다 테이블별로 폴더를 생성하지만 해당 테이블이 추가적인 API가 필요가 없고 table 만 필요할경우 router 부터 controller , service 함수까지 아무런 코드가 적히질 않는다

  • 기준이 되는 Table 일 경우 해당 함수들이 몰릴 가능성이 있다
    아무래도 Router 는 해당 Table 의 이름으로 시작되는 경우가 많기 때문이다

해당 문제를 찾기 위해 동료분에게 물어봤더니 Table 이 아닌 기능별로 묶자는 것이다.

router
	ㄴ userRouter.js
controller
	ㄴ userController.js
service
	ㄴ userService.js
repository
	ㄴ userRepositroy.js
entity
	ㄴ userEntity.js
model
	ㄴ userModel.js

이렇게 구조를 바꾸면

  • Table 만 필요한 경우도 Model 에서 이미 구현해 놓았지만 controller, service, repository 는 작성할 필요가 없어도 구조가 유지가 된다.
  • 한 폴더 내에서 로직을 처리할 필요가 없으므로 애초에 service 는 여러 table 동시에 수정할 수 있다.

그렇다면 이름 또한 기능적으로 바뀌어야 한다.

[ 결론 ]

결과적으로는 현재는 기능별로 구조를 바꿔야 하는 것이 올바른 방향같다

[느낀점]

사실 더 정확한건 해당 부분으로 바꿨을 때의 단점을 아직도 못 찾고 있다.
현재는 천천히 수정을 하고 있긴한데 사실 엄두가 매우 나질 않는다.
단순히 table 이름으로 구분했던 함수들과 조각들이지만 이를 기능별로 다시 재배열 해야하니 많은 양의 함수가 이미 적혀있는 서버인 경우 모든 기능을 다시 만들어야하는 부담감이 느껴져서 섣불리 움직일 수가 없게 된다.

하지만!
앞으로를 위해 다시 조금씩 수정을 진행해보려고 한다.
가능한 최근 개발 순으로... 최대한..건들지 않는게...

그리고 서버 개발자로 일을 하게 되면서 보수적이 되는건 확실한 것 같다. 새로운 변화를 받아들인다는 것은 나의 일이 더 추가되는 일뿐만 아니라 다양한 에러들을 맞닿들인다는 점에서 말이다.

profile
Full 이 되고 싶은 BackEnd

0개의 댓글