오늘은 js와 css 적용에 너무 애로사항이 많아서 강사님이 직접 만드신 거의 백엔드로만 구성된 파일로 실습을 다시 시작했다.
수업 내용 자체에는 문제가 없어서 이대로 진행하기로 했다.
ui_easy
main.py이다. 저번보다 훨씬 간소화되었다.
상세정보까지 딕셔너리 형태로 출력했던 어제 내용에서 이어서 가보겠다.
sales_detail.html이다. 어제는 여기에 불러오기까지만 했지만 이번에는 약간의 html 구성을 추가했다. 컬럼과 내용을 테이블의 head로 칭하고 나머지 키, 그리고 값이 for문을 통해서 들어가도록 했다. 이 데이터는 order[order_no]로 main.py를 통해서 불러와졌다.
이러한 창이 구성된다.
개요
# 개요 - 본 프로젝트는 백엔드 중심으로 UI 프로젝트와 유사하게 구성 - JS 사용은 배제 - CSS 배제 - html은 기본 요소(혹은 태그)만 사용 - main.py, /db/__init__.py 는 동일함 - main.py에서 일부 기능 추가되었음 => form 관련사항 # form 관련 백그라운드 정보 - client가 server용어 정리 - client : 일반 유저, 브라우저를 통해서 소통 (pc, 모바일웹) - sever : 물리적 + S/W = 인프라 / 인프라구성 + (*)실제 서비스 개발이 합쳐짐 - 물리적 : s/w로 구성된 프로그램이 작동되는 공간 - 하드웨어(CPU, ram, 디스크, 네트워크 장비, ... ) - 관리(사내, 온프라미스) 힘드니까 => IDC 센터( 위치, 임대 ) => AWS같은 클라우드 회사 임대(클라우드) - s/w : 서버 운영에 관련된 S/W : os, docker, 네트워크(VPC) .... - 클라이언트에서 서비스를 제공하는 s/w - fastapi기반으로 개발한 s/w => 웹서비스 - springboot기반으로 개발한 s/w => 웹서비스 - client가 server(s/w)에게로 데이터를 전달하는 방법 - 방식 => method => get(헤더로 데이터를 전송) vs post, put, delete, ...(바디로 데이터를 전송) - 코드 관점 - html - 이 두개가 끝임 - <form> - get, post, put, delete 방식 모두 가능함 - form(폼) 전송 -> 특이점 (화면이 껌뻑댐-> 화면을 새로 그림) - 네이버 로그인 / 새로고침 - <a> - get 방식만 존재 - 링크 - js - 내장은 한개가 끝임 - 오리지널 api -> 무시 -> 너무 복잡 - fetch() - html5에서 공식 지원하는 (ECMA에서 추가함) 함수 - 모든 통신방식 ( methon )를 지원 - ajax(아작스, 에이젝스) 통신 지원 - 화면 껌뻑임 X - 백그라운드(뒤로 통신), 비동기(화면에 렉이 없음) 통신 - 지도 서비스, 검색창(추천 검색어 노출) - 주고 받는 데이터의 형태 = XML, json, 텍스트 등 - 프로그래밍적으로 원하는 타이밍에 통신 진행 스타일 - fetch는 대시보드상 - 차트 드로잉 - 챗봇, 채팅 - 검색 - 기타 - 외부 라이브러리 -> axios 등 # 템플릿 엔진 - 목적 - 개발자 코드와 디자이너 코드가 겹치는것을 분리하기 위해서 탄생. - 과거 : html 안에 프로그램 코드(java, cgi, ...) 포함되어있었음 - 템플릿 엔진 개발하여 분리 - java(or jsp) + xslt (템플릿) - 현재 : java + 타임리프 (템플릿) - python + jinja2 (템플릿) - 특징 - 디자이너가 약간의 프로그래밍(변수, 함수호출, 흐름제어, 주석)을 할 수 있게 제공한다 - 값 출력 - {{ 값 (변수 | 연산식 | 함수호출) }} - 흐름제어 - {% for ~ %} - {% endfor %} - ... - 주석 - {# #} - 클라이언트에게 개발자간의 대화 내용(중요 주석)을 숨긴다 - html 내부에 다른 html 포함 - {% include "xxx.html" %} - 거대한 html을 기능별로 분리하여서 필요시, 조립하여 페이지 구성 - 상속 - 자주 사용하는 페이지의 기본 구조, 골격, 표현등을 미리 정의하여, 상속하여 구성 - 기본 뼈대 : base.html - 개별 페이지 : - base.html -> extends -> 커스텀 구성 -> sales_board.html, sales_detail, ... - {% extends "base.html" %} - 커스텀 구성 - {% block 블럭명 %} - {% endblock %} # url -/sales/board/ - get 방식 작성 - 화면 표기 - post 방식 작성 - 검색 결과를 반영하여 표기 - 1개의 url을 기반으로 methon를 다르게 구성하여 어떤 목적 (비즈니스)를 달성 -> restful이라는 표현을 씀
개요에서 중요한 점은 데이터 전달방식의 (깜빡임) 이다. 예를 들어 네이버의 경우 로그인을 누르면 웹사이트 위의 새로고침버튼이 x로 잠깐 바뀐다, 이것이 사이트를 새로 고치며 처음부터 다시 그리는 행위이다, 그런데 직방 사이트, 그리고 다른 지도 사이트, 관련 검색어 추천 등의 웹사이트 움직임은 새로고침이 되지 않고 바로바로 움직인다. 이것이 form 방식과 ajax 방식의 차이이다.
이 코드는 원래 get /sales/board/ post /sales/search/ 였다, 그런데
sales_board.html에서 주소를 생략해버렸다, 이렇게 하면 작동이 될까?
기본 게시판bmw검색
두 페이지 모두 같은 url에서 작동되는 모습을 볼 수 있다. 실제로 다른 많은 웹사이트들에서도 이렇게 같은 url상에서 구동되는 많은 모습을 볼 수 있다고 한다.
로그인 html 만들기 이제 로그인 실습을 해 볼것이다. 먼저 /users/login/ url을 만들어준다.
main.py에서 url을 추가해준다, 그리고 login.html을 참조한다고 작성한다. 이제 login.html을 만들어주면 그 파일을 따라서 로그인 페이지가 만들어질거다. index.html
웹 사이트의 메인페이지(홈)에 로그인 url로 넘어가는 함수를 입력해준다.
이제 사이트를 만들때 모든 형식을 작성할 필요가 없다. base.html을 참조해서 모든 템플릿을 가져오고, 그 이후에 들어갈 부분에만 내용을 작성해주면 된다. 맨 위에는 로그인 글자를 띄웠고 그 아래 내용으로 데이터를 받을 수 있는 input행을 3개 추가하였다.
이러한 페이지가 만들어진다 그런데 이렇게만 해두면 id, password 값을 받을수도 없고, 비효율적이다. 그래서 우린 jinja2의 기능을 사용해서 결과를 받는 함수를 input 태그에 적용한다. marco.html
새 html 파일을 만들어주고 함수를 만들어준다. 함수명은 input_tag이고 이 함수는 type, placeholder, name, size, value 를 값으로 받는다. 여기서 size는 입력창의 길이이고, value에 값을 설정해주면 그 값을 미리 입력해둔다. 예를들어 size를 5로 하고 value값을 sk플래닛으로 해두면
이렇게 창이 줄어들고 sk플래닛이 미리 값으로 들어가있다. 이 함수를 login.html에 적용해준다
login.html
macro.html을 얘는 모르기때문에 import로 참조해줘야된다. 그리고 input 창에 함수를 대입해준다. 이렇게 하면 로그인창이 기존과 같지만 uid, upw를 통해서 값을 받아올 수 있다. 그리고 아무것도 입력하지 않은 걸 잡아내는 require를 macro 함수에 추가해준다. 그러면 아무것도 입력하지 않았을때 경고창이 뜬다.
이렇게 뜬다.
이렇게 로그인창이 작동하도록 만들었다, 이제 이 창이 작동할 뒷 이야기를 백엔드에서 만들어준다
로그인 처리 코드
주석이 좀 많아서 복잡해보이지만 주석을 읽으면서 코드를 해석하면 할 수 있다. 먼저 82~92 코드는 배제하고 생각해보자
데이터베이스상에 id,pw값이 없어서 일단 더미데이터로 고정값으로 세팅했다 -> 79번
이런 경우에는 우선 실패할 경우를 잡아내는 코드를 입력하고나면, 그 나머지가 성공코드이다. 그래서 우리는 else문을 먼저 시작했다, else문 내용은 return(반응) (loginFail.html로 이동,request는 무조건 있어야함) 이다. 그럼 이제 loginFail.html을 만들어준다.
loginFail.html
진짜 별거없지? 1. js를 html에서 사용하도록 <script>로 감싸준다 2. 경고창 명령어 alert로 경고창을 출력한다. 3. history.back() 함수는 이전 사이트로 돌아가게 해준다. 그래서 값이 틀리면 경고창을 출력하고 이전 사이트(로그인 창)으로 다시 돌아간다.
alert 함수 작동
이렇게 else문으로 실패는 잡았다. 이제 성공할때 코드를 작성하자
73~81까지 코드가 일단 로그인의 기본 처리이다. 73번줄 : /users/login/ url을 사용할거다 74번줄 : request로 인자를 불러온다. uid, upw는 login.html에서 클라이언트가 입력한 값이다. 이 것을 받아오는 문법이 uid:form(...) 이다. 우린 js를 최대한 안 쓸거라서 이번 실습은 form문 으로 했다. 79번줄 : 이렇게 가져온 값이 우리가 세팅한 uid, upw와 맞다면 성공이다, '회원이다' 를 출력한다. 그리고 로그인이 성공했으니 2가지를 수행해야 한다.
1. 우리가 로그인 한 기록(세션,쿠키)를 남겨야 한다. = 84번 코드 2. 메인 사이트로 들어가야 한다. = 91번 코드
이 둘은 각각 맨 위 템플릿 불러오기 코드
1번. 세션을 남기는 기능이 9번 코드에 있는 기능이다. 2번. 메인 사이트로 연결시켜주는 redirect기능이 7번 코드에 있는 기능이다. 그냥 외워!
먼저 1번을 구현하기 위해서 starlette.middleware.session 에 있는 내용을 붙여넣어야 한다.
세션 불러오기 위한 코드
미들웨어를 코드에 등록해주고 시크릿키를 등록한다
세션 쿠키 이름을 설정해주고 세션 시간을 정해준다 이게 뭐냐면 예를들어 우리가 네이버에 로그인하고, 일정 시간이 지나고 다시 켜면 로그아웃 되어있지 않은가? 그런 기능을 수행하는 템플릿이다. 이렇게 저장할 쿠키의 이름을 정해준다, 이 쿠키는 브라우저에 저장되는 역할이다.
그리고 84번에 있는 코드는 데이터베이스에 있는 값을 서버라는 공간에 저장한다는, 브라우저에 저장되는 쿠키와는 다른 개발자만의 인덱스라고 생각하면 된다, 우리도 세션과 쿠키를 관리해야 하니 값에 맞는 키를 req.session이라는 서버에 임의로 저장해두는것이다 그리고 그 이름이 user다. 이 기능을 84번에서 수행한다. 기존 사이트, 오른쪽을 보면 쿠키가 비어있다,
로그인을 한 후 오른쪽을 보면 우리가 지정한 쿠키 my_session이 저장되는것을 볼 수 있다.
오후 주 내용
# jinja2의 macro - 여러 html에서 빈번하게 등장하는 표현, 값만 변경해서 사용한 공통 표현 - 매크로 정의 -> 함수처럼 사용 가능 -방법 - macro.html 정의 - 각각의 매크로를 정의 - xxx.html (개별 페이지) - 매크로 import 하여서 사용 # 세션 및 쿠키 - Session - 서버측이 특정 사용자(브라우저)를 기억 | 구분 | 하는 방법 - http의 특징 - stateless = 직전 접속한 브라우저(사용자) 기억 x = 기본적으로 무상태 - 모든 요청은 새로운 유저이다 - 라고 http는 본다. - 사용자 정보(설정된 값, 아이디 등등)를 저장 - 사용자별 id( 해시값 -> 중복되지 않음 ) 생성 - 서버 측 메모리 or 스토리지(redis 등 nosql S/W)등에 저장함 - 쿠키(저장공간, 이동공간)에 담아서 브라우저로 전송 - 브라우저에 저장 - 이후 요청할때마다 브라우저에 저장된 id값을 가지고, 서버측으로 요청 진행 - 쿠키에서 전달된 id와 서버측에 저장된 id를 비교하여 동일 사용자임을 인식 - 은행 등 보안에 민감한 사이트는 => 시간제약을 부여(10분이후 자동 로그아웃 등) - 키:값 - 쿠키 - 클라이언트측 브라우저에 저장되는 정보 - 서버가 보낸 데이터를 브라우저에 저장하는 방식 - 키:값 - fastapi - SessiongMiddleware 클레스 활용 - starlette 패키지 하위에 위치함 # Pydancit (파이단틱) - 두 가지 토끼를 잡을 수 있음 - 목적 - 데이터 검증(타입, 길이 => 유효성 검사) - 데이터의 직렬화 처리 => json 변환이 쉬움, 그래서 씀 - dict 자료구조를 => 문자열로 변환(json) : 직렬화 - json 형태 구성된 문자열 => dict 자료구조로 변경 : 역직렬화 - 직렬화 이유 => 자료구조를 문자열로 변환해서 => 통신 시 데이터 전송에 사용 -> 간단하게 json 형태로 데이터를 묘사하고 전달 가능함 - client <-> json 형태로 주고 받는다. <-> server
redirect
이제 91번 코드 내용을 설명한다. 예를 들면 로그인이 성공하면, 메인 홈페이지로 가고, 로그아웃 하면, 다시 로그인창으로 간다던지 웹 사이트에선 그런 포워딩이 필요하다 그런 포워딩을 수행할 수 있게 해주는 템플릿이다. fastapi안에 내장되어있다. 먼저 91번에서 메인 사이트로 그냥 템플릿을 써서 링크를 걸어본다. 전달 방식이 틀렸다
이게 뜨는 이유는 로그인은 예민한 내용, 데이터 양 등 다양한 이유때문에 post방식으로 보내야 하는데 메인사이트 폼은 get방식이기 때문이다. 이를 해결하기 위한 다양한 방법이 있다. 그중에 하나는
뒤에 저 코드다. vs code 로그에서 오류를 확인한다.
오류 내용은 주석에 있다. 웹 코드가 307로 되어있는데 이는 원래 요청시 사용한 메서드를 그대로 써라, 그래서 오류가 나는거다. 그래서 91번 코드의 뒤에 status_code를 303으로 바꿔준다. 그러면 get방식으로 사이트를 호출한다.
이제 로그인하면 잘 된다.
이제 로그인하면 내 id와 pw를 찾아서 틀리면 로그인 할수 없고, 세션도 남아있고 로그인 시에 메인페이지로도 잘 들어가진다.
이제 해야할건 로그아웃밖에 없다
로그아웃 만들기 먼저 index.html에 로그아웃 버튼을 만들어준다.
그리고 링크를 /users/logout/에 걸어준다.
로그아웃 버튼이 생긴 모습, 위에 사진에도 이미 적용되어서 있을수도 있다. 이제 /users/logout/ 에 작동할 함수를 만들어준다.
로그아웃에 관련된 함수다. logout에 url을 걸어주긴 했지만 html은 필요가 없다. 로그아웃 확인되는 페이지라도 띄울건가? 로그아웃의 과정을 먼저 생각해보자. 1. 내가 로그인 되어있나? => 세션 확인 1-1 세션이 있네? 그러면 세션 삭제 1-2 세션이 없네? 잘못된 접근이네? 로그인창으로 이동 이 과정을 거친다 그래서 확인하는 if문을 사용해서 세션을 확인하고 = 102번 코드 세션이 있다면 지워준다, 이 떄 사용하는 코드는 딕셔너리 관련 코드다. = 104번 코드 그리고 세션이 있으면 세션을 삭제하고, 다시 로그인창으로 돌아가도 되지 않나? 그런데 세션이 없다면, 잘못된 접근이니까 다시 로그인창으로 돌아가지 않나? 이 둘의 차이점이 없다. 그래서 다시 로그인창으로 돌아가는 106번 코드를 if문의 앞으로 빼준다. 어떤 결과가 있던 로그인창으로 돌아가니까. 로그인 세션이 남아있다. 이 때 로그아웃 버튼을 누르면?
세션이 삭제되고 다시 로그인창으로 redirecting 되는 모습이다.
세션 체크 후 사이트 방문 걸러내기
그런 사이트도 있을거다, 사이트를 privite하게, 로그인 하지 않으면 들어올 수도 없게 만들 수도 있다. 회원제, 제한된 컨텐츠 등등 허가받지 않은 사람들은 내 사이트에 들어올 수도 없는것이다. 그렇게 하려면 어떻게 해야 할까? 모든 페이지마다 세션이 있는지, 없는지 체크하는 if문을 달아야 할까?
나는 수업들을때 공항 검색대 생각이 났다. 모든 데이터가 무조건 거쳐가야 할 한 장소에만 세션체크를 설정하면 된다.
메인 사이트에 세션체크를 걸어버렸다. 32번 코드 = 만약 세션 데이터가 없다면(not), 33번 코드 = redirect 로그인창으로 가버렷 근데 여기서 로그인하면? 메인 페이지로 들어간다. 그래서 메인페이지를 갑자기 누군가 검색해서, 혹은 실수로 url을 쳐서 접근한다면, 그 사람은 로그인을 안해서 세션이 없을테니까. 바로 로그인 창으로 넘어간다. 이 때 로그인 하면 세션이 생기니까 들어가지고, 로그인 안하면 못들어오는것이다. 오늘의 수업 끝
오늘까지 약 5일동안의 fastapi 수업이 끝났다.
진짜 이정도로는 앞으로 fastapi수업이 끝났다고 얘기하기 부끄러울정도로 따라가는데 급급했다.
파이썬, sql 등등은 기초 첫날부터 뭐 이해 안 간것은 똑같았지만 점점 배워온것들이 빌드업이 되면서 마지막 실습당시에는 그것들이 한 데 모여서 작용하는구나! 같은 느낌이 있었는데
fastapi 같은 경우에는 처음부터 빌드업이 되는 느낌보다는
이 기술은 이렇게 쓰는거야 네?
이건 이렇게 대입해서 쓰는거야 네?
같은 느낌이 들어서 얘기해봤는데
파이썬, mysql같은 경우에는 '문법'을 배운것이고
fastapi같은 경우에는 '사용법'을 배운 것이라는 말을 들었다.
fastapi를 사용할 때에도 파이썬의 문법, mysql의 문법을 사용하긴 했으니까.
그리고 java의 문법까지 fastapi에서 합쳐져서 그 부분은 참 재밌긴 했다
아 이래서....! 아 이래서....! 만 하루에 10번은 말하는 것 같은 기분?
fastapi는 확실히 언어, 문법같은 느낌보단 어떤 데이터를, 그리고 어떤 결과물을 위해서 다양한 템플릿, 라이브러리 등등을 가져와서 사용하고, 대입하고, 어떻게 하면 더 편하고 빠르게, 그리고 정확하게 필요한 결과물을 얻는지 등
하나의 도구를 사용하는 기분이었다. 지금까지 신발신는 느낌이고 이제 걷는느낌
이제 배우는 내용들이 순서대로 기록되는 것이 아니라 실습하고 진행하면서 이 파일 저 파일 이 언어 저 언어에서 왔다갔다 하도 자주해서 복습할때에도 순서, 혹은 수정되어서 못 보는 이전 작업 등 놓치는게 너무 많을까봐, 그리고 하나하나 기록되지 않다보니까 내가 한번 잠깐 놓쳐도 뒷 작업을 아예 따라가지 못하는 그런 상황들이 생길까봐 이번 주는 진짜 엄청나게 집중하고 했다.
오죽하면 강사님이 나한테 요즘 코멘트가 적어졌다고 말해주실 정도였다 ㅋㅋ
파이썬이 cad라면 fastapi는 리습과 명령어같다.
cad 쓸때 offset 누가 다 쳐서 하나, 누가 offset이 어떤 매커니즘으로 작동해서 값을 띄워주는지 어떤 코드로 돌아가는지 다 공부하고 하나,
그냥 옵셋은 이럴때 쓰는거야, 하지
물론 그 기능을 깊게 파고들면 훨씬 더 활용도가 높아지고, 그로 인해서 그리기 어려운 도면, 곡선, 2 point arc등등 다양한 도면과 그림을 그릴 수 있게 되는것은 맞다.
그리고 리습 등 단축어는 jinja2, fastapi, starlette 등등의 템플릿같다고 느꼈다.
스케치업에도 수많은 ruby를 사용해서 모델링을 하는데 기본 스케치업 기능만 가지고는 못 만드는게 너무나 많으니
다들 루비를 사용해서 비정형적인걸 엄청나게 잘 만들고, 복붙하거나 곡면적인 루버를 만들거나 등등 엄청나게 다양한 활용도가 있고, 그로인해 작업시간도 단축되지 않나,
코딩도 딱 그렇다고 한다, 수업시간에 정말 템플릿이나 이런게 어렵다는 분이 한 분 계셨는데 강사님이 만약 템플릿을 안쓰면
{{ }} 로 끝날거, 아니면 3줄로 끝날거 20줄, 100줄 써야 될 수도 있다고 하셨다.
루비 처음 쓸 떄 누가 어떻게 바로 알고 쓰냐, 다 써보고 대입해보고 만들고 하면서 사용법 익히는거지
진짜 어딜 가나 사람 사는건 다 똑같더라 같은 생각이 들었다.
어딜 가나 더 다양한 거, 더 많이 한 사람, 더 공부한 사람, 더 시간을 갈아넣고, 열정을 가진 사람이 당연히 더 잘 사용하고, 더 빠르다, 감각의 차이는 있겠지만 도구의 사용법과 숙련도는 다르니까.
전기톱으로 나무 자르는 사람이랑 실톱으로 나무 자르는 사람중 누가 더 빠르겠는가.
인테리어 할 때는 툴 공부 많이 안했는데 지금처럼 공부했으면 진짜 잘했겠다 같은 생각이 들었다.
회사 다닐때 툴 진짜 잘해서 상사들도 막 물어보던 선임 있었는데 기억난다 잘 지내시나 결혼하신다던데
이미 안했던 시간 어쩔수 업지 모 지금이라도 열심히 해야지
그래도 템플릿을 도구라고 생각하면서 조립하는 느낌으로 눈에 보이는 결과물을 하나하나 만들어내니 나름 재밌었다.