블로그

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

개발자 경제신문 읽기 15일차

 '라인의 아버지'도 쫓겨났다... 일본, 네이버 지우기 속도신중호 라인야후 최고제품책임자(CPO) 가 라인야후 이사직에 물러났음라인야후, 네이버에 맡겨온 라인야후 IT 인프라 업무를 분리하고 있음  짠물이자에 정기예금 이탈... '주식, 부동산, 코인' 대기자금 1분기 30조 급증예테크족과 이자 생활자가 정기예금에서 이탈하고 있음. 마땅한 투자처를 찾지 못한 자금이 저원가성 예금에 몰렸다주식, 암호화폐, 부동산 등 자산시장의 부지한 흐름 -> 요구불예금에 예치해놓음. - 예수금이 풍부해서 순이자마진도 개선됨  인간이 새긴 '별자리'... 환경 식량 지구문제 '해결사'저궤도 군집 운성으로 전쟁의 양상을 바꿀 수 있을 것으로 에상아마존 '카이퍼' 상공 590~630km 에서 통신 서비스할 군집 위성. 최대 초당 1GB. 지상 기지국에 문제가 생겨도 사용할 수 있어 안보용으로 사용될 수 있음위성에 AI를 붙여 탄소배출량 관리 : 방대한 위성 데이터를 지상에서 다운로드 받지 않고 실시간으로 처리할 있음. 탄소발자국 모니터링, 불법 어선 탐지, 산림 해양 자원 관리 등스페이스 X가 올해 쏘아올린 위성은 562개, 스타링크 군집 위성은 1,2세대 총 5744개  초저궤도 선점 나선 중국.. '2.6만개 위성 군단' 띄운다중국위성네트워크그룹(CSNG, 중국 정부 출자 100%), 저궤도 1,3만개로 고속 통신망을 구축하는 '궈왕'프로젝트 운용 담당상하이시, '상하이원신위성과기'사 저궤도 위성 1.2만개 쏘는 사업 'G60 스타링크' 프로젝트 공개중국의 목표 : 저궤도 위성. 고도가 낮으면 위성 하나가 맡을 수 있는 면적이 좁아지지만 통신 품질, 속도는 개선 가능하다중국의 GNSS 베이더우(56개, GPS는 31개) 정확도 향상 가능지리그룹, 위성 11개 발사. 최종 240개 운용하여 고정밀 지도, 정밀 측위 기술을 위해차이나 모바일, 6세대 이동통신 시험을 위한 저궤도 위성 발사. 위성-기지국 커버 지역에서 통신 가능.화웨이 첫 폴더블 스마트폰 '포켓2', 샤오미 '14울트라' 에 위성통신기능 추가 전기차 주춤할 때... 일반 자동차, 하이브리드 몰고 판매 질주하이브리드카 선두주자 도요타, 엔저 가격 경쟁력 바탕으로 상당기간 호황을 누릴 것으로 예상됨. 1분기 미국 판매량 20.3% 증가GM-도요타-포드-스텔란티스-혼다-닛산(미쓰비시) 판매 순위. 일본 자동차회사, 엔저 현상에 환차익이 영업이익에 반영됨. 총알로 공격적 마케팅을 펼치면 더 약진할 것으로 예상현대-기아차, 하이브리드카 전략으로 TMED-2 개발, 인도에 신형 SUV 쏘넷 추가 투입, 팰리세이드 하이브리드 출시 앞당기기 검토 중 '글로벌 1000만대' 첫 돌파한 도요타... AI 등 미래 투자 확대도요타 2023년 영업이익 5.35억엔 - 최고기록(2021년)의 1.8배 높은 성과설비 투자, 연구개발비 투자로 '미래'를 준비하겠다테슬라, 자율주행 등을 위한 인공지능 개발에 100억달러 투입 예정, 8월에 로보택시 공개중국 샤오미 등 전기차 메이커가 '지능형 자동차'로 공세  명동에 유커 관광버스 수십대... 면세, 여행 업계 볕드나중국인 관광객 회복세, 중국발 제주도 크루즈/항공 증편(30%)한국, 가성비 여행국 됨 : 원화 가치가 위안화 대비 약세를 보임. 비교적 저렴하게 한국 여행 가능하다 '화웨이 굴기'에 미국, "인텔, 퀄컴 중국 수출 하지마"미국 정부, 화웨이에 반도체 수출하는 자국 일부 기업(인텔, 퀄컴)의 수출 면허 취소'화웨이 쇼크'로 인한 위기감 : 미국 제재에도 최첨단 노트북, 스마트폰 출시, 중국 파운드리 SMIC 7나노 첨단 반도체 출시 및 스마트폰 적용화웨이, 인공지능 노트북 '메이트북x 프로' 출시 CPU에 인텔 코어 울트라 9 이 들어갔음. 급성장 '아시아 AI시장' 눈독, 아마존, MS 데이터 센터 투자AWS : 싱가포르에 2028년까지 12조원 투자 인프라 구축. 데이터센터 건설, 재생에너지 인프라 개발, 현지 인력 육성 등도쿄, 오사카 클라우드 인프라 확장에 20조 투자, 인도에 20조원 투자, 사우디에 7조 투입 계획MS : 인도네시아, 말레이시아에 17억달러, 22억달러 투자 계획. 태국에 10억달러 이상 규모 투자 데이터센터 건설아시아 지역에 AI 수요가 빠르게 성장하고 있음. 데이터 저장 수요가 28년까지 25% 늘어날 것으로 전망.  알리 테무 공습에 쿠팡 영업이익 61% 감소, '어닝쇼크'영업이익 61%, 당기순이익 적자. 중국 e커머스 공세에 따른 마케팅 비용 지출로 이익이 감소했다배송, 상품 차별화로 중국e커머스에 맞서겠다 "로켓배송 지역 확대, 한국산 프리미엄 상품으로 승부, 와우 클럽 혜택 강화" 명품, 식품의 힘... 신세계 백화점 1분기 최대 매출백화점 매출 전년 동기 대비 7.9% 증가(1.8조)2023년 말부터 명품 수요 회복, F&B 디저트 전문관 '스위트파크' 로 식품 매출 1분기 12% 향상신세계까사, 센세계라이브쇼핑 등 자회사 흑자 전환신세계 유니버스 연회비 4900으로 인하하여 최대 가입자 갱신함 "귀국 축하금 쏜다" ... 판 커진 여행자보험카카오페이 손해보험, '보험메기' : 저렴한 여행자보험(3인 1.7만원, 3인 할인혜택 10%, 귀국 축하금 1700원)으로 디지털, 고객 맞춤형 전략으로 판을 흔들고 잇따사고가 나야 보상을 받는 기존 보험과 달리, 안전하게 귀국하면 10%를 돌려줌. MZ세대 중심 입소문 -> 출시 10개월만에 누적 가입자 100만, 월별 신계약 건수 1위삼성화재 : 여행자보험 동반 가입 고객 대상 최대 20% 할인KB손보 : 사고 여부와 상관 없이 보험료의 10%를 '귀국 축하금'으로 페이백한화손해보험의 디지털 보험 자회사 "캐롯손해보험" : 무사귀국 시, 보험료 10%를 포인트로 돌려줌해외 여행자보험 취급 손보사의 1분기 신계약 건수는 50만건, 전년동기 대비 2배 이상 급증보험사간 과당 경쟁을 보호하기 위해 예의주시 중인 금감원 : 페이백 제도가 애초에 보험료를 싸게 책정할 수 있는데 불필요하게 소비자를 현혹하지는 않는지?"여행자보험금을 위해 고의로 사고를 내는 경우가 있어 무사고 환급제는 오히려 좋아  

교양신문읽기

[Spring Boot]6.AOP정리

※스프링 부트 시작하기 책에 있는 내용 정리1.AOP는 OOP(Object Oriented Programming:객체지향 프로그래밍)를 더욱 OOP답게 사용하도록 도와주는개념2.AOP는 관점지향 프로그래밍이라고 하는데 자신의 관점에서 보는것이 아닌 제3자가 보는 관점에서 바라본다고 생각하면 된다.3.AOP는 어떤 로직을 기준으로 핵심적인 관점,부가적인 관점으로 나눠서 보고 그 관점을 기준으로 각 모듈화를 하여 사용한다.※AOP에대한 용어를 정리관점(Aspect) : 공통적으로 적용될 기능을 의미한다. 횡단 관심사의 기능이라고 할수 있고, 한개이상의 pointcut과 advice의 조합으로 만들어진다.어드바이스(Advice) : 관점의 구현체로 조인 포인트에 삽입되어 동작하는 것을 의미한다. 스프링에서 사용하는 어드바이스는 동작하는 시점에 따라 다섯종류로 구분된다.조인포인트(joinpoint) : 어드바이스를 적용하는 지점을 의미한다. 스프링 프레임워크에서 조인포인트는 항상 메서드 실행 단계만 가능하다.포인트컷(pointcut) : 어드바이스를 적용할 조인포인트를 선별하는 과정이나 그 기능을 정의한 모듈을 의미 정규표현식이나 AspectJ의 문법을 이용해서 어떤 조인포인트를 사용할 것인지 결정타깃(Target) : 어드바이스를 받을 대상을 의미한다.위빙(weving) : 어드바이스를 적용하는 것을 의미한다. 즉, 공통 코드를 원하는 대상에 삽입하는 것을 뜻한다. ※어드바이스(Advice) 동작시점에 따른 다섯가지 종류Before Advice(@Before) : 대상 메서드가 실행되기 전에 적용할 어드바이스를 정의After returning Advice(@AfterReturning) : 대상 메서드가 성공적으로 실행되고 결과값을 반환한 후 적용할 어드바이스를 정의한다.After throwing Advice(@AfterThrowing) : 대상 메서드에서 예외가 발생 했을때 적용할 어드바이스를 정의한다. try/catch문의 catch와 비슷한 역할을 한다.After Advice(@After) : 대상 메서드의 정상적인 수행 여부와 상관없이 무조건 실행되는 어드바이스를 정의. 즉 예외가 발생하더라도 실행되기 때문에 자바의 finally와 비슷한 역할을 한다.Around Advice(@Around) : 대상 메서드의 호출 전후, 예외 발생등 모든 시점에 적용할수 있는 어드바이스를 정의한다. 가장 범용적으로 사용할 수 있는 어드바이스입니다.※PointCut(포인트컷)에 대한 명시자 정리excution : 가장 대표적이고 강력한 지시자로 접근 제어자, 리턴 타입 ,타입패턴 ,메서드,파라미터 타입,예외타입등을 조합해서 가장 정교한 포인트컷을 만든다.(예)select*)(..)은 0개이상의 파라미터,메서드,패키지등 모든것을 의미한다.사용예)excution(void select*(..))excution(* board.controller.*())excution(* board.controller.*(..))excution(* board..select*(*))excution(* board..select*(*,*))- 리턴타입이 void이면서 메서드 명이 select로 시작하며 파라미터가 0개 이상메서드- board패키지 밑에 파라미터가 없는 모든 메서드- board패키지 밑에 파라미터가 0개이상 모든 메서드- board패키지의 모든하위 패키지에 있는 select로 시작하고 파라미터가 한개인 모든 메소드- board패키지의 모든 하위 패키지에 있는 select로 시작하고 파라미터가 두개인 모든 메서드withub : 특정 타입에 속하는 메서드를 포인트컷으로 설정합니다.사용예)within(board.service.boardServiceImpl)within(board.service.*ServiceImpl)- board.service 패키지 밑에 있는 boardServiceImpl 클래스의 메서드가 호출 될때- board.service 패키지 밑에 있는 ServiceImpl이라는 이름으로 끝나는 메서드가 호출될때bean : 스프링의 빈 이름의 패턴으로 포인트 컷을 설정합니다.bean(boardServiceImpl)bean(*ServiceImpl)- boardServiceImpl이라는 이름을 가진 빈의 메서드가 호출 될때- ServiceImpl이라는 이름으로 끝나는 빈의 메서드가 호출 될때 1.아래와 같이 로그 출력시에 대한 AOP를 적용2.적용하면 아래와 같이 노출이 된다. 

AOP

이용수

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

[인프런 워밍업 클럽 1기] BE 5일차본 게시글은 다음 강의 내용을 진행하고 있습니다.자바와 스프링 부트로 생애 최초 서버 만들기, 누구나 쉽게 개발부터 배포까지! [서버 개발 올인원 패키지] - https://inf.run/XKQg문제 1 풀이 과정, 한 걸음 더사용자로부터 입력을 받는 부분, 주사위를 던지고 계산하는 부분, 결과를 출력하는 부분으로 메소드를 분리하여 구현했다.숫자 범위가 달라지더라도 동작하도록 코드를 수정했다.DiceRoller.javapackage com.group.libraryapp.controller.assignment3; import java.util.Scanner; public class DiceRoller { public static void main(String[] args) { int numOfFaces = getNumOfFaces(); // 주사위 면의 수를 입력 받음 int[] faceCounts = rollDice(numOfFaces); // 주사위를 던져 각 숫자의 출현 횟수를 계산 printResult(faceCounts); // 결과 출력 } // 사용자로부터 주사위 면의 수를 입력받는 메소드 private static int getNumOfFaces() { System.out.println("주사위 면의 수를 입력하세요:"); Scanner scanner = new Scanner(System.in); return scanner.nextInt(); } // 주사위를 던져 각 숫자의 출현 횟수를 계산하는 메소드 private static int[] rollDice(int numOfFaces) { int[] faceCounts = new int[numOfFaces]; for (int i = 0; i < numOfFaces; i++) { double randomValue = Math.random() * numOfFaces; int face = (int) randomValue; faceCounts[face]++; } return faceCounts; } // 결과를 출력하는 메소드 private static void printResult(int[] faceCounts) { for (int i = 0; i < faceCounts.length; i++) { System.out.printf("%d은(는) %d번 나왔습니다.\n", i + 1, faceCounts[i]); } } }결과 - 6 입력결과 - 20 입력

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

이슬

인프런 워밍업 클럽 스터디 1기 FE 과제(1번, 2번, 3번 과제)

[1번 과제(Day2) - 음식 메뉴 앱]따라하며 배우는 자바스크립트 A-Z학습 범위: Section 1 ~ 3https://github.com/helloleesul/inflearn-warmup-club-study/tree/main/food-menu-app과제 이미지데이터를 json파일로 만들어놓고 처음 로드할 때, 불러와서 작업했다.강의에서 배운 이벤트위임을 활용해서 버튼 그룹에 이벤트리스너를 설정해주고 이벤트타겟의 태그가 버튼일 때에만 메뉴를 필터링할 수 있는 함수를 실행하게 했다.[2번 과제(Day3) - 가위 바위 보 앱]따라하며 배우는 자바스크립트 A-Z학습 범위: Section 4(1~8)https://github.com/helloleesul/inflearn-warmup-club-study/tree/main/rock-scissors-paper-app과제 이미지남은 횟수가 끝나면 결과를 알려주는 부분을 잊고 완성했다가 다시 이어서 작업했다.다시 도전하기를 누를때 화면을 초기화하는 함수를 만들었다.[3번 과제(Day4) - 퀴즈 앱]따라하며 배우는 자바스크립트 A-Z학습 범위: Section 4(9~17)https://github.com/helloleesul/inflearn-warmup-club-study/tree/main/js-quiz-app과제 이미지1번 처럼 데이터를 json파일로 만들어놓고 처음 로드할 때, fetch로 불러와서 작업했는데 데이터 객체 안에 문제와 옵션들, 그리고 answer(정답) 키값을 넣었었다. 하지만 브라우저 네트워크에 답까지 노출이 되는 게 문제라고 생각됐다.그래서 answer(정답) 키값을 없애고, 문제와 옵션들만 데이터로 구성하고 script 안에서 정답 유무를 가릴 수 있게 바꿨다. 풀이는 문제를 배열로 해체하고 ×를 *으로, ÷를 /으로 바꾼 후(-,+는 그대로) eval()함수를 쓰지않고 new Function() 새로운 함수를 생성해서 풀이하게 했다. 

웹 개발인프런워밍업클럽FE1기과제

mingle

[인프런 워밍업 클럽 스터디 BE 1기] 첫 번째 발자국

늦었지만 올려보는 첫 번째 발자국참여 계기취업 한지 벌써 2년이 되어간다. 일을 할수록 부족한 나를 마주하는 순간이 많았다. 그래서 항상 공부하겠다고 다짐했지만, 퇴근 후 공부는 생각보다 쉽지 않았고…. ㅎㅎ.. 그런 와중에 인프런에 들어왔다가 워밍업 클럽 스터디 배너를 보고 관심이 갔다. BE 강의 커리큘럼을 보니 회사에서 사용하지 않는 기술도 있어 더 흥미가 갔고 공부하기 좋은 기회라고 생각해서 지원하게 됐다. 배운 내용환경 세팅, HTTPHTTP Method(GET, POST, PUT, DELETE)를 활용한 간단한 API 개발MySQL과 DDL, DMLSpring과 DB 연결. CRUD API 개발.관심사의 분리 가장 인상 깊은 강의는 리팩토링이다. 회사 일을 하다가 내가 짠 코드에 대해 다른 직원분으로부터 문의를 받은 적이 있다. 시간에 쫓겨 작성한 부분이었고.. 강의를 들으면서 매우 많이 찔렸다. 아무리 바빠도 이후에 내 코드를 읽을 동료, 나를 위한 개발을 해야겠다고 생각했다. 화이팅~스터디에서 가장 만족하는 점은 과제다. 과제를 하다 보면 관련된 다른 궁금한 점이 생기고, 계속 샛길로 빠지게 된다. 한 과제를 하는데 하루 종일 걸린다ㅎㅎ.. 기한이 2일이라서 다행이다. 과제 덕분에 더 많이 배울 수 있었고 재밌었다. 이번 주에 배울 내용과 할 과제도 기대가 된다. 과제

백엔드BE워밍업1기

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도 알면 알수록 더 어려워지는 것 같다…

백엔드