Aller au contenu
Développement d'une application web React et d'une API avec une architecture en microservices

Développement d'une application web React et d'une API avec une architecture en microservices

Présentation du projet
#

J’ai réalisé ce projet lors de ma seconde année d’étude en informatique, l’objectif était de mettre en pratique nos connaissances en développement web frontend et backend. Les contraintes qui nous étaient imposées pour le frontend étaient la création d’une application web de type SPA (Single-page application) avec React. Pour le backend, nous devions créer une API qui reposait sur d’autres API externes ainsi qu’un système de gestion d’utilisateurs, tout cela en utilisant une architecture divisée en microservices.

Pour ce projet, nous avons choisi que notre application porterait sur un jeu de cartes à collectionner et nous avons repris en partie des fonctionnalités de l’application Pokémon TCG Pocket.

Notre équipe était composée de cinq personnes, j’ai eu la chance d’adopter le rôle de chef de projet. En plus du développement, j’étais donc en charge de répartir les tâches et de gérer les livrables ainsi que les différentes échéances.

Défis techniques
#

Architecture de l’application
#

Le premier point important de ce projet est l’organisation en microservices. L’objectif est de diviser l’application en un ensemble de petits services qui sont chacun spécialisés dans une tâche. Tous ces services sont indépendants les uns des autres et ils communiquent entre eux à travers une interface que chacun met à disposition, dans notre cas une API REST. Les avantages de cette architecture sont multiples. Tout d’abord, elle permet de développer chaque service indépendamment des autres et une modification de l’un d’eux n’entraîne pas la modification de tout le système. Un autre avantage est que l’ensemble du backend (traitement de données, gestions des utilisateurs, etc) est séparé de l’application web frontend, on pourrait donc très facilement imaginer développer une application Android par exemple qui interagirait avec le même backend.

Schéma de l’architecture
Schéma de l’architecture globale de l’application avec les différents services.

Frontend
#

L’application web a été conçue avec React et des outils classiques comme Vite pour le build et React Router pour faciliter le routage du site. Nous avons aussi utilisé la bibliothèque de composants Radix UI pour accélérer le développement de l’interface. La difficulté sur cette partie a surtout été de gérer les nombreux appels à l’API avec l’interface réactive qui nécessitait d’être rigoureux sur l’utilisation des Hooks.

Backend
#

Chaque service backend suit une architecture semblable au modèle MVC. Tout d’abord, chaque service est composé de modèles qui décrivent le type de chaque champ d’un objet de donnée. Ensuite, il y a les DAO (Data Access Object), qui permettent de séparer les requêtes à la base de données du reste du code, il est ainsi facile de changer le support de stockage des données, il suffit seulement de réécrire un DAO. Viennent après les contrôleurs qui définissent les actions de l’API et font l’interface avec le DAO et d’autres actions suplémentaires comme la gestion du cache ou la vérification de l’authentification. Enfin, il y a les routes qui respectent l’interface uniforme d’une API REST.

L’ensemble des services a été développé en utilisant le framework léger Express.js. Une attention particulière a été portée sur la documentation de l’API, celle-ci est générée automatiquement à partir des routes et des commentaires en utilisant l’outil Swagger. Aussi, pour tous les composants (routes, contrôleurs, modèles, DAO), nous avons écrit des tests unitaires complets qui permettent de valider le fonctionnement global de l’API. Pour faire cela, nous avons mis en place un “stub” qui consiste en une API qui renvoie des réponses statiques, ce qui a permis de tester les interactions entre les services, mais cela a aussi accélérer le développement de l’interface car il n’y avait pas besoin d’attendre que les services soient opérationnels.

Un défi intéressant à relever a été la validation des types pour le stockage. En effet, nous avons utilisé MongoDB pour le stockage des données qui n’est pas une base de données relationnelle, ainsi nous avons eu recours à l’outil Mongoose pour la validation des données. Mais les schémas de Mongoose ne sont pas toujours très pratiques à utiliser et pour permettre la séparation entre le support de stockage et la description des modèles des données, j’ai développé un système qui permet de décrire simplement les types des données au sein des classes de mon modèle et qui sont ensuite transformés en schéma Mongoose. Un exemple de modèle peut être trouvé ici.

Pour finir, certains services avaient des spécificités. Nous avons, par exemple, mis en œuvre un système de cache pour limiter les appels à l’API externe et réduire les temps de réponses. Pour le service de gestion des utilisateurs, nous avons utilisé les JWT (JSON Web Token) qui permettent de construire un système d’authentification fiable rapidement, avec la persistance de la connexion pour l’utilisateur.

Résultat
#

En conclusion, le projet a été un succès, nous avons réussi à développer les fonctionnalités que nous souhaitions dans les temps avec un bon niveau de fiabilité. L’application finale permet de collectionner des cartes Pokémon avec l’ouverture de boosters grâce à des données recueillies depuis une API externe, il est aussi possible de discuter avec des Pokémon grâce à notre intégration de l’API d’OpenAI.

Le code source du projet est consultable sur ce dépôt GitHub :