블로그

홍정모

최적의 프로그래밍 공부 방법

*같은 글의 브런치 링크MZ 세대를 위한 가장 효율적인 프로그래밍 공부 순서 요약- 문법보다 활용- 뭘 하든 생각하는 방법부터지금 프로그래밍 공부를 시작하거나 하고 있는 분들은 정말로 한 분 한 분이 소중합니다. 누구나 얼마든지 무럭무럭 자라나서 창조성을 꽃피울 수 있는 잠재력을 가지고 있음에도 불구하고 C언어 문법 공부로 대표되는 옛날 방식으로 지쳐버리는 것을 보는 것은 안타깝습니다.​오프라인/온라인에서 오랜시간 동안 다양한 과목들을 다양한 학생들에게 가르치면서 프로그래밍 교육에서 고려해야할 점들을 정리해봤습니다.​1. 흥미를 끌고 매 단계마다 재미를 느낄 수 있어야 합니다. 지루함을 억지로 참게하면 안되고 짧은 템포로 강한 집중력을 유도해야 합니다.​2. 왜 필요한지를 먼저 알려줘야 합니다. 예전에는 그냥 알아두면 나중에 도움된다며 일단 압박하며 가르쳐야했던 내용들도 다양한 응용 분야가 내 미래에 직결된다는 것을 미리 알게 되면 강한 의지를 보입니다.​3. 클릭만 유도하는 미디어에 지쳐가는 새싹들에게 수명이 짧고 단편적인 기술이 아니라 생각하는 방법 자체를 배울 수 있는 기회를 제공해야 합니다.​여기에 맞춰 가장 효율적인 프로그래밍 공부 방법을 정리해봤습니다.​1. 안정적인 초중고 교육은 인생 자체를 지탱하는 뿌리가 됩니다. 이 시기에는 컴퓨터로 인해 바뀌어가는 인류의 미래에 대해 호기심을 갖는 정도면 충분합니다. 타의에 의한 강압적인 선행학습은 권장하지 않습니다.​2. 프로그래밍 입문 초반부터 다양한 응용 분야에 대해 가볍게 체험을 해보는 것을 권장합니다. 자신의 가능성에 미리부터 선을 긋고 특정 분야에 대해 단편적인 지식만을 습득하는 방식은 미래의 나에게 족쇄를 채우는 행위일 뿐입니다. 프로그래밍 언어로는 파이썬을 추천합니다. C언어와 달리 소소한 불편함이 없고 분야별로 사용하기 쉬운 패키지들이 미리 준비되어 있어서 빠르게 다양한 체험을 할 수 있습니다. 이 단계에서 주의해야할 점은 쉬운 것일수록 스스로 해결할 수 있도록 올바르게 지도받아야 합니다. 나의 두뇌가 크게 성장할 수 있는 기회를 강탈당하지 않도록 주의하세요.​3. C/C++언어를 최소한으로 공부합니다. 딱 자료구조 공부에 필요한 만큼만 공부하시면 됩니다. C/C++ 문법을 깊게 들어가는 것은 알고리즘 공부 뒤에 자신이 선택한 응용 분야에서 필요하다면 그때 하시면 됩니다. 한 언어를 공부한 후에 다른 언어를 공부하는 것은 쉽구나 하는 체험도 이 단계에서 거쳐가야겠지요.​4. 프로그래밍 연습으로써의 자료구조 공부를 진행합니다. 우리의 목표는 "생각하는 방법 = 알고리즘"이지만 프로그래밍 연습이 부족한 상태에서는 반쪽짜리 공부가 되어버릴 수도 있습니다. 생각하는 방법을 터득하면서 동시에 구현까지 할 수 있으려면 약간의 프로그래밍 연습이 필요합니다. 그렇다고 해서 "C/C++ 문법 공부"를 "프로그래밍 연습"으로 착각하면 안되기 때문에 문법은 최소로 줄이고 자료구조를 공부하는 것을 추천합니다. 파이썬으로 다양한 응용 분야를 체험해봤기 때문에 자료구조와 알고리즘의 추상적인 개념들도 필요성을 느끼고 하나씩 내것으로 만들어나갈 수 있습니다. 파이썬으로 아주 기초적인 문제풀이를 해봤다면 더 좋습니다.​5. 알고리즘 공부를 시작합니다. 보다 구체적으로는 인터넷에 답이 없는 문제도 해결할 수 있는 능력을 갖추는 것입니다. 어떻게 공부해야할까요? 이미 앞에서 쉬운 것부터 스스로 해결하는 습관을 갖추셨다면 약간의 훈련만으로 빠르게 성장하실 수 있습니다. 이 단계에서 주의해야할 점은 코딩테스트 통과를 위한 문제 풀이와 알고리즘 공부를 헷갈리면 안됩니다. 쉬운 것부터 스스로 해결해온 순간들이 모여서 이때부터 화려하게 꽃 피우기 시작합니다. 알고리즘 공부는 Java로 하는 것도 괜찮습니다. 저는 C->C++로 흐름이 자연스럽게 연결될 수 있다는 점에서 C++을 추천합니다. 앞에서 이미 한 번 경험해봤듯이 C++ 후에 자바를 공부하는 것은 빠르게 하실 수 있습니다. 다만, 전문 영역으로써 깊게 언어를 파고드는 것은 추가적인 노력이 필요합니다.​6. 코딩 테스트 문제 풀이를 천천히 시작합니다. 알고리즘에서 터들한 내용들로부터 직결되는 문제들부터 몇 개만 스스로 풀어보며 감을 잡으면 문법 공부 직후에 바로 문제풀이 시작한 사람들보다 오히려 진행 속도가 훨씬 빠를겁니다. 문제풀이는 일찍 시작하고 꾸준히 하는 것을 추천합니다. 대신에 이제부터는 전문/응용 분야와 병행해야 합니다.​7. 전문/응용 분야 공부를 시작하면서 자유와 창의성을 발휘해보세요. 웹을 HTML 사용법 익히는 정도로 생각하는 경우도 있는데 저는 웹 프로그래밍도 고도로 전문화된 응용 분야로 봅니다. 웹, 앱, 서버, 게임, AI, 비전 등의 다양한 분야가 여러분들을 애타게 기다리고 있습니다. 특정 언어의 문법을 깊이 파고 들어가는 공부도 이때 시작하시면 되는데 복잡한 문법도 이런 문법이 왜 필요한지를 깨달으면 쉽게 이해가 되기 때문에 훨씬 수월할겁니다.​당연히 저도 제한된 경험을 가지고 있는 개인이며 제가 제시한 로드맵이 모두에게 정답은 아닐 수도 있습니다. 그러나 앞으로 고도화된 현대사회에서 평생 직장이란 개념 없이 오랜 기간동안 경력을 이어나가야 하는 MZ 세대가 효율적이면서도 미래지향적인 공부를 해나가는 데에 약간의 도움이라도 되기를 바랍니다.​2023년 1월 17일​홍정모 드림

프로그래밍 언어프로그래밍공부순서프로그래머알고리즘문제풀이자료구조코딩테스트웹프로그래밍프로그래밍공부홍정모

Jason

파이썬 왈러스 연산자 소개(필요성, 사용 예시)

이번 글에서는 왈러스 연산자에 대해 알아보겠습니다.왈러스 연산자는 아무래도 새로운 기능을 위한 개념이라기 보다는 짧고 직관적인 코드 작성에 사용되는 개념이다보니 직접 예제를 보며 설명하겠습니다.왈러스 연산자는 비교적 최근인 3.8 버전에서 등장한 개념입니다.한 줄에서 변수에 값을 할당하면서 동시에 이 값을 표현식의 일부로 사용할 수 있습니다.바다코끼리 연산자를 통해 파이썬에서 할당 표현식을 가능하게 합니다.여러분이 오랜만에 소비를 좀 하려고 합니다. 우선 그래픽 카드도 좀 사고 싶고,,, 그 다음 순위로 책(2권 사야됨), 그 다음 순위로 키보드, 그 다음 순위로 만년필을 선호한다고 가정하겠습니다.이제 온라인 쇼핑몰 속을 돌아다니며 현재 예산에서 무엇을 살 수 있을 지 봅니다!예산 내에서 그래픽 카드를 살 수 있으면 사고, 아니면 책 2권 값을 낼 수 있는 지 확인합니다. 그래도 안 되면 순서대로 키보드, 만년필을 살 수 있는지 확인해야 합니다.능숙한 프로그래머인 여러분들은 이정도는 파이썬으로 자동화하실 수 있죠?my_budget = 1000000 gift_value = { # 그래픽 카드는 품절이랍니다 'gc': 1300000, 'book': 50000, 'keyboard': 55000, 'pen': 80000 } # 99999999 정도면 품절 상품도 구매할 수 있다고 칩시다. value = gift_value.get('gc', 99999999) if value <= my_budget: print('그래픽카드 구매') else: value = gift_value.get('book', 99999999) if value*2 <= my_budget: print('책 주문!') else: value = gift_value.get('keyboard', 99999999) if value <= my_budget: print('키보드 구매') else: value = gift_value.get('pen', 99999999) if value <= my_budget: print('만년필 구매') else: print('살 수 있는 게 없습니다.') print(f'{my_budget}에서 {value}만큼 사용하셨습니다.')의도대로 동작하지만;; 너무 복잡해보이는 코드입니다. 제가 코드를 잘못 짰다고요?elif 사용을 통해 직관적으로 보이게 만들 수 있지만, 그렇게 쉽게 줄여지지 않습니다. 항상 동일 환경 조건에서 비교를 하는 것이 아니며(book 같은 경우에는 *2 후 비교) 각 상품마다 나오는 메시지가 다르기 때문입니다.이제 왈러스 연산자가 나올 시간입니다. 이 코드에 왈러스 연산자를 적용해보겠습니다.my_budget = 1000000 gift_value = { # 그래픽 카드는 품절이랍니다 'gc': 1300000, 'book': 50000, 'keyboard': 55000, 'pen': 80000 } if (value := gift_value.get('gc', 99999999)) <= my_budget: print('그래픽카드 구매') elif (value := gift_value.get('book', 99999999) * 2) <= my_budget: print('책 주문!') elif (value := gift_value.get('keyboard', 99999999)) <= my_budget: print('키보드 구매') elif (value := gift_value.get('pen', 99999999)) <= my_budget: print('만년필 구매') else: print('살 수 있는 게 없습니다.') print(f'{my_budget}에서 {value}만큼 사용하셨습니다')위아래 코드의 차이가 잘 느껴지셨으면 좋겠습니다.지금 본 사례처럼 왈러스 연산자를 사용하면 코드를 더 직관적이게 만들 수 있습니다.조건문 내에서 값을 할당하고 바로 검사, 블록 안밖에서 사용까지 할 수 있으니 정말 편리하다고 느낍니다.다른 사용 예시를 보며 마무리하겠습니다.# 입력값을 받아서 검사하고 처리 if (n := int(input("Enter a number: "))) > 10: print("10보다 큰 수를 입력했군")# 튜플 언패킹을 사용한 예 a, b = (1, 2) print(a, b) # 출력: 1 2 # 튜플 타입에서 왈러스 연산자를 사용하려면 반드시 명시적으로 괄호를 해주거나 따로 언패킹, 패킹해야 됩니다. (a := 1, b := 2) print(a, b) # 출력: 1 2 원문: https://pinstella.com/writer/articles/7

프로그래밍 언어파이썬pythonwalruscleancode

[프로그래밍 언어의 고민] 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내생각언어공부고민

Devvy

Java의 실행원리 Deep Dive

Java는 다양한 운영체제에서 동일한 소스코드를 실행할 수 있는 "write once, run anywhere"의 철학을 지닌 프로그래밍 언어입니다. 국내에서 가장 활발히 사용되는 언어이며 제가 현업에서도 주로 사용하는 언어입니다. 이번 포스팅을 통해서 자바가 실행되는 원리에 대해 살펴보겠습니다. 블로그 원본 링크: https://code-run.tistory.com/61 프로그래밍 언어가 특정 운영체제 위에서 실행되기 위해서는 해당 운영체제가 이해할 수 있도록 코드가 작성돼야 합니다. 하지만 자바 개발을 하신 분들은 동일한. java 파일을 맥 OS, 윈도우 또는 Linux에서 실행한 경험이 있으실 겁니다. 정확히는 javac(자바 컴파일러)에 의해 컴파일된 .class 코드가 동일하더라도 해당 코드는 서로 다른 운영체제 위에서 실행될 수 있습니다. 이는 JVM 내부의 interpreter가 운영체제가 이해할 수 있는 코드로 변환해 주기 때문입니다. 즉 java는 운영체제가 이해할 수 있는 코드를 작성하는 책임을 프로그래머로부터 JVM으로 전이한 것으로 볼 수 있습니다. 운영체제별로 다운로드 받을 Java가 구분됨JDK, JRE, JVMJava 프로그램을 실행하기 위해서는 보통 JDK를 다운로드합니다. JDK와 항상 함께 등장하는 JRE 그리고 위에서 소개한 JVM에 대해 알아보겠습니다. JVM은 Java의 .class 파일이 실행될 수 있는 환경입니다. .class 파일의 bytecode를 host 운영체제 위에서 실행될 수 있는 환경을 제공합니다. JRE는 Java Runtime Environment의 약자로 자바 프로그램이 실행될 수 있는 최소환의 환경입니다. JRE는 JVM뿐 아니라 java 프로그램을 실행시키는데 필요한 라이브러리와 소스를 포함합니다. JDK는 Java Development Kit의 약자로 JRE를 포함합니다. 즉 JDK는 JRE와 JVM을 모두 포함하는 구조입니다. JDK는 javac, debugger 등 개발을 위한 도구를 포함합니다. JRE librariesJdk 설치와 함께 javac 등 설치Java의 실행 원리 .java 파일의 실행 흐름다음으로는 우리가 작성한 .java 파일이 어떻게 동작하는지 살펴보겠습니다. 우리가 작성한 .java 파일은 javac에 의해 .class 파일로 컴파일됩니다. 컴파일된 .class 파일은 JVM의 class loader에 의해 JVM의 메모리 영역에 로딩됩니다. JVM 메모리에 로딩된 후 execution engine의 interpreter에 의해 코드가 운영체제가 이해할 수 있는 기계어로 변환되고 이는 운영체제의 적절한 함수를 호출하여 필요한 로직을 수행합니다. 그럼 컴파일된 .class 파일이 어떻게 JVM 메모리에 로드되는지 상세히 살펴보겠습니다. Class Loader Subsystem Class loader subsystem의 주목적은 자바 프로그램을 실행시키기 위해 필요한 class를 찾아서 JVM의 메모리에 로드하고 연결(link) 하기 위함입니다. 필요한 class를 로드하고 연결하는 것 이외에 class variable을 초기화하는 역할도 수행합니다.Class loader subsystemLoad (Class Loaders) Java 프로그램 실행에 필요한 class를 jvm에 로드하기 위해서 class loader를 활용합니다. Class loader는 다음과 같이 목적에 맞게 역할이 나뉘어있습니다. Bootstrap class loader: JVM이 실행될 때 해당 java 프로그램 실행에 필요한 기본적인 class들을 로드합니다(rt.jar 파일 내의 java.lang 등). Extension class loader: Extension class들을 로드합니다(주로 jre/lib/ext에 위치). Extension class는 JDK가 추가적으로 제공하는 라이브러리입니다. Application class loader: classpath에 설정된 class를 로드합니다. 프로그래머는 실행시키고자 하는 java 프로그램의 classpath를 명시할 수 있습니다. // classpath를 직접 명시하는 방법 java -cp /path/to/classes:/path/to/jarfile MyMainClass java -classpath /path/to/classes:/path/to/jarfile MyMainClass // environment variable를 설정해서 classpath를 명시하는 방법 export CLASSPATH=/path/to/classes:/path/to/jarfile // system variable을 설정해서 classpath를 명시하는 방법 java -Djava.class.path=/path/to/classes:/path/to/jarfile MyMainClassLink Link 단계에서는 .class 파일 내의 symbolic references를 실제 메모리 주소로 변환하는 작업을 수행합니다. 단계별로 다음과 같은 작업을 수행합니다. Verify: .class 파일이 java 스펙에 맞는지 검증합니다. Bytecode format, version number 등을 확인하는 단계입니다. Prepare: 클래스와 static variable을 위한 메모리를 할당합니다. 중요한 점은 static variable이 default 값으로 초기화된다는 점입니다. 예를 들어 boolean 타입의 static 변수를 true로 설정하더라도 prepare 단계에서는 해당 변수는 false로 초기화됩니다. Resolve: symbolic reference를 실제 메모리 주소로 변환합니다.Symbolic reference란 우리가 코드를 작성하면서 사용한 class, field, method의 이름을 지칭합니다. Resolve 단계는 class, field, method 그리고 constant pool의 symbolic references를 실제 메모리 주소로 변환합니다. InitializeStatic initializer block을 실행합니다. 위 link의 prepare 단계에서는 static 변수가 default 값으로만 초기화됐지만 initialize 단계에서는 프로그래머가 지정한 값으로 static 변수가 설정됩니다. Initialize가 완료된 이후 main 메서드가 실행됩니다. Runtime Data Areas 다음으로는 JVM 메모리 구조에 대해 살펴보겠습니다.JVM runtime data area의 구조Method Area (Metaspace)Class level 정보를 저장하는 영역입니다. Class 정보, method 정보, static variable과 constant pool 정보를 저장합니다. Java 8부터는 기존의 method area의 한계를 극복하기 위해 method area가 제거되고 metaspace가 도입됐습니다. 기존의 method area의 경우 실행하고자 하는 java 프로그램에 클래스의 수가 너무 많을 때 "java.lang.OutOfMemoryError: PermGenspace" 에러를 발생할 확률이 컸습니다. 이는 method area가 heap의 일부 영역이었고 JVM에 할당된 메모리에 의해 최대 크기가 제한됐기 때문입니다. Metaspace는 JVM에 할당된 메모리가 아닌 system의 native 메모리를 활용하기 때문에 system의 가용 메모리에 제한을 받습니다. 따라서 method area를 활용하는 것보다 OutOfMemoryError가 발생할 확률이 낮아졌습니다. HeapRuntime에 생성된 object 또는 array를 저장하는 메모리 영역입니다. 모든 스레드에 의해 공유되는 영역으로 JVM 생성 시 할당됩니다. 자바 프로그램을 개발하면서 가장 많이 신경 쓰는 메모리 영역이기도 합니다. Managed 언어인 java이지만 memory leak이 발생할 수 있기 때문에 개발자는 사용하지 않는 객체의 참조가 정상적으로 해제되는지 신경 써야 합니다. 중요한 만큼 heap의 구조에 대해 상세히 살펴보겠습니다.VisualVM을 활용한 heap 분석Java의 heap 영역은 young과 old 영역으로 구분됩니다. Young은 말 그대로 최근에 생성된 객체들이 위치하는 영역이고 old 영역은 특정 threshold 이상의 기간 동안 살아남은 객체가 위치하는 영역입니다.  Young 영역은 또다시 eden, s0과 s1으로 구분됩니다. s0과 s1은 survivor의 약자입니다. 객체가 새로 생성될 때 해당 객체는 eden 영역에 할당됩니다. 그리고 eden 영역이 더 이상 객체를 저장할 수 없는 경우 minor gc(garbage collection)을 거쳐 s0 또는 s1의 영역으로 살아남은 객체를 이동시킵니다. 위 사진에서 보시면 s1에 저장된 객체가 없는 것을 확인할 수 있습니다. 다음 minor gc 때 eden과 s0 영역에서 살아남은 객체가 s1으로 이동하는데 이와 같은 플로우를 지니게 된 이유는 데이터 파편화(fragmentation)를 압축(compaction) 없이 해결하기 위해서입니다. 만약 s0과 s1이 동시에 사용된다면 gc에 의해 객체가 제거되면서 메모리 영역 중간중간이 비어 파편화 현상이 발생합니다. 이를 해결하기 위해서는 일정한 간격으로 압축이 필요하지만 JVM의 경우 s0 또는 s1 중 단 하나의 영역만 사용하기 때문에 별도의 압축과정이 필요하지 않습니다. Minor gc로 인해 s0과 eden에서 살아남은 객체가 s1으로 이동Young 영역에서 일정기간 이상 생존한 객체는 old 영역으로 승진(promote)됩니다. 만약 old 영역에 더 이상의 객체가 저장될 수 없는 경우 major gc(garbage collection) 수행합니다. 이때 application이 순간적으로 정지하는 stop the world 현상이 발생합니다. 사용하는 garbage collector의 특성에 따라 stop the world 현상이 상이할 수 있습니다. Heap과 관련돼서 중요한 설정으로는 -Xmx와 -Xms가 있습니다. Xmx 설정을 통해 heap의 최대 크기를 제한할 수 있고 Xms 설정을 통해 heap의 초기(최소) 크기를 설정할 수 있습니다. Xmx 값을 시스템 메모리보다 크게 설정하면 swap이 발생하여 시스템 전체적인 성능이 악화되거나 시스템이 다운될 수 있습니다. 따라서 Xmx값을 시스템 메모리보다 작게 설정하는 게 권고됩니다. 두 번째 권고 사항으로는 Xmx와 Xms 값을 동일하게 설정하는 것인데 이는 만약 두 설정값이 다른 경우 힙의 크기가 Xms에 도달했을 때 운영체제에게 추가 메모리를 요청함으로써 발생하는 오버헤드를 줄이기 위함입니다. 프로덕션 환경에서 운영해 보면 결국 JVM이 사용하는 메모리는 Xms를 넘어 Xmx를 향해 증가하기 때문에 Xms와 Xmx를 동일한 값으로 설정하는 것은 성능적인 관점에서 효율적일 수 있습니다.https://developer.jboss.org/thread/149559Why to set -Xms and -Xmx to the same value?| JBoss.org Content Archive (Read Only)In a production environment, if you monitor the GC data, you will notice that is a relatively short period of time (usually less than an hour), the JVM will eventually increase the heap size to the -Xmx setting. Each time the JVM increases the heap size itdeveloper.jboss.orgJava Stacks 메서드 실행 시 생성되는 function call frame을 저장하기 위해 사용됩니다. Function call frame에는 해당 메서드에서 생성된 지역 변수 등이 저장됩니다. Thread별로 stack 영역이 할당됩니다. 만약 이 영역에 너무 많은 데이터가 저장되는 경우 stack overflow error가 발생할 수 있습니다. 또한 JVM의 -Xss 옵션을 활용해서 stack의 최대 깊이를 제한할 수 있습니다. PC Registers Program counter을 저장하기 위해 사용되는 영역입니다. 특정 thread의 실행 위치를 표시하므로 각각의 thread별로 pc register가 생성됩니다. Native Method Stacks Thread에서 native method를 호출하는 경우, 즉 java 이외의 언어로 작성된 코드를 호출하는 경우 사용됩니다. Thread별로 생성됩니다. Execution Engine Execution engine은 JNI를 활용해 운영체제의 함수를 호출합니다. 이 과정에서 사용되는 각각의 컴포넌트에 대해 살펴보겠습니다. JNI(Java Native Interface)는 JVM에서 실행 중인 java 코드에서 다른 언어(C/C++)로 작성된 코드를 호출할 수 있도록 도와주는 프레임워크입니다. 자바의 기능만으로 수행할 수 없는 로직 또는 성능적인 측면에서 다른 언어를 사용하는 게 효율적일 때 사용됩니다. Execution engineInterpreter Bytecode를 읽어 native code(machin code)로 변환하는 역할을 담당합니다. 자주 실행되는 코드가 실행될 때마다 매번 interpreter에 의해 변환되면 비효율적입니다. 이러한 단점을 극복하기 위해 JVM은 JIT compiler을 활용합니다. JIT Compiler JIT은 just-in-time의 약자입니다. 즉 적절한 시기에 bytecode를 캐싱하고 최적화함으로써 자주 호출되는 코드가 interpreter에 의해 여러 번 변환되는 작업의 수를 줄일 수 있습니다. JIT compiler는 tiered compilation을 활용함으로써 단계별로 최적화하는 정도가 다릅니다. 현업에서 발생할 수 있는 문제 중 하나는 java 애플리케이션이 시작한 지 얼마 되지 않았을 때 코드가 충분히 캐싱 또는 최적화되지 않아 응답지연이 발생하는 점입니다. 이는 JVM warmup을 통해 해결할 수 있습니다. 카카오에서 JVM warmup을 통해 응답지연 현상을 어떻게 해결했는지 좋은 영상이 있어 공유드립니다. https://www.youtube.com/watch?v=CQi3SS2YspY&t=1sProfilerInterpreter에 의해 자주 변환되는 코드를 파악하는 데 사용됩니다. Garbage Collector 사용되지 않는 객체에 할당한 메모리를 해제하지 않으면 언젠가는 OutOfMemoryError에 의해 프로세스가 종료될 수 있습니다. 자바의 경우 참조되지 않는 객체에 할당된 메모리를 garbage collector을 활용해 해제합니다. 그럼 garbage collector은 어떻게 동작하는지 살펴보겠습니다. "Mark and Sweep"은 다양한 garbage collector들의 동작원리입니다. Mark 단계에서는 live 스레드에서 참조하는 객체들을 표시하고 sweep 단계에서 참조되지 않는 객체의 메모리를 해제합니다. Garbage collector의 특성에 따라 garbage collection 중에 애플리케이션이 동작하는 방식이 달라집니다. 다음으로는 어떤 garbage collector가 존재하는지 살펴보겠습니다. Serial GC Serial GC단일 스레드로 mark and sweep을 통해 garbage collection을 수행합니다. Parallel GC Parallel GCSerial collector와 동작원리는 유사하지만 여러 스레드를 활용해서 mark and sweep을 수행합니다. CMS(Concurrent Mark and Sweep) GC 애플리케이션의 중단 없이 mark and sweep이 가능한 garbage collector입니다. 애플리케이션 중단을 최소화하기 위해 사용됩니다. 물론 CMS라고 stop the world 현상이 없지는 않습니다. Initial mark 단계와 remark 단계에서는 stop the world 현상이 발생합니다.  CMS는 다음 순서로 동작합니다. 1. Initial mark: Old 영역의 참조되고 있는 객체를 표시합니다. 짧게나마 stop the world 현상이 발생할 수 있습니다. 2. Concurrent marking: 자바 애플리케이션 중단 없이 참조되는 객체들을 표시합니다. 3. Remark: concurrent marking 단계에서 놓친 참조되는 객체들을 표시합니다. Stop the world 현상이 발생할 수 있습니다. 4. Concurrent sweep: 참조되지 않는 객체의 메모리를 해제합니다. G1(Garbage First) GC G1 GCJava 9 이상부터는 기본 설정되는 GC로 큰 heap에서도 garbage collection에 소요되는 시간을 최소화하기 위해 개발된 garbage collector입니다. G1 GC는 heap을 작은 영역으로 나눠 각 영역에 대해 독립적인 garbage collection을 수행합니다. 여러 영역 중 garbage가 가장 많은 영역을 골라 우선적으로 garbage collection을 수행합니다. 추가로 G1 GC는 "Garbage-First Virtual Space"라는 자료구조를 활용해서 heap의 어떤 영역이 가장 많은 garbage를 가졌는지 추적합니다.  G1 GC는 다음 순서로 동작합니다. 1. Initial mark: 애플리케이션 중단 없이 현재 스레드에서 참조되고 있는 객체를 표시합니다. 2. Concurrent marking: Live  스레드로부터 참조되는 객체를 추가로 찾아 marking 하는 단계입니다. 3. Remark: 짧은 stop the world 현상이 발생할 수 있습니다. 이는 remark 단계에서 live 스레드로부터 참조되는 객체를 정확히 표시하기 위함입니다.4. Garbage collection: Heap에서 가장 많은 garbage를 가진 영역들에 대해 우선적으로 garbage collection을 수행합니다. 애플리케이션 중단 없이 수행됩니다. 5. Clean up: 파편화를 제거하기 위한 압축 등 garbage collection 이후 수행돼야 하는 작업을 수행합니다. 마무리 이번 포스팅을 통해 우리가 작성한 java가 어떻게 실행되고 java를 실행하는데 필요한 다양한 소프트웨어에 대해 살펴봤습니다. JVM은 자바뿐 아니라 Kotlin, Scala 등 다양한 언어의 실행환경이기 때문에 그 내부원리를 잘 이해하는 게 중요하다고 생각합니다. 

프로그래밍 언어JavaJVM

C++의 데이터 열거를 진행하는 방법에 대한 이야기

#include <iostream> using namespace std; /* const로 상수를 설정하다보면 */ const int SCISSORS = 1; const int ROCK = 2; const int PAPER = 3; /* 위에 작성된 것처럼 작성하기 마련이다. 하지만 의미 부여상으로 보면 저렇게 같은 성격을 가진 존재들끼리 하나로 묶는 개념이 필요하다. */ /* 그래서 나타난 개념이 바로 'ENUM'이다! */ enum ENUM_SPP { ENUM_SCISSORS = 1, ENUM_ROCK, ENUM_PAPER }; /* ENUM은 const에 비해 초기값을 설정하지 않아도 된다. (ENUM 과 const의 차이점) 그럼 ENUM 값은 지정을 하지 않을 경우 어떻게 되는가? 숫자를 지정 안하면 첫 값은 0부터 시작한다. (즉, ENUM_SCISSORS = 0; 이라는 의미이다.) 그 다음의 값들은 이전 값에 + 1이 진행된다. 여기서 처음 값을 정한다면? 그 다음 값들도 같이 이전 값에 + 1이 된 상태로 빌드가 된다. */ /* 그렇다면 여기서 const 와 ENUM의 명확한 쓰임새와 차이점에 대해 알아보자. 1. const 의 경우, 메모리에 저장될 때, 되지 않을때가 있다. 일반적으로 const는 빌드를 진행할 때, 메모리에 주소값이 지정되어 있지 않다. F5를 눌러 확인해보면 [식은 lvalue 또는 함수 지정자여야 합니다.]로 출력될 것이다. 하지만 int main() 안에서 auto a = &SCISSORS; 이런 경우, SCISSORS의 주소값을 auto a 에 넣어줬기에 메모리에 담겨 있는 모습을 확인할 수 있다. 이를 조금 심화적으로 다루어 보자면 int main() 밖(data 영역)에 선언한 const int ~~ 들은 메모리에 올라가지 않고 실행될 때, int main() 안에서 자신들이 쓰여진 부분에 자신들(변수)이 들어가는게 아니라 자신의 값(1,2,3)등이 바로 들어가는 경우가 생긴다. 또는 int main() 안(Stack 영역)에 선언한 const int ~~ 들은 stack 영역에 올라가서 동작 방식으 달라질 수 있다. 또는 int main() 밖(data 영역)에 선언한 const int ~~ 을 int main() 안에서 auto b = &ROCK; 처럼 선언한다면 이를 메모리에 할당하게 되는데, 이 방법은 위에서 알게된 방법과 다르게 메모리를 더 소모하는 방향으로 진행된다. (즉, 메모리의 과소모 = 낭비가 이루어질 수 있는 방법이다.) */ /* #이 붙은 개념 -> 전처리 지시문을 의미한다. 우리가 컴파일을 진행할 때, 1) 전처리 -> 2) 컴파일 -> 3) 링크 컴파일을 진행하기 전에 미리 컴파일 하기 쉽도록 거치는 단계 = 전처리 그럼 우리는 어디서 #을 사용하는 거지?! 우리는 CPP 파일을 만들 때, 항상 #include <iostream> 을 작성한다. iostream 의 내용을 전부 긁어서 여기에 붙여주세요!! 라는 의미로 받아들이면 된다. 위에서 간단한 예시로 알아본 결과 DEFINE_SCISSORS 로 작성된 부분을 1이라는 값으로 넣어서 진행해주세요!! 라는 의미로 쓰여진다고 보면 된다. */ #define DEFIME_SCISSORS 1 /* const와 ENUM은 우리가 정수만 사용했었다. 놀랍게도 #define은 정수도 출력할 수 있다. */ #define DEFIME_TEST cout << "HELLO, WORLD"<< endl; /* #define을 그렇게 추천하지 않는 이유가 있다고 한다..... 파일을 실행하면, 앞서 설명 했듯이 (우리가 컴파일을 진행할 때, 1) 전처리 -> 2) 컴파일 -> 3) 링크) 순서대로 진행이 된다. 그렇기에 전처리 단계에서 진행이 되는 #define을 디버깅해서 볼 때는, 결코 찾아볼 수 없다. 이유는 이미 컴파일을 진행할 당시 define에 정의한 변수들이 전부 define의 값으로 치환되어서 컴파일이 진행되었기에 이를 찾아볼 수 없는 것이다. 그렇기에 #define을 추천하지 않는 것이다.(물론 필요하고 적재적소인 부분에서는 사용하는 것이 맞다!) */ int main() { /* 그렇다면 여기서 ENUM에 대한 부분을 살펴보자 */ int input; if (input = ENUM_SCISSORS) { cout << "SCISSORS" << endl; } /* 위처럼 ENUM_SCISSORS 로 작성된 부분에 제대로 된 ENUM_SCISSORS의 값이 들어가게 된다. 이는 메모리를 낭비하는 일도 없으며 const로 선언한 data를 사용하는 방법보다 좋은 부분을 보여준다. 하지만 현업에서는 상황에 따라서 const를 사용하는 경우도 있다보니 이렇게 간단하게 개념을 익히고 가자. */ }

프로그래밍 언어학습일기

하얀종이개발자

Java 스터디 회고록 [김영한의 자바 입문편] with 성빈클럽

회고록 김영한의 자바 입문 - 코드로 시작하는 자바 첫걸음 스터디2024년 10월 27일 → 2024년 11월 8일 목표김영한의 자바 입문 - 코드로 시작하는 자바 첫걸음 강의를 진도에 맞게 듣고 인증각 섹션별 미션 문제를 수행하고 정리하여 공유  목표 수행 여부목표 1 : ✅목표 2 : ✅ Keep요즘 기본기를 튼튼히 하자!라는 방향으로 공부하고 있기때문에 전체 복습하자는 생각으로 스터디에 참여하게 되었습니다.사실 자바를 공부했었고, 실무에서도 사용했었기 때문에 자바를 처음부터 다시보는게 의미가 있을까하는 생각이 있었어요. 그래도 기본기를 복습하자라는 생각으로 꾸준히 진도에 맞게 학습하고, 미션을 모두 수행하다보니 조금은 애매하게 알고 있었던 지식들이 더 확실하게 정립될 수 있었던 것 같아요. 강의 내용 뿐만아니라 자바에 대해 궁금한 부분이 생기면 따로 찾아보기도 하면서 자바안에 수많은 고민들과 개념들이 녹아져 있다는 것을 느껴서 자바를 더 좋아하게 된 것 같기도 하네요.무튼 8일간의 시간동안 13시간의 진도인증 + 미션 풀이 + 공유를 모두 완주하게 되어 기쁘고 뿌듯합니다. Problem조금 제 자신에게 아쉬웠던 부분은 알고 있는 내용을 말로 혹은 글로 풀어서 정리할때 너무 길어지는게 있었던 것 같아요. 아는 것을 좀 더 핵심적으로 간추려서 정리하는 것을 계속 연습해야 할 것 같아요.그리고 스터디를 진행하면서 성빈님(스터디 장)이 직접 미션 문제를 내주시고 리뷰까지 해주시는 방식이 저한테는 매우 편하고 좋았지만 성빈님이 너무 고생하시기도 하고, 스터디원끼리 서로 내용에 대한 생각을 많이 공유하지 못한 부분이 조금 아쉬웠던 것 같기도해요. 빠듯한 일정이라 어쩔수 없기도 했지만요. Try다음 스터디는 자바 기본편 이어서 자바의 꽃인 객체지향 내용을 다루게 될 텐데, 좀 더 꼼꼼히 정리하면서 개념을 정립하고 싶어요. 그리고 스터디의 포맷도 변경될 수 있다고 하여 더 적극적으로 참여해서 저한테도 도움이되고 다른 분들께도 도움이 될 수 있도록 하겠습니다. 성빈님 특히 너무 고생많으셨고, 다른분들도 고생많으셨습니다. 여러모로 많이 배웠습니다.고급자바쟁이까지 끝까지 고고 !! 🙌

프로그래밍 언어김영한의자바입문코드로시작하는자바첫걸음자바스터디성빈클럽

[인프런 워밍업 클럽 BE + ]람다식/스트림 추가 학습하기!

3일차 과제는 조사 과제로, 함수형 인터페이스/람다/스트림 등의 광범위한 키워드를 알아봐야 했다. 검색하면 할수록 부족한 내 자신이 느껴졌다😂. 람다식의 문법 체계와 스트림 API를 문서로만 보았을 때는 나름 할만한데? 라는 생각이 들다가도, 직접 코드를 접하면 이해가 빠릿하게 되지 않는다니... 역시 나는 보는 것 만으로는 50프로도 흡수를 못하는 것 같다. 직접 예제를 만들어보기에는 개념도 겨우 잡는 학생이 시험 문제를 낸다는 느낌이기에, 어떻게 효과적으로 코드 작성하는 걸 공부할 수 있을까? 라는 고민에 빠지다 문득 생각이 들었다. 람다식과 스트림이라는 개념 자체를 몰랐을 적, 프로그래머스에서 나는 몇 줄에 거쳐 해결한 문제를 누군가가 스트림으로 한 줄 만에 풀이를 끝내는 걸 본 기억이... 그래서 나도 그 기억에 따라 프로그래머스의 기초 문제를 람다식과 스트림 API을 통해 푸는 연습을 해보기로 했다!연습 범위는 lv0~lv1. 두 개념을 사용할 수 있는 문제들만 임의로 골라서 꾸준히 풀기!❗문제 전문이나 정답 코드는 작성하지 않는다. 어디까지나 개인 연습용이라 최고 효율적인 답을 기대하고 풀이하지 않습니다. 문제가 막힐 때, https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html 등의 문서 참조'다른 사람의 풀이' 보기!(최후 수단) 1.IntStream을 이런 방식으로도 사용할 수 있다는 생각이 미처 닿지 못해, 부끄럽게도 첫 문제부터 다른 사람의 풀이를 참고하였다. 이번 키워드 메서드를 한 번 보자.IntStream.range(0, strArr.length) .mapToObj(...) .toArray(...);IntStreamrange(n1, n2) - [n1,n2) 까지 순서대로 정렬된 연속된 값을 가진 IntStream 반환[n1,n2]의 경우에는 rangeClosed(n1, n2)를 사용한다.mapToObj(IntFunction<? extends U> mapper) - 스트림 요소에 주어진 함수를 적용한 결과로 구성된 객체 값 반환 정확성 테스트 결과는 위와 같다.이번 문제는 일반적인 반복문을 사용했을 때 압도적으로 빨랐다. 반복문 처리 하였을 때의 정확성 테스트 결과 이미지이다. 

프로그래밍 언어개인학습

코어자바스크립트 강의정리 - 1. 데이터 타입

1. 데이터 타입  자바스크립트 데이터 종류 (기본형, 참조형) 기본형 데이터 : 정적할당 참조형 데이터 : 동적할당 Why? 기본형 데이터의 할당 방식 var a = 1 이라고 하였을때 자바스크립트 내부적으로는 var a; a = 1; 로 처리 따라서 임의의 메모리 주소(1004) 에 (이름 : a, 값 : 없음) 저장 후 다른 임의의 메모리 주소(5000)에 데이터 1 을 저장. 그리고 메모리 주소 1004 의 값에 메모리 주소 5000을 저장하여  (이름 : a, 값 : @5000) 으로 만든다.   참조형 데이터의 할당방식 var obj= { a : 11,  b : 11} 이라고 하였을때 메모리주소 1004에 (이름 : obj, 값 : 없음) 저장, 임의의 메모리 주소 5000에  @7000~@70?? 까지의 메모리 주소 데이터 저장(배열이나 객체는 값이 여러가 들어가기 때문에 미리 공간을 확보해 둠) @7000 에 정적 할당 방식과 같이 (이름 : a , 값 : 없음) 저장, 임의의 메모리 주소 @5001에 데이터 11 저장. @7000 의 값을 @5001 로 저장. @7001 에 (이름 : b, 값 : @5001) 저장. @1004의 값에 @5000 저장.   결국 어떤 데이터를 저장할때 기본형이나 참조형이나 가장 작은 데이터의 단위(위의 예시에서 1, 11 과 같은 값)를 중복하지 않고 공유해서 가지고 있고, 그 주소를 참조한다. 그렇기 때문에 const obj 를 사용하여도 obj 내부의 값을 바꿀수 있는 것. 같은 원리로 var obj2 = obj ; obj2.a=99; 를 하고 나면 obj나 obj2나 @5000이 가리키고 있는 @7000~@70?? 의 값을 받아오기 때문에 obj.a 도 99의 값을 갖는다.   번외 : 그럼 왜 자바스크립트는 가장작은 데이터의 단위를 굳이 따로 저장할까? var a = 1을 하였을때 @1004 (이름 : a, 값 :1 ) 을 하는 것이 할당 속도면에서 더 효율적이지 않을까(장점1)? 라는 의문이 생길 수 있다. 그러나 큰 값이 여러번 저장될때 예를들어 "매우매우긴문자열" 이라는 문자열을 매번 직접 값을 저장하는 방식을 사용하면 하나의 문자열을 계속해서 참조하는 방식에 비해 메모리를 더 차지하게 된다(단점1). 심지어 값을 비교하는 작업이 있다면 매우 긴 문자열의 값을 매 , 우, 매, 우,  긴, 문, 자, 열 로 하나하나 비교해야 해서 하나의 메모리 주소값만 비교하는 방식에 비해 오래걸린다(단점2). 현재 자바스크립트가 사용하고 있는 방식은 값을 한번 할당할때는 느리지만(단점1), 비교에 비용이 들지 않는다(장점1). 또한 할당한 값이 여러군데에서 중복해서 사용될 때에 메모리의 낭비가 적다(장점2). 그렇기때문에 단점보다 장점이 많은 현 자바스크립트의 방식을 자바스크립트는 채택한 것이다.  

프로그래밍 언어자바스크립트

[삽질] 알고도 당하는 Optional의 함정

Java로 진행중인 개인 프로젝트에서 Optional을 요긴하게 쓰고 있다. Null을 사용하였다면 Null check를 일일이 확인하고 테스트하면서 애로사항이 생겼을텐데, Optional 타입을 쓰면서 Null에 대한 확인이 강제되다보니 타입 에러를 따라가서 고쳐주기만 하면 되어서 나름대로 만족하면서 코딩을 하고 있다. 다만 Optional에도 함정이 있었으니... 그렇잖아도 Optional 바르게 쓰기 등의 글들을 보면서 조심해야겠다고 생각하고 있었는데 읽었고 아는 내용인데도 실수하여 이렇게 글을 남기게 되었다. 문제의 코드를 소개하자면 다음과 같다. 이렇게 보면 뻔할 수도 있겠지만 많은 코드 사이에 이게 끼어 있었을 때는 너무 자연스러워서 눈에 띄지 않았던 것 같다. `catRepo`는 카테고리 Entity를 데이터베이스에 저장하는 Spring Data JPA의 Repository이다. // 안중요한 부분들 과감히 생략 @Annotations public class OscillatorService { private final CategoryRepository catRepo; public Category findOrSave(Category category) { return catRepo .findByRuleAndPeriodAndSparkType( category.getRule(), category.getPeriod(), category.getSparkType()) .orElse(catRepo.save(category)); } } 위 코드에서 잘못된 점은 바로 `Optional::orElse`이다. 뭔가 읽기에는 Entity를 찾아보고 Entity가 있으면 그걸 쓰고 없으면 새로 저장하고 쓰라는 것 같지만, 실제로는 `Optional::orElse` 안의 값은 Optional 안의 값에 상관없이 evaluation된다. 본인의 경우 역시 값을 찾았는데도 불구하고 `catRepo.save(category)`가 실행해서 오류가 발생하였다. 그러면 위를 해결해주려면 어떻게 하면 좋을까. `Optional::orElseGet`을 사용하여 다음과 같이 바꾸면 해결된다. // 안중요한 부분들 과감히 생략 @Annotations public class OscillatorService { private final CategoryRepository catRepo; public Category findOrSave(Category category) { return catRepo .findByRuleAndPeriodAndSparkType( category.getRule(), category.getPeriod(), category.getSparkType()) .orElseGet(() -> catRepo.save(category)); } } 꼭 side effect가 있거나 계산이 시간이 많이 걸리는 작업이 아니더라도 그냥 `Optional::orElse` 대신 `Optional::orElseGet`을 쓰는 것이 마음이 편한 것 같아서 앞으로는 기본적으로 `Optional::orElseGet`을 쓰기로 마음먹었다.

프로그래밍 언어Java

홍정훈

[인프런 워밍업 클럽 2기 클린코드&테스트코드] 4주차 발자국

출처: Practical Testing: 실용적인 테스트 가이드1. 학습 내용 요약Persistence LayerData Access의 역할비즈니스 가공 로직이 포함되어서는 안됨Data에 대한 CRUD에만 집중한 레이어Business Layer비즈니스 로직을 구현하는 역할Persistence Layer와의 상호작용(Data를 읽고 쓰는 행위)를 통해 비즈니스 로직을 전개 Presentation Layer외부 세계의 요청을 가장 먼저 받는 계층파라미터에 대한 최소한의 검증을 수행MockMvcMock(가짜) 객체를 사용해 스프링 MVC 동작을 재현할 수 있는 테스트 프레임워크트랜잭션에 대한 이야기readOnly = true읽기 전용CRUD에서 CUD 동작 X / only ReadJPA에서 CUD 스냅샷 저장, 변경감지 X → 성능 향상CQRSCommand와 Read의 분리두 동작이 서로 영향을 주지 않게 분리  Stubbing컴포넌트를 MockBean 처리하고 동작에 대한 가짜 행위를 정의하는 것Test Double Dummy아무 것도 하지 않는 깡통 객체Fake단순한 형태로 동일한 기능은 수행하나, 프로덕션에서 쓰기에는 부족한 객체Stub테스트에서 요청한 것에 대해 미리 준비한 결과를 제공하는 객체그 외에는 응답하지 않음SpyStub이면서 호출된 내용을 기록하여 보여줄 수 있는 객체일부는 실제 객체처럼 동작시키고 일부만 Stubbing할 수 있음Mock행위에 대한 기대를 명세하고그에 따라 동작하도록 만들어진 객체 한 문단에 한 주제 논리 구조가 들어가지 않는 형태로 구성하는 것이 좋음Parameterize Test케이스 테스트 코드를 각각 따로 작성완벽하게 제어하기제어할 수 없는 것들은 상위 계층으로 분리해서 테스트 가능하게테스트 환경의 독립성을 보장하자 테스트 간 독립성을 보장하자테스트 간에는 순서가 없어야 함공유 자원을 사용하는 경우 테스트 간 순서가 생길 수 있음한 눈에 들어오는 Test Fixture 구성하기Fixture고정물, 고정되어 있는 물체테스트를 위해 원하는 상태로 고정시킨 일련의 객체 중복으로 세팅하는 경우에는 셋업에서 구성을 하면 어떨까공유 객체를 사용하는 것과 동일한 효과를 가져올 수 있음 테스트와 결합도가 생김코드가 길어지면 의도가 한 눈에 보이지 않을 수 있음 data.sql 같이 셋업을 다른 파일에 옮기면 픽스쳐의 파편화가 일어날 수 있기에 지양빌더를 생성할 땐 파라미터에 테스트에서 필요한 것만 남겨놓자클렌징DeleteAll() Vs. DeleteAllInBatch()DeleteAll()은 각 엔티티를 개별적으로 삭제하며, 삭제 전 select 쿼리를 실행대신 지우는 순서가 상관없어질 수 있음물론 항상 되는 것은 아님DeleteAllInBatch()는 단일 쿼리로 모든 데이터를 삭제하여 더 효율적대량의 데이터를 처리할 때는 DeleteAllInBatch()가 성능상 유리할 수 있음 @DynamicTest어떠한 시나리오를 기반으로 상태를 공유하면서 테스트를 진행할 수 있음테스트 환경 통합테스트 환경을 통합하여 테스트 성능 최적화환경이 다르면 서버가 테스트마다 새로 떠야함  Rest Docs Vs. SwaggerRestDocs장점테스트를 통과해야 문서가 만들어짐 (신뢰도 증가)프로덕션 코드에 비침투적단점코드 양이 많음설정 어려움Swagger장점적용이 쉬움문서에서 바로 API 호출을 수행해볼 수 있음단점프로덕션 코드에 침투적테스트와 무관하기 때문에 신뢰도가 떨어질 수 있음2. 미션 회고Day 15. Layered Architecture 구조의 레이어별 특징을 정리하고, 어떻게 테스트 하면 좋을 지 정리하는 미션이었다. Persistence Layer, Business Layer, Presentation Layer 역할에 대하여 다시 정리해보고, 레이어의 특징에 따른 테스트 코드 예시를 정리해볼 수 있는 기회였다.미션 링크: https://www.notion.so/Day-15-1275cf1d569e8067b43ef2245e1f74ecDay 18. @Mock, @MockBean, @Spy, @SpyBean, @InjectMocks의 차이를 정리하고, 주어진 테스트 코드를 리팩토링하는 미션이었다. 강의 시간에 다루었던 어노테이션들에 대해서 자세히 알아볼 수 있었다. 또한, 코드를 리팩토링하며 강의에서 배웠던 내용들을 응용해 볼 수 있었다.미션 링크: https://www.notion.so/Day-18-12a5cf1d569e804e8012f4021394b5bd 3. KPTKeep시험 기간이 겹쳤지만, 과제와 진도를 밀리지 않고 잘 수행하였다. Try 학습했던 내용들을 앞으로 잘 활용하여, 한층 더 성장한 개발자가 되어야겠다.4. 느낀점4주간의 워밍업 클럽 일정이 마무리되었다. 처음 워밍업 클럽을 알게 되었을 때, 테스트에 대해 깊이 있게 학습할 수 있는 좋은 기회라고 생각하여 신청했다. 그러나 클럽 활동을 통해 다양한 지식과 기술을 배울 수 있었을 뿐만 아니라, 다른 참가자들의 코드와 질문들을 보면서 새로운 시각을 갖게 되고, 많은 자극을 받을 수 있었다. 다음 워밍업 클럽이 열린다면, 한번 더 참가하고 싶다.

프로그래밍 언어

홍정훈

[인프런 워밍업 클럽 2기 클린코드&테스트코드] 3주차 발자국

출처: Practical Testing: 실용적인 테스트 가이드1. 학습 내용 요약수동으로 테스트할 경우누락되는 케이스 발생 늦은 피드백유지보수 어려움소프트웨어 신뢰도 낮아짐테스트 코드를 작성하지 않는다면변화가 생기는 매순간마다 발생할 수 있는 모든 Case를 고려해야 함변화가 생기는 매순간마다 모든 팀원이 동일한 고민을 해야 함빠르게 변화하는 소프트웨어의 안정성을 보장할 수 없음테스트 코드가 병목이 된다면프로덕션 코드의 안정성을 제공하기 어려움테스트 코드 자체가 유지보수하기 어려운, 새로운 짐이 되어버림잘못된 검증이 이루어질 가능성이 생김올바른 테스트 코드는자동화 테스트로 비교적 빠른 시간 안에 버그 발견 가능, 수동 테스트에 드는 비용 절약소프트웨어의 빠른 변화 지원 단위 테스트작은 코드 단위(클래스 or 메서드)를 독립적으로 검증하는 테스트검증 속도가 빠르고, 안정적 테스트 케이스 세분화해피 케이스예외 케이스경계값 테스트 → 범위(이상, 이하, 초과, 미만), 구간, 날짜 등테스트하기 어려운 영역을 구분하고 분리하기현재 일시와 같이 테스트가 어려운 코드가 들어오는 경우전체가 테스트하기 어려워질 수 있음테스트가 어려운 부분을 외부로 분리 테스트하기 어려운 영역관측할 때마다 다른 값에 의존하는 코드현재 날짜/시간, 랜덤 값, 전역 변수/함수, 사용자 입력 등외부 세계에 영향을 주는 코드표준 출력, 메시지 발송, 데이터베이스에 기록하기 등테스트하기 좋은 함수순수함수 (pure functions)같은 입력에는 항상 같은 결과외부 세상과 단절된 형태테스트하기 쉬운 코드Test Driven Development프로덕션 코드보다 테스트 코드를 먼저 작성하여 테스트가 구현 과정을 주도하도록 하는 방법론TDD의 3단계Red실패하는 테스트 작성Green테스트 통과최소한의 코딩 Refactor구현코드 개선테스트 통과 유지선 테스트 작성, 후 기능 구현복잡도가 낮은, 테스트 가능한 코드로 구현할 수 있게 해줌쉽게 발견하기 어려운 엣지 케이스를 놓지지 않게 해줌구현에 대한 빠른 피드백 가능과감한 리팩토링 가능 BDD 스타일로 작성Behavior Driven DevelopmentTDD에서 파생된 개발 방법함수 단위의 테스트에 집중하기보다, 시나리오에 기반한 테스트케이스(TC) 자체에 집중하여 테스트 BDD ToolGiven시나리오 진행에 필요한 모든 준비 과정 (객체, 값, 상태 등)When시나리오 행동 진행Then시나리오 진행에 대한 결과 명시, 검증통합 테스트여러 모듈이 협력하는 기능을 통합적으로 검증일반적으로 작은 범위의 단위테스트만으로는 기능 전체의 신뢰성 보장 불가풍부한 단위 테스트 & 큰 기능 단위를 검증하는 통합 테스트2. 미션 회고Day 12. 주어진 코드에 대하여 단위 코드를 작성해보는 미션이었다. 직접 테스트 코드를 작성해보는 건 이번이 처음이었다. 이번 미션에서 어려웠던 부분은 테스트하기 어려운 부분을 통제하는 것이었다. 예를 들어 static으로 클래스 내부에 선언된 Scanner의 경우 입력값을 두 번 이상 넣기가 어려웠다. Scanner를 변수로 빼는 부분도 고려해볼 수 있었지만, 원래 코드의 의도를 테스트때문에 해치는 것 같아 망설이게 되었다. 다행히 강의 뒷편에서 이러한 고민을 다루는 부분이 있는 것 같아 학습 후에 이번 미션에서 고민했던 것들을 확인해 볼 수 있을 것 같다. 3. KPTKeep미션을 해결하고 다른 사람들의 코드들을 보면서 놓쳤던 케이스들을 확인하였다.Problem테스트 환경을 제어하는 부분들 중 어려운 것이 많았다.Try 강의 후반부에서 지금까지 생긴 궁금증들을 많이 다루고 있어서, 나중에도 기억할 수 있도록 정리하면서 들어야겠다.4. 느낀점3주차 테스트 코트 강의가 시작되었다. 워밍업 클럽에 참가한 이유 중에 하나이기도 하다. 이전에 서비스 코드는 작성해 본 적이 있지만 단위 테스트, 통합 테스트는 작성해 본 적이 없었다. 테스트를 작성하지 않았던 이유는 강의 초반에서 강사님이 언급했던 것처럼 '귀찮음'이 가장 컸었다. 그러나 여러 테스트 코드를 작성하고, 전체 테스트를 돌려 모두 성공했을 때의 기쁨은 그 귀찮음을 충분히 보상해 주는 것 같다. 또한, TDD 방식으로 구현을 연습해보았는데, 테스트를 먼저 작성하고 코드를 작성하는 방식이 다소 낯설었다. 그러나 기존의 구현 우선 방식보다 확실히 여러 엣지 케이스를 떠올리기가 쉬웠다. 이 방식을 습관화하여 자연스럽게 활용할 수 있도록 노력해야겠다.

프로그래밍 언어

홍정훈

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

출처 : Readable Code: 읽기 좋은 코드를 작성하는 사고법 - 박우빈1. 학습 내용 요약주석의 양면성주석이 많다그만큼 비즈니스 요구사항을 코드에 잘 녹이지 못함코드를 설명하는 주석을 쓰면, 주석에 의존 → 적절하지 않은 추상화 레벨을 갖게 되어 낮은 품질의 코드 생성그럼 언제써야 하나리팩토링 할 때 난관 중 하나는 히스토리를 전혀 알 수 없는 코드후대에 전해야 할 “의사 결정의 히스토리”를 코드로 표현 할 수 없을 때 주석으로 설명모든 표현 방법을 총동원해 코드에 의도를 녹여냈음에도 불구하고 전달해야 할 정보가 남았을 때 사용작성 주의점자주 변하는 정보는 최대한 지양관련 정책이 변하거나 코드가 변경되었다면, 주석도 잊지 않고 함께 업데이트주석이 없는 코드보다, 부정확한 주석이 달린 코드가 더 치명적변수와 메서드 나열 순서변수는 사용하는 순서대로 나열 객체 입장에서도 생각해보자 외부 세계에 내가 어떤 기능을 제공할 수 있는지를 드러냄공개 메서드를 상단에 배치하는 것을 선호물론 정해진 답은 절대 아님!공개 메서드끼리도 기준을 배치, 비공개도 마찬가지상태 변경 >> 판별 ≥ 조회 메서드공통으로 사용하는 메서드인 경우 적당한 곳에 배치패키지문맥으로써의 정보를 제공 가능패키지를 쪼개지 않으면 관리가 어려워짐패키지를 너무 잘게 쪼개도 관리가 어려워짐대규모 패키지 변경은 팀원과의 합의를 이룬 시점에 해야 함오버엔지니어링필요한 적정 수준보다 더 높은 수준의 엔지니어링Ex> 구현체가 하나인 인터페이스, 너무 이른 추상화2. 미션 회고Day 7 미션. 이번 미션은 스터디카페 좌석 예약 시스템 코드를 리팩토링하는 것이었다. 추상화, 일급컬렉션 등 앞선 강의에서 배웠던 개념들을 적용해 볼 수 있었다. 리팩토링 과정에서는 추상화레벨에 대해서 많이 생각하였다. 코드를 처음 보는 사람도 코드가 어떤 구조로 동작하고 있는지 메서드 이름 등으로 최대한 파악할 수 있도록 하였다. 그러나 이전에 경험이 많지 않았기에 추상화를 하는 과정은 쉽지 않았다. 레벨을 높이자니 내용이 날아가는 것 같고 그 반대는 오버엔지니어링이 아닐까하는 고민을 하게 되었다. 그래도 Order와 같은 새로운 도메인 개념 도출, 일급 컬렉션 등 여러 개념들을 십습해 볼 수 있는 기회였다.3. KPTKeep미션을 해결하고 다른 사람들의 코드들을 보면서 여러 관점들을 학습하였다.Problem강의 후반부에서 다루는 개념들은 앞 부분에 비해서 난이도가 조금 더 있었던 것 같다.Try강의를 들으면서 정리해 놓은 내용들을 복습하는 시간을 가져야겠다.앞으로 코드를 짜면서 강의를 통해 배웠던 개념들을 잊지 않고 잘 적용해야겠다.4. 느낀점2주간의 클린코드 강의가 마무리되었다. 강의를 통하여 실습도 해보고, 다른 사람들의 코드도 계속해서 보다 보니 확실히 시작할 때보다 코드를 보는 눈이 생긴 게 체감이 되었다. 강의를 통해 여러 개념들을 공부하면서, 이전에 코드 짜던 사람들이 이러한 구조를 생각해 내는데 얼마나 많은 고민을 했을 까 생각해보게 되는 기회였다. 그리고 이 고민의 결과물들을 강의를 통해 한번에 정리하고 실습도 해볼 수 있어서 좋았다.어느 정도 프로그래밍을 해본 사람들이라면 강의에서 여러 고민의 흔적들을 느낄 수 있을 것이라 생각한다. 또한, 이제 막 코딩을 하고 있는 사람이라면 좋은 습관을 들이는데 좋을 것 같다. 개념을 배웠다고 해서 당장 내일 짜는 코드에서 바로 나타나지는 않듯, 한 번 공부해두면 클린코드를 생각해보는 시간이 모이고 모여 한층 더 성장한 개발자가 될 수 있을 것이다.

프로그래밍 언어

홍정훈

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

출처 : Readable Code: 읽기 좋은 코드를 작성하는 사고법 - 박우빈1. 학습 내용 요약이름 짓기추상적 사고를 기반으로 함단수와 복수를 구분이름 줄이지 않기은어/방언 사용하지 않기좋은 코드를 보고 습득하기 메서드 이름메서드 구현에 대한 부분을 추상화해서 중요한 내용을 가지고 있어야 함파라미터와 연결지어 더 풍부한 의미를 전달 할 수 있음 파라미터타입, 개수, 순서를 통해 의미 전달 반환타입메서드 시그니처에 납득이 가는, 적절한 타입의 반환 값void 대신 충분히 반환할 만한 값이 있는지반환 값이 있다면 테스트에 용이 추상화 레벨하나의 세계 안에서는 추상화 레벨이 동등해야 함읽는 사람으로 하여금 자연스럽게 읽히도록 함 Early return일찍 리턴 할 수 있는 경우에는 빠르게 리턴하자! Depth 줄이기무조건 1 depth로 만들어라 → X추상화를 통한 사고 과정의 depth를 줄이는 것이 중요 사용한 변수는 가깝게 선언하기 공백라인복잡한 로직의 의미 단위를 나누어 보여줌으로써 읽는 사람에게 추가적인 정보 전달 부정어! 를 통하여 조건을 뒤집을 경우 사고 과정이 두 번 일어나게 됨한 번에 이해할 수 있게 메서드명 자체에 부정어구를 녹이는 방법을 사용부정어구를 쓰지 않아도 되는 상황인지도 체크 예외 처리예외가 발생할 가능성 낮추기사용자에게 보여줄 예외 vs 개발자가 보고 처리해야 할 예외  새로운 객체를 만들 때 주의할 점1개의 관심사로 명확하게 책임이 정의되었는지생성자, 정적 팩토리 메서드에서 유효성 검증이 가능setter 사용 자제데이터는 불변이 최고만약 변경해야하는 경우 set~ 보다는 update~와 같이 의도를 드러내는 네이밍 이용getter 사용도 자제반드시 필요한 순간에만 생성객체에게 공손하게 물어보자!필드의 수는 적을수록 좋음불필요한 데이터가 많을 수록 복잡도와 대응할 변화가 증가상속보다는 조합을 사용하자상속은 수정이 어렵다 → 부모와 자식의 결합도가 높음조합과 인터페이스를 활용하는 것이 유연한 구조상속을 통한 코드의 중복 제거가 주는 이점보다, 중복이 생기더라도 유연한 구조 설계가 주는 이점이 더 큼 Value Object도메인의 어떤 개념을 추상화하여 표현한 값 객체값으로 취급 받기 위해선 불변성, 동등성, 유효성 검증 등을 보장해야 함 VO vs EntityEntity는 식별자가 존재, 식별자가 아닌 필드의 값이 달라도, 식별자가 같으면 동등한 객체로 취급VO는 식별자 없이, 내부이 모든 값이 다 같아야 동등한 객체로 취급  일급 컬렉션필드가 반드시 하나!컬렉션을 추상화하며 의미를 담을 수 있고, 가공 로직의 보금자리가 생김getter로 컬렉션을 반환할 일이 생긴다면, 외부 조작을 피하기 위해 꼭 새로운 컬렉션으로 만들어서 반환  Enum상수의 집합, 상수와 관련된 로직을 담을 수 있는 공간특정 도메인 개념에 대해 종류와 개념을 명시적으로 표현 가능  2. 미션 회고미션 1. 추상과 구체의 예시를 적어보는 과제였다. 나는 '호흡'이라는 추상 개념을 구체화 해보기로 했다. 우리 몸이 구체적으로 어떻게 호흡이라는 과정이 일어나는 지 서술해보았다. 미션을 통해 추상화 레벨에 대해 생각해보고, 추상화가 얼마나 중요한지 느끼게 되는 계기가 되었다.미션2. 섹션 3에서 배운 내용을 기반으로 읽기 좋은 코드로 리팩토링하는 과제였다. 강의 이전에 문제 코드를 미리 봤었는데, 강의를 보고 문제 코드를 다시 보니 처음에 캐치하지 못했던 개선점들이 보이는 게 신기했다. 문제는 문제점을 우선 파악하고, 개선 방안을 생각해본 뒤, 코드로 직접 수정하며 해결하였다.미션 풀이 과정은 노션에 따로 정리하였다 https://www.notion.so/Day-4-1145cf1d569e80139747c0781f448f433. KPTKeep코드를 보고 이번에는 어떤 방식으로 리팩토링을 해야 할지 고민하면서 강의를 들었다Problem강의가 조금 밀리니 미션을 해결하는 과정에서 고민할 시간을 많이 가지지 못했다.Try강의를 마감일자에 맞추어서 급하게 듣는 것이 아닌 조금 여유를 가지고 듣는 것이 좋겠다.다른 분들이 제출한 코드들을 내 코드와 비교하는 시간을 가져야겠다.4. 느낀점 이번 주는 잘못 들이고 있던 습관들을 고칠 수 있었다. 부정어, 줄임말 등 정말 많은 곳에서 실수를 하고 있었다. 예를 들어, 무언가 객체를 만들면 거의 조건 반사적으로 @Getter, @Setter를 적곤 했다. 이전에 Setter는 조심해서 사용해야 한다는 글을 본 적이 있어서 이제는 잘 사용하지 않지만 Getter는 거리낌 없이 사용했다. 강의를 보고 나니 Getter도 정말 최후에 생성해야하고, 객체에서 Getter로 변수를 꺼내다 쓰는 것이 아닌 요청하는 습관이 바람직 하다는 것을 알게 되었다. 돌아보면 당장 눈앞에 보이는 코드 짜기에 급급했지, 후대에 다른 개발자가 내 코드를 볼 것이라고 생각하고 코드를 짰던 기억은 정말 손에 꼽았던 것 같다. 이번 워밍업 클럽을 통해 Readable한 코드에 대해 항상 고민하는 개발자가 되었으면 좋겠다.

프로그래밍 언어

jin02019

인프런 워밍업 클럽 2기(클린코드/테스트 코드)_1주차 발자국

1주 회고 (KPT 템플릿 활용)Keep (만족했고, 앞으로 지속하고 싶은 부분)섹션2의 내용인 '추상'에 대해서 그동안 이렇게까지 깊게 생각해본적 없었는데, 강의 덕분에 추상을 객체지향적인 관점과 함께 생각해볼 수 있었다.'캡추상다'처럼 객체지향에 대해 거의 암기식으로 생각을 했었는데 코드와 자세한 설명으로 인해 필요성을 느꼈고 더 와닿게 배울 수 있었다.평일에 퇴근하고 공부를 해야한다는 생각은 했었지만, 그동안 피곤하다는 이유로 실천하는 것이 어려웠다. 그렇지만 워밍업 클럽에 참여하며 강제성이 생겨 조금씩이라도 공부를 할 수 있었다. 이번 기회에 공부습관을 잘 만들어서 지속적으로 이어졌으면 좋겠다.Problem (부정적인 요소로 작용했거나 아쉬웠던 점)지난 달 말부터 새로운 프로젝트에 참여하게 되면서 쉬는 날에도 업무를 해야하는 경우가 생겨 스터디에 투자할 수 있는 시간이 적었다.이로 인해 강의 진도를 커리큘럼대로 따라가지 못해 밀리거나 미션을 마감기한 전에 급하게 제출하는 경우가 있었다.Try (Problem에 대한 해결 방식으로 다음에 시도해볼 점)워밍업 클럽에 참여하는 동안에는 주말의 휴식, 여가시간을 줄이고 강의내용과 미션에 좀 더 집중해봐야겠다.배웠던 내용을 정리하면서 강의를 수강하다보니 강의를 듣는 시간이 오래 걸렸다. 커리큘럼보다 진도가 늦어진 경우에는 강의를 정리하기보다는 먼저 정해진 진도까지 수강하고 여유가 있을 때 복습하는 겸 강의를 정리하면 좋을 것 같다.미션 정리day2 미션 _"추상과 구체" 강의를 듣고, 생각나는 추상과 구체의 예시가 있다면 한번 3~5문장 정도로 적어봅시다.헬스장에서 운동을 하는 과정을 구체 레벨에서 표현한다면? 헬스장에 도착해 출입 카드 등을 통해 출입을 인증한다.운동복과 운동화를 착용한다.준비운동 또는 스트레칭을 통해 근육을 풀어준다.기구 또는 맨몸을 사용하여 신체를 조절한다.헬스장을 나가며 출입을 종료한다.day4 미션 1) 아래 코드와 설명을 보고, [섹션 3. 논리, 사고의 흐름]에서 이야기하는 내용을 중심으로 읽기 좋은 코드로 리팩토링해 봅시다. 2) SOLID에 대하여 자기만의 언어로 정리해 봅시다.https://www.inflearn.com/blogs/8394

프로그래밍 언어워밍업클럽백엔드발자국

jin02019

인프런 워밍업 클럽 2기(클린코드/테스트 코드)_day4 미션

1. 아래 코드와 설명을 보고, [섹션 3. 논리, 사고의 흐름]에서 이야기하는 내용을 중심으로 읽기 좋은 코드로 리팩토링해 봅시다.✔ 사용자가 생성한 '주문'이 유효한지를 검증하는 메서드. ✔ Order는 주문 객체이고, 필요하다면 Order에 추가적인 메서드를 만들어도 된다. (Order 내부의 구현을 구체적으로 할 필요는 없다.) ✔ 필요하다면 메서드를 추출할 수 있다.public boolean validateOrder(Order order) { if (order.getItems().size() == 0) { log.info("주문 항목이 없습니다."); return false; } else { if (order.getTotalPrice() > 0) { if (!order.hasCustomerInfo()) { log.info("사용자 정보가 없습니다."); return false; } else { return true; } } else if (!(order.getTotalPrice() > 0)) { log.info("올바르지 않은 총 가격입니다."); return false; } } return true; }리팩토링 후 public boolean validateOrder(Order order) { if (order.getItems().isEmpty()) { log.info("주문 항목이 없습니다."); return false; } if (order.getTotalPrice() > 0) { if (order.hasCustomerInfo()) { return true; } log.info("사용자 정보가 없습니다."); return false; } if (order.getTotalPrice() <= 0) { log.info("올바르지 않은 총 가격입니다."); return false; } return true; } }!(부정 연산자) 줄이기dept 줄이기공백 라인 추가 2. SOLID에 대하여 자기만의 언어로 정리해 봅시다.단일 책임 원칙하나의 클래스는 하나의 책임만 가져야 한다. 하나의 역할에 집중하면 코드를 수정할 때 다른 부분에 영향을 주지 않고 유지보수가 쉬워진다.개방 - 폐쇄 원칙확장에는 열려 있고 수정에는 닫혀있어야 한다.기존의 코드를 변경하지 않고 새로운 기능을 추가할 수 있어야 한다. 이미 작동하는 코드가 손상될 위험이 줄어들고 확장도 수월하다.리스코프 치환 원칙부모 클래스 대신 자식 클래스를 사용해도 문제가 없어야 한다. 자식 클래스가 부모 클래스의 기능을 대신할 수 있다면 코드의 안정성을 높일 수 있다.인터페이스 분리 법칙인터페이스는 필요한 기능만을 나누어 제공해야 한다.큰 인터페이스보다는 작은 인터페이스 여러 개로 설계해야 한다.불필요한 의존성을 줄이고 코드의 유연성을 높일 수 있다.의존 역전 법칙고수준 모듈은 저수준 모듈에 의존하지 않아야 한다.추상화된 인터페이스에 의존해야 한다.변화에 강한 구조를 만들고 코드의 재사용성을 높일 수 있다. 

프로그래밍 언어읽기좋은코드를작성하는사고법day4미션

Mac codesign 및 실행 파일 변환 하는 Script

apple script 는 권한 문제가 있다 do sheel ..... with administrator privileges 권한문제 가 몬테레이에서 작동하지않는다. 해결이 안된다 sudo 를 암호 없이 실행하게 만들라 하는데 .. Automator 에 빠른실행에 스크립터로 넣으면 된다. 쉘 스크립터가 더나은것같지만 실행파일변환시 와일드카드처럼작동한다, ---------------------------------------------Apple Script---------------------------- on run {input, parameters} set getData to input set orgPath to POSIX path of (getData as text) set strPath to (alias getData as string) & "Contents:Macos:"     set mypath to alias strPath set {folder:Fo, package folder:Pa} to info for getData without size if Fo and not Pa then display dialog "😂선택한 항목은 폴더입니다 스크립터를 종료합니다😂" else if Fo and Pa then set p to POSIX path of ((choose file with prompt "😀실행파일로 변환할 파일을 선택하세요😀" of type {} default location mypath) as text) do shell script "xattr -cr " & quoted form of orgPath & "; codesign --force --deep --sign - " & quoted form of orgPath & "; chmod 577 " & quoted form of p else do shell script "chmod 577 " & quoted form of orgPath & "; xattr -cr " & quoted form of orgPath & "; codesign --force --deep --sign - " & quoted form of orgPath end if end run ---------------------------------------------Shell Script---------------------------- export HISTIGNORE='*sudo -S*' for f in "$@" do if [ -d "$f" ] ; then echo "YOURPASSWORD" |sudo -S -k xattr -cr "$f" echo "YOURPASSWORD" |sudo -S -k codesign --force --deep --sign - "$f" # space filename no process. Macos folder all file EXE for fileName in $(ls "$f/Contents/MacOS/"); do     echo "YOURPASSWORD" |sudo -S -k chmod 577 "$f/Contents/MacOS/$fileName" done else echo "YOURPASSWORD" |sudo -S -k chmod 577 "$f" fi done

프로그래밍 언어

채널톡 아이콘