운영체제 공부한 내용들을 바탕으로 질문을 만들어 정리하는 내용!
현재까지 스터디 하면서 받았던 질문들, 정리해주신 분들의 질문 내용 참고하여 작성
🔍 운영체제란 무엇인가요?
운영체제는 시스템 프로그램의 일종으로 사용자들이 컴퓨터를 쉽게 운영할 수 있도록 하는 프로그램입니다.
🔍 운영체제의 역할은 무엇인가요?
운영체제는 크게 4가지의 역할을 합니다. CPU 스케줄링과 프로세스를 관리하고, 메모리를 관리하며, 디스크 파일을 관리하고, I/O 디바이스를 관리하는 역할을 합니다.
🔍 시스템 콜은 무엇인가요?
시스템 콜은 사용자 프로그램이 운영체제의 커널 기능을 사용할 수 있도록 제공되는 인터페이스입니다. 예를 들어, 파일 입출력이나 프로세스 생성 같은 작업은 운영체제의 자원 관리가 필요하기 때문에, 프로그램이 시스템 콜을 통해 요청하면 운영체제가 이를 처리합니다. 이는 사용자 모드에서 커널 모드로 전환되며 실행되고, 운영체제의 안정성과 보안을 유지하는 데 중요한 역할을 합니다.
🔍 시스템콜과 라이브러리 함수의 차이점은 무엇인가요?
라이브러리 함수는 주로 사용자 공간에서 실행되며, 시스템 콜을 포함할 수 있습니다. 반면, 시스템 콜은 커널 공간에서 직접 실행되며, 하드웨어나 운영체제의 핵심 기능에 접근할 수 있습니다.
🔍 시스템콜이 발생하는 과정을 설명해주세요.
1. 사용자 프로그램이 라이브러리 함수를 호출
2. 라이브러리 함수가 시스템 콜을 트리거
3. CPU가 모드 전환(사용자 모드 -> 커널 모드)을 수행
4. 커널이 요청된 서비스를 처리
5. 결과를 사용자 공간으로 반환하고 모드 전환을 완료.
🔍 fork()와 exec() 시스템 콜의 차이점은 무엇인가요?
fork()는 현재 프로세스를 복제해 새로운 자식 프로세스를 생성하지만,
exec()는 현재 프로세스의 메모리 공간을 새로운 프로그램으로 대체합니다.
🔍 커널이란 무엇인가요?
운영체제의 핵심 부분을 메인 메모리에 적재한 것입니다.
커널은 하드웨어와 응용 프로그램 사이에서 인터페이스를 제공하고 추상화를 통해 하드웨어에서 오는 자원을 관리하고 응용 프로그램이 사용할 수 있도록 해줍니다.
🔍 지역성이란 무엇인가요?
지역성은 데이터 접근이 시간적, 혹은 공간적으로 가깝게 일어나는 것입니다. 구체적으로 설명하자면 시간적 지역성은 특정 데이터가 한번 접근되었을 때, 빠른 시간 안에 한 번 데이터에 접근할 가능성이 높은 것을 의미합니다. 공간적 지역성은 액세스 된 기억장소와 인접한 기억장소가 액세스 될 가능성이 높다는 것을 의미합니다.
🔍 캐시 메모리란 무엇인가요?
캐시 메모리는 CPU의 처리 속도와 주 기억 장치의 접근 속도 차이를 줄이기 위해 사용한다. 데이터 지역성을 활용해 메인 메모리에 있는 데이터를 캐시 메모리에 불러오고, CPU가 필요한 데이터를 캐시 메모리에서 먼저 찾도록 해 시스템 성능을 향상할 수 있다.
🔍 캐시 메모리의 동작 원리는 무엇인가요?
캐시 메모리는 지역성의 원리를 기반으로 동작합니다. CPU는 먼저 캐시 메모리에서 필요한 데이터를 찾고, 캐시에 없다면 메인 메모리에서 데이터를 가져와 캐시에 저장하고 CPU로 전송합니다. 이를 통해 CPU는 데이터를 빠르게 액세스 할 수 있게 됩니다.
🔍 캐시 메모리의 교체 정책에는 어떤 것들이 있나요?
캐시 메모리의 교체 정책은 캐시가 꽉 찼을 때, 더 이상 사용할 수 없는 데이터를 캐시에서 제거하고 새로운 데이터를 저장하는 방법을 결정하는 정책입니다.
LRU(Least Recently Used) : 가장 오래 사용되지 않은 데이터를 교체하는 방식입니다.
FIFO(First In FIrst Out) : 캐시에 가장 먼저 들어온 데이터를 교체하는 방식입니다.
LFU(Lease Frequently Used) : 사용 빈도가 가장 적은 데이터를 교체하는 방식입니다.
Random Replacement : 무작위로 데이터를 교체하는 방식입니다. 간단하지만 비효율적일 수 있습니다.
🔍 만약 필요한 데이터가 하드디스크에 있으면, CPU에서 바로 하드디스크에 접근해서 가져오면 되는데 왜 굳이 모든 계층 구조를 모두 통해서 가져오는지?
프로그램의 실행은 지역적인 특성을 가지고 있습니다. 지역적인 특성으로 인해 L1 캐쉬, L2 캐쉬에 필요한 데이터가 있을 확률이 높습니다. 그렇기에 하드디스크에서 데이터를 읽어들이는 빈도수가 많지 않습니다. 이런 의미에서 계층적으로 메모리를 두었을 때 성능이 훨씬 좋아집니다.
🔍 스택 영역과 힙 영역의 차이가 무엇인가요?
스택 영역은 컴파일 시에 크기가 결정되며 지역변수나 메소드가 저장되는 영역입니다. 또한 공유 영역중 아래쪽 영역부터 할당이 이루어지게 됩니다.
반면 힙 영역은 런타임 시에 동적으로 할당되어 크기가 따로 결정되지 않습니다. 객체들이 주로 할당되고 공유 영역중 위쪽 영역부터 할당이 이루어지게 됩니다.
🔍 프로세스가 무엇인가요?
프로그램이 메모리에 올라갔을 때를 프로세스라고 하며 CPU 스케줄링에 의해 관리되는 작업입니다.
🔍 프로세스 제어 블록이란 무엇인가요?
Process Counter, Stack Pointer, Process Status 같은 프로세스를 관리하기 위한 정보들을 저장하는 구조체입니다.
프로세스가 생성됨과 동시에 고유한 PCB가 생성되며, 사용자가 접근하지 못하는 커널 영역에 저장됩니다. 프로세스가 종료된 후에 PCB도 함께 사라집니다.
🔍 컨텍스트 스위칭이 무엇인가요?
여러 프로세스를 처리하는 과정에서 현재 프로세스의 상태나 정보들을 PCB에 저장하고, 다음 진행할 프로세스의 상태 값을 읽어 레지스터에 적재하는 과정을 의미합니다.
🔍 멀티 쓰레드와 멀티 프로세스의 차이는 무엇인가요?
멀티 쓰레드와 멀티 프로세스는 말 그대로, 여러개의 쓰레드 혹은 여러개의 프로세스로 구성되어 병렬적으로 작업을 수행하도록 하는 것입니다.
둘의 차이에 경우 멀티 쓰레드는 하나의 프로세스의 스택 외의 영역을 공유하여 쓰레드끼리 통신 비용이 감소하고, Context Switching시 스택 영역에 대해서만 초기화하면 되기 때문에 교환에 대한 비용이 적습니다. 하지만, 쓰레드 하나가 종료될 경우 전체 쓰레드가 종료될 수 있는 문제가 있습니다.
🔍 IPC 방식에는 어떤 것들이 있는지 설명하고, 각각의 장단점을 말해주세요.
IPC는 프로세스 간 데이터를 교환하거나 협력하기 위해 사용하는 기술로, 다양한 방식을 운영체제가 제공하고 있습니다.
1) 파이프
: 단방향 통신 방식으로, 주로 부모-자식 프로세스 간 사용됩니다. 구현이 간단하지만, 단방향 통신만 가능하며 두 프로세스가 동시에 실행 중이어야 합니다.
2) 메시지 큐
: 메시지를 큐에 저장하고, 순차적으로 전달하는 방식으로, 비동기 통신이 가능하지만 메시지 크기에 제한이 있을 수 있습니다.
3) 공유 메모리
: 여러 프로세스가 동일한 메모리 공간을 공유하여 데이터를 교환하는 방식으로, 빠르고 대용량 데이터 처리에 적합하지만, 동기화 문제를 해결해야 합니다.
4) 소켓
: 네트워크를 통해 다른 시스템의 프로세스와 통신하는 방식으로, 로컬 및 원격 프로세스 간 통신이 가능하지만 구현이 복잡합니다.
5) 시그널
: 특정 이벤트를 알리기 위한 신호를 전달하며, 간단한 알림에 적합하지만 데이터 교환에는 적합하지 않습니다.
🔍 임계 영역(Critical Section)과 경쟁 상태(Race Condition)은 무엇인가요?
임계 영역은 멀티 쓰레드 상황에서 공유 자원이 존재하는 영역을 말합니다. 이 공유 자원을 여러 쓰레드가 동시에 접근하여 자원의 신뢰성을 해칠 수 있는 상태를 경쟁 상태라고 합니다.
🔍 CPU 스케줄링의 목적은 무엇인가요?
CPU 사용률을 최대화하고, 프로세스의 응답 시간을 최소화하며, 프로세스 처리 속도를 최대한 빠르게 해 전체 시스템의 성능을 향상시키느 것
🔍CPU 스케줄링 알고리즘의 종류는 무엇이 있나요?
FCFS(First-Come, First-Served) -> 먼저 도착한 프로세스를 먼저 처리하는 방식, 대기시간이 길어질 수 있다.
SJF(Shortest Job First) -> 가장 짧은 실행 시간을 가진 프로세스를 먼저 처리하는 방식, 평균 대기 시간을 줄일 수 있습니다.
Round Robin -> 각 프로세스에 동일한 시간 슬라이스를 부여해 차례대로 CPU를 사용하는 방식
Priority Scheduling -> 각 프로세스에 우선순위를 부여하고, 우선순위가 높은 프로세스부터 처리하는 방식
Multilevel Queue Scheduling -> 여러 큐로 프로세스를 분류하고, 각 큐에 대해 서로 다른 스케줄링 알고리즘을 적용하는 방식
🔍 FCFS 스케줄링의 장단점은 무엇인가요?
매우 간단하고 직관적인 장점이 있지만, 호위 효과가 발생할 수 있다.
호위 효과는 긴 프로세스가 먼저 도착한 경우, 그 뒤에 도착한 짧은 프로세스들이 오래 기다려야 하는 문제점을 말한다.
🔍Round Robin 스케줄링의 장단점은 무엇인가요?
시간 할당량(time quantum)을 정해, 준비 상태에 있는 프로세스들이 일정 시간 동안 순서대로 CPU를 사용하는 스케줄링 방식입니다.
응답 시간이 중요할 때 유리하며, 모든 프로세스에 공평하게 CPU를 배정합니다.
하지만, 시간 할당량이 너무 크면 FCFS와 비슷해지고, 너무 작으면 문맥 교환 오버헤드가 증가할 수 있습니다.
🔍 인터럽트(Interupt)가 무엇인가요?
현재 실행 중인 프로세스나 작업을 일시적으로 중단하고, 우선 순위가 높은 다른 작업을 처리하기 위해 CPU의 주의를 전환시키는 신호이다.
인터럽트의 종류에는 하드웨어 인터럽트와 소프트웨어 인터럽트가 있고, 하드웨어 인터럽트는 I/O 작업을 하거나 운영체제의 타이머 인터럽트가 있으며 소프트웨어 인터럽트의 경우 예외 상황이나 시스템 콜이 발생했을 때를 말합니다.
가장 중요한 차이점은 하드웨어 인터럽트는 외부 이벤트에 의해 비동기적으로 발생하고, 소프트웨어 인터럽트는 프로그램의 흐름에 따라 동기적으로 발생합니다.
🔍 인터럽트(Interupt) 발생시에 처리 과정은 무엇인가요?
1. 인터럽트 발생
2. 인터럽트 신호 수신 -> CPU는 인터럽트 신호를 감지하고, 현재 작업을 중단할 준비를 한다.
3. 현재 상태 저장 -> 프로세스의 상태를 저장하여 나중에 복귀할 수 있도록 한다.
4. 인터럽트 벡터 테이블 조회 -> 발생한 인터럽트에 해당하는 인터럽트 서비스 루틴의 주소를 인터럽트 벡터 테이블에서 조회한다. 인터럽트 벡터 테이블은 각 인터럽트 유형에 따라 ISR의 주소를 저장한 테이블이다.
5. 인터럽트 서비스 루틴 실행 -> 해당 ISR을 실행해 인터럽트 요청을 처리한다.
6. 상태 복원 -> ISR 실행을 완료하면, 이전에 저장한 프로세스의 상태를 복원한다.
7. 실행 재개 -> 저장된 상태를 복원 후, CPU는 중단되었던 작업을 이어서 실행한다.
🔍 주소공간이란 무엇인가요?
주소 공간은 프로세스가 사용할 수 있는 메모리 주소의 전체 범위를 의미합니다. 운영체제는 각 프로세스에 독립적인 주소 공간을 할당해 메모리의 충돌을 방지하고, 프로세스 간의 격리와 보안을 보장합니다.
🔍 프로세스의 주소 공간은 일반적으로 어떻게 구성되나요?
1. 코드 섹션 : 실행 가능한 명령어가 저장되는 영역
2. 데이터 섹션 : 초기화된 전역 변수와 정적 변수가 저장되는 영역
3. BSS 섹션 : 초기화되지 않은 전역 변수와 정적 변수가 저장되는 영역
4. 힙 : 동적 메모리 할당을 위한 영역
5. 스택 : 함수 호출 시 지역 변수와 리턴 주소를 저장하는 영역
🔍 가상 주소 공간과 물리적 주소 공간의 차이는 무엇인가요?
가상 주소 공간은 각 프로세스에게 독립적으로 제공되는 주소 공간으로, 프로세스가 인식하는 메모리 주소입니다. 반면 물리적 주소 고간은 실제 하드웨어 메모리의 주소 공간으로, 가상 주소는 메모리 관리 장치(MMU)를 통해 물리적 주소로 변환되어 사용됩니다.
🔍 가상 주소 공간을 사용하는 이유는 무엇인가요?
메모리 관리의 효율성과 프로그램의 안정성을 높이기 위해서입니다.
1) 프로그램마다 독립적인 주소 공간을 제공해, 하나의 프로그램이 다른 프로그램의 메모리에 접근하거나 영향을 주는 것을 방지한다.
2) 가상 주소를 물리 주소로 매핑하는 과정을 통해 실제 메모리가 부족한 경우에도 디스크를 활용해 메모리 가상화를 구현할 수 있다.
3) 가상 주소 공간을 통해 연속적인 주소 공간을 가지는 것처럼 동작시켜, 메모리 단편화를 줄이고 효율적으로 메모리를 활용할 수 있도록 한다.
🔍 32비트 주소 공간과 64비트 주소 공간의 차이는 무엇인가요?
32비트 주소 공간은 최대 4GB(2^32)의 메모리를 주소 지정할 수 있습니다.
반면, 64비트 주소 공간은 2^64의 메모리를 주소 지정할 수 있어, 훨씬 더 큰 메모리 용량을 지원합니다.
그러므로 대규모 데이터 처리와 고성능 컴퓨팅에 유리합니다.
🔍 주소 변환이란 무엇인가요?
컴퓨터 시스템에서 프로그램이 사용하는 가상 주소를 실제 하드웨어가 인식하는 물리적 주소로 변환하는 과정입니다.
🔍 논리 주소와 물리 주소의 차이점은 무엇인가요?
논리 주소는 프로그램이 사용하는 주소로, 가상 메모리의 주소 공간을 의미합니다. 물리 주소는 실제 하드웨어 메모리의 주소를 의미합니다.
🔍 페이징이란 무엇인가요?
페이징은 가상 메모리를 고정 크기의 페이지로 분할하고, 물리 메모리를 동일한 크기의 프레임으로 분할해 가상 주소를 물리 주소로 변환하는 방식입니다.
🔍 페이징에서의 주소 변환은 어떻게 이루어지나요?
페이징에서는 CPU가 생성한 가상 주소를 물리적 주소로 변환하기 위해 페이지 테이블을 사용합니다.
1. 가상 주소 분할 : 가상 주소는 페이지 번호와 페이지 오프셋으로 분할됩니다.
2. 페이지 테이블 조회 : 페이지 번호를 이용해 페이지 테이블에서 해당 페이지가 매핑된 프레임 번호를 찾습니다.
3. 물리 주소 계산 : 프레임 번호f와 페이지 오프셋 d를 조합해 물리 주소를 계산합니다.
-> 물리 주소 = (프레임 번호 * 프레임 크기) + 페이지 오프셋
🔍 페이징의 장점과 단점은 무엇인가요?
장접으로는 외부 단편화가 없고, 비연속적인 메모리 공간에 할당될 수 있어 메모리 활용도가 높습니다. 또한 고정된 크기의 블록을 사용하기 때문에 메모리 할당과 해제가 용이합니다.
단점으로는 프로세스의 마지막 페이지가 채워지지 않으면 사용되지 않는 메모리가 생기고, 각 프로세스에서 페이지 테이블을 유지해야 하기 때문에 메모리 오버헤드가 발생합니다. 페이지 테이블 조회로 인한 메모리 접근 시간이 늘어날 수 있는 단점도 있습니다.
🔍 페이지 폴트란 무엇이고, 운영체제는 어떻게 처리하나요?
페이지 폴트는 프로세스가 접근하려는 페이지가 메모리에 존재하지 않을 때 발생하는 예외 상황입니다.
1. 페이지 폴트 발생 : CPU는 페이지가 메모리에 없음을 감지하고 운영체제로 제어를 넘깁니다.
2. 운영체제 확인 : 해당 페이지 접근이 유효한지 검사하고, 유효할 경우 디스크에서 해당 페이지를 메모리로 로드합니다. 유효하지 않다면, 프로세스를 종료하거나 예외를 처리합니다.
3. 페이지 테이블 갱신 : 로드된 페이지의 프레임 정보를 페이지 테이블에 업데이트합니다.
4. 프로세스 재개 : 중단된 명령어부터 프로세스 실행을 재개합니다.
🔍 페이지 교체 알고리즘은 무엇이고, 어떤 종류가 있나요?
페이지 교체 알고리즘은 메모리가 가득 찬 상태에서 새로운 페이지를 메모리에 로드해야 할 때, 어느 페이지를 교체할지 결정하는 방법입니다.
FIFO -> 가장 먼저 메모리에 로드된 페이지를 교체합니다.
LRU -> 가장 오랫동안 사용되지 않은 페이지를 교체합니다.
OPT -> 앞으로 가장 오래 사용되지 않을 페이지를 교체합니다(이론적 알고리즘)
LFU -> 사용 빈도가 가장 낮은 페이지를 교체합니다.
Clock Algorithm -> FIFO를 개선한 방식으로, 사용 여부에 따라 교체 대상을 결정합니다.
🔍 페이지 교체 알고리즘 중 LRU와 FIFO에 대해 설명해주시고, 각각의 장단점에 대해 말해주세요.
LRU는 가장 오랫동안 사용되지 않은 페이지를 교체하는 방법으로, 최근 사용된 데이터를 유지하므로 성능이 좋습니다. 하지만 구현이 복잡하고 각 페이지의 사용 시점을 추적하기 위해 추가적인 메모리와 계산 자원이 필요하다는 단점이 있습니다. 반면, FIFO는 가장 먼저 들어온 페이지를 교체하는 방법으로, 큐 구조를 사용해 구현이 단순하고 메모리 소모가 적습니다. 하지만 오래된 데이터가 계속 필요할 경우에도 교체가 이루어져 성능이 저하될 수 있습니다.
🔍 Memory Management Unit(MMU)의 역할은 무엇인가요?
MMU는 주소 변환을 수행하는 하드웨어 장치로, 가상 주소를 물리 주소로 변환하고 메모리 접근을 제어합니다.
🔍 세그먼테이션이란 무엇인가요?
세그먼테이션은 메모리를 가변적인 크기의 블록인 세그먼트로 나누는 방법으로, 프로그램의 논리적 구조(코드, 데이터, 스택 등)에 따라 메모리를 분할합니다.
🔍 TLB(Translation Lookaside Buffer)의 역할은 무엇인가요?
페이지 테이블의 일부를 캐시로 보관해 주소 변환 속도를 높이는 하드웨어 장치입니다.
🔍 페이징과 세그먼테이션을 결합한 메모리 관리 방법은 무엇이며, 그 장점은 무엇인가요?
페이징과 세그먼테이션의 결합은 세그먼테이션으로 논리적인 메모리 구조를 반영하면서, 각 세그먼트를 페이징해 메모리 관리의 효율성을 높이는 방법입니다.
장점으로는 세그먼테이션으로 프로그램 구조를 반영해 메모리 접근의 의미를 유지하고, 세그먼트를 페이지로 나누어 페이징함으로 외부 단편화를 줄입니다. 또한 세그먼트 단위로 접근 권한을 부여하고, 필요한 경우 세그먼트 공유가 가능합니다.
🔍 가상 메모리의 이점은 무엇인가요?
물리적 메모리 크기에 관계없이 큰 가상 주소 공간을 제공합니다. 또한 실제로 필요한 페이지만 메모리에 로드해 메모리를 절약합니다.
각 프로세스는 독립된 가상 주소 공간을 가져 보안과 안정성을 높입니다. 프로그래머는 메모리 제약을 신경 쓰지 않고 개발할 수 있습니다. 여러 프로세스가 동시에 실행될 수 있도록 지원합니다.
🔍 동기화가 왜 필요한가요?
동기화는 여러 프로세스나 스레드가 공유 자원에 접근할 때 발생할 수 있는 데이터 불일치와 경쟁 조건을 방지하기 위해 필요합니다. 동기화를 통해 자원의 일관성을 유지하고, 프로세스 간의 협력을 원활하게 합니다.
🔍 뮤텍스와 세마포어의 차이점은 무엇인가요?
뮤텍스는 하나의 스레드만이 공유 자원에 접근할 수 있도록 하는 락으로, 상호 배제를 보장합니다. 오직 잠금을 획득한 스레드만이 자원을 사용할 수 있고, 잠금을 해제하는 것도 해당 스레드만 가능합니다.
세마포어는 카운터를 이용해 여러 스레드가 공유 자원에 접근하는 것을 제어합니다. 세마포어는 소유권이 없으며, 여러 스레드가 신호를 보내거나 대기할 수 있습니다. 세마포어는 자원의 개수를 관리하는데 사용되며, 특히 여러 스레드가 자원을 동시에 사용할 수 있는 경우에 유용합니다.
🔍 교착상태가 발생할 수 있는 상화과 이를 방지하기 위한 방법은 무엇인가요?
교착 상태는 두 개 이상의 프로세스가 서로 상대방이 점유한 자원을 기다리면서 무한 대기하는 상태입니다. 교착 상태의 발생 조건은 상호 배제, 자원 보유 및 대기, 비선점, 순환 대기입니다.
교착 상태 예방 : 네 가지 조건 중 하나 이상을 제거해 교착 상태가 발생하지 않도록 한다.
교착 상태 회피 : 자원의 상태를 감시하고, 교착 상태로 이어질 수 있는 자원 할당을 피한다.
탐지 및 회복 : 교착 상태가 발생한 후 이를 탐지하고, 프로세스를 중단하거나 자원을 회수하여 회복한다.
🔍 파일 시스템은 무엇인가요?
데이터를 저장하고 관리하는 구조를 제공하는 운영체제의 구성 요소입니다. 파일 시스템에서는 하드 디스크, SSD 등의 물리적 저장 장치에 데이터를 효율적으로 관리할 수 있도록 파일 및 디렉토리 구조를 제공합니다.
🔍 파일 시스템의 주요 기능은 무엇인가요?
파일 저장 및 검색 : 파일 시스템은 데이터를 파일 단위로 저장하고, 필요할 때 해당 파일을 검색하여 사용할 수 있게 해줍니다.
파일 및 디렉토리 구조 관리 : 파일을 디렉토리(폴더) 구조로 관리해 데이터를 조직적으로 정리하고 접근할 수 있도록 합니다.
접근 권한 관리 : 파일 및 디렉토리에 대한 사용자별 접근 권한을 설정해 보안을 강화합니다.
공간 할당 및 관리 : 디스크 공간을 효율적으로 할당하고 관리하며, 파일이 저장된 위치와 크기를 추적합니다.
에러 탐지 및 복구 : 파일 시스템은 데이터 손상을 방지하거나 복구하기 위한 오류 탐지 기능을 제공합니다.
'정리' 카테고리의 다른 글
[정리] 안드로이드 - Compose (0) | 2024.11.09 |
---|---|
[정리] 네트워크 정리 (0) | 2024.08.29 |
[정리] 프로그래밍 언어 정리 (0) | 2024.05.29 |
[정리] 안드로이드 정리 (0) | 2024.05.28 |
[정리] 자료구조 정리 (0) | 2024.05.28 |