여기 정리한 라이선스 외에도 수많은 오픈소스 라이선스들이 존재하며 여기 있는 라이선스조차도 제가 정리하지 못한 많은 부분들이 많지만, 앞으로는 오픈소스 SW를 활용하거나 오픈소스 SW를 만들 때 라이선스에 대해 한 번쯤 고민할 수 있는 계기가 됐으면 좋겠습니다. 수정하거나 보완할 내용이 있으면 알려주시기 바랍니다.
*이하 설명하고 있는 오픈소스 라이선스는 소스코드에 적용되는 라이선스이며 일반적으로 소스코드에 대한 문서나 콘텐츠에 대한 라이선스는 CCL 등 별도의 라이선스를 적용합니다.
라이선스 종류
Apache License
– 아파치 라이선스는 아파치소프트웨어재단이 자기네 SW에 적용하기 위해 자체적으로 만든 라이선스다. 소스코드 공개 의무 같은 의무사항은 없지만, 아파치 라이선스 소스코드를 수정해 배포하는 경우 아파치 라이선스 버전 2.0을 꼭 포함시켜야 하며 아파치재단에서 만든 소프트웨어임을 밝혀야 한다.
– 자유소프트웨어재단에서 만든 라이선스다. GNU 프로젝트로 배포하는 소프트웨어(Emacs, GNU 디버거(GDB), GNU 컴파일러 모음(GCC) 등)에 적용하기 위해 리처드 스톨만이 만들었다. 가장 큰 특징은 자유소프트웨어재단답게 가장 강력한 제약 조건을 포함하고 있는 카피레프트 조항이다. GPL 프로그램은 어떤 목적으로, 어떤 형태로든 사용할 수 있지만 사용하거나 변경된 프로그램을 배포하는 경우 무조건 동일한 라이선스 즉, GPL로 공개해야 한다.
– GPL을 기반으로 만든 라이선스로 버전1, 2는 아페로, 가장 최신 버전인 버전3은 자유소프트웨어재단에 의해 개발됐다. 수정한 소스코드를 서버에서만 사용하는 개발자가 그 프로그램을 배포하지 않을 경우 사용자는 소스코드를 가질 수가 없는 문제를 해결하기 위해 마련됐다. 서버에서 프로그램을 실행해 다른 사용자들과 통신하면, 실행되고 있는 프로그램의 소스코드를 사용자들이 다운로드할 수 있게 해야 한다는 독특한 조항을 담고 있다.
– 자유소프트웨어재단의 강력한 철학이 담긴 GPL의 카피레프트 조항을 보완하기 위해 만든 라이선스다. GPL은 단순히 소프트웨어를 사용하기만 하더라도 해당 소스코드를 GPL로 공개해야 하는 부담감 때문에 상용 소프트웨어로 쓰기 부담스럽다는 단점이 있다. 그래서 좋은 자유 소프트웨어 제품이 더 많이 쓰이고 표준이 되도록 유도하기 위해 단순한 라이브러리·모듈 링크를 허용한 라이선스이다. 원래는 한정된 라이브러리에만 적용하려는 의도로 ‘Library GPL’이라는 이름을 붙였으나, 모든 라이브러리에 적용된다는 오해를 사 ‘Lesser GPL’로 변경됐다.
– 버클리의 캘리포니아대학에서 배포하는 공개 SW 라이선스다. BSD 자체가 공공기관에서 만들어낸 것이므로 공공의 몫으로 돌려주자는 의미가 강하므로, 라이선스 자체에는 아무런 제한 없이 누구나 자신의 용도로 사용할 수 있다. 라이선스 및 저작권 표시 조건 외엔 제약이 없는, 굉장히 자유로운 라이선스 중 하나이다.
– 모질라 공용 허가서는 과거 넷스케이프 웹브라우저의 소스코드를 공개하기 위해 개발된 라이선스다. 초기 1.0버전은 넷스케이프 커뮤니케이션의 변호사였던 밋첼 베이커가 작성했고, 1.1과 2.0버전은 모질라재단이 작성했다. MPL의 특징은 소스코드와 실행파일의 저작권을 분리했다는 점이다. 수정한 소스코드는 MPL로 공개하고 원저작자에게 수정한 부분에 대해 알려야 하지만, 실행파일은 독점 라이선스로 배포할 수 있다. 즉 사용한 MPL 소프트웨어와 수정한 MPL 소프트웨어에 대한 공개 의무만 가지며, 별도의 소스코드와 실행파일은 독점 라이선스를 가질 수 있다.
평생 공부하는 건 개발자만이 아니다. 다른 직업을 가진 사람들도 쉼 없이 공부하고, 컨퍼런스와 세미나를 참가하고, 스터디를 한다. 공부없이 할 수 있는 일이 없기 때문이다. 언뜻 보기에 공부와 거리가 멀어 보이는 바텐더조차 공부할 것이 많다. 바텐더를 위한 컨퍼런스는 물론이고 전문적인 팟캐스트 방송까지 있다. 공부는 누구나 하는 것이므로 공부한다는 사실만으로 엄살을 떨 필요는 없다. 문제는 공부의 방향이다.
개발자의 경우는 평균적으로 보았을 때 3년 전에 학습한 지식이면 낡은 징후를 보이기 시작하고 5년이면 생명을 다한다. 더 오래가는 지식도 물론 있다. 프로그래밍의 본질에 가까운 지식은 수명이 오래가고 파편적인 지식일수록 수명이 짧다. 그래서 본질을 추구하며 에피파니(Epiphany)를 경험한 사람은 그렇지 않은 사람에 비해서 공부로 인한 스트레스를 덜 받는다. 중요한 것과 중요하지 않은 것을 구별하는 혜안이 있기 때문이다.
두 사람의 개발자가 있다고 하자. 한 사람은 최신 트렌드에 밝다. 아마존 람다를 이용해서 서버리스 시스템을 구축하고, 코세라 강의를 들으며 머신러닝을 공부한다. 페이스북에서 친구들이 공유하는 새로운 도구를 건드려보며 지식을 확장하고, 컨퍼런스와 스터디를 참석하여 동기를 부여 받는다. 함수형 언어를 학습하고, 새로운 파이썬 라이브러리도 사용하고, 리액트와 앵귤러로 코드를 짜서 웹사이트도 구축해본다. 부지런하다.
다른 한 사람은 최신 트렌드에 관심이 없다. 대신 회사에서 주어지는 요구사항을 날카롭게 분석하고, 꼼꼼한 설계과정을 거쳐서 코드를 작성하고, 정밀하게 테스트하고, 출시가 성공적으로 끝나면 다음 요구사항을 읽는다. 20년째 한 언어를 사용해서 코딩을 하고 있으며 다른 언어나 플랫폼에 대해서 관심이 없다. 하지만 그의 추상은 도메인주도 개발이나 디자인 패턴을 기계적으로 적용하는 수준을 뛰어넘는다. 요구사항을 코드로 바꾸는 과정에서 필요한 추상을 스스로 만들어내고 새로운 구조물의 상호작용, 데이터의 무결성, 성능 등을 빈틈없이 사고한다. 철두철미하다.
회사에서 새로 만들어야 하는 중요한 소프트웨어 제품이 있다고 하자. 이 제품을 잘 설계해서 정해진 시간 안에 출시함으로써 회사의 비즈니스에 결정적인 도움을 주어야 하는 상황이다. 이런 상황이라면 둘 중 누구에게 일을 맡길 것인가? 아이디어의 타당성을 검증하는 POC(Proof of Concept) 프로젝트나 단순한 R&D 업무라면 최신 트렌드에 밝은 사람을 고려할 수 있을 것이다. 하지만 비즈니스의 성공과 직결되는 실전이라면 그럴 수 없다. 실전이 필요로 하는 사람은 두 번째 유형이다. 그가 가진 능력이 프로그래밍의 본질에 더 가깝기 때문이다. (첫 번째 사람이 두 번째 사람이 가진 능력까지 가지고 있다면 이야기는 달라진다.)
개발자가 공부하는 것은 그래서 두 번째 유형의 사람이 가진 능력, 본질적인 능력을 키우는 것을 의미한다. 프로그래밍의 본질은 문제의 해결이다. 트렌드를 좇는 것은 파편적인 지식을 획득하는 것에 불과하기 때문에 큰 의미가 없다. 페이스북이나 트위터의 타임라인을 보면 수만가지 새로운 기술과 도구가 날마다 쏟아진다. 좋은 개발자라면 그런 것들을 모두 알아야 하는가? 전혀 그렇지 않다. 파편적인 지식은 파편적인 태도만으로 충분하다. 트렌드에 필요한 것은 가벼운 눈팅이지 공부가 아니다. 공부는 본질에 다가서려는 노력이다.
나는 프로그래머다 컨퍼런스에서 한 참석자가 ‘실력을 키우려면 어떻게 해야하는가’라는 질문을 한 적이 있다. 나는 그때 실력이 무엇을 의미하는지부터 생각해보자고 대답했다. 우리는 종종 실력을 이미 알고 있는 지식의 총량으로 착각한다. 실력과 지식의 총량은 희미한 상관관계가 있기는 하지만 사실상 무관하다. 진짜 실력은 임기응변이기 때문이다. 실력은 주변상황에 휘둘리지 않는 집중력이다. 해결해야 하는 문제가 무엇인지 알아채는 감각이다. 처음 본 문제를 해결하는 능력이다. 이러한 임기응변, 집중력, 감각, 그리고 능력은 이미 알고있는 지식으로부터 나오는 것이 아니다. 그것은 본질에 다가가기 위해서 감내해온 고통, 불면의 밤, 좌절, 환희, 이런 것으로 점철된 뜨거운 경험에서 나오는 것이다. 그래서 실력은 지식의 총합이 아니다. 고통의 총합이다.
여러분이 페이스북 타임라인을 보다가 누가 공유한 새로운 기술에 대한 링크를 저장했다고 하자. 영원히 볼 일이 없는 글을 저장하는 행위는 쇼핑몰 사이트에서 위시리스트나 보관함에 마음에 드는 상품을 담는 심리와 정확히 일치한다. 즉, 그것은 공부가 아니라 쇼핑이다. 쇼핑과 눈팅이 자체로 의미없는 일은 아니지만 그걸 공부로 착각하는 사람은 파편적인 지식의 늪에서 빠져나오기 어려울 것이다.
개발자에게 공부가 무엇을 의미하는지 알아보았으니 어떻게 공부해야 하는지에 대해서도 잠깐 짚어보자. 지면관계상 짧은 아포리즘 형식으로 나열해 보았다.
1. 지금 다니고 있는 회사에서 하는 일을 잘하기 위해서 노력하는 것이 가장 좋은 공부다.
2. 회사에서 하는 일과 개인적으로 공부하는 내용을 최대한 근접시키기 위해서 노력하라.
3. 새로운 기술을 익히는 최선의 방법은 스스로 문제를 정의한 다음, 새로운 기술을 이용해서 그 문제를 풀어보는 것이다. 책을 읽거나 동영상을 보는 것은 그보다 하위수준의 방법이다.
4. 신기술을 좇는 메뚜기가 되지 말라.
5. 모든 것을 알아야 한다는 강박을 버려라. 미리 획득하는 지식의 99%는 무용지물이다. 필요할 때 필요한 기술을 익힐 수 있는 것이 능력이다. 그 능력을 키워라.
6. 이상한 나라의 앨리스에 나오는 토끼굴(rabbit hole)을 피하라. 카테고리이론을 알아야 함수형 언어를 쓸 수 있는게 아니고, 선형대수학을 공부해야 머신러닝을 할 수 있는게 아니다. 토끼굴에 빠져서 한없이 들어가다보면 비본질적인 공부에 시간을 허비하게 된다.
7. 겉만 핥는 것은 경박하지만 토끼굴에 빠지는 것은 우매하다. 둘 사이의 적당한 지점에서 균형을 잡는 것이 개발자의 능력이다.
8. 머리에 들어오지 않는 어려운 개념이나 용어는 자투리 시간을 이용해서 반복적으로 읽고 암기하라. 나중에 큰 그림을 공부할 때 도움이 된다.
9. 항상 겸손해야 하지만 동시에 자긍심을 가져라. 그대가 지금 작성한 코드, 지금 읽은 책, 지금 공부한 내용을 그대보다 잘 아는 사람은 지구상에 없다. 모든걸 알고 있는 것처럼 보이는 다른 사람들도 그대와 마찬가지로 불안해하고, 위축되고, 두려워하면서 살아가고 있다. 자긍심이란 그런 타인을 돕고자 하는 마음가짐의 다른 이름이다.
10. 혼자 하지 말고 함께 공부하라.
이 시점에서 가슴에 손을 얹고 스스로 질문해보기 바란다. 공부가 재밌는가? 정말 재밌는가? 새로운 기술을 익히고, 키보드를 두드리고, 결과를 확인하고, 친구들과 이야기하는 모든 경험이 그대를 행복하게 만드는가? 이 질문에 대한 대답이 예스라면, 그 예스의 강도만큼 그대의 미래는 성공이 보장되어 있는 것이다. 그러므로 개발자는 미래에 대해 불안해할 필요가 없다. 미래의 성공은 예스라는 작은 변수의 함수이기 때문이다. 그 변수는 개발자 자신의 손에 놓여 있다.
SQL Server 테이블을 저장 하려고 하면 오류 메시지: "변경 내용 저장 허용 되지 않습니다"
적용 대상: Microsoft SQL Server 2008 ExpressMicrosoft SQL Server 2008 Express with Advanced ServicesMicrosoft SQL Server 2008 Standard 자세히
중요: 본 문서는 전문 번역가가 번역한 것이 아니라 Microsoft 기계 번역 소프트웨어로 번역한 것입니다. Microsoft는 번역가가 번역한 문서 및 기계 번역된 문서를 모두 제공하므로 Microsoft 기술 자료에 있는 모든 문서를 한글로 접할 수 있습니다. 그러나 기계 번역 문서가 항상 완벽한 것은 아닙니다. 따라서 기계 번역 문서에는 마치 외국인이 한국어로 말할 때 실수를 하는 것처럼 어휘, 구문 또는 문법에 오류가 있을 수 있습니다. Microsoft는 내용상의 오역 또는 Microsoft 고객이 이러한 오역을 사용함으로써 발생하는 부 정확성, 오류 또는 손해에 대해 책임을 지지 않습니다. Microsoft는 이러한 문제를 해결하기 위해 기계 번역 소프트웨어를 자주 업데이트하고 있습니다.
원본 영어 문서 보기: 956176
증상
데이터 정의 언어 (DDL)를 사용 하 여 테이블을 수정 하 고 다음 Microsoft SQL Server 2008의 테이블을 저장 하려고 하면 다음과 같은 메시지가 나타날 수 있습니다.
변경 내용 저장 허용 되지 않습니다. 변경 내용을 삭제 하 고 다시 만든 다음 표 필요 합니다. 있는 내용을 하나 다시 만들 수 없거나 하는 변경 내용을 저장 안 함 옵션을 사용 하는 테이블에 변경 내용이 필요한 테이블을 다시 만들어야 합니다.
원인
테이블에 다음 변경 중 하나 이상을 확인 하 고 표 재작성 해야 하는 변경 내용을 저장 안 함 옵션을 사용 하면이 문제가 발생 합니다.
열의 Null 허용 설정을 변경합니다.
테이블의 열 순서를 변경 하는.
열 데이터 형식 변경
새 열을 추가 합니다.
테이블의 메타 데이터 구조를 변경 하 고 다음 테이블을 저장 하는 테이블을 변경할 때 테이블 다시 만들어야 변경이 사항에 따라. 테이블을 다시 만드는 동안 메타 데이터 손실에서 및 직접 데이터 손실이 발생할 수 있습니다이. SQL Server Management Studio (SSMS) 옵션 창의 디자이너 섹션에서 테이블 다시 생성 해야 하는 변경 내용을 저장 안 함 옵션을 사용 하는 경우 "현상" 절에 나와 있는 오류 메시지가 나타납니다.
해결 방법
이 문제를 해결 하려면 Transact SQL 문을 사용 하 여 테이블의 메타 데이터 구조를 변경 합니다. 자세한 내용은 SQL Server 온라인 설명서의 다음 항목을 참조 하십시오.
테이블 다시 생성 해야 하는 변경 내용을 저장 안 함 옵션을 변경 하려면 다음과이 같이 하십시오.
SQL Server Management Studio (SSMS)를 엽니다.
도구 메뉴에서, 옵션을 클릭합니다.
옵션 창의 탐색 창에서 디자이너를 클릭 합니다.
선택 하거나 표 재작성 해야 하는 변경 내용을 저장 안 함 확인란의 선택을 취소 하 고 확인을 누릅니다.
참고: 이 옵션을 해제 하면 없습니다 경고가 표시 테이블을 저장할 때 변경 내용을 테이블 메타 데이터 구조를 변경 했습니다. 이 경우 테이블을 저장 하면 데이터 손실이 발생할 수 있습니다.
"표 재작성 해야 하는 변경 내용을 저장 안 함" 옵션을 해제 하면 위험
이 옵션을 해제 하면 테이블을 다시 만들지 않도록 하는 데 도움이 수, 있지만 변경 내용 손실 될 수도 있습니다. 예를 들어, 테이블에 변경 내용을 추적 하는 SQL Server 2008의 변경 내용 추적 기능을 설정 하면 됩니다. 하도록 테이블을 다시 만들어야 하는 작업을 수행할 때 "현상" 절에 나와 있는 오류 메시지가 나타납니다. 그러나이 옵션을 해제 하면 테이블을 다시 만들 때 기존 변경 내용 추적 정보 삭제 됩니다. 따라서 옵션을 해제 하 여이 문제를 해결 작동 하지 않습니다 하는 것이 좋습니다.
테이블에 대해 변경 내용 추적 기능을 사용할지를 결정 하려면 다음이 단계를 수행 합니다.
SQL Server Management Studio 개체 탐색기에서 테이블을 찾습니다.
테이블을 마우스 오른쪽 단추로 클릭 한 다음 속성을 클릭 합니다.
표 속성 대화 상자에서 변경 내용 추적을 클릭 합니다.
변경 내용 추적 항목의 값이 True이면 테이블에 대해이 옵션이 활성화 됩니다. 값이 False이면이 옵션이 비활성화 됩니다.
변경 내용 추적 기능을 사용 하는 경우 Transact SQL 문을 사용 하 여 테이블의 메타 데이터 구조를 변경 합니다.
이 문제를 재현하는 단계
SQL Server Management Studio 테이블 디자이너 도구에서 기본 키를 포함 하는 테이블을 만듭니다.
이 테이블이 포함 된 데이터베이스를 마우스 오른쪽 단추로 클릭 한 다음 속성을 클릭 합니다.
데이터베이스 속성 대화 상자에서 변경 내용 추적을 클릭 합니다.
변경 내용 추적 항목의 값을 True로 설정 하 고 확인을 클릭 합니다.
테이블을 마우스 오른쪽 단추로 클릭 한 다음 속성을 클릭 합니다.
표 속성 대화 상자에서 변경 내용 추적을 클릭 합니다.
변경 내용 추적 항목의 값을 True로 설정 하 고 확인을 클릭 합니다.
도구 메뉴에서, 옵션을 클릭합니다.
옵션 대화 상자에서 디자이너를 클릭 합니다.
테이블 다시 생성 해야 하는 변경 내용을 저장 안 함 확인란을 선택 하려면 클릭 한 다음 클릭 확인 합니다.
위의 플러그인은 maven-dependency-plugin 입니다. 해당 모듈과 의존성 관계를 맺고 있는 모든 항목을 해당 모듈 디렉토리의 lib 폴더로 복사하게 됩니다. phase 태그에서 install로 지정되어 maven의 goal이 install 단계일 때 해당 플러그인의 기능이 수행됩니다.
저의 경우 dms-core 모듈에 Main 클래스가 존재하니 위의 과정을 dms-core 모듈의 pom.xml에 적용하였습니다.
다음으로 Maven Build Configuration에서 goals를 clean install로 설정하고 Run을 클릭! (자세한 내용은 이전 포스팅에서 확인해 주세요) 성공적으로 build가 되었다면 해당 모듈의 디렉토리를 열어보도록 합시다.
해당 모듈의 디렉토리에 가보면 target 폴더가 생성되어 있습니다. 들어가 보시면 위의 사진과 같이 해당 모듈의 jar 파일과 lib 폴더가 생성되어있을 것입니다. (아니라면 플러그인을 잘못 등록하셨거나 빌드가 잘못된 것일 수도)
그럼 이제 cmd 창을 열어 해당 디렉토리에 접근한 뒤 다음 명령어를 통해 jar 파일을 실행시킬 수 있습니다.
java -jar 모듈이름.jar
■ 마무리
InteiliJ의 경우 Maven 프로젝트를 IDE 내에서 실행시키는 기능을 제공해주고 있는데 eclipse는 그게 되는지조차 모르겠습니다. 다음에 한 번 확인해 본 뒤에 포스팅해보도록 하겠습니다.
소프트웨어 개발을 하면 할수록 인생의 지혜를 얻게 된다. 어떤 이들은 개발은 단순한 작업이 아닌, 삶을 사는 방식이라고도 말한다. 코드를 작성하는 일 자체가 직장과 일상 속에서 자신의 모습을 구현하는 일이기 때문이다. 깃허브(GitHub)에는 개발자 속담(Programmer’s Proverbs)이라는 저장소가 생성됐는데, 개발자를 위한 지혜로운 문장들을 모아놓은 것이다. 이제 미래 세대를 이끌어나갈 새싹들이 보고 배울 지혜에 대해 알아보도록 한다.
개발자의 현실 - 때로는 QA의 역할을 때로는 버그 수정 역할을 감당해야 한다는 사실을 인정하라. - 일을 잘할수록 남들은 난이도가 쉽다고 생각한다.
개발자 사명서 - A/B 시험은 두 번 진행하고 변경사항을 한 번에 배치하라. - 게으름이 자신의 가장 좋은 친구이다. 한 번에 자동화할 수 있는 것을 두 번 하지 마라. - 최고의 요청은 아예 요청하지 않는 것이다. - 웹 표준만 설정할 수는 없다. - 자신의 데이터 구조를 파악하면 코드는 자연히 따라갈 것이다. - 오래된 코드 중 일부는 다시 작성할 수 없고, 약간만 변경해도 깨져버린다. - 취했을 때 자신이 춤추는 모습을 떠올리고 다음에 맥주를 마시고 코드를 작성할 때는 책임을 져야 한다. - 술에 취했을 때는 상사와 대화하지 마라. - 많은 시도를 통해 더 높은 품질을 달성할 수 있는 경우가 많다. - 최종 버전의 성공은 거짓이다. 반복만이 있을 뿐이다. 반복을 통해 더 나은 제품을 얻는다. 더 나은 제품을 통해 인기를 얻는다. 인기를 통해 성공을 얻는다. 성공을 통해 잘못 이해한 기술 사양이 깨진다. 개발 사이클이 우리를 자유롭게 하리라. - 버전 관리에 신경 써야 한다. - 데모 페이지를 위한 프레임워크를 선택하는 대신에 코드를 위해 선택하라. - 측정하기 전에 절대로 최적화하지 말라 - 지트(Git)에서 있었던 일은 지트에 남겨 둔다. - 포리치 루프(Foreach Loop)를 피하면 CPU 사이클을 얻는다.
개발은 하루아침에 이뤄지지 않는다 - 프로그래머가 백 명이라도 2년짜리 프로젝트를 일주일 만에 끝낼 수 없다. - 페이스북은 하루아침에 만들어지지 않았다. - 호프스태터(Hofstadter)의 법칙에 따르면 프로젝트를 위해 필요한 시간보다 더 많은 시간을 더해야 한다. 왜냐하면, 호프스태터의 법칙을 고려하더라도 생각한 것보다 더 오래 걸리기 때문이다.
개발은 기초작업이 중요하다 채색하기 전에 밑그림을 그리듯이, 소프트웨어도 설계와 시공에 대한 가이드가 될 큰 밑그림이 필요하다. 이를 '아키텍처'라고 부르는데, 일단 시스템이 개발된 뒤에는 잘못된 구조를 바로잡기가 쉽지 않다는 점에서 매우 중요한 작업이다.
- 프로토타입 없이 완성품을 만들지 마라. - 표준문안이 없다면 개발도 빠를 수 없다. - 아키텍처와 디자인은 실행 시간의 핵심이 아니라 문제와 변화를 위한 대비책이다. - 장기 지원이 필요한 애플리케이션의 아키텍처를 남겨두라.
간결성은 핵심이다 - 충분히 복잡한 앱 아키텍처는 스파게티 코드와 차이가 없다. - 코드를 간소화하라. 읽고 이해하기 힘든 코드는 골치 아픈 잔재가 될 뿐이다. - 코드가 간소할수록 버그가 적다.
디버깅 입력 데이터 유효성을 검증하는 것에 각별한 주의를 쏟아야 하는 부분이다. 버퍼 초과나 SQL 인젝션 공격에 이르기까지, 아주 흔한 보안 취약점은 올바른 입력 포맷인지 검증하지 않은 사용자 입력에 근거한 코드가 직접적인 원인인 경우가 많다. 한편으로는 제품을 출시하기 전에 많은 단위 테스트를 진행할수록 나중에 정식 출시 후 나비효과처럼 불어날 피해에 대한 근본적인 대책을 마련하는 데 도움이 된다.
- 모니터링하지 않는 앱을 배치하는 것은 연료계 없이 자동차 여행을 떠나는 것과 같다. - 프로그램을 작성하는 것보다 디버깅할 때 두 배나 똑똑해야 하므로 동료에게 검토를 부탁하라. 왜냐하면, 자신의 코드를 디버깅할 만큼 똑똑할 수는 없기 때문이다. - 동료의 코드 검토가 없는 코딩 스타일가이드는 자발적인 세금으로 국가를 운영하는 것과 같다. - 처음부터 자신이 문제라는 사실을 인정하면 디버깅이 훨씬 쉬워진다. - 프로그래머에게 올바른 코드를 주면 하루 동안 일 할 수 있다. 프로그래머에게 디버깅을 가르치면 평생 일할 수 있다. - 지락 구드(Chirag Gude) - 디버깅(Debugging)보다는 시험이 쉽다. - 동료가 검토하거나 자신이 사는 곳을 알고 있는 폭력적인 사이코패스가 유지 관리한다고 가정할 때만 오래도록 지속하는 코드를 작성할 수 있다. - 코드에 대한 불만은 코드 재작성에 도움이 되지 않는다. - 시스템이 완벽하게 동작하면 그 안에 뭐가 있는지 아무도 관심을 갖지 않는다. 문제가 발생하면 시스템 디자인과 아키텍처가 자신의 운명을 결정하게 될 것이다. - "그냥 넘겨"라는 말로 설계를 대신할 수는 없다
새 출발이 더 나은 대안일 수도 있다 전임 개발자가 작성한 코드 일부분을 유지 보수하거나 디버깅하는 작업은 정말 어려운 일이다. 기존 코드 한 조각의 작동 원리를 파악하고, 최초 개발자의 의도를 파악하는 것, 특히 문서나 주석이 엉망일 경우에는 거의 불가능에 가깝다. 중복된 코드를 남발하거나 억지로 갖다 붙인 결과, 지나치게 비대해진 취약한 코드 베이스만 남을 뿐이다. 기존의 것에 새로운 기능을 연이어서 탑재하려는 욕심을 우선 버려야 하며, 기존 코드의 질과 정비 용이성을 평가하는 것이 우선이다. 코드 재작성 비용을 청구하는 것이 업그레이드 개발을 하는 것보다 더 저렴할 수도 있다.
- 레거시 코드를 다시 작성하면 품질이 나아진다. - 다시 작성하라. 유지 관리가 불가능한 레거시 코드를 위한 패치는 존재하지 않는다. - 때로는 레거시 지원을 중단해야 새로운 제품이 피어날 수 있다. - 오랜 시간 작업할수록 코드 수가 늘어난다. 대부분 최고의 품질에서 역행하고, 버그를 유발하는 기능들이다.
끊임없는 자기개발 C#, 자바, 자바스크립트 등 전세계적으로 많이 쓰이는 개발 언어들 이외에도 스위프트 등의 새로운 언어들이 대세로 떠오르고 있다. 고지식한 개발자라 하더라도 이와 같은 변화와 새로운 기술을 익히는 데 언제까지나 저항할 수는 없는 노릇이다. '죽어도 다른 언어로는 개발하지 않겠다'는 식의 미숙한 발언은 피해야 한다. 개발자라면 무릇 하나 이상의 개발 언어를 잘 알아야 하며, 새롭게 떠오르는 주제에 대해서도 잘 알아야 한다.
새로운 기술이 번져가기 시작하면, 최소한 그 배경과 그 기술의 작동 원리를 이해할 필요는 있다. 세부적인 사항은 그 기술이 요구사항을 해결하는 데 도움이 될 때 파악해도 늦지 않다. 오래된 도구로는 새로운 문제를 해결할 수 없다는 점을 기억하고, 계속해서 새로운 언어를 익혀나가야 한다.
- 말을 잘하는 개발자는 빨리 일자리를 찾을 수 있지만, 마지막 순간에 간단한 시험에서 실패한다. - 더 많은 기술을 배울수록 자신이 아는 것이 별것 아니라는 것을 알게 된다. - 프로그래밍 언어를 배우고 새로운 개발자가 되라. - 형편없는 프로그래머가 언어를 탓한다. - 더 이상 배우지 않고 쉬운 길을 택하면 기존의 방법론에서 영원히 벗어나지 못하게 될 것이다. - 오늘의 유행은 내일의 구식. - 잘 알려지지 않고 이상한 언어를 배우면 이해의 폭과 깊이가 넓어진다.
오픈소스 오픈소스를 잘 활용하면 잠재적인 고용주에게 자신의 능력을 보여줄 있다. 오픈소스 커뮤니티에서는 '직접 이 부분을 작성했다'고 말하는 데 그 어떤 제약도 없는데, 특히 커미터(Committer) 지위를 얻었다는 것은 협동심이 있고, 진행 중인 프로그램에 기여할 수 있는 능력이 있다는 것을 어필하는 것이다.
옴니TI(OmniTI)에서 15년이상 개발자로 일해온 로버트 트리트는 "사이드 프로젝트(Side Proejct)나 오픈소스 커뮤니티에 참여해서 다양한 기술을 사용하는 기업에 입사하는 것도 좋은 방법"이라고 말했다. 물론, 여러 조직의 전문가, 준전문가 등 다양한 사람들이 협력하는 만큼 '다시는 만나고 싶지 않은 사람'으로 낙인찍힐 수도 있음을 주의해야 한다.
- 오픈소스 개발자는 개인의 명성을 추구하지 않는다. - 오픈소스 프로젝트에서의 협업으로 우정과 커뮤니티를 얻음과 동시에 파벌과 전쟁도 생겨난다. - 공개적인 코드 검토로 더 나은 자신이 될 수 있다. 더 나은 활동, 더 스마트한 솔루션, 개발자로서의 성장을 얻거나 깨지게 된다.
건강이 우선이다 개발자들은 컴퓨터 앞에서 많은 시간을 보낸다. 그러나 제때에 적절한 휴식을 취하지 않으면 안구건조증, 거북목, 손목 터널 증후군, 근막통증후군 등에 걸려 종합병원 신세를 면치 못할 수도 있다. 프로가 되기 위해서는 건강 관리도 병행하는 것이 무엇보다 필수다.
- 억지로 잠을 자라. - 바보는 의사를 멀리한다. - 지칠 때까지 코드를 작성하는 개발자는 생각 없이 산다. - 모든 애플리케이션은 화면을 껐을 때 아름답다.
기타 - 수염을 깎지 못할 정도로 개발에 몰두하고 있는 정도라면 이미 그 수염이 자라 백발이 된 사람은 최소 백 명이다. - 고객이 최고의 시험자이다. - 오류 로그만큼은 없을 때 아름답다. - 마케팅 담당자는 QA가 아니고 개발자는 홍보를 하지 않는다. - 무료 사용자에게 행복감을 주는 제품은 재정이 바닥나면 투자자를 겁먹게 할 뿐이다. - 하나는 하나 이상의 일을 하지 않는다. - 언젠가라는 말이 가장 쉽다. - 가장 매력적인 풀(Pull) 요청은 빨간색으로 도배되어 있다. - 개발자는 먼 곳에서 동료를 찾는다. - 코드의 미학을 스스로 터득할 수는 있지만 다른 사람들도 쉽게 배울 수 있으리라 착각하지 마라.
자바스크립트는 프로토타입 기반 언어라고 불립니다. 자바스크립트 개발을 하면 빠질 수 없는 것이 프로토타입인데요. 프로토타입이 거의 자바스크립트 그 자체이기때문에 이해하는 것이 어렵고 개념도 복잡합니다.
하지만 프로토타입이 무엇인지 깨우친 순간 자바스크립트가 재밌어지고, 숙련도가 올라가는 느낌을 팍팍 받을 수 있습니다. 그럼 지금부터 프로토타입을 이해해봅시다.
Prototype vs Class
클래스(Class)라는 것을 한 번쯤은 들어보셨을겁니다. Java, Python, Ruby등 객체지향언어에서 빠질 수 없는 개념이죠. 그런데 중요한 점은 자바스크립트도 객체지향언어라는 것입니다. 이게 왜 중요하냐구요? 자바스크립트에는 클래스라는 개념이 없거든요. 대신 프로토타입(Prototype)이라는 것이 존재합니다. 자바스크립트가 프로토타입 기반 언어라고 불리는 이유이죠.
클래스가 없으니 기본적으로 상속기능도 없습니다. 그래서 보통 프로토타입을 기반으로 상속을 흉내내도록 구현해 사용합니다.
참고로 최근의 ECMA6 표준에서는 Class 문법이 추가되었습니다. 하지만 문법이 추가되었다는 것이지, 자바스크립트가 클래스 기반으로 바뀌었다는 것은 아닙니다.
어디다 쓰나요?
그럼 프로토타입을 언제 쓰는지 알아봅시다.
넌 이미 알고있다
자바스크립트에 클래스는 없지만 함수(function)와 new를 통해 클래스를 비스무리하게 흉내낼 수 있습니다.
function Person() { this.eyes = 2; this.nose = 1; }
자바스크립트 개발을 하시는 분이라면 아마 써보진 않았어도 최소한 본 적은 있을겁니다. 간단히 설명하자면 Person.prototype이라는 빈 Object가 어딘가에 존재하고, Person 함수로부터 생성된 객체(kim, park)들은 어딘가에 존재하는 Object에 들어있는 값을 모두 갖다쓸 수 있습니다. 즉, eyes와 nose를 어딘가에 있는 빈 공간에 넣어놓고 kim과 park이 공유해서 사용하는 것이죠. 이해되셨나요?
프로토타입을 깊게 파보면 엄청나게 복잡하지만 개발자가 사용하는 부분만 본다면 이게 거의 전부입니다. 하지만 개발자는 사용법만 알고있는게 아니라 언제나 왜? 를 생각해야합니다.
프로토타입이 왜 이렇게 쓰이는지 조금 더 깊게 알아보도록 하겠습니다.
Prototype Link와 Prototype Object
자바스크립트에는 Prototype Link 와 Prototype Object라는 것이 존재합니다. 그리고 이 둘을 통틀어 Prototype이라고 부릅니다. 프로토타입을 좀 안다는 것은 이 둘을 완벽히 이해하고 갖고 놀 수준이 되었다는 뜻입니다.
제가 프로토타입에 대해 공부하면서 중요하다고 생각되는 포인트가 몇 가지 있었습니다. 그 포인트들을 잘 이해하면서 보시기 바랍니다.
Prototype Object
모든 객체(Object)의 조상은 함수(Function)입니다.
function Person() {} // => 함수
var personObject = new Person(); // => 함수로 객체를 생성
personObject 객체는 Person이라는 함수로부터 파생된 객체입니다. 이렇듯 언제나 객체는 함수로부터 시작됩니다. 여러분이 많이 쓰는 일반적인 객체 생성도 예외는 아닙니다.
var obj = {};
얼핏보면 함수랑 전혀 상관없는 코드로 보이지만 위 코드는 사실 다음 코드와 같습니다.
var obj = new Object();
위 코드에서 Object가 자바스크립트에서 기본적으로 제공하는 함수입니다.
Object도 함수다!
Object와 마찬가지로 Function, Array도 모두 함수로 정의되어 있습니다. 이것이 첫 번째 포인트입니다.
그렇다면 이것이 Prototype Object랑 무슨 상관이있느냐? 함수가 정의될 때는 2가지 일이 동시에 이루어집니다.
1.해당 함수에 Constructor(생성자) 자격 부여
Constructor 자격이 부여되면 new를 통해 객체를 만들어 낼 수 있게 됩니다. 이것이 함수만 new 키워드를 사용할 수 있는 이유입니다.
constructor가 아니면 new를 사용할 수 없다!
2.해당 함수의 Prototype Object 생성 및 연결
함수를 정의하면 함수만 생성되는 것이 아니라 Prototype Object도 같이 생성이 됩니다.
함수를 정의하면 이렇게 됩니다
그리고 생성된 함수는 prototype이라는 속성을 통해 Prototype Object에 접근할 수 있습니다. Prototype Object는 일반적인 객체와 같으며 기본적인 속성으로 constructor와 __proto__를 가지고 있습니다.
prototype 속성으로 Prototype Object에 접근
constructor는 Prototype Object와 같이 생성되었던 함수를 가리키고 있습니다. __proto__는 Prototype Link입니다. 밑에서 자세히 설명합니다.
Prototype Object는 일반적인 객체이므로 속성을 마음대로 추가/삭제 할 수 있습니다. kim과 park은 Person 함수를 통해 생성되었으니 Person.prototype을 참조할 수 있게 됩니다.
Prototype Link를 보기 전에 Prototype Object를 어느 정도 이해하시고 보기 바랍니다. 함수가 정의될 때 이루어지는 일들을 이해하는 것이 두 번째 포인트, Prototype Object를 이해하는 것이 세 번째 포인트입니다.
Prototype Link
kim 객체는 eyes가 없는데 ??
kim에는 eyes라는 속성이 없는데도 kim.eyes를 실행하면 2라는 값을 참조하는 것을 볼 수 있습니다. 위에서 설명했듯이 Prototype Object에 존재하는 eyes 속성을 참조한 것인데요, 이게 어떻게 가능한걸까요??
바로 kim이 가지고 있는 딱 하나의 속성 __proto__가 그것을 가능하게 해주는 열쇠입니다.
prototype 속성은 함수만 가지고 있던 것과는 달리(Person.prototype 기억나시죠?) __proto__속성은 모든 객체가 빠짐없이 가지고 있는 속성입니다.
__proto__는 객체가 생성될 때 조상이었던 함수의 Prototype Object를 가리킵니다. kim객체는 Person함수로부터 생성되었으니 Person 함수의 Prototype Object를 가리키고 있는 것이죠.
드디어 __proto__를 공개합니다
__proto__를 까보니 역시 Person 함수의 Prototype Object를 가리키고 있었습니다.
객체, 함수, Prototype Object의 관계
kim객체가 eyes를 직접 가지고 있지 않기 때문에 eyes 속성을 찾을 때 까지 상위 프로토타입을 탐색합니다. 최상위인 Object의 Prototype Object까지 도달했는데도 못찾았을 경우 undefined를 리턴합니다. 이렇게 __proto__속성을 통해 상위 프로토타입과 연결되어있는 형태를 프로토타입 체인(Chain)이라고 합니다.
프로토타입 체인, 최상위는 Object
이런 프로토타입 체인 구조 때문에 모든 객체는 Object의 자식이라고 불리고, Object Prototype Object에 있는 모든 속성을 사용할 수 있습니다. 한 가지 예를 들면 toString함수가 있겠습니다.
<GlobalNamingResources><Resourceauth="Container"description="User database that can be updated and saved"factory="org.apache.catalina.users.MemoryUserDatabaseFactory"name="UserDatabase"pathname="conf/tomcat-users.xml"type="org.apache.catalina.UserDatabase"/><Resourcename="jdbc/testdb"auth="Container"factory="com.zaxxer.hikari.HikariJNDIFactory"type="javax.sql.DataSource"minimumIdle="5"maximumPoolSize="10"connectionTimeout="300000"driverClassName="com.mysql.jdbc.Driver"jdbcUrl="jdbc:mysql://127.0.0.1:3306/test_db"username="root"password="1234"/></GlobalNamingResources>
<!-- JNDI 설정 --><resource-ref><description>test</description><res-ref-name>jdbc/testdb</res-ref-name><res-type>javax.sql.DataSource</res-type><res-auth>Container</res-auth></resource-ref>
Unlike single parameter, multiple parameters are not declared in the same place where they are used and this makes the coding less productive, maintainable and readable.
An alternative to annotation for having full declaration and usage in the mapper file would be something like:
public class WebUtil { // 문자열 변환 String a= "abc" => replace(a, "c") => a : ab public String strReplace(String s1, String s2){ String res = ""; StringTokenizer str = new StringTokenizer(s1, s2);
while(str.hasMoreTokens()){ res += str.nextToken(); System.out.println(res); } return res; } }
JavaScript는 동적 타입이면서 함수로의 인자 전달이 유연하기 때문에 사용에 주의가 요구됩니다.
중복 정의
Java에서는 함수를 중복 정의하면 에러가 발생합니다.
하지만 JavaScript에서는 함수를 중복으로 정의해도 에러가 발생하지 않고 대신 마지막 함수만 유효하게 사용됩니다. 이에 대한 사례는 사용되지 않는 코드를 참고하세요.
호출 인자 누락
호출자(caller)가 함수에 인자를 전달하지 않았는데 함수 내에서 해당 인자를 사용하는 경우입니다.
다음의 예를 보죠.
checkDateFormat 함수를 두 개의 인자 date와 datePattern으로 호출합니다.
functionsetCondition(rowId){try{...var date =getCellEditingValue("input", rowId,"startDate", $tr);var result =checkDateFormat(date, datePattern);if(!result.success){thrownewError("date is not vaild.");}
호출된 checkDateFormat 함수에서는 위에서 전달되지 않은 dateName 인자를 사용합니다.
그 결과 statusCodeId 파라미터가 “undefined”라는 문자열로 서버에 전달되므로 서버에서 이에 대한 처리가 필요할 수 있습니다. 따라서 클라이언트 측에서 해당 속성 존재 여부를 서버 전달 전에 명확하게 체크하는 것이 좋습니다.
API 호출 시 인자 타입 오류
JavaScript built-in 함수나 DOM API 함수는 정해진 타입의 인자가 있어서 잘못된 타입의 인자로 호출하는 경우 TypeError가 발생합니다.
가령 아래 코드 실행 시 TypeError: Argument 1 of Node.appendChild is not an object. 에러가 발생합니다.
document.body.appendChild('foo');
제가 개발 중인 솔루션에서는 built-in 함수와 DOM API 함수 모델링을 통해 인자 타입 정보를 내장하여 실행 전에 소스 레벨에서 아래와 같이 검출할 수 있습니다.first argument type of Node.prototype.appendChild() API must be Node DOM instance object.
API 호출 시 인자 개수 오류
JavaScript built-in 함수나 DOM API 함수는 잘못된 개수의 인자로 호출하는 경우 TypeError가 발생할 수 있습니다.
가령 아래 코드 실행 시 TypeError: Not enough arguments to Document.getElementById. 에러가 발생합니다.
var elem = document.getElementById();
개발 중인 솔루션에서는 built-in 함수와 DOM API 함수 모델링을 통해 아래와 같이 검출됩니다.number of arguments of Document.prototype.getElementById() API must be 1
Wrap-Up
이상 JavaScript 함수 사용에 대해 알아보았습니다.
다른 언어와 다른 JavaScript 특성을 이해하고 함수 사용에 주의하세요.
JavaScript는 함수 오버로딩을 지원하지 않으므로 함수 정의를 중복하지 않도록 한다.
다양한 실행 경로에서 인자 및 인자 속성 정의가 잘 전달되는지 점검한다. 필요한 경우 함수 내에서 인자 및 속성에 대한 유효성 검사를 하는 것이 좋다.