Coder Social home page Coder Social logo

terry960302 / sample-spring-graphql Goto Github PK

View Code? Open in Web Editor NEW
4.0 2.0 0.0 120 KB

(Kotlin, SpringBoot, DGS graphql)Spring Boot + Graphql 을 학습하기 위해 넷플릭스 DGS 프레임워크를 적용하여 프로젝트를 만들었습니다. 사이드프로젝트에 적용하기 위해 공부용으로 제작했습니다.

Kotlin 100.00%
codegen coroutines dataloader dgs filter graphql kotlin many-to-many netflix postgresql

sample-spring-graphql's Introduction

Sample-Spring-Graphql-Project (feat.Netflix DGS)

Background

: 2022.11월 기준으로 들어가는 사이드프로젝트에 사용할 기술스택으로 graphql이 선정되었고 기존에 spring에 대한 지식을 쌓는게 목적에 있었으므로 DGS를 체택 후 공부용으로 제작했습니다. 기획서가 나오기까지 3일 남은 시점에서 짧은 기간동안 빠르게 학습하다보니 코드의 가독성은 약간 떨어질 수 있는 점 양해바랍니다.(나머진 사프하면서 학습....)

ERD

: https://github.com/terry960302/sample-spring-webflux-pattern 에서 사용했던 같은 스키마 구조를 ORM으로 녹였습니다. 최대한 시간을 절약하기 위해.ㅎㅎ

  • UserCredential, CredentialRole, AccountRole 테이블이 Security 기능을 온전히 구현하기 위해 추가되었습니다.

Issues

  • MappedBatchLoader with default value

    // common function example used in dataloader
      fun getAccountRolesByCredentialIds(ids: List<Long>): MutableMap<Long, List<AccountRole>> {
        val roles: List<CredentialRole> = credentialRoleRepository.getCredentialRolesByCredentialIds(ids)
        return roles.groupBy { it.userCredential!!.user!!.id } 
            .map { uc -> uc.key to uc.value.map { cred -> cred.accountRole!! } }.toMap().toMutableMap()
    }
    But `groupBy` method not include all ids. 
    
    Some accountRoles entities under credential entity will set to be `null`.
    But we want it be `empty list`.
    
    So made `groupFillBy` method.
    // use this function
    inline fun <T, K> Iterable<T>.groupFillBy(keys : Iterable<K>, keySelector: (T) -> K): Map<K, List<T>> {
        val groups = LinkedHashMap<K, MutableList<T>>()
        for (key in keys){
            groups[key] = mutableListOf()
        }
        for (element in this) {
            val key : K = keySelector(element)
            val list = groups.getOrPut(key) { ArrayList<T>() }
            list.add(element)
        }
        return groups
    }

Need to Study

  • Setup DGS
    • [Issue] graphql.java library version conflict issue => resolved
  • Relations (1:1, 1:N, N:N) using JPA
    • Implement N:N relation using double OneToMany in (Posting & PostingImage & Image) if want to set extra column in JoinTable
    • Fetch extra custom fields with entity not in DB columns using @Transient & @Postload annotations
  • Apply DataFetcher
  • Apply DataLoader in join column
    • [Performance Tested] getAllPostings : 2 posting each has 500 images => fast enough
    • [Performance Tested] getAllPostings : 100 postings each has 500 images => 1300ms
    • [Performance Tested] getAllPostings(+pagination) : 10 postings each has 100 images(normal use case in production) => 111ms
    • [Performance Tested] getAllPostings(+pagination) : 10 postings each has 100 images with 10 comments => 180ms
  • Aggregate(Count) field
    • aggregate용 쿼리를 따로 제작(기존 쿼리안에 _count 필드로 녹이는 법은 반환 객체를 감싸는 객체를 만든 후, 거기에다 _count를 넣으면 되지만 filter나 input에 대해 분기처리가 많아지는 경우 로직이 복잡해지기 쉽고, 개인적으로 프론트에서 작업할 때도 독립적인 query로 가져오는 방식을 더 사용하게 됨. 성능적인 이슈도 존재)
  • Pagination(Pageable), OrderBy(Sort) etc.. Filter input
  • Security
    • Single Endpoint authentication(그래프큐엘이 단일 엔드포인트이기 때문에)
    • Query, Mutation authentication, authorization using 'Pre-Authorize'(쿼리별로 보안 설정)
    • Jwt stateless authentication, authorization(세션이 아닌 Jwt 토큰 방식 사용)
    • Set auth related db tables in entities, graphql schemas(단순히 인메모리 데이터가 아닌 ERD 적용하여 디비 데이터를 테스트에 사용)
  • Instrumentation(logging, metrics) => check turnaround per each method

ENV

dgs:
  graphql:
    graphiql:
      title: "Sample-Spring-Graphql"
      enabled: true
    path: /graphql/**
server:
  host: localhost
  port: 8000

spring:
  datasource:
    driver-class-name: org.postgresql.Driver
    url: jdbc:postgresql://localhost:5432/postgres
    username: postgres
    password: postgres
  jpa:
    open-in-view: true
    hibernate:
      ddl-auto: create-drop # create-drop, create, update, validate, none
      naming:
        physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
      use-new-id-generator-mappings: false
    show-sql: true
    properties:
      hibernate:
        format_sql: true
      dialect: org.hibernate.dialect.PostgreSQLDialect

logging:
  level:
    org.hibernate.SQL: debug
    org.hibernate.type: trace

References

sample-spring-graphql's People

Contributors

terry960302 avatar

Stargazers

 avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

sample-spring-graphql's Issues

BCryptPasswordEncoder encode 이슈

안녕하세요 spring, graphql, dgs 찾아보다가 오게되었습니다.

테스트해보던중 CredentialService.signIn 에 password 비교부분에 아래 블로그 내용과 동일한 문제가 있는거 같아요

passwordEncoder.matches(password, userCred.get().password) 비교하게 변경해보니 잘되는것 같습니다.

작성해주신 sapmle로 많이 도움이되었습니다. 재미있게 보고 갑니다 감사합니다.

참조 : https://cantcoding.tistory.com/69

원인
원인을 파악하기 위해 여러가지를 찍어보던중 해쉬로 encode되는 값이 매번 달라지는 것을 알아냈다.
System.out.println(result.getPassword());
System.out.println(bCryptPasswordEncoder.encode("12345"));
같아야 하는 값이 계속 다르게 출력되고 있었다. 그래서 BCrypt에 대해서 조사해봤다.
BCrypt는 해쉬에 솔트를 더하여 매번 다르게 값이 출력되게 만들어서 보안을 더 높인 암호화 방식이다.
따라서 솔트가 매번 다르기 때문에 encode된 값과 equals로 비교가 항상 다르기 때문에 테스트가 통과될 수 없는 구조였다. 해쉬를 하면 매번 같은 값이 나올것이라는 착각이였다.

해결방법
equals로 비교할 수 없는 BCryptPasswordEncoder은 비교 메서드 matches를 제공한다.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.