Java programátor expert
API architektúra určuje, ako spolu komunikujú jednotlivé služby aplikácie. Najčastejšie ide o REST API, GraphQL alebo gRPC. REST je univerzálny štandard pre verejné API, GraphQL dáva klientovi kontrolu nad dátami a gRPC ponúka maximálny výkon pre internú komunikáciu medzi mikroslužbami. V praxi sa najčastejšie používa ich kombinácia cez API Gateway.

V článku sa dozvieš:
API architektúra je súbor rozhodnutí o tom, akým protokolom budú služby komunikovať, aký dátový formát použijú a ako sa rieši autentifikácia. Samotné API (Application Programming Interface) slúži ako kontrakt medzi poskytovateľom služby a jej spotrebiteľom: určuje, čo môže klient žiadať, v akom formáte a čo dostane späť. Každý endpoint, ktorý definuješ, reprezentuje vstupnú bránu k tvojej biznis logike.
Voľba architektúry je pritom dôležitejšia než samotné rozhodnutie API použiť. Ovplyvní latenciu, bezpečnosť aj náklady na údržbu a drží škálovateľnosť produktu počas celého softvérového vývojového cyklu (SDLC).
Zatiaľ čo v minulosti dominovali monolitické aplikácie s interným volaním funkcií, dnes komunikujeme cez sieť pomocou rôznych protokolov a dátových formátov. Práve preto je dobré poznať silné a slabé stránky každého z hlavných štýlov, REST, GraphQL, gRPC a tiež doplnkové vzory ako API Gateway či webhook.
REST (Representational State Transfer) definoval Roy Fielding vo svojej dizertačnej práci v roku 2000 a odvtedy sa stal de facto štandardom pre webové služby. Nie je to protokol, ale architektonický štýl, ktorý využíva existujúce mechanizmy HTTP.
Základom je práca so zdrojmi (resources), ktoré sú identifikované pomocou URL. Na manipuláciu s týmito zdrojmi využívaš štandardné HTTP metódy (GET, POST, PUT, DELETE, PATCH).
Hlavná sila REST API spočíva v jednoduchosti a bezstavovosti (statelessness). Každá požiadavka od klienta musí obsahovať všetky informácie potrebné na jej spracovanie. To umožňuje serveru neukladať si kontext o klientovi, čo výrazne zjednodušuje horizontálne škálovanie.
Pokročilejšie REST API môžu implementovať aj princíp HATEOAS (Hypermedia as the Engine of Application State), kde server vracia odkazy na ďalšie možné akcie, čím sa klient naviguje dynamicky bez pevne definovanej logiky.
Pred nástupom REST bol dominantným hráčom SOAP (Simple Object Access Protocol). Hoci sa dnes môže zdať zastaraný, v bankovom sektore a veľkých enterprise systémoch má stále svoje miesto. Pozri sa, v čom sa tieto dva prístupy líšia v praxi.
| Vlastnosť | REST | SOAP |
|---|---|---|
| Formát dát | JSON, XML, HTML, text | Výhradne XML |
| Protokol | Primárne HTTP | HTTP, SMTP, TCP a ďalšie |
| Flexibilita | Vysoká, definuješ si vlastnú štruktúru | Nízka, prísne definované štandardy (WSDL) |
| Bezpečnosť | HTTPS, JWT token | WS-Security (vstavaná podpora) |
| Výkon | Väčší (menší overhead vďaka JSON) | Menší (XML spracovanie je náročné na CPU) |
SOAP vyžaduje striktnú definíciu správ pomocou WSDL (Web Services Description Language). Ak klient pošle čo i len o jeden tag navyše, komunikácia zlyhá. REST je v tomto smere benevolentnejší, čo urýchľuje vývoj, ale vyžaduje disciplínu pri dokumentácii.
Keďže REST natívne nevynucuje schému (na rozdiel od gRPC alebo SOAP), dokumentácia sa stáva kritickým bodom. Tu prichádza na scénu OpenAPI (predtým známe ako Swagger spec).
OpenAPI je špecifikácia, ktorá umožňuje opísať tvoje API v strojovo čitateľnom formáte (YAML alebo JSON). Swagger je tvorený sadou nástrojov, ktoré následne vygenerujú interaktívnu dokumentáciu, kde si môžeš každý endpoint priamo vyskúšať.
Moderný vývoj v Jave stojí pri REST API na anotáciách, ktoré definujú rozhranie. Základ tvorí Spring Framework, nad ktorým Spring Boot pridáva automatickú konfiguráciu a rýchly štart projektu. Všimni si, ako čisto je definovaný prístup k dátam:
@RestController
@RequestMapping("/api/v1/products")
public class ProductController {
private final ProductService productService;
public ProductController(ProductService productService) {
this.productService = productService;
}
// Získanie detailu produktu podľa ID
@GetMapping("/{id}")
public ResponseEntity<ProductDto> getProduct(@PathVariable Long id) {
return ResponseEntity.ok(productService.findById(id));
}
// Vytvorenie nového produktu
@PostMapping
public ResponseEntity<ProductDto> createProduct(@RequestBody ProductDto productDto) {
ProductDto created = productService.save(productDto);
return new ResponseEntity<>(created, HttpStatus.CREATED);
}
}
V tomto kóde vidíš jasné prepojenie medzi HTTP metódou a biznis operáciou. Ak chceš zabezpečiť, aby tvoj kód zostal čistý a testovateľný aj pri stovkách takýchto kontrolórov (controllers), odporúčam aplikovať overené Java návrhové vzory.
Napriek jeho rozšíreniu, REST čelí v moderných aplikáciách dvom hlavným problémom:
Tieto nedostatky viedli k vzniku technológie GraphQL, ktorú si rozoberieme v nasledujúcej kapitole.
Pochopenie SOLID princípov ti pomôže navrhnúť lepšie API endpointy.
GraphQL mení paradigmu a odovzdáva kontrolu nad dátami do rúk klienta. Tento dopytovací jazyk pre API, vyvinutý pôvodne spoločnosťou Facebook, rieši fundamentálne problémy, s ktorými sa pri raste komplexnosti stretávajú klasické REST rozhrania.
Hlavným rozdielom je, že v GraphQL klient presne špecifikuje, ktoré polia potrebuje. Ak tvoj frontend vyžaduje iba meno používateľa a jeho profilový obrázok, server mu nepošle celú adresu, históriu objednávok a zoznam preferencií. Týmto prístupom eliminujeme dva najčastejšie problémy sieťovej komunikácie:
Základným kameňom každej GraphQL implementácie je schéma. Definujeme ju pomocou SDL (Schema Definition Language), čo zabezpečuje jasný kontrakt medzi backendom a frontendom ešte predtým, než sa napíše prvý riadok aplikačnej logiky. Všetko v GraphQL má svoj typ, od základných skalárnych typov (String, Int, Boolean) až po komplexné objekty a enumerácie.
Pri návrhu schémy je dôležité dodržiavať SOLID princípy, najmä princíp zodpovednosti (Single Responsibility). Resolvers, čo sú funkcie zodpovedné za plnenie jednotlivých polí dátami, by mali byť štrukturálne čisté a nemali by v sebe niesť ťažkú biznis logiku.
Na rozdiel od REST, ktorý využíva rôzne HTTP metódy, GraphQL typicky komunikuje cez jediný endpoint (často /graphql), najčastejšie pomocou metódy POST (hoci pre jednoduché dopyty je možné použiť aj GET). Typy operácií rozlišujeme priamo v tele požiadavky:
V Java ekosystéme je dnes štandardom využitie knižníc ako Spring for GraphQL alebo Netflix DGS. Tie umožňujú jednoduché mapovanie schémy na Java objekty a metódy.
// Definícia GraphQL typu v súbore schema.graphqls
/*
type Product {
id: ID!
name: String!
price: Float
category: Category
}
*/
@Controller
public class ProductResolver {
private final ProductService productService;
public ProductResolver(ProductService productService) {
this.productService = productService;
}
// Mapovanie GraphQL dopytu na metódu
@QueryMapping
public Product productById(@Argument Long id) {
return productService.getById(id);
}
// Asynchrónne plnenie vnoreného objektu kategórie
@SchemaMapping
public Category category(Product product) {
return productService.getCategoryForProduct(product);
}
}
V tomto príklade vidíš, že ak klient v dopyte nevyžiada pole category, metóda označená anotáciou @SchemaMapping sa vôbec nespustí. To prináša obrovskú úsporu systémových prostriedkov pri komplexných dátových modeloch.
Hoci GraphQL pôsobí ako riešenie na väčšinu problémov s API, prináša aj nové výzvy, ktoré musíš ako architekt zohľadniť:
Pre systémy, kde je prioritou extrémny výkon a komunikácia prebieha primárne medzi servermi, však existuje ešte efektívnejšia cesta, gRPC, ktorému sa budeme venovať v ďalšej časti.
…že GraphQL endpoint v produkcii nemá zmysel nasadiť bez Query Depth Limiting? Bez tohto obmedzenia môže útočník poslať dopyt vnorený do hĺbky 20 úrovní a vyčerpať pamäť servera v priebehu sekúnd.
Ak hľadáš riešenie pre komunikáciu medzi mikroslužbami, kde sa počíta každá milisekunda a objem prenášaných dát je kritický, gRPC (Google Remote Procedure Call) patrí medzi najvýkonnejšie riešenia. Zatiaľ čo REST a GraphQL sa spoliehajú na textový formát JSON, gRPC využíva binárnu serializáciu a moderný transportný protokol, čo prináša výrazné zlepšenie výkonu.
Základným stavebným kameňom gRPC je Protocol Buffers (Protobuf). Ide o mechanizmus serializácie štruktúrovaných dát, ktorý je nezávislý od programovacieho jazyka. Na rozdiel od JSON, ktorý musí pri každej správe prenášať aj názvy polí (napríklad „firstName“: „Jozef“), Protobuf prenáša len binárne hodnoty mapované na číselné indexy definované v schéme.
Výsledkom je správa, ktorá je o 30 % až 80 % menšia ako ekvivalent v JSON. Šetrí to šírku pásma a najmä procesorový čas potrebný na parsovanie textu na objekty. V prostredí Java to znamená nižšiu záťaž na Garbage Collector a celkovo lepšiu odozvu systému.
gRPC natívne využíva HTTP/2, čo mu dáva obrovské výhody oproti staršiemu HTTP/1.1 často používanému v bežnom REST:
Pri práci s gRPC začínaš definíciou súboru .proto. Tento súbor slúži ako jediný zdroj pravdy (Single Source of Truth). Pomocou kompilátora protoc si následne vygeneruješ Java triedy (stubs), ktoré zabezpečia všetku nízkoúrovňovú komunikáciu. Pozri si nasledujúcu ukážku definície v Protocol Buffers:
// Definícia služby v súbore product.proto
syntax = "proto3";
option java_multiple_files = true;
option java_package = "sk.msgprogramator.api.grpc";
message ProductRequest {
int64 id = 1;
}
message ProductResponse {
int64 id = 1;
string name = 2;
double price = 3;
}
service ProductService {
// Unary volanie - jedna požiadavka, jedna odpoveď
rpc getProductDetail(ProductRequest) returns (ProductResponse);
}
V Java kóde potom už len implementuješ vygenerovaný interface:
public class ProductGrpcService extends ProductServiceImplBase {
@Override
public void getProductDetail(ProductRequest request,
StreamObserver<ProductResponse> responseObserver) {
// Získanie dát z DB alebo inej služby
ProductResponse response = ProductResponse.newBuilder()
.setId(request.getId())
.setName("Headset")
.setPrice(99.99)
.build();
// Odoslanie odpovede klientovi
responseObserver.onNext(response);
// Ukončenie streamu
responseObserver.onCompleted();
}
}
Tento prístup je mimoriadne vhodný pre automatizáciu v CI/CD procesoch. Ak zmeníš .proto súbor, kompilácia ti okamžite ukáže, či si niečo v aplikácii nepokazil, čo pri voľnejšom REST zistíš často až počas runtime testov.
gRPC je ideálne pre komunikáciu medzi mikroslužbami (microservices) v rámci dátového centra. Vďaka silnej typovosti a garantovanému kontraktu znižuje riziko chýb v distribuovanom systéme.
Na druhej strane, gRPC nie je najvhodnejšou voľbou pre verejné API (Public API) určené pre webové prehliadače. Prehliadače totiž nemajú plnú kontrolu nad HTTP/2 rámcami, čo vyžaduje použitie proxy riešení ako gRPC-Web. Takisto debugovanie binárnej komunikácie je náročnejšie ako čítanie čistého JSON-u v konzole. Správa takejto infraštruktúry je skôr náplňou práce DevOps inžiniera, ktorý musí zabezpečiť správnu konfiguráciu balancerov a certifikátov pre HTTP/2.
Keď sa tvoj systém rozrastie a začne ho tvoriť desiatka mikroslužieb (niektoré možno v REST, iné v gRPC), nemôžeš nechať klientov (web, mobil, partneri) komunikovať priamo s každou z nich. To by vytvorilo bezpečnostné riziko a logistický chaos. Tu prichádza na scénu API Gateway.
API Gateway (centrálny vstupný bod pre API požiadavky) funguje ako brána, ktorá prijíma požiadavky od klientov a smeruje ich na príslušné interné služby. Je to v podstate inteligentná reverse proxy vrstva, ktorá okrem smerovania plní množstvo ďalších úloh.
API Gateway typicky plní niekoľko základných úloh, ktoré odoberajú záťaž z jednotlivých mikroslužieb:
Špecifickým typom API architektúry využívajúcej gateway je vzor Backend-for-Frontend. Namiesto jednej univerzálnej brány vytvoríš pre každý typ klienta (napríklad iOS appka vs. Admin web) samostatnú bránu. Tým zabezpečíš, že mobilný klient dostane presne tie dáta, ktoré potrebuje (podobne ako v GraphQL), zatiaľ čo desktopová verzia môže pracovať s komplexnejším modelom.
Aj pri návrhu robustnej brány je dôležité dbať na to, aby tvoja Gateway neobsahovala zbytočnú biznis logiku. Mala by zostať čistým potrubím pre dáta, ktoré sa stará len o infraštruktúrne záležitosti.
Navrhnúť výkonné rozhranie je len polovica úspechu. Druhou, nemenej dôležitou časťou, je zabezpečenie, aby každý endpoint spracoval iba autorizované požiadavky. V distribuovaných systémoch už nestačí spoliehať sa na lokálnu session v pamäti servera.
V modernej API architektúre dominuje bezstavová autentifikácia pomocou JWT (JSON Web Token). Tento mechanizmus umožňuje serveru overiť identitu používateľa bez toho, aby musel pri každej požiadavke kontaktovať databázu.
JWT sa skladá z troch častí, header, payload a signature. Payload obsahuje takzvané claims (napríklad ID používateľa alebo jeho roly), ktoré sú digitálne podpísané tajným kľúčom servera. Keď klient pošle token v hlavičke Authorization: Bearer <token>, API Gateway alebo cieľová služba jednoducho overí podpis. Dáta v tokene sa považujú za dôveryhodné, pokiaľ bol podpis validne overený a token je stále platný (neexspiroval).
Pri implementácii v Jave patrí medzi bežné chyby nesprávna validácia exspirácie tokenu, preto sa oplatí zaradiť bezpečnostné testy priamo do CI/CD pipeline. JWT tu ostáva na konceptuálnej úrovni. Kompletnú implementáciu JWT v Spring Security, teda SecurityFilterChain, autentifikačný filter aj refresh tokeny, nájdeš v samostatnom článku.
Zatiaľ čo JWT rieši otázku identity (kto si), OAuth2 rieši ovládacie práva (čo môžeš robiť). Ide o priemyselný štandard pre delegovanú autorizáciu. Umožňuje tretím stranám pristupovať k chráneným zdrojom bez toho, aby poznali heslo používateľa. V enterprise prostredí sa často kombinuje OAuth2 pre správu prístupov a JWT token ako nosič informácií o týchto prístupoch.
Prečítaj si aj: Spring Security.
Väčšina API architektúr, o ktorých sme doteraz hovorili (REST, GraphQL, gRPC), funguje na princípe dopyt-odpoveď (Pull komunikácia). Klient sa pýta, server odpovedá. Čo ak však tvoj systém potrebuje reagovať na udalosť v momente, keď nastane, bez toho, aby sa klient musel každú sekundu pýtať „už sa niečo stalo?“. Tento problém rieši webhook (spätné volanie servera).
Zatiaľ čo klasické API volanie iniciuje klient, webhook iniciuje server. Je to v podstate obrátené API (Push komunikácia). Rozdiel si môžeš predstaviť takto:
V Java aplikáciách sa webhook často spracováva ako bežný REST controller, ktorý prijíma dáta od externej služby (napríklad Stripe, GitHub alebo tvoj vlastný mikroservis). Je však dôležité implementovať overenie digitálneho podpisu prichádzajúcej požiadavky, aby niekto neposlal falošnú notifikáciu na tvoj server.
Toto je najdôležitejšia časť tvojho architektonického rozhodovania. Neexistuje univerzálne najlepšie API, existuje len najvhodnejší nástroj pre daný kontext. Pri výbere musíš zvážiť výkon, zložitosť vývoja, skúsenosti vývojárov s novými technológiami a typ klienta.
REST je tvoja predvolená voľba pre Public API. Ak buduješ rozhranie, ktoré budú konzumovať vývojári tretích strán, REST s dokumentáciou cez OpenAPI a Swagger je nepísaným zákonom. Je ľahko pochopiteľný, má obrovskú podporu knižníc a funguje v každom prehliadači bez ďalších vrstiev.
GraphQL je ideálny pre komplexné používateľské rozhrania (user interfaces) a mobilné aplikácie, kde sa rozhranie často mení. Ak máš dátový model s množstvom vzťahov (napríklad sociálna sieť alebo e-shop) a chceš sa vyhnúť desiatkam HTTP dopytov pri načítaní jednej stránky, GraphQL ti ušetrí mesiace vývoja na strane frontendu.
gRPC je veľmi častou voľbou pre internú komunikáciu medzi mikroslužbami. Ak tvoj DevOps Engineer rieši problémy s latenciou v distribuovanom systéme, prechod z JSON na binárny Protobuf a HTTP/2 dokáže znížiť odozvu o desiatky percent a zároveň zmenšiť nároky na infraštruktúru.
Nasledujúca tabuľka zhŕňa hlavné rozdiely medzi všetkými architektúrami v jednom prehľade. Použi ju ako rýchlu pomôcku pri výbere riešenia pre konkrétny projekt:
| Kritérium | REST | GraphQL | gRPC |
|---|---|---|---|
| Primárne využitie | Verejné webové služby | Webové/mobilné aplikácie | Interné mikroslužby |
| Dátový formát | JSON (najčastejšie) | JSON | Protobuf (binárny) |
| Typovosť | Slabá (vyžaduje OpenAPI) | Silná (Schema-first) | Silná (Code generation) |
| Výkon a latencia | Stredná | Stredná (overhead na resolveroch) | Extrémne vysoká |
| Caching | Vynikajúci (na úrovni HTTP) | Náročný (aplikačná úroveň) | Náročný |
| Streaming | Limitovaný | Subscriptions (cez WebSocket) | Plne duplexný (natívny) |
V praxi sa málokedy stretneš s projektom, ktorý využíva len jeden prístup. Najmodernejšia API architektúra vyzerá takto:
Tento hybridný model využíva silné stránky každej technológie tam, kde to dáva najväčší zmysel.
API Gateway je centrálny vstupný bod (vstupná brána) pre všetky prichádzajúce požiadavky od klientov do tvojho systému. Funguje ako inteligentná reverse proxy vrstva, ktorá smeruje požiadavky na konkrétne mikroslužby. Jej hlavnou úlohou je oddeliť infraštruktúrnu logiku (autentifikácia, rate limiting, load balancer) od samotnej biznis logiky aplikácie. Vďaka tomu nemusíš v každej jednej službe riešiť overovanie JWT alebo ochranu proti DDoS útokom, API Gateway to vyrieši za teba na jednom mieste.
Hlavný rozdiel spočíva v tom, kto definuje štruktúru vracaných dát. V REST API definuje štruktúru server (každý endpoint vracia fixný JSON). V GraphQL definuje štruktúru klient pomocou dopytu. GraphQL tak rieši problémy ako overfetching (posielanie zbytočných dát) a underfetching (nutnosť viacerých dopytov pre získanie súvisiacich dát), čo z neho robí ideálny nástroj pre moderné UI.
Po gRPC siahni v momente, keď buduješ internú komunikáciu medzi mikroslužbami, kde je prioritou nízka latencia a vysoký výkon. gRPC je vďaka binárnej serializácii cez Protocol Buffers a využitiu HTTP/2 výrazne rýchlejšie ako textový REST. Ak však tvoje API majú konzumovať externí vývojári alebo webové prehliadače, REST v kombinácii s OpenAPI (cez Swagger) zostáva lepšou a kompatibilnejšou voľbou.
Toto nie je súboj buď-alebo, tieto technológie sa dopĺňajú. OAuth2 je autorizačný rámec (protokol), ktorý definuje, ako sa udeľujú prístupy k zdrojom. Token JWT je konkrétny formát (nosič) informácií o identite a právach používateľa. Bežná prax je taká, že systém využije OAuth2 na prihlásenie a následne vygeneruje JWT token, ktorým sa klient preukazuje pri každom endpoint volaní.
Rozdiel je v smere iniciatívy. Bežné API funguje na princípe: klient sa pýta servera (Pull). Webhook funguje opačne: server informuje klienta o udalosti (Push). Namiesto toho, aby tvoja aplikácia neustále kontrolovala stav platby cez API, externe volaný webhook tvojmu serveru pošle správu v sekunde, keď platba prebehne. Ušetríš tým množstvo sieťových prostriedkov a znížiš odozvu systému.
Ak chceš, aby tvoje API niekto úspešne používal (vrátane teba o tri mesiace), tak áno. Swagger (dnes súčasť OpenAPI iniciatívy) automaticky generuje interaktívnu dokumentáciu priamo z tvojho kódu alebo definičného súboru. Bez kvalitnej dokumentácie je aj tá najlepšia API architektúra pre ostatných vývojárov nepoužiteľná.
Navrhnúť špičkovú API architektúru neznamená vybrať si najnovší trend na trhu, ale zvoliť ten správny nástroj pre tvoj špecifický problém. Počas celého vývojového cyklu treba mať na pamäti, že tvoje API je kontrakt, ktorý musí byť stabilný, bezpečný a výkonný.
Nezabúdaj na softvérové princípy ani pri návrhu sieťových rozhraní. Čistý kód na backend a jasne definované kontrakty (či už cez Protobuf alebo OpenAPI) sú to, čo odlišuje priemerný projekt od špičkového systému.
Výber architektúry síce nie je vytesaný do kameňa, ale jeho voľba dnes ovplyvní technickú prevádzku pri nasadení u zákazníka. Vyberaj s rozumom, meraj výkon a vždy mysli na koncového používateľa, ktorý bude tvoj endpoint konzumovať.
Zdroje:
Súvisiace články