23년 1월 원티드 프리온보딩 프론트엔드 1일차 TIL (Wanted Pre Onboarding FrontEnd)
정신없이 지나간...
첫날은 1시간 차이로 백엔드 프론트엔드 둘다 겹쳐 있었다.
어우...
강의 2개를 동시에 틀어두니 정신없었다.
그나마 다행인 것은 프론트엔드가 아이스브레이킹이 좀 길었고, 취업과 관련된 썰로 시간을 좀 벌었다.
강사님도 대단하신 분이고, 강의가 너무 열정적이어서 11시에 끝났어야 하는데 오버 타임이 되었다. (11시 40분 넘었었나..) 난 끝까지 들었다 ㅎㅎ
첫 날이라 큰 내용은 없었고, 그냥 느낀점만 많았다.
강의 진행은 아래와 같았다.
각 챕터별로 느낀점 그리고 배운 점 등을 정리해보겠다.
노션은 공개된 자료인 줄 알았으나... 확실치 않아서 이 부분은 다시 감춤 처리로 바꿨다.
그냥 들으면서 학습한 내용 및 개인 생각을 정리한 노트고, 기술적인 부분은 향후 다룰 예정이다.
1-1 챌린저 메이커 / 코스 커리큘럼 소개
여기는 그냥 오버뷰 시간
입장 인원이 초기 590명까지 들어와서 놀랐다.
두 가지 의미로 놀랐다.
첫 번째로 이렇게 프론트엔드 영역에 대한 인기가 높은 줄은 몰랐다는 점이 컸고...
두 번째는 Zoom이 500명 넘는 인원도 버티는 구나...라는 부분?
영상 송출쪽은 아직 한번도 안해봐서 신기했다.
이번 파트는 어떤 것을 다루고 어떤 방식으로 진행하는지를 다루게 되었다.
1-2 취업 프로세스에서 기술 과제가 갖는 의미 이해하기
주로 면접 질문 및 과제에 대한 자세에 대해 다뤘다.
과제에서 너무 화려한 코드는 오히려 감점.
좀 와닿은 부분은 면접관의 질문을 모두 답한 사람은 오히려 불안해 할 수 있다 라는 대목이었다.
이건 생각도 못한 부분인데 이렇게 다 답변하면 내가 오히려 검증을 충분히 못한 것인가 라는 불안함 이 생긴다는 부분을 다시 생각해보게 되었다.
여긴 정리하면 각 회사의 포지션과 요구하는 인재상이 되도록 노력 또는 준비하자 로 될 것 같다.
1-3 ToDo 앱을 만들며 고려할 것들
여기서부터는 슬슬 기술적인 부분이 조금씩 나오기 시작했다.
참고로 온보딩 전에 사전과제가 나갔고,
이에 대해 나는 한 2일? 3일? 정도 투자해서 냉큼 결과물을 제출할 수 있었다.
물론 시간이 더 있었으면 좋겠지만... 이걸 내가 본게 마감 몇일 전이었다는게 함정...
이 ToDo 프로젝트는 난이도가 상이하다.
간단히 구현하면 엄청 쉬운데, 조건을 몇개 붙이기 시작하면 점점 상승하기 시작한다. (물론 주니어급 이상이거나 경험이 많으면 쉬울수도...)
웹 서비스를 극단적으로 보면 CRUD(Create, Read, Update, Delete)가 전부이지만, 여기에 조건을 붙인 것을,
최선의 방법을 잘 구현하는 것이 목표다 라고 할 수 있겠다.
상태 관리
상태 관리를 설명하는 부분에서는 내가 모르는 부분이 나와서 좀 자세하게 들었다.
리랜더링 이슈의 경우 MyMeLink를 개발하며 어느정도 경험을 해서 와닿았다.
그리고... **제어 컴포넌트(state)**와 **비제어 컴포넌트(ref)**에 대해 언급이 나왔는데
부끄럽게도 아직 리엑트쪽의 이론적인 부분에 대해서는 학습량이 부족하다.
그래서 이 부분은 따로 학습해서 포스팅하여 정리할 예정이다.
비동기, 캐싱
여기는 Promise 관련인데 사실 아주 예전에 조금 찾다가 그냥 async await만 주리장창 쓰는 현재로써...
좀 반성하게 되었다.
캐시는 Next.js에서 몇번 보긴 했는데 일단 이 부분도 학습이 필요하다고 생각이 들었다...
인증과 인가
여기는 충분히 알고 있다.
근데 예시가...(ㅋㅋㅋㅋ 진짜 김문수 도지사 사건은 생각만 하면 죽창을...)
최근 MyMeLink와 흑우집합소를 진행하고 있는 시점에서 JWT와 계정에 따른 권한 등으로 어느정도 학습을 한 상태라서 이 부분은 넘어갔다.
그리고 AOP(Aspect Oriented Programming) 개념도 살짝 나왔다.
React-Query에 대해서도 언급이 있었는데 이 부분은 깊게 다루진 않았다.
사용자 액션에 따른 적절한 피드백 (UI/UX)
여긴 요새 서비스를 직접 만드는 입장으로 가장 중요한 부분인듯 하다.
아무래도 UX와 많은 연관성을 가지는 부분인데 큰 비중을 두진 않았다.
관심사의 분리
AOP(Aspect Oriented Programming) 영역이 살짝 보이기 시작한다.
구석기 프론트엔드 (퍼블리셔쪽과 같이 뭉텅이 쳐서 할 시절)에서는 진짜 그냥 화면 내 그림만 그리고, jQuery떡칠로 서비스를 구현하던 시절...
당시에는 이런 개념이 없었지만...
이제는 프론트엔드에서도 사용자 화면단과, 각 컴포넌트에 대한 상태관리, 그리고 서버 측 데이터 받아서 처리 등...
이제 거의 백엔드와 유사(물론 결이 정말 다르다. 그냥 표현만 그렇다라는 점)한 것 같다.
내 프로젝트도 현재 똥이 되어 가는데 이걸 다시 다 뜯을 생각을 하니...
예시에서 나온 HeadlessUI는 좀 신박한 것 같다.
View 영역과 비즈니스 로직의 분리는 백엔드 영역에서는 어느정도 했지만,
프론트 쪽은 아직 경험이 낮아서 이 부분은 공부를 좀 많이 해봐야 할 것 같다.
특히 아래 코드를 보면서 많은 학습이 필요하다는 생각이 들었다.
// 적용 전 - 무조건 localLogin을 변경해야 함
class UserService {
async localLogin(email: string, password: string) {
const user = await mysql.query(`SELECT * FROM user WHERE email = ?`, [
email,
])
if (jwt.compare(password, user.password)) {
throw new Error("login fail")
}
return jwt.create(user.uuid)
}
}
여기 코드를 보면 문제가 있다는 수준은 된다.
그런데 이것을 개선한 쪽에서...
// 적용 후 - DB, token의 세부 구현을 어떤 것을 쓰더라도 자유로움 -> 추상에 의존
// 추상
class UserService {
constructor(
private userRepository: UserRepository,
private tokenService: TokenService
) {}
async localLogin(email: string, password: string) {
const user = await userRepository.getUserByEmail(email)
if (!tokenService.compare(password, user.password)) {
throw new Error("login fail")
}
return tokenService.create(user.uuid)
}
}
// 추상
interface UserRepository {
getUserByEmail(email: string): Promise<User>
}
// 추상으로부터 구체를 구현
class MysqlUserAdaptor implements UserRepository {
getUserByEmail(email: string) {
return mysql.query(`SELECT * FROM user WHERE email = ?`, [email])
}
}
// 추상
interface TokenService {
compare(value: string, encrypted: string): Boolean
create(value: string): Token
}
// 추상으로부터 구체를 구현
class JWTokenAdaptor implements TokenService {
compare(value, encrypted) {
return jwt.compare(value, encrypted)
}
create(value) {
return jwt.create(value)
}
}
요기 코드에서 인터페이스를 다루는 부분이 나에게 필요한 것 같다.
백엔드는 보통 저런 비슷하게 했는데 프론트는 일단 그냥 무지성 호출?
또는 타입 대신 사용하는 용도로만... 상당히 저수준 형태로만 사용한 것 같아 반성의 시간이 들었다.
1-4 사전 과제 피드백 : TODO 앱 개선
여기에서 다뤘던 참조 깃허브는 좀 충격적이었다.
내가 얼마나 저수준으로 코드를 작성했는지 반성하는 자아성찰의 시간을 가졌다.
진짜 이제 좀 뭐 할수 있겠구나 싶었는데...
내가 짠 코드를 보고 어휴...
어지럽더라...
Feedback 1) 맥락을 이해하기 힘든 변수명
그리고 변수명...
나 또한 일전에 다른 교육에서 변수명 함수명 때문에 지적을 받았는데...
우수갯 말로...(말은 아니지만)
이런 짤도 있다.
오죽하면 이런 서비스도 있다.
그래서 이런 부분을 다뤘다.
다른 몇 분의 코드와 함께...
PS : 이건 여담인데 혹시 나와 같은 코드 스타일을 쓰시는 분이 있는지...
이건 나중에 디스코드에도 물어볼 예정이지만...
function getData4User() {....}
function getPage4Data2User() {....}
이렇게 난 숫자를 통해 for->4 to->2 를 사용하는데 이것에 대한 다른 분들의 의견도 들어보고 싶다.
Feedback 2) 명령형 프로그래밍
명령형(How)는 이름만 들어도 일일히 명령을 내려야 할 것 같은 뉘앙스가 든다.
그러나 선언형(What)은 목적과 목표만 정하기에 훨씬 간결하다.
React와 Vanilla Javascript 예시와 GraphQL, YAML등이 선언형임을 알려줬다.
여기서 설명하다가 Suspense Component개념이 나왔는데 난 이 부분에 대해 처음 들어봤다. (그만큼 이론 지식이나 경험이 부족...)
몇 가지 예시는 생각해보며 내 케이스와 비교해봤다.
Feedback 3) 적절히 추상화 되지 않은 함수와 컴포넌트
여기는 코드의 관리 부분이었다.
공통된 로직을 뽑아서 관리 포인트를 줄이자 라는 것이 목표이다.
즉 아래와 같이...
// 적용 전 - 1) 수정하는 사용자, 2) 등록하는 사용자가 하나의 함수를 사용한다
const getInitialData = (type: 'edit' | 'register') => {
if (type ==== 'edit') {
// 수정 시에 필요한 초기 데이터를 불러오는 로직
} else {
// 등록 시에 필요한 초기 데이터를 불러오는 로직
}
};
이런 코드가 함수 내에 있다면 이것을 뜯어서...
// 적용 후 - 1) 수정하는 사용자, 2) 등록하는 사용자가 서로 다른 함수를 사용한다
const getInitialDataForEdit = () => {
// 수정 시에 필요한 초기 데이터를 불러오는 로직
}
const getInitialDataForRegister = () => {
// 등록 시에 필요한 초기 데이터를 불러오는 로직
}
이렇게 각 함수로 나눠서 처리하는게 좋다.
그리고 우발적 중복은 피하되, 의도한 중복은 핸들링이 어느정도 되지만 가급적 줄이는 것이 좋은 것 같다.
예시 코드가 몇 있었는데 다행히 나는 그렇게 짜진 않았다.
하지만 유사한 부분도 있었기에 좀 바꿔야 할 듯 싶다.
1-5 과제 설명
사전 과제를 기반으로 오늘 설명한 것을 중점적으로 적용을 해보라 하셨다.
근데...
아직 못했다...
이 부분은 어제까지였는데, 한번 주말에 다시 해볼 예정이다.
나의 경우 typescript를 쓰는거라서 아래의 조건을 클리어하는게 목표다.
- 타입스크립트를 써본 경우
- tsconfig에 strict 옵션 적용
- 타입 가드 및 타입 추론을 사용해 any, 타입 단언을 모두 없애기
- 반복되는 타입은 제네릭, 타입 상속 / 합성 등으로 추상화
- 보다 좁은 타입으로 정의 (ex. string → as const or union)
1번과 2번은 원래 적용했고,
3번과 4번은 일부 적용했다.
근데 이것보다 다른 사람들이 짠 코드를 보니 내가 좀 엉망으로 짰구나 라고 생각이 들어 전반적으로 바꿔볼 생각이다.
그리고 같이 듣는 백엔드 Nest.JS를 이용해서 한번 To-Do 앱을 짜볼 예정이다.
함수형 프로그래밍을 적용해보고 둘 간의 사용자 인증 및 화면단 구성 등등...
한번 개인 포트폴리오 겸 만들어봐야겠다.
정리
참 유익했던 것 같다.
강의는 사실 길지 않지만...
거기서 나오는 내용은 너무나도 방대했다. (나에게는?)
나오는 내용은 나에게 있어서 매우 유익했다.
잘 배워서 내 것으로 다 흡수해야겠다.
오늘도 강의가 있는데 잘 들어보고 더 나은 실력을 갖춰서,
내가 만드는 서비스에도 적용해보고,
다른 곳에 들어갈 수 있는 실력도 갖춰봐야겠다.