[App] React Native/[TAVE] Snal 프로젝트

Clean Architecture

유진진 2025. 6. 5. 16:43

클린 아키텍처에 대해 알아보기 전에 주요 개념을 알아보자. 

의존성 규칙:

 

많은 코드들은 다른 코드에 의존한다. Javascript에서는 require이나 import, C에서는 include을 통해 모듈들이 서로 의존한다. 

만약 B 모듈이 A 모듈을 import하고 있다면, B 모듈은 A 모듈에 의존하고 있다고 한다.

그리고 그 B 모듈이 다른 모듈에 의해 참조되지 않는다면, A 모듈과 달리 B 모듈은 유연하게 변경해도 상관없다. (A 모듈은 안정적, B 모듈은 불안정적)

 

불안정한 모듈은 우리가 편안한 마음으로 변경할 수 있어야 하기 때문에 분명히 있어야하고,

우리는 항상 불안정한 모듈이 안정된 모듈에 의존하게 해야 한다. 

 


 

클린 아키텍처 ?

소프트웨어 설계 원칙 중 하나로, 유지보수성, 유연성, 테스트 용이성을 높이기 위해 의존성 규칙을 따르는 구조이다. 

클린 아키텍처는 원하는 기술 스택 (React Native, Flutter, Android 등)에 따라 조금씩 변형은 가능하지만, 이 구조는 앱이 커질 수록 강력한 힘을 발휘한다. 

 

왜 아키텍처가 중요한가 ?

소프트웨어를 만드는 것은 누구나 할 수 있지만, 적은 인력으로 유지보수를 쉽게할 수 있으면서도 버그가 적게 생기는 소프트웨어를 만들기 위해서이다. 

 

클린 아키텍처의 특징

클린 아키텍처는 관심사의 분리를 위한 여러 아키텍처들이 가지고 있는 아이디어들을 하나로 통합해보는 것이다. 

단순한 하나의 동심원 형태를 갖는다. 

소프트웨어 아키텍처는 선을 긋는 기술이며, 나는 이러한 선을 경계(boundary)라고 부른다.
경계는 소프트웨어 요소를 서로 분리하고, 경계 한편에 있는 요소가 반대편에 있는 요소을 알지 못하도록 막는다. - Robert C. Martin, Clean Architecture

 

소스 코드 의존성(화살표 방향)은 반드시 안쪽으로, 고수준의 정책을 향해야 한다. 

- 여기서 수준이란? 
경계의 바깥으로 갈수록 덜 중요하고 세부적인 영역이고, 안으로 갈수록 고수준(더 추상화됨)이다.
고수준은 "운동을 한다", 저수준은 "집에서 팔벌려뛰기 운동을 한다" 라고 할 수 있다. 

 

내부의 원에 속한 요소는 외부의 원에 속한 어떤 것도 알지 못해야 한다. 

예를 들면 repository 레이어는 API 엔드 포인트 등을 포함하는데,  repository 레이어의 구현체는 DB, 웹 등의 것들을 단 하나도 알면 안된다. 

 

1. Entity

어플리케이션의 핵심 중 핵심이 되는 업무 객체. 어플리케이션이 없어도 존재해야 하는 것이다.

- 가장 변하지 않으며 외부로부터 영향을 받지 않는 영역이다. 

예시: 배달 서비스 플랫폼의 경우, "음식점과 주문자"

 

2. UseCase

어플리케이션의 핵심 업무 객체(기능). 어플리케이션의 존재 이유이다. 

- 엔티티로 들어오고 나가는 데이터의 흐름을 조작한다. 

예시: "장바구니에 음식을 담을 수 있다.", "로그인/로그아웃을 할 수 있다."

 

3. 어댑터 

UseCase 가 올바르게 동작하기 위해서는 사용자 인터페이스와 DB가 소통해야하는데, 이 때 UseCase가 GUI나 DB 사이에서 브릿지 역할을 해주는 것이 어댑터 레이어이다. 

- 외부 인터페이스에서 들어오는 데이터를 유즈 케이스와 엔티티에서 처리하기 편한 방식으로 변환한다.

- 유즈케이스와 엔티티에서 나가는 데이터를 외부 인터페이스에서 처리하기 편한 방식으로 변환한다. 

  • repository
  • presenter
  • controller
  • gateway

 

4. 프레임워크과 드라이버

시스템의 핵심업무와는 관련 없는 세부사항 

  • 프레임워크, 데이터베이스, 웹서버 

 

그외

5. 메인 : 어플리케이션의 진입점이자 궁극의 세부사항. 메인은 어플리케이션의 모든 세부사항을 알고 있다.

6. 테스트 : 모든 세부사항보다도 바깥에 있다. 테스트는 다른 것들과 다르게 배포되지 않고 유저에게 영향을 미치지도 않는다. 

 

 

 


클린 아키텍처의 구조

src/
|--- domain [Optional]
|     |- entities
|     |- useCases
|
|--- data
|     |- reposiroties
|     |- sources (ex: PagingSource)
|
|--- presentation 
|     |- components
|     |- screens
|     |- navigation
|     |- state
|
|--- remote
|     |- api
|     |- reponse
|     |- request
|
|--- local
|     |- dao
|     |- tables
|
|--- app.tsx

 

 

Domain/

앱의 비지니스 로직의 핵심을 담당하는 순수한 로직만을 담는 계층이다. (의존성 없음)

  • entities/
    • 앱의 핵심 데이터 모델 (예시: User, Product 같은 도메인 객체)
    • UI나 DB에 의존하지 않는다. 
  • useCase/
    • 비지니스 로직을 담당하는 함수들
    • 예시: "로그인하기", "장바구니에 상품 추가"

 

 

 

Data/

도메인 로직과 실제 데이터 소스를 연결하는 계층 

  • repositories/
    • 도메인 계층에서 사용하는 interface를 구현한다.
    • 외부 소스에서 데이터를 가져오고 이를 정제해서 도메인에 제공한다.
  • sources/
    • 실제 데이터가 오는 곳
    • 예시: PagingSource, RemoteDataSource, LocalDataSource

 

 

Presentation/

화면 UI 관련 코드를 모아두는 곳 

  • components/ 
    • 재사용 가능한 컴포넌트 (버튼, 카드 등)
  • screens/
    • 실제 화면 단위의 컴포넌트들 (예시: 로그인 화면, 상품 목록 화면 등)
  • navigation/
    • 화면 간 이동 로직 (예: 리액트 네이티브에서 라우팅을 정의할 때)
  • state/
    • 화면 상태 관리 (Redux, Zustand, Recoil 사용 시)

 

 

Remote/

네트워크 통신 관련 코드를 모은 곳 

  • api/
    • 실제로 서버와 통신하는 API 함수 정의 
  • request/
    • 서버에 보낼 요청 형식을 정의 (DTO)
  • response/
    • 서버에서 오는 응답 형식을 정의 

 

 

Local/

로컬 저장소 관련 코드 (예: SQLite, Room, SharedPreferences 등)

  • dao/
    • 로컬 DB 접근 함수들을 모은 곳이며, DB 테이블에 쿼리하는 로직이다.
  • tables/
    • DB 테이블 구조를 정의 

 

App.tsx

앱의 진입점.

최상단에서 라우팅, 상태관리, 테마 등을 설정한다. 

 


참고

https://velog.io/@woohm402/clean-architecture-short-summary

https://meetup.nhncloud.com/posts/345