본문 바로가기

전체 글

(42)
병원 페이지 seo 자산화 스키마와 SSR 구조 개선으로 실제 검색 성과 의료 플랫폼에서 SEO작업 한다고 하면 메타 태그 수정이나 키워드 삽입 정도를 떠올리기 쉽다그러나 실제 검색 성과를 만들기 위해서는 페이지 구조 렌더링 방식 URL 설계 구조화 데이터까지 함께 고려한 경험을 정리한다.SEO 관점에서 구조를 개선하고 실제 검색 성과로 이어진 사례를 정리한다 문제 상황은 콘텐츠는 있었지만 검색엔진에는 보이지 않는 구조였다 기존 페이지는 CSR 기반으로 구성되어 있었다병원 목록 페이지는 자바스크립트 실행 이후에만 콘텐츠가 렌더링되었고지역명과 진료과목 조합에 대응하는 개별 URL 구조가 존재하지 않았다 이로 인해 Googlebot이 HTML 기준으로 의미 있는 콘텐츠를 인식하기 어려웠다구조화 데이터가 존재는 했지만schema.org..
next.js parallel routes 회사에서 메인프로젝트를 page router -> app router로 마이그레이션하면서 next의 여러가지 기능을 쓸 수 있게 되었다. parallel routes는 처음 접해보는 기능이었기에 글을 쓰게 되었다.Next.js 패러럴 라우팅으로 헤더와 푸터를 관리한 경험회사에서 PC 웹용 헤더와 푸터를 공통 컴포넌트로 만들고 있었다. 문제는 “공통”이라는 말과 다르게, 실제 요구사항은 전혀 공통적이지 않았다는 점이다. 페이지마다 헤더와 푸터가 조금씩 달랐다.어떤 페이지는 검색창이 있는 헤더가 필요했고,어떤 페이지는 로고만 있는 단순한 헤더가 필요했다.처음에는 조건 분기로 해결하려 했지만, 곧 한계를 느꼈다. 이때 동료가 추천해준 방법이 Next.js의 패러럴 라우트이다.기존 방식의 문제점처음 접근은 전형..
OpenAPI Generator 프론트엔드 개발자가 회사에서 OpenAPI Generator를 처음 보고 놀랐던 이유회사에 입사한 뒤 가장 인상 깊었던 기술을 꼽으라면 단연 OpenAPI Generator였다. 이전에도 REST API 문서를 읽고 개발한 경험은 있었지만, 이 정도 수준으로 정돈된 문서를 기반으로 타입과 클라이언트 코드까지 자동으로 생성하는 방식은 처음이었다. 특히 프론트엔드 입장에서 API 스펙이 자동화된 형태로 제공된다는 경험은 꽤 충격적이었다.프론트엔드가 백엔드에게 가장 자주 묻는 질문들프론트엔드 개발을 하다 보면 자연스럽게 API 타입에 대한 질문이 반복된다.응답이 null로 오는 것과 빈 문자열로 오는 건 어떤 차이인가쿼리 파라미터에 빈 문자열을 보내도 되는가어떤 필드가 optional인지, required인지..
GraphQL과 REST 그동안은 REST API를 주로 사용했지만, 회사에서는 GraphQL을 사용하고 있었.처음에는 단순히 “필요한 데이터만 가져올 수 있는 쿼리 언어” 정도로 생각했지만, 실제로 사용해보니 REST와는 확실히 달랐다.이 글에서는 프론트엔드 관점에서 GraphQL을 사용하면서 느낀 차이점과 장점을 정리했다.1. 필요한 데이터만 가져올 수 있다REST API를 사용할 때 가장 불편했던 점은 오버패칭(Over-fetching) 과 언더패칭(Under-fetching) 문제였다.원하는 데이터를 얻기 위해 불필요한 필드까지 받아야 하거나,반대로 여러 API를 조합해야만 필요한 정보를 완성할 수 있었다.GraphQL을 사용하자 이 문제가 깔끔하게 해결되었다.필요한 필드만 쿼리로 지정하면 그에 맞는 데이터만 반환되기 때..
낙관적 업데이트(Optimistic Update) 문제: 한 줄만 바꾸고 싶은데, 테이블이 다 깜빡였다업무 중 포인트 테이블이 있었는데, 포인트를 충전을 하면전체 리스트를 다시 받아와야 했다.그래서 API 요청 후 refetch()를 돌리면 테이블 전체가 리렌더링되었고,성능은 둘째 치고, 그 순간 페이지가 깜빡거리고 스크롤이 초기화되는 문제가 있었다.낙관적 업데이트로 해결한마디로 정리하면“서버 응답을 기다리지 말고, 프론트에서 먼저 성공했다고 가정하자.”const queryClient = useQueryClient();const mutation = useMutation({ mutationFn: approveUser, onMutate: async (id: string) => { await queryClient.cancelQueries(['user..
플라이웨이트 & 발행-구독 패턴 핵심: 연관된 객체끼리 데이터를 공유하여 애플리케이션 메모리 최소화. 캐시 개념을 코드로 패턴화이를 재사용한 객체 인스턴스를 공유시킴 Flyweight : 경량 객체를 묶는 인터페이스ConcreteFlyweight : 공유 가능하여 재사용되는 객체 (intrinsic state), flIweight의 하위클래스UnsharedConcreteFlyweight : 공유 불가능한 객체 (extrinsic state), flIweight의 하위클래스FlyweightFactory : Flyweight 객체 관리 클래스. 경량 객체를 만드는 공장 역할 &캐시 역할-GetFlyweight() 메서드는 팩토리 메서드 역할만일 객체가 메모리에 존재하면 그대로 가져와 반환하고, 없다면 새로 생성해 반환한다Client : 클..
자바스크립트 기초 - 프로그래밍 시작하기 자바스크립트2015년 이후 매우 발전(ES6)하였다.console.log로 출력 가능.console.log(1+5)console.log("6")줄은 세미콜론으로 구분해주자.사실 상황에 따라 자동으로 추가해주기도 하지만 반드시 사용하는게 편하다.//, /**/은 주석처리.Data type 자료형intString - 더하기 기호로 문자열 연결 가능BooleanfloatNumber추상화abstraction목적을 명확히, 불필요한 것은 숨기고 핵심만변수(값에 이름을 부여):변수를 활용해서 코드를 추상화let espressPrice;expressoPrice = 3000;//할당let espressPrice= 3000;//선언과 동시에 초기화//할당과 초기화는 다르다. 할당은 여러번 가능.//초기화는 맨 처음 한 ..
6. 그래프, 그래프 탐색 - 그래프- DFS- BFS 정점(vertex):그래프를 구성하는 개체(점)=노드간선(edge): 정점과 정점을 연결하는 선그래프(gragh): 정점과 간선으로 구성된 자료구조방향그래프(directed graph): 간선에 방향이 있는 그래프   cf. 양방향 그래프(undirected graph). 그냥 그래프와 같다.차수(degree): 정점에 연결된 간선의 수방향 그래프에서는 정점으로 들어오는 간선과 나가는 간선을 indgree, outdegree로 구분.경로(path): 정점을 중복해서 지나지 않는 간선의 나열사이클: 시작 정점과 끝 정점이 같은 경로방향 그래프에서 사이클을 판단할 때는 방향을 고려해야한다.순환 그래프(cyclic graph)비순환 그래프(acyclic graph) 그래프는 두 정..