백엔드 Back-end 93

Q. HTTP GET 메소드로 Body에 데이터를 실어서 보내면 데이터가 갈까?

A. 간다. 패킷을 보면 전송되는 것을 확인할 수 있다! GET의 경우 Body에 데이터를 실어서 보내도 안 갈거라고 생각했는데 간다는 얘기를 듣고 직접 해보게 되었다. 같은 네트워크 상에 두 컴퓨터를 켜서 요청을 받는 컴퓨터에 WireShark를 설치했다. 192.168.1.23 컴퓨터에서 PostMan으로 메소드는 GET 요청 바디(Request Body)에 Content-Type: application/x-www-form-urlencded로 userId=1이란 값을 입력하고 전송 버튼을 눌렀다. 따라서 192.168.1.23 컴퓨터가 Source 출발지, 192.168.1.2가 Destination 도착지이다. 192.168.1.2에서 WireShark를 실행해서 패킷을 확인했다. userId=1을..

Python requests와 pytest로 REST API 서버 테스트하기

자바스크립트 기반인 frisby.js로 REST API 서버 테스트를 할 수도 있지만, 파이썬이 익숙하다면 requests로도 쉽게 구현할 수 있다. 준비: API 서버 실행 우선 FastAPI 예제를 실행한다. 예제코드는 FastAPI - Email Login with Password.. 여기 있다. localhost:8000/docs로 접속했을 때 아래처럼 뜬다면 정상 작동하고 있는 것이다. API 테스트 코드 작성 위에 브라우저로 확인한 것을 그냥 코드로 아래처럼 작성해서 확인할 수도 있다. import requests def test_get_docs(): endpoint = "http://localhost:8000/docs/" response = requests.get(endpoint) asser..

Q. 장고Django에서 외래키ForeignKey 필드의 id를 얻을 때, field.id를 쓰지 말고 field_id를 써야 하는 이유는?

A. 쓸데 없이 데이터베이스에 Select 쿼리를 날리기 때문이다. 간단히 다음과 같은 장고 모델이 있다고 하자. 전체 코드는 DRF_CRUD 예제에서 확인할 수 있다. from django.db import models class Category(models.Model): name = models.CharField(max_length=200) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) class Beverage(models.Model): name = models.CharField(max_length=200) category = models.ForeignKey(Cat..

Q. MySQL 데이터베이스 쿼리 비용Query Cost를 확인하는 방법은?

A. MySQL Workbench를 활용하면 쿼리 비용을 확인할 수 있다! MySQL Workbench에서 번개에 돋보기가 있는 아이콘을 누르면 쿼리 비용을 숫자로 확인할 수 있다. 바로 아래 이미지 아이콘이다. 예를 들어서 아래와 같은 쿼리문의 비용을 확인해보자. SELECT beverage.name, beverage.price FROM beverage INNER JOIN category ON beverage.category_id = category.id; 번개돋보기 아이콘을 누르면 아래처럼 쿼리 비용 1.10이라고 나타나는 것을 확인할 수 있다. 이번에는 LEFT JOIN 예이다. SELECT beverage.name, beverage.price FROM beverage LEFT JOIN catego..

Q. MySQL 인덱스 타는지 안 타는지 확인하는 방법은?

A. Explain을 활용하면 쉽게 확인할 수 있다. 예를 들어서 아래와 같은 쿼리문이 인덱스를 타는지 궁금하다. SELECT beverage.name, beverage.price FROM beverage LEFT JOIN category ON beverage.category_id = category.id; 이때 SELECT 앞에 EXPLAIN만 붙여두면 확인할 수 있다. 아래 예처럼 말이다. EXPLAIN SELECT beverage.name, beverage.price FROM beverage LEFT JOIN category ON beverage.category_id = category.id; 실제 실행해보면 아래 예처럼 결과가 나온다. Extra에 나온 정보를 보면 Using index를 통해서 ..

셸 스크립트로 MySQL 데이터베이스 원격에서 로컬 데이터베이스로 복사하기

백엔드 개발을 하다보면 QA용 테스트 데이터베이스를 내 컴퓨터 로컬 데이터베이스로 복사를 자주하게 된다. DBeaver, Workbench 등 데이터베이스 클라이언트 프로그램을 이용해도 되지만 번거롭다. 매번 복사할 데이터베이스를 선택하고, export 누르고, 다시 로컬 데이터베이스에 접속해서 import 누르는 과정을 진행하는데도 시간이 꽤 걸린다. 자칫 잘못하면 로컬 데이터베이스를 QA 테스트 데이터베이스로 거꾸로 복사할 수도 있으니 집중해야 해서 더 피곤하다. 그래서 셸 스크립트로 만들었다. #!/bin/bash # 원격 데이터베이스 MYSQL_HOST="" MYSQL_USER="" MYSQL_PASSWORD="" # 로컬 데이터베이스 MYSQL_HOST_LOCAL="127.0.0.1" MYSQL..

Q. 장고에 gunicorn을 같이 써야 하는 이유는?

A. CPU가 여러개인 환경에서는 훨씬 빠르기 때문이다. 그밖에 HTTPS 적용 등 다양한 기능을 활용할 수 있다. 먼저 이 글 Q. NGINX, gunicorn없이 Django장고만 실행 가능할까? 을 참고해서 gunicorn 없이 테스트를 진행하자. gunicorn 설치하고 실행하기 아래 명령어를 참고해서 gunicorn을 설치하고 실행하자. $ pip install gunicorn $ sudo GUNICORN_CMD_ARGS="--bind=0.0.0.0:80 --workers=3" ./venv/bin/gunicorn config.wsgi:application 설정 설명을 보면 추천 worker수는 CPU core수의 2~4배다. Worker Processes workers Command line: ..

Q. NGINX, gunicorn없이 Django장고만 실행 가능할까?

A. 보통은 Nginx - gunicorn - Django로 구성한다. 보통 권장되지 않지만 Django장고만 실행할 수도 있다. 로컬에서 테스트할 때처럼 하면 되고 차이점은 서버 실행 명령어다. 실행 방법 직접 해보면 잘 된다. 장고 실행하기 우선 EC2에 장고를 설치하고 실행해보자. django_minimal을 참고하자. 아래 실행 환경은 EC2 Ubuntu 20.04(t2.micro)다. EC2에 접속해서 아래처럼 진행하면 된다. $ sudo apt update $ sudo apt install python3.8-venv $ mkdir django_minimal $ cd django_minimal$ $ python3 -m venv venv $ source ./venv/bin/activate $ pi..

Q. MongoDB 데이터베이스 백업Dump과 복원Restore 하는 방법은?

A. mongodump와 mongorestore 명령어를 활용하면 된다. EC2에 아래 글을 참고해서 우선 MongoDB를 설치하자. 참고할 글: Q. AWS EC2에 MongoDB 설치하고 외부 접속 가능하게 만드는 방법은? 테스트 데이터 입력하기 MongoDB Compass로 접속해서 아래처럼 test란 데이터베이스를 만들고 collection이란 collection을 만들어서 아무 데이터나 하나 넣었다. mongodump 어드민으로 사용자를 추가한 경우 --authenticationDatabase="admin" 를 추가해줘야 한다. mongodump --host="3.35.154.100:27017" --username="taptorestart" --password="password" --db="te..

Q. 유명 개발자들은 파이썬 테스트 코드를 어떻게 작성할까?

A. 사례를 찾아보면 진짜 생각보다 간단하게 짠다. 테스트 코드 작성 어렵다. 작성하면서도 이게 과연 올바른가 의심될 때가 있다. 이럴 때는 유명 개발자들은 어떻게 하는지 찾아보는 것만으로도 큰 도움이 된다. 게다가 개발 바닥은 쉽게 찾을 수 있으니! 구글 구글부터 살펴보자. github에서 구글로 들어가서, 언어는 파이썬, 정렬은 별개수로 하자. 목록 상단에 있는 google / jax를 골랐다. 여기 들어가니 tests 디렉터리가 있다! 여러 테스트 파일 중 core_test.py를 보자. tree_flatten이란 함수를 테스트하는 코드는 아래가 다다. 값은 직접 입력했고, 입력한 값은 아주 간단한 것을 볼 수 있다. 10개가 아니라 1개다. def test_tree_flatten(self): fl..

Q. 장고 ORM에서 OneToOneField와 ForeignKey에 unique=True를 한 경우 서로 어떤 차이가 있을까?

A. 데이터베이스 상으로는 차이가 없다. 예제 코드는 DRF CRUD 예제 프로젝트를 활용했다. 데이터베이스 설정만 MySQL로 변경했다. 변경한 예는 아래와 같다. DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'test', 'USER': 'root', 'PASSWORD': 'password', 'HOST': '127.0.0.1', 'PORT': '3306', } } 환경은 장고는 3.2.12 파이썬은 3.8 버전이다. ForeignKey 그냥 ForeignKey 모델이다. from django.db import models class Category(models.Model): name = models.CharField..

frisby.js로 REST API 서버 테스트 하기

frisby.js란? "Frisby makes REST API testing easy, fast, and fun." - frisby.js 소개에서 "Frisby는 REST API 테스트를 쉽고, 빠르고 재미있게 만든다." REST API 테스트용 라이브러리다. 어떤 언어로 되어 있나? 자바스크립트 기반이고, 테스트를 실행하기 위해서 Jest를 사용한다. 테스트 코드 자체가 반복적이기 때문에 엄청 높은 수준의 자바스크립트 지식을 필요로 하지는 않는다. 자바 기반 스프링부트나 파이썬 기반 장고 등 다른 언어로 API 서버를 개발해도 쉽게 frisby.js로 테스트 코드를 짤 수 있다. 언제 사용하는가? API 서버를 테스트할 때 사용한다. Postman 같은 API 테스트 플랫폼과 같은 용도다. 장점은 코드..

데이터베이스 예제를 보면서 참고하기

관계형 데이터베이스를 설계 하다보면 다른 사람들은 어떻게 설계하는지 궁금해진다. 특히 전문가들은 어떻게 하는지 궁금해진다. 그때는 예제를 많이 보면 도움이 될 수 있다. Postgresql wiki Sample Databases 에 가면 무료 예제 데이터베이스를 살펴볼 수 있다. 무료 예제 데이터베이스 스키마를 참고하기 편하게 여기에 taptorestart/database-schema-examples 로 정리 중이다.

DRF(Django Rest Framework) API 서버에 requests로 PUT할 때 나타나는 이상현상

BooleanField로 설정한 필드의 값이 만약 default=false라면 모두 false로 변경된다. 간단히 테스트를 위해서 DRF로 API 서버를 만들었다. 주요 모델은 아래처럼 생겼다. (예제코드: DRF CRUD) 모델 class Category(models.Model): name = models.CharField(max_length=200) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) class Beverage(models.Model): name = models.CharField(max_length=200) category = models.ForeignKe..

Lombok @Getter @NoArgsConstructor @Builder @AllArgsConstructor 실제 빌드된 클래스로 살펴보기

Lombok을 사용하면 Getter나 Setter처럼 정말 많이 쓰는 작업을 자동화할 수 있어서 편하다. 테스트를 위해서 User 클래스 하나를 만들었다. 아래처럼 생겼다. package com.test; public class User { private Long id; private String name; private String password; public void update(String name, String password) { this.name = name; this.password = password; } } 빌드해보자. 빌드를 하면 build 디렉터리 아래 class 파일이 생성된다. 원래는 알아볼 수 없게 생겼다. IntelliJ IDEA 상에서 빌드된 파일을 클릭하면 디컴파일러를 통..

Q. API 서버에서 인메모리 데이터베이스를 캐시cache로 쓰면 얼마나 빨라질까?

A. 응답을 받는데 1초가 걸리던 엔드포인트가 있다면, 100배 넘게 빨라질 수 있다! 처음에 1초 걸리던 게, 그 다음에는 0.0003초 걸렸다. 3000배 이상 빨라진 것이다. 컴퓨터 성능에 따라 다르지만 보통 100배 이상 빨라질 수 있다. 위 캡쳐화면을 통해서 왜 인메모리 데이터베이스를 캐시로 써야 하는지 쉽게 이해할 수 있다. 캐시를 쓰는 것만으로도 성능을 엄청나게 빠르게 할 수 있으니, 당연히 써야 한다. 구현 방법 구현 방법은 간단하다. redis 같은 메모리 데이터베이스에 endpoint와 파라미터 전체 url을 키로 넣고, 응답을 값으로 해서 저장하는 식이다. 그럼 완전히 동일한 endpoint와 파라미터로 다시 요청이 왔을 때 메모리 상에 저장해둔 응답을 바로 보내주면 아주 빨리 처리할..

Q. kafka에서 group_id를 설정하면 어떻게 될까?

A. group id가 같을 경우 한 클라이언트에서만 메시지를 소비(consume)할 수 있다. 테스트를 위한 코드: python kafka - producer and consumer 아래처럼 group_id를 설정한 경우에 consumer를 터미널 창을 두 개 띄워서 테스트할 경우 한쪽에서만 메시지를 받을 수 있다. import kafka consumer = kafka.KafkaConsumer(bootstrap_servers='localhost:9092', group_id='test-group') consumer.subscribe(topics=['quickstart-events']) for msg in consumer: print(msg) group_id를 설정하지 않은 경우에는 양쪽에 같은 메시지가 ..

백엔드 Back-end 2022.04.11

FastAPI 바탕 프로젝트: 이메일 회원 가입과 JWT 토큰, MySQL 사용

Full Stack FastAPI and PostgreSQL - Base Project Generator, MIT License을 바탕으로 다른 프로젝트의 시작점이 될 수 있는 베이스 프로젝트를 만들었다. 주요 기능 주요 기능은 다음과 같다. - 이메일과 비밀번호로 회원가입 - 비밀번호 암호화 - 관리자(superuser) 생성 - JWT 토큰으로 사용자 식별 및 권한 제어 - ORM 적용 - MySQL 사용 프로젝트 루트 디렉터리에 .env 파일을 만들어서 저장해둬야 정상 작동한다. .env 파일 예는 아래와 같다. 데이터베이스 정보와, 비밀키, 첫 관리자 생성 정보다. USERNAME=admin PASSWORD=verysecret HOST=localhost PORT=3306 DATABASE=app S..