'어려움' 문제를 내가 스스로 생각해서 처음 맞췄다!!!!!!!!!!!!!!!
오늘 등원할때 궁둥이에 찝찝한게 묻어서 기분이 안좋았었는데 문제 잘푸려고 그랬나보다. 너무너무 행복하다 !
알고리즘 풀이접근법을 잘 몰랐던 내가 이렇게 발전할 수 있는 이유는
1.RunJS를 켜서 실시간으로 값을 확인하며 풀것
2.주어진 값들을 확인하고 어떻게 가공해야하는지 콘솔로 계속 찍으며 생각할것
3.도출하는 값의 타입을 확인하면서 적절한 메서드를 쓸것
이 전에는 사실 귀찮아서(?) 콘솔도 잘 안찍어가며 runjs만 겨우 돌렸는데,
알고리즘 마스터가 될거야 !!!!!!!!!!
-오늘의문제
당신은 폰켓몬을 잡기 위한 오랜 여행 끝에, 홍 박사님의 연구실에 도착했습니다. 홍 박사님은 당신에게 자신의 연구실에 있는 총 N 마리의 폰켓몬 중에서 N/2마리를 가져가도 좋다고 했습니다.
홍 박사님 연구실의 폰켓몬은 종류에 따라 번호를 붙여 구분합니다. 따라서 같은 종류의 폰켓몬은 같은 번호를 가지고 있습니다. 예를 들어 연구실에 총 4마리의 폰켓몬이 있고, 각 폰켓몬의 종류 번호가 [3번, 1번, 2번, 3번]이라면 이는 3번 폰켓몬 두 마리, 1번 폰켓몬 한 마리, 2번 폰켓몬 한 마리가 있음을 나타냅니다. 이때, 4마리의 폰켓몬 중 2마리를 고르는 방법은 다음과 같이 6가지가 있습니다.
첫 번째(3번), 두 번째(1번) 폰켓몬을 선택
첫 번째(3번), 세 번째(2번) 폰켓몬을 선택
첫 번째(3번), 네 번째(3번) 폰켓몬을 선택
두 번째(1번), 세 번째(2번) 폰켓몬을 선택
두 번째(1번), 네 번째(3번) 폰켓몬을 선택
세 번째(2번), 네 번째(3번) 폰켓몬을 선택
이때, 첫 번째(3번) 폰켓몬과 네 번째(3번) 폰켓몬을 선택하는 방법은 한 종류(3번 폰켓몬 두 마리)의 폰켓몬만 가질 수 있지만, 다른 방법들은 모두 두 종류의 폰켓몬을 가질 수 있습니다. 따라서 위 예시에서 가질 수 있는 폰켓몬 종류 수의 최댓값은 2가 됩니다.
당신은 최대한 다양한 종류의 폰켓몬을 가지길 원하기 때문에, 최대한 많은 종류의 폰켓몬을 포함해서 N/2마리를 선택하려 합니다. N마리 폰켓몬의 종류 번호가 담긴 배열 nums가 매개변수로 주어질 때, N/2마리의 폰켓몬을 선택하는 방법 중, 가장 많은 종류의 폰켓몬을 선택하는 방법을 찾아, 그때의 폰켓몬 종류 번호의 개수를 return 하도록 solution 함수를 완성해주세요.
제한사항
nums는 폰켓몬의 종류 번호가 담긴 1차원 배열입니다.
nums의 길이(N)는 1 이상 10,000 이하의 자연수이며, 항상 짝수로 주어집니다.
폰켓몬의 종류 번호는 1 이상 200,000 이하의 자연수로 나타냅니다.
가장 많은 종류의 폰켓몬을 선택하는 방법이 여러 가지인 경우에도, 선택할 수 있는 폰켓몬 종류 개수의 최댓값 하나만 return 하면 됩니다.
입출력 예
nums result
[3,1,2,3] 2
[3,3,3,2,2,4] 3
[3,3,3,2,2,2] 2
입출력 예 설명
입출력 예 #1
문제의 예시와 같습니다.
입출력 예 #2
6마리의 폰켓몬이 있으므로, 3마리의 폰켓몬을 골라야 합니다.
가장 많은 종류의 폰켓몬을 고르기 위해서는 3번 폰켓몬 한 마리, 2번 폰켓몬 한 마리, 4번 폰켓몬 한 마리를 고르면 되며, 따라서 3을 return 합니다.
입출력 예 #3
6마리의 폰켓몬이 있으므로, 3마리의 폰켓몬을 골라야 합니다.
가장 많은 종류의 폰켓몬을 고르기 위해서는 3번 폰켓몬 한 마리와 2번 폰켓몬 두 마리를 고르거나, 혹은 3번 폰켓몬 두 마리와 2번 폰켓몬 한 마리를 고르면 됩니다. 따라서 최대 고를 수 있는 폰켓몬 종류의 수는 2입니다.
-아름이의 기특한 풀이
- localStorage
- 우리 어제 로그인해서 받은 토큰으로 들어가서 내 이름 불러올수 있었던 페이지,
새로고침하면 토큰을 못받아와서 튕겨나가는거 설정했었지!- 근데 그러면 안되지 원래는! 로그인 한번하면
계속 내 아이디로 볼 수 있어야하지!
그니까 브라우저 자체에 저장하는 로컬스토리지라는 데에서
새로고침해도 토큰을 받아올수 있는것 알아볼거야 !
- 지금 내가있는 페이지의 개발자도구의 애플리케이션이다!
들어가보면 로컬스토리지에 값이 들어있는것을 확인가능하다 ! 콘솔로 확인가능하다!
그러면 vscode에서도 사용 가능한거겠지?
- 그러면 여기에 토큰을 저장해놓고
브라우저를 껐다가 키더라도 로그인이 유지되게 할 수 있겠지 !!
로컬 스토리지란? 브라우저에 영구적으로 저장되는 값! - 키와 벨류형태로 저장한다
(보안에 취약해서 중요한 정보 안됨,
그래서refresh토큰에 원래 access토큰 담는데
우리는 일단 여기다 담아서 써보자 ! )
쿠키 - 만료시간 설정가능
쿠키는 클라이언트(브라우저) 로컬에 저장되는 키와 값이 들어있는 작은 데이터 파일.
사용자 인증이 유효한 시간을 명시할 수 있으며, 유효 시간이 정해지면 브라우저가 종료되어도 인증이 유지됨.
세션 스토리지 - 브라우저를 끄면 사라진다
세션은 쿠키를 기반하고 있지만, 사용자 정보 파일을 브라우저에 저장하는 쿠키와 달리 세션은 서버 측에서 관리
서버에서는 클라이언트를 구분하기 위해 세션 ID를 부여하며 웹 브라우저가 서버에 접속해서 브라우저를 종료할 때까지 인증상태를 유지
setItem으로 키와 벨류를 저장하는 과정 ! (키와 벨류를 입력하라고 뜬다 ! )
localStorage.setItem("accessToken",accessToken)
요렇게 한줄 적어주고나니
로그인성공 페이지 갔을때 저장이 된것을 확인가능 !
(다시한번 말하지만 accessToken원래 여기에 저장하는것은 안된다! 보안상 ! )
토큰은 잘 저장해줬는데, 새로고침하면 토큰으로 패치를 하진 못한다 !
새로고침해서 받아올거라고 설정해줘야겠지 ?
새로고침했을때, 로컬스토리지에 있는 accessToken을 가져와라! 라고 app.tsx에 설정을 해줘야한다 !
- Next.js 렌더링의 Diffing / Hydration
프론트엔드 서버에서 브라우저에 넘기기전에 한번 렌더링을 쫙 해보는것
-> prerendering (프리렌더링)
-모든걸 완벽하게 그리는건 아니고, 유즈이팩트, 컴포넌트디드마운트 같은거 말고,
최초1회만 (마운트되기전까지) 딱 그려봐보는 과정이다
-온체인지, 온클릭 같은거 바인딩 안된상태로, 큰 그림 (div..)만 그려보는것
-그 다음에 브라우저에 넘겨준다
-브라우저에서도 실제로 제대로 그림 그리기전에 한번 그려서
프리렌더링과 비교를 해본다 - (diffing 디핑!)
-비교를해서 디핑(diffing)이후에 최종완성형으로 업데이트해주는 과정을 (hydration)이라한다
-하이드레이션 과정에서 자바스크립트의 기능들 함수들이 다 연결되어 최종적으로 그려진다
- 그래서 프리렌더링 할때는 !
로컬스토리지, 세션스토리지안에 아무것도 없다 (중요!)로컬호스트나, 브라우저라는 개념이 없기 때문이다!
그래서 localstorage is not defined가 나오게 되어버린것 !
1번에는 로컬스토리지가 없고, 2번스토리지에 있어서 에러가 난것이다 !
윈도우는 브라우저를 말해
그래서 콘솔에 window.alert하면 뜨는거 확인가능
window가 있다는 뜻? 브라우저가 있다는뜻 !
if(typeof window === "undefined") 이 말은 프론트엔드 서버라는 뜻이다 !
(브라우저에서 그리는게 아니고, 프론트엔드서버다)
if(typeof window !== "undefined") 이건 브라우져라면,
우리의 오류는 .....
프리렌더링페이지에서는 로컬스토리지가 뭐냐? 못찾겠다! 하는거다그러면 디핑할때 브라우저의 로컬스토리지에 저장된 토큰을
프론트서버의 state값으로 넘겨서
최종 완성형으로 그려줄때 데이터를 받아오면 되겠다 !
그러면 로그인 성공 페이지에 가서 이렇게 써주자,
이렇게 지금은 두가지 방법을 쓸수있다 !
새로고침해도 로컬스토리지에있는 스테이트를 꺼내와서 recoilstate에 넣어주기때문에 가능하다
- 권한분기의 이해
-한사이트의 관리자 페이지이란,
유저목록페이지, 통계기록페이지, 등등 사용위한 사이트가 아닌, 관리를 하기위한 사이트 !
프론트엔드 페이지(도메인이) 3개가 될수도 있고, 하나의 도메인으로 3개를 조건에 나눠쓸수도 있다
같은데이터를 쓰려하는거니 백엔드는 공유하게 되는것 !
하나의 사이트에서, 로그인별로 로그인한사람, 안한사람, 관리자인사람 !을 권한분기를 나누려고 할거다
그러려면 알아야하는 기능중에 하나 !
- 자바스크립트에 이런것이 ? - Closure
함수안의 함수를 실행하는 방법,
return해서 함수를 반환하거나 안에서 안을 실행해야됨
aaa()를 실행할때 return 해주면 함수가 나오는게 보이지
안에있는 값을 나오게 하려면 함수를 실행하고 또 실행해야하기때문에
(aaa( ) ) 얘가bbb가 되는거고 ( aaa ( ) )( )이게 bbb( )이게 되는거다 근데 전체는 안감싸줘도 되어서
aaa( )( )이렇게 적어도 된다 !
그래서 리턴되는 함수의 이름은 필요가 없어 !
aaa( )어차피 이거하면나오고( )걔를 이거붙여서 실행시켜줄꺼니까!
여기서 우리가 알수 있는건, apple은 없지만 스코프체인에 의해서 바깥에 있는 변수에 접근가능해서
가져다가 쓰는것내부함수에서 외부함수의 변수(지역변수)를 closure라고 한다 !
-> 말이 조금 어려운데, 지금 내 지역 바깥쪽의 공간! 이라고 이해하장
안에서 선언을 하는 방법 말고, 함수안에 넣어줘서 결과를 도출하는법 ! (알고리즘 풀때랑 똑같다)
aaa("이건사과에여")("이건바나나에요") => 이게 우리에게 hoc의 개념으로 들어올거야
브라우저에서 그려주다가 여기서 멈추라고 하는 breakpoint(중단점)클릭하면 거기까지만 그려진다 !
스택(stact)과 큐(queue)의 개념이 여기서도 다시 등장하게 되고 !
스택과 큐의 개념 오랜만에 다시보기 !스택(stact) - first in last out/ last in first out -리포구조
큐(queue)- first in first out - 피포구조
예) 쉽게말해 ctrl-z의 기능은, 스택으로 쌓여있어서 누를때마다 가장 최근의 작업 되돌리기 기능이 가능한것!
검사의 callstack부분을 보게되면
스택에 먼저 실행된 aaa함수가 시작되면서 쌓이고,
bbb가 먼저 종료가 되어야 aaa가 종료가 되고 다시 어나니머스로 돌아가야 함수가 끝나는거다
aaa만 실행을 해봤는데, scope에 qqq랑 apple이 undefined로 있네?
호이스팅이 되어서 먼저 변수가 선언만 된거고, 할당은 아직 안된거 !
내부함수의 외부함수의 지역변수들의 공간이 closure인거고
그 안에 apple=10이 있고 그래서 bbb안에서 apple을 사용할수 있는것이다
aaa함수로 돌아가는 순간 closure는 빠지게 된다 (안쪽 공간에서 나왔으니까!)
- React에서 제공하는 hoc와 그를 더 쉽게 사용할수 있게 해주는 hof가 있다
hoc를 custom-hooks로 바꾸는 과정까지...!
- 밑에 로그인 성공페이지에서 토큰을 가져와서 없을때 내보내기 해줬는데,
그러면 로그인이 필요한 모든페이지에 저 부분을 적어줘야한다
게다가 수정하기 부분에서 메시지가 바뀌거나 어떤 값이 바뀌면 모든페이지 들어가서 바꿔줘야한다
useEffect 부분을 빼놓고, import해서 페이지 그리기전에 검증하는 컴포넌트로 쓰면 어떨까?
그게 바로 Higher Order Component !!!!!!
- HOC / HOF
HOC - Higher Order Component ( 접속 전에 먼저 실행되는 컴포넌트)
간단하게 개념부터 이해해보자
Aaa가 부모고 Bbb가 자식인거고 이름은 철수입니다로 나오게 되겠지
이것을 가지고 함수형 컴포넌트를 그냥 함수로 변경하는것도 했었지
이게 우리가 생각해야할 부분이고, closure를 사용해줄꺼다
함수안에서 함수를 리턴하고 있기 때문에
중간 로직함수를 하나더 넣을수 있겠지!
먼저실행 컴포넌트 부분을 hoc라고 부른다 !
(사이트를 열기전에 검증이 필요하거나, 데이터를 불러와야 할때 자주 쓰일거야 !)
간단하게 이해하는 과정
중간에 <Component {...props}/>
이게 Bbb( {qqq:"철수"} )
정리부분
보통 검증하는 부분의 이름은 with가 붙게된다 (with보면 HOC인가? 생각하기!!관례니까!)
HOC가 컴포넌트라고 했다면 우리가 이렇게 썼다면
HOF는 하이오더펑션!
jsx를 리턴하지 않는다
onclickchild실행 el실행 event실행
클로저덕에 (el) (event)를 빨간박스 안에서 다 쓸 수 있다.
원래는 태그안에 id를 줘서 event.target.id를 썼었는데
el로 넘겨서 쓰는거고 event도 쓸수있게 되는거다
꼭 두개가 아니라 순서에 맞게 값을 계속 넣어줄수가 있다
map함수안의 el값을 받아서 다시 그 함수에 넣어줘서 결과가 찍힌다는게 hof!
오늘은 알고리즘 시험이 있는날이었는데 마지막 문제를 못풀어따 근데 다른사람들은 후딱풀고 코드 알려주고 배우다보니까 나는 왜 이런생각을 못했을까 또또! 자책하고 그랬는데...! 이거 엄청 안좋은 습관같다!
- 내가 나에게 실망한 포인트는
-문제를 보고 어떠한 방법과 메서드로 접근해야할지 다양한 방법이 떠오르지 않아서 (경험과 견문이 좁아)기본 if와 for문으로 해결하려 복잡하게 생각했다는것
-테스트케이스를 열어서 주어지는 변수들을 정확히 확인안하고 생각속에서만 확인하고 undefined만 보다가 포기한 점
-그 기분을 이어받아 알고리즘 시간에 집중하지 않고 나중에 들어야지하고 집중하지 않은것 자책한것 집에 빨리갈래라고 생각할것
- 이 느낀점을 토대로 나의 발전을 위해 해야할 행동
-경험이 부족하고 투자한 시간이 부족하다는것을 알았으니 알고리즘 공부 매일 1시간반 이상씩 할 것
-어려운 풀이가 나왔어도 이해하고 내것으로 만드려고 노력할것
-자기반성과 비하에 오랫동안 빠져있지말고 자기발전의 토대로 삼을것