📌 Mini Project: Flask로 만드는 인스타그램 REST API
이 프로젝트는 Flask를 이용해 간단한 REST API를 구현하여 인스타그램의 사용자 및 게시물 관리를 수행합니다.
🚦 구현해야 할 주요 API 목록
HTTP Method Endpoint 설명
GET | /users | 모든 사용자 조회 |
POST | /users | 새로운 사용자 생성 |
POST | /users/post/<username> | 사용자 게시물 추가 |
GET | /users/post/<username> | 사용자 게시물 목록 조회 |
PUT | /users/post/like/<username>/<title> | 특정 게시물의 좋아요 수 증가 |
DELETE | /users/<username> | 사용자 삭제 |
💻 구현 코드와 단계별 설명
app.py
from flask import Flask, request, render_template
app = Flask(__name__)
# 사용자 데이터를 저장하는 리스트
users = [
{
"username": "leo",
"posts": [{"title": "Town House", "likes": 120}]
},
{
"username": "alex",
"posts": [{"title": "Mountain Climbing", "likes": 350}, {"title": "River Rafting", "likes": 200}]
},
{
"username": "kim",
"posts": [{"title": "Delicious Ramen", "likes": 230}]
}
]
@app.get("/")
def index():
# 모든 사용자 정보를 JSON 형태로 반환
return render_template('index.html')
@app.get("/users")
def get_users():
# 모든 사용자 정보를 JSON 형태로 반환
return {"users": users}
@app.post("/users")
def create_user():
# 클라이언트로부터 받은 JSON 데이터
request_data = request.get_json()
# 새 사용자 객체 생성
new_user = {"username": request_data["username"], "posts": [{"title": "My First Post", "likes": 0}]}
# 사용자 리스트에 새 사용자 추가
users.append(new_user)
# 생성된 사용자 정보와 HTTP 상태코드 201 반환
return new_user, 201
@app.post("/users/post/<string:username>")
def add_post(username):
# 클라이언트로부터 받은 JSON 데이터
request_data = request.get_json()
# 해당 사용자를 찾아 게시물 추가
for user in users:
if user["username"] == username:
new_post = {"title": request_data["title"], "likes": request_data["likes"]}
user["posts"].append(new_post)
return new_post
# 사용자를 찾지 못한 경우 오류 메시지 반환
return {"message": "User not found"}, 404
@app.get("/users/post/<string:username>")
def get_posts_of_user(username):
# 특정 사용자의 모든 게시물 반환
for user in users:
if user["username"] == username:
return {"posts": user["posts"]}
# 사용자를 찾지 못한 경우 오류 메시지 반환
return {"message": "User not found"}, 404
@app.put("/users/post/like/<string:username>/<string:title>")
def like_post(username, title):
# 특정 게시물의 좋아요 수 증가
for user in users:
if user["username"] == username:
for post in user["posts"]:
if post["title"] == title:
post["likes"] += 1
return post
# 게시물을 찾지 못한 경우 오류 메시지 반환
return {"message": "Post not found"}, 404
@app.delete("/users/<string:username>")
def delete_user(username):
# 전역 users 리스트에서 특정 사용자 삭제
global users
users = [user for user in users if user["username"] != username]
# 삭제 성공 메시지와 HTTP 상태코드 200 반환
return {"message": "User deleted"}, 200
# 애플리케이션 실행
if __name__ == '__main__':
app.run(debug=True)
index.html
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>사용자 관리 시스템</title>
<script>
// 사용자 목록을 요청하여 화면에 출력
function getUsers() {
fetch('/users')
.then(response => response.json())
.then(data => {
let userList = document.getElementById('user-list');
userList.innerHTML = ''; // 기존 목록 초기화
data.users.forEach(user => {
// 각 사용자와 해당 사용자의 게시물 제목을 출력
let postTitles = user.posts.map(post => post.title).join(', ');
userList.innerHTML += `<li>${user.username} - 게시물: ${postTitles}</li>`;
});
});
}
// 사용자 생성 요청
function createUser() {
const username = document.getElementById('new-username').value;
fetch('/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ "username": username })
})
.then(response => response.json())
.then(data => {
alert('사용자가 생성되었습니다: ' + data.username);
getUsers();
});
}
// 특정 사용자에 게시물 추가
function addPost() {
const username = document.getElementById('post-username').value;
const title = document.getElementById('post-title').value;
const likes = parseInt(document.getElementById('post-likes').value, 10);
fetch(`/users/post/${username}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ "title": title, "likes": likes })
})
.then(response => response.json())
.then(data => {
alert('게시물이 추가되었습니다: ' + data.title);
getPosts(username);
});
}
// 특정 사용자의 게시물 조회
function getPosts(username) {
fetch(`/users/post/${username}`)
.then(response => response.json())
.then(data => {
let postList = document.getElementById('post-list');
postList.innerHTML = ''; // 기존 목록 초기화
data.posts.forEach(post => {
postList.innerHTML += `<li>${post.title} - 좋아요: ${post.likes}</li>`;
});
});
}
// 게시물 좋아요 수 증가
function likePost() {
const username = document.getElementById('like-username').value;
const title = document.getElementById('like-title').value;
fetch(`/users/post/like/${username}/${title}`, {
method: 'PUT'
})
.then(response => response.json())
.then(data => {
alert('게시물의 좋아요가 증가되었습니다: ' + data.likes);
getPosts(username);
});
}
// 사용자 삭제 요청
function deleteUser() {
const username = document.getElementById('delete-username').value;
fetch(`/users/${username}`, {
method: 'DELETE'
})
.then(response => response.json())
.then(data => {
alert('사용자가 삭제되었습니다');
getUsers();
});
}
</script>
</head>
<body>
<h1>사용자 관리 시스템</h1>
<h2>1. 사용자 목록 조회</h2>
<button onclick="getUsers()">사용자 목록 조회</button>
<ul id="user-list"></ul>
<h2>2. 사용자 생성</h2>
<input type="text" id="new-username" placeholder="사용자 이름">
<button onclick="createUser()">사용자 생성</button>
<h2>3. 게시물 추가</h2>
<input type="text" id="post-username" placeholder="사용자 이름">
<input type="text" id="post-title" placeholder="게시물 제목">
<input type="number" id="post-likes" placeholder="좋아요 수">
<button onclick="addPost()">게시물 추가</button>
<h2>4. 사용자별 게시물 조회</h2>
<input type="text" id="get-posts-username" placeholder="사용자 이름">
<button onclick="getPosts(document.getElementById('get-posts-username').value)">게시물 조회</button>
<ul id="post-list"></ul>
<h2>5. 게시물 좋아요 수 증가</h2>
<input type="text" id="like-username" placeholder="사용자 이름">
<input type="text" id="like-title" placeholder="게시물 제목">
<button onclick="likePost()">좋아요 증가</button>
<h2>6. 사용자 삭제</h2>
<input type="text" id="delete-username" placeholder="사용자 이름">
<button onclick="deleteUser()">사용자 삭제</button>
</body>
</html>
📚 파이썬 리스트 컴프리헨션
리스트 컴프리헨션은 리스트를 간단하고 효율적으로 생성하는 방법입니다.
기본 형식:
[표현식 for 항목 in 반복가능객체 if 조건]
사용 예시:
예시 코드 설명 결과
[n ** 2 for n in [1,2,3,4,5]] | 각 숫자를 제곱 | [1, 4, 9, 16, 25] |
[n*2 for n in [1,2,3,4,5] if n%2==1] | 홀수만 선택해 두 배로 변환 | [2, 6, 10] |
[word.upper() for word in ["hello", "world"]] | 모든 단어를 대문자로 변환 | ["HELLO", "WORLD"] |
[n**2 if n%2==0 else n*2 for n in [1,2,3]] | 짝수는 제곱, 홀수는 두 배로 변환 | [2, 4, 6] |
🧪 실행 및 테스트 방법
- 서버 실행:
python app.py
- API 테스트 예시 (curl 이용):
- 사용자 목록 조회:
curl http://127.0.0.1:5000/users
- 사용자 추가:
curl -X POST -H "Content-Type: application/json" -d '{"username":"john"}' http://127.0.0.1:5000/users
- 게시물 추가:
curl -X POST -H "Content-Type: application/json" -d '{"title":"Beach Trip","likes":100}' http://127.0.0.1:5000/users/post/john
- 특정 게시물 좋아요 증가:
curl -X PUT http://127.0.0.1:5000/users/post/like/john/Beach%20Trip
- 사용자 삭제:
curl -X DELETE http://127.0.0.1:5000/users/john
3개의 파일로 관리할경우 추가 2개 파일
user_routes.py - 사용자 관련 라우트 정의
from flask import request
from user_model import users, add_user, add_post_to_user, get_user_posts, like_user_post, delete_user
def register_routes(app):
@app.route("/users", methods=["GET", "POST"])
def users_route():
if request.method == "GET":
return {"users": users}
elif request.method == "POST":
request_data = request.get_json()
return add_user(request_data)
@app.route("/users/post/<string:username>", methods=["POST"])
def add_post(username):
request_data = request.get_json()
return add_post_to_user(username, request_data)
@app.route("/users/post/<string:username>", methods=["GET"])
def get_posts(username):
return get_user_posts(username)
@app.route("/users/post/like/<string:username>/<string:title>", methods=["PUT"])
def like_post(username, title):
return like_user_post(username, title)
@app.route("/users/<string:username>", methods=["DELETE"])
def delete(username):
return delete_user(username)
user_model.py - 사용자 데이터 및 관련 함수 정의
users = [
{"username": "leo", "posts": [{"title": "Town House", "likes": 120}]},
{"username": "alex", "posts": [{"title": "Mountain Climbing", "likes": 350}, {"title": "River Rafting", "likes": 200}]},
{"username": "kim", "posts": [{"title": "Delicious Ramen", "likes": 230}]}
]
def add_user(request_data):
new_user = {"username": request_data["username"], "posts": []}
users.append(new_user)
return new_user, 201
def add_post_to_user(username, request_data):
for user in users:
if user["username"] == username:
new_post = {"title": request_data["title"], "likes": 0}
user["posts"].append(new_post)
return new_post, 201
return {"message": "User not found"}, 404
def get_user_posts(username):
for user in users:
if user["username"] == username:
return {"posts": user["posts"]}
return {"message": "User not found"}, 404
def like_user_post(username, title):
for user in users:
if user["username"] == username:
for post in user["posts"]:
if post["title"] == title:
post["likes"] += 1
return post, 200
return {"message": "Post not found"}, 404
def delete_user(username):
global users
users = [user for user in users if user["username"] != username]
return {"message": "User deleted"}, 200
✅ 마무리 및 복습 포인트
- Flask를 활용하여 간단한 REST API를 구현할 수 있습니다.
- JSON 데이터 처리와 RESTful 라우팅 방법을 익힐 수 있습니다.
- 리스트 컴프리헨션을 사용하면 코드가 간결해지고 효율성이 높아집니다.
'Flask' 카테고리의 다른 글
Chapter 5-5 Flask 기반 JWT 인증과 Todo 앱 구축 (0) | 2025.04.23 |
---|---|
Chapter 5-3 Flask와 Jinja를 활용한 사용자 관리 웹 애플리케이션 (0) | 2025.04.23 |
Chapter 5-2 Flask Authentication / Flask-JWT-Extended (0) | 2025.04.23 |
Chapter 5-1 Flask Authentication / Flask-login (0) | 2025.04.22 |
Chapter 4-8(1) Flask 애플리케이션에서 HTTP 기본 인증 사용 (0) | 2025.04.22 |