반응형

서류전형 → 코딩/과제테스트 → 인적성검사 → 면접 → 트라이얼 위크(3주)

에 걸친 현대캐피탈의 지원 절차다.

자기소개서에서는

  1. 현대캐피탈에 지원하게 된 동기와 지원 직무에 필요한 역량을 기르기 위해 노력했던 경험을 기술해 주십시오.
  2. 실패에 대한 두려움을 극복하고 새로운 일에 도전하여 깨달음을 얻은 경험에 대해 기술해 주십시오.
  3. 가치관이 다른 구성원들과 협업했던 과정에서 본인의 역할은 무엇이었는지, 그 경험을 통해 어떤 역량이 향상되었는지 기술해 주십시오.

에 대해 물어봤다.

 

서류 합/불 없이 바로 코테에 들어가서 억울한 그런 기분을 가지며..

 


코딩 테스트

플랫폼 : 프로그래머스

문제수 : 알고리즘 4문항

시험 시간 : 2시간

화상감독 : O, 검색 불가, 외부 IDE 불가

응시 직무 : FE/BE

응시 가능 언어 : FE : Javascript, BE : Java

 

체감 난이도 2/5

백준 골드 찍기까지 C++ 만 썼는데 자바스크립트를 쓰라는 날벼락.. 함수들이 비슷하면서도 헷갈려서 머리가 어지러웠다. 비록 리액트나 Next.js 플젝을 몇번 해보긴 했어도 생 알고리즘 JS 는 생소한 기분.. 화이팅..

 

4문제 중 3솔

 

후기

구현 : 세문제 정도 구현문제였던 것 같다. 근데 한 문제는 배열 복사하는 함수를 까먹어서 중간에 풀지 못했다. ㅠㅠ

DFS : DFS 로 보이는 문제였는데 무난한 듯 보인다.

처음 보는 코테라 많은 테스트케이스를 시도해보지 못했다. 난이도는 쉬운 편이었고 좋은 경험이었다고 생각한다. 다음은 LG uplus 언제 준비하냐.. 예비군 가야하는데


결과

소요일 : 5일

예상했지만 역시 떨,,,,, 경험을 잘 쌓아 잘 나아가보자!

 

 

반응형
반응형

배경

계절학기에 들어가면서 1학점 짜리 웹 프로젝트 연구를 진행하게 되었다. 주제는 웹 보안을 위한 시큐어 코딩 학습 사이트다.

3주 동안 진행되는 계절학기 특성상 미리 준비하는게 정신건강에 좋기 때문에 미리 웹사이트를 구축해보기로 했다.

 

새로운 기술

우선, 평소에는 react, nodejs 로 웹을 구축했었는데 이번에는 nextjs 를 이용해 구축해보려고 한다. 새로운 기술에 대해 배우는고 공부하는데 도움이 될 것 같아 이렇게 진행하려고 한다.

 

취약점 조사

프로젝트에는 웹보안 하면 가장 기초가되는 4가지 공격을 제외한 공격을 다루라고 명시되어 있다. (sql injection, XSS, path traversal, desdrialization)

사실 내가 생각해도 위의 공격은 너무 소스도 많고 기본적인 문제들이라 날로 먹는 느낌이 들 것 같긴했다.

그렇기에 새로운 취약점을 찾아보았고, OWASP 에서 발표한 TOP10 취약점을 알게 되었다.

 

 

여기서 나는 1번 injection, 8번 CSRF 에 대해 진행해보려고 한다. injection 에도 file upload, os command 를 이용한 취약점에 집중하려고 한다.

 

웹 구현

 

next 프로젝트를 구축한 후 app 폴더의 트리 모습이다. layout.js 를 이용해 헤더와 네비게이션을 고정해놓고 page를 바꾸어가며 출력할 예정이다.

 

app
│ favicon.ico
│ globals.css
│ layout.js
│ page.js

├─components
│ Header.js
│ Nav.js

├─csrf
│ page.js

├─file
│ page.js

├─list
│ page.js

└─os

 

헤더와 네비게이션을 고정하기 위해 다음과 같은 코드를 작성했다.

 

layout.js

import Link from "next/link";
import "./globals.css";
import { Inter } from "next/font/google";
import Nav from "./components/Nav";
import Header from "./components/Header";

const inter = Inter({ subsets: ["latin"] });

export const metadata = {
  title: "Create Next App",
  description: "Generated by create next app",
};

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body className={inter.className}>
        <Header/>
        <Nav />
        {children}
      </body>
    </html>
  );
}

Header.js

'use client';
const { default: Link } = require("next/link");

const Header = () =>{
  const toggleDropdown = () => {
    setDropdownVisible(!isDropdownVisible);
  };
    return(
        <div className="header">
            <h3>Secure Coding Lecture</h3>
        </div>
    )
}

export default Header;

Nav.js

'use client';
import { useState } from "react";
const { default: Link } = require("next/link");

const Nav = () =>{
    const [isDropdownVisible, setDropdownVisible] = useState(false);

  const toggleDropdown = () => {
    setDropdownVisible(!isDropdownVisible);
  };
    return(
        <nav className="navbar">
          <ul className="navList">
            <li className="navItem">
              <Link href="/">홈</Link>
            </li>
            <li className="navItem">
              <div onClick={toggleDropdown}>강의
              {isDropdownVisible && (
                <ul className="subNavList">
                  <li className="navItem">
                    <Link href="/file">File Upload Attack</Link>
                  </li>
                  <li className="navItem">
                    <Link href="/os">OS Command Injection</Link>
                  </li>
                  <li className="navItem">
                    <Link href="/csrf">CSRF</Link>
                  </li>
                </ul>
              )}
              </div>
            </li>
            <li className="navItem">
              <Link href="/">설정</Link>
            </li>
          </ul>
        </nav>
    )
}

export default Nav;

위의 코드를 이용하면 다음과 같은 웹이 출력된다.

 

 

 

어려웠던점

  1. Layout.js 내에서 useState 사용불가
    • 이건 내가 next 에 대해 제대로 몰라 생겼던 문제다. next 는 기본적으로 서버 컴포넌트로 작동하는데 useState 는 클라이언트에서만 사용되기에 오류가 발생한다.
    • 따라서, use client 를 최상단에 적어 클라이언트 임을 선언하면 정상작동 된다.
반응형
반응형

저번편에는 API 연동 및 STT, TTS 를 사용해 gpt3.5 와 대화하는 것까지 구현을 진행했다.

하지만, 곰곰히 생각해보니 이 기능만으로는 부족하다는 생각이 들었고 추가 기능을 생각해보기로 했다.

추가 기능 구현

노인을 위한 이미지 편집 기능

보통 어르신들이 친구들과 카카오톡 대화를 할 때 카카오톡 이모티콘 만큼 자주 사용하는 사진들이 있다.

 

 

바로 요런 사진들!

나는 이미지를 Stable-diffusion 을 이용해 생성을 한 후 사용자가 원하는 글귀를 이미지에 삽입하는 기능을 구상했다.

위의 기능을 구현하기 위해 생각한 흐름을 한 번 보자면

 

알고리즘

  1. 이미지로 만들고 싶은 카테고리를 선택한다.
  2. 원하는 글귀를 선택한다.
  3. 이미지를 생성한다.
  4. 원하는 글귀를 이미지에 넣는다.

이미지생성

이미지 생성은 원래 로컬서버에 저장 후 사용하는 방식을 썼는데 그렇게하면 나중에 서버에 여러 이미지가 쌓여 넘칠게 뻔하기 때문에 API 를 이용해 보기로 했다.

async function query() {
        console.log("Send Query")
        setImageURL('');
        var data = { "inputs": props.inputValue,"use_cache":false }
        const response = await fetch(
            "<https://api-inference.huggingface.co/models/stabilityai/stable-diffusion-2-1>",
            {
                headers: { Authorization: "Bearer API_KEY" },
                method: "POST",
                body: JSON.stringify(data),
            }
        );
        var formData = new FormData();
        await response.blob().then((res)=>{
            formData.append('image',res);
            formData.append('textPrompt', props.textPrompt)
            
            axios.post("/api/imgEdit",formData).then((res) => {
                console.log("api img edit response", res.data);
                setImageURL(res.data.slice(2,-1))
                props.setLoading(false)  
              });
        })
    }

frontend 에서 이미지를 받아올 것이기 때문에 js 코드로 함수를 구현했다.

huggingface API 를 사용하면 이미지 데이터는 blob 형식으로 받게 된다. 해당 데이터를 서버로 보내 처리하기 위해서는 formdata 에 저장 후 보내야한다.

formData.append(’image’,res) 를 사용해 blob 데이터를 저장한다. 이제 여기서 blob 데이터를 이미지로 출력하면 생성된 이미지가 화면에 나오게 된다.

나는 여기에 텍스트를 편집할것 이기 때문에 서버로 blob 과 텍스트 데이터를 전송하겠다.

이제 서버에 전달받은 데이터를 파이썬 코드를 실행하기 위해 다음과 같은 코드를 작성했다.

async function imgEdit (imgBlob, text) {
    return new Promise((resolve, reject) =>{
        let dataToSend;
        const msg = text;
        console.log("img edit : ",text, "img URL : ", imgBlob.path);
        const python = spawn(desiredPath, [ msg, imgBlob.path]);

        python.stdout.on('data', async function(data){
            dataToSend = data.toString();
            console.log("imgEdit start", dataToSend);
            resolve(dataToSend)
        });

        python.stderr.on("data", async function(data) {
            console.error("Python Error: ", data.toString())
            reject(data.toString())
        });

        python.on('error', (error) => {
            console.error("Spawn Error: ", error);
            reject(error);
        });
    })
}

Promise 객체를 생성 후 spawn 을 이용해 데이터를 파이썬 코드로 보낸다. 파이썬에서 처리를 한 데이터를 resolve 를 통해 받아 frontend 로 전달한다.

파이썬 코드는 다음과 같다.

import numpy as np
from PIL import ImageFont, ImageDraw, Image
import cv2
import sys
import base64
from io import BytesIO

def calculate_average_color(image):
    # 이미지의 RGB값을 계산
    r, g, b = 0, 0, 0
    pixels = image.load()
    width, height = image.size
    for y in range(height):
        for x in range(width):
            _r, _g, _b = pixels[x, y]
            r += _r
            g += _g
            b += _b
    # 평균값을 계산
    num_pixels = width * height
    r //= num_pixels
    g //= num_pixels
    b //= num_pixels
    return b,g,r

def get_complementary_color(b,g,r):
    # 보색을 계산
    r, g, b = b,g,r
    return 255 - r, 255 - g, 255 - b

try:    
    image = cv2.imread(sys.argv[2], cv2.IMREAD_ANYCOLOR)
    overlay = image.copy()
except Exception as e:
    print("error", e)

imgForColor = Image.open(sys.argv[2])

avgB, avgG,avgR = calculate_average_color(imgForColor)
comB,comG,comR = get_complementary_color(avgB,avgG,avgR)
b,g,r= 0,0,0

if((avgB+avgG+avgR)/3 >=128):
    b,g,r = 0,0,0
else:
    b,g,r = 255,255,255

font_size = 80
h,w,c = image.shape

line_w = w/font_size

height = str(h)

test_str = sys.argv[1]
max_line = (int)(len(test_str)/line_w)+1

str_slice = test_str.split(" ")
exp_str = []
str_token = ""

font = ImageFont.truetype("arial.ttf", font_size)

i = 0
while i != len(str_slice):
    if len(str_token) + len(str_slice[i]) + 1 <= line_w:
        str_token += " " + str_slice[i]
        i += 1
    else:
        exp_str.append(str_token.strip())  # str_token의 앞뒤 공백 제거 후 추가
        str_token = ""  # str_token 초기화
    if i == len(str_slice) and str_token:  # 마지막 요소이고, str_token이 빈 문자열이 아닌 경우
        exp_str.append(str_token.strip()) 

background_h = []

center_w = []
for i in range(len(exp_str)):
    left,top,right,bottom = font.getbbox(exp_str[i])
    center_w.append(right)

for i in range (len(exp_str)):
    background_h.append((int)((h/2) + (i - len(exp_str)/2) * font_size))

cv2.rectangle(overlay, (0, background_h[0]), (w, background_h[len(exp_str)-1]+font_size), (comB, comG, comR), -1)
alpha = 0.7  # 투명도 설정 (0은 완전 투명, 1은 완전 불투명)
image = cv2.addWeighted(overlay, alpha, image, 1 - alpha, 0)

img = np.zeros((200,400,3),np.uint8)
#b,g,r,a = 0,0,0,0
fontpath = "fonts/batang.ttc"
font = ImageFont.truetype(fontpath, font_size)
img_pil = Image.fromarray(image)
draw = ImageDraw.Draw(img_pil)

for i in range (len(exp_str)):
    ex = (int)((w-center_w[i])/2)-50   
    draw.text((ex,(int)((h/2) + (i - len(exp_str)/2) * font_size)), exp_str[i],font=font,fill=(b,g,r))
    
img = np.array(img_pil)

# 임의의 행렬을 생성
matrix = np.array([...])  # 여기에 실제 행렬을 입력

# 행렬을 이미지로 변환
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
resultImg = Image.fromarray(img)

# 이미지를 base64 문자열로 변환
buffered = BytesIO()
resultImg.save(buffered, format="JPEG")
img_str = base64.b64encode(buffered.getvalue())

print(str(img_str))

cv2.waitKey()
cv2.destroyAllWindows()

텍스트와 이미지를 받아 중앙정렬 후 텍스트를 돋보이기 위한 상자를 배치한다.

정말 가독성이 1도 없는 코드라 바꾸고 싶지만 그럴 시간이 있을까?

위의 프로세스를 수행하면 다음과 같은 그림이 생성된다.

 

 

짜란 정말 아무도 안쓸것같은 이미지 완성!

 

반응형

'ChatGPT > 챗봇프로젝트' 카테고리의 다른 글

[프로젝트] 노인을 위한 스마트챗봇 -1-  (2) 2023.03.21
반응형

배경


useEffect 를 이용해 한번만 함수를 처리하게 하려고 했다.
하지만 왜인지 모르게 자꾸 렌더링이 두번씩 되어 함수가 두번 실행이 되었다.

 

해결

https://youngble.tistory.com/175

 

[React] useEffect 2번 실행되는 이유

다음과 같이 useEffect를 사용하여 jQuery메서드 on 으로 해당 요소를 이벤트 등록을 해주었다. 그런데 해당 태그를 눌러 이벤트가 발생하면 2번이 실행돼서 왜이러지? 찾아보니깐 useEffect부분에서 두

youngble.tistory.com

다음 글을 보면 index.js 의 React.StrictMode 때문이라고 한다.

 

import React from 'react';

function ExampleApplication() {
  return (
    <div>
      <Header />
      <React.StrictMode>
        <div>
          <ComponentOne />
          <ComponentTwo />
        </div>
      </React.StrictMode>
      <Footer />
    </div>
  );
}

 

개발모드에서만 작동되는 StrictMode 는 다음과 같은 효과를 준다고한다.

  1. 안전하지 않은 생명주기를 사용하는 컴포넌트 발견
  2. 레거시 문자열 ref 사용에 대한 경고
  3. 권장되지 않는 findDOMNode 사용에 대한 경고
  4. 예상치 못한 부작용 검사
  5. 레거시 context API 검사
  6. Ensuring reusable state

https://ko.legacy.reactjs.org/docs/strict-mode.html

 

Strict 모드 – React

A JavaScript library for building user interfaces

ko.legacy.reactjs.org

문서에 들어가면 더 자세히 볼 수 있다.

 

결론은 index.js React.StrictMode 를 제거하면 한 번만 호출 된다.
반응형

'Error' 카테고리의 다른 글

[Pyinstaller] How to generate an executable on Linux for Windows?  (2) 2023.06.02

+ Recent posts