Programing/GraphQL

세무민의 코딩일기 : Spring Boot + GraphQL 연결하기

세기루민 2022. 5. 1. 14:59
728x90

안녕하세요 세기무민입니다. 

이번 포스팅에서는 Spring Boot와 GraphQL을 사용해보도록 하겠습니다. 


GraphQL?

GraphQL은 페이스북에서 만든 쿼리 언어입니다. 

GrahpQl은 웹 클라이언트가 데이터를 서버로부터 효율적으로 가져올 수 있도록 되어있습니다.

REST API의 경우는 다양한 EndPoint가 존재한다면 GraphQL은 하나의 EndPoint를 가집니다. 

즉 기존에 Url을 보면 이해하기 쉽다. 

Rest Api의 경우는 /newPost, /comments, /user 등 다양한 endPoint를 가지지만 

gql(GraphQL)은 /graphql 하나의 endpoint 만으로도 사용이 가능하다는 점이다. 

 

GraphQL | A query language for your API

Evolve your APIwithout versions Add new fields and types to your GraphQL API without impacting existing queries. Aging fields can be deprecated and hidden from tools. By using a single evolving version, GraphQL APIs give apps continuous access to new featu

graphql.org

자세한 레퍼런스는 위의 링크에서 확인 가능합니다. 

 

Spring Boot + GraphQL 연결하기

 

1. Spring Boot 프로젝트 생성하기

우선 Spring Boot 프로젝트를 생성해줍니다. 

dependencies는 추후에 추가 가능하기 때문에 우선 기본적인 web과 jpa, devTools만 추가해줍니다.

그리고 저의 프로젝트 구조는 위와 같습니다. 

제가 생각한 GraphQL의 장점 중 하나는 Controller를 따로 만들지 않아도 호출이 가능하다는 점이기도 하고

리졸버를 사용하여 데이터베이스에서 데이터를 가져올 수 있는 점도 매력적인거 같습니다.  

그래서 Entity(Domain), Repository, GraphQl 3가지의 패키지로만 구성하였고 

대신 resources 폴더에 Graphqls라는 패키지를 구성하고 .graphqls 파일을 생성해줍니다. 


2. build.gradle 설정

implementation 'com.graphql-java-kickstart:graphql-spring-boot-starter:11.0.0'
testImplementation 'com.graphql-java-kickstart:graphql-spring-boot-starter-test:11.0.0'

build.gradle에 위와 같이 graphQL 속성을 추가해줍니다. 

3. application.properties 설정

graphql.servlet.mapping=/graphql
graphql.tools.schema-location-pattern=**/*.graphqls
graphql.servlet.cors-enabled=true
graphql.servlet.max-query-depth=100
graphql.servlet.exception-handlers-enabled=true

graphql의 스키마 위치부터 맵핑까지 속성들을 설정해줍니다. 

스키마 위치를 설정해주지 않으면 resource 아래에 graphql 패키지와 .graphqls 파일을 찾아가지 못하기 때문에 

이부분을 꼭 추가해주셔야 합니다.(추가 안하는 경우 오류 뜰꺼에요..ㅎ)

4. member.graphqls 생성

schema {
    query: Query,
    mutation: Mutation,
}

type Mutation {
    registerMember(membersn: Int!, memberid: String!, memberemail: String!, membernumber: String!): Member
    deleteMember(memberid: String!): Boolean
}

type Query{
	findMembers(memberid: String!): Member!
	allFindMembers: [Member]
}

type Member{
	membersn: Int
	memberid: String
	memberemail : String
	membernumber : String
}

Query와 Mutation의 차이는 쉽다. 

Query 유형의 경우는 서버에게 데이터를 요청하여 호출 받는 것이라면 

Mutation의 경우 서버에게 데이터를 수정하기 위해 사용되는 것을 말한다.

따라서 Query 유형에서 조회, Mutation 유형에서는 생성 및 삭제, 수정 연산에서 사용된다고 보면된다. 

5. Domain / graphql 패키지 생성

[member.class]

@Builder
@Setter
@Getter
@AllArgsConstructor
@NoArgsConstructor
@Entity(name="member")
public class Member{
    
    @Id
    @Column(nullable = false)
    private int membersn;
    
    @Column(nullable = false)    
    private String memberid;
    
    @Column(nullable = false)
    private String memberemail;
    
    @Column(nullable = false)
    private String membernumber;
}

member entity를 생성해줍니다. 

jpa를 사용하기 때문에 db의 테이블의 컬럼과 동일하게 생성해주었습니다. 

[MemberQuery.class]

@Service
@RequiredArgsConstructor
public class MemberQuery implements GraphQLQueryResolver{
	
	private final MemberRepository memberRepository;
	
	public Member findMembers(String memberId) {

		List<Member> members = memberRepository.findAll();
		Member member = new Member();
		for(Member newMember : members) {
			if(newMember.getMemberid().equals(memberId)) {
				member = memberRepository.findById(newMember.getMembersn())
						.orElse(null);
			}
		}
		return member;
	}
	
	public List<Member> allFindMembers(){
		
		List<Member> member = memberRepository.findAll();
		
		return member;
	}
}

member.graphqls에 있는 query에 생성한 대로 동일하게 만들어 주었습니다. (조회 로직)

기존에는 controller -> service -> repository 구조로 데이터를 호출 및 받아오는 과정이였다면 

grapql을 통해 member.graphqls -> resolver -> repostory로 데이터를 받아온다고 보면 된다. 

리졸버는 gql의 경우 데이터를 가져오는 과정을 구체적으로 구현해야 하는데 

이러한 부담감을 리졸버를 통해서 해결해준다고 보면 됩니다. 

필드의 타입이 우리가 정의한 타입인 경우 해당 타입의 리졸버를 호출하여 사용하면 되고 

이런 방법을 통해 쿼리 관리가 쉽고 효율적인 처리가 가능합니다. 

[MemberMutation.class]

@Service
@RequiredArgsConstructor
public class MemberMutation implements GraphQLMutationResolver {

	private final MemberRepository memberRepository;
	
	public Member registerMember(int memberSn, String memberId, String memberEmail, String memberNumber) {
		
		Member newMember = Member.builder()
				.membersn(memberSn)
				.memberid(memberId)
				.memberemail(memberEmail)
				.membernumber(memberNumber).build();
		
		return memberRepository.save(newMember);
	}

	
	public Boolean deleteMember(String memberId) {
		List<Member> memberList = memberRepository.findAll();
		int deleteChk = 0;
		
		for(Member member : memberList) {
			if(member.getMemberid().equals(memberId)) {
				memberRepository.delete(member);
				deleteChk += 1;
			}
		}
		
		if(deleteChk > 0) {
			return true;
		} else {
			return false;			
		}
	}

}

member.graphqls에 있는 mutation에 생성한 대로 동일하게 만들어 주었습니다. (생성, 수정, 삭제 로직)

6. 실행 및 테스트 (postman)

graphQL 연결이 잘 되었는지 확인하기 위해 저는 PostMan을 통해 진행하였습니다.

[Query -> allFindMembers]

전체 맴버 조회가 가능하다.

[Query -> allFindMembers]

특정 맴버(sg-moomin)도 검색이 가능하다

[Mutation -> registerMember]

맴버 생성도 위와 같이 생성된다. 

[Mutation -> deleteMember]

맴버 삭제도 위와 같이 생성된다. 

GitHub 코드 및 마무리
 

GitHub - sg-moomin/graphQL_study

Contribute to sg-moomin/graphQL_study development by creating an account on GitHub.

github.com

자세한 코드는 위의 링크에서 확인 가능합니다.


이번에 Spring Boot + GraphQL 연결하여 사용해봤는데 

생각보다 어렵기도 했지만 편리하다는 느낌이 컸습니다. 

코드도 깔끔해지는 느낌도 들었고 확실히 Back API 개발 할 때 편리하겠다는 생각이...ㅎ

그리고 삽질 덕분에 이번주말 공부를 열심히 한 느낌도 들어서 뿌듯..ㅎ

무튼 다음 포스팅에서는 더 유익한 정보로 찾아오겠습니다. 

 

728x90