Share
Sign In
Lighthouse Dev
Python의 Decorator
김원준
👍🏻
1
😀
1
0. 들어가며
이번 시간에는, 파이썬의 데코레이터에 대해서 발표해보도록 하겠다.
1. Decorator 란?
파이썬을 사용하다보면, 함수 혹은 메서드 위에 “@” 골뱅이가 붙은 특이한 이름을 본 적이 있을 것이다.
이러한 특이한 문법을 decorator라고 하는데, 영어 사전에서 decorator는 “장식자”이라는 뜻을 가지고 있다.
파이썬의 decorator 역시 동일한 의미로 사용된다. 어떤 함수가 있을 때, 해당 함수를 직접 수정하지 않고, 함수에 기능을 추가 /변경 / 확장 하고자 할 때 decorator를 사용한다.
decorator는 함수를 인자로 받고, 또 다른 함수를 반환하는 고차함수 이다.
💬
고차함수 ?

함수를 인자로 받아서, 함수를 반환하는 함수
파이썬에서 함수는 일급 객체로 취급되기 때문에 가능하다.

일급객체 ?
→ 아래에서 살펴보자.
그렇다면, 도대체 어떤 기능 이길래 추가 /변경 / 확장 모두 가능한 것일까?
지금부터 알아보자.
1.1. 데코레이터 기본 예시
def say_hello_to_lh_team(): print('안녕하세요. 좋은 아침입니다.') print('고생하셨습니다. 내일 뵐게요.') say_hello_to_lh_team() --- 안녕하세요. 좋은 아침입니다. 고생하셨습니다. 내일 뵐게요.
팀원들에게 아침 / 저녁 인사를 하는 함수가 있다.
def work_in_gfc(): print('10시에 스크럼 진행하시죠.') print('잠시 미팅 가능하실까요?') print('ESG 관련해서 질문이 있습니다 !') work_in_gfc() --- 10시에 스크럼 진행하시죠. 잠시 미팅 가능하실까요? ESG 관련해서 질문이 있습니다 !
또, GFC에서 업무를 진행하는 (자주 하곤 하는) 함수가 있다.
그렇다면, 아침 / 저녁 인사 사이에 업무에 관한 대화를 출력하고 싶다면 어떻게 해야할까 ??
def say_hello_to_lh_team(work_func): print('안녕하세요. 좋은 아침입니다.') work_func() print('고생하셨습니다. 내일 뵐게요.') def work_in_gfc(): print('10시에 스크럼 진행하시죠.') print('잠시 미팅 가능하실까요?') print('ESG 관련해서 질문이 있습니다 !') say_hello_to_lh_team(work_in_gfc) --- 안녕하세요. 좋은 아침입니다. 10시에 스크럼 진행하시죠. 잠시 미팅 가능하실까요? ESG 관련해서 질문이 있습니다 ! 고생하셨습니다. 내일 뵐게요.
위에서 말한 것 처럼, 파이썬은 함수를 함수의 인자로, 혹은 리턴값으로 지정할 수 있는 고차함수 이기에,
업무를 진행하는 함수를, 아침 / 저녁 인사를 하는 함수에 인자로 주면 쉽게 구현할 수 있다.
하지만, 팀원들에게 전하는 아침 / 저녁 인사는 매번 동일할 수 있지만, 업무는 매일 다르다. 그러면 매일매일 업무에 따라 work 함수를 정의 할텐데,
그때마다
say_hello_to_lh_team(work_in_gfc_monday)
say_hello_to_lh_team(work_in_gfc_tuesday)
say_hello_to_lh_team(work_in_gfc_wednesday)
say_hello_to_lh_team(work_in_gfc_thursday)
이렇게 표현해야한다.
하지만 데코레이터로 표현하자면,
def say_hello_to_lh_team(work_func): def print_hello(): print('안녕하세요. 좋은 아침입니다.') result = work_func() print('고생하셨습니다. 내일 뵐게요.') return print_hello @say_hello_to_lh_team def work_in_gfc_monday(): print('안녕하세요. 좋은 아침입니다.') ... print('고생하셨습니다. 내일 뵐게요.') ... @say_hello_to_lh_team def work_in_gfc_tuesday(): ... @say_hello_to_lh_team def work_in_gfc_wednesday(): ... work_in_gfc_monday() work_in_gfc_tuesday() work_in_gfc_wednesday()
데코레이터만 추가해준다면, 더이상 say_hello_to_lh_team(work_in_gfc_thursday) 이런식으로 함수를 감싸지 않아도 된다.
즉 데코레이터가 붙은 함수의 호출 Flow는
함수 호출 → 데코레이터 진입 → 데코레이터가 가미된(?) 함수 호출
이러한 흐름을 보이게 된다.
1.2. 장단점
1.2.1. 장점
코드의 재사용성을 높일 수 있다.
데코레이터를 사용하면, 코드의 일부분을 여러 함수에서 공유할 수 있다. 이로 인해 코드의 재사용성이 향상되며, 유지보수도 용이해진다.
코드의 가독성이 향상된다.
데코레이터를 사용하면, 중복 사용되는 부분의 코드가 데코레이터 부분으로 분리되기 때문에, 가독성이 향상된다.
관심사의 분리가 가능해진다.
예를들어, 권한 검증이나 로깅과 같은. 어떻게 보면 API의 핵심 기능과는 동떨어진 로직을 분리함으로써, 함수의 핵심 기능에만 집중할 수 있다.
1.2.2. 단점
코드의 복잡도를 높일 수 있다.
하지만 무분별한 데코레이터의 사용은 코드의 복잡도를 높인다. 다수의 데코레이터가 중첩되어 사용될 경우 코드의 해석이 어려워진다. 이는 버그 발생의 원인이 되기도 하며, 유지보수에 악영향을 미치게된다. 그렇기 때문에, 데코레이터는 필요한 경우에만 적절히 사용하는 것이 좋다.
1.3. 데코레이터 사용시 주의사항
1.3.1. 함수의 메타데이터 변경
데코레이터를 사용하면, 원래 함수의 메타데이터 (함수 이름, 주석 문자열 등등…)이 변경될 수 있다. 그러한 이유는, 데코레이터가 원래 함수를 감싸는 새로운 함수를 반환하기 때문이다. 이로 인해, 디버깅이나 문서화 도구에서 원래의 함수 이름이나 문서화(주석) 문자열을 제대로 인식하지 못할 수 있다.
궁금하다.😒  한번 코드를 통해 알아보자.
def my_decorator(func): def func_in_deco(): #데코레이터 내부 함수 return func() return func_in_deco @my_decorator def original_func(): #원본 함수 """함수 원본입니당.""" #함수 설명 print("Hello!") print(original_func.__name__) print(original_func.__doc__) --- func_in_deco None
original_func의 메타데이터를 호출 해본 결과, 데코레이터 내부 함수의 이름 / doc 이 사라진걸 볼 수 있다.
위에서 언급한 것 처럼, 이러한 상황은 예상치 못한 상황에서 에러를 발생 시킬 수 있다.
이러한 현상은 파이썬의 functools 모듈에 있는 @functools.wraps 데코레이터를 이용하여 해결할 수 있다.
@functools.wraps는 원래 함수의 메타데이터를 유지하면서, 데코레이터를 적용할 수 있도록 도와준다.
import functools def my_decorator(func): @functools.wraps(func) # 추가한 구문 def func_in_deco(): return func() return func_in_deco @my_decorator def original_func(): """함수 원본입니당.""" pass print(original_func.__name__) print(original_func.__doc__) --- original_func 함수 원본입니당.
이처럼 메타데이터가 유지되는 것을 볼 수 있다.
1.3.2. 실행 순서에 주의
여러 데코레이터를 사용할 때, 데코레이터가 적용되는 순서에 따라 최종 값이 변질될 수 있으니, 데코레이터를 올바른 순서로 적용해야한다.
2. 실용적인 Decorator 사용 방안
무분별한 데코레이터 사용은 유지보수 및 코드의 가독성에 악영향을 미칠 수 있다고 했다.
그렇다면, 실 업무 환경에서 데코레이터는 언제 사용하는게 좋을까?
2.1. 권한
프로덕트 내에서 권한에 따라 실행 여부가 결정되는 함수 (API도 함수이다.)가 존재하는 경우가 있다.
이때, 대부분의 함수(API)에서 권한을 검증하는 프로세스가 진행되기 때문에, 각 함수에 중복되는 코드가 존재할 수 밖에 없다. 이때 데코레이터를 사용하면, 효율적이다.
def auth_decorator(func): # 권한을 검증하는 공통 함수 def wrapper(user): if user.is_authenticated: return func(user) # delete_user 함수 실행 else: raise PermissionError("권한이 없습니다.") return wrapper @auth_decorator def delete_user(user, ...): # 프로덕트 내부 함수 pass
해당 함수와 같이, 유저를 삭제하는 꽤나 크리티컬한 함수에 권한 검증 프로세스가 붙어있지 않다면 운영에 큰 차질을 겪을 수 있다. (단순 url호출만으로도 유저가 삭제되니..)
그렇기에 대부분의 프로덕트에서는 권한 검증이 필수로 들어가있고, 이러한 검증 행위는 대부분 같은 함수를 사용하기에 데코레이터를 사용하곤한다.
2.2. 로깅
권한만큼 데코레이터를 이용해서 호출되곤 하는것이 바로 로깅이다. 로깅은 간혹 가벼이 여겨질 수는 있지만, 프로그램의 실행 흐름을 추적하거나 성능 문제를 진단하는데 도움이 될 수 있는 수단이다.
하지만, 이러한 로깅도 대부분의 로직/코드의 형태가 프로덕트 내에서 동일하기에, 데코레이터를 사용하여 표현하곤 한다.
def log_decorator(func): # 실행 시간 및 실행 함수를 로깅하는 decorator def wrapper(*args, **kwargs): # 여러곳에서 사용되기 때문에, 유연한 형태로 인자를 수령 start_time = time.time() end_time = time.time() logging.info(f'{func.__name__} / 실행 시각 : {start_time} 실행 시간: {end_time - start_time} 초') # logging 코드 추가 # 추가로 필요로하는 값을 유연하게 추가. return func() return wrapper @log_decorator def my_func(): pass
2.3. API Router !!
실용적인 방안이라고 하기엔 조금 뭐하지만, FastAPI와 Flask에서 api를 정의할 때 사용하는 (url과 method를 적곤하는) Router역시 데코레이터다.
모든 Rest API에는 필수로 경로(Path)와 메서드(Method)가 명시되어야 한다.
또, 개발자들 끼리 사전에 약속한 프로덕트 Rule (tag를 붙인다든가, response_model을 명시한다든가..)은 거의 모든 API에 적용되기 때문에, 코드의 중복이 발생할 가능성이 크다. 그렇기 때문에, API 내부에서 Router 데코레이터는 개발자에게 편리함을 제공함과 동시에, 유지보수 및 코드의 가독성에도 큰 도움을 준다.
즉, 데코레이터는 반복되는 (코드의 중복 여지가 다분한) 로직에서, 또 비교적 간단한 로직에서 사용되는것이 좋다.
3. Decorator 원리
3.1. Object
파이썬에서 가장 기본이 되는 형(Type)은 객체(Object)라고 볼 수 있다.
이는, 숫자도 문자도 심지어 함수도 모두 객체에서 파생되는 데이터 형이라는 말이 된다.
이는 정말 간단하게도, isinstance를 이용하여 가시적으로 확인할 수 있다.
print(isinstance(1, object)) print(isinstance('str', object)) print(isinstance(original_func, object)) --- True True True
즉, 모든 파이썬의 기본 데이터는 object이며, 다시말해 파이썬은 object를 통해 작동한다. 라고 생각하면 된다.
💬
중간 save point

🤔 파이썬의 모든 Type은 Object이다. (Object를 상속받아 이뤄졌구나.)
🤔 함수 역시 Object 구나
3.2. 일급객체(First-Class Object) / 일급함수(First-Class Function)
일급객체? 영어 단어에서도 볼 수 있듯이, 한우로치면 투쁠한우처럼 보인다.
wikipedia에서는 일급객체를
→ 다른 객체들에 일반적으로 적용 가능한 연산을 모두 지원하는 객체
라고 정의한다.
여기서 일반적으로 적용 가능한 연산 이란, 데이터를 할당하거나 반환하거나 전달하는 것을 의미한다.
즉, 변수나 데이터 구조에 할당이 가능하며, 리턴 값으로 반환할 수 있거나, 파라미터로 전달할 수 있다면, 그 객체는 일급객체 이다.
💬
일급객체 조건

1. 변수 혹은 데이터 구조 안에 담을 수 있다.
2. 파라미터로 전달할 수 있다.
3. Return 값으로 사용할 수 있다.
그럼 의문이 생긴다. 그럼 평범한 정수, 문자열도 일급 객체인가?
→ 맞다. 위의 3가지 조건을 모두 만족하면서 동시에 객체이기 때문에 일급객체가 맞다.
그렇다면, 일급함수 (First-Class Function)는 무엇일까?
너무 간단하다. 일급객체의 조건을 만족하는 함수가 일급함수이다.
근데 위에서, 함수는 객체라고 했다.
💬
아! 함수 역시 일급객체구나!

즉, 파이썬에서는 함수 마저도 int, str, float 등과 같은 기본적인 변수들 처럼 일급객체로 취급한다.
3.3. 결론
데코레이터의 형태를 리마인드 하기 위해, 위의 코드를 다시 보고오자.
“””
변수안에 함수를 담았고
함수를 파라미터로 받아서
리턴값으로 함수를 리턴한다.
“””
즉 데코레이터는, 파이썬의 이러한 기본 원리를 바탕으로 이뤄진 문법이다.
1.
파이썬의 모든 타입은 객체를 기반으로 한다.
2.
특정한 조건을 만족하는 객체를 일급 객체로 한다.
3.
파이썬은 함수 역시 객체 취급을 한다.
4. 마무리
이번 시간에는, 파이썬의 데코레이터에 대해서 알아보는 시간을 가졌다.
다음 시간에는 최근 ESG 개발을 하면서 많이 애를 먹은 부분인 Python의 Meta Class 에 대해서 발표해보려고 한다.
Kp
Subscribe to 'kpmg-lighthouse'
Welcome to 'kpmg-lighthouse'!
By subscribing to my site, you'll be the first to receive notifications and emails about the latest updates, including new posts.
Join SlashPage and subscribe to 'kpmg-lighthouse'!
Subscribe
👍🏻
1
😀
1
Lighthouse
모바엑스텀(MobaXterm)과 소나큐브(SonarQube): 효율적인 개발 환경 구축을 위한 완벽한 조합
안녕하세요, 여러분! 오늘은 개발자와 IT 전문가에게 필수적인 두 가지 도구인 모바엑스텀(MobaXterm)과 소나큐브(SonarQube)에 대해 깊이 있게 다뤄보려 합니다. 이 두 도구는 각각의 강력한 기능을 통해 개발 및 코드 품질 관리에 큰 도움을 줍니다. 이제 각 도구의 사용법과 장점을 자세히 살펴보겠습니다. 모바엑스텀(MobaXterm) 모바엑스텀은 원격 컴퓨팅을 위한 올인원 솔루션으로, SSH, RDP, VNC 등 다양한 프로토콜을 지원합니다. 또한, X 서버와 탭 기반 터미널을 제공하여 여러 세션을 효율적으로 관리할 수 있습니다. 모바엑스텀의 주요 기능 다양한 프로토콜 지원: SSH, RDP, VNC, FTP, SFTP 등 다양한 프로토콜을 지원하여 원격 서버와의 연결이 매우 용이합니다. 탭 기반 터미널: 여러 터미널 세션을 하나의 창에서 관리할 수 있어 작업 효율이 높아집니다. X 서버 내장: 리눅스 GUI 애플리케이션을 윈도우 환경에서 실행할 수 있습니다. 플러그인 지원: 다양한 플러그인을 통해 기능을 확장할 수 있습니다. 파일 전송: 드래그 앤 드롭으로 파일을 쉽게 전송할 수 있습니다. 모바엑스텀 사용법 설치: MobaXterm 공식 웹사이트에서 최신 버전을 다운로드하고 설치합니다. 세션 생성: 프로그램을 실행하고 'Session' 버튼을 클릭합니다. 원하는 프로토콜(예: SSH)을 선택하고 연결할 서버 정보를 입력합니다. 탭 관리: 새로운 세션을 생성하면 탭이 추가됩니다. 여러 세션을 동시에 열어 작업할 수 있습니다. 파일 전송: 터미널 창에서 원격 서버와 로컬 시스템 간의 파일을 드래그 앤 드롭으로 쉽게 전송할 수 있습니다. 플러그인 설치: 필요에 따라 다양한 플러그인을 설치하여 기능을 확장할 수 있습니��. 소나큐브(SonarQube) 소나큐브는 코드 품질 관리 도구로, 코드의 버그, 취약점, 코드 스멜 등을 자동으로 분석하여 보고합니다. 이를 통해 코드의 품질을 향상시키고 유지보수를 용이하게 합니다. 소나큐브의 주요 기능 다양한 언어 지원: 자바, C#, 파이썬 등 다양한 프로그래밍 언어를 지원합니다. 자동 분석: 코드의 버그, 취약점, 코드 스멜 등을 자동으로 분석합니다. 품질 게이트: 코드 품질 기준을 설정하고, 이를 기준으로 빌드 통과 여부를 결정할 수 있습니다. 통합: Jenkins, Azure DevOps 등 다양한 CI/CD 도구와 통합할 수 있습니다. 대시보드: 코드 품질 상태를 시각적으로 확인할 수 있는 대시보드를 제공합니다.
Lighthouse
LAM 로깅 및 모니터링 시스템
Lighthouse에서 개발되는 모든 Product 모니터링 시스템을 갖춥니다. 모니터링이 필요한 부분은 잘 아시다 시피 시스템 영역 그리고 사용자 영역으로 구분될 수 있지요. 시스템 영역에서는 서버 상태, 데이터베이스 성능, 네트워크 트래픽, API 응답 시간 등을 실시간으로 모니터링하여 장애 발생 시 신속하게 대응할 수 있도록 합니다. 이를 통해 가용성, 신뢰성, 성능 등을 지속적으로 최적화하며, 문제 발생 시 그 원인을 빠르게 파악하고 해결할 수 있는 환경을 조성합니다. 또한 로그 분석 및 자동 알림 기능을 통해 예측 가능한 문제를 미리 식별하고 사전에 대응할 수 있도록 합니다. 사용자 영역에서는 사용자 행동 분석, 사용 패턴 추적, 인터페이스 반응 시간 등을 모니터링하여 사용자 경험(UX)을 극대화하는 데 중점을 둡니다. 이를 통해 사용자의 요구를 정확히 이해하고, 서비스 개선을 위한 데이터를 축적할 수 있습니다. 사용자의 피드백을 실시간으로 수집하고 분석하여, 즉각적인 조치와 더불어 장기적인 발전 계획에 반영합니다. 이와 같은 모니터링 시스템은 제품의 전체적인 품질 향상은 물론, 비즈니스 목표 달성에도 크게 기여할 것입니다. Kibana의 강력한 시각화 도구를 활용해, 이러한 데이터를 직관적이고 이해하기 쉬운 형태로 제공함으로써, 제품 개발 및 개선에 필요한 핵심 인사이트를 얻을 수 있습니다. 또한, 사용자 피드백을 자동으로 수집하고 분석하여, 제품에 대한 사용자의 반응을 실시간으로 파악하고 즉각적으로 대응할 수 있는 체계를 갖춥니다.
donggyun_woo
SQLAlchemy 알아보기
시작 하면서 최근 KRM ver2.0 프로젝트를 시작하면서 웹서버를 구현하기 위해 SQLAlchemy를 사용하면서 모델링을 했습니다. 작업을 하면서 SQLAlchemy에 대해 공부한 내용을 공유해 보겠습니다. SQLAlchemy? SQLAlchemy는 파이썬을 위한 SQL 툴킷 및 Object-Relational Mapping(ORM) 라이브러리로, 데이터베이스와의 상호작용을 보다 쉽고 직관적으로 할 수 있게 도와줍니다. SQLAlchemy는 데이터베이스 연결 관리, 트랜잭션 관리, 스키마 정의 및 관리 등 다양한 기능을 제공합니다. SQLAlchemy 구조 크게 Core와 ORM으로 나뉘어져 있습니다. Core (SQL Expression Language): SQLAlchemy의 Core는 SQL 표현 언어를 사용하여 데이터베이스 쿼리를 생성하고 실행하는 데 중점을 둡니다. SQLAlchemy Core는 SQL을 직접 작성하고 데이터베이스와 상호작용할 수 있는 저수준 인터페이스를 제공합니다. Engine 데이터베이스와의 연결을 관리하는 핵심 구성 요소입니다. Engine 객체는 데이터베이스와의 상호작용을 위한 연결 풀(Connection Pool) 및 데이터베이스 드라이버를 포함하여 SQLAlchemy의 다른 부분과의 통신을 조정 Engine의 주요 기능 데이터베이스 연결 설정: Engine은 데이터베이스 URL을 통해 데이터베이스 연결 정보를 설정합니다. 연결 풀 관리: Engine은 연결 풀을 관리하여 데이터베이스 연결의 효율성을 높이고 성능을 최적화합니다. 연결 풀은 데이터베이스 연결을 재사용하여 연결 생성 및 소멸에 따른 오버헤드를 줄입니다. 트랜잭션 관리:
👍🏻
1