Fast API JWT Example을 실행보면서 검토할 사항들
토요일.
운동을 가자고 하는 집사람의 요구를 쌩까면서 Java Spring으로 구현했던 JWT와 Python FastAPI에서 Example로 제공하는 JWT를 비교 해 보고 있다.
먼저 알아야 하는 사항
- OAuth2PasswordRequestForm
- OAuth2PasswordBearer
이 두 가지가 무엇인지 정확하게 식별해놓지 않은 상태에서 Example을 보고 따라하면 통상적으로 하려고 했던것에서 많이 어긋나는 상황이 발생하는듯하다.
OAuth2PasswordRequestForm
아래 이미지 두 개를 보자.

저 오른쪽 노란색 자물쇠가 있는 함수와 없는 함수의 차이를 생각하자.
@app.get("/items_fastapi_jwt/")
async def read_items(token: str = Depends(oauth2_scheme)):
return {"token": token}
저 자물쇠가 나오는 조건은 OAuth2PasswordBearer유형의 Dependency Injection인 경우 출력되는 것으로 유추된다.
VSCode 단축키 설정
토요일.
VSCode를 주 개발도구로 바꾸고 나서, Python과 JavaScript를 동시에 사용하다가 보니, Python에서 Console.log()를 찍고 있고, JavaScript에서 print()를 찍고 있는게 당연한건 아니다.
귀찬으면 뭔가 개선을 해야 해서 좀 찾아보니 VSCode Snipet에 잘 정리가 되어 있다.
[
{
"key": "ctrl+shift+a",
"command": "editor.action.insertSnippet",
"when": "editorTextFocus",
"args": {
"snippet": "console.log(`${CLIPBOARD}:`,${CLIPBOARD});"
}
},
{
"key": "ctrl+shift+z",
"command": "editor.action.insertSnippet",
"when": "editorTextFocus",
"args": {
"snippet": "print(f'${CLIPBOARD}:', $CLIPBOARD)"
}
}
]
일단 내가 사용하는 스타일을 보니 변수명을 복사 한 다음 그 녀석을 찍어보겠다는 생각이니, 손가락이 가까운 a와 z를 하나씩 각인시켜본다.
VSCode + FastAPI 디버깅을 하려는데 No operations defined in spec!
금요일.
아주 예전에 FastAPI에서 JWT 구현했던 것을 끄집어 내서 Toy Project에 붙여넣으며 VSCode에서 디버깅을 하려는데 함수가 하나도 보이지 않는다.

No operations defined in spec!
이 말의 의미를 찬찬히 되새겨봤다면 금방 이해를 했을터인데, 다른 문제인가 싶어서 좀 해매기 시작한다.
# VSCOde Debug용 main은 아래쪽에 있어야 한다.
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=8000)
디버깅을 위해 만들어둔 ****name****을 소스정리하면서 위쪽으로 아무생각 없이 올려두었더니, 그 아래쪽으로는 인식을 못했나 보다.
결론
Stack Overflow에 뭔가를 찾으려 해도 키워드가 애매하면 엉뚱한 것만 나온다.
Python SQLAlchemy + MySQL 파라메터 형식에 대해서
목요일.
아주 예전에 Oracle로 구현해뒀던 JWT를 다시 꺼내서 MySql로 바꾸는 작업을 하고 있었다.
sql = """
SELECT USER_ID
,USER_NAME
,PASSWORD
FROM TB_USER_BAS
WHERE USER_ID = :USER_ID
"""
params = { "USER_ID": userid }
Argument 2 must be Tuple or List!
변경된 부분은 아마도 Python에서 MySql을 사용하기 위해 Mysql Connector를 다시 설정해야 하는 부분이 아니었을까 싶지만, 메시지는 매우 당혹스러운 느낌으로 다가온다.
sql = """
SELECT USER_ID
,USER_NAME
,PASSWORD
FROM TB_USER_BAS
WHERE USER_ID = %(USER_ID)s
"""
params = { "USER_ID": userid }
한참을 찾다가 MySql Connector Python Page에서 표현식이 다른 것을 보고 적용을 해 보니 된다.
Python base64 decode 에러나는 상황
월요일.
아주가끔은 아니고 한 10번에 한 번은 아래와 같은 오류가 발생했다.
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xb1 in position 0: invalid start byte
이것에 대해서 찾아보면 utf-8이 3Byte라서.. 어쩌구 하는 게시물도 있기는 했지만 테스트 해보니 정답은 아닌거 같고.
def getDecode(msg):
msg_byte = base64.b64decode(msg)
# 원래코드
return msg_byte.decode('utf-8')
# 변경된 코드
return msg_byte.decode('utf-16-be')
결론(아직까지는 문제없음)
- utf-8을 utf-16-be로 바꾼다 (utf-16, utf-16-be, utf-16-le의 차이점도 알아두면 나쁘지 않다.)
- 이런저런 사정으로 utf-8에서 제외되는 문자가 있는 모양이다.
- utf-8 vs. utf-16의 문제가 아니었다.
python: Invalid base64-encoded string: number of data characters (37) cannot be 1 more than a multiple of 4
이번에는 이런 오류가 발생하고 있어 구글링을 해 보니 stack overflow에 바로 해당 내용이 나온다
ui5-table이 깨지는 상황
일요일.
Toy Project로 만들고 있는 녀석은 SAP에서 오픈소스로 제공하고 있는 ui5 web-component를 사용하고 있다.
우선 화면을 하나 보면.

- ui5-table-cell.innerHTML에 좀 긴 문자열이 들어가 있지만, 개행되며 정상적으로 Table Layout이 유지되고 있는 것을 볼 수 있다.
- ui5-table의 특성중 popin 또한 정상적으로 적용이 되어 size와 M-Day column은 아래쪽으로 내려갔다.
두 번째 화면은 아래와 같다.

- 동일한 길이의 문자열인데, table이 깨지면서 옆으로 늘어진 것을 볼 수 있다.
- 차이점은 저 녀석이 ui5-link라는 점이다.
이런 사항은 개발자도구에서 차이점을 아무리 찾으려 해 봤지만 식별하지 못한 부분이다. 다양한 시도를 통해서 차근 차근 알아가는 수 밖에.
Nginx를 활용하는 개발, 테스트서버의 설정(Feat. FastAPI, Vite)
목요일.
Toy Project를 하나 만들고 있는데, 이 녀석을 FastAPI와 Vite로 구성하고 (관리의 편의라는 이름으로) 하나의 git project로 관리하고 있다.
root
- api
.gitignore
- __pycache__
api.py
- ui
.gitignore
- node_modules
index.html
개발 할 때는 api 폴더에 들어가서 uvicorn으로 api.py를 구동시켜 http://localhost:8000으로 API서버를 올리고, ui폴더로 들어가서 npm run dev로 http://localhost:3000의 (Static) Web Server를 구동시킨다. 물론 npm run serve도 사용해야 한다.
여기에서 생각해야 하는 사항은
- CORS
- API Server URL
CORS는 FastAPI에서 가이드하는 부분으로 처리하면 되고, API Server URL부터는 좀 생각을 해야 한다.
나는 프론트와 백앤드를 하나의 오리진으로 서비스 하는 것으로 구성 하려고 하기 때문에, 개발 할 때 API서버의 주소와 운영 할 때 API서버의 주소가 상이한 상황이 발생한다.
var, let, const 그리고 hoisting
목요일.
먼저 알아야 하는 내용
- var: 선언 및 초기화 -> 할당
- let, const: 선언 -> TDZ -> 초기화 -> 할당
함께 알아야 하는 내용
- TDZ: Temporal Dead Zone,
What is Temporal Dead Zone - hosting: 끌어올림. (맞다.
호이스트장비라고 생각하면 쉽다.)
중요한 차이는 var의 경우 전역으로, let, const는 블럭으로 scope를 가진다는 것인데, 어려운 사항은 Java나 C만 하다가 JavaScript를 접하는 사람 입장에서는 hoisting이 발생하는 기준이나 TDZ가 이상한 언어라는 인식을 가지게 되는 것이다.
이렇게 생각하시라
C에는 포인터가 있고 Java Spring Framework에는 Injection이 있는데, 이것을 다른 언어만 아는 사람 입장에서 보면 얼마나 황당하겠는가?
Pretendard Web Font 설정하기
화요일.
점심을 먹고 운동을 하고 와서 개발관련 글을 읽고 있는데 폰트가 이쁘다고 생각하고 확인을 해 보니 Pretendard라는 녀석이어서 당연히 외산일것이라 생각하고 구글에서 검색을 하는데 한국인이 만든것인가 보다.
오전에 적용한 ‘D2Coding Web Font’는 이로서 2시간도 안되어 버려지게 되어 버렸다.
Font/CSS설치
Pretendard Font를 받아서 적당한 Font 폴더에 넣는다.
나는 woff2만 지원 할 것이지만 css를 살펴보니 size에 따라 적당한 폰트가 다 따로 있는듯 해서 static woff2 전부를 받았다.Pretendard css를 받아서 적당한 css 폴더에 넣고 경로를 변경해준다.
적용하기
이건 자신이 처한 jekyll 테마 환경마다 다를 것이나, minima 2022-01-18기준으로..
D2Coding을 Web Font로 설정하는 작업
화요일.
일이 이상하게 돌아가고 있다.(그냥 적용해본 구글 Web Font “Noto Sans KR"가 마음에 안든거다.)
무슨 생각이었을까? 갑자기 D2Coding Font를 이 웹페이지에 적용해야 겠다고 생각하고 구글링을 해 보니 먼저 시도 한 사람이 있다.
알아야 할 사항
- woff2, woff, ttf (브라우저 지원을 위한 선택)
- full, subset (Size를 줄이기 위한 선택)
웹 폰트 사용과 최적화의 최근 동향을 읽어보면 브라우저 지원을 위해서는 woff2와 woff까지 가지고 있어야 할 거 같은데, 그냥 woff2만 지원하기로 한다. (현재 Edge에서 테스트 해보니 woff2를 사용했기 때문에 나머지 브라우저에서 이상하게 보이는건 어쩔수없다.)