추상 클래스
1. OOP(Object-Oriented Programming, 객체 지향 프로그래밍)
프로그래밍을 단순히 '데이터의 처리 과정'으로 보지 않고, 독립적인 '객체(Object)'들의 상호작용으로 구성하는 설계 철학'
- 객체 지향의 4대 핵심 개념
- 캡슐화 (Encapsulation): 객체의 내부 데이터와 메서드를 하나로 묶고, 외부에서 함부로 접근하지 못하도록 보호(정보 은닉)하는 것입니다. (예: 자동차의 복잡한 엔진 내부를 뜯어보지 않아도 운전대만으로 조작 가능)
- 상속 (Inheritance): 부모 클래스의 기능을 자식 클래스가 그대로 물려받아 사용하는 것입니다. 중복 코드를 줄이고 기능 확장이 쉬워집니다.
- 다형성 (Polymorphism): 같은 이름의 메서드라도 객체마다 다르게 동작하는 능력입니다. (예: '말하기'라는 명령을 내렸을 때, 사람은 '안녕', 개는 '멍멍'이라고 말하는 것)
- 추상화 (Abstraction): 복잡한 내부 구현은 숨기고, 핵심적인 기능만 인터페이스로 노출하는 것입니다.
2. 추상 클래스 정의하기
파이썬에서 추상 클래스를 만들려면 내장 모듈인 abc에서 ABC 클래스와 @abstractmethod 데코레이터를 가져와야 합니다.
- ABC: 추상 클래스를 만들기 위한 부모 클래스
- @abstractmethod: 자식 클래스가 반드시 오버라이딩(재정의)해야 하는 메서드
from abc import ABC, abstractmethod
class Animal(ABC): # ABC를 상속받아 추상 클래스 설정
@abstractmethod
def speak(self):
# 본문은 보통 비워두거나 pass를 사용합니다.
pass
3. 인스턴스 생성 불가
추상 클래스는 미완성된 설계도이므로, 이를 직접 호출하여 객체(인스턴스)를 만들 수 없습니다. 시도할 경우 TypeError가 발생합니다.
# 에러 발생!
# my_animal = Animal()
3. 메서드 구현 강제
추상 클래스를 상속받은 자식 클래스는 부모의 모든 추상 메서드를 구현해야만 객체를 생성할 수 있습니다.
class Dog(Animal):
def speak(self):
return "멍멍!"
class Cat(Animal):
def speak(self):
return "야옹~"
dog = Dog()
print(dog.speak()) # 출력: 멍멍!
참고: 만약 Cat 클래스에서 speak 메서드를 정의하지 않는다면, Cat 역시 인스턴스를 만들 수 없는 상태가 됩니다.
4. 추상 클래스를 사용하는 이유
추상 클래스는 협업이나 대규모 프로젝트에서 인터페이스 통일을 위해 사용합니다.
- 규격화: 여러 개발자가 참여할 때, "동물 클래스를 상속받으면 무조건 speak 메서드는 만들어야 한다"는 규칙을 코드 수준에서 강제합니다.
- 유지보수: 부모 클래스 타입으로 여러 자식 객체를 다룰 수 있어 코드가 유연해집니다 (다형성).
요약 코드 예시
from abc import ABC, abstractmethod
# 1. 추상 클래스 (설계도)
class Shape(ABC):
@abstractmethod
def area(self):
pass
# 2. 자식 클래스 (구체적인 구현)
class Circle(Shape):
def __init__(self, radius):
self.radius = radius
def area(self):
return 3.14 * self.radius ** 2
class Square(Shape):
def __init__(self, side):
self.side = side
def area(self):
return self.side * self.side
# 사용 예시
shapes = [Circle(5), Square(4)]
for s in shapes:
print(f"넓이: {s.area()}")
lambda
1. 람다 함수의 기본 문법
일반적인 함수 정의 방식인 def와 달리, lambda 키워드를 사용합니다.
# 기본 형태
# lambda 인자 : 표현식
# 예시: 두 수를 더하는 함수
add = lambda x, y: x + y
print(add(5, 3)) # 출력: 8
- 인자: 함수에 전달할 매개변수들 (여러 개 가능)
- 표현식: 인자를 받아 계산할 식 (결과가 자동으로 반환됨)
2. 일반 함수(def) vs 람다 함수
두 방식의 차이를 비교해 보면 람다의 간결함을 알 수 있습니다.
| 구분 | 일반 함수 (def) | 람다 함수 (lambda) |
| 이름 | 함수명이 반드시 존재 | 이름이 없음 (익명) |
| 길이 | 여러 줄의 로직 가능 | 오직 한 줄(표현식)만 가능 |
| 반환 | return 키워드 사용 | return 없이 결과값 자동 반환 |
3. 실무에서 람다가 활용되는 경우
람다는 보통 함수를 인자로 받는 고차 함수(map, filter, sorted 등)와 결합할 때 빛을 발합니다.
① 리스트 정렬 시 (sorted)
데이터의 특정 기준(Key)을 정하고 싶을 때 람다를 사용합니다
# (이름, 점수) 튜플 리스트
students = [("A", 80), ("B", 95), ("C", 70)]
# 점수(x[1])를 기준으로 정렬
sorted_students = sorted(students, key=lambda x: x[1]) #정렬할 값을 x[1]로 쓰겠다는 의미
print(sorted_students) # 출력: [('C', 70), ('A', 80), ('B', 95)]
② 데이터 변환 (map)
리스트의 모든 요소에 동일한 규칙을 적용할 때 유용합니다.
nums = [1, 2, 3, 4, 5]
# 모든 요소에 10을 더함
plus_ten = list(map(lambda x: x + 10, nums))
print(plus_ten) # 출력: [11, 12, 13, 14, 15]
③ 조건부 필터링 (filter)
조건에 맞는 데이터만 걸러낼 때 사용합니다.
nums = [1, 2, 3, 4, 5, 6]
# 짝수만 추출
evens = list(filter(lambda x: x % 2 == 0, nums))
print(evens) # 출력: [2, 4, 6]
4. 람다 함수 사용 시 주의사항
- 가독성: 로직이 조금이라도 복잡해지면(예: 중첩 조건문 등) 람다보다는 일반 함수(def)를 쓰는 것이 코드 읽기에 훨씬 좋습니다.
- 재사용성: 한 번만 쓰고 버릴 로직에는 람다가 좋지만, 여러 곳에서 반복해서 사용한다면 이름을 가진 함수로 정의하는 것이 유지보수에 유리합니다.
Flask
1. Flask란: Python 언어로 웹 애플리케이션을 만들 수 있게 도와주는 아주 간단하고 가벼운 웹 프레임워크
- HTML 페이지를 보여주고,
- 데이터를 전송하고 받아들이며,
- 사용자 요청에 응답하고,
- 나아가 데이터베이스, 사용자 인증, API 개발 등 다양한 기능까지 확장할 수 있습니다.
2. Flask 설치 방법(가상 환경 생성 및 활성화 권장)
pip install Flask #터미널에서
3. Flask 기본 구조
- 애플리케이션 객체 생성
- 모든 Flask 프로젝트는 Flask 클래스의 인스턴스를 생성하는 것에서 시작
- app 객체는 애플리케이션의 중심이 되며, 라우팅, 설정 관리, 요청 처리 등을 담당합니다. __name__은 Flask가 모듈이나 패키지의 경로를 찾는 데 사용
from flask import Flask
app = Flask(__name__)
- 라우팅(Routing)
- 사용자가 브라우저 주소창에 특정 경로를 입력했을 때, 어떤 함수가 실행될지 결정하는 과정
- @app.route 데코레이터를 사용하여 URL 경로와 파이썬 함수를 1:1로 매핑
@app.route('/')
def index():
return "메인 페이지입니다."
- 애플리케이션 실행
- if __name__ == '__main__': 블록을 사용하여, 이 파일을 직접 실행할 때만 서버가 켜지도록 설정
- debug=True 옵션은 에러 발생 시 상세한 디버그 화면을 보여주기 때문에 개발할 때 매우 유용
if __name__ == '__main__':
# 0.0.0.0은 외부 접속 허용, port는 원하는 번호로 지정 가능
app.run(host='0.0.0.0', port=5000, debug=True)
- 요청(Request) 처리 및 응답(Response)
- request 객체는 클라이언트(보통 웹 브라우저)가 서버로 보낸 모든 정보가 담긴 바구니
- Request 객체의 주요 속성
| 속성 | 설명 | 예시 상황 |
| request.args | URL 쿼리 파라미터 | ?name=kim&age=20 |
| request.form | POST 방식으로 보낸 폼 데이터 | 로그인 입력창 데이터 |
| request.json | JSON 형식의 데이터 | API 요청 시 |
| request.method | 요청 방식 (GET, POST 등) | 요청의 종류 확인 |
| request.files | 업로드된 파일 정보 | 이미지/문서 업로드 |
| request.headers | HTTP 헤더 정보 | 브라우저 정보, 인증 토큰 |
from flask import Flask, request
app = Flask(__name__)
@app.route('/submit', methods=['GET', 'POST'])
def submit():
# 1. GET 방식: URL의 ?key=value 형태 추출
# 예: /submit?name=홍길동
name = request.args.get('name', '이름없음')
# 2. POST 방식: 폼(Form) 데이터 추출
# 예: <input name="age">
age = request.form.get('age', 0)
# 3. 요청 방식 확인
method = request.method
return f"이름: {name}, 나이: {age}, 방식: {method}"
* HTTP 메서드(GET, POST, PUT, DELETE)
| 메서드 | 의미 | CRUD | 역할 |
| GET | 가져오기 | Read | 서버의 데이터를 단순히 조회할 때 사용 |
| POST | 생성하기 | Create | 서버에 새로운 데이터를 보낼 때 사용 |
| PUT | 수정하기 | Update | 기존 데이터를 새로운 데이터로 전체 교체할 때 사용 |
| DELETE | 삭제하기 | Delete | 특정 데이터를 삭제할 때 사용 |
- 템플릿 (Templates) 과 정적 파일 (Static)
- HTML 파일에 파이썬 데이터를 넣어서 사용자에게 보여줍니다.
- render_template 함수를 사용하며,
- {{ 변수명 }}: 파이썬에서 전달받은 변수의 값을 출력할 때 사용
- {% 로직 %}: if문, for문 같은 제어문(로직)을 작성할 때 사용 (화면에 직접 출력되지 않음)
- 코드 예시
- flask.py
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def index():
# 파이썬 변수를 HTML로 전달
user_name = "개발자님"
return render_template('index.html', name=user_name)
if __name__ == '__main__':
app.run(debug=True)
- templates/index.html
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
</head>
<body>
<h1>안녕하세요, {{ name }}님!</h1>
<img src="{{ url_for('static', filename='images/logo.png') }}" alt="로고">
</body>
</html>
- static/css/style.css
/* 스타일은 서버의 로직과 관계없이 고정되어 있음 */
h1 {
color: blue;
font-family: sans-serif;
}
| 구분 | 템플릿 (Templates) | 스태틱 (Static) |
| 파일 형식 | .html | .css, .js, .png, .jpg 등 |
| 변화 가능성 | 서버 데이터에 따라 변함(동적) | 정해진 파일을 그대로 전달 (정적) |
| 처리 방식 | Jinja2 엔진이 렌더링 | 그대로 브라우저에 전송 |
| 주요 용도 | 웹 페이지 뼈대(구조) | 스타일링, 애니메이션, 이미지 |
4. 동적 경로 변수 (Dynamic Routing) / 쿼리 스트링 방식(/search?q=Flask)
- 동적 경로 변수: URL 경로의 일부분을 고정하지 않고, 사용자가 입력하는 값에 따라 유연하게 받아오는 기술
- / ( /user/홍길동 ): 리소스 경로를 정의, 매개변수 형태가 <isbn> 식일 때 리소스 경로에서는 값을 함수의 인자로 전달받아 처리함
- 문자형 관련 변환기 정리
변환기 설명 예시 URL <string> (기본값) /를 제외한 모든 문자열을 받습니다. /user/hong <path> /를 포함한 모든 경로를 문자열로 받습니다. (파일 경로 처리 시 유용) /files/dir/a.txt <int> (기본값) /를 제외한 모든 정수를 받습니다. /user/1 <float> (기본값) /를 제외한 모든 실수을 받습니다. /user/11.0 <any(...)> 지정된 목록 중 하나만 허용합니다. /color/red (blue, green도 가능)
from flask import Flask
app = Flask(__name__)
@app.route('/book/<isbn>')
def find_book(isbn):
return f"{isbn} 책은 있습니다."
if __name__ == '__main__':
app.run(debug=True, host = '0.0.0.0')
# [host]
# host='127.0.0.1' (기본값) - localhost
# host='0.0.0.0' - 모든 대역대 ip에서 접근
# host='10.0.66.200' - 특정 ip로 접근
- 쿼리 스트링 방식: URL 뒤에 ?를 붙여서 추가 정보를 전달합니다. 주로 검색 조건이나 필터를 넘길 때 씁니다.
- ? ( /search?q=Flask ) : 추가 정보를 전달, 매개변수 형태가 /search 처럼 없으면서 값을 q=Flask 형태로 넘길 때 쿼리 매개변수는 함수 내에서 request.args.get으로 값을 전달받아 처리함.
from flask import Flask, request
app = Flask(__name__)
@app.route('/search')
def search():
query = request.args.get('q') # get방식으로 넘어온 값 받아오기 (쿼리 스트링)
return f'검색어: {query}'
if __name__ == "__main__":
app.run(debug=True)
* 요약 정리
| 구분 | 동적 경로 (/user/<name>) | 쿼리 스트링 (/search?q=val) |
| 용도 | 리소스 고유 식별 (예: 유저, 글번호) | 추가 조건, 검색, 필터링 |
| 코드 처리 | 함수 인자로 바로 전달받음 | request.args.get()으로 받음 |
| URL 형태 | 깔끔하고 정돈된 형태 | ?와 &로 이어지는 형태 |
5. url_for: 하드코딩된 URL (예: href="/search?q=Flask") 대신, 함수 이름을 통해 URL을 생성해주는 함수
from flask import Flask, request
app = Flask(__name__)
@app.route('/search_link')
def search_link(): # url_for: q= 시작하면 search?q=Flask 로 변환
return f'<a href="{url_for("search", q="Flask")}">Flask 검색하기</a>'
# return f'<a href="/search?q={query}">Flask 검색하기</a>'
if __name__ == "__main__":
app.run(debug=True)
6. redirect: 사용자를 다른 URL로 강제로 이동시킬 때 사용하는 아주 중요한 기능
- redirect 동작 원리: 사용자가 어떤 페이지에 접속했을 때, 서버가 브라우저에게 HTTP 302 상태 코드와 함께 새로운 목적지 주소를 보냅니다. 그러면 브라우저는 서버가 시킨 대로 그 주소로 자동 이동합니다.
- 코드 예시
from flask import Flask, redirect, url_for
app = Flask(__name__)
@app.route('/')
def home():
return '여기는 홈 페이지입니다.'
# 사용자가 /old_page로 접속하면 /로 이동시킴
@app.route('/old_page')
def old_page():
return redirect(url_for('home'))
if __name__ == '__main__':
app.run(debug=True)
느낀점
지난주 마지막 과제가 힘들었어서 그 부분을 복습하기도 바쁜데 FLASK를 배웠다. 파이썬을 이제 프론트 쪽과 연결해서 사용할 수 있게 해주는 모듈인데, 또 새로운 개념을 들으니까 머리 속이 터지는 느낌이 들었다. 앞으로 이제 Flask는 사용해야할 때가 많을 것 같은데 초반부터 놓치면 안되기 때문에 수업을 놓치지 않기 위해 노력해야할 것 같다.
——————————————————————————
본 후기는 [한글과컴퓨터x한국생산성본부x스나이퍼팩토리] 한컴 AI 아카데미 (B-log) 리뷰로 작성 되었습니다.
'학습일지' 카테고리의 다른 글
| [스나이퍼팩토리] 한컴AI아카데미(26.04.29) (0) | 2026.04.29 |
|---|---|
| [스나이퍼팩토리] 한컴AI아카데미(26.04.28) (0) | 2026.04.28 |
| [스나이퍼팩토리] 한컴AI아카데미(26.04.24) (0) | 2026.04.24 |
| [스나이퍼팩토리] 한컴AI아카데미(26.04.23) (0) | 2026.04.23 |
| [스나이퍼팩토리] 한컴AI아카데미(26.04.22) (0) | 2026.04.22 |