greatkit
227
2014-10-12 00:15:53
52
6553

프로젝트 하는 얘기


하라는 일은 PM인데 개발도 하라 해서 개발도 하니 프로젝트는 역시나 산으로 가는군요.
애초에 설계도 다 하긴 했지만…

JAVA는 기본이고 php, python으로 된 것도 만지다 보니 재미는 있네요. 죽기보다 싫은 js는 다행히 안 만지고 있지만 곧 만지게 될 지도…

나름 개발자 하나 좀 키워 보려고 vert.x로 해야 하는 뭔가를 던져 줬더니 로깅하는 것을 설정파일로 안 하고 직접 로거 클래스들 생성자 호출해서 작성하는 놀라운 신공을 보여줄 줄이야… -,.-;
동기/비동기 지식은 있는 것인지 10년 가까이 일했다는 경력 년차 대비 실력이 무척 허접스러워 실망. 서버 사이드 비동기 처리와 클라이언트 사이드 비동기 처리의 차이점도 이해를 못 해서 ajax로 하면 될 것을 왜 어렵게 하려 하냐는 얘기를 할 때는 더 이상 할 말이 없어지네요. Ajax가 여러 사람 망친 듯.

그건 뭐 그냥 그러려니 할 수 있는데 태도 면에서 너무 짜증나게 굴어 살생부에 올림. 까분 댓가는 확실히 치르게 해 줄 예정이고 어차피 실력도 허접해 쓸데가 없음. 자아가 너무 강해 실력이 더 향상될 여지도 없어 보임. 그러면서 다른 개발자 하나를 자기보다 실력 없다고 무시하네요. 제가 보기에는 거기서 거기고 태도를 감안하면 그 못하다고 무시당하는 친구가 오히려 더 나은데. -.-;
(일례로 Queue를 써야 하는 곳에 ArrayList를 쓰고 get(0) 한 다음 remove(0) -,.-; 대체 이런 용감한 코드를 어떻게… 게다가 List xxx = new ArrayList 도 아닌 그냥 ArrayList xxx = new ArrayList… 오랜만에 코드를 보다 살의를 느낌. 그것 말고 도저히 인덱스를 탈 수 없는 기상천외한 sql where 조건문 구현으로 맛가게 만들어준 것도 있음.)

아무튼 그 인간이 망쳐놓은 vert.x에서 쓸모없는 스프링 스케줄러 걷어내고 절대 필요한데 전혀 해 놓지 않은 이벤트 트리거링 처리와 아이들 처리 구현 추가. 개판으로 구현해 놓은 로거 설정 다시 하니 그제야 모든 로깅 코드가 제대로 작동하기 시작.

Java건 php건 python이건 어째 제가 만지면 만질수록 코드량이 줄기만 하는지 알 수가 없군요.

어쨌건 프로젝트는 산으로 갔으니 PM인 저의 잘못.

그냥 대나무숲 삼아 넋두리 풀어놓고 갑니다.
내일(월요일)은 아무도 엄두를 내지 않는 파이썬 모듈 디버깅 예정.
0
  • 댓글 52

  • greatkit
    227
    2014-10-12 01:10:51
    // 머슴
    그럴지도 모르죠.

    이 쪽 상황 보지도 않고서 단정적으로 마구 쓰시는군요.
    그 쪽은 일 잘 하시나 보네요.
  • 머슴.
    722
    2014-10-12 01:11:39
    설계서가 은유적이고 모호한가봐요.
    중요사항이라 생각하는것을 명시하지 않고
    다양하게 해석하도록 배려를 했으니.
    프로그램 코딩하고 프러젝트하고는
    문제의 성격이 다르죠.
    우리모두가 실력이 조금 못해도
    잘할수 있는 sw공학적 개발환경에 대해 생각해 보시면 좋을듯
    언제까지 사람을 욕할건가요.
  • 머슴.
    722
    2014-10-12 01:15:19
    그 쪽 상황을 잘 모르죠.
    님이 pm이라서요 ㅎ
    우린 개발자 사람의 문제로만 생각하는 경향이 강해서
    그 사람이 느끼는 환경의 문제도 생각해봤으면 하는 취지랍니다.
    전 신입 사원 둘데리고 분석 설계 코딩 한적도 있는데
    환경을 만들어주니까
    경력사원 못지 않더군요.
  • greatkit
    227
    2014-10-12 01:20:46
    //머슴
    원 글은 왜 지우셨나요.

    말씀하시는 거 보니까 상당히 뛰어난 분이신 듯 하네요.

    저는 제 글에도 썼듯 제 잘못이라 했으니 더 할 말 없습니다.

    저도 신입 둘 데리고 분석 설계 코딩 잘 한 기억 나름대로 수두룩합니다.

    Logback 설정하는 것도 그 쪽이 이야기하는 설계서가 은유적이고 모호한 내용일 지 잘 모르겠군요.
  • 머슴.
    722
    2014-10-12 01:33:50
    오타 수정해서 올렸어요.
    님이 pm이여서
    더 많은 생각하라고
    올렸으니 기분 상해하지는 마세요. ㅎ
  • LaZyDev
    301
    2014-10-12 05:37:34
    원래 SI바닥이 경력대비 실력이 부족한 사람들이 많죠 -_=;;
  • smasma
    2k
    2014-10-12 10:22:10
    제 생각에는 글쓴님이 잘못하신거 같은데여.. 님 실력이 좋을지는 몰라도 님이 PM이라면 일을 팀원에게 부여했을때 본인이 생각하는 방향을 미리 공지했어야 합니다..
    구현에 대한 힌트 제공은 필수입니다..힌트를 제공하시고 합의점을 서로 맞춘후 일을 진행해야 나중에 님의 마음에 들지 않는 사태가 사라집니다..그리고 그건 성공적인 프로젝트 진행의 기본이구여.
    다른 사람 실력 탓하기 전에 우선 본인의 문제부터 보셔야 할꺼 같습니다.
  • 하늬바람
    503
    2014-10-12 10:55:35
    ArrayList를 써야 할지 Queue를 써야할지 정도를 설계서에 반영하는 것은 SI 환경에서 가능하지도

    않을뿐더러 개발자를 불행하게 만드는 설계서라고 생각합니다.

    더구나 10년차 개발자가 그 정도 수준이라면 PM을 맡고 계시는 greatkit님의 현 심정이 어떠하실지

    미루어 짐작이 갑니다.

    다만 이미 벌어진 일이니 마음을 차분히 하시고 끝까지 마무리 잘하시기를 권해드립니다.
  • 다시시작
    659
    2014-10-12 11:29:44
    10년을 해도 그보다 더했어도 자료구조 모르는 사람 수두룩하니 적당히 데리고 일할수도 있겠다
    생각하다가 원글을 다시보니 문제는 잘 모르는 사람이 자신이 아는게 많다고 생각하고
    남을 무시하는게 문제군요.
    모르면 가르쳐 주면 되지만 그런 성격의 사람은 같이 일하기 곤란하겠네요.
  • greatkit
    227
    2014-10-12 12:03:40
    //하늬바람, 이제다시2년차.

    제가 별로 잘 쓴 글이 아니긴 해도 제대로 읽어 주시는 분이 계시긴 계시는군요.

    감사합니다.

    그리고, 별로 상관없는 얘기지만 SI 아닙니다.
  • 아이스둔
    2k
    2014-10-12 12:09:31
    아침 티타임때나 주간회의때 생각하시던 설계,개발 방향을 말씀만으로라도 주지시켜주시는게 좋을 뻔했습니다.
    시간여유가 있으면 메일및 문서로 정리해서 주심 더 좋았겠지요.
    그래도 안 따라 오는 분들도 많지만요.

    남들의 나의 생각을 이해하고 같은 방향으로 가는게 참 쉽지 않습니다.
    뭐 저도 잘하진 못했고 많은 실망과 후회가 많은 사람중 하나입니다.

    아..창피한 얘기지만 전 처음에 뭐 모르고 PM,PL 했었지만 지금은 돈 많이 준다고 해도 절대 안합니다.. 현업들 및 다른 지원팀 사람들 내팀 개발자 들이 다 내 맘같지 않더군요..
    그냥 개발을 속 편하게 합니다.
  • greatkit
    227
    2014-10-12 12:25:08
    //어떻게 할까?
    말씀하시는 부분들 나름대로 저 또한 당연히 했습니다.
    그러나 개발자 한 명의 자아가 너무 강하더군요.
    (좋게 표현해서 자아지…)

    물론 저도 책임에서 자유로울 수는 없습니다. 어쨌건 PM이고 '적절한 조치'를 취하기에는 너무 늦어 버렸으니까요.
    (사실 대안도 없는 그런 상황이었고)

    구구절절 이야기할 수 없는 프로젝트의 독특한 여건도 있었는데 좀 민감한 문제들이라 얘기하기는 어렵고요. 위의 리소스 대안도 그런 측면 가운데 하나였고요.

    많은 분들 말씀 곱씹어 보며 최악인 가운데 수습 잘 할 수 있는 방법에 대해 고민해 봐야겠습니다.
  • 머슴.
    722
    2014-10-12 15:26:20
    si바닦에서는 처음에 사람보는 안목도 중요하죠. 그리고
    우리네들은 자신의 코드에 대해
    얘기하는 문화가 자연스럽지 못한거는 있어요.
    서로 실력을 키울수 있는 좋은 기회인데요.
    이점에 대해서는 글쓴님의 애로사항이 공감됩니다.
    전, 16000원 짜리 내돈으로 복어탕 사주면서
    코드 체크 했어요. 나중에는 덕분에 일 편하게 했다는 말을 하더군요.
    잘 풀어가시길 응원합니다.
  • ㅇㅇ
    1k
    2014-10-12 16:10:06
    그 사람의 실력을 모르고 일을 시키는건가요?

    그냥 10년차니 이정도? 는 하겟지... 싶어서 테스트겸 시키는건가요??

    일 좀 특이하게 진행하시는듯
  • 카트맨
    2k
    2014-10-12 16:58:51
    진짜 필요한 기술은 사람보는 안목인듯 합니다
  • 지붕뚫고높이차
    1k
    2014-10-12 17:57:31
    저도 같은 입장으로 일부 공감이 가는 내용입니다.

    선동렬 감독이 투수관리에 그리 뛰어나지 않는것처럼
    뛰어난 자신의 개발역량을 다른사람들이 따라오게 할때는 인내 또는 방관이 필요하더라구요.

    자아 강한 개발자는 PM의 능력으로 눌러 관리하던지
    리스크를 감수하더라도 퇴출하는것도 방법이구요.

    이 모든게 PM 이 사용할 시간을 개발에 투입되서 생긴 문제라고 생각됩니다.

    그런데 글내용중
    List xxx = new ArrayList 로 사용하는 개발자가 전 생각없이 보이던데
    어떤 이유때문에 그러는지 알려주시겟어요?
  • smasma
    2k
    2014-10-12 18:53:46
    List 는 인터페이스이기 때문이 아닐까여.. 나중에 arraylist가 아닌 커스터마이즈된 다른 구현체를 사용해야 할 사유가 생겼을 경우 선언부만 바 꿔주면 아래 코드에는 영향이 없기 때문이죠. 선언부에 인터페이스로 지정해주는건 좋은 습관이라고 생각합니다
  • 지붕뚫고높이차
    1k
    2014-10-12 21:18:35
    글쎄요.
    ArrayList 는 컬랙션 객체입니다. ArrayList 에서 재구현되거나 특화된 코드를 버리고
    추상화된 인터페이스를 사용하는건 개발 생산성에 그리 도움되지 않는다고 생각합니다.

    그리고
    나중에 Arraylist가 아닌 커스터마이즈된 다른 구현체를 사용해야 할 사유는 어떤 경우가 있을까요? 실제 예를 들어주시면 도움이 될것 같습니다.

    선언부에 인터페이스를 지정해주는건
    팩토리 패턴같은
    인터페이스 영역이 실제 구현체 영역을 커버할 때
    그리고 구현체 영역이 다수이고
    객체생성에 대해 자동화 할 수 있을때나 유용하지

    컬랙션 객체같은 유틸성 클래스에서 구현체 사용이 아닌
    인터페이스 지정은 나쁜 습관이라고 생각됩니다.

    그리고 글쓴분의 의견도 듣고 싶습니다.
    실제 인터페이스로 선언된 코드를 보면서 한심하다고 생각했는데

    그런 코드를 사용 안했다고 살의를 느낀다는 이야기가 무척 눈에 거슬렸거든요.

    (회사가 아니라서 List 를 구현한 클래스를 찾기가 힘드네요. 시간이 되면 댓글 좀더 보강해보겠습니다.)
  • narise
    2k
    2014-10-12 22:54:47
    ArrayList 는 컬랙션 객체라고 하는데.... 컬렉션의 구현(implements) 클래스죠.

    ArrayList xxx = new ArrayList() 라 되있으면 자바프로그래머라면 열받죠.

    인터페이스 List를 사용하지않고 ArrayList로 ArrayList만의 추가된 메소드를 써야하는 상황이 있을까요?
    그런 로직을 짜는게 잘못된게 아닌지요.

    경우에따라서 LinkedList쓸수도있고(삽입,삭제 빈번한 경우,성능향상을위해),

    ArrayList를 직접 참조하면, 자동완성 기능에서 쓰지도않는 메소드 잔득나오죠.

    단순히 타이핑문자열도 길어지고... 생산성 향상? 성능? 도대체 어떤 장점이 있는지요?
  • 2014-10-13 00:17:30
    ArrayList xxx = new ArrayList() 멤버 변수로 클래스 내부용으로만 소비 되면
    LinkedList 등으로 바꾸어서 쓸일이 거의 없을뿐더러 혹여 있다고 해도
    수정시 부담 별로 없습니다.
    하지만 클래스 외부에서 사용된다면 ArrayList xxx 선언보다는 List xxx 로 했을 경우
    LinkedList 등으로 바꿀일 없다고 해도 혹여 있다면 수정시 겁나게 수정을 해야지요.
    타 부서랑 현업을 해야 하는 SI 에서는 그야말로 환장할 일이 되기도 하기에 충분히 공감합니다.
    하지만 이것은 어디까지나 상황에 따라서 다를 수도 있고,
    ArrayList 를 변경해야할 상황은 성능 최적화 대상으로 선택되었을 경우 정도인데 희박합니다.
    ArrayList 최적화 대상으로 선택되기 희박한 이유는 자료 구조를 고려하여 add, get 이 주력일때 사용하기때문입니다. "지나가다" 님께서 예를 든 삽입, 삭제가 빈번할 경우 애초 ArrayList 를 선택하지 않는다 이말입니다. 물론 자료구조를 고려 안할 수 있고 구현한 초창기랑 달라질 수 있는 여지는 충분히 있습니다. 하지만 ArrayList 가 최적인 경우에도 List xxx = new ArrayList 를 고집해야 하나요?
    결론적으로 List xxx = new ArrayList() 권장이며 ArrayList xxx = new ArrayList() 라고 했다고 무조건 죽을 죄를 지었다고 생각할 필요가 없다 생각합니다.
  • fc
    1k
    2014-10-13 01:22:55
    뭐.. 이런거 가지고 갑을 반론을 하는 것 자체가 좀 그러네요..
    초반에 미리 예상을 못했더라도 ArrayList xxx 선언보다 List xxx 가 훨씬 현재 플젝에 안성맞춤이면..
    '이것으로 이번 플젝은 이러이러한 업무롤로 맞춰 진행합시다' 라고해서 바꾸도록 지침을 내리게 하면 되는 것이지..

    굳이 List 라는 4자에 Array 라는 글자 5자 더 코딩한 것 때문에..
    'k9200544' 님이나 '지붕뚫고높이차' 님이 말씀하신 것처럼..그게 죽이네 살리네 그런 것은 아닌듯 보이며.. SI같은 경우라면 워낙 상황이 다들 여유가 없고 서로 민감하면.. 코딩 1자 가지고도 육두문자 나오는 것은 다반사이겠지만..

    글 작성자분이 SI는 아니라고 하셨고.. 또한 본인이 생각한 지침 사항도 전달했다라고 하셨으며..
    ' 개발자 한 명의 자아가 너무 강하더군요.' 가 가장 포인트인듯 합니다.

    그냥 제가 보기에는 글 작성자분의 롤에 대해서 서로 사사건건 안 맞는 상황인 것 같습니다.
    그건 어쩔수 없죠 ㅜㅜ
    그건 서로 여유를 가지고 결정을 내려야 할 듯.. 아니시라면 패스~
  • benelog
    68
    2014-10-13 02:51:35
    위의 분이 말씀하셨듯이 ArrayList를 List로 참조한다면 나중에 LinkedList로 바꿀때 그 라인외의 다른 곳을 수정할 필요가 없어집니다. 이 경우는 List를 참조한 구현체를 프로젝트에서 직접 만든 경우를 위해서 그런것이 아니고, JDK내의 구현체 내에서 선택을 변경할때를 위한 경우입니다.

    비슷하게 ArrayBlockingQueue를 썼다가 SynchronousQueue로 바꿀 때, LinkedHashMap를 쓰던 곳에서 Concurrency문제로 ConcurrentHashMap로 바꿀때도 마찬가지고요.

    이런 원칙은 메서드 시그니처에서 더욱 중요하긴한데, Local변수에서도 이를 의식한 것은 좋은 습관입니다. 호흡이 짧은 메서드에서는 큰 영향성은 없겠지만, 한번 잘 선언해두면 메소드 추출시에도 자동으로 인터페이스가 반영이 되니까요. 따라서 일관성을 위해, 꼭 특정구현체의 기능을 써야하는 경우가 아니라면 (LinkedHashMap.removeOldestEntry 같은것 처럼..) 인터페이스 참조를 기본 원칙으로 삼는 것을 권장할만합니다. 특정 구현체에만 종속적으로 의지할지를 결정하는데 신중해지는 효과도 있습니다.

    그래서 이 규칙은 특수한 프로젝트에 적합한 룰이라기보다는 보편적인 관례로 취급되는 면이 강합니다. 이런 류의 규칙까지 일일히 프로젝트 초기에 알려주거나 프로젝트 컨벤션 문서 같은데 포함한다면 그런 시간이나 문서의 내용이 너무 길어질것 같고, 이 규칙을 들어보지 못한 사람에게 코드 리뷰때 알려줄 수 있는 정도의 사안인듯합니다.
    (다만 옛날 Android 문서에서는 성능을 이유로 구현체 참조를 권장하는 내용이 있기도했었죠. 지금은 사라졌지만..)

    참고로, 인터페이스 참조에 대한 내용은 Effective java 2nd edition의 Item 52에 설명되어 있습니다. JDK의 최신코드나 Google Guava 등의 많은 라이브러리의 설계에 이 책의 지침이 반영되어 있습니다. '지붕뚫고높이차'님은 이 책의 지침이 한심하다고 느끼실수도 있지만, JDK 같은 라이브러리 설계자의 생각이 어떤지를 참고하시는데는 도움이 되실것이라고 생각합니다.

    암튼 만만치 않은 프로젝트에서 믿고 일을 길만한 연차의 개발자가 지금까지 다른 개발자들에게는 일일히 설명할 필요가 없었던 사안까지 알려줘야 하는 상황이라서 스트레스를 많이 받으신것 같네요..
  • roksoulmc
    2014-10-13 07:18:01
    축구팀에서 선수 한명 못하면 그선수가 못하는건데 팀전체가 그러면 보통 감독이 짤립디다.
  • hotaro2010
    209
    2014-10-13 07:48:50
    아...제대로 쓰여진 설계서가 보고 싶네요.. 한국에선 본 적이 없습니다.
    한번은 제대로 한번 써 볼려 했다가 팀원들의 반발에 부딪혀서 관뒀습니다.
    나중에 이슈가 생기자 "설계서대로 했다" 고 반항하길래 줘 패버렸습니다만....(꿀밤 ㅋ_ㅋ)
  • 삼식이
    1k
    2014-10-13 09:35:05
    greatkit//
    List 건 ArrayList건 그때 그때 상황 따라 쓰면 되는거고.
    LinkList로 바꿀경우에 리플렉셕으로 한방에 코딩 바꾸면 되니 수정 이슈도 없다고 봄.
    프레임웍 개발이 아닌 단일 프로세서 개발할때는 오히려 ArrayList로 쓰는게 더 낫다고 봄.
    List로 해노면 런타임시에 ArrayList 인지 알수 있으니 코드가 직관적이지 않음.

    그리고 서버 사이드 비동기와 클라이언트 사이드 비동기 차이가 몬지 모르겠음.
    둘다 스레드풀로 관리 하고 UI적인 행위만 약관 틀린뿐인디 무슨 차이를 말씀하시는건지?
  • kmjyarto
    1k
    2014-10-13 09:39:10
    맘맞는 사람이란 세상에 존재하지 않을지도 모릅니다.
    얼르고 달래고 싸우고 하면서 가는거겠죠.
    그래도 어쨋거나 프로젝트 성패의 책임을 PM인 내가 쥐고 있다면
    팀원들에 대한 상벌의 권한도 같이 있다고 봅니다.
    글쓴분의 잘못이 있다면
    그런점을 명확히 하지 못한점이라고 생각됩니다.
    개발자의 자아가 강하건 약하건 하는 일에 대한 냉정한 평가가 필요하겠죠.
    코드 리뷰 단계에서 강하게 압박했다면 PM말을 듣던가 스스로 나가던가 했겠지요.
    게다가 나쁜 코드도 문제지만 자기보다 낮은 직급의 팀원을 무시하기까지 하니
    팀분위기까지 망친다면 이건 두고 볼것도 없이 아웃시켜야합니다.
    그래서 PM의 자리는 참 어려운건가 봅니다.
    프로젝트의 성공을 우선순위에 두고 팀원들의 처지에 대한 공감을 조금 줄이는것도 방법인거 같더군요.
    아무튼 건승하시길 바라겠습니다.
  • muttinaong1
    2014-10-13 10:22:52
    상대방 입장도 봐야겠지만

    서버단 동기/비동기 이야기를 하는데 Ajax가 나왔다면 말 다한거 아닐까요?

    아무리 좋게 생각해도 좋게 받아들여지지 않음.

    그리고 작성자님도 까분다는 단어쓰는거보면 뭔가 권위의식이 있는듯.

    협업에 있어서 롤은 롤일뿐이지 롤이 님을 사람위에 있게 하는건 아닙니다.

    그걸 무의식에서 부터 받아들이지 않으면 앞으로도 갈등 많으실 듯.

  • 지붕뚫고높이차
    1k
    2014-10-13 12:07:45
    지나가다 //

    컬랙션 객체나
    컬랙션 구현 클래스나 동일한 의미 아닌가요?

    ArrayList 의 계층구조를 확인해 보니

    ArrayList 사 상속받는건 AbstractList 이고
    인터페이스를 구현한 건 List, RandomAccess, Cloneable, java.io.Serializable 입니다.

    ArrayList 는 List 에서 요청한 인터페이스 메소드를 구현햇을 뿐이지
    ArrayList 가 List 하고 동일하다는 의미가 아니거든요.

    자동완성에 대해서는 이해가 되지를 않는데
    어떤경우인지 실제 예를 들어주시면 이해될것 같구요.

    타이핑 문자도 길어진다고 했는데 전체 코드중 딱 5글자 추가입니다.
    그부분을 문제 삼는건 억지라고 생각합니다.

    그리고 특별하게 사용한 기억은 없지만
    ArrayList 에 특화된 trimToSize, ensureCapacity 메소드를 사용한다는게
    잘못된 로직인지 반문하고 싶구요.


    객체 컬랙션에서
    List 인터페이스가 필요하는 경우는 아래와 같습니다.

    모듈1 에서는 객체저장을 ArrayList 을 사용하고
    모듈2 에서는 객체저장을 LinkedList 을 사용하는데
    정렬(List x) 같은 메소드를 호출하는 경우

    두번째로는
    MVC 패턴에서
    콘트롤러1에서 ArrayList 를 사용하고
    콘트롤러2에선 LinkedList 를 사용하는데
    공통으로 호출하는 뷰에서는 List 로 형 변환해서 사용하는 경우입니다.

    둘다 컬랙션 객체 생성 시점에서
    List list = new ArrayList(); 로 생성하나
    ArrayList list = new ArrayList(); 로 생성하나 차이가 없고
    인터페이스의 목적에 충족되는 방식입니다.

    그리고 마지막으로

    LinkedList 의 예를 들으셨는데
    삽입,삭제 빈번한 경우,성능향상을위해 구현한 인터페이스는
    List 가 아닌 Deque 입니다.
    List list = new LinkedList(); 로 선언해서
    addFirst, addLast 등의 기능을 사용할 수는 없겠죠.


    나는 잘 모르고 내가 하지는 않지만
    언젠가는 다른사람이 편할거라고 기대하면서
    남들이 하니 맞는거라 생각하며 작성한거라고
    개.인.적 으로 판단하는
    List list = new ArrayList() 에 대해

    살의를 느끼는 이유에 대해 질문을 올렸는데

    지나가다님도 열을 받는다고 하시네요. ^^

    시간 되실때 제가 질문드린
    지나가다님이 이야기하신 자동 완성의 문제점과, LinkedList 로 교체했던 예를 올려주시면
    참고하겠습니다.
  • narise
    2k
    2014-10-13 12:21:06
    지붕뚫고높이차>>

    benelog님 글은 읽었는지요?

    질문엔 대답이 없고 엉뚱하게 떡내놔라 이런식으로 물고 늘어지는데.

    님이 고집하는 인터페이스를 쓰지않는 방식은 장점이 없다라는 겁니다.

    일반적인 자바코딩규약에서 권장하는 코딩방식인지?

    "나는 변수이름을 모두 대문자로 쓰겠다. 이게 열받을 일이냐?" 이런식이니 뭐라 할말없군요.

    유명한 라이브러리, 프레임워크 소스 분석하거나, 남의 소스 유지보수 해봤다면 이런 부분은 민감할수밖에 없는거죠.
  • benelog
    68
    2014-10-13 12:23:43
    반대의 경우지만 LinkedList를 ArrayList로 교체한 사례는 Spring프레임워크 2.0.1 -> 2.0.2로 넘어갈때의 아래 클래스의 사례가 생각나네요.

    http://grepcode.com/file/repo1.maven.org/maven2/org.springframework/spring/2.0.1/org/springframework/jdbc/core/RowMapperResultSetExtractor.java/

    http://grepcode.com/file/repo1.maven.org/maven2/org.springframework/spring/2.0.2/org/springframework/jdbc/core/RowMapperResultSetExtractor.java/

    예를 더 들면, 의도하지 않은 변경을 막기 위해 Collections.unmodifiableList 같은 메서드로 감싼 List를 반환하는 경우, 빈 List를 반환할 때 매번 객체를 생성할 필요없이 Collections.emptyList();를 쓰는 경우, 요즘은 BlockingQeue가 있어서 잘 쓰이지는 않지만 Collections.synchroziedList (..)로 감싼 List를 밖으로 반환할때등도 참조가 List로 넘어오므로 이를 받아서 다시 외부로 노출할때도 List로 하는것이 자연스럽습니다.

    그리고 구현초기에 어떤 구현체가 적합할지, 어떤 decorator를 입히는 것이 완벽하게 아는것은 어렵습니다. List의 경우는 비교적 그런 경우가 없겠지만, 요구사항이 추가되거나 부하가 늘어나면서 적절한 구현체가 달라지는 경우고 많기 때문이죠. 예를 들면 처음에 어느 정도의 Queue capacity를 잡아야할지 감을 잡기 어려워서 SynchronousQueue로 쓰다가, 나중에 적절한 정책을 정해서 ArrayBlockingQueue 등으로 바꿀수도 있겠죠.

    JDK8로 업그레이드하면서 Stream의 filter, collect같은것 써서 기존의 Collection의 반복처리 같은것을 바꾸고 싶을때에도 비니지스 코드의 return type이 ArrayList로 박혀있다면 추가적인 수고가 들어가게 됩니다. (Stream.collect(Collectors.toList()) 은 List를 반환하니까요. 찾아보니 Collectors.toList()도 내부적으로 ArrayList를 쓰긴하네요. 하지만 위의 Spring의 사례처럼 언제든지 바뀔 수 있다고 생각합니다.)

    Effective Java의 저자 Joshua Bloch이 Java collections 라이브러리의 설계자였던 만큼, 이런 사용방식에 맞게 JDK가 설계되어 있습니다. 그래서 비지니스 로직의 구현코드에서라도 이 규칙은 염두에 두어야한다고 저는 생각합니다. 즉 디폴트는 인터페이스 참조이고 구현체 참조는 꼭 필요할 때만 쓰는것이죠. '지붕뚫고높이차 '이 생각하시는 원칙과 반대인듯하지만, Joshua Bloch이 권장해서 많은 사람들이 따르고 있는 지침이니 '나쁜 습관'이라고 말하기는 어려울듯합니다.


    ArrayList 에 특화된 trimToSize, ensureCapacity이 꼭 필요하다면 ArrayList로 참조하는게 맞습니다. (Effective Java의 Item52에서는 이런 예외상황에 대해서도 잘 설명하고 있습니다. ) 다만 그런 사용방식도 꼭 필요할때만 노출이 되어야하고, 인터페이스 참조 습관이 그런 결정에도 도움이 됩니다. 만약 Vector->ArrayList의 변화처럼, ArrayList대신 새로운 List구현체를 권장하는 날이 온다면 구현체 종속적인 기능을 쓰는 부분도 부담이 될수 있기 때문이죠. interface도 변할 수 있겠지만, JDK8의 Default메서드 도입등을 볼때 인터페이스의 하위호환성은 더 신중하게 유지될것으로 예상됩니다.

  • narise
    2k
    2014-10-13 12:30:19
    관리하는 입장에서 사소한거 하나하나 이야기 해야하는게 스트레죠.

    인터넷뒤지면 자바코딩큐약 자료도 많고, 잘만들어진 프레임워크 사용하거나 분석하면, 알게되는 건데....


    얼마전 협력업체 산출물 받아서, 경력3년차라는 사람 소스 체크하다보니 기본적인 코딩규약도 지키지 않고 이런 환상적인 소스더군요.


    if (disableABC() == true)...

    if (stringA == stringB)....
  • 겨우살이
    163
    2014-10-13 12:33:18
    우와 ArrayList 하나로 이렇게 시끄러워 지다니...ㅋ
    이글 쓴분의 말은 ArrayList가 문제가 아닌거 같은데...
    글쓰신 분도 그 사람에게 기분나쁘게 얘기했던게 아닌가 싶네요...
    말하는것도 스킬이라고 생각합니다... 기분안나쁘게 내가 알기로는 이런거 같은데
    한번 고려해봐라 이런씩으로...그러면 분명 찾아볼거고...
    뭐 내 생각이 이렇다는겁니다...

    저렇게 까지 이야기 하는데도 안 들어 쳐먹으면 뭐 어쩔수 없는거죠...
    일하다보면 개 씌레기 마인드 가진 놈들이 한둘이 아니니...
    PM이 저들을 오케스트라처럼 관리해야 하는 입장이니...

    여튼 뭐 세상사는게 다 복불복 아니겠나요...~

    지금 여기 댓글들은 ArrayList가지고 너무 아는척 하시는듯..~
    글쓴 분도 본인이 아시는게 다 가 아닐진데 너무 세부적으로 무조건 이거다 하시는
    그런 생각은 고치심이 어떠 실지요..~~

    뭐 기분나쁘라는건 아닙니다...그냥 저의 생각이였습니다..
  • benelog
    68
    2014-10-13 12:55:49
    @겨우살이
    아는 척해서 죄송합니다 ^^; 휴가 중이라 시간이 좀 여유있어서 좀 길게 어떤 분께는 도움이 될 정보를 공유한다고 생각했는데, 겨우살이님은 제가 잘 모르는것을 아는 것처럼 과장하고 있거나 아는 것을 과시하고 있다고 느끼셨나보네요.

    이 게시글이나 게시판의 성격에 맞는 내용은 아니였던것 같습니다. 앞으로는 자제하겠습니다~
  • greatkit
    227
    2014-10-13 13:33:48
    괜히 넋두리성 글을 세련되지 못하게 올려서 논란만 불러일으켰네요.
    누구 잘잘못 따지자는 것도 아니었고 따진다면 PM인 제가 어느 정도가 되었건 책임에서 자유로울 수는 없겠지요.
    그냥 제가 아직 많이 부족하니 더 수양하도록 하겠습니다.

    // 지붕뚫고높이차
    이 분이 제기하신 궁금증에 대해서만 간략히 쓰고 사라질게요.

    말씀하신 대로 그 구현체에서 필요한 것을 굳이 써야 한다면 선언도 ArrayList 로 해도 될 것 같습니다.

    그러나 제 경험상, List 로 선언했을 때 할 수 있는 일이 많아지며 특별히 구현체 특화된 기능을 쓸 일이 거의 없었습니다. 만약 그럴 경우 대부분 설계상의 문제였고요.

    - 우선 unit test 할 때 테스트용 리스트를 Arrays.asList(...) 로 간결하게 만들어 할당할 수 있음.
    - 빈 리스트일 경우 Collections.emptyList() 할당이 가능합니다. 단 한 줄로 코드 자체에서 빈 리스트를 의도했음이 명확해지고요.
    - 그 밖에도 필요한 경우 Collections.synchronizedList(), Collections.unmodifiableList() 등을 사용하여 성격을 쉽게 바꿀 수 있습니다.
  • 삼식이
    1k
    2014-10-13 14:41:43
    다 떠나서 PM이 개발 하면 그 프로젝트 100% 망함.

    한국 SI 특성상 밥을 숫가락으로 먹던 젓가락으로 먹던 손으로 먹던간에 먹기만 하면 장땡임.
  • unigoon3
    295
    2014-10-13 15:27:07
    사수가 꼼꼼하시고 세부적인 지식이 있는 것은 좋지만 다른 사람도 항상 그럴수는 없지요. 좀 더 관용적인 태도로 지시하고 리더쉽을 보여줬으면 합니다. 이거 아니면 틀린거라는 태도는 맞냐틀리냐를 떠나서 협업의 분위기를 죽입니다.
  • unigoon3
    295
    2014-10-13 15:33:31
    물론 인력문제에서 오는 기본적인 답답함은 이해합니다. 답이 없다면 빠른 교체가 답이고 아니면 다소 불만스럽더라도 역량을 끌어내서 이끌어가야죠.몇몇 기술적이슈를 꿰뚫고 있냐로 전체를 판단하는 잣대를 들이대지 말고요.
  • 지붕뚫고높이차
    1k
    2014-10-13 16:18:21
    greatkit //
    답변 감사드립니다.

    그런데 예로 드신
    Arrays.asList(...), Collections.emptyList(), Collections.synchronizedList()
    등의 예는

    List 를 구현한 ArrayList 를 명시적으로 선언했다고 하더라도 동일하게 동작합니다.
    (이 부분이 객체지향언어의 매력이라고 생각합니다.)

    오히려
    LinkedList 처럼 명시적으로 선언하지 않으면
    LinkedList의 고유기능을 사용못하는 경우가 발생하는데 이부분에 대한 의견을 듣고 싶습니다.

    원 글과 상관없는 부분이라서 글 쓰기가 부담스럽네요.
  • rosa
    1k
    2014-10-13 17:57:06
    우선 위에서 다른 분들께서 쓰니 list관련 내용은 재미있게 읽었습니다.

    그런데 중간 중간 아는척! 이라는 둥, 왜 이런 글을 쓰냐는 듯한 뉘앙스의 글들엔
    반문을 하고 싶네요.

    okjsp가 개발자들 사이트인데 사는 얘기 게시판의 댓글로 이런 글이 나왔다지만
    서로가 개발자이고, 각자 다른 개발 환경에 있고, 코딩 스타일도 다르듯이
    이런 개발관련 논쟁이 개발자 사이트에서
    어때서 아는 척과 쓸모 없는 이야기로 도매급으로
    취급 당한지는 모르겠네요;;;;
  • fc
    1k
    2014-10-13 20:00:31
    한마디 썰// 아~ 그것은.. '토론/기타 Qna ' 라는 주제 성격으로써 이러한 장이 열렸으면..
    그건 당연한 것이죠~ 허나.. 여기는 '사는 얘기' 라는 성격으로써..
    글쓴님이 어떠한 힘든 점이나.. 그리고 사람인지라.. 플젝은 넉근히 소화해낼 수 있지만..
    본인이 막상 닥친 변화 무쌍한 팀원들간의 문제 상황등을 풀어나아가는데에 대한 어떤 실마리가..
    현 논점에서의 우선 순위가 제일 높아야 한다는 것이죠~

    지금은 글쓴님이.. 어느 정도 안정을 찾으셨는지는 모르겠으나..
    부차적인 list 토론 과 쟁점 논쟁.. 환영합니다 ㅎㅎ
  • 스타
    3k
    2014-10-13 20:46:04
    소잡는 칼을 만들어 놨더니 닭잡늠 칼로 소 잡을 수 있다라는 이야기로 썰전을 펴고 있군요. 용도에 맞게 쓰는게 최선입니다. 그래야 패치가 되어도 몸고생 안하죠. 대신 소득 창출엔 기여를 합니다. 설득력 있네 .. ㅇ.ㅇ
  • fc
    1k
    2014-10-13 20:55:06
    그렇다 할지라도..

    'benelog' 님이시라던가 기타 다른 분들의 글을 읽으면서.. 그것이 컴퓨터처럼 딱딱 이거냐 저거냐가 아닌 각자 만의 전문적인 내공이 곁들인 생각들이 한 곳에 모여 묶이니까...
    시너지 효과가~ 활력이 ^^ 이러한 장도 나쁘지 않다는..
    무언가 퍼즐 맞추듯이 생각의 정리가 되는 느낌입니다~
  • de
    2014-10-14 09:14:57
    댓글, 답글에서 많은것들 배워갑니다~^^

    지붕~님의 경우에는 실경험의 대한 말씀들을 주로하시고 원글쓰신분은 너무나도 유명한책을 예로 들어 말씀하시니 확실히 후자가 더 설득력 있어 보이네요.
    디자인패턴, 객체지향 공부하고 스프링개발을 할때 느낀점은 인터페이스로 선언하는걸 보편적으로 많이 쓰는것 같습니다.
  • 삼식이
    1k
    2014-10-14 10:27:47
    지붕 vs greatkit

    지붕님 윈~ ㅋㅋ
  • benelog
    68
    2014-10-14 12:20:25
    @지붕뚫고높이차

    아래의 메서드의 return type이 ArrayList이였다면 컴파일이 제대로 되지 않습니다.

    (공백이 제대로 먹힐지 모르겠네요; 여기는 글을 쓰고 수정을 어떻게하는지 모르겠습니다;)

    public List findRoleNames(User user) {
    if ( user.getGrade() == UserGrade.BRONZE) {
    return Collections.emptyList();
    } else if ( user.getGrade() == UserGrade.SILVER){
    return repo.selectRoleNames(user.getId());
    }
    return Arrays.asList("GUEST");
    }

    그래서 메서드 시그니처에서 인터페이스에 의존하는것이 더 중요하긴한데, 메서드 추출등의 리팩토링 가능성을 감안하면 Local에서의 참조도 인터페이스로 하는게 미래의 코드 추가에 더 유리한 선택입니다. Eclipse에서 메서드 추출단축키 누룬후 따로 타입을 수정할 필요도 없고요. 그리고 구현체 레벨의 메서드를 쓰는지 인터페이스 레벨을 쓰는지 인지를 할수도 있습니다.

    앞선 저의 글에서도 계속 말씀드렷듯이 LinkedList같이 클래스의 고유한 메서드가 필요할때는 객체참조를 하시면 되는데, 한번쯤 생각해보고 선택할 사안입니다. 구현체 수준의 기능에 의존할때 쓰는 범위가 좁다면 교체비용이 적겠지만 메서드 외부로 노출하면 다른 구현체로 교체할 때 수정범위가 커집니다.

    List를 예로 드니 구현체 선택의 폭이 좁아보이지만, Google guava (구 google collections)등 java.util.List를 구현한 클래스를 포함한 외부 라이브러리도 있고, 실무에 꽤 쓰이기도합니다.

    혹시나 구현클래스 참조가 필요하더라도, 참조타입을 초기 선택후에 뒤에 수정하는 비용이 (구현체 참조에서 인터페이스 참조로 변경) 보다는 (인터페이스 참조에서 구현클래스 변경)이 훨씬 비용이 싸기 때문에 전자를 디폴트로 추천하는것입니다..

    제가 계속 인용드린 Effective java 2nd edition의 Item52는 아래 링크에도 나와있네요.

    http://jtechies.blogspot.kr/2012/07/item-52-refer-to-objects-by-their.html

    본인의 생각을 바꾸실 필요는 없겠으나 널리알려진 권장방식과 반대로 생각하고 계시는것을 인식하신다면 다른 개발자들과 의사소통을 하실때 더 오해가 적지 않을까 생각합니다.

    'Java collections 프레임워크의 설계자는 인터페이스 참조를 추천했지만 내 생각은 그 반대이다.' 정도로 밝히시면 다른 분들도 맥락파악이 빠를것 같습니다..

    개인적인 경험을 말씀드리면, 제가 11년정도 Java 프로젝트를 해온 동안 지금까지 인터페이스 참조를 권장하는 규칙이 논란이 된적은 없고 대부분 암묵적인 합의로 별 이야기없이도 그렇게 써왔습니다. 사람의 경험은 다들 달라서 어느 것이 질이 높다고 말할 수는 없지만 그냥 지붕님의 주장 근거가 개인적인 경험이시라길래 참고삼아서 말씀드렸습니다 (저하고 프로젝트를 한 사람들의 취향이 우연히 맞은걸수도 있어서 편향된 경험일수도 있다고 생각합니다 ^^;)
  • 랏츠
    1k
    2014-10-14 13:51:31
    글쓰신 pm님 거긴 AA나 TA가 없는겐가요. 소스검증은 툴이 하는거지 pm이 하는게 아니라고 봅니다. 특히나 자존심 강한 개발자 분들에 대해 잘 알고 있는 관리자급이라면 말이죠.

    http://goo.gl/5Zl9i0
  • 2014-10-14 19:18:12
    benelog //
    아래 코드 이클립스에서 잘 동작하던데요.
    형 변환 규칙을 생각해 볼때
    자식 클래스가 부모 클래스로 변환되는것이 자연스러운데
    컴파일 에러가 난다고 하셔서리..
    ----------
    public static List getList() {
    ArrayList list = new ArrayList();
    return list;
    }
  • 스타
    3k
    2014-10-14 19:42:30
    논쟁에 이겨 보겠다도 고만 좀 우기고, 쓰라고 만들어 놓은거 그냥 잘 쓰면 되죠.
    list를 써야 한다는 건 논란거리도 아닌 것 같은데...
  • benelog
    68
    2014-10-14 19:58:50
    @k9200544
    그 코드는 당연히 되죠 ^^;

    위에 제가 짠 코드에서 "return type이 ArrayList이였다면" 컴파일이 안 됩니다.
    (제가 컴파일이 되는 코드를 보여드려서 혼동을 드린것 같네요)

    즉 k9200544님이 짜신것과 비슷한 코드로 컴파일이 안되는 상황을 만들면 아래와 같이, 반대의 상황입니다.

    public static ArrayList getList() {
    return Collections.emptyList();
    }

    위에서 지붕뚫고님이 Arrays.asList(...), Collections.emptyList()도 ArrayList로 선언해도 쓸 수 있다고 하시길래 그렇지 않음을 보여드리기 위해서 꺼낸 예제였습니다.

    method signature가 아니면 큰 상관이 없는데, 왜 local변수의 참조도 인터페이스로 하는것이 좋으냐는 의문이 드실수도 있는데 거기에 대한 대답은 위에서 드린것 같네요..
  • 지붕뚫고높이차
    1k
    2014-12-21 22:18:53
    2달전 글이기는 하지만
    검색해서 들어오시는 분들을 위해 답변 올립니다.

    Collections.emptyList 는 제가 실수로 잘못 예를 들었습니다.

    메모리, CPU 성능에 대해 심각하게 고려하지 않는 성격으로
    한번도 사용안한 메소드라

    asList, synchronizedList 와 동일하게
    메소드 시그니처로 List 를 사용하는줄 알있습니다.

    그리고
    benelog 님의 글에
    이야기 할 말은 많지만

    본 주제에 맞지 않기 때문에

    한가지만 적고 마무리 하겠습니다.

    최근 수년간 잘 사용하던 프레임웍의 모듈중 하나가
    알 수 없는 특정 조건에서 무한 루프가 도는걸 발견하였습니다.
    서버 재가동 후 덤프를 분석해 보니

    HashMap 의 다중스레드 환경에서
    get 메소드 부분에 무한 루프가 돌 수 있다는걸 발견하였습니다.

    어플리케이션 로그나
    지연 서비스를 분석한 결과 HashMap 의 문제가 맞는걸로 분석되었고

    HashMap 를 ConcurrentHashMap 으로 교체해야 하는 문제가 생겼습니다.
    그 모듈은 캐쉬 정책을 담당하고 있고 프레임웍의 핵심 모듈입니다.

    자.
    benelog 님이 인용하신
    http://jtechies.blogspot.kr/2012/07/item-52-refer-to-objects-by-their.html
    주장처럼

    유연하지 않은
    언제 만들었는지 기억도 안나는 그 코드의 수정이 어려웠을까요?

    상상에 맞기겠습니다.
  • benelog
    68
    2015-01-27 11:39:20
    @지붕뚫고 높이차
    직접 그 코드를 보지도 않았는데 상상을 하는것은 어렵네요 ^^;

    의도하신것을 짐작하면, 인터페이스로 참조하지 않았지만 수정하기 쉬웠던 예는 당연히 많습니다. 그리고 수정 비용이 큰 사례도 당연히 많습니다. 그렇다면 1~2줄 차이로 초기 작성 비용에 차이가 크지 않은데 수정하지 어려울 상황이 발생할지도 모를, 리스크가 있는 코드를 굳이 고집할 이유는 적다고 생각합니다.

    앞의 글에서 예로 든것처럼 JDK 1.4에서 Vector를 쓰던 코드를 JDK 버전을 올리면서 Arraylist로 바꾸는 수정은 흔하게 일어날법한 일입니다. 하나 더 들면, 직접 ArrayList를 Return type으로 넘기는 모듈이 있을때, Guava나 GS-Collections같은, 개선된 Collection 라이브러리를 도입하려고 하는 경우입니다. 그럴때 ArrayList를 쓰는 메서드 시그니처와 이를 호출하는 코드를 다 바꿔야합니다. Replace-all로 바꾸면 되지 않냐고 생각하실수도 있지만, 이미 jar파일로 배포되어 있는 모듈의 하위호환성 문제까지 생각하면 비용은 정말 커집니다. 여러 프로젝트에서 쓰이는 공통 라이브러리를 개발한다면 더욱 그렇습니다.

    수정하기 쉽다는 예로 드신 Hashmap사용 코드를 볼수는 없지만, 캐쉬모듈의 외부로 직접 HashMap을 노출했을리는 없으니 더욱 구현체를 바꿔도 수정범위가 적었을것 같습니다. HashMap을 밝으로 노출한 설계라면 당연히 바람직하지 않습니다. 만약 노출한다고 해도 인터페이로도 Map이 아닌 ConcurrentMap으로 해야겠죠.

    하나 궁금한 점은
    1. 메서드 시그니처에서조차도 인터페이스를 의존하는것도 바람직하지 않다고 생각하시는지
    2. 아니면 Local 변수 선언에서만 인터페이스 참조가 바람직하지 않다고 생각하시는지

    만약 지붕뚫고 높이차님의 생각이 1번이라면, 더욱 저의 생각과는 거리가 멉니다.

    서로의 경험이 다르니 당연히 생각은 다를수 있지만, 저는 제 생각이 JDK설계자의 의도를 따르고 있다고 생각하고 있습니다. 그리고 제 경험 중에는 지붕뚫고높이차님이 경험하지 못한 부분도 있을거라고 여겨주시면 님께서 경험한 사례 안에서는는 충분했던 설계원칙을 보강하시는데 더욱 도움이 되실것 같습니다. 그런 이유로 저는 Joshua Bloch의 지침을 귀 기울려 듣고 있고요.

    그리고 하시고 싶은 말씀은 계속 게시판에 적으셔도 좋을것 같습니다..
    (어짜피 원글의 핵심주제와는 멀어지고 있으니까요 ^^;)
  • benelog
    68
    2015-03-09 10:17:05
    이번에 신입사원 교육을 하면서 코드리뷰 때 인터페이스 참조 원칙에 대해서 설명을 한적이 있었습니다. 글로도 정리했었는데, 같이 신입사원 교육을 하신 박재성님이 외부에도 올려줬으면 좋겠다고 요청을 하셔서 아래에 올렸습니다.

    http://www.slipp.net/questions/345


    그리고 https://github.com/benelog/lambda-resort 의 예제를 보시면, Java 세계에서는 JDK의 Collection framework를 개선하려는 수많은 시도들이 있어왔다는 것을 알 수 있습니다. 'java.util.List의 구현체는 java.util.ArrayList  외에는 거의 쓸일이 없다'고 생각하시는 분들은, Google이나 골드만싹스의 개발자들이 왜 Guava나 GS Collections같은 라이브러리를 만들었는지 잠시 호기심을 가져보시는것도 좋을듯합니다.






  • 로그인을 하시면 댓글을 등록할 수 있습니다.