게시글
블로그
전체 102025. 03. 28.
0
인프런 워밍업 클럽 3기 풀스택 - 4주차 발자국
4주차 학습 내용Part 1. Git Repository 생성 및 초기 설정 진행이번 프로젝트는 기존 강의에서 학습했던 방식대로 GitHub에 레포지토리를 생성하고, 초기 설정을 진행하며 시작했다.폴더 구조와 기본적인 세팅은 이전과 동일하게 구성하여 빠르게 시작할 수 있었다.새롭게 만든 message 테이블에는 다음과 같은 컬럼들을 추가했다.id: 기본 키 (primary key)message: 메시지 내용sender: 보낸 사람의 UUIDreceiver: 받는 사람의 UUIDis_deleted: 삭제 여부 (boolean)created_at: 생성 시간 (timestamp) Part 2. 회원가입, 로그인 화면 제작이전에 하던대로 틀 잡고, components로 구분지으면서 제작했다.새롭게 배운 부분으로는 배경색을 그라데이션으로 준 부분이였다. 테일윈드 css로 편하게 gradient값을 줬다.사용법bg-gradient-to-r: 그라디언트를 오른쪽 방향으로 흐르게 함 / ex) to-r = to right from-{color}: 그라디언트의 시작 색상 지정 / ex) from-green-400 to-{color}: 그라디언트의 끝 색상 지정 / ex) to-blue-500via-{color}: 그라디언트의 중간 색상 지정 / ex) via-pink-500 Part 3. Supabase Auth 소개 및 인증방식 기획Supabase Auth는 이메일 기반 인증부터 소셜 로그인까지 다양한 인증 방식을 제공하며, 회원가입, 로그인, 세션 유지 등을 쉽게 처리할 수 있는 백엔드 인증 서비스다.1. Confirmation URL 방식사용자 이메일로 인증 링크를 전송하고, 사용자가 해당 링크를 클릭함으로써 인증이 완료되는 방식이다.사용자가 회원가입(또는 로그인)을 하면, 이메일로 인증 링크가 전송되고사용자가 해당 링크를 클릭하면 Supabase가 사용자의 인증을 완료함 2. 6-Digit OTP 방식사용자 이메일로 6자리 숫자 코드(OTP)를 전송하고 사용자가 해당 코드를 입력해서 인증하는 방식 사용자가 이메일을 입력하면, Supabase는 해당 이메일로 6자리 OTP 코드를 전송하고사용자는 입력창에 이 코드를 입력하고 인증을 완료하게 된다. Part 6. 채팅 화면 구현1. 유저 아바타 랜덤 이미지 사용https://randomuser.me/photos API를 활용해 유저 프로필 사진을 랜덤으로 가져옴별도 이미지 업로드 없이 테스트용 아바타를 빠르게 구현할 수 있음 const randomImage = https://randomuser.me/api/portraits/men/${index}.jpg; 2. javascript-time-ago 라이브러리채팅 메시지 시간 표시를 "1분 전", "3시간 전"처럼 사람이 보기 쉬운 형태로 변환국제화(i18n)도 지원함 (예: 한글/영어/중국어 등)import TimeAgo from "javascript-time-ago"; import ko from "javascript-time-ago/locale/ko.json"; TimeAgo.addDefaultLocale(ko); const timeAgo = new TimeAgo("ko"); timeAgo.format(new Date()) // → "방금 전" Part 7. Supabase Realtime 소개 & 채팅목록 구현 Supabase Realtime은 PostgreSQL 데이터베이스의 변경 사항을 실시간으로 감지해서 클라이언트에 push해주는 기능.기본적으로 WebSocket을 기반으로 작동하고, 내부적으로는 PostgreSQL의 logical replication 기능을 활용한다. 🔧 작동 방식클라이언트가 WebSocket으로 채널 생성.channel() 메서드를 이용해서 원하는 테이블과 이벤트 종류를 구독함예: message 테이블의 INSERT 이벤트Supabase 서버에서 PostgreSQL의 변경 스트림 감지PostgreSQL에서 발생하는 INSERT, UPDATE, DELETE 이벤트를 감지이를 wal2json 등의 logical decoding plugin을 통해 JSON으로 변환Supabase Realtime 서버가 이를 브로드캐스트WebSocket 연결된 클라이언트에게 변경된 데이터(payload)를 push로 전달함프론트에서 실시간 UI 반영받은 payload로 상태를 업데이트하거나 refetch()를 통해 데이터를 다시 불러와서 렌더링Part 9. 배포하기 vercel 배포Add New 파일을 열고 프로젝트를 선택해준다. 나의 깃허브와 연동시켜주고 배포를 원하는 프로젝트를 선택해준다 Deploy를 누르면 배포가 되게 되는데 그전에 프로젝트의 이름을 정하고,프로젝트에서 npm run build를 해서 배포시에 발생할 에러가 있는지 미리 체크한다.그리고 환경변수에는 프로젝트에 있는 .env 파일에 있는 코드를 복사해서 넣어줘야한다. 사진과 같은 에러가 발생했고, 현재 에러를 해결하는 방법은 2가지가 있다.하나는 직접 에러의 원인을 찾아 제거하는 방식 = )}둘째는 any로 지정하는것 처럼 무시하고 지나가라는식의 방법으로 해결하는 방법이다.루트에 index.d.ts를 만들고, declare module "@material-tailwind/react";를 해줌으로써 material-tailwind로 발생하는 에러는 넘겨주는 것. 배포가 끝났고 이제 휴대폰에서도 정상적으로 동작한다! 미션: 그동안 만든 4개 프로젝트 배포하기선택 미션에는 채팅 메세지 삭제 기능 이나 채팅 읽음, 안 읽음 표시 등 추가 작업인데 우선 후순위로 미루고 배포에 집중함. 미션 이외로미션 이외로 나는 휴대폰으로 채팅하는 모습을 확인하고 싶어서 배포를 진행하고 휴대폰을 확인했다.하지만 이메일 인증을 하고 이동하는 코드는 아래처럼 되어 있어서 연결이 깨지게 되어 있다. const signupMutation = useMutation({ mutationFn: async () => { const { data, error } = await supabase.auth.signUp({ email, password, options: { emailRedirectTo: "http://localhost:3000/signup/confirm", }, }); if (data) setConfirmationRequired(true); if (error) alert(error.message); }, });그렇다고 여기서 저부분을 배포 주소로 바꾸자니, 나중에 버그나 새로운 기능을 넣기 위해 작업할때는 또 번거롭게 바꿔줘야 하기때문에 이 문제를 어떻게 해결할지에 대한 고민을 했다. const redirectUrl = process.env.NEXT_PUBLIC_REDIRECT_URL || (process.env.NODE_ENV === "development" ? "http://localhost:3000" : "https://supabase-instagram-clone.vercel.app"); const signupMutation = useMutation({ mutationFn: async () => { const { data, error } = await supabase.auth.signUp({ email, password, options: { emailRedirectTo: `${redirectUrl}/signup/confirm`, // ✅ 변수 사용 }, }); if (data) setConfirmationRequired(true); if (error) alert(error.message); }, });우선 리다이렉트를 구분하기 위해 로컬호스트에서는 로컬호스트를 보내고 수퍼베이스에서는 수퍼베이스만 보내도록 수정함.버셀에서 환경변수를 추가해주고수퍼베이스에서도 배포한 링크를 연결시켜주니 해결했다.말은 쉬운데 사실 해결하려고 몇시간을 싸매고 한 결과다..ㅠ성공한 사진!!🎉🎉UI적으로는 다듬지 못해서 엉망인 모습을 보이고, 남들이 보기엔 별거 아닐지라도 나한테는 휴대폰과 노트북으로 서로 소통을 하는게 이렇게 돌아가는구나 라는것을 느끼고 되게 신기했다.---📝 마지막 회고4주차는 지금까지 중 가장 힘든 한 주였던 것 같다.평소엔 기능을 하나씩 구현해왔는데 이번 주차는 로그인과 채팅 기능을 함께 다루다 보니 정신없고 벅찼다.점점 기능 난이도가 깊어지고 있다는 느낌도 들어서, 생각보다 어렵게 다가왔다.특히 이번 주에는 코드를 따라 치긴 했지만 이해가 부족했던 순간들도 많았고주말에 큰 약속이 있어서 과제를 빨리 끝내야 한다는 부담감 때문에 급하게 하다 보니 놓친 부분도 많았던 것 같다.그렇게 어느새 4주차.. 이 스터디의 마지막 주차가 되어버렸다.돌이켜보면 한 달 전의 나와 비교해 분명 많이 성장한 시간이었다. 📌 이번 한 달간, 내가 얻은 것들처음엔 next.js와 tailwind를 조금만 다룰 줄 알았고 전역 상태 관리도 zustand 정도만 써봤었다.하지만 이번 강의를 통해→ next.js의 프로젝트 구조 잡는 방식→ tailwind를 더 효율적으로 사용하는 법→ 그리고 새롭게 배운 recoil, supabase, server actions, vercel 배포까지!정말 다양한 기술들을 직접 써보면서 익힐 수 있었다. 🙃 좋았던 순간, 힘들었던 순간강사님 코드랑 똑같이 썼는데도 에러가 나서 괜히 억울했던 순간,반대로 내가 직접 구현한 기능이 잘 작동해서 뿌듯했던 순간도 있었다.물론 한 번 배웠다고 해서 금방 능숙하게 다루진 못하지만이 강의를 통해 전반적인 흐름을 훑을 수 있었고이제는 Supabase를 활용해 어떤 기능을 만들어볼까? 상상해보는 재미도 생겼다. 🎉 마지막으로다음엔 이번 주차에서 만들었던 인스타그램 클론을 좀 더 확장해서게시물 기능까지 구현해보고 싶은 욕심도 있다.좋은 아이디어가 생긴다면? 더 멋있는 기능을 섞어서 구현해보고 싶다...어쨌든, 이번 스터디는 정말 기억에 남는 한 달이었다.한 달 동안 함께 완주해온 스터디 분들 정말 수고 많았고,좋은 강의 만들어주신 강사님께도 진심으로 감사합니다! 🎉
풀스택
・
풀스택
・
미션
・
인프런워밍업클럽
・
supabase
・
next.js
2025. 03. 22.
0
인프런 워밍업 클럽 3기 CS - 3주차 미션
3주차 학습 내용 - 미션자료구조 & 알고리즘 1. 지금까지 배운 5개의 정렬 알고리즘의 장단점과 시간 복잡도를 적어주세요.1 ) 버블정렬특징: 인접한 두 요소를 비교해서 큰 값을 뒤로 보내는 방식시간복잡도: 최선: O(n) / 평균,최악: O(n²)장점: 구현이 아주 간단하고 직관적임단점: 성능이 너무 안 좋음, 실전에서 거의 사용 X 2 ) 선택정렬특징: 가장 작은 값을 찾아서 앞으로 하나씩 정렬해가는 방식시간복잡도: 최선,평균,최악: O(n²)장점: 구현 쉬움, 자리 바꿈(Swap) 횟수가 적음단점: 효율성 낮음, 데이터 크기 커지면 성능 ↓ 3) 삽입정렬특징: 정렬된 부분에 새 값을 '삽입'하는 방식시간복잡도: 최선: O(n) / 평균,최악: O(n²)장점: 거의 정렬된 상태일 땐 빠름, 구현 쉽고 안정 정렬단점: 역순 정렬일 경우 성능 급감 4 ) 병합정렬특징: 분할 → 정렬 → 병합하는 재귀 방식 (Divide & Conquer)**시간복잡도: 항상 O(n log n)장점: 성능 안정적, 정렬 정확도 높음, 안정 정렬단점: 추가 메모리 공간 필요, 구현 복잡 5) 퀵정렬특징: 피벗 기준으로 좌우 나눠 정렬하는 분할 정복 방식시간복잡도: 평균: Θ(n log n) / 최악: O(n²)장점: 평균적으로 가장 빠름, 메모리 추가 거의 없음단점: 피벗 선택이 안 좋으면 성능 O(n²), 구현 어렵고 불안정 2. 메모리가 부족한 시스템에서 어떤 문제를 해결하는데 재귀로 쉽게 구현이 가능할 것 같습니다. 여러분이라면 메모이제이션과 타뷸레이션 중 어떤 걸 이용하실 건가요? 이유를 함께 적어주세요. 나는 무조건 타뷸레이션을 사용할 것 같다.메모리가 부족한 상황이라면 어차피 타뷸레이션이나 메모이제이션이나 메모리를 아껴 써야 하는 조건은 비슷하다고 생각한다.그렇다면 굳이 어려운 재귀를 써야 하는 메모이제이션보다는, 반복문 기반으로 더 직관적인 타뷸레이션이 훨씬 낫다.솔직히 말해서 아직 재귀가 너무 어렵다… 그래서 재귀 없이 풀 수 있는 타뷸레이션 쪽을 더 선호하게 되는 것 같다. 😅 운영체제 1. 메모리의 종류는 어떤것들이 있나요? 각 메모리의 특징도 함께 적어주세요. 1 ) 레지스터CPU 내부에 존재하는 가장 빠른 기억장소연산 중인 데이터나 주소 등을 저장CPU가 직접 접근 → 속도 가장 빠름용량은 매우 작고 휘발성2 ) 캐시CPU와 RAM 사이에 위치하는 고속 메모리CPU가 자주 접근하는 데이터를 미리 저장해서 → 메인 메모리 접근을 줄이고 속도 향상캐시가 없으면 RAM까지 가야 하니까 느려짐휘발성3) 메인메모리(RAM)운영체제(OS)와 실행 중인 프로그램이 올라가는 공간휘발성 메모리 → 전원이 꺼지면 데이터 사라짐가격이 비싸기 때문에, 파일 저장용이 아닌 ‘작업 공간’으로 사용됨HDD/SSD보다 훨씬 빠르지만, 레지스터나 캐시보다는 느림4) 보조저장장치데이터를 영구적으로 저장하기 위한 장치비휘발성 메모리 → 전원을 꺼도 데이터가 유지됨가격이 저렴하고 용량이 큼, 대신 RAM보다 느림HDD자기 디스크를 회전시켜 읽고 쓰는 방식물리적인 회전이 필요해서 느림, 하지만 저렴하고 수명은 길다충격에 약하고, 소음 있음 SSD플래시 메모리 기반의 저장장치회전 없이 빠르게 데이터 처리 가능HDD보다 훨씬 빠름, 충격에 강함, 소음 없음단점은 HDD보다 비싸고 수명(쓰기 횟수 제한)이 있음 2. 사용자 프로세스가 메모리의 운영체제 영역에 침범하지 못하도록 만든 레지스터는 어떤 레지스터일까요?✅ 정답: 경계 레지스터 (Boundary Register)경계 레지스터는 사용자 프로세스가 운영체제의 메모리 영역을 침범하지 못하도록 막아주는 역할을 한다.CPU 내부에 존재하며, 메모리 관리자가 경계 값을 기준으로 프로세스가 허용된 영역을 벗어나는지 실시간으로 검사한다.만약 프로세스가 지정된 경계를 넘어서려고 하면, 바로 프로세스를 강제 종료시켜서 시스템 보호를 수행한다. 3. 메모리 할당 방식에서 가변 분할 방식과 고정 분할 방식의 장단점은 뭔가요?✅ 가변 분할 방식프로세스 크기에 맞춰서 메모리를 유동적으로 나누는 방식필요한 만큼만 메모리를 나눠 쓸 수 있어서 공간 활용은 유리함하지만 계속 할당과 해제를 반복하다 보면 여기저기 쪼개진 빈 공간들이 생기며, 이걸 외부 단편화라고 하고, 빈 공간이 충분해 보여도 실제로는 새로운 프로세스를 넣기 힘든 상황이 생길 수 있음 ✅ 고정 분할 방식미리 정해진 크기로 메모리를 쪼개놓고, 거기에 프로세스를 할당하는 방식구조가 단순해서 구현이 쉽고 오버헤드도 적음근데 프로세스 크기랑 딱 안 맞는 경우가 많아서, 작은 프로세스가 큰 메모리 블록을 차지해 공간이 낭비되는 내부 단편화 발생 4. CPU 사용률을 올리기 위해 멀티프로그래밍을 올렸지만 스왑이 더 많이 이루어져 CPU 사용률이 0%에 가까워 지는 것을 뭐라고 할까요?✅ 정답: 스레싱멀티프로그래밍 수준을 높여서 CPU 사용률을 끌어올리려 했는데, 오히려 프로세스들이 메모리를 서로 차지하려고 계속 페이지 교체(스왑)만 일어나게 된다.결국 CPU는 계속 대기만 하게 되고 실제 작업은 거의 하지 못하는 상태가 된다.이런 상황을 스레싱(thrashing)이라고 부른다. 5. HDD나 SSD는 컴퓨터를 실행시키는데 꼭 필요한 걸까요?이유를 함께 적어주세요.조명처럼 켜두거나 그냥 전시용 벽돌로 둘 거라면 없어도 상관없다.하지만 컴퓨터를 제대로 사용하려면 반드시 필요하다.운영체제(OS), 프로그램, 각종 파일들이 저장되는 공간이 바로 HDD나 SSD이기 때문이다.이 저장장치가 없다면 운영체제를 로딩할 수 없고, 프로그램도 실행할 수 없다.결국 컴퓨터는 켜질 수는 있지만 아무것도 하지 못하는 상태가 된다. 6. 파일을 삭제해도 포렌식으로 파일을 복구할 수 있는 이유가 무엇일까요?파일을 삭제해도 실제 데이터는 바로 없어지지 않기 때문파일 시스템은 빈 저장 공간을 관리하기 위해 free block list를 사용한다. 이 리스트는 사용 가능한 블록들을 모아놓은 일종의 기록표다.파일을 삭제하면 파일 시스템은 파일의 데이터 전체를 지우지 않고, 파일의 헤더 정보(위치 정보)만 지운다. 그리고 그 파일이 있던 위치를 free block list에 추가한다.결과적으로 사용자 입장에서는 파일이 사라진 것처럼 보이지만, 실제로는 하드디스크 어딘가에 데이터가 남아 있는 상태다.
알고리즘 · 자료구조
・
자료구조
・
알고리즘
・
운영체제
・
미션
・
인프런워밍업클럽
・
CS
2025. 03. 20.
0
인프런 워밍업 클럽 3기 풀스택 - 3주차 발자국
3주차 학습 내용Part 1. Git Repository 생성 및 초기 설정 진행이전과 동일하게 npx create-next-app@14 inflearn-supabase-netflix-clone 해주고, 2주차의 코드를 가져왔다.테이블의 column을 지정해주고, 강사님께서 가져오신 영화 데이터를 받아 DB를 구성했다. Part 2. UI 작업이번에는 다이나믹 라우트를 사용해서 포스터를 클릭하면 해당 포스터의 id를 들고 상세페이지로 이동한다. 사용법은 간단하게 대괄호를 열고 닫은 폴더명을 사용하면 됨.그거 말고는 전체적으로 예제와 같게 UI작업을 했고, 이전 드롭박스때 처럼 grid로 간단하게 반응형을 구현해줌. Part 3. 영화 검색 기능 & 영화 개별 상세페이지 구현🌀 Recoil 사용 방법✅ 1. 설치먼저 Recoil을 설치한다: npm install recoil✅ 2. 서버 컴포넌트(layout.tsx)에 직접 쓰면 ❌Recoil은 클라이언트 사이드 전용 라이브러리이기 때문에layout.tsx에서 바로 사용하면 에러가 발생한다.✅ 3. RecoilProvider 따로 만들어 감싸기config/RecoilProvider.tsx 파일을 만들고, 아래와 같이 구성한다// config/RecoilProvider.tsx "use client"; import { RecoilRoot } from "recoil"; export default function RecoilProvider({ children }: React.PropsWithChildren) { return {children}; } ✅ 4. 전역 상태 정의 (atoms.ts)utils/recoil/atoms.ts에 전역 상태를 선언한다:// utils/recoil/atoms.ts import { atom } from "recoil"; export const searchState = atom({ key: "searchState", default: "", }); ✅ 5. 컴포넌트에서 사용하기import { useRecoilState } from "recoil"; import { searchState } from "utils/recoil/atoms"; const [search, setSearch] = useRecoilState(searchState); Part 4. 무한 스크롤 기능 구현하기 & 더 나은 검색을 위한 SEO 작업하기 핵심 포인트react-query의 useInfiniteQuery 사용react-intersection-observer로 마지막 요소 감지해서 추가 데이터 불러오기🔧 구현 흐름useInfiniteQuery에서 pageParam으로 현재 페이지 관리searchMovies()를 호출해서 검색어와 페이지 정보를 넘김getNextPageParam으로 다음 페이지 조건 처리마지막 아이템에 ref 붙여서 화면에 보이면 자동 로딩 "use client"; import { useInfiniteQuery } from "@tanstack/react-query"; import MovieCard from "./movie-card"; import { searchMovies } from "actions/movieActions"; import { Spinner } from "@material-tailwind/react"; import { useRecoilValue } from "recoil"; import { searchState } from "utils/recoil/atoms"; import { useInView } from "react-intersection-observer"; import { useEffect } from "react"; export default function MovieCardList() { const search = useRecoilValue(searchState); const { data, isFetching, isFetchingNextPage, fetchNextPage, hasNextPage } = useInfiniteQuery({ initialPageParam: 1, queryKey: ["movie", search], queryFn: ({ pageParam }) => searchMovies({ search, page: pageParam, pageSize: 12 }), getNextPageParam: (lastPage) => lastPage.page ? lastPage.page + 1 : null, }); const { ref, inView } = useInView({ threshold: 0, }); useEffect(() => { if (inView && hasNextPage && !isFetching && !isFetchingNextPage) { fetchNextPage(); } }, [inView, hasNextPage]); useEffect(() => { console.log(inView); }, [inView]); return ( {isFetching || (isFetchingNextPage && )} {data?.pages ?.map((page) => page.data) ?.flat() ?.map((movie) => ( ))} ); } 🔧 구현 흐름Next.js의 generateMetadata()를 사용해서페이지별로 동적으로 메타 태그 생성. 💡 포인트페이지 타이틀에 영화 제목 자동 반영설명은 영화 overview에서 가져옴OG 이미지도 함께 등록해서 링크 공유 시 썸네일 출력됨export async function generateMetadata({ params, searchParams }) { const movie = await getMovie(params.id); return { title: movie.title, description: movie.overview, openGraph: { images: [movie.image_url], }, }; } 미션: 북마크 기능 만들기미션: 찜하기 기능을 만들어서, 찜한 영화를 영화 리스트 화면의 최상단에 보여주기원래는 영화 리스트 화면에서 북마크한 영화를 최상단에 보여주는 미션이었지만,실제 사용자 입장에서 불편할 것 같아서 헤더에 "bookmark" 메뉴를 따로 만들고해당 페이지에서 북마크한 영화만 모아보는 방식으로 약간 변형해서 구현했습니다. 1. Supabase 테이블에 bookmark 추가해주기Supabase의 movie 테이블에 bookmark라는 boolean 컬럼을 추가하고,기본값을 false로 설정하기 위해 SQL Editer에서 UPDATE movie SET bookmark = false WHERE bookmark IS NULL;를 입력해줌 2. 북마크 토글 함수 생성// actions/movieActions.ts export async function toggleBookmark(id: number, current: boolean) { const supabase = await createServerSupabaseClient(); const { error } = await supabase .from("movie") .update({ bookmark: !current }) // 현재 값 반대로 토글 .eq("id", id); // 해당 ID만 업데이트 handleError(error); } movieActions에서 북마크 토글을 지원하는 함수를 만들어줌. 3. 상세 페이지에서 북마크 버튼 만들기// app/movies/[id]/ui.tsx "use client"; import { toggleBookmark } from "actions/movieActions"; import { useState, useTransition } from "react"; import { BookmarkIcon } from "@heroicons/react/24/outline"; import { BookmarkIcon as BookmarkSolidIcon } from "@heroicons/react/24/solid"; export default function MovieDetail({ movie }) { const [bookmarked, setBookmarked] = useState(movie.bookmark); const [isPending, startTransition] = useTransition(); const handleClick = () => { setBookmarked((prev) => !prev); // UI 먼저 변경 startTransition(async () => { await toggleBookmark(movie.id, bookmarked); // 서버에 실제 반영 }); }; return ( {movie.title} {bookmarked ? ( ) : ( )} ); } npm install @heroicons/react을 설치해서 토글 아이콘을 생성함.2번에서 만든 함수를 연결해서 북마크를 키고 끄면 DB에도 연동되게 만들었음. 4. 북마크한 영화만 보여주는 페이지 만들기// actions/movieActions.ts export async function getBookmarkedMovies() { const supabase = await createServerSupabaseClient(); const { data, error } = await supabase .from("movie") .select("*") .eq("bookmark", true) // bookmark가 true인 영화만 가져옴 .order("id", { ascending: true }); // id 순으로 정렬 handleError(error); return data; }movieActions에서 북마크한 영화만 보여주는 함수를 만들어줌. // app/movies/bookmark/page.tsx import MovieCard from "@/components/movie-card"; import { getBookmarkedMovies } from "actions/movieActions"; export default async function BookmarkPage() { const movies = await getBookmarkedMovies(); return ( {movies.map((movie) => ( ))} ); }header에서 북마크를 클릭하면 북마크 페이지로 이동하게 만들었고위에서 만든 북마크 영화 함수를 사용해서 북마크한 영화만 보여주도록 만들었음. 아쉬운 부분무한스크롤이 아직 조금 어려워서 북마크 페이지에서는 아직 구현해지 못했다.추후에 좀 더 공부해보고 넣어주면 좋을 것 같다!회고이번 주차 수업 중에서는 무한 스크롤이 가장 어려웠지만,과제는 이전 주차처럼 단순히 '딸깍하면 되는 문제'가 아니어서"어떻게 구현할까?" 부터 고민하는 재미가 있었다.Supabase에서 테이블을 직접 작성하고,서버 액션에서 원하는 기능을 하는 함수를 만들고,그 함수를 페이지에 붙여서내가 의도한 대로 동작하는 걸 확인했을 때 정말 재밌었다.뭔가 시간이 지나면서 점점 supabase와 친해지는 느낌을 받았다.엄청 어렵지는 않지만,약간만 생각하면 풀리는 적당한 난이도라서 더 좋았던 과제였다.
풀스택
・
풀스택
・
미션
・
인프런워밍업클럽
・
supabase
・
next.js
2025. 03. 17.
0
인프런 워밍업 클럽 3기 CS - 3주차 발자국
3주차 학습 내용 - 발자국자료구조 & 알고리즘 삽입정렬function InsertionSort(arr) { for (let i = 1; i = 0; j--) { if (arr[j] > cnt) { arr[j + 1] = arr[j]; } else { break; } } arr[j + 1] = cnt; } return arr; } console.log(InsertionSort([4, 1, 5, 3, 6, 2])); 시간복잡도: O(N²)이해와 구현이 간단하고 직관적,하지만 성능은 좋지 않아서 작은 데이터나 거의 정렬된 데이터에 적합병합정렬function MergeSort(arr, leftIndex, rightIndex) { if (leftIndex 시간복잡도: O(n log n)재귀 기반 정렬이라 이해와 구현은 조금 어렵지만, 성능은 안정적이고 좋다. 퀵정렬function quickSort(arr, left, right) { if (left = left + 1 && arr[rightStartIndex] >= pivot) { rightStartIndex--; } if (leftStartIndex 시간복잡도: 평균적으로 Θ(n log n)재귀 기반 정렬이라 이해와 구현은 어렵게 느껴질 수 있지만, 실제로는 굉장히 빠르고 효율적인 정렬 알고리즘이다. 메모이제이션function fibonacci2(n, memo) { if (n == 0 || n == 1) return n; // ✅ 기본 조건(Base Case) if (memo[n] == null) { // ✅ 이전에 계산된 값이 없으면 계산 memo[n] = fibonacci2(n - 2, memo) + fibonacci2(n - 1, memo); } return memo[n]; // ✅ 저장된 값이 있으면 재사용 } console.log(fibonacci2(5, {})); // ✅ 초기 memo 객체를 전달한 번 계산한 값을 저장해두고, 같은 계산이 필요할 때는 다시 계산하지 않고 저장된 값을 재사용하는 기법중복 계산을 줄여 알고리즘 속도를 최적화 함.예제에서는 피보니치를 재귀로 구현하고 있음, 하지만 일반 재귀로는 불필요한 중복계산이 많아 효율이 좋지 않음.그래서 n의 값에 따라 그 값을 기억하는 memo를 만들어서 n이 실행될때 이전에 저장한게 있으면 바로 값 대입함. 타뷸레이션function fibonacci3(n) { if (n 타뷸레이션은 하향식인 재귀 방식이 아니라, 상향식으로 배열을 채워나가는 방식이다.아무래도 재귀보다 코드가 직관적이고, 이해하기 쉽다. 타뷸레이션은 재귀 없이도 효율적인 풀이가 가능한 방식이라, 초보자에게 훨씬 부담이 적고 실전에서도 유용하다고 느꼈다. 운영체제 가상 메모리운영체제가 물리적 메모리(RAM)가 부족할 때, 하드디스크(또는 SSD)를 이용하여 추가적인 메모리를 제공하는 기술RAM이 부족하면 일부 데이터를 디스크(하드디스크, SSD)에 저장했다가 필요할 때 다시 불러오는 방식페이지 폴트: 프로그램이 필요한 데이터를 RAM에서 찾지 못할 때 발생하는 현상 -> 운영체제가 디스크에서 해당 데이터를 RAM으로 불러오는 작업을 수행스왑 영역: 물리 RAM이 부족할 때, 디스크의 일부를 메모리처럼 사용하는 영역 세그멘테이션프로그램을 논리적인 단위(세그먼트)로 나누어 메모리를 할당하는 방식동작 방식프로그램이 메모리를 요청하면 운영체제는 세그먼트 번호를 할당함.세그먼트 테이블을 참고하여, 해당 세그먼트의 시작 주소를 찾음.세그먼트 시작 주소 + 오프셋(offset)을 더하여 실제 메모리 주소를 계산함.장점: 내부 단편화 X, 메모리를 논리적 단위로 관리 가능단점: 외부 단편화O페이징메모리를 "고정된 크기(페이지 단위)"로 나누어 관리하는 메모리 할당 기법프로세스를 작은 단위(페이지)로 나누어 메모리에 배치동작 방식프로그램이 실행되면, 프로세스를 동일한 크기의 페이지로 나눔.메모리도 같은 크기의 프레임으로 나누고, 각 페이지를 빈 프레임에 적재.CPU가 메모리에 접근할 때, 페이지 테이블을 이용하여 페이지 번호 → 프레임 번호로 변환.장점: 외부 단편화 없음, 메모리를 효율적으로 사용 가능단점: 내부 단편화 발생, 페이지 테이블을 계속 참조해야 해서 오버헤드 존재 세그멘테이션 vs 페이징둘 중에 뭐가 더 좋다, 이렇게 단정 짓긴 어려움. 결국 사용 목적과 상황에 따라 선택하면 됨.세그멘테이션프로그램이 서로 다른 크기의 논리적 블록(세그먼트)으로 나뉘어 있을 때 유리함함수, 배열, 변수 등 논리 단위로 나뉘는 구조에 적합유연하게 메모리를 할당하고 싶을 때 사용하기 좋음페이징메모리를 고정된 크기(페이지 단위)로 균등하게 나눔운영체제에서 일괄적으로 메모리를 관리하고 싶을 때 적합외부 단편화가 더 신경 쓰이는 경우 페이징이 더 효과적임ㅍ페이지 세그멘테이션세그멘테이션 + 페이징의 장점을 섞은 방식세그먼트마다 다시 페이지 단위로 쪼갬논리적으로는 세그먼트로 구분하고, 물리적으로는 페이지처럼 관리함단점도 줄이고, 장점도 살리는 구조 디맨드 페이징실제로 필요한 페이지만 메모리에 올리는 방식프로그램 실행 시, 전체를 메모리에 올리지 않고 조만간 필요할 것 같은 페이지만 로딩나머지 페이지는 스왑 영역(보조 기억장치)에 남겨둠실제 사용될 때만 메모리에 적재 → 효율적인 메모리 사용 지역성 이론프로그램이 실행될 때 특정 메모리 영역에 집중적으로 접근하는 성질을 지역성이라고 한다. 공간의 지역성: 현재 위치와 가까운 데이터에 접근할 확률이 높음ex) 배열이나 함수 코드처럼 서로 인접한 메모리 위치를 차례로 접근하는 경우이 특성을 기반으로, 근처 데이터까지 한 번에 메모리에 올려두고, 필요 없어 보이는 데이터는 스왑 영역으로 보내서 성능을 높이는 방식이 사용됨 시간의 지역성: 최근 접근했던 데이터가 오래 전에 접근했던 데이터보다 접근할 확률이 높음ex) 방금 쓴 변수나 반복문에서 쓰인 코드들이 다시 사용되는 경우이 특성을 활용해서, 캐시나 페이지 교체 알고리즘에서 최근 사용 여부를 판단하는 데 쓰임 페이지 교체 정책프로세스가 어떤 데이터를 사용하려고 할 때, 그 데이터가 메모리에 없다면 스왑 영역(디스크)에서 가져와야 한다.근데 메모리 공간이 꽉 차 있다면, 기존에 있던 데이터를 하나 꺼내고, 새 데이터를 그 자리에 넣어야 함.이때 어떤 데이터를 꺼낼지 정하는 기준이 바로 페이지 교체 정책이다.1. 무작위로 선택하는 방법지역성을 전혀 고려하지 않기 때문에, 자주 쓰는 데이터가 교체될 수 있어서 성능이 안 좋음하지만 구현은 제일 간단함2. 메모리에서 가장 오래된 페이지를 선택하는 방법(FIFO)자주 쓰는 페이지라도 먼저 들어왔다는 이유로 교체될 수 있음단점은 있지만, 구현이 쉬워서 변형을 거쳐 실제로 많이 사용됨3. 앞으로 가장 오랫동안 쓰이지 않을 페이지를 선택하는 방법(Optimum)이론적으로 가장 완벽한 방식이지만,미래를 예측할 수 없기 때문에 실제 구현은 불가능함다른 알고리즘과 성능 비교할 때 기준점으로 사용함4. 최근에 가장 사용이 적은 페이지를 선택하는 방법(LRU)최근에 사용된 데이터를 우선적으로 보존하는 방식이라 지역성에 잘 맞음단점은, 언제 사용됐는지를 추적하기 위해 시간 정보나 카운터, 비트 등이 필요함 → 구현이 복잡하고 성능 부담이 생길 수 있음시간이 지나면 오버플로우 문제도 발생 가능5. Clock AlgorithmLRU의 단점을 보완한 방식각 페이지에 참조 비트를 붙이고,일정 시간마다 비트를 확인하며 시계 방향으로 스캔참조되지 않은 페이지를 교체하고, 참조된 페이지는 기회를 한 번 더 줌구조는 단순하고 성능도 괜찮아서 실제 운영체제에서 자주 사용됨 6. 2차 기회 페이지 교체 알고리즘FIFO의 단점을 개선한 방식FIFO는 자주 쓰는 페이지라도 먼저 들어왔으면 교체됨 → 이걸 해결함페이지가 교체 대상이 되었는데 최근 사용된 페이지라면, 그 페이지를 맨 뒤로 보내고 한 번 더 기회를 주는 방식간단하면서도 성능이 괜찮은 알고리즘 스레싱프로세스들이 계속 스왑만 하느라 정작 일은 못 하는 상태멀티프로그래밍 수준을 너무 높이면, 한정된 메모리를 너무 많은 프로세스가 나눠 쓰게 된다.이때 필요한 페이지가 자꾸 메모리에 없어서, 운영체제는 디스크와 메모리 사이에서 페이지를 계속 교체(스왑) 하게 된다.결과적으로 CPU는 일은 안 하고, I/O 대기만 계속하면서 놀게 된다.주변 장치그래픽 카드, HDD, SDD, 키보드, 마우스 등 컴퓨터 외부와 연결되는 장치들을 말함.캐릭터 디바이스마우스, 키보드, 사운드카드 등데이터 전송 단위가 '문자 단위(캐릭터)'로 상대적인 크기가 작다블록 디바이스HDD, SSD, 그래픽카드 등데이터 전송 단위가 '블록 단위(범위)'로 상대적인 크기가 크다입출력 제어기예전에는 주변 장치를 CPU가 직접 관리했기 때문에, I/O 명령을 만나면 CPU가 멈춰버리고 입출력이 끝날 때까지 기다려야 했음 → 비효율적이걸 보완하기 위해 입출력 제어기가 생김.이제는 I/O 명령을 만나면, 제어기가 입출력 작업을 대신 맡고, CPU는 다른 작업을 계속 실행할 수 있게 됨 → CPU 사용률이 올라감 3주차 회고벌써 3주차가 되어버렸다..이번 주는 뭔가 유독 어렵게 느껴졌다.아무래도 점점 이전 강의 위에 지식이 쌓여가다 보니, 강의를 봐도 이해가 잘 안 되는 순간들이 많았다.그래서 같은 영상을 계속 반복해서 보면서 겨우겨우 따라갔던 것 같다.특히 재귀는 진짜 어렵다.자주 보려고는 하지만, 어렵다 보니 손이 잘 안 간다… 하하(타뷸레이션 짱😀)3주 전, 아무것도 모르던 나는 그냥 "CS 한 번 배워보자!"는 마음으로 신청했었다.그런데 막상 3주 동안 공부하면서 내가 몰랐던 걸 많이 알게 됐고,동시에 더 꾸준히 공부해야겠다는 자극도 받았다.코드를 직접 치고, 프레임워크나 기술을 익히는 것도 물론 중요하지만,이런 이론적인 부분(CS)도 기초 체력을 길러주는 느낌이라 꼭 필요하다고 생각하게 됐다.아마 완주 포인트를 받으면… 감자님의 알고리즘 상버전을 결제하러 가지 않을까 싶다 😎이 강의를 듣고 싶거나, 워밍업 클럽에 참여할까 고민 중이라면 망설이지 말고 그냥 해보는 걸 추천한다.나는 CS 강의는 처음이라 다른 강의랑 비교할 순 없지만,지금까지는 충분히 만족이다.그리고 솔직히 말해서, 워밍업 클럽이 아니었다면 3주 동안 완강 못 했을 거다.혼자였다면 진작에 놓았을지도… 마지막으로 우리 모두 파이팅! 🔥🔥
자료구조
・
알고리즘
・
운영체제
・
인프런워밍업클럽
・
CS
2025. 03. 15.
0
인프런 워밍업 클럽 3기 풀스택 - 2주차 발자국
2주차 학습 내용Part 1 - Git Repository 생성 및 초기 설정 진행create-next-app을 통해 초기 세팅을 했으며,이전에 TODO에서 했던 코드들을 일부 가져와서 빠르게 세팅함. Part 2 - UI 작업알게된 사실 - page.tsx에는 클라이언트 컴포넌트를 사용하면 좋지않다.그 이유는 나중에 메타데이터를 쓰고 하는데 그건 서버 컴포넌트에서만 돌아가기 때문에 피해줘야 한다.나는 평소 flex만 사용하고 grid는 잘 사용하지 않는다. 항상 쓰던것만 써서 그렇기도 하고 grid로 편하게 구현하는 것도 flex로 구현은 가능하기 때문에 그렇게 했다. 강의에서는 grid를 사용했고 디테일하진 않지만 간단하게 3단계로 반응형도 쉽게 구현되는 모습을 보고 grid를 다시보게 됨className="grid md:grid-cols-3 lg:grid-cols-4 grid-cols-2"그 이후로는 컴포넌트 별로 분리해서 퍼블리싱 작업을 구현했다. Part 3 - 파일 업로드 구현(Supabase Storage) 사진을 업로드 하는데 알 수 없는 에러가 있었고, 분명 코드도 다른부분이 없는데 문제가 생겨서 오랫동안 붙잡고 있었다.원인은 사진이름이 한글로된 경우 안되는 부분이였고, 잠시 오류 수정으로 고쳐서 한글이름으로 된 사진도 업로드가 가능하게 했다. 하지만 한글이름이 아닌 a__a__a같은 이름으로 저장되는 문제가 발생해서 이 문제는 추후 고쳐봐야 할 문제 같다.// actions/storageActions.ts function sanitizeFileName(fileName: string) { return fileName .normalize("NFKD") // 유니코드 정규화 .replace(/[^\w.-]/g, "_") // 특수 문자 제거 .replace(/\s+/g, "_") // 공백을 `_`로 변경 .toLowerCase(); // 소문자로 변환 } export async function uploadFile(formData: FormData) { const supabase = await createServerSupabaseClient(); const file = formData.get("file") as File | null; if (!file) { console.error("❌ 업로드할 파일이 없습니다."); throw new Error("파일이 없습니다."); } // 파일 이름을 안전한 형식으로 변환 const safeFileName = sanitizeFileName(file.name); console.log("✅ 변환된 파일 이름:", safeFileName); const { data, error } = await supabase.storage .from(process.env.NEXT_PUBLIC_STORAGE_BUCKET!) .upload(safeFileName, file, { upsert: true }); if (error) { console.error("❌ Supabase 업로드 실패:", error.message); throw new Error(error.message); } return data; } Part 4 - 파일제거 구현, Darg & Drop, 멀티파일 업로드 구현Darg & Drop을 위해 설치해줌. npm i --save react-dropzone이번주 미션 - 파일의 마지막 수정(업로드) 시간을 표시하는 기능을 추가하기!// components/dropbox-image.tsx 생성일: {formatDate(image.updated_at)} 간단하게 이 부분 넣어서 해결함. 미션 이외로...- 강사님과 같은 코드로 하니까 생긴 에러가 있어서 코드를 약간 수정함.수정한 부분은 actions/storageActions.ts 의 uploadFile 부분임1⃣ 파일 필터링 (undefined 값 제거)✅ 첫 번째 코드 (위 코드) → undefined 또는 잘못된 파일 제거const files = Array.from(formData.entries()) .map(([name, file]) => file as File) .filter((file) => file instanceof File && file.name); // ✅ undefined 제거 filter()를 사용하여 undefined 또는 비정상적인 파일을 제거파일이 null이거나 undefined면 upload()에서 에러 발생 가능성이 있음 → 이를 방지❌ 두 번째 코드 (아래 코드) → 필터링 없음const files = Array.from(formData.entries()).map(([name, file]) => file as File); undefined 파일이 포함될 가능성이 있음 → 업로드 시 오류 발생 가능 2⃣ 파일명 변환 (sanitizeFileName)✅ 첫 번째 코드 (위 코드) → 파일명 변환 추가function sanitizeFileName(fileName: string) { return fileName .normalize("NFC") // ✅ 한글 깨짐 방지 .replace(/[^a-zA-Z0-9ㄱ-ㅎㅏ-ㅣ가-힣_.-]/g, "_"); // ✅ 특수 문자 제거 } const safeFileName = sanitizeFileName(file.name); 특수 문자, 공백 제거 (file.name을 정리)한글 깨짐 방지 (NFC 정규화)→ Supabase는 일부 특수 문자나 공백이 포함된 파일명을 허용하지 않으므로 안정적❌ 두 번째 코드 (아래 코드) → 원본 파일명 그대로 사용supabase.storage .from(process.env.NEXT_PUBLIC_STORAGE_BUCKET) .upload(file.name, file, { upsert: true }); 파일명을 그대로 사용하기 때문에, 특수 문자나 공백이 포함되면 Supabase에서 오류 발생 가능 3⃣ async 처리 및 오류 핸들링✅ 첫 번째 코드 (위 코드) → async 사용 및 오류 처리const results = await Promise.all( files.map(async (file) => { // ✅ async 사용 const safeFileName = sanitizeFileName(file.name); const { data, error } = await supabase.storage .from(process.env.NEXT_PUBLIC_STORAGE_BUCKET) .upload(safeFileName, file, { upsert: true }); if (error) { // ✅ 오류 처리 console.error("❌ Supabase 업로드 실패:", error.message); throw new Error(error.message); } return data; }) ); 각 파일 업로드가 비동기(async)로 처리됨오류 발생 시 console.error로 출력하고 예외 처리각 파일 업로드 후 결과(data) 반환❌ 두 번째 코드 (아래 코드) → 오류 핸들링 없음const results = await Promise.all( files.map((file) => supabase.storage .from(process.env.NEXT_PUBLIC_STORAGE_BUCKET) .upload(file.name, file, { upsert: true }) ) ); async 키워드 없이 바로 upload() 실행오류가 발생해도 catch되지 않으며, 전체 업로드가 실패할 가능성이 있음업로드 성공 여부를 확인할 방법 없음 (data를 반환하지 않음) 2주차 회고 2주차에는 중간점검을 하는 시간을 가졌다. 수강생들이 하고 싶었던 질문을 하나하나 답변해주시는 시간을 가져서 꽤 유용한 시간이였고, 더 열심히 하자는 마음을 다지는 계기가 되었다.첫주때보단 수퍼베이스에 적응을 하는거같다. 아직 친해지기에는 시간이 더 많이 필요할꺼 같긴한데 정처기 준비하고 CS 스터디 하고, 다른 프젝도 마무리 하고, 매일 알고리즘 문제도 풀고 있다보니 시간이 많이 부족한 것 같다.중간점검때 강사님께서 시간관리에 대한 얘기도 했었는데, 매우 동감하는 부분...시간 관리나 스케줄 관리를 잘 해야 할 것 같다.. 의욕만 앞서서 살짝 망하는거 같기도함.그래도 뭐 흥미있고 재미있으니까 만족한다.
풀스택
・
풀스택
・
미션
・
인프런워밍업클럽
・
supabase
・
next.js
2025. 03. 10.
0
인프런 워밍업 클럽 3기 CS - 2주차 미션
2주차 학습 내용 - 미션자료구조 & 알고리즘 1. 재귀함수에서 기저조건을 만들지 않거나 잘못 설정했을 때 어떤 문제가 발생할 수 있나요?기저조건을 만들지 않으면 함수가 계속 실행되서 콜스택이 메모리에 쌓이게 되고, 각자의 메모리 용량에 따라 다르겠지만 메모리끝에 다다르게 되면 실행이 종료된다. 그것을 스택 오버플로우 오류라고 한다. 2. 0부터 입력 n까지 홀수의 합을 더하는 재귀 함수를 만들어보세요.function sumOdd(n) { if (n % 2 !== 0) { // 홀수가 되는 경우 return n + sumOdd(n - 1); } else if (n === 0) { // 종료가 되는 경우 return 0; } else { // 짝수가 되는 경우 return sumOdd(n - 1); } } console.log(sumOdd(10)); // 25이 방법이 100점짜리 정답인지는 모르겠지만 우선 sumOdd 값에 다른 수를 넣어도 홀수의 합만 뽑아서 더하고 있다.로직은 3가지의 조건으로 나뉘고 있다.n이 홀수인경우 n을 더하고 n-1한 sumOdd 함수를 재호출n이 0인경우 0을 리턴하며 종료n이 짝수인 경우 n을 더하지는 않고 n-1한 sumOdd 함수를 재호출이로써 sumOdd(10)을 할 경우 25(1+3+5+7+9)라는 값이 나오게 됨. 3. 다음 코드는 매개변수로 주어진 파일 경로(.는 현재 디렉토리)에 있는 하위 모든 파일과 디렉토리를 출력하는 코드입니다. 다음 코드를 재귀 함수를 이용하는 코드로 변경해보세요.const fs = require("fs"); // 파일을 이용하는 모듈 const path = require("path"); // 폴더와 파일의 경로를 지정해주는 모듈 function traverseDirectoryRecursive(directory) { const files = readdirSync(directory); // 현재 디렉토리의 파일 및 폴더 가져오기 for (const file of files) { const filePath = join(directory, file); const fileStatus = statSync(filePath); if (fileStatus.isDirectory()) { console.log("디렉토리:", filePath); traverseDirectoryRecursive(filePath); // 🔥 폴더라면 재귀 호출 (스택 역할) } else { console.log("파일:", filePath); } } } traverseDirectoryRecursive(".")이 문제의 경우 솔직히 너무 힘들었음..... (나한텐 어려워😐)gpt.. 의 힘을 빌려 성공하긴 했지만 이 코드를 봐도 이해하기 힘들어서 재귀가 눈에 익게 자주 문제를 풀어보고 생각해야할 것 같다. ✅ 재귀 함수 정의function traverseDirectoryRecursive(directory) { const files = readdirSync(directory); // 현재 디렉토리의 파일 및 폴더 목록 가져오기 traverseDirectoryRecursive(directory):directory를 입력받아 해당 폴더 내의 파일과 폴더를 탐색하는 함수readdirSync(directory):해당 디렉토리 안에 있는 파일/폴더 목록을 배열로 반환✅ for문을 사용하여 모든 파일 및 폴더를 탐색 for (const file of files) { const filePath = join(directory, file); // 전체 경로 생성 const fileStatus = statSync(filePath); // 파일 정보 가져오기 for (const file of files):files 배열 안의 파일 또는 폴더를 하나씩 순회join(directory, file):현재 디렉토리 경로 + 파일 이름을 합쳐서 파일의 전체 경로 생성statSync(filePath):해당 경로가 파일인지 폴더인지 확인할 수 있는 정보 가져오기✅ 폴더인 경우 재귀 호출 if (fileStatus.isDirectory()) { console.log("디렉토리:", filePath); traverseDirectoryRecursive(filePath); // 🔁 재귀 호출하여 하위 폴더 탐색 } else { console.log("파일:", filePath); } } ✔ 폴더인 경우 (fileStatus.isDirectory())"디렉토리: [폴더 경로]"를 출력재귀적으로(traverseDirectoryRecursive(filePath)) 다시 탐색 → DFS(깊이 우선 탐색) 방식✔ 파일인 경우"파일: [파일 경로]"를 출력하고 다음 파일로 넘어감✅ 함수 실행 (탐색 시작)traverseDirectoryRecursive("."); // 현재 디렉토리부터 탐색 시작 "."는 현재 실행 중인 디렉토리를 의미현재 디렉토리부터 재귀적으로 모든 파일과 폴더를 탐색운영체제 1. FIFO 스케줄링의 장단점이 뭔가요?FIFO 스케줄링의 로직은 큐에 들어온 순서대로 CPU를 할당받는 방식이다.장점으로는 단순하고 직관적이라는 점단점으로는 한 프로세스가 완전히 끝나야 다음 프로세스를 실행하기 때문에 앞의 프로세스에서 시간이 지연될수록 뒤에 있는 프로세스는 너무 지연되기 때문에 효율성을 따지면 문제가 생김.2. SJF를 사용하기 여러운 이유가 뭔가요?SJF는 Burst Time이 짧은 순서대로 실행하는 로직이다.이론적으로 생각하면 짧은 순서대로 치기때문에 크게 지연되서 생길 문제도 줄어들긴 하지만,2가지 문제점이 발생하게 된다.첫째는 어떤 프로세스가 얼마나 실행될지 알 수 없다는 점.둘째는 Burst Time이 긴 프로세스는 오랜시간동안 실행되지 않을 수 있다는 점.결과적으로 이런 문제때문에 SFJ 알고리즘은 사용되지 않는다. 3. RR 스케줄링에서 타임 슬라이스가 아주 작으면 어떤 문제가 발생할까요?RR 스케줄링은 모든 프로세스에게 공평하게 CPU 시간을 할당해주는 방식으로 돌아가는 로직이다.RR프로세스의 단점중 타임 슬라이스를 너무 짧게 부여하게 되면, 다른 프로세스로 전환하는 과정인 컨텍스트 스위칭이 자주 일어나게 되어 불필요한 처리가 늘어난다는 것이다. 그래서 너무 길지도 짧지도 않은 적정선을 찾아서 지정해줘야 한다. 4. 운영체제가 MLFQ에서 CPU Bound Process와 I/O Bound Process를 어떻게 구분할까요?현대 운영체제에서 가장 일반적으로 쓰이는 방식.CPU Bound Process 와 I/O Bound Process에게 자신에게 맞는 타임 슬라이스를 부여해야하기 때문에 구분을 해야한다.구분하는 방법은 CPU를 사용하는 프로세스가 실행하다가 스스로 CPU를 반납하면 CPU 사용이 적은 것이기 때문 에 I/O 바운드라고 예상할 수 있고, 프로세스가 타임 슬라이스 크기를 오버해서 CPU에게 강제로 뺏기면 CPU 바운드라고 예상 할 수 있다. 5. 공유자원이란무엇인가요?공유자원이란 프로세스 간의 통신을 위해 공동으로 사용하는 변수나 파일, 장치 등을 의미한다. 6. 교착상태에 빠질 수 있는 조건은 어떤 것들을 충족해야할까요?교착상태란 여러 프로세스가 서로 다른 프로세스의 작업이 끝나기를 기다리다가 아무도 작업을 진행하지 못하는 상태이다.교착상태가 발생되는 원인으로는 공유자원을 사용하기 때문이다.교착상태가 발생하기 위해서는 4가지중 하나라도 해당된다면 발생한다.1. 상호배제: A프로세스가 A리소스를 차지한다면, 다른 프로세스에게 공유되면 안된다.2. 비선점: A프로세스가 A리소스를 차지하고 있을때, 프로세스B가 A리소스를 빼앗을 수 없다야 한다.3. 점유와 대기: A프로세스가 리소스A를 차지한 상태에서 리소스B를 원하는 상태여야 한다.4. 원형 대기: 서로가 서로의 리소스를 원하는 경우가 해당하지만 이 4가지 규칙을 지켜도 예방하기란 쉽지 않았고, 결국 교착상태에 빠졌을 경우 해결하는 방법에 대해 연구하게 된다.
알고리즘 · 자료구조
・
자료구조
・
알고리즘
・
운영체제
・
미션
・
인프런워밍업클럽
・
CS