[Code] Study & Practice

[Python] MySQL & Jupyter 연동 - 객체지향 프로그래밍(OOP)을 활용한 DB 작업 프로그램 예제

yssong01 2025. 11. 5. 15:10

HW)

MySQL program과 Jupyter program의 DB 연동으로 객체지향 프로그래밍(OOP)을 활용한 데이터베이스(DB) 작업 프로그램을 만들어보자.

 

MySQL Workbench를 활용해서 아래와 같이 DB를 만들고, Jupyter notebook을 활용하여 DB와 연결한 후 OOP를 구현해보자. ※ Jupyter는 Colab과 유사하게 사용할 수 있는데 특히 웹을 통하지 않고 직접 MySQL과 연동하여 파이썬 코드를 작성하는 것에 유용하다.

 

필자는 최신 국내 하이브리드(HEV) 자동차들의 정보를 DB를 활용하여 만들어보았다. MySQL에서 항목(열 제목)은 영어를 사용하는 것이 권장되기 때문에, 아래와 같이 각 항목을 영어 약어로 만들어 보았다. 각 항목에 대한 하이브리드 자동차별 주요 정보는 danawacar의 자동차 정보 비교 목록을 참고하였다.

약어 영문명 국문명 단위
idx index 순번 -
Mfactr Manufacturer 제조사 -
Mdname Model Name 모델명(자동차 이름) -
Rldate Release Date 출시날짜 -
Vhtype Vehicle Type 차종(소,중,준중,SUV) -
Dtrain Drive train 굴림방식(전륜FF, 4WD) -
Trsmsn Transmission 변속기 -
Engdsp Engine Displacement 배기량 cc
Whsize Wheel size 휠(바퀴) 사이즈 inch
Cfuely Combined Fuel Economy 복합연비(고속, 시내 주행 포함) km/L
Ftanky Fuel Tank Capacity 연료탱크용량 L (Liter)
EDrang Estimated Driving Range 기대주행거리 km

 

MySQL에서 'HEVcar'라는 테이블 제목으로 DB를 만들어서 출력한 결과물이다.

※ 참고로 DB에서 단위는 생략하였다. 또한 기대주행거리 [km] = 복합연비 [km/L] X 연료탱크용량 [L] 로 계산하였다.

 

우선, Jupyter에서 OOP를 아래와 같이 아래와 같이 구조화하여 각 class마다 역할을 부여할 수 있다.

 

OOP 전체 구조와 흐름은 간략히 아래와 같이 정리할 수 있다.

- OOP : Object-Oriented Programming (객체지향 프로그래밍)

- DTO, DAO, Service, UI 등으로 구조화할 수 있다.

 

> DTO :  Data Transfer Object (데이터 클래스)

- DB의 table 항목에 대한 사항을 미리 지정하여 DB를 에러없이 부르고 다룰 수 있는 환경과 틀을 준비한 곳이다.

 

> DAO : Data Access Object (데이터 접근 객체, MySQL 연동 클래스)

- MySQL에서 완성된 DB를 Jupyter로 가져오기 위해서 두 프로그램을 연결(connect)하고 작업 수행에 대한 연산을 준비한 곳 이다.

 

> Service : 비즈니스 로직 처리

- DAO에서 작업 수행을 위해 정리된 DB를 활용하여 작업 수행을 구체적으로 수행(지시)하도록 준비한 곳이다.

 

> UI : User Interface (명령 수행, input()으로 메뉴를 입력 받아서 실행)

- Service에 구분된 작업(삽입,출력,검색,수정,삭제)를 수행하기 위한 Menu(선택)를 준비한 곳이다. 

[그림] MySQL과 Jupyter의 DB 연동 경로 및 OOP의 DB 작업 로직과 구조

 

이제 Menu에서 각 작업을 수행해서 OOP를 구현한 결과를 확인해보자.

- 선택 목록 : 1. 삽입, 2. 출력, 3. 검색, 4. 수정, 5. 삭제, 6. 종료

 

 

첫번째로, '2. 출력'하면 DB가 각 index에 대한 행 별로 잘 불러와지는지 확인할 수 있다.

'''
#---2. 출력 하기-----------------------------------
1.등록 2.출력 3.검색 4.수정 5.삭제 6.종료 : 
 2
자동차 정보 출력

순번: 1, 제조사: 기아, 모델명: 니로, 출시날짜: 2025-05-02
차종: 소형SUV, 굴림방식: FF, 변속기: DCT 6단, 배기량: 1580
휠사이즈:18, 복합연비:19.1, 연료탱크용량:42, 기대주행거리:802

순번: 2, 제조사: 기아, 모델명: K5, 출시날짜: 2025-06-19
차종: 중형, 굴림방식: FF, 변속기: 자동 6단, 배기량: 1999
휠사이즈:17, 복합연비:18.8, 연료탱크용량:50, 기대주행거리:940

순번: 3, 제조사: 기아, 모델명: K8, 출시날짜: 2025-06-19
차종: 준대형, 굴림방식: FF, 변속기: 자동 6단, 배기량: 1598
휠사이즈:17, 복합연비:18.1, 연료탱크용량:50, 기대주행거리:905

순번: 4, 제조사: 기아, 모델명: 쏘렌토, 출시날짜: 2025-07-14
차종: 중형SUV, 굴림방식: FF, 변속기: 자동 6단, 배기량: 1598
휠사이즈:18, 복합연비:14.8, 연료탱크용량:67, 기대주행거리:992

순번: 5, 제조사: 기아, 모델명: 카니발, 출시날짜: 2025-08-18
차종: 대형MPV, 굴림방식: FF, 변속기: 자동 6단, 배기량: 1598
휠사이즈:19, 복합연비:13.5, 연료탱크용량:72, 기대주행거리:972

순번: 6, 제조사: 현대, 모델명: 코나, 출시날짜: 2025-04-23
차종: 소형SUV, 굴림방식: FF, 변속기: DCT 6단, 배기량: 1580
휠사이즈:17, 복합연비:19.8, 연료탱크용량:38, 기대주행거리:752

순번: 7, 제조사: 현대, 모델명: 아반떼, 출시날짜: 2025-04-15
차종: 준중형, 굴림방식: FF, 변속기: DCT 6단, 배기량: 1580
휠사이즈:18, 복합연비:18.5, 연료탱크용량:42, 기대주행거리:777

순번: 8, 제조사: 현대, 모델명: 그랜저, 출시날짜: 2025-05-21
차종: 준대형, 굴림방식: FF, 변속기: 자동 6단, 배기량: 1598
휠사이즈:18, 복합연비:18.0, 연료탱크용량:50, 기대주행거리:900

순번: 9, 제조사: 현대, 모델명: 싼타페, 출시날짜: 2025-08-07
차종: 중형SUV, 굴림방식: FF, 변속기: 자동 6단, 배기량: 1598
휠사이즈:18, 복합연비:15.5, 연료탱크용량:67, 기대주행거리:1039

순번: 10, 제조사: 현대, 모델명: 투싼, 출시날짜: 2025-08-07
차종: 중형SUV, 굴림방식: 4WD, 변속기: 자동 6단, 배기량: 1598
휠사이즈:19, 복합연비:14.3, 연료탱크용량:52, 기대주행거리:744

#---6. 종료 하기-----------------------------------
1.등록 2.출력 3.검색 4.수정 5.삭제 6.종료 : 
 6
프로그램 종료
'''

 

다음으로, '5. 삭제'를 해보자. DB에서 index 10의 '현대 투싼'에 해당하는 행을 삭제해보자. 정삭적으로 삭제된 후, 3번 검색을 해보면 '투싼'을 검색할 수 없음을 확인할 수 있다. 이후 2번 출력을 다시 해보면 마지막 10번째 행이 출력되지 않는다.

'''
#---5. 삭제 하기-----------------------------------
1.등록 2.출력 3.검색 4.수정 5.삭제 6.종료 : 
 5
자동차 정보 삭제

삭제할 모델명(차이름)을 입력하세요: 투싼
삭제 완료!

#---3. 검색 하기-----------------------------------
1.등록 2.출력 3.검색 4.수정 5.삭제 6.종료 : 
 3
자동차 정보 검색

검색할 모델명(차이름)을 입력하세요: 투싼
!!찾는 모델명(차이름)이 없습니다!!

#---2. 출력 하기-----------------------------------
1.등록 2.출력 3.검색 4.수정 5.삭제 6.종료 : 
 2
자동차 정보 출력

순번: 1, 제조사: 기아, 모델명: 니로, 출시날짜: 2025-05-02
차종: 소형SUV, 굴림방식: FF, 변속기: DCT 6단, 배기량: 1580
휠사이즈:18, 복합연비:19.1, 연료탱크용량:42, 기대주행거리:802

순번: 2, 제조사: 기아, 모델명: K5, 출시날짜: 2025-06-19
차종: 중형, 굴림방식: FF, 변속기: 자동 6단, 배기량: 1999
휠사이즈:17, 복합연비:18.8, 연료탱크용량:50, 기대주행거리:940

순번: 3, 제조사: 기아, 모델명: K8, 출시날짜: 2025-06-19
차종: 준대형, 굴림방식: FF, 변속기: 자동 6단, 배기량: 1598
휠사이즈:17, 복합연비:18.1, 연료탱크용량:50, 기대주행거리:905

순번: 4, 제조사: 기아, 모델명: 쏘렌토, 출시날짜: 2025-07-14
차종: 중형SUV, 굴림방식: FF, 변속기: 자동 6단, 배기량: 1598
휠사이즈:18, 복합연비:14.8, 연료탱크용량:67, 기대주행거리:992

순번: 5, 제조사: 기아, 모델명: 카니발, 출시날짜: 2025-08-18
차종: 대형MPV, 굴림방식: FF, 변속기: 자동 6단, 배기량: 1598
휠사이즈:19, 복합연비:13.5, 연료탱크용량:72, 기대주행거리:972

순번: 6, 제조사: 현대, 모델명: 코나, 출시날짜: 2025-04-23
차종: 소형SUV, 굴림방식: FF, 변속기: DCT 6단, 배기량: 1580
휠사이즈:17, 복합연비:19.8, 연료탱크용량:38, 기대주행거리:752

순번: 7, 제조사: 현대, 모델명: 아반떼, 출시날짜: 2025-04-15
차종: 준중형, 굴림방식: FF, 변속기: DCT 6단, 배기량: 1580
휠사이즈:18, 복합연비:18.5, 연료탱크용량:42, 기대주행거리:777

순번: 8, 제조사: 현대, 모델명: 그랜저, 출시날짜: 2025-05-21
차종: 준대형, 굴림방식: FF, 변속기: 자동 6단, 배기량: 1598
휠사이즈:18, 복합연비:18.0, 연료탱크용량:50, 기대주행거리:900

순번: 9, 제조사: 현대, 모델명: 싼타페, 출시날짜: 2025-08-07
차종: 중형SUV, 굴림방식: FF, 변속기: 자동 6단, 배기량: 1598
휠사이즈:18, 복합연비:15.5, 연료탱크용량:67, 기대주행거리:1039

#---6. 종료 하기-----------------------------------
1.등록 2.출력 3.검색 4.수정 5.삭제 6.종료 : 
 6
프로그램 종료
'''


이는 Jupyter에서 index 10번 투싼에 해당하는 행이 삭제되었을 뿐만 아니라, 아래와 같이 MySQL에서도 DB 연동으로 10번째 행이 삭제되었음을 확인할 수 있다. 

 

이번에는 '1. 등록'을 해보자. 위에서 이미 삭제 완료된 index 10번 현대 투싼의 정보를 다시 DB에 등록(입력)해보자. 등록 후, 3. 검색 및 2. 출력을 해보면, DB에 정상적으로 등록되었음을 확인할 수 있다.

'''
#---1. 동록 하기-----------------------------------
1.등록 2.출력 3.검색 4.수정 5.삭제 6.종료 : 
 1
자동차 정보 등록

순번 index:  10
제조사 Manufacturer:  현대
모델명 Model Name:  투싼
출시날짜 Release Date:  2025-08-07
차종 Vehicle Type:  중형SUV
굴림방식 Drive train:  FF
변속기 Transmission:  자동 6단
배기량 Engine Displacement[cc]:  1598
휠사이즈 Wheel size[inch]:  19
복합연비 Combined Fuel Economy[km/L]:  14.3
연료탱크용량 Fuel Tank Capacity[L]:  52
기대주행거리 Estimated Driving Range[km]:  744
자동차 정보가 등록 완료되었습니다.

#---3. 검색 하기-----------------------------------
1.등록 2.출력 3.검색 4.수정 5.삭제 6.종료 : 
 3
자동차 정보 검색

검색할 모델명(차이름)을 입력하세요: 투싼
순번: 10, 제조사: 현대, 모델명: 투싼, 출시날짜: 2025-08-07
차종: 중형SUV, 굴림방식: FF, 변속기: 자동 6단, 배기량: 1598
휠사이즈:19, 복합연비:14.3, 연료탱크용량:52, 기대주행거리:744

#---2. 출력 하기-----------------------------------
1.등록 2.출력 3.검색 4.수정 5.삭제 6.종료 : 
 2
자동차 정보 출력

순번: 1, 제조사: 기아, 모델명: 니로, 출시날짜: 2025-05-02
차종: 소형SUV, 굴림방식: FF, 변속기: DCT 6단, 배기량: 1580
휠사이즈:18, 복합연비:19.1, 연료탱크용량:42, 기대주행거리:802

순번: 2, 제조사: 기아, 모델명: K5, 출시날짜: 2025-06-19
차종: 중형, 굴림방식: FF, 변속기: 자동 6단, 배기량: 1999
휠사이즈:17, 복합연비:18.8, 연료탱크용량:50, 기대주행거리:940

순번: 3, 제조사: 기아, 모델명: K8, 출시날짜: 2025-06-19
차종: 준대형, 굴림방식: FF, 변속기: 자동 6단, 배기량: 1598
휠사이즈:17, 복합연비:18.1, 연료탱크용량:50, 기대주행거리:905

순번: 4, 제조사: 기아, 모델명: 쏘렌토, 출시날짜: 2025-07-14
차종: 중형SUV, 굴림방식: FF, 변속기: 자동 6단, 배기량: 1598
휠사이즈:18, 복합연비:14.8, 연료탱크용량:67, 기대주행거리:992

순번: 5, 제조사: 기아, 모델명: 카니발, 출시날짜: 2025-08-18
차종: 대형MPV, 굴림방식: FF, 변속기: 자동 6단, 배기량: 1598
휠사이즈:19, 복합연비:13.5, 연료탱크용량:72, 기대주행거리:972

순번: 6, 제조사: 현대, 모델명: 코나, 출시날짜: 2025-04-23
차종: 소형SUV, 굴림방식: FF, 변속기: DCT 6단, 배기량: 1580
휠사이즈:17, 복합연비:19.8, 연료탱크용량:38, 기대주행거리:752

순번: 7, 제조사: 현대, 모델명: 아반떼, 출시날짜: 2025-04-15
차종: 준중형, 굴림방식: FF, 변속기: DCT 6단, 배기량: 1580
휠사이즈:18, 복합연비:18.5, 연료탱크용량:42, 기대주행거리:777

순번: 8, 제조사: 현대, 모델명: 그랜저, 출시날짜: 2025-05-21
차종: 준대형, 굴림방식: FF, 변속기: 자동 6단, 배기량: 1598
휠사이즈:18, 복합연비:18.0, 연료탱크용량:50, 기대주행거리:900

순번: 9, 제조사: 현대, 모델명: 싼타페, 출시날짜: 2025-08-07
차종: 중형SUV, 굴림방식: FF, 변속기: 자동 6단, 배기량: 1598
휠사이즈:18, 복합연비:15.5, 연료탱크용량:67, 기대주행거리:1039

순번: 10, 제조사: 현대, 모델명: 투싼, 출시날짜: 2025-08-07
차종: 중형SUV, 굴림방식: FF, 변속기: 자동 6단, 배기량: 1598
휠사이즈:19, 복합연비:14.3, 연료탱크용량:52, 기대주행거리:744

#---6. 종료 하기-----------------------------------
1.등록 2.출력 3.검색 4.수정 5.삭제 6.종료 : 
 6
프로그램 종료
'''

 

마찬가지로 아래 그림과 같이, MySQL에서도 DB연동으로 index 10번 현대 투싼 행의 정보가 입력되었음을 확인할 수 있다.

 

그런데 등록 중에 현대 투싼의 항목 중 Dtrain(굴림 방식)의 정보를 'FF(전륜구동)'으로 잘 못 기입했다.

 

마지막으로 '4. 수정'을 선택하여 FF를 4WD(4륜구동)으로 수정해보자.

 

'''
1.등록 2.출력 3.검색 4.수정 5.삭제 6.종료 : 
 4
자동차 정보 수정

수정할 모델명(차이름)을 입력하세요: 투싼
수정할 순번 index:  10
수정할 제조사 Manufacturer:  현대
수정할 모델명 Model Name:  투싼
수정할 출시날짜 Release Date:  2025-08-07
수정할 차종 Vehicle Type:  중형SUV
수정할 굴림방식 Drive train:  4WD
수정할 변속기 Transmission:  자동 6단
수정할 배기량 Engine Displacement[cc]:  1598
수정할 휠사이즈 Wheel size[inch]:  18
수정할 복합연비 Combined Fuel Economy[km/L]:  15.5
수정할 연료탱크용량 Fuel Tank Capacity[L]:  67
수정할 기대주행거리 Estimated Driving Range[km]:  1039
수정 완료!
1.등록 2.출력 3.검색 4.수정 5.삭제 6.종료 : 
 3
자동차 정보 검색

검색할 모델명(차이름)을 입력하세요: 투싼
순번: 10, 제조사: 현대, 모델명: 투싼, 출시날짜: 2025-08-07
차종: 중형SUV, 굴림방식: 4WD, 변속기: 자동 6단, 배기량: 1598
휠사이즈:18, 복합연비:15.5, 연료탱크용량:67, 기대주행거리:1039

1.등록 2.출력 3.검색 4.수정 5.삭제 6.종료 : 
 2
자동차 정보 출력

순번: 1, 제조사: 기아, 모델명: 니로, 출시날짜: 2025-05-02
차종: 소형SUV, 굴림방식: FF, 변속기: DCT 6단, 배기량: 1580
휠사이즈:18, 복합연비:19.1, 연료탱크용량:42, 기대주행거리:802

순번: 2, 제조사: 기아, 모델명: K5, 출시날짜: 2025-06-19
차종: 중형, 굴림방식: FF, 변속기: 자동 6단, 배기량: 1999
휠사이즈:17, 복합연비:18.8, 연료탱크용량:50, 기대주행거리:940

순번: 3, 제조사: 기아, 모델명: K8, 출시날짜: 2025-06-19
차종: 준대형, 굴림방식: FF, 변속기: 자동 6단, 배기량: 1598
휠사이즈:17, 복합연비:18.1, 연료탱크용량:50, 기대주행거리:905

순번: 4, 제조사: 기아, 모델명: 쏘렌토, 출시날짜: 2025-07-14
차종: 중형SUV, 굴림방식: FF, 변속기: 자동 6단, 배기량: 1598
휠사이즈:18, 복합연비:14.8, 연료탱크용량:67, 기대주행거리:992

순번: 5, 제조사: 기아, 모델명: 카니발, 출시날짜: 2025-08-18
차종: 대형MPV, 굴림방식: FF, 변속기: 자동 6단, 배기량: 1598
휠사이즈:19, 복합연비:13.5, 연료탱크용량:72, 기대주행거리:972

순번: 6, 제조사: 현대, 모델명: 코나, 출시날짜: 2025-04-23
차종: 소형SUV, 굴림방식: FF, 변속기: DCT 6단, 배기량: 1580
휠사이즈:17, 복합연비:19.8, 연료탱크용량:38, 기대주행거리:752

순번: 7, 제조사: 현대, 모델명: 아반떼, 출시날짜: 2025-04-15
차종: 준중형, 굴림방식: FF, 변속기: DCT 6단, 배기량: 1580
휠사이즈:18, 복합연비:18.5, 연료탱크용량:42, 기대주행거리:777

순번: 8, 제조사: 현대, 모델명: 그랜저, 출시날짜: 2025-05-21
차종: 준대형, 굴림방식: FF, 변속기: 자동 6단, 배기량: 1598
휠사이즈:18, 복합연비:18.0, 연료탱크용량:50, 기대주행거리:900

순번: 9, 제조사: 현대, 모델명: 싼타페, 출시날짜: 2025-08-07
차종: 중형SUV, 굴림방식: FF, 변속기: 자동 6단, 배기량: 1598
휠사이즈:18, 복합연비:15.5, 연료탱크용량:67, 기대주행거리:1039

순번: 10, 제조사: 현대, 모델명: 투싼, 출시날짜: 2025-08-07
차종: 중형SUV, 굴림방식: 4WD, 변속기: 자동 6단, 배기량: 1598
휠사이즈:18, 복합연비:15.5, 연료탱크용량:67, 기대주행거리:1039

1.등록 2.출력 3.검색 4.수정 5.삭제 6.종료 : 
 6
프로그램 종료
'''

 

이와 같이, MySQL과 Jupyter의 DB 연동을 통한 OOP 구현을 할 수 있다. 이번 예제는 OOP의 구조를 이해하고 특히 class들 사이의 method call에 대한 이해를 높이는 데에 매우 유익하다. 앞으로도 다른 기능들을 더하여 시도해볼 수 있을 것이다!

 

※ OOP에 대한 코드는 아래에 첨부합니다.

 

DTO - class Car

import MySQLdb
# DTO (Data Transfer Object) - 데이터 클래스
class Car:
    def __init__(self, idx, Mfactr, Mdname, Rldate, Vhtype, Dtrain, Trsmsn, Engdsp=0, Whsize=0, Cfuely=0.0, Ftanky=0, EDrang=0):
        self.idx = idx
        self.Mfactr = Mfactr  
        self.Mdname = Mdname
        self.Rldate = Rldate
        self.Vhtype = Vhtype
        self.Dtrain = Dtrain
        self.Trsmsn = Trsmsn
        self.Engdsp = Engdsp
        self.Whsize = Whsize
        self.Cfuely = Cfuely
        self.Ftanky = Ftanky
        self.EDrang = EDrang

    def __repr__(self):
        return f"Car(idx='{self.idx}', Mfactr='{self.Mfactr}', Mdname='{self.Mdname}', Rldate='{self.Rldate}', \
                Vhtype='{self.Vhtype}, Dtrain='{self.Dtrain}', Trsmsn='{self.Trsmsn}', Engdsp='{self.Engdsp}', \
                Whsize='{self.Whsize}, Cfuely='{self.Cfuely}', Ftanky='{self.Ftanky}', EDrang='{self.EDrang}' )"

    def setidx(self, idx):
        self.idx = idx
    def getidx(self):
        return self.idx
    
    def setMfactr(self, Mfactr):
        self.Mfactr = Mfactr
    def getMfactr(self):
        return self.Mfactr

    def setMdname(self, Mdname):
        self.Mdname = Mdname
    def getMdname(self):
        return self.Mdname

    def setRldate(self, Rldate):
        self.Rldate = Rldate
    def getRldate(self):
        return self.Rldate
            
    def setVhtype(self, Vhtype):
        self.Vhtype = Vhtype
    def getVhtype(self):
        return self.Vhtype

    def setDtrain(self, Dtrain):
        self.Dtrain = Dtrain
    def getDtrain(self):
        return self.Dtrain

    def setTrsmsn(self, Trsmsn):
        self.Trsmsn = Trsmsn
    def getTrsmsn(self):
        return self.Trsmsn

    def setEngdsp(self, Engdsp):
        self.Engdsp = Engdsp
    def getEngdsp(self):
        return self.Engdsp
            
    def setWhsize(self, Whsize):
        self.Whsize = Whsize
    def getWhsize(self):
        return self.Whsize

    def setCfuely(self, Cfuely):
        self.Cfuely = Cfuely
    def getCfuely(self):
        return self.Cfuely

    def setFtanky(self, Ftanky):
        self.Ftanky = Ftanky
    def getFtanky(self):
        return self.Ftanky

    def setEDrang(self, EDrang):
        self.EDrang = EDrang
    def getEDrang(self):
        return self.EDrang

 

DAO - class CarDAO

# DAO (Data Access Object) - MySQL 연동 클래스
class CarDAO:
    def __init__(self):
        self.db = None
        #pass

    def connect(self):
        self.db = MySQLdb.connect('localhost', 'yssong', '2222', 'aiyssong')
        #print(self.db)

    def disconnect(self):
        self.db.close()

    def insert(self, car):
        self.connect()
        cur = self.db.cursor()
        sql = 'insert into HEVcar (idx, Mfactr, Mdname, Rldate, Vhtype, Dtrain, Trsmsn, Engdsp, Whsize, Cfuely, Ftanky, EDrang) \
                values (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)'
        data = (car.getidx(), car.getMfactr(), car.getMdname(), car.getRldate(), car.getVhtype(), car.getDtrain(),
                car.getTrsmsn(), car.getEngdsp(), car.getWhsize(), car.getCfuely(), car.getFtanky(), car.getEDrang())
        cur.execute(sql, data)
        self.db.commit()
        cur.close()
        self.disconnect()

    def selectAll(self):
        self.connect()
        cur = self.db.cursor(MySQLdb.cursors.DictCursor) # 딕셔너리 형식으로 가져오기
        sql = 'select idx, Mfactr, Mdname, Rldate, Vhtype, Dtrain, Trsmsn, Engdsp, Whsize, Cfuely, Ftanky, EDrang \
                from HEVcar order by idx asc'
        cur.execute(sql)
        rows = cur.fetchall()
        cur.close()
        self.disconnect()
        return rows

    def search(self, Mdname):
        self.connect()
        cur = self.db.cursor(MySQLdb.cursors.DictCursor)
        sql = "select idx, Mfactr, Mdname, Rldate, Vhtype, Dtrain, Trsmsn, Engdsp, Whsize, Cfuely, Ftanky, EDrang \
                from HEVcar where Mdname like concat('%%', %s, '%%')"
        data = (Mdname, )
        cur.execute(sql, data)
        rows = cur.fetchall()
        cur.close()
        self.disconnect()
        return rows

    def update(self, car):
        self.connect()
        cur = self.db.cursor()
        sql = 'update HEVcar set Mfactr=%s, Mdname=%s, Rldate=%s, Vhtype=%s, Dtrain=%s, Trsmsn=%s, Engdsp=%s, Whsize=%s, \
                Cfuely=%s, Ftanky=%s, EDrang=%s where idx=%s'
        data = (car.getMfactr(), car.getMdname(), car.getRldate(), car.getVhtype(), car.getDtrain(), car.getTrsmsn(),
                car.getEngdsp(), car.getWhsize(), car.getCfuely(), car.getFtanky(), car.getEDrang(), car.getidx())
        result = cur.execute(sql, data)
        self.db.commit()
        print('수정 완료!' if result > 0 else '!!Error')
        # if result > 0:
        #     print('수정 완료!')
        # else:
        #     print('!!Error')
        cur.close()
        self.disconnect()

    
    def delete(self, Mdname):
        self.connect()
        cur = self.db.cursor()
        sql = 'delete from HEVcar where Mdname=%s'
        data = (Mdname, )
        result = cur.execute(sql, data)
        self.db.commit()
        print('삭제 완료!' if result > 0 else '!!Error')
        # if result > 0:
        #     print('삭제 완료!')
        # else:
        #     print('!!Error')
        cur.close()
        self.disconnect()

 

Service - class CarService

# Service (비지니스 로직 처리)
class CarService:
    def __init__(self):
        self.dao = CarDAO()
        #pass

    def insertCar(self):
        idx = int(input('순번 index: '))
        Mfactr = input('제조사 Manufacturer: ')
        Mdname = input('모델명 Model Name: ')
        Rldate = input('출시날짜 Release Date: ')
        Vhtype = input('차종 Vehicle Type: ')
        Dtrain = input('굴림방식 Drive train: ')
        Trsmsn = input('변속기 Transmission: ')
        Engdsp = int(input('배기량 Engine Displacement[cc]: '))
        Whsize = int(input('휠사이즈 Wheel size[inch]: '))
        Cfuely = float(input('복합연비 Combined Fuel Economy[km/L]: '))
        Ftanky = int(input('연료탱크용량 Fuel Tank Capacity[L]: '))
        EDrang = int(input('기대주행거리 Estimated Driving Range[km]: '))

        carinfo = Car(idx, Mfactr, Mdname, Rldate, Vhtype, Dtrain, Trsmsn, Engdsp, Whsize, Cfuely, Ftanky, EDrang)
        #print(carinfo)

        self.dao.insert(carinfo)
        print('자동차 정보가 등록 완료되었습니다.')

        
    def printAll(self):
        datas = self.dao.selectAll()

        for data in datas:
            print(f"순번: {data['idx']}, 제조사: {data['Mfactr']}, 모델명: {data['Mdname']}, 출시날짜: {data['Rldate']}")
            print(f"차종: {data['Vhtype']}, 굴림방식: {data['Dtrain']}, 변속기: {data['Trsmsn']}, 배기량: {data['Engdsp']}")
            print(f"휠사이즈:{data['Whsize']}, 복합연비:{data['Cfuely']}, 연료탱크용량:{data['Ftanky']}, 기대주행거리:{data['EDrang']}\n")
  
            
    def searchCar(self):
        Mdname = input('검색할 모델명(차이름)을 입력하세요:').strip()
        datas = self.dao.search(Mdname)
        if datas:
            for data in datas:
                print(f"순번: {data['idx']}, 제조사: {data['Mfactr']}, 모델명: {data['Mdname']}, 출시날짜: {data['Rldate']}")
                print(f"차종: {data['Vhtype']}, 굴림방식: {data['Dtrain']}, 변속기: {data['Trsmsn']}, 배기량: {data['Engdsp']}")
                print(f"휠사이즈:{data['Whsize']}, 복합연비:{data['Cfuely']}, 연료탱크용량:{data['Ftanky']}, 기대주행거리:{data['EDrang']}\n")
        else:
            print('!!찾는 모델명(차이름)이 없습니다!!')

    
    def editCar(self):
        Mdname = input('수정할 모델명(차이름)을 입력하세요:')
        car = self.dao.search(Mdname)
        if not car:
            print('!!수정할 모델명(차이름)이 없습니다!!')
        else:
            idx = int(input('수정할 순번 index: '))
            Mfactr = input('수정할 제조사 Manufacturer: ')
            Mdname = input('수정할 모델명 Model Name: ')
            Rldate = input('수정할 출시날짜 Release Date: ')
            Vhtype = input('수정할 차종 Vehicle Type: ')
            Dtrain = input('수정할 굴림방식 Drive train: ')
            Trsmsn = input('수정할 변속기 Transmission: ')
            Engdsp = int(input('수정할 배기량 Engine Displacement[cc]: '))
            Whsize = int(input('수정할 휠사이즈 Wheel size[inch]: '))
            Cfuely = float(input('수정할 복합연비 Combined Fuel Economy[km/L]: '))
            Ftanky = int(input('수정할 연료탱크용량 Fuel Tank Capacity[L]: '))
            EDrang = int(input('수정할 기대주행거리 Estimated Driving Range[km]: '))
            
            carinfo = Car(idx, Mfactr, Mdname, Rldate, Vhtype, Dtrain, Trsmsn, Engdsp, Whsize, Cfuely, Ftanky, EDrang)
            self.dao.update(carinfo)
            #print('!!수정 완료!!')

            
    def delCar(self):
            Mdname = input('삭제할 모델명(차이름)을 입력하세요:').strip()
            car = self.dao.search(Mdname)
            if not car:
                print('!!삭제할 모델명(차이름)이 없습니다!!')
            else:
                self.dao.delete(Mdname)     
                #print('!!삭제 완료!!')

 

UI - class Menu

# UI (메뉴판, 사용자 조작) User Interface

class Menu:
    def __init__(self):
        self.service = CarService()
        #pass

    def doit(self):
        while True:
            try:
                menu = int(input('1.등록 2.출력 3.검색 4.수정 5.삭제 6.종료 : \n'))
                if menu == 1:
                    print('자동차 정보 등록\n')
                    self.service.insertCar()
                elif menu == 2:
                    print('자동차 정보 출력\n')
                    self.service.printAll()
                elif menu == 3:
                    print('자동차 정보 검색\n')
                    self.service.searchCar()
                elif menu == 4:
                    print('자동차 정보 수정\n')
                    self.service.editCar()
                elif menu == 5:
                    print('자동차 정보 삭제\n')
                    self.service.delCar()                   
                elif menu == 6:
                    print('프로그램 종료')
                    break               
                
            except Exception as e:
                print(e)
                print('재입력 요망')
                
# 결과 실행
Menu().doit()

 

 

즐거운 파이썬~ 즐 파이씽!

 

[주의] 내용에 오류가 있을 수 있습니다.