Rookies 6일차: Python 개념 학습 4
☀️공지 사항☀️ 해당 게시글은 SK 쉴더스 루키즈, 생성형AI 활용 사이버보안 전문인력 양성과정 을 수업을 듣고 정리한 글입니다. 자세한 교육 정보는 SK 쉴더스 홈페이지 를 확인해주세요.
학습 내용 요약 (25/10/30)
1. 파이썬 함수의 기본 및 심화 활용
1.1. 함수의 정의 및 장점
파이썬의 함수(Function)는 객체 지향 프로그래밍(OOP)에서 메서드(Method)라고도 불리는 것으로, 일련의 실행 코드를 묶어 재사용 가능하게 만든 단위이다. 함수를 사용하면 다음과 같은 장점을 얻을 수 있다:
- 코드 재사용이 가능하여 개발 효율성을 높인다.
- 가독성이 향상되어 코드 이해가 쉬워진다.
- 유지보수 및 디버깅이 용이해진다.
- 코드를 논리적으로 나누어 모듈화할 수 있다 (예:
import utils).
1.2. 인자 전달 방식
함수 호출 시 인자를 전달하는 방식은 위치 인자(Positional Argument)와 키워드 인자(Keyword Argument)로 나뉜다.
- 위치 인자는 함수 정의 시의 매개변수 순서대로 값을 전달하는 방식이다.
- 키워드 인자는
매개변수명=값형태로 이름을 명시하여 순서에 관계없이 값을 전달하는 방식이다. - 함수 정의 시
def greet(name='guest'):와 같이 기본값 매개변수(Default Parameter)를 설정할 수 있으며, 이 경우 호출 시 인자값이 생략되면 기본값이 사용된다. - 가변인자는
*args또는**args로 나뉘는데,*args는** 튜플 형태의 인자,**args는 **dict 형태의 키워드 인자가 들어간다.
코드 예시
def userAdd(a, b):
return a**b
======================================================================
# 위치 인자(Positional Argument) 예시
result = userAdd(2, 3)
print('type - ', type(result))
print('result - ', result)
======================================================================
# 키워드 인자(Keyword Argument) 예시
result = userAdd(b=3, a=2)
print('type - ', type(result))
print('result - ', result)
======================================================================
# default parameter
def greet(name='guest'): # 입력값이 들어오지 않으면 기본값인 'guest'가 입력된다.
[ . . . ]
======================================================================
가변인자 예시
# *args, **kwargs 섞은거
def variableLenArgsMix(subject, *args, **kwargs) : # 순서도 신경써야된다. 첫번째에 가변인자를 넣으면 에러뜨는 거 같음
print('subject - ', subject)
print('args - ', args)
print('kwargs - ', kwargs)
variableLenArgsMix("사용자 정보", "임섭순", "섭섭해", "힝구리퐁퐁", "너무해", a=1, b=2)
=========================================================================
# 출력 예시
subject - 사용자 정보
args - ('임섭순', '섭섭해', '힝구리퐁퐁', '너무해')
kwargs - {'a': 1, 'b': 2}
1.3. 람다 함수 및 고차 함수 활용
람다 함수(Lambda Function)는 이름이 없는 익명 함수이며, lambda [매개 변수] : [실행문] 형태로 간단한 표현식을 한 줄로 작성할 때 유용하다. return 없이 결과값을 바로 반환한다.
map(function, iterable): 반복 가능한 객체에 람다 함수를 적용하여 새로운 객체를 생성하는 데 사용된다.filter(function, iterable): 람다 함수의 결과가 참(True)인 요소들만 필터링하여 새로운 객체를 생성하는 데 사용된다.sorted()함수에서key매개변수로 람다 함수를 사용하여 정렬 기준을 정의할 수 있다. 예를 들어, 문자열 리스트를 길이 기준으로 정렬할 수 있다.
코드 예시
lst = [1,2,3,4,5,6,7,8]
print('case01 - list comprehension')
result = [ data ** 2 for data in lst ]
print(result)
print('\n---\n')
print('case02 - lambda')
print('map function') # 열거형 타입(반복 가능한 요소에 대해서 특정 함수를 적용하고 그 결과를 map 객체로 반환함)
print('map(function, iterable)') # map 함수는 매개변수가 2개인데, 앞에는 함수, 뒤에는 열거형 객체를 넣어준다.
# double = lambda data : data ** 2 -> 오류 발생
double=list(map(lambda data : data ** 2, lst))
print(double)
print('\n---\n')
print('case03 - 람다 + 삼항연산 활용')
print('filter(function, iterable)')
even=list(filter(lambda data : data % 2 == 0, lst))
print(even)
출력 예시
case01 - list comprehension
[1, 4, 9, 16, 25, 36, 49, 64]
---
case02 - lambda
map function
map(function, iterable)
[1, 4, 9, 16, 25, 36, 49, 64]
---
case03 - 람다 + 삼항연산 활용
filter(function, iterable)
[2, 4, 6, 8]
2. 파이썬 스코프 및 함수 특성 (LEGB, Closure)
2.1. 변수의 스코프 규칙 (LEGB)
파이썬에서 변수 이름을 찾는 규칙은 LEGB 순서를 따른다.
- L (Local): 현재 작업 중인 함수 내부의 지역 스코프이다.
- E (Enclosing): 중첩 함수가 있을 때, 바깥쪽(둘러싸는) 함수의 지역 스코프이다.
- G (Global): 모듈(파일)의 최상단 전역 스코프이다.
- B (Built-in): 파이썬 내장 이름들의 스코프이다 (예:
print(),len()).
2.2. global 및 nonlocal 키워드
global: 함수 내부에서 전역(Global) 스코프의 변수 값을 읽고 수정할 수 있도록 지정하는 키워드이다.nonlocal: 중첩 함수 구조에서, 안쪽 함수가 자신을 둘러싸고 있는 바깥쪽 함수(Enclosing Scope)의 변수 값을 수정할 수 있도록 지정하는 키워드이다.
2.3. 클로저(Closure)와 보안 관점
클로저는 중첩 함수의 한 형태로, 함수가 종료된 후에도 외부 함수(Enclosing)의 변수 값을 기억하고 참조하는 것을 핵심 특징으로 한다.
- 보안 관점: 클로저는 전역 변수를 사용하지 않고도 함수 내부에서 상태를 유지할 수 있게 한다. 이는 상태를 외부에 노출하지 않고 함수 호출 간에 안전하게 캡슐화하고 관리할 수 있게 하여, 보안 설계 측면에서 이점을 제공한다. 카운터 함수 예시(
counter())가 대표적이다. - 데코레이터는 이러한 클로저를 기반으로 구현된다.
# 전역 변수를 사용하지 않는 상태를 유지하는 코드 개선 - 클로저 이용
def counter():
count = 0
def increase():
nonlocal count
count += 1
return count
return increase
cnt = counter()
print(cnt())
print(cnt())
print(cnt())
======================================================================
# 출력 예시
1
2
3
3. 함수 장식자 (Decorator)
데코레이터는 함수를 감싸서 기존 함수의 코드 수정 없이 기능(공통 로직)을 수정하거나 추가시켜주는 디자인 패턴이다. 이는 클로저의 원리를 활용하여 구현된다.
- 현업 활용 예시: 데코레이터는 로깅(Logging), 권한 체크(Permission Check), 함수 실행 시간 측정(Timer) 등의 공통 로직을 여러 함수에 일괄적으로 적용하는 데 자주 사용된다.
- 보안 활용: 웹 프레임워크에서 특정 함수(
@loginRequired) 위에 데코레이터를 붙여 사용자 인증이나 접근 권한을 손쉽게 검사하는 데 핵심적으로 사용된다.
4. 보안 관점의 함수 설계 및 코드 개선
4.1. XSS 취약점 방어: URL 인코딩 및 유효성 검증
사용자로부터 입력받은 데이터를 처리하여 URL을 생성하는 함수는 크로스 사이트 스크립팅(XSS) 공격에 취약할 수 있다. 악성 스크립트가 포함된 입력값이 URL 문자열에 그대로 포함될 경우, 해당 스크립트가 실행될 위험이 있다.
이러한 취약점을 방어하기 위해 다음과 같은 개선 방법이 적용되었다:
-
개선 1: URL 인코딩 적용 (
urllib.parse.quote)- 파이썬의
urllib.parse모듈의quote()함수를 사용하여 입력 문자열 내의 특수문자를 안전하게 인코딩한다. <는%3C,>는%3E등으로 변환되어 브라우저가 스크립트로 해석하지 못하게 막는다.
from urllib.parse import quote def safeMakeUrl(listIn:list) -> list: # quote()를 사용하여 특수문자를 인코딩하여 XSS 공격을 방지한다. return list(map(lambda x:'www.'+quote(x)+'.com', listIn)) - 파이썬의
-
개선 2: 입력 타입 유효성 검증
- 함수의 안정성을 위해 입력값의 타입이 예상한
list와 그 내부 요소가str인지 검증하는 로직을 추가한다. isinstance(lst, list)로 전체 타입 검사를 수행하고,all(isinstance(name, str) for name in lst)로 리스트 내부 요소 전체의 타입을 검사하여 예상치 못한 타입 입력(예: 숫자10)으로 인한 오류를 방지한다.
def safeMakeUrl(lst:list) -> list: if not isinstance(lst, list): raise TypeError("입력은 리스트 타입으로 전달 부탁드립니다.") if not all(isinstance(name, str) for name in lst): raise ValueError("요소의 타입은 문자열로 전달 부탁드립니다.") # 검증 통과 시 안전하게 URL 인코딩 후 리턴한다. return list(map(lambda x:'www.'+quote(x)+'.com', lst)) - 함수의 안정성을 위해 입력값의 타입이 예상한
4.2. API 요청 생성 시 매개변수 화이트리스트 적용
**kwargs를 이용하여 가변적인 키워드 인자를 받는 API 요청 생성 함수에서, 보안 강화 및 매개변수 남용 방지를 위해 화이트리스트(whiteList)를 적용하여 허용된 매개변수만 사용하는 것이 중요하다.
- 보안 원칙: API 요청 시 필요 없는 매개변수를 차단하여 불필요한 데이터 전송을 최소화하고, 잠재적인 민감 정보나 공격 매개변수가 API에 전달되는 것을 막는 방어 기법이다.
makeApiRequest함수는whiteList에 정의된 키('q','page','lang')만 필터링하여 안전한safeParams를 생성하고, 이를 기반으로 URL을 인코딩한다.
from urllib.parse import urlencode
def makeApiRequest(endpoint, **params):
whiteList = {'q', 'page', 'lang'} # 허용된 매개변수 화이트리스트
# 화이트리스트에 있는 키만 필터링하여 안전한 매개변수(safeParams)를 생성한다.
safeParams = { key:value for key, value in params.items() if key in whiteList }
queryString = urlencode(safeParams)
if queryString:
url = f"{endpoint}?{queryString}"
else:
url = endpoint
return url
공부 후기
오늘 파이썬 함수의 심화 개념과 보안 적용 기법에 대해 매우 깊이 있게 공부했다. 오늘은 특별히 앞선 날보다 더 어려웠다ㅠㅠ..(끝나고 동기들한테 물어보니 전공자들도 어려웠다고..)
하지만 보안 관점에서 개선할만한 기법들을 많이 배운 것 같아서 뿌듯한 하루였다! 정리한 내용을 계속 반복해서 보면서 익숙해져야겠다..! 내일도 화이팅!
댓글 남기기