ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 클린 아키텍쳐를 프로젝트에 적용해보자
    프론트엔드 2025. 8. 5. 23:47

    클린 아키텍쳐

    - 클린 아키텍쳐는 소프트웨어 시스템을 계층적으로 분리하는 설계 방식이다. 

    클린 아키텍쳐 관련 글은 작성한 것이 있으니 참고하면 좋을거 같다 

     

    간단하게 정리하면 

    - 클린 아키텍쳐는 내부 계층이 외부 계층을 의존하지 않아야 한다는 특징이 있다.

     

    도메인 계층은 Entity와 Repository가 있다. 

    Entity : 핵심 비지니스 객체이다. -> DB에서 User 데이터가 있다면 User 데이터 객체를 의미한다.  
    Repository : 저장 조회같은 도메인 관점의 데이터 처리를 명세한다 -> 말 그대로 데이터 처리 명세에 초점을 둔다 
    import { FeedBackEntity } from "@/backend/feedbacks/domains/entities/FeedBackEntity";

    export interface FeedBackRepository {
    //create
    AddFeedBack(feedBack: FeedBackEntity): Promise<FeedBackEntity>;
    }

     -> 위 코드에서 보면 AddFeedBack 데이터를 처리하기 위해 명세를 한 것을 볼 수 있다. 

     

    어플리케이션 계층은 DTO, UseCase가 있다. 

    DTO: API 요청시 필요한 데이터 객체를 정의한다
    UseCase : 기능 단위로 로직을 실행한다 -> 어떻게 동작할지만 정의하고 구현은 모른다! 
    import { PrFeedBackRepository } from "@/backend/feedbacks/infrastructures/repositories/PrFeedBackRepository";
    import { FeedBackEntity } from "@/backend/feedbacks/domains/entities/FeedBackEntity";

    export class GetRoutineReviewListUsecase {
    constructor(public readonly PrFeedBackRepository: PrFeedBackRepository) {}

    async execute(feedBack: FeedBackEntity) {
    return this.PrFeedBackRepository.AddFeedBack(feedBack);
    }
    }

    -> UseCase 코드를 보면 execute 안에 실제 실행되어야 할 함수를 넣었다. 

     

     

    인프라계층Repository가 있다

    Repository : 인프라계층은 외부 라이브러리 등에 의존을 하기 때문에 레포지토리안에 외부 라이브러리 코드를 사용한다
    import { FeedBackEntity } from "@/backend/feedbacks/domains/entities/FeedBackEntity";
    import { FeedBackRepository } from "@/backend/feedbacks/domains/repositories/FeedBackRepository";
    import prisma from "@/public/utils/prismaClient";

    export class PrFeedBackRepository implements FeedBackRepository {
    async AddFeedBack(feedBack: FeedBackEntity): Promise<FeedBackEntity> {
    const createdFeedBack = await prisma.feedback.create({
    data: {
    gptResponseContent: feedBack.gptResponseContent,
    challengeId: feedBack.challengeId,
    },
    });

    return new FeedBackEntity(
    createdFeedBack.gptResponseContent,
    createdFeedBack.challengeId
    );
    }
    }

    -> 코드를 보면 prisma를 create를 하는 모습을 볼 수 있다. 

     

    어댑터 계층은 Next.js에서 route.ts가 있다

    Adapter : 외부와 useCase를 이어준다.  
    import { GetRoutineReviewListUsecase } from "@/backend/feedbacks/applications/usecases/GetRoutineReviewListUsecase";
    import { PrFeedBackRepository } from "@/backend/feedbacks/infrastructures/repositories/PrFeedBackRepository";
    import { NextRequest, NextResponse } from "next/server";

    export const POST = async (request: NextRequest) => {
    const body = await request.json();

    try {
    const feedbackRepo = new PrFeedBackRepository();
    const feedBackUseCase = new GetRoutineReviewListUsecase(feedbackRepo);
    const result = await feedBackUseCase.execute(body);

    if (!result) {
    return NextResponse.json(
    { error: "피드백 데이터 저장에 실패했습니다." },
    { status: 400 }
    );
    }
    return NextResponse.json(
    { message: "피드백 데이터가 저장되었습니다." },
    { status: 200 }
    );
    } catch (error) {
    console.error(error);
    return NextResponse.json(
    { error: "Internal Server Error" },
    { status: 500 }
    );
    }
    };

    -> 위 코드에서 보면 route.ts로 POST를 보내는데 useCase를 연결 해주는 것을 볼 수 있다.

     

    결론 🤔

      • 프로젝트 초반엔 구조가 복잡하게 느껴졌지만,
      • 기능별 책임이 명확하게 나뉘니까 협업과 유지보수가 훨씬 쉬워짐
      • 실제로 하나의 기능을 고칠 때 다른 부분에 영향이 거의 없어서,
      • 버그 발생률도 줄고 테스트 코드도 더 잘 작성할 수 있었다. 

    '프론트엔드' 카테고리의 다른 글

    Date.prototype.toISOString()  (0) 2025.08.13
    Next.js 미들웨어로 온보딩 접근 제어 구현하기  (2) 2025.08.13
    TanStack Query 적용해보기  (5) 2025.08.12
    Git Merge 방법  (3) 2025.08.02
    클린아키텍쳐  (0) 2025.07.31
Designed by Tistory.