블로그

볼드 UX

[인프런 워밍업 스터디 1기 디자인] 오리엔테이션 준비하기

 안녕하세요! 지식공유자 볼드입니다. 최근에 인프런 워밍업 스터디 클럽 1기에서 프로덕트 디자인 코치로 참여하게 되었어요.준비 과정이 꽤 새로웠고, 많은 것을 배우는 시간이었습니다. 오늘은 제가 어떻게 러너분들과 첫 만남을 위해 준비를 하였는지 알려드리고자 해요.   첫 만남을 미리 계획하다저는 4주 전부터는 0기 코치님들이 남겨둔 자료들을 보며 어떻게 하면 더 좋은 오리엔테이션을 만들 수 있을지 고민했어요. 구조부터 차근차근 짜고, 내용을 채워 넣어서 빠르게 프레젠테이션을 완성했습니다. 첫만남인 만큼 어떻게 하면 더 재미있고, 참여자들과 적극적으로 소통할 수 있을까 고민을 많이 했어요. 그래서 피그잼을 사용한 워크샵 형태로 진행하기로 결정하고, 세 가지 큰 원칙을 세웠습니다:많은 정보를 빠르게 명확하게 전달하기최대한 재미있고 인터랙티브하게 이야기가 살아있는 컨셉 유지하기 다행히 ‘러너’라는 주제가 이미 있어서 그걸로 컨셉을 잡았고, 다음과 같은 여정으로 구성해 보았어요.🚀 출발: 워밍업 클럽을 시작하게 된 이유🗺 코스: 워밍업 클럽의 미션들🎯 도착: 워밍업 클럽을 마치고 받게 되는 혜택들    OT 시작 전에는 새 직장에서 바쁠 것 같아서 미리 인프런 담당자 셰리님과 자료를 공유하고 점검하는 시간을 가졌어요.그리고 막상 OT 주간이 되니, 예상대로 정신 없었습니다. OT 당일에는 반차를 내고, 오전에 교회에서 성경공부를 마치고 집에 돌아와 커피 한 잔 마시며 마지막 준비를 했죠.    러너 분들과 드디어 만나다영국시간으로 12시에 시작했어요.(한국 시간으로는 오후 8시), 제가 먼저 짧게 발표를 먼저 진행하고 러너 분들은 질문에 따라 각자 글을 작성하셨어요.  작성 후에는 서로의 글을 보며 하트를 남기는 시간을 가졌는데, 이게 생각보다 더 재미있었던 것 같아요.  미리 준비한 탭으로 미션 정보를 빠르게 효과적으로 보여드리고, 원래 OT 전까지 블로그 글을 쓰지 못했는데 셰리님의 빠른 대처로 발자국 미션 시연을 성공적으로 마칠 수 있었어요.  OT 끝나고 난후워크샵이 끝난 후, 참가자분들의 피드백을 부탁드렸어요. 피드백을 보고 나니 제가 준비한 만큼 결과도 좋았다는 생각이 들더군요.(아래는 제가 몇개 선정한 감사한 피드백!)  2기에도 제가 참여할지는 아직 모르겠지만 2기에도 오리엔테이션 준비 경험을 살리거나 또 다른 코치님들이 사용할 수 있도록 이 피그잼 보드를 템플릿화하면 좋을 것 같아요. 또한, 이 방식을 다른 온라인 강의에서도 활용할 수 있을 것 같아요. (필요하신 분들은 알려주세요. 무료 나눔해드릴게요!) 마지막으로 인프런 워밍업 클럽 이전에 제가 진행한 인증샷 스터디에서 수강생과 교류가 있으면 좋을 것 같다는 의견이 있었어요. 처음엔 이걸 어떻게 개선해야할지 막막했는데, 인프런 워밍업 클럽을 참여하면서 이 문제를 해결할 수 있었어요. 그리고 셰리님을 포함한 인프런 팀이 없었다면 이 모든 게 불가능했을 거예요. 정말 감사드립니다! 인프런팀 만세! 앞으로 남은 세 번의 특강, 워크샵을 어떻게 준비할지 계획 중인데, 라이브 튜토리얼과 프레젠테이션을 어떻게 잘 조합할지, 함께 만들어가는 워크샵 과정이 어떨지 기대되네요. 인프런 워밍업 클럽 1기에 참여하신 모든 러너분들 다같이 파이팅해요 🔥     

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

볼드 UX

[인프런 워밍업 스터디 1기 디자인] 1주차 슬기롭게 보내기

발자국 1주차드디어 첫 주가 시작되었어요. 새로운 회사 일도 시작한 지 2주 차라 정신이 없었어요.조용하던 디자인 디스코드 채널이 드디어 활발해지기 시작했어요. 이번 주에는 코치로서 다음과 같은 일을 해야 했어요.폭발적인 강의 질문 대응하기미션 꼼꼼히 체크하기특별 강의 준비하기  첫째, 강의 질문 방에서는 수강생들이 강의를 듣기 시작하면서 질문이 쏟아졌어요. 조용하던 채널이 질문으로 가득 차는 것은 매우 바람직한 현상이에요. 둘째, 미션 제출이 시작되었어요. 평소에는 회사 일에 집중하고, 저녁 늦게나 새벽에 수강생들이 제출한 과제를 살펴봤어요. 처음에는 단순히 미션 여부만 확인하려고 했지만, 과제를 살펴보다가 몇 가지 흥미로운 점을 발견했어요.흥미로운 점 세 가지는 다음과 같아요:1. 같은 강의를 듣고도 실수를 반복하는 수강생이 있다는 것이에요. 이는 온라인 강의의 한계일 수 있어요.2. 이러한 실수가 일부 수강생에게만 나타나는 것이 아니라 반복적으로 나타난다는 점이고, 이것을 데이터로 정리해서 다른 수강생들에게도 요약 노트 등으로 알리면 좋을 것 같아요.3. 인프런 워밍업을 통해 수강생들의 작업 파일을 보고 코멘트를 남기며 피드백을 통해 서로 수정하고 올바르게 배울 수 있었어요. 셋째, 특별 강의를 준비했어요. 세 가지 주제로 구성하고, 강의 준비 과정은 쉽지 않았어요. 밤에 미션을 체크하고 남는 시간에 강의를 만들었어요. 특별 강의는 주로 새벽 5시에 일어나서 준비했고, 다음과 같은 주제로 구성되었어요.- 가장 많이 나오는 질문: 아이콘- 컴포넌트 네이밍 컨벤션- 멀티에딧 베리언츠인터랙티브한 강의를 만들기 위해 네이밍 컨벤션을 공유할 때는 혼동되는 용어에 대한 각 개인의 생각을 물어봤어요. 특별 강의는 기본 1시간을 넘어 20분 더 진행되었고, 많은 수강생이 마지막까지 남아 있었어요. 피드백을 부탁드렸는데, 마치고 나서 살펴보니 열심히 준비한 보람을 느꼈어요. (선정한 5개 수강평)  다음 주 월요일이 영국도 공휴일인이라 쉴 수 있어서 다행이에요. 그렇게 휴식을 취해야 회사 일과 인프런 코칭을 병행할 수 있을 것 같아요. 모두들 2주차도 파이팅입니다!

UX/UI인프런워밍업베리어블스터디디자인시스템

kamser

인프런 워밍업 클럽 백엔드 0기 수료식 후기

인프런 워밍업 클럽 0기 후기 인프런 강의는 회사 업무를 빠르게 적응하려고 듣는 강의가 있고,회사 로직에 추가로 적용시키고 싶은 기술이거나 혹은 미래를 위해서 듣는 강의도 있습니다. 전자의 학습 방법은 예제 코드로 학습을 한 후에 회사에 작성된 다른 선배 개발자 분들의 실무 코드를 보면서 학습할 수 있습니다. 후자 방식으로 듣는 강의는 대부분 예제 코드로 학습을 하고 본인이 작성한 코드만 보게 됩니다.그러다보니 전자의 방식보다 아쉬운 부분이 생깁니다.실무 수준까지는 아니더라도 파일럿 프로젝트 수준의 코드나 다른 개발자 분들이 작성한 코드를 보기 어렵습니다.저는 다른 개발자 분들이 작성한 코드를 보는 것도 하나의 좋은 학습 방법이라 생각하는데 그걸 하지 못합니다. 인프런 워밍업 클럽 스터디는 저에겐 후자의 방식이지만 아쉬운 부분을 채워줬습니다.다른 러너분들이 제출한 과제를 보고 비교하며 학습할 수 있었고,과제의 응용 버전인 미니 프로젝트를 진행하면서 단순히 코드비교 뿐만 아니라 데이터 구조를 어떻게 설계를 했는지 볼 수 있었습니다.혼자서 듣는 강의였다면 이런 좋은 경험을 하지 못했을거라 생각합니다. 결론은 너무 좋은 경험이였고, 다음 1기도 시작하신다면 꼭 신청하려고 합니다. 감사인사존경하는 최태현 지식 공유자님 감사합니다.정규 라이브는 제공된 일정보다 더 길었고, 일정엔 없던 긴급 라이브까지 진행하시느라 목이 쉬시는 열정적인 강사님 모습에 제가 오히려 힘을 받았습니다.특히 과제 리팩토링과 코드 리뷰 라이브 덕분에 제가 헷갈렸던 테스트 개념과 작성하지 못했던 구현 코드까지 수정 했습니다.그외에 Live Q&A와 수료식 Q&A에 답변해주셨던 내용은 잊으면 안될거같아서 따로 정리까지 했습니다.3주간 열정적으로 스터디 진행해주셔서 감사합니다. 이 스터디를 기획하신 담당자분들과 준비해주신 담당자분들에게 모두 감사합니다.담당자분들께서 많은 러너분들 관리해주시고, 음식 준비해주시고, 나누어 주시고,야근까지 하시느라 힘드셨으텐데 친절하게 맞이해주셔서 감사합니다.덕분에 스터디를 진행하면서 처음 자바로 크레이지 아케이드를 만들면서 행복했던 그 때 감정을 다시 느꼈습니다. 그리고 수료식 마지막 시간이였던 네트워킹 시간에 대화를 리드해주신 조성륜 개발자분에게도 감사인사를 전하고 싶습니다.요즘 블로그 글을 쓸때 업데이트를 어떻게 해야할지 고민이 있었는데 위키처럼 작성하신다는 걸 알려주셔서 고민이 해결되었습니다 감사합니다.

인프런인프런워밍업클럽스터디0기

양성빈

[인프런 워밍업 스터디 클럽] 0기 백엔드 미션 - 어노테이션(Day1)

어노테이션 서론드디어 '인프런 워밍업 스터디 클럽 0기' 첫 날이 밝아왔다. 강의를 듣고 미션을 보니 어노테이션에 관련한 내용이었다.나는 이 미션을 보고 오히려 기쁜 마음이 들었다. 😆 내가 강의를 들으면서 어노테이션 부분이 많이 궁금하였는데 이렇게 공부하게 될 계기가 생긴 것 같아서 미션도 완성시키고 나 스스로 깊게 공부도 할 겸 미션을 시작할려고 한다. 미션 내용은 아래와 같다.진도표 1일차와 연결됩니다우리는 최초로 API를 만들어 보았습니다. GET API를 만들기 위해 사용했던 어노테이션에 익숙하지 않다면 자바 어노테이션에 대해서 몇 가지 블로그 글을 찾아보세요! 다음 질문을 생각하며 공부해보면 좋습니다! 😊 [질문]어노테이션을 사용하는 이유 (효과) 는 무엇일까?나만의 어노테이션은 어떻게 만들 수 있을까?내가 알아본 어노테이션의 정의나는 강의의 실습을 통하여 스프링 부트 프로젝트를 생성하고, GET API를 만들어보고 포스트맨을 통하여 테스트 작업도 해보았다. 나는 여기서 다양한 어노테이션들을 볼 수 있었다. @SpringBootApplication, @RestController, @GetMapping 등 여러 어노테이션들을 볼 수 있었다. 여기서 나는 어노테이션이 무엇일까 고민을 해보았다. 단순히 어노테이션은 @ 붙인거라고만 알고 있었기에 이번 기회에 미션도 수행할 겸 깊게 알아보는 것도 좋다 생각하여 공부해보기로 하겠다.먼저 어노테이션이 대체 어떤 정의가 있는지 구글링을 해보기로 하였다. 구글링을 해보니, 다양한 블로그들이 나왔지만 정의가 수록된 위키백과를 먼저 참조해보기로 하였다. 위키백과는 다음과 같이 정의를 내렸다. 자바 어노테이션은 자바 소스 코드에 추가하여 사용할 수 있는 메타데이터의 일종이다. 보통 @ 기호를 앞에 붙여서 사용한다. JDK 1.5 버전 이상에서 사용 가능하다. 자바 어노테이션은 클래스 파일에 임베디드되어 컴파일러에 의해 생성된 후 자바 가상머신에 포함되어 작동한다. 그리고 강의 중에 코치님께서도 어노테이션에 대해 아래와 같이 언급해주셨다. 어노테이션은 어노테이션마다 너무 다양한 역할을 한다. 또한 마법같은 일을 자동으로 해준다는 것이다.예를 들어서, @SpringBootApplication 어노테이션은 스프링을 실행시킬 때 다양한 설정이 필요한데 이 설정을 모두 자동으로 해준다. 또한 이런것이 가장 핵심적인 마법같은 일이다.위키사전, 코치님의 설명을 통해 어노테이션의 정의를 알 수 있었다. 좀 더 내가 설명한 식으로 풀어보자면 다음과 같다.자바의 어노테이션은 코드에 추가 정보를 제공하는 데 사용되며, 컴파일 시간, 배포 시간, 또는 실행 시간에 해당 정보를 활용할 수 있습니다. 이를 통해 개발자는 코드에 메타데이터를 추가하여 코드의 가독성, 유지 보수성을 향상시키고, 다양한 도구와 프레임워크에서 활용될 수 있는 정보를 제공할 수 있습니다.좀 더 자세히 풀어보자.어노테이션은 자바 5부터 도입된 기능으로, 코드에 대한 메타데이터를 제공하는 방법입니다. 어노테이션은 주석과 비슷하지만, 실제로 코드에 영향을 줄 수 있으며, 컴파일러에게 정보를 제공하거나 실행 시간에 특정 동작을 하도록 할 수 있습니다. 어노테이션은 선언적 형태로 코드 안에 포함되어, 클래스, 메소드, 변수 등 다양한 요소에 적용될 수 있습니다.이제 위의 내용을 좀 더 정리해보겠다. 어노테이션이란?자바를 개발한 사람들은 소스코드에 대한 문서를 따로 만들기보다 소스코드와 문서를 하나의 파일로 관리하는 것이 낫다고 생각했다. 그래서 소스코드의 주석에 소스코드에 대한 정보를 저장하고, 소스코드의 주석으로부터 HTML 문서를 생성해내는 프로그램(javadoc.exe)를 만들어 사용했다. 그런데 여기서 의문점이 하나 든다. 🙋🏻 왜 어노테이션이라는 것을 살펴보려 하는데 주석이라는 내용이 먼저 나올까? 프로그램의 소스코드 안에 다른 프로그램을 위한 정보를 미리 약속된 형식으로 포함시킨 것이 바로 어노테이션이다.어노테이션은 주석(comment)처럼 프로그래밍 언어에 영향을 미치지 않으면서도 다른 프로그램에게 유용한 정보를 제공할 수 있다는 장점이 있다. 📚 어노테이션(annotation)의 뜻은 주석, 주해, 메모이다.package org.example; public @interface SampleAnnotation { }위의 코드는 인텔리제이로 나의 어노테이션을 만든 코드이다.그럼 인텔리제이로 어노테이션을 만드는 것도 끝났으니 이제 끝인가? 나는 여기서 더 나아가서 이 어노테이션 코드가 .class파일로 컴파일 되었을 때 어떻게 나오는지 보고 싶어서 터미널로 컴파일을 해보았다. 컴파일 결과는 다음과 같다.public interface org.example.SampleAnnotation extends java.lang.annotation.Annotation { }컴파일 시점에 extends 한적 없는 java.lang.annotation.Annotation 이 extends 되어 있다. 이제 좀 더 자세한 어노테이션의 내용과 활용법을 알아가보자. 어노테이션은 JDK에서 기본적으로 제공하는 것과 다른 프로그램에서 제공하는 것들이 있는데, 어느 것이든 그저 약속된 형식의 정보를 제공하기만 하면 될 뿐이다.JDK에서 제공하는 표준 어노테이션은 주로 컴파일러를 위한 것으로 컴파일러에게 유용한 정보를 제공한다. 📚 JDK에서 제공하는 어노테이션은 'java.lang.annotation' 패키지에 포함되어 있다.어노테이션은 코드에 넣는 주석이다. 완전히 주석같지는 않지만 그 비슷한 부류이다.주석이기 때문에, 실행되는 코드라고 생각하면 안된다. 어노테이션은 기능을 가지고 있는 것이라 착각을 할 수 있지만 어노테이션은 마크, 표시 해놓는 주석이다. 어노테이션은 다이나믹하게 실행되는 코드는 들어가지 않는다.즉, 런타임에 알아내야 하는 것들은 못 들어간다.위의 내용을 좀 더 풀어쓰면 컴파일러 수준에서 해석이 되야 하거나, 완전히 정적이어야 한다는 말이다.이유를 아래 코드로 보여주겠다. package me.sungbin.controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class HelloController { private static final String hello = "/hello"; @GetMapping(hello) public String hello() { return "hello"; } }위와 같이 hello 변수는 정적 변수이므로 @GetMapping 어노테이션에 사용할 수 있다.하지만. hello 변수가 동적인 변수라면 컴파일 에러가 발생한다.아래의 코드를 보자. 컴파일 에러가 발생하는 것을 볼 수 있을 것이다. 간략한 어노테이션 정의 방법새로운 어노테이션을 정의하는 방법은 아래와 같다.'@'기호를 붙이는 것을 제외하면 인터페이스 정의와 동일하다. package me.sungbin; public @interface SampleAnnotation { 타입요소이름(); } 📚 타입요소등, 어노테이션 정의에 대한 자세한 정의방법과 내용들은 구체적인 내용들을 확인 후, 살펴보자.자바의 표준 어노테이션자바에서 기본적으로 제공하는 어노테이션들은 몇 개 없다.그나마 이들의 일부는 '메타 어노테이션(meta annotation)' 으로 어노테이션을 정의하는데 사용되는 어노테이션의 어노테이션이다. 표준 어노테이션과 메타 어노테이션@Override: 컴파일러에게 오바리이딩하는 메서드라는 것을 알린다.@Deprecated: 앞으로 사용하지 않을 것을 권장하는 대상에 붙인다.@SuppressWarnings: 컴파일러의 특정 경고메시지가 나타나지 않게 해준다.@SafeVarags: 제네릭스 타입의 가변인자에 사용한다. (JDK 1.7)@FunctionalInterface: 함수형 인터페이스라는 것을 알린다. (JDK 1.8)@Native: native 메서드에서 참조되는 상수 앞에 붙인다. (JDK 1.8)@Target*: 어노테이션이 적용가능한 대상을 지정하는데 사용한다.@Documented*: 어노테이션 정보가 javadoc으로 작성된 문서에 포함되게 한다.@Inherited*: 어노테이션이 자손 클래스에 상속되도록 한다.@Retention*: 어노테이션이 유지되는 범위를 지정하는데 사용한다.@Repeatable*: 어노테이션을 반복해서 사용할 수 있게 한다. (JDK 1.8)*이 붙은 것이 메타 어노네이션이다.📚 메타 어노테이션: 어노테이션을 정의하는데 사용하는 어노테이션의 어노테이션 @Override현재 메서드가 슈퍼 클래스의 메서드를 오버라이드한 것임을 컴파일러에게 명시해준다.메서드가 슈퍼클래스에 없다면 에러를 발생시기 때문에 오타와 같은 실수도 잡을 수 있다. @Deprecated마커 어노테이션으로 다음 버전에 지원되지 않을 수도 있기 때문에 앞으로 사용하지 말라고 경고를 알린다.@Deprecated를 붙인 메서드는 인텔리제이에서 아래의 사진과 같이 표시해준다. @SuppressWarning경고를 제거하는 어노테이션으로 개발자가 의도를 가지고 설계를 했는데 컴파일은 이를 알지 못하고 컴파일 경고를 띄울 수 있기 때문에 이를 제거하는 목적이다. @SafeVarargsJava 7이상에서 사용가능하고 제네릭같은 가변인자 매개변수 사용시 경고를 무시한다제네릭사용할 클래스,메서드 내부에서의 데이터타입을 외부에서 지정하는 기법 @FunctionalInterfaceJava 8이상에서 사용가능하고 컴파일러에게 함수형 인터페이스라는 것을 알리는 어노테이션이다.메타 어노테이션'어노테이션을 위한 어노테이션' 쯕, 어노테이션에 붙이는 어노테이션으로 어노테이션을 정의할 때 어노테이션의 적용대상(target) 이나 유지기간(retention)등을 지정하는데 사용된다. 📚 메타 어노테이션은 java.lang.annotation 패키지에 포함되어 있다. @Target어노테이션이 적용가능한 대상을 지정하는데 사용한다.아래 예제는 '@SuppressWarnings' 를 정의한 것인데, 이 어노테이션에 적용할 수 있는 대상을 '@Target' 으로 지정한다.여러 개의 값을 지정할 때는 배열처럼 괄호{} 를 이용하여 지정할 수 있다.package me.sungbin; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.*; @Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE}) @Retention(RetentionPolicy.SOURCE) public @interface SuppressWarnings { String[] value(); } @Target으로 지정할 수 있는 어노테이션 적용대상의 종류ANNOTATION_TYPE: 어노테이션CONSTRUCTOR: 생성자FIELD: 필드(멤버 변수, ENUM 상수)LOCAL_VARIABLE: 지역변수METHOD: 메서드PACKAGE: 패키지PARAMETER: 매개변수TYPE: 타입(클래스, 인터페이스, ENUM)TYPE_PARAMETER: 타입 매개변수(JDK1.8)TYPE_USE: 타입이 사용되는 모든 곳(JDK1.8)📚 java.lang.annotation.ElementType 이라는 열거형에 정의되어 있다. static import문을 사용하면 ElementType.TYPE 이 아니라 TYPE 과 같이 간략히 사용할 수 있다. TYPE은 타입을 선언할 때 어노테이션을 붙일 수 있다는 뜻TYPE_USE는 해당 타입의 변수를 선언할 때 붙일 수 있다는 뜻이다.FIELD 는 기본형에 사용할 수 있고, TYPE_USE는 참조형에 사용된다는 점을 주의한다.타입 선언부제네릭 타입, 변수 타입, 매개변수 타입, 예외 타입...타입에 사용할 수 있으려면TYPE_PARAMETER : 타입 변수에만 사용할 수 있다.TYPE_USE : 타입 변수를 포함해서 모든 타입 선언부에 사용할 수 있다.package me.sungbin; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.*; @Target({FIELD, TYPE, TYPE_USE}) public @interface MyAnnotation { } package me.sungbin; import me.sungbin.controller.HelloController; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication @MyAnnotation public class AnnotationTestApplication { @MyAnnotation int i; @MyAnnotation HelloController helloController; public static void main(String[] args) { SpringApplication.run(AnnotationTestApplication.class, args); } } @Retention어노테이션 유지되는 기간을 지정하는데 사용한다. 어노테이션 유지정책의 종류SOURCE: 소스 파일에만 존재. 클래스파일에는 존재하지 않는다.CLASS: 클래스 파일에 존재. 실행 시에 사용 불가능하다. (기본값)RUNTIME: 클래스 파일에 존재하며 실행시에 사용 가능하다.SOURCE -> CLASS -> RUNTIMESOURCE는 소스코드만 유지하겠다.컴파일 시에만 사용하겠다는 것!컴파일하고 나면 어노테이션은 없어진다. -> 바이트코드에도 남아있지 않다.CLASS애노테이션에 대한 정보를 클래스 파일까지, 즉 바이트 코드에도 남겨 두겠다.클래스 정보를 읽어들이는 방법(바이트 코드를 읽어들이는)을 바탕으로 애노테이션 정보를 읽어와서 처리할 수 있다.예) BYTE BUDDY, ASM 활용바이트 코드엔 남아 있지만, 이 클래스파일을 JVM이 실행할 때 클래스에 대한 정보를 클래스로더가 읽어서 메모리에 적재하게되고, 이후 사용 시점에 메모리에서 읽어올 때 애노테이션 정보를 제외하고 읽어옴RUNTIME위 CLASS와 동일하지만, 메모리에 적재된 클래스 정보를 읽어올 때 애노테이션 정보를 그대로 포함하는 것이다.바이트코드에서 읽어오는게 빠를까?RetentionPolicy를 CLASS로 한 이후, 바이트코드를 읽어 처리하는 라이브러리를 활용?리플렉션으로 읽어오는게 빠를까?RetentionPolicy를 CLASS로 한 이후, 바이트코드를 읽어 처리하는 라이브러리를 활용? -> 리플렉션 자체가 부하가 존재한다.-> 바이트 코드의 양에 영향을 끼친다.-> 리플렉션은 메모리에 이미 올라와 있는 정보를 읽는다. 클래스 로더가 읽고 메모리에 적재시킨 후 읽어온다. 📚 커스텀하게 만든 애노테이션이 정말로 RUNTIME 까지 필요한 정보인가? RUNTIME 까지 사용할 필요가 없다면, CLASS 레벨로 내려가거나 SOURCE 레벨로 내려갈 수도 있을 것이다. 그냥, 의례적으로 RUNTIME으로 작성하는 경우가 있었다면? 그 역할을 다시 살펴보고 명확한 Retention Policy 를 정의하자. 표준 어노테이션 중 '@Override' 나 '@SuppressWarnings' 처럼 컴파일러가 사용하는 어노테이션은 유지 정책이 'SOURCE' 이다. -> 컴파일러를 직접 작성할 것이 아니면, SOURCE 이상의 유지정책을 가질 필요가 없다. 유지 정책을 RUNTIME 으로 한다면,실행 시에 리플렉션(Reflection) 을 통해 클래스 파일에 저장된 어노테이션의 정보를 읽어서 처리 할 수 있다.Retention 정책은 RUNTIME 으로 정의하고Target은 TYPE과 FIELD로 정의한다.package me.sungbin; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.*; @Target({TYPE, FIELD}) @Retention(RetentionPolicy.RUNTIME) public @interface MyAnnotation { } Target이 TYPE과 FIELD 임으로 클래스에도 애노테이션을 선언할 수 있고클래스 내부의 필드에도 애노테이션을 선언할 수 있다.package me.sungbin; @MyAnnotation public class TestClass { @MyAnnotation private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } } TestClass 클래스에 선언된 Annotation을 리플렉션을 이용해 확인할 수 있다.package me.sungbin; import java.lang.reflect.Field; import java.util.Arrays; public class App { public static void main(String[] args) { Arrays.stream(TestClass.class.getAnnotations()).forEach(System.out::println); Field[] declaredFields = TestClass.class.getDeclaredFields(); for (Field declaredField : declaredFields) { Arrays.stream(declaredField.getAnnotations()).forEach(System.out::println); } } }  표준 어노테이션 중 '@FunctionalInterface' 는 '@Override' 처럼 컴파일러가 체크해주는 어노테이션이지만, 실행 시에도 사용되므로 유지 정책이 "RUNTIME"으로 되어 있다. @Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface FunctionalInterface {} 유지 정책을 "CLASS" 으로 한다면컴파일러가 어노테이션의 정보를 클래스 파일에 저장할 수 있게 하지만,클래스 파일이 JVM에 로딩 될 때는 어노테이션의 정보가 무시되어 실행 시에 어노테이션에 대한 정보를 얻을 수 없다.→ CLASS 가 유지정책의 기본값임에도 불구하고 잘 사용되지 않는 이유 지역 변수에 붙은 어노테이션은 컴파일러만 인식할 수 있으므로, 유지 정책이 RUNTIME인 어노테이션을 지역변수에 붙여도 실행 시에는 인식되지 않는다. @Documented어노테이션에 대한 정보가 javadoc으로 작성한 문서에 포함되도록 한다.표준 어노테이션 중 Override와 SuppressWarnings를 제외하고 모두 Documented 메타 어노테이션이 붙어 있다. @Documented애노테이션 정보가 javadoc으로 작성된 문서에 포함된다고 한다. 이것이 무슨말일까? 내 코드가 자바docs에 올라간다는 말일까?정확히 말하면 자바docs에 올라간다는 말이 아니라,직접 javadoc을 만들 수 있다는 뜻이다.이런식으로 만들 수 있는데, Local 지역입력 ko_KRother command line arguments : 한글깨짐 방지-encoding UTF-8 -charset UTF-8 -docencoding UTF-8적절하게 내용을 채운뒤 output directory에 경로를 입력해주면 끝이다.그러면 @Documented를 붙인거와 안 붙인것을 비교해보자. 코드public class Korea implements Great{ @Override @Make public String country() { return "한국"; } } 없는거 있는거JavaDoc애노테이션을 알기 전에 JavaDoc에 대해 알아보자.JavaDoc은 Java코드에서 API문서를 HTML 형식으로 생성해주는 도구이다.HTML 형식이기 때문에 다른 API를 하이퍼 링크를 통해 접근이 가능하다. JavaDoc TagsJavaDoc은 여러 Tag를 작성하여 문서를 완성한다.Java 코드에서 애노테이션으로 추가한다.IDE에서 /** 입력 후 엔터를 치면 자동으로 형식이 생성된다.Javadoc Tags의 종류들@author@deprecated@exception@param@return@see@serial@serialData@serialField@since@throws@since@throws@version@Inherited어노테이션이 자손 클래스에 상속되도록 한다.'@Inherited' 가 붙은 어노테이션을 조상 클래스에 붙이면, 자손 클래스도 이 어노테이션이 붙은 것과 같이 인식된다.MyAnnotation은 Inherited 애노테이션을 통해 자손 클래스에도 인식되도록 정의한다.package me.sungbin; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.*; @Retention(RetentionPolicy.RUNTIME) @Target({TYPE, FIELD}) @Inherited public @interface MyAnnotation { } 부모클래스인 Sungbin클래스에 MyAnnotation을 정의package me.sungbin; @MyAnnotation("hi") public class Sungbin { @MyAnnotation("yang sung bin") private String name; }  Sungbin 클래스의 자식 클래스인 Child 클래스에는 별도의 어노테이션 정의가 없다.package me.sungbin; public class Child extends Sungbin { } 리플렉션을 이용해 Child 클래스의 어노테이션을 확인해보자.→ ChildSson 클래스에는 정의한 애노테이션이 없지만,→ 부모 클래스인 Sson 클래스에 정의한 애노테이션이 확인됨을 볼 수 있다.→ Inherited 애노테이션을 통해 자식 클래스까지 전파될 수 있음을 확인할 수 있다. Inherited 애노테이션을 바탕으로 리플렉션을 활용해 자식클래스에서부모클래스에 정의되어 있는 Inherited 애노테이션을 확인할 수 있다. 📚 리플랙션의 getDeclaredFields(); 를 하면 클래스에 정의된(선언된) 것들을 가져와서 조작할 수 있다. public이던, private 이던,, Getter와 Setter에 대해 논의를 하며 큰 비용을 소모하는 것이 크게 가치가 없다.. 객체지향을 얘기하며 Getter, Setter의 정의 관련한 내용으로 얘기할 수 있겠지만, Getter와 Setter가 없더라도 리플랙션을 이용하면 충분히 가져오고 수정할 수 있기 때문이다. 중요한건 Getter, Setter 가 아닌것 같다. @Repeatable보통은 하나의 대상에 한 종류의 어노테이션을 붙이게 되는데,'@Repeatable'이 붙은 어노테이션은 여러 번 붙일 수 있다. 일반적인 어노테이션과 달리 같은 이름의 어노테이션이 어러 개가 하나의 대상에 적용될 수 있기 때문에, 이 어노테이션들을 하나로 묶어서 다룰 수 있는 어노테이션도 추가로 정의해야 한다. @Native네티이브 메서드(native method)에 의해 참조되는 '상수 필드(constant field)'에 붙이는 어노테이션이다.여기서, 네이티브 메서드는 JVM이 설치된 OS의 메서드를 말한다.네이티브 메서드는 보통 C언어로 작성되어 있는데, 자바에서는 메서드의 선언부만 정의하고 구현하지 않는다.그래서 추상 메서드처럼 선언부만 있고 구현부가 없다. 어노테이션 타입 정의어노테이션의 요소어노테이션 내에 선언된 메서드를 어노테이션의 요소라고 한다. 📚 어노테이션에도 인터페이스처럼 상수를 정의할 수 있지만, 디폴트 메서드는 정의할 수 있다. 어노테이션의 요소는 반환 값이 있고 매개변수는 없는 추상 메서드의 형태를 가진다.다만, 어노테이션을 적용할 때 이 요소들의 값을 빠짐없이 지정해주어야 한다.각 요소들은 기본값을 가질 수 있으며, 기본값이 있는 요소들은 어노테이션을 적용할 때 값을 지정하지 않으면 기본값이 사용된다.어노테이션의 요소가 오직 하나 뿐이고 이름이 value 인 경우, 어노테이션을 적용할 때 요소의 이름을 생략하고 값만 적어도 된다.요소 타입이 배열인 경우, 괄호{} 를 사용해 여러 개의 값을 지정할 수 있다.하나인 경우는 괄호{} 를 생략할 수 있다.java.lang.annotation.Annotation모든 어노테이션의 조상은 Annotation이다.그러나 어노테이션은 상속이 허용되지 않으므로 아래와 같이 명시적으로 Annotation을 조상으로 지정할 수 없다. @interface TestInfo extends Annotation{ // 에러. 허용되지 않는 표현이다. int count(); String testedBy(); ... } Annotation 을 살펴보면Annotation은 어노테이션이 아니라 일반적인 인터페이스로 정의되어 있다. 모든 어노테이션의 조상인 Annotation 인터페이스가 위와 같이 정의되어 있기 때문에모든 어노테이션 객체에 대해 equals(), hashCode(), toString() 과 같은 메서드를 호출하는 것이 가능하다.리플랙션(Reflection)을 이용해 특정 클래스에 선언된 애노테이션들을 조회하여 equals, hashCode, toString 메서드를 호출해본다.어노테이션 요소의 규칙어노테이션의 요소를 선언할 때 반드시 지켜야 하는 규칙요소 타입은 기본형, String, Enum, 어노테이션, Class 만 허용() 안에 매개변수를 선언할 수 없다.예외를 선언할 수 없다.요소를 타입 매개변수로 정의할 수 없다.마커 어노테이션 Marker Annotation값을 지정할 필요가 없는 경우,어노테이션의 요소를 하나도 정의하지 않을 수 있다.Serializable 이나 Cloneable 인터페이스처럼, 요소가 하나도 정의되지 않은 어노테이션을 마커 어노테이션이라 한다. 🙋🏻 이런 마커 어노테이션은 왜 사용될까? 글을 찾아보니 아래의 내용이 있었다.마커 어노테이션을 통해 코드 작성 시점, 컴파일 시점, 러타임 시점에 부가적인 작업을 추가할 수 있을 것이다.코드 작성 시점에 어노테이션 정보를 통해 부가적인 정보를 check 하여 컴파일에러를 발생시킬 수 있을 것이며컴파일하는 과정에서 어노테이션 정보를 바탕으로 부가적인 정보를 포함하여 컴파일된 결과를 내보낼 수도 있을 것이다.또한, 런타임 시점에 리플랙션을 이용하여 애노테이션 정보를 바탕으로 부가적인 작업을 할 수 있을 것이다.Java8 어노테이션 변화 애노테이션 관련 큰 변화 두가지자바 8 부터 애노테이션을 타입 선언부에도 사용할 수 있게 되었다.자바 8 부터 애노테이션을 중복해서 사용할 수 있게 되었다.타입 선언부제네릭 타입변수 타입매개변수 타입예외 타입...타입에 사용할 수 있으려면TYPE_PARAMETER : 타입 변수에만 사용할 수 있다.TYPE_USE : 타입 변수를 포함해서 모든 타입 선언부에 사용할 수 있다.중복 사용할 수 있는 애노테이션을 만들기@Repeatable애노테이션들을 감싸고 있을 컨테이너 애노테이션을 선언해야 한다.중복 사용할 애노테이션 만들기컨테이너 애노테이션은 중복 애노테이션과 @Retention 및 @Target 이 같거나 더 넓어야 한다.컨테이너이기 떄문에 , 이것은 접근 지시자의 범위와 유사한 개념이라고 볼 수 있다.@Retention : 애노테이션을 언제까지 유지할 것이냐?@Target : 애노테이션을 어디에 사용할 것이냐?애노테이션 프로세서애노테이션 프로세서는 소스코드 레벨에서 소스코드에 붙어있는애노테이션을 읽어서 컴파일러가 컴파일 하는 중에 새로은 소스코드를 생성하거나 기존 소스코드를 바꿀 수 있다.또는, 클래스(바이트코드) 도 생성할 수 있고 별개의 리소스파일을 생성할 수 있는 강력한 기능이다. 애노테이션 프로세서 사용 예롬복 (기존코드를 변경한다)AutoService (리소스 파일을 생성해준다.)java.util.ServiceLoader 용 파일 생성 유틸리티@Override애노테이션 프로세서 장점바이트코드에 대한 조작은 런타임에 발생되는 조작임으로 런타임에 대한 비용이 발생한다.but. 애노테이션 프로세서는 애플리케이션을 구동하는 런타임 시점이 아니라,컴파일 시점에 조작하여 사용함으로 런타임에 대한 비용이 제로가 된다.단점은 기존의 코드를 고치는 방법은 현재로써는 public 한 API 가 없다.롬복 같은 경우.. 기존 코드를 변경하는 방법이지만 public 한 api를 이용한 것이 아님으로 해킹이라고 할 수 도 있다.롬복(Lombok)의 동작원리Lombok@Getter @Setter, @Builder 등의 애노테이션과애노테이션 프로세서를 제공하여 표준적으로 작성해야 할 코드를 개발자 대신 생성해주는 라이브러리이다.사용하기의존성 추가IntelliJ Lombok 플로그인 설치Intellij Annotation Processing 옵션 활성화동작원리컴파일 시점에 "애노테이션 프로세서"를 사용하여 (자바가 제공하는 애노테이션 프로세서)소스코드의 AST(Abstract Syntax Tree) 를 조작한다.AST에 대한 참고 사이트 (아래 참조 참고)javax.annotation.processing || Interfaec Processor⇒ 소스코드의 AST를 원래는 참조만 할 수 있다. // 수정하지 못한다. 그리고 하면 안된다!⇒ 그러나 수정이 됬음을 알 수 있다.(컴파일 이후 바이트코드 확인)⇒ 참조만 해야 하는 것을 내부 클래스를 사용하여 기존 코드를 조작하는 것임으로 "해킹" 이라고 얘기하기도 한다. 논란 거리공개된 API가 아닌 컴파일러 내부 클래스를 사용하여 기존 소스 코드를 조작한다.특히 이클립스의 경우에는 Java Agent를 사용하여 컴파일러 클래스까지 조작하여 사용한다.해당 클래스들 역시 공개된 API가 아니다보니 버전 호환성에 문제가 생길 수도 있고 언제라도 그런 문제가 발생해도 이상하지 않다.그럼에도 불구하고 엄청난 편리함 때문에 널리 쓰이고 있으며, 대안이 몇가지 있지만 롬복의 모든 기능과 편의성을 대체하지 못하는 상황이다.AutoValueImmutables기존 Getter, Setter, equals, hasCode 등의 메소드를 생성하는 순간?해당 클래스는 이미 방대해진 모습을 볼 수 있다.해당 클래스를 위한 메소드들이 선언이 되어 있더라도 위 메소드들 사이에 파묻혀 있다면?개발자 입장에서 놓칠 수도 있다. (그래서 boilerplat 코드라는 개념도 나온다.)⇒ 롬복을 이용하여 쉽게, 그리고 가독성 높게 클래스를 구현할 수 있다. package me.sungbin; import lombok.Getter; import lombok.Setter; @Getter @Setter public class Member { private String name; private int age; }  위의 롬복이 적용된 코드를 컴파일하면 아래와 같이 나온다. package me.sungbin; public class Member { private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } } 결론위에서 미션에 대해 다 애기한 듯 하다. 결론을 내보겠다.어노테이션을 사용하는 이유는 단순하다.코드의 가독성과 유지보수성 향상: 어노테이션을 사용하면 개발자가 코드의 의도를 더 명확하게 표현할 수 있습니다. 예를 들어, @Override 어노테이션은 메소드가 상위 클래스의 메소드를 오버라이드한다는 것을 명시합니다.컴파일 시간 검사: 어노테이션을 통해 코드에 대한 추가적인 검사를 수행할 수 있어, 잠재적인 오류를 컴파일 시간에 발견하고 수정할 수 있습니다.런타임 처리: 특정 어노테이션이 적용된 요소를 런타임에 검사하고 처리할 수 있어, 리플렉션을 사용한 동적 처리가 가능해집니다. 이는 프레임워크와 라이브러리에서 많이 활용됩니다.이런 이유로 사용이 되며 이로인하여 코드문서화, 컴파일러에 특정처리를 지시, 코드분석 도구 지원, 런타임처리등이 가능해지게 된다. 우리가 스프링의 의존성 주입을 할 때 @Autowired도 이런 기능처리를 해준다. 컴파일러에서의 처리:코드 검증: 컴파일러는 어노테이션을 사용하여 코드에 대한 추가적인 검증을 수행합니다. 예를 들어, @Override 어노테이션은 메서드가 실제로 상위 클래스나 인터페이스의 메서드를 오버라이드하는지 확인하는 데 사용됩니다. 만약 오버라이드하는 메서드가 없다면, 컴파일러는 에러를 발생시킵니다.정책 적용: 일부 어노테이션은 컴파일러에 특정 정책을 적용하도록 지시합니다. 예를 들어, @Deprecated 어노테이션이 적용된 요소를 사용하는 코드는 컴파일러 경고를 발생시키며, 이는 개발자에게 해당 요소가 더 이상 사용되지 않아야 함을 알립니다.소스 코드 변환: 어노테이션 프로세서를 사용하여 컴파일 시점에 소스 코드를 자동으로 생성하거나 수정할 수 있습니다. 이는 코드 생성 라이브러리나 프레임워크에서 흔히 사용되는 기법입니다.런타임에서의 처리:리플렉션을 통한 접근: 런타임에는 리플렉션 API를 사용하여 어노테이션 정보에 접근할 수 있습니다. 이를 통해 개발자는 실행 중인 프로그램에서 클래스, 메서드, 필드 등에 적용된 어노테이션을 검사하고, 해당 어노테이션에 지정된 정보를 바탕으로 동적인 처리를 수행할 수 있습니다.동적 처리: 런타임에 어노테이션을 기반으로 동적 처리를 하는 예로, Java EE와 Spring 프레임워크에서 의존성 주입을 구현하는 방법을 들 수 있습니다. 이러한 프레임워크는 특정 어노테이션(@EJB, @Autowired)이 붙은 필드나 메서드를 찾아, 런타임에 자동으로 의존성을 주입합니다.구성 관리: 어플리케이션의 구성 정보를 어노테이션을 통해 관리할 수 있습니다. 예를 들어, 웹 어플리케이션에서 서블릿이나 REST 엔드포인트를 정의할 때 사용되는 어노테이션들은 런타임에 웹 서버가 해당 구성 정보를 읽어들여 서비스를 구동하는 데 사용됩니다.이러한 방식으로 어노테이션은 컴파일 시점과 런타임에 다양한 목적으로 활용됩니다. 컴파일 시점에는 코드의 정확성을 보장하고, 런타임에는 코드의 동적인 행위를 제어하는 데 중요한 역할을 합니다.커스텀 어노테이션이것 또한 위에서 예제로 많이 보여드렸으므로 어노테이션 예제를 보여줌으로 이 글을 마치려고 한다. 정말 단순히 어노테이션부터 시작해서 리플렉션까지 갔는데 정말 험난한 여정이였지만 보람찬 공부가 되었다. package me.sungbin; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.*; @Retention(RetentionPolicy.RUNTIME) @Target({TYPE, FIELD}) @Inherited public @interface MyAnnotation { String value(); }  📚 참조https://b-programmer.tistory.com/264http://javaparser.org/inspecting-an-ast/

백엔드인프런워킹업스터디클럽백엔드미션어노테이션

xx

[인프런 워밍업 클럽 스터디 0기] 회고

인프런 워밍업 클럽 스터디 0기가 마무리되었다. 참여하게 된 계기우선 백엔드 전체 사이클을 경험할 수 있을 것이라 생각했다. 배포 경험이 없었기에 배포 경험도 쌓고 싶은 것도 이유 중 하나이다. 좋았던 점보통의 강의는 강의를 듣고 나면 뭔가 끝인 느낌이 있지만, 스터디에서는 진도표를 제공하여 매일 어떤 강의를 수강해야 하는지 정해주셨다. 그래서 강의를 수강하는 것이 수월했고, 강의에서 배운 내용들을 바로 적용할 수 있도록 과제가 주어졌다. 과제를 하면서 개념을 정리하고, 실제 코드에 어떻게 적용이 되는지 적용해 볼 수 있어서 좋았다. 그리고 미니 프로젝트를 진행하면서 디스코드 채널에서 코드 리뷰를 같이 할 러너들을 모으는 글을 보고 바로 지원을 했다. 거의 1~2 주 동안 내 코드를 작성하면서 다른 사람의 코드를 리뷰해주면서 코드를 읽는 것이 얼마나 중요한지 느낄 수 있었다. 또한, 내 코드를 읽는 사람이 읽기 좋게 작성해야겠다고 느끼는 계기가 되었다. 아쉬운 점다른 공부도 같이하고 있었기에 여기에만 몰두하는 것이 쉽지만은 않았다. 스터디를 진행하면서 유연한 테이블 설계와 효율적인 쿼리 작성을 미니 프로젝트에 적용해보지 못한 것이 아쉽다. 느낀 점오프라인이라서 기대는 하지 않았지만 짧은 기간 동안 성장할 수 있었고, 앞으로 어떻게 학습해야 하는지 부족한 부분을 알게 되었다. 수료식은 오프라인으로 참여했는데, Q&A에서 강사님께서 해주신 답변이 많은 도움이 되었습니다. 스터디를 이끌어주신 최태현 강사님과 인프런 관계자분들께 다시 한번 감사 인사를 전합니다!

인프런인프런워밍업클럽스터디0기

xx 2달 전
장서윤

[인프런 워밍업 클럽 FE] 인프런 워밍업 클럽 후기

처음에 들어갔을 때는, 굉장히 넓은 회사 규모에 놀랐고, 이 시간까지 남아계신 인프런 관계자 분들을 보고 놀랐다. 저번에도 버그가 저녁 11시쯤에 고쳐지는 걸 보고, 언제 퇴근하시나.. 싶었는데,, 이게 직장인이구나..! 싶었다. 🥲 1. 🧊 아이스 브레이킹아이스 브레이킹 시간에는 프론트 강사님 + 프론트 러너 4분과 사부작사부작 대화를 나눌 수 있었다. 저녁 메뉴였던 핏짜 🍕도 굉장히 맛있었고, 소수 인원이라서 더욱 편했었다. 특히 현업에 계신 강사님과 대화할 수 있는 기회는 너무나도 좋은 기회였기 때문에, 그동안 혼자서 끙끙 앓았던 질문을 와다다 했던 것 같다. 그러다가 어쩌다보니 강사님께 포트폴리오도 보여드리고, 피드백도 받을 수 있었다.🙇‍♂ 보여드릴 때 너무 긴장되어서 손이 벌벌 떨렸지만, 진짜 오길 너무 잘했다!! 라는 생각이 계속 들었다. 2. 🧐 코치 Q&AQ&A시간에서는 코치님들이 정말 많이 고민하셔서 답변을 준비하셨구나! 라는 걸 느낄 수 있었다.가장 기억에 남는 건, 어떻게든 버텨라! 라는 거다. 여전히 나에게는 부족한 게 많고, 할 게 무진장 많이 남았지만, 어떻게든 계속 해봐야겠다 🔥 3. 🎉 우수러너 시상감사하게도 프론트 우수러너로 선정되었다. 상품으로는 멘토링권 + 인프콘 초대권 + 말랑 큐티 인프런 굿즈이다. + 완주러너 상품인 50000잎까지! 무엇보다 제일 원했던 멘토링권을 얻게 되서 너무 행복했던 것 같다. 빨리 코치님께 질문할 것들을 정리해야겠다. 사진은 인프런 굿즈이다. 에코백 + 물컵 + 우산 + 뱃지가 있는데, 정말 너무........ 귀엽다! 입꼬리가 특히 귀엽다.4. 💬 자유 네트워킹관심주제별로 조를 구성했는데, 우리 테이블에는 인프런에 근무중이신 프론트 개발자분께서 와주셨다..!사실 처음에 프론트 개발자분이 오셨으면 좋겠다.... 정말 좋겠다..... 하고 마음속으로 빌고 있었는데, 정말로 오셔서 너무 감격스러웠다! 🙇‍♂ 긴장돼서 뚝딱뚝딱하면서도 궁금했던 질문을 다 물어봤었다. 쉽게 오지 않는 기회라는 걸 알기 때문에 너무 행복했던 시간이었다. 5. 끝같은 취업준비생분들과 애기할 수 있고, 무엇보다 현업에 계신 분들과 직접 얘기할 수 있다는 게 너무 뜻깊은 시간이었던 것 같다. 여전히 부족한 게 많구나 라는 생각도 들었지만, 집에 돌아가는 길이 너무 개운하고 행복했었다. 다들 너무 고생하셨습니다! 🙇‍♂  

인프런인프런워밍업클럽스터디0기

양성빈

[인프런 워밍업 스터디 클럽] 인프런 워밍업 스터디 클럽 후기

후기어느덧 인프런 워밍업 스터디 클럽 0기가 수료식까지 마무리가 되었습니다. 처음 이 스터디 클럽을 신청할때 "과연 이 스터디 클럽이 마무리가 되었을 때 정말 얼마나 나 자신이 성장을 할 수 있을까?"라는 생각을 하게 되었습다. 그리고 지금 마무리 시점에서 정말로 성장을 할 수 있었다는 생각을 들게 되었습니다. 처음에 프로젝트를 실제로 해보지 않고 기본적인 지식들도 흔히 "대강"아는 수준이였다면 과제와 미니프로젝트를 통하여 많은 성장을 이룬 순간이였습니다. 그러면 자세한 후기글을 시작해보겠습니다.수료식오프라인 수료식을 가는 것에 들뜬 저는 수료식 예정 시간보다 너무 일찍이 도착하였습니다. 그래서 처음에 앞에서 대기좀 타다가 정각에 들어가야하나 싶었는데 다행히도 인프랩 직원분들이 따듯하게 환영인사를 맞이해주셨습니다. 또한 명찰로 제 이름을 여쭤보실때 이름을 말씀드리는 순간 살짝 감동을 받았습니다. 열심히 커뮤니티를 활동해주셨다는 말에 조금은 기분이 더 좋아진 느낌이였습니다. 그리고 테이블에 앉고 시간이 지나 다른 러너분들이 한분 두분씩 오시고 오프라인 수료식이 시작되었다는 것을 실감할 수 있었습니다.네트워킹 & 저녁식사오프라인 수료식이 시작되고 네트워킹 타임이 시작되었습니다. 테이블에 다행히도 사이드프로젝트 인원분들과 같이 자리를 할 수 있었고 커뮤니티에서 열심히 활동하시는 다른 러너분들까지 같이 하게 되었습니다. 또한 저녁식사 메뉴는 피자로 피자를 먹으면서 다른 러너분들과의 네트워킹을 할 수 있게 되었습니다. 그런데 다른 러너 한분이 다음날 건강검진 일정으로 못 드시는것을 보고 살짝 마음이 걸리긴 했습니다. 그래도 다른 인프랩 직원분들이 어떻게든 챙겨주실려고 하시는 모습을 보고 그나마 마음을 놓긴 하였습니다. 그리고 사이드프로젝트에 같이 참가하는 다른 러너분들과는 말은 네트워킹이였지만 거의 약간 1차 회의느낌으로 사이드프로젝트에 대해 이야기를 나눴던 시간이였습니다.Q&A어느덧 식사시간이 지났고 Q&A시간이 다가왔습니다. 백엔드 코치님 "최태현"님과 프론트엔드 코치님 "John Ahn"님께서 우리가 사전에 질문드렸던 질문들중 몇개를 선택하셔서 답변주셨습니다. 여기서 인상이 깊었던 질문들 중에 몇가지가 있었습니다.🙋🏻 취준 기간에 포트폴리오용 프로젝트를 어느정도의 규모로 만들어야 할까?이에 대한 답변으로 각 기업의 기술블로그에서 파일럿 프로젝트를 검색해보시라고 하셨습니다. 그 프로젝트들을 참고해보시면 좋을 것 같다고 답변을 해주셨는데 이 점에서 우리 사이드프로젝트도 다른 기업의 파일럿 프로젝트를 한번 참조해보면 좋을 것 같다고 느끼게 되었습니다.다음 질문은 정확히는 기억이 안나지만 한번 생각나는데로 적어보면 아래와 같습니다.🙋🏻 공부를 함에 있어서 더 이상 실력이 안 늘고 지루하다고 느끼는데 어떻게 할까요?이 점에 있어서 김창준님께서 집필하신 "함께자라기"에서 일부를 말씀해주셨습니다. 일단 시도를 먼저 해보시고 시도를 하다가 쉽다고 느껴지면 난이도를 좀 더 높여보고 그런데 어렵다고 느껴진다면 살짝 낮춰보고 그런식으로 적용해보면 좋다고 말씀주셨습니다. 시상식어느덧 우수러너 시상식이 시작되었습니다. 솔직한 마음으로 나름 "나도 받지 않을까?"라는 마음이 없지는 않았지만 그래도 큰 기대는 하지 않았습니다. 그리고 우수러너 발표때 아쉽게도 저는 우수러너에 떨어졌지만, 같이 사이드프로젝트를 진행하는 백엔드 러너분과 프론트 러너 두 분이 우수러너 선정이 되셨습니다. 이에 나는 너무 기뻤다고 느껴졌습니다. 우수러너가 2분이나 계시는데 뭔가 시작도 전에 천군만마를 얻은 느낌이였습니다.그런데 정말 운이 좋게도 인프랩 운영진 특별상이 추가로 있었고 바로 제가 선정되었습니다. 정말로 깜짝 놀랐고 같은 테이블 분들이 축하한다는 응원의 감사 인사에 더욱 기분이 좋았습니다. 이에 내가 열심히 활동했다는 것을 느끼게 되는 계기였습니다.쉬는시간... 막간의 코치님(최태현님)과의 멘토링쉬는시간이 되었고 코치님이 보이시길래 인사라도 드릴 겸 찾아가서 인사를 드렸습니다. 처음에는 저를 몰라보실수도 있다는 생각에 반신반의를 하면 찾아갔고 다행히도 코치님께서는 저를 기억하고 계셨고 제가 제출했던 Q&A에 대해 조언을 주셨습니다. 이에 정말 많은 도움을 주셔서 다시 한번 감사드립니다.관심사 네트워킹마지막 시간으로 관심사 네트워킹이 시작되었고 코치님과 같은 테이블을 앉게 되었습니다. 코치님이 있기에 정말 궁금했던 부분들을 여쭤볼려고 하였고 이에 대해 코치님께서도 답변을 열심히 응해주셨습니다. 또한 다른 러너분들과의 커뮤니케이션을 통하여 정말 열심히 하시는 분들도 많다는 것을 깨닫고 더욱 열심히 해보자는 마음을 가지게 되는 계기였습니다.마지막...그리고 어느덧 수료식도 마무리를 하게 되었습니다. 정말 '인프런 워밍업 스터디 클럽'을 통해 많은 것을 경험하고 깨닫는 시간이였습니다. 처음 제가 작성했던 출사표에 작성했던 손웅정 선생님의 말씀으로 이제 마무리를 지어볼려고 합니다. 정말 이 인프런 워밍업 스터디 클럽을 통해 열심히 뛰고 많이 깨지면서 더욱 성정하는 시간이 되었습니다. 또한 이런 기회를 주신 인프랩 임직원분들께 감사드리며 이 시간을 활발하게 이끌어주신 두 코치님께 감사의 인사를 전달드립니다. 마지막으로 이런 기회를 잘 이용해서 열심히 활동해주신 다른 러너분들께 감사인사를 드립니다.'인프런 워밍업 스터디 클럽'이 다른 기업의 교육프로그램인 '우x코'처럼 커지기를 바라며 1기가 개최가 되고 저에게 다시 기회가 온다면 참여해보고 싶다는 생각을 하며 이 글의 마침표를 적어봅니다. 마지막으로, 인프런 워밍업 스터디 클럽은 마무리가 되었지만 저의 학습여정은 현재진행형이므로 끝까지 달려보겠습니다.

인프런인프런워밍업클럽스터디0기

Yeji Seo

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

1주차 강의 학습 내용 요약강의를 듣기 전에는 Local styles만 사용하고 Local variables는 어렵게 느껴졌는데, 강의를 듣고 실습을 해보며 이해도를 높일 수 있는 시간이었다.학습 내용 중 특히 도움이 되었던 부분은 아래와 같다.베리어블의 계층 구조 디자인 토큰 이름 짓기색상, 간격, 그림자효과 베리어블 등록하기 초반 이론 단계에서는 이해를 하며 강의를 따라가면서도 내가 정말로 이해를 하고 있는게 맞는걸까?라는 의문이 들었지만, 이후 색상 베리어블 구조와 이름을 짜보는 과정을 통해 실습 과정이 참 중요하구나를 깨달았다. 디자인 토큰이 궁금해서 medium이나 구글링을 통해 내용을 찾아볼 때는 이해가 잘 안 됐었는데 Local Variables에 Primitive, Theme, Semantic 컬렉션을 등록하면서 흐름을 이해할 수 있었던! 회고일주일 동안 스스로 칭찬하고 싶은 점실습을 하며 이해가 안 가는 부분, 궁금한 점을 강의 노트에 적고 우선 스스로 답을 찾아보려고 한 점 아쉬웠던 점1주차 강의를 모두 듣지 못한 점아직 미션을 올리지 못했다보완하고 싶은 점커리큘럼대로 수업을 수강하고 미션은 수행하는대로 바로 스레드에 링크 공유하기!수업을 들으며 궁금한 점이 생겼을 때 우선 스스로 생각해보고 해결되지 않을 때 디스코드 채널에 질문해보기!(노션으로 강의 내용을 메모하다 인프런 강의 노트로 옮겼는데 장단점이 있는 듯 하다. 인프런 강의 노트를 사용하면 메모했던 순간으로 영상이 재생되는 게 편한데 이외에 동영상 재생에 오류가 있다던가... 텍스트를 드래그하고 싶어도 클릭으로 인식해 동영상이 다른 타임라인으로 넘어간다거나 하는 부분이 있어서 어떻게 해야 강의 내용을 편하게 기록할 수 있을지 고민 중...)  1주차 미션 미션 해결 과정색상, 간격, 타이포그래피, 그림자 효과를 베리어블 등록하는 과정은 강의 내용을 따라갔다.하지만 아이콘 등록의 경우 Union Selection을 일일이 선택해야 하는 게 사소하지만 생산성이 떨어지는 부분이라고 생각해 Union Selection의 단축키를 생성해봤다. 확실히 작업 속도가 단축되어서 만족!혹시 제 게시물을 보신 분 중 Union Selection 단축키를 등록하고 싶은 분이 계시다면... Mac의 경우 [시스템 설정] - [키보드] - [키보드 단축키]에 들어가면 단축키를 생성할 수 있습니다.응용 프로그램에서 Figma 선택메뉴 제목에 Union Selection 입력 (대소문자 구분 중요. 위의 사진대로 Union selection이라고 입력X)키보드 단축키 입력 (저는 Union의 앞글자를 따서 cmd+shift+U로 등록했어요. 다른 단축키와 충돌이 나면 안 되니, Figma에서 사용되지 않는 단축키를 입력해야 합니다.) 회고1주차 온라인 세션에서 아이콘이 깨지지 않도록 불린하는 방법을 배울 수 있었다. 이전에 아이콘이 깨질 때 어떻게 해야할 지 감이 안 왔었는데 정말 유익한 내용이었다.확실히 지원하는 플러그인이 많은 프로그램이 작업할 때 많은 도움이 되는 것 같다. 피그마에서 지원하지 않는 기능도 있을법한데...?싶어서 플러그인에 검색해보면 있는... 전세계 피그마인들... 감사합니다.. 그리고 강의를 통해서도 좋은 플러그인 정보를 많이 얻을 수 있었다! 강사님께도 감사합니다.. 🍀 

UX/UIFigma인프런워밍업클럽

신영우

[인프런 워밍업 스터디 클럽 1기 디자인] 1주차 발자국 (신영우)

학습 내용복습을 위해 이번 주에 필기한 강의 내용을 갈무리했습니다아틀라시안 디자인 시스템 디자인 원칙/철학 : 우리는 왜 디자인 시스템이 필요한가?: 높은 품질의 UI를 구축하는 핵심 역할로써 디자인, 개발, 배포를 쉽게 할 수 있도록 돕는 것 우리 회사에 디자인 시스템이 필요한가?: 질문에 대한 핵심 답변은 디자인 부채가 발생한다는 점이다. 이는 결국 디자이너의 업무 비효율로 이어지고 이러한 업무 비효율은 개발단의 리소스 낭비로 이어진다. 전체적으로 봤을 때 팀의 손해이고 회사의 손해로 이어진다. 디자인 시스템이 있으면 좋은 점디자인 일관성 유지브랜드 강화효율적인 개발시간 단축팀 간 협업 강화빠른 온보딩유지 보수 용이높은 품질의 경험→ 디자인 시스템은 지속해 발전한다.→ 작은 성공을 이루어가며 구성원들간의 공감대를 형성해가는 것이 중요하다. 베리어블과 스타일의 차이베리어블 : 하나의 변수만 저장, 참조가 가능 / 재사용 가능한 기본 디자인 요소 스타일 : 하나 또는 다수의 변수를 저장, 참조가 불가능 / 그라디언트 ,블랜드 모드 등 다수의 디자인 요소를 적용 베리어블의 구조토큰 개념 : 이름(Name) / 값(Value) / 설명(Description) / 유형(Type) 베리어블의 이름 짓기베리어블 이름의 구조각 계층에서의 다양한 이름토큰 이름 붙이는 공식토큰 이름 예시Namespace : SystemObject : ComponentBase : Category / PropertyModifier : Variant / State / Scale 토큰 개발 실무 팁단어 통일하기80%는 미리 계획하기2~3가지 레퍼런스에서 시작하기 “좋은 음식은 좋은 재료에서 시작한다”단축키 - 베리어블 복사 : ctrl + shift + enter 우리 수업에서 가져갈 라벨링 방식: ‘Theme’ 브랜드(Brand) 부분이 추가됌→ 보통 브랜드는 1개이기 때문에 여러개일 필요 없음(나중에 실무에서 제거해도 이상 무)→ 이해를 돕기 위해 새로운 계층 생성 정리: 추가적으로 참고할 사항→ 각 요소마다 color scoping을 할 수 있음→ 특정 베리어블을 퍼블리싱하고 싶지 않을 경우 ‘_’를 붙여주면 됌 or 각 요소에서 hide 퍼블리싱을 선택해주면 됌→ 웹, AOS, iOS 플랫폼별로 대응하는 코드 이름을 만들어줄 수 있음 간격 스케일 구성: 플랫폼별 렌더링 때문에 4px, 8px unit을 사용함 홀수일 경우 렌더링 시 소수점 발생, 픽셀 퍼팩트하지 않은 상황이 벌어짐4px이 베이스 유닛이냐, 8px이 베이스 유닛이냐는 회사마다 다름 → 조금 더 섬세한 구성으로 하고 싶다 4px스페이싱에 대한 라벨링 또한 4px이 기준(ex. shopify-1)이냐 8px이 기준(atlassian-100)이냐 달라짐마찬가지로 티셔츠 사이즈 척도를 사용하는지 숫자 척도를 사용하는지 입맛에 맛게 선택하면 됌회사 사용 예시아틀라시안 - 100쇼피파이 - 1모질라 - s, m, l카본 - 01간격의 사용0~8px : 작은 UI 구성 요소 12~24px : 카드 UI 패딩, 간격 32~128px : 큰 규모의 UI, 레이아웃간격 유닛의 사용처 : 패딩 / 갭 / 보더 레디우스 / 윗스*하이트 / 보더 윗스에 사용 가능 정리Elevation 높낮이 단계단계마다 사용되는 컴포넌트 분리 → 디스크립션에 넣어서 사용 용도 노티다양한 표현법으로 Elevation 표현다양한 엘리베이션 라벨링 방법반응형 그리드 기본 용어 : 칼럼 / 거터 / 마진그리드는 ‘Fixed’와 ‘Fluid’, ‘Hybrid’가 있음단축키 - 베리어블 바로 적용 : 영역 위에 커서 올려놓고 Shift + 왼쪽 마우스 버튼  미션 내용회고를 위해 이번 주에 진행한 미션 내용을 톺아봤습니다미션 #1 - 컬러 베리어블을 로컬베리어블에 등록하고 다른 디자이너, 개발자 누구나 볼 수 있도록 문서화한다미션 #2 - 타이포 그래피 스타일, 간격 베리어블을 등록하고 Feather icon을 등록한 후 면으로 모두 바꾼다미션 #3 - 그림자 효과, 반응형 기준점, 기타 베리어블 등록하기미션 #4 - 스타일 파운데이션 최종적으로 다듬어서 일관되게 문서화해보기이번 주 미션은 총 4개로 미션 #4의 스타일 가이드 문서를 제작하기 위해 #1~#3과정을 진행하는 미션이었다.스타일 가이드는 만들어본 경험이 있기에 비교적 쉽게 만들 수 있었지만, 베리어블을 사용해서 디자인 시스템을 만들어본 적은 없었기에 미션 #1~#3과정이 꽤나 새로웠다.베리어블로 디자인 시스템을 만들면서 primitive 값을 '참조'한다는 개념이 생소해 과정이 쉽지 않았는데 볼드님의 세세하고 친절한 강의를 들으면서 따라갔기에 어느 정도 개념이 자리 잡은 것 같다(혼자 만들었으면 엄청나게 헤맸을 것 같다)미션 #4를 끝난 현재 아직도 참조 개념이 어렵지만, 다음 주 컴포넌트를 만들면서 조금 더 익숙해지면 좋겠다.베리어블을 자유롭게 사용할 수 있게 되는 그날까지 계속 달려나가 보자! 스스로 칭찬하고 싶은 점 : 생각했던(예상했던) 퀄리티로 스타일 가이드를 만든 점아쉬웠던 점 : 아이콘 백터 깨지는 친구들을 다듬는데 꽤나 많은 시간을 사용한 점보완하고 싶은 점 : 스트로크 아이콘 뿐만 아니라 필 아이콘들도 갖춰놓고 싶다다음주 목표 : 지금처럼 매일매일 빠지지 않고 미션 팔로업 잘 해서 우수 수강생이 되자!

UX/UI디자인시스템베리어블피그마

이양구

[인프런 워밍업클럽 스터디 FE 0기] 후기

0.반년을 일하면서 어떻게든 잘 버티고 있다고 생각했다."간단하게 인풋에 키랑 아이디 넣고 버튼 누르면 삭제되는 html이면 될 것 같아요."새폴더 > index.htmlvs code의 빈 공간이 이렇게나 낯설고 막막하게 느껴질 줄은 몰랐다. 1.나도 나를 잘 모르지만, 얼마나 게으른 사람인지는 잘 안다.어떻게든 날 밀어붙일 계기가 필요하다 생각하고 이것저것 알아보다가 인프런에서 진행하는 스터디를 알게 됐다.무작정 신청하고 들어온 스터디엔 생각보다 많은 사람이 있었고 그만큼이나 열심히 노력하시는 러너님들이 가득했다. 2.사실 스터디 초반엔 이미 다 알고 있는 부분이라 생각해 적당히 강의를 봤던 적도 있었다.그리고 첫 과제를 진행하는 순간 내가 왜 이 스터디를 신청했던 건지 몸소 느낄 수 있었다.생각보다 과제는 하루이틀만에 끝낼 수 없었고 남은 기간 동안 얼마나 할 수 있을지 계산적으로 생각하기도 했지만, 이게 무슨 의미인가 싶어 반쯤은 체념하고 대신 열심히만 하자고 마음을 먹었다.그런데 적당히 포기하고 마음을 놓으니 오히려 오기가 생겼던 것 같다.그 뒤로부터 출근하면서 강의 보고, 퇴근하면서 강의 보고, 집에 와서 과제하고, 주말에는 더 몰아서 강의 보고 과제하고...며칠, 몇 주를 그렇게 지냈다. 3.퇴근하고 디스코드에 들어가면 늦은 시간에도 늘 접속해 계셨던 몇몇 러너님들이 계셨는데 하루쯤 쉴까 싶은 날에는 그런 러너님들을 보며 나를 바로잡곤 했다.그중 한 러너님께서 사이드 프로젝트 인원을 모집한다는 글을 올리셨고, 또다시 나를 밀어붙이기 위해 과감하게 연락을 드려 좋은 기회를 가지게 됐다.이번 워밍업 스터디를 신청하길 잘했다고 가장 크게 느꼈던 점은 정말 많은 분들이 개발에 대해 공부하고 있고 실천하고 있다는 걸 눈으로 확인하고 몸소 느꼈던 부분이 아닐까 싶다.게다가 생각지도 못 했던 우수 러너가 되었다..!나를 선정해주신 코치님에게 감사한 마음과 그만큼 앞으로 더 잘해야겠다는 다짐을 다시 한번 하게 됐다.우연한 기회에 만난 인프런, 그리고 스터디가 내게 많은 전환점이 될 수 있을 것 같아 감사하다는 말씀을 전하고 싶다. 4.사실 원동력의 팔할은 나보다 더 노력하는 러너님들을 향한 시샘과 존경이었다.

프론트엔드인프런인프런워밍업클럽스터디0기

lwisekiml

[인프런 워밍업 클럽 0기] BE 후기

여느 때처럼 인프런 강의를 들으러 사이트에 들어왔더니 인프런 워밍업 클럽을 모집한다는 배너가 보였습니다. 혼자 공부를 하다 보니 목표를 세워도 미루기도 하는 식이였는데 인프런 워밍업 클럽에 참여하면 미션도 있고 미니 프로젝트도 있다고 하여 참여하였습니다. 앞부분은 아는 내용도 많아서 쉬웠지만 뒤로 갈 수로 공부하며 진행하였고 내가 궁금했던 부분들은 이미 다른 분들이 질문을 해서 답변을 얻은 것들을 보면서 공부했습니다. 중간중간 코치님의 라이브를 통해 현재 회사에서는 어떻게 일을 하고 어떤 것을 사용하고 문제를 어떻게 해결하는지 등 많은 내용을 공유해 주셨고 마지막 라이브 때는 열정적으로 2시간 40분 정도 라이브를 해주셨습니다. 열정적으로 알려주셔서인지 시간이 너무 빨리 간 느낌입니다. 수료식 때는 온라인으로 참여하였고 여기서도 많은 것을 알 수 있었고 많은 도움을 받을 수 있었습니다. 러너 분들이 포기하지 않고 완주 목표를 달성할 수 있게 도와주시고 배려 해주시는 운영진분들, 하나라도 더 알려주시는 코치님 그리고 열심히 참여하셨던 러너 분들과 함께할 수 있어서 뜻깊은 시간이 된 것 같습니다. 다음에도 기회가 된다면 참여하고 싶습니다.

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

7마리상어

[인프런 워밍업 클럽 BE 0기] 후기

인프런 워밍업 클럽 후기 이제 막 스프링 부트에 대한 지식을 쌓기 시작한 단계라서 이것저것 어려운 점들이 많았는데 이번에 인프런 워밍업 클럽 스터디를 진행한다는 소식을 듣고 지원하게 되었습니다. 솔직히 처음에는 제가 이 스터디를 잘 따라갈 수 있을지도 의문이었고, 중간에 뒤쳐지진 않을까 걱정도 되었습니다. 그런데 의외로 생각했던 것 만큼 어렵지 않았고, 강사님께서도 정말 쉽게 설명해주셔서 이해하는 데 큰 무리가 없었습니다. 또한 7일차에 거친 과제들과 8일차부터 진행한 미니 프로젝트를 통해 배우는 것에서 그치지 않고 직접 실습 하여 조금 더 제 것으로 만들 수 있었고, 이러한 과제들이 제가 강의를 듣는 데에 소홀해지지 않도록 도움을 준 것 같습니다. 또한 중간중간에 진행했던 Q&A를 통해서 공부를 하다가 막힌 부분이나 더 궁금했던 부분에 대하여 강사님께 직접 물어보고 바로 답을 얻음으로써 몰랐던 지식들을 채워나갈 수 있었고, 특히 다른 러너분들께서 질문 하시는 것들이 궁금했던 것 이외에도 도움이 될 만한 질문들이 많았어서 덕분에 여러 지식을 얻는데 큰 도움을 얻었습니다. 이번 3주간의 인프런 스터디의 경험은 스터디를 시작하기 전과 후의 저가 많이 바뀌게 해주었고, 그만큼 저에게 매우 유익한 시간이었습니다. 다른 러너분들과 함께 지식도 공유하고, 계속해서 스터디를 진행한 결과 이전에는 이해하지 못했던 이론이나 깨닫지 못하는 것들을 시간이 지나고서 이해하게 되었고, 스프링 부트의 전반적인 구조에 대해 익힐 수 있었습니다. 덕분에 이제까지는 들어도 무슨 소리지 했던 내용들이 지금에서는 완벽하게는 아니지만 어떤 내용인지에 대해서는 이해할 수 있게 되었을 정도로 성장했음을 느낍니다! 솔직히 가끔 나태해 질 때가 몇 번 있었는데 다른 러너분들께서 적극적으로 질문도 하시고, 과제나 발자국 제출 등 열심히 하는 모습들을 보니 저도 열정을 넘겨받아 더욱 열심히 참여하게 되었습니다. 평소에 혼자 공부하는 편이었어서 하기 싫을 때 그냥 던져 둘 때가 많았었는데 함께하는 러너분들이 있어서 저도 의지가 계속해서 생겨나서 끝까지 도달할 수 있었습니다. 짧지만 정말 좋은 경험이었고, 다음에도 인프런 스터디를 진행하게 된다면 꼭 참여하고 싶습니다!!

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

xicodey

인프런 워밍업 클럽 후기

독학도 하면서 부트캠프 하는 와중에, 뭔가 새로운거에 도전하고 싶었습니다. 그와중에 인프런에서 워밍업 클럽이라는것을 한다고 하기에 참여하기로 결정을 했습니다.결론적으로 말하자면 뜻밖에 좋은 스터디 공부였다고 생각합니다.스터디 하기 전에 강의는 옛날에 다한 강의 였지만, 진도표를 보고 다시 복습하고 그 내용에 맞는 과제를 하면서 내가 무엇이 부족하고 그 동안 공부한것을 정리하는 시간을 가지게 되어 좋은 개발자로 한발자국을 내딛을 거라 생각합니다. 또한, 무엇보다 중간 Q&A 한 다는 것을 까먹어서 처음거는 놓치고 두번째 부터 참여했습니다.온라인 라이브 세션에서 코드 리뷰나 질문에 대해 자세히 설명해주셔서 배울게 너무 많구나 생각하면서 유익한 시간을 보낸거 같습니다.물론 강의랑 과제는 다했으나 완주 러너에 대상이 안되었지만, 이런 스터디는 처음 참가하는거라 신선했으며 좋은 경험을 얻었다고 생각합니다. 여러 사람들의 코드를 보면서 내 코드와 비교하는것도 좋은 경험인거 같습니다.수료식은 온라인으로 했습니다. 인프런 참여 행사는 거진 판교인거 같아서 시간도 너무 저녁이고 멀기에 가지 못 한게 아쉽네요. 시간적으로 낮이나 장소를 홍대나 서울 안쪽에서 했으면 갈 수 있을거 같은데 항샹 판교에 하신거 같아 참여하기 힘든거 같습니다. 결과적으로, 인프런 워밍업 클럽에 참여한 것은 좋으 결정이었습니다. 그 동안 독학과 학교 공부와 부트 캠프로 해왔지만,거기서 얻지 못 한 경험이 있기 때문에 유익했습니다. 다른 분들이 적극적으로 하시는 분들도 계시고 물론 저는 소극적인 성격때문에 잘 못한게 문제였지만, 유익한 지식을 주신 코치님들과 운영을 영실히 하려는 인프런분들과 여러 수강생분들이 있어 뜻깊은 시간을 보낸거 같습니다. 다음에도 기회가 있으면 참여하고 싶습니다.

인프런인프런워밍업클럽스터디0기

ailen22

[인프런 워밍업 클럽 BE 0기] 인프런 워밍업 클럽 후기

[인프런 워밍업 클럽 후기]인프런 강의를 듣던 중 인프런 워밍업 클럽을 모집한다는 소식을 듣고 고민하다가 결국은 도전해보자하여 듣게 되었는데 많은 것을 얻었던 시간이였습니다. 2일차부터 과제를 제출하는데 굉장히 어려움이 있었고 강의를 듣는 시간보다 그 과제를 제출하기 위해 공부했던 시간이 거의 4배는 되었던 것 같습니다. 질문도 하나씩 읽어보면 이해가 안가서 '기본지식도 없이 뛰어든 사람은 나뿐인가? 다른분들은 다들 너무 잘하시는 것 같은데'라는 생각이 들기도 하였습니다. 그래도 시간을 할애하다보니 조금씩 이해가 되어가기 시작했고 거의 마지막 주에 다시 질문들을 읽어보니 이해가 가고 도움을 얻기도 하였습니다.중간에 1차 OT를 까먹고 못들어서 스트레스도 굉장히 받았는데 그래도 포기하지 않고 과제를 제출하고 강의를 듣다보니 만회할 기회를 주셔서 감사하였습니다. 그리고 다른 분들의 코드를 보면서 정말 다양한 방법으로 풀어나가는 모습을 보면서 신기하기도 하였습니다. 그러면서 문제를 푸는데 있어서 새로운 방법을 알게되기도 하였습니다. 미션이 없었다면 사실 강의를 이해하지 못한채로 끝나지 않았을까 싶기도 합니다. 다른 러너분들도 열정이 넘치셔서 같이 얼떨결에 끌려간 것 같지만 정말 후회는 되지않는 수업이였던 것 같습니다. 마지막까지 열심히 Q&A를 진행하시는 모습을 보고 많은 감동을 느꼈습니다. 정말 감사합니다!

인프런인프런워밍업클럽스터디0기

또니

[인프런 워밍업 클럽 0기 BE] 오프라인 수료식 후기

[오프라인 수료식 후기]3주간의 시간이 지나고, 워밍업 클럽 스터디가 끝나면서 오프라인 수료식을 다녀왔다.[첫번째 순서]낯을 조금 가리는 탓에 처음 도착해서는 앉아서 멀뚱멀뚱 사무실만 구경하고 있었다.감사하게도 같은 테이블에 계신 러너분께서 먼저 대화를 걸어주셔서 수료식 시작 전까지 신나게 대화하였고,다른 러너 두분께서 추가로 오셔서 첫번째 순서인 저녁 식사를 하며 또 다시 수다 타임을 가졌다.[두번째 순서]식사를 마치고 두번째 순서는 지식 공유자분들의 Q&A 타임이었다.질문은 사전에 러너분들께서 작성해주신 질문에서 몇개 골라 선정된 질문들이었다.취업에 관한 질문, 개발자에 대한 질문 등등 여러가지 질문들이 있었는데, 그동안 내가 많이 고민했던 질문들이 많았고내가 고민했던 것과 지식공유자분들이 답변해주신 것과 일치해서 조금은 안도(?) 하였다.🤣[세번째 순서]이후 세번째 순서는 우수러너 시상식이었다. 나는 처음부터 우수러너에 대한 기대는 크게 없었다.블로그도 누군가에게 보여주기 보다는 내가 공부하고 기록하는 곳으로 사용했고 깔끔하게 작성하는 편도 아니다.열심히 해보겠다는 의지는 강했지만 실력자분들이 많아 이런 쉬운 질문을 해도 될까? 라는 생각에 질문을 망설였다.(조금 더 찾아보니 혼자서도 충분히 해결 가능했던 질문들이 많았다ㅎㅎ)위와 같은 이유로 우수러너는 포기하였고, 완주와 내 실력 향상에 초점을 맞추어 묵묵히 열심히 하였다.그런데!!우수러너 명단에 내 이름이 있던 것이었다!!감사하게도 우수러너로 선정되어 인프런의 귀여운 굿즈를 받게 되었다!다시 한번 감사드립니다.[마지막 순서]그렇게 기쁜마음으로 시상식을 마치고 마지막 순서인 네트워킹을 가졌다.조별로 나누어 앉았고 각 조별로 코치님과 인프런 개발자 한분씩 들어가 네트워킹을 가졌다.내가 있던 테이블에는 인프런에서 5년째 일하고 계신 프론트엔드 개발자분이셨고,현재 취업 시장이 어떤지, 현업에서는 어떻게 일하는지 등등 유익한 이야기를 나누며 수료식은 끝이 났다.[스터디를 하면서 느낀점]그동안 공부하면서 이해되지 않았던 부분이 이번 강의를 통해 이해가 되어 고구마 100개 먹은 가슴이 뻥 뚫렸고,궁금한 부분에 대해 해결하고 고민하는 방법을 얻을 수 있어서 좋았다.이전엔 오류가 나고 해당 매서드에 대해 궁금하면 무작정 인터넷을 먼저 찾았지만이제는 해당 매서드에 들어가서 어떤 것들로 구성되어 있고, 해당 오류는 어떤 오류인지 공식문서나 해당 코드를 통해먼저 생각하고 고민해보는 습관이 형성되어 좋았다.짧다면 짧고 길다면 긴 3주동안 재미있게 공부하며 즐겼던 스터디였다.스터디를 진행해주시고 늦은 시간까지 수료식을 위해 자리를 만들어주신 인프랩 임직원분들,바쁘실텐데 중간 중간 깜짝 특강을 진행해주시고 예정된 시간이 지나도 목소리가 쉬어가며 질문과 정보 전달을 위해열정을 보여주신 최태현 코치님께 감사인사 드립니다.그리고 3주간 함께 달리신 러너분들 고생 많으셨습니다!😁

백엔드백엔드인프런워밍업클럽0기

채 수

인프런 워밍업 클럽 후기

[인프런 워밍업 클럽 참여 후기]부트캠프를 마치고 독학 중인데, 제대로 공부하고 있는지 의문이 많았습니다. 그래서 인프런 워밍업 클럽에 참여해보기로 결정했습니다. 이 스터디에 참여한 경험은 정말 값진 것이었습니다.먼저, 진도표를 따라 매일 강의를 수강하고 발자국을 작성하는 것이 매우 도움이 되었습니다. 주말에는 과제를 마무리하고 발자국을 작성하는 시간을 가지면서, 내가 어떤 것을 배웠는지 정리할 수 있었습니다. 이를 통해 제 학습 내용을 정리하고 실제로 습득한 지식을 확인할 수 있었습니다.또한, 온라인 라이브 세션에서는 코치의 특강이나 Q&A 세션을 통해 중간 점검을 받을 수 있었습니다. 코치와 함께 진도를 되돌아보고 질문에 대한 답변을 듣는 것은 매우 유익했습니다. 그리고 스터디의 끝을 알리는 수료식에서는 이 스터디를 통해 얼마나 발전했는지를 되돌아보는 소중한 시간을 가졌습니다. (온라인으로 수료식을 참가해서 아쉬웠습니다 ㅠ)가장 인상 깊었던 점은 코치님들이 직접 제작한 미션을 수행하는 경험했었습니다. 이를 통해 배운 내용을 다시 한 번 복습하고 응용하는 기회를 가질 수 있었습니다. 또한, 다른 참가자들의 발자국을 보면서 서로의 학습 경험을 공유할 수 있어서 좋았습니다.총론적으로, 인프런 워밍업 클럽에 참여한 것은 매우 값진 경험이었습니다. 부트캠프를 마치고도 지식을 유지하고 발전시키기 위한 좋은 방법이라고 생각합니다. 다른 분들에게도 적극 추천하고 싶습니다.유익한 지식을 주신 코치님들, 스터디 클럽을 위해 힘써주신 인프런 분들, 같이 달린 학생들, 또한 이 글을 읽어주신 분들 모두 감사합니다.

인프런인프런워밍업클럽스터디0기

양성빈

[인프런 워밍업 스터디 클럽] 0기 세번째 발자국 (feat. 마지막 발자국 ㅠㅠ)

발자국어느덧 인프런 워밍업 스터디 클럽 마지막 주차가 다가왔다. 매우 즐겁기도 했지만 한편으로는 매우 아쉬운 마음이 너무 걸렸다. 이런 기회가 자주 있었으면 하는 마음으로 마지막 발자국(회고)를 시작해보겠다.강의 요약Day10. 객체지향과 JPA 연관관계조금 더 객체지향적으로 개발할 수 없을까?우리는 지난 시간까지 책 생성 API를 개발하고 대출과 반납기능까지를 개발완료하였다. 하지만 여기서 이런 의문사항이 들 수 있다. SQL 대신에 ORM을 사용하게 된 계기는 "DB 테이블과 객체는 패러다임이 다름" 때문이다. 우리가 사용하는 Java는 객체지향 언어이고 요즘 서비스 진행중인 웹 어플리케이션도 절차지향적이기 보단 객체지향적으로 구성되어 있는 코드들이 많을 것이다. (개인적인 뇌피셜) 그래서 우리가 20강에서 배운 스프링 컨테이너도 객체지향 설계라는 지점에서 출발하게 되었다. 즉, User 객체와 UserLoanHistory를 협업시킬 수 없을까? 즉, 대출기능을 개발할때 BookService가 UserLoanHistory 객체를 만들어 저장하고, 그것을 User객체가 가져오는 방식이였다. 뭔가 BookService를 거쳐가야한다는게 걸린다. 즉, BookService로직은 User객체가 가져와 사용하고 User객체가 직접 UserLoanHistory와 상호작용을 하면 좋을 것 같다. 반납기능도 대출기능과 동일하게 바꾸면 좋을 것 같다. 이렇게 바꾸려면 조건이 존재한다. User객체와 UserLoanHistory가 서로 존재한다는 것을 인지해야 한다. 이것을 위해 연관관계 개념이 등장하였다. 대표적으로 N:1 관계가 존재한다.🙋🏻 N:1 관계란?예시로 들어보자. 어느 한 교실에 여러명의 학생이 존재할 수 있다. 이 때 학생은 N이고 교실은 1이다 이것을 N:1관계라고 부를 수 있다.그럼 관계를 설정하고 나서 다음으로 할 일은 연관관계 주인이 누구인지 알아야한다. 현재 우리의 실습 소스에서 user와 user_loan_history의 테이블을 보면 아래와 같다.create table user ( id bigint auto_increment, name varchar(25), age int, primary key (id) );create table user_loan_history ( id bigint auto_increment, user_id bigint, book_name varchar(255), is_return tinyint(1), primary key (id) );여기서 연관관계 주인을 누구로 할까? 쉽게 생각해서 N:1관계에서 N쪽이 보통은 연관관계 주인이라고 생각하면 쉽다.그리고 연관관계 주인이 아닌쪽에는 mappedBy 속성을 추가해줘야 한다. mappedBy의 속성의 값으로는 관계에 설정된 클래스에 선언된 자신의 객체의 변수명을 적어주면 된다. 실제 코드를 살펴보면 아래와 같이 변경이 가능하다.User.java@Entity public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id = null; @Column(nullable = false, length = 20) private String name; private Integer age; @OneToMany(mappedBy = "user") private List<UserLoanHistory> userLoanHistories = new ArrayList<>(); protected User() { } public User(String name, Integer age) { if (name == null || name.isBlank()) { throw new IllegalArgumentException(String.format("잘못된 name(%s)이 들어왔습니다.", name)); } this.name = name; this.age = age; } public Long getId() { return id; } public String getName() { return name; } public Integer getAge() { return age; } public void updateName(String name) { this.name = name; } }UserLoanHistory.java@Entity public class UserLoanHistory { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id = null; @ManyToOne private User user; private String bookName; private boolean isReturn; protected UserLoanHistory() { } public UserLoanHistory(User user, String bookName) { this.user = user; this.bookName = bookName; this.isReturn = false; } public void doReturn() { this.isReturn = true; } }위의 코드처럼 N쪽에 @ManyToOne 어노테이션을 붙여주고 관계를 맺는 객체를 선언해준다. 그리거 1쪽도 마찬가지로 관계를 맺는 객체를 선언해주고 위에 @OneToMany 어노테이션을 선언해준다. 이런 방식을 양방향 연관관계라고 부르며, 한쪽만 연관관계를 맺을 시 단방향 연관관계라고 부른다. 이렇게 연관관계의 주인의 값이 설정되어야만 진정한 데이터가 저장된다.그럼 BookService는 어떻게 변경을 하는지 살펴보자.BookService.java// 5. 유저와 책 정보를 기반으로 UserLoanHistory를 저장. this.userLoanHistoryRepository.save(new UserLoanHistory(user, book.getName()));이제 위와 같이 user의 id값을 저장하는게 아닌 user 객체를 직접 저장할 수 있다.JPA 연관관계에 대한 추가적인 기능들1:1 관계예를 들어 한 사람과 실거주지의 관계가 딱 1:1 관계이다. 그러면 연관관계 주인은 어느 객체일까? 설정하기 나름이지만 주어진 상황은 사람이 연관관계 주인이라 생각하는게 좋을 것이다. 그러면 코드로 표현하면 아래와 같을 것이다.Person.java@Entity public class Person { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id = null; private String name; @OneToOne private Address address; public Long getId() { return id; } public String getName() { return name; } public Address getAddress() { return address; } public void setAddress(Address address) { this.address = address; this.address.setPerson(this); } }Address.java @Entity public class Address { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String city; private String street; @OneToOne(mappedBy = "address") private Person person; public Long getId() { return id; } public String getCity() { return city; } public String getStreet() { return street; } public Person getPerson() { return person; } public void setPerson(Person person) { this.person = person; } }🔥 연관관계 주인 효과연관관계 주인을 설정하는 것은 객체가 연결되는 기준이 된다.1. 상대 테이블을 참조하고 있으면 연관관계의 주인2. 연관관계의 주인이 아니면 mappedBy를 사용3. 연관관계의 주인의 setter가 사용되어야만 테이블 연결즉, 아래처럼 setter를 이용하여 연결이 가능하다.@Transactional public void savePerson() { Person person = this.personRepository.save(new Person()); Address address = this.addressRepository.save(new Address()); person.setAddress(address); }⚠ 주의만약 트랜잭션이 끝나지 않았을 때 한쪽만 연결해두면 반대쪽은 알 수 없다. 그래서 위의 코드에서 address.getPerson()을 출력을 하면 null이 뜰 것이다. 왜냐하면 지금은 현재 person만 address를 연결해줬기 때문이다. address는 person을 연결해주지 않았기 때문이다.그럼 해결책은 없을까? 객체안에 연관관계 편의 메서드를 만들어 두 객체의 setter를 호출하면 해결이 된다.N : 1 관계 - @ManyToOne과 @OneToMany위에서 언급을 했지만 @ManyToOne과 @OneToMany는 둘다 양방향으로 연결을 할 수 있지만 단방향 연결도 가능하다. 또한 이 어노테이션들을 이용하면서 새롭게 배우는 어노테이션이 있는데 바로 @JoinColumn이다.@JoinColumn- 연관관계의 주인이 활용할 수 있는 어노테이션.- 필드의 이름이나 null 여부, 유일성 여부, 업데이트 여부 등을 지정- 일종의 @Column 어노테이션과 유사하다고 생각하면 좋다.N : M 관계 - @ManyToMany구조가 복잡하고, 테이블이 직관적으로 매핑되지 않아 사용하지 않는 것을 추천한다고 하셨다. 실제로 실무에 근무하는 분들한테 이야기를 들으면 N:M은 많이 사용하지 않고 꼭 이런식으로 처리해야할 경우면 N:1과 1:N으로 풀어쓴다고 하셨다.cascade 옵션 & orphanRemoval 옵션한 객체가 저장되거나 삭제될 때, 그 변경이 폭포처럼 흘러 연결되어 있는 객체도 함께 저장되거나 삭제되는 기능.JPA에는 Entity들 사이의 연관관계를 정의할 때 사용할 수 있는 영속성 전이라고 하는 Cascade 옵션이 있다. 이 옵션을 이용해서 부모에 가해지는 변화를 자식에게 전파할지에 대해 설정할 수 있다.@OneToMany로 자식들을 갖고 있는 부모 객체만 저장/삭제 해도 자식 객체도 함께 저장/삭제 된다던지, 하는 효과를 누릴 수 있다.JPA에는 Entity들 사이의 연관관계를 정의할 때 사용할 수 있는 옵션 중에 orphanRemoval 라는 것이 있다. 이 옵션을 이용하면 부모가 자식에 대한 참조를 끊을 때, 참조가 끊어진 자식 Entity(고아 객체)를 DB에서 삭제하도록 설정할 수 있다.만약 어떤 회원이 책 2권을 대출했다고 하자. 그리고 그 회원이. 갑자기 회원탈퇴를 해서 DB에서 사라졌다. 그럴 경우 많이 이상하게 책 2권이 연결되어 있던게 끊어진 상태가 된다. 이상한 구조일 것이다. 즉, 회원이 삭제될 때 유저 대출기록도 같이 삭제해두는게 좋을 것이다. 그리고 이와 같이 쓰는 옵션이 바로 orphanRemoval 옵션이다.@OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true) private List<UserLoanHistory> userLoanHistories = new ArrayList<>();위의 코드처럼 사용하면 부모객체의 저장/삭제해도 자식 객체도 함께 전파되면 삭제시, 자식 객체도 같이 삭제된다.책 대출/반납 기능 리팩토링과 지연로딩이제 우리가 만든 대출과 반납기능을 리팩토링 해보자. 리팩토링 할 부분은 무엇일까? 현재 코드를 보면 도메인 계층에 비즈니스 로직이 들어가져 있다. 또한 여기서 영속성 컨텍스트 4번째 옵션이 나오는데 바로 지연로딩이다.데이터를 처음에 한번에 로딩을 안하고 꼭 필요한 순간에 데이터를 로딩시킨다. 바로 @OneToMany의 fetch옵션의 default 값이다. 지연 로딩을 사용하게 되면, 연결되어 있는 객체를 꼭 필요한 순간에만 가져온다.그러면 우린 이제까지 연관관계를 맺고 주인을 정하고 지연로딩, cascade, orphanRemoval옵션을 이용해서 리팩토링과정을 거쳐보았다. 이렇게 연관관계를 이용하면 뭐가 좋을까?📖 연관관계 장점1. 각자의 역할에 집중할 수 있다. = 응집성2. 새로운 개발자가 코드를 봤을 때 이해가 쉬워진다.3. 테스트 코드 작성에 용이하다.그러면 무조건 연관관계 맺는것이 좋을까? 그렇지는 않다! 연관관계를 남발해서 사용하면 지나치게 사용하면, 성능상의 문제가 생길 수도 있고 도메인 간의 복잡한 연결로 인해 시스템을 파악하기 어려워질 수 있다. 또한 관계가 복잡하면 하나의 테이블 수정 시, 다른 테이블까지 영향을 끼칠 수 있다. 강의중에서도 코치님께서 아래와 같이 말씀주셨다.비즈니스 요구사항, 기술적인 요구사항, 도메인 아키텍처 등 여러 부분을 고민해서 연관관계 사용을 선택해야 한다.Day11. 기본적인 배포를 위한 준비배포란 무엇인가?배포란 무엇일까? 배포는 제 3자의 사용자가 우리가 만든 서비스를 전달하는 과정이라고 볼 수 있다. 우리는 지금 현재 우리의 개인 PC에다가 개발을 하고 웹을 띄워보며 테스트를 해보았다. 하지만 영희가 우리의 서비스를 이용할려하면 어떻게 할까? 현재 상황에서는 나한테 연락을 하고 우리집에 방문해서 사용하고 가야할 것이다. 물론 영희 1명이고 내가 집에 있다고 한다면 가능하다. 하지만 영희 혼자가 아니라 100만명이 우리의 서비스를 이용한다면 정말 고민이 많을 것이다. 또한, 내가 잘때 갑자기 철수가 오겠다고 하면 나는 잠을 자지도 못하고 철수가 우리집에 올 때까지 기다려야 할 것이다.그래서 나는 좋은 생각을 한다. 제3의 컴퓨터를 빌려서 우리의 웹 어플리케이션을 띄우는 것이다. 그리고 나의 친구들에게 그 컴퓨터 IP주소를 알려주면 된다. 이 과정을 배포과정이라고 한다. 그러면 이 컴퓨터는 누구한테 빌릴까? 네이버, 구글등 다양한 컴퓨팅 서비스를 해주는 곳은 많지만 대부분 아마존을 이용한다. 또한 배포를 위해 컴퓨터를 빌릴때 운영체제를 선택도 해야한다.profile과 H2 DB여기서 우리는 문제를 직면한다. 우리의 코드를 제3의 컴퓨터에서 실행시킬 때 DB같은 자원정보를 변경해줘야 한다. 이런 불편함에 이런 생각을 하게 된다. 코드변경 없이 우리의 컴퓨터에서 실행할때 우리의 DB가 연결이 되고 제3의 컴퓨터에서 실행할때는 제3의 컴퓨터에 설치된 DB가 연결되어야 한다. 즉, 똑같은 코드로 실행환경에 따라 설정을 다르게 하고 싶다. 이때 바로 profile을 이용하는 것이다. 현재 우리는 지금 profile이라는 것을 사용하고 있다. 바로 "default" profile을 사용한다. 아무것도 설정을 안하면 해당 프로필이 자동으로 올라온다. 그럼 실제 우리의 코드에 profile을 적용해보자. 똑같은 서버 코드를 실행시키지만, local 이라는 profile을 입력하면, H2 DB를 사용하고 dev 라는 profile을 입력하면 MySQL DB를 사용하게 바꾸자.🤔 H2 DB란?경량 Database로, 개발 단계에서 많이 사용하며 디스크가 아닌 메모리에 데이터를 저장할 수 있다. 또한, 개발 단계에서는 테이블이 계속 변경되는데 어차피 데이터가 휘발되기 때문에 ddl-auto 옵션을 create로 주면 테이블을 신경쓰지 않고 코드에만 집중할 수 있다! 그래서 개발단계나 테스트에서 H2 DB를 많이 사용한다.그러면 적용한 yml은 아래와 같이 될 수 있다.pring: config: activate: on-profile: local datasource: url: "jdbc:h2:mem:library;MODE=MYSQL;NON_KEYWORDS=USER" username: sa password: driver-class-name: org.h2.Driver jpa: hibernate: ddl-auto: create properties: hibernate: show_sql: true format_sql: true h2: console: enabled: true path: /h2-console --- spring: config: activate: on-profile: dev datasource: url: "jdbc:mysql://localhost/library" username: "root" password: "" driver-class-name: com.mysql.cj.jdbc.Driver jpa: hibernate: ddl-auto: none properties: hibernate: show_sql: true format_sql: true여기서 --- 은 프로필을 구분하는 표시선이라 생각하면 좋다. 그리고 DB 접속 url에 MODE=MYSQL;NON_KEYWORDS=USER 해당 옵션을 붙인 이유는 DB의 키워드중에 USER라는 것이 있기에 키워드로 설정 안하고 모드를 MySQL과 유사하게 만들기 위한 옵션이다. 또한 h2.console.enabled와 h2.console.path 옵션은 해당 경로로 접속했을 때 h2 console을 사용할 수 있기 위해서이다.git과 github이란 무엇인가?!개발 관련 서적이나 자료를 찾다보면 한번쯤 보이는 주소가 있다. 바로 git이다. git이란 코드를 쉽게 관리할 수 있도록 해주는 버전 관리 프로그램이다. 이런 상황이 있다하자. A개발자와 B개발자가 협업을 하고 있다 하자. 그리고 각자 개발 후 소스코드를 합칠때 문제가 생긴다. 다른 코드들은 상관없지만 같은 파일의 코드들을 다르게 수정할 우려가 있기 때문이다. 그래서 이것을 일일이 수작업으로 확인하기엔 너무 힘들다. 이래서 git이 등장한 것이다. 또한 버전을 관리하기에 아래와 같은 사태 또한 일어나지 않을 것이다.그러면 github는 무엇일까? git으로 관리되는 프로젝트들을 관리해주는 저장소이다. 우리는 git으로 관리하는 프로젝트를 github에 저장할 수 있다. 그럼 왜 github에 저장할까? 자랑용, 공유로 저장할 수 있지만 배포가 가장 큰 이유로 볼 수 있다. 제3자의 컴퓨터에 우리의 서비스를 배포해야하는데 우리의 소스코드를 usb나 외장하드에 담아 제3자의 컴퓨터까지 가서 복사해서 할 수는 없을 것이다. 만약 집 근처면 참고 갈테지만 만약 미국의 제3자의 컴퓨터가 있다면 비행기값이 더 나올 것이다. 깃 명령어그럼 간단하게 깃 명령어를 알아보자.📚 용어git init : git 프로젝트 시작하기git remote add origin [각자 저장소 주소]: git 프로젝트의 github 저장소 설정하기git add . : 코드들을 담는다. 일종의 택배상자에 담는다고 보면 된다.git status: 현재 택배상자에 코드들이 잘 담겨져 있는지 확인하는 명령어git commit -m "메세지" : 택배상자에 송장 붙이는 명령어git push : 택배상자를 github에 보내기 택배상자를 github에 보낼 때 git push –set-upstream origin master 명령어를 최초 1번 해줘야 한다. AWS의 EC2 사용하기AWS의 회원가입 로그인 과정을 거쳐서 제3자의 컴퓨터를 빌려보는 실습을 해보았다.Day12. AWS와 EC2 배포EC2에 접속을 하려면 아래와 같은 준비물이 필요하다.1) 우리가 접속하려는 EC2의 IP 주소2) 이전 시간에 다운로드 받았던 키 페어3) 접속하기 위한 프로그램 (git CLI 혹은 Mac terminal)다운로드 받은 키 페어를 이용하는 방법ssh –i 경로/키페어이름.pem ec2-user@IP다음으로 키페어 권한을 변경해주자.chmod 400 경로/키페어이름.pem아니면 위와같은 과정이 불편하다면 AWS의 콘솔을 이용하는 방법도 있다.리눅스 명령어mkdir : 폴더를 만드는 명령어ls : 현재 위치에서 폴더나 파일을 확인하는 명령어ls –l : 조금 더 자세한 정보를 확인할 수 있다!cd : 폴더 안으로 들어가는 명령어pwd : 현재 위치를 확인하는 명령어cd .. : 상위 폴더로 올라가는 명령어rmdir : 비어 있는 폴더(디렉토리)를 제거하는 명령어프로그램 설치이제 EC2에 접속했으니 git, java, mysql을 설치해보자. 먼저 아래와 같이 리눅스 터미널에 명령어를 입력하자.sudo yum update위의 명령어의 sudo는 관리자 권한으로 실행한다는 의미이고 yum은 리눅스 패키지 관리 프로그램 (gradle과 비슷한 역할)이다. update는 현재 설치된 여러 프로그램들을 최신화한다는 의미이다.깃 설치sudo yum install gitJDK11 설치sudo yum install java-11-amazon-corretto -ymysqlsudo yum install mysql-community-server // 설치 sudo systemctl status mysqld // 현재 보이지 않는 프로그램을 관리하는 명령어 + mysql 상태 확인 sudo systemctl restart mysql // mysql 재시작 sudo cat /var/log/mysqld.log | grep “A temporary password” // mysql 임시 비밀번호 확인 mysql –u root –p // mysql 접속빌드와 실행git clone 명령어로 우리가 깃헙에 올린 프로젝트를 가져오자.git clone [github 저장소 주소]이제 빌드준비를 위해 gradlew의 권한을 변경하자chmod +x ./gradlew이제 빌드를 하자 (단, 테스트는 제외)./gradlew build –x test그럼 jar파일이 생겼을텐데, 아래와 같은 명령어로 실행시킨다.java –jar build/libs/library-app-0.0.1-SNAPSHOT.jar --spring.profiles.active=dev그럼 서버가 정상적으로 실행된다. 다음으로 서버를 중단해보자. ctrl + c를 누르면 중단된다.하지만 우리는 터미널을 닫아도 서버는 계속 실행되고 싶다. 즉, 백그라운드 재생을 하고 싶어한다. 아래와 같이 입력한다.nohup [명령어] &그러면 백그라운드로 재생된 우리의 프로그램을 어떻게 종료할까?ps aux | grep java위와 같이 현재 실행중인 프로그램 중 java가 들어가는 프로그램을 확인해서 pid값을 알아내 아래와 같이 입력한다.kill -9 프로그램번호또한 파일의 내용을 확인해 볼 수 있는 명령어도 알아보자.vi : 리눅스 편집기인 vim을 사용하여 파일을 연다.또한 vi말고도 cat 명령어도 있다.cat : 파일에 있는 내용물을 모두 출력하는 명령어또한 끝부분만 확인하고 싶을때 아래와 같이 입력한다.tail : 현재 파일의 끝 부분을 출력하는 명령어여기서 실시간으로 확인하고 싶을 경우 f옵션만 주면 된다.가비아를 이용한 도메인 구입가비아를 통해 도메인을 구입해보았다. 실제 과정은 매우 단순함으로 생략한다.Day13. SpringBoot 설정 및 버전업여기서는 내용을 조금 축약해서 작성해보겠다. 이전에 배웠던 개념이기도 하고 중요하지만 실습적인 부분은 아니기에 간략히 작성한다. 우리는 여기서 gradle의 구성에 대해 알아보았다. 이 gradle 파일안에는 플러그인 설정, 의존성 설정, 저장소 설정등을 확인할 수 있었다. 또한 스프링이 어떻게 생겨났는지 스프링부트는 또 어떻게 생겨났는지 이 둘의 차이는 무엇인지 알 수 있었다. 그리고 yaml 문법과 properties 문법에 대해 알아보았다. 다음 우리의 프로젝트에서 롬복을 적용해서 리팩토링과정도 알아보았다. 마지막으로 스프링부트 버전을 3.x로 바꾸어보았다. gradle에서 스프링부트 버전을 변경하고 빌드할때 달라진 부분들을 고쳐주는 작업을 해보았다.Day14. 마무리 및 꿀팁우리는 여기서 앞으로의 공부 방향성, AWS 비용계산방법, myBatis 적용, 정적파일 처리방법을 배웠다. 나는 여기서 느꼈던 점은 공부 방향성에 있어서 코치님 말씀대로 코틀린 및 스프링의 다양한 모듈에 대해 접근해볼 예정이다.또한 이 수업에서 myBatis를 적용해보았는데 개인적으로 내 스프링부트 버전이 myBatis starter 몇 버전을 쓰는지 복잡함을 느꼈다. 또한 여전히 문자열로 쿼리를 작성한다는게 나한테에 있어서 많은 불편함을 느꼈다. 하지만 여기서 코치님은 대용량 데이터를 insert할때 jdbcTemplate을 이용한 batch 쿼리 실습을 해주셨는데 시간차이를 보니 완전 신세계였다. 이 부분에 대해 좀 더 자세히 알아봐야겠다.미니 프로젝트나는 미니프로젝트를 개발해가면서 많은 어려움과 좌절을 맛 보았다. 1단계는 나름 간단해서 별거 없네라는 식으로 넘어갔다. 하지만 다른 러너분들과 리뷰과정에서 많이 고쳐야 할 점을 보았다. 또한 단계가 갈수록 코드가 점점 개판이 되어간다는 나 자신이 너무 싫었고 특히 마지막 단계는 밤을 꼬박 새워서 해결할 수 있었다. 공공데이터포털로 법정공휴일 api를 가져오려 했지만 이 api가 몇번 타임아웃이 발생한다. 이 문제때문에 시간을 쏟은것은 안 비밀!리뷰중에는 왜 이렇게 작성했냐부터 이렇게 바꾸는 것이 어떤가의 대해 의문점을 던져주셨고 이것을 깊이 통찰하는 시간이 나를 성장하는 계기를 만든 것 같다. 자세한 개발과정은 1단계와 똑같은 절차로 해결했으니 1단계 개발일지를 참조해보시면 좋을 것 같습니다. 개발일지https://inf.run/rF31s PR1단계: https://github.com/crispindeity/warming-up-study-mini/pull/82단계: https://github.com/crispindeity/warming-up-study-mini/pull/93단계: https://github.com/crispindeity/warming-up-study-mini/pull/134단계: https://github.com/crispindeity/warming-up-study-mini/pull/15 최종 머지한 내 프로젝트https://github.com/SungbinYang/warming-up-study-mini/tree/main/sungbin/mini회고드디어 스터디클럽의 여정이 끝났다. 정말 힘들고 출사표때 전달했던 많이 부딧혔고 깨졌다. 그러면서 나는 점점 성장을 해 나간것 같다. 비록 1달이라는 짧다면 짧은 여정이였지만 내 학습의 여정은 아직 끝이 안 났기에 계속 달려볼려고 한다. 이 클럽을 수료하더라도 혹은 1기로 다시 재 신청을 하더라도 내 본연의 학습여정은 계속 될 것이며 그 여정동안 많이 깨지고 부딪히면서 점점 성장하는 개발자 양성빈이 되어야겠다. 화이팅 🔥🔥🔥🔥 📚 참조http://www.jjal.today/bbs/board.php?bo_table=gallery&wr_id=94&sfl=wr_subject%7C%7Cwr_content%7C%7Cwr_4&stx=웃짤&sop=and&page=7

백엔드인프런워밍업스터디클럽발자국마지막

장서윤

[인프런 워밍업 클럽 0기] 2주차 발자국 👣

이번 발자국은 과제 진행 과정을 작성해 볼 예정이다. 목차는 다음과 같다.1. 기능 목록 작성2. 공통 컴포넌트 구현3. 결과물4. 고민했던 부분 ✅️ 1. 기능 목록 작성1. 항목 추가/수정할 수 있다.지출 항목 + 비용을 입력받는다 (조건을 만족할 때까지)지출 항목은 문자열이여야 한다.비용은 숫자여야 한다.지출 항목 + 비용 모두 입력되어야 한다. (공백 제외)  조건을 만족할 경우, 버튼이 enable 된다. 추가/수정을 완료했을 경우, toast 메시지를 띄워준다. 2. 항목 리스트를 보여준다. (테이블 형식)각 항목(row) 마다 수정/삭제 버튼이 존재한다.수정 버튼을 누른 경우[ 기능목록 1. 항목 추가/수정할 수 있다 ] 로 이동한다.삭제 버튼을 누른 경우항목이 삭제되며, toast 메시지를 띄워준다. 총 지출 금액을 보여준다.항목 리스트가 없을 경우, '존재하지 않습니다' 를 보여준다.   3. 모든 항목을 삭제할 수 있다.목록 지우기 버튼을 누른 경우모든 항목이 삭제되며, toast 메시지를 띄워준다. ✅ 2. 공통 컴포넌트 구현MUI와 같은 UI 라이브러리를 쓰지 않고, tailwind css로만 구현할 것이기에, 필요한 컴포넌트는 직접 만들어야한다. 먼저 공통된 디자인을 위해 rounded만을 사용하고자 했다. ( 컴포넌트마다 rounded를 다 다르게 사용하지 않는다)색상은 emerald + slate 만을 최대한 사용했다. 그렇게 해서 필요한 컴포넌트는 다음과 같다. Outlined Input시간을 투자한 부분이다. 기본 html의 input은 굉장히 단순하기에 커스텀이 필요했다.focus 했을 때, label 을 input 박스 위로 가게 하고, 부드러운 애니메이션을 넣고자 했다.Contained Button + Text Button배경을 채운 Contained Button오직 text 만 존재하는 Text ButtonTable기본 table에 css만 추가했다.Toast 메시지 success : 초록색 체크 아이콘추가, 수정, 삭제가 성공적으로 완료되었음을 표시한다. warn : 노란색 경고 아이콘입력값의 유효성검사가 일치하지 않을때 표시한다.  ✅ 3. 결과물 ✅ 4. 고민했던 부분 지출 항목이 문자여야하는데, 이를 어떻게 판별하는가? 이다.애매한 부분이 지출 항목이 "맥북 pro 16" 처럼 오직 문자 type으로 이뤄지지 않고, 여러 type이 같이 존재할 수 있다. 그래서 이걸 어떻게 예외처리 해줄지 고민했었는데, 일단은 지출 항목을 절대 숫자로만 이뤄지지는 않을 것 같아서, isNaN()만을 판별했다. 이 부분은 고민이 더 필요할 것 같다.. toast 메시지의 색상을 어떻게 할 것인가? 이다.상품을 "삭제" 했을 경우, toast 메시지의 아이콘 색상을 고민했었다.빨간색 -> 부정적 의미 -> 삭제와 연관된다! -> 그러나 error 와도 연관됨 -> 사용자 입장에서 "에러가 났다..!" 로 혼동할 수 있음.초록색 -> 삭제가 완료되었다! 에 의미를 둠-> 그러나, 추가, 수정, 삭제도 어쨌든 완료이기에, 다른 기능임에도 아이콘 색상이 같아서 구별이 어렵다는 문제가 존재함.고민 끝에 error와 연관되는 빨간색보다는 초록색으로 가되, "추가", "수정", "삭제" text 를 크고 두껍게 처리해주는 것으로 합의를 보았다!후기UI 라이브러리만 사용하다가, tailwind css로 직접 컴포넌트를 만드니까, 생각보다 시간이 오래 걸렸다. 중간에 계속 애니메이션도 적용된 라이브러리를 사용하고 싶었지만, 이를 css로(비록 tailwind css지만) 직접 완성시켰을때 상당히 뿌듯했다!또한, 기능목록을 제대로 작성한건지 모르겠다. 조금 더 깔끔하게 작성하고 싶은데, 어디까지 자세하게 적어야하는지, ui 부분도 자세하게 적어야하는지(버튼 색깔이 바뀐다거나)를 잘 모르겠다. 더 공부해봐야겠다!  

웹 개발프론트FE워밍업클럽

최경희

[인프런 워밍업 클럽 0기] FE 2주차

2주차 학습 요약(8일차는 중간 점검으로 학습할 강의가 없었습니다.)7일차 - 프로젝트 만들기자바스크립트만으로 Stop Watch 앱과 할 일을 추가하고 삭제하는 Todo 앱, SpeadSheet(엑셀) 앱의 기능을 구현하고, 꾸미는 방법을 배웠습니다. 앱을 만들면서 localStorage를 사용하는 방법을 새로 알 수 있었습니다. 9일차 - 리액트 기본 및 Todo 앱 만들기리액트란 강의에서 리액트에 대한 개념과 리액트에서 사용하는 컴포넌트에 대한 개념 및 종류를 알 수 있었고, 리액트의 가장 중요한 특징인 가상돔을 알기 위해 브라우저가 렌더링하는 과정을 함께 배웠습니다. 그 외 리액트를 사용하기 위한 여러가지 환경 설정을 하는 방법을 알 수 있었습니다. Todo 앱을 만들면서 리액트의 주요 기능인 JSX와 State, Props, Hooks를 배울 수 있었고, 그 외 CSS 프레임워크 중 하나인 TailWind CSS에 대해서도 배울 수 있었습니다. 10일차 - 리액트로 Netflix 만들기Netfilx 클론 앱을 만들면서 API를 사용하는 방법과 axios를 사용하는 방법, 커스텀 Hooks을 작성하는 방법에 대해 배울 수 있었고, Styled Component 라는 CSS 관련 라이브러리를 사용하여 꾸미는 방법과 react-router-dom을 사용하여 페이지 전환을 하는 방법을 새로 알 수 있었습니다. 미션 해결 과정► 과제 총 합본 : https://www.inflearn.com/blogs/6988Day2 미션 : 음식 메뉴 앱각 메뉴를 클릭할 때, 메뉴에 맞는 음식 리스트를 보여주는 앱 입니다.음식 메뉴가 아닌 투썸 플레이스 카페 메뉴로 변경했고, 메뉴 부분의 스타일과 전체적인 색상을 변경했습니다.이미지는 투썸 플레이스 카페의 홈페이지에서 이미지 주소 복사를 통해 가져왔는데, 저작권 문제 때문에 저작권 문제가 없는 다른 이미지를 구해야하나 고민하고 있습니다. 스타일을 수정할 때 가장 시간이 오래 걸렸는데, 간격 조절이 가장 어려웠던 것 같습니다. 저번주에 막혔던 화면 크기로 인한 넘침 문제를 조금이나마 고칠 수 있게 되어, 현재 화면 크기에 따라 한줄에 나열되는 음식 아이템들의 개수가 동적으로 변경되게 했습니다. 처음에는 맥에서 진행해서 몰랐는데, 윈도우에서는 스크롤 바로 인한 밀림 현상이 있는 것을 알게 되어 스크롤 바를 항상 보이게 하는 것으로 수정했습니다. Day3 미션 : 가위 바위 보 앱컴퓨터와 진행하는 가위 바위 보 게임으로 총 10번을 진행하여 승부를 내는 앱 입니다.전체적인 디자인과 색상을 변경했고, 가위, 바위, 보 대신에 아이콘을 사용하여 표현했습니다.저번 주에 진행했던 것과 다르게 전체적으로 다시 꾸몄습니다. 태그 마다 간격을 설정하는 것이 가장 어려웠는데, 사용하는 맥과 윈도우의 화면 크기 차이로 인해 서로 다르게 보이는 문제가 있었고, 최대한 화면 크기와 상관없이 동일한 위치에서 보일 수 있게 개발 했습니다. Day4 미션 : 퀴즈 앱수학 연산 관련 질문이 나오고, 2~3개의 답변 중 맞는 답변을 선택하면 배경이 초록색이 되고 틀린 답변을 선택하면 배경이 빨간 색이 되는 앱 입니다.맞춤법 관련 퀴즈 앱을 만들었습니다. 전체적인 디자인을 변경했고, 배경이 아닌 선택한 답변의 버튼 색이 바뀌게 했습니다. 또한 마지막에 맞은 답변의 개수를 알 수 있게 했습니다.네이버의 한글날 맞춤법 테스트 사이트를 참고하여 만들었습니다. 질문 개수를 많이 만들어서 질문이 랜덤으로 나오게 하고 싶었지만 시간이 없어서 못한 것이 아쉬웠습니다. 다음에 시간이 생기면 변경해보고 싶고, 이것을 바탕으로 심리 사이트 앱을 만들어도 괜찮겠다는 생각을 하게 되었습니다. Day5 미션 : 책 리스트 나열 앱 책 이름과 저자를 입력하여 제출하면 책 리스트에 추가가 되며, 삭제할 수도 있고 추가 및 삭제가 발생할 때마다 알림이 나오는 앱 입니다.전체적인 색상만 변경하고, 구조는 과제 영상과 비슷하게 만들었습니다. 또한 제출 버튼을 클릭했을 때 이름과 저자를 모두 입력하지 않으면 제출되지 않게 만들었습니다.다른 과제처럼 저만의 디자인으로 변경하고 싶었지만, 시간도 부족하고 생각나는 디자인이 없어 과제 영상과 비슷하게 만든 것이 아쉬웠습니다. 다른 과제를 진행하면서 간격 조절하는 것이 익숙해진 것인지 태그들의 간격을 정하는 것이 다른 과제에 비해 수월하게 진행됐습니다. Day9 미션 : 예산 계산기 앱 지출 항목과 비용을 입력하여 제출하면 리스트에 추가되고 리스트에 있는 모든 항목의 총 지출 값을 확인할 수 있으며, 수정 및 삭제가 가능하고 추가,수정,삭제가 발생할 때마다 알림이 나오는 앱 입니다.전체적인 색상만 변경하고, 과제 영상과 비슷하게 만들었습니다. 또한 지출 항목을 입력하지 않으면 제출이 되지 않게 만들었습니다.처음 만드는 리액트 앱이라 만드는데 시간이 오래 걸렸습니다. 알림이 나오고 일정 시간이 지나면 사라지는 기능을 구현할 때 문제가 생겼었습니다. 알림이 연속적으로 추가됐을 때, 각 알림을 기준으로 3초 후에 사라져야 하는데 마지막으로 추가된 알림을 기준으로 3초 후에 첫 알림이 사라지기 시작하는 오류였습니다. 리액트라서 어려울 거라 생각하고 복잡하게 생각해서 생긴 문제로, 현재는 오류가 해결되어 잘 작동됩니다. Day10 미션 : 디즈니 플러스 앱API를 사용하여, 구글 연동 로그인을 진행하고 영화 리스트와 상세 정보를 확인하고 검색도 가능한 앱 입니다.현재 개발 중으로 아직 완성되지 않았습니다. 회고스터디 이전에 리액트 기초에 대해 조금은 공부하고 와서 개념은 알고 있는 상태였습니다.하지만 리액트를 사용하여 프로젝트를 진행한 적은 한번도 없어서 리액트 강의가 좀 어려웠습니다. 특히, API를 사용하여 개발을 해본 적이 없어 이해하기가 어려웠습니다. 그래서 과제인 디즈니 플러스 앱을 만들어 보면서 API를 사용하는 방법에 대해 자세히 알아보려고 합니다.결국 시간이 없어서 자바스크립트 관련 과제는 4개만 완성할 수 있었습니다. 그리고 지금 제 상태를 봐서는 리액트 관련 과제도 전부 완성할 수는 없을 것 같아 아쉽습니다. 과제를 진행하면서 직접 생각하고 알아보는 과정을 통해 제 실력이 늘고 있다는 것이 느껴져 스터디가 끝나고 난 후에라도 남은 과제를 만들려고 합니다.다음주 동안 최대한 리액트 과제를 열심히 만들어서 적어도 4개의 과제를 완성하고 싶습니다.

프론트엔드

Dream

[ 인프런 워밍업 클럽 Study FE 0기 ] Week 2 발자국

발자국워밍업 스터디 클럽이 2주 차에 접어들었습니다. 해당 발자국은 따라 하며 배우는 리액트 A-Z (섹션 0-5) 중심으로 작성되었습니다.요약React를 사용하려면 Node.js가 필요하다. Node.js를 설치하면 NPM도 같이 설치되니 꼭 Node.js를 설치하자. Node.js 공식 홈페이지에 접속하면 2개의 Node 버전이 있는데, 그중에서 안정적인 버전인 LTS를 설치하면 된다. Section 01. React[ React란? ]리액트는 사용자 인터페이스(user interface, UI)를 만들기 위해서 사용되는 자바스크립트의 라이브러리다. 리액트는 인터렉션이 많은 웹 앱을 개발하기 위해서 주로 사용된다. 이렇게 사용자 인터페이스를 만들기 위해 도움을 주는 TOOL로는 리액트 말고도 Vue.js와 Angular.js가 있다.React: 라이브러리Angular, Vue: 프레임워크[ Framework vs Library ]프레임워크와 라이브러리를 대략 설명하자면 다음과 같다.Framework : 어떠한 앱을 만들기 위해 필요한 대부분의 것을 가지고 있다.Library : 어떠한 특정 기능을 모듈화 해 놓은 것이다.프레임워크는 앱을 만드는데 필요한 대부분의 라이브러리를 가지고 있으며, 라이브러리들은 특정 기능을 위해 모듈화 되어있다.리액트는 라이브러리이다. 왜냐? 리액트는 전적으로 UI를 렌더링 하는 데 관여하기 때문이다. 리액트는 여러 모듈을 사용하며 앱을 관리한다.라우팅: react-router-dom …상태관리: redux, mobx …빌드: webpack, npm …테스팅: Eslint, Mocha …[ React Component ]리액트를 공부하다보면 무조건 마주치는 단어가 있다. 바로 컴포넌트이다. 리액트는 컴포넌트 기반이라고 하는데, 이 컴포넌트는 무엇을 말하는 것일까?컴포넌트(Component): React로 만들어진 웹/앱을 이루는 최소한의 단위리액트는 이 컴포넌트를 통해서 웹/앱을 개발하게 된다.리액트는 여러 컴포넌트 조각으로 되어있다. 이것은 블록같다고 생각하면 된다. 여러 블록 조각을 맞추고 쌓아 올려 하나의 블록 작품을 완성하는 것. 리액트도 마찬가지로 컴포넌트를 이리저리 조합하고 쌓아올려 하나의 웹 페이지를 구성하게 된다.리액트 컴포넌트에는 2가지가 있다.클래스형 컴포넌트함수형 컴포넌트React는 여러 컴포넌트 조각으로 구성된다.개인적인 설명을 덧 붙이자면 리액트는 레고 블럭과 같다고 생각한다. 레고 블럭들을 하나 둘 씩 쌓아 올려 하나의 완성된 레고 작품을 만드는 것이다.[ Component 종류 ]React는 2개의 컴포넌트 종류가 있다.클래스형 컴포넌트(Class Components)class App extends Component { render() { return <h1>Hello, ReactJS!</h1>; } }함수형 컴포넌트(Functioanl Components)function App() { return <h1>Hello, ReactJS!</h1>; }💡 현재 함수형 컴포넌트를 HOOK이랑 해서 많이 사용한다.💡 참고로 컴포넌트를 작성할 때 반드시 대문자 시작을 해야 한다. 소문자 시작 시 body, h1, p 같은 DOM 태그로 인식해 버린다.[ 브라우저가 그려지는 원리와 가상 돔 ]React의 가장 큰 특징은 가상 돔(Virtual DOM)이다. 이것을 사용하는 이유는 인터렉션 때문이다. 이 인터렉션에 의해 DOM에 변화가 발생하면 다시 DOM을 재구성하기 시작한다.JS 발자국에도 남겼었지만 웹 브라우저의 경우 다음과 같은 과정을 겪고 이 과정은 비용이 꽤 든다.Critical Render Path (웹 페이지 렌더링 과정): 데이터 파싱(HTML) ➔ DOM Tree 생성 ➔ CSSOM Tree 생성 ➔ JS 실행 ➔ Render Tree 생성 ➔ Layout 생성 ➔ PaintDOM을 재구성 한다는 것은 위 렌더링 과정을 다시 반복한다는 것이다. 즉, 인터렉션이 일어날때마다 위 과정을 다시 한다. 이것을 보완하기 위해서 나온 것이 가상 돔이다.가상돔 과정을 살펴보자..!데이터가 바뀌면 가상 돔에 렌더링 되고, 이전에 생긴 가상 돔과 비교를 해서 바뀐 부분만 실제 돔에 적용 시킨다.바뀐 부분을 찾는 과정을 Diffing이라고 부른다.바뀐 부분만 실제 돔에 적용 시키는 것을 Reconciliation(재 조정)이라고 부른다.[ Create React App 을 이용해서 리액트 설치하기 ]create-react-app 을 통해서 원하는 위치에 리액트를 설치할 수 있다. 이 때, Webpack과 Babel이 함께 설치가 된다. 따라서 React 앱 생성 전에 Webpack과 Babel에 대해서 간단히 알고 가자.Webpack정의: Webpack: 웹팩은 오픈 소스 자바스크립트 모듈 번들러써 여러 개로 나누어져 있는 파일들을 하나의 자바스크립트 코드로 압축고 최적화하는 라이브러리이다.장점여러 파일의 자바스크립트 코드를 압축하여 최적화할 수 있기 때문에 로딩 줄일 수 있. (네트워크 비용 줄음)모듈 단위로 개발이 가능하여 가독성과 유지 보수가 쉽다.Babel정의: 최신 자바스크립트 문법을 지원하지 않는 브라우저들을 위해서 최신 자바스크립트 문법을 구형 브라우저에서도 돌 수 있도록 변환 시켜주는 라이브러리이다.⇒ 이러한 Webpack과 Babel은 개발자가 React 개발 시 알아서 설정 해야 하지만 Create-React-App을 사용해서 React 앱을 생성하면 Babel이나 Webpack 설정이 이미 되어있기 때문에 준비 시간이 단축된다.[ Create-React-App ]프로젝트를 진행할 폴더 생성VSC에서 해당 프로젝트 폴더 열기Termial에 npx create-react-app 생성할파일명 입력강의에서는 npx create-react-app ./을 입력하였다../는 현재 위치를 뜻한다.[ npx create-react-app 에 대하여 ]npx: 노드 패키지 실행을 도와주는 도구이다.npx create-react-app이란 npm 레지스트리에 잇는 패키지를 ./에 실행시켜서 React를 설치해 주는 것이다.실행하는 방법실행하고자 하는 리액트 파일 위치에서 npm run start 입력(강의에서는 npm run start방법만 소개시켜 주셧는데 npm start도 가능하다.)🤔 개인적으로 요즘 vite에 관한 이야기가 보이는데 이도 조사해 보아야겠다… Section 2. 간단한 To-Do 앱 만들며 리액트 익히기[ create react app ]create-react-app으로 리액트를 설치하면 여러 파일이 등장하는데, 이 중에서 절대로 이름을 수정해서는 안되는 파일이 존재한다.public/index.html: 페이지 템플릿src/index.js: 자바스크립트 시작 점조심하자!💡그리고 우리가 새로 js, jsx, css 등 직접 생성할 파일들은 src 폴더에서 하면 된다. Webpack이 src/ 부분에만 작동하기 때문이라고 한다.[ package.json ]해당 프로젝트에 대한 정보들이 들어있다. 프로젝트 이름, 버전, 필요한 라이브러리와 라이브러리들의 버전이 명시되어 잇다.[ 싱글 페이지 애플리케이션(single-page application, SPA) ]싱글 페이지 애플리케이션(single-page application, SPA)은 서버로부터 완전한 새로운 페이지를 불러오지 않고 현재의 페이지를 동적으로 다시 작성함으로써 사용자와 소통하는 웹 애플리케이션이나 웹사이트를 말한다.위키백과React.js는 SPA이다. 즉, 어떠한 데이터에 관한 교체 이벤트가 발생했을 때, 서버로부터 페이지를 새롭게(html 파) 받아와 구성하는 것이 아니라 content를 바꿔치기 한다. 이는 HTML 5의 History API를사용해서 가능하게 만든다.[ History API ]전통적인 웹 사이트는 a page에서 b page로 이동할 때 a.html을 보여주다가 b.html을 보여주면 되었지만 SPA의 경우 오직 1개의 HTML(index.html)이 존재한다. 따라서 페이징 전환을 하기 위해서 HTML 5 History API를 이용한다.History.back(): 세션 기록의 바로 뒤 페이지로 이동하는 비동기 메서드History.forward(): 세션 기록의 바로 앞 페이지로 이동하는 비동기 메서드History.go(): 특정한 세션 기록으로 이동하게 해 주는 비동기 메서드History.pushState(): 주어진 데이터를 세션 기록 스택에 넣어준다.History.replaceState(): 최근 세션 기록 스택의 내용을 주어진 데이터로 교체한다.생성했던 React 프로젝트에서 public/index.js를 살펴보면 <div id="rood"></div>가 있다.그리고 src/index.js 코드에는 document.getElementById('root')라는 코드가 있다.자바스크립트 파일의 시작 점인 src/index.js에서 id값이 rood인 요소를 찾아 그곳에 해당 요소들을 렌더링하는 것이다. 즉, div라는 최상위 루트 노드 아래에 직접 정의한 요소를 더해 화면을 꾸며나가는 것이다!![ JSX ]JSX는 Javascript Syntax Extension의 약자로 자바스크립트의 확장 문법이다.리액트에서는 이 JSX를 이용해서 화면에서 UI가 보이는 모습을 나타내준다.JSX 사용이 필수는 아니나 사용하면 가독성이 너무 좋아서 필수 아닌 필수이다. (애초에 리액트 개발자들 대부분이 JSX를 사용한다고 한다.)JSX는 createElement를 쉽게 사용하기 위해서 사용한다.모든 UI를 만들때 마다 createElement를 사용해서 컴포넌트를 만들 수 없다.Ract는 React.crateElemnt API를 사용해서 엘리먼트를 생성한 후에 이 엘리먼트를 In-Memory에 저장한다. 그리고 RaectDOM.render 함수를 통해 웹 브라우저에 그린다.JSX를 사용하면 Babel이 사용한 문법을 crateElemnt로 자동 변환해준다. 따라서 그냥 개발자는 자유롭게 JSX 사용하면 된다.단, JSX는 컴포넌트에 여러 요소가 있다면 반드시 부모 요소 하나로 감싸줘야 한다.// 안된다. // 자식 요소가 여러 개 라면 부모 요소로 감싸줘라. function hello() { return ( <div>Hello, Raect!</div> <div>Hello, Wrold!</div> ); } // 이렇게 말이다. function hello() { return <div> <div>Hello, Raect!</div> <div>Hello, Wrold!</div> </div>; }💡 만약 JSX에서 JS 코드를 사용하고 싶다면 { } 내부에 작성해주면 된다.[ React와 Key ]map()을 사용한다면 언제나 명심해야 하는 것. KEY. 이것을 넣지 않는다면 에러가 발생한다.React에서 요소의 리스트를 나열할 때는 Key를 넣어줘야 한다. Key는 React가 변경, 추가 또는 제거된 항목을 식별하는 데 도움이 된다.추가적으로, 이 Key에 지정하는 값은 순회하고자 하는 목록의 아이템에 대한 ID 값이면 된다. 즉, 고유한 값이여야 한다. 정 없으면 index 넣어도 되지만 index 값은 권장하지 않는다.리액트는 가상 돔을 이용해서 바뀐 부분만 실제 돔에 적용한다. 그렇다면 리스트를 나열할 때 바뀐 부분만 어떻게 찾을까? 바로 이 key를 이용해서 어떠한 부분이 바뀌었는 인식하는 것이다.[ state ]정말 정말 중요한 개념!!!리액트에서 데이터가 변할 때 화면을 다시 렌더링 해주기 위해서 React State를 사용한다. State란 무엇일까?간단히 말해서 변수이다.단, 이 변수의 값이 변경되면 컴포넌트들이 재렌더링 된다.state에는 리액트의 흐름에 관한 데이터와 관련이 있다. Section 3. To-Do 앱 최적화 하기[ React HOOK ]엄청나게 중요하다. 이 HOOK은 클래스형 컴포넌트처럼 함수형 컴포넌트에서도 state와 생명주기 메서드를 사용할 수 있도록 해주는 메서드이다.클래스 형 컴포넌트에서는 Mounting, Updating, Unmounting 3단계 따라서 생명주기 메서드를 제공한다.Mounting: componentDidMount()Updating: componentDidUpdateUnmounting: componentWillUnmount()함수형 컴포넌트에서는 이를 위해 HOOK을 사용한다.[ HOC(Higher Order Component) ]화면에서 재사용 가능한 로직만을 분리해서 component로 만들고, 재사용 불가능한 UI와 같은 다른 부분들은 parameter로 받아서 처리하는 방법이다.HOC는 HOOK이 나오기 전에 사용했던 부분이다.Wrapper가 많아지면 흐름 파악이 어려워서 이제 잘 안 쓴다.HOC를 만들고 싶으면 Custom HOOK을 사용하자.[ HOOK ]기본적으로 알고 있어야 할 HOOK은 다음과 같다.useState()리액트의 유동적인 데이터들은 state에 담아 사용하기 위해 이용하는 HOOK클래스형 컴포넌트의 setState와 같이 state 객체에 대한 업데이트 실행단!!! state 변경 시 재 렌더링이 일어남useEffect()사이드 이팩트 처리 HOOK클래스형 컴포넌트의 생명 주기 함수 역할 수행useMemo()최적화 용 HOOK, 의존성 배열에 따라 작동의존성 배열에 있는 값이 변하면 지정한 함수를 실행하여 해당 반환 값을 반환useCallback()최적화 용 HOOK, 의존성 배열에 따라 작동의존성 배열에 있는 값이 변하면 함수를 반환useRef()요소의 참조를 위해 사용하는 HOOK[ Props ]Props는 Properties의 줄임말상위 컴포넌트에서 하위 컴포넌트로 데이터를 전송하고 싶을 경우 사용읽기 전용으로 자녀 컴포넌트에서 강제로 이 값을 변경할 수 없다.전달 받은 props가 state고 이 값을 바꾸고 싶다면 props로 set함수를 넘기고 이것을 이[ TailWindCSS ]HTML 안에서 CSS 스타일을 할 수 있게 해주는 CSS 프레임워크빠른 스타일 작업 가능id 혹은 class 명을 작성하기 위해 머리를 혹사 시키지 않아도 된다.class에 특정 키워드를 넣어서 CSS 조작정해진 속성 키워드가 워낙 많으니 공식 홈페이지 검색 필수다[ 리액트 불변성 ]불변성을 지키며 개발을 하자!참조 타입에서 객체나 배열의 값이 변할 때 원본 데이터가 변경되면 예상치 못한 오류가 발생할 수 있다.불변성을 지킬 수 있는 참조 관련 메서드:spread operator, map, filter, slice, reduce불변성을 해치는 참조 관련 메서드:splice, push[ React.memo ]React.memo는 Higher-Order Components(HOC)이다. 불필요한 컴포넌트 렌더링을 방지할 수 있게해준다. (일종의 최적화 용 HOC) Section 4-5. Netflix 앱 만들기주로 실습 내용 이었다. 정리할 이론만 추려내 보겠다.[ Styled Component ]자바스크립트 파일 안에서 CSS를 처리할 수 있게 해주는 라이브러리[ React Router Dom ]React Router DOM을 이용하면 웹/앱에서 동적 라우팅을 구현할 수 있다. 라우팅이 실행 중인 앱 외부의 구성에서 처리되는 기존 라우팅 아키텍처와 달리 React Router DOM은 앱 및 플랫폼의 요구 사항에 따라 컴포넌트 기반 라우팅을 용이하게 한다.React Router DOM을 사용하기 위해서는 몇 가지 설정을 해야한다.index.js에서 BrowerRouter로 루트 컴폰너트를 감싸준다.BrowserRouter은 HTML 5 History API를 사용하여 UI를 URL과 동기화 된 상태로 유지해준다.import { BrowserRouter } from 'react-router-dom'; const root = ReactDOM.createRoot(document.getElementById('root')); root.render( <React.StrictMode> <BrowserRouter > <App /> </BrowserRouter> </React.StrictMode> ); 여러 컴포넌트 생성 및 라우트를 정의한다.Routes와 Route를 사용한다.Routes: 앱에서 생성될 모든 개별 경로에 대한 컨테이너 상위 역할을 한다.Route: 단일 경로를 만드는 데 사용된다.path 속성: 원하는 컴포넌트의 URL 경로를 지정한다.element 속성: 경로에 맞게 렌더링 되어야 하는 컴포넌트를 지정한다.import { Routes, Route } from "react-router-dom"; function App() { return ( <div className="app"> <Routes> <Route path="/" element={<Home />}> <Route path="about" element={<About />} /> <Route path="contact" element={<Contact />} /> </Route> </Routes> </div> ); } +) <Link />를 통해 경로 이동하기Link 구성 요소는 HTML의 a 태그와 유사하다.to 속성은 링크가 유저를 데려가는 경로를 지정한다.앱 구성 요소에 나열된 경로 이름을 생성했기 때문에 링크를 클릭하면 경로를 살펴보고 해당 경로 이름으로 구성 요소를 렌더링한다.import { Link } from "react-router-dom"; function Home() { return ( <div> <h1>홈페이지</h1> <Link to="about">About 페이지를 보여주기</Link> <Link to="contact">Contact 페이지를 보여주기</Link> </div> ); } [ 중첩 라우팅 ]라우팅은 중첩 처리가 가능하다.[ Outlet ]자식 경로 요소를 렌더링하려면 부모 경로 요소에서 Outlet를 사용해야한다.하위 경로가 렌더링될 때 중첩된 UI가 표시될 수 있다.부모 라우트가 정확히 일치하면 자식 인덱스 라우트를 덴더링하거나 인덱스 라우트가 없으면 아무것도 렌더링하지 않는다.[ useNavigate ]경로를 바꿔준다.naviate(”/home”) ⇒ localhost:3000[ useParams ]:style 문법을 path 경로에 사용했다면 useParams()로 읽을 수 있다.function test() { return ( <Routes> <Route path="invoices/:invoiceId" element={<Invoice />} /> </Routes> ); } function Invoice() { let params = useParams(); return <h1>Invoice {params.invoiceId}</h1>; } [ useLocation ]현재 위치의 객체를 반환현재 위치가 변경될 때마다 일부 side effect를 수행하려는 경우 유용하다.[ useRoutes ]<Routes>와 기능적으로 동일하나 <Route> 요소 대신 자바스크립트 객체를 사용하여 경로를 정의한다.일반 <Route> 요소와 동일한 속성을 갖지만 JSX가 필요하지 않는다.[ Custom HOOK ]개발자가 정의하는 HOOK이다.HOOK의 이름은 use로 시작해야 한다.참고로 HOOK은 함수형 컴포넌트 또는 커스텀 HOOK에서만 호출이 가능하다.따라서 커스텀 HOOK도, 함수용 컴포넌트 또는 HOOK 내부에서 호출되어야 한다.강의에서는 useDebounce과 useOnClickOutside HOOK을 만들었다.useDebounce: input 요소에서 데이터 입력이 발생하면 설정한 set함수 때문에 매번 state 값이 바뀌고 재 렌더링이 일어난다. 따라서 keyup 이벤트의 처리를 지연시키는 커스텀 HOOK이다. (코드는 강의를 참고하자!)useOnClickOutside HOOK: 모달 창 밖의 부분을 클릭하면 해당 모달 창이 꺼지는 기능을 수행하는 HOOK이다. (코드는 강의를 참고하자!)이런 식으로 HOOK을 만들고 활용하는구나 싶었다…미션과제 총 합본 https://www.inflearn.com/blogs/7021 JS 미션 03. 퀴즈 앱[ 구현 해야하는 기능 ]1. 퀴즈 문제, 문제에 해당 하는 선택지 (선택지의 갯수가 매번 다름)2. 답 선택 시, 정답 여부에 따라 배경의 색상이 변경되어야 함문제는 data.json을 직접 작성하여 동적 생성했습니다. JS 복습 겸으로 해당 주제로 퀴즈 앱을 간단하게 만들어 봤습니다. 미션을 진행하며 문제는 없었습니다. JS 미션 04. 책 나열 앱[ 구현 해야하는 기능 ]1. 책 이름 입력 란2. 책 저자 입력 란3. 제출 버튼을 누르면 입력한 정보를 저장 함3-1. 제출 시 제출 했다는 안내 문구 떠야 함4. 제출된 데이터는 책 리스트에 출력 됨아이템은 다음과 같은 기능을 가져야 함5-1. 표기 할 데이터: 책 이름, 저자5-2. 각 아이템에는 삭제 기능이 있어야 함 구현하는데 문제가 없었습니다. REACT 01. 예산 계산기[ 구현 해야하는 기능 ]1. 지출 항목 입력 란2. 지출 비용 입력 란3. 제출 버튼을 누르면 입력한 정보를 저장 함3-1. 제출 시 제출 했다는 안내 문구 떠야 함아이템은 다음과 같은 기능을 가져야 함5-1. 표기 할 데이터: 지출 항목, 지출 비용5-2. 각 아이템에는 수정 및 삭제 기능이 있어야 함수정 버튼 클릭 시 수정 모드로 변경전체 삭제 기능이 있어야 함정말 막힘 없이 진행되다 딱 한 군데에서 문제를 맞았습니다. 상황에 맞게 알림을 띄우는 기능이었는데, JS에서는 아무런 문제 없이 해결했던 이 기능을 React에서 구현 하려고 하니 이상한 문제가 발생하더군요. 여러 동작을 해서 메시지가 많이 발생할 경우, 메시지가 예시처럼 모두 생성되는 것이 아니라 같은 자리에서 텍스트만 바뀌어서 출력이 되었습니다. 물론 잘 해결해서 과제를 마쳤습니다.회고워밍업 스터디의 2주 차에 진입하며 자바스크립트 공부를 마치고 새롭게 React 공부를 진행하며 React의 다양한 기술을 접하게 되었습니다. 특히 state, props, hook, 그리고 라우팅 부분은 처음에는 이해하기가 어려웠습니다. 그러나 부족한 이해를 보완하기 위해서 강의 내용을 정리하고, 추가적인 학습 자료를 찾아가며 개념을 확실히 파악하려고 노력했습니다.React 학습을 마치고 시작한 미션도 초반에는 막막함을 느꼈지만 코드를 작성해 나가며 수업 때 배운 내용을 적용해 가며 문제를 해결해 나갔습니다.워밍업 스터디도 이제 끝을 향해 가네요. 마무리되는 날까지 열심히 학습에 참여하고 미션 해결을 위해 도전해 보겠습니다. 

프론트엔드워밍업클럽FE

학생

[2주차 발자국] 인프런 워밍업 클럽 스터디 0기 FE

회고벌써 과정의 2/3가 끝났다는 것이 믿기지 않는다.일주일 간의 회고를 해보자면, 아쉬움이 크다. 이번주는 시간 투자를 많이 하지 못했기 때문이다.저번주에 의욕 넘치게 미션을 진행하느라 밀려났던 다른 일을 처리하는데에 또 시간을 썼다.앞으로 일이든 취준이든 제대로 하려면 시간 분배하는 법을 익혀야 한다는 생각이 들었다.직장 등의 일과 병행하는 다른 분들이 존경스러울 뿐이다.하지만 모두 끝냈기 때문에 이제는 공부에 전념할 일밖에 남지 않았다.모든 미션을 반드시 갈아치워버리겠다. 강의를 들으며 그동안 키워드만 알고 이해하지는 못하고 있었던 개념들을 접하면서 굉장히 반가웠다.특히 프로젝트를 구하는 글에서 종종 SPA 할 줄 아시는 분이라는 글을 봤었는데, 정확히 무슨 뜻인지이해를 하지는 못했었다. 하지만 이번에 공부하면서 정확히 알게 되어 상당한 쾌감을 느꼈다. 그밖에도 평소 무료 사이트의클론 코딩을 무작정 따라하면서 접했던 개념들을 짚고 넘어가게 되어 재미있었다.모닥불에 종종 들어오시는 강사님으로부터 유익한 정보를 얻으려면 질문할 거리가 있어야 한다. 질문할 거리가 있으려면 스스로의 힘으로는 알아내지 못하는 부분이 뭔지 구별할 수 있을 정도로 공부가 되어있어야 한다. 따라서 마지막 주 만큼은 진도를 잘 따라가 질문을 생성할 수 있게끔 되었으면 좋겠다. 리액트 및 프로젝트 부분은 특히나 한 번 보고는 잊어버릴 것 같으므로 여러번 공부를 해야할 것 같다. 시간은 한정되어있으므로 다음주는 선택과 집중이 필요해질지도 모르겠다. 이번주 반성공부 및 미션에 시간투자를 얼마 못함다음주 목표미션 모두 보강 및 완료하기(시간 부족하면 CSS 제외하고서라도)필수지식: API 통신, RESTful API, CRUD, CI/CD CSS flexbox, CSS Grid 공부하기Github README에 GIF(혹은 이미지)도 올리기 강의 요약이번주는 JS프로젝트로 자바스크립트를 마무리하고, 리액트를 시작했다.(자바스크립트 섹션 9 & 리액트 섹션 1 ~ 5)강의 요약은 기억에 남는 부분 위주로, 최대한 개념 부분만 진행했다.ReactReact에 관해리액트 컴포넌트가상 돔create react appSPAJSXReact StateReact HooksTailwindCSSStyled ComponentREACTReact에 관해React는 프레임워크가 아닌 라이브러리다.프레임워크: 어떠한 앱을 만들기 필요한 대부분의 것을 가지고있는것. 라이브러리를 포함.라이브러리: 특정 기능을 모듈화해놓은 것.보통 리액트와 잘 맞는 라이브러리와 함께 리액트를 사용한다.React Component리액트로 만들어진 앱을 이루는 최소한의 단위하나의 페이지를 구성하는 각각의 기능을 위한 컴포넌트가 있다.검색 컴포넌트, 프로필 컴포넌트, ...하나의 컴포넌트를 여러 곳에서 사용할 수 있다.리액트 컴포넌트의 두 가지클래스형 컴포넌트함수형 컴포넌트Virtual DOM(가상 돔)실제 DOM을 메모리에 복사해준 것.리액트의 큰 특징 중 하나는 가상 돔을 사용한다는 것.복습: 웹 페이지 빌드 과정(Critical Rendering Path CRP)DOM tree 생성(html문서를 읽고 렌더링할것 결정)Render tree 생성: DOM과 CSSOM 결합. 화면에 표시되는 모든 콘텐츠 및 스타일 정보를 포함Layout: 브라우저가 페이지에 표시되는 각 요소의 크기와 위치 계산Paint: 실제 화면에 그리기어떤 인터랙션에 의해 DOM에 변화가 발생하면 그 때마다 Render Tree가 재생성됨. 즉 모든 스타일을 다시 계산. Layout과 Repaint과정까지 계속 거치게 됨. 인터랙션이 많을 경우 불필요하게 DOM을 조작하는 비용이 너무 커짐.위의 문제로 나오게 된 것이 가상 돔.가상 돔의 작동방식 가상 돔 생성데이터 바뀌면 새로운 가상 돔 생성이전에 생긴 가상 돔과 새로운 가상 돔 비교(diffing: 바뀐 부분을 찾는 과정)바뀐 부분만 실제 돔에 적용(재조정. reconciliation)시킴가상 돔 장점: 요소가 많이 바뀌어도 한 번에 묶어서 실제 돔에 처리하여 돔을 조작하는 비용 줄임 Create React App리액트 설치를 위해 필요한 것들 Node.jsVisual Studio Code 리액트 앱 설치 방법npx create-react-app <폴더이름>폴더 안에 react app이 설치됨webpack과 babel을 모두 설정해줌.Webpack: 여러 파일을 하나로 모아주는 번들러. 로딩에대한 네트워크 비용 줄임.Babel: 최신 자바스크립트 문법을 구형 브라우저에서도 쓸수있게 변환시켜주는 라이브러리.SPA(Single Page Application)하나의 페이지에 담아 동적으로 화면 바꿔가며 표현.단일 html 내의 div id=root를 자바스크립트로 잡음.페이지 전환(브라우징)은 html5의 history API를 이용.전통적: Multi Page ApplicationReact는 SPA를 사용한다.JSX(Javascript syntax extension)자바스크립트의 확장 문법.UI를 나타낼 때 자바스크립트(logic)와 HTML(markup)구조를 같이 사용.JSX를 이용하면이벤트 처리 등을 더 편하게 구현할 수 있음.의무는 아니지만 훨씬 편리하여 거의 모든 사람이 리액트에서 UI를 위해 사용.JSX로 작성 -> babel이 createElement로 바꿔줌JSX는 컴포넌트에 여러 요소가 있다면 반드시 부모 요소 하나로 감싸야 한다.JSX Key 속성리액트에서 요소의 리스트를 나열할 때 넣어주는 값.React가 변경, 추가, 제거된 항목을 식별하는 데 도움이 됨.요소의 안정적인 ID를 부여하려면 배열 내부의 요소에 키를 제공해야 함.key에는유니크한값을 넣어야한다. index는 비추천.key를 이용하면 새로 그리는게 아니라 기존의 리스트를 이용해준다.React State컴포넌트의 렌더링 결과물에 영향을 주는 데이터를 갖고 있는 객체.컴포넌트 안에서 관리한다.setState 이용React Hooksclass 없이 state를 사용할 수 있는 기능.함수형 컴포넌트를 사용한다.클래스형 컴포넌트: 많은 기능, 길고 복잡한 코드, 느림, *리액트의 생명주기 사용 가능함수형 컴포넌트: 적은 기능, 짧고 심플한 코드, 빠름, *리액트의 생명주기 사용 불가*리액트의 생명주기: 컴포넌트의 시작, 업뎃, 언마운트까지의 주기위처럼 함수형 컴포넌트에서는 리액트의 생명주기를 사용하지 못했었다.그러나 React Hooks로 인해 함수형 컴포넌트에서도 생명주기 사용 가능해짐.리액트 훅스에서는 리액트 생명주기를 useEffect 안에서 다 처리를 해줄 수 있다.클래스형 컴포넌트에서는 마운트, 업데이트, 언마운트 함수 따로 생성.리액트 훅스는 HOC 대신 Custom React Hooks를 사용해 Wrapper 과다를 방지.TailWindCSSHTML 안에서 CSS 스타일을 만들 수 있게 하는 CSS 프레임워크.부트스트랩처럼 미리 세팅된 Utility Class를 활용하는 방식으로, html에서 스타일링을 할 수 있다.클래스 이름 짓기 등으로 골머리를 썩지 않아도 됨.Styled ComponentJavascript 파일 안에서 CSS를 처리할 수 있게 해주는 라이브러리.``를 사용하여 그 안에 스타일 속성들을 넣고, 변수에 할당한다.미션미션7(Day7). 타이핑 테스트 앱자바스크립트 섹션 9에서 다루었던 stopwatch앱을 복습하면서 구현을 시작했다.아직 미완성이고, 구현한 부분은 아래 부분이다.시작 화면index.html<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Typing Test App!</title> <link rel="stylesheet" href="style.css" /> </head> <body> <div class="wrapper"> <h1>타이핑 스피드 측정</h1> <div class="data-container"> <div id="errors"> ERRORS <h2>0</h2> </div> <div id="time"> TIME <h2>20S</h2> </div> <div id="accuracy"> % ACCURACY <h2>100</h2> </div> </div> <div id="sentence">아래를 클릭해서 게임을 시작하세요.</div> <input id="input" type="text" /> </div> <script src="script.js"></script> </body> </html>이 시작화면에서는 텍스트 입력 부분을 클릭하면 게임이 시작되도록 해야 하기에, event listener를 이용했다.// 1. 입력 부분에 클릭했을 때 게임 시작 input.addEventListener("click", startGame);게임 화면(이상하게도 글씨가 왼쪽으로 밀린다.)이 게임화면에서는, 기존에 저장되어있는 등의 문장을 표시해야 하며 카운트다운 타이머를 실행시켜야 한다.(input과 sentence는 코드 맨 위에 document querySelector로 가져와 지정했으나 여기선 생략함. let i, err...도.)const startGame = () => { i = 0; err = 0; sec = 20; acc = 0; interval; input.removeEventListener("click", startGame); // 1-1. 문장 보여주기 sentence.textContent = sentences[i]; // 1-2. 시간초 카운트다운 시작 interval = setInterval(timer, 1000); ...const timer = () => { sec -= 1; timeH2.innerText = `${sec}S`; if (sec === 0) { gameEnd(); } };여기서 stopwatch 프로젝트에서 배웠던 setInterval를 사용하였다.끝 화면(배치가 좀 그렇다)시간 초과가 나거나 주어진 문장을 모두 입력할 경우 이 화면으로 온다. 여기서 clearInterval를 사용하였다.const gameEnd = () => { clearInterval(interval); // 3. 타임 오버 혹은 문장 전부 클리어 // 다시 시작 버튼 활성화이 아주 사소한 부분 해결 과정에서 하고자 하는 것은 setInterval과 clearInterval의 복습이다.결론setInterval()은 주어진 함수를 주어진 간격마다 실행하는 함수이다.clearInterval()은 주어진 interval의 반복을 중단하는 함수이다.예시: hello를 1초마다 콘솔에 반복 출력하는 함수const sayHello = () => { console.log("hello"); } let interval; setInterval(sayHello, 1000); clearInterval(interval); // 반복 중단

프론트엔드

Dream

[ 인프런 워밍업 클럽 Study FE 0기 ] Week 1 발자국

들어가기 앞서...2024년의 첫 해가 밝으며, 지금까지는 단순히 관심만 갖고 있었던 웹 개발에 대한 공부를 시작해보기로 결심했습니다. 먼저 HTML과 CSS의 공부를 마치니 운이 좋게 인프런에서 JS와 ReactJS 스터디를 진행한다는 소식을 듣게 되었습니다. 이런 좋은 기회를 놓치지 않겠다고 생각하고, 워밍업 클럽에 참여하게 되었습니다.발자국OT를 참가한지 엊그제 같은데 시간은 정말 순식간에 지나가는 것 같습니다. 벌써 스터디가 시작된 지 1주차가 되었습니다. 이제 그 동안의 강의 내용을 간단하게 요약하고, 회고를 남겨 보려고 합니다. 이번 주 강의는 따라하며 배우는 자바스크립트 A-Z (섹션 0~8) 부분을 진행하였습니다.요약Section 01. 자바스크립트 기초[ Console 객체 ]자바스크립트의 console 객체는 코드를 작성하고 테스트를 할 때, 사용하기 좋은 함수를 제공해준다. 다음은 강의에서 소개한 주요 Console 객체의 함수들이다.console.log(): console에 메시지를 출력한다. console.table(): console에 배열이나 객체의 데이터를 테이블 형태로 출력한다. console.error(): console에 에러 메시지를 출력한다. console.warn(); console에 경고 메시지를 출력한다. console.time(), console.timeEnd(): 세트로 사용되며, 두 함수 사이의 코드 실행 시간을 측정한다. [ var, let, const과 스코프 ]변수/상수를 선언할 때 let, const 그리고 var 키워들 사용한다. let과 const는 ES6에 새롭게 추가된 키워드이다. var 키워드는 오래된 선언 키워드로 let과 const 사용을 권장하고 있다.let: 변수 키워드, 재선언 X, 재할당O const: 상수 키워드, 재선언 X, 재할당Xvar: 재선언 O, 재할당 O 그리고 사용한 let/const와 var 키워드에 따라 스코프가 다르게 처리된다. 스코프(scope, 유효/참조 범위)란 어떠한 변수를 참조하려고 할 때, 그 변수에 접근 가능한 유효 범위이다.let/const: 모든 코드 블록 { } 내부에서 선언된 변수는 코드 블록 내에서만 유효. var: 함수 내에서 선언된 var 변수는 함수 내에서만 유효하며, 함수 내에서 블록 내·외부에 관계없이 접근 가능. [ 호이스팅 ]코드가 실행되기 전에 변수 및 함수 선언을 로컬 범위(유효 범위)의 맨 위로 끌어 올려지는 경우를 말한다.[ 자바스크립트 타입과 타입 변환 ]자바스크립트의 데이터 타입(자료형)은 다음과 같다.원시 타입: Boolean, String, Number, null, undefined, Symbol고정된 크기로 Call Stack 메모리에 저장실제 데이터가 변수에 할당참조 타입: Object, Array데이터 크기가 정해지지 않고 Call Stack 메모리에 저장데이터의 값이 Heap에 저장되며 메모리의 주소 값이 할당 자바스크립트 변수에 저장된 값은 다른 데이터 유형으로 변환될 수 있다.명시적 데이터 변환(개발자가 직접 함수를 사용해서 변환)자동 데이터 변환(자바스크립트 자체에 의해 자동으로 변환) [ 연산 및 Math ]자바스크립트에서는 기본적인 산술 연산자, 논리 연산자, 비교 연산자를 제공한다.Math를 통해 더 많은 연산을 이용할 수 있다. [ Template Literals]Backtick(`)을 사용하여 문자열을 표현한 것을 템플릿 리터럴이라고 한다. 템플릿 리터럴을 이용하면 다음과 같은 이점이 있다.줄 바꿈이 쉽다.${}을 사용하여 내부에 표현식을 포함할 수 있게 한다. [ Loops ]for: 초기식, 조건식, 증감식을 포함하는 반복문으로 주어진 조건이 참일 경우 블록 안의 코드를 반복 실행for/in: 객체의 열거 간으한 속성들을 반복하는데 사용.while: 주어진 조건이 true일 동안 코드 블록을 계속해서 실행.do/while: 먼저 코드 블록을 실행한 후, 조건을 확인한다. 그러고 나서 조건이 true일 동안 반복 실행한다. Section 02. Window 객체 및 DOM[ Window 객체 ]브라우저에 의해 자동으로 생성된다. (자바스크립트 객체 X, 브라우저에서 제공 O)이 window 객체는 다음과 같은 역할을 수행한다.브라우저에 접근 및 조작 가능자바스크립트 코드의 전역 객체 역할 [ DOM ]문서 객체 모델(Document Object Model, DOM)요소로 이루어진 HTML 파일을 Tree 구조로 표현한 객체 모델최상단에는 document 노드가 위치해 있으며, 이를 통해 DOM 접근 및 조작 가능Critical Render Path (웹 페이지 렌더링 콰정)데이터 파싱(HTML) ➔ DOM Tree 생성 ➔ CSSOM Tree 생성 ➔ JS 실행 ➔ Render Tree 생성 ➔ Layout 생성 ➔ Paint +) 강의에서 수 많은 Property 및 Method를 소개해 주셨지만 너무 많은 관계로 생략... Section 03. Event[ Event ]만약 인프런에서 로그인 버튼을 누르면 무엇이 일어날까? 당연히 로그인 페이지로 이동할 것이다. 이렇게 웹 페이지에서 발생하는 사용자의 행동에 대응하여 브라우저에서 일어나는 특정 사건을 "이벤트"라고 한다. 자바스크립트에서는 다음과 같은 이벤트가 존재한다.UI 이벤트load, change, resize, scroll, error 키보드 이벤트keydown, keyup, keypress마우스 이벤트click, dblclick, mousedown, mouseout, mouseover, mousemove, mouseup포커스 이벤트focus, blur폼 이벤트input, change, select, reset, submit, cut/copy/paste 이벤트를 등록하기 위해서는 addEventListener()를 사용하면 된다. 또한 이벤트 흐름에는 이벤트 bubbling과 Capturing라는 2가지의 기본 모델이 존재한다.[ Event Bubbling과 Event Capturing ]이벤트 bubbling은 가장 깊게 중첩된 요소에 이벤트가 발생했을 때, 이벤트가 위로 전달 되는 것을 의미한다. 이벤트 bubbling은 target 이벤트에서 시작해서 요소를 거쳐 document 객체를 만날 때까지 각 노드에서 모두 발생한다. 만약 bubbling 중단을 원한다면 event.stopPropagation()을 호출하면 된다.event.stopPropagation()DOM Tree를 통한 이벤트 흐름 중지 가능브라우저 기본 동작은 취소 X 이벤트 Capturing은 bubbling과 다르게 제일 상단에 있는 요소에서 아래로 이벤트가 내려오는 것을 말한다.[ Event Delegation ]이벤트 bubbling과 이벤트 Capturing을 통해서 이벤트 위임을 이해할 수 있다. 이 이벤트 위임은 '하위 요소의 이벤트를 상위 요소에 위임하는 것'이다. Section 04. 자바스크립트 중급[ this]Method의 this: 해당 객체를 가리킨다.함수에서 this: window 객체를 가리킨다.constructor의 this: 빈 객체를 가리킨다. [ bind, call, apply]call():함수를 호출하는 함수.첫 번째 인자 값으로 어떠한 것을 전달해 주면 호출되는 함수의 this가 인자 값으로 지정apply(): call()과 유사하나 인수 부분에 배열을 넣어줘야함.bind(): 해당 함수가 지정한 인자 값을 가리키도록 하지만 call(), apply()와 다르게 직접 함수 실행 X [ 삼항 연산자 ]다음과 같은 구문을 갖는다.조건 ? true이면 반환 : false이면 반환 [ Event Loop]자바스크립트는 동기 언어이다. 하지만 가끔 비동기로 작동하는 setTimeout()를 사용하는 예시를 볼 수 있다. 자바스크립트는 비동기 코드를 작성하기 위해서 자바스크립트 이외의 도움을 받는다.[ Closure ]다른 함수 내부에 정의된 함수가 있는 경우, 외부 함수가 실행을 완료하고 해당 변수가 해당 함수의 외부에서 더 이상 엑세스할 수 없는 경우에도, 해당 내부 함수는 외부 함수의 변수 및 액세스가 가능하다. 이 기능을 Closure라고 부른다.[ 구조 분해 할당 ]배열이나 객체의 속성을 해제하여 그 값을 개별 변수에 담을 수 있게 해주는 표현 식이다.[ Map, Filter, Reduce ]Map, Filter, Reduce은 배열 메서드의 대표적인 예시이다.map(): 배열 내의 모든 요소 각각에 대하여 주어진 함수를 호출하고 나온 결과를 모아 새로운 배열로 만들어 반환한다.filter(): 주어진 함수의 필터를 통과하는 모든 요소를 모아 새로운 배열로 반환한다.reduce(): 배열의 각 요소에 주어진 리듀서(reducer) 함수를 실행하고, 하나의 결괏값을 반환한다.[ 얕은 비교 VS 깊은 비교 ]숫자, 문자열 등 원시 자료형은 값을 비교하게 된다. 하지만 배열, 객체 등의 참조 자료형은 참조되는 위치를 비교하게 된다. 얕은 비교를 하게 되면 원시 값의 경우 문제가 없지만 참조 값의 경우 실제 값이 아닌 저장된 위치(참조 값)이 비교되기 때문에 문제가 된다.깊은 비교를 사용하게 되면 참조 자료형도 실제 값으로 비교할 수 있게 된댜ㅏ.객체 depth가 깊지 않은 경우: JSON.stringify() 사용객체 depth가 깊은 경우: lodash 라이브러리의 isEqual() 사용[ 얕은 복사 VS 깊은 복사 ]위에서 정리한 내용처럼 복사에도 문제가 발생하게 된다. 따라서 참조 자료형의 값의 경우 깊은 복사를 사용하면 된다.JSON.stringify()lodash 라이브러리의 deepCopy[ 함수 표현식, 함수 선언문 ]함수 선언문: 함수 선언은 함수를 만들고 이름을 지정하는 것이다.일반적인 함수 선언 방식으로 function 키워드와 식별자를 표기하여 사용한다.함수 표현식은 함수를 만들고; 변수에 할당하는 것이다.익명 함수(function 키워드는 사용했으나 식별자 X), 화살표 함수 사용 Section 05. OOP[ OOP ]OOP(Object-Oriented Programming, 객체 지향 프로그래밍)란 Java 및 C를 비롯한 많은 프로그래밍 언어의 기본이 되는 프로그래밍 패러다임이다. 완전 간단하게 말하자면 객체 지향 프로그래밍은 객체들의 모임이라고 할 수 있다.OOP 특징으로는 다음과 같다.추상화:불필요한 정보는 숨기고 중요한 정보 만을 표현함으로써 프로그램을 간단히 만드는 것.상속:새로운 클래스가 기존의 클래스의 자료와 연산을 이용할 수 있도록 해주는 것.기존 클래스: 부모 클래스, 상위 클래스새로운 클래스: 자식 클래스, 하위 클래스다형성: 하나의 틀을 가지고 여러 개의 다양한 형태를 만드는 것이다.overriding을 통하여 다형성 구현 일반적인 코드를 재사용하고 작성할 수 있다.캡슐화:클래스 안에 있는 Method, 변수 등을 하나로 묶어준다. [ class와 constructor ]class에서는 constructor라는 특별한 메서드를 제공한다. 이 constructor는 생성자로, 인스턴스화된 객체에서 다른 메서드를 호출하기 전에 수행해야 하는 사용자 지정 초기화를 할 수 있게 해준다.클래스를 new 키워드를 붙여 인스턴스 객체로 생성하면 넘겨 받은 인자 값과 함께 constructor가 가장 먼저 실행이 된다. 따라서 이 곳에 초기화를 해야 하는 작업을 수행한다.[ Super]자바스크립트에서 super는 다음과 같은 역할을 수행한다.자식 클래스 내에서 부모 클래스의 생성자를 호출할 때 사용한다.자식 클래스 내에서 부모 클래스의 메소드를 호출할 때 사용한다. Section 06. 비동기[ 동기와 비동기 ]동기(Synchronous)코드를 순차적으로 실행하는 것. 즉, 한 작업이 끝나기를 기다렸다가 끝나면 다음 작업을 수행한다.각 작업이 완료될 때까지 다음 작업이 실행되지 않는다.비동기(Asynchronous)작업이 종료되지 않아도 다음 작업을 진행할 수 있는 방식비동기적인 코드는 특정 작업을 기다리지 않고 다음 작업을 계속 수행한다. [ Callbacks, ES6 Promise, ES7 Async / Await ]callbacks콜백 함수는 특정 함수에 매개변수로 전달된 함수를 의미한다.콜백 함수는 함수를 전달 받은 함수 내부에서 호출된다.단, 콜백 지옥을 맛볼 수 있다.Promise자바스크립트 비동기 처리에 사용되는 객체이다.new 키워드와 생성자를 사용해서 만들며, 생성자의 매개변수로 실행 함수를 전달한다.new Promise(실행함수) 실행 함수의 1번째 매개변수 resolve는 비동기 작업 성공 값이다.실행 함수의 2번째 매개변수 reject는 작업 실패 값이다.Promise는 다음 중 하나의 대기 상태를 갖는다.대기, 이행, 거부단, 체인 지옥이 시작된다...Async / Await비동기 코드를 마치 동기 코드처럼 작성할 수 있도록 해준다.Promise에서 than 체인 형식으로 호출하는 것보다 가독성이 좋다.await는 async 함수에서만 사용 가능하다.동기식 코드에서 사용하는 try...catch 문을 사용할 수 있다. Section 07. Symbol, Iterator, Generator[ Symbol ]ES6에 새롭게 추가된 원시 타입으로, 유니크한 식별자를 만들기 위해서 사용.단, for...in과 getOwnPropertyNames에서 제외 된다.Symbol 사용 시 기본적으로 Property가 숨겨진다. (찾을 수 있는 방법 有)따라서 for...in과 getOwnPropertyNames에서 symbol로 만든 Property가 안보인다.[ Iterator, Generator ]Iterator대표적인 예시로 배열이 있다.반복 가능한 것을 Iterable하다고 한다. for…of를 이용할 수 있다.[Symbol.iterator()] 값을 가지고 있다.Generator사용자의 요구에 따라 일시적으로 정지할 수 있고, 다시 시작할 수 있는 특별한 기능을 가지고 있다.function다음에 Asterisk (애스터리스크)를 붙인 형태로 사용한다.function*yield 키워드를 이용한다: 제너레이터 함수의 실행을 일시적으로 정지시킴. Section 08. Design Pattern[ 디자인 패턴 ]디자인 패턴은 개발자가 응용 프로그래밍나 시스템을 디자인할 때 일반적인 문제를 히결하는 데 사용할 수 있는 공식화된 모범 사례이다.- 위키 피디아다음과 같은 장점이 있다.최고의 솔루션재사용성풍부한 표현력향상된 의사 소통필요없는 코드 리팩토링코드베이스 크기 감소[ 디자인 패턴 종류 ]Singleton Pattern: 클래스의 인스턴스화를 객체 1개로 제한하는 디자인 패턴Factory Pattern: 비슷한 객체를 반복적으로 쉽게 생성하게 해주는 디자인 패턴Mediator Pattern(중재자 패턴): 객체 그룹에 대한 중앙 권한을 제공해주는 디자인 패턴Observer Pattern: event-driven 시스템을 이용하는 디자인 패턴Module Pattern: 코드를 더 작고 재사용 가능한 조각으로 분할하게 해주는 디자인 패턴 미션완벽히 해결한 미션은 다음과 같습니다.음식 메뉴 앱음식 메뉴 앱 미션은 주어진 카테고리에 해당되는 메뉴를 출력하는 웹을 구현하는 것이었습니다. 저는 카페 메뉴를 주제로 해당 웹을 구현했습니다. 다만 출력할 아이템에 대한 DB가 없어서 직접 data.json을 작성하여 처리했습니다. 미션을 해결하면서 기능 구현에는 특별한 문제가 없었으나 기능 구현보다 데이터 파일 생성이 더 오래 걸린 미션이었습니다... (출력되는 메뉴 이미지는 스타벅스 이미지를 활용했습니다.) 가위 바위 보 앱플레이어와 컴퓨터가 가위 바위 보를 하는 게임을 구현하는 미션입니다. 총 10번의 기회가 주어지며 게임에 대한 스코어 제공 및 승패 결과를 제공해야 했습니다. UI를 어떻게 구현할까 고민하다가 이미지를 추가적으로 더 넣어 구성했습니다. 컴퓨터의 가위 바위 보 선택지는 Math.random()을 이용해 처리했으며, 기능 구현에는 특별한 문제는 없었습니다.회고자바스크립트 강의를 들으며 기초를 다지고 그 지식을 바탕으로 주어진 미션을 해결하는 한 주를 보냈습니다. 특히 웹 개발이 처음이라서 미션을 해결해 나가는 시간이 정말 흥미로웠습니다. 앞으로 워밍업 클럽 Study를 진행하며 제가 얼만큼 발전할 수 있는지 궁금해지기도 합니다. 남은 기간 최선을 다해서 임해보겠습니다!

프론트엔드워밍업클럽

윤대

[인프런 워밍업 0기 Day2] 한 걸음 더! 메서드로 코드 재사용해보기!

!! 해당 글은 독자가 인프런 워밍업 0기를 수강하고 있다는 전제 하에 작성되었습니다 !!과제 수행에 있어 스프링부트 3.2.2 버전을 사용하고 있다는 점을 미리 알려드립니다! 안녕하세요🙌! 인프런 워밍업 2일차 과제입니다!2일차에는 API를 작성하는 방법에 대해서 배우고 그에 대한 과제를 받았습니다😎과제를 자세히 살펴보는 도중, 문제 1번과 3번 모두 덧셈을 수행하는 공통로직이 있다는 사실을 발견했습니다!따라서! 오늘은 제가 한 걸음 더 성장하기 위해 메서드를 통해 공통로직을 처리한 과정을 공유할 예정입니다~ ⚙️메서드 설계하기메서드를 만들 때, 제가 중요하다고 생각하는 것은 3가지입니다!메서드가 무엇을 할 것인가 (메서드 명)메서드가 무엇을 반환할 것인가 (리턴 타입)메서드가 무엇을 필요로 하는가 (파라미터)여기서, 중요한 점은 어떻게는 생각하지 않는다는 것입니다! 🙅‍♂️위의 3가지만 만족한다면 공통로직으로 볼 수 있기 때문에 메소드의 내부 로직은 추후에 생각해도 무방합니다! 자, 그렇다면 지금부터 문제 1번과 3번에서 각 절차를 수행해보겠습니다.첫째, 무엇을 할 것인가?문제 1번과 3번 모두 2개 이상의 숫자를 더해야 하는 상황입니다! 따라서, 저는 메서드 명을 addNumbers로 정했습니다.둘째, 무엇을 반환할 것인가?우리는 두 수를 더 한 값을 반환 받아야 합니다! int와 Inteager 등 다양한 숫자가 가능하겠지만, 저는 Inteager를 택했습니다!셋째, 무엇을 필요로 하는가?우리는 숫자를 더하기 위해, 2개 이상의 숫자를 필요로 합니다! 또한, 문제 3번의 경우 몇 개의 숫자가 입력될 지 알 수가 없습니다! 따라서 저는 List<Integer> numbers로 파라미터 값을 설정했습니다.이제 위의 세 부분을 합치면 제가 만들 메서드는 아래와 같은 형식이 될 것입니다!public Integer addNumbers(List<Integer> numbers);💡 int 타입의 경우 List로 받을 수가 없어 Integer를 반환 값으로 설정하였습니다! ⚙메서드 구현하기이제 설계가 끝났으니, 메서드를 구현할 시간입니다! for each문으로 List에 담긴 값을 하나씩 꺼내 더하여 값을 반환만 해주면 구현은 어렵지 않게 끝이 납니다!😎 public Integer addNumbers(List<Integer> numbers) { Integer result = 0; for (Integer number : numbers) { result += number; } return result; }자~ 이제 구현이 끝났으니 메서드를 적용해봐야겠죠? ⚙메서드 적용하기문제 3번먼저, 문제 3번입니다! 3번부터 풀이하는 이유는 1번 문제를 풀며 발생하는 문제 때문입니다!DTO (데이터를 전송 받고 보내는 객체)@Getter @Setter public class NumbersRequest { private List<Integer> numbers; }Controller @PostMapping("/api/v1/calc") public Integer addNumbers(@RequestBody NumbersRequest numbersRequest) { return addNumbers(numbersRequest.getNumbers()); }List<Integer>를 필드 값으로 갖는 NumberRequest를 입력받아 addNumbers()에 필드값을 전달했습니다!입력받은 숫자가 몇 개던지 메서드 내부에서 값이 잘 합산되어 반환될 것입니다! 문제 1번이번엔, 문제 1번을 해결해보죠! 😎DTO@Getter @Setter public class CalcResponse { private int add; private int minus; private int multiply; }Controller @GetMapping("/api/v1/calc") public CalcResponse calc(Integer num1, Integer num2) { List<Integer> numbers = new ArrayList<>(); numbers.add(num1); numbers.add(num2); CalcResponse response = new CalcResponse(); response.setAdd(addNumbers(numbers)); // minus와 multiply도 메서드로 구현해주었습니다! response.setMinus(minusNumbers(numbers)); response.setMultiply(multiplyNumbers(numbers)); return response; }값을 Integer num1과 Integer num2를 입력받기 때문에 입력 값들을 List로 변환해줘야 합니다.이렇게 하여도 문제는 없겠지만, 코드가 지저분한 게 영 마음에 들지 않습니다!그래서, 다음과 같이 코드를 변경해보았습니다!DTO (Request) 추가@Getter @Setter public class CalcRequest { private Integer num1; private Integer num2; public List<Integer> getNumbers() { List<Integer> numbers = new ArrayList<>(); numbers.add(this.num1); numbers.add(this.num2); return numbers; } }입력 값을 각각의 값이 아닌 하나의 객체로 변환하여 받고, 내부에 getNumbers()를 구현하여 입력받은 값을 바로 List<Integer>로 변환하여 받도록 하였습니다!이 DTO를 적용하면 Controller의 코드가 다음과 같이 바뀌게 됩니다! @GetMapping("/api/v1/calc") public CalcResponse calc(@ModelAttribute CalcRequest calcRequest) { CalcResponse response = new CalcResponse(); response.setAdd(addNumbers(calcRequest.getNumbers())); response.setMinus(minusNumbers(calcRequest.getNumbers())); response.setMultiply(multiplyNumbers(calcRequest.getNumbers())); return response; }훨씬 간결해졌죠? 참고로 @ModelAttribute는 쿼리 스트링으로 입력받은 값들을 확인하여 파라미터 타입으로 지정한 타입의 필드 값과 일치하면 자동으로 객체로 변환해주는 Annotation입니다!이렇게, 메서드를 사용하면 공통로직을 단일 메서드 내부에서 관리할 수 있게 되고, 코드의 반복을 줄일 수 있게 됩니다! 여러분도 코드의 중복이 보인다면 메서드로 한 번 만들어보는 것은 어떨까요? 지금 까지의 내용을 정리하면서 2일차 포스팅을 마치도록 하겠습니다! 💡정리 💡메서드를 설계할 때 중요한 것!메서드를 설계할 때는 어떻게는 생각하지 말자!무엇을 하고, 반환하고, 필요한 지 3가지만 충족된다면 공통로직으로 만들 수 있다!객체 내부에서 변환로직 만들기!여러 개의 Integer를 Controller에서 List로 직접 변환할 시 코드가 지저분해진다! @ModelAttribute를 활용하여 객체 내부에서 값을 변환하여 반환하자!

백엔드Spring인프런워밍업메서드API인프런SpringBoot