
사실 대부분 포트폴리오는 피그마나 캔바를 써서 pdf로 만드시는 것 같은데
뭔가 홈페이지로 만드는 게 좀 더 개발자 느낌 날 것 같아서 홈페이지로 만들어봤다. 뭐 PDF로 제출하라는 곳들도 있는데 웹사이트 PDF로 바꿔주는 툴들도 있으니 그런걸 쓰면 될 것 같고
나만무 때 익숙해진 Next.js + TailwindCSS를 사용했는데, 내가 밑바닥부터 만들지는 않았고 인터넷에 돌아다니는 블로그 템플릿을 썼다.
이런 깃허브 템플릿이 있길래 썼다. 여러분도 튜토리얼만 잘 읽으면 따라 쓰실 수 있음
호스팅은 GitHub Pages로 했다. 무료에다가, GitHub Actions랑 연동하면 푸시하면 자동으로 빌드하고 배포해주는게 편하다.

메인페이지는 아직 조촐한데 시간 나면 좀더 꾸밀 생각이다. 일단은 이력서랑 포트폴리오에 더 집중해야 되니까...

포트폴리오에는 정글에서 한 프로젝트 3개 (핀토스, 나만무 준비주차 때 한 클론코딩, 나만무 최종프로젝트)랑 학교에서 코딩 깔짝하면서 만든 프로젝트 2개를 넣었다.
아 그리고 컬러는 내가 좋아하는 핑크로 골랐다.


각 프로젝트별 페이지는, 마크다운 파일만 업로드하면 자동으로 사이트에 올라가는 방식이다. 나름 웹페이지의 장점을 활용하려고 해서 나만무 발표영상도 첨부했고, 5년전에 만든 게임은 직접 해 보실 수도 있다.

근데 아직 포트폴리오 세부내용을 완전히 적지는 못했다. 일단은 방대한 코드를 다시 읽으면서 기술적 챌린지를 판단하는 건 무리수인 것 같아서... 클로드 코드한테 이력서 내용 + 실제 코드 내용 보고 간단히나마 정리해달라고 했다. 내일 참고해서 새롭게 다시 쓰고, 사진도 추가하고 해야겠다.

이력서 페이지도 있는데, 이력서는 얼추 작성은 했지만 웹페이지에는 ㄹㅇ Ctrl+C Ctrl+V만 해 둬서 아직 CSS를 많이 입히진 못했다. 나중에 좀 더 예쁘게 다듬을 생각이다.
기본적으로 JavaScript는 여러 개의 작업을 순서대로, 한 번에 한 개씩 처리한다. (동기)
function taskA() {
console.log("나는 야옹입니다");
}
console.log("당신은 누구십니까");
taskA();
console.log("아하 그렇군요");
/* 출력 결과
// 당신은 누구십니까
// 나는 야옹입니다
// 아하 그렇군요
*/
다만 이런 동기 처리의 경우, 중간의 한 작업의 시간이 길어지면 전체 프로그램의 실행 속도도 느려지는 문제가 있다.
예를 들어, 지금 이 코드의 taskA가 만약 1분 소요되는 작업이였다면, 1분이 지날때까지 console.log("아하 그렇군요")가 출력되지 못한다.
특히 네트워크 요청(API라든지...), 파일 읽기 같이 오래 걸리는 작업일 때 애로사항이 많아진다.
이렇게 도중에 시간이 오래 걸리는 작업이 있는 경우, 비동기 처리하여 다음 코드를 우선 실행 할 수 있다.
비동기란 작업을 백그라운드에서 처리하면서, 다른 작업을 먼저 실행할 수 있는 방식이다.
즉 비동기를 잘 활용하면, 네트워크 요청이나 파일 읽기 등 작업이 이루어지는 동안 전체 프로그램이 멈추는 것을 방지할 수 있다.
console.log("약속장소에 도착했다");
// setTimeout(): 비동기 함수, 일정 시간이 지난 후에 콜백함수를 실행
setTimeout(() => {
console.log("늦어서 미안해!");
}, 3000);
// 3초(3000ms) 타이머만 실행 후 다음 라인으로 넘어감, 기다리지 않음
console.log("얜 왜이렇게 늦게 와?");
/* 출력 결과
// 약속장소에 도착했다 (즉시)
// 얜 왜이렇게 늦게 와? (즉시)
// 늦어서 미안해! (3초 후)
*/
위 코드의 setTimeout은 비동기 함수로, 콜백함수랑 시간(ms)을 인자로 받는다. 우선 인자로 받은 시간만큼 타이머를 실행한 후, 바로 다음 라인으로 넘어간다. 이후 시간이 경과하면 콜백함수가 실행된다.
console.log("데이터 요청 시작");
fetch("https://api.example.com/users")
.then((response) => response.json())
.then((data) => {
console.log("데이터 받음:", data);
});
console.log("다른 작업 실행 중...");
/* 출력 결과
// 데이터 요청 시작
// 다른 작업 실행 중...
// 데이터 받음: [사용자 데이터...] (API 응답 후 출력)
*/
실제로는 setTimeout 대신 fetch와 같은 API 요청 함수가 중간에 들어가는 경우가 많은데, 이러한 함수를 비동기 처리하면, 처리가 완료될 때까지 이후의 라인을 우선 실행할 수 있다는 소리다.
물론 fetch에다가 콜백 함수를 넣어, API 요청이 완료된 후 후속 작업을 지정하는 것도 가능하다.
C#, Java 같은 언어는 멀티쓰레드를 통해 비동기 처리를 실행한다. 쓰레드는 프로그램이 작업을 실행하는 흐름의 단위인데, 이런 언어들론 병렬로 여러 작업을 실행할 수 있다....정도로 이해하면 된다.
하지만 애석하게도 JavaScript 엔진은 싱글쓰레드다. 한 번에 하나의 작업만 처리할 수 있다는 뜻이다. 그런데도 이런 비동기 처리가 가능하다. 왤까?
이는 비동기 작업은 JavaScript 엔진이 아닌, Web API(브라우저가 제공하는 별도 공간이라고만 알아두기)에서 실행되기 때문이다.
클로드 형님께서 그려준 아래 그림을 보고 이해해보자.
JS ENGINE (Call Stack) WEB APIs Callback Queue
┌─────────────────────────┐ ┌──────────────────┐ ┌─────────────────┐
│ │ │ │ │ │
│ 1️⃣ console.log() │ │ │ │ │
│ "약속장소에..." │ │ │ │ │
│ ✓ 실행 완료 │ │ │ │ │
│ │ │ │ │ │
│ 2️⃣ setTimeout() │───▶│ Timer 시작 │ │ │
│ ✓ Web API에 위임 │ │ (3000ms) │ │ │
│ ✓ 즉시 다음으로 │ │ ⏱️ 카운트다운 │ │ │
│ │ │ │ │ │
│ 3️⃣ console.log() │ │ ⏱️ 카운트다운 │ │ │
│ "얜 왜이렇게..." │ │ │ │ │
│ ✓ 실행 완료 │ │ ⏱️ 카운트다운 │ │ │
│ │ │ │ │ │
│ [비어있음] │ │ ✓ 3초 완료! │───▶│ () => {...} │
│ 대기 중... │ │ │ │ 콜백 대기 중 │
│ │ │ │ │ │
│ │ │ │ │ │
│ 4️⃣ () => console.log() │◀───────────────────────────│ 콜백 전달 │
│ "늦어서 미안해!" │ │ │ │ │
│ ✓ 실행! │ │ │ │ [비어있음] │
│ │ │ │ │ │
└─────────────────────────┘ └──────────────────┘ └─────────────────┘
▲ │
│ │
└──────────────────────────────────────────────────────┘
Event Loop (계속 감시)
"Call Stack 비었어? 그럼 Queue에서 가져올게!"
일반적인 동기 함수(e.g., console.log())는 자바스크립트 엔진의 콜 스택에서 실행된다.
하지만 setTimeout()같은 비동기 함수를 만나면, 이러한 절차가 이루어진다.
자바스크립트 엔진은 비동기 작업을 Web API에 맡긴다. 이와 동시에 setTimeout() 종료 후 실행될 콜백 함수도 전달한다.
Web API가 3초 타이머를 실행한다.
3.setTimeout()의 3초 타이머가 종료되면, WEB API가 콜백 함수를 콜백 큐에 추가한다.
다만 비동기 함수 때 콜백 함수를 사용할 땐 애로사항이 많다.
이를테면, 비동기 작업이 끝나고 다른 비동기 작업을 연달아 실행하는 경우가 있다고 하자.
그러면 콜백 함수 자리에 다른 비동기 함수를 넣어 줘야 하는데, 이러한 작업이 많아질수록 코드가 복잡해진다.
실제로 이런 코드를 적을 일은 없지만, 1초 간격으로 음식을 먹었다고 출력하는 코드를 짰다고 가정해 보자.
// 콜백 함수
function eatMandu(callback) {
setTimeout(() => {
const ateMandu = "만두도 먹고";
callback(ateMandu);
}, 1000);
}
function eatPizza(food, callback) {
setTimeout(() => {
const atePizza = `${food} 피자도 먹고`;
callback(atePizza);
}, 1000);
}
function eatJjajang(food, callback) {
setTimeout(() => {
const ateJjajang = `${food} 짜장면도 먹고`;
callback(ateJjajang);
}, 1000);
}
// 비동기 작업의 결과를 다른 비동기 작업의 인수로 활용할 수 있음
// 보다시피 복잡함 - 콜백 지옥 우려
eatMandu((ateMandu) => {
console.log(ateMandu);
eatPizza(ateMandu, (atePizza) => {
console.log(atePizza);
eatJjajang(atePizza, (ateJjajang) => {
console.log(ateJjajang);
});
});
});
// 출력결과
// 만두도 먹고 (1초 후 출력)
// 만두도 먹고 피자도 먹고 (2초 후 출력)
// 만두도 먹고 피자도 먹고 짜장면도 먹고 (3초 후 출력)
보시다시피 비동기작업이 3번 연달아 일어나니 코드가 복잡해지는 것을 볼 수 있다.
이러한 현상을 콜백 지옥이라 하는데, Promise나 async/await라는 친구로 해결할 수 있다. 거기서부턴 내일 정리할게용~
오 꿀팁이다
개꿀탬 하나 얻어갑니덩