Django 템플릿에서 URL 꺼내기: request.path vs path_info vs get_full_path vs build_absolute_uri

Django 템플릿에서 현재 URL이 필요할 때가 많습니다.

  • 네비게이션 “현재 메뉴 활성화”
  • 로그인 후 “원래 보던 페이지로 돌아가기(next)”
  • canonical URL / 공유 링크 만들기
  • 쿼리스트링 포함해서 “현재 페이지 그대로” 링크 만들기

그런데 {{ request.path }} 말고도 비슷한 애들이 여럿이라 헷갈리죠.
오늘은 헷갈리기 쉬운 아래의 4개만 깔끔하게 비교합니다.

  • request.path
  • request.path_info
  • request.get_full_path()
  • request.build_absolute_uri()

{{ request }}는 대체 어디서 오는가

템플릿에서 {{ request }}가 보인다는 건, 보통 request context processor가 켜져 있다는 뜻입니다.

  • django.template.context_processors.request템플릿 컨텍스트에 request를 넣어주는 역할을 합니다.
  • 이 context processor는 TEMPLATES 설정의 OPTIONS['context_processors']에 등록될 때 동작합니다.

즉, Django는 settings.TEMPLATES 에 request를 글로벌 컨텍스트로 넣어주도록 기본으로 설정되어있기 때문에 개발자가 고의로 이 설정을 지우지 않는 이상 Django 사용자는 아무런 불편함없이 당연하듯 사용하게 됩니다.

그리고 request 객체 자체는 Django가 요청을 받을 때 HttpRequest(실제로는 WSGI/ASGI request subclass)를 만들어서 뷰까지 넘겨주는 그 객체입니다. 이 객체에 path, path_info 같은 속성이 들어있어요.

Django라는 이름의 마술사가 request모자에서 도구를 꺼내는 이미지


한 줄 결론: 4개를 이렇게 외우면 편하다

  • path: “도메인 제외, 경로만”
  • path_info: “앱이 보는 진짜 경로(스크립트 prefix 제외)”
  • get_full_path(): “path + 쿼리스트링”
  • build_absolute_uri(): “스킴+호스트+경로까지 전부(완전한 URL)”

이제 각각을 정확히 보죠.


1) request.path : 도메인 없는 “경로(path)”

request.path도메인/스킴 없이 요청 경로만 줍니다. 예시는 이런 형태예요.

  • /music/bands/the_beatles/

언제 유용한가

  • 메뉴 활성화 같은 단순 비교

django {% if request.path == "/settings/" %}active{% endif %} * “이 페이지는 어디 카테고리?” 같이 prefix 비교

django {% if request.path|slice:":5" == "/api/" %}...{% endif %}


2) request.path_info : 배포환경에 덜 흔들리는 “실제 경로”

Django 문서에서 핵심 포인트는 이거예요.

  • 어떤 서버 설정에서는 URL 경로가 스크립트 prefix(SCRIPT_NAME)path info 로 나뉘는데,
  • path_info는 그중 path info 부분을 항상 담는다 (즉, 환경에 덜 의존)

쉽게 말해, 앱이 /app 같은 prefix 아래에 마운트되는 구성(리버스 프록시, 서브패스 배포 등)에서 pathpath_info가 달라질 수 있습니다.

언제 유용한가

  • 서브패스 배포(예: /app/ 아래로 서비스) 같은 환경을 고려해 “앱 기준 경로”로 판단하고 싶을 때
  • 테스트/운영 서버에서 prefix가 달라질 수 있을 때

평소 단일 도메인 루트(/)에서만 돌면 pathpath_info가 같아서 차이를 못 느끼는 경우가 많습니다. 하지만 환경이 바뀌면 그때부터 차이가 의미 있어집니다.


3) request.get_full_path() : path + 쿼리스트링까지

get_full_path()path에 쿼리스트링을 붙인 값을 반환합니다. 예시는 이런 형태입니다.

  • /music/bands/the_beatles/?print=true

언제 유용한가

  • “현재 페이지 그대로 공유/리프레시/되돌아가기” 링크가 필요할 때

django <a href="{{ request.get_full_path }}">새로고침 링크</a> * 로그인/권한 체크 후 원래 페이지로 돌아가게 next 만들 때

django <a href="/login/?next={{ request.get_full_path|urlencode }}">로그인</a>

참고로 Django에는 get_full_path() 말고 get_full_path_info()도 있는데, 후자는 path_info 기반으로 동작합니다. (오늘 비교 대상은 아니지만 차이를 알고 있으면 좋습니다.)


4) request.build_absolute_uri() : 스킴+도메인까지 포함한 “완전한 URL”

build_absolute_uri()는 현재 요청을 기준으로 절대 URL(absolute URI) 을 만들어 줍니다.

대충 이런 형태가 됩니다.

  • https://example.com/music/bands/the_beatles/?print=true

언제 유용한가

  • 이메일/메신저 공유 링크처럼 도메인이 반드시 필요한 경우
  • canonical URL, og:url 같은 메타 태그
  • 외부 시스템에 콜백 URL 전달

주의해야할 점

build_absolute_uri()는 호스트를 만들 때 요청의 Host 정보에 의존합니다(내부적으로 get_host()를 사용). 실제 요청이 들어온 url이 아닙니다. 대부분의 평범한 상황에서는 get_host()의 값과 실제 url도메인이 일치할 수도 있지만, Nginx 가 리버스 프록시 혹은 Django 미들웨어에서 개발자가 의도적으로 get_host() 값고 다른 tenant host를 사용하도록 로직을 만들 경우, {{ request.build_absolute_uri }} 의 값이 항상 실제 브라우저의 url과 일치한다고 볼 수는 없습니다.

따라서, nginx든 Django앱 내부에서든 어떠한 도메인관련 로직을 구현하셨다면, 예상과 다른 도메인/스킴으로 만들어질 수 있으니 배포 설정도 같이 점검하는 게 좋습니다.


결론 및 요약

  • 템플릿에서 메뉴 active 처리request.path
  • 서브패스 배포/프록시 환경까지 안정적으로 비교request.path_info
  • 쿼리스트링까지 포함해서 “현재 페이지 그대로”request.get_full_path()
  • 외부로 나가는 완전한 링크(도메인 포함)request.build_absolute_uri()

관련글 보기: