프론트엔드 개발 문제 해결
GitLab v19.1문제가 생겼나요? 이 가이드에 없는 프론트엔드 개발 문제를 겪었다면, 해당 문제와 가능한 해결책을 이 가이드에 추가하는 것을 고려해 보세요. 이 문제는 Vue 컴포넌트 테스트에서 기대값이 실패할 때 발생할 수 있습니다.
문제가 생겼나요? 이 가이드가 도움이 될 수도 있습니다 ¯\_(ツ)_/¯.
문제 해결#
이 가이드에 해당 문제가 없는 경우#
이 가이드에 없는 프론트엔드 개발 문제를 겪었다면, 해당 문제와 가능한 해결책을 이 가이드에 추가하는 것을 고려해 보세요. 이렇게 하면 미래의 개발자들이 여러분의 경험과 지식으로 무장하여 이러한 어려움을 더 잘 극복할 수 있습니다.
테스트 문제#
nodeType 속성 또는 메서드가 정의되지 않았지만 코드에서 nodeType을 사용하지 않는 경우#
이 문제는 Vue 컴포넌트 테스트에서 기대값이 실패할 때 발생할 수 있습니다. Jest가 콘솔에서 diff를 pretty print하려고 할 때 오류가 발생하는 것입니다. 배열을 속성으로 사용하는 toEqual을 사용하는 것도 원인 중 하나일 수 있습니다.
자세한 개요와 조사 내용은 이 영상을 참조하세요.
해결 방법 - Vue 워처가 있는 객체를 클론해 보세요
- expect(wrapper.findComponent(ChildComponent).props()).toEqual(...);
+ expect(cloneDeep(wrapper.findComponent(ChildComponent).props())).toEqual(...)
해결 방법 - toEqual 대신 toMatchObject를 사용해 보세요
- expect(wrapper.findComponent(ChildComponent).props()).toEqual(...);
+ expect(wrapper.findComponent(ChildComponent).props()).toMatchObject(...);
toMatchObject는 어설션의 성격을 실제로 변경하며, 기대값에서 일부 항목이 누락되어 있어도 실패하지 않습니다.
스크립트 문제#
GitLab 리포지터리 내 스크립트 실행 시 core-js 오류#
아래 명령은 GitLab 리포지터리가 ~/workspace/gdk 디렉터리에 설정되어 있다고 가정합니다. 코드 변환과 같이 GitLab 리포지터리 내에서 스크립트를 실행할 때 다음과 같은 core-js 관련 문제가 발생할 수 있습니다:
~/workspace/gdk/gitlab/node_modules/core-js/modules/es.global-this.js:7
$({
^
TypeError: $ is not a function
at Object.<anonymous> (~/workspace/gdk/gitlab/node_modules/core-js/modules/es.global-this.js:6:1)
at Module._compile (internal/modules/cjs/loader.js:1063:30)
at Module._compile (~/workspace/gdk/gitlab/node_modules/pirates/lib/index.js:99:24)
at Module._extensions..js (internal/modules/cjs/loader.js:1092:10)
at Object.newLoader [as .js] (~/workspace/gdk/gitlab/node_modules/pirates/lib/index.js:104:7)
at Module.load (internal/modules/cjs/loader.js:928:32)
at Function.Module._load (internal/modules/cjs/loader.js:769:14)
at Module.require (internal/modules/cjs/loader.js:952:19)
at require (internal/modules/cjs/helpers.js:88:18)
at Object.<anonymous> (~/workspace/gdk/gitlab/node_modules/core-js/modules/esnext.global-this.js:2:1)
해결 방법 - 스크립트를 별도의 리포지터리로 이동하고 GitLab 리포지터리의 파일을 가리키도록 해보세요
Vue 컴포넌트 사용 문제#
GlFilteredSearch를 사용하는 컴포넌트를 렌더링하고 해당 컴포넌트 또는 부모가 Vue Apollo를 사용하는 경우#
GlFilteredSearch 컴포넌트를 렌더링하려고 할 때 컴포넌트의 provide 함수에서 다음 오류가 발생할 수 있습니다:
cannot read suggestionsListClass of undefined
현재 vue-apollo는 컴포넌트 라이프사이클의 beforeCreate 부분에서 컴포넌트의 provide()를 수동으로 호출하려고 합니다. 이는 provide()가 created 이후에 설정되는 props를 참조할 때 오류가 발생한다는 것을 의미합니다.
자세한 내용은 이 닫힌 머지 리퀘스트를 참조하세요.
해결 방법 - 최상위 Vue 인스턴스 옵션에 apolloProvider를 제공해 보세요
VueApollo는 $options에 apolloProvider가 제공된 것을 확인하면 provide()를 수동으로 실행하는 것을 건너뜁니다.
new Vue(
el,
+ apolloProvider: {},
render(h) {
return h(App);
},
);
Apollo Client 문제 해결#
캐시 쓰기 시 콘솔 오류#
Missing field 'descriptionHtml' while writing result와 같은 오류가 보인다면, Apollo 클라이언트 캐시에 쓸 때 GraphQL 응답 구조를 준수하지 않고 있다는 의미입니다. 웹 애플리케이션 내에서 Apollo Client의 캐시 및 데이터 업데이트 처리 방식과 관련된 GraphQL 오류("Missing field 'description'")가 발생하고 있는 것 같습니다. 오류 스택 트레이스는 문제가 발생하는 Apollo Client 코드의 특정 부분에 대한 단서를 제공합니다.
핵심 문제:
"Missing field 'description'" 오류는 GraphQL 쿼리가 응답에서 "description"이라는 필드를 기대하는데, 백엔드에서 받은 데이터(또는 Apollo Client가 처리하는 방식)에 해당 필드가 없다는 것을 나타냅니다. 이로 인해 Apollo Client의 캐시가 불완전한 데이터로 스토어를 업데이트하려고 할 때 실패하게 됩니다.
이를 디버깅하려면 아래 단계를 따르세요.
- 개발자 콘솔에서 오류 스택을 열어보세요
Missing field 'description' while writing result {
"type": "DESCRIPTION",
"lastEditedAt": null,
"lastEditedBy": null,
"taskCompletionStatus": null,
"__typename": "WorkItemWidgetDescription"
}
-
GraphQL 쿼리를 다시 확인하여 "description" 필드를 요청하고 있는지 확인하세요. 포함되어 있지 않으면 Apollo Client는 응답에서 해당 필드를 찾을 수 없습니다.
-
백엔드가 "WorkItemWidgetDescription" 타입의 응답에서 "description" 필드를 반환하지 않을 수 있습니다. 백엔드 API가 예상대로 데이터를 올바르게 전송하고 있는지 확인하세요.
-
cache.readQuery메서드를 사용하여 Apollo Client 캐시의 내용을 검사하세요. 관련 쿼리에 대한 캐시된 데이터에 "description" 필드가 있는지 확인하세요. -
오류 스택 트레이스를 열면 Apollo Client가 캐시에 데이터를 쓰는 방식과 관련된 문제일 수 있음을 알 수 있습니다. 캐시가 올바르게 업데이트되지 않아 필드가 누락될 가능성이 있습니다.
-
Apollo Client 코드 내에(예: 캐시 쓰기 전후에) 콘솔 로그를 추가하여 처리되는 데이터를 추적하고 "description" 필드가 누락될 수 있는 위치를 파악하세요.
해결 방법
Apollo Client 코드에서 올바른 writeQuery 또는 writeFragment 메서드를 사용하여 "description" 필드를 포함한 완전한 데이터로 캐시를 업데이트하고 있는지 확인하세요.
스택 트레이스에서 이 오류가 발생하는 메서드를 확인할 수 있을 것입니다. 캐시에 쓸 때 "description" 필드를 반드시 추가하세요.
동일한 변수로 쿼리가 캐시되지 않는 경우#
Apollo GraphQL 쿼리가 여러 시나리오에서 캐시되지 않을 수 있습니다:
- 캐시 미스 또는 부분 캐시/쿼리 무효화 또는 변경: 쿼리가 부분 데이터만 반환하거나 캐시 미스(요청한 데이터의 일부가 캐시에 없는 경우)가 발생하면, Apollo가 결과를 효과적으로 캐시하지 못할 수 있습니다.
쿼리와 관련된 데이터가 무효화되거나 업데이트된 경우 캐시에 유효한 정보가 없을 수 있습니다. 예를 들어:
뮤테이션을 사용할 때, refetchQueries를 구성하거나 뮤테이션 후 수동으로 캐시를 업데이트하지 않으면 캐시가 자동으로 업데이트되지 않을 수 있습니다.
예를 들어, 첫 번째 쿼리에 후속 쿼리에서 요청하지 않은 몇 가지 필드가 있는 경우:
query workItemTreeQuery($id: WorkItemID!, $pageSize: Int = 100, $endCursor: String) {
workItem(id: $id) {
namespace {
id
}
userPermissions {
deleteWorkItem
updateWorkItem
}
}
}
query workItemTreeQuery($id: WorkItemID!, $pageSize: Int = 100, $endCursor: String) {
workItem(id: $id) {
namespace {
id
+ fullPath
}
userPermissions {
deleteWorkItem
updateWorkItem
+ adminParentLink
+ setWorkItemMetadata
+ createNote
+ adminWorkItemLink
}
}
}
-
fetchPolicy설정: Apollo Client는 fetchPolicy를 사용하여 쿼리가 캐시와 상호 작용하는 방식을 제어합니다. 정책에 따라 fetchPolicy가no-cache인 경우 쿼리가 캐싱을 완전히 건너뛸 수 있습니다. 이 정책은 쿼리의 어떤 부분도 캐시에 쓰여지지 않도록 합니다. 각 쿼리는 서버에서 직접 데이터를 가져오며 결과를 캐시에 저장하지 않으므로 여러 쿼리가 가져와집니다. -
서로 다른 Apollo Client 인스턴스에서 동일한 쿼리가 실행되는 경우. 두 쿼리를 실행하는 클라이언트가 서로 다른 클라이언트일 수 있습니다.
-
id또는__typename누락: Apollo Client는id와__typename을 사용하여 엔티티를 고유하게 식별하고 캐시합니다. 이러한 필드가 쿼리 응답에 없으면 Apollo가 결과를 제대로 캐시하지 못할 수 있습니다. -
복잡하거나 중첩된 쿼리: 일부 쿼리는 너무 복잡하거나 Apollo Client가 올바르게 캐시하기 어려운 중첩 쿼리를 포함할 수 있습니다. 반환된 데이터의 구조가 캐시 스키마에 깔끔하게 매핑되지 않아 수동 캐시 관리가 필요한 경우 이런 일이 발생할 수 있습니다.
-
페이지네이션 쿼리:
fetchMore를 사용하는 것과 같이 페이지네이션을 포함하는 쿼리의 경우, 캐시를 명시적으로 업데이트하지 않으면 Apollo가 결과를 제대로 캐시하지 못할 수 있습니다.
이러한 모든 경우에 쿼리 캐싱을 효과적으로 처리하려면 Apollo의 캐시 정책을 구성하거나 수동으로 캐시를 업데이트해야 할 수 있습니다.