UWP+Socket+Error 10013
토일 프로젝트로 UWP에서 MPD에 Socket으로 연결하는 작업을 주말마다 아주 조금씩 진행하고 있었다.
처음에는 MVVM 패턴을 이해하지 못해서 진도가 안나가다가 드디어 오늘 Socket 호출을 하게 되었는데 말이다.
socket.Connect(server.serverIp, server.serverPortInt);
이 단순한 문장에서 SocketError 열거형 10013 오류를 throw한다.
|  | 
|---|
| 어플리케이션 설정 기능 | 
원인은 아무래도 UWP이다 보니, 이상한 짓을 하게 놔두지 않으려는 MS의 배려인거 같고.
이 프로그램에서 Socket을 사용할것이라고 설정 해 주면 잘된다.
Jekyll Theme al-folio
거의 1년 만에 미뤄뒀던 블로그를 아니 Jekyll을 다시 꺼내, 일요일 아침부터 만지작거리기 시작한다.
처음 시작 할 때는 Jekyll은 커녕 Ruby라는 것이 있는것만 알았지, 처음 써보는 상황이었다.
물론 지금도 Ruby를 사용하는건 아니다. Gemfile에 대해 알았을 뿐이다.
일요일 아침부터 시작한 Jekyll을 재 설정하면서 무료 Theme를 몇 개 섭렵해 봤는데, 그래도 1년 전에 깔짝거려 본 경험이 있어 그런지 al-folio를 발견하고는 몇 시간에 걸쳐 찬찬히 이주 작업을 했다.
그 사이에 Google Domain에서 blog host를 등록하고 Let’s Encrypt 인증서도 등록해야 했다.
RESTFul response status code에 대해
수요일.
만들고 있는 토이프로젝트가 드디어 데이터에 대한 추가, 변경 그리고 삭제에 들어가게 되어 생각한다.
데이터에 대한 추가가 발생하는 경우 201 Created를 보내준다고 하지만, 변경과 삭제는?
언듯 200인가 싶어 찾아보니, 204 No Content에 대한 내용이 있다.
복잡하게 생각 할 수도 있는데, 200은 화면을 갱신해야 하는 경우. 204는 화면을 (전체)갱신하지 않고 표현 할 수 있다면..으로 이해 해 보자.
나는 변경과 삭제시 해당 Table의 Row만 처리 할 예정이라 204를 보내기로 한다.
그런데, 추가시에는 어떻게 할 것인가? 화면 전체를 갱신 할 것인가?
사용자와 권한에 대한 생각
수요일.
사용자와 권한에 대해 생각한다.
<div class="mermaid"> 
erDiagram
          ROLE ||--o{ ROLE-USER : "1:n"
          ROLE ||--o{ ROLE-MENU : "1:n"
          ROLE ||--o{ ROLE-API : "1:n"
          
          USER ||--o{ ROLE-USER : "1:n"
          ROLE-MENU }o--||  MENU: "1:n"
          ROLE-API }o--||  API: "1:n"
</div>
과연 당신은 사용자와 권한에 대해 어떤 관계를 생각하고 있을까?
<div class="mermaid"> 
erDiagram
          USER ||--o{ ROLE-ITEM : "1:n"
          ROLE ||--o{ ROLE-ITEM : "1:n"
                    
          ROLE-ITEM }o--|| MENU : "1:n"
          ROLE-ITEM }o--|| API : "1:n"
</div>
추상이라고 불리는 모델링은 정답이 없다.
Mermaid로 다이어그램 그리는 테스트
화요일.
GitHub에서 다이어그램이 필요한데, 당연 디이어그램을 이미지로 넣을 생각을 했더니 뭔가 방법이 있다.
Mermaid라는 녀석인데, 코드블럭을 이용해서 파싱하고 그것을 이미지(아마 SVG겠지? 라고 생각했더니 SVG다.)로 만들어 보여주는 모양으로 생각된다.
그런데, Jekyll사용자의 경우 그냥은 안되고 조금 손을 봐야 하는데, [미리 해 본 사람][https://frhyme.github.io/mermaid/Embedding_mermaid_in_github_page/]이 있어서 크게 어렵지는 않다.
<div class="mermaid"> 
sequenceDiagram
    WebBrowser->>+Nginx: Request /
    Nginx-->>-WebBrowser: Response *.js
    WebBrowser->>+WebBrowser: Vuex.route에서 판단
    WebBrowser->>+Nginx: Request /login
    Nginx-->>-WebBrowser: Response login.vue(js)
    WebBrowser->>+WebBrowser: Vuex.store에서 요청
    WebBrowser->>+Uvicorn: Request /api/loginId (Proxy Bypass)
    Uvicorn->>+MySql: Select User
    MySql-->>-Uvicorn: User Data
    Uvicorn-->>+WebBrowser: Access Token
    WebBrowser->>+WebBrowser: internalStorage에 저장
</div>
결론: 좋다!
FastAPI에서 Refresh Token 생성하는 구조
토요일.
지금만들고 있는 Toy Project는 Admin Site이기 때문에, 불특정 다수를 대상으로 하는 것도 아니고 통상적인 자그마한 수준의 트랜잭션을 감당 할 예정이라 모든 요청에 인증 및 권한체크를 하는 것으로 구상을 하고 있다.
인증 후 Token의 만료시간을 30분으로 잡고 있는데, 이 경우 계속 사용을 하면(===요청을 하면), 그 만료시간을 자동으로 늘려주려주는 방식의 구조를 만들려고 한다.
알아야 하는 사항
- login을 제외한 모든 요청은 인증체크와 권한체크가 되어야 한다는 전제이다.
- 모든 요청에 인증체크가 자동으로 되기 위해서 주입(injection)을 사용한다.
- 체크를 위한 값과 체크의 결과를 응답에 섞어서 받거나 내릴수 없기 때문에 request.header와 response.header를 사용한다.
- 해당 Request, Response 객체는 fastapi가 아니고 starlette에 있다.
- dependencies 선언에 파라메터를 넣을 수 없어서, 중간 함수가 하나 필요하다.
이 정도만 있으면, 구글링을 통해서 자신이 원하는 구조를 만들 수 있겠으나 코드를 좀 살펴보면.
Vue3, app의 instance를 다른 모듈에서 사용하기
토요일.
main.js에 구축했던 Google Login모듈을 리팩토링 하려고, google.service.js를 하나 만든것 까지는 좋았는데.
app.use(‘xx’)를 사용 할 수가 없었다.
알아야 하는 사항들
- main.js에서 만든 createApp()은 인스턴스를 생성한다.
- getCurrentInstance()를 사용해서 다른 모듈에서 접근이 가능하다.
- app을 끄집어 내기 위해서는 appContext를 사용해야 한다.
import { getCurrentInstance } from "vue";
function xx() {
  const instance = getCurrentInstance();
  // app에 접근해서 plugin을 주입한다.
  instance.appContext.app.use(PluginObject, PluginOption);
}
Vue3 + script setup과 onMount()에 대한 생각
금요일.
Vue3를 살펴보면서 (아직 잘 몰라서 드는 생각이겠지만) 문서가 Vue2와 Vue3가 혼재하면서 아직 잘 모르는 사람이 찾기에는 어렵다는 생각을 많이 하게 된다.
사실은 Facebook Login기능을 붙이다가 전에 구현한 Google Login기능이 main.js에 덩그러니 있는것을 보고 모듈쪽으로 이동시키려고 시도하면서 시작된 것이었다.
Vue에서만 사용하는 단어인지는 모르겠지만 SFC(Single File Component)라는 단어가 있는데, 컴포넌트가 어딘가에 포함된 것이 아니고, 그 자체가 하나의 파일로 만들어져 있는 경우를 지칭한다고 생각된다.
어쨌거나, Vue3 혹은 Vue를 설명하는 많은 문서들에서 setup()내에 onMount()를 기술하고 있는 것을 볼 수 있는데, 내 경우에는 어찌해도 그녀석이 호출되지 않는 현상이 있었다.
FastAPI 요청 로그 생성하기
목요일.
FastAPI로 요청되는 것들에 대해서 로깅을 하려고 봤더니 한 방에 안되어 좀 찾아본다.
알아야 하는 사항들
- FastAPI 모든 요청에 끼워서 사용 할 수 있는 middleware 기능이 있으며, 사용방법이 아주 다양하다.
- middleware에서 request, response를 사용 할 수 있는데, starlette.requests 등이 필요하다.
- Python Logging을 사용하기 위해서 형식을 지정하는 formatter가 필요한데, FastAPI것도 있고 따로 만들어도 된다. 나는 별도 항목으로 정리하고자 해서 별도로 만들었다.
- Logging형식을 JSON으로 하고 싶어서 찾아보니 pythonjsonlogger라고 만들어 둔 것이 있다.
- logging 객체를 함수안에서 만들면… 함수를 부를 때 마다 로그가 배수로 출력된다. 1 > 2 > 4 > 8 > ..?
설치
sudo pip install starlette-context
sudo pip install python-json-logger
main.py
from starlette.requests import Request
# 로그 객체 생성
logger = logging.getLogger()
logger.setLevel(로그래밸)
handler = logging.FileHandler(로그파일명)
handler.setFormatter(만들어진 포매터를 넣는다. pythonjsonlogger 깃헙 참조)
logger.addHandler(handler)
# Define Audit Log
@app.middleware('http')
async def audit_log(request: Request, call_next):
    # ----------------------------------
    # Next를 안부르면....!!!!
    response = await call_next(request)
    saveLog(logger, request, response)
    return response
유심히 볼 부분은 audit_log 위쪽에 있는 어노테이션이다. 그리고 로거 객체는 함수 밖에서 만들어야 했고, saveLog()에 request와 response를 넘겨줘서 로깅할 내용을 꺼낼 수 있도록 한다.
Vite + Vue3 그리고 compilerOptions.isCustomElement
일요일.
eslint와 prettier설정관련 해서 결국 다른 템플릿으로 바꾸는 작업을 하고있었다.
거의 컴파일 오류를 다 잡고 개발에서 열심히 돌려보니 로직은 잘 돌아가는데 콘솔창에 Vue warning이 열심히 떨어지고 있다.
[Vue warn]: Failed to resolve component: ui5-button
If this is a native custom element, make sure to exclude it from component resolution via compilerOptions.isCustomElement.
이전 Template에서는 되고 새로운 Template에서는 안되는 것인가?
원래 이것은 vite.config.js에서 태깅을 해 뒀던 것이었다.
export default defineConfig({
  plugins: [vue({
    template:{
      compilerOptions: {
        isCustomElement: tag => tag.includes(`ui5`)
      }
    }
  })],
  ...
결론부터 말하자면
개발빌드(npm run dev)에서는 발생하고, 운영빌드(npm run build)에서는 발생하지 않는다.