프론트엔드 아키텍처: API 요청 관리

이문기
19 min readAug 3, 2022

--

Photo by Alina Grubnyak on Unsplash

프론트엔드 개발을 하다보면 종종 아주 기본적인 것부터 고민할 때가 많습니다. 그 중 제 머리속을 떠나지 않고 찜찜한 상태로 남아있는 건 API 요청을 관리하는 것이었습니다. 이 고민들은 ‘API 요청을 하는 함수들은 어떤 디렉터리에 둬야하지?’, ‘관리하는 디렉터리 이름은 뭘로 하지?’, ‘함수의 이름은 뭘로 하지?’ 등과 같이 아주 기본적인 것들을 포함합니다. 특히 작은 스타트업에서 일을 하거나 사이드 프로젝트, 간단한 연습용 프로젝트를 하려고 프로젝트를 구성하다보면 매번 고민하게 되는 이런 문제들은 이젠 더이상 하기 싫은 고민이 됐습니다. 불과 몇 주전에 참고했던 아티클은 새롭게 찾아낸 더 좋아보이는 아티클에 감춰져 지금 프로젝트를 비판하는 것 같았습니다. 답을 구하려고 주변에 물어봐도 뚜렷한 답을 찾을 수 없었습니다. ‘API니까 api 폴더에 두는 거지’와 같이 아주 단순하고 자명해보이는 답을 얻을 때도 있었고 수긍할 수도 있었지만, 백엔드에서 데이터베이스의 동작을 추상화한 레이어를 ‘db’로 부르지않고 ‘repository’로 부르는 걸 보면 그렇게 자명해보이지 않기도 했습니다.

API를 어떤 이름의 디렉터리로 관리할지가 API를 관리하는 데 중요한 역할을 할까요? 전 중요하다고 생각합니다. 결국 어떤 API를 어디에 모아두고, 어떤 서포팅을 하는 기능들이 어떤 곳에 모여있는지 결정하는게 디렉터리라고 하면 더욱 그렇습니다. 그리고 어떻게 이름을 짓는지는 역할을 부여하는 것과 같기 때문에 이것 역시 중요합니다.

지금 그 답을 찾았다는 건 아니지만 확실히 이전보다 더 나은 답을 낼 수 있을 거 같다는 생각에 이렇게 정리를 하게 됐습니다. ‘API 요청을 관리하는 디렉터리 이름은 api로 하는 게 좋을 거 같다’는 답이 나오더라도 그 과정에 고민이 녹아 있다면 더 확신을 갖고 api라고 디렉터리 이름을 지을 수 있지 않을까요?

앞으로 보실 내용은 절대 정답이 아닙니다. 각자의 환경이 다르고 고민의 내용이 다를 수 있습니다. 이 글에선 단순히 이름을 짓는 문제부터 어떻게 하면 API 요청을 잘 관리할 수 있을지에 대한 고민이 있습니다. 제가 예전에 참고했던 아티클들처럼 또 하나의 아티클이라고 봐주시면 좋을 거 같습니다.

시작

처음 웹 개발을 할 땐 아래와 같이 API를 호출했습니다.

즉, 디렉터리나 함수로 관리하기 보다 바로 호출해서 사용했습니다. 이렇게 하다보면 문제가 발생합니다. “A 페이지하고 B 페이지에서 모두 /url로 API로 요청을 보내는 데 어떻게 하지?” 그럼 이제 API 요청을 보내는 부분을 별도의 함수로 만들고 디렉터리와 파일로 구분합니다.

그럼 여기에서 두 번째 고민이 생깁니다. api라고 이름은 지었지만(다른 어떤 이름이라도 상관없습니다) 폴더 이름으로 괜찮은지, 그리고 url.js라는 이름은 적절한지 고민하기 시작합니다. 그리고 때론 팀 내에서 논쟁이 생깁니다.

‘난 api라고 하지 않고 request라고 짓는 편이다.’, ‘난 source라고 짓는다.’, ‘난 data로 짓는다’ 등등 너무 많은 이야기를 들어왔습니다. 전 주로 ‘API를 모아놨으니까 api라고 부르는 게 좋지 않을까?’와 같은 입장이었지만 왜 request라고 지으면 안 되는지 설명해달라고 하면 꿀먹은 벙어리가 됐습니다. 좀 더 극단적으로 apiRequest는 왜 선택지에 없을까요? data는 왜 안 되는지에 대해 어떻게 설명하고 api라는 이름은 왜 api여야 할까요?

// 지금까지 API 폴더 구조
- api
- url.js

API부터 데이터 저장까지

먼저 API는 프론트엔드에서 어떤 역할을 하는지 알아봤습니다. 우린 API(Application Programming Interface)를 활용해 서버에게 요청하고 응답을 받습니다. 어떤 요청과 응답을 주로 주고 받을까요? 그건 데이터와 관련이 깊습니다. 우리가 주로 사용하는 REST API(Representational State Transfer)는 HTTP를 사용하여 클라이언트와 서버가 데이터를 주고받습니다. 이 때 데이터는 주로 JSON의 형태입니다. 그리고 이 방법들의 특징은 ‘상태 없음’입니다. 그렇기 때문에 데이터를 영구적으로 저장하기 위해선 데이터베이스 등의 도움이 필요합니다. 이 때 우린 서버에게 데이터를 보관해달라고 요청하고 필요할 때 저장한 데이터를 조회해달라고 요청합니다. 요청을 받은 서버는 데이터베이스에 데이터 조회 또는 저장 등을 요청하게 됩니다.

클라이언트와 서버 모두 데이터를 저장하기 위해 저장할 수 있는 수단을 가진 대상에게 요청을 합니다. 그렇다면 백엔드는 데이터 요청을 어떻게 관리하고 사용하는지 살펴보면 무언가 통찰을 얻을 수 있지 않을까요?

백엔드에선 Repository, DTO, ORM, DAO 등 많은 개념과 용어들을 데이터를 관리하는 데 사용하고 있었습니다. 특히 Repository와 ORM은 데이터에 대한 요청 및 응답과 관련이 깊어보였습니다. 프론트엔드에서도 사용 가능할까요?

ORM(Object-relational mapping)은 객체지향으로 구성된 프로그램과 스칼라 데이터를 다루는 관계형 데이터베이스 사이에 데이터 매핑을 해주는 프로그래밍 기법입니다. 알아보니 프론트엔드에선 필요할거라 생각이 들진 않았습니다. 클라이언트와 서버 모두 REST API를 활용해 JSON 데이터를 주고받고 있기 때문이었습니다.

Repository는 무언가를 보관하는 창고를 의미합니다. 서버에서는 데이터를 보관하고 관리하는 대상을 Repository로 추상화하여 이해하기 쉽고 유연하게 관리가 가능하도록 합니다. 프론트엔드에서도 사용 가능할까요?

백엔드처럼 프론트엔드도 데이터를 저장하고 다뤄야 하는 영역은 여러가지 입니다. 서버와 API 통신, Cookie, Local Storage 등이 대표적입니다. 프론트엔드에서 이 기술들을 직접 다루는 게 아니라 Repository 처럼 추상화해줄 수 있다면 개발하면서 Local Storage인지 아닌지 여부와 상관없이 함수의 이름을 통해 목적을 파악하고 사용할 수 있게 됩니다. 그리고 언제든 관련 엔드 포인트를 변경할 수도 있는 등 이점이 많습니다.

이런 고민의 결과로 repository라는 이름의 디렉터리에 API, Local Storage, Cookie 등 외부 자원을 다루는 모듈들을 담아두면 어떨지 궁금했습니다.

// 지금까지 폴더 구조
- repository
- api
- url.js
- localStorage
- ...
- cookie
- ...
// 이전 방법이었다면...
- api
- url.js
- localStorage
- cookie

Repository? Request?

하지만 아래와 같은 문제가 발생할 수 있습니다.

  1. Repository라는 이름에 익숙하지 않다.
  2. 정말 Repository처럼 활용하고 있나?

먼저 이름 자체에 익숙하지 않다보니 왜 이렇게 이름을 지어야 했는지 설명하는 과정이 길어질 수 있습니다. 그리고 Repository처럼 활용하고 있는지 생각해볼 필요가 있습니다.

그러다보니 repository라는 디렉터리 하위에 리소스 접근과 관련된 코드를 모아놨다는 것 말고 이전과 차이는 없었습니다. 그래서 하나하나 해결하기 위해 먼저 추상화라는 걸 해보기로 했습니다.

프론트엔드에서 외부 데이터 창고에 접근하는 기술, 방법 등을 직접 다루는 게 아니라 Repository 처럼 추상화해줄 수 있다면, 개발하면서 기술의 종류와 상관없이 함수의 이름을 통해 목적을 파악하고 사용할 수 있게 됩니다. 그리고 관련 구현 내용을 비교적 쉽게 변경하거나 추가할 수 있습니다.

예를 들어,

처럼 되어있으면 사용 하는 곳에서

과 같이 사용할 수 있습니다. 이 방법은

방법보다 조금은 더 추상적입니다. 왜냐하면 구체적으로 어떤 도구(여기에선 axios)를 사용하고 url을 어떻게 구성하는지 숨길 수 있기 때문입니다. 하지만

와 비교했을 때 어떤 방법이 더 나은지 알기 어렵습니다. 이 시점에서 인터페이스를 사용할 수 있다면 더 나은 추상화를 할 수 있습니다. 이 내용은 이 글의 마지막에서 추가로 다루겠습니다.

주의해야 할 사항은 todoListRepository 내에서 공통 로직이 있다고 해서 아래와 같이 추가하면 안 됩니다.

이렇게 하면 todoListRepository를 사용하는 곳에서 somethingCommon에 접근할 수 있는 가능성을 열어두게 됩니다. (위에 정의한 somethingCommon의 경우 export만 붙여주면 간단히 외부에서 접근이 가능합니다.) 외부에서 somethingCommon에 접근하게 되면 get이나 create의 내부 로직에 접근하는 것과 같은 효과를 갖게 되고 향후 로직 변경에 취약해집니다.

그렇기 때문에 아래와 같이 클로저를 사용하는게 더 좋습니다.

이제 요청 방법을 변경한다면 해당 repository만 변경합니다.

이 방법은 Vanilla JS 환경을 예시로 작성했습니다. Typescript 환경이라면 아래와 같이 작성합니다.

Vanilla JS 환경에서 클래스를 사용하지 않은 이유는, 네이밍 컨벤션 등으로 메서드나 속성에 접근하지 못하도록 하는건 다소 느슨한 제약이기 때문입니다.

이렇게 하면 리스트를 어떻게 가져오는지에 대한 변경과 수정이 용이해집니다. 만약 todoListRepository.getById라고 이름을 지었다면 listId 이외에 다른 조건이 추가되어 get: (listId, listName) => { ... }이 됐을 때, 이름도 getByIdOrName 등으로 변경해야 합니다. (둘 다 필요하다면 getByIdAndName이 될 수도 있습니다.)

추상화에 대한 준비는 이정도로 하고, 다음으로 Repository라는 이름이 익숙하지 않아 발생한 문제를 살펴보겠습니다. Repository라는 이름은 프론트엔드 개발자에게 익숙하지 않기 때문에 이 글의 앞에서 언급한 것 처럼 ‘왜 Repository’어야 하는가?’에 대해 설득하는 과정이 필요할 수 있습니다. 그렇기 때문에, 굳이 Repository라는 이름을 사용해서 당장 취할 수 있는 이점 외에 추가적인 설명(비용)이 크게 발생한다면, 네이밍에 집착할 필요는 없다고 생각합니다. 그래서 Repository 대신 Request를 사용하는 것도 좋은 방법이라고 생각합니다. 사실 Request라는 이름이 프론트엔드에서 데이터를 다루기에 적절한 이름이라고 생각하진 않습니다. 프론트엔드에서 하는 요청이 서비스 데이터를 보관하고 관리하는 것만 있진 않기 때문입니다. 그렇기 때문에 데이터를 관리하도록 요청하는 디렉터리를 Request로 짓게 되면 다른 요청과 혼동될 수 있습니다. 예를 들어,

todoListRequest // 할 일 목록을 가져오는 데이터 관리 요청emailRequest // 지정된 내용으로 이메일을 보내도록 외부 서비스에 요청

물론 emailRequest라고 안 지으면 그만이지만 request라는 것 자체가 ‘요청'이라고 해석되는 만큼 얼마든지 혼동될 가능성이 있습니다.

하지만 보통 프론트엔드에서 요청이라고 하면 API 요청을 떠올린다는 점 등을 고려해봤을 때 이런 문제들은 비교적 감당할만 수준이라고 생각합니다. 물론 서비스의 성격을 고려해서 다른 이름을 사용하는 게 더 좋을 수 있기 때문에 그때그때 합리적인 판단을 해야겠습니다.

- request
- urlRequest.js // api
- searchResultRequest.js // local storage
- someTokenRequest.js // cookie

그리고 이전에 localStorage, cookie와 같이 카테고라이징 하던 걸 없애고 -Request로 정한 이유는, 요청 전략은 언제든 변동될 수 있기 때문입니다. 우리가 만든 프로그램은 시간이 지나면서 계속 변합니다. API로 요청해서 해결하던 문제를 LocalStorage를 활용해 해결할지도 모릅니다. Cookie 요청으로 해결하던 문제를 API 요청으로 해결할지도 모릅니다. 만약 이렇게 변화가 생기면 우린 단순히 이름을 바꾸는 데에 너무나 큰 비용을 치를 수도 있습니다.

물론! -Request보다 -Repository가 더 마음에 들고 조직에서 합의를 봤다면 -Repository를 사용하면 됩니다. 또한 당연하지만 다른 이름도 가능합니다!

추가적으로, axios.get 등을 추상화 할 수도 있습니다. 이 내용에 대해선 역시 이 글의 마지막에서 추가로 다루겠습니다.

어떻게 이름을 지을까? — 함수의 분리

프론트엔드 개발을 하면서 백엔드 개발자와 협업을 하다보면 무수한 API가 만들어지고 이름을 어떻게 지을지 매번 고민하게 됩니다. 이럴 땐 조직마다 일관된 컨벤션을 정하는게 중요합니다. 그 중 제가 사용하는 방법은 명령과 조회를 구분하는 것입니다. 예를 들어, 데이터를 조회(query)하는 건 find, get 또는 fetch 등을 붙이고, 수정은 update, 추가는 save 또는 create, 삭제는 remove 또는 delete과 같이 명령(command)형 접두어를 붙이는 식입니다. 이렇게 하면 요청 함수가 무얼 하려고 하는지 이름만 봐도 이해할 수 있습니다.

여기에 더해 중요한 건 이름과 같은 의미로 함수가 구현되어야 한다는 것입니다. 조회하는 함수인데 내부에 명령과 같은 부수효과가 있어선 안 됩니다. 예를 들어, 조회 요청을 할 때마다 수정 요청을 해야만 한다면, 조회 함수 내부에 수정 요청을 넣는 경우가 종종 있습니다.

이렇게 하면 fetchTodoListIncludingTodos 함수를 신뢰해서 사용하기 어렵습니다. 예를 들어,

이렇게 a를 선언 했다면

와 같이 어디에서 얼만큼 a를 사용해도 a1이라는 걸 신뢰해서 사용할 수 있습니다. 하지만 중간에

와 같은 코드가 있다면

와 같이 a = a + 1 전후에 a의 값이 다르기 때문에 코드에 순서가 생기기 시작합니다. 따라서 위 코드는 아래와 같이 구현하는 게 더 좋습니다.

이렇게 하면 업데이트를 하지 않는 곳에선 fetchTodoListIncludingTodos를 값처럼 사용해도 됩니다. 물론 이렇게 분리해서 사용하는 것보다 조회와 명령을 한 곳에 합쳐두는 게 더 좋은 선택일 수 있습니다. 그런 경우엔 이익과 비용을 고려해서 더 나은 방법을 선택해야 겠습니다.

정보 접근의 입구가 어디인지 이해하기

fetch-update- 등을 어떻게 이름짓고 분리할지 정했다면 그 다음은 함수를 어느 -Request에 넣느냐, 즉 그룹핑을 고민해봐야 합니다. 이땐 정보를 얻어내기 위해 어떤 입구로 들어가는지 고려해서 그룹핑 합니다. 예를 들어, 할 일 목록(Todo List)과 목록에 포함된 할 일들(Todos)을 함께 조회한다면, 할 일들(Todos)은 할 일 목록에 속한 정보이기 때문에, 즉 정보에서 할 일들(Todos)에 접근하려면 할 일 목록(Todo List)이라는 입구를 반드시 지나야 하기 때문에 todoListRequest에 포함되는 게 더 적절합니다. (여기에서 입구는 제가 비유로 사용하는 단어 입니다.)

반면에 특정 단어를 포함하는 할 일들(Todos)을 조회하고자 한다면 정보에 접근하는 입구는 할 일들(Todos)이 유일하기 때문에 todoRequest에 포함되는 게 더 적절합니다.

여기에서 정보 접근의 입구는 SQL을 통해 질의를 할 때 사용하는 메인 테이블 정도가 될 것 같습니다. 그리고 충분히 논의된 도메인 시스템을 기반으로 데이터베이스의 엔티티가 설계되었다면, 정보 접근의 입구는 정보가 도메인의 어떤 요소에 속하는지 따져보고 찾아낸 엔티티가 될 것입니다.

예를 들어, 아래와 같이 도메인 지식을 기반으로 엔티티를 구성했습니다.

아주 단순한 구조입니다. 할 일 목록(TodoList)은 1개 이상(N개)의 할 일(Todo)를 갖습니다. 반면 할 일은 오직 하나의 할 일 목록을 갖습니다. 만약 아이디 1을 갖는 할 일 목록과 거기에 속하는 할 일을 가져와야 한다면 입구는 TodoList가 됩니다.

그리고 할 일 중에 foo라는 단어를 포함하는 할 일을 조회한다면 입구는 Todo가 됩니다. 이렇게 도메인의 지식이 API를 그룹핑하는 데 도움을 줍니다. 따라서 직관에 의존한 네이밍과 그룹핑 보단 도메인 지식에 근거한 결정이 더 좋은 결과를 낼 때가 많습니다.

API에서 로직의 분리

우리는 API를 활용해 데이터를 주고 받을 때 종종 까다로운 고민에 빠지곤 합니다. ‘값이 잘못 됐다면 null로 보내야 하는데 어디에서 이 처리를 해야하지?’, ‘프론트에선 날짜를 다룰 때 항상 Date 객체를 통해 하는데 전달할 땐 항상 문자열로 전달해야하네. 어디에서 변환해주지?’와 같은 고민들입니다. 이 예시는 요청에 관한 예시이지만 응답에도 같은 질문이 성립합니다. 즉, 데이터를 보낼 때나 받을 때 데이터를 관리하는 방식의 문제입니다.

전 이전에 API 요청을 아래와 같이 구현하곤 했습니다. (간단한 설명을 위해 인자에 값을 재할당 하는 방법을 사용했습니다.)

다소 억지스러운 예시이지만 간단하게 하기 위해 만들었습니다.

여기엔 두 가지 로직이 있고 큰 문제는 없어보입니다. 하지만 이렇게 되면 비지니스 로직이 수정될 때 API 요청 코드도 수정됩니다. 반대로 API 요청 코드를 수정할 때 비지니스 로직을 수정해야 할 수도 있습니다. 따라서 로직의 종류를 크게 두 가지로 나누고 분리 및 관리할 필요가 있습니다.

‘타입 혹은 자료구조와 관련이 있는가? 아니면 비지니스 로직과 관련이 있는가?’

비지니스 로직, 또는 도메인 로직은 서비스 전반에 걸쳐 사용되는 로직입니다. 그렇기 때문에 API 요청 내부에 비지니스 로직이 있다면 API 요청을 변경할 이유가 없어도 비지니스 로직이 수정되면 API 요청도 수정해야 합니다. 만약 비지니스 로직과 자료구조 로직이 결합되어있다면 수정은 좀 더 번거로워지고 리스크도 올라갑니다.

그렇기 때문에 API 요청 내부의 비지니스 로직을 분리해서 API 요청 전에 다루는 게 좋습니다.

그리고 API 요청 전 필요한 데이터 전처리를 그 다음 자료구조를 맞추는 작업을 진행합니다. 그리고 API를 요청하게 됩니다. 응답의 경우는 그 반대입니다.

이렇게 하면 에러를 핸들링 하는 데에도 도움이 됩니다. 에러의 카테고리를 만들기 수월하고 그에따라 다루기에도 전보다 더 수월해집니다.

이렇게 로직이 분리가 되어있고 한 방향으로 데이터가 흘러간다면 테스트를 작성할 때에도 수월합니다.

결론

API 요청을 관리하는 방법을 이름 짓기부터 시작해서 로직을 분리하는 방법까지 적어봤습니다. 프로젝트를 시작하거나 현재 사용하고 있는 방법에 한계가 드러났을 때 우린 새로운 방법을 찾습니다. 각자 좋은 방법을 찾고 어떤게 더 좋은 방법인지 논의하는 과정은 때론 매우 지난하고 때론 격한 논쟁이 되기도 합니다. 이 내용들은 정답이 아닙니다. 다만 API를 관리하기 위해 좋은 방법을 찾을 때 참고할 수 있는 자료가 되면 좋겠습니다.

이 글은 지난번에 작성한 프론트엔드 아키텍처: Business Logic의 분리와 함께 시리즈로 엮어봤습니다. 이 시리즈에선 어떤 환경에서든 프론트엔드 프로젝트의 구조를 고려할 때 제가 했던 고민들을 적었습니다. 참고하시는 데 도움이 되셨으면 합니다.

참고 자료

추가) 인터페이스를 사용해 요청 추상화하기

추상화는 인터페이스를 활용했을 때 더욱 잘 할 수 있습니다. 그렇다면 프론트엔드에서 추상화는 어떻게 다루면 좋을까요? 먼저 추상화에 대해 한 번 살펴보고 가겠습니다. 추상화란 복잡한 세부 내용으로 부터 불필요한 정보를 제거하고 핵심적인 내용을 추려내는 것을 의미합니다. 우린 todoListRepository에 여러가지 편의기능들을 추가하고 클로저를 사용하지 않고 유틸 함수들을 외부에 열어둘 수도 있습니다. 하지만 이런 내용들은 todoList의 데이터를 관리하는 데 핵심적인 내용이 아닙니다. 따라서 추상화가 필요합니다.

우린 이런 핵심적인 내용을 보통 인터페이스를 활용해 추상화 하곤 합니다.

위에서 다뤘던 예시를 인터페이스를 활용하도록 바꿔보겠습니다. 아래는 이전에 봤던 예시입니다.

이 repository를 추상화할 수 있는 방법은 크게 두 가지 입니다. 하나는 Vanilla JS 환경에서의 추상화이고 다른 하나는 Typescript 환경에서의 추상화 입니다.

Vanilla JS에서 추상화는 JSDoc을 활용하면 좋습니다.

이렇게 하면 사용하는 쪽에서

와 같이 사용하게 되는데 IDE를 통해 인자로 어떤 값을 전달해야 하는지, 반환값은 무엇인지 알 수 있게 됩니다. 무엇보다 todoListRepository의 타입을 TodoListRepository로 정하게 되면서 정말 필요한 핵심 기능이 무엇인지 다시 한 번 살펴보게 합니다.

Typescript 환경에선 더욱 수월합니다.

이렇게 하는 건 어떤 장점이 있을까요?

추상화를 해두면 정말 중요한게 무엇인지 정의할 수 있습니다. 그리고 우리가 만든 코드는 인터페이스, 즉 중요한 걸 기준으로 움직이게 됩니다. 따라서 인터페이스만 지켜준다면 그 어떤 코드를 사용하더라도 코드는 정상동작 하고, 그렇게 만들어져야 합니다.

예를 들어, axios가 아니라 fetch를 사용하도록 바꿀 필요가 있다면 인터페이스를 지키는 범위 내에서 자유로운 변경이 가능합니다. 또는 todoListRepository를 통째로 바꿔도 됩니다.

이 방법은 테스트를 작성할 때에도 도움이 됩니다.

이러한 장점들이 있기 때문에, Typescript 환경이 아니더라도 JSDoc을 활용해 추상화를 시도하는 것도 일정부분 의미가 있습니다.

추가) API 요청 추상화

API 요청도 추상화할 수 있습니다. 예를 들어, axios.get, axios.post 등을 아래와 같이 request.get, request.post 등으로 추상화합니다.

이렇게 하는 것도 좋지만 중요하게 고려해야 할게 있습니다. 사실 axios 자체적으로 충분히 추상화 되어있지 않은지 고민해볼 필요가 있습니다.

극단적으로 이런 추상화라면 큰의미가 없습니다. 이름이 바뀐거 말곤 다른 장점이 없기 때문입니다. 예를 들어,

axiosfetch로 바꾸고자 한다면 단순히 도구를 바꾸는 수준에서 해결할 수 없습니다. 왜냐하면 argsaxios의 요청 구조에 강하게 의존적이기 때문입니다. 따라서

이렇게 되어있어야 우리 코드를 위한 추상화와 도구가 강하게 의존하지 않게 됩니다. 그리고 도구를 추상화(인터페이스)를 지킬 수 있도록 하는 수준에서 교체할 수 있게 됩니다.

이렇게 하면 위에 언급한 것 처럼 역시 테스트에서도 유용하게 활용할 수 있습니다.

--

--

이문기

사용자를 생각하고 개발자를 생각하는 프런트엔드를 만드는 데 관심이 많습니다. 표준, 접근성, 아키텍처, 테스트 등을 꾸준히 훈련하고 적용하려고 노력합니다.