You are on page 1of 11

Šta je REST, a šta GraphQL?

Možda se odlučite za GraphQL kada budete radili neku od svojih budućih aplikacija nakon ovog
članka.

Uvod

Uvod u GraphQL i razlozi zašto ga koristiti

Neke od tema koje će bit obrađivane u ovom poglavlju možemo sažeti u nekoliko pitanja,
a koja ćemo objasniti kasnije. Ta pitanja bi bila:
● Jeste li ikada čuli za termin GraphQL? Ako i jeste možda niste sigurni baš o čemu se tu
radi?
● Jeste li pomislili kako je GraphQL neka vrsta Graph baze podataka?
● Ako znate ponešto o GraphQL, mislite li da je on zamjena za REST?
● Ko i kako može koristiti GraphQL (misli se na programska okruženja i jezike)?
● Umorni ste od održavanja REST-a i stalnog ponavljanja jedinsvenih (unit) i funkcionalnih
testova?

Ako ste na bilo koje od ovih pitanja odgovorili sa DA, vjerovatno je ovaj članak za vas, u
suprotnom možete ići piti kahvu s voljenom osobom, igrati igrica ili raditi nešto treće.

Postoji popriličan broj zabluda oko GraphQL-a, pa ćemo u ovom članku pokušati da ih
predstavimo i po mogućnosti otklonimo. To je tako vjerovatno zato što je veoma malo dobrih
članaka koji GraphQL objašnjavaju od nule, za totalne početnike. Uglavnom se sve nešto
podrazumijeva ili se priča previše apstraktno. Ovdje će se pokušati približiti GraphQL svima,
kako apsolutnim početnicima tako i onima koji imaju odgovarajuće znanje i iskustvo.

Pa krenimo redom. GraphQL je jezik upita (query language) koji je izradio Facebook za
njihove potrebe još sada već, u ovom informatičkom svijetu može se reći, davne 2012. godine.
Zatim su oni odlučiti da to otvore za javnost 2015 u posebnoj speficikaciji
(https://facebook.github.io/graphql/draft/). Iz dana u dan Facebook mobilne aplikacije za Android
i iOS postajale su, i postaju sve složenije i složenije što dovodi do velikih problema, mnogih
grešaka (bugs), pa tako i padova samih aplikacija, što naravno ni jednoj kompaniji, a posebno
ne nekoj kao što je Facebook nije u interesu. Iz svega toga rodila se ideja da se razdvoje podaci
od grafičkog dijela. Također, s GraphQL se dobio i jedan novi pogled, jedno novo razmišljanje o
podacima koji dolaze kao resursi s URL-ova u grafikone objekata i modela koji se koriste u
krajnjoj aplikaciji. Više o ovim nekim detaljima može se naći na Facebook blogu
(https://code.fb.com/core-data/graphql-a-data-query-language/).
U REST-u, svaki entitet se jednostavno identifikuje pomoću resursa, koji je definisan
URL-om preko HTTP(S) protokola. Kada bilo ko traži podatke pomoću URL-a, zahtjev se tipično
rješava na web serveru koji autentifikuje zahtjev, preuzima podatke, obrađuje ih i vraća rezultat
klijentu. GraphQL je veoma, veoma sličan REST-u. Koristi se za dohvaćanje podataka iz bilo
kog pozadinskog servisa (Neka relaciona tabela, NoSQL, File system, ili čak i sam REST) koji
su tipizirani i koji također pružaju mogućnost Statelessness1 i Cacheability2. Međutim, razlika je
u načinu na koji se ovi podaci dobijaju. Pošto je GraphQL objavljen kao specifikacija, moguće je
implementirati GraphQL server na programskom jeziku po želji.

GraphQL je koristan protokol koji svakako treba znati, čak i ako je ovo prvi susret s
nekim od protokola. Što bismo rekli, to je budućnost, ali možemo reći i da je to sadašnjost i to
veoma zaustupljena i popularna. REST nije preduslov za razumijevanje GraphQL-a. Ako ste
ikada prije koristili REST uvidjećete prednosti GraphQL-a, ali ako niste, ne brinite.

Zašto ili za šta koristiti GraphQL?


GraphQL pojednostavljuje radni proces za izgradnju klijentskih aplikacija kao što su iOS,
Android i/ili React-Native. Skoro svaka ozbiljna firma s ozbiljnim proizvodom ima ili želi imati
mobilnu aplikaciju i intenzivno ulažu u više-platformne (cross-platform) aplikacije. Interakcija
korisnika sa proizvodima i uslugama se značajno povećava ako korisnici imaju pristup putem
pametnih telefona što naravno kompanije žele iskoristiti i povećati prihode. Danas u svijetu ima
više od 2,5 milijarde korisnika pametnih telefona a taj broj će svakako rasti. Broj će rasti ne
samo kod korisnika mobilnih, pametnih telefona nego i ostalih pamethih uređaja. Kako se broj
korisnika povećava dolazi do novih problema, zato je veoma važno da aplikacije osim što
trebaju biti brzo napravljene, lagano održavane, moraju biti prilagodljive i s slabom latencijom3.
Na osnovu svih ovih zahtjeva može se reći da je GraphQL idealan alat ako se nađe pri ruci za
pomoć kod njihovog rješavanja. Pomaže klijentima da dobiju odgovarajuću (ni preveliku, ni
premalu) količinu podataka potrebnih za prikaz. GraphQL omogućava klijentima (misli se na
serverske klijente, kao što su mobilne aplilkacije) da definišu oblik odgovora za svaki
pojedinačni zahtjev. Pored toga, uklanja kompleksnost API Endpoint menadžmenta, jer se
obično jedan HTTP Endpoint izlaže za dohvaćanje podataka.

1
​Najjednostavnije objašnjenje je: Ne čuva se nikakva sesija na serveru tokom zahtjeva. To u
osnovi znači da server ne zna ništa o klijentu nakon što se upit završi.
2
​Podrazumijeva da je moguće napraviti keš (ne, nisu pare u pitanju, ovdje se misli na prostor na
HDD ili RAM memoriji gdje pretraživač čuva kopije posjećenih veb stranica).
3
​Vrijeme na koje se čeka od trenutka kada se pošalje zahtjev pa dok se ne dobije odgovor.
Veoma često se koristi kada se spominje satelitski internet, ili kada se govori o mobilnim
aplikacijama.
GraphQL ublažava probleme s pretjeranim ili nedovoljnim
unosom podataka
Zamislimo da izrađujemo mobilnu aplijaciju s kojom ćemo prikazivati fudbalske timove
svjetskog (ili trećeligaškog mahalskog, nebitno je) prvenstva grupisane po podjelama kako to
inače biva. Kada se prikaže lista timova, želi se preći na drugi prikaz s više detalja o timu,
položaju igrača i slično. Ovakva aplikacija se može bez problema napraviti uz pomoć REST-a i
imali bismo tu otprillike slijedeće URL-ove (koji su nadamo se samoopisujući):
GET​ api/teams

GET​ api/teams/1

GET​ api/teams/2

...

Ako se žele dohvatiti detalji za svakog pojedinačnog igrača, onda bi se trebala tražiti
lista, npr:
GET​ api/teams/1/roster

Zvuči jednostavno zar ne? Gdje je taj milioner koji je ovo riješio?

Ako je naša izgradnja platforme bazirana na REST API, onda bismo i eventualno web
stranicu koju imamo gradili na REST API. Naravno, pošto je to web stranica, tu je moguće
prikazati mnogo više podataka nego na tabletu, ili recimo mobitelu, a da i ne govorimo o nekom
pametnom satu. Sada bismo se vratili na naš REST i jednostavno dodali više podataka koji su
neophodni za web stranicu. Međutim, to znači da će mobilne aplikacije dobijati mnoštvo
beskorisnih podataka, a što će povećati latenciju, usporiti aplikaciju, povećati prenos podataka
preko mobilne mreže i slično. Nadalje kada se koristi REST API neizostavan je tzv N+1 problem
4
.

4
​Ne postoji neka posebna definicija, ali može se opisati kroz primjer. Npr, zamislimo da pravimo
upit na bazu podataka da dobavimo sve automobile, zatim to vrtimo kroz neku petlju (for, while,
foreach) i za svaki korak petlje pravimo novi upit kako bismo dobavili još dodatnih podataka za
svaki pojedinačni automobil na osnovu trenutnog ID-a. Ovaj problem se naziva N+1 problem.
Da bi se riješio navedeni problem, može se jednostavno prije petlje pozvati novi upit na bazu i
tražiti da se vrati lista dodatnih podataka za listu ID-ova koje smo dobili iz liste automobila.
Menadžment Endpoint API-ja
Onima koji imaju iskustvo reći će kako je iznad spomenuti problem veoma jednostavno
riješiti tako što će se razdvojiti REST API za mobilne aplikacije i za web strancie. Da, to je istina!
Ali sada imamo najmanje duplo više API Endpoint-a, što usložnjava održavanje, unaprjeđenje,
testiranje, postavke sigurnosti i ostalo. Ovo je moguće riješiti na način tako da klijentska
aplikacija ustvari kaže koji joj podaci trebaju. Na taj način bi se izbjeglo dupliranje, tripliranje,
Endpoint API-ja. I tu na snagu stupa GraphQL s kojim se dobija samo jedan Endpoint za cijelu
aplikaciju. Zvuči čudno ili nemoguće? Ako vam je ovo do sada zagolicalo maštu, nastavite čitati.

S GraphQL-om se izbjegavaju višestruke povratne informacije za


hijerarhijske ili srodne podatke
U već somenutom primjeri iznad s fudbalskim timovima zamislimo novu situaciju.
Recimo da korisnik želi da nekako izabere (selektuje) dva tima i želi da ih poredi, s igračima i
ostalim osobinama. To bi u REST API slučaju značilo da se treba poslati upit za svaki izabrani
tim, zatim za dodatne detalje koji se žele porediti i slično. Ovo zasigurno dovodi do višestrukih
povratnih informacija do servera direktno utičući na latenciju i naravno na grafičko okruženje
aplikacije (vjerovatno će se morati dodati neka animirana sličica za prikaz da se stvari učitavaju
ili neki "loader bar" i slično). Koristeći GraphQL ovaj proces se može umnogome pojednostaviti
tako što će se konstruisati jedan ugnježdeni upit koji će dobiti sve neophodne informacije u
samo jednom kružnom toku! Odgovornos preuzimanja podataka (i naravno obrada kao i u
REST API slučaju) sada se prebacuje na stranu servera.

Zaključak prvog dijela


GraphQL je namijenjen, kao što se da zaključiti, za kijentske aplikacije gdje su propusni
opseg (bandwidth) i latencija ključni. Omogućava klikent da vrši upite za grafikon objekata
(hijerarhijska struktura srodnih objekata). Koristeći GraphQL, klijentske aplikacije također mogu
da izaberu koji podaci, odnosno koja polja će biti uključena u odgovor. To ga čini neuporedivo
jednostavnijim i lakšim za korištenje i preuzimanje podataka na krajnjoj klijentskoj (posebno
mobilnoj) aplikaciji.

Valja naglasiti također da GraphQL nije zamjena za REST. On se ustvari veoma dobro
uklapa u REST i može se koristiti za specifične slučajeve. U nastavku će biti više govora o
razlikama između REST-a i GraphQL-a, te kada je dobro koristiti jedan, a kada drugi.
Uvod u drugi dio
U nastavku kao uvod drugog dijela pokušaćemo predstaviti tabelu neku kao REST vs
GraphQL.

Šta je u REST-u? Šta je u GraphQL-u?

Koristi HTTP Protokol za prenos podataka Protokol za prenos je na strani onoga ko


implementira, tako da to može biti HTTP,
Web Sockt, MQTT, ...

Za svaki Resurs po jedan Endpoint API Gotovo uobičajeno da se koristi jedan


GraphQL Endpoint po aplikaciji

Koristi HTTP sintaksu (GET|POST|Delete|...) Koristi semantiku upita (Queries) i mutacija


za semantiku5 (Mutations)

Koristi HttpStatusCode za poruke o greškama GraphQL ima predvidljivu strukturu odgovora


(Error response) sa podacima i poljima koja sadržavaju poruke
i kodove grešaka

Zahtijeva parametre (Query parameters) za Nema nekih posebnih ni zahtjeva ni


čitanje i HTTP Body za pisanje ograničenja, ali slanje mutacija je vjerovatno
sigurnije sa POST

Server definiše oblik odgovora Klijent definiše kakav oblik odgovora želi da
dobije

Nema podršku za pretplatu (Subscription) Pretplata je dio specifikacije

Održavanje svakog pojedinačnog Endpoint GraphQL je praktično samo-dokumentujuć


Resursa preko Schema introspection

5
​Kao što je opšte poznato, semantika, kao riječ se koristi u mnogim oblastima, ali u računarstvu
je povezano s matematikom i odražava značenje nekog programa ili funkcije, odnosno definiše
značenje sintaksno ipravnih konstrukcija jezika.
Sintaksa u programiranju podrazumijeva pravilno korištenje ključnih riječi i logike programskog
jezika za pisanje funkcionalnog i logički ispravnog koda. Neki kod napisan sintaksno ispravno
(čitaj bez gramatičkih grešaka) ne znači i da je napisan semantički ispravno (čitaj logika mu je
taraba).
Razvrstavanje na stranice (Pagination) odvija Razvrstavanje na stranice se odvija unutar
se preko URL parametara GraphQL upitnih parametara

Životni ciklus zahtjeva u REST-u i u GraphQL-u


GraphQL je javan, odnosno principi na kojima radi, a koji vele da klijenti koriste samo
jedan HTTP endpoint za slanje više upita i mutacija za dohvaćanje i obavljanje podataka u
pozadini (na serveru). Ovo svakako pojednostavljuje tok zahtjeva koji se javljaju između
klijenata i servera. Sve ovo postaje mnogo jasnije, očitije kada se pokušaju dohvatiti povezani
podaci preko nekog upita.

Ako se sjetimo onog N+1 problema iz prvog dijela ove priče može se zamisliti kako se
interakcije klijentskog servera dešavaju dok dohvatamo detalje fudbalskog tima koristeći se
REST endpointim-a, pa će se od servera dobiti nešto recimo nalik ovome:

{
"team":{
"id":​"1"​,
"name":​"FK Buducnost Banovici"​,
"division":​"Crvendaci"​,
"owner":​"RMK Banovici"​,
"headCoach":​"Safet Susic"​,
"players":[
{
"__link":​"api/teams/1/players/p1"
},
{
"__link":​"api/teams/1/players/p2"
}
]
}
}

Pažljivim posmatranjem uočiće se da ovaj tim ima samo dva igrača (recesija, šta li) sa
pojedinačnim linkovima za dohvatiti detalje za svakog od njih, kako se ne bi lutalo ponovo
negdje po “index” strani da se dobavi lista igrača. To svakako smanjuje jedan korak, ali
svejedno da bi se dobili podaci za svakog igrača potrebno je poslati upit na svaki od navedenih
linkova (u ovom slučaju dva).

Ako bi se poslao upit ka serveru, server bi mogao vratiti nešto nalik ovome:
{
"player":{
"id":​"p1"​,
"teamId":​"1"​,
"name":​"Semir Dedic"​,
"height":​65​,
"weight":​175​,
"position":​"Strijelac"
}
}

Nakon ovih malih primjerčića može se bolje razumjeti onaj problem N+1 spomenut
naprijed. U ovom slučaju bi to značilo da ako se tim sastoji od N igrača data se valja poslati N+1
upita na server da bi se dobili svi neophodni podaci. Neko će reći kako se ovo sve može izbjeći i
dobiti rezultate svega u samo jednom upitu ka serveru. Ali sjetimo se šta smo pisali u prvom
dijelu ovog članka o količini podataka koje se traže i koje se dobijaju.

Ovi naprijed navedeni primjeri, odnosno upit ka serveru koji je pogodnjen GraphQL-om
bi imao slijedeći oblik:

query TeamDetails {
getTeam(​id​: ​"1"​) {
​id
​name
division
owner
headCoach
roster {
​id
​name
position
}
}
}

Da se primijetiti da je upit nekakva struktura, ali struktura koju definiše svaki pojedinačni
klijent za svoje vlastite potrebe. Ovaj upit se šalje recimo putem HTTP zahjeva, ali samo
jednom.
Komšijska trava je uvijek zelenija
U pozadini će se vjerovatno imati isti broj upita ka bazi podataka, ali će se smanjiti broj
upita na server preko HTTP endpointa. Neko će reći morebit, pa šta se dobilo onda? Skoro pa
ništa! Svakako, ako se prebaci sva logika na serversku stranu, onda će se napraviti i drugačiji
pristup ka bazi, obrada podataka i slično, što će na kraju davati bolji rezultat, a to i jeste poenta.

Postoje određeni izazovi koji valja biti svjestan prilikom upostavljanja i održavanja
GraphQL servera, a to su:

● Trebala bi se dizajnirati GraphQL šema koja će prepoznavati tipove i njihove donose,


pisanje rezolucija, mnogostruke (batch) zahtjeve za Data Source.
● Valja naći pravu, ispravnu strategiju autorizacije. Pravila autorizacije se mogu postaviti
na raznim nivoima, kao što je na nivou šeme, nivou polja, za svaki upit ili mutaciju.
● REST su ljudi skontali prije nepunih 20 godina. Od tada do danas se razvilo mnoštvo
alata, tako da će možebit oni nekada odvratiti developera da se odvaži koristiti GraphQL.
● GraphQL je podržan specifikacijom suprotnom REST-u, a što je skup smjernica ustvari i
sada postoji podrška implementacije u više (ne nekoliko) popularnih programskih jezika.
No valja istražiti i vidjeti je li biblioteka radi onako kako zahtijeva aplikacija koja se
izrađuje.

Za one koji koriste AWS neke stvari će biti umnogome olakšane jer AWS ima punu
podršku za GraphQL.

Kada koristiti REST?


Kao što se može zaključi iz cijele priče do sada GraphQL i REST su komplementarni i
koriste se za specifične svrhe. Slijedeći slučajevi upotrebe razaraju (overkill) GraphQL, al su
savršeni za REST usluge:

● CRUDL endpoints zasnovane na obrascima. Ako se izrađuje veb aplikacija za nešto


veoma jednostavno, kao što je veb aplikacija za listu studenata koji su prisustvovali
nastavi, tada se ne mora izlagati pravljenju GraphQL šeme za ovaj scenario nikako. To
je zato što će sve biti gotovo s upravljanjem svakog pojedinačnog polja i to je to.
● Još jedan koristan slučaj upotrebe za REST komunikaciju između servera i klijenta jeste
recimo snadbjevač (provider) vijestima. Svi partneri će koristiti RESTful API da povuku
vijesti ka svojim vlastitim stranicama, a onda će to tek kasnije biti preformatirano da se
koristi na desktop ili mobilnim uređajima.
● Ako postoji samo jedna vrsta klijenta tada je REST vjerovatno bolji izbor imaću obzira da
je REST rasprostranjen, mnogo programera zna kako radi, jako mnogo alata ima za
njega i slično.

Životni ciklus razvoja aplikacije


Izrada aplikacije bazirane na REST-u je uvijek bazirana na tome šta klijentu (klijentskoj
aplikaciji) treba. Za sve ono što treba klijentu izrađuje se REST API. U početku to ide sa
lažiranjem podataka iz baze čisto da se dobije struktura REST izlaza, a onda se to kasnije
vezuje kroz neku poslovnu logiku sa stvarnim podacima. Jednom kada se utvrdi putanja, ulazi,
izlazi, odredi se vrsta i način keširanja da se smanji protok i to je to (zvuči jednostavno).

U GraphQL svijetu izrada aplikacija ide malko ili malo više drugačije. Server i klijent se
mogu izrađivati gotovo u potpunosti nezavisno ako su jasno definisane šeme sa tipovima koje
aplikacija zahtijeva/treba. Odnosi između tipova također trebaju biti definisani, a onda se pristupi
izradi upita tzv. mutacija za potrebe klijenta. Jednom kada se ovo jasno definiše, klijent šalje
svoj upit na GraphQL u potrazi za određenim setom podataka i naravno taj set, takav kakav
traži i dobija.

Migracija REST API na GraphQL


Prije nego se bilo ko odluči na migraciju (bio to neki menadžer - mada ne znam šta on
ima ovdje tražiti, softver arhitekta ili pak developer) trebao bi da sam sa sobom malo
porazgovara i odgovori na neka pitanja kao što su:

● Zašto ustvari želim migrirati REST endpointe u GraphQL?


● Da li su troškovi vremena i resutrsa uključeni u sve ovo i je li to ekonomski opravdano?
● Kakvi su mi trenutni REST API-i i kako ih održavam?
● Da li postoje neki novi mobilni uređaji zbog kojih se možda odlučujem na GraphQL (osim
tableta i pametnih telefona recimo pametni sat ili neki drugi uređaj u pametnoj kući,
pametnom autu, …)

Ono što mnogi entuzijazisti zaborave često puta jeste struktura tima. Ko radi u frontend
timu, ko radi u backend timu? Da li su ljudi otvoreni ka novim idejama ili ne? Kakvo imaju
prethodno iskustvo i slično.

Napravite sebi neku kao listu (check list) koju trebate provjeriti prije nego se odlučite da
neki projekat migrirate na GraphQL. Slijedeća lista vam možda može pomoći kod donošenja
takvih odluka:
● Vaš trenutni proces je zamoran i postoji jako mnogo komunikacije između frontend i
backend timova.
● Uočavate probleme s performansama na REST endpointima zbog prevelikog ili
nedovoljnog preuzimanja podataka.
● Operativni troškovi na klijentu se stalno povećavaju, čak umnogostručuju zbog
složenosti podataka ili upravljanja postojećim REST endpointima.

Postoje barem tri pristupa/scenarija koje možete zamisliti kada se prelazi u svijet
GraphQL-a. Ovdje će se opisati ta tri scenarija.

★ Prepisivanje/zamjena postojećeg HTTP veb servera na GraphQL


Ako ste već planirali praviti refactoring vašeg REST-a ili ako nemate baš previše
klijenata na vašem restu možda je to baš pravo vrijeme za preći na GraphQL. U početku će
vjerovatni biti bolno dok se ne namjesti sve na strani GraphQL-a, ali ubrzo će se vidjeti sve
prednosti ili kako mi to znamo reći benefiti.
Jedna od velikih prednosti ovdje je što u svakom slučaju ste htjeli praviti refaktoring ili
nemate mnogo klijenata, ali tačno znate šta treba, tako će novi pristup svemu zasigurno donijeti
mnogo toga i imaćete veoma kvalitetno razvijenu strukturu na strani GraphQL-a.

★ Dodavanje GraphQL-a na preopterećene endpointe koji enkapsuliraju6 postojeće stanje


U ovom pristupu ne bi se izbacio REST. Ostao bi gdje i jeste sa strukturom kakva jeste,
ali između klijenta i REST-a bi sada bio GraphQL, a sve zbog komplikovane strukture i/ili viška
ili manjka podataka koje razni klijenti dobijaju. GraphQL dođe nešto kao proksi. Super kod ovog
pristupa je što klijenti postepeno prelaze na GraphQL, jer svi klijenti koriste REST bez
problema osim onih koje ste natjerali da koriste GraphQL. Neki popularni servisi nude čak i
“automatska” rješenja za REST, odnosno da GraphQL se nakači na taj REST i kasnije se svim
klijentima nudi samo GraphQL usluga (Nije baš automatski, ali nešto slično se može naći u
AWS AppSync).

★ Hibridni pristup ka endpointima koji su i REST i GraphQL


Razlika između drugog scenarija i ovog je što u ovom slučaju GraphQL ne bi bio nikakav
proksi, nego bi se imalo paralelno i REST i GraphQL. Također je dobra stvar jer klijenti mogu da
koriste i REST i GraphQL istovremeno maltene, u zavisnosti od konfiguracije klijenta.

Zakjučak
Ovaj članak je pr(ij)evod jednog članka objavljenog na engleskom jeziku s određenim
modifikacijama i prilagođavanjima. Autor članka se nada da je pristup GraphQL-u i REST-u u
ovom članku nepristrasan i da će pomoći kod odabira pravog rješenja za trenutnu ili aplikaciju
koju imate namjeru tek izrađivati. Kao što se da vidjeti, nema nikakvih konkretnih primjera u

6
Ubaci sve u jednu kapsulu koju je lakše progutati.
ovom članku, ali nadamo se daje jasan (ne tako precizan, ali nadamo se jasan) presjek šta je to
GraphQL, šta REST i koja je razlika između njih u praksi. Ako se odlučite za GraphQL i steknete
neka nova iskustva i znanja, podijelite sa svima nama, da i mi nešto naučimo.

You might also like