함수 = 1번의 선언 + 여러 번의 호출로 코드를 재사용한다
1) 멀티프로세스(Multi-process)란?
하나의 프로그램을 여러 개의 “프로세스”로 나눠 동시에(또는 병렬로) 실행하는 방식
- 프로세스: 실행 중인 프로그램 1개(각각 독립된 메모리 공간을 가짐)
- 멀티프로세스는 보통
- 동시에 여러 작업 처리(성능/응답성 향상)
- 장애 격리(한 프로세스가 죽어도 다른 프로세스는 영향 적음)
를 위해 씁니다.
예시:
- 웹서버가 여러 요청을 동시에 처리하려고 요청마다 프로세스를 분리
- 데이터 처리 파이프라인에서 “수집 / 전처리 / 분석 / 저장”을 프로세스로 쪼개 병렬 처리
2) “개발 비용”은 왜 커질까?
개발 비용은 단순히 코딩 시간만이 아니라 보통 이런 것들이 합쳐져요.
- 요구사항 변경 대응 비용
- 디버깅/테스트/품질 보증 비용
- 유지보수 비용(운영 중 장애, 기능 추가)
- 인수인계/문서화 비용
- 일정 지연으로 인한 기회비용
그래서 소프트웨어 공학은 “코드 잘 짜기”를 넘어서
비용이 커지는 구조를 미리 설계로 막는 학문
3) 개발 비용 절감 → 재사용 → 모듈화가 필요한 이유
재사용을 하려면 코드가 떼어서 다시 붙일 수 있는 형태여야 합니다.
그걸 가능하게 만드는 게 모듈화예요.
모듈화 정의
- 독립적으로 쪼개서 다룰 수 있도록 분리하는 것
- 각 모듈은 “자기 책임”이 명확하고
- 밖에서는 “정해진 인터페이스(사용법)”로만 접근하게 만들기
소프트웨어 공학 = 전체적인 생명 주기 ( 발생 개발~ 폐기) 발생 하는 비용 줄이기 위한 방안
비용절감을 위한 효율적인 프로그래밍 방법론
개발 비용
개발 비용 절감 -> 코드를 재사용 ( 기간 압축 ) = 모듈화 필요
모듈화? 독립적으로 쪼개서 다룰 수 있게 해야 됨
어떻게 쪼갤까? 하나의 단위를 '함수'를 통해 기능(하나의 입력 -> 출력) 단위로 분리
함수 = 1번의 선언 + 여러 번의 호출로 코드를 재사용한다
연산 = 기능
x(입력)-> 기능(function) -> y(결과)
max = 0
#메모리 초기화
# 대입연산자 왜 필요? 값을 저장하기 위한 메모리 공간 확보하기 위해서
if x> y :
max = x
else:
max = y
else 문 없이 구현할 수 있는 방법
임의의 변수 하나를 max로 지정하고 시작
max = x
if x<y:
max = y
print(max)
def get_max(x,y): // c언어 계열
def_getMax(x,y) // Java 계열 -> 카멜 방법
#함수 정의 = 정의문
def getMax(a,b): #c계열 함수 정의
max = a
if b>max:
max = b
return max
##---main
x=10
y=20
##call
result = getMax(x,y) #함수호출
print("1.더 큰 값은: ", result)
x=30
y=15
#호출문
result = getMax(x,y)
print("2.더 큰 값은: ", result)
1. 파일의 종류와 형태
컴퓨터에서 다루는 파일은 크게 내용과 목적에 따라 구분할 수 있다.
① 코드 파일 / 실행 파일 (데이터 + 코드)
- 프로그램 코드와 실행에 필요한 정보가 함께 포함된 파일
- 대표적인 예:
- *.exe (Windows 실행 파일)
② 데이터 파일 – 텍스트 데이터
- 사람이 읽을 수 있는 문자 기반 데이터
- 예:
- *.txt
- *.csv
- *.log
③ 데이터 파일 – 멀티미디어(색상/이미지)
- 픽셀, 색상 정보 등 이진 데이터로 구성
- 예:
- *.bmp
- *.png
- *.jpg
2. 왜 파일 처리가 필요한가?
프로그램이 실행되면 모든 작업은 메모리(RAM) 위에서 이루어진다.
하지만 메모리는 휘발성이 있기 때문에 프로그램 종료 시 데이터가 사라진다.
그래서 프로그램은 다음과 같은 작업이 필요하다.
- 분석할 데이터 준비
- 이전 실행 결과 불러오기
- 대용량 데이터 관리
이때 사용하는 것이 파일이다.
3. 입력(Input)과 출력(Output)의 개념
입력(Input)
외부에 따로 관리되던 파일로부터 데이터를 메모리로 불러오는 작업
- 예:
- 파일 읽기
- 키보드 입력
- 센서 데이터 수신
출력(Output)
메모리에 있는 데이터를 장치나 파일로 내보내는 작업
- 예:
- 화면 출력
- 파일 저장
- 프린터 출력
CPU의 역할
CPU는 직접 데이터를 옮기지 않는다.
대신 **제어 신호(control signal)**를 보내 입출력 장치가 동작하도록 한다.
이 한 줄도 내부적으로는:
- CPU가 출력 장치에 “출력하라”는 제어 신호를 전달
- 장치가 메모리에 있는 데이터를 읽어 화면에 표시
라는 과정을 거친다.
4. I/O와 네트워크의 차이
I/O (입출력)
- 로컬 시스템 내부에서의 데이터 이동
- 예:
- 파일 읽기/쓰기
- 키보드, 모니터, 디스크
네트워크
- 로컬 시스템 밖에서 일어나는 데이터 이동
- 예:
- 서버 ↔ 클라이언트 통신
- 인터넷 데이터 송수신
5. 스트림(Stream)의 개념
스트림은 입출력을 이해하는 데 매우 중요한 개념이다.
스트림이란?
데이터가 한 방향으로만 흐르는 통로
- 단방향이다.
- 입력 스트림(Input Stream)
- 출력 스트림(Output Stream)
#stream 생성하는 함수 ( 경로를 필요로 함 )
f= open("text.txt", "r") #독점권 제공 => 다른 프로세스가 사용 불가
line = f.readline()
print (line)
f.close()
- open() : 파일과 프로그램 사이에 입력 스트림 생성
- readline() : 한 줄만 읽음 (개행 문자 \n 포함)
- close() : 파일 사용 종료 (자원 반환)
#while
f= open("text.txt", "r")
while True:
line = f.readline()
if not line:#파이썬에는 EOF가 없다 -> not line으로
break
print(line)
f.close()
- Python에는 EOF 상수/키워드가 없음
- 파일 끝에 도달하면
👉 readline() → "" (빈 문자열) 반환
if not line:
#For문
f= open("text.txt", "r")
for line in f:
print (line)
f.close()
- open() → 파일 객체(스트림) 생성
- 파일 객체 f는 이터러블(iterable)
- for line in f:
→ 내부적으로 다음과 같은 동작을 반복- 한 줄 읽기
- EOF 도달 시 자동 종료
- EOF 판단을 직접 하지 않아도 됨
➡ readline() + EOF 검사를 파이썬이 대신 처리
줄바꿈 뒤에 자동으로 들어가는 엔터 없애는 방법
print(line, end="")
- line 끝에 이미 \n 포함되었기 때문에 print()도 \n 추가됨 -> 줄 간격이 한 줄씩 더 벌어질 수 있음
-> end ="" 로 줄바꿈 방지
1️⃣ * 하나 (*args) — 위치 인자 (positional arguments)
def print_args(*args):
print(args)
의미
- 여러 개의 위치 인자를 받음
- 전달된 값들은 튜플(tuple) 로 묶임
호출 예시
print_args(1, 2, 3)
#출력 : (1, 2, 3)
핵심 요약
- *args → 값만 받는다
- 키워드 이름 없음
- 결과 타입: tuple
2️⃣ ** 두 개 (**args) — 키워드 인자 (keyword arguments)
def print_args(**args):
print(args)
의미
- 여러 개의 키워드 인자를 받음
- 전달된 이름=값 쌍이 딕셔너리(dict) 로 묶임
호출 예시
print_args(name="Alice", age=20)
#출력 {'name': 'Alice', 'age': 20}
핵심 요약
- **args → 이름=값 쌍을 받는다
- 결과 타입: dict
1️⃣ 함수 정의: 여러 값 반환의 실체
def add_and_mul(a, b):
return (a+b, a*b)
# 출력 (a+b, a*b)
중요한 사실
- Python 함수는 값을 하나만 반환
- 여기서는 튜플(tuple) 하나를 반환
2️⃣ 튜플 언패킹으로 받기 (가장 권장)
(r1, r2) = add_and_mul(3, 4)
print(r1)
print(r2)
#출력 7 12
동작
- 반환된 튜플 (7, 12)을
- r1, r2에 순서대로 분해(언패킹)
3️⃣ 구조분해 할당 - 하나의 변수로 받기
result = add_and_mul(3, 4)
result
#출력 (7,12)
결과
- result의 타입: tuple
4️⃣ 인덱스로 접근 (튜플 성질 사용)
result = add_and_mul(3, 4)
rs1 = result[0]
rs2 = result[1]
print(rs1, rs2)
출력 : 7 12
출력
- 튜플은 순서 있음
- 인덱스 접근 가능
람다 함수 (익명 함수)
(lambda x, y: x + y)(10, 20)
구성
- 이름이 없는 익명 함수
- 반드시 하나의 표현식만 가능
- return 키워드 사용 불가
- 표현식의 결과가 자동으로 반환됨
- 한줄짜리 함수 - > 쓰고 버릴 때 사용
#문제 1

아~ 구조가 2차구낭 !
#1번
students = [
["홍길동", 78, 79, 85, 88],
["김길동", 88, 67, 59, 90],
["이길동", 83, 77, 82, 81]
]
#총점 계산하는 함수
def calc_total(students):
return sum(students[1:])
# 학생 정보를 출력하는 함수
def print_student(name):
for s in students:
if s[0] == name:
stuInfo = {
"이름": s[0],
"국어": s[1],
"수학": s[2],
"영어": s[3],
"과학": s[4],
"총점": calc_total(s)
}
return stuInfo
print_student("홍길동")
#문제2

#문제 2
customers=[
{"고객명": "홍길동", "고객번호": 101, "상품A" : 79, "상품B": 85, "상품C" : 88},
{"고객명": "김길동", "고객번호": 102, "상품A" : 67, "상품B": 59, "상품C" : 90},
{"고객명": "이길동", "고객번호": 103, "상품A" : 77, "상품B": 82, "상품C" : 81},
{"고객명": "박길동", "고객번호": 104, "상품A" : 90, "상품B": 88, "상품C" : 92}
]
#문제2-1 총구매 금액 계산 -> 딕셔너리에 추가
def add_calc_total(customers):
for cost in customers:
total = cost["상품A"] + cost["상품B"] + cost["상품C"]
cost["총구매금액"] = total
add_calc_total(customers)
print(customers)
#문제 2-2 총구매 금액의 평균
def avg_calc_total(customers):
add_calc_total(customers)
totalTotal = 0
for cost in customers:
totalTotal += cost["총구매금액"]
avgCost = totalTotal / 4
return avgCost
print(avg_calc_total(customers))
#문제3 총 구매 금액이 가장 높은 고객의 이름 반환
def high_total_cost(customers):
highTotalCost = customers[0]["총구매금액"]
highTotalName = customers[0]["고객명"]
for cost in customers:
if cost["총구매금액"] > highTotalCost:
highTotalCost = cost["총구매금액"]
highTotalName = cost["고객명"]
return highTotalName
high_total_cost(customers)
'LG DX DATA SCHOOL' 카테고리의 다른 글
| 12/30 기술 통계학 + R (0) | 2025.12.30 |
|---|---|
| 12/29 통계 기반 데이터 분석 (넘파이/ 판다스) (0) | 2025.12.29 |
| 12/24 상속, 정규 표현식 (1) | 2025.12.24 |
| 12/23 객체 지향 복습 / 판다스 (Pandas) (0) | 2025.12.23 |
| 12/22 객체 지향 (0) | 2025.12.22 |