GraphQL **프래그먼트(Fragment)**는 쿼리에서 공통 필드를 재사용할 수 있도록 도와주는 기능입니다. 큰 쿼리나 여러 쿼리에서 동일한 필드를 반복적으로 요청할 때 코드 중복을 줄이고, 유지보수성을 높일 수 있는 중요한 기능입니다.
프래그먼트를 사용하면 여러 쿼리나 뮤테이션에서 자주 사용하는 필드들을 하나의 프래그먼트로 정의하고, 그 프래그먼트를 다른 쿼리 내에서 호출함으로써 일관성을 유지할 수 있습니다. 특히 큰 애플리케이션에서 여러 곳에서 동일한 데이터를 요청할 때 매우 유용합니다.
1. 프래그먼트 기본 개념
프래그먼트는 GraphQL 쿼리나 뮤테이션에서 중복되는 필드를 하나로 묶어, 여러 곳에서 재사용할 수 있도록 하는 일종의 모듈화된 쿼리 블록입니다.
기본 구조:
fragment FragmentName on TypeName {
field1
field2
field3
}
FragmentName
: 프래그먼트의 이름입니다.on TypeName
: 프래그먼트를 적용할 GraphQL 타입을 명시합니다. 예를 들어, 특정 객체 타입(User, Post 등)에만 해당 필드를 사용할 수 있도록 지정합니다.field1, field2, field3
: 재사용할 필드 목록입니다.
2. 프래그먼트 사용 예시
1) 기본 프래그먼트 정의
다음은 User 타입에 대한 필드를 프래그먼트로 정의하는 예시입니다. id
, name
, email
같은 필드가 여러 쿼리에서 공통으로 사용될 경우, 이를 프래그먼트로 정의하고 재사용할 수 있습니다.
fragment UserInfo on User {
id
name
email
}
2) 프래그먼트 사용하기
프래그먼트는 쿼리에서 재사용할 수 있습니다. 예를 들어, 사용자 목록을 요청하는 쿼리와 특정 사용자를 요청하는 쿼리에서 동일한 id
, name
, email
필드를 사용하고 싶다면, 프래그먼트를 다음과 같이 적용할 수 있습니다.
사용자 목록을 가져오는 쿼리:
query {
users {
...UserInfo
}
}
특정 사용자를 가져오는 쿼리:
query {
user(id: 1) {
...UserInfo
}
}
두 쿼리 모두 ...UserInfo
를 통해 id
, name
, email
필드를 요청합니다. 프래그먼트를 사용하면 코드 중복을 줄일 수 있고, 필드가 변경되었을 때 프래그먼트만 수정하면 모든 쿼리가 함께 반영됩니다.
3. 중첩 프래그먼트
프래그먼트는 다른 프래그먼트 안에서 사용할 수도 있습니다. 이를 통해 더 복잡한 구조에서도 재사용성을 극대화할 수 있습니다.
예시:
사용자(User)와 그 사용자가 작성한 게시물(Post)를 요청한다고 가정해 보겠습니다. 각 사용자는 여러 개의 게시물을 가지고 있고, 게시물 정보에도 공통 필드가 있을 수 있습니다.
UserInfo 프래그먼트:
fragment UserInfo on User {
id
name
email
posts {
...PostInfo
}
}
PostInfo 프래그먼트:
fragment PostInfo on Post {
id
title
content
}
쿼리:
사query {
users {
...UserInfo
}
}
이 경우, UserInfo
프래그먼트 안에 PostInfo
프래그먼트를 중첩하여, 사용자 정보와 함께 게시물 정보를 가져옵니다.
4. 프래그먼트의 장점
1) 코드 중복 제거
프래그먼트를 사용하면 쿼리에서 중복되는 필드를 하나로 정의해 재사용할 수 있습니다. 동일한 필드를 여러 쿼리에서 중복 작성하는 대신, 프래그먼트를 한 번 정의해두고 모든 곳에서 재사용할 수 있기 때문에 코드가 간결해집니다.
2) 유지보수성 향상
프래그먼트를 사용하면 특정 필드가 변경되었을 때, 각 쿼리에서 필드를 일일이 수정할 필요 없이 프래그먼트만 수정하면 됩니다. 필드가 변경되면 그 프래그먼트를 사용하는 모든 쿼리에 자동으로 반영됩니다.
3) 큰 쿼리의 가독성 개선
대규모 애플리케이션에서는 쿼리가 복잡하고 커질 수 있습니다. 이때 프래그먼트를 사용하면 필드들을 모듈화하여 쿼리의 가독성을 높일 수 있습니다. 필요한 부분을 프래그먼트로 분리해 관리함으로써, 쿼리의 길이가 길어지는 문제를 해결할 수 있습니다.
5. 프래그먼트의 단점 및 고려사항
1) 오버페칭 가능성
프래그먼트는 재사용성을 극대화하기 위한 도구이지만, 때로는 필요하지 않은 데이터를 포함할 수 있습니다. 즉, 쿼리에서 오버페칭(over-fetching) 문제가 발생할 수 있습니다. 프래그먼트가 포함된 모든 필드를 항상 요청하는 구조이기 때문에, 일부 쿼리에서 불필요한 필드를 가져올 수 있습니다.
이를 방지하기 위해, 필요한 필드만 정확하게 가져오는지를 신경 써서 프래그먼트를 설계해야 합니다. 너무 많은 필드를 프래그먼트로 묶어두면, 각 쿼리에서 실제 필요한 데이터보다 많은 데이터를 요청할 수 있기 때문입니다.
2) 타입 의존성
프래그먼트는 특정 GraphQL 타입에 종속적입니다. 즉, on TypeName
으로 정의된 타입에서만 프래그먼트를 사용할 수 있습니다. 만약 타입이 변경되거나 다른 타입에서 동일한 필드를 사용해야 한다면, 새로운 프래그먼트를 정의해야 할 수 있습니다.
6. 실습: 프래그먼트 사용 예시
예시 시나리오
- 사용자 정보와 그 사용자가 작성한 게시물 정보를 가져오는 쿼리에서 프래그먼트를 사용합니다.
- 사용자는
id
,name
,email
정보를 가지고 있고, 게시물은id
,title
,content
를 가지고 있습니다.
프래그먼트 정의:
graphql코드 복사# User 정보를 위한 프래그먼트
fragment UserInfo on User {
id
name
email
}
# Post 정보를 위한 프래그먼트
fragment PostInfo on Post {
id
title
content
}
쿼리 사용 예시:
query {
users {
...UserInfo
posts {
...PostInfo
}
}
}
이 쿼리는 각 사용자와 그 사용자가 작성한 게시물을 프래그먼트를 사용해 가져옵니다. ...UserInfo
와 ...PostInfo
는 각각의 프래그먼트를 사용하여 정보를 요청합니다.
7. 프래그먼트가 유용한 상황
- 반복적인 데이터 구조: 동일한 데이터를 여러 쿼리에서 반복해서 요청해야 할 때.
- 공통 필드 관리: 데이터 모델이 바뀌었을 때, 여러 쿼리에서 중복된 필드를 수정할 필요 없이 프래그먼트만 수정할 수 있어 일관성을 유지할 수 있습니다.
- 모듈화 필요: 큰 쿼리를 여러 프래그먼트로 분리해 가독성을 개선하고, 모듈화된 쿼리 구조를 만들 때 유용합니다.
결론
프래그먼트는 GraphQL 쿼리에서 코드 중복을 줄이고, 일관성을 유지하며, 쿼리의 가독성과 유지보수성을 높이는 중요한 도구입니다. 그러나, 너무 광범위한 필드를 프래그먼트로 묶어버리면 오버페칭 문제가 발생할 수 있으니, 실제로 필요한 필드를 신중하게 선택해 프래그먼트를 설계하는 것이 중요합니다.