[Microsoft Data School] 6일차 - python 개발 환경 구축, git, python 개요

RudinP·2026년 1월 8일
post-thumbnail

python 개발 환경 구축

Conda

Package 및 환경 관리 시스템

  • python에서 package의 관리 문제를 해결하기 위해 개발
    • package간의 충돌 방지를 위한 종속성 해결(dependency 문제)
  • 버전간의 변경이 심하기 때문
  • miniconda 먼저 깔고 필요한 패키지 깔면 됨(anaconda가 기본 설치된 패키지는 더 많음)

설치 링크

환경 생성

conda prompt에서 실행한다
일반 명령 프롬프트에서 실행하려면 환경변수 설정을 해줘야하는데, 이는 설치 시 제공되는 옵션이기는 하지만 기본 프로그램과 충돌 가능성이 있어 권장되지 않는다고 한다.

conda create -n py313 python=3.13
conda activate py313
conda info --envs //가상환경 리스트 확인
  • conda create -n 환경이름 python=python버전

Visual Studio Code

설치 링크

Extension 설치

  • python/python debugger
  • jupyter: 가상환경을 제공하는 툴
    • 사용 이유: 시각화할때 화면에 디스플레이 되는걸 보고싶을 예정. 그것을 바로 vscode 안에서 볼 수 있도록 해줌

개발 환경 확인

환경변수 설정

  • miniconda를 깔았으므로 miniconda를 기준으로 한다.
  1. 윈도우 검색 창에 환경 변수 편집 입력
  2. Path 변수를 찾아 선택하고 편집 클릭
  3. 새로 만들기
    • C:\Users\[USERNAME]\miniconda3\
    • C:\Users\[USERNAME]\miniconda3\Scripts\

기본 프롬프트 설정

  • preferencessettings → windows 검색


command prompt로 변경

kernel 선택

test

+Code 선택 후
print("hello") 실행해보기
(kernel 설치 필요시 설치)

Python Package 설치

  • 데이터 전처리: NumPy, pandas
  • 데이터 시각화: matplotlib, seaborn, Folium, wordcloud
  • 웹 크롤링: requests, Beautiful Soup, Selenium
  • 시계열 데이터 분석: pandas, statsmodels
  • 한글 처리: KoNLPy, KSS, Kiwi
  • 이미지 처리: OpenCV

conda prompt에서

pip install <package> → dependency 체크 안함

conda install [-c <channel>] <package> → dependency 체크 함

Google Antigravity

VS Code 기반 Agent Manager

  • Artifacts: 작업 목록 및 계획, Diff, Screenshot 및 화면 녹화, 테스트 결과 등
  • Cursor와 같은 코딩 에이전트다
  • 주의: Terminal 명령에 대한 보안 설정 필요
  • VSCode+copilot과 다르게 line by line으로 명령을 칠 수 있다.

git

구조, 브랜치 전략에 집중하자

분산 버전 관리 시스템

  • Single Failure Point가 없음
  • 중앙 서버에 연결할 필요 없음
    • 인터넷 없어도 ok
  • version이 아닌 변경을 추적/관리

기능

  • 버전관리
  • 분기&병합
  • 커밋
  • 충돌 해결
  • 히스토리&로그

branch 전략

Git Flow

branch 종류

  • master: Prod/Live 서버에 제품으로 출시되는 Branch
  • develop: 다음 출시 버전을 개발하는 Branch
  • feature: 추가 기능을 개발하는 Branch. develop으로 merge 된다.
  • release: 제품 출시를 준비하는 Branch. 테스트 및 QA 진행
  • hotfix: 제품 출시 이후 발생한 버그를 수정하는 Branch

장/단점

장점

  • 큰 조직, 여러 팀에 걸쳐 작업에 적합
  • 여러 버전 제품 관리에 효과적
  • 불완전한 부분을 commit하거나 하여 여러 개발자가 하나의 기능 개발에 참여

단점

  • 관리해야하는 branch가 많다
  • 개발된 기능이 누락되거나 불필요한 기능이 추가될 수 있다
  • 개발된 기능이 제품에 반영되기 까지 여러 단계를 거쳐 merge 되어야 한다
  • CI/CD에 부적합

Github Flow

branch 종류

  • master: Prod/Live 서버에 제품으로 출시되는 branch
  • feature: 개발자가 작업하는 branch
    • 새로운 기능이나 버그 수정을 위해 master에서 만들어짐.
    • master로 merge됨.

→ master에 merge되면 바로 제품으로 출시되는 구조

  • 자동화된 test가 충분히 준비되어 있어야 함
  • PR을 충분히 리뷰 필요

장/단점

장점

  • 작은 조직용
  • Agile, CI/CD에 적합
  • 간단
  • 비교적 conflict가 자잘자잘하다

단점

  • master에 merge되면 배포되므로 버그에 쉽게 노출
  • 여러 배포 버전 지원 힘듦
  • 큰 조직일 시 merge confilcts 증가

Git 사용 Tip

  • Merge는 자주 한다
    • diff를 줄여 conflict를 줄이기 위함
  • Commit은 작고 목적에 집중될 수 있도록 한다
    • 기능 개발, Re-engineering을 같이 하지 않는다
      • 리뷰 과정을 빠르게 하기 위함
  • Commit message는 자세히 기술
    • fix, update, typo 금지
    • 작업 이유, 내용, 효과 기술
  • PR에는 review를 수행하는 사람 입장에서 내용 기술

Python

장점

  • 직관적 문법
  • 풍부한 표준 라이브러리와 패키지
    • AI에 적합한 패키지 다수
  • Interpreter언어
    • REPL(Read-Eval-Print Loop) 환경
    • 컴파일 과정 필요 x
    • 생산성 ↑

단점

  • 실행 속도가 느리고 메모리 사용량 많음
  • GIL: Global Interpreter Lock
    • 여러 스레드가 동시에 python 바이트 코드를 실행하지 못하게 함
  • 런타임 오류 가능성

Memory Allocation

  • variable은 object에 묶여있는 이름
    • 실제 값은 Heap 영역에 할당

function이 call 될때마다 해당 function의 필요한 메모리 구조는 Stack에(정적)
dynamic하게 alloc 되는 부분은 heap에(동적)
Stack과 Heap이 서로 공간을 침범하게 되면 Out of memory 발생
cf) C는 바로 Stack으로 dynamic하게 연결. 그래서 실행속도 빠르다.

Data Type

  • immutable: int float str tuple
  • mutable: list dictionary set user-defined class

Default Argument

  • 반드시 immutable을 쓰도록 한다.

Default Argument: 파라미터가 전달되지 않았을 때 기본값

  • a와 b 가 같은 heap주소를 가리키게됨 → 중복으로 myf()가 불려진 것이 됨
  • i = list()는 단 한번만 실행(재사용)

immutable 사용시

#바람직한 버전
def myf(i = None):
	if i is None:
    	i = list()
    i.append('first')
    return i

Argument Evaluation

  • python에서는 argument evaluation → passing 된다.
  • 파라미터가 전부 계산된 상태에서 넘어간다.
    ['no sleep', time.sleep(1), time.sleep(2)][0] 이라고 한 경우
  1. 리스트 내의 값이 전부 계산됨
  2. [0]인 'no sleep' 채택 → 3초 뒤에 값 패싱

Performance

Laziness

  • sum(x*x for x in range(1_000))
    • 리스트를 만들지 않음. iteration을 돌며 sum에게 넘김
    • sum 내부에서 iteration을 돌면서 값을 그때마다 하나씩 가져옴 → 메모리할당 ↓, 속도 느림
    • 중간에 메모리 reallocation 발생 가능
result = []
for i in range(1_000_000):
	result.append(i * i)
  • sum([x*x for x in range(1_000))
    • 리스트가 모두 생긴 뒤에 sum으로 넘겨줌. sum 내부에서 list가 만들어지지 않음.
    • 1000개가 있는 리스트 자체가 넘어감 → 메모리할당 ↑, 속도 빠름
    • 이쪽을 추천
result = [i * i for i in range(1_000_000)]

참고: 읽기 편하라고 1000 단위로 _을 넣는 형태로 코딩함

List의 잘못된 사용

sequential search는 자제하자

  • x in alist (x)
  • alist.pop(0) (x) → reallocation 발생, list의 첫번째 elem을 가리켰기 때문
    • 전체 리스트가 카피됨

local 변수 접근이 빠르다

for i in range(10**6):
	math.sqrt(i)

-----------------------

# Better
from math import sqrt

for i in range(10**6):
	sqrt(i)

→ 물론, call 횟수가 적으면 위쪽을 사용해도 무방

__slots__

파이썬에서 클래스를 만들면 내부적으로 variable이 할당되는데, __slots__ 도 클래스마다 한개씩 생성됨
동일한 클래스라도 서로 다른 var을 가질 수 있다. → __dict__에 저장
클래스마다 동일한 var을 가질 수 있도록 해서 메모리 할당을 초반에 관리
같은 클래스 인스턴스가 여러개가 생기는 경우에 미리 메모리 할당을 해서 동일한 사이즈로 메모리 할당을 할 수 있도록 함
인스턴스가 생성될 때 효율적으로 해당 인스턴스 관리 가능
→ 클래스의 인스턴스가 대량으로 생성될 때 사용
목적: 메모리 관리 위함

  • __dict__를 요구하는 라이브러리에서는 쓸 수 없다
  • 클래스의 인스턴스를 동적으로 쓸 수 없다.

Metaclass

Class라는 Object를 만드는 것

  • template 과 비슷
  • Class의 생성과정을 제어하여 표준화된 API 및 동작 강제
  • 디자인 패턴 구현이나 ORM Framework 등에서 모델 Class를 관리할 때
    ORM: DB 관련 모델 클래스
type("<class name>",(<base classes>),{<attributes, methods>})

Typing hint

  • 런타임에러 방지용으로 typing hint가 추가됨
  • TypedDictDataClassNamedTuple과 헷갈리지 말자

Asynchronous Programming


cf) multiThread: OS차원에서 관리

예전엔 python은 synchronous밖에 안됐음
python에서 애플리케이션 레벨에서 이벤트루프 하에 자체적으로 관리하고 single core에서 일어남.

  • async 쓸거면 단일스레드 환경임을 보장할 수 있도록 노력하자

Python Asyncio Event Loop

저지르기 쉬운 실수

1. Blocking Event Loop

# I/O blocking이 일어나는 synchronous 함수 호출
async def fetch_data(order):
	response = requests.get(“https/example.com”) # →await 붙이기
	return response.text
    
# Heavy CPU bound 작업 수행
async def get_sum():
	return sum(range(10**7)) # → 이 Task가 CPU 계속 사용해서 async 의미 없음

2. Coroutine이 끝날 때까지 기다리지 않기, 끝난 Coroutine 계속 list나 dict에 보관하기

async def cook(order):
	print(f”Getting {order} order”)
	await asyncio.sleep(prepare_time.get(order, 5)) #main이 이미 끝나버려서 5초 안기다려줌
	print(f”{order} is ready”) #안찍힘

async def main():
	pasta_task = asyncio.create_task(cook(“Pasta”)) #이러고 끝남

asyncio.run(main())

3. Unhandled Exceptions

import asyncio
import psutil
import os

def show_memory():
	process = psutil.Process(os.getpid()) 
	print(f"Memory usage: {process.memory_info().rss / 1024 / 1024:.2f} MB")

async def faulty_task(n):
	# Simulate some quick failing tasks
	await asyncio.sleep(0.01)
	raise ValueError(f"Task {n} failed!")

async def main():
	i = 0
	mytasks = []
	while True:
	# BAD: we create tasks that fail, but never await them
	# Their exceptions are stored forever
		mytasks.append(asyncio.create_task(faulty_task(i)))
		i += 1

		if i % 100 == 0:
			show_memory()
		await asyncio.sleep(0.01)

if __name__ == "__main__":
	asyncio.run(main())

Global Interpreter Lock(GIL)

python thread가 동시에 수행되는 것을 막음

  • reference counting에서 race condition 방지
  • I/O Bound에서는 써도 괜찮다.
  • CPU Bound의 멀티스레드 환경에서는 쓰지 말자.

Garbage Collection

python 3.14부터는 없어짐

  • 3개의 Generation(0,1,2)로 나누어 관리
    • 객체는 Gen 0에서 출발, 살아있으면 1, 2로 옮겨감
    • Gen0을 더 자주 검사
  • GC Threshold
    • default: (700, 10, 10)
    • 객체 할당 횟수 - 해제 횟수 > threshold0 → Gen0에 대한 GC 시작
    • Gen1의 GC 수행 후 Gen0의 GC > threshold1 검사했으면 Gen1 GC 시작
    • Gen2 위와 동일

    프로세스 vs 스레드

  • 프로세스는 리소스의 오너
  • 프로세스 내에 스레드가 존재
  • 프로세스가 아닌 스레드 단위로 스위칭

코드 원칙

Don't Repeat Yourself

  • 기존 코드에 대한 이해 부족
  • 과도한 추상화는 가독성 ↓

Keep It Simple, Stupid

  • 작은 문제에 복잡한 디자인 패턴 남용
  • 파악 어렵게 함

You Aren't Gonna Need It

  • 초반에 지레짐작하여 구현부터 시작하면 안됨

디자인 패턴(GoF)

생성

  • Abstract Factory: 서로 관련된 객체들의 집합을 구체 클래스 없이 생성하는 인터페이스 제공
  • Builder: 복잡한 객체를 생성 과정과 표현을 분리하여 단계적으로 생성
  • Factory Method: 객체 생성을 서브클래스에 위임하여 어떤 객체를 만들지 결정
  • Prototype: 기존 객체를 복사 해서 새로운 객체 생성
  • Singleton: 클래스의 인스턴스를 하나만 생성하고 전역 접근 제공

구조

  • Adapter: 호환되지 않는 인터페이스를 변환하여 함께 사용 가능하게 함
  • Bridge: 추상화와 구현을 분리하여 독립적으로 확장 가능
  • Composite: 객체를 트리 구조로 구성하여 단일 객체와 복합 객체를 동일하게 처리
  • Decorator: 객체에 동적으로 기능을 추가 (상속 대신 사용)
  • Facade: 복잡한 서브시스템을 단순한 인터페이스로 제공
  • Flyweight:공유를 통해 메모리 사용 최소화 (많은 객체를 효율적으로 관리)
  • Proxy: 실제 객체에 대한 대리자 역할을 하며 접근 제어

행위

  • Chain of Responsibility: 요청을 여러 객체가 순차적으로 처리할 수 있게 연결
  • Command: 요청을 객체로 캡슐화하여 실행, 취소, 재사용 가능
  • Interpreter: 문법 규칙을 클래스로 표현하여 언어 해석기 구현
  • Iterator: 컬렉션의 내부 구조를 노출하지 않고 순차 접근 제공
  • Mediator: 객체 간 복잡한 상호작용을 중재자 객체로 집중 관리
  • Memento: 객체의 상태를 저장했다가 이전 상태로 복원
  • Observer: 객체 상태 변화 시 의존 객체들에게 자동 알림
  • State: 객체의 상태에 따라 행위를 변경 (조건문 제거)
  • Strategy: 알고리즘을 캡슐화하여 교체 가능
  • Template Method: 알고리즘의 뼈대는 정의하고 세부 단계는 서브클래스에서 구현

면접때 더 궁금한거 없냐고 할 때 할만한 질문

  • 회사 내에서 디자인패턴을 중요시 합니까 등등
profile
iOS 개발자가 되기 위한 스터디룸/스터디의 레퍼런스는 모두 kxcoding

0개의 댓글