1. null vs undefined 둘 다 “값이 없음”을 나타내지만 의미가 다르다. let a; console.log(a); // undefined let b = null; console.log(b); // null undefined : 값이 아직 할당되지 않음 null : 개발자가 의도적으로 “값 없음”을 넣음 실무에서는 API 응답, 초기 상태값, optional 값 처리할 때 자주 만난다. 2. == vs === 1 == "1" // true 1 === "1" // false == 는 비교 전에 타입을 자동 변환한다. === 는 타입과 값이 모두 같은지 비교 한다. 그래서 실무에서는 거의 항상: if (a === b) { } 처럼 === 를 사용한다. 3. 타입 강제 변환(Type Coercion) JavaScript는 상황에 따라 타입을 자동으로 바꾼다. "5" + 1 // "51" "5" - 1 // 4 + 는 문자열 연결로 동작할 수 있지만, - 는 숫자 연산만 가능해서 숫자로 변환된다. 이런 암묵적 변환 때문에 JS에서 예상하지 못한 결과가 생길 수 있다. 4. Truthy / Falsy JS에서는 boolean이 아니어도 조건문에서 참/거짓으로 판단된다. Falsy 값: false 0 "" null undefined NaN 이외 대부분의 값은 Truthy다. if ("hello") { console.log("실행됨"); } 특히 주의할 것: [] // truthy {} // truthy 빈 배열과 빈 객체도 true 취급된다. 5. NaN NaN 은 Not a Number라는 뜻이다. Number("hello"); // NaN 특이하게: NaN === NaN // false 그래서 확인할 때는: Number.isNaN(value); 을 사용한다. 6. typeof 타입 확인: typeof 10 // "number" typeof "hello" // "string" typeof true // "boolean" typeof undefined // "undefined" typeof {} // "object" 그런데 유명한 예외가 있다. typeof null // "object" 이건 JS 초기 설계에서 생긴 오래된 버그성 동작이다. 핵심 정리 undefined → 값이 아직 없음 null → 의도적으로 값 없음 == → 타입 변환 후 비교 === → 타입 + 값 비교 → 실무에서 기본 사용 Truthy / Falsy → 조건문에서 값 자체가 true/false처럼 평가됨 []와 {}는 truthy NaN → 숫자로 변환할 수 없는 값 typeof null === "object" → JS의 오래된 특이사항
웹 애플리케이션 개발 시 피그마(Figma) 디자인을 코드로 구현할 때 단순히 이미지 캡처나 눈대중 수치를 이용하면 패딩, 마진, 폰트 스펙 등에서 오차가 발생한다. VS Code 기반의 Claude Code 환경에 Figma MCP(Model Context Protocol) Server 를 연동하면, 피그마 API를 통해 Auto Layout 수치, 컬러 토큰, Typography 정보를 직접 읽어와 정밀하게 1:1 코드로 변환할 수 있다. 시행착오 끝에 성공한 Figma MCP 서버 설정 과정 및 트러블슈팅 가이드를 정리한다. 1. 피그마 API 토큰 발급 Figma 웹 또는 데스크톱 앱 로그인 후 프로필 아이콘 클릭 $\rightarrow$ Settings 이동. Personal access tokens 섹션으로 이동. Generate new token 클릭. Token Scopes 설정 시 보안을 위해 읽기 전용( :read ) 권한만 선택한다. file_content:read (필수: 레이어 구조, Auto Layout 수치 조회) file_metadata:read library_assets:read / library_content:read file_dev_resources:read 생성된 토큰( figd_... 형태)을 복사해 둔다. 2. Windows PowerShell 스크립트 실행 권한 설정 PowerShell 환경에서 claude CLI 실행 시 스크립트 권한 에러( PSSecurityException )가 발생할 수 있다. 다음 명령어로 현재 사용자 계정의 실행 정책을 변경한다. Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser 권한 변경 확인 시 Y 를 입력한다. 3. .claude.json MCP 설정 파일 구성 npm 공식 스코프 패키지명이 아닌, 검증된 Figma MCP 패키지( figma-developer-mcp )를 사용해야 404 및 바이너리 실행 에러를 방지할 수 있다. VS Code 터미널에서 아래 명령어로 설정 파일을 연다. code C:\Users\Administrator\.claude.json 파일 내용을 다음과 같이 작성하고 저장한다. { "mcpServers": { "figma": { "type": "stdio", "command": "npx", "args": [ "-y", "figma-developer-mcp", "--stdio" ], "env": { "FIGMA_API_KEY": "figd_여기에_발급받은_토큰_입력" } } } } type: "stdio" : Claude Code와 MCP 서버 간 로컬 프로세스 직통 통신(Standard Input/Output) 방식이다. -y : npx 실행 시 패키지 자동 다운로드 승인 옵션이다. --stdio : 백그라운드 stdio 모드로 MCP 서버를 구동하는 옵션이다. 4. 트러블슈팅 (Troubleshooting) 1 npm error 404 Not Found (@modelcontextprotocol/server-figma) 원인 : @modelcontextprotocol/server-figma 패키지는 npm 레지스트리에 존재하지 않는다. 해결 : figma-developer-mcp 패키지를 사용하도록 지정한다. 2 npm error could not determine executable to run (mcp-server-figma) 원인 : npx 에서 해당 패키지의 실행 바이너리를 지정하지 못할 때 발생한다. 해결 : args 에 figma-developer-mcp 와 --stdio 옵션을 명시한다. 5. 연동 상태 확인 및 사용 방법 연동 확인 터미널에서 아래 명령어를 실행하여 연결 상태를 확인한다. claude mcp list 정상적으로 연동되면 다음과 같이 ✓ Connected 상태로 표시된다. figma: npx -y figma-developer-mcp --stdio - ✓ Connected Claude Code 활용 프롬프트 예시 피그마의 특정 프레임 우클릭 $\rightarrow$ Copy link to selection 으로 링크를 복사한 뒤 Claude Code 터미널에 전달한다. "이 피그마 프레임( https://www.figma.com/design/...?node-id=123-456)의 의) 레이아웃과 스타일을 Figma MCP로 읽어와서 src/components/Header.tsx 파일로 Tailwind CSS를 적용해 1:1로 정확히 작성해 줘. Auto Layout의 gap과 padding 수치를 엄격하게 지켜 줘."
알림만 보내면 되는 줄 알았다 신고가 끝나면 고객에게 알린다. 실무자가 하던 일이고, 그걸 시스템이 보내게 만들었다. 메시지 종류를 정하고, 보낸 기록이 남는 틀과 팝빌로 내보내는 연결을 만들었다. 여기까지는 하루 안에 됐다. 만들고 나서 빠진 게 보였다. 고객이 받아야 하는 건 "끝났습니다"라는 말이 아니라 신고서와 납부서 같은 서류다. 그런데 알림톡에는 파일을 못 붙이고, 글자와 버튼만 들어간다. 알림을 보내는 쪽을 만들어놓고, 정작 보내야 하는 건 못 보내는 상태였다. 버튼 뒤에 링크를 뒀다 서류는 서버에 올려두고, 버튼에 그 서류로 가는 주소를 달았다. 고객이 버튼을 누르면 서류가 내려온다. 세무나 법무 쪽에서는 다들 이렇게 한다. 메시지 규정에도 걸리지 않는다. 이때 그 주소는 열쇠 자체였다. 주소를 아는 사람이 곧 받는 사람이다. 주소가 카톡 대화창에 남고, 그 폰을 여는 사람이면 누구나 연다. 본인 확인을 붙일까 생각했다. 그리고 과하다고 적었다. 고객용 사이트를 따로 만들거나 인증을 붙이는 건 혼자 돌리는 시스템에 오버스펙이라고. 주소를 아무나 못 맞히게 길게 만들고, 며칠 지나면 죽게 했다. 그 정도면 된다고 봤다. 하루 만에 뒤집었다 그 판단은 하루를 못 갔다. 버튼을 누르면 파일이 바로 내려오지 않고 페이지가 하나 뜬다. 그 페이지가 휴대폰 끝 네 자리를 묻는데, 알림이 간 바로 그 번호의 끝자리다. 맞으면 그때 서류가 내려온다. 몇 번 틀리면 그 링크는 죽고, 실무자가 다시 보내야 한다. 대가가 있었다. 확인 페이지를 웹사이트 쪽 새 주소에 두면 버튼 주소도 바뀌고, 버튼 주소가 바뀌면 카카오 쪽 심사를 처음부터 다시 받아야 한다. 페이지는 웹사이트가, 파일은 서버가 맡는 구조가 심사를 한 번 더 기다리는 것보다 낫다고 보고 알면서 바꿨다. 오버스펙이라고 적은 지 하루 만에 그걸 넣었고, 심사도 처음부터 다시 신청했다. 신고 한 건은 폴더째 떨어진다 링크 하나에 파일 하나로 만들었다. 서류를 하나 올리면 링크가 하나 나온다. 실제로 신고 한 건이 끝나면 파일이 하나가 아니다. 신고서, 납부서, 영수증, 그 신고에 쓴 자료까지 폴더째 떨어진다. 실무자는 그 폴더를 통째로 보내야 한다. 선택지가 셋이었다. 폴더를 압축해 파일 하나로 올린다. 파일마다 알림을 따로 보낸다. 링크 하나에 파일 여러 개를 매단다. 압축 하나면 보내는 쪽은 링크 하나로 끝난다. 그런데 받는 쪽은 폰이다. 폰에서 압축 파일은 여는 것부터 일이다. 세 번째로 갔다. 링크를 열면 파일 목록이 뜨고 파일마다 따로 받는다. 한꺼번에 받는 버튼도 있는데, 그건 전체를 압축해서 내려준다. 거절한 건 압축이 아니라 압축 하나만 주는 쪽이었다. 본인 확인은 한 번만 하면 된다. 결정은 넷이었다 "서류 보내드릴게요"는 한 문장이다. 시스템으로 옮기니 결정이 넷으로 갈렸다. 어디로 보내나. 카톡으로. 뭘로 보내나. 파일이 아니라 링크로. 누가 여나. 그 번호의 주인이. 몇 개를 보내나. 폴더째. 처음부터 있던 건 어디로 하나였다. 나머지 셋은 만들고 나서야 보였고, 이틀 동안 세 번 고쳤다. 남길 것 세 번 고친 것을 나란히 놓고 보니 공통점이 하나 있었다. 셋 다 받는 사람 폰 화면에 있던 것들 이다. 파일이 안 붙는 것도, 링크만 알면 열리는 것도, 압축 하나로 주면 폰에서 풀어야 하는 것도. 나는 보내는 쪽부터 만들었다. 메시지를 고르고, 기록을 남기고, 팝빌로 내보내는 길까지 깔았다. 받는 사람 화면은 그리지 않았고, 그래서 그 화면에 있던 것들이 하나씩 뒤늦게 왔다. "보내드릴게요"를 시스템으로 옮기면 그 한 문장은 사라지고 결정 넷이 남는다. 넷은 받는 쪽에서 세야 한다.
1. input() 과 split() 질문 입력값을 특정 기준으로 나누려면 어떻게 해야 할까? 핵심 input() 은 문자열을 입력받고, split() 은 문자열을 나눈다. a, b = input().split() m, d, y = input().split('-') 기억할 것 input() # 문자열 입력 .split() # 공백 기준 분리 .split('-') # '-' 기준 분리 2. 여러 변수에 저장하기 질문 a, b = input().split() 은 어떻게 동작할까? 핵심 split() 으로 나눈 값을 각각의 변수에 저장할 수 있다. a, b = input().split() 입력이 10 20 이면 a = '10' b = '20' 기억할 것 변수 개수와 나눠진 값의 개수가 같아야 한다. 3. map() 과 list() 질문 왜 아래 코드는 잘못된 걸까? arr = [map(int, input().split())] 핵심 [map(...)] 은 map 객체 하나를 담은 리스트 다. 숫자들을 리스트로 만들려면: arr = list(map(int, input().split())) 흐름 input() → split() → map(int, ...) → list(...) 예: 10 20 30 arr = [10, 20, 30] 기억할 것 [map(...)] # map 객체 하나를 리스트에 저장 list(map(...)) # map의 결과를 리스트로 변환 4. 문자열을 숫자로 변환하기 질문 입력받은 숫자로 계산하려면? 핵심 input() 의 결과는 기본적으로 문자열이다. a = int(input()) 여러 개라면: a, b = map(int, input().split()) 리스트라면: arr = list(map(int, input().split())) 기억할 것 int() # 정수 변환 float() # 실수 변환 str() # 문자열 변환 list() # 리스트 변환 5. 리스트 기본 함수 핵심 arr = [10, 20, 30] sum(arr) # 60 len(arr) # 3 max(arr) # 30 min(arr) # 10 평균: sum(arr) / len(arr) 기억할 것 len() 은 마지막 인덱스가 아니라 원소 개수 를 반환한다. 6. / , // , % 질문 평균을 버림 처리하려면? 핵심 7 / 3 # 2.333... 7 // 3 # 2 7 % 3 # 1 기억할 것 / : 일반 나눗셈 // : 몫 % : 나머지 7. f-string 소수점 출력 질문 :.0f 는 버림일까? 핵심 아니다. :.0f 는 반올림해서 소수점 0자리까지 출력 한다. x = 3.8 print(f'{x:.0f}') # 4 print(f'{x:.1f}') # 3.8 기억할 것 출력 자릿수 지정과 버림은 다르다. 8. sep 과 end 질문 print() 에서 값 사이의 공백을 없애려면? 핵심 print(a, b, sep='') sep 은 값 사이 , end 는 출력 마지막 을 설정한다. print('A', 'B', sep='') # AB print('A', end='') print('B') # AB 기억할 것 sep : 출력값 사이 end : 출력 마지막 가장 중요하게 복습할 코드 arr = list(map(int, input().split())) 이 코드는 반드시 각 단계를 설명할 수 있어야 한다. input() → 문자열 입력 split() → 문자열 분리 map(int, ...) → 각 값을 정수로 변환 list(...) → 리스트로 변환 Python 기초에서는 우선 입력 → 자료형 변환 → 리스트 저장 → 계산 → 출력 흐름에 익숙해지는 것이 중요하다.