블로그

인프런 워밍업 클럽스터디 3기 FE - 2주차 발자국

자바스크립트[8강]Symbol Type이 타입의 목적은 유니크한 식별자를 만들기 위해서 사용됩니다. Symbol.keyFor()란Symbol.for를 이용해서 전역 심볼을 만들 때(찾을 때)사용하는 description을 얻을 수 있는게 symbol.keyFor()입니다.  Iterator(반복기) & Generator(생성기)iterable : 배열은 반복 가능한 객체이며, 반복이 가능하다는 것을 iterable이라고 부릅니다. for…of를 이용할 수 있거나 [Symbol.iterator]()이 값을 가지면 iterable 한 것입니다.iterator : 반복자는 next()를 호출해서 { value: , done: } 두개의 속성을 가지는 객체를 반환하는 객체입니다.Generator Function는 사용자의 요구에 따라 다른 시간 간격으로 여러 값을 반환할 수 있습니다. 일반 함수 => 단 한 번의 실행으로 함수 끝까지 실행됩니다.제너레이터 함수 => 사용자의 요구에 따라 일시적으로 정지될 수도 있고, 다시 시작될 수도 있습니다.Function* -> 제너레이터 함순느 별표가 붙어야함 [9강]디자인패턴소프트웨어 설계의 주어진 콘텍스트 내에서 일반적으로 발생하는 문제에 대한 일반적이고 재사용 가능한 솔루션입니다.디자인 패턴은 프로그래머가 응용 프로그램이나 시스템을 디자인할 때 일반적인 문제를 해결하는 데 사용할 수 있는 공식화된 모범사례입니다. 장점최고의 솔루션 - 여러번의 수정을 통해 완성되었기에 잘 작동하는것을 알고있어 개발자가 자주 사용함재사용성 - 단일문제에만 존재할 수 없어 여러 문제를 해결하기 위해 특정 상황에서 수정할 수 있는 재사용 가능한 솔루션풍부한 표현련 - 부분적으로 설명할 수 있음향상된 의사 소통 - 문제에 대한 공통 목표를 설정하여 잠재적인 문제와 이러한 문제에 대한 솔루션에 대해 서로 의사 소통하는 데 도움이 됨필요없는 코드 리팩토링 - 종종 다양한 문제에 대한 최적의 솔루션코드베이스 크기 감소 - 공간을 거의 차지하지 않고 몇 줄의 코드로 필요한 솔루션을 구현하여 소중한 공간을 보존Singleton싱글톤 패턴은 클래스의 인스턴스화를 하나의 객체로 제한하는 디자인 패턴입니다. 이는 시스템 전체에서 작업을 조정하는 데 정확히 하나의 객체가 필요한 경우에 유용합니다.고전적으로 싱글톤 패턴은 클래스가 존재하지 않은 경우 클래스의 새 인스턴스를 생성하는 메서드로 클래스를 생성하여 구현할 수 있습니다. 인스턴스가 이미 존재하는 경우 해당 개체에 대한 참조를 반환합니다. Factory 팩토리 패턴을 사용하면 특수 함수인 팩토리 함수를 사용하여 비슷한 객체를 많이 만들 수 있습니다. => 비슷한 객체를 반복적으로 생성해야하는 경우 사용Mediator 중재자 패턴은 객체 그룹에 대한 중앙 권한을 제공합니다. Observer옵저버 패턴은 이벤트 드리븐 시스템을 이용하는 것Module 모듈패턴은 코드를 더 작고 재사용 가능한 조각으로 분할하는 것을 도와줍니다. 리액트-컴포넌트리액트로 만들어진 앱을 이루는 최소한의 단위1. 클래스형 컴포넌트class App extends Component { render(){ return <h1>안녕하세요.</h1> }}2 . 함수형 컴포넌트 function App(){ return <h1>안녕하세요.<h1>}-브라우저가 그려지는 원리 및 가상돔리액트의 주요 특징 중 하나는 가상돔을 사용 하는 것브라우저가 랜더링 하는 과정을 살펴보자웹페이지 빌드 과정 : 웹 브라우저가 HTML 문서를 읽고, 스타일 입히고 뷰포트에 표시하는 과정DOM tree 생성 -> Rander tree 생성 -> Layout -> 실제 화면에 그리기문제점 : 어떤 인터렉션에 의해 DOM에 변화가 발생하면 그 때 마다 Render tree가 재생성 됨. 즉 모든 요소들의 스타일을 다시 계산(레이아웃, 화면 재그리기) , 불필요한 DOM을 조작하는 비용이 너무 크게 됨 이러한 문제점으로 인해 나온 것이 가상 돔. 가상돔이란 실제 DOM을 메모리에 복사해준 것으로 생각하면 됨작동원리: 데이터가 바뀌면 가상돔에 렌더링되고 이전에 생긴 가상돔과 비교해서 바뀐 부분만 실제 돔에 적용을 시켜줌. 바뀐 부분을 찾는 과정을 Diffing이라고 부르며, 바뀐 부분만 실제 돔에 적용시켜주는 것을 재조정이라고 부름 -react app 실행해보기npm run start : 이 명령어로 리액트 앱을 시작할 수 있음-SPAApp.js파일의 소스 코드를 변경하면 변경한 부분이 화면에 적용이 됨public/index.htmlHTML 템플릿 파일입니다. 하단의 div 엘리먼트의 id를 root로 해놓음<div id=“root”></div> scr/index.js자바스크립트의 시작점. 여기서 위에 root id를 가진 div 엘리먼트를 잡아 줌. 그래서 그 엘리먼트 안에서 화면을 꾸밀 수 있게 됨ReactDOM.render( <React.StrictMode> <App /> </React.StricMode), document.getElementById(‘root’));Single Page Application(SPA)원래 a페이지를 만들면 a.html b페이지를 만들면 b.html 이런식으로 만듦 (전통적인 웹 사이트 만들때 사용하는 멀티 페이지 어플리케이션)하지만 요즘엔 웹 사이트의 전체 페이지를 하나의 페이지에 담아 동적으로 화면을 바꿔가며 표현함 (싱글 페이지 어플리케이션 SPA) 과제비밀번호 생성기 앱객체에 각 조건의 값들을 만들어 체크된 것들의 랜덤으로 비밀번호 생성되며, 구현한 값 클릭 시 복사 가능하도록 구현 하였다  

junghlee234

[인프런 워밍업 클럽 스터디 3기 - 프로덕트 디자인 (Figma)] 2주차 발자국

진행 기간: 2주차(20250310-20250316)진행 강의:[UI3 업데이트] 피그마 배리어블을 활용한 디자인 시스템 구축하기강의 및 미션이번 주는 입력과 디스플레이 컴포넌트를 만들어보는 주였습니다.강의 내용 및 미션도 저번 주와는 다르게 구현을 많이 하면서 기본 컴포넌트들을 만들어나가는 부분이 많았습니다.특히 컴포넌트의 속성의 조합에 따른 다양한 파생 베리언트들을 만들어 보는 것이 중요했습니다.미션을 수행하기 위해서는 숙련도 부족으로 정확한 확인을 위해 결국 강의 하나하나를 다시 천천히 들어야 하기에, 특히 시간이 필요하였습니다.회고이번 주는 수술과 좋지 않은 몸 상태로 인해 실제로는 2일(하루 4시간 기준) 이상을 낼 수 없었기에 목표하고자 하는 미션의 절반 이하로만 진행이 가능하였습니다.확인 결과 3주차의 경우에는 컴포넌트의 고도화 및 마무리 과정으로, 거의 하루 1개 미션을 진행해야 하는 상황이므로 다음 주 1일 차에 못한 강의와 미션을 마저 처리하고, 남은 4일에 하루 2개 정도로 처리하고, 만약에 부족한 경우 주말에 처리하는 식으로 진행할 예정입니다.또한 미션과 강의를 전부 하지는 못했지만, 좀 더 Figma 인터페이스에 익숙해져서 빠르게 구현을 할 수 있도록 하여 각 구현의 시간을 줄여야 겠다는 생각이 드는 주였습니다.

UX/UI디자인시스템FigmaUX/UI인프런_워밍업_클럽

hee j

[인프런 워밍업 클럽 3기 풀스택 ] 2주차 발자국

목차Dropbox Clone ProjectDrag & Drop 할 영역 설정 및 서버에 파일 전송supabase의 Storage에 첨부파일 업로드첨부파일 검색, 삭제 2주차 미션파일의 마지막 수정(업로드) 시간을 표시하기파일명을 UUID로 변경하여 업로드하기Dropbox Clone Project1. Drag & Drop 할 영역 설정Drag & Drop 라이브러리 설치npm i --save react-dropzonefile-dragdropzone.tsx 파일div: 파일을 받는 영역 태그input: 파일 정보를 받는 태그isDragActive: 어떤 파일을 드래그 앤 드롭할 때 영역에 무엇을 보여줄지 정할 수 있게 해주는 값 ex) 드래그를 했다면? 파일을 여기에 드롭: 아니라면 파일을 드래그 앤 드롭을 해라 라는 문구 출력formData에 파일 이름과 파일 정보를 담아서 전송multiple을 true로 작성하여 여러 파일을 받을 수 있게 한다 export default function FileDragDropZone() { const uploadImageMutation = useMutation({ mutationFn: uploadFile, onSuccess: () => { queryClient.invalidateQueries({ queryKey: ["images"], // images로 시작하는 것들 전부 리셋 }); }, }); const onDrop = useCallback(async (acceptedFiles) => { // 10개 이하의 파일만 업로드함 if (acceptedFiles.length > 0 && acceptedFiles.length <= 10) { const formData = new FormData(); acceptedFiles.forEach((file) => { formData.append(file.name, file); }); await uploadImageMutation.mutate(formData); } }, []); const { getRootProps, getInputProps, isDragActive } = useDropzone({ onDrop, multiple: true, }); return ( <div {...getRootProps()} className="w-full border-4 border-dotted border-blue-700 flex flex-col items-center justify-center py-20 cursor-pointer" > <input {...getInputProps()} /> {uploadImageMutation.isPending ? ( <Spinner /> ) : isDragActive ? ( <p>파일을 놓아주세요.</p> ) : ( <p>파일을 여기에 끌어다 놓거나 클릭하여 업로드 하세요.</p> )} </div> ); }  2. supabase의 Storage에 첨부파일 업로드.env 파일에 Storage 명 추가NEXT_PUBLIC_STORAGE_BUCKET=miniboxroot/actions 폴더 생성storageActions.ts 파일에 storage에 업로드할 함수 작성export async function uploadFile(formData: FormData) { const files = Array.from(formData.entries()).map( ([name, file]) => file as File ); // all(): 여러 파일을 한 번에 업로드 진행하기 위해 사용 const results = await Promise.all( files.map((file) => { supabase.storage .from(process.env.NEXT_PUBLIC_STORAGE_BUCKET) .upload(file.name, file, { upsert: true }); }) ); return results; 3. 첨부파일 검색, 삭제storageActions.ts 파일에 파일 검색, 파일 삭제 함수 추가export async function searchFiles(search: string = "") { const supabase = await createServerSupabaseClient(); const { data, error } = await supabase.storage .from(process.env.NEXT_PUBLIC_STORAGE_BUCKET) .list(null, { search }); // path, options, parameters handleError(error); return data; } export async function deleteFile(fileName: string) { const supabase = await createServerSupabaseClient(); const { data, error } = await supabase.storage .from(process.env.NEXT_PUBLIC_STORAGE_BUCKET) .remove([fileName]); handleError(error); return data; } 2주차 미션[미션 완성 이미지][파일의 마지막 수정(업로드) 시간을 표시하기]dropbox-image.tsxstorage에서 받아오는 정보 내에 마지막 수정 시간을 담고 있는 updated_at을 가져와 표시formData로 날짜와 시간의 가독성을 높여줌const formData = (dateString: string) => { return format(new Date(dateString), "yyyy-MM-dd HH:mm:ss"); }; return ( ... {/* FileName */} <div>{image.name}</div> <div>수정된 시간: {formData(image.updated_at)}</div> ... ) [파일명을 UUID로 변경하여 업로드하기]- 한글명 파일이 업로드 되지 않아 uuid로 파일 명을 변경하여 업로드 해보았음- 업로드는 잘 되나 같은 파일을 업로드 하여도 파일 명이 변경되어 업로드 되기 때문에 새로 업로드 되어 업로드 시간이 변경되지 않아 적용하지는 않음uuid 설치하기npm install uuidstorageActions.tsext 변수에 첨부 파일의 확장자 추출fileName 변수에 uuid+.확장자를 합쳐 파일명 생성const results = await Promise.all( files.map((file) => { const ext = file.name.split(".").pop(); // 확장자 추출 const fileName = `${uuidv4()}.${ext}`; // UUID 기반 파일명 생성 supabase.storage .from(process.env.NEXT_PUBLIC_STORAGE_BUCKET) .upload(fileName, file, { upsert: true }); }) );

풀스택풀스택next.jsreactsupabase워밍업발자국

연유

인프런 워밍업 클럽 CS 3기 2주차 발자국

✏ 학습회고 2주차 운영체제 강의에서는 프로세스와 메모리에 대해 깊이 배웠습니다. 강의를 들으며 공부한 내용을 기록했는데 집중도 잘되고 복습하기에도 편리했습니다. 다음주에는 3주차 학습과 함께 1주차와 2주차 내용을 복습하겠습니다.🎯 미션 운영체제 FIFO 스케줄링의 장단점이 뭔가요?장점은  단순하고 직관적인 것입니다.단점은 실행시간이 짧고 늦게 요청된 프로세스가 실행시간이 길고 빨리 요청된 프로세스의 작업을 기다려야하는 것입니다. 또한 I/O 작업이 있다면 CPU 사용률이 떨어집니다. SJF를 사용하기 여러운 이유가 뭔가요?프로세스가 얼마나 실행될 지 예측하기 힘듭니다. 그리고 Burst Time이 긴 프로세스의 경우 아주 오랫동안 실행되지 않을 수 있습니다. RR 스케줄링에서 타임 슬라이스가 아주 작으면 어떤 문제가 발생할까요?컨텍스트 스위칭이 빈번하게 발생하여 오버헤드가 너무 커집니다.  운영체제가 MLFQ에서 CPU Bound Process와 I/O Bound Process를 어떻게 구분할까요?타임 슬라이스를 오버하여 CPU를 강제로 뺏기면 CPU Bound Process로 구분하고, 스스로 CPU를 반납하면 I/O Bound Process로 구분을 합니다. 공유자원이란무엇인가요? 프로세스 간 통신을 할 때 공동으로 이용하는 변수나 파일입니다.  교착상태에 빠질 수 있는 조건은 어떤 것들을 충족해야할까요?상호배제, 비선점, 점유와 대기, 원형 대기 입니다.   자료구조와 알고리즘 재귀함수에서 기저조건을 만들지 않거나 잘못 설정했을 때 어떤 문제가 발생할 수 있나요?콜스택에 함수가 무한히 쌓여서  메모리가 부족해집니다. 스택 오버플로우가 발생하며 프로그램이 종료될 수 있습니다. 0부터 입력 n까지 홀수의 합을 더하는 재귀 함수를 만들어보세요.function sumOdd(n){ if(n == 0) return 0; if(n == 1) return 1; if(n & 1) { return sumOdd(n - 2) + n; } else { return sumOdd(n - 1); } } console.log(sumOdd(10)) // 25n이 홀수라면 n의 값을 더하고 sumOdd(n - 2)를 수행하도록 했습니다. 짝수라면 sumOdd(n - 1)을 수행하도록 했습니다.   다음 코드는 매개변수로 주어진 파일 경로(.는 현재 디렉토리)에 있는 하위 모든 파일과 디렉토리를 출력하는 코드입니다. 다음 코드를 재귀 함수를 이용하는 코드로 변경해보세요.const fs = require("fs"); // 파일을 이용하는 모듈 const path = require("path"); // 폴더와 파일의 경로를 지정해주는 모듈 function traverseDirectory1(directory){ const stack = [directory]; // 순회해야 할 디렉토리를 저장할 스택 while (stack.length > 0) { // 스택이 빌 때까지 반복 const currentDir = stack.pop(); // 현재 디렉토리 const files = fs.readdirSync(currentDir); // 인자로 주어진 경로의 디렉토리에 있는 파일or디렉토리들 for (const file of files) { // 현재 디렉토리의 모든 파일or디렉토리 순회 const filePath = path.join(currentDir, file); //directory와 file을 하나의 경로로 합쳐줌 const fileStatus= fs.statSync(filePath); // 파일정보 얻기 if (fileStatus.isDirectory()) { // 해당 파일이 디렉토리라면 console.log('디렉토리:', filePath); stack.push(filePath); } else { // 해당 파일이 파일이라면 console.log('파일:', filePath); } } } } traverseDirectory1("."); // 현재 경로의 모든 하위 경로의 파일, 디렉토리 출력 변경 후function traverseDirectory1(directory){ const files = fs.readdirSync(directory); for(const file of files){ const filePath = path.join(directory, file); const fileStatus = fs.statSync(filePath); if (fileStatus.isDirectory()) { console.log('디렉토리:', filePath); traverseDirectory1(filePath); } else { console.log('파일:', filePath); } } } traverseDirectory1(".");재귀함수를 사용하므로 stack을 사용하지 않아도 됨해당 파일이 디렉토리라면 traverseDirectory1() 를 재귀적으로 호출 📝회고 미션 과정에서 재귀함수를 하향식으로 구현하려고 노력했습니다. 자료구조와 알고리즘 3번 미션에서 for문을 재귀함수로 대체하려고 했으나 구현하지 못했습니다. 이유는 디렉토리에 여러 개의 파일이 있어서 반복해서 출력해야하기 때문입니다. 구현가능한 방법이 있다면 알고 싶습니다.

안지수

[워밍업 클럽] CS 전공지식 2주차 미션

운영체제1. FIFO 스케줄링의 장단점이 뭔가요? FIFO 스케줄링의 장점은 ‘먼저 들어온 작업이 먼저 나가는(First In First Out)’,스케줄링 큐에 들어온 순서대로 CPU를 할당받는 단순하고 직관적인 알고리즘이라는 것이고,단점은 한 프로세스가 완전히 끝나야 다음 프로세스가 시작되기 때문에실행시간이 짧고 늦게 도착한 프로세스가 실행시간이 길고 빨리 도착한 프로세스의 작업을 기다려야 한다는 점입니다.또 I/O 작업이 있을 경우 CPU는 I/O 작업이 끝날 때까지 쉬고 있기 때문에 CPU 사용률이 떨어지게 됩니다.2. SJF를 사용하기 여러운 이유가 뭔가요?SJF는 작업 시간이 짧은 프로세스부터 CPU를 할당하는 알고리즘으로,1) 어떤 프로세스가 얼마나 실행될지 예측하기 힘들고(프로세스의 종료시간을 예측하기 어려움),2) Burst Time이 긴 프로세스는 아주 오랫동안 실행되지 않을 수도 있기 때문에 사용하기 어렵습니다.3. RR 스케줄링에서 타임 슬라이스가 아주 작으면 어떤 문제가 발생할까요?컨텍스트 스위칭이 너무 자주 일어나게 되어 타임 슬라이스에서 실행되는 프로세스의 처리량보다 컨텍스트 스위칭을 처리하는 양이 훨씬 커져서 오버헤드가 큰 상황이 발생합니다. 4. 운영체제가 MLFQ에서 CPU Bound Process와 I/O Bound Process를 어떻게 구분할까요?CPU를 사용하는 프로세스가 CPU를 스스로 반납하면 CPU 사용이 적은 I/O Bound Process,CPU를 사용하는 프로세스가 타임 슬라이스 크기를 오버해서 CPU 스케줄러에 의해 강제로 CPU를 반납하게 되면 CPU를 많이 사용하는 CPU Bound Process로 구분합니다.5. 공유자원이란무엇인가요?프로세스 간 통신을 할 때 공동으로 이용하는 변수나 파일들입니다.6. 교착상태에 빠질 수 있는 조건은 어떤 것들을 충족해야할까요?- 상호배제 : 어떤 프로세스가 한 리소스를 점유했다면 그 리소스는 다른 프로세스에게 공유되면 안됩니다.- 비선점 : 프로세스A가 리소스를 점유하고 있는데 프로세스B가 리소스를 빼앗을 수 없어야 합니다.- 점유와 대기 : 어떤 프로세스가 리소스A를 가지고 있는 상태에서 리소스B를 원하는 상태여야 합니다.- 원형 대기 : 점유와 대기를 하는 프로세스들의 관계가 원형을 이룹니다.자료구조1. 재귀함수에서 기저조건을 만들지 않거나 잘못 설정했을 때 어떤 문제가 발생할 수 있나요?함수를 무한 호출하게 되어 스택오버플로우가 발생할 수 있습니다.2. 0부터 입력 n까지 홀수의 합을 더하는 재귀 함수를 만들어보세요.function sumOdd(n) { if (n <= 0) return 0; if (n % 2 == 0) n--; return n + sumOdd(n - 2); } console.log(sumOdd(10)); // 25 3. 다음 코드는 매개변수로 주어진 파일 경로(.는 현재 디렉토리)에 있는 하위 모든 파일과 디렉토리를 출력하는 코드입니다. 다음 코드를 재귀 함수를 이용하는 코드로 변경해보세요.const fs = require("fs"); const path = require("path"); function traverseDirectory(directory) { const files = fs.readdirSync(directory); // 현재 디렉토리의 파일 및 디렉토리 목록을 가져옴 for (const file of files) { const filePath = path.join(directory, file); const fileStatus = fs.statSync(filePath); if (fileStatus.isDirectory()) { console.log("디렉토리:", filePath); traverseDirectory(filePath); // 재귀 호출 } else { console.log("파일:", filePath); } } } traverseDirectory("."); // 현재 디렉토리부터 탐색 시작

soo97703

인프런 워밍업클럽 2주차 발자국

학습 내용 요약1. 객체 지향 적용하기1) 상속과 조합 - 조합을 사용하자. 상속은 수정이 어렵다.2) value object - 도메인의 어떤 개념을 추상화하여 표현한 값 객체불변성, 동등성, 유효성 검증을 보장해야한다.entity는 식별자가 존재한다는 점이 차이점이다.3) 일급 컬렉션 - 컬렉션을 포장하면서 컬렉션만을 유일한 필드로 가지는 객체4) Enum은 상수의 집합이며 상수와 관련된 로직을 담을 수 있는 공간2. 코드 다듬기1) 주석은 우리가 가진 모든 표현 방법을 총동원해 코드에 의도를 녹여내고 나서 그럼에도 전달해야할 정보가 남았을 때 사용하자2) 메서드는 public 메서드 → private 메서드 순으로 나열하는게 좋다.상태변경 → 판별 → 조회 메서드 순으로 나열!3) 패키지 나누기 - 패키지는 문맥으로써의 정보를 제공할 수 있다.  일주일 동안의 회고강의를 들으면서 노션에 내용을 정리했다.정해진 진도표에 따라서 강의를 듣지 못해서 미션도 제대로 수행하지 못했고 강의가 많이 밀렸다..미션 해결 회고혼자서 리팩토링을 하려고 보니, 어디서부터 어떻게 시작해야할지 모르겠고 너무 막막했다. 일단 이번 주에 강의를 다 듣지 못해서 완성도가 낮은 상태로 일단 제출을 했다. 그리고 value object, 일급 컬렉션 등에 대한 내용이 어렵다고 느껴져서 강의를 듣고 실습을 해본 후에 다시 혼자 리팩토링을 하는 연습을 해봐야겠다는 생각이 들었다. 인프런 강의 [Readable Code : 읽기 좋은 코드를 작성하는 사고법]을 보고 작성했습니다.https://www.inflearn.com/course/readable-code-%EC%9D%BD%EA%B8%B0%EC%A2%8B%EC%9D%80%EC%BD%94%EB%93%9C-%EC%9E%91%EC%84%B1%EC%82%AC%EA%B3%A0%EB%B2%95/dashboard

인프런워밍업클럽

강신욱

[인프런 워밍업 클럽 Full Stack 3기] 스터디 2주차

  미션 수행이번 미션에서는 실습에서 구현한 Dropbox에 마지막 업로드 시간을 표시하는 기능을 추가하는 것이 목표였다.구현 결과각 파일을 표시할 때 아래에 마지막 업로드 시간이 표시되는 것을 확인할 수 있다.2주차 회고2주차에는 중간점검 시간을 가졌다. 수강생들의 다양한 질문과 강사님의 상세한 답변을 통해 많은 것을 배울 수 있었던 유익한 시간이었다.특히, 1주차보다 Supabase의 사용법에 훨씬 익숙해진 것을 느낄 수 있었다. 하지만 여전히 실습 중 오타로 인해 코드가 실행되지 않는 상황이 반복되었다. 결국 깃허브에 제공된 코드나 강의 속 코드를 참고하며 오타를 수정하고 누락된 부분을 채워 넣어야 했다. 이러한 과정에서 실습 코드 오류를 해결하는 데 적지 않은 시간을 쏟게 되었다.자동완성 기능은 매우 편리하지만, 의도치 않은 코드 완성으로 인해 어디서 문제가 발생했는지 찾기가 어려운 경우도 많았다. 이 때문에 앞으로 실습에서는 더욱 신중하게 코드를 작성해야겠다고 다시 한번 다짐했다.이번 주차를 통해 실습 과정에서의 꼼꼼함과 디버깅의 중요성을 다시금 깨달았고, Supabase와 같은 외부 서비스를 활용하는 데 자신감을 조금 더 얻게 되었다.

강신욱

[인프런 워밍업 클럽 Full Stack 3기] 스터디 1주차

강의 주요 내용  서버 액션: 비동기 함수서버에서 실행되는 함수Next.js는 서버에서 실행되는 서버 컴포넌트와 브라우저에서 실행되는 클라이언트 컴포넌트를 구분하여 동작한다.파일 최상단에 'use server'가 선언되어 있으면 서버 컴포넌트이다.'use client'가 선언되어 있으면 클라이언트 컴포넌트이다.서버 컴포넌트 내에서 정의한 함수를 클라이언트에서 직접 호출할 수 있다. 즉, 별도의 API를 구현하지 않아도 클라이언트에서 서버 함수를 바로 사용할 수 있어 개발이 더욱 간편해진다.Recoil: 전역 상태 관리 라이브러리Recoil이란?Recoil은 클라이언트 상태 관리 라이브러리로, 여러 컴포넌트에서 동일한 상태를 공유할 수 있도록 도와준다. 예를 들어:뷰어 상태 관리헤더 검색창 상태 관리이처럼 다양한 상태를 효율적으로 관리할 수 있으며, Redux나 MobX보다 간편하게 사용할 수 있다.Recoil의 핵심 개념Recoil은 Atom과 Selector라는 두 가지 핵심 개념으로 구성된다.1. Atom전역 상태를 정의하는 가장 기본적인 단위여러 컴포넌트에서 공유 가능2. SelectorAtom 상태에서 파생된 값을 생성할 때 사용특정한 값만 변형하여 제공 가능예: 텍스트 상태에서 문자열 길이만 가져오는 Selector 정의Selector를 활용하면 불필요한 연산을 줄이고 최적화된 방식으로 상태를 관리할 수 있다.React Query: 클라이언트 상태 관리 및 데이터 동기화React Query란?React Query는 TanStack에서 개발한 서버 상태 관리 라이브러리로,서버에서 데이터를 가져오거나데이터를 변경하는 요청을 보낼 때 사용된다.React Query의 역할클라이언트에서 데이터 가져오기(Fetching)가져온 데이터 캐싱(Caching)서버 데이터 변경 시 동기화(Syncing)즉, 서버와 클라이언트 간의 데이터 흐름을 효율적으로 관리할 수 있도록 도와준다.React Query의 주요 장점✅ 자동 캐싱 (Auto Caching)✅ 서버 데이터와 클라이언트 데이터 분리 (Separation of Server & Client State)Supabase 주요 기능1. Table EditorTable Editor는 데이터베이스에서 직접 테이블을 생성 및 수정할 수 있는 기능이다.2. SQL EditorSQL Editor를 통해SELECT, UPDATE, DELETE 등의 SQL 쿼리를 실행할 수 있다.Assistant 기능 지원: AI가 DB와 연동되어 SQL을 자동 생성해준다.예: "이 테이블에서 특정 컬럼을 가져오고 싶어!"라고 입력하면, 적절한 SQL 쿼리를 자동 생성해준다.SQL이 익숙하지 않은 사용자에게 유용한 무료 기능이다.3. 데이터베이스 관리생성된 테이블 조회데이터베이스 함수 및 트리거 설정예: 특정 row가 생성, 수정, 삭제될 때 실행되는 트리거 설정 가능액세스 컨트롤(Role-based Access Control)특정 유저가 특정 테이블에 접근할 수 있도록 권한을 설정할 수 있다.(※ 액세스 컨트롤 관련 내용은 본 강좌 범위에서 제외)미션 수행이번 미션에서는 실습에서 구현한 TODO 리스트에 생성 날짜를 표시하는 기능을 추가하는 것이 기본 목표였다.처음 도전해보는 분야였던 만큼 시행착오가 많았고, 라이브러리 버전 호환 문제나 기타 충돌로 인해 많은 구글링이 필요했다.관련해서 강사님이 추천해주신 강의를 다시 한 번 정독한 뒤, 선택 과제도 수행해볼 예정이다.이번 실습을 통해 Next.js, Recoil, React Query, 그리고 Supabase를 더욱 깊이 있게 이해할 수 있었으며, 앞으로의 프로젝트에서도 적극적으로 활용해볼 계획이다.

풀스택

Hyun Ho Kim

인프런 워밍업 클럽 스터디 3기 - 자료구조와 알고리즘 -2주차 미션-

1. 재귀함수에서 기저조건을 만들지 않거나 잘못 설정했을 때 어떤 문제가 발생할 수 있나요?스택 오버플로가 발생합니다.콜스택에 스택 프레임이 쌓이는데, 기저조건을 만들지 않으면 함수가 무제한 호출되며, 스택 프레임도 무제한으로 쌓이게 됩니다.콜스택 메모리의 잉여 용량을 초과하면 프로세스가 OS에 의해 강제 종료되는데 이를 스택 오버플로라고 합니다.  2. 0부터 입력 n까지 홀수의 합을 더하는 재귀함수를 만들어보세요.function sumOdd(n) { if (n <= 0) return 0; // 현재 숫자가 홀수면 더하고, 짝수면 그냥 넘긴다 if (n % 2 !== 0) { return n + sumOdd(n - 1); } else { return sumOdd(n - 1); } } console.log(sumOdd(10)); // 25 3. 다음 코드는 매개변수로 주어진 파일 경로(.는 현재 디렉토리)에 있는 하위 모든 파일과 디렉토리를 출력하는 코드입니다. 다음 코드를 재귀 함수를 이용하는 코드로 변경해보세요. const fs = require("fs"); // 파일을 이용하는 모듈 const path = require("path"); // 폴더와 파일의 경로를 지정해주는 모듈 function traverseDirectory1(directory){ const stack = [directory]; // 순회해야 할 디렉토리를 저장할 스택 while (stack.length > 0) { // 스택이 빌 때까지 반복 const currentDir = stack.pop(); // 현재 디렉토리 const files = fs.readdirSync(currentDir); // 인자로 주어진 경로의 디렉토리에 있는 파일 or 디렉토리들 for (const file of files) { // 현재 디렉토리의 모든 파일 or 디렉토리 순회 const filePath = path.join(currentDir, file); // directory와 file을 하나의 경로로 합쳐줌 const fileStatus= fs.statSync(filePath); // 파일정보 얻기 if (fileStatus.isDirectory()) { // 해당 파일이 디렉토리라면 console.log('디렉토리:', filePath); stack.push(filePath); } else { // 해당 파일이 파일이라면 console.log('파일:', filePath); } } } } traverseDirectory1("."); // 현재 경로의 모든 하위 경로의 파일, 디렉토리 출력 const fs = require("fs"); // 파일을 이용하는 모듈 const path = require("path"); // 폴더와 파일의 경로를 지정해주는 모듈 function recursiveTraverseDirectory(directory) { const files = fs.readdirSync(directory); for (const file of files) { const filePath = path.join(directory, file); const fileStatus = fs.statSync(filePath); if (fileStatus.isDirectory()) { console.log('Directory:', filePath); recursiveTraverseDirectory(filePath); } else { console.log('File:', filePath); } } } recursiveTraverseDirectory("."); // 현재 경로의 모든 하위 경로의 파일, 디렉토리 출력

영후이

[인프런 워밍업 클럽 3기] 백엔드 발자국 2주차

📒 2주차에 배운 내용 📌 Controller, Service , Repository , DTO 개발과 테스팅, 그리고 Tymeleaf fragments 에 대해 학습하는 시간이였다.✏ 강의 중에 다뤘던 PresentationService 테스트 @DisplayName("활성화된 Introduction 만 조회하는데 성공한다. ") @Test fun testGetIntroductions() {/* given */ val introductions = mutableListOf<Introduction>() (1..DATA_SIZE).forEach { introductions.add(Introduction(content = "$it", isActive = it % 2 == 0)) } val activeIntroductions = introductions.filter { it.isActive } Mockito.`when`(presentationRepository.getActiveIntroductions()).thenReturn(activeIntroductions) /* when */ val introductionDTOs = presentationService.getIntroductions() /* then */ assertThat(introductionDTOs).hasSize(DATA_SIZE / 2) introductionDTOs.forEach { assertThat(it.content.toInt()).isEven() } } @DisplayName("활성화된 Link 만 조회하는데 성공한다. ") @Test fun testGetLinks() {/* given */ val links = mutableListOf<Link>() (1..DATA_SIZE).forEach { links.add(Link(name = "$it", content = "$it", isActive = it % 2 != 0)) } val activeLinks = links.filter { it.isActive } Mockito.`when`(presentationRepository.getActiveLinks()).thenReturn(activeLinks) /* when */ val linkDTOs = presentationService.getLinks() /* then */ var expectedSize = DATA_SIZE / 2 if (DATA_SIZE % 2 != 0) expectedSize += 1 assertThat(linkDTOs).hasSize(expectedSize) linkDTOs.forEach { assertThat(it.content.toInt()).isOdd() } } ✏ Repository 성능 개선 -> N + 1 해결하기 (fetch join)@Repository interface ProjectRepository: JpaRepository<Project, Long> { @Query("select distinct p from Project p left join fetch p.details where p.id = :id") override fun findById(id: Long): Optional<Project> }📌 JPQL fetch Joinspring: application: name: kotlin-portfolio jpa: database: h2 open-in-view: false show-sql: true hibernate: ddl-auto: create properties: hibernate: format_sql: true default_batch_fetch_size: 10 # batch size 조절 📌`application.yml` 에서 batch size 설정 ✏ Mocking 을 활용한 Controller 테스트val logger = KotlinLogging.logger {} @AutoConfigureMockMvc @SpringBootTest @DisplayName("[API 컨트롤러 테스트]") class PresentationApiControllerTest ( @Autowired private val mockMvc: MockMvc, ){ @DisplayName("Introductions 조회") @Test fun testGetIntroductions() { /* given */ val uri = "/api/v1/introductions" /* when */ val mvcResult = performGet(uri) val contentAsString = mvcResult.response.contentAsString val jsonArray = JSONArray(contentAsString) /* then */ assertThat(jsonArray.length()).isPositive() } @DisplayName("Links 조회") @Test fun testGetLinks() { /* given */ val uri = "/api/v1/links" /* when */ val mvcResult = performGet(uri) val contentAsString = mvcResult.response.contentAsString val jsonArray = JSONArray(contentAsString) /* then */ assertThat(jsonArray.length()).isPositive() } @DisplayName("Resume 조회") @Test fun testGetResume() { /* given */ val uri = "/api/v1/resume" /* when */ val mvcResult = performGet(uri) val contentAsString = mvcResult.response.contentAsString val jsonObject = JSONObject(contentAsString) /* then */ logger.info{jsonObject.optJSONObject("experiences")} assertThat(jsonObject.optJSONArray("experiences").length()).isPositive() assertThat(jsonObject.optJSONArray("achievements").length()).isPositive() assertThat(jsonObject.optJSONArray("skills").length()).isPositive() } private fun performGet(uri: String): MvcResult { return mockMvc .perform (MockMvcRequestBuilders.get(uri)) .andDo(MockMvcResultHandlers.print()) .andReturn() } }📌 2주차 미션 1 대 다 관계를 갖는 테이블 설계하기 ✔Rest API 를 설계하기✔

한선규

[인프런 워밍업 클럽 3기 - CS] 2주차 발자국

학습 내용 회고: 이번 2주차는 운영체제를 공부하며 정말 재미를 느꼈습니다. 평소에 윈도우 설정을 보면서 그냥 넘어갔던 용어들 ex.조각 모음 같은 용어의 뜻을 알게 되어 너무 재밌게 수강했습니다.   1강 프로세스 간 통신프로세스 간 통신(Inter-Process Communication, IPC)은 같은 컴퓨터 안에서 프로세스들끼리 데이터를 주고받거나, 네트워크로 연결된 다른 컴퓨터의 프로세스와 데이터를 주고받는 기술이다.한 컴퓨터 내에서의 통신 방법파일(File): 여러 프로세스가 하나의 파일을 읽고 쓰면서 데이터를 공유하는 방식.파이프(Pipe): 운영체제가 제공하는 파이프를 통해 데이터를 주고받는 방식.쓰레드(Thread): 같은 프로세스 내에서 공유하는 CODE, DATA, HEAP 영역 중 DATA와 HEAP을 이용해 통신하는 방식.네트워크를 이용한 통신 방법소켓(Socket) 통신: 네트워크를 통해 데이터를 주고받는 방식.원격 프로시저 호출(RPC, Remote Procedure Call): 네트워크를 통해 다른 컴퓨터의 함수를 호출하는 방식.2강 공유자원과 임계구역프로세스 간 통신을 할 때 여러 프로세스가 공동으로 사용하는 변수나 파일을 공유자원(Shared Resource)이라고 한다.문제점: 동기화(Synchronization) 문제공유자원에 여러 프로세스가 동시에 접근하면 실행 순서에 따라 결과가 달라질 수 있다.컨텍스트 스위칭(Context Switching)으로 인해 실행 순서를 예측하기 어렵다.→ 이를 해결하려면 임계구역(Critical Section) 개념이 필요하다.공유자원 사용 시 발생하는 문제경쟁조건(Race Condition): 여러 프로세스가 동시에 공유자원에 접근하면 충돌이 발생할 수 있음.임계구역 문제 해결을 위한 상호 배제(Mutual Exclusion) 메커니즘임계구역에는 동시에 하나의 프로세스만 접근 가능해야 한다.여러 프로세스가 접근을 요청해도 한 번에 하나만 들어갈 수 있어야 한다.임계구역에 들어간 프로세스는 최대한 빨리 나와야 한다.3강 세마포어(Semaphore)세마포어는 상호 배제(Mutual Exclusion) 메커니즘 중 하나로, 공유자원에 대한 접근을 조절하는 역할을 한다.세마포어 개념프린터 방 예시:공유자원: 프린터프로세스: A, B대기 장소: 대기 큐열쇠 관리자: 운영체제열쇠: 세마포어세마포어는 프로세스가 공유자원에 접근하기 전에 획득하고, 사용이 끝나면 해제하는 방식으로 동작한다.4강 모니터(Monitor)세마포어의 단점을 보완한 상호 배제 메커니즘으로, 운영체제가 아닌 프로그래밍 언어 차원에서 지원하는 동기화 기법이다.모니터의 특징세마포어처럼 wait(), signal()을 직접 호출할 필요 없이 언어 차원에서 동기화 기능을 제공한다.더 안전하고 직관적으로 동기화 코드를 작성할 수 있다.예시: Java에서 synchronized 키워드를 사용하면 동시에 여러 프로세스가 같은 메서드를 실행할 수 없다.예시위 코드에서 프로세스 A가 increase() 메서드를 실행 중이면, 프로세스 B는 decrease()를 실행할 수 없다.결론 모니터는 세마포어보다 더 직관적이고 안전한 동기화 메커니즘을 제공하여, 동기화 코드를 쉽게 작성할 수 있도록 해준다. 데드락(교착상태)여러 프로세스가 서로 다른 프로세스의 작업이 끝나길 기다리다 아무도 작업을 진행하지 못하는 상황을 교착상태라 한다.ex. 프로세스A: 프로세스B가 자원을 줘야 실행 됨 프로세스B: 프로세스C가 자원을 주길 기다리고 있음. 프로세스C: 프로세스 A가 자원 주면 지원해주겠음. 교착상태의 발생 원인은 공유자원 때문이다.교착상태의 필요조건 4가지(모두 충족해야함)상호배제(어떤 프로세스가 리소스를 점유했다면 그 리소스는 다른 프로세스에게 공유 되면 안된다.)비선점(프로세스 A가 리소스를 점유하고 있는데 프로세스 B가 리소스를 빼앗을 수 없어야함.)점유와 대기(어떤 프로세스가 리소스 A를 점유하고 있는 상태에서 리소스 B를 원하는 상태)(오른쪽 포크를 쥔 상태에서 왼쪽 포크를 원하는 상태)원형 대기(점유와 대기를 하는 프로세스들의 관계가 원형을 이루고 있어야한다.)(1번은 자원이 공유될 수 있는지, 2번은 점유된 리소스를 빼앗을 수 있는지)교착상태를 예방하는 방법은 너무 비효율적이었다.그래서 교착상태에 빠졌을 때 해결방법을 알아보겠다.교착상태 회피(Deadlock avoidance)운영체제가 프로세스들에게 자원을 할당할 때 어느정도 자원을 할당해야 교착상태에 이르는지 파악하고 발생하지 않는 수준의 자원을 할당한다.교착상태 회피는 할당된 자원의 수를 기준으로 안정 상태와 불안정 상태로 나뉜다.운영체제는 최대한 안정 상태를 유지하려고 자원할당을 한다.불안정상태여도 교착상태에 무조건 빠지는 것이 아닌 확률이 높아지는 것.(은행원 알고리즘)운영체제는 프로세스들에게 자원을 할당하기 전에 자원을 얼마나 가지고 있는지 즉 총 자원을 알고있다.프로세스들은 자기가 필요한 자원의 최대 숫자를 운영체제에게 알려줘야함. 이를 최대 요구 자원 이라 함.안정상태시스템의 총 자원=14 사용가능한 자원=2프로세스 최대 요구 자원 현재 할당된 자원 요청이 예상되는 자원 P1 9 5 4 P2 6 4 2 P3 4 3 1이 상황에서 P1이 4개를 요구하면 요구를 취소하고 P2에게 빌려줌.그 후 P2가 작업을 마치고 6개를 반납함 so P1, P3 요구 전부 가능.불안정상태시스템의 총 자원=14 사용가능한 자원=1프로세스 최대 요구 자원 현재 할당된 자원 요청이 예상되는 자원 P1 9 7 2 P2 6 4 2 P3 4 2 2P1, P2, P3 의 요청 전부 불가능함.지금처럼 불안정상태라해도 모든 프로세스가 최대 요구 자원을 요구하지 않는 이상 교착상태에 빠지진 않지만 요구한다면 교착상태에 빠진다.이는 비효율적이다.교착상태를 어떻게 검출해낼까?가벼운 교착 상태 검출(프로세스가 일정시간 작업을 진행하지 않는다면 교착상태가 발생했다 간주& 해결)(해결: 일정 시점마다 체크포인트를 만들어 작업을 저장하고 타임아웃으로 교착상태가 발생했다면 마지막으로 저장했던 체크포인트로 롤백하는 것)무거운 교착 상태 검출(자원할당 그래프를 이용함, 현재 운영체제에서 프로세스가 어떤 자원을 사용하는지 지켜보고 교착상태가 발생했다면 해결한다. 그래프를 보고 HOW? ,그래프를 보고 순환 구조를 파악한 뒤 교착상태를 발생시킨 프로세스를 강제 종료 시킴. 다시 실행시킬 때 체크포인트로 롤백시킴)(이는 주기적으로 자원할당 그래프를 검사해야 하기 때문에 오버헤드가 발생함)(하지만 가벼운 교착 상태 검출로 검출 될 수 있는 억울하게 종료되는 프로세스는 발생하지 않는다.)컴파일과 프로세스1. 프로그래밍 언어: 컴파일 언어 vs 인터프리터 언어프로그래밍 언어는 컴파일 언어와 인터프리터 언어로 구분할 수 있다.컴파일 언어개발자가 작성한 코드를 컴파일 과정을 거쳐 실행 파일(기계어)로 변환한다.컴파일 과정에서 문법 오류를 검사하고, CPU에서 처리 가능한 기계어로 변환하므로 실행 속도가 빠르다.인터프리터 언어코드를 미리 기계어로 변환하지 않고, 실행 시 한 줄씩 해석하여 실행한다.실행 전 오류 검사를 하지 않으므로 실행 중 오류가 발생할 가능성이 높으며 속도가 느리다.2. 프로세스의 메모리 구조프로세스는 실행될 때 CODE, DATA, HEAP, STACK 영역으로 나뉜다.① 코드(Code) 영역실행해야 할 코드가 저장되는 공간.예시:ret = num1 + num2; ② 데이터(Data) 영역전역 변수나 정적 변수가 저장되는 공간.예시:int global_A = 1; int arr[10]; ③ 스택(Stack) 영역함수 호출 시 생성되는 지역 변수와 함수 호출 기록(스택 프레임)이 저장된다.함수가 종료되면 해당 스택 영역은 자동으로 해제된다.④ 힙(Heap) 영역실행 중 동적 메모리 할당이 이루어지는 공간.개발자가 직접 할당 및 해제해야 한다 (malloc, free 등 사용).3. 컴파일 언어의 실행 과정컴파일 언어로 작성된 코드가 실행 파일이 되기까지의 과정은 다음과 같다.#include <stdio.h> #define MY_NUMBER 100 int main() { int num1 = 50; printf("result: %d", num1 + MY_NUMBER); getchar(); return 0; } 실행 과정전처리기 (Preprocessor) → test.i#include <stdio.h>의 내용을 포함시키고, #define MY_NUMBER 100을 치환한다.코드에 있는 모든 주석을 제거한다.컴파일러 (Compiler) → test.sC 코드(test.i)를 어셈블리 코드로 변환한다.어셈블러 (Assembler) → test.o어셈블리 코드를 목적 파일(기계어)로 변환한다.링커 (Linker) → test.exe여러 목적 파일과 라이브러리를 합쳐 실행 파일(Executable)을 생성한다.실행 파일과 프로세스exe 파일에는 코드(Code) 영역, 데이터(Data) 영역이 명확하게 구분되어 있다.운영체제(OS)는 실행 파일을 읽어 새로운 프로세스를 생성하며:코드, 데이터를 프로세스 메모리에 로드.빈 상태의 스택(Stack)과 힙(Heap) 영역을 할당.PCB(Process Control Block) 생성 후 관리 가능하도록 설정.프로그램 카운터(PC)*를 코드 영역의 첫 번째 명령어 주소로 설정하여 실행을 시작한다.이러한 과정을 통해 프로세스가 실행되며, CPU가 이를 스케줄링하여 프로그램이 동작하게 된다. 메모리의 종류와 주소 체계1. 메모리의 종류컴퓨터에서 사용되는 주요 메모리는 다음과 같이 구분된다.1.1 레지스터 (Register)CPU 내부에 위치하며 가장 빠른 기억장소전원 차단 시 데이터가 사라지는 휘발성 메모리CPU의 비트 수(예: 32비트, 64비트)는 레지스터의 크기를 의미CPU는 연산 시 메인메모리(RAM)의 데이터를 레지스터로 가져와 계산 후 다시 메인메모리에 저장1.2 캐시 메모리 (Cache Memory)레지스터보다 느리지만 메인메모리보다 빠른 휘발성 메모리메인메모리 접근 속도를 개선하기 위해 사용CPU가 자주 사용할 것 같은 데이터를 미리 저장해 속도 차이를 줄임성능 향상을 위해 여러 단계(L1, L2 캐시 등)로 구성됨1.3 메인메모리 (RAM, Random Access Memory)운영체제와 프로세스가 실행되는 공간전원이 꺼지면 데이터가 사라지는 휘발성 메모리프로그램 실행 및 데이터 처리 속도에 직접적인 영향을 줌1.4 보조 저장장치 (HDD, SSD)전원이 차단되어도 데이터가 유지되는 비휘발성 메모리하드디스크(HDD)는 비교적 저렴하지만 속도가 느림솔리드스테이트드라이브(SSD)는 빠르지만 가격이 높음2. 메모리와 주소 체계운영체제는 메모리를 효과적으로 관리하기 위해 1바이트 단위로 구역을 나누고 각 구역에 **주소(Address)**를 부여한다.2.1 32비트 vs 64비트 CPU32비트 CPU레지스터 크기: 32비트연산 장치(ALU), 데이터 버스도 32비트다룰 수 있는 메모리 크기: 2^32=4GB64비트 CPU레지스터 크기: 64비트연산 장치(ALU), 데이터 버스도 64비트다룰 수 있는 메모리 크기 : 2^64 (거의 무한대)2.2 물리 주소와 논리 주소물리 주소 공간: 메모리를 실제로 연결하면 0x0번지부터 시작하는 주소 공간논리 주소 공간: 운영체제가 사용자 프로그램을 위해 제공하는 가상의 주소 공간사용자는 논리 주소만 인식하며, 운영체제가 이를 물리 주소로 변환운영체제 보호를 위해 **경계 레지스터(Boundary Register)**를 사용하여 프로세스가 메모리 접근 시 경계를 넘지 않도록 관리함2.3 절대 주소 vs 상대 주소절대 주소 (Absolute Address): 실제 메모리에서 사용되는 물리 주소상대 주소 (Relative Address): 프로그램이 실행될 때 기준이 되는 시작 주소를 기반으로 한 주소프로그램 실행 시 **재배치 레지스터(Relocation Register)**를 사용해 논리 주소를 절대 주소로 변환2.4 메모리 주소 변환 예시사용자가 논리 주소 0x100의 데이터를 요청CPU가 메모리 관리자에게 0x100번지 데이터를 요청메모리 관리자는 **재배치 레지스터 값(예: 0x4000)**을 더해 **절대 주소 0x4100*의 데이터를 가져옴프로그램 시작 주소가 변경되더라도 재배치 레지스터 값만 수정하면 됨메모리 할당 방식과거 유니프로그래밍 환경에서는 메모리보다 큰 프로그램을 실행할 때 필요한 부분만 메모리에 올리고, 나머지는 하드디스크에 저장하는 메모리 오버레이 기법을 사용했다. 이를 통해 큰 프로그램을 여러 조각으로 나누어 일부만 실행하며, 나머지는 하드디스크의 스왑 영역에 저장했다.현대의 멀티프로그래밍 환경에서는 메모리 할당 방식이 **가변 분할 방식(세그멘테이션)**과 **고정 분할 방식(페이징)**으로 나뉜다.1. 가변 분할 방식 (세그멘테이션)프로세스의 크기에 따라 메모리를 동적으로 나누는 방식하나의 프로세스가 메모리에 연속된 공간에 할당됨 (연속 메모리 할당)✅ 장점낭비되는 공간인 내부 단편화가 발생하지 않음❌ 단점외부 단편화가 발생할 수 있음2. 고정 분할 방식 (페이징)프로세스의 크기와 관계없이 일정한 크기의 블록(페이지)로 나누어 메모리에 할당하나의 프로세스가 메모리 내 비연속적인 공간에 할당됨 (비연속 메모리 할당)✅ 장점구현이 간단하고 오버헤드가 적음❌ 단점사용되지 않는 공간이 발생하여 내부 단편화가 많음메모리 단편화 문제와 해결 방법외부 단편화프로세스가 종료된 후 남은 메모리가 조각나서, 새로운 프로세스가 올라갈 수 없는 현상해결 방법: **조각 모음(Compaction)**을 통해 단편화된 메모리 공간을 정리하지만 조각 모음 과정에서 오버헤드(추가적인 연산 비용)가 발생내부 단편화프로세스 크기보다 큰 고정된 메모리 블록을 할당하면서 사용되지 않는 공간이 생기는 현상해결 방법:할당되는 블록 크기를 조정하여 내부 단편화를 최소화버디 시스템을 사용하여 효율적인 메모리 할당버디 시스템2의 승수 단위로 메모리를 분할하여 할당하는 방식프로세스의 요청 크기에 가장 적합한 크기의 블록을 할당하여 외부 단편화를 방지하지만 내부 단편화는 일부 발생할 수 있음예시2048B(2^11)의 메모리가 있음500B 크기의 프로세스 A가 메모리를 요청512B(2^9) 크기의 블록을 할당이처럼 프로세스 크기에 맞게 할당되며, 불필요한 공간 낭비를 줄일 수 있음.현대의 메모리 관리 방식현재는 가변 분할(세그멘테이션)과 고정 분할(페이징) 방식을 조합하여 사용한다.이를 통해 내부·외부 단편화 문제를 최소화하면서도 효율적인 메모리 활용이 가능하다.

Versa

[3기] 워밍업 클럽-백엔드-code 2주차 발자국

미션 회고DAY7 미션은 스터디카페 코드를 추상화를 진행하는 것이었는데 거의 10줄도 바꾸지 못했다.이것저것 해야될 것 같고 하고 싶은건 많은데 코드로 막상 옮기려니 루미큐브를 하듯이다 벌려놓다가 마지막 하나가 부족해서 다시 처음으로 rollback 을 해야하는 것의 반복이었다.아직 바쁘다는 핑계로 한두번 손을 대고는 더 못댔다.그래도 아예 시작을 못할뻔 했는데 조금이라도 적용해보려고 노력한 내 자신에게 심심한 박수를 주었다.다음에 다시 할때는 한 클래스라도 더 추상화할 수 있을 것이라 생각한다.회고사실 강의도 섹션 5부터는 앞서가는 사람을 쫓아가려는 느낌으로 강의를 들었다. 그래서 그런지 DAY7 과제를 할때 내 생각만큼 추상화를 진행할 수 없었다. 영어를 배울대 읽기와 듣기가 되어도 쓰기와 말하기와 같이 출력하는 것은 다르듯이 실제로 코드를 적용하는 것은 쉽지 않은 일이었다.아직은 읽기와 듣기를 위해 열심히 지식을 입력하는 단계라고 생각한다. 이번 워밍업에서 한번에 다 이해할 수 있을 것이라 생각하지말고 한번 듣고 다음에 또 복습하고 적용해보는 시간을 꼭 가져야겠다.이번 발자국은 남기기 위해 작성했다면 다음 발자국은 남기고 싶어서 남기는 발자국이었으면 좋겠다.

백엔드백엔드워밍업클린코드

노을

[인프런워밍업클럽] 2주차 발자국 미션

섹션4 프로세스 동기화유닛 1 프로세스간 통신프로세스는 독립적으로 실행 or 다른 프로세스와 데이터를 주고 받으며 통신통신은 한 컴퓨터 내에서 실행되고 있는 다른 프로세스와 할 수도 있고, 네트워크로 연결된 다른 컴퓨터에 있는 프로세서와 할 수 도 있음종류한 컴퓨터 내에서 통신파일과 파이프파일통신을 하려는 프로세스들이 하나의 파일을 이용해 읽고 쓰는 방법파이프운영체제가 생성한 파이프를 이용해 데이터를 읽고 쓰는 방법스레드코드, 데이터, 힙 영역을 공유하고 스택만 각자 자기의 것을 가지고 있음데이터 영역에 있는 전역변수나 힙을 이용하면 통신이 가능네트워크운영체제가 제공하는 소켓통신이나 다른 컴퓨터에 있는 함수를 호출하는 RPC(원격 프로시저 호출)를 이용해 통신유닛2 공유자원과 임계구역공유자원프로세스 간 통신을 할 때 공동으로 이용하는 변수, 파일문제공유 자원은 여러 프로세스가 공유하고 있기 때문에 각 프로세스의 접근 순서에 따라 결과 달라짐컨텍스트 스위칭으로 시분할 처리를 하기 때문에 어떤 프로세스가 먼저 실행되고 어떤 프로세스가 나중에 실행되는지 예측하기 힘듦연상결과를 예측하기 힘들고 여기에 발생한 문제를 동기화 문제라고 함예) 게임을 예시로 듦캐릭터 총 체력 100, 현재 체력 20지금은 적에게 공격을 받고 있고 플레이어는 죽지 않기 위해 물약을 먹음이때 물약을 먹는 코드와 적에게 공격받는 코드에서 발생할 수 있는 동기화 문제를 살펴봄두 가지 코드가 동시에 실행됐는데 CPU 스케줄러에 의해 공격받는 코드가 먼저 실행됐다고 가정두번째임계구역여러 프로세스가 동시에 사용하면 안되는 영역경쟁조건공유자원을 서로 사용하기 위해 경쟁하는 것임계구역 문제 해결 방법상호배제의 메커니즘이 필요함요구사항주어진 시간에 항상 하나의 프로세스만 임계구역에 접근 가능동시에 여러개의 요청이 있더라도 하나의 프로세스만 진입하도록 허용임계구역에 들어간 프로세스는 최대한 빠르게 나와야함 → 다른 프로세스들이 오래 기다리기 떄문에유닛3 세마포어프로세스 : 프린트를 사용하려는 직원, 프린터는 여러 프로세스들이 같이 쓰고 있는 공유자원대기큐 : 프린트를 사용하기 위해 프로세스가 기다리는 공간운영체제 : 열쇠관리자세마포어 : 열쇠관리자가 들고 있는 열쇠, 정수형 변수사용법세마포어를 사용하면 공유자원에 여러 프소세스가 동시에 접근하지 못함 → 동기화 문제가 일어나지 않음세마포어는 실제로 여러개의 열쇠를 가질 수 있음정수형 변수, 공유자원이 2개라면 세마포어의 값은 2, → 열쇠 2개로 설정단점웨이트 함수와 시그널 함수의 순서를 이상하게 호출해서 세마포어를 잘못 사용할 수 있다는 가능성섹션5 데드락교착상태여러프로세스가 서로 다른 프로세스의 작업이 끝나기를 기다리다가 아무 작업도 진행하지 못하는 상태이유공유자원 때문에 발생어떤 자원을 여러개의 포로세스가 공유하지 않는다면 교착상태는 발생하지 않음예시) 식사하는 철학자필요조건상호배제 : 어떤 프로세스가 한 리소스를 점유했다면 그 리소스는 다른 프로세스에게 공유가 되면 안됨비선점 : 프로세스 A가 리소스르 점유하고 있는데 프로세스 B가 리소스를 뺏을 수 없음점유와 대기 : 어떤 프로세스가 리소스 A를 가지고 있는 상태에서 리소스 B를 원하는 상태여야만 함원형대기 : 점유와 대기를 하는 프로세스들의 관계가 원형을 이루고 있다는 것해결방법교착상태 회피프로세스들에게 자원을 할당할 때 어느 정도 자원을 할당해야 교착상태가 발생하는지 파악해서 교착상태가 발생하지 않는 자원을 할당함시스템의 총 자원 : 운영체제는 프로세스들에게 자원을 할당하기 전에 자기가 가지고 있는 전체 자원의 수를 알고 있어야 함최대 요구 자원 : 프로세스들은 각자 자기가 필요한 자원의 초대 숫자를 운영체제에게 알려줘야 함교착상태 알아내는 법가벼운 교착상태 검출타이머를 이용하는 방식, 프로세스가 일정시간동안 작업을 진행하지 않는다면 교착상태가 발생했다고 간주하고 교착상태를 해결무거운 교착상태 검출자원할당 그래프를 이용, 현재 운영체제에서 프로세스가 어떤 자원을 사용하는지 지켜보고 교착상태가 발생했다면 해결섹션 6 컴파일과 프로세스컴파일언어개발자가 코드 작성 → 컴파일 → 0과1 기계어로 실행파일 만듦인터프리터언어개발자가 작성한 코드를 미리 기계어로 만들지 않고 실행시 코드를 한 줄 씩 해석해 실행하는 언어프로세스의 메모리 구조스택 : 지역 변수, 함수 관련 값힙 : 실행 중 메모리 공간을 할당할 수 있는 유동적인 공간데이터 : 전역변수나 배열코드 : 실행해야 할 코드중간정리하드웨어, 운영체제 구조, 프로세스 회고운영체제는 강의를 듣고 복습을 하면 이해가 조금 잘 되는데 자료구조와 알고리즘은 이해하는데 시간이 많이 필요하다.. 복습을 더 많이 하고, 관련 서적들도 좀 찾아서 공부해야 할 것 같다

알고리즘 · 자료구조

워밍업 클럽 3기_PM/PO_2주차 발자국

강의 정보강의명: 시작하는 PM/PO들에게 알려주고 싶은, 프로덕트의 모든 것강사명: 김민우링크: https://inf.run/gQh4a강의 내용고객과 직접 만나야 하는 이유고객을 직접 만나는 것이 고객에 대한 이해를 높이는 가장 좋은 방법이다. 고객과 서비스에 대해 직접 문답하면서 고객이 가진 멘탈 모델을 정확하고, 구체적으로, 해상도 높게 가져갈 수 있다.중간 매개자로부터 받는 고객의 의견은 매개자의 시선에서 생략 및 요약되기 때문에 핵심 문제들을 놓치게 될 수 있다. 고객 리서치 방법의사결정을 명확하게 하고, 그에 맞는 리서치 방법과 계획을 세워야 한다.1:1 심층 인터뷰제품 사용 동기, 경험, 문제점 등에 대한 고객의 의견을 수집하는 방식이다.행동이 아니라 말에 의존해서 정보를 수집한다는 점을 유의해야 한다.인터뷰 대상은 10명을 기본으로 추천하나, 의사결정을 하기 충분한 답변을 모았다면 멈춰도 된다.사업>리서치>인터뷰로 질문을 만들고 준비해야 한다. 사업 상의 목적을 명확히 하고, 이를 알아가기 위해 필요한 리서치 방향을 생각한 뒤에 인터뷰 대상자가 답변 가능한 쉬운 질문으로 다듬어 가야 한다. 인터뷰 가이드 작성이 필요하다.답변은 유형화, 전반적인 테마를 발굴하여 중요 내용을 추려서 활용한다.사용성 테스트유저가 사용, 이해, 기능을 발견할 수 있는 제품이 좋은 제품이다.매몰 비용을 최소화하기 위해 사용성 테스트를 진행해야 한다.어림 법칙에 따라 5명 정도면 테스트는 충분하다. 그러나 유저 그룹에 여러 개라면 이를 고려하여 진행해야 한다.테스트 진행 시에는 2인 1조, 녹화 및 녹음이 필수이다.PM이 갖춰야 할 데이터 역량데이터 축적 역량과 활용역량이 필요하다.축적 역량은 로그 데이터를 설계하는 것을 의미한다.활용 역량은 지표를 이해하고 해석하는 것이다.데이터를 쪼개서 자세히 바라보는 연습이 필요하다.후기사용자의 의견을 듣기 위해 온라인 설문조사를 진행한 경험이 있었다. 그땐 가이드가 없어서 알고자 하는 목적에 집중해서 문항을 작성했는데, 지금 생각해 보니 너무 직접적인 질문이었던 것 같다. 목적을 선명히 해야 이후의 작업들을 펼치고 모을 수 있다는 것을 배웠다.국내가 아닌 국외 사용자들은 어떻게 심층 인터뷰나 사용성 테스트를 진행하는 게 좋을지 고민해 보게 되었다.데이터를 활용한 업무를 진행하기 위해서는 그런 환경이 놓인 회사에 가는 것이 필요하다는 이야기가 맘에 와닿았다. 데이터를 수집하기 위해서는 앞서 선행되어야 할 작업들이 많고, 후에 해석에도 많은 시간이 걸린다. 이를 낭비라고 생각하지 않는 회사로 가려면 면접에서 어떤 것을 확인해 봐야 하는 지 궁금해졌다. 미션앱 고도화 작업 이후에 특정 기능을 활용하는 사용자의 수가 감소한 사례가 있었다. 경험한 사례를 기준으로 고객 조사 방법을 설계해보려 한다.  

기획 · PM· PO워밍업클럽3기

안지수

[워밍업 클럽] CS 전공지식 2주차 발자국

운영체제프로세스 동기화공유 자원 : 프로세스 간 통신을 할 때 공동으로 이용하는 변수나 파일들임계 구역(Critical Section) : 여러 프로세스가 동시에 사용하면 안되는 영역경쟁 조건(Race Condition) : 공유 자원을 서로 사용하기 위해 경쟁하는 것상호 배제(Mutual Exclusion) : 임계 구역 문제 해결하기 위한 메커니즘상호 배제 요구사항1. 임계영역엔 동시에 하나의 프로세스만 접근한다.2. 여러 요청에도 하나의 프로세스의 접근만 허용한다.3. 임계구역에 들어간 프로세스는 빠르게 나와야한다.세마포어 : 상호 배제 메커니즘/정수형 변수/동기화 방지/잘못 사용할 가능성 있음모니터 : 세마포어 단점 해결한 상호 배제 메커니즘/프로그래밍 언어 차원에서 지원(예: 자바의 synchronized)데드락데드락(교착상태) : 여러 프로세스가 서로 다른 프로세스의 작업이 끝나기를 기다리다가 아무도 작업을 진행하지 못하는 상태/공유자원 때문에 발생교착상태의 필요조건 상호배제비선점점유와 대기원형 대기 교착상태 회피(Deadlock avoidance) - 은행원 알고리즘교착상태 검출가벼운 교착 상태 검출 : 타이머 이용무거운 교착 상태 검출 : 자원 할당 그래프 이용자료구조재귀어떠한 것을 정의할 때 자기 자신을 참조하는 것재귀 함수는 호출할 때마다 콜스택의 영역을 차지기저 조건(탈출 조건)이 반드시 있어야하위 문제의 결과를 기반으로 현재(상위) 문제 계산하는 데 유용(하향식 계산) 회고칭찬하고 싶은 점강의를 듣고 주력 언어인 자바로 복습하고 있다.아쉬웠던 점계획보다 진도가 밀려서 목표한 학습량을 채우지 못한 점보완하고 싶은 점공부한 내용을 나의 언어로 정리해서 발행하기(Output 만들기)

삼각커피포리

[인프런 워밍업 스터디 클럽 3기] 디자인 2주차 발자국

🐾 두번째 발자국개인적인 일정으로 평일에 시간이 많이 나지 않았고, 업데이트 된 입력 컴포넌트 강의 분량이 늘어나면서 시간이 많이 소요한 주차였다. 그래도 매일 조금씩 들었는데 이번주 분량을 모두 듣지 못 한 것 같아서 개인적으로 매우 아쉬운 주차였다. 📚 배운 점FrameAll 플러그인으로 모든 프레임을 쉽게 선택할 수 있다.아이콘은 오픈소스 아이콘을 사용하여 시간을 단축할 수 있다. 아이콘 미션아이콘이 이상한 경우 가장 추천하는 정리 방법은 Union → Flatten Selection아이콘을 10배 크기로 키워서 픽셀이 어긋난 부분을 화살표를 이용하여 위치를 조절하여 수정해두고 다시 10배 축소 시켜서 정리하면 깔끔하다.입력 컴포넌트 미션Q를 누르면 multi-edit이 가능해서 컴포넌트 편집 시 유용하다.버튼 스택 파트가 추가 되었는데 그 전에 버튼을 각각 만들어서 썼던 경험이 떠올라서 왜 이런 생각을 못했지 싶었다.한 번 컴포넌트를 만들어두면 다음 컴포넌트에서 반복적으로 사용되는 것들이 많다.😊 좋았던 점입력 컴포넌트 미션에서 각 컴포넌트 별로 설명과 만들어야 하는 Type, Style, State 같은 프로퍼티 값이 섹션에 쓰여 있어서 동영상을 보며 놓쳤던 것을 쓰여진 것을 보면서 확인 할 수 있었다.복습임에도 불구하고 내용이 업데이트 되어 새로 강의를 듣는 것과 같았다.전에는 라이브로 진행했던 앤트맨 작전이 강의에 업데이트 되어 복습할 수 있어서 좋았다. 😭 아쉬웠던 점매일매일 조금씩 강의를 듣고 multi-edit을 사용하며 과제를 했는데도 입력 컴포넌트 미션에 시간이 많이 소요되었다. (그래도 보너스 미션까지 완료했다!)이번주에는 미션4와 미션5를 해야하는데 시간이 부족하여 미션4만 수행할 수 있었다. 

UX/UI피그마Figma피그마배리어블

양종문

워밍업 클럽 3기 BE 클린코드&테스트 - 2주차 발자국

Reable Code 강의 요약섹션 6. 코드 다듬기주석의 양면성주석이 많다는 것은, 그만큼 비즈니스 요구사항을 코드에 잘 못 녹였다는 이야기.코드를 설명하는 주석을 쓰면, 코드가 아니라 주석에 의존한다. 주석에 의존하여 코드를 작성하면, 적절하지 않은 추상화 레벨을 갖게 되어 낮은 품질의 코드가 만들어진다.우리가 가진 모든 표현 방법을 총동원해 코드에 의도를 녹여내고, 그럼에도 불구하고 전달해야 할 정보가 남았을 때 사용하는 주석변수와 메서드의 나열 순서변수는 사용하는 순서대로 나열한다.공개 메서드를 상단에 배치하는 것을 선호하는 편.공개 메서드끼리도 기준을 가지고 배치하는 것이 좋다.상태 변경 >> 판별 >= 조회 메서드비공개 메서드는, 공개 메서드에서 언급된 순서대로 배치한다.공통으로 사용하는 메서드라면, (가장 하단과 같은) 적당한 곳에 배치한다.패키지 나누기패키지는, 문맥으로써의 정보를 제공할 수 있다.패키지를 쪼개지 않으면 관리가 어려워진다.패키지를 너무 잘게 쪼개도 마찬가지로 관리가 어려워진다.처음 만들 때부터 잘 고민해서 패키지를 나눠놓는 것이 제일 좋다.IDE의 도움 받기코드 포맷 정렬 (Ctrl + Alt + L)코드 품질 (Sonarlint)포맷 규칙 (.editorconfig)   섹션 7. 리팩토링 연습 스터디 카페 이용권 선택 시스템리팩토링 포인트추상화 레벨객체로 묶어볼만한 것은 없는지객체지향 패러다임에 맞게 객체들이 상호 협력하고 있는지SRP : 책임에 따라 응집도 있게 객체가 잘 나뉘어져 있는지DIP : 의존관계 역전을 적용할만한 곳은 없는지일급 컬렉션리팩토링 한 단계마다, 그 이유를 설명할 수 있어야 한다. 섹션 8. 기억하면 좋은 조언들능동적 읽기복잡하거나 엉망인 코드를 읽고 이해하려 할 때, 리팩토링하면서 읽기공백으로 단락 구분하기메서드와 객체로 추상화 해보기주석으로 이해한 내용 표기하며 읽기핵심 목표는 우리의 도메인 지식을 늘리는 것. 그리고 이전 작성자의 의도를 파악하는 것.오버 엔지니어링필요한 적정 수준보다 더 높은 수준의 엔지니어링은탄환은 없다클린 코드도 은탄환이 아니다.모든 기술과 방법론은 적정 기술의 범위 내에서 사용되어야 한다. 미션 (Day7)지금까지 배운 내용을 기반으로 리팩토링 진행결과: https://github.com/iPhone-design/readable-code/pull/1 과정추상화 레벨 리팩토링Early return 리팩토링DIP 리팩토링 아쉬운점새로운 도메인을 도출하는 과정에서 많은 어려움을 겪었습니다. 도메인 모델을 명확히 정의하고 적절한 개념을 추출하는 작업이 예상보다 복잡하고 까다로워 리팩토링에 많은 시간이 소요되었습니다. 또한, 리팩토링 과정에서 새로운 버그가 유입되거나 기존 기능이 손상되는 등의 부작용도 발생하여 기대만큼 만족스러운 결과를 얻지 못한 점이 아쉬웠습니다. 특히, 도메인을 명확히 정의하고 코드의 책임을 명확히 분리하는 클린 코드의 기본 원칙과 사고방식을 더욱 깊이 이해하고 습관화할 필요가 있다고 생각합니다. 앞으로는 작은 단위로 점진적으로 리팩토링을 진행하고, 자동화된 테스트를 적극적으로 활용하여 코드의 품질과 안정성을 높이도록 노력해야겠다 느꼈습니다.Pratical Testing 강의 요약섹션 2. 테스트는 왜 필요할까?우리가 얻고자 하는 것빠른 피드백자동화안정감테스트 코드를 작성하지 않는다면변화가 생기는 매순간마다 발생할 수 있는 모든 Case를 고려해야 한다.변화가 생기는 매순간마다 모든 팀원이 동일한 고민을 해야 한다.빠르게 변화하는 소프트웨어의 안정성을 보장할 수 없다.테스트 코드가 병목이 된다면프로덕션 코드의 안정성을 제공하기 힘들어진다.테스트 코드 자체가 유지보수하기 어려운, 새로운 짐이 된다.잘못된 검증이 이루어질 가능성이 생긴다.올바른 테스트 코드는자동화 테스트로 비교적 빠른 시간 안에 버그를 발견할 수 있고, 수동 테스트에 드는 비용을 크게 절약할 수 있다.소프트웨어의 빠른 변화를 지원한다.팀원들의 집단 지성을 팀 차원의 이익으로 승격시킨다.가까이 보면 느리지만, 멀리 보면 가장 빠르다.테스트는 귀찮다. 귀찮지만 해야 한다. 섹션 3. 단위 테스트단위 테스트작은 코드 단위를 독립적으로 검증하는 테스트검증 속도가 빠르고, 안정적이다.JUnit 5단위 테스트를 위한 테스트 프레임워크AssertJ테스트 코드 작성을 원활하게 돕는 테스트 라이브러리풍부한 API, 메서드 체이닝 지원테스트 케이스 세분화하기암묵적이거나 아직 드러나지 않은 요구사항이 있는가?테스트 케이스 세분화하기 (해피 케이스, 예외 케이스)테스트하기 어려운 영역을 구분하고 분리하기관측할 때마다 다른 값에 의존하는 코드현재 날짜/시간, 랜덤 값, 전역 변수/함수, 사용자 입력 등외부 세계에 영향을 주는 코드표준 출력, 메시지 발송, 데이터베이스에 기록하기 등 섹션 4. TDD: Test Driven DevelopmentTest Driven Development프로덕션 코드보다 테스트 코드를 먼저 작성하여 테스트가 구현 과정을 주도하도록 하는 방법론실패하는 테스트 작성 > 테스트 통과 최소한의 코딩 > 구현 코드 개선 테스트 통과 유선 기능 구현, 후 테스트 작성테스트 자체의 누락 가능성특정 테스트 케이스만 검증할 가능성잘못된 구현을 다소 늦게 발견할 가능성선 테스트 작성, 후 기능 구현복잡도가 낮은, 테스트 가능한 코드로 구현할 수 있게 한다.쉽게 발견하기 어려운 엣지(Edge) 케이스를 놓치지 않게 해준다.구현에 대한 빠른 피드백을 받을 수 있다.과감한 리팩토링이 가능해진다. 섹션 5. 테스트는 문서다.문서프로덕션 기능을 설명하는 테스트 코드 문서다양한 테스트 케이스를 통해 프로덕션 코드를 이해하는 시각과 관점을 보완어느 한 사람이 과거에 경험했던 고민의 결과물을 팀 차원으로 승격시켜서, 모두의 자산으로 공유할 수 있다.DisplayName을 섬세하게명사의 나열보다 문장으로테스트 행위에 대한 결과까지 기술하기도메인 용어를 사용하여 한층 추상화된 내용을 담기테스트의 현상을 중점으로 기술하지 말 것BDD(Behavior Driven Development) 스타일로 작성하기TDD에서 파생된 개발 방법함수 단위의 테스트에 집중하기보다, 시나리오에 기반한 테스트케이스(TC) 자체에 집중하여 테스트한다.개발자가 아닌 사람이 봐도 이해할 수 있을 정도의 추상화 수준(레벨)을 권장Given / when / then 발작국 2주차 회고이론으로만 접하고 있었던 부분을 실제 리팩토링 실습을 통해 더욱 피부로 와닿게 느낄 수 있었습니다. 특히, 직접 코드를 개선하는 과정에서 이론과 실무 간의 차이를 명확히 이해할 수 있었고, 클린 코드와 리팩토링의 중요성을 더욱 깊이 깨닫게 되었습니다. 또한 이번 주는 다른 개발자분들의 코드를 함께 리뷰하고 피드백을 주고받는 시간을 통해 다양한 접근법과 사고방식을 경험할 수 있었던 의미 있는 시간이었습니다. 혼자서는 생각하지 못했던 다양한 관점과 해결책을 알게 되었고, 협업을 통한 코드 리뷰의 중요성도 다시금 느끼게 되었습니다. 더불어 두 번째 강의에서 다루었던 테스트 코드의 중요성 또한 다시 한번 상기하게 되었습니다. 리팩토링 과정에서 테스트 코드가 얼마나 중요한 역할을 하는지 실질적으로 체감할 수 있었으며, 앞으로 테스트 코드 작성 능력을 향상시키기 위해 더욱 노력해야겠다는 생각이 들었습니다.

백엔드워밍업클럽

이제

[인프런 워밍업 클럽 스터디 3기 디자인] 2주차 발자국

2주 차 - 학습했던 내용 요약피그마 베리어블과 스타일 파운데이션 실습을 저번 주차에 이어서 작업했고 이번주는 컴포넌트들을 만드는 법에 대해 배웠t습니다. 목표한 진도까지는 아직 나가지 못해서 다음주에 조금 더 시간내서 과제랑 마무리해보려고 합니다. [주요 내용 복습] [이론📖] 간격 배리어블 이름, 구조 짜기일관성 있는 간격과 유연한 레이아웃을 구축하기 위해 그리드를 사용1.5배수 랜더링 이슈로 주로 8-point grid를 사용함일반적으로 더 작은 단위로 레이아웃을 정렬하고 싶은 경우 4-point grid를 사용함+1.5배수 랜더링 이슈란?1.5배수 렌더링 이슈란?1.5배수는 1픽셀을 1.5배 크기로 변환해야 하는데, 픽셀은 소수점 단위로 정확히 나눌 수 없는 정수 단위의 단위라서 렌더링 시 오류가 발생할 가능성이 높음.✅ 예제:10px 크기의 요소를 1.5배수 스케일로 렌더링 → 10 × 1.5 = 15px하지만 15px을 정확히 2배 또는 3배 해상도에 맞출 수 없음결과적으로 픽셀 보정(Anti-aliasing) 과정에서 모호한 렌더링(Blurry)이 발생그래서 8pt 그리드를 사용하는 이유8pt 그리드는 모든 크기를 8의 배수(8, 16, 24, 32...)로 설정하는 디자인 시스템.8의 배수를 사용하면, 2배수(2x)나 3배수(3x)와 같은 정수 배율에 정확히 맞출 수 있어서 렌더링 오류를 방지 가능!✅ 예제:8px → 2x 스케일 적용 → 8 × 2 = 16px (정확히 나눠짐)8px → 3x 스케일 적용 → 8 × 3 = 24px (정확히 나눠짐)8px → 1.5x 스케일 적용 → 8 × 1.5 = 12px (정수 단위로 맞춰짐)→ 1.5배수에서 발생하는 반올림 문제를 최소화할 수 있음.[이론&실습] 그리드 시스템과 반응형 기준점 설정하기 ✅break pointmobile(320-767)Count4 stretch Margin:16 Gutter: 16{FluidRange: 320-767} tablet(768-1023)Count8 stretch Margin:24 Gutter: 24{fluiderange: 768-1023} laptop(1024-1415)Count12 stretch Margin:24 Gutter: 24{fluiderange:1024-1415} desktop(1424-)Count12 center W:96 Gutter: 24{Fixedrange:1416-} Grid 적용 후 구현 plugin:Layout Grid Visualizer2주 차 - 회고2주 차에는 1주차 내용을 거의 복습하고 마무리했고 컴포넌트 수업도 조금 듣는 정도로 진도를 나갔습니다. 요즘 ai에게 물어보면서 수업을 정리해가고 있는데 더 머리에 잘 들어오고 좋은 것 같아 좋은 것 같은데 진도가 스케쥴 보다는 많이 뒤쳐지고 있는것 같아서 다음주에 조금 더 많이 진행해보려고 합니다. 아직 진행을 많이 못했지만 컴포넌트 실습 부분이 정말 유익한 것 같은데 많이 연습해봐야 할 것 같습니다. +완성된 배리어블을 Variable Print 로 문서화 했는데 완성작의 문서들이랑 조금 다른 것 같아서 다시 복습해봐야 할 것 같습니다. 인프런 워밍업 클럽 스터디 - 후기유익하고 과제일자가 정해져 있으니 확실히 스터디에 속도가 나는 것 같아서 좋은 것 같습니다. 앞으로도 열심히 진행해보려고 합니다.

UX/UIUXUIfigma디자인시스템베리어블

Berry

[인프런 워밍업 클럽 스터디 3기] 프로덕트 디자인 2주 차 발자국

2주 차 강의 회고아쉬웠던 점 / 보완하고 싶은 점 / 다음 주 계획수업과 과제를 더 열심히 해야하는데 그부분이 아쉽습니다. 다음 주에는 학습한 내용을 더 많이 반복하고, 실제 상황에 적용해보는 연습을 할 계획입니다. 이해안가는 부분도 다시 공부하고, 실무에서 어떻게 활용할 수 있을지 구체적으로 생각하며 학습할 예정입니다.2주 차 미션 해결 과정이번 미션에서는 주어진 강의 내용에 따라 컴포넌트 만들기 준비, 라이브러리 세팅, 디스플레이 및 입력 컴포넌트들을 활용한 실습을 진행했습니다. 반복 학습을 통해 더욱 확실하게 이해하였습니다.특히 버튼, 체크박스, 라디오 버튼, 스위치와 같은 기본적인 컴포넌트들을 실제로 사용하면서, 아이콘 등록과 UI 스타일링도 함께 실습한 점이 중요했습니다. 이러한 컴포넌트들은 실제 프로젝트에서 자주 사용되기 때문에, 실제 프로젝트에서 바로 적용할 수 있는 능력을 키우는 데 큰 도움이 되었습니다. 미션을 해결하는 과정에서 강의 내용을 실무에 바로 적용할 수 있도록 학습하는 점이 인상 깊었습니다.이번 주 학습을 통해 실무에서 사용할 수 있는 기술들을 체계적으로 연습했고, 앞으로도 더 깊이 있는 학습을 통해 실력을 쌓아 나갈 예정입니다. 2주 차 주요 학습 내용컴포넌트 만들기 준비: 기본적인 컴포넌트 구조 설계, 라이브러리 세팅입력 컴포넌트: 버튼, 체크박스, 라디오 버튼, 스위치 등디스플레이 컴포넌트: 아바타, 아코디언, 배지, 툴팁, 칩 등실제 활용: UI 요소를 실무에 맞게 커스터마이징하였습니다.이번 주 학습을 바탕으로, 다음 주에도 실무에서 바로 활용할 수 있는 능력을 키우기 위해 꾸준히 실습하고, 더 심화된 내용을 공부할 준비를 하려고 합니다.

UX/UI

채널톡 아이콘