모도리는 공부중

2023.11. 개발 궁금증 링크 일기 본문

내 지식 정리/날것 그 자체

2023.11. 개발 궁금증 링크 일기

공부하는 모도리 2023. 11. 5. 20:11
728x90
반응형

[ 목차 ]

     

     

    2023.10. 개발 궁금증 링크 일기

     

     

    개인 공부 관련

    JavaScript

    스프레드 문법

    NestJS 강의를 듣고 있는데 현재는 db가 아닌 메모리에 탑재해놓고 crud를 진행중이다. 그러던 중 아래 코드와 같이 스프레드 문법을 이용하면 기존 내용을 복사해와서 기존 내용 위에 변경된 일부 내용만 덮어씌우기가 가능한 것처럼 설명하는데 뭔가 잘 이해가 안 가서 gpt한테도 물어보고 추가 검색도 진행해봤다.

      update(id: number, data) {
        const index = this.getBoardId(id);
        if (index > -1) {
          this.boards[index] = {
            ...this.boards[index],
            ...data
          }
        }
      }

     

    gpt 설명

    좋아, 좀 더 자세히 설명해보겠어. 스프레드 문법(`...`)은 객체나 배열에서 값을 복사하거나 합칠 때 사용되는 문법이에요.

    여기서 `this.boards[index]`는 배열 `this.boards`에서 `index` 위치에 있는 객체를 나타냅니다. 그리고 `...this.boards[index]`는 해당 객체의 속성들을 복사하는 역할을 합니다. 즉, 기존 객체를 변경하지 않고 그 속성들을 새로운 객체로 복사하는 거죠.

    그리고 `...data`는 전달된 `data` 객체의 속성들을 복사합니다. 여기서는 `data` 객체가 새로운 값을 포함하고 있을 거에요.

    그런 다음, 이 두 개의 복사본을 합쳐서 새로운 객체를 만듭니다. 이렇게 만들어진 새로운 객체은 기존 객체의 속성들과 `data` 객체의 속성들이 합쳐져 있어요.

    마지막으로, 이 새로운 객체를 `this.boards[index]`에 할당함으로써 기존 배열을 업데이트합니다. 이렇게 하면 기존 객체를 직접 변경하지 않고 새로운 값을 추가하거나 업데이트할 수 있어요.

    간단하게 말하면, 이 코드는 배열에서 특정 객체를 찾아서 그 객체를 복사한 뒤, 새로운 값을 추가하거나 업데이트해서 배열을 업데이트하는 역할을 합니다.

     

    네, 스프레드 문법을 사용한 객체나 배열의 복사 및 합침은 JavaScript의 일반적인 기능 중 하나에요. 이를 통해 객체나 배열을 간편하게 복사하고 새로운 값을 추가하거나 업데이트할 수 있어요.

    스프레드 문법을 사용한 객체의 복사 및 합침은 기본적으로 JavaScript 언어 자체의 문법입니다. 따라서 별도의 내장 함수가 아니라 JavaScript 엔진이 이를 지원하고 있습니다.

    예를 들어, 아래와 같이 사용할 수 있어요.

    const originalObject = { key1: 'value1', key2: 'value2' };
    
    // 객체 복사
    const copiedObject = { ...originalObject };
    
    // 객체에 새로운 값 추가 또는 업데이트
    const updatedObject = { ...originalObject, key3: 'value3' };​


    이 코드에서 `...`은 스프레드 문법을 나타내며, 이를 통해 객체를 복사하거나 새로운 값을 추가 또는 업데이트할 수 있어요. 이러한 문법은 JavaScript의 ES6부터 도입되었습니다.

     

    07. spread와 rest 문법 · GitBook

     

    실력 성장

    빠르게 학습하는 개발자가 되는 방법 | 요즘IT (wishket.com)

    좋은 엔지니어가 되려면 '경험' 쌓기가 중요합니다 | 요즘IT (wishket.com)

     


     

    업무 관련


    MariaDB & SQL Alchemy

    ORM

    SQLAlchemy 그것이 알고싶다 | Ulfrid_log

    [Fastapi]SQLAlchemy 이용하여 DB와 연결하기 (velog.io)

    sqlalchemay class (object) == db table
    sqlalchemy class atttribute == db column
    sqlalchemy class instance == db row

     

    Relationship

    [SQLAlchemy] 연관관계 설정 (tistory.com)

    SQLAlchemy One to One 설정하기 (backref와 back_populates 차이) (tistory.com)

    여태 내가 궁금한 사항이 인덱스 관련인줄 알았는데 알고 보니 릴레이션쉽이었다..

    공식문서 링크 첨부 ㅜㅜㅜㅜ

    Relationships API — SQLAlchemy 2.0 Documentation

    Basic Relationship Patterns — SQLAlchemy 1.4 Documentation

     

    gpt 설명

    Q. sqlalchemy에서 relationship을 걸면 relationship이 걸린 테이블도 같이 조회돼?

    A. 네, 맞아요. SQLAlchemy에서 `relationship`을 사용하면 해당 관계가 정의된 모델 간에 객체 지향적인 방식으로 데이터를 로드할 수 있습니다. `relationship`을 통해 두 모델 간의 관계를 정의하면, 부모 모델을 쿼리할 때 자동으로 관련된 자식 모델도 함께 로드됩니다.

    간단한 예제로 설명하자면, 예를 들어 `User`와 `Address`라는 두 모델이 있다고 가정해봅시다. `User` 모델에는 여러 개의 주소(`Address`)가 있을 수 있습니다. 이때 `relationship`을 사용하여 관계를 정의하면, `User`를 조회할 때 자동으로 해당 `User`의 주소들도 함께 조회됩니다.

    from sqlalchemy import Column, Integer, String, ForeignKey
    from sqlalchemy.orm import relationship
    
    class User(Base):
        __tablename__ = 'users'
        id = Column(Integer, primary_key=True)
        name = Column(String)
        addresses = relationship('Address', back_populates='user')
    
    class Address(Base):
        __tablename__ = 'addresses'
        id = Column(Integer, primary_key=True)
        email = Column(String)
        user_id = Column(Integer, ForeignKey('users.id'))
        user = relationship('User', back_populates='addresses')


    위의 코드에서 `User` 모델과 `Address` 모델 간에 일대다 관계를 `relationship`을 사용하여 정의하고 있습니다. 이렇게 정의된 관계에서는 다음과 같이 `User`를 조회하면 연관된 주소들도 함께 로드됩니다.

    user = session.query(User).filter_by(name='John').first()
    print(user.addresses)  # 이 부분에서 주소들이 함께 로드됨


    이러한 기능은 관계형 데이터베이스의 조인과 유사한 동작을 수행하며, 객체 간의 관계를 편리하게 다룰 수 있도록 도와줍니다.

     

    Q. user 클래스에 id, name처럼 addresses라는 컬럼이 생기고, 그 컬럼에 Adderess relationship을 걸어줬으니 Address 클래스(테이블)의 모든 컬럼 값이 다 나온다는 거야?

    A. 네, 맞아요. `relationship`을 사용할 때, 해당 관계를 정의한 클래스(`User` 클래스의 `addresses` 속성)는 연관된 모델(`Address` 클래스)의 모든 열을 가지게 됩니다. 이는 SQLAlchemy에서의 일반적인 동작입니다.

    예를 들어, 위에서 `User` 클래스에 `addresses`라는 `relationship`이 정의되었고, `Address` 클래스와의 관계가 정의되었습니다. 이 관계가 일대다 관계라면, `addresses` 속성은 해당 `User` 객체에 연결된 모든 주소를 나타내게 됩니다. 따라서 `addresses` 속성을 조회하면 해당 `User`에 대한 모든 주소 객체가 반환됩니다.

    user = session.query(User).filter_by(name='John').first()
    print(user.addresses)​


    이때, `addresses` 속성에는 `Address` 클래스의 모든 컬럼 값이 담긴 주소 객체들이 포함되어 있습니다. 하지만 이 객체들이 로드되는 시점은 실제로 `addresses` 속성을 사용할 때이며, 필요한 경우에만 로드됩니다. 이를 "지연 로딩"이라고 부르며, 성능 상의 이점을 가져올 수 있습니다.

    요거에 대해서 좀 더 공부하고 정리해서 글 따로 써야겠다.

    python 파이썬 - SQLalchemy에서 backref 및 back_populate의 개념? - 스택 오버플로 (stackoverflow.com)

    여기 글을 읽다보니, 22년 7월부터 backref는 레거시로 간주되며 back_populates가 선호된다고 한다. 아마 어딘가 공식문서에 나와있는 거겠지? 근데 관계성 설명은 아직도 이해가 잘 안 간다.. 좀 공부해본 다음 직접 돌려봐야 하려나?

     

    Timezone

    MySQL & MariaDB 타임존 변경 (CONVERT_TZ 함수 이용) (tistory.com)

    pytz – 세계 시간대 정의를 위한 Python 라이브러리 | edykim

     

    Group by Alias 사용

    Group By에 함수로 가공된 Alias를 사용해도 된다. : 네이버 블로그 (naver.com)

     

    페이지네이션 (오프셋 기반 vs 커서 기반)

    커서 기반 페이지네이션 (Cursor-based Pagination) 구현하기 (velog.io)

    Cursor based Pagination(커서 기반 페이지네이션)이란? - Querydsl로 무한스크롤 구현하기 (velog.io)

     

    인덱스

    SQL 인덱스(INDEX) 뜻과 원리 이해하기(오라클, MS-SQL) : 네이버 블로그 (naver.com)

    [MYSQL] 📚 인덱스(index) 핵심 설계 & 사용 문법 💯 총정리 (tistory.com)

    데이터베이스 초보자를 위한 MS SQL INDEX (인덱스)사용법 : 네이버 블로그 (naver.com)

    [DB] 인덱스(Index) 사용 예시 (생성, 조회, 삭제, 리빌드) (tistory.com)

     

     


    Python

    타입 명시

    age: Union[int, None] = None
    
    # == 
    
    age: int | None = None
    
    # == 
    
    age: Optional[int] = None

    셋 다 같은 사용법

     

    파이썬에서 타입 힌트는 말 그대로 변수 타입에 대한 힌트일 뿐, 다른 타입을 사용한다고 해서 문제가 발생하지 않는다. (TypeScriptt에서는 이렇게 작성하면 타입체커가 열일을 시작하지.)

    문법

    날짜 시간 관련 포맷

    [python] datetime 모듈 strftime 메소드, 포맷(format) 코드 정리 by bskyvision.com

     

    *args, **kwargs, dict()

    이건.. JS의 스프레드 문법 같은 거 없을까? 생각하다가 오? 하고 찾아서 사용법 알아보는 중..

    *args 와 **kwargs 사용하기 - 슬기로운 파이썬 트릭 中 (tistory.com)

    글 이해한 내용 정리

    더보기

    args kwargs
    : argument unpacking
    : 함수 정의에 주로 사용됨

    args
    : 이름이 없는 인자로 구성된 tuple

    kwargs
    : 이름이 주어진 인자로 구성된 dict


    함수 인자 풀기

    *, ** 연산자를 잘 사용하면
    연속된 데이터(*)와
    딕셔너리(**)에서
    함수 인자를 풀어내는 기능을 쉽게 할 수 있다

    def print_vector(x, y, z):
    print(f"<{x}, {y}, {z}>")
    
    tuple_vec = (1, 2, 3)
    list_vec = [1, 2, 3]


    이렇게 튜플이나 리스트로 만들어진 값이 담긴 변수를 *을 이용하면 여러 개의 인자를 요구하는 함수에 한 번에 넘겨줄 수 있다

    dictonary 같은 경우 **로 풀면 값만 알아서 따서 프린트된..다?

    dict_vec = {"x": 1, "y": 5, "z": 10}
    print_vector(**dict_vec)
    출력: <1, 5, 10>


    <<내가 이해한 바를 정리하자면>>
    함수에 받을 인자 개수를 확실하게 알 수 없을 때,
    함수에 여러 개의 인자를 편하게 넘기고 싶을 때 사용하면 좋은 것 같다.

    함수에서 사용하는 꿀팁으로 알려주신 ** 방법은 내가 파이썬 공부를 조금 더 해야할 것 같다. 이해는 되는데 다르게 활용해보라고 하면 아직 정확한 이해가 된 것이 아니라서 감으로 대충 때려맞출 정도..? 이기 때문에 나중에 내 코드 다시 봤을 때 '음..? 뭐였..더라? 아 실행해봐야지.. 아 이런 거였구나.. 음.. 다시 문서를 봐볼까?'할 것 같다.

     

    for문과 if문을 한 줄에! - 리스트 컴프리헨션

    1) 리스트 컴프리헨션 - 제대로 파이썬 (wikidocs.net)

     

    .dict(), .ittems(), setattr()

    sqlalchemy랑 fastaapi pydantic schema 관련으로 궁금한 사항이라서 찾아봄

    [ Python 3 ] 딕셔너리(dictionary) 생성 ({}, dict ()) (tistory.com)

    딕셔너리 타입?

    • 키(Key; immutable)와 값(value: mutable)으로 매핑되어 있는 순서가 없는 집합
    • json 형식과 같

    .dict()

    • dict constructor로 파이썬 구현 과정에서 많이 사용됨

    파이썬 setattr 함수를 사용해 봅시다. (tistory.com)

    Python Schema library 정리 (tistory.com)

    schema

    • JSON/YAML(또는 다른것들)에서 python 데이터 타입으로 변환된 config file, forms, 외부 서비스 또는 command-line 파싱에서 얻은 것과 같은 python 데이터 구조를 검증하기 위한 라이브러리

    Fast API, Schema 예시 설정 및 데이터 타입 (velog.io)

    swagger 작성할 때 fastapi에서도 작성 예시를 직접 들어줄 수 있나보다

     


    FastAPI

    Uvicorn

    FastAPI 애플리케이션에 uvicorn 직접 가져와서 실행하기 - 디버깅 - FastAPI (tiangolo.com)

    위 방법을 이용하면 uvicorn 명령어가 아닌 python 명령어로 앱 실행 가능해짐

    [fastapi] uvicorn, fastapi 비동기 메커니즘 이해 : 네이버 블로그 (naver.com)

    여기를 통해서 알게 된 건데, gunicorn은 uvicorn 프로세스를 관리하는 프로세스로 nodejs에서 pm2와 유사한 개념임.

    단, nodejs가 쓰레드 기반 구현이라면 asgi server, asgi framework는 프로세스 기반으로 구현.

    상세하게 읽어볼 필요 있어 보임.

    __main__ --- 최상위 코드 환경 — Python 3.12.0 documentation

    __main__에 대한 궁금증으로 파이썬 문서 가져옴..!

     

    Pydantic

    pydantic을 사용하여, 안정성 높이기 — re-code-cord (tistory.com)

    앞서 파이썬 타입 명시에서 설명했듯 파이썬은 변수 타입이 이렇다 힌트만 줄 뿐, 강제하지 않는다. pydantic은 런타입에서 타입 힌트를 강제하고 유효하지 않으면 error를 발생시킨다.

    pydantic은 정확하게 따지자면 parsing 라이브러리.

     

    Optional 특성도 여기서 알게 됐다.

    fastapi 공식문서를 보다 보면 스키마에서 각 필드별로 타입 지정을 해줄 때 아래와 같이 해주고 있다.

    # Python3.10~
    description: str | None = None
    
    # ~Python3.9
    description: Union[str, None] = None

     

    Optional을 이용하면 Optional[str] = None 이렇게 사용해줄 필요 없이 한 번만 기입하면 된다고 한다.

    이렇게 편할 수가.. 글자 입력 조금이라도 덜할 수 있는 방식이었네.

    이게 가능한 이유는, python에서 제공하는 자료형 뿐만 아니라 typing  datetime 등 일반적인 자료형을 지원하며 이외에도 직접 만들어서 사용할 수도 있고 기존의 자료형을 제한해서 사용하는 것도 가능하다고 한다.

    pydantic (tistory.com)

     

    [Fastapi]SQLAlchemy 이용하여 DB와 연결하기 (velog.io)

    sqlalchemy 쪽에서도 언급하고 있는 글인데, pydantic에 대한 설명이 있어서 여기에도 끌어왔다.

    pydantic orm_mode : dictionary 자료형이 아니라도 읽을 수 있게 해줌
    orm_mode가 아니라면, path operation으로부터 SQLAlchemy model을 반환했을 때 relationship data는 반환하지 않을 것

    이러한 이유로 'select를 제외한 경우에 사용해야 하는구나!' -> 'relationship을 걸었다면 orm_mode를 걸어줘야 한다고?'로 이어지며 이해되지 않던 생각의 고리가 드디어 이해되면서 탄탄해졌다.

     

    Body 중첩 모델

    Body - Nested Models - FastAPI (tiangolo.com)

    sqlalchemy에서 relationship으로 가져온 내용을 스키마에 담아 보낼 때 이 모델을 사용하는 걸 봤다. 설명이 여기 있었군.

    HTTP Exception 일괄 처리

    logger에 기록되도록 except처리를 할 때 일반 에러를 잡는 것 말고 http exception일 때 따로 상태코드별로 기록할 수 있도록 하는 방법을 알고 싶어 gpt와 열심히 대화를 나눠보았다.

    A. 404 에러를 처리하는 예외를 던지기 위해서는 해당 상황에 대한 조건문이나 검사를 통해 HTTPException을 발생시키면 됩니다. 아래는 간단한 예제입니다:

    from fastapi import HTTPException, status
    
    try:
        # 어떤 작업 수행
        result = find_something()
    
        if result is None:
            # 조건에 따라 404 에러 발생
            raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Resource not found")
    
        # 결과 반환 등 다른 작업 수행
    
    except HTTPException as http_exception:
        # HTTPException이 발생했을 때의 처리
        # 상태 코드, 상세 메시지 등을 가져올 수 있음
        status_code = http_exception.status_code
        detail = http_exception.detail
        logger.error(f"HTTPException occurred: Status Code {status_code}, Detail: {detail}")
        raise  # 예외를 다시 던져줘서 FastAPI가 적절한 응답을 생성하도록 함
    
    except Exception as e:
        # 다른 예외에 대한 처리
        logger.error(f"An unexpected error occurred: {e}")
        raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="Internal server error")​


    이렇게 하면 특정 조건이 만족되었을 때 404 에러를 발생시키고, 그 외의 예외에 대해서는 500 에러를 발생시키도록 할 수 있어요.

    Q. 아 그렇게 하면 404 이외의 에러가 발생하더라도 모두 except HTTPException as http_exception으로 빠져서 로거에 기록하는 로직은 간단화해줄 수 있겠네?

    A. 맞아요. `HTTPException`은 FastAPI에서 예외 처리를 위해 특별히 설계된 예외 클래스이기 때문에, HTTP 상태 코드와 상세 메시지를 제어하기 용이합니다. 따라서 특정 상황에서 404 에러를 발생시켜 처리하고, 그 외의 예외에 대해서는 기본적으로 500 에러를 발생시켜 로깅하면 코드가 간결해지고 유지보수가 편리해집니다.

     

     


    Ubuntu 관련???

    screen

    Linux/기본명령어/screen - 인코덤, 생물정보 전문위키 (incodom.kr)

    [Linux] screen 명령어 :: 토마스의 기술 정리함 (tistory.com)

    백그라운드로 돌리면서 포어그라운드로 가져왔다가 다시 돌려놓는 시스템이라니... 너무 신기하잖아?!

    이렇게 또 배운다.. 재미있다

    [Linux] Screen 사용법 (velog.io)

    스크린을 만들고 로그파일 생성도 가능한가 보다. 오호..

     

    아래는 screen에 대한 이해를 위해 gpt와 수다수다한 내용

    네, Docker 컨테이너 내에서 `screen`을 사용하면 그것은 컨테이너 내부에서의 터미널 세션을 의미할 거야. 간단한 비유로 설명하자면, Docker 컨테이너는 격리된 환경에서 실행되는 가상화된 프로세스이며, 이 컨테이너 내부에서의 터미널 세션은 그 안에서 동작하는 프로세스를 모니터링하거나 명령어를 실행할 수 있는 창문 같은 역할을 하는 거야.

    예를 들어, 당신이 백엔드 서버를 Docker 컨테이너 내에서 실행하고 있다고 가정해봐. 그리고 그 컨테이너 내부에서 `screen`을 사용하여 백엔드 프로세스를 실행하고 있다면, 이 `screen` 세션은 컨테이너 내부에 있는 것이야. 그래서 외부에서 `screen` 명령어를 사용하면 컨테이너 내부의 터미널로 연결되는 것처럼 보일 거야.

    이 비유로 생각해보면, Docker 컨테이너는 하나의 방(가상 환경)이고, 그 방 안에서 `screen`은 그 방의 창문이라고 생각할 수 있어. 창문을 통해 방 안의 일이나 프로세스를 확인하고 제어할 수 있게 돼.

     

    Q. 그러면 질문, docker 컨테이너 bash로 접근하는 것과 screen으로 접근하는 것의 차이가 뭐야?

    A. Docker 컨테이너에 접근하는 방법은 크게 두 가지가 있어: `bash`로 직접 접근하는 것과 `screen`과 같은 터미널 멀티플렉서를 사용하는 것.

    1. **Bash로 직접 접근:**
       - `docker exec -it <container_id> /bin/bash`와 같은 명령을 사용하면 컨테이너 내부의 Bash 셸에 직접 접근할 수 있어. 이는 컨테이너 내에서 명령을 실행하거나 파일을 확인하는 데 유용해.

    2. **Screen 또는 다른 터미널 멀티플렉서를 사용:**
       - `screen` 또는 `tmux`와 같은 터미널 멀티플렉서를 사용하면 컨테이너 내에서 여러 작업을 동시에 실행하고 관리할 수 있어. 예를 들어, 백그라운드에서 돌아가는 프로세스를 유지하거나 여러 터미널 세션 간에 이동할 수 있어.

    간단하게 말하자면, `bash`로 직접 접근하는 것은 컨테이너 내에서 명령을 실행하고 작업을 수행하는 데 사용되는 반면, `screen`과 같은 터미널 멀티플렉서는 여러 터미널 세션을 관리하고 백그라운드에서 실행 중인 작업을 유지하는 데 유용하게 사용돼.

     

    Q. bash로 접근하는 것은 일반적으로 ubuntu 서버를 ssh로 여러 명이 붙어서 작업하는 것처럼 할 수 없고 한 명만 접근이 가능한 거야? ssh로 여러 명이 붙어서 작업할 수 있도록 돕는 게 screen이라고 이해하면 되려나? 그러면서 nohup처럼 백그라운드로 돌리면서 언제든지 포어그라운드로 올렸다 내렸다도 할 수 있는 거구??

    A. 맞아, 네 말이 맞아! `bash`로 직접 접근하는 것은 주로 한 명의 사용자만 접근이 가능한 반면, `screen`이나 `tmux`와 같은 터미널 멀티플렉서를 사용하면 여러 사용자가 동시에 접근하여 작업할 수 있어.

    `screen`을 예로 들면, 이는 세션을 생성하여 각 세션에서 독립적으로 작업할 수 있게 해주어 여러 사용자가 동시에 작업할 수 있도록 돕는다. 이렇게 하면 SSH로 여러 명이 접속해서 각자의 세션에서 작업할 수 있게 되어 효율적인 협업이 가능해진다.

    또한, `nohup`과 비슷하게 백그라운드에서 프로세스를 실행하면서, `screen`을 통해 세션을 유지하고 필요할 때 포그라운드로 올려서 상호작용할 수도 있어. 이는 장기적으로 실행되는 작업이나 서버 프로세스를 관리하는 데에 유용하다.

    요약하자면, `screen`을 사용하면 여러 사용자가 동시에 작업할 수 있고, 백그라운드에서 실행 중인 작업을 관리하면서 언제든지 포그라운드로 전환하여 상호작용할 수 있다.

     

     

     

     

     

    728x90
    반응형
    Comments