ASAC-SK플래닛 T아카데미 데이터 엔지니어

25.11.07 22일차 [GIT GUL | 파이썬 Entity, class, object 개요 | pydantic ]

Datadesigner 2025. 11. 7. 17:49

오늘은

 

 

오전에는

 

GITHUB에서 FORK, repositories 등등의 설명과 

GIT을 vs code에서 GUI 방식으로 작동시키는 법 등을 알려주셨고 

 

오후에는 

 

파이썬에서의 Entity, Class, Object 등의 개요와 연습

pydantic 불러오고 사용하는 방법

pydantic과 BaseModel, Annotated 등으로 로그인 정보를 받아오는 실습을 진행했다.

 


오전

 

어제는 토큰을 받아서 인증하는 방식을 차용하였고 오늘은 로그인방식을 사용했다.

그러려면 키를 발급받아야 하는데 

먼저 깃을 다운받은 후 터미널에서 위 코드를 입력해준다. 그러면 키 파일이생긴다.

 

그 이후 깃허브 사이트에서 우측상단 프로필 > 세팅 > SSH and GPG...> new ssh key > 키 파일 텍스트 입력

하면 등록된다, 처음 단계에만 하면 된다

 

그리고 프로젝트를 하고 로컬과 원격 저장소로 연결하는 방식에는 두가지가 있는데 이를 실습했다.

 

1. 원격 저장소(origin) 생성 > 프로젝트 구성

1. 프로필 > Repositories > 오른쪽 new 버튼 클릭

 

2. 각종 세팅 옵션들, 프라이빗, 퍼블릭, 라이센스 등 다양한 옵션이 있다, 일단 이부분은 고정하고 생략

 

3. 생성된 모습


1-2. vs code에 추가

초록색 code버튼 클릭, ssh 복사
git clone (복사한 사이트명) 엔터

 

clone 을 사용해서 원격 저장소(origin)에서 로컬 저장소(내 컴퓨터 vscode)로 데이터를 복사해온 것을 확인할 수 있다.




1-3. Repositories 삭제

가운데 위에 있는 Setting 클릭
general 맨 밑에 danger zone에서 삭제할 수 있다.

여기는 퍼블릭, 프라이빗 이나 삭제 등 다른 일을 수행할 수 있다.
근데 깃은 다른사람과 연동도 많이 되고 문제도 많이 생겨서 이 부분을 쉽지 않게빼놨다.
그래서 삭제, 수정등이 조금 어렵다 여기서 삭제 

삭제하려면 창 3갠가 뜬다 ㅋ

 

2. 로컬 저장소에서 원격 저장소(origin)으로 파일 업로드

오른쪽 세번째의 source control 클릭 후 initialize repo.... 클릭
git remote add origin ( 사이트명 )

이제 로컬 저장소 - 와 원격 저장소가 연결되었다.
지금은 원격 먼저 진행해서 소스컨트롤에 바로 연결되어있지만 로컬에서 작업하고 추후 원격 저장소로 연결하려면 위 방법을 사용하면 된다.

 

3. add, commit, push, pull
방금 만든 readme.MD 에 글자를 입력했다. 그러니 오른쪽에 창에 뭔가 바뀌었다.
클릭해보면 어떤 부분이 이전 버전과 다르게 바뀌었는지 뜬다
여기서 + 버튼 클릭하면

 

staged changes,로 바뀐다

이게 어제 수업내용에 있었던 add. 를 사용해서 스테이징 하는 행동이다.
CLI에서 GUI로 하니까 이렇게 편한것을


그 이후 commit을 눌러주면

창에서 사라지고 아래쪽 창에 새로 생겼다, 이제 저 각주를 단 부분의 설명이 add:티스토리 테스트이고
변경된 모습은 저기를 누르면 출력된다.

변경된 모습

이제 sync changes 를 누르면 origin(원격저장소)에 오피셜로 업로드되어서 수정되는것이다. 클릭

알림창이 뜬다
저 파란색과 보라색 ui가 각각 로컬과 origin을 뜻한다, 이제 저기부분까지 동기화가 되었다는 뜻이다.
깃허브 사이트에서도 텍스트가 추가된 모습을 볼 수 있다.

 

4. fork
fork는 다른 사람의 원격 저장소(origin) 에서 내 원격저장소(origin)으로 repositories를 복사해오는 것이다.
clone 은 다른 사람의 원격 저장소(origin)에서 내 로컬저장소(local)로 가져오는것이어서 그 둘의 차이가 있다.

웬만한 it 공부 책은 github를 가지고 있다고한다, 이 책을 예시로 실습하겠다

오른쪽 Fork 클릭

요런 창이 뜬다, 필자는 fastapi-ca(클린아키텍쳐) 로 썼고 각주는 그냥 썼다, copy the main branck only는 체크 해제하고 create fork 클릭
내 repositories에 추가된 모습을 볼 수 있다.
이제 아까 수업 내용을 응용해서 이 repositories를 git clone 해서 vs코드에서 소스를 볼 수도 있는것이다.

 

 

commit 메시지 관습

출처 : https://velog.io/@chojs28/Git-%EC%BB%A4%EB%B0%8B-%EB%A9%94%EC%8B%9C%EC%A7%80-%EA%B7%9C%EC%B9%99

깃 커밋을 할 때 아까 위에 단 각주 있지 않은가? 그 각주의 문법이나 규칙이 존재해서 그것을 지키며 달아야만 한다.


파이썬 Entity, Class, Object

 

  • 개념
    • 엔티티 (Entity)
      • 이 세상에 존재하는 유형/ 무형 적 모든것을 대변
        • 유형 : 사람, 자동차, 비행기 ...
        • 무형 : 사랑, 슬픔, 민주주의 ...
      • 엔티티를 코드로 옮긴다면 -> 문법(룰)이 필요하다, -> 클래스 사용
      • 클래스를 통해 묘사하고자 하는 대상 -> 엔티티
    • 클래스 (Class)
      • 엔티티를 코드로 옮긴다면, 클래스 문법에 맞춰서 작성 -> 엔티티를 코드로 표현하는 문법
      • 엔티티 사람 ==> 사람 클래스
      • 클래스는 코드로 존재함
    • 객체 (Object)
      • 작성된 코드가 os상에서 구동되려면 -> 실행버튼(혹은 명령) 수행해야 함, -> 클래스는 메모리에 로드됨 ->
      • 실제 실행이 됨
      • 코드로 작성된 클래스를 본따서 메모리에 로드되면 -> 객체라고 부른다
      • 클래스의 인스턴스는 객체이다
        • 모든 객체는 메모리상에서 구분될 수 있는 주소를 반드시 가짐
        • 해당 주소를 참조하는것이 [변수] 이다.
특징
# 간단하게 표시

# 자동차(엔티티) 클레스 작성
class Car():
  pass

# 클레스를 이용하여 객체 생성
car = Car()
# car라는 변수는  Car 클레스의 인스턴스(객체)를 참조한다.

# 사용 => Car 클레스의 내부 접근은 => .(도트 연산자 사용)
# car.xxx

 

# 로그인 하는 유저 <= 엔티티

# 클레스 구성 <= 코드
class User():
  uid : str
  upw : str

# 실제 구동시 해야할일 작성 => 객체 생성
user = User()       # 객체 생성
user.uid = 'guest'  # 객체 내부의 맴버 변수에 아이디값 세팅
user.upw = '1234'   # 객체 내부의 맴버 변수에 비밀번호값 세팅

# 사용 -> 로그인 쿼리등 로그인 작업 진행
print( user.uid, user.upw )

# 사용자 로그인 정보는 개별값이 아닌 user 객체를 통해서 일괄 관리, 접근가능

 

 

문법
# [] 생략 가능함
class 클레스명[ ( [ 부모클레스, 부모클레스, ... ] )  ]:    # 클레스 선언문
  [
    # 맴버 변수
      # (*)클레스 변수 : 데이터 관점에서 가장 많이 보이는 형태임
      # 인스턴스 변수

    # 커스텀 정의 함수
      # 맴버 함수
      # 스페셜 함수

    # 생성자 함수 (함수명(고정) : __init__ )

    # 기타 함수
      # 소멸자, 객체설명, ....
  ]

 

기능별 문법 확인
  • 상속
  • 자식 클래스 = 부모 클래스의 모든 유산(변수,함수,생성자)를 그대로 사용 가능함 + 스스로(자식) 추가한 자산(변수,함수) 등등
# Object는 가장 근본(root)가 되는 클레스이므로 특별히 생략 가능함.
class A:        # A 클레스의 부모 클레스는 Object
  pass

class A2():     # A2 클레스의 부모 클레스는 Object
  pass

class A3(A):    # A3의 부모는 A라는 것을 명시적 표현
  pass

class A4(A, A2):  # A4의 부모는 A, A2  => 다중상속 표현
  pass
# 상속 관계 확인 => mro() : 내장되어 있음
A.mro(), A2.mro(), A3.mro(), A4.mro()

# Object는 모든 클레스의 수퍼클레스(근본, 루트, 시작점) => 모든 랭귀지는 동일
([__main__.A, object],
 [__main__.A2, object],
 [__main__.A3, __main__.A, object],
 [__main__.A4, __main__.A, __main__.A2, object])

object는 모든 클래스의 근본이다. 이는 모든 랭귀지에서 동일하다.

self

클래스 내부에서 자기 자신을 지칭(대변)하고 싶을때 사용하는 표현

대부분 타 언어들은 this <-> self

왜 사용?

클래스 내부에서 멤버 접근시에 사용함

 self.멤버xx           <= 접근

 

클래스 정의, 객체 생성, 객체 해제
# 가정 : 사람을 대상으로 클레스 설게
# 클레스명은 첫글자 대문자 -> 카멜표기법(관습적)

# 1. 클레스 정의
class Person:
  pass

# 2. 객체 생성
#    클레스명()
#    p는 변수, Person 객체를 참조, Person 객체의 주소값을 가지고 있다
p = Person()

# 2-1. 주소 확인
p, id(p)
(<__main__.Person at 0x79cd8fa096d0>, 133923784922832)

p는 Person을 참조하고 객체의 주소값을 가지고 있다. id(p)가 주소 받는 함수

# 3. 객체 사용 (생략)

# 4. 객체 해제
del p

 del이 국룰이다

# 참조하는대상이 소멸 되었으므로, p는 정의 되어 있지 않게 된다
try:
  print( p )
except Exception as e:
  print( e )

이 때 오류 나지 않게 try ~ except 문을 사용했다

결과는

name 'p' is not defined

 

자동차 클래스 설계
  • 클래스명 : Car
  • 데이터 -> 멤버 변수 -> 인스턴스 변수
    • 모델명 : name
    • 연식 : age
    • 가격 : price
  • 행동 -> 멤버 함수 -> 인스턴스 함수
    • 운전한다 : driving
    • 주유한다 : eating
    • 주차한다 : parking
  • 왜 클래스로 자동차라는  엔티티를 설계?
    • 가정 : 자동차 관리 앱
    • 전 세계에는 수 많은 브랜드, 모델을 가진 차가 존재한다, 이걸 코드로 표현하려면?
    • 변수가 너무 많이 필요하지
    • 자동차가 가진 공통적인 요소를 묶어서 하나의 클래스로 설계 => 각각 브랜드, 모델별 데이터를 넣어주면 => 100개도 넘는 객체마다 각각 다른 브랜드와 모델을 세팅해서 관리할 수 있다.
# 클레스 정의
class Car:
  # 1. 생성자 함수 -> 이름은 __init__,
  #    역활: 객체생성할때호출. 인스턴스변수 초기화(통상)
  def __init__(self, name, age, price):
    # 인스턴스변수를 생성 -> 초기화(통상)
    self.name = name
    self.age = age
    self.price = price

  # 2. 맴버함수
  def driving(self):
    print('자동차는 사람이 운전할 수 있다')
  def eatting(self):
    print('자동차는 사람이 주유할 수 있다')
  def parking(self):
    print('자동차는 사람이 주차할 수 있다')


# 객체 생성
car1 = Car('제네시스', 2025, 7000)
car2 = Car('그랜저', 2024, 5500)
car3 = Car('소나타', 2023, 4000)

# 데이터 사용
# -> 모델명, 년식, 가격 이라는 데이터는 객체를 통해서 한몸(객체)으로 관리됨
car1.name

제네시스

중요 포인트 : 생성자 함수 이름은 무조건 __init__이다

 

일단 이 코드에서 함수는 아직 작동하진 않아서 자세히 기능을 알 순 없었다.

 

클래스를 정의하고, 그 클래스에 인스턴스 변수를 생성하고, car1, 2, 3인 객체를 생성했다.

이 객체를 생성할때 인스턴스변수를 초기화하고, 값을 부여한다.

마지 sql의 테이블처럼 컬럼명을 붙여서 값을 출력해올수 있다

  • 멤버 변수
    • 인스턴스 변수
    • 객체가 생성된 이후에 만들어진(접근 가능한) 변수
      • 생성
  self.변수명 = 값
  # 최초 코드가 등장하는 곳 (생성및 초기화 되는 곳임)
  # 통상 => 생성자에서 구현

 

클래스 변수

클래스를 정의하면서 바로 변수를 입력하는 방법

class User:
  name = 'kim'
  age  = 30

# 객체 생성 없어도 사용 가능
# static(정적) 변수라고도 함(뉘앙스)
# 유틸리티 기능, 상수값 정의
# fastapi 구성시 pydantic용 클레스 정의시에도 자주 사용됨
User.name

kim

정의하면서 바로 값을 부여하는 방법이다.

 

 

# Pydancit (파이단틱)   
- 두 가지 토끼를 잡을 수 있음     
- 목적       
- 데이터 검증(타입, 길이 => 유효성 검사)       
- 데이터의 직렬화 처리 => json 변환이 쉬움, 그래서 씀            
- dict 자료구조를 => 문자열로 변환(json) : 직렬화            
- json 형태 구성된 문자열 => dict 자료구조로 변경 : 역직렬화       
- 직렬화 이유 => 자료구조를 문자열로 변환해서
=> 통신 시 데이터 전송에 사용 -> 간단하게 json 형태로 데이터를 묘사하고 전달 가능함       
- 개별적 데이터를 하나의 구조형 형태(json) 으로 구성하여 통신이 가능.       
- 파이썬에서는 클래스와 객체에 대한 묘사나 사용이 원활해야 가능   
- client <-> json 형태로 주고 받는다. <-> server

오늘은 데이터 검증을 실시했다
1. 모듈 가져오기
1. pydantic 모듈 가져오기

아까 object가 모든 클래스의 상위였던것처럼, 무조건 데이터를 관리할 떄에는 BaseModel을 상속받아야 한다.
그래서 BaseModel을 가져온다, 그리고 app으로 적용한다.

2. 데이터 유효성 체크


pydantic이 틀린 데이터는 쳐낼수 있도록 클래스에 들어가는 변수들에 기본세팅을 한다. 약간 애너테이션 느낌?

4. 라우팅 생성
라우팅이 코드에선 더 뒤에있지만 순서상 먼저와야해서 먼저 작성한다.
이제 /test/item/ url을 만들어주고 BaseModel을 상속받은 클래스를 세팅한다.
item이라는 변수가 클래스 Item을 받는다. 
그리고 잘 출력되면 "전송결과" dict를 출력한다.

3. 데이터 샘플 체크
이 예제에 기반해서 타입을 틀리거나, 누락하거나 각종 실습을 해보면서 값을 확인한다.
먼저 이를 위해서 extension에서 thunderclient를 다운받는다.
thunderclient는 post방식이 잘 작동하는지 확인할 수 있는 extension이다.
전달방식을 post로 바꿔주고, url을 입력하고, body를 통해서 데이터를 전달하면 된다.


1. 정상

2. 오류, price의 타입이 맞지 않는다, int인데 float로 보내서

 

3. 오류, 기본값을 설정하지 않은 price가 없어서 missing 오류가 났다.
4. is_rich는 값을 입력안했지만 기본값이 있어서 오류나지 않고 정상작동하는 모습이다.
전체로 보면 이런 느낌

2. 옵션 처리

같은 방식으로 새로운 데이터를 줬다.
그리고 Optional을 새로 추가했는데 이는 값이 있어도 되고, 없어도 된다는 변수라서 말 그대로 옵션의 역할을 한다.
이제 맥북프로... 데이터를 post 해보겠다
1. 정상
2. desc에 값이 없어도 오류가 나지 않는 모습을 볼 수 있다. 이것이 optional의 기능


3. Field 제약 조건 => Field클래스 사용

전체 컷, 읽어보시길
기본적인 타입체크의 용도보다 조금 더 촘촘한 조건을 제한하는 클래스다,
예제를 보면 최소, 최대 길이 제약, 등 딱 로그인 할때 적용하기 좋아보인다

이제 예제를 대입하며 비교해보자
먼저 tax 변수에 = kor_tax로 별칭을 주었는데 데이터를 요청할때 tax로 해야할까 kor_tax로 해야할까?
1. tax로 변수를 설정하니 오류가 나오는 모습이다

2. kor_tax로 설정하니 오류가 안난다

별칭을 부여했으면 그 별칭으로 데이터를 전달해야 한다,
실제로 이는 나중에 다른 사이트들에 보안유지 문제로 많이 사용한다고 한다.

3. gt 0 인데 0보다 커야하는데 0이랑 같으니 오류가 난다.
이렇게 데이터가 데이터베이스로 오기 전부터 미리 클래스에서 걷어내버리니까 처리시간에 훨씬 더 도움이 되고 빨라지는 기능이라고 한다, 조건문같은 기능으로 보이지만 처리면에서 훨씬 효율적인것이다.


이제 이 기능을 우리가 했던 main 로그인 처리에 적용할 수 있다

 

 

pydantic을 로그인 처리에 적용시키기


1. pydantic을 main.py에 불러온다.



2. pydantic모델을 정의해준다,
기존에 fastapi도 app으로 불러온것처럼
로그인정보에 필요한 uid, upw의 타입을 정의했다.

 

3. 기존 로그인 정보 받아오던 부분에 pydantic문법으로 처리해준다
이렇게 바뀐 부분이 어딘지 확인할 수 있는게 github의 장점이다.

 

기존 코드, form(... 모든걸 받아온다는 뜻)
pydantic을 적용한 코드

기존 코드는 uid, upw, 지금은 두개밖에 없지만 나중에 더 많은 항목의 정보를 받아야할때 모든 변수를 하나하나 지정하고 대입해주기에는 너무 비효율적이다.
그래서 pydantic을 이용해서 클래스를 먼저 지정해주면 그 다음부터는 모든 값을 받아오게 되는것이다.
이때 annotated 기능이 들어가는거다, 디테일한 부분은 필요하다면 구글에 더 검색!

같은 기능을 수행하는것을 확인할 수 있다!

복습 끝~ 깃허브 재밌다 오늘 수업은 스무스했다 근데 실제로 적용하려면 좀 어려울거같긴 하다