오늘 배운 것

요즘의 개발 일상이라 카테고리를 'SWM OneStep'으로 지정은 해 두었지만 살짝 거리가 있는 포스팅을 해 보려고 한다. 그렇다고 다른 데 넣기도 애매한 게, 오늘은 철저히 주관적으로 내가 아는 것들을 한번 슥 훑어볼 예정이기 때문이다. 이유는 바로 오늘 오후에 있을 토스 next 전형에 대해 django 지식을 조금이나마 정리하기 위해서이다. 코테를 갓 끝내고 정신이 비교적 맑을 때 어서 글을 작성해 보자. 참고로 모든 질문과 대답은 내 머릿속에서 나온 것이므로 정확한 질문과 정확한 정답은 없다. 하지만 이렇게 정리하기만 해도 내가 모르는 게 뭔지를 알 수 있어서 해 보려고 한다. 

 

 

django란 무엇일까?

장고(django)는 웹 프레임워크(framework)이다. 프레임워크와 라이브러리의 차이점은 코드의 동작 방식의 제어 유무라고 알고 있다. 자바/스프링에서는 IoC(역전 제어, Inversion of Control)라는 말을 쓰는데, 기존의 코드나 라이브러리에서는 실행의 제어권을 개발자가 갖고 있었다면 프레임워크에서는 이 IoC를 통해 프레임워크가 실행의 제어권을 갖는다. 그렇다. 스프링 강의로 찍먹한 개념인데 스프링도 장고도 모두 프레임워크인 만큼 이 원칙은 둘 모두에게 적용된다고 볼 수 있다. 

 

 

프레임워크를 왜 사용할까?

웹 프레임워크의 경우 웹 개발을 빠르고 편리하게 하기 위해서 사용한다고 알고 있다. 장고의 경우 MVC 패턴(model-view-controller)을 사용해서 웹 개발을 할 수 있는데, 이처럼 프레임워크는 개발자들이 여러 번의 웹 개발을 하면서 반복되는 디자인 패턴 등을 녹여놓았다고 볼 수 있다. 

 

 

그렇다면 프레임워크를 사용하는 이유는 웹 개발을 하면서 반복되는 디자인 패턴 등을 더 편리하게 사용하기 위함인가? 정말 그게 다라면 꼭 프레임워크를 사용할 이유가 있을까?

이 질문을 스스로에게 던진 순간 공부를 더 해야겠다는 생각이 들었다. 나는 '웹 프레임워크'가 웹 개발을 편하게 해 주는 도구임은 어렴풋이 알고 있었지만, 프레임워크의 어떤 것들이 웹 개발을 편리하게 하고, 장고는 그 중에서 어떤 기능들을 제공하는지에 대해서 명확하게 알지 못하고 있었다.

바로 'why do we use framework'로 검색을 해 보았다. 한 사이트에서는 low-level functionality를 제공해서 반복적인 코드 작성을 줄여주는 것도 프레임워크의 역할이라고 하더라. 그랬더니 좋은 예시가 떠올랐다. 

바로 서블릿이었다. 이것도 스프링에서 찍먹한 개념인데, 장고에서도 사용되는 것은 분명했다. 우리는 장고나 스프링에서 뷰나 컨트롤러를 만들 때 요청 객체를 request라는 변수로 바로 받아올 수 있다. 그런데 실제로 웹 서버로 요청이 오면 이는 HTTP 형식으로 온 메시지일 뿐이지 request 타입의 객체가 아니다. 이때 서블릿이 헤더를 파싱하는 등의 작업을 통해 HTTP 형식의 요청 메시지를 우리가 프로그래밍 언어로 다룰 수 있는 Request 타입의 객체로 변환해 준다. 만약 이 작업을 서블릿이 해 주지 않았다면, 매번 핵심 로직을 작성하기 전에 헤더를 파싱하는 등의 반복적인 코드를 계속 작성해야 했을 것이다. 

 

 

스프링에서 서블릿이 위와 같은 역할을 한다면, 장고에서는 무엇이 그런 역할을 한다고 생각하나? 

여기서도 막혔다. 'django servlet'이라고 검색해 보니 나와 같은 고민을 했던 오래된 글이 보였다. 답변자는 장고의 정리된 공식문서를 추천해 주고 있었다. 이 중에서 키워드를 통해서 http 요청이나 servlet과 관련된 것을 찾아봤더니, http 관련 문서가 도움이 될 것 같았다. 그런데 여기서 나오는 URLConf, Middleware, Writing Views는 모두 이미 변환된 request를 사용하는 기능들이었다. 나는 무엇이 http 요청을 request로 바꾸는지를 알고 싶었던 거였는데 말이다. 그래서 GPT 찬스를 써 보았다. 

주의할 점은 이 녀석의 말을 100% 신뢰하기보다는, 여기서 관련된 키워드를 뽑아내는 것이다. 녀석은 Django WAS가 WSGI라는 (비동기 상황에서는 ASGI) 인터페이스를 통해 WS(web server)와 상호작용한다고 알려주었다. 여기까지는 알고 있던 내용이다. 여기서 WSGI는 위 문서에 나오지 않은 키워드였기에 여기에 집중했다. 

녀석은 그렇다고 답변하고 공식 문서 링크도 남겨주었다. WSGI와 관련된 링크였다. 그런데 WSGI는 사실 인터페이스이므로 실제 구현 부분은 WSGI가 아니다. 그렇다면 장고에서 사용하는 WSGI의 구현체들은 어떤 것들이 있을지 궁금해졌다. 

녀석은 Gunicorn, uWSGI와 같은 예시를 들어주었다. 여기서 내가 모르던 지식이 연결되었다. 나는 'gunicorn을 사용하면 WSGI로 통신을 할 수 있다' 까지만 이해하고 있었는데, gunicorn은 WSGI의 구현 서버(WAS)였던 것이다. 그리고 uWSGI는 C로 구현되어서 속도가 빠르다고 한다. 

 

그래서 결론은 WSGI 표준을 구현한 서버들로는 Gunicorn, uWSGI, mod_wsgi 등 다양한 WAS가 있고, 이 WAS와 WS끼리는 WSGI 표준을 통해서 통신하는 것으로 이해했다. 그리고 여러 자료를 찾아보다 이런 유용한 포스트도 발견했다. Apache와 Nginx 모두 웹 서버라는 것은 알고 있었지만 둘의 차이점에 대해서는 크게 생각해보지 않았었다. Apache는 요청이 들어올 때마다 프로세스를 생성하는 방식이고, Nginx는 이벤트 기반의 아키텍처를 사용해서 클라이언트 요청이 폭발적으로 증가할 때 요청을 제대로 처리하지 못하는 문제를 해결했다고 한다. 

 

여기서 워커(worker process) 개념이 나왔다. 한창 gunicorn, uvicorn으로 씨름할 때 나왔던 그 워커가 맞다. 이는 WAS에 있던 프로세스가 맞았다. 나중에 WAS의 구조도 그려보자. 

 

 

아는 디자인 패턴이 있다면 설명해 봐라. 그리고 장고에서 사용하는 예시가 있다면 들어 봐라. 

싱글톤 패턴에 대해서 알고 있다. 처음에는 스프링 컨테이너에서 빈을 기본적으로 싱글톤으로 관리한다는 것을 말하려고 했는데, 장고에서 사용하는 예시는 잘 모르겠었다... 라고 생각했는데, 생각해보니 MVC 패턴이 있었다! 장고에서는 MVT 패턴을 사용한다. 모델(Model)은 장고에서 다뤄지는 데이터이다. 뷰(View)는 모델을 통해 데이터를 처리하는 핵심, 비즈니스 로직이 담겨 있다. 마지막으로 템플릿(Template)은 장고의 템플릿 엔진과 템플릿 문법을 사용해서 화면을 그리는 역할을 한다. 

 

 

MVC 패턴이 왜 유용한가? 왜 모델과 뷰를 분리시켜야 한다고 생각하나?

모델과 뷰를 분리시키지 않으면 로직이 복잡해지기 때문이다. 예를 들면 장고의 models.py에서는 DB에 저장되는 모델을 선언하고, 필요하다면 이와 관련된 메소드를 추가로 선언하는 작업을 한다. 반면 views.py에서는 직접적으로 쿼리셋을 다루지는 않고, 핵심 비즈니스 로직을 다룬다. 이렇게 분리시키지 않으면 로직이 복잡해진다고 생각한다. 

 

 

Fat Models, Skinny View의 원칙이 항상 옳은 것은 아니지만 대개 개발할 때 지향하는 원칙이다. 이유는 뭐라고 생각하나?

뷰에는 핵심 비즈니스 로직이 들어가는 것이 일반적이다. skinny view를 지향하는 이유는 뷰에 핵심 로직만 남겨두기 위함이라고 생각한다. 만약 핵심 로직이 길면 그때는 또 다른 방법을 사용할 수 있겠지만, 적어도 핵심 로직과 관련되지 않은 모델 단의 데이터를 다루는 작업은 모델로 옮기는 것이 바람직하다는 의미라고 이해했다. 

 

 

장고에는 Manager가 있다. 왜 Manager가 필요할까?

Manager를 사용해서 여러 메소드를 정의할 수도 있고, 프록시 모델을 만들 수도 있는 등 여러 기능이 있다고 알고 있다. 그리고 manager는 모델과 DB 사이에 있는 존재이다. 필요에 따라서 모델의 동작 방식을 바꿀 수도 있기 때문에(어떻게 바꾸는지는 모르겠다...) 필요하다고 생각했다. 

 

 

장고에서 Queryset이 필요한 이유는 무엇일까? 

장고 ORM이 필요한 이유와 같다. 쿼리셋이 있기에 장고에서 DB의 데이터를 조회할 때 장고의 문법으로 조회할 수 있다.

 

 

 다음에 답해볼 질문들

적어봤는데 너무 많아서 이번에 다 셀프 문답을 못 했다... 아래의 질문들 및 추가 질문들을 더 꼬리질문으로 이어서 다음에 답해 봐야겠다. 

  1. 이벤트 기반의 아키텍처(event-driven architecture)는 무엇일까?
  2. 아까 IoC 얘기로 돌아가 보자. 스프링에서는 스프링 빈과 컨테이너를 통해서 IoC를 한다. 즉 개발자가 코드의 제어권을 스프링 컨테이너에 넘기고, 스프링 컨테이너에서 스프링 빈을 관리하면서 IoC가 일어난다. 장고에서는 이를 어떻게 할까? 
  3. WSGI 표준을 구현한 WAS들 중 gunicorn의 특징이 뭔지 말해봐라.
  4. WS와 WAS가 어떻게 통신해서 하나의 요청을 처리하는지 그 과정을 설명해 봐라.

 

 궁금한 점

  1. fat models skinny view를 지향하는 현업에서의 이유가 궁금하다. 왜 fat view는 안 괜찮고 fat models은 괜찮은 걸까? 
  2. model에서 manager가 필요한 이유를 정확히는 설명하지 못하겠다. 모델과 DB 사이의 매개 객체가 필요하다고는 생각하는데, 구체적으로 왜 그런 걸까? 

 

+ Recent posts