MySQL Workbench를 이용해서 쉽게 기존 DB SCHEMA 그대로 새로 SCHEMA 생성하기

이미지
1. MySQL Workbench에서 Model 메뉴 진입 2. Reverse Engineer 선택 3. 복제할 대상의 Schema를 선택 후 모든 option next 대충 이런식의 모델이 생성된다. 4. 이 상태에서 그대로 Forward Engineering 5. 적절하게 원하는 옵션선택해주고 나면 마지막에 대략 이런 SQL문이 만들어진다. 이걸 실행하지는 말고  만들어진 내용만 복사하자.  DB명을 새로 만들 DB명으로 변경해줘야 하니까. 스샷 기준으로는 abmgt_prod를 my_new_table_name으로 변경하면 되겠다. 그대로 안되고 에러나는 경우가 있다. MySQL 버전차이로 생기는 문제일 수 있고 문제의 원인은 다양한데 내 경우엔 2가지 이슈가 있었다.  1. Date에 0000-00-00과 같은 값이 허용되지 않음. 3번째 줄 SQL_MODE의 String에 ,ALLOW_INVALID_DATES 를 추가하니까 해결. 2. UNIQUE INDEX 생성 구문 에러 MySQL 버전따라서 `Unique INDEX(id).. VISIBLE)` 이런 곳에서 에러가 날 수 있다.  MySQL 버전차이 때문에 그럴텐데 VISIBLE 혹은 INVISIBLE을 없애거나 꼭 사용하는데 필요하다면 MySQL의 버전을 올리던가 해야한다. 

AWS Lambda로 Excel -> PDF 변환 기능 개발 후기

이미지
요즘엔 서버리스로 개발하는 회사에서 근무중이다. 쓸 수록 느끼지만 서버리스는 간단한 메시지 전달은 좋지만 점점 서비스가 커지면 느껴지는 제약들이 많다. 그 때는 정말 '아 이거 서버 놓고 하면 금방인데 ㅠㅠ' 하는 생각이 절로든다.. 거기다가 Amplify가 아직 성숙하지 않아서 (=버그가 많다) 버전업하면 갑자기 배포가 안되고 그러는 경우도 종종 있다. 아무튼 이번엔 서버리스 환경에서 (=AWS Lambda) 에서 PDF를 Excel로 변환하는 업무가 주어져서 많은 삽질 끝에 해내게 되었다. 즉 이 글은  AWS Lambda에서 Libreoffice를 이 용해 xlsx 파일을 pdf로 변환하는 기능을 구현하던 중 겪은 어려움과 주의사항 에 대해 기술한다. 실제 구현 방법은 아니고 겪은 Trouble이니 실제 구현을 기대한다면 미리 기대에 어긋난다고 이야기 하고 싶다. 문제 1.람다에서 Streaming으로 Response를 제공할 수 없다. 많은 사람들이 아마 API Gateway와 Lambda를 연동해서 사용할 것이다. 우리도 역시 그렇게 활용중인데 Lambda의 특징은 응답을 한번 보내면 종료된다는 것이다.  일반적으로 웹에서 파일을 다운로드 받을 때는 Streaming으로 받아서 현재 다운로드 되는 현황을 구경할 수 있는데 Lambda로는 그렇게 구현하는 방법을 찾지 못했다. 따라서 서버에서 컨버팅 작업을 모두 끝내고 파일이 생성되면 해당 파일의 Binary를 String으로 변환하고, 이 String을 Response의 Body에 담아 보내게 했다. Client는 받은 String을 다시 Binary로 변환해서 이를 다운로드 하게 만들었다. 당연히 파일의 수가 많아질수록 변환하는데 시간은 더 걸릴 것이다.  API Gateway를 잘 customize하면 Streaming도 대응할 수 있는 것 같은데 확실하지 않다. 그리고 중요한 것. Lambda에서 타임아웃을 길게 걸어놔도 Request를 받은 API Gateway...

실용주의 프로그래머 key takeaway for myself.

1장 깨진 창문을 그대로 두지말자. 깨진 창문에는 Not Implemented 혹은 Dummy data를 추가하는 방식으로 구현해둘 것. 카펫을 더럽히는 일(기존 코드를 바꾸는 작업)은 필요한 순간이 온다. 카펫을 더럽히기 싫어서 가던 곳으로 가지 말고 필요하다면 과감하게 바꿀 것. 적당히 괜찮은 것이 늦어지는 것보다 낫다. 약간의 버그를 감내하더라도 그걸 다듬는다고 망치지마라. 언제 멈춰야할지를 알자.어차피 완벽한 코드란 없다. 지식이란 투자 포트폴리오와 같다. 지식을 다각화하고 (한 분야의 외골수보다 다양한 분야로) 계속해서 투자(계속해서 공부할 것)하며 리턴과 리스크의 조정을 적절히 하고 (기술 배울 때 선택) 주기적으로 재점검 하자. - one new language per year - 기술서적을 분기마다 하나씩. (볼 것을 좀 정해두면 좋겠다) 소통도 분위기를 파악해가며 하자. 말을 하기 전에 미리 적절히 정리해놓을 것. 말할 타이밍을 잘 계산하고 말할 것. 2장 강력하게 Coupling 된 Task는 하나만 해도 다른 하나가 업데이트 되도록 자동화를 시켜두자. 테스트 코드가 문서에 따라 자동으로 만들어지는 사례가 있었다. 만약 문서와 코드의 관계가 깊게 coupling 된 관계라면 문서 혹은 코드를 업데이트할 때 이와 관련 된 작업 혹은 the other one도 똑같이 자동으로 업데이트 할 수 있도록 개선하자. 직교성(Orthogonality)은 중요하다. 프로그래밍에서 직교한다라는 말은 하나가 수정되어도 다른 것에 영향을 주지않는다는 의미로 Decoupled 상태라고 볼 수 있다. 회의에서 직교성을 살펴보는 방법도 재미있다. 어떤 주제로 회의를 하려고 할 때 불러야 하는 사람 수가 많아질수록 직교성이 낮다는 것을 의미한다. 잘못 된 객체지향 코드는 때때로 절차지향 코드보다도 더욱 더 스파게티 코드가 될 확률이 높다. 예광탄 코드를 먼저 쏘아올리자. POC(Proof Of Concept)와 비슷하지만 좀 더 큰 개념. 동일한 환경과 제약을 가진채 ...

WebSocket - 예엣날에 공부했던 내용 정리

# Websocket WebSocket Tutorial with Python 웹소켓이란, HTTP 프로토콜의 단점을 극복하고 실시간 full duplex통신을 위한 기술이다. 개인적으로 웹소켓의 핵심은 Real-time dataflow라 생각한다. 1. 웹소켓이 맺어지는 흐름 Client가 TCP/IP 요청을 보내면 서버에서 TCP/IP 요청을 수락한다. 그 후 Client는 서버에게 웹소켓 handshake를 요청하고 서버는 이를 수락한다. 이렇게 하면 http에서 websocket으로 프로토콜이 전환되며 connection이 만들어지고  이 때부터 웹소켓을 통해 데이터를 송, 수신한다. * 웹소켓은 Http와 전혀 다르다. 다만 웹소켓을 만드는데에 http가 개입을 하는 것이다. 웹소켓이 만들어지면 서버는 응답코드 101을 보낸다. (101은 프로토콜이 전환되었음을 알리는 응답코드다) 2. 웹소켓은 왜 쓰는 것인가? Http보다 더 나은 점이 있을테니 websocket을 쓸텐데 그 점은 무엇일까? 그걸 알기 위해서는 일단 비동기 http 통신방식인 Ajax(XMLHttpRequest, 이하 htttp)에 대해 좀 알아야 한다. AJAX의 본래 이름은 XMLhttprequest이다. 이 기술이 나오고 비동기 통신이 팍! 떡상했다. 하지만 http엔 단점이 있다. 크로스 오리진 문제와 헤더의 용량 문제다. 3. 웹소켓이 http보다 더 나은 점은? 웹소켓과 비교하면 http통신은 항상 요청헤더가 부여되기 때문에 1바이트의 정보를 송신하고 싶어도 수킬로바이트에 달하는 쓸모없는 정보를 보내야한다. "에이 1바이트를 보낼 일이 언제 있다고" 하는 생각이 먼저 들었는데, 생각해보면 채팅같은 경우엔 말을 짧게 짧게 보내기도 한다.  "ok" 보내면 겨우 2바이트다. 이걸 매번 http로 통신한다면 저 짧은 두 글자를 보내는데도 많은 트래픽이 소요될 것이고 이는 성능의 문제로 귀결될 것이다. Real-time application에서는...

생산수단은 반드시 필요하다

자본주의에서 부유 계층에 속하는지 아닌지 는 결국 생산수단을 소유하는가에 달려있다. 생산수단이 만들어내는 생산물을 받는 입장일지라도 양이 크다면 일시적으로 부유해질 수 있지만 최대 본인 세대까지 넉넉하게 살 수 있을 듯하다. 일시적 부가 아닌 부유 계층에 속하기 위해서는 생산수단을 소유하는 것이 중요하다. 일생을 살며, pay라는 동사가 능동태가 아닌 수동태로만 쓰여진다면 나와 내 후세대는 절대로 돈에서 자유로워 질 수 없을 것이다. 삶은 많은 경험과 도전과제들이 있다. 돈 때문에 이런 것들을 포기해야 한다면 안타까울 것이다. 그래서 부유한 삶 그 자체가 목표가 아니고 부유하기 때문에 다양한 것을 시도하고 실패할 수 있는 삶을 추구한다.  먹고사니즘에 얽매여 내 삶의 범위를, 자유를 한정짓지 않도록 언젠가 반드시 생산수단은 소유해야한다. 개발자라는 직업은 다른 직업보다 수월하게 본인의 지식과 실력을 생산수단으로 만들 수 있다. 완전한 생산수단이라기 보다는 반(半) 생산수단이라고 보는 것이 합당할 것 같다. 좀 더 발전하여 내 스스로가 완전한 반(半) 생산수단이 되고 나아가 생산수단을 소유할 수 있는 삶을 살 수 있기를.

2020.04.27 TIL 스프링 - Spring Form Tag 사용하기

Spring의 form 태그는 이렇게 prefix를 붙이고 modelAttribute를 추가하여 사용한다. <form:form modelAttribute="student">   <form:input path="name">    // 자동으로 student모델의 getName()의 값이 초기 값으로 세팅되고, 이후에 submit을 하면 setName()이 호출된다. 언제나 case 유의할 것! 처음에 모델을 포함해서 HTML을 렌더링 해주는 controller는 아래와 같이 사용한다. ``` @RequestMapping("/showForm") public String showForm(Model theModel) { Student theStudent = new Student(); theModel.addAttribute("student", theStudent); theModel.addAttribute("theCountryOptions", countryOptions); return "student-form"; } ``` HTML 코드는 이러하고 ``` <form:form action="processForm" modelAttribute="student"> Student first name: <form:input path="firstName"/><br> Student last name: <form:input path="lastName"/><br> <form:select path="country"> <form:options items="${theCountryOptions}"/> </for...

2020.04.25 TIL 스프링 - XML 없이 Configuration 하기

## Configuration 클래스 작성 1. Create java class with @Configuration, @ComponentScan annotation @Configuration @ComponentScan(PACKAGE_NAME) public class MyConfig {} 2. Load Config class context at main file. main { AnnotationConfigApplicationContext context =   new AnnotationConfigApplicationContext(MyConfig.class); } ## Bean도 SpringContainer Config안에서 만들기 1. Config Class에서 @Bean annotation으로 바로 Bean을 주입할 수 있다. - 사전에 필요한 사항은 Bean 클래스가 구현할 인터페이스, Bean 클래스이다. @Configuration public class MyConfig() {   @Bean   public Something something() {     // 이 때 MySomething이 Bean으로 동작할 클래스로, Something을 구현하고 존재하고 있어야 함.     return new MySomething();   }   @Bean   public Another another() {     // 이 때 MyAnother Bean은 something을 inject 받는 Bean이다.     return new MyAnother(something());  //   } } ## Full Code ``` Main public class SwimJavaConfigDemoApp { public static void main(Stri...

2020.04.24 TIL 스프링 - Bean Scope Detail with Annotation

Bean은 특별한 지정 값이 없으면 언제나 싱글톤으로 만들어진다. https://everupgrade.blogspot.com/2020/04/20200408-bean-lifecycle-annotation-bean.html 그런데 이 설정을 굳이 xml이 아닌 Bean Class에서 편하게 할 수 있다. ``` @Component @Scope( singleton(default) or prototype(매번 새로운 객체 생성) or global(용어는 확실치않음. flask g처럼 동작 등 ) public class Bean... (대충 bean 클래스) ``` init, destroy hook도 마찬가지이다. ``` @Component public class Bean... (대충 bean 클래스)     @PostConstruct   public String initMethod() {..대충 bean 함수}   @PreDestroy   public String destroyMethod() {..대충 bean 함수} ``` 주의사항 prototype은 PreDestroy Annotation이 동작하지 않는다. 다른 Scope들은 모두 관리가 되는데 prototype은 스프링 컨테이너가 생성까지만 관여하고 destroy는 관여하지 않는다. 만약 prototype bean에 destroy 훅을 달고 싶으면 Bean이 DisposableBean interface를 구현하고 해당 인터페이스가 제공하는 destroy() 함수를 구현해야한다고 한다. 참고소스:   destroy-protoscope-bean-with-custom-processor.zip

2020.04.22 TIL 스프링 - AutoWiring(2), Qualifier

Bean Inject하는 방법은 3가지가 있고 아래와 같다. 1. Constructor Injection @Component public class NewCoach implements Coach {         private FortuneService fs;     @Autowired public NewCoach(@Qualifier("sadFortuneService") FortuneService fortuneService) {}; @Override public String getDailyWorkout() { // TODO Auto-generated method stub return null; } 2. Setter Injection @Component public class NewCoach implements Coach {         private FortuneService fs; @Autowired public String setFortuneService(FortuneService fs) {                 this.fs = fs; } 3. Field Injection @Component public class NewCoach implements Coach {         @Autowired         @Qualifier("happyFortuneService")         private FortuneService fs; Private 필드에 @Autowired를 붙여서 자동으로 Bean을 주입하고 사용하는 방식은 혼자 자바, 스프링 공부하는 내내 사용했던 문법인데 ...

2020.04.15 파이썬 - Shelve

파이썬 Built-in에 이런 모듈이 있는것을 처음 알았다. import shelve class CustomClass: def __init__ ( self , value): self .value = value def __repr__ ( self ): return f'<class: { self .__class__. __name__ } >' with shelve.open( 'test.db' ) as f: f[ 'my_int' ] = 100 f[ 'my_float' ] = 100.555 f[ 'my_str' ] = 'hello world!' f[ 'my_dict' ] = dict ( hello = 'world' ) f[ 'my_custom_class' ] = CustomClass( 'MyCustomClass' ) with shelve.open( 'test.db' ) as f: print (f[ 'my_int' ]) print (f[ 'my_float' ]) print (f[ 'my_str' ]) print (f[ 'my_dict' ]) print (f[ 'my_custom_class' ]) print (f[ 'my_custom_class' ].value) $ 100 $ 100.555 $ hello world! $ {'hello': 'world'} $ <class: CustomClass> $ MyCustomClass 이렇게 파이썬 객체들 중 picklable 한 객체들은 모두 파일에 저장해둘 수 있고, 불러올 때도 모두 깔끔히 ...

2020.04.14 처음부터, 스프링 - AutoWiring

@Autowired가 붙어있는 field가 있다면 자동으로 Component로 등록해 둔 클래스들 중에서 그 클래스를 찾은 뒤 Inject 시켜준다. 만약 Component로 등록 된 클래스가 하나라면 그 클래스만 무조건 Inject하게 된다. 클래스가 여러 개인 경우는 아직 안 배웠는데 적절히 Config 해줄 수 있는 듯 하다. @Autowired까지 써보니까 이제 DI가 어떤 부분이 크게 다른지 느낌이 조금은 온다. 파이썬, 플라스크 같으면 Class를 선언하고, 해당 클래스를 초기화 할 때 혹은 초기화 한 뒤 필드 값을 set하는 방식을 주로 사용할 것이다. 반면에 Spring은 Bean을 미리 초기화, 조립해서 만든 뒤에 실제 코드 실행부로 넘겨준다. Spring의 Bean은 파이썬에서 모델과 비슷하게 이해할 수 있을 것 같다. 이 방식의 장점은 매 번 필드값을 수동으로 설정하지 않더라도 쉽게 값을 set/get할 수 있다는 것과 모델의 생성 책임을 스프링이 져준다는 것인 것 같다.

2020.04.09 처음부터, 스프링 - Bean의 LifeCycle, Annotation으로 Bean 만들기

<Bean의 속성, 간단하게> Spring에서 생성하는 Bean은 기본적으로 싱글톤으로 동작한다. 만약 Bean을 싱글톤이 아닌 다른 방식으로 생성하고 싶으면 scope를 수정해주면 된다. scope에 사용할 수 있는 value는 singleton(기본), prototype(매번 새로운 객체가 생성됨) 이 있고 그 외에 HTTP request에 binding 하거나 HTTP 세션에 globally하게 반영할 수도 있다. (마치 flask의 g처럼) 그리고 Bean에는 init-method, destroy-method를 통해 hook도 등록이 가능하다. 객체의 생성과 종료 시기에 불려지는 함수이다. 주의할 것은 scope이 prototype이라면 bean은 destroy 훅이 동작하지 않는다. prototype의 bean에 destroy 훅을 걸고 싶다면, 새로운 인터페이스와 클래스를 만들고 Bean 클래스에서 해당 인터페이스를 구현하고 블라블라 하는 방법이 있는데 이거는 필요할 때 찾아보면 될 것 같다. <Annotation을 이용한 Bean 사용> 복잡하게 XML에 미리 모든 Bean을 써놓지 않고, 클래스에 Annotation을 주는 것만으로 해당 클래스가 Bean으로 동작하게 할 수 있다. XML에 설정할 것은 딱 하나이다. component를 스캔할 base-directory 지정하는 것. base-directory와 그 하위 폴더들까지 모두 탐색하며 컴포넌트 Annotation이 붙은 클래스를 찾고 그들을 모두 Bean으로 사용한다. 코드 예시를 보면, 아래처럼 @Component만 주면 tennicCoach가 자동으로 bean id가 되고 @Component("MyTennisCoach") 처럼 ID를 직접 명시할 수도 있다. @Component public class TennisCoach implements Coach { @Override public St...

2020.04.08 처음부터, 스프링 - DI

DI, Dependency Injection 1. Define the dependency interface and class. 2. Create a constructor in class for injections. (일단은 xml로 bean을 관리하는 방식만 배운 상태이다.) 먼저 XML에 모델(Bean)을 선언한다. 모델에서 사용하고자 하는 다른 클래스(혹은 다른 모델)가 있다면, 모델의 생성자에 다른 클래스를 추가한다. 그러면 모델을 초기화할 때 그 모델의 생성자에 추가해 둔 다른 클래스의 메소드를 사용할 수 있게 된다. 강의에서는 이해를 돕기 위해 dependency=helper라는 문구가 자주 나왔다. 거창하게 번역하면 의존성 주입인데, 앱에서 모델을 만들어서 사용하는 것이 아니고 Spring Container가 만든 채로 모델을 전달하는 방식이라고 생각하면 될 것 같다. 파이썬으로 치면 class A의 생성자가 class B의 메소드를 사용하기 위해, A의 생성자에 class B를 인자로 전달해서 실행하는 방식과 같다. 확실히 특이하긴 한데 아직까지 크게 효용성이 느껴지지는 않는다.

2020.03.16 Multiprocessing의 map_async, apply등 나머지

Multiprocessing에서 map 함수의 불편한 점은 2개 이상의 인자를 취하는 함수를 사용할 수 없다는 것이다. 예를 들어 pool.map(func, [(10, 20)])을 하면 func의 첫번째 인자로 10, 두번째 인자로 20이 들어가기를 기대하지만 막상 실행해보면 그냥 첫번째 인자에 (10, 20) 튜플이 들어가게 된다. 이 땐 multi-argument를 accept 하는 함수로 starmap을 사용할 수 있다. map_async callback과 error_callback을 인자로 받을 수 있다. Non-block 방식이기 때문에 프로세스에게 일감을 부여하고 바로 다시 메인 쓰레드로 제어권이 돌아온다. 제어권이 돌아오고 다른 프로세스들은 job을 열심히 돌릴텐데, 이 때 job의 결과물이 모두 반환되면 실행할 callback을 정의할 수 있다. 각 프로세스별로 실행한 함수의 return값을 모두 모아서 callback의 인자로 넘겨준다. 따라서 callback을 정의하여 어디에 notify를 해주던가, 알려주던가 하는 방법이 있다. 완료 되었을 때 callback을 넘겨줄 수 있기 떄문에 후처리를 해줄 수 있다. 이를 확인할 수 있는 함수는 get, wait, ready, successful     def callback(res):         print(res)     pool = multiprocessing.Pool()                       # 현재 PC의 CPU 코어가 12개이다.     a = pool.map_async(calc, range(21, 26), callback=callback)     print(a.ready())     print('Blo...

2020.03.06 EC2에서 계산작업을 돌리는데 속도가 매우 느리다면?

최근에 ec2에서 계산 작업 돌릴 일이 있어 사이즈가 있었다. AWS RDS + AWS EC2를 사용하고 사이즈는 둘 다 거의 최소 사이즈였다. EC2에서 명령어를 실행하면 실시간으로 콘솔에 로깅을 하면서 실시간으로 작업 현황을 보여주도록 해놨는데 어떨 때는 잘 되다가 또 어떨때는 엄청나게 느려지는 경우가 있었다. 어제는 실행을 시켰더니 속도가 매우매우 느렸었는데 원인은 swap 메모리 사용이었다. RDS의 메모리 사이즈가 작아서 내가 불러오려는 쿼리의 총 메모리 용량보다 작았고 그로 인해 SWAP 메모리를 20메가 이상으로 사용한 흔적이 있었다. 이 때 RDS의 사이즈를 늘려주는것도 방법이지만, 그게 여의치 않을 때는 쿼리를 수정해야한다. SQLALCHEMY를 사용한다는 가정하에, 쿼리 수정은 아래와 같은 방법으로 할 수있다. 먼저 query를 호출하면 .all()을 호출하던 그렇지 않던 메모리에 한꺼번에 result set을 올려두는 듯하다. 그러면 당연히 메모리를 많이 차지하는데 어차피 한번에 계산을 하지도 못하기 때문에 필요한만큼만 불러와서 사용할 수 있도록 한다. 간단한 방법은 Query.yield_per() API를 사용하는 것. yield_per()의 인자로 받는 integer가 한번에 불러올 레코드의 갯수다. 총 레코드가 10만개였는데 만약 yield_per(1000)로 1000개씩만 불러오면 당연히 메모리 사용량은 감소할 것이다. 단 yield_per()를 사용할때는 주의할 점이 있다. eager_loading이 된 object들은 yield_per()를 사용할 수 없다. 따라서 joinedload 옵션을 사용하는 쿼리는 바로 사용할 수가 없고,  selectinload로 변경해서 사용해야 yield_per()를 사용할 수 있다고 한다. 왜인지는 좀 더 찾아봐야 하고 일단은 메모만 해놓는다.

2020.02.18 구글 API 사용시 주의할 점.

먼저 Google CloudPlatform에 프로젝트가 생성되어 있어야 하는데 튜토리얼을 따라가다보면 자동으로 생성이 되어있다. 예를들어 https://developers.google.com/sheets/api/quickstart/nodejs   여기 nodejs 튜토리얼을 그대로 따라해주면 되는데 enable 버튼만 누르면 (Project가 없을 때는) 자동으로 Project가 생겨서 나중에 다시 하려고 하니까 헷갈리는 부분이 있었다. 그 외에는 그냥 튜토리얼을 따라가면 되었다. 토큰 바꾸려다가 뻘짓을 많이 해서 참고차 남긴다.

2020.02.17 Python의 multiprocessing 중 Pool.map(), chunksize에 관한 내용

먼저 동시성에 대한 개념, 쓰레드, 프로세스, 비동기에 대한 내용은 알고 있다고 가정하고 실제 코드 사용법에 대해 적어두었습니다. * Pool.map()  def _map (): pool = multiprocessing.Pool() pool.map(summing , [ 10_000_000 + i for i in range ( 5 )]) pool.close() pool.join() # optional (하단에서 설명) 위에서 볼 수 있듯이 map() 함수는 - Python의 빌트인 함수 map처럼 인자로 실행할 함수, 인자(iterable) 를 취한다. - 프로세스에게 함수와 iterable의 인자를 분배하고 각 프로세스가 그 함수를 처리하도록 한다. 사람 언어로 표현하면 일감을 처리하는 방법과 일감에 필요한 재료를 각 일꾼에게 분배하는 것이라고 생각하면 된다. - pool을 생성하면 최초에 프로세스의 개수를 지정하거나 위 예시처럼 비어있도록 둘 수 있는데 그냥 비어있도록 두는 경우에는 현재 코드가 돌아가는 machine의 CPU core 갯수만큼의 process가 생성된다. * 예시) 3곳의 레스토랑에 전화해서 예약을 하려고 하는데 직원 3명(프로세스 3개)에게 이를 시키는 상황을 코드로 표현하면 아래와 같다. def call_restaurant (phone_num): print ( f'Calling { phone_num } to make a reservation!' ) def make_reservations (): pool = multiprocessing.Pool() pool.map(call_restaurant , [ 1 , 2 , 3 ]) # 전화번호는 귀찮으니 1,2,3이라고 가정했다. pool.close() 1) A에게 (전화해서 식당 예약하기, 전화번호1) 2) B에게 (전화해서 식당 예약하기, 전화번호2) 3)...

방통대 2019-2학기 수강내용 정리 <자료구조>

한 학기를 마친 지금, 시험에 목 메지 않고 나의 실력 향상을 위해 학교를 다니자고 다짐한 내 결심을 이행하기 위해 한 학기동안 배운 내용을 정리하고자 한다. 1. 배열 - 여기서 말하는 배열이란 순수한 동적크기의 배열이다. 배열의 모든 원소들은 메모리에 다닥다닥 붙어서 올라간다. 어렵게 이야기 하자면, 메모리에 적재되는 물리적인 위치가 연속적이다 라고 하는 것이다. 이는 공간적 지역성의 원리라고도 한다. 공간적 지역성이란 방금 접근한 메모리 주소에 또 접근할 가능성이 높고 그에 인접한 원소들도 접근할 가능성도 높음을 의미한다. 배열의 공간적 지역성은 탐색을 할 때 그 빛을 발한다. 배열 a=[1,2,3,4,5]를 저장한다고 하면 a의 각 원소들은 모두 메모리 주소에 차곡차곡 순서대로 저장된다. 따라서 배열에 있는 값들은 순회하며 꺼내려 한다면 처음 1을 찾은 메모리 주소에서부터 더 멀리 찾을 필요도 없이 순서대로 꺼내기만 하면 되므로 탐색이 쉽다. 하지만 단점은 데이터의 삽입과 삭제가 일어날 때이다. 만약 배열에 원소를 5개 넣고 싶고 각 원소는 메모리 주소를 1칸씩 차지하면, 우리는 최소한 메모리가 5칸이 되는 곳을 찾아서 그곳에 저장해야한다. 메모리 중간중간에 3칸, 4칸이 비어있어도 이를 활용할 수가 없다는 단점이 있다. 또한 이미 원소가 4개인 배열이 있을때 이 배열의 중간에 값을 추가하고 싶다면 이를 위해 배열 전체를 다른 메모리주소로 옮겨야한다. 그렇지 않으면 배열의 특징인 공간적 지역성이 유효하지 않기 때문이다. 이 때문에 배열에 값이 많아질수록 삽입과 삭제는 부담스러운 연산이 되며 성능 또한 좋지 않게 된다. 2. 연결리스트 - 배열과 가장 잘 비교 되는 자료구조일 것이다. (사실 배열과 연결리스트는 어느 자료구조 커리큘럼이나 가장 초반부에 설명하고 있기 때문에 꽤 많이 봐와서 방통대 강의보다는 그 내용을 바탕으로 이 글을 쓰게 되는게 아닌가 싶다.) 연결리스트는 배열과 달리, 원소들이 메모리에 적재되는 물리...

방통대 컴퓨터과학과 2019-2학기 자료구조 수강 후기

자료구조 2019-2학기 수강 교수: 정광식 교수님 꽤 만족스러운 강의였습니다. 저는 경영학과 출신에 프로그래밍 학원도 안 가고 독학으로 개발자가 된 케이스라 기본기가 많이 부족한 상태였는데요. (물론 지금도 어렵습니다) 인터넷에서  '비전공자들의 발목을 잡는 것은 결국엔 기본기' 라는 이야기를 많이 보곤 했었고 이에 압박감을 느껴 기본기 중 기본기라고 불리는 자료구조를 고민없이 수강했습니다. 일단 방통대 자료구조 강의는 2019년에 새로 촬영이 된 것 같습니다. 정광식 교수님의 예전 강의도 같이 볼 수 있어서 2016년 버전 강의를 1개 정도 아주 짧게 들었는데 개인적으로는 2019년에 새로 촬영하신게 더 좋았습니다. 2016년 버전은 책 내용 설명, 코드 설명이 위주였던 것 같은데 2019년 버전은 책과 코드보다는 개념과 흐름(?) 같은 것을 좀 더 짚어주신 거 같습니다. 교수님 본인도 강의 중간중간 이번에는 예전보다 본인이 좀 더 하고 싶은 이야기를 많이 하려고 한다고 하셨었구요. 그래서인지 강의하다가 텐션이 막 오르실 때가 보입니다. 부담스러운 정도는 아니구요. 집중해서 들을 수 있는 느낌이라 저처럼 책 읽어주는 남자 스타일을 싫어하는 학생들은 좋아할 것 같습니다 . 강의는 다루는 자료구조에 대한 대략적인 설명과 삽입, 삭제, 탐색을 하는 경우에 동작방식, 그리고 거기서 파생되어 나온 자료구조를 설명하는 식으로 강의하십니다. 강의 목차는 자료구조 별로 나누어져 있기 때문에 끊어서 듣기 좋습니다. 예를들면 1장 배열, 2장 연결리스트, 3장 트리 뭐 이런식으로 되어 있는거죠. 시험 난이도는 평이합니다. 많은 분들이 책, 워크북이 필수이고 거기에 나오는 연습문제 무조건 풀어야 셤 잘보는 것 처럼 이야기 하시는데 저는 돈 아까워서 책, 워크북 다 안 샀습니다. 왠지 방통대에서 판매하는 책들은 왠지 사기가 싫어서;; 책 없어도 충분히 가능합니다. 기출문제 잘 푸시고 강의만 잘 들으셔도 A+급 성적...

2019.12.10 방통대 컴퓨터과학과 첫 학기를 마쳤다.

비전공자로서 기본기에 늘 압박이 있던 나는 올해 2학기부터 방통대를 다니기 시작했다. 회사 다니면서 공부하기는 빡세지만 도움이 된다는 후기가 많아서 큰 고민없이 등록했다. 그리고 9월부터 시작 된 학기. 오랜만에 다시 대학생 신분으로 돌아갔다. 강의를 듣고 시험을 치고 평가를 받는다. 이것저것 듣고 싶은 과목들을 수강신청하고 새로운 것을 배운다는 것에 들떴다. 학기 초엔 꽤 신나게 시작했지만, 곧 빡세다는 사람들의 말을 온몸으로 이해할 수 있었다. 수강신청을 할 때 여러 과목이 있었는데 이미 알고 있는 것들을 또 듣고 싶지는 않아서 도움이 될 것 같거나, 아니면 나중에 먼 미래에 써먹을 수지도 모르는 생소한 과목들도 신청했다. 하지만 그렇게 신청한 과목들은 생소하고 어려웠다. 그리고 교수님들은 신입생 혹은 편입생의 텐션과는 달랐다. 나야 오랜만에 다시 대학생이 되어 어쩌면 처음으로(?) 학교에서 내가 하고 싶은 공부를 하는 것인데 교수님들에겐... 강의란 그냥 업이다. 열정적으로 강의하는 교수님도 있었지만 1부터 10까지 강의노트를 읽어주는 교수님의 수업은 이해하기도, 그냥 듣고 있기도 힘들었다. 그래서 '이번에 다니는 학교만큼은 성적에 목 메고 다니지 말아야지' 했는데 후반부엔 그 결심이 무색하게 점수에 연연하는 나를 다시보게 된 것 같다. (사실 과락은 면하자는 마음가짐이었는데 장학금을 받게 되어서 꽤 좋았다. 2만원짜리이긴 하지만 ㅋㅋ) 어쨌든 결론적으로 방통대 편입생의 1학기는 무사히 지나갔다. 조금 더 열심히 할 수 있었을텐데 라는 아쉬움도 남지만, 그래도 이 정도면 한 학기에 6전공을 들으며 자바스크립트 유데미 강의까지 듣고 꽤 열심히 하지 않았나 싶다. 수강했던 과목들에 대한 후기는 하나, 둘씩 올릴 예정이다.