블로그

xicodey

[인프런 워밍업 클럽 1기] BE 5일차 과제

문제주어지는숫자를 하나를 받고 해당 숫자만큼 주사위를 돌려, 각 숫자가 몇 번 나오는지 출력하는 문제 public class Main { public static void main(String[] args) { System.out.println("주사위 면의 수를 입력하세요:"); Scanner scanner = new Scanner(System.in); int a = scanner.nextInt(); int r1 = 0, r2 = 0, r3 = 0, r4 =0, r5 = 0, r6 = 0; for (int i = 0; i < a; i++) { double b = Math.random() * 6; if (b >= 0 && b < 1) { r1++; } else if (b >= 1 && b < 2) { r2++; } else if (b >= 2 && b < 3) { r3++; } else if (b >= 3 && b < 4) { r4++; } else if (b >= 4 && b < 5) { r5++; } else if (b >= 5 && b < 6) { r6++; } } System.out.printf("1은 %d번 나왔습니다.\n", r1); System.out.printf("2은 %d번 나왔습니다.\n", r2); System.out.printf("3은 %d번 나왔습니다.\n", r3); System.out.printf("4은 %d번 나왔습니다.\n", r4); System.out.printf("5은 %d번 나왔습니다.\n", r5); System.out.printf("6은 %d번 나왔습니다.\n", r6); } } 제시된 코드를 최대한 클린하게 만들어라 public class Main { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); int rolls = inputDice(scanner); int sides = inputSide(scanner); int[] results = rollTheDice(rolls, sides); resultPrint(sides, results); } private static int inputSide(Scanner scanner) { System.out.print("주사위 면를 입력해주세요 :"); int sides = scanner.nextInt(); return sides; } private static int inputDice(Scanner scanner) { System.out.print("던질 횟수를 입력해주세요 :"); int rolls = scanner.nextInt(); return rolls; } private static int[] rollTheDice(int rolls, int sides) { int[] results = new int[sides + 1]; for (int i = 1; i <= rolls; i++) { int number = (int)(Math.random() * sides) + 1; results[number]++; } return results; } private static void resultPrint(int sides, int[] results) { for (int i = 1; i <= sides; i++) { System.out.printf("%d은 %d번 나왔습니다.\n", i, results[i]); } } }주사위 면을 받을 수 있는 inputSide함수와 몇번 주사위를 굴릴건지 입력을 받을 수 있는 inputDice 함수,주사위를 돌려 결과를 저장하는 rollTheDice함수와 결과를 출력하는 resultPrint 함수로 구성했다.각 변수는 의미있는 변수명으로 바꾸고 메서드명도 그에 맞게 바꾸었다.

인프런워밍업클럽스터디1기백엔드

이용수

[인프런 워밍업 클럽 1기] BE 4일차

[인프런 워밍업 클럽 1기] BE 4일차본 게시글은 다음 강의 내용을 진행하고 있습니다.자바와 스프링 부트로 생애 최초 서버 만들기, 누구나 쉽게 개발부터 배포까지! [서버 개발 올인원 패키지] - https://inf.run/XKQg문제 1구현 과정구현 목표 : 과일 정보를 입력해 요청하면 상태코드 반환하여 응답함.메서드 타입 : POST경로 : /api/v1/fruitHTTP 요청 Body : { "name" : String, "warehousingDate" : LocalDate, "price" : long } SQL 쿼리문create table fruit ( id bigint auto_increment, name varchar(30), warehousingDate date, price bigint, status boolean default false, primary key (id) );FruitController.javapackage com.group.libraryapp.controller.assingment2.fruit; import com.group.libraryapp.dto.assignment2.request.FruitRequest; import com.group.libraryapp.dto.assignment2.request.SoldRequest; import com.group.libraryapp.dto.assignment2.response.SalesSumResponse; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.web.bind.annotation.*; @RestController public class FruitController { private final JdbcTemplate jdbcTemplate; public FruitController(JdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; } @PostMapping("/api/v1/fruit") public void saveFruit(@RequestBody FruitRequest request) { String sql = "INSERT INTO fruit (name, warehousingDate, price) VALUES (?, ?, ?)"; jdbcTemplate.update(sql, request.getName(), request.getWarehousingDate(), request.getPrice()); }FruitRequest.javapackage com.group.libraryapp.dto.assignment2.request; import java.time.LocalDate; public class FruitRequest { private long id; private String name; private LocalDate warehousingDate; private long price; public long getId() { return id; } public String getName() { return name; } public LocalDate getWarehousingDate() { return warehousingDate; } public long getPrice() { return price; } }한 걸음 더 API에서 long을 사용한 이유null을 사용할 수 있다.int를 사용할 경우 기본값이 0이여서 값이 없어서 0으로 초기화 된건지, 실제 값이 0인지 데이터만 보고 판별하기 어려운 문제점이 있다.반면 Long을 사용할 경우 값이 없으면 null로 초기화되고, 실제 값이 0이면 0으로 저장되기 때문에 값의 유무를 쉽게 판별할 수 있다는 점에서 Long을 주로 사용한다.int보다 더 넓은 범위의 값을 제공한다.정수형 타입 : 데이터의 표현 범위Int : -2,147,483,648 ~ 2,147,483,647Long : -9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807대규모 데이터를 처리하는 경우 데이터의 범위가 중요한데, long 자료형은 int 자료형 보다 월등히 더 넓은 범위의 값을 제공한다.문제 2구현 과정구현 목표 : id를 입력해 요청하면 상태코드 반환하여 응답함.메서드 타입 : PUT경로 : /api/v1/fruitHTTP 요청 Body : { "id" : long }SoldRequest.javapackage com.group.libraryapp.dto.assignment2.request; public class SoldRequest { private long id; public long getId() { return id; } }++FruitController.java ... @PutMapping("/api/v1/fruit") public void updateFruit(@RequestBody SoldRequest request) { String readSql = "SELECT * FROM fruit WHERE id = ?"; boolean isFruitNotExist = jdbcTemplate.query(readSql, (rs, rowNum) -> 0, request.getId()).isEmpty(); if (isFruitNotExist) { throw new IllegalArgumentException(); } String updateSql = "UPDATE fruit SET is_sold = true WHERE id = ?"; jdbcTemplate.update(updateSql, request.getId()); } ...문제 3구현 과정구현 목표 : 과일 정보를 입력해 요청하면 팔린 금액, 팔리지 않은 금액을 반환하여 응답함.메서드 타입 : GET경로 : /api/v1/fruit/statHTTP 요청 Body : { "salesAmount" : long, "notSalesAmount" : long }SalesSumResponse.javapackage com.group.libraryapp.dto.assignment2.response; public class SalesSumResponse { private long salesAmount; private long notSalesAmount; public SalesSumResponse(long salesAmount, long notSalesAmount) { this.salesAmount = salesAmount; this.notSalesAmount = notSalesAmount; } public long getSalesAmount() { return salesAmount; } public long getNotSalesAmount() { return notSalesAmount; } }++FruitController.java@GetMapping("/api/v1/fruit/stat") public SalesSumResponse getAmountInfo(@RequestParam String name) { String sql = "SELECT * FROM fruit WHERE name = ?"; List<SumResponse> list = jdbcTemplate.query(sql, (rs, rowNum) -> new SumResponse(rs.getLong("price"), rs.getBoolean("status")), name); long salesAmount = list.stream() .filter(SumResponse::status) .mapToLong(SumResponse::getPrice) .sum(); long notSalesAmount = list.stream() .filter(res -> !res.status()) .mapToLong(SumResponse::getPrice) .sum(); return new SalesSumResponse(salesAmount, notSalesAmount); }한 걸음 더sum, group by 키워드를 사용해 구현하기++FruitController.java... @GetMapping("/api/v1/fruit/stat") public SalesSumResponse statFruit(@RequestParam String name) { String salesSql = "SELECT sum(price) FROM fruit WHERE is_sold = true GROUP BY name HAVING name = ?"; String notSalesSql = "SELECT sum(price) FROM fruit WHERE is_sold = false GROUP BY name HAVING name = ?"; long salesAmount = jdbcTemplate.queryForObject(salesSql, long.class, name); long notSalesAmount = jdbcTemplate.queryForObject(notSalesSql, long.class, name); return new SalesSumResponse(salesAmount, notSalesAmount); } ...JPA Entity클래스에서 id를 int가 아닌 Long 타입으로 하는 이유 (tistory.com)

백엔드백엔드인프런워밍업

준섭

인프런 워밍업 클럽 스터디 1기 BE 4번째 과제

문제1과일 정보 저장 API{ "name": "사과", "warehousingDate": "2024-02-01", "price": 5000 } 위와 같은 정보를 받아서 저장할 수 있도록 fruit 테이블을 만들었다.create table fruit ( id bigint auto_increment, name varchar(30), warehousingdate date, price bigint, primary key(id) ); 그리고 이전에 구현했던 내용과 똑같이 INSERT문을 이용해 과일 정보 저장 API를 구현했다.public void save(Fruit fruit) { String sql = "INSERT INTO fruit (name, warehousingdate, price) VALUES (?, ?, ?)"; jdbcTemplate.update(sql, fruit.getName(), fruit.getWarehousingDate(), fruit.getPrice()); } 가격을 나타내는 price의 테이터 타입은 long을 사용했는데int를 사용하지 않고 long을 사용하는 이유는가격의 크기가 int의 범위를 초과할 수 있기 때문이다.문제2문제2는 과일이 팔린 경우 팔렸다는 정보를 저장하는 API를 구현하는 문제팔렸다는 정보를 저장하기 위해서 fruit 테이블에 sold라는 컬럼을 추가했다.create table fruit ( id bigint auto_increment, name varchar(30), warehousingdate date, price bigint, sold boolean default false, primary key(id) ); boolean 타입이고 default 값은 false인 sold 컬럼을 만들어서과일이 팔린 경우 해당 API를 호출하면 sold 컬럼을 true로 바꿔주도록 구현헀다.public void updateSold(Long id) { String sql = "UPDATE fruit SET sold = true WHERE id = ?"; jdbcTemplate.update(sql, id); } 문제3특정 과일의 팔린 금액과 팔리지 않은 금액을 조회하는 API 구현하기2가지의 방법으로 구현할 수 있다.1. 과일의 이름에 해당하는 모든 데이터를 조회해서 Service 단에서 금액을 계산하기FruitRepositorypublic List<Fruit> getStat(String name) { String sql = "SELECT name, price, sold FROM fruit WHERE name = ?"; return jdbcTemplate.query(sql, (rs, rowNum) -> new Fruit( rs.getString("name"), rs.getLong("price"), rs.getBoolean("sold") ), name); } FruitServicepublic FruitStatResponse getStat(String name) { List<Fruit> fruits = fruitRepository.getStat(name); long salesAmount = 0; long notSalesAmount = 0; for (Fruit fruit : fruits) { if (fruit.getSold()) { salesAmount += fruit.getPrice(); } else { notSalesAmount += fruit.getPrice(); } } return new FruitStatResponse(salesAmount, notSalesAmount); } 데이터가 다음과 같이 들어있을 경우원하는 결과를 조회할 수 있다.2. 팔린 금액과 팔리지 않은 금액을 조회하는 쿼리를 만들기public FruitStatResponse getStat(String name) { String sql = "SELECT SUM(CASE WHEN sold = true THEN price ELSE 0 END) salesamount, " + "SUM(CASE WHEN sold = false THEN price ELSE 0 END) notsalesamount " + "FROM fruit WHERE name = ?"; return jdbcTemplate.queryForObject(sql, (rs, rowNum) -> new FruitStatResponse( rs.getLong("salesamount"), rs.getLong("notsalesamount") ), name); } SUM 함수를 사용해서 금액의 합을 계산할 수 있고CASE문을 사용하면 sold가 true인 금액을 조건으로 해서 계산할 수 있다. 이렇게 쿼리를 이용하면 다양한 조건의 데이터를 검색할 수 있기 때문에Service단에서 원하는 데이터를 분류하는 작업을 하지 않을 수 있다.SQL을 잘 알면 활용할 수 있는 방법이 무궁무진 하지만SQL도 알면 알수록 더 어려워지는 것 같다…

백엔드

김설하

인프런 워밍업 클럽 스터디 1기 FE | 미션1, 미션2 발자국

미션1: 음식 메뉴 앱간단한 음식 목록을 카테고리 별로 분류하여 보여주는 앱📇 레포지토리 주소: https://github.com/zldnlto/inflearn-warming-up/tree/main/01_%EC%9D%8C%EC%8B%9D%20%EB%A9%94%EB%89%B4%20%EC%95%B1header, main과 같은 큰 골격을 index.html에 짜 두고 기능이 필요한 요소들은 동적으로 생성하여 DOM에 붙이는 방식으로 구현하였다.데이터 페칭을 다루는 방식이 미숙하다고 생각하여, 짧은 데이터지만 굳이 data.json 을 생성해서 페칭을 모사해보았다. HTML validator 통과, 카드 부분에 <figure>,<figcaption> 사용하는 등 시멘틱한 태그 작성 주요 로직MenuList 라는 객체 배열을 통해 메뉴 버튼을 생성하고 관리한다.init() 함수 는 앱 최초 진입시 실행되며 전체 카드 목록을 불러온다. ('All'이 디폴트) renderCard() 함수는 html 요소 템플릿을 찍어내는 함수다. 각각의 Card 컴포넌트를 생성한다.handleFilterBtn() 을 통해 버튼 id와 일치하는 foodData를 필터링한다.const renderCard = (data) => { let newCard = ""; if (data) { data.forEach((v) => { const menuItem = `<li class="card"> <figure class="card-content"> <img src="./assets/${v.image}" alt="${v.name}" class="card-cover" /> <figcaption class="card-text"> <div class="card-title"> <strong>${v.name}</strong> <div class="price">${v.price}원</div> </div> <span class="hr"></span> <p class="card-info"> ${v.description} </p> </figcaption> </figure> </li>`; newCard += menuItem; }); } return newCard; };각각의 요소를 따로 생성하기보다는 Card컴포넌트를 생성할 때 <li> 태그 이하의 자식 요소들이 많은 점을 고려하여 innerHTML 로 덩어리 템플릿을 이어붙이고 렌더링 하는 방식으로 구현하였다. 아쉬운 점 / 느낀점 :오랜만에 vanillaJS를 다뤄서 그런지 파일명과 같은 작은 부분들에서 '이게 맞나' 하는 생각의 연속이었다.프레임워크/라이브러리를 주로 사용했다고 한들 간단한 기능 위주임에도 생각보다 시간이 걸려서 아쉽다. 기능 위주로 구현하면 된다고 하셨는데 이왕이면 하는 마음을 버릴 수가 없어서 디자인도 조금씩 고민하게 된다. 간단한 기능일텐데 코드가 생각보다 길다. 더 효율적으로 짜는 방법이 있을 것 같다. 미션2: 가위 바위 보 앱컴퓨터와 가위바위보!📇 레포지토리 주소: https://github.com/zldnlto/inflearn-warming-up/tree/main/02_%EA%B0%80%EC%9C%84%EB%B0%94%EC%9C%84%EB%B3%B4%20%EC%95%B1 미션 프로젝트들을 한 레포지토리에 관리하려 하는데 root 경로에 common 폴더를 만들고 전반적으로 임포트해 사용할 reset.css 파일을 생성하였다. 주요 로직가위바위보 게임의 특성상 -1,0,1 숫자를 이용한 Matrix를 생성하여 승패를 판가름하였다.const resultMatric = [ [0, -1, 1], // rock [1, 0, -1], // scissors [-1, 1, 0], // paper ]; 기능 별 함수를 분리시켜서 캡슐화시키는 부분에 신경썼다.가위,바위,보 버튼을 눌렀을 때 화면 동작이 발생한다. 그런 의미에서 메인이 되는 함수를 뽑자면 각 버튼의 이벤트 함수라고 생각하였다. handleScissorBtn, handleRockbtn, handlePaperbtn 버튼을 보았을 때 어떤 동작이 일어나는지 한 번에 보이도록 하였고 코드는 아래와 같다. const handleScissorBtn = () => { USER_PICK = 1; COMPUTER_PICK = generateComputerPick(); calculateScore(USER_PICK, COMPUTER_PICK); resultRender(USER_SCORE, COMPUTER_SCORE); return USER_PICK; }; generateComputerPick() 0~2 사이의 난수를 리턴한다.calculateScore() 유저의 패와 컴퓨터의 패를 인자로 받아 resultMatric 기반으로 승패를 계산한다.resultRender() 승패 결과를 렌더링한다. 남은 횟수가 0이 되면 결과를 띄운다.  그 외 코드calculateResult() 게임이 끝난 후 유저가 이겼는지 컴퓨터가 이겼는지 결과만을 판단해 렌더링한다.아쉬운 부분const resultRender = (USER_SCORE, COMPUTER_SCORE) => { REMAINING_POINT -= 1; remainigPoint.innerText = REMAINING_POINT; userScore.innerText = USER_SCORE; computerScore.innerText = COMPUTER_SCORE; if (REMAINING_POINT === 0) { // 아쉬운 부분 resultText.innerText = ""; remainingBox.style.display = "none"; rcpBtnBox.style.display = "none"; selectText.innerText = calculateResult(); selectText.style.fontSize = "3.5rem"; restartBtn.style.display = "block"; return; } };남은 도전 횟수가 0이 되면 가위바위보 각 버튼과 선택하기 텍스트 등을 화면에서 숨기고 게임 결과와 재도전 버튼을 보여주어야 한다. 이 부분을 각각의 요소들을 일일이 display="none" css 처리를 하는 식으로 동작시키고 있는데, classList.add 메서드를 이용하여 코드를 줄이는 방식으로 리팩터링 할 수 있을 것 같다.또한 selectText 변수가 선택하기 텍스트를 보여주며 경우에 따라 게임 결과도 표현하고 있는데 변수명이 포괄적이지 못해 아쉽다.변수를 생성할 때는 영문 기반이라 바위-가위-보 순으로 생각하게 되는데 버튼은 가위 바위 보 순이어서 소소한 통일성 이슈가 있다. 우선 버튼 순서 빼고는 전자로 구현되어 있다. 버튼의 코드 정렬 순서와 가위바위보의 0,1,2 매칭 순서, 그리고 약어로 rsp인데 rcp라 오타나있는 부분 등 통일성 부분에서 개선이 필요하다. (rcpBtnBox) 느낀 점html 태그를 단순히 많이 생성하는 것을 지양하기 위해 body 태그에 id='root' 속성을 부여하고 DOM을 생성하려 했는데 body 안의 <script> 태그 때문에 의도한 대로 작동하지 않았다. 사소한 실수지만 React에서 요소를 렌더링 할 때 <body>를 그대로 쓰지 않고 <div id='root'></div> 를 사용하는 이유가 렌더링 공간을 따로 분리하는 의도였구나 생각한다.VanillaJs를 하면서 오히려 React의 편리함 측면에서 교훈을 많이 얻게 된다. 특히 DOM을 일일이 변경시키는 작업을 통해 React에서 상태가 변화하면 UI가 자동으로 바뀐다는 게 얼마나 경이롭고 편리한 기능인지 느꼈다.미션 1과는 달리 이번에는 모든 요소를 js에서 생성해보았는데, html 코드로 골격을 어느정도 짜 놓은 상태에서 로직을 붙이듯 작성하는 것이 html / css / js 가 기능적으로 분리되어 가독성 측면에서 적절하다 생각한다. 

프론트엔드인프런워밍업클럽

xicodey

[인프런 워밍업 클럽 1기] BE 4일차 과제

문제 1하기전에 테이블을 작성을 합니다.create table fruit ( id bigint auto_increment, name varchar(20), warehousingDate date, price bigint, is_sale boolean default 0, primary key (id) ); 과일 정보 저장하는 API요청을 받기 위해 FruitRequest 를 만듭니다.@Data public class FruitRequest { private String name; private LocalDate warehousingDate; private long price; } 요청을 받고 쿼리문을 날려 저장하는 비지니스 로직을 만듭니다.@AllArgsConstructor @Service public class FruitService { private final JdbcTemplate jdbcTemplate; public void save(FruitRequest request) { String sql = "insert into fruit (name, warehousingDate, price) " + "values (?, ? ,?)"; jdbcTemplate.update(sql, request.getName(), request.getWarehousingDate(), request.getPrice()); } }FruitService 클래스를 만들어 데이터 삽입sql을 만들고 jdbcTemplate로 업데이트 해주는 비지니스 로직을 만듭니다. @AllArgsConstructor @RestController @RequestMapping("/api/v1/fruit") public class FruitController { private final FruitService fruitService; @PostMapping public ResponseEntity<?> savedFruit(@RequestBody FruitRequest request) { fruitService.save(request); return ResponseEntity.ok().build(); } } FruitController를 만들어 비지니스 처리를 완료하면 정상 응답을 내리는 메서드를 만들면 됩니다. int 와 long 사이에 long을 사용하는 이유는 표현 범위 때문입니다.long 이 int 보다 월등히 많은 수를 표현하기 때문입니다. 문제 2과일 팔리면 과일 정보 기록 API응답을 받기 위해 FruitStateRequest 클래스를 만듭니다.@Data public class FruitStateRequest { private Long id; }비즈니스 로직을 수행하기 위해 FruitService 크랠스에서 다음과 같은 메서드를 작성합니다.public void stateUpdate(FruitStateRequest request) { String fruitSql = "select * from fruit where id = ?"; boolean isFruitNotExist = jdbcTemplate .query(fruitSql, (rs, rowNum) -> 0, request.getId()).isEmpty(); if (isFruitNotExist) { throw new IllegalStateException("일치하는 과일 정보가 없습니다."); } String sql = "update fruit set is_sale = 1 where id = ?"; jdbcTemplate.update(sql, request.getId()); }먼저 해당 id로 과일 정보가 있는지 확인을 합니다.없으면 일치하는 과일 정보가 없다고 경고를 주고 있으면 업데이트 sql문으로 업데이트 쿼리를 날립니다.@PutMapping public ResponseEntity<?> FruitStateUpdate(@RequestBody FruitStateRequest request) { fruitService.stateUpdate(request); return ResponseEntity.ok().build(); }FruitController에 put요청을 받기 위한 메서드를 만들고 정상으로 수행이 되면 200 요청을 보냅니다.문제 3특정 과일 기준으로 팔린 금액과 팔리지 않은 금액 조회먼저 수행하기전 테이블에 과일 정보를 입력해둡니다.FruitController 에 과일 이름 파라미터를 받고 처리하기 위해 메서드를 만듭니다.@GetMapping("/stat") public ResponseEntity<?> isSaleStateTotalPrice(@RequestParam String name) { return ResponseEntity.ok(fruitService.getSum(name)); }서비스 로직에서 정상 수행을 하면 결과값을 반환하게 만들었습니다. 이제 비지니스로직을 FruitService에 작성해줍시다public FruitTotalPriceResponse getSum(String name) { String fruitSql = "select * from fruit where name = ?"; boolean isFruitNotExist = jdbcTemplate .query(fruitSql, (rs, rowNum) -> 0, name).isEmpty(); if (isFruitNotExist) { throw new IllegalStateException("일치하는 과일 정보가 없습니다."); } String sql = "select is_sale, sum(price) as totalPrice from fruit " + "where name = ? group by is_sale"; List<FruitTotalPriceResponse> results = jdbcTemplate.query(sql, new Object[]{name}, (rs, rowNum) -> new FruitTotalPriceResponse( rs.getBoolean("is_sale") ? rs.getLong("totalPrice") : 0, !rs.getBoolean("is_sale") ? rs.getLong("totalPrice") : 0)); long salesAmount = 0; long noSalesAmount = 0; for (FruitTotalPriceResponse result : results) { salesAmount += result.getSalesAmount(); noSalesAmount += result.getNoSalesAmount(); } return new FruitTotalPriceResponse(salesAmount, noSalesAmount);과일 이름으로 과일 정보가 있는지 확인합니다.없으면 에러를 일으키고 있다면 다음 로직을 수행합니다.과일이 팔렷는지 아닌지 확인을 위해 is_sale 그룹으로 해당 과일의 is_sale와 price 합계를 구합니다.그리고 쿼리문으로 리스트 결과를 받아 각각의 합계를 구한후 리턴합니다.매번 repository로 하던 습관으로 하다보니 간만에 jdbcTemplate 으로 하는데 꽤나 예를 먹은 과제인거 같다.

인프런워밍업클럽스터디클럽1기백엔드

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

강의 수강일주일 동안 학습했던 내용을 요약해주세요.일주일 간의 학습 내용에 대한 간단한 회고를 작성해 주세요.섹션 0.Java, inteliiJ, Postman, MySQL, git 설치 방법에 대해 배웠습니다.Cmd를 통하여 Mysql에 접속하는 방법으로 데이터베이스, 테이블 조작을 할 수 있다는 것을 알게 되었습니다.MySQL CMD 접속 방법mysql -u [계정] -p [데이터베이스]저는 root 계정과 비밀번호를 설정하여mysql -u root -p 타이핑 후비밀번호 타이핑CMD에서 MySQL을 찾지 못하는 경우에는환경변수에 시스템 변수에 Mysql폴더의 bin폴더까지 주소를 복사하여 넣어주어야합니다. 섹션 0 회고다시 Java, inteliiJ, Postman, MySQL, git 설치 방법에 대해 보게 되니까 예전에 해봤던 기억이 떠오르고 미쳐 몰랐던 inteliiJ에 대해 알아가는 시간이 되었고 Postman을 저번 프로젝트를 할때는 자주 사용하지 않았는데 간편하게 사용할 수 있는 테스트 도구라서 자주 사용할 거 같습니다.  섹션 1.컴파일 : 인간이 이해하기 쉬운 언어를 기계어로 번역하는 과정컴파일러 : 컴파일을 하는 프로그램바이트 코드 : 0 , 1로 이루어진 코드, 컴퓨터가 이해하는 기계어java는 JVM을 통하여 기계어로 OS에 맞게 번역해준다.JVM(Java Virtual Machine) 자바 가상 머신의 약자OS 별로 존재바이너리 코드를 읽고 검증하고 실행 JRE(Java Runtime Environment)JVM + 자바 프로그램 실행에 필요한 라이브러리 파일 등JVM의 실행환경을 구현JDK(Java Development Kit)JRE + 개발을 위한 도구컴파일러, 디버그 도구 등이 포함 섹션 1 회고자바의 작동원리와 SpringBoot에 대한 기본적인 작동 흐름과 CRUD에서 CR에 대해 배우게 되었고, 잘 읽어야 다른 동작에 대해 쉽게 접근할 수 있을거 같아 배운것을 돌아보고 원리에 대해 되집어 보는 시간이 되었습니다. 섹션 2.Mysql에서 테이블만들고, 데이터를 조작하는 방법을 배움sql문을 통하여 intelliJ에서 Update, Delete에 관한 API를 작성섹션 2 회고inteliiJ와 Mysql을 연결하는 작업을 하였습니다. 연결하고 올바르게 데이터가 들어가는게 중요하다 생각이 들었고 sql문이 잘못 작성되어 곤란한 경우가 있었습니다. 찾는 것도 힘들었지만 sql문에 대해 좀 더 정확하게 작성하여 올바르게 전송되게끔 꼼꼼히 작성해보겠습니다.섹션 3. 클린코드에 대해 배우고 기존에 있던 코드를 리펙토링하며 더 분리시키고 깔끔한 코드로 작성하는 방법을 배웠습니다.  섹션 3 회고클린코드에 중요성과 작성하고 있는 코드에서 더 좋은 코드가 될 수 있을 지에 대한 고민이 많이 생긱나는 강의였고, 개발에는 끝없는 고민으로 시작되는거 같습니다.미션미션을 해결하는 과정을 요약해 주세요.미션 1 : https://www.notion.so/1-9ebaa9acab404522894cadf7aada5eb0 -> 구글 검색을 통해서 어노테이션에 대한 미션에 대한 정보들에 대해 보고 실습해보았습니다.미션 2 : https://www.notion.so/2-8e30c53ecab443e5bb3d3a1bcf8abcb4-> 강의를 보고 원하는 Get, Post라던지 관한 정보를 입력하고 어떻게 출력되는지 건드려보게 되었습니다.미션 3 : https://www.notion.so/3-7516e809e6134f0fbc255c3f57d239bb-> 검색을 통하여 람다식에 대해 알게 되었고 잘 활용만 한다면 코드를 단축시키고 클린 코드를 만들어 보게끔 연습을 해보아야겠다는 생각이 들었습니다. 

백엔드백엔드인프런스터디

winnercold

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

학습한 내용Java컴파일: 인간이 이해하기 쉬운 언어를 기계어(바이트 코드)로 번역하는 과정컴파일러: 컴파일을 하는 프로그램바이트 코드: 0과 1로 이루어진 코드, 컴퓨터가 이해할 수 있다.자바의 JVM은 다양한 운영체제에서 바이트 코드를 실행할 수 있도록 중간 단계 역할을 한다.따라서 JVM만 운영체제별로 존재한다면, 하나의 바이트 코드로 각각의 운영체제에서 실행 할 수 있다.JVM자바 바이트 코드를 실행하는 가상머신바이트 코드를 읽고 검증 및 실행한다.Java 외에 다른 언어에서도 사용된다. JRE자바 애플리케이션 실행 환경JVM의 실행환경 구현 JDK컴파일러, 디버그 등을 포함하는 자바 개발 도구 Build소스 코드 파일을 컴퓨터에서 실행할 수 있는 독립 SW 가공물로 변환시키는 과정 빌드 과정소스 코드를 컴파일한다.테스트 코드를 컴파일 한다.테스트 코드를 실행한다.테스트 코드 리포트를 작성한다.기타 추가 설정한 작업들을 진행한다.패키징을 수행한다.최종 SW 결과물(Artifact)을 만들어 낸다.실행작성한 코드(혹은 테스트 코드)를 컴파일 후 실행해 보는 과정독립 SW 가공물이 생성될 수도 있고, 생성되지 않을 수도 있다.인터프리터 언어의 경우, 컴파일 과정이 필요 없다.빌드 툴(Build Tool)빌드 과정을 자동으로 처리 해주는 프로그램외부 소스 코드(외부 라이브러리) 자동 추가, 관리빌드란 단순히 실행하는 것과 다르다.빌드 과정 자동화와 외부 라이브러리 관리를 위해 빌드 툴이 사용된다.네트워크(Network)여러 컴퓨터나 장치들이 서로 데이터를 주고받을 수 있도록 연결된 시스템IP: 네트워크 상에서 각 장치를 구별하기 위해 사용되는 고유의 식별 번호도메인 이름: 외우기 어려운 IP 주소 대신, 사람이 읽을 수 있는 이름으로 대체할 수 있는 별칭포트: 하나의 IP 주소 내에서 특정 프로그램이나 서비스를 식별하기 위해 사용되는 숫자HTTP(Hypertext Transfer Protocol)인터넷에서 데이터를 주고받기 위한 표준 프로토콜프로토콜(Protocol): 통신을 위한 규칙과 약속규칙HTTP Method: 요청을 받는 컴퓨터에게 요구하는 행위GET: 데이터 요청(쿼리 사용)POST: 데이터 전송(바디 사용)PUT: 데이터 수정(바디 사용)DELETE: 데이터 삭제(쿼리 사용)Host: 요청을 받는 컴퓨터의 정보를Path: 요청하는 자원의 경로 데이터 전달 방법쿼리(Query) URL에 포함되어 데이터를 전달?를 통해 쿼리와 Path를 구분한다.쿼리 사이에는 &를 통해 구분한다.본문(Body) 별도의 본문을 통해 데이터를 전달API(Application Programming Interface)클라이언트와 서버 간의 HTTP 통신을 통해 정해진 약속에 따라 특정 기능을 수행인터페이스(Interface): 규약, 규칙JSON(JavaScript Object Notation)객체를 표현하기 위한 형식(객체 표기법)용법중괄호(`{}`)로 묶여 있다.중괄호 안에, "key": value로 표기한다.키("key")와 값("value")은 :로 구분된다.속성(키-값)은 ,로 구분한다.데이터베이스(Database)데이터를 구조화 시켜 저장하고, 관리하는 시스템RDB(Relational Database)는 데이터를 표(table) 형식으로 구조화하여 관리한다. SQL(Structured Query Language)표 형식으로 구조화된 데이터를 조회, 삽입, 수정, 삭제하는 언어SQL을 통해 데이터베이스와 상호작용DDL(Data Definition Language)데이터를 정의하기 위한 SQL데이터베이스 생성CREATE DATABASE [데이터베이스 이름];데이터베이스 목록 조회SHOW DATABASES;데이터베이스 삭제DROP DATABASE [데이터베이스 이름];데이터베이스 선택USE [데이터베이스 이름];테이블 생성 CREATE TABLE [테이블 이름] ( [필드1 이름] [타입] [부가조건], [필드2 이름] [타입] [부가조건], ... PRIMARY KEY ([필드 이름]) );테이블 목록 조회SHOW TABLES;테이블 삭제DROP TABLE [테이블 이름];DML(Data Manipulation Language)데이터 조작을 위한 SQL데이터 삽입 (생성 - Create)INSERT INTO [테이블 이름] (필드1이름, 필드2이름, ...) VALUES (값1, 값2, ...)데이터 조회 (읽기 - Retrieve or Read)SELECT * FROM [테이블 이름] WHERE [조건];데이터 수정 (업데이트 - Update)UPDATE [테이블 이름] SET 필드1이름=값1, 필드2이름=값2, ... WHERE [조건];데이터 삭제 (제거 - Delete)DELETE FROM [테이블 이름] WHERE [조건];수정과 삭제 시, 조건을 지정해주지 않는다면 모든 데이터에 적용되기 때문에 주의해야 한다.클린 코드(Clean Code)코드(Code)는 요구사항을 표현하는 언어다.개발자는 이러한 요구사항을 구현하기 위해 코드를 읽고 작성한다.코드를 읽는 것은 소프트웨어 개발에서 필수적이며 피할 수 없다.작성 원칙함수는 작고 명확하게 작성되어야 한다.클래스는 하나의 책임만을 가져야 한다.이유협업 과정에서 다수의 개발자가 동시에 수정할 수 없다.코드를 읽고, 이해하기 어렵다.함수의 일부분을 수정하더라도, 수정된 코드가 다른 부분에 영향을 미칠 수 있기 때문에 함부로 수정할 수 없게 된다.코드의 기능이 커서 테스트가 어렵다.이로인해 유지보수성이 떨어진다.회고지금까지는 Java의 다양한 기능을 사용하는 과정에서 그저 기능들을 활용하는 데 그쳤던 것 같다. 그러나 이번 스터디를 통해 강의를 듣고 미션을 수행하면서 해당 기능들이 등장한 배경과 목적을 공부할 수 있었고, 앞으로 어떻게 공부해야 하는지 배울 수 있었던 1주차 였다.

백엔드

이영섭

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

강의 수강Section 1 - 생애 최초 API 만들기 스프링부트 프로젝트를 생성과 시작하는 방법 네트워크의 기본지식 GET API, POST API 개발Section 2 - 생애 최초 Database 조작하기MySQL 테이블 생성과 데이터 CRUD스프링에서 DB연결하여 Section 1 에서 만들었던 기능 DB로 바꿔보기예외처리Section 3 - 역할의 분리와 스프링 컨테이너역할의 분리, 스프링 컨테이너를 사용하는 이유미션미션을 해결하는 과정에 있어서 이론에 대한 과제는 구글링을 많이 해보며 해결하였고, 문제풀이 과제에 있어서는 수업시간에 알려주신 내용을 적용해보고자 내가 알고있는 방식을 사용하지 않으려고 최대한 노력하여 해결해나갔습니다.첫번째 과제 : https://marble-morning-cfc.notion.site/cb942416aeb146a8ba1c2cc6a016adf5두번째 과제 : https://marble-morning-cfc.notion.site/228acc26d0a747b1a8cdbec83a2d8165세번째 과제 : https://marble-morning-cfc.notion.site/ed40f10ddb3d48ba830d0f88a6e55a31회고강의내용을 듣고 과제를 함에 있어서 자료도 많이 찾아보고, 생각도 많이 하게되는 과제가 출제해주셔서 스터디를 올바른 방향으로 하고 있구나 느꼈고, 아직 부족한 실력이지만 남은 기간 스터디 이외에 다른 공부들도 열심히해서 많은 것들을 얻어 갈 수있는 스터디가 되도록 열심히 해보겠습니다!

백엔드

강호연

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

1. 강의 관련새로 배운 내용console 객체 console.log 외에 .table, .error, .warn, .time, .clear 등 다양한 메소드가 있다. 변수 선언 let const는 호이스팅 되도 초기화가 일어나지 않아서 TDZ에서 호출시 undefined가 아닌 에러가 뜸객체 타입  콜 스텍에 값이 그대로 저장되는 원시타입과 달리, 객체 타입은 주소만 저장 실제 값은 메모리 힙에 저장이 된다 forEach for 문에서 루프제어를 위한 break, continue를 사용할 수가 없기에 return 등의 꼼수를 써야한다. 웬만하면 배열의 모든 요소를 순회해야할 때만 쓰는 게 좋은 듯 window 객체 원래 스크롤 관련 메소드들만 알고 있었는데, location, history, cliboard 등의 유용한 메소드들이 있다. innerHTML textContent, innerText html 내부 값을 바꿀 때 무지성으로 innerHTML만 써왔는데 비용이 높다고 한다. 내부 텍스트만 수정이 되는 경우에는 text 관련 메소드를 사용하는 것이 좋다.iterator와 generator다시 공부해야함. 뭔소린지 모르겠음회고다행이 미리 알고 있던 내용이 대부분이고, 강의도 미리 들어둬서 진도에는 맞출 수 있었지만 리액트 파트는 진도를 어떻게 따라가야할지 조금 막막하다 지식은 가장 자신만만할 때가 갓 기본을 뗐을 때인 것 같다. 기본 강의 완강하고 뭐든 만들 수 있을 것 같던 때에서 3배는 더 많은 지식을 습득했지만 여전히 JS는 자신이 없다. 리액트 파트 시작 전에 조금 더 심도있게 학습을 해야할 것 같다. 2. 미션 관련Click! 미션 GitHub 주소각 프로젝트별 상세는 각 프로젝트 readme 파일에 서술해 뒀으니 간단하게 언급하고 넘어가려한다. 미션 1 음식 메뉴앱로직 플로우메뉴 항목들이 속한 ul에 click eventListener를 부착하여 개개의 li가 아닌 ul에서 이벤트를 처리한다.클릭된 요소의 name 속성(카테고리 정보)와 data.js에서 갖고온 데이터를 renderMenu 함수에 전달한다.renderMenu함수는 data에서 선택된 메뉴에 해당하는 데이터를 선별 후 화면에 그린다.  회고하는 내내 리액트면 금방하는데 라는 생각을 했던 것 같다. 그래서 리액트 처럼 랜더로직과 데이터를 분리하여 만드는 것을 목표로 했다. 미션 2 가위바위보로직 플로우 시작하기를 누르면 게임화면으로 넘어간다. 컴퓨터는 가위 바위 보 중 랜덤으로 낸다. 가위 바위 보 중 뭐든 냈을 경우에 승패에 따라 스코어를 갱신하고 결과를 보여준다. 한 세트가 끝나면 종합 스코어를 표시하고, 다시하기 버튼으로 다시할 수 있도록 한다. 회고 만들면서 시행착오를 가장 많이 한 프로젝트이다. setTimeout과 setInterval을 원없이 써봤다. 기본 구현 사항이 너무 시시하고 디자인도 좀 아쉬워서, 두 부분을 좀 더 확장해봤다. 미션을 보고 짱꼔뽀가 생각나서 디자인은 거기서 레퍼런스를 얻어 만들었고, 로직은 '안내면 진거'를 추가 했다. 로직 자체는 간단한데 interval을 어디서 clear할지를 고민해야했다. 우측의 카운트 다운과 가운데 컴퓨터 픽이 바뀌는 두 부분이 서로 다른 interval로 돌아가기 떄문이다. 이 때문에 두 interval을 동시에 관리할 수 있는 패턴을 고안하여 설계했다.안 내면 진거 가위바위보 미션 3 퀴즈 앱로직 플로우 문제 데이터를 html에 바인딩고룬 선택지에 따라 화면을 분기정답인 경우오답인 경우 다음 버튼을 눌러 다음 문제로 ( 갖고올 데이터 위치++)회고 미션 영상을 여러번 돌려봤지만 도무지 뭘 만들어야하는 건지 알 수 없었다. 최소 구현 스펙을 서술해주면 좋겠다. 그래서 로직 자체보단 데이터처리나 디자인 처리에 주안점을 두고 미션을 수행했다. 퀴즈 데이터는 chatGPT에게 프론트엔드 퀴즈 10개를 내달라고 부탁해서 데이터를 갖고 왔다. 그러자 문제 데이터를 txt로 주길래 연습할 겸 fs로 데이터를 갖고와서 데이터를 파싱하는 함수를 작성했다(data.js),함수를 작성하던 중 문득 'json형식으로 퀴즈 데이터 만들어줘' 라고 질문하면 되지 않을까 싶어서 해보니 정말 됐다....그러나 연습이니 변수명만 참고하고 직접 해보았다. 또, 알기만 하고 써보진 않았던 ::after 선택자를 활용해서 정오답 처리(o, x)를 진행했다.번외로 가장 디테일을 많이 챙긴 미션이다.배경색은 안과의사가 추천하는 눈이 피로하지 않은 색이다. 퀴즈 푸는 데 머리만 아파야지 눈이 아프면 안 되지, 안 그런가?문제 부분의 텍스트는 수능에서 쓰는 중명조체이고 css font-face를 통해 갖고 왔다.정답 표시 파트에서 선택지에 hover시 노란색으로 변하는 css는 정오답 선택지에 대해서는 무시된다. (정오답 선택지에 !import 붙임) 미션 4 리스트 앱 리액트 기본예제에서 지겹도록 해본 todo앱이다. MVC 패턴을 사용해보려 노력했다. 또 no-CSS 프로젝트로 html만을 이용해서 페이지를 구성했다. 로직 플로우 리스트 추가 및 삭제데이터 수정 (MODEL)데이터 추가 : bookData 배열에 데이터를 추가한다.데이터 삭제 : bookData 배열에서 데이터를 삭제한다.랜더링 (CONTROL) : 수정된 데이터를 받아와서 template(VIEW)에 데이터를 바인딩하여 랜더링알림 : 데이터 수정 후 성공 알림을 띄움 (dialog //화면 중간에 팝업창 뜸)회고 유저 플로우를 생각하여 입력 편의 개선에 신경을 썼다. 별 건 아니지만 꽤 편하다.페이지 최초 진입시 제목 input에 autofocus되도록 속성을 추가함책을 등록 후 제목 input을 비우고, 제목 input에 focus가 되도록 함  생각보다 다양한 HTML 테그가 있다는 것을 알게된 프로젝트이다. dialog, fieldset, legend, table 등 평소 잘 안 써본 테그들을 적극 기용하여 마크업에 힘을 썼다. 특히 dialog 테그를 조작하는 과정에서 js로 html 속성을 다루는 방법을 심도 있게 학습할 수 있던 것 같다. 미션 5 GitHub Finder 앱fetch를 통해 github api를 활용해보는 것이 목표인 프로젝트이다. Next.js에서 지겹게 해본 부분이라 쉽게 해결할 수 있었다. 로직 플로우  검색창 input에 input 이벤트리스너를 부착하여 검색어를 받는다.input의 값이 바뀔 때마다 fetch 함수를 통해 데이터를 불러온다.가져온 데이터를 바인딩한다. (단, 데이터가 없는 경우 (response.message == 'Not Found') 에는 유저 데이터를 표시하지 않는다.). 회고 github OAuth 인증하고 토근을 같이 보내지 않으면 시간당 20건의 요청만 거부되지 않고 할 수 있다. 이 부분을 찾아보고 해결해도 잘 되지 않았다.. mock 데이터를 활용할까 했지만 데이터를 만드는 것이 더 시간이 걸릴 것 같아서 요청을 최소화하면서 날마다 조금씩 작업을 했다. 다행이 어렵진 않아서 금방 끝났지만 다음에는 캐싱을 하든 뭘 하든 해결책을 강구해야할 것 같다. 미션 6 비밀번호 생성 앱로직 플로우  선택된 옵션 항목에 따라 문자풀을 생성한다.생성할 비밀번호 길이와 문자풀을 통해 랜덤 비밀번호를 생생한다.생성된 비밀번호를 결과창에 표시한다.  회고 chatGPT에게 html, css를 맡겼는데 checkbox input과 label을 이용하여 꽤나 세련된 옵션창을 만들어줘서 놀랐다. 물론 fieldset과 legend는 직접 수정했다. 난이도가 제일 쉽고 코드도 가장 짧은 프로젝트였다. 영문 대소문자를 베이스로 하고, 특수문자는 홈페이지마다 비밀번호 양식이 다르니 유저에게 입력 받는 방식으로 만드는 게 더 좋지 않았을까 싶다.  문자풀을 생성하는 과정에서 fromCharCode라는 String의 메소드를 찾았는데 직접 [a,b,c...] 하지 않아도 되서 편했다.let pool = []; //영문 대문자를 풀에 추가 if (qs("#include-uppercase").checked) { const uppers = Array.from({ length: 26 }, (_, idx) => String.fromCharCode(idx + 65) ); pool = pool.concat(uppers); ... } 프로젝트 관련 회고기능 구현은 다 되지만 이게 잘 짜여진 코드인지 아닌지를 스스로 판단할 힘이 다소 부족한 것 같다. 다른 사람들 코드를 참고하면서 좋은 부분을 흡수할 수 있도록 해야겠다. 그리고 미션 7. 타이핑 테스트는 가장 재밌는 미션인데 시간이 너무 부족해서 무사히 마무리할 수 있을지 모르겠다.

프론트엔드워밍업클럽발자국

공존

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

학습 내용강의 내용네트워크IP 고유 주소HTTP와 API에 대해서HTTP는 지켜야 할 규칙. 일종의 통신을 위한 표준서로 소통하고 상호작용하기 위해 정의된 규약HTTP methodGET, POST, PUT, DELETE HTTP 응답값DBRDB데이터를 표처럼 구조화 시켜 저장하는 친구SQL표처럼 구조화된 데이터를 조회하는 언어인텔리J DB 연결 DDLDB를 정의하는 언어CREATEALTERDROPTRUNCATEDMLSQL 데이터를 조작하는 언어SELECTINSERTUPDATEDELETE Layered Architecture 3단 분리ControllerServiceRepository회고록스터디에 참여해서 꾸준히 강의를 듣게 만들어줘서 좋다. 게으른 나도 열심히 하는중!수업 자체가 기본기부터 천천히 접근하기 좋게 되어 있어서 이해하기도 쉽고 전체적으로 내용을 복습하기 좋은 수업이다!생각해보니까 포스트맨 자주 안쓰듯이 개발했는데 이번 기회에 포스트맨으로 테스트 하는 습관을 기른거같다~~! 미션이론, 실습 이렇게 돌아가면서 미션이 있는거같다.이론 부분도 어노테이션이 있어서 사용했지 어노테이션의 배경지식 같은건 깊게 생각해본적이 없는데 이참에 찾아보게 됐다. 실습 부분도 하면서 다른분들은 나랑 다르게 어떻게 진행했는지 알 수 있어서 좋았다!최근에 4일차 미션같은 경우도 요구조건에 맞게 테이블 컬럼을 어떻게 짜보면 좋을지 다시 생각해보게 된거같다.

백엔드워밍업워밍업스터디워밍업1기워밍업백엔드

kacdoogi

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

시작4주 동안 잘 해보자.피그마의 기능/장점을 이애하지 못하고 '빠르게 제작/수정 여럿이서 공동작업이 용이한 툴' 정도로 사용하고 있었다. 그러다 이 강의를 신청하고 동료와 스터디를 하려고 하던 참에 인프런 워밍업 스터디 클럽이 진행된다고 해서 신청했다.무료버전만 사용하다 보니 variable을 안써봤는데 교육용으로 계정도 준다고 하여 고민없이 신청했다.네이밍 짓기 너무 어려운데 알려준다고 한다.4주 열심히 따라가다 보면 완강도 할 수 있을 거 같았다.이런 이유로 나는 워밍업 클럽을 신청하게 됐다.수업 노트 Libraries Color 만들기tailwind color palettes 를 이용해서 색을 만들어줍니다.color style guide를 이용해서 등록된 라이브러리 색을 가이드화 시켜줍니다.만들어진 스타일 가이드에서 필요한 색만 남기고 삭제 해주고 사용하세요. 컨버스에 있는 컬러팔레트와 스타일가이드는 지워주세요.플러그인 -> color style guide 를 실행시켜줍니다. variable collection 만드는 순서primitive Collection를 만들어서 hex 코드를 넣어주세요.semantic Collection 을 만들어서 libraries 에서 색상을 찾아서 연결 시켜주세요.primitiveblue, green, yellow, red, gray ...색의 원시값(Hex)을 저장해 놓은 디자인 언어의 기본 값blue 100/500, red 100 등 이렇게 등록 themebrand, success, danger, info, warning, neutral ...상황에 맞게 등록 함 semantictext, icon, bg, border의미에 맞게. Color Scoping: 색의 범위를 지정해 줌.bg : frame 선택icon: shape 선택text: text 선택border: stroke 선택 베리어블을 다 등록한 후에는 local에 있는 스타일은 지워주세요. 왜요? 색상 값이 너무 많아서 선택하기 힘들어요.Icons단색 아이콘은 vector->union 으로 합쳐주세요. 그러면 Fill로 색상을 바꾸기 좋아요.  PluginAutometic Style Guides: Generate Swatches from Variables 베리어블에 만들어진 내용들을 스타일 가이드 형식으로 만들어줘요.Foundation color generator: ddTailwind Color Palettes: 색을 만들어준다. (필요 없는 색은 지워준다.)Color Style Guide : 등록된 라이브러리 색을 가이드화 시켜주자.typography style guide: 글자 스타일을 등록했다면 스타일 가이드를 만들자.Batch styler: 스타일 등록할 때 글자 지정을 잘 못했다면 일일이 바꾸지 말고 플러그인을 쓰자. GridFrame 에서 Auto Layout 적용 후 반응형 Min-width / Max-width 지정할 수 있어요.회고Variable 등록하기는 자면서 들었나봐요.미션1은 자면서 들었나 싶을 정도로 엉뚱하게 제출. 튜터 볼드님의 코멘트를 보고 수업 노트 적어가며 강의를 다시 들었다. 다른 학습자분들이 올려주신것도 보면서 미션을 수행하니 이해가 잘 됐다. 토요일 저녁 8시 특강 때 궁금했던 점 알려주시고 새로운 내용도 알게 되어 정말 좋았다. 네이밍 할 때 늘 고민되던 것들을 다른 사람들은 어떻게 사용하는지 어디서 찾아볼 수 있는지 팁도 알게되어 알찬 시간이였다.막 사용하던 피그마는 그만이미 피그마를 '막'사용하고 있어서 강의 내용이 쉬울거라 생각했었는데, 정말로 막 사용하고 있었다. ㅠ-ㅠ기초부터 차근차근 배워가고 있다. 프로젝트 진행 시 시스템 가이드를 만들어 '이거 수정 해주세요' 했을 때 파일들 다 열어서 수정하지 않고, 한번에 '수정-적용-배포' 할 수 있는 모습을 그리며, 남은 3주도 잘 따라가보자.

UX/UI워밍업클럽디자인시스템피그마Figma