SvelteKit과 AWS Lambda로 만든 개인 포트폴리오 사이트

몇 년에 한 번씩 찾아오는 이벤트가 있다.

포트폴리오 사이트 리뉴얼이다.

사실 포트폴리오 사이트를 만든 게 이번이 처음은 아니다. 4년 전쯤 cheesu.com 도메인으로 자기소개 겸 포트폴리오 사이트를 만들어 운영했었다. 그때도 Svelte를 사용했고, 꽤 만족하면서 썼던 기억이 있다.

하지만 시간이 지나면서 내용도 많이 오래됐다. 그 사이에 회사에서 했던 일도 바뀌었고, AI 관련 프로젝트나 자동화 경험도 꽤 쌓였다. 마침 이직을 고민하는 시점이기도 해서, 지금까지의 작업물을 다시 정리해보기로 했다.

이번에 새로 만든 사이트는 아래다.

https://cheesu.co.kr

이번에는 “이력서의 증거”를 모으고 싶었다

이번 포트폴리오 사이트를 만들면서 가장 중요하게 생각한 건 화려한 디자인이 아니었다.

물론 보기 좋은 것도 중요하지만, 그보다 먼저 “이 사람이 어떤 개발자인지 빠르게 파악할 수 있는가?”를 더 신경 썼다.

이력서에는 보통 몇 줄로만 적히는 내용들이 있다.

예를 들면 이런 것들이다.

  • AI API 비용 절감
  • 실시간 처리 개선
  • 의료영상 프로젝트 경험
  • 사내 자동화 구축 경험
  • Text2SQL, LLM 활용 경험

문제는 이런 문장만으로는 실제로 뭘 했는지 전달하기가 어렵다는 점이다.

그래서 이번 사이트는 단순한 자기소개 페이지라기보다는, 이력서에 적힌 내용을 확인할 수 있는 허브처럼 만들고 싶었다. 프로젝트 설명, 발표 자료, GitHub 저장소, 데모 페이지 등을 한곳에서 접근할 수 있게 구성했다.

누군가 이력서를 보고 “이건 정확히 뭘 했다는 거지?”라는 생각이 들었을 때, 바로 확인할 수 있는 공간이 있으면 좋겠다고 생각했다.

 

 

React 대신 다시 SvelteKit을 선택한 이유

현재 회사에서는 React를 사용하고 있다. 앞으로도 React를 사용할 일은 많을 것 같다.

그런데 개인 프로젝트를 할 때는 일부러 다른 선택지도 써보는 편이다. 4년 전 포트폴리오 사이트를 만들 때도 Svelte를 사용했고, 이번에도 자연스럽게 SvelteKit을 선택했다.

가장 큰 이유는 코드가 간결하다는 점이다.

같은 기능을 구현해도 React보다 적은 코드로 끝나는 경우가 많다. 포트폴리오 사이트처럼 화면 중심의 프로젝트에서는 이 장점이 꽤 크게 느껴진다.

그리고 요즘은 AI를 활용해서 개발하는 일이 많아졌다. Claude Code 같은 에이전트를 사용하다 보면, 결국 모델이 읽고 생성해야 하는 코드의 양도 비용과 생산성에 영향을 준다.

정확히 토큰 비용을 비교한 건 아니지만, 같은 기능을 더 적은 코드로 표현할 수 있다면 AI와 함께 개발할 때도 유리한 면이 있다고 느꼈다.

이번 프로젝트는 복잡한 서비스도 아니었다. 거대한 상태 관리나 React 생태계의 다양한 라이브러리가 필요한 규모는 아니었다. 포트폴리오 사이트 정도라면 SvelteKit이 더 가볍고 잘 맞는 선택이라고 판단했다.

결과적으로 번들 크기, 빌드 속도, 개발 경험 모두 만족스러웠다.

이번에는 EC2 대신 Lambda를 썼다

이번 프로젝트에서 예전과 가장 달라진 부분은 인프라다.

이전 포트폴리오 사이트는 EC2 기반으로 운영했다. 당시에는 AWS를 공부하는 목적도 있어서 이것저것 직접 구성해봤다.

  • EC2
  • ALB
  • Route53
  • HTTPS 인증서
  • 도메인 연결

서비스 운영 관점에서는 좋은 경험이었다. 문제는 비용이었다.

포트폴리오 사이트 특성상 방문자가 많지 않다. 평소에는 접속자가 거의 없고, 누군가 이력서를 보고 들어오는 정도가 대부분이다.

그런데 EC2는 방문자가 없어도 24시간 켜져 있어야 한다. ALB까지 붙어 있으면 비용도 생각보다 나온다.

어느 순간 “이 정도 트래픽에 이 비용을 계속 내는 게 맞나?”라는 생각이 들었고, 결국 예전 사이트는 중지했다.

그래서 이번에는 서버리스 방식으로 바꿨다.

현재 구성은 대략 이렇다.

  • S3 + CloudFront
  • AWS Lambda + API Gateway
  • Route53
  • ACM
  • Terraform
  • GitHub Actions + OIDC

정적 페이지는 S3와 CloudFront로 제공하고, 필요한 API는 Lambda와 API Gateway로 처리한다.

포트폴리오 사이트처럼 트래픽이 많지 않은 개인 프로젝트라면 Lambda는 거의 무료에 가깝게 운영할 수 있다. 서버를 계속 켜둘 필요가 없다는 점도 마음에 들었다.

이번에는 인프라를 Terraform으로 관리하고, 배포는 GitHub Actions와 OIDC를 사용해서 구성했다. 예전보다 훨씬 깔끔하게 관리되는 느낌이다.

개발보다 기다리는 시간이 더 길었다

사이트 자체는 거의 2일 정도 만에 만들었다.

예전 같으면 디자인 잡고, 레이아웃 만들고, 콘텐츠 정리하고, 배포 환경 구성하는 데 훨씬 오래 걸렸을 것 같다. 그런데 요즘은 AI 덕분에 구현 속도가 확실히 빨라졌다.

오히려 개발보다 기다리는 시간이 더 길게 느껴졌다.

도메인을 등록하고 네임서버가 전파되기를 기다리는 시간, ACM 인증서가 발급되기를 기다리는 시간, CloudFront 캐시가 반영되기를 기다리는 시간 같은 것들이다.

디자인도 이번에는 Claude의 도움을 많이 받았다.

4년 전에 ChatGPT를 활용해서 만들었던 사이트도 당시에는 만족스러웠지만, 이번에는 Claude가 만들어준 디자인 시안이 개인적으로 더 마음에 들었다. 확실히 AI를 활용한 프론트엔드 작업의 품질이 예전보다 많이 좋아졌다는 생각이 들었다.

Text2SQL 데모도 넣었다

이번 사이트에서 가장 보여주고 싶었던 기능 중 하나는 Text2SQL 데모였다.

요즘 AI 관련 작업을 많이 하고 있지만, 이력서에 “LLM 활용 경험 있음”이라고 적는 것만으로는 부족하다고 느꼈다. 그래서 직접 실행해볼 수 있는 데모를 넣었다.

현재는 Gemini의 저가 모델을 사용하고 있다. 비용을 고려해서 선택한 모델이라 응답 속도가 아주 빠르지는 않다.

그래도 자연어를 SQL로 변환하는 흐름은 실제로 동작한다.

완성도 높은 제품이라기보다는, 내가 어떤 문제에 관심이 있고 어떤 방식으로 AI를 활용해보고 있는지 보여주는 데모에 가깝다.

아직 끝난 프로젝트는 아니다

사이트는 일단 공개했지만, 아직 끝난 프로젝트는 아니다.

현재 가장 아쉬운 부분은 검색 엔진 노출이다. Google Search Console과 네이버 서치어드바이저 등록은 끝냈지만, 새 도메인이다 보니 아직 색인이 충분히 진행되지는 않았다.

최근에는 SEO뿐 아니라 AI 검색에 더 잘 노출되는 구조도 조금씩 실험해보고 있다. 다만 외부 언급이 거의 없는 신생 사이트라 어느 정도 시간은 필요할 것 같다.

예전 포트폴리오 사이트가 “자기소개 사이트”에 가까웠다면, 이번 사이트는 지금까지 했던 일과 관심 있는 기술을 한곳에 모아둔 허브에 가깝다.

이직 준비를 계기로 시작했지만, 결과적으로는 지난 몇 년 동안의 작업물을 정리하는 과정이 되었다.

앞으로도 프로젝트가 추가되거나 새로 실험한 내용이 생기면 계속 업데이트해볼 생각이다.

https://cheesu.co.kr

[NODE,NEST] SERVICE_KEY_IS_NOT_REGISTERED_ERROR 해결

 

요즘 node랑 nest 공부 하면서 간단히 이것저것 만들어 보고 있다가.

공공데이터 포탈에서 어떤 API를 가져오려고 작업을 했었다.

그런데 간헐적으로 SERVICE_KEY_IS_NOT_REGISTERED_ERROR  에러가 자꾸 발생을 하는 

현상을 발견했다.

<cmmMsgHeader>
    <errMsg>SERVICE ERROR</errMsg>
    <returnAuthMsg>SERVICE_KEY_IS_NOT_REGISTERED_ERROR</returnAuthMsg>
    <returnReasonCode>30</returnReasonCode>
</cmmMsgHeader>

 

이런 오류가 자꾸 떨어지는데 

분명 포스트맨에서 테스트 할때는 쭉 정상으로 작동을 했는데 

node서버에서 돌릴땐 어떨땐 정상으로 받아오고 어떨땐 저 에러가 발생을 하는 현상이 있어

이것저것 해봤는데 결국은 인코딩 문제였다. 

왜 간헐적으로 정상응답과 오류응답이 나타나는건지 몰라 한참을 해매다가

그냥 차라리 인코딩을 하지 말고 보내 보자 하고 해보니 저 에러가 나타나지 않고 정상작동 하는것을 확인 했다.

 

// firstValueFrom 함수를 사용하여 Observable을 Promise로 변환
      const response = await firstValueFrom(
        this.httpService.get(
          {
            params: queryParams,
            responseType: 'text', // XML 응답을 처리하기 위해 responseType을 'text'로 설정
          },
        ),
      );

이런식으로 요청을 보내고 있었는데 

확인해보니 

 

HttpService (Axios 기반)를 사용할 때, URL 파라미터는 자동으로 인코딩이 된다고 한다.

Axios는 내부적으로 encodeURIComponent 함수를 사용하여 URL 파라미터의 항목들을 인코딩하기 때문에,

별도로 인코딩 처리를 하지 않아도 된다고 한다.

기존에는 당연히 인코딩해서 보내줘야지 하고 parmas에 보내는 값중 키값을

const encodedApiKey = encodeURIComponent(serviceKey); // API 키 인코딩

이렇게 사용하고 있었는데 

자동으로 인코딩이 한번 더 되버리니 키값에 문제가 생긴것인다.

저 인코딩 해주는 부분을 빼고 디코드 키를 바로 사용하면 해결이 된다.

그럼 그냥 전부 다 오류응답으로 나와야 하는데 왜 되다 안되다 하는것인지는 모르겠다;;;

 

 

Cannot find module 'msw/node' 에러 해결

 

NEXT.js 14버전 환경에서 jest를 사용한 테스트 환경 구축중에 

api요청등의 문제를 모킹서버로 해결하기 위해 

msw설치후 테스트를 돌렸는데 

 

msw/node 를 찾지 못한다는 에러가 발생을 하였다.

분명 패키지제이슨엔 설치가 되어 있는데도 오류가 발생하고 있어 

chatGpt에 물어봐도 다시 설치하라는 말만 하고 있어 다른 방법을 찾아 보던중

 

https://github.com/mswjs/msw/issues/1786

 

"Cannot find module 'msw/node'" in Jest JSDOM environment · Issue #1786 · mswjs/msw

Prerequisites I confirm my issue is not in the opened issues I confirm the Frequently Asked Questions didn't contain the answer to my issue Environment check I'm using the latest msw version I'm us...

github.com

이곳의 글을 확인 하였고 코멘트에서 해결방법을 찾았다.

 

jest.config.ts 파일의 설정중에 

testEnvironmentOptions: {
    customExportConditions: [""],
  },

이부분을 추가 하면 된다. 

에러가 난 이유를 설명한걸 해석해 보자면

 

JSDOM이 내보내기 조건을 강제하기 때문입니다 browser.

즉, JSDOM은 "타사 패키지가 browser필드를 내보내는 경우 해당 필드를 사용하십시오"라고 말합니다.

그것이 기본값이고 다소 위험한 기본값입니다. 왜? JSDOM은 여전히 ​​Node.js에서 실행되기 때문입니다 .

게다가 JSDOM은 설계상 100% 브라우저 호환성을 가질 수 없으므로 browser내보내기 조건을 강제하면

MSW와 같이 다양한 환경에 대해 다양한 코드를 제공하는 패키지로 작업할 때 테스트가 필요 이상으로 실패하게 됩니다.

이렇게(위와 같은 설정을) 하면 JSDOM이 올바른 동작인 node(또는 ) 내보내기 조건을 사용하게 됩니다 .default

이번 변경 이후 다른 수입 관련 문제가 발생하는 경우 관련이 없으므로 별도로 처리해야 합니다.

모든 사람이 따를 수 있도록 이 권장 사항을 마이그레이션 가이드에도 추가합니다.

 

라고 한다. 

+ Recent posts