꿈에 그리던 삼성 청년 소프트웨어 아카데미 12기로, 입과를 하게 되었다.

Vue를 이용한 프론트 엔드부터 Java, Spring Boot, MyBatis 백엔드 기술 뿐아니라,

생성형 AI와 할루시네이션 문제, RAG에 대해서 깊이 배울 수 있었다.

뿐만 아니라 좋은 동기들을 만나, 함께 프로젝트를 진행하는 과정에서, 기술에 대한 이해와 협업 능력을 기를 수 있었다.



우선, 강사님께서 전문적인 지식을 가지고 계셔서 깊이 있게,

웹 개발에 대한 프로그래밍 언어와 프레임워크에 대해서 학습할 수 있었던 것 같다.

중간중간 질문을 해도, 친절하게 알려주시는 점이 좋았다.

800시간동안 체계적인 커리큘럼과 실무 중심의 프로젝트 덕분에

단기간 내에 깊이 있게 배우고, 개발 역량을 쌓을 수 있었던 것 같다.

 

 

사실 SSAFY에서 제일 좋았던 건, 열정많고, 정말 좋고, 뛰어난 우리 동기들이었다.

우리반에는 실제 회사에 있다가 온 동기도 있었고, 다른 부트캠프를 다녀온 동기들이 많았다. 

협업과 Git, 웹 개발, 인프라에 대해서 배울 수 있었다.

 

 

보통 아침 9시부터 저녁 6시, 그리고 스터디까지 하면 10시에 집에 가곤했다.

힘든 과정이었지만, 함께 하는 열정 넘치는 동기들이 있어서, 1학기 정말 뿌듯하고 재미있게 보낸 것 같다.

 

 

특히 SSAFY 커리큘럼을 들으면서, SQLD, 정보처리기사 스터디를 진행하면서 자격증도 취득하였다.

 

인프라 스터디를 하면서, Docker와 AWS 배포를 경험할 수 있었고, Github Actions를 통해 CI/CD로 구축을 해보았다.

프로메테우스와 그라파나와 같은 백엔드에게 중요한 성능 측정 모니터링에 대해서도 함께 배우며, 성장할 수 있었다.

 

 

그리고 틈틈히 알고리즘 스터디를 진행하면서, 삼성 SW 역량테스트에서 A+형을 취득할 수 있었고,

백준 사이트에서 골드1 티어를 달성했다. 2학기에 더 열심히 해서 B형도 따고 싶다.

 

 

사실 나보다 뛰어난 동기들이 많지만, 과분하게도 성적과 태도를 고려한 성적 우수상을 내가 받게 되었다.

한 학기라는 시간동안 정말 많이 배우고, 좋은 동기들을 만나서 너무 행복하고 즐거웠다. 

 

 

늘 도움을 주시는 취업 컨설턴트님 덕분에 취업 방향성에 대해 다시 한번 생각하며,

체계적으로 취업을 준비하게 된 것 같다. 그리고 교육 프로님들 덕분에 정말 불편없이 생활했다.

 

 

끝으로, 성적우수상 부상으로 갤럭시 워치 7을 받게 되었다.

 

속도도 굉장히 빠르고 UI 전환도 굉장히 매끄러워진 것 같다. 배터리도 한 번 충전하면, 꽤 오래 쓰는 것 같았다.

 

심박수 모니터링, 혈중 산소 포화도, 그리고 수면 분석 기능도 재미있었다. 

평소 운동을 좋아하는 편인데, 다양한 운동 모드를 제공하는 점도 좋았다.

1. 시작하기전에 생각해볼 것 3가지

어떠한 값이 나올까? 에 대해 한번 곰곰히 생각해보자

 

첫 번째 케이스

두 번째 케이스

세 번째 케이스

3가지 경우에는 어떤 값이 출력이 될까?

 

1. Call by Value

 

 

첫 번째 경우에 a = 1 b = 2가 출력이 된다.

 

 

1. main 함수와 swap 함수

main 함수에서 a = 1, b = 2라는 값을 복사하여서 swap 이라는 함수로 전달한 것이기 때문에,

swap 안에서의 a 와 b는 main의 a 와 b 와는 엄연히 다른 메모리 영역을 가지는 변수  이다.

다시 말해 swap 안의 a와 b는 main의 a와 b 값을 복사해 그대로 전달했을 뿐 다른 함수이고, 두 함수는 아무런 관련이 없다.

 

 

2. 함수 종료 시 a와 b도 소멸

swap 함수가 종료됨과 동시에 swap 함수의 a,b는 사라진다. 정확히 말하면 c언어에서 할당받은 메모리의 변수의 값이 지워졌다기보다는 더 이상 보호를 받지 못하고, 다른 프로그램에 의해 다른 값으로 덮어쓰여지거나 임의의 값이 쓰여진다. 얼마나 시간이 지나야 다른 프로그램에 의해 값이 덮어쓰여질지는 모르지만 프로그래머가 제어할 수 없는 값이니 사라진다는 표현을 사용한다. 

 

 

그러면 어떻게 call by value에서 값을 전달할 수 있을 까? 

 

이러한 경우에 return을 사용하여 main 함수의 변수에 대입을 하면 가능하다.

하지만 c언어의 경우 하나의 변수만 return 할 수 있으므로, 여러 개의 변수를 반환하고 싶으면 구조체나 배열을 통해 반환을 해야한다.


2. Call by Reference

두 번째 케이스는 a = 2, b = 1이 출력된다.

 

1. main 함수와 swap 함수

 

main 함수에서 a = 1, b = 2라는 값의 주소를 넘겨주었기 때문에

swap 안에서의 a 와 b는 main의 a 와 b 와는 같은 메모리 영역을 가지는 변수  이다.

 

 

따라서 swap 안에서 포인터를 통해 특정 메모리의 값을 바꾸었으므로, 함수가 종료되어도

main 함수에서 a와 b 값이 바뀐 것을 확인할 수있다.


 

3. 함수와 메모리 

 

세 번째의 정답은 알 수 없다 이다.

 

왜냐하면 returnaddress에서 선언한 변수 b는 b의 주솟값을 반환하고, 종료한다.

이때 변수 b는 returnaddress에서 선언된 지역변수 이므로, 함수가 종료됨에 따라 소멸한다.

첫 번째 케이스에서 봤던 것처럼, 정확히는 보호를 받지 못하고, 일정 시간이 지나면 다른 프로그램에 의해서 

덮어쓰여지거나 임의의 값으로 덮어쓰여진다.

 

따라서 덮어쓰여지기전에 값이 출력이 된다면 예상한 값이 나올 것이고, 그렇지 않다면 다른 값이 나올 것이다.

 

출력값은 다음과 같이 나온다.

 

 

 


4. 정리

call by value는 값을 복사해온 것이므로, 이것에 의해 생성된 변수는 실제(원본이 되는) 변수와 다른 메모리 영역을 가지는 변수로 실제 변수에 영향을 미치지 못한다.

 

call by reference는 주소값을 복사해온 것이므로, 실제(원본이 되는) 변수와 같은 메모리 영역을 가지는 변수로 pointer를 이용하여 해당하는 주소값의 value를바꿀 수 있다.

 

local 변수는 함수가 끝나면 소멸하고, 여기서 소멸한다는 뜻은 즉시 사라진다는 뜻이 아니라 보호받지 못하는 변수를 의미한다.

 

'Program Language > C' 카테고리의 다른 글

[C] Big Endian vs Little Endian  (0) 2023.11.06

1. Endian

Endian은 걸리버 여행기의 소인국 이야기에서 달걀을 깰 때, 뭉툭한 끝(big-end)을 먼저 깨는 사람들(빅 엔디언)과 뾰족한 끝(little-end)을 먼저 깨는 사람들(리틀 엔디언) 에서 유래된 것으로, 컴퓨터 아키텍에서 메모리에 자료가 저장하고 표현할  바이트 단위로 저장되는 방식을 의미한다.

 

부호가 없는 unsigned int를 가지고 이야기를 해보고자 한다.

 

C언어에서 unsigned int 형의 범위는 0 ~ 4,294,967,295 이지만, 컴퓨터 아키텍쳐에서 메모리의 한 Byte의 크기는 256 이므로 unsigned int는 너무 커서 1byte에 모두 담을 수 없고,  4 byte에 나누어 담아야한다. 메모리에 4byte에 해당하는 값을 저장하게 된다.

 

 

- 낮은 byte를 높은 주소에 저장하는 가?

- 높은 byte를 높은 주소에 저장하는 가?

 

 

낮은 byte를 높은 주소에 저장한다면 Big Endian, 높은 byte를 높은 주소에 저장한다면 Little Endian이라고 한다.

이해가 잘 가지 않을 수 있으니 아래에서 좀 더 자세히 다루어보자!

 

2. Big Endian

Big Endian은 낮은 자리의 Byte가 높장 낮은 자리의 주소에 저장되는 방식이다.

 

 

IBM 또는 Motorola 의 많은 시스템들이 big Endian 방식을 사용하고 있음.

 

 

3. Little Endian

little Endian은 낮은 자리의 byte가 낮은 자리의 주소에 저장되는 방식이다.

 

intel 계열의 cpu와 AMD의 processor는 Little Endian 방식을 사용하고 있음.

 

 

4. Little Endian 실습

 

# define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>

int main() {
	unsigned int number;
	unsigned char arr[4];

	scanf("%u", (int*)arr);

	for (int i = 0; i < 4; i++) {
		printf("%hhu", &arr[i]);
	}

	return 0;
}

 

위의 예시 코드를 가지고 한 줄씩 디버깅을 하면서 살펴보자

insigned int 변수를 선언했고, unsigned char 배열을 선언했다.

그리고 scanf 함수를 이용해서 305419896을  unsigned char 배열에 int*형의 값을 넣어주었다.

 

 

무슨 일이 일어날까??

조사식을 보면 다음과 같다.

 

 

 

 

 

위의 조사식에서

앞에있는 값은 10진수, 뒤에 있는 값은 아스키 코드를 나타낸다.

따라서 10진수를 16진수로 바꾸어보면

 

120 -> 0x78

86   -> 0x56

52   -> 0x34

12   -> 0x12

 

이처럼 높은 바이트의 값이 높은 주소에 저장되어 있다는 것을 알 수있다.

 

 

현재 우리가 사용하고 있는 대부분의 cpu (intel 또는 amd) 는 Little Endian 방식을 사용하고, 다음과 같이 실습해 볼 수있을 것이다. 다만 Mac의 경우는 조금 다를 수 있다.

'Program Language > C' 카테고리의 다른 글

[C] Call by Reference VS Call by Value  (0) 2023.11.06

1. 버전관리시스템(VCS)

1) 버전 관리 시스템(Version Control System, VCS)은 소프트웨어 개발과정에서 파일 및 프로젝트의 변경사항을 추적하고, 관리하는 시스템으로, 여러 개발자들이 동시에 작업을 하고, 파일을 공유하며 변경 내용을 추적하고, 이전 버전으로 돌릴 수 있음.

 

2) 혼자서 개발을 하는 경우, 잘돌아가던 파일이 변경 사항을 적용한 후로 실행이 안 되서 이전 상태로 돌리고 싶거나 컴퓨터 하드가 날라갔거나 하는 문제에 대해 버전 관리 시스템을 사용하면 쉽게 해결 가능

 

3) 함께 개발을 진행하는 경우, 공식적인 코드를 기록해놓을 수도 있고, 하나의 프로젝트에 개발 파트를 나누어 개발을 하는 경우, 누가 어떤 코드를 수정했는 지에 대해 알 수 있고, 각자 개발한 코드를 합칠 수 있고, 버전별로 개발이 가능

 

 

2. git 

버전 관리 시스템 중의 하나로, 소프트웨어 개발 프로젝트의 버전을 관리하고 추적하는 도구

 

Working Directory : 파일 수정, 저장 등의 작업을 하는 디렉터리

 

Staging Area : commit을 하기 전 파일이 대기하는 곳, 일종의 buffer

 

Local Repository : Staging Area의 파일을 버전으로 만들어 저장하는  repository ex) git

 

Remote Repository : Staging Area의 파일을 버전으로 만들어 원격으로 저장하는 repository ex) github

 

pull과 clone의 차이 : pull은 원격 저장소의 변경 사항을 가져와서 merge 한 것, clone은 원격 저장소의 내용을 그대로 복사해온 것

 

 

3. git 설치

## apt 업데이트
$ sudo apt update

## git install
$ sudo apt-get install git

## git에서 사용할 name과 email 설정
$ git config --global user.name "사용자 이름"
$ git config --global user.email "사용자 이메일"

## git setting 확인
$ git config --list

 

4. git init부터 commit까지

1)  git init 

 

2) ls -al : init git  생성 확인

 

 

3) git 상태 확인 - main branch에 존재하고, commit 한 게 없다는 뜻

 

4) git add : 파일 생성 후 add  

 

new file로 staging Area에 test파일이 올라간 것을 볼 수 있음.

 

5) git commit -m "메세지" :  commit을 할 때 메세지를 남김

 

1. Shell과 Terminal

Shell(Kernel과 User간의 Interface) : 사용자가 명령을 입력하면 해석해서 Kernel에 전달하는 프로그램이나 환경

 

Terminal(사용자와 Shell간의 Interface) : 사용자가 Shell에 명령을 전달하거나 Shell으로부터 결과를 반환받아

사용자에게 보여주는 도구로, 하드웨어적인 의미에서 보면 키보드와 모니터이고, 소프트웨어적인 의미에서 보면,

명령프롬프트와 같은 프로그램을 의미

 

2. Shell Script

Shell에서 특정한 명령어들을 순차적으로 실행하도록한 스크립트 파일 

 

2-1) Ubuntu Linux환경에서, nano editor 사용

 

2-2) shellscript 작성

#! /bin/bash :

  shellscript를 사용할 때 사용할 shell 선택(shell의 경로를 알려줌) // 여기서는 bash  shell 사용

echo hello :

  hello 출력

 

Linux에서는 확장자 없이도 내부적으로 파일을 식별할 수 있음, 다만 파일 명에 붙이는 확장자는 사용자가 이해하기 쉽게 관습적으로 붙임

 

2-3) shellscript 실행 및 Permission denied

3. Shell Script 작성 

Up & Down game 

1) shell script 작성

 

#! /bin/bash

#01 game에 대한 설명
echo "Up & Down Game!"
echo -n "Random number range(max : 32768) : "
read number_range
echo "Number Range : 1 - $number_range"

#02 변수 설정
# 1~ number_range까지 중에서 rand_num 설정
rand_num=$(($RANDOM%$(($number_range+1))))
count=0

#03 for문을 돌면서 Up & Down
for i in $(seq 100);do

  # 입력 값 받기
  echo -n "Enter the number : "
  read input

  # 입력 횟수 카운트
  count=$(($count+1))

  if [ $input -eq $rand_num ];then
    echo "Congratuation! Answer is $rand_num"
    break

  elif [ $input -gt $rand_num ];then
    echo "answer is less than $input"

  elif [ $input -lt $rand_num ];then
    echo "answer is greater than $input"
  fi

done

 

- 변수를 초기화 할 떄는 대입연산자와 변수명과 초기화값을 붙여서 작성해야 함.

-  조건문 안에 [] 조건을 작성할 때는 공백을 두고 작성해야 함.

 

2) Permission 설정

 

----------- 의 의미

첫 번째 - 는 directory를 의미

뒤로 9개의 -는 user, group, other의 read, write, execute 권한을 의미

 

 

3) 숫자 맞추기 게임 실행

1. GCC(GNU Compiler Collection)

GNU 프로젝트의 일환으로 개발되어 널리 쓰이고 있는 컴파일러로, 원래는 GNU C Compiler를 의미했지만, Java, C++ 등 여러 언어를 지원하면서 GNU Compiler Collection으로 명칭이 바뀌게 되었다.

 

2. Build 방식에 따른 프로그램 언어 분류

1. Compile 언어 : compiler를 사용하여 소스 코드를 기계어로 변환, build 과정을 거쳐서 실행 파일 생성

ex) C언어, C++

2. Interpreter 언어 : source file을 한번에 번역하는 게 아니라 한 줄씩 해석하면서 즉시 실행

ex) JavaScript, Python

3. Hybird 언어 : Compile 방식과 Interpreter 방식을 모두 사용, Java의 경우 Source file(.java)을 바이트 코드(.class)로 변환하고, JVM(Java Virtual Machine)이라는 프로그램에 의해 운영체제 별로 Byte Code를 한 줄씩 운영체제에 맞는 명령어로

실행시켜줌ex) Java, C#

 

3. Compile 언어의 장점과 단점

1. 장점

  • 빌드 과정이 끝난 executable file은 실행 속도가 빠르다.

2. 단점

  • 프로그램을 수정할 경우, 처음부터 build를 해야한다.
  • 플랫폼에 의존적이다. cpu마다 어셈블리어의 명령어가 다르다.(거의 유사하지만 Windows과 mac(apple의 자체 cpu사용))

 

4. Compile 방식에서 실행 파일 빌드 과정(Building an executable file)

1) preprocessor : 전처리 과정으로 C언어의 #define이나 #include 같은 구문들을 처리 해줌.

2) compile : source file(.c)를 어셈블리 코드로 변환

3) assembler : 어셈블리 코드를 cpu가 이해할 수 있는 기계어로 번역 (object 파일 생성)

4) linker : object 파일들과 library를 묶어서 하나의 실행 파일을 생성

 

5. Visual Studio Code 실행

1) Visual Studio Code 실행

 

6. object 파일 생성

## 파일 directory 생성
$ mkdir src bin obj include lib

## file 생성
$ touch include/funcs.h src/func1.c src/func2.c src/main.c

## object 파일 생성
$ gcc -c src/funcs1.c -o obj/funcs1.o -I./include
$ gcc -c src/funcs2.c -o obj/funcs2.o -I./include

1) 명령어 설명 

-c : link는 따로 하지 않고, object 파일까지만 생성

-o : 생성된 파일의 경로 및 이름 지정

-I (대문자 I): 컴파일러에게 헤더 파일이 위치한 디렉터리를 알려주는 역

 

7. Library 생성

1) 정적 라이브러리(Static Library)와 동적 라이브러리(Dynamic Library) 차이

정적 라이브러리 : .lib(Windows) 또는 .a(Unix/Linux)의 확장자를 가지며, 컴파일시에 실행 파일에 포함되고, 그에 따라 실행파일의 크기가 커짐, 런타임에 외부 라이브러리에 대한 의존성이 없음.

 

동적 라이브러리 : .dll(Windows) 또는 .so(Unix/Linux)의 확장자를 가지며, 런타임시에 프로그램이 필요할 떄 로드가 되고, 실행 파일의 크기가 작아지고, 메모리를 효율적으로 사용할 수 있다는 장점이 있지만, 런타임에 외부 라이브러리에 대한 의존성이 있음.

 

2) 정적 라이브러리 파일 생성

 

2-1) 정적 라이브러리 생성 

ar rv lib/lib(library이름).a (obj 파일들)  

 

2-2) link (정적 라이브러리 + main.obj)

-o : 만들고자하는 파일 이름

-I(대문자) : 컴파일러에게 헤더파일 경로를 알려줌

-l(소문자) : 컴파일러에게 라이브러리 이름을 알려줌

-L: 컴파일러에게 라이브러리 경로를 알려줌

 

 

3) 동적 라이브러리 생성

 

3-1) 동적 라이브러리 생성

## -fPIC를 이용해서 object 파일 생성
$ gcc -fPIC -c src/funcs1.c -I./include -o obj/funcs1.o
$ gcc -fPIC -c src/funcs2.c -I./include -o obj/funcs2.o

## 환경 변수설정 (export는 껐다키면 사라짐)
$ export LD_LIBRARY_PATH=$HOME/opensw/studylibrary/lib
## 환경 변수 확인
$ echo $LD_LIBRARY_PATH

## 동적 library 생성
$ gcc -fPIC -shared -Wl,-soname=libmyfuncs.so.1 obj/*.o -o lib/libmyfuncs.so.1.0 -lc

## softlink
$ ln -s libmyfuncs.so.1.0 lib/libmyfuncs.so.1
$ ln -s libmyfuncs.so.1.0 lib/libmyfuncs.so

$ tree

-fPIC : 메모리에 로딩되는 위치에 상관없이 실행될 수 있는 코드를 의미, 동적 라이브러리나 공유 라이브러리 생성할 때 사용

-l(소문자 l) : 라이브러리 파일을 지정

-L : 컴파일러에게 라이브러리 파일이 위치한 디렉터리를 알려주는 역할

-shared : default가 shared 이지만 가독성을 위해 사용

-Wl(소문자 l) : 다음에 오는 옵션을 링커에게 전달하는 역할

-lc : c 프로그램이 실행될 때, 필요한 기본적인 함수 포함하는 라이브러리

 

 

3-2) link (동적 라이브러리 + main.obj)

 

라이브러리 경로 표시

 

$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:./lib

 

$ gcc src/main.c -I./include -o bin/myapp.lib -lmyfuncs -L./lib

 

 

'Ubuntu Linux' 카테고리의 다른 글

[Ubuntu Linux] 버전 관리 시스템(VCS)과 git  (0) 2023.11.02
[Ubuntu Linux] ShellScript  (0) 2023.10.26
[Ubuntu Linux] 가상 환경 설정 하기  (0) 2023.10.23

1. 가상 환경(virtual environment)

가상 환경이란 하나의 프로젝트나 작업을 하기 위해서 필요한 패키지나 라이브러리를 격리된 공간에 설치하고 관리하는 것을 의미

 

 

 

2. 가상 환경(virtual environment)이 필요한 이유

프로젝트마다 사용되는 패키지 또는 라이브러리의 버전이 다르기 때문에, 분리되지 않은 하나의 환경에서 여러 가지 프로젝트를 진행하게 되면 다른 라이브러리의 버전끼리 충돌을 할 가능성이 있음.

다시 말해, 가상 환경이 필요한 이유는 프로젝트에 필요한 버전만 넣어두어서 버전 충돌의 문제를 방지한다.

 

 

 

3. Ubuntu Linux에서 가상 환경 설정

0. project를 진행할 directory 생성 및 진입

$ mkdir project
$ cd project

 

 

 

1. venv 가상 환경 모듈 사용  myvenv라는 가상환경 설정

$ python3 -m venv myvenv

 

 

2. 가상 환경 활성화

- 계정 옆에 (myvenv)가 생긴 것을 볼 수 있음.

$ source myvenv/bin/activate

 

 

3.  비활성화

$ deactivate

 

+ Recent posts