var returnedFactorial = factorial( (number=4) ) { // 여기서 다음 factorial 함수 호출 // number=4 이므로, if문은 false(실행안함)
var returnedFactorial = factorial( (number=3) ) { // 여기서 다음 factorial 함수 호출 // number=3 이므로, if문은 false(실행안함)
var returnedFactorial = factorial( (number=2) ) { // 여기서 다음 factorial 함수 호출 // number=2 이므로, if문은 false(실행안함)
var returnedFactorial = factorial( (number=4) ) { // 여기서 다음 factorial 함수 호출 // number=1 이므로, if문은 true(실행) if(number == 1) { return 1; }
// 위의 if문이 true이므로 return 1;을 하게 되어 하단의 코드는 무시됨.
// var returnedFactorial = factorial(number-1); // return number * returnedFactorial ; }
return number * returnedFactorial ; }
return number * returnedFactorial ; }
return number * returnedFactorial ; }
return number * returnedFactorial ; }
한글로 풀어보자면, factorial에 파라미터로 전달된 number가 1이 되기 전까지는 factorial(number-1)을 계속 호출합니다. 1이 되면 return 1;을 만나서 재귀가 종료됩니다.
그러므로 재귀함수에서는 기본적으로 return 문이 2개 이상 존재해야 정상 작동됩니다.(재귀된 값을 리턴하는 리턴문과, 재귀 자체를 종료하는 리턴문)
또한 factorial(5)를 호출하면, factorial(5)의 재귀로 인해 factorial(4)가 호출되는 이런 형태로 진행이 되는데, 이 경우, factorial(5)는 factorial(4)가 종료될 때 까지 함수가 종료되지 않고 메모리에서 대기합니다. 마찬가지로 factorial(4)는 factorial(3)을 기다리고, 결국 마지막 factorial(1)이 실행되어 return 1;을 실행하기 직전에는 메모리 사용량이 최대가 되는거죠.
위와같은 이유로, 재귀함수는 잘못사용하게 되면 메모리를 잡아먹는데 큰 일조를 할 수 있습니다.
용도에 맞게 사용되어야 하며 factorial 또한 재귀가 아닌 방법으로 구현할 수 있으므로 실무에서는 크게 사용될 일이 적을 것이라고 보여집니다. 저의 경우에는 웹에서 다단계 메뉴 구조를 "생성"할 때 재귀를 통해 구현을 하고, 해당 결과 값을 html로 출력한 뒤, 해당 값을 사용자에게 출력하는 방식으로 사용합니다.
이렇게 사용하면, 메뉴 구조를 변경하는 경우(자주 일어나지 않으며, 관리자가 주로 변경)에만 재귀함수를 호출하기 때문에 사용자로 하여금 재귀함수의 문제인 메모리 이슈(속도 저하) 등을 겪지 않게 되는거죠.
삼치구이님의 댓글에 덧붙여서 쉽게 설명해보자면 A a = new A();를 했을 때 a 변수에 저장되는건 새로 생성된 인스턴스가 아닌 인스턴스의 주소 값이 저장됩니다. 그리고 이 주소 값을 매개변수로 하여 메서드를 실행했을 때도 주소 값을 전송하는 것 이므로, 어디서 접근하던지 수정되는 값은 모두 동일한 위치에 있는 값입니다. clone() 메서드를 통해서 새로운 인스턴스를 복사해야 원하시는대로 이루어지며, 이러한 방식보다는 위에서의 "A am = a;" 부분을 "A am = new A(); am.setProperty(property);"으로 바꾸거나, A am = new A(); 대신 am.clone()을 사용하시면 되겠습니다.
"카테고리, 타겟, 태그는 enum 같은 정해진 몇개의 텍스트 " - 정해진 몇개의 텍스트라면 varchar를 사용하시는 편이 검색이 빠르던 것으로 알고있습니다.
" select * from fr_hit where hitter=2 and category="community" and tag="inbox" and target=744 "
이 부분을 한개당 0.3초라고 하신 것 같은데, mysql 입장에서는 조금 다릅니다. 1. hitter가 2인것을 모든 행에서 찾고, 2. category가 community인것을 (1)을 찾은 모든 행에서 찾고, 3. tag가 inbox인 것을 (2)를 찾은 모든 행에서 찾고, 4. target이 fr_test.id와 같은것을 (3)을 찾은 모든행에서 찾는
위와 같은 형태로 돌아갑니다. 데이터에 따라 튜닝 형태가 달라지겠지만, 기본적으로 검색할 때는 가장 검색자료가 적은 것 (이름, 나이, 주민등록번호 열이 있다면 주민등록번호, 이름, 나이 순으로 검색.)부터 넣어야 하고, 다른 테이블과의 비교가 필요없는 경우에는 on이 아닌 where 절에 넣어 검색하는게 맞습니다.
UML을 현업에서 쓰고 있으며, 정말 필요하다고 생각합니다. 개발자로서 가장 중요한 부분이 고객과의 커뮤니케이션 그리고 개발자간의 커뮤니케이션이라고 생각하는데, 고객과의 커뮤니케이션을 위해 요구분석서, 스토리보드 등이 필요한 것처럼, 개발자들끼리 확실한 의미 전달을 위해 사용하는게 UML입니다.
현업이든 어디서든 여럿이서 개발하다 보면 같은 생각이라고 시작했지만 결과적으로 서로 다른 생각이였어서 실패하는 경우가 많습니다.
HashMap<String, Object> hashMap = new HashMap<String, Object>(); hashMap.put("memberVo", resultVo);
if(resultVo == null) { throw new Exception("아이디 혹은 비밀번호가 맞지 않습니다."); }
if(!memberService.checkHashedPassword(resultVo.getPassword(), memberVo.getPassword())) { //아이디 혹은 비밀번호가 맞지 않다는 메시지를 나타내는 이유는 사용자에게 아이디가 존재하는지 알리지 않기 위함. throw new Exception("아이디 혹은 비밀번호가 맞지 않습니다."); }