Blog Refactoring Project-1- (Feat. RESTful API)
2025-03-12
As my busy schedule finally starts to clear up, I'm finally getting around to implementing Next.js on the frontend, something I've been putting off for a while.
However, my knowledge of front-end is limited to HTML + CSS + JavaScript, which I picked up for a week during a bootcamp course. In fact, this blog is made up of a combination of those three, and before I started working with the frontend on the MusicLab project, I had a tear-jerker of a show with AI to use shadcn myself, but it ended up failing, which made me think about hiring someone.
But now, the bootcamp is over, and the front-end person I worked with is busy looking for a job, so I can't afford to ask for help, and now, unlike then, there are many coding-specific AIs such as Claude's Sonnet 3.7 and OpenAI's o3-mini-high, so I'm going to try to challenge myself. I won't be able to use the same combination forever.
After doing some research to get started, I realized that in order to adopt Next.js in my current situation, I would need to modify the endpoints of my FastAPI to be RESTful.
There are two main reasons for this
1. data communication standardization
- To align the endpoint structure with the GET/POST/PUT/DELETE methods expected by Next.js' fetch() and getServerSideProps.
2. resource-centric architecture
- Hierarchical URL structure, so endpoints in the form of /users/{id} work naturally with Next.js' dynamic routing (pages/users/[id].js)
- Easy to version (use of the /api/v1/ prefix allows for backward compatibility with future API changes)
Once I realized this, I looked at the endpoints, HTML methods, and actual structure of my APIs and realized that none of this crap was there. If I list them all here, this post would be too long, so I'll just point out a few of the problems
1. Not following RESTful principles
- Using GET sometimes and POST sometimes for resource retrieval
- Using GET to log out
2. inconsistent URL structure vs. action-based URL structure
- Some actions show the action first like /edit/{post_id}
- Some actions show resources first like /post/{post_id}/toggle-publish
- RESTful APIs should be resource-centric, but as shown above, many endpoints are not only inconsistent, but also action-centric (/delete/{post_id}, /post/{post_id})
3. Duplicate endpoints
- Using two methods for the same URL
- For /write, GET to render UI, POST to register post
I said I was going to list just a few, but then again, this is really bad, so I'm going to explain what I've learned about designing RESTful APIs that I only had a vague idea of.
What is a RESTful API?
An API that follows the design principles of the Representational State Transfer (REST) architecture style.
Features of RESTful APIs
- Resource-centered structure: Clearly express resources through URIs
- Utilize HTTP methods: Perform CRUD on resources with HTTP methods such as GET, POST, PUT, DELETE, etc.
- Stateless: All requests are independent, and the server does not store the client's state
- Cacheability: responses can be cached to improve performance
- Client-server structure: client and server roles are clearly separated
- tiering: can be organized into multiple tiers for security, load balancing, etc.
- interface consistency: information is sent and received in a standardized way, allowing for easy integration between systems
As mentioned above, I designed the endpoints to be action-oriented, not resource-oriented, and some of them are even resource-oriented and inconsistent. The HTML methods were also rarely PUT, DELETE, etc.
At one point during the bootcamp, my mentor was looking at another student's web application (not my blog) and told me not to structure it like edit/{id} like I do now, and I thought he was being facetious at the time, but now I realize that he was just speaking from experience.
So how should I design it?
The most important thing to remember when designing a RESTful API is that URIs should represent resources and actions should represent HTTP methods. If you get this right, your API will be clean and consistent.
1. URIs should represent resources of information
URIs in APIs should always be noun-based. If you design an API with verbs, it will not be RESTful.
❌ Bad examples:
/getUsers, /createProduct, /updatePost, /deleteComment
⭕ Good Example:
/users, /products, /posts, /comments
- Groups of resources (collections) are written in plural form = This means you shouldn't do what I'm doing right now.
- Single resources are written in the singular form.
2. Express HTTP method behavior
When creating a CRUD function, the resource itself should be represented by a URI and the action should use an HTTP method.
- Create -> POST(/posts)
- Read -> GET(/posts/1)
- Update -> PUT(/posts/1)
- Delete -> DELETE(/posts/1)
❌ Wrong example:
GET /posts/show/1
POST /posts/insert/2
⭕ Correct example:
GET /posts/1
POST /posts
3. Reflect the hierarchy between resources
When there is a dependency between resources, you should use a forward slash (/) to indicate hierarchy. ** [CODE: ### 3.
For example, if you want to fetch the comments of a specific post?
❌ Incorrect example:
GET /comments?postId=1
⭕ Correct example:
GET /posts/1/comments
4. Don't put a forward slash (/) at the end of a URI
It's important to keep URIs clean in REST APIs. Adding / to the end of a URI only adds confusion. (I learned this the hard way when setting up the NGINX reverse proxy for the ELK stack).
❌ http://api.example.com/users/
⭕ http://api.example.com/users
5. Use only lowercase letters in URIs
Using uppercase letters can be confusing, as well as making the API case sensitive. RFC 3986 (URI Grammar Format) also recommends that URIs be written in lowercase.
❌ /Users/Kim
⭕ /users/kim
6. Use hyphens (-) to improve readability
Using a hyphen (-) instead of an underscore ( _ ) makes it easier to read. (This is a bit confusing because it differs from Python's national snake case).
❌ /products/electronics/computer_accessories
⭕ /products/electronics/computer-accessories
7. Filtering, sorting, and pagination with query parameters
When dealing with collections, you can utilize query parameters to apply search, filtering, and sorting.
/users?name=Kim&age=25&sort=asc&page=2
You should use these intuitive keywords.
❌ Bad example: /users?q=Kim&f=25&o=asc&l=2
⭕ Good example: /users?name=Kim&age=25&sort=asc&page=2
8. Use verbs for specific behaviors
Any special behavior outside of CRUD (activation, deactivation, authorization, etc.) should use verbs to make your API clear.
❌ Incorrect example: /users/1/status
⭕ Correct example: /users/1/activate
❌ Incorrect example: /products/123/delivery
⭕ Correct example: /products/123/send
Conclusion.
I tried to design along these features and design directions, but in the case of /write, which I mentioned earlier as a bad design in the current state, if you want to design it RESTful, you need to pass only the storage API to /posts and separate the GET API that performs UI rendering into a separate /write route, but I think that will make the structure dirty, so I need to think more about whether to apply strict RESTful rules or to follow the big framework but apply some flexibility. So for now, I think I'll put the endpoint and structure refactoring of FastAPI on the back burner and build Next.js first to see if it works with the current structure and then proceed from there.
Kakao
Google
Naver