🎁 모든 강의 30% + 무료 강의 선물🎁

블로그

pej4303

[인프런워밍업클럽3기 BE] 1주차 발자국

1. 강의강의 진도 : 섹션2 ~ 섹션 31.1 학습 내용JPA(Java Persistence API)JDBC처럼 다형성을 기반으로 DB가 달라져도 소스 코드를 거의 수정하지 않아도 된다.자바 표준 ORM내부적으로 JDBC API를 이용한다.@Entity class Achievement( title: String , description: String , achievedDate: LocalDate? , host: String , isActive: Boolean): BaseEntity() { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "achievement_id") var id: Long? = null var title: String = title var description: String = description var achievedDate: LocalDate? = achievedDate var host: String = host var isActive: Boolean = isActive }엔티티 클래스테이블과 매핑되는 자바 클래스를 의미한다.기존 VO(Value Object)와 동일한 개념이다.보통 테이블명 동일한 이름을 사용한다.@Entity엔티티 클래스를 의미한다.이름이 중복되어서는 안된다.name속성을 생략하면 클래스명이 엔티티명이 된다.@Table엔티티와 매핑될 테이블을 설정한다.엔티티명과 테이블명 다를경우에만 지정해주면 된다.@IdPK 컬럼인 경우에만 사용한다.@GeneratedValue PK를 자동으로 생성해준다.방법GenerationType.IDENTITYMySQL의 Auto Increment 기능을 지원하는 DB에서만 가능하다.Oracle 12g 이상 버전도 사용 가능하다.GenerationType.SEQUENCE시퀀스를 지원하는 DB에서만 사용이 가능하다.GenerationType.TABLEDB 종류와 상관없이 사용 할 수 있는 방법이다. GenerationType.AUTO(기본값)DB의 특성에 맞게 알아서 적용해준다.연관관계 매핑 @OneToMany1:N 관계를 맺을 때 사용한다.@ManyToOneN:1 관계를 맺을 때 사용한다.N:M관계에서는 @OneToMany 쪽에서 mappedBy를 설정하고 @ManyToOne 쪽에서 @JoinColumn을 설정해야 한다. 코틀린 기본 문법변수 선언val불변 변수, 자바의 final 변수와 비슷하다.var변경 가능한 변수기본 데이터 타입val number: Int = 42 val pi: Double = 3.14 val isKotlinFun: Boolean = true val letter: Char = 'A' val text: String = "Hello, Kotlin!"null처리var name: String? = null // null 허용 println(name?.length) // null이면 실행하지 않음 println(name?.length ?: 0) // null이면 0 반환 1.2 느낀 점올해 목표였던 코틀린 학습을 실천하게 되어 뿌듯하다. 새로운 언어인 코틀린을 직접 사용해보니 흥미로웠고 재미있었다.다음 주에는 평일마다 최소 1시간씩 꾸준히 강의를 듣는 것을 목표로 삼고자 한다.2. 미션2.1 깃허브 리포지토리에 올리기인프런에서 만든 리포지토리만 따로 모으고 싶어서 서브트리를 이용해서 프로젝트를 추가하였다.URL : https://github.com/pej4303/inflearn-pjt/tree/main/kotlin-missionGit Subtree메인 레포지토리와 함께 관리되고 프로젝트마다 독립적인 커밋 관리가 가능하다.2.2 느낀 점서브트리를 처음 이용해봐서 찾아보고 설정하느라 시간이 좀 걸렸다. 그래도 내가 원하는 기능이 되어서 기분이 좋았다. 출처https://www.inflearn.com/course/%EC%9E%85%EB%AC%B8%EC%9E%90-spring-boot-kotlin-%ED%8F%AC%ED%8A%B8%ED%8F%B4%EB%A6%AC%EC%98%A4/dashboard

백엔드발자국인프런워밍업클럽

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

학습 내용 요약추상읽기 좋다는 것은 결국 이해하기 쉽다는 것이다.추상과 구체에 대해서 배웠다.이름은 줄이지 않고, 단수와 복수를 구분해서 작성한다.하나의 메서드에는 하나의 주제만 담는다.메서드 내 로직의 추상화 레벨을 통일한다.숫자나 문자열 대신 상수나 enum을 사용한다. 논리, 사고의 흐름Early return을 적용하여 중첩 if문을 풀어내는 방법을 배웠다.! 와 같은 부정어를 메서드로 빼서 두번 생각하지 안도록 사고의 depth를 줄이자. 객체 지향 패러다임객체를 설계하는 방법과 SOLID를 코드로 구현하였다. 미션Day - 2추상과 구체에 대한 미션을 받았는데 생각해보다가 앉아있었던 의자에 대해서 작성하였다.Day - 4주어진 코드를 리팩토링하고 SOLID에 대해서 자기만의 언어로 설명하는 미션이었다.SOLID를 나만의 언어로 정리하니 이해가 더 잘된 부분이 있었다. 마무리예전에 했던 토이 프로젝트 코드를 다시 보면서 클린 코드의 중요성을 절실히 깨달았다.프로젝트를 진행할 당시에는 어차피 혼자 하는 작업이고, 코드 한 줄 이라도 더 빨리 작성하는 게 우선이었기 때문에 클린 코드에 대해 깊이 생각하지 않았다. 하지만 나중에 새로운 기능을 추가하거나 기존 코드를 이해하려고 할 때, 예상보다 훨씬 어렵다는 걸 느끼면서 자연스럽게 클린 코드에 관심을 갖게 됐다.관심이 생기고 나니 '어떻게 공부해야 하지?' 하는 고민이 들었고, 우선 이해하기 좋은 강의부터 찾아 듣기 시작했는데 확실히 좋았다.

백엔드

미션 1주차

운영체제 while(true){ wait(1); // 1초 멈춤 bool isActivated = checkSkillActivated(); // 체크 } 1. 위 코드는 1초 마다 플레이어가 스킬을 사용했는지 체크하는 코드입니다. 이 방식은 폴링방식입니다. 1초마다 체크하기 때문에 성능에 좋지 않습니다. 이를 해결하기 위한 방식으로 어떤 걸 이용해야 할까요? -> 인터럽트를 사용한다. 인터럽트는 자신의 상태가 바뀔 때 CPU에 통보해주는 기법이다 프로그램과 프로세스가 어떻게 다른가요?-> 프로그램 : 저장장치(HDD,SSD 등)에 저장되어 특정 작업을 수행하는 명렁어 모음 프로세스 : 메모리에 탑재되어 실행중인 프로그램 멀티프로그래밍과 멀티프로세싱이 어떻게 다른가요?->멀티프로그래밍 : 메모리 위에 여러 개의 프로그램을 실행시켜 처리하는 것 멀티프로세싱 : 두 개 이상의 프로세서(CPU)가 각 프로세스를 처리하는 것 운영체제는 프로세스를 관리하기 위해서 어떤 것을 사용하나요?-> 관리하고자 하는 프로세스의 정보를 가지고 있는 PCB를 만들고 저장한다 컨텍스트 스위칭이란 뭔가요?->실행되어야할 프로세스를 변경하기 위해 기존 프로세스의 정보를 PCB에 저장하고 실행될 프로세스의 PCB 내용대로 작업하는 것  자료구조와 알고리즘 여러분은 교실의 학생 정보를 저장하고 열람할 수 있는 관리 프로그램을 개발하려고 합니다. 이 때 여러분이라면 학생의 정보를 저장하기 위한 자료구조를 어떤 걸 선택하실 건가요? 이유를 함께 적어주세요. -> 한번 정해진 교실의 학생들은 추가/삭제가 빈번하지 않기 때문에 연결리스트가 효율적이다 교실의 학생 수는 언제든지 바뀔 수 있기 때문에 미리 많은 공간을 마련해둬야 하는 해시테이블과 크기가 고정되어 있는 배열은 비효율적이다  여러분은 고객의 주문을 받는 프로그램을 개발하려고 합니다. 주문은 들어온 순서대로 처리됩니다. 이 때 여러분이라면 어떤 자료구조를 선택하실 건가요? 이유를 함께 적어주세요.-> Queue를 사용한다 FIFO방식으로 먼저 온 손님을 먼저 계산해줄 수 있기 때문 우리가 구현한 스택은 0번 인덱스, 즉 입구쪽으로 데이터가 삽입되고 나오는 구조입니다. 반대로 마지막 인덱스, 즉 출구쪽으로 데이터가 삽입되고 나오는 구조로 코드를 변경해주세요.-> LinkedList의 insertLast , deleteLast 함수를 사용한다import { LinkedList } from "./linkedList.mjs"; class Stack { constructor() { this.list = new LinkedList(); } push(data) { this.list.insertAt(0, data); } insertLast(data) { this.list.insertLast(data); } deleteLast() { return this.list.deleteLast(); } pop() { try { return this.list.deleteAt(0); } catch (e) { return null; } } peek() { return this.list.getNodeAt(0); } isEmpty() { return this.list.count === 0; } } export { Stack };   해시테이블의 성능은 해시 함수에 따라 달라집니다. 수업 시간에 등번호를 이용해 간단한 해시 함수를 만들어봤습니다. 이번엔 등번호가 아닌 이름을 이용해 데이터를 골고루 분산시키는 코드로 수정해주세요. 힌트: charCodeAt() 함수를 이용 예시: name1 = "이운재"; name1.charCodeAt(0); // 51060 이운재의 0번 인덱스 ‘이’의 유니코드 출력hashFunction(name){ return name.charAt(0) % 10; }

yeajinny

[워밍업 클럽 CS 3기] 1주차 미션

운영체제 while(true){ wait(1); // 1초 멈춤 bool isActivated = checkSkillActivated(); // 체크 } 위 코드는 1초 마다 플레이어가 스킬을 사용했는지 체크하는 코드입니다. 이 방식은 폴링방식입니다. 1초마다 체크하기 때문에 성능에 좋지 않습니다. 이를 해결하기 위한 방식으로 어떤 걸 이용해야 할까요? 인터럽트 방식으로 전환해야 할 것 같습니다. 주기적으로 매번 체크를 수행하지 말고, ISR 방식처럼 Skill이 Activate 됐을때 인터럽트가 발생하도록 동작을 바꿔서 성능을 높여야 할 것 같습니다. 프로그램과 프로세스가 어떻게 다른가요?프로그램은 하드 디스크에 저장된 명령문의 집합체이지만 프로세스는 실행중인(메모리에 올라간 상태) 프로그램입니다.이에 따라서 프로그램은 단순 집합체라 수동적이지만 프로세스는 능동적으로 필요에 따라 CPU를 사용하고 입력 출력을 하는 양상을 보입니다. 멀티프로그래밍과 멀티프로세싱이 어떻게 다른가요?멀티 프로그래밍은 메모리에 여러개의 프로세스 올려서 처리하는 반면에 멀티 프로세싱은 여러개의 CPU를 사용해서 서로 다른 프로세스를 짧게씩 실행하며 동시에 처리하는것처럼 보이게 합니다.운영체제는 프로세스를 관리하기 위해서 어떤 것을 사용하나요?운영체제는 프로세스의 정보를 가진 PCB(Process Control Block)를 생성해서 프로세스의 정보를 저장하고, CPU 스케쥴링 시에도 프로세스의 상태를 저장하고 관리합니다. 컨텍스트 스위칭이란 뭔가요?다른 프로세스 실행을 위해 프로세스 상태를 저장하고 다른 프로세스 상태값으로 교체하는 것을 말합니다. 자료구조와 알고리즘 여러분은 교실의 학생 정보를 저장하고 열람할 수 있는 관리 프로그램을 개발하려고 합니다. 이 때 여러분이라면 학생의 정보를 저장하기 위한 자료구조를 어떤 걸 선택하실 건가요? 이유를 함께 적어주세요. 해시테이블을 사용할 것 같습니다. 직관적으로 저장하려면, 학생에게 학번을 부여하거나 아니면 가나다 순의 이름으로 정렬할 것 같은데 학번일 경우에는 해시 함수를 사용해서 번호가 골고루 인덱스에 분배될 수 있도록 나누거나 ㄱ,ㄴ,ㄷ등의 자음으로 인덱스를 구성해서 학생의 정보를 저장할 것 같습니다. 각 학생의 이름, 나이, 취미, 특기와 같은 자세한 정보들도 해시테이블에 인덱스를 구성해 저장하기 좋을 것 같습니다. 여러분은 고객의 주문을 받는 프로그램을 개발하려고 합니다. 주문은 들어온 순서대로 처리됩니다. 이 때 여러분이라면 어떤 자료구조를 선택하실 건가요? 이유를 함께 적어주세요.주문은 들어온 순서대로 처리되어야 하므로, FIFO 방식의 큐를 사용하되, 감자튀김 단일 주문 같은걸 패티가 3개 들어간 버거 때문에 너무 늦게 처리 할 수 없으므로 동시에 들어온 주문일 경우 조리 시간이 오래 걸리는 순서대로 스택에 넣어서 짧은 조리시간을 가진 주문부터 처리 할 것 같습니다. 우리가 구현한 스택은 0번 인덱스, 즉 입구쪽으로 데이터가 삽입되고 나오는 구조입니다. 반대로 마지막 인덱스, 즉 출구쪽으로 데이터가 삽입되고 나오는 구조로 코드를 변경해주세요.push(data){ this.list.insertLast(data); } pop(){ try{ return.this.list.deleteLast(); } catch(e) { return null; } }링크드리스트에 deleteLast, insertLast함수가 구현되어있기 때문에 그 함수를 그대로 사용했습니다. 해시테이블의 성능은 해시 함수에 따라 달라집니다. 수업 시간에 등번호를 이용해 간단한 해시 함수를 만들어봤습니다. 이번엔 등번호가 아닌 이름을 이용해 데이터를 골고루 분산시키는 코드로 수정해주세요. 힌트: charCodeAt() 함수를 이용 예시: name1 = "이운재"; name1.charCodeAt(0); // 51060 이운재의 0번 인덱스 ‘이’의 유니코드 출력hashFunction(name){ }hashFunction(name){ return (name.charCodeAt(0) + name.charCodeAt(1)) % 10; }한국에는 특정 성씨, 특히 예시에 나온 이씨와 같은 성씨가 많아서 단순 성씨로 하면 한 곳에 많이 몰릴 것 같아서 두번째 글자까지 더하는 연산으로 구현했습니다.

CS워밍업클럽

별안간뿌우

[인프런 워밍업 클럽_3기 백엔드 프로젝트]1번째 발자국

웹은 클라이언트와 서버로 구성되어있다.클라이언트 : 요청하는 주체서버: 응답하는 주체 (CRUD)데이터베이스 : 데이터의 집합데이터베이스관리시스템:DBMS도메인 주소: WWW.NAVER.COMDNS서버 : 전화번호부 같은 역활DNS서버->해당하는 IP주소를 알려줌-> IP로 다시 요청->다시 크롬으로 응답프레임워크:틀이 정해져있음라이브러리 : 공구상자MVC 패턴레이어드 아키텍쳐 : controller -> service->Repository<->db스프링 bean과 의존성 주입(dependency lnjection)@controller @Service @Repository스프링 컨테이너라는 곳에서 컴포넌트 스캔으로 의존성 주입을 이용한다.의존성 주입에는 3가지 방법이 있다생성자 주입, 수정자, 필드 방식필드가 깔끔하긴 하지만 생성자 주입이 안전하다이미 들어가 있는 의존성을 다른 곳에서 쓸 수 있는 가능성이 있어서순환참조 예방http엔 상태코드 값이라는 것이 있다.200~500까지 해당되는 숫자의 메시지가 다르다.restAPI데이터베이스유일성과 최소성을 만족해야 하는 것 : pkjpa 자바 orm 기술의 표준 인터페이스트랜잭션 : 데이터베이스 작업을 하나로 묶어주는 논리적 단위입니다.영속성 컨텍스트jpa에서 엔티티를 관리하는 임시 메모리, 버퍼와 같은 개념.패키지 구조entity 자바객체들이 들어갈 패키지<미션1 git에 프로젝트 올리기>미션은 깃에 레퍼지토리만들기인데.일단 인텔리제이에서프로젝트에서 commit 이라는 단어를 누른 후마우스 오른쪽 버튼을 눌러 addvcs를 클릭한 후 커밋을 누른다.그 후 깃에 가서 레퍼지토리를 만들고그 주소를복사하여 git->mange remote버튼을 클릭하여 git 주소를 입력하면 된다상단에 git의 master라고 되어 있는 부분을 main으로 바꿔 주고git->commit and push 버튼을 눌러주면 해당 프로젝트로 git에 업로드 된다.강의 프로젝트의 기본 패키지 구성은domain->constant->entity->repository로 구성되어 있다.엔티티 안에 기본 뼈대인 추상 클래스를 하나 만들고그 클래스를 상속하는 뼈대의 테이블 구조와 같게 만든다그리고 레퍼지토리 또한 테이블 구조와 같게 만든다.아직 이 개념이 익숙하지 않아 무지성으로 따라하는 중이다.코틀린에선 var라는 것을 사용하는데분명 자바스크립트에서는 권고하지 않는다 라며 사용을 권장하지 않고 let이라는 것을 사용하도록 유도했다근데 코틀린은 조금 다른 것인가 궁금증이 든다그리고 내가 미처 생각하지 못했는데 난 코틀린을...해본적이 없었다이걸 신청하고 나서 깨달았다.물론 자바나 스프링 모든 걸 다 할 순 있지만. 해본 적 없는 것을 한다고 한 내 호기로움이 제법 무섭기도하다.그리괴 인텔리제이에서 일대다 다대일의 매핑을 해주는어노테이션이 있는 것이 너무 신기하고 사용하기 좋은 거 같다.아직 제대로 한 것이 없어서 반성이나 고쳐야 할 점 보단. 일단 따라가기에 너무 급급했던 것 같다.특히 난 이클립스를 주로 쓰고 인텔리제이는 많이 안 써봐서 낯설고 단축키에 대한 연습이 더 필요할 거 같다그리고 git에 푸시를 할 때 처음엔 무조건 에러나고 두번째엔 되는데 이 현상 또한 왜 그런지 한 번 살펴볼 필요가있을 거 같다.    

웹 개발

[인프런 워밍업 클럽_3기 CS] 1주차 운영체제 미션

운영체제 while(true){ wait(1); // 1초 멈춤 bool isActivated = checkSkillActivated(); // 체크 } 위 코드는 1초 마다 플레이어가 스킬을 사용했는지 체크하는 코드입니다. 이 방식은 폴링방식입니다. 1초마다 체크하기 때문에 성능에 좋지 않습니다. 이를 해결하기 위한 방식으로 어떤 걸 이용해야 할까요? cpu가 입출력 관리자에게 interrupt를 주어서 해당 프로세스 작업을 멈춘 후 다른 작업을 실행한다.입출력 작업이 끝난다면 입출력 관리자는 cpu에게 신호를 보내고, cpu는 진행중인 프로세스 작업이 끝난 후 해당 프로세스를 실행한다.   프로그램과 프로세스가 어떻게 다른가요? 프로그램은 저장장치에 있는 하나의 application을 의미하고 (명령문 집합체)이 프로그램이 저장장치로부터 메모리에 올라와서 작업을 실행중이면 프로세스라고 말한다.   멀티프로그래밍과 멀티프로세싱이 어떻게 다른가요?멀티 프로그래밍은 메모리에 여러개의 프로세스를 올려서 작업하는 것을 의미하고멀티 프로세싱은 메모리에 올라온 프로세스들을 여러개의 cpu로 작업을 처리하는 것을 의미한다.   운영체제는 프로세스를 관리하기 위해서 어떤 것을 사용하나요? Process Control Block 을 사용한다.   컨텍스트 스위칭이란 뭔가요?운영체제가 스케줄링을 통해 CPU를 할당 할 프로세스를 바꾸는 작업을 말한다.

찬우 이

인프런 워밍업 클럽 3기 풀스택 - 1주차 발자국

1주차 학습 내용Firebase vs SupabaseFirebase 특징BaaS: 서버 없이도 빠르게 앱 출시 가능커뮤니티, 문서화 잘되어 있음, 단순한 NoSQL 기반으로 돌아감Supabse보다 비쌈, 오픈소스 아님NoSQL기반이라 복잡한 쿼리 불가하고, 웹 개발엔 그닥,, Supabase 특징오픈소스 구성, PostgreSQL 기반다양한 연동 방식을 지원함커뮤니티, 문서화 부족비교적 적은 기능 Server Action서버에서 실행되는 비동기 함수API 호출 없이 서버에서 바로 데이터 변환 메타데이터SEO를 정의하는 방식Static과 Dynamic 방식이 있는데 추 후 더 배울 예정Tailwindcss<div class="bg-blue-500 text-white p-4 rounded-lg shadow-lg"> 테일윈드 CSS 예제 </div>유틸리티 퍼스트(Utility-First) 방식의 CSS 프레임워크로, 미리 정의된 클래스를 조합하여 빠르게 스타일을 적용할 수 있도록 도와준다.CSS를 직접 작성할 필요 없이 클래스만 조합하여 스타일링 가능 RecoilReact에서 상태 관리를 쉽게 할 수 있도록 도와주는 상태 관리 라이브러리Redux 같은 라이브러리보다 가볍고 사용법이 간단함전역 상태뿐만 아니라 컴포넌트 간의 상태 공유를 효율적으로 관리할 수 있음비동기 상태 관리도 지원하여 서버 데이터를 다룰 때도 유용함  React Query React Query는 비동기 데이터(fetching, caching, synchronization)를 효율적으로 관리하는 라이브러리다.서버 상태 관리에 특화되어 있으며, API 호출 후 데이터를 캐싱하고 자동으로 최신 상태를 유지할 수 있도록 도와준다.React에서 API 요청을 효율적으로 관리하려면 필수적인 라이브러리다.1주차 미션1주차 미션에서는 강의에서 배운 TODO 앱을 기반으로,새로 생성한 TODO는 생성된 시간(created_at)을 표시하고,수정한 TODO는 수정된 시간(updated_at)을 즉시 UI에 반영하도록 구현하는 것이 목표였다. // ui.tsx const createTodoMutation = useMutation({ mutationFn: () => createTodo({ title: "New TODO", completed: false, created_at: new Date().toISOString(), }), onSuccess: () => { todosQuery.refetch(); }, });✅ useMutation을 통해 새로운 TODO를 생성할 때, created_at을 추가하여 서버에 요청하도록 구현했다.✅ 이를 통해 TODO가 생성된 시간을 함께 저장할 수 있도록 설정했다. // todo.tsx const [updatedTime, setUpdatedTime] = useState(todo.updated_at); const updateTodoMutation = useMutation({ mutationFn: () => updateTodo({ id: todo.id, title, completed, updated_at: updatedTime, }), onSuccess: () => { setIsEditing(false); queryClient.invalidateQueries({ queryKey: ["todos"], }); }, }); ---------------------- <> <p className={`flex-1 ${completed && "line-through"}`}>{title}</p> <p> {new Date(todo.updated_at ?? todo.created_at).toLocaleString( "ko-KR", { year: "numeric", month: "2-digit", day: "2-digit", hour: "numeric", minute: "2-digit", hour12: true, } )} </p> </>✅ 수정할 때마다 updated_at을 추가하여 최신화된 시간을 서버로 전송하도록 설정했다.✅ 수정된 TODO(updated_at)가 있다면 수정 시간을, 그렇지 않다면 생성 시간(created_at)을 표시하도록 구현했다.✅ 기본적으로 ?? 연산자를 사용해 updated_at이 존재하는 경우 이를 우선적으로 표시하도록 처리했다.✅ 시간 포맷이 "2025.03.09 오후 7:34" 형식으로 나타나도록 toLocaleString()을 활용해 변환했다.  1주차 회고 내가 이 강의를 수강한 이유는 배우고 싶었던 Recoil, React Query, Supabase를 익히기 위해서였다.하지만 생각보다 많이 어려웠다. 역시 한 번 본다고 해서 쉽게 익힐 수 있는 건 아니라고 느꼈다.섹션 2까지는 본격적인 실습을 하기 전에 준비 단계라고 생각했다.그리고 섹션 3부터는 본격적으로 TODO 프로젝트를 만들면서 학습을 진행했다.Supabase를 사용하면서 백엔드의 기본적인 동작 방식을 조금이나마 이해할 수 있었다.신기하기도 했지만, 한편으로는 어렵기도 했다.미션 자체는 그렇게 어렵다고 느껴지지는 않았다.결국 등록 시간과 수정 시간을 표현하는 것이 핵심이었기 때문이다.하지만 강의에서 React Query나 Supabase를 다루는 부분은 이해가 잘되지 않아 여러 번 반복해서 학습해야 할 것 같다.어려워서 살짝 우울하기도 하지만...결국 어려운 만큼 성장할 수 있는 부분이 많다는 뜻이니까! 😂🔥

풀스택풀스택미션인프런워밍업클럽supabasenext.js

인프런 워밍업 클럽 스터디 3기 - Frontend <1주 발자국>

자바스크립트 기초Console 객체콘솔 객체는 브라우저의 디버깅 콘솔에 접근할 수 있는 메서드를 제공한다. 동작 방식은 각 브라우저마다 다르지만 사실상 표준으로 여겨지는 기능도 여럿있다.console 객체는 아무 전역 객체에서나 접근할 수 있다.호이스팅로컬 범위의 맨 위로 끌어올려지는 것을 의미한다. var 선언은 undefined가 할당 되지만 let, const 선언은 할당이 되지 않는다.Window 객체 및 DOMwindow 객체는 브라우저에 의해 생성된다.DOM문서 객체 모델은 웹 페이지 문서 구조를 트리구조로 표현해서 웹 브라우저가 html 페이지를 인식하게 해준다.브라우저가 트리구조로 만든 객체 모델을 의미한다.dom api를 통해서 dom을 조작할 수 있다.브라우저가 만든 document 객체는 쿼리셀렉터 같은 메소드를 제공한다.Intersection observer브라우저 뷰포트와 설정한 요소의 교차점을 관찰하며, 요소가 뷰포트에 포함되는 지 안되는지 구별하는 기능을 제공비동기로 발생하는데 scroll같은 이벤트 기반 요소 관찰에서 발생하는 렌더링을 성능이나 이벤트 연속 호출 같은 문제없이 사용한다.Pure Function함수형 프로그래밍 패러다임의 한 부분같은 입력값이 주어졌을 때 같은 값을 리턴하고 사이드 이펙트를 만들지 않는 함수사용 이유클린 코드를 위해테스트를 쉽게 하기 위해디버그를 쉽게 하기 위해독립적인 코드를 위해 (Decoupled, Independent)다른 함수에 미치는 영향을 최소화 하고 어떤 결과값을 리턴하는지 알게된다.커링(Currying Function)js가 아닌 다른 언어에도 존재하는 기술f(a,b,c)처럼 단일 호출로 처리하는 함수를 f(a)(b)(c)와 각각의 인수가 호출 가능한 프로세스로 호출된 후 병합될 수 있게 변환하는 것커링은 함수를 호출하는 것이 아닌 변환하는 것이다.const sum = (x,y) => x + y; ​ const curriedSum = x => y => x + y; ​ console.log(sum(10,20)) console.log(curriedSum(10)(20))const makeFood = (ingredient1) => {  return (ingredient2) => {    return (ingredient3) => {     return `${ingredient1} ${ingredient2} ${ingredient3}`   } } }function log(date, importace, mesage) {  alert(`[${date.getHours()} ${date.getMinutes()} ${importance} ${message}]`) }function curry(f) {  return function (a) {    return function (b) {      return function (c) {        return f(a,b,c)     }   } } } ​ const curriedLog = curry(log) curriedLog(new Date())("DEBUG")("some bud")function curry (func) {  return function curried(...args) {    if (args.length > ) } }strict mode제한된 버전을 선택하여 암묵적인 느슨한 모드를 해제하기 위한 방법이다.엄격 모드는 무시되던 에러를 발생시킨다.최적화된 작업을 어렵게 만드는 실수들을 바로 잡는다."use strict"<script src="./script" type="module"></script>OOP객체지향 프로그래밍은 여러 개의 독립된 단위 "객체"들의 모임으로 컴퓨터 프로그램을 파악한다.하나의 문제 해결을 위한 독립 단위인 객체로 만들었으며 객체로 알아보기 쉽고 재사용성이 높은 코드를 작성한다.자료 추상화자료 추상화는 불필요한 정보를 숨기고 중요한 정보를 표현하여 프로그램을 간단하게 만드는 것이다.상속새로운 클래스가 기존의 클래스의 자료와 연산을 이용할 수 있게 하는 기능이다.다형성한 요소에 여러 개념을 넣어 놓는 것같은 메서드라도 인스턴스에 따라 다양한 기능을 수행할 수 있는 것캡슐화클래스 안에서 관련 메서드 변수 등을 하나로 묶는 것 javascript prototypelet user = {  name : "john",  age : 45 } console.log(user.hasOwnProperty("age"))정의하지 않은 메서드는 어디에서 생기는 걸까?프로토 타입은 자바스크립트 객체가 다른 객체로부터 메서드와 속성을 상속받는 메커니즘을 말한다. 이를 프로토타입 체인 (prototype chain)이라고 한다.이로 인해 더 적은 메모리를 사용할 수 있고 코드를 재사용 할 수 있다.ES6 Classesclass를 통해 OOP를 구현할 수 있다.실제 내부에서는 prototype을 사용하여 작동된다.constructor는 인스턴스 생성과 필드의 생성과 초기화를 의미한다.this는 클래스가 생서알 인스턴스constructor는 new에 의해 자동으로 호출된다.static은 인스턴스 메서드가 아닌 독립적으로 사용되는Sub Class(Inheritance)슈퍼클래스의 속성을 서브 클래스에서 확장하여 사용할 수 있다.class parentClass {   } class childClass extends parentClass { constructor () {    super() }   } ​super()인스턴스화된 객체에서 다른 메서드를 호출하기 전에 주행해야 하는 사용자 지정 초기화를 제공super 키워드는 자식 클래스 내에서 부모 생성자를 호출할 때 사용된다.소감기본적인 js 문법 보다는 oop 개념과 제가 몰랐던거 위주로 학습하였습니다.

인프런 프론트엔드 워밍업 클럽 3기 1주차

대학교 개강을 맞아 공부와 병행을 해야하다보니 모든 과제를 다 할 수 없었다. 하지만 최대한 진도를 따라잡고자 노력해보겠다. 이번 주는 1일차와 2일차 과제 밖에 끝내지 못했다. 인프런 워밍업 진도표를 보니 많은 양을 단시간 내에 습득하고 응용해내야 하는 것 같았다. JS는 어느 정도 할 수 있지만 리액트는 거의 처음이라 잘 해낼 수 있을지 막막하다. 하지만 그래도 최선을 다해서 지식을 얻어가보겠다.  학습 요약 1일차 : 섹션 2 ~ 4대부분 아는 내용들이였기에 따로 정리를 하지는 않아서 새로 배운 것들 위주로 정리해보겠다. 이벤트event bubbling : html 내의 요소들을 밑에서부터 올라오는 것event capturing : html 내의 요소들을 위에서부터 밑으로 내려오는 것event delegation : 하위요소의 이벤트들을 상위 요소에 위임하여 관리하는 것  2일차 : 섹션 5 (절반)2일차부터는 모르는 것들이 조금씩 나오기 시작해서 메모를 좀 해두었다. ThisMethod : 객체함수 : 윈도우 객체화살표함수 : 상위 스코프의 this를 가리킴 ; Lexical thiscall 메소드 : 함수를 호출하는 함수, 첫번째 매개변수로 어떤 것을 전달해주면 호출되는 함수의 this에 window객체가 아니라 전달받은 것을 보냄.const fullName = function(city, country){ console.log(this.firstName + ' ' + this.lastName, city, country); } const person1 = { firstName: "John", lastName : "Smith" } fullName.call(person1, 'oslo', 'Norway'); //출력 값 : John Smith Oslo Norway apply 메소드 : call 메소드와 매우 유사. 하지만 뒤에 인자를 넣어줄 때 각각 넣어주는 것이 아니라 배열로 넣어줌.const fullName = function(city, country){ console.log(this.firstName + ' ' + this.lastName, city, country); } const person1 = { firstName: "John", lastName : "Smith" } fullName.apply(person1, ['oslo', 'Norway']); //출력 값 : John Smith Oslo Norway bind 메소드 : 바로 함수를 직접 호출 해주는 것이 아닌 바인딩만 해주고 해당 값은 다른 변수에 저장해서 실행시켜줘야 함.function func(language){ if(language === "kor){ console.log(`language: ${this.korGreeting}`); } else { console.log(`language: ${this.engGreeting}`); } } const greeting = { korGreeting : '안녕', engGreeting : 'Hello' } const boundFunc = func.bind(greeting); boundFunc('kor') //출력값 : language : 안녕 동기 VS. 비동기동기 (Synchronous) : 시간을 맞춤. 1부터 4까지의 단계가 있다면 전 단계가 끝나기 전까지 넘어갈 수 없음비동기 (Asynchronous) : 시간을 맞추지 않음. 1부터 4까지 단계별로 하지 않아도 됨. 동시에 다른 걸 한다던지 순서 상관없이 해도 됨.얕은비교 vs 깊은비교얕은 비교 : 단순히 값만 비교. 객체나 배열 같은 경우에는 위치를 저장하기 때문에 비교  학습 회고 : 시간이 많이 없었다는 변명을 해보지만, 그래도 하루에 1시간 정도는 할애할 수 있었지 않나 싶다. 주말에 몰아서 하려니 양이 많아 엄두가 나질 않는다. 다음주부터는 하루에 과제 하나를 못하더라도 강의만큼은 따라 잡아 보려고 노력해볼 것이다. 하다보니 시간도 없고 다 하지 못할 것 같아서 벌써부터 중도포기를 해야하나 걱정했는데, 벌써 포기하기엔 너무 이른 것 같아서 하는 데까지 해보기로 결심했다. 일주일을 살다보면 가끔 스스로 타협해서 쉬엄쉬엄 가자고 합리화하게 되는데, 이 클럽이 나태해지지 않게 도와주는 것 같아 신청하길 잘 한 것 같다.    미션 요약1일차 : 음식 메뉴 앱CSS는 거의 하지 않았고 기능 자체에만 집중했다. 오랜만에 js를 공부하니까 뇌가 굳어서 이 과제를 하는데 꽤나 많은 시간이 걸렸다. CSS를 다시 하려니 기능도 다 까먹어서 기억을 더듬거리면서 했다. 푸는 과정은 단계별로 천천히 했다.기본적인 틀 만들기음식 배열 만들기음식 양식대로 출력하기필터링 하기 2일차 : 가위바위보 앱가위바위보 앱부터는 CSS를 살짝 더 하면서 했더니 과제물이 훨씬 볼만해졌다.기본적인 틀 만들기이벤트 리스너 생성가위바위보 함수 생성innerHTML 사용해서 횟수 및 점수 업데이트최종 결과 구현 

프론트엔드워밍업클럽FE프론트엔드

인프런 워밍업 클럽 CS 3기 1주차 미션 (자료구조와 알고리즘)

자료구조여러분은 교실의 학생 정보를 저장하고 열람할 수 있는 관리 프로그램을 개발하려고 합니다. 이 때 여러분이라면 학생의 정보를 저장하기 위한 자료구조를 어떤 걸 선택하실 건가요? 이유를 함께 적어주세요. 해시 테이블을 이용할 것 같습니다. 해시 테이블의 경우 데이터의 삽입, 삭제, 접근, 수정이 O(1)의 성능을 가지기 때문에 매우 빠르지만 좋은 해시함수를 선정할 필요가 있으며 공간 효율성이 낮습니다. 하지만 교실의 학생 수는 많아봐야 40명이기에 메모리 공간을 크게 걱정하지 않아도 되며 학생번호를 순서대로 부여받기 때문에 간단한 해시 함수를 사용해도 해시 테이블 내의 key에 value가 고르게 분배될 것입니다. 또한 앞서 적었듯이 해시 테이블은 데이터 접근, 삽입, 삭제가 굉장히 빠르기 때문에 전학같은 이슈 발생 시에도 유연하게 대처가 가능합니다. 여러분은 고객의 주문을 받는 프로그램을 개발하려고 합니다. 주문은 들어온 순서대로 처리됩니다. 이 때 여러분이라면 어떤 자료구조를 선택하실 건가요? 이유를 함께 적어주세요. FIFO의 특징을 가지는 Queue를 사용할 것입니다. DoublyLinkedList를 이용하면 Stack, Queue, Deque, hashTable을 비교적 쉽게 적용할 수 있으므로 구현은 DoublyLinkedList를 기반으로 하는 것이 좋을 것 같습니다.  우리가 구현한 스택은 0번 인덱스, 즉 입구쪽으로 데이터가 삽입되고 나오는 구조입니다. 반대로 마지막 인덱스, 즉 출구쪽으로 데이터가 삽입되고 나오는 구조로 코드를 변경해주세요.import { LinkedList } from '../LinkedList/linked_list.mjs'; class Stack { constructor() { this.LinkedList = new LinkedList(); } /** * 스택에 데이터 삽입 * @param {number} data */ push(data) { this.LinkedList.insertLast(data); } /** * 스택에서 데이터를 삭제하고 반환 * @returns {Node} */ pop() { try { return this.LinkedList.deleteLast(); } catch (error) { return null; } } /** * 스택의 맨 위 데이터를 반환 * @returns {Node} */ peek() { return this.LinkedList.getNodeAt(0); } /** * 스택이 비어있는지 확인 * @returns {boolean} */ isEmpty() { return this.LinkedList.count == 0 ? true : false; } } export { Stack };  해시테이블의 성능은 해시 함수에 따라 달라집니다. 수업 시간에 등번호를 이용해 간단한 해시 함수를 만들어봤습니다. 이번엔 등번호가 아닌 이름을 이용해 데이터를 골고루 분산시키는 코드로 수정해주세요. 힌트: charCodeAt() 함수를 이용 예시: name1 = "이운재"; name1.charCodeAt(0); // 51060 이운재의 0번 인덱스 ‘이’의 유니코드 출력hashFunction(input){ let changed = input.charCodeAt(0) + input.charCodeAt(1); return changed % 5; } /* 결과값 4 0 2 3 2 0 4 2 3 0 1 */ 

알고리즘 · 자료구조

김보민

[인프런 워밍업 클럽 3기 - 백엔드 프로젝트] 1주차 발자국

인프런 워밍업 클럽이 시작되었다..!평소 코틀린 + 스프링에 관심이 있었는데 좋은 기회로 참여할 수 있어서 너무 좋다.🤗또 평소 nestjs만 사용했어서 스프링은 처음이라 기대가 되었다. ✅ 강의1주차 강의는 이론 위주였다.강의에서 같이 만들 프로젝트를 미리 살펴보았다.웹과 데이터베이스 개발 기본 개념에대해서 다루었다.프로젝트 초기 세팅과 엔티티 뼈대를 만들었다.코틀린 문법, 나아가 자바 문법도 안쓴지 오래되어서 따라가기 벅차지 않을까 걱정했는데 강의에서 간단한 문법만 사용하고, 잘 설명해주셔서 문제없었다. 또 진행하면서 스프링의 동작에 대해서도 알아갈 수 있어서 참 좋았다. 스프링이 처음이어서 강사님이 설명해주시는 내용애 대해 강의 자료에도 있지만, 그보다 더 자세하게 나만의 강의 노트에 정리했다.강의 진도에 밀리지 않고 미리 듣고 과제를 할 때 생각하는 시간을 더 갖자는게 목표였는데, 첫주차 강의는 진도보다 미리 다 들어서 목표 달성에 성공했다. 하지만 이 2주차에도 이어가려면 지금 발자국을 작성하는 이 시간에도 진도가 나가있어야하는데 많이 나가진 못해서 아쉽다. 이 발자국을 다 작성하고 나서 더 공부할 것이다.ㅎㅎ ✅ 미션1주차 미션은 두가지 였다.[미션1] 깃허브 리포지토리에 프로젝트 올리기[미션2] 테이블 설계하기 [미션1]은 강의에서 코틀린 프로젝트를 만들어본 것과 똑같이 프로젝트를 생성하고 올리기만하면 되어서 간단했다. 그보다 어떤 프로젝트를 할 지 고민이 많았는데, 평소 음악을 좋아해서 플레이리스트 공유 서비스 프로젝트로 선택했다. 비슷한 프로젝트를 프론트로서 참여한 적이 있는데 백엔드 입장에서 설계해보면 또 다른 느낌일 것 같다는 이유도 있다. [미션2]는 테이블 설계였다. 먼저 사용자는 여러개의 플레이리스트를 만들 수 있다는 1대다 관계에서 시작했다.그런데 음악 데이터는 어떻게할지 고민이되었다. 일단 사용자와 플레이리스트 관계에 집중하고 음악 데이터는 초기 DB에 gpt 등을 이용해 데이터를 추출해 가지고 있기로 결정했다. 그렇게 member(사용자), Track(음원), Playlist(플레이리스트)의 새 개의 테이블을 먼저 설계했다. 하지만 설계하다보니 고민거리가 있었다.member -> playlist (1:N)사용자(member) 와 플레이리스트(playlist) 간의 관계를 설계할 때, 처음에는 member 테이블에도 playlist의 FK를 두는 것을 고려했었다. 하지만 이럴 경우 member가 여러 플레이리스트를 가질 때마다 동일 사용자의 정보가 중복되어 여러 행이 생성된다. 그래서 member가 아닌 playlist 테이블 쪽에만 member의 FK를 두는 형태로 수정했다.  playlist <-> track (N:M)  playlist에 여러 track_id가 여러개 물릴 수 있으니 해당 테이블에 같은 id로 여러 행이 반복되었다. 따라서 playlist_id와 track_id를 FK로 가지는 중간 테이블 Track_Playlist를 만들게되었다. 중간 테이블이 생기니 playlist와 track 테이블에 중복되는 데이터가 사라졌다.🍀 마무리인프런 워밍업 클럽 1주차가 마무리되었다. 2주차 부터는 강의도 과제도 본격적으로 개발에 들어가게된다. 더 열심히 참여할 수 있도록 해야겠다! 화이팅!

백엔드인프런워밍업클럽3기

강현

인프런 워밍업 클럽 스터디 3기 - 백엔드 코드 1주차 발자국

강의 수강섹션2. 추상평소 개발 공부를 하면서 "추상화를 해야한다"를 막연히 알고 있을 뿐 진지하게 생각해본 적이 없는 것 같다.추상과 구체, 그 사이에 추상화 레벨이 존재한다는 것을 배웠다.특히 코딩테스트할 때 변수명으로 count 대신 cnt를 많이 선택했는데, 클린 코드에서는 권장하지 않는다는 내용에 뜨끔했다.섹션3. 논리, 사고의 흐름코드를 이해하기 위해 사용하는 뇌 메모리를 적게 써야한다는 것을 배웠다.중첩 for문은 줄일 수 있으면 좋다는 내용은 알고 있었다. 하지만 if문, else if문, else문 구조와 부정어를 많이 사용했고 이런 코드가 좋지 않은 코드인지 알지 못했다.어려운 방법이 아니니까 앞으로 프로그래밍할 때 부터 적용해봐야겠다.섹션4. 객체 지향 패러다임👍 SRP : 하나의 클래스는 단 하나의 책임만을 가져야 한다.👍 OCP : 확장에는 열려있고 수정에는 닫혀있어야 한다.👍 LSP : 부모 클래스를 자식 클래스로 바꿀 수 있어야 한다.👍 ISP : 필요한 인터페이스만 제공해야 한다.👍 DIP : 구현 클래스말고 인터페이스에 의존해야 한다.섹션5. 객체 지향 적용하기👍 상속보단 조합 이용한다.👍 VO는 식별자가 없지만, Entity는 식별자가 존재한다.👍 변경이 너무 잦으면 Enum보단 DB로 관리한다.👍 추상화와 다형성 활용해서 반복되는 if문 제거한다. 미션Day2먼저 추상화와 구체에 대한 개념을 머릿속에서 정리해보았다. 이후 일상에서 떠오르는 구체와 추상화의 예시를 떠올리며 추상의 레벨에 대해서도 생각해보았다.Day4코드를 살펴보며 내가 적용할 수 있는 early return, 중첩 반복문 제거와 메소드 분리 등을 하나씩 차례로 적용해보았다. SOLID의 원칙을 강의에서 적용한 코드를 살펴보며 내가 다시 봤을 때 잘 알아볼 수 있는 한마디로 표현하고자 생각하는 시간을 가질 수 있었다. 나중에 동료가 스파게티 코드를 짜면 멋지게 고쳐주는 개발자가 되고 싶다.

백엔드

동동

[인프런 워밍업 클럽_3기 CS] 1주차 자료구조와 알고리즘 미션 🐾

자료구조와 알고리즘1. 여러분은 교실의 학생 정보를 저장하고 열람할 수 있는 관리 프로그램을 개발하려고 합니다.이 때 여러분이라면 학생의 정보를 저장하기 위한 자료구조를 어떤 걸 선택하실 건가요?이유를 함께 적어주세요.해시테이블을 사용할 것이다. 학생의 정보 검색에 있어 O(1)의 성능을 제공하여 효율적이다. 2. 여러분은 고객의 주문을 받는 프로그램을 개발하려고 합니다. 주문은 들어온 순서대로 처리됩니다. 이 때 여러분이라면 어떤 자료구조를 선택하실 건가요? 이유를 함께 적어주세요.Queue(큐)를 사용할 것이다. 주문은 FIFO 방식으로 처리 되어야하기에 Queue가 적합하다. 3. 우리가 구현한 스택은 0번 인덱스, 즉 입구쪽으로 데이터가 삽입되고 나오는 구조입니다. 반대로 마지막 인덱스, 즉 출구쪽으로 데이터가 삽입되고 나오는 구조로 코드를 변경해주세요.class Stack {   constructor() {     this.list = new LinkedList();   }   push(data) {     this.list.insertAt(this.list.count, data);   }   pop() {     try {       return this.list.deleteAt(this.list.count - 1);     } catch (e) {       return null;     }   }   peek() {     return this.list.getNodeAt(this.list.count - 1);   }   isEmpty() {     return this.list.count === 0;   } } 4. 해시테이블의 성능은 해시 함수에 따라 달라집니다. 수업 시간에 등번호를 이용해 간단한 해시 함수를 만들어봤습니다. 이번엔 등번호가 아닌 이름을 이용해 데이터를 골고루 분산시키는 코드로 수정해주세요. 힌트: charCodeAt() 함수를 이용 예시: name1 = "이운재"; name1.charCodeAt(0); // 51060 이운재의 0번 인덱스 ‘이’의 유니코드 출력hashFunction(name) { return name.charCodeAt(0) % 10; }

인프런워밍업클럽CS

인프런-워밍업-클럽-3기-FE 발자국 1주차

1주차 강의 : 따라하며 배우는 자바스크립트 - John Ahn님 1주차 강의 범위 및 과제 달성자바스크립트 기초 : Section 2 ~ 4 / 음식 메뉴 앱 만들기 ✅자바스크립트 중급 (1) : Section 5 (1 ~ 8) / 가위 바위 보 앱 만들기 ✅자바스크립트 중급 (2) : Section 5 (9 ~ 17) / 퀴즈 앱 만들기 ✅OOP, 비동기 : Section 6 ~ 7 / 책 리스트 나열 앱 / Gihub Finder 앱 만들기 ❌ 학습FE로 취업을 꿈꾸면서 강의를 열심히 들었던 것 같다.JS에 대한 지식이 별로 없던 나에게는 단비 같은 강의로 너무 알찬 구성이었다.다만 짧은 시간 내에 미션까지 완료하고 싶다는 마음이 압박으로 다가오기도 해서 하나하나 강의 내용을 완벽하게 숙지하지 못했다는 아쉬움이 남았다. 잘 이해가 되지 않았거나 기억이 잘 안나는 내용은 클럽 수료 이후 다시 반복해 들을 생각이다.미션HTML, CSS에 대한 지식이 가물가물한 상태에서 강의를 듣고 앱 만들라는 미션을 봤을 때는 내가 할 수 있을까 라는 생각이 먼저 들었지만, 막상 미션을 시작해보니 HTML 내용과 CSS 내용이 어렴풋이 기억나게 되었고, 목표 학습 강의에서 배운 위주로 하려고 노력했다. HTML, CSS, JS 전부 익숙하지 않아 미션에 많은 시간을 할애하게 되었지만, 결과물이 나올 때는 큰 만족감을 얻을 수 있었다. 미션.1 음식 메뉴 앱 만들기 미션 시작하면서 가장 좋아하는 음식은 엽기 떡볶이 메뉴판을 만들어보고 싶었고,기능 부분을 구현하기 전에 HTML과 CSS로 기본 틀 먼저 구현했다.(제목, 버튼, 메뉴 위치 등) js 구현시 menu에 들어갈 종류가 너무 많아 타이핑하는데 고생했다.. (고생했다.. 손가락아...) 코드 작성시간보다 다양한 메뉴 등록 (토핑, 사이드 칸 등....)에 시간이 더 많이 소요됐던 미션이었음...map(), filter() 함수도 적용해서 구현 해봤고, 중간 중간 오타나, class 명 불일치로 작동 안되던 것을 수정했다.보여지는 것 먼저 하는 것이 편한지, 기능 부분 구현 먼저 편한지 아직까지 잘 모르겠음.. 그리고 과제 하는데 시간을 너무 많이 잡아먹었다.. 다시 똑같이 작성해보라고 하면 자신이 없음...비슷한 앱을 여러번 만들어 보면서 문제를 보고 구현할 HTML 코드와 기능 부분 코드 생각 정리와 실제 구현 시간을 줄이는 연습하려고 한다. 미션.2미션 영상을 보고 가위, 바위, 보 이미지를 선택한 값과 이에 대응되는 컴퓨터의 값에 따라 이미지가 보여지면 좋겠다고 생각했다. 그리고 게임에서 남은 횟수의 값을 불필요하다 느껴 먼저 10점 점수를 획득한 사람이 최종 승리하는 것을 목표로 구현했다. rock, paper, scissors 구현 코드는 이전에 다른 프로그래밍 언어로 구현해본적이 있어 비교적 쉽게 구현을 했다.코드 구현시 이미지가 안나오는 경우가 있어 코드를 보니 playGame 함수 코드 안에 넣지 않아서 작동이 안되었던 것, 수정 후 이미지 출력 잘됨 미션.3시간을 많이 잡아먹은 미션... HTML은 간단하게 하고 JS에 좀 더 투자한 미션이다html이 간단하다 보니 js 기능 구현에 따른 결과가 직관적으로 보여지지 않아서 힘들었던 미션이다... 아직 html과 js 코드 구현 자체에 어려움을 느끼다보니 기능 구현 하나하나 작성하는데 수월하지는 않았다.코드자체는 구현할 기능들을 먼저 정리하고 바로 구현 가능한 부분은 구현, 도움이 필요한 부분은 검색을 통해 보완했다.강의에서 배운 삼항연산자와, IIFE도 미션에 적용하려고 노력했다. 1주차 회고일 끝나고 강의듣고 미션을 진행하려고하니 시간이 빠듯한 느낌이 들었다... 개인 일정(청모, 캠핑 등)도 미리 잡혀 있는게 있다보니 강의만 목표치만큼 듣고 미션을 할 수 있는 만큼 하려고 했다.강의 내용은 알찼지만 알찬 내용을 내 머리에 온전히 담아내기에는 학습투자 시간이 현저히 적었던것 같다. 역시 반복이 답이라 생각해 클럽이 끝나더라도 잘 이해 안가는 부분은 반복해서 들어야겠다. 1주차 회고는 강의 듣는거에 급급해 각 내용에 대한 정리와 궁금사항 해결을 잘 해결하지 못한 주차였다.2주차 때부터는 각 강의에 대한 회고와 미션 진행시 에러 부분과 해결 부분에 대해 좀 더 자세한 기록이 목표이다.

[워밍업클럽3기] Backend 1주차 발자국

Section 02. 추상추상: 뽑을 추 & 코끼리 상(형상 상)구체적 정보에서 어떠한 이미지를 뽑아냄wiki정의 : 사물을 정확하게 이해하기 위해서 사물이 지니고 있는 여러가지 측면 가운데서 특정한 측면만을 가려내어 포착하는 것이다. 어떤 일면만을 추상하는 것은 다른 측면을 버린다는 것과 같다.추상은 항상 구체적인 실재에서 시작해야한다..추상화 과정.. 빅뱅이론에서 쉘든은 추상화가 덜되었고, 보통사람은 추상화가 잘된느낌??추상화가 덜되어서 자꾸 뭐든 설명하려들고, 나머지사람들은 추상화가 잘되어 그렇게까지 디테일하게 말하지 않는 느낌? 예시) 추상: 너 만나기 전에 배가 고파서 먼저 밥먹었는데, 너는 밥 먹었니? 구제: 너와 00시에 만나기로 하였는데, 00시부터 나의 위에서 아무것도 없기 때문에 내 뇌로 배고프다는 신호를 보내주었기 때문에 나의 뇌가 무언가를 먹어야 한다는 신호를 보내어 집안의 냉장도를 열어서 음식을 찾아서 내 입에서 저작작용을 거쳐 식도를 지나 위로 넘어가는 일(=밥먹음)을 하고 왔는데, 너도 그런 일(=너도 먹음?)을 하고 왔니?추상: 심플, 구제: 구구절절 ?추상: 핵심만 담아 짧고 간결하게 표현하는 것. (효율 극대화)구제: 하나하나 풀어서 최대한 자세하게 설명하는 것. (비효율적)Method: 두개이상의 일을 하지 않도록 노력할 것!! 생략할 정보와 의미를 부여하고 드러낼 정보 구분해야함반환 타입 매서드명 (파라미터) {매서드구현부}<method name: 매서드명>추상화된 구체를 유추할 수 있는, 적절한 의미가 담긴 이름파라미터와 연결지어 더 풍부한 의미를 전달 할 수도 있음.<Parameter: 파라미터>파라미터의 타입, 개수, 순서를 통해 의미 전달외부세계와 소통하는 창임!외부세계로 method를 작성한 사람이 읽는 사람, 사용하는 사람으로 하여금 내가 뭘 할지 보여주는 것.<반환타입>method signature에 납득이 가는, 적절한 타입의 반환값 돌려주기.반환타입이 boolean의 경우 참거짓임.void 대신 충분히 반환할 만한 값이 있는지 생각해 볼것.반환값이 있다면 테스트가 용이해짐.void = 반환값이 없음을 의미. "값을 반환하지 않는다"의 의미.추상화는 코드의 양이 중요하다기 보다는 의미가 중요함!!! Section 03. 논리, 사고의 흐름사고의 depth 줄이기보이는 depth를 줄이는 것이 아니라 "사고과정의 depth"를 줄이는 것이 중요함.사고과정에 도움이 되면 여러 depth가 있어도 굳이 분리할 필요 없음 선언한 변수와 실제 사용되는 코드 사이에 쓸데없는(=연관되어있지 않은) 코드를 많이 넣지말것쉽게 생각해서 친한친구끼리 붙여두는것. 친한 친구 두명사이에 여러명이 있으면 둘의 대화가 하기 힘들어짐. 공백라인: 라인의 공백을 잘 주면 코드 읽기가 쉬워짐아무거나 붙여놓고, 떨어뜨려놓으면 가독성이 떨어지기 때문에, 의미단위로 자르는 것이 좋음 부정어: 최대한 부정서 사용을 자제할 것.부정의 의미를 담은 다른 단어 유무 확인부정연산자는 가독성이 떨어지기 때문. Section 04. 객체 지향 패러다임추상의 관점으로 보는 객체지향 절차지향: 정해진 순서대로(절차) 처리  객체지향: 객체간의 협력  함수형: 순수함수를 기반으로함.관심사의 분리관심사를 모음 = 유지보수가 쉬워짐높은 응집도 = 낮은 결합도 객체 설계객체가 제공하는것절차지향에서 잘 보이지 않았던 개념을 가시화함관심사 모음캡슐화되어 높은 추상화레벨에서 domain logic을 다룰 수 있음새로운 객체를 만들때 주의할점1개의 관심사인가외부세계와 어떠한 소통을 하려는지 생각할 것생성자, 정적 factory method에서 유효성 검증가능domain에 특화된 검증 로직이 들어갈 수 있음setter and getter 사용자제데이터는 불변이 최고임변하는 데이터라도 객체가 handling할 수 있어야함.객체 내부에서 자체적으로 변경/ 가공으로 처리 할 수 있는가네이밍은 의도를 드러내는 네이밍이 중요함field의 수는 적을 수록 좋음불필요한 데이터가 많다 = 복잡도가 높다 = 대응할 변화가 많다 = 코드가 골치아파진다미리 제공하는 것이 성능상의 이점이 있다 = 필드로 가지고 있는 것이 좋을 수 있음.SOILDSRP: Single Responsibility Principle하나의 클라스 = 하나의 변경이유(= 책임)객체가 가진 공개 메서드, 필드, 상수 등은 해당 객체의 단일 책임에 의해서만 변경됨관심사의 분리높은 응집도, 낮은 결합도SRP를 잘지킴 = 겹합도 낮음 = individual workingOCP: Open-Closed Principle개방-폐쇄 원칙확장(=open)과 수정(=closed)즉, 확장은 가능, 수정은 불가능추상화와 다형성을 활용하여 지킬 수 있음.LSP: Liskov Substitution Principleparent class의 instance는 child-class의 instance로 치환가능자식클라스는 부모클라스기능 +aLSP를 위반하면 상속 클라스를 사용할 때 오동작, 예상밖의 예외가 발생하거나 이를 방지하기 위하여 불필요한 타입체크가 동반될 수 있음.ISP: Interface Segregation Principle클라이언트는 사용하지 않는 인터페이스에 의존하면 안됨interface를 잘게 쪼개기!ISP위반 = 불필요한 의존성 = 결합도 높아짐 = 특정 기능의 변경이 여러 클래스에 영향을 미침DIP: Dependency Inversion Principle상위수준의 모듈은 하위 수준모듈에 의존해서는 안됨둘 모두 추상화에 의존의존성의 순방향은 고수준이 저수준 모델을 참조하는것, 역방향은 고수준 저수준 모두 추상화에 의존하는것직접적으로 의존하지 않게 설계됨. Section 05. 객체 지향 적용하기상속과 조합상속 < 조합상속은 수정이 어려움조합 and interface를 활용하는 것이 유연한 구조임상속을 통한 코드의 중복제제가 주는 이점보다, 중복이 생겨도 유연한 구조가 주는 설계적 이점이 더 큼.즉 중복도 상황보며 잘 이용해야함 중복이 무조건 나쁜건 아님Value Object (VO)식별자 없이 내부의 모든 값이 다 같아야 동등한 객체로 취급함. 개념적으로 전체 필드가 다같이 식별자 역할을 한다고 생각해도됨\  기본 타입을 객체로 감싸서 추상화 값으로 취급하기 위해서 불변성, 동등성, 유효성 검증등을 보장해야함.불변성: final field, setter금지동등성: 서로다른 인스턴스여도(동일성이 달라도), 내부의 값이 같이면 같은 값 객체로 취급유효성 검증: 객체가 생성되는 시점에 값에 대한 유효성을 보장하기.Entity식별자가 같음 = 동등한 객체같은 식별자, 필드의 값이 다른 두 인스턴스 = entity가 시간이 지남에 따라 변화할 것으로 예측가능일급 컬렉션일급: 다른 요소에게 가능한 모든 연산자를 지원하는 요소변수할당가능파라미터 전달가능함수의 결과로 반환 가능 일급함수: 함수는 변수에 할당될 수 있고, 인자로 전달가능, 함수의 결과로 함수가 반환될 수 있음일급 컬렉션: 컬렉션만을 유일하게 필드로 가지는 객체다른 객체와 동등한 레벨로 다루기 위함collection 추상화: 의미담을 수 있고, 가공로직의 보금자리가 생기고 테스트 작성도 가능 Enum 특성: 상수의 집함, 상수와 관련된 로직을 담을 수 있는 공간특정 도메인 개념에 대해 그 종류와 기능 표현가능변정이 잦은 개념= DB로 관리하는 것이 나을 수 있음다형성활용변화하는것 : 조건 & 행위 = 구체변화하지 않는것: 조건을 만족하는가? 행위를 수행하는가? = 추상화OCP를 지키기 위해서 a,b는 구별해야함.숨겨져 있는 도메인 개념 도출도메인 지식은 만드는 것이아니라 발견하는것!!!객체지향 = 흉내내는 도구설계할 때는 근시적, 거시적 관점에 따라 최대한 미래를 예측틀렸다는 것을 인지할 경우 돌아올 수 있도록 코드를 짜야함.  Day02.미션추상: 핵심만 담아 짧고 간결하게 표현하는 것. (효율 극대화) 구체: 하나하나 풀어서 최대한 자세하게 설명하는 것. (비효율적) 예시) 추상: 너 만나기 전에 배가 고파서 먼저 밥먹었는데, 너는 밥 먹었니? 구체: 너와 00시에 만나기로 하였는데, 00시부터 나의 위에 아무것도 없었기 때문에, 내 뇌로 배고프다는 신호를 보낸 결과 나의 뇌가 무언가를 먹어야 한다는 신호를 보내어 집안의 냉장고에서 찾은 음식이 내 입에서 저작작용을 거쳐 식도를 지나 위로 넘어가는 일을 하고 왔는데, 너도 그런 일을 하고 왔니? 즉, 보통 사람이 이야기하는 것은 추상화 된 개념이고, 이를 하기 위한 코딩을 하는 것이 구체가 되는 것이 아닐까 생각하게 되었습니다. Josh Darnit 유튜버의 Exact instructions challenge영상에서 아빠는 구체화 된 상태이고 아이들이 추상화 된 방법으로 이야기하는 것이라 생각하게 되었습니다. Day04. 미션 // ; Original public boolean validateOrder(Order order) { if (order.getItems().size() == 0) { log.info("주문 항목이 없습니다."); return false; } else { if (order.getTotalPrice() > 0) { if (!order.hasCustomerInfo()) { log.info("사용자 정보가 없습니다."); return false; } else { return true; } } else if (!(order.getTotalPrice() > 0)) { log.info("올바르지 않은 총 가격입니다."); return false; } } return true; }//ordering public boolean validateOrder(Order order) { if (order.getItems().isEmpty()) { log.info("주문 항목이 없습니다."); return false; } if (order.getTotalPrice() <= 0) { log.info("올바르지 않은 총 가격입니다."); return false; } if (!order.hasCustomerInfo()) { log.info("사용자 정보가 없습니다."); return false; } return true; }// 캡슐화 public class Order { public boolean isValid() { return !getItems().isEmpty() && getTotalPrice() > 0 && hasCustomerInfo(); } public String getValidaionMessage { if(getItems().isEmpty()) return "No order list"; if(getTotalPrice() <= 0) return "Wrong Price"; if(!hasCustomerInfo()) return "No user information"; return "Thanks for order." } }// 부정문 제거 public class Order { public boolean isValid() { return hasItems() && getTotalPrice() > 0 && hasCustomerInfo(); } public String getValidationMessage() { if(!hasItems()) return "No order list"; if(getTotalPrice() <= 0) return "Wrong Price"; if(!hasCustomerInfo()) return "No user information"; return "Thanks for order." } public boolean hasItems() { return !getItems().isEmpty(); } public boolean getTotalPrice() { return totalPrice; } public boolean hasCustomerInfo() { return customerInfo() != null; } } SRP: Single Responsibility Principle 하나의 클래스, 하나의 책임 예시) 필름카메라: 필름카메라는 카메라라는 목적에 맞게 사진을 찍는 하나의 기능만을 가지고 있음. OCP: Open-Closed Principle 확장에 대해 열려있고, 수정에 닫혀있음. 예시) 디지털 카메라: 사진을 찍는 목적은 있지만, 여러 렌즈를 교체하며 zoom정도의차이(확장)의 기능을 가지고 있지만, 사진 자체를 수정할 수는 없음. LSP: Liskov Substitution Principle 자식 클라스는 부모 클라스를 대체할 수 있어야 한다. 예시) 스마트폰에 대해 이야기 할 수 있음. 초창기 핸드폰(부모클라스)의 경우 전화와 문자의 기본적인 기능만 있었으나 현재의 스마트폰(자식클라스)는 거기에 추가적으로 카메라, 인터넷접속등의 추가적인 기능이 있어 자식이 부모 클라스를 대체할 수 있다. ISP: Interface segregation Principle 하나의 커다란 인터페이스보다 작고 구체적인 인터페이스가 좋다. 예시) 카메라 기능: 실제 카메라는 사진을 찍는 기술을 가지고 있고, 그 사진을 편집하는 다른 프로그램이 동시에 존재한다. 이 두개를 모두 할 수 있는 것이 스마트폰인데, 이마저도 스마트 폰안의 다른 작은 인터페이스가 구체적이기 때문에 가능한것이다. DIP: Dependency Inversion Principle 고수준 모듈은 저수준 모듈에 의존해서는 안되고, 둘다 추상화된 인터페이스에 의존해야함. 예시) C type의 충전선은 여러 기기를 충전할 수 있음. C type 충전 cable로아이폰, 아이패드, 노트북 모두 충전이 가능함. 즉 추상화된 인터페이스(C type cable)에 각각의 인터페이스(아이폰, 아이패드, 갤럭시, 노트북등)는 각자 구현하는 것임. 마치며...3개 스터디를 한번에 하려는건 역시 무모한 일인가싶어 우선순위를 정했다.FE는 물론 중요하지만 코딩에 시간을 생각보다 많이 써야해서 내 배움 속도에 맞게 하기로 하였다.그래서 BE-CS-FE 순으로 초점을 두기로 하였다. BE야말로 내가 잘 모르는 분야인데 와 Java로 하려니 더 머리가 복잡쓰하다그래도 C#을 배웠던 짬바덕일까, 생각보다 코드 부분에서 나쁘지 않았다.그래도 개념적인 부분에 많은 것이 부족하다 느꼈기 때문에 그런 부분을 다시 review할 수 있는 것이 너무 좋음.특히, solid라는 개념은 대충알고 있었는데 다시한번 짚을 수 있어서 너무 좋음.아 뭐 이런거는 이렇겠지 싶었던 부분도 다시집고 넘어 갈 수 있어서 너무 좋지만 남은 3주가 너무 걱정됨.내가 왜 세개를 했냐고 이렇게 안하면 난 안할테니까...이번주 고생한 나에게 상따윈 없다 담주 더 고생해라! 

백엔드백엔드BE발자국1주차

whdudwo1143

인프런 워밍업 클럽 스터디 3기 - 백엔드 클린 코드, 테스트 코드 1주차 발자국

섹션2. 추상추상화란 구체적인 요소들을 감추고 중요한 특징만을 표현하는 것이다. 특정한 측면 외 나머지는 버린다는 점이 인상적이었습니다.또한 추상화에도 각각의 레벨이 있다는 생각을 해본적이 없었는데, 동일한 내부 세계에서는 동일한 추상화 레벨을 가진다는 내용이 인상적이었습니다.섹션3. 논리, 사고의 흐름하나의 문단에는 하나의 의미를 가지고있고, 하나의 메서드에는 하나의 기능만 가져야한다는 내용이 인상적이었습니다.Early Return불필요한 else를 제거하고, 조건에 맞으면 즉시 return하여 흐름을 명확하게 유지하는 방법을 배웠습니다.사고의 깊이(depth) 줄이기중첩된 분기문과 반복문의 깊이를 줄이고, stream을 활용하여 선형적으로 코드를 읽을 수 있도록 개선하는 방법을 익혔습다.부정어 최소화부정 연산자(!) 사용을 줄이고, 긍정적이고 직관적인 표현으로 메서드 이름을 짓는 것이 가독성 향상에 도움이 됨을 깨달았습니다.미션 해결 과정Day 2 미션"추상과 구체 사이의 적절한 균형을 찾는 것이 중요하다."코드가 지나치게 구체적이면 가독성이 떨어지고, 반대로 너무 추상적이면 실제 동작이 모호해진다는 점을 고민할 수 있어서 유익했습니다.Day 4 미션리팩토링 미션을 진행하며, 중첩된 for문과 if문을 Early Return 방식으로 변환하여 코드를 더 읽기 쉽고 직관적으로 만들었습니다. 또한, 가독성을 고려한 메서드 명명법을 고민하면서 개선해 나갔습니다.또한, SOLID 원칙을 나만의 방식으로 정리하는 미션을 수행하면서 단순 암기가 아니라 스스로 이해하며 정리하는 과정을 거쳤다. 여러 자료를 찾아보면서 개념을 내 언어로 표현한 것이 큰 도움이 되었다.회고추상과 구체 사이의 적절한 지점을 찾는 것이 중요느것을 깨닫게 되었습니다. 제가 가지고 있는 개발하며 안좋은 습관중 하나는 한 번에 모든 것을 처리하려다 보니, 하나의 메서드에 여러 기능을 넣는다는점이었습니다. 이번 수업을 통해 이를 반성하고 채움보다 비움을 통해 더 명료하게 개발하는 것의 중요성을 실감할 수 있었다.실습과 미션을 통해 이를 직접 경험하며, Early Return과 중첩 최소화 등 작은 코드 개선만으로도 가독성이 크게 향상될 수 있음을 체감할 수 있었다.스스로 칭찬하고 싶은 점미션을 통해 배운 내용을 즉시 적용하여 리팩토링하면서 개념을 내 것으로 만들려고 노력한 점추상화 레벨을 생각하며 개발하려 노력한 점하나의 메서드는 하나의 기능만 하도록 개발하려 노력한 점아쉬웠던 점 & 보완할 점변수명과 메서드명을 더 명확하고 직관적으로 짓는 능력이 부족하다고 느낌추상화 레벨을 동일하게 맞추는 방법을 더 깊이 있게 연습할 필요성을 느낌다음 주 학습 목표개인 프로젝트를하며 배운내용을 실전에 사용하는것을 목표로 삼고있다.

백엔드워밍업클럽백엔드클린코드3기박우빈1주차발자국발자국

동동

[인프런 워밍업 클럽_3기 CS] 1주차 운영체제 미션 🐾

운영체제while(true){ wait(1); // 1초 멈춤 bool isActivated = checkSkillActivated(); // 체크 }위 코드는 1초 마다 플레이어가 스킬을 사용했는지 체크하는 코드입니다.이 방식은 폴링방식입니다.1초마다 체크하기 때문에 성능에 좋지 않습니다.이를 해결하기 위한 방식으로 어떤 걸 이용해야 할까요? 풀링 방식은 주기적인 체크로 인해 성능이 좋지 않기에 인터럽트 방식으로 해결한다.  1. 프로그램과 프로세스가 어떻게 다른가요?- 프로그램 : 저장장치에 저장된 명령문의 집합체- 프로세스 : 실행 중인 프로그램 2. 멀티프로그래밍과 멀티프로세싱이 어떻게 다른가요?- 멀티프로그래밍 : 하나의 CPU에서 여러 개의 프로그램을 빠르게 번걸아가면서 실행- 멀티프로세싱 : 여러 개의 CPU를 사용하여 여러 프로세스를 병렬로 작업을 처리 3. 운영체제는 프로세스를 관리하기 위해서 어떤 것을 사용하나요?운영체제(OS)는 프로세스를 관리하기 위해 PCB(Process Control Block)을 사용합니다. PCB는 포인터, 프로세스의 상태 등을 저장하여 운영체제가 프로세스를 제어하고 관리할 수 있도록 합니다.  4. 컨텍스트 스위칭이란 뭔가요?컨텍스트 스위칭(Context Switching)은 프로세스를 실행하는 중에 다른 프로세스를 실행하기 위해 실행중인 프로세스의 상태를 저장하고 다른 프로세스의 상태값으로 교체하는 작업 

인프런워밍업클럽CS

tikitaka

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

 [풀스택 완성] Supabase로 웹사이트 3개 클론하기 (Next.js 14) - 로펀 1주차는 Supabase, Next.js, Tailwindcss, Recoil, React Query 소개와 기본 문법, Server Action CRUD 사용법을 배웠다.Supabase 특징오픈 소스 프로젝트 (자체 서버구축 가능)PostgresSQL 기반 (복잡한 요구사항 개발 가능)Firebase 대비 저렴다양한 연동방식 지원 (+SDK, DB Connection, GraphQL, API) Next.jsNext.js의 폴더명이 곧 Route와 같다.page.tsx는 각 폴더의 대표 파일과 같다.app/layout.tsx는 화면 레이아웃을 잡아주는 Next.js 서버 컴포넌트이므로, 클라이언트에서만 동작하는 상태 관리 라이브러리(Zustand, Recoil, React Query 등)를 직접 사용할 수 없다.따라서 React Query의 Client Provider를 별도의 클라이언트 컴포넌트로 만들어 layout.tsx에 주입해야 한다.(서버 컴포넌트는 클라이언트 상태나 브라우저 API에 접근할 수 없음)서버 액션은 API 라우트 없이 서버에서 직접 실행 가능하다. React Query서버에서 가져온 데이터를 캐싱, 동기화, 상태 관리까지 자동으로 해주는 라이브러리useQuery(): 데이터 조회 (GET 요청)const todosQuery = useQuery({ queryKey: ["todos"], // 캐싱 키 queryFn: fetchTodos, // API 요청 함수 }); const { data, isLoading, error } = todosQuery; queryKey: 데이터 캐싱 키queryFn: 데이터 호출 함수data: fetchTodos의 반환 값isLoading: 데이터 로딩 여부 (true면 로딩 중)error: 요청 실패 시 에러 객체 useMutation(): 데이터 변경 (POST, PUT, DELETE)const mutation = useMutation({ mutationFn: addTodo, onSuccess: () => { console.log("성공!"); }, onError: (error) => { console.error("에러 발생:", error); }, }); mutationFn: API 호출 함수onSuccess: 성공 시 실행할 함수onError: 실패 시 실행할 함수 TODO LIST 만들기Supabase todo 테이블 정의Supabase Next.js 연결.env 환경변수 설정Supabase Project API Keys를 사용하여 환경변수 추가package.json 수정scripts에서 generate-types 옵션 수정Supabase 로그인 후 타입 생성generate-types 실행하여 데이터베이스 테이블의 타입 정의 가져오기 Next.js에서 Supabase 클라이언트 생성브라우저/서버 환경에서 사용할 Supabase 클라이언트 생성Next.js의 모든 request에서 Supabase 인증 토큰을 갱신하도록 middleware 설정 TODO 조회 - server actionexport async function getTodos({ searchInput = "" }): Promise<TodoRow[]> { const supabase = await createServerSupabaseClient(); const { data, error } = await supabase .from("todo") .select("*") .like("title", `%${searchInput}%`) .order("created_at", { ascending: true }); if (error) { handleError(error); } return data; }getTodos 함수는 searchInput을 기본값 ""로 받아 Promise<TodoRow[]> 타입을 반환한다.이 함수는 서버 환경에서 실행되며, Supabase 클라이언트를 사용하여 todo 테이블에서 데이터를 조회한다.title 컬럼에서 searchInput을 포함한 값을 검색하며created_at을 기준으로 오름차순으로 정렬하여 반환한다.검색된 데이터가 없거나 오류가 발생하면 handleError 함수가 호출된다. TODO 조회 - React Query useQuery()const todosQuery = useQuery({ queryKey: ["todos", searchInput], queryFn: () => getTodos({ searchInput }), }); return ( // ... {todosQuery.data && todosQuery.data.map((todo) => <Todo key={todo.id} todo={todo} />)} // ... ) useQuery는 todosQuery라는 데이터를 서버에서 가져오는 비동기 작업을 관리한다.queryKey는 ["todos", searchInput]으로 설정되어, searchInput에 따라 조회된 결과가 달라지도록 한다.queryFn은 서버 액션 getTodos를 호출해, searchInput에 맞는 TODO 데이터를 반환한다.반환된 데이터(todosQuery.data)가 있을 경우, map()을 사용하여 각 TODO 항목을 렌더링한다. 1주차 미션github: https://github.com/thayoon/nextjs-supabase-todolist생성된 TODO의 생성 시간을 저장하고 이를 표시하는 기능을 추가하세요.TODO 항목 옆에 생성 시간을 표시하기component/todo.tsxexport default function Todo({ todo }) { // 한국 시간, YYYY/MM/DD HH:MM 포맷 함수 const getTime = (time: string): string => new Date(time) .toLocaleString("en-US", { year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit", hour12: false, timeZone: "Asia/Seoul", }) .replace(",", ""); const createdTime = getTime(todo.created_at); return( // ... {isEditing ? ( <input className="flex-1 border-b-black border-b pb-1" value={title} onChange={(e) => setTitle(e.target.value)} /> ) : ( <div className="flex-1"> <p className={`${completed && "line-through"}`}>{title}</p> <span className="text-gray-400 text-xs">⏱️{createdTime}</span> </div> )} // ... ); } getTime 함수는 created_at 값을 한국 시간에 맞게 YYYY/MM/DD HH:MM 포맷으로 변환한다.isEditing이 false일 때, 생성된 TODO 항목의 생성 시간을 createdTime을 통해 표시한다.todo 매개변수는 useQuery로 가져온 데이터 객체이며, created_at 값을 이용해 생성 시간을 표시한다. (선택 사항) completed_at 필드를 추가하여 완료한 시간도 함께 저장Supabase에서 completed_at 필드를 추가하여, TODO 완료 시각을 저장한다.completed_at은 NULL을 허용하는 timestamptz 타입 칼럼이다.actions/todo-actions.ts (server action)updateTodo 함수는 completed 상태에 따라 completed_at 값을 업데이트한다.export async function updateTodo(todo: TodoRowUpdate) { const supabase = await createServerSupabaseClient(); console.log(todo); const { data, error } = await supabase .from("todo") .update({ ...todo, updated_at: new Date().toISOString(), completed_at: todo.completed ? new Date().toISOString() : null, }) .eq("id", todo.id); if (error) { handleError(error); } return data; } completed가 true일 경우 completed_at에 현재 시각을 저장하고, false일 경우 null을 저장한다.3. components/todo.tsx (React Query useMutation())completed_at 값을 확인하여 완료 시각을 표시한다.export default function Todo({ todo }) { // 한국 시간, YYYY/MM/DD HH:MM 포맷 함수 const getTime = (time: string): string => new Date(time) .toLocaleString("en-US", { year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit", hour12: false, timeZone: "Asia/Seoul", }) .replace(",", ""); const completedTime = todo.completed_at ? getTime(todo.completed_at) : null; const updateTodoMutation = useMutation({ mutationFn: () => updateTodo({ id: todo.id, title, completed, }), onSuccess: () => { setIsEditing(false); queryClient.invalidateQueries({ queryKey: ["todos"], }); }, }); return( <div className="w-full flex items-center gap-1"> <Checkbox checked={completed} onChange={async (e) => { await setCompleted(e.target.checked); await updateTodoMutation.mutate(); }} /> {isEditing ? ( <input className="flex-1 border-b-black border-b pb-1" value={title} onChange={(e) => setTitle(e.target.value)} /> ) : ( <div className="flex-1"> <p className={`${completed && "line-through"}`}>{title}</p> <span className="text-gray-400 text-xs"> ⏱️{createdTime}{" "}{completedTime && `~ ${completedTime}`} </span> </div> )} // ... </div> ); } completed 상태에 따라 체크박스를 변경하고, 완료된 경우 completed_at 시각을 표시한다.setCompleted로 상태를 갱신하고, updateTodoMutation을 호출하여 서버에서 completed_at 값을 업데이트한다.완료된 TODO 항목에 대해 completed_at 값이 존재하면 완료 시각을 getTime() 함수로 포맷하여 표시한다.정리:TODO 완료 상태 변경:사용자가 체크박스를 클릭하면 setCompleted로 completed 상태를 갱신한다.갱신된 상태는 updateTodoMutation.mutate()를 통해 서버로 전송되어 completed_at 값이 업데이트된다.완료 시각 컴포넌트 업데이트:서버에서 completed_at 값이 갱신되면, 해당 TODO의 완료 시각이 한국 시간으로 포맷되어 표시된다.완료된 경우에는 completed_at을 getTime() 함수를 통해 표시하고, 완료되지 않은 경우에는 null이므로 표시되지 않는다.쿼리 데이터 갱신:updateTodoMutation.onSuccess에서 queryClient.invalidateQueries({ queryKey: ["todos"] })를 호출하여 todos 쿼리의 데이터를 무효화한다.쿼리의 데이터가 무효화되면 React Query는 자동으로 서버에서 최신 데이터를 다시 불러와 화면에 반영한다. 1주차 회고☀사실 Next.js를 아주 짧게 배운 상태로 강의를 듣게 됐는데, 섹션1에서 중요한 부분을 잘 설명해주셔서 큰 어려움없이 수강할 수 있었다. 그리고 실습을 따라하면서 어느정도 흐름은 알게 된 것 같다. 그렇지만 다른 Next.js 강의를 수강하며 구체적인 동작과정을 더 배워야 할 것 같다. 다음 실습도 기대된다. 다음주도 화이팅!

풀스택

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

워밍업클럽 3기 - BE 클린코드/테스트코드 1주차 회고 내용 요약전반적으로 읽기 좋은 코드를 작성할 때 어떤 관점에서 코드를 바라봐야 하는지에 대한 시야를 넓힐 수 있었다.변수명의 중요성과 목적에 따른 메서드 작성 및 나누기의 중요성을 다시 한번 느낄 수 있는 계기가 되었다.회고잘했던 점미션을 해결할 때 지금까지 실무에서 내가 작성했던 방식들을 되돌아 보며 강의 내용을 내 것으로 소화할 수 있었던 것 같다.아쉬웠던 점이번 주에 면접이 많이 잡혀서 해당 면접 준비 때문에 꾸준히 학습을 진행하지 못하였다. 하지만 다음 주도 이어서 면접이 잡혔으면 좋겠다.. ㅋㅋㅋㅋㅋㅋ면접이 잡혔다고 학습을 미루지 않고, 면접에 대한 준비를 평소에 꾸준히 진행하면서 개인 학습 또한 병행할 수 있도록 노력해야겠다. 미션 회고중요하게 생각했던 것개인적으로 웹 백엔드 분야에서 리소스 중심으로 소스를 작성하는 것이 중요하다고 생각한다.좋은 REST API의 필수 요소 중 uri를 리소스 중심으로 디자인 하는 것이 있고 또한 애플리케이션 구조를 고려할 때도 리소스 중심의 패키지 설계를 많이 하기 때문이다.전반적으로 백엔드 애플리케이션을 설계할 때 많은 요소들이 리소스를 중심으로 이루어져 있다보니, 소스 또한 리소스를 중심적으로 작성하는 것이 중요하다고 생각한다. public boolean validateOrder(Order order) { if (order.isEmpty()) { log.info("주문 항목이 없습니다."); return false; } if (order.isInvalidPrice()) { log.info("올바르지 않은 총 가격입니다."); return false; } if (!order.hasCustomerInfo()) { log.info("사용자 정보가 없습니다."); return false; } return true; } 내가 제출한 미션 코드이다.간단한 코드이지만 리소스 중심으로 작성한 코드의 좋은 예시라고 생각한다!기존의 난해한 if-else로 이루어진 코드 보다 훨씬 읽기 좋고, 추가적인 검증을 작성하기도 편한 구조로 리팩토링 하였다.만약 Service layer에서 해당 로직을 사용한다면 해당 클래스를 static으로 만들어서 EntityValidator.validateOrder(order); 와 같은 형태로 사용하면 충분히 실무적으로도 깔끔하고 유지보수 용이하게 관리할 수 있을 것 같다.앞으로도 최대한 실무적인 관점에서 미션들을 풀어나가면 나에게 더욱 더 도움이 될 것 같다.

채널톡 아이콘