Posts

[시원스쿨 독일어 후기] 끝장패키지 수강 1주차

Image
본 포스팅은 실제 구매한 강의에 대한 후기이며, 시원스쿨 독일어 열공챌린지 참여를 위한 포스팅 입니다. 독일어를 공부하게 된 동기 큰 마음을 먹고 시원스쿨 독일어 끝장패키지를 수강했다. 독일에서 일을 하고 있지만, 나는 독일어를 전혀 할줄 모른다. 고등학교 제2외국어도 아니었다. 업무 및 동료들과의 모든 의사소통을 영어로 하고 있다. 하지만 독일에 사는데 독일어를 전혀 못하는건 살아는 지지만 불편한 일을 종종 겪게 된다. 그리고 독일어를 들을수도, 말할수도 없는 순간들은 보통 당황스러운 순간들이다. - 마트에서 물건을 다 결제해서 나오는데 보안탐지기가 갑자기 울린다. - 기차 올 시간이 지났는데도 기차가 안와서 불안한데 안내방송이 독일어로 흘러나온다. - 점심시간같이 업무가 아니면 독일인 동료들끼리는 독일어로 이야기를 하는데 소외감을 느낀다. 그래서 처음엔 유튜브와 블로그들을 통해 독어를 공부해보려고 했다. 하지만 오래 가지 않았다. 어떤 기본지식도 없는 상태에선 길잡이가 되어줄 무언가가 필요하다고 생각했다. 시원스쿨 독일어를 선택한 이유 새해엔 독일어를 한번 시작해보자! 라고 결심을 했다. 처음엔 올해 A1, 혹은 가능하면 A2 를 따는게 목표라고 생각했다. 막상 시작하려니 욕심이 생겨서 B1 은 어떤 느낌일까 궁금해지기 시작했다. 언어라는게 하루아침에 되는게 아니고, 독일어는 정말 완전 기초부터 시작하는데, 1년정도는 목표를 잡고 해야 뭔가 이룰 수 있을것 같았다. 자격증이나, 어떤 시험에 의해서가 아니라 정말 언어를 배우고 잘하고 싶기 때문. 독일어 인강을 검색어로 구글링을 했을때 여러가지 학습 사이트들이 나왔다. 그러다 시원스쿨 끝장패키지 할인에 눈길이 갔다. 무엇보다 1년동안 수강할 수 있고, 전 과정을 학습할 수 있으며, 할인까지! 게다가 몰랐는데, 신규 가입 회원에겐 24시간 무료 수강권을 준다. 신규 가입하면, 24시간동안 모든 독일어 강의를 들어볼 수 있는 것이다. 이때 이것저것 들어보며 나에게 맞는 수준의 강의가 어떤건지 결정을 할 수 있었을...

프로젝트를 진행할때 반드시 읽어볼 것(시작할때, 중간중간 매일 일할때도)

성장을 해야한다. 시간이 지날수록, 경력 기간이 늘어날수록, 실력도 증가해야 한다. 단순히 시간이 지난다고 해서 실력도 발전하진 않는다. 여태까지 그랬다. 시간을 어마어마하게 쏟아부으면, 당연히 없던 실력에선 어느정도 발전이 있을수밖에 없지만. 어느새부턴가 단순반복이 되어버리면, 배움도 없고 발전하지 못한다.   회고의 중요성 실력이 증가하려면 시간과 경험이 일단 쌓여야하지만, 무언가 일단락 되었을때 되돌아봐야만 한다. 늘 언제나 there is a room for an improvement 이다. 언제나 항상. 그리고 여태까지 나는 이  과정이 없었기 때문에 더 발전하고 고칠 수 있었음에도 불구하고 잘못을 답습해왔다. 실수도 반복되면 실력이라고. 내가 더 발전하지 못한 가장 큰 이유중 하나는 회고하고, 되돌아보고, 복기하지 않는다는 것이다. 의미있는 회고가 되려면 제일 중요한건 시작하기 전에 계획이 있어야 한다. 계획이 없이 열심히만 했으면. 회고할때 뭘 잘했고 뭘 잘못했으며 다음번에 다시하게 되면 어떻게 더 잘 할수 있을지를 파악하지 못한다. 그저 그 순간순간 밤새 열심히 했다, 밖에 남지 않아버리면. 다음에도 똑같이 반복할 수밖에 없다. 계획을 잘 짜려면 프로젝트 특성상 deadline 단위로 끊을수밖에 없다. 계획이라는게 결국은 일정관리아닌가. 언제까지 뭘 하겠다가 큰 그림이고. 그럼 backward 로 잘라가면서 milestone 별로 break down 해야한다. 그렇게 언제까지 뭐가 되고, 언제까지 뭐가 되고가 나온다. 그럼 나중에 프로젝트다 끝나고 나면 일정 을 짤때 놓친 부분이 나오고, 다음번 프로젝트에 이를 고려한 일정을 계획할 수 있다. 개발이 다가 아니다 아직까지 고치지 못하는 버릇. 내 부분만 하면 끝난다는 생각. 나머지는 신경도 안쓰고 무책임해버린다. 서버개발은 되었어도 프론트가 안되었으면 테스트를 할수 없다. 개발 자체가 물론 중요하고 개발이 안되면 프로젝트가 망하지만. 일정과 전체적인 진행상황, 일을 제때 제대로 되...

Hibernate cache 에 대해서. 그리고 merge, refresh

 우선 Hibernate 는 1차, 2차 cache 를 제공한다.  1차는 기본적으로 default enabled 되어 있다. 임의로 disable 시킬 수 없다. session 별로 caching 이 유지되며, session 이 close 되면 이에 따라 cache 정보도 날라간다. 2차는 기본적으로 disabled 되어 있다. sessionFactory 단위의 caching 이기때문에 모든 session 에 적용이 된다. Hiberante 자체에서 제공하는게 아니고, ehcache 등 제 3의 memory cache 를 provide  해줘야 하는 모양이다. 그럼 DB 에 임의 로 접근해서 정보를 바꾸거나 지워버리면, Hibernate cache는 어떻게 될까? 이 외부적인 요인에 의한 변경을, hibernate 가 알 방법은 없다.  그렇기 때문에 cache 가 업데이트 되지않는다. merge 혹은 refresh  를 해줘야 하는데, merge : 현재 session entity 가  가지고 있는 데이터를 DB 에 쓴다.  refresh : 현재 DB 에 있는 정보를 session entity 로 가지고 온다. 혹은 기존 session 들에 대해서  아래와 같이 evict  를 호출함으로써, entity 가 다시 불려질때 query 를 통해 최신 정보를 가져오게 할 수있다. org.hibernate.Cache.evictAllRegions() 참조링크 https://howtodoinjava.com/hibernate/understanding-hibernate-first-level-cache-with-example/ https://stackoverflow.com/questions/2461063/how-to-clear-all-hibernate-cache-ehcache-using-spring

EnumMap vs HashMap, 그리고 InteruptedException

회사 동료의 코드리뷰 중 HashMap 을 EnumMap 으로 바꾼 부분을 보고 찾아봤다. EnumMap 은 사실 처음보는거 같은데 . JavaDoc 에 의하면 Enum maps are represented internally as arrays. This representation is extremely compact and efficient. Implementation note: All basic operations execute in constant time. They are likely (though not guaranteed) to be faster than their HashMap counterparts. 이라고 한다. JavaDoc 에서 extremely compact and efficient 라고 표현을 하다니. Map 의 K,V 에서 Key 부분의 타입이 Enum 인 경우에는 반드시 EnumMap 을 쓰도록 해야겠다.

168. Excel Sheet Column Title

난이도는  Easy 인데, Acceptance 는 32% 여서, 뭐지 하고 봤다. 처음엔 쉽게 봤는데, 결국 못풀었다. 26진수나 마찬가지라고 생각해서, % 와 / 연산을 사용했는데. 접근이 비슷하긴 했는데 아주 틀렸다. 문제에서 주어지기로는 A -> 1 B -> 2 C -> 3 ... Z -> 26 AA -> 27 AB -> 28 이런식으로 주어졌다.  문제는, 26진수라고 했을때, 1에서 26까지 가는걸 A 에서 Z 까지 간다고 생각할 수는 있는데,  0이 없다.  10진수의 경우, 0부터 시작해서 9까지 간 다음, 10 으로 가는데. 이건 시작이 1이다. 일반적인 26진수라면  0 -> A 1 -> B 25 -> Z 26 -> BA (= B*26+A*1) 27 -> BB (= B*26+B*1) 이런식으로 간다. 그런데 위의 경우에는 1 -> A 2 -> B 26 -> Z 27 -> AA (= A*26+A*1) 28 -> AB (= A*26+B*1) 이와같이 움직였다. 1,2,3,... 9 다음에 10이 아닌 11이 오는거나 마찬가지인 셈이다....? 음.. 모르겠다. 설명을 봐도. 이해를 못하겠다. 일단 패스.  https://leetcode.com/problems/excel-sheet-column-title/discuss/441430/Detailed-Explanation-Here's-why-we-need-n-at-first-of-every-loop-(JavaPythonC%2B%2B)

901. Online Stock Span

이전에 비슷한 접근법을 요구하는 문제가 있었는데, 그 기억대로 접근해서 한번에 해결. 무식하게 매번 전체 array 를 search 할수도 있는데 그러면 Time limt exception 이 뜰거라고 생각했다. 그런데 그렇게 해서도 accept  가 된 솔루션이 있어보이긴 했지만 아무튼. 요지는 두  array 를 관리 하면서, 현재  price 와 span 을 기록하는데, 현재를 기준으로,  현재보다 이전 날짜의 span 은 그 날보다 가격이 같거나 작은날이 며칠인지를 이야기해주고 있으므로, 하루씩 back 할 필요 없이, 이 span 만큼 건너뛰어서 체크를 할수 있다. 물론 index outOfBound 는 피해야 한다. 처음 submit 할때는, 계산하는 함수를 따로 만들어서 뺐었는데, 그랬더니 32ms 가 나왔다. 가장 빠른 성능은 17ms 여서 뭔가 하고 봤는데 내 접근이랑 똑같은데 함수 호출만 없는거였다. 그래서 나도 private 함수로 뺀 부분을 그냥 합쳤더니 17ms 가 나왔다.  보통 이런 함수 호출이 성능에 그만큼 큰 영향을 주나 싶지만, 주어진 조건에 테스트케이스당 최대 만번의  호출을 하고, 전체 테스트케이스 합산시 15만번의 호출까지 한다고 하니. 함수스택 한번 들어갔다 나오는게 늘어나는만큼 유의미한 차이가 있긴 있었나보다. 그래봤자 15ms 가 일반적으로 쉽게 인식 가능한 범위는 아니지만. 아래의 calculateNewSpan 이 문제의 그 추가적인 함수 호출이었다. class StockSpanner { private int [] priceArray ; private int [] spanArray ; private int count ; public StockSpanner () { priceArray = new int [ 10000 ] ; spanArray = new int [ 10000 ] ; count = ...

547. Number of Provinces

한번에 풀지 못했고, intelliJ 를 통해 디버깅을 해야만 했다. 하지만 그렇게 해서라도 해결은 했다.  일단 첫번째 문제는,  정사각형 매트릭스에서 대각선은 전부 1 이기 때문에 대각선의 반쪽만 확인하면 될거라고 생각했는데, 맨 위 row 나 i맨 아래 row 같은 경우는, 맨 왼쪽 혹은 맨 오른쪽에서 시작해야만 자신의 connected node 를 가져올 수 있다.  그래서 0부터  iteration 을 도는데, visited 정보를 따로 관리 하지 않으면 이게 이미 빠진 건지 아닌지를 알 방법이 없다. 그래서 다시 무한루프에 걸렸었다.  visited 를 이용하니 해결. 성능은 좋지 않다.  4ms  였지만, 25% 일단 나의 접근은 set 에 전체 노드를 집어 넣어놓고 꺼내면서, 연관된 node 들을 다 꺼내는 priority queue 를 관리하는 것이었다. 그래서 기존의  set 이 empty 가 되면 종료. 일단 내 접근에서 문제점은, 쓸데없이 PQ 를 썼다는 것이다. 아무이유 없이. 그냥 Queue 를 썼어도 되었었다. 그리고 실제  node 들을 마치 당구공을 주머니에서 꺼내서 다른 주머니에 넣듯이 했는데. HashSet 으로 visit  을 관리할 필요가 전혀 없이, boolean[n] visited 만으로도 충분했다. 그래서 처음부터 각 node 를 Set 에 넣을 필요도, visited 를 set 에 넣을 필요도 없었다. DFS 로도 접근할 수 있는데, 이렇게 접근한 어떤이의 해결법은 다음과 같다. 아래 풀이를 보고 있자면 사실 그렇게 복잡할 필요도 없었겠다는 생각이 든다. public int findCircleNum ( int [][] isConnected) { boolean [] visited = new boolean [isConnected. length ] ; int provinces = 0 ; for ( int i = 0...