본문 바로가기

전체 글134

최적화 기법 useRef, useCallback 1. useRef- useRef를 단순히 DOM 요소를 잡는 용도로만 알고 있다면, 30%만 알고 있는 것이다.- useRef의 본질은 컴포넌트가 다시 렌더링 되어도 절대 사라지지 않는 나만의 '기억상자'라는 것이다. 이 상자의 내용물 ( .current)는 바뀐다고 해서 컴포넌트가 다시 렌더링 되지도 않는다. 이 때문에 3가지 활용법이 파생된다. 활용법 1 : DOM 참조용, 가장 기본적인 사용법const playerRef = useRef(null);- playerRef라는 기억 상자에 라는 DOM 요소 또는 컴포넌트를 담아달라고 리액트에게 부탁하는 것. - 왜 쓰는가? 리액트의 상태관리 시스템을 통하지 않고, 특정 DOM 요소에게 직접 명령을 내리고 싶을 때 사용한다. 예를 들어 playerRef... 2025. 6. 30.
Grid & clamp 먼저 CSS GRID를 보고가자 grid의 기본구조// 가장 기본적인 gridcss={css` display : grid; grid-template-columns : 1fr 1fr 1fr; // 3개열 같은 크기 grid-template-rows : 100px 200px; // 2개 행, 다른 크기 gap : 20px; // 간격`}그리드 용어- grid container : display grid가 적용된 부모요소- grid item : grid container 안의 직접 자식 요소들- grid line : 격자를 구성하는 선들- grid track : 행 또는 열- grid cell : 한칸- grid area : 여러 셀을 합친 영역 fr 단위css={css` grid-templa.. 2025. 6. 30.
Record와 상태관리에서의 Record 활용 패턴들 Record의 고급활용법먼저 Record란 무엇인가- 객체의 타입을 정의하는 타입스크립트 유틸리티 타입- 키와 값의 타입을 명시적으로 지정- 일반 객체보다 더 엄격하고 안전한 타입체크// Record의 기본형태Record// 실제 예시Record // 키는 string, 값은 number인 객체Record // 키는 'a','b' 중 하나 값은 boolean 일반객체 vs Record// 일반객체 - 타입 안전성 부족const normalObject : { [key:string] : any } = { name : '김철수', age : 30, city : '서울'};// 이런 실수가 가능하다.normalObject.agee = 31; // 오타를 했는데도 에러가 나지 않는다.normalObj.. 2025. 6. 30.
리액트, css 유즈케이스 이것저것 가로 크기에 따라서 반응형으로 나열하려면1. repeat(auto-fill, minmax(350px, 1fr)) - auto-fill : 가능한 많은 열을 자동으로 생성한다.- minmax(350px, 1fr) : 최소 350px, 최대 1fr (남은 공간을 자동분배한다 )- 결과 : 화면 폭에 따라서 자동으로 열 개수를 조정한다. 카드나 어떤 요소에 호버 줄 때css={css` transition : all 0.2s ease; &:hover{ transform : translateY(-2px); box-shadow : 0 4px 16px rgba (0,0,0,0.08); }`} 검색/필터링 디바운스 구현useEffect(()=>{ const debounceT.. 2025. 6. 27.
왜 api 베이스에 서버 IP주소를 그대로 넣으면 안되는가 왜 리액트에서 서버 연결 정보 넣을 때 ip 주소를 바로 넣으면 안될까? [ 보안의 측면에서 ]가장 큰 문제는 내부 시스템 정보노출이다.1. 누구나 볼 수 있다. - React 코드는 최종적으로 사용자의 웹 브라우저에서 실행된다. 악의적인 사용자를 포함한 그 누구라도 브라우저의 개발자 도구를 열어서 네트워크 요청이나, js 소스코드를 살펴보는 것만으로 서버 b의 내부 ip주소와 포트주소를 알아낼 수 있다. 2. 공격자에게 지도를 주는 셈이다.- 공격자는 이제 우리 시스템이 최소한 서버 a( 웹서버 ) 서버b ( api 서버 ) 라는 두개의 서버로 구성되어 있다는 내부 구조를 알게 된다.- 더 중요한 것은, 공격 대상이 될 수 있는 서버 b의 정확한 주소를 확보하게 된다.- 만약 다른 경로 ( 피싱, 내부.. 2025. 6. 27.
아파치 리버스 프록시 설정 + 정규표현식 전에 있던 배포 문제 때문에 리버스 프록시 설정을 고려하게 되는데, 이 경우 중요한 제약사항이 있다. - 서버 전체의 수정을 할 수 없다.- 많은 서비스가 돌아가기 때문에 서버를 껐다 킬 수 없다.- 서버 전체의 설정을 건드리지 않고, 배포 단위 ( 폴더 ) 로만 설정하고 싶다. 그러면 어떻게 해야하는가? 서버의 메인설정파일인 httpd.conf를 직접 수정하는 대신에, .htaccess 파일을 사용하여 디렉토리 ( 폴더 ) 레벨에서 설정을 적용할 수 있다. .htaccess 파일의 내용은 서버를 재시작하지 않아도 즉시 반영된다.다만 ProxyPass 지시어는 보안상의 이유로 .htaccess 파일 내에서 사용하는 것이 기본적으로 허용되지 않는다. 따라서 다른 대안을 사용해야하는데, 아파치의 강력한 기.. 2025. 6. 27.
서비스 배포 케이스1 서버 A ( 사내에만, 다만 VPN 통해서 접속가능 ), 프론트엔드 여기에 올림서버 B ( 사내에만 ), API 여기에 올림 가장 중요한 포인트는 리액트 프론트엔드 코드는 사용자의 웹 브라우저에서 실행된다는 것이다. 1. VPN 사용자의 접속 흐름- VPN 사용자가 서버A의 주소로 접속한다.- 서버A의 아파치 서버는 리액트로 빌드된 정적파일을 사용자에게 전송한다.- 사용자의 웹 브라우저가 이 파일들을 다운로드하여 실행한다. 2. API 통신시도- 이제 사용자의 브라우저에서 실행된 리액트 앱이 데이터를 가져오기 위해서 API를 호출한다.- 이 API의 주소는 서버 B의 IP와 포트로 설정되어있다.- 여기서 문제가 발생한다. API를 호출하는 주체는 서버A가 아니라 VPN에 접속한 사용자의 PC ( 웹 브라.. 2025. 6. 27.
MERGE 구문 MERGE dbo.e_uservideoprogress AS targetUSING (SELECT @employeeid AS employeeid, @videoid AS videoid) AS sourceON (target.employeeid = source.employeeid AND target.videoid = source.videoid) WHEN MATCHED THEN UPDATE SET watchedtime = @watchedtime, iscompleted = @iscompleted, lastwatchedat = @lastwatchedat WHEN NOT MATCHED THEN INSERT (employeei.. 2025. 6. 26.
실제 유즈케이스 hono 1. 먼저 DB 연결과 쿼리 실행 헬퍼 함수를 정의한다.import * as sql from "mssql";// Bun은 기본적으로 process.env를 지원합니다const config: sql.config = { user: process.env.USER || "your_username", password: process.env.PASSWORD || "your_password", server: process.env.SERVER || "localhost", database: process.env.DATABASE || "your_database", options: { encrypt: false, // Azure SQL Database의 경우 trustServerCertificate: f.. 2025. 6. 24.
실제 유즈케이스 1. 어떤 한 페이지 ( 단일 컴포넌트나 몇개의 컴포넌트 ) 에서 state로 사용할 것은위에 interface를 정의한다. 예를 들어서 이렇게interface Course { id: number; title: string; description: string; status: "completed" | "in-progress" | "not-started" | "required"; progress: number; duration: string; dueDate?: string;}const CourseLists: React.FC = () => { const navigate = useNavigate(); const [courses, setCourses] = useState(mockCourses);.. 2025. 6. 24.