-
항해 99 5기 TIL_36항해 99 2022. 2. 15. 03:37
▶ Today I Learned
<CS>
[토큰 저장 방식]
로그인을 위해 JWT 방식을 사용하기로 했고 서버에서 로그인이 인증되면 토큰을 생성하여 클라이언트로 보내주게 된다.
이때 클라이언트에서는 토큰을 받아 저장해야하는데, 그 저장 방식을 고민하게 되었다.
방법은 아래와 같다.
로컬 스토리지: 브라우저에 해당 데이터 저장, 세션 스토리지와는 다르게 사용자가 지울 때 까지 브라우저에 남아있게 됨,
자동 로그인에 적절,
세션 스토리지: 브라우저에 해당 데이터 저장, 로컬 스토리지와는 다르게 브라우저 탭을 닫는 순간 지워지게 됨,
일회성 로그인에 적절
두 스토리지는 window에 위치함,
프로토콜, 호스트, 포트가 같으면 같은 스토리지를 공유,
브라우저별로, 기기별로 다르긴 하지만 보통 모바일은 2.5mb, 데스크탑은 5mb~10mb임
보통 키-밸류 로 이루어진 데이터를 저장하며 어떤 형태의 데이터도 저장 가능하지만 저장 시 문자열로 저장됨
객체를 통째로 저장하려면 setItem() 시에는 JSON.stringify, getItem()할 시에는 JSON.parse로 찾음
아래와 같은 형태로 찾을 수 있음
/ keyName 이라는 이름의 key 에 objectData 이름의 객체 데이터를 세션에 저장 sessionStorage.setItem(keyName, JSON.stringify(objectData)); // keyName 이름의 String 을 가져와 JSON 형태로 다시 Parse 진행 JSON.parse(sessionStorage.getItem(keyName));
쿠키: 쿠키에 해당 정보를 담아 브라우저에 저장, 최대 용량은 4KB이며 만료 기한을 정할 수 있음,
단, 요청을 할 때 마다 쿠키를 매번 보내게 됨(로컬과 세션 스토리지는 서버로 데이터가 자동 전송되지 않음),
HTTP의 특성 상 매번 페이지가 로딩되거나 전환될 때 마다 요청을 보내게되고 그러면 쿠키에 담긴 용량이 매번 쓰이게 된다는 단점이 있음
아래 링크에서 좀 더 자세한 설명 참조 가능
출처:
https://www.zerocho.com/category/HTML&DOM/post/5918515b1ed39f00182d3048
https://sanghye.tistory.com/14
[CPU]
Central Processing Unit (중앙 처리 장치)
→ 프로그램을 실행하기 위해 메인 메모리에서 명령어를 인출하여 해독하고 실행한다.
각각의 단계를 Fetch phase, Decode phase, execute phase라고 함
- 연산
- 덧셈, 뺄셈, 곱셈 등의 산술 연산과 논리곱, 논리합, 부정 등의 논리 연산을 수행
- 제어
- 명령어를 순서대로 실행할 수 있도록 제어
- 저장
- 연산에 필요한 데이터, 연산 결과, 명령어 주소 등을 임시로 저장
CPU의 구조
- 레지스터(Register)
- CPU 내부에 있는 메모리
- 명령어 주소, 코드, 연산에 필요한 데이터, 연산 결과 등을 임시로 저장
- 고속 기억장치
- 다양한 종류가 있음(PC, IR, MBR 등)
- 제어 장치(Control Unit)
- 각 장치들의 동작을 결정하는 신호를 보낸다.
- 주기적장치에서 프로그램 명령어를 꺼내 해독하고, 그 결과에 따라 명령어 실행에 필요한 제어 신호를 기억장치, 연산장치, 입출력 장치로 보냄
- 연산장치(ALU, Arithmetic Logic Unit)
- 산술 및 논리 연산 수행
핵심 특수 목적 레지스터
- 메모리 주소 레지스터(MAR) : 읽기와 쓰기 연산을 수행할 주기억장치의 주소를 저장
- 프로그램 카운터(PC) : 다음에 수행할 명령어의 주소를 저장
- 명령어 레지스터(IR) : 현재 실행 중인 명령어를 저장
- 메모리 버퍼 레지스터(MBR) : 주기억장치에서 읽어온 데이터나 주기억장치에 저장할 데이터를 임시로 저장
- 누산기(AC) : 연산 결과를 임시로 저장
CPU 동작과정
- 주기억장치는 입력장치에서 입력 받은 데이터 또는 보조기억장치에 저장된 프로그램 읽어옴
- CPU는 프로그램을 실행하기 위해 주기억장치에 저장된 프로그램 명령어와 데이터를 읽어와 처리하고 결과를 다시 주기억장치에 저장한다.
- 주기억장치는 처리 결과를 보조기억장치에 저장하거나 출력장치로 보낸다.
- 제어장치는 명령어가 순서대로 실행되도록 각 장치를 제어한다.
CPU 클럭 주파수 (Clock Frequency)
CPU clock frequency 는 CPU 동작 속도를 의미하고, '초당 사이클'을 의미한다. (단위는 Hz)
(사이클은 명령어가 요구하는 동작 들을 수행하는 단위)
동적 주파수 스케일링 (dynamic frquency scaling))을 가지고 있어 speed 조절 가능
Overclocking -> 프로세스 처리 속도를 올릴 수 있지만 신호가 안정되는 속도보다 clock 속도가 빨라질 수도 있으며 CPU가 과열될 수 있음
Underclocking -> 컴퓨터를 사용하지 않을 때 전력 소모를 줄이는 효과가 있음 (노트북이나 휴대폰처럼 배터리 사용하는 것에 유용함)
출처:
https://hidelookit.tistory.com/154
<알고리즘>
조이스틱
소요 시간: 1시간 25분 + 2시간 + 50분
해결 여부 : 미해결
https://programmers.co.kr/learn/courses/30/lessons/42860
열심히 아래와 같이 짜보았다.
let name = "AAAAEEAAAA" let leftRight = 0 //AJEARAO 이거에서 거꾸로 시작하는 건 마치 // AOARAEJ와 같다 // 그렇다면 // 문자열 첫번째 문자를 제외하고 잘라낸 다음 그것을 배열로 쪼개 역순으로 뒤집고 이를 다시 합쳐주어 원래 문자에 더하자. let reversedName = name.substring(0,1) + name.substring(1).split('').reverse().join('') console.log(reversedName) //문자열 내 A가 포함되어 있는가? 그리고 문자중 하나라도 A가 아닌게 있는가? console.log(name.includes('A')); if(name.includes('A')) { // 좌우 경우의 수 따지기 console.log(name.split('')) // "JERAOEN" 인 경우를 고려해보면 A가 중간에 있을 때 나눈 배열의 길이는 같지만 실제로 첫번째에서 마지막문자로 갈때의 횟수 1이 더해지므로 둘중 어떤 선택지가 나을지 비교할 때 [첫번째 배열 길이]와 [두번째 배열 길이 +1]을 비교해주어 더 큰쪽이 있다면 그쪽을 택해야 함 console.log(reversedName.split('')) console.log(name.split('').lastIndexOf('A')) console.log(reversedName.split('').lastIndexOf('A'))// 인덱스가 더 큰쪽이 적게 감 -> 더 마지막 부분에 A가 있기 때문? // 하지만 "EEEAEAR"로 하게 되면 인덱스가 각각 5,4 이지만 횟수는 똑같아 fail // name이나 reversedName의 마지막 글자중 하나라도 A인 경우에는 위의 식이 성립, 아니라면 인덱스 번호가 어떻든 간에 결과는 같음 if(name[name.length-1] === 'A' || reversedName[reversedName.length-1] === 'A') { if(name.split('').lastIndexOf('A') > reversedName.split('').lastIndexOf('A')) { // EERAEAA처럼 마지막에 A가 몰려있는 경우?는 어떻게 값을 반환하지? // 뒤집으면 AAEAREE E의 인덱스는 2 // console.log(name.split('').reverse().reduce((a, b, curIndex) => {if(a === 'A' && b === a) {} else {return curIndex}})) // reduce 구문이 안 멈춘다.. let i = 0 while (i < name.length) { if(name.split('').reverse()[i] === 'A' && name.split('').reverse()[i] === name.split('').reverse()[i+1]) { } else { // 끝에서 A가 이어지다가 다른 문자가 나오는 인덱스를 찾아 반환 console.log('정답', i+1) console.log(reversedName.length - 1 - (i + 1)) // 네임 원래 순서대로, 즉, 오른쪽으로 가는 것 leftRight = reversedName.length - 1 - (i + 1) break } i++ }; // EERAEAA에서 E의 인덱스는 4 } else { // name.split('').lastIndexOf('A') <= reversedName.split('').lastIndexOf('A') let i = 0 while (i < reversedName.length) { if(reversedName.split('')[i] === 'A' && reversedName.split('')[i] === reversedName.split('')[i+1]) { } else { // 끝에서 A가 이어지다가 다른 문자가 나오는 인덱스를 찾아 반환 console.log('정답', i+1) console.log(reversedName.length - (i + 1)) // 네임 원래 순서대로, 즉, 오른쪽으로 가는 것 leftRight = reversedName.length -1 - (i + 1) break } i++ } } } else { // 둘다 A가 들어가있긴 하지만 그게 마지막 인덱스가 아니기 때문에 // 어차피 마지막 까지 이동하여 글자를 바꾸어야 함 -> 어느 쪽으로 가도 좌우 이동 횟수는 같음 leftRight = name.length - 1 } } else { // 문자열 내 A가 없단 소리이므로 좌우 어디로 가도 좌우 이동 횟수는 똑같음, 따질 필요 없음 leftRight = name.length - 1 }; console.log('최종 좌우 결과', leftRight)
하지만 간과한 사실이 있었다.
바로, 정방향이든 역방향이든 어느 한쪽으로만 쭉 가야하는 건 아니라는 것이다..!
아래와 같은 예시가 있었다.
//JBCAAAAABD" 라는 name이 주어졌을 때, JBC를 만들고 다시 뒤로이동(◀)해서 BD를 완성하면 최소로 이동하는 횟수가 될 것이다 // 이 경우를 고려하지 못했다,,! 난 그저 중간에 A가 있는 경우는 좌우 어디로 가도 어차피 똑같으니까 신경안써야지 했는데... // 이렇게 중간에 A가 많이 있는 경우는 진짜 상상도 못했다... 스스로 테스트 케이스를 나눠보지 못한 나, 생각이 짧았다..
내일 해당 풀이를 좀 더 살펴보아야 겠다.
▶ 느낀 점
오늘도 나름 열심히 공부했다 ;) 비록 알고리즘에서도, CS에서도 배울 것이 한참 남아있지만 그래도 이렇게 하루를 보내며
내 지식을 하나씩 차곡차곡 채워나간다.
끝났을 때 뿌듯할 내 모습을 상상하며 히히
▶ 공부 시 참고 링크들
https://tobegood.tistory.com/entry/programmersJoystickJavaScript
https://ghost4551.tistory.com/113?category=982768
'항해 99' 카테고리의 다른 글
항해 99 5기 TIL_38 (0) 2022.02.17 항해 99 5기 TIL_37 (0) 2022.02.16 항해 99 5기 WIL_5 (0) 2022.02.13 항해 99 5기 TIL_35 (0) 2022.02.13 항해 99 5기 TIL_34 (0) 2022.02.13 - 연산