Python을 사용하여 Recipe Finder 애플리케이션을 구축하는 방법
수많은 링크와 광고로 가득 찬 인터넷에서 완벽한 레시피를 찾기란 마치 광활한 사막에서 오아시스를 찾는 것과 같습니다. 하지만 개인 맞춤형 레시피 검색 앱을 개발한다면, 사용자가 불필요한 정보나 방해 요소 없이, 일관된 디자인과 사용자 친화적인 환경에서 원하는 레시피를 쉽게 찾을 수 있도록 도울 수 있습니다.
이러한 앱을 만드는 과정은 HTTP 요청 처리, API 키 관리, 이미지 조작, 그리고 동적인 사용자 인터페이스 구축 등 다양한 기술을 숙달하는 데 도움이 됩니다. 특히 그래픽 사용자 인터페이스(GUI) 개발 능력을 향상시킬 수 있는 좋은 기회가 될 것입니다.
필수 모듈 설치: Tkinter, Requests, Pillow, Webbrowser
레시피 검색 앱을 개발하기 위해서는 Tkinter, Requests, PIL(Pillow), 그리고 Webbrowser 모듈이 필요합니다. Tkinter는 데스크톱 애플리케이션을 만들 수 있는 강력한 도구이며, 다양한 위젯을 제공하여 GUI 개발을 간편하게 만들어 줍니다. Tkinter를 설치하려면 터미널을 열고 다음 명령을 실행하세요.
pip install tkinter
Requests 모듈은 HTTP 요청을 단순화하여 데이터를 주고받는 데 사용됩니다. 이를 통해 응답 객체를 쉽게 처리하고, 웹사이트 상태 검사기, 환율 변환기, 뉴스 앱 등 다양한 기능을 만들 수 있습니다. Requests 모듈을 설치하려면 터미널에서 다음을 실행하세요.
pip install requests
Pillow 라이브러리는 이미지 편집, 생성, 파일 형식 변환 및 저장과 같은 이미지 처리 기능을 제공합니다. Pillow를 설치하려면 터미널에서 다음 명령을 실행하세요.
pip install Pillow
Webbrowser 모듈은 사용자가 링크를 클릭했을 때 기본 브라우저를 통해 열어주는 데 사용됩니다. Python 표준 라이브러리에 포함되어 있으므로 별도로 설치할 필요는 없습니다.
Edamam API 키 발급
레시피 검색에 필요한 Edamam API 키를 발급받는 방법은 다음과 같습니다.
- 에다맘 웹사이트를 방문하여 회원가입 버튼을 클릭하세요. 상세 정보를 입력하고 "Recipe Search API – 개발자" 플랜을 선택합니다.

- 계정에 로그인한 후, 계정 버튼을 누르고 대시보드로 이동합니다.

- "Applications" 탭을 클릭한 후 "Recipe Search API" 옆에 있는 "View" 버튼을 클릭합니다.

- "Application ID"와 "Application Key"를 복사하여 앱 개발에 사용할 수 있도록 안전하게 보관합니다.
상위 5개 레시피를 가져오는 기능 구현
다음은 Python을 사용하여 레시피 검색 앱을 만드는 데 필요한 전체 소스 코드입니다. 더 자세한 내용은 GitHub 저장소에서 확인할 수 있습니다.
먼저 필요한 모듈을 가져옵니다. `get_top_5_recipes()` 메서드를 정의하여 사용자가 검색한 레시피의 제목, 이미지, 링크를 상위 5개까지 검색합니다. `get()` 함수를 사용하여 사용자가 입력한 레시피 이름을 추출합니다.
사용자가 레시피 이름을 입력했다면, Edamam API의 레시피 검색 엔드포인트 기본 URL을 설정합니다. 발급받은 app_id와 app_key를 사용하여 API 요청을 인증합니다.
import tkinter as tk
import requests
from PIL import Image, ImageTk
import webbrowserdef get_top_5_recipes():
recipe_name = entry_recipe_name.get()
if recipe_name:
api_url = "https://api.edamam.com/search"
app_id =
app_key =
API 요청에 필요한 다양한 매개변수를 `params` 딕셔너리에 저장합니다. `q`, `app_id`, `app_key` 키에 각각 해당하는 값들을 설정하고, `from` 및 `to` 매개변수를 설정하여 가져올 레시피의 범위를 지정합니다.
API URL과 `params` 딕셔너리를 사용하여 Edamam API에 GET 요청을 보냅니다. 응답을 받아 JSON 형식으로 추출하고, 이전 검색 결과를 화면에서 지우기 위해 `clear_recipe_list()` 함수를 호출합니다.
params = {
"q": recipe_name,
"app_id": app_id,
"app_key": app_key,
"from": 0,
"to": 5,
} response = requests.get(api_url, params=params)
data = response.json()
clear_recipe_list()
JSON 데이터에 "hits" 키와 검색 결과가 있는지 확인합니다. 있다면 검색 결과를 순회하며 각 레시피의 정보를 추출합니다. 이미지 URL에 GET 요청을 보내고 `stream=True`로 설정하여 이미지 데이터를 스트리밍 방식으로 받습니다.
Pillow의 `Image` 클래스를 사용하여 이미지를 열고, `LANCZOS` 리샘플링 방식을 사용하여 이미지 크기를 200x200 픽셀로 조정합니다. 이 이미지를 Tkinter에서 사용할 수 있는 `PhotoImage` 형식으로 변환하여 GUI에 표시합니다.
if "hits" in data and data["hits"]:
for i, hit in enumerate(data["hits"]):
recipe = hit["recipe"]
recipe_list.append(recipe)
recipe_name = recipe["label"]
recipe_link = recipe["url"]
image_url = recipe["image"]image_response = requests.get(image_url, stream=True)
image = Image.open(image_response.raw)
image = image.resize((200, 200), Image.LANCZOS)
photo_image = ImageTk.PhotoImage(image)
애플리케이션 구조 설계
레시피 제목, 이미지, 링크를 표시할 세 개의 레이블을 정의합니다. 레이블을 배치할 상위 창, 표시할 텍스트, 글꼴 스타일을 설정합니다. 이미지를 표시하기 위해 `image` 속성을 `photo_image`로 설정합니다. 링크 레이블의 커서 옵션을 `hand2`로 설정하여 사용자가 클릭할 수 있도록 만듭니다.
링크를 클릭했을 때 `open_link()` 함수가 실행되도록 바인딩합니다. `pack` 메서드를 사용하여 위젯들을 구성하고, 수평 가운데 정렬과 패딩을 추가합니다. 제목, 이미지, 링크를 각각 다른 리스트에 저장합니다.
recipe_title_label = tk.Label(
canvas_frame,
text=f"{i+1}. {recipe_name}",
font=("Helvetica", 12, "bold"),
)
recipe_title_label.pack(pady=(5, 0), anchor=tk.CENTER)image_response = requests.get(image_url, stream=True)
image = Image.open(image_response.raw)
image = image.resize((200, 200), Image.LANCZOS)
photo_image = ImageTk.PhotoImage(image)
image_label = tk.Label(canvas_frame, image=photo_image)
image_label.image = photo_image
image_label.pack(pady=(0, 5), anchor=tk.CENTER)link_label = tk.Label(
canvas_frame, text=recipe_link, fg="blue", cursor="hand2"
)
link_label.pack(pady=(0, 10), anchor=tk.CENTER)
link_label.bind(
"<Button-1>", lambda event, link=recipe_link: open_link(link)
)recipe_labels.append(recipe_title_label)
recipe_images.append(photo_image)
recipe_links.append(link_label)
이전 요청으로 생성된 화면 콘텐츠를 지우기 위해 `clear_recipe_list()` 메서드를 정의합니다. 레시피 목록의 내용을 지우고 `recipe_labels` 리스트에 있는 각 레이블을 반복합니다.
`pack_forget()` 메서드를 호출하여 디스플레이에서 레이블을 제거하지만, 위젯 객체 자체는 그대로 유지합니다.
새로운 데이터가 추가될 수 있도록 `recipe_labels` 리스트를 비웁니다. 이미지와 링크에 대해서도 같은 작업을 반복합니다. 기본 웹 브라우저에서 레시피 링크를 열기 위해 `open_link()` 메서드를 정의합니다.
def clear_recipe_list():
recipe_list.clear()
for label in recipe_labels:
label.pack_forget()
recipe_labels.clear()
for image_label in recipe_images:
image_label.pack_forget()
recipe_images.clear()
for link_label in recipe_links:
link_label.pack_forget()
recipe_links.clear()def open_link(link):
webbrowser.open(link)
Tkinter 루트 창을 초기화합니다. 애플리케이션의 제목, 크기, 배경색을 설정합니다. 프레임 위젯을 정의하고, 부모 요소와 배경색을 설정합니다. 레이블, 입력 필드, 검색 버튼을 만들고, `pack` 메서드를 사용하여 모든 위젯을 구성하고 패딩을 추가합니다.
root = tk.Tk()
root.title("Recipe Finder")
root.geometry("600x600")
root.configure(bg="#F1F1F1")frame = tk.Frame(root, bg="#F1F1F1")
frame.pack(fill=tk.BOTH, expand=tk.YES, padx=20, pady=20)label_recipe_name = tk.Label(
frame, text="Enter Recipe Name:", font=("Helvetica", 14, "bold"), bg="#F1F1F1"
)
label_recipe_name.pack()entry_recipe_name = tk.Entry(frame, font=("Helvetica", 12))
entry_recipe_name.pack(pady=5)search_button = tk.Button(
frame,
text="Search Recipes",
font=("Helvetica", 12, "bold"),
command=get_top_5_recipes,
)
search_button.pack(pady=10)
레시피 정보가 들어갈 위젯을 표시하기 위해 흰색 배경의 캔버스를 생성합니다. 캔버스를 창 왼쪽에 배치하고, 프레임의 남은 공간을 채우도록 확장합니다.
캔버스에 세로 스크롤바를 추가하고 오른쪽 끝에 배치합니다. `scrollbar.set` 메서드를 `canvas.yview` 메서드에 연결하여 스크롤바를 움직일 때 캔버스 내용이 스크롤되도록 설정합니다.
창의 왼쪽 상단에 고정되어 레시피 항목을 감싸는 프레임을 캔버스 안에 만듭니다. 내용이 변경되거나 크기가 조정될 때 스크롤이 제대로 작동하도록 `
canvas = tk.Canvas(frame, bg="white")
canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=tk.YES)scrollbar = tk.Scrollbar(frame, orient=tk.VERTICAL, command=canvas.yview)
scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
canvas.configure(yscrollcommand=scrollbar.set)canvas_frame = tk.Frame(canvas, bg="white")
canvas.create_window((0, 0), window=canvas_frame, anchor=tk.NW)
canvas_frame.bind(
"<Configure>", lambda event: canvas.configure(scrollregion=canvas.bbox("all"))
)
레시피 정보, 라벨, 이미지, 링크를 저장할 리스트를 생성합니다. `mainloop()` 함수를 사용하여 Tkinter 이벤트 루프를 시작하고, 창이 닫힐 때까지 이벤트를 처리하도록 설정합니다.
recipe_list = []
recipe_labels = []
recipe_images = []
recipe_links = []root.mainloop()
이제 버튼 클릭 한 번으로 원하는 요리를 검색하고 발견할 수 있습니다.
레시피 검색 애플리케이션 실행 결과
프로그램을 실행하고 "치킨 버거"와 같은 요리를 입력하면, 상위 5개의 검색 결과를 얻을 수 있습니다. 각 결과에는 요리 제목, 이미지, 레시피 링크가 표시됩니다. 링크를 클릭하면 기본 웹 브라우저에서 해당 레시피 페이지가 열립니다. 스크롤을 내리면 화면 크기에 맞춰 내용이 유지되며, 모든 결과가 가로로 가운데 정렬되어 표시됩니다.

레시피 검색 애플리케이션 개선 방안
레시피 검색 애플리케이션을 더욱 개선하기 위해 다양한 필터링 및 정렬 기능을 추가할 수 있습니다. 예를 들어, 사용자의 식단 선호도, 요리 시간, 요리 유형에 따라 레시피를 필터링하고 원하는 순서로 정렬할 수 있습니다.
자주 찾는 레시피를 북마크하여 나중에 쉽게 찾을 수 있도록 하고, 소셜 미디어에 공유하는 기능도 추가할 수 있습니다. 또한, 가장 많이 검색된 요리나 북마크된 요리 등을 찾을 수 있도록 카테고리 기능을 추가하는 것도 유용합니다.
이 기본 애플리케이션에 프로그래밍 기술과 API 기능을 결합하여 더욱 강력한 기능을 가진 본격적인 애플리케이션으로 발전시킬 수 있습니다.