블로그

[워밍업 클럽 스터디 2기::백엔드] 1주차 발자국

 일주일간의 학습 내용추상 (抽象)코드 단위에서의 추상 레벨을 지키는 법메서드를 추출하는 기준과 이름 짓기등도메인의 책임 분리에 대해서만 추상화를 생각하고 있었는데코드안에서 추상 레벨을 일관되게 유지하고 제가 제일 어려워하던 이름짓는법을매우 쉽게 설명해주셔서 큰 도움이 되었습니다. 논리, 사고의 흐름읽기 쉬운 코드를 작성하고 싶었으나 그동안은 메서드의 구조, 이름만 신경을 쓰고 있었습니다.잊고 있던 early return을 상기했고 부정문을 메소드로 대체했을때 인지부하를 줄여읽는이로 하여금 더 이해하기 쉬운 코드를 작성할 수 있다는게 신선했습니다. 객체 지향 패러다임SOLID 원칙을 코드에 적용하시는 것을 보고 많이 배웠습니다.늘 SOLID한 코드인가를 고민했는데 강사님의 강의를 듣고 좀 더 시야가 트인 느낌입니다.  학습 회고칭찬하고 싶은 점프로젝트 진행중에도 시간을 쪼개어 강의를 듣고 과제를 수행했다진행중인 프로젝트에도 적용을 시키려 노력했다. 아쉬웠던 점부트캠프에 참여중이라 시간 제약이 있어 강의를 완전 깊게 이해하지 못한 느낌이라 아쉽다.여러번 강의를 듣고 싶은데 시간이 없었다... 보완하고 싶은 점강의 내용을 글로 정리하려했으나 글쓰기가 아직은 많이 어렵게 느껴진다.글을 정리하는법을 공부해야할 것 같다. 미션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;}내가 생각한 문제점들1. 추상화 부족    이 메서드는 주문 항목을 확인하고, 사용자 정보를 확인하고, 총 가격을 확인하고 있다.    주문 검증이라는 책임을 지키는 듯 보이지만 내부를 살펴보면 3가지 일을 직접하고 있기에 확장이 어렵고    단일 책임을 지키지 못한다는 판단을 하였다 이런 문제들은 추상화를 제대로 하지 않았기에 생긴 문제라 판단하여    이 문제를 추상화 부족이라는 문제로 추상화하였다.2. 중첩된 조건문     else문을 보면 else문에서 끝나는 것이 아니라 다시 조건문을 이용하고 그 안에서 다시 조건문을 이용하는 복잡한 형태인데     이런 형태가 가독성을 해치고 로직을 복잡하게 만들고 있다는 생각이 들었다.3. 중복된 조건    order.getTotalPrice() > 0 를 else if에서도 사용중인데 0보다 크거나, 아니거나의 조건 판별을 위해서라면 두번씩이나    조건을 붙이는건 효율적이지 못하다는 결론을 내렸다4. 부정 연산자에 의한 사고의 흐름 방해    order.getTotalPrice() > 0 와 order.hasCustomerInfo에 ! 부정 연산자를 붙인 형태로 보는이로 하여금 한번더 어떤 코드인가를    생각하게 만드는 좋지 않은 조건문이라는 생각이 들었다.내가 생각한 해결방법들1. 추상화 부족    먼저 주문 검증이라는 책임을 어떻게 분산을 시킬것인가를 정했는데    각각의 조건문에서 원하는 검증들을 각각의 메서드들로 분할을 시켜주기로 했다.    리팩토링후에는 validateOrder 내부를 주문 항목 확인, 사용자 정보 확인, 총 가격 확인이라는    각각의 책임을 가진 메서드들로 나누고 validateOrder는 주문 검증이라는 명확한 책임을 가지게 만들어야 겠다고 생각했다.2. 중첩된 조건문    1번에서의 메서드 분할에 따라 각각의 메서드를 조건문에 넣어주기로 했고    6개의 if 또는 else를 3개의 if문으로 줄여보기로 했다3. 중복된 조건    조건문의 순서와 early return을 이용해 order.getTotalPrice()의 조건을 한번만 이용하기로 했다    총가격이 0보다 작거나 같다면 사용자 정보 확인전에 return을 해주어 불필요한 중복 조건을 제거했다.4. 부정 연산자에 의한 사고의 흐름 방해    더 직관적인 코드를 만들기 위해 부정 연산자를 메서드 내부로 숨기고    메서드의 이름을 isCustomerInfoNotFound라는 문장으로 만들어 validateOrder 메서드만 확인해도 해당 조건문에서    무엇을 확인하는지 알 수 있게끔 수정했다. 결과 코드public boolean validateOrder(Order order) { if (isOrderItemsEmpty(order)) { log.info("주문 항목이 없습니다."); return false; } if (isTotalPriceInvalid(order)) { log.info("올바르지 않은 총 가격입니다."); return false; } if (isCustomerInfoNotFound(order)) { log.info("사용자 정보가 없습니다."); return false; } return true;}private boolean isOrderItemsEmpty(Order order) { return order.getItems().isEmpty();}private boolean isTotalPriceInvalid(Order order) { return order.getTotalPrice() < 0;}private boolean isCustomerInfoNotFound(Order order) { return !order.hasCustomerInfo(); }회고재미있는 미션이었다.실제 프로젝트에서는 리팩토링이 부담스럽게 느껴졌는데부담없이 내 맘대로 리팩토링을 진행했기에 마음편히 진행하고 다른 분들의 코드와 비교도 해볼수 있는게 아주 좋다.  

[인프런 워밍업 스터디 클럽 2기 FE] 조승연 1주차 발자국

Day2(자바스크립트 기초)강의요약독학으로 기본은 이미 학습했기에 따라가는 데 지장은 없었다.그래도 기본 개념을 다시 복습하는 계기가 되었다.과제(음식 메뉴 앱)깃허브 링크음식 메뉴요구 사항 카테고리별 아이템 설정카테고리 클릭 이벤트 발생 시 해당 카테고리 아이템들 조회전체 아이템 조회결과최초 실행 시 전체 아이템 display: none카테고리 클릭 시 해당 카테고리 아이템 display: flex 조회전체 아이템 조회 display: flex회고처음엔 createElement로 구현해야 하는 생각에 막막했고, 너무 비효율적이라 구글링을 통해 다른 방법을 생각했다.classList를 통한 css 설정으로 구현할 수 있단 걸 알게 되어 적용했다.아무리 코드가 적어도 좀 묶어놓을 걸 싶다.Day3(자바스크립트 중급 1)강의 요약대부분의 언어에서도 중요한 this와 자바스크립트 만의 클로저구조 분해 할당을 통한 데이터 할당의 편의성데이터 활용도를 높여주는 Map, Filter, Reduce객체 활용도를 올려주는 메서드 bind, call, appply 과제(가위 바위 보 앱)깃허브 가위바위보요구 사항매 회 컴퓨터는 랜덤하게 가위, 바위, 보 중 하나를 선정해야 함매 회 사용자도 랜덤하게 가위, 바위, 보를 클릭 이벤트를 통해 선정해야 함회차별 승패 여부를 점수로 기록회차 기록점수에 따른 최종 승패 여부 결정결과random() 메서드를 통해 컴퓨터가 3개 중 하나 선정로직을 통해 승패 여부 결정 후 결과 기록최종 승패 결정 후 Day1에서의 css를 통한 설정으로 결과 표시회고삼항 연산자로 하기에 좀 지저분 해 보여서 로직을 찾아봤는데 내 코드엔 맞지 않아 포기했다.구현 자체는 쉬워 금방 했는데 DOM으로 가져온 데이터 부분이 커지길래 지저분 해져 깔끔할 방법이 없다 고심했다.Day4(자바스크립트 중급 2)강의 요약그나마 책으로 공부한 게 있어서 이해하는 데 어려움은 없었다.페이지 무한 스크롤, Intersection observer의 원리가 흥미로웠다. 즉시 실행 함수의 활용도가 진짜 높을 텐데 어떤 상황에서 활용하는 지가 좀 어려웠다.과제(퀴즈 앱)깃허브 퀴즈요구 사항랜덤한 숫자의 연산으로 퀴즈 생성사용자는 보기 중에서 정답을 클릭을 통해 선택선택한 보기가 정답일 경우 해당 보기만 초록색으로화면 배경도 초록색으로선택한 보기가 정답이 아닐 경우 틀린 해당 보기는 빨간색으로정답 보기가 초록색으로화면 배경도 빨간색으로전체 회차 종료 재도전 여부 표시결과random() 생성자 함수를 생성하여 연산자와 숫자를 구분하여 선정랜덤으로 뽑은 연산자와 숫자를 화면에 표시표시된 연산의 결과를 정답 보기로 생성, 내부 로직으로 틀린 보기 생성 후 화면에 표시사용자 클릭 시 보기 관련 요구 사항 css 설정으로 구현회차 만료로 퀴즈 종료 시 재시작 선택 여부 확인 후데이터 초기화 후 다시 시작회고함수형으로 구현하려고 했는데 생각보다 쉽지 않았다.계속 한 회차에 두 번 진행 되는 버그 발생. 원인은 함수형으로 구현하다 이벤트 리스너가 한 번 클릭 시 두 번 발생해결 : 이벤트 리스너 함수를 독립적으로 생성하여 해결했다.그래도 내 수준에서 요 정도 함수형으로 구현한 걸로 만족했다.Day5(OOP, 비동기) 강의 요약비동기는 개념을 모르는 상태에서 많이 써봐서 중요하단 건 알았지만, 생각보다 쉬웠다.프로토타입은 책으로 봤을 때 너무 어려웠어서 몇 번을 다시 보면서 공부해서 잘 넘어갔다.클래스를 써보고 싶었는데 잘 엄두가 안났다. 담주에 할 땐 함 써보자. 과제(책 리스트 나열 앱)깃허브 책 리스트요구 사항사용자가 입력한 데이터를 화면에 표 형식으로 표시해당 데이터 저장 공간에 저장(Map or Local Storage)표시된 표 형식의 데이터의 마지막 컬럼에 버튼으로 해당 행 삭제 결과form으로 사용자의 input 데이터를 받고, submit 이벤트 리스너 발생해당 이벤트 일시 정지를 위한 preventDefault() 함수 실행createElement로 데이터와 삭제 버튼을 생성하여 화면에 표시삭제 버튼 클릭 시 해당 행 삭제하는 이벤트 발생데이터 표에 추가 및 삭제 시 메세지 표시 후 비동기 setTimeout() 함수로 종료회고이미 구현 해봤던 내용이라 간단했다. Day6(OOP, 비동기) 강의 요약비동기는 개념을 모르는 상태에서 많이 써봐서 중요하단 건 알았지만, 생각보다 쉬웠다.프로토타입은 책으로 봤을 때 너무 어려웠어서 몇 번을 다시 보면서 공부해서 잘 넘어갔다.클래스를 써보고 싶었는데 잘 엄두가 안났다. 담주에 할 땐 함 써보자.  과제(GihHub Finder 앱)깃허브 GitHub Finder요구 사항사용자의 입력과 동시에 실시간 검색프로필, Repository 수, 팔로워/팔로잉 수 등 데이터 화면에 출력Repository 나열 후 클릭 시 해당 Repository로 이동 결과이벤트 리스너 input 설정과 async/await으로 비동기 실시간 검색 구현 fetch로 URL req 전송 후 Promise.all()로 res 동시에 받기각 Repository 화면에 나열 회고깃허브 API에 대한 내용을 공식 홈페이지에서 확인 해도 헷갈리는 부분이 많아 다른 사람 코드를 참고 했다.처음 문서를 잘못 봐서 되게 복잡하다 생각했는데 막상 코드를 보니 굉장히 쉬운 거였다.보니 요청 횟수가 정해져 있어 토큰을 발급 받아 fetch 헤드에 담아 전송해야 했는데 몰라서 좀 헤맸다.그 분 코드에 굳이 DOM 데이터를 변수에 담아 할 필요는 없다는 걸 깨닭고 실행에 옮겼다. 

프론트엔드

hhw0850

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

Readable Code: 읽기 좋은 코드를 작성하는 사고법 수강 후 작성한 1주차 발자국입니다. 1주차 강의 정리섹션1인텔리제이, jdk 설치 및 readable code fork 를 진행하였다.기존에 jdk8버전을 사용했기에 추가로 jdk17버전을 설치하여 실행했다.섹션2추상화가장 중요한 정보만 남기고 덜 중요한 정보는 덜어내는 과정을 추상화라고 한다.도메인 영역 별로 추상화 기준이 다를 수 있다.이름짓기는 추상화의 가장 대표적인 행위이다.  이름 짓기단수와 복수 구분이름 줄이지 않기은어/방언 사용하지 않기좋은 코드를 보고 습득하기  메서드 선언부메서드명은 추상화된 구체를 유추할 수 있는, 적절한 의미가 담긴 이름으로 지어야 한다.파라미터와 연결지어 더 풍부한 의미를 전달할 수도 있다.파라미터의 타입, 개수, 순서를 통해 의미를 전달할 수 있다.파라미터는 외부 세계와 소통하는 창메서드 시그니터에 납득이 가는, 적절한 타입의 반환값 돌려주기void 대신 충분히 반환할 만한 값이 있는지 고민해보기 추상화 레벨하나의 세계 안에서는 추상화 레벨이 동등해야한다.추상화 레벨을 동등하게 맞춰줌으로써 읽는 사람이 자연스럽게 사고가 흘러갈수있게 하는 기법매직넘버, 매직 스트링의미를 갖고 있으나, 상수로 추출되지 않은 숫자, 문자열 등상수 추출로 이름을 짓고 의미를 부여함으로써 가독성, 유지보수성 올라감자바에서 상수는 대문자, 언더스코어로 작성한다섹션3뇌 메모리 적게 쓰기코드를 작성할때는 읽는 사람의 뇌 메모리를 적게쓰도록 가독성있게 작성하는게 중요하다.인지적 경제성을 추구하자.Early returnEarly return 으로 else 사용을 지양하자.사고의 depth 줄이기중첩 분기문, 중첩 반복문사고 과정의 depth를 줄이는게 중요하다사용할 변수는 가깝게 선언하기 공백 라인을 대하는 자세공백 라인도 의미를 가진다.→ 복잡한 로직의 의미 단위를 나누어 보여줌으로써 읽는 사람에게 추가적인 정보를 전달할 수 있다.부정어를 대하는 자세부정어구를 쓰지 않아도 되는 상황인지 체크하기부정의 의미를 담은 다른 단어가 존재하는지 고민하기 or 부정어구로 메서드명 구성 → isNot doesNot never 등 → 부정 연산자 (!) 의 가독성 떨어지므로해피케이스와 예외처리예외가 발생할 가능성 낮추기어떤 값의 검증이 필요한 부분은 주로 외부 세계와의 접점→ 사용자 입력, 객체 생성자, 외부 서버의 요청 등의도한 예외와 예상하지 못한 예외를 구분하기→ 사용자에게 보여줄 예외와, 개발자가 보고 처리해야 할 예외 구분Null을 대하는 자세항상 NullPointerException을 방지하는 방향으로 경각심 가지기메서드 설계 시 return null을 자제한다.→ 만약 어렵다면, Optional 사용을 고민해본다.Optional에 관하여→ Optional은 비싼 객체다. 꼭 필요한 상황에서 반환 타입에 사용한다. → Optional을 파라미터로 받지 않도록 한다. 분기 케이스가 3개나 된다. → Optional을 반환받았다면 최대한 빠르게 해소한다.섹션4객체 설계하기비공개 필드(데이터), 비공개 로직(코드)공개 메서드 선언부를 통해 외부 세계와 소통 → 각 메서드의 기능은 객체의 책임을 드러내는 창구객체의 책임이 나뉨에 따라 객체 간 협력이 발생객체가 제공하는 것절차 지향에서 잘 보이지 않았던 개념을 가시화관심사가 한 군데로 모이기 때문에, 유지보수성 높아짐 → 객체 내부에서 객체가 가진 데이터의 유효성 검증 책임을 가질 수 있다.여러 객체를 사용하는 입장에서는, 구체적인 구현에 신경 쓰지 않고 보다 높은 추상화 레벨에서 도메인 로직을 다룰 수 있다.새로운 객체를 만들 때 주의할 점1개의 관심사로 명확하게 책임이 정의되었는지 확인하기 → 메서드를 추상화할 때와 비슷하다. → 객체를 만듦으로써 외부 세계와 어떤 소통을 하려고 하는지 생각해보자.생성자, 정적 팩토리 메서드에서 유효성 검증이 가능하다. → 도메인에 특화된 검증 로직이 들어갈 수 있다.setter 사용 자제 → 데이터는 불변이 최고다. 변하는 데이터더라도 객체가 핸들링할 수 있어야한다. → 객체 내부에서 외부 세계의 개입 없이 자체적인 변경, 가공으로 처리할 수 있는지를 확인 → 만약 외부에서 가지고 있는 데이터로 데이터 변경 요청을 해야하는 경우, ‘set~’ 이라는 단순한 이름 보다는 ‘update~’ 같이 의도를 드러내는 네이밍을 고려하자.getter도 처음에는 사용 자제. 반드시 필요한 경우에 추가하기, 객체에 메시지를 보내라 → 필드의 수는 적을수록 좋다.필드의 수는 적을수록 좋다. → 불필요한 데이터가 많을수록 복잡도가 높아지고 대응할 변화가 많아진다. → 필드 A를 가지고 계산할 수 있는 A’ 필드가 있다면 메서드 기능으로 제공SOLIDSRP: Single Responsibility Principle단일 책임 원칙, 하나의 클래스가 하나의 책임만 갖도록 설계하는 원칙하나의 클래스, 객체는 단 한가지의 변경 이유만을 가져야 한다. = 단 하나의 책임, 관심사를 가져야 한다.객체가 가진 공개 메서드, 필드, 상수 등은 해당 객체의 단일 책임에 의해서만 변경되는가?동일한 상수를 A클래스, B클래스 둘다 쓰는 상황관심사의 분리SRP를 지키게 되면 높은 응집도, 낮은 결합도를 가지게 된다.응집도란 클래스나 모듈 내에 있는 요소들이 긴밀하게 연관되어있는 정도를 의미한다. 단일 책임을 가지면 응집도는 높아진다.결합도는 두 개 이상의 객체가 협력한다고 했을 때 하나의 객체가 변경되었을때 다른 객체가 영향받는 정도이다. 서로 다른 두 객체간의 의존성을 최소화시키는게 결합도를 낮춘다는 의미이다.OCP: Open-Closed Principle개방-폐쇄 원칙확장에는 열려 있고, 수정에는 닫혀 있어야 한다.→ 기존 코드의 변경 없이, 시스템의 기능을 확장할 수 있어야 한다.추상화와 다형성을 활용해서 OCP를 지킬 수 있다.새로운 요구사항이 생겼을때 기존 코드의 변경 없이 시스템의 기능을 확장할 수 있어야 한다.인터페이스를 활용하자LSP: Liskov Substitution Principle리스코프 치환 원칙상속 구조에서, 부모 클래스의 인스턴스를 자식 클래스의 인스턴스로 치환할 수 있어야 한다. → 자식 클래스는 부모 클래스의 책임을 준수하며, 부모 클래스의 행동을 변경하지 않아야 한다. → 부모 클래스를 자식클래스로 변경해도 동일한 결과를 내야한다.LSP를 위반하면, 상속 클래스를 사용할 때 오동작, 예상 밖의 예외가 발생하거나, 이를 방지하기 위한 불필요한 타입 체크가 동반될 수 있다.상속 구조를 사용한다면 LSP를 잘 지키도록 구조 설계를 해야한다.부모와 자식 클래스가 있을때 자식 클래스의 기능이 더 많게 된다.ISP : Interface Segregation Principle인터페이스 분리 원칙클라이언트는 자신이 사용하지 않는 인터페이스에 의존하면 안된다.→ 인터페이스를 잘게 쪼개라ISP를 위반하면, 불필요한 의존성으로 인해 결합도가 높아지고, 특정 기능의 변경이 여러 클래스에 영향을 미칠 수 있다.기능 단위로 인터페이스를 잘게 나눠서 사용해라하나의 인터페이스에 여러 기능이 몰려있으면 불필요한 의존성으로 결합도가 높아진다.DIP: Dependency Inversion Principle의존성 역전 원칙상위 수준의 모듈은 하위 수준의 모듈에 의존해서는 안 된다. 둘 모두 추상화에 의존해야 한다.의존성의 순방향 : 고수준 모듈이 저수준 모듈을 참조하는 것의존성의 역방향 : 고수준, 저수준 모듈이 모두 추상화에 의존하는것 → 저수준 모듈이 변경되어도, 고수준 모듈에는 영향이 가지 않는다. 섹션5상속과 조합상속보다 조합을 사용하자상속은 수정이 어렵다.부모와 자식의 결합도가 높다결합도가 높은 설계조합과 인터페이스를 활용하는 것이 유연한 구조상속을 통한 코드의 중복 제거가 주는 이점보다 중복이 생기더라도 유연한 구조 설계가 주는 이점이 더 크다그냥 부모의 기능을 별도의 객체로 두고 이걸 가져다가 쓰면 상속은 사용하지 않아도 된다유지보수하기 쉬운 조합을 사용하는것이 좋다Value Object도메인의 어떤 개념을 추상화하여 표현한 값 객체값으로 취급하기 위해서 불변성 동등성 유효성 검증 등을 보장해야 한다.불변성 : final 필드, setter 금지동등성 : 서로 다른 인스턴스여도 내부의 값이 같으면 같은 값 객체로 취급한다.유효성 검증 vo vs entity  Entity는 식별자가 존재한다. 식별자가 아닌 필드의 값이 달라도, 식별자가 같으면 동등한 객체로 취급한다.VO는 식별자 없이, 내부의 모든 값이 다 같아야 동등한 객체로 취급한다.개념적으로 전체 필드가 다같이 식별자 역할을 한다고 생각해도 된다.일급 컬렉션일급 시민다른 요소에게 사용 가능한 모든 연산을 지원하는 요소변수로 할당될 수 있다.파라미터로 전달될 수 있다.함수의 결과로 반환될 수 있다.ex) 일급 함수함수형 프로그래밍 언어에서, 함수는 일급 시민이다.함수는 변수에 할당될 수 있고, 인자로 전달될 수 있고, 함수의 결과로 함수가 반환될 수도 있다.일급 컬렉션컬렉션을 포장하면서, 컬렉션만을 유일하게 필드로 가지는 객체컬렉션을 다른 객체와 동등한 레벨로 다루기 위함단 하나의 컬렉션 필드만을 가진다.컬렉션을 추상화하며 의미를 담을 수 있고, 가공 로직의 보금자리가 생긴다.가공 로직에 대한 테스트도 작성할 수 있다.만약 getter로 컬렉션을 반환할 일이 생긴다면, 외부 조작을 피하기 위해 꼭 새로운 컬렉션으로 만들어서 반환해주자.EnumEnum은 상수의 집합이며, 상수와 관련된 로직을 담을 수 있는 공간이다.상태와 행위를 한 곳에서 관리할 수 있는 추상화된 객체특정 도메인 개념에 대해 그 종류과 기능을 명시적으로 표현해줄 수 있다.만약 변경이 정말 잦은 개념은, Enum보다 DB로 관리하는 것이 나을 수 있다.다형성 활용하기추상화와 다형성을 활용하여 반복되는 if문 제거, OCP 지키기숨겨져 있는 도메인 개념 도출하기도메인 지식은 만드는 것이 아니라 발견하는 것객체 지향은 현실을 100% 반영하는 도구가 아니라, 흉내내는 것이다.현실 세계에서 쉽게 인지하지 못하는 개념도 도출해서 사용해야 할 때가 있다.설계할 때는 근시적, 거시적 관점에서 최대한 미래를 예측히고, 시간이 지나 만약 틀렸다는 것을 인지하면 언제든 돌아올 수 있도록 코드를 만들어야 한다.완벽한 설계는 없다. 그 당시의 최선이 있을 뿐1주차 강의 수강 회고이번 1주차에서는 지금까지의 잘못된 코드 습관들을 하나씩 알게 되었고 강의에서 배운대로 고쳐 나가야겠다고 다짐하게되었다. 이번에 알게된 나의 잘못된 코드 습관은 다음과 같다.복수형 이름 짓기 시 ~(e)s 사용하지 않고 ~List 사용했던 것줄임말 사용했던 것 ex) cnt, idx 등추상화 레벨을 생각하지 않았던 것부정연산자 많이 사용했던 것getter, setter 남발했던 것 강의를 보면서 뜨끔했던 순간이 정말 많았다. 그중 특히나 추상화 레벨 강의가 기억에 남는다. 강사님께서 안 좋은 예시를 처음에 보여주셨는데 나였으면 그냥 작성하고 넘어갔을 것 같은 코드였어서 정말 뜨끔했다. 이번 강의를 통해 추상과 구체에 대해 알게 됐고 이제 코드에 배운대로 적용해봐야겠다고 생각했다. 아직 많이 부족하지만 코드를 작성할때 나름 가독성있게 코드를 작성하려고 노력했었는데 클린코드를 어떻게 작성하는지 제대로 강의를 들어보니 지금껏 내가 작성했던 코드는 뭐였을까... 다시 한 번 되돌아 볼 수 있었던 1주였던 것 같다.1주차 미션DAY2 미션추상과 구체 예시 작성'라면끓이기'를 구체 레벨에서 표현한다면?라면 1개를 준비한다.냄비를 준비한다.물 500ml을 준비한다.가열장치를 준비한다.가열장치에 냄비를 올린다.냄비에 물 500ml을 넣는다.가열장치를 켜서 냄비를 가열한다.냄비의 물이 끓을때까지 기다린다.면을 넣는다.건더기 스프를 넣는다.분말 스프를 넣는다.3분동안 면을 저으면서 끓인다.가열장치를 끈다.라면을 그릇에 담아 완성한다.    '라면 끓이기' 라는 말이 물넣고 스프넣고 면넣고,, 등등 모든 과정이 함축되어 있는 말 같아서 위와 같이 작성했다. DAY4 미션1. 아래 코드와 설명을 보고, [섹션 3. 논리, 사고의 흐름]에서 이야기하는 내용을 중심으로 읽기 좋은 코드로 리팩토링해 봅시다.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; }사용자가 생성한 '주문'이 유효한지를 검증하는 메서드.Order는 주문 객체이고, 필요하다면 Order에 추가적인 메서드를 만들어도 된다. (Order 내부의 구현을 구체적으로 할 필요는 없다.)필요하다면 메서드를 추출할 수 있다.  풀이과정validateOrder 메서드에서 수행하는 기능을 간단하게 정리하면,주문 항목이 없는지 체크총 가격이 0보다 작은 수인지 체크사용자 정보가 없는지 체크총 3단계로 정리하였다. 그리고 각 단계에서 Early Return을 적용하여 불필요한 else를 없애고 depth를 줄였다.public boolean validateOrder(Order order) { // 1. 주문 항목이 없는지 체크 if (order.getItems().size() == 0) { log.info("주문 항목이 없습니다."); return false; } // 2. 총 가격이 0보다 작은 수인지 체크 if (!(order.getTotalPrice() > 0)) { log.info("올바르지 않은 총 가격입니다."); return false; } // 3. 사용자 정보가 없는지 체크 if (!order.hasCustomerInfo()) { log.info("사용자 정보가 없습니다."); return false; } return true; } 위 코드에서 부정 연산자(!)를 긍정어로 수정하고 get~ 같은 직접적인 메소드명 대신 Order 객체에게 의도된 메세지를 전달하여 가독성 좋게 if문을 수정하였다.public boolean validateOrder(Order order) { // 1. 주문 항목이 없는지 체크 if (order.hasNoneItem()) { log.info("주문 항목이 없습니다."); return false; } // 2. 총 가격이 0보다 작은 수인지 체크 if (order.isTotalPriceLessThenZero()) { log.info("올바르지 않은 총 가격입니다."); return false; } // 3. 사용자 정보가 없는지 체크 if (order.hasNoneCustomerInfo()) { log.info("사용자 정보가 없습니다."); return false; } return true; }2. SOLID에 대하여 자기만의 언어로 정리해 봅시다.SRP: Single Responsibility PrincipleSRP는 하나의 클래스, 하나의 객체는 하나의 책임만을 가져야 한다는 원칙이다. 우리는 코드를 작성할 때 응집도가 높게, 결합도가 낮게 동작하도록 구현하여야 하는데 SRP를 지키게 되면 높은 응집도, 낮은 결합도를 가지게 된다. 응집도란 클래스나 모듈 내에 있는 요소들이 연관되어 있는 정도를 말하며 SRP를 지키면 이 연관되어 있는 정도가 낮아지므로 응집도는 높아진다. 결합도는 두 개 이상의 객체가 협력한다고 했을 때 하나의 객체가 변경될 경우 다른 객체가 영향 받는 정도를 의미한다. SRP를 지키면 두 객체간 의존성을 최소화시킬 수 있으므로 결합도를 낮출 수 있다. OCP: Open-Closed PrincipleOCP는 확장에는 열려있고, 수정에는 닫혀있어야 한다는 원칙이다. 우리는 코드를 한 번 작성하게 되면 끝이 아니라 지속적으로 코드를 수정하게되는 상황이 발생한다. 만약 코드 작성 후 새로운 요구사항이 발생하면 기존 코드를 수정해야하는데 기존 코드의 변경 없이 새로운 요구사항을 적용시킬 수 있어야 한다. 그렇게 하기 위해서는 인터페이스와 같은 추상을 통해 개방-폐쇄 원칙을 지킬 수 있으며 항상 기능의 확장을 고려하여 코드를 작성해야 한다. LSP: Liskov Substitution PrincipleLSP는 상속 구조를 설계할 때 부모 클래스를 자식 클래스로 변경해도 동일 결과를 낼 수 있도록 설계해야한다는 원칙이다. 자식 클래스는 부모 클래스의 기능 + @로 구현되어야 하고 부모 클래스의 기능이 변경되면 안 된다. 만약 LSP를 위반한다면 상속 구조에서 오동작이 발생할 수 있으므로 LSP를 지켜 상속 구조를 설계해야 한다. ISP : Interface Segregation PrincipleISP는 기능 단위로 인터페이스를 분리하라는 원칙이다. 하나의 인터페이스 안에 기능이 여러가지 들어있다면 인터페이스 사용 시 사용하지 않는 기능이 생길 것이다. 이렇게 되면 불필요한 의존성이 발생하므로 결합도가 높아지게 된다. 또한 인터페이스에 기능 변경이 생겼을 때 여러 클래스에 영향을 끼칠 수 있다. 이를 방지하게 위해서 인터페이스는 기능 단위로 잘게 쪼개서 사용해야한다. DIP: Dependency Inversion PrincipleDIP는 상위 수준의 모듈은 하위 수준의 모듈에 의존하면 안되며 모두 추상화에 의존해야한다는 원칙이다. 상위 수준의 모듈은 추상화 레벨이 높은 모듈을 의미하고, 하위 수준의 모듈은 추상화 레벨이 낮은 모듈을 의미한다. 만약 상위 수준의 모듈이 하위 수준의 모듈을 참조하게되면 문제가 발생할 수 있다. 하위 수준 모듈은 구체에 가깝기 때문에 변경될 가능성이 높다. 변경 가능성이 높다면 상위 수준 모듈에도 영향을 줄 수 밖에 없다. 그래서 인터페이스와 같은 추상을 통해 상위수준, 하위수준 모듈 모두 직접 서로 의존하는게 아니라, 추상화에 의존하도록 하는 의존성 역전이 필요하다.1주차 미션 회고DAY4 미션 코드 리팩토링에서 강의를 듣기 전이었다면 Early return만 적용해서 else, else if만 없애고 끝냈을 것이었다. 이번에 강의를 듣고 '부정어 사용 지양', '객체에게 메세지 전달' 을 배워 부정 연산자(!)를 긍정어로 수정하고 get~ 같은 직접적인 메소드명 대신 Order 객체에게 의도된 메세지를 전달하도록 리팩토링 하였다. 앞으로 코드를 작성할 때도 강의에서 배운 내용 대로 적용해봐야겠다고 생각했다.

인프런 워밍업 클럽 백엔드 1주차 후기

내가 워밍업 클럽을 신청한 이유우선 나는 백엔드 개발자로 재직한지 갓 1년이 된 몹시 주니어인 개발자이다.아직 1년 차인 내가 왈가왈부할 실력도 아니고, 다른 회사의 환경을 경험을 한 건 아니지만, 우리 회사의 환경은 뭐랄까.. 내가 공부한 내용과는 괴리가 컸다. Spring Boot를 공부했지만 Spring legacy 환경을 쓰고 있고, JPA를 공부했지만 오직 Mybatis로 구성된 환경이다. (지금 계속 개선되고 있지만 배포도 아직 FTP로 많이 한다...ㅠ)내가 겪은 어려움은 Mybatis를 사용하면서 VO 개념도 쓰고 있긴 하지만, 대부분의 반환 타입이나 매개 변수로 단순한 Map 타입의 객체를 받아서 이를 컨트롤러나 서비스 객체에서 get() 또는 put() 메서드를 활용해서 단순히 절차지향적으로만 쓰는 느낌이 강했다. '오브젝트'와 '객체 지향 사실과 오해' 같은 객체지향 관련한 명저를 읽으면서 객체지향 찍먹을 해봤기에 아직 초급 단계도 못 벗어난 내가 봐도 이거는 자바를 잘 쓰고 있는 느낌을 못 받았었다. 이에 회사 코드를 리팩토링을 시도했지만, 나도 결국 한낱 초보자라 결국 선배들과 비슷한 코드를 작성하며 흘러가고 있는 것이 나에게 큰 고민거리였다.이렇게 리팩토링에 대한 갈망만 가진 채 회사를 다니던 중 우빈님의 강의 'Readable Code'를 발견하게 되었고, 소개 영상과 목차를 통해 강의를 수강하기로 마음 먹었다. 또한 운이 좋게도 이번 워밍업 클럽 과정에 속한 것을 발견하게 되었고, 나와 같은 고민을 가진 분들과 소통하고 싶어 신청하게 되어 열심히 들으며 많은 가르침을 얻고 있는 중이다. 추상의 중요성먼저 강의 시작의 asis의 지뢰찾기 코드를 한 번 보고 충격 받았다. "우리 회사 코드랑 흡사하구나?" 모든 비즈니스 로직이 한 메서드에 들어 가 있는 "조상" 코드를 보며 이것을 어떻게 읽기 좋게 바꿀 것인지가 몹시 궁금해졌다. 그리고 추상이란 행위가 프로그래밍에 있어서 많이 중요함을 느꼈다. 어떤 식으로 이름을 지어줘야 후손이 쉽게 읽을까에 대한 고민을 하게 되었고, 당장에 i, temp 같은 땜빵용 변수명, 메서드명들을 찾아 코드를 읽어보며 의미있게 변경해봤다. 이것만 해보아도 코드 흐름을 상당히 편히 읽히게 할 수 있겠구나 느꼈다. 객체 지향의 중요성객체 지향에 대해서 많은 것을 배울 수 있었다. 특히 일급 컬렉션에 대해서는 이번 개발에 바로 적용해서 써먹어 보았다.이번에 개발할 때 어떤 리스트 컬렉션을 만들어서 데이터를 순회해서 가공했어야 했는데, 이를 일급 컬렉션 객체를 만들어 해당 객체 안에서 추상화된 메시지만 던져 수행시키니 훨씬 응집도가 높아졌고, 호출하는 쪽은 내부 로직은 신경 안 써도 된다는 점에서 이런 것들이 객체 지향의 초석이구나를 느낄 수 있었다. 나의 인프런 온라인 스승님 "김영한" 님의 강의 명언 중 하나인 "백문이불여일타", 보지만 말고 쳐보는 것이 중요함은 이런 것임을 느꼈고 앞으로 강의에서 배운 점은 바로바로 써먹어볼까 한다 미션 수행Day 4의 미션은 코드를 리팩토링 하는 것이었는데, 강의에서 너무 잘 알려주셔서 어렵지 않게 풀어볼 수 있었다.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; }위와 같이 indent가 깊고, if-else로 되어있다보니 이전의 문맥(컨텍스트)를 머릿속에 계속 담아야 하는 불편함이 있었다.또한 order의 변수들을 getter로 꺼내서 호출하는 쪽에서 내용을 판단하는 아주 무례한(?) 행동을 하고 있었다.우빈님 강의에서 언급했듯이 뇌 메모리를 적게 쓰는 방향으로 리팩토링 하도록 노력하였다.public boolean validateOrder(Order order) { // 조기 종료 if (order.hasNotItems()) { log.info("주문 항목이 없습니다."); return false; } // 올바르지 않은 총 가격이면 조기 종료 if (order.isTotalPriceNotValid()) { log.info("올바르지 않은 총 가격입니다."); return false; } // 사용자 정보 없으면 조기 종료 if (order.hasNotCustomerInfo()) { log.info("사용자 정보가 없습니다."); return false; } // 여기까지 오면 정상 종료 return true; }다음과 같이 수정하였는데, early return을 통해 유효하지 않으면 빨리 종료 시키도록 하여 if-else를 없앴고, order에게 메시지를 보내 묻는 형태로 바꾸어서 더는 getter로 꺼내 쓰지 않도록 해보았다. 후기1주일 만에 강의를 통해 정말 많은 것을 느낄 수 있었다. 이를 통해 내가 아직 더 성장할 여지가 많다는 것도 느꼈고, 공부를 통해 회사 코드를 개선해보면서 후대에 이로움만 남겨줘야 겠다는 강한 동기도 얻었다. 다음 주차도 열심히 해봐야겠다.아자아자 화이팅!

백엔드

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

시작사실 마감 직전까지 이런 스터디가 있는 줄도 몰랐다. 인프런에서 볼 수 있는 Josh Long의 Spring Boot 밋업이 재밌길래 그걸 보느라 인프런을 들락날락 하다가 우연히 워밍업 클럽 배너를 봤다. 최근 나의 학습 패턴도 예전같지 않고, 마음가짐도 점점 시들어가는 걸 느끼는 와중이었다. 처음에는 CS 스터디를 신청하려고 했다. 다시보니 스프링에서의 테스트 코드 작성에 관한 스터디가 있었기에 바로 노선을 변경했다. 나는 올해 초, 다른 교육기관에서 클린코드와 리팩터링, TDD에 대한 과정을 수료했다. 그 과정에서 배운 점이 많고 지금도 실무에 많이 적용한다. 굉장히 좋은 과정이었지만, 딱 하나 아쉬운 점이 있었다. 해당 과정은 순수 자바로만 진행된다는 것이다. 클린코드와 리팩터링은 순수 자바만으로도 내 실무에 바로 적용할 수 있었다. 하지만 TDD는 그렇지 않다. TDD 그 자체는 깨우쳤는데, 내 실무 코드는 스프링 프레임워크 위에서 논다. 결국, 스프링 기반 프로젝트에서 TDD를 하는 방법은 순수 자바 TDD와는 꽤 많이 달랐다. Layer 별로 개발해야하고, DB 테스트, Mocking 등 다양한 상황과 변수들이 있었고 배운 걸 써먹기에는 한계가 있었다. 이번 스터디를 진행하며, 이전에 배운 클린코드를 복기하고 스프링을 사용한 TDD를 학습하고자 한다.1주차 학습1주차에는 추상과 구체, 사고를 줄이는 코드 작성법, 객체지향적인 코드(SOLID)에 대해 학습했다. 클린 코드 파트는 내가 올해 초에 수료한 교육기관의 과정이 지금 우빈님의 수업과 굉장히 유사하다. 그도 그럴 것이, 두 분 다 우아한테크코스에 관련되어 계시기 때문에 커리큘럼과 추구하는 클린 코드가 비슷할 것이라 생각한다. 덕분에 내가 배웠던 것을 잘 복기하고 있다. 추상1주차에서 가장 중요하다고 생각하는 부분은 추상에 대한 고찰이다. 컴퓨터는 끝없는 추상의 연속이다. 나 역시 개발자는 끊임없이 무언가를 추상화하는 직업이라고 생각한다. 그렇기 때문에 더더욱 추상과 구체에 대해 이해해야한다. 구현체에서 인터페이스를 뽑아내는 것, 변수나 메서드의 이름을 잘 짓는 것도 추상화이다. 구체에서 어떤 개념을 뽑아내는 것이 추상이기 때문에, 추상화된 것들을 보면 구체가 뭘 할 지 대충 예상할 수 있어야 한다. 메서드로 예를 들어보자. 메서드는 메서드 시그니처(메서드 명과 매개 변수 타입&개수)와 구현(내부 코드)으로 나뉘어져 있다. 메서드 시그니처만 보고, 어떻게(How) 구현되어 있는 지 알 수는 없지만 무엇을(What) 해줄 것인 지는 유추할 수 있어야한다. 그렇지 못한 메서드 시그니처는 추상화에 실패한 것이며 이를 사용할 팀원, 미래의 나에게 무례한 것이다. 클린 코드강의에서는 뇌 메모리 적게 쓰기. 즉, 코드를 읽는 사람으로 하여금 기억해야할 컨텍스트를 줄이는 것이 중요하다고 한다. 이 부분은 매우 동의하고 강의에 나온 것들 모두 실무 개발할 때에도 적극적으로 활용하고 있는 부분들이다. Early Return, 사고의 depth 줄이기, 공백 라인을 대하는 자세, 부정어를 대하는 자세, 해피 케이스와 예외 처리 이다.개인적으로 Early Return과 사고의 depth 줄이기 부분은 조금 조심해서 적용해야한다고 생각한다.Early Return 이전에도 Early Return에 대해 학습한 적이 있어서, Early Return을 할 수 있으면 최대한 사용한다. 그런데 커리어 내내 if, else-if, else 만을 사용해왔던 내 상사는 이 부분을 잘 이해하지 못한다. 작성한 코드를 곰곰이 쳐다보면, 그냥 else를 사용하는 게 이해하기 쉽겠는데? 하는 부분들이 있다. 또한, 강의에서도 우빈님이 else를 불가피하게 써야할 때가 있다는 뉘앙스로 말씀하셨고, 나 역시 너무너무 억지로 Early Return을 하는 것은 그리 좋은 습관인 것 같지 않다.사고의 depth 줄이기이 부분도 Early Return과 비슷한 맥락인데, 억지로 depth를 줄이려고 불필요한 메서드를 만들거나 스트림을 사용하게되는 경우가 많다. 스트림을 적극 활용하는 것이 분명 자바 생태계에서 일반적으로 좋지만, 스트림을 잘 모르는 개발자들에게는 조금 난해할 수도 있다. 후배 개발자라면 같이 공부하겠지만 상사가 스트림을 모르면 난처하다..ㅎㅎ  SOLID객체지향하면 SOLID는 빼놓을 수 없다. 이에 대해 자세하게 학습하였고, 각각의 원칙을 기존 코드를 리팩터링하며 코드로 적용해보았다. SOLID에 대한 내용은 미션에서 작성하였으므로 생략한다. 객체지향 적용하기상속과 조합, VO, 일급 컬렉션, Enum 등을 학습하였다. 이 파트는 코드 따라치기가 분량이 너무 많아서 조금 힘들었다. 그래도, 조합에 대해 알아보고 VO, 일급컬렉션, Enum 등 아는 것들을 복기해볼 수 있는 좋은 파트였다. 나도 Enum 사용하는 것을 매우 좋아하는데, Enum을 구현체로 만드는 것은 해보지 못했다. 또, Enum 각각의 구현체를 인라인으로 생성하여 오버라이드하는 것 역시 신기한 방법이었다. Enum의 원리에 대해 다시 공부해보려고 한다. 미션이번 주 미션은 총 두 개 였으며, 무엇이든 추상화된 것을 구체화해보는 것과, SOLID를 자기 언어로 표현 + 코드 리팩터링이다. 추상화된 것을 구체화내가 퇴근하면서 생각한 것이라, 퇴근 그 자체를 구체화해봤다. 우리가 퇴근이라고 하면 어쨌든 업무를 마무리하고, 근무지에서 나와서 집으로 향하는 것을 말한다. SOLID를 자기 언어로 표현 + 코드 리팩터링해당 미션은 인프런 블로그에 좀 자세하게 길게 썼기 때문에 중복된 내용일 것 같다. 개발자는 중복을 제거하는 것도 중요하기 때문에 중복 제거를 위해 작성하지 않고 링크만 첨부하겠다. https://www.inflearn.com/blogs/8370아직 1주차라 미션이 꽤 간단했다고 생각한다. SOLID에 대해 다시 고민해보는 것은 꽤 좋은 미션이었다. 취준할 때나 생각하지, 실무에 들어선 이상 SOLID를 지켜가며 개발하긴 어렵다. 하지만 사실 SOLID를 지켜야 리팩터링하기에도 테스트하기에도 갑자기 바뀌는 요구사항에 대응하기에도 좋은 코드라는 것을 너무나도 잘 알고있다. 이번 미션을 계기로 실무에서도 SOLID를 생각해보려고 한다.

연이

인프런 워밍업 클럽 스터디 2기 CS | 1주차 미션

운영체제위 코드는 1초 마다 플레이어가 스킬을 사용했는지 체크하는 코드입니다. 이 방식은 폴링방식입니다. 1초마다 체크하기 때문에 성능에 좋지 않습니다. 이를 해결하기 위한 방식으로 어떤 걸 이용해야 할까요?while(true){ wait(1); // 1초 멈춤 bool isActivated = checkSkillActivated(); // 체크 }인터럽트 방식인터렙트 방식은 작업이 완료되었는지 계속해서 확인하지 않고 비동기적으로 동작하기 때문에 폴링 방식보다 성능이 좋음프로그램과 프로세스가 어떻게 다른가요?프로그램(애플리케이션, 앱)하드디스크 등과 같은 저장장치(HDD, SSD)에 저장된 명령문의 집합체Windows 운영체제에서는 .exe 파일의 모습컴퓨터 관점에서 프로그램은 저장 장치만 사용하는 수동적인 존재프로세스하드디스크에 저장된 프로그램이 메모리에 올라갔을 때 실행 중인 프로그램컴퓨터 관점에서 프로세스는 메모리도 사용하고 운영체제의 CPU스케줄링 알고리즘에 따라서 CPU도 사용,필요에 따라 입력과 출력을 하기 때문에 능동적인 존재멀티프로그래밍과 멀티프로세싱이 어떻게 다른가요?멀티프로그래밍메모리에 여러 개의 프로세스가 올라온 것을 말함멀티프로세싱CPU가 여러 개의 프로세스를 처리하는 것을 말함운영체제는 프로세스를 관리하기 위해서 어떤 것을 사용하나요?PCB(Process Control Block) 프로세스가 만들어지면 운영체제는 해당 프로세스의 정보를 가지고 있는 PCB를 만들고 저장PCB들은 연결리스트 자료구조로 저장 컨텍스트 스위칭이란 뭔가요? 프로세스 실행 중에 다른 프로세스로 변경하기 위해 실행 중인 프로세스의 상태를 저장하고 다른 프로세스의 상태값으로 교체하는 작업 컨텍스트 스위칭이 발생할 때 PCB에서 프로세스 상태, 프로그램 카운터, 레지스터 정보, 메모리 관련 정보 등이 변경컨텍스트 스위칭이 발생하는 이유는 CPU점유 시간을 초과했거나, I/O요청이 있거나 다른 종류의 인터럽트가 있을 때 발생 자료구조와 알고리즘여러분은 교실의 학생 정보를 저장하고 열람할 수 있는 관리 프로그램을 개발하려고 합니다.이 때 여러분이라면 학생의 정보를 저장하기 위한 자료구조를 어떤 걸 선택하실 건가요? 이유를 함께 적어주세요. 배열을 선택할 것입니다. 학생 정보 조회가 가장 빈번한 작업일 것으로 예상되며, 배열은 인덱스를 통합 빠른 접근으로 시간복잡도가 O(1)이기 때문입니다. 전학을 오거나 가는 경우처럼 데이터가 추가되거나 삭제가 될 수 있겠지만 이는 상대적으로 드문 이벤트입니다. 데이터의 크기가 크게 변경되지 않을 것이라 예상되어 연결리스트보다 배열이 적합할 것같습니다.여러분은 고객의 주문을 받는 프로그램을 개발하려고 합니다. 주문은 들어온 순서대로 처리됩니다. 이 때 여러분이라면 어떤 자료구조를 선택하실 건가요? 이유를 함께 적어주세요. FIFO 선입선출 방식의 Queue를 선택할 것입니다. 주문을 먼저한 손님 순으로 서비스가 제공되어야하기 때문입니다. 

후루바

[인프런 워밍업 클럽 2기 - CS] 1주차 미션

운영체제1.while(true){ wait(1); // 1초 멈춤 bool isActivated = checkSkillActivated(); // 체크 }위 코드는 1초 마다 플레이어가 스킬을 사용했는지 체크하는 코드입니다.이 방식은 폴링방식입니다. 1초마다 체크하기 때문에 성능에 좋지 않습니다.이를 해결하기 위한 방식으로 어떤 걸 이용해야 할까요?답변 : 인터럽트 방식. CPU는 입출력 관리자에게 명령을 내리고 자기는 다른 작업을 한다. 그리고 입출력관리자는 작업이 완료되면 CPU에게 알리고, CPU는 ‘신호’를 받아 인터럽트 서비스 루틴(ISR)을 실행시켜 작업을 완료한다. 따라서 주기적으로 체크하지 않는 폴링방식보다 신호를 받아 처리하는 인터럽트 방식이 더 효과적이다.프로그램과 프로세스가 어떻게 다른가요?답변 :프로그램은 어플리케이션을 말하고, 이 프로그램이 메모리에 올라간 상태를 프로세스라고 한다.멀티프로그래밍과 멀티프로세싱이 어떻게 다른가요? 답변 : 멀티 프로그래밍은 메모리에 여러 개의 프로세스가 올라온 상태를 말하고, 멀티프로세싱은 CPU 입장에서 CPU가 여러개의 프로세스를 처리하는 것을 말한다.운영체제는 프로세스를 관리하기 위해서 어떤 것을 사용하나요?답변 : PCB를 사용한다. PCB는 Process Contorl Block으로 연결리스트라는 자료구조로 이루어져 있고, PCB에는 포인터, 프로세스상태, 프로세스 ID등 프로세스의 관련된 정보가 저장된다.컨텍스트 스위칭이란 뭔가요? 답변 : 컨텍스트 스위칭은 프로세스를 실행하는 중에 프로세스의 상태를 저장하고, 다른 프로세스의 상태값으로 교체하는 작업이다. 실행중인 작업을 PCB에 저장하고, 실행될 프로세스의 PCB 내용대로 CPU가 다시 세팅된다.자료구조와 알고리즘여러분은 교실의 학생 정보를 저장하고 열람할 수 있는 관리 프로그램을 개발하려고 합니다.이 때 여러분이라면 학생의 정보를 저장하기 위한 자료구조를 어떤 걸 선택하실 건가요? 이유를 함께 적어주세요. 답변 : 배열을 사용할 것입니다. 배열은 모든 학생의 정보를 차례대로 저장할 수 있고, 학생마다 번호를 부여했을 때 인덱스를 사용해서 빠르게 조회가 가능하기 때문입니다.여러분은 고객의 주문을 받는 프로그램을 개발하려고 합니다. 주문은 들어온 순서대로 처리됩니다. 이 때 여러분이라면 어떤 자료구조를 선택하실 건가요? 이유를 함께 적어주세요. 답변 : 큐를 사용할 것입니다. 큐는 First In First Out으로 들어온대로 주문을 처리하기 때문입니다.

김민성

[워밍업 클럽 스터디 2기 - BE] 1주차 발자국

[인프런 워밍업 클럽 스터디 2기 - 백엔드 클린 코드, 테스트 코드 (Java, Spring Boot)]([Readable">https://www.inflearn.com/course/offline/warmup-club-2-be-wb)[Readable">[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)해당 내용을 바탕으로 작성된 블로그 입니다.추상우리가 클린 코드를 추구하는 이유가독성 - Readability글이 잘 읽힌다 = 이해가 잘 된다. = 유지보수 하기 수월해진다. = 우리의 시간과 자원이 절약된다. 클린코드를 관통하는 아주 중요한 주제바로 추상(抽象) 추상과 구체도메인 영역에서 핵심만 남기는 행위가 추상, 이를 보고 유추할 수 있는게 구체중요한 정보는 가려내어 남기고, 덜 중요한 정보는 생략하여 버린다 추상화의 가장 대표적인 행위 : 이름 짓기 이름 짓기이름을 짓는다는 행위는, 추상적 사고를 기반으로 한다. 이름 짓기 팁단수와 복수를 구분하기이름 줄이지 않기은어/방언 사용하지 않기좋은 코드를 보고 습득하기단수와 복수를 구분하기끝에 '(e)s'를 붙여 어떤 데이터(변수, 클래스 등)가 단수인지, 복수인지를 나타내는 것만으로도 읽는 이에게 중요한 정보를 같이 전달할 수 있다.이름 줄이지 않기줄임말이라는 것은 가독성을 제물로 바쳐 효율성을 얻는 것으로, 대부분 잃는 것에 비해 얻는 것이 적다.은어/방언 사용하지 않기농담에서 파생된 용어, 일부 팀원/현재의 우리 팀만 아는 용어 금지Q. 새로운 사람이 합류했을 때 이 용어를 단번에 이해할 수 있는가?도메인 용어 사용하기도메인 용어를 먼저 정의하는 과정(ex. 도메인 용어 사전)이 먼저 필요할 수도 있다.좋은 코드를 보고 습득하기비슷한 상황에서 자주 사용하는 단어, 개념 습득하기→ ex. pool, candidate, threshold 등 https://github.com/iamminseongKim/readable-code/commit/3d1497c43f386f10b8d312623d9a26bf5879b97d이름을 지으면서 코드를 읽을 수 있게 됐다. 메서드와 추상화국어/영어 독해할 때 잘 쓰여진 글이라면 한 문단의 주제는 반드시 하나다.메서드의 이름으로 구체를 추상화 하는 것이다.잘 쓰여진 코드라면 한 메서드의 주제는 반드시 하나다. 메서드 선언부* 메서드 시그니처 : 메서드명 + 파라미터 (메서드 오버로드)메서드명추상화된 구체를 유추할 수 있는, 적절한 의미가 담긴 이름파라미터와 연결지어 더 풍부한 의미를 전달할 수도 있다.파라미터파라미터의 타입, 개수, 순서를 통해 의미를 전달파라미터는 외부 세계와 소통하는 창반환타입메서드 시그니처에 납득이 가는, 적절한 타입의 반환값 돌려주기반환 타입이 boolean인데, 이게 이 메서드에서 무엇을 의미하는지?void 대신 충분히 반환할 만한 값이 있는지 고민해보기반환값이 있다면 테스트도 용이해진다.[지뢰찾기 - 메서드 추출](https://github.com/iamminseongKim/readable-code/commit/66523910ce932a0e103f22bc3ecf2d93f418e116#diff-9f9444b48fc52a78913dc852f9b4c9a5cc42aa4e5525c09fe92c5d24b6e41182) 추상화 레벨하나의 세계 안에서는, 추상화 레벨이 동등해야 한다.public static void main(String[] args) { showGameStartComments(); initializeGame(); showBoard(); if (gameStatus == 1) { System.out.println("지뢰를 모두 찾았습니다. GAME CLEAR!"); break; } ... checkIfGameIsOver(); }자 이 코드에서 메서드를 쭉쭉 호출하다가 갑자기 gameStatus == 1 이런 코드가 나와 멈칫하게 된다.이러한 점이 레벨이 안맞다는 점이다.그럼public static void main(String[] args) { showGameStartComments(); initializeGame(); showBoard(); if (doesUserWinTheGame()) { System.out.println("지뢰를 모두 찾았습니다. GAME CLEAR!"); break; } ... checkIfGameIsOver(); } private boolean doesUserWinTheGame() { return gameStatus == 1; }다음과 같이 레벨을 맞춰주자. 매직 넘버, 매직 스트링 매직 넘버, 매직 스트링?의미를 갖고 있으나, 상수로 추출되지 않는 숫자, 문자열 등상수 추출로 이름을 짓고 의미를 부여함으로써 가독성, 유지보수성 증가 [추상화 레벨 & 매직 넘버, 매직 스트링](https://github.com/iamminseongKim/readable-code/commit/ccdb4d9894b82c6f340acfb7543414423669a296)상수를 뽑아내므로써 가독성, 유지보수성이 증가한걸 느낌. 논리, 사고의 흐름뇌 메모리 적게 쓰기정리하는 뇌 : 정리 시스템에서 중요한 과제는 최소의 인지적 노력으로 최대의 정보를 제공하는 것이다.도둑맞은 집중력 : 뇌는 한 번에 한 가지 일밖에 하지 못한다. 멀티테스킹? 그건 저글링일 뿐.인지적 경제성뇌 메모리 적게 쓰기.. 읽는 사람이 뇌를 적게 쓰기 위해 만들 때 잘 쓰자.. Early returnif (a > 3) { doSomething1(); } else if (a <= 3 && b > 1) { doSomething2(); } else { doSomething3(); }이 if문을 쭉쭉 내려가면서 생각해보면마지막 else를 생각할 때 쯤이면 모든 if 조건을 다 인지하고 있어야 그 예외를 생각하고 doSomething3()이 실행되겠구나 생각할 것이다.이걸 해결하기 위해서 사용하면 좋은 것이 Early return이다. extracted(); void extracted() { if(a > 3) { doSomething1(); return; } if(a<=3 && b>1) { doSomething2(); return; } doSomething3(); } Early return으로 else의 사용을 지양, else를 쓰지 않아도 되면 쓰지 않도록 노력하자.[Early return 코드](https://github.com/iamminseongKim/readable-code/commit/31dc6569a71028141c665e2f341eb7d05cb0896f)사고의 depth 줄이기중첩 분기문, 중첩 반복문중첩 for문을 지양하고 바깥이 어떻게 도는지 알 필요 없게 만들자. 주의"무조건 1depth로 만들어라"가 아니다.보이는 Depth를 줄이는데 급급한 것이 아니라 추상화를 통한 사고 과정의 depth를 줄이는 것이 중요2중 중첩 구조로 표현하는 것이 사고하는데에 더 도움이 된다고 판단한다면, 메서드 분리보다 그대로 놔두는 것이 더 나은 선택일 수 있다. 떄로는 메서드를 분리하는 것이 더 혼선을 줄 수 있다.[예제 코드 - 중첩 for문 (Stream 사용)](https://github.com/iamminseongKim/readable-code/commit/37eaf9ebc8f5c4774cf295d5e3be3dfb82b1c9bb) 사용할 변수는 가깝게 선언하기int i = 10; // 저 ~~아래 한 20줄 int j = i + 30;이런 식으로 사용하지 말자.// 저 아래 20줄 int i = 10; int j = i + 30;가깝게 선언하자.[예제 코드 - scanner 수정(상수로 또 뺌)](https://github.com/iamminseongKim/readable-code/commit/bd15a345918cf602506cb8182a4aa5b90a826877) 공백 라인을 대하는 자세공백 라인도 의미를 가진다복잡한 로직의 의미 단위를 나누어 보여줌으로써 읽는 사람에 추가적인 정보를 제공할 수 있다.부정어를 대하는 자세부정어구를 쓰지 않아도 되는 상황인지 체크부정의 의미를 담은 다른 단어가 존재하는지 고민하기 or 부정어구로 메서드명 구성부정 연산자(!) 는 가독성이 떨어질 수 있다.[예제 코드 - isLandMineCell()에 부정연산자 제거한 과정](https://github.com/iamminseongKim/readable-code/commit/1070112c4dfd0d230f1edbda6ad0a2d8f612509c) 해피 케이스와 예외 처리사람은 해피 케이스에 몰두하는 경향이 있다.예외처리를 꼼꼼히 해야 소프트웨어가 견고해진다.예외가 발생할 가능성 낮추기어떤 값의 검증이 필요한 부분은 주로 외부 세계와의 접점사용자 입력, 객체 생성자, 외부 서버의 요청 등의도한 예외와 예상하지 못한 예외를 구분하기사용자에게 보여줄 예외와, 개발자가 보고 처리해야 할 예외 구분Null을 대하는 자세항상 NullPointException을 방지하는 방향으로 경각심을 가지자.메서드 설계 시 return null을 자제한다.만약 어렵다면, Optional 사용을 고민해본다.Optional에 관하여Optional은 비싼 객체이다. 꼭 필요한 상황에서 반환 타입에 사용한다.Optional을 파라미터로 받지 않도록 한다. 분기 케이스가 3개나 된다.Optional이 가진 데이터가 null인지 아닌지, + Optional 그 자체가 Null인지Optional을 반환 받았다면 최대한 빠르게 해소한다.Optional을 해소하는 방법분기문을 만드는 isPresent()-get() 대신에 풍부한 API 사용ex) orElseGet(), orElseThrow(), ifPresent(), ifPresentOrElse()orElse(), orElseGet(), orElseThrow()의 차이 숙지orElse() : 항상 실행, 확정된 값일 때 사용orElseGet() : null인 경우 실행, 값을 제공하는 동작(Supplier) 정의orElseThrow() : 그냥 쓰면됨, 없으면 예외 만들어서 던짐.[해피 케이스와 예외처리 - 예제](https://github.com/iamminseongKim/readable-code/commit/cb02070c415ed2f2c70cf417cca0701015fe2f18) 객체 지향 패러다임정해진 순서 차례대로 진행하는 프로그래밍 절차 지향객체라는걸 만들어서 상호 작용을 하도록 개발하는 객체지향사이드 이펙트가 없는 a를 넣으면 항상 같은 리턴을 주는 순수 함수이런 함수를 기반으로 개발하는 함수형 프로그래밍 추상의 관점으로 바라보는 객체 지향객체 : Object, 추상화된 (데이터 + 코드)협력과 책임객체간의 협력 + 객체가 담당하는 책임캡추상다캡슐화 : 객체가 가지고있는 데이터, 로직을 숨기고 일부만 보여줌추상화 : 요약상속 : 진짜 필요한 곳에만 사용다형성 : 인터페이스화 추상화관심사의 분리Seperation Of Concern높은 응집도, 낮은 결합도a라는 관점을 모아서 관리 -> 유지보수성 증가그리고 이렇게 모인 관심사들 끼리는 결합도가 낮게 개발.a를 수정했는데 b에 영향이 없게 개발. 객체 설계하기 1오브젝트도 데이터나 로직은 숨기고, 이를 공개적인 메서드를 통해서만 외부에서 소통할 수 있도록 추상화 해야 한다.비공개 필드 (데이터), 비공개 로직(코드)공개 메서드 선언부를 통해 외부 세계와 소통각 메서드의 기능은 객체의 책임을 드러내는 창구객체의 책임이 나뉨에 따라 객체간 협력이 발생객체가 제공하는 것절차 지향에서 잘 보이지 않았던 개념을 가시화관심사가 한 군데로 모이기 때문에, 유지보수성 증가객체 내부에서 객체가 가진 데이터의 유효성 검증 책임을 가질 수 있다.여러 객체를 사용하는 입장에서는, 구체적인 구현에 신경쓰지 않고 보다 높은 추상화 레벨에서 도메인 로직을 다룰 수 있다.새로운 객체를 만들 때 주의할 점1개의 관심사로 명확하게 책임이 정의되었는지 확인하기메서드를 추상화 할 때와 비슷하다.객체를 만듦으로써 외부 세계와 어떤 소통을 하려고 하는지 생각해보자.생성자, 정적 팩토리 메서드에서 유효성 검증이 가능하다.도메인에 특화된 검증 로직이 들어갈 수 있다. setter 사용 자제데이터는 불변이 최고다. 변하는 데이터더라도 객체가 핸들링할 수 있어야 한다.객체 내부에서 외부 세계의 개입 없이 자체적인 변경/가공으로 처리할 수 있는지를 확인만약 외부에서 가지고 있는 데이터로 데이터 변경 요청을 해야하는 경우, 'set~'이라는 단순한 이름보다는 update~같이 의도를 드러내는 네이밍을 고려하자.getter도 처음에는 사용 자제. 반드시 필요한 경우에 추가하기외부에서 객체를 내 데이터가 필요하다고 getter를 남발하는 것은 무례한 행동이다!객체에 메시지를 보내라! 필드의 수는 적을수록 좋다.불필요한 데이터가 많을 수록 복잡도가 높아지고 대응할 변화가 많아진다.필드 A를 가지고 계산할 수 있는 A'필드가 있다면, 메서드 기능으로 제공단, 미리 가공하는 것이 성능 상 이점이 있다면, 필드로 가지고 있는 것이 좋을 수도 있다.도메인 지식은 만드는 것이 아니라 발견하는 것[Board 객체화](https://github.com/iamminseongKim/readable-code/commit/2c04b02413a879e3135a1fd905abb445a4d9dcd9)[Board - Sign Cell 넣기](https://github.com/iamminseongKim/readable-code/commit/7a593983ce867b9233172344189b781c6bf207c1)[cell을 도메인 지식을 통해 리팩토링](https://github.com/iamminseongKim/readable-code/commit/295a3d84a208216fc630e52dee08cbfb1385abfc) SOLIDSRP : Single Responsibility PrincipleOCP : Open-Closed PrincipleLSP : Liskov Substitution PrincipleISP : Interface Segergation PrincipleDIP : Dependency Inversion Principle [SRP - 메인 메서드 분리](https://github.com/iamminseongKim/readable-code/commit/2000d6314228806ebd478954cdd822dff38699a9)[SRP - 사용자 입출력 클래스 분리](https://github.com/iamminseongKim/readable-code/commit/50a1eba65893e74e931cfa5b7c332c031a07e9ea)[SRP - GameBoard 클래스로 분리](https://github.com/iamminseongKim/readable-code/commit/53521ae2db988d90cca080b7890ae4ce9531f7ed) [OCP - 난이도 조절하기 전에 가로 세로 갯수 대응하기](https://github.com/iamminseongKim/readable-code/commit/28d0ea71ea8a21b69cd9dff601ca0cc1a0488e00)[OCP - 난이도 조절하기 내용 구현](https://github.com/iamminseongKim/readable-code/commit/56d37d6e469874f5955209307288506717637c35)[LSP - Cell 역할에 따라 분리](https://github.com/iamminseongKim/readable-code/commit/e3edbcb8c21b7c9b922f98e2e463f4f3f74c90b0) [ISP-게임 인터페이스 구현 및 기능 쪼개기](https://github.com/iamminseongKim/readable-code/commit/47d2a2c4d7c135e4dc8bb9c5c3f4a8fb57cf3a2b) [DIP - 사용자 입력 방식 인터페이스로 바꾸기](https://github.com/iamminseongKim/readable-code/commit/a560adbb557dc4f368a566126b5ec591f98219fd) [DIP - OutputHandler 의 용어 정리 - show, print](https://github.com/iamminseongKim/readable-code/commit/582199fa6907cc470139bcb8868aad9678f1e8c8) 객체 지향 적용하기상속과 조합상속보다 조합을 사용하자![객체지향 적용하기 - 상속과 조합 - 셀을 상속에서 조합으로 바꾸기](https://github.com/iamminseongKim/readable-code/commit/86a49db553a752eca745a0d462125ee0d0b4ad70)Value Object도메인의 어떤 개념을 추상화하여 표현한 값 객체값으로 취급하기 위해서 불변성, 동등성, 유효성 검증 등을 보장해야 한다.불변성 : final 필드, setter 금지동등성 : 서로 다른 인스턴스여도(동일성이 달라도), 내부의 값이 같으면 같은 값 객체로 취급한다. equals() & hashCode() 재정의 필요유효성 검증 : 객체가 생성되는 시점에 값에 대한 유효성을 보장하기만원 지폐가 일렬번호(인스턴스)가 다르다고 가치가 다른 즉 다른 만원인가? VO vs Entity class UserAccount { private String userId; // 식별자 private String 이름; private String 생년월일; private Address 집주소; }이건 Entityclass Address { private String 시도; private String 시군구; private String 도로명; private String 건물번호; }이건 VO 이다. Entity는 식별자가 존재한다. 식별자가 아닌 필드의 값이 달라도, 식별자가 같으면 동등한 객체로 취급한다.equals() & hashCode()도 식별자 필드만 가지고 재정의할 수 있다. 식별자가 같은데 식별자가 아닌 필드의 값이 서로 다른 두 인스턴스가 있다면, 같은Entity가 시간이 지남에 따라 변화한 것으로 이해할 수 있다.VO는 식별자 없이 내부의 모든 값이 다 같아야 동등한 객체로 취급한다.개념적으로, 전체 필드가 다 같아야 식별자 역할을 한다고 생각해도 된다. [Value Object - Cell의 상태를 value object로 만들기.](https://github.com/iamminseongKim/readable-code/commit/b667b43de3dfa2fa78fc6a4baf24af570acf69d6) 미션미션 1 추상과 구체 예시내가 생각한 추상은 모두가 이해할 수 있도록 말을 요약이라 생각해서내가 좋아하는 야구에서 이 예시를 찾아봤다.야구를 좀 본사람은 4-6-3 병살 저 6자만 봐도 어떤 일이 일어났는지 바로 이해할 것이다.그래서 나는 이걸로 미션을 제출했다. 미션 2 코드 리팩토링주문관련 코드를 리팩토링 하는 미션이였다.코드를 보면 if-else로 많이 감싸져 있어서 그걸 제일 먼저 Early return을 이용해서 바꿔줬고,그 다음엔 return false보다는 예외로 값이 잘못된 것을 알려줬다.마지막으로 if문 안에 추상화 레벨을 맞추기 위해 메서드를 추출했다. 아쉬운 점은 예외를 커스텀 예외로 만드는 걸 안했고, if문 검증 로직을 굳이 service단이 아니라 order객체 내에서했어도 좋았을 것 같다는 생각을 했다. 느낀점자바를 2년이상 써오면서 원래 알았던 개념도 있고, 처음 봤던 개념도 있었다.그런데 이번 내용들을 학습하면서 항상 클린코드 클린코드 해야지 생각만 하던걸이젠 직접 어떻게 작성 해야하는지, 어떤 점을 고려해야 하는지 좀 감을 잡을 수 있었던 것 같다. 솔직히 공부를 많이 안했던 것 같아서 좀 부끄럽지만 이번 계기로 클린코드와 테스트 코드에 자신감을 가질 수 있도록 노력하겠다.  

백엔드워밍업클럽

wisehero

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

이번 주는 클린한 코드를 작성하는 방법에 대해서 쭉 배웠습니다.수강하면서 가장 느꼈던 것은 클린 코드는 단순히 '나 이렇게 코드 깔끔하게 짠다'라는 것을 자랑하기 위함이 아닌내가 아닌 함께 일하는 동료를 위한, 이타적인 행위임을 느꼈습니다. 학습 내용 요약 Day 2 - 추상과 구체추상과 구체 시간에는 다시 한번 추상화를 잘하는 것이 클린한 코드의 시작점임을 깨달았습니다.강사님께서 파블로 피카소가 한 말을 말씀하신 것이 인상 깊었는데요. 추상은 항상 구체적인 실재에서 시작해야 한다.사실 얼마전에 팀에서 개발하던 프로젝트가 지나치게 '이른' 추상화 때문에 모든 팀원이 고생한 적이 있습니다.외부 서버와 통신하는 클라이언트를 공통화 했는데, 너무 섣부른 나머지 추가적인 요구사항에 전혀 대응을 할 수없었습니다. 앞으로 나올 구체적인 실재들을 간과한 추상화가 문제였기 때문입니다. 최근의 경험과 더불어서저 문장을 보고 구체와 추상간의 Context Switching을 잘 해야겠다고 생각이 들었습니다. Day 3 - 논리, 사고의 흐름 | 객체 지향 패러다임Day 3의 주제들은 사실 미리 알고 있었던 내용입니다. 저도 입사하고나서 다른 팀원들에게 적극적으로권유하고 있는 방법입니다. 논리, 사고의 흐름이라는 섹션은 딱 하나의 주제를 관통합니다."읽는 사람으로 하여금 덜 고생하게 하자"우리의 뇌를 메모리에 비유하여 읽는 사람으로 하여금 이 자원을 덜 쓰도록 하는 것이 좋은 코드라는 가르침을얻었고 Early Return이나 Depth 줄이기(else 지양), 공백에 의미 부여하기, 부정어를 가급적이면 사용하지 않기처럼 실제로 글쓰기나 말하기에서도 중요한 것들을 코드에 녹이는 방법을 배웠습니다. Day 4 - SOLIDDay 4는 객체 지향의 Core라고 할 수 있는 SOLID입니다. 지뢰찾기 게임을 이 원칙에 맞춰서 리팩토링 해나아갔는데요. 제가 이해한 SOLID는 서로 많이 연관되어 있습니다. 하나의 톱니바퀴 여러개를 맞물려야하는 느낌이었는데요. 이 원칙을 지키는데에 있어서 가장 중요한 것은 도메인 지식을 잘 이해하고 있는 것이 중요하다고 생각합니다. 그래야 필요한 인터페이스는 뭐가 있고 그 인터페이스의 명세는 어떻게 되어야 하며, 객체 간 책임분리를 통한 올바른 설계를 완성할 수 있는 것 같습니다. 개인적으로 단순히 기획서의 디스크립션만 보고 급급하게기능을 개발했던 지난 날을 반성하게 되었습니다. Day 5 - 객체 지향 적용하기Day 5에서 배운 것들 중에서는 상속과 조합, 일급 컬렉션이 가장 기억에 남았습니다. 사실 상속보다는 조합을지향하라는 문구를 본 적은 있는데 실제로 적용을 해본 적은 없었거든요. 이번에 좋은 레퍼런스를 얻었고단순한 상속보다는 약간은 더 복잡하고 코드 양이 늘어나지만 변경에 유연한 조합을 추후에 사내 프로젝트에서적용해보고 싶다는 생각이 들었습니다. 또한 일급 컬렉션의 효용성과 불변성에 대해서 다시 중요성을 깨달았습니다.  개인적으로 칭찬하는 점은 강의를 들으면서 알고 있는 내용도 있었고 몰랐던 내용도 있었는데요.알고 있는 내용에 대해서 강의를 들을 땐 '이렇게 소스 코드를 정리하실 거 같은데?' 라는 생각이 들때쯤제 예상이 맞았던 적이 많았습니다. 이전에 배웠던 것들을 그래도 잘 머릿속에 담아두고 있구나 라는 생각이들었구요. 아쉬웠던 점은 강의에서 배웠던 점들을 적용시키는데 있어서 그 적용 범위를 확장하지 못하고 있는 것 같습니다. 아무래도 경험 부족이 원인인 것 같은데 이 부분은 시간이 해결해주리라 믿고 있겠습니다 ㅠㅠ 발자국 끝!

백엔드백엔드클린코드테스트코드워밍업클럽

jenhuhh

인프런 워밍업 프로덕트 디자인 1주차 발자국

강의 요약 1. 디자인 토큰, 디자인 시스템, 베리어블 1-1) 디자인 토큰디자인 토큰은 UI 요소의 기본 구성 요소로, 작고 반복 가능한 디자인 결정을 의미하며 Brad Frost's Atomic Design 개념 중 '전자(Electrons)'에 속함Brad Frost's Atomic Design'Electrons' > Atom > Molecules > Organisms > Templates > PagesElectrons - 색상, 타이포그래피, 테두리, 그림자 효과를 포함위 디자인이 결정되면 json 포맷으로 내보내어 여러 플랫폼에 적용할 수 있다.→ json 포맷으로 '어떻게' 내보내지고 개발자들이 플랫폼에 '어떻게' 적용하는지 이해가 부족해서 개발팀에게 도움을 요청해야겠다. 1-2) 디자인 시스템디자인 시스템은 일관성과 확장성을 가진 컴포넌트, 패턴, 가이드의 모음디자인 시스템의 장점: 디자인 일관성, 브랜드 강화, 개발 효율성, 시간 단축, 팀 간 협업 강화, 빠른 온보딩, 유지보수 용이, 높은 품질의 경험디자인 시스템의 구성 요소디자인 원칙/철학스타일 가이드컴포넌트 라이브러리패턴 라이브러리문서화시스템 관리 운영 디자인 시스템을 성공하기 위해서비즈니스, 디자인, 개발의 이해와 꾸준한 커뮤니케이션이 필요 꾸준히 발전해나가는 하나의 프로덕트의 개념 1-3) 베리어블 이름과 구조베리어블 구조: 이름(Name), 값(Value), 유형(Type)베리어블 계층 (피라미드 구조)Raw Value: 본래의 값 #D6840BGlobal/primitive/core/base/foundation/root: 사용 맥락에 상관없이 디자인 언어의 기본 값 Orange-MediumAlias/semantic/applied/purpose: 특정 사용 맥락과 의도를 전달할 때 쓰이는 값 Band-primaryComponent/overwrites/scoped: 컴포넌트와 관련된 모든 디자인 속성을 가진 값 Button-primary-background-color베리어블 이름Namespace(System) + Object(Component) + Base(Category/Property) + Modifier(Variant/State/Scale)Namespace다른 디자인 시스템과 구분하기 위해 주로 모든 베리어블/토큰 앞에 접두어로 시작한다. Ojbect디자인 시스템 내에서 특정 컴포넌트의 스타일 및 레이아웃을 적용하고 싶을 때 사용된다.Button, card, input 등BaseCateogry - UI 기본 구성 요소를 공통된 유형으로 그룹화color, font, sizing, spacing 등Property - 각 카테고리 내에서 특성에 따라 세분화한 것color-background, color-border, font-style, font-sizing, radius 등Modifier하나의 디자인 요소를 여러 상황, 상태에 따라 변형할 수 있도록 한다.Variant - Hierarchy(primary, secondary, tertiary), Feedback(success, error, information, warning)State - Interactive StatesScale - 숫자 (1,2,3,4...), 티셔츠 사이즈(xs, sm, md...) 등 이름 지을 때 실무팁개발자와 디자이너 사이에 공통된 이름 짓기 → 회사 프로젝트가 이미 진행이 많이 됬기 때문에, 실무에 적용하기 전에 개발팀에서 사용하고 있는 용어를 먼저 파악해야할 것 같다. 중복, 혼동되는 단어 통일하기스케일 척도 통일하기미리 80% 정도 계획할 것 (엑셀/피그잼 활용)레퍼런스, 레퍼런스, 레퍼런스!   2. 베리어블과 파운데이션 세팅하기강사님이 공유해주신 베리어블 구글 시트는 구조를 이해하는데 정말정말 많은 도움이 되었고, 실무에서도 잘 활용할 수 있을 것 같다.2-1) 컬러색상 베리어블(collection) 구조Primitive - raw valueTheme - 브랜드 모드를 적용하기 위한 목적 → 실습을 하다 질문하고 받은 답변인데, 브랜드가 한 개일 경우 필수는 아니며 강의 내용과 같이 feedback 베리언츠는 바로 semantic에 추가해도 됨Semantic - property, role, variant, state, scale등의 내용이 포함됨 (라이트/다크 모드 적용하기 위한 목적) → 모드는 시멘틱에서만 추가할 수 있고, 다크 모드의 raw value를 다르게 가고싶은경우 primitive에 따로 추가해야됨. 이건 강의 후반 '모드'에서 다룰 예정.특정 베리어블을 퍼블리싱하고 싶지 않을 때컬렉션/그룹 앞에 _ 를 붙이거나,개별 베리어블은 설정에서 'hide from publishing'을 선택Color Syntax웹, aos, ios 플랫폼별로 대응하는 코드 이름을 만들어줄 수 있는데, 왜 필요하고 어떤식으로 다르게 표기되는지 이해하기 위해서 개발팀의 도움이 필요할 것 같다. 2-2) 간격1.5배수 랜더링 이슈로 8Pt 그리드를 사용하고, 더 섬세한 단위로 정렬하고 싶을 때 4pt를 사용한다.간격의 사용 (Spacing in UI)0~8pt 작은 UI 구성 요소12~24pt 카드 UI padding, 간격> 32pt 큰 규모의 UI, 레이아웃간격 베리어블 계층Base grid point - 4ptPrimitive - UnitSemantic - padding, gap, border radius, width/height, border width 컬러와 마찬가지로 number scoping을 설정할 수 있음 2-3) 아이콘Feather icon은 실무에서 자주 사용하는데 이렇게 손이 많이 가는 놈(?)인지 몰랐다. 생각해보면 컬러가 이상하게 설정될 때마다 문제점을 생각할 조차 하지 않았는데, 이를 고치고 컴포넌트화해서 앞으로 시간이 정말 많이 단축될 것 같다.해결방법구조가 똑같게 하기union, flatten selection을 사용해 모두 stroke를 면으로 만들기이름 똑같이 하기Union을 했을 때 아이콘이 깨지는 경우, scale을 키우고 anchor point랑 bezier를 움직여가며 수동으로 수정 (=앤트맨 전략)  2-4) Elevation실무에서 shadow를 스타일화하지 않고 필요할 때마다 따로 만들어서 일관성이 떨어졌는데, 강의에서 배운대로 높낮이에 따라 컴포넌트를 지정하고 description을 잘 활용해서 관리해야겠다고 느꼈다.강의를 보면서 수치를 따라 입력하는데 집중하느라 강의 내용이 잘 기억이 나지 않아, 복습이 특히 필요할 것 같다. 섹션 3 - 다양한 효과 그리고 높낮이를 나타내는 그림자효과 파트 1, 2📝 단축키베리어블 복사: cmd+shift+enter여러 베리어블 속성 변경: 베리어블 선택 후, shift+오른쪽 마우스 버튼베리어블 바로 적용: shift+왼쪽 마우스 버튼회고잘한 점1주차 미션 모두 완수한 나 칭찬해 🙂미션 후 나만의 디자인으로 베리어블을 만들어보았다.다음주 강의와 미션 미리 시작했다.아쉬운 점데드라인에 집중하다보니 기계처럼 미션을 수행한 것 같다.미션 2가 끝날때까지 강의 노트를 미리 작성하지 않아 한번에 많은 양을 복습 하려다보니 블로그를 쓰는데 시간이 너무 소요되었다.베리어블 등록하고 scoping 설정하는걸 자꾸 잊어버렸는데, 이건 무조건 외워야겠다.다음주 계획강의들으면서 노트 꾸준히 작성하기 이번 주 만큼 휴일이 많이 없어서 스케줄 관리에 특히 더 신경쓸 것

UX/UI

박민지

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

피그마 공부를 시작하고 UX/UI 디자인 쪽으로 새 진로를 잡으면서 디자인 시스템에 관해 알게되었다.하지만 배리어블을 어떻게 활용해야 하는지 이해하기 힘들었고, 막연히 이미 나온 서비스에만 적용 할 수 있다고 생각해서취준생인 내가 취직할 때 까지 접할 일이 없다고 생각했으나 최근 사이드프로젝트를 하면서 생각이 달라졌다.시스템이 없으니 프론트엔드 개발자분과 소통이 힘들었기 때문이다. 그래서 배리어블 공부를 하겠다고 마음만 먹었 던 와중에 인프런에서 워밍업 클럽을 한다는 광고를 접해 신청하게 되었다.(취준생(백수!)이라 일정한 수입이 없어서 유료강의는 꿈도 못꾸고 있었는데 국민취업지원제도에서 지원금을 주어서 그걸 쓸수 있게 되었다. 취준생 분들은 한번 신청해보세요. 고용24(정부기관)에서 신청가능.) 강의는 <피그마 배리어블을 활용한 디자인 시스템 구축하기>강사님은 인스타에서 팔로우하고 있었던 bold님 이었고 이분을 통해 토큰이라는 개념을 처음알게 되었었는데 그런점에서 혼자 반갑기도 했다. 하지만...1주차 부터 난항을 거쳤다. 개인 스케쥴이 바빴고 이래저래 계속 일이 생겼다.게다가 강사님이 공유해주신 노션의 스케쥴이 가이드라고 생각했는데 그 스케쥴에 맞춰서 미션 제출을 해야한다는 걸날짜가 다 지나고 디스코드에 들어갔다가 알게되었다. 그때 미션 1이 전부 끝난 상태이긴 했는데 이후 스케쥴을 보아하니 미션 2도 늦어질 것 같아서 그냥 주말에 한꺼번에 제출하기로 결정. 그것도 모자라서 강의 통해서 강사님이 공유해준 미션 카드가 있는 피그마 파일이 아니라 새 파일로 시작했다.이미 배리어블을 꽤 등록해 둔 상태라 (알아챘을 때는 이미 80% 정도 완성한 상태였다ㅠㅠ) 썸네일 등을 복사 붙여넣기하고머리가 나쁘면 몸이 고생한다더니 딱 그꼴이었다.  강의는 핵심 전달과 적절한 예시로 이해하기 쉬웠다. 이전에 알던 개념에서 확장해 여러 예시를 보여주는 점이 제일 좋았다.막연하게 배리어블이 무엇인가 생각할때와는 달리 실무에서 어떻게 적용할수 있는지, 그리고 왜 이걸 요구하는지 알수 있었다.그리고 강의 PPT디자인도 깔끔해서 보기 좋았다. 폰트와 레이아웃이 지나치게 자유분방하면 괴로운게 디자이너들 아니겠습니까. 하지만 내 생각보다 시간이 오래걸렸다. 강의 보면서 따라하느라 시간이 지체되었고 잘 이해 안가면 돌려보고 잠깐 멍때리느라 집중력을 잃어 놓치는 부분 다시보고 하니 10분 짜리를 20분 동안 보게 되었다. 그리고 배리어블을 등록하는 게 끝이 아니라 등록한 배리어블을 협업자와 공유하기 위해 문서형태로 펼쳐놓아야 하니 이부분이 제일 오래걸렸다. 사이드 프로젝트하면서 부족한 점을 제일 많이 느꼈던 부분이라 어떻게 만들어야 하는지 생각을 많이 하게 되었다. 도움이 정말 정말 많이 되었던 부분은 역시나 최근에 업데이트 해주신 아이콘 강의!!이전 경력때 일러스트레이터를 많이 사용했고, 이후 UXUI 포트폴리오를 만들면서 아이콘 제작을 하는데 피그마에서는 아이콘을 깨면 이상하게 깨지는 경우가 많았다(이건 언제 개선이 되려나??). 그럴때마다 일러스트레이터에서 다시 그리거나 처음부터 일러스트레이터에서 작업해서 가져오면서 스케일이나 굵기 때문에 고생한적이 있었는데 이 문제를 해결하는 방법 (앤트맨 방법!)을 알게된 점이 정말 정말 도움이 많이 되었다. 생명의 은인이십니다. 배리어블은 막상 하니 어렵지 않았다. 이해도 쉬웠다. 사용하는 법 자체보다는 팀과 협업해 수치를 지정하고 그걸 지켜가는 과정이 더 중요할거라는 생각이 들었다. 배리어블 생성은 웹페이지 주소를 구성하는 방식과 비슷했고 특정 유닛을 불러와 사용하는 방식이 특히 그렇게 느껴졌다. 아직 컴포넌트 만들기 까지는 강의를 듣지 않았지만 (내일 들을 예정 오늘 6시간 작업했으니 봐주세요) 미션을 끝마친 기념으로 블로그를 적어본다. 잘한점 - 첫 주차에 할당된 미션 완료잘못한점 - 날짜를 맞추지 못했다.반성 - 예상보다 작업이 오래걸리니 좀 더 여유를 가지고 시간을 맞춰 꾸준히 학습해야겠다.

UX/UI디자인시스템베리어블피그마워밍업클럽

sodee

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

신청 계기배리어블 강의를 오픈 당시에 신청했는데 공부해야지 공부해야 하면서 지금까지 미뤄뒀다 😂최근 회사들 JD를 보니 디자인 시스템 제작 경험이 담당 업무이거나 우대사항인 경우를 확인했다.그리고 실무를 하면서도 디자인 시스템 없이는 일관성이 부족함을 체감했기에 꼭 필요하겠다라는 생각이 들어 밀도있게 공부해보자는 생각이 들어 워밍업 클럽을 신청했다. 공부한 파트variable을 활용한 디자인 시스템 제작을 위해 알아야 할 필수 개념 (기본 개념, 구조) 파운데이션 셋팅 (색상, 간격, 타이포그래피, 아이콘, 그림자, 그리드 시스템)입력 컴포넌트 제작 (버튼, 체크박스, 라디오버튼, 스위치 버튼) 배운 점 컴포넌트 이름 명명법, 컴포넌트 별 State, Foundation/Input 파트에서 기본적으로 제작해야 하는 컴포넌트의 종류오토레이아웃을 적용 후 바로 이름 변경하기, 다 만든 후 접근성 체크하기 등 수업을 따라가며 좋은 습관을 많이 배웠다.강의 듣는 동안 좋은 플러그인을 정말 많이 알게 되어 좋았다*.* 잘한 점성실하게 강의를 들었던 점! 일주일만에 진도를 30% 정도 나갔는데 뿌듯하다! 🥰 아쉬웠던 점디테일하게 신경쓰고 마무리에서 아직 약하다는 점. 폰트 컬러 지정을 깜빡하는 등의 실수가 종종 보였다. 강의 일단 완강 후 조금 쉬고 다시 하는 방식으로 해내긴 했지만 실무에서는 내가 편한 방식으로만 할 수는 없으니까.. 이 부분을 주의해야겠다고 생각했다. 다음주에 시도할 것꾸준하게 강의 수강하는 패턴 유지하기중간 중간에 배리어블 지정이 빠진 부분이 없는지 체크하기

UX/UI

하양이

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

Day 2. 추상과 구체추상과 구체추상 (抽象)사물을 정확하게 이해하기 위해서 사물이 지니고 있는 여러 가지 측면 가운데서 특정한 측면만을 가려내어 포착하는 것이다. 어떤 일면만을 추상하는 것은 다른 측면을 버린다는 것과 같다. (위키백과)추상은 항상 구체적인 실재에서 시작해야 한다. - Pablo Picasso추상화의 가장 대표적인 행위이름을 짓는다. 이름 짓기단수와 복수 구분하기이름을 줄이지 않기은어/방언 사용하지 않기좋은 코드를 보고 습득하기 메서드와 추상화잘 쓰여진 코드라면, 한 메서드의 주제는 반드시 하나다.메서드 선언부반환타입 메서드명 (파라미터) {}메서드 선언부: 반환타입 메서드명 (파라미터)메서드 구현부: {}메서드 시그니처: 메서드명 (파라미터)추상화 레벨하나의 세계 안에서는, 추상화 레벨이 동등해야 한다.매직 넘버, 매직 스트링의미를 갖고 있으나, 상수로 추출되지 않은 숫자, 문자열 등미션 - 생각나는 추상과 구체의 예시Winter is coming지구가 태양을 공전하여 태양의 고도가 점차 낮아진다.이로인해 햇빛의 강도가 약해져 기온이 감소한다.북쪽의 차가운 공기가 내려오고 습한 공기와 만나게 되면 눈이 내린다.Day 3. 논리, 사고의 흐름 | 객체 지향 패러다임뇌 메모리 적게 쓰기“정리 시스템에서 중요한 과제는 최소의 인지적 노력으로 최대의 정보를 제공하는 것이다.”- 대니얼 J. 레비틴, 「정리하는 뇌」, 와이즈베리, 2015, 134p뇌는 한 번에 한 가지 일 밖에 하지 못한다. 멀티태스킹? 그건 저글링일 뿐.- 요한 하리, 「도둑맞은 집중력」, 어크로스, 2023, 60pEarly returnEarly return으로 else의 사용을 지양사고의 depth 줄이기중첩 분기문, 중첩 반복문‘무조건 1 depth로 만들어라’가 아니다!사용할 변수는 가깝게 선언하기공백 라인을 대하는 자세공백 라인도 의미를 가진다.부정어를 대하는 자세부정 연산자(!)의 가독성은 낮다.해피 케이스와 예외 처리사람은, 해피 케이스에 몰두하는 경향이 있다.Null을 대하는 자세항상 NullPointException을 방지하는 방향으로 경각심 가지기Optional에 대해 orElse(), orElseGet(), orElseThrow()의 차이 숙지추상의 관점으로 바라보는 객체 지향객체 = 데이터 + 코드협력과 책임캡추상다관심사의 분리객체 설계하기새로운 객체를 만들 때 주의할 점1개의 관심사로 명확하게 책임이 정의되었는지 확인하기생성자, 정적 팩토리 메서드에서 유효성 검증이 가능하다.setter 사용 자제getter도 처음에는 사용 자제. 반드시 필요한 경우에 추가하기필드의 수는 적을수록 좋다.도메인 지식은 만드는 것이 아니라 발견하는 것미션 - 읽기 좋은 코드로 리팩토링public boolean validateOrder(Order order) { if (order.hasNotItem()) { log.info("주문 항목이 없습니다."); return false; } if (order.hasNotTotalPrice()) { log.info("올바르지 않은 총 가격입니다."); return false; } if (order.hasNotCustomerInfo()) { log.info("사용자 정보가 없습니다."); return false; } return true; } class Order { private List<String> items = new ArrayList<>(); private Long totalPrice; private String customerInfo; public boolean hasCustomerInfo() { return customerInfo != null && !customerInfo.isEmpty(); } public boolean hasNotCustomerInfo() { return !hasCustomerInfo(); } public boolean hasNotItem() { return !items.isEmpty(); } public boolean hasTotalPrice() { return totalPrice != null && totalPrice > 0; } public boolean hasNotTotalPrice() { return !hasTotalPrice(); } }Day 4. SOLID미션 - 자기만의 언어로 정리한 SOLIDSRP: Single Responsibility Principle클래스는 하나의 책임, 즉 변경 이유를 한 가지만 가져야 한다. 한 가지 일을 잘 처리하도록 해야 유지보수가 쉬워진다.OCP: Open-Closed Principle새로운 기능이 추가할 때 기존 코드를 변경하지 않고 확장이 가능해야 한다.LSP: Liskov Substitution Principle부모 클래스의 기능을 자식 클래스에서도 사용할 수 있어야 한다.ISP: Interface Segregation Principle하나의 책임이 있는 인터페이스 여러 개로 나눈다. 그래야 필요한 인터페이스에 대해서만 구현할 수 있다.DIP: Dependency Inversion Principle하나의 모듈이 다른 모듈은 참조하지 말고 추상화에 의존해야 하고, 구체적인 사항은 나중에 정의해야 한다.Day 5. 객체 지향 적용하기상속과 조합조합과 인터페이스를 활용하는 것이 유연한 구조상속을 통한 코드의 중복 제거가 주는 이점보다, 중복이 생기더라도 유연한 구조 설계가 주는 이점이 더 크다.Value Object도메인의 어떤 개념을 추상화하여 표현한 값 객체불변성동등성유효성 검증일급 컬렉션일급 시민의 조건을 만족하는 컬렉션컬렉션을 포장하고 유일한 필드로 가지는 객체Enum의 특성과 활용Enum은 상수의 집합이며, 상수와 관련된 로직을 담을 수 있는 공간이다.만약 변경이 정말 잦은 개념은, Enum보다 DB로 관리하는 것이 나을 수 있다.다형성 활용하기변하는 것과 변하지 않는 것을 분리하여 추상화하고, OCP를 지키는 구조숨겨져 있는 도메인 개념 도출하기완벽한 설계는 없다. 그 당시의 최선이 있을 뿐.출처https://inf.run/zgJk5 https://inf.run/kHiWM

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

강희준

[워밍업 클럽 스터디 2기] 1주차 발자국 🐾

강의 수강 강의 내용 요약추상과 구체추상과 구체 개념 공부, 메서드 추상화, 매직 넘버, 매직 스트링 등을 이용해 추상화하자.사고의 흐름 , 읽기 쉬운 코드Early return, 사고의 depth 줄이기 등을 통해 쉽게 잘 읽히는 코드를 작성하자.객체 지향추상의 개념을 생각하며 객체를 설계하자.객체 지향의 SOLID 원칙상속과 조합, VO, Enum, 다형성 등을 활용하여 객체 지향을 적용해보자.회고일주일 동안 진도를 착실히 잘 나아갔던 부분을 칭찬하고 싶다.하지만 진도를 맞추기 위해 정확히 이해하지않고 넘어간 부분도 있는 것 같아 아쉽다.개인 공부가 목적이다보니 다음 주에는 진도 맞추기 보다는 이해하고 넘어가는 것에 초점을 두고 공부할 것이다. 미션 "추상과 구체" 강의를 듣고, 생각나는 추상과 구체의 예시가 있다면 적어보자어떤 주제에 대해서 적어볼까 고민하다가 마침 과자를 먹고 있어서음식물을 입에 넣고 삼키는 과정을 구체화 해보자!라는 생각을 하게 되었고 적절한 검색을 통해 구체화 해보게 되었다. 아래 코드를 [섹션 3. 논리, 사고의 흐름]에서 이야기하는 내용을 중심으로 읽기 좋은 코드로 리팩토링해보자섹션 3에서 주로 다루었던 "읽기 쉬운 코드를 작성하자" 를 계속 생각하며 리팩토링 하려고 노력했다.사고의 depth 줄이기, Early return, 부정어를 대하는 자세를 최대한 활용하려고 노력했다.코드 리뷰를 통해 좀 더 리팩토링 할 여지가 있다는 것을 알게 되었고 덕분에 더 나은 리팩토링을 할 수 있었던 것 같다.SOLID에 대하여 자기만의 언어로 정리해보자평소 SOLID 라는 원칙은 알았으나 누군가에게 설명해줄수 있을 정도로 잘 알고 있지는 못했는데 미션 수행을 위해 검색과 나의 언어로 정리하는 과정을 거치면서 어느 정도 감이 잡혔고 나름 설명할 수 있을 정도가 된 것 같아서 좋았다. 

백엔드인프런워밍업스터디클럽백엔드클린코드테스트코드발자국

ea04638

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

1주차Day 1 OT공지사항을 보니 발자국에 정해진 형식은 없다고 하여, 코드 작성 시 생각의 흐름을 정리 작성하는 방식으로 하기로 하였다.강의를 보고 느낀점, 과제를 보고 판단한 과제 제작 기준, 과제 구현 방식을 요약하여 작성한다.이번엔 시간분배를 잘못해서 캡쳐 등 이미지나 코드를 본문에 첨부하진 못했는데, 다음주엔 첨부하여 좀 보기좋게 만들고싶다. 시간이 나면 본 포스팅에 추가도 하고.  Day 2 자바스크립트 기초 (Section 2 ~ 4)자바스크립트 중급(1) 강의요약자바스크립트를 쓰기위한 기초적인 요소(변수, 연산, 루프 등), Window 객체, DOM의 개념과 클릭 등 활동에 반응하기위한 EVENT 에 대한 개념을 설명한다.과제메뉴판 만들기조건 클릭 이벤트를 감지할 것클릭된 요소들을 구분할 것클릭에 다라 출력되는 화면이 변화할 것해결addEventListener를 통한 클릭 이벤트 감지클릭 한 요소의 data 값을 인식하도록 처리메뉴 카테고리를 배열화하여, 각 배열 요소 중 data값과 동일한 값을 class명으로 가진 요소들이 존재하는지 판별. 해당하는 요소들은 display 상태 변화.회고생각해보니 category를 html 로 작성한 뒤에 getElement를 통해 불러와 array로 저장 할 바엔 그냥 처음부터 배열[오브젝트] 로 작성한 뒤, 해당되는 요소만 걸러서 새 배열을 만들고, 그렇게 만들어진 배열로 html을 작성하게 하는게 나았을 것 같단 생각이 든다.  Day 3 자바스크립트 기초 (Section 5 (1~8))자바스크립트 중급(1) 강의요약자바스크립트의 활용에서 자주 쓰이는 this 키워드, 삼항 연산자를 통한 if문 처리, event loop, map filter등을 통한 배열처리를 학습한다.if else보다 삼항 연상자, 배열에서는 map 등 적절한 기능을 적절한 때에 쓰는게 효율이 좋다는건 아는데, 마음이 급하면 자꾸 새 기능보다 기존에 알던 기능, 손에 익은 작성법대로 작성하게 되어서 고민이 된다. 옛날엔 this 키워드를 엄청 자주 활용해서 아주 잘 알고있다고 생각했는데, 근 1년 반정도 사용하지 않았더니 굉장히 낯선 개념처럼 느껴졌다.과제가위바위보조건매 회 컴퓨터는 가위 ,바위, 보 중에 랜덤한 값을 제시해야한다.매 회 컴퓨터가 제시한 값과 유저가 제시한 값을 비교해야한다.매 회 컴퓨터와 유저가 제시한 값에 따라 승패를 판별하며, 승 패를 기록한다.총 승패의 횟수가 10회가 되면 전체 게임을 정지하며, 유저와 컴퓨터 중 승리한 횟수가 더 많은 쪽을 최종 승자로 판별하여 화면에 출력한다.해결매 회 컴퓨터가 제시할 세가지 값을rsp = ['rock', 'sissor', 'paper'] 형태로 저장. Math.random() 을 사용하여 0, 1, 2 중에 랜덤한 값을 얻고, rsp 배열 중 해당 값을 인덱스로 갖는 값을 컴퓨터가 제시할 값으로 삼는다.if문을 통해 컴퓨터와 유저의 승리여부를 판가름한다.이 때 컴퓨터, 유저의 승리 횟수를 각각 변 수에 저장한다.이 때 totalCnt 를 1씩 증가시키고, restCnt는 10 - totalCnt로 표시한다.totalCnt가 10에 도달하면 컴퓨터, 유저의 승리 횟수를 비교한다.if문을 통해 컴퓨터와 유저 중 어느 쪽의 승리 횟수가 더 많은지에 따라 출력값을 변경한다.회고분명히 더 간략하게 추릴 수 있는 방법이 있을텐데, 진도가 빡빡한 편이다보니 일단 단순무식하지만 빠르게 쳐낼 수 있는 방법으로 작성했다는 기분을 떨칠 수 없다.원래 본 코드는 강의내용에 포함되어있는 삼항연산자로 작성했지만, 올바른 코드임에도 unexpected 괄호 닫음 등의 오류를 많이 발생시켜 if else문으로 재작성, 일부만을 삼항연산자로 작성하였다.컴퓨터나 유저의 선택지를 배열에 저장시킨 후 판가름하면 강의에 나온 map이나 filter등을 사용하여 총합 승패여부를 판별할 수 있지 않을까 하고 좀 더 활용방안을 생각했는데, 그럼 실시간 승패여부판가름 및 카운트를 올릴 수 없기 때문에 관뒀다.script에 addEventListener를 다는 대신, button onclick시 함수를 실행, 실행 함수에 좀 더 처리를 하면 this요소를 활용할 수 있지 않을까 했는데, 굳이 그럴 이유가 없는데다, 시간도 없고, 강의 활용하려다 괜히 빙 돌아가는 길만 만들까봐 그만두었다.  Day 4 자바스크립트 기초 (Section 5 (9~17))자바스크립트 중급(2) 강의요약undefined와 null, 비교와 복사의 얕고 깊음, 함수 표현과 선언문, Strict mode 등 알고는 있지만 헷갈렸던 개념을 되짚었다. 사실 얇고깊음의 비교는 아직도 헷갈리며(특히 지칭대상이라는 것이), 함수 표현과 함수 선언은 엄격히 구분해가면서 쓸 일이 적었어서 자꾸 무시하고 작업하려고 하게 된다.IIFX, Intersection observer, Pure Function, Curry Function등은 알고는 있지만 아주 낯설거나 아예 모르는 것들이었는데. 덕분에 뭐 어떻게 활용해야할지 모르겠다. 9~17이 전반적으로 그러한듯.과제퀴즈앱조건문제가 주어진다.답 선택지가 주어진다.유저의 선택지가 올바른지, 올바르지 않은지 판가름하여 채점화면을 출력한다.동영상과 같이 배경색으로 표현하였으며, 선택 후 정답이면 녹색바탕, 오답이면 붉은바탕이 뜬다.정답 선택지는 녹색, 오답 선택지는 붉게 표현한다.다음을 클릭하면 다음문제가 뜬다.일정 갯수 이상 문제를 풀면 종료되고, Restart를 통해 처음으로 되돌아간다.해결questionList라는 오브젝트형 변수를 정의한다.오브젝트 내 요소 1인 ques1은 배열이고, Math.random과 Math.floor를 통해 0~30까지의 랜덤수 3개 갖는다.오브젝트 내 요소 2인 ques2은 배열이고, Math.random과 Math.floor를 통해 0~30까지의 랜덤수 3개 갖는다.ansList라는 오브젝트형 변수를 정의한다.오브젝트 내 요소 1인 ans1은 빈 배열로 정의, 후에 ques1의 각 요소를 ques2의 각 요소와 순서대로 더한 값을 3개 갖는다. 이는 정답배열이다.오브젝트 내 요소 2인 ans2는 배열이고, Math.random과 Math.floor를 통해 0~60까지의 랜덤수를 두개 뽑아 서로 곱한 값을 3개 갖는다.ques1 + ques2 라는 문제지를 화면상에 출력한다.선택지를 출력한다. 이 때 0부터 2까지의 랜덤값을 생성한다.랜덤값이 2이면 정답선택지는 없다. 랜덤한 오답선택지를 생성한다.랜덤값이 0이면 0번째, 1이면 1번째 버튼이 정답선택지가 되며, 다른 버튼은 오답 선택지가 된다.각 문제의 정답 오답 여부에따라 배경색상이 변한다.문제를 3개풀면 Restart를 통해 화면을 reload하고 새 문제를 시작한다.회고동영상이 숫자문제길래 일단 숫자문제로 했는데, 넘버와 스트링을 섞거나 해서 비교를 얕고 깊게 해볼 수 있도록 답변을 구성했어도 좋았을 것 같다.curry function 을 어떻게 활용해볼 수 있었으려나...? 연구해보기엔 시간이 짧았다.  Day 5 자바스크립트 기초 (Section 6~7)OOP, 비동기 강의요약객체지향 프로그래밍(OOP), 비동기(Promise, Async, Await), Class객체 등 과제책 기록 앱조건책이름과 저자명을 입력받을 것입력받은 값을 각각 화면에 출력할 것출력한 값 옆에 삭제 버튼을 둘 것버튼을 클릭하면 해당 값을 삭제할 것해결새로 추가된 input값을 오브젝트 newData에 저장한다.table에 newData값을 추가한다.createElement를 통해 추가할 tr, td(책제목용, 저자용 2개)를 변수로 (총 3개) 저장한다.각 td에 textContent를 통해 newData의 각 값을 추가한다.createElement를 통해 변수정의한 tr에 appendChild를 통해 두 td를 추가한다.table에 appendChild를 통해 tr을 최종적으로 추가한다.위 같은 방식으로 삭제 버튼 또한 추가한다.삭제 버튼을 클릭하면 해당 행이 삭제되도록 한다.삭제버튼에 addEventListener 'click' 을 추가한다.삭제버튼을 클릭하면, 추가했던 행(변수정의해둔 createElement tr)을 삭제하도록 한다.회고class객체 써볼 수 있었을 것 같은데, 이걸 발자국 쓰면서야 생각했다. 하지만 배열과 객체로 해결할 수 있는데 인스턴스로 제작해서 더 이점이 있었을까. 이 부분은 따로 검색해서 알아봐야겠다. 아직 class나 인스턴스에 대해 아는게 너무 적다.document.getElement~ 를 통해 객체를 찾으면 변수에 저장해놓고 쓰는게 습관이었는데, 이번 과제를 하다보니 굳이 안그래도 되었을 것 같은 부분들이 있었다. 습관적으로 코딩하는 부분이 많다는걸 다시금 깨달았다.과제2깃헙유저검색조건입력받은 값으로 실시간 검색결과를 출력할 것.실시간으로 api를 요청, 값을 전달받아 출력할 것.해결async를 통해 api로부터 값을 요청한다.이때 요청키워드는 입력값이다.입력값은 input값이 변화할 때마다 (키보드 입력이 있을 때마다) 업데이트 되어 새 요청을 한다.addEventListener의 input을 사용하여 input 의 value를 얻는다.textContent, innerHtml, appendChild를 이용하여 화면상에 출력한다.회고데이터를 요청하는 과정에서 필수적으로 비동기 요청이 사용되었기 때문에 차라리 강의내용을 어떻게 끼워넣어볼지 생각 안해도 되는건 편했다.비인증계정 60회 제한이 있는 api 라 테스트하다가 자꾸 막혔다.책 과제를 할 때엔 table 안 tr을 추가하여 td, 혹은 또 그 안의 button을 추가해야해서 코드가 길어졌는데.. 이번엔 두번째 해서인지 혹은 구조가 간단해서인지 비교적 짧게 끝나서 좋았다.

프론트엔드워밍업클럽

Rojojun

[워밍업 클럽 스터디 2기::백엔드] 1주차 발자국

1주일간의 학습 회고이번 한 주 동안 운이 좋게도 시간을 내어 강의를 모두 들을 수 있었다. 강의를 들으면서 강사님이 예제로 주신 프로젝트를 리팩토링하는 시간을 가졌고, 이를 어떻게 하면 더 효율적으로 리팩토링할 수 있을지 고민도 많이 했다. 나의 개발 철학: 누구나 이해할 수 있는 코드내가 코드를 작성할 때 가장 중요하게 생각하는 점은 바로 누구나 이해할 수 있는 코드다. 아무리 정교하고 복잡한 로직이라도 나 외에 다른 사람들이 이해하지 못한다면, 코드 자체는 잘 작성했을지 모르지만 그 코드는 좋은 코드라고 할 수 없다. 개발자는 혼자 일하는 것이 아니라 여러 명과 협업하는 직업이다. 또한 코드는 끊임없이 변화하고 발전하는 유기체라고 생각한다. 그렇기에 모든 사람이 이해할 수 있고, 지속적으로 유지보수할 수 있는 코드가 좋은 코드라고 생각한다. 이번 주 학습에서 잘한 점이번 주 학습에서 내가 스스로 잘했다고 생각한 부분은 기존에 알고 있던 개념들, 예를 들어 톰 롱의 좋은 코드 나쁜 코드, 켄트 백의 Tidy First, 로버트 C. 마틴의 클린 코드와 같은 책에서 배운 내용을 확장시켰다는 점이다. 또한, 내가 경험한 부분들을 도입해서 좀 더 깊이 있게 이해하려고 노력했다는 점이 좋았다. 아쉬웠던 점: 집중력 유지의 어려움하지만 아쉬웠던 점도 있었다. 집중력 유지가 생각보다 쉽지 않았던 것이다. 외부적 요인이든 내부적 요인이든 컨디션에 따라 학습의 진도가 들쑥날쑥했다. 컨디션이 좋은 날은 많은 진도를 나갔지만, 좋지 않은 날은 적은 진도를 공부하게 됐다. 그럼에도 꾸준히 공부하고 성취를 이뤄냈다는 점은 매우 중요한 성과다. 이번 주에 목표했던 학습을 어느 정도 완료했고, 다가오는 한 주는 더 구체적인 목표를 세워 동료와 함께 학습 내용을 토론하며 우리 회사에 적용해 볼 계획이다. 실습과 이론이 어우러진 미션이번 주차에는 두 가지 미션이 주어졌다. 하나는 구체라는 개념을 일상생활에 빗대어 설명하는 미션이었고, 다른 하나는 주어진 코드를 SOLID 원칙에 맞게 리팩토링하는 과제였다. 구체를 일상생활에 빗대어 설명하는 과제는 매우 흥미로웠다. 프로그래밍을 공부하다 보면 언어 자체가 번역투로 이루어져 있거나 어려운 용어가 많아 쉽게 이해하기 힘들 때가 많다. 하지만 일상생활에 비유해 설명하니 훨씬 쉽게 이해할 수 있었고, 동료들에게도 설명할 때 유용했다. SOLID 원칙 과제에서는 내가 생각하는 중복 문제를 예시로 들고 설명했다. 이 과정에서 초등학생에게 설명한다는 가정하에 설명을 시도해 보았다. 초등학생도 이해하지 못한다면, 나 역시 완전히 이해하지 못한 것이기 때문이다. 이는 전문가는 어려운 개념을 쉽게 설명할 수 있지만, 사기꾼은 쉬운 개념을 어렵게 설명한다는 유명한 말과 일맥상통한다. 회사 팀원들과의 협업이번 스터디는 회사 팀원들과 함께 진행하고 있는데, 팀원들과 함께 성장할 수 있는 좋은 기회가 되고 있다. 강의 내용도 매우 만족스러웠고, 팀원들의 반응도 긍정적이다. 누군가 이 강의를 추천하냐고 물어봤을 때, 나는 이렇게 대답했다. “클린 코드 책 읽어보셨나요? 읽으셨다면 좋은 강의고, 안 읽으셨다면 꼭 들어야 할 강의에요.” 클린 코드는 한 사람의 의견만이 정답은 아니라고 생각한다. 여러 사람의 이야기와 경험이 모여야 비로소 읽기 좋은 코드가 완성된다고 본다.

백엔드클린코드백엔드

gusdnchl7144

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

 Section2) 추상Clean Code를 추구해야 하는 이유나를 포함해 다른 개발자가 코드를 읽고 이해하는데 드는 시간이 절약된다.프로그램의 정의프로그램 = (데이터가 담긴) 변수 + (변수를 사용하는) 메서드의 집합추상중요한 정보는 가려내어 남기고, 덜 중요한 정보는 생략하여 버리는 것적절한 추상화 : 도메인 안에서, 정말 중요한 핵심 개념만 남겨서 표현하는 것이다.추상화의 가장 대표적인 행위는 이름을 짓는 것이다.(변수) 이름 짓기 Tip1) 단수와 복수 구분- 끝에 '(e)s'를 붙여 구분2) 이름 줄이지 않기- 일반적으로 무엇이든 이름을 줄여서 사용하는 것은 가독성을 제물로 바쳐 효율성을 얻는 것인데,유지보수 관점에서 득보다 실이 크다.- 관용어 처럼 자주 사용하는 것은 줄여도 괜찮다.=> ex, column -> col, latitude -> lat=> count -> cnt (추천X)3) 은어/방언 사용X- 현재의 팀만 아는 용어 사용 금지4) 좋은 코드를 보고 습득하기메서드와 추상화한 메서드는 반드시 한가지 일만 해야 한다.2가지 일을 하게된다면 추상화된 내용(==메서드 선언부)을 보고 구체적인 내용(메서드 구현부)의 유추가 어렵다.추상화 레벨외부 세계(==추상화 레벨이 높은 세게)와 내부세계(==추상화 레벨이 낮은 구체)를 나누었을때 추상화 레벨이 달라지는데, 하나의 세계 안에서 각 로직의 추상화 레벨은 동등해야 한다.매직 넘버, 매직 스트링매직 넘버(스트링) : 의미를 갖고 있으나, 상수로 추출되지 않은 숫자, 문자열 등을 말한다.Mission 1) 생각나는 추상과 구체의 예시Execute Login1) 클라이언트가 서버에 암호화된 ID와 Password를 HTTP Body에 담아 Request를 보낸다.2) 서버는 ID와 Password를 복호화하고 각 필드에 대한 유효성 검사를 한다.3) 유효하다면, 복호화된 ID와 Password를 DB에 보내 가입된 유저인지 확인한다.4) 가입된 유저라면, Session Cookie 혹은 JWT 등에 사용자 정보를 담아 클라이언트에 Response로 보낸다.Section3) 논리, 사고의 흐름뇌 메모리 적게 쓰기최소의 인지적 노력으로 (뇌 메모리를 줄여) 최대의 정보를 제공해야 한다,Early returnelse (if) 대신 return을 사용하는 것을 권장한다,.사고의 Depth 줄이기1) 중첩 반복문을 메서드 혹은 Stream을 통해 개선하면 좋다.2) 사용할 변수는 가깝게 선언하기공백라인도 의미를 가진다.부정어if문에서 부정어(!) 사용시 메서드화하여 분리하기해피케이스와 예외처리1) 예외가 발생할 가능성을 낮추는게 좋다. (ex, 사용자 입력, 객체 생성자, 외부 서버의 요청 등)2) 의도한 예외(ex, Custom Exception)와 예상하지 못한 예외 구분하기3) NullPointException은 항상 발생하지 않게 해야 한다.- 메서드 설계시 return null을 자제하고, Optional 사용을 고려하기 - Optional의 orElse(), orElsGet(), orElseThrow() 메서드의 차이 이해 필요.Section4) 객체지향 패러다임객체 설계1) 새로운 객체 생성시 주의사항- 1개의 관심사로 명확하게 책임이 정의되었는지 확인 필요- 생성자, 정적 팩토리 메서드에서 유효성 검증이 가능함을 인지- setter 사용 자제- getter도 사용 자제하고, 반드시 필요한 경우에만 추가 - 필드의 수는 적을수록 좋다2) 도메인 지식은 만드는 것이 아니라 발견하는 것Mission 2-1) 읽기 좋은 코드로 리팩토링#중요하게 생각한 점1) order 객체 Null 체크 필요2) if-else문들 if문으로 개선3) 부정어구(!) 없애기4) getter 제거 → 객체에 의미가 담긴 메서드를 별도 생성5) 공백라인 사용public boolean validateOrder(Order order) { //1) Null Check if (order == null) { log.info("주문을 확인할 수 없습니다."); return false; } //2) remove (getter) if (order.hasNoItems()) { log.info("주문 항목이 없습니다."); return false; } //3) remove (! + if-else + getter) if (order.isInvalidTotalPrice()) { log.info("올바르지 않은 총 가격입니다."); return false; } //4) remove (! + if-else) if (order.hasNoCustomerInfo()) { log.info("사용자 정보가 없습니다."); return false } return true; } public class Order { private List<Item> items; private double totalPrice; private CustomerInfo customerInfo; public boolean hasNoItems() { return items == null || items.isEmpty(); } public boolean isInvalidTotalPrice() { return totalPrice <= 0; } public boolean hasNoCustomerInfo() { return customerInfo == null; } }Mission 2-2) 자기만의 언어로 정리한 SOLID1) SRP- Single Responsibility Principle (단일 책임의 원칙)- “하나의 클래스에 변경이 발생한다면 그 이유(==책임)는 반드시 하나여야 한다”는 원칙- ex) 프로그램 실행 부와 실제 실행 로직은 나누어져 있어야 한다.- 높은 응집도, 낮은 결합도와 관련 있음.2) OCP- Open-Closed Principle (개방-폐쇄 원칙)- “기존 코드의 변경 없이, 기능을 확장할 수 있어야 한다”는 원칙3) LSP- Liskov Substitution Principle (리스코프 치환 원칙)- 상속 구조에서, “부모 클래스의 인스턴스는 자식 클래스의 인스턴스로 치환될수 있어야 한다”는 원칙 4) ISP- Interrface Segregation Principle (인터페이스 분리 원칙)- ”하나의 구체 클래스는 자신이 사용하지 않는 인터페이스에 의존해서는 안된다”는 원칙(이때는, 인터페이스를 2개로 분리해야 한다) 5) DIP- Dependency Inversion Principle (의존성 역전 법칙)- “레벨이 높은 모듈(ex, Lv2 카페)은 구체 모듈(ex, Lv0 커피)에 바로 의존해서는 안되고 추상화(ex, Lv1 음료)에 의존해야 한다”는 원칙 미션을 통해 SOLID 원칙을 다시 한번 상기시킬수 있었는데, 실제 업무에 활용하기 위해서는 스스로 좀더 깊은 학습이 필요할것 같다. 그리고 클린코드의 방법론을 미션을 통해 적용해 보면서 코드가 좀 더 잘 읽히고 이해하기 쉬워지는 것을 직접 느낄수 있었다.Section5) 객체지향 적용하기상속과 조합상속은 시멘트처럼 굳어지는 구조이기 때문에 수정이 어려우므로, 상속보다 조합을 사용하는게 좋다.Value Object도메인의 어떤 개념을 추상화하여 표현한 값 객체로, 불변성, 동등성, 유효성 검증 등을 보장해야 한다.VO (Value Object)는 내부의 모든 값이 다 같아야 동등한 객체로 취급한다. 이에 반해 Entity는 식별자만 같으면 동등한 객체로 취급한다.일급 컬렉션컬렉션(List, Set, Map 등)을 포장하면서, 컬렉션만을 유일하게 필드로 가지는 객체로, 단 하나의 컬렉션 필드만을 가진다.만약, getter로 컬렉션을 반환할 일이 생긴다면 외부 조작을 피하기 위해 꼭 새로운 컬렉션(List<Object타입>)으로 만들어 반환하는게 좋다. 스터디를 진행하면서, 처음에는 완벽하게 다 이해하려고 생각해 학습에 시간이 오래걸렸는데, 이제는 내가 당장 적용해 볼수 있는 부분들을 Target으로 하여 배워나가야 겠다는 깨달음을 얻었다. 출처https://inf.run/zgJk5https://inf.run/kHiWM

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

yoon

[워밍업 클럽 2기 BE 클린코드&테스트] 1주차 회고

워밍업 클럽 2기에 열린 BE 클린코드&테스트 스터디에 참가하고 있습니다. 1주차에는 클린 코드 관련한 강의를 듣고 예제 프로젝트를 수정해가며 연습하는 시간을 가졌습니다.아래에 1주차 동안 배운 내용을 요약했습니다. [배운 점]1. 추상화의 중요성클린 코드를 배우면서 가장 인상 깊었던 것은 추상화의 중요성입니다. 코드를 작성할 때 '무엇을 하는가'와 '어떻게 하는가'를 분리하는 것이 얼마나 중요한지 깨달았습니다.- 적절한 이름 짓기의 중요성- 메서드 추출을 통한 코드 구조화- 추상화 레벨을 일관되게 유지하는 것의 중요성이를 통해 코드의 가독성과 유지보수성이 크게 향상될 수 있다는 점을 배웠습니다.2. 논리와 사고의 흐름코드를 작성할 때 논리와 사고의 흐름을 명확히 하는 것이 중요하다는 점을 배웠습니다. 특히:- Early return을 사용하여 복잡성 줄이기- 부정문보다는 긍정문을 사용하여 이해하기 쉽게 만들기- 해피 케이스와 예외 처리를 명확히 구분하기이러한 방법들을 통해 코드를 읽는 사람의 인지 부하를 줄일 수 있다는 점이 인상적이었습니다.3. 객체 지향 패러다임의 적용객체 지향 프로그래밍의 원칙들, 특히 SOLID 원칙에 대해 배운 것이 큰 도움이 되었습니다- 단일 책임 원칙 (SRP)- 개방-폐쇄 원칙 (OCP)- 리스코프 치환 원칙 (LSP)- 인터페이스 분리 원칙 (ISP)- 의존관계 역전 원칙 (DIP)이러한 원칙들을 적용함으로써 더 유연하고 확장 가능한 코드를 작성할 수 있다는 것을 알게 되었습니다.4. 실제 적용과 리팩토링이론을 배우는 것도 중요하지만, 실제로 코드에 적용해보는 것이 더 중요하다는 점을 깨달았습니다.- Value Object와 일급 컬렉션의 활용- Enum을 이용한 다양한 상태 표현- 다형성을 활용한 조건문 개선이러한 기법들을 실제 코드에 적용해보면서, 코드의 품질이 눈에 띄게 향상되는 것을 경험할 수 있었습니다. 앞으로의 다짐이번 학습을 통해 클린 코드의 중요성과 방법에 대해 많이 배웠지만, 이는 시작에 불과하다는 것을 알게 되었습니다.1. 매일 조금씩이라도 기존 코드를 리팩토링하는 습관 들이기2. 코드 리뷰에 적극적으로 참여하여 다른 사람의 코드에서도 배우기3. 클린 코드 관련 서적을 꾸준히 읽고 학습하기이러한 노력을 통해 더 나은 개발자로 성장하고 싶습니다. 클린 코드는 단순히 '예쁜' 코드를 작성하는 것이 아니라, 효율적이고 유지보수와 협업에 용이한 코드를 만드는 것임을 깨달았습니다. 이는 개인의 성장뿐만 아니라 실무에서 팀과 회사의 생산성 향상에도 크게 기여할 수 있는 중요한 기술이라고 생각합니다.

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

전석희

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

인프런 워밍업클럽 2기 1주차피그마 배리어블 기능을 알아가고, 디자인시스템을 효과적으로 제작하기위해 강의를 신청했다.혼자하면 분명 미루게될 것 같아서 워밍업클럽으로 4주동안 다 듣는 것을 목표로 했다. 1주차때 배운 것배리어블 등록 (색상, 간격, 타이포그래피, 아이콘, 그림자)입력 컴포넌트 제작 (버튼, 체크박스, 라디오버튼, 스위치버튼)배리어블을 등록할 때 primitive와 semantic으로 나눠서 지정하는 것을 배웠다.이것을 강의 그대로 따라하는 것은 쉬웠지만, 내가 만들 프로젝트?에 대입해서 어떻게 구성할 것인지는...디자이너 혼자일 때는 어렵지 않겠지만 추후 개발자와 일을 하게 되었을 때에는 꼭 많은 소통이 필요하겠다고 느껴졌다.예전에 작업할 때 state랑 status를 혼동해서 작업했던 것 같다.. 이번 기회에 안헷갈리고 개념을 잘 정리하는 시간이었던 것 같다! 아쉬웠던 점강의를 따라하기만 한 점내가 하고 싶은 프로젝트의 디자인시스템을 만드는데 도움이 되고자 강의를 신청했는데, 일단 강의를 듣다보니 그대로 따라하고만 있었다. 물론 따라하는 것이 나쁜 것은 아니지만... 그 이후 복습했던 시간이 없었던 것 같다.시간 배분을 잘 못했다.강의 초반에는 오전에 강의를 듣고~ 실습하고 그럴려고했는데 사람 마음이.. 아침에 일어나서 공부를 하려니 조금 못했던 것 같다.. 막 점심에도 듣고 저녁에도 듣고... 취준생이라 시간 많으니 오전시간에 다시 듣도록 노력해야겠다.문서 정리를 못한점배리어블 만들기만하고 문서로 정리를 잘 못했다.. 다음에 시도할 점복습을 하자 + 문서 정리를 하자내 개인 프로젝트에 따로 제작을 해보면서 이걸 개발자와 소통하려면 어떻게 배리어블을 구성할 것인지... 문서를 어떻게 할 것인지 생각해보는 시간이 있으면 좋을 것 같다.오전에 수업을 다 몰아듣자!시간을 정해서 듣는게 더 효율이 좋을 것 같다. 2주차도 잘 듣고, 미션도 밀리지 않고싶다! 다들 화이팅..

UX/UI디자인시스템디자인UXUI피그마프로덕트디자인워밍업클럽

vin

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

새로운 프로젝트 아이디어를 찾다가 인프런에서 위밍업클럽 2기를 시작한다는 소식을 듣고 신청하게 됐다. 강의 목록 중 특히 끌리는 강의가 있었고, 코틀린을 사용하는 점도 마음에 들었다. 그동안 코틀린을 접해본 적이 없어서 배우고 싶은 마음도 컸고, 새로운 기술들을 익히면서 동시에 다양한 사람들과 네트워킹을 할 수 있다는 부분이 마음에 들었다. 프로젝트 미리보기 + 웹 개발 기본 개념이번 강의에서는 웹 프레임워크, HTTP, 그리고 REST API와 같은 웹 개발의 기본 개념을 간략하게 학습했다.강의 시간이 짧아서 깊이 있는 설명은 없었지만, 웹 개발에서 필수적인 기초 개념을 알기 쉽게 설명해주었다. 덕분에 그동안 혼란스러웠던 부분들이 정리되었고, 전체적인 웹 개발의 기본 흐름을 이해할 수 있었다. 프로젝트 시작하기 + 데이터베이스 기본 개념데이터베이스와 JPA에 대해 이론적으로 학습하고, 실습으로 테이블 설계와 개발 환경을 구성하여 프로젝트를 시작했다.이전에는 주로 마이바티스(MyBatis)를 사용해 DB와 연결했지만, JPA에 대해서는 개념만 알고 있었다. 이번 강의를 통해 JPA의 기본 개념과 동작 방식을 명확히 이해하게 되었고, Spring Initializr 사이트를 통해 강의에서 사용할 개발 환경을 설정하고 프로젝트를 생성했다. 프로젝트 기초 설정하기코드 형상 관리를 위해 git과 GitHub를 사용하는 방법을 학습했다.또한, 생성된 프로젝트를 GitHub에 연결하고, 기본적인 상수 클래스, 리포지토리 클래스, 엔티티 클래스를 생성하였다.불필요한 파일들이 추적되지 않도록 .gitignore 파일을 설정하였고, 이 작업은 gitignore.io에서 현재 개발 환경에 맞는 설정을 자동으로 생성하여 적용했다.추가로, application.properties 설정 파일을 application-default.yml과 application-docker.yml로 나누어 개발 서버와 운영 서버에서 각각 다른 환경 설정을 적용하였다. H2와 MySQL 중 하나를 선택하여 각 서버에 맞게 설정했다. 프로젝트의 뼈대 엔티티 개발하기설계한 테이블을 바탕으로 엔티티(Entity)를 개발했다. 기본적으로 BaseEntity와 프로젝트에 필요한 여러 엔티티를 작성하였다.JPA와 코틀린을 처음 접해 생소한 부분도 있었지만, 자바에 대한 기본 지식 덕분에 비교적 빠르게 적응할 수 있었다. 연관관계가 있는 엔티티와 없는 엔티티를 나누어 개발하면서 새로운 어노테이션도 많이 사용했는데, 강의에서 해당 어노테이션에 대한 설명이 명확해서 어려움 없이 따라갈 수 있었다. 미션 1 + 21:N테이블 설계하기, 깃허브 리포지토리 만들기1주차에서 배운 내용을 바탕으로 서브 프로젝트의 GitHub 리포지토리를 만들고 테이블을 설계하는 미션을 수행했다.GitHub 리포지토리 생성은 문제없이 따라갔으나, 테이블 설계에서는 과연 내가 올바르게 하고 있는지 의구심이 들었다.적은 수의 테이블을 설계하는 것조차 여러 요인을 고려해야 했고, 설계한 테이블들이 적합한지 확신이 서지 않았다.우선 테이블을 설계하고, 프로젝트를 진행하면서 고려하지 못했던 부분이나 잘못 설계된 부분은 수정해나가기로 생각하였고, 이 과정에서 배운 점들을 기록하며 앞으로 개선해나갈 예정이다.https://github.com/Malvin222/mission-backoffice 

웹 개발백엔드웹개발워밍업클럽스프링

vin 1개월 전
gotjd9773

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

개요인프런 워밍업 스터디 클럽 2기 백엔드(읽기 좋은 코드, 테스트 코드) 9/27 금요일 시작되었다.스터디 주제는 박우빈님의 강의인Readable Code: 읽기 좋은 코드를 작성하는 사고법Practical Testing: 실용적인 테스트 가이드이다.1 ~ 2주차에는 읽기 좋은 코드 강의를 수강하고, 3 ~ 4주차에는 테스트 강의를 수강 하게 되는데,이번 글은 1주차, 읽기 좋은 코드 강의를 수강하고 배운 것들을 정리해 보려고 한다. 1주차 공부한 내용발자국 작성을 위해 표로 정리했다. 생각보다 번거로운 작업이었다. 강의 하나 듣고 로그 기록하고...권장 진도표에 따르면, 섹션 5까지 1주차에 수강 하도록 되어 있는데,이번 주는 섹션 4까지가 한계였다. 생각보다 내용이 많았고, 한 번에 이해되지 않는 내용들은 복습해야 했다. 해결한 것 - 인텔리제이 한글 깨짐 이슈처음부터 난관을 겪었다.인텔리제이 한글 깨짐 이슈...강의에서는 지뢰찾기 게임을 콘솔 프로그램으로 구현이 되어 있고,콘솔에 출력되는 내용이 한글, 지뢰 모양, 네모박스 모양, 깃발 모양 등이 있는데,전부 깨져서 출력되었다.구글링을 통해 해볼 수 있는 것들은 다 해봤던 것 같다.그래도 안 되서 포기하려던 찰나, 유튜브에는 관련 내용이 없는지 살펴보았다.결국, 해결! (유튜브 만세!)Project Structure 에서 SDK와 Language level 을 17 버전으로 동일하게 맞춰주니 한글 깨짐 이슈가 해결되었다.기존에는 SDK는 21 버전이 적용되어 있었다.버전이 제대로 맞지 않으면 한글 깨짐 이슈가 일어나는구나를 깨달았다.  이미 알고 있던 것들1. 이름 짓기 이름을 잘 지어야 한 다는 것은 알고 있었다. 어려워서 그렇지...2. 메서드 추출 이거는 코드짤 때 열심히 활용하고 있다.Ctrl + Alt + M추가적으로 메서드로 추출할 때 주의사항을 설명해주셨는데 도움이 많이 되었다.메서드를 추출할 때마다 항상 주의사항 4가지를 점검해야겠다. 메서드 추출시 주의사항 4가지메서드명은 적절한가?혹시 메서드가 두 가지 일을 하고 있지는 않은가?파라미터는 적절한가?반환타입은 적절한가?왜 이 4가지를 주의 해야 하는지는 강의를 통해 확인하시라. 배운 것들1. 추상화 레벨 "하나의 세계 안에서는 추상화 레벨이 동등해야 한다." - 박우빈추상화 레벨을 동등하게 맞춰야 한다는 개념은 처음 알게 되었다.이해를 돕기 위해 들어주신 서점 비유가 와 닿았다.추상화 레벨을 맞추지 않는 것은 서점 주인이 책들 사이에 표지, 제목도 없는 종이 모음을 책 이랍시고 내놓는 것과 같다.서점에 들어갔는데 종이 모음을 보게 되면 많이 당황스러울 것 같긴 하다. ㅋㅋㅋ나는 이런 서점 주인이 되어서는 안되겠다고 다짐했다. 2. Early returnEarly return 이라는 용어는 처음 접했다.이거를 무의식적으로, 이런 용어가 있다는 것도 모른채 사용해왔던 것 같다.Early return을 사용하면 뇌 메모리의 부하를 줄일 수 있겠구나를 깨달았다. 3. orElse, orElseGet, orElseThrow의 차이자바 8 문법을 배울 때 한 번씩 사용해본 메서드들인데 이번에 제대로 정리할 수 있었다. 4. getter 사용 자제setter를 사용하지 말라는 것은 들어봤지만, getter도 사용 하지 않는 것이 좋다는 것은 처음 들었다.어쩔 수 없을 때는 getter를 써야 겠지만, 클래스를 설계할 때 무지성으로 getter를 선언하는 행동은 지양해야겠다. 미션인프런 워밍업 클럽 스터디는 강의 수강 뿐만 아니라 미션 수행도 해야 한다.이번 1주차에는 Day 2, Day 4 미션이 있었다. Day 2 미션 - 추상과 구체 예시일상 생활에서 추상과 구체에 대한 예시를 찾는 미션이었다.요즘 관심 있는 주제에서 예시를 찾으려고 했다.요즘 관심 있는 주제는 주식, 운동, 스타크래프트인데,운동 분야가 가장 설명하기 쉬워 보였고, 모든 사람이 알만한 스쿼트에 대해서 구체적으로 설명했다. Day 2 미션 답변 - 스쿼트를 구체 레벨에서 표현한다면?발을 어깨너비로 벌리고 무게중심을 발뒤꿈치에 두면서 무릎을 굽힌다.숨을 참고 복압을 유지한 상태로 엉덩이를 뒤로 밀며 허벅지가 지면과 평행해질 때까지 내려간다.하체 근육을 사용해 다시 상체를 들어 올린다.동작이 끝난 후 숨을 내쉰다. Day 4 미션 - 메서드 리팩토링 실습, SOLID 개념을 자신 만의 언어로1. 메서드 리팩터링 실습 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; }위의 메서드를 읽기 좋은 코드로 리팩토링 해보는 미션이었다.Early return, 추상화 레벨을 맞춰주기, 공백 라인, 부정어, 이름 짓기에 주의하며 리팩터링을 수행했다.아래 코드가 리팩터링을 거친 코드public boolean validateOrder(Order order) { if (order.getItems().isEmpty()) { log.info("주문 항목이 없습니다."); return false; } if (order.isTotalPriceInvalid()) { log.info("올바르지 않은 총 가격입니다."); return false; } if (order.hasNoCustomerInfo()) { log.info("사용자 정보가 없습니다."); return false; } return true; }2. SOLID 개념을 자신만의 언어로견고한 객체지향 프로그램을 위해 제시된 개념인 SOLID를 자신만의 언어로 설명하는 미션이었다.글이 너무 길어지니까 이거는 생략하겠다. 아쉬웠던 점읽기 좋은 코드로 리팩터링하기 위해서는 테스트 코드가 꼭 필요하다.원래라면 테스트 코드를 짰을 테지만, 시간이 없었다는 핑계로 테스트 코드는 건너 뛰었다.하지만, 테스트 코드 없는 리팩터링이 오히려 시간을 더 잡아먹을 수 있고, 훨씬 개발자를 불안하게 만드는 것 같다.3주차부터는 테스트 코드를 본격적으로 배우게 될텐데 기대된다. 마무리100점 짜리는 아니었지만, 내 상황에서 최선을 다한 한 주였다.미션을 제 때 낼 수 있어서 기쁘다.2주차도 잘해보자. 

백엔드읽기좋은코드클린코드워밍업클럽객체지향추상화

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

프로그램의 정의프로그램 = 데이터 + 코드추상과 구체추상 : 중요한 정보는 가려내어 남기고, 덜 중요한 정보는 생략하여 버린다.메서드와 추상화잘 쓰여진 코드라면, 한 메서드의 주제는 반드시 하나다.메서드 선언부반환타입 메서드명 ( 파라미터 ) { 메서드 구현부 }void 대신 충분히 반환할 만한 값이 있는지 고민해보기 -> 반환값이 있다면 테스트도 용이해 진다. 인텔리제이 메서드 뽑아내는 단축키 : 코드 드래그 후 옵션 + 커맨드 + m -> 메서드로 만들어 준다 추상화 레벨R r = method( ) ; 메서드를 추출하는 것 자체가 외부 세계와 내부 세계로 나뉜다. (경계가 나뉨)하나의 세계 안에서는, 추상화 레벨이 동등해야 한다.  매직 넘버, 매직 스트링의미를 갖고 있으나, 상수로 추출되지 않은 숫자, 문자열 등상수 추출로 이름을 짓고 의미를 부여함으로써 가독성, 유지보수성 증가 public static final int BOARD_ROW_SIZE = 8; public static final int BOARD_COL_SIZE = 10; private static final String[][] BOARD = new String[BOARD_ROW_SIZE][BOARD_COL_SIZE]; private static final Integer[][] NEARBY_LAND_MINE_COUNTS = new Integer[BOARD_ROW_SIZE][BOARD_COL_SIZE]; private static final boolean[][] LAND_MINES = new boolean[BOARD_ROW_SIZE][BOARD_COL_SIZE]; public static final int LAND_MINE_COUNT = 10; public static final String FLAG_SIGN = "⚑"; public static final String LAND_MINE_SIGN = "☼"; public static final String CLOSED_CELL_SIGN = "□"; public static final String OPENED_CELL_SIGN = "■";인텔리제이 상수 뽑아내는 단축키 : 옵션 + 커맨드 + cEarly returnelse의 사용을 지양 : if , else-if , else 를 같이 쓰지 않고 if - return 으로 바꾸면 앞의 정보를 신경 쓰지 않아도 된다. 사고의 depth 줄이기무조건 1 depth로 만드는게 아니다-> 추상화를 통한 사고 과정의 depth를 줄이는 것이 중요-> 2중 중첩 구조로 표현하는 것이 가독성이 좋을 수도 있다. 메서드 분리부정어를 대하는 자세메소드명 자체에 부정어를 적기되도록 2번 생각 해야하는 부정연산자를 사용하지 않는다. 해피 케이스와 예외 처리사용자 입력, 객체 생성자, 외부 서버의 요청 주의의도한 예외와 예상하지 못한 예외를 구분하기 Null을 대하는 자세항상 NullPointException 경계Optional 사용 자제미션2// asis // 사용자가 생성한 주문이 유효한지를 검증하는 메서드 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; } /** 위 코드를 Readable Code로 리팩토링 한다면 * 1. early return을 사용해서 필요없는 else문 삭제하기 * 2. 최대한 getter 사용 지양하기 강제로 객체의 값을 가져오지 않고 객체에게 질문하기 */ // tobe public boolean validateOrder(Order order) { if (order.hasNoItems()) { log.info("주문 항목이 없습니다."); return false; } if (order.isInvalidTotalPrice()){ log.info("올바르지 않은 총 가격입니다."); return false; } if (order.hasNoCustomerInfo()){ log.info("사용자 정보가 없습니다."); return false; } return true; }출처:인프런 워밍업 클럽 2기(백엔드 클린코드, 테스트코드) - https://www.inflearn.com/course/offline/warmup-club-2-be-wb강의 출처 - 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

채널톡 아이콘