HTTP 프로토콜에 대한 이해
HTTP(HyperText Transfer Protocol)는 TCP 기반의 응용 계층 프로토콜로, 기본 포트는 80번을 사용합니다. 본질적으로 클라이언트와 서버 간의 소켓 통신이며, 요청(Request) → 응답(Response) → 연결 종료의 흐름을 따릅니다.
주요 특징으로는 "비연결(connectionless)"과 "무상태(stateless)"가 있습니다. 무상태 문제를 해결하기 위해 쿠키(Cookie)와 세션(Session) 메커니즘이 도입되었습니다.
HTTP 요청은 요청 라인, 요청 헤더, 요청 바디로 구성되며, 헤더와 바디 사이에는 \r\n\r\n으로 구분합니다.
주요 상태 코드:
- 200: 요청 성공
- 301: 영구 리다이렉트
- 302: 임시 리다이렉트
- 403: 접근 금지 (CSRF 검증 실패 시 발생 가능)
- 500: 서버 내부 오류
주요 HTTP 메서드: GET, POST, PUT, PATCH, DELETE, OPTIONS
중요한 요청 헤더:
- Cookie: 세션 관리
- Content-Type: 전송 데이터 형식 지정
- User-Agent: 클라이언트 정보 식별
- Referer: 이전 페이지 정보, 보안(예: 도메인 차단)에 활용
요청 바디 관련: Django에서 request.POST는 application/x-www-form-urlencoded 형식만 처리하며, JSON 형태의 AJAX 요청은 request.body를 통해 직접 읽어야 합니다.
Django 요청 수명 주기 (DRF 포함)
클라이언트 요청 → WSGI → 미들웨어(process_request) → URL 라우팅 → 미들웨어(process_view) → 뷰 실행 → 미들웨어(process_template_response) → 최종 응답 반환
DRF를 사용하면 APIView가 내부적으로 요청을 감싸고, 인증, 권한, 제한 등의 로직을 추가로 수행합니다.
미들웨어란 무엇인가? 어떤 작업을 해보았는가?
미들웨어는 요청과 응답 중간에 개입하여 공통 로직을 처리하는 컴포넌트입니다. 요청 전처리 및 응답 후처리가 가능합니다.
내장 미들웨어 예시: CSRF 보호, 세션 관리, CORS 설정 등.
실제 적용 사례:
- 사용자 인증 및 JWT 토큰 검증
- API 접근 권한 체크
- 요청 빈도 제한 (Rate Limiting)
- 정적 파일 제공
- CORS(Cross-Origin Resource Sharing) 허용 설정
CSRF 동작 원리
CSRF(Cross-Site Request Forgery) 공격 방지를 위해, 서버는 클라이언트에게 고유한 토큰을 발급하고, POST 등 중요한 요청 시 해당 토큰을 함께 제출하도록 요구합니다. 서버는 제출된 토큰이 유효한지 검증하여 악의적인 요청을 차단합니다.
RESTful 아키텍처 10가지 규칙
- HTTP 메서드 기반 연산: GET(조회), POST(생성), PUT(전체 수정), PATCH(부분 수정), DELETE(삭제)
- 자원 중심 설계: URI는 명사 형태로 자원을 표현 (예:
/users) - 버전 관리:
/api/v1/users또는 하위 도메인api.example.com/v1/users - API 명시: URL에
api를 포함하여 API임을 명확히 함 - HTTPS 사용: 민감한 데이터 전송 시 반드시 암호화 통신
- 적절한 상태 코드 반환: 2xx(성공), 3xx(리다이렉트), 4xx(클라이언트 오류), 5xx(서버 오류)
- 쿼리 파라미터로 조건 전달: 페이징(
?page=1&size=10), 필터링 등 - 응답 구조 표준화:
{ "code": 10000, "data": [ {"id": 1, "name": "홍길동"}, {"id": 2, "name": "김철수"} ] } - 오류 응답 일관성 유지:
{ "code": 10001, "error": "사용자를 찾을 수 없습니다." } - 하이퍼미디어 링크 포함 (HATEOAS): 응답 데이터 내 관련 자원의 URI를 포함
{ "id": 1, "name": "홍길동", "department_url": "https://api.example.com/api/v1/departments/5/" }
DRF 주요 구성 요소 흐름
URL 라우팅 → 뷰(View) → 버전 관리 → 인증(Authentication) → 권한(Authorization) → 요청 빈도 제어 → 파서(Parser) → 직렬화(Serializer) → 페이징(Pagination) → 렌더러(Renderer)
Serializer 활용 패턴
복잡한 관계형 데이터를 JSON 형태로 변환할 때 다양한 기법을 사용합니다.
- 일대일 관계:
source속성을 사용해 관련 모델의 필드 참조 - Choice 필드 처리:
get_field_display메서드를 활용해 레이블 값 반환 - 일대다/다대다 관계:
SerializerMethodField()사용하여 커스텀 메서드 정의
class UserProfileSerializer(serializers.ModelSerializer):
user_name = serializers.CharField(source='user.username')
gender_label = serializers.CharField(source='get_gender_display')
hobbies = serializers.SerializerMethodField()
articles = serializers.SerializerMethodField()
class Meta:
model = Profile
fields = ['user_name', 'gender_label', 'hobbies', 'articles']
def get_hobbies(self, obj):
return [hobby.name for hobby in obj.hobbies.all()]
def get_articles(self, obj):
articles = obj.user.article_set.filter(is_published=True)
return [{'id': a.id, 'title': a.title} for a in articles]
주요 상속 클래스 계층 구조
DRF에서는 다양한 추상화 레벨의 클래스를 제공하며, 아래와 같은 상속 구조를 가집니다.
class View:
pass
class APIView(View):
# DRF의 기본 뷰, 요청/응답 객체 확장
class GenericAPIView(APIView):
# 쿼리셋, 직렬화, 페이징 등 공통 기능 제공
class ViewSetMixin:
# ViewSet 동작을 위한 믹스인
class GenericViewSet(ViewSetMixin, GenericAPIView):
# 제네릭 기능을 갖춘 ViewSet
class ModelViewSet(
mixins.CreateModelMixin,
mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
mixins.ListModelMixin,
GenericViewSet
):
# CRUD 전체를 지원하는 완전한 ViewSet