Translate

2014년 10월 28일 화요일

[OSX][Mevericks] 리눅스에서 Samba 로 공유한 프린터에 연결하기



OS: OSX 10.9.4 (Mevericks)


윈도우에서 공유한 프린터에 연결 시 이따금씩 프린트가 되지 않는 문제가 발생했는데
([OSX] 프린트 할 시 '프린트 준비 완료' 라는 메시지와 함께 프린트가 되지 않는경우)

이번기회에 프린터를 Linux(CentOS) 에 연결 후 Samba 를 이용해 프린터를 공유했다.
(CentOS 6.5를 사용하는데 인터넷보고 했더니 생각보다 쉽게 프린터를 잡고 Samba 공유까지 마쳤다.)




윈도우에서는 해당 프린터 드라이버에 연결하기위해


시작 => 실행 => '\\{IP_ADDRESS}' 입력


접속을 하면 공유된 디렉토리와 프린터를 볼 수 있다.
해당 프린터를 더블클릭해서 프린터 드라이버 선택 후 잡아주면 되었다.





OSX 에서는 다음과 같이 공유프린터를 잡았다.
(삼성 SL-M2670FN 프린터 기준)


1. ‘시스템 환경설정’ => ‘프린터 및 스캐너'
2. 프린터추가버튼(+) 클릭
3. 톱니바퀴(고급) 버튼 클릭
4. 다음과 같이 선택 및 입력
  - 유형: Windows printer via spoolss
  - 장비: 다른장비
  - URL: smb://{IP_ADDRESS}/Samsung-M267x-287x-Series
  - 이름: {원하는 이름}
  - 위치: {원하는 위치} || 빈란
  - 사용: 소프트웨어 선택 => ’Samsung M267x 287x Series’ => 승인


PS.
1. 톱니바퀴가 없는경우
  - control 키를 누른 상태에서 "기본" 아이콘이나 도구 막대의 다른 아이콘을 클릭한 다음, 표시되는 빠른 메뉴에서 도구 막대 사용자화를 선택
  - 고급(톱니바퀴) 아이콘을 도구 막대로 드래그

2. 소프트웨어 선택에 ’Samsung M267x 287x Series’ 가 없는경우
  - http://www.samsung.com/sec/support/model/SL-M2670FN-downloads?downloadName=BM-P
    위의 링크에서 드라이버 선택 후 OSX용 드라이버 설치



윈도우처럼 아이피로만 접속 후 프린터를 선택하면 좋으련만..
공유된 프린터 이름을 정확히 알아야 공유된 프린터 설정이 가능하다.


2014년 10월 27일 월요일

[HTML][Javascript] 브라우저에서 이미지로딩 및 링크(link) 이동 시 리퍼러(referer) 넘기지 않는 방법



referer 를 빼고 서버에 요청을 보내는 방법은 몇가지가 있다.



언어 종류별로 방법은 조금씩 차이가 있지만

서버에서 사용하는 방법은 다음과 같은 방법이 있다.

1. 서버에서 HTTP요청(TCP)을 보낼 때 Header 정보를 수정하여 referrer 정보를 수정하거나 공백으로 보내는 방법

2. 서버에서 시스템의 curl 명령어를 이용하여 웹서버에 Request 후 Response 를 받는 방법



클라이언트에서 사용하는 방법은 다음과 같은 방법이 있다.

1. 브라우저에서 요청을 보낼 시 패킷을 캡쳐 후 변조하여 서버에 보내는 방법




하지만 서버에서 프로그램으로 구현을 해야 하거나 사용자가 툴 사용법을 익혀서 작업을 해야 하는 불편함이 있다.



ReferrerKiller(링크) 라는 페이지를 보고 링크를 눌러서 웹페이지 이동을 하면서 꼼수를 쓰지 않고 referer를 보내지 않는 방법을 알게되었다.


참 아이디어가 참신하고 대단하다는 생각이 들었다.
iframe 의 src 내부에 html 소스를 넣을 생각을 하다니..


ReferrerKiller 의 데모페이지의 소스는 아래와 같다.

<!doctype html>
<html>
 <header>
  <meta charset="utf-8" />
  <title>ReferrerKiller demo</title>
  <script src="ReferrerKiller.js"></script>
 </header>
 <body>
  <h1>Demonstration of how to prevent your browser of sending the referrer http header.</h1>
  <h3>Check the hack's source code <a href="ReferrerKiller.js">here</a>.</h3>
  <h2>Links</h2>
  <ul>
   <li>Not sending referrer <span id="url_kill_referrer"></span></li>
   <li>Sending referrer <a href="http://www.xhaus.com/headers" target="destiny">http://www.xhaus.com/headers</a></li>
  </ul>
  <iframe name="destiny" width="100%" height="460" src="about:blank"></iframe>
  <script>
   document.getElementById('url_kill_referrer').innerHTML = ReferrerKiller.linkHtml( 'http://www.xhaus.com/headers', 'http://www.xhaus.com/headers', { target: 'destiny' }, { verticalAlign: 'bottom' } );
  </script>
  <h2>Image uploaded to pixhost</h2>
  <ul>
   <li>Without sending referrer: <br/> <span id="image_kill_referrer"></span></li>
   <li>Sending referrer: <br/> <img src="http://img4.pixhost.org/images/1693/14341576_a_fun.jpg" /></li>
  </ul>
  <script>
   document.getElementById('image_kill_referrer').innerHTML = ReferrerKiller.imageHtml('http://img3.pixhost.org/images/2669/14341603_a_fun.jpg');
  </script>
 </body>
</html>


ReferrerKiller 라이브러리를 사용하는 방법은 너무나도 쉽다.
데모페이지를 보면 두가지 사용방법이 나온다.


1. ReferrerKiller.linkHtml(url, innerHTML, anchorParams, iframeAttributes)
2. ReferrerKiller.imageHtml(url, imgAttributesParam)





둘다 iframe 태그를 리턴하며 비어있는 iframe 내부에서 해당 URL을 호출하기 때문에 실질적으로 referer 가 없게된다.

때문에 URL을 바로 호출하던.. 아니면 링크를 누르던 스크립트를 통해 referer가 없는 페이지의 구현이 가능하다.


나중에 링크가 안될 수 있는 것을 염려하여 소스를 살짜쿵 퍼왔다.
소스의 주소는 다음과 같다.
http://referrer-killer.googlecode.com/git/ReferrerKiller.js

/**
 * @Project: ReferrerKiller.
 * @Licence: The MIT License.
 * @Author: Juan Pablo Guereca.
 * @Description: Crossbrowser referrer killing solution.
 *   It's a hack that prevents the browser of sending the http referrer in the following cases:
 *    - Link: You can have a link in your website being sure that the destiny won't know about your site.
 *    - Image: You can display an image from another site being sure the other site won't know your website is displaying it.
 *  Other interesting use is displaying an image without blocking the rest of the content, this way in case the image fails
 * it allows the rest of the page to load normally.
 *   Uses:
 *    - Load static content in parallel.
 *    - Provide privacy to your web users.
 *    - Saving bandwidth, considering you safe the extra bytes of the http referrer.
 *   Abuses:
 *    - Stilling bandwidth, using some other site contents (hotlinking, http://en.wikipedia.org/wiki/Inline_linking).
 * @Compatibility:
 *   It's been tested successfully on:
 *    - Chrome 24.
 *    - Firefox 15.
 *    - Safari 6.
 *    - Opera 12: it sends the referrer in the case of anchors if the target is an iframe, not if it opens in other window
 *     or the same one, for images it never sends the referrer even without using the hack.
 *    - IE 6, 7, 8.
 *    - IE 9: it works for images but not links, that's why in that oogle's url redirection is used for this browser, in this case
 *      there is an intermediate page.
 * @Interface:
 *   - ReferrerKiller.linkHtml(url, [innerHtml], [anchorParams], [iframeAttributes]). Returns a string.
 *   - ReferrerKiller.linkNode(url, [innerHtml], [anchorParams], [iframeAttributes]). Returns an Html Node.
 *   - ReferrerKiller.imageHtml(url, [imgParams], [iframeAttributes]). Returns a string.
 *   - ReferrerKiller.imageNode(url, [imgParams], [iframeAttributes]). Returns an Html Node.
 */

/**
 * @module ReferrerKiller
 */
var ReferrerKiller = (function () {
 var URL_REDIRECTION = "https://www.google.com/url?q=", // You can use another service if you use https protocol no referrer will be sent.
  PUB = {},
  IE_GT_8 = (function () {
    /*- Detecting if it's IE greater than 8 -*/
    var trident,
     match = navigator.userAgent.match(/Trident\/(\d)+/);
    if (null === match) {
     return false;
    }
    trident = parseInt(match[1], 10);
    if (isNaN(trident)) {
     return false;
    }
    return trident > 4;
  })();

 /**
  * Escapes double quotes in a string.
  *
  * @private
  * @param {string} str
  * @return {string}
  */
 function escapeDoubleQuotes(str) {
  return str.split('"').join('\\"');
 }
 
 /**
  * Given a html string returns an html node.
  *
  * @private
  * @param {string} html
  * @return {Node}
  */
 function htmlToNode(html) {
  var container = document.createElement('div');
  container.innerHTML = html;
  return container.firstChild;
 }
 
 /**
  * Converts object to html attributes string.
  *
  * @private
  * @param {object} obj
  * @return {string}
  */
 function objectToHtmlAttributes(obj) {
  var attributes = [],
   value;
  for (var name in obj) {
   value = obj[name];
   attributes.push(name + '="' + escapeDoubleQuotes(value) + '"');
  }
  return attributes.join(' ');
 }

 /**
  * It applies the hack to kill the referrer to some html.
  *
  * @public
  * @param {string} html.
  * @param {object} [iframeAttributes]
  * @return {string} html.
  */
 function htmlString(html, iframeAttributes) {
  var iframeAttributes  = iframeAttributes || {},
   defaultStyles = 'border:none; overflow:hidden; ',
   id;
  /*-- Setting default styles and letting the option to add more or overwrite them --*/
  if ('style' in iframeAttributes) {
   iframeAttributes.style =  defaultStyles + iframeAttributes.style;
  } else {
   iframeAttributes.style = defaultStyles;
  }
  id = '__referrer_killer_' + (new Date).getTime() + Math.floor(Math.random()*9999);
  /*-- Returning html with the hack wrapper --*/
  return '<iframe \
    style="border 1px solid #ff0000" \
    scrolling="no" \
    frameborder="no" \
    allowtransparency="true" ' +
   /*-- Adding style attribute --*/
   objectToHtmlAttributes( iframeAttributes ) +
   'id="' + id + '" ' +
   ' src="javascript:\'\
   <!doctype html>\
   <html>\
   <head>\
   <meta charset=\\\'utf-8\\\'>\
   <style>*{margin:0;padding:0;border:0;}</style>\
   </head>' +
   /*-- Function to adapt iframe's size to content's size --*/
   '<script>\
     function resizeWindow() {\
     var elems  = document.getElementsByTagName(\\\'*\\\'),\
      width  = 0,\
      height = 0,\
      first  = document.body.firstChild,\
      elem;\
     if (first.offsetHeight && first.offsetWidth) {\
      width = first.offsetWidth;\
      height = first.offsetHeight;\
     } else {\
      for (var i in elems) {\
           elem = elems[i];\
           if (!elem.offsetWidth) {\
            continue;\
           }\
           width  = Math.max(elem.offsetWidth, width);\
           height = Math.max(elem.offsetHeight, height);\
      }\
     }\
     var ifr = parent.document.getElementById(\\\'' + id + '\\\');\
     ifr.height = height;\
     ifr.width  = width;\
    }\
   </script>' +
   '<body onload=\\\'resizeWindow()\\\'>\' + decodeURIComponent(\'' +
   /*-- Content --*/
   encodeURIComponent(html) +
  '\') +\'</body></html>\'"></iframe>';
 }

 /*-- Public interface --*/

 /**
  * It creates a link without referrer.
  *
  * @public
  * @param {string} url
  * @param {string} innerHTML
  * @param {object} [anchorParams]
  * @param {object} [iframeAttributes]
  * @return {string} html
  */
 function linkHtml(url, innerHTML, anchorParams, iframeAttributes) {
  var html,
   urlRedirection = '';
  innerHTML = innerHTML || false;
  /*-- If there is no innerHTML use the url as innerHTML --*/
  if (!innerHTML) {
   innerHTML = url;
  }
  anchorParams = anchorParams || {};
  /*-- Making sure there is a target attribute and the value isn't '_self' --*/
  if (!('target' in anchorParams) || '_self' === anchorParams.target) {
   /*-- Converting _self to _top else it would open in the iframe container --*/
   anchorParams.target = '_top';
  }
  if (IE_GT_8) {
   urlRedirection = URL_REDIRECTION;
  }
  html = '<a rel="noreferrer" href="' + urlRedirection + escapeDoubleQuotes(url) + '" ' + objectToHtmlAttributes(anchorParams) + '>' + innerHTML + '</a>';
  return htmlString(html, iframeAttributes);
 }
 PUB.linkHtml = linkHtml;
 
 /**
  * It creates a link without referrer.
  *
  * @public
  * @param {String} url
  * @param {String} innerHTML
  * @param {Object} [anchorParams]
  * @param {object} [iframeAttributes]
  * @return {Node}
  */
 function linkNode(url, innerHTML, anchorParams, iframeAttributes) {
  return htmlToNode(linkHtml(url, innerHTML, anchorParams, iframeAttributes));
 }
 PUB.linkNode = linkNode;
 
 /**
  * It displays an image without sending the referrer.
  *
  * @public
  * @param {String} url
  * @param {Object} [imgAttributesParam]
  * @return {String} html
  */
 function imageHtml(url, imgAttributesParam) {
  var imgAttributes = imgAttributesParam || {},
  /*-- Making sure this styles are applyed in the image but let the possibility to overwrite them --*/
   defaultStyles = 'border:none; margin: 0; padding: 0';
  if ('style' in imgAttributes) {
   imgAttributes.style = defaultStyles + imgAttributes.style;
  } else {
   imgAttributes.style = defaultStyles;
  }
  return htmlString('<img src="' + escapeDoubleQuotes(url) + '" ' + objectToHtmlAttributes(imgAttributes) + '/>');
 }
 PUB.imageHtml = imageHtml;
 
 /**
  * It displays an image without sending the referrer.
  *
  * @public
  * @param {string} url
  * @param {object} [imgParams]
  * @return {Node}
  */
 function imageNode(url, imgParams) {
  return htmlToNode(imageHtml(url, imgParams));
 }
 PUB.imageNode = imageNode;

 /*-- Exposing the module interface --*/
 return PUB;
})();





2014년 10월 24일 금요일

[IntelliJ][Android] Package Name 변경하기




지우지 못하는 이미 설치되어(embeded)있는 App을 루팅없이 다시한번 설치하려면 Package Name 변경이 필요하다. (정확히는 Application ID)


========================
2015.04.23 추가
기존의 방법대로 변경 시 R을 인식하지 못하는 문제가 있어서 다시 기술을 한다.
(안되는 분이 있다면 댓글을 달아주시면 좋을텐데.. 아무도 댓글을 달아주지 않는다;;)

========================
2015.04.30 추가
Gradle 없는경우 java packagename 을 변경하지 않고 설치 시 사용하는 id(applicationId) 만 변경하여 단말기에 빌드하는 방법을 추가.



Android Studio 에서의 방법

확인버전: Android Studio 1.1.0

1. gradle 을 사용하는 경우
  - Android Studio 에서 프로젝트를 만들거나 import 시 gradle 만들겠다고 체크한경우

1004lucifer
아래와 같이 gradle 파일에서 applicationId 를 변경해 주면 된다. (간단)


PS. 주의
com.android.application 이 단말기에 설치되어 있는경우
위의 방법을 사용 시 AndroidManifest.xml 의 <permisstion> 태그의 name 변경이 필요하다.
Gradle 에서 applicationId 만 변경 시 permission이름이 자동으로 바뀌지 않는데 Lollipop 에서는 같은 이름의 퍼미션을 허용하지 않는다.




2. gradle 을 사용하지않는 경우
  - 기존에 Eclipse 에서 사용하던 프로젝트를 import 할 시 gradle 없이 import가 가능한데 그때에 사용 가능한 방법이다. (링크: gradle 없이 Module import 방법)
1004lucifer


  1) package name 선택 => Refactor => Rename




  2) "Rename package" 선택




  3) 원하는 package name으로 변경
1004lucifer



  4) AndroidManifest.xml 에서 package 이름에 마우스 커서를 클릭 후 Rename 선택




  5) 변경 원하는 동일한 package name 입력



  6) "Save All" 선택 후 새로운 package 에 R파일이 생성되었는지 확인



위와같이 작업 후 빌드를 하면 변경된 ApplicationID로 빌드가 된다.





IntelliJ 에서의 방법

확인버전: IntelliJ 14.1
1004lucifer
Android Studio - gradle 없는 방법으로 똑같이 작업을 하면 된다.





PS.
위의 방법으로 대부분의 작업이 자동으로 Package Name 변경이 이루어 지는데
(Gradle 사용, 미사용 둘다)

1. aidl 파일
2. String 문자로 이루어진 Package Name
위의 두개의 경우에는 자동으로 변경되지 않으며 수동으로 변경을 해주어야 한다.

빌드를 해보면 에러가 나거나 앱 실행중에 앱이 죽으며 로그를 남기거나 한다.
2번의 경우는 ContentProvider Uri 에 사용되는 Package Name 이 String으로 되어있다보니 자동으로 변경되지 않아 직접 변경을 해 주었다.







VS





Gradle이 없는 상황에서의 위의 방법은 Source의 packagename 이 모두 변경이 된다.
(이거자체는 문제가 안된다.)
하지만 회사의 프로젝트의 경우 아무렇게나 커밋을 할 수 있는 상황이 아니다보니 예상밖의 문제점이 생겼다.
1004lucifer
문제가 되는 부분은 packagename 을 변경 시 모든 java파일의 packagename 을 변경을 하면서 원하지 않던 부분이 변경되는 부분에 문제가 있었다.
(packagename 을 다시 되돌려도 많은 java파일과 xml이 수정되어 있다. - 자동 최적화)

1. AndroidManifest.xml 파일
  - <activity> 태그의 name 속성의 Class 경로가 모두 점(.) 으로 시작되도록 수정되었다.
2. 대부분의 java 파일
  - 사용되지 않는 Class는 import 가 삭제되었다.
  - 문자열 마지막에 필요없는 공백이 삭제되었다.


분명 위의 기능 자체는 좋은 기능이긴 한데 수정된 파일이 너무 많이 생겨버리다보니 어떤 파일을 커밋해야 할지 헷갈려 버리는 문제가 생겨버렸다.



IntelliJ의 버그인지는 잘 모르겠지만 Source의 packagename 을 변경하지 않고 단말기에 프로그램을 설치할 수 있는 방법을 기술한다.


1. 아래와 같이 Project 를 빌드한다. (에러가 없는 상태이어야 한다.)



2. AndroidManifest.xml 파일수정
  [아래의 package 이름을 변경한다. ex)com.test => com.test1 ]
  - <manifest package="com.test">
  - <provider android:authorities="com.test" />
  - <permission android:name="com.test.Permission" /> (선택: Lollipop 에서는 중복 퍼미션을 허용하지 않는다. 같은 앱이 설치되어 있다면 변경해야 한다.)

3. 그외 java 에서 String으로 package명이 기술되어 있다면 수정이 필요할 수 있다.
  (꼭 수정이 되어야 한다면 빌드시 오류가 나거나 앱 실행시 종료가 되어버린다. 로그를 보고 수정하는게 편할 수 도 있다.)
1004lucifer
4.  Run 실행을 하면 단말에 설치가 된다.


PS. 주의
위의 작업 후 Ctrl+s 라던지.. 'Save All' 버튼을 누르지 않도록 주의한다.
위의 상태는 컴파일은 com.test 로 컴파일이 되어있는 상태에서 ApplicationID 만 com.test1 으로 단말기에 설치하는 방법이며 위의 상태에서 컴파일이 된다면 Source 파일에서 R파일 관련하여 오류가 발생을 한다.
그런 경우에는 <manifest package="com.test1"> 부분을 Rollback 후 다시 Project 빌드를 한 후 차례대로 위의 방법대로 따라한다.

꼭 2번의 작업 전에 1번의 작업과 같이 Project 빌드가 끝난 후 작업을 해주어야 단말기에 정상적으로 설치가 된다.

















=======================================
아래의 방법은 현재는 정상적으로 Package 이름이 변경이 되지 않을 수 있다.
상단의 방법을 참고.



1. Manifest 파일
1004lucifer
  1) manifest 태그의 package 속성값 변경
    - <manifest package="com.test1"

=====================================
2015.03.31 추가 (IntelliJ 14.1 에서 테스트 완료)
단순히 문자열만 변경해서는 에러가 나며 제대로 되지 않아 패키지명 변경 시 아래와 같이 작업을 해주어야 한다.

1. AndroidManifest.xml 파일을 열고 package 이름에 커서를 올려 놓은 후 'Refactor => Rename' 선택 (단축키 shift + F6)

2. 변경 할 패키지 이름을 적고 Refactor 버튼 클릭
=====================================



  2) provider 태그의 authorities 속성값 변경
    - <provider android:authorities="com.test1"

  3) permission 태그의 name 속성값 변경 (lollipop 에서는 중복된 퍼미션 허용이 안됨)
    - <permission android:name="com.test.permission.TIME_TICK2"

2. Manifest 파일의 Provider 태그의 name 값에 있는 Class 에서 사용하는 패키지 명 변경




PS.
이클립스도 마찬가지로 위와같이 변경이 가능한 것으로 기억하고 있다.



====================================
간단한 테스트 프로젝트에서는 정상적으로 되지만 현재 작업중인 프로젝트에서는 아래의 방법대로 했을 시 정상적으로 이용이 되지 않아 위의 방법을 사용하고 있다.



JetBrains 사이트에서 변경방법을 참고했다.
http://www.jetbrains.com/idea/webhelp/renaming-an-application-package-(application-id).html






변경 방법은 다음과 같다.
(Android Studio 역시 크게 다르지 않을 것으로 예상한다.)

1004lucifer
1. AndroidManifest.xml 파일을 열고 package 이름에 커서를 올려 놓은 후 'Refactor => Rename' 선택 (단축키 shift + F6)



2. 변경 할 패키지 이름을 적고 Refactor 버튼 클릭



3. 'File => Save All' 선택
    (IntelliJ 툴은 파일을 변경하면 따로 저장버튼을 누르지 않더라도 자동으로 저장이 되지만 이상하게도 cmd + S 를 누르고 나서야 gen 디렉토리에 반영이 되었다.)



3. 'gen => package_name' 변경이 되었는지 확인



4. 'src => package_name' 선택 후 'Refactor => Rename' 선택 (단축키 shift + F6)



5. 'Rename directory' 선택


1004lucifer
6. 변경 할 패키지 이름을 적고 Refactor 버튼 클릭



7. 실행 시 다음과 같은 오류가 나면서 수행이 되지 않는다.
(Error: {package_name}/{Activity} is not an Activity subclass or alias)


1004lucifer
8. 'Activity => Launch' 항목에서 패키지 이름을 정상적으로 고친 후 다시 실행




[iOS] selectedRowInComponent 호출 시 row가 무조건 0으로 리턴되는 경우




시작하세요! iOS 6 프로그래밍 - 10점
데이브 마크 외 지음, 유윤선 옮김/위키북스


위의 책으로 7장 '탭바와 피커' 부분을 공부 하다가 예제소스를 그대로 따라했다고 생각했는데 다음과 같은 문제가 생겼다.



Source
============================
- (void)buttonPressed {
    NSInteger row = [self.singlePicker selectedRowInComponent:0];
    NSString *selected = self.characterNames[row];
    NSString *title = [[NSString alloc] initWithFormat:@"You selected %@!", selected];
    UIAlertView *alert = [[UIAlertView alloc]
                          initWithTitle:title
                          message:@"Thank you for choosing."
                          delegate:nil
                          cancelButtonTitle:@"You're Welcome"
                          otherButtonTitles:nil];
    [alert show];
}
============================


위의 소스에서 selectedRowInComponent 함수가 무조건 0으로만 리턴을해서 row변수에 0이 계속 담기는 증상이 있었다.







찾아서 수정을 하고보니 너무 허무했지만 찾는데 너무 시간을 오래 들였던 것 같다.


원인
- Picker에 아웃렛(outlet) 연결이 되어있지 않았다.








아웃렛(outlet) 연결방법

1. 컨트롤키를 누른상태에서 'File's Owner' 를 클릭하고 피커로 드래그 후 놓는다.


2. 아웃렛을 선택한다.


3. 아웃렛이 연결되었는지 확인한다.





책을 다시한번 꼼꼼하게 읽어보니 아웃렛 연결하는 부분이 있었다. (p.210)



2014년 10월 23일 목요일

[IntelliJ][Android] 컴파일 시 'Cannot start compilation: the output path is not specified for module' 에러




Android Project 를 가져왔는데 셋팅이 제대로 되어있지 않아서
R Directory 도 인식되지 않고 있는상황이었다.
이것저것 셋팅을 하고 컴파일을 하려니 아래와 같은 메시지가 나왔다.





Cannot start compilation: the output path is not specified for module "{Project_name}"
Specify the output path in Configure Project.






output path 가 셋팅되어있지 않아서 컴파일을 할 수 없다는 문구인데
다음과 같이 셋팅을 해 주었다.



위의 빨간 버튼을 눌러서 컴파일이 될 경로를 선택한다.
일반적인 셋팅은 다음과 같다.


{Project_Path}/out


ex) /opt/git/repo/project_name/out



위와같이 설정 후 다시 컴파일 하면 정상적으로 컴파일 되는것을 확인할 수 있다.









위의 설정은 일반적인 프로젝트의 설정을 해주는 방법이고 모듈마다 output path 를 다르게 설정이 가능하다.


모듈별 output path 잡아주는 방법




일반적인 셋팅은 다음과 같다.


{Project_Path}/out/production/{Project_Name}


ex) /opt/git/repo/project_name/out/production/project_name



2014년 10월 16일 목요일

[iOS] "loaded the ~ nib but the view outlet was not set." 문제





시작하세요! iOS 6 프로그래밍 - 10점
데이브 마크 외 지음, 유윤선 옮김/위키북스


위의 책으로 공부를 하고있는데 예제를 따라하다가 앱을 실행시켰더니 다음과 같은 로그가 발생을 하며 앱이 중단이 되었다.


2014-10-16 22:27:34.620 View Switcher[44934:907] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '-[UIViewController _loadViewFromNibNamed:bundle:] loaded the "SwitchView" nib but the view outlet was not set.'
*** First throw call stack:
(0x1c8d012 0x10cae7e 0x1c8cdeb 0xf2f18 0xf3418 0xf3648 0xf3882 0x2663 0xf7b7 0xfda7 0x10fab 0x22315 0x2324b 0x14cf8 0x1be8df9 0x1be8ad0 0x1c02bf5 0x1c02962 0x1c33bb6 0x1c32f44 0x1c32e1b 0x107da 0x1265c 0x23cd 0x22f5 0x1)
libc++abi.dylib: terminate called throwing an exception
(lldb)




원인을 찾아보다가 아직 iOS 개발한지 얼마 되지 않아서 뭔얘기인지도 잘 모르겠고..
책을 보며 예제를 좀더 따라하고 실행해보니(p.175 하단 부분까지) 정상적으로 구동이 되었다.



원인은 xib 파일, Controller 파일들을 따로따로 만들어서 수동으로 엮어주고 있는부분인데

Controller(예제에서는 BIDSwitchViewController)의 view 아웃렛을 nib로 연결이 되지 않아서 문제가 발생을 하는것이었다.


책에서 기술된 내용은 다음과 같다.



이 nib에서 해야 할 일이 한 가지 더 있는데, 바로 BIDSwitchViewController의 view 아웃렛을 nib로 연결하는 일이다.

view 아웃렛은 부모 클래스인 UIViewController로부터 상속하며 컨트롤러가 자신이 관리하는 뷰에 접근할 수 있게 해준다.

이 nib 파일을 수정하기 전에는 NSObject가 File's Owner로 설정되어 있었고 NSObject에는 뷰 아웃렛이 전혀 없다.

따라서 여기서는 컨트롤러를 뷰로 연결해줘야 한다.

이를 위해서는 File's Owner 아이콘을 View 아이콘으로 컨트롤 키를 누른채로 드래그하고 view 아웃렛을 선택하면 된다.




다음과 같이 작업을 했다.





[VirtualBox][CentOS] OS 구동 시 'kernel driver not installed' 에러가 나는경우



CentOS 6.5 환경

우여곡절끝에 VirtualBox 에 Image를 import 시켰는데 구동시

kernel driver not installed

에러가 발생하며 정상적으로 동작하지 않았다.



국내 사이트에서는 http://honghome.tistory.com/417 이곳이 설명이 잘 되어있길래 차근차근 따라했는데도 해결하지 못해서 구글에서 검색하여 겨우 컴퓨터 구동을 시켰다.

나의 경우에는


$ /etc/init.d/vboxdrv setup


이 명령어로 문제를 해결할 수 없었다.



대신 다음과 같은 문제로 증상을 해결했다.


[root@localhost 2.6.32-431.el6.x86_64]#
[root@localhost 2.6.32-431.el6.x86_64]# KERN_DIR=/usr/src/kernels/2.6.32-431.29.2.el6.x86_64
[root@localhost 2.6.32-431.el6.x86_64]# export KERN_DIR
[root@localhost 2.6.32-431.el6.x86_64]#
[root@localhost 2.6.32-431.el6.x86_64]#
[root@localhost 2.6.32-431.el6.x86_64]# /etc/init.d/vboxdrv setup
Stopping VirtualBox kernel modules                         [  OK  ]
Uninstalling old VirtualBox DKMS kernel modules            [  OK  ]
Trying to register the VirtualBox kernel modules using DKMS
Error! Your kernel headers for kernel 2.6.32-431.11.2.el6.x86_64 cannot be found at
/lib/modules/2.6.32-431.11.2.el6.x86_64/build or /lib/modules/2.6.32-431.11.2.el6.x86_64/source.
                                                           [실패]
  (Failed, trying without DKMS)
Recompiling VirtualBox kernel modules                      [  OK  ]
Starting VirtualBox kernel modules                         [  OK  ]
[root@localhost 2.6.32-431.el6.x86_64]#
[root@localhost 2.6.32-431.el6.x86_64]#
[root@localhost 2.6.32-431.el6.x86_64]#
[root@localhost 2.6.32-431.el6.x86_64]#
[root@localhost 2.6.32-431.el6.x86_64]# pwd
/lib/modules/2.6.32-431.el6.x86_64
[root@localhost 2.6.32-431.el6.x86_64]#



그리고
KERN_DIR=/usr/src/kernels/2.6.32-431.29.2.el6.x86_64
이부분에서 kernels/ 뒷부분은 시스템마다 다를 수 있다.


PS.
Linux 의 커널경로를 잡아주니 '/etc/init.d/vboxdrv setup' 명령 시
VirtualBox kernel modules 를 다시 컴파일하여 해결되긴 했는데
DKMS 연동 부분은 실제 해당 경로(/lib/modules/2.6.32-431.11.2.el6.x86_64/build)의 심볼릭 링크가 깨져있었다.

잡아주려 했으나 잡으려는 디렉토리가 없어서 제대로 잡아줄 수 없었다.

아래의 링크를 참고하였다.



[VirtualBox][CentOS] sfx 파일 실행 시 ld-linux.so.2 또는 libstdc++.so.6 오류가 발생하는경우



CentOS 6.5 환경에서 VirtualBox 최신버전을 설치 후

Microsoft 에서 제공하는 Window가 이미 설치된 VirtualBox Image 를 다운받아(링크) 로딩을 시키려고 설명에 나와있는대로 sfx를 실행했는데 오류가 발생을 했다.


문제 1


[localhost@localhost VirtualBox]$
[localhost@localhost VirtualBox]$ ./IE8.WinXP.For.LinuxVirtualBox.part1.sfx
bash: ./IE8.WinXP.For.LinuxVirtualBox.part1.sfx: /lib/ld-linux.so.2: bad ELF interpreter: 그런 파일이나 디렉터리가 없습니다
[localhost@localhost VirtualBox]$



해결방법

[localhost@localhost VirtualBox]$ sudo yum install ld-linux.so.2





문제 2


[localhost@localhost VirtualBox]$
[localhost@localhost VirtualBox]$ ./IE8.WinXP.For.LinuxVirtualBox.part1.sfx
./IE8.WinXP.For.LinuxVirtualBox.part1.sfx: error while loading shared libraries: libstdc++.so.6: cannot open shared object file: No such file or directory
[localhost@localhost VirtualBox]$



해결방법

[localhost@localhost VirtualBox]$ sudo yum install libstdc++.so.6



[Util] Linux, Mac(OSX) 에서 여러장의 jpg, png 파일로 gif 만들기 - 이미지매직(ImageMagick)



윈도우에는 워낙 많은 툴들이 있기에 여러장의 사진들을 모아서 gif 파일을 만드는게 어렵지 않을 수 있겠지만 Linux, 또는 맥(Mac) 과 같은 시스템 에서는 툴들이 많지 않다.

찾아보니 이미지매직(ImageMagick) 이라는 프로그램이 있는데 커맨드로 작업을 해야하기때문에 직관적이지는 않지만 간단히 쓰기에 그리 나쁘지 않은듯 하다.




다운로드 페이지 에 들어가면 다운로드 링크와 설치방법이 기술되어있다.


나의경우 환경변수를 다음과 같이 지정을 했다.

맥(Max - OSX)의 경우
vi ~/.profile
#ImageMagic
export MAGICK_HOME="/opt/util/ImageMagick-6.8.9"
export PATH="$MAGICK_HOME/bin:$PATH"
export DYLD_LIBRARY_PATH="$MAGICK_HOME/lib/"


Linux (Ubuntu, CentOS) 의 경우
vi ~/.bash_profile
#ImageMagic
export MAGICK_HOME="/opt/util/ImageMagick-6.8.9"
export PATH="$MAGICK_HOME/bin:$PATH"
export DYLD_LIBRARY_PATH="$MAGICK_HOME/lib/"


위에서 MAGICK_HOME 부분은 똑같이 하면 안되고 실질적으로 다음과 같이 해야 한다.
export MAGICK_HOME="{설치된 경로, 압축이 풀린 경로}"



위와 같이 설치 및 환경설정이 끝난 후 쉘을 다시 시작하여 위의쉘이 적용되면 바로 사용이 가능하다.

나의 경우에는 다음의 명령어로 gif를 만들었을때 가장 자연스럽게 보였다.

$ convert -delay 25 *.jpg result.gif



2014년 10월 13일 월요일

[iOS] '[UISegmentedControl isOn]: unrecognized selector sent to instance' 오류증상




Java를 공부함에 있어서 100번이상 디버깅을 해봐야 어느정도 할수 있다란 말을 들었는데 참 와닿는 말이면서도 처음에는 간단한 것이라도 디버깅을 하기가 참 힘들다고 느껴진다.


최근 갓 iOS를 공부하면서 책에 있는 예제들을 하나하나 따라가 보는데
공부를 시작하면서 다음의 오류를 찾는데 시간이 좀 걸려서 이렇게 포스팅!!


시작하세요! iOS 6 프로그래밍 - 10점
데이브 마크 외 지음, 유윤선 옮김/위키북스


위의 책을 보면서 공부를 하고있는데 'Control Fun' 예제를 따라하다가 분할컨트롤(Segmented Control)을 클릭 시 아래와 같은 오류가 발생을 했다.



Log 는 다음과 같이 나왔다.

2014-10-13 15:13:45.361 Control Fun[32774:907] -[UISegmentedControl isOn]: unrecognized selector sent to instance 0x7267e70
2014-10-13 15:13:45.363 Control Fun[32774:907] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UISegmentedControl isOn]: unrecognized selector sent to instance 0x7267e70'
*** First throw call stack:
(0x1c8e012 0x10cbe7e 0x1d194bd 0x1c7dbbc 0x1c7d94e 0x24d4 0x10df705 0x16920 0x168b8 0xd7671 0xd7bcf 0xd76a6 0x12c597 0x12e83b 0x4616d 0x46552 0x243aa 0x15cf8 0x1be9df9 0x1be9ad0 0x1c03bf5 0x1c03962 0x1c34bb6 0x1c33f44 0x1c33e1b 0x1be87e3 0x1be8668 0x1365c 0x1c1d 0x1b45)
libc++abi.dylib: terminate called throwing an exception


[UISegmentedControl isOn]: unrecognized selector sent to instance 0x7267e70
에 포커스를 맞춰서 원인분석을 해보니 디버깅하는데 그리 오래 걸리지 않았다.


원인은 'switchChanged' 라는 메소드가 걸려있었는데 해당 메소드에서
UISegmentedControl 에 없는걸 사용하고 있었다.
해당 메소드를 사용하지 않게 제거 하는 것으로 디버깅 해결.

Source
============================
- (IBAction)switchChanged:(UISwitch *)sender {
    BOOL setting = sender.isOn;
    [self.leftSwitch setOn:setting animated:YES];
    [self.rightSwitch setOn:setting animated:YES];

}
============================






[Blogger] 게시물 작성 시 The combined length of all the labels must be at most 200 characters. 에러가 나오는경우



Google 에서 제공하는 Blogger 에서 게시글을 작성하고 게시를 누르는 순간 아래와 같이 나타나는 경우가 있다.




The combined length of all the labels must be at most 200 characters.


이전에는 뭐가 문제지?? 라고 한참 찾았었는데 말그대로였다.
다만 Label 이 한국어 Blogger 에서는 태그라고 적혀있어서 뭔말인지 몰랐을뿐..ㅠㅠ

오른쪽의 '글 설정' => '태그' 란에 너무 많은 태그가 입력이 되어있어서 게시가 되지 않는 문제이다.





2014년 10월 11일 토요일

[Chrome][Plugin] Advenced REST Client 에서 POST 요청을 날릴 때 500 에러만 받는경우



서버에 POST 요청을 날려야 하는 경우가 있어서 Chrome Plugin 중에 하나인
'Advanced REST Client' 프로그렘에 요청을 했더니 다음과 같이 500에러가 응답으로 온다.
(위의 아이콘 프로그램이다.)








  HTTP Status : 500 - 500 Internal Server Error



Description
Request processing failed; 
nested exception is java.lang.NullPointerException



아무리 서버의 로직을 봐도 넘겨줘야 할 Parameter 는 모두 넘겨줬는데
NullPointerException 이라니??



다음날이 되어서야 다음과 같은 방법으로 Response Status 200을 받을 수 있었다.


알고나니 허탈했는데 다음과 같이 해결을 했다.
Header 값으로 아래의 값을 같이 넣어주었다.


Content-Type: application/x-www-form-urlencoded; charset=UTF-8





2014년 10월 10일 금요일

[하드웨어] 시스템 하드웨어 규모산정 (서비스에 따른 웹서버, DB서버 스펙 결정하기)




지금 하는 프로젝트에서 하드웨어증설을 해야 한다고 하길래 알아본것을 포스팅!!

인터넷을 찾아보면 '일일 방문자수가 몇명이고 동접자수가 최대 몇명 정도가 되는데 이정도 서버로 버틸수 있을까요??'  라는 글을 많이 봤다.

나도 궁금했다.
어느정도 서버 스펙이 되어야 동접자 수를 커버할 수 있을까??







알아보니 정부에서 공식으로 사용하는 하드웨어 규모산정이 있다.
한국정보통신기술협회 에서 인정하는 '정보시스템 하드웨어 규모 지침' 이라는 문서가 있는데 한국정보통신기술협회 사이트에서 다운로드가 가능하다.


찾기 귀찮은 사람들을 위해 링크를 올려 놓는다.
다운로드 링크


내용을 보기 귀찮은 사람들을 위해 하단에 요약을 올려 놓았다.




1004lucifer
내용상으로는 다음과 같이 기준산정이 가능하다.
  - 사이트의 순간최대요청을 알아야 계산이 가능
(순간최대요청을 PV로 변경하여 기술,
분당 트랜잭션 수는 Peak 타임을 기준으로 기술했다.)



1. DB서버 (1대 가정)
1) CPU (tpmC 단위)
- 분당 트랜잭션 수 * 기본 tmpC 보정(1.3) * 데이터베이스크기 보정(1.3) * 어플리케이션구조 보정(1.4) * 어플리케이션부하 보정(1.5) * 시스템 여유율(1.3)
2) 메모리
- {시스템영역 + (사용자당 필요메모리(1MB) * 동시사용자수)} * 버퍼캐쉬 보정(1.2) * 시스템 여유율(1.3)
3) 디스크
- 시스템: (시스템OS + 응용프로그램 + SWAP) * 파일시스템 오버헤드(1.1)
- 데이터: (데이터 + 백업) + 파일시스템 오버헤드(1.1) * 데이터디스크 여유율(1.3)

1004lucifer
2. WEB/WAS 서버 (각각 1대 가정)
1) CPU (OPS 단위)
- PV * PV 오퍼레이션(DB호출) 수 * 인터페이스부하 보정(1.1) * 피크타임부하 보정(1.3) * 시스템여유율(1.2)
2) 메모리
- {시스템영역 + (사용자당 필요메모리(1MB) * 동시사용자수)} * 버퍼캐쉬 보정(1.2) * 시스템 여유율(1.3)
3) 디스크
- 시스템: (시스템OS + 응용프로그램 + SWAP) * 파일시스템 오버헤드(1.1)

- 데이터: (데이터 + 백업) + 파일시스템 오버헤드(1.1) * 데이터디스크 여유율(1.3)


계산을 하고나니 tpmC 기준으로는 인터넷을 찾아보니 Cpu 모델별로 성능이 나와서 대충 어떤 CPU를 구매하면 되겠구나 감을 잡을 수는 있지만 우리나라에서만 사용하는 단위인지는 모르겠지만 OPS 단위로는 인터넷으로 적합한 CPU모델을 알 수 없었다.
아마 벤더나 중간업체에 이야기를 하면 알 수 있을지도?







PS.
개인적인 생각으로는 서버스펙도 중요하지만 논리적인 서버의 구성도 상당히 중요하다고 생각한다.

물리적인 서버하나에 WAS를 여러개 올릴수도 있고 WAS하나에 Context를 여러개 올릴수도 있으니 어떤게 가장 효율적인지 확인하고 테스트 해가면서 어떤게 해당 프로젝트에 맞는지 알아보는게 좋다고 생각한다.

1004lucifer
그리고 경험적으로 이따금씩 또는 특정 시간이 되면 서버가 응답이 없는 증상에 대해서 물리적인 스펙변경없이 WAS 셋팅만으로 이슈를 해결한 적이 있었다.

1. WAS의 응답이 너무 느릴 시 체크하여 Thread Dump 를 생성하는 데몬을 만들었었다.

2. GC Log 를 생성하는 옵션을 넣어서 GC 를 지속적으로 모니터링 했었다.

3. Heap Memory 를 4096MB => 2048MB 변경
    - Full GC 할 시 Stop the World 의 시간이 줄어들었다.

4. GC튜닝: 정확히 어떻게 했는지 기억이 가물가물하다.
    - Full GC 하는 딜레이를 Heap Memory가 60~70%만 되어도 Full GC가 수행되도록 변경하여 Full GC 시간(Stop the World)을 줄였던 것으로 기억한다.


다음의 링크가 개념적으로 정리하기에 좋다.
Java Garbage Collection
Garbage Collection 튜닝
Garbage Collection 모니터링 방법
자바 애플리케이션 성능 튜닝의 도(道)

엑셈에서 JVM 옵션을 확인해보는 것이 좋다.
JVM 옵션 정리

Tmax 에서 만든 JVM 튜닝옵션 문서를 참고해도 도움이 될것 같다.
SUN JVM 튜닝 옵션 by Tmax




============================
성능기준치
1) RDBMS => TPC-C
2) WEB => SPECWeb99
3) WAS => SPECjbb2000
1004lucifer
규모산정의 4가지요소
1) 인터뷰 분석 보고서 (규모산정 기초자료)
2) 규모산정 계산식 (계산식의 표준화)
3) 규모산정 절차서 (절차에 의한 규모산정)
4) 규모산정 Repository (사례 DB화를 통한 공유)

개념적 규모산정 절차
1) 구축방향 및 기초자료 조사
2) 기초자료 및 업무분석
3) 참조모델 결정 및 서버 규모산정
4) 참조모델별 가중치 적용


시스템 구축방향 및 기초자료 조사
1) 대략의 서버 개수, 어플리케이션 아키텍처 (2-계층, 3-계층), 통신환경 등을 결정
ex) 2계층은 서버1(WEB,WAS), 서버2(DB) 구성
3계층은 서버1(WEB), 서버2(WAS), 서버3(DB) 구성

2) 서버의 개략적인 업무 성격과 정보 흐름을 파악하기 위해 업무 사용자를 대상으로 아래의 양식에 따라 규모산정을 위한 기초자료 조사

1004lucifer






기초자료 및 업무분석
- 고려해야할 요소는 다음과 같다.
1) 응용업무의 각 트랜잭션 타입, 특성, 가중치를 조사한다.
2) 온라인 업무와 배치처리 업무는 구분해서 분석한다.
3) 현재의 규모와 향후 시스템 서비스를 개시한 후 업그레이드 없이 사용할 기간을 감안하여 필요 규모를 사전 확보해야 한다.




참조모델 결정 및 서버 규모산정
- 참조모델에서 제시하는 서버1, 서버2, 서버3은 물리적이 아니라 논리적인 개념의 서버이다.







참조모델별 가중치 적용







하드웨어 요소별 규모산정 방식
1) CPU 산정방식
가) DB서버 또는 OLTP & Batch (tpmC 추정방식)

1) 분당 트랜잭션 수 (3가지 방법 존재)
ㄱ) 클라이언트 수를 이용하는 방법
- 동시사용자 수를 이용한 분당 트랜잭션을 구한다.
ㄴ) 기존시스템의 트랜잭션을 조사하는 방법
ㄷ) 동시사용자 수를 이용하는 방법
- 분당 트랜잭션 수 = 동시사용자 수 * 사용자당 트랜잭션 처리 수

2) 기본 tmpC 보정
- 20%: 단순, 동시사용자가 300명 미만
- 30%: 복잡, 동시사용자가 300명 이상

3) 피크타임 부하 보정
1004lucifer



4) 데이터베이스 크기 보정
- DB에 속한 가장 큰 테이블의 레코드 건수와 전체 DB의 볼륨을 고려하여 결정
- 아래에서 행은 가장 큰 테이블의 레코드 건수(million)를, 그리고 열은 데이터베이스 크기(Gbyte)를 나타낸다. 




5) 어플리케이션 구조 보정




6) 어플리케이션 부하 보정




7) 클러스터 보정




8) 시스템 여유율 (30%)
- 예기치 못한 업무의 증가 및 시스템의 안정된 운영을 위한 보정치, 일반적으로 피크타임을 고려하여 30%를 적용
1004lucifer
- 산정방식
- 산정식에서 보정치 및 여유율은 100%를 추가한 후 소수점으로 변환(예, 30%는 1.3)하여 계산한다.






나) WEB/WAS (ops 추정방식)

1) 동시사용자 수
- 불특정 다수를 대상: 전체사용자의 1~10%를 접속사용자로 보며, 이러부터 5%~10%를 동시사용자로 산정
- 특정 다수를 대상(인트라넷): 10~20%를 동시사용자로 적용할 수 있다.
<사례>
전국민을 대상으로 하는 서비스인경우 아래와 같이 산정
가입자 수: 100만명
동시접속자 수: 10,000명
동시사용자 수: 1,000명

2) 사용자당 오퍼레이션 수
- 사용자당 한 사람이 초당 발생시키는 비즈니스 로직 오퍼레이션 수로서 다음과 같이 업무유형에 따라 3~6개 정도로 가정


3) 인터페이스 부하 보정 (5%)
- 서버가 타 서버와 통신하게 될 때 인터페이스에서 발생하는 부하를 고려한 보정치, 일반적으로 5% 적용
1004lucifer
4) 피크타임 부하 보정 (아래의 예시 참고)


5) 클러스터 보정


6) 시스템 여유율 (30%)
- 예기치 못한 업무의 증가 및 시스템의 안정된 운영을 위한 보정치로서, 일반적으로 30%를 적용


- 산정방식
- 보정치 및 여유율은 100%를 추가한 후 소수점으로 변환 (예, 30%는 1.3)하여 계산한다.




2) 메모리 산정방식 (프로그래밍 언어나 쓰레드, 특정 시스템에 대한 메모리 구성특성의 반영 고려하지 않고 일반적인 시스템 용도와 구조를 바탕)

가) 시스템 영역
- 시스템 운영시 구동되는 모든 소프트웨어의 소요공간 산정 (일반적으로 각각의 소프트웨어 제조사가 권고하는 필요메모리 반영)

나) 사용자당 필요메모리
- 각 벤더의 WEB, WAS, DBMS 특성에 따라 요구되는 메모리 등을 감안하여 계산한다.
- 계산이 불가능한 경우 0.5MB ~ 1.5MB 값을 임의로 적용할 수 있다.

다) 동시사용자 수
- 독립적으로 산정하는 것이 아니라 이전 단계에서 산정한 CPU의 동시사용자 수 추정치와 동일한 값을 적용한다.

라) 버퍼캐쉬 보정
- 시스템 운영자의 요구에 의해서 정해진다.
1004lucifer
마) 시스템 여유율 (30%)
- 예기치 못한 업무의 증가 및 시스템의 안정된 운영을 위한 보정치로서, 일반적으로 30%를 적용


- 산정방식
- 보정치 및 여유율은 100%를 추가한 후 소수점으로 변환 (예, 30%는 1.3)하여 계산한다.





3) 디스크 산정방식
- 시스템디스크는 모든 서버에 대해 산정하나 데이터디스크는 서버의 특성이나 목적 혹은 구성 형태에 따라 선택적으로 산정한다.
- 디스크 포멧 시 15% 정도의 공간이 필요로 하게되지만 지침의 산정식에서는 이를 감안하지 않고있으니
디스크 규모산정치에 이를 추가적으로 고려할 필요가 있다.

가) 시스템 OS영역
- 대상시스템에 설치될 운영체제, 시스템 S/W와 수퍼유저(SU)를 위한 영역을 포괄한다. (OS, S/W의 크기는 벤더가 권장하는 크기를 바탕으로 산정)

나) 응용프로그램 영역
- 서버용 S/W, 응용 S/W, DBMS 설치에 따른 영역의 모든 크기의 합을 구한다. (S/W는 벤더가 권장하는 크기를 바탕으로 산정)
- DBMS의 경우 실자료공간, 예비용데이터 공간, 인덱스 및 키 데이터 공간 등 세부항목의 합계로 결정

다) SWAP 영역
- 일반적으로 메모리 요구량의 2배로 산정

라) 파일시스템 오버헤드
- 시스템디스크의 경우: 시스템OS 영역과 응용프로그램 영역, SWAP 영역을 합한 값의 10%정도
- 데이터디스크의 경우: 데이터 영역과 백업 영역을 합한 값의 10%정도

마) 시스템/ 데이터 디스크 여유율
- 일반적으로 30%를 산정 (전체 필요 디스크량의 20~50% 정도를 여유율로 산정)

바) 데이터 영역
- 실제 필요한 데이터량을 대상으로, 계산시 매년 증가치를 반영하여 산정

사) 백업 영역
- 백업정책에 의해서 결정
1004lucifer
아) RAID 여유율
- RAID1의 경우 100%를, RAID5의 경우 30%로 산정


- 산정방식
- 파일시스템 오버헤드 및 시스템/데이터디스크 여유율은 100%를 추가한 후 소수점으로 변환(예, 30%는 1.3)하여 계산한다.