블로그

솔 (Sol)

개발 기술 스택 심볼 & 마스코트 톺아보기

‘노트북 꾸미기’ 좋아하세요? 많은 개발자들이 노트북에 자기가 쓰고 있거나 좋아하는 기술 스택 로고 스티커를 붙이며 나만의 개성을 표현하곤 하는데요. 혹시 여러분의 노트북엔 어떤 스티커가 붙어 있나요?귀엽고 멋진 건 놓칠 수 없는 개발자라면 주목! 수많은 개발자들의 마음을 사로잡은 기술 스택에 숨은 아기자기한 심볼과 마스코트 몇 가지를 가볍게 소개할게요.썸네일 속 노트북은 인프런 백엔드 개발자 제이의 노트북!지금 쓰고 있는 스택(GraphQL 등...)이나 앞으로 배우고 싶은 스택(Go 등...), “Think Twice Code Once” 같은 개발자 밈 스티커까지 컨퍼런스나 주변 개발자 분들께 받은 스티커가 붙어 있어요. 🥰프로그래밍 언어 로고/심볼자바 (Java) 모락모락 김이 나는 귀여운 커피 컵! 자바 개발자들은 인도네시아 자바 섬에서 난 원두로 만든 커피를 마시곤 했대요. 몇 시간 동안 머리를 맞대고 토의한 끝에 정한 이름이라고 합니다.파이썬 (Python)‘비단뱀’이라는 뜻의 파이썬. 심볼 속 뱀 두 마리를 찾으셨나요? 파이썬을 만든 귀도 반 로섬(Guido van Rossum)이 영국 코미디 그룹 몬티 파이튼(Monty Python)에서 이름을 따왔다고 해요.스위프트 (Swift) iOS, macOS 개발에 쓰이는 스위프트는 ‘칼새’ 혹은 ‘신속한, 재빠른’이라는 뜻의 영단어 Swift에서 따온 이름이에요. 로고 모양도 날쌘 칼새를 닮았죠? 신속함을 강조하는 스위프트의 정체성을 잘 보여주네요.코틀린 (Kotlin) 자바와 비슷하면서도 간결한 문법으로 이목을 끄는 코틀린! 코틀린을 개발한 젯브레인(JetBrains) 사의 R&D 센터가 있는 러시아 코틀린(Ко́тлин) 섬에서 이름을 따왔는데요. 자바 역시 섬 이름인 걸 보면 두 언어의 관계가 재미있죠. 심볼 역시 머리글자 K를 간결하게 변형한 모양이에요.•••다양한 기술 스택 속 귀여운 마스코트깃허브 (Github) - 옥토캣 (Octocat) 복잡한 코드를 결합하고 관리하는 깃허브의 문어 다리 달린 고양이 마스코트 ‘옥토캣’. 3개 이상의 브랜치를 결합하는 작업을 가리키는 Octopus Merge에서 영감을 얻었다고 해요.리눅스 (Linux) - 턱스 (Tux) 믿거나 말거나! 리눅스를 만든 리누스 토르발스(Linus Torvalds)는 호주 캔버라 동물원에서 펭귄에게 물어뜯겨 펭귄염(?)에 걸린 적이 있다고 해요. 리눅스 마스코트로 삼을 정도면 그만큼 강렬한 경험이었던 모양이죠? 😅PHP (PHP: Hypertext Preprocessor) - 코끼리 (ElePHPant) 대문자로 쓴 PHP라는 글자를 옆에서 비스듬히 보면 코끼리처럼 보인다는 이유로 코끼리 마스코트를 갖게 된 PHP. elePHPant라는 말장난도 왠지 귀엽지 않나요?러스트 (Rust) - 페리스 (Ferris) 최근 개발자들 사이에 코어한 인기를 끄는 언어, 러스트의 비공식 마스코트는 주황색 게 모양이죠. 갑각류(Crustacean)에서 따온 듯한 요 마스코트 덕에 러스트 개발자들은 스스로를 Rustacean이라고 부른다고 하네요.고 (Golang) - 고 고퍼 (Go Gopher) 일러스트레이터 르네 프렌치(Renee French)가 그린 고퍼는 프로그래밍 언어 Go를 상징하는 주머니고퍼(흙파는쥐) 모양의 마스코트예요. 원래는 특별히 정해진 색이 없었다가 Google I/O 2011에서 Go App Engine 런타임을 출시하면서 파란색이 되었다고 해요.안드로이드 (Android) - 안드로보이 (Androboi) 단순한 듯 귀여운 녹색 로봇 마스코트 안드로보이! 안드로이드는 버전 1.1부터 OS 버전에 따라 디저트 이름을 붙이기로 유명한데 (컵케이크, 도넛, 오레오, 롤리팝…) 디저트 모양에 따라 달라지는 안드로보이의 모습을 보는 소소한 재미도 있죠.셀 수 없이 많은 기술 스택만큼, 매력적인 심볼과 마스코트도 무궁무진한데요. 여러분이 좋아하는 기술 심볼/마스코트는 어떻게 생겼나요? 댓글로 여러분의 최애 스킬(!)의 모습을 소개해주세요. 🥰

기타 (개발 · 프로그래밍)javapythonswiftkotlingithublinuxphpgoandroidrust

[프로그래밍 언어의 고민] JAVA와 Python중 언어 선택하기

개발자가 되기에 앞써  나는 비전공자이였기에, 혼자서하기에 많은 어려움이 있다. 처음 접하게되는 접근성의 어려움, 동기가 없이 혼자 시작해야함의 외로움, 남들보다 늦게 시작하는 불안감등 여러 어려움들이 있겠지만,  그중 내가 가장 크게 느끼는 어려운고민은  지금 내가 하고 공부하고 있는 개발이 옳은 길일까? 에 대한 의문점이 였다.  분명 이 의문점을 해결하기에는 온라인커뮤니티로도 한계가 있으며,  양산형적인(?) 학원 같은 곳도 형식적일것 같아,  최근에 알게된 개발자 훈련캠프를 알게되어 지원하였고 운이 좋게 최종테스트까지 다달았다.    하지만, 결국 시간이 턱없이 부족하여 떨어졌다.  떨어진 이유야 여러가지가 있겠지만,(+실력이 부족한것도) 익숙하지 않았던 JAVA 로 시험을 본게 아쉬웠다. 물론 최종테스트때 java언어만 국한되어 있다보니,  더 충분히 연습했어야 했는데, 그렇지 못한점도 있지만,  어쨌든 java라는 언어는 오래되기도 했고, 대기업 및 여러 국내기업에서 많이 사용하고 있는 언어다 보니,  지금이라도 익히면 도움이 될까 하고 공부하였었다.    하지만, 떨어지고 나서야 다시한번 내가 사용할 언어에 대해 되돌아보는 시간을 가지게 되었다. 나는 원래 Python언어로 개발공부를 시작했기에, 과연 JAVA로 바꾸는게 맞는지에 대한 의문이였다. (즉, 이후부터는 필자의 개인적인 의견이 많이 들어감을 참고바람)   가장 먼저 확인한 것은 전망이였다.  확인해본 방법은 아래와 같다.  1.티오베(프로그래밍순위사이트) 1위. Python,   2위. C언어   ,3위. Java 2. 구글트랜드검색 파란색: python , 빨간색 : java 3. 레드몽크(프로그래밍 순위사이트) 2위 : python,   3위 : java    등 그외에도 여러 사이트를 참조해봤지만, 그래도 윗내용은 믿고 맡길수 있는 사이트들이다. 물론, 티오베는 세계의 숙련된 엔지니어, 교육과정등 공급 업체의 수를 기반으로 프로그래밍 언어의 인기도 중심이고, 구글 트랜드검색은 경우의 수가 너무 많으며,  레드몽크도 GitHub와 Stack Overflow를 참고하여 데이터를 제공한다.    물론, 위자료는 세계적인 데이터로, 대한민국에서 개발자로 취업을 할려면 국내에서는 대부분의 대기업들은 Java언어를 사용하고 있어 지금 당장 대기업에 취업하고 싶다면 java의 언어를 선택하는게 좋다.  하지만, 좀더 멀리 보자면 전체적으로 비중이 커져가고 있는 python을 한번 봐보자.   이미 구글에서는 C++과 python을 백엔드로 사용하고 있고,  가장 대표적인 python어플로는 인스타그램이 있다.  그리고 OTT 시장의 (Netflix)넥플릭스도 파이썬으로 서비스를 관리하고 있으며,  클라우드 서비스 (Dropbox)드롭박스도 파이썬으로 개발하였다.  국내기업에서는 요기요 서비스가 파이썬으로 개발되는걸로 알고 있다.    게다가 국내 기업에서 개발자 채용테스트로  코딩테스트를 많이 보는데, python언어도 포함되어 점점 사용범위가 확대되어가고 있음을 알 수 있다. 현재는 AI(인공지능)와 데이터엔지니어부분에서 활용도가 점점 넓어지고 있는데,  좀더 직관적으로 보자면 자동차의 자율주행이나, 드론, 선박등 모빌리티 업계에 적용되고 있고,  또, 종종 보이는 서빙로봇과 같이 로봇에서도 많이 사용하는 언어이기에  이쪽으로 관심이 있다면, python언어  선택해볼만하다.    안드로이드때문에 앱부분은 java의 언어가 더 막강하지만,  안드로이드의 내장되어있는 기능을 사용하지 않는 플랫폼이나, 커뮤니티 앱일 경우  하이브리드로 만들기 때문에 다른 언어도 사용하여 만들기 가능하다. (웹도 마찬가지) --------------------------------------------------------------------------------------------------------------- 마지막으로 정리를 해보자면,  어느새부턴가 사람이름 세글자가 한자가 아닌 순 한글로된 이름으로  바뀌기 시작했다.  아직, 한자로된 이름을 가진 사람들이 더 많지만, 앞으로 태어날 아이들의 이름이 한자로된 이름이 계속 많을거라곤 장담하기 어렵다. 상대적으로 한자가 어렵다보니, 점점 아는 사람이 적어지고 한글이 편하기 때문일 것이다.  그렇다고 한자이름이 잘못되거나 없애야한다는 뜻은 아니다.  시대적흐름이 만들고 있을뿐..    java와 python도 비슷하다고 본다.  상대적으로 java보다는 python언어가 배우기 쉽다. 사용하기도 편리하다.  그리고 세계적으로 python을 선호하는 사람들이 많아지고 있다. 코딩언어도 결국 언어이다 보니  이건 소통하는 언어가 갖는 공통적인 습성이 아닐까싶다.    난 다시 python으로 돌아가 공부를 시작하고자 한다.                                

프로그래밍 언어진로javapython내생각언어공부고민

실무에서 주로 사용되는 정렬 알고리즘 종류 + 장단점

퀵 정렬 (Quick Sort)장점: 평균적으로 가장 빠른 속도를 보입니다.단점: 최악의 경우, O(n^2)의 성능을 보이며, pivot을 어떻게 선택하느냐에 따라 성능이 달라집니다.병합 정렬 (Merge Sort)장점: 입력 데이터의 상태에 상관없이 일정한 성능을 보이며, 안정적인 정렬을 보장합니다.단점: 공간 복잡도가 높아서, 메모리를 많이 사용합니다.힙 정렬 (Heap Sort)장점: 최악의 경우에도 O(n log n)의 성능을 보이며, 추가적인 메모리 공간을 사용하지 않습니다.단점: 구현이 복잡합니다.삽입 정렬 (Insertion Sort)장점: 구현이 쉽고, 데이터가 이미 정렬된 경우 빠르게 정렬합니다.단점: 입력 데이터가 역순으로 정렬되어 있을 때, 최악의 경우 O(n^2)의 성능을 보입니다.선택 정렬 (Selection Sort)장점: 구현이 쉽고, 정렬 중간 과정에서 리스트를 볼 수 있습니다.단점: 입력 데이터에 민감하여, 데이터 개수가 많아질수록 성능이 떨어집니다.따라서, 문제에 따라서 적합한 알고리즘을 선택하여 사용해야 합니다. 예를 들어, 데이터가 이미 정렬되어 있을 경우에는 삽입 정렬이나 선택 정렬을 사용하는 것이 더욱 효율적입니다. 데이터가 무작위로 섞여 있을 경우에는 퀵 정렬, 병합 정렬, 힙 정렬 중에서 선택할 수 있습니다.

java

고승조

java stream 간단한 사용법 정리

필터링(filtering)Stream은 컬렉션의 요소를 필터링하는 기능을 제공합니다. filter() 메서드를 사용하여 조건에 맞는 요소만 선택할 수 있습니다.// 예시 List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5); List<Integer> evenNumbers = numbers.stream() .filter(n -> n % 2 == 0) .collect(Collectors.toList()); // evenNumbers: [2, 4]  매핑(mapping)Stream은 컬렉션의 요소를 다른 값으로 변환하는 매핑 기능을 제공합니다. map() 메서드를 사용하여 각 요소를 원하는 값으로 변환할 수 있습니다.// 예시 List<String> names = Arrays.asList("John", "Paul", "George", "Ringo"); List<Integer> nameLengths = names.stream() .map(String::length) .collect(Collectors.toList()); // nameLengths: [4, 4, 6, 5]  정렬(sorting)Stream은 컬렉션의 요소를 정렬하는 기능을 제공합니다. sorted() 메서드를 사용하여 요소를 정렬할 수 있습니다.// 예시 List<Integer> numbers = Arrays.asList(5, 2, 1, 4, 3); List<Integer> sortedNumbers = numbers.stream() .sorted() .collect(Collectors.toList()); // sortedNumbers: [1, 2, 3, 4, 5] 제한(limiting)Stream은 컬렉션의 요소를 제한하는 기능을 제공합니다. limit() 메서드를 사용하여 최대 요소 개수를 제한할 수 있습니다.// 예시 List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5); List<Integer> limitedNumbers = numbers.stream() .limit(3) .collect(Collectors.toList()); // limitedNumbers: [1, 2, 3]  건너뛰기(skipping)Stream은 컬렉션의 요소를 건너뛰는 기능을 제공합니다. skip() 메서드를 사용하여 처음 몇 개의 요소를 건너뛸지 지정할 수 있습니다.// 예시 List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5); List<Integer> skippedNumbers = numbers.stream() .skip(2) .collect(Collectors.toList()); // skippedNumbers: [3, 4, 5]  리듀싱(reducing)Stream은 컬렉션의 모든 요소를 하나로 리듀싱하는 기능을 제공합니다. reduce() 메서드를 사용하여 컬렉션의 모든 요소를 하나의 값으로 결합할 수 있습니다.// 예시 List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5); int sum = numbers.stream() .reduce(0, Integer::sum); // sum: 15  수집(collecting)Stream은 컬렉션의 요소를 수집하는 기능을 제공합니다. collect() 메서드를 사용하여 원하는 형태로 요소를 수집할 수 있습니다. // 예시 List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5); Set<Integer> numberSet = numbers.stream() .collect(Collectors.toSet()); // numberSet: [1, 2, 3, 4, 5]  그룹핑(grouping)Stream은 컬렉션의 요소를 그룹핑하는 기능을 제공합니다. groupingBy() 메서드를 사용하여 원하는 기준으로 요소를 그룹핑할 수 있습니다. // 예시 List<String> names = Arrays.asList("John", "Paul", "George", "Ringo"); Map<Character, List<String>> namesByFirstLetter = names.stream() .collect(Collectors.groupingBy(name -> name.charAt(0))); // namesByFirstLetter: {J=[John], P=[Paul], G=[George], R=[Ringo]}  병렬 처리(parallel processing)Stream은 병렬 처리를 지원하여 대용량 데이터를 처리할 때 유용합니다. parallel() 메서드를 사용하여 병렬 처리할 수 있습니다.// 예시 List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5); int sum = numbers.parallelStream() .reduce(0, Integer::sum); // sum: 15  

java

최강현

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

Day 7. 스프링 컨테이너의 의미와 사용 방법 이 날 강의를 통해서 드디어 베일에 쌓인 의존성을 공부하는 기회가 되었다.의존성이란다음 코드를 보면 UserController의 생성자는 JdbcTemplate이라는 클래스를 필요로 하고 있다. @RestController public class UserController { private final UserService userService; public UserController(JdbcTemplate jdbcTemplate) { this.userService = new UserService(jdbcTemplate); } }이것을 어려운 말로 '의존한다'라고 한다. 스프링 빈이란스프링부트 서버를 시작할 때 자동으로 해주는 것 중 하나가 거대한 컨테이너(실제 컨테이너를 떠올리면 된다)를 만드는 것이다.이 컨테이너 안에는 클래스가 들어가게 되는데 이렇게 들어간 클래스를 스프링 빈이라고 부른다.클래스가 들어갈 때는 이 빈을 식별 할 수 있는 이름 및 타입과 다양한 정보가 들어가고 인스턴스화도 이루어진다. Day8. Spring Data JPA를 사용한 데이터베이스 조작 8일차 강의를 통해 SQL을 통해서 접근했던 DB를 자바 객체를 DB와 매핑 시켜서 사용하는 JPA를 학습하였다. JPA란객체와 관계형 데이터베이스의 테이블을 짝지어 데이터를 영구적으로 저장할 수 있도록 정해진 Java 진영의 규칙JPA는 API이기 때문에 말 그대로 규칙이고 (자바의 인터페이스와 같다) 이 규칙을 누군가는 실제로 구현을 해야한다그 구현체가 바로 Hibernate이다. Day9. 트랜잭션과 영속성 컨텍스트 9일차 강의는 서비스 계층의 남은 중요한 역할인 트랜잭션에 대해 배웠다.트랜잭션이란 쪼갤 수 없는 업무의 최소단위이다.실제로 예를 들면 인터넷 결제를 진행할 때 1. 주문 기록을 저장하고 2. 포인트를 적립해주고 3. 구매 기록을 저장해준다이 3가지의 과정을 쪼갤 수 없는 하나의 최소단위로 묶고 하나가 실패하면 다른 모든 과정도 실패해버리게 만드는게 트랜잭션이다. Start transaction -> 성공하면 COMMIT -> 실패하면 ROLLBACK 또한 영속성 컨텍스트에 관해서도 학습했는데 조금 어려워서 꼭 기억해야하는것스프링에서는 트랜잭션을 사용하면 영속성 컨택스트가 생기고, 트랜잭션이 종료되면 영속성 컨텍스트가 종료된다. 영속성 컨텍스트의 특별한 능력변경 감지 : 영속성 컨텍스트 안에서 불러와진 Entity는 명시적으로 save를 해주지 않더라도 알아서 변경을 감지하여 저장할 수 있게 해준다.쓰기 지연 : 영속성 컨텍스트에 의해 트랜잭션이 Commit 되는 시점에 SQL을 모아서 한 번만 날리게 된다.1차 캐싱 : ID를 기준으로 Entity를 기억하는 기능이다. 조금 더 복잡한 기능을 API로 구성하기 10일차는 앞서 배운 것들로 JPA를 이용해서 책 생성, 대출, 반납 API를 개발해보았다. 과제 과제 4일차https://devnter.tistory.com/entry/%EC%9D%B8%ED%94%84%EB%9F%B0-%EC%9B%8C%EB%B0%8D%EC%97%85-%ED%81%B4%EB%9F%BD-1%EA%B8%B0BE-4%EC%9D%BC%EC%B0%A8-%EA%B3%BC%EC%A0%9CqueryForObject() 에 대한 학습이 필요. 과제 5일차https://devnter.tistory.com/entry/%EC%9D%B8%ED%94%84%EB%9F%B0-%EC%9B%8C%EB%B0%8D%EC%97%85-%ED%81%B4%EB%9F%BD-1%EA%B8%B0BE-5%EC%9D%BC%EC%B0%A8-%EA%B3%BC%EC%A0%9C주어진 코드를 클린코드로 리팩토링하는 과제를 수행하였다.클래스를 나누기에는 너무 작은 기능이라 생각해서 읽기 좋은 코드로만 수정한다는 생각으로 수정했는데나중에 금요일에 코치님이 따로 열어주신 특강에서 테스트를 하기 위해 역할 별로 클래스를 쪼개고 테스트를 하는 강의를 진행 해 주셔서 새로운 내용에 대해 학습하는 기회가 되었다리팩토링 전에는 테스트를 작성하자! (Junit5, assertj)given / when / then 패턴전략 패턴 (= NumberGenerator의 인터페이스화 + 구현체 갈아끼우기)일급컬렉션MVC 패턴출처 https://www.inflearn.com/course/%EC%9E%90%EB%B0%94-%EC%8A%A4%ED%94%84%EB%A7%81%EB%B6%80%ED%8A%B8-%EC%84%9C%EB%B2%84%EA%B0%9C%EB%B0%9C-%EC%98%AC%EC%9D%B8%EC%9B%90# 아쉬운점좀 더 추가적인 학습(모르는것에 대한 학습)을 하려고 했는데 나태해져서 진행하지 못했다. 다음 마지막 주차는 좀 더 내가 모르는 내용에 대해 민감하게 반응해서 학습 하거나 학습 하지 못한다면 따로 블로그나 노션에 기록해서 추후 공부할 수 있도록 하겠다. 

백엔드인프런워밍업클럽자바스프링javaspring

최강현

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

강의 수강,과제 수행하면서 생겼던 궁금증을 해결하는 과정을 위주로 블로그 글을 작성하려고 합니다. 강의 수강 1일차 - OT 인프런 워밍업 클럽 스터디 및 일정 소개 코치님과 구글 밋을 통해 온라인 OT를 진행하였습니다.간단한 스터디 과정 및 일정에 대해 소개 해줬고, 코치님이 이거까지 알아야하나? 라는 주제로 의견을 공유해주셨습니다. 2일차 - 서버 개발을 위한 환경 설정 및 네트워크 기초 (1강 ~ 5강)2일차에는 서버, 네트워크, HTTP, API를 배웠다.API가 무엇인지 잘 몰랐는데 Input을 주면 OutPut이 나오는 함수와 비슷하다는걸 알게 되었다. API가 무엇인지 와닿지 않았는데 감을 잡을 수 있었다3일차 - 첫 HTTP API 개발 (6강 ~ 10강)GET API와 POST API를 개발해봤다.GET 요청은 쿼리를 통해서 요청을 주고 POST 요청은 body를 통해 요청을 주는데@RequestParam을 통해 주어지는 쿼리를 함수 파라미터에 넣는다.파라미터 대신에 DTO 객체를 넣어서 쿼리를 받을 수 있다public class CalculatorAddRequest{ private final int number1; private final int number2; public CalculatorAddRequest(int number1, int number2) { this.number1 = number1; this.number2 = number2; } public int getNumber1() { return number1; } public int getNumber2() { return number2; } }  post 요청은 body로 들어오는 JSON을 DTO로 바꿔주기 위해 @RequestBody를 사용해야하는데@RequestBody를 사용하면 DTO 객체에 생성자를 만들지 않아도 괜찮은데 이 이유가 궁금했다public class CalculatorMultiplyRequest { private int number1; private int number2; public int getNUmber1(){ return number1 } public int getNumber2(){ return number2; } }다음과 같은 이유를 찾을 수 있었다.Spring의 동작 방식: @RequestBody 어노테이션이 적용된 메서드 파라미터에는 HTTP 요청의 본문을 기반으로 객체가 생성됩니다. Spring은 이를 위해 클래스의 기본 생성자를 호출하여 빈 객체를 생성하고, 요청의 본문에서 추출한 데이터를 객체에 설정합니다.4일차 - 기본적인 데이터베이스 사용법 (11강 ~ 13강) MySQL의 사용법을 배웠다DDL(데이터 정의어) - CREATE, ALTER, DROPDML(데이터 조작어) - INSERT, UPDATE, SELECT, DELETE이 2개를 사용해서 데이터를 DB에 생성, 조회, 갱신, 삭제하고5일차 - 데이터베이스를 사용해 만드는 API (14강 ~ 16강)이 강의를 통해 사람이 직접 DB에 접속해서 DB를 조작하는게 아닌 Spring 서버가 MySQL DB에 접근해서 DB를 조작하게 API를 만들었다. 6일차 - 클린코드의 개념과 첫 리팩토링(17강~ 18강) 이 강의를 통해 저번 강의를 통해 만든 컨트롤러 클래스를 3개의 클래스로 쪼개 보았다.Controller 클래스 - API의 진입 지점으로써 HTTP Body를 객체로 변환Service 클래스 - 분기처리 로직Repository 클래스 - SQL을 사용해 실제 DB와의 통신을 담당 컨트롤러 클래스 작성 시 JdbcTemplate 객체를 생성하는데 new 키워드를 사용하지 않고 생성했다이게 어떻게 가능한지 궁금해서 찾아보니스프링에서는 보통 dependency injection을 사용하여 객체를 주입합니다. 이 코드에서도 JdbcTemplate jdbcTemplate는 생성자를 통해 주입됩니다.생성자 public UserController(JdbcTemplate jdbcTemplate)에서 JdbcTemplate 객체가 주입됩니다. Spring이 UserController를 생성할 때, 필요한 JdbcTemplate 객체를 찾아서 자동으로 주입해줍니다. 이것이 Spring의 IoC (Inversion of Control) 컨셉입니다.따라서 new 키워드를 사용하여 직접 객체를 생성할 필요가 없고, Spring이 해당 객체를 관리하고 주입해줍니다.미션1일차어노테이션을 미리 정의 해두면 @RequestParam 같은 한 단어만 작성해주면 스프링이 알아서 GET 요청의 쿼리를 메서드의 파라미터로 바꿔준다.어노테이션은 이런 마법 같은 일을 해준다.  2일차문제1Controller에서 getter 메서드가 있는 객체를 반환하면 반환 값이 JSON으로 반환 한다! CalculatorResponse.java public class CalculatorResponse { private int add; private int minus; private int multiply; public CalculatorResponse(int num1, int num2) { this.add = num1 + num2; this.minus = num1 - num2; this.multiply = num1 * num2; } public int getAdd() { return add; } public int getMinus() { return minus; } public int getMultiply() { return multiply; } }  ExController.java@RestController public class ExController { @GetMapping("/api/v1/calc") public CalculatorResponse plusMinusMultiplyCalculator(@RequestParam int num1, int num2) { return new CalculatorResponse(num1, num2); } } Response문제2ExController.java@RestController public class ExController { @GetMapping("/api/v1/day-of-the-week") public DateResponse dayOfTheWeek(@RequestParam String date) { return new DateResponse(date); } } DataResponse.java public class DateResponse { private Enum<DayOfWeek> dayOfTheWeek; public DateResponse(String date) { LocalDate parsed = LocalDate.parse(date); this.dayOfTheWeek = parsed.getDayOfWeek(); } public Enum<DayOfWeek> getDayOfTheWeek() { return dayOfTheWeek; } }  GET 메서드에서 파라미터의 value의 타입은 문자열로 들어오므로 DateResponse의 생성자에서 LocalDate.parse()를 통해 문자열을 LocalDate로 바꿔주었다. 문제3 ExController.java@RestController public class ExController { @PostMapping("/api/v1/multi-number-sum") public int multiNumberSum(@RequestBody CalculatorMultiNumber request) { int[] numbers = request.getNumbers(); int sum = Arrays.stream(numbers).sum(); return sum; } } CalculatorMultiNumber.javapublic class CalculatorMultiNumber { int[] numbers = new int[5]; public int[] getNumbers() { return numbers; } } ResponseResponse크기가 5개인 배열을 선언 하고 body에 길이가 6개를 리스트 넣고 요청해도 6개의 값을 반환한 값을 돌려준다.왜 그런지 이유를 찾고 싶었는데 못찾았다 ㅠㅠ 3일차람다식은 익명 클래스를 좀 더 쉽게 쓸 수 있게 자바8부터 도입된 개념이다. OOP인 자바는 람다식의 도입으로 함수형 프로그래밍도 가능해졌다하루에 몰아서 적으려니까 너무 힘들었다 다음주 회고록은 따로 초고를 그날 그날 적어놔야겠다..이 블로그에 올린 코드와 문제의 출처는 https://www.inflearn.com/course/%EC%9E%90%EB%B0%94-%EC%8A%A4%ED%94%84%EB%A7%81%EB%B6%80%ED%8A%B8-%EC%84%9C%EB%B2%84%EA%B0%9C%EB%B0%9C-%EC%98%AC%EC%9D%B8%EC%9B%90입니다  

백엔드java인프런워밍업클럽스프링spring자바

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

진도표 4일차와 연결됩니다우리는 GET API와 POST API를 만드는 방법을 배웠습니다. 👍 추가적인 API 들을 만들어 보며 API 개발에 익숙해져 봅시다!CREATE TABLE fruits ( id INT AUTO_INCREMENT, name VARCHAR(255), warehousingDate DATE, price BIGINT, PRIMARY KEY (id) );import java.time.LocalDate; public class FruitCreateRequest { private String name; private LocalDate warehousingDate; private long price; public String getName() { return name; } public LocalDate getWarehousingDate() { return warehousingDate; } public long getPrice() { return price; } } import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; import java.sql.Date; @RestController public class FruitController { private final JdbcTemplate jdbcTemplate; public FruitController(JdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; } @PostMapping("/api/v1/fruit") public void saveFruit(@RequestBody FruitCreateRequest request) { String sql = "INSERT INTO fruit(name, warehousingDate, price) VALUES(?, ?, ?)"; jdbcTemplate.update(sql, request.getName(), Date.valueOf(request.getWarehousingDate()), request.getPrice()); } } long을 사용하는 이유는 큰 숫자 범위를 처리하기 위해서이다. @PutMapping("/api/v1/fruit") public ResponseEntity<String> markAsSoldOut(@RequestBody Map<String, Long> body) { Long id = body.get("id"); if (id == null) { return ResponseEntity.badRequest().body("id 누락"); } String sql = "UPDATE fruits SET status = 'soldout' WHERE id = ?"; jdbcTemplate.update(sql, id); return ResponseEntity.ok("'soldout'"); }   @GetMapping("/api/v1/fruit/stat") public Map<String, Long> getSalesStat() { String salesAmountSql = "SELECT SUM(price) FROM fruits WHERE status = 'soldout'"; String naoSalesAmountSql = "SELECT SUM(price) FROM fruits WHERE status IS NULL OR status != 'soldout'"; Long salesAmount = jdbcTemplate.queryForObject(salesAmountSql, Long.class); Long naoSalesAmount = jdbcTemplate.queryForObject(naoSalesAmountSql, Long.class); Map<String, Long> result = new HashMap<>(); result.put("salesAmount", salesAmount != null ? salesAmount : 0); result.put("naoSalesAmount", naoSalesAmount != null ? naoSalesAmount : 0); return result; }

백엔드java

[인프런워밍업클럽][BE] 과제 3 | Lambda 식

1. 람다식(Lambda Expression) 이란?: 익명함수를 생성하기 위한 식 (Annoymous Function, 익명함수)1.1 람다식의 등장 배경- 복잡한 요구사항을 처리하기 위해 기존 Java 문법으로는 Method 사용이 늘어나는 등 코드의 복잡도가 높아짐- 메소드의 제한적 사용 - 객체를 통한 접근만을 허용 - 메소드 자체를 변수로 사용 불가 1.2 람다식 특징- 익명 함수 : 식별자없이 실행가능한 함수 (메소드명이 없음)- 간결한 문법- 함수형 인터페이스 지원1.3 람다식의 장/단점(1) 장점- 코드의 간결성 : 불필요한 반복문의 삭제 가능- 지연연산 수행 : 불필요한 연산 최소화- 병렬처리 기능 : 멀티쓰레드 활용- 가독성 향상 : 코드가 실제로 수행하고자 하는 로직이 추상적으로 드러남(2) 단점- 호출을 위해 직접 메소드를 불러야 함 : 람다식 생성 및 전달이 간결한 것과는 달리, 람다식 실행 시 인터페이스에 선언된 메소드 호출이 필요- 재귀 람다식 호출의 어려움 2. 람다식의 사용2.1 람다식 기본기본 형태 : 인터페이스 객체 변수명 = (매개변수, ..., 매개변수) -> {함수몸체;}구성요소매개변수 : 메소드 매개변수(parameter)하나일 경우 매개변수 또는 매개변수를 감싸는 () 생략 가능 (둘 다 생략은 안됨)화살표 : 코드 블럭을 실행(호출)메소드 구현부 (함수몸체) : {}함수몸체가 단일 실행문이면 {} 생략 가능단, 함수몸체가 return 문으로만 구성되어 있으면 {} 생략 불가 2.2 람다식 예제(추가 필요) 2.3 람다식 해석(1) 13강. GET API 람다 식 적용 전RowMapper = PreparedStatement + ResultSetJdbcTemplate.query()와 연동하여 사용SQL문의 결과값 각 행을 원하는 자료형으로 변환 : 즉, 각 행의 각 열(column)과 java 코드의 변수를 매핑시켜 줌.아래 코드에서 함수의 흐름은 다음과 같다각각 다음의 형식으로 매핑시킴long id : id bigintString name : name varchar(20)int age : age intreturn 시에는 method에서 반환값을 List<UserResponse>로 정의했으므로 UserResponse 생성자를 이용하여 구성 @GetMapping("/user") public List<UserResponse> getUsers(){ //1. SQL 조회 String sql = "SELECT * FROM users"; //2. JDBC 연결, 처리 return jdbcTemplate.query(sql, new RowMapper<UserResponse>() { @Override public UserResponse mapRow(ResultSet rs, int rowNum) throws SQLException { long id = rs.getLong("id"); String name = rs.getString("name"); int age = rs.getInt("age"); return new UserResponse(id, name, age); } }); } (2) 13강. GET API 람다 식 적용 후람다식 적용전에 비해 짧아졌으며, 중요한 부분 (매핑되는 부분)이 강조되어 보임.람다식매개변수 : rs (=ResultSet), rowNum함수본체 : 각각 java 변수와 sql 결과를 매핑시킴그러나 여전히 rs = ResultSet 이고, RowMapper 인스턴스를 사용한다는 걸 어떻게 인지하는 건지 모르겠음. @GetMapping("/user") public List<UserResponse> getUsers(){ String sql = "SELECT * FROM user"; return jdbcTemplate.query(sql, (rs, rowNum) -> { long id = rs.getLong("id"); String name = rs.getString("name"); int age = rs.getInt("age"); return new UserResponse(id, name, age); }); } 참고자료Lambda https://blog.naver.com/hj_kim97/222318922263https://blog.naver.com/it_jh/223356024460https://blog.naver.com/krkarma777/223278551937RowMapperhttps://blog.naver.com/3723578/223258910909https://mincanit.tistory.com/13

인프런워밍업클럽인프런워밍업클럽BEjavalambda식

java 파일이 누워서 업로드 됨

우리 회사는 문자발송 시스템 회사다.포토문자를 보냈는데 문자가 누워서 발송된다고 문의가 들어왔다.확인해보니 진짜 누워있다.이미지 리사이징 하는 부분에서 에러가 나는것 같아서 확인해봤는데 자바에서 파일을 읽어올때부터 파일에 가로 세로 사이즈가 바뀌어서 들어왔다.모바일에서 찍은 이미지는 그럴수도 있다그런다.private BufferedImage makeThumbnail(MultipartFile mFile) throws Exception { File imageFile = multipartFileToFile(mFile); //multipartFile To File int orientation = 1; Metadata metadata; Directory directory; try { metadata = ImageMetadataReader.readMetadata(imageFile); directory = metadata.getFirstDirectoryOfType(ExifIFD0Directory.class); if(directory != null){ orientation = directory.getInt(ExifIFD0Directory.TAG_ORIENTATION); } }catch (Exception e) { orientation=1; } BufferedImage bfImage = ImageIO.read(imageFile); switch (orientation) { case 1: break; case 3: bfImage = Scalr.rotate(srcImg, Scalr.Rotation.CW_180, null); break; case 6: bfImage = Scalr.rotate(srcImg, Scalr.Rotation.CW_90, null); break; case 8: bfImage = Scalr.rotate(srcImg, Scalr.Rotation.CW_270, null); break; default: orientation = 1; break; } if (imageFile.exists() && !imageFile.delete()) { throw new IOException("Failed to delete image file: " + imageFile.getAbsolutePath()); } return srcImg; }회전 정보를 가져와서 맞춰주는 방식으로 해결했다.3시간 정도 찾은것같다.재미있었다.-끝-

java

스프링 핵심원리 기본편(김영한) 1 - 객체지향 DIP와 스프링 DI, IoC

  객체는 객체와 끊임없이 상호작용한다. 그렇기에 유연한 변경이 가능해야한다. 예를 들어, 자동차라는 상위 클래스를 다양한 자동차 브랜드로 구현될 수 있고, 운전자가 변화해도 자동차는 영향을 받지 않는다. 사용자, 주문, 할인 등 여러 독립적인 특징을 가진 기능은 클래스로 분리하여 각 클래스에서만 수정 및 사용한다.   역할과 구현을 분리 - 인터페이스와 콘크리트 클래스 인터페이스는 안정적이게, 확장이 무한대로 가능하게 설계해야한다.   SOLID 객체지향 설계 원칙 1. SRP 단일책임원칙 - 변경이 용이한 단위적 책임인가2. OCP 개방폐쇄원칙 - 코드의 변경 없이 확장이 가능한가(조립만으로 변경)3. LSP 리스코프 치환 원칙 - 하위 클래스는 인터페이스(상위 클래스)를 위반하지 않아야한다4. ISP 인터페이스 분리 원칙 - 여러 개의 인터페이스를 통해 명확한 기능을 갖고 있고, 대체 가능성이 높은 환경을 구현할 것5. DIP 의존관계 역전 원칙 - 추상화에 의존할 것, 인터페이스(역할)가 중심이 되어야한다. 구현체에 의존하면 다형성을 잃는다(재활용성을 잃는다) 스프링 컨테이너에 객체 지향 적용 객체를 생성하는 역할과 객체를 실행하는 역할을 분리.의존은 인터페이스로 하고, 설정 파일을 통해 구체적인 구현체를 의존 주입구현체 변경 시 설정 파일만 변경하면 된다.(조립)=> 제어의 역전; 어떤 구현체를 사용할 것인지 AppConfig(Spring)가 결정한다. 동적인 인스턴스 의존관계    

객체지향javaSOLIDspringDIIoCDIP강의김영한

객체 지향 프로그래밍 입문(최범균) 2 - 다형성, 추상화, 조립

  다형성이란, 여러 모형으로 변화하는 것이다. 하나의 객체가 여러 타입을 갖는 것이다. 추상화란, 특정한 성질(interface) 또는 공통 성질(abstract, 일반화)을 뽑아내는 과정이다. 추상화를 통해 객체는 다형적인 모형을 변화 가능하다   <추상화 시점> 추상화는 의존 대상이 변경하는 시점에 추가한다. 실제 변경 및 확장이 일어날 때 공통점을 파악하고 뽑아낸다.   <추상화 예시> 클라우드 파일 관리 기능이 있고, 대상 클라우드의 종류가 n가지일 경우.클라우드 종류에 따라 if문으로 분기하는 로직이 아닌 공통기능인 클라우드 파일 시스템을 추상화한다.클라우드 파일 시스템에서는 파일 목록과 관련된 CRUD 기능을 추상화하고,클라우드 파일에서는 개별 파일의 CRUD 기능을 추상화한다. 특정 클라우드 구현체에서는 추상 클래스를 상속받아서 기능을 재정의한다. 추상화가 진행되면, 구현 클래스의 변경은 있더라도(조립) 서비스 로직은 바뀌지 않는다.   <상속보다는 조립> 상속을 통해서 재사용을 하게 된다면,1. 상위 클래스의 변경이 어렵고2. 기능과 확장이 필요한 만큼 클래스가 증가하고3. 상속을 오용하게 된다.(비슷한 메서드 착오) 상속은 하위타입일 경우에 진행하고, 보통의 경우 객체를 참조하는 방식으로 진행할 것.    

java객체지향최범균강의추상화다형성조립객체참조

객체 지향 프로그래밍 입문(최범균) 3 - 분리, 의존 주입, DIP

<역할과 기능 분리 방법> 1. 패턴 적용 전형적 분리(아키텍처, 디자인패턴) 2. 계산 분리 로직의 기능화 3. 연동 분리 클래스 분리 4. 연속적인 if-else는 추상화 고민할 것   적절한 역할 분리는 테스트도 용이하게 한다.사용자와 직접적으로 관련된 기능은 내부 메서드로, 간접적으로 관련있는 기능은 별도의 클래스로 분리한다.   <의존> 순환 의존은 변경이 연쇄적으로 전파된다. 기능 변경의 파장이 커지면 안 좋기 때문에 의존은 적을수록 좋다. 의존대상의 기능이 많은 경우 클래스로 분리하거나 단일 기능으로 묶을 수 있는지 확인하라. 예를 들어 민원팩토리, 민원리포지토리를 민원등록으로 묶기   <스프링 의존 주입> 추상적 인터페이스를 의존하고, 의존 주입은 보통 생성자 방식으로 외부(스프링)에서 진행한다. 내부에서 new()로 생성하는 것과 반대이다. 1. 의존 대상이 바뀌면 그 대상을 조립하는 부분만 수정하면 됨 2. 대역 객체를 통해 테스트가 가능하다   <DIP 의존 역전 원칙> 고수준 모듈(기대수준), 저수준 모듈(단위적 실제 행위) 고수준 모듈을 의존해야한다. 반대로 고수준 모듈이 저수준 모듈을 의존하는 경우, 저수준 모듈이 변화할 때 고수준 모듈에 영향을 끼침 (목표를 향해 개발하는 것이 아닌, 개발에 따라 목표가 변하는 현상)고수준 모듈을 구현한 추상타입(인터페이스)을 저수준 모듈이 의존하는 방식을 추구해야한다.    

java강의최범균DIPDIinterface분리객체지향

객체 지향 프로그래밍 입문(최범균) 1 - 객체지향, 캡슐화

좋은 코드란, 낮은 비용으로 변화할 수 있는 코드이다 이것은 1. 캡슐화 2. 추상화(다형성 지향)로 이루어낼 수 있다.   절차지향적 코드는 진행될수록 여러 조건문으로 복잡해질 수 있다. 객체지향적 코드는 객체가 제공하는 기능(메서드)이 중심이 되어 설계하는 것이다.  - 호출, 리턴, 익셉션 등의 메세지의 교환 - 데이터 클래스(VO, DTO)는 객체가 아니다. 객체의 기능이 없이 값에만 접근하기 때문이다.   캡슐화는 데이터와 관련된 기능을 묶는 것이다. 데이터의 상세 내용을 외부에 감추고, 외부와 무관하게 객체 내부의 구현 변경이 가능하다. 객체의 기능을 비즈니스 로직이 아닌 객체 내부의 메서드로 구현하면, 기능에 변화가 요구될 때 해당하는 내부 기능을 변경하면 캡슐화를 사용한 곳에 별도의 수정이 필요하지 않다.   캡슐화의 규칙 1. 데이터를 요구하는 것이 아닌 데이터의 처리를 요구할 것if(member.getAge() > 19) Xif(member.isAdult()) O 2. 메서드에서 생성한 객체의 메서드만 호출할 것파라미터로 받은 객체의 메서드만 호출할 것필드로 참조하는 객체의 메서드만 호출할 것 >> 연속적인 메서드 호출이 아닌 객체에 있는 하나의 메서드로 처리member.isAdult() + member.isVIP() + member.addCoupon()으로 하나씩 처리하는 것보다member.receiveBenefits()로 위 세 개 기능 묶기     객체는 속성과 기능으로 구성되어있다. 객체의 여러 기능을 참조하고 묶어서 새로운 기능에 사용하는 것은 객체 지향적인 방식이다.        

java객체지향최범균강의캡슐화DDD

대근

반려동물 시장 진출 웹&앱 스프링 개발자 모집

반려동물 시장 진출 웹&앱 스프링 개발자 모집   안녕하세요 현재 서로 믿을 수 있는 스타트업 멤버 구축 되었고 추가로 능력있고 참하신 스프링 개발자 팀원 찾습니다. 현재 모두 메인 잡은 있는 상황이고 사이드 프로젝트로 운영중이라 부담없이 참여 가능합니다. 관심있으신분 연락 부탁드립니다   1. 주제소개: 반려동물 서비스 중 현재 시장에 없는 서비스 2. 현재 진행 단계: 시장분석 및 명확한 주제와 컨텐츠 방향성까지 잡은 상태 3. 모집분야 및 주요업무: 앱 개발자-하이브리드 앱 (웹앱을 네이티브 형태로 감싼 형태) 유사사이트: https://www.pet-friends.co.kr/main/tab/2 4. 모집경력 및 필요스킬: 앱개발 관련하여 경력이 있거나, 최소 스프링을 자유롭게 다룰 수 있는 스킬 필요 vue.js 옵션,java 등 5. 참고기타사항: 기획/디자인/개발/마케팅 포지션 다 구성되어 있으나, 추가 개발자 필요한 상황 6. 문의/연락: 010-4590-4917 카카오: antoniobae1 참고url:IT 웹 앱 마케팅 개발 창업모임 파랑새(Since 2021.10.02 : 네이버 카페 https://cafe.naver.com/lastpick1004 https://lastpick.modoo.at/ https://www.youtube.com/channel/UCpLCToWUvdjsPqkLRZ-wpZA   이 외 어떤 직군이라도 관심있으신 분은 연락 바랍니다.

모바일 앱 개발springjavavuejs