블로그

윤대

[인프런 워밍업 0기 Day5] 한 걸음 더! 객체 지향으로 클린코딩!

!! 해당 글은 독자가 인프런 워밍업 0기를 수강하고 있다는 전제 하에 작성되었습니다 !!과제 수행에 있어 스프링부트 3.2.2 버전을 사용하고 있다는 점을 미리 알려드립니다!안녕하세요🙌! 인프런 워밍업 5일차 과제입니다!이번에는 클린코드의 중요성에 대하여 학습하고 클린코드를 작성하는 방법에 대해 배웠습니다!😎저는 이번 과제를 그동안 책으로만 공부했던 객체 지향을 적용하여 해결해보고자 했습니다.이론으로만 공부했기 때문에 많이 서툴 수 있다는 점! 그렇기에, 저의 말이 정답이 아니라는 점을 미리 말씀 드리며!지금부터 객체 지향을 향한 저의 여정을 소개하겠습니다! 🤸‍♂️💡과제 살펴보기아래는 과제로 주어진 지저분한 코드입니다! 바라보기만 해도 머리가 어지러운데요.. 😥public class Main { public static void main(String[] args) throws Exception { System.out.print("숫자를 입력하세요 : "); 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); Dice luckyDice = UnknownDice.decideFaces(6); Note memoPad = new MemoPad(); Dealer dealer = Dealer.playWith(luckyDice, memoPad); System.out.print("숫자를 입력하세요 : "); dealer.rollDiceMultipleTimes(scanner.nextInt()); dealer.tellTheResult(); } }어떤가요? 내부 로직이 어떻게 되는지는 모르겠지만, 메소드명만을 보고도 원래의 코드와 똑같은 동작을 수행할 것이 기대할 수 있습니다!그렇다면, 내부는 어떻게 구현됐을까요? 내부 구현을 함께 살펴보기 전에 객체 지향이 무엇인지 짧게 설명 드리고 가겠습니다! 💡객체 지향 프로그래밍이란?객체 지향은 '프로그램이'라는 거대한 로직을 '객체'라는 작은 역할로 나누고, 그 '객체'들끼리 상호 협력하여 데이터를 처리하는 방식을 말합니다!어젯밤에 저는 오렌지를 하나 먹었는데요! 이 오렌지가 집에 오기 까지의 과정을 '프로그램'이라고 보겠습니다.그리고, 지금부터 오렌지의 여정을 절차 지향적으로 설명해보겠습니다! 😎먼저 오렌지 나무를 볕 좋은 곳을 찾아서 심고, 거름도 포대를 찢어서 뿌리 주변에 뿌려주고, 해충도 유기농을 위해 핀셋으로 잡아주고.. 설명이 끝도 없이 길어집니다!그렇다면 이번엔 오렌지의 여정을 객체 지향적으로 설명해볼까요?오렌지를 농부가 '재배'하고, 운송 회사가 '운송'하고, 마트에서 '판매'되어 저의 집까지 왔습니다!어떤가요? 훨씬 설명이 쉽고 이해하기 좋지 않은가요? 오렌지가 어떻게 재배되었는지, 운송되었는지, 판매되었는지 우리는 구체적으로 알 필요가 없습니다! 궁금하지도 않고요!이렇게 내부 구현을 숨기고, 역할 만을 외부에 공개하여 코드의 가독성을 올리고 협업을 용이하게 하는 것이 객체 지향의 장점입니다!이는 개체 지향의 단편적인 장점입니다! 더 많은 장점이 있지만, 지금은 클린코딩과 관련하여 추상화와 캡슐화로 인한 장점 만을 이야기하고 넘어가겠습니다! 😭😭 💡도메인 선정하기!  자! 이제 다시 과제로 넘어와 보겠습니다~ 위에서 객체 지향에서 중요한 것은 역할과 협력이라고 했습니다!우리는 요구 사항을 잘 읽고 작은 역할을 찾고 그 역할을 수행할 주인공(도메인)을 선정해야 합니다. 😎사용자로부터 숫자를 하나 입력 받는다.해당 숫자만큼 주사위를 던져, 각 숫자가 몇 번 나왔는지 알려준다. -> 핵심 로직!!저는 핵심 로직에서 두 가지 역할을 찾았습니다! 하나는 무작위의 수를 생성하는 것, 다른 하나는 생성된 수를 각각 세는 것입니다.그리고, 발견한 역할을 바탕으로 이를 수행할 두 가지 도메인을 만들었습니다.무작위 수를 생성하는 🎲주사위(Dice)와 이를 기록해주는 📃노트(Note)입니다!그렇다면, 이 둘을 재빠르게 설계해 볼까요?abstract public class Dice { private final int faces; protected Dice(int faces) { this.faces = faces; } protected int getFaces() { return this.faces; } abstract int throwDice(); } public interface Note { void record(Integer number); void printTheResult(); }다양한 경험을 위해, 저는 주사위는 추상 클래스로 노트는 인터페이스로 만들었습니다!Dice의 throwDice()는 주사위를 굴리는 행위를 나타내며 무작위 수를 생성합니다!Note의 record()는 입력되는 수를 기록하고 기록된 수는 printTheResult()를 통해 출력할 예정입니다!이렇게, 추상 클래스와 인터페이스로 만드는 이유는 해당 동작을 수행할 수 있다면 그게 무엇이든 역할을 대체할 수 있게 하기 위함입니다! 숫자를 기록하고 출력할 수 있다면 메모지던, 스케치북이던, 스마트폰이던 상관이 없습니다!이제 이 둘을 구현해보겠습니다!public class UnknownDice extends Dice { private UnknownDice(int faces) { super(faces); } public static UnknownDice decideFaces(int faces) { return new UnknownDice(faces); } @Override public int throwDice() { return (int) (Math.random() * super.getFaces()) + 1; } } import java.util.HashMap; import java.util.Map; public class MemoPad implements Note { private final Map<Integer, Integer> page = new HashMap<>(); @Override public void record(Integer number) { page.put(number, page.getOrDefault(number, 0) + 1); } @Override public void printTheResult() { for(Map.Entry<Integer, Integer> number : page.entrySet()){ System.out.printf("%d은(는) %d번 나왔습니다.\n", number.getKey(), number.getValue()); } } }이렇게, 구현이 끝이 났습니다! 그런데, 이럴 수가! 여전히 문제가 있습니다. 도메인을 구현한 것 만으로는 로직을 수행할 수가 없습니다..! 😥바로, 주사위와 노트를 어떻게 사용할 것인지 맥락(컨텍스트)이 없기 때문입니다! 💡컨텍스트 만들기!주사위는 무작위 수를 생성하고! 노트는 기록을 합니다! 제가 생성한 도메인은 자신의 역할을 잘 수행합니다!그러나 노트는 숫자라면 무엇이든 잘 기록할 수 있습니다! 그게 꼭 주사위의 숫자가 아니어도 상관이 없습니다.그렇기에, 우리는 맥락(컨텍스트)이 필요한 것입니다. 도메인을 연결하여 의미가 있는 역할을 수행하게 하는 것이죠!그렇게 저는 딜러(Dealer)라는 새로운 객체를 만들었습니다! 요청을 받아 주사위를 굴리는 게 게임 같았거든요..!public class Dealer { private final Dice dice; private final Note note; private Dealer(Dice dice, Note note) { this.dice = dice; this.note = note; } public static Dealer playWith(Dice dice, Note note) { return new Dealer(dice, note); } public void rollDiceMultipleTimes(int numberOfRoll) { for (int i=0; i<numberOfRoll; i++) { note.record(dice.throwDice()); } } public void tellTheResult() { note.printTheResult(); } }딜러의 역할은 게임의 진행입니다! 사용자에게 요청 받은 숫자만큼 주사위를 굴려주고! 노트에 결과를 전달하고 기록된 결과를 사용자에게 알려주는 역할을 수행합니다! 😃주사위와 노트는 딜러의 게임 진행이라는 맥락(컨텍스트) 아래에서 자신들의 역할을 수행합니다! 어떤가요? 객체들이 서로 협업 하며 역할을 잘 수행하여 로직을 수행하고 있습니다!또한, 흥미로운 점은 딜러는 주사위와 노트가 자신의 역할만 잘 수행할 수 있다면(인터페이스를 충실히 구현했다면) 얼마든지 다른 주사위나 노트로 바꿀 수 있습니다! 사기를 칠 지도 모르겠군요! 😜 💡정리하며...자, 이제 클린코딩을 수행한 코드를 다시 보겠습니다! 현재의 내부 구현은 모두 알지만, 구현체인 주사위와 노트는 언제든지 바뀔 수 있습니다!그러나, 우리는 주사위와 노트가 자신의 역할만 잘 수행할 수 있다면, 그것이 바뀌어도 상관이 없다는 사실도 알고 있습니다!이것이 객체 지향이 주는 다형성이라는 장점입니다! 글이 너무 길어져서 짧게 설명하는 점 죄송합니다...😭public class Main { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); Dice luckyDice = UnknownDice.decideFaces(6); Note memoPad = new MemoPad(); Dealer dealer = Dealer.playWith(luckyDice, memoPad); System.out.print("숫자를 입력하세요 : "); dealer.rollDiceMultipleTimes(scanner.nextInt()); dealer.tellTheResult(); } }객체 지향 정말 매력적이지 않은가요? 책을 통해 이론으로만 배운 객체 지향을 직접 설계부터 구현하며 쓴 저의 긴 기록을 지금까지 읽어주셔서 감사드리며, 객체 지향을 모르시던 분들께 조금이라도 도움이 되었으면 합니다!사실.. SOILD부터 대뜸 외우라고 하면, 어렵습니다 객체 지향..남은 스터디 기간도 다들 즐거운 코딩하시길 바라겠습니다! 🙇‍♂️

백엔드객체지향클린코딩스프링부트인프런워밍업클럽스터디도메인컨텍스트추상화캡슐화

잇택잇

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

출처: https://itaekit.tistory.com/13 들어가기 전에2주차를 마무리하였다. 나름대로 1주차를 충실히 보낸건지,2주차는 조금 더 수월하게 따라갈 수 있었다. 2주차에는 아래의 내용을 학습했다.스프링 컨테이너스프링 빈Spring Data JPA트랜잭션1주차의 내용에 깊이를 더했고,조금 더 프레임워크스러운 내용을 배웠다. Day 06 : 스프링 컨테이너의 의미와 사용 방법여섯째 날,드디어 스프링의 동작 원리에 대해 기본적인 내용을 학습할 수 있었다. 코드를 프로그래머가 직접 제어하는 라이브러리와 달리프레임워크는 프로그래머의 코드가 사용되는 입장이다보니,그 안에서 돌아가는 방식이 정말 궁금했다. Spring Container스프링 컨테이너는 스프링 프레임워크의 핵심 중 하나로 다음의 역할을 수행한다.스프링 빈 관리의존성 주입AOP트랜잭션 관리DI, IoCDI(Dependency Injection)은 '의존성 주입'으로,의존성이 발생하는 클래스에 대해 스프링 빈으로 등록되어있는 경우 스프링에 의해 자동 주입된다. IoC(Inversion Of Control)은 '제어 역전'으로,사용되는 대상을 프로그래머가 아닌 프레임워크가 결정하는 개념이다.Spring Bean스프링 컨테이너에 의해 생성되고 관리되는 객체를 의미한다. Spring Bean 등록 방법스프링 빈으로 등록하기 위해서는 아래의 방법 중 하나를 선택한다. @RestController, @Service, @Repository이전까지 사용하던 방법으로 사용자가 정의한 클래스에 직접 붙여 스프링 빈으로 등록한다. @Configuration, @Bean @Configuration과 @Bean은 세트다.  주로 외부 라이브러리, 프레임워크에서 사용하는 방법이다. @Component 스프링 빈이 되기 위해서는 반.드.시. 가져야하는 어노테이션 특정 클래스를 컴포넌트(스프링 빈)로 취급하기 위한 어노테이션으로,컴포넌트는 스프링 컨테이너의 감지 대상이 된다. @RestController, @Service, @Repository, @Configuration 모두 내부적으로@Component를 가지고 있다. 컨트롤러, 서비스, 레포지토리 이외의 클래스를 추가적으로 스프링 빈으로 등록하기 위해 사용하는 방법이다. Spring Bean 주입 방법스프링 빈에 대한 의존성을 갖는 경우,스프링 컨테이너에 의해 자동으로 DI된다. DI를 처리하기 위해서는 다음과 같은 방법 중 하나를 선택할 수 있다. 생성자를 이용한 주입 (권장) 근본 가장 권장되는 방법으로,특정 스프링 빈을 필드로 갖게 하고 생성자를 작성한다. 참고로 스프링 3이전에는 생성자 위에 @Autowired를 명시해야 했다. setter + @Autowried를 이용한 주입 벌써 불편 @Autowired는 스프링 빈을 찾아 연결해야 함을 전달한다. setter를 이용하는 경우,누군가가 setter를 사용할 수 있어 나도 모르는 사이에 문제가 발생할 수 있는 코드다. 필드에 @Autowired를 이용한 주입 작성하기 편해도 나중에 ㅅ 필드에 직접 주입하는 방법으로테스트가 어려워져 권장하지 않는다. @Qualifier @Qualifier(Spring Bean 이름) 스프링 빈을 매핑하여 사용해야하는 경우 사용하는 어노테이션정상적인 IoC를 위해 사용된다. 과제 리뷰첫번째는,지난 과제에 대해 Layered Architecture에 맞게 리팩토링하는 과제였다. Layerd Architecture로 구조를 잡으니,확실히 코드의 역할이 분명해졌고 유연하게 확장할 수 있게됐다. 두번째는,하나의 인터페이스를 구현하고 있는 여러개의 레포지토리 클래스 중 특정 레포지토리를 사용하기 위한 방법을 묻는 과제였다. 오늘 배운 @Qualifire로 매핑할 수도 있고,@Primary로 지정할 수도 있다. 짧은 회고조금씩 로우레벨로 들어가다보니 확실히 재밌다.그동안 궁금했던 내용에 대해 조금씩 알게 되니 속이 다 시원! 그러나 알아야 할 것들이 너무나 많다는 사실이 조금 섭섭하다. 아직 스프링 빈도 몇 개 안되고,각 레이어에서도 클래스가 한 개 씩 있다보니 아키텍쳐 관점에서의 힘을 충분하게 체감하지 못한 것 같다. Day 07 : Spring Data JPA를 이용한 DB 조작이전까지는 레포지토리 스프링 빈으로 DB와 통신했다.직접 SQL문을 작성했다. 과연 이것이 좋은 코드일까? Java는 객체지향 언어로 절차지향의 코드에서 벗어나야한다.그러나 SQL문을 그대로 작성하는 것 역시 절차지향 관점에 더 가깝다고 볼 수 있다. 직접 SQL을 사용할 때 단점쿼리를 문자열로 작성하게 되어 런타임에서만 오류를 알 수 있음특정 DBMS에 종속적인 코드를 짜게 됨DB의 Table과 코드의 Object는 서로 다른 패러다임으로 이루어져 있어 객체지향 활용이 어려움 JPA (Java Persistence API)Java 진영의 ORM(Object-Relational Mapping)으로 Hibernate를 구현체로 한다. 참고로,Hibernate의 내부는 JDBC로 동작한다. Spring Data JPA는 복잡한 JPA를 한번 더 Wrapping한 라이브러리다. Entity DB의 User tableUser Entity JPA의 객체로 간주되는 클래스를 일컫는다.DB Table과 완벽 호환되어 사용된다. Spring Data JPA를 이용한 쿼리 날리기JPA를 도입한 이유는,코드 레벨에서 DB와 스프링을 객체지향 관점으로 작성하기 위함이다. JPA를 통해 더이상 SQL문을 직접 작성하지 않고도,동일한 기능을 수행할 수 있게 된다. JpaRepository를 상속하는 Repository 생성 @Repository를 붙이지 않아도 스프링 빈으로 등록되는 마법 해당 레포지토리 인터페이스는 스프링에 의해 빈으로 등록되어 객체화된다.프로그래머는 추상화된 인터페이스를 갖고 활용만하면 된다. 아아... Spring Data JPA 너란 녀석은...(1) 기본적으로 다양한 SQL문에 대응하는 여러 연산을 지원한다.  아아... Spring Data JPA 너란 녀석은...(2) 필요에 따라 인터페이스 안에 추상메서드로 선언하는 것으로 기능을 구현할 수 있다. 과제 리뷰역시 바로 이전 과제의 연장선이다. MySQL로 직접 연결하여 사용한 코드를JPA로 리팩토링하는 문제였다. 사실 SQL에도 자신이 있어 크게 불편하지는 않았지만JPA가 손에 익으면 더 편해질 것 같았다. 특히 레포지토리 인터페이스에 새로운 메서드를 작성하는 것으로 손쉽게 SQL문을 그대로 구현할 수 있었다.조금 더 객체지향 코드에 가까워졌다. 그러나,과연 JPA로 복잡한 SQL문까지 완벽히 대체하는걸까? 라는 의문이 들기도 했다. 나중에 알게 되겠지. 짧은 회고처음엔 분명 겁을 먹었다. JPA...?ORM...?Hibernate...? 익숙하지 않아서,들어본 적 없어서 지레 겁을 먹고 배우기를 미뤘던 내용들이었다. 결국에는 일맥상통하는 개념이었다. 아마도,새로운 것을 배워나감에 있어 이런 기분은 계속 이어질 것 같다. 무엇을 배우더라도열린 마음으로 적극적으로 배워나가다보면,결국 익숙해지고다 알게 되는 것 같다.   Day 08 : 트랜잭션과 영속성 컨텍스트SQLD를 취득한 내게 트랜잭션은 꽤 익숙한 개념이다.트랜잭션에 대한 개념을 다시금 확인하고,스프링에서는 트랜잭션을 어떻게 구현하는지 알아보자. Transaction트랜잭션은 쪼갤 수 없는 업무의 최소 단위를 의미한다. 예를 들어,A 계좌에서 B 계좌로 송금이 되었다.그러나 전산 오류로 B 계좌는 돈이 들어오지 않았다. 어쨌거나 돈은 보냈으니,이는 정상적으로 동작했다고 볼 수 있는가? 당연히 아니다.본래 송금이라는 것은 상대방 계좌에 돈이 안전하게 들어가는 것 까지 모든 동작이 이뤄져야 한다. 이렇게 쪼갤 수 없는 업무의 단위를 트랜잭션이라고 한다. @Transactional 점점 프레임워크의 매력에 빠져간다...이렇게 쉽게 해주다니... 스프링은 트랜잭션을 허무할만큼 간단하게 구현할 수 있다.트랜잭션으로 처리할 메서드에 @Transactional을 붙이는 것으로 구현한다. 메서드의 모든 로직이 성공적으로 수행되면 commit 처리되며,동작 중 예외가 발생하는 경우 rollback처리된다. 영속성 컨텍스트 (Persistence Context)트랜잭션 수행 중 Entity 객체를 관리, 보관하는 역할을 수행한다.트랜잭션이 수행될 때 자동으로 생성되며,트랜잭션이 종료되면 함께 종료된다. 영속성 컨텍스트의 특징Dirty Check : Entity 변경 사항을 자동으로 감지하여 저장 (별도의 save가 필요없음)쓰기 지연 : 모든 SQL 요청을 한번에 묶어서 전송하여 DB 통신으로 발생하는 오버헤드를 줄임1차 캐싱 : id를 기준으로 DB로부터 읽어들인 Entity 객체를 캐싱하여 효율적인 입출력 처리 짧은 회고실제 서비스를 위한 재료를 많이 얻어간 날이다.어렵지 않으나 유익한 시간이기도했다. 단순 API 작성에서,JPA를 사용한 DB 처리와 트랜잭션을 고려한 API 작성이 가능하게 됐다. 프레임워크의 강력함에 대해 나날이 느끼고 있다.프레임워크의 내부 동작에 대해서는 여전히 많은 공부가 필요한 것도 사실이다. 사용법만 아는 코더가 되기보다,원리와 해결법 모두 이해한 엔지니어가 되도록 노력하자! Day 09 : 조금 더 복잡한 기능을 API로 구성하기새롭게 배운 내용 없어 정리는 생략! (개꿀) 짧은 회고아홉번째 날은 이제껏 배운 모든 내용을 활용하여 API를 작성하는 연습을 가졌다. 역시 프로그래밍은 내가 직접 만들어갈 때가 제일 재밌다. 세번째 Online Session : Test Code, Refactoring세번째 온라인 미팅은 정기 미팅이 아닌 깜짝 미팅이었다.참여자는 적었지만 배운 내용은 그 어느 때 보다 많았다. 테스트 코드 작성하는 방법많은 채용공고 우대사항 중 "TDD를 사랑하는 사람"이라는 내용을 많이 봤는데아직 내겐 먼 내용이라 생각해 배울 생각도 하지 못한 개념에 대해 맛 볼 수 있었다. 너무나 당연하지만,테스트 코드란 실제 작성한 코드의 구현을 테스트 하는 코드이다. 테스트 코드를 작성함으로써 얻을 수 있는 이점은,나중에 실제 코드를 변경하게 되더라도 동일한 결과를 내는 동일한 로직인지를 쉽게 알아낼 수 있다는 점이다. 작성하는 방법은,필요한 의존성을 설치하고 @Test를 붙이는 것으로 끝이다...public class CalculatorTest { @Test public void addTest() { // given : 데이터 준비 Calculator calculator = new Calculator(); // when : 테스트 메서드 호출 int result = calculator.operate(1, 5, '+'); // then : 값 검증 (예외 테스트 경우 when과 then 통합) assertThat(result).isEqualTo(8); } } 물론 좋은 테스트 코드를 작성하는 것은 지금 수준에서는 벽처럼 느껴졌으나그렇게 어렵지만은 않은 내용이겠구나라고 느낌을 가질 수 있던 것 만으로도 큰 수확이었다. 리팩토링리팩토링이라 하면 이전의 코드와 동일한 기능을 수행하되코드의 가독성을 개선하는 작업이다. 좋은 리팩토링을 하기 위해서는좋은 테스트 코드를 작성함으로써 준비할 수 있다고 한다. (아직 와닿지 않음) 2주차 후기스프링 부트에 대해 익었다고 표현할 수 있을 것 같다. 처음부터 프로젝트 설정에 대해 반복 연습을 하다보니,설정 관련 문제로 막히지 않아 낯설게만 느껴진 프레임워크가 점점 익숙해져간다. API 작성은 계속 연습하고 있고,그동안 배웠지만 흩어졌던 지식들이 하나로 합쳐지면서,"배운 건 어떻게든 돌아오는구나" 라고 느꼈다. 과제도 미리 다 끝내 놓으니 부담도 없다!우수 러너에 선정될지는 모르겠지만... 이미 너무나 많은 것을 배워가고 있단 생각에 이 과정에 참여한 것이 정말 잘한 선택이라고 생각한다.  멘토님 말씀으로,오늘까지 기본적인 재료들은 다 배웠고,앞으로는 조금 더 객체지향스러운 코드를 짜는 법을 배운다고 하신다. '좋은 코드'에 대한 고민을 게을리하지말자.지금부터 확실하게 연습해두자!

백엔드워밍업클럽스터디스프링최태현

잇택잇

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

원본 : https://itaekit.tistory.com/12들어가기 전에인프런 워밍업 클럽 스터디 1기에 참여하게 되었다.함께 성장하는 즐거움을 맛보고 싶었고,커뮤니티로부터 동기부여도 받고 싶었고,무엇보다 막막하기만했던 독학에서 방향성을 얻고 싶었다.3주 간의 여정에서 많은 성장을 해내고 싶다.인프런 워밍업 클럽 스터디 소개인프런에서 주최하는 온라인 스터디다.이번 1기의 경우 Backend(Java/Spring), Frontend(JS/React), Product Design(Figma) 과정이 운영된다.각 과정마다 강사와 서포가 배정되고 강사님의 인프런 강의를 수강하게 된다.내가 참여하게 된 BE 스터디의 경우총 4주 진행 중 3번의 온라인 세션이 예정되어 있다.혼자서 강의를 듣고 공부했던 여태까지의 방식과 다르게,커뮤니티에 참여해 함께 공부하게 되고 강사님 가까이서 배울 수 있단 점이 참 매력적이다.또한,과제 및 미니프로젝트가 제공되어 더욱 견고한 학습을 할 수 있고,현직자의 멘토링을 받으며 학습의 방향성을 잡을 수 있단 점이 가장 큰 차별점이라고 생각한다.뿐만 아니라,수료자/우수 수료자를 뽑아 소정의 장학금, 굿즈, 인프콘 티켓, 1:1 멘토링 등이 제공되어 동기부여가 된다.(굿즈 갖고 싶다...)첫번째 Online Session : OT , 이런것 까지 알아야 할까?온라인 세션을 통해 강사님과 첫번째 만남을 가졌다.전반적인 과정 소개와 함께 과정에 앞서 알고 있으면 좋을 사전 지식들을 설명해주셨다.Java는 컴파일 언어일까, 인터프리터 언어일까?Compile고급 언어로 작성된 소스코드를 로우 레벨의 기계어로 번역하는 과정이다.한 번에 전체 코드를 모두 기계어로 번역하기 때문에 컴파일 이후 실행 속도가 빠르다는 장점이 있다.Java의 경우 .java -> .class(Bytecode)가 컴파일 과정에 해당한다.Interpreter컴파일 방식과 다르게 소스코드 한 줄 씩 읽어들여 런타임으로 번역하는 과정이다.Java의 경우 JVM이 .class를 실행할 때 처리하는 방식이다.Java는 컴파일 언어일까, 인터프리터 언어일까?Write Once, Run Anywhere- James GoslingJava는 두 방식 모두 채택하고 있다.먼저 Bytecode로 컴파일 하고 이를 플랫폼별로 최적화된 JVM이 인터프리터 방식으로 실행한다.이를 통해,기존 컴파일 언어의 단점이었던 OS 종속을 해결했고,기존 인터프리터 언어의 단점이었던 타입 불안전성을 극복할 수 있게된다.JIT (Just-In Time) Compiler인터프리터 언어의 단점은 실행 속도가 느리다는 점이다.이를 극복하기 위해 JVM은 Just-In Time Compiler라는 기술을 사용한다.JIT Compiler는 바이트코드를 분석하고,자주 실행되는 코드 블록을 미리 구분하여 Native machine code로 컴파일하여 실행 속도를 높인다.물론 장점만 얻을 수는 없다.JIT Compiler는 애플리케이션 최초 배포시 사용된 적 없는 코드로 인해 분석에 많은 리소스가 발생하게 된다.이를 해결하기 위해 배포 전 미리 웜업을 거쳐야한다.JVM, JRE, JDKJVM (Java Virtual Machine)Bytecode를 읽고 검증하여 실행하는 가상 머신이다.OS별로 최적화되어있어 동일한 Bytecode에 대해 플랫폼별 실행을 가능하게 한다.JRE (Java Runtime Envrionment)JVM 및 실제 실행에 필요한 여러 라이브러리 파일 포함하는 실행 환경JDK (Java Development Kit)JRE 및 Compiler, Debugger 등 포함하는 개발 환경Build, Build ToolsBuild소스파일로 부터 Artifact를 생성하는 일련의 과정소스코드 컴파일테스트코드 컴파일, 실행, 리포트기타 추가 설정 작업패키징Artifact 생성Build ToolsBuild 자동화 관리 프로그램으로 대표적으로 Gradle(Groovy), Maven(xml) 사용짧은 회고Java/Spring이 처음인 내게,강사님의 모든 말들은 그 자체로 지식의 확장이었다.간간히 들어서 익숙하긴한데,실제 내용을 알지 못하는 부분에 대해 많이 알아갈 수 있었다.이런 기본적인 것들을 왜 두려워하기만 했을까?알아간다는 즐거움과 함께 앞으로 알아가야 할 것들이 얼마나 많을까라는 걱정도 공존했지만,정말 오랜만에 능동적으로 학습하는 기분이 들어 행복했다.Day 01 : 서버 개발을 위한 환경 설정 및 네트워크 기초첫째날 학습한 내용은 아래와 같다.스프링 프로젝트를 시작하는 방법서버 개발에 필요한 기본 지식간단한 API 작성 및 테스트스프링 프로젝트 시작스프링 프로젝트를 시작하는 방법은 크게 2가지다.기존 프로젝트를 다운 받아 시작spring initializr를 사용해 새 프로젝트 생성1번의 경우,프로젝트를 위한 모든 의존성 및 설정이 완료되어 있어 바로 시작할 수 있다.2번의 경우,프로젝트를 위한 모든 의존성 및 설정을 직접 지정해야한다.spring initializr 사용해 프로젝트 생성하기spring initializr에 접속해 프로젝트를 설정한다.각 항목에 대한 내용은 아래와 같다.Project : 프로젝트에 사용될 Build Tools 선택Language : 프로젝트에 사용될 Main languageSpring Boot : Spring Boot의 Version을 지정괄호가 있는 version의 경우, 베타버젼이므로 안정적인 프로젝트를 위해 소괄호 없는 버전 선택을 권장Project Metadata : 프로젝트의 메타데이터를 지정Group : 그룹명, 일반적으로 도메인 작성Artifact : 애플리케이션 이름Name : 프로젝트 이름, 별도의 지정이 없는 경우 artifact명을 따름Description : 프로젝트에 대한 설명Package Name : 패키지명, Group과 Artifact의 조합으로 작성됨Packaging : 패키징 방식 지정Java : JDK VersionDependencies : 프로젝트에서 사용할 Library, Framework 등 의존성 설정Library vs FrameworkLibrary : 프로그래머가 미리 만들어져 있는 기능을 가져와 사용Framework : 프레임워크가 프로그래머의 코드를 가져가 사용Server Programming 기본 개념 : Server, Network, HTTP,  URL,  APIServer요청에 대한 응답을 처리하는 컴퓨터 또는 프로그램Network네트워크란,노드 간 연결로 형성된 디지털 전기통신망이다.각 노드는 상호연결을 통해 리소스를 공유할 수 있다.LAN 부터 Internet Network까지 그 범위는 광범위하다.Internet인터넷이란,전세계 컴퓨터 네트워를 연결하는 광범위한 네트워크를 의미한다.각 디바이스는 각각 Client/Server로 구성되며 TCP/IP 기본 프로토콜을 제공한다.WebInternet을 기반으로 HTML 문서 기반의 리소스를 공유하는 기술, 인프라 그 자체광범위한 Network의 일종인 Internet을 기반으로 HTML Resource를 공유하는 기술 및 Infra 그 자체가 Web이다. IP (Internet Protocol)Internet에서사용되는 통신 규약IP AddressInternet에 연결된 Device를 식별하기 위해 부여되는 고유 주소Domain NameDNS(Domain Name System)에 의해 IP Address와 매핑되어 사용되는 이름으로,사람이 직접 IP 주소를 다루는 것은 불편하여 고안된 방법ping www.google.com으로 구글 ip 확인ex. google에 접속하기 위해 142.250.66.100으로 접속하는 대신 google.com으로 접속PortIP를 통해 인터넷에서 하나의 디바이스를 특정할 수 있었다면,Port를 통해 해당 디바이스의 특정 프로세스에 접근할 수 있게 된다.즉, Port는 일종의 네트워크상 프로세스의 고유 주소가 되는 셈이다.HTTP (HyperText Transfer Protocol)Web에서 사용하는 기본 통신 규약HTTP Method서버가 수행해야 할 action을 지정하는 방식으수행 목적에 따라 GET, POST, PUT, DELETE 등으로 구분된다.HTTP RequestHTTP Request FormatClient에서 Server로 보내는 HTTP 포맷첫째줄에 HTTP Method와 함께 Path 정보가 포함됨HTTP ResponseHTTP Response FormatServer에서 Client로 보내는 HTTP 포맷첫째줄에서 Status Code를 반환URL (Uniform Resource Locator)URL SampleWeb 상에 존재하는 Resource의 주소API (Application Programming Interface)프로그램간 통신하기 위한 규약정해진 약속에 따라 특정 기능을 수행@SpringBootApplication스프링 프로젝트를 실행시키기 위해 필요한 설정들을 모두 자동으로 처리GET API 개발 및 테스트@RestControllerController Class 등록을 위한 어노테이션@GetMapping(Path)GET Method에 대한 API 지정을 위한 어노테이션@RequestParamQuery 추출을 위한 어노테이션GET API 실습API : GET /addQuery로부터 두 정수를 추출하여 더한 값 반환과제 리뷰첫째날 과제는 어노테이션에 대한 학습이었다.소스코드에서 메타데이터를 제공할 수 있는 방법인 어노테이션은프레임워크에서 적극적으로 활용되기 때문에 어노테이션에 대한 기본적인 학습이 필요했다.이전까지 써본 어노테이션이라고는 @Override, @FunctionalInterface 정도였지만이번 과제를 통해 어노테이션에 대한 기본적인 내용을 정리할 수 있었다.Annotation 기본 지식소스코드에 메타데이터를 직접 추가하기 위해 고안된 방법으로JDK 5부터 지원한다.주석과 같이 로직 자체에 영향을 주진 않지만 코드의 연결 방법, 구조를 변경하므로실행 흐름을 변경할 수 있다.컴파일 전처리 대상인 주석과 다르게,런타임 시점에 사용될 정보를 포함할 수 있다.클래스, 메서드, 변수 등에 추가할 수 있다.어노테이션의 종류로는,기본 제공되는 Built-In 어노테이션,직접 만드는 사용자 정의 어노테이션,그리고 사용자 정의 어노테이션을 만들 때 필요한 메타 어노테이션 등이 있다.어노테이션은 오직 자신이 유효한 프레임워크에서만 동작한다는 특징을 가진다.ex. @SpringBootApplication은 Spring framework에서 동작하며 실행에 필요한 설정들을 처리한다.짧은 회고다음 스텝으로 넘아가는 것에 두려움을 가졌던 내 학습 스타일이 깨져가고 변해가는 귀한 시간이었다.본격적인 스프링 프레임워크 학습에 앞서 필요한 지식들을 학습할 수 있었다.그동안 대충 알고 있었던 용어들에 대해 정리하니 개운해졌다고나 할까.특히 그동안 괜히 어려울 것만 같았던 스프링 프로젝트를 직접 실습해보며"생각보다 할만한데?"라는 느낌을 받았다.왜 겁을 먹었던 걸까,이렇게 즐겁기만 한데!자,시작이 반이라고 했던가.정말 필요한 기본 지식들은 모두 끝났다.본격적인 스프링 프레임워크의 학습에 뛰어들어보자!Day 02 : 첫 HTTP API 개발두번째 날,POST API 실습을 진행했다.POST API 개발 및 테스트조회를 위해 사용했던 GET API와 다르게,POST API는 Server에 데이터 생성을 요청한다.생성을 위해 필요한 데이터는 기본적으로 Request Body의 형태로 전달한다.@PostMapping(Path)POST API 지정을 위한 어노테이션@RequestBodyRequest Body를 DTO로 받기 위해 사용하는 어노테이션DTO의 field와 이름이 같은 경우,자동으로 매핑되어 처리POST API 실습POST /multiply전달된 Request Body의 두 Integer 객체로부터 곱을 구하여 전달유저 생성 API 개발 및 테스트이어지는 API 실습에서는,User DTO를 활용하여User를 생성하는 POST API를 만들고전체 User를 조회하는 GET API를 만든다Controller에서 사용하기 위해 동일한 객체에 대해 다양한 DTO를 설계하였다.Request Body로 받아들이기 위한 DTO실제 서버에서 사용할 UserResponse로 사용할 DTO이를 통해 각 객체의 역할을 구분할 수 있었고,용도에 맞춰 사용해 개발하기 한결 수월했다.과제 리뷰둘째날 과제는 주어지는 API Specification에 따른 API 개발이었다.그 중,Query에 날짜를 전달하여 요일을 전달받는 GET API 문제가 가장 재밌었다.특정 날짜에 대해 요일을 영어로 출력하되,이 때 마지막의 "DAY"는 제외하고 반환해야한다.Response DTO를 설계하여문제에서 주어진 JSON 포맷으로 반환하는 것 또한 공부가 되었다.짠-짧은 회고API 실습을 통해Client와 Server가 통신하는 원리를 배울 수 있었다.뿐만 아니라,API 명세에 따라 구현을 하다보니정말 서버 개발자로써 일을 하고 있는 것 같은 기분이 들어 즐거웠다.과제 중 list 형태의 Request Body로부터 합을 계산하여 반환하는 문제가 있었는데,해당 문제에는 Stream API를 사용하니뭐랄까... "은근 Java 좀 치는데?"같은 감상도 들었다.배웠던 내용이 자연스레 떠오르고 코드로 작성되는 순간의 희열은 이루 말할 수 없는 것 같다.아,아직 API 요청에 대해 DB를 연동하지 않았기 때문에Server 메모리 상에서만 데이터를 다루고 있다.얼른 DB를 배워 연동해서 실제 살아있는 서버를 만들고 싶다.Day 03 : 기본적인 DB 사용법DB 활용에 앞서 DB에 대한 기초 및 연결을 학습하는 시간이었다.Database저장 원리기본적으로 컴퓨터의 모든 리소스는 Disk와 같은 저장장치에 반영구적으로 보존된다.프로그램을 실행하게 되면 디스크로부터 프로그램을 RAM에 올려 CPU로 계산을 한다.그렇다면, 클라이언트로부터 데이터를 받은 서버 컴퓨터에서는 해당 데이터를 보존하기 위해 어떻게 해야할까?당연히 서버 컴퓨터에 저장해야한다.RAM과 같이 휘발성이 없는 장치에다가.물론, 서버 컴퓨터에 파일 형태로도 보존할 수 있다.그렇지만 대용량 데이터에 대해 효율적인 연산을 지원하는 DB의 사용이 일반적이고 정석이다.따라서 서버 개발자라면,DB에 대한 지식이 필요하다.DatabaseDB는 대용량 데이터에 대해 효율적인 연산을 제공하는 가상의 저장장치 및 프로그램이다.구조화 방식에 따라 RDB, NoSQL 등이 있으며각각의 목적에 따라 사용된다.프로그래머는 DBMS(Database Management System)을 통해 DB를 관리하는데,여기에는 MySQL, PostgreSQL, MongoDB 등 다양한 제품이 있다.이 때,DBMS에서 DB와 통신하기 위해 사용되는 언어를 SQL(Structured Query Language)라고 한다.Spring에서 DB 연동하기application.ymlSpring framework가 DB에 접근하기 위한 설정 등록한다./resource에서 관리하며 이미 application.properties가 있는 경우 확장자를 변경한다.dependencyapplication.yml에서 mysql을 위한 Driver를 지정하였는데,이를 위해 의존성에 추가한다.IntelliJ에서 DB연동IntelliJ Ultimate를 사용하는 경우,IDEA와 DB를 연결하여 DBMS로 활용할 수 있다.해당 서비스 이용이 어려운 경우,MySQL Client 또는 DBeaver와 같은 프로그램을 사용하면된다.intelliJ에서 MySQL 연결JdbcTemplate를 사용한 간단한 DB 연동 프로그래밍DB를 연결했으니 직접 사용해본다.JdbcTemplate 필드에 대한 의존성 주입서버 코드에서 DB와 연동하기 위한 API로 JdbcTemplate를 사용한다.API 코드 수정이 때 주의해야 할 점으로,jdbcTemplate 필드로 SELECT문을 사용해 반환받은 결과는 List다.또한,RowMapper 구현을 통해List를 생성하기 전 Table의 각 row에 대해 필요한 정보를 지정하여 임의의 객체를 만들어야 한다.과제 리뷰이번 과제는 람다식에 대한 내용이다.함수형 인터페이스에 대해 익명 클래스를 기반으로 동작하는 람다식은 JDK 8부터 추가되었다.생산성 및 가독성을 올려주며,함수형 프로그래밍을 구현할 수 있게 된다.이미 Java 문법에서도 배웠던 내용이라다시 한번 점검할 수 있었다.짧은 회고살아있는 서버를 만드는 일은 정말 즐거웠다.점점 실제 서비스를 만들 수 있는 재료들을 배워가고 있다는 생각에,빨리 이 과정을 졸업하고 프로젝트에 뛰어들고 싶어 근질근질하다.이전에 SQLD를 준비하며 배웠던 SQL이 기억나조금 더 수월하게 따라갈 수 있었다.역시 배운 건 어디 안간다.간단한 CRUD 정도야 바로 사용할 수 있었지만,복잡한 쿼리문을 설계하고 이를 스프링에서도 사용하기 위해DB, SQL을 깊게 파봐야할 것 같다.Day 04 : DB를 사용해 만드는 API지난 시간과 이어지는 DB연동으로,UPDATE, DELETE API를 작성했다.PUT API로 UPDATE 기능 구현, DELETE  API로 DELETE 기능 구현각 API에 대해 예외처리한 코드다.과제 리뷰계속해서 이어지는 API 실습이다.서버 개발자는 결국 Client 요청을 처리하기 위한 API를 개발하는 일을 하는만큼,API 연습만이 살 길이다!과제 중,로직도 복잡하고 DB 테이블을 확장해야 했던 3번이 가장 재미있었지만...이유를 몰라 헤맸던 문제 2번을 해결한 경험을 나누고자 한다.RequestBody DTO에 기본 생성자가 정의되지 않은 경우처음 작성한 코드에는 기본 생성자를 작성하지 않았다.단순히 @RequestBody에 의해 오버라이드한 생성자가 호출되는 줄 알고 아무런 문제를 느끼지 못했다.이상없다고 단정지은 코드...그러나 INSERT 되지 않았다.Status code는 400을 반환 받았고 요청 자체가 잘못되었음을 알 수 있었다.무엇이 문제일까?이를 이해하기 위해서는 @RequestBody의 동작을 이해해야한다.@RequestBody의 동작@RequestBody는 요청으로 넘어온 객체를 지정한 DTO에 매핑시켜 반환한다.이 때,Spring은 Reflection을 사용하는데DTO 클래스에 기본 생성자가 없는 경우 변환하는 과정에서 문제를 일으킬 수 있다.따라서,DTO 클래스를 생성할 때는 반드시 기본 생성자를 작성한다.편-안짧은 회고많은 API 연습을 통해Client와 Server 사이에서 이루어지는 동작에 대해 보다 이해할 수 있었고,무엇보다 API 작성에 자신감을 갖게 되었다.가장 기본이자, 가장 중요한 CRUD API에 대해 모두 학습하였다.API 디자인은 더 많은 연습이 필요하겠지만,API 명세를 이해하고 이를 바탕으로 실제 구현하는 일은 곧 내가 현업에서 밥 먹듯이 하게 될 일이다.기본기가 중요한만큼,더욱 집중해서 학습하고 연마하자!Day 05 : 클린코드의 개념과 첫 리팩토링1주차 마지막 날이다.단순 구현에서 벗어나 좋은 코드에 대한 고민을 시작하게됐다.Clean Code개발자를 준비하면서 심심찮게 들어본 단어 중 하나가 바로 '클린코드'다.실제 개발자는 코드를 작성하는 시간보다 읽는 시간이 더 많다고 한다.어느 한 사람만 이해하고 시간이 지나면 아무도 이해하지 못하는 코드는 결코 좋은 코드라고 말할 수 없을 것이다.코드란 요구사항에 대한 실제 구현이며,좋은 코드란 읽기 좋은 코드를 의미한다.즉,클린코드로 작성하여 가독성을 높여 최종적으로는 생산성을 높이는 것이 가장 중요한 목적이다.Layered Architecture이전의 코드는 모두 하나의 Controller에서 작성되었다.즉, Controller에서 작성된 하나의 메서드가API 진입점으로 사용되고로직을 수행하며DB와 통신을 한다더 좋은 코드를 위해,더 좋은 구조를 위해,역할에 따라 클래스를 구분하고이를 기반으로 통신하는 Layered Architecure를 적용한다.ControllerAPI의 진입점으로 사용되는 클래스다.API 진입점으로 Service와 통신Service비즈니스 로직을 작성하는 클래스다.Controller, Repository와 통신RepositoryDB와 통신하는 클래스다.Service, Database와 통신과제 리뷰좋은 코드를 위한 고민은 멈추지 말아야한다.작성하는 입장보다 읽는 입장을 고려하며 작성하는 것이 좋은 자세일 것이다.그리고 이러한 고민은 아주 오래 전 부터 수많은 개발자에 의해 이뤄져왔다.어느정도 일반적인 클린코드에 대한 가이드가 생겨났다.<Clean Code>라는 책이 좋은 참고가 될 것이며,이론적으로 아는 것 보다 실제 작성하고 읽어보며 체득하는 것이 더욱 유익할 것 같다.짧은 회고처음으로 내가 작성한 코드를 바라보게 되었다."내가 작성한 코드는 좋은 코드인가?"라는 고민을 멈추지 말아야겠다.좋은 습관이 벨 수 있도록,고민하고 작성하자!두번째 Online Session : Live Q&A두번째 온라인 미팅이 진행되었다.이번 세션은 QnA 위주로 진행되었고 가장 도움되었던 내용을 기록해본다.Q. 포트폴리오 주제지원하는 회사에서 하고 있는 프로덕트가 최고다.가장 가고 싶은 회사 한 곳을 선정하여 관련 서비스를 만들어보자.실제 서비스되고 있는 기능을 분석하고 구현하면서 자신의 사용 경험을 기반으로 새로운 기능도 추가해보자.분명 좋은 평가를 받을 것이다.Q. 신입 개발자 역량회사의 사정과 규모에 따라 나뉘겠지만 멘토님이 제시해주신 방향은 아래와 같다.개발자 시작 가능한 수준기본적인 Java 이해 : Java 기본서 90% 이해 및 기본적인 구현 능력기본적인 CRUD 및 Spring 기본최소한의 배포취업 99%의 능력Java 심화추천 도서 : <이펙티브 자바>, <모던 자바 인 액션>, <자바 성능 최적화>Spring 심화 : 통계, 엑셀, 메일을 Spring으로 구현할 수 있어야 함기술에 대한 고민을 할 수 있을 정도의 이해무중단 배포, 서버 확장 전략이번 스터디를 통해 내 수준이 어디까지 올라갈지는 모르겠으나,폭.풍.성.장 하자!1주차 후기이렇게까지 많이 배운 한 주가 있었나 싶을 정도로많이 배웠고, 연습했고, 성장했다.한편으로,이전부터 이렇게 학습했다면 진작 취업하지 않았을까? 라는 아쉬움이 사무쳤다.배운 내용을 완벽히 이해해야만 다음 단계로 넘어갈 수 있었고무엇을 학습하면 좋을지 몰라 닥치는대로 학습했고정작 중요한 서버 지식과 스프링을 배우기 위해서 무엇을 하면 좋을지 몰라지레 겁을 먹었던 지난 날들이었다.이제라도,어떻게 성장해야하는 지 알아가고 있음에 감사하자.제대로 성장하는 방법을 알아가고 있음에 위로를 얻자.앞으로의 성장이 기대되기 시작한 1주차였다.

백엔드워밍업클럽스터디백엔드Java/Spring최태현멘토님

홍승찬

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

참가계기국비학원에서 기초를 다졌지만 이제까지 MyBatis만을 사용한 프로젝트를 진행했었다. 때문에 요즘 기업에서 많이 요구하는 JPA를 공부해야겠다는 생각으로 강의를 결제했지만, 혼자서 게시판을 만들어보는 개인프로젝트를 진행하면서 차일피일 미뤘었다.그런데 마침 인프런 워밍업 클럽 스터디가 시작한다는 것을 알게 되었고, 개인 프로젝트도 어느 정도 기능 구현이 완료된 상태였기에 JPA 기초를 공부하면서 기존 프로젝트를 JPA로 마이그레이션 하는 것이 좋은 경험이 될 것 같아서 워밍업 클럽 스터디에 참여하게 됐다.배운 것1주차는 IDE설치부터 기초적인 개념을 다시 공부하는 시간을 가졌다.1 .인텔리제이와 MySql이제까지 이클립스와 오라클을 사용했지만 강의에서는 인텔리제이와 mySql을 사용해서 두 개를 써보고 있다. 그런데 확실히 인텔리제이가 이클립스 보다 더 안정적으로 느껴져서 앞으로는 인텔리제이를 쭉 사용할거 같다.(사실 SSD 교체해서 이클립스 설치는 귀찮았다.)DB는 오라클 GUI를 사용했었는데, MySql CLI를 사용하려니 살짝 어려운 감이 있었다. 다만 아직 테이블을 설정하고 만들 일이 많이 없기 때문에 크게 힘들지는 않았다. 나중에 개인프로젝트 할 때는 MySql워크벤치? 사용해서 만들 것 같다.2. API알고 있는 내용들을 복습하고 잊고 있었던 부분들을 상기시킬 수 있는 좋은 기회였다.3. 리팩토링국비교육에서는 Controller, Service, Repository를 나눠야 하는 이유를 알려주지 않고 3개가 각자 어떤 책임과 역할이 있는지 알려주지 않았었다. 그래서 국비에서 만든 프로젝트를 보면 컨트롤러에서 많은 역할을 수행하고 서비스단에서는 리포지토리로 넘겨주는 역할 밖에 없었다. 다행히 친구의 피드백으로 인해 왜 3개가 나뉘어야하고, 각자의 책임이 뭔지 알게 됐었는데, 강의에서 그런 부분을 하나하나 짚고 넘어가면서 혼자 공부했던 내용들을 다시 짚고 넘어갈 수 있었다.느낀점위에서 말했던 것처럼 국비교육은 생략해서 혼자 공부하면서 알게 됐던 내용들이 멘토님의 강의에 찰떡 같은 비유와 함께 있는 것을 보면서 국비교육 말고 혼자서 강의로 공부했다면 더 많이 배웠을까 라는 생각이 들었다.개인사유로 인해 금요일에 있었던 백엔드 1차 중간점검에 참여하지 못해서 너무 아쉬웠다. 다음에 있는 중간점검은 꼭 참여해서 멘토님의 이야기를 들으면서 식견을 넓혀야겠다.   

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

[인프런 워밍업 클럽 스터디] 13일차 - Spring Boot 설정, 버전업 이해하기

build.gradle빌드 스크립트라고도 불리며, gradle을 이용해 프로젝트를 빌드하고 의존성을 관리하기 위해 작성되었다.groovy 언어를 사용해 작성되었고, Kotlin이라는 언어를 사용할 수도 있다. org.springframework.boot 플러그인 역할스프링을 빌드했을 때 실행가능한 jar 파일이 나오게 도와주고스프링 애플리케이션을 실행할 수 있게 도와주고또 다른 플러그인들이 잘 적용될 수 있게 해준다. Spring 과 Spring Boot 의 차이점1. 간편한 설정2. 간단한 의존성 관리3. 강력한 확장성MSA에 적합한 모니터링  Lombokgetter, setter, 생성자와 같은 반복되는 보일러 플레이트 코드(boiler plate code)를 제거할 수 있다.lombok 의존성 추가IntelliJ lombok 플러그인 추가IntelliJ Annotation Processor 설정   Spring Boot 2.7.x 에서 3.0.x 로 업데이트 하기Java 최소 버전이 17로 업그레이드 되었다.많은 스프링 프로젝트, Thrid-party Library 가 버전업 되었다.AOT 기초 작업이 이루어졌다. AOT(Ahead of Time) 빌드를 할 때 스프링 애플리케이션을 분석하고 최적화하는 도구애플리케이션 시작 시간과 메모리 사용량을 줄일 수 있게 해준다.javax 대신 jakarta 패키지를 사용하게 된다.모니터링 기능들의 강화외의 다양한 세부적인 변경사항이 많음   

백엔드워밍업클럽스터디백엔드자바스프링부트

[인프런 워밍업 클럽 스터디] 12일차 - AWS와 EC2 배포

Section 7. 생애 최초 배포하기[목표]EC2에 접속하는 방법을 알아보고, EC2에 접속해 리눅스 명령어를 다뤄본다.개발한 서버의 배포를 위해 환경 셋팅을 리눅스에서 진행하고, 실제 배포를 진행한다.foreground와 background의 차이를 이해하고 background 서버를 제어한다.도메인 이름을 사용해 사용자가 IP 대신 이름으로 접속할 수 있도록 한다.[리눅스 기본 명령어]mkdir : 폴더를 만드는 명령어ls : 현재 위치에서 폴더나 파일을 확인하는 명령어ls -l : 조금 더 자세한 정보를 확인할 수 있다.cd : 폴더 안으로 들어가는 명령어pwd : 현재 위치를 확인하는 명령어cd .. : 상위 폴더로 올라가는 명령어rmdir : 비어있는 폴더(디렉토리)를 제거하는 명령어 sudo yum update : 관리자의 권한으로 설치되어 있는 여러 프로그램을 최신화한다.sudo yum install [프로그램이름] : 관리자의 권한으로 프로그램을 설치한다.sudo systemctl status [프로그램이름] : 프로그램의 상태를 확인한다.suto systemctl restart [프로그램이름] : 프로그램을 재시작한다.chmod : 파일이나 폴더의 권한을 변경한다.ctrl + c : foreground로 실행중인 프로그램을 중단하는 신호nohup [명령어] & : [명령어]를 background에서 동작하게 만드는 명령어rm : 파일을 제거하는 명령어 ps aux : 현재 실행중인 프로그램 목록을 확인할 수 있다. kill -9 [프로그램번호] : 해당 프로그램을 종료시킨다. vi : 리눅스 편집기인 vim을 사용하여 파일을 연다.cat : 파일에 있는 내용물을 모두 출력하는 명령어 tail : 현재 파일의 끝 부분을 출력하는 명령어 tail -f : 현재 파일의 끝 부분을 실시간으로 출력해준다.      

백엔드워밍업클럽스터디백엔드자바스프링부트

[인프런 워밍업 클럽 스터디] 10일차 - 객체지향과 JPA 연관관계

[1 : 1 관계][연관관계의 주인]Table을 보았을 때 누가 관계의 주도권을 가지고 있는가연관관계의 주인이 아닌 쪽에 mappedBy 옵션을 달아 주어야 한다.연관관계의 주인의 값이 설정되어야만 진정한 데이터가 저장된다.객체가 연결되는 기준이 된다. [연관관계의 주인 효과]상대 테이블을 참조하고 있으면 연관관계의 주인연관관계의 주인이 아니면 mappedBy를 사용연관관계의 주인의 setter가 사용되어야만 테이블 연결 [N : 1 관계] - @ManyToOne 과 @OneTOMany@JoinColumn연관관계의 주인이 활용할 수 있는 어노테이션.필드의 이름이나 null 여부, 유일성 여부, 업데이트 여부 등을 지정 [N : M 관계] - @ManyToMany구조가 봅잡하고, 테이블이 직관적으로 매핑되지 않아 사용하지 않는 것을 추천 cascade 옵션 : 한 객체가 저장되거나 삭제될 때, 그 변경이 폭포처럼 흘러 연결되어 있는 객체도 함께 저장되거나 삭제되는 기능orphanRemoval 옵션: 객체간의 관계가 끊어진 데이터를 자동으로 제거하는 옵션  [연관관계 정리]상대 테이블을 가리키는 테이블이 연관관계의 주인이다. 연관관계의 주인이 아닌 객체는 mappedBy를 통해 주인에게 매여 있음을 표히새 주어야 한다.양쪽 모두 연관관계를 갖고 있을 때는 양쪽 모두 한 번에 맺어주는게 좋다.cascade 옵션을 활용하면, 저장이나 삭제를 할 때 연관관계에 놓인 테이블까지 함께 저장 또는 삭제가 이루어진다.orphanRemoval 옵션을 활용하면, 연관관계가 끊어진 데이터를 자동으로 제거해준다.  [연관관계를 사용하면 무엇이 좋을까?]각자의 역할에 집중하게 된다.(응집성)새로운 개발자가 코드를 읽을 때 이해하기 쉬워진다.테스트 코드 작성이 쉬워진다.[연관관계를 사용하는 것이 항상 좋을까?]지나치게 사용하면, 성능상의 문제가 생길 수도 있고 도메인 간의 복잡한 연결로 인해 시스템을 파악하기 어려워질 수 있다.또한 너무 얽혀 있으면, A를 수정했을 때 B, C, D 까지 영향을 받을 수 있다.그렇기 때문에 비즈니스 요구사항, 기술적인 요구사항, 도메인 아키텍처 등 여러 부분을 고민해서 연관관계 사용을 선택해야 한다.  Section 5. 정리책 생성, 대출, 반납 API를 온전히 개발하며 지금까지 다루었던 모든 개념을 실습해본다.객체지향적으로 설계하기 위한 연관관계를 이해하고, 연관관계의 다양한 옵션에 대해 이해한다.JPA에서 연관관계를 매핑하는 방법을 이해하고, 연관관계를 사용해 개발할 때와 사용하지 않고 개발할 때의 차이점을 이해한다.   

백엔드워밍업클럽스터디백엔드자바스프링부트

[인프런 워밍업 클럽 스터디] 7일차 - Spring Data JPA를 사용한 데이터베이스

Section 4. 생애 최초 JPA 사용하기[목표]문자열 SQL을 직접 사용하는 것의 한계를 이해하고, 해결책인 JPA, Hibernate, Spring Data JPA가 무엇인지 이해한다.Spring Data JPA를 이용해 데이터를 생성, 조회, 수정, 삭제할 수 있다.트랜잭션이 왜 필요한지 이해하고, 스프링에서 트랜잭션을 제어하는 방법을 익힌다.영속성 컨텍스트와 트랜잭션의 관계를 이해하고, 영속성 컨텍스트의 특징을 알아본다.[SQL을 직접 작성하면 아쉬운 점]문자열을 작성하기 때문에 실수할 수 있고, 실수를 인지하는 시점이 느리다.특정 데이터베이스에 종속적이게 된다.반복 작업이 많아진다. 테이블을 하나 만들 때 마다 CRUD 쿼리가 항상 필요하다.데이터베이스의 테이블과 객체는 패러다임이 다르다.===> 그렇기 때문에 등장한 것이 JPA(Java Persistence API) [JPA란?]객체와 관계형 DB의 테이블을 짝지어 데이터를 영구적으로 저장할 수 있도록 정해진 Java 진영의 규칙이것을 코드로 구현한 것이 Hibernate. Hibernate는 JDBC를 내부적으로 사용한다. [JPA 어노테이션]@Entity : 스프링이 User 객체와 user 테이블을 같은 것으로 바라본다.  기본생성자 꼭 필요함.@Id : 이 필드를 primary key로 간주한다.@GeneratedValue : primary key는 자동 생성되는 값이다.@Column : 객체의 필드와 Table의 필드를 매핑한다. 이름이 같을 시 생략 가능. [spring.jpa.hibernate.ddl-auto]create: 기존 테이블이 있다면 삭제 후 다시 생성create-drop: 스프링이 종료될 때 테이블을 모두 제거update: 객체와 테이블이 다른 부분만 변경validate: 객체와 테이블이 동일한지 확인none: 별다른 조치를 하지 않는다 [지금까지 사용한 JPA Repository 기능]save: 주어지는 객체를 저장하거나 업데이트 시켜준다.findAll: 주어지는 객체가 매핑된 테이블의 모든 데이터를 가져온다.findById: id를 기준으로 특정한 1개의 데이터를 가져온다. [Spring Data JPA]복잡한 JPA 코드를 스프링과 함께 쉽게 사용할 수 있도록 도와주는 라이브러리 [JPA Repository에서 By 앞에 들어갈 수 있는 구절 정리]find: 1건을 가져온다. 반환 타입은 객체가 될 수도 있고, Optional<타입>이 될 수도 있다.findAll: 쿼리의 결과물이 N개인 경우 사용. List<타입> 반환.exists: 쿼리 결과가 존재하는지 확인. 반환 타입은 boolean.count: SQL의 결과 개수를 센다. 반환 타입은 long. [JPA Repository에서 By 뒤에 들어갈 수 있는 구절 정리]GraterThan: 초과GraterThanEqual: 이상LessThan: 미만LessThanEqual: 이하Between: 사이에StartsWith: ~로 시작하는EndsWith: ~로 끝나는  [과제]진도표 7일차와 연결됩니다우리는 JPA라는 개념을 배우고 유저 테이블에 JPA를 적용해 보았습니다. 몇 가지 문제를 통해 JPA를 연습해 봅시다! 🔥 

백엔드워밍업클럽스터디백엔드자바스프링부트

[인프런 워밍업 클럽 스터디] 6일차 - 스프링 컨테이너의 의미와 사용 방법

[정리] Section 3. 역할의 분리와 스프링 컨테이너좋은 코드가 왜 중요한지 이해하고, 원래 있던 Controller 코드를 보다 좋은 코드로 리팩토링 한다.스프링 컨테이너와 스프링 빈이 무엇인지 이해한다.스프링 컨테이너가 왜 필요한지, 좋은 코드와 어떻게 연관이 있는지 이해한다.스프링 빈을 다루는 여러 방법을 이해한다.  클래스 : 객체를 정의해놓은 설계도. 객체를 생성하기 위해 사용된다.객체 : 클래스에 정의된 내용이 인스턴스화되어 실제로 생성된 것. 설계도를 통해 만들어진 집.인스턴스(화) : 클래스를 실제로 사용할 수 있도록 생성하는 것. 스프링 빈 (UserController에 @RestController를 붙여줌으로써 스프링 빈이 됨)서버가 시작되면 스프링 서버 내부에 거대한 컨테이너(클래스 저장소)를 만든다.컨테이너 안에는 클래스가 들어간다.이 때 다양한 정보도 함께 들어있고, 인스턴스화도 이루어진다.이때 스프링 컨테이너 안으로 들어간 클래스를 스프링 빈이라고 한다.JdbcTemplate도 스프링 빈으로 등록되어 있다. (Dependency가 등록해 주고 있음)스프링 컨테이너는 필요한 클래스를 연결해준다.  서버가 시작되면 일어나는 일스프링 컨테이너(클래스 저장소)가 시작된다.기본적으로 많은 스프링 빈들이 등록된다.우리가 설정해 준 스프링 빈이 등록된다.이 때 필요한 의존성이 자동으로 설정된다. 스프링 빈을 등록하는 방법@Configuration클래스에 붙이는 어노테이션@Bean을 사용할 때 함께 사용해야 한다.  @Bean메소드에 붙이는 어노테이션메소드에서 반환되는 객체를 스프링 빈에 등록한다. @Service - @Repository 사용할 때 개발자가 직접 만든 클래스를 스프링 빈으로 등록할 때  @Configuration - @Bean 사용할 때외부 라이브러리, 프레임워크에서 만든 클래스를 등록할 때알아볼 어노테이션@Component주어진 클래스를 '컴포넌트'로 간주한다. 이 클래스들은 스프링 서버가 뜰 때 자동으로 감지된다.@Qualifier스프링 빈에 이름을 지정함으로써 특정 클래스를 가져옴 스프링 빈을 가져오는 방법(가장 권장) 생성자를 이용해 주입받는 방식 : @Autowired 생략 가능setter와 @Autowired 사용 : 누군가 setter를 사용하면 오작동 할 수 있다.필드에 직접 @Autowired 사용 : 테스트를 어렵게 만드는 요인이다.   참고자료 : https://mihee0703.tistory.com/182 

백엔드워밍업클럽스터디백엔드자바스프링부트

[인프런 워밍업 클럽 스터디] 4일차 - 데이터베이스를 사용해 만드는 API

 [이론 정리]생애 최초 database 조작하기디스크와 메모리 차이를 이해하고, Database의 필요성을 이해한다.SQL을 이용해 MySQL Database를 조작할 수 있다.스프링 서버를 이용해 Database에 접근하고 데이터를 저장, 조회, 업데이트, 삭제할 수 있다.API의 예외 상황을 알아보고 예외를 처리할 수 있다.  [과제]문제 1우리는 작은 과일 가게를 운영하고 있습니다. 과일 가게에 입고된 "과일 정보"를 저장하는 API를 만들어 봅시다. 스펙은 다음과 같습니다.HTTP method : POSTHTTP path : /api/v1/fruitHTTP 요청 Body { "name" : String, "warehousingDate" : LocalDate, "price" : long }HTTP 요청 Body 예시 { "name" : "사과", "warehousingDate" : "2024-02-01", "price" : 5000 }응답 : 성공시 200 💡한 걸음 더!자바에서 정수를 다루는 가장 대표적인 두 가지 방법은 int와 long입니다.이 두 가지 방법 중 위 API에서 long을 사용한 이유는 무엇일까요?  문제 2과일이 팔리게 되면, 우리 시스템에 팔린 과일 정보를 기록해야 합니다. 스펙은 다음과 같습니다.HTTP method : PUTHTTP path : /api/v1/fruitHTTP 요청 Body{ "id" : long }HTTP 요청 Body 예시 { "id" : 3 }응답 : 성공시 200  문제 3우리는 특정 과일을 기준으로 팔린 금액, 팔리지 않은 금액을 조회하고 싶습니다.예를 들어(1, 사과, 3000원, 판매O)(2, 사과, 4000원, 판매X)(3, 사과, 3000원, 판매O)와 같은 세 데이터가 있다면 우리의 API는 판매된 금액 : 6000원, 판매되지 않은 금액 : 4000원 이라고 응답해야 합니다.구체적인 스펙은 다음과 같습니다.HTTP method : GETHTTP path : /api/v1/fruit/statHTTP query- name : 과일 이름예시 GET /api/v1/fruit/stat?name=사과HTTP 응답 Body{ "salesAmount" : long, "notSalesAmount" : long }HTTP 응답 Body 예시 { "salesAmount" : 6000, "notSalesAmount" : 4000 }💡한 걸음 더!(문제 3번을 모두 푸셨다면) SQL의 sum, group by 키워드를 검색해 적용해보세요.   

백엔드워밍업클럽스터디백엔드자바스프링부트

[인프런 워밍업 클럽 스터디] 3일차 - 기본적인 데이터베이스 사용법

Section 2. 생애 최초 Database 조작하기[목표]디스크와 메모리의 차이를 이해하고, Database의 필요성을 이해한다.MySQL Database를 SQL과 함께 조작할 수 있다.스프링 서버를 이용해 Database에 접근하고 데이터를 저장, 조회, 업데이트, 삭제할 수 있다.API의 예외 상황을 알아보고 예외를 처리할 수 있다.  과제[키워드]익명 클래스 / 람다 / 함수형 프로그래밍 / @FunctionalInterface / 스트림 API / 메소드 레퍼런스 [질문]자바의 람다식은 왜 등장했을까? 람다식이 등장하게 된 이유는 불필요한 코드를 줄이고, 가독성을 높이기 위함이다. 그렇기 때문에 함수형 인터페이스의 인스턴스를 생성하여 함수를 변수처럼 선언하는 람다식에서는 메소드의 이름이 불필요하다고 여겨져서 이를 사용하지 않는다. 대신 컴파일러가 문맥을 살펴 타입을 추론하게 된다. 또한 람다식으로 선언된 함수는 1급 객체이기 때문에 Stream API의 매개변수로 전달이 가능해진다. 람다식과 익명 클래스는 어떤 관계가 있을까? -> 람다식의 문법은 어떻게 될까? 람다식(Lambda Expression) 이란 함수를 하나의 식(expression)으로 표현한 것이다. 함수를 람다식으로 표현하면 메소드의 이름이 필요 없기 때문에, 람다식은 익명 함수(Anonymous Function)의 한 종류라고 볼 수 있다.익명함수(Anonymous Function)란 함수의 이름이 없는 함수로, 익명함수들은 모두 일급 객체이다. 일급 객체인 함수는 변수처럼 사용 가능하며 매개 변수로 전달이 가능하다는 등의 특징을 가지고 있다.//람다 방식 (매개변수, ... ) -> { 실행문 ... } //예시 () -> "Hello World!"; 출처 : https://bny9164.tistory.com/79참고 : https://dwaejinho.tistory.com/entry/Java-Lambda-Stream-%EB%8F%84%EC%9E%85-%EB%B0%B0%EA%B2%BD%EA%B3%BC-%EC%9B%90%EB%A6%AC-%ED%8C%8C%ED%95%B4%EC%B9%98%EA%B8%B0#1.1%20%EB%9E%8C%EB%8B%A4%20%EB%8F%84%EC%9E%85%20%EB%B0%B0%EA%B2%BD-1

백엔드워밍업클럽스터디백엔드자바스프링부트

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

1주차 진행 순서 [사전 오리엔테이션]진행방식, 중요사항 등 공지와 함께 코치님 소개 [1일차]서버 개발을 위한 환경 설정 및 네트워크 기초 + 미션 [2일차]첫 HTTP API 개발 + 미션 [3일차]기본적인 데이터베이스 사용법 + 미션 [4일차]데이터베이스를 사용해 만드는 API + 미션 [5일차]클린코드의 개념과 첫 리팩토링 + 미션중간 점검 라이브 - 질의응답  [1주차 회고] 느슨해지는 생활을 벗어나고자 외부 요인을 추가했다. 기본적으로는 자율 스터디지만 매일 권장 학습량이 있는 점, 공부 및 미션 수행 후 채널에 글을 제출해야 하는 점, 다른 사람들이 공부하는 방식을 알 수 있다는 점에서 워밍업 스터디는 훌륭한 자극제가 되었다. 하지만 기존 계획과 다르게 첫 주 동안 갑작스러운 일정들이 생겨 공부에 다소 소홀했다. 야심차게 시작한 것 치곤 결과가 미비하다. 다행인것은 그래도 시작한지 겨우 일주일이라는 것. 남은 날이 더 많은 만큼 힘을 낼 날도 많다. 그리고 만약 스터디를 시작하지 않았더라면 하염 없이 할 일을 미뤄 지금만큼의 결과도 얻지 못했으리란 점. 긍정적인 면만 생각하기로 했다. 오늘이 지나면 다시 한 주가 시작된다. 본격적인 스프링 학습에 들어가게 되고 소제목만 봐도 내용이 호락호락 하지 않다. 미래의 나에게 심심한 위로를 보내게 된다. 부디 집중해서 훌륭한 학습을 마치기를. 

백엔드워밍업클럽스터디발자국

[인프런 워밍업 클럽 스터디] 2일차 - 첫 HTTP API 개발

 [Section 1 정리]스프링 프로젝트를 시작하는 방법과 실행하는 방법네트워크, IP, 도메인, 포트, HTTP 요청과 응답 구조, 클라이언트-서버 구조, API와 같은 기반 지식Spring Boot를 이용해 GET API와 POST API를 만드는 방법 [과제]문제 1두 수를 입력하면, 다음과 같은 결과가 나오는 GET API를 만들어보자!path : /api/v1/calc쿼리 파라미터 : num1, num2 { "add" : 덧셈결과, "minus" : 뺄셈결과, "multiply" : 곱셈결과 } 예시GET /api/v1/calc?num1=10&num2=5{ "add" : 15, "minus" : 5, "multiply" : 50 } 문제 2날짜를 입력하면, 무슨 요일인지 알려주는 GET API를 만들어보자!path와 쿼리 파라미터는 임의로 만들어도 상관없다. 예시GET /api/v1/day-of-the-week?date=2023-01-01{ "dayOfTheWeek" : "MON" } 문제 3여러 수를 받아 총 합을 반환하는 POST API를 만들어보자!API에서 받는 Body는 다음과 같은 형태이다.(HINT : 요청을 받는 DTO에서 List를 갖고 있으면 JSON의 배열을 받을 수 있습니다.){ "numbers" : [1, 2, 3, 4, 5] }반환 결과15⚠주의반환결과는 JSON이 아닙니다.함수에서 String 혹은 Integer를 반환하면, API결과가 JSON으로 나가지 않고, 단순한 값으로 나가게 됩니다.POST MAN과 같은 API 테스트 툴을 이용해 한 번 확인해보세요.

백엔드워밍업클럽스터디백엔드자바스프링부트

[인프런 워밍업 클럽 스터디] 1일차 - 서버 개발을 위한 환경설정

 Section 1. 생애 최초 API 만들기[목표]스프링 프로젝트를 설정해 시작하고 실행할 수 있다.서버란 무엇인지, 네트워크와 HTTP, API는 무엇인지, JSON은 무엇인지 등 서버 개발에 필요한 다양한 개념을 이해한다.스프링 부트를 이용해 간단한 GET API, POST API를 만들 수 있다. [이론 총정리](웹을 통한)컴퓨터 간의 통신은 HTTP라는 표준화된 방식이 있다.HTTP 요청은 HTTP Method (GET, POST)와 Path (/portion)가 핵심이다.요청에서 데이터를 전달하기 위한 2가지 방법은 쿼리와 바디이다.HTTP 응답은 상태코드가 핵심이다.클라이언트와 서버는 HTTP를 주고 받으며 기능을 동작하는데 이때 정해진 규칙을 API라고 한다. [사용 어노테이션]@RestController : 주어진 Class를 Controller로 등록한다. API의 진입 지점.@GetMapping("/add") : 아래의 함수를 HTTP Method가 GET이고 HTTP Path가 /add인 API로 지정한다.@RequestParam : 주어지는 쿼리를 함수 파라미터에 넣는다. [질문]어노테이션을 사용하는 이유 (효과) 는 무엇일까? Annotations in JavaAnnotations are used to provide supplemental information about a program.Annotations start with ‘@’.Annotations do not change the action of a compiled program.Annotations help to associate metadata (information) to the program elements i.e. instance variables, constructors, methods, classes, etc.Annotations are not pure comments as they can change the way a program is treated by the compiler.Annotations basically are used to provide additional information, so could be an alternative to XML and Java marker interfaces. 나만의 어노테이션은 어떻게 만들 수 있을까?How to Create Your Own Annotations in Java?Annotations are a form of metadata that provide information about the program but are not a part of the program itself. An Annotation does not affect the operation of the code they Annotate. Now let us go through different types of java annotations present that are listed as follows:Predefined annotations.: @Deprecated, @Override, @SuppressWarnings, @SafeVarargs, @FunctionalInterface.Meta-annotations: @Retention, @Documented, @Target, @Inherited, @Repeatable.Custom annotations: These are defined by the user. (We will be learning to create custom annotations in this module).Geek, now you must be wondering how can we create our own java annotations, for that refer to simple steps sequentially as follows:To create your own Java Annotation you must use @interface Annotation_name, this will create a new Java Annotation for you.The @interface will describe the new annotation type declaration.After giving a name to your Annotation, you will need to create a block of statements inside which you may declare some variables. 출처 1. https://www.geeksforgeeks.org/annotations-in-java/출처 2. https://www.geeksforgeeks.org/how-to-create-your-own-annotations-in-java/ 

백엔드워밍업클럽스터디백엔드자바스프링부트