Just Do IT!

[SODA] 프로젝트 8주차 회고 본문

프로젝트/SODA 프로젝트

[SODA] 프로젝트 8주차 회고

MOON달 2025. 5. 11. 23:45
728x90
반응형

https://www.s0da.co.kr/

 

SODA

B2B 프로젝트 관리는, SODA에서

www.s0da.co.kr

 

이제 슬슬 끝나가니 회고글에도 슬쩍 추가해보는 우리 프로젝트 링크.

자잘한 오류들 및 디자인만 수정하면 발표날이 될 듯 하다.

 

 

 

 

 

 

 

 

리팩토링 기간

 

월요일, 화요일은 연휴 기간이라 물 흐르듯 이틀이 사라졌다.

회고글에도 작성했듯이 시간이 그렇게 많이 있지는 않아서 강의 내용 그대로 리팩토링하지는 않았고 우리 프로젝트에 맞춰서 리팩토링했다.

 

validator는 application layer에 위치하도록.

provider interface는 domain layer, proivderImpl 파일은 intrastructure layer에 만들면서 repository를 직접 참조하지 않도록 했다. 이렇게 파일들을 분리하는 것만으로도 꽤나 생각을 많이 해야 했다.

 

회고글에 잠시 프로젝트 생성을 예시로 작성해봐야겠다. (발표에도 쓸 내용)

 

프로젝트 생성하는 기능을 만들 때, 기존에는 서비스 로직이 엄청 길었다.

이렇게 서비스의 createProject 메서드 안에 너무 많은 책임이 있었다.

  1. 사용자 유효성 검사
  2. 날짜 유효성 검사
  3. 프로젝트 기본 정보 생성
  4. 고객사 지정
  5. 초기 stage 생성
  6. response 생성

 

그래서 리팩토링 하면서 

Project 엔티티는 단순한 데이터 홀더가 아니라, 자신의 데이터를 기반으로 특정 행위(생성, 관계 설정)를 수행하는 주체가 되도록 했다.

 

protected static Project create(String title, String description, LocalDateTime startDate, LocalDateTime endDate,
                                    List<Company> clientCompanies, List<Member> clientManagers, List<Member> clientMembers,
                                    List<String> initialStageNames) {
       var project = Project.builder()
               .title(title)
               .description(description)
               .startDate(startDate)
               .endDate(endDate)
               .status(ProjectStatus.CONTRACT)
               .build();

       project.assignClientCompanies(clientCompanies);
       project.assignClientMembers(clientManagers, clientMembers);
       project.addInitialStages(Stage.createInitialStages(project, initialStageNames));
       return project;
}

private void addInitialStages(List<Stage> initialStages) {
        if (initialStages != null) {
            this.stage.addAll(initialStages);
        }
    }

protected void assignClientMembers(List<Member> clientManagers, List<Member> clientMembers) {
        if (clientManagers != null) {
        List<MemberProject> clientManagerProjects = clientManagers.stream()
                .map(member -> MemberProject.createClientManager(member, this))
                .toList();
        this.memberProjects.addAll(clientManagerProjects);
    }
        if (clientMembers != null) {
            List<MemberProject> clientMemberProjects = clientMembers.stream()
                    .map(member -> MemberProject.createClientMember(member, this))
                    .toList();
            this.memberProjects.addAll(clientMemberProjects);
        }
    }

protected void assignClientCompanies(List<Company> clientCompanies) {
        if (!CollectionUtils.isEmpty(clientCompanies)) {
            List<CompanyProject> clientCompanyProjects = clientCompanies.stream()
                    .distinct()
                    .map(company -> CompanyProject.createClientCompany(company, this))
                    .toList();
            this.companyProjects.addAll(clientCompanyProjects);
        }
    }

 

이런 식으로 Project entity에 자체 연관관계를 설정하고, create 메서드를 생성해 프로젝트 생성하는 기능을 분리했다.

 

최종적으로 리팩토링한 서비스 코드는

public Project createAndStoreProject(
            String title, String description, LocalDateTime startDate, LocalDateTime endDate,
            List<Company> clientCompanies, List<Member> clientManagers, List<Member> clientMembers,
            List<String> initialStageNames) {
            
        Project project = Project.create(
                title, description, startDate, endDate,
                clientCompanies, clientManagers, clientMembers,
                initialStageNames
        );

        Project savedProject = projectProvider.store(project);
        return savedProject;
}

 

이렇게 줄었다.

순수하게 도메인 객체를 만들고 저장하는 데 집중하는 코드로 간결하게 리팩토링할 수 있었다.

 

 

그리고 controller에서 소통하는 facade 파일을 생성했다.

 

public ProjectCreateResponse createProject(String userRole, ProjectCreateRequest request) {
        projectValidator.validateAdminRole(userRole);
        projectValidator.validateProjectDates(request.getStartDate(), request.getEndDate());

        List<Company> clientCompanies = new ArrayList<>();
        List<Member> clientManagers = new ArrayList<>();
        List<Member> clientMembers = new ArrayList<>();

        for (CompanyAssignment assignment : request.getClientAssignments()) {
            // 고객사 조회
            Company clientCompany = companyService.getCompany(assignment.getCompanyId());
            clientCompanies.add(clientCompany);

            // 고객사 매니저 조회 및 소속 검증
            if (!CollectionUtils.isEmpty(assignment.getManagerIds())) {
                List<Member> managers = memberService.findMembersByIdsAndCompany(assignment.getManagerIds(), clientCompany);
                clientManagers.addAll(managers);
            }
            // 고객사 멤버 조회 및 소속 검증
            if (!CollectionUtils.isEmpty(assignment.getMemberIds())) {
                List<Member> members = memberService.findMembersByIdsAndCompany(assignment.getMemberIds(), clientCompany);
                clientMembers.addAll(members);
            }
        }

        Project savedProject = projectService.createAndStoreProject(
                request.getTitle(),
                request.getDescription(),
                request.getStartDate(),
                request.getEndDate(),
                clientCompanies,
                clientManagers,
                clientMembers,
                request.getStageNames() // 초기 스테이지 이름 전달
        );
        
        publishProjectCreatedEvent(savedProject);

        return ProjectCreateResponse.from(savedProject);
}

 

프로젝트 생성과 관련된 여러 서비스 호출 및 작업 흐름 조정하도록 했다.

 

 

프로젝트 생성만 예로 들었지만 댓글, 게시글 등 내가 맡은 부분을 리팩토링하는 걸로 시간을 다 보냈다.

처음에 로직을 구현하는 것만큼 리팩토링에도 생각보다 시간이 오래 걸린다는 걸 깨달았다.

저번 프로젝트에서는 자바 처음 배우고 한 프로젝트라 그냥 냅다 서비스 로직에 엄청 많이 집어넣었었는데...

책임 분리, 단일화 엔티티로 책임 내리기 등등...이번에 배우는게 너무 많다.

 

좋은데 리팩토링할 시간이 조금 더 있었으면 어땠을까 하는 아쉬움이 있긴 하다.

아무튼. 이번주는 리팩토링을 하면서 이슈 테스트에서 나온 버그를 수정하는 주간이었다.

 

 

 

 

 

 

 

 

 

이슈 테스트 버그 수정

 

지난주에 이슈 테스트를 진행했다고 했는데 리팩토링하기 전까지 버그 해결을 하나도 안했다 ㅋㅋㅋ

원래도 안하고 리팩토링 먼저 하려고 했으니까.

목요일에 내가 맡은 부분 리팩토링이 거의 끝나서 그때부터는 FE 버그를 해결하는데 시간을 보냈다.

 

API 연동이 잘못 된 부분들도 있었고, 아예 안된 부분도 있었고...

cursor는 왜 A를 하라니까 B를 변경하면서 같이 A를 고치지 않는 걸까...?

뭐하나 연동하면 다른게 안되고 난리 부르스라 하나 고치는데 생각보다 오래 걸렸다.

 

어찌저찌 해결은 했는데...아직 다 된 건지는 모르겟다.

다음주에 한번 더 체크해봐야지.

 

 

 

 

 

 

 

 

 

 


어느덧 회고글이 8주차가 되었다.

다음주면 발표 준비하면서 PPT 만들고 발표글 작성하면 일주일이 다 지나갈 것 같다.

이제 캠프가 끝나가는데 더 배워야할게 많을 것 같아서 캠프가 끝나면 더 바쁘지 않을까...ㅎ

 

이번 프로젝트는 그래도 코드적으로 많은 고민을 하는 것 같아서 뿌듯하다.

728x90