기억의 실마리
2025. 9. 30. 02:10

🤔지원하게 된 계기

최근 반복되는 일상속에서 더 성장하기 위해서는 새로운 자극이 필요하다는 생각이 들었고, 마침 멋쟁이 백엔드 개발자 친구의 소개로 구름톤이 이번에 참가 인원을 모집하고 있다는 것을 알게 되어 신청하게 되었다.

 

"서로 다른 환경에서 성장하던 동료들과 소통하며, 극단적으로 짧은 기간에 MVP를 완성시킨다." 라는 점에서 분명히 새로운 경험을 기반으로 서로의 애티튜드를 배우며 성장할 수 있는 기회를 얻을 수 있을 것이라고 생각했고 생에 처음으로 구름톤에 신청하게 되었다.

참가 신청은 Google Form으로 몇가지 문항에 대한 답변을 작성하여 제출하는 방식이었고,

주요 문항은 아래와 같다.

 

  1. 사용 가능한 프레임워크/라이브러리(React, Vue 등)를 나열하고, 그중 가장 자신 있는 기술을 하나 골라 이유를 설명해주세요.(공란 포함 최대 300자)
  2. 최근 6개월 내에 가장 많은 시간을 등려 해결했던 기술적 문제를 작성해주세요.(공란 포함 최대 300자)
  3. 현재 관심 있는 프론트엔드 기술이나 개념을 작성해주세요.(공란 포함 최대 300자)
  4. 선호하거나 관심 있는 디자인 시스템을 작성해주세요.(공란 포함 최대 300자)
  5. 구름톤 참여 동기를 작성해주세요.(공란 포함 최대 300자)
  6. 구름톤을 통해 어떤 부분의 '성장'을 기대하고 있는지, 있다면 작성해주세요.
  7. 협업 시 지키는 본인만의 규칙이나 전략은 무엇인가요? 갈등 상황이 발생했을 때의 해결 방법도 함께 알려주세요.
    (공란 포함 최대 500자)
  8. 진행하신 프로젝트 중 하나를 선택하여 설명해 주시고, 그 경험으로 인해 얻을 수 있었던 결과를 작성해주세요.
    (공란 포함 최대 500자)

사실 문항 내용을 보고 생각보다 디테일한 설명을 요구하고 글자 제한도 있어 답변하기 꽤나 어려웠다... 약 1시간 30분정도 작성했던 것 같다.

 

그렇게 제출하고 1주일이 지난 후 합격 통보를 받게 되어 급하게 대표님과 면담하여 5일 연차를 승인 받아 구름톤에 참가 확정서를 제출하였다.

 

당시에는 몰랐지만 지원자 수가 약 400명 이라는 말을 들었고 문항답변을 좋게 봐주신 것 같아 너무 감사했다...🥹

 

내가 글을 썼을 때의 포인트는 핵심 내용 위주의 서술과 가능한 수치화하여 표현하고, 새로운 경험을 통해 배우고 싶다는 진심을 많이 어필했다. 그리고 4번 질문에 디자인시스템에 대한 내용이 있었는데, 현재 회사에는 디자인 시스템을 활용하지 않고 있어 직접 구성중이며 이번에 참가하게 되면 많이 배우고 싶다고 서술한 내용이 있다. 아는척 하는 것 보다는 솔직한 마음으로 "배우고 싶다" 를 어필하는게 더 좋을 것 같다고 생각하여 글에 녹여냈는데 진심이 잘 통한 것 같아서 뿌듯했다.

 

📅구름톤 15기 일정표

이전 14기 일정도 찾아보았는데 크게 달라진건 없어서 참고할 때 큰 도움이 되었다.

 

🤼구름톤 여정

Day - 1

처음에 간단히 구름톤에 대한 소개와 멘토진 소개 후에 아이스 브레이킹 타임으로 임시 팀을 구성하고 함께 퀴즈를 맞추는 시간이 있었는데 생각보다 너무 잘 준비해주셔서 웃으며 모두와 친숙해질 수 있는 시간이었던 것 같다 ㅎㅎ

 

그리고 시작과 동시에 귀여운 컵과 티셔츠를 받아 기분이 좋았다!

이어서 self-pr 시간이 있었고 준비한대로 나를 어필하고자 했지만... 생각보다 잘 안됐던 것 같아 조금 아쉬움이 남았다.

 

이번 해커톤의 주제가 발표되었는데 바로 "제주도민의 삶을 바꾸는 생활 인프라 개선" 이라는 주제였다.

주로 구름톤 in Jeju에서는 이와 비슷한 주제로 제주도의 인프라, 삶의 개선 등에 대한 주제를 많이 다뤄온 것으로 보였다.

 

하지만 우리는 제주도민이 아는데 어떻게 제주도민의 삶을 바꾸는 것을 생각해볼 수 있을까? 라는 의문을 가지고 있을 때 구름톤에서는 여러가지 방향성과 레퍼런스를 제시해주며 해커톤을 진행함에 있어 필요한 내용들을 강의해주는 특강도 많은 도움이 되어 큰 무리 없이 아이디어를 떠올릴 수 있었다.

 

그리고 기획자 Matt님의 특강이 있었는데 다양한 AI 툴을 활용하여 퍼포먼스를 높이는 방식등에 대해 알게 되어 너무 좋았고, 기획자의 역량이 팀의 역량을 크게 좌우할 수도 있구나 라는 생각을 다시금 하게 될 만큼 애티튜드가 좋으셨다. 개발자에게도 기획 역량은 반드시 필요하다고 생각해온 만큼 매트님께 배운 것이 많아 기획자 특강에서 높은 만족감을 느낀 것 같다.

 

Day - 2

2일차에서는 1일차 일정에서 공개된 주제를 기반으로 One Page PPT를 만들어 각자의 기획 아이디어를 발표하고 어찌보면 2번째 self-pr이기도 한 발표시간이 있었다.

 

나는 어떠한 문제가 지속적으로 언급되면서 해결되지 않는 문제의 이유를

3가지로 정의하고 있었다.

 

1. 취합이 어려움

2. 사용하기 어려움( 민원 신고/접수 등 )

3. 시각적으로 이해하기 어려움

 

그래서 저는...

 

짜잔. 제가 만들어 발표한 ppt입니다... ㅎㅎ

 

그렇게 각자의 2차 self-pr을 진행하며 그 이후로 팀을 구성하는 시간에 챡챡챡 빠르게 팀들이 만들어져 갔다.

나 역시 팀을 구성하고 기획 아이디어에 대해 이야기 하며 프로젝트 방향성을 구성하고 있었다.

 

나는 나의 아이디어 자체는 매우 좋다고 생각했지만, 팀원들에게는 전달되지 못했고 채택되지 않았다...

 

최종 발표 / 심사위원 평가 시간에 나의 기획 아이디어를 심사위원으로 참여하신 스타트업 창업자 대표님께서 제안해주시는걸 보며 마음속에서는 "역시... 좋은 아이디어였어...!!!" 라는 메아리가 맴돌았고 나의 설득 능력이 부족하다는 것을 체감했다...😭

 

그렇게 모두 팀을 구성하고 플레이스 캠프로 이동하고 해커톤을 마저 진행하다. 구름톤에서 제공하는 숙소에 짐을 두고 왔다. 침대가 폭신하고 좋았다... 🥹물론 침대에 머물 수 있는 시간은 구름톤을 진행하는 동안 단 2시간 30분 뿐이었지만... 하하

 

그렇게 이어서 구름톤을 진행하다 비어파티 시간이 되어 저녁을구성원들과 함께 저녁을 먹으며 개발과 일상에 대해 소통하며 웃고 친해지는 시간이었다. 어느정도 시간이 흘러 멘토님과의 소통시간이 되었고 생각보다 알차고 재밌는 시간을 보내게 되어 좋았다.

 

그리고... 뷔페식 저녁 너무 맛있었다 ㅎㅎㅎ

 

그렇게 비어파티도 마무리되고 다시 해커톤에 집중하고... 그렇게 눈뜬채로 3일차가 되어버렸다🥹

 

Day - 3

팀원들과 프로젝트를 기획하고 개발하고 논의하며 점점 가까워지고 함께 웃으며 프로젝트를 진행할 수 있었다. 대화를 할 때 매번 편하게 논의할 수 있어서 "좋은 분들을 만나서 너무 다행이다"라는 생각이 들었고 팀원분들에게 너무 감사했다. ㅠㅠ

 

다들 수면시간이 4시간 미만임에도 불구하고 웃으며 나가서 커피 한 잔 하시죠! 하며 예쁘게 팀사진도 찍어서 좋았다.

 

그렇게 또 집중해서 어느덧 저녁이 되었고 오늘은 무조건 시간을 내서라도 제주도에 온 김에 바다를 봐야겠다는 다짐을 했다!

 

가는 길에 이름 모를 귀여운 백마도 만났다🐎

 

내가 찍어두고도 놀랐다... 이렇게 예쁘게 찍히다니! 안보러 왔으면 엄청 후회할 뻔했다 ㅎㅎ 그렇게 20분 정도 경치를 보며 이전에 정리하지 못했던 생각들도 정리하고 기분전환하고 다시 돌아와 MVP를 열심히 만들었다.

 

Day - 4

그렇게 2일차에 2시간, 3일차에 30분 총 2시간 30분 자면서 MVP를 완성하였고 팀원들과 짧은 기간에 최선을 다해 만들었다고 생각하니 매우 뿌듯했다! ㅎㅎ 그리고 우리 팀장님이 발표를 너무 잘해주셔서 너무 좋았다.

 

 

결과는 아쉽게도 수상은 하지 못했지만 좋은 사람들과 함께 웃으며 논의하고, 누구 하나 빠짐없이 집중하고 노력하는 모습이 더 소중하고 값진 경험이었던 것 같다.

 

정말 모두가 열정이 넘치고 의욕 가득하신분들 뿐이여서 나도 모르게 스며들어 더 열심히 하게되었던 것 같다.

 

발표가 끝나고 이야기를 종종 나누고 웃으며 대화했던 각 포지션 사람들과 연락처를 주고받으며 서로 사이드프로젝트 참여하거나 좋은 소식있으면 또 연락하자며 마무리하게 되었다.

 

해커톤에서 정말 많은 것을 배웠고 얻은 것 같다.

 

특히 "사람을 얻어간다." 라는 말이 가장 가깝게 다가왔다.

 

✍🏻마치며...

다양한 사람들과 소통하고 몰입하는 것 자체만으로도 애티튜드가 많이 달라지는 것을 체감했다. 그리고 스스로에게 말할 수 있게 되었다. "만약 내가 성장하지 못하고 있다면, 환경에 변화가 없는 것이다."

2025. 8. 10. 22:06

🤔찾아보게 된 계기

개발 커뮤니티를 돌아다니다 밈같은 것을 보다 우연히

DRY원칙을 준수하지 않는다 라는 이야기를 보고

갑자기 웬 드라이..? 하고 알아보게 되었다.

 

알고보니 3대 원칙 중 하나였고 뜻을 알고보니 밈을 다시

보고 피식하게 되었다.

 

😒KISS ( Keep It Simple, Stupid )

의미: 가능한 단순하게 유지하라. 복잡성을 피하고, 명확하고 이해하기 쉬운 코드를 작성하라.

 

목표:  코드의 가독성을 높이고 유지보수를 용이하게 하며, 버그 발생 가능성을 줄이는 것.

 

 

🥹YAGNI ( You Ain't Gonna Need It )

의미: 지금 당장 필요하지 않은 기능은 만들지 말라. 미래에 필요할 것 같다고 미리 구현하지 말고,

정말 필요할 때 구현하라.

 

목표: 개발 시간과 노력을 절약하고, 불필요한 기능으로 인한 복잡성을 줄이는 것.

 

 

😨DRY

의미: 코드 중복을 피하라.같은 기능을 하는 코드가 여러 곳에 반복되지 않도록 재사용 가능한

모듈이나 함수로 만들어 사용하라.

 

목표: 코드 유지보수를 용이하게 하고, 변경 사항 발생 시 모든 중복 코드를 일일이 수정해야

하는 번거로움을 줄이는 것.

 

 

✍🏻마치며...

소프트웨어 3대원칙을 알고보니 개발할 때 퀄리티( 가독성, 유지보수성 등 )를 높이고 개발자 특유의 "고민"을 많이 줄일 수 있도록 유도한 것 같았다. 단순히 밈 때문에 찾아보게 되었는데 생각보다 중요한 이야기였고 앞으로 개발할 때에도 이 3대원칙을 기반으로 코드를 작성해야겠다.

'Computer Science' 카테고리의 다른 글

[ Circular Dependencies ] 의존성 순환  (0) 2024.02.27
[ Computer Science ] REST API란?  (0) 2023.12.25
2025. 8. 9. 18:30

🤔공부하게 된 계기

재직중인 회사의 고객사 요청으로 운영중인 페스티벌 페이지를

새로운 버전으로 만들어 달라는 요청이 있었다.

 

소개페이지에서 동적 animation을 추가해야 하는 과업이 있었는데 이전 버전의

소개페이지에 접속하면 노트북의 펜이 미친 듯이 돌기 시작했고,

내가 직접 개발한 소개페이지는 더 많은 animation이 추가 되었음에도

불구하고 과부화 되어 펜이 돌거나 하진 않았다.

 

이러한 현상의 원인을 [ postioin, margin ] vs [ transform ] 라고 유추했다.

내가 생각한 것은 "Layout 단계에서 지속적으로 재계산 되기 때문?" 이었다.

 

🖼️브라우저 렌더링 순서

  1. Parsing: HTML → DOM Tree, CSS → CSSOM Tree
  2. Style: DOM Tree + CSSOM Tree → Render Tree 생성
  3. Layout(Reflow): Render Tree의 각 노드 위치·크기 계산
  4. Paint: 각 노드를 픽셀 정보로 변환 (Display List 생성)
  5. Composite: 레이어를 GPU로 합성하여 최종 화면 출력

 

🪄transform이 성능이 더 좋았던 이유

margin, padding, width, height, postion 등의 변경으로 animation을 구현하면

[ Parsing ~~ Composite ] 과정을 지속 반복하게 되는데 특히나 Layout단계에서

발생하는 위치의 재계산CPU의 부하를 높이기 때문에 부담스러운 작업이 된다.

 

반면 transform 속성을 활용하여 animation을 구현하게 되면

Composite단계에서 처리하게 되고, 가장 부담스러운 작업인 Layout(Reflow)

단계를 거치지 않기 때문에 압도적인 성능차이가 나게 되는 것이다.

 

결론

animation을 구현한다면 불가피한 상황이 아니라면 transform 속성을 활용하자!

 

✍🏻마치며...

"활용하는 기술에 대한 이해도를 가지자!" 라고 생각하며 개발에 임하고 있지만 막상 시간에 쫓겨 그러지 못하는 경우가 많은 것 같다. 그간 습득했던 기술지식을 기반으로 유추하고 해결하는 방식이 나쁜 것은 아니지만, 알 수 없는 무언가의 영역이 되어 지나치는 것 보다는 학습을 통해 이해도를 높이고 유추가 아닌 확신이 되어가는 것이 베스트인 것 같다.

'Frontend' 카테고리의 다른 글

[ Frontend ] 모달 컴포넌트 순서  (0) 2024.05.19
2025. 8. 3. 17:36

🤔 개발과 함께한지 3년... 벌써?

생각해보면 참 신기하다.

단지 웹사이트를 보고 HTML, CSS만으로 시작한 사이트 클론 퍼블리싱을 시작으로

프론트엔드 개발, 서버 개발, 사이트배포, 개발자로 취업까지 하게 되었다니...!

 

개발을 시작한건 늦다면 늦은 나이 29살 즈음이었지만,

어느 것을 했을 때보다 강한 성취감을 느꼈고, 개발과 함께한 3년이 지난 지금에도

개발에 임할 때의 태도는 변하지 않았으며 매번 나를 성장시켜주고 있다는 생각 또한

변하지 않고 여전히 나와 함께 머물고 있다.

 

개발은 여전히 나에게 가치 있는 삶이 무엇인지 알려준 지표이고

일생을 함께하고 싶은 친구다.

 

그렇기에 앞으로도 개발을 놓치지 않게 최선을 다 하며 살 생각이다.

오래오래 함께 하자!

 

 

🧑🏻‍💻 개발자로서 1년 6개월

지난 게시글 중 SI 회사에 취업에 성공했다는 이야기를한적이 있다.

그렇다... 나는 그 SI회사에서 1년 6개월이라는 시간을 보내고 있다.

 

잠시 개발자 신입( 경력무관 ) 취업 경쟁률을 이야기 해보자면,

그 당시에도 나는 200 : 1 경쟁률로 지금 회사에 입사하였고 얼마전에 회사에서

2명을 채용한다는 채용공고를 올렸는데 350명이 지원을 했다.

이제는 정말 취업이 더욱 쉽지않은 세상이 되어버린 것 같다...

(참고로 우리 회사는 법인 설립 5년이 채 되지 않은 SI 스타트업이다 ...)

 

🖥️Frontend

🌱2024.02.

입사를 하고 당시 회사는 모든 직원이 신입들로만 이루어져있다는 것을 알게 되었다.

아무도 이끌어 줄 사람이 없었고 특히나 팀원 간 커뮤니케이션을 통해 컨벤션을

설립해야 하는데 원할하지 못했던 것 같다.

 

프론트엔드 개발자들과 소통해보니 모두 필요성을 느끼고 있었지만 그 누구도

나서지 않고 있었고 그저 각자 업무가 너무 바쁘다는 이유로 소통비용 조차

쓸 여유가 없다는 것이었다.

 

하지만 나는 전혀 그렇게 생각하지 않는다.

함께 하나의 프로젝트를 완성시켜 나아가는 것이지, 개인 프로젝트가 아니기 때문에

협업은 반드시 커뮤니테이션이 통해 나아가야한다고 생각하기 때문이다.

 

때문에 소통의 중요성을 이야기하며 노력한 끝에 함께 소통하며

컨벤션을 맞추어 개발을 하기 시작했다.

 

이전에 모두 각자 개발하고 제 각각의 네이밍 케이스, 파일 구조를 가지고 있었다면

점진적으로 일관화된 컨벤션이 되어가고, 함께 소통하는 것이 즐겁고 뿌듯했다.

 

🐤 ~ 2025. 08

나는 주로 React의 상태 흐름(state flow), 컴포넌트 트리 구조에 대한 이해를

바탕으로 버그를 fix하는 것과 모듈 의존성 구조에 대한 이해를 바탕으로

참조 순환(circular reference) 문제를 해결하는 등 전체적으로 문제해결에

많은 일을 도맡아 해왔던 것 같다.

 

그리고 UX향상을 위해 많은 노력을 해왔던 것 같다.

컨텐츠가 넘치거나 없을 때의 경우 디자인이 빠져있는 경우가 꽤나 많았고

응답이 지연되는 상황에 대응하는 로딩 스피너, 스켈레톤 대체, 로딩화면 풀커버링 등

누락된 디자인들에 대해 필요성을 이야기하며 추가 디자인을 요구하며 프로젝트를

진행해왔다.

 

개발 부에서는 어색한 CSS의 개선과 tablet사이즈부터 mobile사이즈까지 대응 가능한

폭 넓은 반응형 style을 만들어내고 컴포넌트 Lazy import로 발생하는 Fallback을

커스텀 훅 useSoftNaviate를 구현하여 부드러운 전환을 만들어내는 등

UX향상을 정말 많이 신경쓰며 개발해왔다.

 

디자이너님과 소수 개발자분들은 UX향상 해준 것이 체감되고 중요하다고 말하지만

생각보다 사내 대다수 개발자들은 잘 모르겠다, 개발시간이 더 중요하기 때문에

그럴 시간이 없다 등... 오히려 좋지 않은 시선을 받는 경우도 많았다.

 

UX향상을 위해 보통 10분~ 30분을 더 투자하기도 하고 난해한 경우에는 그냥

야근을 해서라도 UX가 좋은 화면을 구현하고 싶은 것이 이기적인 욕심인가?

라는 생각도 들었다.

( 그리고 기한을 넘겨서 고객사에 피해를 끼친적도 없다 ㅠㅠ )

 

SI기업의 특성상 일정이 빠듯해서 동료들의 입장도 이해가 되긴한다.

 

그리고 지금의 회사에서 모두가 그렇다고 해도 스스로가 만족하지 못한다면 그저

혼자 더 작업을 하면 될 뿐이고, 나는 이러한 생각을 바꾸고싶지 않다 ㅎㅎ

 

💾Backend

뭐야 너 프론트엔드 개발자잖아.

아니다. 이제는 그냥 잡부라고 보면 될 것 같다.

 

기존에 Nest.js로 Node기반 서버를 만들어 직접 메모서비스를 배포해보기도 하였고,

Next.js와 Prisma를 활용한 Serverless Architecture로 개발하여 현재 실제 운영중인

경제학습 사이트도 개발한 경험도 있다.

 

JAVA Spring에서는 아주 단순한 버그나 확장성에 저해되는 구조를 리팩토링해본

경험도 있고 가장 크게 백엔드를 경험한 것은 Python서버를 개발한 경험이다.

 

개발한 Python서버는 사내 프로젝트중에 사업계획서를 분석해서 보완하면

좋을 부분이나 추가하면 좋을 내용 등을 LLM( GPT )을 프롬프트를 활용해서 내용을

반환해주는 일명 " 사업계획서 피드백 챗봇서버 "를 만들었다.

 

사실 이 부분은 대표님께서 신입 직원으로 Python을 다뤄본 컴퓨터공학과 개발자를

채용하였고 그 신입직원분이 초기 개발을 진행했다.

 

그런데 갑자기 그 분이 떠나게 되었다.

급하게 Python 개발자 파견 인력이 필요했고 때문에 신입 직원분은 사무실을 떠나

고객사에 배치되어 파견업무를 시작하게 된 것...

 

아무래도 서버 개발이니 내가 할 이유도 없었고 해도 서버개발자가 할 것 같았다.

하지만 사무실 배치 인력들은 Python을 본적도 없고 할 줄 모른다는 이유로

서버개발자들도 못한다고 단정지으며 안된다고 했다.

 

나는 Nest.js로 서버를 구현한 적이 있고 JAVA를 공부할 때도 사실 큰 흐름에 대한 것은

다르지 않다 라는걸 알고 있기 때문에 하면 할 수 있다 라고 생각했다.

 

결국 모두가 할 수 없다는 결론이 나왔고, 제가 해보겠다고 자진해서 Python서버를

이어서 개발하기로 했다.

 

🥧Python...

나는 프론트엔드 개발자이지만 한 눈에 알아 볼 수 있었다.

큰일났다. 아무리 그래도 그렇지 app.py에 모든 코드를 넣어버릴 줄은......

가장 우선적으로 프로세스, 로직의 플로우를 이해하기가 매우 어려운 상황이었다.

 

그래서 절차적으로 공부 계획을 짰다...

1. 파이썬 언어가 어떻게 작동하는지, 스레드는 어떤 방식으로 활용하는지

2. 파이썬 문법은 어떻게 활용하는지, 지금 코드에서는 어떻게 활용하고 있는 것인지

3. 사용되고 있는 핵심 라이브러리

 

이렇게 절차적으로 이해도를 가진 상태에서는 디자인패턴을 반드시 추가해야겠다는

생각이 들었다.

 

기본적으로 가장 친숙하게 활용해보았던 Nest.js와 유사한 패턴( MVC와 유사 )으로

폴더를 분기하여 유지보수에 더 유리하도록 리팩토링했다.

 

처음 파이썬을 프로젝트를 열어봤을 때 package.json 같은 패키지 관리파일이 없었고

공부하며 알아보니 requirements.txt 라는 폴더로 package list를 export하고 해당

txt파일을 기준으로 install할 수 있는 기능이 있다는 것을 알게 되었다.

 

그리고 전역에 패키지를 인스톨하는 기존 방식에서 venv를 활용하면 프로젝트 단위로

가상 환경에 패키지를 설치할 수 있다는 사실도 알게 되었다...

 

requirements.txt를 활용한 패키지 리스트관리, venv를 활용한 프로젝트 단위의

가상환경 패키지 관리를 설정하였고 얼마나 날것의 코드인지 알게되는 순간이었다...

 

하지만 챗봇 서버 특성상 중간에 요청을 취소할 수 있어야 했는데

기존에 작업했던 모든 라이브러리가 비동기적으로 활용 불가능한 라이브러리들 뿐이었다...

 

기본적으로 동기적으로만 작동한다면 응답 취소가 불가능하다.

또한 블로킹 형태가 되어 동시에 여러명이 요청을 하게 되면 응답시간이 지연되는

문제도 있었다.

 

때문에 http통신, dbconnection 라이브러리를 교체하여 논블로킹 방식으로 리팩토링했다.

pymysql => aiosql

requests => aiohttp

 

그리고 안전하고 정확하게 요청을 취소하기 위해서 직접 worker-pool을 만들어

요청할 때 받은 id를 pool에 가지고 있다가 취소한 경우 정확하게 해당 id요청을

취소할 수 있도록 구현하였다.

 

db커넥션 속도를 최적화 시키기 위해 db pool 또한 구현하여 처리속도를

약 2배 더 향상시켰고 결과적으로 처리속도는 약 4배 빨라졌고 취소 요청도 모두

성공적으로 작동하는 챗봇서버로 재탄생하였다.

 

그리고 토큰검증을 편리하게 활용하기 위해 기존 java spring서버로 구성되어있는

토큰검증만을 실행하는 api를 작업자에게 작업요청하고 이를 활용하기로 했다.

 

해당 api를 데코레이터로 구성하여 동기/비동기요청에 따라 분기처리하고

토큰을 검증하는 AuthGuard데코레이터로 만들어 간단하게 controller 매서드 위에

선언하여 활용하기도 했다.

 

🏠DevOps

⚙️API 자동생성

기본적으로 포지션이 프론트엔드이기 때문에 서버 개발자들과 요청 시 데이터 형과

필요한 데이터들에 대해 소통할 일이 많고 swagger-ui로 요청 데이터의 key, value를 확인하며

fetch api를 제작하게 된다.

 

나는 개발자를 준비하며 Swagger에 작성된 내용을 자동생성하는 OpenApi - generator를

구현한 경험이 있어 이를 사내 프로젝트에서도 기여하고자 했고, mustache파일을 직접 추출해서

경로를 지정하고 mustache파일을 직접 커스텀하여 swagger 기반으로  API를 자동생성할 수 있도록

package.json - scripts에 명령어를 추가하여 소통비용을 줄이기도 했다.

 

화면을 구현하는 것 역시 재미있지만, 개발 환경을 자동화하는 것도 정말 재밌는 것 같다.

 

🤵🏻Jenkins pipeline & 무중단 배포

기존에 구성되어있던 pipline은 대부분 sh파일을 통해서 직접 pid를 관리하며 down-time이

존재하는 레거시 방식으로 구현되어있었다.

 

프론트엔드 빌드파일은 직접 pm2를 활용하여 cluster mode로 무중단배포화 하기 위해

static html파일을 띄우는 것이 아닌, fastify로 구성한 server.js를 구현하고 node환경에서

무중단배포가 가능하도록 구현했고, 서버작업자에게는 Blue/Green 배포 방식으로 변경하는

것을 권장드렸다.

 

근데 1년전에 말한 것 같은데 아직 바뀌지 않은 것 같다...

조만간 내가 eginx에 추가 코드를 작성해서 무중단배포가 가능하도록 구성해야겠다.

 

pipline은 stage를 필요 구성으로 수정하고 각 처리마다 echo 메시지를 넣어 디버깅에 더욱

유리하게 구성하였고 execCommand를 좀 더 상세히 작성해서 서버가 띄워져 있다면 reload,

서버가 없다면 start 등으로 완전 자동화 방식으로 작업환경을 개선했다.

 

✍️마치며...

이렇게 돌아보며 1년 정도 회고를 해보니 정말 많은 경험을 했고 많은 일이 있었던 것 같다... 매번 생각하지만 스스로 개발자를 자처한다면 아무리 자기 포지션이 아니더라도 해낼 수 있다는 자신감을 가지고 뛰어들어보는 것도 정말 좋은 것 같다. 나는 그렇게 성장해왔고 덕분에 매번 개발이 즐겁거운 것 같다.

2025. 8. 2. 17:46

🤔공부하게 된 계기

나는 Window OS를 사용하고 있다.

회사에서 커밋을 할 때  MacOS를 쓰는 분의 코드를 수정하고

커밋하면 파일의 모든 코드가 변경된 파일로 인식이 되어 네이밍만

변경해도 파일 전체가 다시 커밋되어 문제가 있어 알아보게 되었다.

 

📌OS별 개행 방식의 차이?

기본적으로 Window OS에서는 CRLF방식을 활용하여 개행한다.

그리고 Unix, Linux, MacOS는 LF방식을 활용하여 개행하게 된다.

 

각 개행 방식은 아래와 같다.

  • LF = \n
  • CR = \r
  • CRLF:  \r\n

사실상 CR방식은 MacOS 9버전 이하에서 사용했었기 때문에

이제는 거의 취급하지 않는다.

 

🐈‍⬛개행 방식 자동변환 설정

" git config core.autocrlf " 명령어를 통해서 깃에서 커밋할 때

개행 방식 자동 변환에 대한 설정을 할 수 있다.

 

core.autocrlf = input

branch에 checkout( git pull )할 때

개행방식을 변환하지 않고 기존 코드에 녹아든 방식을 유지하고commit할 때 LF 개행방식으로 변환해서 저장소에 올린다.

 

core.autocrlf = false

자동변환 하지 않는다.

 

core.autocrlf = true

Window에서는 checkout했을 때 LF로 받은 경우 CRLF로 변환하고

commit할 때 LF변환하고 커밋하며

MacOS와 Linux에서는 양방향으로 LF로 자동변환 처리한다.

 

  • 명령어
// 마지막 명령어를 true, false, input 등으로 변경하면 적용된다

git config --global core.autocrlf true
git config --local core.autocrlf true

 

 

✅그렇다면 어떻게?

결론적으로 쉽게 설정하기 위해서 MacOS와 Window OS 모두

input으로 설정해주면 된다.

git config --global core.autocrlf input
git config --local core.autocrlf input

 

그럼에도 혹시나 작업환경이 바뀌었을 때 사람인 이상 깜빡할

가능성은 분명 존재한다.

 

🪄프로젝트 자체에서 공통 설정하기

사실 MacOS나 Window, Linux 등의 개행방식도 중요하지만

Git에서 기대하는 개행 값이 LF 개행방식이기 때문에

공동작업자와의 OS 차이까지 생각해보면 LF 개행방식으로

commit을 하는 것이 바람직하다고 볼 수 있다.

 

이를 해결하기 위해 프로젝트 root 경로에 .gitattributes라는

파일을 생성해준다. 그리고 아래 코드블럭처럼 넣어주면

commit할 때 최우선 순위로 autocrlf 설정이 적용되어 강제로

LF로 commit하게 된다.

 

  • .gitattributes
# 모든 텍스트 파일은 자동 감지되고 LF로 저장
* text=auto eol=lf

# 명시적으로 LF 강제할 확장자들
*.js   text eol=lf
*.jsx  text eol=lf
*.ts   text eol=lf
*.tsx  text eol=lf
*.css  text eol=lf
*.scss text eol=lf
*.html text eol=lf
*.json text eol=lf
*.md   text eol=lf
*.yml  text eol=lf
*.yaml text eol=lf
*.sh   text eol=lf
*.env  text eol=lf

# 바이너리 파일은 줄바꿈 처리 제외
*.png  binary
*.jpg  binary
*.jpeg binary
*.gif  binary
*.ico  binary
*.pdf  binary
*.woff binary
*.woff2 binary
*.ttf  binary
*.eot  binary
*.mp4  binary

 

 

✍🏻마치며...

프론트엔드 개발을 지속하며 React의 state flow나 기본적인 script, memory 프로세스들에 대한 이해도는 높아졌지만 막상 다른 부분들에서 취약점이 드러나는 것 같다. 이제 좀 더 확장하여 딥다이브하는 시간을 많이 가져봐야겠다.

 

'Git' 카테고리의 다른 글

[ Convention / git-commit-message ] 컨벤션이란?  (0) 2024.09.28
2025. 5. 4. 18:35

🤔Cross Platform?

크로스플랫폼이란, 서로 다른 디바이스 또는 전혀 다른 OS에도

대응되어 어색함 없이 동일하게 작동될 수 있도록 프로그램( 어플리케이션 )을

개발하는 것을 의미한다.

 

앱개발로 유명한 두가지 프레임워크를 뽑자면 React Native와 Flutter를 꼽을 수 있다.

 

React-Native 일명 RN은 JS로 이뤄져있는 코드를 큰 번들러로 묶어

액션이 일어나면 브릿지로 JS코드를 전달하고 브릿지는 이를 해석하여

OS가 인식할 수 있는 코드로 재번역하여 전달하고 작동(렌더링)하게 된다.

 

즉, RN은 브릿지가 JS로 이루어진 코드를 Native하게 작동할 수 있도록 하는

아주 중요한 역할을 하는 셈이다.

 

그렇다면 Flutter는 어떻게 크로스플랫폼을 지원하고 있을까?

 

🛠️Flutter

플러터는 Google에서 개발된 Dart 언어 기반의 프레임워크이다.

Dart라는 새로운 언어를 배워야 활용이 가능한 부분에서 러닝커브가 있는 편이지만

React, Java, Python 등을 경험해본 입장에서는 크게 어렵지 않았다.

객체지향 방식의 패턴이 오히려 접근성이 좋아 러닝커브가 높다는 생각은 들지 않았던 것 같다.

 

플러터는 RN과 같이 직접적으로 OS와 소통 후 작동(렌더링)하는 방식이 아닌,

별도의 C++로 구성된 엔진위에서 어플리케이션을 그려낸 후 독립적인 형태로

동작하기 때문에 OS간 불일치율이 없다시피 개발이 가능한 것이 강점이다.

 

 

Create Project

flutter create your_project

 

 

Example Code

import 'package:flutter/material.dart';

void main() {
  runApp(const App());
}

class App extends StatelessWidget {
  const App({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        backgroundColor: Colors.black,
        body: Column(
          children: [
            // 박스를 추가하여 간격을 만듦
            const SizedBox(
              height: 80,
            ),

            // 헤더 Row
            Row(
              // Row의 Align을 end로 설정 ( justify-content: end 와 유사 )
              mainAxisAlignment: MainAxisAlignment.end,
              children: [
                Column(
                  // 해당 컬럼 item 내부 정렬을 end로 설정 ( justify-content: end 와 유사 )
                  crossAxisAlignment: CrossAxisAlignment.end,
                  children: [
                    const Text(
                      "안녕하세요, 홍길동님",
                      style: TextStyle(
                        color: Colors.white,
                        fontSize: 38,
                        fontWeight: FontWeight.w600,
                      ),
                    ),
                    Text(
                      "복귀를 환영합니다.",
                      style: TextStyle(
                          color: Colors.white.withOpacity(0.8), fontSize: 22),
                    ),
                  ],
                )
              ],
            )
          ],
        ),
      ),
    );
  }
}

* 위 예제코드는 " /your_project/lib " 경로에 있는 main.dart 파일에서 활용된 소스코드입니다. 

 

* 예제코드로 나온 결과화면

 

✍️마치며...

새로운 언어, 새로운 프레임워크를 공부하고 개발할 때마다 역시 기술을 공부하며 개발하는 것은 개발자의 평생 숙제라는 것을 다시 한번 깨닫게 되는 계기였다. 여러 언어, 프레임워크를 경험하며 느껴지는 것들은 한가지만 고수하는 것도 분명 역량을 끌어올리기 좋을 수 있지만 다방면의 경험을 쌓는 것 또한 프로그래밍, 개발에 있어 전체적인 흐름을 이해하고 더 넓은 시야로 볼 수 있는 역량이 좋아지고 있는 것 같다. 다시금 느껴지는 것은 개발자라는 직업을 갖게되어 정말 다행이고 행복하다. 앞으로도 이 마음가짐을 잃어버리지 않도록 더욱이 노력해야겠다 ㅎㅎ

2025. 1. 1. 19:18

Flutter를 공부하며 프로젝트를 만드려고

cmd에서 create 명령어를 실행해보았다.

 

 

flutter create flutter-intro !!!!

 

 

 

 

...

 

 

 

 

결과는 성공적이지 못했다...

 

 

 

cmd: Error: Unable to find git in your PATH. ㅋㅋ

 

해당 에러는 Git 보안 설정과 연관이 있다고 한다.

때문에 별도로 예외처리를  적용시켜주어야 하는데

특정 경로만을 예외처리 하지 않고 모든 경로에서

가능하도록 명령어를 실행해주었다.

 

git config --global --add safe.directory '*'

 

이제 모든 경로가 안전하다고 명시되었고, 어떠한 경로에서도 create가 가능해졌다.

 

다시한번...

 

flutter create flutter-intro !!!!

 

cmd: ... Try "flutter_intro" instead. ㅋㅋ

 

 

??

 

 

평소 create-react-app, create-next-app에 절여진 나는...

케밥케이스로 네이밍해왔지만 Dart에선 이를 지양하는 것 같았다...

 

 

flutter create를 사용할 땐 스네이크 케이스를 쓰자 !

 

 

사실 보안상 직접 진행하는 프로젝트만 모아둔 경로만 safe한 것이 좋다.

해커가 심어둔 쿠키가 execCommand로 악성 프로그램을 pull 하게 만들든 후 run 시킨다면...?그때부터는 내 컴퓨터가 아니게 될 수도...

2024. 10. 20. 18:46

🤔NextJS 쿠키?

브라우저에 저장되는 일반적인 쿠키와 다를게 없지만

NextJS는 SSR을 지원한다는 점에서

cookie를 서버에서 확인할 수 있는 방법이

제한적이기 때문에 CSR(React 등)만 활용하여

개발하던 개발자들은 생각보다 더 난해한 문제를

겪게 될 수 있다.

 

그런 개발자 중 한명이 필자였고 특히

쿠키를 활용한 JWT 로그인 유지를 구현할 때

interceptor를 통해 매번 토큰을 header에 넣어 요청하고

accessToken이 만료된 경우에는 refreshToken을

서버에 재발급요청하여 재생성된 토큰들을 쿠키에 저장하고

저장된 쿠키를 통해서 이전 요청을 재요청하는 프로세스에서

accessToken 쿠키가 undefined인 상태로 요청이 되는 이슈

꽤나 험난한 삽질과 많은 시간을 고민하게 되었다.

 

결과적으로 NextJS를 제대로 다루기 위해서는

hydration,

middleware,

server - component,

server - actions / mutations,

위 4가지의 작동방식은 필수적으로 학습을 통해

Next가 작동되는 방식에 대해 이해하고 있어야한다는

생각이 들었다.

 

🫗hydration

(hydration에 대한 글은 개인적 주관이 강한 글이기 때문에 넘어가셔도 좋습니다😊)

필자는 단순히 하이드레이션을 주입식 교육처럼

하이드레이션 = 서버의 결과를 클라이언트로 합치는 것

이라고만 생각했지만 결과적으로 이해하게 된 계기는

여러 이슈를 겪으며 어원에 대해 다시 생각하는 것으로

이해도를 갖추게 된 것 같다.

 

hydration이란 수분공급 이라는 어원을 가지고 있다.

그렇다면 어째서 수분공급이지? 라는 의구심을 가지고

좀 더 단순하게 어원에 대해 생각했을 때 식물이 뿌리에서

흡수한 물을 줄기를 통해서 수분공급을 하는 방식을 떠올려 봤다.

 

뿌리 = Server

(땅속에 있어 우리가 표면적으론 볼 수 없지만 핵심이 되는 뿌리)

 

줄기, 잎, 꽃 등 = Client

(땅을 파지 않아도 겉으로 볼 수 있는 식물의 외형)

 

식물은 수분공급이 제대로 이루어지지 않는다면

그 식물은 시들어버리거나 제대로 성장하지 못한다.

 

그렇기 때문에 Server에서 보여주고자 하는 것을

Client에 공급해주어 제대로된 결과물을 보여주는 것이

Hydration이구나! 라는 결론을 내리게 되었다.

 

물론 그저 나의 상상력으로 여기까지 온 것일 수도 있다...

하지만 좀 더 어원에 대해 이해하려할 수록

이해도가 높아지는 경우가 생각보다 많았던 것 같다.

 

만약 영어가 아닌 한글이었다면 조금 더 직관적으로

프로세스를 이해했을 수도 있지만 프로그래밍 언어가

기본적으로 영어로 되어있기 때문에 우리가 프로그래밍에

대해서 이해하기 어렵게하는 하나의 벽이 되고있지 않나...

하는 생각이 들곤 한다.

 

🔗middleware

middleware는 server에서 client에 렌더링되기 이전에

거치게 되는 곳으로 서버와 클라이언트의 교집합 지점이라고

볼 수도 있는 영역이다. 때문에 NextJS를 다룬다면 정말 중요한

기능이기 때문에 꼭 알아야된다고 생각하는 것 중 하나다.

 

NextJS를 활용해서 사용자에게 보여주기전에 server에서

내부적으로 redirect하거나 필수적인 쿠키를 미리 설정

가능하고 국제화를 하는 경우에는 페이지에 접속한

국가에 적합한 언어로 구성된 페이지를 제공하기 위해서

활용하기도 한다.

 

middleware 활용처는 너무 많기 때문에 예제코드는

필자의 깃허브 링크로 남겨두겠습니다.

 

* nextjs14 app-router 국제화를 적용한 템플릿을 예제로 넣었습니다.

Github: https://github.com/zeriong/next14-app-router-i18n-template/blob/master/middleware.ts

 

⚙️server-component

NextJS에서 컴포넌트를 구성할 때 최상단에 "use client"를

작성하지 않는다면 기본적으로 server-component로 작성된다.

그리고 "use client"를 작성한다면 react에서 사용되는 CSR관련

Hooks를 활용할 수 있게 된다.

 

단 여기서 중요한 것은 "use client"라고 해서 SEO가 안되는 것은

아니라는 점이다.

 

html 구성은 server에서 렌더링이 되기 때문에 SEO는

영향을 끼치지 않는다. 단지 CSR에서 활용 가능한

React의 Hooks를 활용해서 CSR에서 작동되는 JS를 활용하겠다.

라고 선언하고 활용하는 것에 불과하다.

 

그러니 "use clinet"를 썼다고 해서 SEO가 안될 것이라는

걱정은 하지 않아도 될 것이다.

(useEffect를 활용하여 state 변경후에 생성되는 컴포넌트 제외)

 

 

🪄server - actions / mutations

서버에서 실행되는 비동기함수를 뜻한다.

form에서 활용하는 action이나 기타 fetch를 활용한

api요청 등을 server에서 작동하게 만드는 것이다.

 

활용방식은 아주 간단하게 해당 함수의 환경 최상단에

"use server" 를 선언하게 되면 이는 server에서 작동하는

함수로 정의된다.

 

"use server"를 정의하는 환경은 주로 파일단위나

함수단위로도 활용 가능하다.

 

상황에 따라서 우리는 다양하게 활용하지만 주로

하나의 파일에서 "use server"를 최상단에

정의하여 모듈화하여 활용하는 경우가 보편적이다.

 

예시적으로 actions.ts 파일을 생성한다고

가정했을 때의 예제 코드이다.

 

  • server-actions 예제코드
// actions.ts

"use server";

/**@desc login server-action */
export async function loginAction(prevState: { success?: boolean; msg?: string }, formData: FormData) {
  const userId = String(formData.get("userId")).trim() as string;
  const userPassword = String(formData.get("userPassword")).trim() as string;

  if (!userId.length || !userPassword.length) return { success: false, msg: "아이디 또는 비밀번호를 확인해주세요" };

  const reqBody = { userId, userPassword };

  const res = await fetch(`${process.env.NEXT_PUBLIC_API_URL_AUTH}/auth/login`, {
    method: "POST",
    body: JSON.stringify(reqBody),
  });

  const resBody = await res.json();

  if (resBody.code != 200) return { success: false, msg: resBody?.message };

  return { success: true, msg: "success" };
}

 

위처럼 server-action을 구성하고 해당 server-action을 로그인을 하는 컴포넌트에서 useFormState 훅을 활용해서 state로 response 결과값을 client에서 동적으로 확인할 수 있다.

 

  • server-mutations 예제코드
// mutations.ts

"use server";

import { getUserInfo } from "@/apis/user";

/** get user data */
export async function getUserData() {
  const res = await getUserInfo();
  return res.body.data;
}

 

정말 단순하게 "use server"를 명시해주어 server에서 해당 api로 fetch를 통해 response 값을 받아볼 수 있다.

 

server - actions / mutations 장점

  1. network 요청 수를 줄일 수 있다
  2. server 내부에서 미리 값을 fetch 받아 렌더링하기 때문에 SEO 향상
  3. API route 없이 서버 측에서 직접 DB에 접근가능
  4. 민감한 데이터를 클라이언트 측에 노출시키지 않을 수 있음
  5. client side 번들 사이즈가 줄어 초기 로딩 속도 개선

 

🍪NextJS 쿠키 트러블 슈팅

내가 맞닥뜨린 이슈는 결국 NextJS에서 쿠키에 대한

hydration이 필요한 상황이었고 가장 첫번 째로 고민한 것은

가능한 것에 대한 고찰이었다.

 

서버에서 쿠키에 접근가능한 방식을 생각해봤을 때

next header에 접근할 수 있어야하는 것이

우선 선행이 되어야 했다.

 

그렇다면 어떠한 경우에 server에서 쿠키에 접근할 수 있는가?

내가 떠올릴 수 있는건 두가지였다.

 

1. middleware의 NextRequest를 통한 접근

2. server-component에서 next-header의 cookies()로 접근

 

1번의 경우는 현실성이 부족했고 2번으로 접근하기로 했다.

 

하지만 interceptor를 구성할 때 따로 api를 요청할 때 마다

지속적으로 재사용해야 하기 때문에 파일로 분기하여

구성할 수 밖에 없었다.

 

단순히 fetch에 interceptor를 구성하여 붙이는 코드로 구성되어있어

최상단에 "use server"를 명시하는 것도 말이 안되고,

그렇다고 interceptor를 server-component에서 구성하는 것도

말이 안된다고 생각이 들었다.

 

그때 마침 생각난 것이 바로 server-component가

next-header에 접근할 수 있는 이유에 대해서 생각해봤다.

 

nextjs14에서는 컴포넌트 구성 시 최상단에

"use client"를 명시하지 않으면 서버컴포넌트로 정의된다.

 

이는 즉 이전 버전에서 사용하던 "use server"가 생략됐을 뿐이고

server - actions / mutations에서 최상단에 "use server"를

명시하고 활용하는 것과 동일하다고 생각이 들었다.

 

그렇다면 방법은 하나 뿐이다.

utils에 server 폴더를 만들고 최상단에 "use server"를 명시한

cookies.ts파일을 만들어 내부에 유틸을 구성하는 방법이다.

 

getServerSideCookie,

setServerSideCookie,

removeServerSideCookie,

 

위 세가지 쿠키관련 유틸을 구성하고

next-header에 접근할 수 있는 환경에서

쿠키를 컨트롤할 수 있도록 만들어주었다.

 

결과는 성공적이었고,

모든 server - actions / mutations와

클라이언트에서의 fetch 요청으로도 성공적인

로그인 유지가 가능한 결과를 얻을 수 있었다.

 

✍️마치며...

개발에 대한 경험이 늘어남에 따라 느끼는 것은 개발은 언제나 정답이 정해져있는 것이고 그 정답에 도달하기 위해선 내가 맞닥뜨린 문제에서 성공적인 예시를 통해 하나씩 이어가는 것이 가장 빠르고 올바르게 이해하며 정확하게 문제를 해결할 수 있는 방법인 것 같다.