COMENTO

더워지던 6월의 뜨거운 세미나

김문범 프로필 이미지

김문범

2025.09.01

11 min read

더워지던 6월의 뜨거운 세미나

안녕하세요! 코멘토의 백엔드 개발자 김문범입니다.

우리 팀의 소중한 지식 공유 문화를 널리 알리고자 합니다. 지난 6월 11일, 우리 팀에서는 '일 더 하기 일: 더 잘하기 위한 나만의 방법' 이라는 주제로 내부 세미나를 진행했습니다. 이번 세미나는 개개인의 성장을 위한 노하우와 경험을 공유하며 서로에게 배우고, 함께 성장하는 의미 있는 시간이었습니다.

열정 가득했던 세미나의 현장을 요약하여 공유해 드립니다.


여러 개의 모달(Modal), 어떻게 관리하고 계신가요?

공유자: 김민기 (프론트엔드 개발자)

가벼운 공유를 위한 라이트닝 토크를 김민기님께서 첫 번째로 공유해주셨습니다.
프로젝트를 진행하다 보면 수많은 모달창을 다루게 되는데, React 환경에서 각 모달의 열림/닫힘 상태를 개별적인 useState로 관리하는 방식의 불편함과 코드의 장황함에 주목했습니다.

// AS-IS: 개별적인 상태로 관리
const [alertModalOpen, setAlertModalOpen] = useState(false);
const [submitConfirmModalOpen, setSubmitConfirmModalOpen] = useState(false);
const [removeConfirmModalOpen, setRemoveConfirmModalOpen] = useState(false);
// ... 모달 개수만큼 반복

이를 해결하기 위해, 여러 모달의 상태를 하나의 객체로 묶어 관리하는 아이디어를 제시했습니다.

// TO-BE: 중앙에서 상태 관리
export const MODALS = {
  alertModal: false,
  submitConfirm: false,
  removeAttachmentConfirm: false,
  // ... 필요한 모달들을 한 곳에 정의
};

// ModalKeys를 생성하여 타입 안정성 확보 및 휴먼 에러 방지
export const ModalKeys = Object.fromEntries(
  Object.keys(MODALS).map((key) => [key, key]),
) as { [key in keyof typeof MODALS]: key };

// 공통 open/close 함수
function openModal(name: keyof typeof MODALS) {
  setModalStatus((prev) => ({ ...prev, [name]: true }));
}

function closeModal(name: keyof typeof MODALS) {
  setModalStatus((prev) => ({ ...prev, [name]: false }));
}

위의 방식을 통해 불필요한 코드 반복을 줄이고, ModalKeys를 활용해 문자열 오타 등으로 발생할 수 있는 휴먼 에러를 방지하며 코드의 가독성과 유지보수성을 크게 향상한 경험을 공유해 주셨습니다. 앞으로 이 로직을 custom-hook이나 Zustand와 같은 상태 관리 라이브러리를 통해 더 발전시킬 계획도 들을 수 있었습니다.


질의응답 및 의견 공유

김민기님의 발표가 끝난 후, 모달 상태 관리에 대한 깊이 있는 질의응답과 의견 공유가 이어졌습니다.

  • 커스텀 훅과 Zustand의 장단점: 모달 관리를 커스텀 훅으로 만들 때 여러 컴포넌트에서 동적으로 재사용할 수 있지만, 모달을 많이 사용하는 페이지에서는 여러 번 호출되어 성능에 영향을 줄 수 있다는 의견이 나왔습니다. 이에 대한 해결책으로 Zustand와 같은 상태 관리 라이브러리를 활용해 전역 상태로 관리하면, 각 컴포넌트가 필요한 모달 상태만 구독(subscribe)할 수 있어 효율적이라는 의견이 제시되었습니다.
  • 타입 안정성 확보 팁: ModalKeys를 활용한 타입 안정성 확보 방법에 대한 질문과 함께 추가적인 팁을 요청했습니다. 김민기 님은 제네릭(Generic) 타입을 사용하면 더욱 유연한 코드 작성이 가능하다며, 모달의 props 타입을 제네릭으로 받아 재사용할 수 있는 컴포넌트를 만들 수 있다고 설명했습니다.

일 더 하기 일: 아직 멀지만, 이렇게 해보고 있어요

공유자: 박상우 (프론트엔드 개발자)

첫 발표는 인턴 과정을 훌륭하게 소화하고 있는 박상우님께서 열어주셨습니다. '일을 잘하는 사람'에 대한 고민에서 출발하여, 본인만의 성장 루틴을 세 가지 키워드로 정리하여 공유했습니다.

  • 백그라운드 따라가기: Notion, Agit 등 협업 도구의 히스토리를 꾸준히 확인하고, 동료들과의 커피챗과 회고에 적극적으로 참여하며 업무의 맥락을 파악하기 위해 노력합니다.
  • 업무 효율을 위한 루틴 개선: 맡은 업무를 To-Do 리스트로 상세히 정리하는 습관을 통해 태스크의 규모를 정확히 파악하고 핵심을 놓치지 않으려 합니다.
  • 기여해보기: 제품에 필요한 기능을 먼저 개발해 본 뒤, 코드 리뷰를 통해 얻은 피드백을 바탕으로 리팩토링하여 팀의 디자인 시스템에 기여합니다. 또한, ESLint에 커스텀 규칙을 추가하여 잠재적인 휴먼 에러를 방지하는 등 팀 전체의 생산성 향상에 기여한 경험을 나누었습니다.

자신의 성장을 위해 끊임없이 고민하고, 동료와 팀에 기여하고자 하는 상우 님의 열정이 돋보이는 발표였습니다.


인턴 2개월, 이런 걸 해봤어요

공유자: 배기훈 (프론트엔드 개발자)

다음으로 배기훈님께서 2개월의 인턴 기간 동안 경험하고 배운 값진 내용들을 공유해 주셨습니다.

  • Nuxt.js → Next.js 마이그레이션: 검색 답변 페이지를 마이그레이션하는 과정에서 겪었던 중첩 레이아웃 및 컴포넌트 오류 등의 기술적 허들을 해결했습니다. 더 나아가 코드 품질 향상을 위해 ESLint 커스텀 규칙을 적용하여 팀의 코드 스타일을 통일화하는 데 기여했습니다.
  • 구조화 데이터 적용으로 SEO 개선: 검색 엔진 최적화(SEO)의 목적으로, 아래와 같이 JSON-LD 형식의 구조화 데이터를 적용하여 검색 엔진이 웹 페이지의 정보를 더 잘 이해하도록 도운 경험을 나누었습니다. 이는 검색 결과 노출에 긍정적인 영향을 줄 수 있는 중요한 작업입니다.
{
  "@context": "<https://schema.org>",
  "@type": "Event",
  "name": "코멘토 세미나",
  "startDate": "2025-06-11T14:30",
  "location": {
    "@type": "Place",
    "name": "코멘토 사무실",
    "address": "서울 중구 칠패로 28 3층"
  }
}

  • Hackle을 이용한 A/B 테스트: 데이터 기반 의사결정을 위해 A/B 테스트를 도입하며 겪은 기술적 도전을 공유했습니다. 특히 서버 사이드 렌더링(SSR) 환경에서 발생하는 'Hydration Mismatch' (서버에서 렌더링한 초기 UI와 클라이언트에서 SDK 초기화 후 렌더링한 UI가 달라 깜빡이는 현상) 문제의 원인을 분석하고 해결해 나간 과정을 통해 깊은 인상을 남겼습니다.

짧은 기간임에도 불구하고 깊이 있는 고민과 성장을 이룬 기훈 님의 경험은 모두에게 큰 귀감이 되었습니다.


로컬 환경, Traefik으로 한 번에 관리하기

공유자: 윤종석 (프론트엔드 개발자)

이어서 윤종석님께서는 로컬 개발 환경의 효율성을 극대화하는 방법을 공유해 주셨습니다. 개발자가 로컬 환경에서 여러 프로젝트를 실행할 때, localhost:3000, localhost:8080과 같이 각기 다른 포트 번호로 접근해야 하는 번거로움을 겪습니다. 윤종석님은 이 문제를 해결하기 위해 클라우드 네이티브 엣지 라우터인 Traefik을 활용한 방법을 제시했습니다.

Traefik은 Nginx, Caddy 등 다른 대안들과 비교했을 때, 리버스 프록시 기능 자체에 고도로 특화되어 있어 설정이 간편하다는 장점이 있습니다. Docker 기반으로 손쉽게 구성할 수 있으며, 간단한 설정 파일 몇 개만으로 여러 개의 로컬 서버를 service.local.com, api.local.com과 같이 직관적인 도메인으로 묶어 관리할 수 있습니다.

# dynamic.yml
http:
  routers:
  # 'service'라는 이름의 라우터 정의
  service:
    rule: "Host(`service.local.comento.kr`)" # 이 도메인으로 들어오는 요청을
  service: service-web # 'service-web' 서비스로 연결
    entryPoints:
      - http
  services:
    # 'service-web'라는 이름의 서비스 정의
    service-web:
      loadBalancer:
        servers:
          # 실제 서비스가 실행되고 있는 주소
          - url: "<http://host.docker.internal:3000>"

service.local.comento.kr로 들어오는 요청을 내부적으로 host.docker.internal:3000에서 실행 중인 서비스로 손쉽게 연결해 줍니다. 이를 통해 복잡한 포트 번호를 외울 필요 없이, 실제 운영 환경과 유사한 도메인 기반으로 개발을 진행할 수 있어 개발 효율성과 경험을 크게 향상한 노하우를 공유해 주셨습니다.


Vibe 코딩을 해보자 (feat. JetBrains AI)

공유자: 남원규 (백엔드 개발자)

마지막으로 남원규님께서는 JetBrains AI Assistant와 함께하는 'Vibe 코딩'의 세계로 저희를 안내했습니다. 'Vibe 코딩'이란, AI와 함께 리듬을 타듯 유기적으로 협력하며 코드를 작성하는 것을 의미합니다.

남원규님은 AI의 능력을 최대한 활용하기 위해서는 "프롬프트(Prompt)가 가장 중요하다"고 강조했습니다. 단순히 "이거 만들어줘"가 아닌, 다음과 같이 구체적이고 명확한 요구사항을 담아 질문해야 원하는 결과를 얻을 수 있다고 설명했습니다.

  • 정확한 맥락 제시: "EduClassroomAssignment 모델과 연관된 EduApplicant 모델의 no를 기록하는 콘솔 Command를 만들어줘."
  • 제약 조건 명시: "현재 운용 중인 DB에 큰 부하가 가지 않도록 처리해 줘."
  • 사용할 기술 특정: "role과 permission 구현을 위해 spatie/laravel-permission 패키지를 사용해 줘."

물론, AI가 생성한 코드는 반드시 면밀한 검토가 필요하다는 점도 잊지 않았고 아래와 같은 위험한 명령어를 무심코 실행할 수 있다는 경고도 있었습니다.

# AI: "네. 원하시는 작업은 모든 파일 삭제입니다. 실행하시겠습니까?"
$ sudo rm -rf /*

AI를 단순한 코드 생성기가 아닌, 똑똑한 개발 파트너로 활용하는 남원규님의 노하우는 앞으로의 개발 생산성을 어떻게 높일 수 있을지에 대한 새로운 시각을 열어주었습니다.


마치며

이번 '일 더 하기 일' 세미나는 프론트엔드부터 백엔드까지, 인턴부터 시니어까지 모두가 각자의 위치에서 더 나은 개발자로 성장하기 위해 노력하는 모습을 엿볼 수 있는 소중한 시간이었습니다. 동료들의 깊은 고민과 번뜩이는 아이디어를 통해 저 또한 많은 것을 배우고 느낄 수 있었습니다.

지식을 나누고 함께 성장하는 우리 팀의 이야기가 여러분께도 긍정적인 자극이 되었기를 바랍니다. 다음에도 유익한 소식으로 찾아뵙겠습니다. 감사합니다!


커리어의 성장을 돕는 코멘토에서 언제나 함께 성장할 개발자를 기다리고 있습니다. 채용 페이지에서 코멘토가 어떤 회사인지, 어떤 사람을 찾는지 더 자세히 확인해보세요. 😊