8월 22일 TIL

·2023년 8월 22일
0

CS 공부

메인 질문 CPU의 구성 요소 4가지
→산술논리 연산장치(ALU), 제어부(CU)와 내부 버스, 레지스터, 캐시 메모리(L1)

▷ 레지스터
레지스터의 종류 5가지와 무엇을 각각 무엇을 저장하는지 작성
1. 메모리 주소 레지스터: (MAR) : 읽고 쓰기 위한 주기억장치의 주소를 저장한다.
2. 프로그램 카운터 (PC) : 다음에 수행할 명령어의 주소를 저장
3. 명령어 레지스터 (IR) : 현재 실행 중인 명령어를 저장
4. 메모리 버퍼 레지스터 (MBR) : 주기억장치에서 읽어온 데이터나 저장할 테이터를 임시로 저장
5. 누산기 (AC, ACCUMULATOR) : 연산 결과를 임시로 저장

이 레지스터들은 CPU 구성 중 (무엇)을 돕는데 사용되나요? (무엇)은 어떤 역할을 하나요?
산술논리 연산장치(ALU)를 돕는다. 산술논리 연산장치(ALU)는 CPU에서 비교, 판단, 연산을 담당한다.

범용 레지스터와 특수목적 레지스터는 각각 어떤 용도로 사용되나요?
범용: 연산에 필요한 데이터나 연산 결과 임시 저장
특수목적 : 특별한 용도로 사용 - 위의 종류 5가지가 여기에 해당한다.

▷ 제어장치(CU)
제어장치는 제어부와 내부버스를 의미한다. 각각은 어떤 역할을 하는가?
제어부 : 주기억 장치에 저장되어 있는 명령어 순서대로 호출 후 해독하고, 제어 신호를 발생시켜 컴퓨터의 각 장치를 동작하도록 한다.
내부버스 : 기억, 연산, 제어 기능을 실현하기 위한 CPU와 주기억 장치, 입출력 장치, 외부 기억 장치, 주변 장치, 통신 처리 장치 등의 제어부 사이를 연결하는 버스

▷ 연산장치
연산 장치란 무엇인가?
산술 논리 장치 / 덧셈, 뺄셈같은 산술연산과 논리 연산을 계산하는 디지털 회로

▷ CPU의 동작
언어의 고도화 단계를 순서와 각 언어에 대한 설명으로 작성해주세요.
1. 기계어 (0,1) / 저장공간
2. 어셈블리어 : 기계어를 모스부호처럼 하드웨어적으로 CPU가 알아볼 수 있게 변환한 언어
3. 프로그래밍 언어 : 어셈블리어를 사람이 알아볼 수 있도록 변환한 언어

CPU가 명령어를 읽고 수행하는 동작에 대해 순서대로 작성해주세요
1. 명령어 인출 : 수행할 명령어를 가져온다.(CU)
2. 명령어 해독 : 명령어 정보 인출 후 명령어 해독, 레지스터 준비(CU)
3. 실행 : 해독된 명령어 수행, 산술/논리 관련 연산이면 ALU가 주체가 된다.
4. 반영 : 명령어 수행 결과를 반형하면 한 싸이클 마무리.

▷ CPU의 성능
CPU 스펙에서 클럭과 코어는 각각 무엇인가요?
클럭 : CPU 내부에서 일정한 주파수를 가지는 신호로, 이 신호로 모든 명령어가 동작되게 된다. 주파수가 빠를 수록 성능↑
코어 : 중앙 처리 장치 장치 역할을 하는 블록이다. 멀티 코어는 싱글 코어에 비해 많은 연산을 빠르게 병렬 처리 할 수 있다.

▷ 메모리
메모리의 큰 종류 3가지를 말하고 각각을 주 기억장치와 보조 기억장치로 분류해주세요
캐시메모리(SRAM), 메인 메모리(DRAM) : 주 기억장치
하드디스크(HDD): 보조 기억장치

위 3가지 메모리를 조회 속도가 빠른 순으로 나열하세요.
캐시메모리(SRAM) → 메인 메모리(DRAM) → 하드디스크(HDD)

▷ 캐시메모리
캐시 메모리에 대해 설명하세요.
전원이 꺼지면 지워지지만 제일 빠르게 조회할 수 있다.
컴퓨터 시스템 향상을 위해 CPU와 주기억장치 사이에 있는 아주 작고 비싼 메모리
L1 : CPU 구성에 있는 캐시 메모리
L2, L3 : 메모리 그룹에 속한 캐시 메모리

L2, L3 캐시 메모리와 CPU 레지스터의 차이점에 대해서 설명하세요
L2, L3 : CPU와 별도의 공간, 메인 메모리와 CPU간의 속도차이를 극복하기 위한 용도
CPU 레지스터 : CPU 내부의 연산 처리를 위한 데이터 저장공간

▷ 주 기억장치
주 기억장치에 대해 설명하세요.
전원이 꺼지면 지워지지만 조금 더 빠르게 조회할 수 있다. 캐시메모리보다는 느리지만 보조기억장치보단 빠르다.
메인메모리 = 주기억장치 = RAM(Random Access Memory)
CPU가 현재 처리중인 데이터나 명령을 일시적으로 저장하는 휘발성 메모리
모든 프로그램은 '실행'하기 위해 주기억장치 메모리의 일부를 사용한다.

주 기억장치와 보조 기억장치의 차이를 동적/정적, 재충전 필요 여부, 금액으로 분리하여 작성해주세요.
주 기억장치 : 정적, 재충전 필요 없음, 비쌈
보조 기억장치 : 동적, 주기적인 재충전 필요, 저렴함

▷ 보조 기억장치
보조 기억장치에 대해 설명하세요.

전원이 꺼져도 지워지지 않는 저장공간, 데이터와 프로그램 반영구적 저장 = 비휘발성 메모리

최종 프로젝트 구현 중..

오늘은 리스트 정렬 중 생긴 문제와 해결 방법에 대해서 기록해 볼 것이다..!

이런식으로 생긴 셀렉트 박스에 담긴 레이블 값에 따라 리스트를 정렬하려는데
중요한 점은 무한스크롤을 후에 할 수도 있다는 점을 고려하자는 것이였다.

원래도 기능 구현은 했었는데 기존 방식은 리스트 데이터를 한 번만 불러온 후 그 데이터를 계속해서 선택된 레이블에 맞게 switch-case 문으로 정렬하는 것이였다. 아래는 그 당시 작성했던 코드이다 ↓

  // 검색 기능이 적용된 상태에서 정렬이 가능하게끔 연결된다.
  const sortedFreelancers = filteredfreelancerLists || [];
      switch (selectedSortLabel) {
        case "조건1":
          sortedFreelancers.sort(
            (a, b) => Number(b.workExp) - Number(a.workExp)
          );
          break;
        case "조건2":
          sortedFreelancers.sort(
            (a, b) => Number(a.workExp) - Number(b.workExp)
          );
          break;
        case "조건3":
          sortedFreelancers.sort(
            (a, b) => Number(b.singUpDate) - Number(a.singUpDate)
          );
          break;
        case "조건4":
          sortedFreelancers.sort(
            (a, b) => Number(a.singUpDate) - Number(b.singUpDate)
          );
          break;
        case "조건5":
          sortedFreelancers.sort(
            (a, b) => Number(b.portfolioCount) - Number(a.portfolioCount)
          );
          break;
        case "조건6":
          sortedFreelancers.sort(
            (a, b) => Number(a.portfolioCount) - Number(b.portfolioCount)
          );
          break;
        default:
          sortedFreelancers.sort(
            (a, b) => Number(b.workExp) - Number(a.workExp)
          );
          break;
      }
      setFilteredFreelancers(filteredfreelancerLists);

하지만! 이렇게 되면 무한스크롤 진행 시 스크롤을 내려서 새롭게 데이터를 불러오게 되면 정렬이 안된 채로 데이터가 불러오게 될 것이라는 문제가 생겼다.. 무한 스크롤을 프로젝트 기간 내에 구현할 수 있을지 모르지만 고려해놓으면 좋을 것 이라고 생각해서 전체 로직을 수정하기로 결정했다.

현재 react-query를 사용해서 데이터를 불러오는데 기존에는 그냥 조건에 맞는 리스트를 통째로 가져왔었다. (정렬x)

    // 데이터 불러오는 부분
    const { data, error } = await supabase
      .from("users")
      .select("*")
      .eq("role", "freelancer");

수정 후에는 미리 정해놓은 switch-case를 이용해서 선택된 레이블의 orderByField를 기준으로 order를 통해서 미리 정렬 되어있는 상태로 데이터가 불러와지게 했다.

   // switch-case 부분 짧게 
   switch (sortLabel) {
      case "조건1":
        orderByField = "workExp";
        ascending = false;
        break;
      case "조건2":
        orderByField = "workExp";
        ascending = true;
        break;

    // 데이터 불러오는 부분
    const { data, error } = await supabase
      .from("users")
      .select("*")
      .order(orderByField, { ascending });

그런데 여기서 문제가 발생한 부분이 있다.
화면이 최초로 렌더링 되었을 때*
1. 메뉴를 선택할 때마다 새로운 query로 데이터를 불러오기 때문에 select로 레이블을 선택할 때마다 화면이 깜빡거린다. 하지만 다시 해당 레이블을 클릭하면 깜빡임 없이 정렬되었다.
2. select에서 모든 레이블을 각각 최초로 선택했을 때 리스트는 정렬이 되지만 select에 내가 선택한 레이블이 표시되는 것이 아니라 기본 값인 "조건1"로만 보여지고 다시 그 레이블을 선택해야지 select에 반영이 되었다.
두 문제의 공통점은 처음에만 문제가 있고 두 번 같은 행동을 반복했을 때는 괜찮다는 점....🤯

해결방법 ↓
나는 이 문제의 해결을 위해 react-query dev tools를 많이 참고했다.
일단적으로 이 해결 방법이 좋은건지는 알 수 없다.. 혹시 수정하게 되면 다시 추가로 작성하겠다!

수정 전의 dev tools

다른 레이블을 선택하면 이렇게 해당 데이터(정렬이 변경된 상태)가 불러와진다.

그래서 내가 생각한 것은 데이터가 새로 불러와지면서 컴포넌트 리렌더링이 발생하고 1번 문제인 화면 깜빡임이 발생하고 동시에 항상 select에 설정된 기본 값이 띄워지는 것 같았다.
그리고 또 생각한 것은 차라리 미리 불러와놓자는 것이였다. 현재의 내 수준에서는 이 해결 방법이 그나마 제일 빠르게 해결할 수 있는 방도라고 생각했다..

수정 후의 dev Tools

적용 코드는 이렇다

// 미리 모든 정렬에 대한 쿼리를 호출하여 데이터를 가져와 놓는다.
useEffect(() => {
    const sortLabels = [
      "조건1",
      "조건2",
      "조건3",
      "조건4",
      "조건5",
      "조건6",
    ];

    sortLabels.forEach((label) => {
      queryClient.prefetchQuery(["freelancersData", label], () =>
        getFreelancersBySort(label)
      );
    });
  }, [queryClient]);

여기서 queryClient.prefetchQuery는 이 코드를 작성하면서 처음 알게 되었는데
prefetching은 데이터를 캐시에 추가하며, 구성할 수 있긴 하지만 기본값은 만료(stale)인 상태로 가져오는 것입니다.
레이블을 선택하여 원하는 정렬의 데이터를 가져오고자 하면 만료 상태의 데이터를 가져오게 되고
데이터를 가져오는 중에는 캐시에 있는 데이터를 보여주게 됩니다.

queryClient.prefetchQuery('쿼리 키', '쿼리 함수'); 

작성법 및 구성은 useQuery 를 사용할 때와 매우 유사하다고 볼수 있다!

  useEffect(() => {
    if (selectedSortLabel !== "") {
      queryClient.invalidateQueries(["freelancersData", selectedSortLabel]);
    }
  }, [selectedSortLabel]);

그리고 이렇게 코드를 작성해 줌으로써 selectedSortLabel(내가 선택한 레이블)이 변경될 때마다 + 선택된 레이블이 비어있지 않을 때만(초기 선택된 정렬 레이블 무시) freelancersData 쿼리의 캐시를 무효화 시키고 이후에 해당 데이터를 다시 불러올 때는 최신 데이터를 가져올 수 있게 됩니다. 이렇게 해서 사용자에게 레이블이 변경 될 때마다 최신 데이터까지 보여지도록 처리하며 해결할 수 있었습니다..!

profile
코린한별

0개의 댓글